Skip to content

Commit

Permalink
Added the ability to compute heights from parent heights and to layou…
Browse files Browse the repository at this point in the history
…t specified heights
  • Loading branch information
mmeyerho committed Aug 10, 2012
1 parent 470a88f commit 95d0998
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 72 deletions.
23 changes: 17 additions & 6 deletions src/servo/dom/style.rs
Expand Up @@ -3,7 +3,7 @@ import util::color::Color;
#[doc = "
Defines how css rules, both selectors and style specifications, are
stored. CSS selector-matching rules, as presented by
http://www.w3.org/TR/CSS2/selector.html are represented by nested, structural types,
http://www.w3.org/TR/CSS2/selector.html are represented by nested types.
"]

enum DisplayType {
Expand All @@ -15,13 +15,8 @@ enum DisplayType {
enum Unit {
Auto,
Percent(float),
In(float),
Mm(float),
Cm(float),
Em(float),
Ex(float),
Pt(float),
Pc(float),
Px(float)
}

Expand Down Expand Up @@ -51,3 +46,19 @@ enum Selector{
type Rule = (~[~Selector], ~[StyleDeclaration]);

type Stylesheet = ~[~Rule];

#[doc="Convert between units measured in millimeteres and pixels"]
pure fn MmToPx(u : Unit) -> Unit {
match u {
Mm(m) => Px(m * 3.7795),
_ => fail ~"Calling MmToPx on a unit that is not a Mm"
}
}

#[doc="Convert between units measured in points and pixels"]
pure fn PtToPx(u : Unit) -> Unit {
match u {
Pt(m) => Px(m * 1.3333),
_ => fail ~"Calling PtToPx on a unit that is not a Pt"
}
}
59 changes: 45 additions & 14 deletions src/servo/layout/base.rs
Expand Up @@ -11,9 +11,10 @@ import geom::rect::Rect;
import geom::size::Size2D;
import image::base::{image, load};
import util::tree;
import util::color::{Color, css_colors};
import style::style::SpecifiedStyle;
import util::color::Color;
import text::TextBox;
import traverse::extended_full_traversal;
import style::style::{SpecifiedStyle};
import vec::{push, push_all};

import arc::{arc, clone};
Expand Down Expand Up @@ -155,8 +156,17 @@ impl BTree : tree::WriteMethods<@Box> {
}
}

// Private methods
impl @Box {
#[doc="The main reflow routine."]
fn reflow() {
match self.kind {
BlockBox => self.reflow_block(),
InlineBox => self.reflow_inline(),
IntrinsicBox(size) => self.reflow_intrinsic(*size),
TextBoxKind(subbox) => self.reflow_text(subbox)
}
}

#[doc="Dumps the box tree, for debugging, with indentation."]
fn dump_indent(indent: uint) {
let mut s = ~"";
Expand All @@ -173,16 +183,37 @@ impl @Box {
}
}

// Public methods
#[doc = "
Set your width to the maximum available width and return the
maximum available width any children can use. Currently children
are just given the same available width.
"]
fn give_kids_width(+available_width : au, box : @Box) -> au {
// TODO: give smaller available widths if the width of the
// containing box is constrained
match box.kind {
BlockBox | InlineBox => box.bounds.size.width = available_width,
IntrinsicBox(*) | TextBoxKind(*) => { }
}

available_width
}

#[doc="Wrapper around reflow so it can be passed to traverse"]
fn reflow_wrapper(b : @Box) {
b.reflow();
}

impl @Box {
#[doc="The main reflow routine."]
fn reflow(available_width: au) {
match self.kind {
BlockBox => self.reflow_block(available_width),
InlineBox => self.reflow_inline(available_width),
IntrinsicBox(size) => self.reflow_intrinsic(*size),
TextBoxKind(subbox) => self.reflow_text(available_width, subbox)
}
#[doc="
Run a parallel traversal over the layout tree rooted at
this box. On the top-down traversal give each box the
available width determined by their parent and on the
bottom-up traversal reflow each box based on their
attributes and their children's sizes.
"]
fn reflow_subtree(available_width : au) {
extended_full_traversal(self, available_width, give_kids_width, reflow_wrapper);
}

#[doc="The trivial reflow routine for instrinsically-sized frames."]
Expand All @@ -200,7 +231,7 @@ impl @Box {

// Debugging

trait PrivateNodeMethods {
trait PrivateNodeMethods{
fn dump_indent(ident: uint);
}

Expand Down Expand Up @@ -292,7 +323,7 @@ mod test {
tree::add_child(BTree, b3, b1);
tree::add_child(BTree, b3, b2);

b3.reflow_block(au(100));
b3.reflow_subtree(au(100));
let fb = flat_bounds(b3);
#debug["fb=%?", fb];
assert fb == ~[geometry::box(au(0), au(0), au(10), au(10)), // n0
Expand Down
27 changes: 20 additions & 7 deletions src/servo/layout/block.rs
@@ -1,19 +1,20 @@
#[doc="Block layout."]

import dom::style::{Px, Mm, Pt, Auto, Percent, Unit};
import geom::point::Point2D;
import geom::size::Size2D;
import gfx::geometry::au;
import gfx::geometry::{px_to_au, au};
import util::tree;
import base::{Box, BlockBox, BTree};

trait BlockLayoutMethods {
fn reflow_block(available_widh: au);
fn reflow_block();
}

#[doc="The public block layout methods."]
impl @Box : BlockLayoutMethods {
#[doc="The main reflow routine for block layout."]
fn reflow_block(available_width: au) {
fn reflow_block() {
assert self.kind == BlockBox;

#debug["starting reflow block"];
Expand All @@ -24,19 +25,31 @@ impl @Box : BlockLayoutMethods {
// This routine:
// - generates root.bounds.size
// - generates root.bounds.origin for each child
// - and recursively computes the bounds for each child

let mut current_height = 0;

// Find the combined height of all the children and mark the
// relative heights of the children in the box
for tree::each_child(BTree, self) |c| {
let mut blk_available_width = available_width;
// FIXME subtract borders, margins, etc
c.bounds.origin = Point2D(au(0), au(current_height));
c.reflow(blk_available_width);
current_height += *c.bounds.size.height;
}

let height = match self.appearance.height {
Px(p) => px_to_au(p.to_int()),
Auto => au(current_height),
_ => fail ~"inhereit_height failed, height is neither a Px or auto"
};

// FIXME: Width is wrong in the calculation below.
self.bounds.size = Size2D(available_width, au(current_height));
let width = match self.appearance.width {
Px(p) => px_to_au(p.to_int()),
Auto => self.bounds.size.width, // Do nothing here, width was set by top-down pass
_ => fail ~"inhereit_height failed, width is neither a Px or auto"
};

self.bounds.size = Size2D(width, height);

#debug["reflow_block size=%?", copy self.bounds];
}
Expand Down
8 changes: 4 additions & 4 deletions src/servo/layout/display_list_builder.rs
Expand Up @@ -118,7 +118,7 @@ fn should_convert_text_boxes_to_solid_color_background_items() {

let subbox = match check b.kind { TextBoxKind(subbox) => subbox };

b.reflow_text(px_to_au(800), subbox);
b.reflow_text(subbox);
let list = dvec();
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));

Expand All @@ -139,7 +139,7 @@ fn should_convert_text_boxes_to_text_items() {

let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };

b.reflow_text(px_to_au(800), subbox);
b.reflow_text(subbox);
let list = dvec();
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));

Expand All @@ -159,7 +159,7 @@ fn should_calculate_the_bounds_of_the_text_box_background_color() {

let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };

b.reflow_text(px_to_au(800), subbox);
b.reflow_text(subbox);
let list = dvec();
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));

Expand All @@ -181,7 +181,7 @@ fn should_calculate_the_bounds_of_the_text_items() {

let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };

b.reflow_text(px_to_au(800), subbox);
b.reflow_text(subbox);
let list = dvec();
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));

Expand Down
14 changes: 8 additions & 6 deletions src/servo/layout/inline.rs
Expand Up @@ -8,30 +8,32 @@ import util::tree;
import base::{Box, InlineBox, BTree};

trait InlineLayout {
fn reflow_inline(available_width: au);
fn reflow_inline();
}

#[doc="The main reflow routine for inline layout."]
impl @Box : InlineLayout {
fn reflow_inline(available_width: au) {
fn reflow_inline() {
assert self.kind == InlineBox;

#debug["starting reflow inline"];

// FIXME: This is clownshoes inline layout and is not even close to
// correct.
let y = 0;
let mut x = 0, inline_available_width = *available_width;
let mut x = 0;
let mut current_height = 0;

// loop over children and set them at the proper horizontal offset
for tree::each_child(BTree, self) |kid| {
kid.bounds.origin = Point2D(au(x), au(y));
kid.reflow(au(inline_available_width));
inline_available_width -= *kid.bounds.size.width;
x += *kid.bounds.size.width;
current_height = int::max(current_height, *kid.bounds.size.height);
}

self.bounds.size = Size2D(available_width, au(current_height));
// The maximum available width should have been set in the top-down pass
self.bounds.size = Size2D(au(int::max(x, *self.bounds.size.width)),
au(current_height));

#debug["reflow_inline size=%?", copy self.bounds];
}
Expand Down
2 changes: 1 addition & 1 deletion src/servo/layout/layout_task.rs
Expand Up @@ -42,7 +42,7 @@ fn Layout(renderer: Renderer) -> Layout {
this_box.dump();

this_box.apply_css_style();
this_box.reflow(px_to_au(800));
this_box.reflow_subtree(px_to_au(800));

let dlist = build_display_list(this_box);
renderer.send(renderer::RenderMsg(dlist));
Expand Down

0 comments on commit 95d0998

Please sign in to comment.