diff options
Diffstat (limited to 'Source/WebCore/css/CSSParser.cpp')
-rw-r--r-- | Source/WebCore/css/CSSParser.cpp | 536 |
1 files changed, 433 insertions, 103 deletions
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index d16537e6c..8ff97b8e9 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -6,6 +6,7 @@ * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2012 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -43,7 +44,6 @@ #include "CSSMediaRule.h" #include "CSSPageRule.h" #include "CSSPrimitiveValue.h" -#include "CSSProperty.h" #include "CSSPropertySourceData.h" #include "CSSReflectValue.h" #include "CSSSelector.h" @@ -53,7 +53,6 @@ #include "CSSValueKeywords.h" #include "CSSValueList.h" #include "CSSValuePool.h" -#include "StylePropertyShorthand.h" #if ENABLE(CSS_VARIABLES) #include "CSSVariableValue.h" #endif @@ -271,6 +270,9 @@ CSSParser::CSSParser(const CSSParserContext& context) , m_lastSelectorLineNumber(0) , m_allowImportRules(true) , m_allowNamespaceDeclarations(true) +#if ENABLE(CSS_DEVICE_ADAPTATION) + , m_inViewport(false) +#endif , m_selectorVector(adoptPtr(new CSSSelectorVector)) { #if YYDEBUG > 0 @@ -337,11 +339,12 @@ AtomicString CSSParserString::lowerSubstring(unsigned position, unsigned length) return AtomicString(result); } -void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix) +void CSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength) { - m_parsedTextPrefixLength = strlen(prefix); + m_parsedTextPrefixLength = prefixLength; unsigned stringLength = string.length(); - unsigned length = stringLength + m_parsedTextPrefixLength + strlen(suffix) + 1; + unsigned length = stringLength + m_parsedTextPrefixLength + suffixLength + 1; + m_length = length; if (!stringLength || string.is8Bit()) { m_dataStart8 = adoptArrayPtr(new LChar[length]); @@ -352,7 +355,7 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char memcpy(m_dataStart8.get() + m_parsedTextPrefixLength, string.characters8(), stringLength * sizeof(LChar)); unsigned start = m_parsedTextPrefixLength + stringLength; - unsigned end = start + strlen(suffix); + unsigned end = start + suffixLength; for (unsigned i = start; i < end; i++) m_dataStart8[i] = suffix[i - start]; @@ -362,7 +365,6 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char m_currentCharacter8 = m_dataStart8.get(); m_currentCharacter16 = 0; setTokenStart<LChar>(m_currentCharacter8); - m_length = length; m_lexFunc = &CSSParser::realLex<LChar>; return; } @@ -374,7 +376,7 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char memcpy(m_dataStart16.get() + m_parsedTextPrefixLength, string.characters(), stringLength * sizeof(UChar)); unsigned start = m_parsedTextPrefixLength + stringLength; - unsigned end = start + strlen(suffix); + unsigned end = start + suffixLength; for (unsigned i = start; i < end; i++) m_dataStart16[i] = suffix[i - start]; @@ -384,7 +386,6 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char m_currentCharacter8 = 0; m_currentCharacter16 = m_dataStart16.get(); setTokenStart<UChar>(m_currentCharacter16); - m_length = length; m_lexFunc = &CSSParser::realLex<UChar>; } @@ -829,8 +830,8 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int if (valueID == CSSValueNone || valueID == CSSValueEdges) return true; break; - case CSSPropertyWebkitLineBreak: // normal | after-white-space - if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace) + case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space + if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace) return true; break; case CSSPropertyWebkitLineSnap: @@ -1572,7 +1573,7 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode case CSSPrimitiveValue::CSS_TURN: b = (unitflags & FAngle); break; -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSSPrimitiveValue::CSS_DPPX: case CSSPrimitiveValue::CSS_DPI: case CSSPrimitiveValue::CSS_DPCM: @@ -1601,8 +1602,8 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSP ASSERT(isCalculation(value)); return CSSPrimitiveValue::create(m_parsedCalculation.release()); } - -#if ENABLE(CSS_IMAGE_RESOLUTION) + +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS) || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN) @@ -1664,7 +1665,7 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifi return createPrimitiveNumericValue(value); if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN) return createPrimitiveNumericValue(value); -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM) return createPrimitiveNumericValue(value); #endif @@ -1729,6 +1730,11 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return true; } +#if ENABLE(CSS_DEVICE_ADAPTATION) + if (inViewport()) + return parseViewportProperty(propId, important); +#endif + bool validPrimitive = false; RefPtr<CSSValue> parsedValue; @@ -1876,15 +1882,18 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) coords.append(int(value->fValue)); value = m_valueList->next(); } + bool hasHotSpot = false; IntPoint hotSpot(-1, -1); int nrcoords = coords.size(); if (nrcoords > 0 && nrcoords != 2) return false; - if (nrcoords == 2) + if (nrcoords == 2) { + hasHotSpot = true; hotSpot = IntPoint(coords[0], coords[1]); + } if (!uri.isNull()) - list->append(CSSCursorImageValue::create(completeURL(uri), hotSpot)); + list->append(CSSCursorImageValue::create(completeURL(uri), hasHotSpot, hotSpot)); if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ','))) return false; @@ -2853,6 +2862,17 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) // These properties should be handled before in isValidKeywordPropertyAndValue(). ASSERT_NOT_REACHED(); return false; +#if ENABLE(CSS_DEVICE_ADAPTATION) + // Properties bellow are validated inside parseViewportProperty, because we + // check for parser state inViewportScope. We need to invalidate if someone + // adds them outside a @viewport rule. + case CSSPropertyMaxZoom: + case CSSPropertyMinZoom: + case CSSPropertyOrientation: + case CSSPropertyUserZoom: + validPrimitive = false; + break; +#endif #if ENABLE(SVG) default: return parseSVGValue(propId, important); @@ -7210,76 +7230,241 @@ public: , m_allowSingleArgument(false) , m_unit(CSSParser::FUnknown) { - if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scalex(") || equalIgnoringCase(name, "scaley(") || equalIgnoringCase(name, "scalez(")) { - m_unit = CSSParser::FNumber; - if (equalIgnoringCase(name, "scale(")) - m_type = WebKitCSSTransformValue::ScaleTransformOperation; - else if (equalIgnoringCase(name, "scalex(")) - m_type = WebKitCSSTransformValue::ScaleXTransformOperation; - else if (equalIgnoringCase(name, "scaley(")) - m_type = WebKitCSSTransformValue::ScaleYTransformOperation; - else - m_type = WebKitCSSTransformValue::ScaleZTransformOperation; - } else if (equalIgnoringCase(name, "scale3d(")) { - m_type = WebKitCSSTransformValue::Scale3DTransformOperation; - m_argCount = 5; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "rotate(")) { - m_type = WebKitCSSTransformValue::RotateTransformOperation; - m_unit = CSSParser::FAngle; - } else if (equalIgnoringCase(name, "rotatex(") || - equalIgnoringCase(name, "rotatey(") || - equalIgnoringCase(name, "rotatez(")) { - m_unit = CSSParser::FAngle; - if (equalIgnoringCase(name, "rotatex(")) - m_type = WebKitCSSTransformValue::RotateXTransformOperation; - else if (equalIgnoringCase(name, "rotatey(")) - m_type = WebKitCSSTransformValue::RotateYTransformOperation; - else - m_type = WebKitCSSTransformValue::RotateZTransformOperation; - } else if (equalIgnoringCase(name, "rotate3d(")) { - m_type = WebKitCSSTransformValue::Rotate3DTransformOperation; - m_argCount = 7; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "skewx(") || equalIgnoringCase(name, "skewy(")) { - m_unit = CSSParser::FAngle; - if (equalIgnoringCase(name, "skew(")) + const UChar* characters; + unsigned nameLength = name.length(); + + const unsigned longestNameLength = 12; + UChar characterBuffer[longestNameLength]; + if (name.is8Bit()) { + unsigned length = std::min(longestNameLength, nameLength); + const LChar* characters8 = name.characters8(); + for (unsigned i = 0; i < length; ++i) + characterBuffer[i] = characters8[i]; + characters = characterBuffer; + } else + characters = name.characters16(); + + switch (nameLength) { + case 5: + // Valid name: skew(. + if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[1] == 'k') || (characters[1] == 'K')) + & ((characters[2] == 'e') || (characters[2] == 'E')) + & ((characters[3] == 'w') || (characters[3] == 'W')) + & (characters[4] == '(')) { + m_unit = CSSParser::FAngle; m_type = WebKitCSSTransformValue::SkewTransformOperation; - else if (equalIgnoringCase(name, "skewx(")) - m_type = WebKitCSSTransformValue::SkewXTransformOperation; - else - m_type = WebKitCSSTransformValue::SkewYTransformOperation; - } else if (equalIgnoringCase(name, "translate(") || equalIgnoringCase(name, "translatex(") || equalIgnoringCase(name, "translatey(") || equalIgnoringCase(name, "translatez(")) { - m_unit = CSSParser::FLength | CSSParser::FPercent; - if (equalIgnoringCase(name, "translate(")) + m_allowSingleArgument = true; + m_argCount = 3; + } + break; + case 6: + // Valid names: skewx(, skewy(, scale(. + if ((characters[1] == 'c') || (characters[1] == 'C')) { + if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'l') || (characters[3] == 'L')) + & ((characters[4] == 'e') || (characters[4] == 'E')) + & (characters[5] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleTransformOperation; + m_allowSingleArgument = true; + m_argCount = 3; + } + } else if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[1] == 'k') || (characters[1] == 'K')) + & ((characters[2] == 'e') || (characters[2] == 'E')) + & ((characters[3] == 'w') || (characters[3] == 'W')) + & (characters[5] == '(')) { + if ((characters[4] == 'x') || (characters[4] == 'X')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::SkewXTransformOperation; + } else if ((characters[4] == 'y') || (characters[4] == 'Y')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::SkewYTransformOperation; + } + } + break; + case 7: + // Valid names: matrix(, rotate(, scalex(, scaley(, scalez(. + if ((characters[0] == 'm') || (characters[0] == 'M')) { + if (((characters[1] == 'a') || (characters[1] == 'A')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'r') || (characters[3] == 'R')) + & ((characters[4] == 'i') || (characters[4] == 'I')) + & ((characters[5] == 'x') || (characters[5] == 'X')) + & (characters[6] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::MatrixTransformOperation; + m_argCount = 11; + } + } else if ((characters[0] == 'r') || (characters[0] == 'R')) { + if (((characters[1] == 'o') || (characters[1] == 'O')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'a') || (characters[3] == 'A')) + & ((characters[4] == 't') || (characters[4] == 'T')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & (characters[6] == '(')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateTransformOperation; + } + } else if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[1] == 'c') || (characters[1] == 'C')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'l') || (characters[3] == 'L')) + & ((characters[4] == 'e') || (characters[4] == 'E')) + & (characters[6] == '(')) { + if ((characters[5] == 'x') || (characters[5] == 'X')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleXTransformOperation; + } else if ((characters[5] == 'y') || (characters[5] == 'Y')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleYTransformOperation; + } else if ((characters[5] == 'z') || (characters[5] == 'Z')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleZTransformOperation; + } + } + break; + case 8: + // Valid names: rotatex(, rotatey(, rotatez(, scale3d(. + if ((characters[0] == 's') || (characters[0] == 'S')) { + if (((characters[1] == 'c') || (characters[1] == 'C')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'l') || (characters[3] == 'L')) + & ((characters[4] == 'e') || (characters[4] == 'E')) + & (characters[5] == '3') + & ((characters[6] == 'd') || (characters[6] == 'D')) + & (characters[7] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::Scale3DTransformOperation; + m_argCount = 5; + } + } else if (((characters[0] == 'r') || (characters[0] == 'R')) + & ((characters[1] == 'o') || (characters[1] == 'O')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'a') || (characters[3] == 'A')) + & ((characters[4] == 't') || (characters[4] == 'T')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & (characters[7] == '(')) { + if ((characters[6] == 'x') || (characters[6] == 'X')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateXTransformOperation; + } else if ((characters[6] == 'y') || (characters[6] == 'Y')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateYTransformOperation; + } else if ((characters[6] == 'z') || (characters[6] == 'Z')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateZTransformOperation; + } + } + break; + case 9: + // Valid names: matrix3d(, rotate3d(. + if ((characters[0] == 'm') || (characters[0] == 'M')) { + if (((characters[1] == 'a') || (characters[1] == 'A')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'r') || (characters[3] == 'R')) + & ((characters[4] == 'i') || (characters[4] == 'I')) + & ((characters[5] == 'x') || (characters[5] == 'X')) + & (characters[6] == '3') + & ((characters[7] == 'd') || (characters[7] == 'D')) + & (characters[8] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::Matrix3DTransformOperation; + m_argCount = 31; + } + } else if (((characters[0] == 'r') || (characters[0] == 'R')) + & ((characters[1] == 'o') || (characters[1] == 'O')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'a') || (characters[3] == 'A')) + & ((characters[4] == 't') || (characters[4] == 'T')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & (characters[6] == '3') + & ((characters[7] == 'd') || (characters[7] == 'D')) + & (characters[8] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::Rotate3DTransformOperation; + m_argCount = 7; + } + break; + case 10: + // Valid name: translate(. + if (((characters[0] == 't') || (characters[0] == 'T')) + & ((characters[1] == 'r') || (characters[1] == 'R')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'n') || (characters[3] == 'N')) + & ((characters[4] == 's') || (characters[4] == 'S')) + & ((characters[5] == 'l') || (characters[5] == 'L')) + & ((characters[6] == 'a') || (characters[6] == 'A')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'e') || (characters[8] == 'E')) + & (characters[9] == '(')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; m_type = WebKitCSSTransformValue::TranslateTransformOperation; - else if (equalIgnoringCase(name, "translatex(")) - m_type = WebKitCSSTransformValue::TranslateXTransformOperation; - else if (equalIgnoringCase(name, "translatey(")) - m_type = WebKitCSSTransformValue::TranslateYTransformOperation; - else - m_type = WebKitCSSTransformValue::TranslateZTransformOperation; - } else if (equalIgnoringCase(name, "translate3d(")) { - m_type = WebKitCSSTransformValue::Translate3DTransformOperation; - m_argCount = 5; - m_unit = CSSParser::FLength | CSSParser::FPercent; - } else if (equalIgnoringCase(name, "matrix(")) { - m_type = WebKitCSSTransformValue::MatrixTransformOperation; - m_argCount = 11; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "matrix3d(")) { - m_type = WebKitCSSTransformValue::Matrix3DTransformOperation; - m_argCount = 31; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "perspective(")) { - m_type = WebKitCSSTransformValue::PerspectiveTransformOperation; - m_unit = CSSParser::FNumber; - } - - if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "translate(")) { - m_allowSingleArgument = true; - m_argCount = 3; - } + m_allowSingleArgument = true; + m_argCount = 3; + } + break; + case 11: + // Valid names: translatex(, translatey(, translatez(. + if (((characters[0] == 't') || (characters[0] == 'T')) + & ((characters[1] == 'r') || (characters[1] == 'R')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'n') || (characters[3] == 'N')) + & ((characters[4] == 's') || (characters[4] == 'S')) + & ((characters[5] == 'l') || (characters[5] == 'L')) + & ((characters[6] == 'a') || (characters[6] == 'A')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'e') || (characters[8] == 'E')) + & (characters[10] == '(')) { + if ((characters[9] == 'x') || (characters[9] == 'X')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::TranslateXTransformOperation; + } else if ((characters[9] == 'y') || (characters[9] == 'Y')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::TranslateYTransformOperation; + } else if ((characters[9] == 'z') || (characters[9] == 'Z')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::TranslateZTransformOperation; + } + } + break; + case 12: + // Valid names: perspective(, translate3d(. + if ((characters[0] == 'p') || (characters[0] == 'P')) { + if (((characters[1] == 'e') || (characters[1] == 'E')) + & ((characters[2] == 'r') || (characters[2] == 'R')) + & ((characters[3] == 's') || (characters[3] == 'S')) + & ((characters[4] == 'p') || (characters[4] == 'P')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & ((characters[6] == 'c') || (characters[6] == 'C')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'i') || (characters[8] == 'I')) + & ((characters[9] == 'v') || (characters[9] == 'V')) + & ((characters[10] == 'e') || (characters[10] == 'E')) + & (characters[11] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::PerspectiveTransformOperation; + } + } else if (((characters[0] == 't') || (characters[0] == 'T')) + & ((characters[1] == 'r') || (characters[1] == 'R')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'n') || (characters[3] == 'N')) + & ((characters[4] == 's') || (characters[4] == 'S')) + & ((characters[5] == 'l') || (characters[5] == 'L')) + & ((characters[6] == 'a') || (characters[6] == 'A')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'e') || (characters[8] == 'E')) + & (characters[9] == '3') + & ((characters[10] == 'd') || (characters[10] == 'D')) + & (characters[11] == '(')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::Translate3DTransformOperation; + m_argCount = 5; + } + break; + } // end switch () } WebKitCSSTransformValue::TransformOperationType type() const { return m_type; } @@ -8009,6 +8194,8 @@ bool CSSParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& prop switch (propId) { case CSSPropertyWebkitPerspectiveOrigin: + if (m_valueList->size() > 2) + return false; parseFillPosition(m_valueList.get(), value, value2); break; case CSSPropertyWebkitPerspectiveOriginX: { @@ -9010,7 +9197,7 @@ inline void CSSParser::detectNumberToken(CharacterType* type, int length) case 'd': if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'g')) m_token = DEGS; -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) else if (length > 2 && isASCIIAlphaCaselessEqual(type[1], 'p')) { if (length == 4) { // There is a discussion about the name of this unit on www-style. @@ -9185,6 +9372,13 @@ inline void CSSParser::detectAtToken(int length, bool hasEscape) m_token = FONT_FACE_SYM; return; +#if ENABLE(SHADOW_DOM) + case 'h': + if (length == 5 && isEqualToCSSIdentifier(name + 2, "ost")) + m_token = HOST_SYM; + return; +#endif + case 'i': if (length == 7 && isEqualToCSSIdentifier(name + 2, "mport")) { m_parsingMode = MediaQueryMode; @@ -9308,8 +9502,15 @@ inline void CSSParser::detectAtToken(int length, bool hasEscape) return; case 17: - if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-selector")) + if (hasEscape) + return; + + if (isASCIIAlphaCaselessEqual(name[16], 'r') && isEqualToCSSIdentifier(name + 2, "webkit-selecto")) m_token = WEBKIT_SELECTOR_SYM; +#if ENABLE(CSS_DEVICE_ADAPTATION) + else if (isASCIIAlphaCaselessEqual(name[16], 't') && isEqualToCSSIdentifier(name + 2, "webkit-viewpor")) + m_token = WEBKIT_VIEWPORT_RULE_SYM; +#endif return; case 18: @@ -10017,6 +10218,24 @@ StyleRuleBase* CSSParser::createFontFaceRule() return result; } +#if ENABLE(SHADOW_DOM) +StyleRuleBase* CSSParser::createHostRule(RuleList* rules) +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + RefPtr<StyleRuleHost> rule; + if (rules) + rule = StyleRuleHost::create(*rules); + else { + RuleList emptyRules; + rule = StyleRuleHost::create(emptyRules); + } + StyleRuleHost* result = rule.get(); + m_parsedRules.append(rule.release()); + processAndAddNewRuleToSourceTreeIfNeeded(); + return result; +} +#endif + void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri) { if (!m_styleSheet || !m_allowNamespaceDeclarations) @@ -10038,7 +10257,7 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre { AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace; QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace); - if (!specifiers->isUnknownPseudoElement()) { + if (!specifiers->isCustomPseudoElement()) { specifiers->setTag(tag); return; } @@ -10047,7 +10266,7 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre CSSParserSelector* history = specifiers; while (history->tagHistory()) { history = history->tagHistory(); - if (history->isUnknownPseudoElement() || history->hasShadowDescendant()) + if (history->isCustomPseudoElement() || history->hasShadowDescendant()) lastShadowDescendant = history; } @@ -10066,12 +10285,12 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre CSSParserSelector* CSSParser::updateSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier) { - if (newSpecifier->isUnknownPseudoElement()) { + if (newSpecifier->isCustomPseudoElement()) { // Unknown pseudo element always goes at the top of selector chain. newSpecifier->appendTagHistory(CSSSelector::ShadowDescendant, sinkFloatingSelector(specifiers)); return newSpecifier; } - if (specifiers->isUnknownPseudoElement()) { + if (specifiers->isCustomPseudoElement()) { // Specifiers for unknown pseudo element go right behind it in the chain. specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowDescendant); return specifiers; @@ -10364,6 +10583,102 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed) resetPropertyRange(); } +#if ENABLE(CSS_DEVICE_ADAPTATION) +StyleRuleBase* CSSParser::createViewportRule() +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + + RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); + + rule->setProperties(createStylePropertySet()); + clearProperties(); + + StyleRuleViewport* result = rule.get(); + m_parsedRules.append(rule.release()); + processAndAddNewRuleToSourceTreeIfNeeded(); + + return result; +} + +bool CSSParser::parseViewportProperty(CSSPropertyID propId, bool important) +{ + CSSParserValue* value = m_valueList->current(); + if (!value) + return false; + + int id = value->id; + bool validPrimitive = false; + + switch (propId) { + case CSSPropertyMinWidth: // auto | device-width | device-height | <length> | <percentage> + case CSSPropertyMaxWidth: + case CSSPropertyMinHeight: + case CSSPropertyMaxHeight: + if (id == CSSValueAuto || id == CSSValueDeviceWidth || id == CSSValueDeviceHeight) + validPrimitive = true; + else + validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg)); + break; + case CSSPropertyWidth: // shorthand + return parseViewportShorthand(propId, CSSPropertyMinWidth, CSSPropertyMaxWidth, important); + case CSSPropertyHeight: + return parseViewportShorthand(propId, CSSPropertyMinHeight, CSSPropertyMaxHeight, important); + case CSSPropertyMinZoom: // auto | <number> | <percentage> + case CSSPropertyMaxZoom: + case CSSPropertyZoom: + if (id == CSSValueAuto) + validPrimitive = true; + else + validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg)); + break; + case CSSPropertyUserZoom: // zoom | fixed + if (id == CSSValueZoom || id == CSSValueFixed) + validPrimitive = true; + break; + case CSSPropertyOrientation: // auto | portrait | landscape + if (id == CSSValueAuto || id == CSSValuePortrait || id == CSSValueLandscape) + validPrimitive = true; + default: + break; + } + + RefPtr<CSSValue> parsedValue; + if (validPrimitive) { + parsedValue = parseValidPrimitive(id, value); + m_valueList->next(); + } + + if (parsedValue) { + if (!m_valueList->current() || inShorthand()) { + addProperty(propId, parsedValue.release(), important); + return true; + } + } + + return false; +} + +bool CSSParser::parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important) +{ + unsigned numValues = m_valueList->size(); + + if (numValues > 2) + return false; + + ShorthandScope scope(this, propId); + + if (!parseViewportProperty(first, important)) + return false; + + // If just one value is supplied, the second value + // is implicitly initialized with the first value. + if (numValues == 1) + m_valueList->previous(); + + return parseViewportProperty(second, important); +} +#endif + template <typename CharacterType> static CSSPropertyID cssPropertyID(const CharacterType* propertyName, unsigned length) { @@ -10556,20 +10871,16 @@ static bool isCSSTokenizerURL(const String& string) return isCSSTokenizerURL(string.characters(), length); } -// We use single quotes for now because markup.cpp uses double quotes. -String quoteCSSString(const String& string) -{ - // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds - // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned. - if (string.length() >= (std::numeric_limits<unsigned>::max() / 3) - 2) - return ""; +template <typename CharacterType> +static inline String quoteCSSStringInternal(const CharacterType* characters, unsigned length) +{ // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one. // Please see below for the actual logic. unsigned quotedStringSize = 2; // Two quotes surrounding the entire string. bool afterEscape = false; - for (unsigned i = 0; i < string.length(); ++i) { - UChar ch = string[i]; + for (unsigned i = 0; i < length; ++i) { + CharacterType ch = characters[i]; if (ch == '\\' || ch == '\'') { quotedStringSize += 2; afterEscape = false; @@ -10582,12 +10893,12 @@ String quoteCSSString(const String& string) } } - StringBuffer<UChar> buffer(quotedStringSize); + StringBuffer<CharacterType> buffer(quotedStringSize); unsigned index = 0; buffer[index++] = '\''; afterEscape = false; - for (unsigned i = 0; i < string.length(); ++i) { - UChar ch = string[i]; + for (unsigned i = 0; i < length; ++i) { + CharacterType ch = characters[i]; if (ch == '\\' || ch == '\'') { buffer[index++] = '\\'; buffer[index++] = ch; @@ -10610,6 +10921,25 @@ String quoteCSSString(const String& string) return String::adopt(buffer); } +// We use single quotes for now because markup.cpp uses double quotes. +String quoteCSSString(const String& string) +{ + // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds + // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned. + + unsigned length = string.length(); + + if (!length) + return String("\'\'"); + + if (length > std::numeric_limits<unsigned>::max() / 3 - 2) + return emptyString(); + + if (string.is8Bit()) + return quoteCSSStringInternal(string.characters8(), length); + return quoteCSSStringInternal(string.characters16(), length); +} + String quoteCSSStringIfNeeded(const String& string) { return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string); |