Bug 1533491 - nsCSSClipPathInstance::ApplyBasicShapeOrPathClip should consider transform r=longsonr

nsSVGUtils::PaintFrameWithEffects needs to pass its transform to
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip so that the latter
can compute the correct box.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
violet 2019-04-25 00:52:25 +00:00
Родитель 5f0b0bbe8e
Коммит 126058f55b
7 изменённых файлов: 48 добавлений и 15 удалений

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

@ -0,0 +1,6 @@
<svg style="width: 400px; height: 400px">
<mask id="m1">
<rect x="100" y="90" width="200" height="200" fill="blue" style="clip-path: inset(50px 50px)"></rect>
</mask>
<rect width="400" height="400" mask="url(#m1)"></rect>
</svg>

После

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

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

@ -0,0 +1,8 @@
<svg style="width: 400px; height: 400px">
<mask id="m1">
<g transform="translate(100,90)">
<rect width="200" height="200" fill="blue" style="clip-path: inset(50px 50px)"></rect>
</g>
</mask>
<rect width="400" height="400" mask="url(#m1)"></rect>
</svg>

После

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

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

@ -79,6 +79,7 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.[12]/
== clipPath-basic-06.svg pass.svg
== clipPath-basic-07.svg pass.svg
== clipPath-basic-08.svg pass.svg
== clipPath-basic-shape-transform.html clipPath-basic-shape-transform-ref.html
== clipPath-css-transform.html clipPath-css-transform-ref.html
== clipPath-on-outflowElement-01a.html clipPath-on-outflowElement-01-ref.html
== clipPath-on-outflowElement-01b.html clipPath-on-outflowElement-01-ref.html

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

