mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
commit
0265fb9784
6 changed files with 110 additions and 134 deletions
|
@ -216,18 +216,17 @@ impl StyleSharingCandidate {
|
||||||
|
|
||||||
let mut style = Some(style);
|
let mut style = Some(style);
|
||||||
let mut parent_style = Some(parent_style);
|
let mut parent_style = Some(parent_style);
|
||||||
node.with_element(|element| {
|
let element = node.as_element();
|
||||||
if element.style_attribute().is_some() {
|
if element.style_attribute().is_some() {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(StyleSharingCandidate {
|
Some(StyleSharingCandidate {
|
||||||
style: style.take_unwrap(),
|
style: style.take_unwrap(),
|
||||||
parent_style: parent_style.take_unwrap(),
|
parent_style: parent_style.take_unwrap(),
|
||||||
local_name: element.get_local_name().to_str(),
|
local_name: element.get_local_name().to_str(),
|
||||||
class: element.get_attr(&Null, "class")
|
class: element.get_attr(&Null, "class")
|
||||||
.map(|string| string.to_str()),
|
.map(|string| string.to_str()),
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +400,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check tag names, classes, etc.
|
// Check tag names, classes, etc.
|
||||||
if !self.with_element(|element| candidate.can_share_style_with(element)) {
|
if !candidate.can_share_style_with(&self.as_element()) {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,9 +418,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
applicable_declarations: &mut ApplicableDeclarations,
|
||||||
shareable: &mut bool) {
|
shareable: &mut bool) {
|
||||||
let style_attribute = self.with_element(|element| {
|
let style_attribute = self.as_element().style_attribute().as_ref();
|
||||||
element.style_attribute().as_ref()
|
|
||||||
});
|
|
||||||
|
|
||||||
applicable_declarations.normal_shareable =
|
applicable_declarations.normal_shareable =
|
||||||
stylist.push_applicable_declarations(self,
|
stylist.push_applicable_declarations(self,
|
||||||
|
@ -448,9 +445,10 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
if !self.is_element() {
|
if !self.is_element() {
|
||||||
return CannotShare(false)
|
return CannotShare(false)
|
||||||
}
|
}
|
||||||
let ok = self.with_element(|element| {
|
let ok = {
|
||||||
|
let element = self.as_element();
|
||||||
element.style_attribute().is_none() && element.get_attr(&Null, "id").is_none()
|
element.style_attribute().is_none() && element.get_attr(&Null, "id").is_none()
|
||||||
});
|
};
|
||||||
if !ok {
|
if !ok {
|
||||||
return CannotShare(false)
|
return CannotShare(false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,12 +132,11 @@ impl ImageBoxInfo {
|
||||||
local_image_cache: MutexArc<LocalImageCache>)
|
local_image_cache: MutexArc<LocalImageCache>)
|
||||||
-> ImageBoxInfo {
|
-> ImageBoxInfo {
|
||||||
fn convert_length(node: &ThreadSafeLayoutNode, name: &str) -> Option<Au> {
|
fn convert_length(node: &ThreadSafeLayoutNode, name: &str) -> Option<Au> {
|
||||||
node.with_element(|element| {
|
let element = node.as_element();
|
||||||
element.get_attr(&namespace::Null, name).and_then(|string| {
|
element.get_attr(&namespace::Null, name).and_then(|string| {
|
||||||
let n: Option<int> = FromStr::from_str(string);
|
let n: Option<int> = FromStr::from_str(string);
|
||||||
n
|
n
|
||||||
}).and_then(|pixels| Some(Au::from_px(pixels)))
|
}).and_then(|pixels| Some(Au::from_px(pixels)))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageBoxInfo {
|
ImageBoxInfo {
|
||||||
|
|
|
@ -851,8 +851,8 @@ trait ObjectElement {
|
||||||
|
|
||||||
impl<'ln> ObjectElement for ThreadSafeLayoutNode<'ln> {
|
impl<'ln> ObjectElement for ThreadSafeLayoutNode<'ln> {
|
||||||
fn get_type_and_data(&self) -> (Option<&'static str>, Option<&'static str>) {
|
fn get_type_and_data(&self) -> (Option<&'static str>, Option<&'static str>) {
|
||||||
(self.with_element(|e| { e.get_attr(&namespace::Null, "type") } ),
|
let elem = self.as_element();
|
||||||
self.with_element(|e| { e.get_attr(&namespace::Null, "data") } ))
|
(elem.get_attr(&namespace::Null, "type"), elem.get_attr(&namespace::Null, "data"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_object_data(&self) -> bool {
|
fn has_object_data(&self) -> bool {
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
//! `html_element_in_html_document_for_layout()`.
|
//! `html_element_in_html_document_for_layout()`.
|
||||||
|
|
||||||
use extra::url::Url;
|
use extra::url::Url;
|
||||||
use script::dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLIFrameElementDerived};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementDerived};
|
||||||
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
|
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
|
||||||
use script::dom::bindings::js::JS;
|
use script::dom::bindings::js::JS;
|
||||||
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
|
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
|
||||||
|
@ -228,16 +228,13 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
|
|
||||||
/// If this is an element, accesses the element data. Fails if this is not an element node.
|
/// If this is an element, accesses the element data. Fails if this is not an element node.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_element<R>(&self, f: |&LayoutElement<'ln>| -> R) -> R {
|
fn as_element(&self) -> LayoutElement<'ln> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if !self.node.is_element() {
|
|
||||||
fail!("not an element!")
|
|
||||||
}
|
|
||||||
let elem: JS<Element> = self.node.transmute_copy();
|
let elem: JS<Element> = self.node.transmute_copy();
|
||||||
let element = elem.get();
|
let element = elem.get();
|
||||||
f(&LayoutElement {
|
LayoutElement {
|
||||||
element: cast::transmute_region(element),
|
element: cast::transmute_region(element),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,23 +247,22 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
|
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
|
||||||
self.with_element(|element| {
|
let element = self.as_element();
|
||||||
let name = unsafe {
|
let name = unsafe {
|
||||||
if element.element.html_element_in_html_document_for_layout() {
|
if element.element.html_element_in_html_document_for_layout() {
|
||||||
attr.lower_name.as_slice()
|
attr.lower_name.as_slice()
|
||||||
} else {
|
} else {
|
||||||
attr.name.as_slice()
|
attr.name.as_slice()
|
||||||
}
|
|
||||||
};
|
|
||||||
match attr.namespace {
|
|
||||||
SpecificNamespace(ref ns) => {
|
|
||||||
element.get_attr(ns, name)
|
|
||||||
.map_or(false, |attr| test(attr))
|
|
||||||
},
|
|
||||||
// FIXME: https://github.com/mozilla/servo/issues/1558
|
|
||||||
AnyNamespace => false,
|
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
|
match attr.namespace {
|
||||||
|
SpecificNamespace(ref ns) => {
|
||||||
|
element.get_attr(ns, name)
|
||||||
|
.map_or(false, |attr| test(attr))
|
||||||
|
},
|
||||||
|
// FIXME: https://github.com/mozilla/servo/issues/1558
|
||||||
|
AnyNamespace => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,18 +429,15 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
|
||||||
|
|
||||||
/// If this is an element, accesses the element data. Fails if this is not an element node.
|
/// If this is an element, accesses the element data. Fails if this is not an element node.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn with_element<R>(&self, f: |&ThreadSafeLayoutElement| -> R) -> R {
|
pub fn as_element(&self) -> ThreadSafeLayoutElement {
|
||||||
unsafe {
|
unsafe {
|
||||||
if !self.node.is_element() {
|
|
||||||
fail!("not an element!")
|
|
||||||
}
|
|
||||||
let elem: JS<Element> = self.node.transmute_copy();
|
let elem: JS<Element> = self.node.transmute_copy();
|
||||||
let element = elem.unsafe_get();
|
let element = elem.unsafe_get();
|
||||||
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
|
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
|
||||||
// implementations.
|
// implementations.
|
||||||
f(&ThreadSafeLayoutElement {
|
ThreadSafeLayoutElement {
|
||||||
element: cast::transmute::<*mut Element,&mut Element>(element),
|
element: cast::transmute::<*mut Element,&mut Element>(element),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,7 @@ pub trait TNode<E:TElement> : Clone {
|
||||||
fn next_sibling(&self) -> Option<Self>;
|
fn next_sibling(&self) -> Option<Self>;
|
||||||
fn is_document(&self) -> bool;
|
fn is_document(&self) -> bool;
|
||||||
fn is_element(&self) -> bool;
|
fn is_element(&self) -> bool;
|
||||||
|
fn as_element(&self) -> E;
|
||||||
/// FIXME(pcwalton): This should not use the `with` pattern.
|
|
||||||
fn with_element<'a, R>(&self, f: |&E| -> R) -> R;
|
|
||||||
|
|
||||||
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool;
|
fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,44 +117,43 @@ impl SelectorMap {
|
||||||
|
|
||||||
// At the end, we're going to sort the rules that we added, so remember where we began.
|
// At the end, we're going to sort the rules that we added, so remember where we began.
|
||||||
let init_len = matching_rules_list.len();
|
let init_len = matching_rules_list.len();
|
||||||
node.with_element(|element: &E| {
|
let element = node.as_element();
|
||||||
match element.get_attr(&namespace::Null, "id") {
|
match element.get_attr(&namespace::Null, "id") {
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
|
SelectorMap::get_matching_rules_from_hash(node,
|
||||||
|
&self.id_hash,
|
||||||
|
id,
|
||||||
|
matching_rules_list,
|
||||||
|
shareable)
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match element.get_attr(&namespace::Null, "class") {
|
||||||
|
Some(ref class_attr) => {
|
||||||
|
for class in class_attr.split(SELECTOR_WHITESPACE) {
|
||||||
SelectorMap::get_matching_rules_from_hash(node,
|
SelectorMap::get_matching_rules_from_hash(node,
|
||||||
&self.id_hash,
|
&self.class_hash,
|
||||||
id,
|
class,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
shareable)
|
shareable);
|
||||||
}
|
}
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
match element.get_attr(&namespace::Null, "class") {
|
// HTML elements in HTML documents must be matched case-insensitively.
|
||||||
Some(ref class_attr) => {
|
// TODO(pradeep): Case-sensitivity depends on the document type.
|
||||||
for class in class_attr.split(SELECTOR_WHITESPACE) {
|
SelectorMap::get_matching_rules_from_hash_ignoring_case(node,
|
||||||
SelectorMap::get_matching_rules_from_hash(node,
|
&self.element_hash,
|
||||||
&self.class_hash,
|
element.get_local_name(),
|
||||||
class,
|
matching_rules_list,
|
||||||
matching_rules_list,
|
shareable);
|
||||||
shareable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTML elements in HTML documents must be matched case-insensitively.
|
SelectorMap::get_matching_rules(node,
|
||||||
// TODO(pradeep): Case-sensitivity depends on the document type.
|
self.universal_rules,
|
||||||
SelectorMap::get_matching_rules_from_hash_ignoring_case(node,
|
matching_rules_list,
|
||||||
&self.element_hash,
|
shareable);
|
||||||
element.get_local_name(),
|
|
||||||
matching_rules_list,
|
|
||||||
shareable);
|
|
||||||
|
|
||||||
SelectorMap::get_matching_rules(node,
|
|
||||||
self.universal_rules,
|
|
||||||
matching_rules_list,
|
|
||||||
shareable);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort only the rules we just added.
|
// Sort only the rules we just added.
|
||||||
sort::quicksort(matching_rules_list.mut_slice_from(init_len));
|
sort::quicksort(matching_rules_list.mut_slice_from(init_len));
|
||||||
|
@ -582,36 +581,32 @@ fn matches_simple_selector<E:TElement,
|
||||||
// TODO: case-sensitivity depends on the document type
|
// TODO: case-sensitivity depends on the document type
|
||||||
// TODO: intern element names
|
// TODO: intern element names
|
||||||
LocalNameSelector(ref name) => {
|
LocalNameSelector(ref name) => {
|
||||||
element.with_element(|element: &E| {
|
let element = element.as_element();
|
||||||
element.get_local_name().eq_ignore_ascii_case(name.as_slice())
|
element.get_local_name().eq_ignore_ascii_case(name.as_slice())
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NamespaceSelector(ref namespace) => {
|
NamespaceSelector(ref namespace) => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
element.with_element(|element: &E| {
|
let element = element.as_element();
|
||||||
element.get_namespace() == namespace
|
element.get_namespace() == namespace
|
||||||
})
|
|
||||||
}
|
}
|
||||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||||
// TODO: cache and intern IDs on elements.
|
// TODO: cache and intern IDs on elements.
|
||||||
IDSelector(ref id) => {
|
IDSelector(ref id) => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
element.with_element(|element: &E| {
|
let element = element.as_element();
|
||||||
element.get_attr(&namespace::Null, "id")
|
element.get_attr(&namespace::Null, "id")
|
||||||
.map_or(false, |attr| {
|
.map_or(false, |attr| {
|
||||||
attr == *id
|
attr == *id
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// TODO: cache and intern class names on elements.
|
// TODO: cache and intern class names on elements.
|
||||||
ClassSelector(ref class) => {
|
ClassSelector(ref class) => {
|
||||||
element.with_element(|element: &E| {
|
let element = element.as_element();
|
||||||
element.get_attr(&namespace::Null, "class")
|
element.get_attr(&namespace::Null, "class")
|
||||||
.map_or(false, |attr| {
|
.map_or(false, |attr| {
|
||||||
// TODO: case-sensitivity depends on the document type and quirks mode
|
// TODO: case-sensitivity depends on the document type and quirks mode
|
||||||
attr.split(SELECTOR_WHITESPACE).any(|c| c == class.as_slice())
|
attr.split(SELECTOR_WHITESPACE).any(|c| c == class.as_slice())
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,34 +658,30 @@ fn matches_simple_selector<E:TElement,
|
||||||
|
|
||||||
AnyLink => {
|
AnyLink => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
element.with_element(|element: &E| {
|
let element = element.as_element();
|
||||||
element.get_link().is_some()
|
element.get_link().is_some()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
Link => {
|
Link => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
element.with_element(|element: &E| {
|
let elem = element.as_element();
|
||||||
match element.get_link() {
|
match elem.get_link() {
|
||||||
Some(url) => !url_is_visited(url),
|
Some(url) => !url_is_visited(url),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
Visited => {
|
Visited => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
element.with_element(|element: &E| {
|
let elem = element.as_element();
|
||||||
match element.get_link() {
|
match elem.get_link() {
|
||||||
Some(url) => url_is_visited(url),
|
Some(url) => url_is_visited(url),
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Hover => {
|
Hover => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
element.with_element(|element: &E| {
|
let elem = element.as_element();
|
||||||
element.get_hover_state()
|
elem.get_hover_state()
|
||||||
})
|
|
||||||
},
|
},
|
||||||
FirstChild => {
|
FirstChild => {
|
||||||
*shareable = false;
|
*shareable = false;
|
||||||
|
@ -791,14 +782,12 @@ fn matches_generic_nth_child<'a,
|
||||||
|
|
||||||
if node.is_element() {
|
if node.is_element() {
|
||||||
if is_of_type {
|
if is_of_type {
|
||||||
element.with_element(|element: &E| {
|
let element = element.as_element();
|
||||||
node.with_element(|node: &E| {
|
let node = node.as_element();
|
||||||
if element.get_local_name() == node.get_local_name() &&
|
if element.get_local_name() == node.get_local_name() &&
|
||||||
element.get_namespace() == node.get_namespace() {
|
element.get_namespace() == node.get_namespace() {
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue