mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-06-09 15:38:25 +02:00
Improve dash pattern approximation
Dash pattern approximation was taking the caps style into account only for coverage computation, but not when computing the new pattern, thus the computed approximation had a higher coverage if the caps style was SQUARE or ROUND. Reviewed-by: M. Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
This commit is contained in:
parent
8d7841048b
commit
45c795a182
1 changed files with 54 additions and 2 deletions
|
|
@ -251,8 +251,60 @@ _cairo_stroke_style_dash_approximate (const cairo_stroke_style_t *style,
|
|||
|
||||
*num_dashes = 2;
|
||||
|
||||
dashes[0] = scale * coverage;
|
||||
dashes[1] = scale * (1.0 - coverage);
|
||||
/*
|
||||
* We want to create a new dash pattern with the same relative coverage,
|
||||
* but composed of just 2 elements with total length equal to scale.
|
||||
* Based on the formula in _cairo_stroke_style_dash_stroked:
|
||||
* scale * coverage = dashes[0] + cap_scale * MIN (dashes[1], line_width)
|
||||
* = MIN (dashes[0] + cap_scale * (scale - dashes[0]),
|
||||
* dashes[0] + cap_scale * line_width) =
|
||||
* = MIN (dashes[0] * (1 - cap_scale) + cap_scale * scale,
|
||||
* dashes[0] + cap_scale * line_width)
|
||||
*
|
||||
* Solving both cases we get:
|
||||
* dashes[0] = scale * (coverage - cap_scale) / (1 - cap_scale)
|
||||
* when scale - dashes[0] <= line_width
|
||||
* dashes[0] = scale * coverage - cap_scale * line_width
|
||||
* when scale - dashes[0] > line_width.
|
||||
*
|
||||
* Comparing the two cases we get:
|
||||
* second > first
|
||||
* second > scale * (coverage - cap_scale) / (1 - cap_scale)
|
||||
* second - cap_scale * second - scale * coverage + scale * cap_scale > 0
|
||||
* (scale * coverage - cap_scale * line_width) - cap_scale * second - scale * coverage + scale * cap_scale > 0
|
||||
* - line_width - second + scale > 0
|
||||
* scale - second > line_width
|
||||
* which is the condition for the second solution to be the valid one.
|
||||
* So when second > first, the second solution is the correct one (i.e.
|
||||
* the solution is always MAX (first, second).
|
||||
*/
|
||||
switch (style->line_cap) {
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
dashes[0] = 0.0;
|
||||
break;
|
||||
|
||||
case CAIRO_LINE_CAP_BUTT:
|
||||
/* Simplified formula (substituting 0 for cap_scale): */
|
||||
dashes[0] = scale * coverage;
|
||||
break;
|
||||
|
||||
case CAIRO_LINE_CAP_ROUND:
|
||||
dashes[0] = MAX(scale * (coverage - ROUND_MINSQ_APPROXIMATION) / (1.0 - ROUND_MINSQ_APPROXIMATION),
|
||||
scale * coverage - ROUND_MINSQ_APPROXIMATION * style->line_width);
|
||||
break;
|
||||
|
||||
case CAIRO_LINE_CAP_SQUARE:
|
||||
/*
|
||||
* Special attention is needed to handle the case cap_scale == 1 (since the first solution
|
||||
* is either indeterminate or -inf in this case). Since dash lengths are always >=0, using
|
||||
* 0 as first solution always leads to the correct solution.
|
||||
*/
|
||||
dashes[0] = MAX(0.0, scale * coverage - style->line_width);
|
||||
break;
|
||||
}
|
||||
|
||||
dashes[1] = scale - dashes[0];
|
||||
|
||||
*dash_offset = on ? 0.0 : dashes[0];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue