summaryrefslogtreecommitdiffstats
path: root/servo/components/style/servo/media_queries.rs
diff options
context:
space:
mode:
Diffstat (limited to 'servo/components/style/servo/media_queries.rs')
-rw-r--r--servo/components/style/servo/media_queries.rs226
1 files changed, 226 insertions, 0 deletions
diff --git a/servo/components/style/servo/media_queries.rs b/servo/components/style/servo/media_queries.rs
new file mode 100644
index 0000000000..83b12f5ff2
--- /dev/null
+++ b/servo/components/style/servo/media_queries.rs
@@ -0,0 +1,226 @@
+/* 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 https://mozilla.org/MPL/2.0/. */
+
+//! Servo's media-query device and expression representation.
+
+use crate::context::QuirksMode;
+use crate::custom_properties::CssEnvironment;
+use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
+use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
+use crate::media_queries::media_feature_expression::RangeOrOperator;
+use crate::media_queries::MediaType;
+use crate::properties::ComputedValues;
+use crate::values::computed::CSSPixelLength;
+use crate::values::specified::font::FONT_MEDIUM_PX;
+use crate::values::KeyframesName;
+use app_units::Au;
+use euclid::default::Size2D as UntypedSize2D;
+use euclid::{Scale, SideOffsets2D, Size2D};
+use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
+use style_traits::{CSSPixel, DevicePixel};
+
+/// 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, MallocSizeOf)]
+pub struct Device {
+ /// The current media type used by de device.
+ media_type: MediaType,
+ /// The current viewport size, in CSS pixels.
+ viewport_size: Size2D<f32, CSSPixel>,
+ /// The current device pixel ratio, from CSS pixels to device pixels.
+ device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
+ /// The current quirks mode.
+ #[ignore_malloc_size_of = "Pure stack type"]
+ quirks_mode: QuirksMode,
+
+ /// The font size of the root element
+ /// This is set when computing the style of the root
+ /// element, and used for rem units in other elements
+ ///
+ /// When computing the style of the root element, there can't be any
+ /// other style being computed at the same time, given we need the style of
+ /// the parent to compute everything else. So it is correct to just use
+ /// a relaxed atomic here.
+ #[ignore_malloc_size_of = "Pure stack type"]
+ root_font_size: AtomicU32,
+ /// Whether any styles computed in the document relied on the root font-size
+ /// by using rem units.
+ #[ignore_malloc_size_of = "Pure stack type"]
+ used_root_font_size: AtomicBool,
+ /// Whether any styles computed in the document relied on the viewport size.
+ #[ignore_malloc_size_of = "Pure stack type"]
+ used_viewport_units: AtomicBool,
+ /// The CssEnvironment object responsible of getting CSS environment
+ /// variables.
+ environment: CssEnvironment,
+}
+
+impl Device {
+ /// Trivially construct a new `Device`.
+ pub fn new(
+ media_type: MediaType,
+ quirks_mode: QuirksMode,
+ viewport_size: Size2D<f32, CSSPixel>,
+ device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
+ ) -> Device {
+ Device {
+ media_type,
+ viewport_size,
+ device_pixel_ratio,
+ quirks_mode,
+ // FIXME(bz): Seems dubious?
+ root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
+ used_root_font_size: AtomicBool::new(false),
+ used_viewport_units: AtomicBool::new(false),
+ environment: CssEnvironment,
+ }
+ }
+
+ /// Get the relevant environment to resolve `env()` functions.
+ #[inline]
+ pub fn environment(&self) -> &CssEnvironment {
+ &self.environment
+ }
+
+ /// Return the default computed values for this device.
+ pub fn default_computed_values(&self) -> &ComputedValues {
+ // FIXME(bz): This isn't really right, but it's no more wrong
+ // than what we used to do. See
+ // https://github.com/servo/servo/issues/14773 for fixing it properly.
+ ComputedValues::initial_values()
+ }
+
+ /// Get the font size of the root element (for rem)
+ pub fn root_font_size(&self) -> CSSPixelLength {
+ self.used_root_font_size.store(true, Ordering::Relaxed);
+ CSSPixelLength::new(f32::from_bits(self.root_font_size.load(Ordering::Relaxed)))
+ }
+
+ /// Set the font size of the root element (for rem)
+ pub fn set_root_font_size(&self, size: CSSPixelLength) {
+ self.root_font_size
+ .store(size.px().to_bits(), Ordering::Relaxed)
+ }
+
+ /// Get the quirks mode of the current device.
+ pub fn quirks_mode(&self) -> QuirksMode {
+ self.quirks_mode
+ }
+
+ /// Sets the body text color for the "inherit color from body" quirk.
+ ///
+ /// <https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk>
+ pub fn set_body_text_color(&self, _color: RGBA) {
+ // Servo doesn't implement this quirk (yet)
+ }
+
+ /// Whether a given animation name may be referenced from style.
+ pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
+ // Assume it is, since we don't have any good way to prove it's not.
+ true
+ }
+
+ /// Returns whether we ever looked up the root font size of the Device.
+ pub fn used_root_font_size(&self) -> bool {
+ self.used_root_font_size.load(Ordering::Relaxed)
+ }
+
+ /// 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) -> UntypedSize2D<Au> {
+ Size2D::new(
+ Au::from_f32_px(self.viewport_size.width),
+ Au::from_f32_px(self.viewport_size.height),
+ )
+ }
+
+ /// Like the above, but records that we've used viewport units.
+ pub fn au_viewport_size_for_viewport_unit_resolution(&self) -> UntypedSize2D<Au> {
+ self.used_viewport_units.store(true, Ordering::Relaxed);
+ self.au_viewport_size()
+ }
+
+ /// Whether viewport units were used since the last device change.
+ pub fn used_viewport_units(&self) -> bool {
+ self.used_viewport_units.load(Ordering::Relaxed)
+ }
+
+ /// Returns the device pixel ratio.
+ pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
+ self.device_pixel_ratio
+ }
+
+ /// Return the media type of the current device.
+ pub fn media_type(&self) -> MediaType {
+ self.media_type.clone()
+ }
+
+ /// Returns whether document colors are enabled.
+ pub fn use_document_colors(&self) -> bool {
+ true
+ }
+
+ /// Returns the default background color.
+ pub fn default_background_color(&self) -> RGBA {
+ RGBA::new(255, 255, 255, 255)
+ }
+
+ /// Returns the default color color.
+ pub fn default_color(&self) -> RGBA {
+ RGBA::new(0, 0, 0, 255)
+ }
+
+ /// Returns safe area insets
+ pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
+ SideOffsets2D::zero()
+ }
+}
+
+/// https://drafts.csswg.org/mediaqueries-4/#width
+fn eval_width(
+ device: &Device,
+ value: Option<CSSPixelLength>,
+ range_or_operator: Option<RangeOrOperator>,
+) -> bool {
+ RangeOrOperator::evaluate(
+ range_or_operator,
+ value.map(Au::from),
+ device.au_viewport_size().width,
+ )
+}
+
+#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)]
+#[repr(u8)]
+enum Scan {
+ Progressive,
+ Interlace,
+}
+
+/// https://drafts.csswg.org/mediaqueries-4/#scan
+fn eval_scan(_: &Device, _: Option<Scan>) -> bool {
+ // Since we doesn't support the 'tv' media type, the 'scan' feature never
+ // matches.
+ false
+}
+
+lazy_static! {
+ /// A list with all the media features that Servo supports.
+ pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 2] = [
+ feature!(
+ atom!("width"),
+ AllowsRanges::Yes,
+ Evaluator::Length(eval_width),
+ ParsingRequirements::empty(),
+ ),
+ feature!(
+ atom!("scan"),
+ AllowsRanges::No,
+ keyword_evaluator!(eval_scan, Scan),
+ ParsingRequirements::empty(),
+ ),
+ ];
+}