25#ifdef __OCPN__ANDROID__
29#include "pi_TexFont.h"
32#ifdef USE_ANDROID_GLES2
35#include "pi_shaders.h"
44TexFont::~TexFont() { Delete(); }
46void TexFont::Build(wxFont &font,
bool blur) {
49 if (font == m_font && blur == m_blur)
return;
61 for (
int i = MIN_GLYPH; i < MAX_GLYPH; i++) {
64 if (i == DEGREE_GLYPH)
65 text = wxString::Format(_T(
"%c"), 0x00B0);
67 text = wxString::Format(_T(
"%c"), i);
68 wxCoord descent, exlead;
69 sdc.GetTextExtent(text, &gw, &gh, &descent, &exlead,
71 gw *= OCPN_GetWinDIPScaleFactor();
72 gh *= OCPN_GetWinDIPScaleFactor();
78 m_maxglyphw = wxMax(tgi[i].width, m_maxglyphw);
79 m_maxglyphh = wxMax(tgi[i].height, m_maxglyphh);
87 int w = COLS_GLYPHS * m_maxglyphw;
88 int h = ROWS_GLYPHS * m_maxglyphh;
90 wxASSERT(w < 2048 && h < 2048);
93 for (tex_w = 1; tex_w < w; tex_w *= 2);
94 for (tex_h = 1; tex_h < h; tex_h *= 2);
96 wxBitmap tbmp(tex_w, tex_h);
98 dc.SelectObject(tbmp);
102 dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
106 dc.SetTextForeground(wxColour(255, 255, 255));
113 int row = 0, col = 0;
114 for (
int i = MIN_GLYPH; i < MAX_GLYPH; i++) {
115 if (col == COLS_GLYPHS) {
120 tgi[i].x = col * m_maxglyphw;
121 tgi[i].y = row * m_maxglyphh;
124 if (i == DEGREE_GLYPH)
125 text = wxString::Format(_T(
"%c"), 0x00B0);
127 text = wxString::Format(_T(
"%c"), i);
129 dc.DrawText(text, tgi[i].x, tgi[i].y);
136 dc.SelectObject(wxNullBitmap);
138 wxImage image = tbmp.ConvertToImage();
140 GLuint format, internalformat;
144 internalformat = format;
147 if (m_blur) image = image.Blur(1);
149 unsigned char *imgdata = image.GetData();
152 unsigned char *teximage = (
unsigned char *)malloc(stride * tex_w * tex_h);
154 for (
int j = 0; j < tex_w * tex_h; j++)
155 for (
int k = 0; k < stride; k++)
156 teximage[j * stride + k] = imgdata[3 * j];
160 glGenTextures(1, &texobj);
161 glBindTexture(GL_TEXTURE_2D, texobj);
163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
169 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, tex_w, tex_h, 0, format,
170 GL_UNSIGNED_BYTE, teximage);
178void TexFont::Delete() {
180 glDeleteTextures(1, &texobj);
185void TexFont::GetTextExtent(
const char *
string,
int *width,
int *height) {
187 int w = 0, wo = 0, h = 0;
189 for (
int i = 0;
string[i]; i++) {
190 unsigned char c =
string[i];
192 h += tgi[(int)
'A'].height;
197 if (c == 0xc2 && (
unsigned char)
string[i + 1] == 0xb0) {
201 if (c < MIN_GLYPH || c >= MAX_GLYPH)
continue;
205 if (tgisi.height > h) h = tgisi.height;
207 if (width) *width = wxMax(w, wo);
208 if (height) *height = h;
211void TexFont::GetTextExtent(
const wxString &
string,
int *width,
int *height) {
212 GetTextExtent((
const char *)
string.ToUTF8(), width, height);
215void TexFont::RenderGlyph(
int c) {
216 if (c < MIN_GLYPH || c >= MAX_GLYPH)
return;
220 int x = tgic.x, y = tgic.y;
221 float w = m_maxglyphw, h = m_maxglyphh;
222 float tx1 = (float)x / (
float)tex_w;
223 float tx2 = (float)(x + w) / (float)tex_w;
224 float ty1 = (float)y / (
float)tex_h;
225 float ty2 = (float)(y + h) / (float)tex_h;
227#ifndef USE_ANDROID_GLES2
231 glTexCoord2f(tx1, ty1);
233 glTexCoord2f(tx2, ty1);
235 glTexCoord2f(tx2, ty2);
237 glTexCoord2f(tx1, ty2);
241 glTranslatef(tgic.advance, 0.0, 0.0);
270 glUseProgram(pi_texture_2D_shader_program);
273 GLint mPosAttrib = glGetAttribLocation(pi_texture_2D_shader_program,
"aPos");
274 GLint mUvAttrib = glGetAttribLocation(pi_texture_2D_shader_program,
"aUV");
277 GLint texUni = glGetUniformLocation(pi_texture_2D_shader_program,
"uTex");
278 glUniform1i(texUni, 0);
281 glBindBuffer(GL_ARRAY_BUFFER, 0);
282 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
285 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
287 glEnableVertexAttribArray(mPosAttrib);
290 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, uv);
292 glEnableVertexAttribArray(mUvAttrib);
298 mat4x4_rotate_Z(Q, I, angle);
305 glGetUniformLocation(pi_texture_2D_shader_program,
"TransformMatrix");
306 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
309 glActiveTexture(GL_TEXTURE0);
314 GLushort indices1[] = {0,1,3,2};
315 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices1);
338 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, co1);
339 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, tco1);
341 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
344 m_dx += tgic.advance;
349void TexFont::RenderString(
const char *
string,
int x,
int y) {
350#ifndef USE_ANDROID_GLES2
353 glTranslatef(x, y, 0);
356 glBindTexture(GL_TEXTURE_2D, texobj);
358 for (
int i = 0;
string[i]; i++) {
359 if (
string[i] ==
'\n') {
361 glTranslatef(0, tgi[(
int)
'A'].height, 0);
366 if ((
unsigned char)
string[i] == 0xc2 &&
367 (
unsigned char)
string[i + 1] == 0xb0) {
368 RenderGlyph(DEGREE_GLYPH);
372 RenderGlyph(
string[i]);
381 glBindTexture(GL_TEXTURE_2D, texobj);
383 for (
int i = 0;
string[i]; i++) {
384 if (
string[i] ==
'\n') {
385 m_dy += tgi[(int)
'A'].height;
389 if ((
unsigned char)
string[i] == 0xc2 &&
390 (
unsigned char)
string[i + 1] == 0xb0) {
391 RenderGlyph(DEGREE_GLYPH);
395 RenderGlyph(
string[i]);
401void TexFont::RenderString(
const wxString &
string,
int x,
int y) {
402 RenderString((
const char *)
string.ToUTF8(), x, y);