mirror of
https://github.com/servo/servo.git
synced 2025-08-07 22:45:34 +01:00
Split layout/base.rs into box.rs and flow.rs
This commit is contained in:
parent
b5e0cee1ab
commit
c4338500b2
14 changed files with 267 additions and 243 deletions
|
@ -5,7 +5,7 @@
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use dom::node::{Node, NodeTree};
|
use dom::node::{Node, NodeTree};
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree};
|
use layout::box::{RenderBox, SpecifiedStyle, RenderBoxTree};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::traverse_parallel::top_down_traversal;
|
use layout::traverse_parallel::top_down_traversal;
|
||||||
use image::ImageHolder;
|
use image::ImageHolder;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/* The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. */
|
/* The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. */
|
||||||
use css::styles::SpecifiedStyle;
|
use css::styles::SpecifiedStyle;
|
||||||
use css::values::Stylesheet;
|
use css::values::Stylesheet;
|
||||||
|
use dom::bindings;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{Attr, ElementData};
|
use dom::element::{Attr, ElementData};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom::bindings;
|
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::geometry::au;
|
use gfx::geometry::au;
|
||||||
use js::crust::*;
|
use js::crust::*;
|
||||||
|
@ -12,8 +12,8 @@ use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
|
||||||
use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, jsval, JSBool};
|
use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, jsval, JSBool};
|
||||||
use js::rust::{bare_compartment, compartment, methods};
|
use js::rust::{bare_compartment, compartment, methods};
|
||||||
use js::{JSPROP_ENUMERATE, JSPROP_SHARED};
|
use js::{JSPROP_ENUMERATE, JSPROP_SHARED};
|
||||||
use layout::base::FlowContext;
|
|
||||||
use layout::debug::DebugMethods;
|
use layout::debug::DebugMethods;
|
||||||
|
use layout::flow::FlowContext;
|
||||||
use ptr::null;
|
use ptr::null;
|
||||||
use std::arc::ARC;
|
use std::arc::ARC;
|
||||||
use util::tree;
|
use util::tree;
|
||||||
|
|
|
@ -5,8 +5,9 @@ use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::geometry::au;
|
use gfx::geometry::au;
|
||||||
use layout::base::{RenderBox, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
|
use layout::box::{RenderBox};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
|
||||||
use util::tree;
|
use util::tree;
|
||||||
|
|
||||||
struct BlockFlowData {
|
struct BlockFlowData {
|
||||||
|
|
|
@ -17,11 +17,9 @@ use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use image::{Image, ImageHolder};
|
use image::{Image, ImageHolder};
|
||||||
use layout::block::BlockFlowData;
|
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::debug::DebugMethods;
|
use layout::debug::DebugMethods;
|
||||||
use layout::inline::InlineFlowData;
|
use layout::flow::FlowContext;
|
||||||
use layout::root::RootFlowData;
|
|
||||||
use layout::text::TextBoxData;
|
use layout::text::TextBoxData;
|
||||||
use servo_text::text_run::TextRun;
|
use servo_text::text_run::TextRun;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
|
@ -30,12 +28,7 @@ use util::color::Color;
|
||||||
use util::tree;
|
use util::tree;
|
||||||
use vec::{push, push_all};
|
use vec::{push, push_all};
|
||||||
|
|
||||||
|
/**
|
||||||
/** Servo's experimental layout system builds a tree of FlowContexts
|
|
||||||
and RenderBoxes, and figures out positions and display attributes of
|
|
||||||
tree nodes. Positions are computed in several tree traversals driven
|
|
||||||
by fundamental data dependencies of inline and block layout.
|
|
||||||
|
|
||||||
Render boxes (`struct RenderBox`) are the leafs of the layout
|
Render boxes (`struct RenderBox`) are the leafs of the layout
|
||||||
tree. They cannot position themselves. In general, render boxes do not
|
tree. They cannot position themselves. In general, render boxes do not
|
||||||
have a simple correspondence with CSS boxes as in the specification:
|
have a simple correspondence with CSS boxes as in the specification:
|
||||||
|
@ -65,149 +58,8 @@ padding, backgrounds. It is analogous to a CSS nonreplaced content box.
|
||||||
node. Split text boxes are implemented by referring to subsets of a
|
node. Split text boxes are implemented by referring to subsets of a
|
||||||
master TextRun object.
|
master TextRun object.
|
||||||
|
|
||||||
|
|
||||||
Flows (`struct FlowContext`) are interior nodes in the layout tree,
|
|
||||||
and correspond closely to flow contexts in the CSS
|
|
||||||
specification. Flows are responsible for positioning their child flow
|
|
||||||
contexts and render boxes. Flows have purpose-specific fields, such as
|
|
||||||
auxilliary line box structs, out-of-flow child lists, and so on.
|
|
||||||
|
|
||||||
Currently, the important types of flows are:
|
|
||||||
|
|
||||||
* BlockFlow: a flow that establishes a block context. It has several
|
|
||||||
child flows, each of which are positioned according to block
|
|
||||||
formatting context rules (as if child flows CSS block boxes). Block
|
|
||||||
flows also contain a single GenericBox to represent their rendered
|
|
||||||
borders, padding, etc. (In the future, this render box may be
|
|
||||||
folded into BlockFlow to save space.)
|
|
||||||
|
|
||||||
* InlineFlow: a flow that establishes an inline context. It has a
|
|
||||||
flat list of child boxes/flows that are subject to inline layout
|
|
||||||
and line breaking, and structs to represent line breaks and mapping
|
|
||||||
to CSS boxes, for the purpose of handling `getClientRects()`.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct FlowLayoutData {
|
|
||||||
// TODO: min/pref and position are used during disjoint phases of
|
|
||||||
// layout; maybe combine into a single enum to save space.
|
|
||||||
mut min_width: au,
|
|
||||||
mut pref_width: au,
|
|
||||||
mut position: Rect<au>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn FlowLayoutData() -> FlowLayoutData {
|
|
||||||
FlowLayoutData {
|
|
||||||
min_width: au(0),
|
|
||||||
pref_width: au(0),
|
|
||||||
position : au::zero_rect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The type of the formatting context, and data specific to each
|
|
||||||
context, such as linebox structures or float lists */
|
|
||||||
enum FlowContextData {
|
|
||||||
AbsoluteFlow,
|
|
||||||
BlockFlow(BlockFlowData),
|
|
||||||
FloatFlow,
|
|
||||||
InlineBlockFlow,
|
|
||||||
InlineFlow(InlineFlowData),
|
|
||||||
RootFlow(RootFlowData),
|
|
||||||
TableFlow
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A particular kind of layout context. It manages the positioning of
|
|
||||||
render boxes within the context. */
|
|
||||||
struct FlowContext {
|
|
||||||
kind: FlowContextData,
|
|
||||||
data: FlowLayoutData,
|
|
||||||
mut node: Option<Node>,
|
|
||||||
/* reference to parent, children flow contexts */
|
|
||||||
tree: tree::Tree<@FlowContext>,
|
|
||||||
/* TODO: debug only */
|
|
||||||
mut id: int
|
|
||||||
}
|
|
||||||
|
|
||||||
fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -> FlowContext {
|
|
||||||
FlowContext {
|
|
||||||
kind: kind,
|
|
||||||
data: FlowLayoutData(),
|
|
||||||
node: None,
|
|
||||||
tree: tree,
|
|
||||||
id: id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl @FlowContext : cmp::Eq {
|
|
||||||
pure fn eq(other: &@FlowContext) -> bool { box::ptr_eq(self, *other) }
|
|
||||||
pure fn ne(other: &@FlowContext) -> bool { !box::ptr_eq(self, *other) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Flow context disambiguation methods: the verbose alternative to virtual methods */
|
|
||||||
impl @FlowContext {
|
|
||||||
fn bubble_widths(ctx: &LayoutContext) {
|
|
||||||
match self.kind {
|
|
||||||
BlockFlow(*) => self.bubble_widths_block(ctx),
|
|
||||||
InlineFlow(*) => self.bubble_widths_inline(ctx),
|
|
||||||
RootFlow(*) => self.bubble_widths_root(ctx),
|
|
||||||
_ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_widths(ctx: &LayoutContext) {
|
|
||||||
match self.kind {
|
|
||||||
BlockFlow(*) => self.assign_widths_block(ctx),
|
|
||||||
InlineFlow(*) => self.assign_widths_inline(ctx),
|
|
||||||
RootFlow(*) => self.assign_widths_root(ctx),
|
|
||||||
_ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assign_height(ctx: &LayoutContext) {
|
|
||||||
match self.kind {
|
|
||||||
BlockFlow(*) => self.assign_height_block(ctx),
|
|
||||||
InlineFlow(*) => self.assign_height_inline(ctx),
|
|
||||||
RootFlow(*) => self.assign_height_root(ctx),
|
|
||||||
_ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_display_list_recurse(builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
|
|
||||||
offset: &Point2D<au>, list: &dl::DisplayList) {
|
|
||||||
match self.kind {
|
|
||||||
RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list),
|
|
||||||
BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list),
|
|
||||||
InlineFlow(*) => self.build_display_list_inline(builder, dirty, offset, list),
|
|
||||||
_ => fail fmt!("Tried to build_display_list_recurse of flow: %?", self.kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The tree holding FlowContexts */
|
|
||||||
enum FlowTree { FlowTree }
|
|
||||||
|
|
||||||
impl FlowTree : tree::ReadMethods<@FlowContext> {
|
|
||||||
fn each_child(ctx: @FlowContext, f: fn(&&@FlowContext) -> bool) {
|
|
||||||
tree::each_child(self, ctx, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
|
|
||||||
f(b.tree)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FlowTree : tree::WriteMethods<@FlowContext> {
|
|
||||||
fn add_child(parent: @FlowContext, child: @FlowContext) {
|
|
||||||
assert !box::ptr_eq(parent, child);
|
|
||||||
tree::add_child(self, parent, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
|
|
||||||
f(b.tree)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* A box's kind influences how its styles are interpreted during
|
/* A box's kind influences how its styles are interpreted during
|
||||||
layout. For example, replaced content such as images are resized
|
layout. For example, replaced content such as images are resized
|
||||||
|
@ -418,10 +270,11 @@ impl @RenderBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Why do these have to be redefined for each node type?
|
/**
|
||||||
|
* The tree holding render box relations. These are only defined for
|
||||||
/* The tree holding render box relations. (This should only be used
|
* nested CSS boxes that are nested in an otherwise inline flow
|
||||||
for painting nested inlines, AFAIK-- everything else depends on Flow tree) */
|
* context.
|
||||||
|
*/
|
||||||
enum RenderBoxTree { RenderBoxTree }
|
enum RenderBoxTree { RenderBoxTree }
|
||||||
|
|
||||||
impl RenderBoxTree : tree::ReadMethods<@RenderBox> {
|
impl RenderBoxTree : tree::ReadMethods<@RenderBox> {
|
||||||
|
@ -436,7 +289,7 @@ impl RenderBoxTree : tree::ReadMethods<@RenderBox> {
|
||||||
|
|
||||||
impl RenderBoxTree : tree::WriteMethods<@RenderBox> {
|
impl RenderBoxTree : tree::WriteMethods<@RenderBox> {
|
||||||
fn add_child(parent: @RenderBox, child: @RenderBox) {
|
fn add_child(parent: @RenderBox, child: @RenderBox) {
|
||||||
assert !box::ptr_eq(parent, child);
|
assert !core::box::ptr_eq(parent, child);
|
||||||
tree::add_child(self, parent, child)
|
tree::add_child(self, parent, child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,50 +298,6 @@ impl RenderBoxTree : tree::WriteMethods<@RenderBox> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugging
|
|
||||||
|
|
||||||
impl @FlowContext : DebugMethods {
|
|
||||||
fn dump() {
|
|
||||||
self.dump_indent(0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Dumps the flow tree, for debugging, with indentation. */
|
|
||||||
fn dump_indent(indent: uint) {
|
|
||||||
let mut s = ~"|";
|
|
||||||
for uint::range(0u, indent) |_i| {
|
|
||||||
s += ~"---- ";
|
|
||||||
}
|
|
||||||
|
|
||||||
s += self.debug_str();
|
|
||||||
debug!("%s", s);
|
|
||||||
|
|
||||||
for FlowTree.each_child(self) |child| {
|
|
||||||
child.dump_indent(indent + 1u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: we need a string builder. This is horribly inefficient */
|
|
||||||
fn debug_str() -> ~str {
|
|
||||||
let repr = match self.kind {
|
|
||||||
InlineFlow(d) => {
|
|
||||||
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
|
|
||||||
fmt!("%s %?", s, box.id)
|
|
||||||
});
|
|
||||||
s += ~")"; s
|
|
||||||
},
|
|
||||||
BlockFlow(d) => {
|
|
||||||
match d.box {
|
|
||||||
Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().id),
|
|
||||||
None => ~"BlockFlow",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => fmt!("%?", self.kind)
|
|
||||||
};
|
|
||||||
|
|
||||||
fmt!("c%? %?", self.id, repr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl @RenderBox : DebugMethods {
|
impl @RenderBox : DebugMethods {
|
||||||
fn dump() {
|
fn dump() {
|
||||||
self.dump_indent(0u);
|
self.dump_indent(0u);
|
|
@ -7,17 +7,17 @@ use css::values::{Inherit, Initial, Specified};
|
||||||
use dom::element::*;
|
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::base::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree};
|
use layout::flow::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
|
||||||
use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
|
use layout::box::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree};
|
||||||
use layout::block::BlockFlowData;
|
use layout::block::BlockFlowData;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::inline::InlineFlowData;
|
use layout::inline::InlineFlowData;
|
||||||
use layout::root::RootFlowData;
|
use layout::root::RootFlowData;
|
||||||
use layout::text::TextBoxData;
|
use layout::text::TextBoxData;
|
||||||
use option::is_none;
|
use option::is_none;
|
||||||
use util::tree;
|
|
||||||
use servo_text::text_run::TextRun;
|
|
||||||
use servo_text::font_cache::FontCache;
|
use servo_text::font_cache::FontCache;
|
||||||
|
use servo_text::text_run::TextRun;
|
||||||
|
use util::tree;
|
||||||
|
|
||||||
export LayoutTreeBuilder;
|
export LayoutTreeBuilder;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export DisplayListBuilder;
|
export DisplayListBuilder;
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use base::{RenderBox, RenderBoxTree};
|
use au::au;
|
||||||
use css::values::{BgColor, BgColorTransparent, Specified};
|
use css::values::{BgColor, BgColorTransparent, Specified};
|
||||||
use dl = gfx::display_list;
|
use dl = gfx::display_list;
|
||||||
use dom::node::{Text, NodeScope};
|
use dom::node::{Text, NodeScope};
|
||||||
|
@ -11,9 +11,10 @@ use either::{Left, Right};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::geometry::au;
|
use layout::box::{RenderBox, RenderBoxTree, TextBox};
|
||||||
|
use layout::context::LayoutContext;
|
||||||
|
use layout::flow::FlowContext;
|
||||||
use layout::text::TextBoxData;
|
use layout::text::TextBoxData;
|
||||||
use layout::base::{LayoutContext, FlowContext, TextBox};
|
|
||||||
use servo_text::text_run::TextRun;
|
use servo_text::text_run::TextRun;
|
||||||
use util::tree;
|
use util::tree;
|
||||||
use vec::push;
|
use vec::push;
|
||||||
|
|
206
src/servo/layout/flow.rs
Normal file
206
src/servo/layout/flow.rs
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
use au = gfx::geometry;
|
||||||
|
use au::au;
|
||||||
|
use dl = gfx::display_list;
|
||||||
|
use dom::node::Node;
|
||||||
|
use geom::rect::Rect;
|
||||||
|
use geom::point::Point2D;
|
||||||
|
// TODO: pub-use these
|
||||||
|
use layout::block::BlockFlowData;
|
||||||
|
use layout::context::LayoutContext;
|
||||||
|
use layout::debug::DebugMethods;
|
||||||
|
use layout::inline::InlineFlowData;
|
||||||
|
use layout::root::RootFlowData;
|
||||||
|
use util::tree;
|
||||||
|
|
||||||
|
/** Servo's experimental layout system builds a tree of FlowContexts
|
||||||
|
and RenderBoxes, and figures out positions and display attributes of
|
||||||
|
tree nodes. Positions are computed in several tree traversals driven
|
||||||
|
by fundamental data dependencies of inline and block layout.
|
||||||
|
|
||||||
|
Flows are interior nodes in the layout tree, and correspond closely to
|
||||||
|
flow contexts in the CSS specification. Flows are responsible for
|
||||||
|
positioning their child flow contexts and render boxes. Flows have
|
||||||
|
purpose-specific fields, such as auxilliary line box structs,
|
||||||
|
out-of-flow child lists, and so on.
|
||||||
|
|
||||||
|
Currently, the important types of flows are:
|
||||||
|
|
||||||
|
* BlockFlow: a flow that establishes a block context. It has several
|
||||||
|
child flows, each of which are positioned according to block
|
||||||
|
formatting context rules (as if child flows CSS block boxes). Block
|
||||||
|
flows also contain a single GenericBox to represent their rendered
|
||||||
|
borders, padding, etc. (In the future, this render box may be
|
||||||
|
folded into BlockFlow to save space.)
|
||||||
|
|
||||||
|
* InlineFlow: a flow that establishes an inline context. It has a
|
||||||
|
flat list of child boxes/flows that are subject to inline layout
|
||||||
|
and line breaking, and structs to represent line breaks and mapping
|
||||||
|
to CSS boxes, for the purpose of handling `getClientRects()`.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct FlowLayoutData {
|
||||||
|
// TODO: min/pref and position are used during disjoint phases of
|
||||||
|
// layout; maybe combine into a single enum to save space.
|
||||||
|
mut min_width: au,
|
||||||
|
mut pref_width: au,
|
||||||
|
mut position: Rect<au>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn FlowLayoutData() -> FlowLayoutData {
|
||||||
|
FlowLayoutData {
|
||||||
|
min_width: au(0),
|
||||||
|
pref_width: au(0),
|
||||||
|
position : au::zero_rect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The type of the formatting context, and data specific to each
|
||||||
|
context, such as linebox structures or float lists */
|
||||||
|
enum FlowContextData {
|
||||||
|
AbsoluteFlow,
|
||||||
|
BlockFlow(BlockFlowData),
|
||||||
|
FloatFlow,
|
||||||
|
InlineBlockFlow,
|
||||||
|
InlineFlow(InlineFlowData),
|
||||||
|
RootFlow(RootFlowData),
|
||||||
|
TableFlow
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A particular kind of layout context. It manages the positioning of
|
||||||
|
render boxes within the context. */
|
||||||
|
struct FlowContext {
|
||||||
|
kind: FlowContextData,
|
||||||
|
data: FlowLayoutData,
|
||||||
|
mut node: Option<Node>,
|
||||||
|
/* reference to parent, children flow contexts */
|
||||||
|
tree: tree::Tree<@FlowContext>,
|
||||||
|
/* TODO: debug only */
|
||||||
|
mut id: int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -> FlowContext {
|
||||||
|
FlowContext {
|
||||||
|
kind: kind,
|
||||||
|
data: FlowLayoutData(),
|
||||||
|
node: None,
|
||||||
|
tree: tree,
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
fn bubble_widths(ctx: &LayoutContext) {
|
||||||
|
match self.kind {
|
||||||
|
BlockFlow(*) => self.bubble_widths_block(ctx),
|
||||||
|
InlineFlow(*) => self.bubble_widths_inline(ctx),
|
||||||
|
RootFlow(*) => self.bubble_widths_root(ctx),
|
||||||
|
_ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_widths(ctx: &LayoutContext) {
|
||||||
|
match self.kind {
|
||||||
|
BlockFlow(*) => self.assign_widths_block(ctx),
|
||||||
|
InlineFlow(*) => self.assign_widths_inline(ctx),
|
||||||
|
RootFlow(*) => self.assign_widths_root(ctx),
|
||||||
|
_ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assign_height(ctx: &LayoutContext) {
|
||||||
|
match self.kind {
|
||||||
|
BlockFlow(*) => self.assign_height_block(ctx),
|
||||||
|
InlineFlow(*) => self.assign_height_inline(ctx),
|
||||||
|
RootFlow(*) => self.assign_height_root(ctx),
|
||||||
|
_ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_display_list_recurse(builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
|
||||||
|
offset: &Point2D<au>, list: &dl::DisplayList) {
|
||||||
|
match self.kind {
|
||||||
|
RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list),
|
||||||
|
BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list),
|
||||||
|
InlineFlow(*) => self.build_display_list_inline(builder, dirty, offset, list),
|
||||||
|
_ => fail fmt!("Tried to build_display_list_recurse of flow: %?", self.kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The tree holding FlowContexts */
|
||||||
|
enum FlowTree { FlowTree }
|
||||||
|
|
||||||
|
impl FlowTree : tree::ReadMethods<@FlowContext> {
|
||||||
|
fn each_child(ctx: @FlowContext, f: fn(&&@FlowContext) -> bool) {
|
||||||
|
tree::each_child(self, ctx, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
|
||||||
|
f(b.tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlowTree : tree::WriteMethods<@FlowContext> {
|
||||||
|
fn add_child(parent: @FlowContext, child: @FlowContext) {
|
||||||
|
assert !core::box::ptr_eq(parent, child);
|
||||||
|
tree::add_child(self, parent, child)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
|
||||||
|
f(b.tree)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl @FlowContext : DebugMethods {
|
||||||
|
fn dump() {
|
||||||
|
self.dump_indent(0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dumps the flow tree, for debugging, with indentation. */
|
||||||
|
fn dump_indent(indent: uint) {
|
||||||
|
let mut s = ~"|";
|
||||||
|
for uint::range(0u, indent) |_i| {
|
||||||
|
s += ~"---- ";
|
||||||
|
}
|
||||||
|
|
||||||
|
s += self.debug_str();
|
||||||
|
debug!("%s", s);
|
||||||
|
|
||||||
|
for FlowTree.each_child(self) |child| {
|
||||||
|
child.dump_indent(indent + 1u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: we need a string builder. This is horribly inefficient */
|
||||||
|
fn debug_str() -> ~str {
|
||||||
|
let repr = match self.kind {
|
||||||
|
InlineFlow(d) => {
|
||||||
|
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
|
||||||
|
fmt!("%s %?", s, box.id)
|
||||||
|
});
|
||||||
|
s += ~")"; s
|
||||||
|
},
|
||||||
|
BlockFlow(d) => {
|
||||||
|
match d.box {
|
||||||
|
Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().id),
|
||||||
|
None => ~"BlockFlow",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => fmt!("%?", self.kind)
|
||||||
|
};
|
||||||
|
|
||||||
|
fmt!("c%? %?", self.id, repr)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use base::RenderBox;
|
|
||||||
use core::dvec::DVec;
|
use core::dvec::DVec;
|
||||||
use css::values::{BoxAuto, BoxLength, Px};
|
use css::values::{BoxAuto, BoxLength, Px};
|
||||||
use dl = gfx::display_list;
|
use dl = gfx::display_list;
|
||||||
|
@ -8,8 +7,9 @@ use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::geometry::au;
|
use gfx::geometry::au;
|
||||||
|
use layout::box::{RenderBox, RenderBoxTree, ImageBox, TextBox, GenericBox};
|
||||||
|
use layout::flow::{FlowContext, InlineFlow};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::base::{FlowContext, InlineFlow, RenderBoxTree, ImageBox, TextBox, GenericBox};
|
|
||||||
use num::Num;
|
use num::Num;
|
||||||
use util::tree;
|
use util::tree;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#[doc = "
|
/**
|
||||||
The layout task. Performs layout on the DOM, builds display lists and sends them to be
|
The layout task. Performs layout on the DOM, builds display lists and sends them to be
|
||||||
rendered.
|
rendered.
|
||||||
"];
|
*/
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use au::au;
|
use au::au;
|
||||||
|
@ -10,20 +10,20 @@ use core::dvec::DVec;
|
||||||
use css::resolve::apply::apply_style;
|
use css::resolve::apply::apply_style;
|
||||||
use css::values::Stylesheet;
|
use css::values::Stylesheet;
|
||||||
use dl = gfx::display_list;
|
use dl = gfx::display_list;
|
||||||
use dom::node::{Node, LayoutData};
|
|
||||||
use dom::event::{Event, ReflowEvent};
|
use dom::event::{Event, ReflowEvent};
|
||||||
|
use dom::node::{Node, LayoutData};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::render_task;
|
use gfx::render_task;
|
||||||
use layout::base::RenderBox;
|
use layout::box::RenderBox;
|
||||||
use layout::box_builder::LayoutTreeBuilder;
|
use layout::box_builder::LayoutTreeBuilder;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use render_task::RenderTask;
|
use render_task::RenderTask;
|
||||||
use resource::image_cache_task::ImageCacheTask;
|
use resource::image_cache_task::ImageCacheTask;
|
||||||
|
use servo_text::font_cache::FontCache;
|
||||||
use std::arc::ARC;
|
use std::arc::ARC;
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use servo_text::font_cache::FontCache;
|
|
||||||
|
|
||||||
use layout::traverse::*;
|
use layout::traverse::*;
|
||||||
use comm::*;
|
use comm::*;
|
||||||
|
|
|
@ -4,8 +4,9 @@ use dl = gfx::display_list;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::geometry::au;
|
use gfx::geometry::au;
|
||||||
use layout::base::{RenderBox, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
|
use layout::box::RenderBox;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
|
||||||
use util::tree;
|
use util::tree;
|
||||||
|
|
||||||
struct RootFlowData {
|
struct RootFlowData {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use geom::size::Size2D;
|
||||||
use gfx::geometry::au;
|
use gfx::geometry::au;
|
||||||
use servo_text::text_run::TextRun;
|
use servo_text::text_run::TextRun;
|
||||||
use servo_text::font_cache::FontCache;
|
use servo_text::font_cache::FontCache;
|
||||||
use layout::base::{TextBox, RenderBox};
|
use layout::box::{TextBox, RenderBox};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
|
||||||
struct TextBoxData {
|
struct TextBoxData {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/** Interface for running tree-based traversals over layout boxes and contextsg */
|
/** Interface for running tree-based traversals over layout boxes and contextsg */
|
||||||
|
|
||||||
use layout::base::{RenderBox, RenderBoxTree};
|
use layout::box::{RenderBox, RenderBoxTree};
|
||||||
use layout::base::{FlowContext, FlowTree};
|
use layout::flow::{FlowContext, FlowTree};
|
||||||
|
|
||||||
/* TODO: we shouldn't need render box traversals */
|
/* TODO: we shouldn't need render box traversals */
|
||||||
trait RenderBoxTraversals {
|
trait RenderBoxTraversals {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
|
/* Interface for running tree-based traversals over layout boxes */
|
||||||
#[doc = "Interface for running tree-based traversals over layout boxes"]
|
use layout::box::{RenderBox, RenderBoxTree};
|
||||||
use base::{RenderBox, RenderBoxTree};
|
|
||||||
use intrinsic::TyDesc;
|
use intrinsic::TyDesc;
|
||||||
|
|
||||||
export full_traversal;
|
export full_traversal;
|
||||||
|
@ -21,19 +20,23 @@ type shared_box<T> = {
|
||||||
payload : T
|
payload : T
|
||||||
};
|
};
|
||||||
|
|
||||||
#[doc="Transform and @ into its underlying representation. The reference count stays constant."]
|
/**
|
||||||
|
Transform and @ into its underlying representation. The reference count stays constant.
|
||||||
|
*/
|
||||||
fn unwrap_box(-b : @RenderBox) -> *shared_box<RenderBox> unsafe {
|
fn unwrap_box(-b : @RenderBox) -> *shared_box<RenderBox> unsafe {
|
||||||
let new_box : *shared_box<RenderBox> = cast::transmute(b);
|
let new_box : *shared_box<RenderBox> = cast::transmute(b);
|
||||||
return new_box;
|
return new_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="Transform an underlying representation back to an @. The reference count stays constant."]
|
/**
|
||||||
|
Transform an underlying representation back to an @. The reference count stays constant.
|
||||||
|
*/
|
||||||
fn rewrap_box(-b : *shared_box<RenderBox>) -> @RenderBox unsafe {
|
fn rewrap_box(-b : *shared_box<RenderBox>) -> @RenderBox unsafe {
|
||||||
let new_box : @RenderBox = cast::transmute(b);
|
let new_box : @RenderBox = cast::transmute(b);
|
||||||
return new_box;
|
return new_box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="
|
/**
|
||||||
|
|
||||||
Iterate down and then up a tree of layout boxes in parallel and apply
|
Iterate down and then up a tree of layout boxes in parallel and apply
|
||||||
the given functions to each box. Each box applies the first function,
|
the given functions to each box. Each box applies the first function,
|
||||||
|
@ -52,7 +55,7 @@ finish, and then applies the second function to the current box.
|
||||||
* `bottom_up` - A function that is applied to each node after it is
|
* `bottom_up` - A function that is applied to each node after it is
|
||||||
applied to that node's children
|
applied to that node's children
|
||||||
|
|
||||||
"]
|
*/
|
||||||
fn traverse_helper<T : Copy Send>(-root : @RenderBox, returned : T, -top_down : fn~(+T, @RenderBox) -> T,
|
fn traverse_helper<T : Copy Send>(-root : @RenderBox, returned : T, -top_down : fn~(+T, @RenderBox) -> T,
|
||||||
-bottom_up : fn~(@RenderBox)) {
|
-bottom_up : fn~(@RenderBox)) {
|
||||||
let returned = top_down(returned, root);
|
let returned = top_down(returned, root);
|
||||||
|
@ -96,61 +99,63 @@ fn traverse_helper<T : Copy Send>(-root : @RenderBox, returned : T, -top_down :
|
||||||
bottom_up(root);
|
bottom_up(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="A noneffectful function to be used if only one pass is required."]
|
/**
|
||||||
|
A noneffectful function to be used if only one pass is required.
|
||||||
|
*/
|
||||||
fn nop(_box : @RenderBox) {
|
fn nop(_box : @RenderBox) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc= "
|
/**
|
||||||
A wrapper to change a function that only acts on a box to one that
|
A wrapper to change a function that only acts on a box to one that
|
||||||
threasds a unit through to match travserse_helper
|
threasds a unit through to match travserse_helper
|
||||||
"]
|
*/
|
||||||
fn unit_wrapper(-fun : fn~(@RenderBox)) -> fn~(+(), @RenderBox) {
|
fn unit_wrapper(-fun : fn~(@RenderBox)) -> fn~(+(), @RenderBox) {
|
||||||
fn~(+_u : (), box : @RenderBox) { fun(box); }
|
fn~(+_u : (), box : @RenderBox) { fun(box); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="
|
/**
|
||||||
Iterate in parallel over the boxes in a tree, applying one function
|
Iterate in parallel over the boxes in a tree, applying one function
|
||||||
to a parent before recursing on its children and one after.
|
to a parent before recursing on its children and one after.
|
||||||
"]
|
*/
|
||||||
fn full_traversal(+root : @RenderBox, -top_down : fn~(@RenderBox), -bottom_up : fn~(@RenderBox)) {
|
fn full_traversal(+root : @RenderBox, -top_down : fn~(@RenderBox), -bottom_up : fn~(@RenderBox)) {
|
||||||
traverse_helper(root, (), unit_wrapper(top_down), bottom_up);
|
traverse_helper(root, (), unit_wrapper(top_down), bottom_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="
|
/**
|
||||||
Iterate in parallel over the boxes in a tree, applying the given
|
Iterate in parallel over the boxes in a tree, applying the given
|
||||||
function to a parent before its children.
|
function to a parent before its children.
|
||||||
"]
|
*/
|
||||||
fn top_down_traversal(+root : @RenderBox, -top_down : fn~(@RenderBox)) {
|
fn top_down_traversal(+root : @RenderBox, -top_down : fn~(@RenderBox)) {
|
||||||
traverse_helper(root, (), unit_wrapper(top_down), nop);
|
traverse_helper(root, (), unit_wrapper(top_down), nop);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="
|
/**
|
||||||
Iterate in parallel over the boxes in a tree, applying the given
|
Iterate in parallel over the boxes in a tree, applying the given
|
||||||
function to a parent after its children.
|
function to a parent after its children.
|
||||||
"]
|
*/
|
||||||
fn bottom_up_traversal(+root : @RenderBox, -bottom_up : fn~(@RenderBox)) {
|
fn bottom_up_traversal(+root : @RenderBox, -bottom_up : fn~(@RenderBox)) {
|
||||||
traverse_helper(root, (), unit_wrapper(nop), bottom_up);
|
traverse_helper(root, (), unit_wrapper(nop), bottom_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="
|
/**
|
||||||
Iterate in parallel over the boxes in a tree, applying the given
|
Iterate in parallel over the boxes in a tree, applying the given
|
||||||
function to a parent before its children, the value returned by the
|
function to a parent before its children, the value returned by the
|
||||||
function is passed to each child when they are recursed upon. As
|
function is passed to each child when they are recursed upon. As
|
||||||
the recursion unwinds, the second function is applied to first the
|
the recursion unwinds, the second function is applied to first the
|
||||||
children in parallel, and then the parent.
|
children in parallel, and then the parent.
|
||||||
"]
|
*/
|
||||||
fn extended_full_traversal<T : Copy Send>(+root : @RenderBox, first_val : T,
|
fn extended_full_traversal<T : Copy Send>(+root : @RenderBox, first_val : T,
|
||||||
-top_down : fn~(+T, @RenderBox) -> T,
|
-top_down : fn~(+T, @RenderBox) -> T,
|
||||||
-bottom_up : fn~(@RenderBox)) {
|
-bottom_up : fn~(@RenderBox)) {
|
||||||
traverse_helper(root, first_val, top_down, bottom_up);
|
traverse_helper(root, first_val, top_down, bottom_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="
|
/**
|
||||||
Iterate in parallel over the boxes in a tree, applying the given
|
Iterate in parallel over the boxes in a tree, applying the given
|
||||||
function to a parent before its children, the value returned by the
|
function to a parent before its children, the value returned by the
|
||||||
function is passed to each child when they are recursed upon.
|
function is passed to each child when they are recursed upon.
|
||||||
"]
|
*/
|
||||||
fn extended_top_down_traversal<T : Copy Send>(+root : @RenderBox, first_val : T,
|
fn extended_top_down_traversal<T : Copy Send>(+root : @RenderBox, first_val : T,
|
||||||
-top_down : fn~(+T, @RenderBox) -> T) {
|
-top_down : fn~(+T, @RenderBox) -> T) {
|
||||||
traverse_helper(root, first_val, top_down, nop);
|
traverse_helper(root, first_val, top_down, nop);
|
||||||
|
|
|
@ -58,14 +58,15 @@ mod css {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod layout {
|
mod layout {
|
||||||
mod base;
|
|
||||||
mod block;
|
mod block;
|
||||||
|
mod box;
|
||||||
mod box_builder;
|
mod box_builder;
|
||||||
mod context;
|
mod context;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod display_list_builder;
|
mod display_list_builder;
|
||||||
mod inline;
|
mod flow;
|
||||||
mod layout_task;
|
mod layout_task;
|
||||||
|
mod inline;
|
||||||
mod root;
|
mod root;
|
||||||
mod text;
|
mod text;
|
||||||
mod traverse;
|
mod traverse;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue