[Cairo] Re: [xsvg] cairo_text_extents ?

Bill Spitzak spitzak at d2.com
Tue Dec 2 15:58:06 PST 2003

On Wednesday 26 November 2003 11:41 pm, Christof Petig wrote:
> Bill Spitzak schrieb:
> > I have gotten zero response to my proposal that there be two matricies,
> > so that the y_advance can be defined as zero, and the user can choose
> > exaclty what coordinate system the metricies are returned in. Has anybody
> > read it? Is it a stupid idea, or why isn't anybody saying anything?
> I had some difficulties understanding your exact proposal.

There are two 2x2 matricies: the text_matrix, and the font_matrix. Font 
glyphs are transformed by the concatenation of these matrices before being 

The text_matrix can only be changed by copying the current cairo 
transformation, and by grestore. The purpose of it is so you can use cairo 
transforms to position your text next to a graphic without altering the 
letter shapes themselves, similar to OpenGL. For instance you can draw a 
horizontal label next to a corner in a rotated and scaled transform by doing:
set_text_matrix, rotate, scale, moveto, then drawing text.

The text_matrix is not a requirement, we could define that it be identical to 
the current transform at all times, like in PostScript. Horizontal labels 
could still be drawn by doing a grestore after the moveto and before drawing 
the letters. I thought making it a seperate matrix would be useful, and by 
limiting the settings to just copying the current matrix we get the 
advantages while still having the clean PostScript design.

The font_matrix serves several purposes:

1. It gets rid of the confusion about what coordinate system font 
measurements are in. If there was only one matrix, then measurements of font 
info must be either returned either in device space or in font space. Device 
space is an incredible pain for laying out rotated text and makes metricies 
really complicated (for instance the bounding box needs 8 numbers to be 
correct). Font space is a real pain for software that wants to lay out text 
with different-scaled fonts. With two matricies we can define the metrics to 
be measured between them, allowing the programmer to choose exactly how much 
transform to put on each side.

2. It allows y_advance to be defined as zero, while still allowing rotated 
letters, and rotated baselines. This simplifies text layout code 
*enormously*, for instace the escapement of a string can be returned directly 
by a C function, rather than as a structure of two numbers, and makes it easy 
to use the bounding box for line spacing and detecting real visible overlap.

3. It seems that "oblique" is often done with some sort of font matrix 
anyway, so exposing it like this is probably free.

4. It makes it easy to take software that already thinks about "current font 
size" and make the output scale.

> Am I correct
> to assume that you want individual glyph transformation and text
> (advance) direction transformation to be independant. (e.g. drawing
> left-to-right text top-to-bottom or writing mirrored/flipped glyphs in a
> normal direction or positioning upright letters along a diagonal line.)

I think so. Glyphs are transformed by the text_matrix*font_matrix, but text 
advance is done by the text_matrix only. So by setting the font_matrix they 
are independent. However font metricies and text advance direction are NOT 
independent, in fact the "y_advance" is defined to always be exactly zero. It 
may also be that "x_advance" is defined to be >= 0. This non-independence was 
far more important to me because of the huge simplification of layout code.

In my proposal the font_matrix was not arbitrary, as I did not allow 
rotation. This was because I thought it necessary so that y_advance was zero. 
However the rotation could in fact be allowed and it would produce rotated 
glyphs but the text would still layout on a horizontal line. For this to be 
useful at all, I think the font will have to be able to choose the 
translation (ie the center or rotation) and make it different for each glyph 
and each rotation. And it has to be able to change the x_advance in different 
ways depending on the rotation. This is so if you rotate 90 degrees you get 
glyphs that can be laid out as vertical text (assumming a -90 degree rotation 
is appled in the text_matrix). A rotation around the origin would not produce 
anything nice for any proportional font.

> The only extension I might envision is to place text along a curve.
> (with or without glyph rotation). [I use this regularly in DTP.]

This can be done by altering the text_matrix before drawing each letter. The 
x_advance can be considered the distance along the curve.

> > In my opinion the zero-y_advance idea will work, so imagine the second
> > drawing of vertical text rotated sideways so the "advance" is in the x
> > direction, and X and Y and width and height have been swapped in all the
> > names, and yMin and yMax have been swapped. It is then identical except
> > bearingY is in the opposite direction.
> I think that if you want to draw CJK fonts you need vertical advance. If
> you map vertical advance to horizontal advance you will get wrong spacing.

No, the x_advance value will be set to produce the correct spacing.  If a 
font actually contains "vertical advance" information, this is simply used as 
the horizontal advance when 90 degree rotation is selected. If you don't use 
the text_transform, you will see perfectly fine output if you turn your 
monitor sideways.

> E.g. if you draw upright characters at 45° you would compute a decent
> y_advance (e.g. by bounding box) and take 0.70 of y_advance for y and
> 0.70 of the font's x_advance for x.

If a font description has a vertical advance dy and a horizontal advance dx, 
I would transform the vectors (0,dy) and (dx,0) by the font transform, take 
the absolute value of the x coordinates of the results and add them together, 
and return this as the x_advance. Thus the information stored in the font is 
not lost.

In your example I would rotate the text_transform by 45 and the font 
transform by -45. This font transform would produce an x_advance of 
sqrt(2)/2*(dx+dy). The text_transform would turn this back into an x_advance 
and a y_advance of (dx+dy)/2. If you imaging square letters, they boxes would 
just touch at the corners.

                   ,~,~,~,~ ~ ~ ~ ~
     /\_       _|_========___         Bill Spitzak
 ~~~/\/\\~~~~~~\____________/~~~~~~~~ spitzak at d2.com

More information about the cairo mailing list