mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Refactor how calc() clamping is done on computed values (fixes #15296)
This commit is contained in:
parent
f935f2da01
commit
d0b9bd9c64
13 changed files with 173 additions and 154 deletions
|
@ -46,7 +46,6 @@ use gfx_traits::print_tree::PrintTree;
|
|||
use incremental::RelayoutMode;
|
||||
use layout_debug;
|
||||
use model::{AdjoiningMargins, CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo, MaybeAuto};
|
||||
use model::{specified, specified_or_none};
|
||||
use sequential;
|
||||
use serde::{Serialize, Serializer};
|
||||
use servo_geometry::max_rect;
|
||||
|
@ -326,7 +325,7 @@ impl CandidateBSizeIterator {
|
|||
MaybeAuto::Specified(block_container_block_size.scale_by(percent))
|
||||
}
|
||||
(LengthOrPercentageOrAuto::Calc(calc), _) => {
|
||||
MaybeAuto::from_option(calc.to_computed(block_container_block_size))
|
||||
MaybeAuto::from_option(calc.to_used_value(block_container_block_size))
|
||||
}
|
||||
(LengthOrPercentageOrAuto::Percentage(_), None) |
|
||||
(LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto,
|
||||
|
@ -337,7 +336,7 @@ impl CandidateBSizeIterator {
|
|||
Some(block_container_block_size.scale_by(percent))
|
||||
}
|
||||
(LengthOrPercentageOrNone::Calc(calc), _) => {
|
||||
calc.to_computed(block_container_block_size)
|
||||
calc.to_used_value(block_container_block_size)
|
||||
}
|
||||
(LengthOrPercentageOrNone::Percentage(_), None) |
|
||||
(LengthOrPercentageOrNone::None, _) => None,
|
||||
|
@ -348,7 +347,7 @@ impl CandidateBSizeIterator {
|
|||
block_container_block_size.scale_by(percent)
|
||||
}
|
||||
(LengthOrPercentage::Calc(calc), _) => {
|
||||
calc.to_computed(block_container_block_size).unwrap_or(Au(0))
|
||||
calc.to_used_value(block_container_block_size).unwrap_or(Au(0))
|
||||
}
|
||||
(LengthOrPercentage::Percentage(_), None) => Au(0),
|
||||
(LengthOrPercentage::Length(length), _) => length,
|
||||
|
@ -1167,7 +1166,7 @@ impl BlockFlow {
|
|||
|
||||
match (content_block_size, containing_block_size) {
|
||||
(LengthOrPercentageOrAuto::Calc(calc), _) => {
|
||||
calc.to_computed(containing_block_size)
|
||||
calc.to_used_value(containing_block_size)
|
||||
}
|
||||
(LengthOrPercentageOrAuto::Length(length), _) => Some(length),
|
||||
(LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
|
||||
|
@ -1417,8 +1416,8 @@ impl BlockFlow {
|
|||
// we know.
|
||||
if kid.is_inline_flow() {
|
||||
kid.as_mut_inline().first_line_indentation =
|
||||
specified(self.fragment.style().get_inheritedtext().text_indent,
|
||||
containing_block_size);
|
||||
self.fragment.style().get_inheritedtext().text_indent
|
||||
.to_used_value(containing_block_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1512,14 +1511,12 @@ impl BlockFlow {
|
|||
} else {
|
||||
content_box.size.inline
|
||||
} - self.fragment.margin.inline_start_end();
|
||||
let max_inline_size = specified_or_none(
|
||||
self.fragment.style().max_inline_size(),
|
||||
self.base.block_container_inline_size
|
||||
).unwrap_or(MAX_AU);
|
||||
let min_inline_size = specified(
|
||||
self.fragment.style().min_inline_size(),
|
||||
self.base.block_container_inline_size
|
||||
);
|
||||
let max_inline_size =
|
||||
self.fragment.style().max_inline_size()
|
||||
.to_used_value(self.base.block_container_inline_size)
|
||||
.unwrap_or(MAX_AU);
|
||||
let min_inline_size =
|
||||
self.fragment.style().min_inline_size().to_used_value(self.base.block_container_inline_size);
|
||||
let specified_inline_size = self.fragment.style().content_inline_size();
|
||||
let container_size = self.base.block_container_inline_size;
|
||||
let inline_size =
|
||||
|
@ -2413,8 +2410,7 @@ pub trait ISizeAndMarginsComputer {
|
|||
// If the tentative used inline-size is greater than 'max-inline-size', inline-size should
|
||||
// be recalculated, but this time using the computed value of 'max-inline-size' as the
|
||||
// computed value for 'inline-size'.
|
||||
match specified_or_none(block.fragment().style().max_inline_size(),
|
||||
containing_block_inline_size) {
|
||||
match block.fragment().style().max_inline_size().to_used_value(containing_block_inline_size) {
|
||||
Some(max_inline_size) if max_inline_size < solution.inline_size => {
|
||||
input.computed_inline_size = MaybeAuto::Specified(max_inline_size);
|
||||
solution = self.solve_inline_size_constraints(block, &input);
|
||||
|
@ -2425,8 +2421,8 @@ pub trait ISizeAndMarginsComputer {
|
|||
// If the resulting inline-size is smaller than 'min-inline-size', inline-size should be
|
||||
// recalculated, but this time using the value of 'min-inline-size' as the computed value
|
||||
// for 'inline-size'.
|
||||
let computed_min_inline_size = specified(block.fragment().style().min_inline_size(),
|
||||
containing_block_inline_size);
|
||||
let computed_min_inline_size =
|
||||
block.fragment().style().min_inline_size().to_used_value(containing_block_inline_size);
|
||||
if computed_min_inline_size > solution.inline_size {
|
||||
input.computed_inline_size = MaybeAuto::Specified(computed_min_inline_size);
|
||||
solution = self.solve_inline_size_constraints(block, &input);
|
||||
|
|
|
@ -33,7 +33,7 @@ use gfx_traits::{combine_id_with_fragment_type, FragmentType, StackingContextId}
|
|||
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
|
||||
use ipc_channel::ipc;
|
||||
use list_item::ListItemFlow;
|
||||
use model::{self, MaybeAuto, specified};
|
||||
use model::{self, MaybeAuto};
|
||||
use msg::constellation_msg::BrowsingContextId;
|
||||
use net_traits::image::base::PixelFormat;
|
||||
use net_traits::image_cache::UsePlaceholder;
|
||||
|
@ -1026,10 +1026,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
let horiz_position = *get_cyclic(&background.background_position_x.0, index);
|
||||
let vert_position = *get_cyclic(&background.background_position_y.0, index);
|
||||
// Use `background-position` to get the offset.
|
||||
let horizontal_position = model::specified(horiz_position,
|
||||
bounds.size.width - image_size.width);
|
||||
let vertical_position = model::specified(vert_position,
|
||||
bounds.size.height - image_size.height);
|
||||
let horizontal_position = horiz_position.to_used_value(bounds.size.width - image_size.width);
|
||||
let vertical_position = vert_position.to_used_value(bounds.size.height - image_size.height);
|
||||
|
||||
// The anchor position for this background, based on both the background-attachment
|
||||
// and background-position properties.
|
||||
|
@ -1185,8 +1183,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
repeating: bool,
|
||||
style: &ServoComputedValues)
|
||||
-> display_list::RadialGradient {
|
||||
let center = Point2D::new(specified(center.horizontal, bounds.size.width),
|
||||
specified(center.vertical, bounds.size.height));
|
||||
let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
|
||||
center.vertical.to_used_value(bounds.size.height));
|
||||
let radius = match *shape {
|
||||
GenericEndingShape::Circle(Circle::Radius(length)) => {
|
||||
Size2D::new(length, length)
|
||||
|
@ -1195,7 +1193,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
convert_circle_size_keyword(extent, &bounds.size, ¢er)
|
||||
},
|
||||
GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => {
|
||||
Size2D::new(specified(x, bounds.size.width), specified(y, bounds.size.height))
|
||||
Size2D::new(x.to_used_value(bounds.size.width), y.to_used_value(bounds.size.height))
|
||||
},
|
||||
GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => {
|
||||
convert_ellipse_size_keyword(extent, &bounds.size, ¢er)
|
||||
|
|
|
@ -18,7 +18,6 @@ use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED};
|
|||
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
|
||||
use layout_debug;
|
||||
use model::{IntrinsicISizes, MaybeAuto, SizeConstraint};
|
||||
use model::{specified, specified_or_none};
|
||||
use std::cmp::{max, min};
|
||||
use std::ops::Range;
|
||||
use style::computed_values::{align_content, align_self, flex_direction, flex_wrap, justify_content};
|
||||
|
@ -52,7 +51,7 @@ impl AxisSize {
|
|||
}
|
||||
}
|
||||
LengthOrPercentageOrAuto::Calc(calc) => {
|
||||
match calc.to_computed(content_size) {
|
||||
match calc.to_used_value(content_size) {
|
||||
Some(length) => AxisSize::Definite(length),
|
||||
None => AxisSize::Infinite,
|
||||
}
|
||||
|
@ -79,7 +78,7 @@ fn from_flex_basis(flex_basis: LengthOrPercentageOrAutoOrContent,
|
|||
(LengthOrPercentageOrAutoOrContent::Percentage(_), None) =>
|
||||
MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAutoOrContent::Calc(calc), _) =>
|
||||
MaybeAuto::from_option(calc.to_computed(containing_length)),
|
||||
MaybeAuto::from_option(calc.to_used_value(containing_length)),
|
||||
(LengthOrPercentageOrAutoOrContent::Content, _) =>
|
||||
MaybeAuto::Auto,
|
||||
(LengthOrPercentageOrAutoOrContent::Auto, Some(size)) =>
|
||||
|
@ -169,10 +168,11 @@ impl FlexItem {
|
|||
- margin
|
||||
+ block.fragment.box_sizing_boundary(direction);
|
||||
self.base_size = basis.specified_or_default(content_size);
|
||||
self.max_size = specified_or_none(block.fragment.style.max_inline_size(),
|
||||
containing_length).unwrap_or(MAX_AU);
|
||||
self.min_size = specified(block.fragment.style.min_inline_size(),
|
||||
containing_length);
|
||||
self.max_size =
|
||||
block.fragment.style.max_inline_size()
|
||||
.to_used_value(containing_length)
|
||||
.unwrap_or(MAX_AU);
|
||||
self.min_size = block.fragment.style.min_inline_size().to_used_value(containing_length);
|
||||
}
|
||||
Direction::Block => {
|
||||
let basis = from_flex_basis(block.fragment.style.get_position().flex_basis,
|
||||
|
@ -182,10 +182,11 @@ impl FlexItem {
|
|||
- block.fragment.border_padding.block_start_end()
|
||||
+ block.fragment.box_sizing_boundary(direction);
|
||||
self.base_size = basis.specified_or_default(content_size);
|
||||
self.max_size = specified_or_none(block.fragment.style.max_block_size(),
|
||||
containing_length).unwrap_or(MAX_AU);
|
||||
self.min_size = specified(block.fragment.style.min_block_size(),
|
||||
containing_length);
|
||||
self.max_size =
|
||||
block.fragment.style.max_block_size()
|
||||
.to_used_value(containing_length)
|
||||
.unwrap_or(MAX_AU);
|
||||
self.min_size = block.fragment.style.min_block_size().to_used_value(containing_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -907,8 +907,8 @@ impl Fragment {
|
|||
// cascading.
|
||||
let padding = if flags.contains(INTRINSIC_INLINE_SIZE_INCLUDES_PADDING) {
|
||||
let padding = style.logical_padding();
|
||||
(model::specified(padding.inline_start, Au(0)) +
|
||||
model::specified(padding.inline_end, Au(0)))
|
||||
(padding.inline_start.to_used_value(Au(0)) +
|
||||
padding.inline_end.to_used_value(Au(0)))
|
||||
} else {
|
||||
Au(0)
|
||||
};
|
||||
|
@ -935,8 +935,8 @@ impl Fragment {
|
|||
if flags.contains(INTRINSIC_INLINE_SIZE_INCLUDES_SPECIFIED) {
|
||||
specified = MaybeAuto::from_style(style.content_inline_size(),
|
||||
Au(0)).specified_or_zero();
|
||||
specified = max(model::specified(style.min_inline_size(), Au(0)), specified);
|
||||
if let Some(max) = model::specified_or_none(style.max_inline_size(), Au(0)) {
|
||||
specified = max(style.min_inline_size().to_used_value(Au(0)), specified);
|
||||
if let Some(max) = style.max_inline_size().to_used_value(Au(0)) {
|
||||
specified = min(specified, max)
|
||||
}
|
||||
|
||||
|
@ -1159,10 +1159,10 @@ impl Fragment {
|
|||
let border_width = self.border_width();
|
||||
SpeculatedInlineContentEdgeOffsets {
|
||||
start: MaybeAuto::from_style(logical_margin.inline_start, Au(0)).specified_or_zero() +
|
||||
model::specified(logical_padding.inline_start, Au(0)) +
|
||||
logical_padding.inline_start.to_used_value(Au(0)) +
|
||||
border_width.inline_start,
|
||||
end: MaybeAuto::from_style(logical_margin.inline_end, Au(0)).specified_or_zero() +
|
||||
model::specified(logical_padding.inline_end, Au(0)) +
|
||||
logical_padding.inline_end.to_used_value(Au(0)) +
|
||||
border_width.inline_end,
|
||||
}
|
||||
}
|
||||
|
@ -1491,10 +1491,10 @@ impl Fragment {
|
|||
// the size constraints work properly.
|
||||
// TODO(stshine): Find a cleaner way to do this.
|
||||
let padding = self.style.logical_padding();
|
||||
self.border_padding.inline_start = model::specified(padding.inline_start, Au(0));
|
||||
self.border_padding.inline_end = model::specified(padding.inline_end, Au(0));
|
||||
self.border_padding.block_start = model::specified(padding.block_start, Au(0));
|
||||
self.border_padding.block_end = model::specified(padding.block_end, Au(0));
|
||||
self.border_padding.inline_start = padding.inline_start.to_used_value(Au(0));
|
||||
self.border_padding.inline_end = padding.inline_end.to_used_value(Au(0));
|
||||
self.border_padding.block_start = padding.block_start.to_used_value(Au(0));
|
||||
self.border_padding.block_end = padding.block_end.to_used_value(Au(0));
|
||||
let border = self.border_width();
|
||||
self.border_padding.inline_start += border.inline_start;
|
||||
self.border_padding.inline_end += border.inline_end;
|
||||
|
@ -2847,12 +2847,14 @@ impl Fragment {
|
|||
|
||||
let mut transform = Matrix4D::identity();
|
||||
let transform_origin = &self.style.get_box().transform_origin;
|
||||
let transform_origin_x = model::specified(transform_origin.horizontal,
|
||||
stacking_relative_border_box.size
|
||||
.width).to_f32_px();
|
||||
let transform_origin_y = model::specified(transform_origin.vertical,
|
||||
stacking_relative_border_box.size
|
||||
.height).to_f32_px();
|
||||
let transform_origin_x =
|
||||
transform_origin.horizontal
|
||||
.to_used_value(stacking_relative_border_box.size.width)
|
||||
.to_f32_px();
|
||||
let transform_origin_y =
|
||||
transform_origin.vertical
|
||||
.to_used_value(stacking_relative_border_box.size.height)
|
||||
.to_f32_px();
|
||||
let transform_origin_z = transform_origin.depth.to_f32_px();
|
||||
|
||||
let pre_transform = Matrix4D::create_translation(transform_origin_x,
|
||||
|
@ -2875,10 +2877,8 @@ impl Fragment {
|
|||
Matrix4D::create_scale(sx, sy, sz)
|
||||
}
|
||||
transform::ComputedOperation::Translate(tx, ty, tz) => {
|
||||
let tx =
|
||||
model::specified(tx, stacking_relative_border_box.size.width).to_f32_px();
|
||||
let ty =
|
||||
model::specified(ty, stacking_relative_border_box.size.height).to_f32_px();
|
||||
let tx = tx.to_used_value(stacking_relative_border_box.size.width).to_f32_px();
|
||||
let ty = ty.to_used_value(stacking_relative_border_box.size.height).to_f32_px();
|
||||
let tz = tz.to_f32_px();
|
||||
Matrix4D::create_translation(tx, ty, tz)
|
||||
}
|
||||
|
@ -2907,10 +2907,13 @@ impl Fragment {
|
|||
Either::First(length) => {
|
||||
let perspective_origin = self.style().get_box().perspective_origin;
|
||||
let perspective_origin =
|
||||
Point2D::new(model::specified(perspective_origin.horizontal,
|
||||
stacking_relative_border_box.size.width).to_f32_px(),
|
||||
model::specified(perspective_origin.vertical,
|
||||
stacking_relative_border_box.size.height).to_f32_px());
|
||||
Point2D::new(
|
||||
perspective_origin.horizontal
|
||||
.to_used_value(stacking_relative_border_box.size.width)
|
||||
.to_f32_px(),
|
||||
perspective_origin.vertical
|
||||
.to_used_value(stacking_relative_border_box.size.height)
|
||||
.to_f32_px());
|
||||
|
||||
let pre_transform = Matrix4D::create_translation(perspective_origin.x,
|
||||
perspective_origin.y,
|
||||
|
|
|
@ -412,7 +412,7 @@ impl MaybeAuto {
|
|||
MaybeAuto::Specified(containing_length.scale_by(percent))
|
||||
}
|
||||
LengthOrPercentageOrAuto::Calc(calc) => {
|
||||
MaybeAuto::from_option(calc.to_computed(Some(containing_length)))
|
||||
MaybeAuto::from_option(calc.to_used_value(Some(containing_length)))
|
||||
}
|
||||
LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length)
|
||||
}
|
||||
|
@ -463,24 +463,6 @@ pub fn style_length(style_length: LengthOrPercentageOrAuto,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au) -> Option<Au> {
|
||||
match length {
|
||||
LengthOrPercentageOrNone::None => None,
|
||||
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
|
||||
LengthOrPercentageOrNone::Calc(calc) => calc.to_computed(Some(containing_length)),
|
||||
LengthOrPercentageOrNone::Length(length) => Some(length),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au {
|
||||
match length {
|
||||
LengthOrPercentage::Length(length) => length,
|
||||
LengthOrPercentage::Percentage(p) => containing_length.scale_by(p),
|
||||
LengthOrPercentage::Calc(calc) =>
|
||||
containing_length.scale_by(calc.percentage()) + calc.length(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes a border radius size against the containing size.
|
||||
///
|
||||
/// Note that percentages in `border-radius` are resolved against the relevant
|
||||
|
@ -495,8 +477,8 @@ pub fn specified_border_radius(
|
|||
-> Size2D<Au>
|
||||
{
|
||||
let generics::BorderRadiusSize(size) = radius;
|
||||
let w = specified(size.width, containing_size.width);
|
||||
let h = specified(size.height, containing_size.height);
|
||||
let w = size.width.to_used_value(containing_size.width);
|
||||
let h = size.height.to_used_value(containing_size.height);
|
||||
Size2D::new(w, h)
|
||||
}
|
||||
|
||||
|
@ -507,10 +489,10 @@ pub fn padding_from_style(style: &ServoComputedValues,
|
|||
-> LogicalMargin<Au> {
|
||||
let padding_style = style.get_padding();
|
||||
LogicalMargin::from_physical(writing_mode, SideOffsets2D::new(
|
||||
specified(padding_style.padding_top, containing_block_inline_size),
|
||||
specified(padding_style.padding_right, containing_block_inline_size),
|
||||
specified(padding_style.padding_bottom, containing_block_inline_size),
|
||||
specified(padding_style.padding_left, containing_block_inline_size)))
|
||||
padding_style.padding_top.to_used_value(containing_block_inline_size),
|
||||
padding_style.padding_right.to_used_value(containing_block_inline_size),
|
||||
padding_style.padding_bottom.to_used_value(containing_block_inline_size),
|
||||
padding_style.padding_left.to_used_value(containing_block_inline_size)))
|
||||
}
|
||||
|
||||
/// Returns the explicitly-specified margin lengths from the given style. Percentage and auto
|
||||
|
@ -559,7 +541,7 @@ impl SizeConstraint {
|
|||
max_size: LengthOrPercentageOrNone,
|
||||
border: Option<Au>) -> SizeConstraint {
|
||||
let mut min_size = match container_size {
|
||||
Some(container_size) => specified(min_size, container_size),
|
||||
Some(container_size) => min_size.to_used_value(container_size),
|
||||
None => if let LengthOrPercentage::Length(length) = min_size {
|
||||
length
|
||||
} else {
|
||||
|
@ -568,7 +550,7 @@ impl SizeConstraint {
|
|||
};
|
||||
|
||||
let mut max_size = match container_size {
|
||||
Some(container_size) => specified_or_none(max_size, container_size),
|
||||
Some(container_size) => max_size.to_used_value(container_size),
|
||||
None => if let LengthOrPercentageOrNone::Length(length) = max_size {
|
||||
Some(length)
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue