[Cairo] Proposed dual-matrix cairo text drawing interface

Bill Spitzak spitzak at d2.com
Tue Nov 25 13:34:47 PST 2003

> Carl Worth wrote:
> ...describe idea of using two matricies...

Here is my proposal for the two-matrix Cairo text interface. These are all 
the calls used by it:

The glyphs are transformed by the concatenation of two matricies, the text 
matrix and the font scaling matrix. The text matrix is unrelated to the 
current transform, except for the fact that it had to be equal to it at one 
time. All measurements are returned in text-matrix units. The purpose of this 
is twofold: first it allows both the convienence of using transforms to place 
labels without transforming the text itself (like OpenGL), while still 
allowing the PostScript feature of scaling an entire drawing. Second, this 
will allow the font scaling matrix to be very limited, such that the 
y_advance can be forced to be zero in all cases, greatly simplifying the 

Here is a a mockup of the proposed interface (the state parameter is 
missing). The "current point" is the last moveto or similar operation.

cairo_set_text_matrix() : Copies the current transform to the text matrix. 
Only ABCD need to be stored, the translation is not used. This and grestore 
are the only ways to change the text matrix.

cairo_get_text_matrix() : The current transformation matrix is replaced with 
a new one such that 0,0 transforms to the current point and ABCD are set 
equal to the current text matrix. This is so cairo drawing operations can be 
used to draw glyphs. Use gsave/grestore to get the previous transformation 

cairo_set_font("name", A,B,D) : "name" selects a font. ABD sets the font 
matrix (unsure what order these are in, but they are x and y scaling, and an 
oblique factor). The font glyphs are scaled by the concatenation of the text 
matrix and the font matrix.  Possibly this is split into two calls, one to 
set the name and the other to set the matrix. Notice that changing the text 
matrix will also rescale the current font. I do not believe a "font object" 
is needed or wanted: hashing the names will allow lookup of an internal 
object very quickly, and any program that does not know the entire set of 
fonts it will ever use ahead of time is pretty much forced to implement such 
a hash table anyway. Also this allows easy disposal of font structures when 
they are no longer referred to by any graphics contexts.

cairo_draw_utf8(dx,dy, unsigned char* a, int n) : dx,dy is transformed by the 
text matrix and added to the current point to produce the origin of the first 
glyph. Each subsequent glyph is drawn at a point that is x_advance,0 
transformed by the text matrix added to the previous one. Any missing glyphs 
are replaced with some visible glyph with a positive x_advance. The bytes 
a[0] through a[n-1] are interpreted as UTF-8. The decoder must pretend a[-1] 
and a[n] are 0 and not look at them. Any sequence of bytes that is not legal 
UTF-8 (including a code using more bytes than necessary!!!) will instead be 
converted so each byte renders one glyph of that value (ie in the 128-255 
range), which will allow this interface to draw ISO-8859-1 in almost 100% of 
all cases.

float cairo_measure_uft8(unsigned char* a, int n) : the x_advance of all the 
glyphs is added together and the x is returned. Since the y_advance is zero 
it is not returned.

float cairo_draw_glyphs(glyphs*, int n) : draw n glyphs. Each structure 
contains a dx,dy distance from the current point in text transform 
coordinates and a ucs32 glyph.

float cairo_draw_utf8s(utf8segment*, int n) : equivalent to n calls to 
cairo_draw_utf8(). Each structure contains a dx,dy, an unsigned char* 
pointer, and a length. I believe this will be more useful for a pango type 
system where the original text is utf8, but I may be wrong...

float cairo_ascent(), cairo_descent(); cairo_get_text_extents(glyphs*), etc : 
return various measurements of the font. They are all returned in the text 
coordinate system, ie they are converted from the raw font information only 
by the font transform. Also y_advance is by definition zero and no field 
should be provided to return it.

cairo_list_fonts(...) : Some kind of interface to enumerate all the
simple strings that can be passed to cairo_set_font. Any more complex
enumeration can be device-specific.

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

More information about the cairo mailing list