diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/main/css/matching.rs | 102 | ||||
-rw-r--r-- | src/components/main/css/select.rs | 7 | ||||
-rw-r--r-- | src/components/main/layout/layout_task.rs | 21 | ||||
-rw-r--r-- | src/components/main/layout/util.rs | 12 | ||||
-rw-r--r-- | src/components/style/selector_matching.rs | 29 | ||||
-rw-r--r-- | src/components/style/style.rc | 1 |
6 files changed, 144 insertions, 28 deletions
diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs index ead2052421e..827313148fa 100644 --- a/src/components/main/css/matching.rs +++ b/src/components/main/css/matching.rs @@ -18,12 +18,15 @@ use std::rt; use std::task; use std::vec; use style::{TNode, Stylist, cascade}; +use style::{Before, After}; pub trait MatchMethods { fn match_node(&self, stylist: &Stylist); - fn match_subtree(&self, stylist: RWArc<Stylist>); + fn match_subtree(&self, stylist: ~[RWArc<Stylist>]); + fn cascade_before_node(&self, parent: Option<LayoutNode>); fn cascade_node(&self, parent: Option<LayoutNode>); + fn cascade_after_node(&self, parent: Option<LayoutNode>); fn cascade_subtree(&self, parent: Option<LayoutNode>); } @@ -34,17 +37,22 @@ impl<'self> MatchMethods for LayoutNode<'self> { None => None, Some(ref style_attribute) => Some(style_attribute) }; - stylist.get_applicable_declarations(self, style_attribute, None) + stylist.get_applicable_declarations(self, style_attribute) }; match *self.mutate_layout_data().ptr { Some(ref mut layout_data) => { - layout_data.applicable_declarations = applicable_declarations + match stylist.get_pseudo_element() { + Some(Before) => layout_data.before_applicable_declarations = applicable_declarations, + Some(After) => layout_data.after_applicable_declarations = applicable_declarations, + None => layout_data.applicable_declarations = applicable_declarations, + _ => {} + } } None => fail!("no layout data") } } - fn match_subtree(&self, stylist: RWArc<Stylist>) { + fn match_subtree(&self, stylists: ~[RWArc<Stylist>]) { let num_tasks = rt::default_sched_threads() * 2; let mut node_count = 0; let mut nodes_per_task = vec::from_elem(num_tasks, ~[]); @@ -63,7 +71,7 @@ impl<'self> MatchMethods for LayoutNode<'self> { for nodes in nodes_per_task.move_iter() { if nodes.len() > 0 { let chan = chan.clone(); - let stylist = stylist.clone(); + let stylists = stylists.clone(); // FIXME(pcwalton): This transmute is to work around the fact that we have no // mechanism for safe fork/join parallelism. If we had such a thing, then we could @@ -73,15 +81,19 @@ impl<'self> MatchMethods for LayoutNode<'self> { cast::transmute(nodes) }; - do task::spawn_with((evil, stylist)) |(evil, stylist)| { + do task::spawn_with((evil, stylists)) |(evil, stylists)| { let nodes: ~[LayoutNode] = unsafe { cast::transmute(evil) }; let nodes = Cell::new(nodes); - do stylist.read |stylist| { - for node in nodes.take().move_iter() { - node.match_node(stylist); + for i in range(0, stylists.len()) { + do stylists[i].read |stylist| { + nodes.with_ref(|nodes|{ + for node in nodes.iter() { + node.match_node(stylist); + } + }); } } chan.send(()); @@ -94,6 +106,37 @@ impl<'self> MatchMethods for LayoutNode<'self> { } } + fn cascade_before_node(&self, parent: Option<LayoutNode>) { + let parent_style = match parent { + Some(ref parent) => Some(parent.style()), + None => None + }; + + let computed_values = unsafe { + Arc::new(cascade(self.borrow_layout_data_unchecked() + .as_ref() + .unwrap() + .before_applicable_declarations, + parent_style.map(|parent_style| parent_style.get()))) + }; + + match *self.mutate_layout_data().ptr { + None => fail!("no layout data"), + Some(ref mut layout_data) => { + let style = &mut layout_data.before_style; + match *style { + None => (), + Some(ref previous_style) => { + layout_data.restyle_damage = + Some(incremental::compute_damage(previous_style.get(), + computed_values.get()).to_int()) + } + } + *style = Some(computed_values) + } + } + } + fn cascade_node(&self, parent: Option<LayoutNode>) { let parent_style = match parent { Some(ref parent) => Some(parent.style()), @@ -125,8 +168,49 @@ impl<'self> MatchMethods for LayoutNode<'self> { } } + fn cascade_after_node(&self, parent: Option<LayoutNode>) { + let parent_style = match parent { + Some(ref parent) => Some(parent.style()), + None => None + }; + + let computed_values = unsafe { + Arc::new(cascade(self.borrow_layout_data_unchecked() + .as_ref() + .unwrap() + .after_applicable_declarations, + parent_style.map(|parent_style| parent_style.get()))) + }; + + match *self.mutate_layout_data().ptr { + None => fail!("no layout data"), + Some(ref mut layout_data) => { + let style = &mut layout_data.after_style; + match *style { + None => (), + Some(ref previous_style) => { + layout_data.restyle_damage = + Some(incremental::compute_damage(previous_style.get(), + computed_values.get()).to_int()) + } + } + *style = Some(computed_values) + } + } + } + fn cascade_subtree(&self, parent: Option<LayoutNode>) { + unsafe { + if self.borrow_layout_data_unchecked().as_ref().unwrap().before_applicable_declarations.len() > 0 { + self.cascade_before_node(parent); + } + } self.cascade_node(parent); + unsafe { + if self.borrow_layout_data_unchecked().as_ref().unwrap().after_applicable_declarations.len() > 0 { + self.cascade_after_node(parent); + } + } for kid in self.children() { if kid.is_element() { diff --git a/src/components/main/css/select.rs b/src/components/main/css/select.rs index 10ac49875d5..5292c963dc3 100644 --- a/src/components/main/css/select.rs +++ b/src/components/main/css/select.rs @@ -3,16 +3,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use style::{Stylesheet, Stylist, UserAgentOrigin, with_errors_silenced}; +use style::PseudoElement; use extra::url; -pub fn new_stylist() -> Stylist { - let mut stylist = Stylist::new(); +pub fn new_stylist(pseudo_element: Option<PseudoElement>) -> Stylist { + let mut stylist = Stylist::new(pseudo_element); let ua_stylesheet = with_errors_silenced(|| Stylesheet::from_bytes( include_bin!("user-agent.css"), url::from_str("chrome:///user-agent.css").unwrap(), None, None)); - stylist.add_stylesheet(ua_stylesheet, UserAgentOrigin); + stylist.add_stylesheet(&ua_stylesheet, UserAgentOrigin); stylist } diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 8f5edcfb3ab..0443612b57d 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -51,6 +51,7 @@ use std::comm::Port; use std::task; use std::util; use style::{AuthorOrigin, Stylesheet, Stylist}; +use style::{Before, After}; /// Information needed by the layout task. struct LayoutTask { @@ -81,7 +82,7 @@ struct LayoutTask { /// A cached display list. display_list: Option<Arc<DisplayList<OpaqueNode>>>, - stylist: RWArc<Stylist>, + stylists: ~[RWArc<Stylist>], /// The channel on which messages can be sent to the profiler. profiler_chan: ProfilerChan, @@ -236,6 +237,12 @@ impl LayoutTask { profiler_chan: ProfilerChan) -> LayoutTask { + let mut stylists = ~[]; + let stylist_owners = ~[Some(Before), Some(After), None]; + for i in range(0, stylist_owners.len()) { + stylists.push(RWArc::new(new_stylist(stylist_owners[i]))); + } + LayoutTask { id: id, port: port, @@ -248,7 +255,7 @@ impl LayoutTask { display_list: None, - stylist: RWArc::new(new_stylist()), + stylists: stylists, profiler_chan: profiler_chan, opts: opts.clone() } @@ -347,8 +354,12 @@ impl LayoutTask { fn handle_add_stylesheet(&mut self, sheet: Stylesheet) { let sheet = Cell::new(sheet); - do self.stylist.write |stylist| { - stylist.add_stylesheet(sheet.take(), AuthorOrigin) + for i in range(0, self.stylists.len()) { + do self.stylists[i].write |stylist| { + sheet.with_ref(|sheet|{ + stylist.add_stylesheet(sheet, AuthorOrigin); + }); + } } } @@ -445,7 +456,7 @@ impl LayoutTask { ReflowDocumentDamage => {} _ => { do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) { - node.match_subtree(self.stylist.clone()); + node.match_subtree(self.stylists.clone()); node.cascade_subtree(None); } } diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs index 90c85acb1aa..a5dc5047968 100644 --- a/src/components/main/layout/util.rs +++ b/src/components/main/layout/util.rs @@ -127,11 +127,19 @@ impl ElementMapping { /// Data that layout associates with a node. pub struct LayoutData { /// The results of CSS matching for this node. + before_applicable_declarations: ~[Arc<~[PropertyDeclaration]>], + applicable_declarations: ~[Arc<~[PropertyDeclaration]>], + after_applicable_declarations: ~[Arc<~[PropertyDeclaration]>], + /// The results of CSS styling for this node. + before_style: Option<Arc<ComputedValues>>, + style: Option<Arc<ComputedValues>>, + after_style: Option<Arc<ComputedValues>>, + /// Description of how to account for recent style changes. restyle_damage: Option<int>, @@ -145,7 +153,11 @@ impl LayoutData { pub fn new() -> LayoutData { LayoutData { applicable_declarations: ~[], + before_applicable_declarations: ~[], + after_applicable_declarations: ~[], + before_style: None, style: None, + after_style: None, restyle_damage: None, flow_construction_result: NoConstructionResult, } diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index b897888d810..f949b2b8221 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -244,20 +244,22 @@ pub struct Stylist { priv author_rule_map: PerOriginSelectorMap, priv user_rule_map: PerOriginSelectorMap, priv stylesheet_index: uint, + priv pseudo_element: Option<PseudoElement>, } impl Stylist { #[inline] - pub fn new() -> Stylist { + pub fn new(pseudo_element: Option<PseudoElement>) -> Stylist { Stylist { ua_rule_map: PerOriginSelectorMap::new(), author_rule_map: PerOriginSelectorMap::new(), user_rule_map: PerOriginSelectorMap::new(), stylesheet_index: 0u, + pseudo_element: pseudo_element, } } - pub fn add_stylesheet(&mut self, stylesheet: Stylesheet, origin: StylesheetOrigin) { + pub fn add_stylesheet(&mut self, stylesheet: &Stylesheet, origin: StylesheetOrigin) { let rule_map = match origin { UserAgentOrigin => &mut self.ua_rule_map, AuthorOrigin => &mut self.author_rule_map, @@ -275,12 +277,14 @@ impl Stylist { $flag = true; for selector in style_rule.selectors.iter() { // TODO: avoid copying? - rule_map.$priority.insert(Rule { - selector: Arc::new(selector.clone()), - declarations: style_rule.declarations.$priority.clone(), - index: style_rule_index, - stylesheet_index: self.stylesheet_index, + if selector.pseudo_element == self.pseudo_element { + rule_map.$priority.insert(Rule { + selector: Arc::new(selector.clone()), + declarations: style_rule.declarations.$priority.clone(), + index: style_rule_index, + stylesheet_index: self.stylesheet_index, }); + } } } }; @@ -301,11 +305,10 @@ impl Stylist { N:TNode<E>>( &self, element: &N, - style_attribute: Option<&PropertyDeclarationBlock>, - pseudo_element: Option<PseudoElement>) + style_attribute: Option<&PropertyDeclarationBlock>) -> ~[Arc<~[PropertyDeclaration]>] { assert!(element.is_element()); - assert!(style_attribute.is_none() || pseudo_element.is_none(), + assert!(style_attribute.is_none() || self.pseudo_element.is_none(), "Style attributes do not apply to pseudo-elements"); // In cascading order: @@ -327,7 +330,7 @@ impl Stylist { for (i, rule_map) in rule_map_list.iter().enumerate() { rule_map_indices[i] = matching_rules_list.len(); - rule_map.get_all_matching_rules(element, pseudo_element, &mut matching_rules_list); + rule_map.get_all_matching_rules(element, self.pseudo_element, &mut matching_rules_list); } let count = matching_rules_list.len(); @@ -370,6 +373,10 @@ impl Stylist { applicable_declarations } + + pub fn get_pseudo_element(&self) -> Option<PseudoElement> { + self.pseudo_element + } } struct PerOriginRules { diff --git a/src/components/style/style.rc b/src/components/style/style.rc index 3868e39fb70..d41e98682fc 100644 --- a/src/components/style/style.rc +++ b/src/components/style/style.rc @@ -26,6 +26,7 @@ pub use properties::{cascade, PropertyDeclaration, ComputedValues, computed_valu pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes pub use errors::with_errors_silenced; pub use node::{TElement, TNode}; +pub use selectors::{PseudoElement, Before, After}; mod stylesheets; mod errors; |