GNOME Bugzilla – Bug 776297
Markers should not be rendered for circle/rect elements
Last modified: 2017-01-27 20:34:01 UTC
According to https://www.w3.org/TR/SVG11/painting.html#MarkerElement the marker properties should only apply to "path", "line", "polyline", "polygon" elements. We render markers for all path-like objects; this is wrong. See the attached test file; only the square on the left (which is a path) should get markers. Also, in that file, the marker for the lower-left corner of the path has the wrong orientation.
Created attachment 342238 [details] 776297-marker-on-non-path-elements.svg
Thanks again for the test case, Massimo. Fixed in commit 6f270cf091190f3e2a264563ad9eddc1c67135ba.
(In reply to Federico Mena Quintero from comment #0) ... > > Also, in that file, the marker for the lower-left corner of the path has the > wrong orientation. Unfotunately, the fix for the wrong orientation of the lower left marker is not correct, it is possible to see it inverting the orientation of the path: <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 128 64"> <marker id="marker" viewBox="0 -1 4 2" orient="auto"> <path fill="#080" d="M 0 -1 L 4 0 0 1" /> </marker> <g marker-mid="url(#marker)" marker-end="url(#marker)"> <path stroke-width="4" stroke="red" fill="none" d="M12,12h40v40h-40z"/> <path stroke-width="4" stroke="red" fill="none" d="M76,12v40h40v-40z"/> </g> </svg> The problem is computing the bisector of the two tangent vectors, when the difference of the two angles is > M_PI or < -M_PI averaging the 2 angles gives the direction of the inverted bisector. Something like this seems to work: diff --git a/rust/src/marker.rs b/rust/src/marker.rs index 10f2170..ec8572e 100644 --- a/rust/src/marker.rs +++ b/rust/src/marker.rs @@ -308,10 +308,6 @@ fn angle_from_vector (vx: f64, vy: f64) -> f64 { if angle.is_nan () { 0.0 } else { - while angle < 0.0 { - angle += f64::consts::PI * 2.0; - } - angle } } @@ -454,7 +450,16 @@ pub extern fn rsvg_render_markers (ctx: *mut RsvgDrawingCtx, let angle: f64; if has_incoming && has_outgoing { - angle = (incoming + outgoing) / 2.0; + use std::f64::consts::*; + let half_delta: f64; + + half_delta = (outgoing - incoming) * 0.5; + + if FRAC_PI_2 < half_delta.abs () { + angle = incoming + half_delta - PI; + } else { + angle = incoming + half_delta; + } } else if has_incoming { angle = incoming; } else if has_outgoing {
Good catch, and thanks for the patch! I've integrated it in commit 11d99a03757473c6bd10ca6837cf027975131d45. I've also added some tests for angle bisection, so that we can catch problems there before they hit the actual rendering. There is one final problem from your example image in comment #3 - we do not compute the marker's angle correctly in the closepath vertex: https://www.w3.org/TR/SVG/painting.html#OrientAttribute I'll file a bug for that. (If you find any other cases where the angle bisection is broken, please file a different bug.)
Filed the closepath problem as https://bugzilla.gnome.org/show_bug.cgi?id=777854