/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Main header first: #include"SVGClipPathFrame.h"
if (clipPath) {
aContext.Clip(clipPath);
} else { // The spec says clip away everything if we have no children or the // clipping path otherwise can't be resolved:
aContext.Clip(Rect());
}
}
void SVGClipPathFrame::PaintChildren(gfxContext& aMaskContext,
nsIFrame* aClippedFrame, const gfxMatrix& aMatrix) { // Check if this clipPath is itself clipped by another clipPath:
SVGClipPathFrame* clipPathThatClipsClipPath; // XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(this, &clipPathThatClipsClipPath);
SVGUtils::MaskUsage maskUsage = SVGUtils::DetermineMaskUsage(this, true);
gfxGroupForBlendAutoSaveRestore autoGroupForBlend(&aMaskContext); if (maskUsage.ShouldApplyClipPath()) {
clipPathThatClipsClipPath->ApplyClipPath(aMaskContext, aClippedFrame,
aMatrix);
} elseif (maskUsage.ShouldGenerateClipMaskLayer()) {
RefPtr<SourceSurface> maskSurface = clipPathThatClipsClipPath->GetClipMask(
aMaskContext, aClippedFrame, aMatrix); // We want the mask to be untransformed so use the inverse of the current // transform as the maskTransform to compensate.
Matrix maskTransform = aMaskContext.CurrentMatrix();
maskTransform.Invert();
autoGroupForBlend.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0f,
maskSurface, maskTransform);
}
// Paint our children into the mask: for (auto* kid : mFrames) {
PaintFrameIntoMask(kid, aClippedFrame, aMaskContext);
}
if (maskUsage.ShouldApplyClipPath()) {
aMaskContext.PopClip();
}
}
// A clipPath can reference another clipPath, creating a chain of clipPaths // that must all be applied. We re-enter this method for each clipPath in a // chain, so we need to protect against reference chain related crashes etc.:
AutoReferenceChainGuard refChainGuard(this, &mIsBeingProcessed,
&sRefChainLengthCounter); if (MOZ_UNLIKELY(!refChainGuard.Reference())) { return; // Break reference chain
} if (!IsValid()) { return;
}
// Paint this clipPath's contents into aMaskDT: // We need to set mMatrixForChildren here so that under the PaintSVG calls // on our children (below) our GetCanvasTM() method will return the correct // transform.
mMatrixForChildren = GetClipPathTransform(aClippedFrame) * aMatrix;
// The CTM of each frame referencing us can be different.
frame->NotifySVGChanged(ISVGDisplayableFrame::TRANSFORM_CHANGED);
// Children of this clipPath may themselves be clipped.
SVGClipPathFrame* clipPathThatClipsChild; // XXX check return value? if (SVGObserverUtils::GetAndObserveClipPath(aFrame,
&clipPathThatClipsChild) ==
SVGObserverUtils::eHasRefsSomeInvalid) { return;
}
// We want the mask to be untransformed so use the inverse of the current // transform as the maskTransform to compensate.
Matrix maskTransform = aTarget.CurrentMatrix();
maskTransform.Invert();
autoGroupForBlend.PushGroupForBlendBack(gfxContentType::ALPHA, 1.0f,
maskSurface, maskTransform);
}
// clipPath does not result in any image rendering, so we just use a dummy // imgDrawingParams instead of requiring our caller to pass one.
image::imgDrawingParams imgParams;
// Our children have NS_STATE_SVG_CLIPPATH_CHILD set on them, and // SVGGeometryFrame::Render checks for that state bit and paints // only the geometry (opaque black) if set.
frame->PaintSVG(aTarget, toChildsUserSpace, imgParams);
if (maskUsage.ShouldApplyClipPath()) {
aTarget.PopClip();
}
}
// A clipPath can reference another clipPath, creating a chain of clipPaths // that must all be applied. We re-enter this method for each clipPath in a // chain, so we need to protect against reference chain related crashes etc.:
AutoReferenceChainGuard refChainGuard(this, &mIsBeingProcessed,
&sRefChainLengthCounter); if (MOZ_UNLIKELY(!refChainGuard.Reference())) { returnfalse; // Break reference chain
} if (!IsValid()) { returnfalse;
}
gfxMatrix matrix = GetClipPathTransform(aClippedFrame); if (!matrix.Invert()) { returnfalse;
}
gfxPoint point = matrix.TransformPoint(aPoint);
// clipPath elements can themselves be clipped by a different clip path. In // that case the other clip path further clips away the element that is being // clipped by the original clipPath. If this clipPath is being clipped by a // different clip path we need to check if it prevents the original element // from receiving events at aPoint:
SVGClipPathFrame* clipPathFrame; // XXX check return value?
SVGObserverUtils::GetAndObserveClipPath(this, &clipPathFrame); if (clipPathFrame &&
!clipPathFrame->PointIsInsideClipPath(aClippedFrame, aPoint)) { returnfalse;
}
for (auto* kid : mFrames) {
ISVGDisplayableFrame* SVGFrame = do_QueryFrame(kid); if (SVGFrame) {
gfxPoint pointForChild = point;
gfxMatrix m = SVGUtils::GetTransformMatrixInUserSpace(kid); if (!m.IsIdentity()) { if (!m.Invert()) { returnfalse;
}
pointForChild = m.TransformPoint(point);
} if (SVGFrame->GetFrameForPoint(pointForChild)) { returntrue;
}
}
}
returnfalse;
}
bool SVGClipPathFrame::IsTrivial(nsIFrame** aSingleChild) { // If the clip path is clipped then it's non-trivial if (SVGObserverUtils::GetAndObserveClipPath(this, nullptr) ==
SVGObserverUtils::eHasRefsAllValid) { returnfalse;
}
if (aSingleChild) {
*aSingleChild = nullptr;
}
nsIFrame* foundChild = nullptr; for (auto* kid : mFrames) {
ISVGDisplayableFrame* svgChild = do_QueryFrame(kid); if (!svgChild) { continue;
} // We consider a non-trivial clipPath to be one containing // either more than one svg child and/or a svg container if (foundChild || svgChild->IsDisplayContainer()) { returnfalse;
}
// or where the child is itself clipped if (SVGObserverUtils::GetAndObserveClipPath(kid, nullptr) ==
SVGObserverUtils::eHasRefsAllValid) { returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.