Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor flow #416

Merged
merged 12 commits into from May 7, 2013

servo: Refactor the `Flow` type to save memory and allow upcasting an…

…d downcasting more naturally
  • Loading branch information
pcwalton committed May 6, 2013
commit 1d7a3f916d56220206d4f1b086a334917c009eb8
@@ -71,7 +71,7 @@ pub enum NodeTypeId {

pub struct LayoutData {
style: Option<CompleteSelectResults>,
flow: Option<@mut FlowContext>,
flow: Option<FlowContext>,
}

impl LayoutData {
@@ -2,12 +2,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Block layout.
//! CSS block layout.

use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::flow::{BlockFlow, FlowContext, InlineBlockFlow, RootFlow};
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow, RootFlow};
use layout::inline::InlineLayout;

use au = gfx::geometry;
@@ -18,23 +18,33 @@ use gfx::display_list::DisplayList;
use gfx::geometry::Au;

pub struct BlockFlowData {
/// Data common to all flows.
common: FlowData,

/// The associated render box.
box: Option<@mut RenderBox>
}

pub fn BlockFlowData() -> BlockFlowData {
BlockFlowData {
box: None
impl BlockFlowData {
pub fn new(common: FlowData) -> BlockFlowData {
BlockFlowData {
common: common,
box: None,
}
}
}

/// NB: These are part of FlowContext, not part of BlockFlowData, because the root flow calls these
/// as well. It is not clear to me whether this needs to be the case, or whether `RootFlow` can be
/// merged into this.
pub trait BlockLayout {
fn starts_block_flow(&self) -> bool;
fn with_block_box(@mut self, &fn(box: &@mut RenderBox) -> ()) -> ();
fn with_block_box(&self, &fn(box: &@mut RenderBox) -> ()) -> ();

fn bubble_widths_block(@mut self, ctx: &LayoutContext);
fn assign_widths_block(@mut self, ctx: &LayoutContext);
fn assign_height_block(@mut self, ctx: &LayoutContext);
fn build_display_list_block(@mut self,
fn bubble_widths_block(&self, ctx: &LayoutContext);
fn assign_widths_block(&self, ctx: &LayoutContext);
fn assign_height_block(&self, ctx: &LayoutContext);
fn build_display_list_block(&self,
a: &DisplayListBuilder,
b: &Rect<Au>,
c: &Point2D<Au>,
@@ -49,17 +59,21 @@ impl BlockLayout for FlowContext {
}
}

/* 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. */
fn with_block_box(@mut self, cb: &fn(box: &@mut RenderBox) -> ()) -> () {
/// 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.
fn with_block_box(&self, callback: &fn(box: &@mut RenderBox) -> ()) -> () {
match *self {
BlockFlow(*) => {
let box = self.block().box;
for box.each |b| { cb(b); }
for box.each |b| {
callback(b);
}
},
RootFlow(*) => {
let mut box = self.root().box;
for box.each |b| { cb(b); }
for box.each |b| {
callback(b);
}
},
_ => fail!(fmt!("Tried to do something with_block_box(), but this is a %?", self))
}
@@ -74,7 +88,7 @@ impl BlockLayout for FlowContext {
/* TODO: floats */
/* TODO: absolute contexts */
/* TODO: inline-blocks */
fn bubble_widths_block(@mut self, ctx: &LayoutContext) {
fn bubble_widths_block(&self, ctx: &LayoutContext) {
assert!(self.starts_block_flow());

let mut min_width = Au(0);
@@ -84,8 +98,10 @@ impl BlockLayout for FlowContext {
for self.each_child |child_ctx| {
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());

min_width = au::max(min_width, child_ctx.d().min_width);
pref_width = au::max(pref_width, child_ctx.d().pref_width);
do child_ctx.with_common_info |child_info| {
min_width = au::max(min_width, child_info.min_width);
pref_width = au::max(pref_width, child_info.pref_width);
}
}

/* if not an anonymous block context, add in block box's widths.
@@ -95,8 +111,10 @@ impl BlockLayout for FlowContext {
pref_width = pref_width.add(&box.get_pref_width(ctx));
}

self.d().min_width = min_width;
self.d().pref_width = pref_width;
do self.with_common_info |info| {
info.min_width = min_width;
info.pref_width = pref_width;
}
}

/* Recursively (top-down) determines the actual width of child
@@ -106,10 +124,10 @@ impl BlockLayout for FlowContext {
Dual boxes consume some width first, and the remainder is assigned to
all child (block) contexts. */

fn assign_widths_block(@mut self, _ctx: &LayoutContext) {
fn assign_widths_block(&self, _ctx: &LayoutContext) {
assert!(self.starts_block_flow());

let mut remaining_width = self.d().position.size.width;
let mut remaining_width = self.with_common_info(|info| info.position.size.width);
let mut _right_used = Au(0);
let mut left_used = Au(0);

@@ -123,22 +141,28 @@ impl BlockLayout for FlowContext {

for self.each_child |child_ctx| {
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
child_ctx.d().position.origin.x = left_used;
child_ctx.d().position.size.width = remaining_width;
do child_ctx.with_common_info |child_info| {
child_info.position.origin.x = left_used;
child_info.position.size.width = remaining_width;
}
}
}

fn assign_height_block(@mut self, _ctx: &LayoutContext) {
fn assign_height_block(&self, _ctx: &LayoutContext) {
assert!(self.starts_block_flow());

let mut cur_y = Au(0);

for self.each_child |child_ctx| {
child_ctx.d().position.origin.y = cur_y;
cur_y += child_ctx.d().position.size.height;
do child_ctx.with_common_info |child_info| {
child_info.position.origin.y = cur_y;
cur_y += child_info.position.size.height;
}
}

self.d().position.size.height = cur_y;
do self.with_common_info |info| {
info.position.size.height = cur_y;
}

let _used_top = Au(0);
let _used_bot = Au(0);
@@ -150,9 +174,11 @@ impl BlockLayout for FlowContext {
}
}

fn build_display_list_block(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Cell<DisplayList>) {

fn build_display_list_block(&self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
offset: &Point2D<Au>,
list: &Cell<DisplayList>) {
assert!(self.starts_block_flow());

// add box that starts block context
@@ -71,13 +71,13 @@ padding, backgrounds. It is analogous to a CSS nonreplaced content box.
*/
pub struct RenderBoxData {
/* originating DOM node */
node : AbstractNode,
node: AbstractNode,
/* reference to containing flow context, which this box
participates in */
ctx : @mut FlowContext,
ctx: FlowContext,
/* position of this box relative to owning flow */
position : Rect<Au>,
font_size : Length,
position: Rect<Au>,
font_size: Length,
/* TODO (Issue #87): debug only */
id: int
}
@@ -103,7 +103,7 @@ pub enum SplitBoxResult {
SplitDidNotFit(Option<@mut RenderBox>, Option<@mut RenderBox>)
}

pub fn RenderBoxData(node: AbstractNode, ctx: @mut FlowContext, id: int) -> RenderBoxData {
pub fn RenderBoxData(node: AbstractNode, ctx: FlowContext, id: int) -> RenderBoxData {
RenderBoxData {
node : node,
ctx : ctx,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.