diff --git a/float-pigment-css/src/property.rs b/float-pigment-css/src/property.rs index ec8a354..30ad04d 100644 --- a/float-pigment-css/src/property.rs +++ b/float-pigment-css/src/property.rs @@ -55,6 +55,8 @@ property_list! (PropertyValueWithGlobal, { 0x28 FlexBasis: LengthType as Initial default Length::Undefined, resolver = Length::resolve_em; 0x29 JustifyItems: JustifyItemsType as Initial default JustifyItems::Stretch; 0x2a Order: NumberType as Initial default Number::I32(0); + 0x2b RowGap: GapType as Initial default Gap::Normal; + 0x2c ColumnGap: GapType as Initial default Gap::Normal; // background 0x30 BackgroundColor: ColorType as Initial default Color::Undefined; @@ -330,6 +332,20 @@ property_value_format! (PropertyValueWithGlobal, { | "right" => JustifyItems::Right }}; order: {{ Order = -> |x: Number| Number::I32(x.to_i32()); }}; + : + "normal" => Gap::Normal + | -> |length| Gap::Length(length); + ; + column_gap: {{ ColumnGap = }}; + row_gap: {{ RowGap = }}; + gap: {{ (RowGap, ColumnGap) + = [ ? ] -> |(row_gap, column_gap): (Gap, Option)| { + if let Some(column_gap) = column_gap { + return (row_gap, column_gap); + } + return (row_gap.clone(), row_gap); + }; + }}; flex_grow: {{ FlexGrow = }}; flex_shrink: {{ FlexShrink = }}; flex_basis: {{ FlexBasis = }}; diff --git a/float-pigment-css/src/typing.rs b/float-pigment-css/src/typing.rs index 9b219f0..93632cf 100644 --- a/float-pigment-css/src/typing.rs +++ b/float-pigment-css/src/typing.rs @@ -1785,3 +1785,14 @@ pub struct FeatureTag { /// The optional number value in `font-feature-settings`. pub value: Number, } + +#[allow(missing_docs)] +#[repr(C)] +#[property_value_type(PropertyValueWithGlobal for GapType)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ResolveFontSize)] +#[cfg_attr(debug_assertions, derive(CompatibilityEnumCheck))] +pub enum Gap { + Normal, + #[resolve_font_size(Length::resolve_em_and_ratio)] + Length(Length), +} diff --git a/float-pigment-css/src/typing_stringify.rs b/float-pigment-css/src/typing_stringify.rs index a72fd42..22fa9db 100644 --- a/float-pigment-css/src/typing_stringify.rs +++ b/float-pigment-css/src/typing_stringify.rs @@ -2327,3 +2327,12 @@ impl fmt::Display for FontFeatureSettings { write!(f, "{}", ret.join(",")) } } + +impl fmt::Display for Gap { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Gap::Normal => write!(f, "normal"), + Gap::Length(length) => write!(f, "{}", length), + } + } +} diff --git a/float-pigment-css/tests/property.rs b/float-pigment-css/tests/property.rs index 5c0f09f..6a7a239 100644 --- a/float-pigment-css/tests/property.rs +++ b/float-pigment-css/tests/property.rs @@ -2058,6 +2058,42 @@ mod flex { test_parse_property!(order, "order", "1", Number::I32(1)); test_parse_property!(order, "order", "-100", Number::I32(-100)); } + // 0x2b + #[test] + fn row_gap() { + test_parse_property!(row_gap, "row-gap", "normal", Gap::Normal); + test_parse_property!(row_gap, "row-gap", "10px", Gap::Length(Length::Px(10.))); + } + + // 0x2c + #[test] + fn column_gap() { + test_parse_property!(column_gap, "column-gap", "normal", Gap::Normal); + test_parse_property!(column_gap, "column-gap", "-10%", Gap::Normal); + } + + #[test] + fn gap() { + test_parse_property!(row_gap, "gap", "normal", Gap::Normal); + test_parse_property!(column_gap, "gap", "normal", Gap::Normal); + + test_parse_property!(row_gap, "gap", "30px", Gap::Length(Length::Px(30.))); + test_parse_property!(column_gap, "gap", "20px", Gap::Length(Length::Px(20.))); + + test_parse_property!(row_gap, "gap", "normal 10px", Gap::Normal); + test_parse_property!(row_gap, "gap", "10px normal", Gap::Length(Length::Px(10.))); + test_parse_property!( + column_gap, + "gap", + "normal 10px", + Gap::Length(Length::Px(10.)) + ); + test_parse_property!(column_gap, "gap", "10px normal", Gap::Normal); + + test_parse_property!(row_gap, "gap", "30px 40px", Gap::Length(Length::Px(30.))); + test_parse_property!(column_gap, "gap", "30px 40px", Gap::Length(Length::Px(40.))); + } + #[test] fn flex_flow() { let mut ssg = StyleSheetGroup::new(); diff --git a/float-pigment-forest/src/ffi.rs b/float-pigment-forest/src/ffi.rs index 94eed1d..3157a60 100644 --- a/float-pigment-forest/src/ffi.rs +++ b/float-pigment-forest/src/ffi.rs @@ -742,6 +742,71 @@ pub unsafe extern "C" fn NodeStyleSetOrder(node: NodePtr, value: i32) { node.set_order(value); } +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetRowGap(node: NodePtr, value: f32) { + let node = &*(node.ptr as *mut Node); + node.set_row_gap(DefLength::Points(Len::from_f32(value))); +} + +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetRowGapNormal(node: NodePtr) { + let node = &*(node.ptr as *mut Node); + node.set_row_gap(DefLength::Undefined); +} + +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetRowGapPercentage(node: NodePtr, value: f32) { + let node = &*(node.ptr as *mut Node); + node.set_row_gap(DefLength::Percent(value)); +} + +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetRowGapCalcHandle(node: NodePtr, calc_handle: i32) { + let node = &*(node.ptr as *mut Node); + node.set_row_gap(DefLength::Custom(calc_handle)); +} + +/// # Safety +/// +#[no_mangle] + +pub unsafe extern "C" fn NodeStyleSetColumnGap(node: NodePtr, value: f32) { + let node = &*(node.ptr as *mut Node); + node.set_column_gap(DefLength::Points(Len::from_f32(value))); +} + +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetColumnGapNormal(node: NodePtr) { + let node = &*(node.ptr as *mut Node); + node.set_column_gap(DefLength::Undefined); +} + +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetColumnGapPercentage(node: NodePtr, value: f32) { + let node = &*(node.ptr as *mut Node); + node.set_column_gap(DefLength::Percent(value)); +} + +/// # Safety +/// +#[no_mangle] +pub unsafe extern "C" fn NodeStyleSetColumnGapCalcHandle(node: NodePtr, calc_handle: i32) { + let node = &*(node.ptr as *mut Node); + node.set_column_gap(DefLength::Custom(calc_handle)); +} + /// # Safety /// #[no_mangle] diff --git a/float-pigment-forest/src/layout/layout_impl.rs b/float-pigment-forest/src/layout/layout_impl.rs index b107cdb..45258c5 100644 --- a/float-pigment-forest/src/layout/layout_impl.rs +++ b/float-pigment-forest/src/layout/layout_impl.rs @@ -685,4 +685,14 @@ impl LayoutStyle for Node { fn text_align(&self) -> TextAlign { self.style_manager().text_align() } + + #[inline] + fn row_gap(&self) -> Length { + self.style_manager().row_gap() + } + + #[inline] + fn column_gap(&self) -> Length { + self.style_manager().column_gap() + } } diff --git a/float-pigment-forest/src/node.rs b/float-pigment-forest/src/node.rs index 22c100e..9d36725 100644 --- a/float-pigment-forest/src/node.rs +++ b/float-pigment-forest/src/node.rs @@ -618,6 +618,8 @@ pub trait StyleSetter { unsafe fn set_aspect_ratio(&self, value: Option); unsafe fn set_order(&self, value: i32); unsafe fn set_text_align(&self, value: TextAlign); + unsafe fn set_row_gap(&self, value: Length); + unsafe fn set_column_gap(&self, value: Length); } impl StyleSetter for Node { @@ -857,6 +859,16 @@ impl StyleSetter for Node { self.mark_dirty_propagate(); } } + unsafe fn set_row_gap(&self, value: Length) { + if self.style_manager_mut().set_row_gap(value) { + self.mark_dirty_propagate(); + } + } + unsafe fn set_column_gap(&self, value: Length) { + if self.style_manager_mut().set_column_gap(value) { + self.mark_dirty_propagate(); + } + } } #[cfg(test)] diff --git a/float-pigment-forest/src/style.rs b/float-pigment-forest/src/style.rs index e6d57ca..1e64fa3 100644 --- a/float-pigment-forest/src/style.rs +++ b/float-pigment-forest/src/style.rs @@ -76,6 +76,8 @@ struct OtherStyle { pub overflow_y: Overflow, pub text_align: TextAlign, pub aspect_ratio: Option, + pub row_gap: Length, + pub column_gap: Length, } impl Default for OtherStyle { @@ -87,6 +89,8 @@ impl Default for OtherStyle { overflow_y: Overflow::Visible, text_align: TextAlign::Start, aspect_ratio: None, + row_gap: Length::Undefined, + column_gap: Length::Undefined, } } } @@ -945,4 +949,30 @@ impl StyleManager { self.flex_style().flex_basis = value; true } + + pub(crate) fn row_gap(&self) -> Length { + self.other_style().row_gap.clone() + } + + pub(crate) fn set_row_gap(&self, value: Length) -> bool { + if self.other_style().row_gap == value { + return false; + } + self.clone_style(StyleBit::Other); + self.other_style().row_gap = value; + true + } + + pub(crate) fn column_gap(&self) -> Length { + self.other_style().column_gap.clone() + } + + pub(crate) fn set_column_gap(&self, value: Length) -> bool { + if self.other_style().column_gap == value { + return false; + } + self.clone_style(StyleBit::Other); + self.other_style().column_gap = value; + true + } } diff --git a/float-pigment-forest/tests/custom/css_flexbox/gap.rs b/float-pigment-forest/tests/custom/css_flexbox/gap.rs new file mode 100644 index 0000000..a2cdd37 --- /dev/null +++ b/float-pigment-forest/tests/custom/css_flexbox/gap.rs @@ -0,0 +1,61 @@ +use crate::*; + +#[test] +fn gap() { + assert_xml!( + r#" +
+
+
+
+ "# + ) +} + +#[test] +fn column_gap_in_flex_row_box() { + assert_xml!( + r#" +
+
+
+
+ "# + ) +} + +#[test] +fn row_gap_in_flex_row_box() { + assert_xml!( + r#" +
+
+
+
+ "# + ) +} + +#[test] +fn column_gap_in_flex_column_box() { + assert_xml!( + r#" +
+
+
+
+ "# + ) +} + +#[test] +fn row_gap_in_flex_column_box() { + assert_xml!( + r#" +
+
+
+
+ "# + ) +} diff --git a/float-pigment-forest/tests/custom/css_flexbox/mod.rs b/float-pigment-forest/tests/custom/css_flexbox/mod.rs index 6c2217b..c5edcef 100644 --- a/float-pigment-forest/tests/custom/css_flexbox/mod.rs +++ b/float-pigment-forest/tests/custom/css_flexbox/mod.rs @@ -9,3 +9,4 @@ mod order; mod align_content; mod flex_item_margin; +mod gap; diff --git a/float-pigment-forest/tests/mod.rs b/float-pigment-forest/tests/mod.rs index 37e398c..105825f 100644 --- a/float-pigment-forest/tests/mod.rs +++ b/float-pigment-forest/tests/mod.rs @@ -7,7 +7,7 @@ pub use float_pigment_css::length_num::LengthNum; use float_pigment_css::{ parser::parse_inline_style, property::NodeProperties, - typing::{AspectRatio, Display}, + typing::{AspectRatio, Display, Gap}, }; pub use float_pigment_forest::Len; use float_pigment_forest::{layout::LayoutPosition, node::Length, *}; @@ -389,6 +389,36 @@ impl TestCtx { }, "order" => node.set_order(node_props.order().to_i32()), "text-align" => node.set_text_align(node_props.text_align()), + "gap" => { + node.set_row_gap({ + match node_props.row_gap() { + Gap::Length(l) => def_length(l), + Gap::Normal => Length::Undefined, + } + }); + node.set_column_gap({ + match node_props.column_gap() { + Gap::Length(l) => def_length(l), + Gap::Normal => Length::Undefined, + } + }); + } + "column-gap" => { + node.set_column_gap({ + match node_props.column_gap() { + Gap::Length(l) => def_length(l), + Gap::Normal => Length::Undefined, + } + }); + } + "row-gap" => { + node.set_row_gap({ + match node_props.row_gap() { + Gap::Length(l) => def_length(l), + Gap::Normal => Length::Undefined, + } + }); + } _ => {} } }); diff --git a/float-pigment-layout/src/algo/flex_box.rs b/float-pigment-layout/src/algo/flex_box.rs index 137f398..c4a4e94 100644 --- a/float-pigment-layout/src/algo/flex_box.rs +++ b/float-pigment-layout/src/algo/flex_box.rs @@ -2,6 +2,18 @@ use crate::*; use float_pigment_css::num_traits::Zero; +/// Computes the total space taken up by gaps in an axis given: +/// - The size of each gap +/// - The number of items (children or flex-lines) between which there are gaps +#[inline(always)] +fn sum_axis_gaps(gap: L, num_items: usize) -> L { + if num_items <= 1 { + L::zero() + } else { + gap.mul_i32(num_items as i32 - 1) + } +} + pub(crate) fn align_self(child: &T::Style, parent: &T::Style) -> AlignSelf { let s = child.align_self(); if s == AlignSelf::Auto { @@ -335,15 +347,25 @@ impl FlexBox for LayoutUnit { }); } else { let mut flex_items = &mut flex_items[..]; + let main_axis_gap = style + .row_gap() + .resolve(requested_inner_size.main_size(dir), node) + .or_zero(); while !flex_items.is_empty() { let mut line_length = T::Length::zero(); let index = flex_items .iter() .enumerate() - .find(|(idx, child)| { - line_length += child.hypothetical_outer_size.main_size(dir); + .find(|&(idx, child)| { + let gap_contribution = if idx == 0 { + T::Length::zero() + } else { + main_axis_gap + }; + line_length += + child.hypothetical_outer_size.main_size(dir) + gap_contribution; match available_space.main_size(dir).val() { - Some(x) => line_length > x && *idx != 0, + Some(x) => line_length > x && idx != 0, None => false, } }) @@ -369,16 +391,24 @@ impl FlexBox for LayoutUnit { let multi_flex_line = flex_lines.len() > 1; for line in &mut flex_lines { + let total_main_axis_gap = sum_axis_gaps( + style + .row_gap() + .resolve(requested_inner_size.main_size(dir), node) + .or_zero(), + line.items.len(), + ); // 1. Determine the used flex factor. Sum the outer hypothetical main sizes of all // items on the line. If the sum is less than the flex container’s inner main size, // use the flex grow factor for the rest of this algorithm; otherwise, use the // flex shrink factor. - let used_flex_factor: T::Length = length_sum( - line.items - .iter() - .map(|child| child.hypothetical_outer_size.main_size(dir)), - ); + let used_flex_factor: T::Length = total_main_axis_gap + + length_sum( + line.items + .iter() + .map(|child| child.hypothetical_outer_size.main_size(dir)), + ); let growing = used_flex_factor < requested_inner_size.main_size(dir).or_zero(); let shrinking = !growing; @@ -469,14 +499,15 @@ impl FlexBox for LayoutUnit { // and subtract this from the flex container’s inner main size. For frozen items, // use their outer target main size; for other items, use their outer flex base size. - let used_space: T::Length = length_sum(line.items.iter().map(|child| { - child.margin.main_axis_sum(dir) - + if child.frozen { - child.target_size.main_size(dir) - } else { - child.flex_basis - } - })); + let used_space: T::Length = total_main_axis_gap + + length_sum(line.items.iter().map(|child| { + child.margin.main_axis_sum(dir) + + if child.frozen { + child.target_size.main_size(dir) + } else { + child.flex_basis + } + })); let initial_free_space = (target_len - used_space).or_zero(); let mut prev_free_space: Option = None; @@ -496,14 +527,15 @@ impl FlexBox for LayoutUnit { // value is less than the magnitude of the remaining free space, use this // as the remaining free space. - let used_space: T::Length = length_sum(line.items.iter().map(|child| { - child.margin.main_axis_sum(dir) - + if child.frozen { - child.target_size.main_size(dir) - } else { - child.flex_basis - } - })); + let used_space: T::Length = total_main_axis_gap + + length_sum(line.items.iter().map(|child| { + child.margin.main_axis_sum(dir) + + if child.frozen { + child.target_size.main_size(dir) + } else { + child.flex_basis + } + })); let mut unfrozen: Vec<&mut FlexItem> = line .items @@ -518,12 +550,10 @@ impl FlexBox for LayoutUnit { (flex_grow + child.flex_grow, flex_shrink + child.flex_shrink) }); let free_space = if growing && sum_flex_grow < 1.0 { - initial_free_space - .mul_f32(sum_flex_grow) + (initial_free_space.mul_f32(sum_flex_grow) - total_main_axis_gap) .maybe_min(target_len - used_space) } else if shrinking && sum_flex_shrink < 1.0 { - initial_free_space - .mul_f32(sum_flex_shrink) + (initial_free_space.mul_f32(sum_flex_shrink) - total_main_axis_gap) .maybe_max(target_len - used_space) } else { (target_len - used_space).or_zero() @@ -852,8 +882,15 @@ impl FlexBox for LayoutUnit { let requested_cross_size = requested_size.cross_size(dir).or_zero(); let min_inner_cross = self_min_max_limit.cross_size(requested_cross_size, dir) - padding_border_cross; + let total_cross_axis_gap = sum_axis_gaps( + style + .column_gap() + .resolve(requested_inner_size.main_size(dir), node) + .or_zero(), + flex_lines.len(), + ); let line_total_cross: T::Length = - length_sum(flex_lines.iter().map(|line| line.cross_size)); + length_sum(flex_lines.iter().map(|line| line.cross_size)) + total_cross_axis_gap; if line_total_cross < min_inner_cross { let remaining = min_inner_cross - line_total_cross; @@ -980,11 +1017,19 @@ impl FlexBox for LayoutUnit { // 2. Align the items along the main-axis per justify-content. for line in &mut flex_lines { - let used_space: T::Length = length_sum( - line.items - .iter() - .map(|child| child.outer_target_size.main_size(dir)), + let total_main_axis_gap = sum_axis_gaps( + style + .row_gap() + .resolve(requested_inner_size.main_size(dir), node) + .or_zero(), + line.items.len(), ); + let used_space: T::Length = total_main_axis_gap + + length_sum( + line.items + .iter() + .map(|child| child.outer_target_size.main_size(dir)), + ); let free_space = inner_container_size.main_size(dir) - used_space; let mut num_auto_margins = 0; @@ -1021,63 +1066,68 @@ impl FlexBox for LayoutUnit { } } else { let num_items = line.items.len() as i32; + let is_reversed = main_dir_rev == AxisReverse::Reversed; for (index, flex_child) in line.items.iter_mut().enumerate() { let is_first = index == 0; - flex_child.extra_offset_main = match style.justify_content() { - JustifyContent::FlexStart - | JustifyContent::Start - | JustifyContent::Baseline - | JustifyContent::Stretch => T::Length::zero(), - JustifyContent::Center => { - if is_first { - free_space.div_i32(2) - } else { - T::Length::zero() - } - } - JustifyContent::FlexEnd | JustifyContent::End => { - if is_first { - free_space - } else { - T::Length::zero() - } - } - JustifyContent::Left => match main_dir_rev { - AxisReverse::NotReversed => T::Length::zero(), - AxisReverse::Reversed => { - if is_first { + let gap = style + .row_gap() + .resolve(requested_inner_size.main_size(dir), node) + .or_zero(); + flex_child.extra_offset_main = if is_first { + match style.justify_content() { + JustifyContent::Start + | JustifyContent::Baseline + | JustifyContent::Stretch => T::Length::zero(), + JustifyContent::FlexStart => T::Length::zero(), + JustifyContent::Center => free_space.div_i32(2), + JustifyContent::FlexEnd => free_space, + JustifyContent::End => free_space, + JustifyContent::Left => { + if is_reversed { free_space } else { T::Length::zero() } } - }, - JustifyContent::Right => match main_dir_rev { - AxisReverse::NotReversed => { - if is_first { + JustifyContent::Right => { + if is_reversed { + T::Length::zero() + } else { free_space + } + } + JustifyContent::SpaceBetween => T::Length::zero(), + JustifyContent::SpaceAround => { + if free_space >= T::Length::zero() { + free_space.div_i32(num_items).div_i32(2) } else { - T::Length::zero() + free_space.div_i32(2) } } - AxisReverse::Reversed => T::Length::zero(), - }, - JustifyContent::SpaceBetween => { - if is_first { - T::Length::zero() - } else { - free_space.div_i32(num_items - 1) + JustifyContent::SpaceEvenly => { + if free_space >= T::Length::zero() { + free_space.div_i32(num_items + 1) + } else { + free_space.div_i32(2) + } } } - JustifyContent::SpaceAround => { - if is_first { - free_space.div_i32(num_items).div_i32(2) - } else { - free_space.div_i32(num_items) - } + } else { + let free_space = free_space.max(T::Length::zero()); + gap + match style.justify_content() { + JustifyContent::FlexStart + | JustifyContent::Start + | JustifyContent::Baseline + | JustifyContent::Stretch => T::Length::zero(), + JustifyContent::Center => T::Length::zero(), + JustifyContent::FlexEnd | JustifyContent::End => T::Length::zero(), + JustifyContent::Left => T::Length::zero(), + JustifyContent::Right => T::Length::zero(), + JustifyContent::SpaceBetween => free_space.div_i32(num_items - 1), + JustifyContent::SpaceAround => free_space.div_i32(num_items), + JustifyContent::SpaceEvenly => free_space.div_i32(num_items + 1), } - JustifyContent::SpaceEvenly => free_space.div_i32(num_items + 1), - }; + } } } } @@ -1162,45 +1212,57 @@ impl FlexBox for LayoutUnit { } // 16. Align all flex lines per align-content. - let free_space = - (inner_container_size.cross_size(dir) - total_cross_size).max(T::Length::zero()); + let num_lines = flex_lines.len() as i32; + let gap = style + .column_gap() + .resolve(requested_inner_size.main_size(dir), node) + .or_zero(); + let total_cross_axis_gap = sum_axis_gaps(gap, flex_lines.len()); + let free_space = (inner_container_size.cross_size(dir) - total_cross_size) + .max(T::Length::zero()) + + total_cross_axis_gap; for (index, line) in flex_lines.iter_mut().enumerate() { let is_first = index == 0; - line.extra_offset_cross = match style.align_content() { - AlignContent::FlexStart - | AlignContent::Start - | AlignContent::Normal - | AlignContent::Baseline => T::Length::zero(), - AlignContent::FlexEnd | AlignContent::End => { - if is_first { - free_space - } else { + line.extra_offset_cross = if is_first { + match style.align_content() { + AlignContent::Start | AlignContent::Normal | AlignContent::Baseline => { T::Length::zero() } - } - AlignContent::Center => { - if is_first { - free_space.div_i32(2) - } else { - T::Length::zero() + AlignContent::FlexStart => T::Length::zero(), + AlignContent::End => free_space, + AlignContent::FlexEnd => free_space, + AlignContent::Center => free_space.div_i32(2), + AlignContent::Stretch => T::Length::zero(), + AlignContent::SpaceBetween => T::Length::zero(), + AlignContent::SpaceEvenly => { + if free_space >= T::Length::zero() { + free_space.div_i32(num_lines + 1) + } else { + free_space.div_i32(2) + } } - } - AlignContent::Stretch => T::Length::zero(), - AlignContent::SpaceBetween => { - if is_first { - T::Length::zero() - } else { - free_space.div_i32(num_lines - 1) + AlignContent::SpaceAround => { + if free_space >= T::Length::zero() { + free_space.div_i32(num_lines).div_i32(2) + } else { + free_space.div_i32(2) + } } } - AlignContent::SpaceEvenly => free_space.div_i32(num_lines + 1), - AlignContent::SpaceAround => { - if is_first { - free_space.div_i32(num_lines).div_i32(2) - } else { - free_space.div_i32(num_lines) + } else { + gap + match style.align_content() { + AlignContent::Start | AlignContent::Normal | AlignContent::Baseline => { + T::Length::zero() } + AlignContent::FlexStart => T::Length::zero(), + AlignContent::End => T::Length::zero(), + AlignContent::FlexEnd => T::Length::zero(), + AlignContent::Center => T::Length::zero(), + AlignContent::Stretch => T::Length::zero(), + AlignContent::SpaceBetween => free_space.div_i32(num_lines - 1), + AlignContent::SpaceEvenly => free_space.div_i32(num_lines + 1), + AlignContent::SpaceAround => free_space.div_i32(num_lines), } }; } diff --git a/float-pigment-layout/src/lib.rs b/float-pigment-layout/src/lib.rs index 99c80d8..15b56c2 100644 --- a/float-pigment-layout/src/lib.rs +++ b/float-pigment-layout/src/lib.rs @@ -253,6 +253,12 @@ pub trait LayoutStyle { fn text_align(&self) -> TextAlign { TextAlign::Start } + fn column_gap(&self) -> DefLength { + DefLength::Undefined + } + fn row_gap(&self) -> DefLength { + DefLength::Undefined + } } /// The layout information of a tree node.