Do correct calculation of pen dimensions for stroke optimization

This commit is contained in:
Vladimir Vukicevic 2008-02-06 13:01:52 -08:00 committed by Vladimir Vukicevic
parent e104fcab1c
commit bf1f7f70b6
4 changed files with 41 additions and 22 deletions

View file

@ -192,30 +192,23 @@ _cairo_stroker_init (cairo_stroker_t *stroker,
stroker->has_bounds = _cairo_traps_get_limit (traps, &stroker->bounds);
if (stroker->has_bounds) {
/* Extend the bounds by the line width in each direction so that we correctly
* capture segment endcaps and other similar renderings that would extend beyond
* the segment itself.
/* Extend the bounds in each direction to account for the maximum area
* we might generate trapezoids, to capture line segments that are outside
* of the bounds but which might generate rendering that's within bounds.
*/
double width_x = stroker->style->line_width;
double width_y = stroker->style->line_width;
double dx, dy;
cairo_fixed_t fdx, fdy;
cairo_fixed_t fixed_x, fixed_y;
_cairo_stroke_style_max_distance_from_path (stroker->style, stroker->ctm, &dx, &dy);
if (stroke_style->line_join == CAIRO_LINE_JOIN_MITER) {
width_x *= stroker->style->miter_limit;
width_y *= stroker->style->miter_limit;
}
fdx = _cairo_fixed_from_double (dx);
fdy = _cairo_fixed_from_double (dy);
cairo_matrix_transform_distance (stroker->ctm, &width_x, &width_y);
stroker->bounds.p1.x -= fdx;
stroker->bounds.p2.x += fdx;
fixed_x = _cairo_fixed_from_double (width_x);
fixed_y = _cairo_fixed_from_double (width_y);
stroker->bounds.p1.x -= fixed_x;
stroker->bounds.p2.x += fixed_x;
stroker->bounds.p1.y -= fixed_y;
stroker->bounds.p2.y += fixed_y;
stroker->bounds.p1.y -= fdy;
stroker->bounds.p2.y += fdy;
}
return CAIRO_STATUS_SUCCESS;
@ -864,7 +857,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point)
segment.p2.y = _cairo_fixed_from_double (dy2) + p1->y;
if (fully_in_bounds ||
_cairo_box_intersects_line (&stroker->bounds, &segment))
_cairo_box_intersects_line_segment (&stroker->bounds, &segment))
{
if (stroker->dash_on) {
status = _cairo_stroker_add_sub_edge (stroker, &segment.p1, &segment.p2, slope_dx, slope_dy, &sub_start, &sub_end);

View file

@ -106,7 +106,7 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *
*/
cairo_bool_t
_cairo_box_intersects_line (cairo_box_t *box, cairo_line_t *line)
_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line)
{
cairo_fixed_t t1, t2, t3, t4;
cairo_int64_t t1y, t2y, t3x, t4x;

View file

@ -84,3 +84,20 @@ _cairo_stroke_style_fini (cairo_stroke_style_t *style)
}
style->num_dashes = 0;
}
/*
* For a stroke in the given style, compute the maximum distance
* from the path that vertices could be generated. In the case
* of rotation in the ctm, the distance will not be exact.
*/
void
_cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
double *dx, double *dy)
{
double style_expansion = MAX(style->line_cap == CAIRO_LINE_CAP_SQUARE ? M_SQRT1_2 : 0.5,
style->line_join == CAIRO_LINE_JOIN_MITER ? style->miter_limit : 0.5);
*dx = style->line_width * style_expansion * (fabs(ctm->xx) + fabs(ctm->xy));
*dy = style->line_width * style_expansion * (fabs(ctm->yy) + fabs(ctm->yx));
}

View file

@ -98,6 +98,10 @@ _cairo_win32_tmpfile (void);
#define M_SQRT2 1.41421356237309504880
#endif
#ifndef M_SQRT1_2
#define M_SQRT1_2 0.707106781186547524400844362104849039
#endif
#undef ARRAY_LENGTH
#define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0])))
@ -180,7 +184,7 @@ cairo_private void
_cairo_rectangle_intersect (cairo_rectangle_int_t *dest, cairo_rectangle_int_t *src);
cairo_private cairo_bool_t
_cairo_box_intersects_line (cairo_box_t *box, cairo_line_t *line);
_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
cairo_private cairo_bool_t
_cairo_box_contains_point (cairo_box_t *box, cairo_point_t *point);
@ -1482,6 +1486,11 @@ _cairo_stroke_style_init_copy (cairo_stroke_style_t *style,
cairo_private void
_cairo_stroke_style_fini (cairo_stroke_style_t *style);
cairo_private void
_cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style,
const cairo_matrix_t *ctm,
double *dx, double *dy);
/* cairo-surface.c */
cairo_private cairo_surface_t *