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
This commit is contained in:
Carl Worth 2005-08-19 12:02:14 +00:00
parent a2e798b5a1
commit 2b72a4eee8
9 changed files with 203 additions and 15 deletions

View file

@ -6,6 +6,26 @@
* src/cairo-pdf-surface.c (cairo_pdf_surface_create): Document
this funtion.
2005-08-19 Carl Worth <cworth@cworth.org>
Fix for bug #2729:
* src/cairo-gstate.c: (_cairo_gstate_set_dash): 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).
* src/cairo.c (cairo_set_dash): Add documentation.
* src/cairo.h:
* src/cairo.c: (cairo_status_to_string): Add new
CAIRO_STATUS_INVALID_DASH.
* test/.cvsignore:
* test/Makefile.am: Add dash-offfset-negative test from Owen.
* doc/public/tmpl/cairo.sgml: churn
2005-08-19 Carl Worth <cworth@cworth.org>
Fix for bug #3915:

View file

@ -279,8 +279,10 @@ Drawing contexts.
@cr:
@dashes:
@ndash:
@num_dashes:
@offset:
<!-- # Unused Parameters # -->
@ndash:
<!-- ##### FUNCTION cairo_set_miter_limit ##### -->
@ -1027,6 +1029,7 @@ Drawing contexts.
@CAIRO_STATUS_INVALID_FORMAT:
@CAIRO_STATUS_INVALID_VISUAL:
@CAIRO_STATUS_FILE_NOT_FOUND:
@CAIRO_STATUS_INVALID_DASH:
<!-- ##### FUNCTION cairo_status ##### -->
<para>

View file

@ -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;

View file

@ -62,7 +62,7 @@ static const cairo_t cairo_nil = {
* a bit of a pain, but it should be easy to always catch as long as
* one adds a new test case to test a trigger of the new status value.
*/
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_FILE_NOT_FOUND
#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DASH
/**
* _cairo_error:
@ -715,15 +715,42 @@ cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join)
_cairo_set_error (cr, cr->status);
}
/**
* cairo_set_dash:
* @cr: a cairo context
* @dashes: an array specifying alternate lengths of on and off po
* @num_dashes: the length of the dashes array
* @offset: an offset into the dash pattern at which the stroke should start
*
* Sets the dash pattern to be used by cairo_stroke(). A dash pattern
* is specified by @dashes, an array of positive values. Each value
* provides the user-space length of altenate "on" and "off" portions
* of the stroke. The @offset specifies an offset into the pattern at
* which the stroke begins.
*
* If @num_dashes is 0 dashing is disabled.
*
* If @num_dashes is 1 a symmetric pattern is assumed with alternating
* on and off portions of the size specified by the single value in
* @dashes.
*
* If any value in @dashes is negative, or if all values are 0, then
* @cairo_t will be put into an error state with a status of
* #CAIRO_STATUS_INVALID_DASH.
**/
void
cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset)
cairo_set_dash (cairo_t *cr,
double *dashes,
int num_dashes,
double offset)
{
if (cr->status) {
_cairo_set_error (cr, cr->status);
return;
}
cr->status = _cairo_gstate_set_dash (cr->gstate, dashes, ndash, offset);
cr->status = _cairo_gstate_set_dash (cr->gstate,
dashes, num_dashes, offset);
if (cr->status)
_cairo_set_error (cr, cr->status);
}
@ -2483,6 +2510,8 @@ cairo_status_to_string (cairo_status_t status)
return "invalid value for an input Visual*";
case CAIRO_STATUS_FILE_NOT_FOUND:
return "file not found";
case CAIRO_STATUS_INVALID_DASH:
return "invalid value for a dash setting";
}
return "<unknown error status>";

View file

