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