Drawing an <img> with an SVG source into a <canvas> has incorrect rendering if the SVG viewBox does not match the <img> metrics
Reported by
anto...@graougraou.com,
Jul 1 2016
|
||
Issue description
Chrome Version : Version 51.0.2704.103 (64-bit)
URLs (if applicable) :
Other browsers tested:
Safari: FAIL
Firefox: FAIL
What steps will reproduce the problem?
(1) Load the attached test case
What is the expected result?
A green circle is fully drawn onto the <canvas> element.
What happens instead?
Only part of it is drawn.
In the testcase we have an SVG image which has viewBox="0 0 200 200" and a <circle> with its top left corner located at 40,40 and sized to be 120x120. That SVG image is set as the src of an <img> element which is sized to be 100x100 by calling new Image(100, 100). Then we draw the <img> into a <canvas> sized to be 200x200 with a call to drawImage(image, 20, 20, 60, 60, 0, 0, width, height). Since the SVG image is scaled to be 0.5x its intrinsic size, drawing from a source of 20,20 and 60x60 should be a perfect match for the circle metrics but the output doesn't match, except very rarely when the image draws correctly.
WebKit ToT behaves the same as Chrome, Firefox draws black only.
This bug is tracked for WebKit at https://bugs.webkit.org/show_bug.cgi?id=159340.
,
Jul 1 2016
But the sx, sy, sw and sh parameters are provided. Unless the first sentence of this paragraph has no relationship to the second.
,
Jul 1 2016
Yes, they are provided, but what are they relative too - i.e what is the "full size" of the source image? This also comes into play in: "When the source rectangle is outside the source image, the source rectangle must be clipped to the source image..." In https://html.spec.whatwg.org/multipage/scripting.html#image-sources-for-2d-rendering-contexts it says: "When a CanvasImageSource object represents an HTMLOrSVGImageElement, the element's image must be used as the source image." and "When a CanvasImageSource object represents an element that is being rendered and that element has been resized, the original image data of the source image must be used, not the image as it is rendered (e.g. width and height attributes on the source element have no effect on how the object is interpreted when rendering the image for CanvasRenderingContext2D APIs)." Which I interpret as HTMLImageElement.width/height should not be considered here, and hence we use the "Concrete Object Size Resolution" algorithm, which, I believe would yield source image dimensions 200x200.
,
Jul 1 2016
So with an SVG image as the source of an <img>, then the intrinsic size of an SVG image should be used at all times? That seems kind of odd to me since the use of SVG to draw into a canvas is appealing for authors because they can have the image scaled to fit any element size.
,
Jul 1 2016
If I read the description correctly, it seems to be assumed that the viewBox should give an external coordinate system. It does not. It only defines the internal coordinate system and the aspect ratio of the SVG image, in case width and height information is missing. As fs writes, the SVG in this case will be sized to the canvas size (200x200 as it has 1:1 aspect ratio) and the source coordinates will be relative to this resolved image size. The 100x100 size is not used (it's mapped to width&height attributes and does not contribute to the intrinsic size). I agree this is not super intuitive, but as far I can tell it's working as expected according to the specs.
,
Jul 1 2016
So if the canvas was sized to be 500x500, the SVG would be sized to match and be 500x500 as well, taking the size of the canvas as the size to render into? Antoine
,
Jul 1 2016
In particular case (no intrinsic dimensions), yes.
,
Jul 1 2016
Great. But if the root <svg> element provided width/height attributes, then it would be a different story. I guess the rendering is perfectly valid then!
,
Jul 1 2016
Well, "as specified" at least ;-) |
||
►
Sign in to add a comment |
||
Comment 1 by f...@opera.com
, Jul 1 2016Components: Blink>Canvas Blink>SVG