int num_segments; int segments_size;
segment_t *segments;
segment_t segments_embedded[8]; /* common case is a single rectangle */
} cairo_rectilinear_stroker_t;
/* If the miter limit turns right angles into bevels, then we *can'tusethisoptimization.Remember,theratiois *1/sin(ɸ/2).Sothecutoffis1/sin(π/4.0)or⎷2,
* which we round for safety. */ if (stroke_style->miter_limit < M_SQRT2) returnFALSE;
/* For each segment we generate a single rectangle. *Thisrectangleisbasedonaperpendicularextension(byhalfthe *linewidth)ofthesegmentendpoints*aftersomeadjustmentsofthe *endpointstoaccountforcapsandjoins.
*/ for (i = 0; i < stroker->num_segments; i++) {
cairo_bool_t lengthen_initial, lengthen_final;
cairo_point_t *a, *b;
cairo_box_t box;
a = &stroker->segments[i].p1;
b = &stroker->segments[i].p2;
/* We adjust the initial point of the segment to extend the *rectangletoincludethepreviouscaporjoin,(this *adjustmentappliestoallsegmentsexceptforthefirst *segmentofopen,butt-cappedpaths).However,wemustbe *carefulnottoemitamiterjoinacrossadegeneratesegment *whichhasbeenelided. * *Overlappingsegmentswillbeeliminatedbythetessellation. *Ideally,wewouldnotemittheseself-intersectionsatall, *butthatistrickywithsegmentsshorterthanhalf_line_width.
*/
j = i == 0 ? stroker->num_segments - 1 : i-1;
lengthen_initial = (stroker->segments[i].flags ^ stroker->segments[j].flags) & HORIZONTAL;
j = i == stroker->num_segments - 1 ? 0 : i+1;
lengthen_final = (stroker->segments[i].flags ^ stroker->segments[j].flags) & HORIZONTAL; if (stroker->open_sub_path) { if (i == 0)
lengthen_initial = line_cap != CAIRO_LINE_CAP_BUTT;
if (i == stroker->num_segments - 1)
lengthen_final = line_cap != CAIRO_LINE_CAP_BUTT;
}
/* Perform the adjustments of the endpoints. */ if (lengthen_initial | lengthen_final) { if (a->y == b->y) { if (a->x < b->x) { if (lengthen_initial)
a->x -= half_line_x; if (lengthen_final)
b->x += half_line_x;
} else { if (lengthen_initial)
a->x += half_line_x; if (lengthen_final)
b->x -= half_line_x;
}
} else { if (a->y < b->y) { if (lengthen_initial)
a->y -= half_line_y; if (lengthen_final)
b->y += half_line_y;
} else { if (lengthen_initial)
a->y += half_line_y; if (lengthen_final)
b->y -= half_line_y;
}
}
}
/* Form the rectangle by expanding by half the line width in
* either perpendicular direction. */ if (a->y == b->y) {
a->y -= half_line_y;
b->y += half_line_y;
} else {
a->x -= half_line_x;
b->x += half_line_x;
}
if (stroker->dash.dashed)
status = _cairo_rectilinear_stroker_emit_segments_dashed (stroker); else
status = _cairo_rectilinear_stroker_emit_segments (stroker); if (unlikely (status)) return status;
/* reset the dash pattern for new sub paths */
_cairo_stroker_dash_start (&stroker->dash);
/* We don't draw anything for degenerate paths. */ if (! stroker->open_sub_path) return CAIRO_STATUS_SUCCESS;
if (stroker->dash.dashed) {
status = _cairo_rectilinear_stroker_line_to_dashed (stroker,
&stroker->first_point);
} else {
status = _cairo_rectilinear_stroker_line_to (stroker,
&stroker->first_point);
} if (unlikely (status)) return status;
stroker->open_sub_path = FALSE;
if (stroker->dash.dashed)
status = _cairo_rectilinear_stroker_emit_segments_dashed (stroker); else
status = _cairo_rectilinear_stroker_emit_segments (stroker); if (unlikely (status)) return status;
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;
if (boxes->num_limits) {
_cairo_rectilinear_stroker_limit (&rectilinear_stroker,
boxes->limits,
boxes->num_limits);
}
status = _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_rectilinear_stroker_emit_segments_dashed (&rectilinear_stroker); else
status = _cairo_rectilinear_stroker_emit_segments (&rectilinear_stroker); if (unlikely (status)) goto BAIL;
/* As we incrementally tessellate, we do not eliminate self-intersections */
status = _cairo_bentley_ottmann_tessellate_boxes (boxes,
CAIRO_FILL_RULE_WINDING,
boxes); if (unlikely (status)) goto BAIL;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.