Bug 1250490 - Part 1. Move DetermineMaskUsage and ComputeOpacity to nsSVGUtils.
MozReview-Commit-ID: K06trG9nuvU
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -481,16 +481,94 @@ public:
dirtyRect = &tmpDirtyRect;
}
}
return svgChildFrame->PaintSVG(aContext, aTransform, dirtyRect);
}
};
+float
+nsSVGUtils::ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity)
+{
+ float opacity = aFrame->StyleEffects()->mOpacity;
+
+ if (opacity != 1.0f &&
+ (nsSVGUtils::CanOptimizeOpacity(aFrame) || !aHandleOpacity)) {
+ return 1.0f;
+ }
+
+ return opacity;
+}
+
+void
+nsSVGUtils::DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity,
+ MaskUsage& aUsage)
+{
+ aUsage.opacity = ComputeOpacity(aFrame, aHandleOpacity);
+
+ nsIFrame* firstFrame =
+ nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame);
+
+ nsSVGEffects::EffectProperties effectProperties =
+ nsSVGEffects::GetEffectProperties(firstFrame);
+ const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
+
+ nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
+
+#ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
+ // For a HTML doc:
+ // According to css-masking spec, always create a mask surface when we
+ // have any item in maskFrame even if all of those items are
+ // non-resolvable <mask-sources> or <images>, we still need to create a
+ // transparent black mask layer under this condition.
+ // For a SVG doc:
+ // SVG 1.1 say that if we fail to resolve a mask, we should draw the
+ // object unmasked.
+ aUsage.shouldGenerateMaskLayer =
+ (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
+ ? maskFrames.Length() == 1 && maskFrames[0]
+ : maskFrames.Length() > 0;
+#else
+ // Since we do not support image mask so far, we should treat any
+ // unresolvable mask as no mask. Otherwise, any object with a valid image
+ // mask, e.g. url("xxx.png"), will become invisible just because we can not
+ // handle image mask correctly. (See bug 1294171)
+ aUsage.shouldGenerateMaskLayer = maskFrames.Length() == 1 && maskFrames[0];
+#endif
+
+ bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
+ nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
+ MOZ_ASSERT_IF(clipPathFrame,
+ svgReset->mClipPath.GetType() == StyleShapeSourceType::URL);
+
+ switch (svgReset->mClipPath.GetType()) {
+ case StyleShapeSourceType::URL:
+ if (clipPathFrame) {
+ if (clipPathFrame->IsTrivial()) {
+ aUsage.shouldApplyClipPath = true;
+ } else {
+ aUsage.shouldGenerateClipMaskLayer = true;
+ }
+ }
+ break;
+ case StyleShapeSourceType::Shape:
+ case StyleShapeSourceType::Box:
+ aUsage.shouldApplyBasicShape = true;
+ break;
+ case StyleShapeSourceType::None:
+ MOZ_ASSERT(!aUsage.shouldGenerateClipMaskLayer &&
+ !aUsage.shouldApplyClipPath && !aUsage.shouldApplyBasicShape);
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unsupported clip-path type.");
+ break;
+ }
+}
+
DrawResult
nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
gfxContext& aContext,
const gfxMatrix& aTransform,
const nsIntRect *aDirtyRect)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
@@ -561,17 +639,17 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
* 3. Render markers
* 4. Apply filter
* 5. Apply clipping, masking, group opacity
*
* We follow this, but perform a couple of optimizations:
*
* + Use cairo's clipPath when representable natively (single object
* clip region).
- *
+ *f
* + Merge opacity and masking if both used together.
*/
if (opacity != 1.0f && CanOptimizeOpacity(aFrame))
opacity = 1.0f;
DrawTarget* drawTarget = aContext.GetDrawTarget();
bool complexEffects = false;
--- a/layout/svg/nsSVGUtils.h
+++ b/layout/svg/nsSVGUtils.h
@@ -571,11 +571,30 @@ public:
* Returns the app unit canvas bounds of a userspace rect.
*
* @param aToCanvas Transform from userspace to canvas device space.
*/
static nsRect
ToCanvasBounds(const gfxRect &aUserspaceRect,
const gfxMatrix &aToCanvas,
const nsPresContext *presContext);
+
+ struct MaskUsage {
+ bool shouldGenerateMaskLayer;
+ bool shouldGenerateClipMaskLayer;
+ bool shouldApplyClipPath;
+ bool shouldApplyBasicShape;
+ float opacity;
+
+ MaskUsage()
+ : shouldGenerateMaskLayer(false), shouldGenerateClipMaskLayer(false),
+ shouldApplyClipPath(false), shouldApplyBasicShape(false), opacity(0.0)
+ { }
+ };
+
+ static void
+ DetermineMaskUsage(nsIFrame* aFrame, bool aHandleOpacity, MaskUsage& aUsage);
+
+ static float
+ ComputeOpacity(nsIFrame* aFrame, bool aHandleOpacity);
};
#endif