@ -166,6 +166,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_INVALID_FORMAT: invalid value for an input cairo_format_t
* @CAIRO_STATUS_INVALID_VISUAL: invalid value for an input Visual*
* @CAIRO_STATUS_FILE_NOT_FOUND: file not found
* @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting
*
* #cairo_status_t is used to indicate errors that can occur when
* using Cairo. In some cases it is returned directly by functions.
@ -191,7 +192,8 @@ typedef enum _cairo_status {
CAIRO_STATUS_INVALID_CONTENT,
CAIRO_STATUS_INVALID_FORMAT,
CAIRO_STATUS_INVALID_VISUAL,
CAIRO_STATUS_FILE_NOT_FOUND
CAIRO_STATUS_FILE_NOT_FOUND,
CAIRO_STATUS_INVALID_DASH
} cairo_status_t;
/**
@ -386,7 +388,10 @@ void
cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join);
void
cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset);
cairo_set_dash (cairo_t *cr,
double *dashes,
int num_dashes,
double offset);
void
cairo_set_miter_limit (cairo_t *cr, double limit);

View file

@ -12,6 +12,7 @@ composite-integer-translate-over-repeat
coverage
create-from-png
create-from-png-stream
dash-offset-negative
fill-and-stroke
fill-rule
filter-nearest-offset

View file

@ -9,6 +9,7 @@ composite-integer-translate-over \
composite-integer-translate-over-repeat \
create-from-png \
create-from-png-stream \
dash-offset-negative \
fill-and-stroke \
fill-rule \
filter-nearest-offset \
@ -80,6 +81,7 @@ composite-integer-translate-over-ref.png \
composite-integer-translate-over-repeat-ref.png \
create-from-png-ref.png \
create-from-png-stream-ref.png \
dash-offset-negative-ref.png \
fill-and-stroke-ref.png \
fill-rule-ref.png \
filter-nearest-offset-ref.png \
@ -91,6 +93,7 @@ mask-ref.png \
mask-ctm-ref.png \
mask-surface-ctm-ref.png \
move-to-show-surface-ref.png \
nil-surface-ref.png \
operator-clear-ref.png \
operator-source-ref.png \
paint-ref.png \
@ -182,6 +185,7 @@ composite_integer_translate_over_LDADD = $(LDADDS)
composite_integer_translate_over_repeat_LDADD = $(LDADDS)
create_from_png_LDADD = $(LDADDS)
create_from_png_stream_LDADD = $(LDADDS)
dash_offset_negative_LDADD = $(LDADDS)
fill_and_stroke_LDADD = $(LDADDS)
fill_rule_LDADD = $(LDADDS)
filter_nearest_offset_LDADD = $(LDADDS)

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

View file

@ -0,0 +1,99 @@
/*
* Copyright © 2005 Red Hat, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of
* Red Hat, Inc. not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. Red Hat, Inc. makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Author: Owen Taylor <otaylor@redhat.com>
*/
#include "cairo-test.h"
#define IMAGE_WIDTH 19
#define IMAGE_HEIGHT 19
/* Basic test of dashed strokes, including a test for the negative
* dash offset bug:
*
* https://bugs.freedesktop.org/show_bug.cgi?id=2729
*/
cairo_test_t test = {
"dash-offset-negative",
"Tests cairo_set_dash with a negative offset",
IMAGE_WIDTH, IMAGE_HEIGHT
};
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
double dashes[] = { 1 };
cairo_set_line_width (cr, 2);
/* Basic 1-1 dash pattern */
cairo_set_dash (cr, dashes, 1, 0.);
cairo_move_to (cr, 1, 2);
cairo_line_to (cr, 18, 2);
cairo_stroke (cr);
/* Adjust path by 0.5. Ideally this would give a constant 50%
* gray, (but does not due to the location of the regular sample
* grid points. */
cairo_move_to (cr, 1.5, 5);
cairo_line_to (cr, 18., 5);
cairo_stroke (cr);
/* Offset dash by 0.5, rather than the path */
cairo_set_dash (cr, dashes, 1, 0.5);
cairo_move_to (cr, 1, 8);
cairo_line_to (cr, 18, 8);
cairo_stroke (cr);
/* Now, similar tests with negative dash offsets. */
/* Basic 1-1 dash pattern dashing */
cairo_set_dash (cr, dashes, 1, -4);
cairo_move_to (cr, 1, 11);
cairo_line_to (cr, 18, 11);
cairo_stroke (cr);
/* Adjust path by 0.5 */
cairo_move_to (cr, 1.5, 14);
cairo_line_to (cr, 18., 14);
cairo_stroke (cr);
/* Offset dash by 0.5 */
cairo_set_dash (cr, dashes, 1, -3.5);
cairo_move_to (cr, 1, 17);
cairo_line_to (cr, 18, 17);
cairo_stroke (cr);
return CAIRO_TEST_SUCCESS;
}
int
main (void)
{
return cairo_test (&test, draw);
}