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')
-rw-r--r--source/blender/blenfont/BLF_api.h40
-rw-r--r--source/blender/blenfont/intern/blf.c252
-rw-r--r--source/blender/blenfont/intern/blf_font.c241
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c193
-rw-r--r--source/blender/blenfont/intern/blf_internal.h8
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h46
6 files changed, 558 insertions, 222 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index f31c132c973..3466f1665c6 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -35,6 +35,9 @@
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"
+/* enable this only if needed (unused circa 2016) */
+#define BLF_BLUR_ENABLE 0
+
struct rctf;
struct ColorManagedDisplay;
struct ResultBLF;
@@ -43,6 +46,8 @@ int BLF_init(void);
void BLF_exit(void);
void BLF_default_dpi(int dpi);
void BLF_default_set(int fontid);
+int BLF_default(void); /* get default font ID so we can pass it to other functions */
+void BLF_batch_reset(void); /* call when changing opengl context. */
void BLF_antialias_set(bool enabled);
bool BLF_antialias_get(void);
@@ -65,6 +70,17 @@ void BLF_aspect(int fontid, float x, float y, float z);
void BLF_position(int fontid, float x, float y, float z);
void BLF_size(int fontid, int size, int dpi);
+/* goal: small but useful color API */
+void BLF_color4ubv(int fontid, const unsigned char rgba[4]);
+void BLF_color3ubv(int fontid, const unsigned char rgb[3]);
+void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha);
+void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b);
+void BLF_color4f(int fontid, float r, float g, float b, float a);
+void BLF_color4fv(int fontid, const float rgba[4]);
+void BLF_color3f(int fontid, float r, float g, float b);
+void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha);
+/* also available: UI_FontThemeColor(fontid, colorid) */
+
/* Set a 4x4 matrix to be multiplied before draw the text.
* Remember that you need call BLF_enable(BLF_MATRIX)
* to enable this.
@@ -79,6 +95,11 @@ void BLF_size(int fontid, int size, int dpi);
*/
void BLF_matrix(int fontid, const float m[16]);
+/* Batch drawcalls together as long as
+ * the modelview matrix and the font remain unchanged. */
+void BLF_batch_draw_begin(void);
+void BLF_batch_draw_end(void);
+
/* Draw the string using the default font, size and dpi. */
void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
@@ -126,29 +147,16 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt
*/
float BLF_fixed_width(int fontid) ATTR_WARN_UNUSED_RESULT;
-/* and this two function return the width and height
- * of the string, using the default font and both value
- * are multiplied by the aspect of the font.
- */
-void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height) ATTR_NONNULL();
-float BLF_width_default(const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-float BLF_height_default(const char *str, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-
-/* Set rotation for default font. */
-void BLF_rotation_default(float angle);
-
-/* Enable/disable options to the default font. */
-void BLF_enable_default(int option);
-void BLF_disable_default(int option);
-
/* By default, rotation and clipping are disable and
* have to be enable/disable using BLF_enable/disable.
*/
void BLF_rotation(int fontid, float angle);
void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax);
-void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax);
void BLF_wordwrap(int fontid, int wrap_width);
+
+#if BLF_BLUR_ENABLE
void BLF_blur(int fontid, int size);
+#endif
void BLF_enable(int fontid, int option);
void BLF_disable(int fontid, int option);
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 38c1498d76b..b94c6e35823 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -50,13 +50,14 @@
#include "BLI_math.h"
#include "BLI_threads.h"
-#include "BIF_gl.h"
#include "BLF_api.h"
#include "IMB_colormanagement.h"
#ifndef BLF_STANDALONE
-#include "GPU_basic_shader.h"
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
+#include "GPU_immediate.h"
#endif
#include "blf_internal_types.h"
@@ -131,6 +132,11 @@ void BLF_exit(void)
blf_font_exit();
}
+void BLF_batch_reset(void)
+{
+ blf_batch_draw_vao_clear();
+}
+
void BLF_cache_clear(void)
{
FontBLF *font;
@@ -138,8 +144,10 @@ void BLF_cache_clear(void)
for (i = 0; i < BLF_MAX_FONT; i++) {
font = global_font[i];
- if (font)
+ if (font) {
blf_glyph_cache_clear(font);
+ blf_kerning_cache_clear(font);
+ }
}
}
@@ -176,6 +184,12 @@ void BLF_default_set(int fontid)
}
}
+int BLF_default(void)
+{
+ ASSERT_DEFAULT_SET;
+ return global_font_default;
+}
+
void BLF_antialias_set(bool enabled)
{
global_use_antialias = enabled;
@@ -369,24 +383,6 @@ void BLF_disable(int fontid, int option)
}
}
-void BLF_enable_default(int option)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->flags |= option;
- }
-}
-
-void BLF_disable_default(int option)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->flags &= ~option;
- }
-}
-
void BLF_aspect(int fontid, float x, float y, float z)
{
FontBLF *font = blf_get(fontid);
@@ -465,6 +461,7 @@ void BLF_size(int fontid, int size, int dpi)
}
}
+#if BLF_BLUR_ENABLE
void BLF_blur(int fontid, int size)
{
FontBLF *font = blf_get(fontid);
@@ -473,6 +470,90 @@ void BLF_blur(int fontid, int size)
font->blur = size;
}
}
+#endif
+
+void BLF_color4ubv(int fontid, const unsigned char rgba[4])
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->color[0] = rgba[0];
+ font->color[1] = rgba[1];
+ font->color[2] = rgba[2];
+ font->color[3] = rgba[3];
+ }
+}
+
+void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha)
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->color[0] = rgb[0];
+ font->color[1] = rgb[1];
+ font->color[2] = rgb[2];
+ font->color[3] = alpha;
+ }
+}
+
+void BLF_color3ubv(int fontid, const unsigned char rgb[3])
+{
+ BLF_color3ubv_alpha(fontid, rgb, 255);
+}
+
+void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b)
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ font->color[0] = r;
+ font->color[1] = g;
+ font->color[2] = b;
+ font->color[3] = 255;
+ }
+}
+
+void BLF_color4fv(int fontid, const float rgba[4])
+{
+ FontBLF *font = blf_get(fontid);
+
+ if (font) {
+ rgba_float_to_uchar(font->color, rgba);
+ }
+}
+
+void BLF_color4f(int fontid, float r, float g, float b, float a)
+{
+ float rgba[4] = { r, g, b, a };
+ BLF_color4fv(fontid, rgba);
+}
+
+void BLF_color3fv_alpha(int fontid, const float rgb[3], float alpha)
+{
+ float rgba[4];
+ copy_v3_v3(rgba, rgb);
+ rgba[3] = alpha;
+ BLF_color4fv(fontid, rgba);
+}
+
+void BLF_color3f(int fontid, float r, float g, float b)
+{
+ float rgba[4] = { r, g, b, 1.0f };
+ BLF_color4fv(fontid, rgba);
+}
+
+void BLF_batch_draw_begin(void)
+{
+ BLI_assert(g_batch.enabled == false);
+ g_batch.enabled = true;
+}
+
+void BLF_batch_draw_end(void)
+{
+ BLI_assert(g_batch.enabled == true);
+ blf_batch_draw(); /* Draw remaining glyphs */
+ g_batch.enabled = false;
+}
void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
{
@@ -493,72 +574,37 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l
BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
}
-void BLF_rotation_default(float angle)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->angle = angle;
- }
-}
-
-static void blf_draw_gl__start(FontBLF *font, GLint *mode)
+static void blf_draw_gl__start(FontBLF *font)
{
/*
* The pixmap alignment hack is handle
* in BLF_position (old ui_rasterpos_safe).
*/
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-#ifndef BLF_STANDALONE
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
-#endif
-
- /* Save the current matrix mode. */
- glGetIntegerv(GL_MATRIX_MODE, mode);
+ /* always bind the texture for the first glyph */
+ font->tex_bind_state = 0;
- glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glLoadIdentity();
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0)
+ return; /* glyphs will be translated individually and batched. */
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gpuPushMatrix();
if (font->flags & BLF_MATRIX)
- glMultMatrixf(font->m);
+ gpuMultMatrix(font->m);
- glTranslate3fv(font->pos);
+ gpuTranslate3fv(font->pos);
if (font->flags & BLF_ASPECT)
- glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
-
- if (font->flags & BLF_ROTATION) /* radians -> degrees */
- glRotatef(font->angle * (float)(180.0 / M_PI), 0.0f, 0.0f, 1.0f);
+ gpuScale3fv(font->aspect);
- if (font->shadow || font->blur)
- glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
-
- /* always bind the texture for the first glyph */
- font->tex_bind_state = -1;
+ if (font->flags & BLF_ROTATION)
+ gpuRotate2D(RAD2DEG(font->angle));
}
-static void blf_draw_gl__end(GLint mode)
+static void blf_draw_gl__end(FontBLF *font)
{
- glMatrixMode(GL_TEXTURE);
- glPopMatrix();
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- if (mode != GL_MODELVIEW)
- glMatrixMode(mode);
-
-#ifndef BLF_STANDALONE
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-#endif
- glDisable(GL_BLEND);
+ if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) != 0)
+ gpuPopMatrix();
}
void BLF_draw_ex(
@@ -566,23 +612,26 @@ void BLF_draw_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
blf_font_draw__wrap(font, str, len, r_info);
}
else {
blf_font_draw(font, str, len, r_info);
}
- blf_draw_gl__end(mode);
+ blf_draw_gl__end(font);
}
}
void BLF_draw(int fontid, const char *str, size_t len)
{
+ if (len == 0 || str[0] == '\0') {
+ return;
+ }
+
BLF_draw_ex(fontid, str, len, NULL);
}
@@ -591,12 +640,11 @@ void BLF_draw_ascii_ex(
struct ResultBLF *r_info)
{
FontBLF *font = blf_get(fontid);
- GLint mode;
BLF_RESULT_CHECK_INIT(r_info);
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
if (font->flags & BLF_WORD_WRAP) {
/* use non-ascii draw function for word-wrap */
blf_font_draw__wrap(font, str, len, r_info);
@@ -604,24 +652,31 @@ void BLF_draw_ascii_ex(
else {
blf_font_draw_ascii(font, str, len, r_info);
}
- blf_draw_gl__end(mode);
+ blf_draw_gl__end(font);
}
}
void BLF_draw_ascii(int fontid, const char *str, size_t len)
{
+ if (len == 0 || str[0] == '\0') {
+ return;
+ }
+
BLF_draw_ascii_ex(fontid, str, len, NULL);
}
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
{
+ if (len == 0 || str[0] == '\0') {
+ return 0;
+ }
+
FontBLF *font = blf_get(fontid);
- GLint mode;
int columns = 0;
if (font && font->glyph_cache) {
- blf_draw_gl__start(font, &mode);
+ blf_draw_gl__start(font);
columns = blf_font_draw_mono(font, str, len, cwidth);
- blf_draw_gl__end(mode);
+ blf_draw_gl__end(font);
}
return columns;
@@ -701,14 +756,6 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt
}
}
-void BLF_width_and_height_default(const char *str, size_t len, float *r_width, float *r_height)
-{
- ASSERT_DEFAULT_SET;
-
- BLF_size(global_font_default, global_font_points, global_font_dpi);
- BLF_width_and_height(global_font_default, str, len, r_width, r_height);
-}
-
float BLF_width_ex(
int fontid, const char *str, size_t len,
struct ResultBLF *r_info)
@@ -739,14 +786,6 @@ float BLF_fixed_width(int fontid)
return 0.0f;
}
-float BLF_width_default(const char *str, size_t len)
-{
- ASSERT_DEFAULT_SET;
-
- BLF_size(global_font_default, global_font_points, global_font_dpi);
- return BLF_width(global_font_default, str, len);
-}
-
float BLF_height_ex(
int fontid, const char *str, size_t len,
struct ResultBLF *r_info)
@@ -810,15 +849,6 @@ float BLF_ascender(int fontid)
return 0.0f;
}
-float BLF_height_default(const char *str, size_t len)
-{
- ASSERT_DEFAULT_SET;
-
- BLF_size(global_font_default, global_font_points, global_font_dpi);
-
- return BLF_height(global_font_default, str, len);
-}
-
void BLF_rotation(int fontid, float angle)
{
FontBLF *font = blf_get(fontid);
@@ -840,18 +870,6 @@ void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
}
}
-void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
-{
- FontBLF *font = blf_get(global_font_default);
-
- if (font) {
- font->clip_rec.xmin = xmin;
- font->clip_rec.ymin = ymin;
- font->clip_rec.xmax = xmax;
- font->clip_rec.ymax = ymax;
- }
-}
-
void BLF_wordwrap(int fontid, int wrap_width)
{
FontBLF *font = blf_get(fontid);
@@ -867,7 +885,7 @@ void BLF_shadow(int fontid, int level, const float rgba[4])
if (font) {
font->shadow = level;
- copy_v4_v4(font->shadow_col, rgba);
+ rgba_float_to_uchar(font->shadow_color, rgba);
}
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index af0c2fab7dd..07e568dd279 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -58,6 +58,10 @@
#include "BIF_gl.h"
#include "BLF_api.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
+
#include "blf_internal_types.h"
#include "blf_internal.h"
@@ -67,12 +71,154 @@
# define FT_New_Face FT_New_Face__win32_compat
#endif
+/* Batching buffer for drawing. */
+BatchBLF g_batch;
+
/* freetype2 handle ONLY for this file!. */
static FT_Library ft_lib;
static SpinLock ft_lib_mutex;
+/* -------------------------------------------------------------------- */
+/** \name Glyph Batching
+ * \{ */
+/**
+ * Drawcalls are precious! make them count!
+ * Since most of the Text elems are not covered by other UI elements, we can
+ * group some strings together and render them in one drawcall. This behaviour
+ * is on demand only, between BLF_batch_start() and BLF_batch_end().
+ **/
+static void blf_batch_draw_init(void)
+{
+ Gwn_VertFormat format = {0};
+ g_batch.pos_loc = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ g_batch.tex_loc = GWN_vertformat_attr_add(&format, "tex", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+ g_batch.col_loc = GWN_vertformat_attr_add(&format, "col", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
+
+ g_batch.verts = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STREAM);
+ GWN_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX);
+
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ g_batch.glyph_len = 0;
+
+ g_batch.batch = GWN_batch_create_ex(GWN_PRIM_POINTS, g_batch.verts, NULL, GWN_BATCH_OWNS_VBO);
+}
+
+static void blf_batch_draw_exit(void)
+{
+ GWN_BATCH_DISCARD_SAFE(g_batch.batch);
+}
+
+void blf_batch_draw_vao_clear(void)
+{
+ if (g_batch.batch) {
+ gwn_batch_vao_cache_clear(g_batch.batch);
+ }
+}
+
+void blf_batch_draw_begin(FontBLF *font)
+{
+ if (g_batch.batch == NULL) {
+ blf_batch_draw_init();
+ }
+
+ const bool font_changed = (g_batch.font != font);
+ const bool simple_shader = ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0);
+ const bool shader_changed = (simple_shader != g_batch.simple_shader);
+
+ g_batch.active = g_batch.enabled && simple_shader;
+
+ if (simple_shader) {
+ /* Offset is applied to each glyph. */
+ copy_v2_v2(g_batch.ofs, font->pos);
+ }
+ else {
+ /* Offset is baked in modelview mat. */
+ zero_v2(g_batch.ofs);
+ }
+
+ if (g_batch.active) {
+ float gpumat[4][4];
+ gpuGetModelViewMatrix(gpumat);
+
+ bool mat_changed = (memcmp(gpumat, g_batch.mat, sizeof(g_batch.mat)) != 0);
+
+ if (mat_changed) {
+ /* Modelviewmat is no longer the same.
+ * Flush cache but with the previous mat. */
+ gpuPushMatrix();
+ gpuLoadMatrix(g_batch.mat);
+ }
+
+ /* flush cache if config is not the same. */
+ if (mat_changed || font_changed || shader_changed) {
+ blf_batch_draw();
+ g_batch.simple_shader = simple_shader;
+ g_batch.font = font;
+ }
+ else {
+ /* Nothing changed continue batching. */
+ return;
+ }
+
+ if (mat_changed) {
+ gpuPopMatrix();
+ /* Save for next memcmp. */
+ memcpy(g_batch.mat, gpumat, sizeof(g_batch.mat));
+ }
+ }
+ else {
+ /* flush cache */
+ blf_batch_draw();
+ g_batch.font = font;
+ g_batch.simple_shader = simple_shader;
+ }
+}
+
+void blf_batch_draw(void)
+{
+ if (g_batch.glyph_len == 0)
+ return;
+
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ BLI_assert(g_batch.font->tex_bind_state != 0); /* must still be valid */
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, g_batch.font->tex_bind_state);
+
+ GWN_vertbuf_vertex_count_set(g_batch.verts, g_batch.glyph_len);
+ GWN_vertbuf_use(g_batch.verts); /* send data */
+
+ GPUBuiltinShader shader = (g_batch.simple_shader) ? GPU_SHADER_TEXT_SIMPLE : GPU_SHADER_TEXT;
+ GWN_batch_program_set_builtin(g_batch.batch, shader);
+ GWN_batch_uniform_1i(g_batch.batch, "glyph", 0);
+ GWN_batch_draw(g_batch.batch);
+
+ glDisable(GL_BLEND);
+
+ /* restart to 1st vertex data pointers */
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step);
+ g_batch.glyph_len = 0;
+}
+
+static void blf_batch_draw_end(void)
+{
+ if (!g_batch.active) {
+ blf_batch_draw();
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
int blf_font_init(void)
{
+ memset(&g_batch, 0, sizeof(g_batch));
BLI_spin_init(&ft_lib_mutex);
return FT_Init_FreeType(&ft_lib);
}
@@ -81,6 +227,7 @@ void blf_font_exit(void)
{
FT_Done_FreeType(ft_lib);
BLI_spin_end(&ft_lib_mutex);
+ blf_batch_draw_exit();
}
void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
@@ -88,6 +235,14 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
GlyphCacheBLF *gc;
FT_Error err;
+ gc = blf_glyph_cache_find(font, size, dpi);
+ if (gc) {
+ font->glyph_cache = gc;
+ /* Optimization: do not call FT_Set_Char_Size if size did not change. */
+ if (font->size == size && font->dpi == dpi)
+ return;
+ }
+
err = FT_Set_Char_Size(font->face, 0, (FT_F26Dot6)(size * 64), dpi, dpi);
if (err) {
/* FIXME: here we can go through the fixed size and choice a close one */
@@ -98,10 +253,7 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
font->size = size;
font->dpi = dpi;
- gc = blf_glyph_cache_find(font, size, dpi);
- if (gc)
- font->glyph_cache = gc;
- else {
+ if (!gc) {
gc = blf_glyph_cache_new(font);
if (gc)
font->glyph_cache = gc;
@@ -129,6 +281,20 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
}
}
+static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode)
+{
+ KerningCacheBLF *kc = font->kerning_cache;
+
+ font->kerning_mode = kern_mode;
+
+ if (!kc || kc->mode != kern_mode) {
+ font->kerning_cache = kc = blf_kerning_cache_find(font);
+ if (!kc) {
+ font->kerning_cache = kc = blf_kerning_cache_new(font);
+ }
+ }
+}
+
/* Fast path for runs of ASCII characters. Given that common UTF-8
* input will consist of an overwhelming majority of ASCII
* characters.
@@ -156,6 +322,26 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
(((_font)->flags & BLF_KERNING_DEFAULT) ? \
ft_kerning_default : (FT_UInt)FT_KERNING_UNFITTED) \
+/* Note,
+ * blf_font_ensure_ascii_kerning(font, kern_mode); must be called before this macro */
+
+#define BLF_KERNING_STEP_FAST(_font, _kern_mode, _g_prev, _g, _c_prev, _c, _pen_x) \
+{ \
+ if (_g_prev) { \
+ FT_Vector _delta; \
+ if (_c_prev < 0x80 && _c < 0x80) { \
+ _pen_x += (_font)->kerning_cache->table[_c][_c_prev]; \
+ } \
+ else if (FT_Get_Kerning((_font)->face, \
+ (_g_prev)->idx, \
+ (_g)->idx, \
+ _kern_mode, \
+ &(_delta)) == 0) \
+ { \
+ _pen_x += (int)_delta.x >> 6; \
+ } \
+ } \
+} (void)0
#define BLF_KERNING_STEP(_font, _kern_mode, _g_prev, _g, _delta, _pen_x) \
{ \
@@ -176,16 +362,23 @@ static void blf_font_draw_ex(
FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c;
+ unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
- FT_Vector delta;
int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+ if (len == 0) {
+ /* early output, don't do any IMM OpenGL. */
+ return;
+ }
+
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
+ blf_font_ensure_ascii_kerning(font, kern_mode);
+
+ blf_batch_draw_begin(font);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -195,15 +388,18 @@ static void blf_font_draw_ex(
if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
- BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+ BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
/* do not return this loop if clipped, we want every character tested */
blf_glyph_render(font, g, (float)pen_x, (float)pen_y);
pen_x += g->advance_i;
g_prev = g;
+ c_prev = c;
}
+ blf_batch_draw_end();
+
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
@@ -229,6 +425,8 @@ static void blf_font_draw_ascii_ex(
blf_font_ensure_ascii_table(font);
+ blf_batch_draw_begin(font);
+
while ((c = *(str++)) && len--) {
BLI_assert(c < 128);
if ((g = glyph_ascii_table[c]) == NULL)
@@ -243,6 +441,8 @@ static void blf_font_draw_ascii_ex(
g_prev = g;
}
+ blf_batch_draw_end();
+
if (r_info) {
r_info->lines = 1;
r_info->width = pen_x;
@@ -265,6 +465,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
blf_font_ensure_ascii_table(font);
+ blf_batch_draw_begin(font);
+
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -284,6 +486,8 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
pen_x += cwidth * col;
}
+ blf_batch_draw_end();
+
return columns;
}
@@ -570,9 +774,8 @@ static void blf_font_boundbox_ex(
FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info,
int pen_y)
{
- unsigned int c;
+ unsigned int c, c_prev = BLI_UTF8_ERR;
GlyphBLF *g, *g_prev = NULL;
- FT_Vector delta;
int pen_x = 0;
size_t i = 0;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
@@ -587,6 +790,7 @@ static void blf_font_boundbox_ex(
box->ymax = -32000.0f;
blf_font_ensure_ascii_table(font);
+ blf_font_ensure_ascii_kerning(font, kern_mode);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
@@ -596,7 +800,7 @@ static void blf_font_boundbox_ex(
if (UNLIKELY(g == NULL))
continue;
if (has_kerning)
- BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+ BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x);
gbox.xmin = (float)pen_x;
gbox.xmax = (float)pen_x + g->advance;
@@ -611,6 +815,7 @@ static void blf_font_boundbox_ex(
pen_x += g->advance_i;
g_prev = g;
+ c_prev = c;
}
if (box->xmin > box->xmax) {
@@ -891,6 +1096,8 @@ void blf_font_free(FontBLF *font)
blf_glyph_cache_free(gc);
}
+ blf_kerning_cache_clear(font);
+
FT_Done_Face(font->face);
if (font->filename)
MEM_freeN(font->filename);
@@ -901,8 +1108,6 @@ void blf_font_free(FontBLF *font)
static void blf_font_fill(FontBLF *font)
{
- unsigned int i;
-
font->aspect[0] = 1.0f;
font->aspect[1] = 1.0f;
font->aspect[2] = 1.0f;
@@ -910,9 +1115,15 @@ static void blf_font_fill(FontBLF *font)
font->pos[1] = 0.0f;
font->angle = 0.0f;
- for (i = 0; i < 16; i++)
+ for (int i = 0; i < 16; i++)
font->m[i] = 0;
+ /* annoying bright color so we can see where to add BLF_color calls */
+ font->color[0] = 255;
+ font->color[1] = 255;
+ font->color[2] = 0;
+ font->color[3] = 255;
+
font->clip_rec.xmin = 0.0f;
font->clip_rec.xmax = 0.0f;
font->clip_rec.ymin = 0.0f;
@@ -921,8 +1132,12 @@ static void blf_font_fill(FontBLF *font)
font->dpi = 0;
font->size = 0;
BLI_listbase_clear(&font->cache);
+ BLI_listbase_clear(&font->kerning_caches);
font->glyph_cache = NULL;
+ font->kerning_cache = NULL;
+#if BLF_BLUR_ENABLE
font->blur = 0;
+#endif
font->tex_size_max = -1;
font->buf_info.fbuf = NULL;
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 60dfdae519b..6183b54ebcc 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"
#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)
{
@@ -186,18 +242,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
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);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, gc->p2_width, gc->p2_height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
}
GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
@@ -325,79 +370,74 @@ 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], 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], 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];
+ unsigned char color[4];
float dx, dy;
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
-
+ color[0] = color_in[0];
+ color[1] = color_in[1];
+ color[2] = color_in[2];
+
+ const float alpha_in = (1 / 255.0f) * color_in[3];
+
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);
+ color[3] = FTOCHAR(*fp * alpha_in);
+ blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
}
}
-
- glColor4fv(color);
}
-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], 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];
+ unsigned char color[4];
float dx, dy;
- color[0] = shadow_col[0];
- color[1] = shadow_col[1];
- color[2] = shadow_col[2];
+ color[0] = color_in[0];
+ color[1] = color_in[1];
+ color[2] = color_in[2];
+
+ const float alpha_in = (1 / 255.0f) * color_in[3];
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);
+ color[3] = FTOCHAR(*fp * alpha_in);
+ blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
}
}
-
- glColor4fv(color);
}
static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -415,6 +455,8 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
if ((!g->width) || (!g->height))
return;
+ glActiveTexture(GL_TEXTURE0);
+
if (g->build_tex == 0) {
GlyphCacheBLF *gc = font->glyph_cache;
@@ -454,14 +496,21 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
}
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ GLint lsb_first, row_length, alignment;
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsb_first);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
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();
+ glTexSubImage2D(GL_TEXTURE_2D, 0, g->offset_x, g->offset_y, g->width, g->height, GL_RED, GL_UNSIGNED_BYTE, g->bitmap);
+
+ glPixelStorei(GL_UNPACK_LSB_FIRST, lsb_first);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width);
g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height);
@@ -491,39 +540,37 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex));
}
+ /* TODO: blur & shadow in shader, single quad per glyph */
+
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, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+ }
+ else {
+ blf_texture5_draw(font->shadow_color, 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, 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, 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
}
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index d9d758ce548..b48bd2fbae7 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -37,6 +37,10 @@ struct GlyphBLF;
struct GlyphCacheBLF;
struct rctf;
+void blf_batch_draw_vao_clear(void);
+void blf_batch_draw_begin(struct FontBLF *font);
+void blf_batch_draw(void);
+
unsigned int blf_next_p2(unsigned int x);
unsigned int blf_hash(unsigned int val);
@@ -74,6 +78,10 @@ int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const si
void blf_font_free(struct FontBLF *font);
+struct KerningCacheBLF *blf_kerning_cache_find(struct FontBLF *font);
+struct KerningCacheBLF *blf_kerning_cache_new(struct FontBLF *font);
+void blf_kerning_cache_clear(struct FontBLF *font);
+
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, unsigned int size, unsigned int dpi);
struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
void blf_glyph_cache_clear(struct FontBLF *font);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index ced8064302b..af2dc8a66e9 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -31,6 +31,35 @@
#ifndef __BLF_INTERNAL_TYPES_H__
#define __BLF_INTERNAL_TYPES_H__
+#include "../../../intern/gawain/gawain/gwn_vertex_buffer.h"
+
+#define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */
+
+typedef struct BatchBLF{
+ struct FontBLF *font; /* can only batch glyph from the same font */
+ struct Gwn_Batch *batch;
+ struct Gwn_VertBuf *verts;
+ struct Gwn_VertBufRaw pos_step, tex_step, col_step;
+ unsigned int pos_loc, tex_loc, col_loc;
+ unsigned int glyph_len;
+ float ofs[2]; /* copy of font->pos */
+ float mat[4][4]; /* previous call modelmatrix. */
+ bool enabled, active, simple_shader;
+} BatchBLF;
+
+extern BatchBLF g_batch;
+
+typedef struct KerningCacheBLF {
+ struct KerningCacheBLF *next, *prev;
+
+ /* kerning mode. */
+ FT_UInt mode;
+
+ /* only cache a ascii glyph pairs. Only store the x
+ * offset we are interested in, instead of the full FT_Vector. */
+ int table[0x80][0x80];
+} KerningCacheBLF;
+
typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *next;
struct GlyphCacheBLF *prev;
@@ -175,8 +204,10 @@ typedef struct FontBLF {
/* angle in radians. */
float angle;
+#if 0 /* BLF_BLUR_ENABLE */
/* blur: 3 or 5 large kernel */
int blur;
+#endif
/* shadow level. */
int shadow;
@@ -186,10 +217,10 @@ typedef struct FontBLF {
int shadow_y;
/* shadow color. */
- float shadow_col[4];
+ unsigned char shadow_color[4];
- /* store color here when drawing shadow or blur. */
- float orig_col[4];
+ /* main text color. */
+ unsigned char color[4];
/* Multiplied this matrix with the current one before
* draw the text! see blf_draw__start.
@@ -223,6 +254,12 @@ typedef struct FontBLF {
/* current glyph cache, size and dpi. */
GlyphCacheBLF *glyph_cache;
+ /* list of kerning cache for this font. */
+ ListBase kerning_caches;
+
+ /* current kerning cache for this font and kerning mode. */
+ KerningCacheBLF *kerning_cache;
+
/* freetype2 lib handle. */
FT_Library ft_lib;
@@ -232,6 +269,9 @@ typedef struct FontBLF {
/* freetype2 face. */
FT_Face face;
+ /* freetype kerning */
+ FT_UInt kerning_mode;
+
/* data for buffer usage (drawing into a texture buffer) */
FontBufInfoBLF buf_info;
} FontBLF;