1use crate::dom::{NodeData, NodeId};
8use crate::prop_cache::CssPropertyCache;
9
10use crate::styled_dom::StyledNodeState;
11use crate::hash::DefaultHasher;
14use alloc::vec::Vec;
15#[allow(clippy::wildcard_imports)]
16use azul_css::compact_cache::*;
17use azul_css::css::CssPropertyValue;
18use azul_css::props::basic::length::SizeMetric;
19use azul_css::props::layout::dimensions::{LayoutHeight, LayoutWidth};
20use azul_css::props::layout::flex::LayoutFlexBasis;
21use azul_css::props::layout::position::LayoutZIndex;
22use azul_css::props::property::CssProperty;
23use core::hash::{Hash, Hasher};
24
25impl CssPropertyCache {
26 #[allow(clippy::cast_possible_truncation)]
43 #[allow(clippy::similar_names)] #[allow(clippy::too_many_lines, clippy::cognitive_complexity)] pub fn build_compact_cache(
46 &self,
47 node_data: &[NodeData],
48 prev_font_hashes: &[u64],
49 ) -> CompactLayoutCache {
50 let node_count = self.node_count;
51 let default_state = StyledNodeState::default();
52 let mut result = CompactLayoutCache::with_capacity(node_count);
53
54 for (i, nd) in node_data.iter().enumerate().take(node_count) {
55 let node_id = NodeId::new(i);
56
57 let display = self
62 .get_display(nd, &node_id, &default_state)
63 .and_then(|v| v.get_property().copied())
64 .unwrap_or_default();
65 let position = self
66 .get_position(nd, &node_id, &default_state)
67 .and_then(|v| v.get_property().copied())
68 .unwrap_or_default();
69 let float = self
70 .get_float(nd, &node_id, &default_state)
71 .and_then(|v| v.get_property().copied())
72 .unwrap_or_default();
73 let overflow_x = self
74 .get_overflow_x(nd, &node_id, &default_state)
75 .and_then(|v| v.get_property().copied())
76 .unwrap_or_default();
77 let overflow_y = self
78 .get_overflow_y(nd, &node_id, &default_state)
79 .and_then(|v| v.get_property().copied())
80 .unwrap_or_default();
81 let box_sizing = self
82 .get_box_sizing(nd, &node_id, &default_state)
83 .and_then(|v| v.get_property().copied())
84 .unwrap_or_default();
85 let flex_direction = self
86 .get_flex_direction(nd, &node_id, &default_state)
87 .and_then(|v| v.get_property().copied())
88 .unwrap_or_default();
89 let flex_wrap = self
90 .get_flex_wrap(nd, &node_id, &default_state)
91 .and_then(|v| v.get_property().copied())
92 .unwrap_or_default();
93 let justify_content = self
94 .get_justify_content(nd, &node_id, &default_state)
95 .and_then(|v| v.get_property().copied())
96 .unwrap_or_default();
97 let align_items = self
98 .get_align_items(nd, &node_id, &default_state)
99 .and_then(|v| v.get_property().copied())
100 .unwrap_or_default();
101 let align_content = self
102 .get_align_content(nd, &node_id, &default_state)
103 .and_then(|v| v.get_property().copied())
104 .unwrap_or_default();
105 let writing_mode = self
106 .get_writing_mode(nd, &node_id, &default_state)
107 .and_then(|v| v.get_property().copied())
108 .unwrap_or_default();
109 let clear = self
110 .get_clear(nd, &node_id, &default_state)
111 .and_then(|v| v.get_property().copied())
112 .unwrap_or_default();
113 let font_weight = self
114 .get_font_weight(nd, &node_id, &default_state)
115 .and_then(|v| v.get_property().copied())
116 .unwrap_or_default();
117 let font_style = self
118 .get_font_style(nd, &node_id, &default_state)
119 .and_then(|v| v.get_property().copied())
120 .unwrap_or_default();
121 let text_align = self
122 .get_text_align(nd, &node_id, &default_state)
123 .and_then(|v| v.get_property().copied())
124 .unwrap_or_default();
125 let visibility = self
126 .get_visibility(nd, &node_id, &default_state)
127 .and_then(|v| v.get_property().copied())
128 .unwrap_or_default();
129 let white_space = self
130 .get_white_space(nd, &node_id, &default_state)
131 .and_then(|v| v.get_property().copied())
132 .unwrap_or_default();
133 let direction = self
134 .get_direction(nd, &node_id, &default_state)
135 .and_then(|v| v.get_property().copied())
136 .unwrap_or_default();
137 let vertical_align = self
138 .get_vertical_align(nd, &node_id, &default_state)
139 .and_then(|v| v.get_property().copied())
140 .unwrap_or_default();
141
142 let border_collapse = self
143 .get_border_collapse(nd, &node_id, &default_state)
144 .and_then(|v| v.get_property().copied())
145 .unwrap_or_default();
146
147 result.tier1_enums[i] = encode_tier1(
148 display,
149 position,
150 float,
151 overflow_x,
152 overflow_y,
153 box_sizing,
154 flex_direction,
155 flex_wrap,
156 justify_content,
157 align_items,
158 align_content,
159 writing_mode,
160 clear,
161 font_weight,
162 font_style,
163 text_align,
164 visibility,
165 white_space,
166 direction,
167 vertical_align,
168 border_collapse,
169 );
170
171 if let Some(val) = self.get_width(nd, &node_id, &default_state) {
177 result.tier2_dims[i].width = encode_layout_width(val);
178 }
179 if let Some(val) = self.get_height(nd, &node_id, &default_state) {
180 result.tier2_dims[i].height = encode_layout_height(val);
181 }
182
183 if let Some(val) = self.get_min_width(nd, &node_id, &default_state) {
185 result.tier2_dims[i].min_width = encode_pixel_prop(val);
186 }
187 if let Some(val) = self.get_max_width(nd, &node_id, &default_state) {
188 result.tier2_dims[i].max_width = encode_pixel_prop(val);
189 }
190 if let Some(val) = self.get_min_height(nd, &node_id, &default_state) {
191 result.tier2_dims[i].min_height = encode_pixel_prop(val);
192 }
193 if let Some(val) = self.get_max_height(nd, &node_id, &default_state) {
194 result.tier2_dims[i].max_height = encode_pixel_prop(val);
195 }
196
197 if let Some(val) = self.get_flex_basis(nd, &node_id, &default_state) {
199 result.tier2_dims[i].flex_basis = encode_flex_basis(val);
200 }
201
202 if let Some(val) = self.get_font_size(nd, &node_id, &default_state) {
204 result.tier2_dims[i].font_size = encode_pixel_prop(val);
205 }
206
207 if let Some(val) = self.get_padding_top(nd, &node_id, &default_state) {
209 result.tier2_dims[i].padding_top = encode_css_pixel_as_i16(val);
210 }
211 if let Some(val) = self.get_padding_right(nd, &node_id, &default_state) {
212 result.tier2_dims[i].padding_right = encode_css_pixel_as_i16(val);
213 }
214 if let Some(val) = self.get_padding_bottom(nd, &node_id, &default_state) {
215 result.tier2_dims[i].padding_bottom = encode_css_pixel_as_i16(val);
216 }
217 if let Some(val) = self.get_padding_left(nd, &node_id, &default_state) {
218 result.tier2_dims[i].padding_left = encode_css_pixel_as_i16(val);
219 }
220
221 if let Some(val) = self.get_margin_top(nd, &node_id, &default_state) {
223 result.tier2_dims[i].margin_top = encode_margin_i16(val);
224 }
225 if let Some(val) = self.get_margin_right(nd, &node_id, &default_state) {
226 result.tier2_dims[i].margin_right = encode_margin_i16(val);
227 }
228 if let Some(val) = self.get_margin_bottom(nd, &node_id, &default_state) {
229 result.tier2_dims[i].margin_bottom = encode_margin_i16(val);
230 }
231 if let Some(val) = self.get_margin_left(nd, &node_id, &default_state) {
232 result.tier2_dims[i].margin_left = encode_margin_i16(val);
233 }
234
235 if let Some(val) = self.get_border_top_width(nd, &node_id, &default_state) {
237 result.tier2_dims[i].border_top_width = encode_css_pixel_as_i16(val);
238 }
239 if let Some(val) = self.get_border_right_width(nd, &node_id, &default_state) {
240 result.tier2_dims[i].border_right_width = encode_css_pixel_as_i16(val);
241 }
242 if let Some(val) = self.get_border_bottom_width(nd, &node_id, &default_state) {
243 result.tier2_dims[i].border_bottom_width = encode_css_pixel_as_i16(val);
244 }
245 if let Some(val) = self.get_border_left_width(nd, &node_id, &default_state) {
246 result.tier2_dims[i].border_left_width = encode_css_pixel_as_i16(val);
247 }
248
249 if let Some(val) = self.get_top(nd, &node_id, &default_state) {
251 result.tier2_dims[i].top = encode_css_pixel_as_i16(val);
252 }
253 if let Some(val) = self.get_right(nd, &node_id, &default_state) {
254 result.tier2_dims[i].right = encode_css_pixel_as_i16(val);
255 }
256 if let Some(val) = self.get_bottom(nd, &node_id, &default_state) {
257 result.tier2_dims[i].bottom = encode_css_pixel_as_i16(val);
258 }
259 if let Some(val) = self.get_left(nd, &node_id, &default_state) {
260 result.tier2_dims[i].left = encode_css_pixel_as_i16(val);
261 }
262
263 if let Some(val) = self.get_flex_grow(nd, &node_id, &default_state) {
265 if let Some(exact) = val.get_property() {
266 result.tier2_dims[i].flex_grow = encode_flex_u16(exact.inner.get());
267 }
268 }
269 if let Some(val) = self.get_flex_shrink(nd, &node_id, &default_state) {
270 if let Some(exact) = val.get_property() {
271 result.tier2_dims[i].flex_shrink = encode_flex_u16(exact.inner.get());
272 }
273 }
274
275 if let Some(val) = self.get_z_index(nd, &node_id, &default_state) {
281 if let Some(exact) = val.get_property() {
282 match exact {
283 LayoutZIndex::Auto => result.tier2_cold[i].z_index = I16_AUTO,
284 LayoutZIndex::Integer(z) => {
285 result.tier2_cold[i].z_index =
290 if *z >= -32768 && *z < i32::from(I16_SENTINEL_THRESHOLD) {
291 *z as i16
292 } else {
293 I16_SENTINEL
294 };
295 }
296 }
297 }
298 }
299
300 {
302 let bts = self
303 .get_border_top_style(nd, &node_id, &default_state)
304 .and_then(|v| v.get_property().copied())
305 .map(|v| v.inner)
306 .unwrap_or_default();
307 let brs = self
308 .get_border_right_style(nd, &node_id, &default_state)
309 .and_then(|v| v.get_property().copied())
310 .map(|v| v.inner)
311 .unwrap_or_default();
312 let bbs = self
313 .get_border_bottom_style(nd, &node_id, &default_state)
314 .and_then(|v| v.get_property().copied())
315 .map(|v| v.inner)
316 .unwrap_or_default();
317 let bls = self
318 .get_border_left_style(nd, &node_id, &default_state)
319 .and_then(|v| v.get_property().copied())
320 .map(|v| v.inner)
321 .unwrap_or_default();
322 result.tier2_cold[i].border_styles_packed =
323 encode_border_styles_packed(bts, brs, bbs, bls);
324 }
325
326 if let Some(val) = self.get_border_top_color(nd, &node_id, &default_state) {
328 if let Some(color) = val.get_property() {
329 result.tier2_cold[i].border_top_color = encode_color_u32(&color.inner);
330 }
331 }
332 if let Some(val) = self.get_border_right_color(nd, &node_id, &default_state) {
333 if let Some(color) = val.get_property() {
334 result.tier2_cold[i].border_right_color = encode_color_u32(&color.inner);
335 }
336 }
337 if let Some(val) = self.get_border_bottom_color(nd, &node_id, &default_state) {
338 if let Some(color) = val.get_property() {
339 result.tier2_cold[i].border_bottom_color = encode_color_u32(&color.inner);
340 }
341 }
342 if let Some(val) = self.get_border_left_color(nd, &node_id, &default_state) {
343 if let Some(color) = val.get_property() {
344 result.tier2_cold[i].border_left_color = encode_color_u32(&color.inner);
345 }
346 }
347
348 if let Some(val) = self.get_border_spacing(nd, &node_id, &default_state) {
350 if let Some(spacing) = val.get_property() {
351 if spacing.horizontal.metric == SizeMetric::Px {
352 result.tier2_cold[i].border_spacing_h =
353 encode_resolved_px_i16(spacing.horizontal.number.get());
354 }
355 if spacing.vertical.metric == SizeMetric::Px {
356 result.tier2_cold[i].border_spacing_v =
357 encode_resolved_px_i16(spacing.vertical.number.get());
358 }
359 }
360 }
361
362 if let Some(val) = self.get_tab_size(nd, &node_id, &default_state) {
364 result.tier2_cold[i].tab_size = encode_css_pixel_as_i16(val);
365 }
366
367 if let Some(val) = self.get_text_color(nd, &node_id, &default_state) {
373 if let Some(color) = val.get_property() {
374 let c = &color.inner;
375 result.tier2b_text[i].text_color = (u32::from(c.r) << 24)
376 | (u32::from(c.g) << 16)
377 | (u32::from(c.b) << 8)
378 | u32::from(c.a);
379 }
380 }
381
382 if let Some(val) = self.get_font_family(nd, &node_id, &default_state) {
384 if let Some(families) = val.get_property() {
385 let mut hasher = DefaultHasher::new();
386 families.hash(&mut hasher);
387 let h = hasher.finish();
388 let h = if h == 0 { 1 } else { h };
389 result.tier2b_text[i].font_family_hash = h;
390 result.font_hash_to_families.insert(h, families.clone());
391 }
392 }
393
394 if let Some(val) = self.get_line_height(nd, &node_id, &default_state) {
405 if let Some(lh) = val.get_property() {
406 let n = lh.inner.normalized();
407 let stored = if n < 0.0 {
408 ((n * 10.0).round() as i32).max(-32768)
411 } else {
412 (n * 1000.0).round() as i32
413 };
414 if stored >= -32768 && stored < i32::from(I16_SENTINEL_THRESHOLD) {
415 result.tier2b_text[i].line_height = stored as i16;
416 } else {
417 result.tier2b_text[i].line_height = I16_SENTINEL;
418 }
419 }
420 }
421
422 if let Some(val) = self.get_letter_spacing(nd, &node_id, &default_state) {
424 result.tier2b_text[i].letter_spacing = encode_css_pixel_as_i16(val);
425 }
426
427 if let Some(val) = self.get_word_spacing(nd, &node_id, &default_state) {
429 result.tier2b_text[i].word_spacing = encode_css_pixel_as_i16(val);
430 }
431
432 if let Some(val) = self.get_text_indent(nd, &node_id, &default_state) {
434 result.tier2b_text[i].text_indent = encode_css_pixel_as_i16(val);
435 }
436 }
437
438 result.font_dirty_nodes.clear();
445 for i in 0..node_count {
446 let new_hash = result.tier2b_text[i].font_family_hash;
447 let old_hash = prev_font_hashes.get(i).copied().unwrap_or(0);
448 if new_hash != old_hash {
449 result.font_dirty_nodes.push(i);
450 }
451 }
452 result.prev_font_hashes = result
454 .tier2b_text
455 .iter()
456 .map(|t| t.font_family_hash)
457 .collect();
458
459 result
460 }
461
462 pub fn build_compact_cache_with_inheritance(
473 &self,
474 node_data: &[NodeData],
475 node_hierarchy: &[crate::styled_dom::NodeHierarchyItem],
476 prev_font_hashes: &[u64],
477 ) -> CompactLayoutCache {
478 self.build_compact_cache_with_inheritance_debug(
479 node_data,
480 node_hierarchy,
481 prev_font_hashes,
482 &mut None,
483 )
484 }
485
486 #[allow(clippy::too_many_lines, clippy::cognitive_complexity)] pub fn build_compact_cache_with_inheritance_debug(
489 &self,
490 node_data: &[NodeData],
491 node_hierarchy: &[crate::styled_dom::NodeHierarchyItem],
492 prev_font_hashes: &[u64],
493 debug_messages: &mut Option<Vec<azul_css::LayoutDebugMessage>>,
494 ) -> CompactLayoutCache {
495 let node_count = self.node_count;
496 let default_state = StyledNodeState::default();
497 let mut result = CompactLayoutCache::with_capacity(node_count);
498
499 let mut global_tier1: u64 = 0;
502 let mut global_dims = CompactNodeProps::default();
503 let mut global_cold = CompactNodePropsCold::default();
504 let mut global_text = CompactTextProps::default();
505 let has_global = !self.global_css_props.is_empty();
506
507 if has_global {
508 use azul_css::props::property::CssProperty;
509
510 for prop in &self.global_css_props {
511 result.uses_viewport_units |= css_property_uses_viewport_units(prop);
512 macro_rules! global_tier1_enum {
514 ($variant:ident, $shift:ident, $mask:ident, $encoder:ident) => {
515 if let CssProperty::$variant(v) = prop {
516 if let Some(exact) = v.get_property() {
517 let encoded = u64::from($encoder(*exact));
518 let shifted_mask = $mask << $shift;
519 global_tier1 =
520 (global_tier1 & !shifted_mask) | ((encoded & $mask) << $shift);
521 }
522 }
523 };
524 }
525
526 global_tier1_enum!(Display, DISPLAY_SHIFT, DISPLAY_MASK, layout_display_to_u8);
527 global_tier1_enum!(
528 Position,
529 POSITION_SHIFT,
530 POSITION_MASK,
531 layout_position_to_u8
532 );
533 global_tier1_enum!(Float, FLOAT_SHIFT, FLOAT_MASK, layout_float_to_u8);
534 global_tier1_enum!(
535 OverflowX,
536 OVERFLOW_X_SHIFT,
537 OVERFLOW_MASK,
538 layout_overflow_to_u8
539 );
540 global_tier1_enum!(
541 OverflowY,
542 OVERFLOW_Y_SHIFT,
543 OVERFLOW_MASK,
544 layout_overflow_to_u8
545 );
546 global_tier1_enum!(
547 BoxSizing,
548 BOX_SIZING_SHIFT,
549 BOX_SIZING_MASK,
550 layout_box_sizing_to_u8
551 );
552 global_tier1_enum!(
553 FlexDirection,
554 FLEX_DIRECTION_SHIFT,
555 FLEX_DIR_MASK,
556 layout_flex_direction_to_u8
557 );
558 global_tier1_enum!(
559 FlexWrap,
560 FLEX_WRAP_SHIFT,
561 FLEX_WRAP_MASK,
562 layout_flex_wrap_to_u8
563 );
564 global_tier1_enum!(
565 JustifyContent,
566 JUSTIFY_CONTENT_SHIFT,
567 JUSTIFY_MASK,
568 layout_justify_content_to_u8
569 );
570 global_tier1_enum!(
571 AlignItems,
572 ALIGN_ITEMS_SHIFT,
573 ALIGN_MASK,
574 layout_align_items_to_u8
575 );
576 global_tier1_enum!(
577 AlignContent,
578 ALIGN_CONTENT_SHIFT,
579 ALIGN_MASK,
580 layout_align_content_to_u8
581 );
582 global_tier1_enum!(Clear, CLEAR_SHIFT, CLEAR_MASK, layout_clear_to_u8);
583 global_tier1_enum!(
584 Visibility,
585 VISIBILITY_SHIFT,
586 VISIBILITY_MASK,
587 style_visibility_to_u8
588 );
589 global_tier1_enum!(
590 WritingMode,
591 WRITING_MODE_SHIFT,
592 WRITING_MODE_MASK,
593 layout_writing_mode_to_u8
594 );
595 global_tier1_enum!(
596 FontWeight,
597 FONT_WEIGHT_SHIFT,
598 FONT_WEIGHT_MASK,
599 style_font_weight_to_u8
600 );
601 global_tier1_enum!(
602 FontStyle,
603 FONT_STYLE_SHIFT,
604 FONT_STYLE_MASK,
605 style_font_style_to_u8
606 );
607 global_tier1_enum!(
608 TextAlign,
609 TEXT_ALIGN_SHIFT,
610 TEXT_ALIGN_MASK,
611 style_text_align_to_u8
612 );
613 global_tier1_enum!(
614 WhiteSpace,
615 WHITE_SPACE_SHIFT,
616 WHITE_SPACE_MASK,
617 style_white_space_to_u8
618 );
619 global_tier1_enum!(
620 Direction,
621 DIRECTION_SHIFT,
622 DIRECTION_MASK,
623 style_direction_to_u8
624 );
625 global_tier1_enum!(
626 VerticalAlign,
627 VERTICAL_ALIGN_SHIFT,
628 VERTICAL_ALIGN_MASK,
629 style_vertical_align_to_u8
630 );
631 global_tier1_enum!(
632 BorderCollapse,
633 BORDER_COLLAPSE_SHIFT,
634 BORDER_COLLAPSE_MASK,
635 border_collapse_to_u8
636 );
637
638 match prop {
640 CssProperty::PaddingTop(v) => {
641 global_dims.padding_top = encode_css_pixel_as_i16(v);
642 }
643 CssProperty::PaddingRight(v) => {
644 global_dims.padding_right = encode_css_pixel_as_i16(v);
645 }
646 CssProperty::PaddingBottom(v) => {
647 global_dims.padding_bottom = encode_css_pixel_as_i16(v);
648 }
649 CssProperty::PaddingLeft(v) => {
650 global_dims.padding_left = encode_css_pixel_as_i16(v);
651 }
652 CssProperty::MarginTop(v) => {
653 global_dims.margin_top = encode_margin_i16(v);
654 }
655 CssProperty::MarginRight(v) => {
656 global_dims.margin_right = encode_margin_i16(v);
657 }
658 CssProperty::MarginBottom(v) => {
659 global_dims.margin_bottom = encode_margin_i16(v);
660 }
661 CssProperty::MarginLeft(v) => {
662 global_dims.margin_left = encode_margin_i16(v);
663 }
664 CssProperty::Width(v) => {
665 global_dims.width = encode_layout_width(v);
666 }
667 CssProperty::Height(v) => {
668 global_dims.height = encode_layout_height(v);
669 }
670 CssProperty::FontSize(v) => {
671 global_dims.font_size = encode_pixel_prop(v);
672 }
673 CssProperty::BorderTopWidth(v) => {
674 global_dims.border_top_width = encode_css_pixel_as_i16(v);
675 }
676 CssProperty::BorderRightWidth(v) => {
677 global_dims.border_right_width = encode_css_pixel_as_i16(v);
678 }
679 CssProperty::BorderBottomWidth(v) => {
680 global_dims.border_bottom_width = encode_css_pixel_as_i16(v);
681 }
682 CssProperty::BorderLeftWidth(v) => {
683 global_dims.border_left_width = encode_css_pixel_as_i16(v);
684 }
685 _ => {}
686 }
687 }
688
689 if global_tier1 != 0 {
690 global_tier1 |= TIER1_POPULATED_BIT;
691 }
692 }
693
694 macro_rules! cascade_debug {
696 ($($arg:tt)*) => {
697 if let Some(ref mut msgs) = debug_messages {
698 msgs.push(azul_css::LayoutDebugMessage::css_getter(format!($($arg)*)));
699 }
700 };
701 }
702
703 for i in 0..node_count {
704 let node_id = NodeId::new(i);
705 let nd = &node_data[i];
706
707 let parent_id = node_hierarchy[i].parent_id();
721 if let Some(pid) = parent_id {
722 let pi = pid.index();
723
724 debug_assert!(
733 pi < i,
734 "compact cascade: non-pre-order arena — node {i}'s parent {pi} \
735 is not stored before it; inheritance would read default values",
736 );
737 if pi < i {
738 result.tier1_enums[i] = result.tier1_enums[pi] & INHERITABLE_TIER1_MASK;
740
741 result.tier2_dims[i].font_size = result.tier2_dims[pi].font_size;
743
744 result.tier2_cold[i].border_spacing_h = result.tier2_cold[pi].border_spacing_h;
746 result.tier2_cold[i].border_spacing_v = result.tier2_cold[pi].border_spacing_v;
747 result.tier2_cold[i].tab_size = result.tier2_cold[pi].tab_size;
748 result.tier2_cold[i].cursor = result.tier2_cold[pi].cursor;
751
752 result.tier2b_text[i] = result.tier2b_text[pi];
754 }
755 }
756
757 {
758 let d = &result.tier2_dims[i];
759 cascade_debug!("node[{}] {:?} after-inherit: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={} w={} h={}",
760 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
761 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right, d.width, d.height);
762 }
763
764 apply_ua_css_to_compact(
767 &nd.node_type,
768 &mut result.tier1_enums[i],
769 &mut result.tier2_dims[i],
770 &mut result.tier2_cold[i],
771 &mut result.tier2b_text[i],
772 &mut result.font_hash_to_families,
773 );
774
775 {
776 let d = &result.tier2_dims[i];
777 cascade_debug!(
778 "node[{}] {:?} after-UA: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={}",
779 i,
780 nd.node_type,
781 d.padding_top,
782 d.padding_bottom,
783 d.padding_left,
784 d.padding_right,
785 d.margin_top,
786 d.margin_bottom,
787 d.margin_left,
788 d.margin_right
789 );
790 }
791
792 if !nd.is_text_node() {
801 for prop in &self.global_css_props {
802 apply_css_property_to_compact(
804 prop,
805 &mut result.tier1_enums[i],
806 &mut result.tier2_dims[i],
807 &mut result.tier2_cold[i],
808 &mut result.tier2b_text[i],
809 &mut result.font_hash_to_families,
810 );
811 update_dom_declared_flags(prop, &mut result.dom_declared_flags);
812 }
813 }
814
815 {
816 let d = &result.tier2_dims[i];
817 cascade_debug!("node[{}] {:?} after-global-star: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={}",
818 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
819 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right);
820 let n_props = self.css_props.get_slice(i).len();
821 let n_inline = nd.style.iter_inline_properties().count();
822 cascade_debug!(
823 "node[{}] css_props={} entries, inline={} entries",
824 i,
825 n_props,
826 n_inline
827 );
828 for prop in self.css_props.get_slice(i) {
829 cascade_debug!(
830 "node[{}] css_prop: state={:?} type={:?}",
831 i,
832 prop.state,
833 prop.prop_type
834 );
835 }
836 }
837
838 for prop in self.css_props.get_slice(i) {
844 if prop.state != azul_css::dynamic_selector::PseudoStateType::Normal {
845 continue;
846 }
847 result.uses_viewport_units |= css_property_uses_viewport_units(&prop.property);
848 apply_css_property_to_compact(
849 &prop.property,
850 &mut result.tier1_enums[i],
851 &mut result.tier2_dims[i],
852 &mut result.tier2_cold[i],
853 &mut result.tier2b_text[i],
854 &mut result.font_hash_to_families,
855 );
856 update_dom_declared_flags(&prop.property, &mut result.dom_declared_flags);
857 }
858
859 {
860 let d = &result.tier2_dims[i];
861 cascade_debug!("node[{}] {:?} after-css-props: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={}",
862 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
863 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right);
864 }
865
866 for (prop, conds) in nd.style.iter_inline_properties() {
869 let is_normal = conds.as_slice().is_empty()
878 || conds.as_slice().iter().all(|c| match c {
879 azul_css::dynamic_selector::DynamicSelector::PseudoState(s) => {
880 *s == azul_css::dynamic_selector::PseudoStateType::Normal
881 }
882 non_pseudo => {
883 result.has_dynamic_conditions = true;
884 {
889 let mut w = Vec::new();
890 let mut h = Vec::new();
891 azul_css::dynamic_selector::collect_viewport_thresholds(
892 core::slice::from_ref(non_pseudo),
893 &mut w,
894 &mut h,
895 );
896 result
897 .inline_viewport_w
898 .extend(w.into_iter().map(f32::to_bits));
899 result
900 .inline_viewport_h
901 .extend(h.into_iter().map(f32::to_bits));
902 }
903 self.dynamic_context
904 .as_deref()
905 .is_some_and(|ctx| non_pseudo.matches(ctx))
906 }
907 });
908 if !is_normal {
909 continue;
910 }
911 result.uses_viewport_units |= css_property_uses_viewport_units(prop);
912 if let CssProperty::Width(v) = prop {
919 result.tier2_dims[i].width = encode_layout_width(v);
920 } else if let CssProperty::Height(v) = prop {
921 result.tier2_dims[i].height = encode_layout_height(v);
922 } else if let CssProperty::FlexGrow(v) = prop {
923 if let Some(e) = v.get_property() {
924 result.tier2_dims[i].flex_grow = encode_flex_u16(e.inner.get());
925 }
926 } else if let CssProperty::Display(v) = prop {
927 if let Some(e) = v.get_property() {
928 let enc = u64::from(layout_display_to_u8(*e));
929 let m = DISPLAY_MASK;
930 let s = DISPLAY_SHIFT;
931 result.tier1_enums[i] =
932 (result.tier1_enums[i] & !(m << s)) | ((enc & m) << s);
933 }
934 } else {
935 apply_css_property_to_compact(
936 prop,
937 &mut result.tier1_enums[i],
938 &mut result.tier2_dims[i],
939 &mut result.tier2_cold[i],
940 &mut result.tier2b_text[i],
941 &mut result.font_hash_to_families,
942 );
943 }
944 update_dom_declared_flags(prop, &mut result.dom_declared_flags);
945 }
946
947 if let Some(user_props) = self.user_overridden_properties.get(i) {
958 for (_, prop) in user_props {
959 result.uses_viewport_units |= css_property_uses_viewport_units(prop);
960 if let CssProperty::Width(v) = prop {
961 result.tier2_dims[i].width = encode_layout_width(v);
962 } else if let CssProperty::Height(v) = prop {
963 result.tier2_dims[i].height = encode_layout_height(v);
964 } else if let CssProperty::FlexGrow(v) = prop {
965 if let Some(e) = v.get_property() {
966 result.tier2_dims[i].flex_grow = encode_flex_u16(e.inner.get());
967 }
968 } else if let CssProperty::Display(v) = prop {
969 if let Some(e) = v.get_property() {
970 let enc = u64::from(layout_display_to_u8(*e));
971 let m = DISPLAY_MASK;
972 let s = DISPLAY_SHIFT;
973 result.tier1_enums[i] =
974 (result.tier1_enums[i] & !(m << s)) | ((enc & m) << s);
975 }
976 } else {
977 apply_css_property_to_compact(
978 prop,
979 &mut result.tier1_enums[i],
980 &mut result.tier2_dims[i],
981 &mut result.tier2_cold[i],
982 &mut result.tier2b_text[i],
983 &mut result.font_hash_to_families,
984 );
985 }
986 update_dom_declared_flags(prop, &mut result.dom_declared_flags);
987 }
988 }
989
990 resolve_font_size_to_px(&mut result.tier2_dims, i, parent_id);
994
995 if result.tier1_enums[i] != 0 {
997 result.tier1_enums[i] |= TIER1_POPULATED_BIT;
998 }
999 }
1000
1001 result.font_dirty_nodes.clear();
1008 let first_build = prev_font_hashes.is_empty();
1009 for i in 0..node_count {
1010 let new_hash = result.tier2b_text[i].font_family_hash;
1011 let old_hash = prev_font_hashes.get(i).copied().unwrap_or(0);
1012 if first_build || new_hash != old_hash {
1013 result.font_dirty_nodes.push(i);
1014 }
1015 }
1016 result.prev_font_hashes = result
1017 .tier2b_text
1018 .iter()
1019 .map(|t| t.font_family_hash)
1020 .collect();
1021
1022 result.inline_viewport_w.sort_unstable();
1025 result.inline_viewport_w.dedup();
1026 result.inline_viewport_h.sort_unstable();
1027 result.inline_viewport_h.dedup();
1028
1029 result
1030 }
1031}
1032
1033pub const INHERITABLE_TIER1_MASK: u64 = (FONT_WEIGHT_MASK << FONT_WEIGHT_SHIFT)
1054 | (FONT_STYLE_MASK << FONT_STYLE_SHIFT)
1055 | (TEXT_ALIGN_MASK << TEXT_ALIGN_SHIFT)
1056 | (VISIBILITY_MASK << VISIBILITY_SHIFT)
1057 | (WHITE_SPACE_MASK << WHITE_SPACE_SHIFT)
1058 | (DIRECTION_MASK << DIRECTION_SHIFT)
1059 | (BORDER_COLLAPSE_MASK << BORDER_COLLAPSE_SHIFT)
1060 | (WRITING_MODE_MASK << WRITING_MODE_SHIFT);
1066
1067fn apply_ua_css_to_compact(
1068 node_type: &crate::dom::NodeType,
1069 tier1: &mut u64,
1070 dims: &mut CompactNodeProps,
1071 cold: &mut CompactNodePropsCold,
1072 text: &mut CompactTextProps,
1073 font_hash_map: &mut alloc::collections::BTreeMap<
1074 u64,
1075 azul_css::props::basic::font::StyleFontFamilyVec,
1076 >,
1077) {
1078 use azul_css::props::property::CssPropertyType as PT2;
1079 const UA_PROPERTY_TYPES: &[PT2] = &[
1080 PT2::Display,
1082 PT2::Position,
1083 PT2::Float,
1084 PT2::Clear,
1085 PT2::OverflowX,
1086 PT2::OverflowY,
1087 PT2::BoxSizing,
1088 PT2::FlexDirection,
1089 PT2::FlexWrap,
1090 PT2::JustifyContent,
1091 PT2::AlignItems,
1092 PT2::AlignContent,
1093 PT2::WritingMode,
1094 PT2::FontWeight,
1095 PT2::FontStyle,
1096 PT2::TextAlign,
1097 PT2::Visibility,
1098 PT2::WhiteSpace,
1099 PT2::Direction,
1100 PT2::VerticalAlign,
1101 PT2::BorderCollapse,
1102 PT2::Width,
1104 PT2::Height,
1105 PT2::FontSize,
1106 PT2::MarginTop,
1107 PT2::MarginBottom,
1108 PT2::MarginLeft,
1109 PT2::MarginRight,
1110 PT2::PaddingTop,
1111 PT2::PaddingBottom,
1112 PT2::PaddingLeft,
1113 PT2::PaddingRight,
1114 PT2::BorderTopWidth,
1115 PT2::BorderTopStyle,
1116 PT2::BorderTopColor,
1117 PT2::BorderRightWidth,
1118 PT2::BorderRightStyle,
1119 PT2::BorderRightColor,
1120 PT2::BorderBottomWidth,
1121 PT2::BorderBottomStyle,
1122 PT2::BorderBottomColor,
1123 PT2::BorderLeftWidth,
1124 PT2::BorderLeftStyle,
1125 PT2::BorderLeftColor,
1126 PT2::TextColor,
1128 PT2::LineHeight,
1129 PT2::LetterSpacing,
1130 PT2::WordSpacing,
1131 PT2::TextDecoration,
1132 PT2::Cursor,
1133 PT2::ListStyleType,
1134 PT2::CounterReset,
1140 PT2::CounterIncrement,
1141 ];
1142 for pt in UA_PROPERTY_TYPES {
1143 if let Some(ua_prop) = crate::ua_css::get_ua_property(node_type, *pt) {
1144 apply_css_property_to_compact(ua_prop, tier1, dims, cold, text, font_hash_map);
1145 }
1146 }
1147}
1148
1149fn resolve_font_size_to_px(
1153 tier2_dims: &mut [CompactNodeProps],
1154 node_idx: usize,
1155 parent_id: Option<NodeId>,
1156) {
1157 let raw_fs = tier2_dims[node_idx].font_size;
1158 if raw_fs == U32_SENTINEL || raw_fs >= U32_SENTINEL_THRESHOLD {
1159 return;
1160 }
1161 let pv = match decode_pixel_value_u32(raw_fs) {
1162 Some(pv) if pv.metric != SizeMetric::Px => pv,
1163 _ => return,
1164 };
1165
1166 let parent_font_size_px = parent_id.map_or(16.0, |pid| {
1172 let pi = pid.index();
1173 debug_assert!(
1174 pi < node_idx,
1175 "compact font-size resolve: non-pre-order arena — node {node_idx}'s \
1176 parent {pi} font-size is not yet resolved",
1177 );
1178 if pi < node_idx {
1179 tier2_dims
1180 .get(pi)
1181 .and_then(|p| decode_pixel_value_u32(p.font_size))
1182 .map_or(16.0, |ppv| ppv.number.get())
1183 } else {
1184 16.0
1185 }
1186 });
1187
1188 let resolved_px = match pv.metric {
1189 SizeMetric::Em => pv.number.get() * parent_font_size_px,
1190 SizeMetric::Percent => pv.number.get() / 100.0 * parent_font_size_px,
1191 SizeMetric::Rem => {
1192 let rem_base = if parent_id.is_none() {
1199 16.0
1200 } else {
1201 tier2_dims
1202 .first()
1203 .and_then(|r| decode_pixel_value_u32(r.font_size))
1204 .map_or(16.0, |rpv| rpv.number.get())
1205 };
1206 rem_base * pv.number.get()
1207 }
1208 SizeMetric::Pt => pv.number.get() * 96.0 / 72.0,
1209 _ => pv.number.get(),
1210 };
1211 tier2_dims[node_idx].font_size =
1212 encode_pixel_value_u32(&azul_css::props::basic::pixel::PixelValue::px(resolved_px));
1213}
1214
1215fn css_property_uses_viewport_units(prop: &CssProperty) -> bool {
1230 use azul_css::props::basic::length::SizeMetric;
1231 use azul_css::props::basic::pixel::PixelValue;
1232 const fn pv(p: &PixelValue) -> bool {
1233 matches!(
1234 p.metric,
1235 SizeMetric::Vw | SizeMetric::Vh | SizeMetric::Vmin | SizeMetric::Vmax
1236 )
1237 }
1238 fn inner<T: HasInnerPixelValue>(v: &CssPropertyValue<T>) -> bool {
1239 matches!(v, CssPropertyValue::Exact(x) if pv(&x.get_inner_pixel()))
1240 }
1241 use azul_css::props::layout::dimensions::{LayoutHeight, LayoutWidth};
1242 use azul_css::props::layout::flex::LayoutFlexBasis;
1243 match prop {
1244 CssProperty::Width(v) => matches!(v, CssPropertyValue::Exact(w) if match w {
1245 LayoutWidth::Px(p) | LayoutWidth::FitContent(p) => pv(p),
1246 LayoutWidth::Calc(_) => true,
1247 _ => false,
1248 }),
1249 CssProperty::Height(v) => matches!(v, CssPropertyValue::Exact(h) if match h {
1250 LayoutHeight::Px(p) | LayoutHeight::FitContent(p) => pv(p),
1251 LayoutHeight::Calc(_) => true,
1252 _ => false,
1253 }),
1254 CssProperty::FlexBasis(v) => {
1255 matches!(v, CssPropertyValue::Exact(LayoutFlexBasis::Exact(p)) if pv(p))
1256 }
1257 CssProperty::MinWidth(v) => inner(v),
1258 CssProperty::MaxWidth(v) => inner(v),
1259 CssProperty::MinHeight(v) => inner(v),
1260 CssProperty::MaxHeight(v) => inner(v),
1261 CssProperty::FontSize(v) => inner(v),
1262 CssProperty::PaddingTop(v) => inner(v),
1263 CssProperty::PaddingRight(v) => inner(v),
1264 CssProperty::PaddingBottom(v) => inner(v),
1265 CssProperty::PaddingLeft(v) => inner(v),
1266 CssProperty::MarginTop(v) => inner(v),
1267 CssProperty::MarginRight(v) => inner(v),
1268 CssProperty::MarginBottom(v) => inner(v),
1269 CssProperty::MarginLeft(v) => inner(v),
1270 CssProperty::BorderTopWidth(v) => inner(v),
1271 CssProperty::BorderRightWidth(v) => inner(v),
1272 CssProperty::BorderBottomWidth(v) => inner(v),
1273 CssProperty::BorderLeftWidth(v) => inner(v),
1274 CssProperty::Top(v) => inner(v),
1275 CssProperty::Right(v) => inner(v),
1276 CssProperty::Bottom(v) => inner(v),
1277 CssProperty::Left(v) => inner(v),
1278 CssProperty::LetterSpacing(v) => inner(v),
1279 CssProperty::WordSpacing(v) => inner(v),
1280 CssProperty::TextIndent(v) => inner(v),
1281 CssProperty::TabSize(v) => inner(v),
1282 _ => false,
1283 }
1284}
1285
1286#[inline]
1293#[allow(clippy::match_same_arms)]
1299#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
1302#[allow(clippy::too_many_lines, clippy::cognitive_complexity)] fn apply_css_property_to_compact(
1304 prop: &CssProperty,
1305 tier1: &mut u64,
1306 dims: &mut CompactNodeProps,
1307 cold: &mut CompactNodePropsCold,
1308 text: &mut CompactTextProps,
1309 font_hash_map: &mut alloc::collections::BTreeMap<
1310 u64,
1311 azul_css::props::basic::font::StyleFontFamilyVec,
1312 >,
1313) {
1314 macro_rules! set_tier1 {
1315 ($v:expr, $shift:expr, $mask:expr, $encoder:ident) => {
1316 if let Some(exact) = $v.get_property() {
1317 let encoded = u64::from($encoder(*exact));
1318 let shifted_mask = $mask << $shift;
1319 *tier1 = (*tier1 & !shifted_mask) | ((encoded & $mask) << $shift);
1320 }
1321 };
1322 }
1323
1324 match prop {
1325 CssProperty::Display(v) => set_tier1!(v, DISPLAY_SHIFT, DISPLAY_MASK, layout_display_to_u8),
1327 CssProperty::Position(v) => {
1328 set_tier1!(v, POSITION_SHIFT, POSITION_MASK, layout_position_to_u8);
1329 }
1330 CssProperty::Float(v) => set_tier1!(v, FLOAT_SHIFT, FLOAT_MASK, layout_float_to_u8),
1331 CssProperty::OverflowX(v) => {
1332 set_tier1!(v, OVERFLOW_X_SHIFT, OVERFLOW_MASK, layout_overflow_to_u8);
1333 }
1334 CssProperty::OverflowY(v) => {
1335 set_tier1!(v, OVERFLOW_Y_SHIFT, OVERFLOW_MASK, layout_overflow_to_u8);
1336 }
1337 CssProperty::OverflowBlock(v) => {
1347 if let Some(val) = v.get_property() {
1348 let wm_bits = ((*tier1 >> WRITING_MODE_SHIFT) & WRITING_MODE_MASK) as u8;
1349 let vertical = wm_bits
1350 == layout_writing_mode_to_u8(
1351 azul_css::props::layout::wrapping::LayoutWritingMode::VerticalRl,
1352 )
1353 || wm_bits
1354 == layout_writing_mode_to_u8(
1355 azul_css::props::layout::wrapping::LayoutWritingMode::VerticalLr,
1356 );
1357 let shift = if vertical {
1358 OVERFLOW_X_SHIFT
1359 } else {
1360 OVERFLOW_Y_SHIFT
1361 };
1362 let enc = u64::from(layout_overflow_to_u8(*val));
1363 *tier1 = (*tier1 & !(OVERFLOW_MASK << shift)) | ((enc & OVERFLOW_MASK) << shift);
1364 }
1365 }
1366 CssProperty::OverflowInline(v) => {
1367 if let Some(val) = v.get_property() {
1368 let wm_bits = ((*tier1 >> WRITING_MODE_SHIFT) & WRITING_MODE_MASK) as u8;
1369 let vertical = wm_bits
1370 == layout_writing_mode_to_u8(
1371 azul_css::props::layout::wrapping::LayoutWritingMode::VerticalRl,
1372 )
1373 || wm_bits
1374 == layout_writing_mode_to_u8(
1375 azul_css::props::layout::wrapping::LayoutWritingMode::VerticalLr,
1376 );
1377 let shift = if vertical {
1378 OVERFLOW_Y_SHIFT
1379 } else {
1380 OVERFLOW_X_SHIFT
1381 };
1382 let enc = u64::from(layout_overflow_to_u8(*val));
1383 *tier1 = (*tier1 & !(OVERFLOW_MASK << shift)) | ((enc & OVERFLOW_MASK) << shift);
1384 }
1385 }
1386 CssProperty::BoxSizing(v) => set_tier1!(
1387 v,
1388 BOX_SIZING_SHIFT,
1389 BOX_SIZING_MASK,
1390 layout_box_sizing_to_u8
1391 ),
1392 CssProperty::FlexDirection(v) => set_tier1!(
1393 v,
1394 FLEX_DIRECTION_SHIFT,
1395 FLEX_DIR_MASK,
1396 layout_flex_direction_to_u8
1397 ),
1398 CssProperty::FlexWrap(v) => {
1399 set_tier1!(v, FLEX_WRAP_SHIFT, FLEX_WRAP_MASK, layout_flex_wrap_to_u8);
1400 }
1401 CssProperty::JustifyContent(v) => set_tier1!(
1402 v,
1403 JUSTIFY_CONTENT_SHIFT,
1404 JUSTIFY_MASK,
1405 layout_justify_content_to_u8
1406 ),
1407 CssProperty::AlignItems(v) => {
1408 set_tier1!(v, ALIGN_ITEMS_SHIFT, ALIGN_MASK, layout_align_items_to_u8);
1409 }
1410 CssProperty::AlignContent(v) => set_tier1!(
1411 v,
1412 ALIGN_CONTENT_SHIFT,
1413 ALIGN_MASK,
1414 layout_align_content_to_u8
1415 ),
1416 CssProperty::WritingMode(v) => set_tier1!(
1417 v,
1418 WRITING_MODE_SHIFT,
1419 WRITING_MODE_MASK,
1420 layout_writing_mode_to_u8
1421 ),
1422 CssProperty::Clear(v) => set_tier1!(v, CLEAR_SHIFT, CLEAR_MASK, layout_clear_to_u8),
1423 CssProperty::FontWeight(v) => set_tier1!(
1424 v,
1425 FONT_WEIGHT_SHIFT,
1426 FONT_WEIGHT_MASK,
1427 style_font_weight_to_u8
1428 ),
1429 CssProperty::FontStyle(v) => {
1430 set_tier1!(v, FONT_STYLE_SHIFT, FONT_STYLE_MASK, style_font_style_to_u8);
1431 }
1432 CssProperty::TextAlign(v) => {
1433 set_tier1!(v, TEXT_ALIGN_SHIFT, TEXT_ALIGN_MASK, style_text_align_to_u8);
1434 }
1435 CssProperty::Visibility(v) => {
1436 set_tier1!(v, VISIBILITY_SHIFT, VISIBILITY_MASK, style_visibility_to_u8);
1437 }
1438 CssProperty::WhiteSpace(v) => set_tier1!(
1439 v,
1440 WHITE_SPACE_SHIFT,
1441 WHITE_SPACE_MASK,
1442 style_white_space_to_u8
1443 ),
1444 CssProperty::Direction(v) => {
1445 set_tier1!(v, DIRECTION_SHIFT, DIRECTION_MASK, style_direction_to_u8);
1446 }
1447 CssProperty::VerticalAlign(v) => set_tier1!(
1448 v,
1449 VERTICAL_ALIGN_SHIFT,
1450 VERTICAL_ALIGN_MASK,
1451 style_vertical_align_to_u8
1452 ),
1453 CssProperty::Cursor(v) => {
1458 if let Some(exact) = v.get_property() {
1459 cold.cursor = cursor_to_u8(*exact);
1460 }
1461 }
1462 CssProperty::BorderCollapse(v) => set_tier1!(
1463 v,
1464 BORDER_COLLAPSE_SHIFT,
1465 BORDER_COLLAPSE_MASK,
1466 border_collapse_to_u8
1467 ),
1468 CssProperty::AlignSelf(v) => set_tier1!(
1469 v,
1470 ALIGN_SELF_SHIFT,
1471 ALIGN_SELF_MASK,
1472 layout_align_self_to_u8
1473 ),
1474 CssProperty::JustifySelf(v) => set_tier1!(
1475 v,
1476 JUSTIFY_SELF_SHIFT,
1477 JUSTIFY_SELF_MASK,
1478 layout_justify_self_to_u8
1479 ),
1480 CssProperty::GridAutoFlow(v) => set_tier1!(
1481 v,
1482 GRID_AUTO_FLOW_SHIFT,
1483 GRID_AUTO_FLOW_MASK,
1484 layout_grid_auto_flow_to_u8
1485 ),
1486 CssProperty::JustifyItems(v) => set_tier1!(
1487 v,
1488 JUSTIFY_ITEMS_SHIFT,
1489 JUSTIFY_ITEMS_MASK,
1490 layout_justify_items_to_u8
1491 ),
1492
1493 CssProperty::Width(v) => {
1495 dims.width = encode_layout_width(v);
1496 }
1497 CssProperty::Height(v) => {
1498 dims.height = encode_layout_height(v);
1499 }
1500 CssProperty::MinWidth(v) => {
1501 dims.min_width = encode_pixel_prop(v);
1502 }
1503 CssProperty::MaxWidth(v) => {
1504 dims.max_width = encode_pixel_prop(v);
1505 }
1506 CssProperty::MinHeight(v) => {
1507 dims.min_height = encode_pixel_prop(v);
1508 }
1509 CssProperty::MaxHeight(v) => {
1510 dims.max_height = encode_pixel_prop(v);
1511 }
1512 CssProperty::FlexBasis(v) => {
1513 dims.flex_basis = encode_flex_basis(v);
1514 }
1515 CssProperty::FontSize(v) => {
1516 dims.font_size = encode_pixel_prop(v);
1517 }
1518 CssProperty::PaddingTop(v) => {
1519 dims.padding_top = encode_css_pixel_as_i16(v);
1520 }
1521 CssProperty::PaddingRight(v) => {
1522 dims.padding_right = encode_css_pixel_as_i16(v);
1523 }
1524 CssProperty::PaddingBottom(v) => {
1525 dims.padding_bottom = encode_css_pixel_as_i16(v);
1526 }
1527 CssProperty::PaddingLeft(v) => {
1528 dims.padding_left = encode_css_pixel_as_i16(v);
1529 }
1530 CssProperty::MarginTop(v) => {
1531 dims.margin_top = encode_margin_i16(v);
1532 }
1533 CssProperty::MarginRight(v) => {
1534 dims.margin_right = encode_margin_i16(v);
1535 }
1536 CssProperty::MarginBottom(v) => {
1537 dims.margin_bottom = encode_margin_i16(v);
1538 }
1539 CssProperty::MarginLeft(v) => {
1540 dims.margin_left = encode_margin_i16(v);
1541 }
1542 CssProperty::BorderTopWidth(v) => {
1543 dims.border_top_width = encode_css_pixel_as_i16(v);
1544 }
1545 CssProperty::BorderRightWidth(v) => {
1546 dims.border_right_width = encode_css_pixel_as_i16(v);
1547 }
1548 CssProperty::BorderBottomWidth(v) => {
1549 dims.border_bottom_width = encode_css_pixel_as_i16(v);
1550 }
1551 CssProperty::BorderLeftWidth(v) => {
1552 dims.border_left_width = encode_css_pixel_as_i16(v);
1553 }
1554 CssProperty::Top(v) => {
1555 dims.top = encode_css_pixel_as_i16(v);
1556 }
1557 CssProperty::Right(v) => {
1558 dims.right = encode_css_pixel_as_i16(v);
1559 }
1560 CssProperty::Bottom(v) => {
1561 dims.bottom = encode_css_pixel_as_i16(v);
1562 }
1563 CssProperty::Left(v) => {
1564 dims.left = encode_css_pixel_as_i16(v);
1565 }
1566 CssProperty::FlexGrow(v) => {
1567 if let Some(exact) = v.get_property() {
1568 dims.flex_grow = encode_flex_u16(exact.inner.get());
1569 }
1570 }
1571 CssProperty::FlexShrink(v) => {
1572 if let Some(exact) = v.get_property() {
1573 dims.flex_shrink = encode_flex_u16(exact.inner.get());
1574 }
1575 }
1576
1577 CssProperty::RowGap(v) => {
1578 if let Some(g) = v.get_property() {
1579 if g.inner.metric == SizeMetric::Px {
1580 dims.row_gap = encode_resolved_px_i16(g.inner.number.get());
1581 }
1582 }
1583 }
1584 CssProperty::ColumnGap(v) => {
1585 if let Some(g) = v.get_property() {
1586 if g.inner.metric == SizeMetric::Px {
1587 dims.column_gap = encode_resolved_px_i16(g.inner.number.get());
1588 }
1589 }
1590 }
1591 CssProperty::Gap(v) => {
1592 if let Some(g) = v.get_property() {
1593 if g.inner.metric == SizeMetric::Px {
1594 let enc = encode_resolved_px_i16(g.inner.number.get());
1595 dims.row_gap = enc;
1596 dims.column_gap = enc;
1597 }
1598 }
1599 }
1600
1601 CssProperty::GridColumn(v) => {
1603 if let Some(gp) = v.get_property() {
1604 cold.grid_col_start = encode_grid_line(&gp.grid_start);
1605 cold.grid_col_end = encode_grid_line(&gp.grid_end);
1606 }
1607 }
1608 CssProperty::GridRow(v) => {
1609 if let Some(gp) = v.get_property() {
1610 cold.grid_row_start = encode_grid_line(&gp.grid_start);
1611 cold.grid_row_end = encode_grid_line(&gp.grid_end);
1612 }
1613 }
1614
1615 CssProperty::ZIndex(v) => {
1617 if let Some(exact) = v.get_property() {
1618 match exact {
1619 LayoutZIndex::Auto => cold.z_index = I16_AUTO,
1620 LayoutZIndex::Integer(z) => {
1621 cold.z_index = if *z >= -32768 && *z < i32::from(I16_SENTINEL_THRESHOLD) {
1624 *z as i16
1625 } else {
1626 I16_SENTINEL
1627 };
1628 }
1629 }
1630 }
1631 }
1632 CssProperty::BorderTopStyle(v) => {
1633 if let Some(exact) = v.get_property() {
1634 let bs = u16::from(border_style_to_u8(exact.inner));
1635 cold.border_styles_packed = (cold.border_styles_packed & !0x000F) | bs;
1636 }
1637 }
1638 CssProperty::BorderRightStyle(v) => {
1639 if let Some(exact) = v.get_property() {
1640 let bs = u16::from(border_style_to_u8(exact.inner));
1641 cold.border_styles_packed = (cold.border_styles_packed & !0x00F0) | (bs << 4);
1642 }
1643 }
1644 CssProperty::BorderBottomStyle(v) => {
1645 if let Some(exact) = v.get_property() {
1646 let bs = u16::from(border_style_to_u8(exact.inner));
1647 cold.border_styles_packed = (cold.border_styles_packed & !0x0F00) | (bs << 8);
1648 }
1649 }
1650 CssProperty::BorderLeftStyle(v) => {
1651 if let Some(exact) = v.get_property() {
1652 let bs = u16::from(border_style_to_u8(exact.inner));
1653 cold.border_styles_packed = (cold.border_styles_packed & !0xF000) | (bs << 12);
1654 }
1655 }
1656 CssProperty::BorderTopColor(v) => {
1657 if let Some(c) = v.get_property() {
1658 cold.border_top_color = encode_color_u32(&c.inner);
1659 }
1660 }
1661 CssProperty::BorderRightColor(v) => {
1662 if let Some(c) = v.get_property() {
1663 cold.border_right_color = encode_color_u32(&c.inner);
1664 }
1665 }
1666 CssProperty::BorderBottomColor(v) => {
1667 if let Some(c) = v.get_property() {
1668 cold.border_bottom_color = encode_color_u32(&c.inner);
1669 }
1670 }
1671 CssProperty::BorderLeftColor(v) => {
1672 if let Some(c) = v.get_property() {
1673 cold.border_left_color = encode_color_u32(&c.inner);
1674 }
1675 }
1676 CssProperty::BorderSpacing(v) => {
1677 if let Some(spacing) = v.get_property() {
1678 if spacing.horizontal.metric == SizeMetric::Px {
1679 cold.border_spacing_h = encode_resolved_px_i16(spacing.horizontal.number.get());
1680 }
1681 if spacing.vertical.metric == SizeMetric::Px {
1682 cold.border_spacing_v = encode_resolved_px_i16(spacing.vertical.number.get());
1683 }
1684 }
1685 }
1686 CssProperty::TabSize(v) => {
1687 cold.tab_size = encode_css_pixel_as_i16(v);
1688 }
1689
1690 CssProperty::TextColor(v) => {
1692 if let Some(color) = v.get_property() {
1693 let c = &color.inner;
1694 text.text_color = (u32::from(c.r) << 24)
1695 | (u32::from(c.g) << 16)
1696 | (u32::from(c.b) << 8)
1697 | u32::from(c.a);
1698 }
1699 }
1700 CssProperty::FontFamily(v) => {
1701 if let Some(families) = v.get_property() {
1702 let mut hasher = DefaultHasher::new();
1703 families.hash(&mut hasher);
1704 let h = hasher.finish();
1705 let h = if h == 0 { 1 } else { h };
1706 text.font_family_hash = h;
1707 font_hash_map.insert(h, families.clone());
1708 }
1709 }
1710 CssProperty::LineHeight(v) => {
1711 if let Some(lh) = v.get_property() {
1712 let n = lh.inner.normalized();
1719 let stored = if n < 0.0 {
1720 ((n * 10.0).round() as i32).max(-32768)
1721 } else {
1722 (n * 1000.0).round() as i32
1723 };
1724 if stored >= -32768 && stored < i32::from(I16_SENTINEL_THRESHOLD) {
1725 text.line_height = stored as i16;
1726 } else {
1727 text.line_height = I16_SENTINEL;
1728 }
1729 }
1730 }
1731 CssProperty::LetterSpacing(v) => {
1732 text.letter_spacing = encode_css_pixel_as_i16(v);
1733 }
1734 CssProperty::WordSpacing(v) => {
1735 text.word_spacing = encode_css_pixel_as_i16(v);
1736 }
1737 CssProperty::TextIndent(v) => {
1738 text.text_indent = encode_css_pixel_as_i16(v);
1739 }
1740
1741 CssProperty::BorderTopLeftRadius(v) => {
1743 if let Some(exact) = v.get_property() {
1744 if exact.inner.metric == SizeMetric::Px {
1745 cold.border_top_left_radius = encode_resolved_px_i16(exact.inner.number.get());
1746 }
1747 }
1748 }
1749 CssProperty::BorderTopRightRadius(v) => {
1750 if let Some(exact) = v.get_property() {
1751 if exact.inner.metric == SizeMetric::Px {
1752 cold.border_top_right_radius = encode_resolved_px_i16(exact.inner.number.get());
1753 }
1754 }
1755 }
1756 CssProperty::BorderBottomLeftRadius(v) => {
1757 if let Some(exact) = v.get_property() {
1758 if exact.inner.metric == SizeMetric::Px {
1759 cold.border_bottom_left_radius =
1760 encode_resolved_px_i16(exact.inner.number.get());
1761 }
1762 }
1763 }
1764 CssProperty::BorderBottomRightRadius(v) => {
1765 if let Some(exact) = v.get_property() {
1766 if exact.inner.metric == SizeMetric::Px {
1767 cold.border_bottom_right_radius =
1768 encode_resolved_px_i16(exact.inner.number.get());
1769 }
1770 }
1771 }
1772
1773 CssProperty::Opacity(v) => {
1775 if let Some(exact) = v.get_property() {
1776 let o = exact.inner.normalized().clamp(0.0, 1.0);
1777 let byte = (o * 254.0).round() as u8;
1778 cold.opacity = byte;
1780 }
1781 }
1782
1783 CssProperty::Transform(v) => {
1786 if v.get_property().is_some() {
1787 cold.hot_flags |= HOT_FLAG_HAS_TRANSFORM;
1788 }
1789 }
1790 CssProperty::TransformOrigin(v) => {
1791 if v.get_property().is_some() {
1792 cold.hot_flags |= HOT_FLAG_HAS_TRANSFORM_ORIGIN;
1793 }
1794 }
1795 CssProperty::BoxShadowTop(v)
1798 | CssProperty::BoxShadowBottom(v)
1799 | CssProperty::BoxShadowLeft(v)
1800 | CssProperty::BoxShadowRight(v) => {
1801 if v.get_property().is_some() {
1802 cold.hot_flags |= HOT_FLAG_HAS_BOX_SHADOW;
1803 }
1804 }
1805 CssProperty::TextDecoration(v) => {
1806 if v.get_property().is_some() {
1807 cold.hot_flags |= HOT_FLAG_HAS_TEXT_DECORATION;
1808 }
1809 }
1810 CssProperty::ScrollbarGutter(v) => {
1811 if let Some(exact) = v.get_property() {
1812 use azul_css::props::layout::overflow::StyleScrollbarGutter;
1813 let bits: u8 = match exact {
1814 StyleScrollbarGutter::Auto => SCROLLBAR_GUTTER_AUTO,
1815 StyleScrollbarGutter::Stable => SCROLLBAR_GUTTER_STABLE,
1816 StyleScrollbarGutter::StableBothEdges => SCROLLBAR_GUTTER_BOTH_EDGES,
1817 };
1818 cold.hot_flags = (cold.hot_flags & !HOT_FLAG_SCROLLBAR_GUTTER_MASK)
1819 | ((bits << HOT_FLAG_SCROLLBAR_GUTTER_SHIFT) & HOT_FLAG_SCROLLBAR_GUTTER_MASK);
1820 }
1821 }
1822 CssProperty::BackgroundContent(v) => {
1823 if v.get_property().is_some() {
1824 cold.hot_flags |= HOT_FLAG_HAS_BACKGROUND;
1825 }
1826 }
1827 CssProperty::ClipPath(v) => {
1828 if v.get_property().is_some() {
1829 cold.hot_flags |= HOT_FLAG_HAS_CLIP_PATH;
1830 }
1831 }
1832
1833 CssProperty::ScrollbarTrack(v) => {
1837 if v.get_property().is_some() {
1838 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1839 }
1840 }
1841 CssProperty::ScrollbarThumb(v) => {
1842 if v.get_property().is_some() {
1843 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1844 }
1845 }
1846 CssProperty::ScrollbarButton(v) => {
1847 if v.get_property().is_some() {
1848 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1849 }
1850 }
1851 CssProperty::ScrollbarCorner(v) => {
1852 if v.get_property().is_some() {
1853 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1854 }
1855 }
1856 CssProperty::ScrollbarWidth(v) => {
1857 if v.get_property().is_some() {
1858 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1859 }
1860 }
1861 CssProperty::ScrollbarColor(v) => {
1862 if v.get_property().is_some() {
1863 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1864 }
1865 }
1866 CssProperty::ScrollbarVisibility(v) => {
1867 if v.get_property().is_some() {
1868 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1869 }
1870 }
1871 CssProperty::ScrollbarFadeDelay(v) => {
1872 if v.get_property().is_some() {
1873 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1874 }
1875 }
1876 CssProperty::ScrollbarFadeDuration(v) => {
1877 if v.get_property().is_some() {
1878 cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS;
1879 }
1880 }
1881
1882 CssProperty::CounterReset(v) => {
1884 if v.get_property().is_some() {
1885 cold.extra_flags |= EXTRA_FLAG_HAS_COUNTER;
1886 }
1887 }
1888 CssProperty::CounterIncrement(v) => {
1889 if v.get_property().is_some() {
1890 cold.extra_flags |= EXTRA_FLAG_HAS_COUNTER;
1891 }
1892 }
1893 CssProperty::BreakBefore(v) | CssProperty::BreakAfter(v) => {
1895 if v.get_property().is_some() {
1896 cold.extra_flags |= EXTRA_FLAG_HAS_BREAK;
1897 }
1898 }
1899 CssProperty::TextOrientation(v) => {
1900 if v.get_property().is_some() {
1901 cold.extra_flags |= EXTRA_FLAG_HAS_TEXT_ORIENTATION;
1902 }
1903 }
1904 CssProperty::TextShadow(v) => {
1905 if v.get_property().is_some() {
1906 cold.extra_flags |= EXTRA_FLAG_HAS_TEXT_SHADOW;
1907 }
1908 }
1909 CssProperty::BackdropFilter(v) => {
1910 if v.get_property().is_some() {
1911 cold.extra_flags |= EXTRA_FLAG_HAS_BACKDROP_FILTER;
1912 }
1913 }
1914 CssProperty::Filter(v) => {
1915 if v.get_property().is_some() {
1916 cold.extra_flags |= EXTRA_FLAG_HAS_FILTER;
1917 }
1918 }
1919 CssProperty::MixBlendMode(v) => {
1920 if v.get_property().is_some() {
1921 cold.extra_flags |= EXTRA_FLAG_HAS_MIX_BLEND_MODE;
1922 }
1923 }
1924
1925 _ => {}
1927 }
1928}
1929
1930#[allow(clippy::too_many_lines)] const fn update_dom_declared_flags(prop: &CssProperty, flags: &mut u32) {
1936 match prop {
1940 CssProperty::ShapeInside(v) => {
1941 if v.get_property().is_some() {
1942 *flags |= DOM_HAS_SHAPE_INSIDE;
1943 }
1944 }
1945 CssProperty::ShapeOutside(v) => {
1946 if v.get_property().is_some() {
1947 *flags |= DOM_HAS_SHAPE_OUTSIDE;
1948 }
1949 }
1950 CssProperty::TextJustify(v) => {
1951 if v.get_property().is_some() {
1952 *flags |= DOM_HAS_TEXT_JUSTIFY;
1953 }
1954 }
1955 CssProperty::TextIndent(v) => {
1956 if v.get_property().is_some() {
1957 *flags |= DOM_HAS_TEXT_INDENT;
1958 }
1959 }
1960 CssProperty::ColumnCount(v) => {
1961 if v.get_property().is_some() {
1962 *flags |= DOM_HAS_COLUMN_COUNT;
1963 }
1964 }
1965 CssProperty::ColumnGap(v) => {
1966 if v.get_property().is_some() {
1967 *flags |= DOM_HAS_COLUMN_GAP;
1968 }
1969 }
1970 CssProperty::ColumnWidth(v) => {
1971 if v.get_property().is_some() {
1972 *flags |= DOM_HAS_COLUMN_WIDTH;
1973 }
1974 }
1975 CssProperty::InitialLetter(v) => {
1976 if v.get_property().is_some() {
1977 *flags |= DOM_HAS_INITIAL_LETTER;
1978 }
1979 }
1980 CssProperty::InitialLetterAlign(v) => {
1981 if v.get_property().is_some() {
1982 *flags |= DOM_HAS_INITIAL_LETTER_ALIGN;
1983 }
1984 }
1985 CssProperty::LineClamp(v) => {
1986 if v.get_property().is_some() {
1987 *flags |= DOM_HAS_LINE_CLAMP;
1988 }
1989 }
1990 CssProperty::HangingPunctuation(v) => {
1991 if v.get_property().is_some() {
1992 *flags |= DOM_HAS_HANGING_PUNCTUATION;
1993 }
1994 }
1995 CssProperty::TextCombineUpright(v) => {
1996 if v.get_property().is_some() {
1997 *flags |= DOM_HAS_TEXT_COMBINE_UPRIGHT;
1998 }
1999 }
2000 CssProperty::ExclusionMargin(v) => {
2001 if v.get_property().is_some() {
2002 *flags |= DOM_HAS_EXCLUSION_MARGIN;
2003 }
2004 }
2005 CssProperty::ShapeMargin(v) => {
2006 if v.get_property().is_some() {
2007 *flags |= DOM_HAS_SHAPE_MARGIN;
2008 }
2009 }
2010 CssProperty::HyphenationLanguage(v) => {
2011 if v.get_property().is_some() {
2012 *flags |= DOM_HAS_HYPHENATION_LANGUAGE;
2013 }
2014 }
2015 CssProperty::UnicodeBidi(v) => {
2016 if v.get_property().is_some() {
2017 *flags |= DOM_HAS_UNICODE_BIDI;
2018 }
2019 }
2020 CssProperty::TextBoxTrim(v) => {
2021 if v.get_property().is_some() {
2022 *flags |= DOM_HAS_TEXT_BOX_TRIM;
2023 }
2024 }
2025 CssProperty::Hyphens(v) => {
2026 if v.get_property().is_some() {
2027 *flags |= DOM_HAS_HYPHENS;
2028 }
2029 }
2030 CssProperty::WordBreak(v) => {
2031 if v.get_property().is_some() {
2032 *flags |= DOM_HAS_WORD_BREAK;
2033 }
2034 }
2035 CssProperty::OverflowWrap(v) => {
2036 if v.get_property().is_some() {
2037 *flags |= DOM_HAS_OVERFLOW_WRAP;
2038 }
2039 }
2040 CssProperty::LineBreak(v) => {
2041 if v.get_property().is_some() {
2042 *flags |= DOM_HAS_LINE_BREAK;
2043 }
2044 }
2045 CssProperty::TextAlignLast(v) => {
2046 if v.get_property().is_some() {
2047 *flags |= DOM_HAS_TEXT_ALIGN_LAST;
2048 }
2049 }
2050 CssProperty::LineHeight(v) => {
2051 if v.get_property().is_some() {
2052 *flags |= DOM_HAS_LINE_HEIGHT;
2053 }
2054 }
2055 _ => {}
2056 }
2057}
2058
2059#[allow(clippy::cast_possible_truncation)]
2067const fn encode_grid_line(line: &azul_css::props::layout::grid::GridLine) -> i16 {
2068 use azul_css::props::layout::grid::GridLine;
2069 match line {
2070 GridLine::Auto => I16_AUTO,
2071 GridLine::Line(n) => {
2072 if *n >= -32000 && *n <= 32000 {
2073 *n as i16
2074 } else {
2075 I16_SENTINEL
2076 }
2077 }
2078 GridLine::Span(n) => {
2079 if *n >= 1 && *n <= 32000 {
2080 -(*n as i16)
2081 } else {
2082 I16_SENTINEL
2083 }
2084 }
2085 GridLine::Named(_) => I16_SENTINEL,
2086 }
2087}
2088
2089fn encode_layout_width<T: LayoutWidthLike>(val: &CssPropertyValue<T>) -> u32 {
2091 match val {
2092 CssPropertyValue::Exact(w) => w.encode_compact_u32(),
2093 CssPropertyValue::Auto => U32_AUTO,
2094 CssPropertyValue::Initial => U32_INITIAL,
2095 CssPropertyValue::Inherit => U32_INHERIT,
2096 CssPropertyValue::None => U32_NONE,
2097 _ => U32_SENTINEL,
2098 }
2099}
2100
2101fn encode_layout_height<T: LayoutWidthLike>(val: &CssPropertyValue<T>) -> u32 {
2103 encode_layout_width(val)
2104}
2105
2106trait LayoutWidthLike {
2109 fn encode_compact_u32(&self) -> u32;
2110}
2111
2112impl LayoutWidthLike for LayoutWidth {
2113 fn encode_compact_u32(&self) -> u32 {
2114 match self {
2115 Self::Auto => U32_AUTO,
2116 Self::Px(pv) => encode_pixel_value_u32(pv),
2117 Self::MinContent => U32_MIN_CONTENT,
2118 Self::MaxContent => U32_MAX_CONTENT,
2119 Self::FitContent(_) | Self::Calc(_) => U32_SENTINEL,
2121 }
2122 }
2123}
2124
2125impl LayoutWidthLike for LayoutHeight {
2126 fn encode_compact_u32(&self) -> u32 {
2127 match self {
2128 Self::Auto => U32_AUTO,
2129 Self::Px(pv) => encode_pixel_value_u32(pv),
2130 Self::MinContent => U32_MIN_CONTENT,
2131 Self::MaxContent => U32_MAX_CONTENT,
2132 Self::FitContent(_) | Self::Calc(_) => U32_SENTINEL,
2134 }
2135 }
2136}
2137
2138fn encode_pixel_prop<T: HasInnerPixelValue>(val: &CssPropertyValue<T>) -> u32 {
2140 match val {
2141 CssPropertyValue::Exact(inner) => encode_pixel_value_u32(&inner.get_inner_pixel()),
2142 CssPropertyValue::Auto => U32_AUTO,
2143 CssPropertyValue::Initial => U32_INITIAL,
2144 CssPropertyValue::Inherit => U32_INHERIT,
2145 CssPropertyValue::None => U32_NONE,
2146 _ => U32_SENTINEL,
2147 }
2148}
2149
2150trait HasInnerPixelValue {
2152 fn get_inner_pixel(&self) -> azul_css::props::basic::pixel::PixelValue;
2153}
2154
2155macro_rules! impl_has_inner_pixel {
2156 ($($ty:ty),*) => {
2157 $(
2158 impl HasInnerPixelValue for $ty {
2159 fn get_inner_pixel(&self) -> azul_css::props::basic::pixel::PixelValue {
2160 self.inner
2161 }
2162 }
2163 )*
2164 };
2165}
2166
2167impl_has_inner_pixel!(
2168 azul_css::props::layout::dimensions::LayoutMinWidth,
2169 azul_css::props::layout::dimensions::LayoutMaxWidth,
2170 azul_css::props::layout::dimensions::LayoutMinHeight,
2171 azul_css::props::layout::dimensions::LayoutMaxHeight,
2172 azul_css::props::basic::font::StyleFontSize,
2173 azul_css::props::layout::spacing::LayoutPaddingTop,
2174 azul_css::props::layout::spacing::LayoutPaddingRight,
2175 azul_css::props::layout::spacing::LayoutPaddingBottom,
2176 azul_css::props::layout::spacing::LayoutPaddingLeft,
2177 azul_css::props::layout::spacing::LayoutMarginTop,
2178 azul_css::props::layout::spacing::LayoutMarginRight,
2179 azul_css::props::layout::spacing::LayoutMarginBottom,
2180 azul_css::props::layout::spacing::LayoutMarginLeft,
2181 azul_css::props::style::border::LayoutBorderTopWidth,
2182 azul_css::props::style::border::LayoutBorderRightWidth,
2183 azul_css::props::style::border::LayoutBorderBottomWidth,
2184 azul_css::props::style::border::LayoutBorderLeftWidth,
2185 azul_css::props::layout::position::LayoutTop,
2186 azul_css::props::layout::position::LayoutRight,
2187 azul_css::props::layout::position::LayoutInsetBottom,
2188 azul_css::props::layout::position::LayoutLeft,
2189 azul_css::props::style::text::StyleLetterSpacing,
2190 azul_css::props::style::text::StyleWordSpacing,
2191 azul_css::props::style::text::StyleTextIndent,
2192 azul_css::props::style::text::StyleTabSize
2193);
2194
2195fn encode_css_pixel_as_i16<T: HasInnerPixelValue>(val: &CssPropertyValue<T>) -> i16 {
2198 let mapped = match val {
2199 CssPropertyValue::Exact(inner) => CssPropertyValue::Exact(inner.get_inner_pixel()),
2200 CssPropertyValue::Auto => CssPropertyValue::Auto,
2201 CssPropertyValue::Initial => CssPropertyValue::Initial,
2202 CssPropertyValue::Inherit => CssPropertyValue::Inherit,
2203 CssPropertyValue::None => CssPropertyValue::None,
2204 _ => return I16_SENTINEL,
2205 };
2206 azul_css::compact_cache::encode_css_pixel_as_i16(&mapped)
2207}
2208
2209fn encode_margin_i16<T: HasInnerPixelValue>(val: &CssPropertyValue<T>) -> i16 {
2211 encode_css_pixel_as_i16(val)
2212}
2213
2214fn encode_flex_basis(val: &CssPropertyValue<LayoutFlexBasis>) -> u32 {
2216 match val {
2217 CssPropertyValue::Exact(fb) => match fb {
2218 LayoutFlexBasis::Auto => U32_AUTO,
2219 LayoutFlexBasis::Exact(pv) => encode_pixel_value_u32(pv),
2220 },
2221 CssPropertyValue::Auto => U32_AUTO,
2222 CssPropertyValue::Initial => U32_INITIAL,
2223 CssPropertyValue::Inherit => U32_INHERIT,
2224 CssPropertyValue::None => U32_NONE,
2225 _ => U32_SENTINEL,
2226 }
2227}
2228
2229#[cfg(test)]
2230#[path = "compact_test.rs"]
2231mod compact_test;