text_buffer_manager.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  1. /*
  2. * Copyright 2013 Jeremie Roy. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "../common.h"
  6. #include <bgfx/bgfx.h>
  7. #include <bgfx/embedded_shader.h>
  8. #include <stddef.h> // offsetof
  9. #include <memory.h> // memcpy
  10. #include <wchar.h> // wcslen
  11. #include "text_buffer_manager.h"
  12. #include "utf8.h"
  13. #include "../cube_atlas.h"
  14. #include "vs_font_basic.bin.h"
  15. #include "fs_font_basic.bin.h"
  16. #include "vs_font_distance_field.bin.h"
  17. #include "fs_font_distance_field.bin.h"
  18. #include "vs_font_distance_field_subpixel.bin.h"
  19. #include "fs_font_distance_field_subpixel.bin.h"
  20. static const bgfx::EmbeddedShader s_embeddedShaders[] =
  21. {
  22. BGFX_EMBEDDED_SHADER(vs_font_basic),
  23. BGFX_EMBEDDED_SHADER(fs_font_basic),
  24. BGFX_EMBEDDED_SHADER(vs_font_distance_field),
  25. BGFX_EMBEDDED_SHADER(fs_font_distance_field),
  26. BGFX_EMBEDDED_SHADER(vs_font_distance_field_subpixel),
  27. BGFX_EMBEDDED_SHADER(fs_font_distance_field_subpixel),
  28. BGFX_EMBEDDED_SHADER_END()
  29. };
  30. #define MAX_BUFFERED_CHARACTERS (8192 - 5)
  31. class TextBuffer
  32. {
  33. public:
  34. /// TextBuffer is bound to a fontManager for glyph retrieval
  35. /// @remark the ownership of the manager is not taken
  36. TextBuffer(FontManager* _fontManager);
  37. ~TextBuffer();
  38. void setStyle(uint32_t _flags = STYLE_NORMAL)
  39. {
  40. m_styleFlags = _flags;
  41. }
  42. void setTextColor(uint32_t _rgba = 0x000000FF)
  43. {
  44. m_textColor = toABGR(_rgba);
  45. }
  46. void setBackgroundColor(uint32_t _rgba = 0x000000FF)
  47. {
  48. m_backgroundColor = toABGR(_rgba);
  49. }
  50. void setOverlineColor(uint32_t _rgba = 0x000000FF)
  51. {
  52. m_overlineColor = toABGR(_rgba);
  53. }
  54. void setUnderlineColor(uint32_t _rgba = 0x000000FF)
  55. {
  56. m_underlineColor = toABGR(_rgba);
  57. }
  58. void setStrikeThroughColor(uint32_t _rgba = 0x000000FF)
  59. {
  60. m_strikeThroughColor = toABGR(_rgba);
  61. }
  62. void setPenPosition(float _x, float _y)
  63. {
  64. m_penX = _x; m_penY = _y;
  65. }
  66. /// Append an ASCII/utf-8 string to the buffer using current pen
  67. /// position and color.
  68. void appendText(FontHandle _fontHandle, const char* _string, const char* _end = NULL);
  69. /// Append a wide char unicode string to the buffer using current pen
  70. /// position and color.
  71. void appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end = NULL);
  72. /// Append a whole face of the atlas cube, mostly used for debugging
  73. /// and visualizing atlas.
  74. void appendAtlasFace(uint16_t _faceIndex);
  75. /// Clear the text buffer and reset its state (pen/color)
  76. void clearTextBuffer();
  77. /// Get pointer to the vertex buffer to submit it to the graphic card.
  78. const uint8_t* getVertexBuffer()
  79. {
  80. return (uint8_t*) m_vertexBuffer;
  81. }
  82. /// Number of vertex in the vertex buffer.
  83. uint32_t getVertexCount() const
  84. {
  85. return m_vertexCount;
  86. }
  87. /// Size in bytes of a vertex.
  88. uint32_t getVertexSize() const
  89. {
  90. return sizeof(TextVertex);
  91. }
  92. /// get a pointer to the index buffer to submit it to the graphic
  93. const uint16_t* getIndexBuffer() const
  94. {
  95. return m_indexBuffer;
  96. }
  97. /// number of index in the index buffer
  98. uint32_t getIndexCount() const
  99. {
  100. return m_indexCount;
  101. }
  102. /// Size in bytes of an index.
  103. uint32_t getIndexSize() const
  104. {
  105. return sizeof(uint16_t);
  106. }
  107. uint32_t getTextColor() const
  108. {
  109. return toABGR(m_textColor);
  110. }
  111. TextRectangle getRectangle() const
  112. {
  113. return m_rectangle;
  114. }
  115. private:
  116. void appendGlyph(FontHandle _handle, CodePoint _codePoint);
  117. void verticalCenterLastLine(float _txtDecalY, float _top, float _bottom);
  118. static uint32_t toABGR(uint32_t _rgba)
  119. {
  120. return ( ( (_rgba >> 0) & 0xff) << 24)
  121. | ( ( (_rgba >> 8) & 0xff) << 16)
  122. | ( ( (_rgba >> 16) & 0xff) << 8)
  123. | ( ( (_rgba >> 24) & 0xff) << 0)
  124. ;
  125. }
  126. uint32_t m_styleFlags;
  127. // color states
  128. uint32_t m_textColor;
  129. uint32_t m_backgroundColor;
  130. uint32_t m_overlineColor;
  131. uint32_t m_underlineColor;
  132. uint32_t m_strikeThroughColor;
  133. //position states
  134. float m_penX;
  135. float m_penY;
  136. float m_originX;
  137. float m_originY;
  138. float m_lineAscender;
  139. float m_lineDescender;
  140. float m_lineGap;
  141. TextRectangle m_rectangle;
  142. FontManager* m_fontManager;
  143. void setVertex(uint32_t _i, float _x, float _y, uint32_t _rgba, uint8_t _style = STYLE_NORMAL)
  144. {
  145. m_vertexBuffer[_i].x = _x;
  146. m_vertexBuffer[_i].y = _y;
  147. m_vertexBuffer[_i].rgba = _rgba;
  148. m_styleBuffer[_i] = _style;
  149. }
  150. struct TextVertex
  151. {
  152. float x, y;
  153. int16_t u, v, w, t;
  154. uint32_t rgba;
  155. };
  156. TextVertex* m_vertexBuffer;
  157. uint16_t* m_indexBuffer;
  158. uint8_t* m_styleBuffer;
  159. uint32_t m_indexCount;
  160. uint32_t m_lineStartIndex;
  161. uint16_t m_vertexCount;
  162. };
  163. TextBuffer::TextBuffer(FontManager* _fontManager)
  164. : m_styleFlags(STYLE_NORMAL)
  165. , m_textColor(0xffffffff)
  166. , m_backgroundColor(0xffffffff)
  167. , m_overlineColor(0xffffffff)
  168. , m_underlineColor(0xffffffff)
  169. , m_strikeThroughColor(0xffffffff)
  170. , m_penX(0)
  171. , m_penY(0)
  172. , m_originX(0)
  173. , m_originY(0)
  174. , m_lineAscender(0)
  175. , m_lineDescender(0)
  176. , m_lineGap(0)
  177. , m_fontManager(_fontManager)
  178. , m_vertexBuffer(new TextVertex[MAX_BUFFERED_CHARACTERS * 4])
  179. , m_indexBuffer(new uint16_t[MAX_BUFFERED_CHARACTERS * 6])
  180. , m_styleBuffer(new uint8_t[MAX_BUFFERED_CHARACTERS * 4])
  181. , m_indexCount(0)
  182. , m_lineStartIndex(0)
  183. , m_vertexCount(0)
  184. {
  185. m_rectangle.width = 0;
  186. m_rectangle.height = 0;
  187. }
  188. TextBuffer::~TextBuffer()
  189. {
  190. delete [] m_vertexBuffer;
  191. delete [] m_indexBuffer;
  192. delete [] m_styleBuffer;
  193. }
  194. void TextBuffer::appendText(FontHandle _fontHandle, const char* _string, const char* _end)
  195. {
  196. if (m_vertexCount == 0)
  197. {
  198. m_originX = m_penX;
  199. m_originY = m_penY;
  200. m_lineDescender = 0;
  201. m_lineAscender = 0;
  202. m_lineGap = 0;
  203. }
  204. CodePoint codepoint = 0;
  205. uint32_t state = 0;
  206. if (_end == NULL)
  207. {
  208. _end = _string + strlen(_string);
  209. }
  210. BX_CHECK(_end >= _string);
  211. for (; *_string && _string < _end ; ++_string)
  212. {
  213. if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT )
  214. {
  215. appendGlyph(_fontHandle, codepoint);
  216. }
  217. }
  218. BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
  219. }
  220. void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end)
  221. {
  222. if (m_vertexCount == 0)
  223. {
  224. m_originX = m_penX;
  225. m_originY = m_penY;
  226. m_lineDescender = 0;
  227. m_lineAscender = 0;
  228. m_lineGap = 0;
  229. }
  230. if (_end == NULL)
  231. {
  232. _end = _string + wcslen(_string);
  233. }
  234. BX_CHECK(_end >= _string);
  235. for (const wchar_t* _current = _string; _current < _end; ++_current)
  236. {
  237. uint32_t _codePoint = *_current;
  238. appendGlyph(_fontHandle, _codePoint);
  239. }
  240. }
  241. void TextBuffer::appendAtlasFace(uint16_t _faceIndex)
  242. {
  243. if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
  244. {
  245. return;
  246. }
  247. float x0 = m_penX;
  248. float y0 = m_penY;
  249. float x1 = x0 + (float)m_fontManager->getAtlas()->getTextureSize();
  250. float y1 = y0 + (float)m_fontManager->getAtlas()->getTextureSize();
  251. m_fontManager->getAtlas()->packFaceLayerUV(_faceIndex
  252. , (uint8_t*)m_vertexBuffer
  253. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  254. , sizeof(TextVertex)
  255. );
  256. setVertex(m_vertexCount + 0, x0, y0, m_backgroundColor);
  257. setVertex(m_vertexCount + 1, x0, y1, m_backgroundColor);
  258. setVertex(m_vertexCount + 2, x1, y1, m_backgroundColor);
  259. setVertex(m_vertexCount + 3, x1, y0, m_backgroundColor);
  260. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  261. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  262. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  263. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  264. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  265. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  266. m_vertexCount += 4;
  267. m_indexCount += 6;
  268. }
  269. void TextBuffer::clearTextBuffer()
  270. {
  271. m_penX = 0;
  272. m_penY = 0;
  273. m_originX = 0;
  274. m_originY = 0;
  275. m_vertexCount = 0;
  276. m_indexCount = 0;
  277. m_lineStartIndex = 0;
  278. m_lineAscender = 0;
  279. m_lineDescender = 0;
  280. m_lineGap = 0;
  281. m_rectangle.width = 0;
  282. m_rectangle.height = 0;
  283. }
  284. void TextBuffer::appendGlyph(FontHandle _handle, CodePoint _codePoint)
  285. {
  286. if (_codePoint == L'\t')
  287. {
  288. for (uint32_t ii = 0; ii < 4; ++ii)
  289. {
  290. appendGlyph(_handle, L' ');
  291. }
  292. return;
  293. }
  294. const GlyphInfo* glyph = m_fontManager->getGlyphInfo(_handle, _codePoint);
  295. BX_WARN(NULL != glyph, "Glyph not found (font handle %d, code point %d)", _handle.idx, _codePoint);
  296. if (NULL == glyph)
  297. {
  298. return;
  299. }
  300. if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
  301. {
  302. return;
  303. }
  304. const FontInfo& font = m_fontManager->getFontInfo(_handle);
  305. if (_codePoint == L'\n')
  306. {
  307. m_penX = m_originX;
  308. m_penY += m_lineGap + m_lineAscender -m_lineDescender;
  309. m_lineGap = font.lineGap;
  310. m_lineDescender = font.descender;
  311. m_lineAscender = font.ascender;
  312. m_lineStartIndex = m_vertexCount;
  313. return;
  314. }
  315. //is there a change of font size that require the text on the left to be centered again ?
  316. if (font.ascender > m_lineAscender
  317. || (font.descender < m_lineDescender) )
  318. {
  319. if (font.descender < m_lineDescender)
  320. {
  321. m_lineDescender = font.descender;
  322. m_lineGap = font.lineGap;
  323. }
  324. float txtDecals = (font.ascender - m_lineAscender);
  325. m_lineAscender = font.ascender;
  326. m_lineGap = font.lineGap;
  327. verticalCenterLastLine( (txtDecals), (m_penY - m_lineAscender), (m_penY + m_lineAscender - m_lineDescender + m_lineGap) );
  328. }
  329. float kerning = 0 * font.scale;
  330. m_penX += kerning;
  331. const GlyphInfo& blackGlyph = m_fontManager->getBlackGlyph();
  332. const Atlas* atlas = m_fontManager->getAtlas();
  333. if (m_styleFlags & STYLE_BACKGROUND
  334. && m_backgroundColor & 0xff000000)
  335. {
  336. float x0 = (m_penX - kerning);
  337. float y0 = (m_penY);
  338. float x1 = ( (float)x0 + (glyph->advance_x) );
  339. float y1 = (m_penY + m_lineAscender - m_lineDescender + m_lineGap);
  340. atlas->packUV(blackGlyph.regionIndex
  341. , (uint8_t*)m_vertexBuffer
  342. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  343. , sizeof(TextVertex)
  344. );
  345. const uint16_t vertexCount = m_vertexCount;
  346. setVertex(vertexCount + 0, x0, y0, m_backgroundColor, STYLE_BACKGROUND);
  347. setVertex(vertexCount + 1, x0, y1, m_backgroundColor, STYLE_BACKGROUND);
  348. setVertex(vertexCount + 2, x1, y1, m_backgroundColor, STYLE_BACKGROUND);
  349. setVertex(vertexCount + 3, x1, y0, m_backgroundColor, STYLE_BACKGROUND);
  350. m_indexBuffer[m_indexCount + 0] = vertexCount + 0;
  351. m_indexBuffer[m_indexCount + 1] = vertexCount + 1;
  352. m_indexBuffer[m_indexCount + 2] = vertexCount + 2;
  353. m_indexBuffer[m_indexCount + 3] = vertexCount + 0;
  354. m_indexBuffer[m_indexCount + 4] = vertexCount + 2;
  355. m_indexBuffer[m_indexCount + 5] = vertexCount + 3;
  356. m_vertexCount += 4;
  357. m_indexCount += 6;
  358. }
  359. if (m_styleFlags & STYLE_UNDERLINE
  360. && m_underlineColor & 0xFF000000)
  361. {
  362. float x0 = (m_penX - kerning);
  363. float y0 = (m_penY + m_lineAscender - m_lineDescender * 0.5f);
  364. float x1 = ( (float)x0 + (glyph->advance_x) );
  365. float y1 = y0 + font.underlineThickness;
  366. atlas->packUV(blackGlyph.regionIndex
  367. , (uint8_t*)m_vertexBuffer
  368. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  369. , sizeof(TextVertex)
  370. );
  371. setVertex(m_vertexCount + 0, x0, y0, m_underlineColor, STYLE_UNDERLINE);
  372. setVertex(m_vertexCount + 1, x0, y1, m_underlineColor, STYLE_UNDERLINE);
  373. setVertex(m_vertexCount + 2, x1, y1, m_underlineColor, STYLE_UNDERLINE);
  374. setVertex(m_vertexCount + 3, x1, y0, m_underlineColor, STYLE_UNDERLINE);
  375. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  376. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  377. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  378. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  379. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  380. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  381. m_vertexCount += 4;
  382. m_indexCount += 6;
  383. }
  384. if (m_styleFlags & STYLE_OVERLINE
  385. && m_overlineColor & 0xFF000000)
  386. {
  387. float x0 = (m_penX - kerning);
  388. float y0 = (m_penY);
  389. float x1 = ( (float)x0 + (glyph->advance_x) );
  390. float y1 = y0 + font.underlineThickness;
  391. m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex
  392. , (uint8_t*)m_vertexBuffer
  393. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  394. , sizeof(TextVertex)
  395. );
  396. setVertex(m_vertexCount + 0, x0, y0, m_overlineColor, STYLE_OVERLINE);
  397. setVertex(m_vertexCount + 1, x0, y1, m_overlineColor, STYLE_OVERLINE);
  398. setVertex(m_vertexCount + 2, x1, y1, m_overlineColor, STYLE_OVERLINE);
  399. setVertex(m_vertexCount + 3, x1, y0, m_overlineColor, STYLE_OVERLINE);
  400. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  401. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  402. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  403. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  404. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  405. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  406. m_vertexCount += 4;
  407. m_indexCount += 6;
  408. }
  409. if (m_styleFlags & STYLE_STRIKE_THROUGH
  410. && m_strikeThroughColor & 0xFF000000)
  411. {
  412. float x0 = (m_penX - kerning);
  413. float y0 = (m_penY + 0.666667f * font.ascender);
  414. float x1 = ( (float)x0 + (glyph->advance_x) );
  415. float y1 = y0 + font.underlineThickness;
  416. atlas->packUV(blackGlyph.regionIndex
  417. , (uint8_t*)m_vertexBuffer
  418. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  419. , sizeof(TextVertex)
  420. );
  421. setVertex(m_vertexCount + 0, x0, y0, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  422. setVertex(m_vertexCount + 1, x0, y1, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  423. setVertex(m_vertexCount + 2, x1, y1, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  424. setVertex(m_vertexCount + 3, x1, y0, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  425. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  426. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  427. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  428. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  429. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  430. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  431. m_vertexCount += 4;
  432. m_indexCount += 6;
  433. }
  434. float x0 = m_penX + (glyph->offset_x);
  435. float y0 = (m_penY + m_lineAscender + (glyph->offset_y) );
  436. float x1 = (x0 + glyph->width);
  437. float y1 = (y0 + glyph->height);
  438. atlas->packUV(glyph->regionIndex
  439. , (uint8_t*)m_vertexBuffer
  440. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  441. , sizeof(TextVertex)
  442. );
  443. setVertex(m_vertexCount + 0, x0, y0, m_textColor);
  444. setVertex(m_vertexCount + 1, x0, y1, m_textColor);
  445. setVertex(m_vertexCount + 2, x1, y1, m_textColor);
  446. setVertex(m_vertexCount + 3, x1, y0, m_textColor);
  447. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  448. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  449. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  450. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  451. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  452. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  453. m_vertexCount += 4;
  454. m_indexCount += 6;
  455. m_penX += glyph->advance_x;
  456. if (m_penX > m_rectangle.width)
  457. {
  458. m_rectangle.width = m_penX;
  459. }
  460. if ( (m_penY +m_lineAscender - m_lineDescender+m_lineGap) > m_rectangle.height)
  461. {
  462. m_rectangle.height = (m_penY +m_lineAscender - m_lineDescender+m_lineGap);
  463. }
  464. }
  465. void TextBuffer::verticalCenterLastLine(float _dy, float _top, float _bottom)
  466. {
  467. for (uint32_t ii = m_lineStartIndex; ii < m_vertexCount; ii += 4)
  468. {
  469. if (m_styleBuffer[ii] == STYLE_BACKGROUND)
  470. {
  471. m_vertexBuffer[ii + 0].y = _top;
  472. m_vertexBuffer[ii + 1].y = _bottom;
  473. m_vertexBuffer[ii + 2].y = _bottom;
  474. m_vertexBuffer[ii + 3].y = _top;
  475. }
  476. else
  477. {
  478. m_vertexBuffer[ii + 0].y += _dy;
  479. m_vertexBuffer[ii + 1].y += _dy;
  480. m_vertexBuffer[ii + 2].y += _dy;
  481. m_vertexBuffer[ii + 3].y += _dy;
  482. }
  483. }
  484. }
  485. TextBufferManager::TextBufferManager(FontManager* _fontManager)
  486. : m_fontManager(_fontManager)
  487. {
  488. m_textBuffers = new BufferCache[MAX_TEXT_BUFFER_COUNT];
  489. bgfx::RendererType::Enum type = bgfx::getRendererType();
  490. m_basicProgram = bgfx::createProgram(
  491. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_basic")
  492. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_basic")
  493. , true
  494. );
  495. m_distanceProgram = bgfx::createProgram(
  496. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field")
  497. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field")
  498. , true
  499. );
  500. m_distanceSubpixelProgram = bgfx::createProgram(
  501. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_subpixel")
  502. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_subpixel")
  503. , true
  504. );
  505. m_vertexDecl
  506. .begin()
  507. .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
  508. .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Int16, true)
  509. .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
  510. .end();
  511. s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1);
  512. }
  513. TextBufferManager::~TextBufferManager()
  514. {
  515. BX_CHECK(m_textBufferHandles.getNumHandles() == 0, "All the text buffers must be destroyed before destroying the manager");
  516. delete [] m_textBuffers;
  517. bgfx::destroyUniform(s_texColor);
  518. bgfx::destroyProgram(m_basicProgram);
  519. bgfx::destroyProgram(m_distanceProgram);
  520. bgfx::destroyProgram(m_distanceSubpixelProgram);
  521. }
  522. TextBufferHandle TextBufferManager::createTextBuffer(uint32_t _type, BufferType::Enum _bufferType)
  523. {
  524. uint16_t textIdx = m_textBufferHandles.alloc();
  525. BufferCache& bc = m_textBuffers[textIdx];
  526. bc.textBuffer = new TextBuffer(m_fontManager);
  527. bc.fontType = _type;
  528. bc.bufferType = _bufferType;
  529. bc.indexBufferHandleIdx = bgfx::invalidHandle;
  530. bc.vertexBufferHandleIdx = bgfx::invalidHandle;
  531. TextBufferHandle ret = {textIdx};
  532. return ret;
  533. }
  534. void TextBufferManager::destroyTextBuffer(TextBufferHandle _handle)
  535. {
  536. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  537. BufferCache& bc = m_textBuffers[_handle.idx];
  538. m_textBufferHandles.free(_handle.idx);
  539. delete bc.textBuffer;
  540. bc.textBuffer = NULL;
  541. if (bc.vertexBufferHandleIdx == bgfx::invalidHandle)
  542. {
  543. return;
  544. }
  545. switch (bc.bufferType)
  546. {
  547. case BufferType::Static:
  548. {
  549. bgfx::IndexBufferHandle ibh;
  550. bgfx::VertexBufferHandle vbh;
  551. ibh.idx = bc.indexBufferHandleIdx;
  552. vbh.idx = bc.vertexBufferHandleIdx;
  553. bgfx::destroyIndexBuffer(ibh);
  554. bgfx::destroyVertexBuffer(vbh);
  555. }
  556. break;
  557. case BufferType::Dynamic:
  558. bgfx::DynamicIndexBufferHandle ibh;
  559. bgfx::DynamicVertexBufferHandle vbh;
  560. ibh.idx = bc.indexBufferHandleIdx;
  561. vbh.idx = bc.vertexBufferHandleIdx;
  562. bgfx::destroyDynamicIndexBuffer(ibh);
  563. bgfx::destroyDynamicVertexBuffer(vbh);
  564. break;
  565. case BufferType::Transient: // destroyed every frame
  566. break;
  567. }
  568. }
  569. void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id, int32_t _depth)
  570. {
  571. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  572. BufferCache& bc = m_textBuffers[_handle.idx];
  573. uint32_t indexSize = bc.textBuffer->getIndexCount() * bc.textBuffer->getIndexSize();
  574. uint32_t vertexSize = bc.textBuffer->getVertexCount() * bc.textBuffer->getVertexSize();
  575. if (0 == indexSize || 0 == vertexSize)
  576. {
  577. return;
  578. }
  579. bgfx::setTexture(0, s_texColor, m_fontManager->getAtlas()->getTextureHandle() );
  580. bgfx::ProgramHandle program = BGFX_INVALID_HANDLE;
  581. switch (bc.fontType)
  582. {
  583. case FONT_TYPE_ALPHA:
  584. program = m_basicProgram;
  585. bgfx::setState(0
  586. | BGFX_STATE_RGB_WRITE
  587. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  588. );
  589. break;
  590. case FONT_TYPE_DISTANCE:
  591. program = m_distanceProgram;
  592. bgfx::setState(0
  593. | BGFX_STATE_RGB_WRITE
  594. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  595. );
  596. break;
  597. case FONT_TYPE_DISTANCE_SUBPIXEL:
  598. program = m_distanceSubpixelProgram;
  599. bgfx::setState(0
  600. | BGFX_STATE_RGB_WRITE
  601. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR)
  602. , bc.textBuffer->getTextColor()
  603. );
  604. break;
  605. }
  606. switch (bc.bufferType)
  607. {
  608. case BufferType::Static:
  609. {
  610. bgfx::IndexBufferHandle ibh;
  611. bgfx::VertexBufferHandle vbh;
  612. if (bgfx::invalidHandle == bc.vertexBufferHandleIdx)
  613. {
  614. ibh = bgfx::createIndexBuffer(
  615. bgfx::copy(bc.textBuffer->getIndexBuffer(), indexSize)
  616. );
  617. vbh = bgfx::createVertexBuffer(
  618. bgfx::copy(bc.textBuffer->getVertexBuffer(), vertexSize)
  619. , m_vertexDecl
  620. );
  621. bc.vertexBufferHandleIdx = vbh.idx;
  622. bc.indexBufferHandleIdx = ibh.idx;
  623. }
  624. else
  625. {
  626. vbh.idx = bc.vertexBufferHandleIdx;
  627. ibh.idx = bc.indexBufferHandleIdx;
  628. }
  629. bgfx::setVertexBuffer(vbh, 0, bc.textBuffer->getVertexCount() );
  630. bgfx::setIndexBuffer(ibh, 0, bc.textBuffer->getIndexCount() );
  631. }
  632. break;
  633. case BufferType::Dynamic:
  634. {
  635. bgfx::DynamicIndexBufferHandle ibh;
  636. bgfx::DynamicVertexBufferHandle vbh;
  637. if (bgfx::invalidHandle == bc.vertexBufferHandleIdx )
  638. {
  639. ibh = bgfx::createDynamicIndexBuffer(
  640. bgfx::copy(bc.textBuffer->getIndexBuffer(), indexSize)
  641. );
  642. vbh = bgfx::createDynamicVertexBuffer(
  643. bgfx::copy(bc.textBuffer->getVertexBuffer(), vertexSize)
  644. , m_vertexDecl
  645. );
  646. bc.indexBufferHandleIdx = ibh.idx;
  647. bc.vertexBufferHandleIdx = vbh.idx;
  648. }
  649. else
  650. {
  651. ibh.idx = bc.indexBufferHandleIdx;
  652. vbh.idx = bc.vertexBufferHandleIdx;
  653. bgfx::updateDynamicIndexBuffer(ibh
  654. , 0
  655. , bgfx::copy(bc.textBuffer->getIndexBuffer(), indexSize)
  656. );
  657. bgfx::updateDynamicVertexBuffer(vbh
  658. , 0
  659. , bgfx::copy(bc.textBuffer->getVertexBuffer(), vertexSize)
  660. );
  661. }
  662. bgfx::setVertexBuffer(vbh, 0, bc.textBuffer->getVertexCount() );
  663. bgfx::setIndexBuffer(ibh, 0, bc.textBuffer->getIndexCount() );
  664. }
  665. break;
  666. case BufferType::Transient:
  667. {
  668. bgfx::TransientIndexBuffer tib;
  669. bgfx::TransientVertexBuffer tvb;
  670. bgfx::allocTransientIndexBuffer(&tib, bc.textBuffer->getIndexCount() );
  671. bgfx::allocTransientVertexBuffer(&tvb, bc.textBuffer->getVertexCount(), m_vertexDecl);
  672. memcpy(tib.data, bc.textBuffer->getIndexBuffer(), indexSize);
  673. memcpy(tvb.data, bc.textBuffer->getVertexBuffer(), vertexSize);
  674. bgfx::setVertexBuffer(&tvb, 0, bc.textBuffer->getVertexCount() );
  675. bgfx::setIndexBuffer(&tib, 0, bc.textBuffer->getIndexCount() );
  676. }
  677. break;
  678. }
  679. bgfx::submit(_id, program, _depth);
  680. }
  681. void TextBufferManager::setStyle(TextBufferHandle _handle, uint32_t _flags)
  682. {
  683. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  684. BufferCache& bc = m_textBuffers[_handle.idx];
  685. bc.textBuffer->setStyle(_flags);
  686. }
  687. void TextBufferManager::setTextColor(TextBufferHandle _handle, uint32_t _rgba)
  688. {
  689. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  690. BufferCache& bc = m_textBuffers[_handle.idx];
  691. bc.textBuffer->setTextColor(_rgba);
  692. }
  693. void TextBufferManager::setBackgroundColor(TextBufferHandle _handle, uint32_t _rgba)
  694. {
  695. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  696. BufferCache& bc = m_textBuffers[_handle.idx];
  697. bc.textBuffer->setBackgroundColor(_rgba);
  698. }
  699. void TextBufferManager::setOverlineColor(TextBufferHandle _handle, uint32_t _rgba)
  700. {
  701. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  702. BufferCache& bc = m_textBuffers[_handle.idx];
  703. bc.textBuffer->setOverlineColor(_rgba);
  704. }
  705. void TextBufferManager::setUnderlineColor(TextBufferHandle _handle, uint32_t _rgba)
  706. {
  707. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  708. BufferCache& bc = m_textBuffers[_handle.idx];
  709. bc.textBuffer->setUnderlineColor(_rgba);
  710. }
  711. void TextBufferManager::setStrikeThroughColor(TextBufferHandle _handle, uint32_t _rgba)
  712. {
  713. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  714. BufferCache& bc = m_textBuffers[_handle.idx];
  715. bc.textBuffer->setStrikeThroughColor(_rgba);
  716. }
  717. void TextBufferManager::setPenPosition(TextBufferHandle _handle, float _x, float _y)
  718. {
  719. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  720. BufferCache& bc = m_textBuffers[_handle.idx];
  721. bc.textBuffer->setPenPosition(_x, _y);
  722. }
  723. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string, const char* _end)
  724. {
  725. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  726. BufferCache& bc = m_textBuffers[_handle.idx];
  727. bc.textBuffer->appendText(_fontHandle, _string, _end);
  728. }
  729. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end)
  730. {
  731. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  732. BufferCache& bc = m_textBuffers[_handle.idx];
  733. bc.textBuffer->appendText(_fontHandle, _string, _end);
  734. }
  735. void TextBufferManager::appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex)
  736. {
  737. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  738. BufferCache& bc = m_textBuffers[_handle.idx];
  739. bc.textBuffer->appendAtlasFace(_faceIndex);
  740. }
  741. void TextBufferManager::clearTextBuffer(TextBufferHandle _handle)
  742. {
  743. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  744. BufferCache& bc = m_textBuffers[_handle.idx];
  745. bc.textBuffer->clearTextBuffer();
  746. }
  747. TextRectangle TextBufferManager::getRectangle(TextBufferHandle _handle) const
  748. {
  749. BX_CHECK(bgfx::isValid(_handle), "Invalid handle used");
  750. BufferCache& bc = m_textBuffers[_handle.idx];
  751. return bc.textBuffer->getRectangle();
  752. }