/
matching.rs
69 lines (59 loc) · 2.52 KB
/
matching.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
// High-level interface to CSS selector matching.
use css::node_util::NodeUtil;
use css::select_handler::NodeSelectHandler;
use layout::incremental;
use script::dom::node::{AbstractNode, LayoutView};
use newcss::complete::CompleteSelectResults;
use newcss::select::{SelectCtx, SelectResults};
use servo_util::tree::TreeUtils;
pub trait MatchMethods {
fn restyle_subtree(&self, select_ctx: &SelectCtx);
}
impl MatchMethods for AbstractNode<LayoutView> {
/**
* Performs CSS selector matching on a subtree.
*
* This is, importantly, the function that updates the layout data for
* the node (the reader-auxiliary box in the COW model) with the
* computed style.
*/
fn restyle_subtree(&self, select_ctx: &SelectCtx) {
// Only elements have styles
if self.is_element() {
let select_handler = NodeSelectHandler { node: *self };
let incomplete_results = select_ctx.select_style(self, &select_handler);
// Combine this node's results with its parent's to resolve all inherited values
let complete_results = compose_results(*self, incomplete_results);
// If there was an existing style, compute the damage that
// incremental layout will need to fix.
if self.have_css_select_results() {
let damage = incremental::compute_damage(self, self.get_css_select_results(), &complete_results);
self.set_restyle_damage(damage);
}
self.set_css_select_results(complete_results);
}
for self.each_child |kid| {
kid.restyle_subtree(select_ctx);
}
}
}
fn compose_results(node: AbstractNode<LayoutView>, results: SelectResults)
-> CompleteSelectResults {
match find_parent_element_node(node) {
None => CompleteSelectResults::new_root(results),
Some(parent_node) => {
let parent_results = parent_node.get_css_select_results();
CompleteSelectResults::new_from_parent(parent_results, results)
}
}
}
fn find_parent_element_node(node: AbstractNode<LayoutView>) -> Option<AbstractNode<LayoutView>> {
match node.parent_node() {
Some(parent) if parent.is_element() => Some(parent),
Some(parent) => find_parent_element_node(parent),
None => None,
}
}