Closed Bug 1591274 Opened 5 years ago Closed 5 years ago

Canvas drawimage error scale svg

Categories

(Core :: SVG, defect, P3)

70 Branch
defect

Tracking

()

RESOLVED WONTFIX

People

(Reporter: matias.kenig, Unassigned)

Details

Attachments

(2 files, 1 obsolete file)

Attached file canvas with svg bug.zip (obsolete) —

User Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36

Steps to reproduce:

1-open "test.htm"
2-wait to load the "test.svg" image.
3-look the result image scaled (its a bug),
4-compare with google chrome

Actual results:

The loaded svg IS NOT scaled into canvas

Expected results:

the loaded svg image MUST be scaled into canvas

Component: Untriaged → SVG
Product: Firefox → Core
Attachment #9104096 - Attachment is obsolete: true
Status: UNCONFIRMED → NEW
Ever confirmed: true
Priority: -- → P2

In this particular case the SVG has a viewBox and therefore an aspect ratio. We probably shouldn't allow canvas to override that. Our rendering is probably correct here. However I haven't checked what happens if the viewBox is removed.

Priority: P2 → P3
Flags: needinfo?(amelia.bellamy.royds)
Flags: needinfo?(amelia.bellamy.royds)

Hi Amelia, do you know if our behavior here is supported by the SVG and HTML specs, or if we need to add some wording?

Flags: needinfo?(amelia.bellamy.royds)

I don't think we have any specs that specifically talk about the intersection of SVG and canvas contexts. However, my expectation is that you would get the same rendering as if you drew the SVG as an HTML img with the specified width and height (750×200).

SVG was always defined in a way that worked for embedding in any rendering environment. The initial scale is determined by the rectangle the outer rendering system gives the SVG to draw itself in, regardless of how that rectangle is specified in the outer layout language. When such a rectangle is specified, it overrides the width and height attributes on the root element of the SVG file. Those attributes are only used as defaults for when the outer environment allows the embedded image to specify its own size or aspect ratio.

Since the SVG file specifies a square viewBox and doesn't specify a preserveAspectRatio behavior, I would expect the square aspect ratio to be maintained, with the image scaled to meet the rectangle given. I'd also expect the non-scaling-stroke to be respected (relative to the 750×200 dimensions: if you scale the canvas itself, that's another matter).

In other words, IMO, Firefox behavior is correct, Chrome behavior is buggy.

However…

Reading the current text of the SVG 2 spec, it's not so clear that this is true.

SVG 2 reference are the sections "The initial viewport" and "Intrinsic sizing properties of SVG content" in the Coordinates chapter: https://svgwg.org/svg2-draft/coords.html

Compare with the SVG 1.1 version of the same sections: https://www.w3.org/TR/SVG11/coords.html

In trying to be explicit about how SVG interacts with CSS layout, I think the wording has been made a little too specific for CSS layout, by talking specifically about HTML embedded objects and CSS-compatible properties on them. The current reading doesn't allow for non-CSS rendering environments (such as canvas drawImage() commands, or even CSS background image sizing) to override the default width and height on the SVG. In contrast, the SVG 1.1 version of the spec is much more general, and applies to any external layout constraints.

I am not aware of any intentional reasoning for this change, so I've filed a bug on the spec: https://github.com/w3c/svgwg/issues/762

In the meantime, if anyone does want the Chromium behavior:

You can get most of the way there by adding preserveAspectRatio="none" on the <svg> element in the file. That will cause the viewBox to stretch to whatever aspect ratio you give it. However, Firefox will still render the SVG at the pixel size you specify, and will properly maintain the non-scaling-stroke despite the stretched scale.

To completely replicate the Chromium behavior, you would need to draw the SVG image to a temporary canvas at its natural width and height, then use that bitmap rendering as a separate image input to the drawImage function with the distorted dimensions. (This is similar to a popular performance trick used to pre-render a batch of canvas API commands that you want to then reuse like an image sprite.)

Flags: needinfo?(amelia.bellamy.royds)

I think our implementation makes sense. Hopefully the SVG 2 specification will change back given that its current change seems somewhat unintentional.

Status: NEW → RESOLVED
Closed: 5 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: