Bug 159340 - Drawing an <img> with an SVG source into a <canvas> has incorrect rendering if the SVG viewBox does not match the <img> metrics
Summary: Drawing an <img> with an SVG source into a <canvas> has incorrect rendering i...
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: WebKit Nightly Build
Hardware: All All
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2016-07-01 02:47 PDT by Antoine Quint
Modified: 2022-09-22 15:45 PDT (History)
6 users (show)

See Also:


Attachments
Testcase (1.12 KB, text/html)
2016-07-01 02:47 PDT, Antoine Quint
no flags Details
Testcase with setTimeout (1.37 KB, text/html)
2016-07-07 13:42 PDT, Said Abou-Hallawa
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Antoine Quint 2016-07-01 02:47:44 PDT
Created attachment 282532 [details]
Testcase

See the attached testcase. In it 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.

Chrome behaves the same as us and Firefox draws black only.

There was a recent source change to improve this with https://bugs.webkit.org/show_bug.cgi?id=159276, but it seems it doesn't quite cover all cases.
Comment 1 Radar WebKit Bug Importer 2016-07-01 02:47:57 PDT
<rdar://problem/27127786>
Comment 2 Antoine Quint 2016-07-01 02:56:25 PDT
Chromium bug: https://bugs.chromium.org/p/chromium/issues/detail?id=625096.
Comment 3 Antoine Quint 2016-07-01 02:58:37 PDT
Interestingly, this always works with WK1.
Comment 4 Antoine Quint 2016-07-01 03:07:46 PDT
The size of the container for the SVGImage is coming from this line in CanvasRenderingContext2D::drawImage(HTMLImageElement&, const FloatRect&, const FloatRect&, const CompositeOperator&, const BlendMode&, ExceptionCode&):

    FloatRect imageRect = FloatRect(FloatPoint(), size(imageElement, ImageSizeBeforeDevicePixelRatio));

In the WK1 case, when SVGImageCache::imageSizeForRenderer() is eventually called, it finds an `image` which has clearly already been laid out and has a 100x100 size, which is used to size the container.

In the WK2 case, SVGImageCache::imageSizeForRenderer() does not find an image and returns the intrinsic size instead, which is 200x200.
Comment 5 Antoine Quint 2016-07-01 03:12:05 PDT
If the <img> element is not added to the DOM, the failure also occurs on WK1.
Comment 6 Antoine Quint 2016-07-01 08:58:14 PDT
The Chromium bug is a WONTFIX as the behaviour is as spec'd, see discussion in https://bugs.chromium.org/p/chromium/issues/detail?id=625096. It looks like on WK2 we're doing the right thing, while on WK1 we're not, and not the other way around as previously thought.

Basically, when drawing an <img> which points to an SVG image in a <canvas>, the size of the <img> is irrelevant. If the <svg> element specifies width/height attributes, then those should be used as the source image size, otherwise the size should be computed based on the SVG image's aspect ratio based on the viewBox attribute and the size of the <canvas> image.

I'll do a pass through our tests to check that we're correctly implementing this.
Comment 7 Said Abou-Hallawa 2016-07-07 13:42:10 PDT
Created attachment 283040 [details]
Testcase with setTimeout

The rendering can be different in WK2 when calling drawImage() from setTimeout().
Comment 8 Ahmad Saleem 2022-09-22 15:45:55 PDT
All three browsers differ in the "test case" and "test case with setTimeout":

** Safari Technology Preview 154 ***

In second 200 * 200, it shows "full green" circle. Same for other test in both squares / boxes.

*** Chrome Canary 108 ***

In second 200 * 200, it shows "1/4 green" circle (kind of arc). Same for other test in both squares / boxes.

*** Firefox Nightly 107 ***

In second 200 * 200, it shows "complete black" with no green circle. Same for other test in both squares / boxes.

______

Just wanted to share updated testing results. Thanks!