summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-08-04 15:32:25 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-08-29 08:08:31 +0100
commit6dfe050d6360409161418d853df3d7d7dfb216af (patch)
tree3818c4269d6908c3a03018c95ab4698e1356ca3b
parentdc886450ac7c04252cff77729e0653c6ea2768db (diff)
[polygon] Amalgamate collinear edges
Combine sequential collinear edges into a single edge, this benefits immensely by feeding fewer edges into either the tessellator or spans.
-rw-r--r--src/cairo-polygon.c58
-rw-r--r--src/cairo-types-private.h3
2 files changed, 54 insertions, 7 deletions
diff --git a/src/cairo-polygon.c b/src/cairo-polygon.c
index ac4d0945f..a8addff2e 100644
--- a/src/cairo-polygon.c
+++ b/src/cairo-polygon.c
@@ -49,6 +49,7 @@ _cairo_polygon_init (cairo_polygon_t *polygon)
polygon->edges_size = ARRAY_LENGTH (polygon->edges_embedded);
polygon->has_current_point = FALSE;
+ polygon->has_current_edge = FALSE;
polygon->has_limits = FALSE;
polygon->extents.p1.x = polygon->extents.p1.y = INT32_MAX;
@@ -357,6 +358,13 @@ void
_cairo_polygon_move_to (cairo_polygon_t *polygon,
const cairo_point_t *point)
{
+ if (polygon->has_current_edge) {
+ _cairo_polygon_add_edge (polygon,
+ &polygon->last_point,
+ &polygon->current_point);
+ polygon->has_current_edge = FALSE;
+ }
+
if (! polygon->has_current_point) {
polygon->first_point = *point;
polygon->has_current_point = TRUE;
@@ -369,20 +377,56 @@ void
_cairo_polygon_line_to (cairo_polygon_t *polygon,
const cairo_point_t *point)
{
- if (polygon->has_current_point)
- _cairo_polygon_add_edge (polygon, &polygon->current_point, point);
+ /* squash collinear edges */
+ if (polygon->has_current_edge) {
+ if (polygon->current_point.x != point->x ||
+ polygon->current_point.y != point->y)
+ {
+ cairo_slope_t this;
+
+ _cairo_slope_init (&this, &polygon->current_point, point);
+ if (_cairo_slope_equal (&polygon->current_edge, &this)) {
+ polygon->current_point = *point;
+ return;
+ }
+
+ _cairo_polygon_add_edge (polygon,
+ &polygon->last_point,
+ &polygon->current_point);
+
+ polygon->last_point = polygon->current_point;
+ polygon->current_edge = this;
+ }
+ } else if (polygon->has_current_point) {
+ if (polygon->current_point.x != point->x ||
+ polygon->current_point.y != point->y)
+ {
+ polygon->last_point = polygon->current_point;
+ _cairo_slope_init (&polygon->current_edge,
+ &polygon->last_point,
+ point);
+ polygon->has_current_edge = TRUE;
+ }
+ } else {
+ polygon->first_point = *point;
+ polygon->has_current_point = TRUE;
+ }
- _cairo_polygon_move_to (polygon, point);
+ polygon->current_point = *point;
}
void
_cairo_polygon_close (cairo_polygon_t *polygon)
{
if (polygon->has_current_point) {
- _cairo_polygon_add_edge (polygon,
- &polygon->current_point,
- &polygon->first_point);
-
+ _cairo_polygon_line_to (polygon, &polygon->first_point);
polygon->has_current_point = FALSE;
}
+
+ if (polygon->has_current_edge) {
+ _cairo_polygon_add_edge (polygon,
+ &polygon->last_point,
+ &polygon->current_point);
+ polygon->has_current_edge = FALSE;
+ }
}
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index fa7067852..1e1f823d8 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -247,8 +247,11 @@ typedef struct _cairo_polygon {
cairo_status_t status;
cairo_point_t first_point;
+ cairo_point_t last_point;
cairo_point_t current_point;
+ cairo_slope_t current_edge;
cairo_bool_t has_current_point;
+ cairo_bool_t has_current_edge;
cairo_box_t extents;
cairo_box_t limits;