diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2015-03-05 12:37:37 -0800 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2015-03-09 17:13:45 -0700 |
commit | f9cdd05d58e7f1a8cd6198dad3058d86bf479a08 (patch) | |
tree | a09fafccb79081207407e9a691728816c75231c1 /components/layout/incremental.rs | |
parent | 2df4dd9e098671fdbe2951f6669473e7737d6ed3 (diff) | |
download | servo-f9cdd05d58e7f1a8cd6198dad3058d86bf479a08.tar.gz servo-f9cdd05d58e7f1a8cd6198dad3058d86bf479a08.zip |
layout: Implement ordered lists, CSS counters, and `quotes` per CSS 2.1
§ 12.3-12.5.
Only simple alphabetic and numeric counter styles are supported. (This
is most of them though.)
Although this PR adds a sequential pass to layout, I verified that on
pages that contain a reasonable number of ordered lists (Reddit
`/r/rust`), the time spent in generated content resolution is dwarfed by
the time spent in the parallelizable parts of layout. So I don't expect
this to negatively affect our parallelism expect perhaps in pathological
cases.
Diffstat (limited to 'components/layout/incremental.rs')
-rw-r--r-- | components/layout/incremental.rs | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs index b163a8fbf29..9d989c7b65a 100644 --- a/components/layout/incremental.rs +++ b/components/layout/incremental.rs @@ -2,8 +2,7 @@ * 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/. */ -use flow::{self, Flow}; -use flow::{IS_ABSOLUTELY_POSITIONED}; +use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, IS_ABSOLUTELY_POSITIONED}; use std::fmt; use std::sync::Arc; @@ -32,8 +31,12 @@ bitflags! { #[doc = "top-down."] const REFLOW = 0x08, + #[doc = "Re-resolve generated content. \ + Propagates up the flow tree because the computation is inorder."] + const RESOLVE_GENERATED_CONTENT = 0x10, + #[doc = "The entire flow needs to be reconstructed."] - const RECONSTRUCT_FLOW = 0x10 + const RECONSTRUCT_FLOW = 0x20 } } @@ -50,9 +53,9 @@ impl RestyleDamage { /// we should add to the *parent* of this flow. pub fn damage_for_parent(self, child_is_absolutely_positioned: bool) -> RestyleDamage { if child_is_absolutely_positioned { - self & (REPAINT | REFLOW_OUT_OF_FLOW) + self & (REPAINT | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT) } else { - self & (REPAINT | REFLOW | REFLOW_OUT_OF_FLOW) + self & (REPAINT | REFLOW | REFLOW_OUT_OF_FLOW | RESOLVE_GENERATED_CONTENT) } } @@ -91,10 +94,11 @@ impl fmt::Debug for RestyleDamage { let mut first_elem = true; let to_iter = - [ (REPAINT, "Repaint") - , (BUBBLE_ISIZES, "BubbleISizes") + [ (REPAINT, "Repaint") + , (BUBBLE_ISIZES, "BubbleISizes") , (REFLOW_OUT_OF_FLOW, "ReflowOutOfFlow") - , (REFLOW, "Reflow") + , (REFLOW, "Reflow") + , (RESOLVE_GENERATED_CONTENT, "ResolveGeneratedContent") , (RECONSTRUCT_FLOW, "ReconstructFlow") ]; @@ -126,10 +130,18 @@ macro_rules! add_if_not_equal( }) ); +/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed. +/// +/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in +/// unnecessary sequential resolution of generated content. +pub fn rebuild_and_reflow() -> RestyleDamage { + REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW +} + pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage { let old: &ComputedValues = match old.as_ref() { - None => return RestyleDamage::all(), + None => return rebuild_and_reflow(), Some(cv) => &**cv, }; @@ -186,6 +198,9 @@ impl<'a> LayoutDamageComputation for &'a mut (Flow + 'a) { let mut special_damage = SpecialRestyleDamage::empty(); let is_absolutely_positioned = flow::base(self).flags.contains(IS_ABSOLUTELY_POSITIONED); + // In addition to damage, we use this phase to compute whether nodes affect CSS counters. + let mut has_counter_affecting_children = false; + { let self_base = flow::mut_base(self); for kid in self_base.children.iter_mut() { @@ -199,21 +214,32 @@ impl<'a> LayoutDamageComputation for &'a mut (Flow + 'a) { self_base.restyle_damage .insert(flow::base(kid).restyle_damage.damage_for_parent( child_is_absolutely_positioned)); + + has_counter_affecting_children = has_counter_affecting_children || + flow::base(kid).flags.intersects(AFFECTS_COUNTERS | + HAS_COUNTER_AFFECTING_CHILDREN); + } } - let self_base = flow::base(self); + let self_base = flow::mut_base(self); if self_base.flags.float_kind() != float::T::none && self_base.restyle_damage.intersects(REFLOW) { special_damage.insert(REFLOW_ENTIRE_DOCUMENT); } + if has_counter_affecting_children { + self_base.flags.insert(HAS_COUNTER_AFFECTING_CHILDREN) + } else { + self_base.flags.remove(HAS_COUNTER_AFFECTING_CHILDREN) + } + special_damage } fn reflow_entire_document(self) { let self_base = flow::mut_base(self); - self_base.restyle_damage.insert(RestyleDamage::all()); + self_base.restyle_damage.insert(rebuild_and_reflow()); self_base.restyle_damage.remove(RECONSTRUCT_FLOW); for kid in self_base.children.iter_mut() { kid.reflow_entire_document(); |