static cairo_int_status_t _cairo_win32_gdi_compositor_stroke (const cairo_compositor_t *compositor, cairo_composite_rectangles_t *composite, 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) { cairo_int_status_t status; status = CAIRO_INT_STATUS_UNSUPPORTED; if (check_blit (composite) && _cairo_path_fixed_stroke_is_rectilinear (path)) { cairo_boxes_t boxes; TRACE ((stderr, "%s\n", __FUNCTION__)); _cairo_boxes_init_with_clip (&boxes, composite->clip); status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, style, ctm, antialias, &boxes); if (likely (status == CAIRO_INT_STATUS_SUCCESS)) status = draw_boxes (composite, &boxes); _cairo_boxes_fini (&boxes); } return status; }
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; }
static cairo_int_status_t _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor, cairo_composite_rectangles_t *composite, 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) { cairo_int_status_t status; cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; struct _tristrip_composite_info info; cairo_bool_t use_color_attribute; if (! can_use_msaa_compositor (dst, antialias)) return CAIRO_INT_STATUS_UNSUPPORTED; if (composite->is_bounded == FALSE) { cairo_surface_t* surface = _prepare_unbounded_surface (dst); if (unlikely (surface == NULL)) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_compositor_stroke (compositor, surface, CAIRO_OPERATOR_SOURCE, &composite->source_pattern.base, path, style, ctm, ctm_inverse, tolerance, antialias, NULL); if (unlikely (status)) { cairo_surface_destroy (surface); return status; } return _paint_back_unbounded_surface (compositor, composite, surface); } status = _cairo_gl_composite_init (&info.setup, composite->op, dst, FALSE /* assume_component_alpha */); if (unlikely (status)) return status; info.ctx = NULL; use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) || _cairo_gl_hairline_style_is_hairline (style, ctm); status = _cairo_gl_composite_set_source (&info.setup, composite->original_source_pattern, &composite->source_sample_area, &composite->bounded, use_color_attribute); if (unlikely (status)) goto finish; _cairo_gl_msaa_compositor_set_clip (composite, &info.setup); status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx, antialias != CAIRO_ANTIALIAS_NONE); if (unlikely (status)) goto finish; if (_cairo_gl_hairline_style_is_hairline (style, ctm)) { cairo_gl_hairline_closure_t closure; if (! (_is_continuous_arc (path, style) || _is_continuous_single_line (path, style))) { status = _prevent_overlapping_drawing (info.ctx, &info.setup, composite, path, style, ctm); if (unlikely (status)) goto finish; } closure.ctx = info.ctx; closure.tolerance = tolerance; status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure, style, ctm, ctm_inverse, _cairo_gl_hairline_move_to, style->dash ? _cairo_gl_hairline_line_to_dashed : _cairo_gl_hairline_line_to, _cairo_gl_hairline_curve_to, _cairo_gl_hairline_close_path); goto finish; } if (use_color_attribute) { cairo_traps_t traps; _cairo_traps_init (&traps); status = _cairo_path_fixed_stroke_to_traps (path, style, ctm, ctm_inverse, tolerance, &traps); if (unlikely (status)) { _cairo_traps_fini (&traps); goto finish; } status = _draw_traps (info.ctx, &info.setup, &traps); _cairo_traps_fini (&traps); } else { if (!_is_continuous_single_line (path, style)) { status = _prevent_overlapping_drawing (info.ctx, &info.setup, composite, path, style, ctm); if (unlikely (status)) goto finish; } status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path, style, ctm, ctm_inverse, tolerance, _stroke_shaper_add_triangle, _stroke_shaper_add_triangle_fan, _stroke_shaper_add_quad, &info); if (unlikely (status)) goto finish; } finish: _cairo_gl_composite_fini (&info.setup); if (info.ctx) status = _cairo_gl_context_release (info.ctx, status); return status; }
cairo_int_status_t _cairo_path_fixed_stroke_rectilinear_to_boxes (const cairo_path_fixed_t *path, const cairo_stroke_style_t *stroke_style, const cairo_matrix_t *ctm, cairo_antialias_t antialias, cairo_boxes_t *boxes) { cairo_rectilinear_stroker_t rectilinear_stroker; cairo_int_status_t status; cairo_box_t box; assert (_cairo_path_fixed_stroke_is_rectilinear (path)); if (! _cairo_rectilinear_stroker_init (&rectilinear_stroker, stroke_style, ctm, antialias, boxes)) { return CAIRO_INT_STATUS_UNSUPPORTED; } if (! rectilinear_stroker.dash.dashed && _cairo_path_fixed_is_stroke_box (path, &box) && /* if the segments overlap we need to feed them into the tessellator */ box.p2.x - box.p1.x > 2* rectilinear_stroker.half_line_x && box.p2.y - box.p1.y > 2* rectilinear_stroker.half_line_y) { cairo_box_t b; /* top */ b.p1.x = box.p1.x - rectilinear_stroker.half_line_x; b.p2.x = box.p2.x + rectilinear_stroker.half_line_x; b.p1.y = box.p1.y - rectilinear_stroker.half_line_y; b.p2.y = box.p1.y + rectilinear_stroker.half_line_y; status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b); assert (status == CAIRO_INT_STATUS_SUCCESS); /* left (excluding top/bottom) */ b.p1.x = box.p1.x - rectilinear_stroker.half_line_x; b.p2.x = box.p1.x + rectilinear_stroker.half_line_x; b.p1.y = box.p1.y + rectilinear_stroker.half_line_y; b.p2.y = box.p2.y - rectilinear_stroker.half_line_y; status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b); assert (status == CAIRO_INT_STATUS_SUCCESS); /* right (excluding top/bottom) */ b.p1.x = box.p2.x - rectilinear_stroker.half_line_x; b.p2.x = box.p2.x + rectilinear_stroker.half_line_x; b.p1.y = box.p1.y + rectilinear_stroker.half_line_y; b.p2.y = box.p2.y - rectilinear_stroker.half_line_y; status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b); assert (status == CAIRO_INT_STATUS_SUCCESS); /* bottom */ b.p1.x = box.p1.x - rectilinear_stroker.half_line_x; b.p2.x = box.p2.x + rectilinear_stroker.half_line_x; b.p1.y = box.p2.y - rectilinear_stroker.half_line_y; b.p2.y = box.p2.y + rectilinear_stroker.half_line_y; status = (cairo_int_status_t)_cairo_boxes_add (boxes, antialias, &b); assert (status == CAIRO_INT_STATUS_SUCCESS); goto done; } if (boxes->num_limits) { _cairo_rectilinear_stroker_limit (&rectilinear_stroker, boxes->limits, boxes->num_limits); } status = (cairo_int_status_t)_cairo_path_fixed_interpret (path, _cairo_rectilinear_stroker_move_to, rectilinear_stroker.dash.dashed ? _cairo_rectilinear_stroker_line_to_dashed : _cairo_rectilinear_stroker_line_to, NULL, _cairo_rectilinear_stroker_close_path, &rectilinear_stroker); if (unlikely (status)) goto BAIL; if (rectilinear_stroker.dash.dashed) status = (cairo_int_status_t)_cairo_rectilinear_stroker_emit_segments_dashed (&rectilinear_stroker); else status = (cairo_int_status_t)_cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker); if (unlikely (status)) goto BAIL; /* As we incrementally tessellate, we do not eliminate self-intersections */ status = (cairo_int_status_t)_cairo_bentley_ottmann_tessellate_boxes (boxes, CAIRO_FILL_RULE_WINDING, boxes); if (unlikely (status)) goto BAIL; done: _cairo_rectilinear_stroker_fini (&rectilinear_stroker); return (cairo_int_status_t)CAIRO_STATUS_SUCCESS; BAIL: _cairo_rectilinear_stroker_fini (&rectilinear_stroker); _cairo_boxes_clear (boxes); return status; }
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; }