--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2230,18 +2230,19 @@ nsIFrame::BuildDisplayListForStackingCon
nsRect dirtyRectOutsideSVGEffects = dirtyRect;
nsDisplayList hoistedScrollInfoItemsStorage;
if (usingSVGEffects) {
dirtyRect =
nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
}
+ const nsStyleEffects* effects = StyleEffects();
bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this) && !usingSVGEffects;
- bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
+ bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
IsScrollFrameActive(aBuilder,
nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
bool useFixedPosition = nsLayoutUtils::IsFixedPosFrameInDisplayPort(this);
nsDisplayListBuilder::AutoBuildingDisplayList
@@ -2271,17 +2272,16 @@ nsIFrame::BuildDisplayListForStackingCon
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
nsDisplayListBuilder::AutoInTransformSetter
inTransformSetter(aBuilder, inTransform);
nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex
perspectiveIndex(aBuilder, this);
CheckForApzAwareEventHandlers(aBuilder, this);
- const nsStyleEffects* effects = StyleEffects();
nsRect clipPropClip;
if (ApplyClipPropClipping(aBuilder, this, disp, effects, &clipPropClip,
nestedClipState)) {
dirtyRect.IntersectRect(dirtyRect, clipPropClip);
}
MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect);
@@ -2517,17 +2517,17 @@ nsIFrame::BuildDisplayListForStackingCon
* not affected by foreground opacity (only background alpha).
*/
if (useBlendMode && !resultList.IsEmpty()) {
DisplayListClipState::AutoSaveRestore mixBlendClipState(aBuilder);
mixBlendClipState.Clear();
resultList.AppendNewToTop(
new (aBuilder) nsDisplayBlendMode(aBuilder, this, &resultList,
- disp->mMixBlendMode,
+ effects->mMixBlendMode,
containerItemScrollClip));
}
CreateOwnLayerIfNeeded(aBuilder, &resultList);
aList->AppendToTop(&resultList);
}
@@ -2668,17 +2668,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
const nsStyleDisplay* disp = child->StyleDisplay();
const nsStyleEffects* effects = child->StyleEffects();
const nsStylePosition* pos = child->StylePosition();
bool isVisuallyAtomic = child->HasOpacity()
|| child->IsTransformed()
// strictly speaking, 'perspective' doesn't require visual atomicity,
// but the spec says it acts like the rest of these
|| disp->mChildPerspective.GetUnit() == eStyleUnit_Coord
- || disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL
+ || effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child)
|| (child->GetStateBits() & NS_FRAME_HAS_VR_CONTENT);
bool isPositioned = disp->IsAbsPosContainingBlock(child);
bool isStackingContext =
(isPositioned && (disp->IsPositionForcingStackingContext() ||
pos->mZIndex.GetUnit() == eStyleUnit_Integer)) ||
(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
@@ -2720,17 +2720,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
nsIFrame* parent = child->GetParent();
const nsStyleDisplay* parentDisp =
parent == this ? ourDisp : parent->StyleDisplay();
ApplyOverflowClipping(aBuilder, parent, parentDisp, clipState);
nsDisplayList list;
nsDisplayList extraPositionedDescendants;
if (isStackingContext) {
- if (disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
aBuilder->SetContainsBlendMode(true);
}
// True stacking context.
// For stacking contexts, BuildDisplayListForStackingContext handles
// clipping and MarkAbsoluteFramesForDisplayList.
child->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
aBuilder->DisplayCaret(child, dirty, &list);
} else {
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -2613,17 +2613,17 @@ CSS_PROP_POSITION(
CSS_PROPERTY_STORES_CALC |
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK |
CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH,
"",
VARIANT_AHKLP | VARIANT_CALC,
kWidthKTable,
offsetof(nsStylePosition, mMinWidth),
eStyleAnimType_Coord)
-CSS_PROP_DISPLAY(
+CSS_PROP_EFFECTS(
mix-blend-mode,
mix_blend_mode,
MixBlendMode,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_CREATES_STACKING_CONTEXT,
"layout.css.mix-blend-mode.enabled",
VARIANT_HK,
kBlendModeKTable,
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4806,17 +4806,17 @@ nsComputedDOMStyle::DoGetMinWidth()
nsCSSProps::kWidthKTable);
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetMixBlendMode()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
- val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mMixBlendMode,
+ val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleEffects()->mMixBlendMode,
nsCSSProps::kBlendModeKTable));
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetIsolation()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -5642,23 +5642,16 @@ nsRuleNode::ComputeDisplayData(void* aSt
NS_STYLE_DISPLAY_INLINE, 0, 0, 0, 0);
// contain: none, enum, inherit, initial
SetDiscrete(*aRuleData->ValueForContain(), display->mContain, conditions,
SETDSC_ENUMERATED | SETDSC_NONE | SETDSC_UNSET_INITIAL,
parentDisplay->mContain,
NS_STYLE_CONTAIN_NONE, 0, NS_STYLE_CONTAIN_NONE, 0, 0);
- // mix-blend-mode: enum, inherit, initial
- SetDiscrete(*aRuleData->ValueForMixBlendMode(), display->mMixBlendMode,
- conditions,
- SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
- parentDisplay->mMixBlendMode, NS_STYLE_BLEND_NORMAL,
- 0, 0, 0, 0);
-
// scroll-behavior: enum, inherit, initial
SetDiscrete(*aRuleData->ValueForScrollBehavior(), display->mScrollBehavior,
conditions,
SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
parentDisplay->mScrollBehavior, NS_STYLE_SCROLL_BEHAVIOR_AUTO,
0, 0, 0, 0);
// scroll-snap-type-x: none, enum, inherit, initial
@@ -10033,16 +10026,23 @@ nsRuleNode::ComputeEffectsData(void* aSt
}
break;
}
default:
MOZ_ASSERT(false, "unrecognized clip unit");
}
+ // mix-blend-mode: enum, inherit, initial
+ SetDiscrete(*aRuleData->ValueForMixBlendMode(), effects->mMixBlendMode,
+ conditions,
+ SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
+ parentEffects->mMixBlendMode, NS_STYLE_BLEND_NORMAL,
+ 0, 0, 0, 0);
+
COMPUTE_END_RESET(Effects, effects)
}
const void*
nsRuleNode::GetStyleData(nsStyleStructID aSID,
nsStyleContext* aContext,
bool aComputeData)
{
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2879,17 +2879,16 @@ nsStyleDisplay::nsStyleDisplay(StyleStru
mPerspectiveOrigin[0].SetPercentValue(0.5f);
mPerspectiveOrigin[1].SetPercentValue(0.5f);
mChildPerspective.SetNoneValue();
mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
mBackfaceVisibility = NS_STYLE_BACKFACE_VISIBILITY_VISIBLE;
mTransformStyle = NS_STYLE_TRANSFORM_STYLE_FLAT;
mTransformBox = NS_STYLE_TRANSFORM_BOX_BORDER_BOX;
mOrient = NS_STYLE_ORIENT_INLINE;
- mMixBlendMode = NS_STYLE_BLEND_NORMAL;
mIsolation = NS_STYLE_ISOLATION_AUTO;
mTouchAction = NS_STYLE_TOUCH_ACTION_AUTO;
mTopLayer = NS_STYLE_TOP_LAYER_NONE;
mScrollBehavior = NS_STYLE_SCROLL_BEHAVIOR_AUTO;
mScrollSnapTypeX = NS_STYLE_SCROLL_SNAP_TYPE_NONE;
mScrollSnapTypeY = NS_STYLE_SCROLL_SNAP_TYPE_NONE;
mScrollSnapPointsX.SetNoneValue();
mScrollSnapPointsY.SetNoneValue();
@@ -2933,17 +2932,16 @@ nsStyleDisplay::nsStyleDisplay(const nsS
, mBreakInside(aSource.mBreakInside)
, mBreakBefore(aSource.mBreakBefore)
, mBreakAfter(aSource.mBreakAfter)
, mOverflowX(aSource.mOverflowX)
, mOverflowY(aSource.mOverflowY)
, mOverflowClipBox(aSource.mOverflowClipBox)
, mResize(aSource.mResize)
, mOrient(aSource.mOrient)
- , mMixBlendMode(aSource.mMixBlendMode)
, mIsolation(aSource.mIsolation)
, mTopLayer(aSource.mTopLayer)
, mWillChangeBitField(aSource.mWillChangeBitField)
, mWillChange(aSource.mWillChange)
, mTouchAction(aSource.mTouchAction)
, mScrollBehavior(aSource.mScrollBehavior)
, mScrollSnapTypeX(aSource.mScrollSnapTypeX)
, mScrollSnapTypeY(aSource.mScrollSnapTypeY)
@@ -3064,18 +3062,17 @@ nsChangeHint nsStyleDisplay::CalcDiffere
} else {
NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
if ((mOpacity == 1.0f) != (aOther.mOpacity == 1.0f)) {
NS_UpdateHint(hint, nsChangeHint_UpdateUsesOpacity);
}
}
}
- if (mMixBlendMode != aOther.mMixBlendMode
- || mIsolation != aOther.mIsolation) {
+ if (mIsolation != aOther.mIsolation) {
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
}
/* If we've added or removed the transform property, we need to reconstruct the frame to add
* or remove the view object, and also to handle abs-pos and fixed-pos containers.
*/
if (HasTransformStyle() != aOther.HasTransformStyle()) {
// We do not need to apply nsChangeHint_UpdateTransformLayer since
@@ -3984,24 +3981,26 @@ nsStyleVariables::CalcDifference(const n
//-----------------------
// nsStyleEffects
//
nsStyleEffects::nsStyleEffects(StyleStructContext aContext)
: mBoxShadow(nullptr)
, mClip(0, 0, 0, 0)
, mClipFlags(NS_STYLE_CLIP_AUTO)
+ , mMixBlendMode(NS_STYLE_BLEND_NORMAL)
{
MOZ_COUNT_CTOR(nsStyleEffects);
}
nsStyleEffects::nsStyleEffects(const nsStyleEffects& aSource)
: mBoxShadow(aSource.mBoxShadow)
, mClip(aSource.mClip)
, mClipFlags(aSource.mClipFlags)
+ , mMixBlendMode(aSource.mMixBlendMode)
{
MOZ_COUNT_CTOR(nsStyleEffects);
}
nsStyleEffects::~nsStyleEffects()
{
MOZ_COUNT_DTOR(nsStyleEffects);
}
@@ -4028,15 +4027,19 @@ nsStyleEffects::CalcDifference(const nsS
if (!mClip.IsEqualInterior(aOther.mClip)) {
// If the clip has changed, we just need to update overflow areas. DLBI
// will handle the invalidation.
hint |= nsChangeHint_UpdateOverflow |
nsChangeHint_SchedulePaint;
}
+ if (mMixBlendMode != aOther.mMixBlendMode) {
+ hint |= nsChangeHint_RepaintFrame;
+ }
+
if (!hint &&
!mClip.IsEqualEdges(aOther.mClip)) {
hint |= nsChangeHint_NeutralChange;
}
return hint;
}
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2480,17 +2480,16 @@ struct nsStyleDisplay
uint8_t mBreakInside; // [reset] NS_STYLE_PAGE_BREAK_AUTO/AVOID
bool mBreakBefore; // [reset]
bool mBreakAfter; // [reset]
uint8_t mOverflowX; // [reset] see nsStyleConsts.h
uint8_t mOverflowY; // [reset] see nsStyleConsts.h
uint8_t mOverflowClipBox; // [reset] see nsStyleConsts.h
uint8_t mResize; // [reset] see nsStyleConsts.h
uint8_t mOrient; // [reset] see nsStyleConsts.h
- uint8_t mMixBlendMode; // [reset] see nsStyleConsts.h
uint8_t mIsolation; // [reset] see nsStyleConsts.h
uint8_t mTopLayer; // [reset] see nsStyleConsts.h
uint8_t mWillChangeBitField; // [reset] see nsStyleConsts.h. Stores a
// bitfield representation of the properties
// that are frequently queried. This should
// match mWillChange. Also tracks if any of the
// properties in the will-change list require
// a stacking context.
@@ -3592,11 +3591,12 @@ struct nsStyleEffects
return nsChangeHint_NeedReflow |
nsChangeHint_ReflowChangesSizeOrPosition |
nsChangeHint_ClearAncestorIntrinsics;
}
RefPtr<nsCSSShadowArray> mBoxShadow; // [reset] nullptr for 'none'
nsRect mClip; // [reset] offsets from UL border edge
uint8_t mClipFlags; // [reset] see nsStyleConsts.h
+ uint8_t mMixBlendMode; // [reset] see nsStyleConsts.h
};
#endif /* nsStyleStruct_h___ */
--- a/layout/svg/nsSVGImageFrame.cpp
+++ b/layout/svg/nsSVGImageFrame.cpp
@@ -364,17 +364,17 @@ nsSVGImageFrame::PaintSVG(gfxContext& aC
// fill-opacity doesn't affect <image>, so if we're allowed to
// optimize group opacity, the opacity used for compositing the
// image into the current canvas is just the group opacity.
float opacity = 1.0f;
if (nsSVGUtils::CanOptimizeOpacity(this)) {
opacity = StyleDisplay()->mOpacity;
}
- if (opacity != 1.0f || StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
aContext.PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, opacity);
}
nscoord appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel();
nsRect dirtyRect; // only used if aDirtyRect is non-null
if (aDirtyRect) {
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(mState & NS_FRAME_IS_NONDISPLAY),
@@ -430,17 +430,17 @@ nsSVGImageFrame::PaintSVG(gfxContext& aC
PresContext(),
mImageContainer,
nsLayoutUtils::GetGraphicsFilterForFrame(this),
nsPoint(0, 0),
aDirtyRect ? &dirtyRect : nullptr,
drawFlags);
}
- if (opacity != 1.0f || StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (opacity != 1.0f || StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
aContext.PopGroupAndBlend();
}
// gfxContextAutoSaveRestore goes out of scope & cleans up our gfxContext
}
return rv;
}
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -531,17 +531,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
}
}
}
bool complexEffects = false;
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
if (opacity != 1.0f || (clipPathFrame && !isTrivialClip)
- || aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL
+ || aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL
|| hasMaskToDraw) {
complexEffects = true;
aContext.Save();
nsRect clipRect =
aFrame->GetVisualOverflowRectRelativeToSelf() + toUserSpace;
aContext.Clip(NSRectToSnappedRect(clipRect,
aFrame->PresContext()->AppUnitsPerDevPixel(),
@@ -598,17 +598,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
}
if (hasMaskToDraw && !maskSurface) {
// Entire surface is clipped out.
aContext.Restore();
return;
}
- if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
// Create a temporary context to draw to so we can blend it back with
// another operator.
gfxRect clipRect;
{
gfxContextMatrixAutoSaveRestore matRestore(&aContext);
aContext.SetMatrix(gfxMatrix());
clipRect = aContext.GetClipExtents();
@@ -680,17 +680,17 @@ nsSVGIntegrationUtils::PaintFramesWithEf
if (!complexEffects) {
return;
}
if (opacity != 1.0f || hasMaskToDraw || (clipPathFrame && !isTrivialClip)) {
target->PopGroupAndBlend();
}
- if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
target = nullptr;
RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();
aContext.SetMatrix(gfxMatrix()); // This will be restored right after.
RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(targetOffset.x, targetOffset.y));
aContext.SetPattern(pattern);
aContext.Paint();
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -587,17 +587,17 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
// These are used if we require a temporary surface for a custom blend mode.
RefPtr<gfxContext> target = &aContext;
IntPoint targetOffset;
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
if (opacity != 1.0f || maskFrame || (clipPathFrame && !isTrivialClip)
- || aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ || aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
complexEffects = true;
Matrix maskTransform;
RefPtr<SourceSurface> maskSurface =
maskFrame ? maskFrame->GetMaskForMaskedFrame(&aContext,
aFrame, aTransform, opacity, &maskTransform)
: nullptr;
@@ -619,17 +619,17 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
// GetCanvasTM().
overflowRect = overflowRect + aFrame->GetPosition();
}
aContext.Clip(NSRectToSnappedRect(overflowRect,
aFrame->PresContext()->AppUnitsPerDevPixel(),
*drawTarget));
}
- if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
// Create a temporary context to draw to so we can blend it back with
// another operator.
gfxRect clipRect;
{
gfxContextMatrixAutoSaveRestore matRestore(&aContext);
aContext.SetMatrix(gfxMatrix());
clipRect = aContext.GetClipExtents();
@@ -704,17 +704,17 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
/* No more effects, we're done. */
if (!complexEffects)
return;
if (opacity != 1.0f || maskFrame || (clipPathFrame && !isTrivialClip)) {
target->PopGroupAndBlend();
}
- if (aFrame->StyleDisplay()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
+ if (aFrame->StyleEffects()->mMixBlendMode != NS_STYLE_BLEND_NORMAL) {
RefPtr<DrawTarget> targetDT = target->GetDrawTarget();
target = nullptr;
RefPtr<SourceSurface> targetSurf = targetDT->Snapshot();
aContext.SetMatrix(gfxMatrix()); // This will be restored right after.
RefPtr<gfxPattern> pattern = new gfxPattern(targetSurf, Matrix::Translation(targetOffset.x, targetOffset.y));
aContext.SetPattern(pattern);
aContext.Paint();