Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* constants for what needs to be recomputed in response to style changes */ |
michael@0 | 7 | |
michael@0 | 8 | #ifndef nsChangeHint_h___ |
michael@0 | 9 | #define nsChangeHint_h___ |
michael@0 | 10 | |
michael@0 | 11 | #include "nsDebug.h" |
michael@0 | 12 | |
michael@0 | 13 | // Defines for various style related constants |
michael@0 | 14 | |
michael@0 | 15 | enum nsChangeHint { |
michael@0 | 16 | // change was visual only (e.g., COLOR=) |
michael@0 | 17 | // Invalidates all descendant frames (including following |
michael@0 | 18 | // placeholders to out-of-flow frames). |
michael@0 | 19 | nsChangeHint_RepaintFrame = 0x01, |
michael@0 | 20 | |
michael@0 | 21 | // For reflow, we want flags to give us arbitrary FrameNeedsReflow behavior. |
michael@0 | 22 | // just do a FrameNeedsReflow. |
michael@0 | 23 | nsChangeHint_NeedReflow = 0x02, |
michael@0 | 24 | |
michael@0 | 25 | // Invalidate intrinsic widths on the frame's ancestors. Must not be set |
michael@0 | 26 | // without setting nsChangeHint_NeedReflow. |
michael@0 | 27 | nsChangeHint_ClearAncestorIntrinsics = 0x04, |
michael@0 | 28 | |
michael@0 | 29 | // Invalidate intrinsic widths on the frame's descendants. Must not be set |
michael@0 | 30 | // without also setting nsChangeHint_ClearAncestorIntrinsics. |
michael@0 | 31 | nsChangeHint_ClearDescendantIntrinsics = 0x08, |
michael@0 | 32 | |
michael@0 | 33 | // Force unconditional reflow of all descendants. Must not be set without |
michael@0 | 34 | // setting nsChangeHint_NeedReflow, but is independent of both the |
michael@0 | 35 | // Clear*Intrinsics flags. |
michael@0 | 36 | nsChangeHint_NeedDirtyReflow = 0x10, |
michael@0 | 37 | |
michael@0 | 38 | // change requires view to be updated, if there is one (e.g., clip:). |
michael@0 | 39 | // Updates all descendants (including following placeholders to out-of-flows). |
michael@0 | 40 | nsChangeHint_SyncFrameView = 0x20, |
michael@0 | 41 | |
michael@0 | 42 | // The currently shown mouse cursor needs to be updated |
michael@0 | 43 | nsChangeHint_UpdateCursor = 0x40, |
michael@0 | 44 | |
michael@0 | 45 | /** |
michael@0 | 46 | * Used when the computed value (a URI) of one or more of an element's |
michael@0 | 47 | * filter/mask/clip/etc CSS properties changes, causing the element's frame |
michael@0 | 48 | * to start/stop referencing (or reference different) SVG resource elements. |
michael@0 | 49 | * (_Not_ used to handle changes to referenced resource elements.) Using this |
michael@0 | 50 | * hint results in nsSVGEffects::UpdateEffects being called on the element's |
michael@0 | 51 | * frame. |
michael@0 | 52 | */ |
michael@0 | 53 | nsChangeHint_UpdateEffects = 0x80, |
michael@0 | 54 | |
michael@0 | 55 | /** |
michael@0 | 56 | * Visual change only, but the change can be handled entirely by |
michael@0 | 57 | * updating the layer(s) for the frame. |
michael@0 | 58 | * Updates all descendants (including following placeholders to out-of-flows). |
michael@0 | 59 | */ |
michael@0 | 60 | nsChangeHint_UpdateOpacityLayer = 0x100, |
michael@0 | 61 | /** |
michael@0 | 62 | * Updates all descendants. Any placeholder descendants' out-of-flows |
michael@0 | 63 | * are also descendants of the transformed frame, so they're updated. |
michael@0 | 64 | */ |
michael@0 | 65 | nsChangeHint_UpdateTransformLayer = 0x200, |
michael@0 | 66 | |
michael@0 | 67 | /** |
michael@0 | 68 | * Change requires frame change (e.g., display:). |
michael@0 | 69 | * This subsumes all the above. Reconstructs all frame descendants, |
michael@0 | 70 | * including following placeholders to out-of-flows. |
michael@0 | 71 | */ |
michael@0 | 72 | nsChangeHint_ReconstructFrame = 0x400, |
michael@0 | 73 | |
michael@0 | 74 | /** |
michael@0 | 75 | * The frame's overflow area has changed, either through a change in its |
michael@0 | 76 | * transform or a change in its position. Does not update any descendant |
michael@0 | 77 | * frames. |
michael@0 | 78 | */ |
michael@0 | 79 | nsChangeHint_UpdateOverflow = 0x800, |
michael@0 | 80 | |
michael@0 | 81 | /** |
michael@0 | 82 | * The frame's overflow area has changed, through a change in its transform. |
michael@0 | 83 | * Does not update any descendant frames. |
michael@0 | 84 | */ |
michael@0 | 85 | nsChangeHint_UpdatePostTransformOverflow = 0x1000, |
michael@0 | 86 | |
michael@0 | 87 | /** |
michael@0 | 88 | * The children-only transform of an SVG frame changed, requiring the |
michael@0 | 89 | * overflow rects of the frame's immediate children to be updated. |
michael@0 | 90 | */ |
michael@0 | 91 | nsChangeHint_ChildrenOnlyTransform = 0x2000, |
michael@0 | 92 | |
michael@0 | 93 | /** |
michael@0 | 94 | * The frame's offsets have changed, while its dimensions might have |
michael@0 | 95 | * changed as well. This hint is used for positioned frames if their |
michael@0 | 96 | * offset changes. If we decide that the dimensions are likely to |
michael@0 | 97 | * change, this will trigger a reflow. |
michael@0 | 98 | * |
michael@0 | 99 | * Note that this should probably be used in combination with |
michael@0 | 100 | * nsChangeHint_UpdateOverflow in order to get the overflow areas of |
michael@0 | 101 | * the ancestors updated as well. |
michael@0 | 102 | */ |
michael@0 | 103 | nsChangeHint_RecomputePosition = 0x4000, |
michael@0 | 104 | |
michael@0 | 105 | /** |
michael@0 | 106 | * Behaves like ReconstructFrame, but only if the frame has descendants |
michael@0 | 107 | * that are absolutely or fixed position. Use this hint when a style change |
michael@0 | 108 | * has changed whether the frame is a container for fixed-pos or abs-pos |
michael@0 | 109 | * elements, but reframing is otherwise not needed. |
michael@0 | 110 | */ |
michael@0 | 111 | nsChangeHint_AddOrRemoveTransform = 0x8000, |
michael@0 | 112 | |
michael@0 | 113 | /** |
michael@0 | 114 | * This change hint has *no* change handling behavior. However, it |
michael@0 | 115 | * exists to be a non-inherited hint, because when the border-style |
michael@0 | 116 | * changes, and it's inherited by a child, that might require a reflow |
michael@0 | 117 | * due to the border-width change on the child. |
michael@0 | 118 | */ |
michael@0 | 119 | nsChangeHint_BorderStyleNoneChange = 0x10000, |
michael@0 | 120 | |
michael@0 | 121 | /** |
michael@0 | 122 | * SVG textPath needs to be recomputed because the path has changed. |
michael@0 | 123 | * This means that the glyph positions of the text need to be recomputed. |
michael@0 | 124 | */ |
michael@0 | 125 | nsChangeHint_UpdateTextPath = 0x20000 |
michael@0 | 126 | |
michael@0 | 127 | // IMPORTANT NOTE: When adding new hints, consider whether you need to |
michael@0 | 128 | // add them to NS_HintsNotHandledForDescendantsIn() below. |
michael@0 | 129 | }; |
michael@0 | 130 | |
michael@0 | 131 | // Redefine these operators to return nothing. This will catch any use |
michael@0 | 132 | // of these operators on hints. We should not be using these operators |
michael@0 | 133 | // on nsChangeHints |
michael@0 | 134 | inline void operator<(nsChangeHint s1, nsChangeHint s2) {} |
michael@0 | 135 | inline void operator>(nsChangeHint s1, nsChangeHint s2) {} |
michael@0 | 136 | inline void operator!=(nsChangeHint s1, nsChangeHint s2) {} |
michael@0 | 137 | inline void operator==(nsChangeHint s1, nsChangeHint s2) {} |
michael@0 | 138 | inline void operator<=(nsChangeHint s1, nsChangeHint s2) {} |
michael@0 | 139 | inline void operator>=(nsChangeHint s1, nsChangeHint s2) {} |
michael@0 | 140 | |
michael@0 | 141 | // Operators on nsChangeHints |
michael@0 | 142 | |
michael@0 | 143 | // Merge two hints, taking the union |
michael@0 | 144 | inline nsChangeHint NS_CombineHint(nsChangeHint aH1, nsChangeHint aH2) { |
michael@0 | 145 | return (nsChangeHint)(aH1 | aH2); |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | // Merge two hints, taking the union |
michael@0 | 149 | inline nsChangeHint NS_SubtractHint(nsChangeHint aH1, nsChangeHint aH2) { |
michael@0 | 150 | return (nsChangeHint)(aH1 & ~aH2); |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | // Merge the "src" hint into the "dst" hint |
michael@0 | 154 | // Returns true iff the destination changed |
michael@0 | 155 | inline bool NS_UpdateHint(nsChangeHint& aDest, nsChangeHint aSrc) { |
michael@0 | 156 | nsChangeHint r = (nsChangeHint)(aDest | aSrc); |
michael@0 | 157 | bool changed = (int)r != (int)aDest; |
michael@0 | 158 | aDest = r; |
michael@0 | 159 | return changed; |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | // Returns true iff the second hint contains all the hints of the first hint |
michael@0 | 163 | inline bool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) { |
michael@0 | 164 | return (aSubset & aSuperSet) == aSubset; |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | /** |
michael@0 | 168 | * We have an optimization when processing change hints which prevents |
michael@0 | 169 | * us from visiting the descendants of a node when a hint on that node |
michael@0 | 170 | * is being processed. This optimization does not apply in some of the |
michael@0 | 171 | * cases where applying a hint to an element does not necessarily result |
michael@0 | 172 | * in the same hint being handled on the descendants. |
michael@0 | 173 | */ |
michael@0 | 174 | |
michael@0 | 175 | // The most hints that NS_HintsNotHandledForDescendantsIn could possibly return: |
michael@0 | 176 | #define nsChangeHint_Hints_NotHandledForDescendants nsChangeHint( \ |
michael@0 | 177 | nsChangeHint_UpdateTransformLayer | \ |
michael@0 | 178 | nsChangeHint_UpdateEffects | \ |
michael@0 | 179 | nsChangeHint_UpdateOpacityLayer | \ |
michael@0 | 180 | nsChangeHint_UpdateOverflow | \ |
michael@0 | 181 | nsChangeHint_UpdatePostTransformOverflow | \ |
michael@0 | 182 | nsChangeHint_ChildrenOnlyTransform | \ |
michael@0 | 183 | nsChangeHint_RecomputePosition | \ |
michael@0 | 184 | nsChangeHint_AddOrRemoveTransform | \ |
michael@0 | 185 | nsChangeHint_BorderStyleNoneChange | \ |
michael@0 | 186 | nsChangeHint_NeedReflow | \ |
michael@0 | 187 | nsChangeHint_ClearAncestorIntrinsics) |
michael@0 | 188 | |
michael@0 | 189 | inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) { |
michael@0 | 190 | nsChangeHint result = nsChangeHint(aChangeHint & ( |
michael@0 | 191 | nsChangeHint_UpdateTransformLayer | |
michael@0 | 192 | nsChangeHint_UpdateEffects | |
michael@0 | 193 | nsChangeHint_UpdateOpacityLayer | |
michael@0 | 194 | nsChangeHint_UpdateOverflow | |
michael@0 | 195 | nsChangeHint_UpdatePostTransformOverflow | |
michael@0 | 196 | nsChangeHint_ChildrenOnlyTransform | |
michael@0 | 197 | nsChangeHint_RecomputePosition | |
michael@0 | 198 | nsChangeHint_AddOrRemoveTransform | |
michael@0 | 199 | nsChangeHint_BorderStyleNoneChange)); |
michael@0 | 200 | |
michael@0 | 201 | if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aChangeHint) && |
michael@0 | 202 | NS_IsHintSubset(nsChangeHint_NeedReflow, aChangeHint)) { |
michael@0 | 203 | // If NeedDirtyReflow is *not* set, then NeedReflow is a |
michael@0 | 204 | // non-inherited hint. |
michael@0 | 205 | NS_UpdateHint(result, nsChangeHint_NeedReflow); |
michael@0 | 206 | } |
michael@0 | 207 | |
michael@0 | 208 | if (!NS_IsHintSubset(nsChangeHint_ClearDescendantIntrinsics, aChangeHint) && |
michael@0 | 209 | NS_IsHintSubset(nsChangeHint_ClearAncestorIntrinsics, aChangeHint)) { |
michael@0 | 210 | // If ClearDescendantIntrinsics is *not* set, then |
michael@0 | 211 | // ClearAncestorIntrinsics is a non-inherited hint. |
michael@0 | 212 | NS_UpdateHint(result, nsChangeHint_ClearAncestorIntrinsics); |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | NS_ABORT_IF_FALSE(NS_IsHintSubset(result, |
michael@0 | 216 | nsChangeHint_Hints_NotHandledForDescendants), |
michael@0 | 217 | "something is inconsistent"); |
michael@0 | 218 | |
michael@0 | 219 | return result; |
michael@0 | 220 | } |
michael@0 | 221 | |
michael@0 | 222 | // Redefine the old NS_STYLE_HINT constants in terms of the new hint structure |
michael@0 | 223 | #define NS_STYLE_HINT_NONE \ |
michael@0 | 224 | nsChangeHint(0) |
michael@0 | 225 | #define NS_STYLE_HINT_VISUAL \ |
michael@0 | 226 | nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView) |
michael@0 | 227 | #define nsChangeHint_AllReflowHints \ |
michael@0 | 228 | nsChangeHint(nsChangeHint_NeedReflow | \ |
michael@0 | 229 | nsChangeHint_ClearAncestorIntrinsics | \ |
michael@0 | 230 | nsChangeHint_ClearDescendantIntrinsics | \ |
michael@0 | 231 | nsChangeHint_NeedDirtyReflow) |
michael@0 | 232 | #define NS_STYLE_HINT_REFLOW \ |
michael@0 | 233 | nsChangeHint(NS_STYLE_HINT_VISUAL | nsChangeHint_AllReflowHints) |
michael@0 | 234 | #define NS_STYLE_HINT_FRAMECHANGE \ |
michael@0 | 235 | nsChangeHint(NS_STYLE_HINT_REFLOW | nsChangeHint_ReconstructFrame) |
michael@0 | 236 | |
michael@0 | 237 | /** |
michael@0 | 238 | * |nsRestyleHint| is a bitfield for the result of |
michael@0 | 239 | * |HasStateDependentStyle| and |HasAttributeDependentStyle|. When no |
michael@0 | 240 | * restyling is necessary, use |nsRestyleHint(0)|. |
michael@0 | 241 | */ |
michael@0 | 242 | enum nsRestyleHint { |
michael@0 | 243 | eRestyle_Self = 0x1, |
michael@0 | 244 | eRestyle_Subtree = 0x2, /* self and descendants */ |
michael@0 | 245 | eRestyle_LaterSiblings = 0x4 /* implies "and descendants" */ |
michael@0 | 246 | }; |
michael@0 | 247 | |
michael@0 | 248 | |
michael@0 | 249 | #endif /* nsChangeHint_h___ */ |