--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -83,29 +83,19 @@ ServoRestyleManager::PostRestyleEventFor
{
PostRestyleEventInternal(true);
}
void
ServoRestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
nsRestyleHint aRestyleHint)
{
- NS_WARNING("stylo: ServoRestyleManager::RebuildAllStyleData not implemented");
- // That said, we do know that rebuilding all style data in Gecko would get rid
- // of the old ruletree, and hence of the cached-on-the-root default computed
- // styles. So we know we need to clear them here. I think this is the only
- // way they could get cleared, in fact, though not _all_ calls that come
- // through here may need to clear them in practice.
- //
- // We probably need to do some actual restyling here too, though. And figure
- // out whether it actually matters that we may be recomputing the default
- // styles in too many cases. For one thing, we do a bunch of eager work here,
- // whereas we should really just set a bit that says to recompute the default
- // computed styles before the next time we restyle anything!
- StyleSet()->RecomputeDefaultComputedStyles();
+ // TODO(emilio, bz): We probably need to do some actual restyling here too.
+ NS_WARNING("stylo: ServoRestyleManager::RebuildAllStyleData is incomplete");
+ StyleSet()->RebuildData();
}
void
ServoRestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
nsRestyleHint aRestyleHint)
{
NS_WARNING("stylo: ServoRestyleManager::PostRebuildAllStyleDataEvent not implemented");
}
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -45,20 +45,19 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_Clea
const nsACString* data,
ThreadSafeURIHolder* base,
ThreadSafeURIHolder* referrer,
ThreadSafePrincipalHolder* principal)
SERVO_BINDING_FUNC(Servo_StyleSheet_HasRules, bool,
RawServoStyleSheetBorrowed sheet)
SERVO_BINDING_FUNC(Servo_StyleSheet_GetRules, ServoCssRulesStrong,
RawServoStyleSheetBorrowed sheet)
-SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned, RawGeckoPresContextBorrowed pres_context)
-SERVO_BINDING_FUNC(Servo_StyleSet_RecomputeDefaultStyles, void,
- RawServoStyleSetBorrowed set,
- RawGeckoPresContextBorrowed pres_context)
+SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned, RawGeckoPresContextOwned pres_context)
+SERVO_BINDING_FUNC(Servo_StyleSet_RebuildData, void,
+ RawServoStyleSetBorrowed set)
SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet, bool flush)
SERVO_BINDING_FUNC(Servo_StyleSet_PrependStyleSheet, void,
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet, bool flush)
SERVO_BINDING_FUNC(Servo_StyleSet_RemoveStyleSheet, void,
RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet, bool flush)
SERVO_BINDING_FUNC(Servo_StyleSet_InsertStyleSheetBefore, void,
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -97,16 +97,17 @@ DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawG
DECL_BORROWED_REF_TYPE_FOR(RawGeckoElement)
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoElement)
DECL_BORROWED_REF_TYPE_FOR(RawGeckoDocument)
DECL_NULLABLE_BORROWED_REF_TYPE_FOR(RawGeckoDocument)
DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChildrenIterator)
DECL_BORROWED_MUT_REF_TYPE_FOR(ServoElementSnapshot)
DECL_BORROWED_REF_TYPE_FOR(nsCSSValue)
DECL_BORROWED_MUT_REF_TYPE_FOR(nsCSSValue)
+DECL_OWNED_REF_TYPE_FOR(RawGeckoPresContext)
DECL_BORROWED_REF_TYPE_FOR(RawGeckoPresContext)
#undef DECL_ARC_REF_TYPE_FOR
#undef DECL_OWNED_REF_TYPE_FOR
#undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
#undef DECL_BORROWED_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
#undef DECL_BORROWED_MUT_REF_TYPE_FOR
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -544,19 +544,19 @@ ServoStyleSet::AssertTreeIsClean()
DocumentStyleRootIterator iter(mPresContext->Document());
while (Element* root = iter.GetNextStyleRoot()) {
Servo_AssertTreeIsClean(root);
}
}
#endif
void
-ServoStyleSet::RecomputeDefaultComputedStyles()
+ServoStyleSet::RebuildData()
{
- Servo_StyleSet_RecomputeDefaultStyles(mRawSet.get(), mPresContext);
+ Servo_StyleSet_RebuildData(mRawSet.get());
}
ServoComputedValuesStrong
ServoStyleSet::RestyleWithAddedDeclaration(RawServoDeclarationBlock* aDeclarations,
const ServoComputedValues* aPreviousStyle)
{
return Servo_RestyleWithAddedDeclaration(mRawSet.get(), aDeclarations,
aPreviousStyle);
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -156,20 +156,20 @@ public:
#ifdef DEBUG
void AssertTreeIsClean();
#else
void AssertTreeIsClean() {}
#endif
/**
- * Recompute our default computed styles. This will eagerly create a new set
- * of default computed style structs.
+ * Rebuild the style data. This will force a stylesheet flush, and also
+ * recompute the default computed styles.
*/
- void RecomputeDefaultComputedStyles();
+ void RebuildData();
/**
* Resolve style for the given element, and return it as a
* ServoComputedValues, not an nsStyleContext.
*/
already_AddRefed<ServoComputedValues> ResolveServoStyle(dom::Element* aElement);
/**
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -479,16 +479,17 @@ mod bindings {
.raw_line("type nsAString_internal = nsAString;")
.whitelisted_function("Servo_.*")
.whitelisted_function("Gecko_.*");
let structs_types = [
"RawGeckoDocument",
"RawGeckoElement",
"RawGeckoNode",
"RawGeckoPresContext",
+ "RawGeckoPresContextOwned",
"ThreadSafeURIHolder",
"ThreadSafePrincipalHolder",
"CSSPseudoClassType",
"TraversalRootBehavior",
"FontFamilyList",
"FontFamilyType",
"ServoElementSnapshot",
"SheetParsingMode",
--- a/servo/components/style/gecko/data.rs
+++ b/servo/components/style/gecko/data.rs
@@ -2,46 +2,47 @@
* 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/. */
//! Data needed to style a Gecko document.
use animation::Animation;
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use dom::OpaqueNode;
-use euclid::size::TypedSize2D;
-use gecko_bindings::bindings::RawGeckoPresContextBorrowed;
use gecko_bindings::bindings::RawServoStyleSet;
+use gecko_bindings::structs::RawGeckoPresContextOwned;
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
-use media_queries::{Device, MediaType};
+use media_queries::Device;
use num_cpus;
use parking_lot::RwLock;
use properties::ComputedValues;
use rayon;
use std::cmp;
use std::collections::HashMap;
use std::env;
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender, channel};
-use style_traits::ViewportPx;
use stylesheets::Stylesheet;
use stylist::Stylist;
/// The container for data that a Servo-backed Gecko document needs to style
/// itself.
pub struct PerDocumentStyleDataImpl {
/// Rule processor.
pub stylist: Arc<Stylist>,
/// List of stylesheets, mirrored from Gecko.
pub stylesheets: Vec<Arc<Stylesheet>>,
/// Whether the stylesheets list above has changed since the last restyle.
pub stylesheets_changed: bool,
+ /// Whether the device has changed since the last restyle.
+ pub device_changed: bool,
+
// FIXME(bholley): Hook these up to something.
/// Unused. Will go away when we actually implement transitions and
/// animations properly.
pub new_animations_sender: Sender<Animation>,
/// Unused. Will go away when we actually implement transitions and
/// animations properly.
pub new_animations_receiver: Receiver<Animation>,
/// Unused. Will go away when we actually implement transitions and
@@ -52,19 +53,16 @@ pub struct PerDocumentStyleDataImpl {
pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
/// The worker thread pool.
/// FIXME(bholley): This shouldn't be per-document.
pub work_queue: Option<rayon::ThreadPool>,
/// The number of threads of the work queue.
pub num_threads: usize,
-
- /// Default computed values for this document.
- pub default_computed_values: Arc<ComputedValues>
}
/// The data itself is an `AtomicRefCell`, which guarantees the proper semantics
/// and unexpected races while trying to mutate it.
pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
lazy_static! {
/// The number of layout threads, computed statically.
@@ -73,71 +71,80 @@ lazy_static! {
Ok(num) => num,
_ => cmp::max(num_cpus::get() * 3 / 4, 1),
}
};
}
impl PerDocumentStyleData {
/// Create a dummy `PerDocumentStyleData`.
- pub fn new(pres_context: RawGeckoPresContextBorrowed) -> Self {
- // FIXME(bholley): Real window size.
- let window_size: TypedSize2D<f32, ViewportPx> = TypedSize2D::new(800.0, 600.0);
- let default_computed_values = ComputedValues::default_values(pres_context);
-
- // FIXME(bz): We're going to need to either update the computed values
- // in the Stylist's Device or give the Stylist a new Device when our
- // default_computed_values changes.
- let device = Device::new(MediaType::Screen, window_size, &default_computed_values);
+ pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
+ let device = Device::new(pres_context);
let (new_anims_sender, new_anims_receiver) = channel();
PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
stylist: Arc::new(Stylist::new(device)),
stylesheets: vec![],
stylesheets_changed: true,
+ device_changed: true,
new_animations_sender: new_anims_sender,
new_animations_receiver: new_anims_receiver,
running_animations: Arc::new(RwLock::new(HashMap::new())),
expired_animations: Arc::new(RwLock::new(HashMap::new())),
work_queue: if *NUM_THREADS <= 1 {
None
} else {
let configuration =
rayon::Configuration::new().set_num_threads(*NUM_THREADS);
rayon::ThreadPool::new(configuration).ok()
},
num_threads: *NUM_THREADS,
- default_computed_values: default_computed_values,
}))
}
/// Get an immutable reference to this style data.
pub fn borrow(&self) -> AtomicRef<PerDocumentStyleDataImpl> {
self.0.borrow()
}
/// Get an mutable reference to this style data.
pub fn borrow_mut(&self) -> AtomicRefMut<PerDocumentStyleDataImpl> {
self.0.borrow_mut()
}
+
}
impl PerDocumentStyleDataImpl {
/// Recreate the style data if the stylesheets have changed.
pub fn flush_stylesheets(&mut self) {
- // The stylist wants to be flushed if either the stylesheets change or the
- // device dimensions change. When we add support for media queries, we'll
- // need to detect the latter case and trigger a flush as well.
+ let mut stylist = if self.device_changed || self.stylesheets_changed {
+ Some(Arc::get_mut(&mut self.stylist).unwrap())
+ } else {
+ None
+ };
+
+ if self.device_changed {
+ Arc::get_mut(&mut stylist.as_mut().unwrap().device).unwrap().reset();
+ self.device_changed = false;
+ // Force a stylesheet flush if the device has changed.
+ self.stylesheets_changed = true;
+ }
+
if self.stylesheets_changed {
- let _ = Arc::get_mut(&mut self.stylist).unwrap()
- .update(&self.stylesheets, None, true);
+ let _ = stylist.unwrap().update(&self.stylesheets, None, true);
self.stylesheets_changed = false;
}
}
+
+ /// Get the default computed values for this document.
+ pub fn default_computed_values(&self) -> &Arc<ComputedValues> {
+ debug_assert!(!self.device_changed, "A device flush was pending");
+ self.stylist.device.default_values_arc()
+ }
}
unsafe impl HasFFI for PerDocumentStyleData {
type FFIType = RawServoStyleSet;
}
unsafe impl HasSimpleFFI for PerDocumentStyleData {}
unsafe impl HasBoxFFI for PerDocumentStyleData {}
new file mode 100644
--- /dev/null
+++ b/servo/components/style/gecko/media_queries.rs
@@ -0,0 +1,358 @@
+/* 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/. */
+
+//! Gecko's media-query device and expression representation.
+
+use app_units::Au;
+use cssparser::{Parser, Token};
+use euclid::Size2D;
+use gecko_bindings::structs::{nsMediaExpression_Range, nsMediaFeature};
+use gecko_bindings::structs::{nsMediaFeature_ValueType, nsMediaFeature_RangeType, nsMediaFeature_RequirementFlags};
+use gecko_bindings::structs::RawGeckoPresContextOwned;
+use gecko_bindings::bindings;
+use media_queries::MediaType;
+use properties::ComputedValues;
+use std::ascii::AsciiExt;
+use std::fmt;
+use std::sync::Arc;
+use string_cache::Atom;
+use style_traits::ToCss;
+use style_traits::viewport::ViewportConstraints;
+use values::{CSSFloat, specified};
+
+/// The `Device` in Gecko wraps a pres context, has a default values computed,
+/// and contains all the viewport rule state.
+pub struct Device {
+ /// NB: The pres context lifetime is tied to the styleset, who owns the
+ /// stylist, and thus the `Device`, so having a raw pres context pointer
+ /// here is fine.
+ pres_context: RawGeckoPresContextOwned,
+ default_values: Arc<ComputedValues>,
+ viewport_override: Option<ViewportConstraints>,
+}
+
+impl Device {
+ /// Trivially constructs a new `Device`.
+ pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
+ assert!(!pres_context.is_null());
+ Device {
+ pres_context: pres_context,
+ default_values: ComputedValues::default_values(unsafe { &*pres_context }),
+ viewport_override: None,
+ }
+ }
+
+ /// Tells the device that a new viewport rule has been found, and stores the
+ /// relevant viewport constraints.
+ pub fn account_for_viewport_rule(&mut self,
+ constraints: &ViewportConstraints) {
+ self.viewport_override = Some(constraints.clone());
+ }
+
+ /// Returns the default computed values as a reference, in order to match
+ /// Servo.
+ pub fn default_values(&self) -> &ComputedValues {
+ &*self.default_values
+ }
+
+ /// Returns the default computed values as an `Arc`, in order to avoid
+ /// clones.
+ pub fn default_values_arc(&self) -> &Arc<ComputedValues> {
+ &self.default_values
+ }
+
+ /// Recreates all the temporary state that the `Device` stores.
+ ///
+ /// This includes the viewport override from `@viewport` rules, and also the
+ /// default computed values.
+ pub fn reset(&mut self) {
+ // NB: A following stylesheet flush will populate this if appropriate.
+ self.viewport_override = None;
+ self.default_values = ComputedValues::default_values(unsafe { &*self.pres_context });
+ }
+
+ /// Returns the current media type of the device.
+ pub fn media_type(&self) -> MediaType {
+ // TODO
+ MediaType::Screen
+ }
+
+ /// Returns the current viewport size in app units.
+ pub fn au_viewport_size(&self) -> Size2D<Au> {
+ self.viewport_override.as_ref().map(|v| {
+ Size2D::new(Au::from_f32_px(v.size.width),
+ Au::from_f32_px(v.size.height))
+ }).unwrap_or_else(|| {
+ // TODO(emilio): Grab from pres context.
+ Size2D::new(Au(0), Au(0))
+ })
+ }
+}
+
+unsafe impl Sync for Device {}
+unsafe impl Send for Device {}
+
+/// A expression for gecko contains a reference to the media feature, the value
+/// the media query contained, and the range to evaluate.
+#[derive(Debug, Clone)]
+pub struct Expression {
+ feature: &'static nsMediaFeature,
+ value: MediaExpressionValue,
+ range: nsMediaExpression_Range
+}
+
+impl ToCss for Expression {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where W: fmt::Write,
+ {
+ dest.write_str("(")?;
+ match self.range {
+ nsMediaExpression_Range::eMin => dest.write_str("min-")?,
+ nsMediaExpression_Range::eMax => dest.write_str("max-")?,
+ nsMediaExpression_Range::eEqual => {},
+ }
+ // NB: CSSStringWriter not needed, features are under control.
+ write!(dest, "{}", Atom::from(unsafe { *self.feature.mName }))?;
+ dest.write_str(": ")?;
+
+ self.value.to_css(dest)?;
+ dest.write_str(")")
+ }
+}
+
+/// A resolution.
+#[derive(Debug, Clone)]
+pub enum Resolution {
+ /// Dots per inch.
+ Dpi(CSSFloat),
+ /// Dots per pixel.
+ Dppx(CSSFloat),
+ /// Dots per centimeter.
+ Dpcm(CSSFloat),
+}
+
+impl Resolution {
+ fn parse(input: &mut Parser) -> Result<Self, ()> {
+ let (value, unit) = match try!(input.next()) {
+ Token::Dimension(value, unit) => {
+ (value.value, unit)
+ },
+ _ => return Err(()),
+ };
+
+ Ok(match_ignore_ascii_case! { unit,
+ "dpi" => Resolution::Dpi(value),
+ "dppx" => Resolution::Dppx(value),
+ "dpcm" => Resolution::Dpcm(value),
+ _ => return Err(())
+ })
+ }
+}
+
+impl ToCss for Resolution {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where W: fmt::Write,
+ {
+ match *self {
+ Resolution::Dpi(v) => write!(dest, "{}dpi", v),
+ Resolution::Dppx(v) => write!(dest, "{}dppx", v),
+ Resolution::Dpcm(v) => write!(dest, "{}dpcm", v),
+ }
+ }
+}
+
+/// A value found or expected in a media expression.
+#[derive(Debug, Clone)]
+pub enum MediaExpressionValue {
+ /// A length.
+ Length(specified::Length),
+ /// A (non-negative) integer.
+ Integer(u32),
+ /// A floating point value.
+ Float(CSSFloat),
+ /// A boolean value, specified as an integer (i.e., either 0 or 1).
+ BoolInteger(bool),
+ /// Two integers separated by '/', with optional whitespace on either side
+ /// of the '/'.
+ IntRatio(u32, u32),
+ /// A resolution.
+ Resolution(Resolution),
+ /// An enumerated index into the variant keyword table.
+ Enumerated(u32),
+ /// An identifier.
+ Ident(Atom),
+}
+
+impl ToCss for MediaExpressionValue {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result
+ where W: fmt::Write,
+ {
+ match *self {
+ MediaExpressionValue::Length(ref l) => l.to_css(dest),
+ MediaExpressionValue::Integer(v) => write!(dest, "{}", v),
+ MediaExpressionValue::Float(v) => write!(dest, "{}", v),
+ MediaExpressionValue::BoolInteger(v) => {
+ dest.write_str(if v { "1" } else { "0" })
+ },
+ MediaExpressionValue::IntRatio(a, b) => {
+ write!(dest, "{}/{}", a, b)
+ },
+ MediaExpressionValue::Resolution(ref r) => r.to_css(dest),
+ MediaExpressionValue::Enumerated(..) |
+ MediaExpressionValue::Ident(..) => {
+ // TODO(emilio)
+ unimplemented!()
+ }
+ }
+ }
+}
+
+fn starts_with_ignore_ascii_case(string: &str, prefix: &str) -> bool {
+ string.len() > prefix.len() &&
+ string[0..prefix.len()].eq_ignore_ascii_case(prefix)
+}
+
+#[allow(warnings)]
+fn find_feature<F>(mut f: F) -> Option<&'static nsMediaFeature>
+ where F: FnMut(&'static nsMediaFeature) -> bool,
+{
+ // FIXME(emilio): With build-time bindgen, we would be able to use
+ // structs::nsMediaFeatures_features. That would unfortunately break MSVC
+ // builds, or require one bindings file per platform.
+ //
+ // I'm not into any of those, so meanwhile let's use a FFI function.
+ unsafe {
+ let mut features = bindings::Gecko_GetMediaFeatures();
+ while !(*features).mName.is_null() {
+ if f(&*features) {
+ return Some(&*features);
+ }
+ features = features.offset(1);
+ }
+ }
+
+ None
+}
+
+impl Expression {
+ /// Trivially construct a new expression.
+ fn new(feature: &'static nsMediaFeature,
+ value: MediaExpressionValue,
+ range: nsMediaExpression_Range) -> Self {
+ Expression {
+ feature: feature,
+ value: value,
+ range: range,
+ }
+ }
+
+ /// Parse a media expression of the form:
+ ///
+ /// ```
+ /// (media-feature: media-value)
+ /// ```
+ #[allow(warnings)]
+ pub fn parse(input: &mut Parser) -> Result<Self, ()> {
+ try!(input.expect_parenthesis_block());
+ input.parse_nested_block(|input| {
+ let ident = try!(input.expect_ident());
+ try!(input.expect_colon());
+
+ let mut flags = 0;
+ let mut feature_name = &*ident;
+
+ // TODO(emilio): this is under a pref in Gecko.
+ if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
+ feature_name = &feature_name[8..];
+ flags |= nsMediaFeature_RequirementFlags::eHasWebkitPrefix as u8;
+ }
+
+ let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
+ feature_name = &feature_name[4..];
+ nsMediaExpression_Range::eMin
+ } else if starts_with_ignore_ascii_case(feature_name, "max-") {
+ feature_name = &feature_name[4..];
+ nsMediaExpression_Range::eMax
+ } else {
+ nsMediaExpression_Range::eEqual
+ };
+
+ let atom = Atom::from(feature_name);
+ let feature =
+ match find_feature(|f| atom.as_ptr() == unsafe { *f.mName }) {
+ Some(f) => f,
+ None => return Err(()),
+ };
+
+ if (feature.mReqFlags & !flags) != 0 {
+ return Err(());
+ }
+
+ if range != nsMediaExpression_Range::eEqual &&
+ feature.mRangeType != nsMediaFeature_RangeType::eMinMaxAllowed {
+ return Err(());
+ }
+
+ let value = match feature.mValueType {
+ nsMediaFeature_ValueType::eLength => {
+ MediaExpressionValue::Length(
+ specified::Length::parse_non_negative(input)?)
+ },
+ nsMediaFeature_ValueType::eInteger => {
+ let i = input.expect_integer()?;
+ if i < 0 {
+ return Err(())
+ }
+ MediaExpressionValue::Integer(i as u32)
+ }
+ nsMediaFeature_ValueType::eBoolInteger => {
+ let i = input.expect_integer()?;
+ if i < 0 || i > 1 {
+ return Err(())
+ }
+ MediaExpressionValue::BoolInteger(i == 1)
+ }
+ nsMediaFeature_ValueType::eFloat => {
+ MediaExpressionValue::Float(input.expect_number()?)
+ }
+ nsMediaFeature_ValueType::eIntRatio => {
+ let a = input.expect_integer()?;
+ if a <= 0 {
+ return Err(())
+ }
+
+ input.expect_delim('/')?;
+
+ let b = input.expect_integer()?;
+ if b <= 0 {
+ return Err(())
+ }
+ MediaExpressionValue::IntRatio(a as u32, b as u32)
+ }
+ nsMediaFeature_ValueType::eResolution => {
+ MediaExpressionValue::Resolution(Resolution::parse(input)?)
+ }
+ nsMediaFeature_ValueType::eEnumerated => {
+ let index = unsafe {
+ let _table = feature.mData.mKeywordTable.as_ref();
+ 0
+ };
+ MediaExpressionValue::Enumerated(index)
+ }
+ nsMediaFeature_ValueType::eIdent => {
+ MediaExpressionValue::Ident(input.expect_ident()?.into())
+ }
+ };
+
+ Ok(Expression::new(feature, value, range))
+ })
+ }
+
+ /// Returns whether this media query evaluates to true for the given
+ /// device.
+ pub fn matches(&self, _device: &Device) -> bool {
+ // TODO
+ false
+ }
+}
--- a/servo/components/style/gecko/mod.rs
+++ b/servo/components/style/gecko/mod.rs
@@ -1,21 +1,16 @@
/* 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/. */
//! Gecko-specific style-system bits.
pub mod conversions;
pub mod data;
-
-// TODO(emilio): Implement Gecko media query parsing and evaluation using
-// nsMediaFeatures.
-#[path = "../servo/media_queries.rs"]
pub mod media_queries;
-
pub mod restyle_damage;
pub mod selector_parser;
pub mod snapshot;
pub mod snapshot_helpers;
pub mod traversal;
pub mod values;
pub mod wrapper;
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -2,16 +2,17 @@
pub use nsstring::{nsACString, nsAString};
type nsACString_internal = nsACString;
type nsAString_internal = nsAString;
use gecko_bindings::structs::RawGeckoDocument;
use gecko_bindings::structs::RawGeckoElement;
use gecko_bindings::structs::RawGeckoNode;
use gecko_bindings::structs::RawGeckoPresContext;
+use gecko_bindings::structs::RawGeckoPresContextOwned;
use gecko_bindings::structs::ThreadSafeURIHolder;
use gecko_bindings::structs::ThreadSafePrincipalHolder;
use gecko_bindings::structs::CSSPseudoClassType;
use gecko_bindings::structs::TraversalRootBehavior;
use gecko_bindings::structs::FontFamilyList;
use gecko_bindings::structs::FontFamilyType;
use gecko_bindings::structs::ServoElementSnapshot;
use gecko_bindings::structs::SheetParsingMode;
@@ -1095,24 +1096,21 @@ extern "C" {
pub fn Servo_StyleSheet_HasRules(sheet: RawServoStyleSheetBorrowed)
-> bool;
}
extern "C" {
pub fn Servo_StyleSheet_GetRules(sheet: RawServoStyleSheetBorrowed)
-> ServoCssRulesStrong;
}
extern "C" {
- pub fn Servo_StyleSet_Init(pres_context: RawGeckoPresContextBorrowed)
+ pub fn Servo_StyleSet_Init(pres_context: RawGeckoPresContextOwned)
-> RawServoStyleSetOwned;
}
extern "C" {
- pub fn Servo_StyleSet_RecomputeDefaultStyles(set:
- RawServoStyleSetBorrowed,
- pres_context:
- RawGeckoPresContextBorrowed);
+ pub fn Servo_StyleSet_RebuildData(set: RawServoStyleSetBorrowed);
}
extern "C" {
pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowed,
sheet: RawServoStyleSheetBorrowed,
flush: bool);
}
extern "C" {
pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowed,
--- a/servo/components/style/gecko_bindings/structs_debug.rs
+++ b/servo/components/style/gecko_bindings/structs_debug.rs
@@ -12858,17 +12858,19 @@ pub mod root {
pub type RawGeckoDocument = root::nsIDocument;
pub type RawGeckoPresContext = [u64; 162usize];
pub type RawGeckoNodeBorrowed = *const root::RawGeckoNode;
pub type RawGeckoNodeBorrowedOrNull = *const root::RawGeckoNode;
pub type RawGeckoElementBorrowed = *const root::RawGeckoElement;
pub type RawGeckoElementBorrowedOrNull = *const root::RawGeckoElement;
pub type RawGeckoDocumentBorrowed = *const root::RawGeckoDocument;
pub type RawGeckoDocumentBorrowedOrNull = *const root::RawGeckoDocument;
+ pub type RawGeckoPresContextOwned = *mut [u64; 162usize];
pub type RawGeckoPresContextBorrowed = *const [u64; 162usize];
+ pub type RawGeckoPresContextBorrowedMut = *mut [u64; 162usize];
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCSSTokenSerializationType {
eCSSTokenSerialization_Nothing = 0,
eCSSTokenSerialization_Whitespace = 1,
eCSSTokenSerialization_AtKeyword_or_Hash = 2,
eCSSTokenSerialization_Number = 3,
eCSSTokenSerialization_Dimension = 4,
@@ -14304,19 +14306,16 @@ pub mod root {
/**
* <div rustbindgen replaces="nsTArray"></div>
*/
#[repr(C)]
#[derive(Debug)]
pub struct nsTArray<T> {
pub mBuffer: *mut T,
}
- pub type ThreadSafePrincipalHolder =
- root::nsMainThreadPtrHolder<root::nsIPrincipal>;
- pub type ThreadSafeURIHolder = root::nsMainThreadPtrHolder<root::nsIURI>;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsMediaFeature {
pub mName: *mut *mut root::nsIAtom,
pub mRangeType: root::nsMediaFeature_RangeType,
pub mValueType: root::nsMediaFeature_ValueType,
pub mReqFlags: u8,
pub mData: root::nsMediaFeature__bindgen_ty_1,
@@ -14368,16 +14367,19 @@ pub mod root {
#[test]
fn bindgen_test_layout_nsMediaFeature() {
assert_eq!(::std::mem::size_of::<nsMediaFeature>() , 40usize);
assert_eq!(::std::mem::align_of::<nsMediaFeature>() , 8usize);
}
impl Clone for nsMediaFeature {
fn clone(&self) -> Self { *self }
}
+ pub type ThreadSafePrincipalHolder =
+ root::nsMainThreadPtrHolder<root::nsIPrincipal>;
+ pub type ThreadSafeURIHolder = root::nsMainThreadPtrHolder<root::nsIURI>;
pub type nsMediaFeatureValueGetter =
::std::option::Option<unsafe extern "C" fn(aPresContext:
*mut root::nsPresContext,
aFeature:
*const root::nsMediaFeature,
aResult:
*mut root::nsCSSValue)
-> root::nsresult>;
--- a/servo/components/style/gecko_bindings/structs_release.rs
+++ b/servo/components/style/gecko_bindings/structs_release.rs
@@ -12784,17 +12784,19 @@ pub mod root {
pub type RawGeckoDocument = root::nsIDocument;
pub type RawGeckoPresContext = [u64; 158usize];
pub type RawGeckoNodeBorrowed = *const root::RawGeckoNode;
pub type RawGeckoNodeBorrowedOrNull = *const root::RawGeckoNode;
pub type RawGeckoElementBorrowed = *const root::RawGeckoElement;
pub type RawGeckoElementBorrowedOrNull = *const root::RawGeckoElement;
pub type RawGeckoDocumentBorrowed = *const root::RawGeckoDocument;
pub type RawGeckoDocumentBorrowedOrNull = *const root::RawGeckoDocument;
+ pub type RawGeckoPresContextOwned = *mut [u64; 158usize];
pub type RawGeckoPresContextBorrowed = *const [u64; 158usize];
+ pub type RawGeckoPresContextBorrowedMut = *mut [u64; 158usize];
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCSSTokenSerializationType {
eCSSTokenSerialization_Nothing = 0,
eCSSTokenSerialization_Whitespace = 1,
eCSSTokenSerialization_AtKeyword_or_Hash = 2,
eCSSTokenSerialization_Number = 3,
eCSSTokenSerialization_Dimension = 4,
@@ -14230,19 +14232,16 @@ pub mod root {
/**
* <div rustbindgen replaces="nsTArray"></div>
*/
#[repr(C)]
#[derive(Debug)]
pub struct nsTArray<T> {
pub mBuffer: *mut T,
}
- pub type ThreadSafePrincipalHolder =
- root::nsMainThreadPtrHolder<root::nsIPrincipal>;
- pub type ThreadSafeURIHolder = root::nsMainThreadPtrHolder<root::nsIURI>;
#[repr(C)]
#[derive(Debug, Copy)]
pub struct nsMediaFeature {
pub mName: *mut *mut root::nsIAtom,
pub mRangeType: root::nsMediaFeature_RangeType,
pub mValueType: root::nsMediaFeature_ValueType,
pub mReqFlags: u8,
pub mData: root::nsMediaFeature__bindgen_ty_1,
@@ -14294,16 +14293,19 @@ pub mod root {
#[test]
fn bindgen_test_layout_nsMediaFeature() {
assert_eq!(::std::mem::size_of::<nsMediaFeature>() , 40usize);
assert_eq!(::std::mem::align_of::<nsMediaFeature>() , 8usize);
}
impl Clone for nsMediaFeature {
fn clone(&self) -> Self { *self }
}
+ pub type ThreadSafePrincipalHolder =
+ root::nsMainThreadPtrHolder<root::nsIPrincipal>;
+ pub type ThreadSafeURIHolder = root::nsMainThreadPtrHolder<root::nsIURI>;
pub type nsMediaFeatureValueGetter =
::std::option::Option<unsafe extern "C" fn(aPresContext:
*mut root::nsPresContext,
aFeature:
*const root::nsMediaFeature,
aResult:
*mut root::nsCSSValue)
-> root::nsresult>;
--- a/servo/components/style/media_queries.rs
+++ b/servo/components/style/media_queries.rs
@@ -14,17 +14,17 @@ use std::fmt;
use style_traits::ToCss;
#[cfg(feature = "servo")]
pub use servo::media_queries::{Device, Expression};
#[cfg(feature = "gecko")]
pub use gecko::media_queries::{Device, Expression};
/// A type that encapsulates a media query list.
-#[derive(Debug, PartialEq)]
+#[derive(Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct MediaList {
/// The list of media queries.
pub media_queries: Vec<MediaQuery>
}
impl ToCss for MediaList {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
@@ -61,17 +61,17 @@ impl ToCss for Qualifier {
Qualifier::Only => write!(dest, "only"),
}
}
}
/// A [media query][mq].
///
/// [mq]: https://drafts.csswg.org/mediaqueries/
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct MediaQuery {
/// The qualifier for this query.
pub qualifier: Option<Qualifier>,
/// The media type for this query, that can be known, unknown, or "all".
pub media_type: MediaQueryType,
/// The set of expressions that this media query contains.
pub expressions: Vec<Expression>,
--- a/servo/components/style/servo/media_queries.rs
+++ b/servo/components/style/servo/media_queries.rs
@@ -5,78 +5,49 @@
//! Servo's media-query device and expression representation.
use app_units::Au;
use cssparser::Parser;
use euclid::{Size2D, TypedSize2D};
use media_queries::MediaType;
use properties::ComputedValues;
use std::fmt;
-#[cfg(feature = "gecko")]
-use std::sync::Arc;
use style_traits::{ToCss, ViewportPx};
use style_traits::viewport::ViewportConstraints;
use values::computed::{self, ToComputedValue};
use values::specified;
/// A device is a structure that represents the current media a given document
/// is displayed in.
///
/// This is the struct against which media queries are evaluated.
-#[derive(Debug)]
-#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
+#[derive(Debug, HeapSizeOf)]
pub struct Device {
/// The current media type used by de device.
media_type: MediaType,
/// The current viewport size, in viewport pixels.
viewport_size: TypedSize2D<f32, ViewportPx>,
- /// A set of default computed values for this document.
- ///
- /// This allows handling zoom correctly, among other things. Gecko-only for
- /// now, see #14773.
- #[cfg(feature = "gecko")]
- default_values: Arc<ComputedValues>,
}
impl Device {
/// Trivially construct a new `Device`.
- #[cfg(feature = "servo")]
pub fn new(media_type: MediaType,
viewport_size: TypedSize2D<f32, ViewportPx>)
-> Device {
Device {
media_type: media_type,
viewport_size: viewport_size,
}
}
- /// Trivially construct a new `Device`.
- #[cfg(feature = "gecko")]
- pub fn new(media_type:
- MediaType, viewport_size: TypedSize2D<f32, ViewportPx>,
- default_values: &Arc<ComputedValues>) -> Device {
- Device {
- media_type: media_type,
- viewport_size: viewport_size,
- default_values: default_values.clone(),
- }
- }
-
/// Return the default computed values for this device.
- #[cfg(feature = "servo")]
pub fn default_values(&self) -> &ComputedValues {
ComputedValues::initial_values()
}
- /// Return the default computed values for this device.
- #[cfg(feature = "gecko")]
- pub fn default_values(&self) -> &ComputedValues {
- &*self.default_values
- }
-
/// Returns the viewport size of the current device in app units, needed,
/// among other things, to resolve viewport units.
#[inline]
pub fn au_viewport_size(&self) -> Size2D<Au> {
Size2D::new(Au::from_f32_px(self.viewport_size.width),
Au::from_f32_px(self.viewport_size.height))
}
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -44,16 +44,34 @@ pub use ::fnv::FnvHashMap;
/// depending on the pseudo-element (see `PerPseudoElementSelectorMap`),
/// and stylesheet origin (see the fields of `PerPseudoElementSelectorMap`).
///
/// This structure is effectively created once per pipeline, in the
/// LayoutThread corresponding to that pipeline.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct Stylist {
/// Device that the stylist is currently evaluating against.
+ ///
+ /// This field deserves a bigger comment due to the different use that Gecko
+ /// and Servo give to it (that we should eventually unify).
+ ///
+ /// With Gecko, the device is never changed. Gecko manually tracks whether
+ /// the device data should be reconstructed, and "resets" the state of the
+ /// device.
+ ///
+ /// That's why we need to look for viewport rules on a style update (though
+ /// given new viewport rules may appear, this may have been a previous Servo
+ /// bug).
+ ///
+ /// On Servo, on the other hand, the device is a really cheap representation
+ /// that is recreated each time some constraint changes and calling
+ /// `set_device`.
+ ///
+ /// In both cases, the device is actually _owned_ by the Stylist, and it's
+ /// only an `Arc` so we can implement `add_stylesheet` more idiomatically.
pub device: Arc<Device>,
/// Viewport constraints based on the current device.
viewport_constraints: Option<ViewportConstraints>,
/// If true, the quirks-mode stylesheet is applied.
quirks_mode: bool,
@@ -141,16 +159,28 @@ impl Stylist {
pub fn update(&mut self,
doc_stylesheets: &[Arc<Stylesheet>],
ua_stylesheets: Option<&UserAgentStylesheets>,
stylesheets_changed: bool) -> bool {
if !(self.is_device_dirty || stylesheets_changed) {
return false;
}
+ let cascaded_rule = ViewportRule {
+ declarations: viewport::Cascade::from_stylesheets(doc_stylesheets, &self.device).finish(),
+ };
+
+ self.viewport_constraints =
+ ViewportConstraints::maybe_new(&self.device, &cascaded_rule);
+
+ if let Some(ref constraints) = self.viewport_constraints {
+ Arc::get_mut(&mut self.device).unwrap()
+ .account_for_viewport_rule(constraints);
+ }
+
self.element_map = PerPseudoElementSelectorMap::new();
self.pseudos_map = Default::default();
self.animations = Default::default();
SelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
self.pseudos_map.insert(pseudo, PerPseudoElementSelectorMap::new());
});
self.precomputed_pseudo_element_decls = Default::default();
@@ -389,16 +419,23 @@ impl Stylist {
/// Also, the device that arrives here may need to take the viewport rules
/// into account.
///
/// TODO(emilio): Probably should be unified with `update`, right now I
/// don't think we take into account dynamic updates to viewport rules.
///
/// Probably worth to make the stylist own a single `Device`, and have a
/// `update_device` function?
+ ///
+ /// feature = "servo" because gecko only has one device, and manually tracks
+ /// when the device is dirty.
+ ///
+ /// FIXME(emilio): The semantics of the device for Servo and Gecko are
+ /// different enough we may want to unify them.
+ #[cfg(feature = "servo")]
pub fn set_device(&mut self, mut device: Device, stylesheets: &[Arc<Stylesheet>]) {
let cascaded_rule = ViewportRule {
declarations: viewport::Cascade::from_stylesheets(stylesheets, &device).finish(),
};
self.viewport_constraints =
ViewportConstraints::maybe_new(&device, &cascaded_rule);
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -31,25 +31,25 @@ use style::gecko::wrapper::GeckoElement;
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
use style::gecko_bindings::bindings::{RawServoStyleRuleBorrowed, RawServoStyleRuleStrong};
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, nsAString};
use style::gecko_bindings::bindings::RawGeckoElementBorrowed;
-use style::gecko_bindings::bindings::RawGeckoPresContextBorrowed;
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::ServoStyleSheet;
use style::gecko_bindings::structs::nsresult;
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::parallel;
use style::parser::{ParserContext, ParserContextExtraData};
use style::properties::{CascadeFlags, ComputedValues, Importance, PropertyDeclaration};
@@ -102,17 +102,17 @@ fn create_shared_context(per_doc_data: &
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(),
+ 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() {
@@ -172,17 +172,17 @@ pub extern "C" fn Servo_RestyleWithAdded
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,
+ data.default_computed_values(),
None,
Box::new(StdoutErrorReporter),
None,
CascadeFlags::empty());
Arc::new(computed).into_strong()
}
#[no_mangle]
@@ -518,17 +518,17 @@ pub extern "C" fn Servo_ComputedValues_G
-> ServoComputedValuesStrong {
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
let atom = Atom::from(pseudo_tag);
let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
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)
+ 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)
@@ -539,17 +539,17 @@ pub extern "C" fn Servo_ResolvePseudoSty
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()
+ 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(),
}
@@ -561,61 +561,61 @@ fn get_pseudo_style(element: GeckoElemen
{
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)
+ 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();
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)
+ ComputedValues::inherit_from(reference, &data.default_computed_values())
} else {
- data.default_computed_values.clone()
+ data.default_computed_values().clone()
};
style.into_strong()
}
#[no_mangle]
-pub extern "C" fn Servo_ComputedValues_AddRef(ptr: ServoComputedValuesBorrowed) -> () {
+pub extern "C" fn Servo_ComputedValues_AddRef(ptr: ServoComputedValuesBorrowed) {
unsafe { ComputedValues::addref(ptr) };
}
#[no_mangle]
-pub extern "C" fn Servo_ComputedValues_Release(ptr: ServoComputedValuesBorrowed) -> () {
+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: RawGeckoPresContextBorrowed)
+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_RecomputeDefaultStyles(
- raw_data: RawServoStyleSetBorrowed,
- pres_context: RawGeckoPresContextBorrowed) {
+pub extern "C" fn Servo_StyleSet_RebuildData(raw_data: RawServoStyleSetBorrowed) {
let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
- data.default_computed_values = ComputedValues::default_values(pres_context);
- // FIXME(bz): We need to update our Stylist's Device's computed values, but how?
+ data.device_changed = true;
}
#[no_mangle]
pub extern "C" fn Servo_StyleSet_Drop(data: RawServoStyleSetOwned) -> () {
let _ = data.into_box::<PerDocumentStyleData>();
}
@@ -936,17 +936,17 @@ pub extern "C" fn Servo_ResolveStyle(ele
{
let element = GeckoElement(element);
debug!("Servo_ResolveStyle: {:?}", element);
let data = unsafe { element.ensure_data() }.borrow_mut();
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();
+ return per_doc_data.default_computed_values().clone().into_strong();
}
data.styles().primary.values.clone().into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
pseudo_tag: *mut nsIAtom,