mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Implement position: absolute
for non-replaced elements.
+ Re-implement fixed positioning using the absolute positioning code. + Add reftests for absolute positioning and fixed positioning. + Refactor assign_widths in BlockFlow to isolate the calculation of widths and margins. + Pass down details of the Containing Block for absolute and fixed flows during layout. Use it to calculate the static position of absolute flows. + Defer calculation of absolute flow dimensions till we build the display list.
This commit is contained in:
parent
478c9bfc57
commit
c4d177a354
15 changed files with 1203 additions and 194 deletions
File diff suppressed because it is too large
Load diff
|
@ -605,6 +605,16 @@ impl Box {
|
||||||
specified(padding, content_box_width)
|
specified(padding, content_box_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn border_and_padding_horiz(&self) -> Au {
|
||||||
|
self.border.get().left + self.border.get().right + self.padding.get().left
|
||||||
|
+ self.padding.get().right
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn border_and_padding_vertical(&self) -> Au {
|
||||||
|
self.border.get().top + self.border.get().bottom + self.padding.get().top
|
||||||
|
+ self.padding.get().bottom
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noncontent_width(&self) -> Au {
|
pub fn noncontent_width(&self) -> Au {
|
||||||
self.noncontent_left() + self.noncontent_right()
|
self.noncontent_left() + self.noncontent_right()
|
||||||
}
|
}
|
||||||
|
@ -613,6 +623,7 @@ impl Box {
|
||||||
self.noncontent_top() + self.noncontent_bottom()
|
self.noncontent_top() + self.noncontent_bottom()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return offset from original position because of `position: relative`.
|
||||||
pub fn relative_position(&self, container_block_size: &Size2D<Au>) -> Point2D<Au> {
|
pub fn relative_position(&self, container_block_size: &Size2D<Au>) -> Point2D<Au> {
|
||||||
fn left_right(style: &ComputedValues, block_width: Au) -> Au {
|
fn left_right(style: &ComputedValues, block_width: Au) -> Au {
|
||||||
// TODO(ksh8281) : consider RTL(right-to-left) culture
|
// TODO(ksh8281) : consider RTL(right-to-left) culture
|
||||||
|
@ -651,6 +662,7 @@ impl Box {
|
||||||
rel_pos.y = rel_pos.y + top_bottom(self.style(), container_block_size.height);
|
rel_pos.y = rel_pos.y + top_bottom(self.style(), container_block_size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go over the ancestor boxes and add all relative offsets (if any).
|
||||||
let info = self.inline_info.borrow();
|
let info = self.inline_info.borrow();
|
||||||
match info.get() {
|
match info.get() {
|
||||||
&Some(ref info) => {
|
&Some(ref info) => {
|
||||||
|
@ -1122,6 +1134,7 @@ impl Box {
|
||||||
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
||||||
// should have a real `SERVO_DEBUG` system.
|
// should have a real `SERVO_DEBUG` system.
|
||||||
debug!("{:?}", {
|
debug!("{:?}", {
|
||||||
|
// This prints a debug border around the border of this box.
|
||||||
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
lists.with_mut(|lists| {
|
lists.with_mut(|lists| {
|
||||||
|
@ -1432,8 +1445,10 @@ impl Box {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns the appropriate width to this box.
|
/// Assigns replaced width for this box only if it is replaced content.
|
||||||
pub fn assign_width(&self,container_width: Au) {
|
///
|
||||||
|
/// CSS 2.1 § 10.3.2.
|
||||||
|
pub fn assign_replaced_width_if_necessary(&self,container_width: Au) {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericBox | IframeBox(_) => {
|
GenericBox | IframeBox(_) => {
|
||||||
}
|
}
|
||||||
|
@ -1469,7 +1484,8 @@ impl Box {
|
||||||
image_box_info.computed_width.set(Some(width));
|
image_box_info.computed_width.set(Some(width));
|
||||||
}
|
}
|
||||||
ScannedTextBox(_) => {
|
ScannedTextBox(_) => {
|
||||||
// Scanned text boxes will have already had their content_widths assigned by this point.
|
// Scanned text boxes will have already had their
|
||||||
|
// content_widths assigned by this point.
|
||||||
let mut position = self.border_box.borrow_mut();
|
let mut position = self.border_box.borrow_mut();
|
||||||
position.get().size.width = position.get().size.width + self.noncontent_width() +
|
position.get().size.width = position.get().size.width + self.noncontent_width() +
|
||||||
self.noncontent_inline_left() + self.noncontent_inline_right();
|
self.noncontent_inline_left() + self.noncontent_inline_right();
|
||||||
|
@ -1478,6 +1494,7 @@ impl Box {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assign height for image and scanned text boxes.
|
||||||
pub fn assign_height(&self) {
|
pub fn assign_height(&self) {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericBox | IframeBox(_) => {
|
GenericBox | IframeBox(_) => {
|
||||||
|
@ -1514,6 +1531,8 @@ impl Box {
|
||||||
ScannedTextBox(_) => {
|
ScannedTextBox(_) => {
|
||||||
// Scanned text boxes will have already had their widths assigned by this point
|
// Scanned text boxes will have already had their widths assigned by this point
|
||||||
let mut position = self.border_box.borrow_mut();
|
let mut position = self.border_box.borrow_mut();
|
||||||
|
// Scanned text boxes' content heights are calculated by the
|
||||||
|
// text run scanner during Flow construction.
|
||||||
position.get().size.height
|
position.get().size.height
|
||||||
= position.get().size.height + self.noncontent_height()
|
= position.get().size.height + self.noncontent_height()
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,8 +410,9 @@ impl<'a> FlowConstructor<'a> {
|
||||||
/// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly
|
/// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly
|
||||||
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
|
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
|
||||||
/// to happen.
|
/// to happen.
|
||||||
fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode, is_fixed: bool) -> ~Flow {
|
fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode, positioning: position::T)
|
||||||
let mut flow = ~BlockFlow::from_node(self, node, is_fixed) as ~Flow;
|
-> ~Flow {
|
||||||
|
let mut flow = ~BlockFlow::from_node(self, node, positioning) as ~Flow;
|
||||||
self.build_children_of_block_flow(&mut flow, node);
|
self.build_children_of_block_flow(&mut flow, node);
|
||||||
flow
|
flow
|
||||||
}
|
}
|
||||||
|
@ -636,7 +637,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn process(&mut self, node: &ThreadSafeLayoutNode) -> bool {
|
fn process(&mut self, node: &ThreadSafeLayoutNode) -> bool {
|
||||||
// Get the `display` property for this node, and determine whether this node is floated.
|
// Get the `display` property for this node, and determine whether this node is floated.
|
||||||
let (display, float, position) = match node.type_id() {
|
let (display, float, positioning) = match node.type_id() {
|
||||||
ElementNodeTypeId(_) => {
|
ElementNodeTypeId(_) => {
|
||||||
let style = node.style().get();
|
let style = node.style().get();
|
||||||
(style.Box.get().display, style.Box.get().float, style.Box.get().position)
|
(style.Box.get().display, style.Box.get().float, style.Box.get().position)
|
||||||
|
@ -652,7 +653,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
debug!("building flow for node: {:?} {:?}", display, float);
|
debug!("building flow for node: {:?} {:?}", display, float);
|
||||||
|
|
||||||
// Switch on display and floatedness.
|
// Switch on display and floatedness.
|
||||||
match (display, float, position) {
|
match (display, float, positioning) {
|
||||||
// `display: none` contributes no flow construction result. Nuke the flow construction
|
// `display: none` contributes no flow construction result. Nuke the flow construction
|
||||||
// results of children.
|
// results of children.
|
||||||
(display::none, _, _) => {
|
(display::none, _, _) => {
|
||||||
|
@ -673,12 +674,12 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
// TODO(pcwalton): Make this only trigger for blocks and handle the other `display`
|
// TODO(pcwalton): Make this only trigger for blocks and handle the other `display`
|
||||||
// properties separately.
|
// properties separately.
|
||||||
|
|
||||||
(_, _, position::fixed) => {
|
(_, _, position::absolute) | (_, _, position::fixed) => {
|
||||||
let flow = self.build_flow_for_block(node, true);
|
let flow = self.build_flow_for_block(node, positioning);
|
||||||
node.set_flow_construction_result(FlowConstructionResult(flow))
|
node.set_flow_construction_result(FlowConstructionResult(flow))
|
||||||
}
|
}
|
||||||
(_, float::none, _) => {
|
(_, float::none, _) => {
|
||||||
let flow = self.build_flow_for_block(node, false);
|
let flow = self.build_flow_for_block(node, positioning);
|
||||||
node.set_flow_construction_result(FlowConstructionResult(flow))
|
node.set_flow_construction_result(FlowConstructionResult(flow))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,4 +855,3 @@ fn strip_ignorable_whitespace_from_end(opt_boxes: &mut Option<~[Box]>) {
|
||||||
*opt_boxes = None
|
*opt_boxes = None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
///
|
///
|
||||||
/// * `BlockFlow`: A flow that establishes a block context. It has several child flows, each of
|
/// * `BlockFlow`: A flow that establishes a block context. It has several child flows, each of
|
||||||
/// which are positioned according to block formatting context rules (CSS block boxes). Block
|
/// which are positioned according to block formatting context rules (CSS block boxes). Block
|
||||||
/// flows also contain a single `GenericBox` to represent their rendered borders, padding, etc.
|
/// flows also contain a single box to represent their rendered borders, padding, etc.
|
||||||
/// The BlockFlow at the root of the tree has special behavior: it stretches to the boundaries of
|
/// The BlockFlow at the root of the tree has special behavior: it stretches to the boundaries of
|
||||||
/// the viewport.
|
/// the viewport.
|
||||||
///
|
///
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
/// similar methods.
|
/// similar methods.
|
||||||
|
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use layout::block::BlockFlow;
|
use layout::block::{BlockFlow};
|
||||||
use layout::box_::Box;
|
use layout::box_::Box;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
|
@ -208,6 +208,7 @@ pub trait MutableFlowUtils {
|
||||||
self,
|
self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
container_block_size: &Size2D<Au>,
|
container_block_size: &Size2D<Au>,
|
||||||
|
absolute_cb_abs_position: Point2D<Au>,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
index: uint,
|
index: uint,
|
||||||
mut list: &RefCell<DisplayListCollection<E>>)
|
mut list: &RefCell<DisplayListCollection<E>>)
|
||||||
|
@ -498,8 +499,9 @@ pub struct BaseFlow {
|
||||||
min_width: Au,
|
min_width: Au,
|
||||||
pref_width: Au,
|
pref_width: Au,
|
||||||
|
|
||||||
/// The position of the upper left corner of the border box of this flow, relative to the
|
/// The upper left corner of the box representing this flow, relative to
|
||||||
/// containing block.
|
/// the box representing its parent flow.
|
||||||
|
/// For absolute flows, this represents the position wrt to its Containing Block.
|
||||||
position: Rect<Au>,
|
position: Rect<Au>,
|
||||||
|
|
||||||
/// The amount of overflow of this flow, relative to the containing block. Must include all the
|
/// The amount of overflow of this flow, relative to the containing block. Must include all the
|
||||||
|
@ -514,7 +516,11 @@ pub struct BaseFlow {
|
||||||
/// The floats next to this flow.
|
/// The floats next to this flow.
|
||||||
floats: Floats,
|
floats: Floats,
|
||||||
|
|
||||||
/// The number of floated descendants of this flow (including this flow, if it's floated).
|
/// For normal flows, this is the number of floated descendants that are
|
||||||
|
/// not contained within any other floated descendant of this flow. For
|
||||||
|
/// floats, it is 1.
|
||||||
|
/// It is used to allocate float data if necessary and to
|
||||||
|
/// decide whether to do an in-order traversal for assign_height.
|
||||||
num_floats: uint,
|
num_floats: uint,
|
||||||
|
|
||||||
/// The position of this flow in page coordinates, computed during display list construction.
|
/// The position of this flow in page coordinates, computed during display list construction.
|
||||||
|
@ -707,6 +713,19 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
f(mut_base(self).children.back_mut())
|
f(mut_base(self).children.back_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate and set overflow for current flow.
|
||||||
|
///
|
||||||
|
/// CSS Section 11.1
|
||||||
|
/// This is ideally the union of all flows for which we define the
|
||||||
|
/// Containing Block.
|
||||||
|
///
|
||||||
|
/// Assumption: This is called in a bottom-up traversal, so kids' overflows have
|
||||||
|
/// already been set.
|
||||||
|
/// So, currently this is a union of the overflows of all kids and our own
|
||||||
|
/// flow rectangle.
|
||||||
|
/// FIXME: Handle the overflow of absolute flow descendants, because their
|
||||||
|
/// assign-heights happen after the normal
|
||||||
|
/// assign-height-and-store-overflow traversal
|
||||||
fn store_overflow(self, _: &mut LayoutContext) {
|
fn store_overflow(self, _: &mut LayoutContext) {
|
||||||
let my_position = mut_base(self).position;
|
let my_position = mut_base(self).position;
|
||||||
let mut overflow = my_position;
|
let mut overflow = my_position;
|
||||||
|
@ -723,17 +742,29 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
/// For InlineFlow, add display items for all its boxes onto list`.
|
/// For InlineFlow, add display items for all its boxes onto list`.
|
||||||
/// For BlockFlow, add a ClipDisplayItemClass for itself and its children,
|
/// For BlockFlow, add a ClipDisplayItemClass for itself and its children,
|
||||||
/// plus any other display items like border.
|
/// plus any other display items like border.
|
||||||
|
///
|
||||||
|
/// `container_block_size`: Size of the Containing Block for the current
|
||||||
|
/// flow. This is used for relative positioning (which resolves percentage
|
||||||
|
/// values for 'top', etc. after all Containing Block heights have been computed.)
|
||||||
|
/// `absolute_cb_abs_position`: Absolute position of the Containing Block
|
||||||
|
/// for the flow if it is absolutely positioned.
|
||||||
fn build_display_lists<E:ExtraDisplayListData>(
|
fn build_display_lists<E:ExtraDisplayListData>(
|
||||||
self,
|
self,
|
||||||
builder: &DisplayListBuilder,
|
builder: &DisplayListBuilder,
|
||||||
container_block_size: &Size2D<Au>,
|
container_block_size: &Size2D<Au>,
|
||||||
|
absolute_cb_abs_position: Point2D<Au>,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
mut index: uint,
|
mut index: uint,
|
||||||
lists: &RefCell<DisplayListCollection<E>>)
|
lists: &RefCell<DisplayListCollection<E>>)
|
||||||
-> bool {
|
-> bool {
|
||||||
debug!("Flow: building display list");
|
debug!("Flow: building display list");
|
||||||
index = match self.class() {
|
index = match self.class() {
|
||||||
BlockFlowClass => self.as_block().build_display_list_block(builder, container_block_size, dirty, index, lists),
|
BlockFlowClass => self.as_block().build_display_list_block(builder,
|
||||||
|
container_block_size,
|
||||||
|
absolute_cb_abs_position,
|
||||||
|
dirty,
|
||||||
|
index,
|
||||||
|
lists),
|
||||||
InlineFlowClass => self.as_inline().build_display_list_inline(builder, container_block_size, dirty, index, lists),
|
InlineFlowClass => self.as_inline().build_display_list_inline(builder, container_block_size, dirty, index, lists),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -745,21 +776,31 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
let mut child_lists = DisplayListCollection::new();
|
let mut child_lists = DisplayListCollection::new();
|
||||||
child_lists.add_list(DisplayList::new());
|
child_lists.add_list(DisplayList::new());
|
||||||
let child_lists = RefCell::new(child_lists);
|
let child_lists = RefCell::new(child_lists);
|
||||||
let container_block_size = match self.class() {
|
let is_positioned = self.as_block().is_positioned();
|
||||||
BlockFlowClass => {
|
let container_block_size;
|
||||||
if self.as_block().box_.is_some() {
|
let abs_cb_position;
|
||||||
self.as_block().box_.get_ref().border_box.get().size
|
let flow_pos = base(self).abs_position;
|
||||||
|
match self.as_block().box_ {
|
||||||
|
Some(ref box_) => {
|
||||||
|
// FIXME: This should be the size of the content box (which is the
|
||||||
|
// Containing Block formed by a BlockFlow), not the border box.
|
||||||
|
container_block_size = box_.border_box.get().size;
|
||||||
|
|
||||||
|
abs_cb_position = if is_positioned {
|
||||||
|
let padding_box_pos = flow_pos + box_.border_box.get().origin
|
||||||
|
+ Point2D(box_.border.get().left, box_.border.get().top);
|
||||||
|
padding_box_pos
|
||||||
} else {
|
} else {
|
||||||
base(self).position.size
|
absolute_cb_abs_position
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
base(self).position.size
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
None => fail!("Flow: block container should have a box_")
|
||||||
|
}
|
||||||
|
|
||||||
for kid in child_iter(self) {
|
for kid in child_iter(self) {
|
||||||
kid.build_display_lists(builder, &container_block_size, dirty, 0u, &child_lists);
|
kid.build_display_lists(builder, &container_block_size,
|
||||||
|
abs_cb_position,
|
||||||
|
dirty, 0u, &child_lists);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut child_lists = Some(child_lists.unwrap());
|
let mut child_lists = Some(child_lists.unwrap());
|
||||||
|
@ -828,4 +869,3 @@ impl MutableOwnedFlowUtils for ~Flow {
|
||||||
self_borrowed.destroy();
|
self_borrowed.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -657,18 +657,13 @@ impl Flow for InlineFlow {
|
||||||
{
|
{
|
||||||
let this = &mut *self;
|
let this = &mut *self;
|
||||||
for box_ in this.boxes.iter() {
|
for box_ in this.boxes.iter() {
|
||||||
box_.assign_width(self.base.position.size.width);
|
box_.assign_replaced_width_if_necessary(self.base.position.size.width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(ksh8281) avoid copy
|
assert!(self.base.children.len() == 0,
|
||||||
let flags_info = self.base.flags_info.clone();
|
"InlineFlow: should not have children flows in the current layout implementation.");
|
||||||
for kid in self.base.child_iter() {
|
|
||||||
let child_base = flow::mut_base(kid);
|
|
||||||
child_base.position.size.width = self.base.position.size.width;
|
|
||||||
child_base.flags_info.flags.set_inorder(self.base.flags_info.flags.inorder());
|
|
||||||
child_base.flags_info.propagate_text_alignment_from_parent(&flags_info)
|
|
||||||
}
|
|
||||||
// There are no child contexts, so stop here.
|
// There are no child contexts, so stop here.
|
||||||
|
|
||||||
// TODO(Issue #225): once there are 'inline-block' elements, this won't be
|
// TODO(Issue #225): once there are 'inline-block' elements, this won't be
|
||||||
|
@ -685,6 +680,9 @@ impl Flow for InlineFlow {
|
||||||
self.assign_height(ctx);
|
self.assign_height(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calculate and set the height of this Flow.
|
||||||
|
///
|
||||||
|
/// CSS Section 10.6.1
|
||||||
fn assign_height(&mut self, _: &mut LayoutContext) {
|
fn assign_height(&mut self, _: &mut LayoutContext) {
|
||||||
debug!("assign_height_inline: assigning height for flow");
|
debug!("assign_height_inline: assigning height for flow");
|
||||||
|
|
||||||
|
@ -901,4 +899,3 @@ impl Flow for InlineFlow {
|
||||||
~"InlineFlow: " + self.boxes.map(|s| s.debug_str()).connect(", ")
|
~"InlineFlow: " + self.boxes.map(|s| s.debug_str()).connect(", ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ use layout::wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
|
||||||
|
|
||||||
use extra::url::Url;
|
use extra::url::Url;
|
||||||
use extra::arc::{Arc, MutexArc};
|
use extra::arc::{Arc, MutexArc};
|
||||||
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator};
|
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator};
|
||||||
|
@ -614,6 +615,7 @@ impl LayoutTask {
|
||||||
if data.goal == ReflowForDisplay {
|
if data.goal == ReflowForDisplay {
|
||||||
profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
|
profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
|
||||||
let root_size = flow::base(layout_root).position.size;
|
let root_size = flow::base(layout_root).position.size;
|
||||||
|
let root_abs_position = Point2D(Au::new(0), Au::new(0));
|
||||||
let mut display_list_collection = DisplayListCollection::new();
|
let mut display_list_collection = DisplayListCollection::new();
|
||||||
display_list_collection.add_list(DisplayList::<OpaqueNode>::new());
|
display_list_collection.add_list(DisplayList::<OpaqueNode>::new());
|
||||||
let display_list_collection = ~RefCell::new(display_list_collection);
|
let display_list_collection = ~RefCell::new(display_list_collection);
|
||||||
|
@ -621,7 +623,9 @@ impl LayoutTask {
|
||||||
let display_list_builder = DisplayListBuilder {
|
let display_list_builder = DisplayListBuilder {
|
||||||
ctx: &layout_ctx,
|
ctx: &layout_ctx,
|
||||||
};
|
};
|
||||||
layout_root.build_display_lists(&display_list_builder, &root_size, &dirty, 0u, display_list_collection);
|
layout_root.build_display_lists(&display_list_builder, &root_size,
|
||||||
|
root_abs_position,
|
||||||
|
&dirty, 0u, display_list_collection);
|
||||||
|
|
||||||
let display_list_collection = Arc::new(display_list_collection.unwrap());
|
let display_list_collection = Arc::new(display_list_collection.unwrap());
|
||||||
|
|
||||||
|
@ -842,4 +846,3 @@ impl LayoutTask {
|
||||||
util::replace(layout_data_ref.get(), None));
|
util::replace(layout_data_ref.get(), None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,18 @@ impl FlowParallelInfo {
|
||||||
|
|
||||||
/// A parallel bottom-up flow traversal.
|
/// A parallel bottom-up flow traversal.
|
||||||
trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
|
/// Process current flow and potentially traverse its ancestors.
|
||||||
|
///
|
||||||
|
/// If we are the last child that finished processing, recursively process
|
||||||
|
/// our parent. Else, stop.
|
||||||
|
/// Also, stop at the root (obviously :P).
|
||||||
|
///
|
||||||
|
/// Thus, if we start with all the leaves of a tree, we end up traversing
|
||||||
|
/// the whole tree bottom-up because each parent will be processed exactly
|
||||||
|
/// once (by the last child that finishes processing).
|
||||||
|
///
|
||||||
|
/// The only communication between siblings is that they both
|
||||||
|
/// fetch-and-subtract the parent's children count.
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&mut self,
|
||||||
mut unsafe_flow: UnsafeFlow,
|
mut unsafe_flow: UnsafeFlow,
|
||||||
_: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>) {
|
_: &mut WorkerProxy<*mut LayoutContext,PaddedUnsafeFlow>) {
|
||||||
|
@ -144,8 +156,9 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// No, we're not at the root yet. Then are we the last sibling of our parent? If
|
// No, we're not at the root yet. Then are we the last child
|
||||||
// so, we can continue on with our parent; otherwise, we've gotta wait.
|
// of our parent to finish processing? If so, we can continue
|
||||||
|
// on with our parent; otherwise, we've gotta wait.
|
||||||
let parent: &mut ~Flow = cast::transmute(&unsafe_parent);
|
let parent: &mut ~Flow = cast::transmute(&unsafe_parent);
|
||||||
let parent_base = flow::mut_base(*parent);
|
let parent_base = flow::mut_base(*parent);
|
||||||
if parent_base.parallel.children_count.fetch_sub(1, SeqCst) == 1 {
|
if parent_base.parallel.children_count.fetch_sub(1, SeqCst) == 1 {
|
||||||
|
@ -426,4 +439,3 @@ pub fn traverse_flow_tree_preorder(root: &mut ~Flow,
|
||||||
|
|
||||||
queue.data = ptr::mut_null()
|
queue.data = ptr::mut_null()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
src/test/ref/position_abs_height_width_a.html
Normal file
26
src/test/ref/position_abs_height_width_a.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
position: relative;
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
#abs {
|
||||||
|
position: absolute;
|
||||||
|
left: 30px;
|
||||||
|
top: 30px;
|
||||||
|
right: 30px;
|
||||||
|
bottom: 30px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<div id="abs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
29
src/test/ref/position_abs_height_width_b.html
Normal file
29
src/test/ref/position_abs_height_width_b.html
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<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">
|
||||||
|
</div>
|
||||||
|
<div class="row"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
30
src/test/ref/position_abs_left_a.html
Normal file
30
src/test/ref/position_abs_left_a.html
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#first {
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
#abs {
|
||||||
|
position: absolute;
|
||||||
|
left: auto;
|
||||||
|
top: 0px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="abs">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
18
src/test/ref/position_abs_left_b.html
Normal file
18
src/test/ref/position_abs_left_b.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#first {
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
26
src/test/ref/position_abs_width_percentage_a.html
Normal file
26
src/test/ref/position_abs_width_percentage_a.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
position: relative;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
#abs {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
right: 50%;
|
||||||
|
top: 50%;
|
||||||
|
height: 50px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<div id="abs">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
27
src/test/ref/position_abs_width_percentage_b.html
Normal file
27
src/test/ref/position_abs_width_percentage_b.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
#first {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: solid 1px;
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
width: 100px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.green_square {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first">
|
||||||
|
<div class="row"></div>
|
||||||
|
<div class="green_square">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
38
src/test/ref/position_fixed_simple_a.html
Normal file
38
src/test/ref/position_fixed_simple_a.html
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#rel-cont {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#first {
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
#normal {
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
#fixed {
|
||||||
|
position: fixed;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first" class="box">
|
||||||
|
</div>
|
||||||
|
<div id="normal" class="box"></div>
|
||||||
|
<!-- This should become empty -->
|
||||||
|
<div id="rel-cont">
|
||||||
|
<div id="fixed" class="box">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
src/test/ref/position_fixed_simple_b.html
Normal file
24
src/test/ref/position_fixed_simple_b.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#first {
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
#normal {
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="first" class="box">
|
||||||
|
</div>
|
||||||
|
<div id="normal" class="box"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue