add color support to new text measuring functions

This commit is contained in:
nulano 2020-10-12 16:05:19 +01:00
parent 90e8255ba4
commit d7a08cbd15
4 changed files with 43 additions and 13 deletions

View File

@ -513,7 +513,7 @@ Methods
.. versionadded:: 6.2.0
.. py:method:: ImageDraw.textlength(text, font=None, direction=None, features=None, language=None)
.. py:method:: ImageDraw.textlength(text, font=None, direction=None, features=None, language=None, embedded_color=False)
Returns length (in pixels with 1/64 precision) of given text when rendered
in font with provided direction, features, and language.
@ -577,8 +577,9 @@ Methods
correct substitutions as appropriate, if available.
It should be a `BCP 47 language code`_.
Requires libraqm.
:param embedded_color: Whether to use font embedded color glyphs (COLR or CBDT).
.. py:method:: ImageDraw.textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0)
.. py:method:: ImageDraw.textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False)
Returns bounding box (in pixels) of given text relative to given anchor
when rendered in font with provided direction, features, and language.
@ -625,8 +626,9 @@ Methods
It should be a `BCP 47 language code`_.
Requires libraqm.
:param stroke_width: The width of the text stroke.
:param embedded_color: Whether to use font embedded color glyphs (COLR or CBDT).
.. py:method:: ImageDraw.multiline_textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0)
.. py:method:: ImageDraw.multiline_textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False)
Returns bounding box (in pixels) of given text relative to given anchor
when rendered in font with provided direction, features, and language.
@ -667,6 +669,7 @@ Methods
It should be a `BCP 47 language code`_.
Requires libraqm.
:param stroke_width: The width of the text stroke.
:param embedded_color: Whether to use font embedded color glyphs (COLR or CBDT).
.. py:method:: getdraw(im=None, hints=None)

View File

@ -500,15 +500,26 @@ class ImageDraw:
max_width = max(max_width, line_width)
return max_width, len(lines) * line_spacing - spacing
def textlength(self, text, font=None, direction=None, features=None, language=None):
def textlength(
self,
text,
font=None,
direction=None,
features=None,
language=None,
embedded_color=False,
):
"""Get the length of a given string, in pixels with 1/64 precision."""
if self._multiline_check(text):
raise ValueError("can't measure length of multiline text")
if embedded_color and self.mode not in ("RGB", "RGBA"):
raise ValueError("Embedded color supported only in RGB and RGBA modes")
if font is None:
font = self.getfont()
mode = "RGBA" if embedded_color else self.fontmode
try:
return font.getlength(text, self.fontmode, direction, features, language)
return font.getlength(text, mode, direction, features, language)
except AttributeError:
size = self.textsize(
text, font, direction=direction, features=features, language=language
@ -529,8 +540,12 @@ class ImageDraw:
features=None,
language=None,
stroke_width=0,
embedded_color=False,
):
"""Get the bounding box of a given string, in pixels."""
if embedded_color and self.mode not in ("RGB", "RGBA"):
raise ValueError("Embedded color supported only in RGB and RGBA modes")
if self._multiline_check(text):
return self.multiline_textbbox(
xy,
@ -543,12 +558,14 @@ class ImageDraw:
features,
language,
stroke_width,
embedded_color,
)
if font is None:
font = self.getfont()
mode = "RGBA" if embedded_color else self.fontmode
bbox = font.getbbox(
text, self.fontmode, direction, features, language, stroke_width, anchor
text, mode, direction, features, language, stroke_width, anchor
)
return bbox[0] + xy[0], bbox[1] + xy[1], bbox[2] + xy[0], bbox[3] + xy[1]
@ -564,6 +581,7 @@ class ImageDraw:
features=None,
language=None,
stroke_width=0,
embedded_color=False,
):
if direction == "ttb":
raise ValueError("ttb direction is unsupported for multiline text")
@ -583,7 +601,12 @@ class ImageDraw:
)
for line in lines:
line_width = self.textlength(
line, font, direction=direction, features=features, language=language
line,
font,
direction=direction,
features=features,
language=language,
embedded_color=embedded_color,
)
widths.append(line_width)
max_width = max(max_width, line_width)
@ -625,6 +648,7 @@ class ImageDraw:
features=features,
language=language,
stroke_width=stroke_width,
embedded_color=embedded_color,
)
if bbox is None:
bbox = bbox_line

View File

@ -290,9 +290,7 @@ class FreeTypeFont:
:return: Width for horizontal, height for vertical text.
"""
return (
self.font.getlength(text, mode == "1", direction, features, language) / 64
)
return self.font.getlength(text, mode, direction, features, language) / 64
def getbbox(
self,
@ -352,7 +350,7 @@ class FreeTypeFont:
:return: ``(left, top, right, bottom)`` bounding box
"""
size, offset = self.font.getsize(
text, mode == "1", direction, features, language, anchor
text, mode, direction, features, language, anchor
)
left, top = offset[0] - stroke_width, offset[1] - stroke_width
width, height = size[0] + 2 * stroke_width, size[1] + 2 * stroke_width

View File

@ -624,6 +624,8 @@ font_getlength(FontObject* self, PyObject* args)
size_t i, count; /* glyph_info index and length */
int horizontal_dir; /* is primary axis horizontal? */
int mask = 0; /* is FT_LOAD_TARGET_MONO enabled? */
int color = 0; /* is FT_LOAD_COLOR enabled? */
const char *mode = NULL;
const char *dir = NULL;
const char *lang = NULL;
PyObject *features = Py_None;
@ -631,13 +633,16 @@ font_getlength(FontObject* self, PyObject* args)
/* calculate size and bearing for a given string */
if (!PyArg_ParseTuple(args, "O|izOz:getlength", &string, &mask, &dir, &features, &lang)) {
if (!PyArg_ParseTuple(args, "O|zzOz:getlength", &string, &mode, &dir, &features, &lang)) {
return NULL;
}
horizontal_dir = dir && strcmp(dir, "ttb") == 0 ? 0 : 1;
count = text_layout(string, self, dir, features, lang, &glyph_info, mask);
mask = mode && strcmp(mode, "1") == 0;
color = mode && strcmp(mode, "RGBA") == 0;
count = text_layout(string, self, dir, features, lang, &glyph_info, mask, color);
if (PyErr_Occurred()) {
return NULL;
}