text_buffer_manager.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. /* Copyright 2013 Jeremie Roy. All rights reserved.
  2. * License: http://www.opensource.org/licenses/BSD-2-Clause
  3. */
  4. #include "text_buffer_manager.h"
  5. #include "../cube_atlas.h"
  6. #include <bx/bx.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <math.h>
  10. #include <stddef.h> /* offsetof */
  11. #define MAX_TEXT_BUFFER_COUNT 64
  12. #define MAX_BUFFERED_CHARACTERS 8192
  13. // Table from Flexible and Economical UTF-8 Decoder
  14. // Copyright (c) 2008-2009 Bjoern Hoehrmann <[email protected]>
  15. // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
  16. static const uint8_t utf8d[] = {
  17. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
  18. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
  19. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
  20. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
  21. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
  22. 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
  23. 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
  24. 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
  25. 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
  26. 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
  27. 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
  28. 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
  29. 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
  30. 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
  31. };
  32. #define UTF8_ACCEPT 0
  33. #define UTF8_REJECT 1
  34. inline uint32_t utf8_decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
  35. uint32_t type = utf8d[byte];
  36. *codep = (*state != UTF8_ACCEPT) ?
  37. (byte & 0x3fu) | (*codep << 6) :
  38. (0xff >> type) & (byte);
  39. *state = utf8d[256 + *state*16 + type];
  40. return *state;
  41. }
  42. inline int utf8_strlen(uint8_t* s, size_t* count) {
  43. uint32_t codepoint;
  44. uint32_t state = 0;
  45. for (*count = 0; *s; ++s)
  46. if (!utf8_decode(&state, &codepoint, *s))
  47. *count += 1;
  48. return state != UTF8_ACCEPT;
  49. }
  50. class TextBuffer
  51. {
  52. public:
  53. /// TextBuffer is bound to a fontManager for glyph retrieval
  54. /// @remark the ownership of the manager is not taken
  55. TextBuffer(FontManager* _fontManager);
  56. ~TextBuffer();
  57. void setStyle(uint32_t _flags = STYLE_NORMAL) { m_styleFlags = _flags; }
  58. void setTextColor(uint32_t _rgba = 0x000000FF) { m_textColor = toABGR(_rgba); }
  59. void setBackgroundColor(uint32_t _rgba = 0x000000FF) { m_backgroundColor = toABGR(_rgba); }
  60. void setOverlineColor(uint32_t _rgba = 0x000000FF) { m_overlineColor = toABGR(_rgba); }
  61. void setUnderlineColor(uint32_t _rgba = 0x000000FF) { m_underlineColor = toABGR(_rgba); }
  62. void setStrikeThroughColor(uint32_t _rgba = 0x000000FF) { m_strikeThroughColor = toABGR(_rgba); }
  63. void setPenPosition(float _x, float _y) { m_penX = _x; m_penY = _y; }
  64. /// return the size of the text
  65. //Rectangle measureText(FontHandle _fontHandle, const char * _string);
  66. //Rectangle measureText(FontHandle _fontHandle, const wchar_t * _string);
  67. /// append an ASCII/utf-8 string to the buffer using current pen position and color
  68. void appendText(FontHandle _fontHandle, const char * _string);
  69. /// append a wide char unicode string to the buffer using current pen position and color
  70. void appendText(FontHandle _fontHandle, const wchar_t * _string);
  71. /// Clear the text buffer and reset its state (pen/color)
  72. void clearTextBuffer();
  73. /// get pointer to the vertex buffer to submit it to the graphic card
  74. const uint8_t* getVertexBuffer(){ return (uint8_t*) m_vertexBuffer; }
  75. /// number of vertex in the vertex buffer
  76. uint32_t getVertexCount(){ return m_vertexCount; }
  77. /// size in bytes of a vertex
  78. uint32_t getVertexSize(){ return sizeof(TextVertex); }
  79. /// get a pointer to the index buffer to submit it to the graphic
  80. const uint16_t* getIndexBuffer(){ return m_indexBuffer; }
  81. /// number of index in the index buffer
  82. uint32_t getIndexCount(){ return m_indexCount; }
  83. /// size in bytes of an index
  84. uint32_t getIndexSize(){ return sizeof(uint16_t); }
  85. uint32_t getTextColor(){ return toABGR(m_textColor); }
  86. private:
  87. void appendGlyph(CodePoint_t _codePoint, const FontInfo& _font, const GlyphInfo& _glyphInfo);
  88. void verticalCenterLastLine(float _txtDecalY, float _top, float _bottom);
  89. uint32_t toABGR(uint32_t _rgba)
  90. {
  91. return (((_rgba >> 0) & 0xff) << 24) |
  92. (((_rgba >> 8) & 0xff) << 16) |
  93. (((_rgba >> 16) & 0xff) << 8) |
  94. (((_rgba >> 24) & 0xff) << 0);
  95. }
  96. uint32_t m_styleFlags;
  97. // color states
  98. uint32_t m_textColor;
  99. uint32_t m_backgroundColor;
  100. uint32_t m_overlineColor;
  101. uint32_t m_underlineColor;
  102. uint32_t m_strikeThroughColor;
  103. //position states
  104. float m_penX;
  105. float m_penY;
  106. float m_originX;
  107. float m_originY;
  108. float m_lineAscender;
  109. float m_lineDescender;
  110. float m_lineGap;
  111. ///
  112. FontManager* m_fontManager;
  113. void setVertex(uint32_t _i, float _x, float _y, uint32_t _rgba, uint8_t _style = STYLE_NORMAL)
  114. {
  115. m_vertexBuffer[_i].x = _x;
  116. m_vertexBuffer[_i].y = _y;
  117. m_vertexBuffer[_i].rgba = _rgba;
  118. m_styleBuffer[_i] = _style;
  119. }
  120. struct TextVertex
  121. {
  122. float x,y;
  123. int16_t u,v,w,t;
  124. uint32_t rgba;
  125. };
  126. TextVertex* m_vertexBuffer;
  127. uint16_t* m_indexBuffer;
  128. uint8_t* m_styleBuffer;
  129. uint32_t m_vertexCount;
  130. uint32_t m_indexCount;
  131. uint32_t m_lineStartIndex;
  132. };
  133. TextBuffer::TextBuffer(FontManager* _fontManager)
  134. {
  135. m_styleFlags = STYLE_NORMAL;
  136. //0xAABBGGRR
  137. m_textColor = 0xFFFFFFFF;
  138. m_backgroundColor = 0xFFFFFFFF;
  139. m_backgroundColor = 0xFFFFFFFF;
  140. m_overlineColor = 0xFFFFFFFF;
  141. m_underlineColor = 0xFFFFFFFF;
  142. m_strikeThroughColor = 0xFFFFFFFF;
  143. m_penX = 0;
  144. m_penY = 0;
  145. m_originX = 0;
  146. m_originY = 0;
  147. m_lineAscender = 0;
  148. m_lineDescender = 0;
  149. m_lineGap = 0;
  150. m_fontManager = _fontManager;
  151. m_vertexBuffer = new TextVertex[MAX_BUFFERED_CHARACTERS * 4];
  152. m_indexBuffer = new uint16_t[MAX_BUFFERED_CHARACTERS * 6];
  153. m_styleBuffer = new uint8_t[MAX_BUFFERED_CHARACTERS * 4];
  154. m_vertexCount = 0;
  155. m_indexCount = 0;
  156. m_lineStartIndex = 0;
  157. }
  158. TextBuffer::~TextBuffer()
  159. {
  160. delete[] m_vertexBuffer;
  161. delete[] m_indexBuffer;
  162. }
  163. void TextBuffer::appendText(FontHandle _fontHandle, const char * _string)
  164. {
  165. GlyphInfo glyph;
  166. const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
  167. if(m_vertexCount == 0)
  168. {
  169. m_originX = m_penX;
  170. m_originY = m_penY;
  171. m_lineDescender = 0;// font.m_descender;
  172. m_lineAscender = 0;//font.m_ascender;
  173. }
  174. uint32_t codepoint;
  175. uint32_t state = 0;
  176. for (; *_string; ++_string)
  177. if (!utf8_decode(&state, &codepoint, *_string))
  178. {
  179. if(m_fontManager->getGlyphInfo(_fontHandle, (CodePoint_t)codepoint, glyph))
  180. {
  181. appendGlyph((CodePoint_t)codepoint, font, glyph);
  182. }else
  183. {
  184. BX_CHECK(false, "Glyph not found");
  185. }
  186. }
  187. //printf("U+%04X\n", codepoint);
  188. if (state != UTF8_ACCEPT)
  189. {
  190. // assert(false && "The string is not well-formed");
  191. return; //"The string is not well-formed\n"
  192. }
  193. }
  194. void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t * _string)
  195. {
  196. GlyphInfo glyph;
  197. const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
  198. if(m_vertexCount == 0)
  199. {
  200. m_originX = m_penX;
  201. m_originY = m_penY;
  202. m_lineDescender = 0;// font.m_descender;
  203. m_lineAscender = 0;//font.m_ascender;
  204. m_lineGap = 0;
  205. }
  206. //parse string
  207. for( uint32_t ii=0, end = wcslen(_string) ; ii < end; ++ii )
  208. {
  209. //if glyph cached, continue
  210. uint32_t _codePoint = _string[ii];
  211. if(m_fontManager->getGlyphInfo(_fontHandle, _codePoint, glyph))
  212. {
  213. appendGlyph(_codePoint, font, glyph);
  214. }else
  215. {
  216. BX_CHECK(false, "Glyph not found");
  217. }
  218. }
  219. }
  220. /*
  221. TextBuffer::Rectangle TextBuffer::measureText(FontHandle _fontHandle, const char * _string)
  222. {
  223. }
  224. TextBuffer::Rectangle TextBuffer::measureText(FontHandle _fontHandle, const wchar_t * _string)
  225. {
  226. }
  227. */
  228. void TextBuffer::clearTextBuffer()
  229. {
  230. m_vertexCount = 0;
  231. m_indexCount = 0;
  232. m_lineStartIndex = 0;
  233. m_lineAscender = 0;
  234. m_lineDescender = 0;
  235. }
  236. void TextBuffer::appendGlyph(CodePoint_t _codePoint, const FontInfo& _font, const GlyphInfo& _glyphInfo)
  237. {
  238. //handle newlines
  239. if(_codePoint == L'\n' )
  240. {
  241. m_penX = m_originX;
  242. m_penY -= m_lineDescender;
  243. m_penY += m_lineGap;
  244. m_lineDescender = 0;
  245. m_lineAscender = 0;
  246. m_lineStartIndex = m_vertexCount;
  247. return;
  248. }
  249. if( _font.m_ascender > m_lineAscender || (_font.m_descender < m_lineDescender) )
  250. {
  251. if( _font.m_descender < m_lineDescender )
  252. {
  253. m_lineDescender = _font.m_descender;
  254. m_lineGap = _font.m_lineGap;
  255. }
  256. float txtDecals = (_font.m_ascender - m_lineAscender);
  257. m_lineAscender = _font.m_ascender;
  258. m_lineGap = _font.m_lineGap;
  259. m_penY += txtDecals;
  260. verticalCenterLastLine((txtDecals), (m_penY - m_lineAscender), (m_penY - m_lineDescender+m_lineGap));
  261. }
  262. //handle kerning
  263. float kerning = 0;
  264. /*
  265. if( previous && markup->font->kerning )
  266. {
  267. kerning = texture_glyph_get_kerning( glyph, previous );
  268. }
  269. */
  270. m_penX += kerning * _font.m_scale;
  271. GlyphInfo& blackGlyph = m_fontManager->getBlackGlyph();
  272. if( m_styleFlags & STYLE_BACKGROUND && m_backgroundColor & 0xFF000000)
  273. {
  274. float x0 = ( m_penX - kerning );
  275. float y0 = ( m_penY - m_lineAscender);
  276. float x1 = ( (float)x0 + (_glyphInfo.m_advance_x));
  277. float y1 = ( m_penY - m_lineDescender + m_lineGap );
  278. m_fontManager->getAtlas()->packUV(blackGlyph.m_regionIndex, (uint8_t*)m_vertexBuffer,sizeof(TextVertex) *m_vertexCount + offsetof(TextVertex, u), sizeof(TextVertex));
  279. setVertex(m_vertexCount+0, x0, y0, m_backgroundColor,STYLE_BACKGROUND);
  280. setVertex(m_vertexCount+1, x0, y1, m_backgroundColor,STYLE_BACKGROUND);
  281. setVertex(m_vertexCount+2, x1, y1, m_backgroundColor,STYLE_BACKGROUND);
  282. setVertex(m_vertexCount+3, x1, y0, m_backgroundColor,STYLE_BACKGROUND);
  283. m_indexBuffer[m_indexCount + 0] = m_vertexCount+0;
  284. m_indexBuffer[m_indexCount + 1] = m_vertexCount+1;
  285. m_indexBuffer[m_indexCount + 2] = m_vertexCount+2;
  286. m_indexBuffer[m_indexCount + 3] = m_vertexCount+0;
  287. m_indexBuffer[m_indexCount + 4] = m_vertexCount+2;
  288. m_indexBuffer[m_indexCount + 5] = m_vertexCount+3;
  289. m_vertexCount += 4;
  290. m_indexCount += 6;
  291. }
  292. if( m_styleFlags & STYLE_UNDERLINE && m_underlineColor & 0xFF000000)
  293. {
  294. float x0 = ( m_penX - kerning );
  295. float y0 = (m_penY - m_lineDescender/2 );
  296. float x1 = ( (float)x0 + (_glyphInfo.m_advance_x));
  297. float y1 = y0+_font.m_underline_thickness;
  298. m_fontManager->getAtlas()->packUV(blackGlyph.m_regionIndex, (uint8_t*)m_vertexBuffer,sizeof(TextVertex) *m_vertexCount + offsetof(TextVertex, u), sizeof(TextVertex));
  299. setVertex(m_vertexCount+0, x0, y0, m_underlineColor,STYLE_UNDERLINE);
  300. setVertex(m_vertexCount+1, x0, y1, m_underlineColor,STYLE_UNDERLINE);
  301. setVertex(m_vertexCount+2, x1, y1, m_underlineColor,STYLE_UNDERLINE);
  302. setVertex(m_vertexCount+3, x1, y0, m_underlineColor,STYLE_UNDERLINE);
  303. m_indexBuffer[m_indexCount + 0] = m_vertexCount+0;
  304. m_indexBuffer[m_indexCount + 1] = m_vertexCount+1;
  305. m_indexBuffer[m_indexCount + 2] = m_vertexCount+2;
  306. m_indexBuffer[m_indexCount + 3] = m_vertexCount+0;
  307. m_indexBuffer[m_indexCount + 4] = m_vertexCount+2;
  308. m_indexBuffer[m_indexCount + 5] = m_vertexCount+3;
  309. m_vertexCount += 4;
  310. m_indexCount += 6;
  311. }
  312. if( m_styleFlags & STYLE_OVERLINE && m_overlineColor & 0xFF000000)
  313. {
  314. float x0 = ( m_penX - kerning );
  315. float y0 = (m_penY - _font.m_ascender );
  316. float x1 = ( (float)x0 + (_glyphInfo.m_advance_x));
  317. float y1 = y0+_font.m_underline_thickness;
  318. m_fontManager->getAtlas()->packUV(blackGlyph.m_regionIndex, (uint8_t*)m_vertexBuffer,sizeof(TextVertex) *m_vertexCount + offsetof(TextVertex, u), sizeof(TextVertex));
  319. setVertex(m_vertexCount+0, x0, y0, m_overlineColor,STYLE_OVERLINE);
  320. setVertex(m_vertexCount+1, x0, y1, m_overlineColor,STYLE_OVERLINE);
  321. setVertex(m_vertexCount+2, x1, y1, m_overlineColor,STYLE_OVERLINE);
  322. setVertex(m_vertexCount+3, x1, y0, m_overlineColor,STYLE_OVERLINE);
  323. m_indexBuffer[m_indexCount + 0] = m_vertexCount+0;
  324. m_indexBuffer[m_indexCount + 1] = m_vertexCount+1;
  325. m_indexBuffer[m_indexCount + 2] = m_vertexCount+2;
  326. m_indexBuffer[m_indexCount + 3] = m_vertexCount+0;
  327. m_indexBuffer[m_indexCount + 4] = m_vertexCount+2;
  328. m_indexBuffer[m_indexCount + 5] = m_vertexCount+3;
  329. m_vertexCount += 4;
  330. m_indexCount += 6;
  331. }
  332. if( m_styleFlags & STYLE_STRIKE_THROUGH && m_strikeThroughColor & 0xFF000000)
  333. {
  334. float x0 = ( m_penX - kerning );
  335. float y0 = (m_penY - _font.m_ascender/3 );
  336. float x1 = ( (float)x0 + (_glyphInfo.m_advance_x) );
  337. float y1 = y0+_font.m_underline_thickness;
  338. m_fontManager->getAtlas()->packUV(blackGlyph.m_regionIndex, (uint8_t*)m_vertexBuffer,sizeof(TextVertex) *m_vertexCount + offsetof(TextVertex, u), sizeof(TextVertex));
  339. setVertex(m_vertexCount+0, x0, y0, m_strikeThroughColor,STYLE_STRIKE_THROUGH);
  340. setVertex(m_vertexCount+1, x0, y1, m_strikeThroughColor,STYLE_STRIKE_THROUGH);
  341. setVertex(m_vertexCount+2, x1, y1, m_strikeThroughColor,STYLE_STRIKE_THROUGH);
  342. setVertex(m_vertexCount+3, x1, y0, m_strikeThroughColor,STYLE_STRIKE_THROUGH);
  343. m_indexBuffer[m_indexCount + 0] = m_vertexCount+0;
  344. m_indexBuffer[m_indexCount + 1] = m_vertexCount+1;
  345. m_indexBuffer[m_indexCount + 2] = m_vertexCount+2;
  346. m_indexBuffer[m_indexCount + 3] = m_vertexCount+0;
  347. m_indexBuffer[m_indexCount + 4] = m_vertexCount+2;
  348. m_indexBuffer[m_indexCount + 5] = m_vertexCount+3;
  349. m_vertexCount += 4;
  350. m_indexCount += 6;
  351. }
  352. //handle glyph
  353. float x0_precise = m_penX + (_glyphInfo.m_offset_x);
  354. float x0 = ( x0_precise);
  355. float y0 = ( m_penY + (_glyphInfo.m_offset_y));
  356. float x1 = ( x0 + _glyphInfo.m_width );
  357. float y1 = ( y0 + _glyphInfo.m_height );
  358. m_fontManager->getAtlas()->packUV(_glyphInfo.m_regionIndex, (uint8_t*)m_vertexBuffer, sizeof(TextVertex) *m_vertexCount + offsetof(TextVertex, u), sizeof(TextVertex));
  359. setVertex(m_vertexCount+0, x0, y0, m_textColor);
  360. setVertex(m_vertexCount+1, x0, y1, m_textColor);
  361. setVertex(m_vertexCount+2, x1, y1, m_textColor);
  362. setVertex(m_vertexCount+3, x1, y0, m_textColor);
  363. m_indexBuffer[m_indexCount + 0] = m_vertexCount+0;
  364. m_indexBuffer[m_indexCount + 1] = m_vertexCount+1;
  365. m_indexBuffer[m_indexCount + 2] = m_vertexCount+2;
  366. m_indexBuffer[m_indexCount + 3] = m_vertexCount+0;
  367. m_indexBuffer[m_indexCount + 4] = m_vertexCount+2;
  368. m_indexBuffer[m_indexCount + 5] = m_vertexCount+3;
  369. m_vertexCount += 4;
  370. m_indexCount += 6;
  371. //TODO see what to do when doing subpixel rendering
  372. m_penX += _glyphInfo.m_advance_x;
  373. }
  374. void TextBuffer::verticalCenterLastLine(float _dy, float _top, float _bottom)
  375. {
  376. for( uint32_t ii=m_lineStartIndex; ii < m_vertexCount; ii+=4 )
  377. {
  378. if( m_styleBuffer[ii] == STYLE_BACKGROUND)
  379. {
  380. m_vertexBuffer[ii+0].y = _top;
  381. m_vertexBuffer[ii+1].y = _bottom;
  382. m_vertexBuffer[ii+2].y = _bottom;
  383. m_vertexBuffer[ii+3].y = _top;
  384. }else{
  385. m_vertexBuffer[ii+0].y += _dy;
  386. m_vertexBuffer[ii+1].y += _dy;
  387. m_vertexBuffer[ii+2].y += _dy;
  388. m_vertexBuffer[ii+3].y += _dy;
  389. }
  390. }
  391. }
  392. // ****************************************************************
  393. TextBufferManager::TextBufferManager(FontManager* _fontManager):m_fontManager(_fontManager), m_textBufferHandles(MAX_TEXT_BUFFER_COUNT)
  394. {
  395. m_textBuffers = new BufferCache[MAX_TEXT_BUFFER_COUNT];
  396. }
  397. TextBufferManager::~TextBufferManager()
  398. {
  399. BX_CHECK(m_textBufferHandles.getNumHandles() == 0, "All the text buffers must be destroyed before destroying the manager");
  400. delete[] m_textBuffers;
  401. bgfx::destroyUniform(u_texColor);
  402. bgfx::destroyUniform(u_inverse_gamma);
  403. bgfx::destroyProgram(m_basicProgram);
  404. bgfx::destroyProgram(m_distanceProgram);
  405. bgfx::destroyProgram(m_distanceSubpixelProgram);
  406. }
  407. void TextBufferManager::init(const char* _shaderPath)
  408. {
  409. m_vertexDecl.begin();
  410. m_vertexDecl.add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float);
  411. m_vertexDecl.add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Int16, true);
  412. m_vertexDecl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
  413. m_vertexDecl.end();
  414. u_texColor = bgfx::createUniform("u_texColor", bgfx::UniformType::Uniform1iv);
  415. u_inverse_gamma = bgfx::createUniform("u_inverse_gamma", bgfx::UniformType::Uniform1f);
  416. const bgfx::Memory* mem;
  417. mem = loadShader(_shaderPath, "vs_font_basic");
  418. bgfx::VertexShaderHandle vsh = bgfx::createVertexShader(mem);
  419. mem = loadShader(_shaderPath, "fs_font_basic");
  420. bgfx::FragmentShaderHandle fsh = bgfx::createFragmentShader(mem);
  421. m_basicProgram = bgfx::createProgram(vsh, fsh);
  422. bgfx::destroyVertexShader(vsh);
  423. bgfx::destroyFragmentShader(fsh);
  424. mem = loadShader(_shaderPath, "vs_font_distance_field");
  425. vsh = bgfx::createVertexShader(mem);
  426. mem = loadShader(_shaderPath, "fs_font_distance_field");
  427. fsh = bgfx::createFragmentShader(mem);
  428. m_distanceProgram = bgfx::createProgram(vsh, fsh);
  429. bgfx::destroyVertexShader(vsh);
  430. bgfx::destroyFragmentShader(fsh);
  431. mem = loadShader(_shaderPath, "vs_font_distance_field_subpixel");
  432. vsh = bgfx::createVertexShader(mem);
  433. mem = loadShader(_shaderPath, "fs_font_distance_field_subpixel");
  434. fsh = bgfx::createFragmentShader(mem);
  435. m_distanceSubpixelProgram = bgfx::createProgram(vsh, fsh);
  436. bgfx::destroyVertexShader(vsh);
  437. bgfx::destroyFragmentShader(fsh);
  438. }
  439. TextBufferHandle TextBufferManager::createTextBuffer(FontType _type, BufferType _bufferType)
  440. {
  441. uint16_t textIdx = m_textBufferHandles.alloc();
  442. BufferCache& bc = m_textBuffers[textIdx];
  443. bc.m_textBuffer = new TextBuffer(m_fontManager);
  444. bc.m_fontType = _type;
  445. bc.m_bufferType = _bufferType;
  446. bc.m_indexBufferHandle = bgfx::invalidHandle;
  447. bc.m_vertexBufferHandle = bgfx::invalidHandle;
  448. TextBufferHandle ret = {textIdx};
  449. return ret;
  450. }
  451. void TextBufferManager::destroyTextBuffer(TextBufferHandle _handle)
  452. {
  453. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  454. BufferCache& bc = m_textBuffers[_handle.idx];
  455. m_textBufferHandles.free(_handle.idx);
  456. delete bc.m_textBuffer;
  457. bc.m_textBuffer = NULL;
  458. if(bc.m_vertexBufferHandle == bgfx::invalidHandle ) return;
  459. switch(bc.m_bufferType)
  460. {
  461. case STATIC:
  462. {
  463. bgfx::IndexBufferHandle ibh;
  464. bgfx::VertexBufferHandle vbh;
  465. ibh.idx = bc.m_indexBufferHandle;
  466. vbh.idx = bc.m_vertexBufferHandle;
  467. bgfx::destroyIndexBuffer(ibh);
  468. bgfx::destroyVertexBuffer(vbh);
  469. }
  470. break;
  471. case DYNAMIC:
  472. bgfx::DynamicIndexBufferHandle ibh;
  473. bgfx::DynamicVertexBufferHandle vbh;
  474. ibh.idx = bc.m_indexBufferHandle;
  475. vbh.idx = bc.m_vertexBufferHandle;
  476. bgfx::destroyDynamicIndexBuffer(ibh);
  477. bgfx::destroyDynamicVertexBuffer(vbh);
  478. break;
  479. case TRANSIENT: //naturally destroyed
  480. break;
  481. }
  482. }
  483. void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, uint8_t _id, int32_t _depth)
  484. {
  485. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  486. BufferCache& bc = m_textBuffers[_handle.idx];
  487. uint32_t indexSize = bc.m_textBuffer->getIndexCount() * bc.m_textBuffer->getIndexSize();
  488. uint32_t vertexSize = bc.m_textBuffer->getVertexCount() * bc.m_textBuffer->getVertexSize();
  489. const bgfx::Memory* mem;
  490. bgfx::setTexture(0, u_texColor, m_fontManager->getAtlas()->getTextureHandle());
  491. float inverse_gamme = 1.0f/2.2f;
  492. bgfx::setUniform(u_inverse_gamma, &inverse_gamme);
  493. switch (bc.m_fontType)
  494. {
  495. case FONT_TYPE_ALPHA:
  496. bgfx::setProgram(m_basicProgram);
  497. bgfx::setState( BGFX_STATE_RGB_WRITE | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) );
  498. break;
  499. case FONT_TYPE_DISTANCE:
  500. bgfx::setProgram(m_distanceProgram);
  501. bgfx::setState( BGFX_STATE_RGB_WRITE | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) );
  502. break;
  503. case FONT_TYPE_DISTANCE_SUBPIXEL:
  504. bgfx::setProgram(m_distanceSubpixelProgram);
  505. bgfx::setState( BGFX_STATE_RGB_WRITE |BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR) , bc.m_textBuffer->getTextColor());
  506. break;
  507. }
  508. switch(bc.m_bufferType)
  509. {
  510. case STATIC:
  511. {
  512. bgfx::IndexBufferHandle ibh;
  513. bgfx::VertexBufferHandle vbh;
  514. if(bc.m_vertexBufferHandle == bgfx::invalidHandle)
  515. {
  516. mem = bgfx::alloc(indexSize);
  517. memcpy(mem->data, bc.m_textBuffer->getIndexBuffer(), indexSize);
  518. ibh = bgfx::createIndexBuffer(mem);
  519. mem = bgfx::alloc(vertexSize);
  520. memcpy(mem->data, bc.m_textBuffer->getVertexBuffer(), vertexSize);
  521. vbh = bgfx::createVertexBuffer(mem, m_vertexDecl);
  522. bc.m_indexBufferHandle = ibh.idx ;
  523. bc.m_vertexBufferHandle = vbh.idx;
  524. }else
  525. {
  526. ibh.idx = bc.m_indexBufferHandle;
  527. vbh.idx = bc.m_vertexBufferHandle;
  528. }
  529. bgfx::setVertexBuffer(vbh, bc.m_textBuffer->getVertexCount());
  530. bgfx::setIndexBuffer(ibh, bc.m_textBuffer->getIndexCount());
  531. }break;
  532. case DYNAMIC:
  533. {
  534. bgfx::DynamicIndexBufferHandle ibh;
  535. bgfx::DynamicVertexBufferHandle vbh;
  536. if(bc.m_vertexBufferHandle == bgfx::invalidHandle)
  537. {
  538. mem = bgfx::alloc(indexSize);
  539. memcpy(mem->data, bc.m_textBuffer->getIndexBuffer(), indexSize);
  540. ibh = bgfx::createDynamicIndexBuffer(mem);
  541. mem = bgfx::alloc(vertexSize);
  542. memcpy(mem->data, bc.m_textBuffer->getVertexBuffer(), vertexSize);
  543. vbh = bgfx::createDynamicVertexBuffer(mem, m_vertexDecl);
  544. bc.m_indexBufferHandle = ibh.idx ;
  545. bc.m_vertexBufferHandle = vbh.idx;
  546. }else
  547. {
  548. ibh.idx = bc.m_indexBufferHandle;
  549. vbh.idx = bc.m_vertexBufferHandle;
  550. mem = bgfx::alloc(indexSize);
  551. memcpy(mem->data, bc.m_textBuffer->getIndexBuffer(), indexSize);
  552. bgfx::updateDynamicIndexBuffer(ibh, mem);
  553. mem = bgfx::alloc(vertexSize);
  554. memcpy(mem->data, bc.m_textBuffer->getVertexBuffer(), vertexSize);
  555. bgfx::updateDynamicVertexBuffer(vbh, mem);
  556. }
  557. bgfx::setVertexBuffer(vbh, bc.m_textBuffer->getVertexCount());
  558. bgfx::setIndexBuffer(ibh, bc.m_textBuffer->getIndexCount());
  559. }break;
  560. case TRANSIENT:
  561. {
  562. bgfx::TransientIndexBuffer tib;
  563. bgfx::TransientVertexBuffer tvb;
  564. bgfx::allocTransientIndexBuffer(&tib, bc.m_textBuffer->getIndexCount());
  565. bgfx::allocTransientVertexBuffer(&tvb, bc.m_textBuffer->getVertexCount(), m_vertexDecl);
  566. memcpy(tib.data, bc.m_textBuffer->getIndexBuffer(), indexSize);
  567. memcpy(tvb.data, bc.m_textBuffer->getVertexBuffer(), vertexSize);
  568. bgfx::setVertexBuffer(&tvb, bc.m_textBuffer->getVertexCount());
  569. bgfx::setIndexBuffer(&tib, bc.m_textBuffer->getIndexCount());
  570. }break;
  571. }
  572. bgfx::submit(_id, _depth);
  573. }
  574. void TextBufferManager::submitTextBufferMask(TextBufferHandle /*_handle*/, uint32_t /*_viewMask*/, int32_t /*_depth*/)
  575. {
  576. //TODO
  577. BX_CHECK(false, "TODO TODO");
  578. }
  579. void TextBufferManager::setStyle(TextBufferHandle _handle, uint32_t _flags )
  580. {
  581. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  582. BufferCache& bc = m_textBuffers[_handle.idx];
  583. bc.m_textBuffer->setStyle(_flags);
  584. }
  585. void TextBufferManager::setTextColor(TextBufferHandle _handle, uint32_t _rgba )
  586. {
  587. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  588. BufferCache& bc = m_textBuffers[_handle.idx];
  589. bc.m_textBuffer->setTextColor(_rgba);
  590. }
  591. void TextBufferManager::setBackgroundColor(TextBufferHandle _handle, uint32_t _rgba )
  592. {
  593. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  594. BufferCache& bc = m_textBuffers[_handle.idx];
  595. bc.m_textBuffer->setBackgroundColor(_rgba);
  596. }
  597. void TextBufferManager::setOverlineColor(TextBufferHandle _handle, uint32_t _rgba )
  598. {
  599. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  600. BufferCache& bc = m_textBuffers[_handle.idx];
  601. bc.m_textBuffer->setOverlineColor(_rgba);
  602. }
  603. void TextBufferManager::setUnderlineColor(TextBufferHandle _handle, uint32_t _rgba )
  604. {
  605. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  606. BufferCache& bc = m_textBuffers[_handle.idx];
  607. bc.m_textBuffer->setUnderlineColor(_rgba);
  608. }
  609. void TextBufferManager::setStrikeThroughColor(TextBufferHandle _handle, uint32_t _rgba )
  610. {
  611. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  612. BufferCache& bc = m_textBuffers[_handle.idx];
  613. bc.m_textBuffer->setStrikeThroughColor(_rgba);
  614. }
  615. void TextBufferManager::setPenPosition(TextBufferHandle _handle, float _x, float _y)
  616. {
  617. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  618. BufferCache& bc = m_textBuffers[_handle.idx];
  619. bc.m_textBuffer->setPenPosition(_x,_y);
  620. }
  621. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char * _string)
  622. {
  623. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  624. BufferCache& bc = m_textBuffers[_handle.idx];
  625. bc.m_textBuffer->appendText(_fontHandle, _string);
  626. }
  627. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t * _string)
  628. {
  629. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  630. BufferCache& bc = m_textBuffers[_handle.idx];
  631. bc.m_textBuffer->appendText(_fontHandle, _string);
  632. }
  633. void TextBufferManager::clearTextBuffer(TextBufferHandle _handle)
  634. {
  635. BX_CHECK( bgfx::invalidHandle != _handle.idx, "Invalid handle used");
  636. BufferCache& bc = m_textBuffers[_handle.idx];
  637. bc.m_textBuffer->clearTextBuffer();
  638. }