static cairo_int_status_t clip_and_composite_polygon (const cairo_spans_compositor_t *compositor, cairo_composite_rectangles_t *extents, cairo_polygon_t *polygon, cairo_fill_rule_t fill_rule, cairo_antialias_t antialias) { cairo_int_status_t status; /* XXX simply uses polygon limits.point extemities, tessellation? */ status = trim_extents_to_polygon (extents, polygon); if (unlikely (status)) return status; if (_cairo_polygon_is_empty (polygon)) { cairo_boxes_t boxes; if (extents->is_bounded) return CAIRO_STATUS_SUCCESS; _cairo_boxes_init (&boxes); extents->bounded.width = extents->bounded.height = 0; return fixup_unbounded_boxes (compositor, extents, &boxes); } if (extents->is_bounded && extents->clip->path) { cairo_polygon_t clipper; cairo_antialias_t clip_antialias; cairo_fill_rule_t clip_fill_rule; status = _cairo_clip_get_polygon (extents->clip, &clipper, &clip_fill_rule, &clip_antialias); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *old_clip; if (clip_antialias == antialias) { /* refresh limits after trimming extents */ _cairo_polygon_limit_to_clip(polygon, extents->clip); status = _cairo_polygon_intersect (polygon, fill_rule, &clipper, clip_fill_rule); _cairo_polygon_fini (&clipper); if (unlikely (status)) return status; old_clip = extents->clip; extents->clip = _cairo_clip_copy_region (extents->clip); _cairo_clip_destroy (old_clip); } else { _cairo_polygon_fini (&clipper); } } } return composite_polygon (compositor, extents, polygon, fill_rule, antialias); }
static cairo_int_status_t fixup_unbounded_polygon (const cairo_spans_compositor_t *compositor, const cairo_composite_rectangles_t *extents, cairo_boxes_t *boxes) { cairo_polygon_t polygon, intersect; cairo_composite_rectangles_t composite; cairo_fill_rule_t fill_rule; cairo_antialias_t antialias; cairo_int_status_t status; TRACE((stderr, "%s\n", __FUNCTION__)); /* Can we treat the clip as a regular clear-polygon and use it to fill? */ status = _cairo_clip_get_polygon (extents->clip, &polygon, &fill_rule, &antialias); if (status == CAIRO_INT_STATUS_UNSUPPORTED) return status; status= _cairo_polygon_init_boxes (&intersect, boxes); if (unlikely (status)) goto cleanup_polygon; status = _cairo_polygon_intersect (&polygon, fill_rule, &intersect, CAIRO_FILL_RULE_WINDING); _cairo_polygon_fini (&intersect); if (unlikely (status)) goto cleanup_polygon; status = _cairo_composite_rectangles_init_for_polygon (&composite, extents->surface, CAIRO_OPERATOR_CLEAR, &_cairo_pattern_clear.base, &polygon, NULL); if (unlikely (status)) goto cleanup_polygon; status = composite_polygon (compositor, &composite, &polygon, fill_rule, antialias); _cairo_composite_rectangles_fini (&composite); cleanup_polygon: _cairo_polygon_fini (&polygon); return status; }
cairo_int_status_t _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx, cairo_gl_composite_t *setup, cairo_clip_t *clip, cairo_traps_t *traps) { cairo_int_status_t status; cairo_polygon_t polygon; cairo_antialias_t antialias; cairo_fill_rule_t fill_rule; if (! clip) return CAIRO_INT_STATUS_UNSUPPORTED; if (clip->num_boxes == 1 && ! clip->path) return _cairo_gl_msaa_compositor_draw_quad (ctx, setup, &clip->boxes[0]); if (traps->num_traps == 0) { status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); if (unlikely (status)) return status; /* We ignore the antialias mode of the clip here, since the user requested * unantialiased rendering of their path and we expect that this stencil * based rendering of the clip to be a reasonable approximation to * the intersection between that clip and the path. * * In other words, what the user expects when they try to perform * a geometric intersection between an unantialiased polygon and an * antialiased polygon is open to interpretation. And we choose the fast * option. */ status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, fill_rule); _cairo_polygon_fini (&polygon); if (unlikely (status)) return status; } status = _draw_traps (ctx, setup, traps); return status; }
static cairo_int_status_t _draw_clip (cairo_gl_context_t *ctx, cairo_gl_composite_t *setup, cairo_clip_t *clip) { cairo_int_status_t status; cairo_traps_t traps; cairo_polygon_t polygon; cairo_antialias_t antialias; cairo_fill_rule_t fill_rule; status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); if (unlikely (status)) return status; /* We ignore the antialias mode of the clip here, since the user requested * unantialiased rendering of their path and we expect that this stencil * based rendering of the clip to be a reasonable approximation to * the intersection between that clip and the path. * * In other words, what the user expects when they try to perform * a geometric intersection between an unantialiased polygon and an * antialiased polygon is open to interpretation. And we choose the fast * option. */ _cairo_traps_init (&traps); status = _cairo_bentley_ottmann_tessellate_polygon (&traps, &polygon, fill_rule); _cairo_polygon_fini (&polygon); if (unlikely (status)) return status; status = _draw_traps (ctx, setup, &traps); _cairo_traps_fini (&traps); return status; }
static cairo_int_status_t _clip_to_traps (cairo_clip_t *clip, cairo_traps_t *traps) { cairo_int_status_t status; cairo_polygon_t polygon; cairo_antialias_t antialias; cairo_fill_rule_t fill_rule; _cairo_traps_init (traps); if (clip->num_boxes == 1 && clip->path == NULL) { cairo_boxes_t boxes; _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes); return _cairo_traps_init_boxes (traps, &boxes); } status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); if (unlikely (status)) return status; /* We ignore the antialias mode of the clip here, since the user requested * unantialiased rendering of their path and we expect that this stencil * based rendering of the clip to be a reasonable approximation to * the intersection between that clip and the path. * * In other words, what the user expects when they try to perform * a geometric intersection between an unantialiased polygon and an * antialiased polygon is open to interpretation. And we choose the fast * option. */ _cairo_traps_init (traps); status = _cairo_bentley_ottmann_tessellate_polygon (traps, &polygon, fill_rule); _cairo_polygon_fini (&polygon); return status; }
static cairo_int_status_t clip_and_composite_boxes (const cairo_spans_compositor_t *compositor, cairo_composite_rectangles_t *extents, cairo_boxes_t *boxes) { cairo_int_status_t status; cairo_polygon_t polygon; TRACE ((stderr, "%s\n", __FUNCTION__)); status = trim_extents_to_boxes (extents, boxes); if (unlikely (status)) return status; if (boxes->num_boxes == 0) { if (extents->is_bounded) return CAIRO_STATUS_SUCCESS; return fixup_unbounded_boxes (compositor, extents, boxes); } /* Can we reduce drawing through a clip-mask to simply drawing the clip? */ if (extents->clip->path != NULL && extents->is_bounded) { cairo_polygon_t polygon; cairo_fill_rule_t fill_rule; cairo_antialias_t antialias; cairo_clip_t *clip; clip = _cairo_clip_copy (extents->clip); clip = _cairo_clip_intersect_boxes (clip, boxes); if (_cairo_clip_is_all_clipped (clip)) return CAIRO_INT_STATUS_NOTHING_TO_DO; status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); _cairo_clip_path_destroy (clip->path); clip->path = NULL; if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *saved_clip = extents->clip; extents->clip = clip; status = clip_and_composite_polygon (compositor, extents, &polygon, fill_rule, antialias); clip = extents->clip; extents->clip = saved_clip; _cairo_polygon_fini (&polygon); } _cairo_clip_destroy (clip); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; } if (boxes->is_pixel_aligned) { status = composite_aligned_boxes (compositor, extents, boxes); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; } status = composite_boxes (compositor, extents, boxes); if (status != CAIRO_INT_STATUS_UNSUPPORTED) return status; status = _cairo_polygon_init_boxes (&polygon, boxes); if (unlikely (status)) return status; status = composite_polygon (compositor, extents, &polygon, CAIRO_FILL_RULE_WINDING, CAIRO_ANTIALIAS_DEFAULT); _cairo_polygon_fini (&polygon); return status; }
static cairo_int_status_t clip_and_composite_polygon (const cairo_spans_compositor_t *compositor, cairo_composite_rectangles_t *extents, cairo_polygon_t *polygon, cairo_fill_rule_t fill_rule, cairo_antialias_t antialias) { cairo_int_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); /* XXX simply uses polygon limits.point extemities, tessellation? */ status = trim_extents_to_polygon (extents, polygon); if (unlikely (status)) return status; if (_cairo_polygon_is_empty (polygon)) { cairo_boxes_t boxes; if (extents->is_bounded) return CAIRO_STATUS_SUCCESS; _cairo_boxes_init (&boxes); extents->bounded.width = extents->bounded.height = 0; return fixup_unbounded_boxes (compositor, extents, &boxes); } if (extents->is_bounded && extents->clip->path) { cairo_polygon_t clipper; cairo_antialias_t clip_antialias; cairo_fill_rule_t clip_fill_rule; TRACE((stderr, "%s - combining shape with clip polygon\n", __FUNCTION__)); status = _cairo_clip_get_polygon (extents->clip, &clipper, &clip_fill_rule, &clip_antialias); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) { cairo_clip_t *old_clip; if (clip_antialias == antialias) { status = _cairo_polygon_intersect (polygon, fill_rule, &clipper, clip_fill_rule); _cairo_polygon_fini (&clipper); if (unlikely (status)) return status; old_clip = extents->clip; extents->clip = _cairo_clip_copy_region (extents->clip); _cairo_clip_destroy (old_clip); status = trim_extents_to_polygon (extents, polygon); if (unlikely (status)) return status; fill_rule = CAIRO_FILL_RULE_WINDING; } else { _cairo_polygon_fini (&clipper); } } } return composite_polygon (compositor, extents, polygon, fill_rule, antialias); }