1
votes

I'm quite new to Cairo, and was fiddling with a program to generate small SVG images. I'd wanted to fill regions of some of these images with repeating patterns that were also constructed in Cairo - in other words, I've been trying to draw on a Cairo surface in memory and then use it as a source pattern to fill paths on another surface. From the API, this looks as though it should be relatively straightforward, but I seem to be missing something as attempting something as simple as a pattern from a surface with a background color and a simple shape is only filling with the surface's background color.

A relatively minimized example is below (have been using paths instead of rect as my intended usage involves arbitrary shapes):

import cairo

def drawPattern(ctx):
    ctx.move_to(0.0, 0.0)
    ctx.line_to(0.0, 1.0)
    ctx.line_to(1.0, 1.0)
    ctx.line_to(1.0, 0.0)
    ctx.line_to(0.0, 0.0)
    ctx.set_source_rgb(0.8, 1.0, 0)
    ctx.fill()
    ctx.move_to(0.5, 0.8)
    ctx.line_to(0.8, 0.5)
    ctx.line_to(0.5, 0.2)
    ctx.line_to(0.2, 0.5)
    ctx.line_to(0.5, 0.8)
    ctx.set_source_rgb(0, 0, 0)
    ctx.fill()

surf = cairo.SVGSurface("test.svg", 256, 256)
context = cairo.Context(surf)
context.scale(256, 256)

patternSurf = cairo.SVGSurface(None, 32, 32)
patternCtx = cairo.Context(patternSurf)
patternCtx.scale(32, 32)
drawPattern(patternCtx)
patternSurf.flush()

context.move_to(0.0, 0.0)
context.line_to(0.0, 1.0)
context.line_to(1.0, 1.0)
context.line_to(1.0, 0.0)
context.line_to(0.0, 0.0)
context.set_source_rgb(0.0, 1.0, 0.0)
context.fill()

context.move_to(0.5, 0.0)
context.line_to(0.5, 1.0)
context.line_to(1.0, 1.0)
context.line_to(1.0, 0.0)
context.line_to(0.5, 0.0)
context.set_source_surface(patternSurf)
context.get_source().set_extend(cairo.Extend.REPEAT)
context.fill()

surf.finish()

My aim for this example was that it would produce a simple square image, with the left half green and the right half more of a yellow-green with repeated black diamonds. However, the diamonds do not appear, although the yellow-green background color does (this is representative of the broader issue I've been having). How would this be corrected so that the surface with the black diamonds is correctly used as a repeating pattern fill for the other surface?

I'm using Pycairo, with installed Cairo version 1.14.12, though I imagine the question is probably general to Cairo usage rather than specific to the Python bindings.

1

1 Answers

3
votes

You are scaling your image up when drawing it to surf. Due to the initial context.scale(256, 256), the surface contents of patternSurf are scaled with a factor of 256 before drawing. When I add contxt.scale(1.0/256.0, 1.0/256.0) before the call to set_source_surface, I get the result that I guess you expect.