[cairo] cairo stroke problem with potential patch
Jeff Muizelaar
jeff at infidigm.net
Tue Jun 20 10:51:21 PDT 2006
On Tue, Jun 20, 2006 at 07:47:28AM -0400, Keith Wells wrote:
> I have been working on some bugs in the Mozilla SVG arena. The initial
> stroke-cap is missing from the very first dash-array element drawn in the
> following svg example. I noticed there was a cairo bug already in the
> system, https://bugs.freedesktop.org/show_bug.cgi?id=4409, that addressed
> this issue, or close to it, but apparently still exists on, at least, the
> Windows XP version of recent builds of firefox. I don't think this has
> been resolved in the most recent version of cairo-path-stroke.c.
>
> This is the svg example I have been playing with that shows this problem:
> <?xml version="1.0" ?>
> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
> <rect x="20" y="20" width="100" height="100" fill="blue" stroke="red"
> stroke-width="20" stroke-dasharray="0.001,20" stroke-linecap="round"/>
> </svg>
>
> If you render this in firefox, you will notice that the very first leading
> cap is cutoff.
>
> Here is a fix for it:
>
> @@ -720,21 +738,20 @@ _cairo_stroker_line_to_dashed (void *clo
> if (stroker->has_current_face) {
> status = _cairo_stroker_join (stroker,
> &stroker->current_face, &sub_start);
> if (status)
> return status;
> } else {
> if (!stroker->has_first_face) {
> stroker->first_face = sub_start;
> stroker->has_first_face = 1;
> - } else {
> + }
> status = _cairo_stroker_add_leading_cap (stroker,
> &sub_start);
> if (status)
> return status;
> - }
> }
> }
> if (remain) {
> /*
> * Cap if not at end of segment
> */
> status = _cairo_stroker_add_trailing_cap (stroker, &sub_end);
> if (status)
>
> The problem with the above svg example is that the first element in this
> dash-array NEVER invokes _cairo_stroker_add_leading_cap.
This is not exactly true. The first element of the dash-array is usually
capped by _cairo_stroker_add_caps either by
_cairo_path_fixed_stroke_to_traps or _cairo_stroker_move_to. I haven't
actually looked at the However, it
looks like the problem you are seeing is caused by stroking a closed
dashed path. Basically, what happen is:
- _cairo_stroker_line_to_dashed adds the first_face expecting it to be
capped later on
- when _cairo_stroker_close_path is called it draws that last line
with _cairo_stroker_line_to_dashed.
- _cairo_stroker_line_to_dashed returns with stroker->has_current_face
unset.
- the test for has_first_face and has_current_face fails correctly
- close_path then incorrectly discards first_face, causing the bug.
Unconditionally adding the cap in the dashed_line_to is wrong because if
the _cairo_stroker_line_to_dashed returns with has_current_face set the
line needs to be joined and not capped.
This means the fix probably belongs in _cairo_stroker_close_path instead
of _cairo_stroker_line_to_dashed.
Thanks for the bug report and attempted fix, the stroking/dashing code
is a little hairy.
-Jeff
More information about the cairo
mailing list