[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
drawn.
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