[cairo] Serious concerns about cairo

Bill Spitzak spitzak at d2.com
Wed Sep 27 10:23:57 PDT 2006

Bertram Felgenhauer wrote:
> Bill Spitzak wrote:
>> The biggest problem I have with Cairo is the fact that the pen and font 
>> is changed by the current transform
> I don't see that as much of a problem. This is exactly what I need
> when I want to, say, transform an SVG and let the rendering be done by
> a different library (librsvg, say). I'd expect that to be a common
> use case.

As Behdad pointed out this will still work, as long as you set the pen 
*after* doing the transform. Since the SVG interperter almost certainly 
sets the pen as the first step, this will work with no changes.

In fact I suspect that NO Cairo programs, or even any PDF or PostScript 
files, depend on the current behavior. It is possible to make a test in 
Cairo to see if a program is depending on this: when doing a transform 
by the matrix [a b c d x y] check if a*a+c*c!=1 || b*b+d*d!=1 
(indicating it will distort a circular pen) and set a flag. Clear the 
flag on any call to set the pen. And in stroke(), if the flag is set, 
dump a warning message. See if any programs produce this warning.

I would also like the font transfromation to be fixed at the time it is 
set. This is really useful in OpenGL for labelling objects in 3D space, 
and would allow the same ability to use Cairo's transforms to label 
things in 2D. I also suspect that this would simplify font handling 
considerably. However I do think some programs rely on the current 
behavior (mostly demos producing text swirls), but I feel this 
incompatibility is worth it.

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

> I thought the main thing to figure out is that on an image surface
> with identity transform, (0,0) is the corner of a pixel and for lines
> you usually want to start at the center of a pixel instead.

This is really difficult since .5,.5 must be added to the path 
coordinates in device space. You could use the cairo interface to 
transform to device coordinates, then offset them, then use cairo to 
transform back, then use cairo to set the coordinates (3 calls!). This 
suffers from math inaccuracy, and also fails in degenerate transforms.

It is much easier to just never tell Cairo to transform and do the them 
yourself, which appears to be the solution used by all toolkit graphics 

Moving the path is a real pain because emulating a Cairo/PostScript type 
API that has a hairline mode means the entire path must be stored 
locally, because until the fill or stroke is done you cannot know if the 
path needs to be offset or not. The end result is that lots of Cairo's 
machinery is unused and wasted.

> I too would like to see a separate API for that. Using zero line width
> or even negative line widths (which would be the next obvious idea) is
> a dirty hack in my opinion. Degenerate matrices are even worse. How
> close to zero would the determinant have to be?

Negative line widths must draw the same as the absolute value in the 
current Cairo. If asymmetric line caps are ever supported the negative 
line width would reflect them about the centerline of the stroke.

If hairline mode is triggered by zero line width, it will require a 
value==0 to be passed to set-pen. A non-zero value will not turn on 
hairline mode, either due to numeric underflow (when a tiny pen is set 
in a tiny scale) or due to the CTM being degenerate.

It sounds to me like a more popular solution here is to have a separate 
call to turn on hairline mode. This is acceptable because it is no 
problem for an emulator to check for zero in it's set-line-width call. I 
highly recommend that there only be a call to turn on hairline mode, 
turning it off is done by setting the pen.

More information about the cairo mailing list