Reputation: 135
I't trying to fill a polygon with pyCairo
, but I want certain areas to ramin unfilled. For instance, I'd like to produce something like this:
The grey background is the background of the SVG viewer, so represents transparent portions of the image.
I tried with this code:
import cairo
cairo.FILL_RULE_EVEN_ODD
svg_file_pointer = open('CairoPoly.svg', 'wb')
shape_container = cairo.SVGSurface(svg_file_pointer, 500, 500)
shape_description = cairo.Context(shape_container)
shape_description.rectangle(0, 0, 500, 500)
shape_description.clip_preserve()
shape_description.stroke()
shape_description.set_line_width(1)
shape_description.set_source_rgb(20/51, 0, 0)
for r in ((100, 100, 400, 400), (200, 200, 350, 300), (150, 110, 190, 390)):
shape_description.move_to(r[0], r[1])
shape_description.line_to(r[0], r[3])
shape_description.line_to(r[2], r[3])
shape_description.line_to(r[2], r[1])
shape_description.line_to(r[0], r[1])
shape_description.close_path()
shape_description.fill()
shape_container.finish()
svg_file_pointer.close()
del shape_container
But it doesn't work. Can this be done with pyCairo, and if yes, how?
Upvotes: 1
Views: 1323
Reputation: 101820
I'm not familiar with pyCairo, but the basic idea of what you are doing is correct from an SVG perspective. You are close, but not quite right.
What you want to do is create a path with sub-paths for each of your rectangles.
<svg width="500" height="500">
<path d="M 100,100 L 100,400 L 400,400 L 400,100 L 100,100
M 200,200 L 200,300 L 350,300 L 350,200 L 200,200
M 150,110 L 150,390 L 190,390 L 190,110 L 150,110 Z"
fill-rule="evenodd" />
</svg>
It looks like this is more or less what you are doing, but you'll also need to change the fill-rule to "evenodd". The default of "nonzero" will result in your "holes" being filled in instead of being left as holes.
set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
Upvotes: 2
Reputation: 328614
To get a polygon with holes, you need to define the outline. The outline must be a single stroke. Edges which partially overlap will cause problems. My suggestion: Too hard to get right.
I see two solutions:
Note: There are 2D libraries which can intersect rectangles for you. If you have one (there might even be one in Cairo), then you can let the library calculate the necessary list of rectangles by applying boolean operations to the outer rectangle (adding and removing rectangles from it to get lists of rectangles).
Upvotes: -1