Font.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. * Font.cpp
  3. */
  4. #include "Base.h"
  5. #include "Font.h"
  6. #include "Game.h"
  7. #include "FileSystem.h"
  8. #include "Package.h"
  9. // Default font vertex shader
  10. #define FONT_VSH \
  11. "uniform mat4 sb_projection_matrix;" \
  12. "attribute vec3 a_position;" \
  13. "attribute vec2 a_texcoord;" \
  14. "attribute vec4 a_color;" \
  15. "varying vec2 vtexcoord;" \
  16. "varying vec4 vcolor;" \
  17. "void main()" \
  18. "{" \
  19. "gl_Position = sb_projection_matrix * vec4(a_position, 1);" \
  20. "vtexcoord = a_texcoord;" \
  21. "vcolor = a_color;" \
  22. "}"
  23. // Default font fragment shader
  24. #define FONT_FSH \
  25. "precision mediump float;" \
  26. "varying vec2 vtexcoord;" \
  27. "varying vec4 vcolor;" \
  28. "uniform sampler2D texture;" \
  29. "void main()" \
  30. "{" \
  31. "gl_FragColor = vcolor;" \
  32. "gl_FragColor.a = texture2D(texture, vtexcoord).a;" \
  33. "}"
  34. namespace gameplay
  35. {
  36. static std::vector<Font*> __fontCache;
  37. static Effect* __fontEffect = NULL;
  38. Font::Font() :
  39. _style(PLAIN), _size(0), _glyphs(NULL), _glyphCount(0), _texture(NULL), _batch(NULL)
  40. {
  41. }
  42. Font::Font(const Font& copy)
  43. {
  44. // hidden
  45. }
  46. Font::~Font()
  47. {
  48. // Remove this Font from the font cache.
  49. std::vector<Font*>::iterator itr = find(__fontCache.begin(), __fontCache.end(), this);
  50. if (itr != __fontCache.end())
  51. {
  52. __fontCache.erase(itr);
  53. }
  54. SAFE_DELETE(_batch);
  55. SAFE_DELETE_ARRAY(_glyphs);
  56. SAFE_RELEASE(_texture);
  57. }
  58. Font* Font::create(const char* path, const char* id)
  59. {
  60. // Search the font cache for a font with the given path and ID.
  61. for (unsigned int i = 0, count = __fontCache.size(); i < count; ++i)
  62. {
  63. Font* f = __fontCache[i];
  64. if (f->_path == path && (id == NULL || f->_id == id))
  65. {
  66. // Found a match.
  67. f->addRef();
  68. return f;
  69. }
  70. }
  71. // Load the package.
  72. Package* pkg = Package::create(path);
  73. if (pkg == NULL)
  74. {
  75. return NULL;
  76. }
  77. Font* font = NULL;
  78. if (id == NULL)
  79. {
  80. // Get the ID of the first/only object in the package (assume it's a Font).
  81. const char* id;
  82. if (pkg->getObjectCount() != 1 || (id = pkg->getObjectID(0)) == NULL)
  83. {
  84. return NULL;
  85. }
  86. // Load the font using the ID of the first object in the package.
  87. font = pkg->loadFont(pkg->getObjectID(0));
  88. }
  89. else
  90. {
  91. // Load the font with the given ID.
  92. font = pkg->loadFont(id);
  93. }
  94. if (font)
  95. {
  96. // Add this font to the cache.
  97. __fontCache.push_back(font);
  98. }
  99. SAFE_RELEASE(pkg);
  100. return font;
  101. }
  102. Font* Font::create(const char* family, Style style, unsigned int size, Glyph* glyphs, int glyphCount, Texture* texture)
  103. {
  104. // Create the effect for the font's sprite batch.
  105. if (__fontEffect == NULL)
  106. {
  107. __fontEffect = Effect::createFromSource(FONT_VSH, FONT_FSH);
  108. if (__fontEffect == NULL)
  109. {
  110. LOG_ERROR("Failed to create effect for font.");
  111. SAFE_RELEASE(texture);
  112. return NULL;
  113. }
  114. }
  115. else
  116. {
  117. __fontEffect->addRef();
  118. }
  119. // Create batch for the font.
  120. SpriteBatch* batch = SpriteBatch::create(texture, __fontEffect, 128);
  121. // Release __fontEffect since the SpriteBatch keeps a reference to it
  122. SAFE_RELEASE(__fontEffect);
  123. if (batch == NULL)
  124. {
  125. LOG_ERROR("Failed to create batch for font.");
  126. return NULL;
  127. }
  128. // Increase the ref count of the texture to retain it.
  129. texture->addRef();
  130. Font* font = new Font();
  131. font->_family = family;
  132. font->_style = style;
  133. font->_size = size;
  134. font->_texture = texture;
  135. font->_batch = batch;
  136. // Copy the glyphs array.
  137. font->_glyphs = new Glyph[glyphCount];
  138. memcpy(font->_glyphs, glyphs, sizeof(Glyph) * glyphCount);
  139. font->_glyphCount = glyphCount;
  140. return font;
  141. }
  142. void Font::begin()
  143. {
  144. _batch->begin();
  145. }
  146. void Font::drawText(const char* text, int x, int y, const Vector4& color)
  147. {
  148. const int length = strlen(text);
  149. int xPos = x, yPos = y;
  150. for (int i = 0; i < length; ++i)
  151. {
  152. char c = text[i];
  153. unsigned int index = c - 32; // HACK for ASCII
  154. if (index >= 0 && index < _glyphCount)
  155. {
  156. Glyph& g = _glyphs[index];
  157. // Draw this character.
  158. switch (c)
  159. {
  160. case ' ':
  161. xPos += _size>>1;
  162. break;
  163. case '\r':
  164. case '\n':
  165. yPos += _size;
  166. xPos = x;
  167. break;
  168. case '\t':
  169. xPos += (_size>>1)+4;
  170. break;
  171. default:
  172. _batch->draw(xPos, yPos, g.width, _size, g.uvs[0], g.uvs[1], g.uvs[2], g.uvs[3], color);
  173. xPos += g.width + (_size>>3);
  174. break;
  175. }
  176. }
  177. }
  178. }
  179. void Font::end()
  180. {
  181. _batch->end();
  182. }
  183. }