TextField.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. #include <sstream>
  2. #include "TextField.h"
  3. #include "Font.h"
  4. #include "DebugActor.h"
  5. #include "res/Resources.h"
  6. #include "RenderState.h"
  7. #include "utils/stringUtils.h"
  8. #include "core/gl/VideoDriverGLES20.h"
  9. #include "text_utils/TextBuilder.h"
  10. #include "text_utils/Node.h"
  11. #include "Serialize.h"
  12. #include "Material.h"
  13. namespace oxygine
  14. {
  15. static ResFont* _defaultFont = 0;
  16. void TextField::setDefaultFont(ResFont* f)
  17. {
  18. _defaultFont = f;
  19. }
  20. ResFont* TextField::getDefaultFont()
  21. {
  22. return _defaultFont;
  23. }
  24. TextField::TextField():
  25. _root(0),
  26. _textRect(0, 0, 0, 0),
  27. _rtscale(1.0f)
  28. {
  29. _flags |= flag_rebuild;
  30. _style.font = _defaultFont;
  31. }
  32. TextField::~TextField()
  33. {
  34. delete _root;
  35. _root = 0;
  36. }
  37. void TextField::copyFrom(const TextField& src, cloneOptions opt)
  38. {
  39. inherited::copyFrom(src, opt);
  40. _text = src._text;
  41. _style = src._style;
  42. _root = 0;
  43. _rtscale = 1.0f;
  44. _flags |= flag_rebuild;
  45. _textRect = src._textRect;
  46. }
  47. bool TextField::isOn(const Vector2& localPosition)
  48. {
  49. Rect r = getTextRect();
  50. r.expand(Point(_extendedIsOn, _extendedIsOn), Point(_extendedIsOn, _extendedIsOn));
  51. return r.pointIn(Point((int)localPosition.x, (int)localPosition.y));
  52. }
  53. void TextField::needRebuild()
  54. {
  55. _flags |= flag_rebuild;
  56. }
  57. void TextField::setVAlign(TextStyle::VerticalAlign align)
  58. {
  59. _style.vAlign = align;
  60. needRebuild();
  61. }
  62. void TextField::setMultiline(bool multiline)
  63. {
  64. _style.multiline = multiline;
  65. needRebuild();
  66. }
  67. void TextField::setBreakLongWords(bool val)
  68. {
  69. _style.breakLongWords = val;
  70. needRebuild();
  71. }
  72. void TextField::setLinesOffset(int offset)
  73. {
  74. _style.linesOffset = offset;
  75. needRebuild();
  76. }
  77. void TextField::setBaselineScale(float s)
  78. {
  79. _style.baselineScale = s;
  80. needRebuild();
  81. }
  82. void TextField::setKerning(int kerning)
  83. {
  84. _style.kerning = kerning;
  85. needRebuild();
  86. }
  87. void TextField::setFontSize(int size)
  88. {
  89. _style.fontSize = size;
  90. needRebuild();
  91. }
  92. void TextField::setStyleColor(const Color& color)
  93. {
  94. _style.color = color;
  95. needRebuild();
  96. }
  97. void TextField::setOptions(unsigned int opt)
  98. {
  99. _style.options = opt;
  100. needRebuild();
  101. }
  102. const ResFont* TextField::getFont() const
  103. {
  104. return _style.font;
  105. }
  106. void TextField::setFont(const ResFont* font)
  107. {
  108. _style.font = font;
  109. if (!_style.font)
  110. _style.font = _defaultFont;
  111. needRebuild();
  112. }
  113. void TextField::setOutlineColor(const Color& c)
  114. {
  115. _style.outlineColor = c;
  116. }
  117. void TextField::setOutline(float v)
  118. {
  119. _style.outline = v;
  120. }
  121. void TextField::setWeight(float v)
  122. {
  123. _style.weight = v;
  124. }
  125. void TextField::setHAlign(TextStyle::HorizontalAlign align)
  126. {
  127. _style.hAlign = align;
  128. needRebuild();
  129. }
  130. void TextField::setAlign(TextStyle::VerticalAlign vAlign, TextStyle::HorizontalAlign hAlign)
  131. {
  132. _style.vAlign = vAlign;
  133. _style.hAlign = hAlign;
  134. needRebuild();
  135. }
  136. void TextField::setStyle(const TextStyle& st)
  137. {
  138. TextStyle::HorizontalAlign halign = _style.hAlign;
  139. TextStyle::VerticalAlign valign = _style.vAlign;
  140. int size = _style.fontSize;
  141. _style = st;
  142. if (st.hAlign == TextStyle::HALIGN_DEFAULT)
  143. _style.hAlign = halign;
  144. if (st.vAlign == TextStyle::VALIGN_DEFAULT)
  145. _style.vAlign = valign;
  146. if (st.fontSize == 0)
  147. _style.fontSize = size;
  148. if (!_style.font)
  149. _style.font = _defaultFont;
  150. needRebuild();
  151. }
  152. void TextField::sizeChanged(const Vector2& size)
  153. {
  154. needRebuild();
  155. }
  156. void TextField::setText(const std::string& str)
  157. {
  158. _flags &= ~flag_html;
  159. if (_text != str)
  160. {
  161. _text = str;
  162. needRebuild();
  163. }
  164. }
  165. void TextField::setText(const std::wstring& str)
  166. {
  167. setText(ws2utf8(str.c_str()));
  168. }
  169. void TextField::setHtmlText(const std::string& str)
  170. {
  171. _flags |= flag_html;
  172. if (_text != str)
  173. {
  174. _text = str;
  175. needRebuild();
  176. }
  177. }
  178. void TextField::setHtmlText(const std::wstring& str)
  179. {
  180. setHtmlText(ws2utf8(str.c_str()));
  181. }
  182. int TextField::getFontSize() const
  183. {
  184. return _style.fontSize;
  185. }
  186. int TextField::getLinesOffset() const
  187. {
  188. return _style.linesOffset;
  189. }
  190. TextStyle::VerticalAlign TextField::getVAlign() const
  191. {
  192. return _style.vAlign;
  193. }
  194. TextStyle::HorizontalAlign TextField::getHAlign() const
  195. {
  196. return _style.hAlign;
  197. }
  198. bool TextField::getMultiline() const
  199. {
  200. return _style.multiline;
  201. }
  202. bool TextField::getBreakLongWords() const
  203. {
  204. return _style.breakLongWords;
  205. }
  206. int TextField::getKerning() const
  207. {
  208. return _style.kerning;
  209. }
  210. const Color& TextField::getOutlineColor() const
  211. {
  212. return _style.outlineColor;
  213. }
  214. float TextField::getOutline() const
  215. {
  216. return _style.outline;
  217. }
  218. const oxygine::Color& TextField::getStyleColor() const
  219. {
  220. return _style.color;
  221. }
  222. float TextField::getWeight() const
  223. {
  224. return _style.weight;
  225. }
  226. float TextField::getBaselineScale() const
  227. {
  228. return _style.baselineScale;
  229. }
  230. unsigned int TextField::getOptions() const
  231. {
  232. return _style.options;
  233. }
  234. text::Symbol* TextField::getSymbolAt(int pos) const
  235. {
  236. return const_cast<TextField*>(this)->getRootNode(_rtscale)->getSymbol(pos);
  237. }
  238. const Rect& TextField::getTextRect() const
  239. {
  240. const_cast<TextField*>(this)->getRootNode(_rtscale);
  241. return _textRect;
  242. }
  243. bool TextField::getBounds(RectF& r) const
  244. {
  245. r = getTextRect().cast<RectF>();
  246. return true;
  247. }
  248. text::Node* TextField::getRootNode(float globalScale)
  249. {
  250. if (!_style.font)
  251. return _root;
  252. float scale = 1.0f;
  253. const Font* font = _style.font->getClosestFont(globalScale, _style.fontSize, scale);
  254. if ((_flags & flag_rebuild || _rtscale != scale) && _style.font)
  255. {
  256. _rtscale = scale;
  257. //_realFontSize = fontSize;
  258. delete _root;
  259. _flags &= ~flag_rebuild;
  260. if (_flags & flag_html)
  261. {
  262. text::TextBuilder b;
  263. _root = b.parse(_text);
  264. }
  265. else
  266. {
  267. _root = new text::TextNode(_text.c_str());
  268. }
  269. text::Aligner rd(_style, font, scale, getSize());
  270. rd.begin();
  271. _root->resize(rd);
  272. rd.end();
  273. _root->finalPass(rd);
  274. rd.bounds = (rd.bounds.cast<RectF>() / rd.getScale()).cast<Rect>();
  275. _textRect = rd.bounds;
  276. }
  277. return _root;
  278. }
  279. const char* get_valign(TextStyle::VerticalAlign v)
  280. {
  281. switch (v)
  282. {
  283. case TextStyle::VALIGN_BASELINE:
  284. return "baseline";
  285. case TextStyle::VALIGN_TOP:
  286. return "top";
  287. case TextStyle::VALIGN_BOTTOM:
  288. return "bottom";
  289. case TextStyle::VALIGN_MIDDLE:
  290. return "middle";
  291. }
  292. return "unknown";
  293. }
  294. const char* get_halign(TextStyle::HorizontalAlign v)
  295. {
  296. switch (v)
  297. {
  298. case TextStyle::HALIGN_DEFAULT:
  299. return "default";
  300. case TextStyle::HALIGN_LEFT:
  301. return "left";
  302. case TextStyle::HALIGN_RIGHT:
  303. return "right";
  304. case TextStyle::HALIGN_MIDDLE:
  305. return "middle";
  306. }
  307. return "unknown";
  308. }
  309. std::string dumpStyle(const TextStyle& s, bool onlydiff)
  310. {
  311. TextStyle def;
  312. std::stringstream stream;
  313. if (!onlydiff || def.hAlign != s.hAlign)
  314. stream << "hAlign=" << get_halign(s.hAlign);
  315. if (!onlydiff || def.vAlign != s.vAlign)
  316. stream << " vAlign=" << get_valign(s.vAlign);
  317. if (!onlydiff || def.multiline != s.multiline)
  318. stream << " " << (s.multiline ? "multiline" : "singleline");
  319. if (!onlydiff || def.breakLongWords != s.breakLongWords)
  320. stream << " " << (s.breakLongWords ? "breakLongWords=1" : "breakLongWords=0");
  321. if (!onlydiff || def.kerning != s.kerning)
  322. stream << " kerning=" << s.kerning;
  323. if (!onlydiff || def.linesOffset != s.linesOffset)
  324. stream << " linesOffset=" << s.linesOffset;
  325. if (!onlydiff || def.fontSize != s.fontSize)
  326. stream << " fontSize=" << s.fontSize;
  327. if (!onlydiff || def.outline != s.outline)
  328. stream << " outline=" << s.outline;
  329. if (s.font)
  330. {
  331. stream << " font='" << s.font->getName() << "'";
  332. }
  333. return stream.str();
  334. }
  335. std::string TextField::dump(const dumpOptions& options) const
  336. {
  337. std::stringstream stream;
  338. stream << "{TextField}\n";
  339. stream << _vstyle.dump();
  340. std::string text = _text;
  341. if (text.size() > 15)
  342. {
  343. text.resize(15);
  344. text += "...";
  345. }
  346. stream << " text=<div c='2b1a94'>'<![CDATA[" << text << "']]></div>";
  347. std::string st = dumpStyle(_style, true);
  348. if (st.size())
  349. stream << " textStyle={" << st << "}";
  350. if (_flags & flag_html)
  351. {
  352. stream << " htmlMode";
  353. }
  354. Rect r = const_cast<TextField*>(this)->getTextRect();
  355. stream << " textRect=(" << r.pos.x << ", " << r.pos.y << ", " << r.size.x << ", " << r.size.y << ")";
  356. stream << "\n" << Actor::dump(options);
  357. return stream.str();
  358. }
  359. void TextField::doRender(RenderState const& rs)
  360. {
  361. rs.material->doRender(this, rs);
  362. }
  363. void TextField::serialize(serializedata* data)
  364. {
  365. inherited::serialize(data);
  366. pugi::xml_node node = data->node;
  367. TextStyle def;
  368. if (!_text.empty())
  369. node.append_attribute("text").set_value(_text.c_str());
  370. setAttr(node, "fontsize2scale", _style.fontSize, def.fontSize);
  371. setAttr(node, "linesOffset", _style.linesOffset, def.linesOffset);
  372. setAttr(node, "kerning", _style.kerning, def.kerning);
  373. setAttr(node, "valign", _style.vAlign, def.vAlign);
  374. setAttr(node, "halign", _style.hAlign, def.hAlign);
  375. setAttr(node, "multiline", _style.multiline, def.multiline);
  376. setAttr(node, "baselineScale", _style.baselineScale, def.baselineScale);
  377. setAttr(node, "breakLongWords", _style.breakLongWords, def.breakLongWords);
  378. if (_style.font)
  379. node.append_attribute("font").set_value(_style.font->getName().c_str());
  380. node.set_name("TextField");
  381. }
  382. void TextField::deserialize(const deserializedata* data)
  383. {
  384. inherited::deserialize(data);
  385. pugi::xml_node node = data->node;
  386. TextStyle def;
  387. _style.vAlign = (TextStyle::VerticalAlign)node.attribute("valign").as_int(def.vAlign);
  388. _style.hAlign = (TextStyle::HorizontalAlign)node.attribute("halign").as_int(def.hAlign);
  389. _style.multiline = node.attribute("multiline").as_bool(def.multiline);
  390. _style.breakLongWords = node.attribute("breakLongWords").as_bool(def.breakLongWords);
  391. _style.fontSize = node.attribute("fontsize2scale").as_int(def.fontSize);
  392. _style.linesOffset = node.attribute("linesOffset").as_int(def.linesOffset);
  393. _style.kerning = node.attribute("kerning").as_int(def.kerning);
  394. _style.baselineScale = node.attribute("baselineScale").as_float(def.baselineScale);
  395. const char* fnt = node.attribute("font").as_string(0);
  396. if (fnt && *fnt)
  397. {
  398. ResFont* font = data->factory->getResFont(fnt);
  399. if (font)
  400. _style.font = font;
  401. }
  402. needRebuild();
  403. setText(node.attribute("text").as_string());
  404. }
  405. }