Chromium Code Reviews| 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 12 matching lines...) Expand all Loading... | |
| 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 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 "CSSValueKeywords.h" | |
| 34 #include "core/css/CSSAspectRatioValue.h" | 33 #include "core/css/CSSAspectRatioValue.h" |
| 35 #include "core/css/CSSParserValues.h" | 34 #include "core/css/CSSParserValues.h" |
| 36 #include "core/css/CSSPrimitiveValue.h" | 35 #include "core/css/CSSPrimitiveValue.h" |
| 37 #include "core/html/parser/HTMLParserIdioms.h" | 36 #include "core/html/parser/HTMLParserIdioms.h" |
| 37 #include "wtf/DecimalNumber.h" | |
| 38 #include "wtf/text/StringBuffer.h" | |
| 38 #include "wtf/text/StringBuilder.h" | 39 #include "wtf/text/StringBuilder.h" |
| 39 | 40 |
| 40 namespace WebCore { | 41 namespace WebCore { |
| 41 | 42 |
| 42 using namespace MediaFeatureNames; | 43 using namespace MediaFeatureNames; |
| 43 | 44 |
| 44 static inline bool featureWithCSSValueID(const String& mediaFeature, const CSSPa rserValue* value) | 45 static inline bool featureWithCSSValueID(const String& mediaFeature, const CSSPa rserValue* value) |
| 45 { | 46 { |
| 46 if (!value->id) | 47 if (!value->id) |
| 47 return false; | 48 return false; |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 || m_mediaFeature == orientationMediaFeature | 195 || m_mediaFeature == orientationMediaFeature |
| 195 || m_mediaFeature == aspectRatioMediaFeature | 196 || m_mediaFeature == aspectRatioMediaFeature |
| 196 || m_mediaFeature == minAspectRatioMediaFeature | 197 || m_mediaFeature == minAspectRatioMediaFeature |
| 197 || m_mediaFeature == devicePixelRatioMediaFeature | 198 || m_mediaFeature == devicePixelRatioMediaFeature |
| 198 || m_mediaFeature == resolutionMediaFeature | 199 || m_mediaFeature == resolutionMediaFeature |
| 199 || m_mediaFeature == maxAspectRatioMediaFeature; | 200 || m_mediaFeature == maxAspectRatioMediaFeature; |
| 200 } | 201 } |
| 201 | 202 |
| 202 MediaQueryExp::MediaQueryExp(const MediaQueryExp& other) | 203 MediaQueryExp::MediaQueryExp(const MediaQueryExp& other) |
| 203 : m_mediaFeature(other.mediaFeature()) | 204 : m_mediaFeature(other.mediaFeature()) |
| 204 , m_value(other.value()) | 205 , m_expValue(other.expValue()) |
| 205 { | 206 { |
| 206 } | 207 } |
| 207 | 208 |
| 208 MediaQueryExp::MediaQueryExp(const String& mediaFeature, PassRefPtrWillBeRawPtr< CSSValue> value) | 209 MediaQueryExp::MediaQueryExp(const String& mediaFeature, const MediaQueryExpValu e& expValue) |
| 209 : m_mediaFeature(mediaFeature) | 210 : m_mediaFeature(mediaFeature) |
| 210 , m_value(value) | 211 , m_expValue(expValue) |
| 211 { | 212 { |
| 212 } | 213 } |
| 213 | 214 |
| 214 PassOwnPtrWillBeRawPtr<MediaQueryExp> MediaQueryExp::createIfValid(const String& mediaFeature, CSSParserValueList* valueList) | 215 PassOwnPtrWillBeRawPtr<MediaQueryExp> MediaQueryExp::createIfValid(const String& mediaFeature, CSSParserValueList* valueList) |
| 215 { | 216 { |
| 216 ASSERT(!mediaFeature.isNull()); | 217 ASSERT(!mediaFeature.isNull()); |
| 217 | 218 |
| 218 // FIXME - Creation of CSSValue here may not be thread safe. | 219 MediaQueryExpValue expValue; |
| 219 // It should be replaced by a different way to pass the values to MediaQuery Evaluator. | |
| 220 RefPtrWillBeRawPtr<CSSValue> cssValue = nullptr; | |
| 221 bool isValid = false; | 220 bool isValid = false; |
| 222 String lowerMediaFeature = attemptStaticStringCreation(mediaFeature.lower()) ; | 221 String lowerMediaFeature = attemptStaticStringCreation(mediaFeature.lower()) ; |
| 223 | 222 |
| 224 // Create value for media query expression that must have 1 or more values. | 223 // Create value for media query expression that must have 1 or more values. |
| 225 if (valueList && valueList->size() > 0) { | 224 if (valueList && valueList->size() > 0) { |
| 226 if (valueList->size() == 1) { | 225 if (valueList->size() == 1) { |
| 227 CSSParserValue* value = valueList->current(); | 226 CSSParserValue* value = valueList->current(); |
| 228 ASSERT(value); | 227 ASSERT(value); |
| 229 | 228 |
| 230 if (featureWithCSSValueID(lowerMediaFeature, value)) { | 229 if (featureWithCSSValueID(lowerMediaFeature, value) && featureWithVa lidIdent(lowerMediaFeature, value->id)) { |
| 231 // Media features that use CSSValueIDs. | 230 // Media features that use CSSValueIDs. |
| 232 cssValue = CSSPrimitiveValue::createIdentifier(value->id); | 231 expValue.id = value->id; |
| 233 if (!featureWithValidIdent(lowerMediaFeature, toCSSPrimitiveValu e(cssValue.get())->getValueID())) | 232 expValue.unit = CSSPrimitiveValue::CSS_VALUE_ID; |
| 234 cssValue.clear(); | 233 expValue.isID = true; |
| 235 } else if (featureWithValidDensity(lowerMediaFeature, value)) { | 234 } else if (featureWithValidDensity(lowerMediaFeature, value) |
| 236 // Media features that must have non-negative <density>, ie. dpp x, dpi or dpcm. | 235 || featureWithValidPositiveLength(lowerMediaFeature, value)) { |
| 237 cssValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiv eValue::UnitTypes) value->unit); | 236 // Media features that must have non-negative <density>, ie. dpp x, dpi or dpcm, |
| 238 } else if (featureWithValidPositiveLength(lowerMediaFeature, value)) { | 237 // or Media features that must have non-negative <length> or num ber value. |
| 239 // Media features that must have non-negative <lenght> or number value. | 238 expValue.value = value->fValue; |
| 240 cssValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiv eValue::UnitTypes) value->unit); | 239 expValue.unit = value->unit; |
| 241 } else if (featureWithPositiveInteger(lowerMediaFeature, value)) { | 240 expValue.isValue = true; |
| 242 // Media features that must have non-negative integer value. | 241 expValue.isInteger = value->isInt; |
| 243 cssValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitive Value::CSS_NUMBER); | 242 } else if (featureWithPositiveInteger(lowerMediaFeature, value) |
| 244 } else if (featureWithPositiveNumber(lowerMediaFeature, value)) { | 243 || featureWithPositiveNumber(lowerMediaFeature, value) |
| 245 // Media features that must have non-negative number value. | 244 || featureWithZeroOrOne(lowerMediaFeature, value)) { |
| 246 cssValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitive Value::CSS_NUMBER); | 245 // Media features that must have non-negative integer value, |
| 247 } else if (featureWithZeroOrOne(lowerMediaFeature, value)) { | 246 // or media features that must have non-negative number value, |
| 248 // Media features that must have (0|1) value. | 247 // or media features that must have (0|1) value. |
| 249 cssValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitive Value::CSS_NUMBER); | 248 expValue.value = value->fValue; |
| 249 expValue.unit = CSSPrimitiveValue::CSS_NUMBER; | |
| 250 expValue.isValue = true; | |
| 251 expValue.isInteger = value->isInt; | |
| 250 } | 252 } |
| 251 | 253 |
| 252 isValid = cssValue; | 254 isValid = (expValue.isID || expValue.isValue); |
| 253 | 255 |
| 254 } else if (valueList->size() == 3 && featureWithAspectRatio(lowerMediaFe ature)) { | 256 } else if (valueList->size() == 3 && featureWithAspectRatio(lowerMediaFe ature)) { |
| 255 // Create list of values. | 257 // Create list of values. |
| 256 // Currently accepts only <integer>/<integer>. | 258 // Currently accepts only <integer>/<integer>. |
| 257 // Applicable to device-aspect-ratio and aspec-ratio. | 259 // Applicable to device-aspect-ratio and aspec-ratio. |
| 258 isValid = true; | 260 isValid = true; |
| 259 float numeratorValue = 0; | 261 float numeratorValue = 0; |
| 260 float denominatorValue = 0; | 262 float denominatorValue = 0; |
| 261 // The aspect-ratio must be <integer> (whitespace)? / (whitespace)? <integer>. | 263 // The aspect-ratio must be <integer> (whitespace)? / (whitespace)? <integer>. |
| 262 for (unsigned i = 0; i < 3; ++i, valueList->next()) { | 264 for (unsigned i = 0; i < 3; ++i, valueList->next()) { |
| 263 const CSSParserValue* value = valueList->current(); | 265 const CSSParserValue* value = valueList->current(); |
| 264 if (i != 1 && value->unit == CSSPrimitiveValue::CSS_NUMBER && va lue->fValue > 0 && value->isInt) { | 266 if (i != 1 && value->unit == CSSPrimitiveValue::CSS_NUMBER && va lue->fValue > 0 && value->isInt) { |
| 265 if (!i) | 267 if (!i) |
| 266 numeratorValue = value->fValue; | 268 numeratorValue = value->fValue; |
| 267 else | 269 else |
| 268 denominatorValue = value->fValue; | 270 denominatorValue = value->fValue; |
| 269 } else if (i == 1 && value->unit == CSSParserValue::Operator && value->iValue == '/') { | 271 } else if (i == 1 && value->unit == CSSParserValue::Operator && value->iValue == '/') { |
| 270 continue; | 272 continue; |
| 271 } else { | 273 } else { |
| 272 isValid = false; | 274 isValid = false; |
| 273 break; | 275 break; |
| 274 } | 276 } |
| 275 } | 277 } |
| 276 | 278 |
| 277 if (isValid) | 279 if (isValid) { |
| 278 cssValue = CSSAspectRatioValue::create(numeratorValue, denominat orValue); | 280 expValue.numerator = (unsigned)numeratorValue; |
| 281 expValue.denominator = (unsigned)denominatorValue; | |
| 282 expValue.isRatio = true; | |
| 283 } | |
| 279 } | 284 } |
| 280 } else if (featureWithoutValue(lowerMediaFeature)) { | 285 } else if (featureWithoutValue(lowerMediaFeature)) { |
| 281 isValid = true; | 286 isValid = true; |
| 282 } | 287 } |
| 283 | 288 |
| 284 if (!isValid) | 289 if (!isValid) |
| 285 return nullptr; | 290 return nullptr; |
| 286 | 291 |
| 287 return adoptPtrWillBeNoop(new MediaQueryExp(lowerMediaFeature, cssValue)); | 292 return adoptPtrWillBeNoop(new MediaQueryExp(lowerMediaFeature, expValue)); |
| 288 } | 293 } |
| 289 | 294 |
| 290 MediaQueryExp::~MediaQueryExp() | 295 MediaQueryExp::~MediaQueryExp() |
| 291 { | 296 { |
| 292 } | 297 } |
| 293 | 298 |
| 299 bool MediaQueryExp::operator==(const MediaQueryExp& other) const | |
| 300 { | |
| 301 return (other.m_mediaFeature == m_mediaFeature) | |
| 302 && ((!other.m_expValue.set() && !m_expValue.set()) | |
| 303 || (other.m_expValue.set() && m_expValue.set() && other.m_expValue.e quals(m_expValue))); | |
| 304 } | |
| 305 | |
| 294 String MediaQueryExp::serialize() const | 306 String MediaQueryExp::serialize() const |
| 295 { | 307 { |
| 296 StringBuilder result; | 308 StringBuilder result; |
| 297 result.append("("); | 309 result.append("("); |
| 298 result.append(m_mediaFeature.lower()); | 310 result.append(m_mediaFeature.lower()); |
| 299 if (m_value) { | 311 if (m_expValue.set()) { |
| 300 result.append(": "); | 312 result.append(": "); |
| 301 result.append(m_value->cssText()); | 313 result.append(m_expValue.cssText()); |
| 302 } | 314 } |
| 303 result.append(")"); | 315 result.append(")"); |
| 304 | 316 |
| 305 return result.toString(); | 317 return result.toString(); |
| 306 } | 318 } |
| 307 | 319 |
| 320 static String unitToString(unsigned short unit) | |
|
eseidel
2014/04/22 16:22:23
I wonder if this doesn't belong on CSSPrimitiveVal
| |
| 321 { | |
| 322 switch (unit) { | |
| 323 case CSSPrimitiveValue::CSS_PERCENTAGE: | |
| 324 return String("%"); | |
| 325 case CSSPrimitiveValue::CSS_EMS: | |
| 326 return String("em"); | |
| 327 case CSSPrimitiveValue::CSS_EXS: | |
| 328 return String("ex"); | |
| 329 case CSSPrimitiveValue::CSS_REMS: | |
| 330 return String("rem"); | |
| 331 case CSSPrimitiveValue::CSS_CHS: | |
| 332 return String("ch"); | |
| 333 case CSSPrimitiveValue::CSS_PX: | |
| 334 return String("px"); | |
| 335 case CSSPrimitiveValue::CSS_CM: | |
| 336 return String("cm"); | |
| 337 case CSSPrimitiveValue::CSS_DPPX: | |
| 338 return String("dppx"); | |
| 339 case CSSPrimitiveValue::CSS_DPI: | |
| 340 return String("dpi"); | |
| 341 case CSSPrimitiveValue::CSS_DPCM: | |
| 342 return String("dpcm"); | |
| 343 } | |
| 344 return String(); | |
| 345 } | |
| 346 | |
| 347 static String printNumber(double number) | |
| 348 { | |
| 349 DecimalNumber decimal(number); | |
| 350 StringBuffer<LChar> buffer(decimal.bufferLengthForStringDecimal()); | |
| 351 decimal.toStringDecimal(buffer.characters(), buffer.length()); | |
| 352 return String::adopt(buffer); | |
| 353 } | |
| 354 | |
| 355 String MediaQueryExpValue::cssText() const | |
| 356 { | |
| 357 StringBuilder output; | |
| 358 if (isValue) { | |
| 359 output.append(printNumber(value)); | |
| 360 output.append(unitToString(unit)); | |
| 361 } else if (isRatio) { | |
| 362 output.append(printNumber(numerator)); | |
| 363 output.append("/"); | |
| 364 output.append(printNumber(denominator)); | |
| 365 } else if (isID) { | |
| 366 output.append(getValueName(id)); | |
| 367 } | |
| 368 | |
| 369 return output.toString(); | |
| 370 } | |
| 371 | |
| 308 } // namespace | 372 } // namespace |
| OLD | NEW |