summaryrefslogtreecommitdiff
path: root/src/cairo-path-stroke-boxes.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-03-19 19:42:01 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-03-19 20:02:50 +0000
commit0a778d974f2dca2555711ef79e738cb0614b2a3f (patch)
treec36f5f400c6eff6b48b2b765872540d1a760b0a1 /src/cairo-path-stroke-boxes.c
parent1e4f385dec03083b2453205bf5f4bef25b3af806 (diff)
downloadcairo-0a778d974f2dca2555711ef79e738cb0614b2a3f.tar.gz
stroke: Adapt rectilinear stroker to handle separable non-unity scaling
Reported-by: Christos Sotiriou <csotiriou@gmail.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-path-stroke-boxes.c')
-rw-r--r--src/cairo-path-stroke-boxes.c125
1 files changed, 65 insertions, 60 deletions
diff --git a/src/cairo-path-stroke-boxes.c b/src/cairo-path-stroke-boxes.c
index 12e4dd165..3e8c5a4ce 100644
--- a/src/cairo-path-stroke-boxes.c
+++ b/src/cairo-path-stroke-boxes.c
@@ -57,7 +57,7 @@ typedef struct _cairo_rectilinear_stroker {
const cairo_matrix_t *ctm;
cairo_antialias_t antialias;
- cairo_fixed_t half_line_width;
+ cairo_fixed_t half_line_x, half_line_y;
cairo_boxes_t *boxes;
cairo_point_t current_point;
cairo_point_t first_point;
@@ -82,11 +82,11 @@ _cairo_rectilinear_stroker_limit (cairo_rectilinear_stroker_t *stroker,
stroker->has_bounds = TRUE;
_cairo_boxes_get_extents (boxes, num_boxes, &stroker->bounds);
- stroker->bounds.p1.x -= stroker->half_line_width;
- stroker->bounds.p2.x += stroker->half_line_width;
+ stroker->bounds.p1.x -= stroker->half_line_x;
+ stroker->bounds.p2.x += stroker->half_line_x;
- stroker->bounds.p1.y -= stroker->half_line_width;
- stroker->bounds.p2.y += stroker->half_line_width;
+ stroker->bounds.p1.y -= stroker->half_line_y;
+ stroker->bounds.p2.y += stroker->half_line_y;
}
static cairo_bool_t
@@ -122,15 +122,18 @@ _cairo_rectilinear_stroker_init (cairo_rectilinear_stroker_t *stroker,
return FALSE;
}
- if (! _cairo_matrix_has_unity_scale (ctm))
+ if (! _cairo_matrix_is_scale (ctm))
return FALSE;
stroker->stroke_style = stroke_style;
stroker->ctm = ctm;
stroker->antialias = antialias;
- stroker->half_line_width =
- _cairo_fixed_from_double (stroke_style->line_width / 2.0);
+ stroker->half_line_x =
+ _cairo_fixed_from_double (fabs(ctm->xx) * stroke_style->line_width / 2.0);
+ stroker->half_line_y =
+ _cairo_fixed_from_double (fabs(ctm->yy) * stroke_style->line_width / 2.0);
+
stroker->open_sub_path = FALSE;
stroker->segments = stroker->segments_embedded;
stroker->segments_size = ARRAY_LENGTH (stroker->segments_embedded);
@@ -197,7 +200,8 @@ static cairo_status_t
_cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
{
cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
- cairo_fixed_t half_line_width = stroker->half_line_width;
+ cairo_fixed_t half_line_x = stroker->half_line_x;
+ cairo_fixed_t half_line_y = stroker->half_line_y;
cairo_status_t status;
int i;
@@ -238,26 +242,26 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
if (a->y == b->y) {
if (a->x < b->x) {
if (lengthen_initial)
- a->x -= half_line_width;
+ a->x -= half_line_x;
if (lengthen_final)
- b->x += half_line_width;
+ b->x += half_line_x;
} else {
if (lengthen_initial)
- a->x += half_line_width;
+ a->x += half_line_x;
if (lengthen_final)
- b->x -= half_line_width;
+ b->x -= half_line_x;
}
} else {
if (a->y < b->y) {
if (lengthen_initial)
- a->y -= half_line_width;
+ a->y -= half_line_y;
if (lengthen_final)
- b->y += half_line_width;
+ b->y += half_line_y;
} else {
if (lengthen_initial)
- a->y += half_line_width;
+ a->y += half_line_y;
if (lengthen_final)
- b->y -= half_line_width;
+ b->y -= half_line_y;
}
}
}
@@ -265,11 +269,11 @@ _cairo_rectilinear_stroker_emit_segments (cairo_rectilinear_stroker_t *stroker)
/* Form the rectangle by expanding by half the line width in
* either perpendicular direction. */
if (a->y == b->y) {
- a->y -= half_line_width;
- b->y += half_line_width;
+ a->y -= half_line_y;
+ b->y += half_line_y;
} else {
- a->x -= half_line_width;
- b->x += half_line_width;
+ a->x -= half_line_x;
+ b->x += half_line_x;
}
if (a->x < b->x) {
@@ -301,7 +305,8 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
{
cairo_status_t status;
cairo_line_cap_t line_cap = stroker->stroke_style->line_cap;
- cairo_fixed_t half_line_width = stroker->half_line_width;
+ cairo_fixed_t half_line_x = stroker->half_line_x;
+ cairo_fixed_t half_line_y = stroker->half_line_y;
int i;
for (i = 0; i < stroker->num_segments; i++) {
@@ -332,25 +337,25 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
if (is_horizontal) {
if (box.p1.x <= box.p2.x) {
box.p1.x = box.p2.x;
- box.p2.x += half_line_width;
+ box.p2.x += half_line_x;
} else {
- box.p1.x = box.p2.x - half_line_width;
+ box.p1.x = box.p2.x - half_line_x;
}
if (out_slope.dy >= 0)
- box.p1.y -= half_line_width;
+ box.p1.y -= half_line_x;
if (out_slope.dy <= 0)
- box.p2.y += half_line_width;
+ box.p2.y += half_line_x;
} else {
if (box.p1.y <= box.p2.y) {
box.p1.y = box.p2.y;
- box.p2.y += half_line_width;
+ box.p2.y += half_line_x;
} else {
- box.p1.y = box.p2.y - half_line_width;
+ box.p1.y = box.p2.y - half_line_x;
}
if (out_slope.dx >= 0)
- box.p1.x -= half_line_width;
+ box.p1.x -= half_line_x;
if (out_slope.dx <= 0)
- box.p2.x += half_line_width;
+ box.p2.x += half_line_x;
}
status = _cairo_boxes_add (stroker->boxes, stroker->antialias, &box);
@@ -362,29 +367,29 @@ _cairo_rectilinear_stroker_emit_segments_dashed (cairo_rectilinear_stroker_t *st
if (is_horizontal) {
if (line_cap == CAIRO_LINE_CAP_SQUARE) {
if (a->x <= b->x) {
- a->x -= half_line_width;
- b->x += half_line_width;
+ a->x -= half_line_x;
+ b->x += half_line_x;
} else {
- a->x += half_line_width;
- b->x -= half_line_width;
+ a->x += half_line_x;
+ b->x -= half_line_x;
}
}
- a->y += half_line_width;
- b->y -= half_line_width;
+ a->y += half_line_y;
+ b->y -= half_line_y;
} else {
if (line_cap == CAIRO_LINE_CAP_SQUARE) {
if (a->y <= b->y) {
- a->y -= half_line_width;
- b->y += half_line_width;
+ a->y -= half_line_y;
+ b->y += half_line_y;
} else {
- a->y += half_line_width;
- b->y -= half_line_width;
+ a->y += half_line_y;
+ b->y -= half_line_y;
}
}
- a->x += half_line_width;
- b->x -= half_line_width;
+ a->x += half_line_x;
+ b->x -= half_line_x;
}
if (a->x == b->x && a->y == b->y)
@@ -621,40 +626,40 @@ _cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path,
if (! rectilinear_stroker.dash.dashed &&
_cairo_path_fixed_is_stroke_box (path, &box) &&
/* if the segments overlap we need to feed them into the tessellator */
- box.p2.x - box.p1.x > 2* rectilinear_stroker.half_line_width &&
- box.p2.y - box.p1.y > 2* rectilinear_stroker.half_line_width)
+ box.p2.x - box.p1.x > 2* rectilinear_stroker.half_line_x &&
+ box.p2.y - box.p1.y > 2* rectilinear_stroker.half_line_y)
{
cairo_box_t b;
/* top */
- b.p1.x = box.p1.x - rectilinear_stroker.half_line_width;
- b.p2.x = box.p2.x + rectilinear_stroker.half_line_width;
- b.p1.y = box.p1.y - rectilinear_stroker.half_line_width;
- b.p2.y = box.p1.y + rectilinear_stroker.half_line_width;
+ b.p1.x = box.p1.x - rectilinear_stroker.half_line_x;
+ b.p2.x = box.p2.x + rectilinear_stroker.half_line_x;
+ b.p1.y = box.p1.y - rectilinear_stroker.half_line_y;
+ b.p2.y = box.p1.y + rectilinear_stroker.half_line_y;
status = _cairo_boxes_add (boxes, antialias, &b);
assert (status == CAIRO_INT_STATUS_SUCCESS);
/* left (excluding top/bottom) */
- b.p1.x = box.p1.x - rectilinear_stroker.half_line_width;
- b.p2.x = box.p1.x + rectilinear_stroker.half_line_width;
- b.p1.y = box.p1.y + rectilinear_stroker.half_line_width;
- b.p2.y = box.p2.y - rectilinear_stroker.half_line_width;
+ b.p1.x = box.p1.x - rectilinear_stroker.half_line_x;
+ b.p2.x = box.p1.x + rectilinear_stroker.half_line_x;
+ b.p1.y = box.p1.y + rectilinear_stroker.half_line_y;
+ b.p2.y = box.p2.y - rectilinear_stroker.half_line_y;
status = _cairo_boxes_add (boxes, antialias, &b);
assert (status == CAIRO_INT_STATUS_SUCCESS);
/* right (excluding top/bottom) */
- b.p1.x = box.p2.x - rectilinear_stroker.half_line_width;
- b.p2.x = box.p2.x + rectilinear_stroker.half_line_width;
- b.p1.y = box.p1.y + rectilinear_stroker.half_line_width;
- b.p2.y = box.p2.y - rectilinear_stroker.half_line_width;
+ b.p1.x = box.p2.x - rectilinear_stroker.half_line_x;
+ b.p2.x = box.p2.x + rectilinear_stroker.half_line_x;
+ b.p1.y = box.p1.y + rectilinear_stroker.half_line_y;
+ b.p2.y = box.p2.y - rectilinear_stroker.half_line_y;
status = _cairo_boxes_add (boxes, antialias, &b);
assert (status == CAIRO_INT_STATUS_SUCCESS);
/* bottom */
- b.p1.x = box.p1.x - rectilinear_stroker.half_line_width;
- b.p2.x = box.p2.x + rectilinear_stroker.half_line_width;
- b.p1.y = box.p2.y - rectilinear_stroker.half_line_width;
- b.p2.y = box.p2.y + rectilinear_stroker.half_line_width;
+ b.p1.x = box.p1.x - rectilinear_stroker.half_line_x;
+ b.p2.x = box.p2.x + rectilinear_stroker.half_line_x;
+ b.p1.y = box.p2.y - rectilinear_stroker.half_line_y;
+ b.p2.y = box.p2.y + rectilinear_stroker.half_line_y;
status = _cairo_boxes_add (boxes, antialias, &b);
assert (status == CAIRO_INT_STATUS_SUCCESS);