layout: Make the display list freezable/dual mode

This commit is contained in:
Patrick Walton 2012-10-25 22:01:52 -07:00
parent 7c029a322d
commit b101f8258e
8 changed files with 58 additions and 43 deletions

View file

@ -82,22 +82,32 @@ impl DisplayItem {
}
}
pub type DisplayList = DVec<~DisplayItem>;
// Dual-mode/freezable.
pub struct DisplayList {
list: ~[~DisplayItem]
}
trait DisplayListMethods {
fn append_item(&mut self, item: ~DisplayItem);
fn draw_into_context(ctx: &RenderContext);
}
impl DisplayList {
static fn new() -> DisplayList {
DisplayList { list: ~[] }
}
}
impl DisplayList : DisplayListMethods {
fn append_item(item: ~DisplayItem) {
fn append_item(&mut self, item: ~DisplayItem) {
// FIXME(Issue #150): crashes
//debug!("Adding display item %u: %?", self.len(), item);
self.push(move item);
self.list.push(move item);
}
fn draw_into_context(ctx: &RenderContext) {
debug!("beginning display list");
for self.each |item| {
for self.list.each |item| {
// FIXME(Issue #150): crashes
//debug!("drawing %?", *item);
item.draw_into_context(ctx);

View file

@ -1,9 +1,9 @@
use au = gfx::geometry;
use css::values::*;
use dl = gfx::display_list;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::{DisplayList, DisplayListBuilder};
use gfx::geometry::Au;
use layout::box::{RenderBox};
use layout::context::LayoutContext;
@ -27,8 +27,8 @@ trait BlockLayout {
fn bubble_widths_block(@self, ctx: &LayoutContext);
fn assign_widths_block(@self, ctx: &LayoutContext);
fn assign_height_block(@self, ctx: &LayoutContext);
fn build_display_list_block(@self, a: &dl::DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &dl::DisplayList);
fn build_display_list_block(@self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &mut DisplayList);
}
impl FlowContext : BlockLayout {
@ -141,8 +141,8 @@ impl FlowContext : BlockLayout {
}
}
fn build_display_list_block(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) {
fn build_display_list_block(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) {
assert self.starts_block_flow();

View file

@ -9,14 +9,14 @@ use core::dvec::DVec;
use core::to_str::ToStr;
use core::rand;
use css::styles::SpecifiedStyle;
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent, BdrColor, PosAbsolute};
use dl = gfx::display_list;
use dl::DisplayItem;
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent};
use css::values::{BdrColor, PosAbsolute};
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use geom::rect::Rect;
use geom::size::Size2D;
use geom::point::Point2D;
use gfx::display_list::{DisplayItem, DisplayList, DisplayListBuilder};
use image::{Image, ImageHolder};
use layout::context::LayoutContext;
use layout::debug::BoxedDebugMethods;
@ -118,8 +118,8 @@ trait RenderBoxMethods {
fn get_pref_width(&LayoutContext) -> Au;
fn get_used_width() -> (Au, Au);
fn get_used_height() -> (Au, Au);
fn build_display_list(@self, &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, &dl::DisplayList);
fn build_display_list(@self, &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, dl: &mut DisplayList);
}
fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData {
@ -381,8 +381,8 @@ impl RenderBox : RenderBoxMethods {
* `origin` - Total offset from display list root flow to this box's owning flow
* `list` - List to which items should be appended
*/
fn build_display_list(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) {
fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) {
let style = self.d().node.style();
let box_bounds : Rect<Au> = match style.position {
@ -441,7 +441,7 @@ impl RenderBox : RenderBoxMethods {
self.add_border_to_list(list, &abs_box_bounds);
}
fn add_bgcolor_to_list(list: &dl::DisplayList, abs_bounds: &Rect<Au>) {
fn add_bgcolor_to_list(list: &mut DisplayList, abs_bounds: &Rect<Au>) {
use std::cmp::FuzzyEq;
// TODO: shouldn't need to unbox CSSValue by now
let boxed_bgcolor = self.d().node.style().background_color;
@ -454,7 +454,7 @@ impl RenderBox : RenderBoxMethods {
}
}
fn add_border_to_list(list: &dl::DisplayList, abs_bounds: &Rect<Au>) {
fn add_border_to_list(list: &mut DisplayList, abs_bounds: &Rect<Au>) {
let style = self.d().node.style();
match style.border_width {
Specified(Px(px)) => {
@ -474,7 +474,8 @@ impl RenderBox : RenderBoxMethods {
Specified(BdrColor(color)) => color,
_ => rgb(0, 0, 0) // FIXME
};
list.push(~DisplayItem::new_Border(&abs_bounds, border_width, color.red, color.green, color.blue));
list.append_item(~DisplayItem::new_Border(&abs_bounds, border_width, color.red,
color.green, color.blue));
}
_ => () // TODO
}

View file

@ -3,7 +3,6 @@ export DisplayListBuilder;
use au = gfx::geometry;
use au::Au;
use css::values::{BgColor, BgColorTransparent, Specified};
use dl = gfx::display_list;
use dom::node::{Text, NodeScope};
use dom::cow::Scope;
use dvec::DVec;
@ -11,6 +10,7 @@ use either::{Left, Right};
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::DisplayList;
use layout::box::{RenderBox, TextBox};
use layout::context::LayoutContext;
use layout::flow::FlowContext;
@ -32,21 +32,24 @@ pub struct DisplayListBuilder {
trait FlowDisplayListBuilderMethods {
fn build_display_list(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &dl::DisplayList);
fn build_display_list(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &mut DisplayList);
fn build_display_list_for_child(@self, a: &DisplayListBuilder, b: @FlowContext,
c: &Rect<Au>, d: &Point2D<Au>, e: &dl::DisplayList);
c: &Rect<Au>, d: &Point2D<Au>, e: &mut DisplayList);
}
impl FlowContext: FlowDisplayListBuilderMethods {
fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, list: &dl::DisplayList) {
fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
list: &mut DisplayList) {
let zero = au::zero_point();
self.build_display_list_recurse(builder, dirty, &zero, list);
}
fn build_display_list_for_child(@self, builder: &DisplayListBuilder, child_flow: @FlowContext,
fn build_display_list_for_child(@self,
builder: &DisplayListBuilder,
child_flow: @FlowContext,
dirty: &Rect<Au>, offset: &Point2D<Au>,
list: &dl::DisplayList) {
list: &mut DisplayList) {
// adjust the dirty rect to child flow context coordinates
let abs_flow_bounds = child_flow.d().position.translate(offset);

View file

@ -1,10 +1,10 @@
use au = gfx::geometry;
use au::Au;
use core::dvec::DVec;
use dl = gfx::display_list;
use dom::node::Node;
use geom::rect::Rect;
use geom::point::Point2D;
use gfx::display_list::{DisplayList, DisplayListBuilder};
// TODO: pub-use these
use layout::block::BlockFlowData;
use layout::box::RenderBox;
@ -72,8 +72,8 @@ trait FlowContextMethods {
fn bubble_widths(@self, &LayoutContext);
fn assign_widths(@self, &LayoutContext);
fn assign_height(@self, &LayoutContext);
fn build_display_list_recurse(@self, &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, &dl::DisplayList);
fn build_display_list_recurse(@self, &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, &mut DisplayList);
pure fn foldl_boxes_for_node<B: Copy>(Node, +seed: B, cb: pure fn&(+a: B,@RenderBox) -> B) -> B;
pure fn iter_boxes_for_node<T>(Node, cb: pure fn&(@RenderBox) -> T);
}
@ -168,8 +168,8 @@ impl FlowContext : FlowContextMethods {
}
}
fn build_display_list_recurse(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) {
fn build_display_list_recurse(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) {
debug!("FlowContext::build_display_list at %?: %s", self.d().position, self.debug_str());
match self {

View file

@ -2,11 +2,11 @@ use au = gfx::geometry;
use core::dlist::DList;
use core::dvec::DVec;
use css::values::{BoxAuto, BoxLength, Px};
use dl = gfx::display_list;
use dom::node::Node;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::{DisplayList, DisplayListBuilder};
use gfx::geometry::Au;
use layout::box::*;
use layout::context::LayoutContext;
@ -538,7 +538,8 @@ trait InlineLayout {
fn bubble_widths_inline(@self, ctx: &LayoutContext);
fn assign_widths_inline(@self, ctx: &LayoutContext);
fn assign_height_inline(@self, ctx: &LayoutContext);
fn build_display_list_inline(@self, a: &dl::DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>, d: &dl::DisplayList);
fn build_display_list_inline(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>,
d: &mut DisplayList);
}
impl FlowContext : InlineLayout {
@ -648,8 +649,8 @@ impl FlowContext : InlineLayout {
self.d().position.size.height = cur_y;
}
fn build_display_list_inline(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) {
fn build_display_list_inline(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) {
assert self.starts_inline_flow();

View file

@ -15,6 +15,7 @@ use dom::node::{Node, LayoutData};
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::DisplayList;
use gfx::render_task;
use gfx::render_layers::RenderLayer;
use layout::box::RenderBox;
@ -179,12 +180,11 @@ impl Layout {
}
do time("layout: display list building") {
let dlist = DVec();
let builder = dl::DisplayListBuilder {
ctx: &layout_ctx,
};
let render_layer = RenderLayer {
display_list: move dlist,
let mut render_layer = RenderLayer {
display_list: DisplayList::new(),
size: Size2D(au::to_px(screen_size.width) as uint,
au::to_px(screen_size.height) as uint)
};
@ -192,7 +192,7 @@ impl Layout {
// TODO: set options on the builder before building
// TODO: be smarter about what needs painting
layout_root.build_display_list(&builder, &copy layout_root.d().position,
&render_layer.display_list);
&mut render_layer.display_list);
self.render_task.send(render_task::RenderMsg(move render_layer));
} // time(layout: display list building)

View file

@ -1,8 +1,8 @@
use au = gfx::geometry;
use css::values::*;
use dl = gfx::display_list;
use geom::point::Point2D;
use geom::rect::Rect;
use gfx::display_list::{DisplayList, DisplayListBuilder};
use gfx::geometry::Au;
use layout::box::RenderBox;
use layout::context::LayoutContext;
@ -25,8 +25,8 @@ trait RootLayout {
fn bubble_widths_root(@self, ctx: &LayoutContext);
fn assign_widths_root(@self, ctx: &LayoutContext);
fn assign_height_root(@self, ctx: &LayoutContext);
fn build_display_list_root(@self, a: &dl::DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &dl::DisplayList);
fn build_display_list_root(@self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &mut DisplayList);
}
impl FlowContext : RootLayout {
@ -57,8 +57,8 @@ impl FlowContext : RootLayout {
self.assign_height_block(ctx);
}
fn build_display_list_root(@self, builder: &dl::DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &dl::DisplayList) {
fn build_display_list_root(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) {
assert self.starts_root_flow();
self.build_display_list_block(builder, dirty, offset, list);