diff options
author | Andrea Canciani <ranma42@gmail.com> | 2011-01-04 10:55:00 +0100 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2011-01-08 15:30:35 +0100 |
commit | 75d310f2c726b014fa7ca4e532f3714ca95e52a9 (patch) | |
tree | 7e03960503216f4a7b8344fc15bda64c9b62d455 | |
parent | 787e21bbaf35c4e7f342ee82de6ced88836e4187 (diff) |
wipwip/cs7
-rw-r--r-- | src/cairo-color-private.h | 108 | ||||
-rw-r--r-- | src/cairo-color.c | 382 | ||||
-rw-r--r-- | src/cairo-gstate.c | 15 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 30 | ||||
-rw-r--r-- | src/cairo-mesh-pattern-rasterizer.c | 35 | ||||
-rw-r--r-- | src/cairo-pattern.c | 192 | ||||
-rw-r--r-- | src/cairo-quartz-surface.c | 26 | ||||
-rw-r--r-- | src/cairo-surface-fallback-private.h | 11 | ||||
-rw-r--r-- | src/cairo-surface-fallback.c | 48 | ||||
-rw-r--r-- | src/cairo-surface.c | 53 | ||||
-rw-r--r-- | src/cairo-types-private.h | 8 | ||||
-rw-r--r-- | src/cairo.c | 34 | ||||
-rw-r--r-- | src/cairo.h | 3 | ||||
-rw-r--r-- | src/cairoint.h | 78 |
14 files changed, 380 insertions, 643 deletions
diff --git a/src/cairo-color-private.h b/src/cairo-color-private.h index a78db08dc..ddbe6b7e3 100644 --- a/src/cairo-color-private.h +++ b/src/cairo-color-private.h @@ -38,69 +38,57 @@ #include "cairoint.h" -#define CAIRO_COLOR_NIL_INIT \ - { \ - { \ - { \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0 \ - } \ - }, \ - NULL, \ - CAIRO_STATUS_NO_MEMORY, \ - CAIRO_REFERENCE_COUNT_INVALID \ - } +#define CAIRO_COMPONENTS_CLEAR_INIT \ + { \ + { \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0 \ + } \ + } \ -#define CAIRO_COLOR_CLEAR_INIT \ - { \ - { \ - { \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0 \ - } \ - }, \ - NULL, \ - CAIRO_STATUS_SUCCESS, \ - CAIRO_REFERENCE_COUNT_INVALID \ - } +#define CAIRO_COMPONENTS_BLACK_INIT \ + { \ + { \ + 1.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0 \ + } \ + } \ -#define CAIRO_COLOR_BLACK_INIT \ - { \ - { \ - { \ - 1.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0 \ - } \ - }, \ - (cairo_color_space_t *) &_cairo_color_space_device_gray, \ - CAIRO_STATUS_SUCCESS, \ - CAIRO_REFERENCE_COUNT_INVALID \ - } +#define CAIRO_COMPONENTS_WHITE_INIT \ + { \ + { \ + 1.0, 1.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0, \ + 0.0, 0.0, 0.0, 0.0 \ + } \ + } \ -#define CAIRO_COLOR_WHITE_INIT \ - { \ - { \ - { \ - 1.0, 1.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0, \ - 0.0, 0.0, 0.0, 0.0 \ - } \ - }, \ - (cairo_color_space_t *) &_cairo_color_space_device_gray, \ - CAIRO_STATUS_SUCCESS, \ - CAIRO_REFERENCE_COUNT_INVALID \ - } +static const cairo_color_components_t _cairo_components_clear = CAIRO_COMPONENTS_CLEAR_INIT; +static const cairo_color_components_t _cairo_components_black = CAIRO_COMPONENTS_BLACK_INIT; +static const cairo_color_components_t _cairo_components_white = CAIRO_COMPONENTS_WHITE_INIT; -slim_hidden_proto (cairo_color_reference); -slim_hidden_proto (cairo_color_destroy); -slim_hidden_proto (cairo_color_status); -slim_hidden_proto (cairo_color_get_color_space); +#define CAIRO_COMPONENTS_CLEAR (&_cairo_components_clear) +#define CAIRO_COMPONENTS_BLACK (&_cairo_components_black) +#define CAIRO_COMPONENTS_WHITE (&_cairo_components_white) + +/* Convert a double in [0.0, 1.0] to an integer in [0, 65535] + * The conversion is designed to divide the input range into 65536 + * equally-sized regions. This is achieved by multiplying by 65536 and + * then special-casing the result of an input value of 1.0 so that it + * maps to 65535 instead of 65536. + */ +static inline uint16_t +_cairo_color_double_to_short (double d) +{ + uint32_t i; + i = (uint32_t) (d * 65536); + i -= (i >> 16); + return i; +} #endif /* CAIRO_COLOR_PRIVATE_H */ diff --git a/src/cairo-color.c b/src/cairo-color.c index a67c8a328..6be79639a 100644 --- a/src/cairo-color.c +++ b/src/cairo-color.c @@ -38,391 +38,71 @@ #include "cairoint.h" #include "cairo-color-private.h" -#include "cairo-error-private.h" -#include "cairo-freed-pool-private.h" -#if HAS_FREED_POOL -static freed_pool_t freed_color_pool; -#endif - -cairo_private const cairo_color_t _cairo_color_nil = CAIRO_COLOR_NIL_INIT; -cairo_private const cairo_color_t _cairo_color_clear = CAIRO_COLOR_CLEAR_INIT; -cairo_private const cairo_color_t _cairo_color_black = CAIRO_COLOR_BLACK_INIT; -cairo_private const cairo_color_t _cairo_color_white = CAIRO_COLOR_WHITE_INIT; - - -/** - * _cairo_color_set_error: - * @color: a pattern - * @status: a status value indicating an error - * - * Atomically sets color->status to @status and calls _cairo_error; - * Does nothing if status is %CAIRO_STATUS_SUCCESS. - * - * All assignments of an error status to color->status should happen - * through _cairo_color_set_error(). Note that due to the nature of - * the atomic operation, it is not safe to call this function on the nil - * objects. - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - **/ -#if 0 -// NYU -cairo_status_t -_cairo_color_set_error (cairo_pattern_t *color, - cairo_status_t status) -{ - if (status == CAIRO_STATUS_SUCCESS) - return status; - - /* Don't overwrite an existing error. This preserves the first - * error, which is the most significant. */ - _cairo_status_set_error (&color->status, status); - - return _cairo_error (status); -} -#endif - -void -_cairo_color_init (cairo_color_t *color, cairo_color_space_t *color_space, - const double *components, double alpha) -{ - cairo_color_components_t *ccomp = &color->components; - int n_comp = cairo_color_space_get_number_of_components (color_space); - - CAIRO_REFERENCE_COUNT_INIT (&color->ref_count, 0); - color->status = cairo_color_space_status (color_space); - color->color_space = color_space; - ccomp->alpha = alpha; - memset (&ccomp->generic.c, 0, sizeof (ccomp->generic.c)); - memcpy (&ccomp->generic.c, components, n_comp * sizeof (double)); -} - -void -_cairo_color_init_rgba (cairo_color_t *color, - double red, double green, double blue, - double alpha) -{ - double components[3] = { red, green, blue }; - - _cairo_color_init (color, - (cairo_color_space_t *) &_cairo_color_space_device_rgb, - components, alpha); -} - -#if 0 -NYU -void -_cairo_color_init_static_copy (cairo_color_t *color, - const cairo_color_t *other) -{ - memcpy (color, other, sizeof (*color)); - CAIRO_REFERENCE_COUNT_INIT (&color->ref_count, 0); -} -#endif - - -/* Convert a double in [0.0, 1.0] to an integer in [0, 65535] - * The conversion is designed to divide the input range into 65536 - * equally-sized regions. This is achieved by multiplying by 65536 and - * then special-casing the result of an input value of 1.0 so that it - * maps to 65535 instead of 65536. - */ -static uint16_t -_cairo_color_double_to_short (double d) -{ - uint32_t i; - i = (uint32_t) (d * 65536); - i -= (i >> 16); - return i; -} - -/** - * cairo_color_create_alpha: - * @color_space: the color space - * @colors: the color components - * @alpha: alpha of the color - * - * Creates a new #cairo_color_t corresponding the given color - * components in the given color space with the given alpha. The - * alpha is in the range 0 to 1. If the values passed in are outside - * that range, they will be clamped. - * - * Return value: the newly created #cairo_color_t if successful, or - * an error color in case of no memory. The caller owns the - * returned object and should call cairo_color_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the color status will be set to an error. To inspect - * the status of a color use cairo_color_status(). - **/ -cairo_public cairo_color_t * -cairo_color_create_alpha (cairo_color_space_t *color_space, - const double *components, double alpha) -{ - cairo_color_t *color; - - color = _freed_pool_get (&freed_color_pool); - if (unlikely (color == NULL)) { - /* None cached, need to create a new color. */ - color = malloc (sizeof (cairo_color_t)); - if (unlikely (color == NULL)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_color_t *) &_cairo_color_nil; - } - } - - _cairo_color_init (color, cairo_color_space_reference (color_space), components, alpha); - - CAIRO_REFERENCE_COUNT_INIT (&color->ref_count, 1); - - return color; -} - -cairo_public cairo_color_t * -cairo_color_create (cairo_color_space_t *color_space, - const double *components) -{ - return cairo_color_create_alpha (color_space, components, 1.0); -} - -/** - * cairo_color_create_rgb: - * @red: red component of the color - * @green: green component of the color - * @blue: blue component of the color - * @alpha: alpha of the color - * - * Return value: the newly created #cairo_color_t if successful, or - * an error color in case of no memory. The caller owns the - * returned object and should call cairo_color_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the color status will be set to an error. To inspect - * the status of a color use cairo_color_status(). - **/ -cairo_public cairo_color_t * -cairo_color_create_rgba (double red, - double green, - double blue, - double alpha) -{ - double components[3] = { red, green, blue }; - - return cairo_color_create_alpha ((cairo_color_space_t *) &_cairo_color_space_device_rgb, components, alpha); -} - -/** - * cairo_color_create_rgb: - * @red: red component of the color - * @green: green component of the color - * @blue: blue component of the color - * - * Return value: the newly created #cairo_color_t if successful, or - * an error color in case of no memory. The caller owns the - * returned object and should call cairo_color_destroy() when - * finished with it. - * - * This function will always return a valid pointer, but if an error - * occurred the color status will be set to an error. To inspect - * the status of a color use cairo_color_status(). - **/ -cairo_color_t * -cairo_color_create_rgb (double red, - double green, - double blue) -{ - return cairo_color_create_rgba (red, green, blue, 1.0); -} - -/** - * cairo_color_reference: - * @color: a #cairo_color_t - * - * Increases the reference count on @color by one. This prevents - * @color from being destroyed until a matching call to - * cairo_color_destroy() is made. - * - * The number of references to a #cairo_color_t can be get using - * cairo_color_get_reference_count(). - * - * Return value: the referenced #cairo_color_t. - **/ -cairo_color_t * -cairo_color_reference (cairo_color_t *color) -{ - if (color == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&color->ref_count)) - return color; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&color->ref_count)); - - _cairo_reference_count_inc (&color->ref_count); - - return color; -} -slim_hidden_def (cairo_color_reference); - -/** - * cairo_color_destroy: - * @color: a #cairo_color_t - * - * Decreases the reference count on @color by one. If the result is - * zero, then @color and all associated resources are freed. See - * cairo_color_reference(). - **/ -void -cairo_color_destroy (cairo_color_t *color) -{ - if (color == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&color->ref_count)) - return; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&color->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&color->ref_count)) - return; - - cairo_color_space_destroy (color->color_space); - - /* maintain a small cache of freed colors */ - _freed_pool_put (&freed_color_pool, color); -} -slim_hidden_def (cairo_color_destroy); - -/** - * cairo_color_status: - * @color: a #cairo_color_t - * - * Checks whether an error has previously occurred for this - * color. - * - * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or - * %CAIRO_STATUS_COLOR_TYPE_MISMATCH. - **/ -cairo_status_t -cairo_color_status (const cairo_color_t *color) -{ - return color->status; -} -slim_hidden_def (cairo_color_status); - -cairo_color_space_t * -cairo_color_get_color_space (cairo_color_t *color) -{ - return cairo_color_space_reference (color->color_space); -} -slim_hidden_def (cairo_color_get_color_space); - -/** - * cairo_color_get_reference_count: - * @color_space: a #cairo_color_t - * - * Returns the current reference count of @color. - * - * Return value: the current reference count of @color. If the - * object is a nil object, 0 will be returned. - **/ -unsigned int -cairo_color_get_reference_count (cairo_color_t *color) -{ - if (color == NULL || - CAIRO_REFERENCE_COUNT_IS_INVALID (&color->ref_count)) - return 0; - - return CAIRO_REFERENCE_COUNT_GET_VALUE (&color->ref_count); -} - -cairo_public void -cairo_color_get_components (const cairo_color_t *color, - double *components) -{ - if (color != NULL) - memcpy (components, color->components.generic.c, - cairo_color_space_get_number_of_components (color->color_space) * sizeof (double)); -} - -cairo_public double -cairo_color_get_alpha (const cairo_color_t *color) +cairo_content_t +_cairo_color_get_content (cairo_color_space_t *color_space, + const cairo_color_components_t *components) { - if (color == NULL) - return 0.0; - - return color->components.alpha; + if (CAIRO_COMPONENTS_IS_OPAQUE (components)) + return CAIRO_CONTENT_COLOR; + else if (color_space == NULL) + return CAIRO_CONTENT_ALPHA; + else + return CAIRO_CONTENT_COLOR_ALPHA; } cairo_bool_t -_cairo_color_equal (const cairo_color_t *color_a, - const cairo_color_t *color_b) +_cairo_color_equal (const cairo_color_components_t *color_a, + const cairo_color_components_t *color_b) { if (color_a == color_b) return TRUE; - if (color_a->status != color_b->status || - color_a->components.alpha != color_b->components.alpha) + if (color_a->compalpha != color_b->compalpha) return FALSE; - if (CAIRO_COLOR_IS_CLEAR (color_a)) + if (CAIRO_COMPONENTS_IS_CLEAR (color_a)) return TRUE; - return _cairo_color_space_equal (color_a->color_space, color_b->color_space) && - !memcmp (color_a->components.generic.c, - color_b->components.generic.c, - sizeof (color_a->components.generic.c)); -} - -cairo_content_t -_cairo_color_get_content (const cairo_color_t *color) -{ - if (CAIRO_COLOR_IS_OPAQUE (color)) - return CAIRO_CONTENT_COLOR; - else if (color->color_space == NULL) - return CAIRO_CONTENT_ALPHA; - else - return CAIRO_CONTENT_COLOR_ALPHA; + return ! memcmp (color_a->generic.c, color_b->generic.c, sizeof (color_a->generic.c)); } void -_cairo_color_to_pixman_color (const cairo_color_t *color, - pixman_color_t *out) +_cairo_color_to_pixman_color (const cairo_color_space_t *color_space, + const cairo_color_components_t *components, + pixman_color_t *out) { - const cairo_color_components_t *in = &color->components; - - out->alpha = _cairo_color_double_to_short (in->alpha); + out->alpha = _cairo_color_double_to_short (components->compalpha); - if (color->color_space == NULL) { + if (color_space == NULL) { out->red = out->green = out->blue = 0; - } else if (color->color_space == &_cairo_color_space_device_gray) { - out->red = _cairo_color_double_to_short (in->alpha * in->comp[1]); + } else if (color_space == &_cairo_color_space_device_gray) { + out->red = _cairo_color_double_to_short (components->compalpha * components->comp[1]); out->green = out->blue = out->red; - } else if (color->color_space == &_cairo_color_space_device_rgb) { - out->red = _cairo_color_double_to_short (in->alpha * in->argb.red); - out->green = _cairo_color_double_to_short (in->alpha * in->argb.green); - out->blue = _cairo_color_double_to_short (in->alpha * in->argb.blue); + } else if (color_space == &_cairo_color_space_device_rgb) { + out->red = _cairo_color_double_to_short (components->compalpha * components->argb.red); + out->green = _cairo_color_double_to_short (components->compalpha * components->argb.green); + out->blue = _cairo_color_double_to_short (components->compalpha * components->argb.blue); } else ASSERT_NOT_REACHED; } void _cairo_stop_to_pixman_stop (const cairo_color_space_t *color_space, - const cairo_color_components_t *color_comp, + const cairo_color_components_t *components, pixman_color_t *out_stop) { - out_stop->alpha = _cairo_color_double_to_short (color_comp->alpha); + out_stop->alpha = _cairo_color_double_to_short (components->compalpha); if (color_space == NULL) { out_stop->red = out_stop->green = out_stop->blue = 0; } else if (color_space == &_cairo_color_space_device_gray) { - out_stop->red = _cairo_color_double_to_short (color_comp->comp[1]); + out_stop->red = _cairo_color_double_to_short (components->comp[1]); out_stop->green = out_stop->blue = out_stop->red; } else if (color_space == &_cairo_color_space_device_rgb) { - out_stop->red = _cairo_color_double_to_short (color_comp->argb.red); - out_stop->green = _cairo_color_double_to_short (color_comp->argb.green); - out_stop->blue = _cairo_color_double_to_short (color_comp->argb.blue); + out_stop->red = _cairo_color_double_to_short (components->argb.red); + out_stop->green = _cairo_color_double_to_short (components->argb.green); + out_stop->blue = _cairo_color_double_to_short (components->argb.blue); } else ASSERT_NOT_REACHED; } diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index f1308f83d..0b7bec0fb 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -38,6 +38,7 @@ #include "cairoint.h" #include "cairo-clip-private.h" +#include "cairo-color-private.h" #include "cairo-error-private.h" #include "cairo-gstate-private.h" @@ -435,7 +436,7 @@ _cairo_gstate_get_source (cairo_gstate_t *gstate) { if (gstate->source == &_cairo_pattern_black.base) { /* do not expose the static object to the user */ - gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK); + gstate->source = _cairo_pattern_create_solid (NULL, CAIRO_COMPONENTS_BLACK); } return gstate->source; @@ -879,19 +880,21 @@ _cairo_gstate_copy_pattern (cairo_pattern_t *pattern, if (_cairo_pattern_is_clear (original)) { _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern, - CAIRO_COLOR_CLEAR); + NULL, + CAIRO_COMPONENTS_CLEAR); return; } if (original->type == CAIRO_PATTERN_TYPE_LINEAR || original->type == CAIRO_PATTERN_TYPE_RADIAL) { - double components[MAX_COLOR_COMPONENTS + 1]; - if (_cairo_gradient_pattern_is_solid ((cairo_gradient_pattern_t *) original, - NULL, components+1, components)) + cairo_color_components_t components; + const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *) original; + + if (_cairo_gradient_pattern_is_solid (gradient, NULL, &components)) { _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern, - components+1, components[0]); + gradient->color_space, &components); return; } } diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 6c89d8e71..e134ca013 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -978,8 +978,8 @@ hars_petruska_f54_1_random (void) } static struct { - cairo_color_space_t color_space; - cairo_color_components_t color; + cairo_color_space_t *color_space; + cairo_color_components_t components; pixman_image_t *image; } cache[16]; static int n_cached; @@ -1016,7 +1016,7 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern) int i; #if HAS_ATOMIC_OPS - if (CAIRO_COLOR_IS_CLEAR (&pattern->color)) + if (CAIRO_COMPONENTS_IS_CLEAR (&pattern->components)) return _pixman_transparent_image (); /* TODO @@ -1030,14 +1030,16 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern) CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex); for (i = 0; i < n_cached; i++) { - if (_cairo_color_equal (&cache[i].color, &pattern->color)) { + if (cache[i].color_space == pattern->color_space && + _cairo_color_equal (&cache[i].components, &pattern->components)) + { image = pixman_image_ref (cache[i].image); goto UNLOCK; } } // TODO - _cairo_color_to_pixman_color (&pattern->color, &color); + _cairo_color_to_pixman_color (pattern->color_space, &pattern->components, &color); image = pixman_image_create_solid_fill (&color); if (image == NULL) @@ -1048,9 +1050,11 @@ _pixman_image_for_solid (const cairo_solid_pattern_t *pattern) } else { i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache); pixman_image_unref (cache[i].image); + cairo_color_space_destroy (pattern->color_space); } cache[i].image = pixman_image_ref (image); - cache[i].color = pattern->color; + cache[i].components = pattern->components; + cache[i].color_space = cairo_color_space_reference (pattern->color_space); UNLOCK: CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex); @@ -4091,12 +4095,12 @@ _cairo_image_surface_composite (cairo_operator_t op, } static cairo_int_status_t -_cairo_image_surface_fill_rectangles (void *abstract_surface, - cairo_operator_t op, - const cairo_color_components_t *color, - cairo_color_space_t *color_space, - cairo_rectangle_int_t *rects, - int num_rects) +_cairo_image_surface_fill_rectangles (void *abstract_surface, + cairo_operator_t op, + cairo_color_space_t *color_space, + const cairo_color_components_t *color, + cairo_rectangle_int_t *rects, + int num_rects) { cairo_image_surface_t *surface = abstract_surface; @@ -4111,7 +4115,7 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface, return _cairo_error (CAIRO_STATUS_NO_MEMORY); // TODO - _cairo_color_to_pixman_color (color, &pixman_color); + _cairo_color_to_pixman_color (color_space, color, &pixman_color); if (num_rects > ARRAY_LENGTH (stack_boxes)) { pixman_boxes = _cairo_malloc_ab (num_rects, sizeof (pixman_box32_t)); diff --git a/src/cairo-mesh-pattern-rasterizer.c b/src/cairo-mesh-pattern-rasterizer.c index 21fdeff3d..43b27f221 100644 --- a/src/cairo-mesh-pattern-rasterizer.c +++ b/src/cairo-mesh-pattern-rasterizer.c @@ -35,6 +35,7 @@ */ #include "cairoint.h" +#include "cairo-color-private.h" /* * Rasterizer for mesh patterns. @@ -892,7 +893,7 @@ _cairo_mesh_pattern_rasterize (const cairo_mesh_pattern_t *mesh, unsigned int i, j, k, n; cairo_status_t status; const cairo_mesh_patch_t *patch; - cairo_color_components_t *c; + const cairo_color_components_t *c; assert (mesh->base.status == CAIRO_STATUS_SUCCESS); assert (mesh->current_patch == NULL); @@ -914,28 +915,28 @@ _cairo_mesh_pattern_rasterize (const cairo_mesh_pattern_t *mesh, } c = &patch->colors[0]; - colors[0][0] = c->red; - colors[0][1] = c->green; - colors[0][2] = c->blue; - colors[0][3] = c->alpha; + colors[0][0] = c->argb.red; + colors[0][1] = c->argb.green; + colors[0][2] = c->argb.blue; + colors[0][3] = c->argb.alpha; c = &patch->colors[3]; - colors[1][0] = c->red; - colors[1][1] = c->green; - colors[1][2] = c->blue; - colors[1][3] = c->alpha; + colors[1][0] = c->argb.red; + colors[1][1] = c->argb.green; + colors[1][2] = c->argb.blue; + colors[1][3] = c->argb.alpha; c = &patch->colors[1]; - colors[2][0] = c->red; - colors[2][1] = c->green; - colors[2][2] = c->blue; - colors[2][3] = c->alpha; + colors[2][0] = c->argb.red; + colors[2][1] = c->argb.green; + colors[2][2] = c->argb.blue; + colors[2][3] = c->argb.alpha; c = &patch->colors[2]; - colors[3][0] = c->red; - colors[3][1] = c->green; - colors[3][2] = c->blue; - colors[3][3] = c->alpha; + colors[3][0] = c->argb.red; + colors[3][1] = c->argb.green; + colors[3][2] = c->argb.blue; + colors[3][3] = c->argb.alpha; draw_bezier_patch (data, width, height, stride, nodes, colors); patch++; diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 483446902..d3b32c69a 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -87,7 +87,8 @@ const cairo_solid_pattern_t _cairo_pattern_black = { { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT}, /* extend */ - CAIRO_COLOR_BLACK_INIT, /* color */ + CAIRO_COMPONENTS_BLACK_INIT, /* components */ + CAIRO_COLOR_SPACE_DEVICE_GRAY /* color_space */ }; const cairo_solid_pattern_t _cairo_pattern_clear = { @@ -98,7 +99,8 @@ const cairo_solid_pattern_t _cairo_pattern_clear = { { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT}, /* extend */ - CAIRO_COLOR_CLEAR_INIT, /* color */ + CAIRO_COMPONENTS_CLEAR_INIT, /* components */ + NULL /* color_space */ }; const cairo_solid_pattern_t _cairo_pattern_white = { @@ -109,7 +111,8 @@ const cairo_solid_pattern_t _cairo_pattern_white = { { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_GRADIENT_DEFAULT}, /* extend */ - CAIRO_COLOR_WHITE_INIT, /* color */ + CAIRO_COMPONENTS_WHITE_INIT, /* components */ + CAIRO_COLOR_SPACE_DEVICE_GRAY /* color_space */ }; /** @@ -465,11 +468,13 @@ _cairo_pattern_create_copy (cairo_pattern_t **pattern_out, void -_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, - const cairo_color_t *color) +_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, + cairo_color_space_t *color_space, + const cairo_color_components_t *components) { _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID); - pattern->color = *color; + pattern->color_space = cairo_color_space_reference (color_space); + pattern->components = *components; } void @@ -528,7 +533,8 @@ _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern, } cairo_pattern_t * -_cairo_pattern_create_solid (const cairo_color_t *color) +_cairo_pattern_create_solid (cairo_color_space_t *color_space, + const cairo_color_components_t *components) { cairo_solid_pattern_t *pattern; @@ -543,7 +549,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color) } } - _cairo_pattern_init_solid (pattern, color); + _cairo_pattern_init_solid (pattern, color_space, components); CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1); return &pattern->base; @@ -559,7 +565,7 @@ _cairo_pattern_create_in_error (cairo_status_t status) CAIRO_MUTEX_INITIALIZE (); - pattern = _cairo_pattern_create_solid (CAIRO_COLOR_CLEAR); + pattern = _cairo_pattern_create_solid (NULL, CAIRO_COMPONENTS_CLEAR); if (pattern->status == CAIRO_STATUS_SUCCESS) status = _cairo_pattern_set_error (pattern, status); @@ -618,18 +624,16 @@ cairo_pattern_t * cairo_pattern_create_rgba (double red, double green, double blue, double alpha) { - cairo_color_t color; + cairo_color_components_t components; - red = _cairo_restrict_value (red, 0.0, 1.0); - green = _cairo_restrict_value (green, 0.0, 1.0); - blue = _cairo_restrict_value (blue, 0.0, 1.0); - alpha = _cairo_restrict_value (alpha, 0.0, 1.0); - - _cairo_color_init_rgba (&color, red, green, blue, alpha); + components.argb.red = _cairo_restrict_value (red, 0.0, 1.0); + components.argb.green = _cairo_restrict_value (green, 0.0, 1.0); + components.argb.blue = _cairo_restrict_value (blue, 0.0, 1.0); + components.argb.alpha = _cairo_restrict_value (alpha, 0.0, 1.0); CAIRO_MUTEX_INITIALIZE (); - return _cairo_pattern_create_solid (&color); + return _cairo_pattern_create_solid (CAIRO_COLOR_SPACE_DEVICE_RGB, &components); } slim_hidden_def (cairo_pattern_create_rgba); @@ -1296,7 +1300,7 @@ cairo_pattern_mesh_end_patch (cairo_pattern_t *pattern) for (i = 0; i < 4; i++) { if (! mesh->has_color[i]) - current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT; + current_patch->colors[i] = *CAIRO_COMPONENTS_CLEAR; } mesh->current_patch = NULL; @@ -1618,21 +1622,16 @@ _cairo_pattern_mesh_set_corner_color (cairo_mesh_pattern_t *mesh, double red, double green, double blue, double alpha) { - cairo_color_t *color; + cairo_color_components_t *components; assert (mesh->current_patch); assert (corner_num <= 3); - color = &mesh->current_patch->colors[corner_num]; - color->red = red; - color->green = green; - color->blue = blue; - color->alpha = alpha; - - color->red_short = _cairo_color_double_to_short (red); - color->green_short = _cairo_color_double_to_short (green); - color->blue_short = _cairo_color_double_to_short (blue); - color->alpha_short = _cairo_color_double_to_short (alpha); + components = &mesh->current_patch->colors[corner_num]; + components->argb.red = red; + components->argb.green = green; + components->argb.blue = blue; + components->argb.alpha = alpha; mesh->has_color[corner_num] = TRUE; } @@ -1763,7 +1762,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, } stops[i].offset = offset; - stops[i].components.alpha = alpha; + stops[i].components.compalpha = alpha; memset (&stops[i].components.generic.c, 0, sizeof (stops[i].components.generic.c)); memcpy (&stops[i].components.generic.c, components, cairo_color_space_get_number_of_components (pattern->color_space) * sizeof (double)); @@ -2122,13 +2121,10 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat return _cairo_error (CAIRO_STATUS_NO_MEMORY); } + /* TODO */ for (i = 0; i < pattern->n_stops; i++) { pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset); - /* TODO - pixman_stops[i].color.red = pattern->stops[i].color.red_short; - pixman_stops[i].color.green = pattern->stops[i].color.green_short; - pixman_stops[i].color.blue = pattern->stops[i].color.blue_short; - pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short; + _cairo_stop_to_pixman_stop (pattern->color_space, &pattern->stops[i].components, &pixman_stops[i].color); } _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes); @@ -2335,8 +2331,8 @@ _cairo_pattern_acquire_surface_for_mesh (const cairo_mesh_pattern_t *pattern, #define MAX_SURFACE_CACHE_SIZE 16 static struct { struct _cairo_pattern_solid_surface_cache{ - cairo_color_t color; - cairo_surface_t *surface; + cairo_color_components_t components; + cairo_surface_t *surface; } cache[MAX_SURFACE_CACHE_SIZE]; int size; } solid_surface_cache; @@ -2347,7 +2343,12 @@ _cairo_pattern_solid_surface_matches ( const cairo_solid_pattern_t *pattern, cairo_surface_t *dst) { - if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (&pattern->color)) + /* TODO + if (cache->surface->color_space != pattern->color_space) + return FALSE; + */ + + if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (pattern->color_space, &pattern->components)) return FALSE; if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1) @@ -2365,7 +2366,12 @@ _cairo_pattern_solid_surface_matches_color ( const cairo_solid_pattern_t *pattern, cairo_surface_t *dst) { - if (! _cairo_color_equal (&cache->color, &pattern->color)) + /* TODO + if (cache->surface->color_space != pattern->color_space) + return FALSE; + */ + + if (! _cairo_color_equal (&cache->components, &pattern->components)) return FALSE; return _cairo_pattern_solid_surface_matches (cache, pattern, dst); @@ -2456,8 +2462,8 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt solid_surface_cache.size++; to_destroy = solid_surface_cache.cache[i].surface; - solid_surface_cache.cache[i].surface = surface; - solid_surface_cache.cache[i].color = pattern->color; + solid_surface_cache.cache[i].surface = surface; + solid_surface_cache.cache[i].components = pattern->components; DONE: *out = cairo_surface_reference (solid_surface_cache.cache[i].surface); @@ -3148,20 +3154,16 @@ _gradient_is_clear (const cairo_gradient_pattern_t *gradient, static void _gradient_color_average (const cairo_gradient_pattern_t *gradient, - cairo_color_t *color) + cairo_color_components_t *components) { double delta0, delta1; - cairo_color_components_t c; unsigned int i, j, n, start = 1, end; assert (gradient->n_stops > 0); assert (gradient->base.extend != CAIRO_EXTEND_NONE); if (gradient->n_stops == 1) { - _cairo_color_init (color, - gradient->color_space, - gradient->stops[0].components.generic.c, - gradient->stops[0].components.generic.alpha); + *components = gradient->stops[0].components; return; } @@ -3225,12 +3227,12 @@ _gradient_color_average (const cairo_gradient_pattern_t *gradient, case CAIRO_EXTEND_NONE: default: ASSERT_NOT_REACHED; - _cairo_color_init_rgba (color, 0, 0, 0, 0); + *components = *CAIRO_COMPONENTS_CLEAR; return; } for (j = 0; j <= n; ++j) - c.comp[j] = delta0 * gradient->stops[0].components.comp[j]; + components->comp[j] = delta0 * gradient->stops[0].components.comp[j]; for (i = start; i < end; ++i) { /* Inner stops weight is the same as the area of the triangle they influence @@ -3240,16 +3242,14 @@ _gradient_color_average (const cairo_gradient_pattern_t *gradient, */ double delta = gradient->stops[i+1].offset - gradient->stops[i-1].offset; for (j = 0; j <= n; ++j) - c.comp[j] += delta * gradient->stops[i].components.comp[j]; + components->comp[j] += delta * gradient->stops[i].components.comp[j]; } for (j = 0; j <= n; ++j) - c.comp[j] += delta1 * gradient->stops[end].components.comp[j]; + components->comp[j] += delta1 * gradient->stops[end].components.comp[j]; for (j = 0; j <= n; ++j) - c.comp[j] *= 0.5; - - _cairo_color_init (color, gradient->color_space, c.generic.c, c.generic.alpha); + components->comp[j] *= 0.5; } /** @@ -3272,7 +3272,7 @@ _cairo_pattern_alpha_range (const cairo_pattern_t *pattern, switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: { const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern; - alpha_min = alpha_max = solid->color.components.alpha; + alpha_min = alpha_max = solid->components.compalpha; break; } @@ -3283,12 +3283,12 @@ _cairo_pattern_alpha_range (const cairo_pattern_t *pattern, assert (gradient->n_stops >= 1); - alpha_min = alpha_max = gradient->stops[0].components.alpha; + alpha_min = alpha_max = gradient->stops[0].components.compalpha; for (i = 1; i < gradient->n_stops; i++) { - if (alpha_min > gradient->stops[i].components.alpha) - alpha_min = gradient->stops[i].components.alpha; - else if (alpha_max < gradient->stops[i].components.alpha) - alpha_max = gradient->stops[i].components.alpha; + if (alpha_min > gradient->stops[i].components.compalpha) + alpha_min = gradient->stops[i].components.compalpha; + else if (alpha_max < gradient->stops[i].components.compalpha) + alpha_max = gradient->stops[i].components.compalpha; } break; @@ -3301,13 +3301,13 @@ _cairo_pattern_alpha_range (const cairo_pattern_t *pattern, assert (n >= 1); - alpha_min = alpha_max = patch[0].colors[0].alpha; + alpha_min = alpha_max = patch[0].colors[0].compalpha; for (i = 0; i < n; i++) { for (j = 0; j < 4; j++) { - if (patch[i].colors[j].alpha < alpha_min) - alpha_min = patch[i].colors[j].alpha; - else if (patch[i].colors[j].alpha > alpha_max) - alpha_max = patch[i].colors[j].alpha; + if (patch[i].colors[j].compalpha < alpha_min) + alpha_min = patch[i].colors[j].compalpha; + else if (patch[i].colors[j].compalpha > alpha_max) + alpha_max = patch[i].colors[j].compalpha; } } @@ -3401,8 +3401,8 @@ _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh, **/ cairo_bool_t _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, - const cairo_rectangle_int_t *extents, - cairo_color_t *color) + const cairo_rectangle_int_t *extents, + cairo_color_components_t *components) { unsigned int i; @@ -3413,7 +3413,7 @@ _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) { cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient; if (_linear_pattern_is_degenerate (linear)) { - _gradient_color_average (gradient, color); + _gradient_color_average (gradient, components); return TRUE; } @@ -3444,10 +3444,7 @@ _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, if (memcmp (&gradient->stops[0].components, &gradient->stops[i].components, sizeof (gradient->stops[0].components))) return FALSE; - _cairo_color_init (color, - gradient->color_space, - gradient->stops[0].components.generic.c, - gradient->stops[0].components.generic.alpha); + *components = gradient->stops[0].components; return TRUE; } @@ -3489,7 +3486,7 @@ _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern) solid = (cairo_solid_pattern_t *) pattern; - return CAIRO_COLOR_IS_OPAQUE (&solid->color); + return CAIRO_COMPONENTS_IS_OPAQUE (&solid->components); } static cairo_bool_t @@ -3625,7 +3622,7 @@ _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern) pattern = (cairo_pattern_union_t *) abstract_pattern; switch (pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: - return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color); + return CAIRO_COMPONENTS_IS_CLEAR (&pattern->solid.components); case CAIRO_PATTERN_TYPE_SURFACE: return _surface_is_clear (&pattern->surface); case CAIRO_PATTERN_TYPE_LINEAR: @@ -3818,7 +3815,8 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat cairo_surface_destroy (surface); surface = _cairo_surface_create_similar_solid (dst, dst->content, w, h, - CAIRO_COLOR_CLEAR, + NULL, + CAIRO_COMPONENTS_CLEAR, FALSE); if (surface == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -4094,17 +4092,15 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src, ! mask->has_component_alpha && mask->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_color_t combined; + cairo_color_components_t combined; cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask; - _cairo_color_init (&combined, - src_solid->color.color_space, - src_solid->color.components.generic.c, - src_solid->color.components.alpha * mask_solid->color.components.alpha); + combined = src_solid->components; + combined.compalpha *= mask_solid->components.compalpha; + + _cairo_pattern_init_solid (&src_tmp.solid, src_solid->color_space, &combined); - _cairo_pattern_init_solid (&src_tmp.solid, &combined); - src = &src_tmp.base; mask = NULL; } @@ -4336,7 +4332,8 @@ static unsigned long _cairo_solid_pattern_hash (unsigned long hash, const cairo_solid_pattern_t *solid) { - hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color)); + /* TODO: colorspace */ + hash = _cairo_hash_bytes (hash, &solid->components, sizeof (solid->components)); return hash; } @@ -4450,7 +4447,10 @@ static cairo_bool_t _cairo_solid_pattern_equal (const cairo_solid_pattern_t *a, const cairo_solid_pattern_t *b) { - return _cairo_color_equal (&a->color, &b->color); + if (a->color_space != b->color_space) + return FALSE; + + return _cairo_color_equal (&a->components, &b->components); } static cairo_bool_t @@ -4462,6 +4462,9 @@ _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a, if (a->n_stops != b->n_stops) return FALSE; + if (a->color_space != b->color_space) + return FALSE; + for (n = 0; n < a->n_stops; n++) { if (a->stops[n].offset != b->stops[n].offset) return FALSE; @@ -4623,17 +4626,17 @@ cairo_pattern_get_rgba (cairo_pattern_t *pattern, if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); - if (solid->color.color_space != &_cairo_color_space_device_rgb) + if (solid->color_space != &_cairo_color_space_device_rgb) return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); // COLORSPACE_MISMATCH? if (red) - *red = solid->color.components.argb.red; + *red = solid->components.argb.red; if (green) - *green = solid->color.components.argb.green; + *green = solid->components.argb.green; if (blue) - *blue = solid->color.components.argb.blue; + *blue = solid->components.argb.blue; if (alpha) - *alpha = solid->color.components.argb.alpha; + *alpha = solid->components.argb.alpha; return CAIRO_STATUS_SUCCESS; } @@ -5027,16 +5030,19 @@ cairo_pattern_mesh_get_corner_color_rgba (cairo_pattern_t *pattern, if (unlikely (patch_num >= patch_count)) return _cairo_error (CAIRO_STATUS_INVALID_INDEX); + if (mesh->color_space != &_cairo_color_space_device_rgb) + return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); // COLORSPACE_MISMATCH? + patch = _cairo_array_index_const (&mesh->patches, patch_num); if (red) - *red = patch->colors[corner_num].red; + *red = patch->colors[corner_num].argb.red; if (green) - *green = patch->colors[corner_num].green; + *green = patch->colors[corner_num].argb.green; if (blue) - *blue = patch->colors[corner_num].blue; + *blue = patch->colors[corner_num].argb.blue; if (alpha) - *alpha = patch->colors[corner_num].alpha; + *alpha = patch->colors[corner_num].argb.alpha; return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c index 0c510fcfc..eb446bcb5 100644 --- a/src/cairo-quartz-surface.c +++ b/src/cairo-quartz-surface.c @@ -1224,18 +1224,20 @@ _cairo_quartz_setup_source (cairo_quartz_drawing_state_t *state, if (source->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; + cairo_quartz_float_t components[MAX_COLOR_COMPONENTS]; + CGColorRef color; + int i; - /* TODO */ - CGContextSetRGBStrokeColor (surface->cgContext, - solid->color.components.argb.red, - solid->color.components.argb.green, - solid->color.components.argb.blue, - solid->color.components.argb.alpha); - CGContextSetRGBFillColor (surface->cgContext, - solid->color.components.argb.red, - solid->color.components.argb.green, - solid->color.components.argb.blue, - solid->color.components.argb.alpha); + for (i = 0; i < 3; i++) + components[i] = solid->components.generic.c[i]; + components[i] = solid->components.generic.alpha; + + color = CGColorCreate (CGColorSpaceCreateDeviceRGB (), components); + + CGContextSetFillColorWithColor (surface->cgContext, color); + CGContextSetStrokeColorWithColor (surface->cgContext, color); + + CGColorRelease (color); state->action = DO_DIRECT; return CAIRO_STATUS_SUCCESS; @@ -2395,7 +2397,7 @@ _cairo_quartz_surface_mask_cg (cairo_quartz_surface_t *surface, /* This is easy; we just need to paint with the alpha. */ cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; - CGContextSetAlpha (surface->cgContext, solid_mask->color.components.alpha); + CGContextSetAlpha (surface->cgContext, solid_mask->components.compalpha); rv = _cairo_quartz_surface_paint_cg (surface, op, source, clip); CGContextSetAlpha (surface->cgContext, 1.0); diff --git a/src/cairo-surface-fallback-private.h b/src/cairo-surface-fallback-private.h index e993de62e..b363f8ba8 100644 --- a/src/cairo-surface-fallback-private.h +++ b/src/cairo-surface-fallback-private.h @@ -104,11 +104,12 @@ _cairo_surface_fallback_composite (cairo_operator_t op, cairo_region_t *clip_region); cairo_private cairo_status_t -_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects); +_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, + cairo_operator_t op, + cairo_color_space_t *color_space, + const cairo_color_components_t *components, + cairo_rectangle_int_t *rects, + int num_rects); cairo_private cairo_status_t _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op, diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 2de9a9cb0..8083712b9 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -42,6 +42,7 @@ #include "cairo-boxes-private.h" #include "cairo-clip-private.h" +#include "cairo-color-private.h" #include "cairo-composite-rectangles-private.h" #include "cairo-error-private.h" #include "cairo-region-private.h" @@ -149,7 +150,8 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern, CAIRO_CONTENT_ALPHA, extents->width, extents->height, - CAIRO_COLOR_CLEAR, + NULL, + CAIRO_COMPONENTS_CLEAR, TRUE); if (unlikely (mask->status)) return mask->status; @@ -606,15 +608,21 @@ _clip_and_composite_region (const cairo_pattern_t *src, if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) && clip == NULL) { - const cairo_color_t *color; + cairo_color_space_t *color_space; + const cairo_color_components_t *components; - if (op == CAIRO_OPERATOR_CLEAR) - color = CAIRO_COLOR_CLEAR; - else - color = &((cairo_solid_pattern_t *)src)->color; + if (op == CAIRO_OPERATOR_CLEAR) { + color_space = NULL; + components = CAIRO_COMPONENTS_CLEAR; + } else { + const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) src; + + color_space = solid->color_space; + components = &solid->components; + } /* Solid rectangles special case */ - status = _cairo_surface_fill_region (dst, op, color, trap_region); + status = _cairo_surface_fill_region (dst, op, color_space, components, trap_region); } else { /* For a simple rectangle, we can just use composite(), for more * rectangles, we have to set a clip region. The cost of rasterizing @@ -639,7 +647,8 @@ _clip_and_composite_region (const cairo_pattern_t *src, if (status == CAIRO_STATUS_SUCCESS) { status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, - CAIRO_COLOR_CLEAR, + NULL, + CAIRO_COMPONENTS_CLEAR, &clear_region); } _cairo_region_fini (&clear_region); @@ -656,7 +665,8 @@ _fill_rectangles (cairo_surface_t *dst, cairo_traps_t *traps, cairo_clip_t *clip) { - const cairo_color_t *color; + cairo_color_space_t *color_space; + const cairo_color_components_t *components; cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)]; cairo_rectangle_int_t *rects = stack_rects; cairo_status_t status; @@ -716,12 +726,17 @@ _fill_rectangles (cairo_surface_t *dst, rects[i].height = y2 - y1; } - if (op == CAIRO_OPERATOR_CLEAR) - color = CAIRO_COLOR_CLEAR; - else - color = &((cairo_solid_pattern_t *)src)->color; + if (op == CAIRO_OPERATOR_CLEAR) { + color_space = NULL; + components = CAIRO_COMPONENTS_CLEAR; + } else { + const cairo_solid_pattern_t *solid = (const cairo_solid_pattern_t *) src; + + color_space = solid->color_space; + components = &solid->components; + } - status = _cairo_surface_fill_rectangles (dst, op, color, rects, i); + status = _cairo_surface_fill_rectangles (dst, op, color_space, components, rects, i); if (rects != stack_rects) free (rects); @@ -1448,7 +1463,8 @@ _cairo_surface_fallback_composite (cairo_operator_t op, cairo_status_t _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, cairo_operator_t op, - const cairo_color_t *color, + cairo_color_space_t *color_space, + const cairo_color_components_t *components, cairo_rectangle_int_t *rects, int num_rects) { @@ -1507,7 +1523,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface, } status = _cairo_surface_fill_rectangles (&state.image->base, - op, color, + op, color_space, components, rects, num_rects); free (offset_rects); diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 03bb72280..896a158d4 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -40,6 +40,7 @@ #include "cairo-surface-fallback-private.h" #include "cairo-clip-private.h" +#include "cairo-color-private.h" #include "cairo-device-private.h" #include "cairo-error-private.h" #include "cairo-recording-surface-private.h" @@ -510,7 +511,8 @@ cairo_surface_create_similar (cairo_surface_t *other, return _cairo_surface_create_similar_solid (other, content, width, height, - CAIRO_COLOR_CLEAR, + NULL, + CAIRO_COMPONENTS_CLEAR, TRUE); } @@ -519,7 +521,8 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other, cairo_content_t content, int width, int height, - const cairo_color_t *color, + cairo_color_space_t *color_space, + const cairo_color_components_t *components, cairo_bool_t allow_fallback) { cairo_status_t status; @@ -534,9 +537,9 @@ _cairo_surface_create_similar_solid (cairo_surface_t *other, if (surface == NULL || surface->status) return surface; - _cairo_pattern_init_solid (&pattern, color); + _cairo_pattern_init_solid (&pattern, color_space, components); status = _cairo_surface_paint (surface, - color == CAIRO_COLOR_CLEAR ? + components == CAIRO_COMPONENTS_CLEAR ? CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE, &pattern.base, NULL); if (unlikely (status)) { @@ -551,6 +554,8 @@ cairo_surface_t * _cairo_surface_create_solid_pattern_surface (cairo_surface_t *other, const cairo_solid_pattern_t *solid_pattern) { + cairo_content_t content; + if (other->backend->create_solid_pattern_surface != NULL) { cairo_surface_t *surface; @@ -560,10 +565,14 @@ _cairo_surface_create_solid_pattern_surface (cairo_surface_t *other, return surface; } + content = _cairo_color_get_content (solid_pattern->color_space, + &solid_pattern->components); + return _cairo_surface_create_similar_solid (other, - _cairo_color_get_content (&solid_pattern->color), + content, 1, 1, - &solid_pattern->color, + solid_pattern->color_space, + &solid_pattern->components, FALSE); } @@ -1626,7 +1635,8 @@ _cairo_recording_surface_clone_similar (cairo_surface_t *surface, similar = _cairo_surface_create_similar_solid (surface, src->content, width, height, - CAIRO_COLOR_CLEAR, + NULL, + CAIRO_COMPONENTS_CLEAR, FALSE); if (similar == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1879,7 +1889,8 @@ _cairo_surface_composite (cairo_operator_t op, cairo_status_t _cairo_surface_fill_region (cairo_surface_t *surface, cairo_operator_t op, - const cairo_color_t *color, + cairo_color_space_t *color_space, + const cairo_color_components_t *components, cairo_region_t *region) { int num_rects; @@ -1898,12 +1909,13 @@ _cairo_surface_fill_region (cairo_surface_t *surface, return CAIRO_STATUS_SUCCESS; /* catch a common reduction of _cairo_clip_combine_with_surface() - TODO: A8+opaque*/ + TODO: A8+opaque if (op == CAIRO_OPERATOR_IN && _cairo_color_equal (color, CAIRO_COLOR_WHITE)) { return CAIRO_STATUS_SUCCESS; } + */ if (num_rects > ARRAY_LENGTH (stack_rects)) { rects = _cairo_malloc_ab (num_rects, @@ -1918,7 +1930,8 @@ _cairo_surface_fill_region (cairo_surface_t *surface, cairo_region_get_rectangle (region, i, &rects[i]); status = _cairo_surface_fill_rectangles (surface, - op, color, rects, num_rects); + op, color_space, components, + rects, num_rects); if (rects != stack_rects) free (rects); @@ -1943,11 +1956,12 @@ _cairo_surface_fill_region (cairo_surface_t *surface, * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred **/ cairo_status_t -_cairo_surface_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) +_cairo_surface_fill_rectangles (cairo_surface_t *surface, + cairo_operator_t op, + cairo_color_space_t *color_space, + const cairo_color_components_t *components, + cairo_rectangle_int_t *rects, + int num_rects) { cairo_int_status_t status; @@ -1961,7 +1975,8 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface, if (surface->backend->fill_rectangles) { status = surface->backend->fill_rectangles (surface, - op, color, + op, color_space, + components, rects, num_rects); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return _cairo_surface_set_error (surface, status); @@ -1969,7 +1984,8 @@ _cairo_surface_fill_rectangles (cairo_surface_t *surface, return _cairo_surface_set_error (surface, _cairo_surface_fallback_fill_rectangles (surface, - op, color, + op, color_space, + components, rects, num_rects)); } @@ -2781,7 +2797,8 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst, EMPTY: status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, - CAIRO_COLOR_CLEAR, + NULL, + CAIRO_COMPONENTS_CLEAR, &clear_region); CLEANUP_REGIONS: diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h index d571fe68d..de123788e 100644 --- a/src/cairo-types-private.h +++ b/src/cairo-types-private.h @@ -186,7 +186,7 @@ struct _cairo_color_space { typedef union { double comp[MAX_COLOR_COMPONENTS+1]; - double alpha; + double compalpha; struct { double alpha; @@ -391,7 +391,8 @@ struct _cairo_pattern { struct _cairo_solid_pattern { cairo_pattern_t base; - cairo_color_t color; + cairo_color_components_t components; + cairo_color_space_t *color_space; }; typedef struct _cairo_surface_pattern { @@ -468,12 +469,13 @@ typedef union { typedef struct _cairo_mesh_patch { cairo_point_double_t points[4][4]; - cairo_color_t colors[4]; + cairo_color_components_t colors[4]; } cairo_mesh_patch_t; typedef struct _cairo_mesh_pattern { cairo_pattern_t base; + cairo_color_space_t *color_space; cairo_array_t patches; cairo_mesh_patch_t *current_patch; int current_side; diff --git a/src/cairo.c b/src/cairo.c index 5e405c754..f72eea6ac 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -40,6 +40,7 @@ #include "cairo-private.h" #include "cairo-arc-private.h" +#include "cairo-color-private.h" #include "cairo-error-private.h" #include "cairo-path-private.h" @@ -694,7 +695,8 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content) content, extents.width, extents.height, - CAIRO_COLOR_CLEAR, + _cairo_color_space_from_cairo_content (content), + CAIRO_COMPONENTS_CLEAR, TRUE); status = group_surface->status; if (unlikely (status)) @@ -886,21 +888,22 @@ _current_source_matches_solid (cairo_t *cr, double blue, double alpha) { - const cairo_pattern_t *current; - cairo_color_t color; + const cairo_solid_pattern_t *current; + cairo_color_components_t color; - current = cr->gstate->source; - if (current->type != CAIRO_PATTERN_TYPE_SOLID) + if (cr->gstate->source->type != CAIRO_PATTERN_TYPE_SOLID) return FALSE; - red = _cairo_restrict_value (red, 0.0, 1.0); - green = _cairo_restrict_value (green, 0.0, 1.0); - blue = _cairo_restrict_value (blue, 0.0, 1.0); - alpha = _cairo_restrict_value (alpha, 0.0, 1.0); + current = (const cairo_solid_pattern_t *) cr->gstate->source; + if (current->color_space != CAIRO_COLOR_SPACE_DEVICE_RGB) + return FALSE; + + color.argb.red = _cairo_restrict_value (red, 0.0, 1.0); + color.argb.green = _cairo_restrict_value (green, 0.0, 1.0); + color.argb.blue = _cairo_restrict_value (blue, 0.0, 1.0); + color.argb.alpha = _cairo_restrict_value (alpha, 0.0, 1.0); - _cairo_color_init_rgba (&color, red, green, blue, alpha); - return _cairo_color_equal (&color, - &((cairo_solid_pattern_t *) current)->color); + return _cairo_color_equal (&color, ¤t->components); } /** * cairo_set_source_rgb @@ -2262,7 +2265,7 @@ cairo_paint_with_alpha (cairo_t *cr, double alpha) { cairo_status_t status; - cairo_color_t color; + cairo_color_components_t components; cairo_solid_pattern_t pattern; if (unlikely (cr->status)) @@ -2278,8 +2281,9 @@ cairo_paint_with_alpha (cairo_t *cr, return; } - _cairo_color_init_rgba (&color, 0., 0., 0., alpha); - _cairo_pattern_init_solid (&pattern, &color); + components = *CAIRO_COMPONENTS_CLEAR; + components.compalpha = alpha; + _cairo_pattern_init_solid (&pattern, NULL, &components); status = _cairo_gstate_mask (cr->gstate, &pattern.base); if (unlikely (status)) diff --git a/src/cairo.h b/src/cairo.h index f39fa8ee9..c459d2a12 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -2377,7 +2377,7 @@ cairo_pattern_create_rgba (double red, double green, double blue, double alpha); cairo_public cairo_pattern_t * -cairo_pattern_create_color (cairo_color_space_t *color_space +cairo_pattern_create_color (cairo_color_space_t *color_space, double *components, double alpha); @@ -2479,6 +2479,7 @@ cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, const double *components, double alpha); +cairo_public void cairo_pattern_mesh_begin_patch (cairo_pattern_t *pattern); cairo_public void diff --git a/src/cairoint.h b/src/cairoint.h index 960a416e3..7bce8cfa1 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -148,11 +148,8 @@ do { \ #define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= 1.0) #define CAIRO_ALPHA_IS_CLEAR(alpha) ((alpha) <= 0.0) -#define CAIRO_COMPONENTS_IS_OPAQUE(c) CAIRO_ALPHA_IS_OPAQUE ((c)->alpha) -#define CAIRO_COMPONENTS_IS_CLEAR(c) CAIRO_ALPHA_IS_CLEAR ((c)->alpha) - -#define CAIRO_COLOR_IS_OPAQUE(color) CAIRO_COMPONENTS_IS_OPAQUE (&(color)->components) -#define CAIRO_COLOR_IS_CLEAR(color) CAIRO_COMPONENTS_IS_CLEAR (&(color)->components) +#define CAIRO_COMPONENTS_IS_OPAQUE(c) CAIRO_ALPHA_IS_OPAQUE ((c)->compalpha) +#define CAIRO_COMPONENTS_IS_CLEAR(c) CAIRO_ALPHA_IS_CLEAR ((c)->compalpha) /* Reverse the bits in a byte with 7 operations (no 64-bit): * Devised by Sean Anderson, July 13, 2001. @@ -662,11 +659,12 @@ struct _cairo_surface_backend { cairo_region_t *clip_region); cairo_warn cairo_int_status_t - (*fill_rectangles) (void *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects); + (*fill_rectangles) (void *surface, + cairo_operator_t op, + const cairo_color_space_t *color_space, + const cairo_color_components_t *color, + cairo_rectangle_int_t *rects, + int num_rects); /* XXX: dst should be the first argument for consistency */ cairo_warn cairo_int_status_t @@ -1021,6 +1019,10 @@ cairo_private uint32_t _cairo_operator_bounded_by_either (cairo_operator_t op) cairo_const; /* cairo-color.c */ +cairo_content_t +_cairo_color_get_content (cairo_color_space_t *color_space, + const cairo_color_components_t *components); + cairo_private cairo_bool_t _cairo_color_equal (const cairo_color_components_t *color_a, const cairo_color_components_t *color_b) cairo_pure; @@ -1032,7 +1034,7 @@ _cairo_color_components_equal (const cairo_color_components_t *color_a, cairo_private void _cairo_color_to_pixman_color (const cairo_color_space_t *color_space, const cairo_color_components_t *color_comp, - pixman_color_t *out_color); + pixman_color_t *out); cairo_private void _cairo_stop_to_pixman_stop (const cairo_color_space_t *color_space, @@ -1041,8 +1043,13 @@ _cairo_stop_to_pixman_stop (const cairo_color_space_t *color_space, /* cairo-color-space.c */ -extern const cairo_private cairo_color_space_t _cairo_color_space_nil, - _cairo_color_space_device_gray, _cairo_color_space_device_rgb, _cairo_color_space_device_cmyk; +extern const cairo_private cairo_color_space_t _cairo_color_space_device_gray; +extern const cairo_private cairo_color_space_t _cairo_color_space_device_rgb; +extern const cairo_private cairo_color_space_t _cairo_color_space_device_cmyk; + +#define CAIRO_COLOR_SPACE_DEVICE_GRAY ((cairo_color_space_t *) &_cairo_color_space_device_gray) +#define CAIRO_COLOR_SPACE_DEVICE_RGB ((cairo_color_space_t *) &_cairo_color_space_device_rgb) +#define CAIRO_COLOR_SPACE_DEVICE_CMYK ((cairo_color_space_t *) &_cairo_color_space_device_cmyk) cairo_private cairo_bool_t _cairo_color_space_equal (const cairo_color_space_t *color_space_a, @@ -1537,12 +1544,13 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other, int height); cairo_private cairo_surface_t * -_cairo_surface_create_similar_solid (cairo_surface_t *other, - cairo_content_t content, - int width, - int height, - const cairo_color_t *color, - cairo_bool_t allow_fallback); +_cairo_surface_create_similar_solid (cairo_surface_t *other, + cairo_content_t content, + int width, + int height, + cairo_color_space_t *color_space, + const cairo_color_components_t *components, + cairo_bool_t allow_fallback); cairo_private cairo_surface_t * _cairo_surface_create_solid_pattern_surface (cairo_surface_t *other, @@ -1579,17 +1587,19 @@ _cairo_surface_composite (cairo_operator_t op, cairo_region_t *clip_region); cairo_private cairo_status_t -_cairo_surface_fill_region (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_region_t *region); +_cairo_surface_fill_region (cairo_surface_t *surface, + cairo_operator_t op, + cairo_color_space_t *color_space, + const cairo_color_components_t *color, + cairo_region_t *region); cairo_private cairo_status_t -_cairo_surface_fill_rectangles (cairo_surface_t *surface, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects); +_cairo_surface_fill_rectangles (cairo_surface_t *surface, + cairo_operator_t op, + cairo_color_space_t *color_space, + const cairo_color_components_t *color, + cairo_rectangle_int_t *rects, + int num_rects); cairo_private cairo_status_t _cairo_surface_paint (cairo_surface_t *surface, @@ -2181,8 +2191,9 @@ _cairo_pattern_init_snapshot (cairo_pattern_t *pattern, const cairo_pattern_t *other); cairo_private void -_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, - const cairo_color_t *color); +_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern, + cairo_color_space_t *color_space, + const cairo_color_components_t *components); cairo_private void _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, @@ -2192,7 +2203,8 @@ cairo_private void _cairo_pattern_fini (cairo_pattern_t *pattern); cairo_private cairo_pattern_t * -_cairo_pattern_create_solid (const cairo_color_t *color); +_cairo_pattern_create_solid (cairo_color_space_t *color_space, + const cairo_color_components_t *components); cairo_private void _cairo_pattern_transform (cairo_pattern_t *pattern, @@ -2211,8 +2223,8 @@ _cairo_pattern_alpha_range (const cairo_pattern_t *gradient, cairo_private cairo_bool_t _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient, - const cairo_rectangle_int_t *extents, - cairo_color_t *color); + const cairo_rectangle_int_t *extents, + cairo_color_components_t *components); cairo_private void _cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient, |