cairo_status_t _cairo_clip_clip (cairo_clip_t *clip, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias, cairo_surface_t *target) { cairo_status_t status; cairo_rectangle_int_t rectangle; cairo_traps_t traps; cairo_box_t ignored_box; if (clip->all_clipped) return CAIRO_STATUS_SUCCESS; /* catch the empty clip path */ if (! path->has_current_point) { _cairo_clip_set_all_clipped (clip, target); return CAIRO_STATUS_SUCCESS; } status = _cairo_clip_intersect_path (clip, path, fill_rule, tolerance, antialias); if (status == CAIRO_STATUS_SUCCESS) clip->serial = _cairo_surface_allocate_clip_serial (target); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; /* TODO: allow ANTIALIAS_NONE when we have a mono scan converter * again. */ if (antialias != CAIRO_ANTIALIAS_NONE && !_cairo_path_fixed_is_box (path, &ignored_box) && !_cairo_path_fixed_is_region (path)) { status = _cairo_clip_intersect_mask_using_spans ( clip, path, fill_rule, tolerance, antialias, target); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; } _cairo_traps_init (&traps); /* Limit the traps to the target surface * - so we don't add more traps than needed. */ status = _cairo_surface_get_extents (target, &rectangle); if (status == CAIRO_STATUS_SUCCESS) { cairo_box_t box; _cairo_box_from_rectangle (&box, &rectangle); _cairo_traps_limit (&traps, &box); } status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); if (unlikely (status)) goto bail; status = _cairo_clip_intersect_region (clip, &traps, target); if (status != CAIRO_INT_STATUS_UNSUPPORTED) goto bail; status = _cairo_clip_intersect_mask (clip, &traps, antialias, target); bail: _cairo_traps_fini (&traps); return status; }
cairo_status_t _cairo_surface_fallback_fill (cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { cairo_status_t status; cairo_traps_t traps; cairo_box_t box; cairo_rectangle_int_t extents; status = _cairo_surface_get_extents (surface, &extents); 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 (unlikely (status)) return status; if (! _cairo_rectangle_intersect (&extents, &source_extents)) return CAIRO_STATUS_SUCCESS; } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (unlikely (status)) return status; if (extents.width == 0 || extents.height == 0) return CAIRO_STATUS_SUCCESS; /* 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_clip_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); status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); if (unlikely (status)) { _cairo_traps_fini (&traps); return status; } status = _clip_and_composite_trapezoids (source, op, surface, &traps, surface->clip, antialias); _cairo_traps_fini (&traps); return status; }