summaryrefslogtreecommitdiff
path: root/src/cairo-tor-scan-converter.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-09-30 10:22:41 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-09-30 13:57:05 +0100
commit167561f2823767058e2be3a26131b5f820b35c35 (patch)
tree690ef71b1b1f1a5c7ec02b66cd7693c956f52585 /src/cairo-tor-scan-converter.c
parentff23afd5f26e46e9b3c1fbfa31b2809f4329c4f0 (diff)
downloadcairo-167561f2823767058e2be3a26131b5f820b35c35.tar.gz
tor: Review full-row walker
When updating the quorem between cells, we would lose the overflow increment as it was only applied locally and not preserved by updating the quorem. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-tor-scan-converter.c')
-rw-r--r--src/cairo-tor-scan-converter.c86
1 files changed, 34 insertions, 52 deletions
diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
index 46473e9a9..1c8979844 100644
--- a/src/cairo-tor-scan-converter.c
+++ b/src/cairo-tor-scan-converter.c
@@ -458,21 +458,6 @@ struct glitter_scan_converter {
grid_scaled_y_t ymin, ymax;
};
-/* Compute the floored division a/b. Assumes / and % perform symmetric
- * division. */
-inline static struct quorem
-floored_divrem(int a, int b)
-{
- struct quorem qr;
- qr.quo = a/b;
- qr.rem = a%b;
- if ((a^b)<0 && qr.rem) {
- qr.quo -= 1;
- qr.rem += b;
- }
- return qr;
-}
-
static struct _pool_chunk *
_pool_chunk_init(
struct _pool_chunk *p,
@@ -804,21 +789,12 @@ cell_list_render_edge(struct cell_list *cells,
struct edge *edge,
int sign)
{
- grid_scaled_y_t y1, y2, dy;
- grid_scaled_x_t dx;
- int ix1, ix2;
grid_scaled_x_t fx1, fx2;
+ int ix1, ix2;
- int x1, x2;
-
- /* XXX review for loss of precision from dropping x.rem in our stepper */
-
- x1 = edge->cell;
+ GRID_X_TO_INT_FRAC(edge->cell, ix1, fx1);
full_step (edge);
- x2 = edge->cell;
-
- GRID_X_TO_INT_FRAC(x1, ix1, fx1);
- GRID_X_TO_INT_FRAC(x2, ix2, fx2);
+ GRID_X_TO_INT_FRAC(edge->cell, ix2, fx2);
/* Edge is entirely within a column? */
if (ix1 == ix2) {
@@ -831,26 +807,31 @@ cell_list_render_edge(struct cell_list *cells,
}
/* Orient the edge left-to-right. */
- dx = x2 - x1;
- if (dx >= 0) {
- y1 = 0;
- y2 = GRID_Y;
- } else {
- int tmp;
- tmp = ix1; ix1 = ix2; ix2 = tmp;
- tmp = fx1; fx1 = fx2; fx2 = tmp;
- dx = -dx;
- sign = -sign;
- y1 = GRID_Y;
- y2 = 0;
+ if (ix2 < ix1) {
+ int t;
+
+ t = ix1;
+ ix1 = ix2;
+ ix2 = t;
+
+ t = fx1;
+ fx1 = fx2;
+ fx2 = t;
}
- dy = y2 - y1;
/* Add coverage for all pixels [ix1,ix2] on this row crossed
* by the edge. */
{
struct cell_pair pair;
- struct quorem y = floored_divrem((GRID_X - fx1)*dy, dx);
+ struct quorem y;
+ int32_t dx;
+ int y_last;
+
+ dx = (ix2 - ix1) * GRID_X + (fx2 - fx1);
+ assert (dx > 0);
+
+ y.quo = (GRID_X - fx1) * GRID_Y / dx;
+ y.rem = (GRID_X - fx1) * GRID_Y % dx;
/* When rendering a previous edge on the active list we may
* advance the cell list cursor past the leftmost pixel of the
@@ -875,26 +856,27 @@ cell_list_render_edge(struct cell_list *cells,
pair = cell_list_find_pair(cells, ix1, ix1+1);
pair.cell1->uncovered_area += sign*y.quo*(GRID_X + fx1);
pair.cell1->covered_height += sign*y.quo;
- y.quo += y1;
+ y_last = y.quo;
if (ix1+1 < ix2) {
- struct quorem dydx_full = floored_divrem(GRID_X*dy, dx);
struct cell *cell = pair.cell2;
+ struct quorem dydx_full;
+
+ dydx_full.quo = GRID_Y * GRID_X / dx;
+ dydx_full.rem = GRID_Y * GRID_X % dx;
++ix1;
do {
- grid_scaled_y_t y_skip = dydx_full.quo;
+ y.quo += dydx_full.quo;
y.rem += dydx_full.rem;
if (y.rem >= dx) {
- ++y_skip;
+ y.quo++;
y.rem -= dx;
}
- y.quo += y_skip;
-
- y_skip *= sign;
- cell->uncovered_area += y_skip*GRID_X;
- cell->covered_height += y_skip;
+ cell->uncovered_area += sign*(y.quo - y_last)*GRID_X;
+ cell->covered_height += sign*(y.quo - y_last);
+ y_last = y.quo;
++ix1;
cell = cell_list_find(cells, ix1);
@@ -902,8 +884,8 @@ cell_list_render_edge(struct cell_list *cells,
pair.cell2 = cell;
}
- pair.cell2->uncovered_area += sign*(y2 - y.quo)*fx2;
- pair.cell2->covered_height += sign*(y2 - y.quo);
+ pair.cell2->uncovered_area += sign*(GRID_Y - y_last)*fx2;
+ pair.cell2->covered_height += sign*(GRID_Y - y_last);
}
}