diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 44f8c31bf0e..40f95bf768b 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -13,7 +13,7 @@ use layout::model::{MaybeAuto, Specified, Auto, specified_or_none, specified}; use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType}; use std::cell::RefCell; -use geom::{Point2D, Rect, SideOffsets2D}; +use geom::{Point2D, Rect, SideOffsets2D, Size2D}; use gfx::display_list::{DisplayList, DisplayListCollection}; use servo_util::geometry::Au; use servo_util::geometry; @@ -533,12 +533,13 @@ impl BlockFlow { pub fn build_display_list_block( &mut self, builder: &DisplayListBuilder, + container_block_size: &Size2D, dirty: &Rect, mut index: uint, lists: &RefCell>) -> uint { if self.is_float() { - self.build_display_list_float(builder, dirty, index, lists); + self.build_display_list_float(builder, container_block_size, dirty, index, lists); return index; } @@ -556,16 +557,28 @@ impl BlockFlow { debug!("build_display_list_block: adding display element"); + let rel_offset = match self.box_ { + Some(ref box_) => { + box_.relative_position(container_block_size) + }, + None => { + Point2D { + x: Au::new(0), + y: Au::new(0), + } + } + }; + // add box that starts block context for box_ in self.box_.iter() { - box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists); + box_.build_display_list(builder, dirty, self.base.abs_position + rel_offset, (&*self) as &Flow, index, lists); } // TODO: handle any out-of-flow elements let this_position = self.base.abs_position; for child in self.base.child_iter() { let child_base = flow::mut_base(*child); - child_base.abs_position = this_position + child_base.position.origin; + child_base.abs_position = this_position + child_base.position.origin + rel_offset; } index @@ -574,6 +587,7 @@ impl BlockFlow { pub fn build_display_list_float( &mut self, builder: &DisplayListBuilder, + container_block_size: &Size2D, dirty: &Rect, index: uint, lists: &RefCell>) @@ -583,8 +597,21 @@ impl BlockFlow { return true; } + // position:relative + let rel_offset = match self.box_ { + Some(ref box_) => { + box_.relative_position(container_block_size) + }, + None => { + Point2D { + x: Au::new(0), + y: Au::new(0), + } + } + }; - let offset = self.base.abs_position + self.float.get_ref().rel_pos; + + let offset = self.base.abs_position + self.float.get_ref().rel_pos + rel_offset; // add box that starts block context for box_ in self.box_.iter() { box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, index, lists); @@ -596,7 +623,7 @@ impl BlockFlow { // go deeper into the flow tree for child in self.base.child_iter() { let child_base = flow::mut_base(*child); - child_base.abs_position = offset + child_base.position.origin; + child_base.abs_position = offset + child_base.position.origin + rel_offset; } false diff --git a/src/components/main/layout/box_.rs b/src/components/main/layout/box_.rs index 9908fa1cceb..8df9a39957b 100644 --- a/src/components/main/layout/box_.rs +++ b/src/components/main/layout/box_.rs @@ -29,7 +29,7 @@ use std::cmp::ApproxEq; use std::num::Zero; use style::{ComputedValues, TElement, TNode}; use style::computed_values::{LengthOrPercentage, LengthOrPercentageOrAuto, overflow, LPA_Auto}; -use style::computed_values::{border_style, clear, font_family, line_height}; +use style::computed_values::{border_style, clear, font_family, line_height, position}; use style::computed_values::{text_align, text_decoration, vertical_align, visibility, white_space}; use css::node_style::StyledNode; @@ -651,6 +651,59 @@ impl Box { &None => {} } } + pub fn relative_position(&self, container_block_size: &Size2D) -> Point2D { + fn left_right(style: &ComputedValues,block_width: Au) -> Au { + // TODO(ksh8281) : consider RTL(right-to-left) culture + match (style.PositionOffsets.left, style.PositionOffsets.right) { + (LPA_Auto, _) => { + -MaybeAuto::from_style(style.PositionOffsets.right, block_width) + .specified_or_zero() + } + (_, _) => { + MaybeAuto::from_style(style.PositionOffsets.left, block_width) + .specified_or_zero() + } + } + } + + fn top_bottom(style: &ComputedValues,block_height: Au) -> Au { + match (style.PositionOffsets.top, style.PositionOffsets.bottom) { + (LPA_Auto, _) => { + -MaybeAuto::from_style(style.PositionOffsets.bottom, block_height) + .specified_or_zero() + } + (_, _) => { + MaybeAuto::from_style(style.PositionOffsets.top, block_height) + .specified_or_zero() + } + } + } + + let mut rel_pos: Point2D = Point2D { + x: Au::new(0), + y: Au::new(0), + }; + + if self.style().Box.position == position::relative { + rel_pos.x = rel_pos.x + left_right(self.style(), container_block_size.width); + rel_pos.y = rel_pos.y + top_bottom(self.style(), container_block_size.height); + } + + let info = self.inline_info.borrow(); + match info.get() { + &Some(ref info) => { + for info in info.parent_info.iter() { + if info.style.get().Box.position == position::relative { + rel_pos.x = rel_pos.x + left_right(info.style.get(), container_block_size.width); + rel_pos.y = rel_pos.y + top_bottom(info.style.get(), container_block_size.height); + } + } + }, + &None => {} + } + rel_pos + } + /// Always inline for SCCP. /// /// FIXME(pcwalton): Just replace with the clear type from the style module for speed? diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index f3070481e04..6549a425d36 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -40,6 +40,7 @@ use layout::wrapper::ThreadSafeLayoutNode; use extra::dlist::{DList, DListIterator, MutDListIterator}; use extra::container::Deque; use geom::point::Point2D; +use geom::Size2D; use geom::rect::Rect; use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection, DisplayList}; use layout::display_list_builder::ToGfxColor; @@ -207,6 +208,7 @@ pub trait MutableFlowUtils { fn build_display_lists( self, builder: &DisplayListBuilder, + container_block_size: &Size2D, dirty: &Rect, index: uint, mut list: &RefCell>) @@ -726,14 +728,15 @@ impl<'a> MutableFlowUtils for &'a mut Flow { fn build_display_lists( self, builder: &DisplayListBuilder, + container_block_size: &Size2D, dirty: &Rect, mut index: uint, lists: &RefCell>) -> bool { debug!("Flow: building display list for f{}", base(self).id); index = match self.class() { - BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, index, lists), - InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, index, lists), + BlockFlowClass => self.as_block().build_display_list_block(builder, container_block_size, dirty, index, lists), + InlineFlowClass => self.as_inline().build_display_list_inline(builder, container_block_size, dirty, index, lists), }; if lists.with_mut(|lists| lists.lists[index].list.len() == 0) { @@ -744,8 +747,21 @@ impl<'a> MutableFlowUtils for &'a mut Flow { let mut child_lists = DisplayListCollection::new(); child_lists.add_list(DisplayList::new()); let child_lists = RefCell::new(child_lists); + let container_block_size = match self.class() { + BlockFlowClass => { + if self.as_block().box_.is_some() { + self.as_block().box_.get_ref().position.get().size + } else { + base(self).position.size + } + }, + _ => { + base(self).position.size + } + }; + for kid in child_iter(self) { - kid.build_display_lists(builder, dirty, 0u, &child_lists); + kid.build_display_lists(builder, &container_block_size, dirty, 0u, &child_lists); } let mut child_lists = Some(child_lists.unwrap()); diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 1a29866fe8f..7a15cb35dc3 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -494,6 +494,7 @@ impl InlineFlow { pub fn build_display_list_inline( &self, builder: &DisplayListBuilder, + container_block_size: &Size2D, dirty: &Rect, index: uint, lists: &RefCell>) @@ -510,7 +511,8 @@ impl InlineFlow { self.boxes.len()); for box_ in self.boxes.iter() { - box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists); + let rel_offset: Point2D = box_.relative_position(container_block_size); + box_.build_display_list(builder, dirty, self.base.abs_position + rel_offset, (&*self) as &Flow, index, lists); } // TODO(#225): Should `inline-block` elements have flows as children of the inline flow or diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index f5572208218..cc8eae3e3db 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -615,7 +615,7 @@ impl LayoutTask { let display_list_builder = DisplayListBuilder { ctx: &layout_ctx, }; - layout_root.build_display_lists(&display_list_builder, &dirty, 0u, display_list_collection); + layout_root.build_display_lists(&display_list_builder, &root_size, &dirty, 0u, display_list_collection); let display_list_collection = Arc::new(display_list_collection.unwrap()); diff --git a/src/test/ref/basic.list b/src/test/ref/basic.list index 74601f3fe0e..8f6d3fb4f68 100644 --- a/src/test/ref/basic.list +++ b/src/test/ref/basic.list @@ -26,3 +26,4 @@ == upper_id_attr.html upper_id_attr_ref.html # inline_border_a.html inline_border_b.html == anon_block_inherit_a.html anon_block_inherit_b.html +== position_relative_a.html position_relative_b.html diff --git a/src/test/ref/inline_border_a.html b/src/test/ref/inline_border_a.html index 71b02c225ce..e29ca5030fa 100644 --- a/src/test/ref/inline_border_a.html +++ b/src/test/ref/inline_border_a.html @@ -16,7 +16,7 @@ body { - + diff --git a/src/test/ref/position_relative_a.html b/src/test/ref/position_relative_a.html new file mode 100644 index 00000000000..c1b87cc0c04 --- /dev/null +++ b/src/test/ref/position_relative_a.html @@ -0,0 +1,17 @@ + + + + today, weather is very cold..... + + + + +
+
+ + diff --git a/src/test/ref/position_relative_b.html b/src/test/ref/position_relative_b.html new file mode 100644 index 00000000000..588ed733f85 --- /dev/null +++ b/src/test/ref/position_relative_b.html @@ -0,0 +1,18 @@ + + + + today, weather is very cold..... + + + + +
+ +
+ + diff --git a/src/test/ref/inline_border.jpeg b/src/test/ref/test.jpeg similarity index 100% rename from src/test/ref/inline_border.jpeg rename to src/test/ref/test.jpeg