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) 2012-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 "Common.h"
22 #include "Text.h"
23 #include "Texture.h"
24 #include "Shader.h"
25 #include "VectorTypes.h"
26 
27 #include <cstring>
28 
29 namespace MaliSDK
30 {
31  const float Text::scale = 2.0f;
32 
33  const int Text::textureCharacterWidth = 8;
34  const int Text::textureCharacterHeight = 16;
35 
36  Text::Text(const char* vertexShaderFileName,
37  const char* fragmentShaderFileName,
38  const char* textureFileName,
39  int windowWidth,
40  int windowHeight)
41  {
42  vertexShaderID = 0;
43  fragmentShaderID = 0;
44  programID = 0;
45 
47  textVertex = NULL;
49  color = NULL;
50  textIndex = NULL;
51 
52  /* Create an orthographic projection. */
53  projectionMatrix = Matrix::matrixOrthographic(0, (float)windowWidth, 0, (float)windowHeight, 0, 1);
54 
55  /* Shaders. */
56  Shader::processShader(&vertexShaderID, vertexShaderFileName, GL_VERTEX_SHADER);
57  Shader::processShader(&fragmentShaderID, fragmentShaderFileName, GL_FRAGMENT_SHADER);
58 
59  /* Set up shaders. */
60  programID = GL_CHECK(glCreateProgram());
61 
62  GL_CHECK(glAttachShader(programID, vertexShaderID));
63  GL_CHECK(glAttachShader(programID, fragmentShaderID));
64  GL_CHECK(glLinkProgram(programID));
65  GL_CHECK(glUseProgram(programID));
66 
67  /* Vertex positions. */
68  m_iLocPosition = GL_CHECK(glGetAttribLocation(programID, "a_v4Position"));
69  /* Text colors. */
70  m_iLocTextColor = GL_CHECK(glGetAttribLocation(programID, "a_v4FontColor"));
71  /* TexCoords. */
72  m_iLocTexCoord = GL_CHECK(glGetAttribLocation(programID, "a_v2TexCoord"));
73  /* Projection matrix. */
74  m_iLocProjection = GL_CHECK(glGetUniformLocation(programID, "u_m4Projection"));
75  /* Set the sampler to point at the 0th texture unit. */
76  m_iLocTexture = GL_CHECK(glGetUniformLocation(programID, "u_s2dTexture"));
77 
78  ASSERT(m_iLocPosition != -1, "Attribute not found: a_v4Position");
79  ASSERT(m_iLocTextColor != -1, "Attribute not found: a_v4FontColor");
80  ASSERT(m_iLocTexCoord != -1, "Attribute not found: a_v2TexCoord");
81  ASSERT(m_iLocProjection != -1, "Uniform not found: u_m4Projection");
82  ASSERT(m_iLocTexture != -1, "Uniform not found: u_s2dTexture");
83 
84  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
85  GL_CHECK(glUniform1i (m_iLocTexture, 1));
86 
87  /* Load texture. */
88  GL_CHECK(glActiveTexture(GL_TEXTURE1));
89  GL_CHECK(glGenTextures (1, &textureID));
90  GL_CHECK(glBindTexture (GL_TEXTURE_2D, textureID));
91 
92  /* Set filtering. */
93  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
94  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
95  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
96  GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
97 
98  unsigned char *textureData = NULL;
99 
100  Texture::loadData(textureFileName, &textureData);
101 
102  GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 48, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData));
103 
104  free(textureData);
105  textureData = NULL;
106  }
107 
108  void Text::clear(void)
109  {
110  numberOfCharacters = 0;
111 
112  free(textVertex);
114  free(color);
115  free(textIndex);
116 
117  textVertex = NULL;
118  textTextureCoordinates = NULL;
119  color = NULL;
120  textIndex = NULL;
121  }
122 
123  void Text::addString(int xPosition, int yPosition, const char *string, int red, int green, int blue, int alpha)
124  {
125  int length = (int)strlen(string);
126  int iTexCoordPos = 4 * 2 * numberOfCharacters;
127  int iVertexPos = 4 * 3 * numberOfCharacters;
128  int iColorPos = 4 * 4 * numberOfCharacters;
129  int iIndex = 0;
130  int iIndexPos = 0;
131 
133 
134  /* Realloc memory. */
135  textVertex = (float *)realloc(textVertex, numberOfCharacters * 4 * 3 * sizeof(float));
136  textTextureCoordinates = (float *)realloc(textTextureCoordinates, numberOfCharacters * 4 * 2 * sizeof(float));
137  color = (float *)realloc(color, numberOfCharacters * 4 * 4 * sizeof(float));
138  textIndex = (GLshort *)realloc(textIndex, (numberOfCharacters * 6 - 2) * sizeof(GLshort));
139  if((textVertex == NULL) || (textTextureCoordinates == NULL) || (color == NULL) || (textIndex == NULL))
140  {
141  LOGE("Out of memory at %s:%i\n", __FILE__, __LINE__);
142  exit(1);
143  }
144 
145  /* Re-init entire index array. */
146  textIndex[iIndex ++] = 0;
147  textIndex[iIndex ++] = 1;
148  textIndex[iIndex ++] = 2;
149  textIndex[iIndex ++] = 3;
150 
151  iIndexPos = 4;
152  for(int cIndex = 1; cIndex < numberOfCharacters; cIndex ++)
153  {
154  textIndex[iIndexPos ++] = iIndex - 1;
155  textIndex[iIndexPos ++] = iIndex;
156  textIndex[iIndexPos ++] = iIndex++;
157  textIndex[iIndexPos ++] = iIndex++;
158  textIndex[iIndexPos ++] = iIndex++;
159  textIndex[iIndexPos ++] = iIndex++;
160  }
161 
162  for(int iChar = 0; iChar < (signed int)strlen(string); iChar ++)
163  {
164  char cChar = string[iChar];
165  int iCharX = 0;
166  int iCharY = 0;
167  Vec2 sBottom_left;
168  Vec2 sBottom_right;
169  Vec2 sTop_left;
170  Vec2 sTop_right;
171 
172  /* Calculate tex coord for char here. */
173  cChar -= 32;
174  iCharX = cChar % 32;
175  iCharY = cChar / 32;
176  iCharX *= textureCharacterWidth;
177  iCharY *= textureCharacterHeight;
178  sBottom_left.x = iCharX;
179  sBottom_left.y = iCharY;
180  sBottom_right.x = iCharX + textureCharacterWidth;
181  sBottom_right.y = iCharY;
182  sTop_left.x = iCharX;
183  sTop_left.y = iCharY + textureCharacterHeight;
184  sTop_right.x = iCharX + textureCharacterWidth;
185  sTop_right.y = iCharY + textureCharacterHeight;
186 
187  /* Add vertex position data here. */
188  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
189  textVertex[iVertexPos++] = (float)yPosition;
190  textVertex[iVertexPos++] = 0;
191 
192  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
193  textVertex[iVertexPos++] = (float)yPosition;
194  textVertex[iVertexPos++] = 0;
195 
196  textVertex[iVertexPos++] = xPosition + iChar * textureCharacterWidth * scale;
197  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
198  textVertex[iVertexPos++] = 0;
199 
200  textVertex[iVertexPos++] = xPosition + (iChar + 1) * textureCharacterWidth * scale;
201  textVertex[iVertexPos++] = yPosition + textureCharacterHeight * scale;
202  textVertex[iVertexPos++] = 0;
203 
204  /* Texture coords here. Because textures are read in upside down, flip Y coords here. */
205  textTextureCoordinates[iTexCoordPos++] = sBottom_left.x / 256.0f;
206  textTextureCoordinates[iTexCoordPos++] = sTop_left.y / 48.0f;
207 
208  textTextureCoordinates[iTexCoordPos++] = sBottom_right.x / 256.0f;
209  textTextureCoordinates[iTexCoordPos++] = sTop_right.y / 48.0f;
210 
211  textTextureCoordinates[iTexCoordPos++] = sTop_left.x / 256.0f;
212  textTextureCoordinates[iTexCoordPos++] = sBottom_left.y / 48.0f;
213 
214  textTextureCoordinates[iTexCoordPos++] = sTop_right.x / 256.0f;
215  textTextureCoordinates[iTexCoordPos++] = sBottom_right.y / 48.0f;
216 
217  /* Color data. */
218  color[iColorPos ++] = red / 255.0f;
219  color[iColorPos ++] = green / 255.0f;
220  color[iColorPos ++] = blue / 255.0f;
221  color[iColorPos ++] = alpha / 255.0f;
222 
223  /* Copy to the other 3 vertices. */
224  memcpy(&color[iColorPos], &color[iColorPos - 4], 4 * sizeof(float));
225  memcpy(&color[iColorPos + 4], &color[iColorPos], 4 * sizeof(float));
226  memcpy(&color[iColorPos + 8], &color[iColorPos + 4], 4 * sizeof(float));
227  iColorPos += 3 * 4;
228  }
229  }
230 
231  void Text::draw(void)
232  {
233  GL_CHECK(glBindVertexArray(0));
234  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
235 
236  if(numberOfCharacters == 0)
237  {
238  return;
239  }
240 
241  GL_CHECK(glUseProgram(programID));
242 
243  if(m_iLocPosition != -1)
244  {
245  GL_CHECK(glEnableVertexAttribArray(m_iLocPosition));
246  GL_CHECK(glVertexAttribPointer(m_iLocPosition, 3, GL_FLOAT, GL_FALSE, 0, textVertex));
247  }
248 
249  if(m_iLocTextColor != -1)
250  {
251  GL_CHECK(glEnableVertexAttribArray(m_iLocTextColor));
252  GL_CHECK(glVertexAttribPointer(m_iLocTextColor, 4, GL_FLOAT, GL_FALSE, 0, color));
253  }
254 
255  if(m_iLocTexCoord != -1)
256  {
257  GL_CHECK(glEnableVertexAttribArray(m_iLocTexCoord));
258  GL_CHECK(glVertexAttribPointer(m_iLocTexCoord, 2, GL_FLOAT, GL_FALSE, 0, textTextureCoordinates));
259  }
260 
261  if(m_iLocProjection != -1)
262  {
263  GL_CHECK(glUniformMatrix4fv(m_iLocProjection, 1, GL_FALSE, projectionMatrix.getAsArray()));
264  }
265 
266  GL_CHECK(glActiveTexture(GL_TEXTURE0));
267  GL_CHECK(glBindTexture(GL_TEXTURE_2D, textureID));
268 
269  GL_CHECK(glDrawElements(GL_TRIANGLE_STRIP, numberOfCharacters * 6 - 2, GL_UNSIGNED_SHORT, textIndex));
270 
271  if(m_iLocTextColor != -1)
272  {
273  GL_CHECK(glDisableVertexAttribArray(m_iLocTextColor));
274  }
275 
276  if(m_iLocTexCoord != -1)
277  {
278  GL_CHECK(glDisableVertexAttribArray(m_iLocTexCoord));
279  }
280 
281  if(m_iLocPosition != -1)
282  {
283  GL_CHECK(glDisableVertexAttribArray(m_iLocPosition));
284  }
285  }
286 
287  Text::~Text(void)
288  {
289  clear();
290 
291  GL_CHECK(glDeleteTextures(1, &textureID));
292  }
293 }
int m_iLocProjection
Definition: Text.h:68
float * textTextureCoordinates
Definition: Text.h:64
int windowWidth
Definition: Cube.cpp:56
int m_iLocTextColor
Definition: Text.h:69
Text(const char *resourceDirectory, int windowWidth, int windowHeight)
Constructor for Text.
Definition: Text.cpp:43
static const float scale
Scaling factor to use when rendering the text.
Definition: Text.h:57
struct AstcTextures::Vec2 Vec2
Type representing texture coordinates.
precision highp int
Definition: hiz_cull.cs:38
void clear(void)
Removes the current string from the class.
Definition: Text.cpp:142
GLshort * textIndex
Definition: Text.h:66
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:483
int windowHeight
Definition: Cube.cpp:57
float * textVertex
Definition: Text.h:63
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
int numberOfCharacters
Definition: Text.h:62
static const int textureCharacterHeight
The height (in pixels) of the characters in the text texture.
Definition: Text.h:89
virtual ~Text(void)
Default destructor.
Definition: Text.cpp:322
GLuint textureID
Definition: Text.h:75
static const int textureCharacterWidth
The width (in pixels) of the characters in the text texture.
Definition: Text.h:83
float * color
Definition: Text.h:65
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:157
int m_iLocTexCoord
Definition: Text.h:70
GLuint fragmentShaderID
Definition: Text.h:73
#define GL_CHECK(x)
Definition: AstcTextures.h:59
GLuint vertexShaderID
Definition: Text.h:72
unsigned char * textureData
Definition: ThreadSync.cpp:109
static void loadData(const char *filename, unsigned char **textureData)
Load texture data from a file into memory.
Definition: Texture.cpp:167
int m_iLocTexture
Definition: Text.h:71
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
Vector types.
int m_iLocPosition
Definition: Text.h:67
#define LOGE(...)
Definition: AstcTextures.h:30
#define ASSERT(x, s)
Definition: common.h:45
precision highp float
Definition: hiz_cull.cs:37
static void processShader(GLuint *shader, const char *filename, GLint shaderType)
Create shader, load in source, compile, and dump debug as necessary.
Definition: Shader.cpp:29
GLuint programID
Definition: Text.h:74
void draw(void)
Draw the text to the screen.
Definition: Text.cpp:265
Matrix projectionMatrix
Definition: Text.h:61