OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Text.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "Text.h"
22 #include "AstcTextures.h"
23 
24 #include <cstdio>
25 #include <cstdlib>
26 
27 namespace AstcTextures
28 {
29  const char Text::textureFilename[] = "font.raw";
30 
31  const float Text::scale = 1.0f;
32 
33  const int Text::textureCharacterWidth = 8;
34  const int Text::textureCharacterHeight = 16;
35 
36  /* Please see header for specification. */
37  void loadData(const char* filename, unsigned char** textureData)
38  {
39  LOGI("Texture loadData started for %s...\n", filename);
40 
41  FILE* file = fopen(filename, "rb");
42 
43  if (file == NULL)
44  {
45  LOGE("Failed to open '%s'\n", filename);
46  exit(EXIT_FAILURE);
47  }
48 
49  fseek(file, 0, SEEK_END);
50 
51  unsigned int length = ftell(file);
52  unsigned char* loadedTexture = NULL;
53 
54  MALLOC_CHECK(unsigned char*, loadedTexture, length);
55 
56  fseek(file, 0, SEEK_SET);
57 
58  size_t read = fread(loadedTexture, sizeof(unsigned char), length, file);
59 
60  if (read != length)
61  {
62  LOGE("Failed to read in '%s'\n", filename);
63  exit(EXIT_FAILURE);
64  }
65 
66  fclose(file);
67 
68  *textureData = loadedTexture;
69  }
70 
71  /* Please see header for specification. */
73  {
74  vertexShaderID = 0;
75  fragmentShaderID = 0;
76  programID = 0;
78 
79  textVertex = NULL;
81  color = NULL;
82  textIndex = NULL;
83 
84  /* Create an orthographic projection. */
85  projectionMatrix = Matrix::matrixOrthographic(0, (float)windowWidth, 0, (float)windowHeight, 0, 1);
86 
87  /* Create program object and initialize it. */
89 
90  GL_CHECK(glUseProgram(programID));
91 
92  /* Vertex positions. */
94 
95  /* Text colors. */
97 
98  /* TexCoords. */
100 
101  /* Projection matrix. */
103 
104  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
105 
106  /* Set the sampler to point at the 0th texture unit. */
108 
109  GL_CHECK(glUniform1i(m_iLocTexture, 0));
110 
111  /* Load texture. */
112  GL_CHECK(glActiveTexture(GL_TEXTURE0));
113  GL_CHECK(glGenTextures(1, &textureID));
114  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
115 
116  /* Set filtering. */
117  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
118  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
119  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
120  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
121 
122  const int textureLength = strlen(resourceDirectory) + strlen(textureFilename);
123  char* texture = NULL;
124 
125  MALLOC_CHECK(char*, texture, textureLength);
126  strcpy(texture, resourceDirectory);
127  strcat(texture, textureFilename);
128 
129  unsigned char* textureData = NULL;
130 
131  loadData(texture, &textureData);
132 
133  FREE_CHECK(texture);
134 
135  GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 48, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData));
136 
137  FREE_CHECK(textureData);
138  }
139 
140  /* Please see header for specification. */
141  void Text::clear(void)
142  {
143  numberOfCharacters = 0;
144 
147  FREE_CHECK(color);
149  }
150 
151  /* Please see header for specification. */
152  void Text::addString(int xPosition, int yPosition, const char* string, int red, int green, int blue, int alpha)
153  {
154  int length = (int)strlen(string);
155  int iTexCoordPos = 4 * 2 * numberOfCharacters;
156  int iVertexPos = 4 * 3 * numberOfCharacters;
157  int iColorPos = 4 * 4 * numberOfCharacters;
158  int iIndex = 0;
159  int iIndexPos = 0;
160 
162 
163  /* Realloc memory. */
164  REALLOC_CHECK(float*, textVertex, numberOfCharacters * 4 * 3 * sizeof(float));
165  REALLOC_CHECK(float*, textTextureCoordinates, numberOfCharacters * 4 * 2 * sizeof(float));
166  REALLOC_CHECK(float*, color, numberOfCharacters * 4 * 4 * sizeof(float));
167  REALLOC_CHECK(GLshort*, textIndex, (numberOfCharacters * 6 - 2) * sizeof(GLshort));
168 
169  /* Re-init entire index array. */
170  textIndex[iIndex++] = 0;
171  textIndex[iIndex++] = 1;
172  textIndex[iIndex++] = 2;
173  textIndex[iIndex++] = 3;
174 
175  iIndexPos = 4;
176  for (int cIndex = 1; cIndex < numberOfCharacters; cIndex ++)
177  {
178  textIndex[iIndexPos++] = iIndex - 1;
179  textIndex[iIndexPos++] = iIndex;
180  textIndex[iIndexPos++] = iIndex++;
181  textIndex[iIndexPos++] = iIndex++;
182  textIndex[iIndexPos++] = iIndex++;
183  textIndex[iIndexPos++] = iIndex++;
184  }
185 
186  for (int iChar = 0; iChar < (signed int)strlen(string); iChar ++)
187  {
188  char cChar = string[iChar];
189  int iCharX = 0;
190  int iCharY = 0;
191  Vec2 sBottom_left;
192  Vec2 sBottom_right;
193  Vec2 sTop_left;
194  Vec2 sTop_right;
195 
196  /* Calculate tex coord for char here. */
197  cChar -= 32;
198  iCharX = cChar % 32;
199  iCharY = cChar / 32;
200  iCharX *= textureCharacterWidth;
201  iCharY *= textureCharacterHeight;
202  sBottom_left.x = iCharX;
203  sBottom_left.y = iCharY;
204  sBottom_right.x = iCharX + textureCharacterWidth;
205  sBottom_right.y = iCharY;
206  sTop_left.x = iCharX;
207  sTop_left.y = iCharY + textureCharacterHeight;
208  sTop_right.x = iCharX + textureCharacterWidth;
209  sTop_right.y = iCharY + textureCharacterHeight;
210 
211  /* Add vertex position data here. */
212  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
213  textVertex[iVertexPos++] = (float)yPosition;
214  textVertex[iVertexPos++] = 0;
215 
216  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
217  textVertex[iVertexPos++] = (float)yPosition;
218  textVertex[iVertexPos++] = 0;
219 
220  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
221  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
222  textVertex[iVertexPos++] = 0;
223 
224  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
225  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
226  textVertex[iVertexPos++] = 0;
227 
228  /* Texture coords here. Because textures are read in upside down, flip Y coords here. */
229  textTextureCoordinates[iTexCoordPos++] = sBottom_left.x / 256.0f;
230  textTextureCoordinates[iTexCoordPos++] = sTop_left.y / 48.0f;
231 
232  textTextureCoordinates[iTexCoordPos++] = sBottom_right.x / 256.0f;
233  textTextureCoordinates[iTexCoordPos++] = sTop_right.y / 48.0f;
234 
235  textTextureCoordinates[iTexCoordPos++] = sTop_left.x / 256.0f;
236  textTextureCoordinates[iTexCoordPos++] = sBottom_left.y / 48.0f;
237 
238  textTextureCoordinates[iTexCoordPos++] = sTop_right.x / 256.0f;
239  textTextureCoordinates[iTexCoordPos++] = sBottom_right.y / 48.0f;
240 
241  /* Color data. */
242  color[iColorPos++] = red / 255.0f;
243  color[iColorPos++] = green / 255.0f;
244  color[iColorPos++] = blue / 255.0f;
245  color[iColorPos++] = alpha / 255.0f;
246 
247  /* Copy to the other 3 vertices. */
248  memcpy(&color[iColorPos], &color[iColorPos - 4], 4 * sizeof(float));
249  memcpy(&color[iColorPos + 4], &color[iColorPos], 4 * sizeof(float));
250  memcpy(&color[iColorPos + 8], &color[iColorPos + 4], 4 * sizeof(float));
251  iColorPos += 3 * 4;
252  }
253  }
254 
255  /* Please see header for specification. */
256  void Text::draw(void)
257  {
258  /* Push currently bound vertex array object. */
259  GLint vertexArray = 0;
260 
261  GL_CHECK(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vertexArray));
262  GL_CHECK(glBindVertexArray(0));
263  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
264 
265  /* Push currently used program object. */
266  GLint currentProgram = 0;
267 
268  GL_CHECK(glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram));
269 
270  GL_CHECK(glUseProgram(programID));
271 
272  if (m_iLocPosition == -1 || m_iLocTextColor == -1 || m_iLocTexCoord == -1 || m_iLocProjection == -1)
273  {
274  LOGI("At least one of the attributes and/or uniforms is missing. Have you invoked Text(const char*, int, int) constructor?");
275  exit(EXIT_FAILURE);
276  }
277 
278  if (numberOfCharacters == 0)
279  {
280  return;
281  }
282 
283  GL_CHECK(glEnableVertexAttribArray(m_iLocPosition));
284  GL_CHECK(glEnableVertexAttribArray(m_iLocTextColor));
285  GL_CHECK(glEnableVertexAttribArray(m_iLocTexCoord));
286 
287  GL_CHECK(glVertexAttribPointer(m_iLocPosition, 3, GL_FLOAT, GL_FALSE, 0, textVertex));
288  GL_CHECK(glVertexAttribPointer(m_iLocTextColor, 4, GL_FLOAT, GL_FALSE, 0, color));
289  GL_CHECK(glVertexAttribPointer(m_iLocTexCoord, 2, GL_FLOAT, GL_FALSE, 0, textTextureCoordinates));
290  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
291 
292  GL_CHECK(glActiveTexture(GL_TEXTURE0));
293  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
294 
295  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, numberOfCharacters * 6 - 2, GL_UNSIGNED_SHORT, textIndex));
296 
297  GL_CHECK(glDisableVertexAttribArray(m_iLocTextColor));
298  GL_CHECK(glDisableVertexAttribArray(m_iLocTexCoord));
299  GL_CHECK(glDisableVertexAttribArray(m_iLocPosition));
300 
301  /* Pop previously used program object. */
302  GL_CHECK(glUseProgram(currentProgram));
303 
304  /* Pop previously bound vertex array object. */
305  GL_CHECK(glBindVertexArray(vertexArray));
306  }
307 
308  /* Please see header for specification. */
309  Text::Text() :
310  m_iLocPosition(-1),
311  m_iLocProjection(-1),
312  m_iLocTextColor(-1),
313  m_iLocTexCoord(-1),
314  m_iLocTexture(-1),
315  vertexShaderID(0),
316  fragmentShaderID(0),
317  programID(0),
318  textureID(0)
319  {
320  clear();
321  }
322 
323  /* Please see header for specification. */
324  Text::~Text(void)
325  {
326  clear();
327 
328  GL_CHECK(glDeleteTextures(1, &textureID));
329  }
330 }
GLuint create_program(const char *vertex_source, const char *fragment_source)
Create program object, attach vertex and fragment shader to it. Link program object and check whether...
const char fontFragmentShaderSource[]
Fragment shader source code for text rendering.
Definition: Text.h:52
void loadData(const char *filename, unsigned char **textureData)
Load texture data from a file into memory.
Definition: Text.cpp:38
float * textVertex
Definition: Text.h:106
#define MALLOC_CHECK(ptr_type, ptr, size)
Definition: AstcTextures.h:33
int windowWidth
Definition: Cube.cpp:56
GLuint textureID
#define LOGI(...)
Definition: AstcTextures.h:29
int m_iLocProjection
Definition: Text.h:111
GLint get_and_check_attrib_location(GLuint program, const GLchar *attrib_name)
Invoke glGetAttribLocation(), if it has returned a positive value. Otherwise, print a message and exi...
Definition: Text.cpp:73
const char fontVertexShaderSource[]
Vertex shader source code for text rendering.
Definition: Text.h:33
float * textTextureCoordinates
Definition: Text.h:107
static const int textureCharacterHeight
The height (in pixels) of the characters in the text texture.
Definition: Text.h:131
void clear(void)
Removes the current string from the class.
Definition: Text.cpp:142
Matrix projectionMatrix
Definition: Text.h:104
Text(void)
Overloaded default constructor.
Definition: Text.cpp:310
struct AstcTextures::Vec2 Vec2
Type representing texture coordinates.
float * color
Definition: Text.h:108
int m_iLocTexCoord
Definition: Text.h:113
GLint get_and_check_uniform_location(GLuint program, const GLchar *uniform_name)
Invoke glGetUniformLocation, if it has returned a positive value. Otherwise, print a message and exit...
Definition: Text.cpp:87
GLuint fragmentShaderID
precision highp int
Definition: hiz_cull.cs:38
static const char textureFilename[]
Definition: Text.h:92
int windowHeight
Definition: Cube.cpp:57
int m_iLocTexture
Definition: Text.h:114
int m_iLocPosition
Definition: Text.h:110
static Matrix matrixOrthographic(float left, float right, float bottom, float top, float zNear, float zFar)
Create and return an orthographic projection matrix.
Definition: Matrix.cpp:87
GLuint textureID
Definition: Text.h:118
static const int textureCharacterWidth
The width (in pixels) of the characters in the text texture.
Definition: Text.h:125
~Text(void)
Overloaded default destructor.
Definition: Text.cpp:325
GLuint fragmentShaderID
Definition: Text.h:116
int m_iLocTextColor
Definition: Text.h:112
GLuint programID
Definition: AntiAlias.cpp:60
#define GL_CHECK(x)
Definition: AstcTextures.h:59
unsigned char * textureData
Definition: ThreadSync.cpp:109
GLenum GLuint texture
Definition: gl2ext.h:385
string resourceDirectory
Definition: AntiAlias.cpp:55
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:52
#define REALLOC_CHECK(ptr_type, ptr, size)
Definition: AstcTextures.h:43
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
GLuint vertexShaderID
#define LOGE(...)
Definition: AstcTextures.h:30
precision highp float
Definition: hiz_cull.cs:37
GLuint programID
Definition: Text.h:117
#define FREE_CHECK(ptr)
Definition: AstcTextures.h:53
static const float scale
Scaling factor to use when rendering the text.
Definition: Text.h:102
void draw(void)
Draw the text to the screen.
Definition: Text.cpp:257
GLshort * textIndex
Definition: Text.h:109
GLuint vertexShaderID
Definition: Text.h:115
void addString(int xPosition, int yPosition, const char *string, int red, int green, int blue, int alpha)
Add a std::string to be drawn to the screen.
Definition: Text.cpp:153
int numberOfCharacters
Definition: Text.h:105