From c244169a8ea6acc779b1a5c3f5846488649ee3e7 Mon Sep 17 00:00:00 2001 From: nulano Date: Thu, 2 Feb 2023 15:41:29 +0000 Subject: [PATCH] fix Raqm fallback algorithm when a missing glyph is followed by a non-missing glyph in a single cluster --- src/PIL/ImageFont.py | 2 +- src/_imagingft.c | 42 ++++++++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 135f38cae..ac7cf3c07 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -731,7 +731,7 @@ class FreeTypeFontFamily: # f2 = ImageFont.truetype("segoeui.ttf", 24) # f3 = ImageFont.truetype("seguisym.ttf", 24) # ff = ImageFont.FreeTypeFontFamily(f1, f2, f3, layout_engine=le) - # for s in ("testčingšsšccčcč", "ية↦α,abc", "a↦ľ"): + # for s in ("testčingšsšccčcč", "ية↦α,abc", "a↦ľ", "ῶ,ω̃,ώ,ώ, ́,á"): # im = Image.new("RGBA", (300, 300), "white") # d = ImageDraw.Draw(im) # d.text((10, 60), s, "black", f1, direction="ltr", anchor="ls") diff --git a/src/_imagingft.c b/src/_imagingft.c index 81a5c0099..4a270d446 100644 --- a/src/_imagingft.c +++ b/src/_imagingft.c @@ -398,7 +398,7 @@ text_layout_raqm( GlyphInfo **glyph_info ) { int face = 0; - size_t i = 0, j = 0, count = 0, start = 0; + size_t i = 0, count = 0, start = 0; raqm_t *rq = NULL; raqm_glyph_t *glyphs = NULL; raqm_direction_t direction; @@ -458,9 +458,8 @@ text_layout_raqm( PyErr_SetString(PyExc_ValueError, "failed to allocate fallback buffer."); goto failed; } - fallback[0] = -1; - for (j = 1; j < size; j++) { - fallback[j] = -2; + for (i = 0; i < size; i++) { + fallback[i] = -2; } } @@ -545,25 +544,25 @@ text_layout_raqm( } } else { start = 0; - for (j = 0; j <= size; j++) { - if (j < size) { - if (fallback[j] == -2) { + for (i = 0; i <= size; i++) { + if (i < size) { + if (fallback[i] == -2) { /* not a cluster boundary */ continue; } - if (fallback[start] == fallback[j]) { + if (fallback[start] == fallback[i]) { /* use same font face for this cluster */ continue; } } - if (fallback[start] == -1) { + if (fallback[start] < 0) { raqm_set_freetype_face_range( - rq, family->faces[face], start, j - start); + rq, family->faces[face], start, i - start); } else { raqm_set_freetype_face_range( - rq, family->faces[fallback[start]], start, j - start); + rq, family->faces[fallback[start]], start, i - start); } - start = j; + start = i; } } @@ -579,24 +578,27 @@ text_layout_raqm( goto failed; } - if (i + 1 == family->font_count) { + //if (face + 1 == family->font_count) { + // break; + //} + if (family->font_count == 1) { break; } - for (j = 1; j < size; j++) { - if (fallback[j] == -1) { - fallback[j] = -2; + for (i = 1; i < size; i++) { + if (fallback[i] == -1) { + fallback[i] = -2; } } int missing = 0; - for (j = 0; j < count; j++) { - int cluster = glyphs[j].cluster; - if (glyphs[j].index == 0) { + for (i = 0; i < count; i++) { + int cluster = glyphs[i].cluster; + if (glyphs[i].index == 0) { /* cluster contains missing glyph */ fallback[cluster] = -1; missing = 1; - } else if (fallback[cluster] < 0) { + } else if (fallback[cluster] == -2) { /* use current font face for this cluster */ fallback[cluster] = face; }