[cairo] Seams with image backend again

Soeren Sandmann sandmann at daimi.au.dk
Thu Jun 24 01:24:53 PDT 2010


Hi,

The program below shows that the image backend can produce seams
between abutting polygons, even when the shared edge is specified with
the exact same coordinates, and even when the ADD operator and a
temporary surface are used.

It only happens when the color channels of the polygons are neither
full white nor full black. 

The seam is always lighter than the color of the polygons and doesn't
depend on the background color, so my theory is that the two shapes
overlap slightly, causing the addition to result in a light seam.

If you change the const int image variable from 1 to 0, the program
will use the X backend and the seam goes away.


Soren



#include <math.h>
#include <gtk/gtk.h>
#include <stdio.h>

static void
draw_quad (cairo_t *cr,
	   double x1, double y1, double x2, double y2,
	   double x3, double y3, double x4, double y4)
{
    cairo_move_to (cr, x1, y1);
    cairo_line_to (cr, x2, y2);
    cairo_line_to (cr, x3, y3);
    cairo_line_to (cr, x4, y4);
    cairo_close_path (cr);

    cairo_set_source_rgb (cr, 0, 0.6, 0);
    cairo_fill (cr);

#if 0
    cairo_set_line_width (cr, 0.05);
    cairo_set_source_rgb (cr, 0, 0, 0);

    cairo_stroke (cr);
#endif
}

const int image = 1;

static gboolean
on_expose (GtkWidget *widget, GdkEvent *event, gpointer data)
{
    if (GTK_WIDGET_DRAWABLE (widget))
    {
	cairo_t *cr;
	int w, h;
	cairo_surface_t *surface;

        gdk_drawable_get_size (widget->window, &w, &h);

	if (image)
	{
	    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
	    cr = cairo_create (surface);
	}
	else
	{
	    cr = gdk_cairo_create (widget->window);
	}

        cairo_rectangle (cr, 0, 0, w, h);
        cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
        cairo_fill (cr);

	cairo_scale (cr, 20, 20);
	cairo_translate (cr, 5, 1);

	cairo_push_group (cr);

	cairo_set_operator (cr, CAIRO_OPERATOR_ADD);

	draw_quad (cr,
		   1.50, 1.50,
		   2.64, 1.63,
		   1.75, 2.75,
		   0.55, 2.63);
	draw_quad (cr,
		   0.55, 2.63,
		   1.75, 2.75,
		   0.98, 4.11,
		   -0.35, 4.05);

	cairo_pop_group_to_source (cr);

	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
	cairo_paint (cr);

	cairo_destroy (cr);

	if (image)
	{
	    cr = gdk_cairo_create (widget->window);

	    cairo_set_source_surface (cr, surface, 0, 0);

	    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);

	    cairo_paint (cr);

	    cairo_destroy (cr);
	}
    }

    return TRUE;
}

int
main (int argc, char **argv)
{
    GtkWindow *window;
    GtkDrawingArea *area;

    gtk_init (&argc, &argv);

    window = GTK_WINDOW  (gtk_window_new (GTK_WINDOW_TOPLEVEL));
    area = GTK_DRAWING_AREA (gtk_drawing_area_new ());

    gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (area));

    gtk_window_set_default_size (window, 500, 300);

    gtk_widget_show_all (GTK_WIDGET (window));

    g_signal_connect (area, "expose_event", G_CALLBACK (on_expose), NULL);

    gtk_main ();
    return 0;
}



More information about the cairo mailing list