auto merge of #589 : eric93/servo/diplaylist-refactor, r=pcwalton

This commit is contained in:
bors-servo 2013-07-15 18:03:27 -07:00
commit 45e6873f80
6 changed files with 74 additions and 83 deletions

View file

@ -7,7 +7,6 @@
use layout::box::{RenderBox}; use layout::box::{RenderBox};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow, FloatFlow}; use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow, FloatFlow};
use layout::inline::InlineLayout; use layout::inline::InlineLayout;
use layout::model::{MaybeAuto, Specified, Auto}; use layout::model::{MaybeAuto, Specified, Auto};
@ -327,11 +326,17 @@ impl BlockFlowData {
pub fn build_display_list_block<E:ExtraDisplayListData>(@mut self, pub fn build_display_list_block<E:ExtraDisplayListData>(@mut self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Cell<DisplayList<E>>)
list: &Cell<DisplayList<E>>) { -> bool {
let abs_rect = Rect(self.common.abs_position, self.common.position.size);
if !abs_rect.intersects(dirty) {
return false;
}
// add box that starts block context // add box that starts block context
self.box.map(|&box| { self.box.map(|&box| {
box.build_display_list(builder, dirty, offset, list) box.build_display_list(builder, dirty, &self.common.abs_position, list)
}); });
@ -340,8 +345,12 @@ impl BlockFlowData {
// go deeper into the flow tree // go deeper into the flow tree
let flow = BlockFlow(self); let flow = BlockFlow(self);
for flow.each_child |child| { for flow.each_child |child| {
flow.build_display_list_for_child(builder, child, dirty, offset, list) do child.with_mut_base |base| {
base.abs_position = self.common.abs_position + base.position.origin;
}
} }
true
} }
} }

View file

@ -6,16 +6,9 @@
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::flow::FlowContext;
use std::cell::Cell;
use geom::point::Point2D;
use geom::rect::Rect;
use gfx::display_list::DisplayList;
use gfx::geometry::Au;
use gfx; use gfx;
use newcss; use newcss;
use servo_util::tree::TreeNodeRef;
/// Extra display list data is either nothing (if the display list is to be rendered) or the /// Extra display list data is either nothing (if the display list is to be rendered) or the
/// originating render box (if the display list is generated for hit testing). /// originating render box (if the display list is generated for hit testing).
@ -49,54 +42,6 @@ pub struct DisplayListBuilder<'self> {
ctx: &'self LayoutContext, ctx: &'self LayoutContext,
} }
pub trait FlowDisplayListBuilderMethods {
fn build_display_list<E:ExtraDisplayListData>(&self,
a: &DisplayListBuilder,
b: &Rect<Au>,
c: &Cell<DisplayList<E>>);
fn build_display_list_for_child<E:ExtraDisplayListData>(&self,
a: &DisplayListBuilder,
b: FlowContext,
c: &Rect<Au>,
d: &Point2D<Au>,
e: &Cell<DisplayList<E>>);
}
impl FlowDisplayListBuilderMethods for FlowContext {
fn build_display_list<E:ExtraDisplayListData>(&self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &Cell<DisplayList<E>>) {
let zero = gfx::geometry::zero_point();
self.build_display_list_recurse(builder, dirty, &zero, list);
}
fn build_display_list_for_child<E:ExtraDisplayListData>(&self,
builder: &DisplayListBuilder,
child_flow: FlowContext,
dirty: &Rect<Au>,
offset: &Point2D<Au>,
list: &Cell<DisplayList<E>>) {
// Adjust the dirty rect to child flow context coordinates.
do child_flow.with_base |child_node| {
let abs_flow_bounds = child_node.position.translate(offset);
let adj_offset = offset.add(&child_node.position.origin);
debug!("build_display_list_for_child: rel=%?, abs=%?",
child_node.position,
abs_flow_bounds);
debug!("build_display_list_for_child: dirty=%?, offset=%?", dirty, offset);
if dirty.intersects(&abs_flow_bounds) {
debug!("build_display_list_for_child: intersected. recursing into child flow...");
child_flow.build_display_list_recurse(builder, dirty, &adj_offset, list);
} else {
debug!("build_display_list_for_child: Did not intersect...");
}
}
}
}
// //
// Miscellaneous useful routines // Miscellaneous useful routines
// //

View file

@ -5,7 +5,6 @@
use layout::box::{RenderBox}; use layout::box::{RenderBox};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
use layout::flow::{FloatFlow, FlowData}; use layout::flow::{FloatFlow, FlowData};
use layout::model::{MaybeAuto}; use layout::model::{MaybeAuto};
use layout::float_context::{FloatContext, PlacementInfo, FloatType}; use layout::float_context::{FloatContext, PlacementInfo, FloatType};
@ -226,20 +225,33 @@ impl FloatFlowData {
pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self, pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Cell<DisplayList<E>>)
list: &Cell<DisplayList<E>>) { -> bool {
let offset = *offset + self.rel_pos; let abs_rect = Rect(self.common.abs_position, self.common.position.size);
if !abs_rect.intersects(dirty) {
return false;
}
let offset = self.common.abs_position + self.rel_pos;
// add box that starts block context
self.box.map(|&box| { self.box.map(|&box| {
box.build_display_list(builder, dirty, &offset, list) box.build_display_list(builder, dirty, &offset, list)
}); });
// TODO: handle any out-of-flow elements
// go deeper into the flow tree // go deeper into the flow tree
let flow = FloatFlow(self); let flow = FloatFlow(self);
for flow.each_child |child| { for flow.each_child |child| {
flow.build_display_list_for_child(builder, child, dirty, &offset, list) do child.with_mut_base |base| {
base.abs_position = offset;
}
} }
true
} }
} }

