diff --git a/PIL/ImageFont.py b/PIL/ImageFont.py index 8ec60fef9..271669146 100644 --- a/PIL/ImageFont.py +++ b/PIL/ImageFont.py @@ -30,6 +30,11 @@ from __future__ import print_function from PIL import Image import os, sys +try: + import warnings +except ImportError: + warnings = None + class _imagingft_not_installed: # module placeholder def __getattr__(self, id): @@ -40,6 +45,13 @@ try: except ImportError: core = _imagingft_not_installed() +if bytes is str: + def isStringType(t): + return isinstance(t, basestring) +else: + def isStringType(t): + return isinstance(t, str) + # FIXME: add support for pilfont2 format (see FontFile.py) # -------------------------------------------------------------------- @@ -129,9 +141,18 @@ class ImageFont: class FreeTypeFont: "FreeType font wrapper (requires _imagingft service)" - def __init__(self, file, size, index=0, encoding=""): + def __init__(self, font=None, size=10, index=0, encoding="", file=None): # FIXME: use service provider instead - self.font = core.getfont(file, size, index, encoding) + if file: + if warnings: + warnings.warn('file parameter deprecated, please use font parameter instead.', DeprecationWarning) + font = file + + if isStringType(font): + self.font = core.getfont(font, size, index, encoding) + else: + font_bytes = font.read() + self.font = core.getfont("", size, index, encoding, font_bytes) def getname(self): return self.font.family, self.font.style @@ -212,10 +233,16 @@ def load(filename): # @return A font object. # @exception IOError If the file could not be read. -def truetype(filename, size, index=0, encoding=""): +def truetype(font=None, size=10, index=0, encoding="", filename=None): "Load a truetype font file." + + if filename: + if warnings: + warnings.warn('filename parameter deprecated, please use font parameter instead.', DeprecationWarning) + font = filename + try: - return FreeTypeFont(filename, size, index, encoding) + return FreeTypeFont(font, size, index, encoding) except IOError: if sys.platform == "win32": # check the windows font repository @@ -223,8 +250,8 @@ def truetype(filename, size, index=0, encoding=""): # 1.5.2's os.environ.get() windir = os.environ.get("WINDIR") if windir: - filename = os.path.join(windir, "fonts", filename) - return FreeTypeFont(filename, size, index, encoding) + filename = os.path.join(windir, "fonts", font) + return FreeTypeFont(font, size, index, encoding) raise ## diff --git a/Tests/fonts/FreeMono.ttf b/Tests/fonts/FreeMono.ttf new file mode 100644 index 000000000..f88bcef9c Binary files /dev/null and b/Tests/fonts/FreeMono.ttf differ diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py index 3c4e1f1b8..8305656e2 100644 --- a/Tests/test_imagefont.py +++ b/Tests/test_imagefont.py @@ -1,6 +1,8 @@ from tester import * from PIL import Image +from io import BytesIO + try: from PIL import ImageFont ImageFont.core.getfont # check if freetype is available @@ -8,5 +10,21 @@ except ImportError: skip() def test_sanity(): - assert_match(ImageFont.core.freetype2_version, "\d+\.\d+\.\d+$") + +def test_font_with_name(): + font_name = "Tests/fonts/FreeMono.ttf" + font_size = 10 + assert_no_exception(lambda: ImageFont.truetype(font_name, font_size)) + +def test_font_with_filelike(): + font_name = "Tests/fonts/FreeMono.ttf" + font_filelike = BytesIO(open(font_name, 'rb').read()) + font_size = 10 + assert_no_exception(lambda: ImageFont.truetype(font_filelike, font_size)) + +def test_font_old_parameters(): + font_name = "Tests/fonts/FreeMono.ttf" + font_size = 10 + assert_warning(DeprecationWarning, lambda: ImageFont.truetype(filename=font_name, size=font_size)) + diff --git a/_imagingft.c b/_imagingft.c index e29e3a244..9f9dd35c4 100644 --- a/_imagingft.c +++ b/_imagingft.c @@ -99,17 +99,20 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) FontObject* self; int error; - char* filename; + char* filename = NULL; int size; int index = 0; - unsigned char* encoding = NULL; + unsigned char* encoding; + unsigned char* file_like; + int file_like_size = 0; static char* kwlist[] = { - "filename", "size", "index", "encoding", NULL + "filename", "size", "index", "encoding", "file_like", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kw, "eti|is", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kw, "eti|iss#", kwlist, Py_FileSystemDefaultEncoding, &filename, - &size, &index, &encoding)) + &size, &index, &encoding, &file_like, + &file_like_size)) return NULL; if (!library) { @@ -124,8 +127,12 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw) if (!self) return NULL; - error = FT_New_Face(library, filename, index, &self->face); - + if (filename && file_like_size <= 0) { + error = FT_New_Face(library, filename, index, &self->face); + } else { + error = FT_New_Memory_Face(library, (FT_Byte*)file_like, file_like_size, index, &self->face); + } + if (!error) error = FT_Set_Pixel_Sizes(self->face, 0, size);