mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-23 23:30:34 +03:00
Merge pull request #8701 from radarhere/stroke_outside
This commit is contained in:
commit
b03f143df1
|
@ -1396,6 +1396,28 @@ def test_stroke_descender() -> None:
|
||||||
assert_image_similar_tofile(im, "Tests/images/imagedraw_stroke_descender.png", 6.76)
|
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")
|
@skip_unless_feature("freetype2")
|
||||||
def test_split_word() -> None:
|
def test_split_word() -> None:
|
||||||
# Arrange
|
# Arrange
|
||||||
|
|
|
@ -461,6 +461,20 @@ def test_free_type_font_get_mask(font: ImageFont.FreeTypeFont) -> None:
|
||||||
assert mask.size == (108, 13)
|
assert mask.size == (108, 13)
|
||||||
|
|
||||||
|
|
||||||
|
def test_stroke_mask() -> None:
|
||||||
|
# Arrange
|
||||||
|
text = "i"
|
||||||
|
|
||||||
|
# Act
|
||||||
|
font = ImageFont.truetype(FONT_PATH, 128)
|
||||||
|
mask = font.getmask(text, stroke_width=2)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert mask.getpixel((34, 5)) == 255
|
||||||
|
assert mask.getpixel((38, 5)) == 0
|
||||||
|
assert mask.getpixel((42, 5)) == 255
|
||||||
|
|
||||||
|
|
||||||
def test_load_when_image_not_found() -> None:
|
def test_load_when_image_not_found() -> None:
|
||||||
with tempfile.NamedTemporaryFile(delete=False) as tmp:
|
with tempfile.NamedTemporaryFile(delete=False) as tmp:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -643,6 +643,7 @@ class ImageDraw:
|
||||||
features=features,
|
features=features,
|
||||||
language=language,
|
language=language,
|
||||||
stroke_width=stroke_width,
|
stroke_width=stroke_width,
|
||||||
|
stroke_filled=True,
|
||||||
anchor=anchor,
|
anchor=anchor,
|
||||||
ink=ink,
|
ink=ink,
|
||||||
start=start,
|
start=start,
|
||||||
|
@ -692,7 +693,8 @@ class ImageDraw:
|
||||||
draw_text(stroke_ink, stroke_width)
|
draw_text(stroke_ink, stroke_width)
|
||||||
|
|
||||||
# Draw normal text
|
# Draw normal text
|
||||||
draw_text(ink, 0)
|
if ink != stroke_ink:
|
||||||
|
draw_text(ink)
|
||||||
else:
|
else:
|
||||||
# Only draw normal text
|
# Only draw normal text
|
||||||
draw_text(ink)
|
draw_text(ink)
|
||||||
|
|
|
@ -644,6 +644,7 @@ class FreeTypeFont:
|
||||||
features,
|
features,
|
||||||
language,
|
language,
|
||||||
stroke_width,
|
stroke_width,
|
||||||
|
kwargs.get("stroke_filled", False),
|
||||||
anchor,
|
anchor,
|
||||||
ink,
|
ink,
|
||||||
start[0],
|
start[0],
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Font:
|
||||||
features: list[str] | None,
|
features: list[str] | None,
|
||||||
lang: str | None,
|
lang: str | None,
|
||||||
stroke_width: float,
|
stroke_width: float,
|
||||||
|
stroke_filled: bool,
|
||||||
anchor: str | None,
|
anchor: str | None,
|
||||||
foreground_ink_long: int,
|
foreground_ink_long: int,
|
||||||
x_start: float,
|
x_start: float,
|
||||||
|
|
|
@ -834,6 +834,7 @@ font_render(FontObject *self, PyObject *args) {
|
||||||
int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
|
int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
|
||||||
int color = 0; /* is FT_LOAD_COLOR enabled? */
|
int color = 0; /* is FT_LOAD_COLOR enabled? */
|
||||||
float stroke_width = 0;
|
float stroke_width = 0;
|
||||||
|
int stroke_filled = 0;
|
||||||
PY_LONG_LONG foreground_ink_long = 0;
|
PY_LONG_LONG foreground_ink_long = 0;
|
||||||
unsigned int foreground_ink;
|
unsigned int foreground_ink;
|
||||||
const char *mode = NULL;
|
const char *mode = NULL;
|
||||||
|
@ -853,7 +854,7 @@ font_render(FontObject *self, PyObject *args) {
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(
|
if (!PyArg_ParseTuple(
|
||||||
args,
|
args,
|
||||||
"OO|zzOzfzLffO:render",
|
"OO|zzOzfpzLffO:render",
|
||||||
&string,
|
&string,
|
||||||
&fill,
|
&fill,
|
||||||
&mode,
|
&mode,
|
||||||
|
@ -861,6 +862,7 @@ font_render(FontObject *self, PyObject *args) {
|
||||||
&features,
|
&features,
|
||||||
&lang,
|
&lang,
|
||||||
&stroke_width,
|
&stroke_width,
|
||||||
|
&stroke_filled,
|
||||||
&anchor,
|
&anchor,
|
||||||
&foreground_ink_long,
|
&foreground_ink_long,
|
||||||
&x_start,
|
&x_start,
|
||||||
|
@ -1005,7 +1007,8 @@ font_render(FontObject *self, PyObject *args) {
|
||||||
if (stroker != NULL) {
|
if (stroker != NULL) {
|
||||||
error = FT_Get_Glyph(glyph_slot, &glyph);
|
error = FT_Get_Glyph(glyph_slot, &glyph);
|
||||||
if (!error) {
|
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) {
|
if (!error) {
|
||||||
FT_Vector origin = {0, 0};
|
FT_Vector origin = {0, 0};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user