PS: Fix for dash-zero-length

This commit is contained in:
Carl Worth 2006-06-29 05:13:37 +02:00
parent 7285499700
commit 8aa306caac

View file

@ -1805,15 +1805,82 @@ _cairo_ps_surface_stroke (void *abstract_surface,
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_int_status_t status;
double *dash = style->dash;
int num_dashes = style->num_dashes;
double dash_offset = style->dash_offset;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
return _analyze_operation (surface, op, source);
assert (operation_supported (surface, op, source));
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_stroke\n");
/* PostScript has "special needs" when it comes to zero-length
* dash segments with butt caps. It apparently (at least
* according to ghostscript) draws hairlines for this
* case. That's not what the cairo semantics want, so we first
* touch up the array to eliminate any 0.0 values that will
* result in "on" segments.
*/
if (num_dashes && style->line_cap == CAIRO_LINE_CAP_BUTT) {
int i;
/* If there's an odd number of dash values they will each get
* interpreted as both on and off. So we first explicitly
* expand the array to remove the duplicate usage so that we
* can modify some of the values.
*/
if (num_dashes % 2) {
dash = malloc (2 * num_dashes * sizeof (double));
if (dash == NULL)
return CAIRO_STATUS_NO_MEMORY;
memcpy (dash, style->dash, num_dashes * sizeof (double));
memcpy (dash + num_dashes, style->dash, num_dashes * sizeof (double));
num_dashes *= 2;
}
for (i = 0; i < num_dashes; i += 2) {
if (dash[i] == 0.0) {
/* If we're at the front of the list, we first rotate
* two elements from the end of the list to the front
* of the list before folding away the 0.0. Or, if
* there are only two dash elements, then there is
* nothing at all to draw.
*/
if (i == 0) {
double last_two[2];
if (num_dashes == 2) {
if (dash != style->dash)
free (dash);
return CAIRO_STATUS_SUCCESS;
}
/* The cases of num_dashes == 0, 1, or 3 elements
* cannot exist, so the rotation of 2 elements
* will always be safe */
memcpy (last_two, dash + num_dashes - 2, sizeof (last_two));
memmove (dash + 2, dash, (num_dashes - 2) * sizeof (double));
memcpy (dash, last_two, sizeof (last_two));
dash_offset += dash[0] + dash[1];
i = 2;
}
dash[i-1] += dash[i+1];
num_dashes -= 2;
memmove (dash + i, dash + i + 2, (num_dashes - i) * sizeof (double));
/* If we might have just rotated, it's possible that
* we rotated a 0.0 value to the front of the list.
* Set i to -2 so it will get incremented to 0. */
if (i == 2)
i = -2;
}
}
}
emit_pattern (surface, source);
_cairo_output_stream_printf (stream,
@ -1836,14 +1903,18 @@ _cairo_ps_surface_stroke (void *abstract_surface,
_cairo_output_stream_printf (stream, "%d setlinejoin\n",
_cairo_ps_line_join (style->line_join));
/* dashes */
if (style->num_dashes) {
if (num_dashes) {
int d;
_cairo_output_stream_printf (stream, "[");
for (d = 0; d < style->num_dashes; d++)
_cairo_output_stream_printf (stream, " %f", style->dash[d]);
for (d = 0; d < num_dashes; d++)
_cairo_output_stream_printf (stream, " %f", dash[d]);
_cairo_output_stream_printf (stream, "] %f setdash\n",
style->dash_offset);
dash_offset);
}
if (dash != style->dash)
free (dash);
/* miter limit */
_cairo_output_stream_printf (stream, "%f setmiterlimit\n",
style->miter_limit);