Fix punctuation glyph overlap and line-end clipping
PIL draws full-width punctuation offset inside the advance box (e.g. left bracket '(' ink sits at x+42..x+61 while its advance is only 0.45em), so the next glyph overlapped it and a trailing bracket could clip. Shift the draw x by the ink offset for narrow punctuation and add right padding so line ends never clip. Verified: bracket gap restored, line end intact.
This commit is contained in:
1 parent
4fcc5acc85
commit
d322404e5a
1 file changed
+16
-3
+16
-3
@@ -339,13 +339,25 @@ def render_text(ly: dict, cw: int, ch: int) -> Optional[Tuple[Image.Image, Tuple
|
||||
# faux bold (textFontStyle=1) via stroke width
|
||||
stroke_w = max(1, int(size / 40)) if ly.get("textFontStyle") == "1" else 0
|
||||
pad = stroke_w # room for the stroke so glyphs don't clip
|
||||
raw_w, raw_h = max(1, int(round(tw)) + 2 * pad), max(1, int(round(th)) + 2 * pad)
|
||||
tail = max(int(size * 0.3), 8) # right padding so the last glyph never clips
|
||||
raw_w, raw_h = max(1, int(round(tw)) + 2 * pad + tail), max(1, int(round(th)) + 2 * pad)
|
||||
img = Image.new("RGBA", (raw_w, raw_h), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(img)
|
||||
for i, ln in enumerate(lines):
|
||||
x = pad
|
||||
for ch_ in ln:
|
||||
draw.text((x, pad + int(round(i * line_h))), ch_, font=font,
|
||||
off = 0
|
||||
if ch_ in NARROW_PUNCT:
|
||||
# PIL draws full-width punctuation offset inside the advance
|
||||
# box (e.g. '(' ink sits at x+42..x+61). Shift the draw x so
|
||||
# the ink starts at the layout x; otherwise it overlaps the
|
||||
# next glyph or clips at line end.
|
||||
t_img = Image.new("RGBA", (int(size) + 16, int(size) + 16), (0, 0, 0, 0))
|
||||
ImageDraw.Draw(t_img).text((4, 4), ch_, font=font,
|
||||
fill=(255, 255, 255, 255))
|
||||
t_bb = t_img.getchannel("A").getbbox()
|
||||
off = t_bb[0] - 4 if t_bb else 0
|
||||
draw.text((x - off, pad + int(round(i * line_h))), ch_, font=font,
|
||||
fill=fill, stroke_width=stroke_w, stroke_fill=fill)
|
||||
x += char_advance(ch_) + ls
|
||||
|
||||
@@ -355,7 +367,8 @@ def render_text(ly: dict, cw: int, ch: int) -> Optional[Tuple[Image.Image, Tuple
|
||||
# export for the title layers).
|
||||
cx, cy = (l + r) / 2, (t + b) / 2
|
||||
if prof.get("narrow"):
|
||||
left_full = int(round(cx - raw_w / 2))
|
||||
# center on the advance width (excluding the clip-padding tail)
|
||||
left_full = int(round(cx - (tw + 2 * pad) / 2))
|
||||
top_full = int(round(cy - raw_h / 2))
|
||||
content = img.getchannel("A").getbbox()
|
||||
if content:
|
||||
|
||||
Reference in new issue
Block a user