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