mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Implement position: absolute
for replaced elements.
Add reftests for replaced and nested absolute flows.
This commit is contained in:
parent
4a6077ca4c
commit
070be51910
9 changed files with 402 additions and 43 deletions
|
@ -10,8 +10,8 @@
|
||||||
//! The term 'positioned element' refers to elements with position =
|
//! The term 'positioned element' refers to elements with position =
|
||||||
//! 'relative', 'absolute', or 'fixed'.
|
//! 'relative', 'absolute', or 'fixed'.
|
||||||
|
|
||||||
use layout::box_::Box;
|
use layout::box_::{Box, ImageBox, ScannedTextBox};
|
||||||
use layout::construct::{FlowConstructor, OptVector};
|
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, ExtraDisplayListData};
|
||||||
use layout::floats::{FloatKind, Floats, PlacementInfo};
|
use layout::floats::{FloatKind, Floats, PlacementInfo};
|
||||||
|
@ -78,6 +78,94 @@ impl WidthConstraintSolution {
|
||||||
margin_right: margin_right,
|
margin_right: margin_right,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Solve the horizontal constraint equation for absolute replaced elements.
|
||||||
|
///
|
||||||
|
/// `static_x_offset`: total offset of current flow's hypothetical
|
||||||
|
/// position (static position) from its actual Containing Block.
|
||||||
|
///
|
||||||
|
/// Assumption: The used value for width has already been calculated.
|
||||||
|
///
|
||||||
|
/// CSS Section 10.3.8
|
||||||
|
/// Constraint equation:
|
||||||
|
/// left + right + width + margin-left + margin-right
|
||||||
|
/// = absolute containing block width - (horizontal padding and border)
|
||||||
|
/// [aka available_width]
|
||||||
|
///
|
||||||
|
/// Return the solution for the equation.
|
||||||
|
fn solve_horiz_constraints_abs_replaced(width: Au,
|
||||||
|
left_margin: MaybeAuto,
|
||||||
|
right_margin: MaybeAuto,
|
||||||
|
left: MaybeAuto,
|
||||||
|
right: MaybeAuto,
|
||||||
|
available_width: Au,
|
||||||
|
static_x_offset: Au)
|
||||||
|
-> WidthConstraintSolution {
|
||||||
|
// TODO: Check for direction of static-position Containing Block (aka
|
||||||
|
// parent flow, _not_ the actual Containing Block) when right-to-left
|
||||||
|
// is implemented
|
||||||
|
// Assume direction is 'ltr' for now
|
||||||
|
// TODO: Handle all the cases for 'rtl' direction.
|
||||||
|
|
||||||
|
// Distance from the left edge of the Absolute Containing Block to the
|
||||||
|
// left margin edge of a hypothetical box that would have been the
|
||||||
|
// first box of the element.
|
||||||
|
let static_position_left = static_x_offset;
|
||||||
|
|
||||||
|
let (left, right, width, margin_left, margin_right) = match (left, right) {
|
||||||
|
(Auto, Auto) => {
|
||||||
|
let left = static_position_left;
|
||||||
|
let margin_l = left_margin.specified_or_zero();
|
||||||
|
let margin_r = right_margin.specified_or_zero();
|
||||||
|
let sum = left + width + margin_l + margin_r;
|
||||||
|
(left, available_width - sum, width, margin_l, margin_r)
|
||||||
|
}
|
||||||
|
// If only one is Auto, solve for it
|
||||||
|
(Auto, Specified(right)) => {
|
||||||
|
let margin_l = left_margin.specified_or_zero();
|
||||||
|
let margin_r = right_margin.specified_or_zero();
|
||||||
|
let sum = right + width + margin_l + margin_r;
|
||||||
|
(available_width - sum, right, width, margin_l, margin_r)
|
||||||
|
}
|
||||||
|
(Specified(left), Auto) => {
|
||||||
|
let margin_l = left_margin.specified_or_zero();
|
||||||
|
let margin_r = right_margin.specified_or_zero();
|
||||||
|
let sum = left + width + margin_l + margin_r;
|
||||||
|
(left, available_width - sum, width, margin_l, margin_r)
|
||||||
|
}
|
||||||
|
(Specified(left), Specified(right)) => {
|
||||||
|
match (left_margin, right_margin) {
|
||||||
|
(Auto, Auto) => {
|
||||||
|
let total_margin_val = (available_width - left - right - width);
|
||||||
|
if total_margin_val < Au(0) {
|
||||||
|
// margin-left becomes 0 because direction is 'ltr'.
|
||||||
|
(left, right, width, Au(0), total_margin_val)
|
||||||
|
} else {
|
||||||
|
// Equal margins
|
||||||
|
(left, right, width,
|
||||||
|
total_margin_val.scale_by(0.5),
|
||||||
|
total_margin_val.scale_by(0.5))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Specified(margin_l), Auto) => {
|
||||||
|
let sum = left + right + width + margin_l;
|
||||||
|
(left, right, width, margin_l, available_width - sum)
|
||||||
|
}
|
||||||
|
(Auto, Specified(margin_r)) => {
|
||||||
|
let sum = left + right + width + margin_r;
|
||||||
|
(left, right, width, available_width - sum, margin_r)
|
||||||
|
}
|
||||||
|
(Specified(margin_l), Specified(margin_r)) => {
|
||||||
|
// Values are over-constrained.
|
||||||
|
// Ignore value for 'right' cos direction is 'ltr'.
|
||||||
|
let sum = left + width + margin_l + margin_r;
|
||||||
|
(left, available_width - sum, width, margin_l, margin_r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
WidthConstraintSolution::new(left, right, width, margin_left, margin_right)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The solutions for the heights-and-margins constraint equation.
|
/// The solutions for the heights-and-margins constraint equation.
|
||||||
|
@ -110,20 +198,20 @@ impl HeightConstraintSolution {
|
||||||
/// [aka available_height]
|
/// [aka available_height]
|
||||||
///
|
///
|
||||||
/// Return the solution for the equation.
|
/// Return the solution for the equation.
|
||||||
fn solve_vertical_constraints_abs_position(height: MaybeAuto,
|
fn solve_vertical_constraints_abs_nonreplaced(height: MaybeAuto,
|
||||||
top_margin: MaybeAuto,
|
top_margin: MaybeAuto,
|
||||||
bottom_margin: MaybeAuto,
|
bottom_margin: MaybeAuto,
|
||||||
top: MaybeAuto,
|
top: MaybeAuto,
|
||||||
bottom: MaybeAuto,
|
bottom: MaybeAuto,
|
||||||
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.
|
||||||
let static_position_top = static_y_offset;
|
let static_position_top = static_y_offset;
|
||||||
;
|
|
||||||
let (top, bottom, height, margin_top, margin_bottom) = match (top, bottom, height) {
|
let (top, bottom, height, margin_top, margin_bottom) = match (top, bottom, height) {
|
||||||
(Auto, Auto, Auto) => {
|
(Auto, Auto, Auto) => {
|
||||||
let margin_top = top_margin.specified_or_zero();
|
let margin_top = top_margin.specified_or_zero();
|
||||||
|
@ -209,6 +297,80 @@ impl HeightConstraintSolution {
|
||||||
};
|
};
|
||||||
HeightConstraintSolution::new(top, bottom, height, margin_top, margin_bottom)
|
HeightConstraintSolution::new(top, bottom, height, margin_top, margin_bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Solve the vertical constraint equation for absolute replaced elements.
|
||||||
|
///
|
||||||
|
/// Assumption: The used value for height has already been calculated.
|
||||||
|
///
|
||||||
|
/// CSS Section 10.6.5
|
||||||
|
/// Constraint equation:
|
||||||
|
/// top + bottom + height + margin-top + margin-bottom
|
||||||
|
/// = absolute containing block height - (vertical padding and border)
|
||||||
|
/// [aka available_height]
|
||||||
|
///
|
||||||
|
/// Return the solution for the equation.
|
||||||
|
fn solve_vertical_constraints_abs_replaced(height: Au,
|
||||||
|
top_margin: MaybeAuto,
|
||||||
|
bottom_margin: MaybeAuto,
|
||||||
|
top: MaybeAuto,
|
||||||
|
bottom: MaybeAuto,
|
||||||
|
_: Au,
|
||||||
|
available_height: Au,
|
||||||
|
static_y_offset: Au)
|
||||||
|
-> HeightConstraintSolution {
|
||||||
|
// Distance from the top edge of the Absolute Containing Block to the
|
||||||
|
// top margin edge of a hypothetical box that would have been the
|
||||||
|
// first box of the element.
|
||||||
|
let static_position_top = static_y_offset;
|
||||||
|
|
||||||
|
let (top, bottom, height, margin_top, margin_bottom) = match (top, bottom) {
|
||||||
|
(Auto, Auto) => {
|
||||||
|
let margin_top = top_margin.specified_or_zero();
|
||||||
|
let margin_bottom = bottom_margin.specified_or_zero();
|
||||||
|
let top = static_position_top;
|
||||||
|
let sum = top + height + margin_top + margin_bottom;
|
||||||
|
(top, available_height - sum, height, margin_top, margin_bottom)
|
||||||
|
}
|
||||||
|
(Specified(top), Specified(bottom)) => {
|
||||||
|
match (top_margin, bottom_margin) {
|
||||||
|
(Auto, Auto) => {
|
||||||
|
let total_margin_val = (available_height - top - bottom - height);
|
||||||
|
(top, bottom, height,
|
||||||
|
total_margin_val.scale_by(0.5),
|
||||||
|
total_margin_val.scale_by(0.5))
|
||||||
|
}
|
||||||
|
(Specified(margin_top), Auto) => {
|
||||||
|
let sum = top + bottom + height + margin_top;
|
||||||
|
(top, bottom, height, margin_top, available_height - sum)
|
||||||
|
}
|
||||||
|
(Auto, Specified(margin_bottom)) => {
|
||||||
|
let sum = top + bottom + height + margin_bottom;
|
||||||
|
(top, bottom, height, available_height - sum, margin_bottom)
|
||||||
|
}
|
||||||
|
(Specified(margin_top), Specified(margin_bottom)) => {
|
||||||
|
// Values are over-constrained. Ignore value for 'bottom'.
|
||||||
|
let sum = top + height + margin_top + margin_bottom;
|
||||||
|
(top, available_height - sum, height, margin_top, margin_bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If only one is Auto, solve for it
|
||||||
|
(Auto, Specified(bottom)) => {
|
||||||
|
let margin_top = top_margin.specified_or_zero();
|
||||||
|
let margin_bottom = bottom_margin.specified_or_zero();
|
||||||
|
let sum = bottom + height + margin_top + margin_bottom;
|
||||||
|
(available_height - sum, bottom, height, margin_top, margin_bottom)
|
||||||
|
}
|
||||||
|
(Specified(top), Auto) => {
|
||||||
|
let margin_top = top_margin.specified_or_zero();
|
||||||
|
let margin_bottom = bottom_margin.specified_or_zero();
|
||||||
|
let sum = top + height + margin_top + margin_bottom;
|
||||||
|
(top, available_height - sum, height, margin_top, margin_bottom)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
HeightConstraintSolution::new(top, bottom, height, margin_top, margin_bottom)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The real assign-heights traversal for flows with position 'absolute'.
|
/// The real assign-heights traversal for flows with position 'absolute'.
|
||||||
|
@ -424,6 +586,22 @@ impl BlockFlow {
|
||||||
traversal.process(flow)
|
traversal.process(flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if this has a replaced box.
|
||||||
|
///
|
||||||
|
/// The only two types of replaced boxes currently are text boxes and
|
||||||
|
/// image boxes.
|
||||||
|
fn is_replaced_content(&self) -> bool {
|
||||||
|
match self.box_ {
|
||||||
|
Some(ref box_) => {
|
||||||
|
match box_.specific {
|
||||||
|
ScannedTextBox(_) | ImageBox(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
for box_ in self.box_.iter() {
|
for box_ in self.box_.iter() {
|
||||||
box_.teardown();
|
box_.teardown();
|
||||||
|
@ -521,14 +699,28 @@ impl BlockFlow {
|
||||||
(MaybeAuto::from_style(style.PositionOffsets.get().left, containing_block_width),
|
(MaybeAuto::from_style(style.PositionOffsets.get().left, containing_block_width),
|
||||||
MaybeAuto::from_style(style.PositionOffsets.get().right, containing_block_width));
|
MaybeAuto::from_style(style.PositionOffsets.get().right, containing_block_width));
|
||||||
let available_width = containing_block_width - box_.border_and_padding_horiz();
|
let available_width = containing_block_width - box_.border_and_padding_horiz();
|
||||||
// TODO: Extract this later into a SolveConstraints trait or something
|
|
||||||
let solution = self.solve_horiz_constraints_abs_position(width,
|
let solution = if self.is_replaced_content() {
|
||||||
margin_left,
|
// Calculate used value of width just like we do for inline replaced elements.
|
||||||
margin_right,
|
box_.assign_replaced_width_if_necessary(containing_block_width);
|
||||||
left,
|
let width = box_.border_box.get().size.width;
|
||||||
right,
|
WidthConstraintSolution::solve_horiz_constraints_abs_replaced(width,
|
||||||
available_width,
|
margin_left,
|
||||||
static_x_offset);
|
margin_right,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
available_width,
|
||||||
|
static_x_offset)
|
||||||
|
} else {
|
||||||
|
// TODO: Extract this later into a SolveConstraints trait or something
|
||||||
|
self.solve_horiz_constraints_abs_nonreplaced(width,
|
||||||
|
margin_left,
|
||||||
|
margin_right,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
available_width,
|
||||||
|
static_x_offset)
|
||||||
|
};
|
||||||
|
|
||||||
let mut margin = box_.margin.get();
|
let mut margin = box_.margin.get();
|
||||||
margin.left = solution.margin_left;
|
margin.left = solution.margin_left;
|
||||||
|
@ -614,17 +806,18 @@ impl BlockFlow {
|
||||||
/// [aka available_width]
|
/// [aka available_width]
|
||||||
///
|
///
|
||||||
/// Return the solution for the equation.
|
/// Return the solution for the equation.
|
||||||
fn solve_horiz_constraints_abs_position(&self,
|
fn solve_horiz_constraints_abs_nonreplaced(&self,
|
||||||
width: MaybeAuto,
|
width: MaybeAuto,
|
||||||
left_margin: MaybeAuto,
|
left_margin: MaybeAuto,
|
||||||
right_margin: MaybeAuto,
|
right_margin: MaybeAuto,
|
||||||
left: MaybeAuto,
|
left: MaybeAuto,
|
||||||
right: MaybeAuto,
|
right: MaybeAuto,
|
||||||
available_width: Au,
|
available_width: Au,
|
||||||
static_x_offset: Au)
|
static_x_offset: Au)
|
||||||
-> WidthConstraintSolution {
|
-> WidthConstraintSolution {
|
||||||
// TODO: Check for direction of parent flow (NOT Containing Block)
|
// TODO: Check for direction of static-position Containing Block (aka
|
||||||
// when right-to-left is implemented.
|
// parent flow, _not_ the actual Containing Block) when right-to-left
|
||||||
|
// is implemented
|
||||||
// Assume direction is 'ltr' for now
|
// Assume direction is 'ltr' for now
|
||||||
|
|
||||||
// Distance from the left edge of the Absolute Containing Block to the
|
// Distance from the left edge of the Absolute Containing Block to the
|
||||||
|
@ -1358,15 +1551,34 @@ impl BlockFlow {
|
||||||
MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_block_height));
|
MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_block_height));
|
||||||
let available_height = containing_block_height - box_.border_and_padding_vert();
|
let available_height = containing_block_height - box_.border_and_padding_vert();
|
||||||
|
|
||||||
let solution = HeightConstraintSolution::solve_vertical_constraints_abs_position(
|
let solution = if self.is_replaced_content() {
|
||||||
height_used_val,
|
// Calculate used value of height just like we do for inline replaced elements.
|
||||||
margin_top,
|
// TODO: Pass in the containing block height when Box's
|
||||||
margin_bottom,
|
// assign-height can handle it correctly.
|
||||||
top,
|
box_.assign_replaced_height_if_necessary();
|
||||||
bottom,
|
// TODO: Right now, this content height value includes the
|
||||||
content_height,
|
// margin because of erroneous height calculation in Box_.
|
||||||
available_height,
|
// Check this when that has been fixed.
|
||||||
static_y_offset);
|
let height_used_val = box_.border_box.get().size.height;
|
||||||
|
HeightConstraintSolution::solve_vertical_constraints_abs_replaced(height_used_val,
|
||||||
|
margin_top,
|
||||||
|
margin_bottom,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
content_height,
|
||||||
|
available_height,
|
||||||
|
static_y_offset)
|
||||||
|
} else {
|
||||||
|
HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
|
||||||
|
height_used_val,
|
||||||
|
margin_top,
|
||||||
|
margin_bottom,
|
||||||
|
top,
|
||||||
|
bottom,
|
||||||
|
content_height,
|
||||||
|
available_height,
|
||||||
|
static_y_offset)
|
||||||
|
};
|
||||||
|
|
||||||
let mut margin = box_.margin.get();
|
let mut margin = box_.margin.get();
|
||||||
margin.top = solution.margin_top;
|
margin.top = solution.margin_top;
|
||||||
|
@ -1626,7 +1838,7 @@ impl Flow for BlockFlow {
|
||||||
fn assign_height(&mut self, ctx: &mut LayoutContext) {
|
fn assign_height(&mut self, ctx: &mut LayoutContext) {
|
||||||
// Assign height for box if it is an image box.
|
// Assign height for box if it is an image box.
|
||||||
for box_ in self.box_.iter() {
|
for box_ in self.box_.iter() {
|
||||||
box_.assign_height();
|
box_.assign_replaced_height_if_necessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
|
|
|
@ -166,6 +166,10 @@ impl ImageBoxInfo {
|
||||||
Au::from_px(image_ref.get().get_size().unwrap_or(Size2D(0,0)).width)
|
Au::from_px(image_ref.get().get_size().unwrap_or(Size2D(0,0)).width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return used value for width or height.
|
||||||
|
//
|
||||||
|
// `dom_length`: width or height as specified in the `img` tag.
|
||||||
|
// `style_length`: width as given in the CSS
|
||||||
pub fn style_length(style_length: LengthOrPercentageOrAuto,
|
pub fn style_length(style_length: LengthOrPercentageOrAuto,
|
||||||
dom_length: Option<Au>,
|
dom_length: Option<Au>,
|
||||||
container_width: Au) -> MaybeAuto {
|
container_width: Au) -> MaybeAuto {
|
||||||
|
@ -1455,6 +1459,7 @@ impl Box {
|
||||||
|
|
||||||
/// Assigns replaced width for this box only if it is replaced content.
|
/// Assigns replaced width for this box only if it is replaced content.
|
||||||
///
|
///
|
||||||
|
/// This assigns only the width, not margin or anything else.
|
||||||
/// CSS 2.1 § 10.3.2.
|
/// CSS 2.1 § 10.3.2.
|
||||||
pub fn assign_replaced_width_if_necessary(&self,container_width: Au) {
|
pub fn assign_replaced_width_if_necessary(&self,container_width: Au) {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
|
@ -1502,8 +1507,10 @@ impl Box {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign height for image and scanned text boxes.
|
/// Assign height for this box if it is replaced content.
|
||||||
pub fn assign_height(&self) {
|
///
|
||||||
|
/// Ideally, this should follow CSS 2.1 § 10.6.2
|
||||||
|
pub fn assign_replaced_height_if_necessary(&self) {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericBox | IframeBox(_) => {
|
GenericBox | IframeBox(_) => {
|
||||||
}
|
}
|
||||||
|
|
|
@ -687,6 +687,13 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
|
// Construct Flow based on 'display', 'position', and 'float' values.
|
||||||
|
//
|
||||||
|
// CSS 2.1 Section 9.7
|
||||||
|
//
|
||||||
|
// TODO: This should actually consult the table in that section to get the
|
||||||
|
// final computed value for 'display'.
|
||||||
|
//
|
||||||
// `#[inline(always)]` because this is always called from the traversal function and for some
|
// `#[inline(always)]` because this is always called from the traversal function and for some
|
||||||
// reason LLVM's inlining heuristics go awry here.
|
// reason LLVM's inlining heuristics go awry here.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -718,6 +725,10 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Absolutely positioned elements will have computed value of
|
||||||
|
// `float` as 'none' and `display` as per the table.
|
||||||
|
// Currently, for original `display` value of 'inline', the new
|
||||||
|
// `display` value is 'block'.
|
||||||
(_, _, position::absolute) | (_, _, position::fixed) => {
|
(_, _, position::absolute) | (_, _, position::fixed) => {
|
||||||
node.set_flow_construction_result(self.build_flow_for_block(node))
|
node.set_flow_construction_result(self.build_flow_for_block(node))
|
||||||
}
|
}
|
||||||
|
|
|
@ -698,7 +698,7 @@ impl Flow for InlineFlow {
|
||||||
debug!("assign_height_inline: floats in: {:?}", self.base.floats);
|
debug!("assign_height_inline: floats in: {:?}", self.base.floats);
|
||||||
// assign height for inline boxes
|
// assign height for inline boxes
|
||||||
for box_ in self.boxes.iter() {
|
for box_ in self.boxes.iter() {
|
||||||
box_.assign_height();
|
box_.assign_replaced_height_if_necessary();
|
||||||
}
|
}
|
||||||
let scanner_floats = self.base.floats.clone();
|
let scanner_floats = self.base.floats.clone();
|
||||||
let mut scanner = LineboxScanner::new(scanner_floats);
|
let mut scanner = LineboxScanner::new(scanner_floats);
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
== 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
|
||||||
== position_abs_left_a.html position_abs_left_b.html
|
== position_abs_left_a.html position_abs_left_b.html
|
||||||
|
== position_abs_nested_a.html position_abs_nested_b.html
|
||||||
|
== position_abs_replaced_simple_a.html position_abs_replaced_simple_b.html
|
||||||
== position_abs_static_y_a.html position_abs_static_y_b.html
|
== position_abs_static_y_a.html position_abs_static_y_b.html
|
||||||
== position_abs_width_percentage_a.html position_abs_width_percentage_b.html
|
== position_abs_width_percentage_a.html position_abs_width_percentage_b.html
|
||||||
== position_fixed_a.html position_fixed_b.html
|
== position_fixed_a.html position_fixed_b.html
|
||||||
|
|
34
src/test/ref/position_abs_nested_a.html
Normal file
34
src/test/ref/position_abs_nested_a.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
position: relative;
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
#abs {
|
||||||
|
position: absolute;
|
||||||
|
left: 30px;
|
||||||
|
top: 30px;
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
#abs2 {
|
||||||
|
position: absolute;
|
||||||
|
background: green;
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<div id="abs">
|
||||||
|
<div id="abs2">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
36
src/test/ref/position_abs_nested_b.html
Normal file
36
src/test/ref/position_abs_nested_b.html
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
width: 90px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
margin-left: 30px;
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
.little-box {
|
||||||
|
height: 15px;
|
||||||
|
width: 15px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<div class="row"></div>
|
||||||
|
<div class="center">
|
||||||
|
<div class="little-box">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
25
src/test/ref/position_abs_replaced_simple_a.html
Normal file
25
src/test/ref/position_abs_replaced_simple_a.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
position: relative;
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
#abs {
|
||||||
|
position: absolute;
|
||||||
|
margin: 0px;
|
||||||
|
top: 30px;
|
||||||
|
right: 30px;
|
||||||
|
bottom: 30px;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<img src="rust_logo.png" width="100" id="abs" alt="Rust Logo" />
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
32
src/test/ref/position_abs_replaced_simple_b.html
Normal file
32
src/test/ref/position_abs_replaced_simple_b.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
width: 90px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
margin-left: 30px;
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<div class="row">
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<img src="rust_logo.png" width="30" id="abs" alt="Rust Logo" />
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue