diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index 98687e90b8ce..96d534ccd0ab 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -107,25 +107,10 @@ enum nsChangeHint { * has changed whether the frame is a container for fixed-pos or abs-pos * elements, but reframing is otherwise not needed. */ - nsChangeHint_AddOrRemoveTransform = 0x4000, + nsChangeHint_AddOrRemoveTransform = 0x4000 - /** - * We have an optimization when processing change hints which prevents - * us from visiting the descendants of a node when a hint on that node - * is being processed. This optimization does not apply in some of the - * cases where applying a hint to an element does not necessarily result - * in the same hint being handled on the descendants. - * - * If you're adding such a hint, you should add your hint to this list. - */ - nsChangeHint_NonInherited_Hints = - nsChangeHint_UpdateTransformLayer | - nsChangeHint_UpdateEffects | - nsChangeHint_UpdateOpacityLayer | - nsChangeHint_UpdateOverflow | - nsChangeHint_ChildrenOnlyTransform | - nsChangeHint_RecomputePosition | - nsChangeHint_AddOrRemoveTransform + // IMPORTANT NOTE: When adding new hints, consider whether you need to + // add them to NS_HintsNotHandledForDescendantsIn() below. }; // Redefine these operators to return nothing. This will catch any use @@ -164,6 +149,40 @@ inline bool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) { return (aSubset & aSuperSet) == aSubset; } +/** + * We have an optimization when processing change hints which prevents + * us from visiting the descendants of a node when a hint on that node + * is being processed. This optimization does not apply in some of the + * cases where applying a hint to an element does not necessarily result + * in the same hint being handled on the descendants. + */ +inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) { + nsChangeHint result = nsChangeHint(aChangeHint & ( + nsChangeHint_UpdateTransformLayer | + nsChangeHint_UpdateEffects | + nsChangeHint_UpdateOpacityLayer | + nsChangeHint_UpdateOverflow | + nsChangeHint_ChildrenOnlyTransform | + nsChangeHint_RecomputePosition | + nsChangeHint_AddOrRemoveTransform)); + + if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint) && + NS_IsHintSubset(nsChangeHint_NeedReflow, aChangeHint)) { + // If NeedDirtyReflow is *not* set, then NeedReflow is a + // non-inherited hint. + NS_UpdateHint(result, nsChangeHint_NeedReflow); + } + + if (!NS_IsHintSubset(nsChangeHint_ClearDescendantIntrinsics, aChangeHint) && + NS_IsHintSubset(nsChangeHint_ClearAncestorIntrinsics, aChangeHint)) { + // If ClearDescendantIntrinsics is *not* set, then + // ClearAncestorIntrinsics is a non-inherited hint. + NS_UpdateHint(result, nsChangeHint_ClearAncestorIntrinsics); + } + + return result; +} + // Redefine the old NS_STYLE_HINT constants in terms of the new hint structure #define NS_STYLE_HINT_NONE \ nsChangeHint(0) diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index d0f3758f78cf..932c63b19dd7 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -1011,28 +1011,10 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext, nsTArray& aVisibleKidsOfHiddenElement, TreeMatchContext &aTreeMatchContext) { - if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aMinChange)) { - // If aMinChange doesn't include nsChangeHint_NeedDirtyReflow, clear out - // all the reflow change bits from it, so that we'll make sure to append a - // change to the list for ourselves if we need a reflow. We need this - // because the parent may or may not actually end up reflowing us - // otherwise. - aMinChange = NS_SubtractHint(aMinChange, nsChangeHint_ReflowFrame); - } else if (!NS_IsHintSubset(nsChangeHint_ClearDescendantIntrinsics, - aMinChange)) { - // If aMinChange doesn't include nsChangeHint_ClearDescendantIntrinsics, - // clear out the nsChangeHint_ClearAncestorIntrinsics flag, since it's - // possible that we had some random ancestor that cleared ancestor - // intrinsic widths, but we still need to clear intrinsic widths on frames - // that are our ancestors but its descendants. - aMinChange = - NS_SubtractHint(aMinChange, nsChangeHint_ClearAncestorIntrinsics); - } - // We need to generate a new change list entry for every frame whose style // comparision returns one of these hints. These hints don't automatically // update all their descendant frames. - aMinChange = NS_SubtractHint(aMinChange, nsChangeHint_NonInherited_Hints); + aMinChange = NS_SubtractHint(aMinChange, NS_HintsNotHandledForDescendantsIn(aMinChange)); // It would be nice if we could make stronger assertions here; they // would let us simplify the ?: expressions below setting |content| diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp index 72def98c0c52..233df721554e 100644 --- a/layout/style/nsStyleContext.cpp +++ b/layout/style/nsStyleContext.cpp @@ -399,8 +399,7 @@ nsStyleContext::CalcStyleDifference(nsStyleContext* aOther) nsStyle##struct_::MaxDifference()), \ "CalcDifference() returned bigger hint than MaxDifference()"); \ NS_ASSERTION(nsStyle##struct_::ForceCompare() || \ - NS_IsHintSubset(nsStyle##struct_::MaxDifference(), \ - nsChangeHint(~nsChangeHint_NonInherited_Hints)), \ + NS_HintsNotHandledForDescendantsIn(nsStyle##struct_::MaxDifference()) == 0, \ "Structs that can return non-inherited hints must return true " \ "from ForceCompare"); \ NS_UpdateHint(hint, this##struct_->CalcDifference(*other##struct_)); \