mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-29 16:20:40 +02:00
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:
parent
a2e798b5a1
commit
2b72a4eee8
9 changed files with 203 additions and 15 deletions
20
ChangeLog
20
ChangeLog
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
35
src/cairo.c
35
src/cairo.c
|
|
@ -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>";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
BIN
test/dash-offset-negative-ref.png
Normal file
BIN
test/dash-offset-negative-ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 155 B |
99
test/dash-offset-negative.c
Normal file
99
test/dash-offset-negative.c
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue