Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

min/max-width/height, replaced elements #25207

Merged
merged 19 commits into from Dec 10, 2019
Merged
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a2c2b29
Move `clamp_*` functions to methods of `Length`
SimonSapin Dec 7, 2019
ce7e84b
Replace `percent_resolved_*` functions with methods
SimonSapin Dec 7, 2019
999dd72
Account for min/max-width in outer intrinsic sizing
SimonSapin Dec 7, 2019
bf96988
Add min/max-width/height support for `inline-block`
SimonSapin Dec 7, 2019
c40583b
Move replaced box used size computation to a method of `ReplacedConte…
SimonSapin Dec 7, 2019
b73eb49
Add sizing of inline replaced boxes
SimonSapin Dec 7, 2019
8996be3
Don’t assume replaced elements have an intrinsic size
SimonSapin Dec 7, 2019
80b2b5f
Fix min/max-content of replaced boxes
SimonSapin Dec 7, 2019
f43dc3a
Remove inline/block_size from AbsolutelyPositionedFragment
SimonSapin Dec 7, 2019
e86222d
Remove AbsoluteBoxOffsets’s type parameter
SimonSapin Dec 7, 2019
14ddf39
Rename ReplacedContent::used_size to used_size_as_if_inline_element
SimonSapin Dec 7, 2019
f09c14a
impl From<&'_ DefiniteContainingBlock> for ContainingBlock
SimonSapin Dec 7, 2019
1fcdde9
Move two AbsoluteBoxOffsets fields into a Vec2
SimonSapin Dec 7, 2019
1fa20e9
Implement replaced abspos
SimonSapin Dec 7, 2019
c07c980
Delayed initialization over mutation
SimonSapin Dec 8, 2019
2906722
Conditionsals over closures
SimonSapin Dec 8, 2019
be8df1d
Move `solve_axis` function to module level
SimonSapin Dec 8, 2019
a17db21
Struct with named fields over large tuple
SimonSapin Dec 8, 2019
53ce714
Fix a “Accessing content size that was not requested” panic
SimonSapin Dec 8, 2019
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Move replaced box used size computation to a method of `ReplacedConte…

