static cairo_int_status_t _cairo_analysis_surface_stroke (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_stroke_style_t *style, cairo_matrix_t *ctm, cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, cairo_rectangle_int_t *stroke_extents) { cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_rectangle_int_t extents; cairo_bool_t is_empty; if (!surface->target->backend->stroke) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->stroke) (surface->target, op, source, path, style, ctm, ctm_inverse, tolerance, antialias, NULL); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (_cairo_status_is_error (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; is_empty = _cairo_rectangle_intersect (&extents, &source_extents); } is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, &mask_extents); is_empty = _cairo_rectangle_intersect (&extents, &mask_extents); } if (stroke_extents) *stroke_extents = extents; status = _add_operation (surface, &extents, backend_status); return status; }
static cairo_int_status_t _cairo_analysis_surface_paint (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_rectangle_int_t *paint_extents) { cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_rectangle_int_t extents; cairo_bool_t is_empty; if (!surface->target->backend->paint) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->paint) (surface->target, op, source, NULL); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (_cairo_status_is_error (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; is_empty = _cairo_rectangle_intersect (&extents, &source_extents); } is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); if (paint_extents) *paint_extents = extents; status = _add_operation (surface, &extents, backend_status); return status; }
static cairo_int_status_t _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const char *utf8, int utf8_len, cairo_glyph_t *glyphs, int num_glyphs, const cairo_text_cluster_t *clusters, int num_clusters, cairo_text_cluster_flags_t cluster_flags, cairo_scaled_font_t *scaled_font, cairo_rectangle_int_t *show_text_glyphs_extents) { cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; cairo_bool_t is_empty; /* Adapted from _cairo_surface_show_glyphs */ backend_status = CAIRO_INT_STATUS_UNSUPPORTED; if (surface->target->backend->show_text_glyphs) backend_status = surface->target->backend->show_text_glyphs (surface->target, op, source, utf8, utf8_len, glyphs, num_glyphs, clusters, num_clusters, cluster_flags, scaled_font, NULL); if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) { int remaining_glyphs = num_glyphs; backend_status = surface->target->backend->show_glyphs (surface->target, op, source, glyphs, num_glyphs, scaled_font, &remaining_glyphs, NULL); glyphs += num_glyphs - remaining_glyphs; num_glyphs = remaining_glyphs; if (remaining_glyphs == 0) backend_status = CAIRO_STATUS_SUCCESS; } if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (_cairo_status_is_error (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; is_empty = _cairo_rectangle_intersect (&extents, &source_extents); } is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, &glyph_extents); if (unlikely (status)) return status; is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents); } if (show_text_glyphs_extents) *show_text_glyphs_extents = extents; status = _add_operation (surface, &extents, backend_status); return status; }
static cairo_int_status_t _cairo_analysis_surface_mask (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, cairo_rectangle_int_t *mask_extents) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t status, backend_status; cairo_rectangle_int_t extents; cairo_bool_t is_empty; if (!surface->target->backend->mask) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->mask) (surface->target, op, source, mask, NULL); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) { cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS; cairo_int_status_t backend_mask_status = CAIRO_STATUS_SUCCESS; if (source->type == CAIRO_PATTERN_TYPE_SURFACE) { const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t *) source; if (_cairo_surface_is_meta (surface_pattern->surface)) { backend_source_status = _analyze_meta_surface_pattern (surface, source); if (_cairo_status_is_error (backend_source_status)) return backend_source_status; } } if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) { cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) mask; if (_cairo_surface_is_meta (surface_pattern->surface)) { backend_mask_status = _analyze_meta_surface_pattern (surface, mask); if (_cairo_status_is_error (backend_mask_status)) return backend_mask_status; } } backend_status = _cairo_analysis_surface_merge_status (backend_source_status, backend_mask_status); } status = _cairo_surface_get_extents (&surface->base, &extents); if (_cairo_status_is_error (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; is_empty = _cairo_rectangle_intersect (&extents, &source_extents); } if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; status = _cairo_pattern_get_extents (mask, &mask_extents); if (unlikely (status)) return status; is_empty = _cairo_rectangle_intersect (&extents, &mask_extents); } is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip); if (mask_extents) *mask_extents = extents; status = _add_operation (surface, &extents, backend_status); return status; }
static cairo_int_status_t _cairo_analysis_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, int *remaining_glyphs) { cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_rectangle_int_t extents, glyph_extents; /* Adapted from _cairo_surface_show_glyphs */ if (surface->target->backend->show_glyphs) backend_status = (*surface->target->backend->show_glyphs) (surface->target, op, source, glyphs, num_glyphs, scaled_font, remaining_glyphs); else if (surface->target->backend->show_text_glyphs) backend_status = surface->target->backend->show_text_glyphs (surface->target, op, source, NULL, 0, glyphs, num_glyphs, NULL, 0, FALSE, scaled_font); else backend_status = CAIRO_INT_STATUS_UNSUPPORTED; if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) 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) return status; _cairo_rectangle_intersect (&extents, &source_extents); } _cairo_rectangle_intersect (&extents, &surface->current_clip); if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, &glyph_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &glyph_extents); } status = _add_operation (surface, &extents, backend_status); return status; }
static cairo_int_status_t _cairo_analysis_surface_fill (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { cairo_analysis_surface_t *surface = abstract_surface; cairo_status_t status, backend_status; cairo_traps_t traps; cairo_rectangle_int_t extents; if (!surface->target->backend->fill) backend_status = CAIRO_INT_STATUS_UNSUPPORTED; else backend_status = (*surface->target->backend->fill) (surface->target, op, source, path, fill_rule, tolerance, antialias); if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) backend_status = _analyze_meta_surface_pattern (surface, source); status = _cairo_surface_get_extents (&surface->base, &extents); if (status && status != CAIRO_INT_STATUS_UNSUPPORTED) 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) return status; _cairo_rectangle_intersect (&extents, &source_extents); } _cairo_rectangle_intersect (&extents, &surface->current_clip); if (_cairo_operator_bounded_by_mask (op)) { cairo_box_t box; _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 (status) { _cairo_traps_fini (&traps); return status; } _cairo_traps_extents (&traps, &box); _cairo_traps_fini (&traps); _cairo_box_round_to_rectangle (&box, &extents); } status = _add_operation (surface, &extents, backend_status); return status; }