Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(580)

Unified Diff: Source/core/css/parser/SizesAttributeParser.cpp

Issue 224733011: A sizes attribute parser (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added invalid length layout test Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/css/parser/SizesAttributeParser.cpp
diff --git a/Source/core/css/parser/SizesAttributeParser.cpp b/Source/core/css/parser/SizesAttributeParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a7cd5f87532df948f143f77a7f6cf33d260de551
--- /dev/null
+++ b/Source/core/css/parser/SizesAttributeParser.cpp
@@ -0,0 +1,133 @@
+// 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 "config.h"
+#include "SizesAttributeParser.h"
+
+#include "MediaTypeNames.h"
+#include "core/css/MediaQueryEvaluator.h"
+#include "core/css/parser/MediaQueryTokenizer.h"
+
+namespace WebCore {
+
+unsigned SizesAttributeParser::findEffectiveSize(const String& attribute, PassRefPtr<MediaValues> mediaValues)
+{
+ Vector<MediaQueryToken> tokens;
+ SizesAttributeParser parser(mediaValues);
+
+ MediaQueryTokenizer::tokenize(attribute, tokens);
+ if (!parser.parse(tokens))
+ return parser.effectiveSizeDefaultValue();
+ return parser.effectiveSize();
+}
+
+bool SizesAttributeParser::calculateLengthInPixels(TokenIterator startToken, TokenIterator endToken, unsigned& result)
+{
+ MediaQueryTokenType type = startToken->type();
+ if (type == NumberToken || type == PercentageToken || type == DimensionToken) {
eseidel 2014/04/14 23:10:13 Would this be clearer returning early instead of a
+ int length;
eseidel 2014/04/14 23:10:13 Can this be negative?
+ RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::create(startToken->numericValue(), startToken->unitType());
eseidel 2014/04/14 23:10:13 Presumably this only ever runs on the main thread?
+ if (!primitiveValue->isLength())
+ return false;
+ if (m_mediaValues->computeLength(*primitiveValue, length)) {
+ if (length > 0) {
+ result = (unsigned)length;
+ return true;
+ }
+ }
+ }
+ // FIXME - Handle calc() functions here!
+ return false;
+}
+
+static void reverseSkipIrrelevantTokens(TokenIterator& token, TokenIterator startToken)
+{
+ TokenIterator endToken = token;
+ while (token != startToken && (token->type() == WhitespaceToken || token->type() == CommentToken || token->type() == EOFToken))
+ --token;
+ if (token != endToken)
+ ++token;
+}
+
+static void reverseSkipUntilComponentStart(TokenIterator& token, TokenIterator startToken)
+{
+ if (token == startToken)
+ return;
+ --token;
+ if (token->blockType() != MediaQueryToken::BlockEnd)
+ return;
+ unsigned blockLevel = 0;
+ while (token != startToken) {
+ if (token->blockType() == MediaQueryToken::BlockEnd) {
+ ++blockLevel;
+ } else if (token->blockType() == MediaQueryToken::BlockStart) {
+ --blockLevel;
+ if (!blockLevel)
+ break;
+ }
+
+ --token;
+ }
+}
+
+bool SizesAttributeParser::mediaConditionMatches(PassRefPtr<MediaQuerySet> mediaCondition)
+{
+ // FIXME: How do I handle non-screen media types here?
+ MediaQueryEvaluator mediaQueryEvaluator(MediaTypeNames::screen, *m_mediaValues);
+ return mediaQueryEvaluator.eval(mediaCondition.get());
+}
+
+bool SizesAttributeParser::parseMediaConditionAndLength(TokenIterator startToken, TokenIterator endToken)
+{
+ TokenIterator lengthTokenStart;
+ TokenIterator lengthTokenEnd;
+
+ reverseSkipIrrelevantTokens(endToken, startToken);
+ lengthTokenEnd = endToken;
+ reverseSkipUntilComponentStart(endToken, startToken);
+ lengthTokenStart = endToken;
+ unsigned length;
+ if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length))
+ return false;
+ RefPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(startToken, endToken);
+ if (mediaCondition && mediaConditionMatches(mediaCondition)) {
+ m_length = length;
+ return true;
+ }
+ return false;
+}
+
+bool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens)
+{
+ TokenIterator startToken = tokens.begin();
+ TokenIterator endToken;
+ // Split on a comma token, and send the result tokens to be parsed as (media-condition, length) pairs
+ for (TokenIterator token = tokens.begin(); token != tokens.end(); ++token) {
+ if (token->type() == CommaToken) {
+ endToken = token;
+ if (parseMediaConditionAndLength(startToken, endToken))
+ return true;
+ startToken = token;
+ ++startToken;
+ }
+ }
+ endToken = tokens.end();
+ return parseMediaConditionAndLength(startToken, --endToken);
+}
+
+unsigned SizesAttributeParser::effectiveSize()
+{
+ if (m_length)
+ return m_length;
+ return effectiveSizeDefaultValue();
+}
+
+unsigned SizesAttributeParser::effectiveSizeDefaultValue()
+{
+ // Returning the equivalent of "100%"
+ return m_mediaValues->viewportWidth();
+}
+
+} // namespace
+

Powered by Google App Engine
This is Rietveld 408576698