33#ifdef USE_ANDROID_GLES2
36#include "pi_shaders.h"
45TexFont::~TexFont() { Delete(); }
47void TexFont::Build(wxFont &font,
bool blur) {
50 if (font == m_font && blur == m_blur)
return;
62 for (
int i = MIN_GLYPH; i < MAX_GLYPH; i++) {
65 if (i == DEGREE_GLYPH)
66 text = wxString::Format(
"%c", 0x00B0);
68 text = wxString::Format(
"%c", i);
69 wxCoord descent, exlead;
70 sdc.GetTextExtent(text, &gw, &gh, &descent, &exlead,
79 m_maxglyphw = wxMax(tgi[i].width, m_maxglyphw);
80 m_maxglyphh = wxMax(tgi[i].height, m_maxglyphh);
88 int w = COLS_GLYPHS * m_maxglyphw;
89 int h = ROWS_GLYPHS * m_maxglyphh;
91 wxASSERT(w < 2048 && h < 2048);
94 for (tex_w = 1; tex_w < w; tex_w *= 2);
95 for (tex_h = 1; tex_h < h; tex_h *= 2);
97 wxBitmap tbmp(tex_w, tex_h);
99 dc.SelectObject(tbmp);
103 dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
107 dc.SetTextForeground(wxColour(255, 255, 255));
114 int row = 0, col = 0;
115 for (
int i = MIN_GLYPH; i < MAX_GLYPH; i++) {
116 if (col == COLS_GLYPHS) {
121 tgi[i].x = col * m_maxglyphw;
122 tgi[i].y = row * m_maxglyphh;
125 if (i == DEGREE_GLYPH)
126 text = wxString::Format(
"%c", 0x00B0);
128 text = wxString::Format(
"%c", i);
130 dc.DrawText(text, tgi[i].x, tgi[i].y);
137 dc.SelectObject(wxNullBitmap);
139 wxImage image = tbmp.ConvertToImage();
141 GLuint format, internalformat;
145 internalformat = format;
148 if (m_blur) image = image.Blur(1);
150 unsigned char *imgdata = image.GetData();
153 auto *teximage = (
unsigned char *)malloc(stride * tex_w * tex_h);
155 for (
int j = 0; j < tex_w * tex_h; j++)
156 for (
int k = 0; k < stride; k++)
157 teximage[j * stride + k] = imgdata[3 * j];
161 glGenTextures(1, &texobj);
162 glBindTexture(GL_TEXTURE_2D, texobj);
164 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
165 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
170 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, tex_w, tex_h, 0, format,
171 GL_UNSIGNED_BYTE, teximage);
179void TexFont::Delete() {
181 glDeleteTextures(1, &texobj);
186void TexFont::GetTextExtent(
const char *
string,
int *width,
int *height) {
188 int w = 0, wo = 0, h = 0;
190 for (
int i = 0;
string[i]; i++) {
191 unsigned char c =
string[i];
193 h += tgi[(int)
'A'].height;
198 if (c == 0xc2 && (
unsigned char)
string[i + 1] == 0xb0) {
202 if (c < MIN_GLYPH || c >= MAX_GLYPH)
continue;
206 if (tgisi.height > h) h = tgisi.height;
208 if (width) *width = wxMax(w, wo);
209 if (height) *height = h;
212void TexFont::GetTextExtent(
const wxString &
string,
int *width,
int *height) {
213 GetTextExtent((
const char *)
string.ToUTF8(), width, height);
216void TexFont::RenderGlyph(
int c) {
217 if (c < MIN_GLYPH || c >= MAX_GLYPH)
return;
221 int x = tgic.x, y = tgic.y;
222 float w = m_maxglyphw, h = m_maxglyphh;
223 float tx1 = (float)x / (
float)tex_w;
224 float tx2 = (float)(x + w) / (float)tex_w;
225 float ty1 = (float)y / (
float)tex_h;
226 float ty2 = (float)(y + h) / (float)tex_h;
228#ifndef USE_ANDROID_GLES2
232 glTexCoord2f(tx1, ty1);
234 glTexCoord2f(tx2, ty1);
236 glTexCoord2f(tx2, ty2);
238 glTexCoord2f(tx1, ty2);
242 glTranslatef(tgic.advance, 0.0, 0.0);
271 glUseProgram(pi_texture_2D_shader_program);
274 GLint mPosAttrib = glGetAttribLocation(pi_texture_2D_shader_program,
"aPos");
275 GLint mUvAttrib = glGetAttribLocation(pi_texture_2D_shader_program,
"aUV");
278 GLint texUni = glGetUniformLocation(pi_texture_2D_shader_program,
"uTex");
279 glUniform1i(texUni, 0);
282 glBindBuffer(GL_ARRAY_BUFFER, 0);
283 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
286 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, coords);
288 glEnableVertexAttribArray(mPosAttrib);
291 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, uv);
293 glEnableVertexAttribArray(mUvAttrib);
299 mat4x4_rotate_Z(Q, I, angle);
306 glGetUniformLocation(pi_texture_2D_shader_program,
"TransformMatrix");
307 glUniformMatrix4fv(matloc, 1, GL_FALSE, (
const GLfloat *)Q);
310 glActiveTexture(GL_TEXTURE0);
315 GLushort indices1[] = {0,1,3,2};
316 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices1);
339 glVertexAttribPointer(mPosAttrib, 2, GL_FLOAT, GL_FALSE, 0, co1);
340 glVertexAttribPointer(mUvAttrib, 2, GL_FLOAT, GL_FALSE, 0, tco1);
342 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
345 m_dx += tgic.advance;
350void TexFont::RenderString(
const char *
string,
int x,
int y) {
351#ifndef USE_ANDROID_GLES2
354 glTranslatef(x, y, 0);
357 glBindTexture(GL_TEXTURE_2D, texobj);
359 for (
int i = 0;
string[i]; i++) {
360 if (
string[i] ==
'\n') {
362 glTranslatef(0, tgi[(
int)
'A'].height, 0);
367 if ((
unsigned char)
string[i] == 0xc2 &&
368 (
unsigned char)
string[i + 1] == 0xb0) {
369 RenderGlyph(DEGREE_GLYPH);
373 RenderGlyph(
string[i]);
382 glBindTexture(GL_TEXTURE_2D, texobj);
384 for (
int i = 0;
string[i]; i++) {
385 if (
string[i] ==
'\n') {
386 m_dy += tgi[(int)
'A'].height;
390 if ((
unsigned char)
string[i] == 0xc2 &&
391 (
unsigned char)
string[i + 1] == 0xb0) {
392 RenderGlyph(DEGREE_GLYPH);
396 RenderGlyph(
string[i]);
402void TexFont::RenderString(
const wxString &
string,
int x,
int y) {
403 RenderString((
const char *)
string.ToUTF8(), x, y);
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
Graphics abstraction layer on top of wxDC or OpenGL.