Implement min-width and max-width for non-block flows.

+ Add simple reftests.
+ Add reftests for float min-width and max-width.
This commit is contained in:
S Pradeep Kumar 2014-03-07 19:08:31 +09:00
parent e98c839ab0
commit 9d510a7112
12 changed files with 292 additions and 77 deletions

View file

@ -364,23 +364,25 @@ impl BlockFlow {
} }
} }
pub fn new_root(base: BaseFlow) -> BlockFlow { fn width_computer(&mut self) -> ~WidthAndMarginsComputer {
BlockFlow { if self.is_absolutely_positioned() {
base: base, if self.is_replaced_content() {
box_: None, ~AbsoluteReplaced as ~WidthAndMarginsComputer
is_root: true, } else {
static_y_offset: Au::new(0), ~AbsoluteNonReplaced as ~WidthAndMarginsComputer
float: None }
} } else if self.is_float() {
} if self.is_replaced_content() {
~FloatReplaced as ~WidthAndMarginsComputer
pub fn new_float(base: BaseFlow, float_kind: FloatKind) -> BlockFlow { } else {
BlockFlow { ~FloatNonReplaced as ~WidthAndMarginsComputer
base: base, }
box_: None, } else {
is_root: false, if self.is_replaced_content() {
static_y_offset: Au::new(0), ~BlockReplaced as ~WidthAndMarginsComputer
float: Some(~FloatedBlockInfo::new(float_kind)) } else {
~BlockNonReplaced as ~WidthAndMarginsComputer
}
} }
} }
@ -1282,28 +1284,7 @@ impl Flow for BlockFlow {
self.base.flags_info.flags.set_inorder(false); self.base.flags_info.flags.set_inorder(false);
} }
let width_computer; let width_computer = self.width_computer();
// TODO(pradeep): Extract this into a method.
width_computer = if self.is_absolutely_positioned() {
if self.is_replaced_content() {
&AbsoluteReplaced as &WidthAndMarginsComputer
} else {
&AbsoluteNonReplaced as &WidthAndMarginsComputer
}
} else if self.is_float() {
if self.is_replaced_content() {
&FloatReplaced as &WidthAndMarginsComputer
} else {
&FloatNonReplaced as &WidthAndMarginsComputer
}
} else {
if self.is_replaced_content() {
&BlockReplaced as &WidthAndMarginsComputer
} else {
&BlockNonReplaced as &WidthAndMarginsComputer
}
};
width_computer.compute_used_width(self, ctx, containing_block_width); width_computer.compute_used_width(self, ctx, containing_block_width);
for box_ in self.box_.iter() { for box_ in self.box_.iter() {
@ -1591,16 +1572,19 @@ impl WidthConstraintSolution {
} }
} }
// Trait to encapsulate the Width and Margin calculation.
//
// CSS Section 10.3
trait WidthAndMarginsComputer { trait WidthAndMarginsComputer {
/// Any pre-computation to be done for widths. /// Compute the inputs for the Width constraint equation.
/// ///
/// Compute and return the necessary input values from the box's style. /// This is called only once to compute the initial inputs. For
/// This is called only once. /// calculation involving min-width and max-width, we don't need to
// TODO(pradeep): Rename this to compute_inputs /// recompute these.
fn pre_computation(&self, fn compute_width_constraint_inputs(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
parent_flow_width: Au, parent_flow_width: Au,
ctx: &mut LayoutContext) ctx: &mut LayoutContext)
-> WidthConstraintInput { -> WidthConstraintInput {
let containing_block_width = self.containing_block_width(block, parent_flow_width, ctx); let containing_block_width = self.containing_block_width(block, parent_flow_width, ctx);
let computed_width = self.initial_computed_width(block, parent_flow_width, ctx); let computed_width = self.initial_computed_width(block, parent_flow_width, ctx);
@ -1694,40 +1678,33 @@ trait WidthAndMarginsComputer {
block: &mut BlockFlow, block: &mut BlockFlow,
ctx: &mut LayoutContext, ctx: &mut LayoutContext,
parent_flow_width: Au) { parent_flow_width: Au) {
// TODO(pradeep): First, get the constraint solutions. Then, do the let mut input = self.compute_width_constraint_inputs(block, parent_flow_width, ctx);
// min-width + max-width dance. THEN, set the width in the Box.
let input = self.pre_computation(block, parent_flow_width, ctx); let containing_block_width = self.containing_block_width(block, parent_flow_width, ctx);
let mut solution = self.solve_width_constraints(block, input);
// If the tentative used width is greater than 'max-width', width should be recalculated,
// but this time using the computed value of 'max-width' as the computed value for 'width'.
match specified_or_none(block.box_().style().Box.get().max_width, containing_block_width) {
Some(max_width) if max_width < solution.width => {
input.computed_width = Specified(max_width);
solution = self.solve_width_constraints(block, input);
}
_ => {}
}
// If the resulting width is smaller than 'min-width', width should be recalculated,
// but this time using the value of 'min-width' as the computed value for 'width'.
let computed_min_width = specified(block.box_().style().Box.get().min_width,
containing_block_width);
if computed_min_width > solution.width {
input.computed_width = Specified(computed_min_width);
solution = self.solve_width_constraints(block, input);
}
let solution = self.solve_width_constraints(block, input);
self.set_width_constraint_solutions(block, solution); self.set_width_constraint_solutions(block, solution);
self.set_flow_x_coord_if_necessary(block, solution); self.set_flow_x_coord_if_necessary(block, solution);
// // If the tentative used width is greater than 'max-width', width should be recalculated,
// // but this time using the computed value of 'max-width' as the computed value for 'width'.
// let (width, margin_left, margin_right) = {
// match specified_or_none(style.Box.get().max_width, containing_block_width) {
// Some(value) if value < width => block.compute_horiz(Specified(value),
// maybe_margin_left,
// maybe_margin_right,
// available_width),
// _ => (width, margin_left, margin_right)
// }
// };
// // If the resulting width is smaller than 'min-width', width should be recalculated,
// // but this time using the value of 'min-width' as the computed value for 'width'.
// let (width, margin_left, margin_right) = {
// let computed_min_width = specified(style.Box.get().min_width, containing_block_width);
// if computed_min_width > width {
// block.compute_horiz(Specified(computed_min_width),
// maybe_margin_left,
// maybe_margin_right,
// available_width)
// } else {
// (width, margin_left, margin_right)
// }
// };
} }
/// Computes left and right margins and width. /// Computes left and right margins and width.
@ -1800,6 +1777,10 @@ trait WidthAndMarginsComputer {
} }
} }
/// The different types of Blocks.
///
/// They mainly differ in the way width and heights and margins are calculated
/// for them.
struct AbsoluteNonReplaced; struct AbsoluteNonReplaced;
struct AbsoluteReplaced; struct AbsoluteReplaced;
struct BlockNonReplaced; struct BlockNonReplaced;

