summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/css/CSSParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/css/CSSParser.cpp')
-rw-r--r--Source/WebCore/css/CSSParser.cpp348
1 files changed, 270 insertions, 78 deletions
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp
index df8816c..02733ae 100644
--- a/Source/WebCore/css/CSSParser.cpp
+++ b/Source/WebCore/css/CSSParser.cpp
@@ -36,6 +36,7 @@
#include "CSSImportRule.h"
#include "CSSInheritedValue.h"
#include "CSSInitialValue.h"
+#include "CSSLineBoxContainValue.h"
#include "CSSMediaRule.h"
#include "CSSMutableStyleDeclaration.h"
#include "CSSPageRule.h"
@@ -72,6 +73,7 @@
#include "WebKitCSSKeyframesRule.h"
#include "WebKitCSSTransformValue.h"
#include <limits.h>
+#include <wtf/HexNumber.h>
#include <wtf/dtoa.h>
#include <wtf/text/StringBuffer.h>
@@ -97,6 +99,7 @@ using namespace WTF;
namespace WebCore {
static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
+static const double MAX_SCALE = 1000000;
static bool equal(const CSSParserString& a, const char* b)
{
@@ -177,6 +180,7 @@ CSSParser::~CSSParser()
fastFree(m_data);
fastDeleteAllValues(m_floatingSelectors);
+ deleteAllValues(m_floatingSelectorVectors);
deleteAllValues(m_floatingValueLists);
deleteAllValues(m_floatingFunctions);
}
@@ -698,10 +702,11 @@ bool CSSParser::parseValue(int propId, bool important)
else
return parseQuotes(propId, important);
break;
- case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | inherit
- if (id == CSSValueNormal ||
- id == CSSValueEmbed ||
- id == CSSValueBidiOverride)
+ case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | inherit
+ if (id == CSSValueNormal
+ || id == CSSValueEmbed
+ || id == CSSValueBidiOverride
+ || id == CSSValueWebkitIsolate)
validPrimitive = true;
break;
@@ -838,9 +843,10 @@ bool CSSParser::parseValue(int propId, bool important)
break;
case CSSPropertyTextAlign:
- // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit
- if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitCenter) || id == CSSValueStart || id == CSSValueEnd ||
- value->unit == CSSPrimitiveValue::CSS_STRING)
+ // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent |
+ // start | end | <string> | inherit
+ if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
+ || value->unit == CSSPrimitiveValue::CSS_STRING)
validPrimitive = true;
break;
@@ -1887,6 +1893,7 @@ bool CSSParser::parseValue(int propId, bool important)
case CSSPropertyWebkitTextEmphasisStyle:
return parseTextEmphasisStyle(important);
+<<<<<<< HEAD
#ifdef ANDROID_CSS_RING
case CSSPropertyWebkitRing:
{
@@ -1924,6 +1931,20 @@ bool CSSParser::parseValue(int propId, bool important)
m_valueList->next();
break;
#endif
+=======
+ case CSSPropertyWebkitTextOrientation:
+ // FIXME: For now just support upright and vertical-right.
+ if (id == CSSValueVerticalRight || id == CSSValueUpright)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitLineBoxContain:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else
+ return parseLineBoxContain(important);
+ break;
+>>>>>>> webkit.org at r82507
#if ENABLE(SVG)
default:
@@ -2608,34 +2629,80 @@ bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
return false;
}
-PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(CSSParserValueList* valueList, bool& xFound, bool& yFound)
+PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
+{
+ int id = valueList->current()->id;
+ if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
+ int percent = 0;
+ if (id == CSSValueRight)
+ percent = 100;
+ else if (id == CSSValueCenter)
+ percent = 50;
+ return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ if (validUnit(valueList->current(), FPercent | FLength, m_strict))
+ return primitiveValueCache()->createValue(valueList->current()->fValue,
+ (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
+{
+ int id = valueList->current()->id;
+ if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
+ int percent = 0;
+ if (id == CSSValueBottom)
+ percent = 100;
+ else if (id == CSSValueCenter)
+ percent = 50;
+ return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ if (validUnit(valueList->current(), FPercent | FLength, m_strict))
+ return primitiveValueCache()->createValue(valueList->current()->fValue,
+ (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
{
int id = valueList->current()->id;
if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
int percent = 0;
if (id == CSSValueLeft || id == CSSValueRight) {
- if (xFound)
+ if (cumulativeFlags & XFillPosition)
return 0;
- xFound = true;
+ cumulativeFlags |= XFillPosition;
+ individualFlag = XFillPosition;
if (id == CSSValueRight)
percent = 100;
}
else if (id == CSSValueTop || id == CSSValueBottom) {
- if (yFound)
+ if (cumulativeFlags & YFillPosition)
return 0;
- yFound = true;
+ cumulativeFlags |= YFillPosition;
+ individualFlag = YFillPosition;
if (id == CSSValueBottom)
percent = 100;
- }
- else if (id == CSSValueCenter)
+ } else if (id == CSSValueCenter) {
// Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
percent = 50;
+ cumulativeFlags |= AmbiguousFillPosition;
+ individualFlag = AmbiguousFillPosition;
+ }
return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
}
- if (validUnit(valueList->current(), FPercent | FLength, m_strict))
+ if (validUnit(valueList->current(), FPercent | FLength, m_strict)) {
+ if (!cumulativeFlags) {
+ cumulativeFlags |= XFillPosition;
+ individualFlag = XFillPosition;
+ } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
+ cumulativeFlags |= YFillPosition;
+ individualFlag = YFillPosition;
+ } else
+ return 0;
return primitiveValueCache()->createValue(valueList->current()->fValue,
- (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
-
+ (CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
+ }
return 0;
}
@@ -2644,8 +2711,10 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue
CSSParserValue* value = valueList->current();
// Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
- bool value1IsX = false, value1IsY = false;
- value1 = parseFillPositionXY(valueList, value1IsX, value1IsY);
+ unsigned cumulativeFlags = 0;
+ FillPositionFlag value1Flag = InvalidFillPosition;
+ FillPositionFlag value2Flag = InvalidFillPosition;
+ value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
if (!value1)
return;
@@ -2658,9 +2727,8 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue
if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
value = 0;
- bool value2IsX = false, value2IsY = false;
if (value) {
- value2 = parseFillPositionXY(valueList, value2IsX, value2IsY);
+ value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
if (value2)
valueList->next();
else {
@@ -2678,7 +2746,7 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue
// For left/right/center, the default of 50% in the y is still correct.
value2 = primitiveValueCache()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
- if (value1IsY || value2IsX)
+ if (value1Flag == YFillPosition || value2Flag == XFillPosition)
value1.swap(value2);
}
@@ -2856,16 +2924,14 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
break;
case CSSPropertyBackgroundPositionX:
case CSSPropertyWebkitMaskPositionX: {
- bool xFound = false, yFound = true;
- currValue = parseFillPositionXY(m_valueList, xFound, yFound);
+ currValue = parseFillPositionX(m_valueList);
if (currValue)
m_valueList->next();
break;
}
case CSSPropertyBackgroundPositionY:
case CSSPropertyWebkitMaskPositionY: {
- bool xFound = true, yFound = false;
- currValue = parseFillPositionXY(m_valueList, xFound, yFound);
+ currValue = parseFillPositionY(m_valueList);
if (currValue)
m_valueList->next();
break;
@@ -3940,10 +4006,76 @@ bool CSSParser::parseFontFaceUnicodeRange()
return true;
}
-static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar terminator, int& value)
+// Returns the number of characters which form a valid double
+// and are terminated by the given terminator character
+static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator)
+{
+ int length = end - string;
+ if (length < 1)
+ return 0;
+
+ bool decimalMarkSeen = false;
+ int processedLength = 0;
+
+ for (int i = 0; i < length; ++i) {
+ if (string[i] == terminator) {
+ processedLength = i;
+ break;
+ }
+ if (!isASCIIDigit(string[i])) {
+ if (!decimalMarkSeen && string[i] == '.')
+ decimalMarkSeen = true;
+ else
+ return 0;
+ }
+ }
+
+ if (decimalMarkSeen && processedLength == 1)
+ return 0;
+
+ return processedLength;
+}
+
+// Returns the number of characters consumed for parsing a valid double
+// terminated by the given terminator character
+static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value)
+{
+ int length = checkForValidDouble(string, end, terminator);
+ if (!length)
+ return 0;
+
+ int position = 0;
+ double localValue = 0;
+
+ // The consumed characters here are guaranteed to be
+ // ASCII digits with or without a decimal mark
+ for (; position < length; ++position) {
+ if (string[position] == '.')
+ break;
+ localValue = localValue * 10 + string[position] - '0';
+ }
+
+ if (++position == length) {
+ value = localValue;
+ return length;
+ }
+
+ double fraction = 0;
+ double scale = 1;
+
+ while (position < length && scale < MAX_SCALE) {
+ fraction = fraction * 10 + string[position++] - '0';
+ scale *= 10;
+ }
+
+ value = localValue + fraction / scale;
+ return length;
+}
+
+static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
{
const UChar* current = string;
- int localValue = 0;
+ double localValue = 0;
bool negative = false;
while (current != end && isHTMLSpace(*current))
current++;
@@ -3954,7 +4086,7 @@ static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar t
if (current == end || !isASCIIDigit(*current))
return false;
while (current != end && isASCIIDigit(*current)) {
- int newValue = localValue * 10 + *current++ - '0';
+ double newValue = localValue * 10 + *current++ - '0';
if (newValue >= 255) {
// Clamp values at 255.
localValue = 255;
@@ -3964,12 +4096,42 @@ static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar t
}
localValue = newValue;
}
+
+ if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%'))
+ return false;
+
+ if (*current == '.') {
+ // We already parsed the integral part, try to parse
+ // the fraction part of the percentage value.
+ double percentage = 0;
+ int numCharactersParsed = parseDouble(current, end, '%', percentage);
+ if (!numCharactersParsed)
+ return false;
+ current += numCharactersParsed;
+ if (*current != '%')
+ return false;
+ localValue += percentage;
+ }
+
+ if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%')
+ return false;
+
+ if (*current == '%') {
+ expect = CSSPrimitiveValue::CSS_PERCENTAGE;
+ localValue = localValue / 100.0 * 256.0;
+ // Clamp values at 255 for percentages over 100%
+ if (localValue > 255)
+ localValue = 255;
+ current++;
+ } else
+ expect = CSSPrimitiveValue::CSS_NUMBER;
+
while (current != end && isHTMLSpace(*current))
current++;
if (current == end || *current++ != terminator)
return false;
// Clamp negative values at zero.
- value = negative ? 0 : localValue;
+ value = negative ? 0 : static_cast<int>(localValue);
string = current;
return true;
}
@@ -3987,21 +4149,7 @@ static inline bool isTenthAlpha(const UChar* string, const int length)
return false;
}
-static inline bool isValidDouble(const UChar* string, const int length)
-{
- bool decimalMarkSeen = false;
- for (int i = 0; i < length; ++i) {
- if (!isASCIIDigit(string[i])) {
- if (!decimalMarkSeen && string[i] == '.')
- decimalMarkSeen = true;
- else
- return false;
- }
- }
- return true;
-}
-
-static inline bool parseAlphaValue(const UChar*& string, const UChar* end, UChar terminator, int& value)
+static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value)
{
while (string != end && isHTMLSpace(*string))
string++;
@@ -4023,7 +4171,7 @@ static inline bool parseAlphaValue(const UChar*& string, const UChar* end, UChar
return false;
if (string[0] != '0' && string[0] != '1' && string[0] != '.') {
- if (isValidDouble(string, length - 1)) {
+ if (checkForValidDouble(string, end, terminator)) {
value = negative ? 0 : 255;
string = end;
return true;
@@ -4044,20 +4192,12 @@ static inline bool parseAlphaValue(const UChar*& string, const UChar* end, UChar
return true;
}
- if (!isValidDouble(string, length - 1))
- return false;
-
- Vector<char, 8> bytes(length + 1);
-
- for (int i = 0; i < length; ++i)
- bytes[i] = string[i];
-
- bytes[length] = '\0';
- char* foundTerminator;
- double d = WTF::strtod(bytes.data(), &foundTerminator);
- value = negative ? 0 : static_cast<int>(d * nextafter(256.0, 0.0));
- string += (foundTerminator - bytes.data()) + 1;
- return *foundTerminator == terminator;
+ double alpha = 0;
+ if (!parseDouble(string, end, terminator, alpha))
+ return false;
+ value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0));
+ string = end;
+ return true;
}
static inline bool mightBeRGBA(const UChar* characters, unsigned length)
@@ -4085,6 +4225,7 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict)
{
const UChar* characters = name.characters();
unsigned length = name.length();
+ CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN;
if (!strict && length >= 3) {
if (name[0] == '#') {
@@ -4104,11 +4245,12 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict)
int green;
int blue;
int alpha;
- if (!parseColorInt(current, end, ',', red))
+
+ if (!parseColorIntOrPercentage(current, end, ',', expect, red))
return false;
- if (!parseColorInt(current, end, ',', green))
+ if (!parseColorIntOrPercentage(current, end, ',', expect, green))
return false;
- if (!parseColorInt(current, end, ',', blue))
+ if (!parseColorIntOrPercentage(current, end, ',', expect, blue))
return false;
if (!parseAlphaValue(current, end, ')', alpha))
return false;
@@ -4125,11 +4267,11 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict)
int red;
int green;
int blue;
- if (!parseColorInt(current, end, ',', red))
+ if (!parseColorIntOrPercentage(current, end, ',', expect, red))
return false;
- if (!parseColorInt(current, end, ',', green))
+ if (!parseColorIntOrPercentage(current, end, ',', expect, green))
return false;
- if (!parseColorInt(current, end, ')', blue))
+ if (!parseColorIntOrPercentage(current, end, ')', expect, blue))
return false;
if (current != end)
return false;
@@ -5544,15 +5686,13 @@ bool CSSParser::parseTransformOrigin(int propId, int& propId1, int& propId2, int
// parseTransformOriginShorthand advances the m_valueList pointer
break;
case CSSPropertyWebkitTransformOriginX: {
- bool xFound = false, yFound = true;
- value = parseFillPositionXY(m_valueList, xFound, yFound);
+ value = parseFillPositionX(m_valueList);
if (value)
m_valueList->next();
break;
}
case CSSPropertyWebkitTransformOriginY: {
- bool xFound = true, yFound = false;
- value = parseFillPositionXY(m_valueList, xFound, yFound);
+ value = parseFillPositionY(m_valueList);
if (value)
m_valueList->next();
break;
@@ -5583,15 +5723,13 @@ bool CSSParser::parsePerspectiveOrigin(int propId, int& propId1, int& propId2, R
parseFillPosition(m_valueList, value, value2);
break;
case CSSPropertyWebkitPerspectiveOriginX: {
- bool xFound = false, yFound = true;
- value = parseFillPositionXY(m_valueList, xFound, yFound);
+ value = parseFillPositionX(m_valueList);
if (value)
m_valueList->next();
break;
}
case CSSPropertyWebkitPerspectiveOriginY: {
- bool xFound = true, yFound = false;
- value = parseFillPositionXY(m_valueList, xFound, yFound);
+ value = parseFillPositionY(m_valueList);
if (value)
m_valueList->next();
break;
@@ -5658,6 +5796,46 @@ bool CSSParser::parseTextEmphasisStyle(bool important)
return false;
}
+bool CSSParser::parseLineBoxContain(bool important)
+{
+ LineBoxContain lineBoxContain = LineBoxContainNone;
+
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ if (value->id == CSSValueBlock) {
+ if (lineBoxContain & LineBoxContainBlock)
+ return false;
+ lineBoxContain |= LineBoxContainBlock;
+ } else if (value->id == CSSValueInline) {
+ if (lineBoxContain & LineBoxContainInline)
+ return false;
+ lineBoxContain |= LineBoxContainInline;
+ } else if (value->id == CSSValueFont) {
+ if (lineBoxContain & LineBoxContainFont)
+ return false;
+ lineBoxContain |= LineBoxContainFont;
+ } else if (value->id == CSSValueGlyphs) {
+ if (lineBoxContain & LineBoxContainGlyphs)
+ return false;
+ lineBoxContain |= LineBoxContainGlyphs;
+ } else if (value->id == CSSValueReplaced) {
+ if (lineBoxContain & LineBoxContainReplaced)
+ return false;
+ lineBoxContain |= LineBoxContainReplaced;
+ } else if (value->id == CSSValueInlineBox) {
+ if (lineBoxContain & LineBoxContainInlineBox)
+ return false;
+ lineBoxContain |= LineBoxContainInlineBox;
+ } else
+ return false;
+ }
+
+ if (!lineBoxContain)
+ return false;
+
+ addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important);
+ return true;
+}
+
static inline int yyerror(const char*) { return 1; }
#define END_TOKEN 0
@@ -5689,6 +5867,7 @@ int CSSParser::lex(void* yylvalWithoutType)
case DIMEN:
case UNICODERANGE:
case FUNCTION:
+ case ANYFUNCTION:
case NOTFUNCTION:
yylval->string.characters = t;
yylval->string.length = length;
@@ -5902,6 +6081,22 @@ PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector*
return adoptPtr(selector);
}
+Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector()
+{
+ Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
+ m_floatingSelectorVectors.add(selectorVector);
+ return selectorVector;
+}
+
+Vector<OwnPtr<CSSParserSelector> >* CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
+{
+ if (selectorVector) {
+ ASSERT(m_floatingSelectorVectors.contains(selectorVector));
+ m_floatingSelectorVectors.remove(selectorVector);
+ }
+ return selectorVector;
+}
+
CSSParserValueList* CSSParser::createFloatingValueList()
{
CSSParserValueList* list = new CSSParserValueList;
@@ -6485,11 +6680,8 @@ String quoteCSSString(const String& string)
buffer[index++] = ch;
afterEscape = false;
} else if (ch < 0x20 || ch == 0x7F) { // Control characters.
- static const char hexDigits[17] = "0123456789abcdef";
buffer[index++] = '\\';
- if (ch >= 0x10)
- buffer[index++] = hexDigits[ch >> 4];
- buffer[index++] = hexDigits[ch & 0xF];
+ placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase);
afterEscape = true;
} else {
// Space character may be required to separate backslash-escape sequence and normal characters.