[cairo] problem rotating svg

Russell Strong rstrong at bigpond.net.au
Sat Apr 2 18:20:22 PST 2005


>On Fri, 01 Apr 2005 19:28:29 +1000, Russell Strong wrote: 
>> I've tried rotating some SVG images and found that parts of the image
>> aren't behaving correctly.  I'm not sure how to describe it except by
>> saying run the code and take a look.  The file home.svg comes from
>> cairo-demo/cairo_snippets/data.
>> 
>> Is it a bug or am I bone?
>
>Wow, that looks like a whopper of a bug. It appears that gradient
>patterns aren't behaving properly under rotation. The next thing to do
>would be to replicate the bug in a small C program, (which we can put
>into cairo/test to keep something like this from showing up again
>unnoticed).
>
>-Carl

I suspect that libsvg-cairo is doing something similar to the code below, which shows similar behaviour. 

        pat = cairo_pattern_create_linear(0.0,0.0,0.0,w/2);
        cairo_pattern_add_color_stop (pat, 1, 0, 0, 0, 1);
        cairo_pattern_add_color_stop (pat, 0, 1, 1, 1, 1);

        cairo_rectangle (cr,0,0,w/2,h/2);
        cairo_set_rgb_color (cr,0,0,0);
        cairo_stroke(cr);
        cairo_rectangle (cr, 0,0,w/2,h/2);
        cairo_set_pattern (cr, pat);

        cairo_translate(cr, w/2, h/2);
        cairo_rotate(cr, angle);

        cairo_fill (cr);
        cairo_pattern_destroy(pat);

Here the translate and rotate operations are affecting the gradient, which I wouldn't have expected.
Is there some sort of problem with libsvg-cairo handling of gradients and matrices?

full code:

#include <gtk/gtk.h>
#include <gtkcairo.h>

float angle=0.0;

static void paint (GtkWidget *widget,cairo_t *cr,gpointer data)
{
        gint w,h;
        cairo_pattern_t *pat;

        w = widget->allocation.width;
        h = widget->allocation.height;
        cairo_rectangle (cr, 0, 0, w, h);
        cairo_set_rgb_color (cr, 1,1,1);
        cairo_fill (cr);

        pat = cairo_pattern_create_linear(0.0,0.0,0.0,w/2);
        cairo_pattern_add_color_stop (pat, 1, 0, 0, 0, 1);
        cairo_pattern_add_color_stop (pat, 0, 1, 1, 1, 1);

        cairo_rectangle (cr,0,0,w/2,h/2);
        cairo_set_rgb_color (cr,0,0,0);
        cairo_stroke(cr);
        cairo_rectangle (cr, 0,0,w/2,h/2);
        cairo_set_pattern (cr, pat);

        cairo_translate(cr, w/2, h/2);
        cairo_rotate(cr, angle);

        cairo_fill (cr);
        cairo_pattern_destroy(pat);
}

static gint periodic(gpointer data)
{
        GtkWidget *widget = GTK_WIDGET(data);
        angle += 0.03;
        gtk_widget_queue_draw(widget);
        return TRUE;
}

gint main (gint argc, gchar *argv[])
{
        GtkWidget *win;
        GtkWidget *gtkcairo;

        gtk_init (&argc, &argv);
        win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        g_signal_connect (G_OBJECT (win), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
        gtkcairo = gtk_cairo_new ();
        gtk_widget_set_size_request (gtkcairo, 400, 400);
        g_signal_connect (G_OBJECT (gtkcairo), "paint", G_CALLBACK (paint), NULL);
        gtk_container_add (GTK_CONTAINER (win), gtkcairo);
        gtk_widget_show_all (win);
        g_timeout_add(50,periodic,gtkcairo);
        gtk_main ();
        return 0;
}

- Russell




More information about the cairo mailing list