[Image-SIG] TrueType support in PIL 1.1.4 a1

Fredrik Lundh fredrik@pythonware.com
Fri, 17 Jan 2003 10:00:59 +0100


frank wrote:


> I have been a long time user of PIL and I appreciate it very much. I us=
e it
> for auto labelling of pictures and make town maps
> (http://art-nouveau.kubos.org/en/index.htm). The new
> truetype support is great but it seems to be broken with special charac=
ters
> like =E9,=E8,=FC, © .... they appear as squares in PIL although in=
 my
> favourite word processor they are OK with the same tt font.

the version in 1.1.4a1 messes up on non-ascii characters.  the
following patch fixes this, and adds support for unicode strings
as well.

regards /F

=3D=3D=3D=3D //modules/pil/_imagingft.c#4 (ktext) - //modules/pil/_imagin=
gft.c#7 (ktext) =3D=3D=3D=3D content
***************
*** 7,18 ****
   * history:
   * 2001-02-17 fl  Created (based on old experimental freetype 1.0 code)
   * 2001-04-18 fl  Fixed some egcs compiler nits
   *
   * Copyright (c) 1998-2001 by Secret Labs AB
   */

- /* FIXME: add unicode support (1.6 and later) */
-
  #include "Python.h"
  #include "Imaging.h"

--- 7,17 ----
   * history:
   * 2001-02-17 fl  Created (based on old experimental freetype 1.0 code)
   * 2001-04-18 fl  Fixed some egcs compiler nits
+  * 2002-11-08 fl  Added unicode support; more font metrics, etc
   *
   * Copyright (c) 1998-2001 by Secret Labs AB
   */

  #include "Python.h"
  #include "Imaging.h"

***************
*** 82,105 ****
      return (PyObject*) self;
  }

  static PyObject*
  font_getsize(FontObject* self, PyObject* args)
  {
      int i, x;

      /* calculate size for a given string */
!     char* text;
!     int chars;
!     if (!PyArg_ParseTuple(args, "s#", &text, &chars))
          return NULL;

  #if PY_VERSION_HEX >=3D 0x01060000
!     /* FIXME: Unicode support */
  #endif

!     for (x =3D i =3D 0; i < chars; i++) {
          int index, error;
!         index =3D FT_Get_Char_Index(self->face, (FT_ULong) text[i]);
          error =3D FT_Load_Glyph(self->face, index, FT_LOAD_DEFAULT);
          if (error)
              goto failure;
--- 81,134 ----
      return (PyObject*) self;
  }

+ static int
+ font_getchar(PyObject* string, int index, FT_ULong* char_out)
+ {
+ #if PY_VERSION_HEX >=3D 0x01060000
+     if (PyUnicode_Check(string)) {
+         Py_UNICODE* p =3D PyUnicode_AS_UNICODE(string);
+         int size =3D PyUnicode_GET_SIZE(string);
+         if (index >=3D size)
+             return 0;
+         *char_out =3D p[index];
+         return 1;
+     } else
+ #endif
+     if (PyString_Check(string)) {
+         unsigned char* p =3D PyString_AS_STRING(string);
+         int size =3D PyString_GET_SIZE(string);
+         if (index >=3D size)
+             return 0;
+         *char_out =3D (unsigned char) p[index];
+         return 1;
+     }
+     return 0;
+ }
+
  static PyObject*
  font_getsize(FontObject* self, PyObject* args)
  {
      int i, x;
+     FT_ULong ch;

      /* calculate size for a given string */
!
!     PyObject* string;
!     if (!PyArg_ParseTuple(args, "O:getsize", &string))
          return NULL;

  #if PY_VERSION_HEX >=3D 0x01060000
!     if (!PyUnicode_Check(string) && !PyString_Check(string)) {
! #else
!     if (!PyString_Check(string)) {
  #endif
+         PyErr_SetString(PyExc_TypeError, "expected string");
+         return NULL;
+     }

!     for (x =3D i =3D 0; font_getchar(string, i, &ch); i++) {
          int index, error;
!         index =3D FT_Get_Char_Index(self->face, ch);
          error =3D FT_Load_Glyph(self->face, index, FT_LOAD_DEFAULT);
          if (error)
              goto failure;
***************
*** 123,146 ****
      Imaging im;
      int index, error, ascender;
      unsigned char *source;
      FT_GlyphSlot glyph;

      /* render string into given buffer (the buffer *must* have
         the right size, or this will crash) */
!     char* text;
!     int chars;
      long id;
!     if (!PyArg_ParseTuple(args, "s#l", &text, &chars, &id))
          return NULL;

  #if PY_VERSION_HEX >=3D 0x01060000
!     /* FIXME: Unicode support */
  #endif

      im =3D (Imaging) id;

!     for (x =3D i =3D 0; i < chars; i++) {
!         index =3D FT_Get_Char_Index(self->face, (FT_ULong) text[i]);
          error =3D FT_Load_Glyph(self->face, index, FT_LOAD_RENDER);
          if (error)
              goto failure;
--- 152,180 ----
      Imaging im;
      int index, error, ascender;
      unsigned char *source;
+     FT_ULong ch;
      FT_GlyphSlot glyph;

      /* render string into given buffer (the buffer *must* have
         the right size, or this will crash) */
!     PyObject* string;
      long id;
!     if (!PyArg_ParseTuple(args, "Ol:render", &string, &id))
          return NULL;

  #if PY_VERSION_HEX >=3D 0x01060000
!     if (!PyUnicode_Check(string) && !PyString_Check(string)) {
! #else
!     if (!PyString_Check(string)) {
  #endif
+         PyErr_SetString(PyExc_TypeError, "expected string");
+         return NULL;
+     }

      im =3D (Imaging) id;

!     for (x =3D i =3D 0; font_getchar(string, i, &ch); i++) {
!         index =3D FT_Get_Char_Index(self->face, ch);
          error =3D FT_Load_Glyph(self->face, index, FT_LOAD_RENDER);
          if (error)
              goto failure;
***************
*** 198,210 ****

      /* attributes */
      if (!strcmp(name, "family"))
!         return Py_BuildValue("s", self->face->family_name);
      if (!strcmp(name, "style"))
!         return Py_BuildValue("s", self->face->style_name);

      if (!strcmp(name, "glyphs"))
          /* number of glyphs provided by this font */
!         return Py_BuildValue("i", self->face->num_glyphs);

      PyErr_SetString(PyExc_AttributeError, name);
      return NULL;
--- 232,249 ----

      /* attributes */
      if (!strcmp(name, "family"))
!         return PyString_FromString(self->face->family_name);
      if (!strcmp(name, "style"))
!         return PyString_FromString(self->face->style_name);
!
!     if (!strcmp(name, "ascent"))
!         return PyInt_FromLong(PIXEL(self->face->size->metrics.ascender)=
);
!     if (!strcmp(name, "descent"))
!         return PyInt_FromLong(-PIXEL(self->face->size->metrics.descende=
r));

      if (!strcmp(name, "glyphs"))
          /* number of glyphs provided by this font */
!         return PyInt_FromLong(self->face->num_glyphs);

      PyErr_SetString(PyExc_AttributeError, name);
      return NULL;