Skip to content

Commit

Permalink
Merge pull request #517 from wiredfool/pcf
Browse files Browse the repository at this point in the history
Fix support for characters >128 using .pcf or .pil fonts in Py3k
  • Loading branch information
aclark4life committed Mar 17, 2014
2 parents 320308c + 540e1e2 commit 35241da
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 8 deletions.
Binary file added Tests/images/high_ascii_chars.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 19 additions & 1 deletion Tests/test_font_pcf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,28 @@ def test_sanity():

font.save(tempname)

def test_draw():
def xtest_draw():

font = ImageFont.load(tempname)
image = Image.new("L", font.getsize(message), "white")
draw = ImageDraw.Draw(image)
draw.text((0, 0), message, font=font)
# assert_signature(image, "7216c60f988dea43a46bb68321e3c1b03ec62aee")

def _test_high_characters(message):

font = ImageFont.load(tempname)
image = Image.new("L", font.getsize(message), "white")
draw = ImageDraw.Draw(image)
draw.text((0, 0), message, font=font)

compare = Image.open('Tests/images/high_ascii_chars.png')
assert_image_equal(image, compare)

def test_high_characters():
message = "".join([chr(i+1) for i in range(140,232)])
_test_high_characters(message)
# accept bytes instances in Py3.
if bytes is not str:
_test_high_characters(message.encode('latin1'))

56 changes: 49 additions & 7 deletions _imaging.c
Original file line number Diff line number Diff line change
Expand Up @@ -2239,30 +2239,66 @@ textwidth(ImagingFontObject* self, const unsigned char* text)
return xsize;
}

void _font_text_asBytes(PyObject* encoded_string, unsigned char** text){
PyObject* bytes = NULL;

*text = NULL;

if (PyUnicode_CheckExact(encoded_string)){
bytes = PyUnicode_AsLatin1String(encoded_string);
} else if (PyBytes_Check(encoded_string)) {
bytes = encoded_string;
}
if (bytes) {
*text = (unsigned char*)PyBytes_AsString(bytes);
return;
}

#if PY_VERSION_HEX < 0x03000000
/* likely case here is py2.x with an ordinary string.
but this isn't defined in Py3.x */
if (PyString_Check(encoded_string)) {
*text = (unsigned char *)PyString_AsString(encoded_string);
}
#endif
}


static PyObject*
_font_getmask(ImagingFontObject* self, PyObject* args)
{
Imaging im;
Imaging bitmap;
int x, b;
int i=0;
int status;
Glyph* glyph;

PyObject* encoded_string;

unsigned char* text;
char* mode = "";
if (!PyArg_ParseTuple(args, "s|s:getmask", &text, &mode))

if (!PyArg_ParseTuple(args, "O|s:getmask", &encoded_string, &mode)){
return NULL;
}

_font_text_asBytes(encoded_string, &text);
if (!text) {
return NULL;
}

im = ImagingNew(self->bitmap->mode, textwidth(self, text), self->ysize);
if (!im)
if (!im) {
return NULL;
}

b = 0;
(void) ImagingFill(im, &b);

b = self->baseline;
for (x = 0; *text; text++) {
glyph = &self->glyphs[*text];
for (x = 0; text[i]; i++) {
glyph = &self->glyphs[text[i]];
bitmap = ImagingCrop(
self->bitmap,
glyph->sx0, glyph->sy0, glyph->sx1, glyph->sy1
Expand All @@ -2279,7 +2315,6 @@ _font_getmask(ImagingFontObject* self, PyObject* args)
x = x + glyph->dx;
b = b + glyph->dy;
}

return PyImagingNew(im);

failed:
Expand All @@ -2291,10 +2326,17 @@ static PyObject*
_font_getsize(ImagingFontObject* self, PyObject* args)
{
unsigned char* text;
if (!PyArg_ParseTuple(args, "s:getsize", &text))
PyObject* encoded_string;

if (!PyArg_ParseTuple(args, "O:getsize", &encoded_string))
return NULL;

_font_text_asBytes(encoded_string, &text);
if (!text) {
return NULL;
}

return Py_BuildValue("ii", textwidth(self, text), self->ysize);
return Py_BuildValue("ii", textwidth(self, text), self->ysize);
}

static struct PyMethodDef _font_methods[] = {
Expand Down

0 comments on commit 35241da

Please sign in to comment.