text_buffer_manager.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896
  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
  57. /// position and color.
  58. void appendText(FontHandle _fontHandle, const char* _string, const char* _end = NULL);
  59. /// Append a wide char unicode string to the buffer using current pen
  60. /// position and color.
  61. void appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end = NULL);
  62. /// Append a whole face of the atlas cube, mostly used for debugging
  63. /// 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() const
  74. {
  75. return m_vertexCount;
  76. }
  77. /// Size in bytes of a vertex.
  78. uint32_t getVertexSize() const
  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() const
  84. {
  85. return m_indexBuffer;
  86. }
  87. /// number of index in the index buffer
  88. uint32_t getIndexCount() const
  89. {
  90. return m_indexCount;
  91. }
  92. /// Size in bytes of an index.
  93. uint32_t getIndexSize() const
  94. {
  95. return sizeof(uint16_t);
  96. }
  97. uint32_t getTextColor() const
  98. {
  99. return toABGR(m_textColor);
  100. }
  101. TextRectangle getRectangle() const
  102. {
  103. return m_rectangle;
  104. }
  105. private:
  106. void appendGlyph(FontHandle _handle, CodePoint _codePoint);
  107. void verticalCenterLastLine(float _txtDecalY, float _top, float _bottom);
  108. static 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. }
  116. uint32_t m_styleFlags;
  117. // color states
  118. uint32_t m_textColor;
  119. uint32_t m_backgroundColor;
  120. uint32_t m_overlineColor;
  121. uint32_t m_underlineColor;
  122. uint32_t m_strikeThroughColor;
  123. //position states
  124. float m_penX;
  125. float m_penY;
  126. float m_originX;
  127. float m_originY;
  128. float m_lineAscender;
  129. float m_lineDescender;
  130. float m_lineGap;
  131. TextRectangle m_rectangle;
  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, 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. for (; *_string && _string<_end ; ++_string)
  196. {
  197. if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT )
  198. {
  199. appendGlyph(_fontHandle, codepoint);
  200. }
  201. }
  202. BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed");
  203. }
  204. void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end)
  205. {
  206. if (m_vertexCount == 0)
  207. {
  208. m_originX = m_penX;
  209. m_originY = m_penY;
  210. m_lineDescender = 0;
  211. m_lineAscender = 0;
  212. m_lineGap = 0;
  213. }
  214. if (_end == NULL)
  215. {
  216. _end = _string + (uint32_t) wcslen(_string);
  217. }
  218. BX_CHECK(_end >= _string);
  219. for (const wchar_t* _current = _string; _current < _end; ++_current)
  220. {
  221. uint32_t _codePoint = *_current;
  222. appendGlyph(_fontHandle, _codePoint);
  223. }
  224. }
  225. void TextBuffer::appendAtlasFace(uint16_t _faceIndex)
  226. {
  227. if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
  228. {
  229. return;
  230. }
  231. float x0 = m_penX;
  232. float y0 = m_penY;
  233. float x1 = x0 + (float)m_fontManager->getAtlas()->getTextureSize();
  234. float y1 = y0 + (float)m_fontManager->getAtlas()->getTextureSize();
  235. m_fontManager->getAtlas()->packFaceLayerUV(_faceIndex
  236. , (uint8_t*)m_vertexBuffer
  237. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  238. , sizeof(TextVertex)
  239. );
  240. setVertex(m_vertexCount + 0, x0, y0, m_backgroundColor);
  241. setVertex(m_vertexCount + 1, x0, y1, m_backgroundColor);
  242. setVertex(m_vertexCount + 2, x1, y1, m_backgroundColor);
  243. setVertex(m_vertexCount + 3, x1, y0, m_backgroundColor);
  244. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  245. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  246. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  247. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  248. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  249. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  250. m_vertexCount += 4;
  251. m_indexCount += 6;
  252. }
  253. void TextBuffer::clearTextBuffer()
  254. {
  255. m_penX = 0;
  256. m_penY = 0;
  257. m_originX = 0;
  258. m_originY = 0;
  259. m_vertexCount = 0;
  260. m_indexCount = 0;
  261. m_lineStartIndex = 0;
  262. m_lineAscender = 0;
  263. m_lineDescender = 0;
  264. m_lineGap = 0;
  265. m_rectangle.width = 0;
  266. m_rectangle.height = 0;
  267. }
  268. void TextBuffer::appendGlyph(FontHandle _handle, CodePoint _codePoint)
  269. {
  270. const GlyphInfo* glyph = m_fontManager->getGlyphInfo(_handle, _codePoint);
  271. BX_WARN(NULL != glyph, "Glyph not found (font handle %d, code point %d)", _handle.idx, _codePoint);
  272. if (NULL == glyph)
  273. {
  274. return;
  275. }
  276. const FontInfo& font = m_fontManager->getFontInfo(_handle);
  277. if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
  278. {
  279. return;
  280. }
  281. if (_codePoint == L'\n')
  282. {
  283. m_penX = m_originX;
  284. m_penY += m_lineGap + m_lineAscender -m_lineDescender;
  285. m_lineGap = font.lineGap;
  286. m_lineDescender = font.descender;
  287. m_lineAscender = font.ascender;
  288. m_lineStartIndex = m_vertexCount;
  289. return;
  290. }
  291. //is there a change of font size that require the text on the left to be centered again ?
  292. if (font.ascender > m_lineAscender
  293. || (font.descender < m_lineDescender) )
  294. {
  295. if (font.descender < m_lineDescender)
  296. {
  297. m_lineDescender = font.descender;
  298. m_lineGap = font.lineGap;
  299. }
  300. float txtDecals = (font.ascender - m_lineAscender);
  301. m_lineAscender = font.ascender;
  302. m_lineGap = font.lineGap;
  303. verticalCenterLastLine( (txtDecals), (m_penY - m_lineAscender), (m_penY + m_lineAscender - m_lineDescender + m_lineGap) );
  304. }
  305. float kerning = 0 * font.scale;
  306. m_penX += kerning;
  307. const GlyphInfo& blackGlyph = m_fontManager->getBlackGlyph();
  308. if (m_styleFlags & STYLE_BACKGROUND
  309. && m_backgroundColor & 0xFF000000)
  310. {
  311. float x0 = (m_penX - kerning);
  312. float y0 = (m_penY);
  313. float x1 = ( (float)x0 + (glyph->advance_x) );
  314. float y1 = (m_penY + m_lineAscender - m_lineDescender + m_lineGap);
  315. m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex
  316. , (uint8_t*)m_vertexBuffer
  317. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  318. , sizeof(TextVertex)
  319. );
  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 + (glyph->advance_x) );
  339. float y1 = y0 + font.underlineThickness;
  340. m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex
  341. , (uint8_t*)m_vertexBuffer
  342. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  343. , sizeof(TextVertex)
  344. );
  345. setVertex(m_vertexCount + 0, x0, y0, m_underlineColor, STYLE_UNDERLINE);
  346. setVertex(m_vertexCount + 1, x0, y1, m_underlineColor, STYLE_UNDERLINE);
  347. setVertex(m_vertexCount + 2, x1, y1, m_underlineColor, STYLE_UNDERLINE);
  348. setVertex(m_vertexCount + 3, x1, y0, m_underlineColor, STYLE_UNDERLINE);
  349. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  350. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  351. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  352. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  353. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  354. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  355. m_vertexCount += 4;
  356. m_indexCount += 6;
  357. }
  358. if (m_styleFlags & STYLE_OVERLINE
  359. && m_overlineColor & 0xFF000000)
  360. {
  361. float x0 = (m_penX - kerning);
  362. float y0 = (m_penY);
  363. float x1 = ( (float)x0 + (glyph->advance_x) );
  364. float y1 = y0 + font.underlineThickness;
  365. m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex
  366. , (uint8_t*)m_vertexBuffer
  367. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  368. , sizeof(TextVertex)
  369. );
  370. setVertex(m_vertexCount + 0, x0, y0, m_overlineColor, STYLE_OVERLINE);
  371. setVertex(m_vertexCount + 1, x0, y1, m_overlineColor, STYLE_OVERLINE);
  372. setVertex(m_vertexCount + 2, x1, y1, m_overlineColor, STYLE_OVERLINE);
  373. setVertex(m_vertexCount + 3, x1, y0, m_overlineColor, STYLE_OVERLINE);
  374. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  375. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  376. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  377. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  378. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  379. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  380. m_vertexCount += 4;
  381. m_indexCount += 6;
  382. }
  383. if (m_styleFlags & STYLE_STRIKE_THROUGH
  384. && m_strikeThroughColor & 0xFF000000)
  385. {
  386. float x0 = (m_penX - kerning);
  387. float y0 = (m_penY + 0.666667f * font.ascender);
  388. float x1 = ( (float)x0 + (glyph->advance_x) );
  389. float y1 = y0 + font.underlineThickness;
  390. m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex
  391. , (uint8_t*)m_vertexBuffer
  392. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  393. , sizeof(TextVertex)
  394. );
  395. setVertex(m_vertexCount + 0, x0, y0, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  396. setVertex(m_vertexCount + 1, x0, y1, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  397. setVertex(m_vertexCount + 2, x1, y1, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  398. setVertex(m_vertexCount + 3, x1, y0, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  399. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  400. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  401. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  402. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  403. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  404. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  405. m_vertexCount += 4;
  406. m_indexCount += 6;
  407. }
  408. float x0 = m_penX + (glyph->offset_x);
  409. float y0 = (m_penY + m_lineAscender + (glyph->offset_y) );
  410. float x1 = (x0 + glyph->width);
  411. float y1 = (y0 + glyph->height);
  412. m_fontManager->getAtlas()->packUV(glyph->regionIndex
  413. , (uint8_t*)m_vertexBuffer
  414. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  415. , sizeof(TextVertex)
  416. );
  417. setVertex(m_vertexCount + 0, x0, y0, m_textColor);
  418. setVertex(m_vertexCount + 1, x0, y1, m_textColor);
  419. setVertex(m_vertexCount + 2, x1, y1, m_textColor);
  420. setVertex(m_vertexCount + 3, x1, y0, m_textColor);
  421. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  422. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  423. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  424. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  425. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  426. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  427. m_vertexCount += 4;
  428. m_indexCount += 6;
  429. m_penX += glyph->advance_x;
  430. if (m_penX > m_rectangle.width)
  431. {
  432. m_rectangle.width = m_penX;
  433. }
  434. if ( (m_penY +m_lineAscender - m_lineDescender+m_lineGap) > m_rectangle.height)
  435. {
  436. m_rectangle.height = (m_penY +m_lineAscender - m_lineDescender+m_lineGap);
  437. }
  438. }
  439. void TextBuffer::verticalCenterLastLine(float _dy, float _top, float _bottom)
  440. {
  441. for (uint32_t ii = m_lineStartIndex; ii < m_vertexCount; ii += 4)
  442. {
  443. if (m_styleBuffer[ii] == STYLE_BACKGROUND)
  444. {
  445. m_vertexBuffer[ii + 0].y = _top;
  446. m_vertexBuffer[ii + 1].y = _bottom;
  447. m_vertexBuffer[ii + 2].y = _bottom;
  448. m_vertexBuffer[ii + 3].y = _top;
  449. }
  450. else
  451. {
  452. m_vertexBuffer[ii + 0].y += _dy;
  453. m_vertexBuffer[ii + 1].y += _dy;
  454. m_vertexBuffer[ii + 2].y += _dy;
  455. m_vertexBuffer[ii + 3].y += _dy;
  456. }
  457. }
  458. }
  459. TextBufferManager::TextBufferManager(FontManager* _fontManager)
  460. : m_textBufferHandles(MAX_TEXT_BUFFER_COUNT)
  461. , m_fontManager(_fontManager)
  462. {
  463. m_textBuffers = new BufferCache[MAX_TEXT_BUFFER_COUNT];
  464. const bgfx::Memory* vs_font_basic;
  465. const bgfx::Memory* fs_font_basic;
  466. const bgfx::Memory* vs_font_distance_field;
  467. const bgfx::Memory* fs_font_distance_field;
  468. const bgfx::Memory* vs_font_distance_field_subpixel;
  469. const bgfx::Memory* fs_font_distance_field_subpixel;
  470. switch (bgfx::getRendererType() )
  471. {
  472. case bgfx::RendererType::Direct3D9:
  473. vs_font_basic = bgfx::makeRef(vs_font_basic_dx9, sizeof(vs_font_basic_dx9) );
  474. fs_font_basic = bgfx::makeRef(fs_font_basic_dx9, sizeof(fs_font_basic_dx9) );
  475. vs_font_distance_field = bgfx::makeRef(vs_font_distance_field_dx9, sizeof(vs_font_distance_field_dx9) );
  476. fs_font_distance_field = bgfx::makeRef(fs_font_distance_field_dx9, sizeof(fs_font_distance_field_dx9) );
  477. vs_font_distance_field_subpixel = bgfx::makeRef(vs_font_distance_field_subpixel_dx9, sizeof(vs_font_distance_field_subpixel_dx9) );
  478. fs_font_distance_field_subpixel = bgfx::makeRef(fs_font_distance_field_subpixel_dx9, sizeof(fs_font_distance_field_subpixel_dx9) );
  479. break;
  480. case bgfx::RendererType::Direct3D11:
  481. vs_font_basic = bgfx::makeRef(vs_font_basic_dx11, sizeof(vs_font_basic_dx11) );
  482. fs_font_basic = bgfx::makeRef(fs_font_basic_dx11, sizeof(fs_font_basic_dx11) );
  483. vs_font_distance_field = bgfx::makeRef(vs_font_distance_field_dx11, sizeof(vs_font_distance_field_dx11) );
  484. fs_font_distance_field = bgfx::makeRef(fs_font_distance_field_dx11, sizeof(fs_font_distance_field_dx11) );
  485. vs_font_distance_field_subpixel = bgfx::makeRef(vs_font_distance_field_subpixel_dx11, sizeof(vs_font_distance_field_subpixel_dx11) );
  486. fs_font_distance_field_subpixel = bgfx::makeRef(fs_font_distance_field_subpixel_dx11, sizeof(fs_font_distance_field_subpixel_dx11) );
  487. break;
  488. default:
  489. vs_font_basic = bgfx::makeRef(vs_font_basic_glsl, sizeof(vs_font_basic_glsl) );
  490. fs_font_basic = bgfx::makeRef(fs_font_basic_glsl, sizeof(fs_font_basic_glsl) );
  491. vs_font_distance_field = bgfx::makeRef(vs_font_distance_field_glsl, sizeof(vs_font_distance_field_glsl) );
  492. fs_font_distance_field = bgfx::makeRef(fs_font_distance_field_glsl, sizeof(fs_font_distance_field_glsl) );
  493. vs_font_distance_field_subpixel = bgfx::makeRef(vs_font_distance_field_subpixel_glsl, sizeof(vs_font_distance_field_subpixel_glsl) );
  494. fs_font_distance_field_subpixel = bgfx::makeRef(fs_font_distance_field_subpixel_glsl, sizeof(fs_font_distance_field_subpixel_glsl) );
  495. break;
  496. }
  497. bgfx::VertexShaderHandle vsh;
  498. bgfx::FragmentShaderHandle fsh;
  499. vsh = bgfx::createVertexShader(vs_font_basic);
  500. fsh = bgfx::createFragmentShader(fs_font_basic);
  501. m_basicProgram = bgfx::createProgram(vsh, fsh);
  502. bgfx::destroyVertexShader(vsh);
  503. bgfx::destroyFragmentShader(fsh);
  504. vsh = bgfx::createVertexShader(vs_font_distance_field);
  505. fsh = bgfx::createFragmentShader(fs_font_distance_field);
  506. m_distanceProgram = bgfx::createProgram(vsh, fsh);
  507. bgfx::destroyVertexShader(vsh);
  508. bgfx::destroyFragmentShader(fsh);
  509. vsh = bgfx::createVertexShader(vs_font_distance_field_subpixel);
  510. fsh = bgfx::createFragmentShader(fs_font_distance_field_subpixel);
  511. m_distanceSubpixelProgram = bgfx::createProgram(vsh, fsh);
  512. bgfx::destroyVertexShader(vsh);
  513. bgfx::destroyFragmentShader(fsh);
  514. m_vertexDecl.begin();
  515. m_vertexDecl.add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float);
  516. m_vertexDecl.add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Int16, true);
  517. m_vertexDecl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
  518. m_vertexDecl.end();
  519. u_texColor = bgfx::createUniform("u_texColor", bgfx::UniformType::Uniform1iv);
  520. u_inverse_gamma = bgfx::createUniform("u_inverse_gamma", bgfx::UniformType::Uniform1f);
  521. }
  522. TextBufferManager::~TextBufferManager()
  523. {
  524. BX_CHECK(m_textBufferHandles.getNumHandles() == 0, "All the text buffers must be destroyed before destroying the manager");
  525. delete[] m_textBuffers;
  526. bgfx::destroyUniform(u_texColor);
  527. bgfx::destroyUniform(u_inverse_gamma);
  528. bgfx::destroyProgram(m_basicProgram);
  529. bgfx::destroyProgram(m_distanceProgram);
  530. bgfx::destroyProgram(m_distanceSubpixelProgram);
  531. }
  532. TextBufferHandle TextBufferManager::createTextBuffer(uint32_t _type, BufferType _bufferType)
  533. {
  534. uint16_t textIdx = m_textBufferHandles.alloc();
  535. BufferCache& bc = m_textBuffers[textIdx];
  536. bc.textBuffer = new TextBuffer(m_fontManager);
  537. bc.fontType = _type;
  538. bc.bufferType = _bufferType;
  539. bc.indexBufferHandle = bgfx::invalidHandle;
  540. bc.vertexBufferHandle = bgfx::invalidHandle;
  541. TextBufferHandle ret = {textIdx};
  542. return ret;
  543. }
  544. void TextBufferManager::destroyTextBuffer(TextBufferHandle _handle)
  545. {
  546. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  547. BufferCache& bc = m_textBuffers[_handle.idx];
  548. m_textBufferHandles.free(_handle.idx);
  549. delete bc.textBuffer;
  550. bc.textBuffer = NULL;
  551. if (bc.vertexBufferHandle == bgfx::invalidHandle)
  552. {
  553. return;
  554. }
  555. switch (bc.bufferType)
  556. {
  557. case STATIC:
  558. {
  559. bgfx::IndexBufferHandle ibh;
  560. bgfx::VertexBufferHandle vbh;
  561. ibh.idx = bc.indexBufferHandle;
  562. vbh.idx = bc.vertexBufferHandle;
  563. bgfx::destroyIndexBuffer(ibh);
  564. bgfx::destroyVertexBuffer(vbh);
  565. }
  566. break;
  567. case DYNAMIC:
  568. bgfx::DynamicIndexBufferHandle ibh;
  569. bgfx::DynamicVertexBufferHandle vbh;
  570. ibh.idx = bc.indexBufferHandle;
  571. vbh.idx = bc.vertexBufferHandle;
  572. bgfx::destroyDynamicIndexBuffer(ibh);
  573. bgfx::destroyDynamicVertexBuffer(vbh);
  574. break;
  575. case TRANSIENT: //naturally destroyed
  576. break;
  577. }
  578. }
  579. void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id, int32_t _depth)
  580. {
  581. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  582. BufferCache& bc = m_textBuffers[_handle.idx];
  583. uint32_t indexSize = bc.textBuffer->getIndexCount() * bc.textBuffer->getIndexSize();
  584. uint32_t vertexSize = bc.textBuffer->getVertexCount() * bc.textBuffer->getVertexSize();
  585. const bgfx::Memory* mem;
  586. bgfx::setTexture(0, u_texColor, m_fontManager->getAtlas()->getTextureHandle() );
  587. float inverse_gamme = 1.0f / 2.2f;
  588. bgfx::setUniform(u_inverse_gamma, &inverse_gamme);
  589. switch (bc.fontType)
  590. {
  591. case FONT_TYPE_ALPHA:
  592. bgfx::setProgram(m_basicProgram);
  593. bgfx::setState(0
  594. | BGFX_STATE_RGB_WRITE
  595. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  596. );
  597. break;
  598. case FONT_TYPE_DISTANCE:
  599. bgfx::setProgram(m_distanceProgram);
  600. bgfx::setState(0
  601. | BGFX_STATE_RGB_WRITE
  602. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  603. );
  604. break;
  605. case FONT_TYPE_DISTANCE_SUBPIXEL:
  606. bgfx::setProgram(m_distanceSubpixelProgram);
  607. bgfx::setState(0
  608. | BGFX_STATE_RGB_WRITE
  609. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR)
  610. , bc.textBuffer->getTextColor()
  611. );
  612. break;
  613. }
  614. switch (bc.bufferType)
  615. {
  616. case STATIC:
  617. {
  618. bgfx::IndexBufferHandle ibh;
  619. bgfx::VertexBufferHandle vbh;
  620. if (bc.vertexBufferHandle == bgfx::invalidHandle)
  621. {
  622. mem = bgfx::alloc(indexSize);
  623. memcpy(mem->data, bc.textBuffer->getIndexBuffer(), indexSize);
  624. ibh = bgfx::createIndexBuffer(mem);
  625. mem = bgfx::alloc(vertexSize);
  626. memcpy(mem->data, bc.textBuffer->getVertexBuffer(), vertexSize);
  627. vbh = bgfx::createVertexBuffer(mem, m_vertexDecl);
  628. bc.indexBufferHandle = ibh.idx;
  629. bc.vertexBufferHandle = vbh.idx;
  630. }
  631. else
  632. {
  633. ibh.idx = bc.indexBufferHandle;
  634. vbh.idx = bc.vertexBufferHandle;
  635. }
  636. bgfx::setVertexBuffer(vbh, bc.textBuffer->getVertexCount() );
  637. bgfx::setIndexBuffer(ibh, bc.textBuffer->getIndexCount() );
  638. } break;
  639. case DYNAMIC:
  640. {
  641. bgfx::DynamicIndexBufferHandle ibh;
  642. bgfx::DynamicVertexBufferHandle vbh;
  643. if (bc.vertexBufferHandle == bgfx::invalidHandle)
  644. {
  645. mem = bgfx::alloc(indexSize);
  646. memcpy(mem->data, bc.textBuffer->getIndexBuffer(), indexSize);
  647. ibh = bgfx::createDynamicIndexBuffer(mem);
  648. mem = bgfx::alloc(vertexSize);
  649. memcpy(mem->data, bc.textBuffer->getVertexBuffer(), vertexSize);
  650. vbh = bgfx::createDynamicVertexBuffer(mem, m_vertexDecl);
  651. bc.indexBufferHandle = ibh.idx;
  652. bc.vertexBufferHandle = vbh.idx;
  653. }
  654. else
  655. {
  656. ibh.idx = bc.indexBufferHandle;
  657. vbh.idx = bc.vertexBufferHandle;
  658. mem = bgfx::alloc(indexSize);
  659. memcpy(mem->data, bc.textBuffer->getIndexBuffer(), indexSize);
  660. bgfx::updateDynamicIndexBuffer(ibh, mem);
  661. mem = bgfx::alloc(vertexSize);
  662. memcpy(mem->data, bc.textBuffer->getVertexBuffer(), vertexSize);
  663. bgfx::updateDynamicVertexBuffer(vbh, mem);
  664. }
  665. bgfx::setVertexBuffer(vbh, bc.textBuffer->getVertexCount() );
  666. bgfx::setIndexBuffer(ibh, bc.textBuffer->getIndexCount() );
  667. } break;
  668. case TRANSIENT:
  669. {
  670. bgfx::TransientIndexBuffer tib;
  671. bgfx::TransientVertexBuffer tvb;
  672. bgfx::allocTransientIndexBuffer(&tib, bc.textBuffer->getIndexCount() );
  673. bgfx::allocTransientVertexBuffer(&tvb, bc.textBuffer->getVertexCount(), m_vertexDecl);
  674. memcpy(tib.data, bc.textBuffer->getIndexBuffer(), indexSize);
  675. memcpy(tvb.data, bc.textBuffer->getVertexBuffer(), vertexSize);
  676. bgfx::setVertexBuffer(&tvb, bc.textBuffer->getVertexCount() );
  677. bgfx::setIndexBuffer(&tib, bc.textBuffer->getIndexCount() );
  678. } break;
  679. }
  680. bgfx::submit(_id, _depth);
  681. }
  682. void TextBufferManager::setStyle(TextBufferHandle _handle, uint32_t _flags)
  683. {
  684. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  685. BufferCache& bc = m_textBuffers[_handle.idx];
  686. bc.textBuffer->setStyle(_flags);
  687. }
  688. void TextBufferManager::setTextColor(TextBufferHandle _handle, uint32_t _rgba)
  689. {
  690. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  691. BufferCache& bc = m_textBuffers[_handle.idx];
  692. bc.textBuffer->setTextColor(_rgba);
  693. }
  694. void TextBufferManager::setBackgroundColor(TextBufferHandle _handle, uint32_t _rgba)
  695. {
  696. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  697. BufferCache& bc = m_textBuffers[_handle.idx];
  698. bc.textBuffer->setBackgroundColor(_rgba);
  699. }
  700. void TextBufferManager::setOverlineColor(TextBufferHandle _handle, uint32_t _rgba)
  701. {
  702. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  703. BufferCache& bc = m_textBuffers[_handle.idx];
  704. bc.textBuffer->setOverlineColor(_rgba);
  705. }
  706. void TextBufferManager::setUnderlineColor(TextBufferHandle _handle, uint32_t _rgba)
  707. {
  708. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  709. BufferCache& bc = m_textBuffers[_handle.idx];
  710. bc.textBuffer->setUnderlineColor(_rgba);
  711. }
  712. void TextBufferManager::setStrikeThroughColor(TextBufferHandle _handle, uint32_t _rgba)
  713. {
  714. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  715. BufferCache& bc = m_textBuffers[_handle.idx];
  716. bc.textBuffer->setStrikeThroughColor(_rgba);
  717. }
  718. void TextBufferManager::setPenPosition(TextBufferHandle _handle, float _x, float _y)
  719. {
  720. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  721. BufferCache& bc = m_textBuffers[_handle.idx];
  722. bc.textBuffer->setPenPosition(_x, _y);
  723. }
  724. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string, const char* _end)
  725. {
  726. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  727. BufferCache& bc = m_textBuffers[_handle.idx];
  728. bc.textBuffer->appendText(_fontHandle, _string, _end);
  729. }
  730. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end)
  731. {
  732. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  733. BufferCache& bc = m_textBuffers[_handle.idx];
  734. bc.textBuffer->appendText(_fontHandle, _string, _end);
  735. }
  736. void TextBufferManager::appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex)
  737. {
  738. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  739. BufferCache& bc = m_textBuffers[_handle.idx];
  740. bc.textBuffer->appendAtlasFace(_faceIndex);
  741. }
  742. void TextBufferManager::clearTextBuffer(TextBufferHandle _handle)
  743. {
  744. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  745. BufferCache& bc = m_textBuffers[_handle.idx];
  746. bc.textBuffer->clearTextBuffer();
  747. }
  748. TextRectangle TextBufferManager::getRectangle(TextBufferHandle _handle) const
  749. {
  750. BX_CHECK(bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  751. BufferCache& bc = m_textBuffers[_handle.idx];
  752. return bc.textBuffer->getRectangle();
  753. }