1use crate::props::basic::length::{FloatValue, SizeMetric};
12use crate::props::basic::pixel::PixelValue;
13use crate::props::layout::{
14 display::LayoutDisplay,
15 dimensions::{LayoutHeight, LayoutWidth, LayoutMaxHeight, LayoutMaxWidth, LayoutMinHeight, LayoutMinWidth},
16 flex::{
17 LayoutAlignContent, LayoutAlignItems, LayoutFlexDirection, LayoutFlexWrap,
18 LayoutJustifyContent,
19 },
20 overflow::LayoutOverflow,
21 position::LayoutPosition,
22 wrapping::{LayoutClear, LayoutWritingMode},
23 table::StyleBorderCollapse,
24};
25use crate::props::layout::display::LayoutFloat;
26use crate::props::layout::dimensions::LayoutBoxSizing;
27use crate::props::basic::font::{StyleFontStyle, StyleFontWeight};
28use crate::props::basic::color::ColorU;
29use crate::props::style::{StyleTextAlign, StyleVerticalAlign, StyleVisibility, StyleWhiteSpace, StyleDirection};
30use crate::props::style::border::BorderStyle;
31use crate::props::property::{CssProperty, CssPropertyType};
32use crate::css::CssPropertyValue;
33use alloc::boxed::Box;
34use alloc::collections::BTreeMap;
35use alloc::vec::Vec;
36
37pub const U16_SENTINEL: u16 = 0xFFFF;
43pub const U16_AUTO: u16 = 0xFFFE;
44pub const U16_NONE: u16 = 0xFFFD;
45pub const U16_INHERIT: u16 = 0xFFFC;
46pub const U16_INITIAL: u16 = 0xFFFB;
47pub const U16_MIN_CONTENT: u16 = 0xFFFA;
48pub const U16_MAX_CONTENT: u16 = 0xFFF9;
49pub const U16_SENTINEL_THRESHOLD: u16 = 0xFFF9;
51
52pub const I16_SENTINEL: i16 = 0x7FFF; pub const I16_AUTO: i16 = 0x7FFE; pub const I16_INHERIT: i16 = 0x7FFD; pub const I16_INITIAL: i16 = 0x7FFC; pub const I16_SENTINEL_THRESHOLD: i16 = 0x7FFC; pub const U32_SENTINEL: u32 = 0xFFFFFFFF;
62pub const U32_AUTO: u32 = 0xFFFFFFFE;
63pub const U32_NONE: u32 = 0xFFFFFFFD;
64pub const U32_INHERIT: u32 = 0xFFFFFFFC;
65pub const U32_INITIAL: u32 = 0xFFFFFFFB;
66pub const U32_MIN_CONTENT: u32 = 0xFFFFFFFA;
67pub const U32_MAX_CONTENT: u32 = 0xFFFFFFF9;
68pub const U32_SENTINEL_THRESHOLD: u32 = 0xFFFFFFF9;
70
71const DISPLAY_SHIFT: u32 = 0;
101const POSITION_SHIFT: u32 = 5;
102const FLOAT_SHIFT: u32 = 8;
103const OVERFLOW_X_SHIFT: u32 = 10;
104const OVERFLOW_Y_SHIFT: u32 = 13;
105const BOX_SIZING_SHIFT: u32 = 16;
106const FLEX_DIRECTION_SHIFT: u32 = 17;
107const FLEX_WRAP_SHIFT: u32 = 19;
108const JUSTIFY_CONTENT_SHIFT: u32 = 21;
109const ALIGN_ITEMS_SHIFT: u32 = 24;
110const ALIGN_CONTENT_SHIFT: u32 = 27;
111const WRITING_MODE_SHIFT: u32 = 30;
112const CLEAR_SHIFT: u32 = 32;
113const FONT_WEIGHT_SHIFT: u32 = 34;
114const FONT_STYLE_SHIFT: u32 = 38;
115const TEXT_ALIGN_SHIFT: u32 = 40;
116const VISIBILITY_SHIFT: u32 = 43;
117const WHITE_SPACE_SHIFT: u32 = 45;
118const DIRECTION_SHIFT: u32 = 48;
119const VERTICAL_ALIGN_SHIFT: u32 = 49;
120const BORDER_COLLAPSE_SHIFT: u32 = 52;
121
122const DISPLAY_MASK: u64 = 0x1F; const POSITION_MASK: u64 = 0x07; const FLOAT_MASK: u64 = 0x03; const OVERFLOW_MASK: u64 = 0x07; const BOX_SIZING_MASK: u64 = 0x01; const FLEX_DIR_MASK: u64 = 0x03; const FLEX_WRAP_MASK: u64 = 0x03; const JUSTIFY_MASK: u64 = 0x07; const ALIGN_MASK: u64 = 0x07; const WRITING_MODE_MASK: u64 = 0x03;const CLEAR_MASK: u64 = 0x03; const FONT_WEIGHT_MASK: u64 = 0x0F; const FONT_STYLE_MASK: u64 = 0x03; const TEXT_ALIGN_MASK: u64 = 0x07; const VISIBILITY_MASK: u64 = 0x03; const WHITE_SPACE_MASK: u64 = 0x07; const DIRECTION_MASK: u64 = 0x01; const VERTICAL_ALIGN_MASK: u64 = 0x07; const BORDER_COLLAPSE_MASK: u64 = 0x01; const TIER1_POPULATED_BIT: u64 = 1 << 63;
149
150#[inline(always)]
156pub fn layout_display_from_u8(v: u8) -> LayoutDisplay {
157 match v {
158 0 => LayoutDisplay::None,
159 1 => LayoutDisplay::Block,
160 2 => LayoutDisplay::Inline,
161 3 => LayoutDisplay::InlineBlock,
162 4 => LayoutDisplay::Flex,
163 5 => LayoutDisplay::InlineFlex,
164 6 => LayoutDisplay::Table,
165 7 => LayoutDisplay::InlineTable,
166 8 => LayoutDisplay::TableRowGroup,
167 9 => LayoutDisplay::TableHeaderGroup,
168 10 => LayoutDisplay::TableFooterGroup,
169 11 => LayoutDisplay::TableRow,
170 12 => LayoutDisplay::TableColumnGroup,
171 13 => LayoutDisplay::TableColumn,
172 14 => LayoutDisplay::TableCell,
173 15 => LayoutDisplay::TableCaption,
174 16 => LayoutDisplay::FlowRoot,
175 17 => LayoutDisplay::ListItem,
176 18 => LayoutDisplay::RunIn,
177 19 => LayoutDisplay::Marker,
178 20 => LayoutDisplay::Grid,
179 21 => LayoutDisplay::InlineGrid,
180 _ => LayoutDisplay::Block, }
182}
183
184#[inline(always)]
186pub fn layout_display_to_u8(v: LayoutDisplay) -> u8 {
187 match v {
188 LayoutDisplay::None => 0,
189 LayoutDisplay::Block => 1,
190 LayoutDisplay::Inline => 2,
191 LayoutDisplay::InlineBlock => 3,
192 LayoutDisplay::Flex => 4,
193 LayoutDisplay::InlineFlex => 5,
194 LayoutDisplay::Table => 6,
195 LayoutDisplay::InlineTable => 7,
196 LayoutDisplay::TableRowGroup => 8,
197 LayoutDisplay::TableHeaderGroup => 9,
198 LayoutDisplay::TableFooterGroup => 10,
199 LayoutDisplay::TableRow => 11,
200 LayoutDisplay::TableColumnGroup => 12,
201 LayoutDisplay::TableColumn => 13,
202 LayoutDisplay::TableCell => 14,
203 LayoutDisplay::TableCaption => 15,
204 LayoutDisplay::FlowRoot => 16,
205 LayoutDisplay::ListItem => 17,
206 LayoutDisplay::RunIn => 18,
207 LayoutDisplay::Marker => 19,
208 LayoutDisplay::Grid => 20,
209 LayoutDisplay::InlineGrid => 21,
210 }
211}
212
213#[inline(always)]
214pub fn layout_position_from_u8(v: u8) -> LayoutPosition {
215 match v {
216 0 => LayoutPosition::Static,
217 1 => LayoutPosition::Relative,
218 2 => LayoutPosition::Absolute,
219 3 => LayoutPosition::Fixed,
220 4 => LayoutPosition::Sticky,
221 _ => LayoutPosition::Static,
222 }
223}
224
225#[inline(always)]
226pub fn layout_position_to_u8(v: LayoutPosition) -> u8 {
227 match v {
228 LayoutPosition::Static => 0,
229 LayoutPosition::Relative => 1,
230 LayoutPosition::Absolute => 2,
231 LayoutPosition::Fixed => 3,
232 LayoutPosition::Sticky => 4,
233 }
234}
235
236#[inline(always)]
237pub fn layout_float_from_u8(v: u8) -> LayoutFloat {
238 match v {
239 0 => LayoutFloat::Left,
240 1 => LayoutFloat::Right,
241 2 => LayoutFloat::None,
242 _ => LayoutFloat::None,
243 }
244}
245
246#[inline(always)]
247pub fn layout_float_to_u8(v: LayoutFloat) -> u8 {
248 match v {
249 LayoutFloat::Left => 0,
250 LayoutFloat::Right => 1,
251 LayoutFloat::None => 2,
252 }
253}
254
255#[inline(always)]
256pub fn layout_overflow_from_u8(v: u8) -> LayoutOverflow {
257 match v {
258 0 => LayoutOverflow::Scroll,
259 1 => LayoutOverflow::Auto,
260 2 => LayoutOverflow::Hidden,
261 3 => LayoutOverflow::Visible,
262 4 => LayoutOverflow::Clip,
263 _ => LayoutOverflow::Visible,
264 }
265}
266
267#[inline(always)]
268pub fn layout_overflow_to_u8(v: LayoutOverflow) -> u8 {
269 match v {
270 LayoutOverflow::Scroll => 0,
271 LayoutOverflow::Auto => 1,
272 LayoutOverflow::Hidden => 2,
273 LayoutOverflow::Visible => 3,
274 LayoutOverflow::Clip => 4,
275 }
276}
277
278#[inline(always)]
279pub fn layout_box_sizing_from_u8(v: u8) -> LayoutBoxSizing {
280 match v {
281 0 => LayoutBoxSizing::ContentBox,
282 1 => LayoutBoxSizing::BorderBox,
283 _ => LayoutBoxSizing::ContentBox,
284 }
285}
286
287#[inline(always)]
288pub fn layout_box_sizing_to_u8(v: LayoutBoxSizing) -> u8 {
289 match v {
290 LayoutBoxSizing::ContentBox => 0,
291 LayoutBoxSizing::BorderBox => 1,
292 }
293}
294
295#[inline(always)]
296pub fn layout_flex_direction_from_u8(v: u8) -> LayoutFlexDirection {
297 match v {
298 0 => LayoutFlexDirection::Row,
299 1 => LayoutFlexDirection::RowReverse,
300 2 => LayoutFlexDirection::Column,
301 3 => LayoutFlexDirection::ColumnReverse,
302 _ => LayoutFlexDirection::Row,
303 }
304}
305
306#[inline(always)]
307pub fn layout_flex_direction_to_u8(v: LayoutFlexDirection) -> u8 {
308 match v {
309 LayoutFlexDirection::Row => 0,
310 LayoutFlexDirection::RowReverse => 1,
311 LayoutFlexDirection::Column => 2,
312 LayoutFlexDirection::ColumnReverse => 3,
313 }
314}
315
316#[inline(always)]
317pub fn layout_flex_wrap_from_u8(v: u8) -> LayoutFlexWrap {
318 match v {
319 0 => LayoutFlexWrap::Wrap,
320 1 => LayoutFlexWrap::NoWrap,
321 2 => LayoutFlexWrap::WrapReverse,
322 _ => LayoutFlexWrap::NoWrap,
323 }
324}
325
326#[inline(always)]
327pub fn layout_flex_wrap_to_u8(v: LayoutFlexWrap) -> u8 {
328 match v {
329 LayoutFlexWrap::Wrap => 0,
330 LayoutFlexWrap::NoWrap => 1,
331 LayoutFlexWrap::WrapReverse => 2,
332 }
333}
334
335#[inline(always)]
336pub fn layout_justify_content_from_u8(v: u8) -> LayoutJustifyContent {
337 match v {
338 0 => LayoutJustifyContent::FlexStart,
339 1 => LayoutJustifyContent::FlexEnd,
340 2 => LayoutJustifyContent::Start,
341 3 => LayoutJustifyContent::End,
342 4 => LayoutJustifyContent::Center,
343 5 => LayoutJustifyContent::SpaceBetween,
344 6 => LayoutJustifyContent::SpaceAround,
345 7 => LayoutJustifyContent::SpaceEvenly,
346 _ => LayoutJustifyContent::FlexStart,
347 }
348}
349
350#[inline(always)]
351pub fn layout_justify_content_to_u8(v: LayoutJustifyContent) -> u8 {
352 match v {
353 LayoutJustifyContent::FlexStart => 0,
354 LayoutJustifyContent::FlexEnd => 1,
355 LayoutJustifyContent::Start => 2,
356 LayoutJustifyContent::End => 3,
357 LayoutJustifyContent::Center => 4,
358 LayoutJustifyContent::SpaceBetween => 5,
359 LayoutJustifyContent::SpaceAround => 6,
360 LayoutJustifyContent::SpaceEvenly => 7,
361 }
362}
363
364#[inline(always)]
365pub fn layout_align_items_from_u8(v: u8) -> LayoutAlignItems {
366 match v {
367 0 => LayoutAlignItems::Stretch,
368 1 => LayoutAlignItems::Center,
369 2 => LayoutAlignItems::Start,
370 3 => LayoutAlignItems::End,
371 4 => LayoutAlignItems::Baseline,
372 _ => LayoutAlignItems::Stretch,
373 }
374}
375
376#[inline(always)]
377pub fn layout_align_items_to_u8(v: LayoutAlignItems) -> u8 {
378 match v {
379 LayoutAlignItems::Stretch => 0,
380 LayoutAlignItems::Center => 1,
381 LayoutAlignItems::Start => 2,
382 LayoutAlignItems::End => 3,
383 LayoutAlignItems::Baseline => 4,
384 }
385}
386
387#[inline(always)]
388pub fn layout_align_content_from_u8(v: u8) -> LayoutAlignContent {
389 match v {
390 0 => LayoutAlignContent::Stretch,
391 1 => LayoutAlignContent::Center,
392 2 => LayoutAlignContent::Start,
393 3 => LayoutAlignContent::End,
394 4 => LayoutAlignContent::SpaceBetween,
395 5 => LayoutAlignContent::SpaceAround,
396 _ => LayoutAlignContent::Stretch,
397 }
398}
399
400#[inline(always)]
401pub fn layout_align_content_to_u8(v: LayoutAlignContent) -> u8 {
402 match v {
403 LayoutAlignContent::Stretch => 0,
404 LayoutAlignContent::Center => 1,
405 LayoutAlignContent::Start => 2,
406 LayoutAlignContent::End => 3,
407 LayoutAlignContent::SpaceBetween => 4,
408 LayoutAlignContent::SpaceAround => 5,
409 }
410}
411
412#[inline(always)]
413pub fn layout_writing_mode_from_u8(v: u8) -> LayoutWritingMode {
414 match v {
415 0 => LayoutWritingMode::HorizontalTb,
416 1 => LayoutWritingMode::VerticalRl,
417 2 => LayoutWritingMode::VerticalLr,
418 _ => LayoutWritingMode::HorizontalTb,
419 }
420}
421
422#[inline(always)]
423pub fn layout_writing_mode_to_u8(v: LayoutWritingMode) -> u8 {
424 match v {
425 LayoutWritingMode::HorizontalTb => 0,
426 LayoutWritingMode::VerticalRl => 1,
427 LayoutWritingMode::VerticalLr => 2,
428 }
429}
430
431#[inline(always)]
432pub fn layout_clear_from_u8(v: u8) -> LayoutClear {
433 match v {
434 0 => LayoutClear::None,
435 1 => LayoutClear::Left,
436 2 => LayoutClear::Right,
437 3 => LayoutClear::Both,
438 _ => LayoutClear::None,
439 }
440}
441
442#[inline(always)]
443pub fn layout_clear_to_u8(v: LayoutClear) -> u8 {
444 match v {
445 LayoutClear::None => 0,
446 LayoutClear::Left => 1,
447 LayoutClear::Right => 2,
448 LayoutClear::Both => 3,
449 }
450}
451
452#[inline(always)]
453pub fn style_font_weight_from_u8(v: u8) -> StyleFontWeight {
454 match v {
455 0 => StyleFontWeight::Lighter,
456 1 => StyleFontWeight::W100,
457 2 => StyleFontWeight::W200,
458 3 => StyleFontWeight::W300,
459 4 => StyleFontWeight::Normal,
460 5 => StyleFontWeight::W500,
461 6 => StyleFontWeight::W600,
462 7 => StyleFontWeight::Bold,
463 8 => StyleFontWeight::W800,
464 9 => StyleFontWeight::W900,
465 10 => StyleFontWeight::Bolder,
466 _ => StyleFontWeight::Normal,
467 }
468}
469
470#[inline(always)]
471pub fn style_font_weight_to_u8(v: StyleFontWeight) -> u8 {
472 match v {
473 StyleFontWeight::Lighter => 0,
474 StyleFontWeight::W100 => 1,
475 StyleFontWeight::W200 => 2,
476 StyleFontWeight::W300 => 3,
477 StyleFontWeight::Normal => 4,
478 StyleFontWeight::W500 => 5,
479 StyleFontWeight::W600 => 6,
480 StyleFontWeight::Bold => 7,
481 StyleFontWeight::W800 => 8,
482 StyleFontWeight::W900 => 9,
483 StyleFontWeight::Bolder => 10,
484 }
485}
486
487#[inline(always)]
488pub fn style_font_style_from_u8(v: u8) -> StyleFontStyle {
489 match v {
490 0 => StyleFontStyle::Normal,
491 1 => StyleFontStyle::Italic,
492 2 => StyleFontStyle::Oblique,
493 _ => StyleFontStyle::Normal,
494 }
495}
496
497#[inline(always)]
498pub fn style_font_style_to_u8(v: StyleFontStyle) -> u8 {
499 match v {
500 StyleFontStyle::Normal => 0,
501 StyleFontStyle::Italic => 1,
502 StyleFontStyle::Oblique => 2,
503 }
504}
505
506#[inline(always)]
507pub fn style_text_align_from_u8(v: u8) -> StyleTextAlign {
508 match v {
509 0 => StyleTextAlign::Left,
510 1 => StyleTextAlign::Center,
511 2 => StyleTextAlign::Right,
512 3 => StyleTextAlign::Justify,
513 4 => StyleTextAlign::Start,
514 5 => StyleTextAlign::End,
515 _ => StyleTextAlign::Left,
516 }
517}
518
519#[inline(always)]
520pub fn style_text_align_to_u8(v: StyleTextAlign) -> u8 {
521 match v {
522 StyleTextAlign::Left => 0,
523 StyleTextAlign::Center => 1,
524 StyleTextAlign::Right => 2,
525 StyleTextAlign::Justify => 3,
526 StyleTextAlign::Start => 4,
527 StyleTextAlign::End => 5,
528 }
529}
530
531#[inline(always)]
532pub fn style_visibility_from_u8(v: u8) -> StyleVisibility {
533 match v {
534 0 => StyleVisibility::Visible,
535 1 => StyleVisibility::Hidden,
536 2 => StyleVisibility::Collapse,
537 _ => StyleVisibility::Visible,
538 }
539}
540
541#[inline(always)]
542pub fn style_visibility_to_u8(v: StyleVisibility) -> u8 {
543 match v {
544 StyleVisibility::Visible => 0,
545 StyleVisibility::Hidden => 1,
546 StyleVisibility::Collapse => 2,
547 }
548}
549
550#[inline(always)]
551pub fn style_white_space_from_u8(v: u8) -> StyleWhiteSpace {
552 match v {
553 0 => StyleWhiteSpace::Normal,
554 1 => StyleWhiteSpace::Pre,
555 2 => StyleWhiteSpace::Nowrap,
556 3 => StyleWhiteSpace::PreWrap,
557 4 => StyleWhiteSpace::PreLine,
558 5 => StyleWhiteSpace::BreakSpaces,
559 _ => StyleWhiteSpace::Normal,
560 }
561}
562
563#[inline(always)]
564pub fn style_white_space_to_u8(v: StyleWhiteSpace) -> u8 {
565 match v {
566 StyleWhiteSpace::Normal => 0,
567 StyleWhiteSpace::Pre => 1,
568 StyleWhiteSpace::Nowrap => 2,
569 StyleWhiteSpace::PreWrap => 3,
570 StyleWhiteSpace::PreLine => 4,
571 StyleWhiteSpace::BreakSpaces => 5,
572 }
573}
574
575#[inline(always)]
576pub fn style_direction_from_u8(v: u8) -> StyleDirection {
577 match v {
578 0 => StyleDirection::Ltr,
579 1 => StyleDirection::Rtl,
580 _ => StyleDirection::Ltr,
581 }
582}
583
584#[inline(always)]
585pub fn style_direction_to_u8(v: StyleDirection) -> u8 {
586 match v {
587 StyleDirection::Ltr => 0,
588 StyleDirection::Rtl => 1,
589 }
590}
591
592#[inline(always)]
593pub fn style_vertical_align_from_u8(v: u8) -> StyleVerticalAlign {
594 match v {
595 0 => StyleVerticalAlign::Baseline,
596 1 => StyleVerticalAlign::Top,
597 2 => StyleVerticalAlign::Middle,
598 3 => StyleVerticalAlign::Bottom,
599 4 => StyleVerticalAlign::Sub,
600 5 => StyleVerticalAlign::Superscript,
601 6 => StyleVerticalAlign::TextTop,
602 7 => StyleVerticalAlign::TextBottom,
603 _ => StyleVerticalAlign::Baseline,
604 }
605}
606
607#[inline(always)]
608pub fn style_vertical_align_to_u8(v: StyleVerticalAlign) -> u8 {
609 match v {
610 StyleVerticalAlign::Baseline => 0,
611 StyleVerticalAlign::Top => 1,
612 StyleVerticalAlign::Middle => 2,
613 StyleVerticalAlign::Bottom => 3,
614 StyleVerticalAlign::Sub => 4,
615 StyleVerticalAlign::Superscript => 5,
616 StyleVerticalAlign::TextTop => 6,
617 StyleVerticalAlign::TextBottom => 7,
618 }
619}
620
621#[inline(always)]
622pub fn border_collapse_from_u8(v: u8) -> StyleBorderCollapse {
623 match v {
624 0 => StyleBorderCollapse::Separate,
625 1 => StyleBorderCollapse::Collapse,
626 _ => StyleBorderCollapse::Separate,
627 }
628}
629
630#[inline(always)]
631pub fn border_collapse_to_u8(v: StyleBorderCollapse) -> u8 {
632 match v {
633 StyleBorderCollapse::Separate => 0,
634 StyleBorderCollapse::Collapse => 1,
635 }
636}
637
638#[inline(always)]
639pub fn border_style_from_u8(v: u8) -> BorderStyle {
640 match v {
641 0 => BorderStyle::None,
642 1 => BorderStyle::Solid,
643 2 => BorderStyle::Double,
644 3 => BorderStyle::Dotted,
645 4 => BorderStyle::Dashed,
646 5 => BorderStyle::Hidden,
647 6 => BorderStyle::Groove,
648 7 => BorderStyle::Ridge,
649 8 => BorderStyle::Inset,
650 9 => BorderStyle::Outset,
651 _ => BorderStyle::None,
652 }
653}
654
655#[inline(always)]
656pub fn border_style_to_u8(v: BorderStyle) -> u8 {
657 match v {
658 BorderStyle::None => 0,
659 BorderStyle::Solid => 1,
660 BorderStyle::Double => 2,
661 BorderStyle::Dotted => 3,
662 BorderStyle::Dashed => 4,
663 BorderStyle::Hidden => 5,
664 BorderStyle::Groove => 6,
665 BorderStyle::Ridge => 7,
666 BorderStyle::Inset => 8,
667 BorderStyle::Outset => 9,
668 }
669}
670
671#[inline]
673pub fn encode_border_styles_packed(top: BorderStyle, right: BorderStyle, bottom: BorderStyle, left: BorderStyle) -> u16 {
674 (border_style_to_u8(top) as u16)
675 | ((border_style_to_u8(right) as u16) << 4)
676 | ((border_style_to_u8(bottom) as u16) << 8)
677 | ((border_style_to_u8(left) as u16) << 12)
678}
679
680#[inline(always)]
682pub fn decode_border_top_style(packed: u16) -> BorderStyle {
683 border_style_from_u8((packed & 0x0F) as u8)
684}
685
686#[inline(always)]
688pub fn decode_border_right_style(packed: u16) -> BorderStyle {
689 border_style_from_u8(((packed >> 4) & 0x0F) as u8)
690}
691
692#[inline(always)]
694pub fn decode_border_bottom_style(packed: u16) -> BorderStyle {
695 border_style_from_u8(((packed >> 8) & 0x0F) as u8)
696}
697
698#[inline(always)]
700pub fn decode_border_left_style(packed: u16) -> BorderStyle {
701 border_style_from_u8(((packed >> 12) & 0x0F) as u8)
702}
703
704#[inline(always)]
706pub fn encode_color_u32(c: &ColorU) -> u32 {
707 ((c.r as u32) << 24) | ((c.g as u32) << 16) | ((c.b as u32) << 8) | (c.a as u32)
708}
709
710#[inline(always)]
712pub fn decode_color_u32(v: u32) -> Option<ColorU> {
713 if v == 0 { return None; }
714 Some(ColorU {
715 r: ((v >> 24) & 0xFF) as u8,
716 g: ((v >> 16) & 0xFF) as u8,
717 b: ((v >> 8) & 0xFF) as u8,
718 a: (v & 0xFF) as u8,
719 })
720}
721
722#[inline]
728pub fn encode_tier1(
729 display: LayoutDisplay,
730 position: LayoutPosition,
731 float: LayoutFloat,
732 overflow_x: LayoutOverflow,
733 overflow_y: LayoutOverflow,
734 box_sizing: LayoutBoxSizing,
735 flex_direction: LayoutFlexDirection,
736 flex_wrap: LayoutFlexWrap,
737 justify_content: LayoutJustifyContent,
738 align_items: LayoutAlignItems,
739 align_content: LayoutAlignContent,
740 writing_mode: LayoutWritingMode,
741 clear: LayoutClear,
742 font_weight: StyleFontWeight,
743 font_style: StyleFontStyle,
744 text_align: StyleTextAlign,
745 visibility: StyleVisibility,
746 white_space: StyleWhiteSpace,
747 direction: StyleDirection,
748 vertical_align: StyleVerticalAlign,
749 border_collapse: StyleBorderCollapse,
750) -> u64 {
751 let mut v: u64 = TIER1_POPULATED_BIT;
752 v |= (layout_display_to_u8(display) as u64) << DISPLAY_SHIFT;
753 v |= (layout_position_to_u8(position) as u64) << POSITION_SHIFT;
754 v |= (layout_float_to_u8(float) as u64) << FLOAT_SHIFT;
755 v |= (layout_overflow_to_u8(overflow_x) as u64) << OVERFLOW_X_SHIFT;
756 v |= (layout_overflow_to_u8(overflow_y) as u64) << OVERFLOW_Y_SHIFT;
757 v |= (layout_box_sizing_to_u8(box_sizing) as u64) << BOX_SIZING_SHIFT;
758 v |= (layout_flex_direction_to_u8(flex_direction) as u64) << FLEX_DIRECTION_SHIFT;
759 v |= (layout_flex_wrap_to_u8(flex_wrap) as u64) << FLEX_WRAP_SHIFT;
760 v |= (layout_justify_content_to_u8(justify_content) as u64) << JUSTIFY_CONTENT_SHIFT;
761 v |= (layout_align_items_to_u8(align_items) as u64) << ALIGN_ITEMS_SHIFT;
762 v |= (layout_align_content_to_u8(align_content) as u64) << ALIGN_CONTENT_SHIFT;
763 v |= (layout_writing_mode_to_u8(writing_mode) as u64) << WRITING_MODE_SHIFT;
764 v |= (layout_clear_to_u8(clear) as u64) << CLEAR_SHIFT;
765 v |= (style_font_weight_to_u8(font_weight) as u64) << FONT_WEIGHT_SHIFT;
766 v |= (style_font_style_to_u8(font_style) as u64) << FONT_STYLE_SHIFT;
767 v |= (style_text_align_to_u8(text_align) as u64) << TEXT_ALIGN_SHIFT;
768 v |= (style_visibility_to_u8(visibility) as u64) << VISIBILITY_SHIFT;
769 v |= (style_white_space_to_u8(white_space) as u64) << WHITE_SPACE_SHIFT;
770 v |= (style_direction_to_u8(direction) as u64) << DIRECTION_SHIFT;
771 v |= (style_vertical_align_to_u8(vertical_align) as u64) << VERTICAL_ALIGN_SHIFT;
772 v |= (border_collapse_to_u8(border_collapse) as u64) << BORDER_COLLAPSE_SHIFT;
773 v
774}
775
776#[inline(always)]
780pub fn decode_display(t1: u64) -> LayoutDisplay {
781 layout_display_from_u8(((t1 >> DISPLAY_SHIFT) & DISPLAY_MASK) as u8)
782}
783
784#[inline(always)]
785pub fn decode_position(t1: u64) -> LayoutPosition {
786 layout_position_from_u8(((t1 >> POSITION_SHIFT) & POSITION_MASK) as u8)
787}
788
789#[inline(always)]
790pub fn decode_float(t1: u64) -> LayoutFloat {
791 layout_float_from_u8(((t1 >> FLOAT_SHIFT) & FLOAT_MASK) as u8)
792}
793
794#[inline(always)]
795pub fn decode_overflow_x(t1: u64) -> LayoutOverflow {
796 layout_overflow_from_u8(((t1 >> OVERFLOW_X_SHIFT) & OVERFLOW_MASK) as u8)
797}
798
799#[inline(always)]
800pub fn decode_overflow_y(t1: u64) -> LayoutOverflow {
801 layout_overflow_from_u8(((t1 >> OVERFLOW_Y_SHIFT) & OVERFLOW_MASK) as u8)
802}
803
804#[inline(always)]
805pub fn decode_box_sizing(t1: u64) -> LayoutBoxSizing {
806 layout_box_sizing_from_u8(((t1 >> BOX_SIZING_SHIFT) & BOX_SIZING_MASK) as u8)
807}
808
809#[inline(always)]
810pub fn decode_flex_direction(t1: u64) -> LayoutFlexDirection {
811 layout_flex_direction_from_u8(((t1 >> FLEX_DIRECTION_SHIFT) & FLEX_DIR_MASK) as u8)
812}
813
814#[inline(always)]
815pub fn decode_flex_wrap(t1: u64) -> LayoutFlexWrap {
816 layout_flex_wrap_from_u8(((t1 >> FLEX_WRAP_SHIFT) & FLEX_WRAP_MASK) as u8)
817}
818
819#[inline(always)]
820pub fn decode_justify_content(t1: u64) -> LayoutJustifyContent {
821 layout_justify_content_from_u8(((t1 >> JUSTIFY_CONTENT_SHIFT) & JUSTIFY_MASK) as u8)
822}
823
824#[inline(always)]
825pub fn decode_align_items(t1: u64) -> LayoutAlignItems {
826 layout_align_items_from_u8(((t1 >> ALIGN_ITEMS_SHIFT) & ALIGN_MASK) as u8)
827}
828
829#[inline(always)]
830pub fn decode_align_content(t1: u64) -> LayoutAlignContent {
831 layout_align_content_from_u8(((t1 >> ALIGN_CONTENT_SHIFT) & ALIGN_MASK) as u8)
832}
833
834#[inline(always)]
835pub fn decode_writing_mode(t1: u64) -> LayoutWritingMode {
836 layout_writing_mode_from_u8(((t1 >> WRITING_MODE_SHIFT) & WRITING_MODE_MASK) as u8)
837}
838
839#[inline(always)]
840pub fn decode_clear(t1: u64) -> LayoutClear {
841 layout_clear_from_u8(((t1 >> CLEAR_SHIFT) & CLEAR_MASK) as u8)
842}
843
844#[inline(always)]
845pub fn decode_font_weight(t1: u64) -> StyleFontWeight {
846 style_font_weight_from_u8(((t1 >> FONT_WEIGHT_SHIFT) & FONT_WEIGHT_MASK) as u8)
847}
848
849#[inline(always)]
850pub fn decode_font_style(t1: u64) -> StyleFontStyle {
851 style_font_style_from_u8(((t1 >> FONT_STYLE_SHIFT) & FONT_STYLE_MASK) as u8)
852}
853
854#[inline(always)]
855pub fn decode_text_align(t1: u64) -> StyleTextAlign {
856 style_text_align_from_u8(((t1 >> TEXT_ALIGN_SHIFT) & TEXT_ALIGN_MASK) as u8)
857}
858
859#[inline(always)]
860pub fn decode_visibility(t1: u64) -> StyleVisibility {
861 style_visibility_from_u8(((t1 >> VISIBILITY_SHIFT) & VISIBILITY_MASK) as u8)
862}
863
864#[inline(always)]
865pub fn decode_white_space(t1: u64) -> StyleWhiteSpace {
866 style_white_space_from_u8(((t1 >> WHITE_SPACE_SHIFT) & WHITE_SPACE_MASK) as u8)
867}
868
869#[inline(always)]
870pub fn decode_direction(t1: u64) -> StyleDirection {
871 style_direction_from_u8(((t1 >> DIRECTION_SHIFT) & DIRECTION_MASK) as u8)
872}
873
874#[inline(always)]
875pub fn decode_vertical_align(t1: u64) -> StyleVerticalAlign {
876 style_vertical_align_from_u8(((t1 >> VERTICAL_ALIGN_SHIFT) & VERTICAL_ALIGN_MASK) as u8)
877}
878
879#[inline(always)]
880pub fn decode_border_collapse(t1: u64) -> StyleBorderCollapse {
881 border_collapse_from_u8(((t1 >> BORDER_COLLAPSE_SHIFT) & BORDER_COLLAPSE_MASK) as u8)
882}
883
884#[inline(always)]
886pub fn tier1_is_populated(t1: u64) -> bool {
887 (t1 & TIER1_POPULATED_BIT) != 0
888}
889
890#[inline]
905pub fn encode_pixel_value_u32(pv: &PixelValue) -> u32 {
906 let metric = size_metric_to_u8(pv.metric) as u32;
907 let raw = pv.number.number; if raw < -134_217_728 || raw > 134_217_727 {
910 return U32_SENTINEL; }
912 let value_bits = ((raw as i32) as u32) << 4;
914 value_bits | metric
915}
916
917#[inline]
919pub fn decode_pixel_value_u32(encoded: u32) -> Option<PixelValue> {
920 if encoded >= U32_SENTINEL_THRESHOLD {
921 return None; }
923 let metric = size_metric_from_u8((encoded & 0xF) as u8);
924 let value_bits = (encoded as i32) >> 4;
926 let raw = value_bits as isize; Some(PixelValue {
928 metric,
929 number: FloatValue { number: raw },
930 })
931}
932
933#[inline]
936pub fn encode_resolved_px_i16(px: f32) -> i16 {
937 let scaled = (px * 10.0).round() as i32;
938 if scaled < -32768 || scaled > I16_SENTINEL_THRESHOLD as i32 - 1 {
939 return I16_SENTINEL; }
941 scaled as i16
942}
943
944#[inline(always)]
946pub fn decode_resolved_px_i16(v: i16) -> Option<f32> {
947 if v >= I16_SENTINEL_THRESHOLD {
948 return None;
949 }
950 Some(v as f32 / 10.0)
951}
952
953#[inline]
956pub fn encode_flex_u16(value: f32) -> u16 {
957 let scaled = (value * 100.0).round() as i32;
958 if scaled < 0 || scaled >= U16_SENTINEL_THRESHOLD as i32 {
959 return U16_SENTINEL;
960 }
961 scaled as u16
962}
963
964#[inline(always)]
966pub fn decode_flex_u16(v: u16) -> Option<f32> {
967 if v >= U16_SENTINEL_THRESHOLD {
968 return None;
969 }
970 Some(v as f32 / 100.0)
971}
972
973#[inline(always)]
975pub fn size_metric_to_u8(m: SizeMetric) -> u8 {
976 match m {
977 SizeMetric::Px => 0,
978 SizeMetric::Pt => 1,
979 SizeMetric::Em => 2,
980 SizeMetric::Rem => 3,
981 SizeMetric::In => 4,
982 SizeMetric::Cm => 5,
983 SizeMetric::Mm => 6,
984 SizeMetric::Percent => 7,
985 SizeMetric::Vw => 8,
986 SizeMetric::Vh => 9,
987 SizeMetric::Vmin => 10,
988 SizeMetric::Vmax => 11,
989 }
990}
991
992#[inline(always)]
994pub fn size_metric_from_u8(v: u8) -> SizeMetric {
995 match v {
996 0 => SizeMetric::Px,
997 1 => SizeMetric::Pt,
998 2 => SizeMetric::Em,
999 3 => SizeMetric::Rem,
1000 4 => SizeMetric::In,
1001 5 => SizeMetric::Cm,
1002 6 => SizeMetric::Mm,
1003 7 => SizeMetric::Percent,
1004 8 => SizeMetric::Vw,
1005 9 => SizeMetric::Vh,
1006 10 => SizeMetric::Vmin,
1007 11 => SizeMetric::Vmax,
1008 _ => SizeMetric::Px,
1009 }
1010}
1011
1012#[derive(Debug, Copy, Clone, PartialEq)]
1015#[repr(C)]
1016pub struct CompactNodeProps {
1017 pub width: u32,
1019 pub height: u32,
1020 pub min_width: u32,
1021 pub max_width: u32,
1022 pub min_height: u32,
1023 pub max_height: u32,
1024 pub flex_basis: u32,
1025 pub font_size: u32,
1026
1027 pub border_top_color: u32,
1029 pub border_right_color: u32,
1030 pub border_bottom_color: u32,
1031 pub border_left_color: u32,
1032
1033 pub padding_top: i16,
1035 pub padding_right: i16,
1036 pub padding_bottom: i16,
1037 pub padding_left: i16,
1038 pub margin_top: i16,
1039 pub margin_right: i16,
1040 pub margin_bottom: i16,
1041 pub margin_left: i16,
1042 pub border_top_width: i16,
1043 pub border_right_width: i16,
1044 pub border_bottom_width: i16,
1045 pub border_left_width: i16,
1046 pub top: i16,
1047 pub right: i16,
1048 pub bottom: i16,
1049 pub left: i16,
1050 pub border_spacing_h: i16,
1051 pub border_spacing_v: i16,
1052 pub tab_size: i16,
1053
1054 pub flex_grow: u16,
1056 pub flex_shrink: u16,
1057
1058 pub z_index: i16, pub border_styles_packed: u16,
1062 pub _pad: [u8; 2],
1063}
1064
1065impl Default for CompactNodeProps {
1066 fn default() -> Self {
1067 Self {
1068 width: U32_AUTO,
1070 height: U32_AUTO,
1071 min_width: U32_AUTO,
1072 max_width: U32_NONE,
1073 min_height: U32_AUTO,
1074 max_height: U32_NONE,
1075 flex_basis: U32_AUTO,
1076 font_size: U32_INITIAL,
1077 border_top_color: 0,
1079 border_right_color: 0,
1080 border_bottom_color: 0,
1081 border_left_color: 0,
1082 padding_top: 0,
1084 padding_right: 0,
1085 padding_bottom: 0,
1086 padding_left: 0,
1087 margin_top: 0,
1088 margin_right: 0,
1089 margin_bottom: 0,
1090 margin_left: 0,
1091 border_top_width: 0,
1092 border_right_width: 0,
1093 border_bottom_width: 0,
1094 border_left_width: 0,
1095 top: I16_AUTO,
1096 right: I16_AUTO,
1097 bottom: I16_AUTO,
1098 left: I16_AUTO,
1099 border_spacing_h: 0,
1100 border_spacing_v: 0,
1101 tab_size: I16_SENTINEL, flex_grow: 0,
1104 flex_shrink: encode_flex_u16(1.0), z_index: I16_AUTO,
1107 border_styles_packed: 0, _pad: [0; 2],
1109 }
1110 }
1111}
1112
1113#[derive(Debug, Copy, Clone, PartialEq)]
1119#[repr(C)]
1120pub struct CompactTextProps {
1121 pub text_color: u32, pub font_family_hash: u64, pub line_height: i16, pub letter_spacing: i16, pub word_spacing: i16, pub text_indent: i16, }
1128
1129impl Default for CompactTextProps {
1130 fn default() -> Self {
1131 Self {
1132 text_color: 0,
1133 font_family_hash: 0,
1134 line_height: I16_SENTINEL, letter_spacing: 0,
1136 word_spacing: 0,
1137 text_indent: 0,
1138 }
1139 }
1140}
1141
1142pub type CompactOverflowProps = BTreeMap<CssPropertyType, CssProperty>;
1152
1153#[derive(Debug, Clone, PartialEq)]
1162pub struct CompactLayoutCache {
1163 pub tier1_enums: Vec<u64>,
1165 pub tier2_dims: Vec<CompactNodeProps>,
1167 pub tier2b_text: Vec<CompactTextProps>,
1169 pub tier3_overflow: Vec<Option<Box<CompactOverflowProps>>>,
1171}
1172
1173impl CompactLayoutCache {
1174 pub fn empty() -> Self {
1176 Self {
1177 tier1_enums: Vec::new(),
1178 tier2_dims: Vec::new(),
1179 tier2b_text: Vec::new(),
1180 tier3_overflow: Vec::new(),
1181 }
1182 }
1183
1184 pub fn with_capacity(node_count: usize) -> Self {
1186 Self {
1187 tier1_enums: vec![0u64; node_count],
1188 tier2_dims: vec![CompactNodeProps::default(); node_count],
1189 tier2b_text: vec![CompactTextProps::default(); node_count],
1190 tier3_overflow: vec![None; node_count],
1191 }
1192 }
1193
1194 #[inline]
1196 pub fn node_count(&self) -> usize {
1197 self.tier1_enums.len()
1198 }
1199
1200 #[inline(always)]
1203 pub fn get_display(&self, node_idx: usize) -> LayoutDisplay {
1204 decode_display(self.tier1_enums[node_idx])
1205 }
1206
1207 #[inline(always)]
1208 pub fn get_position(&self, node_idx: usize) -> LayoutPosition {
1209 decode_position(self.tier1_enums[node_idx])
1210 }
1211
1212 #[inline(always)]
1213 pub fn get_float(&self, node_idx: usize) -> LayoutFloat {
1214 decode_float(self.tier1_enums[node_idx])
1215 }
1216
1217 #[inline(always)]
1218 pub fn get_overflow_x(&self, node_idx: usize) -> LayoutOverflow {
1219 decode_overflow_x(self.tier1_enums[node_idx])
1220 }
1221
1222 #[inline(always)]
1223 pub fn get_overflow_y(&self, node_idx: usize) -> LayoutOverflow {
1224 decode_overflow_y(self.tier1_enums[node_idx])
1225 }
1226
1227 #[inline(always)]
1228 pub fn get_box_sizing(&self, node_idx: usize) -> LayoutBoxSizing {
1229 decode_box_sizing(self.tier1_enums[node_idx])
1230 }
1231
1232 #[inline(always)]
1233 pub fn get_flex_direction(&self, node_idx: usize) -> LayoutFlexDirection {
1234 decode_flex_direction(self.tier1_enums[node_idx])
1235 }
1236
1237 #[inline(always)]
1238 pub fn get_flex_wrap(&self, node_idx: usize) -> LayoutFlexWrap {
1239 decode_flex_wrap(self.tier1_enums[node_idx])
1240 }
1241
1242 #[inline(always)]
1243 pub fn get_justify_content(&self, node_idx: usize) -> LayoutJustifyContent {
1244 decode_justify_content(self.tier1_enums[node_idx])
1245 }
1246
1247 #[inline(always)]
1248 pub fn get_align_items(&self, node_idx: usize) -> LayoutAlignItems {
1249 decode_align_items(self.tier1_enums[node_idx])
1250 }
1251
1252 #[inline(always)]
1253 pub fn get_align_content(&self, node_idx: usize) -> LayoutAlignContent {
1254 decode_align_content(self.tier1_enums[node_idx])
1255 }
1256
1257 #[inline(always)]
1258 pub fn get_writing_mode(&self, node_idx: usize) -> LayoutWritingMode {
1259 decode_writing_mode(self.tier1_enums[node_idx])
1260 }
1261
1262 #[inline(always)]
1263 pub fn get_clear(&self, node_idx: usize) -> LayoutClear {
1264 decode_clear(self.tier1_enums[node_idx])
1265 }
1266
1267 #[inline(always)]
1268 pub fn get_font_weight(&self, node_idx: usize) -> StyleFontWeight {
1269 decode_font_weight(self.tier1_enums[node_idx])
1270 }
1271
1272 #[inline(always)]
1273 pub fn get_font_style(&self, node_idx: usize) -> StyleFontStyle {
1274 decode_font_style(self.tier1_enums[node_idx])
1275 }
1276
1277 #[inline(always)]
1278 pub fn get_text_align(&self, node_idx: usize) -> StyleTextAlign {
1279 decode_text_align(self.tier1_enums[node_idx])
1280 }
1281
1282 #[inline(always)]
1283 pub fn get_visibility(&self, node_idx: usize) -> StyleVisibility {
1284 decode_visibility(self.tier1_enums[node_idx])
1285 }
1286
1287 #[inline(always)]
1288 pub fn get_white_space(&self, node_idx: usize) -> StyleWhiteSpace {
1289 decode_white_space(self.tier1_enums[node_idx])
1290 }
1291
1292 #[inline(always)]
1293 pub fn get_direction(&self, node_idx: usize) -> StyleDirection {
1294 decode_direction(self.tier1_enums[node_idx])
1295 }
1296
1297 #[inline(always)]
1298 pub fn get_vertical_align(&self, node_idx: usize) -> StyleVerticalAlign {
1299 decode_vertical_align(self.tier1_enums[node_idx])
1300 }
1301
1302 #[inline(always)]
1303 pub fn get_border_collapse(&self, node_idx: usize) -> StyleBorderCollapse {
1304 decode_border_collapse(self.tier1_enums[node_idx])
1305 }
1306
1307 #[inline(always)]
1311 pub fn get_width_raw(&self, node_idx: usize) -> u32 {
1312 self.tier2_dims[node_idx].width
1313 }
1314
1315 #[inline(always)]
1316 pub fn get_height_raw(&self, node_idx: usize) -> u32 {
1317 self.tier2_dims[node_idx].height
1318 }
1319
1320 #[inline(always)]
1321 pub fn get_min_width_raw(&self, node_idx: usize) -> u32 {
1322 self.tier2_dims[node_idx].min_width
1323 }
1324
1325 #[inline(always)]
1326 pub fn get_max_width_raw(&self, node_idx: usize) -> u32 {
1327 self.tier2_dims[node_idx].max_width
1328 }
1329
1330 #[inline(always)]
1331 pub fn get_min_height_raw(&self, node_idx: usize) -> u32 {
1332 self.tier2_dims[node_idx].min_height
1333 }
1334
1335 #[inline(always)]
1336 pub fn get_max_height_raw(&self, node_idx: usize) -> u32 {
1337 self.tier2_dims[node_idx].max_height
1338 }
1339
1340 #[inline(always)]
1341 pub fn get_font_size_raw(&self, node_idx: usize) -> u32 {
1342 self.tier2_dims[node_idx].font_size
1343 }
1344
1345 #[inline(always)]
1346 pub fn get_flex_basis_raw(&self, node_idx: usize) -> u32 {
1347 self.tier2_dims[node_idx].flex_basis
1348 }
1349
1350 #[inline(always)]
1352 pub fn get_padding_top(&self, node_idx: usize) -> Option<f32> {
1353 decode_resolved_px_i16(self.tier2_dims[node_idx].padding_top)
1354 }
1355
1356 #[inline(always)]
1357 pub fn get_padding_right(&self, node_idx: usize) -> Option<f32> {
1358 decode_resolved_px_i16(self.tier2_dims[node_idx].padding_right)
1359 }
1360
1361 #[inline(always)]
1362 pub fn get_padding_bottom(&self, node_idx: usize) -> Option<f32> {
1363 decode_resolved_px_i16(self.tier2_dims[node_idx].padding_bottom)
1364 }
1365
1366 #[inline(always)]
1367 pub fn get_padding_left(&self, node_idx: usize) -> Option<f32> {
1368 decode_resolved_px_i16(self.tier2_dims[node_idx].padding_left)
1369 }
1370
1371 #[inline(always)]
1372 pub fn get_margin_top(&self, node_idx: usize) -> Option<f32> {
1373 let v = self.tier2_dims[node_idx].margin_top;
1374 if v == I16_AUTO { return None; } decode_resolved_px_i16(v)
1376 }
1377
1378 #[inline(always)]
1379 pub fn get_margin_right(&self, node_idx: usize) -> Option<f32> {
1380 let v = self.tier2_dims[node_idx].margin_right;
1381 if v == I16_AUTO { return None; }
1382 decode_resolved_px_i16(v)
1383 }
1384
1385 #[inline(always)]
1386 pub fn get_margin_bottom(&self, node_idx: usize) -> Option<f32> {
1387 let v = self.tier2_dims[node_idx].margin_bottom;
1388 if v == I16_AUTO { return None; }
1389 decode_resolved_px_i16(v)
1390 }
1391
1392 #[inline(always)]
1393 pub fn get_margin_left(&self, node_idx: usize) -> Option<f32> {
1394 let v = self.tier2_dims[node_idx].margin_left;
1395 if v == I16_AUTO { return None; }
1396 decode_resolved_px_i16(v)
1397 }
1398
1399 #[inline(always)]
1401 pub fn is_margin_top_auto(&self, node_idx: usize) -> bool {
1402 self.tier2_dims[node_idx].margin_top == I16_AUTO
1403 }
1404
1405 #[inline(always)]
1406 pub fn is_margin_right_auto(&self, node_idx: usize) -> bool {
1407 self.tier2_dims[node_idx].margin_right == I16_AUTO
1408 }
1409
1410 #[inline(always)]
1411 pub fn is_margin_bottom_auto(&self, node_idx: usize) -> bool {
1412 self.tier2_dims[node_idx].margin_bottom == I16_AUTO
1413 }
1414
1415 #[inline(always)]
1416 pub fn is_margin_left_auto(&self, node_idx: usize) -> bool {
1417 self.tier2_dims[node_idx].margin_left == I16_AUTO
1418 }
1419
1420 #[inline(always)]
1421 pub fn get_border_top_width(&self, node_idx: usize) -> Option<f32> {
1422 decode_resolved_px_i16(self.tier2_dims[node_idx].border_top_width)
1423 }
1424
1425 #[inline(always)]
1426 pub fn get_border_right_width(&self, node_idx: usize) -> Option<f32> {
1427 decode_resolved_px_i16(self.tier2_dims[node_idx].border_right_width)
1428 }
1429
1430 #[inline(always)]
1431 pub fn get_border_bottom_width(&self, node_idx: usize) -> Option<f32> {
1432 decode_resolved_px_i16(self.tier2_dims[node_idx].border_bottom_width)
1433 }
1434
1435 #[inline(always)]
1436 pub fn get_border_left_width(&self, node_idx: usize) -> Option<f32> {
1437 decode_resolved_px_i16(self.tier2_dims[node_idx].border_left_width)
1438 }
1439
1440 #[inline(always)]
1443 pub fn get_padding_top_raw(&self, node_idx: usize) -> i16 {
1444 self.tier2_dims[node_idx].padding_top
1445 }
1446
1447 #[inline(always)]
1448 pub fn get_padding_right_raw(&self, node_idx: usize) -> i16 {
1449 self.tier2_dims[node_idx].padding_right
1450 }
1451
1452 #[inline(always)]
1453 pub fn get_padding_bottom_raw(&self, node_idx: usize) -> i16 {
1454 self.tier2_dims[node_idx].padding_bottom
1455 }
1456
1457 #[inline(always)]
1458 pub fn get_padding_left_raw(&self, node_idx: usize) -> i16 {
1459 self.tier2_dims[node_idx].padding_left
1460 }
1461
1462 #[inline(always)]
1463 pub fn get_margin_top_raw(&self, node_idx: usize) -> i16 {
1464 self.tier2_dims[node_idx].margin_top
1465 }
1466
1467 #[inline(always)]
1468 pub fn get_margin_right_raw(&self, node_idx: usize) -> i16 {
1469 self.tier2_dims[node_idx].margin_right
1470 }
1471
1472 #[inline(always)]
1473 pub fn get_margin_bottom_raw(&self, node_idx: usize) -> i16 {
1474 self.tier2_dims[node_idx].margin_bottom
1475 }
1476
1477 #[inline(always)]
1478 pub fn get_margin_left_raw(&self, node_idx: usize) -> i16 {
1479 self.tier2_dims[node_idx].margin_left
1480 }
1481
1482 #[inline(always)]
1483 pub fn get_border_top_width_raw(&self, node_idx: usize) -> i16 {
1484 self.tier2_dims[node_idx].border_top_width
1485 }
1486
1487 #[inline(always)]
1488 pub fn get_border_right_width_raw(&self, node_idx: usize) -> i16 {
1489 self.tier2_dims[node_idx].border_right_width
1490 }
1491
1492 #[inline(always)]
1493 pub fn get_border_bottom_width_raw(&self, node_idx: usize) -> i16 {
1494 self.tier2_dims[node_idx].border_bottom_width
1495 }
1496
1497 #[inline(always)]
1498 pub fn get_border_left_width_raw(&self, node_idx: usize) -> i16 {
1499 self.tier2_dims[node_idx].border_left_width
1500 }
1501
1502 #[inline(always)]
1503 pub fn get_top(&self, node_idx: usize) -> i16 {
1504 self.tier2_dims[node_idx].top
1505 }
1506
1507 #[inline(always)]
1508 pub fn get_right(&self, node_idx: usize) -> i16 {
1509 self.tier2_dims[node_idx].right
1510 }
1511
1512 #[inline(always)]
1513 pub fn get_bottom(&self, node_idx: usize) -> i16 {
1514 self.tier2_dims[node_idx].bottom
1515 }
1516
1517 #[inline(always)]
1518 pub fn get_left(&self, node_idx: usize) -> i16 {
1519 self.tier2_dims[node_idx].left
1520 }
1521
1522 #[inline(always)]
1523 pub fn get_flex_grow(&self, node_idx: usize) -> Option<f32> {
1524 decode_flex_u16(self.tier2_dims[node_idx].flex_grow)
1525 }
1526
1527 #[inline(always)]
1528 pub fn get_flex_shrink(&self, node_idx: usize) -> Option<f32> {
1529 decode_flex_u16(self.tier2_dims[node_idx].flex_shrink)
1530 }
1531
1532 #[inline(always)]
1533 pub fn get_z_index(&self, node_idx: usize) -> i16 {
1534 self.tier2_dims[node_idx].z_index
1535 }
1536
1537 #[inline(always)]
1540 pub fn get_border_top_color_raw(&self, node_idx: usize) -> u32 {
1541 self.tier2_dims[node_idx].border_top_color
1542 }
1543
1544 #[inline(always)]
1545 pub fn get_border_right_color_raw(&self, node_idx: usize) -> u32 {
1546 self.tier2_dims[node_idx].border_right_color
1547 }
1548
1549 #[inline(always)]
1550 pub fn get_border_bottom_color_raw(&self, node_idx: usize) -> u32 {
1551 self.tier2_dims[node_idx].border_bottom_color
1552 }
1553
1554 #[inline(always)]
1555 pub fn get_border_left_color_raw(&self, node_idx: usize) -> u32 {
1556 self.tier2_dims[node_idx].border_left_color
1557 }
1558
1559 #[inline(always)]
1562 pub fn get_border_styles_packed(&self, node_idx: usize) -> u16 {
1563 self.tier2_dims[node_idx].border_styles_packed
1564 }
1565
1566 #[inline(always)]
1567 pub fn get_border_top_style(&self, node_idx: usize) -> BorderStyle {
1568 decode_border_top_style(self.tier2_dims[node_idx].border_styles_packed)
1569 }
1570
1571 #[inline(always)]
1572 pub fn get_border_right_style(&self, node_idx: usize) -> BorderStyle {
1573 decode_border_right_style(self.tier2_dims[node_idx].border_styles_packed)
1574 }
1575
1576 #[inline(always)]
1577 pub fn get_border_bottom_style(&self, node_idx: usize) -> BorderStyle {
1578 decode_border_bottom_style(self.tier2_dims[node_idx].border_styles_packed)
1579 }
1580
1581 #[inline(always)]
1582 pub fn get_border_left_style(&self, node_idx: usize) -> BorderStyle {
1583 decode_border_left_style(self.tier2_dims[node_idx].border_styles_packed)
1584 }
1585
1586 #[inline(always)]
1589 pub fn get_border_spacing_h_raw(&self, node_idx: usize) -> i16 {
1590 self.tier2_dims[node_idx].border_spacing_h
1591 }
1592
1593 #[inline(always)]
1594 pub fn get_border_spacing_v_raw(&self, node_idx: usize) -> i16 {
1595 self.tier2_dims[node_idx].border_spacing_v
1596 }
1597
1598 #[inline(always)]
1601 pub fn get_tab_size_raw(&self, node_idx: usize) -> i16 {
1602 self.tier2_dims[node_idx].tab_size
1603 }
1604
1605 #[inline(always)]
1608 pub fn get_text_color_raw(&self, node_idx: usize) -> u32 {
1609 self.tier2b_text[node_idx].text_color
1610 }
1611
1612 #[inline(always)]
1613 pub fn get_font_family_hash(&self, node_idx: usize) -> u64 {
1614 self.tier2b_text[node_idx].font_family_hash
1615 }
1616
1617 #[inline(always)]
1618 pub fn get_line_height(&self, node_idx: usize) -> Option<f32> {
1619 decode_resolved_px_i16(self.tier2b_text[node_idx].line_height)
1620 }
1621
1622 #[inline(always)]
1623 pub fn get_letter_spacing(&self, node_idx: usize) -> Option<f32> {
1624 decode_resolved_px_i16(self.tier2b_text[node_idx].letter_spacing)
1625 }
1626
1627 #[inline(always)]
1628 pub fn get_word_spacing(&self, node_idx: usize) -> Option<f32> {
1629 decode_resolved_px_i16(self.tier2b_text[node_idx].word_spacing)
1630 }
1631
1632 #[inline(always)]
1633 pub fn get_text_indent(&self, node_idx: usize) -> Option<f32> {
1634 decode_resolved_px_i16(self.tier2b_text[node_idx].text_indent)
1635 }
1636
1637 #[inline]
1641 pub fn get_overflow_prop(&self, node_idx: usize, prop: &CssPropertyType) -> Option<&CssProperty> {
1642 self.tier3_overflow
1643 .get(node_idx)
1644 .and_then(|opt| opt.as_ref())
1645 .and_then(|map| map.get(prop))
1646 }
1647
1648 pub fn set_overflow_prop(&mut self, node_idx: usize, prop: CssPropertyType, value: CssProperty) {
1650 if let Some(slot) = self.tier3_overflow.get_mut(node_idx) {
1651 slot.get_or_insert_with(|| Box::new(BTreeMap::new()))
1652 .insert(prop, value);
1653 }
1654 }
1655}
1656
1657#[inline]
1666pub fn encode_css_pixel_as_i16(prop: &CssPropertyValue<PixelValue>) -> i16 {
1667 match prop {
1668 CssPropertyValue::Exact(pv) => {
1669 if pv.metric == SizeMetric::Px {
1670 encode_resolved_px_i16(pv.number.get())
1671 } else {
1672 I16_SENTINEL }
1674 }
1675 CssPropertyValue::Auto => I16_AUTO,
1676 CssPropertyValue::Initial => I16_INITIAL,
1677 CssPropertyValue::Inherit => I16_INHERIT,
1678 _ => I16_SENTINEL,
1679 }
1680}
1681
1682#[cfg(test)]
1683mod tests {
1684 use super::*;
1685
1686 #[test]
1687 fn test_tier1_roundtrip() {
1688 let t1 = encode_tier1(
1689 LayoutDisplay::Flex,
1690 LayoutPosition::Relative,
1691 LayoutFloat::Left,
1692 LayoutOverflow::Hidden,
1693 LayoutOverflow::Scroll,
1694 LayoutBoxSizing::BorderBox,
1695 LayoutFlexDirection::Column,
1696 LayoutFlexWrap::Wrap,
1697 LayoutJustifyContent::SpaceBetween,
1698 LayoutAlignItems::Center,
1699 LayoutAlignContent::End,
1700 LayoutWritingMode::VerticalRl,
1701 LayoutClear::Both,
1702 StyleFontWeight::Bold,
1703 StyleFontStyle::Italic,
1704 StyleTextAlign::Center,
1705 StyleVisibility::Hidden,
1706 StyleWhiteSpace::Pre,
1707 StyleDirection::Rtl,
1708 StyleVerticalAlign::Middle,
1709 StyleBorderCollapse::Collapse,
1710 );
1711
1712 assert!(tier1_is_populated(t1));
1713 assert_eq!(decode_display(t1), LayoutDisplay::Flex);
1714 assert_eq!(decode_position(t1), LayoutPosition::Relative);
1715 assert_eq!(decode_float(t1), LayoutFloat::Left);
1716 assert_eq!(decode_overflow_x(t1), LayoutOverflow::Hidden);
1717 assert_eq!(decode_overflow_y(t1), LayoutOverflow::Scroll);
1718 assert_eq!(decode_box_sizing(t1), LayoutBoxSizing::BorderBox);
1719 assert_eq!(decode_flex_direction(t1), LayoutFlexDirection::Column);
1720 assert_eq!(decode_flex_wrap(t1), LayoutFlexWrap::Wrap);
1721 assert_eq!(decode_justify_content(t1), LayoutJustifyContent::SpaceBetween);
1722 assert_eq!(decode_align_items(t1), LayoutAlignItems::Center);
1723 assert_eq!(decode_align_content(t1), LayoutAlignContent::End);
1724 assert_eq!(decode_writing_mode(t1), LayoutWritingMode::VerticalRl);
1725 assert_eq!(decode_clear(t1), LayoutClear::Both);
1726 assert_eq!(decode_font_weight(t1), StyleFontWeight::Bold);
1727 assert_eq!(decode_font_style(t1), StyleFontStyle::Italic);
1728 assert_eq!(decode_text_align(t1), StyleTextAlign::Center);
1729 assert_eq!(decode_visibility(t1), StyleVisibility::Hidden);
1730 assert_eq!(decode_white_space(t1), StyleWhiteSpace::Pre);
1731 assert_eq!(decode_direction(t1), StyleDirection::Rtl);
1732 assert_eq!(decode_vertical_align(t1), StyleVerticalAlign::Middle);
1733 assert_eq!(decode_border_collapse(t1), StyleBorderCollapse::Collapse);
1734 }
1735
1736 #[test]
1737 fn test_tier1_defaults() {
1738 let t1 = encode_tier1(
1739 LayoutDisplay::Block,
1740 LayoutPosition::Static,
1741 LayoutFloat::None,
1742 LayoutOverflow::Visible,
1743 LayoutOverflow::Visible,
1744 LayoutBoxSizing::ContentBox,
1745 LayoutFlexDirection::Row,
1746 LayoutFlexWrap::NoWrap,
1747 LayoutJustifyContent::FlexStart,
1748 LayoutAlignItems::Stretch,
1749 LayoutAlignContent::Stretch,
1750 LayoutWritingMode::HorizontalTb,
1751 LayoutClear::None,
1752 StyleFontWeight::Normal,
1753 StyleFontStyle::Normal,
1754 StyleTextAlign::Left,
1755 StyleVisibility::Visible,
1756 StyleWhiteSpace::Normal,
1757 StyleDirection::Ltr,
1758 StyleVerticalAlign::Baseline,
1759 StyleBorderCollapse::Separate,
1760 );
1761
1762 assert!(tier1_is_populated(t1));
1763 assert_eq!(decode_display(t1), LayoutDisplay::Block);
1764 assert_eq!(decode_position(t1), LayoutPosition::Static);
1765 }
1766
1767 #[test]
1768 fn test_pixel_value_u32_roundtrip() {
1769 let pv = PixelValue::px(123.456);
1770 let encoded = encode_pixel_value_u32(&pv);
1771 assert!(encoded < U32_SENTINEL_THRESHOLD);
1772 let decoded = decode_pixel_value_u32(encoded).unwrap();
1773 assert_eq!(decoded.metric, SizeMetric::Px);
1774 assert!((decoded.number.get() - 123.456).abs() < 0.002);
1776 }
1777
1778 #[test]
1779 fn test_pixel_value_u32_percent() {
1780 let pv = PixelValue {
1781 metric: SizeMetric::Percent,
1782 number: FloatValue::new(50.0),
1783 };
1784 let encoded = encode_pixel_value_u32(&pv);
1785 let decoded = decode_pixel_value_u32(encoded).unwrap();
1786 assert_eq!(decoded.metric, SizeMetric::Percent);
1787 assert!((decoded.number.get() - 50.0).abs() < 0.002);
1788 }
1789
1790 #[test]
1791 fn test_sentinel_values() {
1792 assert_eq!(decode_pixel_value_u32(U32_SENTINEL), None);
1793 assert_eq!(decode_pixel_value_u32(U32_AUTO), None);
1794 assert_eq!(decode_pixel_value_u32(U32_MIN_CONTENT), None);
1795 assert_eq!(decode_resolved_px_i16(I16_SENTINEL), None);
1796 assert_eq!(decode_resolved_px_i16(I16_AUTO), None);
1797 }
1798
1799 #[test]
1800 fn test_resolved_px_i16_roundtrip() {
1801 let px = 123.4f32;
1802 let encoded = encode_resolved_px_i16(px);
1803 let decoded = decode_resolved_px_i16(encoded).unwrap();
1804 assert!((decoded - 123.4).abs() < 0.11);
1805
1806 let px = -50.7f32;
1808 let encoded = encode_resolved_px_i16(px);
1809 let decoded = decode_resolved_px_i16(encoded).unwrap();
1810 assert!((decoded - (-50.7)).abs() < 0.11);
1811 }
1812
1813 #[test]
1814 fn test_flex_u16_roundtrip() {
1815 let v = 2.5f32;
1816 let encoded = encode_flex_u16(v);
1817 let decoded = decode_flex_u16(encoded).unwrap();
1818 assert!((decoded - 2.5).abs() < 0.011);
1819 }
1820
1821 #[test]
1822 fn test_compact_node_props_size() {
1823 assert_eq!(core::mem::size_of::<CompactNodeProps>(), 96);
1824 }
1825
1826 #[test]
1827 fn test_compact_text_props_size() {
1828 assert_eq!(core::mem::size_of::<CompactTextProps>(), 24);
1829 }
1830}