Skip to content

Commit

Permalink
implement position:relative
Browse files Browse the repository at this point in the history
  • Loading branch information
ksh8281 committed Feb 5, 2014
1 parent 35a869d commit a90c2e3
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 13 deletions.
39 changes: 33 additions & 6 deletions src/components/main/layout/block.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -533,12 +533,13 @@ impl BlockFlow {
pub fn build_display_list_block<E:ExtraDisplayListData>(
&mut self,
builder: &DisplayListBuilder,
container_block_size: &Size2D<Au>,
dirty: &Rect<Au>,
mut index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> 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;
}

Expand All @@ -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
Expand All @@ -574,6 +587,7 @@ impl BlockFlow {
pub fn build_display_list_float<E:ExtraDisplayListData>(
&mut self,
builder: &DisplayListBuilder,
container_block_size: &Size2D<Au>,
dirty: &Rect<Au>,
index: uint,
lists: &RefCell<DisplayListCollection<E>>)
Expand All @@ -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);
Expand All @@ -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
Expand Down
55 changes: 54 additions & 1 deletion src/components/main/layout/box_.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -651,6 +651,59 @@ impl Box {
&None => {}
}
}
pub fn relative_position(&self, container_block_size: &Size2D<Au>) -> Point2D<Au> {
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<Au> = 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?
Expand Down
22 changes: 19 additions & 3 deletions src/components/main/layout/flow.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -207,6 +208,7 @@ pub trait MutableFlowUtils {
fn build_display_lists<E:ExtraDisplayListData>(
self,
builder: &DisplayListBuilder,
container_block_size: &Size2D<Au>,
dirty: &Rect<Au>,
index: uint,
mut list: &RefCell<DisplayListCollection<E>>)
Expand Down Expand Up @@ -726,14 +728,15 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
fn build_display_lists<E:ExtraDisplayListData>(
self,
builder: &DisplayListBuilder,
container_block_size: &Size2D<Au>,
dirty: &Rect<Au>,
mut index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> 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) {
Expand All @@ -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());
Expand Down
4 changes: 3 additions & 1 deletion src/components/main/layout/inline.rs
Expand Up @@ -494,6 +494,7 @@ impl InlineFlow {
pub fn build_display_list_inline<E:ExtraDisplayListData>(
&self,
builder: &DisplayListBuilder,
container_block_size: &Size2D<Au>,
dirty: &Rect<Au>,
index: uint,
lists: &RefCell<DisplayListCollection<E>>)
Expand All @@ -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<Au> = 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
Expand Down
2 changes: 1 addition & 1 deletion src/components/main/layout/layout_task.rs
Expand Up @@ -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());

Expand Down
1 change: 1 addition & 0 deletions src/test/ref/basic.list
Expand Up @@ -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
2 changes: 1 addition & 1 deletion src/test/ref/inline_border_a.html
Expand Up @@ -16,7 +16,7 @@
</style>
</head>
<body>
<span style="border: 10px black solid"><img width="100" style="border:10px red solid" src="inline_border.jpeg"></span>
<span style="border: 10px black solid"><img width="100" style="border:10px red solid" src="test.jpeg"></span>
</body>
</html>

17 changes: 17 additions & 0 deletions src/test/ref/position_relative_a.html
@@ -0,0 +1,17 @@
<html>
<head>
<title>
today, weather is very cold.....
</title>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div style="width:500px;height:200px;position:relative;left:100px;top:100px" >
<img src="test.jpeg" style="width:100px;height:100px;"/><span style="position:relative;left:-200px;top:-100px"><img src="test.jpeg" style="position:relative;left:100px;top:100px;width:100px;height:100px"/></span></div>
</body>
</html>
18 changes: 18 additions & 0 deletions src/test/ref/position_relative_b.html
@@ -0,0 +1,18 @@
<html>
<head>
<title>
today, weather is very cold.....
</title>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div style="width:500px;height:200px;margin-left:100px;margin-top:100px" >
<img src="test.jpeg" style="width:100px;height:100px;"/>
</div>
</body>
</html>
File renamed without changes

5 comments on commit a90c2e3

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from larsbergstrom
at ksh8281@a90c2e3

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging ksh8281/servo/pos_rel = a90c2e3 into auto

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ksh8281/servo/pos_rel = a90c2e3 merged ok, testing candidate = 48e9b8f

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 48e9b8f

Please sign in to comment.