WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED WONTFIX
86010
.getTransformToElement doesn’t work correctly across embedded svg elements
https://bugs.webkit.org/show_bug.cgi?id=86010
Summary
.getTransformToElement doesn’t work correctly across embedded svg elements
wdih6m31071m
Reported
2012-05-09 13:16:05 PDT
Created
attachment 141004
[details]
Simple test case If .getTransformToElement() is called with target outside of element’s nearest viewport, the result doesn’t include any transformations that are applied to elements outside of element’s nearest viewport. In the example: <svg width="600px" height="500px" version="1.1" xmlns="
http://www.w3.org/2000/svg
"> <g transform="translate(30, 30)"> <!-- Webkit ignores this transform --> <svg width="150" height="150"> <rect id="rect" x="50" y="50" width="25px" height="25px" fill="gray"></rect> </svg> </g> </svg> Firefox (Gecko/20120508 Firefox/14.0a2), IE 9 (9.0.8112.16421) and Batik (1.7) all include the transform, producing following: matrix(1, 0, 0, 1, 30, 30) Webkit (Google Chrome 20.0.1123.4; 536.10 (@115920); Linux) and Opera 11.62 ignore the tranform, producing following: matrix(1, 0, 0, 1, 0, 0) Working example included in attachment.
Attachments
Simple test case
(1.41 KB, image/svg+xml)
2012-05-09 13:16 PDT
,
wdih6m31071m
no flags
Details
Complex test case (output to the console)
(3.23 KB, image/svg+xml)
2012-08-27 16:17 PDT
,
MH
no flags
Details
Complex test case -- output data
(7.49 KB, text/plain)
2012-08-27 16:28 PDT
,
MH
no flags
Details
View All
Add attachment
proposed patch, testcase, etc.
Nikolas Zimmermann
Comment 1
2012-05-10 00:00:14 PDT
Thanks for the testcase Denis, and the detailed analysis - I can confirm your findings with FF/Opera and WebKit at least. From the spec: SVGMatrix getTransformToElement(in SVGElement element) Returns the transformation matrix from the user coordinate system on the current element (after application of the ‘transform’ attribute, if any) to the user coordinate system on parameter element (after application of its ‘transform’ attribute, if any). The user agent should build a transformation from the passed in 'element' down to the elements where the method is called. Clearly we and Opera have a bug here: <svg width="600px" height="500px" version="1.1" xmlns="
http://www.w3.org/2000/svg
"> ... <g transform="translate(30, 30)"> <!-- this transformation is ignored by webkit --> <svg width="150" height="150"> <rect id="rect" x="50" y="50" width="25px" height="25px" fill="gray"></rect> </svg> </g> </svg> .. var m = document.getElementById("rect").getTransformToElement(document.documentElement); .. This should indeed build a transform that starts from the outermost <svg> down to the <rect> inside the inner <svg> element. We stop at the nearest viewport element instead, which is determined as the parent inner <svg> of the <rect>. It's obvious that our behavior violates the spec. You should consider filing a bug against Opera as well. CC'ing some Google/SVG folks who might be interested - this bug should be easy to fix.
Nikolas Zimmermann
Comment 2
2012-05-10 00:06:50 PDT
(In reply to
comment #1
)
> CC'ing some Google/SVG folks who might be interested - this bug should be easy to fix.
I couldn't resist: AffineTransform SVGLocatable::getTransformToElement(SVGElement* target, ExceptionCode& ec, StyleUpdateStrategy styleUpdateStrategy) { AffineTransform ctm = getCTM(styleUpdateStrategy); if (target && target->isStyledLocatable()) { AffineTransform targetCTM = static_cast<SVGStyledLocatableElement*>(target)->getCTM(styleUpdateStrategy); if (!targetCTM.isInvertible()) { ec = SVGException::SVG_MATRIX_NOT_INVERTABLE; return ctm; } ctm = targetCTM.inverse() * ctm; } return ctm; } We're calling getCTM() from getTransformTlElement, which uses SVGLocatable::computeCTM, with NearestViewportScope (aka. stop at the nearest viewport) - this is obviously wrong. AffineTransform SVGStyledLocatableElement::getCTM(StyleUpdateStrategy styleUpdateStrategy) { return SVGLocatable::computeCTM(this, SVGLocatable::NearestViewportScope, styleUpdateStrategy); } The fix is to use getScreenCTM in getTransformToElement, when computing the targetCTM - so it won't stop at the nearest viewport element. Obviously this needs more testing, in different scenarios of multiple nested inner <svgs>, including <use> on <svg>, etc. Anyone feels tempted? :-)
MH
Comment 3
2012-08-27 16:15:42 PDT
I wrote more detailed tests to precise the problem. It shows also screenCTM and matrix computing at different nested coordinate levels... Detailed test shows that every browser has its own problem, but at different places... :-( I will attach test case + results from FF, Opera and Chrome/Webkit. Some output matrixes are really crazy ;-) I spend too many time with this problem already ...to find strange problem in our web app, which works with complex SVG drawings... .getTransformToElement() and .getScreenCTM() are really essential functions for any SVG app. Please help.
MH
Comment 4
2012-08-27 16:17:30 PDT
Created
attachment 160848
[details]
Complex test case (output to the console)
MH
Comment 5
2012-08-27 16:28:35 PDT
Created
attachment 160853
[details]
Complex test case -- output data BUG IS MARKED by ===> This test also shows example transformation of point [100,100] using matrixes we get as output of .getScreenCTM() and .getTransformToElement(): ------------------- Chrome 13.0.782.220 / Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1 ------------------- Coordinate System LEVEL0 getScreenCTM(): 5, 0, 0, 5, 0, 0; point [100,100] in svg#level0 coordinate system -> transformed to screen pixels [500,500] getTransformToElement MATRIX: 1, 0, 0, 1, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to svg#level0 coordinate system [100,100] getScreenCTM(): 5, 0, 0, 5, 0, 0; point [100,100] in rect#level0rect coordinate system -> transformed to screen pixels [500,500] getTransformToElement MATRIX: 1, 0, 0, 1, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level0rect coordinate system [100,100] Coordinate System LEVEL1 getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in g#level1 coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to g#level1 coordinate system [49,45] getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in rect#level1rect coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level1rect coordinate system [49,45] getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in text#level1text coordinate system -> transformed to screen pixels [1010,1050] ===> getTransformToElement MATRIX: 5, 0, 0, 5, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to text#level1text coordinate system [500,500] !!BUG Coordinate System LEVEL2 getScreenCTM(): 5, 0, 0, 5, 10, 50; point [100,100] in svg#level2 coordinate system -> transformed to screen pixels [510,550] getTransformToElement MATRIX: 1, 0, 0, 1, -2, -10; point [100,100] in baseNode#level0 coordinate system -> transformed to svg#level2 coordinate system [98,90] getScreenCTM(): 5, 0, 0, 5, 10, 50; point [100,100] in rect#level2rect coordinate system -> transformed to screen pixels [510,550] ===> getTransformToElement MATRIX: 10, 0, 0, 10, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level2rect coordinate system [1000,1000] !!BUG ------------------- Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.10.289 Version/12.01 (Core 2.10.289) ------------------- Coordinate System LEVEL0 getScreenCTM(): 5, 0, 0, 5, 0, 0; point [100,100] in svg#level0 coordinate system -> transformed to screen pixels [500,500] getTransformToElement MATRIX: 1, 0, 0, 1, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to svg#level0 coordinate system [100,100] getScreenCTM(): 5, 0, 0, 5, 0, 0; point [100,100] in rect#level0rect coordinate system -> transformed to screen pixels [500,500] getTransformToElement MATRIX: 1, 0, 0, 1, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level0rect coordinate system [100,100] Coordinate System LEVEL1 getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in g#level1 coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to g#level1 coordinate system [49,45] getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in rect#level1rect coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level1rect coordinate system [49,45] getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in text#level1text coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to text#level1text coordinate system [49,45] Coordinate System LEVEL2 getScreenCTM(): 5, 0, 0, 5, 10, 50; point [100,100] in svg#level2 coordinate system -> transformed to screen pixels [510,550] getTransformToElement MATRIX: 1, 0, 0, 1, -2, -10; point [100,100] in baseNode#level0 coordinate system -> transformed to svg#level2 coordinate system [98,90] getScreenCTM(): 5, 0, 0, 5, 10, 50; point [100,100] in rect#level2rect coordinate system -> transformed to screen pixels [510,550] ===> getTransformToElement MATRIX: 10, 0, 0, 10, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level2rect coordinate system [1000,1000] !!BUG ------------------- FF 17.0a1 (2012-08-09) / Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:17.0) Gecko/17.0 Firefox/17.0 ------------------- Coordinate System LEVEL0 getScreenCTM(): 5, 0, 0, 5, 0, 0; point [100,100] in svg#level0 coordinate system -> transformed to screen pixels [500,500] getTransformToElement MATRIX: 1, 0, 0, 1, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to svg#level0 coordinate system [100,100] getScreenCTM(): 5, 0, 0, 5, 0, 0; point [100,100] in rect#level0rect coordinate system -> transformed to screen pixels [500,500] getTransformToElement MATRIX: 1, 0, 0, 1, 0, 0; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level0rect coordinate system [100,100] Coordinate System LEVEL1 getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in g#level1 coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to g#level1 coordinate system [49,45] getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in rect#level1rect coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level1rect coordinate system [49,45] getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in text#level1text coordinate system -> transformed to screen pixels [1010,1050] getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to text#level1text coordinate system [49,45] Coordinate System LEVEL2 ===>getScreenCTM(): 10, 0, 0, 10, 10, 50; point [100,100] in svg#level2 coordinate system -> transformed to screen pixels [1010,1050] !!BUG ===> getTransformToElement MATRIX: 0.5, 0, 0, 0.5, -1, -5; point [100,100] in baseNode#level0 coordinate system -> transformed to svg#level2 coordinate system [49,45] !!BUG getScreenCTM(): 5, 0, 0, 5, 10, 50; point [100,100] in rect#level2rect coordinate system -> transformed to screen pixels [510,550] getTransformToElement MATRIX: 1, 0, 0, 1, -2, -10; point [100,100] in baseNode#level0 coordinate system -> transformed to rect#level2rect coordinate system [98,90]
MH
Comment 6
2012-08-27 16:33:21 PDT
From the specs:
http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
Unlike the ‘transform’ attribute (see effect of the ‘transform’ on sibling attributes), the automatic transformation that is created due to a ‘viewBox’ does not affect the ‘x’, ‘y’, ‘width’ and ‘height’ attributes (or in the case of the ‘marker’ element, the ‘markerWidth’ and ‘markerHeight’ attributes) on the element with the ‘viewBox’ attribute... On the other hand, like the ‘transform’ attribute, it does establish a new coordinate system for all other attributes and for descendant elements. ******* all getScreenCTM() matrixes in the same Coordinate System must be identical ******* ******* all getTransformToElement() matrixes in the same Coordinate System must be identical *******
Russel Simmons
Comment 7
2013-05-23 02:03:34 PDT
For whatever it's worth, a workaround is to replace: fromElem.getTransformToElement(toElem) with: toElem.getScreenCTM().inverse().multiply(fromElem.getScreenCTM())
Brent Fulgham
Comment 8
2022-07-15 15:10:47 PDT
Expected result: matrix(1, 0, 0, 1, 30, 30) Chrome doesn't provide a result: ??? Firefox produces the correct result: matrix(1, 0, 0, 1, 30, 30) Safari fails to provide the correct results for the last two values of the matrix: matrix(1, 0, 0, 1, 0, 0)
Radar WebKit Bug Importer
Comment 9
2022-07-15 15:10:58 PDT
<
rdar://problem/97096747
>
Ahmad Saleem
Comment 10
2024-01-07 18:07:11 PST
As per below, 'getTransformToElement' was removed from web-spec:
https://lists.w3.org/Archives/Public/www-svg/2015Aug/att-0009/SVGWG-F2F-minutes-20150824.html#item02
and it was removed in below Blink commit:
https://chromium.googlesource.com/chromium/src.git/+/f7dafa91c1745acecc30c5cede04429163814a77
It is not in SVG2 specs:
https://svgwg.org/svg2-draft/
Additionally,
bug 204038
is about to remove this as well. I think we can close this since we might not fix and just remove it from support to align with SVG2 web-spec. Although curious about Firefox case as well. Marking it as 'RESOLVED WONTFIX' and CCing - few others, if they want to keep it open.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug