зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #9515 - Stylo uplifts Part 2 (from bholley:stylo_uplifts_2); r=SimonSapin
A bunch of random things that we might as well merge into the tree. Source-Repo: https://github.com/servo/servo Source-Revision: 629b1d33d5d6153da87d1ae176ea6c9b9298c650
This commit is contained in:
Родитель
797ece8f28
Коммит
7d75623720
|
@ -50,6 +50,7 @@ pub fn heap_size_of_local_context() -> usize {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep this implementation in sync with the one in ports/geckolib/traversal.rs.
|
||||||
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
|
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
|
||||||
-> Rc<LocalLayoutContext> {
|
-> Rc<LocalLayoutContext> {
|
||||||
LOCAL_CONTEXT_KEY.with(|r| {
|
LOCAL_CONTEXT_KEY.with(|r| {
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use context::{LocalStyleContext, SharedStyleContext, StyleContext};
|
use context::{SharedStyleContext, StyleContext};
|
||||||
use dom::{OpaqueNode, TNode, TRestyleDamage, UnsafeNode};
|
use dom::{OpaqueNode, TNode, TRestyleDamage, UnsafeNode};
|
||||||
use matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
|
use matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::mem;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use util::opts;
|
use util::opts;
|
||||||
use util::tid::tid;
|
use util::tid::tid;
|
||||||
|
|
||||||
|
@ -115,47 +113,6 @@ pub trait DomTraversalContext<'ln, N: TNode<'ln>> {
|
||||||
fn process_postorder(&self, node: N);
|
fn process_postorder(&self, node: N);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StandaloneStyleContext<'a> {
|
|
||||||
pub shared: &'a SharedStyleContext,
|
|
||||||
cached_local_style_context: Rc<LocalStyleContext>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> StandaloneStyleContext<'a> {
|
|
||||||
pub fn new(_: &'a SharedStyleContext) -> Self { panic!("Not implemented") }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
|
|
||||||
fn shared_context(&self) -> &'a SharedStyleContext {
|
|
||||||
&self.shared
|
|
||||||
}
|
|
||||||
|
|
||||||
fn local_context(&self) -> &LocalStyleContext {
|
|
||||||
&self.cached_local_style_context
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RecalcStyleOnly<'lc> {
|
|
||||||
context: StandaloneStyleContext<'lc>,
|
|
||||||
root: OpaqueNode,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'lc, 'ln, N: TNode<'ln>> DomTraversalContext<'ln, N> 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 SharedStyleContext = unsafe { mem::transmute(shared) };
|
|
||||||
RecalcStyleOnly {
|
|
||||||
context: StandaloneStyleContext::new(shared_lc),
|
|
||||||
root: root,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_preorder(&self, node: N) { recalc_style_at(&self.context, self.root, node); }
|
|
||||||
fn process_postorder(&self, _: N) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The recalc-style-for-node traversal, which styles each node and must run before
|
/// The recalc-style-for-node traversal, which styles each node and must run before
|
||||||
/// layout computation. This computes the styles applied to each node.
|
/// layout computation. This computes the styles applied to each node.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -28,19 +28,22 @@ pub type intptr_t = int64_t;
|
||||||
pub type uintptr_t = uint64_t;
|
pub type uintptr_t = uint64_t;
|
||||||
pub type intmax_t = ::libc::c_long;
|
pub type intmax_t = ::libc::c_long;
|
||||||
pub type uintmax_t = ::libc::c_ulong;
|
pub type uintmax_t = ::libc::c_ulong;
|
||||||
pub type Enum_NodeType = ::libc::c_uint;
|
#[derive(Clone, Copy)]
|
||||||
pub const ELEMENT_NODE: ::libc::c_uint = 1;
|
#[repr(u32)]
|
||||||
pub const ATTRIBUTE_NODE: ::libc::c_uint = 2;
|
pub enum Enum_NodeType {
|
||||||
pub const TEXT_NODE: ::libc::c_uint = 3;
|
ELEMENT_NODE = 1,
|
||||||
pub const CDATA_SECTION_NODE: ::libc::c_uint = 4;
|
ATTRIBUTE_NODE = 2,
|
||||||
pub const ENTITY_REFERENCE_NODE: ::libc::c_uint = 5;
|
TEXT_NODE = 3,
|
||||||
pub const ENTITY_NODE: ::libc::c_uint = 6;
|
CDATA_SECTION_NODE = 4,
|
||||||
pub const PROCESSING_INSTRUCTION_NODE: ::libc::c_uint = 7;
|
ENTITY_REFERENCE_NODE = 5,
|
||||||
pub const COMMENT_NODE: ::libc::c_uint = 8;
|
ENTITY_NODE = 6,
|
||||||
pub const DOCUMENT_NODE: ::libc::c_uint = 9;
|
PROCESSING_INSTRUCTION_NODE = 7,
|
||||||
pub const DOCUMENT_TYPE_NODE: ::libc::c_uint = 10;
|
COMMENT_NODE = 8,
|
||||||
pub const DOCUMENT_FRAGMENT_NODE: ::libc::c_uint = 11;
|
DOCUMENT_NODE = 9,
|
||||||
pub const NOTATION_NODE: ::libc::c_uint = 12;
|
DOCUMENT_TYPE_NODE = 10,
|
||||||
|
DOCUMENT_FRAGMENT_NODE = 11,
|
||||||
|
NOTATION_NODE = 12,
|
||||||
|
}
|
||||||
pub enum Struct_RawGeckoNode { }
|
pub enum Struct_RawGeckoNode { }
|
||||||
pub type RawGeckoNode = Struct_RawGeckoNode;
|
pub type RawGeckoNode = Struct_RawGeckoNode;
|
||||||
pub enum Struct_RawGeckoElement { }
|
pub enum Struct_RawGeckoElement { }
|
||||||
|
@ -49,10 +52,15 @@ pub enum Struct_RawGeckoDocument { }
|
||||||
pub type RawGeckoDocument = Struct_RawGeckoDocument;
|
pub type RawGeckoDocument = Struct_RawGeckoDocument;
|
||||||
pub enum Struct_ServoNodeData { }
|
pub enum Struct_ServoNodeData { }
|
||||||
pub type ServoNodeData = Struct_ServoNodeData;
|
pub type ServoNodeData = Struct_ServoNodeData;
|
||||||
|
pub enum Struct_ServoArcStyleSheet { }
|
||||||
|
pub type ServoArcStyleSheet = Struct_ServoArcStyleSheet;
|
||||||
|
pub enum Struct_ServoStyleSetData { }
|
||||||
|
pub type ServoStyleSetData = Struct_ServoStyleSetData;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_ElementState(element: *mut RawGeckoElement) -> uint8_t;
|
pub fn Gecko_ElementState(element: *mut RawGeckoElement) -> uint8_t;
|
||||||
pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement, ns: *const uint8_t,
|
pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement,
|
||||||
name: *const uint8_t, length: *mut uint32_t)
|
ns: *const uint8_t, name: *const uint8_t,
|
||||||
|
length: *mut uint32_t)
|
||||||
-> *const ::libc::c_char;
|
-> *const ::libc::c_char;
|
||||||
pub fn Gecko_ChildrenCount(node: *mut RawGeckoNode) -> uint32_t;
|
pub fn Gecko_ChildrenCount(node: *mut RawGeckoNode) -> uint32_t;
|
||||||
pub fn Gecko_GetDocumentElement(document: *mut RawGeckoDocument)
|
pub fn Gecko_GetDocumentElement(document: *mut RawGeckoDocument)
|
||||||
|
@ -61,21 +69,50 @@ extern "C" {
|
||||||
pub fn Gecko_GetLastChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
pub fn Gecko_GetLastChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||||
pub fn Gecko_GetPrevSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
pub fn Gecko_GetPrevSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||||
pub fn Gecko_GetNextSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
pub fn Gecko_GetNextSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||||
|
pub fn Gecko_GetParentElement(element: *mut RawGeckoElement)
|
||||||
|
-> *mut RawGeckoElement;
|
||||||
|
pub fn Gecko_GetFirstChildElement(element: *mut RawGeckoElement)
|
||||||
|
-> *mut RawGeckoElement;
|
||||||
|
pub fn Gecko_GetLastChildElement(element: *mut RawGeckoElement)
|
||||||
|
-> *mut RawGeckoElement;
|
||||||
|
pub fn Gecko_GetPrevSiblingElement(element: *mut RawGeckoElement)
|
||||||
|
-> *mut RawGeckoElement;
|
||||||
|
pub fn Gecko_GetNextSiblingElement(element: *mut RawGeckoElement)
|
||||||
|
-> *mut RawGeckoElement;
|
||||||
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
|
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
|
||||||
pub fn Gecko_GetParentNode(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
pub fn Gecko_GetParentNode(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
|
||||||
pub fn Gecko_LocalName(element: *mut RawGeckoElement, length: *mut uint32_t)
|
pub fn Gecko_LocalName(element: *mut RawGeckoElement,
|
||||||
-> *const uint16_t;
|
length: *mut uint32_t) -> *const uint16_t;
|
||||||
pub fn Gecko_IsHTMLElementInHTMLDocument(element: *mut RawGeckoElement)
|
pub fn Gecko_IsHTMLElementInHTMLDocument(element: *mut RawGeckoElement)
|
||||||
-> ::libc::c_int;
|
-> ::libc::c_int;
|
||||||
pub fn Gecko_IsLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
pub fn Gecko_IsLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
||||||
pub fn Gecko_IsTextNode(node: *mut RawGeckoNode) -> ::libc::c_int;
|
pub fn Gecko_IsTextNode(node: *mut RawGeckoNode) -> ::libc::c_int;
|
||||||
pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement)
|
||||||
pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement) -> ::libc::c_int;
|
-> ::libc::c_int;
|
||||||
pub fn Gecko_Namespace(element: *mut RawGeckoElement, length: *mut uint32_t)
|
pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement)
|
||||||
-> *const uint16_t;
|
-> ::libc::c_int;
|
||||||
|
pub fn Gecko_IsRootElement(element: *mut RawGeckoElement)
|
||||||
|
-> ::libc::c_int;
|
||||||
|
pub fn Gecko_Namespace(element: *mut RawGeckoElement,
|
||||||
|
length: *mut uint32_t) -> *const uint16_t;
|
||||||
pub fn Gecko_NodeIsElement(node: *mut RawGeckoNode) -> ::libc::c_int;
|
pub fn Gecko_NodeIsElement(node: *mut RawGeckoNode) -> ::libc::c_int;
|
||||||
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
|
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
|
||||||
data: *mut ServoNodeData) -> ();
|
data: *mut ServoNodeData);
|
||||||
pub fn Servo_RestyleDocument(aDoc: *mut RawGeckoDocument) -> ();
|
pub fn Servo_RestyleDocument(doc: *mut RawGeckoDocument,
|
||||||
pub fn Servo_DropNodeData(data: *mut ServoNodeData) -> ();
|
data: *mut ServoStyleSetData);
|
||||||
|
pub fn Servo_DropNodeData(data: *mut ServoNodeData);
|
||||||
|
pub fn Servo_StylesheetFromUTF8Bytes(bytes: *const uint8_t,
|
||||||
|
length: uint32_t)
|
||||||
|
-> *mut ServoArcStyleSheet;
|
||||||
|
pub fn Servo_AppendStyleSheet(sheet: *mut ServoArcStyleSheet,
|
||||||
|
data: *mut ServoStyleSetData);
|
||||||
|
pub fn Servo_PrependStyleSheet(sheet: *mut ServoArcStyleSheet,
|
||||||
|
data: *mut ServoStyleSetData);
|
||||||
|
pub fn Servo_RemoveStyleSheet(sheet: *mut ServoArcStyleSheet,
|
||||||
|
data: *mut ServoStyleSetData);
|
||||||
|
pub fn Servo_StyleSheetHasRules(sheet: *mut ServoArcStyleSheet)
|
||||||
|
-> ::libc::c_int;
|
||||||
|
pub fn Servo_DropStylesheet(sheet: *mut ServoArcStyleSheet);
|
||||||
|
pub fn Servo_InitStyleSetData() -> *mut ServoStyleSetData;
|
||||||
|
pub fn Servo_DropStyleSetData(data: *mut ServoStyleSetData);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/* 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 bindings::ServoStyleSetData;
|
||||||
|
use euclid::Size2D;
|
||||||
|
use euclid::size::TypedSize2D;
|
||||||
|
use num_cpus;
|
||||||
|
use std::cmp;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use style::animation::Animation;
|
||||||
|
use style::context::SharedStyleContext;
|
||||||
|
use style::dom::OpaqueNode;
|
||||||
|
use style::media_queries::{Device, MediaType};
|
||||||
|
use style::parallel::WorkQueueData;
|
||||||
|
use style::selector_matching::Stylist;
|
||||||
|
use style::stylesheets::Stylesheet;
|
||||||
|
use util::geometry::ViewportPx;
|
||||||
|
use util::thread_state;
|
||||||
|
use util::workqueue::WorkQueue;
|
||||||
|
|
||||||
|
pub struct PerDocumentStyleData {
|
||||||
|
|
||||||
|
/// Rule processor.
|
||||||
|
pub stylist: 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: WorkQueue<SharedStyleContext, WorkQueueData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PerDocumentStyleData {
|
||||||
|
pub fn new() -> PerDocumentStyleData {
|
||||||
|
// FIXME(bholley): Real window size.
|
||||||
|
let window_size: TypedSize2D<ViewportPx, f32> = Size2D::typed(800.0, 600.0);
|
||||||
|
let device = Device::new(MediaType::Screen, window_size);
|
||||||
|
|
||||||
|
let (new_anims_sender, new_anims_receiver) = channel();
|
||||||
|
let num_threads = cmp::max(num_cpus::get() * 3 / 4, 1);
|
||||||
|
|
||||||
|
PerDocumentStyleData {
|
||||||
|
stylist: Stylist::new(device),
|
||||||
|
stylesheets: Vec::new(),
|
||||||
|
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: WorkQueue::new("StyleWorker", thread_state::LAYOUT, num_threads),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn borrow_mut_from_raw<'a>(data: *mut ServoStyleSetData) -> &'a mut Self {
|
||||||
|
unsafe { &mut *(data as *mut PerDocumentStyleData) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PerDocumentStyleData {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.work_queue.shutdown();
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,27 +6,22 @@
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use bindings::RawGeckoDocument;
|
use bindings::RawGeckoDocument;
|
||||||
use bindings::ServoNodeData;
|
use bindings::{ServoArcStyleSheet, ServoNodeData, ServoStyleSetData, uint8_t, uint32_t};
|
||||||
|
use data::PerDocumentStyleData;
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use euclid::size::TypedSize2D;
|
use std::mem::{forget, transmute};
|
||||||
use num_cpus;
|
use std::slice;
|
||||||
use std::cmp;
|
use std::str::from_utf8_unchecked;
|
||||||
use std::collections::HashMap;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::mpsc::{channel, Sender};
|
|
||||||
use std::sync::{Arc, Mutex, RwLock};
|
|
||||||
use style::animation::Animation;
|
|
||||||
use style::context::{ReflowGoal, SharedStyleContext, StylistWrapper};
|
use style::context::{ReflowGoal, SharedStyleContext, StylistWrapper};
|
||||||
use style::dom::{TDocument, TNode};
|
use style::dom::{TDocument, TNode};
|
||||||
use style::error_reporting::StdoutErrorReporter;
|
use style::error_reporting::StdoutErrorReporter;
|
||||||
use style::media_queries::{Device, MediaType};
|
use style::parallel;
|
||||||
use style::parallel::{self, WorkQueueData};
|
use style::stylesheets::{Origin, Stylesheet};
|
||||||
use style::selector_matching::Stylist;
|
use traversal::RecalcStyleOnly;
|
||||||
use style::stylesheets::Stylesheet;
|
use url::Url;
|
||||||
use style::traversal::RecalcStyleOnly;
|
use util::arc_ptr_eq;
|
||||||
use util::geometry::ViewportPx;
|
|
||||||
use util::resource_files::set_resources_path;
|
use util::resource_files::set_resources_path;
|
||||||
use util::thread_state;
|
|
||||||
use util::workqueue::WorkQueue;
|
|
||||||
use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData};
|
use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -38,50 +33,36 @@ use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument) -> () {
|
pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument, raw_data: *mut ServoStyleSetData) -> () {
|
||||||
let document = unsafe { GeckoDocument::from_raw(doc) };
|
let document = unsafe { GeckoDocument::from_raw(doc) };
|
||||||
let node = match document.root_node() {
|
let node = match document.root_node() {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
let data = unsafe { &mut *(raw_data as *mut PerDocumentStyleData) };
|
||||||
|
|
||||||
// FIXME(bholley): Don't hardcode resources path. We may want to use Gecko's UA stylesheets
|
// FIXME(bholley): Don't hardcode resources path. We may want to use Gecko's UA stylesheets
|
||||||
// anyway.
|
// anyway.
|
||||||
set_resources_path(Some("/files/mozilla/stylo/servo/resources/".to_owned()));
|
set_resources_path(Some("/files/mozilla/stylo/servo/resources/".to_owned()));
|
||||||
|
|
||||||
// FIXME(bholley): Real window size.
|
let _needs_dirtying = data.stylist.update(&data.stylesheets, data.stylesheets_changed);
|
||||||
let window_size: TypedSize2D<ViewportPx, f32> = Size2D::typed(800.0, 600.0);
|
data.stylesheets_changed = false;
|
||||||
let device = Device::new(MediaType::Screen, window_size);
|
|
||||||
|
|
||||||
// FIXME(bholley): Real stylist and stylesheets.
|
|
||||||
let stylesheets: Vec<Arc<Stylesheet>> = Vec::new();
|
|
||||||
let mut stylist = Box::new(Stylist::new(device));
|
|
||||||
let _needs_dirtying = stylist.update(&stylesheets, false);
|
|
||||||
|
|
||||||
// FIXME(bholley): Hook this up to something.
|
|
||||||
let new_animations_sender: Sender<Animation> = channel().0;
|
|
||||||
|
|
||||||
let shared_style_context = SharedStyleContext {
|
let shared_style_context = SharedStyleContext {
|
||||||
viewport_size: Size2D::new(Au(0), Au(0)),
|
viewport_size: Size2D::new(Au(0), Au(0)),
|
||||||
screen_size_changed: false,
|
screen_size_changed: false,
|
||||||
generation: 0,
|
generation: 0,
|
||||||
goal: ReflowGoal::ForScriptQuery,
|
goal: ReflowGoal::ForScriptQuery,
|
||||||
stylist: StylistWrapper(&*stylist),
|
stylist: StylistWrapper(&data.stylist),
|
||||||
new_animations_sender: Mutex::new(new_animations_sender),
|
new_animations_sender: Mutex::new(data.new_animations_sender.clone()),
|
||||||
running_animations: Arc::new(RwLock::new(HashMap::new())),
|
running_animations: data.running_animations.clone(),
|
||||||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
expired_animations: data.expired_animations.clone(),
|
||||||
error_reporter: Box::new(StdoutErrorReporter),
|
error_reporter: Box::new(StdoutErrorReporter),
|
||||||
};
|
};
|
||||||
|
|
||||||
let num_threads = cmp::max(num_cpus::get() * 3 / 4, 1);
|
|
||||||
let mut parallel_traversal: WorkQueue<SharedStyleContext, WorkQueueData> =
|
|
||||||
WorkQueue::new("StyleWorker", thread_state::LAYOUT, num_threads);
|
|
||||||
|
|
||||||
if node.is_dirty() || node.has_dirty_descendants() {
|
if node.is_dirty() || node.has_dirty_descendants() {
|
||||||
parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context, &mut parallel_traversal);
|
parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context, &mut data.work_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
parallel_traversal.shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -90,3 +71,88 @@ pub extern "C" fn Servo_DropNodeData(data: *mut ServoNodeData) -> () {
|
||||||
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
|
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const uint8_t,
|
||||||
|
length: uint32_t) -> *mut ServoArcStyleSheet {
|
||||||
|
|
||||||
|
let input = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
|
||||||
|
|
||||||
|
// FIXME(heycam): Pass in the real base URL and sheet origin to use.
|
||||||
|
let url = Url::parse("about:none").unwrap();
|
||||||
|
let sheet = Arc::new(Stylesheet::from_str(input, url, Origin::Author, Box::new(StdoutErrorReporter)));
|
||||||
|
unsafe {
|
||||||
|
transmute(sheet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_arc_stylesheet<F, Output>(raw: *mut ServoArcStyleSheet, cb: F) -> Output
|
||||||
|
where F: FnOnce(&Arc<Stylesheet>) -> Output {
|
||||||
|
let owned = unsafe { consume_arc_stylesheet(raw) };
|
||||||
|
let result = cb(&owned);
|
||||||
|
forget(owned);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn consume_arc_stylesheet(raw: *mut ServoArcStyleSheet) -> Arc<Stylesheet> {
|
||||||
|
transmute(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: *mut ServoArcStyleSheet,
|
||||||
|
raw_data: *mut ServoStyleSetData) {
|
||||||
|
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||||
|
with_arc_stylesheet(raw_sheet, |sheet| {
|
||||||
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||||
|
data.stylesheets.push(sheet.clone());
|
||||||
|
data.stylesheets_changed = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_PrependStyleSheet(raw_sheet: *mut ServoArcStyleSheet,
|
||||||
|
raw_data: *mut ServoStyleSetData) {
|
||||||
|
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||||
|
with_arc_stylesheet(raw_sheet, |sheet| {
|
||||||
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||||
|
data.stylesheets.insert(0, sheet.clone());
|
||||||
|
data.stylesheets_changed = true;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_RemoveStyleSheet(raw_sheet: *mut ServoArcStyleSheet,
|
||||||
|
raw_data: *mut ServoStyleSetData) {
|
||||||
|
let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
|
||||||
|
with_arc_stylesheet(raw_sheet, |sheet| {
|
||||||
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
||||||
|
data.stylesheets_changed = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_StyleSheetHasRules(raw_sheet: *mut ServoArcStyleSheet) -> ::libc::c_int {
|
||||||
|
with_arc_stylesheet(raw_sheet, |sheet| if sheet.rules.is_empty() { 0 } else { 1 })
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_DropStylesheet(sheet: *mut ServoArcStyleSheet) -> () {
|
||||||
|
unsafe {
|
||||||
|
let _ = consume_arc_stylesheet(sheet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_InitStyleSetData() -> *mut ServoStyleSetData {
|
||||||
|
let data = Box::new(PerDocumentStyleData::new());
|
||||||
|
Box::into_raw(data) as *mut ServoStyleSetData
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Servo_DropStyleSetData(data: *mut ServoStyleSetData) -> () {
|
||||||
|
unsafe {
|
||||||
|
let _ = Box::<PerDocumentStyleData>::from_raw(data as *mut PerDocumentStyleData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ extern crate util;
|
||||||
|
|
||||||
#[allow(dead_code, non_camel_case_types)]
|
#[allow(dead_code, non_camel_case_types)]
|
||||||
mod bindings;
|
mod bindings;
|
||||||
|
mod data;
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod glue;
|
pub mod glue;
|
||||||
|
mod traversal;
|
||||||
mod wrapper;
|
mod wrapper;
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/* 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 std::cell::RefCell;
|
||||||
|
use std::mem;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use style::context::{LocalStyleContext, SharedStyleContext, StyleContext};
|
||||||
|
use style::dom::{OpaqueNode, TNode};
|
||||||
|
use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
|
||||||
|
use style::traversal::{DomTraversalContext, recalc_style_at};
|
||||||
|
|
||||||
|
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 {
|
||||||
|
applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
|
||||||
|
style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
|
||||||
|
});
|
||||||
|
*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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RecalcStyleOnly<'lc> {
|
||||||
|
context: StandaloneStyleContext<'lc>,
|
||||||
|
root: OpaqueNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lc, 'ln, N: TNode<'ln>> DomTraversalContext<'ln, N> 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 SharedStyleContext = unsafe { mem::transmute(shared) };
|
||||||
|
RecalcStyleOnly {
|
||||||
|
context: StandaloneStyleContext::new(shared_lc),
|
||||||
|
root: root,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_preorder(&self, node: N) { recalc_style_at(&self.context, self.root, node); }
|
||||||
|
fn process_postorder(&self, _: N) {}
|
||||||
|
}
|
||||||
|
|
|
@ -6,9 +6,13 @@
|
||||||
|
|
||||||
use bindings::{Gecko_ChildrenCount};
|
use bindings::{Gecko_ChildrenCount};
|
||||||
use bindings::{Gecko_ElementState, Gecko_GetAttrAsUTF8, Gecko_GetDocumentElement};
|
use bindings::{Gecko_ElementState, Gecko_GetAttrAsUTF8, Gecko_GetDocumentElement};
|
||||||
use bindings::{Gecko_GetFirstChild, Gecko_GetLastChild, Gecko_GetNodeData};
|
use bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement};
|
||||||
use bindings::{Gecko_GetParentNode, Gecko_GetPrevSibling, Gecko_GetNextSibling};
|
use bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement};
|
||||||
use bindings::{Gecko_IsHTMLElementInHTMLDocument, Gecko_IsLink, Gecko_IsTextNode};
|
use bindings::{Gecko_GetNextSibling, Gecko_GetNextSiblingElement};
|
||||||
|
use bindings::{Gecko_GetNodeData};
|
||||||
|
use bindings::{Gecko_GetParentElement, Gecko_GetParentNode};
|
||||||
|
use bindings::{Gecko_GetPrevSibling, Gecko_GetPrevSiblingElement};
|
||||||
|
use bindings::{Gecko_IsHTMLElementInHTMLDocument, Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNode};
|
||||||
use bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
|
use bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
|
||||||
#[allow(unused_imports)] // Used in commented-out code.
|
#[allow(unused_imports)] // Used in commented-out code.
|
||||||
use bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
use bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
|
||||||
|
@ -334,7 +338,7 @@ impl<'le> TElement<'le> for GeckoElement<'le> {
|
||||||
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
|
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
|
||||||
where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
|
where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
|
||||||
{
|
{
|
||||||
unimplemented!()
|
// FIXME(bholley) - Need to implement this.
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -356,27 +360,39 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
type Impl = ServoSelectorImpl;
|
type Impl = ServoSelectorImpl;
|
||||||
|
|
||||||
fn parent_element(&self) -> Option<Self> {
|
fn parent_element(&self) -> Option<Self> {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
Gecko_GetParentElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_child_element(&self) -> Option<Self> {
|
fn first_child_element(&self) -> Option<Self> {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
Gecko_GetFirstChildElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_child_element(&self) -> Option<Self> {
|
fn last_child_element(&self) -> Option<Self> {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
Gecko_GetLastChildElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prev_sibling_element(&self) -> Option<Self> {
|
fn prev_sibling_element(&self) -> Option<Self> {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
Gecko_GetPrevSiblingElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_sibling_element(&self) -> Option<Self> {
|
fn next_sibling_element(&self) -> Option<Self> {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
Gecko_GetNextSiblingElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_root(&self) -> bool {
|
fn is_root(&self) -> bool {
|
||||||
unimplemented!()
|
unsafe {
|
||||||
|
Gecko_IsRootElement(self.element) != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче