[cairo] Userfont hinting

Behdad Esfahbod behdad at behdad.org
Thu May 15 17:26:35 PDT 2008

On Sun, 2008-05-11 at 02:27 +0100, Peter Clifton wrote:

> It appears that the user-font code in cairo doesn't compute the correct
> extents at various rotations.

user-font code does the right thing.  The extent code in analysis
surface doesn't.  It computes extents of each operation in device space,
then converts it into the desired space (analysis ctm).

Now that answers your question from a few days ago, that why can't we
just not set ctm on analysis surface and convert the metrics afterward.
Because that would compute the union of the bounding box of the
operations all in device space, and convert the union box to the ctm.
That gives even worse results than the current code.  Imagine you have
to operations in the places marked by X:
     / \
    / X )
   /   /
  /   /
 ( X /

The box I drew is pretty much what you get currently, which is "union of
(bounding box of operation in device space, converted to target space)".
Ideally you simply want "union of (bounding box of operation in target
space".  What you get if you don't set ctm on analysis surface and just
convert the extents at the end is "union of (bounding box of operation
in device space), converted to target space", which for the example
above will be:

   /  \
 /|   X|\
/ |    | \
\ |    | /
  \    /
   \  /

Which has a much larger area than the tight box, or that of what we
currently compute.

Note that this is already happening for show_glyphs() calls in analysis
surface.  But previous uses of analysis-surface ctm has been with
scale-only matrices, so it wasn't an issue.

> I'll post some patches I used to hack this into working, but someone
> with a clue (Behdad?) should take a look :)
> It seems that setting the ctm on the analysis surface doesn't have the
> desired effect, (to rotate the replayed meta-surface strokes as they go
> down), and only seems to serve to bloat the bounding box for rotated
> glyphs.
> e.g.:
>      /\
>     /  \
>    /    \
>   /------\   _ x axis.
>  / | /\ | \  /|
> /  |/  \|  \/
> \  |\  /|  /
>  \ | \/ | /
>   \------/
>    \    /
>     \  /
>      \/
>       \ |
>       _\| y axis.
> Inner box is the glyph being drawn (supposed to be a rotated rectangle).
> In font space, this is upright:
>   _                                /\
>  |_| in user space, it is rotated: \/
> If we analyse this with an identity ctm, we get bounds as the middle
> rectangle. (x and y axies horizontal & vertical). It seems that by
> setting the analysis surface ctm to the scale_inverse matrix from the
> scaled_font, we only increase the bounds further (outer box).
> I've had a stab at bodging around this by setting the device_transform
> matrix on the analysis surface. This also required extending the
> implementation of _cairo_path_fixed_device_transform(...) to work with
> an arbitrary matrix.

Using device_transform was what I had originally planned and even
implemented, just to change later.  It sounds like it completely solves
the problem, except for one very ugly catch: the show_glyphs calls end
up using a different scaled-font, so the computed extents will be
affected by glyphs hinted for a different matrix.  That's pretty
unacceptable in user-font code.

I'm yet to find the right fix.  Maybe I just add some special code to
cairo-scaled-font and make analysis-surface use that, and then we can
completely drop the ctm support in analysis surface and just use

> I repeatedly fell over the fixed-point scaling in the analysis surface
> though, so what I have may still be wrong.

I gave up when I had to implement that initially.  Now I got it for
free.  Haha.

> Note the change from offsetting the glyph image by its (font space)
> bearings, to its (device space) bounding box.



"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759

More information about the cairo mailing list