Skip to content

Commit

Permalink
BoxSizing::ContentBox for Block, root and leaf layout
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoburns committed Jul 16, 2024
1 parent 8d1984c commit 1ca522c
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 24 deletions.
77 changes: 66 additions & 11 deletions src/compute/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::util::sys::f32_max;
use crate::util::sys::Vec;
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
use crate::BoxSizing;

#[cfg(feature = "content_size")]
use super::common::content_size::compute_content_size_contribution;
Expand Down Expand Up @@ -63,13 +64,29 @@ pub fn compute_block_layout(tree: &mut impl LayoutPartialTree, node_id: NodeId,

// Pull these out earlier to avoid borrowing issues
let aspect_ratio = style.aspect_ratio;
let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);
let padding_border_size = (padding + border).sum_axes();
let box_sizing_adjustment =
if style.box_sizing == BoxSizing::ContentBox { padding_border_size } else { Size::ZERO };

let min_size = style
.min_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let max_size = style
.max_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let clamped_style_size = if inputs.sizing_mode == SizingMode::InherentSize {
style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_clamp(min_size, max_size)
style
.size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment)
.maybe_clamp(min_size, max_size)
} else {
Size::NONE
};
Expand Down Expand Up @@ -106,9 +123,6 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
let raw_border = style.border;
let raw_margin = style.margin;
let aspect_ratio = style.aspect_ratio;
let size = style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);

Expand All @@ -128,6 +142,21 @@ fn compute_inner(tree: &mut impl LayoutPartialTree, node_id: NodeId, inputs: Lay
let content_box_inset = padding_border + scrollbar_gutter;
let container_content_box_size = known_dimensions.maybe_sub(content_box_inset.sum_axes());

let box_sizing_adjustment =
if style.box_sizing == BoxSizing::ContentBox { padding_border_size } else { Size::ZERO };
let size =
style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio).maybe_add(box_sizing_adjustment);
let min_size = style
.min_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let max_size = style
.max_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);

