### Usage Example Source: https://docs.rs/cssbox-core/latest/cssbox_core/index.html Demonstrates how to use the cssbox-core crate to compute layout for a styled node tree. ```APIDOC ## Usage Example ### Description This example shows the basic steps to initialize the layout engine, build a tree of styled nodes, and compute the layout. ### Code ```rust use cssbox_core::tree::BoxTreeBuilder; use cssbox_core::style::ComputedStyle; use cssbox_core::geometry::Size; use cssbox_core::layout::{compute_layout, FixedWidthTextMeasure}; let mut builder = BoxTreeBuilder::new(); let root = builder.root(ComputedStyle::block()); // ... add children ... let tree = builder.build(); let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(800.0, 600.0)); let root_rect = result.bounding_rect(tree.root()); ``` ``` -------------------------------- ### Create a New BoxTree Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Initializes and returns a new, empty BoxTree. This is the starting point for building a layout tree. ```rust pub fn new() -> Self ``` -------------------------------- ### Calculate track positions Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/grid.rs.html Computes the starting positions for tracks given their sizes and a gap value. ```rust fn track_positions(sizes: &[f32], gap: f32) -> Vec { let mut positions = Vec::with_capacity(sizes.len()); let mut pos = 0.0f32; for &size in sizes.iter() { positions.push(pos); pos += size + gap; } positions } ``` -------------------------------- ### Test Column Positioning Calculation Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/table.rs.html Tests the `col_position` function, which calculates the starting position of a column based on preceding column widths and a gutter. Asserts correct positions for multiple columns. ```rust #[test] fn test_col_position() { let widths = vec![100.0, 200.0, 150.0]; assert_eq!(col_position(&widths, 0, 5.0), 5.0); assert_eq!(col_position(&widths, 1, 5.0), 110.0); // 5 + 100 + 5 assert_eq!(col_position(&widths, 2, 5.0), 315.0); // 5 + 100 + 5 + 200 + 5 } ``` -------------------------------- ### Test Distribute Justify Space Evenly Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/flex.rs.html Tests the `distribute_justify` function with `JustifyContent::SpaceEvenly`. Asserts that the calculated start and between space values are correct for three items in a 400px space. ```rust #[test] fn test_distribute_justify_space_evenly() { let (start, between) = distribute_justify(JustifyContent::SpaceEvenly, 400.0, 3); assert_eq!(start, 100.0); assert_eq!(between, 100.0); } ``` -------------------------------- ### Get Root Node ID Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Returns the NodeId of the root node in the BoxTree. Essential for starting tree traversals or operations from the top. ```rust pub fn root(&self) -> NodeId ``` -------------------------------- ### Resolve Offset Pair for Relative Positioning Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/position.rs.html Resolves an offset pair (start and end) for relative positioning. If both start and end values are specified, the start value takes precedence. Handles 'auto' values by resolving them to a concrete length or percentage. ```rust fn resolve_offset_pair( start: &crate::values::LengthPercentageAuto, end: &crate::values::LengthPercentageAuto, reference: f32, ) -> f32 { let s = start.resolve(reference); let e = end.resolve(reference); match (s, e) { (Some(sv), _) => sv, // start wins (None, Some(ev)) => -ev, // end is negated (None, None) => 0.0, } } ``` -------------------------------- ### fn try_into Source: https://docs.rs/cssbox-core/latest/cssbox_core/float/struct.FloatContext.html Documentation for the try_into conversion method. ```APIDOC ## fn try_into(self) -> Result>::Error> ### Description Performs the conversion from the current type to a target type U. ### Parameters - **self** - Required - The instance to be converted. ### Response - **Result>::Error>** - Returns the converted type U or an error if the conversion fails. ``` -------------------------------- ### Initialize New Line Box Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/inline.rs.html Creates a new, empty LineBox with default values. ```rust fn new() -> Self { Self { items: Vec::new(), width: 0.0, height: 0.0, baseline: 0.0, } } ``` -------------------------------- ### Test Case: Relative Offset Both Start Wins Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/position.rs.html Tests `resolve_offset_pair` when both left and right offsets are specified. Verifies that the left (start) offset is returned, as it takes precedence. ```rust let left = LengthPercentageAuto::px(20.0); let right = LengthPercentageAuto::px(10.0); assert_eq!(resolve_offset_pair(&left, &right, 800.0), 20.0); ``` -------------------------------- ### Fragment Implementation Methods Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/fragment.rs.html Provides methods for creating fragments and calculating various box model rectangles and absolute positions. ```rust impl Fragment { pub fn new(node: NodeId, kind: FragmentKind) -> Self { Self { node, position: Point::ZERO, size: Size::ZERO, padding: Edges::ZERO, border: Edges::ZERO, margin: Edges::ZERO, children: Vec::new(), kind, } } /// Border box rect (position + padding + border + content, relative to parent). pub fn border_box(&self) -> Rect { Rect::new( self.position.x, self.position.y, self.size.width + self.padding.horizontal() + self.border.horizontal(), self.size.height + self.padding.vertical() + self.border.vertical(), ) } /// Margin box rect (position + margin + border + padding + content, relative to parent). pub fn margin_box(&self) -> Rect { Rect::new( self.position.x - self.margin.left, self.position.y - self.margin.top, self.size.width + self.padding.horizontal() + self.border.horizontal() + self.margin.horizontal(), self.size.height + self.padding.vertical() + self.border.vertical() + self.margin.vertical(), ) } /// Content box rect (position offset by border + padding). pub fn content_box(&self) -> Rect { Rect::new( self.position.x + self.border.left + self.padding.left, self.position.y + self.border.top + self.padding.top, self.size.width, self.size.height, ) } /// Compute absolute position by walking up the tree. /// The position is the top-left of the border box in viewport coordinates. pub fn absolute_position(&self, ancestors: &[&Fragment]) -> Point { let mut x = self.position.x; let mut y = self.position.y; for ancestor in ancestors.iter().rev() { x += ancestor.position.x + ancestor.border.left + ancestor.padding.left; y += ancestor.position.y + ancestor.border.top + ancestor.padding.top; } Point::new(x, y) } } ``` -------------------------------- ### Get Rect size Source: https://docs.rs/cssbox-core/latest/cssbox_core/geometry/struct.Rect.html Returns the dimensions of the rectangle as a Size object. ```rust pub fn size(&self) -> Size ``` -------------------------------- ### Get Rect origin Source: https://docs.rs/cssbox-core/latest/cssbox_core/geometry/struct.Rect.html Returns the origin (top-left corner) of the rectangle as a Point. ```rust pub fn origin(&self) -> Point ``` -------------------------------- ### Type ID Retrieval Source: https://docs.rs/cssbox-core/latest/cssbox_core/fragment/struct.LayoutOutput.html Gets the `TypeId` of a type, useful for runtime type identification. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Implement CloneToUninit for T Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.NodeId.html Nightly-only experimental API for copying data to uninitialized memory. Requires T to implement Clone. ```rust unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### cssbox-core Modules Overview Source: https://docs.rs/cssbox-core/latest/index.html An overview of the different modules available within the cssbox-core crate, each handling specific aspects of CSS layout. ```APIDOC ## Modules The `cssbox-core` crate is organized into several modules, each responsible for a distinct part of the CSS layout process: - **block**: Handles block formatting context layout. - **box_model**: Manages box model resolution, including margin, border, and padding computation. - **flex**: Implements the Flexbox layout algorithm. - **float**: Deals with float layout according to CSS 2.1 §9.5.1. - **fragment**: Defines the fragment tree, which is the output of the layout process. - **geometry**: Provides geometric primitives used in layout computation. - **grid**: Implements the CSS Grid Layout algorithm. - **inline**: Contains the implementation for inline formatting contexts. - **layout**: Serves as the entry point for layout computation and dispatch. - **position**: Handles CSS positioning (relative, absolute, fixed, sticky). - **style**: Defines computed CSS style types used for layout. - **table**: Implements the CSS Table Layout algorithm. - **tree**: Represents the box tree structure used internally for layout. - **values**: Manages CSS value types and their resolution. ``` -------------------------------- ### Get Used Width of Line Box Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/inline.rs.html Returns the total width occupied by items in the LineBox. ```rust fn used_width(&self) -> f32 { self.width } ``` -------------------------------- ### Point::new Constructor Source: https://docs.rs/cssbox-core/latest/cssbox_core/geometry/struct.Point.html Creates a new Point instance with specified x and y coordinates. Use this to initialize points with custom values. ```rust pub fn new(x: f32, y: f32) -> Self ``` -------------------------------- ### Get Rect bottom edge coordinate Source: https://docs.rs/cssbox-core/latest/cssbox_core/geometry/struct.Rect.html Calculates and returns the y-coordinate of the bottom edge of the rectangle. ```rust pub fn bottom(&self) -> f32 ``` -------------------------------- ### Test BoxTree Construction and Context Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/tree.rs.html Unit tests demonstrating tree construction and formatting context detection. ```rust #[cfg(test)] mod tests { use super::*; use crate::style::ComputedStyle; #[test] fn test_build_simple_tree() { let mut builder = BoxTreeBuilder::new(); let root = builder.root(ComputedStyle::block()); let child1 = builder.element(root, ComputedStyle::block()); let child2 = builder.element(root, ComputedStyle::block()); builder.text(child1, "Hello"); let tree = builder.build(); assert_eq!(tree.len(), 4); assert_eq!(tree.children(root).len(), 2); assert_eq!(tree.children(child1).len(), 1); assert_eq!(tree.children(child2).len(), 0); assert_eq!(tree.parent(child1), Some(root)); } #[test] fn test_formatting_context_detection() { let mut builder = BoxTreeBuilder::new(); let root = builder.root(ComputedStyle::block()); builder.element(root, ComputedStyle::block()); builder.element(root, ComputedStyle::block()); let tree = builder.build(); assert_eq!(tree.formatting_context(root), FormattingContextType::Block); } } ``` -------------------------------- ### Grid layout tests Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/grid.rs.html Unit tests verifying basic grid layout, track positioning, and gap handling. ```rust #[cfg(test)] mod tests { use super::*; use crate::layout::{compute_layout, FixedWidthTextMeasure}; use crate::style::ComputedStyle; use crate::tree::BoxTreeBuilder; #[test] fn test_grid_basic_2x2() { let mut builder = BoxTreeBuilder::new(); let mut root_style = ComputedStyle { display: Display::GRID, ..ComputedStyle::block() }; root_style.grid_template_columns = vec![ TrackDefinition::new(TrackSizingFunction::Fr(1.0)), TrackDefinition::new(TrackSizingFunction::Fr(1.0)), ]; root_style.grid_template_rows = vec![ TrackDefinition::new(TrackSizingFunction::Length(50.0)), TrackDefinition::new(TrackSizingFunction::Length(50.0)), ]; let root = builder.root(root_style); // 4 items for 2x2 grid for _ in 0..4 { let child_style = ComputedStyle::block(); builder.element(root, child_style); } let tree = builder.build(); let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(800.0, 600.0)); let children = tree.children(tree.root()); let r0 = result.bounding_rect(children[0]).unwrap(); let r1 = result.bounding_rect(children[1]).unwrap(); let r2 = result.bounding_rect(children[2]).unwrap(); let r3 = result.bounding_rect(children[3]).unwrap(); // Each column should be 400px wide (800 / 2) assert!((r0.width - 400.0).abs() < 1.0); assert!((r1.width - 400.0).abs() < 1.0); // Positions assert!((r0.x - 0.0).abs() < 1.0); assert!((r1.x - 400.0).abs() < 1.0); assert!((r2.x - 0.0).abs() < 1.0); assert!((r3.x - 400.0).abs() < 1.0); assert!((r0.y - 0.0).abs() < 1.0); assert!((r1.y - 0.0).abs() < 1.0); assert!((r2.y - 50.0).abs() < 1.0); assert!((r3.y - 50.0).abs() < 1.0); } #[test] fn test_track_positions() { let sizes = vec![100.0, 200.0, 150.0]; let positions = track_positions(&sizes, 10.0); assert_eq!(positions, vec![0.0, 110.0, 320.0]); } #[test] fn test_grid_with_gap() { let mut builder = BoxTreeBuilder::new(); let mut root_style = ComputedStyle { display: Display::GRID, ..ComputedStyle::block() }; root_style.grid_template_columns = vec![ TrackDefinition::new(TrackSizingFunction::Fr(1.0)), TrackDefinition::new(TrackSizingFunction::Fr(1.0)), ]; root_style.grid_template_rows = vec![TrackDefinition::new(TrackSizingFunction::Length(50.0))]; root_style.column_gap = 20.0; let root = builder.root(root_style); builder.element(root, ComputedStyle::block()); builder.element(root, ComputedStyle::block()); let tree = builder.build(); let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(820.0, 600.0)); let children = tree.children(tree.root()); let r0 = result.bounding_rect(children[0]).unwrap(); let r1 = result.bounding_rect(children[1]).unwrap(); // (820 - 20 gap) / 2 = 400 each assert!((r0.width - 400.0).abs() < 1.0); assert!((r1.x - 420.0).abs() < 1.0); // 400 + 20 gap } } ``` -------------------------------- ### Get Rect right edge coordinate Source: https://docs.rs/cssbox-core/latest/cssbox_core/geometry/struct.Rect.html Calculates and returns the x-coordinate of the right edge of the rectangle. ```rust pub fn right(&self) -> f32 ``` -------------------------------- ### Get Bottom Edge of Floats Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/float.rs.html Retrieves the maximum bottom edge coordinate from a slice of float boxes. ```rust fn bottom_of_floats(&self, floats: &[FloatBox]) -> f32 { floats .iter() ``` -------------------------------- ### Display Helper Methods Source: https://docs.rs/cssbox-core/latest/cssbox_core/style/struct.Display.html Methods to check display properties like if it's none, block-level, inline-level, establishes a BFC, or is a table part. ```rust pub fn is_none(&self) -> bool ``` ```rust pub fn is_block_level(&self) -> bool ``` ```rust pub fn is_inline_level(&self) -> bool ``` ```rust pub fn establishes_bfc(&self) -> bool ``` ```rust pub fn is_table_part(&self) -> bool ``` -------------------------------- ### Module grid Source: https://docs.rs/cssbox-core/latest/cssbox_core/grid/index.html Provides the CSS Grid Layout algorithm. ```APIDOC ## Module grid ### Description Implements CSS Grid Layout Module Level 2. Reference: https://www.w3.org/TR/css-grid-2/ ### Functions #### layout_grid ##### Description Layout a grid container and its items. ##### Method (Not specified, likely an internal function) ##### Endpoint (Not applicable, this is a library function) ##### Parameters (No parameters specified) ##### Request Body (Not applicable) ##### Response (No response details specified) ``` -------------------------------- ### BoxTree Methods: new Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/tree.rs.html Constructor for creating a new, empty `BoxTree`. ```rust impl BoxTree { pub fn new() -> Self { Self { nodes: Vec::new(), root: NodeId(0), } } // ... ``` -------------------------------- ### Calculate text alignment offset Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/inline.rs.html Determines the horizontal starting position for a line based on the specified text alignment property. ```rust fn calculate_text_align_offset( align: TextAlign, containing_width: f32, line_width: f32, _item_count: usize, ) -> f32 { match align { TextAlign::Left => 0.0, TextAlign::Right => (containing_width - line_width).max(0.0), TextAlign::Center => ((containing_width - line_width) / 2.0).max(0.0), TextAlign::Justify => { // Justify only applies to spacing between items, not initial offset 0.0 } } } ``` -------------------------------- ### BoxTree Methods: len, is_empty Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/tree.rs.html Utility methods to get the total number of nodes in the tree and check if the tree is empty. ```rust /// Total number of nodes. pub fn len(&self) -> usize { self.nodes.len() } pub fn is_empty(&self) -> bool { self.nodes.is_empty() } ``` -------------------------------- ### Compute CSS Layout with BoxTreeBuilder Source: https://docs.rs/cssbox-core/latest/cssbox_core/index.html Initializes a layout tree using BoxTreeBuilder and computes the final layout using the compute_layout function. ```rust use cssbox_core::tree::BoxTreeBuilder; use cssbox_core::style::ComputedStyle; use cssbox_core::geometry::Size; use cssbox_core::layout::{compute_layout, FixedWidthTextMeasure}; let mut builder = BoxTreeBuilder::new(); let root = builder.root(ComputedStyle::block()); // ... add children ... let tree = builder.build(); let result = compute_layout(&tree, &FixedWidthTextMeasure, Size::new(800.0, 600.0)); let root_rect = result.bounding_rect(tree.root()); ``` -------------------------------- ### Get Total Number of Nodes Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Returns the total count of nodes currently present in the BoxTree. Useful for capacity checks or debugging. ```rust pub fn len(&self) -> usize ``` -------------------------------- ### BoxTreeBuilder Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTreeBuilder.html Helper to build a box tree from a simple description. ```APIDOC ## Struct BoxTreeBuilder ### Description Helper to build a box tree from a simple description. ### Fields - **tree** (BoxTree) - The BoxTree being built. ### Methods #### pub fn new() -> Self Creates a new instance of BoxTreeBuilder. #### pub fn root(&mut self, style: ComputedStyle) -> NodeId Adds the root element to the tree. #### pub fn element(&mut self, parent: NodeId, style: ComputedStyle) -> NodeId Adds an element child to a specified parent node. #### pub fn text(&mut self, parent: NodeId, text: &str) -> NodeId Adds a text child to a specified parent node. #### pub fn build(self) -> BoxTree Finalizes the building process and returns the constructed BoxTree. ``` -------------------------------- ### Get Mutable Node Reference Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Retrieves a mutable reference to a node in the BoxTree using its NodeId. Allows for modification of node properties. ```rust pub fn node_mut(&mut self, id: NodeId) -> &mut BoxTreeNode ``` -------------------------------- ### Test Basic Line Formatting Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/inline.rs.html Verifies the basic layout of a single line of text within an inline formatting context. Ensures one line box and one text run are created. ```rust layout_inline_formatting_context(&ctx, root, 800.0, &mut fragments, &mut float_ctx); assert_eq!(fragments.len(), 1); // One line box assert!(height > 0.0); assert_eq!(fragments[0].kind, FragmentKind::LineBox); assert_eq!(fragments[0].children.len(), 1); // One text run ``` -------------------------------- ### Get Parent Node ID Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Returns an Option containing the NodeId of the parent of the specified node. Returns None if the node is the root or has no parent. ```rust pub fn parent(&self, id: NodeId) -> Option ``` -------------------------------- ### PartialEq Implementation for LayoutOutput Source: https://docs.rs/cssbox-core/latest/cssbox_core/fragment/struct.LayoutOutput.html Provides methods for comparing LayoutOutput values for equality. ```rust fn eq(&self, other: &LayoutOutput) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Implement Any for T Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.NodeId.html Provides runtime type information for any type T. This is a blanket implementation. ```rust fn type_id(&self) -> TypeId ``` -------------------------------- ### Get Node Style Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Retrieves an immutable reference to the ComputedStyle associated with a given node. Provides access to the node's styling information. ```rust pub fn style(&self, id: NodeId) -> &ComputedStyle ``` -------------------------------- ### Grid Properties Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/style.rs.html Documentation for CSS grid track sizing functions and definitions. ```APIDOC ## TrackSizingFunction Enum ### Description Represents a grid track sizing function. ### Enum Values - `Length(f32)`: A fixed length. - `Percentage(f32)`: A percentage of the grid container's size. - `Fr(f32)`: A fraction of the remaining space in the grid container. - `MinContent`: The minimum intrinsic size of the content. - `MaxContent`: The maximum intrinsic size of the content. - `Auto`: Auto sizing based on content. - `MinMax(Box, Box)`: Defines a size range with a minimum and maximum value. - `FitContent(f32)`: Defines a size that is at most the specified limit, but otherwise as large as its content allows. ``` ```APIDOC ## TrackDefinition Struct ### Description Represents a grid track definition, including its sizing and an optional line name. ### Fields - `sizing` (TrackSizingFunction): The sizing function for the track. - `line_name` (Option): An optional name for the grid line. ``` -------------------------------- ### Get Children of a Node Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Returns a slice containing the NodeIds of all direct children of the specified node. Useful for iterating over a node's descendants. ```rust pub fn children(&self, id: NodeId) -> &[NodeId] ``` -------------------------------- ### Get Bounding Rect for Node Source: https://docs.rs/cssbox-core/latest/cssbox_core/fragment/struct.LayoutResult.html Obtains the bounding client rectangle for a given node ID. Returns None if the node ID does not exist. ```rust pub fn bounding_rect(&self, node: NodeId) -> Option ``` -------------------------------- ### Layout Table Element Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/table.rs.html Main entry point for calculating the layout of a table element, including border resolution, column width determination, and child fragment positioning. ```rust pub fn layout_table( ctx: &LayoutContext, node: NodeId, containing_block_width: f32, containing_block_height: f32, ) -> Fragment { let style = ctx.tree.style(node); let mut fragment = Fragment::new(node, FragmentKind::Box); // Resolve table box model let border = BoxModel::resolve_border(style); let padding = BoxModel::resolve_padding(style, containing_block_width); let margin = BoxModel::resolve_margin(style, containing_block_width); fragment.border = border; fragment.padding = padding; fragment.margin = margin; let content_width = match style.width.resolve(containing_block_width) { Some(mut w) => { if style.box_sizing == BoxSizing::BorderBox { w = (w - border.horizontal() - padding.horizontal()).max(0.0); } w } None => (containing_block_width - border.horizontal() - padding.horizontal() - margin.horizontal()) .max(0.0), }; // Collect table structure let mut table = TableStructure::new(); collect_table_structure(ctx, node, &mut table); let is_fixed = style.table_layout == TableLayout::Fixed; let is_collapse = style.border_collapse == BorderCollapse::Collapse; let border_spacing = if is_collapse { 0.0 } else { style.border_spacing }; // Determine column widths let col_widths = if is_fixed { fixed_table_layout(&table, content_width, border_spacing, ctx) } else { auto_table_layout(&table, content_width, border_spacing, ctx) }; let num_cols = col_widths.len(); let total_spacing = border_spacing * (num_cols + 1) as f32; let table_content_width = col_widths.iter().sum::() + total_spacing; // Layout captions (top) let mut cursor_y = 0.0f32; if style.caption_side == CaptionSide::Top { for &caption_node in &table.captions { let mut cap_frag = layout::layout_node(ctx, caption_node, content_width, containing_block_height); cap_frag.position = Point::new(cap_frag.margin.left, cursor_y); cursor_y += cap_frag.border_box().height + cap_frag.margin.vertical(); fragment.children.push(cap_frag); } } // Layout rows for row in table.rows.iter() { let mut row_height: f32 = 0.0; let mut cell_fragments: Vec<(usize, Fragment)> = Vec::new(); for cell in &row.cells { let col_idx = cell.col_start; let col_span = cell.col_span; // Calculate cell width let mut cell_width = 0.0f32; for c in col_idx..(col_idx + col_span).min(num_cols) { cell_width += col_widths[c]; if c > col_idx { cell_width += border_spacing; } } // Layout cell content let cell_frag = layout::layout_node(ctx, cell.node, cell_width, containing_block_height); let cell_total_height = cell_frag.border_box().height; row_height = row_height.max(cell_total_height); cell_fragments.push((col_idx, cell_frag)); } // Resolve specified row height if let Some(row_node) = row.node { let row_style = ctx.tree.style(row_node); if let Some(h) = row_style.height.resolve(containing_block_height) { row_height = row_height.max(h); } } // Position cells for (col_idx, mut cell_frag) in cell_fragments { let x = col_position(&col_widths, col_idx, border_spacing); cell_frag.position = Point::new(x, cursor_y); // Vertical alignment in cell — default to top // TODO: implement vertical-align for table cells fragment.children.push(cell_frag); } cursor_y += row_height + border_spacing; } // Layout captions (bottom) if style.caption_side == CaptionSide::Bottom { for &caption_node in &table.captions { let mut cap_frag = layout::layout_node(ctx, caption_node, content_width, containing_block_height); ``` -------------------------------- ### Get Immutable Node Reference Source: https://docs.rs/cssbox-core/latest/cssbox_core/tree/struct.BoxTree.html Retrieves an immutable reference to a node in the BoxTree using its NodeId. Used for inspecting node properties without modification. ```rust pub fn node(&self, id: NodeId) -> &BoxTreeNode ``` -------------------------------- ### Create Rect from Point and Size Source: https://docs.rs/cssbox-core/latest/cssbox_core/geometry/struct.Rect.html Creates a Rect from a Point and a Size object. ```rust pub fn from_point_size(point: Point, size: Size) -> Self ``` -------------------------------- ### Rust Enum for CSS Justify Content Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/style.rs.html Represents the CSS `justify-content` property. Includes `FlexStart`, `FlexEnd`, `Center`, `SpaceBetween`, `SpaceAround`, `SpaceEvenly`, `Start`, and `End`. ```rust pub enum JustifyContent { #[default] FlexStart, FlexEnd, Center, SpaceBetween, SpaceAround, SpaceEvenly, Start, End, } ``` -------------------------------- ### ComputedStyle Factory Methods and Helpers Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/style.rs.html Methods for creating specific element styles and checking layout context properties. ```rust impl ComputedStyle { /// Create a block-level element style with default values. pub fn block() -> Self { Self { display: Display::BLOCK, ..Default::default() } } /// Create an inline element style. pub fn inline() -> Self { Self::default() } /// Whether this element establishes a new block formatting context. pub fn establishes_bfc(&self) -> bool { self.display.establishes_bfc() || self.overflow_x != Overflow::Visible || self.overflow_y != Overflow::Visible || self.float != Float::None || self.position.is_absolutely_positioned() } /// Whether this element is out of flow. pub fn is_out_of_flow(&self) -> bool { self.position.is_absolutely_positioned() || self.float != Float::None } } ``` -------------------------------- ### Rust Enum for CSS Align Self Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/style.rs.html Represents the CSS `align-self` property. Supports `Auto`, `Stretch`, `FlexStart`, `FlexEnd`, `Center`, `Baseline`, `Start`, and `End`. ```rust pub enum AlignSelf { #[default] Auto, Stretch, FlexStart, FlexEnd, Center, Baseline, Start, End, } ``` -------------------------------- ### Implement BoxTreeBuilder Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/tree.rs.html Provides methods to construct a box tree by adding roots, elements, and text nodes. ```rust pub struct BoxTreeBuilder { pub tree: BoxTree, } impl BoxTreeBuilder { pub fn new() -> Self { Self { tree: BoxTree::new(), } } /// Add the root element. pub fn root(&mut self, style: ComputedStyle) -> NodeId { let id = self.tree.add_node(NodeKind::Element, style); self.tree.set_root(id); id } /// Add an element child. pub fn element(&mut self, parent: NodeId, style: ComputedStyle) -> NodeId { let id = self.tree.add_node(NodeKind::Element, style); self.tree.append_child(parent, id); id } /// Add a text child. pub fn text(&mut self, parent: NodeId, text: &str) -> NodeId { let id = self.tree.add_node( NodeKind::Text(TextContent { text: text.to_string(), }), ComputedStyle::inline(), ); self.tree.append_child(parent, id); id } /// Finish building and return the tree. pub fn build(self) -> BoxTree { self.tree } } impl Default for BoxTreeBuilder { fn default() -> Self { Self::new() } } ``` -------------------------------- ### TryFrom and TryInto Conversions Source: https://docs.rs/cssbox-core/latest/cssbox_core/fragment/struct.LayoutOutput.html Provides fallible conversion methods between types, returning a `Result`. ```rust type Error = Infallible ``` ```rust fn try_from(value: U) -> Result>::Error> ``` ```rust type Error = >::Error ``` ```rust fn try_into(self) -> Result>::Error> ``` -------------------------------- ### Resolve LengthPercentage Source: https://docs.rs/cssbox-core/latest/cssbox_core/values/enum.LengthPercentage.html Resolves a LengthPercentage value against a reference value to get a final pixel value. This method is useful for converting relative units to absolute ones. ```rust pub fn resolve(&self, reference: f32) -> f32 ``` -------------------------------- ### Rust Enum for CSS Align Content Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/style.rs.html Represents the CSS `align-content` property. Supports `Stretch`, `FlexStart`, `FlexEnd`, `Center`, `SpaceBetween`, `SpaceAround`, `SpaceEvenly`, `Start`, and `End`. ```rust pub enum AlignContent { #[default] Stretch, FlexStart, FlexEnd, Center, SpaceBetween, SpaceAround, SpaceEvenly, Start, End, } ``` -------------------------------- ### Display PartialEq Implementation Source: https://docs.rs/cssbox-core/latest/cssbox_core/style/struct.Display.html Enables comparison for equality between Display values. ```rust fn eq(&self, other: &Display) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Get Layout Output for Node Source: https://docs.rs/cssbox-core/latest/cssbox_core/fragment/struct.LayoutResult.html Retrieves the layout output, equivalent to a bounding client rect, for a specific node ID. Returns None if the node ID is not found. ```rust pub fn get_layout(&self, node: NodeId) -> Option ``` -------------------------------- ### Implement CloneToUninit Trait (Nightly) Source: https://docs.rs/cssbox-core/latest/cssbox_core/style/enum.AlignItems.html An experimental nightly-only feature for copying AlignItems to uninitialized memory. Use with caution. ```rust impl CloneToUninit for T where T: Clone, Source unsafe fn clone_to_uninit(&self, dest: *mut u8) ``` -------------------------------- ### Block Width Resolution Tests Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/box_model.rs.html Unit tests verifying width calculation logic for auto-filling, centered margins, padding, and border-box sizing. ```rust #[cfg(test)] mod tests { use super::*; use crate::style::ComputedStyle; use crate::values::LengthPercentageAuto; #[test] fn test_block_width_auto_fills_container() { let style = ComputedStyle::block(); let (width, margin) = resolve_block_width(&style, 800.0); assert_eq!(width, 800.0); assert_eq!(margin.left, 0.0); assert_eq!(margin.right, 0.0); } #[test] fn test_block_width_fixed_centers_with_auto_margins() { let mut style = ComputedStyle::block(); style.width = LengthPercentageAuto::px(400.0); style.margin_left = LengthPercentageAuto::Auto; style.margin_right = LengthPercentageAuto::Auto; let (width, margin) = resolve_block_width(&style, 800.0); assert_eq!(width, 400.0); assert_eq!(margin.left, 200.0); assert_eq!(margin.right, 200.0); } #[test] fn test_block_width_with_padding() { let mut style = ComputedStyle::block(); style.padding_left = crate::values::LengthPercentage::px(20.0); style.padding_right = crate::values::LengthPercentage::px(20.0); let (width, _margin) = resolve_block_width(&style, 800.0); assert_eq!(width, 760.0); // 800 - 20 - 20 } #[test] fn test_block_width_border_box() { let mut style = ComputedStyle::block(); style.width = LengthPercentageAuto::px(400.0); style.box_sizing = crate::style::BoxSizing::BorderBox; style.padding_left = crate::values::LengthPercentage::px(20.0); style.padding_right = crate::values::LengthPercentage::px(20.0); style.border_left_width = 5.0; style.border_right_width = 5.0; let (width, _margin) = resolve_block_width(&style, 800.0); assert_eq!(width, 350.0); // 400 - 20 - 20 - 5 - 5 } } ``` -------------------------------- ### Rust Enum for CSS Align Items Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/style.rs.html Represents CSS alignment values for properties like `align-items`. Includes `Stretch`, `FlexStart`, `FlexEnd`, `Center`, `Baseline`, `Start`, and `End`. ```rust pub enum AlignItems { #[default] Stretch, FlexStart, FlexEnd, Center, Baseline, Start, End, } ``` -------------------------------- ### Collect Table Row Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/table.rs.html Collects table cells within a specific table row node. It iterates through row children and creates TableCell structs, calculating the starting column. ```rust fn collect_row(ctx: &LayoutContext, row_node: NodeId, table: &mut TableStructure) { let children = ctx.tree.children(row_node); let mut cells = Vec::new(); let mut col = 0; for &child_id in children { let child_style = ctx.tree.style(child_id); if child_style.display.is_none() { continue; } cells.push(TableCell { node: child_id, col_start: col, col_span: 1, // TODO: colspan attribute support }); col += 1; } table.rows.push(TableRow { node: Some(row_node), cells, }); } ``` -------------------------------- ### Test single line layout Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/inline.rs.html Unit test for verifying basic single-line layout construction. ```rust #[test] fn test_single_line_layout() { let mut builder = BoxTreeBuilder::new(); let root = builder.root(ComputedStyle::block()); builder.text(root, "Hello"); let tree = builder.build(); let ctx = LayoutContext { tree: &tree, text_measure: &FixedWidthTextMeasure, viewport: Size::new(800.0, 600.0), }; let mut fragments = Vec::new(); let mut float_ctx = FloatContext::new(800.0); let height = ``` -------------------------------- ### PartialEq Implementation for TableLayout Source: https://docs.rs/cssbox-core/latest/cssbox_core/style/enum.TableLayout.html Allows comparison of TableLayout values for equality using `eq` and inequality using `ne`. ```rust fn eq(&self, other: &TableLayout) -> bool ``` ```rust fn ne(&self, other: &Rhs) -> bool ``` -------------------------------- ### Test Case: Absolute Position Stretch Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/position.rs.html Tests the `resolve_absolute_axis` function when both start and end offsets are specified, and size is 'auto', causing the element to stretch. Verifies the calculated position and width. ```rust let (x, w) = resolve_absolute_axis( &LengthPercentageAuto::px(10.0), &LengthPercentageAuto::px(10.0), &LengthPercentageAuto::Auto, &LengthPercentageAuto::px(0.0), &LengthPercentageAuto::px(0.0), 0.0, 0.0, 800.0, 0.0, ); assert_eq!(x, 10.0); assert_eq!(w, 780.0); // 800 - 10 - 10 ``` -------------------------------- ### Test Zero Available Width Scenario Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/float.rs.html Tests a scenario where left and right floats, when placed, leave no horizontal space between them. It verifies that the available width calculation correctly reflects this. ```rust #[test] fn test_zero_available_width() { let mut ctx = FloatContext::new(400.0); let left = create_fragment(250.0, 100.0, 0.0); ctx.place_float(left, Float::Left, 0.0); let right = create_fragment(250.0, 100.0, 0.0); ctx.place_float(right, Float::Right, 0.0); let (_, width) = ctx.available_width_at(50.0, 10.0); // Right float doesn't fit next to left float, so wraps below it. // At y=50, only left float (y=0-100) overlaps, so available width is 400-250=150 assert_eq!(width, 150.0); } ``` -------------------------------- ### Distribute Justify Function Source: https://docs.rs/cssbox-core/latest/src/cssbox_core/flex.rs.html Calculates the distribution of space for justification along the main axis in a flex container. Handles various `JustifyContent` values like `FlexStart`, `Center`, `SpaceBetween`, `SpaceAround`, and `SpaceEvenly`. Returns the start and between space values. ```rust fn distribute_justify(justify: JustifyContent, extra: f32, item_count: usize) -> (f32, f32) { if item_count == 0 { return (0.0, 0.0); } match justify { JustifyContent::FlexStart | JustifyContent::Start => (0.0, 0.0), JustifyContent::FlexEnd | JustifyContent::End => (extra, 0.0), JustifyContent::Center => (extra / 2.0, 0.0), JustifyContent::SpaceBetween => { if item_count <= 1 { (0.0, 0.0) } else { (0.0, extra / (item_count - 1) as f32) } } JustifyContent::SpaceAround => { let gap = extra / item_count as f32; (gap / 2.0, gap) } JustifyContent::SpaceEvenly => { let gap = extra / (item_count + 1) as f32; (gap, gap) } } } ```