diff --git a/ppl2psd.py b/ppl2psd.py index aebc69a..8aaa79f 100644 --- a/ppl2psd.py +++ b/ppl2psd.py @@ -38,7 +38,8 @@ except ImportError: # pragma: no cover # Optional TypeLayer (editable text) support try: from psd_tools.psd.tagged_blocks import TypeToolObjectSetting - from psd_tools.psd.engine_data import (String, Float, Integer, Dict, List) + from psd_tools.psd.engine_data import (String, Float, Integer, Bool, + Dict, List) _TYSHA = True except ImportError: # pragma: no cover _TYSHA = False @@ -331,13 +332,17 @@ def render_text(ly: dict, cw: int, ch: int) -> Optional[Tuple[Image.Image, Tuple th = len(lines) * line_h + size * 0.25 # slack so the last line never clips # --- render at natural size, centered on the layer box --- - raw_w, raw_h = max(1, int(round(tw))), max(1, int(round(th))) + # 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) img = Image.new("RGBA", (raw_w, raw_h), (0, 0, 0, 0)) draw = ImageDraw.Draw(img) for i, ln in enumerate(lines): - x = 0 + x = pad for ch_ in ln: - draw.text((x, int(round(i * line_h))), ch_, font=font, fill=fill) + draw.text((x, pad + int(round(i * line_h))), ch_, font=font, + fill=fill, stroke_width=stroke_w, stroke_fill=fill) x += char_advance(ch_) + ls # center on the boundingRect. Narrow-profile fonts (Source Han @@ -512,6 +517,10 @@ def build_type_layer_tysh(ly: dict, font_ps: str) -> bytes: Float(b / 255.0), Float(a / 255.0)]) ssd["FillColor"] = fc + # bold / italic (textFontStyle: 1 = faux bold) + if ly.get("textFontStyle") == "1": + ssd["FauxBold"] = Bool(True) + res["FontSet"][0]["Name"] = String(font_ps) l, t, rr, bb = bounding_rect(ly)