summaryrefslogtreecommitdiff
path: root/src/cairo-pattern.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-11-25 00:59:31 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-11-25 10:35:42 +0000
commit8844d50308e03e7eb1d6e1530bb4bd98be490cea (patch)
tree655923fadb907cc692a02d8a4a452e8e3774a225 /src/cairo-pattern.c
parent2c4f6bbfbcaacea41386c36f42210120ee815055 (diff)
downloadcairo-8844d50308e03e7eb1d6e1530bb4bd98be490cea.tar.gz
Convert cairo_mime_surface_t to cairo_raster_source_pattern_t
As discussed, overloading the cairo_surface_t semantics to include sources (i.e. read-only surfaces) was duplicating the definition of cairo_pattern_t. So rather than introduce a new surface type with pattern semantics, start along the thorny road of extensible pattern types. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-pattern.c')
-rw-r--r--src/cairo-pattern.c130
1 files changed, 121 insertions, 9 deletions
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index f91de2658..e55e5eb5c 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -187,7 +187,7 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern,
return _cairo_error (status);
}
-static void
+void
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
{
#if HAVE_VALGRIND
@@ -207,6 +207,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
case CAIRO_PATTERN_TYPE_MESH:
VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ break;
}
#endif
@@ -219,7 +221,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
_cairo_user_data_array_init (&pattern->user_data);
- if (type == CAIRO_PATTERN_TYPE_SURFACE)
+ if (type == CAIRO_PATTERN_TYPE_SURFACE ||
+ type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
else
pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
@@ -291,6 +294,8 @@ cairo_status_t
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
+ cairo_status_t status;
+
if (other->status)
return _cairo_pattern_set_error (pattern, other->status);
@@ -316,7 +321,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
case CAIRO_PATTERN_TYPE_RADIAL: {
cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
- cairo_status_t status;
if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
@@ -332,7 +336,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
case CAIRO_PATTERN_TYPE_MESH: {
cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern;
cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other;
- cairo_status_t status;
VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
@@ -341,6 +344,12 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern,
return status;
} break;
+
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
+ status = _cairo_raster_source_pattern_init_copy (pattern, other);
+ if (unlikely (status))
+ return status;
+ } break;
}
/* The reference count and user_data array are unique to the copy. */
@@ -376,6 +385,9 @@ _cairo_pattern_init_static_copy (cairo_pattern_t *pattern,
case CAIRO_PATTERN_TYPE_MESH:
size = sizeof (cairo_mesh_pattern_t);
break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ size = sizeof (cairo_raster_source_pattern_t);
+ break;
}
memcpy (pattern, other, size);
@@ -407,11 +419,11 @@ _cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
cairo_surface_destroy (surface);
- if (surface_pattern->surface->status)
- return surface_pattern->surface->status;
- }
+ status = surface_pattern->surface->status;
+ } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
+ status = _cairo_raster_source_pattern_snapshot (pattern);
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
void
@@ -442,6 +454,9 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
_cairo_array_fini (&mesh->patches);
} break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ _cairo_raster_source_pattern_finish (pattern);
+ break;
}
#if HAVE_VALGRIND
@@ -461,6 +476,8 @@ _cairo_pattern_fini (cairo_pattern_t *pattern)
case CAIRO_PATTERN_TYPE_MESH:
VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t));
break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ break;
}
#endif
}
@@ -491,6 +508,9 @@ _cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
case CAIRO_PATTERN_TYPE_MESH:
pattern = malloc (sizeof (cairo_mesh_pattern_t));
break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ pattern = malloc (sizeof (cairo_raster_source_pattern_t));
+ break;
default:
ASSERT_NOT_REACHED;
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
@@ -1093,7 +1113,10 @@ cairo_pattern_destroy (cairo_pattern_t *pattern)
_cairo_pattern_fini (pattern);
/* maintain a small cache of freed patterns */
- _freed_pool_put (&freed_pattern_pool[type], pattern);
+ if (type < ARRAY_LENGTH (freed_pattern_pool))
+ _freed_pool_put (&freed_pattern_pool[type], pattern);
+ else
+ free (pattern);
}
slim_hidden_def (cairo_pattern_destroy);
@@ -2929,6 +2952,7 @@ _cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
/* fall through */
case CAIRO_PATTERN_TYPE_SURFACE:
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
alpha_min = 0;
alpha_max = 1;
break;
@@ -3133,6 +3157,29 @@ _surface_is_opaque (const cairo_surface_pattern_t *pattern,
}
static cairo_bool_t
+_raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern,
+ const cairo_rectangle_int_t *sample)
+{
+ if (pattern->content & CAIRO_CONTENT_ALPHA)
+ return FALSE;
+
+ if (pattern->base.extend != CAIRO_EXTEND_NONE)
+ return TRUE;
+
+ if (sample != NULL) {
+ if (sample->x >= pattern->extents.x &&
+ sample->y >= pattern->extents.y &&
+ sample->x + sample->width <= pattern->extents.x + pattern->extents.width &&
+ sample->y + sample->height <= pattern->extents.y + pattern->extents.height)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static cairo_bool_t
_surface_is_clear (const cairo_surface_pattern_t *pattern)
{
cairo_rectangle_int_t extents;
@@ -3146,6 +3193,12 @@ _surface_is_clear (const cairo_surface_pattern_t *pattern)
}
static cairo_bool_t
+_raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
+{
+ return pattern->extents.width == 0 || pattern->extents.height == 0;
+}
+
+static cairo_bool_t
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
const cairo_rectangle_int_t *sample)
{
@@ -3215,6 +3268,8 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
return _cairo_pattern_is_opaque_solid (abstract_pattern);
case CAIRO_PATTERN_TYPE_SURFACE:
return _surface_is_opaque (&pattern->surface, sample);
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ return _raster_source_is_opaque (&pattern->raster_source, sample);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
return _gradient_is_opaque (&pattern->gradient.base, sample);
@@ -3240,6 +3295,8 @@ _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
case CAIRO_PATTERN_TYPE_SURFACE:
return _surface_is_clear (&pattern->surface);
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ return _raster_source_is_clear (&pattern->raster_source);
case CAIRO_PATTERN_TYPE_LINEAR:
case CAIRO_PATTERN_TYPE_RADIAL:
return _gradient_is_clear (&pattern->gradient.base, NULL);
@@ -3409,6 +3466,29 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
}
break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ {
+ const cairo_raster_source_pattern_t *raster =
+ (const cairo_raster_source_pattern_t *) pattern;
+ double pad;
+
+ if (raster->extents.width == 0 || raster->extents.height == 0)
+ goto EMPTY;
+
+ if (pattern->extend != CAIRO_EXTEND_NONE)
+ goto UNBOUNDED;
+
+ /* The filter can effectively enlarge the extents of the
+ * pattern, so extend as necessary.
+ */
+ _cairo_pattern_analyze_filter (pattern, &pad);
+ x1 = raster->extents.x - pad;
+ y1 = raster->extents.y - pad;
+ x2 = raster->extents.x + (int) raster->extents.width + pad;
+ y2 = raster->extents.y + (int) raster->extents.height + pad;
+ }
+ break;
+
case CAIRO_PATTERN_TYPE_RADIAL:
{
const cairo_radial_pattern_t *radial =
@@ -3666,6 +3746,15 @@ _cairo_surface_pattern_hash (unsigned long hash,
return hash;
}
+static unsigned long
+_cairo_raster_source_pattern_hash (unsigned long hash,
+ const cairo_raster_source_pattern_t *raster)
+{
+ hash ^= (uintptr_t)raster->user_data;
+
+ return hash;
+}
+
unsigned long
_cairo_pattern_hash (const cairo_pattern_t *pattern)
{
@@ -3698,6 +3787,8 @@ _cairo_pattern_hash (const cairo_pattern_t *pattern)
return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
case CAIRO_PATTERN_TYPE_SURFACE:
return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
default:
ASSERT_NOT_REACHED;
return FALSE;
@@ -3804,6 +3895,13 @@ _cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
return a->surface->unique_id == b->surface->unique_id;
}
+static cairo_bool_t
+_cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a,
+ const cairo_raster_source_pattern_t *b)
+{
+ return a->user_data == b->user_data;
+}
+
cairo_bool_t
_cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
{
@@ -3846,6 +3944,9 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
case CAIRO_PATTERN_TYPE_SURFACE:
return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a,
(cairo_surface_pattern_t *) b);
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a,
+ (cairo_raster_source_pattern_t *) b);
default:
ASSERT_NOT_REACHED;
return FALSE;
@@ -4381,6 +4482,13 @@ _cairo_debug_print_surface_pattern (FILE *file,
}
static void
+_cairo_debug_print_raster_source_pattern (FILE *file,
+ const cairo_raster_source_pattern_t *raster)
+{
+ printf (" content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height);
+}
+
+static void
_cairo_debug_print_linear_pattern (FILE *file,
const cairo_linear_pattern_t *pattern)
{
@@ -4408,6 +4516,7 @@ _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break;
case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break;
case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break;
default: s = "invalid"; ASSERT_NOT_REACHED; break;
}
@@ -4442,6 +4551,9 @@ _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
default:
case CAIRO_PATTERN_TYPE_SOLID:
break;
+ case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
+ _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
+ break;
case CAIRO_PATTERN_TYPE_SURFACE:
_cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
break;