TextField.cpp 12 KB

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