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