Merge remote-tracking branch 'origin/master' into pcwalton-master

Conflicts:
	src/components/main/layout/box_builder.rs
This commit is contained in:
Jack Moffitt 2013-06-10 21:31:11 -06:00
commit 5425154f96
14 changed files with 252 additions and 193 deletions

View file

@ -112,14 +112,14 @@ pub impl<'self> FontContext {
debug!("(create font group) --- starting ---"); debug!("(create font group) --- starting ---");
let list = self.get_font_list();
// TODO(Issue #193): make iteration over 'font-family' more robust. // TODO(Issue #193): make iteration over 'font-family' more robust.
for str::each_split_char(style.families, ',') |family| { for str::each_split_char(style.families, ',') |family| {
let family_name = str::trim(family); let family_name = str::trim(family);
let transformed_family_name = self.transform_family(family_name); let transformed_family_name = self.transform_family(family_name);
debug!("(create font group) transformed family is `%s`", transformed_family_name); debug!("(create font group) transformed family is `%s`", transformed_family_name);
let list = self.get_font_list();
let result = list.find_font_in_family(transformed_family_name, style); let result = list.find_font_in_family(transformed_family_name, style);
let mut found = false; let mut found = false;
for result.each |font_entry| { for result.each |font_entry| {
@ -134,6 +134,16 @@ pub impl<'self> FontContext {
} }
} }
let last_resort = FontList::get_last_resort_font_families();
for last_resort.each |family| {
let result = list.find_font_in_family(*family,style);
for result.each |font_entry| {
let instance = Font::new_from_existing_handle(self, &font_entry.handle, style, self.backend);
do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); }
}
}
assert!(fonts.len() > 0); assert!(fonts.len() > 0);
// TODO(Issue #179): Split FontStyle into specified and used styles // TODO(Issue #179): Split FontStyle into specified and used styles
let used_style = copy *style; let used_style = copy *style;

View file

@ -19,6 +19,7 @@ pub type FontFamilyMap = HashMap<~str, @mut FontFamily>;
trait FontListHandleMethods { trait FontListHandleMethods {
fn get_available_families(&self, fctx: &FontContextHandle) -> FontFamilyMap; fn get_available_families(&self, fctx: &FontContextHandle) -> FontFamilyMap;
fn load_variations_for_family(&self, family: @mut FontFamily); fn load_variations_for_family(&self, family: @mut FontFamily);
fn get_last_resort_font_families() -> ~[~str];
} }
/// The platform-independent font list abstraction. /// The platform-independent font list abstraction.
@ -86,6 +87,11 @@ pub impl FontList {
// TODO(Issue #188): look up localized font family names if canonical name not found // TODO(Issue #188): look up localized font family names if canonical name not found
family.map(|f| **f) family.map(|f| **f)
} }
pub fn get_last_resort_font_families() -> ~[~str] {
let last_resort = FontListHandle::get_last_resort_font_families();
last_resort
}
} }
// Holds a specific font family, and the various // Holds a specific font family, and the various

View file

@ -125,6 +125,10 @@ pub impl FontListHandle {
FcObjectSetDestroy(object_set); FcObjectSetDestroy(object_set);
} }
} }
fn get_last_resort_font_families() -> ~[~str] {
~[~"Arial"]
}
} }
struct AutoPattern { struct AutoPattern {

View file

@ -55,4 +55,8 @@ pub impl FontListHandle {
family.entries.push(entry) family.entries.push(entry)
} }
} }
fn get_last_resort_font_families() -> ~[~str] {
~[~"Arial Unicode MS",~"Arial"]
}
} }

View file

