Skip to content

Commit

Permalink
Only use outside border of stroke in text()
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Jan 18, 2025
1 parent a92a664 commit 4a7be8c
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 2 deletions.
22 changes: 22 additions & 0 deletions Tests/test_imagedraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,28 @@ def test_stroke_descender() -> None:
assert_image_similar_tofile(im, "Tests/images/imagedraw_stroke_descender.png", 6.76)


@skip_unless_feature("freetype2")
def test_stroke_inside_gap() -> None:
# Arrange
im = Image.new("RGB", (120, 130))
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120)

# Act
draw.text((12, 12), "i", "#f00", font, stroke_width=20)

# Assert
for y in range(im.height):
glyph = ""
for x in range(im.width):
if im.getpixel((x, y)) == (0, 0, 0):
if glyph == "started":
glyph = "ended"
else:
assert glyph != "ended", "Gap inside stroked glyph"
glyph = "started"


@skip_unless_feature("freetype2")
def test_split_word() -> None:
# Arrange
Expand Down
12 changes: 12 additions & 0 deletions Tests/test_imagefont.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,18 @@ def test_free_type_font_get_mask(font: ImageFont.FreeTypeFont) -> None:
assert mask.size == (108, 13)


def test_stroke_mask() -> None:
# Arrange
text = "mask this"

# Act
font = ImageFont.truetype(FONT_PATH, 64)
mask = font.getmask(text, stroke_width=1)

# Assert
assert mask.size == (348, 43)


def test_load_when_image_not_found() -> None:
with tempfile.NamedTemporaryFile(delete=False) as tmp:
pass
Expand Down
1 change: 1 addition & 0 deletions src/PIL/ImageDraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ def draw_text(ink: int, stroke_width: float = 0) -> None:
features=features,
language=language,
stroke_width=stroke_width,
stroke_filled=True,
anchor=anchor,
ink=ink,
start=start,
Expand Down
1 change: 1 addition & 0 deletions src/PIL/ImageFont.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ def fill(width: int, height: int) -> Image.core.ImagingCore:
features,
language,
stroke_width,
kwargs.get("stroke_filled", False),
anchor,
ink,
start[0],
Expand Down
1 change: 1 addition & 0 deletions src/PIL/_imagingft.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Font:
features: list[str] | None,
lang: str | None,
stroke_width: float,
stroke_filled: bool,
anchor: str | None,
foreground_ink_long: int,
x_start: float,
Expand Down
7 changes: 5 additions & 2 deletions src/_imagingft.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ font_render(FontObject *self, PyObject *args) {
int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
int color = 0; /* is FT_LOAD_COLOR enabled? */
float stroke_width = 0;
int stroke_filled = 0;
PY_LONG_LONG foreground_ink_long = 0;
unsigned int foreground_ink;
const char *mode = NULL;
Expand All @@ -853,14 +854,15 @@ font_render(FontObject *self, PyObject *args) {

if (!PyArg_ParseTuple(
args,
"OO|zzOzfzLffO:render",
"OO|zzOzfpzLffO:render",
&string,
&fill,
&mode,
&dir,
&features,
&lang,
&stroke_width,
&stroke_filled,
&anchor,
&foreground_ink_long,
&x_start,
Expand Down Expand Up @@ -1005,7 +1007,8 @@ font_render(FontObject *self, PyObject *args) {
if (stroker != NULL) {
error = FT_Get_Glyph(glyph_slot, &glyph);
if (!error) {
error = FT_Glyph_Stroke(&glyph, stroker, 1);
error = stroke_filled ? FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1)
: FT_Glyph_Stroke(&glyph, stroker, 1);
}
if (!error) {
FT_Vector origin = {0, 0};
Expand Down

0 comments on commit 4a7be8c

Please sign in to comment.