In the world of digital font formats we have several different kinds of ways of describing outlines. Cubic bezier curves for PostScript fonts, quadratic curves for TrueType fonts. Each with their own peculiarities. FontParts is format-agnostic, so it should be able to store all PostScript and all TrueType points. The structure here is meant to be able to do all that.

Contours

A glyph can contain one or more contours. Depending on what you want to do, there are different ways of looking at the data of the contour, the points, the line segments. The RContour object is way to the outlines.

a contour
# take a glyph (one with outlines obviously)
glyph = CurrentGlyph()

# get to contours by index:
print(glyph[0])

# get the 'length' of a contour:
print(len(glyph[0]))
>>> <Contour of glyph:a>
>>> 18
>>> # 18? 18 of what?

A description of the RContour object.

Segments

This circle consists of a couple of segments, each a piece of the contour. A contour is a sequence of segments, you can iterate through a contour to get segments. A contour also has methods for adding and deleting segments.

a contour’s segments
glyph = CurrentGlyph()
contour = glyph[0]

for segment in contour:
    print(segment)
>>> <Segment object>
>>> <Segment object>
>>> <Segment object>
>>> ...

In turn, a segment is made up of a sequence of points. Any number of off-curve points followed by an on-curve point. For the PostScript-centric designers: in TrueType outlines it is allowed to have any number of off-curve points before an on-curve. These points know whether they need to be rendered as bezier or quadratic curves.

segments with on-curve and off-curve points

A description of the RSegment object.

Points

Another way to look at a contour is as a sequence of on-curve and off-curve points. This is the approach taken by glyph.drawPoints() and PointPen.

points (on-curve and off-curve)
# get straight to the points in a contour
# through the points attribute

glyph = CurrentGlyph()

for aPt in glyph[0].points:
    print(aPt)
>>> <Point x:119 y:314>
>>> <Point x:117 y:343>
>>> <Point x:115 y:372>
>>> <Point x:133 y:432>
>>> etc..

A description of the RPoint object.

bPoints

This is another way to look at contours and its parts: bPoints behave very much like RoboFog points used to do. A point object has an incoming BCP, an on-curve (“anchor point” fog called it) and an outgoing BCP. This approach has been added for folks more at ease with the RoboFogA fork of Fontographer with a built-in Python interpreter. structure.

If the contour contains series of off-curve points, bPoints won’t help you.

bPoints with incoming and outcoming BCPs
# bpoints

glyph = CurrentGlyph()

for aPt in glyph[0].bPoints:
    print(aPt.anchor)
    print(aPt.bcpIn)
    print(aPt.bcpOut)
    print(aPt.type)
    print()
>>> (119, 314)
>>> (0, 0)
>>> (0, 0)
>>> corner
>>>
>>> (117, 343)
>>> (0, 0)
>>> (-2, 29)
>>> corner
>>>
>>> ...

A description of the RBPoint object.


Adapted from the RoboFab documentation.

Text by Erik van Blokland, diagrams by Tal Leming.

Last edited on 01/09/2021