summaryrefslogtreecommitdiff
path: root/src/cairo-gstate.c
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2005-08-19 12:02:14 +0000
committerCarl Worth <cworth@cworth.org>2005-08-19 12:02:14 +0000
commit2b72a4eee80e73f0553779a281e6ef5f0587519e (patch)
treea59ebce04ad87fc7a2e457967dc4df368605d7c6 /src/cairo-gstate.c
parenta2e798b5a126a0aaf7043b817120986889538acf (diff)
Fix for bug #2729:
Adjust negative offsets up to their equivalent positive value. Add error checking for dash values, (must each be non-negative and must not be all zero). Add documentation. Add new CAIRO_STATUS_INVALID_DASH. Add dash-offfset-negative test from Owen. churn
Diffstat (limited to 'src/cairo-gstate.c')
-rw-r--r--src/cairo-gstate.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 79962c3a..c7b0c640 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -430,21 +430,48 @@ _cairo_gstate_get_line_join (cairo_gstate_t *gstate)
cairo_status_t
_cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset)
{
- if (gstate->dash) {
+ int i;
+ double dash_total;
+
+ if (gstate->dash)
free (gstate->dash);
- gstate->dash = NULL;
- }
gstate->num_dashes = num_dashes;
- if (gstate->num_dashes) {
- gstate->dash = malloc (gstate->num_dashes * sizeof (double));
- if (gstate->dash == NULL) {
- gstate->num_dashes = 0;
- return CAIRO_STATUS_NO_MEMORY;
- }
+
+ if (gstate->num_dashes == 0) {
+ gstate->dash = NULL;
+ gstate->dash_offset = 0.0;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ gstate->dash = malloc (gstate->num_dashes * sizeof (double));
+ if (gstate->dash == NULL) {
+ gstate->num_dashes = 0;
+ return CAIRO_STATUS_NO_MEMORY;
}
memcpy (gstate->dash, dash, gstate->num_dashes * sizeof (double));
+
+ dash_total = 0.0;
+ for (i = 0; i < gstate->num_dashes; i++) {
+ if (gstate->dash[i] < 0)
+ return CAIRO_STATUS_INVALID_DASH;
+ dash_total += gstate->dash[i];
+ }
+
+ if (dash_total == 0.0)
+ return CAIRO_STATUS_INVALID_DASH;
+
+ /* A single dash value indicate symmetric repeating, so the total
+ * is twice as long. */
+ if (gstate->num_dashes == 1)
+ dash_total *= 2;
+
+ /* The dashing code doesn't like a negative offset, so we compute
+ * the equivalent positive offset. */
+ if (offset < 0)
+ offset += ceil (-offset / dash_total + 0.5) * dash_total;
+
gstate->dash_offset = offset;
return CAIRO_STATUS_SUCCESS;