Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenfont/intern/blf_glyph.c')
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c230
1 files changed, 78 insertions, 152 deletions
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 80d43a49e77..8e88bda37a5 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -143,13 +143,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket));
- gc->textures = (GPUTexture **)MEM_callocN(sizeof(GPUTexture *) * 256, __func__);
- gc->textures_len = 256;
- gc->texture_current = BLF_TEXTURE_UNSET;
- gc->offset_x = 3; /* enough padding for blur */
- gc->offset_y = 3; /* enough padding for blur */
- gc->pad = 6;
-
gc->glyphs_len_max = (int)font->face->num_glyphs;
gc->glyphs_len_free = (int)font->face->num_glyphs;
gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f;
@@ -173,9 +166,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
CLAMP_MIN(gc->glyph_width_max, 1);
CLAMP_MIN(gc->glyph_height_max, 1);
- gc->p2_width = 0;
- gc->p2_height = 0;
-
BLI_addhead(&font->cache, gc);
return gc;
}
@@ -229,52 +219,13 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
blf_glyph_free(g);
}
}
- for (i = 0; i < gc->textures_len; i++) {
- if (gc->textures[i]) {
- GPU_texture_free(gc->textures[i]);
- }
+ if (gc->texture) {
+ GPU_texture_free(gc->texture);
}
- MEM_freeN(gc->textures);
- MEM_freeN(gc);
-}
-
-static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
-{
- int i;
- char error[256];
-
- /* move the index. */
- gc->texture_current++;
-
- if (UNLIKELY(gc->texture_current >= gc->textures_len)) {
- gc->textures_len *= 2;
- gc->textures = MEM_recallocN((void *)gc->textures, sizeof(GPUTexture *) * gc->textures_len);
- }
-
- gc->p2_width = (int)blf_next_p2(
- (unsigned int)((gc->glyphs_len_free * gc->glyph_width_max) + (gc->pad * 2)));
- if (gc->p2_width > font->tex_size_max) {
- gc->p2_width = font->tex_size_max;
+ if (gc->bitmap_result) {
+ MEM_freeN(gc->bitmap_result);
}
-
- i = (int)((gc->p2_width - (gc->pad * 2)) / gc->glyph_width_max);
- gc->p2_height = (int)blf_next_p2(
- (unsigned int)(((gc->glyphs_len_max / i) + 1) * gc->glyph_height_max + (gc->pad * 2)));
-
- if (gc->p2_height > font->tex_size_max) {
- gc->p2_height = font->tex_size_max;
- }
-
- GPUTexture *tex = GPU_texture_create_nD(
- gc->p2_width, gc->p2_height, 0, 2, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, error);
-
- GPU_texture_bind(tex, 0);
- GPU_texture_wrap_mode(tex, false);
- GPU_texture_filters(tex, GPU_NEAREST, GPU_LINEAR);
- GPU_texture_clear(tex, GPU_DATA_UNSIGNED_BYTE, NULL);
- GPU_texture_unbind(tex);
-
- gc->textures[gc->texture_current] = tex;
+ MEM_freeN(gc);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -377,8 +328,6 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
g->c = c;
g->idx = (FT_UInt)index;
- g->offset_x = -1;
- g->offset_y = -1;
bitmap = slot->bitmap;
g->width = (int)bitmap.width;
g->height = (int)bitmap.rows;
@@ -418,17 +367,19 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
void blf_glyph_free(GlyphBLF *g)
{
- /* don't need free the texture, the GlyphCache already
- * have a list of all the texture and free it.
- */
if (g->bitmap) {
MEM_freeN(g->bitmap);
}
MEM_freeN(g);
}
-static void blf_texture_draw(
- const unsigned char color[4], const float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture_draw(const unsigned char color[4],
+ const int glyph_size[2],
+ const int offset,
+ float x1,
+ float y1,
+ float x2,
+ float y2)
{
/* Only one vertex per glyph, geometry shader expand it into a quad. */
/* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
@@ -437,8 +388,10 @@ static void blf_texture_draw(
y1 + g_batch.ofs[1],
x2 + g_batch.ofs[0],
y2 + g_batch.ofs[1]);
- copy_v4_v4(GPU_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
copy_v4_v4_uchar(GPU_vertbuf_raw_step(&g_batch.col_step), color);
+ copy_v2_v2_int(GPU_vertbuf_raw_step(&g_batch.glyph_size_step), glyph_size);
+ *((int *)GPU_vertbuf_raw_step(&g_batch.offset_step)) = offset;
+
g_batch.glyph_len++;
/* Flush cache if it's full. */
if (g_batch.glyph_len == BLF_BATCH_DRAW_LEN_MAX) {
@@ -447,45 +400,35 @@ static void blf_texture_draw(
}
static void blf_texture5_draw(const unsigned char color_in[4],
- int tex_w,
- int tex_h,
- const float uv[2][2],
+ const int glyph_size[2],
+ const int offset,
float x1,
float y1,
float x2,
float y2)
{
- float ofs[2] = {2 / (float)tex_w, 2 / (float)tex_h};
- float uv_flag[2][2];
- copy_v4_v4((float *)uv_flag, (float *)uv);
+ int glyph_size_flag[2];
/* flag the x and y component signs for 5x5 blurring */
- uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
- uv_flag[0][1] = -(uv_flag[0][1] - ofs[1]);
- uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
- uv_flag[1][1] = -(uv_flag[1][1] + ofs[1]);
+ glyph_size_flag[0] = -glyph_size[0];
+ glyph_size_flag[1] = -glyph_size[1];
- blf_texture_draw(color_in, uv_flag, x1 - 2, y1 + 2, x2 + 2, y2 - 2);
+ blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
}
static void blf_texture3_draw(const unsigned char color_in[4],
- int tex_w,
- int tex_h,
- const float uv[2][2],
+ const int glyph_size[2],
+ const int offset,
float x1,
float y1,
float x2,
float y2)
{
- float ofs[2] = {1 / (float)tex_w, 1 / (float)tex_h};
- float uv_flag[2][2];
- copy_v4_v4((float *)uv_flag, (float *)uv);
+ int glyph_size_flag[2];
/* flag the x component sign for 3x3 blurring */
- uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
- uv_flag[0][1] = (uv_flag[0][1] - ofs[1]);
- uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
- uv_flag[1][1] = (uv_flag[1][1] + ofs[1]);
+ glyph_size_flag[0] = -glyph_size[0];
+ glyph_size_flag[1] = glyph_size[1];
- blf_texture_draw(color_in, uv_flag, x1 - 1, y1 + 1, x2 + 1, y2 - 1);
+ blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -518,63 +461,38 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
return;
}
- if (g->build_tex == 0) {
+ if (!g->cached) {
if (font->tex_size_max == -1) {
font->tex_size_max = GPU_max_texture_size();
}
- if (gc->texture_current == BLF_TEXTURE_UNSET) {
- blf_glyph_cache_texture(font, gc);
- gc->offset_x = gc->pad;
- gc->offset_y = 3; /* enough padding for blur */
- }
+ g->offset = gc->bitmap_len;
- if (gc->offset_x > (gc->p2_width - gc->glyph_width_max)) {
- gc->offset_x = gc->pad;
- gc->offset_y += gc->glyph_height_max;
+ int buff_size = g->width * g->height;
+ int bitmap_len = gc->bitmap_len + buff_size;
- if (gc->offset_y > (gc->p2_height - gc->glyph_height_max)) {
- gc->offset_y = 3; /* enough padding for blur */
- blf_glyph_cache_texture(font, gc);
- }
- }
+ if (bitmap_len > gc->bitmap_len_alloc) {
+ int w = font->tex_size_max;
+ int h = bitmap_len / w + 1;
- g->tex = gc->textures[gc->texture_current];
- g->offset_x = gc->offset_x;
- g->offset_y = gc->offset_y;
+ gc->bitmap_len_alloc = w * h;
+ gc->bitmap_result = MEM_reallocN(gc->bitmap_result, (size_t)gc->bitmap_len_alloc);
- /* prevent glTexSubImage2D from failing if the character
- * asks for pixels out of bounds, this tends only to happen
- * with very small sizes (5px high or less) */
- if (UNLIKELY((g->offset_x + g->width) > gc->p2_width)) {
- g->width -= (g->offset_x + g->width) - gc->p2_width;
- BLI_assert(g->width > 0);
- }
- if (UNLIKELY((g->offset_y + g->height) > gc->p2_height)) {
- g->height -= (g->offset_y + g->height) - gc->p2_height;
- BLI_assert(g->height > 0);
- }
-
- GPU_texture_update_sub(g->tex,
- GPU_DATA_UNSIGNED_BYTE,
- g->bitmap,
- g->offset_x,
- g->offset_y,
- 0,
- g->width,
- g->height,
- 0);
+ /* Keep in sync with the texture. */
+ if (gc->texture) {
+ GPU_texture_free(gc->texture);
+ }
+ gc->texture = GPU_texture_create_nD(
+ w, h, 0, 1, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, NULL);
- g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width);
- g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height);
- g->uv[1][0] = ((float)(g->offset_x + g->width)) / ((float)gc->p2_width);
- g->uv[1][1] = ((float)(g->offset_y + g->height)) / ((float)gc->p2_height);
+ gc->bitmap_len_landed = 0;
+ }
- /* update the x offset for the next glyph. */
- gc->offset_x += (int)BLI_rctf_size_x(&g->box) + gc->pad;
+ memcpy(&gc->bitmap_result[gc->bitmap_len], g->bitmap, (size_t)buff_size);
+ gc->bitmap_len = bitmap_len;
gc->glyphs_len_free--;
- g->build_tex = 1;
+ g->cached = true;
}
if (font->flags & BLF_CLIPPING) {
@@ -587,27 +505,26 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
}
}
- if (font->tex_bind_state != g->tex) {
- blf_batch_draw();
- font->tex_bind_state = g->tex;
- GPU_texture_bind(font->tex_bind_state, 0);
- }
-
- g_batch.tex_bind_state = g->tex;
+ g_batch.glyph_cache = gc;
+ BLI_assert(g->offset < gc->bitmap_len);
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
blf_glyph_calc_rect_shadow(&rect_ofs, g, x, y, font);
if (font->shadow == 0) {
- blf_texture_draw(
- font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ blf_texture_draw(font->shadow_color,
+ (int[2]){g->width, g->height},
+ g->offset,
+ rect_ofs.xmin,
+ rect_ofs.ymin,
+ rect_ofs.xmax,
+ rect_ofs.ymax);
}
else if (font->shadow <= 4) {
blf_texture3_draw(font->shadow_color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect_ofs.xmin,
rect_ofs.ymin,
rect_ofs.xmax,
@@ -615,9 +532,8 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
}
else {
blf_texture5_draw(font->shadow_color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect_ofs.xmin,
rect_ofs.ymin,
rect_ofs.xmax,
@@ -632,9 +548,8 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
switch (font->blur) {
case 3:
blf_texture3_draw(font->color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect.xmin,
rect.ymin,
rect.xmax,
@@ -642,18 +557,29 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl
break;
case 5:
blf_texture5_draw(font->color,
- gc->p2_width,
- gc->p2_height,
- g->uv,
+ (int[2]){g->width, g->height},
+ g->offset,
rect.xmin,
rect.ymin,
rect.xmax,
rect.ymax);
break;
default:
- blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture_draw(font->color,
+ (int[2]){g->width, g->height},
+ g->offset,
+ rect.xmin,
+ rect.ymin,
+ rect.xmax,
+ rect.ymax);
}
#else
- blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture_draw(font->color,
+ (int[2]){g->width, g->height},
+ g->offset,
+ rect.xmin,
+ rect.ymin,
+ rect.xmax,
+ rect.ymax);
#endif
}