View file

@ -35,6 +35,10 @@
== object_element_a.html object_element_b.html == object_element_a.html object_element_b.html
== height_compute_reset.html height_compute.html == height_compute_reset.html height_compute.html
== width_nonreplaced_block_simple_a.html width_nonreplaced_block_simple_b.html == width_nonreplaced_block_simple_a.html width_nonreplaced_block_simple_b.html
== max_width_float_simple_a.html max_width_float_simple_b.html
== max_width_simple_a.html max_width_simple_b.html
== min_width_float_simple_a.html min_width_float_simple_b.html
== min_width_simple_a.html min_width_simple_b.html
# Positioning tests # Positioning tests
== position_abs_cb_with_non_cb_kid_a.html position_abs_cb_with_non_cb_kid_b.html == position_abs_cb_with_non_cb_kid_a.html position_abs_cb_with_non_cb_kid_b.html
== position_abs_height_width_a.html position_abs_height_width_b.html == position_abs_height_width_a.html position_abs_height_width_b.html

View file

@ -0,0 +1,24 @@
<html>
<head>
<style>
#first {
width: 100px;
height: 100px;
border: solid 1px;
}
#float {
float: left;
height: 50px;
width: 50px;
max-width: 40px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="float">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,22 @@
<html>
<head>
<style>
#first {
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 40px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,24 @@
<html>
<head>
<style>
#first {
position: relative;
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 50%;
max-width: 40px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,22 @@
<html>
<head>
<style>
#first {
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 40px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,25 @@
<html>
<head>
<style>
#first {
position: relative;
width: 100px;
height: 100px;
border: solid 1px;
}
#float {
float: left;
height: 50px;
width: 50%;
min-width: 60px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="float">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,22 @@
<html>
<head>
<style>
#first {
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 60px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,24 @@
<html>
<head>
<style>
#first {
position: relative;
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 50%;
min-width: 60px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,22 @@
<html>
<head>
<style>
#first {
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 60px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,23 @@
<html>
<head>
<style>
#first {
position: relative;
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 50%;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,22 @@
<html>
<head>
<style>
#first {
width: 100px;
height: 100px;
border: solid 1px;
}
#block {
height: 50px;
width: 50px;
background: green;
}
</style>
</head>
<body>
<div id="first">
<div id="block">
</div>
</div>
</body>
</html>