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 == NumberToken || type == PercentageToken || type == DimensionToken ) { | |
eseidel
2014/04/14 23:10:13
Would this be clearer returning early instead of a
| |
29 int length; | |
eseidel
2014/04/14 23:10:13
Can this be negative?
| |
30 RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::create(sta rtToken->numericValue(), startToken->unitType()); | |
eseidel
2014/04/14 23:10:13
Presumably this only ever runs on the main thread?
| |
31 if (!primitiveValue->isLength()) | |
32 return false; | |
33 if (m_mediaValues->computeLength(*primitiveValue, length)) { | |
34 if (length > 0) { | |
35 result = (unsigned)length; | |
36 return true; | |
37 } | |
38 } | |
39 } | |
40 // FIXME - Handle calc() functions here! | |
41 return false; | |
42 } | |
43 | |
44 static void reverseSkipIrrelevantTokens(TokenIterator& token, TokenIterator star tToken) | |
45 { | |
46 TokenIterator endToken = token; | |
47 while (token != startToken && (token->type() == WhitespaceToken || token->ty pe() == CommentToken || token->type() == EOFToken)) | |
48 --token; | |
49 if (token != endToken) | |
50 ++token; | |
51 } | |
52 | |
53 static void reverseSkipUntilComponentStart(TokenIterator& token, TokenIterator s tartToken) | |
54 { | |
55 if (token == startToken) | |
56 return; | |
57 --token; | |
58 if (token->blockType() != MediaQueryToken::BlockEnd) | |
59 return; | |
60 unsigned blockLevel = 0; | |
61 while (token != startToken) { | |
62 if (token->blockType() == MediaQueryToken::BlockEnd) { | |
63 ++blockLevel; | |
64 } else if (token->blockType() == MediaQueryToken::BlockStart) { | |
65 --blockLevel; | |
66 if (!blockLevel) | |
67 break; | |
68 } | |
69 | |
70 --token; | |
71 } | |
72 } | |
73 | |
74 bool SizesAttributeParser::mediaConditionMatches(PassRefPtr<MediaQuerySet> media Condition) | |
75 { | |
76 // FIXME: How do I handle non-screen media types here? | |
77 MediaQueryEvaluator mediaQueryEvaluator(MediaTypeNames::screen, *m_mediaValu es); | |
78 return mediaQueryEvaluator.eval(mediaCondition.get()); | |
79 } | |
80 | |
81 bool SizesAttributeParser::parseMediaConditionAndLength(TokenIterator startToken , TokenIterator endToken) | |
82 { | |
83 TokenIterator lengthTokenStart; | |
84 TokenIterator lengthTokenEnd; | |
85 | |
86 reverseSkipIrrelevantTokens(endToken, startToken); | |
87 lengthTokenEnd = endToken; | |
88 reverseSkipUntilComponentStart(endToken, startToken); | |
89 lengthTokenStart = endToken; | |
90 unsigned length; | |
91 if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length)) | |
92 return false; | |
93 RefPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition (startToken, endToken); | |
94 if (mediaCondition && mediaConditionMatches(mediaCondition)) { | |
95 m_length = length; | |
96 return true; | |
97 } | |
98 return false; | |
99 } | |
100 | |
101 bool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens) | |
102 { | |
103 TokenIterator startToken = tokens.begin(); | |
104 TokenIterator endToken; | |
105 // Split on a comma token, and send the result tokens to be parsed as (media -condition, length) pairs | |
106 for (TokenIterator token = tokens.begin(); token != tokens.end(); ++token) { | |
107 if (token->type() == CommaToken) { | |
108 endToken = token; | |
109 if (parseMediaConditionAndLength(startToken, endToken)) | |
110 return true; | |
111 startToken = token; | |
112 ++startToken; | |
113 } | |
114 } | |
115 endToken = tokens.end(); | |
116 return parseMediaConditionAndLength(startToken, --endToken); | |
117 } | |
118 | |
119 unsigned SizesAttributeParser::effectiveSize() | |
120 { | |
121 if (m_length) | |
122 return m_length; | |
123 return effectiveSizeDefaultValue(); | |
124 } | |
125 | |
126 unsigned SizesAttributeParser::effectiveSizeDefaultValue() | |
127 { | |
128 // Returning the equivalent of "100%" | |
129 return m_mediaValues->viewportWidth(); | |
130 } | |
131 | |
132 } // namespace | |
133 | |
OLD | NEW |