Move most of geckolib into style::gecko

This commit is contained in:
Manish Goregaokar 2016-09-22 16:14:19 +05:30
parent bc9cbc87ba
commit b2e592b121
27 changed files with 167 additions and 157 deletions

View file

@ -2272,6 +2272,7 @@ version = "0.0.1"
dependencies = [
"app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2286,6 +2287,7 @@ dependencies = [
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"plugins 0.0.1",
"quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -13,7 +13,7 @@ path = "lib.rs"
[features]
gecko = []
servo = ["serde/unstable", "serde_macros", "heapsize_plugin",
servo = ["serde/unstable", "serde", "serde_macros", "heapsize_plugin",
"style_traits/servo", "app_units/plugins",
"cssparser/heap_size", "cssparser/serde-serialization",
"selectors/heap_size", "selectors/unstable", "string_cache",
@ -33,15 +33,17 @@ heapsize = "0.3.0"
heapsize_plugin = {version = "0.1.2", optional = true}
lazy_static = "0.2"
log = "0.3.5"
libc = "0.2"
matches = "0.1"
num-integer = "0.1.32"
num-traits = "0.1.32"
num_cpus = "0.2.2"
ordered-float = "0.2.2"
quickersort = "2.0.0"
rand = "0.3"
rustc-serialize = "0.3"
selectors = "0.13"
serde = "0.8"
serde = {version = "0.8", optional = true}
serde_macros = {version = "0.8", optional = true}
smallvec = "0.1"
string_cache = {version = "0.2.26", features = ["heap_size"], optional = true}

View file

@ -432,11 +432,13 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
flags.append("--blacklist-type")
flags.append("{}Strong".format(ty))
flags.append("--raw-line")
flags.append("pub type {0}Strong = ::gecko_bindings::sugar::ownership::Strong<{0}>;".format(ty))
flags.append("pub type {0}Strong = ::gecko_bindings::sugar::ownership::Strong<{0}>;"
.format(ty))
flags.append("--blacklist-type")
flags.append("{}BorrowedOrNull".format(ty))
flags.append("--raw-line")
flags.append("pub type {0}BorrowedOrNull<'a> = ::gecko_bindings::sugar::ownership::Borrowed<'a, {0}>;".format(ty))
flags.append("pub type {0}BorrowedOrNull<'a> = \
::gecko_bindings::sugar::ownership::Borrowed<'a, {0}>;".format(ty))
flags.append("--blacklist-type")
flags.append("{}Borrowed".format(ty))
flags.append("--raw-line")
@ -452,7 +454,8 @@ def build(objdir, target_name, debug, debugger, kind_name=None,
flags.append("--blacklist-type")
flags.append("{}BorrowedOrNull".format(ty))
flags.append("--raw-line")
flags.append("pub type {0}BorrowedOrNull<'a> = ::gecko_bindings::sugar::ownership::Borrowed<'a, {0}>;".format(ty))
flags.append("pub type {0}BorrowedOrNull<'a> = \
::gecko_bindings::sugar::ownership::Borrowed<'a, {0}>;".format(ty))
# Right now the only immutable borrow types are ones which we import
# from the |structs| module. As such, we don't need to create an opaque
# type with zero_size_type. If we ever introduce immutable borrow types

View file

@ -138,7 +138,8 @@ def write_atom_macro(atoms, file_name):
f.write("}\n\n")
f.write("#[macro_export]\n")
f.write("macro_rules! atom {\n")
f.writelines(['("%s") => { $crate::string_cache::atom_macro::unsafe_atom_from_static($crate::string_cache::atom_macro::%s as *mut _) };\n'
f.writelines(['("%s") => { $crate::string_cache::atom_macro::unsafe_atom_from_static(\
$crate::string_cache::atom_macro::%s as *mut _) };\n'
% (atom.value, atom.ident) for atom in atoms])
f.write("}\n")
@ -192,5 +193,5 @@ def write_pseudo_element_helper(atoms, target_filename):
def build(objdir, verbose=False):
atoms = collect_atoms(objdir)
write_atom_macro(atoms, "../gecko_string_cache/atom_macro.rs")
write_pseudo_element_helper(atoms, "../generated/gecko_pseudo_element_helper.rs")
write_pseudo_element_helper(atoms, "../gecko/generated/gecko_pseudo_element_helper.rs")
return 0

View file

@ -0,0 +1,51 @@
/* 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/. */
use context::{LocalStyleContext, StyleContext, SharedStyleContext};
use std::cell::RefCell;
use std::rc::Rc;
thread_local!(static LOCAL_CONTEXT_KEY: RefCell<Option<Rc<LocalStyleContext>>> = RefCell::new(None));
// Keep this implementation in sync with the one in components/layout/context.rs.
fn create_or_get_local_context(shared: &SharedStyleContext) -> Rc<LocalStyleContext> {
LOCAL_CONTEXT_KEY.with(|r| {
let mut r = r.borrow_mut();
if let Some(context) = r.clone() {
if shared.screen_size_changed {
context.applicable_declarations_cache.borrow_mut().evict_all();
}
context
} else {
let context = Rc::new(LocalStyleContext::new(&shared.local_context_creation_data.lock().unwrap()));
*r = Some(context.clone());
context
}
})
}
pub struct StandaloneStyleContext<'a> {
pub shared: &'a SharedStyleContext,
cached_local_context: Rc<LocalStyleContext>,
}
impl<'a> StandaloneStyleContext<'a> {
pub fn new(shared: &'a SharedStyleContext) -> Self {
let local_context = create_or_get_local_context(shared);
StandaloneStyleContext {
shared: shared,
cached_local_context: local_context,
}
}
}
impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
fn shared_context(&self) -> &'a SharedStyleContext {
&self.shared
}
fn local_context(&self) -> &LocalStyleContext {
&self.cached_local_context
}
}

View file

@ -107,12 +107,12 @@ impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
pub mod basic_shape {
use euclid::size::Size2D;
use gecko::values::GeckoStyleCoordConvertible;
use gecko_bindings::structs;
use gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleFillRule};
use gecko_bindings::structs::{nsStyleCoord, nsStyleCorners};
use gecko_bindings::structs::StyleClipPathGeometryBox;
use gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
use gecko::values::GeckoStyleCoordConvertible;
use std::borrow::Borrow;
use values::computed::{BorderRadiusSize, LengthOrPercentage};
use values::computed::basic_shape::*;

View file

@ -0,0 +1,105 @@
/* 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/. */
use animation::Animation;
use context::SharedStyleContext;
use dom::OpaqueNode;
use euclid::size::TypedSize2D;
use gecko_bindings::bindings::RawServoStyleSet;
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
use media_queries::{Device, MediaType};
use num_cpus;
use parallel::WorkQueueData;
use selector_matching::Stylist;
use std::cmp;
use std::collections::HashMap;
use std::env;
use std::sync::{Arc, RwLock};
use std::sync::mpsc::{Receiver, Sender, channel};
use style_traits::ViewportPx;
use stylesheets::Stylesheet;
use thread_state;
use workqueue::WorkQueue;
pub struct PerDocumentStyleData {
/// Rule processor.
pub stylist: Arc<Stylist>,
/// List of stylesheets, mirrored from Gecko.
pub stylesheets: Vec<Arc<Stylesheet>>,
/// Whether the stylesheets list above has changed since the last restyle.
pub stylesheets_changed: bool,
// FIXME(bholley): Hook these up to something.
pub new_animations_sender: Sender<Animation>,
pub new_animations_receiver: Receiver<Animation>,
pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
// FIXME(bholley): This shouldn't be per-document.
pub work_queue: Option<WorkQueue<SharedStyleContext, WorkQueueData>>,
pub num_threads: usize,
}
lazy_static! {
pub static ref NUM_THREADS: usize = {
match env::var("STYLO_THREADS").map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS")) {
Ok(num) => num,
_ => cmp::max(num_cpus::get() * 3 / 4, 1),
}
};
}
impl PerDocumentStyleData {
pub fn new() -> PerDocumentStyleData {
// FIXME(bholley): Real window size.
let window_size: TypedSize2D<f32, ViewportPx> = TypedSize2D::new(800.0, 600.0);
let device = Device::new(MediaType::Screen, window_size);
let (new_anims_sender, new_anims_receiver) = channel();
PerDocumentStyleData {
stylist: Arc::new(Stylist::new(device)),
stylesheets: vec![],
stylesheets_changed: true,
new_animations_sender: new_anims_sender,
new_animations_receiver: new_anims_receiver,
running_animations: Arc::new(RwLock::new(HashMap::new())),
expired_animations: Arc::new(RwLock::new(HashMap::new())),
work_queue: if *NUM_THREADS <= 1 {
None
} else {
WorkQueue::new("StyleWorker", thread_state::LAYOUT, *NUM_THREADS).ok()
},
num_threads: *NUM_THREADS,
}
}
pub fn flush_stylesheets(&mut self) {
// The stylist wants to be flushed if either the stylesheets change or the
// device dimensions change. When we add support for media queries, we'll
// need to detect the latter case and trigger a flush as well.
if self.stylesheets_changed {
let _ = Arc::get_mut(&mut self.stylist).unwrap()
.update(&self.stylesheets, None, true);
self.stylesheets_changed = false;
}
}
}
unsafe impl HasFFI for PerDocumentStyleData {
type FFIType = RawServoStyleSet;
}
unsafe impl HasSimpleFFI for PerDocumentStyleData {}
unsafe impl HasBoxFFI for PerDocumentStyleData {}
impl Drop for PerDocumentStyleData {
fn drop(&mut self) {
if let Some(ref mut queue) = self.work_queue {
queue.shutdown();
}
}
}

View file

@ -0,0 +1,15 @@
/* 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/. */
pub mod context;
pub mod data;
pub mod snapshot;
pub mod snapshot_helpers;
pub mod traversal;
pub mod wrapper;
pub mod conversions;
pub mod selector_impl;
pub mod values;

View file

@ -70,7 +70,7 @@ impl PseudoElement {
}}
}
include!("../generated/gecko_pseudo_element_helper.rs");
include!("generated/gecko_pseudo_element_helper.rs");
None
}
@ -88,7 +88,7 @@ impl PseudoElement {
}}
}
include!("../generated/gecko_pseudo_element_helper.rs");
include!("generated/gecko_pseudo_element_helper.rs");
None
}
@ -238,7 +238,7 @@ impl GeckoSelectorImpl {
}}
}
include!("../generated/gecko_pseudo_element_helper.rs")
include!("generated/gecko_pseudo_element_helper.rs")
}
#[inline]

