mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Refactor FlowContext to have the preferred nesting strategy of enum variants and structs.
This commit is contained in:
parent
e89d2fa782
commit
49de0a7fac
7 changed files with 207 additions and 190 deletions
|
@ -22,7 +22,6 @@ fn BlockFlowData() -> BlockFlowData {
|
|||
|
||||
trait BlockLayout {
|
||||
pure fn starts_block_flow() -> bool;
|
||||
pure fn access_block<T>(fn(&&BlockFlowData) -> T) -> T;
|
||||
pure fn with_block_box(fn(&&@RenderBox) -> ()) -> ();
|
||||
|
||||
fn bubble_widths_block(ctx: &LayoutContext);
|
||||
|
@ -36,36 +35,25 @@ trait BlockLayout {
|
|||
impl FlowContext : BlockLayout {
|
||||
|
||||
pure fn starts_block_flow() -> bool {
|
||||
match self.kind {
|
||||
match self {
|
||||
RootFlow(*) | BlockFlow(*) | InlineBlockFlow(*) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pure fn access_block<T>(cb:fn(&&BlockFlowData) -> T) -> T {
|
||||
match self.kind {
|
||||
BlockFlow(d) => cb(d),
|
||||
_ => fail fmt!("Tried to access() data of BlockFlow, but this is a %?", self.kind)
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the current flow's corresponding block box, if it exists, and do something with it.
|
||||
This works on both BlockFlow and RootFlow, since they are mostly the same. */
|
||||
pure fn with_block_box(cb:fn(&&@RenderBox) -> ()) -> () {
|
||||
match self.kind {
|
||||
BlockFlow(*) => {
|
||||
do self.access_block |d| {
|
||||
let mut box = d.box;
|
||||
box.iter(cb)
|
||||
}
|
||||
},
|
||||
match self {
|
||||
BlockFlow(*) => {
|
||||
let mut box = self.block().box;
|
||||
box.iter(cb);
|
||||
},
|
||||
RootFlow(*) => {
|
||||
do self.access_root |d| {
|
||||
let mut box = d.box;
|
||||
box.iter(cb)
|
||||
}
|
||||
let mut box = self.root().box;
|
||||
box.iter(cb);
|
||||
},
|
||||
_ => fail fmt!("Tried to do something with_block_box(), but this is a %?", self.kind)
|
||||
_ => fail fmt!("Tried to do something with_block_box(), but this is a %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,8 +76,8 @@ impl FlowContext : BlockLayout {
|
|||
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);
|
||||
pref_width = au::max(pref_width, child_ctx.data.pref_width);
|
||||
min_width = au::max(min_width, child_ctx.d().min_width);
|
||||
pref_width = au::max(pref_width, child_ctx.d().pref_width);
|
||||
}
|
||||
|
||||
/* if not an anonymous block context, add in block box's widths.
|
||||
|
@ -99,8 +87,8 @@ impl FlowContext : BlockLayout {
|
|||
pref_width = pref_width.add(box.get_pref_width());
|
||||
}
|
||||
|
||||
self.data.min_width = min_width;
|
||||
self.data.pref_width = pref_width;
|
||||
self.d().min_width = min_width;
|
||||
self.d().pref_width = pref_width;
|
||||
}
|
||||
|
||||
/* Recursively (top-down) determines the actual width of child
|
||||
|
@ -113,7 +101,7 @@ impl FlowContext : BlockLayout {
|
|||
fn assign_widths_block(_ctx: &LayoutContext) {
|
||||
assert self.starts_block_flow();
|
||||
|
||||
let mut remaining_width = self.data.position.size.width;
|
||||
let mut remaining_width = self.d().position.size.width;
|
||||
let mut _right_used = au(0);
|
||||
let mut left_used = au(0);
|
||||
|
||||
|
@ -127,8 +115,8 @@ impl FlowContext : BlockLayout {
|
|||
|
||||
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;
|
||||
child_ctx.d().position.origin.x = left_used;
|
||||
child_ctx.d().position.size.width = remaining_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,11 +126,11 @@ impl FlowContext : BlockLayout {
|
|||
let mut cur_y = au(0);
|
||||
|
||||
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);
|
||||
child_ctx.d().position.origin.y = cur_y;
|
||||
cur_y = cur_y.add(child_ctx.d().position.size.height);
|
||||
}
|
||||
|
||||
self.data.position.size.height = cur_y;
|
||||
self.d().position.size.height = cur_y;
|
||||
|
||||
let _used_top = au(0);
|
||||
let _used_bot = au(0);
|
||||
|
|
|
@ -7,10 +7,10 @@ use css::values::{Inherit, Initial, Specified};
|
|||
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::*;
|
||||
use layout::block::BlockFlowData;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::flow::*;
|
||||
use layout::inline::InlineFlowData;
|
||||
use layout::root::RootFlowData;
|
||||
use layout::text::TextBoxData;
|
||||
|
@ -69,7 +69,7 @@ impl LayoutTreeBuilder {
|
|||
if (parent_ctx.starts_inline_flow()) {
|
||||
parent_ctx
|
||||
} else {
|
||||
self.make_ctx(InlineFlow(InlineFlowData()), tree::empty())
|
||||
self.make_ctx(Flow_Inline)
|
||||
}
|
||||
},
|
||||
RenderBox_Image | RenderBox_Generic => {
|
||||
|
@ -80,12 +80,12 @@ impl LayoutTreeBuilder {
|
|||
if (parent_ctx.starts_inline_flow()) {
|
||||
parent_ctx
|
||||
} else {
|
||||
self.make_ctx(InlineFlow(InlineFlowData()), tree::empty())
|
||||
self.make_ctx(Flow_Inline)
|
||||
}
|
||||
},
|
||||
/* block boxes always create a new context */
|
||||
DisplayBlock => {
|
||||
self.make_ctx(BlockFlow(BlockFlowData()), tree::empty())
|
||||
self.make_ctx(Flow_Block)
|
||||
},
|
||||
_ => fail fmt!("unsupported display type in box generation: %?", simulated_display)
|
||||
}
|
||||
|
@ -101,25 +101,27 @@ impl LayoutTreeBuilder {
|
|||
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 {
|
||||
InlineFlow(d) => {
|
||||
d.boxes.push(new_box);
|
||||
match *next_ctx {
|
||||
InlineFlow(*) => {
|
||||
next_ctx.inline().boxes.push(new_box);
|
||||
|
||||
if (parent_box.is_some()) {
|
||||
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.d().id, new_box.d().id);
|
||||
debug!("In inline flow f%?, set child b%? of parent b%?",
|
||||
next_ctx.d().id, parent.d().id, new_box.d().id);
|
||||
RenderBoxTree.add_child(parent, new_box);
|
||||
}
|
||||
}
|
||||
BlockFlow(d) => { d.box = Some(new_box) }
|
||||
BlockFlow(*) => next_ctx.block().box = Some(new_box),
|
||||
_ => {} // TODO: float lists, etc.
|
||||
};
|
||||
|
||||
|
||||
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.d().id, next_ctx.d().id);
|
||||
FlowTree.add_child(parent_ctx, next_ctx);
|
||||
}
|
||||
// recurse
|
||||
|
@ -134,8 +136,8 @@ impl LayoutTreeBuilder {
|
|||
let mut found_child_block = false;
|
||||
|
||||
do FlowTree.each_child(next_ctx) |child_ctx| {
|
||||
match child_ctx.kind {
|
||||
InlineFlow(*) | InlineBlockFlow => found_child_inline = true,
|
||||
match *child_ctx {
|
||||
InlineFlow(*) | InlineBlockFlow(*) => found_child_inline = true,
|
||||
BlockFlow(*) => found_child_block = true,
|
||||
_ => {}
|
||||
}; true
|
||||
|
@ -176,14 +178,22 @@ impl LayoutTreeBuilder {
|
|||
/** entry point for box creation. Should only be
|
||||
called on root DOM element. */
|
||||
fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@FlowContext, ()> {
|
||||
self.root_ctx = Some(self.make_ctx(RootFlow(RootFlowData()), tree::empty()));
|
||||
|
||||
self.root_ctx = Some(self.make_ctx(Flow_Root));
|
||||
self.construct_recursively(layout_ctx, root, self.root_ctx.get(), None);
|
||||
return Ok(self.root_ctx.get())
|
||||
}
|
||||
|
||||
fn make_ctx(kind : FlowContextData, tree: tree::Tree<@FlowContext>) -> @FlowContext {
|
||||
let ret = @FlowContext(self.next_ctx_id(), kind, tree);
|
||||
fn make_ctx(ty : FlowContextType) -> @FlowContext {
|
||||
let data = FlowData(self.next_ctx_id());
|
||||
let ret = match ty {
|
||||
Flow_Absolute => @AbsoluteFlow(data),
|
||||
Flow_Block => @BlockFlow(data, BlockFlowData()),
|
||||
Flow_Float => @FloatFlow(data),
|
||||
Flow_InlineBlock => @InlineBlockFlow(data),
|
||||
Flow_Inline => @InlineFlow(data, InlineFlowData()),
|
||||
Flow_Root => @RootFlow(data, RootFlowData()),
|
||||
Flow_Table => @TableFlow(data)
|
||||
};
|
||||
debug!("Created context: %s", ret.debug_str());
|
||||
ret
|
||||
}
|
||||
|
|
|
@ -49,10 +49,10 @@ impl FlowContext: FlowDisplayListBuilderMethods {
|
|||
dirty: &Rect<au>, offset: &Point2D<au>, list: &dl::DisplayList) {
|
||||
|
||||
// adjust the dirty rect to child flow context coordinates
|
||||
let adj_dirty = dirty.translate(&child.data.position.origin);
|
||||
let adj_offset = offset.add(&child.data.position.origin);
|
||||
let adj_dirty = dirty.translate(&child.d().position.origin);
|
||||
let adj_offset = offset.add(&child.d().position.origin);
|
||||
|
||||
if (adj_dirty.intersects(&child.data.position)) {
|
||||
if (adj_dirty.intersects(&child.d().position)) {
|
||||
child.build_display_list_recurse(builder, &adj_dirty, &adj_offset, list);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,8 +40,74 @@ Currently, the important types of flows are:
|
|||
|
||||
*/
|
||||
|
||||
/* The type of the formatting context, and data specific to each
|
||||
context, such as linebox structures or float lists */
|
||||
enum FlowContext {
|
||||
AbsoluteFlow(FlowData),
|
||||
BlockFlow(FlowData, BlockFlowData),
|
||||
FloatFlow(FlowData),
|
||||
InlineBlockFlow(FlowData),
|
||||
InlineFlow(FlowData, InlineFlowData),
|
||||
RootFlow(FlowData, RootFlowData),
|
||||
TableFlow(FlowData)
|
||||
}
|
||||
|
||||
struct FlowLayoutData {
|
||||
enum FlowContextType {
|
||||
Flow_Absolute,
|
||||
Flow_Block,
|
||||
Flow_Float,
|
||||
Flow_InlineBlock,
|
||||
Flow_Inline,
|
||||
Flow_Root,
|
||||
Flow_Table
|
||||
}
|
||||
|
||||
impl FlowContext {
|
||||
pure fn d(&self) -> &self/FlowData {
|
||||
match *self {
|
||||
AbsoluteFlow(ref d) => d,
|
||||
BlockFlow(ref d, _) => d,
|
||||
FloatFlow(ref d) => d,
|
||||
InlineBlockFlow(ref d) => d,
|
||||
InlineFlow(ref d, _) => d,
|
||||
RootFlow(ref d, _) => d,
|
||||
TableFlow(ref d) => d
|
||||
}
|
||||
}
|
||||
|
||||
pure fn inline(&self) -> &self/InlineFlowData {
|
||||
match *self {
|
||||
InlineFlow(_, ref i) => i,
|
||||
_ => fail fmt!("Tried to access inline data of non-inline: %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
pure fn block(&self) -> &self/BlockFlowData {
|
||||
match *self {
|
||||
BlockFlow(_, ref b) => b,
|
||||
_ => fail fmt!("Tried to access block data of non-block: %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
pure fn root(&self) -> &self/RootFlowData {
|
||||
match *self {
|
||||
RootFlow(_, ref r) => r,
|
||||
_ => fail fmt!("Tried to access root data of non-root: %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* A particular kind of layout context. It manages the positioning of
|
||||
render boxes within the context. */
|
||||
struct FlowData {
|
||||
mut node: Option<Node>,
|
||||
/* reference to parent, children flow contexts */
|
||||
tree: tree::Tree<@FlowContext>,
|
||||
/* TODO (Issue #87): debug only */
|
||||
mut id: int,
|
||||
|
||||
/* layout computations */
|
||||
// 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,
|
||||
|
@ -49,85 +115,55 @@ struct FlowLayoutData {
|
|||
mut position: Rect<au>,
|
||||
}
|
||||
|
||||
fn FlowLayoutData() -> FlowLayoutData {
|
||||
FlowLayoutData {
|
||||
|
||||
fn FlowData(id: int) -> FlowData {
|
||||
FlowData {
|
||||
node: None,
|
||||
tree: tree::empty(),
|
||||
id: id,
|
||||
|
||||
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 (Issue #87): 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
|
||||
position: au::zero_rect()
|
||||
}
|
||||
}
|
||||
|
||||
/* Flow context disambiguation methods: the verbose alternative to virtual methods */
|
||||
impl FlowContext {
|
||||
fn bubble_widths(ctx: &LayoutContext) {
|
||||
match self.kind {
|
||||
match self {
|
||||
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)
|
||||
_ => fail fmt!("Tried to bubble_widths of flow: %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
fn assign_widths(ctx: &LayoutContext) {
|
||||
match self.kind {
|
||||
match self {
|
||||
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)
|
||||
_ => fail fmt!("Tried to assign_widths of flow: %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
fn assign_height(ctx: &LayoutContext) {
|
||||
match self.kind {
|
||||
match self {
|
||||
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)
|
||||
_ => fail fmt!("Tried to assign_height of flow: %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
fn build_display_list_recurse(builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
|
||||
offset: &Point2D<au>, list: &dl::DisplayList) {
|
||||
match self.kind {
|
||||
match self {
|
||||
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)
|
||||
_ => fail fmt!("Tried to build_display_list_recurse of flow: %?", self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,39 +171,39 @@ impl FlowContext {
|
|||
// Actual methods that do not require much flow-specific logic
|
||||
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 {
|
||||
match self {
|
||||
RootFlow(*) => match self.root().box {
|
||||
Some(box) if box.d().node == node => { blk(seed, box) },
|
||||
_ => seed
|
||||
},
|
||||
BlockFlow(d) => match d.box {
|
||||
BlockFlow(*) => match self.block().box {
|
||||
Some(box) if box.d().node == node => { blk(seed, box) },
|
||||
_ => seed
|
||||
},
|
||||
InlineFlow(d) => do d.boxes.foldl(seed) |acc, box| {
|
||||
InlineFlow(*) => do self.inline().boxes.foldl(seed) |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)
|
||||
_ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self)
|
||||
}
|
||||
}
|
||||
|
||||
pure fn iter_boxes_for_node<T>(node: Node, cb: pure fn&(@RenderBox) -> T) {
|
||||
match self.kind {
|
||||
RootFlow(d) => match d.box {
|
||||
match self {
|
||||
RootFlow(*) => match self.root().box {
|
||||
Some(box) if box.d().node == node => { cb(box); },
|
||||
_ => {}
|
||||
},
|
||||
BlockFlow(d) => match d.box {
|
||||
BlockFlow(*) => match self.block().box {
|
||||
Some(box) if box.d().node == node => { cb(box); },
|
||||
_ => {}
|
||||
},
|
||||
InlineFlow(d) => {
|
||||
for d.boxes.each |box| {
|
||||
InlineFlow(*) => {
|
||||
for self.inline().boxes.each |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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,7 +218,7 @@ impl FlowTree : tree::ReadMethods<@FlowContext> {
|
|||
}
|
||||
|
||||
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
|
||||
f(b.tree)
|
||||
f(b.d().tree)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +229,7 @@ impl FlowTree : tree::WriteMethods<@FlowContext> {
|
|||
}
|
||||
|
||||
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
|
||||
f(b.tree)
|
||||
f(b.d().tree)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,22 +256,28 @@ impl FlowContext : BoxedDebugMethods {
|
|||
|
||||
/* TODO: we need a string builder. This is horribly inefficient */
|
||||
fn debug_str(@self) -> ~str {
|
||||
let repr = match self.kind {
|
||||
InlineFlow(d) => {
|
||||
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
|
||||
let repr = match *self {
|
||||
InlineFlow(*) => {
|
||||
let mut s = self.inline().boxes.foldl(~"InlineFlow(children=", |s, box| {
|
||||
fmt!("%s %?", s, box.d().id)
|
||||
});
|
||||
s += ~")"; s
|
||||
},
|
||||
BlockFlow(d) => {
|
||||
match d.box {
|
||||
Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().d().id),
|
||||
BlockFlow(*) => {
|
||||
match self.block().box {
|
||||
Some(box) => fmt!("BlockFlow(box=b%?)", box.d().id),
|
||||
None => ~"BlockFlow",
|
||||
}
|
||||
},
|
||||
_ => fmt!("%?", self.kind)
|
||||
RootFlow(*) => {
|
||||
match self.root().box {
|
||||
Some(box) => fmt!("RootFlo(box=b%?)", box.d().id),
|
||||
None => ~"RootFlow",
|
||||
}
|
||||
},
|
||||
_ => ~"(Unknown flow)"
|
||||
};
|
||||
|
||||
fmt!("c%? %?", self.id, repr)
|
||||
fmt!("c%? %?", self.d().id, repr)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ fn InlineFlowData() -> InlineFlowData {
|
|||
trait InlineLayout {
|
||||
pure fn starts_inline_flow() -> bool;
|
||||
|
||||
pure fn access_inline<T>(fn(&&InlineFlowData) -> T) -> T;
|
||||
fn bubble_widths_inline(ctx: &LayoutContext);
|
||||
fn assign_widths_inline(ctx: &LayoutContext);
|
||||
fn assign_height_inline(ctx: &LayoutContext);
|
||||
|
@ -58,14 +57,7 @@ trait 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 {
|
||||
match self.kind {
|
||||
InlineFlow(d) => cb(d),
|
||||
_ => fail fmt!("Tried to access() data of InlineFlow, but this is a %?", self.kind)
|
||||
}
|
||||
}
|
||||
pure fn starts_inline_flow() -> bool { match self { InlineFlow(*) => true, _ => false } }
|
||||
|
||||
fn bubble_widths_inline(_ctx: &LayoutContext) {
|
||||
assert self.starts_inline_flow();
|
||||
|
@ -73,15 +65,13 @@ impl FlowContext : InlineLayout {
|
|||
let mut min_width = au(0);
|
||||
let mut pref_width = au(0);
|
||||
|
||||
do self.access_inline |d| {
|
||||
for d.boxes.each |box| {
|
||||
min_width = au::max(min_width, box.get_min_width());
|
||||
pref_width = au::max(pref_width, box.get_pref_width());
|
||||
}
|
||||
for self.inline().boxes.each |box| {
|
||||
min_width = au::max(min_width, box.get_min_width());
|
||||
pref_width = au::max(pref_width, box.get_pref_width());
|
||||
}
|
||||
|
||||
self.data.min_width = min_width;
|
||||
self.data.pref_width = pref_width;
|
||||
self.d().min_width = min_width;
|
||||
self.d().pref_width = pref_width;
|
||||
}
|
||||
|
||||
/* Recursively (top-down) determines the actual width of child
|
||||
|
@ -91,59 +81,56 @@ impl FlowContext : InlineLayout {
|
|||
assert self.starts_inline_flow();
|
||||
|
||||
/* Perform inline flow with the available width. */
|
||||
//let avail_width = self.data.position.size.width;
|
||||
//let avail_width = self.d().position.size.width;
|
||||
|
||||
let line_height = au::from_px(20);
|
||||
//let mut cur_x = au(0);
|
||||
let mut cur_y = au(0);
|
||||
|
||||
do self.access_inline |d| {
|
||||
for d.boxes.each |box| {
|
||||
/* TODO: actually do inline flow.
|
||||
- Create a working linebox, and successively put boxes
|
||||
into it, splitting if necessary.
|
||||
|
||||
- Set width and height for each positioned element based on
|
||||
where its chunks ended up.
|
||||
for self.inline().boxes.each |box| {
|
||||
/* TODO: actually do inline flow.
|
||||
- Create a working linebox, and successively put boxes
|
||||
into it, splitting if necessary.
|
||||
|
||||
- Set width and height for each positioned element based on
|
||||
where its chunks ended up.
|
||||
|
||||
- Save the dvec of this context's lineboxes. */
|
||||
- Save the dvec of this context's lineboxes. */
|
||||
|
||||
/* hack: until text box splitting is hoisted into this
|
||||
function, force "reflow" on TextBoxes. */
|
||||
match *box {
|
||||
@TextBox(*) => box.reflow_text(ctx),
|
||||
_ => {}
|
||||
}
|
||||
/* hack: until text box splitting is hoisted into this
|
||||
function, force "reflow" on TextBoxes. */
|
||||
match *box {
|
||||
@TextBox(*) => box.reflow_text(ctx),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
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)
|
||||
};
|
||||
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)
|
||||
};
|
||||
|
||||
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)
|
||||
};
|
||||
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)
|
||||
};
|
||||
|
||||
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|
|
||||
}
|
||||
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|
|
||||
|
||||
self.data.position.size.height = cur_y;
|
||||
|
||||
/* There are no child contexts, so stop here. */
|
||||
self.d().position.size.height = cur_y;
|
||||
|
||||
/* There are no child contexts, so stop here. */
|
||||
|
||||
// TODO: once there are 'inline-block' elements, this won't be
|
||||
// true. In that case, perform inline flow, and then set the
|
||||
// block flow context's width as the width of the
|
||||
// 'inline-block' box that created this flow.
|
||||
|
||||
} // fn assign_widths_inline
|
||||
// TODO: once there are 'inline-block' elements, this won't be
|
||||
// true. In that case, perform inline flow, and then set the
|
||||
// block flow context's width as the width of the
|
||||
// 'inline-block' box that created this flow.
|
||||
}
|
||||
|
||||
fn assign_height_inline(_ctx: &LayoutContext) {
|
||||
// Don't need to set box or ctx heights, since that is done
|
||||
|
@ -160,10 +147,8 @@ impl FlowContext : InlineLayout {
|
|||
|
||||
// TODO: once we form line boxes and have their cached bounds, we can be
|
||||
// smarter and not recurse on a line if nothing in it can intersect dirty
|
||||
do self.access_inline |d| {
|
||||
for d.boxes.each |box| {
|
||||
box.build_display_list(builder, dirty, offset, list)
|
||||
}
|
||||
for self.inline().boxes.each |box| {
|
||||
box.build_display_list(builder, dirty, offset, list)
|
||||
}
|
||||
|
||||
// TODO: should inline-block elements have flows as children
|
||||
|
|
|
@ -168,7 +168,7 @@ impl Layout {
|
|||
};
|
||||
// TODO: set options on the builder before building
|
||||
// TODO: be smarter about what needs painting
|
||||
layout_root.build_display_list(&builder, © layout_root.data.position, &dlist);
|
||||
layout_root.build_display_list(&builder, © layout_root.d().position, &dlist);
|
||||
self.render_task.send(render_task::RenderMsg(dlist));
|
||||
} // time(layout)
|
||||
} // BuildMsg
|
||||
|
|
|
@ -21,7 +21,6 @@ fn RootFlowData() -> RootFlowData {
|
|||
|
||||
trait RootLayout {
|
||||
pure fn starts_root_flow() -> bool;
|
||||
pure fn access_root<T>(fn(&&RootFlowData) -> T) -> T;
|
||||
|
||||
fn bubble_widths_root(ctx: &LayoutContext);
|
||||
fn assign_widths_root(ctx: &LayoutContext);
|
||||
|
@ -33,19 +32,12 @@ trait RootLayout {
|
|||
impl FlowContext : RootLayout {
|
||||
|
||||
pure fn starts_root_flow() -> bool {
|
||||
match self.kind {
|
||||
match self {
|
||||
RootFlow(*) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pure fn access_root<T>(cb:fn(&&RootFlowData) -> T) -> T {
|
||||
match self.kind {
|
||||
RootFlow(d) => cb(d),
|
||||
_ => fail fmt!("Tried to access() data of RootFlow, but this is a %?", self.kind)
|
||||
}
|
||||
}
|
||||
|
||||
/* defer to the block algorithm */
|
||||
fn bubble_widths_root(ctx: &LayoutContext) {
|
||||
assert self.starts_root_flow();
|
||||
|
@ -55,7 +47,7 @@ impl FlowContext : RootLayout {
|
|||
fn assign_widths_root(ctx: &LayoutContext) {
|
||||
assert self.starts_root_flow();
|
||||
|
||||
self.data.position = copy ctx.screen_size;
|
||||
self.d().position = copy ctx.screen_size;
|
||||
self.assign_widths_block(ctx)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue