OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "config.h" | |
6 #include "SizesAttributeParser.h" | |
7 | |
8 #include "MediaTypeNames.h" | |
9 #include "core/css/MediaQueryEvaluator.h" | |
10 #include "core/css/parser/MediaQueryTokenizer.h" | |
11 | |
12 namespace WebCore { | |
13 | |
14 unsigned SizesAttributeParser::findEffectiveSize(const String& attribute, PassRe
fPtr<MediaValues> mediaValues) | |
15 { | |
16 Vector<MediaQueryToken> tokens; | |
17 SizesAttributeParser parser(mediaValues); | |
18 | |
19 MediaQueryTokenizer::tokenize(attribute, tokens); | |
20 if (!parser.parse(tokens)) | |
21 return parser.effectiveSizeDefaultValue(); | |
22 return parser.effectiveSize(); | |
23 } | |
24 | |
25 bool SizesAttributeParser::calculateLengthInPixels(TokenIterator startToken, Tok
enIterator endToken, unsigned& result) | |
26 { | |
27 MediaQueryTokenType type = startToken->type(); | |
28 if (type == DimensionToken) { | |
29 int length; | |
30 if (!CSSPrimitiveValue::isLength(startToken->unitType())) | |
31 return false; | |
32 if (m_mediaValues->computeLength(startToken->numericValue(), startToken-
>unitType(), length)) { | |
33 if (length > 0) { | |
34 result = (unsigned)length; | |
35 return true; | |
36 } | |
37 } | |
38 } | |
39 if (type == FunctionToken) { | |
40 // FIXME - Handle calc() functions here! | |
41 } | |
42 return false; | |
43 } | |
44 | |
45 static void reverseSkipIrrelevantTokens(TokenIterator& token, TokenIterator star
tToken) | |
46 { | |
47 TokenIterator endToken = token; | |
48 while (token != startToken && (token->type() == WhitespaceToken || token->ty
pe() == CommentToken || token->type() == EOFToken)) | |
49 --token; | |
50 if (token != endToken) | |
51 ++token; | |
52 } | |
53 | |
54 static void reverseSkipUntilComponentStart(TokenIterator& token, TokenIterator s
tartToken) | |
55 { | |
56 if (token == startToken) | |
57 return; | |
58 --token; | |
59 if (token->blockType() != MediaQueryToken::BlockEnd) | |
60 return; | |
61 unsigned blockLevel = 0; | |
62 while (token != startToken) { | |
63 if (token->blockType() == MediaQueryToken::BlockEnd) { | |
64 ++blockLevel; | |
65 } else if (token->blockType() == MediaQueryToken::BlockStart) { | |
66 --blockLevel; | |
67 if (!blockLevel) | |
68 break; | |
69 } | |
70 | |
71 --token; | |
72 } | |
73 } | |
74 | |
75 bool SizesAttributeParser::mediaConditionMatches(PassRefPtr<MediaQuerySet> media
Condition) | |
76 { | |
77 // FIXME: How do I handle non-screen media types here? | |
78 MediaQueryEvaluator mediaQueryEvaluator(MediaTypeNames::screen, *m_mediaValu
es); | |
79 return mediaQueryEvaluator.eval(mediaCondition.get()); | |
80 } | |
81 | |
82 bool SizesAttributeParser::parseMediaConditionAndLength(TokenIterator startToken
, TokenIterator endToken) | |
83 { | |
84 TokenIterator lengthTokenStart; | |
85 TokenIterator lengthTokenEnd; | |
86 | |
87 reverseSkipIrrelevantTokens(endToken, startToken); | |
88 lengthTokenEnd = endToken; | |
89 reverseSkipUntilComponentStart(endToken, startToken); | |
90 lengthTokenStart = endToken; | |
91 unsigned length; | |
92 if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length)) | |
93 return false; | |
94 RefPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition
(startToken, endToken); | |
95 if (mediaCondition && mediaConditionMatches(mediaCondition)) { | |
96 m_length = length; | |
97 return true; | |
98 } | |
99 return false; | |
100 } | |
101 | |
102 bool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens) | |
103 { | |
104 TokenIterator startToken = tokens.begin(); | |
105 TokenIterator endToken; | |
106 // Split on a comma token, and send the result tokens to be parsed as (media
-condition, length) pairs | |
107 for (TokenIterator token = tokens.begin(); token != tokens.end(); ++token) { | |
108 if (token->type() == CommaToken) { | |
109 endToken = token; | |
110 if (parseMediaConditionAndLength(startToken, endToken)) | |
111 return true; | |
112 startToken = token; | |
113 ++startToken; | |
114 } | |
115 } | |
116 endToken = tokens.end(); | |
117 return parseMediaConditionAndLength(startToken, --endToken); | |
118 } | |
119 | |
120 unsigned SizesAttributeParser::effectiveSize() | |
121 { | |
122 if (m_length) | |
123 return m_length; | |
124 return effectiveSizeDefaultValue(); | |
125 } | |
126 | |
127 unsigned SizesAttributeParser::effectiveSizeDefaultValue() | |
128 { | |
129 // Returning the equivalent of "100%" | |
130 return m_mediaValues->viewportWidth(); | |
131 } | |
132 | |
133 } // namespace | |
134 | |
OLD | NEW |