@ -25,8 +25,8 @@ using namespace mozilla::dom;
using namespace mozilla::gfx;
/* static*/
void nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(gfxContext& aContext,
nsIFrame* aFrame) {
void nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(
gfxContext& aContext, nsIFrame* aFrame, const gfxMatrix& aTransform) {
auto& clipPathStyle = aFrame->StyleSVGReset()->mClipPath;
#ifdef DEBUG
@ -40,7 +40,8 @@ void nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(gfxContext& aContext,
nsCSSClipPathInstance instance(aFrame, clipPathStyle);
aContext.NewPath();
RefPtr<Path> path = instance.CreateClipPath(aContext.GetDrawTarget());
RefPtr<Path> path =
instance.CreateClipPath(aContext.GetDrawTarget(), aTransform);
aContext.SetPath(path);
aContext.Clip();
}
@ -61,7 +62,8 @@ bool nsCSSClipPathInstance::HitTestBasicShapeOrPathClip(
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<Path> path = instance.CreateClipPath(drawTarget);
RefPtr<Path> path = instance.CreateClipPath(
drawTarget, nsSVGUtils::GetCSSPxToDevPxMatrix(aFrame));
float pixelRatio = float(AppUnitsPerCSSPixel()) /
aFrame->PresContext()->AppUnitsPerDevPixel();
return path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix());
@ -78,19 +80,31 @@ Rect nsCSSClipPathInstance::GetBoundingRectForBasicShapeOrPathClip(
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<Path> path = instance.CreateClipPath(drawTarget);
RefPtr<Path> path = instance.CreateClipPath(
drawTarget, nsSVGUtils::GetCSSPxToDevPxMatrix(aFrame));
return path->GetBounds();
}
already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPath(
DrawTarget* aDrawTarget) {
DrawTarget* aDrawTarget, const gfxMatrix& aTransform) {
if (mClipPathStyle.GetType() == StyleShapeSourceType::Path) {
return CreateClipPathPath(aDrawTarget);
}
nscoord appUnitsPerDevPixel =
mTargetFrame->PresContext()->AppUnitsPerDevPixel();
nsRect r = nsLayoutUtils::ComputeGeometryBox(
mTargetFrame, mClipPathStyle.GetReferenceBox());
gfxRect rr(r.x, r.y, r.width, r.height);
rr.Scale(1.0 / AppUnitsPerCSSPixel());
rr = aTransform.TransformRect(rr);
rr.Scale(appUnitsPerDevPixel);
rr.Round();
r = nsRect(int(rr.x), int(rr.y), int(rr.width), int(rr.height));
if (mClipPathStyle.GetType() != StyleShapeSourceType::Shape) {
// TODO Clip to border-radius/reference box if no shape
// was specified.
@ -98,8 +112,6 @@ already_AddRefed<Path> nsCSSClipPathInstance::CreateClipPath(
return builder->Finish();
}
nscoord appUnitsPerDevPixel =
mTargetFrame->PresContext()->AppUnitsPerDevPixel();
r = ToAppUnits(r.ToNearestPixels(appUnitsPerDevPixel), appUnitsPerDevPixel);
const auto& basicShape = mClipPathStyle.BasicShape();

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

@ -7,10 +7,11 @@
#ifndef __NS_CSSCLIPPATHINSTANCE_H__
#define __NS_CSSCLIPPATHINSTANCE_H__
#include "gfxMatrix.h"
#include "gfxPoint.h"
#include "nsStyleStruct.h"
#include "nsRect.h"
#include "mozilla/gfx/2D.h"
#include "nsRect.h"
#include "nsStyleStruct.h"
class nsIFrame;
class gfxContext;
@ -23,7 +24,8 @@ class nsCSSClipPathInstance {
typedef mozilla::gfx::Rect Rect;
public:
static void ApplyBasicShapeOrPathClip(gfxContext& aContext, nsIFrame* aFrame);
static void ApplyBasicShapeOrPathClip(gfxContext& aContext, nsIFrame* aFrame,
const gfxMatrix& aTransform);
// aPoint is in CSS pixels.
static bool HitTestBasicShapeOrPathClip(nsIFrame* aFrame,
const gfxPoint& aPoint);
@ -36,7 +38,8 @@ class nsCSSClipPathInstance {
const StyleShapeSource& aClipPathStyle)
: mTargetFrame(aFrame), mClipPathStyle(aClipPathStyle) {}
already_AddRefed<Path> CreateClipPath(DrawTarget* aDrawTarget);
already_AddRefed<Path> CreateClipPath(DrawTarget* aDrawTarget,
const gfxMatrix& aTransform);
already_AddRefed<Path> CreateClipPathCircle(DrawTarget* aDrawTarget,
const nsRect& aRefBox);

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

@ -803,7 +803,8 @@ bool nsSVGIntegrationUtils::PaintMask(const PaintFramesParams& aParams) {
MoveContextOriginToUserSpace(firstFrame, aParams);
basicShapeSR.SetContext(&ctx);
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(ctx, frame);
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(ctx, frame,
nsSVGUtils::GetCSSPxToDevPxMatrix(frame));
if (!maskUsage.shouldGenerateMaskLayer) {
// Only have basic-shape clip-path effect. Fill clipped region by
// opaque white.
@ -995,7 +996,8 @@ void PaintMaskAndClipPathInternal(const PaintFramesParams& aParams,
if (maskUsage.shouldApplyClipPath) {
clipPathFrame->ApplyClipPath(context, frame, cssPxToDevPxMatrix);
} else {
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(context, frame);
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(context, frame,
cssPxToDevPxMatrix);
}
}

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

@ -757,7 +757,8 @@ void nsSVGUtils::PaintFrameWithEffects(nsIFrame* aFrame, gfxContext& aContext,
if (maskUsage.shouldApplyClipPath) {
clipPathFrame->ApplyClipPath(aContext, aFrame, aTransform);
} else {
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(aContext, aFrame);
nsCSSClipPathInstance::ApplyBasicShapeOrPathClip(aContext, aFrame,
aTransform);
}
}