…nts`
  • Loading branch information
SimonSapin committed Dec 10, 2019
commit c40583b64480acb4b4b7ec2ac8837a040827e006
@@ -521,160 +521,32 @@ fn layout_in_flow_replaced_block_level<'a>(
style: &Arc<ComputedValues>,
replaced: &ReplacedContent,
) -> BoxFragment {
let size = replaced.used_size(containing_block, style);

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 mode = style.writing_mode;
// FIXME(nox): We shouldn't pretend we always have a fully known intrinsic size.
let intrinsic_size = replaced.intrinsic_size.size_to_flow_relative(mode);
// FIXME(nox): This can divide by zero.
let intrinsic_ratio = intrinsic_size.inline.px() / intrinsic_size.block.px();

let box_size = style.box_size().percentages_relative_to(containing_block);
let min_box_size = style
.min_box_size()
.percentages_relative_to(containing_block)
.auto_is(Length::zero);
let max_box_size = style
.max_box_size()
.percentages_relative_to(containing_block);

let clamp = |inline_size: Length, block_size: Length| {
(
inline_size.clamp_between_extremums(min_box_size.inline, max_box_size.inline),
block_size.clamp_between_extremums(min_box_size.block, max_box_size.block),
)
};
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
let (inline_size, block_size) = match (box_size.inline, box_size.block) {
(LengthOrAuto::LengthPercentage(inline), LengthOrAuto::LengthPercentage(block)) => {
clamp(inline, block)
},
(LengthOrAuto::LengthPercentage(inline), LengthOrAuto::Auto) => {
clamp(inline, inline / intrinsic_ratio)
},
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(block)) => {
clamp(block * intrinsic_ratio, block)
},
(LengthOrAuto::Auto, LengthOrAuto::Auto) => {
enum Violation {
None,
Below(Length),
Above(Length),
}
let violation = |size, min_size, mut max_size: Option<Length>| {
if let Some(max) = max_size.as_mut() {
max.max_assign(min_size);
}
if size < min_size {
return Violation::Below(min_size);
}
match max_size {
Some(max_size) if size > max_size => Violation::Above(max_size),
_ => Violation::None,
}
};
match (
violation(
intrinsic_size.inline,
min_box_size.inline,
max_box_size.inline,
),
violation(intrinsic_size.block, min_box_size.block, max_box_size.block),
) {
// Row 1.
(Violation::None, Violation::None) => (intrinsic_size.inline, intrinsic_size.block),
// Row 2.
(Violation::Above(max_inline_size), Violation::None) => {
let block_size = (max_inline_size / intrinsic_ratio).max(min_box_size.block);
(max_inline_size, block_size)
},
// Row 3.
(Violation::Below(min_inline_size), Violation::None) => {
let block_size =
(min_inline_size / intrinsic_ratio).clamp_below_max(max_box_size.block);
(min_inline_size, block_size)
},
// Row 4.
(Violation::None, Violation::Above(max_block_size)) => {
let inline_size = (max_block_size * intrinsic_ratio).max(min_box_size.inline);
(inline_size, max_block_size)
},
// Row 5.
(Violation::None, Violation::Below(min_block_size)) => {
let inline_size =
(min_block_size * intrinsic_ratio).clamp_below_max(max_box_size.inline);
(inline_size, min_block_size)
},
// Rows 6-7.
(Violation::Above(max_inline_size), Violation::Above(max_block_size)) => {
if max_inline_size.px() / intrinsic_size.inline.px() <=
max_block_size.px() / intrinsic_size.block.px()
{
// Row 6.
let block_size =
(max_inline_size / intrinsic_ratio).max(min_box_size.block);
(max_inline_size, block_size)
} else {
// Row 7.
let inline_size =
(max_block_size * intrinsic_ratio).max(min_box_size.inline);
(inline_size, max_block_size)
}
},
// Rows 8-9.
(Violation::Below(min_inline_size), Violation::Below(min_block_size)) => {
if min_inline_size.px() / intrinsic_size.inline.px() <=
min_block_size.px() / intrinsic_size.block.px()
{
// Row 8.
let inline_size =
(min_block_size * intrinsic_ratio).clamp_below_max(max_box_size.inline);
(inline_size, min_block_size)
} else {
// Row 9.
let block_size =
(min_inline_size / intrinsic_ratio).clamp_below_max(max_box_size.block);
(min_inline_size, block_size)
}
},
// Row 10.
(Violation::Below(min_inline_size), Violation::Above(max_block_size)) => {
(min_inline_size, max_block_size)
},
// Row 11.
(Violation::Above(max_inline_size), Violation::Below(min_block_size)) => {
(max_inline_size, min_block_size)
},
}
},
};

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,
inline_size,
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),
};
let size = Vec2 {
block: block_size,
inline: inline_size,
};
let fragments = replaced.make_fragments(style, size.clone());
let relative_adjustement = relative_adjustement(
style,
inline_size,
LengthOrAuto::LengthPercentage(block_size),
size.inline,
LengthOrAuto::LengthPercentage(size.block),
);
let content_rect = Rect {
start_corner: Vec2 {
@@ -5,11 +5,14 @@
use crate::dom_traversal::NodeExt;
use crate::fragments::{Fragment, ImageFragment};
use crate::geom::{flow_relative, physical};
use crate::style_ext::ComputedValuesExt;
use crate::ContainingBlock;
use net_traits::image::base::Image;
use servo_arc::Arc as ServoArc;
use std::sync::Arc;
use style::properties::ComputedValues;
use style::values::computed::Length;
use style::values::computed::{Length, LengthOrAuto};
use style::Zero;

#[derive(Debug)]
pub(crate) struct ReplacedContent {
@@ -56,4 +59,147 @@ impl ReplacedContent {
.collect(),
}
}

// https://drafts.csswg.org/css2/visudet.html#inline-replaced-width
// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height
pub fn used_size(
&self,
containing_block: &ContainingBlock,
style: &ComputedValues,
) -> flow_relative::Vec2<Length> {
let mode = style.writing_mode;
// FIXME(nox): We shouldn't pretend we always have a fully known intrinsic size.
let intrinsic_size = self.intrinsic_size.size_to_flow_relative(mode);
// FIXME(nox): This can divide by zero.
let intrinsic_ratio = intrinsic_size.inline.px() / intrinsic_size.block.px();

let box_size = style.box_size().percentages_relative_to(containing_block);
let min_box_size = style
.min_box_size()
.percentages_relative_to(containing_block)
.auto_is(Length::zero);
let max_box_size = style
.max_box_size()
.percentages_relative_to(containing_block);

let clamp = |inline_size: Length, block_size: Length| {
(
inline_size.clamp_between_extremums(min_box_size.inline, max_box_size.inline),
block_size.clamp_between_extremums(min_box_size.block, max_box_size.block),
)
};
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
let (inline_size, block_size) = match (box_size.inline, box_size.block) {
(LengthOrAuto::LengthPercentage(inline), LengthOrAuto::LengthPercentage(block)) => {
clamp(inline, block)
},
(LengthOrAuto::LengthPercentage(inline), LengthOrAuto::Auto) => {
clamp(inline, inline / intrinsic_ratio)
},
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(block)) => {
clamp(block * intrinsic_ratio, block)
},
(LengthOrAuto::Auto, LengthOrAuto::Auto) => {
enum Violation {
None,
Below(Length),
Above(Length),
}
let violation = |size, min_size, mut max_size: Option<Length>| {
if let Some(max) = max_size.as_mut() {
max.max_assign(min_size);
}
if size < min_size {
return Violation::Below(min_size);
}
match max_size {
Some(max_size) if size > max_size => Violation::Above(max_size),
_ => Violation::None,
}
};
match (
violation(
intrinsic_size.inline,
min_box_size.inline,
max_box_size.inline,
),
violation(intrinsic_size.block, min_box_size.block, max_box_size.block),
) {
// Row 1.
(Violation::None, Violation::None) => {
(intrinsic_size.inline, intrinsic_size.block)
},
// Row 2.
(Violation::Above(max_inline_size), Violation::None) => {
let block_size =
(max_inline_size / intrinsic_ratio).max(min_box_size.block);
(max_inline_size, block_size)
},
// Row 3.
(Violation::Below(min_inline_size), Violation::None) => {
let block_size =
(min_inline_size / intrinsic_ratio).clamp_below_max(max_box_size.block);
(min_inline_size, block_size)
},
// Row 4.
(Violation::None, Violation::Above(max_block_size)) => {
let inline_size =
(max_block_size * intrinsic_ratio).max(min_box_size.inline);
(inline_size, max_block_size)
},
// Row 5.
(Violation::None, Violation::Below(min_block_size)) => {
let inline_size =
(min_block_size * intrinsic_ratio).clamp_below_max(max_box_size.inline);
(inline_size, min_block_size)
},
// Rows 6-7.
(Violation::Above(max_inline_size), Violation::Above(max_block_size)) => {
if max_inline_size.px() / intrinsic_size.inline.px() <=
max_block_size.px() / intrinsic_size.block.px()
{
// Row 6.
let block_size =
(max_inline_size / intrinsic_ratio).max(min_box_size.block);
(max_inline_size, block_size)
} else {
// Row 7.
let inline_size =
(max_block_size * intrinsic_ratio).max(min_box_size.inline);
(inline_size, max_block_size)
}
},
// Rows 8-9.
(Violation::Below(min_inline_size), Violation::Below(min_block_size)) => {
if min_inline_size.px() / intrinsic_size.inline.px() <=
min_block_size.px() / intrinsic_size.block.px()
{
// Row 8.
let inline_size = (min_block_size * intrinsic_ratio)
.clamp_below_max(max_box_size.inline);
(inline_size, min_block_size)
} else {
// Row 9.
let block_size = (min_inline_size / intrinsic_ratio)
.clamp_below_max(max_box_size.block);
(min_inline_size, block_size)
}
},
// Row 10.
(Violation::Below(min_inline_size), Violation::Above(max_block_size)) => {
(min_inline_size, max_block_size)
},
// Row 11.
(Violation::Above(max_inline_size), Violation::Below(min_block_size)) => {
(max_inline_size, min_block_size)
},
}
},
};
flow_relative::Vec2 {
inline: inline_size,
block: block_size,
}
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.