summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2011-06-12 13:05:22 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2011-06-12 13:05:22 +0800
commit71768e8d8bb1fd2aaaff5481485c046f78d96e56 (patch)
treee045626c516409f6c9abef440d56b2db42812a6c
parent4d1a3848f246666f03cef9eca095fb04d82e10b3 (diff)
opengles: fix the renderer to draw glyphs at correct positions
-rw-r--r--src/sdl-freetype-opengles.c245
1 files changed, 137 insertions, 108 deletions
diff --git a/src/sdl-freetype-opengles.c b/src/sdl-freetype-opengles.c
index b1425b5..c20e463 100644
--- a/src/sdl-freetype-opengles.c
+++ b/src/sdl-freetype-opengles.c
@@ -37,6 +37,7 @@
#include "sdl-freetype-opengles.h"
#include "sdl-freetype-utils.h"
+#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
@@ -67,8 +68,10 @@ typedef struct {
} sdl_freetype_opengles_coord_t;
typedef struct {
+ sdl_freetype_font_t * font;
+ FT_UInt index;
sdl_freetype_area_t * area;
- sdl_freetype_bool_t locked;
+ int locked;
sdl_freetype_opengles_coord_t uv[2];
} sdl_freetype_opengles_user_data_t;
@@ -90,9 +93,9 @@ sdl_freetype_opengles_user_data_destroy (sdl_freetype_opengles_user_data_t * dat
static sdl_freetype_error_t
sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
- sdl_freetype_glyph_render_t * render,
- sdl_freetype_glyph_info_t * info,
- FT_UInt index)
+ sdl_freetype_glyph_render_t * render,
+ sdl_freetype_glyph_info_t * info,
+ FT_UInt index)
{
sdl_freetype_opengles_render_t * opengles_render =
(sdl_freetype_opengles_render_t *) render;
@@ -159,7 +162,7 @@ sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
unsigned char * src, * dst;
int h;
- width = pitch = (bitmap->width + 3) & ~3;
+ width = pitch = (bitmap->width + 1 + 3) & ~3;
data = calloc (pitch * info->bitmap.rows, 1);
if (!data)
return SDL_FREETYPE_ERR_OUT_OF_MEMORY;
@@ -175,11 +178,11 @@ sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
}
}
} else if (bitmap->pixel_mode == FT_PIXEL_MODE_LCD ||
- bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V) {
+ bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V) {
unsigned char * src, * dst;
int h;
- width = pitch = (bitmap->width + 3) & ~3;
+ width = pitch = (bitmap->width + 1 + 3) & ~3;
data = calloc (pitch * info->bitmap.rows, 1);
if (!data)
return SDL_FREETYPE_ERR_OUT_OF_MEMORY;
@@ -188,17 +191,17 @@ sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
dst = data;
for (h = bitmap->rows; h > 0; h--, src += bitmap->pitch, dst += pitch) {
int x;
- unsigned int *s = (unsigned int*)src;
+ unsigned int *s = (unsigned int*)src;
for (x = 0; x < bitmap->width; x++)
- dst[x] = s[x] >> 24;
+ dst[x] = s[x] >> 24;
}
} else {
data = NULL;
pitch = bitmap->pitch;
- width = (bitmap->width + 3) & ~3;
+ width = (bitmap->width + 1 + 3) & ~3;
}
- height = (bitmap->rows + 3) & ~3;
+ height = (bitmap->rows + 1 + 3) & ~3;
user_data = sdl_freetype_opengles_user_data_create ();
if (!user_data)
@@ -246,8 +249,10 @@ sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
if (data)
free (data);
- user_data->uv[0].x = (float)area->x;
- user_data->uv[0].y = (float)area->y;
+ user_data->font = font;
+ user_data->index = index;
+ user_data->uv[0].x = (float)area->x / opengles_render->width;
+ user_data->uv[0].y = (float)area->y / opengles_render->height;
user_data->uv[1].x = (float)(area->x + bitmap->width) / opengles_render->width;
user_data->uv[1].y = (float)(area->y + bitmap->rows) / opengles_render->height;
info->data = user_data;
@@ -291,7 +296,8 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
sdl_freetype_opengles_glyph_info_t * cached, stack_cached[LOCAL_BUF];
sdl_freetype_glyph_info_t * info;
double x1, y1, x2, y2;
- int i, num_cached;
+ int i, start, num_cached;
+ sdl_freetype_bool_t dirty = SDL_FREETYPE_FALSE;
GLboolean blend_enabled;
if (!render->valid) {
@@ -316,123 +322,145 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
blend_enabled = glIsEnabled(GL_BLEND);
- num_cached = 0;
- for (i = 0; i < num_glyphs; i++) {
- info = sdl_freetype_font_glyph_info_lookup (font, glyphs[i].index,
- SDL_FREETYPE_GLYPH_SURFACE |
- SDL_FREETYPE_GLYPH_USER_DATA);
- if (!info)
- continue;
- user_data = info->data;
- if (!user_data || !user_data->area)
- continue;
- user_data->locked = SDL_FREETYPE_TRUE;
- cached[num_cached].index = i;
- cached[num_cached++].info = info;
- }
+ start = 0;
+ while (start < num_glyphs) {
+ int end;
+
+ num_cached = 0;
+ for (i = start; i < num_glyphs; i++) {
+ info = sdl_freetype_font_glyph_info_lookup (font, glyphs[i].index,
+ SDL_FREETYPE_GLYPH_SURFACE |
+ SDL_FREETYPE_GLYPH_USER_DATA);
+ if (!info || info->flags & SDL_FREETYPE_GLYPH_EMPTY)
+ continue;
+
+ user_data = info->data;
+ if (!user_data) {
+ if (num_cached)
+ i--;
+ break;
+ }
+ if (!user_data->area)
+ continue;
+ user_data->locked++;
+ cached[num_cached].index = i;
+ cached[num_cached++].info = info;
+ }
+ end = i + 1;
- if (num_cached) {
- GLfloat *vertex_buffer = render->vertex_buffer;
- GLfloat *texcoord_buffer = render->texcoord_buffer;
- int left = num_cached;
+ if (num_cached) {
+ GLfloat *vertex_buffer = render->vertex_buffer;
+ GLfloat *texcoord_buffer = render->texcoord_buffer;
+ int left = num_cached;
- glMatrixMode (GL_TEXTURE);
- glPushMatrix ();
- glLoadIdentity ();
+ if (!dirty) {
+ dirty = SDL_FREETYPE_TRUE;
- glMatrixMode (GL_MODELVIEW);
- glPushMatrix ();
+ glMatrixMode (GL_TEXTURE);
+ glPushMatrix ();
+ glLoadIdentity ();
- glEnable (GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glMatrixMode (GL_MODELVIEW);
+ glPushMatrix ();
- glEnable (GL_TEXTURE_2D);
- glBindTexture (GL_TEXTURE_2D, render->texture);
+ glEnable (GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glTranslatef (x * render->usx, y * render->usy, 0.0f);
+ glEnable (GL_TEXTURE_2D);
+ glBindTexture (GL_TEXTURE_2D, render->texture);
- glColor4ub (r, g, b, a);
+ glTranslatef (x * render->usx, y * render->usy, 0.0f);
- glEnableClientState (GL_VERTEX_ARRAY);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ glColor4ub (r, g, b, a);
- glVertexPointer (2, GL_FLOAT, 0, vertex_buffer);
- glTexCoordPointer (2, GL_FLOAT, 0, texcoord_buffer);
+ glEnableClientState (GL_VERTEX_ARRAY);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- i = 0;
- while (left) {
- int num_quads = VERTEX_BUFFER_SIZE;
- int max_index;
- int j = 0;
+ glVertexPointer (2, GL_FLOAT, 0, vertex_buffer);
+ glTexCoordPointer (2, GL_FLOAT, 0, texcoord_buffer);
+ }
- if (left < num_quads)
- num_quads = left;
+ i = 0;
+ while (left) {
+ int num_quads = VERTEX_BUFFER_SIZE;
+ int max_index;
+ int j;
- max_index = i + num_quads;
- for (j = 0; i < max_index; i++, j += 12) {
- user_data = cached[i].info->data;
+ if (left < num_quads)
+ num_quads = left;
- x1 = FIXEDTOD (glyphs[cached[i].index].x) + cached[i].info->x_offset;
- y2 = -FIXEDTOD (glyphs[cached[i].index].y) - cached[i].info->y_offset;
- x2 = x1 + cached[i].info->bitmap.width;
- y1 = y2 - cached[i].info->bitmap.rows;
+ max_index = i + num_quads;
- x1 *= render->usx;
- y1 *= render->usy;
- x2 *= render->usx;
- y2 *= render->usy;
+ for (j = 0; i < max_index; i++, j += 12) {
+ user_data = cached[i].info->data;
- texcoord_buffer[j + 0] = user_data->uv[0].x;
- texcoord_buffer[j + 1] = user_data->uv[0].y;
- vertex_buffer[j + 0] = x1;
- vertex_buffer[j + 1] = y1;
+ assert (user_data->locked != 0);
- texcoord_buffer[j + 2] = user_data->uv[0].x;
- texcoord_buffer[j + 3] = user_data->uv[1].y;
- vertex_buffer[j + 2] = x1;
- vertex_buffer[j + 3] = y2;
+ x1 = FIXEDTOD (glyphs[cached[i].index].x) + cached[i].info->x_offset;
+ y1 = FIXEDTOD (glyphs[cached[i].index].y) + cached[i].info->y_offset;
+ x2 = x1 + cached[i].info->bitmap.width;
+ y2 = y1 + cached[i].info->bitmap.rows;
- texcoord_buffer[j + 4] = user_data->uv[1].x;
- texcoord_buffer[j + 5] = user_data->uv[1].y;
- vertex_buffer[j + 4] = x2;
- vertex_buffer[j + 5] = y2;
+ x1 *= render->usx;
+ y1 *= render->usy;
+ x2 *= render->usx;
+ y2 *= render->usy;
- texcoord_buffer[j + 6] = user_data->uv[1].x;
- texcoord_buffer[j + 7] = user_data->uv[1].y;
- vertex_buffer[j + 6] = x2;
- vertex_buffer[j + 7] = y2;
+ texcoord_buffer[j + 0] = user_data->uv[0].x;
+ texcoord_buffer[j + 1] = user_data->uv[0].y;
+ vertex_buffer[j + 0] = x1;
+ vertex_buffer[j + 1] = y1;
- texcoord_buffer[j + 8] = user_data->uv[1].x;
- texcoord_buffer[j + 9] = user_data->uv[0].y;
- vertex_buffer[j + 8] = x2;
- vertex_buffer[j + 9] = y1;
+ texcoord_buffer[j + 2] = user_data->uv[0].x;
+ texcoord_buffer[j + 3] = user_data->uv[1].y;
+ vertex_buffer[j + 2] = x1;
+ vertex_buffer[j + 3] = y2;
- texcoord_buffer[j + 10] = user_data->uv[0].x;
- texcoord_buffer[j + 11] = user_data->uv[0].y;
- vertex_buffer[j + 10] = x1;
- vertex_buffer[j + 11] = y1;
+ texcoord_buffer[j + 4] = user_data->uv[1].x;
+ texcoord_buffer[j + 5] = user_data->uv[1].y;
+ vertex_buffer[j + 4] = x2;
+ vertex_buffer[j + 5] = y2;
- user_data->locked = SDL_FREETYPE_FALSE;
- }
+ texcoord_buffer[j + 6] = user_data->uv[1].x;
+ texcoord_buffer[j + 7] = user_data->uv[1].y;
+ vertex_buffer[j + 6] = x2;
+ vertex_buffer[j + 7] = y2;
+
+ texcoord_buffer[j + 8] = user_data->uv[1].x;
+ texcoord_buffer[j + 9] = user_data->uv[0].y;
+ vertex_buffer[j + 8] = x2;
+ vertex_buffer[j + 9] = y1;
- glDrawArrays (GL_TRIANGLES, 0, num_quads * 6);
+ texcoord_buffer[j + 10] = user_data->uv[0].x;
+ texcoord_buffer[j + 11] = user_data->uv[0].y;
+ vertex_buffer[j + 10] = x1;
+ vertex_buffer[j + 11] = y1;
- left -= num_quads;
+ user_data->locked--;
+ }
+
+ glDrawArrays (GL_TRIANGLES, 0, num_quads * 6);
+
+ left -= num_quads;
+ }
}
+ start = end;
+ }
+ if (dirty) {
glDisableClientState (GL_VERTEX_ARRAY);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glPopMatrix ();
+ glPopMatrix ();
- glMatrixMode (GL_TEXTURE);
- glPopMatrix ();
- }
+ glMatrixMode (GL_TEXTURE);
+ glPopMatrix ();
- if (!blend_enabled)
- glDisable (GL_BLEND);
+ if (!blend_enabled)
+ glDisable (GL_BLEND);
- glBindTexture (GL_TEXTURE_2D, 0);
+ glBindTexture (GL_TEXTURE_2D, 0);
+ }
if (cached != stack_cached)
free (cached);
@@ -471,17 +499,18 @@ sdl_freetype_opengles_glyph_move_in (sdl_freetype_area_manager_t * manager,
static void
sdl_freetype_opengles_glyph_move_out (sdl_freetype_area_manager_t * manager,
- sdl_freetype_area_t * area, void * closure)
+ sdl_freetype_area_t * area, void * closure)
{
sdl_freetype_opengles_user_data_t * user_data = closure;
user_data->area = NULL;
+ sdl_freetype_font_glyph_clear_user_data(user_data->font, user_data->index);
}
static int
sdl_freetype_opengles_glyph_compare_score (sdl_freetype_area_manager_t * manager,
- sdl_freetype_area_t * area,
- void * closure1, void * closure2)
+ sdl_freetype_area_t * area,
+ void * closure1, void * closure2)
{
sdl_freetype_opengles_user_data_t * user_data = closure1;
@@ -511,10 +540,10 @@ sdl_freetype_opengles_render_create (void)
render->usx = render->usy = 1.0;
render->width = render->height = GLYPH_CACHE_SIZE;
render->manager =
- sdl_freetype_area_manager_create (render->width,
- render->height,
- GLYPH_CACHE_LEVEL,
- &sdl_freetype_opengles_glyph_ops);
+ sdl_freetype_area_manager_create (render->width,
+ render->height,
+ GLYPH_CACHE_LEVEL,
+ &sdl_freetype_opengles_glyph_ops);
if (!render->manager)
goto errquit1;
@@ -534,7 +563,7 @@ sdl_freetype_opengles_render_create (void)
sdl_freetype_error_t
sdl_freetype_opengles_render_set_unit_scale (sdl_freetype_glyph_render_t * render,
- float sx, float sy)
+ float sx, float sy)
{
sdl_freetype_opengles_render_t * opengles_render =
(sdl_freetype_opengles_render_t *) render;