| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- #include <sstream>
- #include "TextField.h"
- #include "Font.h"
- #include "DebugActor.h"
- #include "res/Resources.h"
- #include "RenderState.h"
- #include "utils/stringUtils.h"
- #include "core/gl/VideoDriverGLES20.h"
- #include "text_utils/TextBuilder.h"
- #include "text_utils/Node.h"
- #include "Serialize.h"
- #include "Material.h"
- namespace oxygine
- {
- static ResFont* _defaultFont = 0;
- void TextField::setDefaultFont(ResFont* f)
- {
- _defaultFont = f;
- }
- ResFont* TextField::getDefaultFont()
- {
- return _defaultFont;
- }
- TextField::TextField():
- _root(0),
- _textRect(0, 0, 0, 0),
- _rtscale(1.0f)
- {
- _flags |= flag_rebuild;
- _style.font = _defaultFont;
- }
- TextField::~TextField()
- {
- delete _root;
- _root = 0;
- }
- void TextField::copyFrom(const TextField& src, cloneOptions opt)
- {
- inherited::copyFrom(src, opt);
- _text = src._text;
- _style = src._style;
- _root = 0;
- _rtscale = 1.0f;
- _flags |= flag_rebuild;
- _textRect = src._textRect;
- }
- bool TextField::isOn(const Vector2& localPosition)
- {
- Rect r = getTextRect();
- r.expand(Point(_extendedIsOn, _extendedIsOn), Point(_extendedIsOn, _extendedIsOn));
- return r.pointIn(Point((int)localPosition.x, (int)localPosition.y));
- }
- void TextField::needRebuild()
- {
- _flags |= flag_rebuild;
- }
- void TextField::setVAlign(TextStyle::VerticalAlign align)
- {
- _style.vAlign = align;
- needRebuild();
- }
- void TextField::setMultiline(bool multiline)
- {
- _style.multiline = multiline;
- needRebuild();
- }
- void TextField::setBreakLongWords(bool val)
- {
- _style.breakLongWords = val;
- needRebuild();
- }
- void TextField::setLinesOffset(int offset)
- {
- _style.linesOffset = offset;
- needRebuild();
- }
- void TextField::setBaselineScale(float s)
- {
- _style.baselineScale = s;
- needRebuild();
- }
- void TextField::setKerning(int kerning)
- {
- _style.kerning = kerning;
- needRebuild();
- }
- void TextField::setFontSize(int size)
- {
- _style.fontSize = size;
- needRebuild();
- }
- void TextField::setStyleColor(const Color& color)
- {
- _style.color = color;
- needRebuild();
- }
- void TextField::setOptions(unsigned int opt)
- {
- _style.options = opt;
- needRebuild();
- }
- const ResFont* TextField::getFont() const
- {
- return _style.font;
- }
- void TextField::setFont(const ResFont* font)
- {
- _style.font = font;
- if (!_style.font)
- _style.font = _defaultFont;
- needRebuild();
- }
- void TextField::setOutlineColor(const Color& c)
- {
- _style.outlineColor = c;
- }
- void TextField::setOutline(float v)
- {
- _style.outline = v;
- }
- void TextField::setWeight(float v)
- {
- _style.weight = v;
- }
- void TextField::setHAlign(TextStyle::HorizontalAlign align)
- {
- _style.hAlign = align;
- needRebuild();
- }
- void TextField::setAlign(TextStyle::VerticalAlign vAlign, TextStyle::HorizontalAlign hAlign)
- {
- _style.vAlign = vAlign;
- _style.hAlign = hAlign;
- needRebuild();
- }
- void TextField::setStyle(const TextStyle& st)
- {
- TextStyle::HorizontalAlign halign = _style.hAlign;
- TextStyle::VerticalAlign valign = _style.vAlign;
- int size = _style.fontSize;
- _style = st;
- if (st.hAlign == TextStyle::HALIGN_DEFAULT)
- _style.hAlign = halign;
- if (st.vAlign == TextStyle::VALIGN_DEFAULT)
- _style.vAlign = valign;
- if (st.fontSize == 0)
- _style.fontSize = size;
- if (!_style.font)
- _style.font = _defaultFont;
- needRebuild();
- }
- void TextField::sizeChanged(const Vector2& size)
- {
- needRebuild();
- }
- void TextField::setText(const std::string& str)
- {
- _flags &= ~flag_html;
- if (_text != str)
- {
- _text = str;
- needRebuild();
- }
- }
- void TextField::setText(const std::wstring& str)
- {
- setText(ws2utf8(str.c_str()));
- }
- void TextField::setHtmlText(const std::string& str)
- {
- _flags |= flag_html;
- if (_text != str)
- {
- _text = str;
- needRebuild();
- }
- }
- void TextField::setHtmlText(const std::wstring& str)
- {
- setHtmlText(ws2utf8(str.c_str()));
- }
- int TextField::getFontSize() const
- {
- return _style.fontSize;
- }
- int TextField::getLinesOffset() const
- {
- return _style.linesOffset;
- }
- TextStyle::VerticalAlign TextField::getVAlign() const
- {
- return _style.vAlign;
- }
- TextStyle::HorizontalAlign TextField::getHAlign() const
- {
- return _style.hAlign;
- }
- bool TextField::getMultiline() const
- {
- return _style.multiline;
- }
- bool TextField::getBreakLongWords() const
- {
- return _style.breakLongWords;
- }
- int TextField::getKerning() const
- {
- return _style.kerning;
- }
- const Color& TextField::getOutlineColor() const
- {
- return _style.outlineColor;
- }
- float TextField::getOutline() const
- {
- return _style.outline;
- }
- const oxygine::Color& TextField::getStyleColor() const
- {
- return _style.color;
- }
- float TextField::getWeight() const
- {
- return _style.weight;
- }
- float TextField::getBaselineScale() const
- {
- return _style.baselineScale;
- }
- unsigned int TextField::getOptions() const
- {
- return _style.options;
- }
- text::Symbol* TextField::getSymbolAt(int pos) const
- {
- return const_cast<TextField*>(this)->getRootNode(_rtscale)->getSymbol(pos);
- }
- const Rect& TextField::getTextRect() const
- {
- const_cast<TextField*>(this)->getRootNode(_rtscale);
- return _textRect;
- }
- bool TextField::getBounds(RectF& r) const
- {
- r = getTextRect().cast<RectF>();
- return true;
- }
- text::Node* TextField::getRootNode(float globalScale)
- {
- if (!_style.font)
- return _root;
- float scale = 1.0f;
- const Font* font = _style.font->getClosestFont(globalScale, _style.fontSize, scale);
- if ((_flags & flag_rebuild || _rtscale != scale) && _style.font)
- {
- _rtscale = scale;
- //_realFontSize = fontSize;
- delete _root;
- _flags &= ~flag_rebuild;
- if (_flags & flag_html)
- {
- text::TextBuilder b;
- _root = b.parse(_text);
- }
- else
- {
- _root = new text::TextNode(_text.c_str());
- }
- text::Aligner rd(_style, font, scale, getSize());
- rd.begin();
- _root->resize(rd);
- rd.end();
- _root->finalPass(rd);
- rd.bounds = (rd.bounds.cast<RectF>() / rd.getScale()).cast<Rect>();
- _textRect = rd.bounds;
- }
- return _root;
- }
- const char* get_valign(TextStyle::VerticalAlign v)
- {
- switch (v)
- {
- case TextStyle::VALIGN_BASELINE:
- return "baseline";
- case TextStyle::VALIGN_TOP:
- return "top";
- case TextStyle::VALIGN_BOTTOM:
- return "bottom";
- case TextStyle::VALIGN_MIDDLE:
- return "middle";
- }
- return "unknown";
- }
- const char* get_halign(TextStyle::HorizontalAlign v)
- {
- switch (v)
- {
- case TextStyle::HALIGN_DEFAULT:
- return "default";
- case TextStyle::HALIGN_LEFT:
- return "left";
- case TextStyle::HALIGN_RIGHT:
- return "right";
- case TextStyle::HALIGN_MIDDLE:
- return "middle";
- }
- return "unknown";
- }
- std::string dumpStyle(const TextStyle& s, bool onlydiff)
- {
- TextStyle def;
- std::stringstream stream;
- if (!onlydiff || def.hAlign != s.hAlign)
- stream << "hAlign=" << get_halign(s.hAlign);
- if (!onlydiff || def.vAlign != s.vAlign)
- stream << " vAlign=" << get_valign(s.vAlign);
- if (!onlydiff || def.multiline != s.multiline)
- stream << " " << (s.multiline ? "multiline" : "singleline");
- if (!onlydiff || def.breakLongWords != s.breakLongWords)
- stream << " " << (s.breakLongWords ? "breakLongWords=1" : "breakLongWords=0");
- if (!onlydiff || def.kerning != s.kerning)
- stream << " kerning=" << s.kerning;
- if (!onlydiff || def.linesOffset != s.linesOffset)
- stream << " linesOffset=" << s.linesOffset;
- if (!onlydiff || def.fontSize != s.fontSize)
- stream << " fontSize=" << s.fontSize;
- if (!onlydiff || def.outline != s.outline)
- stream << " outline=" << s.outline;
- if (s.font)
- {
- stream << " font='" << s.font->getName() << "'";
- }
- return stream.str();
- }
- std::string TextField::dump(const dumpOptions& options) const
- {
- std::stringstream stream;
- stream << "{TextField}\n";
- stream << _vstyle.dump();
- std::string text = _text;
- if (text.size() > 15)
- {
- text.resize(15);
- text += "...";
- }
- stream << " text=<div c='2b1a94'>'<![CDATA[" << text << "']]></div>";
- std::string st = dumpStyle(_style, true);
- if (st.size())
- stream << " textStyle={" << st << "}";
- if (_flags & flag_html)
- {
- stream << " htmlMode";
- }
- Rect r = const_cast<TextField*>(this)->getTextRect();
- stream << " textRect=(" << r.pos.x << ", " << r.pos.y << ", " << r.size.x << ", " << r.size.y << ")";
- stream << "\n" << Actor::dump(options);
- return stream.str();
- }
- void TextField::doRender(RenderState const& rs)
- {
- rs.material->doRender(this, rs);
- }
- void TextField::serialize(serializedata* data)
- {
- inherited::serialize(data);
- pugi::xml_node node = data->node;
- TextStyle def;
- if (!_text.empty())
- node.append_attribute("text").set_value(_text.c_str());
- setAttr(node, "fontsize2scale", _style.fontSize, def.fontSize);
- setAttr(node, "linesOffset", _style.linesOffset, def.linesOffset);
- setAttr(node, "kerning", _style.kerning, def.kerning);
- setAttr(node, "valign", _style.vAlign, def.vAlign);
- setAttr(node, "halign", _style.hAlign, def.hAlign);
- setAttr(node, "multiline", _style.multiline, def.multiline);
- setAttr(node, "baselineScale", _style.baselineScale, def.baselineScale);
- setAttr(node, "breakLongWords", _style.breakLongWords, def.breakLongWords);
- if (_style.font)
- node.append_attribute("font").set_value(_style.font->getName().c_str());
- node.set_name("TextField");
- }
- void TextField::deserialize(const deserializedata* data)
- {
- inherited::deserialize(data);
- pugi::xml_node node = data->node;
- TextStyle def;
- _style.vAlign = (TextStyle::VerticalAlign)node.attribute("valign").as_int(def.vAlign);
- _style.hAlign = (TextStyle::HorizontalAlign)node.attribute("halign").as_int(def.hAlign);
- _style.multiline = node.attribute("multiline").as_bool(def.multiline);
- _style.breakLongWords = node.attribute("breakLongWords").as_bool(def.breakLongWords);
- _style.fontSize = node.attribute("fontsize2scale").as_int(def.fontSize);
- _style.linesOffset = node.attribute("linesOffset").as_int(def.linesOffset);
- _style.kerning = node.attribute("kerning").as_int(def.kerning);
- _style.baselineScale = node.attribute("baselineScale").as_float(def.baselineScale);
- const char* fnt = node.attribute("font").as_string(0);
- if (fnt && *fnt)
- {
- ResFont* font = data->factory->getResFont(fnt);
- if (font)
- _style.font = font;
- }
- needRebuild();
- setText(node.attribute("text").as_string());
- }
- }
|