--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1178,19 +1178,20 @@ nsIFrame::Extend3DContext() const
return false;
}
// If we're all scroll frame, then all descendants will be clipped, so we can't preserve 3d.
if (GetType() == nsGkAtoms::scrollFrame) {
return false;
}
+ const nsStyleEffects* effects = StyleEffects();
nsRect temp;
return !nsFrame::ShouldApplyOverflowClipping(this, disp) &&
- !GetClipPropClipRect(disp, &temp, GetSize()) &&
+ !GetClipPropClipRect(disp, effects, &temp, GetSize()) &&
!nsSVGIntegrationUtils::UsingEffectsForFrame(this);
}
bool
nsIFrame::Combines3DTransformWithAncestors() const
{
if (!GetParent() || !GetParent()->Extend3DContext()) {
return false;
@@ -1892,61 +1893,64 @@ inline static bool IsSVGContentWithCSSCl
// the CSS spec for outer-<svg> (since that's what we generally do), but
// obey the SVG spec for other SVG elements to which 'clip' applies.
return (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
aFrame->GetContent()->IsAnyOfSVGElements(nsGkAtoms::svg,
nsGkAtoms::foreignObject);
}
bool
-nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
+nsIFrame::GetClipPropClipRect(const nsStyleDisplay* aDisp,
+ const nsStyleEffects* aEffects,
+ nsRect* aRect,
const nsSize& aSize) const
{
NS_PRECONDITION(aRect, "Must have aRect out parameter");
- if (!(aDisp->mClipFlags & NS_STYLE_CLIP_RECT) ||
+ if (!(aEffects->mClipFlags & NS_STYLE_CLIP_RECT) ||
!(aDisp->IsAbsolutelyPositioned(this) || IsSVGContentWithCSSClip(this))) {
return false;
}
- *aRect = aDisp->mClip;
+ *aRect = aEffects->mClip;
if (MOZ_LIKELY(StyleBorder()->mBoxDecorationBreak ==
NS_STYLE_BOX_DECORATION_BREAK_SLICE)) {
// The clip applies to the joined boxes so it's relative the first
// continuation.
nscoord y = 0;
for (nsIFrame* f = GetPrevContinuation(); f; f = f->GetPrevContinuation()) {
y += f->GetRect().height;
}
aRect->MoveBy(nsPoint(0, -y));
}
- if (NS_STYLE_CLIP_RIGHT_AUTO & aDisp->mClipFlags) {
+ if (NS_STYLE_CLIP_RIGHT_AUTO & aEffects->mClipFlags) {
aRect->width = aSize.width - aRect->x;
}
- if (NS_STYLE_CLIP_BOTTOM_AUTO & aDisp->mClipFlags) {
+ if (NS_STYLE_CLIP_BOTTOM_AUTO & aEffects->mClipFlags) {
aRect->height = aSize.height - aRect->y;
}
return true;
}
/**
* If the CSS 'clip' property applies to this frame, set it up
* in aBuilder->ClipState() to clip all content descendants. Returns true
* if the property applies, and if so also returns the clip rect (relative
* to aFrame) in *aRect.
*/
static bool
ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
const nsIFrame* aFrame,
const nsStyleDisplay* aDisp,
+ const nsStyleEffects* aEffects,
nsRect* aRect,
DisplayListClipState::AutoSaveRestore& aClipState)
{
- if (!aFrame->GetClipPropClipRect(aDisp, aRect, aFrame->GetSize()))
+ if (!aFrame->GetClipPropClipRect(aDisp, aEffects, aRect, aFrame->GetSize()))
return false;
nsRect clipRect = *aRect + aBuilder->ToReferenceFrame(aFrame);
aClipState.ClipContentDescendants(clipRect);
return true;
}
/**
@@ -2267,18 +2271,19 @@ 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, &clipPropClip,
+ if (ApplyClipPropClipping(aBuilder, this, disp, effects, &clipPropClip,
nestedClipState)) {
dirtyRect.IntersectRect(dirtyRect, clipPropClip);
}
MarkAbsoluteFramesForDisplayList(aBuilder, dirtyRect);
// Extend3DContext() also guarantees that applyAbsPosClipping and usingSVGEffects are false
// We only modify the preserve-3d rect if we are the top of a preserve-3d heirarchy
@@ -2656,16 +2661,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
// Don't paint our children if the theme object is a leaf.
if (IsThemed(ourDisp) &&
!PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
return;
// Child is composited if it's transformed, partially transparent, or has
// SVG effects or a blend mode..
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
|| nsSVGIntegrationUtils::UsingEffectsForFrame(child)
@@ -2675,17 +2681,17 @@ nsIFrame::BuildDisplayListForChild(nsDis
bool isStackingContext =
(isPositioned && (disp->IsPositionForcingStackingContext() ||
pos->mZIndex.GetUnit() == eStyleUnit_Integer)) ||
(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
disp->mIsolation != NS_STYLE_ISOLATION_AUTO ||
isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT);
if (isVisuallyAtomic || isPositioned || (!isSVG && disp->IsFloating(child)) ||
- ((disp->mClipFlags & NS_STYLE_CLIP_RECT) &&
+ ((effects->mClipFlags & NS_STYLE_CLIP_RECT) &&
IsSVGContentWithCSSClip(child)) ||
disp->mIsolation != NS_STYLE_ISOLATION_AUTO ||
(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
(aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
// If you change this, also change IsPseudoStackingContextFromStyle()
pseudoStackingContext = true;
}
NS_ASSERTION(!isStackingContext || pseudoStackingContext,
@@ -2724,17 +2730,18 @@ nsIFrame::BuildDisplayListForChild(nsDis
}
// True stacking context.
// For stacking contexts, BuildDisplayListForStackingContext handles
// clipping and MarkAbsoluteFramesForDisplayList.
child->BuildDisplayListForStackingContext(aBuilder, dirty, &list);
aBuilder->DisplayCaret(child, dirty, &list);
} else {
nsRect clipRect;
- if (ApplyClipPropClipping(aBuilder, child, disp, &clipRect, clipState)) {
+ if (ApplyClipPropClipping(aBuilder, child, disp, effects, &clipRect,
+ clipState)) {
// clipRect is in builder-reference-frame coordinates,
// dirty/clippedDirtyRect are in child coordinates
dirty.IntersectRect(dirty, clipRect);
}
child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
if (aBuilder->IsBuildingLayerEventRegions()) {
@@ -7740,19 +7747,21 @@ UnionBorderBoxes(nsIFrame* aFrame, bool
nsIAtom* fType = aFrame->GetType();
if (nsFrame::ShouldApplyOverflowClipping(aFrame, disp) ||
fType == nsGkAtoms::scrollFrame ||
fType == nsGkAtoms::listControlFrame ||
fType == nsGkAtoms::svgOuterSVGFrame) {
return u;
}
+ const nsStyleEffects* effects = aFrame->StyleEffects();
nsRect clipPropClipRect;
bool hasClipPropClip =
- aFrame->GetClipPropClipRect(disp, &clipPropClipRect, bounds.Size());
+ aFrame->GetClipPropClipRect(disp, effects, &clipPropClipRect,
+ bounds.Size());
// Iterate over all children except pop-ups.
const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList |
nsIFrame::kSelectPopupList);
for (nsIFrame::ChildListIterator childLists(aFrame);
!childLists.IsDone(); childLists.Next()) {
if (skip.Contains(childLists.CurrentID())) {
continue;
@@ -7983,18 +7992,20 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
ComputeAndIncludeOutlineArea(this, aOverflowAreas, aNewSize);
// Nothing in here should affect scrollable overflow.
aOverflowAreas.VisualOverflow() =
ComputeEffectsRect(this, aOverflowAreas.VisualOverflow(), aNewSize);
// Absolute position clipping
+ const nsStyleEffects* effects = StyleEffects();
nsRect clipPropClipRect;
- bool hasClipPropClip = GetClipPropClipRect(disp, &clipPropClipRect, aNewSize);
+ bool hasClipPropClip =
+ GetClipPropClipRect(disp, effects, &clipPropClipRect, aNewSize);
if (hasClipPropClip) {
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o.IntersectRect(o, clipPropClipRect);
}
}
/* If we're transformed, transform the overflow rect by the current transformation. */
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2821,17 +2821,19 @@ public:
* property applies to HTML frames if they are absolutely positioned. The
* 'clip' property applies to SVG frames regardless of the value of the
* 'position' property.
*
* If this method returns true, then we also set aRect to the computed clip
* rect, with coordinates relative to this frame's origin. aRect must not be
* null!
*/
- bool GetClipPropClipRect(const nsStyleDisplay* aDisp, nsRect* aRect,
+ bool GetClipPropClipRect(const nsStyleDisplay* aDisp,
+ const nsStyleEffects* aEffects,
+ nsRect* aRect,
const nsSize& aSize) const;
/**
* Check if this frame is focusable and in the current tab order.
* Tabbable is indicated by a nonnegative tabindex & is a subset of focusable.
* For example, only the selected radio button in a group is in the
* tab order, unless the radio group has no selection in which case
* all of the visible, non-disabled radio buttons in the group are
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -3459,39 +3459,39 @@ StyleAnimationValue::ExtractComputedValu
nscoordToCSSValue(srect.y, vrect->mTop);
nscoordToCSSValue(srect.XMost(), vrect->mRight);
nscoordToCSSValue(srect.YMost(), vrect->mBottom);
aComputedValue.SetAndAdoptCSSRectValue(vrect, eUnit_CSSRect);
break;
}
case eCSSProperty_clip: {
- const nsStyleDisplay *display =
- static_cast<const nsStyleDisplay*>(styleStruct);
- if (!(display->mClipFlags & NS_STYLE_CLIP_RECT)) {
+ const nsStyleEffects* effects =
+ static_cast<const nsStyleEffects*>(styleStruct);
+ if (!(effects->mClipFlags & NS_STYLE_CLIP_RECT)) {
aComputedValue.SetAutoValue();
} else {
nsCSSRect *vrect = new nsCSSRect;
- const nsRect &srect = display->mClip;
- if (display->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
+ const nsRect &srect = effects->mClip;
+ if (effects->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
vrect->mTop.SetAutoValue();
} else {
nscoordToCSSValue(srect.y, vrect->mTop);
}
- if (display->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
vrect->mRight.SetAutoValue();
} else {
nscoordToCSSValue(srect.XMost(), vrect->mRight);
}
- if (display->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
vrect->mBottom.SetAutoValue();
} else {
nscoordToCSSValue(srect.YMost(), vrect->mBottom);
}
- if (display->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
vrect->mLeft.SetAutoValue();
} else {
nscoordToCSSValue(srect.x, vrect->mLeft);
}
aComputedValue.SetAndAdoptCSSRectValue(vrect, eUnit_CSSRect);
}
break;
}
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1358,26 +1358,26 @@ CSS_PROP_DISPLAY(
clear,
Clear,
CSS_PROPERTY_PARSE_VALUE,
"",
VARIANT_HK,
kClearKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
-CSS_PROP_DISPLAY(
+CSS_PROP_EFFECTS(
clip,
clip,
Clip,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_UNITLESS_LENGTH_QUIRK,
"",
0,
nullptr,
- offsetof(nsStyleDisplay, mClip),
+ offsetof(nsStyleEffects, mClip),
eStyleAnimType_Custom)
CSS_PROP_COLOR(
color,
color,
Color,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
CSS_PROPERTY_APPLIES_TO_PLACEHOLDER |
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -4467,50 +4467,50 @@ nsComputedDOMStyle::DoGetPosition()
return val.forget();
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetClip()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
- const nsStyleDisplay* display = StyleDisplay();
-
- if (display->mClipFlags == NS_STYLE_CLIP_AUTO) {
+ const nsStyleEffects* effects = StyleEffects();
+
+ if (effects->mClipFlags == NS_STYLE_CLIP_AUTO) {
val->SetIdent(eCSSKeyword_auto);
} else {
// create the cssvalues for the sides, stick them in the rect object
nsROCSSPrimitiveValue *topVal = new nsROCSSPrimitiveValue;
nsROCSSPrimitiveValue *rightVal = new nsROCSSPrimitiveValue;
nsROCSSPrimitiveValue *bottomVal = new nsROCSSPrimitiveValue;
nsROCSSPrimitiveValue *leftVal = new nsROCSSPrimitiveValue;
nsDOMCSSRect * domRect = new nsDOMCSSRect(topVal, rightVal,
bottomVal, leftVal);
- if (display->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
topVal->SetIdent(eCSSKeyword_auto);
} else {
- topVal->SetAppUnits(display->mClip.y);
+ topVal->SetAppUnits(effects->mClip.y);
}
- if (display->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
rightVal->SetIdent(eCSSKeyword_auto);
} else {
- rightVal->SetAppUnits(display->mClip.width + display->mClip.x);
+ rightVal->SetAppUnits(effects->mClip.width + effects->mClip.x);
}
- if (display->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
bottomVal->SetIdent(eCSSKeyword_auto);
} else {
- bottomVal->SetAppUnits(display->mClip.height + display->mClip.y);
+ bottomVal->SetAppUnits(effects->mClip.height + effects->mClip.y);
}
- if (display->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
+ if (effects->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
leftVal->SetIdent(eCSSKeyword_auto);
} else {
- leftVal->SetAppUnits(display->mClip.x);
+ leftVal->SetAppUnits(effects->mClip.x);
}
val->SetRect(domRect);
}
return val.forget();
}
already_AddRefed<CSSValue>
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -6000,90 +6000,16 @@ nsRuleNode::ComputeDisplayData(void* aSt
parentDisplay->mOverflowClipBox,
NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX, 0, 0, 0, 0);
SetDiscrete(*aRuleData->ValueForResize(), display->mResize, conditions,
SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
parentDisplay->mResize,
NS_STYLE_RESIZE_NONE, 0, 0, 0, 0);
- // clip property: length, auto, inherit
- const nsCSSValue* clipValue = aRuleData->ValueForClip();
- switch (clipValue->GetUnit()) {
- case eCSSUnit_Inherit:
- conditions.SetUncacheable();
- display->mClipFlags = parentDisplay->mClipFlags;
- display->mClip = parentDisplay->mClip;
- break;
-
- case eCSSUnit_Initial:
- case eCSSUnit_Unset:
- case eCSSUnit_Auto:
- display->mClipFlags = NS_STYLE_CLIP_AUTO;
- display->mClip.SetRect(0,0,0,0);
- break;
-
- case eCSSUnit_Null:
- break;
-
- case eCSSUnit_Rect: {
- const nsCSSRect& clipRect = clipValue->GetRectValue();
-
- display->mClipFlags = NS_STYLE_CLIP_RECT;
-
- if (clipRect.mTop.GetUnit() == eCSSUnit_Auto) {
- display->mClip.y = 0;
- display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
- }
- else if (clipRect.mTop.IsLengthUnit()) {
- display->mClip.y = CalcLength(clipRect.mTop, aContext,
- mPresContext, conditions);
- }
-
- if (clipRect.mBottom.GetUnit() == eCSSUnit_Auto) {
- // Setting to NS_MAXSIZE for the 'auto' case ensures that
- // the clip rect is nonempty. It is important that mClip be
- // nonempty if the actual clip rect could be nonempty.
- display->mClip.height = NS_MAXSIZE;
- display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
- }
- else if (clipRect.mBottom.IsLengthUnit()) {
- display->mClip.height = CalcLength(clipRect.mBottom, aContext,
- mPresContext, conditions) -
- display->mClip.y;
- }
-
- if (clipRect.mLeft.GetUnit() == eCSSUnit_Auto) {
- display->mClip.x = 0;
- display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
- }
- else if (clipRect.mLeft.IsLengthUnit()) {
- display->mClip.x = CalcLength(clipRect.mLeft, aContext,
- mPresContext, conditions);
- }
-
- if (clipRect.mRight.GetUnit() == eCSSUnit_Auto) {
- // Setting to NS_MAXSIZE for the 'auto' case ensures that
- // the clip rect is nonempty. It is important that mClip be
- // nonempty if the actual clip rect could be nonempty.
- display->mClip.width = NS_MAXSIZE;
- display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
- }
- else if (clipRect.mRight.IsLengthUnit()) {
- display->mClip.width = CalcLength(clipRect.mRight, aContext,
- mPresContext, conditions) -
- display->mClip.x;
- }
- break;
- }
-
- default:
- MOZ_ASSERT(false, "unrecognized clip unit");
- }
-
if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
// CSS2 9.7 specifies display type corrections dealing with 'float'
// and 'position'. Since generated content can't be floated or
// positioned, we can deal with it here.
nsIAtom* pseudo = aContext->GetPseudo();
if (pseudo && display->mDisplay == NS_STYLE_DISPLAY_CONTENTS) {
// We don't want to create frames for anonymous content using a parent
@@ -10033,16 +9959,90 @@ nsRuleNode::ComputeEffectsData(void* aSt
effects->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
aContext, true, conditions);
break;
default:
MOZ_ASSERT(false, "unrecognized shadow unit");
}
+ // clip property: length, auto, inherit
+ const nsCSSValue* clipValue = aRuleData->ValueForClip();
+ switch (clipValue->GetUnit()) {
+ case eCSSUnit_Inherit:
+ conditions.SetUncacheable();
+ effects->mClipFlags = parentEffects->mClipFlags;
+ effects->mClip = parentEffects->mClip;
+ break;
+
+ case eCSSUnit_Initial:
+ case eCSSUnit_Unset:
+ case eCSSUnit_Auto:
+ effects->mClipFlags = NS_STYLE_CLIP_AUTO;
+ effects->mClip.SetRect(0,0,0,0);
+ break;
+
+ case eCSSUnit_Null:
+ break;
+
+ case eCSSUnit_Rect: {
+ const nsCSSRect& clipRect = clipValue->GetRectValue();
+
+ effects->mClipFlags = NS_STYLE_CLIP_RECT;
+
+ if (clipRect.mTop.GetUnit() == eCSSUnit_Auto) {
+ effects->mClip.y = 0;
+ effects->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
+ }
+ else if (clipRect.mTop.IsLengthUnit()) {
+ effects->mClip.y = CalcLength(clipRect.mTop, aContext,
+ mPresContext, conditions);
+ }
+
+ if (clipRect.mBottom.GetUnit() == eCSSUnit_Auto) {
+ // Setting to NS_MAXSIZE for the 'auto' case ensures that
+ // the clip rect is nonempty. It is important that mClip be
+ // nonempty if the actual clip rect could be nonempty.
+ effects->mClip.height = NS_MAXSIZE;
+ effects->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
+ }
+ else if (clipRect.mBottom.IsLengthUnit()) {
+ effects->mClip.height = CalcLength(clipRect.mBottom, aContext,
+ mPresContext, conditions) -
+ effects->mClip.y;
+ }
+
+ if (clipRect.mLeft.GetUnit() == eCSSUnit_Auto) {
+ effects->mClip.x = 0;
+ effects->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
+ }
+ else if (clipRect.mLeft.IsLengthUnit()) {
+ effects->mClip.x = CalcLength(clipRect.mLeft, aContext,
+ mPresContext, conditions);
+ }
+
+ if (clipRect.mRight.GetUnit() == eCSSUnit_Auto) {
+ // Setting to NS_MAXSIZE for the 'auto' case ensures that
+ // the clip rect is nonempty. It is important that mClip be
+ // nonempty if the actual clip rect could be nonempty.
+ effects->mClip.width = NS_MAXSIZE;
+ effects->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
+ }
+ else if (clipRect.mRight.IsLengthUnit()) {
+ effects->mClip.width = CalcLength(clipRect.mRight, aContext,
+ mPresContext, conditions) -
+ effects->mClip.x;
+ }
+ break;
+ }
+
+ default:
+ MOZ_ASSERT(false, "unrecognized clip unit");
+ }
+
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
@@ -2866,18 +2866,16 @@ nsStyleDisplay::nsStyleDisplay(StyleStru
mBreakType = NS_STYLE_CLEAR_NONE;
mBreakInside = NS_STYLE_PAGE_BREAK_AUTO;
mBreakBefore = false;
mBreakAfter = false;
mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
mOverflowClipBox = NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX;
mResize = NS_STYLE_RESIZE_NONE;
- mClipFlags = NS_STYLE_CLIP_AUTO;
- mClip.SetRect(0,0,0,0);
mOpacity = 1.0f;
mSpecifiedTransform = nullptr;
mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
mTransformOrigin[1].SetPercentValue(0.5f);
mTransformOrigin[2].SetCoordValue(0);
mPerspectiveOrigin[0].SetPercentValue(0.5f);
mPerspectiveOrigin[1].SetPercentValue(0.5f);
mChildPerspective.SetNoneValue();
@@ -2918,34 +2916,32 @@ nsStyleDisplay::nsStyleDisplay(StyleStru
mAnimationDirectionCount = 1;
mAnimationFillModeCount = 1;
mAnimationPlayStateCount = 1;
mAnimationIterationCountCount = 1;
}
nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
: mBinding(aSource.mBinding)
- , mClip(aSource.mClip)
, mOpacity(aSource.mOpacity)
, mDisplay(aSource.mDisplay)
, mOriginalDisplay(aSource.mOriginalDisplay)
, mContain(aSource.mContain)
, mAppearance(aSource.mAppearance)
, mPosition(aSource.mPosition)
, mFloats(aSource.mFloats)
, mOriginalFloats(aSource.mOriginalFloats)
, mBreakType(aSource.mBreakType)
, mBreakInside(aSource.mBreakInside)
, mBreakBefore(aSource.mBreakBefore)
, mBreakAfter(aSource.mBreakAfter)
, mOverflowX(aSource.mOverflowX)
, mOverflowY(aSource.mOverflowY)
, mOverflowClipBox(aSource.mOverflowClipBox)
, mResize(aSource.mResize)
- , mClipFlags(aSource.mClipFlags)
, mOrient(aSource.mOrient)
, mMixBlendMode(aSource.mMixBlendMode)
, mIsolation(aSource.mIsolation)
, mTopLayer(aSource.mTopLayer)
, mWillChangeBitField(aSource.mWillChangeBitField)
, mWillChange(aSource.mWillChange)
, mTouchAction(aSource.mTouchAction)
, mScrollBehavior(aSource.mScrollBehavior)
@@ -3049,28 +3045,20 @@ nsChangeHint nsStyleDisplay::CalcDiffere
// XXX the following is conservative, for now: changing float breaking shouldn't
// necessarily require a repaint, reflow should suffice.
if (mBreakType != aOther.mBreakType
|| mBreakInside != aOther.mBreakInside
|| mBreakBefore != aOther.mBreakBefore
|| mBreakAfter != aOther.mBreakAfter
|| mAppearance != aOther.mAppearance
|| mOrient != aOther.mOrient
- || mOverflowClipBox != aOther.mOverflowClipBox
- || mClipFlags != aOther.mClipFlags)
+ || mOverflowClipBox != aOther.mOverflowClipBox)
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AllReflowHints,
nsChangeHint_RepaintFrame));
- if (!mClip.IsEqualInterior(aOther.mClip)) {
- // If the clip has changed, we just need to update overflow areas. DLBI
- // will handle the invalidation.
- NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdateOverflow,
- nsChangeHint_SchedulePaint));
- }
-
if (mOpacity != aOther.mOpacity) {
// If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
// repaint the frame because DLBI will not catch the invalidation. Otherwise,
// just update the opacity layer.
if ((mOpacity >= 0.99f && mOpacity < 1.0f && aOther.mOpacity == 1.0f) ||
(aOther.mOpacity >= 0.99f && aOther.mOpacity < 1.0f && mOpacity == 1.0f)) {
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
} else {
@@ -3189,18 +3177,17 @@ nsChangeHint nsStyleDisplay::CalcDiffere
// Note: Likewise, for animation-*, the animation manager gets
// notified about every new style context constructed, and it uses
// that opportunity to handle dynamic changes appropriately.
// But we still need to return nsChangeHint_NeutralChange for these
// properties, since some data did change in the style struct.
if (!hint &&
- (!mClip.IsEqualEdges(aOther.mClip) ||
- mOriginalDisplay != aOther.mOriginalDisplay ||
+ (mOriginalDisplay != aOther.mOriginalDisplay ||
mOriginalFloats != aOther.mOriginalFloats ||
mTransitions != aOther.mTransitions ||
mTransitionTimingFunctionCount !=
aOther.mTransitionTimingFunctionCount ||
mTransitionDurationCount != aOther.mTransitionDurationCount ||
mTransitionDelayCount != aOther.mTransitionDelayCount ||
mTransitionPropertyCount != aOther.mTransitionPropertyCount ||
mAnimations != aOther.mAnimations ||
@@ -3995,22 +3982,26 @@ nsStyleVariables::CalcDifference(const n
}
//-----------------------
// nsStyleEffects
//
nsStyleEffects::nsStyleEffects(StyleStructContext aContext)
: mBoxShadow(nullptr)
+ , mClip(0, 0, 0, 0)
+ , mClipFlags(NS_STYLE_CLIP_AUTO)
{
MOZ_COUNT_CTOR(nsStyleEffects);
}
nsStyleEffects::nsStyleEffects(const nsStyleEffects& aSource)
: mBoxShadow(aSource.mBoxShadow)
+ , mClip(aSource.mClip)
+ , mClipFlags(aSource.mClipFlags)
{
MOZ_COUNT_CTOR(nsStyleEffects);
}
nsStyleEffects::~nsStyleEffects()
{
MOZ_COUNT_DTOR(nsStyleEffects);
}
@@ -4025,10 +4016,27 @@ nsStyleEffects::CalcDifference(const nsS
// Also request a repaint, since it's possible that only the color
// of the shadow is changing (and UpdateOverflow/SchedulePaint won't
// repaint for that, since they won't know what needs invalidating.)
hint |= nsChangeHint_UpdateOverflow |
nsChangeHint_SchedulePaint |
nsChangeHint_RepaintFrame;
}
+ if (mClipFlags != aOther.mClipFlags) {
+ hint |= nsChangeHint_AllReflowHints |
+ nsChangeHint_RepaintFrame;
+ }
+
+ 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 (!hint &&
+ !mClip.IsEqualEdges(aOther.mClip)) {
+ hint |= nsChangeHint_NeutralChange;
+ }
+
return hint;
}
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2460,17 +2460,16 @@ struct nsStyleDisplay
// XXXdholbert, XXXkgilbert nsStyleImageLayers::Position should probably be
// moved to a different scope, since we're now using it in multiple style
// structs.
typedef nsStyleImageLayers::Position Position;
// We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
// mBinding->mOriginPrincipal.
RefPtr<mozilla::css::URLValue> mBinding; // [reset]
- nsRect mClip; // [reset] offsets from upper-left border edge
float mOpacity; // [reset]
uint8_t mDisplay; // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
uint8_t mOriginalDisplay; // [reset] saved mDisplay for position:absolute/fixed
// and float:left/right; otherwise equal
// to mDisplay
uint8_t mContain; // [reset] see nsStyleConsts.h NS_STYLE_CONTAIN_*
uint8_t mAppearance; // [reset]
uint8_t mPosition; // [reset] see nsStyleConsts.h
@@ -2480,17 +2479,16 @@ struct nsStyleDisplay
uint8_t mBreakType; // [reset] see nsStyleConsts.h NS_STYLE_CLEAR_*
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 mClipFlags; // [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
@@ -3577,22 +3575,28 @@ struct nsStyleEffects
void Destroy(nsPresContext* aContext) {
this->~nsStyleEffects();
aContext->PresShell()->
FreeByObjectID(mozilla::eArenaObjectID_nsStyleEffects, this);
}
nsChangeHint CalcDifference(const nsStyleEffects& aOther) const;
static nsChangeHint MaxDifference() {
- return nsChangeHint_UpdateOverflow |
+ return nsChangeHint_AllReflowHints |
+ nsChangeHint_UpdateOverflow |
nsChangeHint_SchedulePaint |
- nsChangeHint_RepaintFrame;
+ nsChangeHint_RepaintFrame |
+ nsChangeHint_NeutralChange;
}
static nsChangeHint DifferenceAlwaysHandledForDescendants() {
// CalcDifference never returns the reflow hints that are sometimes
// handled for descendants as hints not handled for descendants.
- return nsChangeHint(0);
+ 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
};
#endif /* nsStyleStruct_h___ */
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -874,35 +874,36 @@ nsSVGUtils::HitTestRect(const gfx::Matri
rect.y <= p.y && p.y <= rect.YMost();
}
gfxRect
nsSVGUtils::GetClipRectForFrame(nsIFrame *aFrame,
float aX, float aY, float aWidth, float aHeight)
{
const nsStyleDisplay* disp = aFrame->StyleDisplay();
+ const nsStyleEffects* effects = aFrame->StyleEffects();
- if (!(disp->mClipFlags & NS_STYLE_CLIP_RECT)) {
- NS_ASSERTION(disp->mClipFlags == NS_STYLE_CLIP_AUTO,
+ if (!(effects->mClipFlags & NS_STYLE_CLIP_RECT)) {
+ NS_ASSERTION(effects->mClipFlags == NS_STYLE_CLIP_AUTO,
"We don't know about this type of clip.");
return gfxRect(aX, aY, aWidth, aHeight);
}
if (disp->mOverflowX == NS_STYLE_OVERFLOW_HIDDEN ||
disp->mOverflowY == NS_STYLE_OVERFLOW_HIDDEN) {
nsIntRect clipPxRect =
- disp->mClip.ToOutsidePixels(aFrame->PresContext()->AppUnitsPerDevPixel());
+ effects->mClip.ToOutsidePixels(aFrame->PresContext()->AppUnitsPerDevPixel());
gfxRect clipRect =
gfxRect(clipPxRect.x, clipPxRect.y, clipPxRect.width, clipPxRect.height);
- if (NS_STYLE_CLIP_RIGHT_AUTO & disp->mClipFlags) {
+ if (NS_STYLE_CLIP_RIGHT_AUTO & effects->mClipFlags) {
clipRect.width = aWidth - clipRect.X();
}
- if (NS_STYLE_CLIP_BOTTOM_AUTO & disp->mClipFlags) {
+ if (NS_STYLE_CLIP_BOTTOM_AUTO & effects->mClipFlags) {
clipRect.height = aHeight - clipRect.Y();
}
if (disp->mOverflowX != NS_STYLE_OVERFLOW_HIDDEN) {
clipRect.x = aX;
clipRect.width = aWidth;
}
if (disp->mOverflowY != NS_STYLE_OVERFLOW_HIDDEN) {