1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/css/parser/SizesAttributeParser.h"
8 #include "core/MediaTypeNames.h"
9 #include "core/css/MediaQueryEvaluator.h"
10 #include "core/css/parser/MediaQueryTokenizer.h"
11 #include "core/css/parser/SizesCalcParser.h"
15 SizesAttributeParser::SizesAttributeParser(PassRefPtr<MediaValues> mediaValues, const String& attribute)
16 : m_mediaValues(mediaValues)
18 , m_lengthWasSet(false)
19 , m_viewportDependant(false)
21 MediaQueryTokenizer::tokenize(attribute, m_tokens);
22 m_isValid = parse(m_tokens);
25 unsigned SizesAttributeParser::length()
28 return effectiveSize();
29 return effectiveSizeDefaultValue();
32 bool SizesAttributeParser::calculateLengthInPixels(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken, unsigned& result)
34 if (startToken == endToken)
36 MediaQueryTokenType type = startToken->type();
37 if (type == DimensionToken) {
39 if (!CSSPrimitiveValue::isLength(startToken->unitType()))
41 m_viewportDependant = CSSPrimitiveValue::isViewportPercentageLength(startToken->unitType());
42 if ((m_mediaValues->computeLength(startToken->numericValue(), startToken->unitType(), length)) && (length > 0)) {
43 result = (unsigned)length;
46 } else if (type == FunctionToken) {
47 SizesCalcParser calcParser(startToken, endToken, m_mediaValues);
48 if (!calcParser.isValid())
50 m_viewportDependant = calcParser.viewportDependant();
51 result = calcParser.result();
53 } else if (type == NumberToken && !startToken->numericValue()) {
61 static void reverseSkipIrrelevantTokens(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken)
63 MediaQueryTokenIterator endToken = token;
64 while (token != startToken && (token->type() == WhitespaceToken || token->type() == CommentToken || token->type() == EOFToken))
66 if (token != endToken)
70 static void reverseSkipUntilComponentStart(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken)
72 if (token == startToken)
75 if (token->blockType() != MediaQueryToken::BlockEnd)
77 unsigned blockLevel = 0;
78 while (token != startToken) {
79 if (token->blockType() == MediaQueryToken::BlockEnd) {
81 } else if (token->blockType() == MediaQueryToken::BlockStart) {
91 bool SizesAttributeParser::mediaConditionMatches(PassRefPtrWillBeRawPtr<MediaQuerySet> mediaCondition)
93 // A Media Condition cannot have a media type other then screen.
94 MediaQueryEvaluator mediaQueryEvaluator(*m_mediaValues);
95 return mediaQueryEvaluator.eval(mediaCondition.get());
98 bool SizesAttributeParser::parseMediaConditionAndLength(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken)
100 MediaQueryTokenIterator lengthTokenStart;
101 MediaQueryTokenIterator lengthTokenEnd;
103 reverseSkipIrrelevantTokens(endToken, startToken);
104 lengthTokenEnd = endToken;
105 reverseSkipUntilComponentStart(endToken, startToken);
106 lengthTokenStart = endToken;
108 if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length))
110 RefPtrWillBeRawPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(startToken, endToken);
111 if (mediaCondition && mediaConditionMatches(mediaCondition)) {
113 m_lengthWasSet = true;
119 bool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens)
121 if (tokens.isEmpty())
123 MediaQueryTokenIterator startToken = tokens.begin();
124 MediaQueryTokenIterator endToken;
125 // Split on a comma token, and send the result tokens to be parsed as (media-condition, length) pairs
126 for (MediaQueryTokenIterator token = tokens.begin(); token != tokens.end(); ++token) {
127 if (token->type() == CommaToken) {
129 if (parseMediaConditionAndLength(startToken, endToken))
135 endToken = tokens.end();
136 return parseMediaConditionAndLength(startToken, --endToken);
139 unsigned SizesAttributeParser::effectiveSize()
143 return effectiveSizeDefaultValue();
146 unsigned SizesAttributeParser::effectiveSizeDefaultValue()
148 // Returning the equivalent of "100vw"
149 m_viewportDependant = true;
150 return m_mediaValues->viewportWidth();