Use fractional coordinates when drawing text

This commit is contained in:
Andrew Murray 2022-11-08 11:49:39 +11:00
parent 820214d210
commit 5471dc2b26
16 changed files with 54 additions and 8 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 807 B

After

Width:  |  Height:  |  Size: 809 B

View File

@ -1238,6 +1238,27 @@ def test_stroke_descender():
assert_image_similar_tofile(im, "Tests/images/imagedraw_stroke_descender.png", 6.76)
@skip_unless_feature("freetype2")
def test_split_word():
# Arrange
im = Image.new("RGB", (230, 55))
expected = im.copy()
expected_draw = ImageDraw.Draw(expected)
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 48)
expected_draw.text((0, 0), "paradise", font=font)
draw = ImageDraw.Draw(im)
# Act
draw.text((0, 0), "par", font=font)
length = draw.textlength("par", font=font)
draw.text((length, 0), "adise", font=font)
# Assert
assert_image_equal(im, expected)
@skip_unless_feature("freetype2")
def test_stroke_multiline():
# Arrange

View File

@ -452,7 +452,11 @@ class ImageDraw:
mode = self.fontmode
if stroke_width == 0 and embedded_color:
mode = "RGBA"
coord = xy
coord = []
start = []
for i in range(2):
coord.append(int(xy[i]))
start.append(math.modf(xy[i])[0])
try:
mask, offset = font.getmask2(
text,
@ -463,6 +467,7 @@ class ImageDraw:
stroke_width=stroke_width,
anchor=anchor,
ink=ink,
start=start,
*args,
**kwargs,
)
@ -478,6 +483,7 @@ class ImageDraw:
stroke_width,
anchor,
ink,
start=start,
*args,
**kwargs,
)
@ -490,7 +496,7 @@ class ImageDraw:
# extract mask and set text alpha
color, mask = mask, mask.getband(3)
color.fillband(3, (ink >> 24) & 0xFF)
x, y = (int(c) for c in coord)
x, y = coord
self.im.paste(color, (x, y, x + mask.size[0], y + mask.size[1]), mask)
else:
self.draw.draw_bitmap(coord, mask, ink)

View File

@ -26,6 +26,7 @@
#
import base64
import math
import os
import sys
import warnings
@ -588,6 +589,7 @@ class FreeTypeFont:
stroke_width=0,
anchor=None,
ink=0,
start=None,
):
"""
Create a bitmap for the text.
@ -659,6 +661,7 @@ class FreeTypeFont:
stroke_width=stroke_width,
anchor=anchor,
ink=ink,
start=start,
)[0]
def getmask2(
@ -672,6 +675,7 @@ class FreeTypeFont:
stroke_width=0,
anchor=None,
ink=0,
start=None,
*args,
**kwargs,
):
@ -750,12 +754,23 @@ class FreeTypeFont:
size, offset = self.font.getsize(
text, mode, direction, features, language, anchor
)
size = size[0] + stroke_width * 2, size[1] + stroke_width * 2
if start is None:
start = (0, 0)
size = tuple(math.ceil(size[i] + stroke_width * 2 + start[i]) for i in range(2))
offset = offset[0] - stroke_width, offset[1] - stroke_width
Image._decompression_bomb_check(size)
im = fill("RGBA" if mode == "RGBA" else "L", size, 0)
self.font.render(
text, im.id, mode, direction, features, language, stroke_width, ink
text,
im.id,
mode,
direction,
features,
language,
stroke_width,
ink,
start[0],
start[1],
)
return im, offset

View File

@ -777,13 +777,15 @@ font_render(FontObject *self, PyObject *args) {
const char *lang = NULL;
PyObject *features = Py_None;
PyObject *string;
float x_start = 0;
float y_start = 0;
/* render string into given buffer (the buffer *must* have
the right size, or this will crash) */
if (!PyArg_ParseTuple(
args,
"On|zzOziL:render",
"On|zzOziLff:render",
&string,
&id,
&mode,
@ -791,7 +793,9 @@ font_render(FontObject *self, PyObject *args) {
&features,
&lang,
&stroke_width,
&foreground_ink_long)) {
&foreground_ink_long,
&x_start,
&y_start)) {
return NULL;
}
@ -876,8 +880,8 @@ font_render(FontObject *self, PyObject *args) {
}
/* set pen position to text origin */
x = (-x_min + stroke_width) << 6;
y = (-y_max + (-stroke_width)) << 6;
x = (-x_min + stroke_width + x_start) * 64;
y = (-y_max + (-stroke_width) - y_start) * 64;
if (stroker == NULL) {
load_flags |= FT_LOAD_RENDER;