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; 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; if (extents->mask.width > extents->unbounded.width || extents->mask.height > extents->unbounded.height) { _cairo_polygon_init_with_clip (&polygon, extents->clip); } else { _cairo_polygon_init_with_clip (&polygon, NULL); } status = _cairo_path_fixed_stroke_to_polygon (path, style, ctm, ctm_inverse, tolerance, &polygon); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { status = clip_and_composite_polygon (compositor, extents, &polygon, CAIRO_FILL_RULE_WINDING, antialias); } _cairo_polygon_fini (&polygon); } return status; }
cairo_int_status_t _cairo_clip_get_polygon (const cairo_clip_t *clip, cairo_polygon_t *polygon, cairo_fill_rule_t *fill_rule, cairo_antialias_t *antialias) { cairo_status_t status; cairo_clip_path_t *clip_path; if (_cairo_clip_is_all_clipped (clip)) { _cairo_polygon_init (polygon, NULL, 0); return CAIRO_INT_STATUS_SUCCESS; } /* If there is no clip, we need an infinite polygon */ assert (clip && (clip->path || clip->num_boxes)); if (clip->path == NULL) { *fill_rule = CAIRO_FILL_RULE_WINDING; *antialias = CAIRO_ANTIALIAS_DEFAULT; return _cairo_polygon_init_box_array (polygon, clip->boxes, clip->num_boxes); } /* check that residual is all of the same type/tolerance */ if (! can_convert_to_polygon (clip)) return CAIRO_INT_STATUS_UNSUPPORTED; if (clip->num_boxes < 2) _cairo_polygon_init_with_clip (polygon, clip); else _cairo_polygon_init_with_clip (polygon, NULL); clip_path = clip->path; *fill_rule = clip_path->fill_rule; *antialias = clip_path->antialias; status = _cairo_path_fixed_fill_to_polygon (&clip_path->path, clip_path->tolerance, polygon); if (unlikely (status)) goto err; if (clip->num_boxes > 1) { status = _cairo_polygon_intersect_with_boxes (polygon, fill_rule, clip->boxes, clip->num_boxes); if (unlikely (status)) goto err; } polygon->limits = NULL; polygon->num_limits = 0; while ((clip_path = clip_path->prev) != NULL) { cairo_polygon_t next; _cairo_polygon_init (&next, NULL, 0); status = _cairo_path_fixed_fill_to_polygon (&clip_path->path, clip_path->tolerance, &next); if (likely (status == CAIRO_STATUS_SUCCESS)) status = _cairo_polygon_intersect (polygon, *fill_rule, &next, clip_path->fill_rule); _cairo_polygon_fini (&next); if (unlikely (status)) goto err; *fill_rule = CAIRO_FILL_RULE_WINDING; } return CAIRO_STATUS_SUCCESS; err: _cairo_polygon_fini (polygon); return status; }