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/intern/blf.c1
-rw-r--r--source/blender/blenfont/intern/blf_font.c671
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c50
-rw-r--r--source/blender/blenfont/intern/blf_internal.h4
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h9
5 files changed, 378 insertions, 357 deletions
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 9168e7aa19c..2f9eb0753ac 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -108,7 +108,6 @@ void BLF_cache_clear(void)
FontBLF *font = global_font[i];
if (font) {
blf_glyph_cache_clear(font);
- blf_kerning_cache_clear(font);
}
}
}
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 00d3cfb09eb..75a2e893119 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -72,6 +72,38 @@ static SpinLock ft_lib_mutex;
static SpinLock blf_glyph_cache_mutex;
/* -------------------------------------------------------------------- */
+/** \name FreeType Utilities (Internal)
+ * \{ */
+
+/**
+ * Convert a FreeType 26.6 value representing an unscaled design size to pixels.
+ * This is an exact copy of the scaling done inside FT_Get_Kerning when called
+ * with #FT_KERNING_DEFAULT, including arbitrary resizing for small fonts.
+ */
+static int blf_unscaled_F26Dot6_to_pixels(FontBLF *font, FT_Pos value)
+{
+ /* Scale value by font size using integer-optimized multiplication. */
+ FT_Long scaled = FT_MulFix(value, font->face->size->metrics.x_scale);
+
+ /* FreeType states that this '25' has been determined heuristically. */
+ if (font->face->size->metrics.x_ppem < 25) {
+ scaled = FT_MulDiv(scaled, font->face->size->metrics.x_ppem, 25);
+ }
+
+ /* Copies of internal FreeType macros needed here. */
+#define FT_PIX_FLOOR(x) ((x) & ~63)
+#define FT_PIX_ROUND(x) FT_PIX_FLOOR((x) + 32)
+
+ /* Round to even 64ths, then divide by 64. */
+ return (int)FT_PIX_ROUND(scaled) >> 6;
+
+#undef FT_PIX_FLOOR
+#undef FT_PIX_ROUND
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Glyph Batching
* \{ */
@@ -257,67 +289,8 @@ static void blf_batch_draw_end(void)
/** \} */
/* -------------------------------------------------------------------- */
-
-int blf_font_init(void)
-{
- memset(&g_batch, 0, sizeof(g_batch));
- BLI_spin_init(&ft_lib_mutex);
- BLI_spin_init(&blf_glyph_cache_mutex);
- return FT_Init_FreeType(&ft_lib);
-}
-
-void blf_font_exit(void)
-{
- FT_Done_FreeType(ft_lib);
- BLI_spin_end(&ft_lib_mutex);
- BLI_spin_end(&blf_glyph_cache_mutex);
- blf_batch_draw_exit();
-}
-
-void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
-{
- GlyphCacheBLF *gc;
- FT_Error err;
-
- blf_glyph_cache_acquire(font);
-
- gc = blf_glyph_cache_find(font, size, dpi);
- if (gc) {
- /* Optimization: do not call FT_Set_Char_Size if size did not change. */
- if (font->size == size && font->dpi == dpi) {
- blf_glyph_cache_release(font);
- 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 */
- printf("The current font don't support the size, %u and dpi, %u\n", size, dpi);
-
- blf_glyph_cache_release(font);
- return;
- }
-
- font->size = size;
- font->dpi = dpi;
-
- if (!gc) {
- blf_glyph_cache_new(font);
- }
- blf_glyph_cache_release(font);
-}
-
-static void blf_font_ensure_ascii_kerning(FontBLF *font, GlyphCacheBLF *gc)
-{
- if (font->kerning_cache || !FT_HAS_KERNING(font->face)) {
- return;
- }
- font->kerning_cache = blf_kerning_cache_find(font);
- if (!font->kerning_cache) {
- font->kerning_cache = blf_kerning_cache_new(font, gc);
- }
-}
+/** \name Glyph Stepping Utilities (Internal)
+ * \{ */
/* Fast path for runs of ASCII characters. Given that common UTF-8
* input will consist of an overwhelming majority of ASCII
@@ -355,22 +328,40 @@ BLI_INLINE void blf_kerning_step_fast(FontBLF *font,
const uint c,
int *pen_x_p)
{
- /* `blf_font_ensure_ascii_kerning(font, gc);` must be called before this function. */
- BLI_assert(font->kerning_cache != NULL || !FT_HAS_KERNING(font->face));
+ if (!FT_HAS_KERNING(font->face) || g_prev == NULL) {
+ return;
+ }
- if (g_prev != NULL && FT_HAS_KERNING(font->face)) {
- if ((c_prev < KERNING_CACHE_TABLE_SIZE) && (c < GLYPH_ASCII_TABLE_SIZE)) {
- *pen_x_p += font->kerning_cache->ascii_table[c][c_prev];
- }
- else {
- FT_Vector delta;
- if (FT_Get_Kerning(font->face, g_prev->idx, g->idx, FT_KERNING_DEFAULT, &delta) == 0) {
- *pen_x_p += (int)delta.x >> 6;
- }
- }
+ FT_Vector delta = {KERNING_ENTRY_UNSET};
+
+ /* Get unscaled kerning value from our cache if ASCII. */
+ if ((c_prev < KERNING_CACHE_TABLE_SIZE) && (c < GLYPH_ASCII_TABLE_SIZE)) {
+ delta.x = font->kerning_cache->ascii_table[c][c_prev];
+ }
+
+ /* If not ASCII or not found in cache, ask FreeType for kerning. */
+ if (UNLIKELY(delta.x == KERNING_ENTRY_UNSET)) {
+ /* Note that this function sets delta values to zero on any error. */
+ FT_Get_Kerning(font->face, g_prev->idx, g->idx, FT_KERNING_UNSCALED, &delta);
+ }
+
+ /* If ASCII we save this value to our cache for quicker access next time. */
+ if ((c_prev < KERNING_CACHE_TABLE_SIZE) && (c < GLYPH_ASCII_TABLE_SIZE)) {
+ font->kerning_cache->ascii_table[c][c_prev] = (int)delta.x;
+ }
+
+ if (delta.x != 0) {
+ /* Convert unscaled design units to pixels and move pen. */
+ *pen_x_p += blf_unscaled_F26Dot6_to_pixels(font, delta.x);
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Text Drawing: GPU
+ * \{ */
+
static void blf_font_draw_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
@@ -388,8 +379,6 @@ static void blf_font_draw_ex(FontBLF *font,
return;
}
- blf_font_ensure_ascii_kerning(font, gc);
-
blf_batch_draw_begin(font);
while ((i < len) && str[i]) {
@@ -435,8 +424,6 @@ static void blf_font_draw_ascii_ex(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_kerning(font, gc);
-
blf_batch_draw_begin(font);
while ((c = *(str++)) && len--) {
@@ -515,6 +502,12 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth)
return columns;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Text Drawgin: Buffer
+ * \{ */
+
/* Sanity checks are done by BLF_draw_buffer() */
static void blf_font_draw_buffer_ex(FontBLF *font,
GlyphCacheBLF *gc,
@@ -536,8 +529,6 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
int chx, chy;
int y, x;
- blf_font_ensure_ascii_kerning(font, gc);
-
/* another buffer specific call for color conversion */
while ((i < len) && str[i]) {
@@ -662,6 +653,16 @@ void blf_font_draw_buffer(FontBLF *font, const char *str, size_t len, struct Res
blf_glyph_cache_release(font);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Text Evaluation: Width to Sting Length
+ *
+ * Use to implement exported functions:
+ * - #BLF_width_to_strlen
+ * - #BLF_width_to_rstrlen
+ * \{ */
+
static bool blf_font_width_to_strlen_glyph_process(FontBLF *font,
const uint c_prev,
const uint c,
@@ -694,8 +695,6 @@ size_t blf_font_width_to_strlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
- blf_font_ensure_ascii_kerning(font, gc);
-
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < len) && str[i];
i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
@@ -725,8 +724,6 @@ size_t blf_font_width_to_rstrlen(
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
const int width_i = (int)width;
- blf_font_ensure_ascii_kerning(font, gc);
-
i = BLI_strnlen(str, len);
s = BLI_str_find_prev_char_utf8(str, &str[i]);
i = (size_t)((s != NULL) ? s - str : 0);
@@ -759,6 +756,12 @@ size_t blf_font_width_to_rstrlen(
return i;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Text Evaluation: Glyph Bound Box with Callback
+ * \{ */
+
static void blf_font_boundbox_ex(FontBLF *font,
GlyphCacheBLF *gc,
const char *str,
@@ -778,8 +781,6 @@ static void blf_font_boundbox_ex(FontBLF *font,
box->ymin = 32000.0f;
box->ymax = -32000.0f;
- blf_font_ensure_ascii_kerning(font, gc);
-
while ((i < len) && str[i]) {
g = blf_utf8_next_fast(font, gc, str, &i, &c);
@@ -835,8 +836,165 @@ void blf_font_boundbox(
blf_glyph_cache_release(font);
}
+void blf_font_width_and_height(FontBLF *font,
+ const char *str,
+ size_t len,
+ float *r_width,
+ float *r_height,
+ struct ResultBLF *r_info)
+{
+ float xa, ya;
+ rctf box;
+
+ if (font->flags & BLF_ASPECT) {
+ xa = font->aspect[0];
+ ya = font->aspect[1];
+ }
+ else {
+ xa = 1.0f;
+ ya = 1.0f;
+ }
+
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
+ *r_width = (BLI_rctf_size_x(&box) * xa);
+ *r_height = (BLI_rctf_size_y(&box) * ya);
+}
+
+float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ float xa;
+ rctf box;
+
+ if (font->flags & BLF_ASPECT) {
+ xa = font->aspect[0];
+ }
+ else {
+ xa = 1.0f;
+ }
+
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
+ return BLI_rctf_size_x(&box) * xa;
+}
+
+float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+{
+ float ya;
+ rctf box;
+
+ if (font->flags & BLF_ASPECT) {
+ ya = font->aspect[1];
+ }
+ else {
+ ya = 1.0f;
+ }
+
+ if (font->flags & BLF_WORD_WRAP) {
+ blf_font_boundbox__wrap(font, str, len, &box, r_info);
+ }
+ else {
+ blf_font_boundbox(font, str, len, &box, r_info);
+ }
+ return BLI_rctf_size_y(&box) * ya;
+}
+
+float blf_font_fixed_width(FontBLF *font)
+{
+ const unsigned int c = ' ';
+
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+ GlyphBLF *g = blf_glyph_search(gc, c);
+ if (!g) {
+ g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, c), c);
+
+ /* if we don't find the glyph. */
+ if (!g) {
+ blf_glyph_cache_release(font);
+ return 0.0f;
+ }
+ }
+
+ blf_glyph_cache_release(font);
+ return g->advance;
+}
+
+static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
+ GlyphCacheBLF *gc,
+ const char *str,
+ size_t len,
+ BLF_GlyphBoundsFn user_fn,
+ void *user_data,
+ struct ResultBLF *r_info,
+ int pen_y)
+{
+ unsigned int c, c_prev = BLI_UTF8_ERR;
+ GlyphBLF *g, *g_prev = NULL;
+ int pen_x = 0;
+ size_t i = 0, i_curr;
+ rcti gbox;
+
+ if (len == 0) {
+ /* early output. */
+ return;
+ }
+
+ while ((i < len) && str[i]) {
+ i_curr = i;
+ g = blf_utf8_next_fast(font, gc, str, &i, &c);
+
+ if (UNLIKELY(c == BLI_UTF8_ERR)) {
+ break;
+ }
+ if (UNLIKELY(g == NULL)) {
+ continue;
+ }
+ blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+
+ gbox.xmin = pen_x;
+ gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->dims[0]);
+ gbox.ymin = pen_y;
+ gbox.ymax = gbox.ymin - g->dims[1];
+
+ pen_x += g->advance_i;
+
+ if (user_fn(str, i_curr, &gbox, g->advance_i, &g->box, g->pos, user_data) == false) {
+ break;
+ }
+
+ g_prev = g;
+ c_prev = c;
+ }
+
+ if (r_info) {
+ r_info->lines = 1;
+ r_info->width = pen_x;
+ }
+}
+void blf_font_boundbox_foreach_glyph(FontBLF *font,
+ const char *str,
+ size_t len,
+ BLF_GlyphBoundsFn user_fn,
+ void *user_data,
+ struct ResultBLF *r_info)
+{
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+ blf_font_boundbox_foreach_glyph_ex(font, gc, str, len, user_fn, user_data, r_info, 0);
+ blf_glyph_cache_release(font);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
-/** \name Word-Wrap Support
+/** \name Text Evaluation: Word-Wrap with Callback
* \{ */
/**
@@ -869,8 +1027,6 @@ static void blf_font_wrap_apply(FontBLF *font,
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_ensure_ascii_kerning(font, gc);
-
struct WordWrapVars {
int wrap_width;
size_t start, last[2];
@@ -1008,216 +1164,120 @@ void blf_font_draw_buffer__wrap(FontBLF *font,
/** \} */
-void blf_font_width_and_height(FontBLF *font,
- const char *str,
- size_t len,
- float *r_width,
- float *r_height,
- struct ResultBLF *r_info)
+/* -------------------------------------------------------------------- */
+/** \name Text Evaluation: Count Missing Characters
+ * \{ */
+
+int blf_font_count_missing_chars(FontBLF *font,
+ const char *str,
+ const size_t len,
+ int *r_tot_chars)
{
- float xa, ya;
- rctf box;
+ int missing = 0;
+ size_t i = 0;
- if (font->flags & BLF_ASPECT) {
- xa = font->aspect[0];
- ya = font->aspect[1];
- }
- else {
- xa = 1.0f;
- ya = 1.0f;
- }
+ *r_tot_chars = 0;
+ while (i < len) {
+ unsigned int c;
- if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, &box, r_info);
- }
- else {
- blf_font_boundbox(font, str, len, &box, r_info);
+ if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {
+ i++;
+ }
+ else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
+ if (FT_Get_Char_Index((font)->face, c) == 0) {
+ missing++;
+ }
+ }
+ (*r_tot_chars)++;
}
- *r_width = (BLI_rctf_size_x(&box) * xa);
- *r_height = (BLI_rctf_size_y(&box) * ya);
+ return missing;
}
-float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
-{
- float xa;
- rctf box;
-
- if (font->flags & BLF_ASPECT) {
- xa = font->aspect[0];
- }
- else {
- xa = 1.0f;
- }
+/** \} */
- if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, &box, r_info);
- }
- else {
- blf_font_boundbox(font, str, len, &box, r_info);
- }
- return BLI_rctf_size_x(&box) * xa;
-}
+/* -------------------------------------------------------------------- */
+/** \name Font Query: Attributes
+ * \{ */
-float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info)
+int blf_font_height_max(FontBLF *font)
{
- float ya;
- rctf box;
+ int height_max;
- if (font->flags & BLF_ASPECT) {
- ya = font->aspect[1];
- }
- else {
- ya = 1.0f;
- }
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+ height_max = gc->glyph_height_max;
- if (font->flags & BLF_WORD_WRAP) {
- blf_font_boundbox__wrap(font, str, len, &box, r_info);
- }
- else {
- blf_font_boundbox(font, str, len, &box, r_info);
- }
- return BLI_rctf_size_y(&box) * ya;
+ blf_glyph_cache_release(font);
+ return height_max;
}
-float blf_font_fixed_width(FontBLF *font)
+int blf_font_width_max(FontBLF *font)
{
- const unsigned int c = ' ';
+ int width_max;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- GlyphBLF *g = blf_glyph_search(gc, c);
- if (!g) {
- g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, c), c);
-
- /* if we don't find the glyph. */
- if (!g) {
- blf_glyph_cache_release(font);
- return 0.0f;
- }
- }
+ width_max = gc->glyph_width_max;
blf_glyph_cache_release(font);
- return g->advance;
+ return width_max;
}
-/* -------------------------------------------------------------------- */
-/** \name Glyph Bound Box with Callback
- * \{ */
-
-static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
- GlyphCacheBLF *gc,
- const char *str,
- size_t len,
- BLF_GlyphBoundsFn user_fn,
- void *user_data,
- struct ResultBLF *r_info,
- int pen_y)
+float blf_font_descender(FontBLF *font)
{
- unsigned int c, c_prev = BLI_UTF8_ERR;
- GlyphBLF *g, *g_prev = NULL;
- int pen_x = 0;
- size_t i = 0, i_curr;
- rcti gbox;
-
- if (len == 0) {
- /* early output. */
- return;
- }
-
- blf_font_ensure_ascii_kerning(font, gc);
-
- while ((i < len) && str[i]) {
- i_curr = i;
- g = blf_utf8_next_fast(font, gc, str, &i, &c);
-
- if (UNLIKELY(c == BLI_UTF8_ERR)) {
- break;
- }
- if (UNLIKELY(g == NULL)) {
- continue;
- }
- blf_kerning_step_fast(font, g_prev, g, c_prev, c, &pen_x);
+ float descender;
- gbox.xmin = pen_x;
- gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->dims[0]);
- gbox.ymin = pen_y;
- gbox.ymax = gbox.ymin - g->dims[1];
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+ descender = gc->descender;
- pen_x += g->advance_i;
+ blf_glyph_cache_release(font);
+ return descender;
+}
- if (user_fn(str, i_curr, &gbox, g->advance_i, &g->box, g->pos, user_data) == false) {
- break;
- }
+float blf_font_ascender(FontBLF *font)
+{
+ float ascender;
- g_prev = g;
- c_prev = c;
- }
+ GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
+ ascender = gc->ascender;
- if (r_info) {
- r_info->lines = 1;
- r_info->width = pen_x;
- }
+ blf_glyph_cache_release(font);
+ return ascender;
}
-void blf_font_boundbox_foreach_glyph(FontBLF *font,
- const char *str,
- size_t len,
- BLF_GlyphBoundsFn user_fn,
- void *user_data,
- struct ResultBLF *r_info)
+
+char *blf_display_name(FontBLF *font)
{
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- blf_font_boundbox_foreach_glyph_ex(font, gc, str, len, user_fn, user_data, r_info, 0);
- blf_glyph_cache_release(font);
+ if (!font->face->family_name) {
+ return NULL;
+ }
+ return BLI_sprintfN("%s %s", font->face->family_name, font->face->style_name);
}
/** \} */
-int blf_font_count_missing_chars(FontBLF *font,
- const char *str,
- const size_t len,
- int *r_tot_chars)
-{
- int missing = 0;
- size_t i = 0;
-
- *r_tot_chars = 0;
- while (i < len) {
- unsigned int c;
+/* -------------------------------------------------------------------- */
+/** \name Font Subsystem Init/Exit
+ * \{ */
- if ((c = str[i]) < GLYPH_ASCII_TABLE_SIZE) {
- i++;
- }
- else if ((c = BLI_str_utf8_as_unicode_step(str, &i)) != BLI_UTF8_ERR) {
- if (FT_Get_Char_Index((font)->face, c) == 0) {
- missing++;
- }
- }
- (*r_tot_chars)++;
- }
- return missing;
+int blf_font_init(void)
+{
+ memset(&g_batch, 0, sizeof(g_batch));
+ BLI_spin_init(&ft_lib_mutex);
+ BLI_spin_init(&blf_glyph_cache_mutex);
+ return FT_Init_FreeType(&ft_lib);
}
-void blf_font_free(FontBLF *font)
+void blf_font_exit(void)
{
- BLI_spin_lock(&blf_glyph_cache_mutex);
- GlyphCacheBLF *gc;
-
- while ((gc = BLI_pophead(&font->cache))) {
- blf_glyph_cache_free(gc);
- }
-
- blf_kerning_cache_clear(font);
+ FT_Done_FreeType(ft_lib);
+ BLI_spin_end(&ft_lib_mutex);
+ BLI_spin_end(&blf_glyph_cache_mutex);
+ blf_batch_draw_exit();
+}
- FT_Done_Face(font->face);
- if (font->filename) {
- MEM_freeN(font->filename);
- }
- if (font->name) {
- MEM_freeN(font->name);
- }
- MEM_freeN(font);
+/** \} */
- BLI_spin_unlock(&blf_glyph_cache_mutex);
-}
+/* -------------------------------------------------------------------- */
+/** \name Font New/Free
+ * \{ */
static void blf_font_fill(FontBLF *font)
{
@@ -1246,7 +1306,6 @@ 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->kerning_cache = NULL;
#if BLF_BLUR_ENABLE
font->blur = 0;
@@ -1307,6 +1366,17 @@ FontBLF *blf_font_new(const char *name, const char *filename)
font->name = BLI_strdup(name);
font->filename = BLI_strdup(filename);
blf_font_fill(font);
+
+ if (FT_HAS_KERNING(font->face)) {
+ /* Create kerning cache table and fill with value indicating "unset". */
+ font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
+ for (uint i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
+ for (uint j = 0; j < KERNING_CACHE_TABLE_SIZE; j++) {
+ font->kerning_cache->ascii_table[i][j] = KERNING_ENTRY_UNSET;
+ }
+ }
+ }
+
return font;
}
@@ -1346,54 +1416,61 @@ FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int m
return font;
}
-int blf_font_height_max(FontBLF *font)
+void blf_font_free(FontBLF *font)
{
- int height_max;
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- height_max = gc->glyph_height_max;
+ BLI_spin_lock(&blf_glyph_cache_mutex);
+ GlyphCacheBLF *gc;
- blf_glyph_cache_release(font);
- return height_max;
-}
+ while ((gc = BLI_pophead(&font->cache))) {
+ blf_glyph_cache_free(gc);
+ }
-int blf_font_width_max(FontBLF *font)
-{
- int width_max;
+ if (font->kerning_cache) {
+ MEM_freeN(font->kerning_cache);
+ }
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- width_max = gc->glyph_width_max;
+ FT_Done_Face(font->face);
+ if (font->filename) {
+ MEM_freeN(font->filename);
+ }
+ if (font->name) {
+ MEM_freeN(font->name);
+ }
+ MEM_freeN(font);
- blf_glyph_cache_release(font);
- return width_max;
+ BLI_spin_unlock(&blf_glyph_cache_mutex);
}
-float blf_font_descender(FontBLF *font)
-{
- float descender;
-
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- descender = gc->descender;
+/** \} */
- blf_glyph_cache_release(font);
- return descender;
-}
+/* -------------------------------------------------------------------- */
+/** \name Font Configure
+ * \{ */
-float blf_font_ascender(FontBLF *font)
+void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
{
- float ascender;
+ blf_glyph_cache_acquire(font);
- GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
- ascender = gc->ascender;
+ GlyphCacheBLF *gc = blf_glyph_cache_find(font, size, dpi);
+ if (gc && (font->size == size && font->dpi == dpi)) {
+ /* Optimization: do not call FT_Set_Char_Size if size did not change. */
+ }
+ else {
+ const FT_Error 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 */
+ printf("The current font don't support the size, %u and dpi, %u\n", size, dpi);
+ }
+ else {
+ font->size = size;
+ font->dpi = dpi;
+ if (gc == NULL) {
+ blf_glyph_cache_new(font);
+ }
+ }
+ }
blf_glyph_cache_release(font);
- return ascender;
}
-char *blf_display_name(FontBLF *font)
-{
- if (!font->face->family_name) {
- return NULL;
- }
- return BLI_sprintfN("%s %s", font->face->family_name, font->face->style_name);
-}
+/** \} */
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 5fb69251466..6cdf5fc5996 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -55,56 +55,6 @@
#include "BLI_math_vector.h"
#include "BLI_strict_flags.h"
-KerningCacheBLF *blf_kerning_cache_find(FontBLF *font)
-{
- return (KerningCacheBLF *)font->kerning_caches.first;
-}
-
-/* Create a new glyph cache for the current kerning mode. */
-KerningCacheBLF *blf_kerning_cache_new(FontBLF *font, GlyphCacheBLF *gc)
-{
- KerningCacheBLF *kc = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
- kc->next = NULL;
- kc->prev = NULL;
-
- GlyphBLF *g_table[KERNING_CACHE_TABLE_SIZE];
- for (uint i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
- GlyphBLF *g = blf_glyph_search(gc, i);
- if (UNLIKELY(g == NULL)) {
- FT_UInt glyph_index = FT_Get_Char_Index(font->face, i);
- g = blf_glyph_add(font, gc, glyph_index, i);
- }
- g_table[i] = g;
- }
-
- memset(kc->ascii_table, 0, sizeof(kc->ascii_table));
- for (uint i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
- GlyphBLF *g = g_table[i];
- if (g == NULL) {
- continue;
- }
- for (uint j = 0; j < KERNING_CACHE_TABLE_SIZE; j++) {
- GlyphBLF *g_prev = g_table[j];
- if (g_prev == NULL) {
- continue;
- }
- FT_Vector delta;
- if (FT_Get_Kerning(font->face, g_prev->idx, g->idx, FT_KERNING_DEFAULT, &delta) == 0) {
- kc->ascii_table[i][j] = (int)delta.x >> 6;
- }
- }
- }
-
- 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)
{
GlyphCacheBLF *p;
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 35a6d019eac..ab2a26b1e06 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -121,10 +121,6 @@ int blf_font_count_missing_chars(struct FontBLF *font,
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, struct GlyphCacheBLF *gc);
-void blf_kerning_cache_clear(struct FontBLF *font);
-
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font,
unsigned int size,
unsigned int dpi);
diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h
index caa10b2b125..38d7d7b6e21 100644
--- a/source/blender/blenfont/intern/blf_internal_types.h
+++ b/source/blender/blenfont/intern/blf_internal_types.h
@@ -34,6 +34,9 @@
/* Number of characters in KerningCacheBLF.table. */
#define KERNING_CACHE_TABLE_SIZE 128
+/* A value in the kerning cache that indicates it is not yet set. */
+#define KERNING_ENTRY_UNSET INT_MAX
+
typedef struct BatchBLF {
struct FontBLF *font; /* can only batch glyph from the same font */
struct GPUBatch *batch;
@@ -50,7 +53,6 @@ typedef struct BatchBLF {
extern BatchBLF g_batch;
typedef struct KerningCacheBLF {
- struct KerningCacheBLF *next, *prev;
/**
* Cache a ascii glyph pairs. Only store the x offset we are interested in,
* instead of the full #FT_Vector since it's not used for drawing at the moment.
@@ -223,10 +225,7 @@ typedef struct FontBLF {
*/
ListBase cache;
- /* list of kerning cache for this font. */
- ListBase kerning_caches;
-
- /* current kerning cache for this font and kerning mode. */
+ /* Cache of unscaled kerning values. Will be NULL if font does not have kerning. */
KerningCacheBLF *kerning_cache;
/* freetype2 lib handle. */