[cairo] Serious concerns about cairo

Bill Spitzak spitzak at d2.com
Tue Sep 26 16:16:02 PDT 2006

Behdad Esfahbod wrote:

>> * Font metrics that return rectangles (such as bounding boxes, offsets 
>> to parts of the image, and the horizontal/vertical advance pairs) return 
>> a rectangle with the same *area* as if the font was not rotated. This 
>> appears to be the most useful value. Rotating the CTM after specifying 
>> the font is not recommended, so we don't care about preventing 
>> intersections, and any other solution results in huge boxes.
> Not sure what this exactly means, but I believe the huge boxes are more
> useful than any other interpretation.  They can be used to draw bounding
> boxes after all.

If the actual bounding boxes can be determined, it should return those. 
What we don't want is a sudden massive change in the font metrics if the 
back end switches to being able to return the actual bounding boxes. 
Since the area-preserving box is a much closer guess, I recommend 
returning that.

>> * Add an api to specify the pen as a 2x2 matrix, used to transform a 
>> .5-radius circle to get the pen. This is so that a get-pen api can work.
> Instead of a 2x2 matrix, use a regular matrix and use the translation
> components to shift the pen.  That is consistent with the font matrix,
> and actually not quite useless.

My only concern with this is that it may be somewhat inconsistent 
because the translation of the CTM is *not* multiplied by the pen/font 
matrix to get the resulting matrix to device space. The 2x2 matrix makes 
it clear there can be no translation component from the CTM. However if 
fonts are already doing this (and patters certainly are!) then the 
probably should be done for pens, too.

>> * Dashed lines are done by inverse-transforming the path to pen space, 
>> converting the path to dashes using the simpler unit circle for the pen, 
>> and then transforming the resulting path back and filling it. Thus 
>> dashes will scale with the size and shape of the pen.
>> * There is a "dash size" variable, and the dash pattern is multiplied by 
>> this before use to make the dash. This is for back compatability. The 
>> older set-pen that takes a single number r for the pen sets the pen 
>> matrix to [r 0 0 r]*ctm and sets the dash size to 1/r. Add an api to 
>> directly get/set the "dash size".
> This works.  Or we may be able to come up with more interesting ways to
> keep backwards compatibility.

I actually thought about this quite a bit, and this is the best I can 
come up with. The only unknown is if the new pen api should reset the 
dash size to 1.

>> II. Proposed fix for "hairline" mode:

>> * Setting the line width to zero (or setting the pen to a degenerate 
>> matrix) puts Cairo into "hairline" mode. Setting the pen to a non-zero 
>> size (including negative) turns off hairline mode.
> A degenerate pen matrix is completely useful on its own.  For example,
> to emulate a calligraphic pen.  Ok, you probably don't want the
> degenerate case for that, but it is well-defined already.  Charging it
> to do something else is confusing.
> Why not add an explicit hairline mode?  If you set the pen, hairline
> mode is gone.  Ugly, but better than overloading the pen.

An explicit hairline mode, as long as setting the pen turns it off, 
would be acceptable. The main reason I have for zero doing it is that 
this matches what every other graphics api does, which would make 
emulation easier. But it probably is not very hard for the emulator to 
check for the pen being set to zero.

You are correct that a degenerate pen matrix does not necessarily have a 
zero cross-section and thus can draw something. The stroke algorithim 
will need to switch to a different method for this, since the default is 
to inverse-transform the (flattened?) path to pen space, figure out the 
stroke and dash bounds there, and transform it back.

My guess as to the degenerate pen algorithm: transform the unit circle 
to pen space, resulting in a straight line. Use the end points of the 
straight line and transform the path by these two points. Somehow join 
all the matching points of these paths and then fill the area between 
them. If the two points are the same it draws nothing.

>> * A new cairo context defaults to hairline mode.
> This totally breaks current API

Unfortunately you are probably right. An alternative solution would be 
to have cairo-using widgets turn on hairline mode initially in the cairo 
contexts they create. The main thing is so that a beginning programmer 
does not see those thick lines initially.

>> * To draw a UTF-8 string, there is an api that takes a pointer to the 
>> string, it's length, and NOTHING ELSE, and the result is the text 
>> appears on the output surface. Any structure or context or anything else 
>> other than the cairo_t is by my definition, NOT "fun or easy to use", 
>> and thus contrary to Cairo's design goals.
> That's the current toy API indeed.

Yes, I think the problem is that since programmers *want* the toy api, 
they are going to use it, no matter how much you say "use pango". The 
only way to get them to use I18N is if they can seamlessly transistion 
from the "toy" api to the full one by gradually adding more advanced 
calls. Therefore the "toy api" must not bypass any layout engine, and 
whatever sets the font for the "toy" api must also set the font for the 
advanced api.

> I have plans for the user-font API to let the toy API switch to higher
> level systems like Pango transparently (if you set it up, which should
> be a matter of a single Pango call done just once.)

This is probably the solution, though I think it will have to be enabled 
by default.

More information about the cairo mailing list