text_buffer_manager.cpp 26 KB

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