Swap RenderBox and RenderBoxData, making RenderBox variants each hold

the common struct as first field. Add a d() accessor for the common
struct data. Other miscellaneous fixes.
This commit is contained in:
Brian J. Burg 2012-09-26 16:14:15 -07:00
parent b9b3895a8a
commit e89d2fa782
10 changed files with 195 additions and 149 deletions

View file

@ -65,11 +65,11 @@ impl Node : cmp::Eq {
impl Node : DebugMethods { impl Node : DebugMethods {
/* Dumps the subtree rooted at this node, for debugging. */ /* Dumps the subtree rooted at this node, for debugging. */
fn dump() { fn dump(&self) {
self.dump_indent(0u); self.dump_indent(0u);
} }
/* Dumps the node tree, for debugging, with indentation. */ /* Dumps the node tree, for debugging, with indentation. */
fn dump_indent(indent: uint) { fn dump_indent(&self, indent: uint) {
let mut s = ~""; let mut s = ~"";
for uint::range(0u, indent) |_i| { for uint::range(0u, indent) |_i| {
s += ~" "; s += ~" ";
@ -78,12 +78,12 @@ impl Node : DebugMethods {
s += self.debug_str(); s += self.debug_str();
debug!("%s", s); debug!("%s", s);
for NodeTree.each_child(self) |kid| { for NodeTree.each_child(*self) |kid| {
kid.dump_indent(indent + 1u) kid.dump_indent(indent + 1u)
} }
} }
fn debug_str() -> ~str { fn debug_str(&self) -> ~str {
do self.read |n| { fmt!("%?", n.kind) } do self.read |n| { fmt!("%?", n.kind) }
} }
} }

View file

@ -33,7 +33,7 @@ trait BlockLayout {
c: &Point2D<au>, d: &dl::DisplayList); c: &Point2D<au>, d: &dl::DisplayList);
} }
impl @FlowContext : BlockLayout { impl FlowContext : BlockLayout {
pure fn starts_block_flow() -> bool { pure fn starts_block_flow() -> bool {
match self.kind { match self.kind {
@ -85,7 +85,7 @@ impl @FlowContext : BlockLayout {
let mut pref_width = au(0); let mut pref_width = au(0);
/* find max width from child block contexts */ /* find max width from child block contexts */
for FlowTree.each_child(self) |child_ctx| { for FlowTree.each_child(@self) |child_ctx| {
assert child_ctx.starts_block_flow() || child_ctx.starts_inline_flow(); assert child_ctx.starts_block_flow() || child_ctx.starts_inline_flow();
min_width = au::max(min_width, child_ctx.data.min_width); min_width = au::max(min_width, child_ctx.data.min_width);
@ -120,12 +120,12 @@ impl @FlowContext : BlockLayout {
/* Let the box consume some width. It will return the amount remaining /* Let the box consume some width. It will return the amount remaining
for its children. */ for its children. */
do self.with_block_box |box| { do self.with_block_box |box| {
box.data.position.size.width = remaining_width; box.d().position.size.width = remaining_width;
let (left_used, right_used) = box.get_used_width(); let (left_used, right_used) = box.get_used_width();
remaining_width = remaining_width.sub(left_used.add(right_used)); remaining_width = remaining_width.sub(left_used.add(right_used));
} }
for FlowTree.each_child(self) |child_ctx| { for FlowTree.each_child(@self) |child_ctx| {
assert child_ctx.starts_block_flow() || child_ctx.starts_inline_flow(); assert child_ctx.starts_block_flow() || child_ctx.starts_inline_flow();
child_ctx.data.position.origin.x = left_used; child_ctx.data.position.origin.x = left_used;
child_ctx.data.position.size.width = remaining_width; child_ctx.data.position.size.width = remaining_width;
@ -137,7 +137,7 @@ impl @FlowContext : BlockLayout {
let mut cur_y = au(0); let mut cur_y = au(0);
for FlowTree.each_child(self) |child_ctx| { for FlowTree.each_child(@self) |child_ctx| {
child_ctx.data.position.origin.y = cur_y; child_ctx.data.position.origin.y = cur_y;
cur_y = cur_y.add(child_ctx.data.position.size.height); cur_y = cur_y.add(child_ctx.data.position.size.height);
} }
@ -148,8 +148,8 @@ impl @FlowContext : BlockLayout {
let _used_bot = au(0); let _used_bot = au(0);
do self.with_block_box |box| { do self.with_block_box |box| {
box.data.position.origin.y = au(0); box.d().position.origin.y = au(0);
box.data.position.size.height = cur_y; box.d().position.size.height = cur_y;
let (_used_top, _used_bot) = box.get_used_height(); let (_used_top, _used_bot) = box.get_used_height();
} }
} }
@ -167,7 +167,7 @@ impl @FlowContext : BlockLayout {
// TODO: handle any out-of-flow elements // TODO: handle any out-of-flow elements
// go deeper into the flow tree // go deeper into the flow tree
for FlowTree.each_child(self) |child| { for FlowTree.each_child(@self) |child| {
self.build_display_list_for_child(builder, child, dirty, offset, list) self.build_display_list_for_child(builder, child, dirty, offset, list)
} }
} }

View file

@ -18,7 +18,7 @@ use geom::size::Size2D;
use geom::point::Point2D; use geom::point::Point2D;
use image::{Image, ImageHolder}; use image::{Image, ImageHolder};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::DebugMethods; use layout::debug::BoxedDebugMethods;
use layout::flow::FlowContext; use layout::flow::FlowContext;
use layout::text::TextBoxData; use layout::text::TextBoxData;
use servo_text::text_run::TextRun; use servo_text::text_run::TextRun;
@ -68,27 +68,8 @@ padding, backgrounds. It is analogous to a CSS nonreplaced content box.
It also holds data specific to different box types, such as text. It also holds data specific to different box types, such as text.
*/ */
struct BoxLayoutData {
mut position: Rect<au>,
mut font_size: Length,
}
/* TODO: this should eventually be just 'position', and struct RenderBoxData {
merged into the base RenderBox struct */
fn BoxLayoutData() -> BoxLayoutData {
BoxLayoutData {
position : au::zero_rect(),
font_size : Px(0.0),
}
}
enum BoxData {
GenericBox,
ImageBox(ImageHolder),
TextBox(TextBoxData)
}
struct RenderBox {
/* references to children, parent inline flow boxes */ /* references to children, parent inline flow boxes */
tree : tree::Tree<@RenderBox>, tree : tree::Tree<@RenderBox>,
/* originating DOM node */ /* originating DOM node */
@ -96,30 +77,51 @@ struct RenderBox {
/* reference to containing flow context, which this box /* reference to containing flow context, which this box
participates in */ participates in */
ctx : @FlowContext, ctx : @FlowContext,
/* results of flow computation */ /* position of this box relative to owning flow */
data : BoxLayoutData, mut position : Rect<au>,
/* kind tag and kind-specific data */ font_size : Length,
kind : BoxData,
/* TODO (Issue #87): debug only */ /* TODO (Issue #87): debug only */
mut id: int mut id: int
} }
fn RenderBox(id: int, node: Node, ctx: @FlowContext, kind: BoxData) -> RenderBox { enum RenderBoxType {
RenderBox { RenderBox_Generic,
RenderBox_Image,
RenderBox_Text
}
enum RenderBox {
GenericBox(RenderBoxData),
ImageBox(RenderBoxData, ImageHolder),
TextBox(RenderBoxData, TextBoxData)
}
impl RenderBox {
pure fn d(&self) -> &self/RenderBoxData {
match *self {
GenericBox(ref d) => d,
ImageBox(ref d, _) => d,
TextBox(ref d, _) => d
}
}
}
fn RenderBoxData(node: Node, ctx: @FlowContext, id: int) -> RenderBoxData {
RenderBoxData {
/* will be set if box is parented */ /* will be set if box is parented */
tree : tree::empty(), tree : tree::empty(),
node : node, node : node,
ctx : ctx, mut ctx : ctx,
data : BoxLayoutData(), mut position : au::zero_rect(),
kind : kind, font_size: Px(0.0),
id : id id : id
} }
} }
impl @RenderBox { impl RenderBox {
pure fn is_replaced() -> bool { pure fn is_replaced() -> bool {
match self.kind { match self {
ImageBox(*) => true, // TODO: form elements, etc ImageBox(*) => true, // TODO: form elements, etc
_ => false _ => false
} }
} }
@ -129,35 +131,35 @@ impl @RenderBox {
* holder.get_image() * holder.get_image()
*/ */
fn get_min_width() -> au { fn get_min_width() -> au {
match self.kind { match self {
// TODO: this should account for min/pref widths of the // TODO: this should account for min/pref widths of the
// box element in isolation. That includes // box element in isolation. That includes
// border/margin/padding but not child widths. The block // border/margin/padding but not child widths. The block
// FlowContext will combine the width of this element and // FlowContext will combine the width of this element and
// that of its children to arrive at the context width. // that of its children to arrive at the context width.
GenericBox => au(0), GenericBox(*) => au(0),
// TODO: consult CSS 'width', margin, border. // TODO: consult CSS 'width', margin, border.
// TODO: If image isn't available, consult 'width'. // TODO: If image isn't available, consult 'width'.
ImageBox(i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width), ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
TextBox(d) => d.runs.foldl(au(0), |sum, run| { TextBox(_,d) => d.runs.foldl(au(0), |sum, run| {
au::max(sum, run.min_break_width()) au::max(sum, run.min_break_width())
}) })
} }
} }
fn get_pref_width() -> au { fn get_pref_width() -> au {
match self.kind { match self {
// TODO: this should account for min/pref widths of the // TODO: this should account for min/pref widths of the
// box element in isolation. That includes // box element in isolation. That includes
// border/margin/padding but not child widths. The block // border/margin/padding but not child widths. The block
// FlowContext will combine the width of this element and // FlowContext will combine the width of this element and
// that of its children to arrive at the context width. // that of its children to arrive at the context width.
GenericBox => au(0), GenericBox(*) => au(0),
ImageBox(i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width), ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
// TODO: account for line breaks, etc. The run should know // TODO: account for line breaks, etc. The run should know
// how to compute its own min and pref widths, and should // how to compute its own min and pref widths, and should
// probably cache them. // probably cache them.
TextBox(d) => d.runs.foldl(au(0), |sum, run| { TextBox(_,d) => d.runs.foldl(au(0), |sum, run| {
au::max(sum, run.size().width) au::max(sum, run.size().width)
}) })
} }
@ -184,21 +186,21 @@ impl @RenderBox {
/* The box formed by the content edge, as defined in CSS 2.1 Section 8.1. /* The box formed by the content edge, as defined in CSS 2.1 Section 8.1.
Coordinates are relative to the owning flow. */ Coordinates are relative to the owning flow. */
pure fn content_box() -> Rect<au> { pure fn content_box() -> Rect<au> {
match self.kind { match self {
ImageBox(i) => { ImageBox(_,i) => {
let size = i.size(); let size = i.size();
Rect { Rect {
origin: copy self.data.position.origin, origin: copy self.d().position.origin,
size: Size2D(au::from_px(size.width), size: Size2D(au::from_px(size.width),
au::from_px(size.height)) au::from_px(size.height))
} }
}, },
GenericBox(*) => { GenericBox(*) => {
copy self.data.position copy self.d().position
/* FIXME: The following hits an ICE for whatever reason /* FIXME: The following hits an ICE for whatever reason
let origin = self.data.position.origin; let origin = self.d().position.origin;
let size = self.data.position.size; let size = self.d().position.size;
let (offset_left, offset_right) = self.get_used_width(); let (offset_left, offset_right) = self.get_used_width();
let (offset_top, offset_bottom) = self.get_used_height(); let (offset_top, offset_bottom) = self.get_used_height();
@ -209,7 +211,7 @@ impl @RenderBox {
}*/ }*/
}, },
TextBox(*) => { TextBox(*) => {
copy self.data.position copy self.d().position
} }
} }
} }
@ -241,15 +243,15 @@ impl @RenderBox {
*/ */
fn build_display_list(_builder: &dl::DisplayListBuilder, dirty: &Rect<au>, fn build_display_list(_builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
offset: &Point2D<au>, list: &dl::DisplayList) { offset: &Point2D<au>, list: &dl::DisplayList) {
if !self.data.position.intersects(dirty) { if !self.d().position.intersects(dirty) {
return; return;
} }
let bounds : Rect<au> = Rect(self.data.position.origin.add(offset), let bounds : Rect<au> = Rect(self.d().position.origin.add(offset),
copy self.data.position.size); copy self.d().position.size);
match self.kind { match self {
TextBox(d) => { TextBox(_,d) => {
let mut runs = d.runs; let mut runs = d.runs;
// TODO: don't paint background for text boxes // TODO: don't paint background for text boxes
list.push(~dl::SolidColor(bounds, 255u8, 255u8, 255u8)); list.push(~dl::SolidColor(bounds, 255u8, 255u8, 255u8));
@ -271,13 +273,13 @@ impl @RenderBox {
}, },
// TODO: items for background, border, outline // TODO: items for background, border, outline
GenericBox(*) => { }, GenericBox(*) => { },
ImageBox(i) => { ImageBox(_,i) => {
match i.get_image() { match i.get_image() {
Some(image) => list.push(~dl::Image(bounds, image)), Some(image) => list.push(~dl::Image(bounds, image)),
/* No image data at all? Okay, add some fallback content instead. */ /* No image data at all? Okay, add some fallback content instead. */
None => { None => {
// TODO: shouldn't need to unbox CSSValue by now // TODO: shouldn't need to unbox CSSValue by now
let boxed_color = self.node.style().background_color; let boxed_color = self.d().node.style().background_color;
let color = match boxed_color { let color = match boxed_color {
Specified(BgColor(c)) => c, Specified(BgColor(c)) => c,
Specified(BgColorTransparent) | _ => util::color::rgba(0,0,0,0.0) Specified(BgColorTransparent) | _ => util::color::rgba(0,0,0,0.0)
@ -290,6 +292,10 @@ impl @RenderBox {
} }
} }
trait ImageBoxMethods {
}
/** /**
* The tree holding render box relations. These are only defined for * The tree holding render box relations. These are only defined for
* nested CSS boxes that are nested in an otherwise inline flow * nested CSS boxes that are nested in an otherwise inline flow
@ -303,7 +309,7 @@ impl RenderBoxTree : tree::ReadMethods<@RenderBox> {
} }
fn with_tree_fields<R>(&&b: @RenderBox, f: fn(tree::Tree<@RenderBox>) -> R) -> R { fn with_tree_fields<R>(&&b: @RenderBox, f: fn(tree::Tree<@RenderBox>) -> R) -> R {
f(b.tree) f(b.d().tree)
} }
} }
@ -314,17 +320,17 @@ impl RenderBoxTree : tree::WriteMethods<@RenderBox> {
} }
fn with_tree_fields<R>(&&b: @RenderBox, f: fn(tree::Tree<@RenderBox>) -> R) -> R { fn with_tree_fields<R>(&&b: @RenderBox, f: fn(tree::Tree<@RenderBox>) -> R) -> R {
f(b.tree) f(b.d().tree)
} }
} }
impl @RenderBox : DebugMethods { impl RenderBox : BoxedDebugMethods {
fn dump() { fn dump(@self) {
self.dump_indent(0u); self.dump_indent(0u);
} }
/* Dumps the node tree, for debugging, with indentation. */ /* Dumps the node tree, for debugging, with indentation. */
fn dump_indent(indent: uint) { fn dump_indent(@self, indent: uint) {
let mut s = ~""; let mut s = ~"";
for uint::range(0u, indent) |_i| { for uint::range(0u, indent) |_i| {
s += ~" "; s += ~" ";
@ -338,11 +344,11 @@ impl @RenderBox : DebugMethods {
} }
} }
fn debug_str() -> ~str { fn debug_str(@self) -> ~str {
let repr = match self.kind { let repr = match self {
GenericBox(*) => ~"GenericBox", @GenericBox(*) => ~"GenericBox",
ImageBox(*) => ~"ImageBox", @ImageBox(*) => ~"ImageBox",
TextBox(d) => { @TextBox(_,d) => {
let mut s = d.runs.foldl(~"TextBox(runs=", |s, run| { let mut s = d.runs.foldl(~"TextBox(runs=", |s, run| {
fmt!("%s \"%s\"", s, run.text) fmt!("%s \"%s\"", s, run.text)
}); });
@ -350,7 +356,7 @@ impl @RenderBox : DebugMethods {
} }
}; };
fmt!("box b%?: %?", self.id, repr) fmt!("box b%?: %?", self.d().id, repr)
} }
} }

View file

@ -8,7 +8,7 @@ use dom::element::*;
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData}; use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData};
use image::holder::ImageHolder; use image::holder::ImageHolder;
use layout::flow::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree}; use layout::flow::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
use layout::box::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree}; use layout::box::*;
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::inline::InlineFlowData; use layout::inline::InlineFlowData;
@ -58,21 +58,21 @@ impl LayoutTreeBuilder {
v => v v => v
}; };
// first, create the proper box kind, based on node characteristics // first, determine the box type, based on node characteristics
let box_data = self.create_box_data(layout_ctx, cur_node, simulated_display); let box_type = self.decide_box_type(cur_node, simulated_display);
// then, figure out its proper context, possibly reorganizing. // then, figure out its proper context, possibly reorganizing.
let next_ctx: @FlowContext = match box_data { let next_ctx: @FlowContext = match box_type {
/* Text box is always an inline flow. create implicit inline /* Text box is always an inline flow. create implicit inline
flow ctx if we aren't inside one already. */ flow ctx if we aren't inside one already. */
TextBox(*) => { RenderBox_Text => {
if (parent_ctx.starts_inline_flow()) { if (parent_ctx.starts_inline_flow()) {
parent_ctx parent_ctx
} else { } else {
self.make_ctx(InlineFlow(InlineFlowData()), tree::empty()) self.make_ctx(InlineFlow(InlineFlowData()), tree::empty())
} }
}, },
ImageBox(*) | GenericBox => { RenderBox_Image | RenderBox_Generic => {
match simulated_display { match simulated_display {
DisplayInline | DisplayInlineBlock => { DisplayInline | DisplayInlineBlock => {
/* if inline, try to put into inline context, /* if inline, try to put into inline context,
@ -98,7 +98,7 @@ impl LayoutTreeBuilder {
do cur_node.aux |data| { data.flow = Some(next_ctx) } do cur_node.aux |data| { data.flow = Some(next_ctx) }
// make box, add box to any context-specific list. // make box, add box to any context-specific list.
let mut new_box = self.make_box(cur_node, parent_ctx, box_data); let mut new_box = self.make_box(layout_ctx, box_type, cur_node, parent_ctx);
debug!("Assign ^box to flow: %?", next_ctx.debug_str()); debug!("Assign ^box to flow: %?", next_ctx.debug_str());
match next_ctx.kind { match next_ctx.kind {
@ -109,7 +109,7 @@ impl LayoutTreeBuilder {
let parent = parent_box.get(); let parent = parent_box.get();
// connect the box to its parent box // connect the box to its parent box
debug!("In inline flow f%?, set child b%? of parent b%?", next_ctx.id, parent.id, new_box.id); debug!("In inline flow f%?, set child b%? of parent b%?", next_ctx.id, parent.d().id, new_box.d().id);
RenderBoxTree.add_child(parent, new_box); RenderBoxTree.add_child(parent, new_box);
} }
} }
@ -118,7 +118,7 @@ impl LayoutTreeBuilder {
}; };
if (!next_ctx.eq(&parent_ctx)) { if !core::box::ptr_eq(next_ctx, parent_ctx) {
debug!("Adding child flow f%? of f%?", parent_ctx.id, next_ctx.id); debug!("Adding child flow f%? of f%?", parent_ctx.id, next_ctx.id);
FlowTree.add_child(parent_ctx, next_ctx); FlowTree.add_child(parent_ctx, next_ctx);
} }
@ -188,39 +188,79 @@ impl LayoutTreeBuilder {
ret ret
} }
fn make_box(node : Node, ctx: @FlowContext, data: BoxData) -> @RenderBox { /**
let ret = @RenderBox(self.next_box_id(), node, ctx, data); disambiguate between different methods here instead of inlining, since each
case has very different complexity
*/
fn make_box(layout_ctx: &LayoutContext, ty: RenderBoxType, node: Node, ctx: @FlowContext) -> @RenderBox {
let ret = match ty {
RenderBox_Generic => self.make_generic_box(layout_ctx, node, ctx),
RenderBox_Text => self.make_text_box(layout_ctx, node, ctx),
RenderBox_Image => self.make_image_box(layout_ctx, node, ctx),
};
debug!("Created box: %s", ret.debug_str()); debug!("Created box: %s", ret.debug_str());
ret ret
} }
/* Based on the DOM node type, create a specific type of box */ fn make_generic_box(_layout_ctx: &LayoutContext, node: Node, ctx: @FlowContext) -> @RenderBox {
fn create_box_data(layout_ctx: &LayoutContext, node: Node, display: CSSDisplay) -> BoxData { @GenericBox(RenderBoxData(node, ctx, self.next_box_id()))
// TODO: handle more types of nodes. }
fn make_image_box(layout_ctx: &LayoutContext, node: Node, ctx: @FlowContext) -> @RenderBox {
do node.read |n| {
match n.kind {
~Element(ed) => match ed.kind {
~HTMLImageElement(d) => {
// TODO: this could be written as a pattern guard, but it triggers
// an ICE (mozilla/rust issue #3601)
if d.image.is_some() {
let holder = ImageHolder(&d.image.get(),
layout_ctx.image_cache,
copy layout_ctx.reflow_cb);
@ImageBox(RenderBoxData(node, ctx, self.next_box_id()), holder)
} else {
info!("Tried to make image box, but couldn't find image. Made generic box instead.");
self.make_generic_box(layout_ctx, node, ctx)
}
},
_ => fail ~"WAT error: why couldn't we make an image box?"
},
_ => fail ~"WAT error: why couldn't we make an image box?"
}
}
}
fn make_text_box(layout_ctx: &LayoutContext, node: Node, ctx: @FlowContext) -> @RenderBox {
do node.read |n| { do node.read |n| {
match n.kind { match n.kind {
~Doctype(*) | ~Comment(*) => fail ~"Hey, doctypes and comments shouldn't get here! They are display:none!",
~Text(string) => { ~Text(string) => {
// TODO: clean this up. Fonts should not be created here. // TODO: clean this up. Fonts should not be created here.
let font = layout_ctx.font_cache.get_test_font(); let font = layout_ctx.font_cache.get_test_font();
let run = TextRun(font, string); let run = TextRun(font, string);
TextBox(TextBoxData(copy string, ~[move run])) @TextBox(RenderBoxData(node, ctx, self.next_box_id()),
} TextBoxData(copy string, ~[move run]))
},
_ => fail ~"WAT error: why couldn't we make a text box?"
}
}
}
fn decide_box_type(node: Node, display: CSSDisplay) -> RenderBoxType {
do node.read |n| {
match n.kind {
~Doctype(*) | ~Comment(*) => fail ~"Hey, doctypes and comments shouldn't get here! They are display:none!",
~Text(*) => RenderBox_Text,
~Element(element) => { ~Element(element) => {
match (element.kind, display) { match (element.kind, display) {
(~HTMLImageElement(d), _) if d.image.is_some() => { (~HTMLImageElement(d), _) if d.image.is_some() => RenderBox_Image,
let holder = ImageHolder(&d.image.get(),
layout_ctx.image_cache,
copy layout_ctx.reflow_cb);
ImageBox(holder)
},
// (_, Specified(_)) => GenericBox, // (_, Specified(_)) => GenericBox,
(_, _) => GenericBox // TODO: replace this with the commented lines (_, _) => RenderBox_Generic // TODO: replace this with the commented lines
// (_, _) => fail ~"Can't create box for Node with non-specified 'display' type" // (_, _) => fail ~"Can't create box for Node with non-specified 'display' type"
} }
} }
} }
} }
} }
} }

View file

@ -1,5 +1,11 @@
trait DebugMethods { trait BoxedDebugMethods {
fn dump(); fn dump(@self);
fn dump_indent(ident: uint); fn dump_indent(@self, ident: uint);
fn debug_str() -> ~str; fn debug_str(@self) -> ~str;
}
trait DebugMethods {
fn dump(&self);
fn dump_indent(&self, ident: uint);
fn debug_str(&self) -> ~str;
} }

View file

@ -38,7 +38,7 @@ trait FlowDisplayListBuilderMethods {
c: &Rect<au>, d: &Point2D<au>, e: &dl::DisplayList); c: &Rect<au>, d: &Point2D<au>, e: &dl::DisplayList);
} }
impl @FlowContext: FlowDisplayListBuilderMethods { impl FlowContext: FlowDisplayListBuilderMethods {
fn build_display_list(builder: &DisplayListBuilder, dirty: &Rect<au>, list: &dl::DisplayList) { fn build_display_list(builder: &DisplayListBuilder, dirty: &Rect<au>, list: &dl::DisplayList) {
let zero = au::zero_point(); let zero = au::zero_point();

View file

@ -8,7 +8,7 @@ use geom::point::Point2D;
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::DebugMethods; use layout::debug::BoxedDebugMethods;
use layout::inline::InlineFlowData; use layout::inline::InlineFlowData;
use layout::root::RootFlowData; use layout::root::RootFlowData;
use util::tree; use util::tree;
@ -92,14 +92,8 @@ fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -
} }
} }
impl @FlowContext : cmp::Eq {
pure fn eq(other: &@FlowContext) -> bool { core::box::ptr_eq(self, *other) }
pure fn ne(other: &@FlowContext) -> bool { !core::box::ptr_eq(self, *other) }
}
/* Flow context disambiguation methods: the verbose alternative to virtual methods */ /* Flow context disambiguation methods: the verbose alternative to virtual methods */
impl @FlowContext { impl FlowContext {
fn bubble_widths(ctx: &LayoutContext) { fn bubble_widths(ctx: &LayoutContext) {
match self.kind { match self.kind {
BlockFlow(*) => self.bubble_widths_block(ctx), BlockFlow(*) => self.bubble_widths_block(ctx),
@ -139,19 +133,19 @@ impl @FlowContext {
} }
// Actual methods that do not require much flow-specific logic // Actual methods that do not require much flow-specific logic
impl @FlowContext { impl FlowContext {
pure fn foldl_boxes_for_node<B: Copy>(node: Node, seed: B, blk: pure fn&(B,@RenderBox) -> B) -> B { pure fn foldl_boxes_for_node<B: Copy>(node: Node, seed: B, blk: pure fn&(B,@RenderBox) -> B) -> B {
match self.kind { match self.kind {
RootFlow(d) => match d.box { RootFlow(d) => match d.box {
Some(box) if box.node == node => { blk(seed, box) }, Some(box) if box.d().node == node => { blk(seed, box) },
_ => seed _ => seed
}, },
BlockFlow(d) => match d.box { BlockFlow(d) => match d.box {
Some(box) if box.node == node => { blk(seed, box) }, Some(box) if box.d().node == node => { blk(seed, box) },
_ => seed _ => seed
}, },
InlineFlow(d) => do d.boxes.foldl(seed) |acc, box| { InlineFlow(d) => do d.boxes.foldl(seed) |acc, box| {
if box.node == node { blk(acc, box) } if box.d().node == node { blk(acc, box) }
else { acc } else { acc }
}, },
_ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self.kind) _ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self.kind)
@ -161,16 +155,16 @@ impl @FlowContext {
pure fn iter_boxes_for_node<T>(node: Node, cb: pure fn&(@RenderBox) -> T) { pure fn iter_boxes_for_node<T>(node: Node, cb: pure fn&(@RenderBox) -> T) {
match self.kind { match self.kind {
RootFlow(d) => match d.box { RootFlow(d) => match d.box {
Some(box) if box.node == node => { cb(box); }, Some(box) if box.d().node == node => { cb(box); },
_ => {} _ => {}
}, },
BlockFlow(d) => match d.box { BlockFlow(d) => match d.box {
Some(box) if box.node == node => { cb(box); }, Some(box) if box.d().node == node => { cb(box); },
_ => {} _ => {}
}, },
InlineFlow(d) => { InlineFlow(d) => {
for d.boxes.each |box| { for d.boxes.each |box| {
if box.node == node { cb(*box); } if box.d().node == node { cb(*box); }
} }
}, },
_ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self.kind) _ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self.kind)
@ -204,13 +198,13 @@ impl FlowTree : tree::WriteMethods<@FlowContext> {
} }
impl @FlowContext : DebugMethods { impl FlowContext : BoxedDebugMethods {
fn dump() { fn dump(@self) {
self.dump_indent(0u); self.dump_indent(0u);
} }
/** Dumps the flow tree, for debugging, with indentation. */ /** Dumps the flow tree, for debugging, with indentation. */
fn dump_indent(indent: uint) { fn dump_indent(@self, indent: uint) {
let mut s = ~"|"; let mut s = ~"|";
for uint::range(0u, indent) |_i| { for uint::range(0u, indent) |_i| {
s += ~"---- "; s += ~"---- ";
@ -225,17 +219,17 @@ impl @FlowContext : DebugMethods {
} }
/* TODO: we need a string builder. This is horribly inefficient */ /* TODO: we need a string builder. This is horribly inefficient */
fn debug_str() -> ~str { fn debug_str(@self) -> ~str {
let repr = match self.kind { let repr = match self.kind {
InlineFlow(d) => { InlineFlow(d) => {
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| { let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
fmt!("%s %?", s, box.id) fmt!("%s %?", s, box.d().id)
}); });
s += ~")"; s s += ~")"; s
}, },
BlockFlow(d) => { BlockFlow(d) => {
match d.box { match d.box {
Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().id), Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().d().id),
None => ~"BlockFlow", None => ~"BlockFlow",
} }
}, },

View file

@ -57,7 +57,7 @@ trait InlineLayout {
fn build_display_list_inline(a: &dl::DisplayListBuilder, b: &Rect<au>, c: &Point2D<au>, d: &dl::DisplayList); fn build_display_list_inline(a: &dl::DisplayListBuilder, b: &Rect<au>, c: &Point2D<au>, d: &dl::DisplayList);
} }
impl @FlowContext : InlineLayout { impl FlowContext : InlineLayout {
pure fn starts_inline_flow() -> bool { match self.kind { InlineFlow(*) => true, _ => false } } pure fn starts_inline_flow() -> bool { match self.kind { InlineFlow(*) => true, _ => false } }
pure fn access_inline<T>(cb: fn(&&InlineFlowData) -> T) -> T { pure fn access_inline<T>(cb: fn(&&InlineFlowData) -> T) -> T {
@ -110,27 +110,27 @@ impl @FlowContext : InlineLayout {
/* hack: until text box splitting is hoisted into this /* hack: until text box splitting is hoisted into this
function, force "reflow" on TextBoxes. */ function, force "reflow" on TextBoxes. */
match box.kind { match *box {
TextBox(*) => box.reflow_text(ctx), @TextBox(*) => box.reflow_text(ctx),
_ => {} _ => {}
} }
box.data.position.size.width = match box.kind { box.d().position.size.width = match *box {
ImageBox(img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width), @ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width),
TextBox(d) => d.runs[0].size().width, @TextBox(_,d) => d.runs[0].size().width,
// TODO: this should be set to the extents of its children // TODO: this should be set to the extents of its children
GenericBox(*) => au(0) @GenericBox(*) => au(0)
}; };
box.data.position.size.height = match box.kind { box.d().position.size.height = match *box {
ImageBox(img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height), @ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height),
TextBox(d) => d.runs[0].size().height, @TextBox(_,d) => d.runs[0].size().height,
// TODO: this should be set to the extents of its children // TODO: this should be set to the extents of its children
GenericBox(*) => au(0) @GenericBox(*) => au(0)
}; };
box.data.position.origin = Point2D(au(0), cur_y); box.d().position.origin = Point2D(au(0), cur_y);
cur_y = cur_y.add(au::max(line_height, box.data.position.size.height)); cur_y = cur_y.add(au::max(line_height, box.d().position.size.height));
} // for boxes.each |box| } // for boxes.each |box|
} }

View file

@ -30,7 +30,7 @@ trait RootLayout {
fn build_display_list_root(a: &dl::DisplayListBuilder, b: &Rect<au>, c: &Point2D<au>, d: &dl::DisplayList); fn build_display_list_root(a: &dl::DisplayListBuilder, b: &Rect<au>, c: &Point2D<au>, d: &dl::DisplayList);
} }
impl @FlowContext : RootLayout { impl FlowContext : RootLayout {
pure fn starts_root_flow() -> bool { pure fn starts_root_flow() -> bool {
match self.kind { match self.kind {

View file

@ -27,8 +27,8 @@ trait TextLayout {
#[doc="The main reflow routine for text layout."] #[doc="The main reflow routine for text layout."]
impl @RenderBox : TextLayout { impl @RenderBox : TextLayout {
fn reflow_text(ctx: &LayoutContext) { fn reflow_text(ctx: &LayoutContext) {
let d = match self.kind { let d = match self {
TextBox(d) => { d } @TextBox(_,d) => { d }
_ => { fail ~"expected text box in reflow_text!" } _ => { fail ~"expected text box in reflow_text!" }
}; };
@ -73,7 +73,7 @@ impl @RenderBox : TextLayout {
let total_height = au(*current.size().height * line_count); let total_height = au(*current.size().height * line_count);
lines.push(move current); lines.push(move current);
self.data.position.size = Size2D(max_width, total_height); self.d().position.size = Size2D(max_width, total_height);
d.runs = move dvec::unwrap(lines); d.runs = move dvec::unwrap(lines);
} }
} }