diff --git a/gfx/2d/DrawTargetCairo.cpp b/gfx/2d/DrawTargetCairo.cpp index dfac78c4b8a..6cc922789b7 100644 --- a/gfx/2d/DrawTargetCairo.cpp +++ b/gfx/2d/DrawTargetCairo.cpp @@ -958,6 +958,8 @@ DrawTargetCairo::MaskSurface(const Pattern &aSource, cairo_matrix_init_translate (&matrix, -aOffset.x, -aOffset.y); cairo_pattern_set_matrix (mask, &matrix); + cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp)); + cairo_mask(mContext, mask); cairo_surface_destroy(surf); diff --git a/gfx/layers/basic/BasicCanvasLayer.cpp b/gfx/layers/basic/BasicCanvasLayer.cpp index 6fd69021cc5..6e70bf68b47 100644 --- a/gfx/layers/basic/BasicCanvasLayer.cpp +++ b/gfx/layers/basic/BasicCanvasLayer.cpp @@ -5,6 +5,7 @@ #include "BasicCanvasLayer.h" #include "basic/BasicLayers.h" // for BasicLayerManager +#include "basic/BasicLayersImpl.h" // for GetEffectiveOperator #include "mozilla/mozalloc.h" // for operator new #include "nsAutoPtr.h" // for nsRefPtr #include "nsCOMPtr.h" // for already_AddRefed @@ -29,11 +30,10 @@ BasicCanvasLayer::Paint(DrawTarget* aTarget, SourceSurface* aMaskSurface) UpdateTarget(); FireDidTransactionCallback(); - CompositionOp mixBlendMode = GetEffectiveMixBlendMode(); PaintWithOpacity(aTarget, GetEffectiveOpacity(), aMaskSurface, - mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator()); + GetEffectiveOperator(this)); } void diff --git a/gfx/layers/basic/BasicColorLayer.cpp b/gfx/layers/basic/BasicColorLayer.cpp index de5cc96aec2..4bafd89b0ca 100644 --- a/gfx/layers/basic/BasicColorLayer.cpp +++ b/gfx/layers/basic/BasicColorLayer.cpp @@ -48,9 +48,8 @@ public: if (IsHidden()) { return; } - CompositionOp mixBlendMode = GetEffectiveMixBlendMode(); - CompositionOp op = - mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator(); + + CompositionOp op = GetEffectiveOperator(this); DrawOptions opts = DrawOptions(); opts.mCompositionOp = op; diff --git a/gfx/layers/basic/BasicImageLayer.cpp b/gfx/layers/basic/BasicImageLayer.cpp index f7ba8c2387c..c7fbd8aa24d 100644 --- a/gfx/layers/basic/BasicImageLayer.cpp +++ b/gfx/layers/basic/BasicImageLayer.cpp @@ -129,9 +129,7 @@ BasicImageLayer::GetAndPaintCurrentImage(DrawTarget* aTarget, // The visible region can extend outside the image, so just draw // within the image bounds. SurfacePattern pat(surf, ExtendMode::CLAMP, Matrix(), ToFilter(mFilter)); - CompositionOp mixBlendMode = GetEffectiveMixBlendMode(); - CompositionOp op = - mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator(); + CompositionOp op = GetEffectiveOperator(this); DrawOptions opts(aOpacity, op); aTarget->MaskSurface(pat, aMaskSurface, Point(0, 0), opts); @@ -171,9 +169,7 @@ BasicImageLayer::DeprecatedGetAndPaintCurrentImage(gfxContext* aContext, // The visible region can extend outside the image, so just draw // within the image bounds. if (aContext) { - CompositionOp mixBlendMode = GetEffectiveMixBlendMode(); - CompositionOp op = - mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator(); + CompositionOp op = GetEffectiveOperator(this); AutoSetOperator setOptimizedOperator(aContext, ThebesOp(op)); DeprecatedPaintContext(pat, diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 0315ed32b2b..327ecf766c9 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -861,9 +861,10 @@ BasicLayerManager::FlushGroup(PaintLayerContext& aPaintContext, bool aNeedsClipT gfxUtils::ClipToRegion(aPaintContext.mTarget, aPaintContext.mLayer->GetEffectiveVisibleRegion()); } - BasicContainerLayer* container = static_cast(aPaintContext.mLayer); - AutoSetOperator setOperator(aPaintContext.mTarget, - ThebesOp(container->GetOperator())); + + CompositionOp op = GetEffectiveOperator(aPaintContext.mLayer); + AutoSetOperator setOperator(aPaintContext.mTarget, ThebesOp(op)); + PaintWithMask(aPaintContext.mTarget, aPaintContext.mLayer->GetEffectiveOpacity(), aPaintContext.mLayer->GetMaskLayer()); } diff --git a/gfx/layers/basic/BasicLayersImpl.cpp b/gfx/layers/basic/BasicLayersImpl.cpp index d7ad34643fb..71fc3586a5a 100644 --- a/gfx/layers/basic/BasicLayersImpl.cpp +++ b/gfx/layers/basic/BasicLayersImpl.cpp @@ -135,6 +135,18 @@ ToData(Layer* aLayer) return static_cast(aLayer->ImplData()); } +gfx::CompositionOp +GetEffectiveOperator(Layer* aLayer) +{ + CompositionOp op = aLayer->GetEffectiveMixBlendMode(); + + if (op != CompositionOp::OP_OVER) { + return op; + } + + return ToData(aLayer)->GetOperator(); +} + ShadowableLayer* ToShadowable(Layer* aLayer) { diff --git a/gfx/layers/basic/BasicLayersImpl.h b/gfx/layers/basic/BasicLayersImpl.h index cd90d4fb1fa..d76b39577bb 100644 --- a/gfx/layers/basic/BasicLayersImpl.h +++ b/gfx/layers/basic/BasicLayersImpl.h @@ -94,6 +94,21 @@ FillWithMask(gfxContext* aContext, float aOpacity, Layer* aMaskLayer); BasicImplData* ToData(Layer* aLayer); +/** + * Returns the operator to be used when blending and compositing this layer. + * Currently there is no way to specify both a blending and a compositing + * operator other than normal and source over respectively. + * + * If the layer has + * an effective blend mode operator other than normal, as returned by + * GetEffectiveMixBlendMode, this operator is used for blending, and source + * over is used for compositing. + * If the blend mode for this layer is normal, the compositing operator + * returned by GetOperator is used. + */ +gfx::CompositionOp +GetEffectiveOperator(Layer* aLayer); + } } diff --git a/gfx/layers/basic/BasicThebesLayer.cpp b/gfx/layers/basic/BasicThebesLayer.cpp index 2bd38fdd3e1..c769c50c902 100644 --- a/gfx/layers/basic/BasicThebesLayer.cpp +++ b/gfx/layers/basic/BasicThebesLayer.cpp @@ -62,7 +62,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext, } float opacity = GetEffectiveOpacity(); - CompositionOp mixBlendMode = GetEffectiveMixBlendMode(); + CompositionOp effectiveOperator = GetEffectiveOperator(this); if (!BasicManager()->IsRetained()) { NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer"); @@ -84,16 +84,14 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext, bool needsClipToVisibleRegion = GetClipToVisibleRegion(); bool needsGroup = opacity != 1.0 || - GetOperator() != CompositionOp::OP_OVER || - mixBlendMode != CompositionOp::OP_OVER || + effectiveOperator != CompositionOp::OP_OVER || aMaskLayer; nsRefPtr groupContext; if (needsGroup) { groupContext = BasicManager()->PushGroupForLayer(aContext, this, toDraw, &needsClipToVisibleRegion); - if (GetOperator() != CompositionOp::OP_OVER || - mixBlendMode != CompositionOp::OP_OVER) { + if (effectiveOperator != CompositionOp::OP_OVER) { needsClipToVisibleRegion = true; } } else { @@ -106,9 +104,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext, if (needsClipToVisibleRegion) { gfxUtils::ClipToRegion(aContext, toDraw); } - CompositionOp op = - mixBlendMode != CompositionOp::OP_OVER ? mixBlendMode : GetOperator(); - AutoSetOperator setOptimizedOperator(aContext, ThebesOp(op)); + AutoSetOperator setOptimizedOperator(aContext, ThebesOp(effectiveOperator)); PaintWithMask(aContext, opacity, aMaskLayer); }