| OLD | NEW |
| 1 /* | 1 /* |
| 2 * CSS Media Query | 2 * CSS Media Query |
| 3 * | 3 * |
| 4 * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. | 4 * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>. |
| 5 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). | 5 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
| 6 * Copyright (C) 2013 Apple Inc. All rights reserved. | 6 * Copyright (C) 2013 Apple Inc. All rights reserved. |
| 7 * | 7 * |
| 8 * Redistribution and use in source and binary forms, with or without | 8 * Redistribution and use in source and binary forms, with or without |
| 9 * modification, are permitted provided that the following conditions | 9 * modification, are permitted provided that the following conditions |
| 10 * are met: | 10 * are met: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 */ | 28 */ |
| 29 | 29 |
| 30 #include "config.h" | 30 #include "config.h" |
| 31 #include "core/css/MediaQueryExp.h" | 31 #include "core/css/MediaQueryExp.h" |
| 32 | 32 |
| 33 #include "core/css/CSSPrimitiveValue.h" | 33 #include "core/css/CSSPrimitiveValue.h" |
| 34 #include "core/css/parser/CSSParserValues.h" | 34 #include "core/css/parser/CSSParserToken.h" |
| 35 #include "core/html/parser/HTMLParserIdioms.h" | 35 #include "core/html/parser/HTMLParserIdioms.h" |
| 36 #include "platform/Decimal.h" | 36 #include "platform/Decimal.h" |
| 37 #include "platform/RuntimeEnabledFeatures.h" | 37 #include "platform/RuntimeEnabledFeatures.h" |
| 38 #include "wtf/text/StringBuffer.h" | 38 #include "wtf/text/StringBuffer.h" |
| 39 #include "wtf/text/StringBuilder.h" | 39 #include "wtf/text/StringBuilder.h" |
| 40 | 40 |
| 41 namespace blink { | 41 namespace blink { |
| 42 | 42 |
| 43 using namespace MediaFeatureNames; | 43 using namespace MediaFeatureNames; |
| 44 | 44 |
| 45 static inline bool featureWithCSSValueID(const String& mediaFeature, const CSSPa
rserValue* value) | 45 static inline bool featureWithCSSValueID(const String& mediaFeature, const CSSVa
lueID& id) |
| 46 { | 46 { |
| 47 if (!value->id) | 47 if (!id) |
| 48 return false; | 48 return false; |
| 49 | 49 |
| 50 return mediaFeature == displayModeMediaFeature | 50 return mediaFeature == displayModeMediaFeature |
| 51 || mediaFeature == orientationMediaFeature | 51 || mediaFeature == orientationMediaFeature |
| 52 || mediaFeature == pointerMediaFeature | 52 || mediaFeature == pointerMediaFeature |
| 53 || mediaFeature == anyPointerMediaFeature | 53 || mediaFeature == anyPointerMediaFeature |
| 54 || mediaFeature == hoverMediaFeature | 54 || mediaFeature == hoverMediaFeature |
| 55 || mediaFeature == anyHoverMediaFeature | 55 || mediaFeature == anyHoverMediaFeature |
| 56 || mediaFeature == scanMediaFeature; | 56 || mediaFeature == scanMediaFeature; |
| 57 } | 57 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 70 if (mediaFeature == hoverMediaFeature || mediaFeature == anyHoverMediaFeatur
e) | 70 if (mediaFeature == hoverMediaFeature || mediaFeature == anyHoverMediaFeatur
e) |
| 71 return ident == CSSValueNone || ident == CSSValueOnDemand || ident == CS
SValueHover; | 71 return ident == CSSValueNone || ident == CSSValueOnDemand || ident == CS
SValueHover; |
| 72 | 72 |
| 73 if (mediaFeature == scanMediaFeature) | 73 if (mediaFeature == scanMediaFeature) |
| 74 return ident == CSSValueInterlace || ident == CSSValueProgressive; | 74 return ident == CSSValueInterlace || ident == CSSValueProgressive; |
| 75 | 75 |
| 76 ASSERT_NOT_REACHED(); | 76 ASSERT_NOT_REACHED(); |
| 77 return false; | 77 return false; |
| 78 } | 78 } |
| 79 | 79 |
| 80 static inline bool featureWithValidPositiveLength(const String& mediaFeature, co
nst CSSParserValue* value) | 80 static inline bool featureWithValidPositiveLength(const String& mediaFeature, co
nst CSSParserToken& token) |
| 81 { | 81 { |
| 82 if (!(CSSPrimitiveValue::isLength((CSSPrimitiveValue::UnitType)value->unit)
|| (value->unit == CSSPrimitiveValue::CSS_NUMBER && value->fValue == 0)) || valu
e->fValue < 0) | 82 if (!(CSSPrimitiveValue::isLength(token.unitType()) || (token.unitType() ==
CSSPrimitiveValue::CSS_NUMBER && token.numericValue() == 0)) || token.numericVal
ue() < 0) |
| 83 return false; | 83 return false; |
| 84 | 84 |
| 85 | 85 |
| 86 return mediaFeature == heightMediaFeature | 86 return mediaFeature == heightMediaFeature |
| 87 || mediaFeature == maxHeightMediaFeature | 87 || mediaFeature == maxHeightMediaFeature |
| 88 || mediaFeature == minHeightMediaFeature | 88 || mediaFeature == minHeightMediaFeature |
| 89 || mediaFeature == widthMediaFeature | 89 || mediaFeature == widthMediaFeature |
| 90 || mediaFeature == maxWidthMediaFeature | 90 || mediaFeature == maxWidthMediaFeature |
| 91 || mediaFeature == minWidthMediaFeature | 91 || mediaFeature == minWidthMediaFeature |
| 92 || mediaFeature == deviceHeightMediaFeature | 92 || mediaFeature == deviceHeightMediaFeature |
| 93 || mediaFeature == maxDeviceHeightMediaFeature | 93 || mediaFeature == maxDeviceHeightMediaFeature |
| 94 || mediaFeature == minDeviceHeightMediaFeature | 94 || mediaFeature == minDeviceHeightMediaFeature |
| 95 || mediaFeature == deviceWidthMediaFeature | 95 || mediaFeature == deviceWidthMediaFeature |
| 96 || mediaFeature == minDeviceWidthMediaFeature | 96 || mediaFeature == minDeviceWidthMediaFeature |
| 97 || mediaFeature == maxDeviceWidthMediaFeature; | 97 || mediaFeature == maxDeviceWidthMediaFeature; |
| 98 } | 98 } |
| 99 | 99 |
| 100 static inline bool featureWithValidDensity(const String& mediaFeature, const CSS
ParserValue* value) | 100 static inline bool featureWithValidDensity(const String& mediaFeature, const CSS
ParserToken& token) |
| 101 { | 101 { |
| 102 if ((value->unit != CSSPrimitiveValue::CSS_DPPX && value->unit != CSSPrimiti
veValue::CSS_DPI && value->unit != CSSPrimitiveValue::CSS_DPCM) || value->fValue
<= 0) | 102 if ((token.unitType() != CSSPrimitiveValue::CSS_DPPX && token.unitType() !=
CSSPrimitiveValue::CSS_DPI && token.unitType() != CSSPrimitiveValue::CSS_DPCM) |
| token.numericValue() <= 0) |
| 103 return false; | 103 return false; |
| 104 | 104 |
| 105 return mediaFeature == resolutionMediaFeature | 105 return mediaFeature == resolutionMediaFeature |
| 106 || mediaFeature == minResolutionMediaFeature | 106 || mediaFeature == minResolutionMediaFeature |
| 107 || mediaFeature == maxResolutionMediaFeature; | 107 || mediaFeature == maxResolutionMediaFeature; |
| 108 } | 108 } |
| 109 | 109 |
| 110 static inline bool featureWithPositiveInteger(const String& mediaFeature, const
CSSParserValue* value) | 110 static inline bool featureWithPositiveInteger(const String& mediaFeature, const
CSSParserToken& token) |
| 111 { | 111 { |
| 112 if (!value->isInt || value->fValue < 0) | 112 if (token.numericValueType() != IntegerValueType || token.numericValue() < 0
) |
| 113 return false; | 113 return false; |
| 114 | 114 |
| 115 return mediaFeature == colorMediaFeature | 115 return mediaFeature == colorMediaFeature |
| 116 || mediaFeature == maxColorMediaFeature | 116 || mediaFeature == maxColorMediaFeature |
| 117 || mediaFeature == minColorMediaFeature | 117 || mediaFeature == minColorMediaFeature |
| 118 || mediaFeature == colorIndexMediaFeature | 118 || mediaFeature == colorIndexMediaFeature |
| 119 || mediaFeature == maxColorIndexMediaFeature | 119 || mediaFeature == maxColorIndexMediaFeature |
| 120 || mediaFeature == minColorIndexMediaFeature | 120 || mediaFeature == minColorIndexMediaFeature |
| 121 || mediaFeature == monochromeMediaFeature | 121 || mediaFeature == monochromeMediaFeature |
| 122 || mediaFeature == maxMonochromeMediaFeature | 122 || mediaFeature == maxMonochromeMediaFeature |
| 123 || mediaFeature == minMonochromeMediaFeature; | 123 || mediaFeature == minMonochromeMediaFeature; |
| 124 } | 124 } |
| 125 | 125 |
| 126 static inline bool featureWithPositiveNumber(const String& mediaFeature, const C
SSParserValue* value) | 126 static inline bool featureWithPositiveNumber(const String& mediaFeature, const C
SSParserToken& token) |
| 127 { | 127 { |
| 128 if (value->unit != CSSPrimitiveValue::CSS_NUMBER || value->fValue < 0) | 128 if (token.unitType() != CSSPrimitiveValue::CSS_NUMBER || token.numericValue(
) < 0) |
| 129 return false; | 129 return false; |
| 130 | 130 |
| 131 return mediaFeature == transform3dMediaFeature | 131 return mediaFeature == transform3dMediaFeature |
| 132 || mediaFeature == devicePixelRatioMediaFeature | 132 || mediaFeature == devicePixelRatioMediaFeature |
| 133 || mediaFeature == maxDevicePixelRatioMediaFeature | 133 || mediaFeature == maxDevicePixelRatioMediaFeature |
| 134 || mediaFeature == minDevicePixelRatioMediaFeature; | 134 || mediaFeature == minDevicePixelRatioMediaFeature; |
| 135 } | 135 } |
| 136 | 136 |
| 137 static inline bool featureWithZeroOrOne(const String& mediaFeature, const CSSPar
serValue* value) | 137 static inline bool featureWithZeroOrOne(const String& mediaFeature, const CSSPar
serToken& token) |
| 138 { | 138 { |
| 139 if (!value->isInt || !(value->fValue == 1 || !value->fValue)) | 139 if (token.numericValueType() != IntegerValueType || !(token.numericValue() =
= 1 || !token.numericValue())) |
| 140 return false; | 140 return false; |
| 141 | 141 |
| 142 return mediaFeature == gridMediaFeature; | 142 return mediaFeature == gridMediaFeature; |
| 143 } | 143 } |
| 144 | 144 |
| 145 static inline bool featureWithAspectRatio(const String& mediaFeature) | 145 static inline bool featureWithAspectRatio(const String& mediaFeature) |
| 146 { | 146 { |
| 147 return mediaFeature == aspectRatioMediaFeature | 147 return mediaFeature == aspectRatioMediaFeature |
| 148 || mediaFeature == deviceAspectRatioMediaFeature | 148 || mediaFeature == deviceAspectRatioMediaFeature |
| 149 || mediaFeature == minAspectRatioMediaFeature | 149 || mediaFeature == minAspectRatioMediaFeature |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 , m_expValue(other.expValue()) | 197 , m_expValue(other.expValue()) |
| 198 { | 198 { |
| 199 } | 199 } |
| 200 | 200 |
| 201 MediaQueryExp::MediaQueryExp(const String& mediaFeature, const MediaQueryExpValu
e& expValue) | 201 MediaQueryExp::MediaQueryExp(const String& mediaFeature, const MediaQueryExpValu
e& expValue) |
| 202 : m_mediaFeature(mediaFeature) | 202 : m_mediaFeature(mediaFeature) |
| 203 , m_expValue(expValue) | 203 , m_expValue(expValue) |
| 204 { | 204 { |
| 205 } | 205 } |
| 206 | 206 |
| 207 PassOwnPtrWillBeRawPtr<MediaQueryExp> MediaQueryExp::createIfValid(const String&
mediaFeature, CSSParserValueList* valueList) | 207 CSSValueID cssValueKeywordID(const CSSParserString&); |
| 208 |
| 209 PassOwnPtrWillBeRawPtr<MediaQueryExp> MediaQueryExp::createIfValid(const String&
mediaFeature, const Vector<CSSParserToken, 4>& tokenList) |
| 208 { | 210 { |
| 209 ASSERT(!mediaFeature.isNull()); | 211 ASSERT(!mediaFeature.isNull()); |
| 210 | 212 |
| 211 MediaQueryExpValue expValue; | 213 MediaQueryExpValue expValue; |
| 212 bool isValid = false; | 214 bool isValid = false; |
| 213 String lowerMediaFeature = attemptStaticStringCreation(mediaFeature.lower())
; | 215 String lowerMediaFeature = attemptStaticStringCreation(mediaFeature.lower())
; |
| 214 | 216 |
| 215 // Create value for media query expression that must have 1 or more values. | 217 // Create value for media query expression that must have 1 or more values. |
| 216 if (valueList && valueList->size() > 0) { | 218 if (tokenList.size() > 0) { |
| 217 if (valueList->size() == 1) { | 219 if (tokenList.size() == 1) { |
| 218 CSSParserValue* value = valueList->current(); | 220 CSSParserToken token = tokenList.at(0); |
| 219 ASSERT(value); | 221 CSSValueID id = token.type() == IdentToken ? cssValueKeywordID(token
.value()) : CSSValueInvalid; |
| 220 | 222 |
| 221 if (featureWithCSSValueID(lowerMediaFeature, value) && featureWithVa
lidIdent(lowerMediaFeature, value->id)) { | 223 if (featureWithCSSValueID(lowerMediaFeature, id) && featureWithValid
Ident(lowerMediaFeature, id)) { |
| 222 // Media features that use CSSValueIDs. | 224 // Media features that use CSSValueIDs. |
| 223 expValue.id = value->id; | 225 expValue.id = id; |
| 224 expValue.unit = CSSPrimitiveValue::CSS_VALUE_ID; | 226 expValue.unit = CSSPrimitiveValue::CSS_VALUE_ID; |
| 225 expValue.isID = true; | 227 expValue.isID = true; |
| 226 } else if (featureWithValidDensity(lowerMediaFeature, value) | 228 } else if (token.type() == NumberToken || token.type() == Percentage
Token || token.type() == DimensionToken) { |
| 227 || featureWithValidPositiveLength(lowerMediaFeature, value)) { | 229 // Check for numeric token types since it is only safe for these
types to call numericValue. |
| 228 // Media features that must have non-negative <density>, ie. dpp
x, dpi or dpcm, | 230 if (featureWithValidDensity(lowerMediaFeature, token) |
| 229 // or Media features that must have non-negative <length> or num
ber value. | 231 || featureWithValidPositiveLength(lowerMediaFeature, token))
{ |
| 230 expValue.value = value->fValue; | 232 // Media features that must have non-negative <density>, ie.
dppx, dpi or dpcm, |
| 231 expValue.unit = (CSSPrimitiveValue::UnitType)value->unit; | 233 // or Media features that must have non-negative <length> or
number value. |
| 232 expValue.isValue = true; | 234 expValue.value = token.numericValue(); |
| 233 } else if (featureWithPositiveInteger(lowerMediaFeature, value) | 235 expValue.unit = token.unitType(); |
| 234 || featureWithPositiveNumber(lowerMediaFeature, value) | 236 expValue.isValue = true; |
| 235 || featureWithZeroOrOne(lowerMediaFeature, value)) { | 237 } else if (featureWithPositiveInteger(lowerMediaFeature, token) |
| 236 // Media features that must have non-negative integer value, | 238 || featureWithPositiveNumber(lowerMediaFeature, token) |
| 237 // or media features that must have non-negative number value, | 239 || featureWithZeroOrOne(lowerMediaFeature, token)) { |
| 238 // or media features that must have (0|1) value. | 240 // Media features that must have non-negative integer value, |
| 239 expValue.value = value->fValue; | 241 // or media features that must have non-negative number valu
e, |
| 240 expValue.unit = CSSPrimitiveValue::CSS_NUMBER; | 242 // or media features that must have (0|1) value. |
| 241 expValue.isValue = true; | 243 expValue.value = token.numericValue(); |
| 244 expValue.unit = CSSPrimitiveValue::CSS_NUMBER; |
| 245 expValue.isValue = true; |
| 246 } |
| 242 } | 247 } |
| 243 | 248 |
| 244 isValid = (expValue.isID || expValue.isValue); | 249 isValid = (expValue.isID || expValue.isValue); |
| 245 | 250 |
| 246 } else if (valueList->size() == 3 && featureWithAspectRatio(lowerMediaFe
ature)) { | 251 } else if (tokenList.size() == 3 && featureWithAspectRatio(lowerMediaFea
ture)) { |
| 247 // Create list of values. | 252 // Create list of values. |
| 248 // Currently accepts only <integer>/<integer>. | 253 // Currently accepts only <integer>/<integer>. |
| 249 // Applicable to device-aspect-ratio and aspec-ratio. | 254 // Applicable to device-aspect-ratio and aspec-ratio. |
| 250 isValid = true; | 255 isValid = true; |
| 251 float numeratorValue = 0; | 256 float numeratorValue = 0; |
| 252 float denominatorValue = 0; | 257 float denominatorValue = 0; |
| 253 // The aspect-ratio must be <integer> (whitespace)? / (whitespace)?
<integer>. | 258 // The aspect-ratio must be <integer> (whitespace)? / (whitespace)?
<integer>. |
| 254 for (unsigned i = 0; i < 3; ++i, valueList->next()) { | 259 for (unsigned i = 0; i < 3; ++i) { |
| 255 const CSSParserValue* value = valueList->current(); | 260 const CSSParserToken& token = tokenList.at(i); |
| 256 if (i != 1 && value->unit == CSSPrimitiveValue::CSS_NUMBER && va
lue->fValue > 0 && value->isInt) { | 261 if (i != 1 && token.unitType() == CSSPrimitiveValue::CSS_NUMBER
&& token.numericValue() > 0 && token.numericValueType() == IntegerValueType) { |
| 257 if (!i) | 262 if (!i) |
| 258 numeratorValue = value->fValue; | 263 numeratorValue = token.numericValue(); |
| 259 else | 264 else |
| 260 denominatorValue = value->fValue; | 265 denominatorValue = token.numericValue(); |
| 261 } else if (i == 1 && value->unit == CSSParserValue::Operator &&
value->iValue == '/') { | 266 } else if (i == 1 && token.type() == DelimiterToken && token.del
imiter() == '/') { |
| 262 continue; | 267 continue; |
| 263 } else { | 268 } else { |
| 264 isValid = false; | 269 isValid = false; |
| 265 break; | 270 break; |
| 266 } | 271 } |
| 267 } | 272 } |
| 268 | 273 |
| 269 if (isValid) { | 274 if (isValid) { |
| 270 expValue.numerator = (unsigned)numeratorValue; | 275 expValue.numerator = (unsigned)numeratorValue; |
| 271 expValue.denominator = (unsigned)denominatorValue; | 276 expValue.denominator = (unsigned)denominatorValue; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 output.append('/'); | 328 output.append('/'); |
| 324 output.append(printNumber(denominator)); | 329 output.append(printNumber(denominator)); |
| 325 } else if (isID) { | 330 } else if (isID) { |
| 326 output.append(getValueName(id)); | 331 output.append(getValueName(id)); |
| 327 } | 332 } |
| 328 | 333 |
| 329 return output.toString(); | 334 return output.toString(); |
| 330 } | 335 } |
| 331 | 336 |
| 332 } // namespace | 337 } // namespace |
| OLD | NEW |