mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
layout: Take min-height
and max-height
into account
This commit is contained in:
parent
cd9d824c21
commit
9874d0f9d3
1 changed files with 156 additions and 27 deletions
|
@ -12,24 +12,33 @@
|
||||||
//!
|
//!
|
||||||
//! CB: Containing Block of the current flow.
|
//! CB: Containing Block of the current flow.
|
||||||
|
|
||||||
use layout::box_::{Box, ImageBox, ScannedTextBox};
|
use layout::box_::{Box, ImageBox, MainBoxKind, ScannedTextBox};
|
||||||
use layout::construct::FlowConstructor;
|
use layout::construct::FlowConstructor;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
use layout::display_list_builder::{DisplayListBuilder, DisplayListBuildingInfo};
|
||||||
use layout::floats::{FloatKind, Floats, PlacementInfo};
|
use layout::floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, Floats, PlacementInfo};
|
||||||
use layout::flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
use layout::flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||||
use layout::flow::{mut_base, PreorderFlowTraversal, PostorderFlowTraversal, MutableFlowUtils};
|
use layout::flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
||||||
use layout::flow;
|
use layout::flow;
|
||||||
use layout::model::{MaybeAuto, Specified, Auto, specified_or_none, specified};
|
use layout::model::{Auto, IntrinsicWidths, MarginCollapseInfo, MarginsCollapse};
|
||||||
|
use layout::model::{MarginsCollapseThrough, MaybeAuto, NoCollapsibleMargins, Specified, specified};
|
||||||
|
use layout::model::{specified_or_none};
|
||||||
use layout::wrapper::ThreadSafeLayoutNode;
|
use layout::wrapper::ThreadSafeLayoutNode;
|
||||||
use style::computed_values::{position};
|
use style::ComputedValues;
|
||||||
|
use style::computed_values::{clear, position};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::{DisplayListCollection, DisplayList};
|
use gfx::color;
|
||||||
|
use gfx::display_list::{BackgroundAndBorderLevel, BlockLevel, RootOfStackingContextLevel};
|
||||||
|
use gfx::display_list::{StackingContext};
|
||||||
|
use gfx::render_task::RenderLayer;
|
||||||
|
use servo_msg::compositor_msg::{FixedPosition, LayerId, Scrollable};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::geometry;
|
use servo_util::geometry;
|
||||||
use servo_util::smallvec::{SmallVec, SmallVec0};
|
use servo_util::smallvec::{SmallVec, SmallVec0};
|
||||||
|
use style::computed_values::{LPA_Auto, LPA_Length, LPA_Percentage, LPN_Length, LPN_None};
|
||||||
|
use style::computed_values::{LPN_Percentage, LP_Length, LP_Percentage};
|
||||||
|
use sync::Arc;
|
||||||
|
|
||||||
/// Information specific to floated blocks.
|
/// Information specific to floated blocks.
|
||||||
pub struct FloatedBlockInfo {
|
pub struct FloatedBlockInfo {
|
||||||
|
@ -98,7 +107,7 @@ impl HeightConstraintSolution {
|
||||||
content_height: Au,
|
content_height: Au,
|
||||||
available_height: Au,
|
available_height: Au,
|
||||||
static_y_offset: Au)
|
static_y_offset: Au)
|
||||||
-> HeightConstraintSolution {
|
-> HeightConstraintSolution {
|
||||||
// Distance from the top edge of the Absolute Containing Block to the
|
// Distance from the top edge of the Absolute Containing Block to the
|
||||||
// top margin edge of a hypothetical box that would have been the
|
// top margin edge of a hypothetical box that would have been the
|
||||||
// first box of the element.
|
// first box of the element.
|
||||||
|
@ -265,6 +274,115 @@ impl HeightConstraintSolution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs height calculations potentially multiple times, taking `height`, `min-height`, and
|
||||||
|
/// `max-height` into account. After each call to `next()`, the caller must call `.try()` with the
|
||||||
|
/// current calculated value of `height`.
|
||||||
|
///
|
||||||
|
/// See CSS 2.1 § 10.7.
|
||||||
|
struct CandidateHeightIterator {
|
||||||
|
height: MaybeAuto,
|
||||||
|
max_height: Option<Au>,
|
||||||
|
min_height: Au,
|
||||||
|
candidate_value: Au,
|
||||||
|
status: CandidateHeightIteratorStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CandidateHeightIterator {
|
||||||
|
pub fn new(style: &ComputedValues, auto_value: Au, is_absolutely_positioned: bool)
|
||||||
|
-> CandidateHeightIterator {
|
||||||
|
// Per CSS 2.1 § 10.7, if the height is not *specified explicitly*, then we ignore
|
||||||
|
// `min-height` and `max-height`. Heights are considered to be specified explicitly if the
|
||||||
|
// element is absolutely positioned or the value of the containing block's height depends
|
||||||
|
// on the content.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): Consider heights specified explicitly if the containing block's height
|
||||||
|
// depends on the content.
|
||||||
|
let height_specified_explicitly = is_absolutely_positioned;
|
||||||
|
|
||||||
|
let height = match style.Box.get().height {
|
||||||
|
LPA_Percentage(percent) if height_specified_explicitly => {
|
||||||
|
Specified(auto_value.scale_by(percent))
|
||||||
|
}
|
||||||
|
LPA_Percentage(_) | LPA_Auto => Auto,
|
||||||
|
LPA_Length(length) => Specified(length),
|
||||||
|
};
|
||||||
|
let max_height = match style.Box.get().max_height {
|
||||||
|
LPN_Percentage(percent) if height_specified_explicitly => {
|
||||||
|
Some(auto_value.scale_by(percent))
|
||||||
|
}
|
||||||
|
LPN_Percentage(_) | LPN_None => None,
|
||||||
|
LPN_Length(length) => Some(length),
|
||||||
|
};
|
||||||
|
let min_height = match style.Box.get().min_height {
|
||||||
|
LP_Percentage(percent) if height_specified_explicitly => auto_value.scale_by(percent),
|
||||||
|
LP_Percentage(_) => Au(0),
|
||||||
|
LP_Length(length) => length,
|
||||||
|
};
|
||||||
|
|
||||||
|
CandidateHeightIterator {
|
||||||
|
height: height,
|
||||||
|
max_height: max_height,
|
||||||
|
min_height: min_height,
|
||||||
|
candidate_value: Au(0),
|
||||||
|
status: InitialCandidateHeightStatus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next<'a>(&'a mut self) -> Option<(MaybeAuto, &'a mut Au)> {
|
||||||
|
self.status = match self.status {
|
||||||
|
InitialCandidateHeightStatus => TryingHeightCandidateHeightStatus,
|
||||||
|
TryingHeightCandidateHeightStatus => {
|
||||||
|
match self.max_height {
|
||||||
|
Some(max_height) if self.candidate_value > max_height => {
|
||||||
|
TryingMaxCandidateHeightStatus
|
||||||
|
}
|
||||||
|
_ if self.candidate_value < self.min_height => TryingMinCandidateHeightStatus,
|
||||||
|
_ => FoundCandidateHeightStatus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TryingMaxCandidateHeightStatus => {
|
||||||
|
if self.candidate_value < self.min_height {
|
||||||
|
TryingMinCandidateHeightStatus
|
||||||
|
} else {
|
||||||
|
FoundCandidateHeightStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TryingMinCandidateHeightStatus | FoundCandidateHeightStatus => {
|
||||||
|
FoundCandidateHeightStatus
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.status {
|
||||||
|
TryingHeightCandidateHeightStatus => Some((self.height, &mut self.candidate_value)),
|
||||||
|
TryingMaxCandidateHeightStatus => {
|
||||||
|
Some((Specified(self.max_height.unwrap()), &mut self.candidate_value))
|
||||||
|
}
|
||||||
|
TryingMinCandidateHeightStatus => {
|
||||||
|
Some((Specified(self.min_height), &mut self.candidate_value))
|
||||||
|
}
|
||||||
|
FoundCandidateHeightStatus => None,
|
||||||
|
InitialCandidateHeightStatus => fail!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CandidateHeightIteratorStatus {
|
||||||
|
InitialCandidateHeightStatus,
|
||||||
|
TryingHeightCandidateHeightStatus,
|
||||||
|
TryingMaxCandidateHeightStatus,
|
||||||
|
TryingMinCandidateHeightStatus,
|
||||||
|
FoundCandidateHeightStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
// A helper function used in height calculation.
|
||||||
|
fn translate_including_floats(cur_y: &mut Au, delta: Au, inorder: bool, floats: &mut Floats) {
|
||||||
|
*cur_y = *cur_y + delta;
|
||||||
|
|
||||||
|
if inorder {
|
||||||
|
floats.translate(Point2D(Au(0), -delta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The real assign-heights traversal for flows with position 'absolute'.
|
/// The real assign-heights traversal for flows with position 'absolute'.
|
||||||
///
|
///
|
||||||
/// This is a traversal of an Absolute Flow tree.
|
/// This is a traversal of an Absolute Flow tree.
|
||||||
|
@ -1288,25 +1406,36 @@ impl BlockFlow {
|
||||||
// margin because of erroneous height calculation in Box_.
|
// margin because of erroneous height calculation in Box_.
|
||||||
// Check this when that has been fixed.
|
// Check this when that has been fixed.
|
||||||
let height_used_val = box_.border_box.get().size.height;
|
let height_used_val = box_.border_box.get().size.height;
|
||||||
HeightConstraintSolution::solve_vertical_constraints_abs_replaced(height_used_val,
|
solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced(
|
||||||
margin_top,
|
height_used_val,
|
||||||
margin_bottom,
|
margin_top,
|
||||||
top,
|
margin_bottom,
|
||||||
bottom,
|
top,
|
||||||
content_height,
|
bottom,
|
||||||
available_height,
|
content_height,
|
||||||
static_y_offset)
|
available_height,
|
||||||
|
static_y_offset));
|
||||||
} else {
|
} else {
|
||||||
HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
|
let mut candidate_height_iterator =
|
||||||
height_used_val,
|
CandidateHeightIterator::new(style, containing_block_height, true);
|
||||||
margin_top,
|
|
||||||
margin_bottom,
|
for (height_used_val, new_candidate_height) in candidate_height_iterator {
|
||||||
top,
|
solution =
|
||||||
bottom,
|
Some(HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
|
||||||
content_height,
|
height_used_val,
|
||||||
available_height,
|
margin_top,
|
||||||
static_y_offset)
|
margin_bottom,
|
||||||
};
|
top,
|
||||||
|
bottom,
|
||||||
|
content_height,
|
||||||
|
available_height,
|
||||||
|
static_y_offset));
|
||||||
|
|
||||||
|
*new_candidate_height = solution.unwrap().height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let solution = solution.unwrap();
|
||||||
|
|
||||||
let mut margin = box_.margin.get();
|
let mut margin = box_.margin.get();
|
||||||
margin.top = solution.margin_top;
|
margin.top = solution.margin_top;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue