summaryrefslogtreecommitdiff
path: root/src/cairo-surface-fallback.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-surface-fallback.c')
-rw-r--r--src/cairo-surface-fallback.c182
1 files changed, 140 insertions, 42 deletions
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index a5dcd57a..88975e9a 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -79,7 +79,7 @@ _fallback_init (fallback_state_t *state,
status = _cairo_surface_acquire_dest_image (dst, &state->extents,
&state->image, &state->image_rect,
&state->image_extra);
- if (status)
+ if (unlikely (status))
return status;
/* XXX: This NULL value tucked away in state->image is a rather
@@ -131,7 +131,7 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
NULL, mask,
extents->x, extents->y,
extents);
- if (status)
+ if (unlikely (status))
goto CLEANUP_SURFACE;
if (clip && clip->surface)
@@ -139,7 +139,7 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
mask,
extents->x, extents->y,
extents);
- if (status)
+ if (unlikely (status))
goto CLEANUP_SURFACE;
_cairo_pattern_init_for_surface (mask_pattern, mask);
@@ -169,7 +169,7 @@ _clip_and_composite_with_mask (cairo_clip_t *clip,
clip,
draw_func, draw_closure,
dst, extents);
- if (status)
+ if (unlikely (status))
return status;
status = _cairo_surface_composite (op,
@@ -226,14 +226,14 @@ _clip_and_composite_combine (cairo_clip_t *clip,
_cairo_pattern_fini (&dst_pattern.base);
- if (status)
+ if (unlikely (status))
goto CLEANUP_SURFACE;
status = (*draw_func) (draw_closure, op,
src, intermediate,
extents->x, extents->y,
extents);
- if (status)
+ if (unlikely (status))
goto CLEANUP_SURFACE;
/* Combine that with the clip
@@ -242,7 +242,7 @@ _clip_and_composite_combine (cairo_clip_t *clip,
intermediate,
extents->x, extents->y,
extents);
- if (status)
+ if (unlikely (status))
goto CLEANUP_SURFACE;
/* Punch the clip out of the destination
@@ -251,7 +251,7 @@ _clip_and_composite_combine (cairo_clip_t *clip,
dst,
0, 0,
extents);
- if (status)
+ if (unlikely (status))
goto CLEANUP_SURFACE;
/* Now add the two results together
@@ -293,7 +293,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
clip,
draw_func, draw_closure,
dst, extents);
- if (status)
+ if (unlikely (status))
return status;
/* Compute dest' = dest OUT (mask IN clip)
@@ -305,7 +305,7 @@ _clip_and_composite_source (cairo_clip_t *clip,
extents->x, extents->y,
extents->width, extents->height);
- if (status)
+ if (unlikely (status))
goto CLEANUP_MASK_PATTERN;
/* Now compute (src IN (mask IN clip)) ADD dest'
@@ -439,7 +439,7 @@ _composite_trap_region (cairo_clip_t *clip,
status = _cairo_surface_set_clip_region (dst,
trap_region,
clip_serial);
- if (status)
+ if (unlikely (status))
return status;
}
@@ -531,7 +531,7 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_get_extents (dst, &extents);
- if (status)
+ if (unlikely (status))
return status;
status = _cairo_traps_extract_region (traps, &trap_region);
@@ -548,7 +548,7 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
if (has_trap_region) {
status = _cairo_clip_intersect_to_region (clip, &trap_region);
- if (status)
+ if (unlikely (status))
goto out;
_cairo_region_get_extents (&trap_region, &trap_extents);
@@ -564,7 +564,7 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
}
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
- if (status)
+ if (unlikely (status))
goto out;
} else {
cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
@@ -579,13 +579,13 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
has_clear_region = TRUE;
status = _cairo_clip_intersect_to_region (clip, &clear_region);
- if (status)
+ if (unlikely (status))
goto out;
_cairo_region_get_extents (&clear_region, &extents);
status = _cairo_region_subtract (&clear_region, &clear_region, &trap_region);
- if (status)
+ if (unlikely (status))
goto out;
if (!_cairo_region_not_empty (&clear_region)) {
@@ -597,7 +597,7 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
}
}
- if (status)
+ if (unlikely (status))
goto out;
if (has_trap_region) {
@@ -670,6 +670,53 @@ out:
return status;
}
+typedef struct {
+ cairo_path_fixed_t *path;
+ cairo_fill_rule_t fill_rule;
+ double tolerance;
+ cairo_antialias_t antialias;
+} cairo_composite_spans_fill_info_t;
+
+static cairo_status_t
+_composite_spans_fill_func (void *closure,
+ cairo_operator_t op,
+ const cairo_pattern_t *src,
+ cairo_surface_t *dst,
+ int dst_x,
+ int dst_y,
+ const cairo_rectangle_int_t *extents)
+{
+ cairo_composite_rectangles_t rects;
+ cairo_composite_spans_fill_info_t *info = closure;
+ cairo_pattern_union_t pattern;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ _cairo_composite_rectangles_init (
+ &rects, extents->x, extents->y,
+ extents->width, extents->height);
+
+ /* The incoming dst_x/y are where we're pretending the origin of
+ * the dst surface is -- *not* the offset of a rectangle where
+ * we'd like to place the result. */
+ rects.dst.x -= dst_x;
+ rects.dst.y -= dst_y;
+
+ /* We're called without a source pattern from
+ * _create_composite_mask_pattern(). */
+ _cairo_pattern_init_solid (&pattern.solid, CAIRO_COLOR_WHITE,
+ CAIRO_CONTENT_COLOR);
+ if (src == NULL)
+ src = &pattern.base;
+
+ status = _cairo_path_fixed_fill_using_spans (
+ op, src, info->path, dst,
+ info->fill_rule, info->tolerance, info->antialias,
+ &rects);
+
+ _cairo_pattern_fini (&pattern.base);
+ return status;
+}
+
cairo_status_t
_cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_operator_t op,
@@ -681,14 +728,14 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
cairo_traps_t traps;
status = _cairo_surface_get_extents (surface, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &source_extents))
@@ -696,7 +743,7 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
+ if (unlikely (status))
return status;
_cairo_box_from_rectangle (&box, &extents);
@@ -752,12 +799,12 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
cairo_rectangle_int_t extents, source_extents, mask_extents;
status = _cairo_surface_get_extents (surface, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &source_extents))
@@ -766,7 +813,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
if (_cairo_operator_bounded_by_mask (op)) {
status = _cairo_pattern_get_extents (mask, &mask_extents);
- if (status)
+ if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &mask_extents))
@@ -774,7 +821,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
+ if (unlikely (status))
return status;
status = _clip_and_composite (surface->clip, op,
@@ -804,13 +851,13 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
cairo_rectangle_int_t extents;
status = _cairo_surface_get_extents (surface, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &source_extents))
@@ -818,7 +865,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (extents.width == 0 || extents.height == 0)
@@ -834,7 +881,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
ctm, ctm_inverse,
tolerance,
&traps);
- if (status)
+ if (unlikely (status))
goto FAIL;
status = _clip_and_composite_trapezoids (source,
@@ -865,14 +912,14 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
cairo_rectangle_int_t extents;
status = _cairo_surface_get_extents (surface, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (_cairo_operator_bounded_by_source (op)) {
cairo_rectangle_int_t source_extents;
status = _cairo_pattern_get_extents (source, &source_extents);
- if (status)
+ if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &source_extents))
@@ -880,14 +927,51 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (extents.width == 0 || extents.height == 0)
return CAIRO_STATUS_SUCCESS;
- _cairo_box_from_rectangle (&box, &extents);
+ /* Ask if the surface would like to render this combination of
+ * op/source/dst/antialias with spans or not, but don't actually
+ * make a renderer yet. We'll try to hit the region optimisations
+ * in _clip_and_composite_trapezoids() if it looks like the path
+ * is a region. */
+ /* TODO: Until we have a mono scan converter we won't even try
+ * to use spans for CAIRO_ANTIALIAS_NONE. */
+ /* TODO: The region filling code should be lifted from
+ * _clip_and_composite_trapezoids() and given first priority
+ * explicitly before deciding between spans and trapezoids. */
+ if (antialias != CAIRO_ANTIALIAS_NONE &&
+ !_cairo_path_fixed_is_box (path, &box) &&
+ !_cairo_path_fixed_is_region (path) &&
+ _cairo_surface_check_span_renderer (
+ op, source, surface, antialias, NULL))
+ {
+ cairo_composite_spans_fill_info_t info;
+ info.path = path;
+ info.fill_rule = fill_rule;
+ info.tolerance = tolerance;
+ info.antialias = antialias;
+
+ if (_cairo_operator_bounded_by_mask (op)) {
+ cairo_rectangle_int_t path_extents;
+ _cairo_path_fixed_approximate_extents (path, &path_extents);
+ if (! _cairo_rectangle_intersect (&extents, &path_extents))
+ return CAIRO_STATUS_SUCCESS;
+ }
+ return _clip_and_composite (
+ surface->clip, op, source,
+ _composite_spans_fill_func,
+ &info,
+ surface,
+ &extents);
+ }
+
+ /* Fall back to trapezoid fills. */
+ _cairo_box_from_rectangle (&box, &extents);
_cairo_traps_init (&traps);
_cairo_traps_limit (&traps, &box);
@@ -895,7 +979,7 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
fill_rule,
tolerance,
&traps);
- if (status) {
+ if (unlikely (status)) {
_cairo_traps_fini (&traps);
return status;
}
@@ -992,7 +1076,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
cairo_show_glyphs_info_t glyph_info;
status = _cairo_surface_get_extents (surface, &extents);
- if (status)
+ if (unlikely (status))
return status;
if (_cairo_operator_bounded_by_mask (op)) {
@@ -1002,7 +1086,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
glyphs,
num_glyphs,
&glyph_extents);
- if (status)
+ if (unlikely (status))
return status;
if (! _cairo_rectangle_intersect (&extents, &glyph_extents))
@@ -1010,7 +1094,7 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
}
status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents);
- if (status)
+ if (unlikely (status))
return status;
glyph_info.font = scaled_font;
@@ -1036,10 +1120,16 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
cairo_surface_pattern_t pattern;
cairo_image_surface_t *image;
void *image_extra;
+ const char *mime_types[] = {
+ CAIRO_MIME_TYPE_JPEG,
+ CAIRO_MIME_TYPE_PNG,
+ CAIRO_MIME_TYPE_JP2,
+ NULL
+ }, **mime_type;
status = _cairo_surface_acquire_source_image (surface,
&image, &image_extra);
- if (status)
+ if (unlikely (status))
return _cairo_surface_create_in_error (status);
snapshot = cairo_image_surface_create (image->format,
@@ -1067,7 +1157,7 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
_cairo_surface_release_source_image (surface,
image, image_extra);
- if (status) {
+ if (unlikely (status)) {
cairo_surface_destroy (snapshot);
return _cairo_surface_create_in_error (status);
}
@@ -1075,6 +1165,14 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
snapshot->device_transform = surface->device_transform;
snapshot->device_transform_inverse = surface->device_transform_inverse;
+ for (mime_type = mime_types; *mime_type; mime_type++) {
+ status = _cairo_surface_copy_mime_data (snapshot, surface, *mime_type);
+ if (unlikely (status)) {
+ cairo_surface_destroy (snapshot);
+ return _cairo_surface_create_in_error (status);
+ }
+ }
+
snapshot->is_snapshot = TRUE;
return snapshot;
@@ -1098,7 +1196,7 @@ _cairo_surface_fallback_composite (cairo_operator_t op,
cairo_status_t status;
status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (status) {
+ if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
@@ -1159,7 +1257,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
}
status = _fallback_init (&state, surface, x1, y1, x2 - x1, y2 - y1);
- if (status) {
+ if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;
@@ -1169,7 +1267,7 @@ _cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
if (state.image_rect.x != 0 || state.image_rect.y != 0) {
offset_rects = _cairo_malloc_ab (num_rects, sizeof (cairo_rectangle_int_t));
- if (offset_rects == NULL) {
+ if (unlikely (offset_rects == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto DONE;
}
@@ -1215,7 +1313,7 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
cairo_status_t status;
status = _fallback_init (&state, dst, dst_x, dst_y, width, height);
- if (status) {
+ if (unlikely (status)) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
return CAIRO_STATUS_SUCCESS;
return status;