aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-04-14 18:14:11 -0500
committerbors-servo <metajack+bors@gmail.com>2015-04-14 18:14:11 -0500
commitbdcf606f4802e5b1ab3ee251b45ee1e81800359a (patch)
treefaca884b34b5ae66de7e3742436e95b2a5d6bcf4
parent3dc25af9e121db010e4385efb3863ba45b0e0bcf (diff)
parent82fcbf78704cce6f425d1d8a5abbdd58469e8eb0 (diff)
downloadservo-bdcf606f4802e5b1ab3ee251b45ee1e81800359a.tar.gz
servo-bdcf606f4802e5b1ab3ee251b45ee1e81800359a.zip
Auto merge of #5691 - pcwalton:hypothetical-box-reform, r=glennw
Before this change, Servo used one code path that computed the position of flows with `position: static` or `position: relative` and another separate code path that computed the position of flows with `position: absolute` or `position: fixed`. The latter code attempted to duplicate the former code to determine the static position of hypothetical boxes, but this was both fragile and incorrect in the case of hypothetical boxes nested inside floats. In fact, it's impossible to determine the static position of an absolute flow relative to its containing block at inline-size assignment time, because that static position could depend on a float that cannot be placed until block-size assignment! This patch changes block layout to use the same code path for static positioning of regular flows and static positioning of absolute flows where applicable. This both simplifies the code and improves its efficiency, since it allows the `hypothetical_position` field and `static_block_offsets` data structure to be removed. Moreover, it improves correctness in the above case (which the new reftest checks). This allows the sidebar in Facebook Timeline to be positioned properly. r? @glennw <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/5691) <!-- Reviewable:end -->
-rw-r--r--components/layout/block.rs797
-rw-r--r--components/layout/flow.rs146
-rw-r--r--components/layout/fragment.rs3
-rw-r--r--components/layout/inline.rs7
-rw-r--r--components/layout/model.rs11
-rw-r--r--components/layout/table.rs5
-rw-r--r--components/layout/table_wrapper.rs6
-rw-r--r--components/style/properties.mako.rs6
-rw-r--r--tests/ref/absolute_hypothetical_float_a.html21
-rw-r--r--tests/ref/absolute_hypothetical_float_ref.html21
-rw-r--r--tests/ref/basic.list1
11 files changed, 492 insertions, 532 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index 5dc867e45ee..e24dd869894 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -34,8 +34,8 @@ use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{self, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
use flow::{ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal};
use flow::{PostorderFlowTraversal, mut_base};
-use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
-use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
+use flow::{BLOCK_POSITION_IS_STATIC, HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
+use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC};
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
use flow::{IS_ABSOLUTELY_POSITIONED};
use flow::{CLEARS_LEFT, CLEARS_RIGHT};
@@ -90,7 +90,6 @@ impl FloatedBlockInfo {
#[derive(Copy)]
struct BSizeConstraintSolution {
block_start: Au,
- _block_end: Au,
block_size: Au,
margin_block_start: Au,
margin_block_end: Au
@@ -98,14 +97,12 @@ struct BSizeConstraintSolution {
impl BSizeConstraintSolution {
fn new(block_start: Au,
- block_end: Au,
block_size: Au,
margin_block_start: Au,
margin_block_end: Au)
-> BSizeConstraintSolution {
BSizeConstraintSolution {
block_start: block_start,
- _block_end: block_end,
block_size: block_size,
margin_block_start: margin_block_start,
margin_block_end: margin_block_end,
@@ -127,30 +124,18 @@ impl BSizeConstraintSolution {
block_start: MaybeAuto,
block_end: MaybeAuto,
content_block_size: Au,
- available_block_size: Au,
- static_b_offset: Au)
+ available_block_size: Au)
-> BSizeConstraintSolution {
- // Distance from the block-start edge of the Absolute Containing Block to the
- // block-start margin edge of a hypothetical box that would have been the
- // first box of the element.
- let static_position_block_start = static_b_offset;
-
- let (block_start, block_end, block_size, margin_block_start, margin_block_end) =
+ let (block_start, block_size, margin_block_start, margin_block_end) =
match (block_start, block_end, block_size) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
- let block_start = static_position_block_start;
// Now it is the same situation as block-start Specified and block-end
// and block-size Auto.
-
let block_size = content_block_size;
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start,
- available_block_size - sum,
- block_size,
- margin_block_start,
- margin_block_end)
+ // Use a dummy value for `block_start`, since it has the static position.
+ (Au(0), block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start),
MaybeAuto::Specified(block_end),
@@ -159,36 +144,26 @@ impl BSizeConstraintSolution {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let total_margin_val =
available_block_size - block_start - block_end - block_size;
- (block_start, block_end, block_size,
+ (block_start,
+ block_size,
total_margin_val.scale_by(0.5),
total_margin_val.scale_by(0.5))
}
(MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => {
let sum = block_start + block_end + block_size + margin_block_start;
(block_start,
- block_end,
block_size,
margin_block_start,
available_block_size - sum)
}
(MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => {
let sum = block_start + block_end + block_size + margin_block_end;
- (block_start,
- block_end,
- block_size,
- available_block_size - sum,
- margin_block_end)
+ (block_start, block_size, available_block_size - sum, margin_block_end)
}
(MaybeAuto::Specified(margin_block_start),
MaybeAuto::Specified(margin_block_end)) => {
// Values are over-constrained. Ignore value for 'block-end'.
- let sum = block_start + block_size + margin_block_start +
- margin_block_end;
- (block_start,
- available_block_size - sum,
- block_size,
- margin_block_start,
- margin_block_end)
+ (block_start, block_size, margin_block_start, margin_block_end)
}
}
}
@@ -202,23 +177,14 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_end + block_size + margin_block_start + margin_block_end;
- (available_block_size - sum,
- block_end,
- block_size,
- margin_block_start,
- margin_block_end)
+ (available_block_size - sum, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start),
MaybeAuto::Auto,
MaybeAuto::Specified(block_size)) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start,
- available_block_size - sum,
- block_size,
- margin_block_start,
- margin_block_end)
+ (block_start, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start),
MaybeAuto::Specified(block_end),
@@ -226,11 +192,7 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_start + block_end + margin_block_start + margin_block_end;
- (block_start,
- block_end,
- available_block_size - sum,
- margin_block_start,
- margin_block_end)
+ (block_start, available_block_size - sum, margin_block_start, margin_block_end)
}
// If block-size is auto, then block-size is content block-size. Solve for the
@@ -239,43 +201,25 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_size = content_block_size;
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start,
- available_block_size - sum,
- block_size,
- margin_block_start,
- margin_block_end)
+ (block_start, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Auto, MaybeAuto::Specified(block_end), MaybeAuto::Auto) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_size = content_block_size;
let sum = block_end + block_size + margin_block_start + margin_block_end;
- (available_block_size - sum,
- block_end,
- block_size,
- margin_block_start,
- margin_block_end)
+ (available_block_size - sum, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(block_size)) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
- let block_start = static_position_block_start;
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start,
- available_block_size - sum,
- block_size,
- margin_block_start,
- margin_block_end)
+ // Use a dummy value for `block_start`, since it has the static position.
+ (Au(0), block_size, margin_block_start, margin_block_end)
}
};
- BSizeConstraintSolution::new(block_start,
- block_end,
- block_size,
- margin_block_start,
- margin_block_end)
+ BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end)
}
/// Solve the vertical constraint equation for absolute replaced elements.
@@ -286,7 +230,7 @@ impl BSizeConstraintSolution {
/// Constraint equation:
/// block-start + block-end + block-size + margin-block-start + margin-block-end
/// = absolute containing block block-size - (vertical padding and border)
- /// [aka available_block-size]
+ /// [aka available block-size]
///
/// Return the solution for the equation.
fn solve_vertical_constraints_abs_replaced(block_size: Au,
@@ -295,61 +239,59 @@ impl BSizeConstraintSolution {
block_start: MaybeAuto,
block_end: MaybeAuto,
_: Au,
- available_block_size: Au,
- static_b_offset: Au)
+ available_block_size: Au)
-> BSizeConstraintSolution {
- // Distance from the block-start edge of the Absolute Containing Block to the
- // block-start margin edge of a hypothetical box that would have been the
- // first box of the element.
- let static_position_block_start = static_b_offset;
-
- let (block_start, block_end, block_size, margin_block_start, margin_block_end) = match (block_start, block_end) {
- (MaybeAuto::Auto, MaybeAuto::Auto) => {
- let margin_block_start = block_start_margin.specified_or_zero();
- let margin_block_end = block_end_margin.specified_or_zero();
- let block_start = static_position_block_start;
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start, available_block_size - sum, block_size, margin_block_start, margin_block_end)
- }
- (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => {
- match (block_start_margin, block_end_margin) {
- (MaybeAuto::Auto, MaybeAuto::Auto) => {
- let total_margin_val = available_block_size - block_start - block_end - block_size;
- (block_start, block_end, block_size,
- total_margin_val.scale_by(0.5),
- total_margin_val.scale_by(0.5))
- }
- (MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => {
- let sum = block_start + block_end + block_size + margin_block_start;
- (block_start, block_end, block_size, margin_block_start, available_block_size - sum)
- }
- (MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => {
- let sum = block_start + block_end + block_size + margin_block_end;
- (block_start, block_end, block_size, available_block_size - sum, margin_block_end)
- }
- (MaybeAuto::Specified(margin_block_start), MaybeAuto::Specified(margin_block_end)) => {
- // Values are over-constrained. Ignore value for 'block-end'.
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start, available_block_size - sum, block_size, margin_block_start, margin_block_end)
+ let (block_start, block_size, margin_block_start, margin_block_end) =
+ match (block_start, block_end) {
+ (MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let margin_block_start = block_start_margin.specified_or_zero();
+ let margin_block_end = block_end_margin.specified_or_zero();
+ // Use a dummy value for `block_start`, since it has the static position.
+ (Au(0), block_size, margin_block_start, margin_block_end)
+ }
+ (MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => {
+ match (block_start_margin, block_end_margin) {
+ (MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let total_margin_val = available_block_size - block_start - block_end -
+ block_size;
+ (block_start,
+ block_size,
+ total_margin_val.scale_by(0.5),
+ total_margin_val.scale_by(0.5))
+ }
+ (MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => {
+ let sum = block_start + block_end + block_size + margin_block_start;
+ (block_start,
+ block_size,
+ margin_block_start,
+ available_block_size - sum)
+ }
+ (MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => {
+ let sum = block_start + block_end + block_size + margin_block_end;
+ (block_start, block_size, available_block_size - sum, margin_block_end)
+ }
+ (MaybeAuto::Specified(margin_block_start),
+ MaybeAuto::Specified(margin_block_end)) => {
+ // Values are over-constrained. Ignore value for 'block-end'.
+ (block_start, block_size, margin_block_start, margin_block_end)
+ }
}
}
- }
- // If only one is Auto, solve for it
- (MaybeAuto::Auto, MaybeAuto::Specified(block_end)) => {
- let margin_block_start = block_start_margin.specified_or_zero();
- let margin_block_end = block_end_margin.specified_or_zero();
- let sum = block_end + block_size + margin_block_start + margin_block_end;
- (available_block_size - sum, block_end, block_size, margin_block_start, margin_block_end)
- }
- (MaybeAuto::Specified(block_start), MaybeAuto::Auto) => {
- let margin_block_start = block_start_margin.specified_or_zero();
- let margin_block_end = block_end_margin.specified_or_zero();
- let sum = block_start + block_size + margin_block_start + margin_block_end;
- (block_start, available_block_size - sum, block_size, margin_block_start, margin_block_end)
- }
- };
- BSizeConstraintSolution::new(block_start, block_end, block_size, margin_block_start, margin_block_end)
+ // If only one is Auto, solve for it
+ (MaybeAuto::Auto, MaybeAuto::Specified(block_end)) => {
+ let margin_block_start = block_start_margin.specified_or_zero();
+ let margin_block_end = block_end_margin.specified_or_zero();
+ let sum = block_end + block_size + margin_block_start + margin_block_end;
+ (available_block_size - sum, block_size, margin_block_start, margin_block_end)
+ }
+ (MaybeAuto::Specified(block_start), MaybeAuto::Auto) => {
+ let margin_block_start = block_start_margin.specified_or_zero();
+ let margin_block_end = block_end_margin.specified_or_zero();
+ (block_start, block_size, margin_block_start, margin_block_end)
+ }
+ };
+ BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end)
}
}
@@ -590,9 +532,6 @@ pub struct BlockFlow {
/// The associated fragment.
pub fragment: Fragment,
- /// Static y offset of an absolute flow from its CB.
- pub static_b_offset: Au,
-
/// The sum of the inline-sizes of all logically left floats that precede this block. This is
/// used to speculatively lay out block formatting contexts.
inline_size_of_preceding_left_floats: Au,
@@ -601,9 +540,6 @@ pub struct BlockFlow {
/// used to speculatively lay out block formatting contexts.
inline_size_of_preceding_right_floats: Au,
- /// The hypothetical position, used for absolutely-positioned flows.
- hypothetical_position: LogicalPoint<Au>,
-
/// Additional floating flow members.
pub float: Option<Box<FloatedBlockInfo>>,
@@ -628,12 +564,12 @@ impl BlockFlow {
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloatedFlag::ForceNonfloated),
+ base: BaseFlow::new(Some((*node).clone()),
+ writing_mode,
+ ForceNonfloatedFlag::ForceNonfloated),
fragment: fragment,
- static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
- hypothetical_position: LogicalPoint::new(writing_mode, Au(0), Au(0)),
float: None,
flags: BlockFlowFlags::empty(),
}
@@ -645,12 +581,12 @@ impl BlockFlow {
-> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
- base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloatedFlag::FloatIfNecessary),
+ base: BaseFlow::new(Some((*node).clone()),
+ writing_mode,
+ ForceNonfloatedFlag::FloatIfNecessary),
fragment: fragment,
- static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
- hypothetical_position: LogicalPoint::new(writing_mode, Au(0), Au(0)),
float: Some(box FloatedBlockInfo::new(float_kind)),
flags: BlockFlowFlags::empty(),
}
@@ -684,33 +620,45 @@ impl BlockFlow {
/// Compute the actual inline size and position for this block.
pub fn compute_used_inline_size(&mut self,
- ctx: &LayoutContext,
+ layout_context: &LayoutContext,
containing_block_inline_size: Au) {
let block_type = self.block_type();
match block_type {
BlockType::AbsoluteReplaced => {
let inline_size_computer = AbsoluteReplaced;
- inline_size_computer.compute_used_inline_size(self, ctx, containing_block_inline_size);
+ inline_size_computer.compute_used_inline_size(self,
+ layout_context,
+ containing_block_inline_size);
}
BlockType::AbsoluteNonReplaced => {
let inline_size_computer = AbsoluteNonReplaced;
- inline_size_computer.compute_used_inline_size(self, ctx, containing_block_inline_size);
+ inline_size_computer.compute_used_inline_size(self,
+ layout_context,
+ containing_block_inline_size);
}
BlockType::FloatReplaced => {
let inline_size_computer = FloatReplaced;
- inline_size_computer.compute_used_inline_size(self, ctx, containing_block_inline_size);
+ inline_size_computer.compute_used_inline_size(self,
+ layout_context,
+ containing_block_inline_size);
}
BlockType::FloatNonReplaced => {
let inline_size_computer = FloatNonReplaced;
- inline_size_computer.compute_used_inline_size(self, ctx, containing_block_inline_size);
+ inline_size_computer.compute_used_inline_size(self,
+ layout_context,
+ containing_block_inline_size);
}
BlockType::Replaced => {
let inline_size_computer = BlockReplaced;
- inline_size_computer.compute_used_inline_size(self, ctx, containing_block_inline_size);
+ inline_size_computer.compute_used_inline_size(self,
+ layout_context,
+ containing_block_inline_size);
}
BlockType::NonReplaced => {
let inline_size_computer = BlockNonReplaced;
- inline_size_computer.compute_used_inline_size(self, ctx, containing_block_inline_size);
+ inline_size_computer.compute_used_inline_size(self,
+ layout_context,
+ containing_block_inline_size);
}
}
}
@@ -720,15 +668,6 @@ impl BlockFlow {
&mut self.fragment
}
- /// Return the static x offset from the appropriate Containing Block for this flow.
- pub fn static_i_offset(&self) -> Au {
- if self.is_fixed() {
- self.base.fixed_static_i_offset
- } else {
- self.base.absolute_static_i_offset
- }
- }
-
/// Return the size of the Containing Block for this flow.
///
/// Right now, this only gets the Containing Block size for absolutely
@@ -750,33 +689,25 @@ impl BlockFlow {
///
/// Traverse all your direct absolute descendants, who will then traverse
/// their direct absolute descendants.
- /// Also, set the static y offsets for each descendant (using the value
- /// which was bubbled up during normal assign-block-size).
///
/// Return true if the traversal is to continue or false to stop.
- fn traverse_preorder_absolute_flows<T:PreorderFlowTraversal>(&mut self,
- traversal: &mut T) {
+ fn traverse_preorder_absolute_flows<T>(&mut self, traversal: &mut T)
+ where T: PreorderFlowTraversal {
let flow = self as &mut Flow;
traversal.process(flow);
- let cb_block_start_edge_offset = flow.generated_containing_block_rect().start.b;
- let descendant_offset_iter = mut_base(flow).abs_descendants.iter_with_offset();
- // Pass in the respective static y offset for each descendant.
- for (ref mut descendant_link, ref y_offset) in descendant_offset_iter {
- let block = descendant_link.as_block();
- // The stored y_offset is wrt to the flow box.
- // Translate it to the CB (which is the padding box).
- block.static_b_offset = **y_offset - cb_block_start_edge_offset;
- block.traverse_preorder_absolute_flows(traversal);
+ let descendant_offset_iter = mut_base(flow).abs_descendants.iter();
+ for ref mut descendant_link in descendant_offset_iter {
+ descendant_link.as_block().traverse_preorder_absolute_flows(traversal)
}
}
/// Traverse the Absolute flow tree in postorder.
///
/// Return true if the traversal is to continue or false to stop.
- fn traverse_postorder_absolute_flows<T:PostorderFlowTraversal>(&mut self,
- traversal: &mut T) {
+ fn traverse_postorder_absolute_flows<T>(&mut self, traversal: &mut T)
+ where T: PostorderFlowTraversal {
let flow = self as &mut Flow;
for descendant_link in mut_base(flow).abs_descendants.iter() {
@@ -898,7 +829,11 @@ impl BlockFlow {
if flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
// Assume that the *hypothetical box* for an absolute flow starts immediately
// after the block-end border edge of the previous flow.
- kid.as_block().hypothetical_position.b = cur_b;
+ if flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) {
+ flow::mut_base(kid).position.start.b = cur_b +
+ flow::base(kid).collapsible_margins
+ .block_start_margin_for_noncollapsible_context()
+ }
kid.place_float_if_applicable(layout_context);
if !flow::base(kid).flags.is_float() {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
@@ -989,9 +924,6 @@ impl BlockFlow {
// order (CSS 2.1, Appendix E).
self.base.flags.set(LAYERS_NEEDED_FOR_DESCENDANTS, layers_needed_for_descendants);
- // Collect various offsets needed by absolutely positioned descendants.
- (&mut *self as &mut Flow).collect_static_block_offsets_from_children();
-
// Add in our block-end margin and compute our collapsible margins.
let can_collapse_block_end_margin_with_kids =
margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse &&
@@ -1149,15 +1081,13 @@ impl BlockFlow {
Au(0),
self.fragment.margin.block_start);
- if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
- let mut origin = LogicalPoint::new(self.base.writing_mode,
- self.hypothetical_position.i,
- self.base.position.start.b);
- origin = origin.add_point(&float_offset).add_point(&margin_offset);
- self.base.position = LogicalRect::from_point_size(self.base.writing_mode,
- origin,
- self.base.position.size);
- }
+ let mut origin = LogicalPoint::new(self.base.writing_mode,
+ self.base.position.start.i,
+ self.base.position.start.b);
+ origin = origin.add_point(&float_offset).add_point(&margin_offset);
+ self.base.position = LogicalRect::from_point_size(self.base.writing_mode,
+ origin,
+ self.base.position.size);
}
@@ -1170,7 +1100,6 @@ impl BlockFlow {
/// + block-size, vertical margins, and y-coordinate for the flow's box.
fn calculate_absolute_block_size_and_margins(&mut self, ctx: &LayoutContext) {
let containing_block_block_size = self.containing_block_size(ctx.shared.screen_size).block;
- let static_b_offset = self.static_b_offset;
// This is the stored content block-size value from assign-block-size
let content_block_size = self.fragment.border_box.size.block;
@@ -1216,8 +1145,7 @@ impl BlockFlow {
block_start,
block_end,
content_block_size,
- available_block_size,
- static_b_offset));
+ available_block_size))
} else {
let mut candidate_block_size_iterator =
CandidateBSizeIterator::new(&self.fragment, Some(containing_block_block_size));
@@ -1235,8 +1163,7 @@ impl BlockFlow {
block_start,
block_end,
content_block_size,
- available_block_size,
- static_b_offset));
+ available_block_size));
candidate_block_size_iterator.candidate_value
= solution.unwrap().block_size;
@@ -1252,7 +1179,9 @@ impl BlockFlow {
self.fragment.margin.block_end = solution.margin_block_end;
self.fragment.border_box.start.b = Au(0);
- self.base.position.start.b = solution.block_start + self.fragment.margin.block_start;
+ if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
+ self.base.position.start.b = solution.block_start + self.fragment.margin.block_start
+ }
let block_size = solution.block_size + self.fragment.border_padding.block_start_end();
self.fragment.border_box.size.block = block_size;
@@ -1272,17 +1201,6 @@ impl BlockFlow {
}
}
- /// Return the block-start outer edge of the hypothetical box for an absolute flow.
- ///
- /// This is wrt its parent flow box.
- ///
- /// During normal layout assign-block-size, the absolute flow's position is
- /// roughly set to its static position (the position it would have had in
- /// the normal flow).
- pub fn get_hypothetical_block_start_edge(&self) -> Au {
- self.hypothetical_position.b
- }
-
/// Assigns the computed inline-start content edge and inline-size to all the children of this
/// block flow. Also computes whether each child will be impacted by floats.
///
@@ -1401,8 +1319,7 @@ impl BlockFlow {
let kid_mode = flow::base(kid).writing_mode;
{
let kid_base = flow::mut_base(kid);
- if !kid_base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
- !kid_base.flags.is_float() {
+ if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
kid_base.position.start.i =
if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() {
inline_start_content_edge
@@ -1414,15 +1331,6 @@ impl BlockFlow {
kid_base.block_container_inline_size = content_inline_size;
kid_base.block_container_writing_mode = containing_block_mode;
}
- if kid.is_block_like() {
- kid.as_block().hypothetical_position.i =
- if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() {
- inline_start_content_edge
- } else {
- // The kid's inline 'start' is at the parent's 'end'
- inline_end_content_edge
- }
- }
{
let kid_base = flow::mut_base(kid);
@@ -1521,7 +1429,7 @@ impl BlockFlow {
// Offset our position by whatever displacement is needed to not impact the floats.
let rect = self.base.floats.place_between_floats(&info);
- self.base.position.start.i = self.hypothetical_position.i + rect.start.i;
+ self.base.position.start.i = self.base.position.start.i + rect.start.i;
// TODO(pcwalton): If the inline-size of this flow is different from the size we estimated
// earlier, lay it out again.
@@ -1586,7 +1494,8 @@ impl Flow for BlockFlow {
let mut left_float_width = Au(0);
let mut right_float_width = Au(0);
for kid in self.base.child_iter() {
- let is_absolutely_positioned = flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED);
+ let is_absolutely_positioned =
+ flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED);
let child_base = flow::mut_base(kid);
let float_kind = child_base.flags.float_kind();
if !is_absolutely_positioned && !fixed_width {
@@ -1791,7 +1700,7 @@ impl Flow for BlockFlow {
// Compute our position relative to the nearest ancestor stacking context. This will be
// passed down later as part of containing block details for absolute descendants.
- self.base.stacking_relative_position = if self.is_fixed() {
+ let absolute_stacking_relative_position = if self.is_fixed() {
// The viewport is initially at (0, 0).
position_start
} else {
@@ -1800,6 +1709,22 @@ impl Flow for BlockFlow {
self.base
.absolute_position_info
.stacking_relative_position_of_absolute_containing_block + position_start
+ };
+
+ if !self.base.writing_mode.is_vertical() {
+ if !self.base.flags.contains(INLINE_POSITION_IS_STATIC) {
+ self.base.stacking_relative_position.x = absolute_stacking_relative_position.x
+ }
+ if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
+ self.base.stacking_relative_position.y = absolute_stacking_relative_position.y
+ }
+ } else {
+ if !self.base.flags.contains(INLINE_POSITION_IS_STATIC) {
+ self.base.stacking_relative_position.y = absolute_stacking_relative_position.y
+ }
+ if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
+ self.base.stacking_relative_position.x = absolute_stacking_relative_position.x
+ }
}
}
@@ -1888,13 +1813,34 @@ impl Flow for BlockFlow {
// Process children.
for kid in self.base.child_iter() {
- if !flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
+ if flow::base(kid).flags.contains(INLINE_POSITION_IS_STATIC) ||
+ flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) {
let kid_base = flow::mut_base(kid);
// FIXME (mbrubeck): `position.size` is inflated by the inline margin size, making
// this incorrect for RTL blocks (see `set_inline_size_constraint_solutions`).
let physical_position = kid_base.position.to_physical(kid_base.writing_mode,
container_size_for_children);
- kid_base.stacking_relative_position = origin_for_children + physical_position.origin;
+
+ // Set the inline and block positions as necessary.
+ if !kid_base.writing_mode.is_vertical() {
+ if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
+ kid_base.stacking_relative_position.x = origin_for_children.x +
+ physical_position.origin.x
+ }
+ if kid_base.flags.contains(BLOCK_POSITION_IS_STATIC) {
+ kid_base.stacking_relative_position.y = origin_for_children.y +
+ physical_position.origin.y
+ }
+ } else {
+ if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
+ kid_base.stacking_relative_position.y = origin_for_children.y +
+ physical_position.origin.y
+ }
+ if kid_base.flags.contains(BLOCK_POSITION_IS_STATIC) {
+ kid_base.stacking_relative_position.x = origin_for_children.x +
+ physical_position.origin.x
+ }
+ }
}
flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
@@ -2019,7 +1965,6 @@ pub struct ISizeConstraintInput {
pub inline_start: MaybeAuto,
pub inline_end: MaybeAuto,
pub available_inline_size: Au,
- pub static_i_offset: Au,
}
impl ISizeConstraintInput {
@@ -2028,8 +1973,7 @@ impl ISizeConstraintInput {
inline_end_margin: MaybeAuto,
inline_start: MaybeAuto,
inline_end: MaybeAuto,
- available_inline_size: Au,
- static_i_offset: Au)
+ available_inline_size: Au)
-> ISizeConstraintInput {
ISizeConstraintInput {
computed_inline_size: computed_inline_size,
@@ -2038,7 +1982,6 @@ impl ISizeConstraintInput {
inline_start: inline_start,
inline_end: inline_end,
available_inline_size: available_inline_size,
- static_i_offset: static_i_offset,
}
}
}
@@ -2047,7 +1990,6 @@ impl ISizeConstraintInput {
#[derive(Copy, Debug)]
pub struct ISizeConstraintSolution {
pub inline_start: Au,
- pub inline_end: Au,
pub inline_size: Au,
pub margin_inline_start: Au,
pub margin_inline_end: Au
@@ -2058,7 +2000,6 @@ impl ISizeConstraintSolution {
-> ISizeConstraintSolution {
ISizeConstraintSolution {
inline_start: Au(0),
- inline_end: Au(0),
inline_size: inline_size,
margin_inline_start: margin_inline_start,
margin_inline_end: margin_inline_end,
@@ -2066,14 +2007,12 @@ impl ISizeConstraintSolution {
}
fn for_absolute_flow(inline_start: Au,
- inline_end: Au,
inline_size: Au,
margin_inline_start: Au,
margin_inline_end: Au)
-> ISizeConstraintSolution {
ISizeConstraintSolution {
inline_start: inline_start,
- inline_end: inline_end,
inline_size: inline_size,
margin_inline_start: margin_inline_start,
margin_inline_end: margin_inline_end,
@@ -2123,14 +2062,16 @@ pub trait ISizeAndMarginsComputer {
let available_inline_size = containing_block_inline_size -
block.fragment.border_padding.inline_start_end();
- return ISizeConstraintInput::new(
- computed_inline_size,
- MaybeAuto::from_style(margin.inline_start, containing_block_inline_size),
- MaybeAuto::from_style(margin.inline_end, containing_block_inline_size),
- MaybeAuto::from_style(position.inline_start, containing_block_inline_size),
- MaybeAuto::from_style(position.inline_end, containing_block_inline_size),
- available_inline_size,
- block.static_i_offset());
+ ISizeConstraintInput::new(computed_inline_size,
+ MaybeAuto::from_style(margin.inline_start,
+ containing_block_inline_size),
+ MaybeAuto::from_style(margin.inline_end,
+ containing_block_inline_size),
+ MaybeAuto::from_style(position.inline_start,
+ containing_block_inline_size),
+ MaybeAuto::from_style(position.inline_end,
+ containing_block_inline_size),
+ available_inline_size)
}
/// Set the used values for inline-size and margins from the relevant constraint equation.
@@ -2188,8 +2129,10 @@ pub trait ISizeAndMarginsComputer {
flow::mut_base(block).position.size.inline = inline_size + extra_inline_size_from_margin;
}
- /// Set the x coordinate of the given flow if it is absolutely positioned.
- fn set_flow_x_coord_if_necessary(&self, _: &mut BlockFlow, _: ISizeConstraintSolution) {}
+ /// Set the inline coordinate of the given flow if it is absolutely positioned.
+ fn set_inline_position_of_flow_if_necessary(&self,
+ _: &mut BlockFlow,
+ _: ISizeConstraintSolution) {}
/// Solve the inline-size and margins constraints for this block flow.
fn solve_inline_size_constraints(&self,
@@ -2255,7 +2198,7 @@ pub trait ISizeAndMarginsComputer {
}
self.set_inline_size_constraint_solutions(block, solution);
- self.set_flow_x_coord_if_necessary(block, solution);
+ self.set_inline_position_of_flow_if_necessary(block, solution);
}
/// Computes inline-start and inline-end margins and inline-size.
@@ -2367,13 +2310,13 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
/// Constraint equation:
/// inline-start + inline-end + inline-size + margin-inline-start + margin-inline-end
/// = absolute containing block inline-size - (horizontal padding and border)
- /// [aka available_inline-size]
+ /// [aka available inline-size]
///
/// Return the solution for the equation.
fn solve_inline_size_constraints(&self,
- block: &mut BlockFlow,
- input: &ISizeConstraintInput)
- -> ISizeConstraintSolution {
+ block: &mut BlockFlow,
+ input: &ISizeConstraintInput)
+ -> ISizeConstraintSolution {
let &ISizeConstraintInput {
computed_inline_size,
inline_start_margin,
@@ -2381,7 +2324,6 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
inline_start,
inline_end,
available_inline_size,
- static_i_offset,
..
} = input;
@@ -2392,140 +2334,152 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
// FIXME (mbrubeck): Handle vertical writing modes.
let parent_has_same_direction = container_mode.is_bidi_ltr() == block_mode.is_bidi_ltr();
- // Distance from the inline-start edge of the Absolute Containing Block to the
- // inline-start margin edge of a hypothetical box that would have been the
- // first box of the element.
- let static_position_inline_start = static_i_offset;
-
- let (inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end) = match (inline_start, inline_end, computed_inline_size) {
- (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let inline_start = static_position_inline_start;
- // Now it is the same situation as inline-start Specified and inline-end
- // and inline-size Auto.
-
- // Set inline-end to zero to calculate inline-size
- let inline_size = block.get_shrink_to_fit_inline_size(
- available_inline_size - (inline_start + margin_start + margin_end));
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- }
- (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end), MaybeAuto::Specified(inline_size)) => {
- match (inline_start_margin, inline_end_margin) {
- (MaybeAuto::Auto, MaybeAuto::Auto) => {
- let total_margin_val = available_inline_size - inline_start - inline_end - inline_size;
- if total_margin_val < Au(0) {
- if parent_has_same_direction {
- // margin-inline-start becomes 0
- (inline_start, inline_end, inline_size, Au(0), total_margin_val)
+ let (inline_start, inline_size, margin_inline_start, margin_inline_end) =
+ match (inline_start, inline_end, computed_inline_size) {
+ (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ // Now it is the same situation as inline-start Specified and inline-end
+ // and inline-size Auto.
+
+ // Set inline-end to zero to calculate inline-size.
+ let inline_size =
+ block.get_shrink_to_fit_inline_size(available_inline_size -
+ (margin_start + margin_end));
+ (Au(0), inline_size, margin_start, margin_end)
+ }
+ (MaybeAuto::Specified(inline_start),
+ MaybeAuto::Specified(inline_end),
+ MaybeAuto::Specified(inline_size)) => {
+ match (inline_start_margin, inline_end_margin) {
+ (MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let total_margin_val =
+ available_inline_size - inline_start - inline_end - inline_size;
+ if total_margin_val < Au(0) {
+ if parent_has_same_direction {
+ // margin-inline-start becomes 0
+ (inline_start, inline_size, Au(0), total_margin_val)
+ } else {
+ // margin-inline-end becomes 0, because it's toward the parent's
+ // inline-start edge.
+ (inline_start, inline_size, total_margin_val, Au(0))
+ }
} else {
- // margin-inline-end becomes 0, because it's toward the parent's
- // inline-start edge.
- (inline_start, inline_end, inline_size, total_margin_val, Au(0))
+ // Equal margins
+ (inline_start,
+ inline_size,
+ total_margin_val.scale_by(0.5),
+ total_margin_val.scale_by(0.5))
}
- } else {
- // Equal margins
- (inline_start, inline_end, inline_size,
- total_margin_val.scale_by(0.5),
- total_margin_val.scale_by(0.5))
}
- }
- (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => {
- let sum = inline_start + inline_end + inline_size + margin_start;
- (inline_start, inline_end, inline_size, margin_start, available_inline_size - sum)
- }
- (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
- let sum = inline_start + inline_end + inline_size + margin_end;
- (inline_start, inline_end, inline_size, available_inline_size - sum, margin_end)
- }
- (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => {
- // Values are over-constrained.
- let sum = inline_start + inline_size + margin_start + margin_end;
- if parent_has_same_direction {
- // Ignore value for 'inline-end'
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- } else {
- // Ignore value for 'inline-start'
- (available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
+ (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => {
+ let sum = inline_start + inline_end + inline_size + margin_start;
+ (inline_start, inline_size, margin_start, available_inline_size - sum)
+ }
+ (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
+ let sum = inline_start + inline_end + inline_size + margin_end;
+ (inline_start, inline_size, available_inline_size - sum, margin_end)
+ }
+ (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => {
+ // Values are over-constrained.
+ let sum = inline_start + inline_size + margin_start + margin_end;
+ if parent_has_same_direction {
+ // Ignore value for 'inline-end'
+ (inline_start, inline_size, margin_start, margin_end)
+ } else {
+ // Ignore value for 'inline-start'
+ (available_inline_size - sum,
+ inline_size,
+ margin_start,
+ margin_end)
+ }
}
}
}
- }
- // For the rest of the cases, auto values for margin are set to 0
-
- // If only one is Auto, solve for it
- (MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Specified(inline_size)) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let sum = inline_end + inline_size + margin_start + margin_end;
- (available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
- }
- (MaybeAuto::Specified(inline_start), MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- }
- (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let sum = inline_start + inline_end + margin_start + margin_end;
- (inline_start, inline_end, available_inline_size - sum, margin_start, margin_end)
- }
+ // For the rest of the cases, auto values for margin are set to 0
- // If inline-size is auto, then inline-size is shrink-to-fit. Solve for the
- // non-auto value.
- (MaybeAuto::Specified(inline_start), MaybeAuto::Auto, MaybeAuto::Auto) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- // Set inline-end to zero to calculate inline-size
- let inline_size = block.get_shrink_to_fit_inline_size(
- available_inline_size - (inline_start + margin_start + margin_end));
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- }
- (MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- // Set inline-start to zero to calculate inline-size
- let inline_size = block.get_shrink_to_fit_inline_size(
- available_inline_size - (inline_end + margin_start + margin_end));
- let sum = inline_end + inline_size + margin_start + margin_end;
- (available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
- }
+ // If only one is Auto, solve for it
+ (MaybeAuto::Auto,
+ MaybeAuto::Specified(inline_end),
+ MaybeAuto::Specified(inline_size)) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ let sum = inline_end + inline_size + margin_start + margin_end;
+ (available_inline_size - sum, inline_size, margin_start, margin_end)
+ }
+ (MaybeAuto::Specified(inline_start),
+ MaybeAuto::Auto,
+ MaybeAuto::Specified(inline_size)) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ (inline_start, inline_size, margin_start, margin_end)
+ }
+ (MaybeAuto::Specified(inline_start),
+ MaybeAuto::Specified(inline_end),
+ MaybeAuto::Auto) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ let sum = inline_start + inline_end + margin_start + margin_end;
+ (inline_start, available_inline_size - sum, margin_start, margin_end)
+ }
- (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- // Setting 'inline-start' to static position because direction is 'ltr'.
- // TODO: Handle 'rtl' when it is implemented.
- let inline_start = static_position_inline_start;
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- }
- };
- ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end)
+ // If inline-size is auto, then inline-size is shrink-to-fit. Solve for the
+ // non-auto value.
+ (MaybeAuto::Specified(inline_start), MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ // Set inline-end to zero to calculate inline-size
+ let inline_size =
+ block.get_shrink_to_fit_inline_size(available_inline_size -
+ (margin_start + margin_end));
+ (inline_start, inline_size, margin_start, margin_end)
+ }
+ (MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ // Set inline-start to zero to calculate inline-size
+ let inline_size =
+ block.get_shrink_to_fit_inline_size(available_inline_size -
+ (margin_start + margin_end));
+ let sum = inline_end + inline_size + margin_start + margin_end;
+ (available_inline_size - sum, inline_size, margin_start, margin_end)
+ }
+
+ (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ // Setting 'inline-start' to static position because direction is 'ltr'.
+ // TODO: Handle 'rtl' when it is implemented.
+ (Au(0), inline_size, margin_start, margin_end)
+ }
+ };
+ ISizeConstraintSolution::for_absolute_flow(inline_start,
+ inline_size,
+ margin_inline_start,
+ margin_inline_end)
}
- fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
- block.containing_block_size(ctx.shared.screen_size).inline
+ fn containing_block_inline_size(&self,
+ block: &mut BlockFlow,
+ _: Au,
+ layout_context: &LayoutContext)
+ -> Au {
+ block.containing_block_size(layout_context.shared.screen_size).inline
}
- fn set_flow_x_coord_if_necessary(&self,
- block: &mut BlockFlow,
- solution: ISizeConstraintSolution) {
- // Set the x-coordinate of the absolute flow wrt to its containing block.
- block.base.position.start.i = solution.inline_start;
+ fn set_inline_position_of_flow_if_necessary(&self,
+ block: &mut BlockFlow,
+ solution: ISizeConstraintSolution) {
+ // Set the inline position of the absolute flow wrt to its containing block.
+ if !block.base.flags.contains(INLINE_POSITION_IS_STATIC) {
+ block.base.position.start.i = solution.inline_start;
+ }
}
}
impl ISizeAndMarginsComputer for AbsoluteReplaced {
/// Solve the horizontal constraint equation for absolute replaced elements.
///
- /// `static_i_offset`: total offset of current flow's hypothetical
- /// position (static position) from its actual Containing Block.
- ///
/// CSS Section 10.3.8
/// Constraint equation:
/// inline-start + inline-end + inline-size + margin-inline-start + margin-inline-end
@@ -2534,7 +2488,7 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
///
/// Return the solution for the equation.
fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput)
- -> ISizeConstraintSolution {
+ -> ISizeConstraintSolution {
let &ISizeConstraintInput {
computed_inline_size,
inline_start_margin,
@@ -2542,7 +2496,6 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
inline_start,
inline_end,
available_inline_size,
- static_i_offset,
..
} = input;
// TODO: Check for direction of static-position Containing Block (aka
@@ -2558,64 +2511,61 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
"should have already been calculated by now.")
};
- // Distance from the inline-start edge of the Absolute Containing Block to the
- // inline-start margin edge of a hypothetical box that would have been the
- // first box of the element.
- let static_position_inline_start = static_i_offset;
-
- let (inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end) = match (inline_start, inline_end) {
- (MaybeAuto::Auto, MaybeAuto::Auto) => {
- let inline_start = static_position_inline_start;
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- }
- // If only one is Auto, solve for it
- (MaybeAuto::Auto, MaybeAuto::Specified(inline_end)) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let sum = inline_end + inline_size + margin_start + margin_end;
- (available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
- }
- (MaybeAuto::Specified(inline_start), MaybeAuto::Auto) => {
- let margin_start = inline_start_margin.specified_or_zero();
- let margin_end = inline_end_margin.specified_or_zero();
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
- }
- (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) => {
- match (inline_start_margin, inline_end_margin) {
- (MaybeAuto::Auto, MaybeAuto::Auto) => {
- let total_margin_val = available_inline_size - inline_start - inline_end - inline_size;
- if total_margin_val < Au(0) {
- // margin-inline-start becomes 0 because direction is 'ltr'.
- (inline_start, inline_end, inline_size, Au(0), total_margin_val)
- } else {
- // Equal margins
- (inline_start, inline_end, inline_size,
- total_margin_val.scale_by(0.5),
- total_margin_val.scale_by(0.5))
+ let (inline_start, inline_size, margin_inline_start, margin_inline_end) =
+ match (inline_start, inline_end) {
+ (MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ (Au(0), inline_size, margin_start, margin_end)
+ }
+ // If only one is Auto, solve for it
+ (MaybeAuto::Auto, MaybeAuto::Specified(inline_end)) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ let sum = inline_end + inline_size + margin_start + margin_end;
+ (available_inline_size - sum, inline_size, margin_start, margin_end)
+ }
+ (MaybeAuto::Specified(inline_start), MaybeAuto::Auto) => {
+ let margin_start = inline_start_margin.specified_or_zero();
+ let margin_end = inline_end_margin.specified_or_zero();
+ (inline_start, inline_size, margin_start, margin_end)
+ }
+ (MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) => {
+ match (inline_start_margin, inline_end_margin) {
+ (MaybeAuto::Auto, MaybeAuto::Auto) => {
+ let total_margin_val = available_inline_size - inline_start -
+ inline_end - inline_size;
+ if total_margin_val < Au(0) {
+ // margin-inline-start becomes 0 because direction is 'ltr'.
+ (inline_start, inline_size, Au(0), total_margin_val)
+ } else {
+ // Equal margins
+ (inline_start,
+ inline_size,
+ total_margin_val.scale_by(0.5),
+ total_margin_val.scale_by(0.5))
+ }
+ }
+ (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => {
+ let sum = inline_start + inline_end + inline_size + margin_start;
+ (inline_start, inline_size, margin_start, available_inline_size - sum)
+ }
+ (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
+ let sum = inline_start + inline_end + inline_size + margin_end;
+ (inline_start, inline_size, available_inline_size - sum, margin_end)
+ }
+ (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => {
+ // Values are over-constrained.
+ // Ignore value for 'inline-end' cos direction is 'ltr'.
+ (inline_start, inline_size, margin_start, margin_end)
}
- }
- (MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => {
- let sum = inline_start + inline_end + inline_size + margin_start;
- (inline_start, inline_end, inline_size, margin_start, available_inline_size - sum)
- }
- (MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
- let sum = inline_start + inline_end + inline_size + margin_end;
- (inline_start, inline_end, inline_size, available_inline_size - sum, margin_end)
- }
- (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => {
- // Values are over-constrained.
- // Ignore value for 'inline-end' cos direction is 'ltr'.
- let sum = inline_start + inline_size + margin_start + margin_end;
- (inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
}
}
- }
- };
- ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end)
+ };
+ ISizeConstraintSolution::for_absolute_flow(inline_start,
+ inline_size,
+ margin_inline_start,
+ margin_inline_end)
}
/// Calculate used value of inline-size just like we do for inline replaced elements.
@@ -2638,9 +2588,9 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
block.containing_block_size(ctx.shared.screen_size).inline
}
- fn set_flow_x_coord_if_necessary(&self,
- block: &mut BlockFlow,
- solution: ISizeConstraintSolution) {
+ fn set_inline_position_of_flow_if_necessary(&self,
+ block: &mut BlockFlow,
+ solution: ISizeConstraintSolution) {
// Set the x-coordinate of the absolute flow wrt to its containing block.
block.base.position.start.i = solution.inline_start;
}
@@ -2695,13 +2645,15 @@ impl ISizeAndMarginsComputer for FloatNonReplaced {
block: &mut BlockFlow,
input: &ISizeConstraintInput)
-> ISizeConstraintSolution {
- let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) = (input.computed_inline_size,
- input.inline_start_margin,
- input.inline_end_margin,
- input.available_inline_size);
+ let (computed_inline_size, inline_start_margin, inline_end_margin, available_inline_size) =
+ (input.computed_inline_size,
+ input.inline_start_margin,
+ input.inline_end_margin,
+ input.available_inline_size);
let margin_inline_start = inline_start_margin.specified_or_zero();
let margin_inline_end = inline_end_margin.specified_or_zero();
- let available_inline_size_float = available_inline_size - margin_inline_start - margin_inline_end;
+ let available_inline_size_float = available_inline_size - margin_inline_start -
+ margin_inline_end;
let shrink_to_fit = block.get_shrink_to_fit_inline_size(available_inline_size_float);
let inline_size = computed_inline_size.specified_or_default(shrink_to_fit);
debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size);
@@ -2715,9 +2667,8 @@ impl ISizeAndMarginsComputer for FloatReplaced {
/// If inline-size is computed as 'auto', the used value is the 'shrink-to-fit' inline-size.
fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput)
-> ISizeConstraintSolution {
- let (computed_inline_size, inline_start_margin, inline_end_margin) = (input.computed_inline_size,
- input.inline_start_margin,
- input.inline_end_margin);
+ let (computed_inline_size, inline_start_margin, inline_end_margin) =
+ (input.computed_inline_size, input.inline_start_margin, input.inline_end_margin);
let margin_inline_start = inline_start_margin.specified_or_zero();
let margin_inline_end = inline_end_margin.specified_or_zero();
let inline_size = match computed_inline_size {
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index ce495865c30..0d31b839d7e 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -58,11 +58,12 @@ use std::fmt;
use std::iter::Zip;
use std::num::FromPrimitive;
use std::raw;
-use std::sync::atomic::{AtomicUsize, Ordering};
use std::slice::IterMut;
+use std::sync::Arc;
+use std::sync::atomic::{AtomicUsize, Ordering};
use style::computed_values::{clear, empty_cells, float, position, text_align};
use style::properties::ComputedValues;
-use std::sync::Arc;
+use style::values::computed::LengthOrPercentageOrAuto;
/// Virtual methods that make up a float context.
///
@@ -426,16 +427,6 @@ pub trait MutableFlowUtils {
/// Computes the overflow region for this flow.
fn store_overflow(self, _: &LayoutContext);
- /// Gathers static block-offsets bubbled up by kids.
- ///
- /// This essentially gives us offsets of all absolutely positioned direct descendants and all
- /// fixed descendants, in tree order.
- ///
- /// This is called in a bottom-up traversal (specifically, the assign-block-size traversal).
- /// So, kids have their flow origin already set. In the case of absolute flow kids, they have
- /// their hypothetical box position already set.
- fn collect_static_block_offsets_from_children(self);
-
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
/// calling them individually, since there is no reason not to perform both operations.
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
@@ -548,7 +539,17 @@ bitflags! {
const AFFECTS_COUNTERS = 0b0000_1000_0000_0000_0000,
#[doc = "Whether this flow's descendants have fragments that affect `counter-reset` or \
`counter-increment` styles."]
- const HAS_COUNTER_AFFECTING_CHILDREN = 0b0001_0000_0000_0000_0000
+ const HAS_COUNTER_AFFECTING_CHILDREN = 0b0001_0000_0000_0000_0000,
+ #[doc = "Whether this flow behaves as though it had `position: static` for the purposes \
+ of positioning in the inline direction. This is set for flows with `position: \
+ static` and `position: relative` as well as absolutely-positioned flows with \
+ unconstrained positions in the inline direction."]
+ const INLINE_POSITION_IS_STATIC = 0b0010_0000_0000_0000_0000,
+ #[doc = "Whether this flow behaves as though it had `position: static` for the purposes \
+ of positioning in the block direction. This is set for flows with `position: \
+ static` and `position: relative` as well as absolutely-positioned flows with \
+ unconstrained positions in the block direction."]
+ const BLOCK_POSITION_IS_STATIC = 0b0100_0000_0000_0000_0000,
}
}
@@ -637,16 +638,12 @@ pub struct Descendants {
/// Links to every descendant. This must be private because it is unsafe to leak `FlowRef`s to
/// layout.
descendant_links: Vec<FlowRef>,
-
- /// Static block-direction offsets of all descendants from the start of this flow box.
- pub static_block_offsets: Vec<Au>,
}
impl Descendants {
pub fn new() -> Descendants {
Descendants {
descendant_links: Vec::new(),
- static_block_offsets: Vec::new(),
}
}
@@ -677,14 +674,6 @@ impl Descendants {
iter: self.descendant_links.iter_mut(),
}
}
-
- /// Return an iterator over (descendant, static y offset).
- pub fn iter_with_offset<'a>(&'a mut self) -> DescendantOffsetIter<'a> {
- let descendant_iter = DescendantIter {
- iter: self.descendant_links.iter_mut(),
- };
- descendant_iter.zip(self.static_block_offsets.iter_mut())
- }
}
pub type AbsDescendants = Descendants;
@@ -916,37 +905,50 @@ impl BaseFlow {
force_nonfloated: ForceNonfloatedFlag)
-> BaseFlow {
let mut flags = FlowFlags::empty();
- if let Some(node) = node {
- let node_style = node.style();
- match node_style.get_box().position {
- position::T::absolute | position::T::fixed => {
- flags.insert(IS_ABSOLUTELY_POSITIONED)
+ match node {
+ Some(node) => {
+ let node_style = node.style();
+ match node_style.get_box().position {
+ position::T::absolute | position::T::fixed => {
+ flags.insert(IS_ABSOLUTELY_POSITIONED);
+
+ let logical_position = node_style.logical_position();
+ if logical_position.inline_start == LengthOrPercentageOrAuto::Auto &&
+ logical_position.inline_end == LengthOrPercentageOrAuto::Auto {
+ flags.insert(INLINE_POSITION_IS_STATIC);
+ }
+ if logical_position.block_start == LengthOrPercentageOrAuto::Auto &&
+ logical_position.block_end == LengthOrPercentageOrAuto::Auto {
+ flags.insert(BLOCK_POSITION_IS_STATIC);
+ }
+ }
+ _ => flags.insert(BLOCK_POSITION_IS_STATIC | INLINE_POSITION_IS_STATIC),
}
- _ => {}
- }
- if force_nonfloated == ForceNonfloatedFlag::FloatIfNecessary {
- match node_style.get_box().float {
- float::T::none => {}
- float::T::left => flags.insert(FLOATS_LEFT),
- float::T::right => flags.insert(FLOATS_RIGHT),
+ if force_nonfloated == ForceNonfloatedFlag::FloatIfNecessary {
+ match node_style.get_box().float {
+ float::T::none => {}
+ float::T::left => flags.insert(FLOATS_LEFT),
+ float::T::right => flags.insert(FLOATS_RIGHT),
+ }
}
- }
- match node_style.get_box().clear {
- clear::T::none => {}
- clear::T::left => flags.insert(CLEARS_LEFT),
- clear::T::right => flags.insert(CLEARS_RIGHT),
- clear::T::both => {
- flags.insert(CLEARS_LEFT);
- flags.insert(CLEARS_RIGHT);
+ match node_style.get_box().clear {
+ clear::T::none => {}
+ clear::T::left => flags.insert(CLEARS_LEFT),
+ clear::T::right => flags.insert(CLEARS_RIGHT),
+ clear::T::both => {
+ flags.insert(CLEARS_LEFT);
+ flags.insert(CLEARS_RIGHT);
+ }
}
- }
- if !node_style.get_counters().counter_reset.0.is_empty() ||
- !node_style.get_counters().counter_increment.0.is_empty() {
- flags.insert(AFFECTS_COUNTERS)
+ if !node_style.get_counters().counter_reset.0.is_empty() ||
+ !node_style.get_counters().counter_increment.0.is_empty() {
+ flags.insert(AFFECTS_COUNTERS)
+ }
}
+ None => flags.insert(BLOCK_POSITION_IS_STATIC | INLINE_POSITION_IS_STATIC),
}
// New flows start out as fully damaged.
@@ -1268,52 +1270,6 @@ impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
mut_base(self).overflow = overflow;
}
- /// Collect and update static y-offsets bubbled up by kids.
- ///
- /// This would essentially give us offsets of all absolutely positioned
- /// direct descendants and all fixed descendants, in tree order.
- ///
- /// Assume that this is called in a bottom-up traversal (specifically, the
- /// assign-block-size traversal). So, kids have their flow origin already set.
- /// In the case of absolute flow kids, they have their hypothetical box
- /// position already set.
- fn collect_static_block_offsets_from_children(self) {
- let mut absolute_descendant_block_offsets = Vec::new();
- for kid in mut_base(self).child_iter() {
- let mut gives_absolute_offsets = true;
- if kid.is_block_like() {
- let kid_block = kid.as_block();
- if kid_block.is_fixed() || kid_block.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
- // It won't contribute any offsets for descendants because it would be the
- // containing block for them.
- gives_absolute_offsets = false;
- // Give the offset for the current absolute flow alone.
- absolute_descendant_block_offsets.push(
- kid_block.get_hypothetical_block_start_edge());
- } else if kid_block.is_positioned() {
- // It won't contribute any offsets because it would be the containing block
- // for the descendants.
- gives_absolute_offsets = false;
- }
- }
-
- if gives_absolute_offsets {
- let kid_base = mut_base(kid);
- // Avoid copying the offset vector.
- let offsets = mem::replace(&mut kid_base.abs_descendants.static_block_offsets,
- Vec::new());
- // Consume all the static block-offsets bubbled up by kids.
- for block_offset in offsets.into_iter() {
- // The offsets are with respect to the kid flow's fragment. Translate them to
- // that of the current flow.
- absolute_descendant_block_offsets.push(
- block_offset + kid_base.position.start.b);
- }
- }
- }
- mut_base(self).abs_descendants.static_block_offsets = absolute_descendant_block_offsets
- }
-
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
/// calling them individually, since there is no reason not to perform both operations.
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>) {
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 64c16d349a9..cfaa8d87bf4 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -1226,7 +1226,8 @@ impl Fragment {
}
- /// TODO: What exactly does this function return? Why is it Au(0) for SpecificFragmentInfo::Generic?
+ /// TODO: What exactly does this function return? Why is it Au(0) for
+ /// SpecificFragmentInfo::Generic?
pub fn content_inline_size(&self) -> Au {
match self.specific {
SpecificFragmentInfo::Generic |
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index c04190a36eb..cf42b29577d 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -8,8 +8,7 @@ use css::node_style::StyledNode;
use context::LayoutContext;
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
use floats::{FloatKind, Floats, PlacementInfo};
-use flow::{self, BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
-use flow::{IS_ABSOLUTELY_POSITIONED};
+use flow::{self, BaseFlow, FlowClass, Flow, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT};
use layout_debug;
@@ -1184,10 +1183,6 @@ impl Flow for InlineFlow {
fn assign_block_size(&mut self, layout_context: &LayoutContext) {
let _scope = layout_debug_scope!("inline::assign_block_size {:x}", self.base.debug_id());
- // Collect various offsets needed by absolutely positioned inline-block or hypothetical
- // absolute descendants.
- (&mut *self as &mut Flow).collect_static_block_offsets_from_children();
-
// Divide the fragments into lines.
//
// TODO(pcwalton, #226): Get the CSS `line-height` property from the style of the
diff --git a/components/layout/model.rs b/components/layout/model.rs
index 2479ab7cb47..670d2210681 100644
--- a/components/layout/model.rs
+++ b/components/layout/model.rs
@@ -80,6 +80,17 @@ impl CollapsibleMargins {
pub fn new() -> CollapsibleMargins {
CollapsibleMargins::None(Au(0), Au(0))
}
+
+ /// Returns the amount of margin that should be applied in a noncollapsible context. This is
+ /// currently used to apply block-start margin for hypothetical boxes, since we do not collapse
+ /// margins of hypothetical boxes.
+ pub fn block_start_margin_for_noncollapsible_context(&self) -> Au {
+ match *self {
+ CollapsibleMargins::None(block_start, _) => block_start,
+ CollapsibleMargins::Collapse(ref block_start, _) |
+ CollapsibleMargins::CollapseThrough(ref block_start) => block_start.collapse(),
+ }
+ }
}
enum FinalMarginState {
diff --git a/components/layout/table.rs b/components/layout/table.rs
index f10e448ffd6..ce337b08a67 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -11,7 +11,7 @@ use block::{ISizeConstraintInput, ISizeConstraintSolution};
use context::LayoutContext;
use floats::FloatKind;
use flow::{self, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
-use flow::{ImmutableFlowUtils, MutableFlowUtils};
+use flow::{ImmutableFlowUtils};
use fragment::{Fragment, FragmentBorderBoxIterator};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
@@ -477,9 +477,6 @@ impl TableLikeFlow for BlockFlow {
current_block_offset = current_block_offset + kid_base.position.size.block;
}
- // Collect various offsets needed by absolutely positioned descendants.
- (&mut *self as &mut Flow).collect_static_block_offsets_from_children();
-
// Compute any explicitly-specified block size.
// Can't use `for` because we assign to `candidate_block_size_iterator.candidate_value`.
let mut block_size = current_block_offset - block_start_border_padding;
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index f96e5efcd3c..290876e05b0 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -211,12 +211,14 @@ impl TableWrapperFlow {
let solution = FloatNonReplaced.solve_inline_size_constraints(&mut self.block_flow,
&input);
FloatNonReplaced.set_inline_size_constraint_solutions(&mut self.block_flow, solution);
- FloatNonReplaced.set_flow_x_coord_if_necessary(&mut self.block_flow, solution);
+ FloatNonReplaced.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
+ solution);
} else {
let solution = BlockNonReplaced.solve_inline_size_constraints(&mut self.block_flow,
&input);
BlockNonReplaced.set_inline_size_constraint_solutions(&mut self.block_flow, solution);
- BlockNonReplaced.set_flow_x_coord_if_necessary(&mut self.block_flow, solution);
+ BlockNonReplaced.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
+ solution);
}
}
}
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs
index 26e0bdb0f44..234fecfc9eb 100644
--- a/components/style/properties.mako.rs
+++ b/components/style/properties.mako.rs
@@ -4704,7 +4704,11 @@ impl ComputedValues {
#[inline]
pub fn content_inline_size(&self) -> computed::LengthOrPercentageOrAuto {
let box_style = self.get_box();
- if self.writing_mode.is_vertical() { box_style.height } else { box_style.width }
+ if self.writing_mode.is_vertical() {
+ box_style.height
+ } else {
+ box_style.width
+ }
}
#[inline]
diff --git a/tests/ref/absolute_hypothetical_float_a.html b/tests/ref/absolute_hypothetical_float_a.html
new file mode 100644
index 00000000000..78f1c70e04d
--- /dev/null
+++ b/tests/ref/absolute_hypothetical_float_a.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#a {
+ float: right;
+ width: 250px;
+}
+#b {
+ background: blue;
+ position: absolute;
+ width: 100px;
+ height: 100px;
+}
+</style>
+</head>
+<body>
+<div id=a><div id=b>asdf</div></div>
+</body>
+</html>
+
diff --git a/tests/ref/absolute_hypothetical_float_ref.html b/tests/ref/absolute_hypothetical_float_ref.html
new file mode 100644
index 00000000000..008b2a65d29
--- /dev/null
+++ b/tests/ref/absolute_hypothetical_float_ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+#a {
+ float: right;
+ width: 250px;
+}
+#b {
+ background: blue;
+ width: 100px;
+ height: 100px;
+}
+</style>
+</head>
+<body>
+<div id=a><div id=b>asdf</div></div>
+</body>
+</html>
+
+
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index 30af1f25250..be7e36e9e89 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -40,6 +40,7 @@ fragment=top != ../html/acid2.html acid2_ref.html
== abs_float_pref_width_a.html abs_float_pref_width_ref.html
== absolute_content_height_a.html absolute_content_height_ref.html
+== absolute_hypothetical_float_a.html absolute_hypothetical_float_ref.html
== acid1_a.html acid1_b.html
== acid2_noscroll.html acid2_ref_broken.html
== after_block_iteration.html after_block_iteration_ref.html