Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TextRenderer.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "precompiled.h"
19 
20 #include "TextRenderer.h"
21 
22 #include "lib/ogl.h"
24 #include "ps/CStrIntern.h"
25 #include "ps/Font.h"
26 
27 extern int g_xres, g_yres;
28 
30  m_Shader(shader)
31 {
33  Color(CColor(1.0f, 1.0f, 1.0f, 1.0f));
34  Font(L"sans-10");
35 }
36 
38 {
40  m_Transform.Scale(1.0f, -1.f, 1.0f);
41  m_Transform.Translate(0.0f, (float)g_yres, -1000.0f);
42 
43  CMatrix3D proj;
44  proj.SetOrtho(0.f, (float)g_xres, 0.f, (float)g_yres, -1.f, 1000.f);
45  m_Transform = proj * m_Transform;
46 }
47 
49 {
50  return m_Transform;
51 }
52 
53 void CTextRenderer::SetTransform(const CMatrix3D& transform)
54 {
55  m_Transform = transform;
56 }
57 
58 void CTextRenderer::Translate(float x, float y, float z)
59 {
60  CMatrix3D m;
61  m.SetTranslation(x, y, z);
63 }
64 
65 void CTextRenderer::Color(const CColor& color)
66 {
67  m_Color = color;
68 }
69 
70 void CTextRenderer::Color(float r, float g, float b, float a)
71 {
72  m_Color = CColor(r, g, b, a);
73 }
74 
75 void CTextRenderer::Font(const CStrW& font)
76 {
77  if (!m_Fonts[font])
78  m_Fonts[font] = shared_ptr<CFont>(new CFont(font));
79 
80  m_Font = m_Fonts[font];
81 }
82 
83 void CTextRenderer::PrintfAdvance(const wchar_t* fmt, ...)
84 {
85  wchar_t buf[1024] = {0};
86 
87  va_list args;
88  va_start(args, fmt);
89  int ret = vswprintf(buf, ARRAY_SIZE(buf)-1, fmt, args);
90  va_end(args);
91 
92  if (ret < 0)
93  debug_printf(L"CTextRenderer::Printf vswprintf failed (buffer size exceeded?) - return value %d, errno %d\n", ret, errno);
94 
95  PutAdvance(buf);
96 }
97 
98 
99 void CTextRenderer::PrintfAt(float x, float y, const wchar_t* fmt, ...)
100 {
101  wchar_t buf[1024] = {0};
102 
103  va_list args;
104  va_start(args, fmt);
105  int ret = vswprintf(buf, ARRAY_SIZE(buf)-1, fmt, args);
106  va_end(args);
107 
108  if (ret < 0)
109  debug_printf(L"CTextRenderer::PrintfAt vswprintf failed (buffer size exceeded?) - return value %d, errno %d\n", ret, errno);
110 
111  Put(x, y, buf);
112 }
113 
114 void CTextRenderer::PutAdvance(const wchar_t* buf)
115 {
116  Put(0.0f, 0.0f, buf);
117 
118  int w, h;
119  m_Font->CalculateStringSize(buf, w, h);
120  Translate((float)w, 0.0f, 0.0f);
121 }
122 
123 void CTextRenderer::Put(float x, float y, const wchar_t* buf)
124 {
125  if (buf[0] == 0)
126  return; // empty string; don't bother storing
127 
128  CMatrix3D translate;
129  translate.SetTranslation(x, y, 0.0f);
130 
131  SBatch batch;
132  batch.transform = m_Transform * translate;
133  batch.color = m_Color;
134  batch.font = m_Font;
135  batch.text = buf;
136  m_Batches.push_back(batch);
137 }
138 
139 struct t2f_v2i
140 {
141  t2f_v2i() : u(0), v(0), x(0), y(0) { }
142  float u, v;
143  i16 x, y;
144 };
145 
147 {
148  std::vector<u16> indexes;
149  std::vector<t2f_v2i> vertexes;
150 
151  for (size_t i = 0; i < m_Batches.size(); ++i)
152  {
153  SBatch& batch = m_Batches[i];
154 
155  if (batch.text.empty()) // avoid zero-length arrays
156  continue;
157 
158  const std::map<u16, UnifontGlyphData>& glyphs = batch.font->GetGlyphs();
159 
160  m_Shader->BindTexture(str_tex, batch.font->GetTexture());
161 
162  m_Shader->Uniform(str_transform, batch.transform);
163 
164  // ALPHA-only textures will have .rgb sampled as 0, so we need to
165  // replace it with white (but not affect RGBA textures)
166  if (batch.font->HasRGB())
167  m_Shader->Uniform(str_colorAdd, CColor(0.0f, 0.0f, 0.0f, 0.0f));
168  else
169  m_Shader->Uniform(str_colorAdd, CColor(1.0f, 1.0f, 1.0f, 0.0f));
170 
171  m_Shader->Uniform(str_colorMul, batch.color);
172 
173  vertexes.clear();
174  vertexes.resize(batch.text.size()*4);
175 
176  indexes.clear();
177  indexes.resize(batch.text.size()*6);
178 
179  i16 x = 0;
180  for (size_t i = 0; i < batch.text.size(); ++i)
181  {
182  std::map<u16, UnifontGlyphData>::const_iterator it = glyphs.find(batch.text[i]);
183 
184  if (it == glyphs.end())
185  it = glyphs.find(0xFFFD); // Use the missing glyph symbol
186 
187  if (it == glyphs.end()) // Missing the missing glyph symbol - give up
188  continue;
189 
190  const UnifontGlyphData& g = it->second;
191 
192  vertexes[i*4].u = g.u1;
193  vertexes[i*4].v = g.v0;
194  vertexes[i*4].x = g.x1 + x;
195  vertexes[i*4].y = g.y0;
196 
197  vertexes[i*4+1].u = g.u0;
198  vertexes[i*4+1].v = g.v0;
199  vertexes[i*4+1].x = g.x0 + x;
200  vertexes[i*4+1].y = g.y0;
201 
202  vertexes[i*4+2].u = g.u0;
203  vertexes[i*4+2].v = g.v1;
204  vertexes[i*4+2].x = g.x0 + x;
205  vertexes[i*4+2].y = g.y1;
206 
207  vertexes[i*4+3].u = g.u1;
208  vertexes[i*4+3].v = g.v1;
209  vertexes[i*4+3].x = g.x1 + x;
210  vertexes[i*4+3].y = g.y1;
211 
212  indexes[i*6+0] = i*4+0;
213  indexes[i*6+1] = i*4+1;
214  indexes[i*6+2] = i*4+2;
215  indexes[i*6+3] = i*4+2;
216  indexes[i*6+4] = i*4+3;
217  indexes[i*6+5] = i*4+0;
218 
219  x += g.xadvance;
220  }
221 
222  m_Shader->VertexPointer(2, GL_SHORT, sizeof(t2f_v2i), &vertexes[0].x);
223  m_Shader->TexCoordPointer(GL_TEXTURE0, 2, GL_FLOAT, sizeof(t2f_v2i), &vertexes[0].u);
224 
225  glDrawElements(GL_TRIANGLES, indexes.size(), GL_UNSIGNED_SHORT, &indexes[0]);
226  }
227 
228  m_Batches.clear();
229 }
void Translate(float x, float y, float z)
Definition: Matrix3D.cpp:172
shared_ptr< CFont > m_Font
Definition: TextRenderer.h:102
void PrintfAt(float x, float y, const wchar_t *fmt,...)
Print formatted text at (x,y) under the current transform.
void Translate(float x, float y, float z)
void SetTranslation(float x, float y, float z)
Definition: Matrix3D.cpp:158
void Render()
Render all of the previously printed text calls.
CMatrix3D GetTransform()
void PutAdvance(const wchar_t *buf)
Print text at (0,0) under the current transform, and advance the transform by the width of the text...
Definition: Overlay.h:34
int g_xres
Definition: Config.cpp:58
CTextRenderer(const CShaderProgramPtr &shader)
#define i16
Definition: types.h:35
CMatrix3D m_Transform
Definition: TextRenderer.h:99
#define ARRAY_SIZE(name)
shared_ptr< CFont > font
Definition: TextRenderer.h:93
CShaderProgramPtr m_Shader
Definition: TextRenderer.h:97
void Put(float x, float y, const wchar_t *buf)
Print text at (x,y) under the current transform, and advance the transform by the width of the text...
void Color(const CColor &color)
Set the color for subsequent print calls.
void PrintfAdvance(const wchar_t *fmt,...)
Print formatted text at (0,0) under the current transform, and advance the transform by the width of ...
void ResetTransform()
Reset the text transform to the default, with (0,0) in the top-left of the screen.
Definition: Font.h:28
int g_yres
Definition: Config.cpp:58
std::vector< SBatch > m_Batches
Definition: TextRenderer.h:106
void Scale(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:210
void SetIdentity()
Definition: Matrix3D.cpp:30
void SetTransform(const CMatrix3D &transform)
void Font(const CStrW &font)
Set the font for subsequent print calls.
void SetOrtho(float l, float r, float b, float t, float n, float f)
Definition: Matrix3D.cpp:47
shared_ptr< CShaderProgram > CShaderProgramPtr
std::map< CStrW, shared_ptr< CFont > > m_Fonts
Definition: TextRenderer.h:104
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142