gecko-dev/servo/ports/geckolib/glue.rs

1295 lines
53 KiB
Rust
Raw Normal View History

/* 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;
use atomic_refcell::AtomicRefMut;
use cssparser::Parser;
use cssparser::ToCss as ParserToCss;
use env_logger;
use euclid::Size2D;
use parking_lot::RwLock;
use selectors::Element;
use servo_url::ServoUrl;
use std::borrow::Cow;
use std::fmt::Write;
use std::mem;
use std::ptr;
use std::sync::{Arc, Mutex};
use style::arc_ptr_eq;
use style::context::{QuirksMode, ReflowGoal, SharedStyleContext, StyleContext};
use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInfo};
use style::data::{ElementData, ElementStyles, RestyleData};
use style::dom::{ShowSubtreeData, TElement, TNode};
use style::error_reporting::StdoutErrorReporter;
use style::gecko::data::{NUM_THREADS, PerDocumentStyleData, PerDocumentStyleDataImpl};
use style::gecko::restyle_damage::GeckoRestyleDamage;
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
servo: Merge #13372 - Merge most of geckolib into style (from Manishearth:merge-stylo); r=emilio Fixes #13038 r? @emilio Source-Repo: https://github.com/servo/servo Source-Revision: f763eca344fa6a49f2467d9baa25044bebc41ff2 --HG-- rename : servo/ports/geckolib/binding_tools/.gitignore => servo/components/style/binding_tools/.gitignore rename : servo/ports/geckolib/binding_tools/README.md => servo/components/style/binding_tools/README.md rename : servo/ports/geckolib/binding_tools/regen.py => servo/components/style/binding_tools/regen.py rename : servo/ports/geckolib/binding_tools/regen.sh => servo/components/style/binding_tools/regen.sh rename : servo/ports/geckolib/binding_tools/regen_atoms.py => servo/components/style/binding_tools/regen_atoms.py rename : servo/ports/geckolib/binding_tools/setup_bindgen.sh => servo/components/style/binding_tools/setup_bindgen.sh rename : servo/ports/geckolib/context.rs => servo/components/style/gecko/context.rs rename : servo/components/style/gecko_conversions.rs => servo/components/style/gecko/conversions.rs rename : servo/ports/geckolib/data.rs => servo/components/style/gecko/data.rs rename : servo/components/style/generated/gecko_pseudo_element_helper.rs => servo/components/style/gecko/generated/gecko_pseudo_element_helper.rs rename : servo/components/style/gecko_selector_impl.rs => servo/components/style/gecko/selector_impl.rs rename : servo/ports/geckolib/snapshot.rs => servo/components/style/gecko/snapshot.rs rename : servo/ports/geckolib/snapshot_helpers.rs => servo/components/style/gecko/snapshot_helpers.rs rename : servo/ports/geckolib/traversal.rs => servo/components/style/gecko/traversal.rs rename : servo/components/style/gecko_values.rs => servo/components/style/gecko/values.rs rename : servo/ports/geckolib/wrapper.rs => servo/components/style/gecko/wrapper.rs rename : servo/ports/geckolib/gecko_bindings/bindings.rs => servo/components/style/gecko_bindings/bindings.rs rename : servo/ports/geckolib/gecko_bindings/lib.rs => servo/components/style/gecko_bindings/mod.rs rename : servo/ports/geckolib/gecko_bindings/ptr.rs => servo/components/style/gecko_bindings/ptr.rs rename : servo/ports/geckolib/gecko_bindings/structs_debug.rs => servo/components/style/gecko_bindings/structs_debug.rs rename : servo/ports/geckolib/gecko_bindings/structs_release.rs => servo/components/style/gecko_bindings/structs_release.rs rename : servo/ports/geckolib/gecko_bindings/sugar/mod.rs => servo/components/style/gecko_bindings/sugar/mod.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_css_shadow_array.rs => servo/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_auto_array.rs => servo/components/style/gecko_bindings/sugar/ns_style_auto_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs => servo/components/style/gecko_bindings/sugar/ns_style_coord.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_t_array.rs => servo/components/style/gecko_bindings/sugar/ns_t_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ownership.rs => servo/components/style/gecko_bindings/sugar/ownership.rs rename : servo/ports/geckolib/string_cache/lib.rs => servo/components/style/gecko_string_cache/mod.rs rename : servo/ports/geckolib/string_cache/namespace.rs => servo/components/style/gecko_string_cache/namespace.rs
2016-09-26 07:36:05 +00:00
use style::gecko::traversal::RecalcStyleOnly;
use style::gecko::wrapper::DUMMY_BASE_URL;
use style::gecko::wrapper::GeckoElement;
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
servo: Merge #13372 - Merge most of geckolib into style (from Manishearth:merge-stylo); r=emilio Fixes #13038 r? @emilio Source-Repo: https://github.com/servo/servo Source-Revision: f763eca344fa6a49f2467d9baa25044bebc41ff2 --HG-- rename : servo/ports/geckolib/binding_tools/.gitignore => servo/components/style/binding_tools/.gitignore rename : servo/ports/geckolib/binding_tools/README.md => servo/components/style/binding_tools/README.md rename : servo/ports/geckolib/binding_tools/regen.py => servo/components/style/binding_tools/regen.py rename : servo/ports/geckolib/binding_tools/regen.sh => servo/components/style/binding_tools/regen.sh rename : servo/ports/geckolib/binding_tools/regen_atoms.py => servo/components/style/binding_tools/regen_atoms.py rename : servo/ports/geckolib/binding_tools/setup_bindgen.sh => servo/components/style/binding_tools/setup_bindgen.sh rename : servo/ports/geckolib/context.rs => servo/components/style/gecko/context.rs rename : servo/components/style/gecko_conversions.rs => servo/components/style/gecko/conversions.rs rename : servo/ports/geckolib/data.rs => servo/components/style/gecko/data.rs rename : servo/components/style/generated/gecko_pseudo_element_helper.rs => servo/components/style/gecko/generated/gecko_pseudo_element_helper.rs rename : servo/components/style/gecko_selector_impl.rs => servo/components/style/gecko/selector_impl.rs rename : servo/ports/geckolib/snapshot.rs => servo/components/style/gecko/snapshot.rs rename : servo/ports/geckolib/snapshot_helpers.rs => servo/components/style/gecko/snapshot_helpers.rs rename : servo/ports/geckolib/traversal.rs => servo/components/style/gecko/traversal.rs rename : servo/components/style/gecko_values.rs => servo/components/style/gecko/values.rs rename : servo/ports/geckolib/wrapper.rs => servo/components/style/gecko/wrapper.rs rename : servo/ports/geckolib/gecko_bindings/bindings.rs => servo/components/style/gecko_bindings/bindings.rs rename : servo/ports/geckolib/gecko_bindings/lib.rs => servo/components/style/gecko_bindings/mod.rs rename : servo/ports/geckolib/gecko_bindings/ptr.rs => servo/components/style/gecko_bindings/ptr.rs rename : servo/ports/geckolib/gecko_bindings/structs_debug.rs => servo/components/style/gecko_bindings/structs_debug.rs rename : servo/ports/geckolib/gecko_bindings/structs_release.rs => servo/components/style/gecko_bindings/structs_release.rs rename : servo/ports/geckolib/gecko_bindings/sugar/mod.rs => servo/components/style/gecko_bindings/sugar/mod.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_css_shadow_array.rs => servo/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_auto_array.rs => servo/components/style/gecko_bindings/sugar/ns_style_auto_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs => servo/components/style/gecko_bindings/sugar/ns_style_coord.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_t_array.rs => servo/components/style/gecko_bindings/sugar/ns_t_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ownership.rs => servo/components/style/gecko_bindings/sugar/ownership.rs rename : servo/ports/geckolib/string_cache/lib.rs => servo/components/style/gecko_string_cache/mod.rs rename : servo/ports/geckolib/string_cache/namespace.rs => servo/components/style/gecko_string_cache/namespace.rs
2016-09-26 07:36:05 +00:00
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
use style::gecko_bindings::bindings::{nsACString, nsCSSValueBorrowedMut, nsAString};
use style::gecko_bindings::bindings::Gecko_AnimationAppendKeyframe;
use style::gecko_bindings::bindings::RawGeckoAnimationValueListBorrowedMut;
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
use style::gecko_bindings::bindings::RawGeckoKeyframeListBorrowedMut;
use style::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use style::gecko_bindings::bindings::RawServoAnimationValueBorrowed;
use style::gecko_bindings::bindings::RawServoAnimationValueStrong;
use style::gecko_bindings::bindings::RawServoImportRuleBorrowed;
use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
use style::gecko_bindings::bindings::nsTArrayBorrowed_uintptr_t;
use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint};
use style::gecko_bindings::structs::Loader;
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
use style::gecko_bindings::structs::RawServoAnimationValueBorrowedListBorrowed;
use style::gecko_bindings::structs::ServoStyleSheet;
use style::gecko_bindings::structs::nsCSSValueSharedList;
use style::gecko_bindings::structs::nsTimingFunction;
use style::gecko_bindings::structs::nsresult;
servo: Merge #13372 - Merge most of geckolib into style (from Manishearth:merge-stylo); r=emilio Fixes #13038 r? @emilio Source-Repo: https://github.com/servo/servo Source-Revision: f763eca344fa6a49f2467d9baa25044bebc41ff2 --HG-- rename : servo/ports/geckolib/binding_tools/.gitignore => servo/components/style/binding_tools/.gitignore rename : servo/ports/geckolib/binding_tools/README.md => servo/components/style/binding_tools/README.md rename : servo/ports/geckolib/binding_tools/regen.py => servo/components/style/binding_tools/regen.py rename : servo/ports/geckolib/binding_tools/regen.sh => servo/components/style/binding_tools/regen.sh rename : servo/ports/geckolib/binding_tools/regen_atoms.py => servo/components/style/binding_tools/regen_atoms.py rename : servo/ports/geckolib/binding_tools/setup_bindgen.sh => servo/components/style/binding_tools/setup_bindgen.sh rename : servo/ports/geckolib/context.rs => servo/components/style/gecko/context.rs rename : servo/components/style/gecko_conversions.rs => servo/components/style/gecko/conversions.rs rename : servo/ports/geckolib/data.rs => servo/components/style/gecko/data.rs rename : servo/components/style/generated/gecko_pseudo_element_helper.rs => servo/components/style/gecko/generated/gecko_pseudo_element_helper.rs rename : servo/components/style/gecko_selector_impl.rs => servo/components/style/gecko/selector_impl.rs rename : servo/ports/geckolib/snapshot.rs => servo/components/style/gecko/snapshot.rs rename : servo/ports/geckolib/snapshot_helpers.rs => servo/components/style/gecko/snapshot_helpers.rs rename : servo/ports/geckolib/traversal.rs => servo/components/style/gecko/traversal.rs rename : servo/components/style/gecko_values.rs => servo/components/style/gecko/values.rs rename : servo/ports/geckolib/wrapper.rs => servo/components/style/gecko/wrapper.rs rename : servo/ports/geckolib/gecko_bindings/bindings.rs => servo/components/style/gecko_bindings/bindings.rs rename : servo/ports/geckolib/gecko_bindings/lib.rs => servo/components/style/gecko_bindings/mod.rs rename : servo/ports/geckolib/gecko_bindings/ptr.rs => servo/components/style/gecko_bindings/ptr.rs rename : servo/ports/geckolib/gecko_bindings/structs_debug.rs => servo/components/style/gecko_bindings/structs_debug.rs rename : servo/ports/geckolib/gecko_bindings/structs_release.rs => servo/components/style/gecko_bindings/structs_release.rs rename : servo/ports/geckolib/gecko_bindings/sugar/mod.rs => servo/components/style/gecko_bindings/sugar/mod.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_css_shadow_array.rs => servo/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_auto_array.rs => servo/components/style/gecko_bindings/sugar/ns_style_auto_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs => servo/components/style/gecko_bindings/sugar/ns_style_coord.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_t_array.rs => servo/components/style/gecko_bindings/sugar/ns_t_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ownership.rs => servo/components/style/gecko_bindings/sugar/ownership.rs rename : servo/ports/geckolib/string_cache/lib.rs => servo/components/style/gecko_string_cache/mod.rs rename : servo/ports/geckolib/string_cache/namespace.rs => servo/components/style/gecko_string_cache/namespace.rs
2016-09-26 07:36:05 +00:00
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
use style::gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI};
use style::gecko_properties::style_structs;
use style::keyframes::KeyframesStepValue;
use style::parallel;
use style::parser::{ParserContext, ParserContextExtraData};
use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
use style::properties::{PropertyDeclarationParseResult, PropertyDeclarationBlock, PropertyId};
use style::properties::{apply_declarations, parse_one_declaration};
use style::properties::animated_properties::{AnimationValue, Interpolate, TransitionProperty};
use style::restyle_hints::RestyleHint;
use style::selector_parser::PseudoElementCascadeType;
use style::sequential;
servo: Merge #13372 - Merge most of geckolib into style (from Manishearth:merge-stylo); r=emilio Fixes #13038 r? @emilio Source-Repo: https://github.com/servo/servo Source-Revision: f763eca344fa6a49f2467d9baa25044bebc41ff2 --HG-- rename : servo/ports/geckolib/binding_tools/.gitignore => servo/components/style/binding_tools/.gitignore rename : servo/ports/geckolib/binding_tools/README.md => servo/components/style/binding_tools/README.md rename : servo/ports/geckolib/binding_tools/regen.py => servo/components/style/binding_tools/regen.py rename : servo/ports/geckolib/binding_tools/regen.sh => servo/components/style/binding_tools/regen.sh rename : servo/ports/geckolib/binding_tools/regen_atoms.py => servo/components/style/binding_tools/regen_atoms.py rename : servo/ports/geckolib/binding_tools/setup_bindgen.sh => servo/components/style/binding_tools/setup_bindgen.sh rename : servo/ports/geckolib/context.rs => servo/components/style/gecko/context.rs rename : servo/components/style/gecko_conversions.rs => servo/components/style/gecko/conversions.rs rename : servo/ports/geckolib/data.rs => servo/components/style/gecko/data.rs rename : servo/components/style/generated/gecko_pseudo_element_helper.rs => servo/components/style/gecko/generated/gecko_pseudo_element_helper.rs rename : servo/components/style/gecko_selector_impl.rs => servo/components/style/gecko/selector_impl.rs rename : servo/ports/geckolib/snapshot.rs => servo/components/style/gecko/snapshot.rs rename : servo/ports/geckolib/snapshot_helpers.rs => servo/components/style/gecko/snapshot_helpers.rs rename : servo/ports/geckolib/traversal.rs => servo/components/style/gecko/traversal.rs rename : servo/components/style/gecko_values.rs => servo/components/style/gecko/values.rs rename : servo/ports/geckolib/wrapper.rs => servo/components/style/gecko/wrapper.rs rename : servo/ports/geckolib/gecko_bindings/bindings.rs => servo/components/style/gecko_bindings/bindings.rs rename : servo/ports/geckolib/gecko_bindings/lib.rs => servo/components/style/gecko_bindings/mod.rs rename : servo/ports/geckolib/gecko_bindings/ptr.rs => servo/components/style/gecko_bindings/ptr.rs rename : servo/ports/geckolib/gecko_bindings/structs_debug.rs => servo/components/style/gecko_bindings/structs_debug.rs rename : servo/ports/geckolib/gecko_bindings/structs_release.rs => servo/components/style/gecko_bindings/structs_release.rs rename : servo/ports/geckolib/gecko_bindings/sugar/mod.rs => servo/components/style/gecko_bindings/sugar/mod.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_css_shadow_array.rs => servo/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_auto_array.rs => servo/components/style/gecko_bindings/sugar/ns_style_auto_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs => servo/components/style/gecko_bindings/sugar/ns_style_coord.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_t_array.rs => servo/components/style/gecko_bindings/sugar/ns_t_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ownership.rs => servo/components/style/gecko_bindings/sugar/ownership.rs rename : servo/ports/geckolib/string_cache/lib.rs => servo/components/style/gecko_string_cache/mod.rs rename : servo/ports/geckolib/string_cache/namespace.rs => servo/components/style/gecko_string_cache/namespace.rs
2016-09-26 07:36:05 +00:00
use style::string_cache::Atom;
use style::stylesheets::{CssRule, CssRules, Origin, Stylesheet, StyleRule, ImportRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::supports::parse_condition_or_declaration;
use style::thread_state;
use style::timer::Timer;
use style::traversal::{resolve_style, DomTraversal, TraversalDriver};
use style_traits::ToCss;
use stylesheet_loader::StylesheetLoader;
servo: Merge #13372 - Merge most of geckolib into style (from Manishearth:merge-stylo); r=emilio Fixes #13038 r? @emilio Source-Repo: https://github.com/servo/servo Source-Revision: f763eca344fa6a49f2467d9baa25044bebc41ff2 --HG-- rename : servo/ports/geckolib/binding_tools/.gitignore => servo/components/style/binding_tools/.gitignore rename : servo/ports/geckolib/binding_tools/README.md => servo/components/style/binding_tools/README.md rename : servo/ports/geckolib/binding_tools/regen.py => servo/components/style/binding_tools/regen.py rename : servo/ports/geckolib/binding_tools/regen.sh => servo/components/style/binding_tools/regen.sh rename : servo/ports/geckolib/binding_tools/regen_atoms.py => servo/components/style/binding_tools/regen_atoms.py rename : servo/ports/geckolib/binding_tools/setup_bindgen.sh => servo/components/style/binding_tools/setup_bindgen.sh rename : servo/ports/geckolib/context.rs => servo/components/style/gecko/context.rs rename : servo/components/style/gecko_conversions.rs => servo/components/style/gecko/conversions.rs rename : servo/ports/geckolib/data.rs => servo/components/style/gecko/data.rs rename : servo/components/style/generated/gecko_pseudo_element_helper.rs => servo/components/style/gecko/generated/gecko_pseudo_element_helper.rs rename : servo/components/style/gecko_selector_impl.rs => servo/components/style/gecko/selector_impl.rs rename : servo/ports/geckolib/snapshot.rs => servo/components/style/gecko/snapshot.rs rename : servo/ports/geckolib/snapshot_helpers.rs => servo/components/style/gecko/snapshot_helpers.rs rename : servo/ports/geckolib/traversal.rs => servo/components/style/gecko/traversal.rs rename : servo/components/style/gecko_values.rs => servo/components/style/gecko/values.rs rename : servo/ports/geckolib/wrapper.rs => servo/components/style/gecko/wrapper.rs rename : servo/ports/geckolib/gecko_bindings/bindings.rs => servo/components/style/gecko_bindings/bindings.rs rename : servo/ports/geckolib/gecko_bindings/lib.rs => servo/components/style/gecko_bindings/mod.rs rename : servo/ports/geckolib/gecko_bindings/ptr.rs => servo/components/style/gecko_bindings/ptr.rs rename : servo/ports/geckolib/gecko_bindings/structs_debug.rs => servo/components/style/gecko_bindings/structs_debug.rs rename : servo/ports/geckolib/gecko_bindings/structs_release.rs => servo/components/style/gecko_bindings/structs_release.rs rename : servo/ports/geckolib/gecko_bindings/sugar/mod.rs => servo/components/style/gecko_bindings/sugar/mod.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_css_shadow_array.rs => servo/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_auto_array.rs => servo/components/style/gecko_bindings/sugar/ns_style_auto_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_style_coord.rs => servo/components/style/gecko_bindings/sugar/ns_style_coord.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ns_t_array.rs => servo/components/style/gecko_bindings/sugar/ns_t_array.rs rename : servo/ports/geckolib/gecko_bindings/sugar/ownership.rs => servo/components/style/gecko_bindings/sugar/ownership.rs rename : servo/ports/geckolib/string_cache/lib.rs => servo/components/style/gecko_string_cache/mod.rs rename : servo/ports/geckolib/string_cache/namespace.rs => servo/components/style/gecko_string_cache/namespace.rs
2016-09-26 07:36:05 +00: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.
*/
#[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();
// Pretend that we're a Servo Layout thread, to make some assertions happy.
thread_state::initialize(thread_state::LAYOUT);
}
#[no_mangle]
pub extern "C" fn Servo_Shutdown() -> () {
}
fn create_shared_context(per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext {
let local_context_data =
ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
SharedStyleContext {
// FIXME (bug 1303229): Use the actual viewport size here
viewport_size: Size2D::new(Au(0), Au(0)),
screen_size_changed: false,
goal: ReflowGoal::ForScriptQuery,
stylist: per_doc_data.stylist.clone(),
running_animations: per_doc_data.running_animations.clone(),
expired_animations: per_doc_data.expired_animations.clone(),
error_reporter: Box::new(StdoutErrorReporter),
local_context_creation_data: Mutex::new(local_context_data),
timer: Timer::new(),
// FIXME Find the real QuirksMode information for this document
quirks_mode: QuirksMode::NoQuirks,
default_computed_values: per_doc_data.default_computed_values().clone(),
}
}
fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
unstyled_children_only: bool) {
// 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() {
if parent.borrow_data().map_or(true, |d| d.styles().is_display_none()) {
debug!("{:?} has unstyled parent - ignoring call to traverse_subtree", parent);
return;
}
}
servo: Merge #14436 - Make restyle tracking more granular (from bholley:granular_restyle); r=emilio The primary idea of this patch is to ditch the rigid enum of Previous/Current styles, and replace it with a series of indicators for the various types of work that needs to be performed (expanding snapshots, rematching, recascading, and damage processing). This loses us a little bit of sanity checking (since the up-to-date-ness of our style is no longer baked into the type system), but gives us a lot more flexibility that we'll need going forward (especially when we separate matching from cascading). We also eliminate get_styling_mode in favor of a method on the traversal. This patch does a few other things as ridealongs: * Temporarily eliminates the handling for transfering ownership of styles to the frame. We'll need this again at some point, but for now it's causing too much complexity for a half-implemented feature. * Ditches TRestyleDamage, which is no longer necessary post-crate-merge, and is a constant source of compilation failures from either needing to be imported or being unnecessarily imported (which varies between gecko and servo). * Expands Snapshots for the traversal root, which was missing before. * Fixes up the skip_root stuff to avoid visiting the skipped root. * Unifies parallel traversal and avoids spawning for a single work item. * Adds an explicit pre_traverse step do any pre-processing and determine whether we need to traverse at all. Source-Repo: https://github.com/servo/servo Source-Revision: b9a8ccd775c3192e3810a1730b1d0bc2b5c9dfb6
2016-12-10 01:01:05 +00:00
let mut per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let token = RecalcStyleOnly::pre_traverse(element, &per_doc_data.stylist, unstyled_children_only);
servo: Merge #14436 - Make restyle tracking more granular (from bholley:granular_restyle); r=emilio The primary idea of this patch is to ditch the rigid enum of Previous/Current styles, and replace it with a series of indicators for the various types of work that needs to be performed (expanding snapshots, rematching, recascading, and damage processing). This loses us a little bit of sanity checking (since the up-to-date-ness of our style is no longer baked into the type system), but gives us a lot more flexibility that we'll need going forward (especially when we separate matching from cascading). We also eliminate get_styling_mode in favor of a method on the traversal. This patch does a few other things as ridealongs: * Temporarily eliminates the handling for transfering ownership of styles to the frame. We'll need this again at some point, but for now it's causing too much complexity for a half-implemented feature. * Ditches TRestyleDamage, which is no longer necessary post-crate-merge, and is a constant source of compilation failures from either needing to be imported or being unnecessarily imported (which varies between gecko and servo). * Expands Snapshots for the traversal root, which was missing before. * Fixes up the skip_root stuff to avoid visiting the skipped root. * Unifies parallel traversal and avoids spawning for a single work item. * Adds an explicit pre_traverse step do any pre-processing and determine whether we need to traverse at all. Source-Repo: https://github.com/servo/servo Source-Revision: b9a8ccd775c3192e3810a1730b1d0bc2b5c9dfb6
2016-12-10 01:01:05 +00:00
if !token.should_traverse() {
error!("Unnecessary call to traverse_subtree");
return;
}
debug!("Traversing subtree:");
debug!("{:?}", ShowSubtreeData(element.as_node()));
let shared_style_context = create_shared_context(&per_doc_data);
let traversal_driver = if per_doc_data.num_threads == 1 || per_doc_data.work_queue.is_none() {
TraversalDriver::Sequential
} else {
TraversalDriver::Parallel
};
let traversal = RecalcStyleOnly::new(shared_style_context, traversal_driver);
let known_depth = None;
if traversal_driver.is_parallel() {
parallel::traverse_dom(&traversal, element, known_depth, token,
per_doc_data.work_queue.as_mut().unwrap());
} else {
sequential::traverse_dom(&traversal, element, token);
}
}
#[no_mangle]
pub extern "C" fn Servo_TraverseSubtree(root: RawGeckoElementBorrowed,
raw_data: RawServoStyleSetBorrowed,
behavior: structs::TraversalRootBehavior) -> () {
let element = GeckoElement(root);
debug!("Servo_TraverseSubtree: {:?}", element);
traverse_subtree(element, raw_data,
behavior == structs::TraversalRootBehavior::UnstyledChildrenOnly);
}
#[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
{
let value = unsafe { value.as_ref().unwrap() };
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()
}
#[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");
}
}
/// 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) {
gecko.mValue.mServo.set_arc_leaky(Arc::new(servo));
}
}
// 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) };
}
#[no_mangle]
pub extern "C" fn Servo_RestyleWithAddedDeclaration(raw_data: RawServoStyleSetBorrowed,
declarations: RawServoDeclarationBlockBorrowed,
previous_style: ServoComputedValuesBorrowed)
-> ServoComputedValuesStrong
{
let previous_style = ComputedValues::as_arc(&previous_style);
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
let guard = declarations.read();
let declarations = || {
guard.declarations.iter().rev().map(|&(ref decl, _importance)| decl)
};
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
// FIXME (bug 1303229): Use the actual viewport size here
let computed = apply_declarations(Size2D::new(Au(0), Au(0)),
/* is_root_element = */ false,
declarations,
previous_style,
data.default_computed_values(),
None,
Box::new(StdoutErrorReporter),
None,
CascadeFlags::empty());
Arc::new(computed).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
*NUM_THREADS as u32
}
#[no_mangle]
pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) -> () {
GeckoElement(element).clear_data();
}
#[no_mangle]
pub extern "C" fn Servo_Element_ShouldTraverse(element: RawGeckoElementBorrowed) -> bool {
let element = GeckoElement(element);
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
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyleSheetStrong {
let url = ServoUrl::parse("about:blank").unwrap();
let extra_data = ParserContextExtraData::default();
let origin = match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
SheetParsingMode::eUserSheetFeatures => Origin::User,
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
};
let sheet = Arc::new(Stylesheet::from_str(
"", url, origin, Default::default(), None,
Box::new(StdoutErrorReporter), extra_data));
unsafe {
mem::transmute(sheet)
}
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
stylesheet: *mut ServoStyleSheet,
data: *const nsACString,
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() };
let origin = match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
SheetParsingMode::eUserSheetFeatures => Origin::User,
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
};
let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() };
let url = ServoUrl::parse(base_str).unwrap();
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, 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 = Arc::new(Stylesheet::from_str(
input, url, origin, Default::default(), loader,
Box::new(StdoutErrorReporter), extra_data));
unsafe {
mem::transmute(sheet)
}
}
#[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);
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
flush: bool) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
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;
if flush {
data.flush_stylesheets();
}
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
flush: bool) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
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;
if flush {
data.flush_stylesheets();
}
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
raw_reference: RawServoStyleSheetBorrowed,
flush: bool) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
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;
if flush {
data.flush_stylesheets();
}
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowed,
raw_sheet: RawServoStyleSheetBorrowed,
flush: bool) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let sheet = HasArcFFI::as_arc(&raw_sheet);
data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
data.stylesheets_changed = true;
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();
}
#[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;
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_HasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
!Stylesheet::as_arc(&raw_sheet).rules.read().0.is_empty()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed) -> ServoCssRulesStrong {
Stylesheet::as_arc(&sheet).rules.clone().into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_AddRef(sheet: RawServoStyleSheetBorrowed) -> () {
unsafe { Stylesheet::addref(sheet) };
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_Release(sheet: RawServoStyleSheetBorrowed) -> () {
unsafe { Stylesheet::release(sheet) };
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_ListTypes(rules: ServoCssRulesBorrowed,
result: nsTArrayBorrowed_uintptr_t) -> () {
let rules = RwLock::<CssRules>::as_arc(&rules).read();
let iter = rules.0.iter().map(|rule| rule.rule_type() as usize);
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 {
let rules = RwLock::<CssRules>::as_arc(&rules).read();
match rules.0[index as usize] {
CssRule::Style(ref rule) => rule.clone().into_strong(),
_ => {
unreachable!("GetStyleRuleAt should only be called on a style rule");
}
}
}
#[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()
}
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_AddRef(rules: ServoCssRulesBorrowed) -> () {
unsafe { RwLock::<CssRules>::addref(rules) };
}
#[no_mangle]
pub extern "C" fn Servo_CssRules_Release(rules: ServoCssRulesBorrowed) -> () {
unsafe { RwLock::<CssRules>::release(rules) };
}
#[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();
}
#[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) };
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowedOrNull,
pseudo_tag: *mut nsIAtom,
raw_data: RawServoStyleSetBorrowed)
-> ServoComputedValuesStrong {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
servo: Merge #12815 - stylo: Use atoms as the pseudo-element back-end (from emilio:stylo-atoms); r=bholley <!-- Please describe your changes on the following line: --> A bit of work left, and we can uber-optimize this (left comments, will fill follow-ups), but this is a decent refactor so I thought I'd rather get some feedback on it. r? @bholley (not formally yet, maybe, but some feedback is appreciated). --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because geckolib only... <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: c386a3c8813a17d810f48d0b4ad18f2c984ecaa4 --HG-- rename : servo/ports/geckolib/gecko_bindings/tools/.gitignore => servo/ports/geckolib/binding_tools/.gitignore rename : servo/ports/geckolib/gecko_bindings/tools/README.md => servo/ports/geckolib/binding_tools/README.md rename : servo/ports/geckolib/gecko_bindings/tools/regen.py => servo/ports/geckolib/binding_tools/regen.py rename : servo/ports/geckolib/gecko_bindings/tools/regen.sh => servo/ports/geckolib/binding_tools/regen.sh rename : servo/ports/geckolib/gecko_bindings/tools/setup_bindgen.sh => servo/ports/geckolib/binding_tools/setup_bindgen.sh
2016-08-16 17:50:29 +00:00
let atom = Atom::from(pseudo_tag);
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
2016-10-05 05:59:56 +00:00
let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null);
data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent,
data.default_computed_values(), false)
.values
.into_strong()
}
#[no_mangle]
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();
let doc_data = PerDocumentStyleData::from_ffi(raw_data);
// FIXME(bholley): Assert against this.
if data.get_styles().is_none() {
error!("Calling Servo_ResolvePseudoStyle on unstyled element");
return if is_probe {
Strong::null()
} else {
doc_data.borrow().default_computed_values().clone().into_strong()
};
}
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(),
}
}
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);
match SelectorImpl::pseudo_element_cascade_type(&pseudo) {
PseudoElementCascadeType::Eager => styles.pseudos.get(&pseudo).map(|s| s.values.clone()),
PseudoElementCascadeType::Precomputed => unreachable!("No anonymous boxes"),
PseudoElementCascadeType::Lazy => {
let d = doc_data.borrow_mut();
let base = &styles.primary.values;
d.stylist.lazily_compute_pseudo_element_style(&element, &pseudo, base, &d.default_computed_values())
.map(|s| s.values.clone())
},
}
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_Inherit(
raw_data: RawServoStyleSetBorrowed,
parent_style: ServoComputedValuesBorrowedOrNull)
-> ServoComputedValuesStrong {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
2016-10-05 05:59:56 +00:00
let maybe_arc = ComputedValues::arc_from_borrowed(&parent_style);
let style = if let Some(reference) = maybe_arc.as_ref() {
ComputedValues::inherit_from(reference, &data.default_computed_values())
} else {
data.default_computed_values().clone()
};
style.into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_AddRef(ptr: ServoComputedValuesBorrowed) {
unsafe { ComputedValues::addref(ptr) };
}
#[no_mangle]
pub extern "C" fn Servo_ComputedValues_Release(ptr: ServoComputedValuesBorrowed) {
unsafe { ComputedValues::release(ptr) };
}
/// 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).
#[no_mangle]
pub extern "C" fn Servo_StyleSet_Init(pres_context: RawGeckoPresContextOwned)
-> RawServoStyleSetOwned {
let data = Box::new(PerDocumentStyleData::new(pres_context));
data.into_ffi()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_RebuildData(raw_data: RawServoStyleSetBorrowed) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
data.reset_device();
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) -> () {
let _ = data.into_box::<PerDocumentStyleData>();
}
#[no_mangle]
pub extern "C" fn Servo_ParseProperty(property: *const nsACString, value: *const nsACString,
base_url: *const nsACString, base: *mut ThreadSafeURIHolder,
referrer: *mut ThreadSafeURIHolder,
principal: *mut ThreadSafePrincipalHolder)
-> RawServoDeclarationBlockStrong {
let name = unsafe { property.as_ref().unwrap().as_str_unchecked() };
let id = if let Ok(id) = PropertyId::parse(name.into()) {
id
} else {
return RawServoDeclarationBlockStrong::null()
};
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
let base_str = unsafe { base_url.as_ref().unwrap().as_str_unchecked() };
let base_url = ServoUrl::parse(base_str).unwrap();
let extra_data = unsafe { ParserContextExtraData {
base: Some(GeckoArcURI::new(base)),
referrer: Some(GeckoArcURI::new(referrer)),
principal: Some(GeckoArcPrincipal::new(principal)),
}};
let context = ParserContext::new_with_extra_data(Origin::Author, &base_url,
Box::new(StdoutErrorReporter),
extra_data);
let mut results = vec![];
match PropertyDeclaration::parse(id, &context, &mut Parser::new(value),
&mut results, false) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {},
_ => return RawServoDeclarationBlockStrong::null(),
}
Arc::new(RwLock::new(PropertyDeclarationBlock {
declarations: results,
important_count: 0,
})).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_ParseStyleAttribute(data: *const nsACString) -> RawServoDeclarationBlockStrong {
let value = unsafe { data.as_ref().unwrap().as_str_unchecked() };
Arc::new(RwLock::new(GeckoElement::parse_style_attribute(value))).into_strong()
}
#[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()
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: RawServoDeclarationBlockBorrowed) {
unsafe { RwLock::<PropertyDeclarationBlock>::addref(declarations) };
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_Release(declarations: RawServoDeclarationBlockBorrowed) {
unsafe { RwLock::<PropertyDeclarationBlock>::release(declarations) };
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
b: RawServoDeclarationBlockBorrowed)
-> bool {
*RwLock::<PropertyDeclarationBlock>::as_arc(&a).read() == *RwLock::<PropertyDeclarationBlock>::as_arc(&b).read()
}
#[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();
}
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; }
}
}}
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_SerializeOneValue(
declarations: RawServoDeclarationBlockBorrowed,
property_id: nsCSSPropertyID, buffer: *mut nsAString)
{
let property_id = get_property_id_from_nscsspropertyid!(property_id, ());
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
let mut string = String::new();
let rv = declarations.read().single_value_to_css(&property_id, &mut string);
debug_assert!(rv.is_ok());
write!(unsafe { &mut *buffer }, "{}", string).expect("Failed to copy string");
}
#[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() };
decl.id().to_css(result).unwrap();
true
} else {
false
}
}
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();
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_GetPropertyValue(declarations: RawServoDeclarationBlockBorrowed,
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)
}
#[no_mangle]
pub extern "C" fn Servo_DeclarationBlock_GetPropertyIsImportant(declarations: RawServoDeclarationBlockBorrowed,
property: *const nsACString) -> bool {
let property_id = get_property_id_from_property!(property, false);
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
declarations.read().property_priority(&property_id).important()
}
fn set_property(declarations: RawServoDeclarationBlockBorrowed, property_id: PropertyId,
value: *mut nsACString, is_important: bool) -> bool {
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();
if let Ok(decls) = parse_one_declaration(property_id, value, &base_url,
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() {
declarations.set_parsed_declaration(decl.0, importance);
}
true
} else {
false
}
}
#[no_mangle]
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) {
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
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, ()))
}
#[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() {
PropertyDeclaration::Color(DeclaredValue::Value(Box::new(
specified::CSSRGBA {
parsed: convert_nscolor_to_rgba(color),
authored: None
}
)))
} 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));
}
#[no_mangle]
pub extern "C" fn Servo_CSSSupports2(property: *const nsACString, value: *const nsACString) -> bool {
let property = unsafe { property.as_ref().unwrap().as_str_unchecked() };
let id = if let Ok(id) = PropertyId::parse(property.into()) {
id
} else {
return false
};
let value = unsafe { value.as_ref().unwrap().as_str_unchecked() };
let base_url = &*DUMMY_BASE_URL;
let extra_data = ParserContextExtraData::default();
match parse_one_declaration(id, &value, &base_url, Box::new(StdoutErrorReporter), extra_data) {
Ok(decls) => !decls.is_empty(),
Err(()) => false,
}
}
servo: Merge #12469 - style: Rewrite the restyle hints code to allow different kinds of element snapshots (from emilio:stylo); r=bholley <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because refactoring. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> This is a rewrite for how style interfaces with its consumers in order to allow different representations for an element snapshot. This also changes the requirements of an element snapshot, requiring them to only implement MatchAttr, instead of MatchAttrGeneric. This is important for stylo since implementing MatchAttrGeneric is way more difficult for us given the atom limitations. This also allows for more performant implementations in the Gecko side of things. I don't want to get this merged just yet, mainly because the stylo part is not implemented, but I'd like early feedback from @bholley and/or @heycam: How do you see this approach? I don't think we'll have much problem to implement MatchAttr for our element snapshots, but... worth checking. r? @heycam Source-Repo: https://github.com/servo/servo Source-Revision: 1e0321f7dde5f33f7d26bbd4f088622fa3660477
2016-07-21 21:54:34 +00: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
}
}
/// 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>
{
// Don't generate a useless RestyleData if the element hasn't been styled.
if !data.has_styles() {
return None;
}
// 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())
}
servo: Merge #12469 - style: Rewrite the restyle hints code to allow different kinds of element snapshots (from emilio:stylo); r=bholley <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because refactoring. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> This is a rewrite for how style interfaces with its consumers in order to allow different representations for an element snapshot. This also changes the requirements of an element snapshot, requiring them to only implement MatchAttr, instead of MatchAttrGeneric. This is important for stylo since implementing MatchAttrGeneric is way more difficult for us given the atom limitations. This also allows for more performant implementations in the Gecko side of things. I don't want to get this merged just yet, mainly because the stylo part is not implemented, but I'd like early feedback from @bholley and/or @heycam: How do you see this approach? I don't think we'll have much problem to implement MatchAttr for our element snapshots, but... worth checking. r? @heycam Source-Repo: https://github.com/servo/servo Source-Revision: 1e0321f7dde5f33f7d26bbd4f088622fa3660477
2016-07-21 21:54:34 +00:00
#[no_mangle]
pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) -> *mut structs::ServoElementSnapshot
{
let element = GeckoElement(element);
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()
}
},
};
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);
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 {
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)");
}
}
#[no_mangle]
pub extern "C" fn Servo_ImportRule_GetSheet(import_rule:
RawServoImportRuleBorrowed)
-> RawServoStyleSheetStrong {
let import_rule = RwLock::<ImportRule>::as_arc(&import_rule);
unsafe { mem::transmute(import_rule.read().stylesheet.clone()) }
}
#[no_mangle]
pub extern "C" fn Servo_TakeChangeHint(element: RawGeckoElementBorrowed) -> nsChangeHint
{
let element = GeckoElement(element);
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 {
error!("Trying to get change hint from unstyled element");
GeckoRestyleDamage::empty()
};
debug!("Servo_TakeChangeHint: {:?}, damage={:?}", element, damage);
damage.as_change_hint()
}
#[no_mangle]
pub extern "C" fn Servo_ResolveStyle(element: RawGeckoElementBorrowed,
raw_data: RawServoStyleSetBorrowed)
-> ServoComputedValuesStrong
{
let element = GeckoElement(element);
debug!("Servo_ResolveStyle: {:?}", element);
let data = unsafe { element.ensure_data() }.borrow_mut();
servo: Merge #14436 - Make restyle tracking more granular (from bholley:granular_restyle); r=emilio The primary idea of this patch is to ditch the rigid enum of Previous/Current styles, and replace it with a series of indicators for the various types of work that needs to be performed (expanding snapshots, rematching, recascading, and damage processing). This loses us a little bit of sanity checking (since the up-to-date-ness of our style is no longer baked into the type system), but gives us a lot more flexibility that we'll need going forward (especially when we separate matching from cascading). We also eliminate get_styling_mode in favor of a method on the traversal. This patch does a few other things as ridealongs: * Temporarily eliminates the handling for transfering ownership of styles to the frame. We'll need this again at some point, but for now it's causing too much complexity for a half-implemented feature. * Ditches TRestyleDamage, which is no longer necessary post-crate-merge, and is a constant source of compilation failures from either needing to be imported or being unnecessarily imported (which varies between gecko and servo). * Expands Snapshots for the traversal root, which was missing before. * Fixes up the skip_root stuff to avoid visiting the skipped root. * Unifies parallel traversal and avoids spawning for a single work item. * Adds an explicit pre_traverse step do any pre-processing and determine whether we need to traverse at all. Source-Repo: https://github.com/servo/servo Source-Revision: b9a8ccd775c3192e3810a1730b1d0bc2b5c9dfb6
2016-12-10 01:01:05 +00:00
if !data.has_current_styles() {
error!("Resolving style on unstyled element with lazy computation forbidden.");
let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
return per_doc_data.default_computed_values().clone().into_strong();
servo: Merge #14436 - Make restyle tracking more granular (from bholley:granular_restyle); r=emilio The primary idea of this patch is to ditch the rigid enum of Previous/Current styles, and replace it with a series of indicators for the various types of work that needs to be performed (expanding snapshots, rematching, recascading, and damage processing). This loses us a little bit of sanity checking (since the up-to-date-ness of our style is no longer baked into the type system), but gives us a lot more flexibility that we'll need going forward (especially when we separate matching from cascading). We also eliminate get_styling_mode in favor of a method on the traversal. This patch does a few other things as ridealongs: * Temporarily eliminates the handling for transfering ownership of styles to the frame. We'll need this again at some point, but for now it's causing too much complexity for a half-implemented feature. * Ditches TRestyleDamage, which is no longer necessary post-crate-merge, and is a constant source of compilation failures from either needing to be imported or being unnecessarily imported (which varies between gecko and servo). * Expands Snapshots for the traversal root, which was missing before. * Fixes up the skip_root stuff to avoid visiting the skipped root. * Unifies parallel traversal and avoids spawning for a single work item. * Adds an explicit pre_traverse step do any pre-processing and determine whether we need to traverse at all. Source-Repo: https://github.com/servo/servo Source-Revision: b9a8ccd775c3192e3810a1730b1d0bc2b5c9dfb6
2016-12-10 01:01:05 +00:00
}
data.styles().primary.values.clone().into_strong()
}
servo: Merge #12469 - style: Rewrite the restyle hints code to allow different kinds of element snapshots (from emilio:stylo); r=bholley <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because refactoring. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> This is a rewrite for how style interfaces with its consumers in order to allow different representations for an element snapshot. This also changes the requirements of an element snapshot, requiring them to only implement MatchAttr, instead of MatchAttrGeneric. This is important for stylo since implementing MatchAttrGeneric is way more difficult for us given the atom limitations. This also allows for more performant implementations in the Gecko side of things. I don't want to get this merged just yet, mainly because the stylo part is not implemented, but I'd like early feedback from @bholley and/or @heycam: How do you see this approach? I don't think we'll have much problem to implement MatchAttr for our element snapshots, but... worth checking. r? @heycam Source-Repo: https://github.com/servo/servo Source-Revision: 1e0321f7dde5f33f7d26bbd4f088622fa3660477
2016-07-21 21:54:34 +00: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()
}
#[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);
}
}
}
servo: Merge #12469 - style: Rewrite the restyle hints code to allow different kinds of element snapshots (from emilio:stylo); r=bholley <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because refactoring. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> This is a rewrite for how style interfaces with its consumers in order to allow different representations for an element snapshot. This also changes the requirements of an element snapshot, requiring them to only implement MatchAttr, instead of MatchAttrGeneric. This is important for stylo since implementing MatchAttrGeneric is way more difficult for us given the atom limitations. This also allows for more performant implementations in the Gecko side of things. I don't want to get this merged just yet, mainly because the stylo part is not implemented, but I'd like early feedback from @bholley and/or @heycam: How do you see this approach? I don't think we'll have much problem to implement MatchAttr for our element snapshots, but... worth checking. r? @heycam Source-Repo: https://github.com/servo/servo Source-Revision: 1e0321f7dde5f33f7d26bbd4f088622fa3660477
2016-07-21 21:54:34 +00:00
assert_subtree_is_clean(root);
servo: Merge #12469 - style: Rewrite the restyle hints code to allow different kinds of element snapshots (from emilio:stylo); r=bholley <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] These changes do not require tests because refactoring. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> This is a rewrite for how style interfaces with its consumers in order to allow different representations for an element snapshot. This also changes the requirements of an element snapshot, requiring them to only implement MatchAttr, instead of MatchAttrGeneric. This is important for stylo since implementing MatchAttrGeneric is way more difficult for us given the atom limitations. This also allows for more performant implementations in the Gecko side of things. I don't want to get this merged just yet, mainly because the stylo part is not implemented, but I'd like early feedback from @bholley and/or @heycam: How do you see this approach? I don't think we'll have much problem to implement MatchAttr for our element snapshots, but... worth checking. r? @heycam Source-Repo: https://github.com/servo/servo Source-Revision: 1e0321f7dde5f33f7d26bbd4f088622fa3660477
2016-07-21 21:54:34 +00: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
}