110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch// found in the LICENSE file. 410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch#include "config.h" 65d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/css/parser/SizesAttributeParser.h" 710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 85d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/MediaTypeNames.h" 910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch#include "core/css/MediaQueryEvaluator.h" 1010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch#include "core/css/parser/MediaQueryTokenizer.h" 11f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu#include "core/css/parser/SizesCalcParser.h" 1210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 13c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 1410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 15c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)SizesAttributeParser::SizesAttributeParser(PassRefPtr<MediaValues> mediaValues, const String& attribute) 16c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) : m_mediaValues(mediaValues) 17c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_length(0) 18c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_lengthWasSet(false) 19c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) , m_viewportDependant(false) 2010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 21c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) MediaQueryTokenizer::tokenize(attribute, m_tokens); 22c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_isValid = parse(m_tokens); 23c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} 2410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 25c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)unsigned SizesAttributeParser::length() 26c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){ 27c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (m_isValid) 28c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return effectiveSize(); 29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return effectiveSizeDefaultValue(); 3010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 3110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 32f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liubool SizesAttributeParser::calculateLengthInPixels(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken, unsigned& result) 3310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 34f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (startToken == endToken) 35f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) return false; 3610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch MediaQueryTokenType type = startToken->type(); 3710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (type == DimensionToken) { 3810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch int length; 3910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (!CSSPrimitiveValue::isLength(startToken->unitType())) 4010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return false; 41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_viewportDependant = CSSPrimitiveValue::isViewportPercentageLength(startToken->unitType()); 4210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if ((m_mediaValues->computeLength(startToken->numericValue(), startToken->unitType(), length)) && (length > 0)) { 4310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch result = (unsigned)length; 4410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return true; 4510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 46f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu } else if (type == FunctionToken) { 47c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SizesCalcParser calcParser(startToken, endToken, m_mediaValues); 48c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!calcParser.isValid()) 49c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return false; 50c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_viewportDependant = calcParser.viewportDependant(); 51c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) result = calcParser.result(); 52c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) return true; 53f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) } else if (type == NumberToken && !startToken->numericValue()) { 54f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) result = 0; 55f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) return true; 5610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 5810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return false; 5910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 6010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustatic void reverseSkipIrrelevantTokens(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken) 6210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu MediaQueryTokenIterator endToken = token; 6410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch while (token != startToken && (token->type() == WhitespaceToken || token->type() == CommentToken || token->type() == EOFToken)) 6510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch --token; 6610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (token != endToken) 6710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ++token; 6810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 6910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 70f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liustatic void reverseSkipUntilComponentStart(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken) 7110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 7210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (token == startToken) 7310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return; 7410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch --token; 7510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (token->blockType() != MediaQueryToken::BlockEnd) 7610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return; 7710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch unsigned blockLevel = 0; 7810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch while (token != startToken) { 7910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (token->blockType() == MediaQueryToken::BlockEnd) { 8010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ++blockLevel; 8110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } else if (token->blockType() == MediaQueryToken::BlockStart) { 8210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch --blockLevel; 8310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (!blockLevel) 8410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch break; 8510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 8610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 8710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch --token; 8810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 8910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 9010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 9110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochbool SizesAttributeParser::mediaConditionMatches(PassRefPtrWillBeRawPtr<MediaQuerySet> mediaCondition) 9210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 93d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // A Media Condition cannot have a media type other then screen. 94197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch MediaQueryEvaluator mediaQueryEvaluator(*m_mediaValues); 9510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return mediaQueryEvaluator.eval(mediaCondition.get()); 9610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 9710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 98f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liubool SizesAttributeParser::parseMediaConditionAndLength(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken) 9910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 100f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu MediaQueryTokenIterator lengthTokenStart; 101f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu MediaQueryTokenIterator lengthTokenEnd; 10210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 10310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch reverseSkipIrrelevantTokens(endToken, startToken); 10410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch lengthTokenEnd = endToken; 10510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch reverseSkipUntilComponentStart(endToken, startToken); 10610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch lengthTokenStart = endToken; 10710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch unsigned length; 10810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length)) 10910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return false; 11010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch RefPtrWillBeRawPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(startToken, endToken); 11110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (mediaCondition && mediaConditionMatches(mediaCondition)) { 11210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch m_length = length; 113f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) m_lengthWasSet = true; 11410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return true; 11510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 11610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return false; 11710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 11810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 11910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochbool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens) 12010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 12110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (tokens.isEmpty()) 12210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return false; 123f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu MediaQueryTokenIterator startToken = tokens.begin(); 124f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu MediaQueryTokenIterator endToken; 12510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch // Split on a comma token, and send the result tokens to be parsed as (media-condition, length) pairs 126f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu for (MediaQueryTokenIterator token = tokens.begin(); token != tokens.end(); ++token) { 12710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (token->type() == CommaToken) { 12810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch endToken = token; 12910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch if (parseMediaConditionAndLength(startToken, endToken)) 13010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return true; 13110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch startToken = token; 13210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch ++startToken; 13310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 13410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch } 13510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch endToken = tokens.end(); 13610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return parseMediaConditionAndLength(startToken, --endToken); 13710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 13810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 13910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochunsigned SizesAttributeParser::effectiveSize() 14010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 141f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles) if (m_lengthWasSet) 14210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return m_length; 14310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return effectiveSizeDefaultValue(); 14410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 14510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 14610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdochunsigned SizesAttributeParser::effectiveSizeDefaultValue() 14710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch{ 148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) // Returning the equivalent of "100vw" 149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) m_viewportDependant = true; 15010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return m_mediaValues->viewportWidth(); 15110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} 15210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 15310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch} // namespace 15410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch 155