static cairo_clip_t * _cairo_clip_reduce_to_boxes (cairo_clip_t *clip) { struct reduce r; cairo_clip_path_t *clip_path; cairo_status_t status; return clip; if (clip->path == NULL) return clip; r.clip = clip; r.extents.p1.x = r.extents.p1.y = INT_MAX; r.extents.p2.x = r.extents.p2.y = INT_MIN; r.inside = FALSE; r.limit.p1.x = _cairo_fixed_from_int (clip->extents.x); r.limit.p1.y = _cairo_fixed_from_int (clip->extents.y); r.limit.p2.x = _cairo_fixed_from_int (clip->extents.x + clip->extents.width); r.limit.p2.y = _cairo_fixed_from_int (clip->extents.y + clip->extents.height); clip_path = clip->path; do { r.current_point.x = 0; r.current_point.y = 0; r.last_move_to = r.current_point; status = _cairo_path_fixed_interpret_flat (&clip_path->path, _reduce_move_to, _reduce_line_to, _reduce_close, &r, clip_path->tolerance); assert (status == CAIRO_STATUS_SUCCESS); _reduce_close (&r); } while ((clip_path = clip_path->prev)); if (! r.inside) { _cairo_clip_path_destroy (clip->path); clip->path = NULL; } return _cairo_clip_intersect_box (clip, &r.extents); }
static cairo_int_status_t _cairo_spans_compositor_stroke (const cairo_compositor_t *_compositor, cairo_composite_rectangles_t *extents, 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_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor; cairo_int_status_t status; TRACE_ (_cairo_debug_print_path (stderr, path)); status = CAIRO_INT_STATUS_UNSUPPORTED; if (_cairo_path_fixed_stroke_is_rectilinear (path)) { cairo_boxes_t boxes; _cairo_boxes_init (&boxes); if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask)) _cairo_boxes_limit (&boxes, extents->clip->boxes, extents->clip->num_boxes); status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, style, ctm, antialias, &boxes); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) status = clip_and_composite_boxes (compositor, extents, &boxes); _cairo_boxes_fini (&boxes); } if (status == CAIRO_INT_STATUS_UNSUPPORTED) { cairo_polygon_t polygon; cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING; if (extents->mask.width > extents->unbounded.width || extents->mask.height > extents->unbounded.height) { cairo_box_t limits; _cairo_box_from_rectangle (&limits, &extents->unbounded); _cairo_polygon_init (&polygon, &limits, 1); } else { _cairo_polygon_init (&polygon, NULL, 0); } status = _cairo_path_fixed_stroke_to_polygon (path, style, ctm, ctm_inverse, tolerance, &polygon); TRACE_ (_cairo_debug_print_polygon (stderr, &polygon)); if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) { status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule, extents->clip->boxes, extents->clip->num_boxes); } if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *saved_clip = extents->clip; if (extents->is_bounded) { extents->clip = _cairo_clip_copy_path (extents->clip); extents->clip = _cairo_clip_intersect_box(extents->clip, &polygon.extents); } status = clip_and_composite_polygon (compositor, extents, &polygon, fill_rule, antialias); if (extents->is_bounded) { _cairo_clip_destroy (extents->clip); extents->clip = saved_clip; } } _cairo_polygon_fini (&polygon); } return status; }
cairo_clip_t * _cairo_clip_intersect_boxes (cairo_clip_t *clip, const cairo_boxes_t *boxes) { cairo_boxes_t clip_boxes; cairo_box_t limits; cairo_rectangle_int_t extents; if (_cairo_clip_is_all_clipped (clip)) return clip; if (boxes->num_boxes == 0) return _cairo_clip_set_all_clipped (clip); if (boxes->num_boxes == 1) return _cairo_clip_intersect_box (clip, boxes->chunks.base); if (clip == NULL) clip = _cairo_clip_create (); if (clip->num_boxes) { _cairo_boxes_init_for_array (&clip_boxes, clip->boxes, clip->num_boxes); if (unlikely (_cairo_boxes_intersect (&clip_boxes, boxes, &clip_boxes))) { clip = _cairo_clip_set_all_clipped (clip); goto out; } if (clip->boxes != &clip->embedded_box) free (clip->boxes); clip->boxes = NULL; boxes = &clip_boxes; } if (boxes->num_boxes == 0) { clip = _cairo_clip_set_all_clipped (clip); goto out; } else if (boxes->num_boxes == 1) { clip->boxes = &clip->embedded_box; clip->boxes[0] = boxes->chunks.base[0]; clip->num_boxes = 1; } else { clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE); } _cairo_boxes_extents (boxes, &limits); _cairo_box_round_to_rectangle (&limits, &extents); if (clip->path == NULL) clip->extents = extents; else if (! _cairo_rectangle_intersect (&clip->extents, &extents)) clip = _cairo_clip_set_all_clipped (clip); if (clip->region) { cairo_region_destroy (clip->region); clip->region = NULL; } clip->is_region = FALSE; out: if (boxes == &clip_boxes) _cairo_boxes_fini (&clip_boxes); return clip; }
static cairo_int_status_t _cairo_spans_compositor_fill (const cairo_compositor_t *_compositor, cairo_composite_rectangles_t *extents, const cairo_path_fixed_t *path, cairo_fill_rule_t fill_rule, double tolerance, cairo_antialias_t antialias) { const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor; cairo_int_status_t status; TRACE((stderr, "%s op=%d, antialias=%d\n", __FUNCTION__, extents->op, antialias)); status = CAIRO_INT_STATUS_UNSUPPORTED; if (_cairo_path_fixed_fill_is_rectilinear (path)) { cairo_boxes_t boxes; TRACE((stderr, "%s - rectilinear\n", __FUNCTION__)); _cairo_boxes_init (&boxes); if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask)) _cairo_boxes_limit (&boxes, extents->clip->boxes, extents->clip->num_boxes); status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, fill_rule, antialias, &boxes); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) status = clip_and_composite_boxes (compositor, extents, &boxes); _cairo_boxes_fini (&boxes); } if (status == CAIRO_INT_STATUS_UNSUPPORTED) { cairo_polygon_t polygon; TRACE((stderr, "%s - polygon\n", __FUNCTION__)); if (extents->mask.width > extents->unbounded.width || extents->mask.height > extents->unbounded.height) { cairo_box_t limits; TRACE((stderr, "%s - clipping to bounds\n", __FUNCTION__)); _cairo_box_from_rectangle (&limits, &extents->unbounded); _cairo_polygon_init (&polygon, &limits, 1); } else { _cairo_polygon_init (&polygon, NULL, 0); } status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon); if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) { TRACE((stderr, "%s - polygon intersect with %d clip boxes\n", __FUNCTION__, extents->clip->num_boxes)); status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule, extents->clip->boxes, extents->clip->num_boxes); } if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *saved_clip = extents->clip; if (extents->is_bounded) { TRACE((stderr, "%s - polygon discard clip boxes\n", __FUNCTION__)); extents->clip = _cairo_clip_copy_path (extents->clip); extents->clip = _cairo_clip_intersect_box(extents->clip, &polygon.extents); } status = clip_and_composite_polygon (compositor, extents, &polygon, fill_rule, antialias); if (extents->is_bounded) { _cairo_clip_destroy (extents->clip); extents->clip = saved_clip; } } _cairo_polygon_fini (&polygon); TRACE((stderr, "%s - polygon status=%d\n", __FUNCTION__, status)); } return status; }