@ -175,7 +175,9 @@ impl BlockFlowData {
/// Dual boxes consume some width first, and the remainder is assigned to all child (block) /// Dual boxes consume some width first, and the remainder is assigned to all child (block)
/// contexts. /// contexts.
pub fn assign_widths_block(@mut self, ctx: &LayoutContext) { pub fn assign_widths_block(@mut self, ctx: &LayoutContext) {
debug!("assign_widths_block: assigning width for flow %?", self.common.id);
if self.is_root { if self.is_root {
debug!("Setting root position");
self.common.position.origin = Au::zero_point(); self.common.position.origin = Au::zero_point();
self.common.position.size.width = ctx.screen_size.size.width; self.common.position.size.width = ctx.screen_size.size.width;
} }

View file

@ -626,7 +626,21 @@ pub impl RenderBox {
}); });
}, },
GenericRenderBoxClass(_) => {} GenericRenderBoxClass(_) => {
debug!("%?", {
// Compute the text box bounds and draw a border surrounding them.
do list.with_mut_ref |list| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
},
width: Au::from_px(1),
color: rgb(0, 0, 0).to_gfx_color(),
};
list.append_item(BorderDisplayItemClass(border_display_item))
}
});
}
ImageRenderBoxClass(image_box) => { ImageRenderBoxClass(image_box) => {
match image_box.image.get_image() { match image_box.image.get_image() {

View file

@ -14,8 +14,13 @@ use layout::flow::{AbsoluteFlow, BlockFlow, FloatFlow, Flow_Absolute, Flow_Block
use layout::flow::{Flow_Inline, Flow_InlineBlock, Flow_Root, Flow_Table, FlowContext}; use layout::flow::{Flow_Inline, Flow_InlineBlock, Flow_Root, Flow_Table, FlowContext};
use layout::flow::{FlowContextType, FlowData, InlineBlockFlow, InlineFlow, TableFlow}; use layout::flow::{FlowContextType, FlowData, InlineBlockFlow, InlineFlow, TableFlow};
use layout::inline::{InlineFlowData, InlineLayout}; use layout::inline::{InlineFlowData, InlineLayout};
use css::node_style::StyledNode;
use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock}; use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock};
use newcss::values::{CSSDisplayTable, CSSDisplayInlineTable, CSSDisplayListItem};
use newcss::values::{CSSDisplayTableRowGroup, CSSDisplayTableHeaderGroup, CSSDisplayTableFooterGroup};
use newcss::values::{CSSDisplayTableRow, CSSDisplayTableColumnGroup, CSSDisplayTableColumn};
use newcss::values::{CSSDisplayTableCell, CSSDisplayTableCaption};
use newcss::values::{CSSDisplayNone}; use newcss::values::{CSSDisplayNone};
use script::dom::element::*; use script::dom::element::*;
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId}; use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
@ -25,16 +30,16 @@ use servo_util::tree::{TreeNodeRef, TreeUtils};
pub struct LayoutTreeBuilder { pub struct LayoutTreeBuilder {
root_flow: Option<FlowContext>, root_flow: Option<FlowContext>,
next_cid: int,
next_bid: int, next_bid: int,
next_cid: int
} }
pub impl LayoutTreeBuilder { pub impl LayoutTreeBuilder {
fn new() -> LayoutTreeBuilder { fn new() -> LayoutTreeBuilder {
LayoutTreeBuilder { LayoutTreeBuilder {
root_flow: None, root_flow: None,
next_cid: -1,
next_bid: -1, next_bid: -1,
next_cid: -1
} }
} }
} }
@ -86,6 +91,8 @@ priv fn simulate_UA_display_rules(node: AbstractNode<LayoutView>) -> CSSDisplay
} }
impl BoxGenerator { impl BoxGenerator {
/* Debug ids only */
fn new(flow: FlowContext) -> BoxGenerator { fn new(flow: FlowContext) -> BoxGenerator {
debug!("Creating box generator for flow: %s", flow.debug_str()); debug!("Creating box generator for flow: %s", flow.debug_str());
BoxGenerator { BoxGenerator {
@ -110,14 +117,14 @@ impl BoxGenerator {
pub fn push_node(&mut self, pub fn push_node(&mut self,
ctx: &LayoutContext, ctx: &LayoutContext,
builder: &mut LayoutTreeBuilder, node: AbstractNode<LayoutView>,
node: AbstractNode<LayoutView>) { builder: &mut LayoutTreeBuilder) {
debug!("BoxGenerator[f%d]: pushing node: %s", self.flow.id(), node.debug_str()); debug!("BoxGenerator[f%d]: pushing node: %s", self.flow.id(), node.debug_str());
// first, determine the box type, based on node characteristics // first, determine the box type, based on node characteristics
let simulated_display = simulate_UA_display_rules(node); let simulated_display = simulate_UA_display_rules(node);
// TODO: remove this once UA styles work // TODO: remove this once UA styles work
let box_type = builder.decide_box_type(node, simulated_display); let box_type = self.decide_box_type(node, simulated_display);
debug!("BoxGenerator[f%d]: point a", self.flow.id()); debug!("BoxGenerator[f%d]: point a", self.flow.id());
@ -129,7 +136,7 @@ impl BoxGenerator {
// if a leaf, make a box. // if a leaf, make a box.
if node.is_leaf() { if node.is_leaf() {
let new_box = builder.make_box(ctx, box_type, node, self.flow); let new_box = self.make_box(ctx, box_type, node, self.flow, builder);
inline.boxes.push(new_box); inline.boxes.push(new_box);
} else if self.inline_spacers_needed_for_node(node) { } else if self.inline_spacers_needed_for_node(node) {
// else, maybe make a spacer for "left" margin, border, padding // else, maybe make a spacer for "left" margin, border, padding
@ -142,7 +149,7 @@ impl BoxGenerator {
}, },
BlockFlow(block) => { BlockFlow(block) => {
debug!("BoxGenerator[f%d]: point b", block.common.id); debug!("BoxGenerator[f%d]: point b", block.common.id);
let new_box = builder.make_box(ctx, box_type, node, self.flow); let new_box = self.make_box(ctx, box_type, node, self.flow, builder);
debug!("BoxGenerator[f%d]: attaching box[b%d] to block flow (node: %s)", debug!("BoxGenerator[f%d]: attaching box[b%d] to block flow (node: %s)",
block.common.id, block.common.id,
@ -158,7 +165,6 @@ impl BoxGenerator {
pub fn pop_node(&mut self, pub fn pop_node(&mut self,
ctx: &LayoutContext, ctx: &LayoutContext,
_builder: &LayoutTreeBuilder,
node: AbstractNode<LayoutView>) { node: AbstractNode<LayoutView>) {
debug!("BoxGenerator[f%d]: popping node: %s", self.flow.id(), node.debug_str()); debug!("BoxGenerator[f%d]: popping node: %s", self.flow.id(), node.debug_str());
@ -189,148 +195,106 @@ impl BoxGenerator {
_ => warn!("pop_node() not implemented for flow %?", self.flow.id()), _ => warn!("pop_node() not implemented for flow %?", self.flow.id()),
} }
} }
}
struct BuilderContext { /// Disambiguate between different methods here instead of inlining, since each case has very
default_collector: @mut BoxGenerator, /// different complexity.
priv inline_collector: Option<@mut BoxGenerator> fn make_box(&mut self,
} layout_ctx: &LayoutContext,
ty: RenderBoxType,
impl BuilderContext {
fn new(collector: @mut BoxGenerator) -> BuilderContext {
{
let collector = &mut *collector;
debug!("Creating new BuilderContext for flow: %s", collector.flow.debug_str());
}
BuilderContext {
default_collector: collector,
inline_collector: None,
}
}
fn clone(self) -> BuilderContext {
debug!("BuilderContext: cloning context");
copy self
}
priv fn attach_child_flow(&self, child: FlowContext) {
let default_collector = &mut *self.default_collector;
debug!("BuilderContext: Adding child flow f%? of f%?",
default_collector.flow.id(),
child.id());
default_collector.flow.add_child(child);
}
priv fn create_child_flow_of_type(&self,
flow_type: FlowContextType,
builder: &mut LayoutTreeBuilder,
node: AbstractNode<LayoutView>) -> BuilderContext {
let new_flow = builder.make_flow(flow_type, node);
self.attach_child_flow(new_flow);
BuilderContext::new(@mut BoxGenerator::new(new_flow))
}
priv fn make_inline_collector(&mut self,
builder: &mut LayoutTreeBuilder,
node: AbstractNode<LayoutView>)
-> BuilderContext {
debug!("BuilderContext: making new inline collector flow");
let new_flow = builder.make_flow(Flow_Inline, node);
let new_generator = @mut BoxGenerator::new(new_flow);
self.inline_collector = Some(new_generator);
self.attach_child_flow(new_flow);
BuilderContext::new(new_generator)
}
priv fn get_inline_collector(&mut self,
builder: &mut LayoutTreeBuilder,
node: AbstractNode<LayoutView>)
-> BuilderContext {
match copy self.inline_collector {
Some(collector) => BuilderContext::new(collector),
None => self.make_inline_collector(builder, node)
}
}
priv fn clear_inline_collector(&mut self) {
self.inline_collector = None;
}
// returns a context for the current node, or None if the document subtree rooted
// by the node should not generate a layout tree. For example, nodes with style 'display:none'
// should just not generate any flows or boxes.
fn containing_context_for_node(&mut self,
node: AbstractNode<LayoutView>, node: AbstractNode<LayoutView>,
flow_context: FlowContext,
builder: &mut LayoutTreeBuilder) builder: &mut LayoutTreeBuilder)
-> Option<BuilderContext> { -> RenderBox {
// TODO: remove this once UA styles work let base = RenderBoxBase::new(node, flow_context, builder.next_box_id());
// TODO: handle interactions with 'float', 'position' (CSS 2.1, Section 9.7) let result = match ty {
let simulated_display = match simulate_UA_display_rules(node) { RenderBox_Generic => GenericRenderBoxClass(@mut base),
CSSDisplayNone => return None, // tree ends here if 'display: none' RenderBox_Text => UnscannedTextRenderBoxClass(@mut UnscannedTextRenderBox::new(base)),
v => v RenderBox_Image => self.make_image_box(layout_ctx, node, base),
}; };
debug!("BoxGenerator: created box: %s", result.debug_str());
let containing_context = match (simulated_display, self.default_collector.flow) { result
(CSSDisplayBlock, BlockFlow(info)) => match (info.is_root, node.parent_node()) {
// If this is the root node, then use the root flow's
// context. Otherwise, make a child block context.
(true, Some(_)) => { self.create_child_flow_of_type(Flow_Block, builder, node) }
(true, None) => { self.clone() }
(false, _) => {
self.clear_inline_collector();
self.create_child_flow_of_type(Flow_Block, builder, node)
} }
},
(CSSDisplayInline, InlineFlow(*)) => self.clone(),
(CSSDisplayInlineBlock, InlineFlow(*)) => self.clone(),
(CSSDisplayInline, BlockFlow(*)) => self.get_inline_collector(builder, node),
(CSSDisplayInlineBlock, BlockFlow(*)) => self.get_inline_collector(builder, node),
_ => self.clone()
};
Some(containing_context) fn make_image_box(&mut self,
layout_ctx: &LayoutContext,
node: AbstractNode<LayoutView>,
base: RenderBoxBase)
-> RenderBox {
assert!(node.is_image_element());
do node.with_imm_image_element |image_element| {
if image_element.image.is_some() {
// FIXME(pcwalton): Don't copy URLs.
let url = copy *image_element.image.get_ref();
ImageRenderBoxClass(@mut ImageRenderBox::new(base, url, layout_ctx.image_cache))
} else {
info!("Tried to make image box, but couldn't find image. Made generic box \
instead.");
GenericRenderBoxClass(@mut base)
} }
}
}
fn decide_box_type(&self, node: AbstractNode<LayoutView>, _: CSSDisplay) -> RenderBoxType {
if node.is_text() {
RenderBox_Text
} else if node.is_image_element() {
do node.with_imm_image_element |image_element| {
match image_element.image {
Some(_) => RenderBox_Image,
None => RenderBox_Generic,
}
}
} else if node.is_element() {
RenderBox_Generic
} else {
fail!(~"Hey, doctypes and comments shouldn't get here! They are display:none!")
}
}
} }
pub impl LayoutTreeBuilder { pub impl LayoutTreeBuilder {
/* Debug-only ids */ /* Debug-only ids */
fn next_box_id(&mut self) -> int { self.next_bid += 1; self.next_bid }
fn next_flow_id(&mut self) -> int { self.next_cid += 1; self.next_cid } fn next_flow_id(&mut self) -> int { self.next_cid += 1; self.next_cid }
fn next_box_id(&mut self) -> int { self.next_bid += 1; self.next_bid }
/// 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.
fn construct_recursively(&mut self, fn construct_recursively(&mut self,
layout_ctx: &LayoutContext, layout_ctx: &LayoutContext,
cur_node: AbstractNode<LayoutView>, cur_node: AbstractNode<LayoutView>,
parent_ctx: &mut BuilderContext) { parent_generator: @mut BoxGenerator,
prev_sibling_generator: Option<@mut BoxGenerator>)
-> Option<@mut BoxGenerator> {
debug!("Considering node: %s", cur_node.debug_str()); debug!("Considering node: %s", cur_node.debug_str());
let mut this_ctx = match parent_ctx.containing_context_for_node(cur_node, self) { let this_generator = match self.box_generator_for_node(cur_node,
Some(ctx) => ctx, parent_generator,
None => { return; } // no context because of display: none. Stop building subtree. prev_sibling_generator) {
Some(gen) => gen,
None => { return prev_sibling_generator; }
}; };
debug!("point a: %s", cur_node.debug_str()); debug!("point a: %s", cur_node.debug_str());
this_ctx.default_collector.push_node(layout_ctx, self, cur_node); this_generator.push_node(layout_ctx, cur_node, self);
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 mut prev_generator: Option<@mut BoxGenerator> = None;
for cur_node.each_child |child_node| { for cur_node.each_child |child_node| {
self.construct_recursively(layout_ctx, child_node, &mut this_ctx); prev_generator = self.construct_recursively(layout_ctx, child_node, this_generator, prev_generator);
} }
this_ctx.default_collector.pop_node(layout_ctx, self, cur_node); this_generator.pop_node(layout_ctx, cur_node);
self.simplify_children_of_flow(layout_ctx, &this_ctx); self.simplify_children_of_flow(layout_ctx, &mut this_generator.flow);
// store reference to the flow context which contains any // store reference to the flow context which contains any
// boxes that correspond to child_flow.node. These boxes may // boxes that correspond to child_flow.node. These boxes may
// eventually be elided or split, but the mapping between // eventually be elided or split, but the mapping between
// nodes and FlowContexts should not change during layout. // nodes and FlowContexts should not change during layout.
let flow = &mut this_ctx.default_collector.flow; let flow: &FlowContext = &this_generator.flow;
let flow: &FlowContext = flow;
for flow.each_child |child_flow| { for flow.each_child |child_flow| {
do child_flow.with_base |child_node| { do child_flow.with_base |child_node| {
let dom_node = child_node.node; let dom_node = child_node.node;
@ -338,6 +302,118 @@ pub impl LayoutTreeBuilder {
dom_node.layout_data().flow = Some(child_flow); dom_node.layout_data().flow = Some(child_flow);
} }
} }
Some(this_generator)
}
fn box_generator_for_node(&mut self,
node: AbstractNode<LayoutView>,
parent_generator: @mut BoxGenerator,
sibling_generator: Option<@mut BoxGenerator>)
-> Option<@mut BoxGenerator> {
fn is_root(node: AbstractNode<LayoutView>) -> bool {
match node.parent_node() {
None => true,
Some(_) => false
}
}
let display = if (node.is_element()) {
match node.style().display(is_root(node)) {
CSSDisplayNone => return None, // tree ends here if 'display: none'
// TODO(eatkinson) these are hacks so that the code doesn't crash
// when unsupported display values are used. They should be deleted
// as they are implemented.
CSSDisplayListItem => CSSDisplayBlock,
CSSDisplayTable => CSSDisplayBlock,
CSSDisplayInlineTable => CSSDisplayInlineBlock,
CSSDisplayTableRowGroup => CSSDisplayBlock,
CSSDisplayTableHeaderGroup => CSSDisplayBlock,
CSSDisplayTableFooterGroup => CSSDisplayBlock,
CSSDisplayTableRow => CSSDisplayBlock,
CSSDisplayTableColumnGroup => return None,
CSSDisplayTableColumn => return None,
CSSDisplayTableCell => CSSDisplayBlock,
CSSDisplayTableCaption => CSSDisplayBlock,
v => v
}
} else {
match node.type_id() {
ElementNodeTypeId(_) => CSSDisplayInline,
TextNodeTypeId => CSSDisplayInline,
DoctypeNodeTypeId | CommentNodeTypeId => return None,
}
};
let sibling_flow: Option<FlowContext> = match sibling_generator {
None => None,
Some(gen) => Some(gen.flow)
};
let new_generator = match (display, parent_generator.flow, sibling_flow) {
(CSSDisplayBlock, BlockFlow(info), _) => match (info.is_root, node.parent_node()) {
// If this is the root node, then use the root flow's
// context. Otherwise, make a child block context.
(true, Some(_)) => { self.create_child_generator(node, parent_generator, Flow_Block) }
(true, None) => { parent_generator }
(false, _) => {
self.create_child_generator(node, parent_generator, Flow_Block)
}
},
// Inlines that are children of inlines are part of the same flow
(CSSDisplayInline, InlineFlow(*), _) => parent_generator,
(CSSDisplayInlineBlock, InlineFlow(*), _) => parent_generator,
// Inlines that are children of blocks create new flows if their
// previous sibling was a block.
(CSSDisplayInline, BlockFlow(*), Some(BlockFlow(*))) |
(CSSDisplayInlineBlock, BlockFlow(*), Some(BlockFlow(*))) => {
self.create_child_generator(node, parent_generator, Flow_Inline)
}
// Inlines whose previous sibling was not a block try to use their
// sibling's flow context.
(CSSDisplayInline, BlockFlow(*), _) |
(CSSDisplayInlineBlock, BlockFlow(*), _) => {
self.create_child_generator_if_needed(node,
parent_generator,
sibling_generator,
Flow_Inline)
}
// TODO(eatkinson): blocks that are children of inlines need
// to split their parent flows.
//
// TODO(eatkinson): floats and positioned elements.
_ => parent_generator
};
Some(new_generator)
}
fn create_child_generator(&mut self,
node: AbstractNode<LayoutView>,
parent_generator: @mut BoxGenerator,
ty: FlowContextType)
-> @mut BoxGenerator {
let new_flow = self.make_flow(ty, node);
parent_generator.flow.add_child(new_flow);
@mut BoxGenerator::new(new_flow)
}
fn create_child_generator_if_needed(&mut self,
node: AbstractNode<LayoutView>,
parent_generator: @mut BoxGenerator,
maybe_generator: Option<@mut BoxGenerator>,
ty: FlowContextType)
-> @mut BoxGenerator {
match maybe_generator {
None => self.create_child_generator(node, parent_generator, ty),
Some(gen) => gen
}
} }
/// Fix up any irregularities such as: /// Fix up any irregularities such as:
@ -348,15 +424,14 @@ pub impl LayoutTreeBuilder {
/// ///
/// The latter can only be done immediately adjacent to, or at the beginning or end of a block /// The latter can only be done immediately adjacent to, or at the beginning or end of a block
/// flow. Otherwise, the whitespace might affect whitespace collapsing with adjacent text. /// flow. Otherwise, the whitespace might affect whitespace collapsing with adjacent text.
fn simplify_children_of_flow(&self, _: &LayoutContext, parent_ctx: &BuilderContext) { fn simplify_children_of_flow(&self, _: &LayoutContext, parent_flow: &mut FlowContext) {
match parent_ctx.default_collector.flow { match *parent_flow {
InlineFlow(*) => { InlineFlow(*) => {
let mut found_child_inline = false; let mut found_child_inline = false;
let mut found_child_block = false; let mut found_child_block = false;
let flow = &mut parent_ctx.default_collector.flow; let flow = *parent_flow;
let flow: &FlowContext = flow; for flow.each_child |child_ctx: FlowContext| {
for flow.each_child |child_ctx| {
match child_ctx { match child_ctx {
InlineFlow(*) | InlineBlockFlow(*) => found_child_inline = true, InlineFlow(*) | InlineBlockFlow(*) => found_child_inline = true,
BlockFlow(*) => found_child_block = true, BlockFlow(*) => found_child_block = true,
@ -365,13 +440,12 @@ pub impl LayoutTreeBuilder {
} }
if found_child_block && found_child_inline { if found_child_block && found_child_inline {
self.fixup_split_inline(parent_ctx.default_collector.flow) self.fixup_split_inline(*parent_flow)
} }
}, },
BlockFlow(*) => { BlockFlow(*) => {
// FIXME: this will create refcounted cycles between the removed flow and any // FIXME: this will create refcounted cycles between the removed flow and any
// of its RenderBox or FlowContext children, and possibly keep alive other junk // of its RenderBox or FlowContext children, and possibly keep alive other junk
let parent_flow = parent_ctx.default_collector.flow;
// check first/last child for whitespace-ness // check first/last child for whitespace-ness
let first_child = do parent_flow.with_base |parent_node| { let first_child = do parent_flow.with_base |parent_node| {
@ -434,10 +508,9 @@ pub impl LayoutTreeBuilder {
-> Result<FlowContext, ()> { -> Result<FlowContext, ()> {
let new_flow = self.make_flow(Flow_Root, root); let new_flow = self.make_flow(Flow_Root, root);
let new_generator = @mut BoxGenerator::new(new_flow); let new_generator = @mut BoxGenerator::new(new_flow);
let mut root_ctx = BuilderContext::new(new_generator);
self.root_flow = Some(new_flow); self.root_flow = Some(new_flow);
self.construct_recursively(layout_ctx, root, &mut root_ctx); self.construct_recursively(layout_ctx, root, new_generator, None);
return Ok(new_flow) return Ok(new_flow)
} }
@ -456,59 +529,4 @@ pub impl LayoutTreeBuilder {
debug!("LayoutTreeBuilder: created flow: %s", result.debug_str()); debug!("LayoutTreeBuilder: created flow: %s", result.debug_str());
result result
} }
/// Disambiguate between different methods here instead of inlining, since each case has very
/// different complexity.
fn make_box(&mut self,
layout_ctx: &LayoutContext,
ty: RenderBoxType,
node: AbstractNode<LayoutView>,
flow_context: FlowContext)
-> RenderBox {
let base = RenderBoxBase::new(node, flow_context, self.next_box_id());
let result = match ty {
RenderBox_Generic => GenericRenderBoxClass(@mut base),
RenderBox_Text => UnscannedTextRenderBoxClass(@mut UnscannedTextRenderBox::new(base)),
RenderBox_Image => self.make_image_box(layout_ctx, node, base),
};
debug!("LayoutTreeBuilder: created box: %s", result.debug_str());
result
}
fn make_image_box(&mut self,
layout_ctx: &LayoutContext,
node: AbstractNode<LayoutView>,
base: RenderBoxBase)
-> RenderBox {
assert!(node.is_image_element());
do node.with_imm_image_element |image_element| {
if image_element.image.is_some() {
// FIXME(pcwalton): Don't copy URLs.
let url = copy *image_element.image.get_ref();
ImageRenderBoxClass(@mut ImageRenderBox::new(base, url, layout_ctx.image_cache))
} else {
info!("Tried to make image box, but couldn't find image. Made generic box \
instead.");
GenericRenderBoxClass(@mut base)
}
}
}
fn decide_box_type(&self, node: AbstractNode<LayoutView>, _: CSSDisplay) -> RenderBoxType {
if node.is_text() {
RenderBox_Text
} else if node.is_image_element() {
do node.with_imm_image_element |image_element| {
match image_element.image {
Some(_) => RenderBox_Image,
None => RenderBox_Generic,
}
}
} else if node.is_element() {
RenderBox_Generic
} else {
fail!(~"Hey, doctypes and comments shouldn't get here! They are display:none!")
}
}
} }

View file

@ -412,7 +412,7 @@ impl<'self> FlowContext {
}; };
do self.with_base |base| { do self.with_base |base| {
fmt!("f%? %?", base.id, repr) fmt!("f%? %? size %?", base.id, repr, base.position)
} }
} }
} }

View file

@ -252,6 +252,8 @@ impl Layout {
} // time(layout: display list building) } // time(layout: display list building)
} }
debug!("%?", layout_root.dump());
// Tell script that we're done. // Tell script that we're done.
data.script_join_chan.send(()); data.script_join_chan.send(());
} }

@ -1 +1 @@
Subproject commit ff8e2a63938ded5d2688619680a981c73d25080d Subproject commit d916b9796668d4bb46a3b1b4976c95ab7da79837

@ -1 +1 @@
Subproject commit 2f3f03cbafb88608d4f89216da7172d3b754fbef Subproject commit 09d2db847c11bcab7f1832d5daf5947a7c1384ee

@ -1 +1 @@
Subproject commit 969af0260ef38d2c80ef2f51037da7ed1fc5cc85 Subproject commit dd25d69abde67e2275fbbbd93196043b69afd67b

@ -1 +1 @@
Subproject commit 3565b32ba3d15d31b02cc76bdf76d6b13fc88451 Subproject commit 8ecca4b5d779e749a298b1c2ca1152aa2ecd4e79

View file

@ -9,8 +9,7 @@
<body> <body>
<div> <div>
<div>Hello</div> <div>Hello!</div>
<div>World</div> <div>World</div>
</div> </div>
</body> </body>