Skip to content

Instantly share code, notes, and snippets.

@Fuyutsubaki
Created July 7, 2019 17:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fuyutsubaki/c35765811a94586aa3364924760de277 to your computer and use it in GitHub Desktop.
Save Fuyutsubaki/c35765811a94586aa3364924760de277 to your computer and use it in GitHub Desktop.
リッチテキスト
namespace cfn {
struct RichText {
std::unique_ptr<XMLElementNode> root_;
struct Context {
std::int32_t size;
};
struct PosState {
s3d::Vec2 pos{ 0,0 };
s3d::Vec2 newline_pos{ 0,0 };
};
s3d::Font get_font(Context const& ctx) {
s3d::String fontname = s3d::Format(U"s", ctx.size);
if (!s3d::FontAsset::IsRegistered(fontname)) {
s3d::FontAsset::Register(fontname, ctx.size);
}
return s3d::FontAsset(fontname);
}
s3d::Font default_font{ 10 };
RichText(s3d::String const& code)
:root_(xml_root_node(U"<default>" + code + U"</default>"))
{}
void draw(PosState& pos, Context const& ctx, XMLTextNode const& text) {
auto font = get_font(ctx);
for (s3d::StringView s{ text.text }; s;) {
// tokenize(/\n|[^\n]+/)
if (s[0] == U'\n') {
pos.pos = pos.newline_pos;
pos.newline_pos.y = 0;
s.remove_prefix(1);
}
else {
auto substr = s.substr(0, s.indexOf(U'\n')); // nposでも期待通り動く
auto rect = font(substr).draw(pos.pos);
pos.pos = rect.tr();
pos.newline_pos.y = std::max(pos.newline_pos.y, rect.br().y);
s.remove_prefix(substr.size());
}
}
}
void draw(PosState&, Context const&, XMLCommentNode const&) { }
void draw(PosState&, Context const&, XMLUnknownNode const&) { }
void draw(PosState& pos, Context const& ctx_old, XMLElementNode const& elem) {
Context ctx = ctx_old;
if (elem.name == U"font") {
for (auto& [k, v] : elem.attributes) {
if (k == U"size") {
ctx.size = s3d::ParseInt<std::int32_t>(v);
}
}
}
for (auto& node : elem.children) {
std::visit([&](auto const& e) {
draw(pos, ctx, e);
}, *node);
}
}
void draw() {
s3d::Vec2{ 0,0 };
PosState pos{ s3d::Vec2{ 0,0 }, s3d::Vec2{ 0,0 } };
Context ctx{ 10 };
draw(pos, ctx, *root_);
}
};
}
// siv3dの.cppに書いてたやつ
// includeとか足りないかも
# include <tinyxml/tinyxml2.h>
namespace cfn {
XMLElementNode buildXML(tinyxml2::XMLElement const*elem) {
s3d::Array<std::unique_ptr<XMLNode>> children;
for (const tinyxml2::XMLNode* node = elem->FirstChild(); node; node = node->NextSibling()) {
if (auto e = node->ToElement()) {
children.push_back(std::make_unique<XMLNode>(buildXML(e)));
}
else if (auto txt = node->ToText()) {
children.push_back(std::make_unique<XMLNode>(XMLTextNode{ s3d::Unicode::FromUTF8(txt->Value()) }));
}
else if (node->ToComment()) {
children.push_back(std::make_unique<XMLNode>(XMLCommentNode{}));
}
else {
children.push_back(std::make_unique<XMLNode>(XMLUnknownNode{}));
}
}
s3d::Array<std::pair<s3d::String, s3d::String>> attr_list;
for (auto a = elem->FirstAttribute(); a; a = a->Next())
{
attr_list.emplace_back(s3d::Unicode::FromUTF8(a->Name()), s3d::Unicode::FromUTF8(a->Value()));
}
return XMLElementNode{ s3d::Unicode::FromUTF8(elem->Name()), std::move(attr_list), std::move(children) };
}
std::unique_ptr<XMLElementNode> xml_root_node(s3d::String const&code) {
std::shared_ptr<tinyxml2::XMLDocument> document = std::make_shared<tinyxml2::XMLDocument>(true, tinyxml2::PRESERVE_WHITESPACE);
std::string text = code.toUTF8();
auto err = document->Parse(text.c_str(), text.size());
assert(err == tinyxml2::XML_SUCCESS);
auto root = document->FirstChildElement();
return std::make_unique<XMLElementNode>(buildXML(root));
}
}
#include<variant>
namespace cfn {
struct XMLTextNode;
struct XMLElementNode;
struct XMLCommentNode;
struct XMLUnknownNode;
using XMLNode = std::variant<XMLTextNode, XMLElementNode, XMLCommentNode, XMLUnknownNode>;
struct XMLTextNode {
s3d::String text;
};
struct XMLElementNode {
s3d::String name;
s3d::Array<std::pair<s3d::String, s3d::String>> attributes;
s3d::Array<std::unique_ptr<XMLNode>> children;
};
struct XMLCommentNode {};
struct XMLUnknownNode {/*no impl*/ };
std::unique_ptr<XMLElementNode> xml_root_node(s3d::String const& code);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment