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 "SizesAttributeParser.h"
8 #include "MediaTypeNames.h"
9 #include "core/css/MediaQueryEvaluator.h"
10 #include "core/css/parser/MediaQueryTokenizer.h"
11 #include "core/css/parser/SizesCalcParser.h"
15 unsigned SizesAttributeParser::findEffectiveSize(const String& attribute, PassRefPtr<MediaValues> mediaValues)
17 Vector<MediaQueryToken> tokens;
18 SizesAttributeParser parser(mediaValues);
20 MediaQueryTokenizer::tokenize(attribute, tokens);
21 if (!parser.parse(tokens))
22 return parser.effectiveSizeDefaultValue();
23 return parser.effectiveSize();
26 bool SizesAttributeParser::calculateLengthInPixels(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken, unsigned& result)
28 MediaQueryTokenType type = startToken->type();
29 if (type == DimensionToken) {
31 if (!CSSPrimitiveValue::isLength(startToken->unitType()))
33 if ((m_mediaValues->computeLength(startToken->numericValue(), startToken->unitType(), length)) && (length > 0)) {
34 result = (unsigned)length;
37 } else if (type == FunctionToken) {
38 return SizesCalcParser::parse(startToken, endToken, m_mediaValues, result);
44 static void reverseSkipIrrelevantTokens(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken)
46 MediaQueryTokenIterator endToken = token;
47 while (token != startToken && (token->type() == WhitespaceToken || token->type() == CommentToken || token->type() == EOFToken))
49 if (token != endToken)
53 static void reverseSkipUntilComponentStart(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken)
55 if (token == startToken)
58 if (token->blockType() != MediaQueryToken::BlockEnd)
60 unsigned blockLevel = 0;
61 while (token != startToken) {
62 if (token->blockType() == MediaQueryToken::BlockEnd) {
64 } else if (token->blockType() == MediaQueryToken::BlockStart) {
74 bool SizesAttributeParser::mediaConditionMatches(PassRefPtrWillBeRawPtr<MediaQuerySet> mediaCondition)
76 // FIXME: How do I handle non-screen media types here?
77 MediaQueryEvaluator mediaQueryEvaluator(MediaTypeNames::screen, *m_mediaValues);
78 return mediaQueryEvaluator.eval(mediaCondition.get());
81 bool SizesAttributeParser::parseMediaConditionAndLength(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken)
83 MediaQueryTokenIterator lengthTokenStart;
84 MediaQueryTokenIterator lengthTokenEnd;
86 reverseSkipIrrelevantTokens(endToken, startToken);
87 lengthTokenEnd = endToken;
88 reverseSkipUntilComponentStart(endToken, startToken);
89 lengthTokenStart = endToken;
91 if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length))
93 RefPtrWillBeRawPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(startToken, endToken);
94 if (mediaCondition && mediaConditionMatches(mediaCondition)) {
101 bool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens)
103 if (tokens.isEmpty())
105 MediaQueryTokenIterator startToken = tokens.begin();
106 MediaQueryTokenIterator endToken;
107 // Split on a comma token, and send the result tokens to be parsed as (media-condition, length) pairs
108 for (MediaQueryTokenIterator token = tokens.begin(); token != tokens.end(); ++token) {
109 if (token->type() == CommaToken) {
111 if (parseMediaConditionAndLength(startToken, endToken))
117 endToken = tokens.end();
118 return parseMediaConditionAndLength(startToken, --endToken);
121 unsigned SizesAttributeParser::effectiveSize()
125 return effectiveSizeDefaultValue();
128 unsigned SizesAttributeParser::effectiveSizeDefaultValue()
130 // Returning the equivalent of "100%"
131 return m_mediaValues->viewportWidth();