Merge pull request #3693 from iwsfutcmd/text-set-language

Added ability to set language for text rendering
This commit is contained in:
Hugo 2019-03-12 11:32:33 +02:00 committed by GitHub
commit e2fda900cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 195 additions and 45 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

View File

@ -525,6 +525,15 @@ class TestImageFont(PillowTestCase):
self.assertEqual(t.getsize_multiline('ABC\nA'), (36, 36)) self.assertEqual(t.getsize_multiline('ABC\nA'), (36, 36))
self.assertEqual(t.getsize_multiline('ABC\nAaaa'), (48, 36)) self.assertEqual(t.getsize_multiline('ABC\nAaaa'), (48, 36))
def test_complex_font_settings(self):
# Arrange
t = self.get_font()
# Act / Assert
if t.layout_engine == ImageFont.LAYOUT_BASIC:
self.assertRaises(KeyError, t.getmask, 'абвг', direction='rtl')
self.assertRaises(KeyError, t.getmask, 'абвг', features=['-kern'])
self.assertRaises(KeyError, t.getmask, 'абвг', language='sr')
@unittest.skipUnless(HAS_RAQM, "Raqm not Available") @unittest.skipUnless(HAS_RAQM, "Raqm not Available")
class TestImageFont_RaqmLayout(TestImageFont): class TestImageFont_RaqmLayout(TestImageFont):

View File

@ -130,3 +130,16 @@ class TestImagecomplextext(PillowTestCase):
target_img = Image.open(target) target_img = Image.open(target)
self.assert_image_similar(im, target_img, .5) self.assert_image_similar(im, target_img, .5)
def test_language(self):
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
im = Image.new(mode='RGB', size=(300, 100))
draw = ImageDraw.Draw(im)
draw.text((0, 0), 'абвг', font=ttf, fill=500,
language='sr')
target = 'Tests/images/test_language.png'
target_img = Image.open(target)
self.assert_image_similar(im, target_img, .5)

View File

@ -255,7 +255,7 @@ Methods
Draw a shape. Draw a shape.
.. py:method:: PIL.ImageDraw.ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left", direction=None, features=None) .. py:method:: PIL.ImageDraw.ImageDraw.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left", direction=None, features=None, language=None)
Draws the string at the given position. Draws the string at the given position.
@ -287,7 +287,17 @@ Methods
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0
.. py:method:: PIL.ImageDraw.ImageDraw.multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left", direction=None, features=None) :param language: Language of the text. Different languages may use
different glyph shapes or ligatures. This parameter tells
the font which language the text is in, and to apply the
correct substitutions as appropriate, if available.
It should be a `BCP47 language code
<https://www.w3.org/International/articles/language-tags/>`
Requires libraqm.
.. versionadded:: 6.0.0
.. py:method:: PIL.ImageDraw.ImageDraw.multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left", direction=None, features=None, language=None)
Draws the string at the given position. Draws the string at the given position.
@ -316,7 +326,17 @@ Methods
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0
.. py:method:: PIL.ImageDraw.ImageDraw.textsize(text, font=None, spacing=4, direction=None, features=None) :param language: Language of the text. Different languages may use
different glyph shapes or ligatures. This parameter tells
the font which language the text is in, and to apply the
correct substitutions as appropriate, if available.
It should be a `BCP47 language code
<https://www.w3.org/International/articles/language-tags/>`
Requires libraqm.
.. versionadded:: 6.0.0
.. py:method:: PIL.ImageDraw.ImageDraw.textsize(text, font=None, spacing=4, direction=None, features=None, language=None)
Return the size of the given string, in pixels. Return the size of the given string, in pixels.
@ -330,7 +350,6 @@ Methods
Requires libraqm. Requires libraqm.
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0
:param features: A list of OpenType font features to be used during text :param features: A list of OpenType font features to be used during text
layout. This is usually used to turn on optional layout. This is usually used to turn on optional
font features that are not enabled by default, font features that are not enabled by default,
@ -343,8 +362,17 @@ Methods
Requires libraqm. Requires libraqm.
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0
:param language: Language of the text. Different languages may use
different glyph shapes or ligatures. This parameter tells
the font which language the text is in, and to apply the
correct substitutions as appropriate, if available.
It should be a `BCP47 language code
<https://www.w3.org/International/articles/language-tags/>`
Requires libraqm.
.. py:method:: PIL.ImageDraw.ImageDraw.multiline_textsize(text, font=None, spacing=4, direction=None, features=None) .. versionadded:: 6.0.0
.. py:method:: PIL.ImageDraw.ImageDraw.multiline_textsize(text, font=None, spacing=4, direction=None, features=None, language=None)
Return the size of the given string, in pixels. Return the size of the given string, in pixels.
@ -370,6 +398,16 @@ Methods
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0
:param language: Language of the text. Different languages may use
different glyph shapes or ligatures. This parameter tells
the font which language the text is in, and to apply the
correct substitutions as appropriate, if available.
It should be a `BCP47 language code
<https://www.w3.org/International/articles/language-tags/>`
Requires libraqm.
.. versionadded:: 6.0.0
.. py:method:: PIL.ImageDraw.getdraw(im=None, hints=None) .. py:method:: PIL.ImageDraw.getdraw(im=None, hints=None)
.. warning:: This method is experimental. .. warning:: This method is experimental.

