Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 47 additions & 18 deletions float-pigment-forest/tests/custom/css_aspect_ratio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,21 @@ pub fn aspect_ratio_in_block_width_fixed() {
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

let child2 = as_ref(Node::new_ptr());
child2.set_width(DefLength::Points(Len::from_f32(100.)));
child2.set_height(DefLength::Auto);
child2.set_aspect_ratio(Some(0.5 / 1.));
container.append_child(convert_node_ref_to_ptr(child2));

root.layout(
OptionSize::new(OptionNum::some(Len::from_f32(400.)), OptionNum::none()),
Size::new(Len::from_f32(0.), Len::from_f32(0.)),
);

assert_eq!(child.layout_position().width, 100.);
assert_eq!(child.layout_position().height, 50.);
assert_eq!(child2.layout_position().width, 100.);
assert_eq!(child2.layout_position().height, 200.);
}
}

Expand All @@ -338,13 +346,21 @@ pub fn aspect_ratio_in_block_height_fixed() {
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

let child2 = as_ref(Node::new_ptr());
child2.set_width(DefLength::Auto);
child2.set_height(DefLength::Points(Len::from_f32(200.)));
child2.set_aspect_ratio(Some(0.5 / 1.));
container.append_child(convert_node_ref_to_ptr(child2));

root.layout(
OptionSize::new(OptionNum::some(Len::from_f32(400.)), OptionNum::none()),
Size::new(Len::from_f32(0.), Len::from_f32(0.)),
);

assert_eq!(child.layout_position().width, 200.);
assert_eq!(child.layout_position().height, 100.);
assert_eq!(child2.layout_position().width, 100.);
assert_eq!(child2.layout_position().height, 200.);
}
}

Expand All @@ -360,9 +376,20 @@ pub fn aspect_ratio_in_parent_block_cross_size_fixed() {

let child = as_ref(Node::new_ptr());
child.set_width(DefLength::Auto);
child.set_aspect_ratio(Some(1. / 1.));
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

let container2 = as_ref(Node::new_ptr());
container2.set_width(DefLength::Auto);
container2.set_height(DefLength::Points(Len::from_f32(300.)));
container2.set_writing_mode(WritingMode::VerticalLr);
root.append_child(convert_node_ref_to_ptr(container2));

let child2 = as_ref(Node::new_ptr());
child2.set_width(DefLength::Auto);
child2.set_aspect_ratio(Some(0.5 / 1.));
container2.append_child(convert_node_ref_to_ptr(child2));

root.layout(
OptionSize::new(OptionNum::some(Len::from_f32(400.)), OptionNum::none()),
Size::new(Len::from_f32(0.), Len::from_f32(0.)),
Expand All @@ -381,7 +408,9 @@ pub fn aspect_ratio_in_parent_block_cross_size_fixed() {
);

assert_eq!(child.layout_position().width, 300.);
assert_eq!(child.layout_position().height, 300.);
assert_eq!(child.layout_position().height, 150.);
assert_eq!(child2.layout_position().width, 150.);
assert_eq!(child2.layout_position().height, 300.);
}
}

Expand All @@ -398,7 +427,7 @@ pub fn aspect_ratio_with_min_width_constraint() {
child.set_width(DefLength::Auto);
child.set_height(DefLength::Auto);
child.set_min_width(DefLength::Points(Len::from_f32(400.)));
child.set_aspect_ratio(Some(1. / 1.));
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

root.layout(
Expand All @@ -419,7 +448,7 @@ pub fn aspect_ratio_with_min_width_constraint() {
);

assert_eq!(child.layout_position().width, 400.);
assert_eq!(child.layout_position().height, 400.);
assert_eq!(child.layout_position().height, 200.);
}
}

Expand All @@ -436,7 +465,7 @@ pub fn aspect_ratio_with_max_width_constraint() {
child.set_width(DefLength::Auto);
child.set_height(DefLength::Auto);
child.set_max_width(DefLength::Points(Len::from_f32(80.)));
child.set_aspect_ratio(Some(1. / 1.));
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

root.layout(
Expand All @@ -457,7 +486,7 @@ pub fn aspect_ratio_with_max_width_constraint() {
);

assert_eq!(child.layout_position().width, 80.);
assert_eq!(child.layout_position().height, 80.);
assert_eq!(child.layout_position().height, 40.);
}
}

Expand Down Expand Up @@ -516,7 +545,7 @@ pub fn aspect_ratio_block_size_with_box_sizing() {
child.set_padding_left(DefLength::Points(Len::from_f32(30.)));
child.set_border_left(DefLength::Points(Len::from_f32(20.)));
child.set_box_sizing(BoxSizing::BorderBox);
child.set_aspect_ratio(Some(1. / 1.));
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

let child2 = as_ref(Node::new_ptr());
Expand All @@ -526,7 +555,7 @@ pub fn aspect_ratio_block_size_with_box_sizing() {
child2.set_padding_left(DefLength::Points(Len::from_f32(30.)));
child2.set_border_left(DefLength::Points(Len::from_f32(20.)));
child2.set_box_sizing(BoxSizing::PaddingBox);
child2.set_aspect_ratio(Some(1. / 1.));
child2.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child2));

