text_buffer_manager.cpp 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  1. /*
  2. * Copyright 2013 Jeremie Roy. All rights reserved.
  3. * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
  4. */
  5. #include "../common.h"
  6. #include <bgfx/bgfx.h>
  7. #include <bgfx/embedded_shader.h>
  8. #include <stddef.h> // offsetof
  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. #include "vs_font_distance_field_outline.bin.h"
  20. #include "fs_font_distance_field_outline.bin.h"
  21. #include "vs_font_distance_field_outline_image.bin.h"
  22. #include "fs_font_distance_field_outline_image.bin.h"
  23. #include "vs_font_distance_field_drop_shadow.bin.h"
  24. #include "fs_font_distance_field_drop_shadow.bin.h"
  25. #include "vs_font_distance_field_drop_shadow_image.bin.h"
  26. #include "fs_font_distance_field_drop_shadow_image.bin.h"
  27. #include "vs_font_distance_field_outline_drop_shadow_image.bin.h"
  28. #include "fs_font_distance_field_outline_drop_shadow_image.bin.h"
  29. static const bgfx::EmbeddedShader s_embeddedShaders[] =
  30. {
  31. BGFX_EMBEDDED_SHADER(vs_font_basic),
  32. BGFX_EMBEDDED_SHADER(fs_font_basic),
  33. BGFX_EMBEDDED_SHADER(vs_font_distance_field),
  34. BGFX_EMBEDDED_SHADER(fs_font_distance_field),
  35. BGFX_EMBEDDED_SHADER(vs_font_distance_field_subpixel),
  36. BGFX_EMBEDDED_SHADER(fs_font_distance_field_subpixel),
  37. BGFX_EMBEDDED_SHADER(vs_font_distance_field_outline),
  38. BGFX_EMBEDDED_SHADER(fs_font_distance_field_outline),
  39. BGFX_EMBEDDED_SHADER(vs_font_distance_field_outline_image),
  40. BGFX_EMBEDDED_SHADER(fs_font_distance_field_outline_image),
  41. BGFX_EMBEDDED_SHADER(vs_font_distance_field_drop_shadow),
  42. BGFX_EMBEDDED_SHADER(fs_font_distance_field_drop_shadow),
  43. BGFX_EMBEDDED_SHADER(vs_font_distance_field_drop_shadow_image),
  44. BGFX_EMBEDDED_SHADER(fs_font_distance_field_drop_shadow_image),
  45. BGFX_EMBEDDED_SHADER(vs_font_distance_field_outline_drop_shadow_image),
  46. BGFX_EMBEDDED_SHADER(fs_font_distance_field_outline_drop_shadow_image),
  47. BGFX_EMBEDDED_SHADER_END()
  48. };
  49. #define MAX_BUFFERED_CHARACTERS (8192 - 5)
  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. uint32_t getOutlineColor()
  58. {
  59. return m_outlineColor;
  60. }
  61. float getOutlineWidth()
  62. {
  63. return m_outlineWidth;
  64. }
  65. uint32_t getDropShadowColor()
  66. {
  67. return m_dropShadowColor;
  68. }
  69. float getDropShadowOffsetU()
  70. {
  71. return m_dropShadowOffset[0];
  72. }
  73. float getDropShadowOffsetV()
  74. {
  75. return m_dropShadowOffset[1];
  76. }
  77. float getDropShadowSoftener()
  78. {
  79. return m_dropShadowSoftener;
  80. }
  81. void setStyle(uint32_t _flags = STYLE_NORMAL)
  82. {
  83. m_styleFlags = _flags;
  84. }
  85. void setTextColor(uint32_t _rgba = 0x000000FF)
  86. {
  87. m_textColor = toABGR(_rgba);
  88. }
  89. void setBackgroundColor(uint32_t _rgba = 0x000000FF)
  90. {
  91. m_backgroundColor = toABGR(_rgba);
  92. }
  93. void setOverlineColor(uint32_t _rgba = 0x000000FF)
  94. {
  95. m_overlineColor = toABGR(_rgba);
  96. }
  97. void setUnderlineColor(uint32_t _rgba = 0x000000FF)
  98. {
  99. m_underlineColor = toABGR(_rgba);
  100. }
  101. void setStrikeThroughColor(uint32_t _rgba = 0x000000FF)
  102. {
  103. m_strikeThroughColor = toABGR(_rgba);
  104. }
  105. void setOutlineColor(uint32_t _rgba = 0x000000FF)
  106. {
  107. m_outlineColor = toABGR(_rgba);
  108. }
  109. void setOutlineWidth(float _outlineWidth = 3.0f)
  110. {
  111. m_outlineWidth = _outlineWidth;
  112. }
  113. void setDropShadowColor(uint32_t _rgba = 0x000000FF)
  114. {
  115. m_dropShadowColor = toABGR(_rgba);
  116. }
  117. /*
  118. void setDropShadowWidth(float _dropShadowWidth = 3.0f)
  119. {
  120. m_dropShadowWidth = _dropShadowWidth;
  121. }
  122. */
  123. void setDropShadowOffset(float u, float v)
  124. {
  125. m_dropShadowOffset[0] = u;
  126. m_dropShadowOffset[1] = v;
  127. }
  128. void setDropShadowSoftener(float smoother)
  129. {
  130. m_dropShadowSoftener = smoother;
  131. }
  132. void setPenPosition(float _x, float _y)
  133. {
  134. m_penX = _x; m_penY = _y;
  135. }
  136. /// Append an ASCII/utf-8 string to the buffer using current pen
  137. /// position and color.
  138. void appendText(FontHandle _fontHandle, const char* _string, const char* _end = NULL);
  139. /// Append a wide char unicode string to the buffer using current pen
  140. /// position and color.
  141. void appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end = NULL);
  142. /// Append a whole face of the atlas cube, mostly used for debugging
  143. /// and visualizing atlas.
  144. void appendAtlasFace(uint16_t _faceIndex);
  145. /// Clear the text buffer and reset its state (pen/color)
  146. void clearTextBuffer();
  147. /// Get pointer to the vertex buffer to submit it to the graphic card.
  148. const uint8_t* getVertexBuffer()
  149. {
  150. return (uint8_t*) m_vertexBuffer;
  151. }
  152. /// Number of vertex in the vertex buffer.
  153. uint32_t getVertexCount() const
  154. {
  155. return m_vertexCount;
  156. }
  157. /// Size in bytes of a vertex.
  158. uint32_t getVertexSize() const
  159. {
  160. return sizeof(TextVertex);
  161. }
  162. /// get a pointer to the index buffer to submit it to the graphic
  163. const uint16_t* getIndexBuffer() const
  164. {
  165. return m_indexBuffer;
  166. }
  167. /// number of index in the index buffer
  168. uint32_t getIndexCount() const
  169. {
  170. return m_indexCount;
  171. }
  172. /// Size in bytes of an index.
  173. uint32_t getIndexSize() const
  174. {
  175. return sizeof(uint16_t);
  176. }
  177. uint32_t getTextColor() const
  178. {
  179. return toABGR(m_textColor);
  180. }
  181. TextRectangle getRectangle() const
  182. {
  183. return m_rectangle;
  184. }
  185. private:
  186. void appendGlyph(FontHandle _handle, CodePoint _codePoint, bool shadow);
  187. void verticalCenterLastLine(float _txtDecalY, float _top, float _bottom);
  188. static uint32_t toABGR(uint32_t _rgba)
  189. {
  190. return ( ( (_rgba >> 0) & 0xff) << 24)
  191. | ( ( (_rgba >> 8) & 0xff) << 16)
  192. | ( ( (_rgba >> 16) & 0xff) << 8)
  193. | ( ( (_rgba >> 24) & 0xff) << 0)
  194. ;
  195. }
  196. uint32_t m_styleFlags;
  197. // color states
  198. uint32_t m_textColor;
  199. uint32_t m_backgroundColor;
  200. uint32_t m_overlineColor;
  201. uint32_t m_underlineColor;
  202. uint32_t m_strikeThroughColor;
  203. // outline state
  204. float m_outlineWidth;
  205. uint32_t m_outlineColor;
  206. // drop shadow state
  207. float m_dropShadowOffset[2];
  208. uint32_t m_dropShadowColor;
  209. float m_dropShadowSoftener;
  210. //position states
  211. float m_penX;
  212. float m_penY;
  213. float m_originX;
  214. float m_originY;
  215. float m_lineAscender;
  216. float m_lineDescender;
  217. float m_lineGap;
  218. CodePoint m_previousCodePoint;
  219. TextRectangle m_rectangle;
  220. FontManager* m_fontManager;
  221. void setVertex(uint32_t _i, float _x, float _y, uint32_t _rgba, uint8_t _style = STYLE_NORMAL)
  222. {
  223. m_vertexBuffer[_i].x = _x;
  224. m_vertexBuffer[_i].y = _y;
  225. m_vertexBuffer[_i].rgba = _rgba;
  226. m_styleBuffer[_i] = _style;
  227. }
  228. void setOutlineColor(uint32_t _i, uint32_t _rgbaOutline)
  229. {
  230. m_vertexBuffer[_i].rgbaOutline = _rgbaOutline;
  231. }
  232. struct TextVertex
  233. {
  234. float x, y;
  235. int16_t u, v, w, t;
  236. int16_t u1, v1, w1, t1;
  237. int16_t u2, v2, w2, t2;
  238. uint32_t rgba;
  239. uint32_t rgbaOutline;
  240. };
  241. TextVertex* m_vertexBuffer;
  242. uint16_t* m_indexBuffer;
  243. uint8_t* m_styleBuffer;
  244. uint32_t m_indexCount;
  245. uint32_t m_lineStartIndex;
  246. uint16_t m_vertexCount;
  247. };
  248. TextBuffer::TextBuffer(FontManager* _fontManager)
  249. : m_styleFlags(STYLE_NORMAL)
  250. , m_textColor(0xffffffff)
  251. , m_backgroundColor(0xffffffff)
  252. , m_overlineColor(0xffffffff)
  253. , m_underlineColor(0xffffffff)
  254. , m_strikeThroughColor(0xffffffff)
  255. , m_outlineWidth(3.0f)
  256. , m_outlineColor(0x000000ff)
  257. , m_dropShadowColor(0x0000005a)
  258. , m_dropShadowSoftener(1.0f)
  259. , m_penX(0)
  260. , m_penY(0)
  261. , m_originX(0)
  262. , m_originY(0)
  263. , m_lineAscender(0)
  264. , m_lineDescender(0)
  265. , m_lineGap(0)
  266. , m_fontManager(_fontManager)
  267. , m_vertexBuffer(new TextVertex[MAX_BUFFERED_CHARACTERS * 4])
  268. , m_indexBuffer(new uint16_t[MAX_BUFFERED_CHARACTERS * 6])
  269. , m_styleBuffer(new uint8_t[MAX_BUFFERED_CHARACTERS * 4])
  270. , m_indexCount(0)
  271. , m_lineStartIndex(0)
  272. , m_vertexCount(0)
  273. , m_previousCodePoint(0)
  274. {
  275. m_rectangle.width = 0;
  276. m_rectangle.height = 0;
  277. m_dropShadowOffset[0] = 0.00f;
  278. m_dropShadowOffset[1] = 0.00f;
  279. }
  280. TextBuffer::~TextBuffer()
  281. {
  282. delete [] m_vertexBuffer;
  283. delete [] m_indexBuffer;
  284. delete [] m_styleBuffer;
  285. }
  286. void TextBuffer::appendText(FontHandle _fontHandle, const char* _string, const char* _end)
  287. {
  288. if (m_vertexCount == 0)
  289. {
  290. m_originX = m_penX;
  291. m_originY = m_penY;
  292. m_lineDescender = 0;
  293. m_lineAscender = 0;
  294. m_lineGap = 0;
  295. m_previousCodePoint = 0;
  296. }
  297. CodePoint codepoint = 0;
  298. uint32_t state = 0;
  299. if (_end == NULL)
  300. {
  301. _end = _string + bx::strLen(_string);
  302. }
  303. BX_ASSERT(_end >= _string);
  304. const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
  305. if (font.fontType & FONT_TYPE_MASK_DISTANCE_DROP_SHADOW)
  306. {
  307. float savePenX = m_penX;
  308. float savePenY = m_penY;
  309. CodePoint savePreviousCodePoint = m_previousCodePoint;
  310. TextRectangle saveRectangle = m_rectangle;
  311. const char* origString = _string;
  312. for (; *_string && _string < _end ; ++_string)
  313. {
  314. if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT )
  315. {
  316. appendGlyph(_fontHandle, codepoint, true);
  317. }
  318. }
  319. _string = origString;
  320. m_penX = savePenX;
  321. m_penY = savePenY;
  322. m_previousCodePoint = savePreviousCodePoint;
  323. m_rectangle = saveRectangle;
  324. }
  325. for (; *_string && _string < _end ; ++_string)
  326. {
  327. if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT )
  328. {
  329. appendGlyph(_fontHandle, codepoint, false);
  330. }
  331. }
  332. BX_ASSERT(state == UTF8_ACCEPT, "The string is not well-formed");
  333. }
  334. void TextBuffer::appendText(FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end)
  335. {
  336. if (m_vertexCount == 0)
  337. {
  338. m_originX = m_penX;
  339. m_originY = m_penY;
  340. m_lineDescender = 0;
  341. m_lineAscender = 0;
  342. m_lineGap = 0;
  343. m_previousCodePoint = 0;
  344. }
  345. if (_end == NULL)
  346. {
  347. _end = _string + wcslen(_string);
  348. }
  349. BX_ASSERT(_end >= _string);
  350. const FontInfo& font = m_fontManager->getFontInfo(_fontHandle);
  351. if (font.fontType & FONT_TYPE_MASK_DISTANCE_DROP_SHADOW)
  352. {
  353. float savePenX = m_penX;
  354. float savePenY = m_penY;
  355. CodePoint savePreviousCodePoint = m_previousCodePoint;
  356. TextRectangle saveRectangle = m_rectangle;
  357. for (const wchar_t* _current = _string; _current < _end; ++_current)
  358. {
  359. uint32_t _codePoint = *_current;
  360. appendGlyph(_fontHandle, _codePoint, true);
  361. }
  362. m_penX = savePenX;
  363. m_penY = savePenY;
  364. m_previousCodePoint = savePreviousCodePoint;
  365. m_rectangle = saveRectangle;
  366. }
  367. for (const wchar_t* _current = _string; _current < _end; ++_current)
  368. {
  369. uint32_t _codePoint = *_current;
  370. appendGlyph(_fontHandle, _codePoint, false);
  371. }
  372. }
  373. void TextBuffer::appendAtlasFace(uint16_t _faceIndex)
  374. {
  375. if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
  376. {
  377. return;
  378. }
  379. float x0 = m_penX;
  380. float y0 = m_penY;
  381. float x1 = x0 + (float)m_fontManager->getAtlas()->getTextureSize();
  382. float y1 = y0 + (float)m_fontManager->getAtlas()->getTextureSize();
  383. m_fontManager->getAtlas()->packFaceLayerUV(_faceIndex
  384. , (uint8_t*)m_vertexBuffer
  385. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  386. , sizeof(TextVertex)
  387. );
  388. setVertex(m_vertexCount + 0, x0, y0, m_backgroundColor);
  389. setVertex(m_vertexCount + 1, x0, y1, m_backgroundColor);
  390. setVertex(m_vertexCount + 2, x1, y1, m_backgroundColor);
  391. setVertex(m_vertexCount + 3, x1, y0, m_backgroundColor);
  392. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  393. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  394. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  395. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  396. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  397. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  398. m_vertexCount += 4;
  399. m_indexCount += 6;
  400. }
  401. void TextBuffer::clearTextBuffer()
  402. {
  403. m_penX = 0;
  404. m_penY = 0;
  405. m_originX = 0;
  406. m_originY = 0;
  407. m_vertexCount = 0;
  408. m_indexCount = 0;
  409. m_lineStartIndex = 0;
  410. m_lineAscender = 0;
  411. m_lineDescender = 0;
  412. m_lineGap = 0;
  413. m_previousCodePoint = 0;
  414. m_rectangle.width = 0;
  415. m_rectangle.height = 0;
  416. }
  417. void TextBuffer::appendGlyph(FontHandle _handle, CodePoint _codePoint, bool shadow)
  418. {
  419. if (_codePoint == L'\t')
  420. {
  421. for (uint32_t ii = 0; ii < 4; ++ii)
  422. {
  423. appendGlyph(_handle, L' ', shadow);
  424. }
  425. return;
  426. }
  427. const GlyphInfo* glyph = m_fontManager->getGlyphInfo(_handle, _codePoint);
  428. BX_WARN(NULL != glyph, "Glyph not found (font handle %d, code point %d)", _handle.idx, _codePoint);
  429. if (NULL == glyph)
  430. {
  431. m_previousCodePoint = 0;
  432. return;
  433. }
  434. if( m_vertexCount/4 >= MAX_BUFFERED_CHARACTERS)
  435. {
  436. m_previousCodePoint = 0;
  437. return;
  438. }
  439. const FontInfo& font = m_fontManager->getFontInfo(_handle);
  440. if (_codePoint == L'\n')
  441. {
  442. m_penX = m_originX;
  443. m_penY += m_lineGap + m_lineAscender -m_lineDescender;
  444. m_lineGap = font.lineGap;
  445. m_lineDescender = font.descender;
  446. m_lineAscender = font.ascender;
  447. m_lineStartIndex = m_vertexCount;
  448. m_previousCodePoint = 0;
  449. return;
  450. }
  451. //is there a change of font size that require the text on the left to be centered again ?
  452. if (font.ascender > m_lineAscender
  453. || (font.descender < m_lineDescender) )
  454. {
  455. if (font.descender < m_lineDescender)
  456. {
  457. m_lineDescender = font.descender;
  458. m_lineGap = font.lineGap;
  459. }
  460. float txtDecals = (font.ascender - m_lineAscender);
  461. m_lineAscender = font.ascender;
  462. m_lineGap = font.lineGap;
  463. verticalCenterLastLine( (txtDecals), (m_penY - m_lineAscender), (m_penY + m_lineAscender - m_lineDescender + m_lineGap) );
  464. }
  465. float kerning = m_fontManager->getKerning(_handle, m_previousCodePoint, _codePoint);
  466. m_penX += kerning;
  467. const GlyphInfo& blackGlyph = m_fontManager->getBlackGlyph();
  468. const Atlas* atlas = m_fontManager->getAtlas();
  469. const AtlasRegion& atlasRegion = atlas->getRegion(glyph->regionIndex);
  470. if (shadow)
  471. {
  472. if (atlasRegion.getType() != AtlasRegion::TYPE_BGRA8)
  473. {
  474. float extraXOffset = m_dropShadowOffset[0];
  475. float extraYOffset = m_dropShadowOffset[1];
  476. float x0 = m_penX + (glyph->offset_x) + extraXOffset;
  477. float y0 = (m_penY + m_lineAscender + (glyph->offset_y) + extraYOffset );
  478. float x1 = (x0 + glyph->width);
  479. float y1 = (y0 + glyph->height);
  480. bx::memSet(&m_vertexBuffer[m_vertexCount], 0, sizeof(TextVertex) * 4);
  481. atlas->packUV(glyph->regionIndex
  482. , (uint8_t*)m_vertexBuffer
  483. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u2)
  484. , sizeof(TextVertex)
  485. );
  486. uint32_t adjustedDropShadowColor = ((((m_dropShadowColor & 0xff000000) >> 8) * (m_textColor >> 24)) & 0xff000000) | (m_dropShadowColor & 0x00ffffff);
  487. setVertex(m_vertexCount + 0, x0, y0, adjustedDropShadowColor);
  488. setVertex(m_vertexCount + 1, x0, y1, adjustedDropShadowColor);
  489. setVertex(m_vertexCount + 2, x1, y1, adjustedDropShadowColor);
  490. setVertex(m_vertexCount + 3, x1, y0, adjustedDropShadowColor);
  491. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  492. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  493. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  494. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  495. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  496. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  497. m_vertexCount += 4;
  498. m_indexCount += 6;
  499. }
  500. m_penX += glyph->advance_x;
  501. if (m_penX > m_rectangle.width)
  502. {
  503. m_rectangle.width = m_penX;
  504. }
  505. if ( (m_penY +m_lineAscender - m_lineDescender+m_lineGap) > m_rectangle.height)
  506. {
  507. m_rectangle.height = (m_penY +m_lineAscender - m_lineDescender+m_lineGap);
  508. }
  509. m_previousCodePoint = _codePoint;
  510. return;
  511. }
  512. if (m_styleFlags & STYLE_BACKGROUND
  513. && m_backgroundColor & 0xff000000)
  514. {
  515. float x0 = (m_penX - kerning);
  516. float y0 = (m_penY);
  517. float x1 = ( (float)x0 + (glyph->advance_x) );
  518. float y1 = (m_penY + m_lineAscender - m_lineDescender + m_lineGap);
  519. atlas->packUV(blackGlyph.regionIndex
  520. , (uint8_t*)m_vertexBuffer
  521. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  522. , sizeof(TextVertex)
  523. );
  524. const uint16_t vertexCount = m_vertexCount;
  525. setVertex(vertexCount + 0, x0, y0, m_backgroundColor, STYLE_BACKGROUND);
  526. setVertex(vertexCount + 1, x0, y1, m_backgroundColor, STYLE_BACKGROUND);
  527. setVertex(vertexCount + 2, x1, y1, m_backgroundColor, STYLE_BACKGROUND);
  528. setVertex(vertexCount + 3, x1, y0, m_backgroundColor, STYLE_BACKGROUND);
  529. m_indexBuffer[m_indexCount + 0] = vertexCount + 0;
  530. m_indexBuffer[m_indexCount + 1] = vertexCount + 1;
  531. m_indexBuffer[m_indexCount + 2] = vertexCount + 2;
  532. m_indexBuffer[m_indexCount + 3] = vertexCount + 0;
  533. m_indexBuffer[m_indexCount + 4] = vertexCount + 2;
  534. m_indexBuffer[m_indexCount + 5] = vertexCount + 3;
  535. m_vertexCount += 4;
  536. m_indexCount += 6;
  537. }
  538. if (m_styleFlags & STYLE_UNDERLINE
  539. && m_underlineColor & 0xFF000000)
  540. {
  541. float x0 = (m_penX - kerning);
  542. float y0 = (m_penY + m_lineAscender - m_lineDescender * 0.5f);
  543. float x1 = ( (float)x0 + (glyph->advance_x) );
  544. float y1 = y0 + font.underlineThickness;
  545. atlas->packUV(blackGlyph.regionIndex
  546. , (uint8_t*)m_vertexBuffer
  547. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  548. , sizeof(TextVertex)
  549. );
  550. setVertex(m_vertexCount + 0, x0, y0, m_underlineColor, STYLE_UNDERLINE);
  551. setVertex(m_vertexCount + 1, x0, y1, m_underlineColor, STYLE_UNDERLINE);
  552. setVertex(m_vertexCount + 2, x1, y1, m_underlineColor, STYLE_UNDERLINE);
  553. setVertex(m_vertexCount + 3, x1, y0, m_underlineColor, STYLE_UNDERLINE);
  554. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  555. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  556. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  557. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  558. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  559. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  560. m_vertexCount += 4;
  561. m_indexCount += 6;
  562. }
  563. if (m_styleFlags & STYLE_OVERLINE
  564. && m_overlineColor & 0xFF000000)
  565. {
  566. float x0 = (m_penX - kerning);
  567. float y0 = (m_penY);
  568. float x1 = ( (float)x0 + (glyph->advance_x) );
  569. float y1 = y0 + font.underlineThickness;
  570. m_fontManager->getAtlas()->packUV(blackGlyph.regionIndex
  571. , (uint8_t*)m_vertexBuffer
  572. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  573. , sizeof(TextVertex)
  574. );
  575. setVertex(m_vertexCount + 0, x0, y0, m_overlineColor, STYLE_OVERLINE);
  576. setVertex(m_vertexCount + 1, x0, y1, m_overlineColor, STYLE_OVERLINE);
  577. setVertex(m_vertexCount + 2, x1, y1, m_overlineColor, STYLE_OVERLINE);
  578. setVertex(m_vertexCount + 3, x1, y0, m_overlineColor, STYLE_OVERLINE);
  579. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  580. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  581. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  582. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  583. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  584. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  585. m_vertexCount += 4;
  586. m_indexCount += 6;
  587. }
  588. if (m_styleFlags & STYLE_STRIKE_THROUGH
  589. && m_strikeThroughColor & 0xFF000000)
  590. {
  591. float x0 = (m_penX - kerning);
  592. float y0 = (m_penY + 0.666667f * font.ascender);
  593. float x1 = ( (float)x0 + (glyph->advance_x) );
  594. float y1 = y0 + font.underlineThickness;
  595. atlas->packUV(blackGlyph.regionIndex
  596. , (uint8_t*)m_vertexBuffer
  597. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  598. , sizeof(TextVertex)
  599. );
  600. setVertex(m_vertexCount + 0, x0, y0, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  601. setVertex(m_vertexCount + 1, x0, y1, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  602. setVertex(m_vertexCount + 2, x1, y1, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  603. setVertex(m_vertexCount + 3, x1, y0, m_strikeThroughColor, STYLE_STRIKE_THROUGH);
  604. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  605. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  606. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  607. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  608. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  609. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  610. m_vertexCount += 4;
  611. m_indexCount += 6;
  612. }
  613. if (!shadow && atlasRegion.getType() == AtlasRegion::TYPE_BGRA8)
  614. {
  615. bx::memSet(&m_vertexBuffer[m_vertexCount], 0, sizeof(TextVertex) * 4);
  616. atlas->packUV(glyph->regionIndex
  617. , (uint8_t*)m_vertexBuffer
  618. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u1)
  619. , sizeof(TextVertex)
  620. );
  621. float glyphScale = glyph->bitmapScale;
  622. float glyphWidth = glyph->width * glyphScale;
  623. float glyphHeight = glyph->height * glyphScale;
  624. float x0 = m_penX + (glyph->offset_x);
  625. float y0 = (m_penY + (font.ascender + -font.descender - glyphHeight) / 2);
  626. float x1 = (x0 + glyphWidth);
  627. float y1 = (y0 + glyphHeight);
  628. setVertex(m_vertexCount + 0, x0, y0, m_textColor);
  629. setVertex(m_vertexCount + 1, x0, y1, m_textColor);
  630. setVertex(m_vertexCount + 2, x1, y1, m_textColor);
  631. setVertex(m_vertexCount + 3, x1, y0, m_textColor);
  632. }
  633. else if (!shadow)
  634. {
  635. bx::memSet(&m_vertexBuffer[m_vertexCount], 0, sizeof(TextVertex) * 4);
  636. atlas->packUV(glyph->regionIndex
  637. , (uint8_t*)m_vertexBuffer
  638. , sizeof(TextVertex) * m_vertexCount + offsetof(TextVertex, u)
  639. , sizeof(TextVertex)
  640. );
  641. float x0 = m_penX + (glyph->offset_x);
  642. float y0 = (m_penY + m_lineAscender + (glyph->offset_y) );
  643. float x1 = (x0 + glyph->width);
  644. float y1 = (y0 + glyph->height);
  645. setVertex(m_vertexCount + 0, x0, y0, m_textColor);
  646. setVertex(m_vertexCount + 1, x0, y1, m_textColor);
  647. setVertex(m_vertexCount + 2, x1, y1, m_textColor);
  648. setVertex(m_vertexCount + 3, x1, y0, m_textColor);
  649. setOutlineColor(m_vertexCount + 0, m_outlineColor);
  650. setOutlineColor(m_vertexCount + 1, m_outlineColor);
  651. setOutlineColor(m_vertexCount + 2, m_outlineColor);
  652. setOutlineColor(m_vertexCount + 3, m_outlineColor);
  653. }
  654. m_indexBuffer[m_indexCount + 0] = m_vertexCount + 0;
  655. m_indexBuffer[m_indexCount + 1] = m_vertexCount + 1;
  656. m_indexBuffer[m_indexCount + 2] = m_vertexCount + 2;
  657. m_indexBuffer[m_indexCount + 3] = m_vertexCount + 0;
  658. m_indexBuffer[m_indexCount + 4] = m_vertexCount + 2;
  659. m_indexBuffer[m_indexCount + 5] = m_vertexCount + 3;
  660. m_vertexCount += 4;
  661. m_indexCount += 6;
  662. m_penX += glyph->advance_x;
  663. if (m_penX > m_rectangle.width)
  664. {
  665. m_rectangle.width = m_penX;
  666. }
  667. if ( (m_penY +m_lineAscender - m_lineDescender+m_lineGap) > m_rectangle.height)
  668. {
  669. m_rectangle.height = (m_penY +m_lineAscender - m_lineDescender+m_lineGap);
  670. }
  671. m_previousCodePoint = _codePoint;
  672. }
  673. void TextBuffer::verticalCenterLastLine(float _dy, float _top, float _bottom)
  674. {
  675. for (uint32_t ii = m_lineStartIndex; ii < m_vertexCount; ii += 4)
  676. {
  677. if (m_styleBuffer[ii] == STYLE_BACKGROUND)
  678. {
  679. m_vertexBuffer[ii + 0].y = _top;
  680. m_vertexBuffer[ii + 1].y = _bottom;
  681. m_vertexBuffer[ii + 2].y = _bottom;
  682. m_vertexBuffer[ii + 3].y = _top;
  683. }
  684. else
  685. {
  686. m_vertexBuffer[ii + 0].y += _dy;
  687. m_vertexBuffer[ii + 1].y += _dy;
  688. m_vertexBuffer[ii + 2].y += _dy;
  689. m_vertexBuffer[ii + 3].y += _dy;
  690. }
  691. }
  692. }
  693. TextBufferManager::TextBufferManager(FontManager* _fontManager)
  694. : m_fontManager(_fontManager)
  695. {
  696. m_textBuffers = new BufferCache[MAX_TEXT_BUFFER_COUNT];
  697. bgfx::RendererType::Enum type = bgfx::getRendererType();
  698. m_basicProgram = bgfx::createProgram(
  699. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_basic")
  700. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_basic")
  701. , true
  702. );
  703. m_distanceProgram = bgfx::createProgram(
  704. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field")
  705. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field")
  706. , true
  707. );
  708. m_distanceSubpixelProgram = bgfx::createProgram(
  709. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_subpixel")
  710. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_subpixel")
  711. , true
  712. );
  713. m_distanceDropShadowProgram = bgfx::createProgram(
  714. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_drop_shadow")
  715. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_drop_shadow")
  716. , true
  717. );
  718. m_distanceDropShadowImageProgram = bgfx::createProgram(
  719. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_drop_shadow_image")
  720. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_drop_shadow_image")
  721. , true
  722. );
  723. m_distanceOutlineProgram = bgfx::createProgram(
  724. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_outline")
  725. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_outline")
  726. , true
  727. );
  728. m_distanceOutlineImageProgram = bgfx::createProgram(
  729. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_outline_image")
  730. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_outline_image")
  731. , true
  732. );
  733. m_distanceOutlineDropShadowImageProgram = bgfx::createProgram(
  734. bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_font_distance_field_outline_drop_shadow_image")
  735. , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_font_distance_field_outline_drop_shadow_image")
  736. , true
  737. );
  738. m_vertexLayout
  739. .begin()
  740. .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float)
  741. .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Int16, true)
  742. .add(bgfx::Attrib::TexCoord1, 4, bgfx::AttribType::Int16, true)
  743. .add(bgfx::Attrib::TexCoord2, 4, bgfx::AttribType::Int16, true)
  744. .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
  745. .add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8, true)
  746. .end();
  747. s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler);
  748. u_dropShadowColor = bgfx::createUniform("u_dropShadowColor", bgfx::UniformType::Vec4);
  749. u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4);
  750. }
  751. TextBufferManager::~TextBufferManager()
  752. {
  753. BX_ASSERT(m_textBufferHandles.getNumHandles() == 0, "All the text buffers must be destroyed before destroying the manager");
  754. delete [] m_textBuffers;
  755. bgfx::destroy(u_params);
  756. bgfx::destroy(u_dropShadowColor);
  757. bgfx::destroy(s_texColor);
  758. bgfx::destroy(m_basicProgram);
  759. bgfx::destroy(m_distanceProgram);
  760. bgfx::destroy(m_distanceSubpixelProgram);
  761. bgfx::destroy(m_distanceOutlineProgram);
  762. bgfx::destroy(m_distanceOutlineImageProgram);
  763. bgfx::destroy(m_distanceDropShadowProgram);
  764. bgfx::destroy(m_distanceDropShadowImageProgram);
  765. bgfx::destroy(m_distanceOutlineDropShadowImageProgram);
  766. }
  767. TextBufferHandle TextBufferManager::createTextBuffer(uint32_t _type, BufferType::Enum _bufferType)
  768. {
  769. uint16_t textIdx = m_textBufferHandles.alloc();
  770. BufferCache& bc = m_textBuffers[textIdx];
  771. bc.textBuffer = new TextBuffer(m_fontManager);
  772. bc.fontType = _type;
  773. bc.bufferType = _bufferType;
  774. bc.indexBufferHandleIdx = bgfx::kInvalidHandle;
  775. bc.vertexBufferHandleIdx = bgfx::kInvalidHandle;
  776. TextBufferHandle ret = {textIdx};
  777. return ret;
  778. }
  779. void TextBufferManager::destroyTextBuffer(TextBufferHandle _handle)
  780. {
  781. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  782. BufferCache& bc = m_textBuffers[_handle.idx];
  783. m_textBufferHandles.free(_handle.idx);
  784. delete bc.textBuffer;
  785. bc.textBuffer = NULL;
  786. if (bc.vertexBufferHandleIdx == bgfx::kInvalidHandle)
  787. {
  788. return;
  789. }
  790. switch (bc.bufferType)
  791. {
  792. case BufferType::Static:
  793. {
  794. bgfx::IndexBufferHandle ibh;
  795. bgfx::VertexBufferHandle vbh;
  796. ibh.idx = bc.indexBufferHandleIdx;
  797. vbh.idx = bc.vertexBufferHandleIdx;
  798. bgfx::destroy(ibh);
  799. bgfx::destroy(vbh);
  800. }
  801. break;
  802. case BufferType::Dynamic:
  803. bgfx::DynamicIndexBufferHandle ibh;
  804. bgfx::DynamicVertexBufferHandle vbh;
  805. ibh.idx = bc.indexBufferHandleIdx;
  806. vbh.idx = bc.vertexBufferHandleIdx;
  807. bgfx::destroy(ibh);
  808. bgfx::destroy(vbh);
  809. break;
  810. case BufferType::Transient: // destroyed every frame
  811. break;
  812. }
  813. }
  814. void TextBufferManager::submitTextBuffer(TextBufferHandle _handle, bgfx::ViewId _id, int32_t _depth)
  815. {
  816. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  817. BufferCache& bc = m_textBuffers[_handle.idx];
  818. uint32_t indexSize = bc.textBuffer->getIndexCount() * bc.textBuffer->getIndexSize();
  819. uint32_t vertexSize = bc.textBuffer->getVertexCount() * bc.textBuffer->getVertexSize();
  820. if (0 == indexSize || 0 == vertexSize)
  821. {
  822. return;
  823. }
  824. bgfx::setTexture(0, s_texColor, m_fontManager->getAtlas()->getTextureHandle() );
  825. bgfx::ProgramHandle program = BGFX_INVALID_HANDLE;
  826. switch (bc.fontType)
  827. {
  828. case FONT_TYPE_ALPHA:
  829. program = m_basicProgram;
  830. bgfx::setState(0
  831. | BGFX_STATE_WRITE_RGB
  832. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  833. );
  834. break;
  835. case FONT_TYPE_DISTANCE:
  836. {
  837. program = m_distanceProgram;
  838. bgfx::setState(0
  839. | BGFX_STATE_WRITE_RGB
  840. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  841. );
  842. float params[4] = { 0.0f, (float)m_fontManager->getAtlas()->getTextureSize() / 512.0f, 0.0f, 0.0f };
  843. bgfx::setUniform(u_params, &params);
  844. break;
  845. }
  846. case FONT_TYPE_DISTANCE_SUBPIXEL:
  847. program = m_distanceSubpixelProgram;
  848. bgfx::setState(0
  849. | BGFX_STATE_WRITE_RGB
  850. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_INV_SRC_COLOR)
  851. , bc.textBuffer->getTextColor()
  852. );
  853. break;
  854. case FONT_TYPE_DISTANCE_OUTLINE:
  855. {
  856. program = m_distanceOutlineProgram;
  857. bgfx::setState(0
  858. | BGFX_STATE_WRITE_RGB
  859. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  860. );
  861. float params[4] = { 0.0f, (float)m_fontManager->getAtlas()->getTextureSize() / 512.0f, 0.0f, bc.textBuffer->getOutlineWidth() };
  862. bgfx::setUniform(u_params, &params);
  863. break;
  864. }
  865. case FONT_TYPE_DISTANCE_OUTLINE_IMAGE:
  866. {
  867. program = m_distanceOutlineImageProgram;
  868. bgfx::setState(0
  869. | BGFX_STATE_WRITE_RGB
  870. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  871. );
  872. float params[4] = { 0.0f, (float)m_fontManager->getAtlas()->getTextureSize() / 512.0f, 0.0f, bc.textBuffer->getOutlineWidth() };
  873. bgfx::setUniform(u_params, &params);
  874. break;
  875. }
  876. case FONT_TYPE_DISTANCE_DROP_SHADOW:
  877. {
  878. program = m_distanceDropShadowProgram;
  879. bgfx::setState(0
  880. | BGFX_STATE_WRITE_RGB
  881. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  882. );
  883. uint32_t dropShadowColor = bc.textBuffer->getDropShadowColor();
  884. float dropShadowColorVec[4] = { ((dropShadowColor >> 16) & 0xff) / 255.0f, ((dropShadowColor >> 8) & 0xff) / 255.0f, (dropShadowColor & 0xff) / 255.0f, (dropShadowColor >> 24) / 255.0f };
  885. bgfx::setUniform(u_dropShadowColor, &dropShadowColorVec);
  886. float params[4] = { 0.0f, (float)m_fontManager->getAtlas()->getTextureSize() / 512.0f, bc.textBuffer->getDropShadowSoftener(), 0.0 };
  887. bgfx::setUniform(u_params, &params);
  888. break;
  889. }
  890. case FONT_TYPE_DISTANCE_DROP_SHADOW_IMAGE:
  891. {
  892. program = m_distanceDropShadowImageProgram;
  893. bgfx::setState(0
  894. | BGFX_STATE_WRITE_RGB
  895. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  896. );
  897. uint32_t dropShadowColor = bc.textBuffer->getDropShadowColor();
  898. float dropShadowColorVec[4] = { ((dropShadowColor >> 16) & 0xff) / 255.0f, ((dropShadowColor >> 8) & 0xff) / 255.0f, (dropShadowColor & 0xff) / 255.0f, (dropShadowColor >> 24) / 255.0f };
  899. bgfx::setUniform(u_dropShadowColor, &dropShadowColorVec);
  900. float params[4] = { 0.0f, (float)m_fontManager->getAtlas()->getTextureSize() / 512.0f, bc.textBuffer->getDropShadowSoftener(), 0.0 };
  901. bgfx::setUniform(u_params, &params);
  902. break;
  903. }
  904. case FONT_TYPE_DISTANCE_OUTLINE_DROP_SHADOW_IMAGE:
  905. {
  906. program = m_distanceOutlineDropShadowImageProgram;
  907. bgfx::setState(0
  908. | BGFX_STATE_WRITE_RGB
  909. | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
  910. );
  911. uint32_t dropShadowColor = bc.textBuffer->getDropShadowColor();
  912. float dropShadowColorVec[4] = { ((dropShadowColor >> 16) & 0xff) / 255.0f, ((dropShadowColor >> 8) & 0xff) / 255.0f, (dropShadowColor & 0xff) / 255.0f, (dropShadowColor >> 24) / 255.0f };
  913. bgfx::setUniform(u_dropShadowColor, &dropShadowColorVec);
  914. float params[4] = { 0.0f, (float)m_fontManager->getAtlas()->getTextureSize() / 512.0f, bc.textBuffer->getDropShadowSoftener(), bc.textBuffer->getOutlineWidth() };
  915. bgfx::setUniform(u_params, &params);
  916. break;
  917. }
  918. }
  919. switch (bc.bufferType)
  920. {
  921. case BufferType::Static:
  922. {
  923. bgfx::IndexBufferHandle ibh;
  924. bgfx::VertexBufferHandle vbh;
  925. if (bgfx::kInvalidHandle == bc.vertexBufferHandleIdx)
  926. {
  927. ibh = bgfx::createIndexBuffer(
  928. bgfx::copy(bc.textBuffer->getIndexBuffer(), indexSize)
  929. );
  930. vbh = bgfx::createVertexBuffer(
  931. bgfx::copy(bc.textBuffer->getVertexBuffer(), vertexSize)
  932. , m_vertexLayout
  933. );
  934. bc.vertexBufferHandleIdx = vbh.idx;
  935. bc.indexBufferHandleIdx = ibh.idx;
  936. }
  937. else
  938. {
  939. vbh.idx = bc.vertexBufferHandleIdx;
  940. ibh.idx = bc.indexBufferHandleIdx;
  941. }
  942. bgfx::setVertexBuffer(0, vbh, 0, bc.textBuffer->getVertexCount() );
  943. bgfx::setIndexBuffer(ibh, 0, bc.textBuffer->getIndexCount() );
  944. }
  945. break;
  946. case BufferType::Dynamic:
  947. {
  948. bgfx::DynamicIndexBufferHandle ibh;
  949. bgfx::DynamicVertexBufferHandle vbh;
  950. if (bgfx::kInvalidHandle == bc.vertexBufferHandleIdx )
  951. {
  952. ibh = bgfx::createDynamicIndexBuffer(
  953. bgfx::copy(bc.textBuffer->getIndexBuffer(), indexSize)
  954. );
  955. vbh = bgfx::createDynamicVertexBuffer(
  956. bgfx::copy(bc.textBuffer->getVertexBuffer(), vertexSize)
  957. , m_vertexLayout
  958. );
  959. bc.indexBufferHandleIdx = ibh.idx;
  960. bc.vertexBufferHandleIdx = vbh.idx;
  961. }
  962. else
  963. {
  964. ibh.idx = bc.indexBufferHandleIdx;
  965. vbh.idx = bc.vertexBufferHandleIdx;
  966. bgfx::update(
  967. ibh
  968. , 0
  969. , bgfx::copy(bc.textBuffer->getIndexBuffer(), indexSize)
  970. );
  971. bgfx::update(
  972. vbh
  973. , 0
  974. , bgfx::copy(bc.textBuffer->getVertexBuffer(), vertexSize)
  975. );
  976. }
  977. bgfx::setVertexBuffer(0, vbh, 0, bc.textBuffer->getVertexCount() );
  978. bgfx::setIndexBuffer(ibh, 0, bc.textBuffer->getIndexCount() );
  979. }
  980. break;
  981. case BufferType::Transient:
  982. {
  983. bgfx::TransientIndexBuffer tib;
  984. bgfx::TransientVertexBuffer tvb;
  985. bgfx::allocTransientIndexBuffer(&tib, bc.textBuffer->getIndexCount() );
  986. bgfx::allocTransientVertexBuffer(&tvb, bc.textBuffer->getVertexCount(), m_vertexLayout);
  987. bx::memCopy(tib.data, bc.textBuffer->getIndexBuffer(), indexSize);
  988. bx::memCopy(tvb.data, bc.textBuffer->getVertexBuffer(), vertexSize);
  989. bgfx::setVertexBuffer(0, &tvb, 0, bc.textBuffer->getVertexCount() );
  990. bgfx::setIndexBuffer(&tib, 0, bc.textBuffer->getIndexCount() );
  991. }
  992. break;
  993. }
  994. bgfx::submit(_id, program, _depth);
  995. }
  996. void TextBufferManager::setStyle(TextBufferHandle _handle, uint32_t _flags)
  997. {
  998. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  999. BufferCache& bc = m_textBuffers[_handle.idx];
  1000. bc.textBuffer->setStyle(_flags);
  1001. }
  1002. void TextBufferManager::setTextColor(TextBufferHandle _handle, uint32_t _rgba)
  1003. {
  1004. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1005. BufferCache& bc = m_textBuffers[_handle.idx];
  1006. bc.textBuffer->setTextColor(_rgba);
  1007. }
  1008. void TextBufferManager::setBackgroundColor(TextBufferHandle _handle, uint32_t _rgba)
  1009. {
  1010. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1011. BufferCache& bc = m_textBuffers[_handle.idx];
  1012. bc.textBuffer->setBackgroundColor(_rgba);
  1013. }
  1014. void TextBufferManager::setOverlineColor(TextBufferHandle _handle, uint32_t _rgba)
  1015. {
  1016. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1017. BufferCache& bc = m_textBuffers[_handle.idx];
  1018. bc.textBuffer->setOverlineColor(_rgba);
  1019. }
  1020. void TextBufferManager::setUnderlineColor(TextBufferHandle _handle, uint32_t _rgba)
  1021. {
  1022. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1023. BufferCache& bc = m_textBuffers[_handle.idx];
  1024. bc.textBuffer->setUnderlineColor(_rgba);
  1025. }
  1026. void TextBufferManager::setStrikeThroughColor(TextBufferHandle _handle, uint32_t _rgba)
  1027. {
  1028. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1029. BufferCache& bc = m_textBuffers[_handle.idx];
  1030. bc.textBuffer->setStrikeThroughColor(_rgba);
  1031. }
  1032. void TextBufferManager::setOutlineColor(TextBufferHandle _handle, uint32_t _rgba)
  1033. {
  1034. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1035. BufferCache& bc = m_textBuffers[_handle.idx];
  1036. bc.textBuffer->setOutlineColor(_rgba);
  1037. }
  1038. void TextBufferManager::setOutlineWidth(TextBufferHandle _handle, float _outlineWidth)
  1039. {
  1040. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1041. BufferCache& bc = m_textBuffers[_handle.idx];
  1042. bc.textBuffer->setOutlineWidth(_outlineWidth);
  1043. }
  1044. void TextBufferManager::setDropShadowColor(TextBufferHandle _handle, uint32_t _rgba)
  1045. {
  1046. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1047. BufferCache& bc = m_textBuffers[_handle.idx];
  1048. bc.textBuffer->setDropShadowColor(_rgba);
  1049. }
  1050. void TextBufferManager::setDropShadowOffset(TextBufferHandle _handle, float _u, float _v)
  1051. {
  1052. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1053. BufferCache& bc = m_textBuffers[_handle.idx];
  1054. bc.textBuffer->setDropShadowOffset(_u, _v);
  1055. }
  1056. void TextBufferManager::setDropShadowSoftener(TextBufferHandle _handle, float smoother)
  1057. {
  1058. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1059. BufferCache& bc = m_textBuffers[_handle.idx];
  1060. bc.textBuffer->setDropShadowSoftener(smoother);
  1061. }
  1062. void TextBufferManager::setPenPosition(TextBufferHandle _handle, float _x, float _y)
  1063. {
  1064. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1065. BufferCache& bc = m_textBuffers[_handle.idx];
  1066. bc.textBuffer->setPenPosition(_x, _y);
  1067. }
  1068. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const char* _string, const char* _end)
  1069. {
  1070. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1071. BufferCache& bc = m_textBuffers[_handle.idx];
  1072. bc.textBuffer->appendText(_fontHandle, _string, _end);
  1073. }
  1074. void TextBufferManager::appendText(TextBufferHandle _handle, FontHandle _fontHandle, const wchar_t* _string, const wchar_t* _end)
  1075. {
  1076. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1077. BufferCache& bc = m_textBuffers[_handle.idx];
  1078. bc.textBuffer->appendText(_fontHandle, _string, _end);
  1079. }
  1080. void TextBufferManager::appendAtlasFace(TextBufferHandle _handle, uint16_t _faceIndex)
  1081. {
  1082. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1083. BufferCache& bc = m_textBuffers[_handle.idx];
  1084. bc.textBuffer->appendAtlasFace(_faceIndex);
  1085. }
  1086. void TextBufferManager::clearTextBuffer(TextBufferHandle _handle)
  1087. {
  1088. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1089. BufferCache& bc = m_textBuffers[_handle.idx];
  1090. bc.textBuffer->clearTextBuffer();
  1091. }
  1092. TextRectangle TextBufferManager::getRectangle(TextBufferHandle _handle) const
  1093. {
  1094. BX_ASSERT(bgfx::isValid(_handle), "Invalid handle used");
  1095. BufferCache& bc = m_textBuffers[_handle.idx];
  1096. return bc.textBuffer->getRectangle();
  1097. }