View File

@ -47,11 +47,45 @@ Functions
Methods Methods
------- -------
.. py:method:: PIL.ImageFont.ImageFont.getsize(text) .. py:method:: PIL.ImageFont.ImageFont.getsize(text, direction=None, features=[], language=None)
Returns width and height (in pixels) of given text if rendered in font with
provided direction, features, and language.
:param text: Text to measure.
:param direction: Direction of the text. It can be 'rtl' (right to
left), 'ltr' (left to right) or 'ttb' (top to bottom).
Requires libraqm.
.. versionadded:: 4.2.0
:param features: A list of OpenType font features to be used during text
layout. This is usually used to turn on optional
font features that are not enabled by default,
for example 'dlig' or 'ss01', but can be also
used to turn off default font features for
example '-liga' to disable ligatures or '-kern'
to disable kerning. To get all supported
features, see
https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist
Requires libraqm.
.. versionadded:: 4.2.0
:param language: Language of the text. Different languages may use
different glyph shapes or ligatures. This parameter tells
the font which language the text is in, and to apply the
correct substitutions as appropriate, if available.
It should be a `BCP47 language code
<https://www.w3.org/International/articles/language-tags/>`
Requires libraqm.
.. versionadded:: 6.0.0
:return: (width, height) :return: (width, height)
.. py:method:: PIL.ImageFont.ImageFont.getmask(text, mode='', direction=None, features=[]) .. py:method:: PIL.ImageFont.ImageFont.getmask(text, mode='', direction=None, features=[], language=None)
Create a bitmap for the text. Create a bitmap for the text.
@ -85,5 +119,15 @@ Methods
.. versionadded:: 4.2.0 .. versionadded:: 4.2.0
:param language: Language of the text. Different languages may use
different glyph shapes or ligatures. This parameter tells
the font which language the text is in, and to apply the
correct substitutions as appropriate, if available.
It should be a `BCP47 language code
<https://www.w3.org/International/articles/language-tags/>`
Requires libraqm.
.. versionadded:: 6.0.0
:return: An internal PIL storage memory instance as defined by the :return: An internal PIL storage memory instance as defined by the
:py:mod:`PIL.Image.core` interface module. :py:mod:`PIL.Image.core` interface module.

View File

@ -102,17 +102,32 @@ Use ``PIL.__version__`` instead.
API Additions API Additions
============= =============
DIB File Format DIB file format
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
Pillow now supports reading and writing the DIB "Device Independent Bitmap" file format. Pillow now supports reading and writing the Device Independent Bitmap file format.
Image.quantize Image.quantize
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
The `dither` option is now a customisable parameter (was previously hardcoded to `1`). This parameter takes the same values used in `Image.convert` The ``dither`` option is now a customisable parameter (was previously hardcoded to ``1``).
This parameter takes the same values used in ``Image.convert``.
PNG EXIF Data New language parameter
^^^^^^^^^^^^^^^^^^^^^^
These text-rendering functions now accept a ``language`` parameter to request
language-specific glyphs and ligatures from the font:
* ``ImageDraw.ImageDraw.multiline_text()``
* ``ImageDraw.ImageDraw.multiline_textsize()``
* ``ImageDraw.ImageDraw.text()``
* ``ImageDraw.ImageDraw.textsize()``
* ``ImageFont.ImageFont.getmask()``
* ``ImageFont.ImageFont.getsize_multiline()``
* ``ImageFont.ImageFont.getsize()``
PNG EXIF data
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
EXIF data can now be read from and saved to PNG images. However, unlike other image EXIF data can now be read from and saved to PNG images. However, unlike other image
@ -130,4 +145,5 @@ Pillow can now read uncompressed RGB data from DDS images.
Reading TIFF with old-style JPEG compression Reading TIFF with old-style JPEG compression
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Added support reading TIFF files with old-style JPEG compression through LibTIFF. All YCbCr TIFF images are now always read as RGB. Added support reading TIFF files with old-style JPEG compression through LibTIFF. All YCbCr
TIFF images are now always read as RGB.

View File

@ -282,13 +282,17 @@ class ImageDraw(object):
self.draw.draw_bitmap(xy, mask, ink) self.draw.draw_bitmap(xy, mask, ink)
def multiline_text(self, xy, text, fill=None, font=None, anchor=None, def multiline_text(self, xy, text, fill=None, font=None, anchor=None,
spacing=4, align="left", direction=None, features=None): spacing=4, align="left", direction=None, features=None,
language=None):
widths = [] widths = []
max_width = 0 max_width = 0
lines = self._multiline_split(text) lines = self._multiline_split(text)
line_spacing = self.textsize('A', font=font)[1] + spacing line_spacing = self.textsize('A', font=font)[1] + spacing
for line in lines: for line in lines:
line_width, line_height = self.textsize(line, font) line_width, line_height = self.textsize(line, font,
direction=direction,
features=features,
language=language)
widths.append(line_width) widths.append(line_width)
max_width = max(max_width, line_width) max_width = max(max_width, line_width)
left, top = xy left, top = xy
@ -302,29 +306,30 @@ class ImageDraw(object):
else: else:
raise ValueError('align must be "left", "center" or "right"') raise ValueError('align must be "left", "center" or "right"')
self.text((left, top), line, fill, font, anchor, self.text((left, top), line, fill, font, anchor,
direction=direction, features=features) direction=direction, features=features, language=language)
top += line_spacing top += line_spacing
left = xy[0] left = xy[0]
def textsize(self, text, font=None, spacing=4, direction=None, def textsize(self, text, font=None, spacing=4, direction=None,
features=None): features=None, language=None):
"""Get the size of a given string, in pixels.""" """Get the size of a given string, in pixels."""
if self._multiline_check(text): if self._multiline_check(text):
return self.multiline_textsize(text, font, spacing, return self.multiline_textsize(text, font, spacing,
direction, features) direction, features, language)
if font is None: if font is None:
font = self.getfont() font = self.getfont()
return font.getsize(text, direction, features) return font.getsize(text, direction, features, language)
def multiline_textsize(self, text, font=None, spacing=4, direction=None, def multiline_textsize(self, text, font=None, spacing=4, direction=None,
features=None): features=None, language=None):
max_width = 0 max_width = 0
lines = self._multiline_split(text) lines = self._multiline_split(text)
line_spacing = self.textsize('A', font=font)[1] + spacing line_spacing = self.textsize('A', font=font)[1] + spacing
for line in lines: for line in lines:
line_width, line_height = self.textsize(line, font, spacing, line_width, line_height = self.textsize(line, font, spacing,
direction, features) direction, features,
language)
max_width = max(max_width, line_width) max_width = max(max_width, line_width)
return max_width, len(lines)*line_spacing - spacing return max_width, len(lines)*line_spacing - spacing

View File

@ -158,17 +158,17 @@ class FreeTypeFont(object):
def getmetrics(self): def getmetrics(self):
return self.font.ascent, self.font.descent return self.font.ascent, self.font.descent
def getsize(self, text, direction=None, features=None): def getsize(self, text, direction=None, features=None, language=None):
size, offset = self.font.getsize(text, direction, features) size, offset = self.font.getsize(text, direction, features, language)
return (size[0] + offset[0], size[1] + offset[1]) return (size[0] + offset[0], size[1] + offset[1])
def getsize_multiline(self, text, direction=None, def getsize_multiline(self, text, direction=None, spacing=4,
spacing=4, features=None): features=None, language=None):
max_width = 0 max_width = 0
lines = self._multiline_split(text) lines = self._multiline_split(text)
line_spacing = self.getsize('A')[1] + spacing line_spacing = self.getsize('A')[1] + spacing
for line in lines: for line in lines:
line_width, line_height = self.getsize(line, direction, features) line_width, line_height = self.getsize(line, direction, features, language)
max_width = max(max_width, line_width) max_width = max(max_width, line_width)
return max_width, len(lines)*line_spacing - spacing return max_width, len(lines)*line_spacing - spacing
@ -176,15 +176,15 @@ class FreeTypeFont(object):
def getoffset(self, text): def getoffset(self, text):
return self.font.getsize(text)[1] return self.font.getsize(text)[1]
def getmask(self, text, mode="", direction=None, features=None): def getmask(self, text, mode="", direction=None, features=None, language=None):
return self.getmask2(text, mode, direction=direction, return self.getmask2(text, mode, direction=direction, features=features,
features=features)[0] language=language)[0]
def getmask2(self, text, mode="", fill=Image.core.fill, direction=None, def getmask2(self, text, mode="", fill=Image.core.fill, direction=None,
features=None, *args, **kwargs): features=None, language=None, *args, **kwargs):
size, offset = self.font.getsize(text, direction, features) size, offset = self.font.getsize(text, direction, features, language)
im = fill("L", size, 0) im = fill("L", size, 0)
self.font.render(text, im.id, mode == "1", direction, features) self.font.render(text, im.id, mode == "1", direction, features, language)
return im, offset return im, offset
def font_variant(self, font=None, size=None, index=None, encoding=None, def font_variant(self, font=None, size=None, index=None, encoding=None,

View File

@ -87,6 +87,10 @@ typedef bool (*t_raqm_set_text_utf8) (raqm_t *rq,
size_t len); size_t len);
typedef bool (*t_raqm_set_par_direction) (raqm_t *rq, typedef bool (*t_raqm_set_par_direction) (raqm_t *rq,
raqm_direction_t dir); raqm_direction_t dir);
typedef bool (*t_raqm_set_language) (raqm_t *rq,
const char *lang,
size_t start,
size_t len);
typedef bool (*t_raqm_add_font_feature) (raqm_t *rq, typedef bool (*t_raqm_add_font_feature) (raqm_t *rq,
const char *feature, const char *feature,
int len); int len);
@ -106,6 +110,7 @@ typedef struct {
t_raqm_set_text set_text; t_raqm_set_text set_text;
t_raqm_set_text_utf8 set_text_utf8; t_raqm_set_text_utf8 set_text_utf8;
t_raqm_set_par_direction set_par_direction; t_raqm_set_par_direction set_par_direction;
t_raqm_set_language set_language;
t_raqm_add_font_feature add_font_feature; t_raqm_add_font_feature add_font_feature;
t_raqm_set_freetype_face set_freetype_face; t_raqm_set_freetype_face set_freetype_face;
t_raqm_layout layout; t_raqm_layout layout;
@ -160,6 +165,7 @@ setraqm(void)
p_raqm.set_text = (t_raqm_set_text)dlsym(p_raqm.raqm, "raqm_set_text"); p_raqm.set_text = (t_raqm_set_text)dlsym(p_raqm.raqm, "raqm_set_text");
p_raqm.set_text_utf8 = (t_raqm_set_text_utf8)dlsym(p_raqm.raqm, "raqm_set_text_utf8"); p_raqm.set_text_utf8 = (t_raqm_set_text_utf8)dlsym(p_raqm.raqm, "raqm_set_text_utf8");
p_raqm.set_par_direction = (t_raqm_set_par_direction)dlsym(p_raqm.raqm, "raqm_set_par_direction"); p_raqm.set_par_direction = (t_raqm_set_par_direction)dlsym(p_raqm.raqm, "raqm_set_par_direction");
p_raqm.set_language = (t_raqm_set_language)dlsym(p_raqm.raqm, "raqm_set_language");
p_raqm.add_font_feature = (t_raqm_add_font_feature)dlsym(p_raqm.raqm, "raqm_add_font_feature"); p_raqm.add_font_feature = (t_raqm_add_font_feature)dlsym(p_raqm.raqm, "raqm_add_font_feature");
p_raqm.set_freetype_face = (t_raqm_set_freetype_face)dlsym(p_raqm.raqm, "raqm_set_freetype_face"); p_raqm.set_freetype_face = (t_raqm_set_freetype_face)dlsym(p_raqm.raqm, "raqm_set_freetype_face");
p_raqm.layout = (t_raqm_layout)dlsym(p_raqm.raqm, "raqm_layout"); p_raqm.layout = (t_raqm_layout)dlsym(p_raqm.raqm, "raqm_layout");
@ -176,6 +182,7 @@ setraqm(void)
p_raqm.set_text && p_raqm.set_text &&
p_raqm.set_text_utf8 && p_raqm.set_text_utf8 &&
p_raqm.set_par_direction && p_raqm.set_par_direction &&
p_raqm.set_language &&
p_raqm.add_font_feature && p_raqm.add_font_feature &&
p_raqm.set_freetype_face && p_raqm.set_freetype_face &&
p_raqm.layout && p_raqm.layout &&
@ -190,6 +197,7 @@ setraqm(void)
p_raqm.set_text = (t_raqm_set_text)GetProcAddress(p_raqm.raqm, "raqm_set_text"); p_raqm.set_text = (t_raqm_set_text)GetProcAddress(p_raqm.raqm, "raqm_set_text");
p_raqm.set_text_utf8 = (t_raqm_set_text_utf8)GetProcAddress(p_raqm.raqm, "raqm_set_text_utf8"); p_raqm.set_text_utf8 = (t_raqm_set_text_utf8)GetProcAddress(p_raqm.raqm, "raqm_set_text_utf8");
p_raqm.set_par_direction = (t_raqm_set_par_direction)GetProcAddress(p_raqm.raqm, "raqm_set_par_direction"); p_raqm.set_par_direction = (t_raqm_set_par_direction)GetProcAddress(p_raqm.raqm, "raqm_set_par_direction");
p_raqm.set_language = (t_raqm_set_language)GetProcAddress(p_raqm.raqm, "raqm_set_language");
p_raqm.add_font_feature = (t_raqm_add_font_feature)GetProcAddress(p_raqm.raqm, "raqm_add_font_feature"); p_raqm.add_font_feature = (t_raqm_add_font_feature)GetProcAddress(p_raqm.raqm, "raqm_add_font_feature");
p_raqm.set_freetype_face = (t_raqm_set_freetype_face)GetProcAddress(p_raqm.raqm, "raqm_set_freetype_face"); p_raqm.set_freetype_face = (t_raqm_set_freetype_face)GetProcAddress(p_raqm.raqm, "raqm_set_freetype_face");
p_raqm.layout = (t_raqm_layout)GetProcAddress(p_raqm.raqm, "raqm_layout"); p_raqm.layout = (t_raqm_layout)GetProcAddress(p_raqm.raqm, "raqm_layout");
@ -205,6 +213,7 @@ setraqm(void)
p_raqm.set_text && p_raqm.set_text &&
p_raqm.set_text_utf8 && p_raqm.set_text_utf8 &&
p_raqm.set_par_direction && p_raqm.set_par_direction &&
p_raqm.set_language &&
p_raqm.add_font_feature && p_raqm.add_font_feature &&
p_raqm.set_freetype_face && p_raqm.set_freetype_face &&
p_raqm.layout && p_raqm.layout &&
@ -332,8 +341,8 @@ font_getchar(PyObject* string, int index, FT_ULong* char_out)
} }
static size_t static size_t
text_layout_raqm(PyObject* string, FontObject* self, const char* dir, text_layout_raqm(PyObject* string, FontObject* self, const char* dir, PyObject *features,
PyObject *features ,GlyphInfo **glyph_info, int mask) const char* lang, GlyphInfo **glyph_info, int mask)
{ {
int i = 0; int i = 0;
raqm_t *rq; raqm_t *rq;
@ -341,6 +350,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir,
raqm_glyph_t *glyphs = NULL; raqm_glyph_t *glyphs = NULL;
raqm_glyph_t_01 *glyphs_01 = NULL; raqm_glyph_t_01 *glyphs_01 = NULL;
raqm_direction_t direction; raqm_direction_t direction;
size_t start = 0;
rq = (*p_raqm.create)(); rq = (*p_raqm.create)();
if (rq == NULL) { if (rq == NULL) {
@ -360,6 +370,13 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir,
PyErr_SetString(PyExc_ValueError, "raqm_set_text() failed"); PyErr_SetString(PyExc_ValueError, "raqm_set_text() failed");
goto failed; goto failed;
} }
if (lang) {
if (!(*p_raqm.set_language)(rq, lang, start, size)) {
PyErr_SetString(PyExc_ValueError, "raqm_set_language() failed");
goto failed;
}
}
} }
#if PY_VERSION_HEX < 0x03000000 #if PY_VERSION_HEX < 0x03000000
else if (PyString_Check(string)) { else if (PyString_Check(string)) {
@ -372,6 +389,12 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir,
PyErr_SetString(PyExc_ValueError, "raqm_set_text_utf8() failed"); PyErr_SetString(PyExc_ValueError, "raqm_set_text_utf8() failed");
goto failed; goto failed;
} }
if (lang) {
if (!(*p_raqm.set_language)(rq, lang, start, size)) {
PyErr_SetString(PyExc_ValueError, "raqm_set_language() failed");
goto failed;
}
}
} }
#endif #endif
else { else {
@ -498,8 +521,8 @@ failed:
} }
static size_t static size_t
text_layout_fallback(PyObject* string, FontObject* self, const char* dir, text_layout_fallback(PyObject* string, FontObject* self, const char* dir, PyObject *features,
PyObject *features ,GlyphInfo **glyph_info, int mask) const char* lang, GlyphInfo **glyph_info, int mask)
{ {
int error, load_flags; int error, load_flags;
FT_ULong ch; FT_ULong ch;
@ -509,8 +532,8 @@ text_layout_fallback(PyObject* string, FontObject* self, const char* dir,
FT_UInt last_index = 0; FT_UInt last_index = 0;
int i; int i;
if (features != Py_None || dir != NULL) { if (features != Py_None || dir != NULL || lang != NULL) {
PyErr_SetString(PyExc_KeyError, "setting text direction or font features is not supported without libraqm"); PyErr_SetString(PyExc_KeyError, "setting text direction, language or font features is not supported without libraqm");
} }
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
if (!PyUnicode_Check(string)) { if (!PyUnicode_Check(string)) {
@ -564,15 +587,15 @@ text_layout_fallback(PyObject* string, FontObject* self, const char* dir,
} }
static size_t static size_t
text_layout(PyObject* string, FontObject* self, const char* dir, text_layout(PyObject* string, FontObject* self, const char* dir, PyObject *features,
PyObject *features, GlyphInfo **glyph_info, int mask) const char* lang, GlyphInfo **glyph_info, int mask)
{ {
size_t count; size_t count;
if (p_raqm.raqm && self->layout_engine == LAYOUT_RAQM) { if (p_raqm.raqm && self->layout_engine == LAYOUT_RAQM) {
count = text_layout_raqm(string, self, dir, features, glyph_info, mask); count = text_layout_raqm(string, self, dir, features, lang, glyph_info, mask);
} else { } else {
count = text_layout_fallback(string, self, dir, features, glyph_info, mask); count = text_layout_fallback(string, self, dir, features, lang, glyph_info, mask);
} }
return count; return count;
} }
@ -584,6 +607,7 @@ font_getsize(FontObject* self, PyObject* args)
FT_Face face; FT_Face face;
int xoffset, yoffset; int xoffset, yoffset;
const char *dir = NULL; const char *dir = NULL;
const char *lang = NULL;
size_t count; size_t count;
GlyphInfo *glyph_info = NULL; GlyphInfo *glyph_info = NULL;
PyObject *features = Py_None; PyObject *features = Py_None;
@ -591,14 +615,14 @@ font_getsize(FontObject* self, PyObject* args)
/* calculate size and bearing for a given string */ /* calculate size and bearing for a given string */
PyObject* string; PyObject* string;
if (!PyArg_ParseTuple(args, "O|zO:getsize", &string, &dir, &features)) if (!PyArg_ParseTuple(args, "O|zOz:getsize", &string, &dir, &features, &lang))
return NULL; return NULL;
face = NULL; face = NULL;
xoffset = yoffset = 0; xoffset = yoffset = 0;
y_max = y_min = 0; y_max = y_min = 0;
count = text_layout(string, self, dir, features, &glyph_info, 0); count = text_layout(string, self, dir, features, lang, &glyph_info, 0);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} }
@ -691,16 +715,17 @@ font_render(FontObject* self, PyObject* args)
int temp; int temp;
int xx, x0, x1; int xx, x0, x1;
const char *dir = NULL; const char *dir = NULL;
const char *lang = NULL;
size_t count; size_t count;
GlyphInfo *glyph_info; GlyphInfo *glyph_info;
PyObject *features = NULL; PyObject *features = NULL;
if (!PyArg_ParseTuple(args, "On|izO:render", &string, &id, &mask, &dir, &features)) { if (!PyArg_ParseTuple(args, "On|izOz:render", &string, &id, &mask, &dir, &features, &lang)) {
return NULL; return NULL;
} }
glyph_info = NULL; glyph_info = NULL;
count = text_layout(string, self, dir, features, &glyph_info, mask); count = text_layout(string, self, dir, features, lang, &glyph_info, mask);
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return NULL; return NULL;
} }