[cairo] Pixman centre pixel sampling in unantialiased mode.

M Joonas Pihlaja jpihlaja at cc.helsinki.fi
Thu Aug 13 07:56:21 PDT 2009


A follow-up to a minor point on the pixman unantialised rasterisation 
brought up on #cairo:

The pixman rasteriser treats edges hitting exactly the sample point at 
the pixel centre as being outside for top/left and inside for 
bottom/right edges.  This can be seen from the attached test case.  
The same issue occurs in the antialiased case, but there the issue is 
much less noticeable.

I'm also attaching a small patch against pixman to change it to 
consider top/left inside and bot/right outside, but I haven't really 
tested it at all apart from this particular case.  Seems to work. :)

Cheers,

Joonas
-------------- next part --------------
#include <cairo.h>

/* Tests the half-way pixel sampling rule for ANTIALIAS_NONE. */

int
main()
{
#define W 50
#define H 50
        cairo_t *cr = cairo_create(
                cairo_image_surface_create(
                        CAIRO_FORMAT_RGB24, 100, 100));
        cairo_set_source_rgb(cr,1,1,1);
        cairo_paint(cr);

        /* Red box.  All edges hit pixel centres. */
        cairo_set_source_rgb(cr, 1, 0, 0);
        cairo_rectangle(cr, 24.5, 24.5, W, H);
        cairo_fill(cr);

        /* Black box w/o antialiasing.  The bottom and right edges
         * should show some of the red box beneath. */
        cairo_set_source_rgb(cr, 0, 0, 0);
        cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
        cairo_rectangle(cr, 24.5, 24.5, W, H);
        cairo_fill(cr);

        cairo_surface_write_to_png(cairo_get_target(cr), "out-antialias-none.png");
        return 0;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: out-antialias-none.png
Type: application/octet-stream
Size: 373 bytes
Desc: 
Url : http://lists.cairographics.org/archives/cairo/attachments/20090813/110c90ef/attachment.obj 
-------------- next part --------------
diff --git a/pixman/pixman-edge-imp.h b/pixman/pixman-edge-imp.h
index a30f821..09ffaca 100644
--- a/pixman/pixman-edge-imp.h
+++ b/pixman/pixman-edge-imp.h
@@ -51,8 +51,8 @@ RASTERIZE_EDGES (pixman_image_t  *image,
 	/* For the non-antialiased case, round the coordinates up, in effect
 	 * sampling the center of the pixel. (The AA case does a similar 
 	 * adjustment in RENDER_SAMPLES_X) */
-	lx += X_FRAC_FIRST(1);
-	rx += X_FRAC_FIRST(1);
+	lx += X_FRAC_FIRST(1) - 1;
+	rx += X_FRAC_FIRST(1) - 1;
 #endif
 	/* clip X */
 	if (lx < 0)
diff --git a/pixman/pixman-trap.c b/pixman/pixman-trap.c
index 962cbb3..68ac11d 100644
--- a/pixman/pixman-trap.c
+++ b/pixman/pixman-trap.c
@@ -38,7 +38,7 @@ pixman_sample_ceil_y (pixman_fixed_t y, int n)
     pixman_fixed_t f = pixman_fixed_frac (y);
     pixman_fixed_t i = pixman_fixed_floor (y);
 
-    f = ((f + Y_FRAC_FIRST (n)) / STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
+    f = ((f + Y_FRAC_FIRST (n) - 1) / STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
 	Y_FRAC_FIRST (n);
     
     if (f > Y_FRAC_LAST (n))
@@ -67,7 +67,7 @@ pixman_sample_floor_y (pixman_fixed_t y,
     pixman_fixed_t f = pixman_fixed_frac (y);
     pixman_fixed_t i = pixman_fixed_floor (y);
 
-    f = DIV (f - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
+    f = DIV (f - Y_FRAC_FIRST (n) - 1, STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
 	Y_FRAC_FIRST (n);
 
     if (f < Y_FRAC_FIRST (n))


More information about the cairo mailing list