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(Clone, Debug)]
24pub struct SourceSize {
25 condition: QueryCondition,
26 value: Length,
27}
28
29impl Parse for SourceSize {
30 fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
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(Clone, 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(
62 context,
63 &mut CustomMediaEvaluator::none(),
64 &mut AttributeTracker::new_dummy(),
65 )
66 .to_bool(false)
67 });
68
69 match matching_source_size {
70 Some(source_size) => source_size.value.to_computed_value(context),
71 None => match self.value {
72 Some(ref v) => v.to_computed_value(context),
73 None => Length::new(NoCalcLength::new(LengthUnit::Vw, 100.))
74 .to_computed_value(context),
75 },
76 }
77 })
78 .into()
79 }
80}
81
82enum SourceSizeOrLength {
83 SourceSize(SourceSize),
84 Length(Length),
85}
86
87impl Parse for SourceSizeOrLength {
88 fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
89 if let Ok(size) = input.try_parse(|input| SourceSize::parse(context, input)) {
90 return Ok(SourceSizeOrLength::SourceSize(size));
91 }
92
93 let length = Length::parse_non_negative(context, input)?;
94 Ok(SourceSizeOrLength::Length(length))
95 }
96}
97
98impl SourceSizeList {
99 pub fn parse(context: &ParserContext, input: &mut Parser) -> Self {
103 let mut source_sizes = vec![];
104
105 loop {
106 let result = input.parse_until_before(Delimiter::Comma, |input| {
107 SourceSizeOrLength::parse(context, input)
108 });
109
110 match result {
111 Ok(SourceSizeOrLength::Length(value)) => {
112 return Self {
113 source_sizes,
114 value: Some(value),
115 };
116 },
117 Ok(SourceSizeOrLength::SourceSize(source_size)) => {
118 source_sizes.push(source_size);
119 },
120 Err(..) => {},
121 }
122
123 match input.next() {
124 Ok(&Token::Comma) => {},
125 Err(..) => break,
126 _ => unreachable!(),
127 }
128 }
129
130 SourceSizeList {
131 source_sizes,
132 value: None,
133 }
134 }
135}