Bug 534612 - clipPath references with clipPath elements do not work correctly. r=roc

This commit is contained in:
Robert Longson 2010-02-26 09:58:42 +00:00
Родитель 1d0a08e5af
Коммит 63e32ef130
3 изменённых файлов: 174 добавлений и 4 удалений

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

@ -0,0 +1,84 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<title>Testcase for clipPath referencing other clipPaths</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=534612 -->
<defs>
<clipPath id="clip1">
<rect id="r1" x="20" y="-40" width="100" height="40" />
</clipPath>
<clipPath id="clip2">
<rect x="20" y="20" width="100" height="100" clip-path="url(#clip1)" />
</clipPath>
<clipPath id="clip3">
<rect x="140" y="-40" width="100" height="40" />
</clipPath>
<clipPath id="clip4" clip-path="url(#clip3)">
<rect x="140" y="20" width="100" height="100" />
</clipPath>
<clipPath id="clip1">
<rect x="20" y="-40" width="100" height="40" />
</clipPath>
<clipPath id="clip5">
<rect id="r5" x="20" y="140" width="100" height="100" />
</clipPath>
<clipPath id="clip6">
<use xlink:href="#r5" clip-path="url(#clip5)" />
</clipPath>
<clipPath id="clip7">
<rect id="r7" x="140" y="140" width="100" height="100" />
</clipPath>
<clipPath id="clip8">
<use xlink:href="#r7" fill="red" clip-path="url(#clip1)"/>
</clipPath>
<clipPath id="clip9">
<rect x="20" y="260" width="100" height="100" />
</clipPath>
<clipPath id="clip10">
<use xlink:href="#r1" fill="red" clip-path="url(#clip9)"/>
</clipPath>
<clipPath id="clip11">
<rect id="r11" x="140" y="260" width="100" height="100" clip-path="url(#clip1)"/>
</clipPath>
<clipPath id="clip12">
<use xlink:href="#r11" fill="red" clip-path="url(#clip11)"/>
</clipPath>
<clipPath id="clip12" clipPathUnits="objectBoundingBox">
<rect width=".5" height=".5"/>
</clipPath>
<clipPath id="clip13" clip-path="url(#clip12)">
<circle cx="100" cy="470" r="150"/>
</clipPath>
<clipPath id="clip14">
<use xlink:href="#clip1"/>
</clipPath>
<clipPath id="clip15" clip-path="url(#clip14)">
<text x="140" y="500" font-size="100px">CLIP</text>
</clipPath>
</defs>
<rect width="100%" height="100%" fill="lime" />
<!-- clip path where an object is itself clipped -->
<rect x="20" y="20" width="100" height="100" fill="red" clip-path="url(#clip2)" />
<!-- clip path referencing another clip-path -->
<rect x="140" y="20" width="100" height="100" fill="red" clip-path="url(#clip4)" />
<!-- clip paths where object has complex clipping -->
<rect x="20" y="140" width="100" height="100" fill="red" />
<rect x="20" y="140" width="100" height="100" fill="lime" clip-path="url(#clip6)" />
<rect x="140" y="140" width="100" height="100" fill="red" clip-path="url(#clip8)" />
<rect x="20" y="260" width="100" height="100" fill="red" clip-path="url(#clip10)" />
<rect x="140" y="260" width="100" height="100" fill="red" clip-path="url(#clip12)" />
<!-- clip paths with different clipPathUnits -->
<rect x="20" y="400" height="300" width="300" fill="red" clip-path="url(#clip13)" />
<rect x="20" y="400" width="100" height="100" fill="lime" />
<!-- text clipping -->
<rect x="140" y="400" height="300" width="300" fill="red" clip-path="url(#clip15)" />
</svg>

После

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

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

@ -19,6 +19,7 @@ include svg-integration/reftest.list
== clip-01.svg pass.svg
== clip-02a.svg clip-02-ref.svg
== clip-02b.svg clip-02-ref.svg
== clipPath-advanced-01.svg pass.svg
== clipPath-and-shape-rendering-01.svg clipPath-and-shape-rendering-01-ref.svg
== clipPath-basic-01.svg pass.svg
== clipPath-winding-01.svg pass.svg

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

