try to reset flows which need reflow, since reflow isn't yet idempotent

This commit is contained in:
Clark Gaebel 2014-10-10 11:25:41 -04:00
parent d168501555
commit f552e2f750
13 changed files with 310 additions and 82 deletions

View file

@ -44,7 +44,7 @@ use table_rowgroup::TableRowGroupFlow;
use table_row::TableRowFlow;
use table_cell::TableCellFlow;
use text::TextRunScanner;
use util::{LayoutDataAccess, OpaqueNodeMethods};
use util::{LayoutDataAccess, OpaqueNodeMethods, LayoutDataWrapper};
use wrapper::{PostorderNodeMutTraversal, TLayoutNode, ThreadSafeLayoutNode};
use wrapper::{Before, After, Normal};
@ -81,6 +81,22 @@ pub enum ConstructionResult {
ConstructionItemConstructionResult(ConstructionItem),
}
impl ConstructionResult {
pub fn swap_out(&mut self, layout_context: &LayoutContext) -> ConstructionResult {
if layout_context.shared.opts.incremental_layout {
match *self {
NoConstructionResult =>
return NoConstructionResult,
FlowConstructionResult(ref flow_ref, ref abs_descendants) =>
return FlowConstructionResult((*flow_ref).clone(), (*abs_descendants).clone()),
ConstructionItemConstructionResult(_) => {},
}
}
mem::replace(self, NoConstructionResult)
}
}
/// Represents the output of flow construction for a DOM node that has not yet resulted in a
/// complete flow. Construction items bubble up the tree until they find a `Flow` to be attached
/// to.
@ -361,7 +377,7 @@ impl<'a> FlowConstructor<'a> {
&mut InlineFragmentsAccumulator,
abs_descendants: &mut Descendants,
first_fragment: &mut bool) {
match kid.swap_out_construction_result() {
match kid.swap_out_construction_result(self.layout_context) {
NoConstructionResult => {}
FlowConstructionResult(kid_flow, kid_abs_descendants) => {
// If kid_flow is TableCaptionFlow, kid_flow should be added under
@ -562,7 +578,7 @@ impl<'a> FlowConstructor<'a> {
if kid.get_pseudo_element_type() != Normal {
self.process(&kid);
}
match kid.swap_out_construction_result() {
match kid.swap_out_construction_result(self.layout_context) {
NoConstructionResult => {}
FlowConstructionResult(flow, kid_abs_descendants) => {
// {ib} split. Flush the accumulator to our new split and make a new
@ -743,12 +759,13 @@ impl<'a> FlowConstructor<'a> {
table_wrapper_flow: &mut FlowRef,
node: &ThreadSafeLayoutNode) {
for kid in node.children() {
match kid.swap_out_construction_result() {
match kid.swap_out_construction_result(self.layout_context) {
NoConstructionResult | ConstructionItemConstructionResult(_) => {}
FlowConstructionResult(kid_flow, _) => {
// Only kid flows with table-caption are matched here.
assert!(kid_flow.get().is_table_caption());
table_wrapper_flow.add_new_child(kid_flow);
if kid_flow.get().is_table_caption() {
table_wrapper_flow.add_new_child(kid_flow);
}
}
}
}
@ -905,7 +922,7 @@ impl<'a> FlowConstructor<'a> {
for kid in node.children() {
// CSS 2.1 § 17.2.1. Treat all non-column child fragments of `table-column-group`
// as `display: none`.
match kid.swap_out_construction_result() {
match kid.swap_out_construction_result(self.layout_context) {
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(
fragment)) => {
col_fragments.push(fragment);
@ -974,7 +991,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
// results of children.
(display::none, _, _) => {
for child in node.children() {
drop(child.swap_out_construction_result())
drop(child.swap_out_construction_result(self.layout_context))
}
}
@ -1079,12 +1096,14 @@ trait NodeUtils {
/// Returns true if this node doesn't render its kids and false otherwise.
fn is_replaced_content(&self) -> bool;
fn get_construction_result<'a>(self, layout_data: &'a mut LayoutDataWrapper) -> &'a mut ConstructionResult;
/// Sets the construction result of a flow.
fn set_flow_construction_result(&self, result: ConstructionResult);
fn set_flow_construction_result(self, result: ConstructionResult);
/// Replaces the flow construction result in a node with `NoConstructionResult` and returns the
/// old value.
fn swap_out_construction_result(&self) -> ConstructionResult;
fn swap_out_construction_result(self, layout_context: &LayoutContext) -> ConstructionResult;
}
impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
@ -1103,43 +1122,30 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
}
}
#[inline(always)]
fn set_flow_construction_result(&self, result: ConstructionResult) {
let mut layout_data_ref = self.mutate_layout_data();
match &mut *layout_data_ref {
&Some(ref mut layout_data) =>{
match self.get_pseudo_element_type() {
Before(_) => layout_data.data.before_flow_construction_result = result,
After(_) => layout_data.data.after_flow_construction_result = result,
Normal => layout_data.data.flow_construction_result = result,
}
},
&None => fail!("no layout data"),
fn get_construction_result<'a>(self, layout_data: &'a mut LayoutDataWrapper) -> &'a mut ConstructionResult {
match self.get_pseudo_element_type() {
Before(_) => &mut layout_data.data.before_flow_construction_result,
After (_) => &mut layout_data.data.after_flow_construction_result,
Normal => &mut layout_data.data.flow_construction_result,
}
}
#[inline(always)]
fn swap_out_construction_result(&self) -> ConstructionResult {
fn set_flow_construction_result(self, result: ConstructionResult) {
let mut layout_data_ref = self.mutate_layout_data();
match &mut *layout_data_ref {
&Some(ref mut layout_data) => {
match self.get_pseudo_element_type() {
Before(_) => {
mem::replace(&mut layout_data.data.before_flow_construction_result,
NoConstructionResult)
}
After(_) => {
mem::replace(&mut layout_data.data.after_flow_construction_result,
NoConstructionResult)
}
Normal => {
mem::replace(&mut layout_data.data.flow_construction_result,
NoConstructionResult)
}
}
}
&None => fail!("no layout data"),
}
let layout_data = layout_data_ref.as_mut().expect("no layout data");
let dst = self.get_construction_result(layout_data);
*dst = result;
}
#[inline(always)]
fn swap_out_construction_result(self, layout_context: &LayoutContext) -> ConstructionResult {
let mut layout_data_ref = self.mutate_layout_data();
let layout_data = layout_data_ref.as_mut().expect("no layout data");
self.get_construction_result(layout_data).swap_out(layout_context)
}
}