[GRASS-dev] Cairo monitor driver

Dylan Beaudette wrote:

Since the Cairo graphics library (http://www.cairographics.org, LGPL
licensed) provides very high-quality graphics output in several vector
and raster formats, I thought it would make sense to create a "pseudo"
monitor driver for it (similar to the PNG and PS drivers). So I did.
Cairo does all of the hard work, so it's really mostly simple "glue" code.

Indeed. I have been using it for all of my R work lately. I don't know why this hasn't come up before, but something like Cairo actually solves a lot of the problems we are facing: high quality on-screen display, output to PDF...

Yep.

This would also solve the translucency problem, as Cairo can deal with that quite nicely.

Indeed. Cairo has good support for many things that (AFAIK) aren't
directly supported by GRASS yet, but may one day be really nice to have.

Examples include: Transparency (although gis.m "emulates" this using
g.pnmcomp) and more advanced compositing, different line end/join styles
(rounded, beveled, square, ...), high-quality text rendering, line
patterns (dashed, dotted, ...), fill patterns, gradients, free-form
antialiased masking, non-integer line widths etc.

Of course, such niceness comes at a price. It takes longer to draw
complex vector data, compared to the PNG driver. However, I imagine that
in most cases drawing is not the main bottleneck anyway.

For hard copy output like PDF this isn't a problem.

True. And even for screen rendering, in practical cases we're probably
talking about seconds at most.

Additionally, the fact that GRASS monitors (unfortunately) receive
integer data (screen coordinates, line widths, etc) somewhat limits the
effectiveness of the high-precision output from the CAIRO driver. For
example, in the "Massachusetts Counties and roads" example, the
antialiasing breaks down for certain lines because they are divided into
smaller segments whose coordinates are rounded before they are drawn.
Similarly, zooming in on vector output will also reveal this drawback.

Perhaps that rounding can be toggled based on the output device...

I wish, and please prove me wrong here, but I believe that this would
require a (minor) architectural change to GRASS. All monitors drivers
get their drawing coordinates as integer data, e.g. "Draw a line from
position 4, 23 to 5, 45", rather than floating point values, like "Draw
a line from 3.84, 22.96 to 5.41, 45.11".

That makes some sense as long as you only display data on a pixel based
screen/file with no antialiasing or oversampling (like the X or PNG
monitors), but not for higher quality or vector format output.

The PS driver that is currently in the CVS tree seems to suffer from the
same problem, btw, which limits its usefulness as well.

Changing this would probably mean adjusting all monitor drivers (which I
don't think would be overly complicated, but it would take a bit of work).

Eventually it would be nice if GRASS supported floating point for things
like line widths, point/symbol/text sizes and similar things too, but
this would probably require more substantial changes.

My main question is: Does all of this seem useful to anyone else? I do
realize that most of these things can be achieved in other ways, but
I've personally found this driver to produce high quality output in a
very convenient way. Feedback is appreciated!

In the past I would approximate this type of output by rendering a PNG at 2x size and then shrink it down with imagemagick. This would give me nice looking lines, but not as nice as what Cairo does.

I've done the same thing, often even 4x or 6x.

What I found inconvenient about this approach is that, after working at
1x, not only does the resolution need to be changed, but every line
width, symbol size, text size in every drawing command needs to be
scaled accordingly as well. You can get "creative" here with scripting,
but in the end it still means more work for you...

It would also be nice to have an output device which can deal with alpha transparency and PDF versions

= 1.3, which would allow translucency in PDF files.

I would, although I'm not sure how it would be handled by GRASS.

Posting the code would be great - which version of GRASS was this built against?

I am not a developer, but since this is close to something that I would use on a regular basis I can certainly test it out.

Great! I'll post the code to the patch tracker, as suggested by Maciek,
as soon as I can.

Cheers, and thanks for the innovative work!

Thanks for the feedback! It's appreciated.

/ Lars

--
Lars Ahlzen
lars@ahlzen.com

Lars Ahlzen wrote:

>> Additionally, the fact that GRASS monitors (unfortunately) receive
>> integer data (screen coordinates, line widths, etc) somewhat limits the
>> effectiveness of the high-precision output from the CAIRO driver. For
>> example, in the "Massachusetts Counties and roads" example, the
>> antialiasing breaks down for certain lines because they are divided into
>> smaller segments whose coordinates are rounded before they are drawn.
>> Similarly, zooming in on vector output will also reveal this drawback.
>
> Perhaps that rounding can be toggled based on the output device...

I wish, and please prove me wrong here, but I believe that this would
require a (minor) architectural change to GRASS. All monitors drivers
get their drawing coordinates as integer data, e.g. "Draw a line from
position 4, 23 to 5, 45", rather than floating point values, like "Draw
a line from 3.84, 22.96 to 5.41, 45.11".

One of the main changes in 7.x is that graphics coordinates will use
floating-point. For geographic data, the expected approach will be to
set an appropriate transform then use cartographic coordinates.

That makes some sense as long as you only display data on a pixel based
screen/file with no antialiasing or oversampling (like the X or PNG
monitors), but not for higher quality or vector format output.

The PS driver that is currently in the CVS tree seems to suffer from the
same problem, btw, which limits its usefulness as well.

Changing this would probably mean adjusting all monitor drivers (which I
don't think would be overly complicated, but it would take a bit of work).

Changing the drivers is the easy part; it's changing all of the d.*
commands which takes the effort.

--
Glynn Clements <glynn@gclements.plus.com>