mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
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:
parent
b9b3895a8a
commit
e89d2fa782
10 changed files with 195 additions and 149 deletions
|
@ -65,11 +65,11 @@ impl Node : cmp::Eq {
|
|||
|
||||
impl Node : DebugMethods {
|
||||
/* Dumps the subtree rooted at this node, for debugging. */
|
||||
fn dump() {
|
||||
fn dump(&self) {
|
||||
self.dump_indent(0u);
|
||||
}
|
||||
/* Dumps the node tree, for debugging, with indentation. */
|
||||
fn dump_indent(indent: uint) {
|
||||
fn dump_indent(&self, indent: uint) {
|
||||
let mut s = ~"";
|
||||
for uint::range(0u, indent) |_i| {
|
||||
s += ~" ";
|
||||
|
@ -78,12 +78,12 @@ impl Node : DebugMethods {
|
|||
s += self.debug_str();
|
||||
debug!("%s", s);
|
||||
|
||||
for NodeTree.each_child(self) |kid| {
|
||||
for NodeTree.each_child(*self) |kid| {
|
||||
kid.dump_indent(indent + 1u)
|
||||
}
|
||||
}
|
||||
|
||||
fn debug_str() -> ~str {
|
||||
fn debug_str(&self) -> ~str {
|
||||
do self.read |n| { fmt!("%?", n.kind) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ trait BlockLayout {
|
|||
c: &Point2D<au>, d: &dl::DisplayList);
|
||||
}
|
||||
|
||||
impl @FlowContext : BlockLayout {
|
||||
impl FlowContext : BlockLayout {
|
||||
|
||||
pure fn starts_block_flow() -> bool {
|
||||
match self.kind {
|
||||
|
@ -85,7 +85,7 @@ impl @FlowContext : BlockLayout {
|
|||
let mut pref_width = au(0);
|
||||
|
||||
/* 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();
|
||||
|
||||
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
|
||||
for its children. */
|
||||
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();
|
||||
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();
|
||||
child_ctx.data.position.origin.x = left_used;
|
||||
child_ctx.data.position.size.width = remaining_width;
|
||||
|
@ -137,7 +137,7 @@ impl @FlowContext : BlockLayout {
|
|||
|
||||
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;
|
||||
cur_y = cur_y.add(child_ctx.data.position.size.height);
|
||||
}
|
||||
|
@ -148,8 +148,8 @@ impl @FlowContext : BlockLayout {
|
|||
let _used_bot = au(0);
|
||||
|
||||
do self.with_block_box |box| {
|
||||
box.data.position.origin.y = au(0);
|
||||
box.data.position.size.height = cur_y;
|
||||
box.d().position.origin.y = au(0);
|
||||
box.d().position.size.height = cur_y;
|
||||
let (_used_top, _used_bot) = box.get_used_height();
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ impl @FlowContext : BlockLayout {
|
|||
// TODO: handle any out-of-flow elements
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use geom::size::Size2D;
|
|||
use geom::point::Point2D;
|
||||
use image::{Image, ImageHolder};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::debug::DebugMethods;
|
||||
use layout::debug::BoxedDebugMethods;
|
||||
use layout::flow::FlowContext;
|
||||
use layout::text::TextBoxData;
|
||||
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.
|
||||
*/
|
||||
|
||||
struct BoxLayoutData {
|
||||
mut position: Rect<au>,
|
||||
mut font_size: Length,
|
||||
}
|
||||
|
||||
/* TODO: this should eventually be just 'position', and
|
||||
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 {
|
||||
struct RenderBoxData {
|
||||
/* references to children, parent inline flow boxes */
|
||||
tree : tree::Tree<@RenderBox>,
|
||||
/* originating DOM node */
|
||||
|
@ -96,30 +77,51 @@ struct RenderBox {
|
|||
/* reference to containing flow context, which this box
|
||||
participates in */
|
||||
ctx : @FlowContext,
|
||||
/* results of flow computation */
|
||||
data : BoxLayoutData,
|
||||
/* kind tag and kind-specific data */
|
||||
kind : BoxData,
|
||||
/* position of this box relative to owning flow */
|
||||
mut position : Rect<au>,
|
||||
font_size : Length,
|
||||
/* TODO (Issue #87): debug only */
|
||||
mut id: int
|
||||
}
|
||||
|
||||
fn RenderBox(id: int, node: Node, ctx: @FlowContext, kind: BoxData) -> RenderBox {
|
||||
RenderBox {
|
||||
enum RenderBoxType {
|
||||
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 */
|
||||
tree : tree::empty(),
|
||||
node : node,
|
||||
ctx : ctx,
|
||||
data : BoxLayoutData(),
|
||||
kind : kind,
|
||||
mut ctx : ctx,
|
||||
mut position : au::zero_rect(),
|
||||
font_size: Px(0.0),
|
||||
id : id
|
||||
}
|
||||
}
|
||||
|
||||
impl @RenderBox {
|
||||
impl RenderBox {
|
||||
pure fn is_replaced() -> bool {
|
||||
match self.kind {
|
||||
ImageBox(*) => true, // TODO: form elements, etc
|
||||
match self {
|
||||
ImageBox(*) => true, // TODO: form elements, etc
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
@ -129,35 +131,35 @@ impl @RenderBox {
|
|||
* holder.get_image()
|
||||
*/
|
||||
fn get_min_width() -> au {
|
||||
match self.kind {
|
||||
match self {
|
||||
// TODO: this should account for min/pref widths of the
|
||||
// box element in isolation. That includes
|
||||
// border/margin/padding but not child widths. The block
|
||||
// FlowContext will combine the width of this element and
|
||||
// that of its children to arrive at the context width.
|
||||
GenericBox => au(0),
|
||||
GenericBox(*) => au(0),
|
||||
// TODO: consult CSS 'width', margin, border.
|
||||
// TODO: If image isn't available, consult 'width'.
|
||||
ImageBox(i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
|
||||
TextBox(d) => d.runs.foldl(au(0), |sum, run| {
|
||||
ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
|
||||
TextBox(_,d) => d.runs.foldl(au(0), |sum, run| {
|
||||
au::max(sum, run.min_break_width())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_pref_width() -> au {
|
||||
match self.kind {
|
||||
match self {
|
||||
// TODO: this should account for min/pref widths of the
|
||||
// box element in isolation. That includes
|
||||
// border/margin/padding but not child widths. The block
|
||||
// FlowContext will combine the width of this element and
|
||||
// that of its children to arrive at the context width.
|
||||
GenericBox => au(0),
|
||||
ImageBox(i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
|
||||
GenericBox(*) => au(0),
|
||||
ImageBox(_,i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
|
||||
// TODO: account for line breaks, etc. The run should know
|
||||
// how to compute its own min and pref widths, and should
|
||||
// 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)
|
||||
})
|
||||
}
|
||||
|
@ -184,21 +186,21 @@ impl @RenderBox {
|
|||
/* The box formed by the content edge, as defined in CSS 2.1 Section 8.1.
|
||||
Coordinates are relative to the owning flow. */
|
||||
pure fn content_box() -> Rect<au> {
|
||||
match self.kind {
|
||||
ImageBox(i) => {
|
||||
match self {
|
||||
ImageBox(_,i) => {
|
||||
let size = i.size();
|
||||
Rect {
|
||||
origin: copy self.data.position.origin,
|
||||
origin: copy self.d().position.origin,
|
||||
size: Size2D(au::from_px(size.width),
|
||||
au::from_px(size.height))
|
||||
}
|
||||
},
|
||||
GenericBox(*) => {
|
||||
copy self.data.position
|
||||
copy self.d().position
|
||||
/* FIXME: The following hits an ICE for whatever reason
|
||||
|
||||
let origin = self.data.position.origin;
|
||||
let size = self.data.position.size;
|
||||
let origin = self.d().position.origin;
|
||||
let size = self.d().position.size;
|
||||
let (offset_left, offset_right) = self.get_used_width();
|
||||
let (offset_top, offset_bottom) = self.get_used_height();
|
||||
|
||||
|
@ -209,7 +211,7 @@ impl @RenderBox {
|
|||
}*/
|
||||
},
|
||||
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>,
|
||||
offset: &Point2D<au>, list: &dl::DisplayList) {
|
||||
if !self.data.position.intersects(dirty) {
|
||||
if !self.d().position.intersects(dirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
let bounds : Rect<au> = Rect(self.data.position.origin.add(offset),
|
||||
copy self.data.position.size);
|
||||
let bounds : Rect<au> = Rect(self.d().position.origin.add(offset),
|
||||
copy self.d().position.size);
|
||||
|
||||
match self.kind {
|
||||
TextBox(d) => {
|
||||
match self {
|
||||
TextBox(_,d) => {
|
||||
let mut runs = d.runs;
|
||||
// TODO: don't paint background for text boxes
|
||||
list.push(~dl::SolidColor(bounds, 255u8, 255u8, 255u8));
|
||||
|
@ -271,13 +273,13 @@ impl @RenderBox {
|
|||
},
|
||||
// TODO: items for background, border, outline
|
||||
GenericBox(*) => { },
|
||||
ImageBox(i) => {
|
||||
ImageBox(_,i) => {
|
||||
match i.get_image() {
|
||||
Some(image) => list.push(~dl::Image(bounds, image)),
|
||||
/* No image data at all? Okay, add some fallback content instead. */
|
||||
None => {
|
||||
// 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 {
|
||||
Specified(BgColor(c)) => c,
|
||||
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
|
||||
* 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 {
|
||||
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 {
|
||||
f(b.tree)
|
||||
f(b.d().tree)
|
||||
}
|
||||
}
|
||||
|
||||
impl @RenderBox : DebugMethods {
|
||||
fn dump() {
|
||||
impl RenderBox : BoxedDebugMethods {
|
||||
fn dump(@self) {
|
||||
self.dump_indent(0u);
|
||||
}
|
||||
|
||||
/* Dumps the node tree, for debugging, with indentation. */
|
||||
fn dump_indent(indent: uint) {
|
||||
fn dump_indent(@self, indent: uint) {
|
||||
let mut s = ~"";
|
||||
for uint::range(0u, indent) |_i| {
|
||||
s += ~" ";
|
||||
|
@ -338,11 +344,11 @@ impl @RenderBox : DebugMethods {
|
|||
}
|
||||
}
|
||||
|
||||
fn debug_str() -> ~str {
|
||||
let repr = match self.kind {
|
||||
GenericBox(*) => ~"GenericBox",
|
||||
ImageBox(*) => ~"ImageBox",
|
||||
TextBox(d) => {
|
||||
fn debug_str(@self) -> ~str {
|
||||
let repr = match self {
|
||||
@GenericBox(*) => ~"GenericBox",
|
||||
@ImageBox(*) => ~"ImageBox",
|
||||
@TextBox(_,d) => {
|
||||
let mut s = d.runs.foldl(~"TextBox(runs=", |s, run| {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use dom::element::*;
|
|||
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData};
|
||||
use image::holder::ImageHolder;
|
||||
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::context::LayoutContext;
|
||||
use layout::inline::InlineFlowData;
|
||||
|
@ -58,21 +58,21 @@ impl LayoutTreeBuilder {
|
|||
v => v
|
||||
};
|
||||
|
||||
// first, create the proper box kind, based on node characteristics
|
||||
let box_data = self.create_box_data(layout_ctx, cur_node, simulated_display);
|
||||
// first, determine the box type, based on node characteristics
|
||||
let box_type = self.decide_box_type(cur_node, simulated_display);
|
||||
|
||||
// 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
|
||||
flow ctx if we aren't inside one already. */
|
||||
TextBox(*) => {
|
||||
RenderBox_Text => {
|
||||
if (parent_ctx.starts_inline_flow()) {
|
||||
parent_ctx
|
||||
} else {
|
||||
self.make_ctx(InlineFlow(InlineFlowData()), tree::empty())
|
||||
}
|
||||
},
|
||||
ImageBox(*) | GenericBox => {
|
||||
RenderBox_Image | RenderBox_Generic => {
|
||||
match simulated_display {
|
||||
DisplayInline | DisplayInlineBlock => {
|
||||
/* if inline, try to put into inline context,
|
||||
|
@ -98,7 +98,7 @@ impl LayoutTreeBuilder {
|
|||
do cur_node.aux |data| { data.flow = Some(next_ctx) }
|
||||
|
||||
// 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());
|
||||
|
||||
match next_ctx.kind {
|
||||
|
@ -109,7 +109,7 @@ impl LayoutTreeBuilder {
|
|||
let parent = parent_box.get();
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
FlowTree.add_child(parent_ctx, next_ctx);
|
||||
}
|
||||
|
@ -188,39 +188,79 @@ impl LayoutTreeBuilder {
|
|||
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());
|
||||
ret
|
||||
}
|
||||
|
||||
/* Based on the DOM node type, create a specific type of box */
|
||||
fn create_box_data(layout_ctx: &LayoutContext, node: Node, display: CSSDisplay) -> BoxData {
|
||||
// TODO: handle more types of nodes.
|
||||
fn make_generic_box(_layout_ctx: &LayoutContext, node: Node, ctx: @FlowContext) -> @RenderBox {
|
||||
@GenericBox(RenderBoxData(node, ctx, self.next_box_id()))
|
||||
}
|
||||
|
||||
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| {
|
||||
match n.kind {
|
||||
~Doctype(*) | ~Comment(*) => fail ~"Hey, doctypes and comments shouldn't get here! They are display:none!",
|
||||
~Text(string) => {
|
||||
// TODO: clean this up. Fonts should not be created here.
|
||||
let font = layout_ctx.font_cache.get_test_font();
|
||||
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) => {
|
||||
match (element.kind, display) {
|
||||
(~HTMLImageElement(d), _) if d.image.is_some() => {
|
||||
let holder = ImageHolder(&d.image.get(),
|
||||
layout_ctx.image_cache,
|
||||
copy layout_ctx.reflow_cb);
|
||||
ImageBox(holder)
|
||||
},
|
||||
(~HTMLImageElement(d), _) if d.image.is_some() => RenderBox_Image,
|
||||
// (_, 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,11 @@
|
|||
trait DebugMethods {
|
||||
fn dump();
|
||||
fn dump_indent(ident: uint);
|
||||
fn debug_str() -> ~str;
|
||||
trait BoxedDebugMethods {
|
||||
fn dump(@self);
|
||||
fn dump_indent(@self, ident: uint);
|
||||
fn debug_str(@self) -> ~str;
|
||||
}
|
||||
|
||||
trait DebugMethods {
|
||||
fn dump(&self);
|
||||
fn dump_indent(&self, ident: uint);
|
||||
fn debug_str(&self) -> ~str;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ trait FlowDisplayListBuilderMethods {
|
|||
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) {
|
||||
let zero = au::zero_point();
|
||||
|
|
|
@ -8,7 +8,7 @@ use geom::point::Point2D;
|
|||
use layout::block::BlockFlowData;
|
||||
use layout::box::RenderBox;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::debug::DebugMethods;
|
||||
use layout::debug::BoxedDebugMethods;
|
||||
use layout::inline::InlineFlowData;
|
||||
use layout::root::RootFlowData;
|
||||
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 */
|
||||
impl @FlowContext {
|
||||
impl FlowContext {
|
||||
fn bubble_widths(ctx: &LayoutContext) {
|
||||
match self.kind {
|
||||
BlockFlow(*) => self.bubble_widths_block(ctx),
|
||||
|
@ -139,19 +133,19 @@ impl @FlowContext {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
match self.kind {
|
||||
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
|
||||
},
|
||||
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
|
||||
},
|
||||
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 }
|
||||
},
|
||||
_ => 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) {
|
||||
match self.kind {
|
||||
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 {
|
||||
Some(box) if box.node == node => { cb(box); },
|
||||
Some(box) if box.d().node == node => { cb(box); },
|
||||
_ => {}
|
||||
},
|
||||
InlineFlow(d) => {
|
||||
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)
|
||||
|
@ -204,13 +198,13 @@ impl FlowTree : tree::WriteMethods<@FlowContext> {
|
|||
}
|
||||
|
||||
|
||||
impl @FlowContext : DebugMethods {
|
||||
fn dump() {
|
||||
impl FlowContext : BoxedDebugMethods {
|
||||
fn dump(@self) {
|
||||
self.dump_indent(0u);
|
||||
}
|
||||
|
||||
/** Dumps the flow tree, for debugging, with indentation. */
|
||||
fn dump_indent(indent: uint) {
|
||||
fn dump_indent(@self, indent: uint) {
|
||||
let mut s = ~"|";
|
||||
for uint::range(0u, indent) |_i| {
|
||||
s += ~"---- ";
|
||||
|
@ -225,17 +219,17 @@ impl @FlowContext : DebugMethods {
|
|||
}
|
||||
|
||||
/* TODO: we need a string builder. This is horribly inefficient */
|
||||
fn debug_str() -> ~str {
|
||||
fn debug_str(@self) -> ~str {
|
||||
let repr = match self.kind {
|
||||
InlineFlow(d) => {
|
||||
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
|
||||
fmt!("%s %?", s, box.id)
|
||||
fmt!("%s %?", s, box.d().id)
|
||||
});
|
||||
s += ~")"; s
|
||||
},
|
||||
BlockFlow(d) => {
|
||||
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",
|
||||
}
|
||||
},
|
||||
|
|
|
@ -57,7 +57,7 @@ trait InlineLayout {
|
|||
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 access_inline<T>(cb: fn(&&InlineFlowData) -> T) -> T {
|
||||
|
@ -110,27 +110,27 @@ impl @FlowContext : InlineLayout {
|
|||
|
||||
/* hack: until text box splitting is hoisted into this
|
||||
function, force "reflow" on TextBoxes. */
|
||||
match box.kind {
|
||||
TextBox(*) => box.reflow_text(ctx),
|
||||
match *box {
|
||||
@TextBox(*) => box.reflow_text(ctx),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
box.data.position.size.width = match box.kind {
|
||||
ImageBox(img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width),
|
||||
TextBox(d) => d.runs[0].size().width,
|
||||
|
||||
box.d().position.size.width = match *box {
|
||||
@ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width),
|
||||
@TextBox(_,d) => d.runs[0].size().width,
|
||||
// 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 {
|
||||
ImageBox(img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height),
|
||||
TextBox(d) => d.runs[0].size().height,
|
||||
box.d().position.size.height = match *box {
|
||||
@ImageBox(_,img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height),
|
||||
@TextBox(_,d) => d.runs[0].size().height,
|
||||
// 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);
|
||||
cur_y = cur_y.add(au::max(line_height, box.data.position.size.height));
|
||||
|
||||
box.d().position.origin = Point2D(au(0), cur_y);
|
||||
cur_y = cur_y.add(au::max(line_height, box.d().position.size.height));
|
||||
} // for boxes.each |box|
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ trait RootLayout {
|
|||
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 {
|
||||
match self.kind {
|
||||
|
|
|
@ -27,8 +27,8 @@ trait TextLayout {
|
|||
#[doc="The main reflow routine for text layout."]
|
||||
impl @RenderBox : TextLayout {
|
||||
fn reflow_text(ctx: &LayoutContext) {
|
||||
let d = match self.kind {
|
||||
TextBox(d) => { d }
|
||||
let d = match self {
|
||||
@TextBox(_,d) => { d }
|
||||
_ => { fail ~"expected text box in reflow_text!" }
|
||||
};
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl @RenderBox : TextLayout {
|
|||
let total_height = au(*current.size().height * line_count);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue