167 lines
5.4 KiB
Diff
167 lines
5.4 KiB
Diff
|
From 5796011ea5232783ee89e8467a76656873a3f7b4 Mon Sep 17 00:00:00 2001
|
||
|
From: Federico Mena Quintero <federico@gnome.org>
|
||
|
Date: Wed, 6 Nov 2019 17:59:53 -0600
|
||
|
Subject: [PATCH 2/3] Compute the specificity of CSS selectors
|
||
|
|
||
|
And remove the unused function CssRules::lookup()
|
||
|
---
|
||
|
rsvg_internals/src/croco.rs | 2 ++
|
||
|
rsvg_internals/src/css.rs | 44 ++++++++++++++++++++++---------------
|
||
|
2 files changed, 28 insertions(+), 18 deletions(-)
|
||
|
|
||
|
diff --git a/rsvg_internals/src/croco.rs b/rsvg_internals/src/croco.rs
|
||
|
index 21ac8051..7bee041d 100644
|
||
|
--- a/rsvg_internals/src/croco.rs
|
||
|
+++ b/rsvg_internals/src/croco.rs
|
||
|
@@ -11,6 +11,7 @@ pub type CRTerm = gpointer;
|
||
|
pub type CRAdditionalSel = gpointer;
|
||
|
|
||
|
pub type CRStatus = u32;
|
||
|
+pub const CR_OK: u32 = 0;
|
||
|
|
||
|
pub type CREncoding = u32;
|
||
|
pub const CR_UTF_8: CREncoding = 5;
|
||
|
@@ -105,6 +106,7 @@ extern "C" {
|
||
|
pub fn cr_selector_unref(a_this: *mut CRSelector) -> gboolean;
|
||
|
|
||
|
pub fn cr_simple_sel_to_string(a_this: *mut CRSimpleSel) -> *mut libc::c_char;
|
||
|
+ pub fn cr_simple_sel_compute_specificity(a_this: *mut CRSimpleSel) -> CRStatus;
|
||
|
|
||
|
pub fn cr_string_peek_raw_str(a_this: CRString) -> *const libc::c_char;
|
||
|
|
||
|
diff --git a/rsvg_internals/src/css.rs b/rsvg_internals/src/css.rs
|
||
|
index 2bb4a3b9..c8ae072c 100644
|
||
|
--- a/rsvg_internals/src/css.rs
|
||
|
+++ b/rsvg_internals/src/css.rs
|
||
|
@@ -73,11 +73,17 @@ impl<'i> AtRuleParser<'i> for DeclParser {
|
||
|
}
|
||
|
|
||
|
#[derive(Clone, Hash, PartialEq, Eq)]
|
||
|
-pub struct Selector(String);
|
||
|
+pub struct Selector {
|
||
|
+ name: String,
|
||
|
+ specificity: u64,
|
||
|
+}
|
||
|
|
||
|
impl Selector {
|
||
|
- fn new(s: &str) -> Selector {
|
||
|
- Selector(s.to_string())
|
||
|
+ fn new(s: &str, specificity: u64) -> Selector {
|
||
|
+ Selector {
|
||
|
+ name: s.to_string(),
|
||
|
+ specificity,
|
||
|
+ }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -196,10 +202,6 @@ impl CssRules {
|
||
|
decl_list.add_declaration(declaration);
|
||
|
}
|
||
|
|
||
|
- pub fn lookup(&self, selector: &str) -> Option<&DeclarationList> {
|
||
|
- self.get_declarations(&Selector::new(selector))
|
||
|
- }
|
||
|
-
|
||
|
pub fn get_declarations(&self, selector: &Selector) -> Option<&DeclarationList> {
|
||
|
self.selectors_to_declarations.get(selector)
|
||
|
}
|
||
|
@@ -219,12 +221,12 @@ impl CssRules {
|
||
|
let id = node_data.get_id();
|
||
|
|
||
|
// *
|
||
|
- if *selector == Selector::new("*") {
|
||
|
+ if selector.name == "*" {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// tag
|
||
|
- if *selector == Selector::new(element_name) {
|
||
|
+ if selector.name == element_name {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@@ -234,7 +236,7 @@ impl CssRules {
|
||
|
// tag.class#id
|
||
|
if let Some(id) = id {
|
||
|
let target = format!("{}.{}#{}", element_name, cls, id);
|
||
|
- if *selector == Selector::new(&target) {
|
||
|
+ if selector.name == target {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
@@ -242,20 +244,20 @@ impl CssRules {
|
||
|
// .class#id
|
||
|
if let Some(id) = id {
|
||
|
let target = format!(".{}#{}", cls, id);
|
||
|
- if *selector == Selector::new(&target) {
|
||
|
+ if selector.name == target {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// tag.class
|
||
|
let target = format!("{}.{}", element_name, cls);
|
||
|
- if *selector == Selector::new(&target) {
|
||
|
+ if selector.name == target {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// didn't find anything more specific, just apply the class style
|
||
|
let target = format!(".{}", cls);
|
||
|
- if *selector == Selector::new(&target) {
|
||
|
+ if selector.name == target {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
@@ -265,13 +267,13 @@ impl CssRules {
|
||
|
if let Some(id) = id {
|
||
|
// id
|
||
|
let target = format!("#{}", id);
|
||
|
- if *selector == Selector::new(&target) {
|
||
|
+ if selector.name == target {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// tag#id
|
||
|
let target = format!("{}#{}", element_name, id);
|
||
|
- if *selector == Selector::new(&target) {
|
||
|
+ if selector.name == target {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
@@ -375,7 +377,15 @@ unsafe extern "C" fn css_property(
|
||
|
while !cur_sel.is_null() {
|
||
|
let simple_sel = (*cur_sel).simple_sel;
|
||
|
|
||
|
+ cur_sel = (*cur_sel).next;
|
||
|
+
|
||
|
if !simple_sel.is_null() {
|
||
|
+ if cr_simple_sel_compute_specificity(simple_sel) != CR_OK {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ let specificity = u64::from((*simple_sel).specificity);
|
||
|
+
|
||
|
let raw_selector_name = cr_simple_sel_to_string(simple_sel) as *mut libc::c_char;
|
||
|
|
||
|
if !raw_selector_name.is_null() {
|
||
|
@@ -405,14 +415,12 @@ unsafe extern "C" fn css_property(
|
||
|
|
||
|
handler_data
|
||
|
.css_rules
|
||
|
- .add_declaration(Selector::new(&selector_name), declaration);
|
||
|
+ .add_declaration(Selector::new(&selector_name, specificity), declaration);
|
||
|
}
|
||
|
Err(_) => (), // invalid property name or invalid value; ignore
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
-
|
||
|
- cur_sel = (*cur_sel).next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
--
|
||
|
2.23.0
|
||
|
|