1use crate::dom::{NodeData, NodeId};
8use crate::prop_cache::CssPropertyCache;
9
10use crate::styled_dom::StyledNodeState;
11use azul_css::compact_cache::*;
12use azul_css::css::CssPropertyValue;
13use azul_css::props::property::CssProperty;
14use azul_css::props::basic::length::SizeMetric;
15use azul_css::props::layout::dimensions::{LayoutHeight, LayoutWidth};
16use azul_css::props::layout::flex::LayoutFlexBasis;
17use azul_css::props::layout::position::LayoutZIndex;
18use core::hash::{Hash, Hasher};
19use std::collections::hash_map::DefaultHasher;
20
21impl CssPropertyCache {
22 pub fn build_compact_cache(
37 &self,
38 node_data: &[NodeData],
39 prev_font_hashes: &[u64],
40 ) -> CompactLayoutCache {
41 let node_count = self.node_count;
42 let default_state = StyledNodeState::default();
43 let mut result = CompactLayoutCache::with_capacity(node_count);
44
45 for i in 0..node_count {
46 let node_id = NodeId::new(i);
47 let nd = &node_data[i];
48
49 let display = self
54 .get_display(nd, &node_id, &default_state)
55 .and_then(|v| v.get_property().copied())
56 .unwrap_or_default();
57 let position = self
58 .get_position(nd, &node_id, &default_state)
59 .and_then(|v| v.get_property().copied())
60 .unwrap_or_default();
61 let float = self
62 .get_float(nd, &node_id, &default_state)
63 .and_then(|v| v.get_property().copied())
64 .unwrap_or_default();
65 let overflow_x = self
66 .get_overflow_x(nd, &node_id, &default_state)
67 .and_then(|v| v.get_property().copied())
68 .unwrap_or_default();
69 let overflow_y = self
70 .get_overflow_y(nd, &node_id, &default_state)
71 .and_then(|v| v.get_property().copied())
72 .unwrap_or_default();
73 let box_sizing = self
74 .get_box_sizing(nd, &node_id, &default_state)
75 .and_then(|v| v.get_property().copied())
76 .unwrap_or_default();
77 let flex_direction = self
78 .get_flex_direction(nd, &node_id, &default_state)
79 .and_then(|v| v.get_property().copied())
80 .unwrap_or_default();
81 let flex_wrap = self
82 .get_flex_wrap(nd, &node_id, &default_state)
83 .and_then(|v| v.get_property().copied())
84 .unwrap_or_default();
85 let justify_content = self
86 .get_justify_content(nd, &node_id, &default_state)
87 .and_then(|v| v.get_property().copied())
88 .unwrap_or_default();
89 let align_items = self
90 .get_align_items(nd, &node_id, &default_state)
91 .and_then(|v| v.get_property().copied())
92 .unwrap_or_default();
93 let align_content = self
94 .get_align_content(nd, &node_id, &default_state)
95 .and_then(|v| v.get_property().copied())
96 .unwrap_or_default();
97 let writing_mode = self
98 .get_writing_mode(nd, &node_id, &default_state)
99 .and_then(|v| v.get_property().copied())
100 .unwrap_or_default();
101 let clear = self
102 .get_clear(nd, &node_id, &default_state)
103 .and_then(|v| v.get_property().copied())
104 .unwrap_or_default();
105 let font_weight = self
106 .get_font_weight(nd, &node_id, &default_state)
107 .and_then(|v| v.get_property().copied())
108 .unwrap_or_default();
109 let font_style = self
110 .get_font_style(nd, &node_id, &default_state)
111 .and_then(|v| v.get_property().copied())
112 .unwrap_or_default();
113 let text_align = self
114 .get_text_align(nd, &node_id, &default_state)
115 .and_then(|v| v.get_property().copied())
116 .unwrap_or_default();
117 let visibility = self
118 .get_visibility(nd, &node_id, &default_state)
119 .and_then(|v| v.get_property().copied())
120 .unwrap_or_default();
121 let white_space = self
122 .get_white_space(nd, &node_id, &default_state)
123 .and_then(|v| v.get_property().copied())
124 .unwrap_or_default();
125 let direction = self
126 .get_direction(nd, &node_id, &default_state)
127 .and_then(|v| v.get_property().copied())
128 .unwrap_or_default();
129 let vertical_align = self
130 .get_vertical_align(nd, &node_id, &default_state)
131 .and_then(|v| v.get_property().copied())
132 .unwrap_or_default();
133
134 let border_collapse = self
135 .get_border_collapse(nd, &node_id, &default_state)
136 .and_then(|v| v.get_property().copied())
137 .unwrap_or_default();
138
139 result.tier1_enums[i] = encode_tier1(
140 display,
141 position,
142 float,
143 overflow_x,
144 overflow_y,
145 box_sizing,
146 flex_direction,
147 flex_wrap,
148 justify_content,
149 align_items,
150 align_content,
151 writing_mode,
152 clear,
153 font_weight,
154 font_style,
155 text_align,
156 visibility,
157 white_space,
158 direction,
159 vertical_align,
160 border_collapse,
161 );
162
163 if let Some(val) = self.get_width(nd, &node_id, &default_state) {
169 result.tier2_dims[i].width = encode_layout_width(val);
170 }
171 if let Some(val) = self.get_height(nd, &node_id, &default_state) {
172 result.tier2_dims[i].height = encode_layout_height(val);
173 }
174
175 if let Some(val) = self.get_min_width(nd, &node_id, &default_state) {
177 result.tier2_dims[i].min_width = encode_pixel_prop(val);
178 }
179 if let Some(val) = self.get_max_width(nd, &node_id, &default_state) {
180 result.tier2_dims[i].max_width = encode_pixel_prop(val);
181 }
182 if let Some(val) = self.get_min_height(nd, &node_id, &default_state) {
183 result.tier2_dims[i].min_height = encode_pixel_prop(val);
184 }
185 if let Some(val) = self.get_max_height(nd, &node_id, &default_state) {
186 result.tier2_dims[i].max_height = encode_pixel_prop(val);
187 }
188
189 if let Some(val) = self.get_flex_basis(nd, &node_id, &default_state) {
191 result.tier2_dims[i].flex_basis = encode_flex_basis(val);
192 }
193
194 if let Some(val) = self.get_font_size(nd, &node_id, &default_state) {
196 result.tier2_dims[i].font_size = encode_pixel_prop(val);
197 }
198
199 if let Some(val) = self.get_padding_top(nd, &node_id, &default_state) {
201 result.tier2_dims[i].padding_top = encode_css_pixel_as_i16(val);
202 }
203 if let Some(val) = self.get_padding_right(nd, &node_id, &default_state) {
204 result.tier2_dims[i].padding_right = encode_css_pixel_as_i16(val);
205 }
206 if let Some(val) = self.get_padding_bottom(nd, &node_id, &default_state) {
207 result.tier2_dims[i].padding_bottom = encode_css_pixel_as_i16(val);
208 }
209 if let Some(val) = self.get_padding_left(nd, &node_id, &default_state) {
210 result.tier2_dims[i].padding_left = encode_css_pixel_as_i16(val);
211 }
212
213 if let Some(val) = self.get_margin_top(nd, &node_id, &default_state) {
215 result.tier2_dims[i].margin_top = encode_margin_i16(val);
216 }
217 if let Some(val) = self.get_margin_right(nd, &node_id, &default_state) {
218 result.tier2_dims[i].margin_right = encode_margin_i16(val);
219 }
220 if let Some(val) = self.get_margin_bottom(nd, &node_id, &default_state) {
221 result.tier2_dims[i].margin_bottom = encode_margin_i16(val);
222 }
223 if let Some(val) = self.get_margin_left(nd, &node_id, &default_state) {
224 result.tier2_dims[i].margin_left = encode_margin_i16(val);
225 }
226
227 if let Some(val) = self.get_border_top_width(nd, &node_id, &default_state) {
229 result.tier2_dims[i].border_top_width = encode_css_pixel_as_i16(val);
230 }
231 if let Some(val) = self.get_border_right_width(nd, &node_id, &default_state) {
232 result.tier2_dims[i].border_right_width = encode_css_pixel_as_i16(val);
233 }
234 if let Some(val) = self.get_border_bottom_width(nd, &node_id, &default_state) {
235 result.tier2_dims[i].border_bottom_width = encode_css_pixel_as_i16(val);
236 }
237 if let Some(val) = self.get_border_left_width(nd, &node_id, &default_state) {
238 result.tier2_dims[i].border_left_width = encode_css_pixel_as_i16(val);
239 }
240
241 if let Some(val) = self.get_top(nd, &node_id, &default_state) {
243 result.tier2_dims[i].top = encode_css_pixel_as_i16(val);
244 }
245 if let Some(val) = self.get_right(nd, &node_id, &default_state) {
246 result.tier2_dims[i].right = encode_css_pixel_as_i16(val);
247 }
248 if let Some(val) = self.get_bottom(nd, &node_id, &default_state) {
249 result.tier2_dims[i].bottom = encode_css_pixel_as_i16(val);
250 }
251 if let Some(val) = self.get_left(nd, &node_id, &default_state) {
252 result.tier2_dims[i].left = encode_css_pixel_as_i16(val);
253 }
254
255 if let Some(val) = self.get_flex_grow(nd, &node_id, &default_state) {
257 if let Some(exact) = val.get_property() {
258 result.tier2_dims[i].flex_grow = encode_flex_u16(exact.inner.get());
259 }
260 }
261 if let Some(val) = self.get_flex_shrink(nd, &node_id, &default_state) {
262 if let Some(exact) = val.get_property() {
263 result.tier2_dims[i].flex_shrink = encode_flex_u16(exact.inner.get());
264 }
265 }
266
267 if let Some(val) = self.get_z_index(nd, &node_id, &default_state) {
273 if let Some(exact) = val.get_property() {
274 match exact {
275 LayoutZIndex::Auto => result.tier2_cold[i].z_index = I16_AUTO,
276 LayoutZIndex::Integer(z) => {
277 if *z >= I16_SENTINEL_THRESHOLD as i32 {
278 result.tier2_cold[i].z_index = I16_SENTINEL;
279 } else {
280 result.tier2_cold[i].z_index = *z as i16;
281 }
282 }
283 }
284 }
285 }
286
287 {
289 let bts = self.get_border_top_style(nd, &node_id, &default_state)
290 .and_then(|v| v.get_property().copied())
291 .map(|v| v.inner)
292 .unwrap_or_default();
293 let brs = self.get_border_right_style(nd, &node_id, &default_state)
294 .and_then(|v| v.get_property().copied())
295 .map(|v| v.inner)
296 .unwrap_or_default();
297 let bbs = self.get_border_bottom_style(nd, &node_id, &default_state)
298 .and_then(|v| v.get_property().copied())
299 .map(|v| v.inner)
300 .unwrap_or_default();
301 let bls = self.get_border_left_style(nd, &node_id, &default_state)
302 .and_then(|v| v.get_property().copied())
303 .map(|v| v.inner)
304 .unwrap_or_default();
305 result.tier2_cold[i].border_styles_packed =
306 encode_border_styles_packed(bts, brs, bbs, bls);
307 }
308
309 if let Some(val) = self.get_border_top_color(nd, &node_id, &default_state) {
311 if let Some(color) = val.get_property() {
312 result.tier2_cold[i].border_top_color = encode_color_u32(&color.inner);
313 }
314 }
315 if let Some(val) = self.get_border_right_color(nd, &node_id, &default_state) {
316 if let Some(color) = val.get_property() {
317 result.tier2_cold[i].border_right_color = encode_color_u32(&color.inner);
318 }
319 }
320 if let Some(val) = self.get_border_bottom_color(nd, &node_id, &default_state) {
321 if let Some(color) = val.get_property() {
322 result.tier2_cold[i].border_bottom_color = encode_color_u32(&color.inner);
323 }
324 }
325 if let Some(val) = self.get_border_left_color(nd, &node_id, &default_state) {
326 if let Some(color) = val.get_property() {
327 result.tier2_cold[i].border_left_color = encode_color_u32(&color.inner);
328 }
329 }
330
331 if let Some(val) = self.get_border_spacing(nd, &node_id, &default_state) {
333 if let Some(spacing) = val.get_property() {
334 if spacing.horizontal.metric == SizeMetric::Px {
335 result.tier2_cold[i].border_spacing_h = encode_resolved_px_i16(spacing.horizontal.number.get());
336 }
337 if spacing.vertical.metric == SizeMetric::Px {
338 result.tier2_cold[i].border_spacing_v = encode_resolved_px_i16(spacing.vertical.number.get());
339 }
340 }
341 }
342
343 if let Some(val) = self.get_tab_size(nd, &node_id, &default_state) {
345 result.tier2_cold[i].tab_size = encode_css_pixel_as_i16(val);
346 }
347
348 if let Some(val) = self.get_text_color(nd, &node_id, &default_state) {
354 if let Some(color) = val.get_property() {
355 let c = &color.inner;
356 result.tier2b_text[i].text_color =
357 ((c.r as u32) << 24) | ((c.g as u32) << 16) | ((c.b as u32) << 8) | (c.a as u32);
358 }
359 }
360
361 if let Some(val) = self.get_font_family(nd, &node_id, &default_state) {
363 if let Some(families) = val.get_property() {
364 let mut hasher = DefaultHasher::new();
365 families.hash(&mut hasher);
366 let h = hasher.finish();
367 let h = if h == 0 { 1 } else { h };
368 result.tier2b_text[i].font_family_hash = h;
369 result.font_hash_to_families.insert(h, families.clone());
370 }
371 }
372
373 if let Some(val) = self.get_line_height(nd, &node_id, &default_state) {
375 if let Some(lh) = val.get_property() {
376 let pct_x10 = (lh.inner.normalized() * 1000.0).round() as i32;
380 if pct_x10 >= -32768 && pct_x10 < I16_SENTINEL_THRESHOLD as i32 {
381 result.tier2b_text[i].line_height = pct_x10 as i16;
382 } else {
383 result.tier2b_text[i].line_height = I16_SENTINEL;
384 }
385 }
386 }
387
388 if let Some(val) = self.get_letter_spacing(nd, &node_id, &default_state) {
390 result.tier2b_text[i].letter_spacing = encode_css_pixel_as_i16(val);
391 }
392
393 if let Some(val) = self.get_word_spacing(nd, &node_id, &default_state) {
395 result.tier2b_text[i].word_spacing = encode_css_pixel_as_i16(val);
396 }
397
398 if let Some(val) = self.get_text_indent(nd, &node_id, &default_state) {
400 result.tier2b_text[i].text_indent = encode_css_pixel_as_i16(val);
401 }
402 }
403
404 result.font_dirty_nodes.clear();
411 for i in 0..node_count {
412 let new_hash = result.tier2b_text[i].font_family_hash;
413 let old_hash = prev_font_hashes.get(i).copied().unwrap_or(0);
414 if new_hash != old_hash {
415 result.font_dirty_nodes.push(i);
416 }
417 }
418 result.prev_font_hashes = result.tier2b_text.iter().map(|t| t.font_family_hash).collect();
420
421 result
422 }
423
424 pub fn build_compact_cache_with_inheritance(
435 &self,
436 node_data: &[NodeData],
437 node_hierarchy: &[crate::styled_dom::NodeHierarchyItem],
438 prev_font_hashes: &[u64],
439 ) -> CompactLayoutCache {
440 self.build_compact_cache_with_inheritance_debug(node_data, node_hierarchy, prev_font_hashes, &mut None)
441 }
442
443 pub fn build_compact_cache_with_inheritance_debug(
445 &self,
446 node_data: &[NodeData],
447 node_hierarchy: &[crate::styled_dom::NodeHierarchyItem],
448 prev_font_hashes: &[u64],
449 debug_messages: &mut Option<Vec<azul_css::LayoutDebugMessage>>,
450 ) -> CompactLayoutCache {
451 let node_count = self.node_count;
452 let default_state = StyledNodeState::default();
453 let mut result = CompactLayoutCache::with_capacity(node_count);
454
455 let mut global_tier1: u64 = 0;
458 let mut global_dims = CompactNodeProps::default();
459 let mut global_cold = CompactNodePropsCold::default();
460 let mut global_text = CompactTextProps::default();
461 let has_global = !self.global_css_props.is_empty();
462
463 if has_global {
464 use azul_css::props::property::CssProperty;
465
466 for prop in &self.global_css_props {
467 macro_rules! global_tier1_enum {
469 ($variant:ident, $shift:ident, $mask:ident, $encoder:ident) => {
470 if let CssProperty::$variant(v) = prop {
471 if let Some(exact) = v.get_property() {
472 let encoded = $encoder(*exact) as u64;
473 let shifted_mask = $mask << $shift;
474 global_tier1 = (global_tier1 & !shifted_mask) | ((encoded & $mask) << $shift);
475 }
476 }
477 };
478 }
479
480 global_tier1_enum!(Display, DISPLAY_SHIFT, DISPLAY_MASK, layout_display_to_u8);
481 global_tier1_enum!(Position, POSITION_SHIFT, POSITION_MASK, layout_position_to_u8);
482 global_tier1_enum!(Float, FLOAT_SHIFT, FLOAT_MASK, layout_float_to_u8);
483 global_tier1_enum!(OverflowX, OVERFLOW_X_SHIFT, OVERFLOW_MASK, layout_overflow_to_u8);
484 global_tier1_enum!(OverflowY, OVERFLOW_Y_SHIFT, OVERFLOW_MASK, layout_overflow_to_u8);
485 global_tier1_enum!(BoxSizing, BOX_SIZING_SHIFT, BOX_SIZING_MASK, layout_box_sizing_to_u8);
486 global_tier1_enum!(FlexDirection, FLEX_DIRECTION_SHIFT, FLEX_DIR_MASK, layout_flex_direction_to_u8);
487 global_tier1_enum!(FlexWrap, FLEX_WRAP_SHIFT, FLEX_WRAP_MASK, layout_flex_wrap_to_u8);
488 global_tier1_enum!(JustifyContent, JUSTIFY_CONTENT_SHIFT, JUSTIFY_MASK, layout_justify_content_to_u8);
489 global_tier1_enum!(AlignItems, ALIGN_ITEMS_SHIFT, ALIGN_MASK, layout_align_items_to_u8);
490 global_tier1_enum!(AlignContent, ALIGN_CONTENT_SHIFT, ALIGN_MASK, layout_align_content_to_u8);
491 global_tier1_enum!(Clear, CLEAR_SHIFT, CLEAR_MASK, layout_clear_to_u8);
492 global_tier1_enum!(Visibility, VISIBILITY_SHIFT, VISIBILITY_MASK, style_visibility_to_u8);
493 global_tier1_enum!(WritingMode, WRITING_MODE_SHIFT, WRITING_MODE_MASK, layout_writing_mode_to_u8);
494 global_tier1_enum!(FontWeight, FONT_WEIGHT_SHIFT, FONT_WEIGHT_MASK, style_font_weight_to_u8);
495 global_tier1_enum!(FontStyle, FONT_STYLE_SHIFT, FONT_STYLE_MASK, style_font_style_to_u8);
496 global_tier1_enum!(TextAlign, TEXT_ALIGN_SHIFT, TEXT_ALIGN_MASK, style_text_align_to_u8);
497 global_tier1_enum!(WhiteSpace, WHITE_SPACE_SHIFT, WHITE_SPACE_MASK, style_white_space_to_u8);
498 global_tier1_enum!(Direction, DIRECTION_SHIFT, DIRECTION_MASK, style_direction_to_u8);
499 global_tier1_enum!(VerticalAlign, VERTICAL_ALIGN_SHIFT, VERTICAL_ALIGN_MASK, style_vertical_align_to_u8);
500 global_tier1_enum!(BorderCollapse, BORDER_COLLAPSE_SHIFT, BORDER_COLLAPSE_MASK, border_collapse_to_u8);
501
502 match prop {
504 CssProperty::PaddingTop(v) => { global_dims.padding_top = encode_css_pixel_as_i16(v); }
505 CssProperty::PaddingRight(v) => { global_dims.padding_right = encode_css_pixel_as_i16(v); }
506 CssProperty::PaddingBottom(v) => { global_dims.padding_bottom = encode_css_pixel_as_i16(v); }
507 CssProperty::PaddingLeft(v) => { global_dims.padding_left = encode_css_pixel_as_i16(v); }
508 CssProperty::MarginTop(v) => { global_dims.margin_top = encode_margin_i16(v); }
509 CssProperty::MarginRight(v) => { global_dims.margin_right = encode_margin_i16(v); }
510 CssProperty::MarginBottom(v) => { global_dims.margin_bottom = encode_margin_i16(v); }
511 CssProperty::MarginLeft(v) => { global_dims.margin_left = encode_margin_i16(v); }
512 CssProperty::Width(v) => { global_dims.width = encode_layout_width(v); }
513 CssProperty::Height(v) => { global_dims.height = encode_layout_height(v); }
514 CssProperty::FontSize(v) => { global_dims.font_size = encode_pixel_prop(v); }
515 CssProperty::BorderTopWidth(v) => { global_dims.border_top_width = encode_css_pixel_as_i16(v); }
516 CssProperty::BorderRightWidth(v) => { global_dims.border_right_width = encode_css_pixel_as_i16(v); }
517 CssProperty::BorderBottomWidth(v) => { global_dims.border_bottom_width = encode_css_pixel_as_i16(v); }
518 CssProperty::BorderLeftWidth(v) => { global_dims.border_left_width = encode_css_pixel_as_i16(v); }
519 _ => {}
520 }
521 }
522
523 if global_tier1 != 0 {
524 global_tier1 |= TIER1_POPULATED_BIT;
525 }
526 }
527
528 macro_rules! cascade_debug {
530 ($($arg:tt)*) => {
531 if let Some(ref mut msgs) = debug_messages {
532 msgs.push(azul_css::LayoutDebugMessage::css_getter(format!($($arg)*)));
533 }
534 };
535 }
536
537 for i in 0..node_count {
538 let node_id = NodeId::new(i);
539 let nd = &node_data[i];
540
541 const INHERITABLE_TIER1_MASK: u64 =
555 (FONT_WEIGHT_MASK << FONT_WEIGHT_SHIFT)
556 | (FONT_STYLE_MASK << FONT_STYLE_SHIFT)
557 | (TEXT_ALIGN_MASK << TEXT_ALIGN_SHIFT)
558 | (VISIBILITY_MASK << VISIBILITY_SHIFT)
559 | (WHITE_SPACE_MASK << WHITE_SPACE_SHIFT)
560 | (DIRECTION_MASK << DIRECTION_SHIFT)
561 | (BORDER_COLLAPSE_MASK << BORDER_COLLAPSE_SHIFT);
562
563 let parent_id = node_hierarchy[i].parent_id();
564 if let Some(pid) = parent_id {
565 let pi = pid.index();
566
567 result.tier1_enums[i] = result.tier1_enums[pi] & INHERITABLE_TIER1_MASK;
569
570 result.tier2_dims[i].font_size = result.tier2_dims[pi].font_size;
572
573 result.tier2_cold[i].border_spacing_h = result.tier2_cold[pi].border_spacing_h;
575 result.tier2_cold[i].border_spacing_v = result.tier2_cold[pi].border_spacing_v;
576 result.tier2_cold[i].tab_size = result.tier2_cold[pi].tab_size;
577
578 result.tier2b_text[i] = result.tier2b_text[pi];
580 }
581
582 {
583 let d = &result.tier2_dims[i];
584 cascade_debug!("node[{}] {:?} after-inherit: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={} w={} h={}",
585 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
586 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right, d.width, d.height);
587 }
588
589 apply_ua_css_to_compact(
592 &nd.node_type,
593 &mut result.tier1_enums[i],
594 &mut result.tier2_dims[i],
595 &mut result.tier2_cold[i],
596 &mut result.tier2b_text[i],
597 &mut result.font_hash_to_families,
598 );
599
600 {
601 let d = &result.tier2_dims[i];
602 cascade_debug!("node[{}] {:?} after-UA: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={}",
603 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
604 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right);
605 }
606
607 if !nd.is_text_node() {
616 for prop in self.global_css_props.iter() {
617 apply_css_property_to_compact(
618 prop,
619 &mut result.tier1_enums[i],
620 &mut result.tier2_dims[i],
621 &mut result.tier2_cold[i],
622 &mut result.tier2b_text[i],
623 &mut result.font_hash_to_families,
624 );
625 update_dom_declared_flags(prop, &mut result.dom_declared_flags);
626 }
627 }
628
629 {
630 let d = &result.tier2_dims[i];
631 cascade_debug!("node[{}] {:?} after-global-star: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={}",
632 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
633 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right);
634 let n_props = self.css_props.get_slice(i).len();
635 let n_inline = nd.style.iter_inline_properties().count();
636 cascade_debug!("node[{}] css_props={} entries, inline={} entries", i, n_props, n_inline);
637 for prop in self.css_props.get_slice(i) {
638 cascade_debug!("node[{}] css_prop: state={:?} type={:?}", i, prop.state, prop.prop_type);
639 }
640 }
641
642 for prop in self.css_props.get_slice(i) {
648 if prop.state != azul_css::dynamic_selector::PseudoStateType::Normal { continue; }
649 apply_css_property_to_compact(
650 &prop.property,
651 &mut result.tier1_enums[i],
652 &mut result.tier2_dims[i],
653 &mut result.tier2_cold[i],
654 &mut result.tier2b_text[i],
655 &mut result.font_hash_to_families,
656 );
657 update_dom_declared_flags(&prop.property, &mut result.dom_declared_flags);
658 }
659
660 {
661 let d = &result.tier2_dims[i];
662 cascade_debug!("node[{}] {:?} after-css-props: pt={} pb={} pl={} pr={} mt={} mb={} ml={} mr={}",
663 i, nd.node_type, d.padding_top, d.padding_bottom, d.padding_left, d.padding_right,
664 d.margin_top, d.margin_bottom, d.margin_left, d.margin_right);
665 }
666
667 for (prop, conds) in nd.style.iter_inline_properties() {
670 let is_normal = conds.as_slice().is_empty()
672 || conds.as_slice().iter().all(|c|
673 matches!(c, azul_css::dynamic_selector::DynamicSelector::PseudoState(
674 azul_css::dynamic_selector::PseudoStateType::Normal
675 ))
676 );
677 if !is_normal { continue; }
678 apply_css_property_to_compact(
679 prop,
680 &mut result.tier1_enums[i],
681 &mut result.tier2_dims[i],
682 &mut result.tier2_cold[i],
683 &mut result.tier2b_text[i],
684 &mut result.font_hash_to_families,
685 );
686 update_dom_declared_flags(prop, &mut result.dom_declared_flags);
687 }
688
689 resolve_font_size_to_px(
693 &mut result.tier2_dims,
694 i,
695 parent_id,
696 );
697
698 if result.tier1_enums[i] != 0 {
700 result.tier1_enums[i] |= TIER1_POPULATED_BIT;
701 }
702 }
703
704 result.font_dirty_nodes.clear();
711 let first_build = prev_font_hashes.is_empty();
712 for i in 0..node_count {
713 let new_hash = result.tier2b_text[i].font_family_hash;
714 let old_hash = prev_font_hashes.get(i).copied().unwrap_or(0);
715 if first_build || new_hash != old_hash {
716 result.font_dirty_nodes.push(i);
717 }
718 }
719 result.prev_font_hashes = result.tier2b_text.iter().map(|t| t.font_family_hash).collect();
720
721 result
722 }
723}
724
725fn apply_ua_css_to_compact(
732 node_type: &crate::dom::NodeType,
733 tier1: &mut u64,
734 dims: &mut CompactNodeProps,
735 cold: &mut CompactNodePropsCold,
736 text: &mut CompactTextProps,
737 font_hash_map: &mut alloc::collections::BTreeMap<u64, azul_css::props::basic::font::StyleFontFamilyVec>,
738) {
739 use azul_css::props::property::CssPropertyType as PT2;
740 const UA_PROPERTY_TYPES: &[PT2] = &[
741 PT2::Display, PT2::Position, PT2::Float, PT2::Clear,
743 PT2::OverflowX, PT2::OverflowY, PT2::BoxSizing,
744 PT2::FlexDirection, PT2::FlexWrap, PT2::JustifyContent,
745 PT2::AlignItems, PT2::AlignContent, PT2::WritingMode,
746 PT2::FontWeight, PT2::FontStyle, PT2::TextAlign,
747 PT2::Visibility, PT2::WhiteSpace, PT2::Direction,
748 PT2::VerticalAlign, PT2::BorderCollapse,
749 PT2::Width, PT2::Height, PT2::FontSize,
751 PT2::MarginTop, PT2::MarginBottom, PT2::MarginLeft, PT2::MarginRight,
752 PT2::PaddingTop, PT2::PaddingBottom, PT2::PaddingLeft, PT2::PaddingRight,
753 PT2::BorderTopWidth, PT2::BorderTopStyle, PT2::BorderTopColor,
754 PT2::BorderRightWidth, PT2::BorderRightStyle, PT2::BorderRightColor,
755 PT2::BorderBottomWidth, PT2::BorderBottomStyle, PT2::BorderBottomColor,
756 PT2::BorderLeftWidth, PT2::BorderLeftStyle, PT2::BorderLeftColor,
757 PT2::TextColor, PT2::LineHeight, PT2::LetterSpacing, PT2::WordSpacing,
759 PT2::TextDecoration, PT2::Cursor, PT2::ListStyleType,
760 ];
761 for pt in UA_PROPERTY_TYPES {
762 if let Some(ua_prop) = crate::ua_css::get_ua_property(node_type, *pt) {
763 apply_css_property_to_compact(ua_prop, tier1, dims, cold, text, font_hash_map);
764 }
765 }
766}
767
768fn resolve_font_size_to_px(
772 tier2_dims: &mut [CompactNodeProps],
773 node_idx: usize,
774 parent_id: Option<NodeId>,
775) {
776 let raw_fs = tier2_dims[node_idx].font_size;
777 if raw_fs == U32_SENTINEL || raw_fs >= U32_SENTINEL_THRESHOLD {
778 return;
779 }
780 let pv = match decode_pixel_value_u32(raw_fs) {
781 Some(pv) if pv.metric != SizeMetric::Px => pv,
782 _ => return,
783 };
784
785 let parent_font_size_px = parent_id
786 .map(|pid| {
787 decode_pixel_value_u32(tier2_dims[pid.index()].font_size)
788 .map(|ppv| ppv.number.get())
789 .unwrap_or(16.0)
790 })
791 .unwrap_or(16.0);
792
793 let resolved_px = match pv.metric {
794 SizeMetric::Em => pv.number.get() * parent_font_size_px,
795 SizeMetric::Percent => pv.number.get() / 100.0 * parent_font_size_px,
796 SizeMetric::Rem => {
797 decode_pixel_value_u32(tier2_dims[0].font_size)
798 .map(|rpv| rpv.number.get())
799 .unwrap_or(16.0)
800 * pv.number.get()
801 }
802 SizeMetric::Pt => pv.number.get() * 96.0 / 72.0,
803 _ => pv.number.get(),
804 };
805 tier2_dims[node_idx].font_size =
806 encode_pixel_value_u32(&azul_css::props::basic::pixel::PixelValue::px(resolved_px));
807}
808
809#[inline]
816fn apply_css_property_to_compact(
817 prop: &CssProperty,
818 tier1: &mut u64,
819 dims: &mut CompactNodeProps,
820 cold: &mut CompactNodePropsCold,
821 text: &mut CompactTextProps,
822 font_hash_map: &mut alloc::collections::BTreeMap<u64, azul_css::props::basic::font::StyleFontFamilyVec>,
823) {
824 macro_rules! set_tier1 {
825 ($v:expr, $shift:expr, $mask:expr, $encoder:ident) => {
826 if let Some(exact) = $v.get_property() {
827 let encoded = $encoder(*exact) as u64;
828 let shifted_mask = $mask << $shift;
829 *tier1 = (*tier1 & !shifted_mask) | ((encoded & $mask) << $shift);
830 }
831 };
832 }
833
834 match prop {
835 CssProperty::Display(v) => set_tier1!(v, DISPLAY_SHIFT, DISPLAY_MASK, layout_display_to_u8),
837 CssProperty::Position(v) => set_tier1!(v, POSITION_SHIFT, POSITION_MASK, layout_position_to_u8),
838 CssProperty::Float(v) => set_tier1!(v, FLOAT_SHIFT, FLOAT_MASK, layout_float_to_u8),
839 CssProperty::OverflowX(v) => set_tier1!(v, OVERFLOW_X_SHIFT, OVERFLOW_MASK, layout_overflow_to_u8),
840 CssProperty::OverflowY(v) => set_tier1!(v, OVERFLOW_Y_SHIFT, OVERFLOW_MASK, layout_overflow_to_u8),
841 CssProperty::BoxSizing(v) => set_tier1!(v, BOX_SIZING_SHIFT, BOX_SIZING_MASK, layout_box_sizing_to_u8),
842 CssProperty::FlexDirection(v) => set_tier1!(v, FLEX_DIRECTION_SHIFT, FLEX_DIR_MASK, layout_flex_direction_to_u8),
843 CssProperty::FlexWrap(v) => set_tier1!(v, FLEX_WRAP_SHIFT, FLEX_WRAP_MASK, layout_flex_wrap_to_u8),
844 CssProperty::JustifyContent(v) => set_tier1!(v, JUSTIFY_CONTENT_SHIFT, JUSTIFY_MASK, layout_justify_content_to_u8),
845 CssProperty::AlignItems(v) => set_tier1!(v, ALIGN_ITEMS_SHIFT, ALIGN_MASK, layout_align_items_to_u8),
846 CssProperty::AlignContent(v) => set_tier1!(v, ALIGN_CONTENT_SHIFT, ALIGN_MASK, layout_align_content_to_u8),
847 CssProperty::WritingMode(v) => set_tier1!(v, WRITING_MODE_SHIFT, WRITING_MODE_MASK, layout_writing_mode_to_u8),
848 CssProperty::Clear(v) => set_tier1!(v, CLEAR_SHIFT, CLEAR_MASK, layout_clear_to_u8),
849 CssProperty::FontWeight(v) => set_tier1!(v, FONT_WEIGHT_SHIFT, FONT_WEIGHT_MASK, style_font_weight_to_u8),
850 CssProperty::FontStyle(v) => set_tier1!(v, FONT_STYLE_SHIFT, FONT_STYLE_MASK, style_font_style_to_u8),
851 CssProperty::TextAlign(v) => set_tier1!(v, TEXT_ALIGN_SHIFT, TEXT_ALIGN_MASK, style_text_align_to_u8),
852 CssProperty::Visibility(v) => set_tier1!(v, VISIBILITY_SHIFT, VISIBILITY_MASK, style_visibility_to_u8),
853 CssProperty::WhiteSpace(v) => set_tier1!(v, WHITE_SPACE_SHIFT, WHITE_SPACE_MASK, style_white_space_to_u8),
854 CssProperty::Direction(v) => set_tier1!(v, DIRECTION_SHIFT, DIRECTION_MASK, style_direction_to_u8),
855 CssProperty::VerticalAlign(v) => set_tier1!(v, VERTICAL_ALIGN_SHIFT, VERTICAL_ALIGN_MASK, style_vertical_align_to_u8),
856 CssProperty::BorderCollapse(v) => set_tier1!(v, BORDER_COLLAPSE_SHIFT, BORDER_COLLAPSE_MASK, border_collapse_to_u8),
857 CssProperty::AlignSelf(v) => set_tier1!(v, ALIGN_SELF_SHIFT, ALIGN_SELF_MASK, layout_align_self_to_u8),
858 CssProperty::JustifySelf(v) => set_tier1!(v, JUSTIFY_SELF_SHIFT, JUSTIFY_SELF_MASK, layout_justify_self_to_u8),
859 CssProperty::GridAutoFlow(v) => set_tier1!(v, GRID_AUTO_FLOW_SHIFT, GRID_AUTO_FLOW_MASK, layout_grid_auto_flow_to_u8),
860 CssProperty::JustifyItems(v) => set_tier1!(v, JUSTIFY_ITEMS_SHIFT, JUSTIFY_ITEMS_MASK, layout_justify_items_to_u8),
861
862 CssProperty::Width(v) => { dims.width = encode_layout_width(v); }
864 CssProperty::Height(v) => { dims.height = encode_layout_height(v); }
865 CssProperty::MinWidth(v) => { dims.min_width = encode_pixel_prop(v); }
866 CssProperty::MaxWidth(v) => { dims.max_width = encode_pixel_prop(v); }
867 CssProperty::MinHeight(v) => { dims.min_height = encode_pixel_prop(v); }
868 CssProperty::MaxHeight(v) => { dims.max_height = encode_pixel_prop(v); }
869 CssProperty::FlexBasis(v) => { dims.flex_basis = encode_flex_basis(v); }
870 CssProperty::FontSize(v) => { dims.font_size = encode_pixel_prop(v); }
871 CssProperty::PaddingTop(v) => { dims.padding_top = encode_css_pixel_as_i16(v); }
872 CssProperty::PaddingRight(v) => { dims.padding_right = encode_css_pixel_as_i16(v); }
873 CssProperty::PaddingBottom(v) => { dims.padding_bottom = encode_css_pixel_as_i16(v); }
874 CssProperty::PaddingLeft(v) => { dims.padding_left = encode_css_pixel_as_i16(v); }
875 CssProperty::MarginTop(v) => { dims.margin_top = encode_margin_i16(v); }
876 CssProperty::MarginRight(v) => { dims.margin_right = encode_margin_i16(v); }
877 CssProperty::MarginBottom(v) => { dims.margin_bottom = encode_margin_i16(v); }
878 CssProperty::MarginLeft(v) => { dims.margin_left = encode_margin_i16(v); }
879 CssProperty::BorderTopWidth(v) => { dims.border_top_width = encode_css_pixel_as_i16(v); }
880 CssProperty::BorderRightWidth(v) => { dims.border_right_width = encode_css_pixel_as_i16(v); }
881 CssProperty::BorderBottomWidth(v) => { dims.border_bottom_width = encode_css_pixel_as_i16(v); }
882 CssProperty::BorderLeftWidth(v) => { dims.border_left_width = encode_css_pixel_as_i16(v); }
883 CssProperty::Top(v) => { dims.top = encode_css_pixel_as_i16(v); }
884 CssProperty::Right(v) => { dims.right = encode_css_pixel_as_i16(v); }
885 CssProperty::Bottom(v) => { dims.bottom = encode_css_pixel_as_i16(v); }
886 CssProperty::Left(v) => { dims.left = encode_css_pixel_as_i16(v); }
887 CssProperty::FlexGrow(v) => {
888 if let Some(exact) = v.get_property() {
889 dims.flex_grow = encode_flex_u16(exact.inner.get());
890 }
891 }
892 CssProperty::FlexShrink(v) => {
893 if let Some(exact) = v.get_property() {
894 dims.flex_shrink = encode_flex_u16(exact.inner.get());
895 }
896 }
897
898 CssProperty::RowGap(v) => {
899 if let Some(g) = v.get_property() {
900 if g.inner.metric == SizeMetric::Px {
901 dims.row_gap = encode_resolved_px_i16(g.inner.number.get());
902 }
903 }
904 }
905 CssProperty::ColumnGap(v) => {
906 if let Some(g) = v.get_property() {
907 if g.inner.metric == SizeMetric::Px {
908 dims.column_gap = encode_resolved_px_i16(g.inner.number.get());
909 }
910 }
911 }
912 CssProperty::Gap(v) => {
913 if let Some(g) = v.get_property() {
914 if g.inner.metric == SizeMetric::Px {
915 let enc = encode_resolved_px_i16(g.inner.number.get());
916 dims.row_gap = enc;
917 dims.column_gap = enc;
918 }
919 }
920 }
921
922 CssProperty::GridColumn(v) => {
924 if let Some(gp) = v.get_property() {
925 cold.grid_col_start = encode_grid_line(&gp.grid_start);
926 cold.grid_col_end = encode_grid_line(&gp.grid_end);
927 }
928 }
929 CssProperty::GridRow(v) => {
930 if let Some(gp) = v.get_property() {
931 cold.grid_row_start = encode_grid_line(&gp.grid_start);
932 cold.grid_row_end = encode_grid_line(&gp.grid_end);
933 }
934 }
935
936 CssProperty::ZIndex(v) => {
938 if let Some(exact) = v.get_property() {
939 match exact {
940 LayoutZIndex::Auto => cold.z_index = I16_AUTO,
941 LayoutZIndex::Integer(z) => {
942 cold.z_index = if *z >= I16_SENTINEL_THRESHOLD as i32 { I16_SENTINEL } else { *z as i16 };
943 }
944 }
945 }
946 }
947 CssProperty::BorderTopStyle(v) => {
948 if let Some(exact) = v.get_property() {
949 let bs = border_style_to_u8(exact.inner) as u16;
950 cold.border_styles_packed = (cold.border_styles_packed & !0x000F) | bs;
951 }
952 }
953 CssProperty::BorderRightStyle(v) => {
954 if let Some(exact) = v.get_property() {
955 let bs = border_style_to_u8(exact.inner) as u16;
956 cold.border_styles_packed = (cold.border_styles_packed & !0x00F0) | (bs << 4);
957 }
958 }
959 CssProperty::BorderBottomStyle(v) => {
960 if let Some(exact) = v.get_property() {
961 let bs = border_style_to_u8(exact.inner) as u16;
962 cold.border_styles_packed = (cold.border_styles_packed & !0x0F00) | (bs << 8);
963 }
964 }
965 CssProperty::BorderLeftStyle(v) => {
966 if let Some(exact) = v.get_property() {
967 let bs = border_style_to_u8(exact.inner) as u16;
968 cold.border_styles_packed = (cold.border_styles_packed & !0xF000) | (bs << 12);
969 }
970 }
971 CssProperty::BorderTopColor(v) => {
972 if let Some(c) = v.get_property() { cold.border_top_color = encode_color_u32(&c.inner); }
973 }
974 CssProperty::BorderRightColor(v) => {
975 if let Some(c) = v.get_property() { cold.border_right_color = encode_color_u32(&c.inner); }
976 }
977 CssProperty::BorderBottomColor(v) => {
978 if let Some(c) = v.get_property() { cold.border_bottom_color = encode_color_u32(&c.inner); }
979 }
980 CssProperty::BorderLeftColor(v) => {
981 if let Some(c) = v.get_property() { cold.border_left_color = encode_color_u32(&c.inner); }
982 }
983 CssProperty::BorderSpacing(v) => {
984 if let Some(spacing) = v.get_property() {
985 if spacing.horizontal.metric == SizeMetric::Px {
986 cold.border_spacing_h = encode_resolved_px_i16(spacing.horizontal.number.get());
987 }
988 if spacing.vertical.metric == SizeMetric::Px {
989 cold.border_spacing_v = encode_resolved_px_i16(spacing.vertical.number.get());
990 }
991 }
992 }
993 CssProperty::TabSize(v) => { cold.tab_size = encode_css_pixel_as_i16(v); }
994
995 CssProperty::TextColor(v) => {
997 if let Some(color) = v.get_property() {
998 let c = &color.inner;
999 text.text_color = ((c.r as u32) << 24) | ((c.g as u32) << 16) | ((c.b as u32) << 8) | (c.a as u32);
1000 }
1001 }
1002 CssProperty::FontFamily(v) => {
1003 if let Some(families) = v.get_property() {
1004 let mut hasher = DefaultHasher::new();
1005 families.hash(&mut hasher);
1006 let h = hasher.finish();
1007 let h = if h == 0 { 1 } else { h };
1008 text.font_family_hash = h;
1009 font_hash_map.insert(h, families.clone());
1010 }
1011 }
1012 CssProperty::LineHeight(v) => {
1013 if let Some(lh) = v.get_property() {
1014 let pct_x10 = (lh.inner.normalized() * 1000.0).round() as i32;
1015 if pct_x10 >= -32768 && pct_x10 < I16_SENTINEL_THRESHOLD as i32 {
1016 text.line_height = pct_x10 as i16;
1017 } else {
1018 text.line_height = I16_SENTINEL;
1019 }
1020 }
1021 }
1022 CssProperty::LetterSpacing(v) => { text.letter_spacing = encode_css_pixel_as_i16(v); }
1023 CssProperty::WordSpacing(v) => { text.word_spacing = encode_css_pixel_as_i16(v); }
1024 CssProperty::TextIndent(v) => { text.text_indent = encode_css_pixel_as_i16(v); }
1025
1026 CssProperty::BorderTopLeftRadius(v) => {
1028 if let Some(exact) = v.get_property() {
1029 if exact.inner.metric == SizeMetric::Px {
1030 cold.border_top_left_radius = encode_resolved_px_i16(exact.inner.number.get());
1031 }
1032 }
1033 }
1034 CssProperty::BorderTopRightRadius(v) => {
1035 if let Some(exact) = v.get_property() {
1036 if exact.inner.metric == SizeMetric::Px {
1037 cold.border_top_right_radius = encode_resolved_px_i16(exact.inner.number.get());
1038 }
1039 }
1040 }
1041 CssProperty::BorderBottomLeftRadius(v) => {
1042 if let Some(exact) = v.get_property() {
1043 if exact.inner.metric == SizeMetric::Px {
1044 cold.border_bottom_left_radius = encode_resolved_px_i16(exact.inner.number.get());
1045 }
1046 }
1047 }
1048 CssProperty::BorderBottomRightRadius(v) => {
1049 if let Some(exact) = v.get_property() {
1050 if exact.inner.metric == SizeMetric::Px {
1051 cold.border_bottom_right_radius = encode_resolved_px_i16(exact.inner.number.get());
1052 }
1053 }
1054 }
1055
1056 CssProperty::Opacity(v) => {
1058 if let Some(exact) = v.get_property() {
1059 let o = exact.inner.normalized().clamp(0.0, 1.0);
1060 let byte = (o * 254.0).round() as u8;
1061 cold.opacity = byte;
1063 }
1064 }
1065
1066 CssProperty::Transform(v) => {
1069 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_TRANSFORM; }
1070 }
1071 CssProperty::TransformOrigin(v) => {
1072 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_TRANSFORM_ORIGIN; }
1073 }
1074 CssProperty::BoxShadowTop(v) => {
1075 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_BOX_SHADOW; }
1076 }
1077 CssProperty::BoxShadowBottom(v) => {
1078 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_BOX_SHADOW; }
1079 }
1080 CssProperty::BoxShadowLeft(v) => {
1081 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_BOX_SHADOW; }
1082 }
1083 CssProperty::BoxShadowRight(v) => {
1084 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_BOX_SHADOW; }
1085 }
1086 CssProperty::TextDecoration(v) => {
1087 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_TEXT_DECORATION; }
1088 }
1089 CssProperty::ScrollbarGutter(v) => {
1090 if let Some(exact) = v.get_property() {
1091 use azul_css::props::layout::overflow::StyleScrollbarGutter;
1092 let bits: u8 = match exact {
1093 StyleScrollbarGutter::Auto => SCROLLBAR_GUTTER_AUTO,
1094 StyleScrollbarGutter::Stable => SCROLLBAR_GUTTER_STABLE,
1095 StyleScrollbarGutter::StableBothEdges => SCROLLBAR_GUTTER_BOTH_EDGES,
1096 };
1097 cold.hot_flags = (cold.hot_flags & !HOT_FLAG_SCROLLBAR_GUTTER_MASK)
1098 | ((bits << HOT_FLAG_SCROLLBAR_GUTTER_SHIFT) & HOT_FLAG_SCROLLBAR_GUTTER_MASK);
1099 }
1100 }
1101 CssProperty::BackgroundContent(v) => {
1102 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_BACKGROUND; }
1103 }
1104 CssProperty::ClipPath(v) => {
1105 if v.get_property().is_some() { cold.hot_flags |= HOT_FLAG_HAS_CLIP_PATH; }
1106 }
1107
1108 CssProperty::ScrollbarTrack(v) => {
1112 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1113 }
1114 CssProperty::ScrollbarThumb(v) => {
1115 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1116 }
1117 CssProperty::ScrollbarButton(v) => {
1118 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1119 }
1120 CssProperty::ScrollbarCorner(v) => {
1121 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1122 }
1123 CssProperty::ScrollbarWidth(v) => {
1124 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1125 }
1126 CssProperty::ScrollbarColor(v) => {
1127 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1128 }
1129 CssProperty::ScrollbarVisibility(v) => {
1130 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1131 }
1132 CssProperty::ScrollbarFadeDelay(v) => {
1133 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1134 }
1135 CssProperty::ScrollbarFadeDuration(v) => {
1136 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_SCROLLBAR_CSS; }
1137 }
1138
1139 CssProperty::CounterReset(v) => {
1141 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_COUNTER; }
1142 }
1143 CssProperty::CounterIncrement(v) => {
1144 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_COUNTER; }
1145 }
1146 CssProperty::BreakBefore(v) => {
1147 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_BREAK; }
1148 }
1149 CssProperty::BreakAfter(v) => {
1150 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_BREAK; }
1151 }
1152 CssProperty::TextOrientation(v) => {
1153 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_TEXT_ORIENTATION; }
1154 }
1155 CssProperty::TextShadow(v) => {
1156 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_TEXT_SHADOW; }
1157 }
1158 CssProperty::BackdropFilter(v) => {
1159 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_BACKDROP_FILTER; }
1160 }
1161 CssProperty::Filter(v) => {
1162 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_FILTER; }
1163 }
1164 CssProperty::MixBlendMode(v) => {
1165 if v.get_property().is_some() { cold.extra_flags |= EXTRA_FLAG_HAS_MIX_BLEND_MODE; }
1166 }
1167
1168 _ => {}
1170 }
1171}
1172
1173fn update_dom_declared_flags(prop: &CssProperty, flags: &mut u32) {
1178 match prop {
1182 CssProperty::ShapeInside(v) => if v.get_property().is_some() { *flags |= DOM_HAS_SHAPE_INSIDE; }
1183 CssProperty::ShapeOutside(v) => if v.get_property().is_some() { *flags |= DOM_HAS_SHAPE_OUTSIDE; }
1184 CssProperty::TextJustify(v) => if v.get_property().is_some() { *flags |= DOM_HAS_TEXT_JUSTIFY; }
1185 CssProperty::TextIndent(v) => if v.get_property().is_some() { *flags |= DOM_HAS_TEXT_INDENT; }
1186 CssProperty::ColumnCount(v) => if v.get_property().is_some() { *flags |= DOM_HAS_COLUMN_COUNT; }
1187 CssProperty::ColumnGap(v) => if v.get_property().is_some() { *flags |= DOM_HAS_COLUMN_GAP; }
1188 CssProperty::ColumnWidth(v) => if v.get_property().is_some() { *flags |= DOM_HAS_COLUMN_WIDTH; }
1189 CssProperty::InitialLetter(v) => if v.get_property().is_some() { *flags |= DOM_HAS_INITIAL_LETTER; }
1190 CssProperty::InitialLetterAlign(v) => if v.get_property().is_some() { *flags |= DOM_HAS_INITIAL_LETTER_ALIGN; }
1191 CssProperty::LineClamp(v) => if v.get_property().is_some() { *flags |= DOM_HAS_LINE_CLAMP; }
1192 CssProperty::HangingPunctuation(v) => if v.get_property().is_some() { *flags |= DOM_HAS_HANGING_PUNCTUATION; }
1193 CssProperty::TextCombineUpright(v) => if v.get_property().is_some() { *flags |= DOM_HAS_TEXT_COMBINE_UPRIGHT; }
1194 CssProperty::ExclusionMargin(v) => if v.get_property().is_some() { *flags |= DOM_HAS_EXCLUSION_MARGIN; }
1195 CssProperty::ShapeMargin(v) => if v.get_property().is_some() { *flags |= DOM_HAS_SHAPE_MARGIN; }
1196 CssProperty::HyphenationLanguage(v) => if v.get_property().is_some() { *flags |= DOM_HAS_HYPHENATION_LANGUAGE; }
1197 CssProperty::UnicodeBidi(v) => if v.get_property().is_some() { *flags |= DOM_HAS_UNICODE_BIDI; }
1198 CssProperty::TextBoxTrim(v) => if v.get_property().is_some() { *flags |= DOM_HAS_TEXT_BOX_TRIM; }
1199 CssProperty::Hyphens(v) => if v.get_property().is_some() { *flags |= DOM_HAS_HYPHENS; }
1200 CssProperty::WordBreak(v) => if v.get_property().is_some() { *flags |= DOM_HAS_WORD_BREAK; }
1201 CssProperty::OverflowWrap(v) => if v.get_property().is_some() { *flags |= DOM_HAS_OVERFLOW_WRAP; }
1202 CssProperty::LineBreak(v) => if v.get_property().is_some() { *flags |= DOM_HAS_LINE_BREAK; }
1203 CssProperty::TextAlignLast(v) => if v.get_property().is_some() { *flags |= DOM_HAS_TEXT_ALIGN_LAST; }
1204 CssProperty::LineHeight(v) => if v.get_property().is_some() { *flags |= DOM_HAS_LINE_HEIGHT; }
1205 _ => {}
1206 }
1207}
1208
1209fn encode_grid_line(line: &azul_css::props::layout::grid::GridLine) -> i16 {
1216 use azul_css::props::layout::grid::GridLine;
1217 match line {
1218 GridLine::Auto => I16_AUTO,
1219 GridLine::Line(n) => {
1220 if *n >= -32000 && *n <= 32000 { *n as i16 } else { I16_SENTINEL }
1221 }
1222 GridLine::Span(n) => {
1223 if *n >= 1 && *n <= 32000 { -(*n as i16) } else { I16_SENTINEL }
1224 }
1225 GridLine::Named(_) => I16_SENTINEL,
1226 }
1227}
1228
1229fn encode_layout_width<T: LayoutWidthLike>(val: &CssPropertyValue<T>) -> u32 {
1231 match val {
1232 CssPropertyValue::Exact(w) => w.encode_compact_u32(),
1233 CssPropertyValue::Auto => U32_AUTO,
1234 CssPropertyValue::Initial => U32_INITIAL,
1235 CssPropertyValue::Inherit => U32_INHERIT,
1236 CssPropertyValue::None => U32_NONE,
1237 _ => U32_SENTINEL,
1238 }
1239}
1240
1241fn encode_layout_height<T: LayoutWidthLike>(val: &CssPropertyValue<T>) -> u32 {
1243 encode_layout_width(val)
1244}
1245
1246trait LayoutWidthLike {
1249 fn encode_compact_u32(&self) -> u32;
1250}
1251
1252impl LayoutWidthLike for LayoutWidth {
1253 fn encode_compact_u32(&self) -> u32 {
1254 match self {
1255 LayoutWidth::Auto => U32_AUTO,
1256 LayoutWidth::Px(pv) => encode_pixel_value_u32(pv),
1257 LayoutWidth::MinContent => U32_MIN_CONTENT,
1258 LayoutWidth::MaxContent => U32_MAX_CONTENT,
1259 LayoutWidth::FitContent(_) => U32_SENTINEL,
1260 LayoutWidth::Calc(_) => U32_SENTINEL, }
1262 }
1263}
1264
1265impl LayoutWidthLike for LayoutHeight {
1266 fn encode_compact_u32(&self) -> u32 {
1267 match self {
1268 LayoutHeight::Auto => U32_AUTO,
1269 LayoutHeight::Px(pv) => encode_pixel_value_u32(pv),
1270 LayoutHeight::MinContent => U32_MIN_CONTENT,
1271 LayoutHeight::MaxContent => U32_MAX_CONTENT,
1272 LayoutHeight::FitContent(_) => U32_SENTINEL,
1273 LayoutHeight::Calc(_) => U32_SENTINEL,
1274 }
1275 }
1276}
1277
1278fn encode_pixel_prop<T: HasInnerPixelValue>(val: &CssPropertyValue<T>) -> u32 {
1280 match val {
1281 CssPropertyValue::Exact(inner) => encode_pixel_value_u32(&inner.get_inner_pixel()),
1282 CssPropertyValue::Auto => U32_AUTO,
1283 CssPropertyValue::Initial => U32_INITIAL,
1284 CssPropertyValue::Inherit => U32_INHERIT,
1285 CssPropertyValue::None => U32_NONE,
1286 _ => U32_SENTINEL,
1287 }
1288}
1289
1290trait HasInnerPixelValue {
1292 fn get_inner_pixel(&self) -> azul_css::props::basic::pixel::PixelValue;
1293}
1294
1295macro_rules! impl_has_inner_pixel {
1296 ($($ty:ty),*) => {
1297 $(
1298 impl HasInnerPixelValue for $ty {
1299 fn get_inner_pixel(&self) -> azul_css::props::basic::pixel::PixelValue {
1300 self.inner
1301 }
1302 }
1303 )*
1304 };
1305}
1306
1307impl_has_inner_pixel!(
1308 azul_css::props::layout::dimensions::LayoutMinWidth,
1309 azul_css::props::layout::dimensions::LayoutMaxWidth,
1310 azul_css::props::layout::dimensions::LayoutMinHeight,
1311 azul_css::props::layout::dimensions::LayoutMaxHeight,
1312 azul_css::props::basic::font::StyleFontSize,
1313 azul_css::props::layout::spacing::LayoutPaddingTop,
1314 azul_css::props::layout::spacing::LayoutPaddingRight,
1315 azul_css::props::layout::spacing::LayoutPaddingBottom,
1316 azul_css::props::layout::spacing::LayoutPaddingLeft,
1317 azul_css::props::layout::spacing::LayoutMarginTop,
1318 azul_css::props::layout::spacing::LayoutMarginRight,
1319 azul_css::props::layout::spacing::LayoutMarginBottom,
1320 azul_css::props::layout::spacing::LayoutMarginLeft,
1321 azul_css::props::style::border::LayoutBorderTopWidth,
1322 azul_css::props::style::border::LayoutBorderRightWidth,
1323 azul_css::props::style::border::LayoutBorderBottomWidth,
1324 azul_css::props::style::border::LayoutBorderLeftWidth,
1325 azul_css::props::layout::position::LayoutTop,
1326 azul_css::props::layout::position::LayoutRight,
1327 azul_css::props::layout::position::LayoutInsetBottom,
1328 azul_css::props::layout::position::LayoutLeft,
1329 azul_css::props::style::text::StyleLetterSpacing,
1330 azul_css::props::style::text::StyleWordSpacing,
1331 azul_css::props::style::text::StyleTextIndent,
1332 azul_css::props::style::text::StyleTabSize
1333);
1334
1335fn encode_css_pixel_as_i16<T: HasInnerPixelValue>(val: &CssPropertyValue<T>) -> i16 {
1338 let mapped = match val {
1339 CssPropertyValue::Exact(inner) => CssPropertyValue::Exact(inner.get_inner_pixel()),
1340 CssPropertyValue::Auto => CssPropertyValue::Auto,
1341 CssPropertyValue::Initial => CssPropertyValue::Initial,
1342 CssPropertyValue::Inherit => CssPropertyValue::Inherit,
1343 CssPropertyValue::None => CssPropertyValue::None,
1344 _ => return I16_SENTINEL,
1345 };
1346 azul_css::compact_cache::encode_css_pixel_as_i16(&mapped)
1347}
1348
1349fn encode_margin_i16<T: HasInnerPixelValue>(val: &CssPropertyValue<T>) -> i16 {
1351 encode_css_pixel_as_i16(val)
1352}
1353
1354fn encode_flex_basis(val: &CssPropertyValue<LayoutFlexBasis>) -> u32 {
1356 match val {
1357 CssPropertyValue::Exact(fb) => match fb {
1358 LayoutFlexBasis::Auto => U32_AUTO,
1359 LayoutFlexBasis::Exact(pv) => encode_pixel_value_u32(pv),
1360 },
1361 CssPropertyValue::Auto => U32_AUTO,
1362 CssPropertyValue::Initial => U32_INITIAL,
1363 CssPropertyValue::Inherit => U32_INHERIT,
1364 CssPropertyValue::None => U32_NONE,
1365 _ => U32_SENTINEL,
1366 }
1367}