let child3 = as_ref(Node::new_ptr());
Expand All @@ -535,7 +564,7 @@ pub fn aspect_ratio_block_size_with_box_sizing() {
child3.set_width(DefLength::Points(Len::from_f32(50.)));
child3.set_padding_left(DefLength::Points(Len::from_f32(30.)));
child3.set_border_left(DefLength::Points(Len::from_f32(20.)));
child3.set_aspect_ratio(Some(1. / 1.));
child3.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child3));

root.layout(
Expand All @@ -556,11 +585,11 @@ pub fn aspect_ratio_block_size_with_box_sizing() {
);

assert_eq!(child.layout_position().width, 50.);
assert_eq!(child.layout_position().height, 50.);
assert_eq!(child.layout_position().height, 25.);
assert_eq!(child2.layout_position().width, 80.);
assert_eq!(child2.layout_position().height, 50.);
assert_eq!(child2.layout_position().height, 25.);
assert_eq!(child3.layout_position().width, 100.);
assert_eq!(child3.layout_position().height, 50.);
assert_eq!(child3.layout_position().height, 25.);
}
}

Expand All @@ -581,7 +610,7 @@ pub fn aspect_ratio_block_size_with_box_sizing_and_writing_mode() {
child.set_padding_top(DefLength::Points(Len::from_f32(30.)));
child.set_border_top(DefLength::Points(Len::from_f32(20.)));
child.set_box_sizing(BoxSizing::BorderBox);
child.set_aspect_ratio(Some(1. / 1.));
child.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child));

let child2 = as_ref(Node::new_ptr());
Expand All @@ -591,7 +620,7 @@ pub fn aspect_ratio_block_size_with_box_sizing_and_writing_mode() {
child2.set_padding_top(DefLength::Points(Len::from_f32(30.)));
child2.set_border_top(DefLength::Points(Len::from_f32(20.)));
child2.set_box_sizing(BoxSizing::PaddingBox);
child2.set_aspect_ratio(Some(1. / 1.));
child2.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child2));

