mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
stylo: implement indexed and count getters for custom properties
This commit is contained in:
parent
71f1f4b508
commit
93f0de7899
4 changed files with 135 additions and 31 deletions
|
@ -13,7 +13,7 @@ use properties::{CSSWideKeyword, DeclaredValue};
|
||||||
use selectors::parser::SelectorParseError;
|
use selectors::parser::SelectorParseError;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, hash_map, HashSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style_traits::{HasViewportPercentage, ToCss, StyleParseError, ParseError};
|
use style_traits::{HasViewportPercentage, ToCss, StyleParseError, ParseError};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
|
@ -92,7 +92,65 @@ impl ToCss for ComputedValue {
|
||||||
|
|
||||||
/// A map from CSS variable names to CSS variable computed values, used for
|
/// A map from CSS variable names to CSS variable computed values, used for
|
||||||
/// resolving.
|
/// resolving.
|
||||||
pub type ComputedValuesMap = HashMap<Name, ComputedValue>;
|
///
|
||||||
|
/// A consistent ordering is required for CSSDeclaration objects in the
|
||||||
|
/// DOM. CSSDeclarations expose property names as indexed properties, which
|
||||||
|
/// need to be stable. So we keep an array of property names which order is
|
||||||
|
/// determined on the order that they are added to the name-value map.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct CustomPropertiesMap {
|
||||||
|
/// Custom property name index.
|
||||||
|
index: Vec<Name>,
|
||||||
|
/// Computed values indexed by custom property name.
|
||||||
|
values: HashMap<Name, ComputedValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CustomPropertiesMap {
|
||||||
|
/// Creates a new custom properties map.
|
||||||
|
pub fn new() -> Self {
|
||||||
|
CustomPropertiesMap {
|
||||||
|
index: Vec::new(),
|
||||||
|
values: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert a computed value if it has not previously been inserted.
|
||||||
|
pub fn insert(&mut self, name: &Name, value: ComputedValue) {
|
||||||
|
debug_assert!(!self.index.contains(name));
|
||||||
|
self.index.push(name.clone());
|
||||||
|
self.values.insert(name.clone(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Custom property computed value getter by name.
|
||||||
|
pub fn get_computed_value(&self, name: &Name) -> Option<&ComputedValue> {
|
||||||
|
let value = self.values.get(name);
|
||||||
|
debug_assert_eq!(value.is_some(), self.index.contains(name));
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the name of a custom property given its list index.
|
||||||
|
pub fn get_name_at(&self, index: u32) -> Option<&Name> {
|
||||||
|
self.index.get(index as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an iterator for custom properties computed values.
|
||||||
|
pub fn iter(&self) -> hash_map::Iter<Name, ComputedValue> {
|
||||||
|
self.values.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the count of custom properties computed values.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
debug_assert_eq!(self.values.len(), self.index.len());
|
||||||
|
self.values.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for CustomPropertiesMap {}
|
||||||
|
impl PartialEq for CustomPropertiesMap {
|
||||||
|
fn eq(&self, other: &CustomPropertiesMap) -> bool {
|
||||||
|
self.values == other.values && self.index == other.index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ComputedValue {
|
impl ComputedValue {
|
||||||
fn empty() -> ComputedValue {
|
fn empty() -> ComputedValue {
|
||||||
|
@ -335,7 +393,7 @@ fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>,
|
||||||
/// Add one custom property declaration to a map, unless another with the same
|
/// Add one custom property declaration to a map, unless another with the same
|
||||||
/// name was already there.
|
/// name was already there.
|
||||||
pub fn cascade<'a>(custom_properties: &mut Option<HashMap<&'a Name, BorrowedSpecifiedValue<'a>>>,
|
pub fn cascade<'a>(custom_properties: &mut Option<HashMap<&'a Name, BorrowedSpecifiedValue<'a>>>,
|
||||||
inherited: &'a Option<Arc<HashMap<Name, ComputedValue>>>,
|
inherited: &'a Option<Arc<CustomPropertiesMap>>,
|
||||||
seen: &mut HashSet<&'a Name>,
|
seen: &mut HashSet<&'a Name>,
|
||||||
name: &'a Name,
|
name: &'a Name,
|
||||||
specified_value: DeclaredValue<'a, Box<SpecifiedValue>>) {
|
specified_value: DeclaredValue<'a, Box<SpecifiedValue>>) {
|
||||||
|
@ -388,8 +446,8 @@ pub fn cascade<'a>(custom_properties: &mut Option<HashMap<&'a Name, BorrowedSpec
|
||||||
///
|
///
|
||||||
/// Otherwise, just use the inherited custom properties map.
|
/// Otherwise, just use the inherited custom properties map.
|
||||||
pub fn finish_cascade(specified_values_map: Option<HashMap<&Name, BorrowedSpecifiedValue>>,
|
pub fn finish_cascade(specified_values_map: Option<HashMap<&Name, BorrowedSpecifiedValue>>,
|
||||||
inherited: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
inherited: &Option<Arc<CustomPropertiesMap>>)
|
||||||
-> Option<Arc<HashMap<Name, ComputedValue>>> {
|
-> Option<Arc<CustomPropertiesMap>> {
|
||||||
if let Some(mut map) = specified_values_map {
|
if let Some(mut map) = specified_values_map {
|
||||||
remove_cycles(&mut map);
|
remove_cycles(&mut map);
|
||||||
Some(Arc::new(substitute_all(map, inherited)))
|
Some(Arc::new(substitute_all(map, inherited)))
|
||||||
|
@ -445,18 +503,19 @@ fn remove_cycles(map: &mut HashMap<&Name, BorrowedSpecifiedValue>) {
|
||||||
|
|
||||||
/// Replace `var()` functions for all custom properties.
|
/// Replace `var()` functions for all custom properties.
|
||||||
fn substitute_all(specified_values_map: HashMap<&Name, BorrowedSpecifiedValue>,
|
fn substitute_all(specified_values_map: HashMap<&Name, BorrowedSpecifiedValue>,
|
||||||
inherited: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
inherited: &Option<Arc<CustomPropertiesMap>>)
|
||||||
-> HashMap<Name, ComputedValue> {
|
-> CustomPropertiesMap {
|
||||||
let mut computed_values_map = HashMap::new();
|
let mut custom_properties_map = CustomPropertiesMap::new();
|
||||||
let mut invalid = HashSet::new();
|
let mut invalid = HashSet::new();
|
||||||
for (&name, value) in &specified_values_map {
|
for (&name, value) in &specified_values_map {
|
||||||
// If this value is invalid at computed-time it won’t be inserted in computed_values_map.
|
// If this value is invalid at computed-time it won’t be inserted in computed_values_map.
|
||||||
// Nothing else to do.
|
// Nothing else to do.
|
||||||
let _ = substitute_one(
|
let _ = substitute_one(
|
||||||
name, value, &specified_values_map, inherited, None,
|
name, value, &specified_values_map, inherited, None,
|
||||||
&mut computed_values_map, &mut invalid);
|
&mut custom_properties_map, &mut invalid);
|
||||||
}
|
}
|
||||||
computed_values_map
|
|
||||||
|
custom_properties_map
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replace `var()` functions for one custom property.
|
/// Replace `var()` functions for one custom property.
|
||||||
|
@ -466,12 +525,12 @@ fn substitute_all(specified_values_map: HashMap<&Name, BorrowedSpecifiedValue>,
|
||||||
fn substitute_one(name: &Name,
|
fn substitute_one(name: &Name,
|
||||||
specified_value: &BorrowedSpecifiedValue,
|
specified_value: &BorrowedSpecifiedValue,
|
||||||
specified_values_map: &HashMap<&Name, BorrowedSpecifiedValue>,
|
specified_values_map: &HashMap<&Name, BorrowedSpecifiedValue>,
|
||||||
inherited: &Option<Arc<HashMap<Name, ComputedValue>>>,
|
inherited: &Option<Arc<CustomPropertiesMap>>,
|
||||||
partial_computed_value: Option<&mut ComputedValue>,
|
partial_computed_value: Option<&mut ComputedValue>,
|
||||||
computed_values_map: &mut HashMap<Name, ComputedValue>,
|
custom_properties_map: &mut CustomPropertiesMap,
|
||||||
invalid: &mut HashSet<Name>)
|
invalid: &mut HashSet<Name>)
|
||||||
-> Result<TokenSerializationType, ()> {
|
-> Result<TokenSerializationType, ()> {
|
||||||
if let Some(computed_value) = computed_values_map.get(name) {
|
if let Some(computed_value) = custom_properties_map.get_computed_value(&name) {
|
||||||
if let Some(partial_computed_value) = partial_computed_value {
|
if let Some(partial_computed_value) = partial_computed_value {
|
||||||
partial_computed_value.push_variable(computed_value)
|
partial_computed_value.push_variable(computed_value)
|
||||||
}
|
}
|
||||||
|
@ -491,7 +550,7 @@ fn substitute_one(name: &Name,
|
||||||
&mut |name, partial_computed_value| {
|
&mut |name, partial_computed_value| {
|
||||||
if let Some(other_specified_value) = specified_values_map.get(name) {
|
if let Some(other_specified_value) = specified_values_map.get(name) {
|
||||||
substitute_one(name, other_specified_value, specified_values_map, inherited,
|
substitute_one(name, other_specified_value, specified_values_map, inherited,
|
||||||
Some(partial_computed_value), computed_values_map, invalid)
|
Some(partial_computed_value), custom_properties_map, invalid)
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -502,7 +561,7 @@ fn substitute_one(name: &Name,
|
||||||
partial_computed_value
|
partial_computed_value
|
||||||
} else {
|
} else {
|
||||||
// Invalid at computed-value time. Use the inherited value.
|
// Invalid at computed-value time. Use the inherited value.
|
||||||
if let Some(inherited_value) = inherited.as_ref().and_then(|i| i.get(name)) {
|
if let Some(inherited_value) = inherited.as_ref().and_then(|i| i.values.get(name)) {
|
||||||
inherited_value.clone()
|
inherited_value.clone()
|
||||||
} else {
|
} else {
|
||||||
invalid.insert(name.clone());
|
invalid.insert(name.clone());
|
||||||
|
@ -521,7 +580,7 @@ fn substitute_one(name: &Name,
|
||||||
partial_computed_value.push_variable(&computed_value)
|
partial_computed_value.push_variable(&computed_value)
|
||||||
}
|
}
|
||||||
let last_token_type = computed_value.last_token_type;
|
let last_token_type = computed_value.last_token_type;
|
||||||
computed_values_map.insert(name.clone(), computed_value);
|
custom_properties_map.insert(name, computed_value);
|
||||||
Ok(last_token_type)
|
Ok(last_token_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,7 +675,7 @@ fn substitute_block<'i, 't, F>(input: &mut Parser<'i, 't>,
|
||||||
/// Replace `var()` functions for a non-custom property.
|
/// Replace `var()` functions for a non-custom property.
|
||||||
/// Return `Err(())` for invalid at computed time.
|
/// Return `Err(())` for invalid at computed time.
|
||||||
pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
|
pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
|
||||||
computed_values_map: &Option<Arc<HashMap<Name, ComputedValue>>>)
|
computed_values_map: &Option<Arc<CustomPropertiesMap>>)
|
||||||
-> Result<String, ParseError<'i>> {
|
-> Result<String, ParseError<'i>> {
|
||||||
let mut substituted = ComputedValue::empty();
|
let mut substituted = ComputedValue::empty();
|
||||||
let mut input = ParserInput::new(input);
|
let mut input = ParserInput::new(input);
|
||||||
|
@ -624,7 +683,7 @@ pub fn substitute<'i>(input: &'i str, first_token_type: TokenSerializationType,
|
||||||
let mut position = (input.position(), first_token_type);
|
let mut position = (input.position(), first_token_type);
|
||||||
let last_token_type = substitute_block(
|
let last_token_type = substitute_block(
|
||||||
&mut input, &mut position, &mut substituted, &mut |name, substituted| {
|
&mut input, &mut position, &mut substituted, &mut |name, substituted| {
|
||||||
if let Some(value) = computed_values_map.as_ref().and_then(|map| map.get(name)) {
|
if let Some(value) = computed_values_map.as_ref().and_then(|map| map.get_computed_value(name)) {
|
||||||
substituted.push_variable(value);
|
substituted.push_variable(value);
|
||||||
Ok(value.last_token_type)
|
Ok(value.last_token_type)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2709,6 +2709,22 @@ extern "C" {
|
||||||
RawServoDeclarationBlockBorrowed,
|
RawServoDeclarationBlockBorrowed,
|
||||||
buffer: *mut nsAString);
|
buffer: *mut nsAString);
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_GetCustomPropertyValue(computed_values:
|
||||||
|
ServoComputedValuesBorrowed,
|
||||||
|
name: *const nsAString,
|
||||||
|
value: *mut nsAString) -> bool;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_GetCustomPropertiesCount(computed_values:
|
||||||
|
ServoComputedValuesBorrowed)
|
||||||
|
-> u32;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Servo_GetCustomPropertyNameAt(arg1: ServoComputedValuesBorrowed,
|
||||||
|
index: u32, name: *mut nsAString)
|
||||||
|
-> bool;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Servo_GetStyleFont(computed_values:
|
pub fn Servo_GetStyleFont(computed_values:
|
||||||
ServoComputedValuesBorrowedOrNull)
|
ServoComputedValuesBorrowedOrNull)
|
||||||
|
|
|
@ -375,7 +375,7 @@ impl PropertyDeclarationIdSet {
|
||||||
% else:
|
% else:
|
||||||
value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>,
|
value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>,
|
||||||
% endif
|
% endif
|
||||||
custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: &Option<Arc<::custom_properties::CustomPropertiesMap>>,
|
||||||
f: &mut F,
|
f: &mut F,
|
||||||
error_reporter: &ParseErrorReporter,
|
error_reporter: &ParseErrorReporter,
|
||||||
quirks_mode: QuirksMode)
|
quirks_mode: QuirksMode)
|
||||||
|
@ -406,7 +406,7 @@ impl PropertyDeclarationIdSet {
|
||||||
first_token_type: TokenSerializationType,
|
first_token_type: TokenSerializationType,
|
||||||
url_data: &UrlExtraData,
|
url_data: &UrlExtraData,
|
||||||
from_shorthand: Option<ShorthandId>,
|
from_shorthand: Option<ShorthandId>,
|
||||||
custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: &Option<Arc<::custom_properties::CustomPropertiesMap>>,
|
||||||
f: &mut F,
|
f: &mut F,
|
||||||
error_reporter: &ParseErrorReporter,
|
error_reporter: &ParseErrorReporter,
|
||||||
quirks_mode: QuirksMode)
|
quirks_mode: QuirksMode)
|
||||||
|
@ -1816,7 +1816,7 @@ pub struct ComputedValues {
|
||||||
% for style_struct in data.active_style_structs():
|
% for style_struct in data.active_style_structs():
|
||||||
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
${style_struct.ident}: Arc<style_structs::${style_struct.name}>,
|
||||||
% endfor
|
% endfor
|
||||||
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
|
||||||
/// The writing mode of this computed values struct.
|
/// The writing mode of this computed values struct.
|
||||||
pub writing_mode: WritingMode,
|
pub writing_mode: WritingMode,
|
||||||
/// The keyword behind the current font-size property, if any
|
/// The keyword behind the current font-size property, if any
|
||||||
|
@ -1839,7 +1839,7 @@ pub struct ComputedValues {
|
||||||
impl ComputedValues {
|
impl ComputedValues {
|
||||||
/// Construct a `ComputedValues` instance.
|
/// Construct a `ComputedValues` instance.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
|
||||||
writing_mode: WritingMode,
|
writing_mode: WritingMode,
|
||||||
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||||
flags: ComputedValueFlags,
|
flags: ComputedValueFlags,
|
||||||
|
@ -1937,7 +1937,7 @@ impl ComputedValues {
|
||||||
// Aah! The << in the return type below is not valid syntax, but we must
|
// Aah! The << in the return type below is not valid syntax, but we must
|
||||||
// escape < that way for Mako.
|
// escape < that way for Mako.
|
||||||
/// Gets a reference to the custom properties map (if one exists).
|
/// Gets a reference to the custom properties map (if one exists).
|
||||||
pub fn get_custom_properties(&self) -> Option<<&::custom_properties::ComputedValuesMap> {
|
pub fn get_custom_properties(&self) -> Option<<&::custom_properties::CustomPropertiesMap> {
|
||||||
self.custom_properties.as_ref().map(|x| &**x)
|
self.custom_properties.as_ref().map(|x| &**x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1945,7 +1945,7 @@ impl ComputedValues {
|
||||||
///
|
///
|
||||||
/// Cloning the Arc here is fine because it only happens in the case where
|
/// Cloning the Arc here is fine because it only happens in the case where
|
||||||
/// we have custom properties, and those are both rare and expensive.
|
/// we have custom properties, and those are both rare and expensive.
|
||||||
pub fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> {
|
pub fn custom_properties(&self) -> Option<Arc<::custom_properties::CustomPropertiesMap>> {
|
||||||
self.custom_properties.clone()
|
self.custom_properties.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2241,7 +2241,7 @@ impl ComputedValues {
|
||||||
PropertyDeclarationId::Custom(name) => {
|
PropertyDeclarationId::Custom(name) => {
|
||||||
self.custom_properties
|
self.custom_properties
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|map| map.get(name))
|
.and_then(|map| map.get_computed_value(name))
|
||||||
.map(|value| value.to_css_string())
|
.map(|value| value.to_css_string())
|
||||||
.unwrap_or(String::new())
|
.unwrap_or(String::new())
|
||||||
}
|
}
|
||||||
|
@ -2401,7 +2401,7 @@ pub struct StyleBuilder<'a> {
|
||||||
/// The rule node representing the ordered list of rules matched for this
|
/// The rule node representing the ordered list of rules matched for this
|
||||||
/// node.
|
/// node.
|
||||||
rules: Option<StrongRuleNode>,
|
rules: Option<StrongRuleNode>,
|
||||||
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
|
||||||
/// The writing mode flags.
|
/// The writing mode flags.
|
||||||
///
|
///
|
||||||
/// TODO(emilio): Make private.
|
/// TODO(emilio): Make private.
|
||||||
|
@ -2423,7 +2423,7 @@ impl<'a> StyleBuilder<'a> {
|
||||||
inherited_style: &'a ComputedValues,
|
inherited_style: &'a ComputedValues,
|
||||||
reset_style: &'a ComputedValues,
|
reset_style: &'a ComputedValues,
|
||||||
rules: Option<StrongRuleNode>,
|
rules: Option<StrongRuleNode>,
|
||||||
custom_properties: Option<Arc<::custom_properties::ComputedValuesMap>>,
|
custom_properties: Option<Arc<::custom_properties::CustomPropertiesMap>>,
|
||||||
writing_mode: WritingMode,
|
writing_mode: WritingMode,
|
||||||
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
font_size_keyword: Option<(longhands::font_size::KeywordSize, f32)>,
|
||||||
visited_style: Option<Arc<ComputedValues>>,
|
visited_style: Option<Arc<ComputedValues>>,
|
||||||
|
@ -2544,7 +2544,7 @@ impl<'a> StyleBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// Cloning the Arc here is fine because it only happens in the case where
|
/// Cloning the Arc here is fine because it only happens in the case where
|
||||||
/// we have custom properties, and those are both rare and expensive.
|
/// we have custom properties, and those are both rare and expensive.
|
||||||
fn custom_properties(&self) -> Option<Arc<::custom_properties::ComputedValuesMap>> {
|
fn custom_properties(&self) -> Option<Arc<::custom_properties::CustomPropertiesMap>> {
|
||||||
self.custom_properties.clone()
|
self.custom_properties.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3185,15 +3185,16 @@ pub extern "C" fn Servo_StyleSet_HasStateDependency(raw_data: RawServoStyleSetBo
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_GetCustomProperty(computed_values: ServoComputedValuesBorrowed,
|
pub extern "C" fn Servo_GetCustomPropertyValue(computed_values: ServoComputedValuesBorrowed,
|
||||||
name: *const nsAString, value: *mut nsAString) -> bool {
|
name: *const nsAString,
|
||||||
|
value: *mut nsAString) -> bool {
|
||||||
let custom_properties = match ComputedValues::as_arc(&computed_values).custom_properties() {
|
let custom_properties = match ComputedValues::as_arc(&computed_values).custom_properties() {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = unsafe { Atom::from((&*name)) };
|
let name = unsafe { Atom::from((&*name)) };
|
||||||
let computed_value = match custom_properties.get(&name) {
|
let computed_value = match custom_properties.get_computed_value(&name) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
@ -3201,3 +3202,31 @@ pub extern "C" fn Servo_GetCustomProperty(computed_values: ServoComputedValuesBo
|
||||||
computed_value.to_css(unsafe { value.as_mut().unwrap() }).unwrap();
|
computed_value.to_css(unsafe { value.as_mut().unwrap() }).unwrap();
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_GetCustomPropertiesCount(computed_values: ServoComputedValuesBorrowed) -> u32 {
|
||||||
|
match ComputedValues::as_arc(&computed_values).custom_properties() {
|
||||||
|
Some(p) => p.len() as u32,
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_GetCustomPropertyNameAt(computed_values: ServoComputedValuesBorrowed,
|
||||||
|
index: u32,
|
||||||
|
name: *mut nsAString) -> bool {
|
||||||
|
let custom_properties = match ComputedValues::as_arc(&computed_values).custom_properties() {
|
||||||
|
Some(p) => p,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let property_name = match custom_properties.get_name_at(index) {
|
||||||
|
Some(n) => n,
|
||||||
|
None => return false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = unsafe { name.as_mut().unwrap() };
|
||||||
|
name.assign(&*property_name.as_slice());
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue