Bug 77719 - SVG Pattern doesn't consider viewport transform for image size
Summary: SVG Pattern doesn't consider viewport transform for image size
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL: http://srufaculty.sru.edu/david.daile...
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2012-02-02 23:03 PST by Dirk Schulze
Modified: 2022-11-03 15:34 PDT (History)
8 users (show)

See Also:


Attachments
Pattern on patter in inner SVG (519 bytes, image/svg+xml)
2012-02-02 23:03 PST, Dirk Schulze
no flags Details
Pattern on patter in inner SVG (560 bytes, image/svg+xml)
2012-02-02 23:05 PST, Dirk Schulze
no flags Details
Safari 15.5 differs from other browsers (2.32 MB, image/png)
2022-07-10 12:30 PDT, Ahmad Saleem
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dirk Schulze 2012-02-02 23:03:48 PST
Created attachment 125265 [details]
Pattern on patter in inner SVG

SVG Pattern doesn't consider the transformation of the nearest viewport on calculating the size of the temp imageBuffer when referenced by another pattern.

The attached example is a reproduction of http://srufaculty.sru.edu/david.dailey/svg/recent/sliderzoom.svg

Note: the current pixelation does just occur if we use a inner SVG element with a viewBox.
Comment 1 Dirk Schulze 2012-02-02 23:05:35 PST
Created attachment 125267 [details]
Pattern on patter in inner SVG

Added wrong example.
Comment 2 Dirk Schulze 2012-02-03 19:29:55 PST
The culprit is SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem. But the description is longer:

We try to create pattern tiles in the screen coordinate space to avoid pixelation. Therefor we take the RenderObject of the element where we want to apply the pattern. After that we walk up the DOM Tree (render tree in reality) and consider all transformations on the road. That is done by applying all transformations (including the viewBox and transform of the pattern) to a intermediate transform. We use this transform to map the drawing rect of the tile and get the size that a tile would need on the screen.

This works almost all the time, almost. The attached example is different, since the patterns and the referenced object are in different viewports:

<svg	xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="500" >

<defs>
<pattern  id="P2" patternUnits="userSpaceOnUse" width="100%" height="100%">
  <rect width="100%" height="100%" fill="url(#P1)"/>
</pattern>

<pattern  id="P1" patternUnits="userSpaceOnUse" width="20" height="20">
  <circle id="S1" r="10" cx="10" cy="10" stroke="black" fill="pink" stroke-width="2" />
</pattern>
</defs>

<svg viewBox="0 0 100 100" preserveAspectRatio="none">
  <rect fill="url(#P2)" width="100%" height="100%"/>
</svg>
</svg>

The last rect in the example above is what we see on the screen. This rect gets filled with pattern P2.

P2 wants to get the tile size of the pattern. Therefor we take the object (the rect), and apply all transforms on the way up to the root. That means, we create a new AffineTransform, apply the transform of the rect (still identity matrix). After that we walk up the DOM and reach the inner SVG element. We apply the viewBox (similar to a transform) and walk up the DOM. We reach the root element and apply the transform of the root element.

For P2 we get the correct size of the tile. But the rect in pattern P2 uses a pattern P1 as well. The new pattern will take this rect to calculate the transform. The problem is, that this rect is not in the viewport of the target element. Therefor we don't apply the transform of the inner SVG on the way up of the DOM.

This ends up in the pixelation. We still need to consider the rect in the pattern, it's transform as well as the transform of the pattern. Afterwards we need the transform of the rect element, the transform of the inner SVG and at the end the root transform.
Comment 3 Nikolas Zimmermann 2012-02-04 08:52:39 PST
(In reply to comment #2)
> The culprit is SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem. But the description is longer:
The currentContentTransformation() is used to support nested masks with different view ports, maybe it can be used here as well? I'm not sure I fully understood your analysis, without tracing through the code on my own, so I'm rather guessing here.
Comment 4 Ahmad Saleem 2022-07-10 12:30:39 PDT
Created attachment 460784 [details]
Safari 15.5 differs from other browsers

I am able to reproduce pixelation in attached test case using Safari 15.5 on macOS 12.4 and Safari Technical Preview 148.

Other browser does not have pixelation as bad as Safari, Chrome Canary is not as sharp as Firefox Nightly but it is still better than Safari. Please refer to attached screenshot for all browser behavior. Thanks!
Comment 5 Radar WebKit Bug Importer 2022-11-03 15:34:53 PDT
<rdar://problem/101934285>