[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