static inline cairo_bool_t _cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents, int width, int height, cairo_operator_t op, const cairo_pattern_t *source, cairo_clip_t *clip) { extents->unbounded.x = extents->unbounded.y = 0; extents->unbounded.width = width; extents->unbounded.height = height; if (clip != NULL) { const cairo_rectangle_int_t *clip_extents; clip_extents = _cairo_clip_get_extents (clip); if (clip_extents == NULL) return FALSE; if (! _cairo_rectangle_intersect (&extents->unbounded, clip_extents)) return FALSE; } extents->bounded = extents->unbounded; extents->is_bounded = _cairo_operator_bounded_by_either (op); _cairo_pattern_get_extents (source, &extents->source); if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) { if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source)) return FALSE; } return TRUE; }
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; }
cairo_bool_t _cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper, cairo_bool_t surface_is_unbounded, cairo_rectangle_int_t *extents) { cairo_rectangle_int_t clip; cairo_bool_t has_clip = FALSE; if (!surface_is_unbounded) has_clip = _cairo_surface_get_extents (wrapper->target, &clip); if (wrapper->clip) { if (has_clip) { if (! _cairo_rectangle_intersect (&clip, _cairo_clip_get_extents (wrapper->clip))) return FALSE; } else { has_clip = TRUE; clip = *_cairo_clip_get_extents (wrapper->clip); } } if (has_clip && wrapper->needs_transform) { cairo_matrix_t m; double x1, y1, x2, y2; _cairo_surface_wrapper_get_inverse_transform (wrapper, &m); x1 = clip.x; y1 = clip.y; x2 = clip.x + clip.width; y2 = clip.y + clip.height; _cairo_matrix_transform_bounding_box (&m, &x1, &y1, &x2, &y2, NULL); clip.x = floor (x1); clip.y = floor (y1); clip.width = ceil (x2) - clip.x; clip.height = ceil (y2) - clip.y; } if (has_clip) { if (wrapper->has_extents) { *extents = wrapper->extents; return _cairo_rectangle_intersect (extents, &clip); } else { *extents = clip; return TRUE; } } else if (wrapper->has_extents) { *extents = wrapper->extents; return TRUE; } else { _cairo_unbounded_rectangle_init (extents); return TRUE; } }
static inline cairo_bool_t _cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip, cairo_bool_t *should_be_lazy) { if (_cairo_clip_is_all_clipped (clip)) return FALSE; extents->surface = surface; extents->op = op; _cairo_surface_get_extents (surface, &extents->destination); extents->clip = NULL; extents->unbounded = extents->destination; extents->is_bounded = _cairo_operator_bounded_by_either (op); if (*should_be_lazy) *should_be_lazy = _cairo_composite_rectangles_check_lazy_init (extents, surface, source); if ((! *should_be_lazy) && (clip && ! _cairo_rectangle_intersect (&extents->unbounded, _cairo_clip_get_extents (clip)))) return FALSE; extents->bounded = extents->unbounded; extents->original_source_pattern = source; if (! *should_be_lazy) { _cairo_composite_reduce_pattern (source, &extents->source_pattern); _cairo_pattern_get_extents (&extents->source_pattern.base, &extents->source); } else _cairo_pattern_get_extents (extents->original_source_pattern, &extents->source); if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) { if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source)) return FALSE; } extents->original_mask_pattern = NULL; extents->mask_pattern.base.type = CAIRO_PATTERN_TYPE_SOLID; extents->mask_pattern.solid.color.alpha = 1.; /* XXX full initialisation? */ extents->mask_pattern.solid.color.alpha_short = 0xffff; return TRUE; }
static cairo_int_status_t _cairo_analysis_surface_stroke (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_path_fixed_t *path, const cairo_stroke_style_t *style, const cairo_matrix_t *ctm, const cairo_matrix_t *ctm_inverse, double tolerance, cairo_antialias_t antialias, const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; cairo_rectangle_int_t extents; if (surface->target->backend->stroke == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { backend_status = surface->target->backend->stroke (surface->target, op, source, path, style, ctm, ctm_inverse, tolerance, antialias, clip); if (_cairo_int_status_is_error (backend_status)) return backend_status; } _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); _cairo_rectangle_intersect (&extents, &rec_extents); } if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t mask_extents; cairo_int_status_t status; status = _cairo_path_fixed_stroke_extents (path, style, ctm, ctm_inverse, tolerance, &mask_extents); if (unlikely (status)) return status; _cairo_rectangle_intersect (&extents, &mask_extents); } return _add_operation (surface, &extents, backend_status); }
static cairo_int_status_t _cairo_analysis_surface_intersect_clip_path (void *abstract_surface, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { cairo_analysis_surface_t *surface = abstract_surface; if (path == NULL) { surface->current_clip.x = 0; surface->current_clip.y = 0; surface->current_clip.width = surface->width; surface->current_clip.height = surface->height; } else { cairo_rectangle_int_t extents; cairo_bool_t is_empty; _cairo_path_fixed_approximate_clip_extents (path, &extents); is_empty = _cairo_rectangle_intersect (&surface->current_clip, &extents); } return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t _cairo_analysis_surface_paint (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip) { cairo_analysis_surface_t *surface = abstract_surface; cairo_int_status_t backend_status; cairo_rectangle_int_t extents; if (surface->target->backend->paint == NULL) { backend_status = CAIRO_INT_STATUS_UNSUPPORTED; } else { backend_status = surface->target->backend->paint (surface->target, op, source, clip); if (_cairo_int_status_is_error (backend_status)) return backend_status; } _cairo_analysis_surface_operation_extents (surface, op, source, clip, &extents); if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN) { cairo_rectangle_int_t rec_extents; backend_status = _analyze_recording_surface_pattern (surface, source, &rec_extents); _cairo_rectangle_intersect (&extents, &rec_extents); } return _add_operation (surface, &extents, backend_status); }
cairo_int_status_t _cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip) { if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) { return CAIRO_INT_STATUS_NOTHING_TO_DO; } extents->mask = extents->destination; extents->clip = _cairo_clip_reduce_for_composite (clip, extents); if (_cairo_clip_is_all_clipped (extents->clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (! _cairo_rectangle_intersect (&extents->unbounded, _cairo_clip_get_extents (extents->clip))) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) _cairo_pattern_sampled_area (&extents->source_pattern.base, &extents->bounded, &extents->source_sample_area); return CAIRO_STATUS_SUCCESS; }
static cairo_int_status_t _cairo_analysis_surface_intersect_clip_path (void *abstract_surface, cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { cairo_analysis_surface_t *surface = abstract_surface; double x1, y1, x2, y2; cairo_rectangle_int_t extent; if (path == NULL) { surface->current_clip.x = 0; surface->current_clip.y = 0; surface->current_clip.width = surface->width; surface->current_clip.height = surface->height; } else { cairo_status_t status; status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance); if (status) return status; extent.x = floor (x1); extent.y = floor (y1); extent.width = ceil (x2) - extent.x; extent.height = ceil (y2) - extent.y; _cairo_rectangle_intersect (&surface->current_clip, &extent); } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path, cairo_rectangle_int_t *rectangle) { while (clip_path) { cairo_status_t status; cairo_traps_t traps; cairo_box_t extents; cairo_rectangle_int_t extents_rect; _cairo_traps_init (&traps); status = _cairo_path_fixed_fill_to_traps (&clip_path->path, clip_path->fill_rule, clip_path->tolerance, &traps); if (status) { _cairo_traps_fini (&traps); return status; } _cairo_traps_extents (&traps, &extents); _cairo_box_round_to_rectangle (&extents, &extents_rect); _cairo_rectangle_intersect (rectangle, &extents_rect); _cairo_traps_fini (&traps); clip_path = clip_path->prev; } return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_surface_fallback_fill (cairo_surface_t *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_status_t status; cairo_traps_t traps; cairo_box_t box; cairo_rectangle_int_t extents; status = _cairo_surface_get_extents (surface, &extents); if (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) return status; _cairo_rectangle_intersect (&extents, &source_extents); } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (status) return status; box.p1.x = _cairo_fixed_from_int (extents.x); box.p1.y = _cairo_fixed_from_int (extents.y); box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); _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; } status = _clip_and_composite_trapezoids (source, op, surface, &traps, surface->clip, antialias); _cairo_traps_fini (&traps); return status; }
static cairo_status_t _cairo_surface_subsurface_mark_dirty (void *abstract_surface, int x, int y, int width, int height) { cairo_surface_subsurface_t *surface = abstract_surface; cairo_status_t status; status = CAIRO_STATUS_SUCCESS; if (surface->target->backend->mark_dirty_rectangle != NULL) { cairo_rectangle_int_t rect, extents; rect.x = x; rect.y = y; rect.width = width; rect.height = height; extents.x = extents.y = 0; extents.width = surface->extents.width; extents.height = surface->extents.height; if (_cairo_rectangle_intersect (&rect, &extents)) { status = surface->target->backend->mark_dirty_rectangle (surface->target, rect.x + surface->extents.x, rect.y + surface->extents.y, rect.width, rect.height); } } return status; }
static cairo_int_status_t _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents, const cairo_clip_t *clip) { if ((!_cairo_rectangle_intersect (&extents->bounded, &extents->mask)) && (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) { extents->unbounded = extents->bounded; } else if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) { if (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask)) return CAIRO_INT_STATUS_NOTHING_TO_DO; } extents->clip = _cairo_clip_reduce_for_composite (clip, extents); if (_cairo_clip_is_all_clipped (extents->clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (! _cairo_rectangle_intersect (&extents->unbounded, _cairo_clip_get_extents (extents->clip))) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (! _cairo_rectangle_intersect (&extents->bounded, _cairo_clip_get_extents (extents->clip)) && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) { return CAIRO_INT_STATUS_NOTHING_TO_DO; } if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) _cairo_pattern_sampled_area (&extents->source_pattern.base, &extents->bounded, &extents->source_sample_area); if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) { _cairo_pattern_sampled_area (&extents->mask_pattern.base, &extents->bounded, &extents->mask_sample_area); if (extents->mask_sample_area.width == 0 || extents->mask_sample_area.height == 0) { _cairo_composite_rectangles_fini (extents); return CAIRO_INT_STATUS_NOTHING_TO_DO; } } return CAIRO_STATUS_SUCCESS; }
cairo_int_status_t _cairo_composite_rectangles_lazy_init_for_mask (cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask, const cairo_clip_t *clip) { cairo_bool_t ret; cairo_bool_t should_be_lazy = (op == CAIRO_OPERATOR_SOURCE) ? FALSE : TRUE; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip, &should_be_lazy)) { return CAIRO_INT_STATUS_NOTHING_TO_DO; } extents->original_mask_pattern = mask; if (! should_be_lazy) { _cairo_composite_reduce_pattern (mask, &extents->mask_pattern); _cairo_pattern_get_extents (&extents->mask_pattern.base, &extents->mask); return _cairo_composite_rectangles_intersect (extents, clip); } _cairo_pattern_get_extents (extents->original_mask_pattern, &extents->mask); ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask); if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) return CAIRO_INT_STATUS_NOTHING_TO_DO; if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE)) extents->unbounded = extents->bounded; else if ((extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) && (!_cairo_rectangle_intersect (&extents->unbounded, &extents->mask))) return CAIRO_INT_STATUS_NOTHING_TO_DO; extents->clip = _cairo_clip_copy (clip); return CAIRO_INT_STATUS_SUCCESS; }
cairo_status_t _cairo_surface_fallback_mask (cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_pattern_t *mask) { cairo_status_t status; cairo_rectangle_int_t extents, source_extents, mask_extents; status = _cairo_surface_get_extents (surface, &extents); if (unlikely (status)) return status; if (_cairo_operator_bounded_by_source (op)) { status = _cairo_pattern_get_extents (source, &source_extents); if (unlikely (status)) return status; if (! _cairo_rectangle_intersect (&extents, &source_extents)) return CAIRO_STATUS_SUCCESS; } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_pattern_get_extents (mask, &mask_extents); if (unlikely (status)) return status; if (! _cairo_rectangle_intersect (&extents, &mask_extents)) return CAIRO_STATUS_SUCCESS; } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (unlikely (status)) return status; status = _clip_and_composite (surface->clip, op, source, _cairo_surface_mask_draw_func, (void *) mask, surface, &extents); return status; }
cairo_bool_t _cairo_composite_rectangles_can_reduce_clip (cairo_composite_rectangles_t *composite, cairo_clip_t *clip) { cairo_rectangle_int_t extents; cairo_box_t box; if (clip == NULL) return TRUE; extents = composite->destination; if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) _cairo_rectangle_intersect (&extents, &composite->source); if (composite->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) _cairo_rectangle_intersect (&extents, &composite->mask); _cairo_box_from_rectangle (&box, &extents); return _cairo_clip_contains_box (clip, &box); }
cairo_status_t _cairo_surface_fallback_mask (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, cairo_pattern_t *mask) { cairo_status_t status; cairo_rectangle_int16_t extents, source_extents, mask_extents; status = _cairo_surface_get_extents (surface, &extents); if (status) return status; if (_cairo_operator_bounded_by_source (op)) { status = _cairo_pattern_get_extents (source, &source_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &source_extents); } if (_cairo_operator_bounded_by_mask (op)) { status = _cairo_pattern_get_extents (mask, &mask_extents); if (status) return status; _cairo_rectangle_intersect (&extents, &mask_extents); } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (status) return status; status = _clip_and_composite (surface->clip, op, source, _cairo_surface_mask_draw_func, mask, surface, &extents); 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_composite_rectangles_intersect (cairo_composite_rectangles_t *extents) { cairo_bool_t ret; ret = _cairo_rectangle_intersect (&extents->bounded, &extents->mask); if (! ret && extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) return CAIRO_INT_STATUS_NOTHING_TO_DO; return CAIRO_STATUS_SUCCESS; }
void _cairo_surface_wrapper_intersect_extents (cairo_surface_wrapper_t *wrapper, const cairo_rectangle_int_t *extents) { if (! wrapper->has_extents) { wrapper->extents = *extents; wrapper->has_extents = TRUE; } else _cairo_rectangle_intersect (&wrapper->extents, extents); wrapper->needs_transform = _cairo_surface_wrapper_needs_device_transform (wrapper); }
cairo_status_t _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, cairo_rectangle_int_t *rectangle) { cairo_status_t status; cairo_bool_t is_empty; if (!clip) return CAIRO_STATUS_SUCCESS; if (clip->all_clipped) { *rectangle = clip->surface_rect; return CAIRO_STATUS_SUCCESS; } if (clip->path) { status = _cairo_clip_path_intersect_to_rectangle (clip->path, rectangle); if (unlikely (status)) return status; } if (clip->has_region) { cairo_rectangle_int_t extents; _cairo_region_get_extents (&clip->region, &extents); is_empty = _cairo_rectangle_intersect (rectangle, &extents); if (is_empty) return CAIRO_STATUS_SUCCESS; } if (clip->surface) is_empty = _cairo_rectangle_intersect (rectangle, &clip->surface_rect); return CAIRO_STATUS_SUCCESS; }
cairo_bool_t _cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper, cairo_rectangle_int_t *extents) { if (wrapper->has_extents) { if (_cairo_surface_get_extents (wrapper->target, extents)) _cairo_rectangle_intersect (extents, &wrapper->extents); else *extents = wrapper->extents; return TRUE; } else { return _cairo_surface_get_extents (wrapper->target, extents); } }
cairo_status_t _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font) { cairo_status_t status; cairo_rectangle_int_t extents; cairo_show_glyphs_info_t glyph_info; status = _cairo_surface_get_extents (surface, &extents); if (unlikely (status)) return status; if (_cairo_operator_bounded_by_mask (op)) { cairo_rectangle_int_t glyph_extents; status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, &glyph_extents); if (unlikely (status)) return status; if (! _cairo_rectangle_intersect (&extents, &glyph_extents)) return CAIRO_STATUS_SUCCESS; } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (unlikely (status)) return status; glyph_info.font = scaled_font; glyph_info.glyphs = glyphs; glyph_info.num_glyphs = num_glyphs; status = _clip_and_composite (surface->clip, op, source, _cairo_surface_old_show_glyphs_draw_func, &glyph_info, surface, &extents); return status; }
cairo_status_t _cairo_surface_fallback_paint (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source) { cairo_status_t status; cairo_rectangle_int_t extents; cairo_box_t box; cairo_traps_t traps; status = _cairo_surface_get_extents (surface, &extents); if (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) return status; _cairo_rectangle_intersect (&extents, &source_extents); } status = _cairo_clip_intersect_to_rectangle (surface->clip, &extents); if (status) return status; box.p1.x = _cairo_fixed_from_int (extents.x); box.p1.y = _cairo_fixed_from_int (extents.y); box.p2.x = _cairo_fixed_from_int (extents.x + extents.width); box.p2.y = _cairo_fixed_from_int (extents.y + extents.height); status = _cairo_traps_init_box (&traps, &box); if (status) return status; status = _clip_and_composite_trapezoids (source, op, surface, &traps, surface->clip, CAIRO_ANTIALIAS_NONE); _cairo_traps_fini (&traps); return status; }
static cairo_status_t _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path, cairo_rectangle_int_t *rectangle) { while (clip_path) { cairo_rectangle_int_t extents; _cairo_path_fixed_approximate_clip_extents (&clip_path->path, &extents); if (! _cairo_rectangle_intersect (rectangle, &extents)) return CAIRO_STATUS_SUCCESS; clip_path = clip_path->prev; } return CAIRO_STATUS_SUCCESS; }
cairo_status_t _cairo_surface_fallback_paint (cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source) { cairo_status_t status; cairo_rectangle_int_t extents; cairo_box_t box; cairo_traps_t traps; 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; _cairo_box_from_rectangle (&box, &extents); _cairo_traps_init_box (&traps, &box); status = _clip_and_composite_trapezoids (source, op, surface, &traps, surface->clip, CAIRO_ANTIALIAS_NONE); _cairo_traps_fini (&traps); return status; }
cairo_int_status_t _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents, cairo_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, const cairo_clip_t *clip, cairo_bool_t *overlap) { cairo_status_t status; if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; /* Computing the exact bbox and the overlap is expensive. * First perform a cheap test to see if the glyphs are all clipped out. */ if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK && _cairo_scaled_font_glyph_approximate_extents (scaled_font, glyphs, num_glyphs, &extents->mask)) { if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask)) return CAIRO_INT_STATUS_NOTHING_TO_DO; } status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, &extents->mask, overlap); if (unlikely (status)) return status; if (overlap && *overlap && scaled_font->options.antialias == CAIRO_ANTIALIAS_NONE && _cairo_pattern_is_opaque_solid (&extents->source_pattern.base)) { *overlap = FALSE; } return _cairo_composite_rectangles_intersect (extents, clip); }
cairo_status_t _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip, cairo_rectangle_int_t *rectangle) { if (!clip) return CAIRO_STATUS_SUCCESS; if (clip->all_clipped) { *rectangle = clip->surface_rect; return CAIRO_STATUS_SUCCESS; } if (clip->path) { cairo_status_t status; status = _cairo_clip_path_intersect_to_rectangle (clip->path, rectangle); if (status) return status; } if (clip->has_region) { cairo_status_t status = CAIRO_STATUS_SUCCESS; cairo_region_t intersection; _cairo_region_init_rect (&intersection, rectangle); status = _cairo_region_intersect (&intersection, &clip->region, &intersection); if (!status) _cairo_region_get_extents (&intersection, rectangle); _cairo_region_fini (&intersection); if (status) return status; } if (clip->surface) _cairo_rectangle_intersect (rectangle, &clip->surface_rect); return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip, cairo_clip_path_t *other_path, const cairo_matrix_t *matrix) { cairo_status_t status; cairo_clip_path_t *clip_path; cairo_bool_t is_empty; if (other_path->prev != NULL) { status = _cairo_clip_path_reapply_clip_path_transform (clip, other_path->prev, matrix); if (unlikely (status)) return status; } clip_path = _cairo_clip_path_create (clip); if (unlikely (clip_path == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); status = _cairo_path_fixed_init_copy (&clip_path->path, &other_path->path); if (unlikely (status)) { _cairo_clip_path_destroy (clip_path); return status; } _cairo_path_fixed_transform (&clip_path->path, matrix); _cairo_path_fixed_approximate_clip_extents (&clip_path->path, &clip_path->extents); if (clip_path->prev != NULL) { is_empty = _cairo_rectangle_intersect (&clip_path->extents, &clip_path->prev->extents); } clip_path->fill_rule = other_path->fill_rule; clip_path->tolerance = other_path->tolerance; clip_path->antialias = other_path->antialias; return CAIRO_STATUS_SUCCESS; }
static void _cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface, cairo_operator_t op, const cairo_pattern_t *source, const cairo_clip_t *clip, cairo_rectangle_int_t *extents) { cairo_bool_t is_empty; is_empty = _cairo_surface_get_extents (&surface->base, extents); if (_cairo_operator_bounded_by_source (op)) { cairo_rectangle_int_t source_extents; _cairo_pattern_get_extents (source, &source_extents); _cairo_rectangle_intersect (extents, &source_extents); } _rectangle_intersect_clip (extents, clip); }