View file

@ -0,0 +1,151 @@
/* 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/. */
use element_state::ElementState;
use gecko::snapshot_helpers;
use gecko::wrapper::AttrSelectorHelpers;
use gecko_bindings::bindings;
use gecko_bindings::structs::ServoElementSnapshot;
use gecko_bindings::structs::ServoElementSnapshotFlags as Flags;
use restyle_hints::ElementSnapshot;
use selector_impl::TheSelectorImpl;
use selectors::parser::AttrSelector;
use string_cache::Atom;
// NB: This is sound, in some sense, because during computation of restyle hints
// the snapshot is kept alive by the modified elements table.
#[derive(Debug)]
pub struct GeckoElementSnapshot(*mut ServoElementSnapshot);
impl GeckoElementSnapshot {
#[inline]
pub unsafe fn from_raw(raw: *mut ServoElementSnapshot) -> Self {
GeckoElementSnapshot(raw)
}
#[inline]
fn is_html_element_in_html_document(&self) -> bool {
unsafe { (*self.0).mIsHTMLElementInHTMLDocument }
}
#[inline]
fn has_any(&self, flags: Flags) -> bool {
unsafe { ((*self.0).mContains as u8 & flags as u8) != 0 }
}
}
impl ::selectors::MatchAttr for GeckoElementSnapshot {
type Impl = TheSelectorImpl;
fn match_attr_has(&self, attr: &AttrSelector<TheSelectorImpl>) -> bool {
unsafe {
bindings::Gecko_SnapshotHasAttr(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()))
}
}
fn match_attr_equals(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrEquals(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr(),
/* ignoreCase = */ false)
}
}
fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrEquals(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr(),
/* ignoreCase = */ true)
}
}
fn match_attr_includes(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrIncludes(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_dash(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrDashEquals(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_prefix(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrHasPrefix(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_substring(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrHasSubstring(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_suffix(&self, attr: &AttrSelector<TheSelectorImpl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_SnapshotAttrHasSuffix(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
}
impl ElementSnapshot for GeckoElementSnapshot {
fn state(&self) -> Option<ElementState> {
if self.has_any(Flags::State) {
Some(ElementState::from_bits_truncate(unsafe { (*self.0).mState as u16 }))
} else {
None
}
}
#[inline]
fn has_attrs(&self) -> bool {
self.has_any(Flags::Attributes)
}
fn id_attr(&self) -> Option<Atom> {
let ptr = unsafe {
bindings::Gecko_SnapshotAtomAttrValue(self.0,
atom!("id").as_ptr())
};
if ptr.is_null() {
None
} else {
Some(Atom::from(ptr))
}
}
// TODO: share logic with Element::{has_class, each_class}?
fn has_class(&self, name: &Atom) -> bool {
snapshot_helpers::has_class(self.0,
name,
bindings::Gecko_SnapshotClassOrClassList)
}
fn each_class<F>(&self, callback: F)
where F: FnMut(&Atom)
{
snapshot_helpers::each_class(self.0,
callback,
bindings::Gecko_SnapshotClassOrClassList)
}
}

View file

@ -0,0 +1,53 @@
/* 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/. */
//! Element an snapshot common logic.
use gecko_bindings::structs::nsIAtom;
use std::{ptr, slice};
use string_cache::Atom;
pub type ClassOrClassList<T> = unsafe extern fn (T, *mut *mut nsIAtom, *mut *mut *mut nsIAtom) -> u32;
pub fn has_class<T>(item: T,
name: &Atom,
getter: ClassOrClassList<T>) -> bool
{
unsafe {
let mut class: *mut nsIAtom = ptr::null_mut();
let mut list: *mut *mut nsIAtom = ptr::null_mut();
let length = getter(item, &mut class, &mut list);
match length {
0 => false,
1 => name.as_ptr() == class,
n => {
let classes = slice::from_raw_parts(list, n as usize);
classes.iter().any(|ptr| name.as_ptr() == *ptr)
}
}
}
}
pub fn each_class<F, T>(item: T,
mut callback: F,
getter: ClassOrClassList<T>)
where F: FnMut(&Atom)
{
unsafe {
let mut class: *mut nsIAtom = ptr::null_mut();
let mut list: *mut *mut nsIAtom = ptr::null_mut();
let length = getter(item, &mut class, &mut list);
match length {
0 => {}
1 => Atom::with(class, &mut callback),
n => {
let classes = slice::from_raw_parts(list, n as usize);
for c in classes {
Atom::with(*c, &mut callback)
}
}
}
}
}

View file

@ -0,0 +1,49 @@
/* 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/. */
use context::{LocalStyleContext, SharedStyleContext, StyleContext};
use dom::OpaqueNode;
use gecko::context::StandaloneStyleContext;
use gecko::wrapper::GeckoNode;
use std::mem;
use traversal::{DomTraversalContext, recalc_style_at};
use traversal::RestyleResult;
pub struct RecalcStyleOnly<'lc> {
context: StandaloneStyleContext<'lc>,
root: OpaqueNode,
}
impl<'lc, 'ln> DomTraversalContext<GeckoNode<'ln>> for RecalcStyleOnly<'lc> {
type SharedContext = SharedStyleContext;
#[allow(unsafe_code)]
fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self {
// See the comment in RecalcStyleAndConstructFlows::new for an explanation of why this is
// necessary.
let shared_lc: &'lc Self::SharedContext = unsafe { mem::transmute(shared) };
RecalcStyleOnly {
context: StandaloneStyleContext::new(shared_lc),
root: root,
}
}
fn process_preorder(&self, node: GeckoNode<'ln>) -> RestyleResult {
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML
// parser.
node.initialize_data();
recalc_style_at(&self.context, self.root, node)
}
fn process_postorder(&self, _: GeckoNode<'ln>) {
unreachable!();
}
/// We don't use the post-order traversal for anything.
fn needs_postorder_traversal(&self) -> bool { false }
fn local_context(&self) -> &LocalStyleContext {
self.context.local_context()
}
}

View file

@ -0,0 +1,728 @@
/* 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/. */
#![allow(unsafe_code)]
use data::PrivateStyleData;
use dom::{LayoutIterator, NodeInfo, TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
use dom::{OpaqueNode, PresentationalHintsSynthetizer};
use element_state::ElementState;
use error_reporting::StdoutErrorReporter;
use gecko::selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PseudoElement};
use gecko::snapshot::GeckoElementSnapshot;
use gecko::snapshot_helpers;
use gecko_bindings::bindings;
use gecko_bindings::bindings::{Gecko_CalcStyleDifference, Gecko_StoreStyleDifference};
use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator};
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentElement};
use gecko_bindings::bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement};
use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement};
use gecko_bindings::bindings::{Gecko_GetNextSibling, Gecko_GetNextSiblingElement, Gecko_GetNextStyleChild};
use gecko_bindings::bindings::{Gecko_GetNodeFlags, Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
use gecko_bindings::bindings::{Gecko_GetParentElement, Gecko_GetParentNode};
use gecko_bindings::bindings::{Gecko_GetPrevSibling, Gecko_GetPrevSiblingElement};
use gecko_bindings::bindings::{Gecko_GetServoDeclarationBlock, Gecko_IsHTMLElementInHTMLDocument};
use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNode};
use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement};
use gecko_bindings::bindings::Gecko_ClassOrClassList;
use gecko_bindings::bindings::Gecko_GetStyleContext;
use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
use gecko_bindings::structs::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
use gecko_bindings::structs::{nsChangeHint, nsIAtom, nsStyleContext};
use gecko_bindings::structs::OpaqueStyleData;
use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasFFI};
use libc::uintptr_t;
use parser::ParserContextExtraData;
use properties::{ComputedValues, parse_style_attribute};
use properties::PropertyDeclarationBlock;
use refcell::{Ref, RefCell, RefMut};
use selector_impl::ElementExt;
use selector_matching::ApplicableDeclarationBlock;
use selectors::Element;
use selectors::parser::{AttrSelector, NamespaceConstraint};
use sink::Push;
use std::fmt;
use std::ops::BitOr;
use std::ptr;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicPtr};
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use url::Url;
pub struct NonOpaqueStyleData(RefCell<PrivateStyleData>);
impl NonOpaqueStyleData {
pub fn new() -> Self {
NonOpaqueStyleData(RefCell::new(PrivateStyleData::new()))
}
}
pub struct GeckoDeclarationBlock {
pub declarations: Option<Arc<PropertyDeclarationBlock>>,
// XXX The following two fields are made atomic to work around the
// ownership system so that they can be changed inside a shared
// instance. It wouldn't provide safety as Rust usually promises,
// but it is fine as far as we only access them in a single thread.
// If we need to access them in different threads, we would need
// to redesign how it works with MiscContainer in Gecko side.
pub cache: AtomicPtr<bindings::nsHTMLCSSStyleSheet>,
pub immutable: AtomicBool,
}
unsafe impl HasFFI for GeckoDeclarationBlock {
type FFIType = bindings::ServoDeclarationBlock;
}
unsafe impl HasArcFFI for GeckoDeclarationBlock {}
// We can eliminate OpaqueStyleData when the bindings move into the style crate.
fn to_opaque_style_data(d: *mut NonOpaqueStyleData) -> *mut OpaqueStyleData {
d as *mut OpaqueStyleData
}
fn from_opaque_style_data(d: *mut OpaqueStyleData) -> *mut NonOpaqueStyleData {
d as *mut NonOpaqueStyleData
}
// Important: We don't currently refcount the DOM, because the wrapper lifetime
// magic guarantees that our LayoutFoo references won't outlive the root, and
// we don't mutate any of the references on the Gecko side during restyle. We
// could implement refcounting if need be (at a potentially non-trivial
// performance cost) by implementing Drop and making LayoutFoo non-Copy.
#[derive(Clone, Copy)]
pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
impl<'ln> GeckoNode<'ln> {
fn get_node_data(&self) -> Option<&NonOpaqueStyleData> {
unsafe {
from_opaque_style_data(self.0.mServoData.get()).as_ref()
}
}
pub fn initialize_data(self) {
if self.get_node_data().is_none() {
let ptr = Box::new(NonOpaqueStyleData::new());
debug_assert!(self.0.mServoData.get().is_null());
self.0.mServoData.set(to_opaque_style_data(Box::into_raw(ptr)));
}
}
pub fn clear_data(self) {
if !self.get_node_data().is_none() {
let d = from_opaque_style_data(self.0.mServoData.get());
let _ = unsafe { Box::from_raw(d) };
self.0.mServoData.set(ptr::null_mut());
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct GeckoRestyleDamage(nsChangeHint);
impl TRestyleDamage for GeckoRestyleDamage {
type PreExistingComputedValues = nsStyleContext;
fn empty() -> Self {
use std::mem;
GeckoRestyleDamage(unsafe { mem::transmute(0u32) })
}
fn compute(source: &nsStyleContext,
new_style: &Arc<ComputedValues>) -> Self {
let context = source as *const nsStyleContext as *mut nsStyleContext;
let hint = unsafe { Gecko_CalcStyleDifference(context, new_style.as_borrowed()) };
GeckoRestyleDamage(hint)
}
fn rebuild_and_reflow() -> Self {
GeckoRestyleDamage(nsChangeHint::nsChangeHint_ReconstructFrame)
}
}
impl BitOr for GeckoRestyleDamage {
type Output = Self;
fn bitor(self, other: Self) -> Self {
use std::mem;
GeckoRestyleDamage(unsafe { mem::transmute(self.0 as u32 | other.0 as u32) })
}
}
impl<'ln> NodeInfo for GeckoNode<'ln> {
fn is_element(&self) -> bool {
unsafe {
Gecko_NodeIsElement(self.0)
}
}
fn is_text_node(&self) -> bool {
unsafe {
Gecko_IsTextNode(self.0)
}
}
}
impl<'ln> TNode for GeckoNode<'ln> {
type ConcreteDocument = GeckoDocument<'ln>;
type ConcreteElement = GeckoElement<'ln>;
type ConcreteRestyleDamage = GeckoRestyleDamage;
type ConcreteChildrenIterator = GeckoChildrenIterator<'ln>;
fn to_unsafe(&self) -> UnsafeNode {
(self.0 as *const _ as usize, 0)
}
unsafe fn from_unsafe(n: &UnsafeNode) -> Self {
GeckoNode(&*(n.0 as *mut RawGeckoNode))
}
fn dump(self) {
unimplemented!()
}
fn dump_style(self) {
unimplemented!()
}
fn children(self) -> LayoutIterator<GeckoChildrenIterator<'ln>> {
let maybe_iter = unsafe { Gecko_MaybeCreateStyleChildrenIterator(self.0) };
if let Some(iter) = maybe_iter.into_owned_opt() {
LayoutIterator(GeckoChildrenIterator::GeckoIterator(iter))
} else {
LayoutIterator(GeckoChildrenIterator::Current(self.first_child()))
}
}
fn opaque(&self) -> OpaqueNode {
let ptr: uintptr_t = self.0 as *const _ as uintptr_t;
OpaqueNode(ptr)
}
fn layout_parent_node(self, reflow_root: OpaqueNode) -> Option<GeckoNode<'ln>> {
if self.opaque() == reflow_root {
None
} else {
self.parent_node()
}
}
fn debug_id(self) -> usize {
unimplemented!()
}
fn as_element(&self) -> Option<GeckoElement<'ln>> {
if self.is_element() {
unsafe { Some(GeckoElement(&*(self.0 as *const _ as *const RawGeckoElement))) }
} else {
None
}
}
fn as_document(&self) -> Option<GeckoDocument<'ln>> {
unimplemented!()
}
// NOTE: This is not relevant for Gecko, since we get explicit restyle hints
// when a content has changed.
fn has_changed(&self) -> bool { false }
unsafe fn set_changed(&self, _value: bool) {
unimplemented!()
}
fn is_dirty(&self) -> bool {
// Return true unconditionally if we're not yet styled. This is a hack
// and should go away soon.
if self.get_node_data().is_none() {
return true;
}
let flags = unsafe { Gecko_GetNodeFlags(self.0) };
flags & (NODE_IS_DIRTY_FOR_SERVO as u32) != 0
}
unsafe fn set_dirty(&self, value: bool) {
if value {
Gecko_SetNodeFlags(self.0, NODE_IS_DIRTY_FOR_SERVO as u32)
} else {
Gecko_UnsetNodeFlags(self.0, NODE_IS_DIRTY_FOR_SERVO as u32)
}
}
fn has_dirty_descendants(&self) -> bool {
// Return true unconditionally if we're not yet styled. This is a hack
// and should go away soon.
if self.get_node_data().is_none() {
return true;
}
let flags = unsafe { Gecko_GetNodeFlags(self.0) };
flags & (NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32) != 0
}
unsafe fn set_dirty_descendants(&self, value: bool) {
if value {
Gecko_SetNodeFlags(self.0, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
} else {
Gecko_UnsetNodeFlags(self.0, NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO as u32)
}
}
fn can_be_fragmented(&self) -> bool {
// FIXME(SimonSapin): Servo uses this to implement CSS multicol / fragmentation
// Maybe this isnt useful for Gecko?
false
}
unsafe fn set_can_be_fragmented(&self, _value: bool) {
// FIXME(SimonSapin): Servo uses this to implement CSS multicol / fragmentation
// Maybe this isnt useful for Gecko?
}
#[inline(always)]
unsafe fn borrow_data_unchecked(&self) -> Option<*const PrivateStyleData> {
self.get_node_data().as_ref().map(|d| d.0.as_unsafe_cell().get()
as *const PrivateStyleData)
}
#[inline(always)]
fn borrow_data(&self) -> Option<Ref<PrivateStyleData>> {
self.get_node_data().as_ref().map(|d| d.0.borrow())
}
#[inline(always)]
fn mutate_data(&self) -> Option<RefMut<PrivateStyleData>> {
self.get_node_data().as_ref().map(|d| d.0.borrow_mut())
}
fn restyle_damage(self) -> Self::ConcreteRestyleDamage {
// Not called from style, only for layout.
unimplemented!();
}
fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage) {
unsafe { Gecko_StoreStyleDifference(self.0, damage.0) }
}
fn parent_node(&self) -> Option<GeckoNode<'ln>> {
unsafe {
Gecko_GetParentNode(self.0).borrow_opt().map(|n| GeckoNode(n))
}
}
fn first_child(&self) -> Option<GeckoNode<'ln>> {
unsafe {
Gecko_GetFirstChild(self.0).borrow_opt().map(|n| GeckoNode(n))
}
}
fn last_child(&self) -> Option<GeckoNode<'ln>> {
unsafe {
Gecko_GetLastChild(self.0).borrow_opt().map(|n| GeckoNode(n))
}
}
fn prev_sibling(&self) -> Option<GeckoNode<'ln>> {
unsafe {
Gecko_GetPrevSibling(self.0).borrow_opt().map(|n| GeckoNode(n))
}
}
fn next_sibling(&self) -> Option<GeckoNode<'ln>> {
unsafe {
Gecko_GetNextSibling(self.0).borrow_opt().map(|n| GeckoNode(n))
}
}
fn existing_style_for_restyle_damage<'a>(&'a self,
current_cv: Option<&'a Arc<ComputedValues>>,
pseudo: Option<&PseudoElement>)
-> Option<&'a nsStyleContext> {
if current_cv.is_none() {
// Don't bother in doing an ffi call to get null back.
return None;
}
unsafe {
let atom_ptr = pseudo.map(|p| p.as_atom().as_ptr())
.unwrap_or(ptr::null_mut());
let context_ptr = Gecko_GetStyleContext(self.0, atom_ptr);
context_ptr.as_ref()
}
}
fn needs_dirty_on_viewport_size_changed(&self) -> bool {
// Gecko's node doesn't have the DIRTY_ON_VIEWPORT_SIZE_CHANGE flag,
// so we force them to be dirtied on viewport size change, regardless if
// they use viewport percentage size or not.
// TODO(shinglyu): implement this in Gecko: https://github.com/servo/servo/pull/11890
true
}
// TODO(shinglyu): implement this in Gecko: https://github.com/servo/servo/pull/11890
unsafe fn set_dirty_on_viewport_size_changed(&self) {}
}
// We generally iterate children by traversing the siblings of the first child
// like Servo does. However, for nodes with anonymous children, we use a custom
// (heavier-weight) Gecko-implemented iterator.
pub enum GeckoChildrenIterator<'a> {
Current(Option<GeckoNode<'a>>),
GeckoIterator(bindings::StyleChildrenIteratorOwned),
}
impl<'a> Drop for GeckoChildrenIterator<'a> {
fn drop(&mut self) {
if let GeckoChildrenIterator::GeckoIterator(ref it) = *self {
unsafe {
Gecko_DropStyleChildrenIterator(ptr::read(it as *const _));
}
}
}
}
impl<'a> Iterator for GeckoChildrenIterator<'a> {
type Item = GeckoNode<'a>;
fn next(&mut self) -> Option<GeckoNode<'a>> {
match *self {
GeckoChildrenIterator::Current(curr) => {
let next = curr.and_then(|node| node.next_sibling());
*self = GeckoChildrenIterator::Current(next);
curr
},
GeckoChildrenIterator::GeckoIterator(ref it) => unsafe {
Gecko_GetNextStyleChild(&it).borrow_opt().map(GeckoNode)
}
}
}
}
#[derive(Clone, Copy)]
pub struct GeckoDocument<'ld>(pub &'ld RawGeckoDocument);
impl<'ld> TDocument for GeckoDocument<'ld> {
type ConcreteNode = GeckoNode<'ld>;
type ConcreteElement = GeckoElement<'ld>;
fn as_node(&self) -> GeckoNode<'ld> {
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
}
fn root_node(&self) -> Option<GeckoNode<'ld>> {
unsafe {
Gecko_GetDocumentElement(self.0).borrow_opt().map(|el| GeckoElement(el).as_node())
}
}
fn drain_modified_elements(&self) -> Vec<(GeckoElement<'ld>, GeckoElementSnapshot)> {
unimplemented!()
/*
let elements = unsafe { self.0.drain_modified_elements() };
elements.into_iter().map(|(el, snapshot)| (ServoLayoutElement::from_layout_js(el), snapshot)).collect()*/
}
fn will_paint(&self) { unimplemented!() }
fn needs_paint_from_layout(&self) { unimplemented!() }
}
#[derive(Clone, Copy)]
pub struct GeckoElement<'le>(pub &'le RawGeckoElement);
impl<'le> fmt::Debug for GeckoElement<'le> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "<{}", self.get_local_name()));
if let Some(id) = self.get_id() {
try!(write!(f, " id={}", id));
}
write!(f, ">")
}
}
impl<'le> GeckoElement<'le> {
pub fn parse_style_attribute(value: &str) -> Option<PropertyDeclarationBlock> {
// FIXME(bholley): Real base URL and error reporter.
let base_url = &*DUMMY_BASE_URL;
// FIXME(heycam): Needs real ParserContextExtraData so that URLs parse
// properly.
let extra_data = ParserContextExtraData::default();
Some(parse_style_attribute(value, &base_url, Box::new(StdoutErrorReporter), extra_data))
}
}
lazy_static! {
pub static ref DUMMY_BASE_URL: Url = {
Url::parse("http://www.example.org").unwrap()
};
}
impl<'le> TElement for GeckoElement<'le> {
type ConcreteNode = GeckoNode<'le>;
type ConcreteDocument = GeckoDocument<'le>;
fn as_node(&self) -> Self::ConcreteNode {
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
}
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.0) };
if declarations.is_null() {
None
} else {
let declarations = declarations.as_arc::<GeckoDeclarationBlock>();
declarations.declarations.as_ref().map(|r| r as *const Arc<_>).map(|ptr| unsafe { &*ptr })
}
}
fn get_state(&self) -> ElementState {
unsafe {
ElementState::from_bits_truncate(Gecko_ElementState(self.0) as u16)
}
}
#[inline]
fn has_attr(&self, namespace: &Namespace, attr: &Atom) -> bool {
unsafe {
bindings::Gecko_HasAttr(self.0,
namespace.0.as_ptr(),
attr.as_ptr())
}
}
#[inline]
fn attr_equals(&self, namespace: &Namespace, attr: &Atom, val: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrEquals(self.0,
namespace.0.as_ptr(),
attr.as_ptr(),
val.as_ptr(),
/* ignoreCase = */ false)
}
}
}
impl<'le> PartialEq for GeckoElement<'le> {
fn eq(&self, other: &Self) -> bool {
self.0 as *const _ == other.0 as *const _
}
}
impl<'le> PresentationalHintsSynthetizer for GeckoElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
where V: Push<ApplicableDeclarationBlock>
{
// FIXME(bholley) - Need to implement this.
}
}
impl<'le> ::selectors::Element for GeckoElement<'le> {
fn parent_element(&self) -> Option<Self> {
unsafe {
Gecko_GetParentElement(self.0).borrow_opt().map(|el| GeckoElement(el))
}
}
fn first_child_element(&self) -> Option<Self> {
unsafe {
Gecko_GetFirstChildElement(self.0).borrow_opt().map(|el| GeckoElement(el))
}
}
fn last_child_element(&self) -> Option<Self> {
unsafe {
Gecko_GetLastChildElement(self.0).borrow_opt().map(|el| GeckoElement(el))
}
}
fn prev_sibling_element(&self) -> Option<Self> {
unsafe {
Gecko_GetPrevSiblingElement(self.0).borrow_opt().map(|el| GeckoElement(el))
}
}
fn next_sibling_element(&self) -> Option<Self> {
unsafe {
Gecko_GetNextSiblingElement(self.0).borrow_opt().map(|el| GeckoElement(el))
}
}
fn is_root(&self) -> bool {
unsafe {
Gecko_IsRootElement(self.0)
}
}
fn is_empty(&self) -> bool {
// XXX(emilio): Implement this properly.
false
}
fn get_local_name(&self) -> &WeakAtom {
unsafe {
WeakAtom::new(Gecko_LocalName(self.0))
}
}
fn get_namespace(&self) -> &WeakNamespace {
unsafe {
WeakNamespace::new(Gecko_Namespace(self.0))
}
}
fn match_non_ts_pseudo_class(&self, pseudo_class: NonTSPseudoClass) -> bool {
match pseudo_class {
// https://github.com/servo/servo/issues/8718
NonTSPseudoClass::AnyLink => unsafe { Gecko_IsLink(self.0) },
NonTSPseudoClass::Link => unsafe { Gecko_IsUnvisitedLink(self.0) },
NonTSPseudoClass::Visited => unsafe { Gecko_IsVisitedLink(self.0) },
NonTSPseudoClass::Active |
NonTSPseudoClass::Focus |
NonTSPseudoClass::Hover |
NonTSPseudoClass::Enabled |
NonTSPseudoClass::Disabled |
NonTSPseudoClass::Checked |
NonTSPseudoClass::ReadWrite |
NonTSPseudoClass::Indeterminate => {
self.get_state().contains(pseudo_class.state_flag())
},
NonTSPseudoClass::ReadOnly => {
!self.get_state().contains(pseudo_class.state_flag())
}
}
}
fn get_id(&self) -> Option<Atom> {
let ptr = unsafe {
bindings::Gecko_AtomAttrValue(self.0,
atom!("id").as_ptr())
};
if ptr.is_null() {
None
} else {
Some(Atom::from(ptr))
}
}
fn has_class(&self, name: &Atom) -> bool {
snapshot_helpers::has_class(self.0,
name,
Gecko_ClassOrClassList)
}
fn each_class<F>(&self, callback: F)
where F: FnMut(&Atom)
{
snapshot_helpers::each_class(self.0,
callback,
Gecko_ClassOrClassList)
}
fn is_html_element_in_html_document(&self) -> bool {
unsafe {
Gecko_IsHTMLElementInHTMLDocument(self.0)
}
}
}
pub trait AttrSelectorHelpers {
fn ns_or_null(&self) -> *mut nsIAtom;
fn select_name(&self, is_html_element_in_html_document: bool) -> *mut nsIAtom;
}
impl AttrSelectorHelpers for AttrSelector<GeckoSelectorImpl> {
fn ns_or_null(&self) -> *mut nsIAtom {
match self.namespace {
NamespaceConstraint::Any => ptr::null_mut(),
NamespaceConstraint::Specific(ref ns) => ns.url.0.as_ptr(),
}
}
fn select_name(&self, is_html_element_in_html_document: bool) -> *mut nsIAtom {
if is_html_element_in_html_document {
self.lower_name.as_ptr()
} else {
self.name.as_ptr()
}
}
}
impl<'le> ::selectors::MatchAttr for GeckoElement<'le> {
type Impl = GeckoSelectorImpl;
fn match_attr_has(&self, attr: &AttrSelector<Self::Impl>) -> bool {
unsafe {
bindings::Gecko_HasAttr(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()))
}
}
fn match_attr_equals(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrEquals(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr(),
/* ignoreCase = */ false)
}
}
fn match_attr_equals_ignore_ascii_case(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrEquals(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr(),
/* ignoreCase = */ false)
}
}
fn match_attr_includes(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrIncludes(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_dash(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrDashEquals(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_prefix(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrHasPrefix(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_substring(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrHasSubstring(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
fn match_attr_suffix(&self, attr: &AttrSelector<Self::Impl>, value: &Atom) -> bool {
unsafe {
bindings::Gecko_AttrHasSuffix(self.0,
attr.ns_or_null(),
attr.select_name(self.is_html_element_in_html_document()),
value.as_ptr())
}
}
}
impl<'le> ElementExt for GeckoElement<'le> {
type Snapshot = GeckoElementSnapshot;
#[inline]
fn is_link(&self) -> bool {
self.match_non_ts_pseudo_class(NonTSPseudoClass::AnyLink)
}
}

View file

@ -165,10 +165,10 @@ use gecko_bindings::structs::nsINode;
use gecko_bindings::structs::nsIDocument;
use gecko_bindings::structs::nsIPrincipal;
use gecko_bindings::structs::nsIURI;
use structs::RawGeckoNode;
use structs::RawGeckoElement;
use structs::RawGeckoDocument;
use structs::ServoNodeData;
use gecko_bindings::structs::RawGeckoNode;
use gecko_bindings::structs::RawGeckoElement;
use gecko_bindings::structs::RawGeckoDocument;
use gecko_bindings::structs::ServoNodeData;
extern "C" {
pub fn Gecko_EnsureTArrayCapacity(aArray: *mut ::std::os::raw::c_void,

View file

@ -5,9 +5,9 @@
use gecko_bindings::bindings::Gecko_AddRefCSSShadowArrayArbitraryThread;
use gecko_bindings::bindings::Gecko_NewCSSShadowArray;
use gecko_bindings::bindings::Gecko_ReleaseCSSShadowArrayArbitraryThread;
use gecko_bindings::structs::{RefPtr, nsCSSShadowArray, nsCSSShadowItem};
use std::{ptr, slice};
use std::ops::{Deref, DerefMut};
use gecko_bindings::structs::{RefPtr, nsCSSShadowArray, nsCSSShadowItem};
impl RefPtr<nsCSSShadowArray> {
pub fn replace_with_new(&mut self, len: u32) {

View file

@ -2,9 +2,9 @@
* 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/. */
use gecko_bindings::structs::nsStyleAutoArray;
use std::iter::{once, Chain, Once, IntoIterator};
use std::slice::{Iter, IterMut};
use gecko_bindings::structs::nsStyleAutoArray;
impl<T> nsStyleAutoArray<T> {
pub fn iter_mut(&mut self) -> Chain<Once<&mut T>, IterMut<T>> {

View file

@ -3,9 +3,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use gecko_bindings::bindings::{Gecko_ResetStyleCoord, Gecko_SetStyleCoordCalcValue, Gecko_AddRefCalcArbitraryThread};
use std::mem;
use gecko_bindings::structs::{nsStyleCoord_Calc, nsStyleUnit, nsStyleUnion, nsStyleCoord, nsStyleSides, nsStyleCorners};
use gecko_bindings::structs::{nsStyleCoord_CalcValue, nscoord};
use std::mem;
impl nsStyleCoord {
#[inline]
@ -245,8 +245,8 @@ pub trait CoordDataMut : CoordData {
#[inline(always)]
fn set_value(&mut self, value: CoordDataValue) {
use self::CoordDataValue::*;
use gecko_bindings::structs::nsStyleUnit::*;
use self::CoordDataValue::*;
self.reset();
unsafe {
let (unit, union) = self.values_mut();
@ -337,8 +337,8 @@ pub trait CoordData {
#[inline(always)]
fn as_value(&self) -> CoordDataValue {
use self::CoordDataValue::*;
use gecko_bindings::structs::nsStyleUnit::*;
use self::CoordDataValue::*;
unsafe {
match self.unit() {
eStyleUnit_Null => Null,

View file

@ -3,11 +3,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use gecko_bindings::bindings;
use gecko_bindings::structs::{nsTArray, nsTArrayHeader};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::os::raw::c_void;
use std::slice;
use gecko_bindings::structs::{nsTArray, nsTArrayHeader};
impl<T> Deref for nsTArray<T> {
type Target = [T];

View file

@ -2,6 +2,8 @@
* 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/. */
#![allow(unsafe_code)]
use gecko_bindings::bindings::Gecko_AddRefAtom;
use gecko_bindings::bindings::Gecko_Atomize;
use gecko_bindings::bindings::Gecko_ReleaseAtom;
@ -9,7 +11,6 @@ use gecko_bindings::structs::nsIAtom;
use heapsize::HeapSizeOf;
use selectors::bloom::BloomHash;
use selectors::parser::FromCowStr;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::ascii::AsciiExt;
use std::borrow::{Cow, Borrow};
use std::char::{self, DecodeUtf16};
@ -236,19 +237,6 @@ impl HeapSizeOf for Atom {
}
}
impl Serialize for Atom {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
self.with_str(|s| s.serialize(serializer))
}
}
impl Deserialize for Atom {
fn deserialize<D>(deserializer: &mut D) -> Result<Atom, D::Error> where D: Deserializer {
let string: String = try!(Deserialize::deserialize(deserializer));
Ok(Atom::from(&*string))
}
}
impl fmt::Debug for Atom {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
write!(w, "Gecko Atom({:p}, {})", self.0, self)

View file

@ -2,12 +2,12 @@
* 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/. */
use string_cache::{Atom, WeakAtom};
use gecko_bindings::structs::nsIAtom;
use selectors::bloom::BloomHash;
use std::borrow::Borrow;
use std::fmt;
use std::ops::Deref;
use string_cache::{Atom, WeakAtom};
#[macro_export]
macro_rules! ns {

View file

@ -51,6 +51,7 @@ extern crate heapsize;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
#[allow(unused_extern_crates)]
@ -58,11 +59,13 @@ extern crate log;
extern crate matches;
extern crate num_integer;
extern crate num_traits;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate ordered_float;
extern crate quickersort;
extern crate rand;
extern crate rustc_serialize;
extern crate selectors;
#[cfg(feature = "servo")]
extern crate serde;
extern crate smallvec;
#[cfg(feature = "servo")] #[macro_use] extern crate string_cache;
@ -74,7 +77,6 @@ extern crate util;
#[cfg(feature = "gecko")]
#[path = "./gecko_string_cache/mod.rs"]
#[allow(unsafe_code)]
#[macro_use] pub mod string_cache;
pub mod animation;