style/values/specified/
source_size_list.rs1use crate::media_queries::Device;
8use crate::parser::{Parse, ParserContext};
9use crate::queries::{FeatureType, QueryCondition};
10use crate::values::computed::{self, ToComputedValue};
11use crate::values::specified::{Length, NoCalcLength, ViewportPercentageLength};
12use app_units::Au;
13use cssparser::{Delimiter, Parser, Token};
14use selectors::context::QuirksMode;
15use style_traits::ParseError;
16
17#[derive(Debug)]
21pub struct SourceSize {
22 condition: QueryCondition,
23 value: Length,
24}
25
26impl Parse for SourceSize {
27 fn parse<'i, 't>(
28 context: &ParserContext,
29 input: &mut Parser<'i, 't>,
30 ) -> Result<Self, ParseError<'i>> {
31 let condition = QueryCondition::parse(context, input, FeatureType::Media)?;
32 let value = Length::parse_non_negative(context, input)?;
33 Ok(Self { condition, value })
34 }
35}
36
37#[derive(Debug)]
41pub struct SourceSizeList {
42 source_sizes: Vec<SourceSize>,
43 value: Option<Length>,
44}
45
46impl SourceSizeList {
47 pub fn empty() -> Self {
49 Self {
50 source_sizes: vec![],
51 value: None,
52 }
53 }
54
55 pub fn evaluate(&self, device: &Device, quirks_mode: QuirksMode) -> Au {
57 computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
58 let matching_source_size = self.source_sizes.iter().find(|source_size| {
59 source_size
60 .condition
61 .matches(context)
62 .to_bool(false)
63 });
64
65 match matching_source_size {
66 Some(source_size) => source_size.value.to_computed_value(context),
67 None => match self.value {
68 Some(ref v) => v.to_computed_value(context),
69 None => Length::NoCalc(NoCalcLength::ViewportPercentage(
70 ViewportPercentageLength::Vw(100.),
71 ))
72 .to_computed_value(context),
73 },
74 }
75 })
76 .into()
77 }
78}
79
80enum SourceSizeOrLength {
81 SourceSize(SourceSize),
82 Length(Length),
83}
84
85impl Parse for SourceSizeOrLength {
86 fn parse<'i, 't>(
87 context: &ParserContext,
88 input: &mut Parser<'i, 't>,
89 ) -> Result<Self, ParseError<'i>> {
90 if let Ok(size) = input.try_parse(|input| SourceSize::parse(context, input)) {
91 return Ok(SourceSizeOrLength::SourceSize(size));
92 }
93
94 let length = Length::parse_non_negative(context, input)?;
95 Ok(SourceSizeOrLength::Length(length))
96 }
97}
98
99impl SourceSizeList {
100 pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Self {
104 let mut source_sizes = vec![];
105
106 loop {
107 let result = input.parse_until_before(Delimiter::Comma, |input| {
108 SourceSizeOrLength::parse(context, input)
109 });
110
111 match result {
112 Ok(SourceSizeOrLength::Length(value)) => {
113 return Self {
114 source_sizes,
115 value: Some(value),
116 };
117 },
118 Ok(SourceSizeOrLength::SourceSize(source_size)) => {
119 source_sizes.push(source_size);
120 },
121 Err(..) => {},
122 }
123
124 match input.next() {
125 Ok(&Token::Comma) => {},
126 Err(..) => break,
127 _ => unreachable!(),
128 }
129 }
130
131 SourceSizeList {
132 source_sizes,
133 value: None,
134 }
135 }
136}