mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
geckolib: Refactor atom-to-pseudo logic and use ArcHelpers when
appropiate
This commit is contained in:
parent
02da1bb050
commit
2dbd17040a
1 changed files with 53 additions and 31 deletions
|
@ -12,7 +12,7 @@ use data::PerDocumentStyleData;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use gecko_style_structs::SheetParsingMode;
|
use gecko_style_structs::SheetParsingMode;
|
||||||
use properties::GeckoComputedValues;
|
use properties::GeckoComputedValues;
|
||||||
use selector_impl::{GeckoSelectorImpl, SharedStyleContext, Stylesheet};
|
use selector_impl::{GeckoSelectorImpl, PseudoElement, SharedStyleContext, Stylesheet};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::{forget, transmute};
|
use std::mem::{forget, transmute};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -30,6 +30,29 @@ use url::Url;
|
||||||
use util::arc_ptr_eq;
|
use util::arc_ptr_eq;
|
||||||
use wrapper::{GeckoDocument, GeckoElement, GeckoNode, NonOpaqueStyleData};
|
use wrapper::{GeckoDocument, GeckoElement, GeckoNode, NonOpaqueStyleData};
|
||||||
|
|
||||||
|
// TODO: This is ugly and should go away once we get an atom back-end.
|
||||||
|
pub fn pseudo_element_from_atom(pseudo: *mut nsIAtom,
|
||||||
|
in_ua_stylesheet: bool) -> Result<PseudoElement, String> {
|
||||||
|
use bindings::Gecko_GetAtomAsUTF16;
|
||||||
|
use selectors::parser::{ParserContext, SelectorImpl};
|
||||||
|
|
||||||
|
let pseudo_string = unsafe {
|
||||||
|
let mut length = 0;
|
||||||
|
let mut buff = Gecko_GetAtomAsUTF16(pseudo, &mut length);
|
||||||
|
|
||||||
|
// Handle the annoying preceding colon in front of everything in nsCSSAnonBoxList.h.
|
||||||
|
debug_assert!(length >= 2 && *buff == ':' as u16 && *buff.offset(1) != ':' as u16);
|
||||||
|
buff = buff.offset(1);
|
||||||
|
length -= 1;
|
||||||
|
|
||||||
|
String::from_utf16(slice::from_raw_parts(buff, length as usize)).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut context = ParserContext::new();
|
||||||
|
context.in_user_agent_stylesheet = in_ua_stylesheet;
|
||||||
|
GeckoSelectorImpl::parse_pseudo_element(&context, &pseudo_string).map_err(|_| pseudo_string)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
|
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
|
||||||
* the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
|
* the C header in Gecko. In order to catch accidental mismatches, we run rust-bindgen against
|
||||||
|
@ -106,19 +129,40 @@ pub struct ArcHelpers<GeckoType, ServoType> {
|
||||||
phantom2: PhantomData<ServoType>,
|
phantom2: PhantomData<ServoType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
|
impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
|
||||||
pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output
|
pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output
|
||||||
where F: FnOnce(&Arc<ServoType>) -> Output {
|
where F: FnOnce(&Arc<ServoType>) -> Output {
|
||||||
|
debug_assert!(!raw.is_null());
|
||||||
|
|
||||||
let owned = unsafe { Self::into(raw) };
|
let owned = unsafe { Self::into(raw) };
|
||||||
let result = cb(&owned);
|
let result = cb(&owned);
|
||||||
forget(owned);
|
forget(owned);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn maybe_with<F, Output>(maybe_raw: *mut GeckoType, cb: F) -> Output
|
||||||
|
where F: FnOnce(Option<&Arc<ServoType>>) -> Output {
|
||||||
|
let owned = if maybe_raw.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(unsafe { Self::into(maybe_raw) })
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = cb(owned.as_ref());
|
||||||
|
forget(owned);
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> {
|
pub unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> {
|
||||||
transmute(ptr)
|
transmute(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub unsafe fn from(owned: Arc<ServoType>) -> *mut GeckoType {
|
||||||
|
transmute(owned)
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn addref(ptr: *mut GeckoType) {
|
pub unsafe fn addref(ptr: *mut GeckoType) {
|
||||||
Self::with(ptr, |arc| forget(arc.clone()));
|
Self::with(ptr, |arc| forget(arc.clone()));
|
||||||
}
|
}
|
||||||
|
@ -210,44 +254,22 @@ pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(parent_style_or_null: *
|
||||||
pseudo_tag: *mut nsIAtom,
|
pseudo_tag: *mut nsIAtom,
|
||||||
raw_data: *mut RawServoStyleSet)
|
raw_data: *mut RawServoStyleSet)
|
||||||
-> *mut ServoComputedValues {
|
-> *mut ServoComputedValues {
|
||||||
use bindings::Gecko_GetAtomAsUTF16;
|
|
||||||
use selectors::parser::{ParserContext, SelectorImpl};
|
|
||||||
|
|
||||||
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||||
|
|
||||||
// TODO: This is ugly and should go away once we get an atom back-end.
|
let pseudo = match pseudo_element_from_atom(pseudo_tag, true) {
|
||||||
let pseudo_string = unsafe {
|
|
||||||
let mut length = 0;
|
|
||||||
let buff = Gecko_GetAtomAsUTF16(pseudo_tag, &mut length);
|
|
||||||
String::from_utf16(slice::from_raw_parts(buff, length as usize)).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut context = ParserContext::new();
|
|
||||||
// Parse every pseudo-element possible.
|
|
||||||
context.in_user_agent_stylesheet = true;
|
|
||||||
|
|
||||||
let pseudo = match GeckoSelectorImpl::parse_pseudo_element(&context, &pseudo_string) {
|
|
||||||
Ok(pseudo) => pseudo,
|
Ok(pseudo) => pseudo,
|
||||||
Err(_) => {
|
Err(pseudo) => {
|
||||||
warn!("stylo: Unable to parse pseudo-element: {}", pseudo_string);
|
warn!("stylo: Unable to parse anonymous-box pseudo-element: {}", pseudo);
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
type Helpers = ArcHelpers<ServoComputedValues, GeckoComputedValues>;
|
||||||
let parent: Option<Arc<GeckoComputedValues>> =
|
|
||||||
if parent_style_or_null.is_null() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(transmute(parent_style_or_null))
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_computed = data.stylist.computed_values_for_pseudo(&pseudo, parent.as_ref());
|
Helpers::maybe_with(parent_style_or_null, |maybe_parent| {
|
||||||
|
let new_computed = data.stylist.computed_values_for_pseudo(&pseudo, maybe_parent);
|
||||||
forget(parent);
|
new_computed.map_or(ptr::null_mut(), |c| unsafe { Helpers::from(c) })
|
||||||
|
})
|
||||||
new_computed.map_or(ptr::null_mut(), |c| transmute(c))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue