added layout engine switch

This commit is contained in:
wiredfool 2017-06-13 09:03:23 -07:00
parent f371ca07f4
commit b8c04de043
3 changed files with 47 additions and 18 deletions

View File

@ -41,6 +41,9 @@ try:
except ImportError:
core = _imagingft_not_installed()
LAYOUT_BASIC = 0
LAYOUT_RAQM = 1
# FIXME: add support for pilfont2 format (see FontFile.py)
# --------------------------------------------------------------------
@ -115,7 +118,8 @@ class ImageFont(object):
class FreeTypeFont(object):
"FreeType font wrapper (requires _imagingft service)"
def __init__(self, font=None, size=10, index=0, encoding=""):
def __init__(self, font=None, size=10, index=0, encoding="",
layout_engine=None):
# FIXME: use service provider instead
self.path = font
@ -123,12 +127,21 @@ class FreeTypeFont(object):
self.index = index
self.encoding = encoding
if layout_engine not in (LAYOUT_BASIC, LAYOUT_RAQM):
layout_engine = LAYOUT_BASIC
if core.HAVE_RAQM:
layout_engine = LAYOUT_RAQM
if layout_engine == LAYOUT_RAQM and not core.HAVE_RAQM:
layout_engine = LAYOUT_BASIC
self.layout_engine = layout_engine
if isPath(font):
self.font = core.getfont(font, size, index, encoding)
self.font = core.getfont(font, size, index, encoding, layout_engine=layout_engine)
else:
self.font_bytes = font.read()
self.font = core.getfont(
"", size, index, encoding, self.font_bytes)
"", size, index, encoding, self.font_bytes, layout_engine)
def getname(self):
return self.font.family, self.font.style
@ -152,7 +165,8 @@ class FreeTypeFont(object):
self.font.render(text, im.id, mode == "1", direction, features)
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,
layout_engine=None):
"""
Create a copy of this FreeTypeFont object,
using any specified arguments to override the settings.
@ -165,8 +179,9 @@ class FreeTypeFont(object):
return FreeTypeFont(font=self.path if font is None else font,
size=self.size if size is None else size,
index=self.index if index is None else index,
encoding=self.encoding if encoding is None else
encoding)
encoding=self.encoding if encoding is None else encoding,
layout_engine=self.layout_engine if layout_engine is None else layout_engine
)
class TransposedFont(object):
@ -212,7 +227,8 @@ def load(filename):
return f
def truetype(font=None, size=10, index=0, encoding=""):
def truetype(font=None, size=10, index=0, encoding="",
layout_engine=None):
"""
Load a TrueType or OpenType font file, and create a font object.
This function loads a font object from the given file, and creates
@ -230,12 +246,14 @@ def truetype(font=None, size=10, index=0, encoding=""):
Symbol), "ADOB" (Adobe Standard), "ADBE" (Adobe Expert),
and "armn" (Apple Roman). See the FreeType documentation
for more information.
:param layout_engine: Which layout engine to use, if available:
`ImageFont.LAYOUT_BASIC` or `ImageFont.LAYOUT_RAQM`.
:return: A font object.
:exception IOError: If the file could not be read.
"""
try:
return FreeTypeFont(font, size, index, encoding)
return FreeTypeFont(font, size, index, encoding, layout_engine)
except IOError:
ttf_filename = os.path.basename(font)
@ -266,16 +284,16 @@ def truetype(font=None, size=10, index=0, encoding=""):
for walkfilename in walkfilenames:
if ext and walkfilename == ttf_filename:
fontpath = os.path.join(walkroot, walkfilename)
return FreeTypeFont(fontpath, size, index, encoding)
return FreeTypeFont(fontpath, size, index, encoding, layout_engine)
elif not ext and os.path.splitext(walkfilename)[0] == ttf_filename:
fontpath = os.path.join(walkroot, walkfilename)
if os.path.splitext(fontpath)[1] == '.ttf':
return FreeTypeFont(fontpath, size, index, encoding)
return FreeTypeFont(fontpath, size, index, encoding, layout_engine)
if not ext and first_font_with_a_different_extension is None:
first_font_with_a_different_extension = fontpath
if first_font_with_a_different_extension:
return FreeTypeFont(first_font_with_a_different_extension, size,
index, encoding)
index, encoding, layout_engine)
raise

View File

@ -379,12 +379,12 @@ try:
# Make a copy of FreeTypeFont so we can patch the original
free_type_font = copy.deepcopy(ImageFont.FreeTypeFont)
with SimplePatcher(ImageFont, '_FreeTypeFont', free_type_font):
def loadable_font(filepath, size, index, encoding):
def loadable_font(filepath, size, index, encoding, *args, **kwargs):
if filepath == path_to_fake:
return ImageFont._FreeTypeFont(FONT_PATH, size, index,
encoding)
encoding, *args, **kwargs)
return ImageFont._FreeTypeFont(filepath, size, index,
encoding)
encoding, *args, **kwargs)
with SimplePatcher(ImageFont, 'FreeTypeFont', loadable_font):
font = ImageFont.truetype(fontname)
# Make sure it's loaded

View File

@ -45,6 +45,9 @@
#include <raqm.h>
#endif
#define LAYOUT_FALLBACK 0
#define LAYOUT_RAQM 1
typedef struct
{
int index, x_offset, x_advance, y_offset;
@ -67,6 +70,7 @@ typedef struct {
PyObject_HEAD
FT_Face face;
unsigned char *font_bytes;
int layout_engine;
} FontObject;
static PyTypeObject Font_Type;
@ -100,11 +104,13 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw)
char* filename = NULL;
int size;
int index = 0;
int layout_engine = 0;
unsigned char* encoding;
unsigned char* font_bytes;
int font_bytes_size = 0;
static char* kwlist[] = {
"filename", "size", "index", "encoding", "font_bytes", NULL
"filename", "size", "index", "encoding", "font_bytes",
"layout_engine", NULL
};
if (!library) {
@ -115,10 +121,10 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw)
return NULL;
}
if (!PyArg_ParseTupleAndKeywords(args, kw, "eti|iss#", kwlist,
if (!PyArg_ParseTupleAndKeywords(args, kw, "eti|iss#i", kwlist,
Py_FileSystemDefaultEncoding, &filename,
&size, &index, &encoding, &font_bytes,
&font_bytes_size)) {
&font_bytes_size, &layout_engine)) {
return NULL;
}
@ -130,6 +136,7 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw)
}
self->face = NULL;
self->layout_engine = layout_engine;
if (filename && font_bytes_size <= 0) {
self->font_bytes = NULL;
@ -409,7 +416,11 @@ text_layout(PyObject* string, FontObject* self, const char* dir,
{
size_t count;
#ifdef HAVE_RAQM
count = text_layout_raqm(string, self, dir, features, glyph_info, mask);
if (self->layout_engine == LAYOUT_RAQM) {
count = text_layout_raqm(string, self, dir, features, glyph_info, mask);
} else {
count = text_layout_fallback(string, self, dir, features, glyph_info, mask);
}
#else
count = text_layout_fallback(string, self, dir, features, glyph_info, mask);
#endif