You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is currently an interop issue when drawing an SVG image to a canvas regarding the scaling operation.
Let source_image be a detached HTMLImageElement with no width nor height attributes pointing to an SVG document whose root <svg> element has <svg width="100" height="100" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"...
Then let's draw this image in a way it should get scaled non-uniformly on a target canvas
Note that we use an SVG image with intrinsic width and height, and that we do define the source rectangle of drawImage to avoid more interop issues.
Firefox will render it as if it was rendered in an <img width="350" height="100"> element, i.e they will respect the preserveAspectRatio rule and draw our 100x100 graphic unscaled in the middle of the dest_rect.
Chrome on the other hand will treat it as a two pass rendering, as if they were first drawing source_image as a bitmap using the SVG's intrinsic size1 and then stretching that bitmap to dest_rect, except that they don't really do that in order to keep the drawings sharp. So in this browser, we end up with our graphic stretched to the dest_rect, completely ignoring the svg's preserveAspectRatio.
Safari apparently takes the source <img> element as image, which would be against what CanvasImageSource says. So in this exact case, they'll stretch it like Chrome but with all the antialias artifacts, and if the <img> has a width and height on its own (even if set only through CSS) they'll pass what's rendered in that <img> to drawImage(). [fiddle].
If we try to find what the specs have to say, we have in drawImage
Paint the region of the image argument specified by the source rectangle on the region of the rendering context's output bitmap specified by the destination rectangle, after applying the current transformation matrix to the destination rectangle.
Both interpretations sound possible here. We need to check what image really means and in what state it is: if it doesn't have a size yet, SVG's viewBox and preserveAspectRatio probably can't be used and the SVG doesn't have a viewport, which means it's in an undefined state.
Trying to go back to what is this "image argument" leads to CanvasImageSource which states
When a CanvasImageSource object represents an HTMLOrSVGImageElement, the element's image must be used as the source image.
And then going to HTMLImageElement, there doesn't seem to be anything specifying in which state is an "image" representing a vector graphic, so it's hard to tell who's right.
FWIW, as a web-author I was assuming Firefox's behavior was the correct one because it made sense to me to have the dest_rect act as the final host for the SVG image, but that was before I read the drawImage specs... Now I just don't know anymore.
I've come across this while looking through canvas issues. The SVG issue highlights the underlying conflict here: Should the canvas drawImage behavior respect the SVG image author's request or the canvas author's request. I find these two arguments in favor of the canvas author to be rather compelling:
If the canvas is drawing 3rd party images, an end user would not expect scaling behavior to change between a PNG and an SVG given as the image to draw.
It is possible to achieve any desired result with canvas src and dest rect settings, but not possible to do so if the browser forces the SVG aspect ratio. In particular, I think a canvas author setting up a CanvasImageSource from an element, can determine if it's SVG and if it has a preserveAspectRatio (not so sure about this bit) and so on. Then choose to respect it in the scr/dest rectangles.
In other words, I believe we could update the spec to say that the preserveAspectRatio in SVG-as-image used as a canvas source respects the aspect ratio in determining the source intrinsic dimensions but not when mapping to the dest.
There is currently an interop issue when drawing an SVG image to a canvas regarding the scaling operation.
Let
source_image
be a detached HTMLImageElement with nowidth
norheight
attributes pointing to an SVG document whose root <svg> element has<svg width="100" height="100" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"...
Then let's draw this image in a way it should get scaled non-uniformly on a target canvas
https://jsfiddle.net/z5a89mqh/
Note that we use an SVG image with intrinsic width and height, and that we do define the source rectangle of
drawImage
to avoid more interop issues.<img width="350" height="100">
element, i.e they will respect thepreserveAspectRatio
rule and draw our 100x100 graphic unscaled in the middle of the dest_rect.source_image
as a bitmap using the SVG's intrinsic size1 and then stretching that bitmap to dest_rect, except that they don't really do that in order to keep the drawings sharp. So in this browser, we end up with our graphic stretched to the dest_rect, completely ignoring the svg'spreserveAspectRatio
.<img>
element as image, which would be against what CanvasImageSource says. So in this exact case, they'll stretch it like Chrome but with all the antialias artifacts, and if the<img>
has a width and height on its own (even if set only through CSS) they'll pass what's rendered in that<img>
todrawImage()
. [fiddle].If we try to find what the specs have to say, we have in
drawImage
Both interpretations sound possible here. We need to check what image really means and in what state it is: if it doesn't have a size yet, SVG's
viewBox
andpreserveAspectRatio
probably can't be used and the SVG doesn't have a viewport, which means it's in an undefined state.Trying to go back to what is this "image argument" leads to CanvasImageSource which states
And then going to HTMLImageElement, there doesn't seem to be anything specifying in which state is an "image" representing a vector graphic, so it's hard to tell who's right.
FWIW, as a web-author I was assuming Firefox's behavior was the correct one because it made sense to me to have the dest_rect act as the final host for the SVG image, but that was before I read the
drawImage
specs... Now I just don't know anymore.The text was updated successfully, but these errors were encountered: