mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 12:18:01 +02:00
Fix for bug #4088:
New function to return the current nil pattern depending on the status. Add missing early bailout on surface->status with error propagation to the pattern. Related cleanups for cairo_pattern_t: Don't check other->status since this is a static function. Add missing early bailout on other->status. Cleanup identifier names. Track rename of nil patterns. Don't call _cairo_error for pre-existing errors. Take care to initialize some fields to that _cairo_pattern_release_surface will work even after an error. Track rename of cairo_solid_pattern_nil to cairo_pattern_nil. New test to ensure that a file-not-found error will propagate from a surface, through a pattern, and onto a cairo_t.
This commit is contained in:
parent
0e56f2ea0a
commit
435fb3c65f
8 changed files with 184 additions and 57 deletions
48
ChangeLog
48
ChangeLog
|
|
@ -1,3 +1,51 @@
|
|||
2005-08-18 Carl Worth <cworth@cworth.org>
|
||||
|
||||
Fix for bug #4088:
|
||||
|
||||
* src/cairo-pattern.c: (_cairo_pattern_nil_for_status):
|
||||
New function to return the current nil pattern depending on the
|
||||
status.
|
||||
|
||||
* src/cairo-pattern.c: (cairo_pattern_create_for_surface):
|
||||
* src/cairo-pattern.c: (_cairo_pattern_init_for_surface): Add
|
||||
missing early bailout on surface->status with error propagation to
|
||||
the pattern.
|
||||
|
||||
Related cleanups for cairo_pattern_t:
|
||||
|
||||
* src/cairo-pattern.c: (_cairo_gradient_pattern_init_copy): Don't
|
||||
check other->status since this is a static function.
|
||||
|
||||
* src/cairo-pattern.c: (_cairo_pattern_init_copy): Add missing
|
||||
early bailout on other->status.
|
||||
|
||||
* src/cairo-pattern.c: (_cairo_pattern_fini): Cleanup identifier
|
||||
names.
|
||||
|
||||
* src/cairo-pattern.c: (_cairo_pattern_create_solid),
|
||||
(cairo_pattern_create_linear), (cairo_pattern_create_radial):
|
||||
Track rename of nil patterns.
|
||||
|
||||
* src/cairo-pattern.c: (cairo_pattern_set_matrix),
|
||||
(cairo_pattern_set_filter),
|
||||
(cairo_pattern_set_extend): Don't call _cairo_error for
|
||||
pre-existing errors.
|
||||
|
||||
* src/cairo-pattern.c: (_cairo_pattern_acquire_surface): Take care
|
||||
to initialize some fields to that _cairo_pattern_release_surface
|
||||
will work even after an error.
|
||||
|
||||
* src/cairoint.h:
|
||||
* src/cairo.c: (cairo_get_source): Track rename of
|
||||
cairo_solid_pattern_nil to cairo_pattern_nil.
|
||||
|
||||
* test/.cvsignore:
|
||||
* test/Makefile.am:
|
||||
* test/nil-surface-ref.png:
|
||||
* test/nil-surface.c: (draw), (main): New test to ensure that a
|
||||
file-not-found error will propagate from a surface, through a
|
||||
pattern, and onto a cairo_t.
|
||||
|
||||
2005-08-18 Carl Worth <cworth@cworth.org>
|
||||
|
||||
* test/.valgrind-suppressions: Suppress a pthread initialization
|
||||
|
|
|
|||
|
|
@ -50,51 +50,46 @@ typedef struct _cairo_shader_op {
|
|||
((unsigned char) \
|
||||
((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff))
|
||||
|
||||
const cairo_solid_pattern_t cairo_solid_pattern_nil = {
|
||||
const cairo_solid_pattern_t cairo_pattern_nil = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
{ 0.0, 0.0, 0.0, 1.0, /* solid black */
|
||||
0x0, 0x0, 0x0, 0xffff }
|
||||
};
|
||||
|
||||
static const cairo_surface_pattern_t cairo_surface_pattern_nil = {
|
||||
{ CAIRO_PATTERN_SURFACE, /* type */
|
||||
const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
CAIRO_STATUS_FILE_NOT_FOUND, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
NULL /* surface */
|
||||
};
|
||||
|
||||
static const cairo_linear_pattern_t cairo_linear_pattern_nil = {
|
||||
{ { CAIRO_PATTERN_LINEAR, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
NULL, /* stops */
|
||||
0 }, /* n_stops */
|
||||
{ 0., 0. }, { 1.0, 1.0 } /* point0, point1 */
|
||||
const cairo_solid_pattern_t cairo_pattern_nil_read_error = {
|
||||
{ CAIRO_PATTERN_SOLID, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_READ_ERROR, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
};
|
||||
|
||||
static const cairo_radial_pattern_t cairo_radial_pattern_nil = {
|
||||
{ { CAIRO_PATTERN_RADIAL, /* type */
|
||||
(unsigned int)-1, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
|
||||
CAIRO_FILTER_DEFAULT, /* filter */
|
||||
CAIRO_EXTEND_DEFAULT }, /* extend */
|
||||
NULL, /* stops */
|
||||
0 }, /* n_stops */
|
||||
{ 0., 0. }, { 0.0, 0.0 }, /* center0, center1 */
|
||||
1.0, 1.0, /* radius0, radius1 */
|
||||
};
|
||||
static const cairo_pattern_t *
|
||||
_cairo_pattern_nil_for_status (cairo_status_t status)
|
||||
{
|
||||
switch (status) {
|
||||
case CAIRO_STATUS_FILE_NOT_FOUND:
|
||||
return &cairo_pattern_nil_file_not_found.base;
|
||||
case CAIRO_STATUS_READ_ERROR:
|
||||
return &cairo_pattern_nil_read_error.base;
|
||||
default:
|
||||
case CAIRO_STATUS_NO_MEMORY:
|
||||
return &cairo_pattern_nil.base;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_pattern_set_error:
|
||||
|
|
@ -152,17 +147,11 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
|
|||
*dst = *src;
|
||||
}
|
||||
|
||||
if (other->base.status)
|
||||
_cairo_pattern_set_error (&pattern->base, other->base.status);
|
||||
|
||||
if (other->n_stops)
|
||||
{
|
||||
pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t));
|
||||
if (pattern->stops == NULL) {
|
||||
if (other->base.type == CAIRO_PATTERN_LINEAR)
|
||||
_cairo_gradient_pattern_init_copy (pattern, &cairo_linear_pattern_nil.base);
|
||||
else
|
||||
_cairo_gradient_pattern_init_copy (pattern, &cairo_radial_pattern_nil.base);
|
||||
_cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -175,6 +164,11 @@ void
|
|||
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
|
||||
const cairo_pattern_t *other)
|
||||
{
|
||||
if (other->status) {
|
||||
_cairo_pattern_set_error (pattern, other->status);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (other->type) {
|
||||
case CAIRO_PATTERN_SOLID: {
|
||||
cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
|
||||
|
|
@ -208,16 +202,18 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
|
|||
case CAIRO_PATTERN_SOLID:
|
||||
break;
|
||||
case CAIRO_PATTERN_SURFACE: {
|
||||
cairo_surface_pattern_t *fini = (cairo_surface_pattern_t *) pattern;
|
||||
cairo_surface_pattern_t *surface_pattern =
|
||||
(cairo_surface_pattern_t *) pattern;
|
||||
|
||||
cairo_surface_destroy (fini->surface);
|
||||
cairo_surface_destroy (surface_pattern->surface);
|
||||
} break;
|
||||
case CAIRO_PATTERN_LINEAR:
|
||||
case CAIRO_PATTERN_RADIAL: {
|
||||
cairo_gradient_pattern_t *fini = (cairo_gradient_pattern_t *) pattern;
|
||||
cairo_gradient_pattern_t *gradient =
|
||||
(cairo_gradient_pattern_t *) pattern;
|
||||
|
||||
if (fini->n_stops)
|
||||
free (fini->stops);
|
||||
if (gradient->stops)
|
||||
free (gradient->stops);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
@ -234,6 +230,13 @@ void
|
|||
_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
if (surface->status) {
|
||||
/* Force to solid to simplify the pattern_fini process. */
|
||||
pattern->base.type = CAIRO_PATTERN_SOLID;
|
||||
_cairo_pattern_set_error (&pattern->base, surface->status);
|
||||
return;
|
||||
}
|
||||
|
||||
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SURFACE);
|
||||
|
||||
pattern->surface = cairo_surface_reference (surface);
|
||||
|
|
@ -283,7 +286,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
|
|||
|
||||
pattern = malloc (sizeof (cairo_solid_pattern_t));
|
||||
if (pattern == NULL)
|
||||
return (cairo_pattern_t *) &cairo_solid_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
|
||||
_cairo_pattern_init_solid (pattern, color);
|
||||
|
||||
|
|
@ -391,10 +394,13 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface)
|
|||
{
|
||||
cairo_surface_pattern_t *pattern;
|
||||
|
||||
if (surface->status)
|
||||
return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status);
|
||||
|
||||
pattern = malloc (sizeof (cairo_surface_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *)&cairo_surface_pattern_nil.base;
|
||||
return (cairo_pattern_t *)&cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (pattern, surface);
|
||||
|
|
@ -436,7 +442,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
|
|||
pattern = malloc (sizeof (cairo_linear_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *) &cairo_linear_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
|
||||
|
|
@ -481,7 +487,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0,
|
|||
pattern = malloc (sizeof (cairo_radial_pattern_t));
|
||||
if (pattern == NULL) {
|
||||
_cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_pattern_t *) &cairo_radial_pattern_nil.base;
|
||||
return (cairo_pattern_t *) &cairo_pattern_nil.base;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
|
||||
|
|
@ -717,10 +723,8 @@ void
|
|||
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
|
||||
const cairo_matrix_t *matrix)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->matrix = *matrix;
|
||||
}
|
||||
|
|
@ -741,10 +745,8 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
|
|||
void
|
||||
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->filter = filter;
|
||||
}
|
||||
|
|
@ -758,10 +760,8 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern)
|
|||
void
|
||||
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
|
||||
{
|
||||
if (pattern->status) {
|
||||
_cairo_pattern_set_error (pattern, pattern->status);
|
||||
if (pattern->status)
|
||||
return;
|
||||
}
|
||||
|
||||
pattern->extend = extend;
|
||||
}
|
||||
|
|
@ -1457,8 +1457,11 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (pattern->status)
|
||||
if (pattern->status) {
|
||||
*surface_out = NULL;
|
||||
attributes->acquired = FALSE;
|
||||
return pattern->status;
|
||||
}
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_SOLID: {
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ cairo_pattern_t *
|
|||
cairo_get_source (cairo_t *cr)
|
||||
{
|
||||
if (cr->status)
|
||||
return (cairo_pattern_t*) &cairo_solid_pattern_nil.base;
|
||||
return (cairo_pattern_t*) &cairo_pattern_nil.base;
|
||||
|
||||
return _cairo_gstate_get_source (cr->gstate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -936,7 +936,7 @@ typedef struct _cairo_solid_pattern {
|
|||
cairo_color_t color;
|
||||
} cairo_solid_pattern_t;
|
||||
|
||||
extern const cairo_private cairo_solid_pattern_t cairo_solid_pattern_nil;
|
||||
extern const cairo_private cairo_solid_pattern_t cairo_pattern_nil;
|
||||
|
||||
typedef struct _cairo_surface_pattern {
|
||||
cairo_pattern_t base;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ mask
|
|||
mask-ctm
|
||||
mask-surface-ctm
|
||||
move-to-show-surface
|
||||
nil-surface
|
||||
operator-clear
|
||||
operator-source
|
||||
paint
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ mask \
|
|||
mask-ctm \
|
||||
mask-surface-ctm \
|
||||
move-to-show-surface \
|
||||
nil-surface \
|
||||
operator-clear \
|
||||
operator-source \
|
||||
paint \
|
||||
|
|
@ -194,6 +195,7 @@ mask_LDADD = $(LDADDS)
|
|||
mask_ctm_LDADD = $(LDADDS)
|
||||
mask_surface_ctm_LDADD = $(LDADDS)
|
||||
move_to_show_surface_LDADD = $(LDADDS)
|
||||
nil_surface_LDADD = $(LDADDS)
|
||||
operator_clear_LDADD = $(LDADDS)
|
||||
operator_source_LDADD = $(LDADDS)
|
||||
paint_LDADD = $(LDADDS)
|
||||
|
|
|
|||
BIN
test/nil-surface-ref.png
Normal file
BIN
test/nil-surface-ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 107 B |
73
test/nil-surface.c
Normal file
73
test/nil-surface.c
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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: Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
#include <cairo-ft.h>
|
||||
|
||||
/* Test case for: https://bugs.freedesktop.org/show_bug.cgi?id=4088 */
|
||||
|
||||
cairo_test_t test = {
|
||||
"nil-surface",
|
||||
"Test that nil surfaces do not make cairo crash.",
|
||||
1, 1
|
||||
};
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_t *cr2;
|
||||
|
||||
/* Make a custom context to not interfere with the one passed in. */
|
||||
cr2 = cairo_create (cairo_get_target (cr));
|
||||
|
||||
/* First, let's make a nil surface. */
|
||||
surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
|
||||
|
||||
/* Let the error propagate into a nil pattern. */
|
||||
pattern = cairo_pattern_create_for_surface (surface);
|
||||
|
||||
/* Then let it propagate into the cairo_t. */
|
||||
cairo_set_source (cr2, pattern);
|
||||
cairo_paint (cr2);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
/* Check that the error made it all that way. */
|
||||
if (cairo_status (cr2) != CAIRO_STATUS_FILE_NOT_FOUND)
|
||||
return CAIRO_TEST_FAILURE;
|
||||
|
||||
cairo_destroy (cr2);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return cairo_test (&test, draw);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue