blob: 7a59eb3401842d9fa9d19585c580db4058e2b0bd (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/parser/sizes_attribute_parser.h"
#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/parser/sizes_math_function_parser.h"
#include "third_party/blink/renderer/core/media_type_names.h"
namespace blink {
SizesAttributeParser::SizesAttributeParser(MediaValues* media_values,
const String& attribute)
: media_values_(media_values), length_(0), length_was_set_(false) {
DCHECK(media_values_.Get());
is_valid_ =
Parse(CSSParserTokenRange(CSSTokenizer(attribute).TokenizeToEOF()));
}
float SizesAttributeParser::length() {
if (is_valid_)
return EffectiveSize();
return EffectiveSizeDefaultValue();
}
bool SizesAttributeParser::CalculateLengthInPixels(CSSParserTokenRange range,
float& result) {
const CSSParserToken& start_token = range.Peek();
CSSParserTokenType type = start_token.GetType();
if (type == kDimensionToken) {
double length;
if (!CSSPrimitiveValue::IsLength(start_token.GetUnitType()))
return false;
if ((media_values_->ComputeLength(start_token.NumericValue(),
start_token.GetUnitType(), length)) &&
(length >= 0)) {
result = clampTo<float>(length);
return true;
}
} else if (type == kFunctionToken) {
SizesMathFunctionParser calc_parser(range, media_values_);
if (!calc_parser.IsValid())
return false;
result = calc_parser.Result();
return true;
} else if (type == kNumberToken && !start_token.NumericValue()) {
result = 0;
return true;
}
return false;
}
bool SizesAttributeParser::MediaConditionMatches(
const MediaQuerySet& media_condition) {
// A Media Condition cannot have a media type other then screen.
MediaQueryEvaluator media_query_evaluator(*media_values_);
return media_query_evaluator.Eval(media_condition);
}
bool SizesAttributeParser::Parse(CSSParserTokenRange range) {
// Split on a comma token and parse the result tokens as (media-condition,
// length) pairs
while (!range.AtEnd()) {
const CSSParserToken* media_condition_start = &range.Peek();
// The length is the last component value before the comma which isn't
// whitespace or a comment
const CSSParserToken* length_token_start = &range.Peek();
const CSSParserToken* length_token_end = &range.Peek();
while (!range.AtEnd() && range.Peek().GetType() != kCommaToken) {
length_token_start = &range.Peek();
range.ConsumeComponentValue();
length_token_end = &range.Peek();
range.ConsumeWhitespace();
}
range.Consume();
float length;
if (!CalculateLengthInPixels(
range.MakeSubRange(length_token_start, length_token_end), length))
continue;
scoped_refptr<MediaQuerySet> media_condition =
MediaQueryParser::ParseMediaCondition(
range.MakeSubRange(media_condition_start, length_token_start));
if (!media_condition || !MediaConditionMatches(*media_condition))
continue;
length_ = length;
length_was_set_ = true;
return true;
}
return false;
}
float SizesAttributeParser::EffectiveSize() {
if (length_was_set_)
return length_;
return EffectiveSizeDefaultValue();
}
float SizesAttributeParser::EffectiveSizeDefaultValue() {
// Returning the equivalent of "100vw"
return clampTo<float>(media_values_->ViewportWidth());
}
} // namespace blink
|