summaryrefslogtreecommitdiffstats
path: root/servo/components/style/values/specified/source_size_list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'servo/components/style/values/specified/source_size_list.rs')
-rw-r--r--servo/components/style/values/specified/source_size_list.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/servo/components/style/values/specified/source_size_list.rs b/servo/components/style/values/specified/source_size_list.rs
new file mode 100644
index 0000000000..ac47461cc4
--- /dev/null
+++ b/servo/components/style/values/specified/source_size_list.rs
@@ -0,0 +1,136 @@
+/* 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/. */
+
+//! https://html.spec.whatwg.org/multipage/#source-size-list
+
+use crate::media_queries::Device;
+use crate::parser::{Parse, ParserContext};
+use crate::queries::{FeatureType, QueryCondition};
+use crate::values::computed::{self, ToComputedValue};
+use crate::values::specified::{Length, NoCalcLength, ViewportPercentageLength};
+use app_units::Au;
+use cssparser::{Delimiter, Parser, Token};
+use selectors::context::QuirksMode;
+use style_traits::ParseError;
+
+/// A value for a `<source-size>`:
+///
+/// https://html.spec.whatwg.org/multipage/#source-size
+#[derive(Debug)]
+pub struct SourceSize {
+ condition: QueryCondition,
+ value: Length,
+}
+
+impl Parse for SourceSize {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ let condition = QueryCondition::parse(context, input, FeatureType::Media)?;
+ let value = Length::parse_non_negative(context, input)?;
+ Ok(Self { condition, value })
+ }
+}
+
+/// A value for a `<source-size-list>`:
+///
+/// https://html.spec.whatwg.org/multipage/#source-size-list
+#[derive(Debug)]
+pub struct SourceSizeList {
+ source_sizes: Vec<SourceSize>,
+ value: Option<Length>,
+}
+
+impl SourceSizeList {
+ /// Create an empty `SourceSizeList`, which can be used as a fall-back.
+ pub fn empty() -> Self {
+ Self {
+ source_sizes: vec![],
+ value: None,
+ }
+ }
+
+ /// Evaluate this <source-size-list> to get the final viewport length.
+ pub fn evaluate(&self, device: &Device, quirks_mode: QuirksMode) -> Au {
+ computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
+ let matching_source_size = self.source_sizes.iter().find(|source_size| {
+ source_size
+ .condition
+ .matches(context)
+ .to_bool(/* unknown = */ false)
+ });
+
+ match matching_source_size {
+ Some(source_size) => source_size.value.to_computed_value(context),
+ None => match self.value {
+ Some(ref v) => v.to_computed_value(context),
+ None => Length::NoCalc(NoCalcLength::ViewportPercentage(
+ ViewportPercentageLength::Vw(100.),
+ ))
+ .to_computed_value(context),
+ },
+ }
+ })
+ .into()
+ }
+}
+
+enum SourceSizeOrLength {
+ SourceSize(SourceSize),
+ Length(Length),
+}
+
+impl Parse for SourceSizeOrLength {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ if let Ok(size) = input.try_parse(|input| SourceSize::parse(context, input)) {
+ return Ok(SourceSizeOrLength::SourceSize(size));
+ }
+
+ let length = Length::parse_non_negative(context, input)?;
+ Ok(SourceSizeOrLength::Length(length))
+ }
+}
+
+impl SourceSizeList {
+ /// NOTE(emilio): This doesn't match the grammar in the spec, see:
+ ///
+ /// https://html.spec.whatwg.org/multipage/#parsing-a-sizes-attribute
+ pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Self {
+ let mut source_sizes = vec![];
+
+ loop {
+ let result = input.parse_until_before(Delimiter::Comma, |input| {
+ SourceSizeOrLength::parse(context, input)
+ });
+
+ match result {
+ Ok(SourceSizeOrLength::Length(value)) => {
+ return Self {
+ source_sizes,
+ value: Some(value),
+ };
+ },
+ Ok(SourceSizeOrLength::SourceSize(source_size)) => {
+ source_sizes.push(source_size);
+ },
+ Err(..) => {},
+ }
+
+ match input.next() {
+ Ok(&Token::Comma) => {},
+ Err(..) => break,
+ _ => unreachable!(),
+ }
+ }
+
+ SourceSizeList {
+ source_sizes,
+ value: None,
+ }
+ }
+}