Fix rounding of top and bottom coordinates.
authorSøren Sandmann Pedersen <sandmann@redhat.com>
Thu, 12 Nov 2009 22:20:32 +0000 (17:20 -0500)
committerSøren Sandmann Pedersen <sandmann@redhat.com>
Tue, 17 Nov 2009 06:58:01 +0000 (01:58 -0500)
The rules for trap rasterization is that coordinates are rounded
towards north-west.

The pixman_sample_ceil() function is used to compute the first
(top-most) sample row included in the trap, so when the input
coordinate is already exactly on a sample row, no rounding should take
place.

On the other hand, pixman_sample_floor() is used to compute the final
(bottom-most) sample row, so if the input is precisely on a sample
row, it needs to be rounded down to the previous row.

This commit fixes the rounding computation. The idea of the
computation is like this:

Floor operation that rounds exact matches down: First subtract
pixman_fixed_e to make sure input already on a sample row gets rounded
down. Then find out how many small steps are between the input and the
first fraction. Then add those small steps to the first fraction.

The ceil operation first adds (small_step + pixman_e), then runs a
floor. This ensures that exact matches are not rounded off.

Based on a patch by M Joonas Pihlaja.

pixman/pixman-trap.c

index 962cbb3..8353992 100644 (file)
@@ -28,8 +28,8 @@
 #include "pixman-private.h"
 
 /*
- * Compute the smallest value no less than y which is on a
- * grid row
+ * Compute the smallest value greater than or equal to y which is on a
+ * grid row.
  */
 
 PIXMAN_EXPORT pixman_fixed_t
@@ -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 = DIV (f - Y_FRAC_FIRST (n) + (STEP_Y_SMALL (n) - pixman_fixed_e), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
        Y_FRAC_FIRST (n);
     
     if (f > Y_FRAC_LAST (n))
@@ -57,8 +57,8 @@ pixman_sample_ceil_y (pixman_fixed_t y, int n)
 }
 
 /*
- * Compute the largest value no greater than y which is on a
- * grid row
+ * Compute the largest value strictly less than y which is on a
+ * grid row.
  */
 PIXMAN_EXPORT pixman_fixed_t
 pixman_sample_floor_y (pixman_fixed_t y,
@@ -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 - pixman_fixed_e - Y_FRAC_FIRST (n), STEP_Y_SMALL (n)) * STEP_Y_SMALL (n) +
        Y_FRAC_FIRST (n);
 
     if (f < Y_FRAC_FIRST (n))
@@ -380,7 +380,7 @@ pixman_rasterize_trapezoid (pixman_image_t *          image,
     if (pixman_fixed_to_int (b) >= height)
        b = pixman_int_to_fixed (height) - 1;
     b = pixman_sample_floor_y (b, bpp);
-
+    
     if (b >= t)
     {
        /* initialize edge walkers */