2016-01-19 11:49:10 +03:00
|
|
|
/* 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 app_units::Au;
|
2017-01-04 06:20:59 +03:00
|
|
|
use atomic_refcell::AtomicRefMut;
|
2016-11-07 08:26:08 +03:00
|
|
|
use cssparser::Parser;
|
2016-11-24 02:47:18 +03:00
|
|
|
use cssparser::ToCss as ParserToCss;
|
2016-05-05 04:37:26 +03:00
|
|
|
use env_logger;
|
2016-01-19 11:49:10 +03:00
|
|
|
use euclid::Size2D;
|
2016-10-04 19:58:56 +03:00
|
|
|
use parking_lot::RwLock;
|
2016-11-25 20:00:44 +03:00
|
|
|
use selectors::Element;
|
2016-11-18 00:34:47 +03:00
|
|
|
use servo_url::ServoUrl;
|
2016-12-18 05:22:10 +03:00
|
|
|
use std::borrow::Cow;
|
2016-11-04 07:42:06 +03:00
|
|
|
use std::fmt::Write;
|
2017-01-14 00:25:39 +03:00
|
|
|
use std::mem;
|
2016-11-25 20:00:44 +03:00
|
|
|
use std::ptr;
|
2016-02-04 20:55:09 +03:00
|
|
|
use std::sync::{Arc, Mutex};
|
2016-07-11 15:11:48 +03:00
|
|
|
use style::arc_ptr_eq;
|
2016-12-21 22:11:12 +03:00
|
|
|
use style::context::{QuirksMode, ReflowGoal, SharedStyleContext, StyleContext};
|
|
|
|
use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInfo};
|
2016-12-26 05:13:30 +03:00
|
|
|
use style::data::{ElementData, ElementStyles, RestyleData};
|
2016-12-13 06:13:03 +03:00
|
|
|
use style::dom::{ShowSubtreeData, TElement, TNode};
|
2016-01-19 11:49:10 +03:00
|
|
|
use style::error_reporting::StdoutErrorReporter;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko::data::{NUM_THREADS, PerDocumentStyleData, PerDocumentStyleDataImpl};
|
|
|
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
2016-11-22 19:44:03 +03:00
|
|
|
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko::traversal::RecalcStyleOnly;
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko::wrapper::DUMMY_BASE_URL;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko::wrapper::GeckoElement;
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
|
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
|
|
|
|
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
|
2017-02-04 04:36:04 +03:00
|
|
|
use style::gecko_bindings::bindings::{nsACString, nsCSSValueBorrowedMut, nsAString};
|
2017-01-29 08:24:04 +03:00
|
|
|
use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
|
2017-01-14 00:25:39 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoAnimationValueListBorrowedMut;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
|
2017-01-29 08:24:04 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoKeyframeListBorrowedMut;
|
2017-01-05 08:01:38 +03:00
|
|
|
use style::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
|
2017-01-14 00:25:39 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
|
2017-01-26 10:36:33 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::gecko_bindings::bindings::RawServoImportRuleBorrowed;
|
2016-10-18 08:51:14 +03:00
|
|
|
use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
|
2016-11-24 02:47:18 +03:00
|
|
|
use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::structs;
|
2016-12-18 05:22:10 +03:00
|
|
|
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
|
2016-12-05 14:52:16 +03:00
|
|
|
use style::gecko_bindings::structs::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::gecko_bindings::structs::Loader;
|
2017-01-18 16:39:57 +03:00
|
|
|
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
|
2017-01-27 11:36:30 +03:00
|
|
|
use style::gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::gecko_bindings::structs::ServoStyleSheet;
|
2017-02-09 05:39:45 +03:00
|
|
|
use style::gecko_bindings::structs::nsCSSValueSharedList;
|
2017-01-29 08:24:04 +03:00
|
|
|
use style::gecko_bindings::structs::nsTimingFunction;
|
2016-12-01 08:54:46 +03:00
|
|
|
use style::gecko_bindings::structs::nsresult;
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
|
|
|
|
use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
|
2016-10-14 06:31:20 +03:00
|
|
|
use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
|
2017-02-09 05:39:45 +03:00
|
|
|
use style::gecko_properties::style_structs;
|
2017-01-29 08:24:04 +03:00
|
|
|
use style::keyframes::KeyframesStepValue;
|
2016-02-04 20:55:09 +03:00
|
|
|
use style::parallel;
|
2016-10-09 16:53:28 +03:00
|
|
|
use style::parser::{ParserContext, ParserContextExtraData};
|
2016-10-27 04:14:04 +03:00
|
|
|
use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
|
2016-12-10 12:16:26 +03:00
|
|
|
use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock, PropertyId};
|
2016-11-06 01:11:24 +03:00
|
|
|
use style::properties::{apply_declarations, parse_one_declaration};
|
2017-01-29 08:24:04 +03:00
|
|
|
use style::properties::animated_properties::{AnimationValue, Interpolate, TransitionProperty};
|
2016-11-25 20:00:44 +03:00
|
|
|
use style::restyle_hints::RestyleHint;
|
2016-11-20 18:21:52 +03:00
|
|
|
use style::selector_parser::PseudoElementCascadeType;
|
2016-07-06 04:55:36 +03:00
|
|
|
use style::sequential;
|
2016-09-26 10:36:05 +03:00
|
|
|
use style::string_cache::Atom;
|
2016-12-31 06:12:55 +03:00
|
|
|
use style::stylesheets::{CssRule, CssRules, Origin, Stylesheet, StyleRule, ImportRule};
|
|
|
|
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
2017-01-17 00:56:51 +03:00
|
|
|
use style::supports::parse_condition_or_declaration;
|
2016-11-21 17:16:36 +03:00
|
|
|
use style::thread_state;
|
2016-07-20 21:38:31 +03:00
|
|
|
use style::timer::Timer;
|
2017-01-25 04:02:41 +03:00
|
|
|
use style::traversal::{resolve_style, DomTraversal, TraversalDriver};
|
2016-11-07 08:26:08 +03:00
|
|
|
use style_traits::ToCss;
|
2016-12-16 20:43:19 +03:00
|
|
|
use stylesheet_loader::StylesheetLoader;
|
2016-09-26 10:36:05 +03:00
|
|
|
|
2016-01-19 11:49:10 +03:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
* those signatures as well, giving us a second declaration of all the Servo_* functions in this
|
|
|
|
* crate. If there's a mismatch, LLVM will assert and abort, which is a rather awful thing to
|
|
|
|
* depend on but good enough for our purposes.
|
|
|
|
*/
|
|
|
|
|
2016-05-05 04:37:26 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Initialize() -> () {
|
|
|
|
// Enable standard Rust logging.
|
|
|
|
//
|
|
|
|
// See https://doc.rust-lang.org/log/env_logger/index.html for instructions.
|
|
|
|
env_logger::init().unwrap();
|
2016-08-04 04:20:21 +03:00
|
|
|
|
2016-11-21 17:16:36 +03:00
|
|
|
// Pretend that we're a Servo Layout thread, to make some assertions happy.
|
|
|
|
thread_state::initialize(thread_state::LAYOUT);
|
2016-08-04 04:20:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Shutdown() -> () {
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
2016-04-04 17:41:29 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
fn create_shared_context(per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext {
|
2016-07-02 00:12:54 +03:00
|
|
|
let local_context_data =
|
2016-12-16 22:38:27 +03:00
|
|
|
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
|
2016-01-19 11:49:10 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
SharedStyleContext {
|
2016-10-09 16:53:28 +03:00
|
|
|
// FIXME (bug 1303229): Use the actual viewport size here
|
2016-01-19 11:49:10 +03:00
|
|
|
viewport_size: Size2D::new(Au(0), Au(0)),
|
|
|
|
screen_size_changed: false,
|
|
|
|
goal: ReflowGoal::ForScriptQuery,
|
2016-07-02 00:12:54 +03:00
|
|
|
stylist: per_doc_data.stylist.clone(),
|
|
|
|
running_animations: per_doc_data.running_animations.clone(),
|
|
|
|
expired_animations: per_doc_data.expired_animations.clone(),
|
2016-01-19 11:49:10 +03:00
|
|
|
error_reporter: Box::new(StdoutErrorReporter),
|
2016-07-02 00:12:54 +03:00
|
|
|
local_context_creation_data: Mutex::new(local_context_data),
|
2016-07-20 21:38:31 +03:00
|
|
|
timer: Timer::new(),
|
2016-12-18 00:25:06 +03:00
|
|
|
// FIXME Find the real QuirksMode information for this document
|
|
|
|
quirks_mode: QuirksMode::NoQuirks,
|
2017-01-18 16:39:57 +03:00
|
|
|
default_computed_values: per_doc_data.default_computed_values().clone(),
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
2016-12-13 06:13:03 +03:00
|
|
|
unstyled_children_only: bool) {
|
2016-11-25 20:00:44 +03:00
|
|
|
// When new content is inserted in a display:none subtree, we will call into
|
|
|
|
// servo to try to style it. Detect that here and bail out.
|
|
|
|
if let Some(parent) = element.parent_element() {
|
2016-12-15 06:41:12 +03:00
|
|
|
if parent.borrow_data().map_or(true, |d| d.styles().is_display_none()) {
|
2016-11-25 20:00:44 +03:00
|
|
|
debug!("{:?} has unstyled parent - ignoring call to traverse_subtree", parent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-10 04:01:05 +03:00
|
|
|
let mut per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
|
2016-12-13 06:13:03 +03:00
|
|
|
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only);
|
2016-12-10 04:01:05 +03:00
|
|
|
if !token.should_traverse() {
|
2016-11-25 20:00:44 +03:00
|
|
|
error!("Unnecessary call to traverse_subtree");
|
2016-10-26 14:36:06 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-13 06:13:03 +03:00
|
|
|
debug!("Traversing subtree:");
|
|
|
|
debug!("{:?}", ShowSubtreeData(element.as_node()));
|
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
let shared_style_context = create_shared_context(&per_doc_data);
|
2017-01-25 04:02:41 +03:00
|
|
|
let traversal_driver = if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() {
|
|
|
|
TraversalDriver::Sequential
|
2016-07-28 01:56:26 +03:00
|
|
|
} else {
|
2017-01-25 04:02:41 +03:00
|
|
|
TraversalDriver::Parallel
|
|
|
|
};
|
|
|
|
|
|
|
|
let traversal = RecalcStyleOnly::new(shared_style_context, traversal_driver);
|
|
|
|
let known_depth = None;
|
|
|
|
if traversal_driver.is_parallel() {
|
2016-12-16 22:38:27 +03:00
|
|
|
parallel::traverse_dom(&traversal, element, known_depth, token,
|
|
|
|
per_doc_data.work_queue.as_mut().unwrap());
|
2017-01-25 04:02:41 +03:00
|
|
|
} else {
|
|
|
|
sequential::traverse_dom(&traversal, element, token);
|
2016-01-19 11:49:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-26 00:26:11 +03:00
|
|
|
#[no_mangle]
|
2016-11-25 20:00:44 +03:00
|
|
|
pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed,
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
2016-12-13 06:13:03 +03:00
|
|
|
behavior: structs::TraversalRootBehavior) -> () {
|
2016-11-25 20:00:44 +03:00
|
|
|
let element = GeckoElement(root);
|
|
|
|
debug!("Servo_TraverseSubtree: {:?}", element);
|
2016-12-13 06:13:03 +03:00
|
|
|
traverse_subtree(element, raw_data,
|
|
|
|
behavior == structs::TraversalRootBehavior::UnstyledChildrenOnly);
|
2016-05-26 00:26:11 +03:00
|
|
|
}
|
|
|
|
|
2017-01-26 10:36:33 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_Interpolate(from: RawServoAnimationValueBorrowed,
|
|
|
|
to: RawServoAnimationValueBorrowed,
|
|
|
|
progress: f64)
|
|
|
|
-> RawServoAnimationValueStrong
|
|
|
|
{
|
|
|
|
let from_value = AnimationValue::as_arc(&from);
|
|
|
|
let to_value = AnimationValue::as_arc(&to);
|
|
|
|
if let Ok(value) = from_value.interpolate(to_value, progress) {
|
|
|
|
Arc::new(value).into_strong()
|
|
|
|
} else {
|
|
|
|
RawServoAnimationValueStrong::null()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_Uncompute(value: RawServoAnimationValueBorrowedListBorrowed)
|
|
|
|
-> RawServoDeclarationBlockStrong
|
|
|
|
{
|
2017-01-27 11:36:30 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap() };
|
2017-01-26 10:36:33 +03:00
|
|
|
let uncomputed_values = value.into_iter()
|
|
|
|
.map(|v| {
|
|
|
|
let raw_anim = unsafe { v.as_ref().unwrap() };
|
|
|
|
let anim = AnimationValue::as_arc(&raw_anim);
|
|
|
|
(anim.uncompute(), Importance::Normal)
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
|
|
|
declarations: uncomputed_values,
|
|
|
|
important_count: 0,
|
|
|
|
})).into_strong()
|
|
|
|
}
|
|
|
|
|
2017-02-09 05:39:45 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_GetOpacity(value: RawServoAnimationValueBorrowed)
|
|
|
|
-> f32
|
|
|
|
{
|
|
|
|
let value = AnimationValue::as_arc(&value);
|
|
|
|
if let AnimationValue::Opacity(opacity) = **value {
|
|
|
|
opacity
|
|
|
|
} else {
|
|
|
|
panic!("The AnimationValue should be Opacity");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_GetTransform(value: RawServoAnimationValueBorrowed,
|
|
|
|
list: &mut structs::RefPtr<nsCSSValueSharedList>)
|
|
|
|
{
|
|
|
|
let value = AnimationValue::as_arc(&value);
|
|
|
|
if let AnimationValue::Transform(ref servo_list) = **value {
|
|
|
|
style_structs::Box::convert_transform(servo_list.0.clone().unwrap(), list);
|
|
|
|
} else {
|
|
|
|
panic!("The AnimationValue should be transform");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-14 00:25:39 +03:00
|
|
|
/// Takes a ServoAnimationValues and populates it with the animation values corresponding
|
|
|
|
/// to a given property declaration block
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValues_Populate(anim: RawGeckoAnimationValueListBorrowedMut,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
style: ServoComputedValuesBorrowed,
|
|
|
|
parent_style: ServoComputedValuesBorrowedOrNull,
|
|
|
|
pres_context: RawGeckoPresContextBorrowed)
|
|
|
|
{
|
|
|
|
use style::properties::declaration_block::Importance;
|
|
|
|
use style::values::computed::Context;
|
|
|
|
|
|
|
|
let parent_style = parent_style.as_ref().map(|r| &**ComputedValues::as_arc(&r));
|
|
|
|
// FIXME this might not be efficient since Populate
|
|
|
|
// is called multiple times. We should precalculate the Context
|
|
|
|
// and share it across Populate calls
|
|
|
|
let style = ComputedValues::as_arc(&style);
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
let guard = declarations.read();
|
|
|
|
|
|
|
|
let init = ComputedValues::default_values(pres_context);
|
|
|
|
|
|
|
|
let context = Context {
|
|
|
|
is_root_element: false,
|
|
|
|
// FIXME (bug 1303229): Use the actual viewport size here
|
|
|
|
viewport_size: Size2D::new(Au(0), Au(0)),
|
|
|
|
inherited_style: parent_style.unwrap_or(&init),
|
|
|
|
style: (**style).clone(),
|
|
|
|
font_metrics_provider: None,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut iter = guard.declarations
|
|
|
|
.iter()
|
|
|
|
.filter_map(|&(ref decl, imp)| {
|
|
|
|
if imp == Importance::Normal {
|
|
|
|
AnimationValue::from_declaration(decl, &context, &init)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let mut geckoiter = anim.iter_mut();
|
|
|
|
{
|
|
|
|
// we reborrow to scope the consumed mutable borrow
|
|
|
|
// we need to be able to ensure geckoiter is empty later on
|
|
|
|
// and thus can't directly use `geckoiter`
|
|
|
|
let local_geckoiter = &mut geckoiter;
|
|
|
|
for (gecko, servo) in local_geckoiter.zip(&mut iter) {
|
2017-02-09 05:39:45 +03:00
|
|
|
gecko.mValue.mServo.set_arc_leaky(Arc::new(servo));
|
2017-01-14 00:25:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we should have gone through both iterators
|
|
|
|
if iter.next().is_some() || geckoiter.next().is_some() {
|
|
|
|
error!("stylo: Mismatched sizes of Gecko and Servo \
|
|
|
|
array during animation value construction");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValue_AddRef(anim: RawServoAnimationValueBorrowed) -> () {
|
|
|
|
unsafe { AnimationValue::addref(anim) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AnimationValue_Release(anim: RawServoAnimationValueBorrowed) -> () {
|
|
|
|
unsafe { AnimationValue::release(anim) };
|
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2017-01-05 08:01:38 +03:00
|
|
|
pub extern "C" fn Servo_RestyleWithAddedDeclaration(raw_data: RawServoStyleSetBorrowed,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
2016-10-09 16:53:28 +03:00
|
|
|
previous_style: ServoComputedValuesBorrowed)
|
|
|
|
-> ServoComputedValuesStrong
|
|
|
|
{
|
2016-11-06 01:11:24 +03:00
|
|
|
let previous_style = ComputedValues::as_arc(&previous_style);
|
2016-10-18 08:51:14 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-11-06 01:11:24 +03:00
|
|
|
|
|
|
|
let guard = declarations.read();
|
|
|
|
|
|
|
|
let declarations = || {
|
|
|
|
guard.declarations.iter().rev().map(|&(ref decl, _importance)| decl)
|
2016-10-18 08:51:14 +03:00
|
|
|
};
|
|
|
|
|
2017-01-05 08:01:38 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
|
|
|
|
2016-10-18 08:51:14 +03:00
|
|
|
// FIXME (bug 1303229): Use the actual viewport size here
|
2016-11-06 01:11:24 +03:00
|
|
|
let computed = apply_declarations(Size2D::new(Au(0), Au(0)),
|
|
|
|
/* is_root_element = */ false,
|
|
|
|
declarations,
|
|
|
|
previous_style,
|
2017-01-18 16:39:57 +03:00
|
|
|
data.default_computed_values(),
|
2016-11-06 01:11:24 +03:00
|
|
|
None,
|
|
|
|
Box::new(StdoutErrorReporter),
|
2016-11-13 13:55:02 +03:00
|
|
|
None,
|
2016-11-06 01:11:24 +03:00
|
|
|
CascadeFlags::empty());
|
2016-10-18 08:51:14 +03:00
|
|
|
Arc::new(computed).into_strong()
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
2016-07-06 04:55:36 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
|
|
|
|
*NUM_THREADS as u32
|
|
|
|
}
|
|
|
|
|
2016-01-19 11:49:10 +03:00
|
|
|
#[no_mangle]
|
2016-11-25 20:00:44 +03:00
|
|
|
pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) -> () {
|
|
|
|
GeckoElement(element).clear_data();
|
2016-01-19 11:49:10 +03:00
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
|
2016-12-03 09:58:49 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_Element_ShouldTraverse(element: RawGeckoElementBorrowed) -> bool {
|
|
|
|
let element = GeckoElement(element);
|
2017-01-10 04:26:50 +03:00
|
|
|
debug_assert!(!element.has_dirty_descendants(),
|
|
|
|
"only call Servo_Element_ShouldTraverse if you know the element \
|
|
|
|
does not have dirty descendants");
|
|
|
|
let result = match element.borrow_data() {
|
|
|
|
// Note that we check for has_restyle here rather than has_current_styles,
|
|
|
|
// because we also want the traversal code to trigger if there's restyle
|
|
|
|
// damage. We really only need the Gecko post-traversal in that case, so
|
|
|
|
// the servo traversal will be a no-op, but it's cheap enough that we
|
|
|
|
// don't bother distinguishing the two cases.
|
|
|
|
Some(d) => !d.has_styles() || d.has_restyle(),
|
|
|
|
None => true,
|
|
|
|
};
|
|
|
|
result
|
2016-12-03 09:58:49 +03:00
|
|
|
}
|
|
|
|
|
2016-11-10 21:56:48 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyleSheetStrong {
|
2016-11-18 00:34:47 +03:00
|
|
|
let url = ServoUrl::parse("about:blank").unwrap();
|
2016-11-10 21:56:48 +03:00
|
|
|
let extra_data = ParserContextExtraData::default();
|
|
|
|
let origin = match mode {
|
|
|
|
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
|
|
|
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
|
|
|
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
|
|
|
};
|
2016-11-22 04:33:57 +03:00
|
|
|
let sheet = Arc::new(Stylesheet::from_str(
|
2016-12-31 06:12:55 +03:00
|
|
|
"", url, origin, Default::default(), None,
|
2016-12-16 20:43:19 +03:00
|
|
|
Box::new(StdoutErrorReporter), extra_data));
|
2016-11-10 21:56:48 +03:00
|
|
|
unsafe {
|
2017-01-14 00:25:39 +03:00
|
|
|
mem::transmute(sheet)
|
2016-11-10 21:56:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-12-31 06:12:55 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
|
|
|
|
stylesheet: *mut ServoStyleSheet,
|
|
|
|
data: *const nsACString,
|
2016-10-25 12:09:19 +03:00
|
|
|
mode: SheetParsingMode,
|
|
|
|
base_url: *const nsACString,
|
|
|
|
base: *mut ThreadSafeURIHolder,
|
|
|
|
referrer: *mut ThreadSafeURIHolder,
|
|
|
|
principal: *mut ThreadSafePrincipalHolder)
|
|
|
|
-> RawServoStyleSheetStrong {
|
|
|
|
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
2016-02-04 20:55:09 +03:00
|
|
|
|
2016-04-30 00:27:16 +03:00
|
|
|
let origin = match mode {
|
|
|
|
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
|
|
|
|
SheetParsingMode::eUserSheetFeatures => Origin::User,
|
|
|
|
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
|
|
|
|
};
|
|
|
|
|
2016-10-25 12:09:19 +03:00
|
|
|
let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() };
|
2016-11-18 00:34:47 +03:00
|
|
|
let url = ServoUrl::parse(base_str).unwrap();
|
2016-10-14 06:31:20 +03:00
|
|
|
let extra_data = unsafe { ParserContextExtraData {
|
2016-05-25 00:41:04 +03:00
|
|
|
base: Some(GeckoArcURI::new(base)),
|
|
|
|
referrer: Some(GeckoArcURI::new(referrer)),
|
|
|
|
principal: Some(GeckoArcPrincipal::new(principal)),
|
2016-10-14 06:31:20 +03:00
|
|
|
}};
|
2016-12-31 06:12:55 +03:00
|
|
|
let loader = if loader.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(StylesheetLoader::new(loader, stylesheet))
|
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
|
|
|
|
let loader: Option<&StyleStylesheetLoader> = match loader {
|
|
|
|
None => None,
|
|
|
|
Some(ref s) => Some(s),
|
|
|
|
};
|
|
|
|
|
2016-11-22 04:33:57 +03:00
|
|
|
let sheet = Arc::new(Stylesheet::from_str(
|
2016-12-31 06:12:55 +03:00
|
|
|
input, url, origin, Default::default(), loader,
|
2016-12-16 20:43:19 +03:00
|
|
|
Box::new(StdoutErrorReporter), extra_data));
|
2016-02-04 20:55:09 +03:00
|
|
|
unsafe {
|
2017-01-14 00:25:39 +03:00
|
|
|
mem::transmute(sheet)
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_ClearAndUpdate(stylesheet: RawServoStyleSheetBorrowed,
|
|
|
|
loader: *mut Loader,
|
|
|
|
gecko_stylesheet: *mut ServoStyleSheet,
|
|
|
|
data: *const nsACString,
|
|
|
|
base: *mut ThreadSafeURIHolder,
|
|
|
|
referrer: *mut ThreadSafeURIHolder,
|
|
|
|
principal: *mut ThreadSafePrincipalHolder)
|
|
|
|
{
|
|
|
|
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let extra_data = unsafe { ParserContextExtraData {
|
|
|
|
base: Some(GeckoArcURI::new(base)),
|
|
|
|
referrer: Some(GeckoArcURI::new(referrer)),
|
|
|
|
principal: Some(GeckoArcPrincipal::new(principal)),
|
|
|
|
}};
|
|
|
|
|
|
|
|
let loader = if loader.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(StylesheetLoader::new(loader, gecko_stylesheet))
|
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
|
|
|
|
let loader: Option<&StyleStylesheetLoader> = match loader {
|
|
|
|
None => None,
|
|
|
|
Some(ref s) => Some(s),
|
|
|
|
};
|
|
|
|
|
|
|
|
let sheet = Stylesheet::as_arc(&stylesheet);
|
|
|
|
sheet.rules.write().0.clear();
|
|
|
|
|
|
|
|
Stylesheet::update_from_str(&sheet, input, loader,
|
|
|
|
Box::new(StdoutErrorReporter), extra_data);
|
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
data.stylesheets.push(sheet.clone());
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
data.stylesheets.insert(0, sheet.clone());
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-04-29 08:37:40 +03:00
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowed,
|
2016-08-24 16:16:05 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_reference: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
let reference = HasArcFFI::as_arc(&raw_reference);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
let index = data.stylesheets.iter().position(|x| arc_ptr_eq(x, reference)).unwrap();
|
|
|
|
data.stylesheets.insert(index, sheet.clone());
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
2016-04-29 08:37:40 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-10-11 20:03:29 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowed,
|
2016-12-26 05:13:30 +03:00
|
|
|
raw_sheet: RawServoStyleSheetBorrowed,
|
|
|
|
flush: bool) {
|
2016-10-11 20:03:29 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-09-03 06:42:21 +03:00
|
|
|
let sheet = HasArcFFI::as_arc(&raw_sheet);
|
|
|
|
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
|
|
|
|
data.stylesheets_changed = true;
|
2016-12-26 05:13:30 +03:00
|
|
|
if flush {
|
|
|
|
data.flush_stylesheets();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_FlushStyleSheets(raw_data: RawServoStyleSetBorrowed) {
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
data.flush_stylesheets();
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-12-19 08:49:28 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_NoteStyleSheetsChanged(raw_data: RawServoStyleSetBorrowed) {
|
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
data.stylesheets_changed = true;
|
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_HasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
|
2016-11-29 14:26:46 +03:00
|
|
|
!Stylesheet::as_arc(&raw_sheet).rules.read().0.is_empty()
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed) -> ServoCssRulesStrong {
|
2016-11-29 14:26:46 +03:00
|
|
|
Stylesheet::as_arc(&sheet).rules.clone().into_strong()
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_AddRef(sheet: RawServoStyleSheetBorrowed) -> () {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { Stylesheet::addref(sheet) };
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
2016-02-04 20:55:09 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
2016-08-24 16:16:05 +03:00
|
|
|
pub extern "C" fn Servo_StyleSheet_Release(sheet: RawServoStyleSheetBorrowed) -> () {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { Stylesheet::release(sheet) };
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
|
|
|
|
result: nsTArrayBorrowed_uintptr_t) -> () {
|
2016-11-29 14:26:46 +03:00
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules).read();
|
|
|
|
let iter = rules.0.iter().map(|rule| rule.rule_type() as usize);
|
2016-11-24 02:47:18 +03:00
|
|
|
let (size, upper) = iter.size_hint();
|
|
|
|
debug_assert_eq!(size, upper.unwrap());
|
|
|
|
unsafe { result.set_len(size as u32) };
|
|
|
|
result.iter_mut().zip(iter).fold((), |_, (r, v)| *r = v);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_GetStyleRuleAt(rules: ServoCssRulesBorrowed, index: u32)
|
|
|
|
-> RawServoStyleRuleStrong {
|
2016-11-29 14:26:46 +03:00
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules).read();
|
|
|
|
match rules.0[index as usize] {
|
2016-11-24 02:47:18 +03:00
|
|
|
CssRule::Style(ref rule) => rule.clone().into_strong(),
|
|
|
|
_ => {
|
|
|
|
unreachable!("GetStyleRuleAt should only be called on a style rule");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-01 08:54:46 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_InsertRule(rules: ServoCssRulesBorrowed, sheet: RawServoStyleSheetBorrowed,
|
|
|
|
rule: *const nsACString, index: u32, nested: bool,
|
|
|
|
rule_type: *mut u16) -> nsresult {
|
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules);
|
|
|
|
let sheet = Stylesheet::as_arc(&sheet);
|
|
|
|
let rule = unsafe { rule.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
match rules.write().insert_rule(rule, sheet, index as usize, nested) {
|
|
|
|
Ok(new_rule) => {
|
|
|
|
*unsafe { rule_type.as_mut().unwrap() } = new_rule.rule_type() as u16;
|
|
|
|
nsresult::NS_OK
|
|
|
|
}
|
|
|
|
Err(err) => err.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_DeleteRule(rules: ServoCssRulesBorrowed, index: u32) -> nsresult {
|
|
|
|
let rules = RwLock::<CssRules>::as_arc(&rules);
|
|
|
|
match rules.write().remove_rule(index as usize) {
|
|
|
|
Ok(_) => nsresult::NS_OK,
|
|
|
|
Err(err) => err.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-24 02:47:18 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_AddRef(rules: ServoCssRulesBorrowed) -> () {
|
2016-11-29 14:26:46 +03:00
|
|
|
unsafe { RwLock::<CssRules>::addref(rules) };
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CssRules_Release(rules: ServoCssRulesBorrowed) -> () {
|
2016-11-29 14:26:46 +03:00
|
|
|
unsafe { RwLock::<CssRules>::release(rules) };
|
2016-11-24 02:47:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_AddRef(rule: RawServoStyleRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<StyleRule>::addref(rule) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_Release(rule: RawServoStyleRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<StyleRule>::release(rule) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_Debug(rule: RawServoStyleRuleBorrowed, result: *mut nsACString) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
let result = unsafe { result.as_mut().unwrap() };
|
|
|
|
write!(result, "{:?}", *rule.read()).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetStyle(rule: RawServoStyleRuleBorrowed) -> RawServoDeclarationBlockStrong {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
rule.read().block.clone().into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_SetStyle(rule: RawServoStyleRuleBorrowed,
|
|
|
|
declarations: RawServoDeclarationBlockBorrowed) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
rule.write().block = declarations.clone();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetCssText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
rule.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleRule_GetSelectorText(rule: RawServoStyleRuleBorrowed, result: *mut nsAString) -> () {
|
|
|
|
let rule = RwLock::<StyleRule>::as_arc(&rule);
|
|
|
|
rule.read().selectors.to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_AddRef(rule: RawServoImportRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<ImportRule>::addref(rule) };
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_Release(rule: RawServoImportRuleBorrowed) -> () {
|
|
|
|
unsafe { RwLock::<ImportRule>::release(rule) };
|
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2016-09-03 06:42:21 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowedOrNull,
|
2016-04-30 00:27:16 +03:00
|
|
|
pseudo_tag: *mut nsIAtom,
|
2016-10-11 20:03:29 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
2016-08-17 15:35:43 +03:00
|
|
|
-> ServoComputedValuesStrong {
|
2016-12-26 05:13:30 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2016-08-16 20:50:29 +03:00
|
|
|
let atom = Atom::from(pseudo_tag);
|
|
|
|
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
|
2016-04-30 00:27:16 +03:00
|
|
|
|
|
|
|
|
2016-10-05 08:59:56 +03:00
|
|
|
let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null);
|
2017-01-09 13:46:09 +03:00
|
|
|
data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent,
|
2017-01-18 16:39:57 +03:00
|
|
|
data.default_computed_values(), false)
|
2017-01-09 13:46:09 +03:00
|
|
|
.values
|
|
|
|
.into_strong()
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
2016-05-04 13:42:23 +03:00
|
|
|
#[no_mangle]
|
2016-12-26 05:13:30 +03:00
|
|
|
pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_tag: *mut nsIAtom, is_probe: bool,
|
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
|
|
|
-> ServoComputedValuesStrong
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let data = unsafe { element.ensure_data() }.borrow_mut();
|
2017-01-05 08:01:38 +03:00
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
// FIXME(bholley): Assert against this.
|
|
|
|
if data.get_styles().is_none() {
|
|
|
|
error!("Calling Servo_ResolvePseudoStyle on unstyled element");
|
|
|
|
return if is_probe {
|
2016-09-03 06:42:21 +03:00
|
|
|
Strong::null()
|
2016-05-04 13:42:23 +03:00
|
|
|
} else {
|
2017-01-18 16:39:57 +03:00
|
|
|
doc_data.borrow().default_computed_values().clone().into_strong()
|
2016-12-26 05:13:30 +03:00
|
|
|
};
|
|
|
|
}
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
match get_pseudo_style(element, pseudo_tag, data.styles(), doc_data) {
|
|
|
|
Some(values) => values.into_strong(),
|
|
|
|
None if !is_probe => data.styles().primary.values.clone().into_strong(),
|
|
|
|
None => Strong::null(),
|
|
|
|
}
|
|
|
|
}
|
2016-05-04 13:42:23 +03:00
|
|
|
|
2016-12-26 05:13:30 +03:00
|
|
|
fn get_pseudo_style(element: GeckoElement, pseudo_tag: *mut nsIAtom,
|
|
|
|
styles: &ElementStyles, doc_data: &PerDocumentStyleData)
|
|
|
|
-> Option<Arc<ComputedValues>>
|
|
|
|
{
|
|
|
|
let pseudo = PseudoElement::from_atom_unchecked(Atom::from(pseudo_tag), false);
|
2016-11-22 19:44:03 +03:00
|
|
|
match SelectorImpl::pseudo_element_cascade_type(&pseudo) {
|
2016-12-26 05:13:30 +03:00
|
|
|
PseudoElementCascadeType::Eager => styles.pseudos.get(&pseudo).map(|s| s.values.clone()),
|
|
|
|
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
|
2016-05-04 13:42:23 +03:00
|
|
|
PseudoElementCascadeType::Lazy => {
|
2016-12-26 05:13:30 +03:00
|
|
|
let d = doc_data.borrow_mut();
|
|
|
|
let base = &styles.primary.values;
|
2017-01-18 16:39:57 +03:00
|
|
|
d.stylist.lazily_compute_pseudo_element_style(&element, &pseudo, base, &d.default_computed_values())
|
2016-12-26 05:13:30 +03:00
|
|
|
.map(|s| s.values.clone())
|
|
|
|
},
|
2016-05-04 13:42:23 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-06 14:30:47 +03:00
|
|
|
#[no_mangle]
|
2017-01-05 08:01:38 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_Inherit(
|
|
|
|
raw_data: RawServoStyleSetBorrowed,
|
|
|
|
parent_style: ServoComputedValuesBorrowedOrNull)
|
2016-08-17 15:35:43 +03:00
|
|
|
-> ServoComputedValuesStrong {
|
2017-01-05 08:01:38 +03:00
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2016-10-05 08:59:56 +03:00
|
|
|
let maybe_arc = ComputedValues::arc_from_borrowed(&parent_style);
|
|
|
|
let style = if let Some(reference) = maybe_arc.as_ref() {
|
2017-01-18 16:39:57 +03:00
|
|
|
ComputedValues::inherit_from(reference, &data.default_computed_values())
|
2016-08-04 04:20:21 +03:00
|
|
|
} else {
|
2017-01-18 16:39:57 +03:00
|
|
|
data.default_computed_values().clone()
|
2016-08-04 04:20:21 +03:00
|
|
|
};
|
2016-09-03 06:42:21 +03:00
|
|
|
style.into_strong()
|
2016-05-06 14:30:47 +03:00
|
|
|
}
|
|
|
|
|
2016-03-25 00:57:33 +03:00
|
|
|
#[no_mangle]
|
2017-01-18 16:39:57 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_AddRef(ptr: ServoComputedValuesBorrowed) {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { ComputedValues::addref(ptr) };
|
2016-03-25 00:57:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2017-01-18 16:39:57 +03:00
|
|
|
pub extern "C" fn Servo_ComputedValues_Release(ptr: ServoComputedValuesBorrowed) {
|
2016-08-17 15:35:43 +03:00
|
|
|
unsafe { ComputedValues::release(ptr) };
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2017-01-18 16:39:57 +03:00
|
|
|
/// See the comment in `Device` to see why it's ok to pass an owned reference to
|
|
|
|
/// the pres context (hint: the context outlives the StyleSet, that holds the
|
|
|
|
/// device alive).
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2017-01-18 16:39:57 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_Init(pres_context: RawGeckoPresContextOwned)
|
2017-01-05 08:01:38 +03:00
|
|
|
-> RawServoStyleSetOwned {
|
|
|
|
let data = Box::new(PerDocumentStyleData::new(pres_context));
|
2016-09-03 06:42:21 +03:00
|
|
|
data.into_ffi()
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
|
|
|
|
2017-01-05 08:01:38 +03:00
|
|
|
#[no_mangle]
|
2017-01-18 16:39:57 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_RebuildData(raw_data: RawServoStyleSetBorrowed) {
|
2017-01-05 08:01:38 +03:00
|
|
|
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
2017-01-28 23:56:50 +03:00
|
|
|
data.reset_device();
|
2017-01-05 08:01:38 +03:00
|
|
|
}
|
|
|
|
|
2016-02-04 20:55:09 +03:00
|
|
|
#[no_mangle]
|
2016-09-03 06:42:21 +03:00
|
|
|
pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) -> () {
|
|
|
|
let _ = data.into_box::<PerDocumentStyleData>();
|
2016-02-04 20:55:09 +03:00
|
|
|
}
|
2016-06-24 05:46:25 +03:00
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2016-10-25 12:09:19 +03:00
|
|
|
pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const nsACString,
|
|
|
|
base_url: *const nsACString, base: *mut ThreadSafeURIHolder,
|
2016-10-09 16:53:28 +03:00
|
|
|
referrer: *mut ThreadSafeURIHolder,
|
|
|
|
principal: *mut ThreadSafePrincipalHolder)
|
2016-10-18 08:51:14 +03:00
|
|
|
-> RawServoDeclarationBlockStrong {
|
2016-10-25 12:09:19 +03:00
|
|
|
let name = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
2016-12-10 12:16:26 +03:00
|
|
|
let id = if let Ok(id) = PropertyId::parse(name.into()) {
|
|
|
|
id
|
|
|
|
} else {
|
|
|
|
return RawServoDeclarationBlockStrong::null()
|
|
|
|
};
|
2016-10-25 12:09:19 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() };
|
2016-11-18 00:34:47 +03:00
|
|
|
let base_url = ServoUrl::parse(base_str).unwrap();
|
2016-10-14 06:31:20 +03:00
|
|
|
let extra_data = unsafe { ParserContextExtraData {
|
2016-10-09 16:53:28 +03:00
|
|
|
base: Some(GeckoArcURI::new(base)),
|
|
|
|
referrer: Some(GeckoArcURI::new(referrer)),
|
|
|
|
principal: Some(GeckoArcPrincipal::new(principal)),
|
2016-10-14 06:31:20 +03:00
|
|
|
}};
|
2016-10-09 16:53:28 +03:00
|
|
|
|
|
|
|
let context = ParserContext::new_with_extra_data(Origin::Author, &base_url,
|
|
|
|
Box::new(StdoutErrorReporter),
|
|
|
|
extra_data);
|
|
|
|
|
|
|
|
let mut results = vec![];
|
2016-12-10 12:16:26 +03:00
|
|
|
match PropertyDeclaration::parse(id, &context, &mut Parser::new(value),
|
2016-10-09 16:53:28 +03:00
|
|
|
&mut results, false) {
|
|
|
|
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {},
|
2016-10-18 08:51:14 +03:00
|
|
|
_ => return RawServoDeclarationBlockStrong::null(),
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
2016-10-18 08:51:14 +03:00
|
|
|
Arc::new(RwLock::new(PropertyDeclarationBlock {
|
|
|
|
declarations: results,
|
|
|
|
important_count: 0,
|
|
|
|
})).into_strong()
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
2016-10-18 08:51:14 +03:00
|
|
|
|
2016-06-24 05:46:25 +03:00
|
|
|
#[no_mangle]
|
2016-10-25 12:09:19 +03:00
|
|
|
pub extern "C" fn Servo_ParseStyleAttribute(data: *const nsACString) -> RawServoDeclarationBlockStrong {
|
|
|
|
let value = unsafe { data.as_ref().unwrap().as_str_unchecked() };
|
2016-10-18 08:51:14 +03:00
|
|
|
Arc::new(RwLock::new(GeckoElement::parse_style_attribute(value))).into_strong()
|
2016-06-24 05:46:25 +03:00
|
|
|
}
|
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_CreateEmpty() -> RawServoDeclarationBlockStrong {
|
|
|
|
Arc::new(RwLock::new(PropertyDeclarationBlock { declarations: vec![], important_count: 0 })).into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Clone(declarations: RawServoDeclarationBlockBorrowed)
|
|
|
|
-> RawServoDeclarationBlockStrong {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
Arc::new(RwLock::new(declarations.read().clone())).into_strong()
|
|
|
|
}
|
|
|
|
|
2016-06-24 05:46:25 +03:00
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: RawServoDeclarationBlockBorrowed) {
|
|
|
|
unsafe { RwLock::<PropertyDeclarationBlock>::addref(declarations) };
|
2016-06-24 05:46:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Release(declarations: RawServoDeclarationBlockBorrowed) {
|
|
|
|
unsafe { RwLock::<PropertyDeclarationBlock>::release(declarations) };
|
2016-08-23 05:12:23 +03:00
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
2016-10-18 08:51:14 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
|
|
|
|
b: RawServoDeclarationBlockBorrowed)
|
2016-10-09 16:53:28 +03:00
|
|
|
-> bool {
|
2016-10-18 08:51:14 +03:00
|
|
|
*RwLock::<PropertyDeclarationBlock>::as_arc(&a).read() == *RwLock::<PropertyDeclarationBlock>::as_arc(&b).read()
|
2016-06-24 05:46:25 +03:00
|
|
|
}
|
2016-07-19 07:25:31 +03:00
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetCssText(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
result: *mut nsAString) {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
declarations.read().to_css(unsafe { result.as_mut().unwrap() }).unwrap();
|
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
macro_rules! get_property_id_from_nscsspropertyid {
|
|
|
|
($property_id: ident, $ret: expr) => {{
|
|
|
|
match PropertyId::from_nscsspropertyid($property_id) {
|
|
|
|
Ok(property_id) => property_id,
|
|
|
|
Err(()) => { return $ret; }
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
2016-10-09 16:53:28 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SerializeOneValue(
|
2016-10-18 08:51:14 +03:00
|
|
|
declarations: RawServoDeclarationBlockBorrowed,
|
2016-12-18 05:22:10 +03:00
|
|
|
property_id: nsCSSPropertyID, buffer: *mut nsAString)
|
2016-10-09 16:53:28 +03:00
|
|
|
{
|
2016-12-18 05:22:10 +03:00
|
|
|
let property_id = get_property_id_from_nscsspropertyid!(property_id, ());
|
2016-10-18 08:51:14 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-11-25 13:39:52 +03:00
|
|
|
let mut string = String::new();
|
2016-12-18 05:22:10 +03:00
|
|
|
let rv = declarations.read().single_value_to_css(&property_id, &mut string);
|
2016-11-25 13:39:52 +03:00
|
|
|
debug_assert!(rv.is_ok());
|
2016-10-18 08:51:14 +03:00
|
|
|
|
2016-12-01 07:12:28 +03:00
|
|
|
write!(unsafe { &mut *buffer }, "{}", string).expect("Failed to copy string");
|
2016-10-09 16:53:28 +03:00
|
|
|
}
|
|
|
|
|
2016-11-04 07:42:06 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_Count(declarations: RawServoDeclarationBlockBorrowed) -> u32 {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
declarations.read().declarations.len() as u32
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetNthProperty(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
index: u32, result: *mut nsAString) -> bool {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
if let Some(&(ref decl, _)) = declarations.read().declarations.get(index as usize) {
|
|
|
|
let result = unsafe { result.as_mut().unwrap() };
|
2016-12-10 12:16:26 +03:00
|
|
|
decl.id().to_css(result).unwrap();
|
2016-11-04 07:42:06 +03:00
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
macro_rules! get_property_id_from_property {
|
|
|
|
($property: ident, $ret: expr) => {{
|
|
|
|
let property = unsafe { $property.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
match PropertyId::parse(Cow::Borrowed(property)) {
|
|
|
|
Ok(property_id) => property_id,
|
|
|
|
Err(()) => { return $ret; }
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_property_value(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property_id: PropertyId, value: *mut nsAString) {
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
declarations.read().property_value_to_css(&property_id, unsafe { value.as_mut().unwrap() }).unwrap();
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetPropertyValue(declarations: RawServoDeclarationBlockBorrowed,
|
2016-12-18 05:22:10 +03:00
|
|
|
property: *const nsACString, value: *mut nsAString) {
|
|
|
|
get_property_value(declarations, get_property_id_from_property!(property, ()), value)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetPropertyValueById(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID, value: *mut nsAString) {
|
|
|
|
get_property_value(declarations, get_property_id_from_nscsspropertyid!(property, ()), value)
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_GetPropertyIsImportant(declarations: RawServoDeclarationBlockBorrowed,
|
2016-12-18 05:22:10 +03:00
|
|
|
property: *const nsACString) -> bool {
|
|
|
|
let property_id = get_property_id_from_property!(property, false);
|
2016-11-04 07:42:06 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-12-18 05:22:10 +03:00
|
|
|
declarations.read().property_priority(&property_id).important()
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2016-12-18 05:22:10 +03:00
|
|
|
fn set_property(declarations: RawServoDeclarationBlockBorrowed, property_id: PropertyId,
|
|
|
|
value: *mut nsACString, is_important: bool) -> bool {
|
2016-11-04 07:42:06 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
// FIXME Needs real URL and ParserContextExtraData.
|
|
|
|
let base_url = &*DUMMY_BASE_URL;
|
|
|
|
let extra_data = ParserContextExtraData::default();
|
2016-12-18 05:22:10 +03:00
|
|
|
if let Ok(decls) = parse_one_declaration(property_id, value, &base_url,
|
2016-11-04 07:42:06 +03:00
|
|
|
Box::new(StdoutErrorReporter), extra_data) {
|
|
|
|
let mut declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations).write();
|
|
|
|
let importance = if is_important { Importance::Important } else { Importance::Normal };
|
|
|
|
for decl in decls.into_iter() {
|
2017-01-19 04:41:05 +03:00
|
|
|
declarations.set_parsed_declaration(decl.0, importance);
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
2016-12-18 05:22:10 +03:00
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetProperty(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString, value: *mut nsACString,
|
|
|
|
is_important: bool) -> bool {
|
|
|
|
set_property(declarations, get_property_id_from_property!(property, false), value, is_important)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_SetPropertyById(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID, value: *mut nsACString,
|
|
|
|
is_important: bool) -> bool {
|
|
|
|
set_property(declarations, get_property_id_from_nscsspropertyid!(property, false), value, is_important)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_property(declarations: RawServoDeclarationBlockBorrowed, property_id: PropertyId) {
|
2016-11-04 07:42:06 +03:00
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
2016-12-18 05:22:10 +03:00
|
|
|
declarations.write().remove_property(&property_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_RemoveProperty(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: *const nsACString) {
|
|
|
|
remove_property(declarations, get_property_id_from_property!(property, ()))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID) {
|
|
|
|
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ()))
|
2016-11-04 07:42:06 +03:00
|
|
|
}
|
|
|
|
|
2017-02-04 04:36:04 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_DeclarationBlock_AddPresValue(declarations: RawServoDeclarationBlockBorrowed,
|
|
|
|
property: nsCSSPropertyID,
|
|
|
|
css_value: nsCSSValueBorrowedMut) {
|
|
|
|
use style::gecko::values::convert_nscolor_to_rgba;
|
|
|
|
use style::properties::{DeclaredValue, LonghandId, PropertyDeclaration, PropertyId, longhands};
|
|
|
|
use style::values::specified;
|
|
|
|
|
|
|
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
|
|
|
let prop = PropertyId::from_nscsspropertyid(property);
|
|
|
|
|
|
|
|
let long = match prop {
|
|
|
|
Ok(PropertyId::Longhand(long)) => long,
|
|
|
|
_ => {
|
|
|
|
error!("stylo: unknown presentation property with id {:?}", property);
|
|
|
|
return
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let decl = match long {
|
|
|
|
LonghandId::FontSize => {
|
|
|
|
if let Some(int) = css_value.integer() {
|
|
|
|
PropertyDeclaration::FontSize(DeclaredValue::Value(
|
|
|
|
longhands::font_size::SpecifiedValue(
|
|
|
|
specified::LengthOrPercentage::Length(
|
|
|
|
specified::NoCalcLength::from_font_size_int(int as u8)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
))
|
|
|
|
} else {
|
|
|
|
error!("stylo: got unexpected non-integer value for font-size presentation attribute");
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LonghandId::Color => {
|
|
|
|
if let Some(color) = css_value.color_value() {
|
2017-02-09 13:21:36 +03:00
|
|
|
PropertyDeclaration::Color(DeclaredValue::Value(Box::new(
|
2017-02-04 04:36:04 +03:00
|
|
|
specified::CSSRGBA {
|
|
|
|
parsed: convert_nscolor_to_rgba(color),
|
|
|
|
authored: None
|
|
|
|
}
|
2017-02-09 13:21:36 +03:00
|
|
|
)))
|
2017-02-04 04:36:04 +03:00
|
|
|
} else {
|
|
|
|
error!("stylo: got unexpected non-integer value for color presentation attribute");
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
error!("stylo: cannot handle longhand {:?} from presentation attribute", long);
|
|
|
|
return
|
|
|
|
}
|
|
|
|
};
|
|
|
|
declarations.write().declarations.push((decl, Importance::Normal));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-07-19 07:25:31 +03:00
|
|
|
#[no_mangle]
|
2017-01-17 00:56:51 +03:00
|
|
|
pub extern "C" fn Servo_CSSSupports2(property: *const nsACString, value: *const nsACString) -> bool {
|
2016-10-25 12:09:19 +03:00
|
|
|
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
|
2016-12-10 12:16:26 +03:00
|
|
|
let id = if let Ok(id) = PropertyId::parse(property.into()) {
|
|
|
|
id
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
};
|
2016-10-25 12:09:19 +03:00
|
|
|
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
|
2016-07-19 07:25:31 +03:00
|
|
|
|
|
|
|
let base_url = &*DUMMY_BASE_URL;
|
|
|
|
let extra_data = ParserContextExtraData::default();
|
|
|
|
|
2016-12-10 12:16:26 +03:00
|
|
|
match parse_one_declaration(id, &value, &base_url, Box::new(StdoutErrorReporter), extra_data) {
|
2016-07-19 07:25:31 +03:00
|
|
|
Ok(decls) => !decls.is_empty(),
|
|
|
|
Err(()) => false,
|
|
|
|
}
|
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2017-01-17 00:56:51 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_CSSSupports(cond: *const nsACString) -> bool {
|
|
|
|
let condition = unsafe { cond.as_ref().unwrap().as_str_unchecked() };
|
|
|
|
let mut input = Parser::new(&condition);
|
|
|
|
let cond = parse_condition_or_declaration(&mut input);
|
|
|
|
if let Ok(cond) = cond {
|
|
|
|
let url = ServoUrl::parse("about:blank").unwrap();
|
|
|
|
let context = ParserContext::new_for_cssom(&url);
|
|
|
|
cond.eval(&context)
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
/// Only safe to call on the main thread, with exclusive access to the element and
|
|
|
|
/// its ancestors.
|
|
|
|
unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: GeckoElement)
|
|
|
|
-> Option<&'a mut RestyleData>
|
|
|
|
{
|
2017-01-10 04:26:50 +03:00
|
|
|
// Don't generate a useless RestyleData if the element hasn't been styled.
|
|
|
|
if !data.has_styles() {
|
|
|
|
return None;
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
2017-01-10 04:26:50 +03:00
|
|
|
|
|
|
|
// Propagate the bit up the chain.
|
|
|
|
let mut curr = element;
|
|
|
|
while let Some(parent) = curr.parent_element() {
|
|
|
|
curr = parent;
|
|
|
|
if curr.has_dirty_descendants() { break; }
|
|
|
|
curr.set_dirty_descendants();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure and return the RestyleData.
|
|
|
|
Some(data.ensure_restyle())
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
|
|
|
|
2016-07-22 00:54:34 +03:00
|
|
|
#[no_mangle]
|
2016-11-25 20:00:44 +03:00
|
|
|
pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) -> *mut structs::ServoElementSnapshot
|
|
|
|
{
|
2016-09-09 10:00:13 +03:00
|
|
|
let element = GeckoElement(element);
|
2017-01-13 06:23:17 +03:00
|
|
|
let snapshot = match element.mutate_data() {
|
|
|
|
None => ptr::null_mut(),
|
|
|
|
Some(mut data) => {
|
|
|
|
if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } {
|
|
|
|
restyle_data.snapshot.ensure(|| element.create_snapshot()).borrow_mut_raw()
|
|
|
|
} else {
|
|
|
|
ptr::null_mut()
|
|
|
|
}
|
|
|
|
},
|
2016-11-25 20:00:44 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
debug!("Servo_Element_GetSnapshot: {:?}: {:?}", element, snapshot);
|
|
|
|
snapshot
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed,
|
|
|
|
restyle_hint: nsRestyleHint,
|
|
|
|
change_hint: nsChangeHint) {
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let damage = GeckoRestyleDamage::new(change_hint);
|
|
|
|
debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
|
|
|
|
element, restyle_hint, change_hint);
|
|
|
|
|
2017-01-13 06:23:17 +03:00
|
|
|
let mut maybe_data = element.mutate_data();
|
|
|
|
let maybe_restyle_data =
|
|
|
|
maybe_data.as_mut().and_then(|d| unsafe { maybe_restyle(d, element) });
|
|
|
|
if let Some(restyle_data) = maybe_restyle_data {
|
2016-11-25 20:00:44 +03:00
|
|
|
let restyle_hint: RestyleHint = restyle_hint.into();
|
|
|
|
restyle_data.hint.insert(&restyle_hint.into());
|
|
|
|
restyle_data.damage |= damage;
|
|
|
|
} else {
|
|
|
|
debug!("(Element not styled, discarding hints)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-31 06:12:55 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ImportRule_GetSheet(import_rule:
|
|
|
|
RawServoImportRuleBorrowed)
|
|
|
|
-> RawServoStyleSheetStrong {
|
|
|
|
let import_rule = RwLock::<ImportRule>::as_arc(&import_rule);
|
2017-01-14 00:25:39 +03:00
|
|
|
unsafe { mem::transmute(import_rule.read().stylesheet.clone()) }
|
2016-12-31 06:12:55 +03:00
|
|
|
}
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
#[no_mangle]
|
2017-01-10 04:26:50 +03:00
|
|
|
pub extern "C" fn Servo_TakeChangeHint(element: RawGeckoElementBorrowed) -> nsChangeHint
|
2016-11-25 20:00:44 +03:00
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
2017-01-10 04:26:50 +03:00
|
|
|
let damage = if let Some(mut data) = element.mutate_data() {
|
|
|
|
let d = data.get_restyle().map_or(GeckoRestyleDamage::empty(), |r| r.damage);
|
|
|
|
data.clear_restyle();
|
|
|
|
d
|
|
|
|
} else {
|
2016-11-25 20:00:44 +03:00
|
|
|
error!("Trying to get change hint from unstyled element");
|
2017-01-10 04:26:50 +03:00
|
|
|
GeckoRestyleDamage::empty()
|
|
|
|
};
|
2016-11-25 20:00:44 +03:00
|
|
|
|
2017-01-10 04:26:50 +03:00
|
|
|
debug!("Servo_TakeChangeHint: {:?}, damage={:?}", element, damage);
|
2016-11-25 20:00:44 +03:00
|
|
|
damage.as_change_hint()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ResolveStyle(element: RawGeckoElementBorrowed,
|
2017-01-10 04:26:50 +03:00
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
2016-12-28 06:55:01 +03:00
|
|
|
-> ServoComputedValuesStrong
|
2016-11-25 20:00:44 +03:00
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
2017-01-10 04:26:50 +03:00
|
|
|
debug!("Servo_ResolveStyle: {:?}", element);
|
|
|
|
let data = unsafe { element.ensure_data() }.borrow_mut();
|
2016-12-10 04:01:05 +03:00
|
|
|
|
|
|
|
if !data.has_current_styles() {
|
|
|
|
error!("Resolving style on unstyled element with lazy computation forbidden.");
|
2017-01-10 04:26:50 +03:00
|
|
|
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
2017-01-18 16:39:57 +03:00
|
|
|
return per_doc_data.default_computed_values().clone().into_strong();
|
2016-12-10 04:01:05 +03:00
|
|
|
}
|
|
|
|
|
2017-01-10 04:26:50 +03:00
|
|
|
data.styles().primary.values.clone().into_strong()
|
2016-11-25 20:00:44 +03:00
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2016-12-28 06:55:01 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
|
|
|
|
pseudo_tag: *mut nsIAtom,
|
|
|
|
raw_data: RawServoStyleSetBorrowed)
|
|
|
|
-> ServoComputedValuesStrong
|
|
|
|
{
|
|
|
|
let element = GeckoElement(element);
|
|
|
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
|
|
|
|
let finish = |styles: &ElementStyles| -> Arc<ComputedValues> {
|
|
|
|
let maybe_pseudo = if !pseudo_tag.is_null() {
|
|
|
|
get_pseudo_style(element, pseudo_tag, styles, doc_data)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
maybe_pseudo.unwrap_or_else(|| styles.primary.values.clone())
|
|
|
|
};
|
|
|
|
|
|
|
|
// In the common case we already have the style. Check that before setting
|
|
|
|
// up all the computation machinery.
|
|
|
|
let mut result = element.mutate_data()
|
|
|
|
.and_then(|d| d.get_styles().map(&finish));
|
|
|
|
if result.is_some() {
|
|
|
|
return result.unwrap().into_strong();
|
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have the style ready. Go ahead and compute it as necessary.
|
|
|
|
let shared = create_shared_context(&mut doc_data.borrow_mut());
|
|
|
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
|
|
|
let mut context = StyleContext {
|
|
|
|
shared: &shared,
|
|
|
|
thread_local: &mut tlc,
|
|
|
|
};
|
|
|
|
let ensure = |el: GeckoElement| { unsafe { el.ensure_data(); } };
|
|
|
|
let clear = |el: GeckoElement| el.clear_data();
|
|
|
|
resolve_style(&mut context, element, &ensure, &clear,
|
|
|
|
|styles| result = Some(finish(styles)));
|
|
|
|
|
|
|
|
result.unwrap().into_strong()
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) {
|
|
|
|
if !cfg!(debug_assertions) {
|
|
|
|
panic!("Calling Servo_AssertTreeIsClean in release build");
|
|
|
|
}
|
|
|
|
|
|
|
|
let root = GeckoElement(root);
|
|
|
|
fn assert_subtree_is_clean<'le>(el: GeckoElement<'le>) {
|
|
|
|
debug_assert!(!el.has_dirty_descendants());
|
|
|
|
for child in el.as_node().children() {
|
|
|
|
if let Some(child) = child.as_element() {
|
|
|
|
assert_subtree_is_clean(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-07-22 00:54:34 +03:00
|
|
|
|
2016-11-25 20:00:44 +03:00
|
|
|
assert_subtree_is_clean(root);
|
2016-07-22 00:54:34 +03:00
|
|
|
}
|
2017-01-29 08:24:04 +03:00
|
|
|
|
|
|
|
#[no_mangle]
|
|
|
|
pub extern "C" fn Servo_StyleSet_FillKeyframesForName(raw_data: RawServoStyleSetBorrowed,
|
|
|
|
name: *const nsACString,
|
|
|
|
timing_function: *const nsTimingFunction,
|
|
|
|
style: ServoComputedValuesBorrowed,
|
|
|
|
keyframes: RawGeckoKeyframeListBorrowedMut) -> bool {
|
|
|
|
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
|
|
|
let name = unsafe { Atom::from(name.as_ref().unwrap().as_str_unchecked()) };
|
|
|
|
let style_timing_function = unsafe { timing_function.as_ref().unwrap() };
|
|
|
|
let style = ComputedValues::as_arc(&style);
|
|
|
|
|
|
|
|
if let Some(ref animation) = data.stylist.animations().get(&name) {
|
|
|
|
for step in &animation.steps {
|
|
|
|
// Override timing_function if the keyframe has animation-timing-function.
|
|
|
|
let timing_function = if let Some(val) = step.get_animation_timing_function() {
|
|
|
|
val.into()
|
|
|
|
} else {
|
|
|
|
*style_timing_function
|
|
|
|
};
|
|
|
|
|
|
|
|
let keyframe = unsafe {
|
|
|
|
Gecko_AnimationAppendKeyframe(keyframes,
|
|
|
|
step.start_percentage.0 as f32,
|
|
|
|
&timing_function)
|
|
|
|
};
|
|
|
|
|
|
|
|
match step.value {
|
|
|
|
KeyframesStepValue::ComputedValues => {
|
|
|
|
for (index, property) in animation.properties_changed.iter().enumerate() {
|
|
|
|
let block = style.to_declaration_block(property.clone().into());
|
|
|
|
unsafe {
|
|
|
|
(*keyframe).mPropertyValues.set_len((index + 1) as u32);
|
|
|
|
(*keyframe).mPropertyValues[index].mProperty = property.clone().into();
|
|
|
|
(*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky(
|
|
|
|
Arc::new(RwLock::new(block)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
KeyframesStepValue::Declarations { ref block } => {
|
|
|
|
let guard = block.read();
|
|
|
|
// Filter out non-animatable properties.
|
|
|
|
let animatable =
|
|
|
|
guard.declarations
|
|
|
|
.iter()
|
|
|
|
.filter(|&&(ref declaration, _)| {
|
|
|
|
declaration.is_animatable()
|
|
|
|
});
|
|
|
|
for (index, &(ref declaration, _)) in animatable.enumerate() {
|
|
|
|
unsafe {
|
|
|
|
(*keyframe).mPropertyValues.set_len((index + 1) as u32);
|
|
|
|
(*keyframe).mPropertyValues[index].mProperty =
|
|
|
|
TransitionProperty::from_declaration(declaration).unwrap().into();
|
|
|
|
(*keyframe).mPropertyValues[index].mServoDeclarationBlock.set_arc_leaky(
|
|
|
|
Arc::new(RwLock::new(
|
|
|
|
PropertyDeclarationBlock { declarations: vec![ (declaration.clone(),
|
|
|
|
Importance::Normal) ],
|
|
|
|
important_count: 0 })));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|