[cairo] fill pre-existing png polygons? (tried formatting better)

Daniel Goldman dagoldman at yahoo.com
Mon Aug 9 11:41:50 PDT 2010


> With GD, I would import a png outline of the map that has been generated 
>before, 
>
> and use gdImageFill () to fill a polygon. With cairo, it's easy to get the 
> outline map in with cairo_image_surface_create_from_png (). But I'm getting the 
>
> feeling that is not a helpful step under cairo, that cairo does not fill 
> existing png polygons.

Right, cairo doesn't have the equivalent of gdImageFill().

> Can cairo fill polygons from a pre-existing png file? 

Sort of.  What you can do is have an image consisting of only an alpha 
channel containing 0.0 where you don't want colour and 1.0 where you 
do (and possibly values in between for antialiasing at the edges), and 
use cairo_mask() to "colour in" the pixels according to their alpha 
values.  Something like this, assuming you have a single polygon in 
the file "polygon123.png" which you want to appear at position 
(poly_x, poly_y):

  cairo_surface_t *poly_mask = 
cairo_image_surface_create_from_png("polygon123.png");
  cairo_set_source_rgb(cr, r,g,b);
  cairo_mask_surface(cr, poly_mask, poly_x, poly_y);
  cairo_surface_destroy(poly_mask);

However, there's a huge downside to this method!  Your pdf maps will 
actually contain prerasterised polygons rather than vector ones (which 
are scalable and can be zoomed into nicely etc.)

> Is it correct the GD model (import png outline map, fill existing 
> polygons) doesn't work under vector-based cairo? 

You're correct that you can't do that with cairo.

> Do I need to use cairo_move_to () and cairo_line_to () to create the 
> polygons in real-time before filling them?

This is the preferred way to make it work for both vector and raster 
backends.  If rendering is too slow, please let us know!

> My preference is to use the pre-existing outline, since it never 
> changes, but it would not be that big a deal to draw the map each 
> time.

Repeated rendering is best cached into a "similar surface" in cairo: 
you draw it once into a cached surface, and then copy from cached 
surface whenever you need to redraw the same content into your map.

Each backend can create a similar surface from another which retains 
the characteristic of the first.  The idea is that for instance the 
pdf backend can keep its vector drawings in vector form in the similar 
surface, whereas the image backend can rasterise the drawings just 
once.

Joonas

*********************** New reply is below

Thanks for the quick response, and helping me avoid needless experimentation. 
I'll draw all the polygons to be filled in real-time as you suggest. I'm already 
doing so for the pdf output, and it's fast. My guess is there will be no problem 
with the png output. I keep the pdf and png outputs in different contexts and 
surfaces, because the pdf contains explanatory text for the map. The explanatory 
text is left off the png map, and is instead put into HTML along with the png 
map on a web page.

What might be some example cairo functions that cache surfaces? I think what you 
are saying is maybe I can just draw once, and then copy to the png and pdf 
surfaces. I have the png polygon coordinates as integers, and the pdf 
coordinates as doubles. Maybe I might draw with the doubles, and then copy the 
surface to the png map, possibly resizing if a bigger or smaller map is needed.

Daniel


More information about the cairo mailing list