From 5aa78be7c9bb61766201d37993d99109d59e1892 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Tue, 5 Sep 2023 11:59:35 -0700 Subject: [PATCH 1/5] Updated to the current state of main. --- source/blender/blenfont/BLF_api.h | 2 + source/blender/blenfont/intern/blf_font.cc | 119 +++++++++--------- source/blender/blenfont/intern/blf_glyph.cc | 73 +++++++---- source/blender/blenfont/intern/blf_internal.h | 5 + .../blenfont/intern/blf_internal_types.h | 13 +- .../editors/interface/interface_widgets.cc | 2 +- 6 files changed, 120 insertions(+), 94 deletions(-) diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 152323a24f8..0c4ae5a6197 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -348,6 +348,8 @@ enum { BLF_BAD_FONT = 1 << 16, /** This font is managed by the FreeType cache subsystem. */ BLF_CACHED = 1 << 17, + /** For legacy DejaVu. No hinting and half-pixel too tight. */ + BLF_LEGACY_SPACING = 1 << 18, }; #define BLF_DRAW_STR_DUMMY_MAX 1024 diff --git a/source/blender/blenfont/intern/blf_font.cc b/source/blender/blenfont/intern/blf_font.cc index 03d714046c5..28fd34ed25b 100644 --- a/source/blender/blenfont/intern/blf_font.cc +++ b/source/blender/blenfont/intern/blf_font.cc @@ -356,25 +356,17 @@ static void blf_batch_draw_end() /** \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 - * characters. - */ - -BLI_INLINE GlyphBLF *blf_glyph_from_utf8_and_step( - FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p) -{ - uint charcode = BLI_str_utf8_as_unicode_step(str, str_len, i_p); - /* Invalid unicode sequences return the byte value, stepping forward one. - * This allows `latin1` to display (which is sometimes used for file-paths). */ - BLI_assert(charcode != BLI_UTF8_ERR); - return blf_glyph_ensure(font, gc, charcode); -} - BLI_INLINE ft_pix blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const GlyphBLF *g) { ft_pix adjustment = 0; + if (font->flags & BLF_LEGACY_SPACING) { + if (font->flags & BLF_HINTING_NONE || !g_prev || g_prev->c == ' ') { + return 0; + } + adjustment -= 32; + } + /* Small adjust if there is hinting. */ adjustment += g->lsb_delta - ((g_prev) ? g_prev->rsb_delta : 0); @@ -406,6 +398,35 @@ BLI_INLINE ft_pix blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const Glyph return adjustment; } +BLI_INLINE GlyphBLF *blf_glyph_from_utf8_and_step(FontBLF *font, + GlyphCacheBLF *gc, + GlyphBLF *g_prev, + const char *str, + size_t str_len, + size_t *i_p, + int32_t *pen_x) +{ + uint charcode = BLI_str_utf8_as_unicode_step(str, str_len, i_p); + /* Invalid unicode sequences return the byte value, stepping forward one. + * This allows `latin1` to display (which is sometimes used for file-paths). */ + BLI_assert(charcode != BLI_UTF8_ERR); + GlyphBLF *g = blf_glyph_ensure(font, gc, charcode); + if (g && pen_x && !(font->flags & BLF_MONOSPACED)) { + *pen_x += blf_kerning(font, g_prev, g); + g = blf_glyph_ensure_subpixel(font, gc, g, *pen_x); + } + return g; +} + +BLI_INLINE ft_pix blf_pen_advance(FontBLF *font, ft_pix v, ft_pix step) +{ + if (font->flags & BLF_LEGACY_SPACING && font->flags & BLF_HINTING_NONE) { + /* DejaVu with no hinting, so truncate pen position to match old spacing. */ + return (v + step) & ~63; + } + return v + step; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -419,7 +440,7 @@ static void blf_font_draw_ex(FontBLF *font, ResultBLF *r_info, const ft_pix pen_y) { - GlyphBLF *g, *g_prev = nullptr; + GlyphBLF *g = nullptr; ft_pix pen_x = 0; size_t i = 0; @@ -431,18 +452,13 @@ static void blf_font_draw_ex(FontBLF *font, blf_batch_draw_begin(font); while ((i < str_len) && str[i]) { - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); - + g = blf_glyph_from_utf8_and_step(font, gc, g, str, str_len, &i, &pen_x); if (UNLIKELY(g == nullptr)) { continue; } - pen_x += blf_kerning(font, g_prev, g); - /* do not return this loop if clipped, we want every character tested */ blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y)); - - pen_x = ft_pix_round_advance(pen_x, g->advance_x); - g_prev = g; + pen_x = blf_pen_advance(font, pen_x, g->advance_x); } blf_batch_draw_end(); @@ -473,7 +489,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int blf_batch_draw_begin(font); while ((i < str_len) && str[i]) { - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); + g = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i, nullptr); if (UNLIKELY(g == nullptr)) { continue; @@ -620,7 +636,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, ResultBLF *r_info, ft_pix pen_y) { - GlyphBLF *g, *g_prev = nullptr; + GlyphBLF *g = nullptr; ft_pix pen_x = ft_pix_from_int(font->pos[0]); ft_pix pen_y_basis = ft_pix_from_int(font->pos[1]) + pen_y; size_t i = 0; @@ -631,17 +647,13 @@ static void blf_font_draw_buffer_ex(FontBLF *font, /* another buffer specific call for color conversion */ while ((i < str_len) && str[i]) { - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); + g = blf_glyph_from_utf8_and_step(font, gc, g, str, str_len, &i, &pen_x); if (UNLIKELY(g == nullptr)) { continue; } - pen_x += blf_kerning(font, g_prev, g); - blf_glyph_draw_buffer(buf_info, g, pen_x, pen_y_basis); - - pen_x = ft_pix_round_advance(pen_x, g->advance_x); - g_prev = g; + pen_x = blf_pen_advance(font, pen_x, g->advance_x); } if (r_info) { @@ -674,7 +686,7 @@ static bool blf_font_width_to_strlen_glyph_process( return false; /* continue the calling loop. */ } *pen_x += blf_kerning(font, g_prev, g); - *pen_x = ft_pix_round_advance(*pen_x, g->advance_x); + *pen_x = blf_pen_advance(font, *pen_x, g->advance_x); /* When true, break the calling loop. */ return (ft_pix_to_int(*pen_x) >= width_i); @@ -694,8 +706,7 @@ size_t blf_font_width_to_strlen( for (i_prev = i = 0, width_new = pen_x = 0, g_prev = nullptr; (i < str_len) && str[i]; i_prev = i, width_new = pen_x, g_prev = g) { - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); - + g = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i, nullptr); if (blf_font_width_to_strlen_glyph_process(font, g_prev, g, &pen_x, width_i)) { break; } @@ -726,7 +737,7 @@ size_t blf_font_width_to_rstrlen( i_prev = size_t(s_prev - str); i_tmp = i; - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i_tmp); + g = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i_tmp, nullptr); for (width_new = pen_x = 0; (s != nullptr); i = i_prev, s = s_prev, g = g_prev, g_prev = nullptr, width_new = pen_x) { @@ -735,7 +746,7 @@ size_t blf_font_width_to_rstrlen( if (s_prev != nullptr) { i_tmp = i_prev; - g_prev = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i_tmp); + g_prev = blf_glyph_from_utf8_and_step(font, gc, nullptr, str, str_len, &i_tmp, nullptr); BLI_assert(i_tmp == i); } @@ -766,7 +777,7 @@ static void blf_font_boundbox_ex(FontBLF *font, ResultBLF *r_info, ft_pix pen_y) { - GlyphBLF *g, *g_prev = nullptr; + GlyphBLF *g = nullptr; ft_pix pen_x = 0; size_t i = 0; @@ -776,13 +787,12 @@ static void blf_font_boundbox_ex(FontBLF *font, ft_pix box_ymax = ft_pix_from_int(-32000); while ((i < str_len) && str[i]) { - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); + g = blf_glyph_from_utf8_and_step(font, gc, g, str, str_len, &i, &pen_x); if (UNLIKELY(g == nullptr)) { continue; } - pen_x += blf_kerning(font, g_prev, g); - const ft_pix pen_x_next = ft_pix_round_advance(pen_x, g->advance_x); + const ft_pix pen_x_next = blf_pen_advance(font, pen_x, g->advance_x); const ft_pix gbox_xmin = pen_x; const ft_pix gbox_xmax = pen_x_next; @@ -804,7 +814,6 @@ static void blf_font_boundbox_ex(FontBLF *font, } pen_x = pen_x_next; - g_prev = g; } if (box_xmin > box_xmax) { @@ -917,7 +926,7 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font, BLF_GlyphBoundsFn user_fn, void *user_data) { - GlyphBLF *g, *g_prev = nullptr; + GlyphBLF *g = nullptr; ft_pix pen_x = 0; size_t i = 0, i_curr; @@ -930,13 +939,11 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font, while ((i < str_len) && str[i]) { i_curr = i; - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); + g = blf_glyph_from_utf8_and_step(font, gc, g, str, str_len, &i, &pen_x); if (UNLIKELY(g == nullptr)) { continue; } - pen_x += blf_kerning(font, g_prev, g); - rcti bounds; bounds.xmin = ft_pix_to_int_floor(pen_x) + ft_pix_to_int_floor(g->box_xmin); bounds.xmax = ft_pix_to_int_floor(pen_x) + ft_pix_to_int_ceil(g->box_xmax); @@ -946,8 +953,7 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font, if (user_fn(str, i_curr, &bounds, user_data) == false) { break; } - pen_x = ft_pix_round_advance(pen_x, g->advance_x); - g_prev = g; + pen_x = blf_pen_advance(font, pen_x, g->advance_x); } blf_glyph_cache_release(font); @@ -1055,7 +1061,8 @@ static void blf_font_wrap_apply(FontBLF *font, void *userdata), void *userdata) { - GlyphBLF *g, *g_prev = nullptr; + GlyphBLF *g = nullptr; + GlyphBLF *g_prev = nullptr; ft_pix pen_x = 0; ft_pix pen_y = 0; size_t i = 0; @@ -1078,12 +1085,11 @@ static void blf_font_wrap_apply(FontBLF *font, size_t i_curr = i; bool do_draw = false; - g = blf_glyph_from_utf8_and_step(font, gc, str, str_len, &i); + g = blf_glyph_from_utf8_and_step(font, gc, g_prev, str, str_len, &i, &pen_x); if (UNLIKELY(g == nullptr)) { continue; } - pen_x += blf_kerning(font, g_prev, g); /** * Implementation Detail (utf8). @@ -1093,7 +1099,7 @@ static void blf_font_wrap_apply(FontBLF *font, * * This is _only_ done when we know for sure the character is ascii (newline or a space). */ - pen_x_next = ft_pix_round_advance(pen_x, g->advance_x); + pen_x_next = blf_pen_advance(font, pen_x, g->advance_x); if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) { do_draw = true; } @@ -1427,14 +1433,9 @@ bool blf_ensure_face(FontBLF *font) font->face_flags = font->face->face_flags; - /* XXX: Temporarily disable kerning in our main font. Kerning had been accidentally removed - * from our font in 3.1. In 3.4 we disable kerning here in the new version to keep spacing the - * same - * (#101506). Enable again later with change of font, placement, or rendering - Harley. */ - if (font && font->filepath && - (BLI_path_cmp(BLI_path_basename(font->filepath), BLF_DEFAULT_PROPORTIONAL_FONT) == 0)) - { - font->face_flags &= ~FT_FACE_FLAG_KERNING; + if (font->face && STREQ(font->face->family_name, "DejaVu Sans")) { + /* So our legacy font can keep its too-tight spacing. */ + font->flags |= BLF_LEGACY_SPACING; } if (FT_HAS_MULTIPLE_MASTERS(font)) { diff --git a/source/blender/blenfont/intern/blf_glyph.cc b/source/blender/blenfont/intern/blf_glyph.cc index 19c1f766fc4..86890e1f0dd 100644 --- a/source/blender/blenfont/intern/blf_glyph.cc +++ b/source/blender/blenfont/intern/blf_glyph.cc @@ -94,7 +94,6 @@ static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) gc->char_width = font->char_width; gc->char_spacing = font->char_spacing; - memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table)); memset(gc->bucket, 0, sizeof(gc->bucket)); blf_ensure_size(font); @@ -169,15 +168,13 @@ void blf_glyph_cache_clear(FontBLF *font) * * \return nullptr if not found. */ -static GlyphBLF *blf_glyph_cache_find_glyph(const GlyphCacheBLF *gc, uint charcode) +static GlyphBLF *blf_glyph_cache_find_glyph(const GlyphCacheBLF *gc, + uint charcode, + uint8_t subpixel) { - if (charcode < GLYPH_ASCII_TABLE_SIZE) { - return gc->glyph_ascii_table[charcode]; - } - - GlyphBLF *g = static_cast(gc->bucket[blf_hash(charcode)].first); + GlyphBLF *g = static_cast(gc->bucket[blf_hash(charcode << 6 | subpixel)].first); while (g) { - if (g->c == charcode) { + if (g->c == charcode && g->subpixel == subpixel) { return g; } g = g->next; @@ -225,8 +222,12 @@ static uchar blf_glyph_gamma(uchar c) /** * Add a rendered glyph to a cache. */ -static GlyphBLF *blf_glyph_cache_add_glyph( - FontBLF *font, GlyphCacheBLF *gc, FT_GlyphSlot glyph, uint charcode, FT_UInt glyph_index) +static GlyphBLF *blf_glyph_cache_add_glyph(FontBLF *font, + GlyphCacheBLF *gc, + FT_GlyphSlot glyph, + uint charcode, + FT_UInt glyph_index, + uint8_t subpixel) { GlyphBLF *g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_get"); g->c = charcode; @@ -237,6 +238,7 @@ static GlyphBLF *blf_glyph_cache_add_glyph( g->dims[0] = int(glyph->bitmap.width); g->dims[1] = int(glyph->bitmap.rows); g->pitch = glyph->bitmap.pitch; + g->subpixel = subpixel; FT_BBox bbox; FT_Outline_Get_CBox(&(glyph->outline), &bbox); @@ -269,11 +271,7 @@ static GlyphBLF *blf_glyph_cache_add_glyph( memcpy(g->bitmap, glyph->bitmap.buffer, size_t(buffer_size)); } - const uint key = blf_hash(g->c); - BLI_addhead(&(gc->bucket[key]), g); - if (charcode < GLYPH_ASCII_TABLE_SIZE) { - gc->glyph_ascii_table[charcode] = g; - } + BLI_addhead(&(gc->bucket[blf_hash(g->c << 6 | subpixel)]), g); return g; } @@ -731,9 +729,8 @@ static FT_GlyphSlot blf_glyph_load(FontBLF *font, FT_UInt glyph_index) load_flags |= FT_LOAD_TARGET_NORMAL; } else { - /* Default, hinting disabled until FreeType has been upgraded - * to give good results on all platforms. */ - load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING; + /* Default "Auto" is Slight (vertical only) hinting. */ + load_flags |= FT_LOAD_TARGET_LIGHT; } } @@ -997,6 +994,7 @@ static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, FontBLF *glyph_font, FT_UInt glyph_index, uint charcode, + uint8_t subpixel, int fixed_width) { if (glyph_font != settings_font) { @@ -1071,15 +1069,20 @@ static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, blf_glyph_transform_spacing(glyph, spacing); } + FT_Outline_Translate(&glyph->outline, (FT_Pos)subpixel, 0); + if (blf_glyph_render_bitmap(glyph_font, glyph)) { return glyph; } return nullptr; } -GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, const uint charcode) +static GlyphBLF *blf_glyph_ensure_ex(FontBLF *font, + GlyphCacheBLF *gc, + const uint charcode, + uint8_t subpixel) { - GlyphBLF *g = blf_glyph_cache_find_glyph(gc, charcode); + GlyphBLF *g = blf_glyph_cache_find_glyph(gc, charcode, subpixel); if (g) { return g; } @@ -1093,16 +1096,42 @@ GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, const uint charcode } FT_GlyphSlot glyph = blf_glyph_render( - font, font_with_glyph, glyph_index, charcode, gc->fixed_width); + font, font_with_glyph, glyph_index, charcode, subpixel, gc->fixed_width); if (glyph) { /* Save this glyph in the initial font's cache. */ - g = blf_glyph_cache_add_glyph(font, gc, glyph, charcode, glyph_index); + g = blf_glyph_cache_add_glyph(font, gc, glyph, charcode, glyph_index, subpixel); } return g; } +GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, const uint charcode) +{ + return blf_glyph_ensure_ex(font, gc, charcode, 0); +} + +GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x) +{ + if (font->flags & BLF_HINTING_NONE) { + /* Not if we are not also hinting.*/ + return g; + } + + if (font->size > 35.0f || g->dims[0] == 0 || g->advance_x < 0) { + /* Single position for large sizes, spaces, and combining characters. */ + return g; + } + + /* Four sub-pixel positions up to 16 point, 2 until 35 points. */ + const uint8_t subpixel = (uint8_t)(pen_x & ((font->size > 16.0f) ? 32L : 48L)); + + if (g->subpixel != subpixel) { + g = blf_glyph_ensure_ex(font, gc, g->c, subpixel); + } + return g; +} + void blf_glyph_free(GlyphBLF *g) { if (g->bitmap) { diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 5ebda01f89d..0c770372848 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -168,6 +168,11 @@ void blf_glyph_cache_clear(struct FontBLF *font); */ struct GlyphBLF *blf_glyph_ensure(struct FontBLF *font, struct GlyphCacheBLF *gc, uint charcode); +struct GlyphBLF *blf_glyph_ensure_subpixel(struct FontBLF *font, + struct GlyphCacheBLF *gc, + struct GlyphBLF *g, + int32_t pen_x); + void blf_glyph_free(struct GlyphBLF *g); void blf_glyph_draw( struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, int x, int y); diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 511230e9cc6..d12791c2e69 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -91,12 +91,6 @@ BLI_INLINE ft_pix ft_pix_from_float(float v) return lroundf(v * 64.0f); } -BLI_INLINE ft_pix ft_pix_round_advance(ft_pix v, ft_pix step) -{ - /** See #USE_LEGACY_SPACING, rounding logic could change here. */ - return FT_PIX_DEFAULT_ROUNDING(v) + FT_PIX_DEFAULT_ROUNDING(step); -} - #undef FT_PIX_ROUND #undef FT_PIX_CEIL #undef FT_PIX_DEFAULT_ROUNDING @@ -105,9 +99,6 @@ BLI_INLINE ft_pix ft_pix_round_advance(ft_pix v, ft_pix step) #define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */ -/** Number of characters in #GlyphCacheBLF.glyph_ascii_table. */ -#define GLYPH_ASCII_TABLE_SIZE 128 - /** Number of characters in #KerningCacheBLF.table. */ #define KERNING_CACHE_TABLE_SIZE 128 @@ -161,9 +152,6 @@ typedef struct GlyphCacheBLF { /** The glyphs. */ ListBase bucket[257]; - /** Fast ascii lookup */ - struct GlyphBLF *glyph_ascii_table[GLYPH_ASCII_TABLE_SIZE]; - /** Texture array, to draw the glyphs. */ GPUTexture *texture; char *bitmap_result; @@ -190,6 +178,7 @@ typedef struct GlyphBLF { ft_pix box_ymax; ft_pix advance_x; + uint8_t subpixel; /** The difference in bearings when hinting is active, zero otherwise. */ ft_pix lsb_delta; diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 05b4bd0eee2..7c0e8a1f1f5 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -1663,7 +1663,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, strwidth = BLF_width(fstyle->uifont_id, str, max_len); } - BLI_assert((strwidth <= okwidth) || (okwidth <= 0.0f)); + //BLI_assert((strwidth <= okwidth) || (okwidth <= 0.0f)); return strwidth; } -- 2.30.2 From d704598d48efa7fc564e5096fb7948afd9f98552 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 13 Sep 2023 14:59:11 -0700 Subject: [PATCH 2/5] Removing Legacy spacing. Fixing blf_glyph_calc_rect_test for Full hinting. --- source/blender/blenfont/BLF_api.h | 2 -- source/blender/blenfont/intern/blf_font.cc | 16 ---------------- source/blender/blenfont/intern/blf_glyph.cc | 2 +- .../editors/interface/interface_widgets.cc | 2 +- 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 0c4ae5a6197..152323a24f8 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -348,8 +348,6 @@ enum { BLF_BAD_FONT = 1 << 16, /** This font is managed by the FreeType cache subsystem. */ BLF_CACHED = 1 << 17, - /** For legacy DejaVu. No hinting and half-pixel too tight. */ - BLF_LEGACY_SPACING = 1 << 18, }; #define BLF_DRAW_STR_DUMMY_MAX 1024 diff --git a/source/blender/blenfont/intern/blf_font.cc b/source/blender/blenfont/intern/blf_font.cc index 28fd34ed25b..e903dbb970f 100644 --- a/source/blender/blenfont/intern/blf_font.cc +++ b/source/blender/blenfont/intern/blf_font.cc @@ -360,13 +360,6 @@ BLI_INLINE ft_pix blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const Glyph { ft_pix adjustment = 0; - if (font->flags & BLF_LEGACY_SPACING) { - if (font->flags & BLF_HINTING_NONE || !g_prev || g_prev->c == ' ') { - return 0; - } - adjustment -= 32; - } - /* Small adjust if there is hinting. */ adjustment += g->lsb_delta - ((g_prev) ? g_prev->rsb_delta : 0); @@ -420,10 +413,6 @@ BLI_INLINE GlyphBLF *blf_glyph_from_utf8_and_step(FontBLF *font, BLI_INLINE ft_pix blf_pen_advance(FontBLF *font, ft_pix v, ft_pix step) { - if (font->flags & BLF_LEGACY_SPACING && font->flags & BLF_HINTING_NONE) { - /* DejaVu with no hinting, so truncate pen position to match old spacing. */ - return (v + step) & ~63; - } return v + step; } @@ -1433,11 +1422,6 @@ bool blf_ensure_face(FontBLF *font) font->face_flags = font->face->face_flags; - if (font->face && STREQ(font->face->family_name, "DejaVu Sans")) { - /* So our legacy font can keep its too-tight spacing. */ - font->flags |= BLF_LEGACY_SPACING; - } - if (FT_HAS_MULTIPLE_MASTERS(font)) { FT_Get_MM_Var(font->face, &(font->variations)); } diff --git a/source/blender/blenfont/intern/blf_glyph.cc b/source/blender/blenfont/intern/blf_glyph.cc index 86890e1f0dd..fac0c20cb8d 100644 --- a/source/blender/blenfont/intern/blf_glyph.cc +++ b/source/blender/blenfont/intern/blf_glyph.cc @@ -1159,7 +1159,7 @@ static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const /* Intentionally check with `g->advance`, because this is the * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ - rect->xmin = x; + rect->xmin = x + g->pos[0]; rect->xmax = rect->xmin + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]); rect->ymin = y; rect->ymax = rect->ymin - g->dims[1]; diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 997091aba1f..772bf57e23b 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -1656,7 +1656,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, strwidth = BLF_width(fstyle->uifont_id, str, max_len); } - //BLI_assert((strwidth <= okwidth) || (okwidth <= 0.0f)); + BLI_assert((strwidth <= okwidth) || (okwidth <= 0.0f)); return strwidth; } -- 2.30.2 From 3272189a6cf10a39894720e8e9e0c17a38f7b331 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Wed, 13 Sep 2023 15:55:00 -0700 Subject: [PATCH 3/5] Adjusting string clip assert. And allowing out by one on the glyph rect test. --- source/blender/blenfont/intern/blf_glyph.cc | 2 +- source/blender/editors/interface/interface_widgets.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenfont/intern/blf_glyph.cc b/source/blender/blenfont/intern/blf_glyph.cc index fac0c20cb8d..5759f17f727 100644 --- a/source/blender/blenfont/intern/blf_glyph.cc +++ b/source/blender/blenfont/intern/blf_glyph.cc @@ -1159,7 +1159,7 @@ static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const /* Intentionally check with `g->advance`, because this is the * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ - rect->xmin = x + g->pos[0]; + rect->xmin = x + g->pos[0] + 1; rect->xmax = rect->xmin + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]); rect->ymin = y; rect->ymax = rect->ymin - g->dims[1]; diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 772bf57e23b..5caf6116f61 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -1656,7 +1656,7 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle, strwidth = BLF_width(fstyle->uifont_id, str, max_len); } - BLI_assert((strwidth <= okwidth) || (okwidth <= 0.0f)); + BLI_assert((strwidth <= (okwidth + 1)) || (okwidth <= 0.0f)); return strwidth; } -- 2.30.2 From 11340ec4eb21a694de496483e7f373c82765cbc6 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Thu, 14 Sep 2023 17:48:02 -0700 Subject: [PATCH 4/5] Cleanup. --- source/blender/blenfont/intern/blf_font.cc | 18 ++++++------------ source/blender/blenfont/intern/blf_glyph.cc | 2 +- .../blenfont/intern/blf_internal_types.h | 19 ------------------- 3 files changed, 7 insertions(+), 32 deletions(-) diff --git a/source/blender/blenfont/intern/blf_font.cc b/source/blender/blenfont/intern/blf_font.cc index e903dbb970f..d5ed6246948 100644 --- a/source/blender/blenfont/intern/blf_font.cc +++ b/source/blender/blenfont/intern/blf_font.cc @@ -411,11 +411,6 @@ BLI_INLINE GlyphBLF *blf_glyph_from_utf8_and_step(FontBLF *font, return g; } -BLI_INLINE ft_pix blf_pen_advance(FontBLF *font, ft_pix v, ft_pix step) -{ - return v + step; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -447,7 +442,7 @@ static void blf_font_draw_ex(FontBLF *font, } /* do not return this loop if clipped, we want every character tested */ blf_glyph_draw(font, gc, g, ft_pix_to_int_floor(pen_x), ft_pix_to_int_floor(pen_y)); - pen_x = blf_pen_advance(font, pen_x, g->advance_x); + pen_x += g->advance_x; } blf_batch_draw_end(); @@ -642,7 +637,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, continue; } blf_glyph_draw_buffer(buf_info, g, pen_x, pen_y_basis); - pen_x = blf_pen_advance(font, pen_x, g->advance_x); + pen_x += g->advance_x; } if (r_info) { @@ -674,8 +669,7 @@ static bool blf_font_width_to_strlen_glyph_process( if (UNLIKELY(g == nullptr)) { return false; /* continue the calling loop. */ } - *pen_x += blf_kerning(font, g_prev, g); - *pen_x = blf_pen_advance(font, *pen_x, g->advance_x); + *pen_x += blf_kerning(font, g_prev, g) + g->advance_x; /* When true, break the calling loop. */ return (ft_pix_to_int(*pen_x) >= width_i); @@ -781,7 +775,7 @@ static void blf_font_boundbox_ex(FontBLF *font, if (UNLIKELY(g == nullptr)) { continue; } - const ft_pix pen_x_next = blf_pen_advance(font, pen_x, g->advance_x); + const ft_pix pen_x_next = pen_x + g->advance_x; const ft_pix gbox_xmin = pen_x; const ft_pix gbox_xmax = pen_x_next; @@ -942,7 +936,7 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font, if (user_fn(str, i_curr, &bounds, user_data) == false) { break; } - pen_x = blf_pen_advance(font, pen_x, g->advance_x); + pen_x += g->advance_x; } blf_glyph_cache_release(font); @@ -1088,7 +1082,7 @@ static void blf_font_wrap_apply(FontBLF *font, * * This is _only_ done when we know for sure the character is ascii (newline or a space). */ - pen_x_next = blf_pen_advance(font, pen_x, g->advance_x); + pen_x_next = pen_x + g->advance_x; if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) { do_draw = true; } diff --git a/source/blender/blenfont/intern/blf_glyph.cc b/source/blender/blenfont/intern/blf_glyph.cc index 5759f17f727..413e26818af 100644 --- a/source/blender/blenfont/intern/blf_glyph.cc +++ b/source/blender/blenfont/intern/blf_glyph.cc @@ -1160,7 +1160,7 @@ static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ rect->xmin = x + g->pos[0] + 1; - rect->xmax = rect->xmin + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]); + rect->xmax = x + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]); rect->ymin = y; rect->ymax = rect->ymin - g->dims[1]; } diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index d12791c2e69..5ffcb556afe 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -44,31 +44,13 @@ typedef int32_t ft_pix; /* Macros copied from `include/freetype/internal/ftobjs.h`. */ -/** - * FIXME(@ideasman42): Follow rounding from Blender 3.1x and older. - * This is what users will expect and changing this creates wider spaced text. - * Use this macro to communicate that rounding should be used, using floor is to avoid - * user visible changes, which can be reviewed and handled separately. - */ -#define USE_LEGACY_SPACING - #define FT_PIX_FLOOR(x) ((x) & ~63) #define FT_PIX_ROUND(x) FT_PIX_FLOOR((x) + 32) #define FT_PIX_CEIL(x) ((x) + 63) -#ifdef USE_LEGACY_SPACING -# define FT_PIX_DEFAULT_ROUNDING(x) FT_PIX_FLOOR(x) -#else -# define FT_PIX_DEFAULT_ROUNDING(x) FT_PIX_ROUND(x) -#endif - BLI_INLINE int ft_pix_to_int(ft_pix v) { -#ifdef USE_LEGACY_SPACING return (int)(v >> 6); -#else - return (int)(FT_PIX_DEFAULT_ROUNDING(v) >> 6); -#endif } BLI_INLINE int ft_pix_to_int_floor(ft_pix v) @@ -93,7 +75,6 @@ BLI_INLINE ft_pix ft_pix_from_float(float v) #undef FT_PIX_ROUND #undef FT_PIX_CEIL -#undef FT_PIX_DEFAULT_ROUNDING /** \} */ -- 2.30.2 From bd9e4ee23d555dbbc8732c9bad546c7928a2a7e3 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Mon, 18 Sep 2023 14:00:12 -0700 Subject: [PATCH 5/5] Adding defines that enable subpixel positioning and subpixel antialiasing --- source/blender/blenfont/intern/blf_font.cc | 5 +++++ source/blender/blenfont/intern/blf_glyph.cc | 2 ++ source/blender/blenfont/intern/blf_internal.h | 12 ++++++++++++ source/blender/blenfont/intern/blf_internal_types.h | 3 --- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/source/blender/blenfont/intern/blf_font.cc b/source/blender/blenfont/intern/blf_font.cc index 86af399c2d6..315d1d6c9f3 100644 --- a/source/blender/blenfont/intern/blf_font.cc +++ b/source/blender/blenfont/intern/blf_font.cc @@ -406,7 +406,12 @@ BLI_INLINE GlyphBLF *blf_glyph_from_utf8_and_step(FontBLF *font, GlyphBLF *g = blf_glyph_ensure(font, gc, charcode); if (g && pen_x && !(font->flags & BLF_MONOSPACED)) { *pen_x += blf_kerning(font, g_prev, g); +#ifndef BLF_SUBPIXEL_POSITION + *pen_x = FT_PIX_ROUND(*pen_x); +#endif +#ifdef BLF_SUBPIXEL_AA g = blf_glyph_ensure_subpixel(font, gc, g, *pen_x); +#endif } return g; } diff --git a/source/blender/blenfont/intern/blf_glyph.cc b/source/blender/blenfont/intern/blf_glyph.cc index 5f26a5167fb..ee33b502c38 100644 --- a/source/blender/blenfont/intern/blf_glyph.cc +++ b/source/blender/blenfont/intern/blf_glyph.cc @@ -1113,6 +1113,7 @@ GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, const uint charcode return blf_glyph_ensure_ex(font, gc, charcode, 0); } +#ifdef BLF_SUBPIXEL_AA GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x) { if (font->flags & BLF_HINTING_NONE) { @@ -1133,6 +1134,7 @@ GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF * } return g; } +#endif void blf_glyph_free(GlyphBLF *g) { diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 0c770372848..7c341e7ebc2 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -24,6 +24,16 @@ struct rcti; */ #define BLF_MAX_FONT 64 +/** + * If enabled, glyphs positions are on 64ths of a pixel. Disabled, they are on whole pixels. + */ +#define BLF_SUBPIXEL_POSITION + +/** + * If enabled, glyphs are rendered at multiple horizontal subpixel positions. + */ +#define BLF_SUBPIXEL_AA + /** Maximum number of opened FT_Face objects managed by cache. 0 is default of 2. */ #define BLF_CACHE_MAX_FACES 4 /** Maximum number of opened FT_Size objects managed by cache. 0 is default of 4 */ @@ -168,10 +178,12 @@ void blf_glyph_cache_clear(struct FontBLF *font); */ struct GlyphBLF *blf_glyph_ensure(struct FontBLF *font, struct GlyphCacheBLF *gc, uint charcode); +#ifdef BLF_SUBPIXEL_AA struct GlyphBLF *blf_glyph_ensure_subpixel(struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, int32_t pen_x); +#endif void blf_glyph_free(struct GlyphBLF *g); void blf_glyph_draw( diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 5ffcb556afe..4785de08463 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -73,9 +73,6 @@ BLI_INLINE ft_pix ft_pix_from_float(float v) return lroundf(v * 64.0f); } -#undef FT_PIX_ROUND -#undef FT_PIX_CEIL - /** \} */ #define BLF_BATCH_DRAW_LEN_MAX 2048 /* in glyph */ -- 2.30.2