View file

@ -80,6 +80,19 @@ impl FlowContext {
InlineFlow(data) => data.teardown() InlineFlow(data) => data.teardown()
} }
} }
/// Like traverse_preorder, but don't end the whole traversal if the callback
/// returns false.
fn partially_traverse_preorder(&self, callback: &fn(FlowContext) -> bool) {
if !callback((*self).clone()) {
return;
}
for self.each_child |kid| {
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
kid.partially_traverse_preorder(|a| callback(a));
}
}
} }
impl FlowData { impl FlowData {
@ -162,6 +175,7 @@ pub struct FlowData {
floats_in: FloatContext, floats_in: FloatContext,
floats_out: FloatContext, floats_out: FloatContext,
num_floats: uint, num_floats: uint,
abs_position: Point2D<Au>
} }
impl TreeNode<FlowContext> for FlowData { impl TreeNode<FlowContext> for FlowData {
@ -225,6 +239,7 @@ impl FlowData {
floats_in: Invalid, floats_in: Invalid,
floats_out: Invalid, floats_out: Invalid,
num_floats: 0, num_floats: 0,
abs_position: Point2D(Au(0), Au(0))
} }
} }
} }
@ -296,21 +311,22 @@ impl<'self> FlowContext {
} }
} }
pub fn build_display_list_recurse<E:ExtraDisplayListData>(&self, pub fn build_display_list<E:ExtraDisplayListData>(&self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Cell<DisplayList<E>>)
list: &Cell<DisplayList<E>>) { -> bool {
do self.with_base |info| {
debug!("FlowContext::build_display_list at %?: %s", info.position, self.debug_str());
match *self {
BlockFlow(info) => info.build_display_list_block(builder, dirty, list),
InlineFlow(info) => info.build_display_list_inline(builder, dirty, list),
FloatFlow(info) => info.build_display_list_float(builder, dirty, list),
_ => {
fail!("Tried to build_display_list_recurse of flow: %?", self)
}
} }
match *self {
BlockFlow(info) => info.build_display_list_block(builder, dirty, offset, list),
InlineFlow(info) => info.build_display_list_inline(builder, dirty, offset, list),
FloatFlow(info) => info.build_display_list_float(builder, dirty, offset, list),
_ => fail!(fmt!("Tried to build_display_list_recurse of flow: %?", self))
}
} }
// Actual methods that do not require much flow-specific logic // Actual methods that do not require much flow-specific logic

View file

@ -745,8 +745,14 @@ impl InlineFlowData {
pub fn build_display_list_inline<E:ExtraDisplayListData>(&self, pub fn build_display_list_inline<E:ExtraDisplayListData>(&self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Cell<DisplayList<E>>)
list: &Cell<DisplayList<E>>) { -> bool {
let abs_rect = Rect(self.common.abs_position, self.common.position.size);
if !abs_rect.intersects(dirty) {
return false;
}
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and // TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
// not recurse on a line if nothing in it can intersect the dirty region. // not recurse on a line if nothing in it can intersect the dirty region.
debug!("FlowContext[%d]: building display list for %u inline boxes", debug!("FlowContext[%d]: building display list for %u inline boxes",
@ -754,11 +760,12 @@ impl InlineFlowData {
self.boxes.len()); self.boxes.len());
for self.boxes.iter().advance |box| { for self.boxes.iter().advance |box| {
box.build_display_list(builder, dirty, offset, list) box.build_display_list(builder, dirty, &self.common.abs_position, list)
} }
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or // TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
// should the flow be nested inside the box somehow? // should the flow be nested inside the box somehow?
true
} }
} }

View file

@ -11,7 +11,7 @@ use layout::aux::{LayoutData, LayoutAuxMethods};
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::box_builder::LayoutTreeBuilder; use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods}; use layout::display_list_builder::{DisplayListBuilder};
use layout::flow::FlowContext; use layout::flow::FlowContext;
use std::cast::transmute; use std::cast::transmute;
@ -241,7 +241,9 @@ impl LayoutTask {
// TODO: Set options on the builder before building. // TODO: Set options on the builder before building.
// TODO: Be smarter about what needs painting. // TODO: Be smarter about what needs painting.
layout_root.build_display_list(&builder, &layout_root.position(), display_list); for layout_root.traverse_preorder |flow| {
flow.build_display_list(&builder, &layout_root.position(), display_list);
}
let root_size = do layout_root.with_base |base| { let root_size = do layout_root.with_base |base| {
base.position.size base.position.size