@@ -12,7 +12,10 @@ use crate::computed_values::mix_blend_mode::T as MixBlendMode;
1212use crate :: computed_values:: transform_style:: T as TransformStyle ;
1313use crate :: dom:: TElement ;
1414use 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+ } ;
1619use crate :: values:: computed:: basic_shape:: ClipPath ;
1720use crate :: values:: computed:: Perspective ;
1821use crate :: values:: generics:: transform:: { GenericRotate , GenericScale , GenericTranslate } ;
@@ -125,64 +128,67 @@ impl fmt::Display for ServoRestyleDamage {
125128 }
126129}
127130
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+ }
128147fn compute_damage ( old : & ComputedValues , new : & ComputedValues ) -> ServoRestyleDamage {
129148 let mut damage = ServoRestyleDamage :: empty ( ) ;
130149
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) {
185159 damage. insert ( ServoRestyleDamage :: REPAINT ) ;
186160 }
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+
187166 damage
188167}
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