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