diff --git a/float-pigment-layout/src/algo/flex_box.rs b/float-pigment-layout/src/algo/flex_box.rs index c4a4e94..be302e5 100644 --- a/float-pigment-layout/src/algo/flex_box.rs +++ b/float-pigment-layout/src/algo/flex_box.rs @@ -1303,9 +1303,11 @@ impl FlexBox for LayoutUnit { } }; let baseline_diff = child.gen_origin( - dir, - main_dir_rev, - cross_dir_rev, + AxisInfo { + main_dir_rev, + cross_dir_rev, + dir, + }, *container_size, offset_main, offset_cross, @@ -1344,9 +1346,11 @@ impl FlexBox for LayoutUnit { &ret, border, padding_border, - dir, - main_dir_rev, - AxisReverse::NotReversed, + AxisInfo { + dir, + main_dir_rev, + cross_dir_rev: AxisReverse::NotReversed, + }, true, ); self.result = Rect::new(Point::zero(), ret.size.0); diff --git a/float-pigment-layout/src/algo/flow.rs b/float-pigment-layout/src/algo/flow.rs index 395fd6a..8a43363 100644 --- a/float-pigment-layout/src/algo/flow.rs +++ b/float-pigment-layout/src/algo/flow.rs @@ -297,9 +297,10 @@ impl Flow for LayoutUnit { &ret, border, padding_border, - axis_info.dir, - axis_info.main_dir_rev, - AxisReverse::NotReversed, + AxisInfo { + cross_dir_rev: AxisReverse::NotReversed, + ..axis_info + }, false, ); self.result = Rect::new(Point::zero(), ret.size.0); @@ -491,9 +492,10 @@ impl Flow for LayoutUnit { .or_zero() }; let baseline_diff = child.gen_origin( - axis_info.dir, - axis_info.main_dir_rev, - AxisReverse::NotReversed, + AxisInfo { + cross_dir_rev: AxisReverse::NotReversed, + ..axis_info + }, node_inner_size.or_zero(), main_offset, cross_offset, @@ -616,9 +618,10 @@ impl Flow for LayoutUnit { child.result = Rect::new(Point::zero(), child_res.size); child.cache.touch(child_node); child.gen_origin( - axis_info.dir, - axis_info.main_dir_rev, - AxisReverse::NotReversed, + AxisInfo { + cross_dir_rev: AxisReverse::NotReversed, + ..axis_info + }, node_inner_size.or_zero(), main_offset + child_origin.main_axis(axis_info.dir), cross_offset + child_origin.cross_axis(axis_info.dir), @@ -671,9 +674,7 @@ impl Flow for LayoutUnit { }, border, padding_border, - axis_info.dir, - axis_info.main_dir_rev, - axis_info.cross_dir_rev, + axis_info, false, ) } diff --git a/float-pigment-layout/src/special_positioned.rs b/float-pigment-layout/src/special_positioned.rs index eccf4cb..b27e93a 100644 --- a/float-pigment-layout/src/special_positioned.rs +++ b/float-pigment-layout/src/special_positioned.rs @@ -24,9 +24,7 @@ pub(crate) fn compute_special_position_children( node_result: &ComputeResult, border: Edge, padding_border: Edge, - dir: AxisDirection, - main_dir_rev: AxisReverse, - cross_dir_rev: AxisReverse, + axis_info: AxisInfo, accept_flex_props: bool, ) { let style: &::Style = node.style(); @@ -48,345 +46,89 @@ pub(crate) fn compute_special_position_children( child.clear_display_none_result(child_node); return; } - match child_style.position() { - Position::Absolute | Position::Sticky => { - compute_position_absolute( - env, - child_node, - ( - node_result, - style, - node_inner_size, - node_inner_option_size, - border, - padding_border, - ), - dir, - main_dir_rev, - cross_dir_rev, - accept_flex_props, - ); - } - Position::Fixed => compute_position_fixed( - env, - child_node, - (node_result, style, node_inner_size, border, padding_border), - dir, - main_dir_rev, - cross_dir_rev, - accept_flex_props, - ), - Position::Static => {} - Position::Relative => { - compute_position_relative(child_node, node_inner_size); - } - } + compute_special_position( + env, + child_node, + ParentInfo { + compute_result: node_result, + style, + inner_size: &node_inner_size, + inner_option_size: &node_inner_option_size, + border: &border, + padding_border: &padding_border, + }, + axis_info, + accept_flex_props, + child_style.position(), + ); }; node.tree_visitor() .for_each_child(|child_node, _| f(child_node)); } -#[allow(clippy::type_complexity)] -pub(crate) fn compute_position_fixed( +pub(crate) struct ParentInfo<'a, T: LayoutTreeNode> { + pub(crate) compute_result: &'a ComputeResult, + pub(crate) style: &'a T::Style, + pub(crate) inner_size: &'a Normalized>, + pub(crate) inner_option_size: &'a Normalized>, + pub(crate) border: &'a Edge, + pub(crate) padding_border: &'a Edge, +} + +#[inline] +pub(crate) fn compute_special_position( env: &mut T::Env, node: &T, - parent: ( - &ComputeResult, - &T::Style, - Normalized>, - Edge, - Edge, - ), - dir: AxisDirection, - main_dir_rev: AxisReverse, - cross_dir_rev: AxisReverse, + parent: ParentInfo, + axis_info: AxisInfo, accept_flex_props: bool, + position: Position, ) { - let (parent_node_result, parent_style, parent_inner_size, parent_border, parent_padding_border) = - parent; + if position == Position::Static { + return; + } let mut layout_unit = node.layout_node().unit(); let style = node.style(); - let container_width = env.screen_width(); - let container_height = env.screen_height(); - let container_option_size = OptionSize::new( - OptionNum::some(container_width), - OptionNum::some(container_height), - ); - let container_size = Size::new(container_width, container_height); - let left = style.left().resolve_num(container_width, node); - let right = style.right().resolve_num(container_width, node); - let top = style.top().resolve_num(container_height, node); - let bottom = style.bottom().resolve_num(container_height, node); - let (margin, border, padding_border) = - layout_unit.margin_border_padding(node, container_option_size); - let css_size = - layout_unit.css_border_box_size(node, container_option_size, border, padding_border); - let width = css_size.width.or(if left.is_some() && right.is_some() { - OptionNum::some(container_width) - - left - - right - - margin.left.or_zero() - - margin.right.or_zero() - } else { - OptionNum::none() - }); - let height = css_size.height.or(if top.is_some() && bottom.is_some() { - OptionNum::some(container_height) - - top - - bottom - - margin.top.or_zero() - - margin.bottom.or_zero() + + let container_size = if position == Position::Fixed { + Size::new(env.screen_width(), env.screen_height()) } else { - OptionNum::none() - }); - let min_max_limit = - layout_unit.normalized_min_max_limit(node, container_option_size, border, padding_border); - let size = min_max_limit.normalized_size(OptionSize::new(width, height)); - let max_content_width = size.width.unwrap_or( - container_width - - left.or_zero() - - right.or_zero() - - margin.left.or_zero() - - margin.right.or_zero(), - ); - let max_content_height = size.height.unwrap_or( - container_height - - top.or_zero() - - bottom.or_zero() - - margin.top.or_zero() - - margin.bottom.or_zero(), - ); - let max_content = min_max_limit.normalized_size(OptionSize::new( - OptionNum::some(max_content_width), - OptionNum::some(max_content_height), - )); - let result = if size.width.is_none() || size.height.is_none() { - let auto_size = layout_unit - .compute_internal( - env, - node, - ComputeRequest { - size, - parent_inner_size: Normalized(container_option_size), - max_content, - kind: ComputeRequestKind::AllSize, - parent_is_block: false, - }, - ) - .size; - layout_unit.compute_internal( - env, - node, - ComputeRequest { - size: Normalized(OptionSize::new( - OptionNum::some(auto_size.width), - OptionNum::some(auto_size.height), - )), - parent_inner_size: Normalized(container_option_size), - max_content, - kind: ComputeRequestKind::Position, - parent_is_block: false, - }, - ) + **parent.inner_size + }; + let container_option_size = if position == Position::Fixed { + Normalized(OptionSize::new( + OptionNum::some(container_size.width), + OptionNum::some(container_size.height), + )) } else { - layout_unit.compute_internal( - env, - node, - ComputeRequest { - size, - parent_inner_size: Normalized(container_option_size), - max_content, - kind: ComputeRequestKind::Position, - parent_is_block: false, - }, - ) + *parent.inner_option_size }; - let free_space = container_size - result.size.0; - let parent_free_space = *parent_inner_size - result.size.0; - macro_rules! axis { - ( - $main_start: ident, - $main_end: ident, - $cross_start: ident, - $cross_end: ident, - $main_size: ident, - $cross_size: ident, - $main_axis: ident, - $cross_axis: ident, - ) => {{ - let offset_main = if $main_start.val().is_some() - && $main_end.val().is_some() - && margin.$main_start.val().is_none() - && margin.$main_end.val().is_none() - { - let main_start = $main_start.val().unwrap_or(T::Length::zero()); - let main_end = $main_end.val().unwrap_or(T::Length::zero()); - let free_space_main_size = container_size.$main_size; - main_start + (free_space_main_size - main_end - main_start).div_i32(2) - - result.size.0.$main_size.div_i32(2) - } else { - let offset_main = if let Some(x) = $main_start.val() { - x - } else if let Some(x) = $main_end.val() { - free_space.$main_size - x - } else if accept_flex_props { - match parent_style.justify_content() { - JustifyContent::SpaceBetween - | JustifyContent::FlexStart - | JustifyContent::Start - | JustifyContent::Stretch - | JustifyContent::Baseline => parent_padding_border.$main_start, - JustifyContent::FlexEnd | JustifyContent::End => { - parent_border.$main_start + parent_free_space.$main_size - - (parent_padding_border.$main_end - parent_border.$main_end) - } - JustifyContent::Left => match main_dir_rev { - AxisReverse::NotReversed => parent_padding_border.$main_start, - AxisReverse::Reversed => { - parent_border.$main_start + parent_free_space.$main_size - - (parent_padding_border.$main_end - parent_border.$main_end) - } - }, - JustifyContent::Right => match main_dir_rev { - AxisReverse::NotReversed => { - parent_border.$main_start + parent_free_space.$main_size - - (parent_padding_border.$main_end - parent_border.$main_end) - } - AxisReverse::Reversed => parent_padding_border.$main_start, - }, - JustifyContent::SpaceEvenly - | JustifyContent::SpaceAround - | JustifyContent::Center => { - parent_border.$main_start + parent_free_space.$main_size.div_i32(2) - } - } - } else { - T::Length::zero() - }; - let offset_main = if let Some(x) = margin.$main_start.val() { - offset_main + x - } else if let Some(x) = margin.$main_end.val() { - offset_main - x - } else { - offset_main - }; - offset_main - }; - let offset_cross = if $cross_start.val().is_some() - && $cross_end.val().is_some() - && margin.$cross_start.val().is_none() - && margin.$cross_end.val().is_none() - { - let cross_start = $cross_start.val().unwrap_or(T::Length::zero()); - let cross_end = $cross_end.val().unwrap_or(T::Length::zero()); - let free_space_cross_size = container_size.$cross_size; - cross_start + (free_space_cross_size - cross_end - cross_start).div_i32(2) - - (result.size.0.$cross_size.div_i32(2)) - } else { - let offset_cross = if let Some(x) = $cross_start.val() { - x - } else if let Some(x) = $cross_end.val() { - free_space.$cross_size - x - } else if accept_flex_props { - match algo::flex_box::align_self::(style, parent_style) { - AlignSelf::FlexStart - | AlignSelf::Start - | AlignSelf::SelfStart - | AlignSelf::Normal => parent_padding_border.$cross_start, - AlignSelf::FlexEnd | AlignSelf::End | AlignSelf::SelfEnd => { - parent_border.$cross_start + parent_free_space.$cross_size - - (parent_padding_border.$cross_end - parent_border.$cross_end) - } - AlignSelf::Center => { - parent_border.$cross_start + parent_free_space.$cross_size.div_i32(2) - } - AlignSelf::Baseline => { - parent_node_result.first_baseline_ascent.$cross_axis - - result.first_baseline_ascent.$cross_axis - } - AlignSelf::Auto | AlignSelf::Stretch => parent_padding_border.$cross_start, - } - } else { - T::Length::zero() - }; - let offset_cross = if let Some(x) = margin.$cross_start.val() { - offset_cross + x - } else if let Some(x) = margin.$cross_end.val() { - offset_cross - x - } else { - offset_cross - }; - offset_cross - }; - - layout_unit.gen_origin( - dir, - main_dir_rev, - cross_dir_rev, - container_size, - offset_main, - offset_cross, - ); - }}; - } + let left = style.left().resolve_num(container_size.width, node); + let right = style.right().resolve_num(container_size.width, node); + let top = style.top().resolve_num(container_size.height, node); + let bottom = style.bottom().resolve_num(container_size.height, node); - match (dir, main_dir_rev) { - (AxisDirection::Horizontal, AxisReverse::NotReversed) => { - axis!(left, right, top, bottom, width, height, x, y,); + if position == Position::Relative { + if let Some(left) = left.val() { + layout_unit.result.origin.x += left; + } else if let Some(right) = right.val() { + layout_unit.result.origin.x -= right; } - (AxisDirection::Horizontal, AxisReverse::Reversed) => { - axis!(right, left, top, bottom, width, height, x, y,); + if let Some(top) = top.val() { + layout_unit.result.origin.y += top; + } else if let Some(bottom) = bottom.val() { + layout_unit.result.origin.y -= bottom; } - (AxisDirection::Vertical, AxisReverse::NotReversed) => { - axis!(top, bottom, left, right, height, width, y, x,); - } - (AxisDirection::Vertical, AxisReverse::Reversed) => { - axis!(top, bottom, right, left, height, width, y, x,); - } - }; -} - -#[allow(clippy::too_many_arguments, clippy::type_complexity)] -pub(crate) fn compute_position_absolute( - env: &mut T::Env, - node: &T, - parent: ( - &ComputeResult, - &T::Style, - Normalized>, - Normalized>, - Edge, - Edge, - ), - dir: AxisDirection, - main_dir_rev: AxisReverse, - cross_dir_rev: AxisReverse, - accept_flex_props: bool, -) { - let ( - parent_node_result, - parent_style, - parent_inner_size, - parent_inner_option_size, - parent_border, - parent_padding_border, - ) = parent; - let mut layout_unit = node.layout_node().unit(); - let style = node.style(); - let container_width = parent_inner_size.width; - let container_height = parent_inner_size.height; - let left = style.left().resolve_num(parent_inner_size.width, node); - let right = style.right().resolve_num(parent_inner_size.width, node); - let top = style.top().resolve_num(parent_inner_size.height, node); - let bottom = style.bottom().resolve_num(parent_inner_size.height, node); + return; + } let (margin, border, padding_border) = - layout_unit.margin_border_padding(node, *parent_inner_option_size); + layout_unit.margin_border_padding(node, *container_option_size); let css_size = - layout_unit.css_border_box_size(node, *parent_inner_option_size, border, padding_border); + layout_unit.css_border_box_size(node, *container_option_size, border, padding_border); let width = css_size.width.or(if left.is_some() && right.is_some() { - OptionNum::some(container_width) + OptionNum::some(container_size.width) - left - right - margin.left.or_zero() @@ -395,7 +137,7 @@ pub(crate) fn compute_position_absolute( OptionNum::none() }); let height = css_size.height.or(if top.is_some() && bottom.is_some() { - OptionNum::some(container_height) + OptionNum::some(container_size.height) - top - bottom - margin.top.or_zero() @@ -403,30 +145,24 @@ pub(crate) fn compute_position_absolute( } else { OptionNum::none() }); - let min_max_limit = layout_unit.normalized_min_max_limit( - node, - *parent_inner_option_size, - border, - padding_border, - ); + let min_max_limit = + layout_unit.normalized_min_max_limit(node, *container_option_size, border, padding_border); let size = min_max_limit.normalized_size(OptionSize::new(width, height)); - let max_content_width = size.width.unwrap_or( - container_width - - left.or_zero() - - right.or_zero() - - margin.left.or_zero() - - margin.right.or_zero(), - ); - let max_content_height = size.height.unwrap_or( - container_height - - top.or_zero() - - bottom.or_zero() - - margin.top.or_zero() - - margin.bottom.or_zero(), - ); let max_content = min_max_limit.normalized_size(OptionSize::new( - OptionNum::some(max_content_width), - OptionNum::some(max_content_height), + OptionNum::some(size.width.unwrap_or( + container_size.width + - left.or_zero() + - right.or_zero() + - margin.left.or_zero() + - margin.right.or_zero(), + )), + OptionNum::some(size.height.unwrap_or( + container_size.height + - top.or_zero() + - bottom.or_zero() + - margin.top.or_zero() + - margin.bottom.or_zero(), + )), )); let result = if size.width.is_none() || size.height.is_none() { @@ -436,7 +172,7 @@ pub(crate) fn compute_position_absolute( node, ComputeRequest { size, - parent_inner_size: parent_inner_option_size, + parent_inner_size: container_option_size, max_content, kind: ComputeRequestKind::AllSize, parent_is_block: false, @@ -451,7 +187,7 @@ pub(crate) fn compute_position_absolute( OptionNum::some(auto_size.width), OptionNum::some(auto_size.height), )), - parent_inner_size: parent_inner_option_size, + parent_inner_size: container_option_size, max_content, kind: ComputeRequestKind::Position, parent_is_block: false, @@ -463,171 +199,260 @@ pub(crate) fn compute_position_absolute( node, ComputeRequest { size, - parent_inner_size: parent_inner_option_size, + parent_inner_size: container_option_size, max_content, kind: ComputeRequestKind::Position, parent_is_block: false, }, ) }; - let free_space = *parent_inner_size - result.size.0; + let free_space = container_size - result.size.0; + let parent_free_space = **parent.inner_size - result.size.0; + let (main_start, main_end, cross_start, cross_end) = + match (axis_info.dir, axis_info.main_dir_rev) { + (AxisDirection::Horizontal, AxisReverse::NotReversed) => (left, right, top, bottom), + (AxisDirection::Horizontal, AxisReverse::Reversed) => (right, left, top, bottom), + (AxisDirection::Vertical, AxisReverse::NotReversed) => (top, bottom, left, right), + (AxisDirection::Vertical, AxisReverse::Reversed) => (top, bottom, right, left), + }; - macro_rules! axis { - ( - $main_start: ident, - $main_end: ident, - $cross_start: ident, - $cross_end: ident, - $main_size: ident, - $cross_size: ident, - $main_axis: ident, - $cross_axis: ident, - ) => {{ - let offset_main = if $main_start.val().is_some() - && $main_end.val().is_some() - && margin.$main_start.val().is_none() - && margin.$main_end.val().is_none() - { - let main_start = $main_start.val().unwrap_or(T::Length::zero()); - let main_end = $main_end.val().unwrap_or(T::Length::zero()); - let free_space_main_size = parent_inner_size.$main_size; - main_start + (free_space_main_size - main_end - main_start).div_i32(2) - - parent_border.$main_start - - result.size.0.$main_size.div_i32(2) - } else { - let offset_main = if let Some(x) = $main_start.val() { - parent_border.$main_start + x - } else if let Some(x) = $main_end.val() { - parent_border.$main_start + free_space.$main_size - x - } else if accept_flex_props { - match parent_style.justify_content() { - JustifyContent::SpaceBetween - | JustifyContent::FlexStart - | JustifyContent::Start - | JustifyContent::Stretch - | JustifyContent::Baseline => parent_padding_border.$main_start, - JustifyContent::FlexEnd | JustifyContent::End => { - parent_border.$main_start + free_space.$main_size - - (parent_padding_border.$main_end - parent_border.$main_end) - } - JustifyContent::Left => match main_dir_rev { - AxisReverse::NotReversed => parent_padding_border.$main_start, - AxisReverse::Reversed => { - parent_border.$main_start + free_space.$main_size - - (parent_padding_border.$main_end - parent_border.$main_end) - } - }, - JustifyContent::Right => match main_dir_rev { - AxisReverse::NotReversed => { - parent_border.$main_start + free_space.$main_size - - (parent_padding_border.$main_end - parent_border.$main_end) - } - AxisReverse::Reversed => parent_padding_border.$main_start, - }, - JustifyContent::SpaceEvenly - | JustifyContent::SpaceAround - | JustifyContent::Center => { - let parent_padding = parent_padding_border - parent_border; - let free_content_main_size = free_space.$main_size - - parent_padding.$main_start - - parent_padding.$main_end; - parent_border.$main_start - + parent_padding.$main_start - + free_content_main_size.div_i32(2) - } - } - } else { - parent_padding_border.$main_start - }; - let offset_main = if let Some(x) = margin.$main_start.val() { - offset_main + x - } else if let Some(x) = margin.$main_end.val() { - offset_main - x - } else { - offset_main - }; - offset_main - }; + let offset_main = if main_start.val().is_some() + && main_end.val().is_some() + && margin + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + .val() + .is_none() + && margin + .main_axis_end(axis_info.dir, axis_info.main_dir_rev) + .val() + .is_none() + { + let main_start = main_start.val().unwrap_or(T::Length::zero()); + let main_end = main_end.val().unwrap_or(T::Length::zero()); + let free_space_main_size = container_size.main_size(axis_info.dir); - let offset_cross = if $cross_start.val().is_some() - && $cross_end.val().is_some() - && margin.$cross_start.val().is_none() - && margin.$cross_end.val().is_none() - { - let cross_start = $cross_start.val().unwrap_or(T::Length::zero()); - let cross_end = $cross_end.val().unwrap_or(T::Length::zero()); - let free_space_cross_size = parent_inner_size.$cross_size; - cross_start + (free_space_cross_size - cross_end - cross_start).div_i32(2) - - parent_border.$cross_start - - (result.size.0.$cross_size.div_i32(2)) + if position == Position::Fixed { + main_start + (free_space_main_size - main_end - main_start).div_i32(2) + - result.size.0.main_size(axis_info.dir).div_i32(2) + } else { + main_start + (free_space_main_size - main_end - main_start).div_i32(2) + - parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + - result.size.0.main_size(axis_info.dir).div_i32(2) + } + } else { + let offset_main = if let Some(x) = main_start.val() { + if position == Position::Fixed { + x + } else { + parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + x + } + } else if let Some(x) = main_end.val() { + if position == Position::Fixed { + free_space.main_size(axis_info.dir) - x } else { - let offset_cross = if let Some(x) = $cross_start.val() { - x + parent_border.$cross_start - } else if let Some(x) = $cross_end.val() { - parent_border.$cross_start + free_space.$cross_size - x - } else if accept_flex_props { - match algo::flex_box::align_self::(style, parent_style) { - AlignSelf::FlexStart - | AlignSelf::Start - | AlignSelf::SelfStart - | AlignSelf::Normal => parent_padding_border.$cross_start, - AlignSelf::FlexEnd | AlignSelf::End | AlignSelf::SelfEnd => { - parent_border.$cross_start + free_space.$cross_size - - (parent_padding_border.$cross_end - parent_border.$cross_end) - } - AlignSelf::Center => { - let parent_padding = parent_padding_border - parent_border; - let free_content_cross_size = free_space.$cross_size - - parent_padding.$cross_start - - parent_padding.$cross_end; - parent_border.$cross_start - + parent_padding.$cross_start - + free_content_cross_size.div_i32(2) - } - AlignSelf::Baseline => { - parent_node_result.first_baseline_ascent.$cross_axis - - result.first_baseline_ascent.$cross_axis - } - AlignSelf::Auto | AlignSelf::Stretch => parent_padding_border.$cross_start, + parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_free_space.main_size(axis_info.dir) + - x + } + } else if accept_flex_props { + match parent.style.justify_content() { + JustifyContent::SpaceBetween + | JustifyContent::FlexStart + | JustifyContent::Start + | JustifyContent::Stretch + | JustifyContent::Baseline => parent + .padding_border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev), + JustifyContent::FlexEnd | JustifyContent::End => { + parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_free_space.main_size(axis_info.dir) + - (parent + .padding_border + .main_axis_end(axis_info.dir, axis_info.main_dir_rev) + - parent + .border + .main_axis_end(axis_info.dir, axis_info.main_dir_rev)) + } + JustifyContent::Left => match axis_info.main_dir_rev { + AxisReverse::NotReversed => parent + .padding_border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev), + AxisReverse::Reversed => { + parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_free_space.main_size(axis_info.dir) + - (parent + .padding_border + .main_axis_end(axis_info.dir, axis_info.main_dir_rev) + - parent + .border + .main_axis_end(axis_info.dir, axis_info.main_dir_rev)) } - } else { - parent_padding_border.$cross_start - }; - let offset_cross = if let Some(x) = margin.$cross_start.val() { - offset_cross + x - } else if let Some(x) = margin.$cross_end.val() { - offset_cross - x - } else { - offset_cross - }; - offset_cross - }; - - layout_unit.gen_origin( - dir, - main_dir_rev, - cross_dir_rev, - *parent_inner_size, - offset_main, - offset_cross, - ); - }}; - } + }, + JustifyContent::Right => match axis_info.main_dir_rev { + AxisReverse::NotReversed => { + parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_free_space.main_size(axis_info.dir) + - (parent + .padding_border + .main_axis_end(axis_info.dir, axis_info.main_dir_rev) + - parent + .border + .main_axis_end(axis_info.dir, axis_info.main_dir_rev)) + } + AxisReverse::Reversed => parent + .padding_border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev), + }, + JustifyContent::SpaceEvenly + | JustifyContent::SpaceAround + | JustifyContent::Center => { + let parent_padding = *parent.padding_border - *parent.border; + let free_content_main_size = parent_free_space.main_size(axis_info.dir) + - parent_padding.main_axis_start(axis_info.dir, axis_info.main_dir_rev) + - parent_padding.main_axis_end(axis_info.dir, axis_info.main_dir_rev); + parent + .border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_padding.main_axis_start(axis_info.dir, axis_info.main_dir_rev) + + free_content_main_size.div_i32(2) + } + } + } else { + parent + .padding_border + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + }; + let offset_main = if let Some(x) = margin + .main_axis_start(axis_info.dir, axis_info.main_dir_rev) + .val() + { + offset_main + x + } else if let Some(x) = margin + .main_axis_end(axis_info.dir, axis_info.main_dir_rev) + .val() + { + offset_main - x + } else { + offset_main + }; + offset_main + }; - match (dir, main_dir_rev) { - (AxisDirection::Horizontal, AxisReverse::NotReversed) => { - axis!(left, right, top, bottom, width, height, x, y,); - } - (AxisDirection::Horizontal, AxisReverse::Reversed) => { - axis!(right, left, top, bottom, width, height, x, y,); - } - (AxisDirection::Vertical, AxisReverse::NotReversed) => { - axis!(top, bottom, left, right, height, width, y, x,); - } - (AxisDirection::Vertical, AxisReverse::Reversed) => { - axis!(top, bottom, right, left, height, width, y, x,); - } + let offset_cross = if cross_end.val().is_some() + && cross_end.val().is_some() + && margin + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + .val() + .is_none() + && margin + .cross_axis_end(axis_info.dir, axis_info.main_dir_rev) + .val() + .is_none() + { + let cross_start = cross_start.val().unwrap_or(T::Length::zero()); + let cross_end = cross_end.val().unwrap_or(T::Length::zero()); + let free_space_cross_size = container_size.cross_size(axis_info.dir); + cross_start + (free_space_cross_size - cross_end - cross_start).div_i32(2) + - parent + .border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + - (result.size.0.cross_size(axis_info.dir).div_i32(2)) + } else { + let offset_cross = if let Some(x) = cross_start.val() { + if position == Position::Fixed { + x + } else { + x + parent + .border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + } + } else if let Some(x) = cross_end.val() { + if position == Position::Fixed { + free_space.cross_size(axis_info.dir) - x + } else { + parent + .border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_free_space.cross_size(axis_info.dir) + - x + } + } else if accept_flex_props { + match algo::flex_box::align_self::(style, parent.style) { + AlignSelf::FlexStart + | AlignSelf::Start + | AlignSelf::SelfStart + | AlignSelf::Normal => parent + .padding_border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev), + AlignSelf::FlexEnd | AlignSelf::End | AlignSelf::SelfEnd => { + parent + .border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_free_space.cross_size(axis_info.dir) + - (parent + .padding_border + .cross_axis_end(axis_info.dir, axis_info.main_dir_rev) + - parent + .border + .cross_axis_end(axis_info.dir, axis_info.main_dir_rev)) + } + AlignSelf::Center => { + let parent_padding = *parent.padding_border - *parent.border; + let free_content_cross_size = parent_free_space.cross_size(axis_info.dir) + - parent_padding.cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + - parent_padding.cross_axis_end(axis_info.dir, axis_info.main_dir_rev); + parent + .border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + + parent_padding.cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + + free_content_cross_size.div_i32(2) + } + AlignSelf::Baseline => { + parent + .compute_result + .first_baseline_ascent + .cross_axis(axis_info.dir) + - result.first_baseline_ascent.cross_axis(axis_info.dir) + } + AlignSelf::Auto | AlignSelf::Stretch => parent + .padding_border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev), + } + } else { + parent + .padding_border + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + }; + let offset_cross = if let Some(x) = margin + .cross_axis_start(axis_info.dir, axis_info.main_dir_rev) + .val() + { + offset_cross + x + } else if let Some(x) = margin + .cross_axis_end(axis_info.dir, axis_info.main_dir_rev) + .val() + { + offset_cross - x + } else { + offset_cross + }; + offset_cross }; + + layout_unit.gen_origin(axis_info, **parent.inner_size, offset_main, offset_cross); } pub(crate) fn compute_position_relative( diff --git a/float-pigment-layout/src/unit.rs b/float-pigment-layout/src/unit.rs index 7665101..c3ac0b4 100644 --- a/float-pigment-layout/src/unit.rs +++ b/float-pigment-layout/src/unit.rs @@ -646,16 +646,24 @@ impl LayoutUnit { #[inline] pub(crate) fn gen_origin( &mut self, - dir: AxisDirection, - main_dir_rev: AxisReverse, - cross_dir_rev: AxisReverse, + axis_info: AxisInfo, parent_size: Size, offset_main: T::Length, offset_cross: T::Length, ) -> Vector { - let (width, height, width_rev, height_rev) = match dir { - AxisDirection::Horizontal => (offset_main, offset_cross, main_dir_rev, cross_dir_rev), - AxisDirection::Vertical => (offset_cross, offset_main, cross_dir_rev, main_dir_rev), + let (width, height, width_rev, height_rev) = match axis_info.dir { + AxisDirection::Horizontal => ( + offset_main, + offset_cross, + axis_info.main_dir_rev, + axis_info.cross_dir_rev, + ), + AxisDirection::Vertical => ( + offset_cross, + offset_main, + axis_info.cross_dir_rev, + axis_info.main_dir_rev, + ), }; let width = match width_rev { AxisReverse::NotReversed => width,