[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