drawImage() fails silently when drawing an SVG image without @width or @height
Categories
(Core :: SVG, defect)
Tracking
()
Tracking | Status | |
---|---|---|
firefox120 | --- | fixed |
People
(Reporter: sephr, Assigned: dlrobertson)
References
(Blocks 1 open bug, )
Details
(Keywords: webcompat:platform-bug)
Attachments
(7 files, 1 obsolete file)
![]() |
||
Comment 1•13 years ago
|
||
Comment 2•13 years ago
|
||
Comment 3•13 years ago
|
||
Comment 4•13 years ago
|
||
Comment 5•13 years ago
|
||
Comment 6•13 years ago
|
||
Updated•13 years ago
|
Comment 7•12 years ago
|
||
Comment 8•12 years ago
|
||
Comment 9•12 years ago
|
||
Comment 10•12 years ago
|
||
Comment hidden (me-too) |
Comment 12•10 years ago
|
||
Comment 13•10 years ago
|
||
Comment 14•10 years ago
|
||
Comment 15•10 years ago
|
||
Comment 16•10 years ago
|
||
Comment 17•10 years ago
|
||
Comment 18•10 years ago
|
||
Comment 19•10 years ago
|
||
Comment 21•9 years ago
|
||
Comment hidden (me-too) |
Comment 24•8 years ago
|
||
Updated•8 years ago
|
Updated•8 years ago
|
Comment 25•8 years ago
|
||
Comment 26•8 years ago
|
||
Comment 27•8 years ago
|
||
Comment 28•8 years ago
|
||
Comment 29•8 years ago
|
||
Comment hidden (off-topic) |
Comment hidden (obsolete) |
Comment hidden (obsolete) |
Comment hidden (off-topic) |
Comment hidden (off-topic) |
Comment 39•6 years ago
|
||
Here is a workaround where you can use the built SVG document to set the width/heights.
const svgDocument = new DOMParser().parseFromString(atob(base64EncodedSVG), "image/svg+xml");
svgDocument.documentElement.width.baseVal.valueAsString = svgDocument.documentElement.width.baseVal.value.toString();
svgDocument.documentElement.height.baseVal.valueAsString = svgDocument.documentElement.height.baseVal.value.toString();
base64EncodedSVG = btoa(new XMLSerializer().serializeToString(svgDocument));
This works because the document knows it should be 100% (default in valueAsString) and it calculates the value correctly from the viewBox in baseVal.value.
So it's quite weird that it doesn't "just work" without this silly workaround.
Comment hidden (advocacy) |
Comment 41•6 years ago
|
||
Firefox own SVGDocument knows the value to use since it exposes the correct value in width.baseVal.value. So they follow the other browsers there.
So different stances within the browser...
Comment 43•5 years ago
|
||
Why doesn't this work with the overload specifying a size, i.e. drawImage(img, 0, 0, width, height)? Surely that size could then be used as the box size to display the SVG in, and then there is at least a workaround for drawing SVGs to a canvas. Is that the same as this bug or is it a different case?
Comment hidden (me-too) |
Comment hidden (advocacy) |
Comment 47•4 years ago
|
||
This is affecting at least one site using canvas-based map software mapbox-gl in conjuction with SVG icons for markers, as can be seen in https://webcompat.com/issues/64352.
Comment hidden (advocacy) |
Updated•3 years ago
|
Comment 50•3 years ago
|
||
https://github.com/whatwg/html/issues/3510
(via https://github.com/CesiumGS/cesium/pull/9191, about to stance re: this issue)
![]() |
||
Updated•3 years ago
|
![]() |
||
Comment 51•3 years ago
|
||
Both square should be the same visible.
No red should be visible.
![]() |
||
Comment 52•3 years ago
|
||
- Gecko (Firefox) Red
- Blink (Edge), WebKit (Safari) Green
Updated•2 years ago
|
Comment 57•2 years ago
|
||
The severity field for this bug is relatively low, S3. However, the bug has 11 duplicates and 13 votes.
:jwatt, could you consider increasing the bug severity?
For more information, please visit auto_nag documentation.
Comment 58•2 years ago
|
||
The last needinfo from me was triggered in error by recent activity on the bug. I'm clearing the needinfo since this is a very old bug and I don't know if it's still relevant.
Updated•2 years ago
|
Comment 60•2 years ago
|
||
Hi! I can confirm this bug is still present in Firefox 110. I've just ran into it when trying to visit the site of an official state bank from Argentina: https://github.com/webcompat/web-bugs/issues/118373
Could the severity of this bug be risen? There are several examples of it preventing the normal functioning of a site.
Comment 61•2 years ago
|
||
I made an overview of how browsers handle different SVGs with/without width and height specifiers: https://codepen.io/atjn/full/GRyMWvZ
AFAICT the only major issue is this issue in Firefox. It is a major pain point because drawImage
is the best method of taking an unknown user image and sanitizing it to a known format, but there are many SVGs that only have a viewBox, making them completely impossible to import with this method.
Here is another website that this is affecting: https://github.com/webcompat/web-bugs/issues/101816
Comment 62•2 years ago
|
||
I made an overview of how browsers handle different SVGs with/without width and height specifiers: https://codepen.io/atjn/full/GRyMWvZ
That's a really helpful/thorough testcase, thanks!
Could the severity of this bug be risen? There are several examples of it preventing the normal functioning of a site.
Yeah, let's bump this to S2 at this point... It's been accumulating webcompat issues for a while. Let's try to get this prioritized and fixed/mitigated.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Comment 63•2 years ago
|
||
Did a little debugging of this today when I had some spare cycles and it looks like this is actually due to us not handling percent values in GetHeight
/GetWidth
for SVG images. We currently exit early and fail here and here if the width is a percent value (we do the same for height). This comment and bug 1112533 (comment 3) shed some further light on this.
Assignee | ||
Comment 64•2 years ago
|
||
Do not return a failure for the image height or width when the intrinsic size of
an SVG is a percent value. We now return a value calculated by returning the
percent of the containing block height or width.
Comment 65•2 years ago
|
||
Here's a test to exercise various options with width
, height
, and viewBox
on SVG drawn to canvas.
Comment 66•2 years ago
|
||
Updated•2 years ago
|
Comment 67•2 years ago
|
||
Looking at "megatest 2":
Firstly, all browsers agree on the final row. i.e. if the <svg> width and height attributes are both present and both pixel-valued (the final row of the testcase), then all browsers use those as the intrinsic size.
For the other rows (where width or height are missing or percent-valued): WebKit renders all of those rows the same (though not quite the same as they render the final row).
Summing up their behavior:
- If the SVG image has a missing or percent-valued width or height attribute, then WebKit ignores the width and height attributes entirely, and instead looks at the viewBox, using the width and height components (both of them) from the viewBox as an intrinsic size. (as can be seen in 2nd and 3rd column of this testcase, which have two different viewBox options)
- If the viewBox is missing (as in the first column of this testcase), WebKit just uses the fallback 300x150 replaced element intrinsic size.
Comment 68•2 years ago
|
||
Comment 69•2 years ago
•
|
||
[side note: megatests 1 and 2 have a stray code-comment Will draw the image as 300x227
which is just copypasta that I forgot to delete; ignore it, sorry if it adds confusion when looking at those test sources]
So comparing Chrome on megatest 2 vs. 3 is interesting. Sorry if the following is confusing; it's a little bit stream-of-consciousness as I try to make sense of things.
There are two different sizes that the browser has to fill in, for each drawImage operation in these megatests:
(1) What size region of the <canvas>
should we draw the image into?
(2) What size should we use as the size for the SVG viewport, when rendering the SVG?
In megatest 3, the answer to question (1) is always 80x160 (hardcoded into the drawImage function-call as args).
In megatest 2, Chrome's answer to question (1) is the full [width,height] of the canvas, if the SVG image has a percent [width,height] -- though if there's a viewBox, Chrome instead seems to size the area-to-fill using the viewBox's aspect-ratio, scaled up to meet the edges of the canvas. (So for example, in the upper right corner of megatest 1, they don't draw any pink, i.e. nothing from outside of the viewBox).
And then as for question (2): if there's a pixel value in both axes, all browsers use that (and shrink the viewBox to fit it). Otherwise, Chrome just renders the viewBox itself. Or if there's no viewBox and a percent valued width or height, then Chrome resolves the percent value against the size that they arrived at for question (1). So for example in the first cell in the second-to-last row of megatest 2: Chrome uses the height of the canvas as the height of the area-to-be-drawn-into, and then it uses a viewport that's sized at 60% of that height, which then ends up meaning the square looks vertically-stretched when we actually draw the rendered SVG to fill the full canvas height.
Comment 70•2 years ago
•
|
||
The bottom line here is that things are pretty wildly non-interoperable for the edge cases.
The simplest thing to start out here might be to just use the fallback 300x150 size if the SVG image is missing either a pixel-valued width or height. I suspect that'll be easy, will make us match WebKit (so some interop improvement), and is probably good enough for common cases to work, as a quick fix to stop the pain here.
I think Chrome's more-nuanced behavior is probably what the spec actually calls for, though.
FWIW the relevant spec text here seems to be under Establish the source and destination rectangles as follows
in https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-drawimage-dev (dw/dh = destination width & height [omitted in megatests 1 and 2], sw/sh = source width and height [omitted in all tests here I think]. Quoting the spec, bold section being the most-relevant bit:
If not specified, the dw and dh arguments must default to the values of sw and sh, interpreted such that one CSS pixel in the image is treated as one unit in the output bitmap's coordinate space. If the sx, sy, sw, and sh arguments are omitted, then they must default to 0, 0, the image's intrinsic width in image pixels, and the image's intrinsic height in image pixels, respectively. If the image has no intrinsic dimensions, then the concrete object size must be used instead, as determined using the CSS "Concrete Object Size Resolution" algorithm, with the specified size having neither a definite width nor height, nor any additional constraints, the object's intrinsic properties being those of the image argument, and the default object size being the size of the output bitmap.
Assignee | ||
Comment 71•2 years ago
|
||
Thanks! This helps clear things up a lot... Still trying to digest it a bit, but things are definitely more clear.
(In reply to Daniel Holbert [:dholbert] from comment #70)
[...]
The simplest thing to start out here might be to just use the fallback 300x150 size if the SVG image is missing either a pixel-valued width or height. I suspect that'll be easy, will make us match WebKit (so some interop improvement), and is probably good enough for common cases to work, as a quick fix to stop the pain here.
Yeah, I think this is probably a good target for this bug.
I think Chrome's more-nuanced behavior is probably what the spec actually calls for, though.
Agreed.
FWIW the relevant spec text here seems to be under
Establish the source and destination rectangles as follows
in https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-drawimage-dev (dw/dh = destination width & height [omitted in megatests 1 and 2], sw/sh = source width and height [omitted in all tests here I think].
Nice! That does seem relevant.
Updated•2 years ago
|
Updated•2 years ago
|
Assignee | ||
Comment 72•2 years ago
|
||
Add tests for CanvasRenderingContext2D.drawImage() when the image to be drawn is
an SVG with no width or height attribute.
Depends on D176974
Assignee | ||
Comment 73•2 years ago
|
||
When computing the size of an image for CanvasRenderingContext2D.drawImage(),
use the default size of 300 x 150 if no width or height was given.
Depends on D182487
Updated•1 year ago
|
Comment 74•1 year ago
|
||
Comment on attachment 9331273 [details]
Bug 700533 - Do not use negative values to determine percentages for svg intrinsic sizes. r=dholbert
Revision D176974 was moved to bug 1853991. Setting attachment 9331273 [details] to obsolete.
Comment 75•1 year ago
|
||
Comment 76•1 year ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/88857e8df4e2
https://hg.mozilla.org/mozilla-central/rev/189a06036d6f
Comment 77•1 year ago
|
||
:dlrobertson is this something you want to mention in the Fx120 relnotes?
Assignee | ||
Comment 78•1 year ago
|
||
(In reply to Dianna Smith [:diannaS] from comment #77)
:dlrobertson is this something you want to mention in the Fx120 relnotes?
I don't think this is relnote worthy, since this is more of a bugfix, but if you think it is worthwhile, I'd be happy to add the relevant info.
Updated•6 months ago
|
Description
•