1use hashbrown::{HashMap, HashSet};
64use indexmap::IndexMap;
65use log::warn;
66use std::fmt::Debug;
67use std::hash::{DefaultHasher, Hash, Hasher};
68use std::ops::Range;
69use vizia_style::selectors::parser::{AncestorHashes, Selector};
70
71use crate::prelude::*;
72use crate::storage::animatable_var_set::AnimatableVarSet;
73
74pub use vizia_style::{
75 Alignment, Angle, BackgroundImage, BackgroundSize, BorderStyleKeyword, ClipPath, Color,
76 CornerShape, CssRule, CursorIcon, Direction, Display, Filter, FontFamily, FontSize,
77 FontSizeKeyword, FontSlant, FontVariation, FontWeight, FontWeightKeyword, FontWidth,
78 GenericFontFamily, Gradient, HorizontalPosition, HorizontalPositionKeyword, LayoutWrap, Length,
79 LengthOrPercentage, LengthValue, LetterSpacing, LineClamp, LineDirection, LineHeight,
80 LinearGradient, Matrix, Opacity, Overflow, PointerEvents, Position, PositionType, RGBA, Scale,
81 Shadow, TextAlign, TextDecorationLine, TextDecorationStyle, TextOverflow, TextStroke,
82 TextStrokeStyle, Transform, Transition, Translate, VerticalPosition, VerticalPositionKeyword,
83 Visibility,
84};
85
86use cssparser::Token as CssToken;
87use vizia_style::{
88 BlendMode, EasingFunction, KeyframeSelector, ParserOptions, Property, Selectors, StyleSheet,
89 TokenList, TokenOrValue, Variable,
90};
91
92mod rule;
93pub(crate) use rule::Rule;
94
95mod pseudoclass;
96pub(crate) use pseudoclass::*;
97
98mod transform;
99pub(crate) use transform::*;
100
101use crate::animation::{AnimationState, Interpolator, Keyframe, TimingFunction};
102use crate::storage::animatable_set::AnimatableSet;
103use crate::storage::style_set::StyleSet;
104use bitflags::bitflags;
105use vizia_id::IdManager;
106use vizia_storage::SparseSet;
107
108bitflags! {
109 #[derive(Debug, Clone, Copy)]
111 pub(crate) struct Abilities: u8 {
112 const HOVERABLE = 1 << 0;
114 const FOCUSABLE = 1 << 1;
116 const CHECKABLE = 1 << 2;
118 const NAVIGABLE = 1 << 3;
120 const DRAGGABLE = 1 << 4;
122 }
123}
124
125impl Default for Abilities {
126 fn default() -> Abilities {
127 Abilities::HOVERABLE
128 }
129}
130
131bitflags! {
132 pub(crate) struct SystemFlags: u8 {
133 const RELAYOUT = 1;
134 const RESTYLE = 1 << 1;
135 const REFLOW = 1 << 2;
136 const REDRAW = 1 << 3;
137 const RETRANSFORM = 1 << 4;
138 const RECLIP = 1 << 5;
139 const REACCESS = 1 << 6;
140 }
141}
142
143impl Default for SystemFlags {
144 fn default() -> Self {
145 SystemFlags::all()
146 }
147}
148
149#[derive(Debug, Clone, PartialEq)]
151pub enum ImageOrGradient {
152 Image(String),
154 Gradient(Gradient),
156}
157
158#[derive(Debug, Clone, PartialEq, Eq)]
160pub enum FamilyOwned {
161 Generic(GenericFontFamily),
163 Named(String),
165}
166
167impl AsRef<str> for FamilyOwned {
168 fn as_ref(&self) -> &str {
169 match self {
170 FamilyOwned::Generic(generic) => match generic {
171 GenericFontFamily::Serif => "serif",
172 GenericFontFamily::SansSerif => "sans-serif",
173 GenericFontFamily::Cursive => todo!(),
174 GenericFontFamily::Fantasy => todo!(),
175 GenericFontFamily::Monospace => "Cascadia Mono",
176 },
177 FamilyOwned::Named(family) => family.as_str(),
178 }
179 }
180}
181
182pub(crate) struct StyleRule {
183 pub(crate) selector: Selector<Selectors>,
184 pub(crate) hashes: AncestorHashes,
186}
187
188impl StyleRule {
189 pub(crate) fn new(selector: Selector<Selectors>) -> Self {
190 let hashes = AncestorHashes::new(&selector, vizia_style::QuirksMode::NoQuirks);
191 Self { selector, hashes }
192 }
193}
194
195#[derive(Default)]
197pub struct Style {
198 pub(crate) rule_manager: IdManager<Rule>,
199
200 pub(crate) animation_manager: IdManager<Animation>,
202 pub(crate) animations: HashMap<String, Animation>,
203 pub(crate) pending_animations: Vec<(Entity, Animation, Duration, Duration)>,
205
206 pub(crate) rules: IndexMap<Rule, StyleRule>,
208
209 pub(crate) default_font: Vec<FamilyOwned>,
210
211 pub(crate) element: SparseSet<u32>,
213 pub(crate) ids: SparseSet<String>,
214 pub(crate) classes: SparseSet<HashSet<String>>,
215 pub(crate) pseudo_classes: SparseSet<PseudoClassFlags>,
216 pub(crate) disabled: StyleSet<bool>,
217 pub(crate) abilities: SparseSet<Abilities>,
218
219 pub(crate) name: StyleSet<String>,
221 pub(crate) role: SparseSet<Role>,
222 pub(crate) live: SparseSet<Live>,
223 pub(crate) labelled_by: SparseSet<String>,
224 pub(crate) described_by: SparseSet<String>,
225 pub(crate) controls: SparseSet<String>,
226 pub(crate) active_descendant: SparseSet<String>,
227 pub(crate) expanded: SparseSet<bool>,
228 pub(crate) selected: SparseSet<bool>,
229 pub(crate) hidden: SparseSet<bool>,
230 pub(crate) orientation: SparseSet<Orientation>,
231 pub(crate) text_value: SparseSet<String>,
232 pub(crate) numeric_value: SparseSet<f64>,
233
234 pub(crate) visibility: StyleSet<Visibility>,
236
237 pub(crate) opacity: AnimatableVarSet<Opacity>,
239
240 pub(crate) z_index: StyleSet<i32>,
242
243 pub(crate) ignore_clipping: StyleSet<bool>,
245
246 pub(crate) clip_path: AnimatableSet<ClipPath>,
248
249 pub(crate) overflowx: StyleSet<Overflow>,
251 pub(crate) overflowy: StyleSet<Overflow>,
252
253 pub(crate) filter: AnimatableSet<Filter>,
255 pub(crate) backdrop_filter: AnimatableSet<Filter>,
256
257 pub(crate) blend_mode: StyleSet<BlendMode>,
258
259 pub(crate) transform: AnimatableSet<Vec<Transform>>,
261 pub(crate) transform_origin: AnimatableSet<Translate>,
262 pub(crate) translate: AnimatableSet<Translate>,
263 pub(crate) rotate: AnimatableSet<Angle>,
264 pub(crate) scale: AnimatableSet<Scale>,
265
266 pub(crate) border_width: AnimatableVarSet<LengthOrPercentage>,
268 pub(crate) border_color: AnimatableVarSet<Color>,
269 pub(crate) border_style: StyleSet<BorderStyleKeyword>,
270
271 pub(crate) corner_top_left_shape: StyleSet<CornerShape>,
273 pub(crate) corner_top_right_shape: StyleSet<CornerShape>,
274 pub(crate) corner_bottom_left_shape: StyleSet<CornerShape>,
275 pub(crate) corner_bottom_right_shape: StyleSet<CornerShape>,
276
277 pub(crate) corner_top_left_radius: AnimatableVarSet<LengthOrPercentage>,
279 pub(crate) corner_top_right_radius: AnimatableVarSet<LengthOrPercentage>,
280 pub(crate) corner_bottom_left_radius: AnimatableVarSet<LengthOrPercentage>,
281 pub(crate) corner_bottom_right_radius: AnimatableVarSet<LengthOrPercentage>,
282
283 pub(crate) corner_top_left_smoothing: AnimatableSet<f32>,
285 pub(crate) corner_top_right_smoothing: AnimatableSet<f32>,
286 pub(crate) corner_bottom_left_smoothing: AnimatableSet<f32>,
287 pub(crate) corner_bottom_right_smoothing: AnimatableSet<f32>,
288
289 pub(crate) outline_width: AnimatableVarSet<LengthOrPercentage>,
291 pub(crate) outline_color: AnimatableVarSet<Color>,
292 pub(crate) outline_offset: AnimatableVarSet<LengthOrPercentage>,
293
294 pub(crate) background_color: AnimatableVarSet<Color>,
296 pub(crate) background_image: AnimatableSet<Vec<ImageOrGradient>>,
297 pub(crate) background_size: AnimatableSet<Vec<BackgroundSize>>,
298
299 pub(crate) shadow: AnimatableVarSet<Vec<Shadow>>,
301
302 pub(crate) text: SparseSet<String>,
304 pub(crate) text_wrap: StyleSet<bool>,
305 pub(crate) text_overflow: StyleSet<TextOverflow>,
306 pub(crate) letter_spacing: AnimatableVarSet<LetterSpacing>,
307 pub(crate) line_height: AnimatableVarSet<LineHeight>,
308 pub(crate) line_clamp: StyleSet<LineClamp>,
309 pub(crate) text_align: StyleSet<TextAlign>,
310 pub(crate) text_decoration_line: StyleSet<TextDecorationLine>,
311 pub(crate) text_decoration_style: StyleSet<TextDecorationStyle>,
312 pub(crate) text_decoration_color: AnimatableVarSet<Color>,
313 pub(crate) text_stroke_width: StyleSet<Length>,
314 pub(crate) text_stroke_style: StyleSet<TextStrokeStyle>,
315 pub(crate) font_family: StyleSet<Vec<FamilyOwned>>,
316 pub(crate) font_color: AnimatableVarSet<Color>,
317 pub(crate) font_size: AnimatableVarSet<FontSize>,
318 pub(crate) font_weight: StyleSet<FontWeight>,
319 pub(crate) font_slant: StyleSet<FontSlant>,
320 pub(crate) font_width: StyleSet<FontWidth>,
321 pub(crate) font_variation_settings: StyleSet<Vec<FontVariation>>,
322 pub(crate) caret_color: AnimatableVarSet<Color>,
323 pub(crate) selection_color: AnimatableVarSet<Color>,
324
325 pub(crate) fill: AnimatableVarSet<Color>,
326
327 pub(crate) cursor: StyleSet<CursorIcon>,
329
330 pub(crate) pointer_events: StyleSet<PointerEvents>,
331
332 pub(crate) display: AnimatableSet<Display>,
336
337 pub(crate) layout_type: StyleSet<LayoutType>,
339
340 pub(crate) position_type: StyleSet<PositionType>,
342
343 pub(crate) alignment: StyleSet<Alignment>,
344 pub(crate) direction: StyleSet<Direction>,
345 pub(crate) wrap: StyleSet<LayoutWrap>,
346
347 pub(crate) grid_columns: StyleSet<Vec<Units>>,
349 pub(crate) grid_rows: StyleSet<Vec<Units>>,
350
351 pub(crate) column_start: StyleSet<usize>,
352 pub(crate) column_span: StyleSet<usize>,
353 pub(crate) row_start: StyleSet<usize>,
354 pub(crate) row_span: StyleSet<usize>,
355
356 pub(crate) left: AnimatableVarSet<Units>,
358 pub(crate) right: AnimatableVarSet<Units>,
359 pub(crate) top: AnimatableVarSet<Units>,
360 pub(crate) bottom: AnimatableVarSet<Units>,
361
362 pub(crate) padding_left: AnimatableVarSet<Units>,
364 pub(crate) padding_right: AnimatableVarSet<Units>,
365 pub(crate) padding_top: AnimatableVarSet<Units>,
366 pub(crate) padding_bottom: AnimatableVarSet<Units>,
367 pub(crate) vertical_gap: AnimatableVarSet<Units>,
368 pub(crate) horizontal_gap: AnimatableVarSet<Units>,
369
370 pub(crate) vertical_scroll: AnimatableSet<f32>,
372 pub(crate) horizontal_scroll: AnimatableSet<f32>,
373
374 pub(crate) width: AnimatableVarSet<Units>,
376 pub(crate) height: AnimatableVarSet<Units>,
377
378 pub(crate) min_width: AnimatableVarSet<Units>,
380 pub(crate) max_width: AnimatableVarSet<Units>,
381 pub(crate) min_height: AnimatableVarSet<Units>,
382 pub(crate) max_height: AnimatableVarSet<Units>,
383
384 pub(crate) min_horizontal_gap: AnimatableVarSet<Units>,
386 pub(crate) max_horizontal_gap: AnimatableVarSet<Units>,
387 pub(crate) min_vertical_gap: AnimatableVarSet<Units>,
388 pub(crate) max_vertical_gap: AnimatableVarSet<Units>,
389
390 pub(crate) system_flags: SystemFlags,
391
392 pub(crate) restyle: HashSet<Entity>,
393 pub(crate) text_construction: HashSet<Entity>,
394 pub(crate) text_layout: HashSet<Entity>,
395 pub(crate) reaccess: HashSet<Entity>,
396 pub(crate) retransform: HashSet<Entity>,
397 pub(crate) reclip: HashSet<Entity>,
398
399 pub(crate) text_range: SparseSet<Range<usize>>,
400 pub(crate) text_span: SparseSet<bool>,
401
402 pub(crate) dpi_factor: f64,
404
405 pub(crate) custom_color_props: HashMap<u64, AnimatableVarSet<Color>>,
406 pub(crate) custom_length_props: HashMap<u64, AnimatableVarSet<LengthOrPercentage>>,
407 pub(crate) custom_font_size_props: HashMap<u64, AnimatableVarSet<FontSize>>,
408 pub(crate) custom_letter_spacing_props: HashMap<u64, AnimatableVarSet<LetterSpacing>>,
409 pub(crate) custom_line_height_props: HashMap<u64, AnimatableVarSet<LineHeight>>,
410 pub(crate) custom_units_props: HashMap<u64, AnimatableVarSet<Units>>,
411 pub(crate) custom_opacity_props: HashMap<u64, AnimatableVarSet<Opacity>>,
412 pub(crate) custom_shadow_props: HashMap<u64, AnimatableVarSet<Vec<Shadow>>>,
413}
414
415impl Style {
416 pub fn scale_factor(&self) -> f32 {
418 self.dpi_factor as f32
419 }
420
421 pub fn logical_to_physical(&self, logical: f32) -> f32 {
423 (logical * self.dpi_factor as f32).round()
424 }
425
426 pub fn physical_to_logical(&self, physical: f32) -> f32 {
428 physical / self.dpi_factor as f32
429 }
430
431 pub(crate) fn remove_rules(&mut self) {
432 self.rule_manager.reset();
433 self.rules.clear();
434 }
435
436 pub(crate) fn get_animation(&self, name: &str) -> Option<&Animation> {
437 self.animations.get(name)
438 }
439
440 pub(crate) fn add_keyframe(
441 &mut self,
442 animation_id: Animation,
443 time: f32,
444 properties: &[Property],
445 ) {
446 fn insert_keyframe<T: 'static + Interpolator + Debug + Clone + PartialEq + Default>(
447 storage: &mut AnimatableSet<T>,
448 animation_id: Animation,
449 time: f32,
450 value: T,
451 ) {
452 let keyframe = Keyframe { time, value, timing_function: TimingFunction::linear() };
453
454 if let Some(anim_state) = storage.get_animation_mut(animation_id) {
455 anim_state.keyframes.push(keyframe)
456 } else {
457 let anim_state = AnimationState::new(animation_id).with_keyframe(keyframe);
458 storage.insert_animation(animation_id, anim_state);
459 }
460 }
461
462 fn insert_keyframe2<T: 'static + Interpolator + Debug + Clone + PartialEq + Default>(
463 storage: &mut AnimatableVarSet<T>,
464 animation_id: Animation,
465 time: f32,
466 value: T,
467 ) {
468 let keyframe = Keyframe { time, value, timing_function: TimingFunction::linear() };
469
470 if let Some(anim_state) = storage.get_animation_mut(animation_id) {
471 anim_state.keyframes.push(keyframe)
472 } else {
473 let anim_state = AnimationState::new(animation_id).with_keyframe(keyframe);
474 storage.insert_animation(animation_id, anim_state);
475 }
476 }
477
478 for property in properties.iter() {
479 match property {
480 Property::Display(value) => {
482 insert_keyframe(&mut self.display, animation_id, time, *value);
483 }
484
485 Property::Opacity(value) => {
486 insert_keyframe2(&mut self.opacity, animation_id, time, *value);
487 }
488
489 Property::ClipPath(value) => {
490 insert_keyframe(&mut self.clip_path, animation_id, time, value.clone());
491 }
492
493 Property::Transform(value) => {
495 insert_keyframe(&mut self.transform, animation_id, time, value.clone());
496 }
497
498 Property::TransformOrigin(transform_origin) => {
499 let x = transform_origin.x.to_length_or_percentage();
500 let y = transform_origin.y.to_length_or_percentage();
501 let value = Translate { x, y };
502 insert_keyframe(&mut self.transform_origin, animation_id, time, value);
503 }
504
505 Property::Translate(value) => {
506 insert_keyframe(&mut self.translate, animation_id, time, value.clone());
507 }
508
509 Property::Rotate(value) => {
510 insert_keyframe(&mut self.rotate, animation_id, time, *value);
511 }
512
513 Property::Scale(value) => {
514 insert_keyframe(&mut self.scale, animation_id, time, *value);
515 }
516
517 Property::BorderWidth(value) => {
519 insert_keyframe2(
520 &mut self.border_width,
521 animation_id,
522 time,
523 value.left.0.clone(),
524 );
525 }
526
527 Property::BorderColor(value) => {
528 insert_keyframe2(&mut self.border_color, animation_id, time, *value);
529 }
530
531 Property::CornerTopLeftRadius(value) => {
532 insert_keyframe2(
533 &mut self.corner_top_left_radius,
534 animation_id,
535 time,
536 value.clone(),
537 );
538 }
539
540 Property::CornerTopRightRadius(value) => {
541 insert_keyframe2(
542 &mut self.corner_top_right_radius,
543 animation_id,
544 time,
545 value.clone(),
546 );
547 }
548
549 Property::CornerBottomLeftRadius(value) => {
550 insert_keyframe2(
551 &mut self.corner_bottom_left_radius,
552 animation_id,
553 time,
554 value.clone(),
555 );
556 }
557
558 Property::CornerBottomRightRadius(value) => {
559 insert_keyframe2(
560 &mut self.corner_bottom_right_radius,
561 animation_id,
562 time,
563 value.clone(),
564 );
565 }
566
567 Property::OutlineWidth(value) => {
569 insert_keyframe2(
570 &mut self.outline_width,
571 animation_id,
572 time,
573 value.left.0.clone(),
574 );
575 }
576
577 Property::OutlineColor(value) => {
578 insert_keyframe2(&mut self.outline_color, animation_id, time, *value);
579 }
580
581 Property::OutlineOffset(value) => {
582 insert_keyframe2(&mut self.outline_offset, animation_id, time, value.clone());
583 }
584
585 Property::BackgroundColor(value) => {
587 insert_keyframe2(&mut self.background_color, animation_id, time, *value);
588 }
589
590 Property::BackgroundImage(images) => {
591 let images = images
592 .iter()
593 .filter_map(|img| match img {
594 BackgroundImage::None => None,
595 BackgroundImage::Gradient(gradient) => {
596 Some(ImageOrGradient::Gradient(*gradient.clone()))
597 }
598 BackgroundImage::Url(url) => {
599 Some(ImageOrGradient::Image(url.url.to_string()))
600 }
601 })
602 .collect::<Vec<_>>();
603 insert_keyframe(&mut self.background_image, animation_id, time, images);
604 }
605
606 Property::BackgroundSize(value) => {
607 insert_keyframe(&mut self.background_size, animation_id, time, value.clone());
608 }
609
610 Property::Shadow(value) => {
612 insert_keyframe2(&mut self.shadow, animation_id, time, value.clone());
613 }
614
615 Property::FontColor(value) => {
617 insert_keyframe2(&mut self.font_color, animation_id, time, *value);
618 }
619
620 Property::FontSize(value) => {
621 insert_keyframe2(&mut self.font_size, animation_id, time, value.clone());
622 }
623
624 Property::LetterSpacing(value) => {
625 insert_keyframe2(&mut self.letter_spacing, animation_id, time, value.clone());
626 }
627
628 Property::LineHeight(value) => {
629 insert_keyframe2(&mut self.line_height, animation_id, time, value.clone());
630 }
631
632 Property::CaretColor(value) => {
633 insert_keyframe2(&mut self.caret_color, animation_id, time, *value);
634 }
635
636 Property::SelectionColor(value) => {
637 insert_keyframe2(&mut self.selection_color, animation_id, time, *value);
638 }
639
640 Property::Left(value) => {
642 insert_keyframe2(&mut self.left, animation_id, time, *value);
643 }
644
645 Property::Right(value) => {
646 insert_keyframe2(&mut self.right, animation_id, time, *value);
647 }
648
649 Property::Top(value) => {
650 insert_keyframe2(&mut self.top, animation_id, time, *value);
651 }
652
653 Property::Bottom(value) => {
654 insert_keyframe2(&mut self.bottom, animation_id, time, *value);
655 }
656
657 Property::PaddingLeft(value) => {
659 insert_keyframe2(&mut self.padding_left, animation_id, time, *value);
660 }
661
662 Property::PaddingRight(value) => {
663 insert_keyframe2(&mut self.padding_right, animation_id, time, *value);
664 }
665
666 Property::PaddingTop(value) => {
667 insert_keyframe2(&mut self.padding_top, animation_id, time, *value);
668 }
669
670 Property::PaddingBottom(value) => {
671 insert_keyframe2(&mut self.padding_bottom, animation_id, time, *value);
672 }
673
674 Property::HorizontalGap(value) => {
675 insert_keyframe2(&mut self.horizontal_gap, animation_id, time, *value);
676 }
677
678 Property::VerticalGap(value) => {
679 insert_keyframe2(&mut self.vertical_gap, animation_id, time, *value);
680 }
681
682 Property::Gap(value) => {
683 insert_keyframe2(&mut self.horizontal_gap, animation_id, time, *value);
684 insert_keyframe2(&mut self.vertical_gap, animation_id, time, *value);
685 }
686
687 Property::MinGap(value) => {
689 insert_keyframe2(&mut self.min_horizontal_gap, animation_id, time, *value);
690 insert_keyframe2(&mut self.min_vertical_gap, animation_id, time, *value);
691 }
692
693 Property::MaxGap(value) => {
694 insert_keyframe2(&mut self.max_horizontal_gap, animation_id, time, *value);
695 insert_keyframe2(&mut self.max_vertical_gap, animation_id, time, *value);
696 }
697
698 Property::MinHorizontalGap(value) => {
699 insert_keyframe2(&mut self.min_horizontal_gap, animation_id, time, *value);
700 }
701
702 Property::MaxHorizontalGap(value) => {
703 insert_keyframe2(&mut self.max_horizontal_gap, animation_id, time, *value);
704 }
705
706 Property::MinVerticalGap(value) => {
707 insert_keyframe2(&mut self.min_vertical_gap, animation_id, time, *value);
708 }
709
710 Property::MaxVerticalGap(value) => {
711 insert_keyframe2(&mut self.max_vertical_gap, animation_id, time, *value);
712 }
713
714 Property::Width(value) => {
716 insert_keyframe2(&mut self.width, animation_id, time, *value);
717 }
718
719 Property::Height(value) => {
720 insert_keyframe2(&mut self.height, animation_id, time, *value);
721 }
722
723 Property::MinWidth(value) => {
725 insert_keyframe2(&mut self.min_width, animation_id, time, *value);
726 }
727
728 Property::MaxWidth(value) => {
729 insert_keyframe2(&mut self.max_width, animation_id, time, *value);
730 }
731
732 Property::MinHeight(value) => {
733 insert_keyframe2(&mut self.min_height, animation_id, time, *value);
734 }
735
736 Property::MaxHeight(value) => {
737 insert_keyframe2(&mut self.max_height, animation_id, time, *value);
738 }
739
740 Property::TextDecorationColor(value) => {
741 insert_keyframe2(&mut self.text_decoration_color, animation_id, time, *value);
742 }
743
744 Property::Fill(value) => {
745 insert_keyframe2(&mut self.fill, animation_id, time, *value);
746 }
747
748 _ => {}
749 }
750 }
751 }
752
753 pub(crate) fn add_animation(&mut self, animation: AnimationBuilder) -> Animation {
754 let animation_id = self.animation_manager.create();
755 for keyframe in animation.keyframes.iter() {
756 self.add_keyframe(animation_id, keyframe.time, &keyframe.properties);
757 }
758
759 animation_id
760 }
761
762 pub(crate) fn enqueue_animation(
763 &mut self,
764 entity: Entity,
765 animation: Animation,
766 duration: Duration,
767 delay: Duration,
768 ) {
769 self.pending_animations.push((entity, animation, duration, delay));
770 }
771
772 pub(crate) fn play_pending_animations(&mut self) {
773 let start_time = Instant::now();
774
775 let pending_animations = self.pending_animations.drain(..).collect::<Vec<_>>();
776
777 for (entity, animation, duration, delay) in pending_animations {
778 self.play_animation(entity, animation, start_time + delay, duration, delay)
779 }
780 }
781
782 pub(crate) fn play_animation(
783 &mut self,
784 entity: Entity,
785 animation: Animation,
786 start_time: Instant,
787 duration: Duration,
788 delay: Duration,
789 ) {
790 self.display.play_animation(entity, animation, start_time, duration, delay);
791 self.opacity.play_animation(entity, animation, start_time, duration, delay);
792 self.clip_path.play_animation(entity, animation, start_time, duration, delay);
793
794 self.transform.play_animation(entity, animation, start_time, duration, delay);
795 self.transform_origin.play_animation(entity, animation, start_time, duration, delay);
796 self.translate.play_animation(entity, animation, start_time, duration, delay);
797 self.rotate.play_animation(entity, animation, start_time, duration, delay);
798 self.scale.play_animation(entity, animation, start_time, duration, delay);
799
800 self.border_width.play_animation(entity, animation, start_time, duration, delay);
801 self.border_color.play_animation(entity, animation, start_time, duration, delay);
802
803 self.corner_top_left_radius.play_animation(entity, animation, start_time, duration, delay);
804 self.corner_top_right_radius.play_animation(entity, animation, start_time, duration, delay);
805 self.corner_bottom_left_radius
806 .play_animation(entity, animation, start_time, duration, delay);
807 self.corner_bottom_right_radius
808 .play_animation(entity, animation, start_time, duration, delay);
809
810 self.outline_width.play_animation(entity, animation, start_time, duration, delay);
811 self.outline_color.play_animation(entity, animation, start_time, duration, delay);
812 self.outline_offset.play_animation(entity, animation, start_time, duration, delay);
813
814 self.background_color.play_animation(entity, animation, start_time, duration, delay);
815 self.background_image.play_animation(entity, animation, start_time, duration, delay);
816 self.background_size.play_animation(entity, animation, start_time, duration, delay);
817
818 self.shadow.play_animation(entity, animation, start_time, duration, delay);
819
820 self.font_color.play_animation(entity, animation, start_time, duration, delay);
821 self.font_size.play_animation(entity, animation, start_time, duration, delay);
822 self.letter_spacing.play_animation(entity, animation, start_time, duration, delay);
823 self.line_height.play_animation(entity, animation, start_time, duration, delay);
824 self.caret_color.play_animation(entity, animation, start_time, duration, delay);
825 self.selection_color.play_animation(entity, animation, start_time, duration, delay);
826
827 self.left.play_animation(entity, animation, start_time, duration, delay);
828 self.right.play_animation(entity, animation, start_time, duration, delay);
829 self.top.play_animation(entity, animation, start_time, duration, delay);
830 self.bottom.play_animation(entity, animation, start_time, duration, delay);
831
832 self.padding_left.play_animation(entity, animation, start_time, duration, delay);
833 self.padding_right.play_animation(entity, animation, start_time, duration, delay);
834 self.padding_top.play_animation(entity, animation, start_time, duration, delay);
835 self.padding_bottom.play_animation(entity, animation, start_time, duration, delay);
836 self.horizontal_gap.play_animation(entity, animation, start_time, duration, delay);
837 self.vertical_gap.play_animation(entity, animation, start_time, duration, delay);
838
839 self.width.play_animation(entity, animation, start_time, duration, delay);
840 self.height.play_animation(entity, animation, start_time, duration, delay);
841
842 self.min_width.play_animation(entity, animation, start_time, duration, delay);
843 self.max_width.play_animation(entity, animation, start_time, duration, delay);
844 self.min_height.play_animation(entity, animation, start_time, duration, delay);
845 self.max_height.play_animation(entity, animation, start_time, duration, delay);
846
847 self.min_horizontal_gap.play_animation(entity, animation, start_time, duration, delay);
848 self.max_horizontal_gap.play_animation(entity, animation, start_time, duration, delay);
849 self.min_vertical_gap.play_animation(entity, animation, start_time, duration, delay);
850 self.max_vertical_gap.play_animation(entity, animation, start_time, duration, delay);
851
852 self.text_decoration_color.play_animation(entity, animation, start_time, duration, delay);
853
854 self.fill.play_animation(entity, animation, start_time, duration, delay);
855
856 for store in self.custom_color_props.values_mut() {
858 store.play_animation(entity, animation, start_time, duration, delay);
859 }
860 for store in self.custom_length_props.values_mut() {
862 store.play_animation(entity, animation, start_time, duration, delay);
863 }
864 for store in self.custom_font_size_props.values_mut() {
866 store.play_animation(entity, animation, start_time, duration, delay);
867 }
868 for store in self.custom_letter_spacing_props.values_mut() {
870 store.play_animation(entity, animation, start_time, duration, delay);
871 }
872 for store in self.custom_line_height_props.values_mut() {
874 store.play_animation(entity, animation, start_time, duration, delay);
875 }
876 for store in self.custom_units_props.values_mut() {
878 store.play_animation(entity, animation, start_time, duration, delay);
879 }
880 for store in self.custom_opacity_props.values_mut() {
882 store.play_animation(entity, animation, start_time, duration, delay);
883 }
884 for store in self.custom_shadow_props.values_mut() {
886 store.play_animation(entity, animation, start_time, duration, delay);
887 }
888 }
889
890 pub(crate) fn is_animating(&self, entity: Entity, animation: Animation) -> bool {
891 self.display.has_active_animation(entity, animation)
892 | self.opacity.has_active_animation(entity, animation)
893 | self.clip_path.has_active_animation(entity, animation)
894 | self.transform.has_active_animation(entity, animation)
895 | self.transform_origin.has_active_animation(entity, animation)
896 | self.translate.has_active_animation(entity, animation)
897 | self.rotate.has_active_animation(entity, animation)
898 | self.scale.has_active_animation(entity, animation)
899 | self.border_width.has_active_animation(entity, animation)
900 | self.border_color.has_active_animation(entity, animation)
901 | self.corner_top_left_radius.has_active_animation(entity, animation)
902 | self.corner_top_right_radius.has_active_animation(entity, animation)
903 | self.corner_bottom_left_radius.has_active_animation(entity, animation)
904 | self.corner_bottom_right_radius.has_active_animation(entity, animation)
905 | self.outline_width.has_active_animation(entity, animation)
906 | self.outline_color.has_active_animation(entity, animation)
907 | self.outline_offset.has_active_animation(entity, animation)
908 | self.background_color.has_active_animation(entity, animation)
909 | self.background_image.has_active_animation(entity, animation)
910 | self.background_size.has_active_animation(entity, animation)
911 | self.shadow.has_active_animation(entity, animation)
912 | self.font_color.has_active_animation(entity, animation)
913 | self.font_size.has_active_animation(entity, animation)
914 | self.letter_spacing.has_active_animation(entity, animation)
915 | self.line_height.has_active_animation(entity, animation)
916 | self.caret_color.has_active_animation(entity, animation)
917 | self.selection_color.has_active_animation(entity, animation)
918 | self.left.has_active_animation(entity, animation)
919 | self.right.has_active_animation(entity, animation)
920 | self.top.has_active_animation(entity, animation)
921 | self.bottom.has_active_animation(entity, animation)
922 | self.padding_left.has_active_animation(entity, animation)
923 | self.padding_right.has_active_animation(entity, animation)
924 | self.padding_top.has_active_animation(entity, animation)
925 | self.padding_bottom.has_active_animation(entity, animation)
926 | self.horizontal_gap.has_active_animation(entity, animation)
927 | self.vertical_gap.has_active_animation(entity, animation)
928 | self.width.has_active_animation(entity, animation)
929 | self.height.has_active_animation(entity, animation)
930 | self.min_width.has_active_animation(entity, animation)
931 | self.max_width.has_active_animation(entity, animation)
932 | self.min_height.has_active_animation(entity, animation)
933 | self.max_height.has_active_animation(entity, animation)
934 | self.min_horizontal_gap.has_active_animation(entity, animation)
935 | self.max_horizontal_gap.has_active_animation(entity, animation)
936 | self.min_vertical_gap.has_active_animation(entity, animation)
937 | self.max_vertical_gap.has_active_animation(entity, animation)
938 | self.text_decoration_color.has_active_animation(entity, animation)
939 | self.fill.has_active_animation(entity, animation)
940 }
941
942 pub(crate) fn parse_theme(&mut self, stylesheet: &str) {
943 if let Ok(stylesheet) = StyleSheet::parse(stylesheet, ParserOptions::new()) {
944 let rules = stylesheet.rules.0;
945
946 for rule in rules {
947 match rule {
948 CssRule::Style(style_rule) => {
949 for selector in style_rule.selectors.slice() {
952 let rule_id = self.rule_manager.create();
953
954 for property in style_rule.declarations.declarations.iter() {
955 match property {
956 Property::Transition(transitions) => {
957 for transition in transitions.iter() {
958 self.insert_transition(rule_id, transition);
959 }
960 }
961
962 _ => {
963 self.insert_property(rule_id, property);
964 }
965 }
966 }
967
968 self.rules.insert(rule_id, StyleRule::new(selector.clone()));
969 }
970 }
971
972 CssRule::Keyframes(keyframes_rule) => {
973 let name = keyframes_rule.name.as_string();
974
975 let animation_id = self.animation_manager.create();
976
977 for keyframes in keyframes_rule.keyframes {
978 for selector in keyframes.selectors.iter() {
979 let time = match selector {
980 KeyframeSelector::From => 0.0,
981 KeyframeSelector::To => 1.0,
982 KeyframeSelector::Percentage(percentage) => {
983 percentage.0 / 100.0
984 }
985 };
986
987 self.add_keyframe(
988 animation_id,
989 time,
990 &keyframes.declarations.declarations,
991 );
992 }
993 }
994
995 self.animations.insert(name, animation_id);
996 }
997
998 _ => {}
999 }
1000 }
1001 } else {
1002 println!("Failed to parse stylesheet");
1003 }
1004 }
1005
1006 fn insert_transition(&mut self, rule_id: Rule, transition: &Transition) {
1007 let animation = self.animation_manager.create();
1008 match transition.property.as_ref() {
1009 "display" => {
1010 self.display.insert_animation(animation, self.add_transition(transition));
1011 self.display.insert_transition(rule_id, animation);
1012 }
1013
1014 "opacity" => {
1015 self.opacity.insert_animation(animation, self.add_transition(transition));
1016 self.opacity.insert_transition(rule_id, animation);
1017 }
1018
1019 "clip-path" => {
1020 self.clip_path.insert_animation(animation, self.add_transition(transition));
1021 self.clip_path.insert_transition(rule_id, animation);
1022 }
1023
1024 "transform" => {
1025 self.transform.insert_animation(animation, self.add_transition(transition));
1026 self.transform.insert_transition(rule_id, animation);
1027 }
1028
1029 "transform-origin" => {
1030 self.transform_origin.insert_animation(animation, self.add_transition(transition));
1031 self.transform_origin.insert_transition(rule_id, animation);
1032 }
1033
1034 "translate" => {
1035 self.translate.insert_animation(animation, self.add_transition(transition));
1036 self.translate.insert_transition(rule_id, animation);
1037 }
1038
1039 "rotate" => {
1040 self.rotate.insert_animation(animation, self.add_transition(transition));
1041 self.rotate.insert_transition(rule_id, animation);
1042 }
1043
1044 "scale" => {
1045 self.scale.insert_animation(animation, self.add_transition(transition));
1046 self.scale.insert_transition(rule_id, animation);
1047 }
1048
1049 "border" => {
1050 self.border_width.insert_animation(animation, self.add_transition(transition));
1051 self.border_width.insert_transition(rule_id, animation);
1052 self.border_color.insert_animation(animation, self.add_transition(transition));
1053 self.border_color.insert_transition(rule_id, animation);
1054 }
1055
1056 "border-width" => {
1057 self.border_width.insert_animation(animation, self.add_transition(transition));
1058 self.border_width.insert_transition(rule_id, animation);
1059 }
1060
1061 "border-color" => {
1062 self.border_color.insert_animation(animation, self.add_transition(transition));
1063 self.border_color.insert_transition(rule_id, animation);
1064 }
1065
1066 "corner-radius" => {
1067 self.corner_bottom_left_radius
1068 .insert_animation(animation, self.add_transition(transition));
1069 self.corner_bottom_left_radius.insert_transition(rule_id, animation);
1070 self.corner_bottom_right_radius
1071 .insert_animation(animation, self.add_transition(transition));
1072 self.corner_bottom_right_radius.insert_transition(rule_id, animation);
1073 self.corner_top_left_radius
1074 .insert_animation(animation, self.add_transition(transition));
1075 self.corner_top_left_radius.insert_transition(rule_id, animation);
1076 self.corner_top_right_radius
1077 .insert_animation(animation, self.add_transition(transition));
1078 self.corner_top_right_radius.insert_transition(rule_id, animation);
1079 }
1080
1081 "corner-top-left-radius" => {
1082 self.corner_top_left_radius
1083 .insert_animation(animation, self.add_transition(transition));
1084 self.corner_top_left_radius.insert_transition(rule_id, animation);
1085 }
1086
1087 "corner-top-right-radius" => {
1088 self.corner_top_right_radius
1089 .insert_animation(animation, self.add_transition(transition));
1090 self.corner_top_right_radius.insert_transition(rule_id, animation);
1091 }
1092
1093 "corner-bottom-left-radius" => {
1094 self.corner_bottom_left_radius
1095 .insert_animation(animation, self.add_transition(transition));
1096 self.corner_bottom_left_radius.insert_transition(rule_id, animation);
1097 }
1098
1099 "corner-bottom-right-radius" => {
1100 self.corner_bottom_right_radius
1101 .insert_animation(animation, self.add_transition(transition));
1102 self.corner_bottom_right_radius.insert_transition(rule_id, animation);
1103 }
1104
1105 "outline" => {
1106 self.outline_width.insert_animation(animation, self.add_transition(transition));
1107 self.outline_width.insert_transition(rule_id, animation);
1108 self.outline_color.insert_animation(animation, self.add_transition(transition));
1109 self.outline_color.insert_transition(rule_id, animation);
1110 }
1111
1112 "outline-width" => {
1113 self.outline_width.insert_animation(animation, self.add_transition(transition));
1114 self.outline_width.insert_transition(rule_id, animation);
1115 }
1116
1117 "outline-color" => {
1118 self.outline_color.insert_animation(animation, self.add_transition(transition));
1119 self.outline_color.insert_transition(rule_id, animation);
1120 }
1121
1122 "outline-offset" => {
1123 self.outline_offset.insert_animation(animation, self.add_transition(transition));
1124 self.outline_offset.insert_transition(rule_id, animation);
1125 }
1126
1127 "background-color" => {
1128 self.background_color.insert_animation(animation, self.add_transition(transition));
1129 self.background_color.insert_transition(rule_id, animation);
1130 }
1131
1132 "background-image" => {
1133 self.background_image.insert_animation(animation, self.add_transition(transition));
1134 self.background_image.insert_transition(rule_id, animation);
1135 }
1136
1137 "background-size" => {
1138 self.background_size.insert_animation(animation, self.add_transition(transition));
1139 self.background_size.insert_transition(rule_id, animation);
1140 }
1141
1142 "shadow" => {
1143 self.shadow.insert_animation(animation, self.add_transition(transition));
1144 self.shadow.insert_transition(rule_id, animation);
1145 }
1146
1147 "color" => {
1148 self.font_color.insert_animation(animation, self.add_transition(transition));
1149 self.font_color.insert_transition(rule_id, animation);
1150 }
1151
1152 "font-size" => {
1153 self.font_size.insert_animation(animation, self.add_transition(transition));
1154 self.font_size.insert_transition(rule_id, animation);
1155 }
1156
1157 "letter-spacing" => {
1158 self.letter_spacing.insert_animation(animation, self.add_transition(transition));
1159 self.letter_spacing.insert_transition(rule_id, animation);
1160 }
1161
1162 "line-height" => {
1163 self.line_height.insert_animation(animation, self.add_transition(transition));
1164 self.line_height.insert_transition(rule_id, animation);
1165 }
1166
1167 "caret-color" => {
1168 self.caret_color.insert_animation(animation, self.add_transition(transition));
1169 self.caret_color.insert_transition(rule_id, animation);
1170 }
1171
1172 "selection-color" => {
1173 self.selection_color.insert_animation(animation, self.add_transition(transition));
1174 self.selection_color.insert_transition(rule_id, animation);
1175 }
1176
1177 "left" => {
1178 self.left.insert_animation(animation, self.add_transition(transition));
1179 self.left.insert_transition(rule_id, animation);
1180 }
1181
1182 "right" => {
1183 self.right.insert_animation(animation, self.add_transition(transition));
1184 self.right.insert_transition(rule_id, animation);
1185 }
1186
1187 "top" => {
1188 self.top.insert_animation(animation, self.add_transition(transition));
1189 self.top.insert_transition(rule_id, animation);
1190 }
1191
1192 "bottom" => {
1193 self.bottom.insert_animation(animation, self.add_transition(transition));
1194 self.bottom.insert_transition(rule_id, animation);
1195 }
1196
1197 "padding-left" => {
1198 self.padding_left.insert_animation(animation, self.add_transition(transition));
1199 self.padding_left.insert_transition(rule_id, animation);
1200 }
1201
1202 "padding-right" => {
1203 self.padding_right.insert_animation(animation, self.add_transition(transition));
1204 self.padding_right.insert_transition(rule_id, animation);
1205 }
1206
1207 "padding-top" => {
1208 self.padding_top.insert_animation(animation, self.add_transition(transition));
1209 self.padding_top.insert_transition(rule_id, animation);
1210 }
1211
1212 "padding-bottom" => {
1213 self.padding_bottom.insert_animation(animation, self.add_transition(transition));
1214 self.padding_bottom.insert_transition(rule_id, animation);
1215 }
1216
1217 "horizontal-gap" => {
1218 self.horizontal_gap.insert_animation(animation, self.add_transition(transition));
1219 self.horizontal_gap.insert_transition(rule_id, animation);
1220 }
1221
1222 "vertical-gap" => {
1223 self.vertical_gap.insert_animation(animation, self.add_transition(transition));
1224 self.vertical_gap.insert_transition(rule_id, animation);
1225 }
1226
1227 "gap" => {
1228 self.horizontal_gap.insert_animation(animation, self.add_transition(transition));
1229 self.horizontal_gap.insert_transition(rule_id, animation);
1230 self.vertical_gap.insert_animation(animation, self.add_transition(transition));
1231 self.vertical_gap.insert_transition(rule_id, animation);
1232 }
1233
1234 "width" => {
1235 self.width.insert_animation(animation, self.add_transition(transition));
1236 self.width.insert_transition(rule_id, animation);
1237 }
1238
1239 "height" => {
1240 self.height.insert_animation(animation, self.add_transition(transition));
1241 self.height.insert_transition(rule_id, animation);
1242 }
1243
1244 "min-width" => {
1245 self.min_width.insert_animation(animation, self.add_transition(transition));
1246 self.min_width.insert_transition(rule_id, animation);
1247 }
1248
1249 "max-width" => {
1250 self.max_width.insert_animation(animation, self.add_transition(transition));
1251 self.max_width.insert_transition(rule_id, animation);
1252 }
1253
1254 "min-height" => {
1255 self.min_height.insert_animation(animation, self.add_transition(transition));
1256 self.min_height.insert_transition(rule_id, animation);
1257 }
1258
1259 "max-height" => {
1260 self.max_height.insert_animation(animation, self.add_transition(transition));
1261 self.max_height.insert_transition(rule_id, animation);
1262 }
1263
1264 "min-horizontal-gap" => {
1265 self.min_horizontal_gap
1266 .insert_animation(animation, self.add_transition(transition));
1267 self.min_horizontal_gap.insert_transition(rule_id, animation);
1268 }
1269
1270 "max-horizontal-gap" => {
1271 self.max_horizontal_gap
1272 .insert_animation(animation, self.add_transition(transition));
1273 self.max_horizontal_gap.insert_transition(rule_id, animation);
1274 }
1275
1276 "min-vertical-gap" => {
1277 self.min_vertical_gap.insert_animation(animation, self.add_transition(transition));
1278 self.min_vertical_gap.insert_transition(rule_id, animation);
1279 }
1280
1281 "max-vertical-gap" => {
1282 self.max_vertical_gap.insert_animation(animation, self.add_transition(transition));
1283 self.max_vertical_gap.insert_transition(rule_id, animation);
1284 }
1285
1286 "text-decoration-color" => {
1287 self.text_decoration_color
1288 .insert_animation(animation, self.add_transition(transition));
1289 self.text_decoration_color.insert_transition(rule_id, animation);
1290 }
1291
1292 "fill" => {
1293 self.fill.insert_animation(animation, self.add_transition(transition));
1294 self.fill.insert_transition(rule_id, animation);
1295 }
1296
1297 property_name if property_name.starts_with("--") => {
1298 let mut s = DefaultHasher::new();
1299 property_name.hash(&mut s);
1300 let variable_name_hash = s.finish();
1301 let anim_color: AnimationState<Color> = self.add_transition(transition);
1304 let anim_length: AnimationState<LengthOrPercentage> =
1305 self.add_transition(transition);
1306 let anim_font_size: AnimationState<FontSize> = self.add_transition(transition);
1307 let anim_letter_spacing: AnimationState<LetterSpacing> =
1308 self.add_transition(transition);
1309 let anim_line_height: AnimationState<LineHeight> = self.add_transition(transition);
1310 let anim_units: AnimationState<Units> = self.add_transition(transition);
1311 let anim_opacity: AnimationState<Opacity> = self.add_transition(transition);
1312
1313 if let Some(store) = self.custom_color_props.get_mut(&variable_name_hash) {
1316 store.insert_animation(animation, anim_color);
1317 store.insert_transition(rule_id, animation);
1318 } else {
1319 let mut store = AnimatableVarSet::default();
1320 store.insert_animation(animation, anim_color);
1321 store.insert_transition(rule_id, animation);
1322 self.custom_color_props.insert(variable_name_hash, store);
1323 }
1324
1325 if let Some(store) = self.custom_length_props.get_mut(&variable_name_hash) {
1326 store.insert_animation(animation, anim_length);
1327 store.insert_transition(rule_id, animation);
1328 } else {
1329 let mut store = AnimatableVarSet::default();
1330 store.insert_animation(animation, anim_length);
1331 store.insert_transition(rule_id, animation);
1332 self.custom_length_props.insert(variable_name_hash, store);
1333 }
1334
1335 if let Some(store) = self.custom_font_size_props.get_mut(&variable_name_hash) {
1336 store.insert_animation(animation, anim_font_size);
1337 store.insert_transition(rule_id, animation);
1338 } else {
1339 let mut store = AnimatableVarSet::default();
1340 store.insert_animation(animation, anim_font_size);
1341 store.insert_transition(rule_id, animation);
1342 self.custom_font_size_props.insert(variable_name_hash, store);
1343 }
1344
1345 if let Some(store) = self.custom_letter_spacing_props.get_mut(&variable_name_hash) {
1346 store.insert_animation(animation, anim_letter_spacing);
1347 store.insert_transition(rule_id, animation);
1348 } else {
1349 let mut store = AnimatableVarSet::default();
1350 store.insert_animation(animation, anim_letter_spacing);
1351 store.insert_transition(rule_id, animation);
1352 self.custom_letter_spacing_props.insert(variable_name_hash, store);
1353 }
1354
1355 if let Some(store) = self.custom_line_height_props.get_mut(&variable_name_hash) {
1356 store.insert_animation(animation, anim_line_height);
1357 store.insert_transition(rule_id, animation);
1358 } else {
1359 let mut store = AnimatableVarSet::default();
1360 store.insert_animation(animation, anim_line_height);
1361 store.insert_transition(rule_id, animation);
1362 self.custom_line_height_props.insert(variable_name_hash, store);
1363 }
1364
1365 if let Some(store) = self.custom_units_props.get_mut(&variable_name_hash) {
1366 store.insert_animation(animation, anim_units);
1367 store.insert_transition(rule_id, animation);
1368 } else {
1369 let mut store = AnimatableVarSet::default();
1370 store.insert_animation(animation, anim_units);
1371 store.insert_transition(rule_id, animation);
1372 self.custom_units_props.insert(variable_name_hash, store);
1373 }
1374
1375 if let Some(store) = self.custom_opacity_props.get_mut(&variable_name_hash) {
1376 store.insert_animation(animation, anim_opacity);
1377 store.insert_transition(rule_id, animation);
1378 } else {
1379 let mut store = AnimatableVarSet::default();
1380 store.insert_animation(animation, anim_opacity);
1381 store.insert_transition(rule_id, animation);
1382 self.custom_opacity_props.insert(variable_name_hash, store);
1383 }
1384 }
1385
1386 _ => {}
1387 }
1388 }
1389
1390 fn insert_property(&mut self, rule_id: Rule, property: &Property) {
1391 fn variable_hash(var: &Variable<'_>) -> u64 {
1392 let mut s = DefaultHasher::new();
1393 var.name.hash(&mut s);
1394 s.finish()
1395 }
1396
1397 fn first_fallback_token<'i>(var: &'i Variable<'i>) -> Option<&'i TokenOrValue<'i>> {
1398 var.fallback.as_ref().and_then(|TokenList(tokens)| tokens.first())
1399 }
1400
1401 fn color_fallback(var: &Variable<'_>) -> Option<Color> {
1402 match first_fallback_token(var) {
1403 Some(TokenOrValue::Color(color)) => Some(*color),
1404 _ => None,
1405 }
1406 }
1407
1408 fn length_fallback(var: &Variable<'_>) -> Option<LengthOrPercentage> {
1409 match first_fallback_token(var) {
1410 Some(TokenOrValue::Token(CssToken::Dimension { value, unit, .. }))
1411 if unit.as_ref().eq_ignore_ascii_case("px") =>
1412 {
1413 Some(LengthOrPercentage::Length(Length::Value(LengthValue::Px(*value))))
1414 }
1415
1416 Some(TokenOrValue::Token(CssToken::Percentage { unit_value, .. })) => {
1417 Some(LengthOrPercentage::Percentage(*unit_value * 100.0))
1418 }
1419
1420 _ => None,
1421 }
1422 }
1423
1424 fn font_size_fallback(var: &Variable<'_>) -> Option<FontSize> {
1425 match first_fallback_token(var) {
1426 Some(TokenOrValue::Token(CssToken::Dimension { value, unit, .. }))
1427 if unit.as_ref().eq_ignore_ascii_case("px") =>
1428 {
1429 Some(FontSize(Length::Value(LengthValue::Px(*value))))
1430 }
1431
1432 _ => None,
1433 }
1434 }
1435
1436 fn letter_spacing_fallback(var: &Variable<'_>) -> Option<LetterSpacing> {
1437 match first_fallback_token(var) {
1438 Some(TokenOrValue::Token(CssToken::Dimension { value, unit, .. }))
1439 if unit.as_ref().eq_ignore_ascii_case("px") =>
1440 {
1441 Some(LetterSpacing::Length(Length::Value(LengthValue::Px(*value))))
1442 }
1443
1444 Some(TokenOrValue::Token(CssToken::Ident(ident)))
1445 if ident.as_ref().eq_ignore_ascii_case("normal") =>
1446 {
1447 Some(LetterSpacing::Normal)
1448 }
1449
1450 _ => None,
1451 }
1452 }
1453
1454 fn line_height_fallback(var: &Variable<'_>) -> Option<LineHeight> {
1455 match first_fallback_token(var) {
1456 Some(TokenOrValue::Token(CssToken::Dimension { value, unit, .. }))
1457 if unit.as_ref().eq_ignore_ascii_case("px") =>
1458 {
1459 Some(LineHeight::Length(Length::Value(LengthValue::Px(*value))))
1460 }
1461
1462 Some(TokenOrValue::Token(CssToken::Percentage { unit_value, .. })) => {
1463 Some(LineHeight::Percentage(*unit_value * 100.0))
1464 }
1465
1466 Some(TokenOrValue::Token(CssToken::Number { value, .. })) => {
1467 Some(LineHeight::Number(*value))
1468 }
1469
1470 Some(TokenOrValue::Token(CssToken::Ident(ident)))
1471 if ident.as_ref().eq_ignore_ascii_case("normal") =>
1472 {
1473 Some(LineHeight::Normal)
1474 }
1475
1476 _ => None,
1477 }
1478 }
1479
1480 fn units_fallback(var: &Variable<'_>) -> Option<Units> {
1481 match first_fallback_token(var) {
1482 Some(TokenOrValue::Token(CssToken::Dimension { value, unit, .. }))
1483 if unit.as_ref().eq_ignore_ascii_case("px") =>
1484 {
1485 Some(Units::Pixels(*value))
1486 }
1487
1488 Some(TokenOrValue::Token(CssToken::Dimension { value, unit, .. }))
1489 if unit.as_ref().eq_ignore_ascii_case("s") =>
1490 {
1491 Some(Units::Stretch(*value))
1492 }
1493
1494 Some(TokenOrValue::Token(CssToken::Ident(ident)))
1495 if ident.as_ref().eq_ignore_ascii_case("auto") =>
1496 {
1497 Some(Units::Auto)
1498 }
1499
1500 Some(TokenOrValue::Token(CssToken::Percentage { unit_value, .. })) => {
1501 Some(Units::Percentage(*unit_value * 100.0))
1502 }
1503
1504 _ => None,
1505 }
1506 }
1507
1508 fn opacity_fallback(var: &Variable<'_>) -> Option<Opacity> {
1509 match first_fallback_token(var) {
1510 Some(TokenOrValue::Token(CssToken::Percentage { unit_value, .. })) => {
1511 Some(Opacity(*unit_value))
1512 }
1513
1514 Some(TokenOrValue::Token(CssToken::Number { value, .. })) => Some(Opacity(*value)),
1515
1516 _ => None,
1517 }
1518 }
1519
1520 fn parse_shadow_list(tokens: &[TokenOrValue<'_>]) -> Option<Vec<Shadow>> {
1521 fn parse_shadow_length(token: &TokenOrValue<'_>) -> Option<Length> {
1522 match token {
1523 TokenOrValue::Token(CssToken::Dimension { value, unit, .. })
1524 if unit.as_ref().eq_ignore_ascii_case("px") =>
1525 {
1526 Some(Length::Value(LengthValue::Px(*value)))
1527 }
1528
1529 TokenOrValue::Token(CssToken::Number { value, .. }) if *value == 0.0 => {
1530 Some(Length::Value(LengthValue::Px(0.0)))
1531 }
1532
1533 _ => None,
1534 }
1535 }
1536
1537 fn parse_single_shadow(tokens: &[TokenOrValue<'_>]) -> Option<Shadow> {
1538 let mut lengths: Vec<Length> = Vec::new();
1539 let mut color = None;
1540 let mut inset = false;
1541
1542 for token in tokens {
1543 match token {
1544 TokenOrValue::Token(CssToken::WhiteSpace(_)) => {}
1545
1546 TokenOrValue::Color(c) => {
1547 if color.is_some() {
1548 return None;
1549 }
1550 color = Some(*c);
1551 }
1552
1553 TokenOrValue::Token(CssToken::Ident(ident))
1554 if ident.as_ref().eq_ignore_ascii_case("inset") =>
1555 {
1556 if inset {
1557 return None;
1558 }
1559 inset = true;
1560 }
1561
1562 other => {
1563 if let Some(length) = parse_shadow_length(other) {
1564 lengths.push(length);
1565 } else {
1566 return None;
1567 }
1568 }
1569 }
1570 }
1571
1572 if !(2..=4).contains(&lengths.len()) {
1573 return None;
1574 }
1575
1576 let x_offset = lengths[0].clone();
1577 let y_offset = lengths[1].clone();
1578 let blur_radius = lengths.get(2).cloned();
1579 let spread_radius = lengths.get(3).cloned();
1580
1581 Some(Shadow::new(x_offset, y_offset, blur_radius, spread_radius, color, inset))
1582 }
1583
1584 let mut parts = Vec::<&[TokenOrValue<'_>]>::new();
1585 let mut start = 0usize;
1586 for (idx, token) in tokens.iter().enumerate() {
1587 if matches!(token, TokenOrValue::Token(CssToken::Comma)) {
1588 parts.push(&tokens[start..idx]);
1589 start = idx + 1;
1590 }
1591 }
1592 parts.push(&tokens[start..]);
1593
1594 let mut parsed = Vec::new();
1595 for part in parts {
1596 let shadow = parse_single_shadow(part)?;
1597 parsed.push(shadow);
1598 }
1599
1600 Some(parsed)
1601 }
1602
1603 fn shadow_fallback(var: &Variable<'_>) -> Option<Vec<Shadow>> {
1604 var.fallback.as_ref().and_then(|TokenList(tokens)| parse_shadow_list(tokens))
1605 }
1606
1607 match property.clone() {
1608 Property::Display(display) => {
1610 self.display.insert_rule(rule_id, display);
1611 }
1612
1613 Property::Visibility(visibility) => {
1615 self.visibility.insert_rule(rule_id, visibility);
1616 }
1617
1618 Property::Opacity(opacity) => {
1620 self.opacity.insert_rule(rule_id, opacity);
1621 }
1622
1623 Property::ClipPath(clip) => {
1625 self.clip_path.insert_rule(rule_id, clip);
1626 }
1627
1628 Property::Filter(filter) => {
1630 self.filter.insert_rule(rule_id, filter);
1631 }
1632
1633 Property::BackdropFilter(filter) => {
1634 self.backdrop_filter.insert_rule(rule_id, filter);
1635 }
1636
1637 Property::BlendMode(blend_mode) => {
1639 self.blend_mode.insert_rule(rule_id, blend_mode);
1640 }
1641
1642 Property::LayoutType(layout_type) => {
1644 self.layout_type.insert_rule(rule_id, layout_type);
1645 }
1646
1647 Property::PositionType(position) => {
1649 self.position_type.insert_rule(rule_id, position);
1650 }
1651
1652 Property::Alignment(alignment) => {
1653 self.alignment.insert_rule(rule_id, alignment);
1654 }
1655
1656 Property::Direction(direction) => {
1657 self.direction.insert_rule(rule_id, direction);
1658 }
1659
1660 Property::Wrap(value) => {
1661 self.wrap.insert_rule(rule_id, value);
1662 }
1663 Property::GridColumns(columns) => {
1664 self.grid_columns.insert_rule(rule_id, columns);
1665 }
1666
1667 Property::GridRows(rows) => {
1668 self.grid_rows.insert_rule(rule_id, rows);
1669 }
1670
1671 Property::ColumnStart(start) => {
1672 self.column_start.insert_rule(rule_id, start);
1673 }
1674
1675 Property::ColumnSpan(span) => {
1676 self.column_span.insert_rule(rule_id, span);
1677 }
1678
1679 Property::RowStart(start) => {
1680 self.row_start.insert_rule(rule_id, start);
1681 }
1682
1683 Property::RowSpan(span) => {
1684 self.row_span.insert_rule(rule_id, span);
1685 }
1686
1687 Property::Space(space) => {
1689 self.left.insert_rule(rule_id, space);
1690 self.right.insert_rule(rule_id, space);
1691 self.top.insert_rule(rule_id, space);
1692 self.bottom.insert_rule(rule_id, space);
1693 }
1694
1695 Property::Left(left) => {
1696 self.left.insert_rule(rule_id, left);
1697 }
1698
1699 Property::Right(right) => {
1700 self.right.insert_rule(rule_id, right);
1701 }
1702
1703 Property::Top(top) => {
1704 self.top.insert_rule(rule_id, top);
1705 }
1706
1707 Property::Bottom(bottom) => {
1708 self.bottom.insert_rule(rule_id, bottom);
1709 }
1710
1711 Property::Size(size) => {
1713 self.width.insert_rule(rule_id, size);
1714 self.height.insert_rule(rule_id, size);
1715 }
1716
1717 Property::Width(width) => {
1718 self.width.insert_rule(rule_id, width);
1719 }
1720
1721 Property::Height(height) => {
1722 self.height.insert_rule(rule_id, height);
1723 }
1724
1725 Property::Padding(padding) => {
1727 self.padding_left.insert_rule(rule_id, padding);
1728 self.padding_right.insert_rule(rule_id, padding);
1729 self.padding_top.insert_rule(rule_id, padding);
1730 self.padding_bottom.insert_rule(rule_id, padding);
1731 }
1732
1733 Property::PaddingLeft(padding_left) => {
1734 self.padding_left.insert_rule(rule_id, padding_left);
1735 }
1736
1737 Property::PaddingRight(padding_right) => {
1738 self.padding_right.insert_rule(rule_id, padding_right);
1739 }
1740
1741 Property::PaddingTop(padding_top) => {
1742 self.padding_top.insert_rule(rule_id, padding_top);
1743 }
1744
1745 Property::PaddingBottom(padding_bottom) => {
1746 self.padding_bottom.insert_rule(rule_id, padding_bottom);
1747 }
1748
1749 Property::VerticalGap(vertical_gap) => {
1750 self.vertical_gap.insert_rule(rule_id, vertical_gap);
1751 }
1752
1753 Property::HorizontalGap(horizontal_gap) => {
1754 self.horizontal_gap.insert_rule(rule_id, horizontal_gap);
1755 }
1756
1757 Property::Gap(gap) => {
1758 self.horizontal_gap.insert_rule(rule_id, gap);
1759 self.vertical_gap.insert_rule(rule_id, gap);
1760 }
1761
1762 Property::MinSize(min_size) => {
1764 self.min_width.insert_rule(rule_id, min_size);
1765 self.min_height.insert_rule(rule_id, min_size);
1766 }
1767
1768 Property::MinWidth(min_width) => {
1769 self.min_width.insert_rule(rule_id, min_width);
1770 }
1771
1772 Property::MinHeight(min_height) => {
1773 self.min_height.insert_rule(rule_id, min_height);
1774 }
1775
1776 Property::MaxSize(max_size) => {
1777 self.max_width.insert_rule(rule_id, max_size);
1778 self.max_height.insert_rule(rule_id, max_size);
1779 }
1780
1781 Property::MaxWidth(max_width) => {
1782 self.max_width.insert_rule(rule_id, max_width);
1783 }
1784
1785 Property::MaxHeight(max_height) => {
1786 self.max_height.insert_rule(rule_id, max_height);
1787 }
1788
1789 Property::MinGap(min_gap) => {
1791 self.min_horizontal_gap.insert_rule(rule_id, min_gap);
1792 self.min_vertical_gap.insert_rule(rule_id, min_gap);
1793 }
1794
1795 Property::MinHorizontalGap(min_gap) => {
1796 self.min_horizontal_gap.insert_rule(rule_id, min_gap);
1797 }
1798
1799 Property::MinVerticalGap(min_gap) => {
1800 self.min_vertical_gap.insert_rule(rule_id, min_gap);
1801 }
1802
1803 Property::MaxGap(max_gap) => {
1804 self.max_horizontal_gap.insert_rule(rule_id, max_gap);
1805 self.max_vertical_gap.insert_rule(rule_id, max_gap);
1806 }
1807
1808 Property::MaxHorizontalGap(max_gap) => {
1809 self.max_horizontal_gap.insert_rule(rule_id, max_gap);
1810 }
1811
1812 Property::MaxVerticalGap(max_gap) => {
1813 self.max_vertical_gap.insert_rule(rule_id, max_gap);
1814 }
1815
1816 Property::BackgroundColor(color) => {
1818 self.background_color.insert_rule(rule_id, color);
1819 }
1820
1821 Property::Border(border) => {
1823 if let Some(border_color) = border.color {
1824 self.border_color.insert_rule(rule_id, border_color);
1825 }
1826
1827 if let Some(border_width) = border.width {
1828 self.border_width.insert_rule(rule_id, border_width.into());
1829 }
1830
1831 if let Some(border_style) = border.style {
1832 self.border_style.insert_rule(rule_id, border_style.top);
1833 }
1834 }
1835
1836 Property::BorderWidth(border_width) => {
1838 self.border_width.insert_rule(rule_id, border_width.top.0);
1839 }
1840
1841 Property::BorderColor(color) => {
1842 self.border_color.insert_rule(rule_id, color);
1843 }
1844
1845 Property::BorderStyle(style) => {
1846 self.border_style.insert_rule(rule_id, style.top);
1847 }
1848
1849 Property::CornerRadius(corner_radius) => {
1851 self.corner_bottom_left_radius.insert_rule(rule_id, corner_radius.bottom_left);
1852 self.corner_bottom_right_radius.insert_rule(rule_id, corner_radius.bottom_right);
1853 self.corner_top_left_radius.insert_rule(rule_id, corner_radius.top_left);
1854 self.corner_top_right_radius.insert_rule(rule_id, corner_radius.top_right);
1855 }
1856
1857 Property::CornerBottomLeftRadius(corner_radius) => {
1858 self.corner_bottom_left_radius.insert_rule(rule_id, corner_radius);
1859 }
1860
1861 Property::CornerTopLeftRadius(corner_radius) => {
1862 self.corner_top_left_radius.insert_rule(rule_id, corner_radius);
1863 }
1864
1865 Property::CornerBottomRightRadius(corner_radius) => {
1866 self.corner_bottom_right_radius.insert_rule(rule_id, corner_radius);
1867 }
1868
1869 Property::CornerTopRightRadius(corner_radius) => {
1870 self.corner_top_right_radius.insert_rule(rule_id, corner_radius);
1871 }
1872
1873 Property::CornerShape(corner_shape) => {
1875 self.corner_top_left_shape.insert_rule(rule_id, corner_shape.0);
1876 self.corner_top_right_shape.insert_rule(rule_id, corner_shape.1);
1877 self.corner_bottom_right_shape.insert_rule(rule_id, corner_shape.2);
1878 self.corner_bottom_left_shape.insert_rule(rule_id, corner_shape.3);
1879 }
1880
1881 Property::CornerTopLeftShape(corner_shape) => {
1882 self.corner_top_left_shape.insert_rule(rule_id, corner_shape);
1883 }
1884
1885 Property::CornerTopRightShape(corner_shape) => {
1886 self.corner_top_right_shape.insert_rule(rule_id, corner_shape);
1887 }
1888
1889 Property::CornerBottomLeftShape(corner_shape) => {
1890 self.corner_bottom_left_shape.insert_rule(rule_id, corner_shape);
1891 }
1892
1893 Property::CornerBottomRightShape(corner_shape) => {
1894 self.corner_bottom_right_shape.insert_rule(rule_id, corner_shape);
1895 }
1896
1897 Property::FontFamily(font_family) => {
1899 self.font_family.insert_rule(
1900 rule_id,
1901 font_family
1902 .iter()
1903 .map(|family| match family {
1904 FontFamily::Named(name) => FamilyOwned::Named(name.to_string()),
1905 FontFamily::Generic(generic) => FamilyOwned::Generic(*generic),
1906 })
1907 .collect::<Vec<_>>(),
1908 );
1909 }
1910
1911 Property::FontColor(font_color) => {
1913 self.font_color.insert_rule(rule_id, font_color);
1914 }
1915
1916 Property::FontSize(font_size) => {
1918 self.font_size.insert_rule(rule_id, font_size);
1919 }
1920
1921 Property::LetterSpacing(letter_spacing) => {
1923 self.letter_spacing.insert_rule(rule_id, letter_spacing);
1924 }
1925
1926 Property::FontWeight(font_weight) => {
1928 self.font_weight.insert_rule(rule_id, font_weight);
1929 }
1930
1931 Property::FontSlant(font_slant) => {
1933 self.font_slant.insert_rule(rule_id, font_slant);
1934 }
1935
1936 Property::FontWidth(font_width) => {
1938 self.font_width.insert_rule(rule_id, font_width);
1939 }
1940
1941 Property::FontVariationSettings(font_variation_settings) => {
1943 self.font_variation_settings.insert_rule(rule_id, font_variation_settings);
1944 }
1945
1946 Property::CaretColor(caret_color) => {
1948 self.caret_color.insert_rule(rule_id, caret_color);
1949 }
1950
1951 Property::SelectionColor(selection_color) => {
1953 self.selection_color.insert_rule(rule_id, selection_color);
1954 }
1955
1956 Property::Transform(transforms) => {
1958 self.transform.insert_rule(rule_id, transforms);
1959 }
1960
1961 Property::TransformOrigin(transform_origin) => {
1962 let x = transform_origin.x.to_length_or_percentage();
1963 let y = transform_origin.y.to_length_or_percentage();
1964 self.transform_origin.insert_rule(rule_id, Translate { x, y });
1965 }
1966
1967 Property::Translate(translate) => {
1968 self.translate.insert_rule(rule_id, translate);
1969 }
1970
1971 Property::Rotate(rotate) => {
1972 self.rotate.insert_rule(rule_id, rotate);
1973 }
1974
1975 Property::Scale(scale) => {
1976 self.scale.insert_rule(rule_id, scale);
1977 }
1978
1979 Property::Overflow(overflow) => {
1981 self.overflowx.insert_rule(rule_id, overflow);
1982 self.overflowy.insert_rule(rule_id, overflow);
1983 }
1984
1985 Property::OverflowX(overflow) => {
1986 self.overflowx.insert_rule(rule_id, overflow);
1987 }
1988
1989 Property::OverflowY(overflow) => {
1990 self.overflowy.insert_rule(rule_id, overflow);
1991 }
1992
1993 Property::ZIndex(z_index) => self.z_index.insert_rule(rule_id, z_index),
1995
1996 Property::Outline(outline) => {
1998 if let Some(outline_color) = outline.color {
1999 self.outline_color.insert_rule(rule_id, outline_color);
2000 }
2001
2002 if let Some(outline_width) = outline.width {
2003 self.outline_width.insert_rule(rule_id, outline_width.into());
2004 }
2005 }
2006
2007 Property::OutlineColor(outline_color) => {
2008 self.outline_color.insert_rule(rule_id, outline_color);
2009 }
2010
2011 Property::OutlineWidth(outline_width) => {
2012 self.outline_width.insert_rule(rule_id, outline_width.left.0);
2013 }
2014
2015 Property::OutlineOffset(outline_offset) => {
2016 self.outline_offset.insert_rule(rule_id, outline_offset);
2017 }
2018
2019 Property::BackgroundImage(images) => {
2021 let images = images
2022 .into_iter()
2023 .filter_map(|img| match img {
2024 BackgroundImage::None => None,
2025 BackgroundImage::Gradient(gradient) => {
2026 Some(ImageOrGradient::Gradient(*gradient))
2027 }
2028 BackgroundImage::Url(url) => {
2029 Some(ImageOrGradient::Image(url.url.to_string()))
2030 }
2031 })
2032 .collect::<Vec<_>>();
2033
2034 self.background_image.insert_rule(rule_id, images);
2035 }
2036
2037 Property::BackgroundSize(sizes) => {
2039 self.background_size.insert_rule(rule_id, sizes);
2040 }
2041
2042 Property::TextWrap(text_wrap) => {
2044 self.text_wrap.insert_rule(rule_id, text_wrap);
2045 }
2046
2047 Property::TextAlign(text_align) => {
2049 self.text_align.insert_rule(rule_id, text_align);
2050 }
2051
2052 Property::Shadow(shadows) => {
2054 self.shadow.insert_rule(rule_id, shadows);
2055 }
2056
2057 Property::Cursor(cursor) => {
2059 self.cursor.insert_rule(rule_id, cursor);
2060 }
2061
2062 Property::PointerEvents(pointer_events) => {
2063 self.pointer_events.insert_rule(rule_id, pointer_events);
2064 }
2065
2066 Property::TextOverflow(text_overflow) => {
2067 self.text_overflow.insert_rule(rule_id, text_overflow);
2068 }
2069 Property::LineHeight(line_height) => {
2070 self.line_height.insert_rule(rule_id, line_height);
2071 }
2072 Property::LineClamp(line_clamp) => {
2073 self.line_clamp.insert_rule(rule_id, line_clamp);
2074 }
2075 Property::TextDecoration(decoration) => {
2076 self.text_decoration_line.insert_rule(rule_id, decoration.line);
2077 self.text_decoration_style.insert_rule(rule_id, decoration.style);
2078 self.text_decoration_color.insert_rule(rule_id, decoration.color.into());
2079 }
2080 Property::TextDecorationLine(line) => {
2081 self.text_decoration_line.insert_rule(rule_id, line);
2082 }
2083 Property::TextDecorationColor(decoration_color) => {
2084 self.text_decoration_color.insert_rule(rule_id, decoration_color);
2085 }
2086 Property::TextDecorationStyle(decoration_style) => {
2087 self.text_decoration_style.insert_rule(rule_id, decoration_style);
2088 }
2089 Property::TextStroke(stroke) => {
2090 self.text_stroke_width.insert_rule(rule_id, stroke.width);
2091 self.text_stroke_style.insert_rule(rule_id, stroke.style);
2092 }
2093 Property::TextStrokeWidth(stroke_width) => {
2094 self.text_stroke_width.insert_rule(rule_id, stroke_width);
2095 }
2096 Property::TextStrokeStyle(stroke_style) => {
2097 self.text_stroke_style.insert_rule(rule_id, stroke_style);
2098 }
2099 Property::Fill(fill) => {
2100 self.fill.insert_rule(rule_id, fill);
2101 }
2102
2103 Property::Unparsed(unparsed) => {
2105 macro_rules! parse_color_var {
2106 ($prop:expr) => {
2107 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2108 $prop.insert_variable_rule(
2109 rule_id,
2110 variable_hash(var),
2111 color_fallback(var),
2112 );
2113 }
2114 };
2115 }
2116 macro_rules! parse_length_var {
2117 ($($prop:expr),+) => {
2118 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2119 let hash = variable_hash(var);
2120 let fallback = length_fallback(var);
2121 $($prop.insert_variable_rule(rule_id, hash, fallback.clone());)+
2122 }
2123 };
2124 }
2125 macro_rules! parse_font_size_var {
2126 ($prop:expr) => {
2127 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2128 $prop.insert_variable_rule(
2129 rule_id,
2130 variable_hash(var),
2131 font_size_fallback(var),
2132 );
2133 }
2134 };
2135 }
2136 macro_rules! parse_letter_spacing_var {
2137 ($prop:expr) => {
2138 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2139 $prop.insert_variable_rule(
2140 rule_id,
2141 variable_hash(var),
2142 letter_spacing_fallback(var),
2143 );
2144 }
2145 };
2146 }
2147 macro_rules! parse_line_height_var {
2148 ($prop:expr) => {
2149 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2150 $prop.insert_variable_rule(
2151 rule_id,
2152 variable_hash(var),
2153 line_height_fallback(var),
2154 );
2155 }
2156 };
2157 }
2158 macro_rules! parse_units_var {
2159 ($($prop:expr),+) => {
2160 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2161 let hash = variable_hash(var);
2162 let fallback = units_fallback(var);
2163 $($prop.insert_variable_rule(rule_id, hash, fallback.clone());)+
2164 }
2165 };
2166 }
2167 match unparsed.name.as_ref() {
2168 "background-color" => parse_color_var!(self.background_color),
2169 "border-color" => parse_color_var!(self.border_color),
2170 "outline-color" => parse_color_var!(self.outline_color),
2171 "color" => parse_color_var!(self.font_color),
2172 "caret-color" => parse_color_var!(self.caret_color),
2173 "selection-color" => parse_color_var!(self.selection_color),
2174 "fill" => parse_color_var!(self.fill),
2175 "text-decoration-color" => parse_color_var!(self.text_decoration_color),
2176 "font-size" => parse_font_size_var!(self.font_size),
2177 "letter-spacing" => parse_letter_spacing_var!(self.letter_spacing),
2178 "line-height" => parse_line_height_var!(self.line_height),
2179 "corner-radius" => parse_length_var!(
2180 self.corner_top_left_radius,
2181 self.corner_top_right_radius,
2182 self.corner_bottom_left_radius,
2183 self.corner_bottom_right_radius
2184 ),
2185 "corner-top-left-radius" => parse_length_var!(self.corner_top_left_radius),
2186 "corner-top-right-radius" => parse_length_var!(self.corner_top_right_radius),
2187 "corner-bottom-left-radius" => {
2188 parse_length_var!(self.corner_bottom_left_radius)
2189 }
2190 "corner-bottom-right-radius" => {
2191 parse_length_var!(self.corner_bottom_right_radius)
2192 }
2193 "border-width" => parse_length_var!(self.border_width),
2194 "border" => {
2195 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2196 let hash = variable_hash(var);
2197 self.border_width.insert_variable_rule(
2198 rule_id,
2199 hash,
2200 length_fallback(var),
2201 );
2202 self.border_color.insert_variable_rule(
2203 rule_id,
2204 hash,
2205 color_fallback(var),
2206 );
2207 }
2208 }
2209 "outline" => {
2210 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2211 let hash = variable_hash(var);
2212 self.outline_width.insert_variable_rule(
2213 rule_id,
2214 hash,
2215 length_fallback(var),
2216 );
2217 self.outline_color.insert_variable_rule(
2218 rule_id,
2219 hash,
2220 color_fallback(var),
2221 );
2222 }
2223 }
2224 "outline-width" => parse_length_var!(self.outline_width),
2225 "outline-offset" => parse_length_var!(self.outline_offset),
2226 "left" => parse_units_var!(self.left),
2227 "right" => parse_units_var!(self.right),
2228 "top" => parse_units_var!(self.top),
2229 "bottom" => parse_units_var!(self.bottom),
2230 "space" => parse_units_var!(self.left, self.right, self.top, self.bottom),
2231 "width" => parse_units_var!(self.width),
2232 "height" => parse_units_var!(self.height),
2233 "size" => parse_units_var!(self.width, self.height),
2234 "min-width" => parse_units_var!(self.min_width),
2235 "max-width" => parse_units_var!(self.max_width),
2236 "min-height" => parse_units_var!(self.min_height),
2237 "max-height" => parse_units_var!(self.max_height),
2238 "min-size" => parse_units_var!(self.min_width, self.min_height),
2239 "max-size" => parse_units_var!(self.max_width, self.max_height),
2240 "padding-left" => parse_units_var!(self.padding_left),
2241 "padding-right" => parse_units_var!(self.padding_right),
2242 "padding-top" => parse_units_var!(self.padding_top),
2243 "padding-bottom" => parse_units_var!(self.padding_bottom),
2244 "padding" => parse_units_var!(
2245 self.padding_left,
2246 self.padding_right,
2247 self.padding_top,
2248 self.padding_bottom
2249 ),
2250 "row-gap" | "vertical-gap" => parse_units_var!(self.vertical_gap),
2251 "column-gap" | "horizontal-gap" => parse_units_var!(self.horizontal_gap),
2252 "gap" => parse_units_var!(self.vertical_gap, self.horizontal_gap),
2253 "min-gap" => {
2254 parse_units_var!(self.min_horizontal_gap, self.min_vertical_gap)
2255 }
2256 "max-gap" => {
2257 parse_units_var!(self.max_horizontal_gap, self.max_vertical_gap)
2258 }
2259 "opacity" => {
2260 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2261 self.opacity.insert_variable_rule(
2262 rule_id,
2263 variable_hash(var),
2264 opacity_fallback(var),
2265 );
2266 }
2267 }
2268 "shadow" => {
2269 if let Some(TokenOrValue::Var(var)) = unparsed.value.0.first() {
2270 self.shadow.insert_variable_rule(
2271 rule_id,
2272 variable_hash(var),
2273 shadow_fallback(var),
2274 );
2275 }
2276 }
2277 n => warn!("Unparsed {} {:?}", n, unparsed.value),
2278 }
2279 }
2280
2281 Property::Custom(custom) => {
2282 let mut s = DefaultHasher::new();
2283 custom.name.hash(&mut s);
2284 let variable_name_hash = s.finish();
2285
2286 if let Some(shadows) = parse_shadow_list(&custom.value.0) {
2287 if let Some(store) = self.custom_shadow_props.get_mut(&variable_name_hash) {
2288 store.insert_rule(rule_id, shadows);
2289 } else {
2290 let mut store = AnimatableVarSet::default();
2291 store.insert_rule(rule_id, shadows);
2292 self.custom_shadow_props.insert(variable_name_hash, store);
2293 }
2294 }
2295
2296 for token in custom.value.0.iter() {
2298 if let TokenOrValue::Color(color) = token {
2300 if let Some(store) = self.custom_color_props.get_mut(&variable_name_hash) {
2301 store.insert_rule(rule_id, *color);
2302 } else {
2303 let mut store = AnimatableVarSet::default();
2304 store.insert_rule(rule_id, *color);
2305 self.custom_color_props.insert(variable_name_hash, store);
2306 }
2307 }
2308
2309 match token {
2311 TokenOrValue::Token(CssToken::Dimension { value, unit, .. }) => {
2312 let lop = if unit.as_ref().eq_ignore_ascii_case("px") {
2313 Some(LengthOrPercentage::Length(Length::Value(LengthValue::Px(
2314 *value,
2315 ))))
2316 } else {
2317 None
2318 };
2319 if let Some(lop) = lop {
2320 if let Some(store) =
2321 self.custom_length_props.get_mut(&variable_name_hash)
2322 {
2323 store.insert_rule(rule_id, lop.clone());
2324 } else {
2325 let mut store = AnimatableVarSet::default();
2326 store.insert_rule(rule_id, lop.clone());
2327 self.custom_length_props.insert(variable_name_hash, store);
2328 }
2329 let fs = FontSize(Length::Value(LengthValue::Px(*value)));
2331 if let Some(store) =
2332 self.custom_font_size_props.get_mut(&variable_name_hash)
2333 {
2334 store.insert_rule(rule_id, fs);
2335 } else {
2336 let mut store = AnimatableVarSet::default();
2337 store.insert_rule(rule_id, fs);
2338 self.custom_font_size_props.insert(variable_name_hash, store);
2339 }
2340 let letter_spacing =
2342 LetterSpacing::Length(Length::Value(LengthValue::Px(*value)));
2343 if let Some(store) =
2344 self.custom_letter_spacing_props.get_mut(&variable_name_hash)
2345 {
2346 store.insert_rule(rule_id, letter_spacing);
2347 } else {
2348 let mut store = AnimatableVarSet::default();
2349 store.insert_rule(rule_id, letter_spacing);
2350 self.custom_letter_spacing_props
2351 .insert(variable_name_hash, store);
2352 }
2353 let line_height =
2355 LineHeight::Length(Length::Value(LengthValue::Px(*value)));
2356 if let Some(store) =
2357 self.custom_line_height_props.get_mut(&variable_name_hash)
2358 {
2359 store.insert_rule(rule_id, line_height);
2360 } else {
2361 let mut store = AnimatableVarSet::default();
2362 store.insert_rule(rule_id, line_height);
2363 self.custom_line_height_props.insert(variable_name_hash, store);
2364 }
2365 let units_val = Units::Pixels(*value);
2367 if let Some(store) =
2368 self.custom_units_props.get_mut(&variable_name_hash)
2369 {
2370 store.insert_rule(rule_id, units_val);
2371 } else {
2372 let mut store = AnimatableVarSet::default();
2373 store.insert_rule(rule_id, units_val);
2374 self.custom_units_props.insert(variable_name_hash, store);
2375 }
2376 } else if unit.as_ref().eq_ignore_ascii_case("s") {
2377 let units_val = Units::Stretch(*value);
2379 if let Some(store) =
2380 self.custom_units_props.get_mut(&variable_name_hash)
2381 {
2382 store.insert_rule(rule_id, units_val);
2383 } else {
2384 let mut store = AnimatableVarSet::default();
2385 store.insert_rule(rule_id, units_val);
2386 self.custom_units_props.insert(variable_name_hash, store);
2387 }
2388 }
2389 }
2390 TokenOrValue::Token(CssToken::Ident(ident))
2391 if ident.as_ref().eq_ignore_ascii_case("auto") =>
2392 {
2393 let units_val = Units::Auto;
2394 if let Some(store) =
2395 self.custom_units_props.get_mut(&variable_name_hash)
2396 {
2397 store.insert_rule(rule_id, units_val);
2398 } else {
2399 let mut store = AnimatableVarSet::default();
2400 store.insert_rule(rule_id, units_val);
2401 self.custom_units_props.insert(variable_name_hash, store);
2402 }
2403 }
2404 TokenOrValue::Token(CssToken::Percentage { unit_value, .. }) => {
2405 let lop = LengthOrPercentage::Percentage(*unit_value * 100.0);
2406 if let Some(store) =
2407 self.custom_length_props.get_mut(&variable_name_hash)
2408 {
2409 store.insert_rule(rule_id, lop);
2410 } else {
2411 let mut store = AnimatableVarSet::default();
2412 store.insert_rule(rule_id, lop);
2413 self.custom_length_props.insert(variable_name_hash, store);
2414 }
2415 let line_height = LineHeight::Percentage(*unit_value * 100.0);
2417 if let Some(store) =
2418 self.custom_line_height_props.get_mut(&variable_name_hash)
2419 {
2420 store.insert_rule(rule_id, line_height);
2421 } else {
2422 let mut store = AnimatableVarSet::default();
2423 store.insert_rule(rule_id, line_height);
2424 self.custom_line_height_props.insert(variable_name_hash, store);
2425 }
2426 let units_val = Units::Percentage(*unit_value * 100.0);
2428 if let Some(store) =
2429 self.custom_units_props.get_mut(&variable_name_hash)
2430 {
2431 store.insert_rule(rule_id, units_val);
2432 } else {
2433 let mut store = AnimatableVarSet::default();
2434 store.insert_rule(rule_id, units_val);
2435 self.custom_units_props.insert(variable_name_hash, store);
2436 }
2437 let opacity_val = Opacity(*unit_value);
2439 if let Some(store) =
2440 self.custom_opacity_props.get_mut(&variable_name_hash)
2441 {
2442 store.insert_rule(rule_id, opacity_val);
2443 } else {
2444 let mut store = AnimatableVarSet::default();
2445 store.insert_rule(rule_id, opacity_val);
2446 self.custom_opacity_props.insert(variable_name_hash, store);
2447 }
2448 }
2449 TokenOrValue::Var(var) => {
2450 let name_hash = variable_hash(var);
2451 if let Some(store) =
2453 self.custom_color_props.get_mut(&variable_name_hash)
2454 {
2455 store.insert_variable_rule(rule_id, name_hash, color_fallback(var));
2456 } else {
2457 let mut store = AnimatableVarSet::default();
2458 store.insert_variable_rule(rule_id, name_hash, color_fallback(var));
2459 self.custom_color_props.insert(variable_name_hash, store);
2460 }
2461 if let Some(store) =
2462 self.custom_length_props.get_mut(&variable_name_hash)
2463 {
2464 store.insert_variable_rule(
2465 rule_id,
2466 name_hash,
2467 length_fallback(var),
2468 );
2469 } else {
2470 let mut store: AnimatableVarSet<LengthOrPercentage> =
2471 AnimatableVarSet::default();
2472 store.insert_variable_rule(
2473 rule_id,
2474 name_hash,
2475 length_fallback(var),
2476 );
2477 self.custom_length_props.insert(variable_name_hash, store);
2478 }
2479 if let Some(store) =
2480 self.custom_font_size_props.get_mut(&variable_name_hash)
2481 {
2482 store.insert_variable_rule(
2483 rule_id,
2484 name_hash,
2485 font_size_fallback(var),
2486 );
2487 } else {
2488 let mut store: AnimatableVarSet<FontSize> =
2489 AnimatableVarSet::default();
2490 store.insert_variable_rule(
2491 rule_id,
2492 name_hash,
2493 font_size_fallback(var),
2494 );
2495 self.custom_font_size_props.insert(variable_name_hash, store);
2496 }
2497 if let Some(store) =
2498 self.custom_letter_spacing_props.get_mut(&variable_name_hash)
2499 {
2500 store.insert_variable_rule(
2501 rule_id,
2502 name_hash,
2503 letter_spacing_fallback(var),
2504 );
2505 } else {
2506 let mut store: AnimatableVarSet<LetterSpacing> =
2507 AnimatableVarSet::default();
2508 store.insert_variable_rule(
2509 rule_id,
2510 name_hash,
2511 letter_spacing_fallback(var),
2512 );
2513 self.custom_letter_spacing_props.insert(variable_name_hash, store);
2514 }
2515 if let Some(store) =
2516 self.custom_line_height_props.get_mut(&variable_name_hash)
2517 {
2518 store.insert_variable_rule(
2519 rule_id,
2520 name_hash,
2521 line_height_fallback(var),
2522 );
2523 } else {
2524 let mut store: AnimatableVarSet<LineHeight> =
2525 AnimatableVarSet::default();
2526 store.insert_variable_rule(
2527 rule_id,
2528 name_hash,
2529 line_height_fallback(var),
2530 );
2531 self.custom_line_height_props.insert(variable_name_hash, store);
2532 }
2533 if let Some(store) =
2534 self.custom_units_props.get_mut(&variable_name_hash)
2535 {
2536 store.insert_variable_rule(rule_id, name_hash, units_fallback(var));
2537 } else {
2538 let mut store: AnimatableVarSet<Units> =
2539 AnimatableVarSet::default();
2540 store.insert_variable_rule(rule_id, name_hash, units_fallback(var));
2541 self.custom_units_props.insert(variable_name_hash, store);
2542 }
2543 if let Some(store) =
2544 self.custom_opacity_props.get_mut(&variable_name_hash)
2545 {
2546 store.insert_variable_rule(
2547 rule_id,
2548 name_hash,
2549 opacity_fallback(var),
2550 );
2551 } else {
2552 let mut store: AnimatableVarSet<Opacity> =
2553 AnimatableVarSet::default();
2554 store.insert_variable_rule(
2555 rule_id,
2556 name_hash,
2557 opacity_fallback(var),
2558 );
2559 self.custom_opacity_props.insert(variable_name_hash, store);
2560 }
2561
2562 if let Some(store) =
2563 self.custom_shadow_props.get_mut(&variable_name_hash)
2564 {
2565 store.insert_variable_rule(
2566 rule_id,
2567 name_hash,
2568 shadow_fallback(var),
2569 );
2570 } else {
2571 let mut store: AnimatableVarSet<Vec<Shadow>> =
2572 AnimatableVarSet::default();
2573 store.insert_variable_rule(
2574 rule_id,
2575 name_hash,
2576 shadow_fallback(var),
2577 );
2578 self.custom_shadow_props.insert(variable_name_hash, store);
2579 }
2580 }
2581 TokenOrValue::Token(CssToken::Number { value, .. }) => {
2582 let opacity_val = Opacity(*value);
2584 if let Some(store) =
2585 self.custom_opacity_props.get_mut(&variable_name_hash)
2586 {
2587 store.insert_rule(rule_id, opacity_val);
2588 } else {
2589 let mut store = AnimatableVarSet::default();
2590 store.insert_rule(rule_id, opacity_val);
2591 self.custom_opacity_props.insert(variable_name_hash, store);
2592 }
2593
2594 let line_height = LineHeight::Number(*value);
2596 if let Some(store) =
2597 self.custom_line_height_props.get_mut(&variable_name_hash)
2598 {
2599 store.insert_rule(rule_id, line_height);
2600 } else {
2601 let mut store = AnimatableVarSet::default();
2602 store.insert_rule(rule_id, line_height);
2603 self.custom_line_height_props.insert(variable_name_hash, store);
2604 }
2605 }
2606 TokenOrValue::Token(CssToken::Ident(ident))
2607 if ident.as_ref().eq_ignore_ascii_case("normal") =>
2608 {
2609 let line_height = LineHeight::Normal;
2610 if let Some(store) =
2611 self.custom_line_height_props.get_mut(&variable_name_hash)
2612 {
2613 store.insert_rule(rule_id, line_height);
2614 } else {
2615 let mut store = AnimatableVarSet::default();
2616 store.insert_rule(rule_id, line_height);
2617 self.custom_line_height_props.insert(variable_name_hash, store);
2618 }
2619
2620 let letter_spacing = LetterSpacing::Normal;
2621 if let Some(store) =
2622 self.custom_letter_spacing_props.get_mut(&variable_name_hash)
2623 {
2624 store.insert_rule(rule_id, letter_spacing);
2625 } else {
2626 let mut store = AnimatableVarSet::default();
2627 store.insert_rule(rule_id, letter_spacing);
2628 self.custom_letter_spacing_props.insert(variable_name_hash, store);
2629 }
2630 }
2631 _ => {}
2632 }
2633 }
2634 }
2635 _ => {}
2636 }
2637 }
2638
2639 fn add_transition<T: Default + Interpolator>(
2641 &self,
2642 transition: &Transition,
2643 ) -> AnimationState<T> {
2644 let timing_function = transition
2645 .timing_function
2646 .map(|easing| match easing {
2647 EasingFunction::Linear => TimingFunction::linear(),
2648 EasingFunction::Ease => TimingFunction::ease(),
2649 EasingFunction::EaseIn => TimingFunction::ease_in(),
2650 EasingFunction::EaseOut => TimingFunction::ease_out(),
2651 EasingFunction::EaseInOut => TimingFunction::ease_in_out(),
2652 EasingFunction::CubicBezier(x1, y1, x2, y2) => TimingFunction::new(x1, y1, x2, y2),
2653 })
2654 .unwrap_or_default();
2655
2656 AnimationState::new(Animation::null())
2657 .with_duration(transition.duration)
2658 .with_delay(transition.delay.unwrap_or_default())
2659 .with_keyframe(Keyframe { time: 0.0, value: Default::default(), timing_function })
2660 .with_keyframe(Keyframe { time: 1.0, value: Default::default(), timing_function })
2661 }
2662
2663 pub(crate) fn add(&mut self, entity: Entity) {
2665 self.pseudo_classes.insert(entity, PseudoClassFlags::VALID);
2666 self.classes.insert(entity, HashSet::new());
2667 self.abilities.insert(entity, Abilities::default());
2668 self.system_flags = SystemFlags::RELAYOUT;
2669 self.restyle.insert(entity);
2670 self.reaccess.insert(entity);
2671 self.retransform.insert(entity);
2672 self.reclip.insert(entity);
2673 }
2674
2675 pub(crate) fn remove(&mut self, entity: Entity) {
2677 self.ids.remove(entity);
2678 self.classes.remove(entity);
2679 self.pseudo_classes.remove(entity);
2680 self.disabled.remove(entity);
2681 self.abilities.remove(entity);
2682
2683 self.name.remove(entity);
2684 self.role.remove(entity);
2685 self.live.remove(entity);
2687 self.labelled_by.remove(entity);
2688 self.described_by.remove(entity);
2689 self.controls.remove(entity);
2690 self.active_descendant.remove(entity);
2691 self.expanded.remove(entity);
2692 self.selected.remove(entity);
2693 self.hidden.remove(entity);
2694 self.orientation.remove(entity);
2695 self.text_value.remove(entity);
2696 self.numeric_value.remove(entity);
2697
2698 self.display.remove(entity);
2700 self.visibility.remove(entity);
2702 self.opacity.remove(entity);
2704 self.z_index.remove(entity);
2706 self.ignore_clipping.remove(entity);
2707 self.clip_path.remove(entity);
2709
2710 self.overflowx.remove(entity);
2711 self.overflowy.remove(entity);
2712
2713 self.filter.remove(entity);
2715 self.backdrop_filter.remove(entity);
2716
2717 self.blend_mode.remove(entity);
2719
2720 self.transform.remove(entity);
2722 self.transform_origin.remove(entity);
2723 self.translate.remove(entity);
2724 self.rotate.remove(entity);
2725 self.scale.remove(entity);
2726
2727 self.border_width.remove(entity);
2729 self.border_color.remove(entity);
2730 self.border_style.remove(entity);
2731
2732 self.corner_bottom_left_shape.remove(entity);
2734 self.corner_bottom_right_shape.remove(entity);
2735 self.corner_top_left_shape.remove(entity);
2736 self.corner_top_right_shape.remove(entity);
2737
2738 self.corner_bottom_left_radius.remove(entity);
2740 self.corner_bottom_right_radius.remove(entity);
2741 self.corner_top_left_radius.remove(entity);
2742 self.corner_top_right_radius.remove(entity);
2743
2744 self.corner_bottom_left_smoothing.remove(entity);
2746 self.corner_bottom_right_smoothing.remove(entity);
2747 self.corner_top_left_smoothing.remove(entity);
2748 self.corner_top_right_smoothing.remove(entity);
2749
2750 self.outline_width.remove(entity);
2752 self.outline_color.remove(entity);
2753 self.outline_offset.remove(entity);
2754
2755 self.background_color.remove(entity);
2757 self.background_image.remove(entity);
2758 self.background_size.remove(entity);
2759
2760 self.shadow.remove(entity);
2762
2763 self.text.remove(entity);
2765 self.text_wrap.remove(entity);
2766 self.text_overflow.remove(entity);
2767 self.letter_spacing.remove(entity);
2768 self.line_height.remove(entity);
2769 self.line_clamp.remove(entity);
2770 self.text_align.remove(entity);
2771 self.font_family.remove(entity);
2772 self.font_color.remove(entity);
2773 self.font_size.remove(entity);
2774 self.font_weight.remove(entity);
2775 self.font_slant.remove(entity);
2776 self.font_width.remove(entity);
2777 self.font_variation_settings.remove(entity);
2778 self.caret_color.remove(entity);
2779 self.selection_color.remove(entity);
2780 self.text_decoration_line.remove(entity);
2781 self.text_decoration_style.remove(entity);
2782 self.text_decoration_color.remove(entity);
2783 self.text_stroke_width.remove(entity);
2784 self.text_stroke_style.remove(entity);
2785
2786 self.cursor.remove(entity);
2788
2789 self.pointer_events.remove(entity);
2790
2791 self.layout_type.remove(entity);
2793
2794 self.position_type.remove(entity);
2796
2797 self.alignment.remove(entity);
2798 self.direction.remove(entity);
2799 self.wrap.remove(entity);
2800
2801 self.grid_columns.remove(entity);
2803 self.grid_rows.remove(entity);
2804 self.column_start.remove(entity);
2805 self.column_span.remove(entity);
2806 self.row_start.remove(entity);
2807 self.row_span.remove(entity);
2808
2809 self.left.remove(entity);
2811 self.right.remove(entity);
2812 self.top.remove(entity);
2813 self.bottom.remove(entity);
2814
2815 self.padding_left.remove(entity);
2817 self.padding_right.remove(entity);
2818 self.padding_top.remove(entity);
2819 self.padding_bottom.remove(entity);
2820 self.vertical_gap.remove(entity);
2821 self.horizontal_gap.remove(entity);
2822
2823 self.vertical_scroll.remove(entity);
2825 self.horizontal_scroll.remove(entity);
2826
2827 self.width.remove(entity);
2829 self.height.remove(entity);
2830
2831 self.min_width.remove(entity);
2833 self.max_width.remove(entity);
2834 self.min_height.remove(entity);
2835 self.max_height.remove(entity);
2836
2837 self.min_horizontal_gap.remove(entity);
2838 self.max_horizontal_gap.remove(entity);
2839 self.min_vertical_gap.remove(entity);
2840 self.max_vertical_gap.remove(entity);
2841
2842 self.text_range.remove(entity);
2843 self.text_span.remove(entity);
2844
2845 self.fill.remove(entity);
2846
2847 for store in self.custom_color_props.values_mut() {
2849 store.remove(entity);
2850 }
2851 for store in self.custom_length_props.values_mut() {
2852 store.remove(entity);
2853 }
2854 for store in self.custom_font_size_props.values_mut() {
2855 store.remove(entity);
2856 }
2857 for store in self.custom_letter_spacing_props.values_mut() {
2858 store.remove(entity);
2859 }
2860 for store in self.custom_line_height_props.values_mut() {
2861 store.remove(entity);
2862 }
2863 for store in self.custom_units_props.values_mut() {
2864 store.remove(entity);
2865 }
2866 for store in self.custom_opacity_props.values_mut() {
2867 store.remove(entity);
2868 }
2869 }
2870
2871 pub(crate) fn needs_restyle(&mut self, entity: Entity) {
2872 if entity == Entity::null() || self.restyle.contains(&entity) {
2873 return;
2874 }
2875 self.restyle.insert(entity);
2876 }
2877
2878 pub(crate) fn needs_relayout(&mut self) {
2879 self.system_flags.set(SystemFlags::RELAYOUT, true);
2880 }
2881
2882 pub(crate) fn needs_access_update(&mut self, entity: Entity) {
2883 self.reaccess.insert(entity);
2884 }
2885
2886 pub(crate) fn needs_text_update(&mut self, entity: Entity) {
2887 self.text_construction.insert(entity);
2888 self.text_layout.insert(entity);
2889 }
2890
2891 pub(crate) fn needs_text_layout(&mut self, entity: Entity) {
2892 self.text_layout.insert(entity);
2893 }
2894
2895 pub(crate) fn needs_retransform(&mut self, entity: Entity) {
2896 self.retransform.insert(entity);
2897 }
2898
2899 pub(crate) fn needs_reclip(&mut self, entity: Entity) {
2900 self.reclip.insert(entity);
2901 }
2902
2903 pub(crate) fn clear_style_rules(&mut self) {
2911 self.disabled.clear_rules();
2912 self.display.clear_rules();
2914 self.visibility.clear_rules();
2916 self.opacity.clear_rules();
2918 self.z_index.clear_rules();
2920
2921 self.clip_path.clear_rules();
2923
2924 self.filter.clear_rules();
2926 self.backdrop_filter.clear_rules();
2927
2928 self.blend_mode.clear_rules();
2930
2931 self.transform.clear_rules();
2933 self.transform_origin.clear_rules();
2934 self.translate.clear_rules();
2935 self.rotate.clear_rules();
2936 self.scale.clear_rules();
2937
2938 self.overflowx.clear_rules();
2939 self.overflowy.clear_rules();
2940
2941 self.border_width.clear_rules();
2943 self.border_color.clear_rules();
2944 self.border_style.clear_rules();
2945
2946 self.corner_bottom_left_shape.clear_rules();
2948 self.corner_bottom_right_shape.clear_rules();
2949 self.corner_top_left_shape.clear_rules();
2950 self.corner_top_right_shape.clear_rules();
2951
2952 self.corner_bottom_left_radius.clear_rules();
2954 self.corner_bottom_right_radius.clear_rules();
2955 self.corner_top_left_radius.clear_rules();
2956 self.corner_top_right_radius.clear_rules();
2957
2958 self.corner_bottom_left_smoothing.clear_rules();
2960 self.corner_bottom_right_smoothing.clear_rules();
2961 self.corner_top_left_smoothing.clear_rules();
2962 self.corner_top_right_smoothing.clear_rules();
2963
2964 self.outline_width.clear_rules();
2966 self.outline_color.clear_rules();
2967 self.outline_offset.clear_rules();
2968
2969 self.background_color.clear_rules();
2971 self.background_image.clear_rules();
2972 self.background_size.clear_rules();
2973
2974 self.shadow.clear_rules();
2975
2976 self.layout_type.clear_rules();
2977 self.position_type.clear_rules();
2978 self.alignment.clear_rules();
2979 self.direction.clear_rules();
2980 self.wrap.clear_rules();
2981
2982 self.grid_columns.clear_rules();
2984 self.grid_rows.clear_rules();
2985 self.column_start.clear_rules();
2986 self.column_span.clear_rules();
2987
2988 self.left.clear_rules();
2990 self.right.clear_rules();
2991 self.top.clear_rules();
2992 self.bottom.clear_rules();
2993
2994 self.width.clear_rules();
2996 self.height.clear_rules();
2997
2998 self.min_width.clear_rules();
3000 self.max_width.clear_rules();
3001 self.min_height.clear_rules();
3002 self.max_height.clear_rules();
3003
3004 self.min_horizontal_gap.clear_rules();
3005 self.max_horizontal_gap.clear_rules();
3006 self.min_vertical_gap.clear_rules();
3007 self.max_vertical_gap.clear_rules();
3008
3009 self.padding_left.clear_rules();
3011 self.padding_right.clear_rules();
3012 self.padding_top.clear_rules();
3013 self.padding_bottom.clear_rules();
3014 self.horizontal_gap.clear_rules();
3015 self.vertical_gap.clear_rules();
3016
3017 self.horizontal_scroll.clear_rules();
3019 self.vertical_scroll.clear_rules();
3020
3021 self.text_wrap.clear_rules();
3023 self.text_overflow.clear_rules();
3024 self.letter_spacing.clear_rules();
3025 self.line_height.clear_rules();
3026 self.line_clamp.clear_rules();
3027 self.text_align.clear_rules();
3028 self.font_family.clear_rules();
3029 self.font_weight.clear_rules();
3030 self.font_slant.clear_rules();
3031 self.font_color.clear_rules();
3032 self.font_size.clear_rules();
3033 self.font_variation_settings.clear_rules();
3034 self.selection_color.clear_rules();
3035 self.caret_color.clear_rules();
3036 self.text_decoration_line.clear_rules();
3037 self.text_decoration_style.clear_rules();
3038 self.text_decoration_color.clear_rules();
3039 self.text_stroke_width.clear_rules();
3040 self.text_stroke_style.clear_rules();
3041
3042 self.cursor.clear_rules();
3043
3044 self.pointer_events.clear_rules();
3045
3046 self.name.clear_rules();
3047
3048 self.fill.clear_rules();
3049
3050 for store in self.custom_color_props.values_mut() {
3052 store.clear_rules();
3053 }
3054 self.custom_color_props
3055 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3056 for store in self.custom_length_props.values_mut() {
3057 store.clear_rules();
3058 }
3059 self.custom_length_props
3060 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3061 for store in self.custom_font_size_props.values_mut() {
3062 store.clear_rules();
3063 }
3064 self.custom_font_size_props
3065 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3066 for store in self.custom_letter_spacing_props.values_mut() {
3067 store.clear_rules();
3068 }
3069 self.custom_letter_spacing_props
3070 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3071 for store in self.custom_line_height_props.values_mut() {
3072 store.clear_rules();
3073 }
3074 self.custom_line_height_props
3075 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3076 for store in self.custom_units_props.values_mut() {
3077 store.clear_rules();
3078 }
3079 self.custom_units_props
3080 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3081 for store in self.custom_opacity_props.values_mut() {
3082 store.clear_rules();
3083 }
3084 self.custom_opacity_props
3085 .retain(|_, store| !store.shared_data.is_empty() || !store.inline_data.is_empty());
3086 }
3087}