text_buffer_manager.cpp 27 KB

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