[cairo-commit] 7 commits - src/cairo-bentley-ottmann.c src/cairo-default-context.c src/cairo-script-surface.c src/cairo-tor-scan-converter.c src/cairo-xlib-surface.c util/show-polygon.c util/show-traps.c
Chris Wilson
ickle at kemper.freedesktop.org
Fri Aug 12 13:37:37 PDT 2011
src/cairo-bentley-ottmann.c | 47 ++-
src/cairo-default-context.c | 15 -
src/cairo-script-surface.c | 1
src/cairo-tor-scan-converter.c | 583 +++++++++++++++--------------------------
src/cairo-xlib-surface.c | 35 --
util/show-polygon.c | 23 +
util/show-traps.c | 100 ++++++-
7 files changed, 373 insertions(+), 431 deletions(-)
New commits:
commit be1ff2f45fdbc69537e513834fcffa0435e63073
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 12 20:36:13 2011 +0100
xlib: Set the clip_region for glyphs
Broken (never set!) since the clipping overhaul. We could emulate the
xcb code to avoid setting it unnecessarily...
Fixes partial-clip-test.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 57b2604..dc3aac8 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -4767,7 +4767,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
composite_operation_t operation;
cairo_surface_attributes_t attributes;
cairo_xlib_surface_t *src = NULL;
- cairo_region_t *clip_region = NULL;
cairo_xlib_display_t *display;
if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst))
@@ -4807,30 +4806,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
X_DEBUG ((display->display, "show_glyphs (dst=%x)", (unsigned int) dst->drawable));
- if (clip_region != NULL &&
- cairo_region_num_rectangles (clip_region) == 1)
- {
- cairo_rectangle_int_t glyph_extents;
- const cairo_rectangle_int_t *clip_extents;
-
- /* Can we do without the clip?
- * Around 50% of the time the clip is redundant (firefox).
- */
- _cairo_scaled_font_glyph_approximate_extents (scaled_font,
- glyphs, num_glyphs,
- &glyph_extents);
-
- clip_extents = &clip->path->extents;
- if (clip_extents->x <= glyph_extents.x &&
- clip_extents->y <= glyph_extents.y &&
- clip_extents->x + clip_extents->width >= glyph_extents.x + glyph_extents.width &&
- clip_extents->y + clip_extents->height >= glyph_extents.y + glyph_extents.height)
- {
- clip_region = NULL;
- }
- }
-
- status = _cairo_xlib_surface_set_clip_region (dst, clip_region);
+ status = _cairo_xlib_surface_set_clip_region (dst,
+ _cairo_clip_get_region (clip));
if (unlikely (status))
goto BAIL0;
@@ -4869,14 +4846,6 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
if (unlikely (status))
goto BAIL0;
- if (clip != NULL) {
- if (! _cairo_rectangle_intersect (&glyph_extents,
- _cairo_clip_get_extents (clip)))
- {
- goto BAIL0;
- }
- }
-
status = _cairo_xlib_surface_acquire_pattern_surface (display,
dst, src_pattern,
glyph_extents.x,
commit e7fcbed63ac19d894cb94fd0a7589f4580a072f1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 11 18:43:56 2011 +0100
bo: Perform an initial bucket sort on the start events
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-bentley-ottmann.c b/src/cairo-bentley-ottmann.c
index d7b017a..70d4482 100644
--- a/src/cairo-bentley-ottmann.c
+++ b/src/cairo-bentley-ottmann.c
@@ -1040,9 +1040,6 @@ _cairo_bo_event_queue_init (cairo_bo_event_queue_t *event_queue,
cairo_bo_event_t **start_events,
int num_events)
{
- _cairo_bo_event_queue_sort (start_events, num_events);
- start_events[num_events] = NULL;
-
event_queue->start_events = start_events;
_cairo_freepool_init (&event_queue->pool,
@@ -1162,6 +1159,7 @@ _cairo_bo_sweep_line_insert (cairo_bo_sweep_line_t *sweep_line,
}
} else {
sweep_line->head = edge;
+ edge->next = NULL;
}
sweep_line->current_edge = edge;
@@ -1727,13 +1725,25 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
cairo_bo_start_event_t *events;
cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
cairo_bo_event_t **event_ptrs;
- int num_events;
- int i;
+ cairo_bo_start_event_t *stack_event_y[64];
+ cairo_bo_start_event_t **event_y = NULL;
+ int i, num_events, y, ymin, ymax;
num_events = polygon->num_edges;
if (unlikely (0 == num_events))
return CAIRO_STATUS_SUCCESS;
+ if (polygon->num_limits) {
+ ymin = _cairo_fixed_integer_floor (polygon->limit.p1.y);
+ ymax = _cairo_fixed_integer_ceil (polygon->limit.p2.y) - ymin;
+
+ if (ymax > 64)
+ event_y = _cairo_malloc_ab(sizeof (cairo_bo_event_t*), ymax);
+ else
+ event_y = stack_event_y;
+ memset (event_y, 0, ymax * sizeof(cairo_bo_event_t *));
+ }
+
events = stack_events;
event_ptrs = stack_event_ptrs;
if (num_events > ARRAY_LENGTH (stack_events)) {
@@ -1748,8 +1758,6 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
}
for (i = 0; i < num_events; i++) {
- event_ptrs[i] = (cairo_bo_event_t *) &events[i];
-
events[i].type = CAIRO_BO_EVENT_TYPE_START;
events[i].point.y = polygon->edges[i].top;
events[i].point.x =
@@ -1760,8 +1768,30 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
events[i].edge.deferred_trap.right = NULL;
events[i].edge.prev = NULL;
events[i].edge.next = NULL;
+
+ if (event_y) {
+ y = _cairo_fixed_integer_floor (events[i].point.y) - ymin;
+ events[i].edge.next = (cairo_bo_edge_t *) event_y[y];
+ event_y[y] = (cairo_bo_start_event_t *) &events[i];
+ } else
+ event_ptrs[i] = (cairo_bo_event_t *) &events[i];
}
+ if (event_y) {
+ for (y = i = 0; y < ymax && i < num_events; y++) {
+ cairo_bo_start_event_t *e;
+ int j = i;
+ for (e = event_y[y]; e; e = (cairo_bo_start_event_t *)e->edge.next)
+ event_ptrs[i++] = (cairo_bo_event_t *) e;
+ if (i > j + 1)
+ _cairo_bo_event_queue_sort (event_ptrs+j, i-j);
+ }
+ if (event_y != stack_event_y)
+ free (event_y);
+ } else
+ _cairo_bo_event_queue_sort (event_ptrs, i);
+ event_ptrs[i] = NULL;
+
#if DEBUG_TRAPS
dump_edges (events, num_events, "bo-polygon-edges.txt");
#endif
@@ -1770,8 +1800,7 @@ _cairo_bentley_ottmann_tessellate_polygon (cairo_traps_t *traps,
* passes of the Bentley-Ottmann algorithm. It would merely
* require storing the results of each pass into a temporary
* cairo_traps_t. */
- status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs,
- num_events,
+ status = _cairo_bentley_ottmann_tessellate_bo_edges (event_ptrs, num_events,
fill_rule, traps,
&intersections);
#if DEBUG_TRAPS
commit 64bcabfe4bcc5d95ee47e0bc7eed5b4544640279
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 11 23:12:44 2011 +0100
tor: Micro-optimise
Inline sub-step edges and combine non-zero/even-odd paths by using a
winding_mask.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
index c35ec0f..d571f6e 100644
--- a/src/cairo-tor-scan-converter.c
+++ b/src/cairo-tor-scan-converter.c
@@ -97,7 +97,6 @@
#include "cairo-spans-private.h"
#include "cairo-error-private.h"
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@@ -124,35 +123,6 @@ typedef cairo_status_t glitter_status_t;
struct pool;
struct cell_list;
-static glitter_status_t
-blit_with_span_renderer(
- struct cell_list *coverages,
- cairo_span_renderer_t *span_renderer,
- struct pool *span_pool,
- int y,
- int height,
- int xmin,
- int xmax);
-
-static glitter_status_t
-blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height);
-
-#define GLITTER_BLIT_COVERAGES_ARGS \
- cairo_span_renderer_t *span_renderer, \
- struct pool *span_pool
-
-#define GLITTER_BLIT_COVERAGES(cells, y, height,xmin, xmax) do { \
- blit_with_span_renderer (cells, \
- span_renderer, \
- span_pool, \
- y, height, \
- xmin, xmax); \
-} while (0)
-
-#define GLITTER_BLIT_COVERAGES_EMPTY(y, height, xmin, xmax) do { \
- blit_empty_with_span_renderer (span_renderer, y, height); \
-} while (0)
-
/*-------------------------------------------------------------------------
* glitter-paths.h
*/
@@ -212,14 +182,6 @@ glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
* rule is used.
*
* The scan converter must be reset or destroyed after this call. */
-#ifndef GLITTER_BLIT_COVERAGES_ARGS
-# define GLITTER_BLIT_COVERAGES_ARGS unsigned char *raster_pixels, long raster_stride
-#endif
-I void
-glitter_scan_converter_render(
- glitter_scan_converter_t *converter,
- int nonzero_fill,
- GLITTER_BLIT_COVERAGES_ARGS);
/*-------------------------------------------------------------------------
* glitter-paths.c: Implementation internal types
@@ -284,7 +246,6 @@ typedef int grid_scaled_y_t;
* vertices are given in grid scaled coordinates. The scale factor
* comes from needing to accurately represent the area 0.5*dx*dy of a
* triangle with base dx and height dy in grid scaled numbers. */
-typedef int grid_area_t;
#define GRID_XY (2*GRID_X*GRID_Y) /* Unit area on the grid. */
/* GRID_AREA_TO_ALPHA(area): map [0,GRID_XY] to [0,255]. */
@@ -455,8 +416,8 @@ struct polygon {
struct cell {
struct cell *next;
int x;
- grid_area_t uncovered_area;
- grid_scaled_y_t covered_height;
+ int16_t uncovered_area;
+ int16_t covered_height;
};
/* A cell list represents the scan line sparsely as cells ordered by
@@ -467,7 +428,7 @@ struct cell_list {
struct cell head, tail;
/* Cursor state for iterating through the cell list. */
- struct cell *cursor;
+ struct cell *cursor, *rewind;
/* Cells in the cell list are owned by the cell list and are
* allocated from this pool. */
@@ -501,6 +462,9 @@ struct glitter_scan_converter {
struct active_list active[1];
struct cell_list coverages[1];
+ cairo_half_open_span_t *spans;
+ cairo_half_open_span_t spans_embedded[64];
+
/* Clip box. */
grid_scaled_x_t xmin, xmax;
grid_scaled_y_t ymin, ymax;
@@ -672,13 +636,20 @@ cell_list_rewind (struct cell_list *cells)
cells->cursor = &cells->head;
}
-/* Rewind the cell list if its cursor has been advanced past x. */
inline static void
cell_list_maybe_rewind (struct cell_list *cells, int x)
{
- struct cell *tail = cells->cursor;
- if (tail->x > x)
- cell_list_rewind (cells);
+ if (x < cells->cursor->x) {
+ cells->cursor = cells->rewind;
+ if (x < cells->cursor->x)
+ cells->cursor = &cells->head;
+ }
+}
+
+inline static void
+cell_list_set_rewind (struct cell_list *cells)
+{
+ cells->rewind = cells->cursor;
}
static void
@@ -710,7 +681,7 @@ cell_list_reset (struct cell_list *cells)
pool_reset (cells->cell_pool.base);
}
-static struct cell *
+inline static struct cell *
cell_list_alloc (struct cell_list *cells,
struct cell *tail,
int x)
@@ -721,8 +692,8 @@ cell_list_alloc (struct cell_list *cells,
cell->next = tail->next;
tail->next = cell;
cell->x = x;
- cell->uncovered_area = 0;
- cell->covered_height = 0;
+ *(uint32_t *)&cell->uncovered_area = 0;
+
return cell;
}
@@ -736,6 +707,11 @@ cell_list_find (struct cell_list *cells, int x)
{
struct cell *tail = cells->cursor;
+ assert (x >= tail->x);
+
+ if (tail->x == x)
+ return tail;
+
while (1) {
UNROLL3({
if (tail->next->x > x)
@@ -762,6 +738,9 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
{
struct cell_pair pair;
+ assert (x2 > x1);
+ assert (x1 >= cells->cursor->x);
+
pair.cell1 = cells->cursor;
while (1) {
UNROLL3({
@@ -770,16 +749,8 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
pair.cell1 = pair.cell1->next;
});
}
- if (pair.cell1->x != x1) {
- struct cell *cell = pool_alloc (cells->cell_pool.base,
- sizeof (struct cell));
- cell->x = x1;
- cell->uncovered_area = 0;
- cell->covered_height = 0;
- cell->next = pair.cell1->next;
- pair.cell1->next = cell;
- pair.cell1 = cell;
- }
+ if (pair.cell1->x != x1)
+ pair.cell1 = cell_list_alloc (cells, pair.cell1, x1);
pair.cell2 = pair.cell1;
while (1) {
@@ -789,47 +760,25 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
pair.cell2 = pair.cell2->next;
});
}
- if (pair.cell2->x != x2) {
- struct cell *cell = pool_alloc (cells->cell_pool.base,
- sizeof (struct cell));
- cell->uncovered_area = 0;
- cell->covered_height = 0;
- cell->x = x2;
- cell->next = pair.cell2->next;
- pair.cell2->next = cell;
- pair.cell2 = cell;
- }
+ if (pair.cell2->x != x2)
+ pair.cell2 = cell_list_alloc (cells, pair.cell2, x2);
cells->cursor = pair.cell2;
return pair;
}
-/* Add an unbounded subpixel span covering subpixels >= x to the
- * coverage cells. */
-static void
-cell_list_add_unbounded_subspan (struct cell_list *cells,
- grid_scaled_x_t x)
-{
- struct cell *cell;
- int ix, fx;
-
- GRID_X_TO_INT_FRAC(x, ix, fx);
-
- cell = cell_list_find (cells, ix);
- cell->uncovered_area += 2*fx;
- cell->covered_height++;
-}
-
/* Add a subpixel span covering [x1, x2) to the coverage cells. */
inline static void
-cell_list_add_subspan(
- struct cell_list *cells,
- grid_scaled_x_t x1,
- grid_scaled_x_t x2)
+cell_list_add_subspan(struct cell_list *cells,
+ grid_scaled_x_t x1,
+ grid_scaled_x_t x2)
{
int ix1, fx1;
int ix2, fx2;
+ if (x1 == x2)
+ return;
+
GRID_X_TO_INT_FRAC(x1, ix1, fx1);
GRID_X_TO_INT_FRAC(x2, ix2, fx2);
@@ -864,10 +813,9 @@ cell_list_add_subspan(
* active list in the order they appear on the list (i.e. with
* non-decreasing x-coordinate.) */
static void
-cell_list_render_edge(
- struct cell_list *cells,
- struct edge *edge,
- int sign)
+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;
@@ -1058,8 +1006,6 @@ polygon_add_edge (struct polygon *polygon,
grid_scaled_y_t ymin = polygon->ymin;
grid_scaled_y_t ymax = polygon->ymax;
- assert (edge->bottom > edge->top);
-
if (unlikely (edge->top >= ymax || edge->bottom <= ymin))
return;
@@ -1255,7 +1201,7 @@ merge_unsorted_edges (struct edge *head, struct edge *unsorted)
/* Test if the edges on the active list can be safely advanced by a
* full row without intersections or any edges ending. */
inline static int
-active_list_can_step_full_row (struct active_list *active)
+can_do_full_row (struct active_list *active)
{
const struct edge *e;
int prev_x = INT_MIN;
@@ -1292,7 +1238,7 @@ active_list_can_step_full_row (struct active_list *active)
++x.quo;
}
- if (x.quo <= prev_x)
+ if (x.quo < prev_x)
return 0;
prev_x = x.quo;
@@ -1345,13 +1291,9 @@ active_list_substep_edges(struct active_list *active)
grid_scaled_x_t prev_x = INT_MIN;
struct edge *edge = active->head.next;
- do {
- struct edge *next;
-
- if (&active->tail == edge)
- break;
+ while (edge != &active->tail) {
+ struct edge *next = edge->next;
- next = edge->next;
if (--edge->height_left) {
edge->x.quo += edge->dxdy.quo;
edge->x.rem += edge->dxdy.rem;
@@ -1377,167 +1319,118 @@ active_list_substep_edges(struct active_list *active)
edge->prev->next = next;
next->prev = edge->prev;
}
- edge = next;
- } while (1);
-}
-
-inline static void
-apply_nonzero_fill_rule_for_subrow (struct active_list *active,
- struct cell_list *coverages)
-{
- struct edge *edge = active->head.next;
-
- cell_list_rewind (coverages);
-
- while (&active->tail != edge) {
- int xstart = edge->x.quo;
- int winding = edge->dir;
- while (1) {
- edge = edge->next;
- if (&active->tail == edge)
- return cell_list_add_unbounded_subspan (coverages, xstart);
-
- winding += edge->dir;
- if (0 == winding && edge->next->x.quo != edge->x.quo)
- break;
- }
- cell_list_add_subspan (coverages, xstart, edge->x.quo);
- edge = edge->next;
+ edge = next;
}
}
-static void
-apply_evenodd_fill_rule_for_subrow (struct active_list *active,
- struct cell_list *coverages)
+inline static void
+sub_row (struct active_list *active,
+ struct cell_list *coverages,
+ unsigned int mask)
{
struct edge *edge = active->head.next;
+ int xstart = INT_MIN, prev_x = INT_MIN;
+ int winding = 0;
cell_list_rewind (coverages);
while (&active->tail != edge) {
- int xstart = edge->x.quo;
+ struct edge *next = edge->next;
+ int xend = edge->x.quo;
- while (1) {
- edge = edge->next;
- if (&active->tail == edge) {
- cell_list_add_unbounded_subspan (coverages, xstart);
- return;
+ if (--edge->height_left) {
+ edge->x.quo += edge->dxdy.quo;
+ edge->x.rem += edge->dxdy.rem;
+ if (edge->x.rem >= 0) {
+ ++edge->x.quo;
+ edge->x.rem -= edge->dy;
}
- if (edge->next->x.quo != edge->x.quo)
- break;
-
- edge = edge->next;
+ if (edge->x.quo < prev_x) {
+ struct edge *pos = edge->prev;
+ pos->next = next;
+ next->prev = pos;
+ do {
+ pos = pos->prev;
+ } while (edge->x.quo < pos->x.quo);
+ pos->next->prev = edge;
+ edge->next = pos->next;
+ edge->prev = pos;
+ pos->next = edge;
+ } else
+ prev_x = edge->x.quo;
+ } else {
+ edge->prev->next = next;
+ next->prev = edge->prev;
}
- cell_list_add_subspan (coverages, xstart, edge->x.quo);
- edge = edge->next;
+ winding += edge->dir;
+ if ((winding & mask) == 0) {
+ if (next->x.quo != xend) {
+ cell_list_add_subspan (coverages, xstart, xend);
+ xstart = INT_MIN;
+ }
+ } else if (xstart == INT_MIN)
+ xstart = xend;
+
+ edge = next;
}
}
-static void
-apply_nonzero_fill_rule_and_step_edges (struct active_list *active,
- struct cell_list *coverages)
+inline static void dec (struct edge *e, int h)
{
- struct edge *pos = active->head.next;
-
- while (&active->tail != pos) {
- struct edge *left_edge = pos;
- struct edge *right_edge;
- int winding;
-
- left_edge->height_left -= GRID_Y;
- if (! left_edge->height_left) {
- left_edge->prev->next = left_edge->next;
- left_edge->next->prev = left_edge->prev;
- }
-
- winding = left_edge->dir;
- right_edge = left_edge->next;
- while (1) {
- if (&active->tail == right_edge) {
- cell_list_render_edge (coverages, left_edge, +1);
- return;
- }
-
- right_edge->height_left -= GRID_Y;
- if (! right_edge->height_left) {
- right_edge->prev->next = right_edge->next;
- right_edge->next->prev = right_edge->prev;
- }
-
- winding += right_edge->dir;
- if (0 == winding && right_edge->next->x.quo != right_edge->x.quo)
- break;
-
- if (! right_edge->vertical) {
- right_edge->x.quo += right_edge->dxdy_full.quo;
- right_edge->x.rem += right_edge->dxdy_full.rem;
- if (right_edge->x.rem >= 0) {
- ++right_edge->x.quo;
- right_edge->x.rem -= right_edge->dy;
- }
- }
+ e->height_left -= h;
+ if (e->height_left == 0) {
+ e->prev->next = e->next;
+ e->next->prev = e->prev;
+ }
+}
- right_edge = right_edge->next;
+inline static void full_step (struct edge *e)
+{
+ if (! e->vertical) {
+ e->x.quo += e->dxdy_full.quo;
+ e->x.rem += e->dxdy_full.rem;
+ if (e->x.rem >= 0) {
+ ++e->x.quo;
+ e->x.rem -= e->dy;
}
-
- cell_list_render_edge (coverages, left_edge, +1);
- cell_list_render_edge (coverages, right_edge, -1);
-
- pos = right_edge->next;
}
}
static void
-apply_evenodd_fill_rule_and_step_edges (struct active_list *active,
- struct cell_list *coverages)
+full_row (struct active_list *active,
+ struct cell_list *coverages,
+ unsigned int mask)
{
- struct edge *pos = active->head.next;
-
- while (&active->tail != pos) {
- struct edge *left_edge = pos;
- struct edge *right_edge;
+ struct edge *left = active->head.next;
- left_edge->height_left -= GRID_Y;
- if (! left_edge->height_left) {
- left_edge->prev->next = left_edge->next;
- left_edge->next->prev = left_edge->prev;
- }
+ while (&active->tail != left) {
+ struct edge *right;
+ int winding;
- right_edge = left_edge->next;
- while (1) {
- if (&active->tail == right_edge) {
- cell_list_render_edge (coverages, left_edge, +1);
- return;
- }
+ dec (left, GRID_Y);
- right_edge->height_left -= GRID_Y;
- if (! right_edge->height_left) {
- right_edge->prev->next = right_edge->next;
- right_edge->next->prev = right_edge->prev;
- }
+ winding = left->dir;
+ right = left->next;
+ do {
+ dec (right, GRID_Y);
- if (right_edge->next->x.quo != right_edge->x.quo)
+ winding += right->dir;
+ if ((winding & mask) == 0 && right->next->x.quo != right->x.quo)
break;
- if (! right_edge->vertical) {
- right_edge->x.quo += right_edge->dxdy_full.quo;
- right_edge->x.rem += right_edge->dxdy_full.rem;
- if (right_edge->x.rem >= 0) {
- ++right_edge->x.quo;
- right_edge->x.rem -= right_edge->dy;
- }
- }
+ full_step (right);
- right_edge = right_edge->next;
- }
+ right = right->next;
+ } while (1);
- cell_list_render_edge (coverages, left_edge, +1);
- cell_list_render_edge (coverages, right_edge, -1);
+ cell_list_set_rewind (coverages);
+ cell_list_render_edge (coverages, left, +1);
+ cell_list_render_edge (coverages, right, -1);
- pos = right_edge->next;
+ left = right->next;
}
}
@@ -1554,14 +1447,18 @@ _glitter_scan_converter_init(glitter_scan_converter_t *converter, jmp_buf *jmp)
}
static void
-_glitter_scan_converter_fini(glitter_scan_converter_t *converter)
+_glitter_scan_converter_fini(glitter_scan_converter_t *self)
{
- polygon_fini(converter->polygon);
- cell_list_fini(converter->coverages);
- converter->xmin=0;
- converter->ymin=0;
- converter->xmax=0;
- converter->ymax=0;
+ if (self->spans != self->spans_embedded)
+ free (self->spans);
+
+ polygon_fini(self->polygon);
+ cell_list_fini(self->coverages);
+
+ self->xmin=0;
+ self->ymin=0;
+ self->xmax=0;
+ self->ymax=0;
}
static grid_scaled_t
@@ -1593,6 +1490,14 @@ glitter_scan_converter_reset(
converter->xmin = 0; converter->xmax = 0;
converter->ymin = 0; converter->ymax = 0;
+ if (xmax - xmin > ARRAY_LENGTH(converter->spans_embedded)) {
+ converter->spans = _cairo_malloc_ab (xmax - xmin,
+ sizeof (cairo_half_open_span_t));
+ if (unlikely (converter->spans == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ } else
+ converter->spans = converter->spans_embedded;
+
xmin = int_to_grid_scaled_x(xmin);
ymin = int_to_grid_scaled_y(ymin);
xmax = int_to_grid_scaled_x(xmax);
@@ -1688,11 +1593,79 @@ step_edges (struct active_list *active, int count)
}
}
+static glitter_status_t
+blit (struct cell_list *cells,
+ cairo_span_renderer_t *renderer,
+ cairo_half_open_span_t *spans,
+ int y, int height,
+ int xmin, int xmax)
+{
+ struct cell *cell = cells->head.next;
+ int prev_x = xmin, last_x = -1;
+ int16_t cover = 0, last_cover = 0;
+ unsigned num_spans;
+
+ if (cell == &cells->tail)
+ return CAIRO_STATUS_SUCCESS;
+
+ /* Skip cells to the left of the clip region. */
+ while (cell->x < xmin) {
+ cover += cell->covered_height;
+ cell = cell->next;
+ }
+ cover *= GRID_X*2;
+
+ /* Form the spans from the coverages and areas. */
+ num_spans = 0;
+ for (; cell->x < xmax; cell = cell->next) {
+ int x = cell->x;
+ int16_t area;
+
+ if (x > prev_x && cover != last_cover) {
+ spans[num_spans].x = prev_x;
+ spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
+ last_cover = cover;
+ last_x = prev_x;
+ ++num_spans;
+ }
+
+ cover += cell->covered_height*GRID_X*2;
+ area = cover - cell->uncovered_area;
+
+ if (area != last_cover) {
+ spans[num_spans].x = x;
+ spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
+ last_cover = area;
+ last_x = x;
+ ++num_spans;
+ }
+
+ prev_x = x+1;
+ }
+
+ if (prev_x <= xmax && cover != last_cover) {
+ spans[num_spans].x = prev_x;
+ spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
+ last_cover = cover;
+ last_x = prev_x;
+ ++num_spans;
+ }
+
+ if (last_x < xmax && last_cover) {
+ spans[num_spans].x = xmax;
+ spans[num_spans].coverage = 0;
+ ++num_spans;
+ }
+
+ /* Dump them into the renderer. */
+ return renderer->render_rows (renderer, y, height, spans, num_spans);
+}
+
+
I void
-glitter_scan_converter_render(
- glitter_scan_converter_t *converter,
- int nonzero_fill,
- GLITTER_BLIT_COVERAGES_ARGS)
+glitter_scan_converter_render(glitter_scan_converter_t *converter,
+ unsigned int winding_mask,
+ cairo_span_renderer_t *renderer)
{
int i, j;
int ymax_i = converter->ymax / GRID_Y;
@@ -1714,7 +1687,7 @@ glitter_scan_converter_render(
/* Render each pixel row. */
for (i = 0; i < h; i = j) {
- int do_full_step = 0;
+ int do_full_row = 0;
j = i + 1;
@@ -1730,15 +1703,12 @@ glitter_scan_converter_render(
continue;
}
- do_full_step = active_list_can_step_full_row (active);
+ do_full_row = can_do_full_row (active);
}
- if (do_full_step) {
+ if (do_full_row) {
/* Step by a full pixel row's worth. */
- if (nonzero_fill)
- apply_nonzero_fill_rule_and_step_edges (active, coverages);
- else
- apply_evenodd_fill_rule_and_step_edges (active, coverages);
+ full_row (active, coverages, winding_mask);
if (active->is_vertical) {
while (j < h &&
@@ -1766,16 +1736,12 @@ glitter_scan_converter_render(
buckets[sub] = NULL;
}
- if (nonzero_fill)
- apply_nonzero_fill_rule_for_subrow (active, coverages);
- else
- apply_evenodd_fill_rule_for_subrow (active, coverages);
-
- active_list_substep_edges(active);
+ sub_row (active, coverages, winding_mask);
}
}
- GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, j-i, xmin_i, xmax_i);
+ blit (coverages, renderer, converter->spans,
+ i+ymin_i, j-i, xmin_i, xmax_i);
cell_list_reset (coverages);
active->min_height -= GRID_Y;
@@ -1785,100 +1751,6 @@ glitter_scan_converter_render(
GLITTER_BLIT_COVERAGES_END;
}
-/*-------------------------------------------------------------------------
- * cairo specific implementation: the coverage blitter and
- * scan converter subclass. */
-
-static glitter_status_t
-blit_with_span_renderer (struct cell_list *cells,
- cairo_span_renderer_t *renderer,
- struct pool *span_pool,
- int y, int height,
- int xmin, int xmax)
-{
- struct cell *cell = cells->head.next;
- int prev_x = xmin, last_x = -1;
- int cover = 0, last_cover = 0;
- cairo_half_open_span_t *spans;
- unsigned num_spans;
-
- if (cell == &cells->tail)
- return blit_empty_with_span_renderer (renderer, y, height);
-
- /* Skip cells to the left of the clip region. */
- while (cell->x < xmin) {
- cover += cell->covered_height;
- cell = cell->next;
- }
- cover *= GRID_X*2;
-
- /* Count number of cells remaining. */
- {
- struct cell *next = cell;
- num_spans = 2;
- while (next->x < xmax) {
- next = next->next;
- ++num_spans;
- }
- num_spans = 2*num_spans;
- }
-
- /* Allocate enough spans for the row. */
- pool_reset (span_pool);
- spans = pool_alloc (span_pool, sizeof(spans[0])*num_spans);
- num_spans = 0;
-
- /* Form the spans from the coverages and areas. */
- for (; cell->x < xmax; cell = cell->next) {
- int x = cell->x;
- int area;
-
- if (x > prev_x && cover != last_cover) {
- spans[num_spans].x = prev_x;
- spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
- last_cover = cover;
- last_x = prev_x;
- ++num_spans;
- }
-
- cover += cell->covered_height*GRID_X*2;
- area = cover - cell->uncovered_area;
-
- if (area != last_cover) {
- spans[num_spans].x = x;
- spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
- last_cover = area;
- last_x = x;
- ++num_spans;
- }
-
- prev_x = x+1;
- }
-
- if (prev_x <= xmax && cover != last_cover) {
- spans[num_spans].x = prev_x;
- spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
- last_cover = cover;
- last_x = prev_x;
- ++num_spans;
- }
-
- if (last_x < xmax && last_cover) {
- spans[num_spans].x = xmax;
- spans[num_spans].coverage = 0;
- ++num_spans;
- }
-
- /* Dump them into the renderer. */
- return renderer->render_rows (renderer, y, height, spans, num_spans);
-}
-
-static glitter_status_t
-blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height)
-{
- return renderer->render_rows (renderer, y, height, NULL, 0);
-}
-
struct _cairo_tor_scan_converter {
cairo_scan_converter_t base;
@@ -1886,11 +1758,6 @@ struct _cairo_tor_scan_converter {
cairo_fill_rule_t fill_rule;
jmp_buf jmp;
-
- struct {
- struct pool base[1];
- cairo_half_open_span_t embedded[32];
- } span_pool;
};
typedef struct _cairo_tor_scan_converter cairo_tor_scan_converter_t;
@@ -1903,7 +1770,6 @@ _cairo_tor_scan_converter_destroy (void *converter)
return;
}
_glitter_scan_converter_fini (self->converter);
- pool_fini (self->span_pool.base);
free(self);
}
@@ -1952,9 +1818,8 @@ _cairo_tor_scan_converter_generate (void *converter,
return _cairo_scan_converter_set_error (self, _cairo_error (status));
glitter_scan_converter_render (self->converter,
- self->fill_rule == CAIRO_FILL_RULE_WINDING,
- renderer,
- self->span_pool.base);
+ self->fill_rule == CAIRO_FILL_RULE_WINDING ? ~0 : 1,
+ renderer);
return CAIRO_STATUS_SUCCESS;
}
@@ -1979,10 +1844,6 @@ _cairo_tor_scan_converter_create (int xmin,
self->base.add_polygon = _cairo_tor_scan_converter_add_polygon;
self->base.generate = _cairo_tor_scan_converter_generate;
- pool_init (self->span_pool.base, &self->jmp,
- 250 * sizeof(self->span_pool.embedded[0]),
- sizeof(self->span_pool.embedded));
-
_glitter_scan_converter_init (self->converter, &self->jmp);
status = glitter_scan_converter_reset (self->converter,
xmin, ymin, xmax, ymax);
commit 02da8c7efb007d046f95456734968d7e9335a7af
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 11 13:46:16 2011 +0100
default-context: Tidy push-group
Fix a couple of instances of the older style clipping code.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-default-context.c b/src/cairo-default-context.c
index 4124632..017eb7b 100644
--- a/src/cairo-default-context.c
+++ b/src/cairo-default-context.c
@@ -141,18 +141,18 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
goto bail;
} else {
cairo_surface_t *parent_surface;
- const cairo_rectangle_int_t *clip_extents;
cairo_rectangle_int_t extents;
- cairo_matrix_t matrix;
cairo_bool_t is_empty;
parent_surface = _cairo_gstate_get_target (cr->gstate);
/* Get the extents that we'll use in creating our new group surface */
is_empty = _cairo_surface_get_extents (parent_surface, &extents);
- clip_extents = _cairo_clip_get_extents (_cairo_gstate_get_clip (cr->gstate));
- if (clip_extents != NULL)
- is_empty = _cairo_rectangle_intersect (&extents, clip_extents);
+ if (clip)
+ is_empty = _cairo_rectangle_intersect (&extents,
+ _cairo_clip_get_extents (clip));
+
+ /* XXX unbounded surface creation */
group_surface = _cairo_surface_create_similar_solid (parent_surface,
content,
@@ -175,8 +175,9 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
/* If we have a current path, we need to adjust it to compensate for
* the device offset just applied. */
- cairo_matrix_init_translate (&matrix, -extents.x, -extents.y);
- _cairo_path_fixed_transform (cr->path, &matrix);
+ _cairo_path_fixed_translate (cr->path,
+ _cairo_fixed_from_int (-extents.x),
+ _cairo_fixed_from_int (-extents.y));
}
/* create a new gstate for the redirect */
commit a3d2d5b42b769241e888a34c3edd015619560431
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 12 19:02:35 2011 +0100
script: Remove reference to image-surface-private
That header doesn't exist yet.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 0f7252a..b6e0098 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -50,7 +50,6 @@
#include "cairo-default-context-private.h"
#include "cairo-device-private.h"
#include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
#include "cairo-list-private.h"
#include "cairo-recording-surface-private.h"
#include "cairo-output-stream-private.h"
commit e7bd4c93e320325b09e6a2cc8c3d9547c7b0d1f2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Aug 12 20:15:19 2011 +0100
util/show-traps: Cache the rendering of the traps+edges
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/util/show-traps.c b/util/show-traps.c
index 9a99aba..f46c8b0 100644
--- a/util/show-traps.c
+++ b/util/show-traps.c
@@ -47,6 +47,9 @@ typedef struct _TrapView {
struct _TrapView *group_next;
struct _TrapView *group_prev;
+ cairo_surface_t *pixmap;
+ int pixmap_width, pixmap_height;
+
traps_t *traps_list;
traps_t *current_traps;
@@ -95,30 +98,27 @@ _compute_intersection_point (const line_t *line,
p->x = _compute_intersection_x_for_y (line, p->y = y);
}
-static void
-trap_view_draw (TrapView *self, cairo_t *cr)
+static cairo_surface_t *
+pixmap_create (TrapView *self, cairo_surface_t *target)
{
+ cairo_surface_t *surface = cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR,
+ self->widget.allocation.width,
+ self->widget.allocation.height);
+ cairo_t *cr;
traps_t *traps;
edges_t *edges;
gdouble sf_x, sf_y, sf;
gdouble mid, dim;
- gdouble x0, x1, y0, y1;
+ gdouble x0, y0;
double dash[2] = {8, 8};
double dots[2] = {0., 1.};
int n;
box_t extents;
point_t p;
- cairo_save (cr);
- cairo_save (cr);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_restore (cr);
-
traps = self->current_traps;
if (traps == NULL)
- return;
-
+ return surface;
edges = self->current_edges;
extents = traps->extents;
@@ -146,11 +146,13 @@ trap_view_draw (TrapView *self, cairo_t *cr)
mid = (extents.p2.x + extents.p1.x) / 2.;
dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
x0 = mid - dim;
- x1 = mid + dim;
mid = (extents.p2.y + extents.p1.y) / 2.;
dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
y0 = mid - dim;
- y1 = mid + dim;
+
+ cr = cairo_create (surface);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
cairo_save (cr);
cairo_scale (cr, sf, sf);
@@ -353,12 +355,80 @@ trap_view_draw (TrapView *self, cairo_t *cr)
cairo_restore (cr);
}
+ cairo_destroy (cr);
+ return surface;
+}
+
+static void
+trap_view_draw (TrapView *self, cairo_t *cr)
+{
+ traps_t *traps;
+ edges_t *edges;
+ gdouble sf_x, sf_y, sf;
+ gdouble mid, dim;
+ gdouble x0, y0;
+ double dash[2] = {8, 8};
+ int n;
+ box_t extents;
+ point_t p;
+
+ if (self->pixmap_width != self->widget.allocation.width ||
+ self->pixmap_height != self->widget.allocation.height)
+ {
+ cairo_surface_destroy (self->pixmap);
+ self->pixmap = pixmap_create (self, cairo_get_target (cr));
+ self->pixmap_width = self->widget.allocation.width;
+ self->pixmap_height = self->widget.allocation.height;
+ }
+
+ cairo_save (cr);
+ cairo_set_source_surface (cr, self->pixmap, 0, 0);
+ cairo_paint (cr);
+ cairo_restore (cr);
+
+ traps = self->current_traps;
+ if (traps == NULL)
+ return;
+
+ extents = traps->extents;
+ edges = self->current_edges;
+ if (edges != NULL) {
+ if (edges->extents.p1.x < extents.p1.x)
+ extents.p1.x = edges->extents.p1.x;
+ if (edges->extents.p1.y < extents.p1.y)
+ extents.p1.y = edges->extents.p1.y;
+ if (edges->extents.p2.x > extents.p2.x)
+ extents.p2.x = edges->extents.p2.x;
+ if (edges->extents.p2.y > extents.p2.y)
+ extents.p2.y = edges->extents.p2.y;
+ }
+
+ mid = (extents.p2.x + extents.p1.x) / 2.;
+ dim = (extents.p2.x - extents.p1.x) / 2. * 1.25;
+ sf_x = self->widget.allocation.width / dim / 2;
+
+ mid = (extents.p2.y + extents.p1.y) / 2.;
+ dim = (extents.p2.y - extents.p1.y) / 2. * 1.25;
+ sf_y = self->widget.allocation.height / dim / 2;
+
+ sf = MIN (sf_x, sf_y);
+
+ mid = (extents.p2.x + extents.p1.x) / 2.;
+ dim = sf_x / sf * (extents.p2.x - extents.p1.x) / 2. * 1.25;
+ x0 = mid - dim;
+ mid = (extents.p2.y + extents.p1.y) / 2.;
+ dim = sf_y / sf * (extents.p2.y - extents.p1.y) / 2. * 1.25;
+ y0 = mid - dim;
+
+ cairo_save (cr);
+
/* draw a zoom view of the area around the mouse */
{
- cairo_save (cr);
double zoom = self->mag_zoom;
int size = self->mag_size;
+ cairo_save (cr);
+
/* bottom right */
cairo_rectangle (cr, self->mag_x, self->mag_y, size, size);
cairo_stroke_preserve (cr);
@@ -645,6 +715,7 @@ trap_view_advance (TrapView *self)
self->current_traps = self->current_traps->prev;
if (self->current_edges && self->current_edges->prev)
self->current_edges = self->current_edges->prev;
+ self->pixmap_width = self->pixmap_height = 0;
gtk_widget_queue_draw (&self->widget);
}
@@ -655,6 +726,7 @@ trap_view_back (TrapView *self)
self->current_traps = self->current_traps->next;
if (self->current_edges && self->current_edges->next)
self->current_edges = self->current_edges->next;
+ self->pixmap_width = self->pixmap_height = 0;
gtk_widget_queue_draw (&self->widget);
}
commit b8e8c4cf9a10834923d7185d379d6457687912a1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Aug 11 23:12:32 2011 +0100
util/show-polygon: Show end-points
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/util/show-polygon.c b/util/show-polygon.c
index 7c9031c..5549cf2 100644
--- a/util/show-polygon.c
+++ b/util/show-polygon.c
@@ -49,7 +49,7 @@ typedef struct _PolygonViewClass {
G_DEFINE_TYPE (PolygonView, polygon_view, GTK_TYPE_WIDGET)
-static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
+static void draw_edges (cairo_t *cr, polygon_t *p, gdouble sf, int dir)
{
int n;
@@ -59,6 +59,17 @@ static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
if (e->dir != dir)
continue;
+ cairo_arc (cr, e->p1.x, e->p1.y, 3/sf, 0, 2*M_PI);
+ cairo_arc (cr, e->p2.x, e->p2.y, 3/sf, 0, 2*M_PI);
+ cairo_fill (cr);
+ }
+
+ for (n = 0; n < p->num_edges; n++) {
+ const edge_t *e = &p->edges[n];
+
+ if (e->dir != dir)
+ continue;
+
cairo_move_to (cr, e->p1.x, e->p1.y);
cairo_line_to (cr, e->p2.x, e->p2.y);
}
@@ -69,13 +80,13 @@ static void draw_edges (cairo_t *cr, polygon_t *p, int dir)
} cairo_restore (cr);
}
-static void draw_polygon (cairo_t *cr, polygon_t *p)
+static void draw_polygon (cairo_t *cr, polygon_t *p, gdouble sf)
{
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
- draw_edges (cr, p, -1);
+ draw_edges (cr, p, sf, -1);
cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
- draw_edges (cr, p, +1);
+ draw_edges (cr, p, sf, +1);
}
static cairo_surface_t *
@@ -127,7 +138,7 @@ pixmap_create (PolygonView *self, cairo_surface_t *target)
if (polygon->num_edges == 0)
continue;
- draw_polygon (cr, polygon);
+ draw_polygon (cr, polygon, sf);
}
} cairo_restore (cr);
@@ -211,7 +222,7 @@ polygon_view_draw (PolygonView *self, cairo_t *cr)
if (polygon->num_edges == 0)
continue;
- draw_polygon (cr, polygon);
+ draw_polygon (cr, polygon, zoom);
}
} cairo_restore (cr);
More information about the cairo-commit
mailing list