Seams with CAIRO_ANTIALIAS_FAST
[email protected] (Søren Sandmann)
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
The CAIRO_ANTIALIAS_FAST option uses a 2x2 sampling grid where each
sample has a weight of 64 when the depth of the mask is 8 bits.
This is problematic because the four samples then sum to 256, which
causes a seam a pixel is fully covered by a combination of independent
polygons.
The attached program demonstrates this. The blue rectangle is drawn as
four separate rectangles and the cross where they meet has a blue
channel of 0x74 where the rest of the rectangle is 0x73.
There are various fixes possible:
(a) Make ANTIALIAS_FAST use a 3x5 sampling grid. This is tempting
because X Render already supports this antialiasing mode (rendering
trapezoids to a 4 bit mask will use it).
(b) Make the weight of one of the samples 63 instead of 64. I don't know
how difficult this will be in the tor22 rasterizer.
(c) Ignore it and document that cairo can't draw seamless polygons.
Considering that the bug-seams.c test has been failing ever since
the tor rasterizer was added, and that fixing that test will
probably involve a performance hit from turning off analytical
antialiasing, maybe this is the more honest way to go.
Soren
--
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
seams22.c
(text/x-csrc, 2.4 KB)
#include <math.h>
#include <gtk/gtk.h>
#include <stdio.h>
static void
path_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);
}
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_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_set_antialias (cr, CAIRO_ANTIALIAS_FAST);
cairo_push_group (cr);
cairo_set_source_rgba (cr, 0, 0, 0.45, 1);
cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
cairo_rectangle (cr, 199.5, 149.5, 200, 150);
cairo_fill (cr);
cairo_rectangle (cr, 399.5, 149.5, 200, 150);
cairo_fill (cr);
cairo_rectangle (cr, 199.5, 299.5, 200, 150);
cairo_fill (cr);
cairo_rectangle (cr, 399.5, 299.5, 200, 150);
cairo_fill (cr);
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, 800, 600);
gtk_widget_show_all (GTK_WIDGET (window));
g_signal_connect (area, "expose_event", G_CALLBACK (on_expose), NULL);
gtk_main ();
return 0;
}