[GRASS-dev] Cairo monitor driver

Lars Ahlzen lars at ahlzen.com
Tue Oct 16 20:05:39 EDT 2007

Glynn Clements wrote:
> I've committed [the cairo driver] to CVS, with a few changes; mostly, just
> conforming to existing coding and formatting conventions.

Thanks! I very much appreciate the time you obviously spent on looking 
at the code, cleaning it up and adding it.

> The main one is that code should stick to ANSI C89...
> Variables which aren't used outside of the file in which they are
> defined should be declared "static".

Noted. I guess I should have enabled the -ansi flag in GCC.

> The only externally-visible change is that the driver and monitor
> names have been changed from "CAIRO" to "cairo" (the web site treats
> "cairo" as a normal word, i.e. all lower-case except in a title or at
> the beginning of a sentence). PNG and PS are upper-case as they are
> acronyms; XDRIVER is a historical artifact (and the monitor names are
> "x0" etc).

Makes perfect sense.

> A question about the set_drawing_op/finish_drawing_op stuff: is this
> meant to merge distinct line segments into a single path? If so, I'll
> remove it.
> The lack of begin/end operations for paths (move/cont) is a flaw in
> the interface, and is one of the planned interface changes for 7.x. 
> Note that the PS driver doesn't attempt to hack around this; if you
> want a single path, you have to use the polyline operation.

Yes, it was primarily to ensure that lines are connected (for nice line 
joins etc). But I guess you're right - that's what polyline is for.

I believe this means that pretty much all of drawing.c can go. One would 
have to call cairo_stroke or cairo_fill directly from the drawing 
functions instead.

> The global cairo_translate(cairo, 0.5, 0.5) is wrong. If you want to
> work around the problems with lines having their endpoints on pixel
> boundaries (rather than centres), apply the translation only to lines. 
> Other operations (box/polygon fills, images, text) should *not* be
> translated in this way. FWIW, the PS driver doesn't even translate
> lines.

Well, this one is a little bit tricky.

You're right that filled shapes and images must not be translated to 
remain sharp. However, this would not really produce a correct result 
either (with correct being defined as similar to other drivers).

If ONLY lines were translated and nothing more was done, the 1/2 pixel 
offset between lines and filled shapes would very likely cause issues 
where lines and filled areas meet.

Furthermore, there's a problem with polygon size. Consider a case of a 
filled rectangle from (10,2) to (20,3). Mathematically (and the way 
Cairo sees things) this is a 10 units wide by 1 unit tall rectangle. 
Pixel based drivers (PNG, X, etc) would draw an 11 pixel wide and 2 
pixel tall rectangle. Cairo, assuming no translation, would draw a 10 
pixel wide and 1 pixel tall rectangle. OTOH, with the translation and 
antialiasing enabled, cairo would draw an 11 pixel wide and 2 pixel tall 
rectangle, but with fuzzy edges (on a pixel-based "canvas"), which 
seemed (and still seems) like the less bad of the two options to me.

So, why not just disable translation for filled rectangles and make them 
one unit wider and taller (for pixel-based output)? This approach might 
work for rectangles, but not for arbitrary shapes, such as a triangle - 
at least not in any trivial way.

I don't believe that adding the offset to lines only would solve the 
fundamental problem, or even really improve the situation, although I'm 
happy to try it if you insist.

One could also forget about the whole offset thing and accept fuzzy 
lines, knowing that this is only a problem because of the current lack 
of floating point coordinates. It's either sharp lines or sharp filled 
shapes. Having tried both, I personally much prefer the former, though. 
Quoting from the official Cairo FAQ regarding fuzzy lines [1]:

"It is not possible to set up sample locations in a way so that both 
fills and strokes with integer coordinates work nicely, so one had to be 
preferred over the other. One argument in favor of preferring fills is 
that all fills with integer coordinates align nicely this way. The best 
that can be done with strokes is to make all even-integer-width strokes 
align nicely (as they do in cairo) or to make odd-integer-width strokes 
align (which would then break the fill alignment)."

[1] http://www.cairographics.org/FAQ/#sharp_lines

Regarding the comparison with the PS driver, note that the cairo driver 
applies the translation ONLY for pixel-based formats (PNG). It doesn't 
translate anything for PS output (or any other vector format) either.

> The use of pkg-config really belongs in the configure script...
> At present, the only way to enable the cairo driver is to manually set
> USE_CAIRO=1, e.g. "make USE_CAIRO=1".

Yes, the makefiles need work. Ideally, this should probably be a 
configure option, i.e. ./configure --with-cairo

> The raster library should be extended to allow direct rendering via
> cairo, but we should get it working fully first.
> I note that clipping isn't enabled, and that the bitmap primitive
> (used for freetype text, amongst other things) is a no-op. Both of
> these are relatively important; the bitmap primitive would be less
> important if the driver implements the draw_text method using cairo's
> built-in font rendering.
> AFAICT, clipping should just be a matter of calling cairo_reset_clip()
> and cairo_clip(). Ignore the encapsulation issues; again, that's an
> interface flaw (which also affects the PS driver).

I agree, clipping and Draw_bitmap should be added ASAP. Neither should 
be very difficult to implement.

Please prove me wrong here, but one of the problems I've had is that the 
documentation on the monitor interface (such as driver struct) in the 
Grass Programmer's manual is virtually nonexistent. Most of the cairo 
driver work was done by looking at the PNG and PS drivers with some 
trial-and-error thrown in. Does complete documentation for these areas 

Given the text rendering support in Cairo, I hope that adding good 
quality text rendering will be relatively straightforward as well.

I take it that the best thing for me to do right now would be to work on 
  the mentioned issues and missing features and post a patch? Perhaps 
add basic documentation in display/drivers/cairo as well?

Again, thanks for the feedback!

/ Lars

Lars Ahlzen
lars at ahlzen.com

More information about the grass-dev mailing list