Refactor how calc() clamping is done on computed values (fixes #15296)

This commit is contained in:
Anthony Ramine 2017-05-16 15:44:59 +02:00
parent f935f2da01
commit d0b9bd9c64
13 changed files with 173 additions and 154 deletions

View file

@ -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);

View file

@ -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, &center)
},
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, &center)

View file

@ -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);
}
}
}

View file

@ -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,

View file

@ -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 {