[cairo] Building an SVG surface with shapes, text, and images together?

Alexander Shulgin alex.shulgin at gmail.com
Sun Sep 12 23:26:57 PDT 2010


On Sun, Sep 12, 2010 at 20:46, John Anderson <sontek at gmail.com> wrote:
> I'm building a website using django and I want to generate an image
> based on some elements in the database. I have text rendering just
> fine but now I want to be able to add images as well but I can't find
> much good documentation on doing this.
>
> Here is what I have so far:
>
> @login_required()
> def view_event_design(request, event_id, design_id, surface_type):
>    design = get_object_or_404(Design, pk=design_id)
>
>    if surface_type == 'png':
>        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
> design.width, design.height)
>    elif surface_type == 'svg':
>        output = StringIO.StringIO()
>        surface = cairo.SVGSurface(output, design.width, design.height)
>    else:
>        return
>
>    context = cairo.Context(surface)
>
>    context.scale(1, 1)
>
>    # grab all elements, sorted by z
>    elements = design.designelement_set.all().order_by('-z')
>
>    # figure out if its a text or an image
>    for element in elements:
>        if element.designelementtext:
>            text = element.designelementtext.text
>            font_size = element.designelementtext.font_size
>            font_face = element.designelementtext.font_face
>            slant = cairo.FONT_SLANT_NORMAL
>            weight = cairo.FONT_WEIGHT_NORMAL
>
>            if element.designelementtext.is_bold:
>                weight = cairo.FONT_WEIGHT_BOLD
>
>            if element.designelementtext.is_italic:
>                slant = cairo.FONT_SLANT_ITALIC
>
>            rgb = hex_to_rgb(element.designelementtext.font_color)
>            context.set_source_rgb (rgb[0], rgb[1], rgb[2])
>            context.select_font_face(font_face, slant, weight)
>
>            context.move_to (element.x, element.y + font_size)
>            context.set_font_size(font_size)
>            context.show_text (text)
>
>
>        elif element.designelementimage:
>            # How do I add an image to the surface?

That would be something like this:

context.rectangle(x, y, width, height)
context.set_source_surface(the_image, x, y) # or should it be 0,0 ?
context.paint()

For SVG output you have an option to embed the image or put a href
link to it.  Actually, with cairo-1.8.x the above code will result in
embedding the image data into SVG output in PNG format
(base64-encoded).

With the recently released cairo-1.10 (or a not too old 1.9.x
snapshot) you may embed the image in PNG or JPEG format, or put a link
to it instead.  To do so, you should use the new
cairo_surface_set_mime_data API (for a href link--with
CAIRO_MIME_TYPE_URI):

http://www.cairographics.org/manual/cairo-cairo-surface-t.html#cairo-surface-set-mime-data

Unfortunately, this API doesn't seem to be supported with the latest
pycairo, so if you want the feature you'll likely need to find a
workaround (e.g., hack pycairo).

--
Alex


More information about the cairo mailing list