Re: [cairo] rsvg and cairo alpha puzzle

Carl Worth <[email protected]>
Newsgroups gmane.comp.gnome.lib.librsvg.devel,gmane.comp.lib.cairo
Message-ID <87y7cfbpre.wl%[email protected]>
On Fri, 30 Nov 2007 14:47:52 +0200, Donn wrote:
>  I realize that rsvg is not your problem, but I thought there may be some
> advice or clever hackery to be had.

Yes, this looks like a librsvg problem.

>  I include the script at end. The basic problem is the cairo_render ( ctx)
> command in pyRsvg in combination with paint_with_alpha.

It's not paint_with_alpha that's the problem... just the fact that
you're doing rendering within a group.

> When one tries to translate the SVG *while* it's within the push_group scope
> it ignores it. When you removes the alpha code, it will translate.

And it's not simply ignoring the translation. It does respect most
aspects of the transformation matrix. But it seems to adjust the
translation component in such a way so that the upper-left corner of
the bounds of the SVG content ends up at the device's upper-left
corner, (even if some of it should have been rendered off-screen,
say).

I've attached a minimal, self-contained C program demonstrating the
buggy behavior.

I've looked into the problem a very little bit and I suspect the bug
is in the manipulation of the target surface's device offset in
rsvg_handle_render_cairo_sub. At this point, librsvg renders with an
identity matrix, (apparently after having copied the original cairo
transformation into its own data structures), and computes an offset
based on the bounds of the surface. There clearly seems to be
something bogus happening there.

Oh, and also there's this comment in rsvg_cairo_new_drawing_ctx:

    /* adjust transform so that the corner of the bounding box above is
     * at (0,0) - we compensate for this in rsvg_handle_render_cairo_sub()
     * below */
    state->affine[4] -= render->offset_x;
    state->affine[5] -= render->offset_y;

Librsvg hackers, care to comment on this?

-Carl

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

_______________________________________________
Librsvg-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/librsvg-devel
rsvg-bug.c (application/octet-stream, 2.2 KB)
/* cc -g -Wall $(pkg-config --cflags --libs cairo librsvg-2.0) -o rsvg-bug rsvg-bug.c
 *
 * This is a test case to demonstrate a bug in librsvg exposed by
 * calling rsvg_handle_render_cairo from within a
 * cairo_push_group/cairo_pop_group block.
 *
 * The same code is run twice, once without a group, and then once
 * with a group and the results are saved to nogroup.png and
 * group.png. The results should be identical in both cases, (a
 * rotated red and a green square on top of each other at the
 * origin). But in the group case, the red square from the SVG is
 * mysteriously offset.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cairo.h>
#include <math.h>
#include <librsvg/rsvg.h>
#include <librsvg/rsvg-cairo.h>

/* A simple SVG drawing a translucent red square */
char *svg = "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
    "<svg width=\"20\" height=\"20\">\n"
    "<rect x=\"0\" y=\"0\" width=\"20\" height=\"20\" fill=\"red\" fill-opacity=\"0.5\" />\n"
    "</svg>\n";

void
draw (RsvgHandle *handle, int use_group, const char *filename)
{
    cairo_surface_t *surface;
    cairo_t *cr;

    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 100, 100);
    cr = cairo_create (surface);

    cairo_scale (cr, 0.5, 0.5);
    cairo_rotate (cr, M_PI / 4.0);

    if (use_group) {
	cairo_push_group (cr);
    }

    /* Before drawing the SVG, draw a green square in what should be
     * the same place. */

    cairo_rectangle (cr, 0, 0, 20, 20);
    cairo_set_source_rgba (cr, 0, 1, 0, 0.5);
    cairo_fill (cr);

    rsvg_handle_render_cairo (handle, cr);

    if (use_group) {
	cairo_pop_group_to_source (cr);
	cairo_paint (cr);
    }

    cairo_surface_write_to_png(surface, filename);

    cairo_destroy (cr);
    cairo_surface_destroy (surface);
}

int
main (void)
{
    GError *error = NULL;
    RsvgHandle *handle;

    g_type_init ();

    handle = rsvg_handle_new_from_data ((guint8*) svg, strlen(svg) - 1, &error);
    if (error != NULL) {
	fprintf (stderr, error->message);
	exit (1);
    }

    /* Draw once with no group, which works. */
    draw (handle, FALSE, "nogroup.png");

    /* Then again with a group, which doesn't. */
    draw (handle, TRUE, "group.png");

    return 0;
}
signature.asc (application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQBHUEnV6JDdNq8qSWgRAjSoAJ9zfS4J+HSyfvSwKWTCbZYQrVSJggCgjS4H
wtjVLJDObNTovQiu6bOHgMs=
=aPOx
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.