auto merge of #753 : metajack/servo/inline-block, r=eric93

r? @eric93
This commit is contained in:
bors-servo 2013-08-21 14:24:47 -07:00
commit 11911b901f
2 changed files with 107 additions and 32 deletions

View file

@ -276,11 +276,23 @@ impl<'self> BoxGenerator<'self> {
} }
enum BoxGenResult<'self> { enum BoxGenResult<'self> {
NoGenerator, NoGenerator,
ParentGenerator, ParentGenerator,
SiblingGenerator, SiblingGenerator,
NewGenerator(BoxGenerator<'self>), NewGenerator(BoxGenerator<'self>),
Mixed(BoxGenerator<'self>, ~BoxGenResult<'self>), /// Start a new generator, but also switch the parent out for the
/// grandparent, ending the parent generator.
ReparentingGenerator(BoxGenerator<'self>),
Mixed(BoxGenerator<'self>, ~BoxGenResult<'self>),
}
/// Determines whether the result of child box construction needs to reparent
/// or not. Reparenting is needed when a block flow is a child of an inline;
/// in that case, we need to let the level up the stack no to end the parent
/// genertor and continue with the grandparent.
enum BoxConstructResult<'self> {
Normal(Option<BoxGenerator<'self>>),
Reparent(BoxGenerator<'self>),
} }
impl LayoutTreeBuilder { impl LayoutTreeBuilder {
@ -291,34 +303,53 @@ impl LayoutTreeBuilder {
/// Creates necessary box(es) and flow context(s) for the current DOM node, /// Creates necessary box(es) and flow context(s) for the current DOM node,
/// and recurses on its children. /// and recurses on its children.
pub fn construct_recursively<'a>(&mut self, pub fn construct_recursively<'a>(&mut self,
layout_ctx: &LayoutContext, layout_ctx: &LayoutContext,
cur_node: AbstractNode<LayoutView>, cur_node: AbstractNode<LayoutView>,
mut parent_generator: BoxGenerator<'a>, mut grandparent_generator: Option<BoxGenerator<'a>>,
mut prev_sibling_generator: Option<BoxGenerator<'a>>) mut parent_generator: BoxGenerator<'a>,
-> Option<BoxGenerator<'a>> { mut prev_sibling_generator: Option<BoxGenerator<'a>>)
-> BoxConstructResult<'a> {
debug!("Considering node: %s", cur_node.debug_str()); debug!("Considering node: %s", cur_node.debug_str());
let box_gen_result = { let box_gen_result = {
let grandparent_gen_ref = match grandparent_generator {
Some(ref mut generator) => Some(generator),
None => None,
};
let sibling_gen_ref = match prev_sibling_generator { let sibling_gen_ref = match prev_sibling_generator {
Some(ref mut generator) => Some(generator), Some(ref mut generator) => Some(generator),
None => None, None => None,
}; };
self.box_generator_for_node(cur_node, &mut parent_generator, sibling_gen_ref) self.box_generator_for_node(cur_node, grandparent_gen_ref, &mut parent_generator, sibling_gen_ref)
}; };
let mut reparent = false;
debug!("result from generator_for_node: %?", &box_gen_result); debug!("result from generator_for_node: %?", &box_gen_result);
// Skip over nodes that don't belong in the flow tree // Skip over nodes that don't belong in the flow tree
let (this_generator, next_generator) = let (this_generator, next_generator) =
match box_gen_result { match box_gen_result {
NoGenerator => return prev_sibling_generator, NoGenerator => return Normal(prev_sibling_generator),
ParentGenerator => (parent_generator, None), ParentGenerator => {
do parent_generator.with_clone |clone| {
(clone, None)
}
}
SiblingGenerator => (prev_sibling_generator.take_unwrap(), None), SiblingGenerator => (prev_sibling_generator.take_unwrap(), None),
NewGenerator(gen) => (gen, None), NewGenerator(gen) => (gen, None),
ReparentingGenerator(gen) => {
reparent = true;
(gen, None)
}
Mixed(gen, next_gen) => (gen, Some(match *next_gen { Mixed(gen, next_gen) => (gen, Some(match *next_gen {
ParentGenerator => parent_generator, ParentGenerator => {
do parent_generator.with_clone |clone| {
clone
}
}
SiblingGenerator => prev_sibling_generator.take_unwrap(), SiblingGenerator => prev_sibling_generator.take_unwrap(),
_ => fail!("Unexpect BoxGenResult") _ => fail!("Unexpect BoxGenResult")
})) }))
}; };
@ -329,12 +360,30 @@ impl LayoutTreeBuilder {
debug!("point b: %s", cur_node.debug_str()); debug!("point b: %s", cur_node.debug_str());
// recurse on child nodes. // recurse on child nodes.
let prev_gen_cell = Cell::new(None); let prev_gen_cell = Cell::new(Normal(None));
for child_node in cur_node.children() { for child_node in cur_node.children() {
do this_generator.with_clone |clone| { do parent_generator.with_clone |grandparent_clone| {
let mut prev_generator = prev_gen_cell.take(); let grandparent_clone_cell = Cell::new(Some(grandparent_clone));
prev_generator = self.construct_recursively(layout_ctx, child_node, clone, prev_generator); do this_generator.with_clone |parent_clone| {
prev_gen_cell.put_back(prev_generator); match prev_gen_cell.take() {
Normal(prev_gen) => {
let prev_generator = self.construct_recursively(layout_ctx,
child_node,
grandparent_clone_cell.take(),
parent_clone,
prev_gen);
prev_gen_cell.put_back(prev_generator);
}
Reparent(prev_gen) => {
let prev_generator = self.construct_recursively(layout_ctx,
child_node,
None,
grandparent_clone_cell.take().unwrap(),
Some(prev_gen));
prev_gen_cell.put_back(prev_generator);
}
}
}
} }
} }
@ -342,18 +391,25 @@ impl LayoutTreeBuilder {
self.simplify_children_of_flow(layout_ctx, this_generator.flow); self.simplify_children_of_flow(layout_ctx, this_generator.flow);
match next_generator { match next_generator {
Some(n_gen) => Some(n_gen), Some(n_gen) => Normal(Some(n_gen)),
None => Some(this_generator), None => {
if reparent {
Reparent(this_generator)
} else {
Normal(Some(this_generator))
}
}
} }
} }
pub fn box_generator_for_node<'a>(&mut self, pub fn box_generator_for_node<'a>(&mut self,
node: AbstractNode<LayoutView>, node: AbstractNode<LayoutView>,
parent_generator: &mut BoxGenerator<'a>, grandparent_generator: Option<&mut BoxGenerator<'a>>,
mut sibling_generator: Option<&mut BoxGenerator<'a>>) parent_generator: &mut BoxGenerator<'a>,
-> BoxGenResult<'a> { mut sibling_generator: Option<&mut BoxGenerator<'a>>)
-> BoxGenResult<'a> {
let display = if node.is_element() { let display = if node.is_element() {
match node.style().display(node.is_root()) { match node.style().display(node.is_root()) {
@ -466,8 +522,20 @@ impl LayoutTreeBuilder {
} }
} }
// TODO(eatkinson): blocks that are children of inlines need // blocks that are children of inlines need to split their parent
// to split their parent flows. // flows.
(CSSDisplayBlock, & &InlineFlow(*), _) => {
match grandparent_generator {
None => fail!("expected to have a grandparent block flow"),
Some(grandparent_gen) => {
assert!(grandparent_gen.flow.is_block_like());
let block_gen = self.create_child_generator(node, grandparent_gen, Flow_Block);
return ReparentingGenerator(block_gen);
}
}
}
_ => return ParentGenerator _ => return ParentGenerator
}; };
@ -590,7 +658,7 @@ impl LayoutTreeBuilder {
let mut new_flow = self.make_flow(Flow_Root, root); let mut new_flow = self.make_flow(Flow_Root, root);
{ {
let new_generator = BoxGenerator::new(&mut new_flow); let new_generator = BoxGenerator::new(&mut new_flow);
self.construct_recursively(layout_ctx, root, new_generator, None); self.construct_recursively(layout_ctx, root, None, new_generator, None);
} }
return Ok(new_flow) return Ok(new_flow)
} }

View file

@ -130,7 +130,14 @@ impl FlowContext {
} }
impl<'self> FlowContext { impl<'self> FlowContext {
pub fn leaf(&self) -> bool { pub fn is_block_like(&self) -> bool {
match *self {
BlockFlow(*) | FloatFlow(*) => true,
_ => false,
}
}
pub fn is_leaf(&self) -> bool {
do self.with_base |base| { do self.with_base |base| {
base.children.len() == 0 base.children.len() == 0
} }