text_buffer_manager.cpp 27 KB

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