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::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow, FloatFlow};
use layout::inline::InlineLayout;
use layout::model::{MaybeAuto, Specified, Auto};
@ -327,11 +326,17 @@ impl BlockFlowData {
pub fn build_display_list_block<E:ExtraDisplayListData>(@mut self,
builder: &DisplayListBuilder,
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
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
let flow = BlockFlow(self);
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::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 newcss;
use servo_util::tree::TreeNodeRef;
/// 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).
@ -49,54 +42,6 @@ pub struct DisplayListBuilder<'self> {
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
//

View file

@ -5,7 +5,6 @@
use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
use layout::flow::{FloatFlow, FlowData};
use layout::model::{MaybeAuto};
use layout::float_context::{FloatContext, PlacementInfo, FloatType};
@ -226,20 +225,33 @@ impl FloatFlowData {
pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self,
builder: &DisplayListBuilder,
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| {
box.build_display_list(builder, dirty, &offset, list)
});
// TODO: handle any out-of-flow elements
// go deeper into the flow tree
let flow = FloatFlow(self);
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()
}
}
/// 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 {
@ -162,6 +175,7 @@ pub struct FlowData {
floats_in: FloatContext,
floats_out: FloatContext,
num_floats: uint,
abs_position: Point2D<Au>
}
impl TreeNode<FlowContext> for FlowData {
@ -225,6 +239,7 @@ impl FlowData {
floats_in: Invalid,
floats_out: Invalid,
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,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
offset: &Point2D<Au>,
list: &Cell<DisplayList<E>>) {
do self.with_base |info| {
debug!("FlowContext::build_display_list at %?: %s", info.position, self.debug_str());
pub fn build_display_list<E:ExtraDisplayListData>(&self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &Cell<DisplayList<E>>)
-> bool {
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

View file

@ -745,8 +745,14 @@ impl InlineFlowData {
pub fn build_display_list_inline<E:ExtraDisplayListData>(&self,
builder: &DisplayListBuilder,
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
// not recurse on a line if nothing in it can intersect the dirty region.
debug!("FlowContext[%d]: building display list for %u inline boxes",
@ -754,11 +760,12 @@ impl InlineFlowData {
self.boxes.len());
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
// 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_builder::LayoutTreeBuilder;
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::display_list_builder::{DisplayListBuilder};
use layout::flow::FlowContext;
use std::cast::transmute;
@ -241,7 +241,9 @@ impl LayoutTask {
// TODO: Set options on the builder before building.
// 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| {
base.position.size