// Determine margin collapsing behaviour
let own_margins_collapse_with_children = Line {
start: vertical_margins_are_collapsible.start
Expand Down Expand Up @@ -262,13 +291,28 @@ fn generate_item_list(
let aspect_ratio = child_style.aspect_ratio;
let padding = child_style.padding.resolve_or_zero(node_inner_size);
let border = child_style.border.resolve_or_zero(node_inner_size);
let pb_sum = (padding + border).sum_axes();
let box_sizing_adjustment =
if child_style.box_sizing == BoxSizing::ContentBox { pb_sum } else { Size::ZERO };
BlockItem {
node_id: child_node_id,
order: order as u32,

size: child_style.size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
min_size: child_style.min_size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
max_size: child_style.max_size.maybe_resolve(node_inner_size).maybe_apply_aspect_ratio(aspect_ratio),
size: child_style
.size
.maybe_resolve(node_inner_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment),
min_size: child_style
.min_size
.maybe_resolve(node_inner_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment),
max_size: child_style
.max_size
.maybe_resolve(node_inner_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment),
overflow: child_style.overflow,
scrollbar_width: child_style.scrollbar_width,
position: child_style.position,
Expand Down Expand Up @@ -511,6 +555,8 @@ fn perform_absolute_layout_on_absolute_children(
let padding = child_style.padding.resolve_or_zero(Some(area_width));
let border = child_style.border.resolve_or_zero(Some(area_width));
let padding_border_sum = (padding + border).sum_axes();
let box_sizing_adjustment =
if child_style.box_sizing == BoxSizing::ContentBox { padding_border_sum } else { Size::ZERO };

// Resolve inset
let left = child_style.inset.left.maybe_resolve(area_width);
Expand All @@ -519,14 +565,23 @@ fn perform_absolute_layout_on_absolute_children(
let bottom = child_style.inset.bottom.maybe_resolve(area_height);

// Compute known dimensions from min/max/inherent size styles
let style_size = child_style.size.maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
let style_size = child_style
.size
.maybe_resolve(area_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let min_size = child_style
.min_size
.maybe_resolve(area_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment)
.or(padding_border_sum.map(Some))
.maybe_max(padding_border_sum);
let max_size = child_style.max_size.maybe_resolve(area_size).maybe_apply_aspect_ratio(aspect_ratio);
let max_size = child_style
.max_size
.maybe_resolve(area_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let mut known_dimensions = style_size.maybe_clamp(min_size, max_size);

// Fill in width from left/right and reapply aspect ratio if:
Expand Down
31 changes: 21 additions & 10 deletions src/compute/leaf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::util::debug::debug_log;
use crate::util::sys::f32_max;
use crate::util::MaybeMath;
use crate::util::{MaybeResolve, ResolveOrZero};
use crate::BoxSizing;
use core::unreachable;

/// Compute the size of a leaf node (node with no children)
Expand All @@ -21,6 +22,15 @@ where
{
let LayoutInput { known_dimensions, parent_size, available_space, sizing_mode, run_mode, .. } = inputs;

// Note: both horizontal and vertical percentage padding/borders are resolved against the container's inline size (i.e. width).
// This is not a bug, but is how CSS is specified (see: https://developer.mozilla.org/en-US/docs/Web/CSS/padding#values)
let margin = style.margin.resolve_or_zero(parent_size.width);
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);
let padding_border = padding + border;
let pb_sum = padding_border.sum_axes();
let box_sizing_adjustment = if style.box_sizing == BoxSizing::ContentBox { pb_sum } else { Size::ZERO };

// Resolve node's preferred/min/max sizes (width/heights) against the available space (percentages resolve to pixel values)
// For ContentSize mode, we pretend that the node has no size styles as these should be ignored.
let (node_size, node_min_size, node_max_size, aspect_ratio) = match sizing_mode {
Expand All @@ -32,22 +42,23 @@ where
}
SizingMode::InherentSize => {
let aspect_ratio = style.aspect_ratio;
let style_size = style.size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let style_min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let style_max_size = style.max_size.maybe_resolve(parent_size);
let style_size = style
.size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let style_min_size = style
.min_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let style_max_size = style.max_size.maybe_resolve(parent_size).maybe_add(box_sizing_adjustment);

let node_size = known_dimensions.or(style_size);
(node_size, style_min_size, style_max_size, aspect_ratio)
}
};

// Note: both horizontal and vertical percentage padding/borders are resolved against the container's inline size (i.e. width).
// This is not a bug, but is how CSS is specified (see: https://developer.mozilla.org/en-US/docs/Web/CSS/padding#values)
let margin = style.margin.resolve_or_zero(parent_size.width);
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);
let padding_border = padding + border;

// Scrollbar gutters are reserved when the `overflow` property is set to `Overflow::Scroll`.
// However, the axis are switched (transposed) because a node that scrolls vertically needs
// *horizontal* space to be reserved for a scrollbar
Expand Down
18 changes: 15 additions & 3 deletions src/compute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use crate::tree::{
use crate::util::debug::{debug_log, debug_log_node, debug_pop_node, debug_push_node};
use crate::util::sys::round;
use crate::util::ResolveOrZero;
use crate::{Display, MaybeMath, MaybeResolve};
use crate::{BoxSizing, Display, MaybeMath, MaybeResolve};

/// Compute layout for the root node in the tree
pub fn compute_root_layout(tree: &mut impl LayoutPartialTree, root: NodeId, available_space: Size<AvailableSpace>) {
Expand All @@ -67,15 +67,27 @@ pub fn compute_root_layout(tree: &mut impl LayoutPartialTree, root: NodeId, avai
// Pull these out earlier to avoid borrowing issues
let aspect_ratio = style.aspect_ratio;
let margin = style.margin.resolve_or_zero(parent_size.width);
let min_size = style.min_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let max_size = style.max_size.maybe_resolve(parent_size).maybe_apply_aspect_ratio(aspect_ratio);
let padding = style.padding.resolve_or_zero(parent_size.width);
let border = style.border.resolve_or_zero(parent_size.width);
let padding_border_size = (padding + border).sum_axes();
let box_sizing_adjustment =
if style.box_sizing == BoxSizing::ContentBox { padding_border_size } else { Size::ZERO };

let min_size = style
.min_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let max_size = style
.max_size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment);
let clamped_style_size = style
.size
.maybe_resolve(parent_size)
.maybe_apply_aspect_ratio(aspect_ratio)
.maybe_add(box_sizing_adjustment)
.maybe_clamp(min_size, max_size);

// If both min and max in a given axis are set and max <= min then this determines the size in that axis
Expand Down

0 comments on commit 1ca522c

Please sign in to comment.