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.c269
1 files changed, 144 insertions, 125 deletions
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 9af347908e1..84388bedb7b 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -56,13 +56,69 @@
#include "BLF_api.h"
#ifndef BLF_STANDALONE
-# include "GPU_basic_shader.h"
+# include "GPU_immediate.h"
+# include "GPU_extensions.h"
#endif
#include "blf_internal_types.h"
#include "blf_internal.h"
#include "BLI_strict_flags.h"
+#include "BLI_math_vector.h"
+
+KerningCacheBLF *blf_kerning_cache_find(FontBLF *font)
+{
+ KerningCacheBLF *p;
+
+ p = (KerningCacheBLF *)font->kerning_caches.first;
+ while (p) {
+ if (p->mode == font->kerning_mode)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+/* Create a new glyph cache for the current kerning mode. */
+KerningCacheBLF *blf_kerning_cache_new(FontBLF *font)
+{
+ KerningCacheBLF *kc;
+
+ kc = (KerningCacheBLF *)MEM_callocN(sizeof(KerningCacheBLF), "blf_kerning_cache_new");
+ kc->next = NULL;
+ kc->prev = NULL;
+ kc->mode = font->kerning_mode;
+
+ unsigned int i, j;
+ for (i = 0; i < 0x80; i++) {
+ for (j = 0; j < 0x80; j++) {
+ GlyphBLF *g = blf_glyph_search(font->glyph_cache, i);
+ if (!g) {
+ FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
+ g = blf_glyph_add(font, glyph_index, i);
+ }
+ /* Cannot fail since it has been added just before. */
+ GlyphBLF *g_prev = blf_glyph_search(font->glyph_cache, j);
+
+ FT_Vector delta = {.x = 0, .y = 0};
+ if (FT_Get_Kerning(font->face, g_prev->idx, g->idx, kc->mode, &delta) == 0) {
+ kc->table[i][j] = (int)delta.x >> 6;
+ }
+ else {
+ kc->table[i][j] = 0;
+ }
+ }
+ }
+
+ BLI_addhead(&font->kerning_caches, kc);
+ return kc;
+}
+
+void blf_kerning_cache_clear(FontBLF *font)
+{
+ font->kerning_cache = NULL;
+ BLI_freelistN(&font->kerning_caches);
+}
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
{
@@ -91,12 +147,12 @@ 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 = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__);
+ gc->textures = (GPUTexture **)MEM_callocN(sizeof(GPUTexture *) * 256, __func__);
gc->textures_len = 256;
gc->texture_current = BLF_TEXTURE_UNSET;
- gc->offset_x = 0;
- gc->offset_y = 0;
- gc->pad = 3;
+ 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;
@@ -141,16 +197,17 @@ void blf_glyph_cache_clear(FontBLF *font)
void blf_glyph_cache_free(GlyphCacheBLF *gc)
{
GlyphBLF *g;
- int i;
+ unsigned int i;
for (i = 0; i < 257; i++) {
while ((g = BLI_pophead(&gc->bucket[i]))) {
blf_glyph_free(g);
}
}
-
- if (gc->texture_current != BLF_TEXTURE_UNSET) {
- glDeleteTextures((int)gc->texture_current + 1, gc->textures);
+ for (i = 0; i < gc->textures_len; i++) {
+ if (gc->textures[i]) {
+ GPU_texture_free(gc->textures[i]);
+ }
}
MEM_freeN(gc->textures);
MEM_freeN(gc);
@@ -159,13 +216,14 @@ void blf_glyph_cache_free(GlyphCacheBLF *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_reallocN((void *)gc->textures, sizeof(GLuint) * gc->textures_len);
+ 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)));
@@ -174,30 +232,20 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
}
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->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;
}
- glGenTextures(1, &gc->textures[gc->texture_current]);
- glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = gc->textures[gc->texture_current]));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
-#ifndef BLF_STANDALONE
- /* needed since basic shader doesn't support alpha-only textures,
- * while we could add support this is only used in a few places
- * (an alternative could be to have a simple shader for BLF). */
- if (GLEW_ARB_texture_swizzle && GPU_basic_shader_use_glsl_get()) {
- GLint swizzle_mask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA};
- glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzle_mask);
- }
-#endif
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA8, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, NULL);
+ unsigned char *pixels = MEM_callocN((size_t)gc->p2_width * (size_t)gc->p2_height, "BLF texture init");
+ GPUTexture *tex = GPU_texture_create_2D(gc->p2_width, gc->p2_height, GPU_R8, (const float *)pixels, error);
+ MEM_freeN(pixels);
+ gc->textures[gc->texture_current] = tex;
+ GPU_texture_bind(tex, 0);
+ GPU_texture_wrap_mode(tex, false);
+ GPU_texture_filters(tex, GPU_NEAREST, GPU_LINEAR);
+ GPU_texture_unbind(tex);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -296,8 +344,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
}
}
- g->bitmap = (unsigned char *)MEM_mallocN((size_t)(g->width * g->height), "glyph bitmap");
- memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)(g->width * g->height));
+ g->bitmap = (unsigned char *)MEM_mallocN((size_t)g->width * (size_t)g->height, "glyph bitmap");
+ memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)g->width * (size_t)g->height);
}
g->advance = ((float)slot->advance.x) / 64.0f;
@@ -325,79 +373,54 @@ 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) {
+ if (g->bitmap)
MEM_freeN(g->bitmap);
- }
MEM_freeN(g);
}
-static void blf_texture_draw(float uv[2][2], float dx, float y1, float dx1, float y2)
+static void blf_texture_draw(const unsigned char color[4], const float uv[2][2], float x1, float y1, float x2, float y2)
{
- glBegin(GL_QUADS);
- glTexCoord2f(uv[0][0], uv[0][1]);
- glVertex2f(dx, y1);
-
- glTexCoord2f(uv[0][0], uv[1][1]);
- glVertex2f(dx, y2);
-
- glTexCoord2f(uv[1][0], uv[1][1]);
- glVertex2f(dx1, y2);
-
- glTexCoord2f(uv[1][0], uv[0][1]);
- glVertex2f(dx1, y1);
- glEnd();
+ /* 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 */
+ copy_v4_fl4(GWN_vertbuf_raw_step(&g_batch.pos_step), x1 + g_batch.ofs[0], y1 + g_batch.ofs[1],
+ x2 + g_batch.ofs[0], y2 + g_batch.ofs[1]);
+ copy_v4_v4(GWN_vertbuf_raw_step(&g_batch.tex_step), (float *)uv);
+ copy_v4_v4_uchar(GWN_vertbuf_raw_step(&g_batch.col_step), color);
+ g_batch.glyph_len++;
+ /* Flush cache if it's full. */
+ if (g_batch.glyph_len == BLF_BATCH_DRAW_LEN_MAX) {
+ blf_batch_draw();
+ }
}
-static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const unsigned char color_in[4], int tex_w, int tex_h, const float uv[2][2],
+ float x1, float y1, float x2, float y2)
{
- const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
- 1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
- 2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
- 1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
- 1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
-
- const float *fp = soft;
- float color[4];
- float dx, dy;
-
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
-
- for (dx = -2; dx < 3; dx++) {
- for (dy = -2; dy < 3; dy++, fp++) {
- color[3] = *(fp) * shadow_col[3];
- glColor4fv(color);
- blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
- }
- }
-
- glColor4fv(color);
+ float ofs[2] = { 2 / (float)tex_w, 2 / (float)tex_h };
+ float uv_flag[2][2];
+ copy_v4_v4((float *)uv_flag, (float *)uv);
+ /* flag the x and y component signs for 5x5 bluring */
+ 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]);
+
+ blf_texture_draw(color_in, uv_flag, x1 - 2, y1 + 2, x2 + 2, y2 - 2);
}
-static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const unsigned char color_in[4], int tex_w, int tex_h, const float uv[2][2],
+ float x1, float y1, float x2, float y2)
{
- const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
- 2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
- 1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
-
- const float *fp = soft;
- float color[4];
- float dx, dy;
-
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
-
- for (dx = -1; dx < 2; dx++) {
- for (dy = -1; dy < 2; dy++, fp++) {
- color[3] = *(fp) * shadow_col[3];
- glColor4fv(color);
- blf_texture_draw(uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
- }
- }
-
- glColor4fv(color);
+ float ofs[2] = { 1 / (float)tex_w, 1 / (float)tex_h };
+ float uv_flag[2][2];
+ copy_v4_v4((float *)uv_flag, (float *)uv);
+ /* flag the x component sign for 3x3 bluring */
+ 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]);
+
+ blf_texture_draw(color_in, uv_flag, x1 - 1, y1 + 1, x2 + 1, y2 - 1);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -419,12 +442,12 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
GlyphCacheBLF *gc = font->glyph_cache;
if (font->tex_size_max == -1)
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->tex_size_max);
+ 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 = 0;
+ gc->offset_y = 3; /* enough padding for blur */
}
if (gc->offset_x > (gc->p2_width - gc->glyph_width_max)) {
@@ -432,7 +455,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
gc->offset_y += gc->glyph_height_max;
if (gc->offset_y > (gc->p2_height - gc->glyph_height_max)) {
- gc->offset_y = 0;
+ gc->offset_y = 3; /* enough padding for blur */
blf_glyph_cache_texture(font, gc);
}
}
@@ -453,15 +476,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
BLI_assert(g->height > 0);
}
-
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
- glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
- glBindTexture(GL_TEXTURE_2D, g->tex);
- glTexSubImage2D(GL_TEXTURE_2D, 0, g->offset_x, g->offset_y, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap);
- glPopClientAttrib();
+ GPU_texture_update_sub(g->tex, g->bitmap, g->offset_x, g->offset_y, 0, g->width, g->height, 0);
g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width);
g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height);
@@ -488,42 +503,46 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
}
if (font->tex_bind_state != g->tex) {
- glBindTexture(GL_TEXTURE_2D, (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;
+
if (font->flags & BLF_SHADOW) {
rctf rect_ofs;
blf_glyph_calc_rect(&rect_ofs, g,
x + (float)font->shadow_x,
y + (float)font->shadow_y);
- switch (font->shadow) {
- case 3:
- blf_texture3_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
- case 5:
- blf_texture5_draw(font->shadow_col, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
- default:
- glColor4fv(font->shadow_col);
- blf_texture_draw(g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
- break;
+ if (font->shadow == 0) {
+ blf_texture_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else if (font->shadow <= 4) {
+ blf_texture3_draw(font->shadow_color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else {
+ blf_texture5_draw(font->shadow_color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
}
-
- glColor4fv(font->orig_col);
}
+#if BLF_BLUR_ENABLE
switch (font->blur) {
case 3:
- blf_texture3_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture3_draw(font->color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
case 5:
- blf_texture5_draw(font->orig_col, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ blf_texture5_draw(font->color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+ rect.xmin, rect.ymin, rect.xmax, rect.ymax);
break;
default:
- blf_texture_draw(g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
- break;
+ blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
}
-
- return;
+#else
+ blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+#endif
}