let child3 = as_ref(Node::new_ptr());
Expand All @@ -600,7 +629,7 @@ pub fn aspect_ratio_block_size_with_box_sizing_and_writing_mode() {
child3.set_height(DefLength::Points(Len::from_f32(50.)));
child3.set_padding_top(DefLength::Points(Len::from_f32(30.)));
child3.set_border_top(DefLength::Points(Len::from_f32(20.)));
child3.set_aspect_ratio(Some(1. / 1.));
child3.set_aspect_ratio(Some(2. / 1.));
container.append_child(convert_node_ref_to_ptr(child3));

root.layout(
Expand All @@ -620,11 +649,11 @@ pub fn aspect_ratio_block_size_with_box_sizing_and_writing_mode() {
)
);

assert_eq!(child.layout_position().width, 50.);
assert_eq!(child.layout_position().width, 100.);
assert_eq!(child.layout_position().height, 50.);
assert_eq!(child2.layout_position().width, 50.);
assert_eq!(child2.layout_position().width, 100.);
assert_eq!(child2.layout_position().height, 80.);
assert_eq!(child3.layout_position().width, 50.);
assert_eq!(child3.layout_position().width, 100.);
assert_eq!(child3.layout_position().height, 100.);
}
}
125 changes: 68 additions & 57 deletions float-pigment-layout/src/algo/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,21 +365,19 @@ impl<T: LayoutTreeNode> Flow<T> for LayoutUnit<T> {
let has_aspect_ratio = aspect_ratio.is_some() && aspect_ratio.unwrap() > 0.;
if css_size.width.is_none() ^ css_size.height.is_none() && has_aspect_ratio {
if css_size.height.is_none() {
css_size.height = OptionNum::some(resolve_block_size_from_aspect_ratio(
AxisDirection::Vertical,
css_size.height = OptionNum::some(resolve_height_from_aspect_ratio(
child_border,
child_padding_border,
aspect_ratio.unwrap(),
&child_node.style().box_sizing(),
aspect_ratio.unwrap(),
css_size.width.val().unwrap(),
))
} else {
css_size.width = OptionNum::some(resolve_block_size_from_aspect_ratio(
AxisDirection::Horizontal,
css_size.width = OptionNum::some(resolve_width_from_aspect_ratio(
child_border,
child_padding_border,
aspect_ratio.unwrap(),
&child_node.style().box_sizing(),
aspect_ratio.unwrap(),
css_size.height.val().unwrap(),
))
}
Expand Down Expand Up @@ -418,14 +416,26 @@ impl<T: LayoutTreeNode> Flow<T> for LayoutUnit<T> {
css_size.set_cross_size(axis_info.dir, stretched_cross_size);
css_size.set_main_size(
axis_info.dir,
OptionNum::some(resolve_block_size_from_aspect_ratio(
axis_info.dir,
child_border,
child_padding_border,
aspect_ratio.unwrap(),
&child_node.style().box_sizing(),
stretched_cross_size.or_zero(),
)),
match axis_info.dir {
AxisDirection::Horizontal => {
OptionNum::some(resolve_width_from_aspect_ratio(
child_border,
child_padding_border,
&child_node.style().box_sizing(),
aspect_ratio.unwrap(),
stretched_cross_size.or_zero(),
))
}
AxisDirection::Vertical => {
OptionNum::some(resolve_height_from_aspect_ratio(
child_border,
child_padding_border,
&child_node.style().box_sizing(),
aspect_ratio.unwrap(),
stretched_cross_size.or_zero(),
))
}
},
);
}
}
Expand Down Expand Up @@ -814,12 +824,11 @@ pub(crate) fn transfer_min_max_size<L: LengthNum>(
let mut transfer_limit = min_max_limit.clone();

if min_max_limit.min_cross_size(main_dir).is_positive() {
let min_main_size = resolve_block_size_from_aspect_ratio(
main_dir,
let min_main_size = resolve_height_from_aspect_ratio(
border,
padding_border,
ratio,
&box_sizing,
ratio,
min_max_limit.min_cross_size(main_dir),
)
.maybe_max(css_size.height)
Expand All @@ -828,12 +837,11 @@ pub(crate) fn transfer_min_max_size<L: LengthNum>(
}

if min_max_limit.max_cross_size(main_dir).is_some() {
let mut max_main_size = resolve_block_size_from_aspect_ratio(
main_dir,
let mut max_main_size = resolve_height_from_aspect_ratio(
border,
padding_border,
ratio,
&box_sizing,
ratio,
min_max_limit.max_cross_size(main_dir).or_zero(),
)
.maybe_min(css_size.height)
Expand All @@ -848,49 +856,52 @@ pub(crate) fn transfer_min_max_size<L: LengthNum>(
transfer_limit
}

// third_party/blink/renderer/core/layout/length_utils.cc#BlockSizeFromAspectRatio
#[inline]
pub(crate) fn resolve_block_size_from_aspect_ratio<L: LengthNum>(
main_dir: AxisDirection,
pub(crate) fn resolve_width_from_aspect_ratio<L: LengthNum>(
border: Edge<L>,
padding_border: Edge<L>,
box_sizing: &BoxSizing,
ratio: f32,
determining_size: L,
) -> L {
let (dependent_padding_border, determining_padding_border) =
(padding_border.horizontal(), padding_border.vertical());
let (dependent_border, determining_border) = (border.horizontal(), border.vertical());
match box_sizing {
BoxSizing::BorderBox => dependent_padding_border.max(determining_size.mul_f32(ratio)),
BoxSizing::PaddingBox => {
(determining_size - determining_padding_border + determining_border).mul_f32(ratio)
+ dependent_padding_border
- dependent_border
}
BoxSizing::ContentBox => {
(determining_size - determining_padding_border).mul_f32(ratio)
+ dependent_padding_border
}
}
}

#[inline]
pub(crate) fn resolve_height_from_aspect_ratio<L: LengthNum>(
border: Edge<L>,
padding_border: Edge<L>,
box_sizing: &BoxSizing,
inline_size: L,
ratio: f32,
determining_size: L,
) -> L {
// (block, inline)
let (block_padding_border, inline_padding_border) = match main_dir {
AxisDirection::Vertical => (padding_border.vertical(), padding_border.horizontal()),
AxisDirection::Horizontal => (padding_border.horizontal(), padding_border.vertical()),
};
let (block_border, inline_border) = match main_dir {
AxisDirection::Vertical => (border.vertical(), border.horizontal()),
AxisDirection::Horizontal => (border.horizontal(), border.vertical()),
};
let (dependent_padding_border, determining_padding_border) =
(padding_border.vertical(), padding_border.horizontal());
let (dependent_border, determining_border) = (border.vertical(), border.horizontal());
match box_sizing {
BoxSizing::BorderBox => match main_dir {
AxisDirection::Vertical => block_padding_border.max(inline_size.div_f32(ratio)),
AxisDirection::Horizontal => block_padding_border.max(inline_size.mul_f32(ratio)),
},
BoxSizing::PaddingBox => match main_dir {
AxisDirection::Vertical => {
(inline_size - inline_padding_border + inline_border).div_f32(ratio)
+ block_padding_border
- block_border
}
AxisDirection::Horizontal => {
(inline_size - inline_padding_border + inline_border).mul_f32(ratio)
+ block_padding_border
- block_border
}
},
BoxSizing::ContentBox => match main_dir {
AxisDirection::Vertical => {
(inline_size - inline_padding_border).div_f32(ratio) + block_padding_border
}
AxisDirection::Horizontal => {
(inline_size - inline_padding_border).mul_f32(ratio) + block_padding_border
}
},
BoxSizing::BorderBox => dependent_padding_border.max(determining_size.div_f32(ratio)),
BoxSizing::PaddingBox => {
(determining_size - determining_padding_border + determining_border).div_f32(ratio)
+ dependent_padding_border
- dependent_border
}
BoxSizing::ContentBox => {
(determining_size - determining_padding_border).div_f32(ratio)
+ dependent_padding_border
}
}
}