@@ -12,7 +12,10 @@ use crate::computed_values::mix_blend_mode::T as MixBlendMode;
12
12
use crate :: computed_values:: transform_style:: T as TransformStyle ;
13
13
use crate :: dom:: TElement ;
14
14
use crate :: matching:: { StyleChange , StyleDifference } ;
15
- use crate :: properties:: { style_structs, ComputedValues } ;
15
+ use crate :: properties:: {
16
+ restyle_damage_rebuild_box, restyle_damage_rebuild_stacking_context,
17
+ restyle_damage_recalculate_overflow, restyle_damage_repaint, style_structs, ComputedValues ,
18
+ } ;
16
19
use crate :: values:: computed:: basic_shape:: ClipPath ;
17
20
use crate :: values:: computed:: Perspective ;
18
21
use crate :: values:: generics:: transform:: { GenericRotate , GenericScale , GenericTranslate } ;
@@ -125,64 +128,67 @@ impl fmt::Display for ServoRestyleDamage {
125
128
}
126
129
}
127
130
131
+ fn augmented_restyle_damage_rebuild_box ( old : & ComputedValues , new : & ComputedValues ) -> bool {
132
+ let old_box = old. get_box ( ) ;
133
+ let new_box = new. get_box ( ) ;
134
+ restyle_damage_rebuild_box ( old, new)
135
+ || old_box. original_display != new_box. original_display
136
+ || old_box. has_transform_or_perspective ( ) != new_box. has_transform_or_perspective ( )
137
+ || old. get_effects ( ) . filter . 0 . is_empty ( ) != new. get_effects ( ) . filter . 0 . is_empty ( )
138
+ }
139
+
140
+ fn augmented_restyle_damage_rebuild_stacking_context (
141
+ old : & ComputedValues ,
142
+ new : & ComputedValues ,
143
+ ) -> bool {
144
+ restyle_damage_rebuild_stacking_context ( old, new)
145
+ || old. guarantees_stacking_context ( ) != new. guarantees_stacking_context ( )
146
+ }
128
147
fn compute_damage ( old : & ComputedValues , new : & ComputedValues ) -> ServoRestyleDamage {
129
148
let mut damage = ServoRestyleDamage :: empty ( ) ;
130
149
131
- let has_transform_or_perspective_style = |style_box : & style_structs:: Box | {
132
- !style_box. transform . 0 . is_empty ( ) ||
133
- style_box. scale != GenericScale :: None ||
134
- style_box. rotate != GenericRotate :: None ||
135
- style_box. translate != GenericTranslate :: None ||
136
- style_box. perspective != Perspective :: None ||
137
- style_box. transform_style == TransformStyle :: Preserve3d
138
- } ;
139
-
140
- let rebuild_box_extra = || {
141
- let old_box = old. get_box ( ) ;
142
- let new_box = new. get_box ( ) ;
143
- old_box. original_display != new_box. original_display ||
144
- has_transform_or_perspective_style ( old_box) !=
145
- has_transform_or_perspective_style ( new_box) ||
146
- old. get_effects ( ) . filter . 0 . is_empty ( ) != new. get_effects ( ) . filter . 0 . is_empty ( )
147
- } ;
148
-
149
- // Some properties establish a stacking context when they are set to a non-initial value.
150
- // In that case, the damage is only set to `ServoRestyleDamage::REPAINT` because we don't
151
- // need to rebuild stacking contexts when the style changes between different non-initial
152
- // values. This function checks whether any of these properties is set to a value that
153
- // guarantees a stacking context, so that we only do the work when this changes.
154
- // Note that it's still possible to establish a stacking context when this returns false.
155
- let guarantees_stacking_context = |style : & ComputedValues | {
156
- style. get_effects ( ) . opacity != 1.0 ||
157
- old. get_effects ( ) . mix_blend_mode != MixBlendMode :: Normal ||
158
- old. get_svg ( ) . clip_path != ClipPath :: None ||
159
- style. get_box ( ) . isolation == Isolation :: Isolate
160
- } ;
161
-
162
- // This uses short-circuiting boolean OR for its side effects and ignores the result.
163
- let _ = restyle_damage_rebuild_box ! (
164
- old,
165
- new,
166
- damage,
167
- [ ServoRestyleDamage :: RELAYOUT ] ,
168
- rebuild_box_extra( )
169
- ) || restyle_damage_recalculate_overflow ! (
170
- old,
171
- new,
172
- damage,
173
- [ ServoRestyleDamage :: RECALCULATE_OVERFLOW ]
174
- ) || restyle_damage_rebuild_stacking_context ! (
175
- old,
176
- new,
177
- damage,
178
- [ ServoRestyleDamage :: REBUILD_STACKING_CONTEXT ] ,
179
- guarantees_stacking_context( old) != guarantees_stacking_context( new)
180
- ) || restyle_damage_repaint ! ( old, new, damage, [ ServoRestyleDamage :: REPAINT ] ) ;
181
-
182
- // Paint worklets may depend on custom properties,
183
- // so if they have changed we should repaint.
184
- if !old. custom_properties_equal ( new) {
150
+ // Damage flags higher up the if-else chain imply damage flags lower down the if-else chain,
151
+ // so we can skip the diffing process for later flags if an earlier flag is true
152
+ if augmented_restyle_damage_rebuild_box ( old, new) {
153
+ damage. insert ( ServoRestyleDamage :: RELAYOUT )
154
+ } else if restyle_damage_recalculate_overflow ( old, new) {
155
+ damage. insert ( ServoRestyleDamage :: RECALCULATE_OVERFLOW )
156
+ } else if augmented_restyle_damage_rebuild_stacking_context ( old, new) {
157
+ damage. insert ( ServoRestyleDamage :: REBUILD_STACKING_CONTEXT ) ;
158
+ } else if restyle_damage_repaint ( old, new) {
185
159
damage. insert ( ServoRestyleDamage :: REPAINT ) ;
186
160
}
161
+ // Paint worklets may depend on custom properties, so if they have changed we should repaint.
162
+ else if !old. custom_properties_equal ( new) {
163
+ damage. insert ( ServoRestyleDamage :: REPAINT ) ;
164
+ }
165
+
187
166
damage
188
167
}
168
+
169
+ impl ComputedValues {
170
+ /// Some properties establish a stacking context when they are set to a non-initial value.
171
+ /// In that case, the damage is only set to `ServoRestyleDamage::REPAINT` because we don't
172
+ /// need to rebuild stacking contexts when the style changes between different non-initial
173
+ /// values. This function checks whether any of these properties is set to a value that
174
+ /// guarantees a stacking context, so that we only do the work when this changes.
175
+ /// Note that it's still possible to establish a stacking context when this returns false.
176
+ pub fn guarantees_stacking_context ( & self ) -> bool {
177
+ self . get_effects ( ) . opacity != 1.0
178
+ || self . get_effects ( ) . mix_blend_mode != MixBlendMode :: Normal
179
+ || self . get_svg ( ) . clip_path != ClipPath :: None
180
+ || self . get_box ( ) . isolation == Isolation :: Isolate
181
+ }
182
+ }
183
+
184
+ impl style_structs:: Box {
185
+ /// Whether there is a non-default transform or perspective style set
186
+ pub fn has_transform_or_perspective ( & self ) -> bool {
187
+ !self . transform . 0 . is_empty ( )
188
+ || self . scale != GenericScale :: None
189
+ || self . rotate != GenericRotate :: None
190
+ || self . translate != GenericTranslate :: None
191
+ || self . perspective != Perspective :: None
192
+ || self . transform_style == TransformStyle :: Preserve3d
193
+ }
194
+ }
0 commit comments