Introduction to freetypy

Since freetypy closely follows FreeType’s native C API, the FreeType documentation serves as a good introduction to freetypy as well.

Basic usage

The convention for importing freetypy is:

>>> import freetypy as ft

First, load a font from a file. freetypy also supports loading a font from a Python file-like object:

>>> face = ft.Face("Vera.ttf")

Then the size (in points) must be selected:

>>> face.set_char_size(48)

Once that setup is performed, a glyph may be loaded. We pass load_flags=ft.LOAD.RENDER to tell FreeType to load the glyph outline and then subsequently render it to a bitmap:

>>> glyph = face.load_char_unicode(u"S", load_flags=ft.LOAD.RENDER)
<freetypy.Glyph at 0x17afb00>
>>> bitmap = glyph.bitmap

The bitmap data can be converted to a list:

>>> bitmap.to_list()
[[0L, 0L, 0L, 0L, 0L, 0L, 10L, 85L, 142L, 195L, 222L, 238L, 252L,
 243L, 230L, 207L, 170L, 132L, 76L, 17L, 0L, 0L, 0L, 0L, 0L, 0L] ...

However, to display it at the console, it’s usually nicer to use the freetypy.util.bitmap_to_ascii helper function:

>>> ft.util.bitmap_to_ascii(bitmap)
       .+*******++.
     +*############**.
   .*##################
  .*###################
  *####*+.     .++*####
 *###*.            .*##
.###*.               .*
+###+
*###
*###
*###
*###
*###+
+####+
 #####*+.
 +#######**+.
  *###########**+.
   +##############*+
    .*##############*.
      .+*############*.
          .++*########*
               .+*#####*
                  +*####.
                   .*###+
                    +###*
                     ###*
                     ###*
                     ###*
                     ###*
                    +###+
*.                 .####.
##*+              +*###*
#####*+..      .+*#####.
#####################*.
####################*.
 .+*##############*+
     .++*******+.

This Bitmap is a Python buffer object. If you have Numpy, you can easily convert this data to an array:

>>> import numpy as np
>>> array = np.array(bitmap)

Getting the outline from a glyph

To get the outline data from a glyph, for example to convert it to another format, the easiest way is to use freetypy.Outline.decompose:

class Decomposer(object):
    def __init__(self):
        self.entries = []

    def move_to(self, point):
        self.entries.append(('move_to', point))

    def line_to(self, point):
        self.entries.append(('line_to', point))

    def conic_to(self, a, b):
        self.entries.append(('conic_to', a, b))

    def cubic_to(self, a, b, c):
        self.entries.append(('cubic_to', a, b, c))

face = ft.Face("Vera.ttf")
face.set_char_size(12, 12, 300, 300)
glyph = face.load_char(ord('B'))

d = Decomposer()
glyph.outline.decompose(d)
print(d.entries)

This outputs:

[('move_to', (640.0, 1088.0)),
 ('line_to', (640.0, 256.0)),
 ('line_to', (1130.0, 256.0)),
 ('conic_to', (1402.0, 256.0), (1533.0, 358.0)),
 ('conic_to', (1664.0, 461.0), (1664.0, 673.0)),
 ('conic_to', (1664.0, 886.0), (1533.0, 987.0)),
 ('conic_to', (1402.0, 1088.0), (1130.0, 1088.0)),
 ('line_to', (640.0, 1088.0)),
 ('move_to', (640.0, 2048.0)),
 ('line_to', (640.0, 1344.0)),
 ('line_to', (1093.0, 1344.0)),
 ('conic_to', (1317.0, 1344.0), (1426.0, 1431.0)),
 ('conic_to', (1536.0, 1518.0), (1536.0, 1696.0)),
 ('conic_to', (1536.0, 1873.0), (1426.0, 1960.0)),
 ('conic_to', (1317.0, 2048.0), (1093.0, 2048.0)),
 ('line_to', (640.0, 2048.0)),
 ('move_to', (320.0, 2304.0)),
 ('line_to', (1115.0, 2304.0)),
 ('conic_to', (1471.0, 2304.0), (1663.0, 2154.0)),
 ('conic_to', (1856.0, 2005.0), (1856.0, 1729.0)),
 ('conic_to', (1856.0, 1516.0), (1756.0, 1389.0)),
 ('conic_to', (1656.0, 1263.0), (1462.0, 1232.0)),
 ('conic_to', (1710.0, 1183.0), (1847.0, 1027.0)),
 ('conic_to', (1984.0, 872.0), (1984.0, 640.0)),
 ('conic_to', (1984.0, 334.0), (1766.0, 167.0)),
 ('conic_to', (1548.0, 0.0), (1146.0, 0.0)),
 ('line_to', (320.0, 0.0)),
 ('line_to', (320.0, 2304.0))]