mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
implement position:relative
This commit is contained in:
parent
35a869d3d6
commit
a90c2e3a26
10 changed files with 147 additions and 13 deletions
|
@ -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<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;
|
||||
}
|
||||
|
||||
|
@ -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<E:ExtraDisplayListData>(
|
||||
&mut self,
|
||||
builder: &DisplayListBuilder,
|
||||
container_block_size: &Size2D<Au>,
|
||||
dirty: &Rect<Au>,
|
||||
index: uint,
|
||||
lists: &RefCell<DisplayListCollection<E>>)
|
||||
|
@ -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
|
||||
|
|
|
@ -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<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?
|
||||
|
|
|
@ -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<E:ExtraDisplayListData>(
|
||||
self,
|
||||
builder: &DisplayListBuilder,
|
||||
container_block_size: &Size2D<Au>,
|
||||
dirty: &Rect<Au>,
|
||||
index: uint,
|
||||
mut list: &RefCell<DisplayListCollection<E>>)
|
||||
|
@ -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) {
|
||||
|
@ -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());
|
||||
|
|
|
@ -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>>)
|
||||
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -16,7 +16,7 @@ body {
|
|||
</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
src/test/ref/position_relative_a.html
Normal file
17
src/test/ref/position_relative_a.html
Normal file
|
@ -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
src/test/ref/position_relative_b.html
Normal file
18
src/test/ref/position_relative_b.html
Normal file
|
@ -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>
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Loading…
Add table
Add a link
Reference in a new issue