Bug 1193586 - Fix scaling of patterns with viewBoxes that are not at the origin r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D176462
This commit is contained in:
Robert Longson 2023-04-26 08:48:01 +00:00
parent 973159afeb
commit 26b601bb79
5 changed files with 58 additions and 32 deletions

View File

@ -334,7 +334,7 @@ fuzzy(0-1,0-6400) == mask-type-04.svg mask-type-01-ref.svg
fuzzy(0-3,0-448000) == nesting-invalid-01.svg nesting-invalid-01-ref.svg
fuzzy(0-2,0-1000) == non-scaling-stroke-01.svg non-scaling-stroke-01-ref.svg # bug 1074161 for Win7 and OSX 10.8
fuzzy-if(gtkWidget,0-1,0-99) fuzzy-if(!contentSameGfxBackendAsCanvas,0-9,0-99) fuzzy-if(Android,0-9,0-586) fails-if(useDrawSnapshot) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
fuzzy(0-51,0-900) fuzzy-if(Android,0-51,0-4090) fails-if(useDrawSnapshot) == non-scaling-stroke-02.svg non-scaling-stroke-02-ref.svg
== non-scaling-stroke-03.svg non-scaling-stroke-03-ref.svg
== objectBoundingBox-and-clipPath.svg pass.svg
@ -392,15 +392,15 @@ fuzzy(0-1,0-400) == path-06.svg path-06-ref.svg
fuzzy(0-128,0-100) == pattern-big-image.html pattern-big-image-ref.html
== pattern-css-transform.html pattern-css-transform-ref.html
== pattern-invalid-01.svg pattern-invalid-01-ref.svg
fuzzy(0-1,0-5) == pattern-live-01a.svg pattern-live-01-ref.svg
fuzzy(0-1,0-5) == pattern-live-01b.svg pattern-live-01-ref.svg
fuzzy(0-1,0-5) == pattern-live-01c.svg pattern-live-01-ref.svg
== pattern-live-01a.svg pattern-live-01-ref.svg
== pattern-live-01b.svg pattern-live-01-ref.svg
== pattern-live-01c.svg pattern-live-01-ref.svg
== pattern-scale-01a.svg pattern-scale-01-ref.svg
== pattern-scale-01b.svg pattern-scale-01-ref.svg
== pattern-scale-01c.svg pattern-scale-01-ref.svg
== pattern-transform-presence-01.svg pattern-transform-presence-01-ref.svg
fuzzy(0-72,0-865) == pattern-transformed-01.svg pattern-transformed-01-ref.svg
fuzzy(0-27,0-7960) fuzzy-if(Android,0-28,0-11200) == pattern-transformed-02.svg pattern-transformed-02-ref.svg
== pattern-transformed-01.svg pattern-transformed-01-ref.svg
fuzzy(0-27,0-9058) == pattern-transformed-02.svg pattern-transformed-02-ref.svg
== polygon-01.svg polygon-01-ref.svg
== polygon-marker-01.svg pass.svg
@ -588,7 +588,7 @@ test-pref(svg.use-element.graphics-element-restrictions,1) ref-pref(svg.use-elem
== viewBox-and-pattern-01.svg pass.svg
== viewBox-and-pattern-02.svg pass.svg
fuzzy(0-43,0-5) == viewBox-and-pattern-03.svg pass.svg
== viewBox-and-pattern-03.svg pass.svg
== viewBox-and-pattern-04.svg pass.svg
== viewBox-and-symbol-01.svg pass.svg
== viewBox-invalid-01.svg pass.svg

View File

@ -186,7 +186,7 @@ fuzzy-if(winWidget,0-105,0-56) == clipPath-content.svg clipPath-content-ref.svg
fuzzy-if(winWidget,0-53,0-112) == clipPath-content-2.svg clipPath-content-2-ref.svg
# text and patterns
fuzzy(0-74,0-385) fuzzy-if(geckoview,0-49,0-1793) == pattern-content.svg pattern-content-ref.svg
== pattern-content.svg pattern-content-ref.svg
# text and filters
fuzzy-if(winWidget,0-126,0-336) == filter-applied.svg filter-applied-ref.svg

View File

@ -149,8 +149,10 @@ static bool IncludeBBoxScale(const SVGAnimatedViewBox& aViewBox,
// Given the matrix for the pattern element's own transform, this returns a
// combined matrix including the transforms applicable to its target.
static Matrix GetPatternMatrix(uint16_t aPatternUnits,
const Matrix& patternTransform,
static Matrix GetPatternMatrix(nsIFrame* aSource,
const StyleSVGPaint nsStyleSVG::*aFillOrStroke,
uint16_t aPatternUnits,
const gfxMatrix& patternTransform,
const gfxRect& bbox, const gfxRect& callerBBox,
const Matrix& callerCTM) {
// We really want the pattern matrix to handle translations
@ -162,12 +164,20 @@ static Matrix GetPatternMatrix(uint16_t aPatternUnits,
miny += callerBBox.Y();
}
float scale = 1.0f / MaxExpansion(callerCTM);
Matrix patternMatrix = patternTransform;
patternMatrix.PreScale(scale, scale);
double scale = 1.0 / MaxExpansion(callerCTM);
auto patternMatrix = patternTransform;
patternMatrix.PostScale(scale, scale);
patternMatrix.PreTranslate(minx, miny);
return patternMatrix;
// revert the vector effect transform so that the pattern appears unchanged
if (aFillOrStroke == &nsStyleSVG::mStroke) {
gfxMatrix userToOuterSVG;
if (SVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
patternMatrix *= userToOuterSVG;
}
}
return ToMatrix(patternMatrix);
}
static nsresult GetTargetGeometry(gfxRect* aBBox,
@ -280,31 +290,20 @@ already_AddRefed<SourceSurface> SVGPatternFrame::PaintPattern(
}
// Get the pattern transform
Matrix patternTransform = ToMatrix(GetPatternTransform());
// revert the vector effect transform so that the pattern appears unchanged
if (aFillOrStroke == &nsStyleSVG::mStroke) {
gfxMatrix userToOuterSVG;
if (SVGUtils::GetNonScalingStrokeTransform(aSource, &userToOuterSVG)) {
patternTransform *= ToMatrix(userToOuterSVG);
if (patternTransform.IsSingular()) {
NS_WARNING("Singular matrix painting non-scaling-stroke");
return nullptr;
}
}
}
auto patternTransform = GetPatternTransform();
// Get the transformation matrix that we will hand to the renderer's pattern
// routine.
*patternMatrix = GetPatternMatrix(patternUnits, patternTransform, bbox,
callerBBox, aContextMatrix);
*patternMatrix =
GetPatternMatrix(aSource, aFillOrStroke, patternUnits, patternTransform,
bbox, callerBBox, aContextMatrix);
if (patternMatrix->IsSingular()) {
return nullptr;
}
// Now that we have all of the necessary geometries, we can
// create our surface.
gfxSize scaledSize = bbox.Size() * MaxExpansion(patternTransform);
gfxSize scaledSize = bbox.Size() * MaxExpansion(ToMatrix(patternTransform));
bool resultOverflows;
IntSize surfaceSize =
@ -321,8 +320,8 @@ already_AddRefed<SourceSurface> SVGPatternFrame::PaintPattern(
if (resultOverflows || patternWidth != surfaceSize.width ||
patternHeight != surfaceSize.height) {
// scale drawing to pattern surface size
patternWithChildren->mCTM->PreScale(surfaceSize.width / patternWidth,
surfaceSize.height / patternHeight);
patternWithChildren->mCTM->PostScale(surfaceSize.width / patternWidth,
surfaceSize.height / patternHeight);
// and rescale pattern to compensate
patternMatrix->PreScale(patternWidth / surfaceSize.width,

View File

@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5669 5669" xmlns:html="http://www.w3.org/1999/xhtml">
<g id="testmeta">
<title>Pattern: viewBox with x offset</title>
<html:link rel="help"
href="https://www.w3.org/TR/SVG2/pservers.html#Patterns"/>
<html:link rel="match" href="reference/pattern-viewbox-01-ref.svg"/>
</g>
<pattern width="2258.997" height="1289.823" patternUnits="userSpaceOnUse" id="pattern"
viewBox="752.999 0 2258.997 1289.823" patternTransform="scale(0.5)">
<g transform="translate(0,1934.735)" fill="none" stroke="black" stroke-width="10">
<rect x="752.999" y="-1934.735" width="2258.997" height="1289.823"/>
<circle cx="1882.4975" cy="-1289.8235" r="644.9115"/>
</g>
</pattern>
<rect width="100%" height="100%" fill="url(#pattern)"/>
</svg>

After

Width:  |  Height:  |  Size: 832 B

View File

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 5669 5669">
<pattern width="2258.997" height="1289.823" patternUnits="userSpaceOnUse" id="pattern"
viewBox="0 0 2258.997 1289.823" patternTransform="scale(0.5)">
<g transform="translate(-752.999, 1934.735)" fill="none" stroke="black" stroke-width="10">
<rect x="752.999" y="-1934.735" width="2258.997" height="1289.823"/>
<circle cx="1882.4975" cy="-1289.8235" r="644.9115"/>
</g>
</pattern>
<rect width="100%" height="100%" fill="url(#pattern)"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B