Bug 1247218 - Should consider CSS transform when using non-scaling-stroke r=longsonr

We remove initial x/y offset for nsSVGUtils::GetTransformMatrixInUserSpace
so that it can be used in not-nondisplay context. Previously it was only
used in nondisplay context, where x/y offset is always 0.

Then we use this utility to get the transform matrix to judge whether we need
special care for non-scaling-stroke. The old matrix doesn't account for CSS
transform.

Differential Revision: https://phabricator.services.mozilla.com/D28193

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-04-20 02:04:52 +00:00
Родитель 2bc9b8f0bc
Коммит f48d16aaf5
4 изменённых файлов: 26 добавлений и 13 удалений

Просмотреть файл

@ -162,6 +162,7 @@ fuzzy-if(d2d&&layersGPUAccelerated,0-3,0-1200) == dynamic-rect-02.svg dynamic-re
== dynamic-stroke-01.svg pass.svg
== dynamic-stroke-opacity-01.svg pass.svg
== dynamic-stroke-width-01.svg pass.svg
== test_bug1247218.html test_bug1247218-ref.html
== dynamic-switch-01.svg pass.svg
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == dynamic-text-01.svg dynamic-text-01-ref.svg # bug 1392106
fuzzy-if(d2d&&layersGPUAccelerated,0-3,0-12739) == dynamic-text-02.svg dynamic-text-02-ref.svg # bug 776038 for Win7, Win8

Просмотреть файл

@ -0,0 +1,3 @@
<svg style="width: 500px; height: 500px; border: 1px solid green;">
<rect id="square" transform="translate(100,200) scale(1,2.5)" stroke="blue" vector-effect="non-scaling-stroke" stroke-width="6" x="50px" y="50px" width="50px" height="50px" fill="pink" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 265 B

Просмотреть файл

@ -0,0 +1,8 @@
<style>
#square{
transform: translate(100px,200px) scale(1,2.5);
}
</style>
<svg style="width: 500px; height: 500px; border: 1px solid green;">
<rect id="square" stroke="blue" vector-effect="non-scaling-stroke" stroke-width="6" x="50px" y="50px" width="50px" height="50px" fill="pink" />
</svg>

Просмотреть файл

@ -1248,13 +1248,12 @@ bool nsSVGUtils::GetNonScalingStrokeTransform(nsIFrame* aFrame,
return false;
}
nsIContent* content = aFrame->GetContent();
MOZ_ASSERT(content->IsSVGElement(), "bad cast");
MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "should be an SVG element");
*aUserToOuterSVG = ThebesMatrix(
SVGContentUtils::GetCTM(static_cast<SVGElement*>(content), true));
nsSVGOuterSVGFrame* outer = nsSVGUtils::GetOuterSVGFrame(aFrame);
*aUserToOuterSVG = nsSVGUtils::GetTransformMatrixInUserSpace(aFrame, outer);
return !aUserToOuterSVG->IsIdentity();
return aUserToOuterSVG->HasNonTranslation();
}
// The logic here comes from _cairo_stroke_style_max_distance_from_path
@ -1705,19 +1704,21 @@ gfxMatrix nsSVGUtils::GetTransformMatrixInUserSpace(const nsIFrame* aFrame,
"Only use this wrapper for SVG elements");
Matrix mm;
auto trans = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor);
auto trans = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestor,
nsIFrame::IN_CSS_UNITS);
trans.ProjectTo2D();
trans.CanDraw2D(&mm);
gfxMatrix ret = ThebesMatrix(mm);
float devPixelPerCSSPixel = float(AppUnitsPerCSSPixel()) /
aFrame->PresContext()->AppUnitsPerDevPixel();
float initPositionX = NSAppUnitsToFloatPixels(aFrame->GetPosition().x,
AppUnitsPerCSSPixel()),
initPositionY = NSAppUnitsToFloatPixels(aFrame->GetPosition().y,
AppUnitsPerCSSPixel());
// The matrix obtained by nsIFrame::GetTransformMatrix is "from
// device space to device space", we need to change it to be "from
// user space to user space".
ret.PreScale(devPixelPerCSSPixel, devPixelPerCSSPixel);
ret.PostScale(1.f / devPixelPerCSSPixel, 1.f / devPixelPerCSSPixel);
// Remove the initial displacement to mimic the behavior
// of SVGElement::PrependLocalTransformsTo().
ret = ret.PreTranslate(-initPositionX, -initPositionY);
return ret;
}