michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* constants for what needs to be recomputed in response to style changes */ michael@0: michael@0: #ifndef nsChangeHint_h___ michael@0: #define nsChangeHint_h___ michael@0: michael@0: #include "nsDebug.h" michael@0: michael@0: // Defines for various style related constants michael@0: michael@0: enum nsChangeHint { michael@0: // change was visual only (e.g., COLOR=) michael@0: // Invalidates all descendant frames (including following michael@0: // placeholders to out-of-flow frames). michael@0: nsChangeHint_RepaintFrame = 0x01, michael@0: michael@0: // For reflow, we want flags to give us arbitrary FrameNeedsReflow behavior. michael@0: // just do a FrameNeedsReflow. michael@0: nsChangeHint_NeedReflow = 0x02, michael@0: michael@0: // Invalidate intrinsic widths on the frame's ancestors. Must not be set michael@0: // without setting nsChangeHint_NeedReflow. michael@0: nsChangeHint_ClearAncestorIntrinsics = 0x04, michael@0: michael@0: // Invalidate intrinsic widths on the frame's descendants. Must not be set michael@0: // without also setting nsChangeHint_ClearAncestorIntrinsics. michael@0: nsChangeHint_ClearDescendantIntrinsics = 0x08, michael@0: michael@0: // Force unconditional reflow of all descendants. Must not be set without michael@0: // setting nsChangeHint_NeedReflow, but is independent of both the michael@0: // Clear*Intrinsics flags. michael@0: nsChangeHint_NeedDirtyReflow = 0x10, michael@0: michael@0: // change requires view to be updated, if there is one (e.g., clip:). michael@0: // Updates all descendants (including following placeholders to out-of-flows). michael@0: nsChangeHint_SyncFrameView = 0x20, michael@0: michael@0: // The currently shown mouse cursor needs to be updated michael@0: nsChangeHint_UpdateCursor = 0x40, michael@0: michael@0: /** michael@0: * Used when the computed value (a URI) of one or more of an element's michael@0: * filter/mask/clip/etc CSS properties changes, causing the element's frame michael@0: * to start/stop referencing (or reference different) SVG resource elements. michael@0: * (_Not_ used to handle changes to referenced resource elements.) Using this michael@0: * hint results in nsSVGEffects::UpdateEffects being called on the element's michael@0: * frame. michael@0: */ michael@0: nsChangeHint_UpdateEffects = 0x80, michael@0: michael@0: /** michael@0: * Visual change only, but the change can be handled entirely by michael@0: * updating the layer(s) for the frame. michael@0: * Updates all descendants (including following placeholders to out-of-flows). michael@0: */ michael@0: nsChangeHint_UpdateOpacityLayer = 0x100, michael@0: /** michael@0: * Updates all descendants. Any placeholder descendants' out-of-flows michael@0: * are also descendants of the transformed frame, so they're updated. michael@0: */ michael@0: nsChangeHint_UpdateTransformLayer = 0x200, michael@0: michael@0: /** michael@0: * Change requires frame change (e.g., display:). michael@0: * This subsumes all the above. Reconstructs all frame descendants, michael@0: * including following placeholders to out-of-flows. michael@0: */ michael@0: nsChangeHint_ReconstructFrame = 0x400, michael@0: michael@0: /** michael@0: * The frame's overflow area has changed, either through a change in its michael@0: * transform or a change in its position. Does not update any descendant michael@0: * frames. michael@0: */ michael@0: nsChangeHint_UpdateOverflow = 0x800, michael@0: michael@0: /** michael@0: * The frame's overflow area has changed, through a change in its transform. michael@0: * Does not update any descendant frames. michael@0: */ michael@0: nsChangeHint_UpdatePostTransformOverflow = 0x1000, michael@0: michael@0: /** michael@0: * The children-only transform of an SVG frame changed, requiring the michael@0: * overflow rects of the frame's immediate children to be updated. michael@0: */ michael@0: nsChangeHint_ChildrenOnlyTransform = 0x2000, michael@0: michael@0: /** michael@0: * The frame's offsets have changed, while its dimensions might have michael@0: * changed as well. This hint is used for positioned frames if their michael@0: * offset changes. If we decide that the dimensions are likely to michael@0: * change, this will trigger a reflow. michael@0: * michael@0: * Note that this should probably be used in combination with michael@0: * nsChangeHint_UpdateOverflow in order to get the overflow areas of michael@0: * the ancestors updated as well. michael@0: */ michael@0: nsChangeHint_RecomputePosition = 0x4000, michael@0: michael@0: /** michael@0: * Behaves like ReconstructFrame, but only if the frame has descendants michael@0: * that are absolutely or fixed position. Use this hint when a style change michael@0: * has changed whether the frame is a container for fixed-pos or abs-pos michael@0: * elements, but reframing is otherwise not needed. michael@0: */ michael@0: nsChangeHint_AddOrRemoveTransform = 0x8000, michael@0: michael@0: /** michael@0: * This change hint has *no* change handling behavior. However, it michael@0: * exists to be a non-inherited hint, because when the border-style michael@0: * changes, and it's inherited by a child, that might require a reflow michael@0: * due to the border-width change on the child. michael@0: */ michael@0: nsChangeHint_BorderStyleNoneChange = 0x10000, michael@0: michael@0: /** michael@0: * SVG textPath needs to be recomputed because the path has changed. michael@0: * This means that the glyph positions of the text need to be recomputed. michael@0: */ michael@0: nsChangeHint_UpdateTextPath = 0x20000 michael@0: michael@0: // IMPORTANT NOTE: When adding new hints, consider whether you need to michael@0: // add them to NS_HintsNotHandledForDescendantsIn() below. michael@0: }; michael@0: michael@0: // Redefine these operators to return nothing. This will catch any use michael@0: // of these operators on hints. We should not be using these operators michael@0: // on nsChangeHints michael@0: inline void operator<(nsChangeHint s1, nsChangeHint s2) {} michael@0: inline void operator>(nsChangeHint s1, nsChangeHint s2) {} michael@0: inline void operator!=(nsChangeHint s1, nsChangeHint s2) {} michael@0: inline void operator==(nsChangeHint s1, nsChangeHint s2) {} michael@0: inline void operator<=(nsChangeHint s1, nsChangeHint s2) {} michael@0: inline void operator>=(nsChangeHint s1, nsChangeHint s2) {} michael@0: michael@0: // Operators on nsChangeHints michael@0: michael@0: // Merge two hints, taking the union michael@0: inline nsChangeHint NS_CombineHint(nsChangeHint aH1, nsChangeHint aH2) { michael@0: return (nsChangeHint)(aH1 | aH2); michael@0: } michael@0: michael@0: // Merge two hints, taking the union michael@0: inline nsChangeHint NS_SubtractHint(nsChangeHint aH1, nsChangeHint aH2) { michael@0: return (nsChangeHint)(aH1 & ~aH2); michael@0: } michael@0: michael@0: // Merge the "src" hint into the "dst" hint michael@0: // Returns true iff the destination changed michael@0: inline bool NS_UpdateHint(nsChangeHint& aDest, nsChangeHint aSrc) { michael@0: nsChangeHint r = (nsChangeHint)(aDest | aSrc); michael@0: bool changed = (int)r != (int)aDest; michael@0: aDest = r; michael@0: return changed; michael@0: } michael@0: michael@0: // Returns true iff the second hint contains all the hints of the first hint michael@0: inline bool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) { michael@0: return (aSubset & aSuperSet) == aSubset; michael@0: } michael@0: michael@0: /** michael@0: * We have an optimization when processing change hints which prevents michael@0: * us from visiting the descendants of a node when a hint on that node michael@0: * is being processed. This optimization does not apply in some of the michael@0: * cases where applying a hint to an element does not necessarily result michael@0: * in the same hint being handled on the descendants. michael@0: */ michael@0: michael@0: // The most hints that NS_HintsNotHandledForDescendantsIn could possibly return: michael@0: #define nsChangeHint_Hints_NotHandledForDescendants nsChangeHint( \ michael@0: nsChangeHint_UpdateTransformLayer | \ michael@0: nsChangeHint_UpdateEffects | \ michael@0: nsChangeHint_UpdateOpacityLayer | \ michael@0: nsChangeHint_UpdateOverflow | \ michael@0: nsChangeHint_UpdatePostTransformOverflow | \ michael@0: nsChangeHint_ChildrenOnlyTransform | \ michael@0: nsChangeHint_RecomputePosition | \ michael@0: nsChangeHint_AddOrRemoveTransform | \ michael@0: nsChangeHint_BorderStyleNoneChange | \ michael@0: nsChangeHint_NeedReflow | \ michael@0: nsChangeHint_ClearAncestorIntrinsics) michael@0: michael@0: inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) { michael@0: nsChangeHint result = nsChangeHint(aChangeHint & ( michael@0: nsChangeHint_UpdateTransformLayer | michael@0: nsChangeHint_UpdateEffects | michael@0: nsChangeHint_UpdateOpacityLayer | michael@0: nsChangeHint_UpdateOverflow | michael@0: nsChangeHint_UpdatePostTransformOverflow | michael@0: nsChangeHint_ChildrenOnlyTransform | michael@0: nsChangeHint_RecomputePosition | michael@0: nsChangeHint_AddOrRemoveTransform | michael@0: nsChangeHint_BorderStyleNoneChange)); michael@0: michael@0: if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint) && michael@0: NS_IsHintSubset(nsChangeHint_NeedReflow, aChangeHint)) { michael@0: // If NeedDirtyReflow is *not* set, then NeedReflow is a michael@0: // non-inherited hint. michael@0: NS_UpdateHint(result, nsChangeHint_NeedReflow); michael@0: } michael@0: michael@0: if (!NS_IsHintSubset(nsChangeHint_ClearDescendantIntrinsics, aChangeHint) && michael@0: NS_IsHintSubset(nsChangeHint_ClearAncestorIntrinsics, aChangeHint)) { michael@0: // If ClearDescendantIntrinsics is *not* set, then michael@0: // ClearAncestorIntrinsics is a non-inherited hint. michael@0: NS_UpdateHint(result, nsChangeHint_ClearAncestorIntrinsics); michael@0: } michael@0: michael@0: NS_ABORT_IF_FALSE(NS_IsHintSubset(result, michael@0: nsChangeHint_Hints_NotHandledForDescendants), michael@0: "something is inconsistent"); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: // Redefine the old NS_STYLE_HINT constants in terms of the new hint structure michael@0: #define NS_STYLE_HINT_NONE \ michael@0: nsChangeHint(0) michael@0: #define NS_STYLE_HINT_VISUAL \ michael@0: nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView) michael@0: #define nsChangeHint_AllReflowHints \ michael@0: nsChangeHint(nsChangeHint_NeedReflow | \ michael@0: nsChangeHint_ClearAncestorIntrinsics | \ michael@0: nsChangeHint_ClearDescendantIntrinsics | \ michael@0: nsChangeHint_NeedDirtyReflow) michael@0: #define NS_STYLE_HINT_REFLOW \ michael@0: nsChangeHint(NS_STYLE_HINT_VISUAL | nsChangeHint_AllReflowHints) michael@0: #define NS_STYLE_HINT_FRAMECHANGE \ michael@0: nsChangeHint(NS_STYLE_HINT_REFLOW | nsChangeHint_ReconstructFrame) michael@0: michael@0: /** michael@0: * |nsRestyleHint| is a bitfield for the result of michael@0: * |HasStateDependentStyle| and |HasAttributeDependentStyle|. When no michael@0: * restyling is necessary, use |nsRestyleHint(0)|. michael@0: */ michael@0: enum nsRestyleHint { michael@0: eRestyle_Self = 0x1, michael@0: eRestyle_Subtree = 0x2, /* self and descendants */ michael@0: eRestyle_LaterSiblings = 0x4 /* implies "and descendants" */ michael@0: }; michael@0: michael@0: michael@0: #endif /* nsChangeHint_h___ */