mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Auto merge of #26079 - servo:box-sizing, r=nox
Implement the `box-sizing` property
This commit is contained in:
commit
5926577534
134 changed files with 3964 additions and 274 deletions
|
@ -206,7 +206,7 @@ impl InlineFormattingContext {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_lengthpercentage(&mut self, lp: LengthPercentage) {
|
||||
fn add_lengthpercentage(&mut self, lp: &LengthPercentage) {
|
||||
if let Some(l) = lp.to_length() {
|
||||
self.add_length(l);
|
||||
}
|
||||
|
@ -421,13 +421,11 @@ impl InlineBox {
|
|||
ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>,
|
||||
) -> PartialInlineBoxFragment<'box_tree> {
|
||||
let style = self.style.clone();
|
||||
let cbis = ifc.containing_block.inline_size;
|
||||
let mut padding = style.padding().percentages_relative_to(cbis);
|
||||
let mut border = style.border_width();
|
||||
let mut margin = style
|
||||
.margin()
|
||||
.percentages_relative_to(cbis)
|
||||
.auto_is(Length::zero);
|
||||
let pbm = style.padding_border_margin(&ifc.containing_block);
|
||||
let mut padding = pbm.padding;
|
||||
let mut border = pbm.border;
|
||||
let mut margin = pbm.margin.auto_is(Length::zero);
|
||||
|
||||
if self.first_fragment {
|
||||
ifc.inline_position += padding.inline_start + border.inline_start + margin.inline_start;
|
||||
} else {
|
||||
|
@ -530,18 +528,12 @@ fn layout_atomic(
|
|||
ifc: &mut InlineFormattingContextState,
|
||||
atomic: &IndependentFormattingContext,
|
||||
) {
|
||||
let cbis = ifc.containing_block.inline_size;
|
||||
let padding = atomic.style.padding().percentages_relative_to(cbis);
|
||||
let border = atomic.style.border_width();
|
||||
let margin = atomic
|
||||
.style
|
||||
.margin()
|
||||
.percentages_relative_to(cbis)
|
||||
.auto_is(Length::zero);
|
||||
let pbm = &(&padding + &border) + &margin;
|
||||
ifc.inline_position += pbm.inline_start;
|
||||
let pbm = atomic.style.padding_border_margin(&ifc.containing_block);
|
||||
let margin = pbm.margin.auto_is(Length::zero);
|
||||
let pbm_sums = &(&pbm.padding + &pbm.border) + &margin;
|
||||
ifc.inline_position += pbm_sums.inline_start;
|
||||
let mut start_corner = Vec2 {
|
||||
block: pbm.block_start,
|
||||
block: pbm_sums.block_start,
|
||||
inline: ifc.inline_position - ifc.current_nesting_level.inline_start,
|
||||
};
|
||||
if atomic.style.clone_position().is_relative() {
|
||||
|
@ -550,7 +542,8 @@ fn layout_atomic(
|
|||
|
||||
let fragment = match atomic.as_replaced() {
|
||||
Ok(replaced) => {
|
||||
let size = replaced.used_size_as_if_inline_element(ifc.containing_block, &atomic.style);
|
||||
let size =
|
||||
replaced.used_size_as_if_inline_element(ifc.containing_block, &atomic.style, &pbm);
|
||||
let fragments = replaced.make_fragments(&atomic.style, size.clone());
|
||||
let content_rect = Rect { start_corner, size };
|
||||
BoxFragment::new(
|
||||
|
@ -558,30 +551,27 @@ fn layout_atomic(
|
|||
atomic.style.clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
padding,
|
||||
border,
|
||||
pbm.padding,
|
||||
pbm.border,
|
||||
margin,
|
||||
CollapsedBlockMargins::zero(),
|
||||
)
|
||||
},
|
||||
Err(non_replaced) => {
|
||||
let box_size = atomic.style.box_size();
|
||||
let box_size = atomic.style.content_box_size(&ifc.containing_block, &pbm);
|
||||
let max_box_size = atomic
|
||||
.style
|
||||
.max_box_size()
|
||||
.percentages_relative_to(ifc.containing_block);
|
||||
.content_max_box_size(&ifc.containing_block, &pbm);
|
||||
let min_box_size = atomic
|
||||
.style
|
||||
.min_box_size()
|
||||
.percentages_relative_to(ifc.containing_block)
|
||||
.content_min_box_size(&ifc.containing_block, &pbm)
|
||||
.auto_is(Length::zero);
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
||||
let tentative_inline_size =
|
||||
box_size.inline.percentage_relative_to(cbis).auto_is(|| {
|
||||
let available_size = cbis - pbm.inline_sum();
|
||||
atomic.content_sizes.shrink_to_fit(available_size)
|
||||
});
|
||||
let tentative_inline_size = box_size.inline.auto_is(|| {
|
||||
let available_size = ifc.containing_block.inline_size - pbm_sums.inline_sum();
|
||||
atomic.content_sizes.shrink_to_fit(available_size)
|
||||
});
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
||||
// In this case “applying the rules above again” with a non-auto inline-size
|
||||
|
@ -589,12 +579,9 @@ fn layout_atomic(
|
|||
let inline_size = tentative_inline_size
|
||||
.clamp_between_extremums(min_box_size.inline, max_box_size.inline);
|
||||
|
||||
let block_size = box_size
|
||||
.block
|
||||
.maybe_percentage_relative_to(ifc.containing_block.block_size.non_auto());
|
||||
let containing_block_for_children = ContainingBlock {
|
||||
inline_size,
|
||||
block_size,
|
||||
block_size: box_size.block,
|
||||
style: &atomic.style,
|
||||
};
|
||||
assert_eq!(
|
||||
|
@ -613,7 +600,9 @@ fn layout_atomic(
|
|||
);
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
||||
let tentative_block_size = block_size.auto_is(|| independent_layout.content_block_size);
|
||||
let tentative_block_size = box_size
|
||||
.block
|
||||
.auto_is(|| independent_layout.content_block_size);
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
|
||||
// In this case “applying the rules above again” with a non-auto block-size
|
||||
|
@ -633,18 +622,18 @@ fn layout_atomic(
|
|||
atomic.style.clone(),
|
||||
independent_layout.fragments,
|
||||
content_rect,
|
||||
padding,
|
||||
border,
|
||||
pbm.padding,
|
||||
pbm.border,
|
||||
margin,
|
||||
CollapsedBlockMargins::zero(),
|
||||
)
|
||||
},
|
||||
};
|
||||
|
||||
ifc.inline_position += pbm.inline_end + fragment.content_rect.size.inline;
|
||||
ifc.inline_position += pbm_sums.inline_end + fragment.content_rect.size.inline;
|
||||
ifc.current_nesting_level
|
||||
.max_block_size_of_fragments_so_far
|
||||
.max_assign(pbm.block_sum() + fragment.content_rect.size.block);
|
||||
.max_assign(pbm_sums.block_sum() + fragment.content_rect.size.block);
|
||||
ifc.current_nesting_level
|
||||
.fragments_so_far
|
||||
.push(Fragment::Box(fragment));
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::fragments::{CollapsedBlockMargins, CollapsedMargin, Fragment};
|
|||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
|
||||
use crate::replaced::ReplacedContent;
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::ContainingBlock;
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||
use rayon_croissant::ParallelIteratorExt;
|
||||
|
@ -350,40 +350,27 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
tree_rank: usize,
|
||||
float_context: Option<&mut FloatContext>,
|
||||
) -> BoxFragment {
|
||||
let cbis = containing_block.inline_size;
|
||||
let padding = style.padding().percentages_relative_to(cbis);
|
||||
let border = style.border_width();
|
||||
let margin = style.margin().percentages_relative_to(cbis);
|
||||
let pb = &padding + &border;
|
||||
let pb_inline_sum = pb.inline_sum();
|
||||
|
||||
let box_size = style.box_size().percentages_relative_to(containing_block);
|
||||
let max_box_size = style
|
||||
.max_box_size()
|
||||
.percentages_relative_to(containing_block);
|
||||
let pbm = style.padding_border_margin(containing_block);
|
||||
let box_size = style.content_box_size(containing_block, &pbm);
|
||||
let max_box_size = style.content_max_box_size(containing_block, &pbm);
|
||||
let min_box_size = style
|
||||
.min_box_size()
|
||||
.percentages_relative_to(containing_block)
|
||||
.content_min_box_size(containing_block, &pbm)
|
||||
.auto_is(Length::zero);
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
||||
let solve_inline_margins = |inline_size| {
|
||||
solve_inline_margins_for_in_flow_block_level(
|
||||
containing_block,
|
||||
pb_inline_sum,
|
||||
margin.inline_start,
|
||||
margin.inline_end,
|
||||
inline_size,
|
||||
)
|
||||
solve_inline_margins_for_in_flow_block_level(containing_block, &pbm, inline_size)
|
||||
};
|
||||
let (mut inline_size, mut inline_margins) =
|
||||
if let Some(inline_size) = box_size.inline.non_auto() {
|
||||
(inline_size, solve_inline_margins(inline_size))
|
||||
} else {
|
||||
let margin_inline_start = margin.inline_start.auto_is(Length::zero);
|
||||
let margin_inline_end = margin.inline_end.auto_is(Length::zero);
|
||||
let margin_inline_sum = margin_inline_start + margin_inline_end;
|
||||
let inline_size = cbis - pb_inline_sum - margin_inline_sum;
|
||||
let margin_inline_start = pbm.margin.inline_start.auto_is(Length::zero);
|
||||
let margin_inline_end = pbm.margin.inline_end.auto_is(Length::zero);
|
||||
let inline_size = containing_block.inline_size -
|
||||
pbm.padding_border_sums.inline -
|
||||
margin_inline_start -
|
||||
margin_inline_end;
|
||||
(inline_size, (margin_inline_start, margin_inline_end))
|
||||
};
|
||||
if let Some(max_inline_size) = max_box_size.inline {
|
||||
|
@ -400,8 +387,8 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
let margin = Sides {
|
||||
inline_start: inline_margins.0,
|
||||
inline_end: inline_margins.1,
|
||||
block_start: margin.block_start.auto_is(Length::zero),
|
||||
block_end: margin.block_end.auto_is(Length::zero),
|
||||
block_start: pbm.margin.block_start.auto_is(Length::zero),
|
||||
block_end: pbm.margin.block_end.auto_is(Length::zero),
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
|
||||
|
@ -427,8 +414,10 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
let mut content_block_size;
|
||||
match block_level_kind {
|
||||
NonReplacedContents::SameFormattingContextBlock(contents) => {
|
||||
let this_start_margin_can_collapse_with_children = pb.block_start == Length::zero();
|
||||
let this_end_margin_can_collapse_with_children = pb.block_end == Length::zero() &&
|
||||
let start_margin_can_collapse_with_children = pbm.padding.block_start == Length::zero() &&
|
||||
pbm.border.block_start == Length::zero();
|
||||
let end_margin_can_collapse_with_children = pbm.padding.block_end == Length::zero() &&
|
||||
pbm.border.block_end == Length::zero() &&
|
||||
block_size == LengthOrAuto::Auto &&
|
||||
min_box_size.block == Length::zero();
|
||||
|
||||
|
@ -438,13 +427,13 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
&containing_block_for_children,
|
||||
tree_rank,
|
||||
float_context,
|
||||
CollapsibleWithParentStartMargin(this_start_margin_can_collapse_with_children),
|
||||
CollapsibleWithParentStartMargin(start_margin_can_collapse_with_children),
|
||||
);
|
||||
fragments = flow_layout.fragments;
|
||||
content_block_size = flow_layout.content_block_size;
|
||||
let mut collapsible_margins_in_children = flow_layout.collapsible_margins_in_children;
|
||||
|
||||
if this_start_margin_can_collapse_with_children {
|
||||
if start_margin_can_collapse_with_children {
|
||||
block_margins_collapsed_with_children
|
||||
.start
|
||||
.adjoin_assign(&collapsible_margins_in_children.start);
|
||||
|
@ -457,7 +446,7 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
));
|
||||
}
|
||||
}
|
||||
if this_end_margin_can_collapse_with_children {
|
||||
if end_margin_can_collapse_with_children {
|
||||
block_margins_collapsed_with_children
|
||||
.end
|
||||
.adjoin_assign(&collapsible_margins_in_children.end);
|
||||
|
@ -465,8 +454,8 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
content_block_size += collapsible_margins_in_children.end.solve();
|
||||
}
|
||||
block_margins_collapsed_with_children.collapsed_through =
|
||||
this_start_margin_can_collapse_with_children &&
|
||||
this_end_margin_can_collapse_with_children &&
|
||||
start_margin_can_collapse_with_children &&
|
||||
end_margin_can_collapse_with_children &&
|
||||
collapsible_margins_in_children.collapsed_through;
|
||||
},
|
||||
NonReplacedContents::EstablishesAnIndependentFormattingContext(non_replaced) => {
|
||||
|
@ -485,8 +474,8 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
});
|
||||
let content_rect = Rect {
|
||||
start_corner: Vec2 {
|
||||
block: pb.block_start,
|
||||
inline: pb.inline_start + margin.inline_start,
|
||||
block: pbm.padding.block_start + pbm.border.block_start,
|
||||
inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
|
||||
},
|
||||
size: Vec2 {
|
||||
block: block_size,
|
||||
|
@ -498,8 +487,8 @@ fn layout_in_flow_non_replaced_block_level(
|
|||
style.clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
padding,
|
||||
border,
|
||||
pbm.padding,
|
||||
pbm.border,
|
||||
margin,
|
||||
block_margins_collapsed_with_children,
|
||||
)
|
||||
|
@ -514,32 +503,22 @@ fn layout_in_flow_replaced_block_level<'a>(
|
|||
style: &Arc<ComputedValues>,
|
||||
replaced: &ReplacedContent,
|
||||
) -> BoxFragment {
|
||||
let size = replaced.used_size_as_if_inline_element(containing_block, style);
|
||||
let pbm = style.padding_border_margin(containing_block);
|
||||
let size = replaced.used_size_as_if_inline_element(containing_block, style, &pbm);
|
||||
|
||||
let cbis = containing_block.inline_size;
|
||||
let padding = style.padding().percentages_relative_to(cbis);
|
||||
let border = style.border_width();
|
||||
let computed_margin = style.margin().percentages_relative_to(cbis);
|
||||
let pb = &padding + &border;
|
||||
|
||||
let (margin_inline_start, margin_inline_end) = solve_inline_margins_for_in_flow_block_level(
|
||||
containing_block,
|
||||
pb.inline_sum(),
|
||||
computed_margin.inline_start,
|
||||
computed_margin.inline_end,
|
||||
size.inline,
|
||||
);
|
||||
let (margin_inline_start, margin_inline_end) =
|
||||
solve_inline_margins_for_in_flow_block_level(containing_block, &pbm, size.inline);
|
||||
let margin = Sides {
|
||||
inline_start: margin_inline_start,
|
||||
inline_end: margin_inline_end,
|
||||
block_start: computed_margin.block_start.auto_is(Length::zero),
|
||||
block_end: computed_margin.block_end.auto_is(Length::zero),
|
||||
block_start: pbm.margin.block_start.auto_is(Length::zero),
|
||||
block_end: pbm.margin.block_end.auto_is(Length::zero),
|
||||
};
|
||||
let fragments = replaced.make_fragments(style, size.clone());
|
||||
let content_rect = Rect {
|
||||
start_corner: Vec2 {
|
||||
block: pb.block_start,
|
||||
inline: pb.inline_start + margin.inline_start,
|
||||
block: pbm.padding.block_start + pbm.border.block_start,
|
||||
inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
|
||||
},
|
||||
size,
|
||||
};
|
||||
|
@ -549,8 +528,8 @@ fn layout_in_flow_replaced_block_level<'a>(
|
|||
style.clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
padding,
|
||||
border,
|
||||
pbm.padding,
|
||||
pbm.border,
|
||||
margin,
|
||||
block_margins_collapsed_with_children,
|
||||
)
|
||||
|
@ -558,15 +537,13 @@ fn layout_in_flow_replaced_block_level<'a>(
|
|||
|
||||
fn solve_inline_margins_for_in_flow_block_level(
|
||||
containing_block: &ContainingBlock,
|
||||
padding_border_inline_sum: Length,
|
||||
computed_margin_inline_start: LengthOrAuto,
|
||||
computed_margin_inline_end: LengthOrAuto,
|
||||
pbm: &PaddingBorderMargin,
|
||||
inline_size: Length,
|
||||
) -> (Length, Length) {
|
||||
let inline_margins = containing_block.inline_size - padding_border_inline_sum - inline_size;
|
||||
match (computed_margin_inline_start, computed_margin_inline_end) {
|
||||
(LengthOrAuto::Auto, LengthOrAuto::Auto) => (inline_margins / 2., inline_margins / 2.),
|
||||
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => (inline_margins - end, end),
|
||||
(LengthOrAuto::LengthPercentage(start), _) => (start, inline_margins - start),
|
||||
let available = containing_block.inline_size - pbm.padding_border_sums.inline - inline_size;
|
||||
match (pbm.margin.inline_start, pbm.margin.inline_end) {
|
||||
(LengthOrAuto::Auto, LengthOrAuto::Auto) => (available / 2., available / 2.),
|
||||
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => (available - end, end),
|
||||
(LengthOrAuto::LengthPercentage(start), _) => (start, available - start),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ use std::fmt;
|
|||
use std::ops::{Add, AddAssign, Sub};
|
||||
use style::logical_geometry::{BlockFlowDirection, InlineBaseDirection};
|
||||
use style::logical_geometry::{PhysicalCorner, WritingMode};
|
||||
use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
|
||||
use style::values::generics::length::MaxSize;
|
||||
use style::values::computed::{Length, LengthPercentage};
|
||||
use style::values::generics::length::GenericLengthPercentageOrAuto as AutoOr;
|
||||
use style::Zero;
|
||||
use style_traits::CSSPixel;
|
||||
|
||||
|
@ -16,6 +16,8 @@ pub type PhysicalPoint<U> = euclid::Point2D<U, CSSPixel>;
|
|||
pub type PhysicalSize<U> = euclid::Size2D<U, CSSPixel>;
|
||||
pub type PhysicalRect<U> = euclid::Rect<U, CSSPixel>;
|
||||
pub type PhysicalSides<U> = euclid::SideOffsets2D<U, CSSPixel>;
|
||||
pub type LengthOrAuto = AutoOr<Length>;
|
||||
pub type LengthPercentageOrAuto<'a> = AutoOr<&'a LengthPercentage>;
|
||||
|
||||
pub(crate) mod flow_relative {
|
||||
#[derive(Clone, Serialize)]
|
||||
|
@ -107,7 +109,7 @@ impl flow_relative::Vec2<LengthOrAuto> {
|
|||
}
|
||||
}
|
||||
|
||||
impl flow_relative::Vec2<LengthPercentageOrAuto> {
|
||||
impl flow_relative::Vec2<LengthPercentageOrAuto<'_>> {
|
||||
pub fn percentages_relative_to(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
|
@ -123,24 +125,18 @@ impl flow_relative::Vec2<LengthPercentageOrAuto> {
|
|||
}
|
||||
}
|
||||
|
||||
impl flow_relative::Vec2<MaxSize<LengthPercentage>> {
|
||||
impl flow_relative::Vec2<Option<&'_ LengthPercentage>> {
|
||||
pub fn percentages_relative_to(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
) -> flow_relative::Vec2<Option<Length>> {
|
||||
flow_relative::Vec2 {
|
||||
inline: match self.inline {
|
||||
MaxSize::None => None,
|
||||
MaxSize::LengthPercentage(ref lp) => {
|
||||
Some(lp.percentage_relative_to(containing_block.inline_size))
|
||||
},
|
||||
},
|
||||
block: match self.block {
|
||||
MaxSize::None => None,
|
||||
MaxSize::LengthPercentage(ref lp) => {
|
||||
lp.maybe_percentage_relative_to(containing_block.block_size.non_auto())
|
||||
},
|
||||
},
|
||||
inline: self
|
||||
.inline
|
||||
.map(|lp| lp.percentage_relative_to(containing_block.inline_size)),
|
||||
block: self.block.and_then(|lp| {
|
||||
lp.maybe_percentage_relative_to(containing_block.block_size.non_auto())
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,13 +276,13 @@ impl<T> flow_relative::Sides<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl flow_relative::Sides<LengthPercentage> {
|
||||
impl flow_relative::Sides<&'_ LengthPercentage> {
|
||||
pub fn percentages_relative_to(&self, basis: Length) -> flow_relative::Sides<Length> {
|
||||
self.map(|s| s.percentage_relative_to(basis))
|
||||
}
|
||||
}
|
||||
|
||||
impl flow_relative::Sides<LengthPercentageOrAuto> {
|
||||
impl flow_relative::Sides<LengthPercentageOrAuto<'_>> {
|
||||
pub fn percentages_relative_to(&self, basis: Length) -> flow_relative::Sides<LengthOrAuto> {
|
||||
self.map(|s| s.percentage_relative_to(basis))
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use crate::dom_traversal::{Contents, NodeExt};
|
|||
use crate::formatting_contexts::IndependentFormattingContext;
|
||||
use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment};
|
||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||
use crate::geom::{LengthOrAuto, LengthPercentageOrAuto};
|
||||
use crate::sizing::ContentSizesRequest;
|
||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
||||
use crate::{ContainingBlock, DefiniteContainingBlock};
|
||||
|
@ -16,7 +17,7 @@ use rayon_croissant::ParallelIteratorExt;
|
|||
use servo_arc::Arc;
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
|
||||
use style::values::computed::{Length, LengthPercentage};
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
use style::Zero;
|
||||
|
||||
|
@ -112,29 +113,34 @@ impl AbsolutelyPositionedBox {
|
|||
(None, None) => AbsoluteBoxOffsets::StaticStart {
|
||||
start: initial_static_start,
|
||||
},
|
||||
(Some(start), Some(end)) => AbsoluteBoxOffsets::Both { start, end },
|
||||
(None, Some(end)) => AbsoluteBoxOffsets::End { end },
|
||||
(Some(start), None) => AbsoluteBoxOffsets::Start { start },
|
||||
(Some(start), Some(end)) => AbsoluteBoxOffsets::Both {
|
||||
start: start.clone(),
|
||||
end: end.clone(),
|
||||
},
|
||||
(None, Some(end)) => AbsoluteBoxOffsets::End { end: end.clone() },
|
||||
(Some(start), None) => AbsoluteBoxOffsets::Start {
|
||||
start: start.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
let box_offsets = self.contents.style.box_offsets();
|
||||
HoistedAbsolutelyPositionedBox {
|
||||
absolutely_positioned_box: self,
|
||||
tree_rank,
|
||||
box_offsets: Vec2 {
|
||||
inline: absolute_box_offsets(
|
||||
initial_start_corner.inline,
|
||||
box_offsets.inline_start.clone(),
|
||||
box_offsets.inline_end.clone(),
|
||||
box_offsets.inline_start,
|
||||
box_offsets.inline_end,
|
||||
),
|
||||
block: absolute_box_offsets(
|
||||
initial_start_corner.block,
|
||||
box_offsets.block_start.clone(),
|
||||
box_offsets.block_end.clone(),
|
||||
box_offsets.block_start,
|
||||
box_offsets.block_end,
|
||||
),
|
||||
},
|
||||
fragment: ArcRefCell::new(None),
|
||||
absolutely_positioned_box: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,9 +411,10 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>,
|
||||
containing_block: &DefiniteContainingBlock,
|
||||
) -> BoxFragment {
|
||||
let style = &self.absolutely_positioned_box.contents.style;
|
||||
let cbis = containing_block.size.inline;
|
||||
let cbbs = containing_block.size.block;
|
||||
let style = &self.absolutely_positioned_box.contents.style;
|
||||
let pbm = style.padding_border_margin(&containing_block.into());
|
||||
|
||||
let size;
|
||||
let replaced_used_size;
|
||||
|
@ -415,45 +422,37 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
Ok(replaced) => {
|
||||
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
|
||||
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
|
||||
let u = replaced.used_size_as_if_inline_element(&containing_block.into(), style);
|
||||
let used_size =
|
||||
replaced.used_size_as_if_inline_element(&containing_block.into(), style, &pbm);
|
||||
size = Vec2 {
|
||||
inline: LengthOrAuto::LengthPercentage(u.inline),
|
||||
block: LengthOrAuto::LengthPercentage(u.block),
|
||||
inline: LengthOrAuto::LengthPercentage(used_size.inline),
|
||||
block: LengthOrAuto::LengthPercentage(used_size.block),
|
||||
};
|
||||
replaced_used_size = Some(u);
|
||||
replaced_used_size = Some(used_size);
|
||||
},
|
||||
Err(_non_replaced) => {
|
||||
let box_size = style.box_size();
|
||||
size = Vec2 {
|
||||
inline: box_size.inline.percentage_relative_to(cbis),
|
||||
block: box_size.block.percentage_relative_to(cbbs),
|
||||
};
|
||||
size = style.content_box_size(&containing_block.into(), &pbm);
|
||||
replaced_used_size = None;
|
||||
},
|
||||
}
|
||||
|
||||
let padding = style.padding().percentages_relative_to(cbis);
|
||||
let border = style.border_width();
|
||||
let computed_margin = style.margin().percentages_relative_to(cbis);
|
||||
let pb = &padding + &border;
|
||||
|
||||
let inline_axis = solve_axis(
|
||||
cbis,
|
||||
pb.inline_sum(),
|
||||
computed_margin.inline_start.clone(),
|
||||
computed_margin.inline_end.clone(),
|
||||
pbm.padding_border_sums.inline,
|
||||
pbm.margin.inline_start,
|
||||
pbm.margin.inline_end,
|
||||
/* avoid_negative_margin_start */ true,
|
||||
self.box_offsets.inline.clone(),
|
||||
&self.box_offsets.inline,
|
||||
size.inline,
|
||||
);
|
||||
|
||||
let block_axis = solve_axis(
|
||||
cbis,
|
||||
pb.block_sum(),
|
||||
computed_margin.block_start.clone(),
|
||||
computed_margin.block_end.clone(),
|
||||
pbm.padding_border_sums.block,
|
||||
pbm.margin.block_start,
|
||||
pbm.margin.block_end,
|
||||
/* avoid_negative_margin_start */ false,
|
||||
self.box_offsets.block.clone(),
|
||||
&self.box_offsets.block,
|
||||
size.block,
|
||||
);
|
||||
|
||||
|
@ -483,14 +482,14 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
|
||||
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height
|
||||
let inline_size = inline_axis.size.auto_is(|| {
|
||||
let available_size = match inline_axis.anchor {
|
||||
Anchor::Start(start) => {
|
||||
cbis - start - pb.inline_sum() - margin.inline_sum()
|
||||
},
|
||||
Anchor::End(end) => {
|
||||
cbis - end - pb.inline_sum() - margin.inline_sum()
|
||||
},
|
||||
let anchor = match inline_axis.anchor {
|
||||
Anchor::Start(start) => start,
|
||||
Anchor::End(end) => end,
|
||||
};
|
||||
let available_size = cbis -
|
||||
anchor -
|
||||
pbm.padding_border_sums.inline -
|
||||
margin.inline_sum();
|
||||
self.absolutely_positioned_box
|
||||
.contents
|
||||
.content_sizes
|
||||
|
@ -526,6 +525,7 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
},
|
||||
};
|
||||
|
||||
let pb = &pbm.padding + &pbm.border;
|
||||
let inline_start = match inline_axis.anchor {
|
||||
Anchor::Start(start) => start + pb.inline_start + margin.inline_start,
|
||||
Anchor::End(end) => {
|
||||
|
@ -550,8 +550,8 @@ impl HoistedAbsolutelyPositionedBox {
|
|||
style.clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
padding,
|
||||
border,
|
||||
pbm.padding,
|
||||
pbm.border,
|
||||
margin,
|
||||
CollapsedBlockMargins::zero(),
|
||||
)
|
||||
|
@ -589,12 +589,12 @@ fn solve_axis(
|
|||
computed_margin_start: LengthOrAuto,
|
||||
computed_margin_end: LengthOrAuto,
|
||||
avoid_negative_margin_start: bool,
|
||||
box_offsets: AbsoluteBoxOffsets,
|
||||
box_offsets: &AbsoluteBoxOffsets,
|
||||
size: LengthOrAuto,
|
||||
) -> AxisResult {
|
||||
match box_offsets {
|
||||
AbsoluteBoxOffsets::StaticStart { start } => AxisResult {
|
||||
anchor: Anchor::Start(start),
|
||||
anchor: Anchor::Start(*start),
|
||||
size,
|
||||
margin_start: computed_margin_start.auto_is(Length::zero),
|
||||
margin_end: computed_margin_end.auto_is(Length::zero),
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::fragments::{DebugId, Fragment, ImageFragment};
|
|||
use crate::geom::flow_relative::{Rect, Vec2};
|
||||
use crate::geom::PhysicalSize;
|
||||
use crate::sizing::ContentSizes;
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin};
|
||||
use crate::ContainingBlock;
|
||||
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromLayoutMsg};
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
|
@ -240,19 +240,17 @@ impl ReplacedContent {
|
|||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
style: &ComputedValues,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> Vec2<Length> {
|
||||
let mode = style.writing_mode;
|
||||
let intrinsic_size = self.flow_relative_intrinsic_size(style);
|
||||
let intrinsic_ratio = self.inline_size_over_block_size_intrinsic_ratio(style);
|
||||
|
||||
let box_size = style.box_size().percentages_relative_to(containing_block);
|
||||
let box_size = style.content_box_size(containing_block, &pbm);
|
||||
let max_box_size = style.content_max_box_size(containing_block, &pbm);
|
||||
let min_box_size = style
|
||||
.min_box_size()
|
||||
.percentages_relative_to(containing_block)
|
||||
.content_min_box_size(containing_block, &pbm)
|
||||
.auto_is(Length::zero);
|
||||
let max_box_size = style
|
||||
.max_box_size()
|
||||
.percentages_relative_to(containing_block);
|
||||
|
||||
let default_object_size = || {
|
||||
// FIXME:
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
//! https://drafts.csswg.org/css-sizing/
|
||||
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
use style::properties::longhands::box_sizing::computed_value::T as BoxSizing;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthPercentage, Percentage};
|
||||
use style::values::generics::length::MaxSize;
|
||||
use style::Zero;
|
||||
|
||||
/// Which min/max-content values should be computed during box construction
|
||||
|
@ -63,6 +63,13 @@ impl ContentSizes {
|
|||
}
|
||||
}
|
||||
|
||||
fn map(&self, f: impl Fn(Length) -> Length) -> Self {
|
||||
Self {
|
||||
min_content: f(self.min_content),
|
||||
max_content: f(self.max_content),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max_assign(&mut self, other: &Self) {
|
||||
self.min_content.max_assign(other.min_content);
|
||||
self.max_content.max_assign(other.max_content);
|
||||
|
@ -108,61 +115,68 @@ impl BoxContentSizes {
|
|||
&self,
|
||||
style: &ComputedValues,
|
||||
) -> (ContentSizes, Percentage) {
|
||||
// FIXME: account for 'box-sizing'
|
||||
let inline_size = style.box_size().inline;
|
||||
let min_inline_size = style
|
||||
.min_box_size()
|
||||
.inline
|
||||
.percentage_relative_to(Length::zero())
|
||||
.auto_is(Length::zero);
|
||||
let max_inline_size = match style.max_box_size().inline {
|
||||
MaxSize::None => None,
|
||||
MaxSize::LengthPercentage(ref lp) => lp.to_length(),
|
||||
};
|
||||
let clamp = |l: Length| l.clamp_between_extremums(min_inline_size, max_inline_size);
|
||||
|
||||
// Percentages for 'width' are treated as 'auto'
|
||||
let inline_size = inline_size.map(|lp| lp.to_length());
|
||||
// The (inner) min/max-content are only used for 'auto'
|
||||
let mut outer = match inline_size.non_auto().flatten() {
|
||||
None => {
|
||||
let inner = self.expect_inline().clone();
|
||||
ContentSizes {
|
||||
min_content: clamp(inner.min_content),
|
||||
max_content: clamp(inner.max_content),
|
||||
}
|
||||
},
|
||||
Some(length) => {
|
||||
let length = clamp(length);
|
||||
ContentSizes {
|
||||
min_content: length,
|
||||
max_content: length,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let mut pbm_lengths = Length::zero();
|
||||
let mut pbm_percentages = Percentage::zero();
|
||||
let padding = style.padding();
|
||||
let border = style.border_width();
|
||||
let margin = style.margin();
|
||||
pbm_lengths += border.inline_sum();
|
||||
let mut add = |x: LengthPercentage| {
|
||||
if let Some(l) = x.to_length() {
|
||||
pbm_lengths += l;
|
||||
}
|
||||
if let Some(p) = x.to_percentage() {
|
||||
pbm_percentages += p;
|
||||
}
|
||||
|
||||
let mut pbm_percentages = Percentage::zero();
|
||||
let mut decompose = |x: &LengthPercentage| {
|
||||
pbm_percentages += x.to_percentage().unwrap_or_else(Zero::zero);
|
||||
x.to_length().unwrap_or_else(Zero::zero)
|
||||
};
|
||||
add(padding.inline_start);
|
||||
add(padding.inline_end);
|
||||
margin.inline_start.non_auto().map(&mut add);
|
||||
margin.inline_end.non_auto().map(&mut add);
|
||||
let pb_lengths =
|
||||
border.inline_sum() + decompose(padding.inline_start) + decompose(padding.inline_end);
|
||||
let mut m_lengths = Length::zero();
|
||||
if let Some(m) = margin.inline_start.non_auto() {
|
||||
m_lengths += decompose(m)
|
||||
}
|
||||
if let Some(m) = margin.inline_end.non_auto() {
|
||||
m_lengths += decompose(m)
|
||||
}
|
||||
|
||||
outer.min_content += pbm_lengths;
|
||||
outer.max_content += pbm_lengths;
|
||||
let box_sizing = style.get_position().box_sizing;
|
||||
let inline_size = style
|
||||
.box_size()
|
||||
.inline
|
||||
.non_auto()
|
||||
// Percentages for 'width' are treated as 'auto'
|
||||
.and_then(|lp| lp.to_length());
|
||||
let min_inline_size = style
|
||||
.min_box_size()
|
||||
.inline
|
||||
// Percentages for 'min-width' are treated as zero
|
||||
.percentage_relative_to(Length::zero())
|
||||
// FIXME: 'auto' is not zero in Flexbox
|
||||
.auto_is(Length::zero);
|
||||
let max_inline_size = style
|
||||
.max_box_size()
|
||||
.inline
|
||||
// Percentages for 'max-width' are treated as 'none'
|
||||
.and_then(|lp| lp.to_length());
|
||||
let clamp = |l: Length| l.clamp_between_extremums(min_inline_size, max_inline_size);
|
||||
|
||||
let border_box_sizes = match inline_size {
|
||||
Some(non_auto) => {
|
||||
let clamped = clamp(non_auto);
|
||||
let border_box_size = match box_sizing {
|
||||
BoxSizing::ContentBox => clamped + pb_lengths,
|
||||
BoxSizing::BorderBox => clamped,
|
||||
};
|
||||
ContentSizes {
|
||||
min_content: border_box_size,
|
||||
max_content: border_box_size,
|
||||
}
|
||||
},
|
||||
None => self.expect_inline().map(|content_box_size| {
|
||||
match box_sizing {
|
||||
// Clamp to 'min-width' and 'max-width', which are sizing the…
|
||||
BoxSizing::ContentBox => clamp(content_box_size) + pb_lengths,
|
||||
BoxSizing::BorderBox => clamp(content_box_size + pb_lengths),
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
let outer = border_box_sizes.map(|s| s + m_lengths);
|
||||
(outer, pbm_percentages)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,16 +2,20 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::geom::{flow_relative, PhysicalSides, PhysicalSize};
|
||||
use crate::geom::flow_relative;
|
||||
use crate::geom::{LengthOrAuto, LengthPercentageOrAuto, PhysicalSides, PhysicalSize};
|
||||
use crate::ContainingBlock;
|
||||
use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
||||
use style::computed_values::position::T as ComputedPosition;
|
||||
use style::computed_values::transform_style::T as ComputedTransformStyle;
|
||||
use style::properties::longhands::box_sizing::computed_value::T as BoxSizing;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthPercentage, LengthPercentageOrAuto};
|
||||
use style::values::computed::{Length, LengthPercentage};
|
||||
use style::values::computed::{NonNegativeLengthPercentage, Size};
|
||||
use style::values::generics::box_::Perspective;
|
||||
use style::values::generics::length::MaxSize;
|
||||
use style::values::specified::box_ as stylo;
|
||||
use style::Zero;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub(crate) enum Display {
|
||||
|
@ -43,14 +47,40 @@ pub(crate) enum DisplayInside {
|
|||
FlowRoot,
|
||||
}
|
||||
|
||||
/// Percentages resolved but not `auto` margins
|
||||
pub(crate) struct PaddingBorderMargin {
|
||||
pub padding: flow_relative::Sides<Length>,
|
||||
pub border: flow_relative::Sides<Length>,
|
||||
pub margin: flow_relative::Sides<LengthOrAuto>,
|
||||
|
||||
/// Pre-computed sums in each axis
|
||||
pub padding_border_sums: flow_relative::Vec2<Length>,
|
||||
}
|
||||
|
||||
pub(crate) trait ComputedValuesExt {
|
||||
fn inline_size_is_length(&self) -> bool;
|
||||
fn inline_box_offsets_are_both_non_auto(&self) -> bool;
|
||||
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
|
||||
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
|
||||
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>;
|
||||
fn max_box_size(&self) -> flow_relative::Vec2<MaxSize<LengthPercentage>>;
|
||||
fn padding(&self) -> flow_relative::Sides<LengthPercentage>;
|
||||
fn max_box_size(&self) -> flow_relative::Vec2<Option<&LengthPercentage>>;
|
||||
fn content_box_size(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> flow_relative::Vec2<LengthOrAuto>;
|
||||
fn content_min_box_size(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> flow_relative::Vec2<LengthOrAuto>;
|
||||
fn content_max_box_size(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> flow_relative::Vec2<Option<Length>>;
|
||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin;
|
||||
fn padding(&self) -> flow_relative::Sides<&LengthPercentage>;
|
||||
fn border_width(&self) -> flow_relative::Sides<Length>;
|
||||
fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto>;
|
||||
fn has_transform_or_perspective(&self) -> bool;
|
||||
|
@ -81,69 +111,142 @@ impl ComputedValuesExt for ComputedValues {
|
|||
!a.is_auto() && !b.is_auto()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto> {
|
||||
let position = self.get_position();
|
||||
flow_relative::Sides::from_physical(
|
||||
&PhysicalSides::new(
|
||||
position.top.clone(),
|
||||
position.right.clone(),
|
||||
position.bottom.clone(),
|
||||
position.left.clone(),
|
||||
position.top.as_ref(),
|
||||
position.right.as_ref(),
|
||||
position.bottom.as_ref(),
|
||||
position.left.as_ref(),
|
||||
),
|
||||
self.writing_mode,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
|
||||
let position = self.get_position();
|
||||
flow_relative::Vec2::from_physical_size(
|
||||
&PhysicalSize::new(
|
||||
size_to_length(position.width.clone()),
|
||||
size_to_length(position.height.clone()),
|
||||
size_to_length(&position.width),
|
||||
size_to_length(&position.height),
|
||||
),
|
||||
self.writing_mode,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> {
|
||||
let position = self.get_position();
|
||||
flow_relative::Vec2::from_physical_size(
|
||||
&PhysicalSize::new(
|
||||
size_to_length(position.min_width.clone()),
|
||||
size_to_length(position.min_height.clone()),
|
||||
size_to_length(&position.min_width),
|
||||
size_to_length(&position.min_height),
|
||||
),
|
||||
self.writing_mode,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max_box_size(&self) -> flow_relative::Vec2<MaxSize<LengthPercentage>> {
|
||||
let unwrap = |max_size: MaxSize<NonNegativeLengthPercentage>| match max_size {
|
||||
MaxSize::LengthPercentage(length) => MaxSize::LengthPercentage(length.0),
|
||||
MaxSize::None => MaxSize::None,
|
||||
};
|
||||
fn max_box_size(&self) -> flow_relative::Vec2<Option<&LengthPercentage>> {
|
||||
fn unwrap(max_size: &MaxSize<NonNegativeLengthPercentage>) -> Option<&LengthPercentage> {
|
||||
match max_size {
|
||||
MaxSize::LengthPercentage(length) => Some(&length.0),
|
||||
MaxSize::None => None,
|
||||
}
|
||||
}
|
||||
let position = self.get_position();
|
||||
flow_relative::Vec2::from_physical_size(
|
||||
&PhysicalSize::new(
|
||||
unwrap(position.max_width.clone()),
|
||||
unwrap(position.max_height.clone()),
|
||||
),
|
||||
&PhysicalSize::new(unwrap(&position.max_width), unwrap(&position.max_height)),
|
||||
self.writing_mode,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn padding(&self) -> flow_relative::Sides<LengthPercentage> {
|
||||
fn content_box_size(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> flow_relative::Vec2<LengthOrAuto> {
|
||||
let box_size = self.box_size().percentages_relative_to(containing_block);
|
||||
match self.get_position().box_sizing {
|
||||
BoxSizing::ContentBox => box_size,
|
||||
BoxSizing::BorderBox => flow_relative::Vec2 {
|
||||
// These may be negative, but will later be clamped by `min-width`/`min-height`
|
||||
// which is clamped to zero.
|
||||
inline: box_size.inline.map(|i| i - pbm.padding_border_sums.inline),
|
||||
block: box_size.block.map(|b| b - pbm.padding_border_sums.block),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn content_min_box_size(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> flow_relative::Vec2<LengthOrAuto> {
|
||||
let min_box_size = self
|
||||
.min_box_size()
|
||||
.percentages_relative_to(containing_block);
|
||||
match self.get_position().box_sizing {
|
||||
BoxSizing::ContentBox => min_box_size,
|
||||
BoxSizing::BorderBox => flow_relative::Vec2 {
|
||||
// Clamp to zero to make sure the used size components are non-negative
|
||||
inline: min_box_size
|
||||
.inline
|
||||
.map(|i| (i - pbm.padding_border_sums.inline).max(Length::zero())),
|
||||
block: min_box_size
|
||||
.block
|
||||
.map(|b| (b - pbm.padding_border_sums.block).max(Length::zero())),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn content_max_box_size(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
pbm: &PaddingBorderMargin,
|
||||
) -> flow_relative::Vec2<Option<Length>> {
|
||||
let max_box_size = self
|
||||
.max_box_size()
|
||||
.percentages_relative_to(containing_block);
|
||||
match self.get_position().box_sizing {
|
||||
BoxSizing::ContentBox => max_box_size,
|
||||
BoxSizing::BorderBox => {
|
||||
// This may be negative, but will later be clamped by `min-width`
|
||||
// which itself is clamped to zero.
|
||||
flow_relative::Vec2 {
|
||||
inline: max_box_size
|
||||
.inline
|
||||
.map(|i| i - pbm.padding_border_sums.inline),
|
||||
block: max_box_size
|
||||
.block
|
||||
.map(|b| b - pbm.padding_border_sums.block),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin {
|
||||
let cbis = containing_block.inline_size;
|
||||
let padding = self.padding().percentages_relative_to(cbis);
|
||||
let border = self.border_width();
|
||||
PaddingBorderMargin {
|
||||
padding_border_sums: flow_relative::Vec2 {
|
||||
inline: padding.inline_sum() + border.inline_sum(),
|
||||
block: padding.block_sum() + border.block_sum(),
|
||||
},
|
||||
padding,
|
||||
border,
|
||||
margin: self.margin().percentages_relative_to(cbis),
|
||||
}
|
||||
}
|
||||
|
||||
fn padding(&self) -> flow_relative::Sides<&LengthPercentage> {
|
||||
let padding = self.get_padding();
|
||||
flow_relative::Sides::from_physical(
|
||||
&PhysicalSides::new(
|
||||
padding.padding_top.0.clone(),
|
||||
padding.padding_right.0.clone(),
|
||||
padding.padding_bottom.0.clone(),
|
||||
padding.padding_left.0.clone(),
|
||||
&padding.padding_top.0,
|
||||
&padding.padding_right.0,
|
||||
&padding.padding_bottom.0,
|
||||
&padding.padding_left.0,
|
||||
),
|
||||
self.writing_mode,
|
||||
)
|
||||
|
@ -166,10 +269,10 @@ impl ComputedValuesExt for ComputedValues {
|
|||
let margin = self.get_margin();
|
||||
flow_relative::Sides::from_physical(
|
||||
&PhysicalSides::new(
|
||||
margin.margin_top.clone(),
|
||||
margin.margin_right.clone(),
|
||||
margin.margin_bottom.clone(),
|
||||
margin.margin_left.clone(),
|
||||
margin.margin_top.as_ref(),
|
||||
margin.margin_right.as_ref(),
|
||||
margin.margin_bottom.as_ref(),
|
||||
margin.margin_left.as_ref(),
|
||||
),
|
||||
self.writing_mode,
|
||||
)
|
||||
|
@ -285,11 +388,9 @@ impl From<stylo::Display> for Display {
|
|||
}
|
||||
}
|
||||
|
||||
fn size_to_length(size: Size) -> LengthPercentageOrAuto {
|
||||
fn size_to_length(size: &Size) -> LengthPercentageOrAuto {
|
||||
match size {
|
||||
Size::LengthPercentage(length) => {
|
||||
LengthPercentageOrAuto::LengthPercentage(length.0.clone())
|
||||
},
|
||||
Size::LengthPercentage(length) => LengthPercentageOrAuto::LengthPercentage(&length.0),
|
||||
Size::Auto => LengthPercentageOrAuto::Auto,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,7 +313,6 @@ ${helpers.single_keyword(
|
|||
"box-sizing",
|
||||
"content-box border-box",
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
servo_2020_pref="layout.2020.unimplemented",
|
||||
extra_prefixes="moz:layout.css.prefixes.box-sizing webkit",
|
||||
spec="https://drafts.csswg.org/css-ui/#propdef-box-sizing",
|
||||
gecko_enum_prefix="StyleBoxSizing",
|
||||
|
|
|
@ -109,8 +109,19 @@ impl LengthPercentageOrAuto {
|
|||
}
|
||||
}
|
||||
|
||||
computed_length_percentage_or_auto!(LengthPercentage);
|
||||
/// Convert to have a borrow inside the enum
|
||||
pub fn as_ref(&self) -> generics::GenericLengthPercentageOrAuto<&LengthPercentage> {
|
||||
use values::generics::length::LengthPercentageOrAuto::*;
|
||||
match *self {
|
||||
LengthPercentage(ref lp) => LengthPercentage(lp),
|
||||
Auto => Auto,
|
||||
}
|
||||
}
|
||||
|
||||
computed_length_percentage_or_auto!(LengthPercentage);
|
||||
}
|
||||
|
||||
impl generics::GenericLengthPercentageOrAuto<&LengthPercentage> {
|
||||
/// Resolves the percentage.
|
||||
#[inline]
|
||||
pub fn percentage_relative_to(&self, basis: Length) -> LengthOrAuto {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue