diff options
Diffstat (limited to 'src/cairo-surface-fallback.c')
-rw-r--r-- | src/cairo-surface-fallback.c | 182 |
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; |