@ -40,6 +40,7 @@
#include "nsSVGClipPathFrame.h"
#include "nsGkAtoms.h"
#include "nsSVGUtils.h"
#include "nsSVGEffects.h"
#include "nsSVGClipPathElement.h"
#include "gfxContext.h"
#include "nsSVGMatrix.h"
@ -69,7 +70,7 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
}
AutoClipPathReferencer clipRef(this);
mClipParent = aParent,
mClipParent = aParent;
mClipParentMatrix = NS_NewSVGMatrix(aMatrix);
PRBool isTrivial = IsTrivial();
@ -78,6 +79,23 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
isTrivial ? nsSVGRenderState::CLIP
: nsSVGRenderState::CLIP_MASK);
gfxContext *gfx = aContext->GetGfxContext();
PRBool isOK = PR_TRUE;
nsSVGClipPathFrame *clipPathFrame =
nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(&isOK);
PRBool referencedClipIsTrivial;
if (clipPathFrame) {
referencedClipIsTrivial = clipPathFrame->IsTrivial();
gfx->Save();
if (referencedClipIsTrivial) {
clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
} else {
gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
}
}
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
@ -85,13 +103,64 @@ nsSVGClipPathFrame::ClipPaint(nsSVGRenderState* aContext,
// The CTM of each frame referencing us can be different.
SVGFrame->NotifySVGChanged(nsISVGChildFrame::SUPPRESS_INVALIDATION |
nsISVGChildFrame::TRANSFORM_CHANGED);
PRBool isOK = PR_TRUE;
nsSVGClipPathFrame *clipPathFrame =
nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame(&isOK);
PRBool isTrivial;
if (clipPathFrame) {
isTrivial = clipPathFrame->IsTrivial();
gfx->Save();
if (isTrivial) {
clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
} else {
gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
}
}
SVGFrame->PaintSVG(aContext, nsnull);
if (clipPathFrame) {
if (!isTrivial) {
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> clipMaskSurface;
gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
clipMaskSurface = gfx->PopGroup();
if (clipMaskSurface) {
gfx->Mask(clipMaskSurface);
}
}
gfx->Restore();
}
}
}
if (clipPathFrame) {
if (!referencedClipIsTrivial) {
gfx->PopGroupToSource();
nsRefPtr<gfxPattern> clipMaskSurface;
gfx->PushGroup(gfxASurface::CONTENT_ALPHA);
clipPathFrame->ClipPaint(aContext, aParent, aMatrix);
clipMaskSurface = gfx->PopGroup();
if (clipMaskSurface) {
gfx->Mask(clipMaskSurface);
}
}
gfx->Restore();
}
if (isTrivial) {
aContext->GetGfxContext()->Clip();
aContext->GetGfxContext()->NewPath();
gfx->Clip();
gfx->NewPath();
}
return NS_OK;
@ -111,9 +180,15 @@ nsSVGClipPathFrame::ClipHitTest(nsIFrame* aParent,
}
AutoClipPathReferencer clipRef(this);
mClipParent = aParent,
mClipParent = aParent;
mClipParentMatrix = NS_NewSVGMatrix(aMatrix);
PRBool isOK = PR_TRUE;
nsSVGClipPathFrame *clipPathFrame =
nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(&isOK);
if (clipPathFrame && !clipPathFrame->ClipHitTest(aParent, aMatrix, aPoint))
return PR_FALSE;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsISVGChildFrame* SVGFrame = do_QueryFrame(kid);
@ -133,6 +208,11 @@ nsSVGClipPathFrame::ClipHitTest(nsIFrame* aParent,
PRBool
nsSVGClipPathFrame::IsTrivial()
{
// If the clip path is clipped then it's non-trivial
PRBool isOK = PR_TRUE;
if (nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(&isOK))
return PR_FALSE;
PRBool foundChild = PR_FALSE;
for (nsIFrame* kid = mFrames.FirstChild(); kid;
@ -143,6 +223,11 @@ nsSVGClipPathFrame::IsTrivial()
// either more than one svg child and/or a svg container
if (foundChild || svgChild->IsDisplayContainer())
return PR_FALSE;
// or where the child is itself clipped
if (nsSVGEffects::GetEffectProperties(kid).GetClipPathFrame(&isOK))
return PR_FALSE;
foundChild = PR_TRUE;
}
}