diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
commit | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch) | |
tree | 8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/WebCore/css | |
parent | d11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff) | |
download | qtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz |
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/WebCore/css')
57 files changed, 3776 insertions, 1834 deletions
diff --git a/Source/WebCore/css/CSSAllInOne.cpp b/Source/WebCore/css/CSSAllInOne.cpp index 50901aac7..7d5f250d1 100644 --- a/Source/WebCore/css/CSSAllInOne.cpp +++ b/Source/WebCore/css/CSSAllInOne.cpp @@ -26,14 +26,13 @@ // This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build. #include "CSSAspectRatioValue.cpp" +#include "CSSBorderImage.cpp" #include "CSSBorderImageSliceValue.cpp" -#include "CSSBorderImageValue.cpp" #include "CSSCanvasValue.cpp" #include "CSSCharsetRule.cpp" #include "CSSComputedStyleDeclaration.cpp" #include "CSSCrossfadeValue.cpp" #include "CSSCursorImageValue.cpp" -#include "CSSElementStyleDeclaration.cpp" #include "CSSFlexValue.cpp" #include "CSSFontFace.cpp" #include "CSSFontFaceRule.cpp" diff --git a/Source/WebCore/css/CSSBorderImage.cpp b/Source/WebCore/css/CSSBorderImage.cpp new file mode 100644 index 000000000..ac3e51ef1 --- /dev/null +++ b/Source/WebCore/css/CSSBorderImage.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "CSSBorderImage.h" + +namespace WebCore { + +PassRefPtr<CSSValueList> createBorderImageValue(PassRefPtr<CSSValue> image, PassRefPtr<CSSValue> imageSlice, PassRefPtr<CSSValue> borderSlice, + PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat) +{ + RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + if (image) + list->append(image); + + if (borderSlice || outset) { + RefPtr<CSSValueList> listSlash = CSSValueList::createSlashSeparated(); + if (imageSlice) + listSlash->append(imageSlice); + + if (borderSlice) + listSlash->append(borderSlice); + + if (outset) + listSlash->append(outset); + + list->append(listSlash); + } else if (imageSlice) + list->append(imageSlice); + if (repeat) + list->append(repeat); + return list.release(); +} + +} // namespace WebCore diff --git a/Source/WebCore/css/CSSBorderImage.h b/Source/WebCore/css/CSSBorderImage.h new file mode 100644 index 000000000..b0769f31d --- /dev/null +++ b/Source/WebCore/css/CSSBorderImage.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSBorderImage_h +#define CSSBorderImage_h + +#include "CSSBorderImageSliceValue.h" +#include "CSSValueList.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +PassRefPtr<CSSValueList> createBorderImageValue(PassRefPtr<CSSValue> image, PassRefPtr<CSSValue> imageSlice, PassRefPtr<CSSValue> borderSlice, + PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat); + +} // namespace WebCore + +#endif // CSSBorderImage_h diff --git a/Source/WebCore/css/CSSBorderImageValue.cpp b/Source/WebCore/css/CSSBorderImageValue.cpp deleted file mode 100644 index 846ea6dc5..000000000 --- a/Source/WebCore/css/CSSBorderImageValue.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * (C) 1999-2003 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. 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 - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "CSSBorderImageValue.h" - -#include "PlatformString.h" -#include "Rect.h" - -namespace WebCore { - -CSSBorderImageValue::CSSBorderImageValue(PassRefPtr<CSSValue> image, PassRefPtr<CSSBorderImageSliceValue> imageSlice, - PassRefPtr<CSSValue> borderSlice, PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat) - : CSSValue(BorderImageClass) - , m_image(image) - , m_imageSlice(imageSlice) - , m_borderSlice(borderSlice) - , m_outset(outset) - , m_repeat(repeat) -{ -} - -String CSSBorderImageValue::customCssText() const -{ - // Image first. - String text; - - if (m_image) - text += m_image->cssText(); - - // Now the slices. - if (m_imageSlice) { - if (!text.isEmpty()) - text += " "; - text += m_imageSlice->cssText(); - } - - // Now the border widths. - if (m_borderSlice) { - text += " / "; - text += m_borderSlice->cssText(); - } - - if (m_outset) { - text += " / "; - text += m_outset->cssText(); - } - - if (m_repeat) { - // Now the keywords. - if (!text.isEmpty()) - text += " "; - text += m_repeat->cssText(); - } - - return text; -} - -void CSSBorderImageValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet) -{ - m_image->addSubresourceStyleURLs(urls, styleSheet); -} - -} // namespace WebCore diff --git a/Source/WebCore/css/CSSBorderImageValue.h b/Source/WebCore/css/CSSBorderImageValue.h deleted file mode 100644 index 675758cc3..000000000 --- a/Source/WebCore/css/CSSBorderImageValue.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * (C) 1999-2003 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. 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 - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef CSSBorderImageValue_h -#define CSSBorderImageValue_h - -#include "CSSBorderImageSliceValue.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> - -namespace WebCore { - -class Rect; - -class CSSBorderImageValue : public CSSValue { -public: - static PassRefPtr<CSSBorderImageValue> create(PassRefPtr<CSSValue> image, PassRefPtr<CSSBorderImageSliceValue> imageSlice, - PassRefPtr<CSSValue> borderSlice, PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat) - { - return adoptRef(new CSSBorderImageValue(image, imageSlice, borderSlice, outset, repeat)); - } - - String customCssText() const; - - CSSValue* imageValue() const { return m_image.get(); } - - void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*); - - // The border image. - RefPtr<CSSValue> m_image; - - // These four values are used to make "cuts" in the image. They can be numbers - // or percentages. - RefPtr<CSSBorderImageSliceValue> m_imageSlice; - - // These four values are used to make "cuts" in the border image drawing area. - // They can be numbers, percentages or lengths. - RefPtr<CSSValue> m_borderSlice; - - // The outset values are used to inflate the border image drawing area. - RefPtr<CSSValue> m_outset; - - // Values for how to handle the scaling/stretching/tiling of the image slices. - RefPtr<CSSValue> m_repeat; - -private: - CSSBorderImageValue(PassRefPtr<CSSValue> image, PassRefPtr<CSSBorderImageSliceValue>, PassRefPtr<CSSValue> borderSlice, - PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat); -}; - -} // namespace WebCore - -#endif // CSSBorderImageValue_h diff --git a/Source/WebCore/css/CSSCalculationValue.cpp b/Source/WebCore/css/CSSCalculationValue.cpp new file mode 100755 index 000000000..11907f280 --- /dev/null +++ b/Source/WebCore/css/CSSCalculationValue.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSCalculationValue.h" + +#include "CSSStyleSelector.h" +#include "CSSValueList.h" +#include "Length.h" + +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/text/StringBuilder.h> + +static const int maxExpressionDepth = 100; + +enum ParseState { + OK, + TooDeep, + NoMoreTokens +}; + +namespace WebCore { + +static CalculationCategory unitCategory(CSSPrimitiveValue::UnitTypes type) +{ + switch (type) { + case CSSPrimitiveValue::CSS_NUMBER: + case CSSPrimitiveValue::CSS_PARSER_INTEGER: + return CalcNumber; + case CSSPrimitiveValue::CSS_PERCENTAGE: + return CalcPercent; + case CSSPrimitiveValue::CSS_EMS: + case CSSPrimitiveValue::CSS_EXS: + case CSSPrimitiveValue::CSS_PX: + case CSSPrimitiveValue::CSS_CM: + case CSSPrimitiveValue::CSS_MM: + case CSSPrimitiveValue::CSS_IN: + case CSSPrimitiveValue::CSS_PT: + case CSSPrimitiveValue::CSS_PC: + case CSSPrimitiveValue::CSS_REMS: + return CalcLength; + default: + return CalcOther; + } +} + +String CSSCalcValue::customCssText() const +{ + return ""; +} + +CSSCalcExpressionNode::~CSSCalcExpressionNode() +{ +} + +class CSSCalcPrimitiveValue : public CSSCalcExpressionNode { +public: + + static PassRefPtr<CSSCalcPrimitiveValue> create(CSSPrimitiveValue* value, bool isInteger) + { + return adoptRef(new CSSCalcPrimitiveValue(value, isInteger)); + } + + virtual String cssText() const + { + return m_value->cssText(); + } + + +private: + explicit CSSCalcPrimitiveValue(CSSPrimitiveValue* value, bool isInteger) + : CSSCalcExpressionNode(unitCategory((CSSPrimitiveValue::UnitTypes)value->primitiveType()), isInteger) + , m_value(value) + { + } + + RefPtr<CSSPrimitiveValue> m_value; +}; + +static const CalculationCategory addSubtractResult[CalcOther][CalcOther] = { + { CalcNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther }, + { CalcOther, CalcLength, CalcPercentLength, CalcOther, CalcPercentLength }, + { CalcPercentNumber, CalcPercentLength, CalcPercent, CalcPercentNumber, CalcPercentLength }, + { CalcPercentNumber, CalcOther, CalcPercentNumber, CalcPercentNumber, CalcOther }, + { CalcOther, CalcPercentLength, CalcPercentLength, CalcOther, CalcPercentLength }, +}; + +class CSSCalcBinaryOperation : public CSSCalcExpressionNode { +public: + static PassRefPtr<CSSCalcBinaryOperation> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) + { + CalculationCategory leftCategory = leftSide->category(); + CalculationCategory rightCategory = rightSide->category(); + CalculationCategory newCategory = CalcOther; + + ASSERT(leftCategory != CalcOther && rightCategory != CalcOther); + + switch (op) { + case CalcAdd: + case CalcSubtract: + if (leftCategory == CalcOther || rightCategory == CalcOther) + return 0; + newCategory = addSubtractResult[leftCategory][rightCategory]; + break; + + case CalcMultiply: + if (leftCategory != CalcNumber && rightCategory != CalcNumber) + return 0; + + newCategory = leftCategory == CalcNumber ? rightCategory : leftCategory; + break; + + case CalcDivide: + case CalcMod: + if (rightCategory != CalcNumber || rightSide->isZero()) + return 0; + newCategory = leftCategory; + break; + } + + if (newCategory == CalcOther) + return 0; + + return adoptRef(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory)); + } + +private: + CSSCalcBinaryOperation(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op, CalculationCategory category) + : CSSCalcExpressionNode(category, leftSide->isInteger() && rightSide->isInteger()) + , m_leftSide(leftSide) + , m_rightSide(rightSide) + , m_operator(op) + { + } + + const RefPtr<CSSCalcExpressionNode> m_leftSide; + const RefPtr<CSSCalcExpressionNode> m_rightSide; + const CalcOperator m_operator; +}; + +static ParseState checkDepthAndIndex(int* depth, unsigned index, CSSParserValueList* tokens) +{ + (*depth)++; + if (*depth > maxExpressionDepth) + return TooDeep; + if (index >= tokens->size()) + return NoMoreTokens; + return OK; +} + +class CSSCalcExpressionNodeParser { +public: + PassRefPtr<CSSCalcExpressionNode> parseCalc(CSSParserValueList* tokens) + { + unsigned index = 0; + Value result; + bool ok = parseValueExpression(tokens, 0, &index, &result); + ASSERT(index <= tokens->size()); + if (!ok || index != tokens->size()) + return 0; + return result.value; + } + +private: + struct Value { + RefPtr<CSSCalcExpressionNode> value; + }; + + char operatorValue(CSSParserValueList* tokens, unsigned index) + { + if (index >= tokens->size()) + return 0; + CSSParserValue* value = tokens->valueAt(index); + if (value->unit != CSSParserValue::Operator) + return 0; + + return value->iValue; + } + + bool parseValue(CSSParserValueList* tokens, unsigned* index, Value* result) + { + CSSParserValue* parserValue = tokens->valueAt(*index); + if (parserValue->unit == CSSParserValue::Operator || parserValue->unit == CSSParserValue::Function) + return false; + + RefPtr<CSSValue> value = parserValue->createCSSValue(); + if (!value || !value->isPrimitiveValue()) + return false; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value.get()); + result->value = CSSCalcPrimitiveValue::create(primitiveValue, parserValue->isInt); + + ++*index; + return true; + } + + bool parseValueTerm(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) + { + if (checkDepthAndIndex(&depth, *index, tokens) != OK) + return false; + + if (operatorValue(tokens, *index) == '(') { + unsigned currentIndex = *index + 1; + if (!parseValueExpression(tokens, depth, ¤tIndex, result)) + return false; + + if (operatorValue(tokens, currentIndex) != ')') + return false; + *index = currentIndex + 1; + return true; + } + + return parseValue(tokens, index, result); + } + + bool parseValueMultiplicativeExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) + { + if (checkDepthAndIndex(&depth, *index, tokens) != OK) + return false; + + if (!parseValueTerm(tokens, depth, index, result)) + return false; + + while (*index < tokens->size() - 1) { + char operatorCharacter = operatorValue(tokens, *index); + if (operatorCharacter != CalcMultiply && operatorCharacter != CalcDivide && operatorCharacter != CalcMod) + break; + ++*index; + + Value rhs; + if (!parseValueTerm(tokens, depth, index, &rhs)) + return false; + + result->value = CSSCalcBinaryOperation::create(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter)); + if (!result->value) + return false; + } + + ASSERT(*index <= tokens->size()); + return true; + } + + bool parseAdditiveValueExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) + { + if (checkDepthAndIndex(&depth, *index, tokens) != OK) + return false; + + if (!parseValueMultiplicativeExpression(tokens, depth, index, result)) + return false; + + while (*index < tokens->size() - 1) { + char operatorCharacter = operatorValue(tokens, *index); + if (operatorCharacter != CalcAdd && operatorCharacter != CalcSubtract) + break; + ++*index; + + Value rhs; + if (!parseValueMultiplicativeExpression(tokens, depth, index, &rhs)) + return false; + + result->value = CSSCalcBinaryOperation::create(result->value, rhs.value, static_cast<CalcOperator>(operatorCharacter)); + if (!result->value) + return false; + } + + ASSERT(*index <= tokens->size()); + return true; + } + + bool parseValueExpression(CSSParserValueList* tokens, int depth, unsigned* index, Value* result) + { + return parseAdditiveValueExpression(tokens, depth, index, result); + } +}; + +PassRefPtr<CSSCalcValue> CSSCalcValue::create(CSSParserString name, CSSParserValueList* parserValueList) +{ + CSSCalcExpressionNodeParser parser; + RefPtr<CSSCalcExpressionNode> expression; + + if (equalIgnoringCase(name, "-webkit-calc(")) + expression = parser.parseCalc(parserValueList); + // FIXME calc (http://webkit.org/b/16662) Add parsing for min and max here + + return expression ? adoptRef(new CSSCalcValue(expression)) : 0; +} + +} // namespace WebCore diff --git a/Source/WebCore/css/CSSCalculationValue.h b/Source/WebCore/css/CSSCalculationValue.h new file mode 100755 index 000000000..4d4639d11 --- /dev/null +++ b/Source/WebCore/css/CSSCalculationValue.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSCalculationValue_h +#define CSSCalculationValue_h + +#include "CSSParserValues.h" +#include "CSSValue.h" +#include "CalculationValue.h" +#include <wtf/PassOwnPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSParserValueList; +class CSSValueList; +class RenderStyle; +class CalcValue; +class CalcExpressionNode; + +enum CalculationCategory { + CalcNumber = 0, + CalcLength, + CalcPercent, + CalcPercentNumber, + CalcPercentLength, + CalcOther +}; + +class CSSCalcExpressionNode : public RefCounted<CSSCalcExpressionNode> { +public: + + virtual ~CSSCalcExpressionNode() = 0; + + CalculationCategory category() const { return m_category; } + bool isInteger() const { return m_isInteger; } + bool isZero() const { return false; } + +protected: + CSSCalcExpressionNode(CalculationCategory category, bool isInteger) + : m_category(category) + , m_isInteger(isInteger) + { + } + + CalculationCategory m_category; + bool m_isInteger; +}; + +class CSSCalcValue : public CSSValue { +public: + static PassRefPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList*); + + CalculationCategory category() const { return m_expression->category(); } + bool isInt() const { return m_expression->isInteger(); } + + String customCssText() const; + +private: + CSSCalcValue(PassRefPtr<CSSCalcExpressionNode> expression) + : CSSValue(CalculationClass) + , m_expression(expression) + { + } + + const RefPtr<CSSCalcExpressionNode> m_expression; +}; + +} // namespace WebCore + +#endif // CSSCalculationValue_h diff --git a/Source/WebCore/css/CSSCanvasValue.h b/Source/WebCore/css/CSSCanvasValue.h index efad7e692..159e61956 100644 --- a/Source/WebCore/css/CSSCanvasValue.h +++ b/Source/WebCore/css/CSSCanvasValue.h @@ -35,7 +35,7 @@ class Document; class CSSCanvasValue : public CSSImageGeneratorValue { public: - static PassRefPtr<CSSCanvasValue> create() { return adoptRef(new CSSCanvasValue); } + static PassRefPtr<CSSCanvasValue> create(const String& name) { return adoptRef(new CSSCanvasValue(name)); } ~CSSCanvasValue(); String customCssText() const; @@ -47,12 +47,11 @@ public: bool isPending() const { return false; } void loadSubimages(CachedResourceLoader*) { } - void setName(const String& name) { m_name = name; } - private: - CSSCanvasValue() + CSSCanvasValue(const String& name) : CSSImageGeneratorValue(CanvasClass) , m_canvasObserver(this) + , m_name(name) , m_element(0) { } diff --git a/Source/WebCore/css/CSSCharsetRule.idl b/Source/WebCore/css/CSSCharsetRule.idl index 2b158ff8b..87f796aff 100644 --- a/Source/WebCore/css/CSSCharsetRule.idl +++ b/Source/WebCore/css/CSSCharsetRule.idl @@ -25,7 +25,7 @@ module css { #if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C readonly attribute [ConvertNullStringTo=Null] DOMString encoding; #else - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString encoding + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString encoding setter raises(DOMException); #endif }; diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp index 112abbe83..90f98c8d3 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -26,9 +26,10 @@ #include "AnimationController.h" #include "CSSAspectRatioValue.h" -#include "CSSBorderImageValue.h" +#include "CSSBorderImage.h" #include "CSSLineBoxContainValue.h" #include "CSSMutableStyleDeclaration.h" +#include "CSSParser.h" #include "CSSPrimitiveValue.h" #include "CSSPrimitiveValueMappings.h" #include "CSSProperty.h" @@ -42,7 +43,9 @@ #include "CounterContent.h" #include "CursorList.h" #if ENABLE(CSS_SHADERS) +#include "CustomFilterNumberParameter.h" #include "CustomFilterOperation.h" +#include "CustomFilterParameter.h" #endif #include "Document.h" #include "ExceptionCode.h" @@ -56,6 +59,7 @@ #include "RenderStyle.h" #include "ShadowValue.h" #if ENABLE(CSS_FILTERS) +#include "StyleCustomFilterProgram.h" #include "WebKitCSSFilterValue.h" #endif #include "WebKitCSSTransformValue.h" @@ -217,12 +221,14 @@ static const int computedProperties[] = { #endif CSSPropertyWebkitFlexOrder, CSSPropertyWebkitFlexPack, + CSSPropertyWebkitFlexAlign, CSSPropertyWebkitFlexItemAlign, CSSPropertyWebkitFlexDirection, CSSPropertyWebkitFlexFlow, CSSPropertyWebkitFlexWrap, CSSPropertyWebkitFontKerning, CSSPropertyWebkitFontSmoothing, + CSSPropertyWebkitFontVariantLigatures, #if ENABLE(CSS_GRID_LAYOUT) CSSPropertyWebkitGridColumns, CSSPropertyWebkitGridRows, @@ -496,7 +502,7 @@ static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, // Create the repeat rules. RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image, cssValuePool); - return CSSBorderImageValue::create(imageValue.release(), imageSlices.release(), borderSlices.release(), outset.release(), repeat); + return createBorderImageValue(imageValue, imageSlices, borderSlices, outset, repeat); } inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(int value, const RenderStyle* style, CSSValuePool* cssValuePool) @@ -710,6 +716,30 @@ static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const Rend return list.release(); } +#if ENABLE(CSS_SHADERS) +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForCustomFilterNumberParameter(const CustomFilterNumberParameter* numberParameter) const +{ + RefPtr<CSSValueList> numberParameterValue = CSSValueList::createSpaceSeparated(); + CSSValuePool* cssValuePool = m_node->document()->cssValuePool().get(); + for (unsigned i = 0; i < numberParameter->size(); ++i) + numberParameterValue->append(cssValuePool->createValue(numberParameter->valueAt(i), CSSPrimitiveValue::CSS_NUMBER)); + return numberParameterValue.release(); +} + +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForCustomFilterParameter(const CustomFilterParameter* parameter) const +{ + // FIXME: Add here computed style for the other types: boolean, transform, matrix, texture. + ASSERT(parameter); + switch (parameter->parameterType()) { + case CustomFilterParameter::NUMBER: + return valueForCustomFilterNumberParameter(static_cast<const CustomFilterNumberParameter*>(parameter)); + } + + ASSERT_NOT_REACHED(); + return 0; +} +#endif // ENABLE(CSS_SHADERS) + #if ENABLE(CSS_FILTERS) PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(RenderStyle* style) const { @@ -801,13 +831,16 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(RenderStyle* st // The output should be verbose, even if the values are the default ones. + ASSERT(customOperation->program()); + StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customOperation->program()); + RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated(); - if (customOperation->vertexShader()) - shadersList->append(customOperation->vertexShader()->cssValue()); + if (program->vertexShader()) + shadersList->append(program->vertexShader()->cssValue()); else shadersList->append(cssValuePool->createIdentifierValue(CSSValueNone)); - if (customOperation->fragmentShader()) - shadersList->append(customOperation->fragmentShader()->cssValue()); + if (program->fragmentShader()) + shadersList->append(program->fragmentShader()->cssValue()); else shadersList->append(cssValuePool->createIdentifierValue(CSSValueNone)); filterValue->append(shadersList.release()); @@ -824,6 +857,20 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(RenderStyle* st filterValue->append(meshParameters.release()); + const CustomFilterParameterList& parameters = customOperation->parameters(); + size_t parametersSize = parameters.size(); + if (!parametersSize) + break; + RefPtr<CSSValueList> parametersCSSValue = CSSValueList::createCommaSeparated(); + for (size_t i = 0; i < parametersSize; ++i) { + const CustomFilterParameter* parameter = parameters.at(i).get(); + RefPtr<CSSValueList> parameterCSSNameAndValue = CSSValueList::createSpaceSeparated(); + parameterCSSNameAndValue->append(cssValuePool->createValue(parameter->name(), CSSPrimitiveValue::CSS_STRING)); + parameterCSSNameAndValue->append(valueForCustomFilterParameter(parameter)); + parametersCSSValue->append(parameterCSSNameAndValue.release()); + } + + filterValue->append(parametersCSSValue.release()); break; } #endif @@ -1521,7 +1568,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper return cssValuePool->createValue(style->flexOrder(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitFlexPack: return cssValuePool->createValue(style->flexPack()); + case CSSPropertyWebkitFlexAlign: + return cssValuePool->createValue(style->flexAlign()); case CSSPropertyWebkitFlexItemAlign: + // FIXME: If flex-item-align:auto, then we should return the parent's flex-align. + // http://webkit.org/b/76326 return cssValuePool->createValue(style->flexItemAlign()); case CSSPropertyWebkitFlexDirection: return cssValuePool->createValue(style->flexDirection()); @@ -1871,6 +1922,23 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper return cssValuePool->createValue(style->fontDescription().kerning()); case CSSPropertyWebkitFontSmoothing: return cssValuePool->createValue(style->fontDescription().fontSmoothing()); + case CSSPropertyWebkitFontVariantLigatures: { + FontDescription::LigaturesState commonLigaturesState = style->fontDescription().commonLigaturesState(); + FontDescription::LigaturesState discretionaryLigaturesState = style->fontDescription().discretionaryLigaturesState(); + FontDescription::LigaturesState historicalLigaturesState = style->fontDescription().historicalLigaturesState(); + if (commonLigaturesState == FontDescription::NormalLigaturesState && discretionaryLigaturesState == FontDescription::NormalLigaturesState + && historicalLigaturesState == FontDescription::NormalLigaturesState) + return cssValuePool->createIdentifierValue(CSSValueNormal); + + RefPtr<CSSValueList> valueList = CSSValueList::createSpaceSeparated(); + if (commonLigaturesState != FontDescription::NormalLigaturesState) + valueList->append(cssValuePool->createIdentifierValue(commonLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoCommonLigatures : CSSValueCommonLigatures)); + if (discretionaryLigaturesState != FontDescription::NormalLigaturesState) + valueList->append(cssValuePool->createIdentifierValue(discretionaryLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoDiscretionaryLigatures : CSSValueDiscretionaryLigatures)); + if (historicalLigaturesState != FontDescription::NormalLigaturesState) + valueList->append(cssValuePool->createIdentifierValue(historicalLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoHistoricalLigatures : CSSValueHistoricalLigatures)); + return valueList; + } case CSSPropertyZIndex: if (style->hasAutoZIndex()) return cssValuePool->createIdentifierValue(CSSValueAuto); @@ -2408,24 +2476,8 @@ String CSSComputedStyleDeclaration::getPropertyValue(int propertyID) const return ""; } -bool CSSComputedStyleDeclaration::getPropertyPriority(int /*propertyID*/) const -{ - // All computed styles have a priority of false (not "important"). - return false; -} - -String CSSComputedStyleDeclaration::removeProperty(int /*propertyID*/, ExceptionCode& ec) -{ - ec = NO_MODIFICATION_ALLOWED_ERR; - return String(); -} - -void CSSComputedStyleDeclaration::setProperty(int /*propertyID*/, const String& /*value*/, bool /*important*/, ExceptionCode& ec) -{ - ec = NO_MODIFICATION_ALLOWED_ERR; -} -unsigned CSSComputedStyleDeclaration::virtualLength() const +unsigned CSSComputedStyleDeclaration::length() const { Node* node = m_node.get(); if (!node) @@ -2454,12 +2506,12 @@ bool CSSComputedStyleDeclaration::cssPropertyMatches(const CSSProperty* property if (style && style->fontDescription().keywordSize()) { int sizeValue = cssIdentifierForFontSizeKeyword(style->fontDescription().keywordSize()); CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(property->value()); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && primitiveValue->getIdent() == sizeValue) + if (primitiveValue->isIdent() && primitiveValue->getIdent() == sizeValue) return true; } } - - return CSSStyleDeclaration::cssPropertyMatches(property); + RefPtr<CSSValue> value = getPropertyCSSValue(property->id()); + return value && value->cssText() == property->value()->cssText(); } PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::copy() const @@ -2510,4 +2562,74 @@ PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::getCSSPropertyValuesForSid return list.release(); } +PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::copyPropertiesInSet(const int* set, unsigned length) const +{ + Vector<CSSProperty> list; + list.reserveInitialCapacity(length); + for (unsigned i = 0; i < length; ++i) { + RefPtr<CSSValue> value = getPropertyCSSValue(set[i]); + if (value) + list.append(CSSProperty(set[i], value.release(), false)); + } + return CSSMutableStyleDeclaration::create(list); +} + +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(const String& propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return 0; + return getPropertyCSSValue(propertyID); +} + +String CSSComputedStyleDeclaration::getPropertyValue(const String &propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return String(); + return getPropertyValue(propertyID); +} + +String CSSComputedStyleDeclaration::getPropertyPriority(const String&) +{ + // All computed styles have a priority of not "important". + return ""; +} + +String CSSComputedStyleDeclaration::getPropertyShorthand(const String&) +{ + return ""; +} + +bool CSSComputedStyleDeclaration::isPropertyImplicit(const String&) +{ + return false; +} + +void CSSComputedStyleDeclaration::setProperty(const String&, const String&, const String&, ExceptionCode& ec) +{ + ec = NO_MODIFICATION_ALLOWED_ERR; +} + +String CSSComputedStyleDeclaration::removeProperty(const String&, ExceptionCode& ec) +{ + ec = NO_MODIFICATION_ALLOWED_ERR; + return String(); +} + +PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID) +{ + return getPropertyCSSValue(propertyID); +} + +String CSSComputedStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID) +{ + return getPropertyValue(propertyID); +} + +void CSSComputedStyleDeclaration::setPropertyInternal(CSSPropertyID, const String&, bool, ExceptionCode& ec) +{ + ec = NO_MODIFICATION_ALLOWED_ERR; +} + } // namespace WebCore diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.h b/Source/WebCore/css/CSSComputedStyleDeclaration.h index 6ef90af6e..b44a5cff0 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.h +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.h @@ -38,6 +38,11 @@ class RenderStyle; class ShadowData; class SVGPaint; +#if ENABLE(CSS_SHADERS) +class CustomFilterNumberParameter; +class CustomFilterParameter; +#endif + enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true }; class CSSComputedStyleDeclaration : public CSSStyleDeclaration { @@ -45,16 +50,9 @@ public: friend PassRefPtr<CSSComputedStyleDeclaration> computedStyle(PassRefPtr<Node>, bool allowVisitedStyle, const String& pseudoElementName); virtual ~CSSComputedStyleDeclaration(); - virtual String cssText() const; - - virtual unsigned virtualLength() const; - virtual String item(unsigned index) const; - - virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; - virtual String getPropertyValue(int propertyID) const; - virtual bool getPropertyPriority(int propertyID) const; - virtual int getPropertyShorthand(int /*propertyID*/) const { return -1; } - virtual bool isPropertyImplicit(int /*propertyID*/) const { return false; } + PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; + String getPropertyValue(int propertyID) const; + bool getPropertyPriority(int propertyID) const; virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const; virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable(); @@ -66,16 +64,28 @@ public: PassRefPtr<CSSValue> getSVGPropertyCSSValue(int propertyID, EUpdateLayout) const; #endif -protected: - virtual bool cssPropertyMatches(const CSSProperty*) const; + PassRefPtr<CSSMutableStyleDeclaration> copyPropertiesInSet(const int* set, unsigned length) const; private: CSSComputedStyleDeclaration(PassRefPtr<Node>, bool allowVisitedStyle, const String&); + // CSSOM functions. Don't make these public. + virtual unsigned length() const; + virtual String item(unsigned index) const; + virtual PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName); + virtual String getPropertyValue(const String& propertyName); + virtual String getPropertyPriority(const String& propertyName); + virtual String getPropertyShorthand(const String& propertyName); + virtual bool isPropertyImplicit(const String& propertyName); + virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode&); + virtual String removeProperty(const String& propertyName, ExceptionCode&); + virtual String cssText() const; virtual void setCssText(const String&, ExceptionCode&); + virtual PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID); + virtual String getPropertyValueInternal(CSSPropertyID); + virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionCode&); - virtual String removeProperty(int propertyID, ExceptionCode&); - virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&); + virtual bool cssPropertyMatches(const CSSProperty*) const; PassRefPtr<CSSValue> valueForShadow(const ShadowData*, int, RenderStyle*) const; PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(RenderStyle*, const Color&) const; @@ -83,6 +93,11 @@ private: PassRefPtr<SVGPaint> adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint>, RenderStyle*) const; #endif +#if ENABLE(CSS_SHADERS) + PassRefPtr<CSSValue> valueForCustomFilterNumberParameter(const CustomFilterNumberParameter*) const; + PassRefPtr<CSSValue> valueForCustomFilterParameter(const CustomFilterParameter*) const; +#endif + #if ENABLE(CSS_FILTERS) PassRefPtr<CSSValue> valueForFilter(RenderStyle*) const; #endif diff --git a/Source/WebCore/css/CSSElementStyleDeclaration.cpp b/Source/WebCore/css/CSSElementStyleDeclaration.cpp deleted file mode 100644 index 81782619c..000000000 --- a/Source/WebCore/css/CSSElementStyleDeclaration.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CSSElementStyleDeclaration.h" - -#include "StyledElement.h" - -namespace WebCore { - -CSSStyleSheet* CSSElementStyleDeclaration::styleSheet() const -{ - if (m_element && m_element->document()) - return m_element->document()->elementSheet(); - return 0; -} - -} // namespace WebCore diff --git a/Source/WebCore/css/CSSElementStyleDeclaration.h b/Source/WebCore/css/CSSElementStyleDeclaration.h deleted file mode 100644 index 71ca518d5..000000000 --- a/Source/WebCore/css/CSSElementStyleDeclaration.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CSSElementStyleDeclaration_h -#define CSSElementStyleDeclaration_h - -#include "CSSMutableStyleDeclaration.h" - -namespace WebCore { - -class StyledElement; - -// Base class for CSSInlineStyleDeclaration and FontFaceStyleDeclaration (SVG). - -class CSSElementStyleDeclaration : public CSSMutableStyleDeclaration { -public: - StyledElement* element() const { return m_element; } - void clearElement() { m_element = 0; } - - virtual CSSStyleSheet* styleSheet() const; - -protected: - CSSElementStyleDeclaration(StyledElement* element, bool isInline) - : CSSMutableStyleDeclaration() - , m_element(element) - { - m_isElementStyleDeclaration = true; - m_isInlineStyleDeclaration = isInline; - } - - virtual ~CSSElementStyleDeclaration() { } - -private: - StyledElement* m_element; -}; - -} // namespace WebCore - -#endif // CSSElementStyleDeclaration_h diff --git a/Source/WebCore/css/CSSFontFaceRule.cpp b/Source/WebCore/css/CSSFontFaceRule.cpp index b4c697662..53d605dbd 100644 --- a/Source/WebCore/css/CSSFontFaceRule.cpp +++ b/Source/WebCore/css/CSSFontFaceRule.cpp @@ -41,7 +41,7 @@ String CSSFontFaceRule::cssText() const { String result("@font-face"); result += " { "; - result += m_style->cssText(); + result += m_style->asText(); result += "}"; return result; } diff --git a/Source/WebCore/css/CSSFontFaceRule.h b/Source/WebCore/css/CSSFontFaceRule.h index 3d1f76cf3..545c90a63 100644 --- a/Source/WebCore/css/CSSFontFaceRule.h +++ b/Source/WebCore/css/CSSFontFaceRule.h @@ -42,10 +42,11 @@ public: ~CSSFontFaceRule(); - CSSMutableStyleDeclaration* style() const { return m_style.get(); } + CSSStyleDeclaration* style() const { return m_style.get(); } String cssText() const; + CSSMutableStyleDeclaration* declaration() const { return m_style.get(); } void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) { m_style = style; } void addSubresourceStyleURLs(ListHashSet<KURL>& urls); diff --git a/Source/WebCore/css/CSSFontSelector.cpp b/Source/WebCore/css/CSSFontSelector.cpp index 4c90ae3d7..b13fffdda 100644 --- a/Source/WebCore/css/CSSFontSelector.cpp +++ b/Source/WebCore/css/CSSFontSelector.cpp @@ -86,7 +86,7 @@ bool CSSFontSelector::isEmpty() const void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) { // Obtain the font-family property and the src property. Both must be defined. - const CSSMutableStyleDeclaration* style = fontFaceRule->style(); + const CSSMutableStyleDeclaration* style = fontFaceRule->declaration(); RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSSPropertyFontFamily); RefPtr<CSSValue> src = style->getPropertyCSSValue(CSSPropertySrc); RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSSPropertyUnicodeRange); @@ -285,9 +285,9 @@ void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) for (int i = 0; i < familyLength; i++) { CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->itemWithoutBoundsCheck(i)); String familyName; - if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING) + if (item->isString()) familyName = static_cast<FontFamilyValue*>(item)->familyName(); - else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) { + else if (item->isIdent()) { // We need to use the raw text for all the generic family types, since @font-face is a way of actually // defining what font to use for those types. String familyName; @@ -615,6 +615,8 @@ void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*) // Balances incrementRequestCount() in beginLoadingFontSoon(). cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get()); } + // Ensure that if the request count reaches zero, the frame loader will know about it. + cachedResourceLoader->loadDone(); } } diff --git a/Source/WebCore/css/CSSGradientValue.cpp b/Source/WebCore/css/CSSGradientValue.cpp index 41977fb03..d8d7253d1 100644 --- a/Source/WebCore/css/CSSGradientValue.cpp +++ b/Source/WebCore/css/CSSGradientValue.cpp @@ -117,7 +117,7 @@ void CSSGradientValue::addStops(Gradient* gradient, RenderObject* renderer, Rend Color color = renderer->document()->styleSelector()->colorFromPrimitiveValue(stop.m_color.get()); float offset; - if (stop.m_position->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (stop.m_position->isPercentage()) offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100; else offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_NUMBER); @@ -150,10 +150,9 @@ void CSSGradientValue::addStops(Gradient* gradient, RenderObject* renderer, Rend stops[i].color = renderer->document()->styleSelector()->colorFromPrimitiveValue(stop.m_color.get()); if (stop.m_position) { - int type = stop.m_position->primitiveType(); - if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + if (stop.m_position->isPercentage()) stops[i].offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100; - else if (CSSPrimitiveValue::isUnitTypeLength(type)) { + else if (stop.m_position->isLength()) { float length = stop.m_position->computeLength<float>(style, rootStyle, style->effectiveZoom()); if (!computedGradientLength) { FloatSize gradientSize(gradientStart - gradientEnd); @@ -363,32 +362,28 @@ static float positionFromValue(CSSPrimitiveValue* value, RenderStyle* style, Ren { float zoomFactor = style->effectiveZoom(); - switch (value->primitiveType()) { - case CSSPrimitiveValue::CSS_NUMBER: + if (value->isNumber()) return value->getFloatValue() * zoomFactor; - case CSSPrimitiveValue::CSS_PERCENTAGE: + if (value->isPercentage()) return value->getFloatValue() / 100.f * (isHorizontal ? size.width() : size.height()); - case CSSPrimitiveValue::CSS_IDENT: - switch (value->getIdent()) { - case CSSValueTop: - ASSERT(!isHorizontal); - return 0; - case CSSValueLeft: - ASSERT(isHorizontal); - return 0; - case CSSValueBottom: - ASSERT(!isHorizontal); - return size.height(); - case CSSValueRight: - ASSERT(isHorizontal); - return size.width(); - } - - default: - return value->computeLength<float>(style, rootStyle, zoomFactor); + switch (value->getIdent()) { + case CSSValueTop: + ASSERT(!isHorizontal); + return 0; + case CSSValueLeft: + ASSERT(isHorizontal); + return 0; + case CSSValueBottom: + ASSERT(!isHorizontal); + return size.height(); + case CSSValueRight: + ASSERT(isHorizontal); + return size.width(); } + + return value->computeLength<float>(style, rootStyle, zoomFactor); } FloatPoint CSSGradientValue::computeEndPoint(CSSPrimitiveValue* first, CSSPrimitiveValue* second, RenderStyle* style, RenderStyle* rootStyle, const IntSize& size) @@ -416,8 +411,7 @@ bool CSSGradientValue::isCacheable() const if (!stop.m_position) continue; - unsigned short unitType = stop.m_position->primitiveType(); - if (unitType == CSSPrimitiveValue::CSS_EMS || unitType == CSSPrimitiveValue::CSS_EXS || unitType == CSSPrimitiveValue::CSS_REMS) + if (stop.m_position->isFontRelativeLength()) return false; } @@ -640,9 +634,9 @@ float CSSRadialGradientValue::resolveRadius(CSSPrimitiveValue* radius, RenderSty float zoomFactor = style->effectiveZoom(); float result = 0; - if (radius->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // Can the radius be a percentage? + if (radius->isNumber()) // Can the radius be a percentage? result = radius->getFloatValue() * zoomFactor; - else if (widthOrHeight && radius->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (widthOrHeight && radius->isPercentage()) result = *widthOrHeight * radius->getFloatValue() / 100; else result = radius->computeLength<float>(style, rootStyle, zoomFactor); @@ -761,29 +755,27 @@ PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(RenderObject* render } else { enum GradientShape { Circle, Ellipse }; GradientShape shape = Ellipse; - if (m_shape && m_shape->primitiveType() == CSSPrimitiveValue::CSS_IDENT && m_shape->getIdent() == CSSValueCircle) + if (m_shape && m_shape->getIdent() == CSSValueCircle) shape = Circle; enum GradientFill { ClosestSide, ClosestCorner, FarthestSide, FarthestCorner }; GradientFill fill = FarthestCorner; - if (m_sizingBehavior && m_sizingBehavior->primitiveType() == CSSPrimitiveValue::CSS_IDENT) { - switch (m_sizingBehavior->getIdent()) { - case CSSValueContain: - case CSSValueClosestSide: - fill = ClosestSide; - break; - case CSSValueClosestCorner: - fill = ClosestCorner; - break; - case CSSValueFarthestSide: - fill = FarthestSide; - break; - case CSSValueCover: - case CSSValueFarthestCorner: - fill = FarthestCorner; - break; - } + switch (m_sizingBehavior ? m_sizingBehavior->getIdent() : 0) { + case CSSValueContain: + case CSSValueClosestSide: + fill = ClosestSide; + break; + case CSSValueClosestCorner: + fill = ClosestCorner; + break; + case CSSValueFarthestSide: + fill = FarthestSide; + break; + case CSSValueCover: + case CSSValueFarthestCorner: + fill = FarthestCorner; + break; } // Now compute the end radii based on the second point, shape and fill. diff --git a/Source/WebCore/css/CSSInlineStyleDeclaration.h b/Source/WebCore/css/CSSInlineStyleDeclaration.h deleted file mode 100644 index 718e40959..000000000 --- a/Source/WebCore/css/CSSInlineStyleDeclaration.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2008, 2011 Apple Inc. All rights reserved. - * Copyright (C) 2011 Andreas Kling (kling@webkit.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CSSInlineStyleDeclaration_h -#define CSSInlineStyleDeclaration_h - -#include "CSSElementStyleDeclaration.h" - -namespace WebCore { - -class CSSInlineStyleDeclaration : public CSSElementStyleDeclaration { -public: - virtual ~CSSInlineStyleDeclaration() { } - - static PassRefPtr<CSSInlineStyleDeclaration> create(StyledElement* element) - { - return adoptRef(new CSSInlineStyleDeclaration(element)); - } - -private: - CSSInlineStyleDeclaration(StyledElement* element) - : CSSElementStyleDeclaration(element, /* isInline */ true) - { - } -}; - -inline CSSInlineStyleDeclaration* toCSSInlineStyleDeclaration(CSSMutableStyleDeclaration* decl) -{ - ASSERT(!decl || decl->isInlineStyleDeclaration()); - return static_cast<CSSInlineStyleDeclaration*>(decl); -} - -} // namespace WebCore - -#endif // CSSInlineStyleDeclaration_h diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp index c831b07df..c7d5d06f6 100644 --- a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp @@ -23,7 +23,6 @@ #include "CSSMutableStyleDeclaration.h" #include "CSSImageValue.h" -#include "CSSInlineStyleDeclaration.h" #include "CSSParser.h" #include "CSSPropertyLonghand.h" #include "CSSPropertyNames.h" @@ -66,17 +65,14 @@ public: #if ENABLE(MUTATION_OBSERVERS) if (!s_currentDecl->isInlineStyleDeclaration()) return; - - CSSInlineStyleDeclaration* inlineDecl = toCSSInlineStyleDeclaration(s_currentDecl); - if (!inlineDecl->element()) + if (!s_currentDecl->parentElement()) return; - - m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(inlineDecl->element(), HTMLNames::styleAttr); + m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(s_currentDecl->parentElement(), HTMLNames::styleAttr); if (!m_mutationRecipients) return; - AtomicString oldValue = m_mutationRecipients->isOldValueRequested() ? inlineDecl->element()->getAttribute(HTMLNames::styleAttr) : nullAtom; - m_mutation = MutationRecord::createAttributes(inlineDecl->element(), HTMLNames::styleAttr, oldValue); + AtomicString oldValue = m_mutationRecipients->isOldValueRequested() ? s_currentDecl->parentElement()->getAttribute(HTMLNames::styleAttr) : nullAtom; + m_mutation = MutationRecord::createAttributes(s_currentDecl->parentElement(), HTMLNames::styleAttr, oldValue); #endif } @@ -91,17 +87,16 @@ public: m_mutationRecipients->enqueueMutationRecord(m_mutation); s_shouldDeliver = false; #endif - if (!s_shouldNotifyInspector) { s_currentDecl = 0; return; } - - CSSInlineStyleDeclaration* inlineDecl = toCSSInlineStyleDeclaration(s_currentDecl); + // We have to clear internal state before calling Inspector's code. + CSSMutableStyleDeclaration* localCopyStyleDecl = s_currentDecl; s_currentDecl = 0; s_shouldNotifyInspector = false; - if (inlineDecl->element() && inlineDecl->element()->document()) - InspectorInstrumentation::didInvalidateStyleAttr(inlineDecl->element()->document(), inlineDecl->element()); + if (localCopyStyleDecl->isInlineStyleDeclaration() && localCopyStyleDecl->parentElement() && localCopyStyleDecl->parentElement()->document()) + InspectorInstrumentation::didInvalidateStyleAttr(localCopyStyleDecl->parentElement()->document(), localCopyStyleDecl->parentElement()); } #if ENABLE(MUTATION_OBSERVERS) @@ -139,7 +134,6 @@ bool StyleAttributeMutationScope::s_shouldDeliver = false; } // namespace CSSMutableStyleDeclaration::CSSMutableStyleDeclaration() - : CSSStyleDeclaration(0) { // This constructor is used for various inline style declarations, so disable strict parsing. m_strictParsing = false; @@ -180,13 +174,17 @@ CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CS } } +CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(StyledElement* element) + : CSSStyleDeclaration(element) +{ +} + CSSMutableStyleDeclaration::~CSSMutableStyleDeclaration() { } void CSSMutableStyleDeclaration::copyPropertiesFrom(const CSSMutableStyleDeclaration& other) { - ASSERT(!m_iteratorCount); m_properties = other.m_properties; } @@ -613,8 +611,6 @@ bool CSSMutableStyleDeclaration::removeShorthandProperty(int propertyID, bool no String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif @@ -646,15 +642,13 @@ String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyCha void CSSMutableStyleDeclaration::setNeedsStyleRecalc() { - if (isElementStyleDeclaration() && static_cast<CSSElementStyleDeclaration*>(this)->element()) { - StyledElement* element = static_cast<CSSElementStyleDeclaration*>(this)->element(); - if (!isInlineStyleDeclaration()) - element->setNeedsStyleRecalc(FullStyleChange); - else { - element->setNeedsStyleRecalc(InlineStyleChange); - element->invalidateStyleAttribute(); - StyleAttributeMutationScope(this).didInvalidateStyleAttr(); - } + if (isInlineStyleDeclaration()) { + StyledElement* element = parentElement(); + if (!element) + return; + element->setNeedsStyleRecalc(InlineStyleChange); + element->invalidateStyleAttribute(); + StyleAttributeMutationScope(this).didInvalidateStyleAttr(); return; } @@ -664,10 +658,21 @@ void CSSMutableStyleDeclaration::setNeedsStyleRecalc() } } -bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const +bool CSSMutableStyleDeclaration::propertyIsImportant(int propertyID) const { const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->isImportant() : false; + if (property) + return property->isImportant(); + + CSSPropertyLonghand longhands = longhandForProperty(propertyID); + if (!longhands.length()) + return false; + + for (unsigned i = 0; i < longhands.length(); ++i) { + if (!propertyIsImportant(longhands.properties()[i])) + return false; + } + return true; } int CSSMutableStyleDeclaration::getPropertyShorthand(int propertyID) const @@ -682,22 +687,8 @@ bool CSSMutableStyleDeclaration::isPropertyImplicit(int propertyID) const return property ? property->isImplicit() : false; } -void CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, ExceptionCode& ec) -{ - ec = 0; - setProperty(propertyID, value, important, true); -} - -String CSSMutableStyleDeclaration::removeProperty(int propertyID, ExceptionCode& ec) -{ - ec = 0; - return removeProperty(propertyID, true, true); -} - bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, bool notifyChanged) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif @@ -728,10 +719,8 @@ bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value return true; } -void CSSMutableStyleDeclaration::setPropertyInternal(const CSSProperty& property, CSSProperty* slot) +void CSSMutableStyleDeclaration::setProperty(const CSSProperty& property, CSSProperty* slot) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif @@ -753,7 +742,7 @@ void CSSMutableStyleDeclaration::setPropertyInternal(const CSSProperty& property bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged) { CSSProperty property(propertyID, CSSPrimitiveValue::createIdentifier(value), important); - setPropertyInternal(property); + setProperty(property); if (notifyChanged) setNeedsStyleRecalc(); return true; @@ -762,7 +751,7 @@ bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool imp bool CSSMutableStyleDeclaration::setProperty(int propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important, bool notifyChanged) { CSSProperty property(propertyID, CSSPrimitiveValue::create(value, unit), important); - setPropertyInternal(property); + setProperty(property); if (notifyChanged) setNeedsStyleRecalc(); return true; @@ -770,8 +759,6 @@ bool CSSMutableStyleDeclaration::setProperty(int propertyID, double value, CSSPr void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif @@ -789,8 +776,6 @@ void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty* const* properties, int numProperties) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif @@ -809,14 +794,12 @@ void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty* const* p void CSSMutableStyleDeclaration::addParsedProperty(const CSSProperty& property) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif // Only add properties that have no !important counterpart present - if (!getPropertyPriority(property.id()) || property.isImportant()) { + if (!propertyIsImportant(property.id()) || property.isImportant()) { removeProperty(property.id(), false, false); m_properties.append(property); } @@ -826,9 +809,9 @@ void CSSMutableStyleDeclaration::addParsedProperty(const CSSProperty& property) #endif } -unsigned CSSMutableStyleDeclaration::virtualLength() const +unsigned CSSMutableStyleDeclaration::length() const { - return length(); + return propertyCount(); } String CSSMutableStyleDeclaration::item(unsigned i) const @@ -838,7 +821,7 @@ String CSSMutableStyleDeclaration::item(unsigned i) const return getPropertyName(static_cast<CSSPropertyID>(m_properties[i].id())); } -String CSSMutableStyleDeclaration::cssText() const +String CSSMutableStyleDeclaration::asText() const { String result = ""; @@ -909,8 +892,6 @@ void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& e void CSSMutableStyleDeclaration::merge(const CSSMutableStyleDeclaration* other, bool argOverridesOnConflict) { - ASSERT(!m_iteratorCount); - #if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif @@ -922,7 +903,7 @@ void CSSMutableStyleDeclaration::merge(const CSSMutableStyleDeclaration* other, if (old) { if (!argOverridesOnConflict && old->value()) continue; - setPropertyInternal(toMerge, old); + setProperty(toMerge, old); } else m_properties.append(toMerge); } @@ -983,8 +964,6 @@ void CSSMutableStyleDeclaration::removeBlockProperties() bool CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged) { - ASSERT(!m_iteratorCount); - if (m_properties.isEmpty()) return false; @@ -1052,4 +1031,119 @@ CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID) return 0; } +String CSSMutableStyleDeclaration::cssText() const +{ + return asText(); +} + +PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(const String& propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return 0; + return getPropertyCSSValue(propertyID); +} + +String CSSMutableStyleDeclaration::getPropertyValue(const String &propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return String(); + return getPropertyValue(propertyID); +} + +String CSSMutableStyleDeclaration::getPropertyPriority(const String& propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return String(); + return propertyIsImportant(propertyID) ? "important" : ""; +} + +String CSSMutableStyleDeclaration::getPropertyShorthand(const String& propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return String(); + int shorthandID = getPropertyShorthand(propertyID); + if (!shorthandID) + return String(); + return getPropertyName(static_cast<CSSPropertyID>(shorthandID)); +} + +bool CSSMutableStyleDeclaration::isPropertyImplicit(const String& propertyName) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return false; + return isPropertyImplicit(propertyID); +} + +void CSSMutableStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode& ec) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return; + bool important = priority.find("important", 0, false) != notFound; + ec = 0; + setProperty(propertyID, value, important, true); +} + +String CSSMutableStyleDeclaration::removeProperty(const String& propertyName, ExceptionCode& ec) +{ + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return String(); + ec = 0; + return removeProperty(propertyID, true, true); +} + +PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID) +{ + return getPropertyCSSValue(propertyID); +} + +String CSSMutableStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID) +{ + return getPropertyValue(propertyID); +} + +void CSSMutableStyleDeclaration::setPropertyInternal(CSSPropertyID propertyID, const String& value, bool important, ExceptionCode& ec) +{ + ec = 0; + setProperty(propertyID, value, important, true); +} + +PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyPropertiesInSet(const int* set, unsigned length) const +{ + Vector<CSSProperty> list; + list.reserveInitialCapacity(length); + for (unsigned i = 0; i < length; ++i) { + RefPtr<CSSValue> value = getPropertyCSSValue(set[i]); + if (value) + list.append(CSSProperty(set[i], value.release(), false)); + } + return CSSMutableStyleDeclaration::create(list); +} + +bool CSSMutableStyleDeclaration::cssPropertyMatches(const CSSProperty* property) const +{ + RefPtr<CSSValue> value = getPropertyCSSValue(property->id()); + return value && value->cssText() == property->value()->cssText(); +} + +void CSSMutableStyleDeclaration::removeEquivalentProperties(const CSSStyleDeclaration* style) +{ + Vector<int> propertiesToRemove; + size_t size = m_properties.size(); + for (size_t i = 0; i < size; ++i) { + const CSSProperty& property = m_properties[i]; + if (style->cssPropertyMatches(&property)) + propertiesToRemove.append(property.id()); + } + // FIXME: This should use mass removal. + for (unsigned i = 0; i < propertiesToRemove.size(); ++i) + removeProperty(propertiesToRemove[i]); +} + } // namespace WebCore diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.h b/Source/WebCore/css/CSSMutableStyleDeclaration.h index f483fbe5c..73af49f2e 100644 --- a/Source/WebCore/css/CSSMutableStyleDeclaration.h +++ b/Source/WebCore/css/CSSMutableStyleDeclaration.h @@ -31,27 +31,7 @@ namespace WebCore { -class CSSMutableStyleDeclarationConstIterator { -public: - CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclaration* decl, CSSProperty* current); - CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclarationConstIterator& o); - ~CSSMutableStyleDeclarationConstIterator(); - - const CSSProperty& operator*() const { return *m_current; } - const CSSProperty* operator->() const { return m_current; } - - bool operator!=(const CSSMutableStyleDeclarationConstIterator& o) { ASSERT(m_decl == o.m_decl); return m_current != o.m_current; } - bool operator==(const CSSMutableStyleDeclarationConstIterator& o) { ASSERT(m_decl == o.m_decl); return m_current == o.m_current; } - - CSSMutableStyleDeclarationConstIterator& operator=(const CSSMutableStyleDeclarationConstIterator& o); - - CSSMutableStyleDeclarationConstIterator& operator++(); - CSSMutableStyleDeclarationConstIterator& operator--(); - -private: - const CSSMutableStyleDeclaration* m_decl; - CSSProperty* m_current; -}; +class StyledElement; class CSSMutableStyleDeclaration : public CSSStyleDeclaration { public: @@ -73,39 +53,30 @@ public: { return adoptRef(new CSSMutableStyleDeclaration(0, properties)); } + static PassRefPtr<CSSMutableStyleDeclaration> createInline(StyledElement* element) + { + return adoptRef(new CSSMutableStyleDeclaration(element)); + } - // Used by StyledElement::copyNonAttributeProperties(). - void copyPropertiesFrom(const CSSMutableStyleDeclaration&); - - typedef CSSMutableStyleDeclarationConstIterator const_iterator; - - const_iterator begin() { return const_iterator(this, m_properties.begin()); } - const_iterator end() { return const_iterator(this, m_properties.end()); } - - virtual String cssText() const; - virtual void setCssText(const String&, ExceptionCode&); - - virtual unsigned virtualLength() const; - unsigned length() const { return m_properties.size(); } - - virtual String item(unsigned index) const; - - virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; - virtual String getPropertyValue(int propertyID) const; - virtual bool getPropertyPriority(int propertyID) const; - virtual int getPropertyShorthand(int propertyID) const; - virtual bool isPropertyImplicit(int propertyID) const; + unsigned propertyCount() const { return m_properties.size(); } + bool isEmpty() const { return m_properties.isEmpty(); } + const CSSProperty& propertyAt(unsigned index) const { return m_properties[index]; } - virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&); - virtual String removeProperty(int propertyID, ExceptionCode&); + PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const; + String getPropertyValue(int propertyID) const; + bool propertyIsImportant(int propertyID) const; + int getPropertyShorthand(int propertyID) const; + bool isPropertyImplicit(int propertyID) const; virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const; bool setProperty(int propertyID, int value, bool important = false) { return setProperty(propertyID, value, important, true); } bool setProperty(int propertyId, double value, CSSPrimitiveValue::UnitTypes unit, bool important = false) { return setProperty(propertyId, value, unit, important, true); } bool setProperty(int propertyID, const String& value, bool important = false) { return setProperty(propertyID, value, important, true); } - + void setProperty(const CSSProperty&, CSSProperty* slot = 0); + void removeProperty(int propertyID) { removeProperty(propertyID, true, false); } + String removeProperty(int propertyID, bool notifyChanged, bool returnText); // The following parses an entire new style declaration. void parseDeclaration(const String& styleDeclaration); @@ -127,19 +98,40 @@ public: void addSubresourceStyleURLs(ListHashSet<KURL>&); -protected: - CSSMutableStyleDeclaration(CSSRule* parentRule); - CSSMutableStyleDeclaration(); + // Used by StyledElement::copyNonAttributeProperties(). + void copyPropertiesFrom(const CSSMutableStyleDeclaration&); - void setPropertyInternal(const CSSProperty&, CSSProperty* slot = 0); - String removeProperty(int propertyID, bool notifyChanged, bool returnText); + void removeEquivalentProperties(const CSSStyleDeclaration*); + + PassRefPtr<CSSMutableStyleDeclaration> copyPropertiesInSet(const int* set, unsigned length) const; + + String asText() const; private: + CSSMutableStyleDeclaration(); + CSSMutableStyleDeclaration(CSSRule* parentRule); CSSMutableStyleDeclaration(CSSRule* parentRule, const Vector<CSSProperty>&); CSSMutableStyleDeclaration(CSSRule* parentRule, const CSSProperty* const *, int numProperties); + CSSMutableStyleDeclaration(StyledElement*); virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable(); + // CSSOM functions. Don't make these public. + virtual unsigned length() const; + virtual String item(unsigned index) const; + virtual PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName); + virtual String getPropertyValue(const String& propertyName); + virtual String getPropertyPriority(const String& propertyName); + virtual String getPropertyShorthand(const String& propertyName); + virtual bool isPropertyImplicit(const String& propertyName); + virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode&); + virtual String removeProperty(const String& propertyName, ExceptionCode&); + virtual String cssText() const; + virtual void setCssText(const String&, ExceptionCode&); + virtual PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID); + virtual String getPropertyValueInternal(CSSPropertyID); + virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionCode&); + void setNeedsStyleRecalc(); String getShorthandValue(const int* properties, size_t) const; @@ -160,62 +152,14 @@ private: bool removeShorthandProperty(int propertyID, bool notifyChanged); bool removePropertiesInSet(const int* set, unsigned length, bool notifyChanged); - Vector<CSSProperty>::const_iterator findPropertyWithId(int propertyId) const; - Vector<CSSProperty>::iterator findPropertyWithId(int propertyId); + virtual bool cssPropertyMatches(const CSSProperty*) const; - Vector<CSSProperty, 4> m_properties; + const CSSProperty* findPropertyWithId(int propertyId) const; + CSSProperty* findPropertyWithId(int propertyId); - friend class CSSMutableStyleDeclarationConstIterator; + Vector<CSSProperty, 4> m_properties; }; -inline CSSMutableStyleDeclarationConstIterator::CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclaration* decl, CSSProperty* current) -: m_decl(decl) -, m_current(current) -{ -#ifndef NDEBUG - const_cast<CSSMutableStyleDeclaration*>(m_decl)->m_iteratorCount++; -#endif -} - -inline CSSMutableStyleDeclarationConstIterator::CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclarationConstIterator& o) -: m_decl(o.m_decl) -, m_current(o.m_current) -{ -#ifndef NDEBUG - const_cast<CSSMutableStyleDeclaration*>(m_decl)->m_iteratorCount++; -#endif -} - -inline CSSMutableStyleDeclarationConstIterator::~CSSMutableStyleDeclarationConstIterator() -{ -#ifndef NDEBUG - const_cast<CSSMutableStyleDeclaration*>(m_decl)->m_iteratorCount--; -#endif -} - -inline CSSMutableStyleDeclarationConstIterator& CSSMutableStyleDeclarationConstIterator::operator=(const CSSMutableStyleDeclarationConstIterator& o) -{ - m_decl = o.m_decl; - m_current = o.m_current; -#ifndef NDEBUG - const_cast<CSSMutableStyleDeclaration*>(m_decl)->m_iteratorCount++; -#endif - return *this; -} - -inline CSSMutableStyleDeclarationConstIterator& CSSMutableStyleDeclarationConstIterator::operator++() -{ - ASSERT(m_current != const_cast<CSSMutableStyleDeclaration*>(m_decl)->m_properties.end()); - ++m_current; - return *this; -} - -inline CSSMutableStyleDeclarationConstIterator& CSSMutableStyleDeclarationConstIterator::operator--() -{ - --m_current; - return *this; -} - } // namespace WebCore #endif // CSSMutableStyleDeclaration_h diff --git a/Source/WebCore/css/CSSPageRule.idl b/Source/WebCore/css/CSSPageRule.idl index 989fd8d50..a71c24ba8 100644 --- a/Source/WebCore/css/CSSPageRule.idl +++ b/Source/WebCore/css/CSSPageRule.idl @@ -23,7 +23,7 @@ module css { // Introduced in DOM Level 2: interface CSSPageRule : CSSRule { - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString selectorText; + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString selectorText; readonly attribute CSSStyleDeclaration style; diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index 2f5cab605..ac8d177e5 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -26,7 +26,7 @@ #include "CSSParser.h" #include "CSSAspectRatioValue.h" -#include "CSSBorderImageValue.h" +#include "CSSBorderImage.h" #include "CSSCanvasValue.h" #include "CSSCharsetRule.h" #include "CSSCrossfadeValue.h" @@ -73,6 +73,7 @@ #include "Pair.h" #include "Rect.h" #include "RenderTheme.h" +#include "Settings.h" #include "ShadowValue.h" #if ENABLE(CSS_FILTERS) #include "WebKitCSSFilterValue.h" @@ -200,7 +201,9 @@ CSSParser::CSSParser(bool strictParsing) , m_propertyRange(UINT_MAX, UINT_MAX) , m_ruleRangeMap(0) , m_currentRuleData(0) - , yy_start(1) + , m_parsingMode(NormalMode) + , m_currentCharacter(0) + , m_token(0) , m_lineNumber(0) , m_lastSelectorLineNumber(0) , m_allowImportRules(true) @@ -242,27 +245,22 @@ void CSSParserString::lower() void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix) { - int length = string.length() + strlen(prefix) + strlen(suffix) + 2; + int length = string.length() + strlen(prefix) + strlen(suffix) + 1; - m_data = adoptArrayPtr(new UChar[length]); + m_dataStart = adoptArrayPtr(new UChar[length]); for (unsigned i = 0; i < strlen(prefix); i++) - m_data[i] = prefix[i]; + m_dataStart[i] = prefix[i]; - memcpy(m_data.get() + strlen(prefix), string.characters(), string.length() * sizeof(UChar)); + memcpy(m_dataStart.get() + strlen(prefix), string.characters(), string.length() * sizeof(UChar)); unsigned start = strlen(prefix) + string.length(); unsigned end = start + strlen(suffix); for (unsigned i = start; i < end; i++) - m_data[i] = suffix[i - start]; + m_dataStart[i] = suffix[i - start]; - m_data[length - 1] = 0; - m_data[length - 2] = 0; + m_dataStart[length - 1] = 0; - yy_hold_char = 0; - yyleng = 0; - yytext = m_data.get(); - yy_c_buf_p = yytext; - yy_hold_char = *yy_c_buf_p; + m_currentCharacter = m_tokenStart = m_dataStart.get(); resetRuleBodyMarks(); } @@ -413,28 +411,58 @@ static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativ static bool parseSimpleLengthValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict, CSSStyleSheet* contextStyleSheet = 0) { - const UChar* characters = string.characters(); - unsigned length = string.length(); - if (!characters || !length) - return false; bool acceptsNegativeNumbers; - if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) + unsigned length = string.length(); + + if (!length) return false; + double number; + bool ok; CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; - if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') { - length -= 2; - unit = CSSPrimitiveValue::CSS_PX; - } else if (length > 1 && characters[length - 1] == '%') { - length -= 1; - unit = CSSPrimitiveValue::CSS_PERCENTAGE; + + if (string.is8Bit()) { + const LChar* characters8 = string.characters8(); + if (!characters8) + return false; + + if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) + return false; + + if (length > 2 && (characters8[length - 2] | 0x20) == 'p' && (characters8[length - 1] | 0x20) == 'x') { + length -= 2; + unit = CSSPrimitiveValue::CSS_PX; + } else if (length > 1 && characters8[length - 1] == '%') { + length -= 1; + unit = CSSPrimitiveValue::CSS_PERCENTAGE; + } + + // We rely on charactersToDouble for validation as well. The function + // will set "ok" to "false" if the entire passed-in character range does + // not represent a double. + number = charactersToDouble(characters8, length, &ok); + } else { + const UChar* characters16 = string.characters16(); + if (!characters16) + return false; + + if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) + return false; + + if (length > 2 && (characters16[length - 2] | 0x20) == 'p' && (characters16[length - 1] | 0x20) == 'x') { + length -= 2; + unit = CSSPrimitiveValue::CSS_PX; + } else if (length > 1 && characters16[length - 1] == '%') { + length -= 1; + unit = CSSPrimitiveValue::CSS_PERCENTAGE; + } + + // We rely on charactersToDouble for validation as well. The function + // will set "ok" to "false" if the entire passed-in character range does + // not represent a double. + number = charactersToDouble(characters16, length, &ok); } - // We rely on charactersToDouble for validation as well. The function - // will set "ok" to "false" if the entire passed-in character range does - // not represent a double. - bool ok; - double number = charactersToDouble(characters, length, &ok); if (!ok) return false; if (unit == CSSPrimitiveValue::CSS_NUMBER) { @@ -456,18 +484,18 @@ static bool parseSimpleLengthValue(CSSMutableStyleDeclaration* declaration, int return true; } -bool CSSParser::parseMappedAttributeValue(CSSMappedAttributeDeclaration* declaration, StyledElement* element, int propertyId, const String& value) +bool CSSParser::parseMappedAttributeValue(CSSMappedAttributeDeclaration* mappedAttribute, StyledElement* element, int propertyId, const String& value) { - ASSERT(declaration); + ASSERT(mappedAttribute); ASSERT(element); ASSERT(element->document()); CSSStyleSheet* elementSheet = element->document()->elementSheet(); - if (parseSimpleLengthValue(declaration, propertyId, value, false, false, elementSheet)) + if (parseSimpleLengthValue(mappedAttribute->declaration(), propertyId, value, false, false, elementSheet)) return true; - if (parseColorValue(declaration, propertyId, value, false, false, elementSheet)) + if (parseColorValue(mappedAttribute->declaration(), propertyId, value, false, false, elementSheet)) return true; CSSParser parser(false); - return parser.parseValue(declaration, propertyId, value, false, elementSheet); + return parser.parseValue(mappedAttribute->declaration(), propertyId, value, false, elementSheet); } bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) @@ -527,7 +555,7 @@ bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict) return false; CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); - if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_RGBCOLOR) + if (!primitiveValue->isRGBColor()) return false; color = primitiveValue->getRGBA32Value(); @@ -691,13 +719,54 @@ Document* CSSParser::findDocument() const return m_styleSheet->findDocument(); } +bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags) +{ + if (!parseCalculation(value)) + return false; + + bool b = false; + switch (m_parsedCalculation->category()) { + case CalcLength: + b = (unitflags & FLength); + break; + case CalcPercent: + b = (unitflags & FPercent); + // FIXME calc (http://webkit.org/b/16662): test FNonNeg here, eg + // if (b && (unitflags & FNonNeg) && m_parsedCalculation->doubleValue() < 0) + // b = false; + break; + case CalcNumber: + b = (unitflags & FNumber); + if (!b && (unitflags & FInteger) && m_parsedCalculation->isInt()) + b = true; + // FIXME calc (http://webkit.org/b/16662): test FNonNeg here, eg + // if (b && (unitflags & FNonNeg) && m_parsedCalculation->doubleValue() < 0) + // b = false; + break; + case CalcPercentLength: + b = (unitflags & FPercent) && (unitflags & FLength); + break; + case CalcPercentNumber: + b = (unitflags & FPercent) && (unitflags & FNumber); + break; + case CalcOther: + break; + } + if (!b) + m_parsedCalculation.release(); + return b; +} + bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, bool strict) { + if (isCalculation(value)) + return validCalculationUnit(value, unitflags); + bool b = false; switch (value->unit) { case CSSPrimitiveValue::CSS_NUMBER: b = (unitflags & FNumber); - if (!b && ((unitflags & (FLength | FAngle | FTime)) && (value->fValue == 0 || !strict))) { + if (!b && ((unitflags & (FLength | FAngle | FTime)) && (!value->fValue || !strict))) { value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX : ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS); b = true; @@ -743,6 +812,14 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, bool strict) inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value) { + if (m_parsedCalculation) { + ASSERT(isCalculation(value)); + // FIXME calc() http://webkit.org/b/16662: create a CSSPrimitiveValue here, ie + // return CSSPrimitiveValue::create(m_parsedCalculation.release()); + m_parsedCalculation.release(); + return 0; + } + ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)); return cssValuePool()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); @@ -840,6 +917,11 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int id, CSSP return createPrimitiveNumericValue(value); if (value->unit >= CSSParserValue::Q_EMS) return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); + if (isCalculation(value)) + // FIXME calc() http://webkit.org/b/16662: create a primitive value here, ie + // return CSSPrimitiveValue::create(m_parsedCalculation.release()); + m_parsedCalculation.release(); + return 0; } @@ -853,6 +935,10 @@ bool CSSParser::parseValue(int propId, bool important) if (!value) return false; + // Note: m_parsedCalculation is used to pass the calc value to validUnit and then cleared at the end of this function. + // FIXME: This is to avoid having to pass parsedCalc to all validUnit callers. + ASSERT(!m_parsedCalculation); + int id = value->id; // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to @@ -1037,7 +1123,7 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyClear: // none | left | right | both | inherit if (id == CSSValueNone || id == CSSValueLeft - || id == CSSValueRight|| id == CSSValueBoth) + || id == CSSValueRight || id == CSSValueBoth) validPrimitive = true; break; @@ -1315,7 +1401,7 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyMaxWidth: // <length> | <percentage> | none | inherit case CSSPropertyWebkitMaxLogicalWidth: case CSSPropertyWebkitMaxLogicalHeight: - if (id == CSSValueNone || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic) { + if (id == CSSValueNone) { validPrimitive = true; break; } @@ -1473,7 +1559,10 @@ bool CSSParser::parseValue(int propId, bool important) validPrimitive = true; break; - case CSSPropertyBorderImage: + case CSSPropertyBorderImage: { + RefPtr<CSSValue> result; + return parseBorderImage(propId, result, important); + } case CSSPropertyWebkitBorderImage: case CSSPropertyWebkitMaskBoxImage: { RefPtr<CSSValue> result; @@ -1635,7 +1724,10 @@ bool CSSParser::parseValue(int propId, bool important) } break; case CSSPropertyWebkitFlexPack: - validPrimitive = id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter || id == CSSValueJustify; + validPrimitive = id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter || id == CSSValueJustify || id == CSSValueDistribute; + break; + case CSSPropertyWebkitFlexAlign: + validPrimitive = id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter || id == CSSValueBaseline || id == CSSValueStretch; break; case CSSPropertyWebkitFlexItemAlign: validPrimitive = id == CSSValueAuto || id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter || id == CSSValueBaseline || id == CSSValueStretch; @@ -1972,7 +2064,7 @@ bool CSSParser::parseValue(int propId, bool important) } break; case CSSPropertyWebkitLineGridSnap: - if (id == CSSValueNone || id == CSSValueBaseline || id == CSSValueBounds) + if (id == CSSValueNone || id == CSSValueBaseline || id == CSSValueContain) validPrimitive = true; break; case CSSPropertyWebkitLocale: @@ -2233,6 +2325,13 @@ bool CSSParser::parseValue(int propId, bool important) validPrimitive = true; break; + case CSSPropertyWebkitFontVariantLigatures: + if (id == CSSValueNormal) + validPrimitive = true; + else + return parseFontVariantLigatures(important); + break; + case CSSPropertyWebkitWrapShapeInside: case CSSPropertyWebkitWrapShapeOutside: if (id == CSSValueAuto) @@ -2267,6 +2366,7 @@ bool CSSParser::parseValue(int propId, bool important) parsedValue = parseValidPrimitive(id, value); m_valueList->next(); } + ASSERT(!m_parsedCalculation); if (parsedValue) { if (!m_valueList->current() || inShorthand()) { addProperty(propId, parsedValue.release(), important); @@ -2883,7 +2983,7 @@ PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() int id = m_valueList->current()->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor || (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict)) - return cssValuePool()->createIdentifierValue(id); + return cssValuePool()->createIdentifierValue(id); return parseColor(); } @@ -2974,8 +3074,11 @@ PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* v } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) { cumulativeFlags |= YFillPosition; individualFlag = YFillPosition; - } else + } else { + if (m_parsedCalculation) + m_parsedCalculation.release(); return 0; + } return createPrimitiveNumericValue(valueList->current()); } return 0; @@ -4774,10 +4877,10 @@ static inline bool mightBeRGBA(const UChar* characters, unsigned length) if (length < 5) return false; return characters[4] == '(' - && (characters[0] | 0x20) == 'r' - && (characters[1] | 0x20) == 'g' - && (characters[2] | 0x20) == 'b' - && (characters[3] | 0x20) == 'a'; + && isASCIIAlphaCaselessEqual(characters[0], 'r') + && isASCIIAlphaCaselessEqual(characters[1], 'g') + && isASCIIAlphaCaselessEqual(characters[2], 'b') + && isASCIIAlphaCaselessEqual(characters[3], 'a'); } static inline bool mightBeRGB(const UChar* characters, unsigned length) @@ -4785,9 +4888,9 @@ static inline bool mightBeRGB(const UChar* characters, unsigned length) if (length < 4) return false; return characters[3] == '(' - && (characters[0] | 0x20) == 'r' - && (characters[1] | 0x20) == 'g' - && (characters[2] | 0x20) == 'b'; + && isASCIIAlphaCaselessEqual(characters[0], 'r') + && isASCIIAlphaCaselessEqual(characters[1], 'g') + && isASCIIAlphaCaselessEqual(characters[2], 'b'); } bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict) @@ -4857,22 +4960,49 @@ bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict) } return false; } + +inline double CSSParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueCondition releaseCalc) +{ + // FIXME calc (http://webkit.org/b/16662): evaluate calc here, eg + // const double result = m_parsedCalculation ? m_parsedCalculation->doubleValue() : v->fValue; + const double result = m_parsedCalculation ? 0 : v->fValue; + if (releaseCalc == ReleaseParsedCalcValue) + m_parsedCalculation.release(); + return result; +} -static inline int colorIntFromValue(CSSParserValue* v) +bool CSSParser::isCalculation(CSSParserValue* value) { - if (v->fValue <= 0.0) + return (value->unit == CSSParserValue::Function) + && (equalIgnoringCase(value->function->name, "-webkit-calc(") + || equalIgnoringCase(value->function->name, "-webkit-min(") + || equalIgnoringCase(value->function->name, "-webkit-max(")); +} + +inline int CSSParser::colorIntFromValue(CSSParserValue* v) +{ + bool isPercent; + + if (m_parsedCalculation) + isPercent = m_parsedCalculation->category() == CalcPercent; + else + isPercent = v->unit == CSSPrimitiveValue::CSS_PERCENTAGE; + + const double value = parsedDouble(v, ReleaseParsedCalcValue); + + if (value <= 0.0) return 0; - if (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE) { - if (v->fValue >= 100.0) + if (isPercent) { + if (value >= 100.0) return 255; - return static_cast<int>(v->fValue * 256.0 / 100.0); + return static_cast<int>(value * 256.0 / 100.0); } - if (v->fValue >= 255.0) + if (value >= 255.0) return 255; - return static_cast<int>(v->fValue); + return static_cast<int>(value); } bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha) @@ -4887,6 +5017,7 @@ bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, boo unitType = FPercent; else return false; + colorArray[0] = colorIntFromValue(v); for (int i = 1; i < 3; i++) { v = args->next(); @@ -4904,9 +5035,10 @@ bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, boo v = args->next(); if (!validUnit(v, FNumber, true)) return false; + const double value = parsedDouble(v, ReleaseParsedCalcValue); // Convert the floating pointer number of alpha to an integer in the range [0, 256), // with an equal distribution across all 256 values. - colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * nextafter(256.0, 0.0)); + colorArray[3] = static_cast<int>(max(0.0, min(1.0, value)) * nextafter(256.0, 0.0)); } return true; } @@ -4924,7 +5056,7 @@ bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bo if (!validUnit(v, FNumber, true)) return false; // normalize the Hue value and change it to be between 0 and 1.0 - colorArray[0] = (((static_cast<int>(v->fValue) % 360) + 360) % 360) / 360.0; + colorArray[0] = (((static_cast<int>(parsedDouble(v, ReleaseParsedCalcValue)) % 360) + 360) % 360) / 360.0; for (int i = 1; i < 3; i++) { v = args->next(); if (v->unit != CSSParserValue::Operator && v->iValue != ',') @@ -4932,7 +5064,7 @@ bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bo v = args->next(); if (!validUnit(v, FPercent, true)) return false; - colorArray[i] = max(0.0, min(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0 + colorArray[i] = max(0.0, min(100.0, parsedDouble(v, ReleaseParsedCalcValue))) / 100.0; // needs to be value between 0 and 1.0 } if (parseAlpha) { v = args->next(); @@ -4941,7 +5073,7 @@ bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bo v = args->next(); if (!validUnit(v, FNumber, true)) return false; - colorArray[3] = max(0.0, min(1.0, v->fValue)); + colorArray[3] = max(0.0, min(1.0, parsedDouble(v, ReleaseParsedCalcValue))); } return true; } @@ -5009,9 +5141,9 @@ bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) // This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return) // without the allowBreak bit being set, then it will clean up all of the objects and destroy them. struct ShadowParseContext { - ShadowParseContext(CSSPropertyID prop, CSSValuePool* cssValuePool) + ShadowParseContext(CSSPropertyID prop, CSSParser* parser) : property(prop) - , m_cssValuePool(cssValuePool) + , m_parser(parser) , allowX(true) , allowY(false) , allowBlur(false) @@ -5054,7 +5186,7 @@ struct ShadowParseContext { void commitLength(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val = m_cssValuePool->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + RefPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v); if (allowX) { x = val.release(); @@ -5096,7 +5228,7 @@ struct ShadowParseContext { void commitStyle(CSSParserValue* v) { - style = m_cssValuePool->createIdentifierValue(v->id); + style = m_parser->cssValuePool()->createIdentifierValue(v->id); allowStyle = false; if (allowX) allowBreak = false; @@ -5108,7 +5240,7 @@ struct ShadowParseContext { } CSSPropertyID property; - CSSValuePool* m_cssValuePool; + CSSParser* m_parser; RefPtr<CSSValueList> values; RefPtr<CSSPrimitiveValue> x; @@ -5129,7 +5261,7 @@ struct ShadowParseContext { PassRefPtr<CSSValueList> CSSParser::parseShadow(CSSParserValueList* valueList, int propId) { - ShadowParseContext context(static_cast<CSSPropertyID>(propId), cssValuePool()); + ShadowParseContext context(static_cast<CSSPropertyID>(propId), this); CSSParserValue* val; while ((val = valueList->current())) { // Check for a comma break first. @@ -5288,9 +5420,8 @@ bool CSSParser::parseFlex(int propId, bool important) } struct BorderImageParseContext { - BorderImageParseContext(CSSValuePool* cssValuePool) - : m_cssValuePool(cssValuePool) - , m_canAdvance(false) + BorderImageParseContext() + : m_canAdvance(false) , m_allowCommit(true) , m_allowImage(true) , m_allowImageSlice(true) @@ -5370,13 +5501,27 @@ struct BorderImageParseContext { m_allowImage = !m_image; } - PassRefPtr<CSSValue> commitBorderImage() + PassRefPtr<CSSValue> commitWebKitBorderImage() { - // Make our new border image value now. - return CSSBorderImageValue::create(m_image, m_imageSlice, m_borderSlice, m_outset, m_repeat); + return createBorderImageValue(m_image, m_imageSlice, m_borderSlice, m_outset, m_repeat); + } + + void commitBorderImage(CSSParser* parser, bool important) + { + commitBorderImageProperty(CSSPropertyBorderImageSource, parser, m_image, important); + commitBorderImageProperty(CSSPropertyBorderImageSlice, parser, m_imageSlice, important); + commitBorderImageProperty(CSSPropertyBorderImageWidth, parser, m_borderSlice, important); + commitBorderImageProperty(CSSPropertyBorderImageOutset, parser, m_outset, important); + commitBorderImageProperty(CSSPropertyBorderImageRepeat, parser, m_repeat, important); } - CSSValuePool* m_cssValuePool; + void commitBorderImageProperty(int propId, CSSParser* parser, PassRefPtr<CSSValue> value, bool important) + { + if (value) + parser->addProperty(propId, value, important); + else + parser->addProperty(propId, parser->cssValuePool()->createImplicitInitialValue(), important, true); + } bool m_canAdvance; @@ -5397,10 +5542,10 @@ struct BorderImageParseContext { RefPtr<CSSValue> m_repeat; }; -bool CSSParser::parseBorderImage(int propId, RefPtr<CSSValue>& result) +bool CSSParser::parseBorderImage(int propId, RefPtr<CSSValue>& result, bool important) { ShorthandScope scope(this, propId); - BorderImageParseContext context(cssValuePool()); + BorderImageParseContext context; while (CSSParserValue* val = m_valueList->current()) { context.setCanAdvance(false); @@ -5453,8 +5598,11 @@ bool CSSParser::parseBorderImage(int propId, RefPtr<CSSValue>& result) } if (context.allowCommit()) { - // Need to fully commit as a single value. - result = context.commitBorderImage(); + if (propId == CSSPropertyBorderImage) + context.commitBorderImage(this, important); + else + // Need to fully commit as a single value. + result = context.commitWebKitBorderImage(); return true; } @@ -5497,8 +5645,8 @@ bool CSSParser::parseBorderImageRepeat(RefPtr<CSSValue>& result) class BorderImageSliceParseContext { public: - BorderImageSliceParseContext(CSSValuePool* cssValuePool) - : m_cssValuePool(cssValuePool) + BorderImageSliceParseContext(CSSParser* parser) + : m_parser(parser) , m_allowNumber(true) , m_allowFill(false) , m_allowFinalCommit(false) @@ -5512,7 +5660,7 @@ public: void commitNumber(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val = m_cssValuePool->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + RefPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v); if (!m_top) m_top = val; else if (!m_right) @@ -5539,16 +5687,16 @@ public: // We need to clone and repeat values for any omissions. ASSERT(m_top); if (!m_right) { - m_right = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_bottom = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_right = m_top; + m_bottom = m_top; + m_left = m_top; } if (!m_bottom) { - m_bottom = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = m_cssValuePool->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_bottom = m_top; + m_left = m_right; } if (!m_left) - m_left = m_cssValuePool->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_left = m_right; // Now build a rect value to hold all four of our primitive values. RefPtr<Quad> quad = Quad::create(); @@ -5558,11 +5706,11 @@ public: quad->setLeft(m_left); // Make our new border image value now. - return CSSBorderImageSliceValue::create(m_cssValuePool->createValue(quad.release()), m_fill); + return CSSBorderImageSliceValue::create(m_parser->cssValuePool()->createValue(quad.release()), m_fill); } private: - CSSValuePool* m_cssValuePool; + CSSParser* m_parser; bool m_allowNumber; bool m_allowFill; @@ -5578,10 +5726,11 @@ private: bool CSSParser::parseBorderImageSlice(int propId, RefPtr<CSSBorderImageSliceValue>& result) { - BorderImageSliceParseContext context(cssValuePool()); + BorderImageSliceParseContext context(this); CSSParserValue* val; while ((val = m_valueList->current())) { - if (context.allowNumber() && validUnit(val, FInteger | FNonNeg | FPercent, true)) { + // FIXME calc() http://webkit.org/b/16662 : calc is parsed but values are not created yet. + if (context.allowNumber() && !isCalculation(val) && validUnit(val, FInteger | FNonNeg | FPercent, true)) { context.commitNumber(val); } else if (context.allowFill() && val->id == CSSValueFill) context.commitFill(); @@ -5614,8 +5763,8 @@ bool CSSParser::parseBorderImageSlice(int propId, RefPtr<CSSBorderImageSliceValu class BorderImageQuadParseContext { public: - BorderImageQuadParseContext(CSSValuePool* cssValuePool) - : m_cssValuePool(cssValuePool) + BorderImageQuadParseContext(CSSParser* parser) + : m_parser(parser) , m_allowNumber(true) , m_allowFinalCommit(false) { } @@ -5628,9 +5777,9 @@ public: { RefPtr<CSSPrimitiveValue> val; if (v->id == CSSValueAuto) - val = m_cssValuePool->createIdentifierValue(v->id); + val = m_parser->cssValuePool()->createIdentifierValue(v->id); else - val = m_cssValuePool->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + val = m_parser->createPrimitiveNumericValue(v); if (!m_top) m_top = val; @@ -5655,16 +5804,16 @@ public: // We need to clone and repeat values for any omissions. ASSERT(m_top); if (!m_right) { - m_right = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_bottom = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_right = m_top; + m_bottom = m_top; + m_left = m_top; } if (!m_bottom) { - m_bottom = m_cssValuePool->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = m_cssValuePool->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_bottom = m_top; + m_left = m_right; } if (!m_left) - m_left = m_cssValuePool->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_left = m_right; // Now build a quad value to hold all four of our primitive values. RefPtr<Quad> quad = Quad::create(); @@ -5674,11 +5823,11 @@ public: quad->setLeft(m_left); // Make our new value now. - return m_cssValuePool->createValue(quad.release()); + return m_parser->cssValuePool()->createValue(quad.release()); } private: - CSSValuePool* m_cssValuePool; + CSSParser* m_parser; bool m_allowNumber; bool m_allowFinalCommit; @@ -5691,7 +5840,7 @@ private: bool CSSParser::parseBorderImageQuad(Units validUnits, RefPtr<CSSPrimitiveValue>& result) { - BorderImageQuadParseContext context(cssValuePool()); + BorderImageQuadParseContext context(this); CSSParserValue* val; while ((val = m_valueList->current())) { if (context.allowNumber() && (validUnit(val, validUnits, true) || val->id == CSSValueAuto)) { @@ -5881,7 +6030,7 @@ static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue else if (equalIgnoringCase(a->string, "center")) result = cssValuePool->createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE); } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE) - result = cssValuePool->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); + result = cssValuePool->createValue(a->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(a->unit)); return result; } @@ -6434,19 +6583,17 @@ bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& bool CSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& canvas) { - RefPtr<CSSCanvasValue> result = CSSCanvasValue::create(); - // Walk the arguments. CSSParserValueList* args = valueList->current()->function->args.get(); if (!args || args->size() != 1) return false; // The first argument is the canvas name. It is an identifier. - CSSParserValue* a = args->current(); - if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT) + CSSParserValue* value = args->current(); + if (!value || value->unit != CSSPrimitiveValue::CSS_IDENT) return false; - result->setName(a->string); - canvas = result; + + canvas = CSSCanvasValue::create(value->string); return true; } @@ -6803,7 +6950,6 @@ PassRefPtr<WebKitCSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParse case WebKitCSSFilterValue::SaturateFilterOperation: case WebKitCSSFilterValue::InvertFilterOperation: case WebKitCSSFilterValue::OpacityFilterOperation: - case WebKitCSSFilterValue::BrightnessFilterOperation: case WebKitCSSFilterValue::ContrastFilterOperation: { // One optional argument, 0-1 or 0%-100%, if missing use 100%. if (args->size() > 1) @@ -6816,9 +6962,8 @@ PassRefPtr<WebKitCSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParse double amount = value->fValue; - // Saturate, Brightness and Contrast allow values over 100%. + // Saturate and Contrast allow values over 100%. if (filterType != WebKitCSSFilterValue::SaturateFilterOperation - && filterType != WebKitCSSFilterValue::BrightnessFilterOperation && filterType != WebKitCSSFilterValue::ContrastFilterOperation) { double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0; if (amount > maxAllowed) @@ -6829,6 +6974,26 @@ PassRefPtr<WebKitCSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParse } break; } + case WebKitCSSFilterValue::BrightnessFilterOperation: { + // One optional argument, -1 to +1 or -100% to +100%, if missing use 0, + if (args->size() > 1) + return 0; + + if (args->size()) { + CSSParserValue* value = args->current(); + if (!validUnit(value, FNumber | FPercent, true)) + return 0; + + double amount = value->fValue; + double minAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? -100.0 : -1.0; + double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0; + if (amount < minAllowed || amount > maxAllowed) + return 0; + + filterValue->append(cssValuePool()->createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); + } + break; + } case WebKitCSSFilterValue::HueRotateFilterOperation: { // hue-rotate() takes one optional angle. if (args->size() > 1) @@ -6901,6 +7066,13 @@ PassRefPtr<CSSValueList> CSSParser::parseFilter() #if ENABLE(CSS_SHADERS) if (filterType == WebKitCSSFilterValue::CustomFilterOperation) { + // Make sure parsing fails if custom filters are disabled. + if (Document* document = findDocument()) { + Settings* settings = document->settings(); + if (!settings || !settings->isCSSCustomFilterEnabled()) + return 0; + } + RefPtr<WebKitCSSFilterValue> filterValue = parseCustomFilter(value); if (!filterValue) return 0; @@ -7227,236 +7399,1271 @@ bool CSSParser::parseFontFeatureSettings(bool important) return false; } -static inline int yyerror(const char*) { return 1; } +bool CSSParser::parseFontVariantLigatures(bool important) +{ + RefPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated(); + bool sawCommonLigaturesValue = false; + bool sawDiscretionaryLigaturesValue = false; + bool sawHistoricalLigaturesValue = false; + + for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { + if (value->unit != CSSPrimitiveValue::CSS_IDENT) + return false; + + switch (value->id) { + case CSSValueNoCommonLigatures: + case CSSValueCommonLigatures: + if (sawCommonLigaturesValue) + return false; + sawCommonLigaturesValue = true; + ligatureValues->append(cssValuePool()->createIdentifierValue(value->id)); + break; + case CSSValueNoDiscretionaryLigatures: + case CSSValueDiscretionaryLigatures: + if (sawDiscretionaryLigaturesValue) + return false; + sawDiscretionaryLigaturesValue = true; + ligatureValues->append(cssValuePool()->createIdentifierValue(value->id)); + break; + case CSSValueNoHistoricalLigatures: + case CSSValueHistoricalLigatures: + if (sawHistoricalLigaturesValue) + return false; + sawHistoricalLigaturesValue = true; + ligatureValues->append(cssValuePool()->createIdentifierValue(value->id)); + break; + default: + return false; + } + } + + if (!ligatureValues->length()) + return false; + + addProperty(CSSPropertyWebkitFontVariantLigatures, ligatureValues.release(), important); + return true; +} + +bool CSSParser::parseCalculation(CSSParserValue* value) +{ + ASSERT(isCalculation(value)); + + CSSParserValueList* args = value->function->args.get(); + if (!args || !args->size()) + return false; + + ASSERT(!m_parsedCalculation); + m_parsedCalculation = CSSCalcValue::create(value->function->name, args); + + if (!m_parsedCalculation) + return false; + + return true; +} #define END_TOKEN 0 #include "CSSGrammar.h" +enum CharacterType { + // Types for the main switch. + + // The first 4 types must be grouped together, as they + // represent the allowed chars in an identifier. + CharacterCaselessU, + CharacterIdentifierStart, + CharacterNumber, + CharacterDash, + + CharacterOther, + CharacterNull, + CharacterWhiteSpace, + CharacterEndMediaQuery, + CharacterEndNthChild, + CharacterQuote, + CharacterExclamationMark, + CharacterHashmark, + CharacterDollar, + CharacterAsterisk, + CharacterPlus, + CharacterDot, + CharacterSlash, + CharacterLess, + CharacterAt, + CharacterBackSlash, + CharacterXor, + CharacterVerticalBar, + CharacterTilde, +}; + +// 128 ASCII codes +static const CharacterType typesOfASCIICharacters[128] = { +/* 0 - Null */ CharacterNull, +/* 1 - Start of Heading */ CharacterOther, +/* 2 - Start of Text */ CharacterOther, +/* 3 - End of Text */ CharacterOther, +/* 4 - End of Transm. */ CharacterOther, +/* 5 - Enquiry */ CharacterOther, +/* 6 - Acknowledgment */ CharacterOther, +/* 7 - Bell */ CharacterOther, +/* 8 - Back Space */ CharacterOther, +/* 9 - Horizontal Tab */ CharacterWhiteSpace, +/* 10 - Line Feed */ CharacterWhiteSpace, +/* 11 - Vertical Tab */ CharacterOther, +/* 12 - Form Feed */ CharacterWhiteSpace, +/* 13 - Carriage Return */ CharacterWhiteSpace, +/* 14 - Shift Out */ CharacterOther, +/* 15 - Shift In */ CharacterOther, +/* 16 - Data Line Escape */ CharacterOther, +/* 17 - Device Control 1 */ CharacterOther, +/* 18 - Device Control 2 */ CharacterOther, +/* 19 - Device Control 3 */ CharacterOther, +/* 20 - Device Control 4 */ CharacterOther, +/* 21 - Negative Ack. */ CharacterOther, +/* 22 - Synchronous Idle */ CharacterOther, +/* 23 - End of Transmit */ CharacterOther, +/* 24 - Cancel */ CharacterOther, +/* 25 - End of Medium */ CharacterOther, +/* 26 - Substitute */ CharacterOther, +/* 27 - Escape */ CharacterOther, +/* 28 - File Separator */ CharacterOther, +/* 29 - Group Separator */ CharacterOther, +/* 30 - Record Separator */ CharacterOther, +/* 31 - Unit Separator */ CharacterOther, +/* 32 - Space */ CharacterWhiteSpace, +/* 33 - ! */ CharacterExclamationMark, +/* 34 - " */ CharacterQuote, +/* 35 - # */ CharacterHashmark, +/* 36 - $ */ CharacterDollar, +/* 37 - % */ CharacterOther, +/* 38 - & */ CharacterOther, +/* 39 - ' */ CharacterQuote, +/* 40 - ( */ CharacterOther, +/* 41 - ) */ CharacterEndNthChild, +/* 42 - * */ CharacterAsterisk, +/* 43 - + */ CharacterPlus, +/* 44 - , */ CharacterOther, +/* 45 - - */ CharacterDash, +/* 46 - . */ CharacterDot, +/* 47 - / */ CharacterSlash, +/* 48 - 0 */ CharacterNumber, +/* 49 - 1 */ CharacterNumber, +/* 50 - 2 */ CharacterNumber, +/* 51 - 3 */ CharacterNumber, +/* 52 - 4 */ CharacterNumber, +/* 53 - 5 */ CharacterNumber, +/* 54 - 6 */ CharacterNumber, +/* 55 - 7 */ CharacterNumber, +/* 56 - 8 */ CharacterNumber, +/* 57 - 9 */ CharacterNumber, +/* 58 - : */ CharacterOther, +/* 59 - ; */ CharacterEndMediaQuery, +/* 60 - < */ CharacterLess, +/* 61 - = */ CharacterOther, +/* 62 - > */ CharacterOther, +/* 63 - ? */ CharacterOther, +/* 64 - @ */ CharacterAt, +/* 65 - A */ CharacterIdentifierStart, +/* 66 - B */ CharacterIdentifierStart, +/* 67 - C */ CharacterIdentifierStart, +/* 68 - D */ CharacterIdentifierStart, +/* 69 - E */ CharacterIdentifierStart, +/* 70 - F */ CharacterIdentifierStart, +/* 71 - G */ CharacterIdentifierStart, +/* 72 - H */ CharacterIdentifierStart, +/* 73 - I */ CharacterIdentifierStart, +/* 74 - J */ CharacterIdentifierStart, +/* 75 - K */ CharacterIdentifierStart, +/* 76 - L */ CharacterIdentifierStart, +/* 77 - M */ CharacterIdentifierStart, +/* 78 - N */ CharacterIdentifierStart, +/* 79 - O */ CharacterIdentifierStart, +/* 80 - P */ CharacterIdentifierStart, +/* 81 - Q */ CharacterIdentifierStart, +/* 82 - R */ CharacterIdentifierStart, +/* 83 - S */ CharacterIdentifierStart, +/* 84 - T */ CharacterIdentifierStart, +/* 85 - U */ CharacterCaselessU, +/* 86 - V */ CharacterIdentifierStart, +/* 87 - W */ CharacterIdentifierStart, +/* 88 - X */ CharacterIdentifierStart, +/* 89 - Y */ CharacterIdentifierStart, +/* 90 - Z */ CharacterIdentifierStart, +/* 91 - [ */ CharacterOther, +/* 92 - \ */ CharacterBackSlash, +/* 93 - ] */ CharacterOther, +/* 94 - ^ */ CharacterXor, +/* 95 - _ */ CharacterIdentifierStart, +/* 96 - ` */ CharacterOther, +/* 97 - a */ CharacterIdentifierStart, +/* 98 - b */ CharacterIdentifierStart, +/* 99 - c */ CharacterIdentifierStart, +/* 100 - d */ CharacterIdentifierStart, +/* 101 - e */ CharacterIdentifierStart, +/* 102 - f */ CharacterIdentifierStart, +/* 103 - g */ CharacterIdentifierStart, +/* 104 - h */ CharacterIdentifierStart, +/* 105 - i */ CharacterIdentifierStart, +/* 106 - j */ CharacterIdentifierStart, +/* 107 - k */ CharacterIdentifierStart, +/* 108 - l */ CharacterIdentifierStart, +/* 109 - m */ CharacterIdentifierStart, +/* 110 - n */ CharacterIdentifierStart, +/* 111 - o */ CharacterIdentifierStart, +/* 112 - p */ CharacterIdentifierStart, +/* 113 - q */ CharacterIdentifierStart, +/* 114 - r */ CharacterIdentifierStart, +/* 115 - s */ CharacterIdentifierStart, +/* 116 - t */ CharacterIdentifierStart, +/* 117 - u */ CharacterCaselessU, +/* 118 - v */ CharacterIdentifierStart, +/* 119 - w */ CharacterIdentifierStart, +/* 120 - x */ CharacterIdentifierStart, +/* 121 - y */ CharacterIdentifierStart, +/* 122 - z */ CharacterIdentifierStart, +/* 123 - { */ CharacterEndMediaQuery, +/* 124 - | */ CharacterVerticalBar, +/* 125 - } */ CharacterOther, +/* 126 - ~ */ CharacterTilde, +/* 127 - Delete */ CharacterOther, +}; + +// Utility functions for the CSS tokenizer. + +static inline bool isCSSLetter(UChar character) +{ + return character >= 128 || typesOfASCIICharacters[character] <= CharacterDash; +} + +static inline bool isCSSEscape(UChar character) +{ + return character >= ' ' && character != 127; +} + +static inline bool isURILetter(UChar character) +{ + return (character >= '*' && character != 127) || (character >= '#' && character <= '&') || character == '!'; +} + +static inline bool isIdentifierStartAfterDash(UChar* currentCharacter) +{ + return isASCIIAlpha(currentCharacter[0]) || currentCharacter[0] == '_' || currentCharacter[0] >= 128 + || (currentCharacter[0] == '\\' && isCSSEscape(currentCharacter[1])); +} + +static inline bool isEqualToCSSIdentifier(UChar* cssString, const char* constantString) +{ + // Compare an UChar memory data with a zero terminated string. + do { + // The input must be part of an identifier if constantChar or constString + // contains '-'. Otherwise toASCIILowerUnchecked('\r') would be equal to '-'. + ASSERT((*constantString >= 'a' && *constantString <= 'z') || *constantString == '-'); + ASSERT(*constantString != '-' || isCSSLetter(*cssString)); + if (toASCIILowerUnchecked(*cssString++) != (*constantString++)) + return false; + } while (*constantString); + return true; +} + +static UChar* checkAndSkipEscape(UChar* currentCharacter) +{ + // Returns with 0, if escape check is failed. Otherwise + // it returns with the following character. + ASSERT(*currentCharacter == '\\'); + + ++currentCharacter; + if (!isCSSEscape(*currentCharacter)) + return 0; + + if (isASCIIHexDigit(*currentCharacter)) { + int length = 6; + + do { + ++currentCharacter; + } while (isASCIIHexDigit(*currentCharacter) && --length); + + // Optional space after the escape sequence. + if (isHTMLSpace(*currentCharacter)) + ++currentCharacter; + return currentCharacter; + } + return currentCharacter + 1; +} + +static inline UChar* skipWhiteSpace(UChar* currentCharacter) +{ + while (isHTMLSpace(*currentCharacter)) + ++currentCharacter; + return currentCharacter; +} + +// Main CSS tokenizer functions. + +inline bool CSSParser::isIdentifierStart() +{ + // Check whether an identifier is started. + return isIdentifierStartAfterDash((*m_currentCharacter != '-') ? m_currentCharacter : m_currentCharacter + 1); +} + +inline UChar* CSSParser::checkAndSkipString(UChar* currentCharacter, UChar quote) +{ + // Returns with 0, if string check is failed. Otherwise + // it returns with the following character. This is necessary + // since we cannot revert escape sequences, thus strings + // must be validated before parsing. + while (true) { + if (UNLIKELY(*currentCharacter == quote)) { + // String parsing is successful. + return currentCharacter + 1; + } + if (UNLIKELY(*currentCharacter <= '\r' && (!*currentCharacter || *currentCharacter == '\n' || (*currentCharacter | 0x1) == '\r'))) { + // String parsing is failed for character '\0', '\n', '\f' or '\r'. + return 0; + } + + if (LIKELY(currentCharacter[0] != '\\')) + ++currentCharacter; + else if (currentCharacter[1] == '\n' || currentCharacter[1] == '\f') + currentCharacter += 2; + else if (currentCharacter[1] == '\r') + currentCharacter += currentCharacter[2] == '\n' ? 3 : 2; + else { + currentCharacter = checkAndSkipEscape(currentCharacter); + if (!currentCharacter) + return 0; + } + } +} + +void CSSParser::parseEscape(UChar*& result) +{ + ASSERT(*m_currentCharacter == '\\' && isCSSEscape(m_currentCharacter[1])); + + ++m_currentCharacter; + if (isASCIIHexDigit(*m_currentCharacter)) { + unsigned unicode = 0; + int length = 6; + + do { + unicode = (unicode << 4) + toASCIIHexValue(*m_currentCharacter++); + } while (--length && isASCIIHexDigit(*m_currentCharacter)); + + // Characters above 0xffff are not handled. + if (unicode > 0xffff) + unicode = 0xfffd; + + // Optional space after the escape sequence. + if (isHTMLSpace(*m_currentCharacter)) + ++m_currentCharacter; + *result = unicode; + } else + *result = *m_currentCharacter++; + ++result; +} + +inline void CSSParser::parseIdentifier(UChar*& result, bool& hasEscape) +{ + // If a valid identifier start is found, we can safely + // parse the identifier until the next invalid character. + ASSERT(isIdentifierStart()); + hasEscape = false; + do { + if (LIKELY(*m_currentCharacter != '\\')) + *result++ = *m_currentCharacter++; + else { + hasEscape = true; + parseEscape(result); + } + } while (isCSSLetter(m_currentCharacter[0]) || (m_currentCharacter[0] == '\\' && isCSSEscape(m_currentCharacter[1]))); +} + +inline void CSSParser::parseString(UChar*& result, UChar quote) +{ + while (true) { + if (UNLIKELY(*m_currentCharacter == quote)) { + // String parsing is done. + ++m_currentCharacter; + return; + } + ASSERT(*m_currentCharacter > '\r' || (*m_currentCharacter < '\n' && *m_currentCharacter) || *m_currentCharacter == '\v'); + + if (LIKELY(m_currentCharacter[0] != '\\')) + *result++ = *m_currentCharacter++; + else if (m_currentCharacter[1] == '\n' || m_currentCharacter[1] == '\f') + m_currentCharacter += 2; + else if (m_currentCharacter[1] == '\r') + m_currentCharacter += m_currentCharacter[2] == '\n' ? 3 : 2; + else + parseEscape(result); + } +} + +inline void CSSParser::parseURI(UChar*& start, UChar*& result) +{ + UChar* uriStart = skipWhiteSpace(m_currentCharacter); + + if (*uriStart == '"' || *uriStart == '\'') { + UChar quote = *uriStart; + ++uriStart; + + UChar* stringEnd = checkAndSkipString(uriStart, quote); + if (!stringEnd) + return; + stringEnd = skipWhiteSpace(stringEnd); + if (*stringEnd != ')') + return; + + start = result = m_currentCharacter = uriStart; + parseString(result, quote); + + m_currentCharacter = stringEnd + 1; + m_token = URI; + } else { + UChar* stringEnd = uriStart; + + while (isURILetter(*stringEnd)) { + if (*stringEnd != '\\') + ++stringEnd; + else { + stringEnd = checkAndSkipEscape(stringEnd); + if (!stringEnd) + return; + } + } + + stringEnd = skipWhiteSpace(stringEnd); + if (*stringEnd != ')') + return; + + start = result = m_currentCharacter = uriStart; + while (isURILetter(*m_currentCharacter)) { + if (LIKELY(*m_currentCharacter != '\\')) + *result++ = *m_currentCharacter++; + else + parseEscape(result); + } + + m_currentCharacter = stringEnd + 1; + m_token = URI; + } +} + +inline bool CSSParser::parseUnicodeRange() +{ + UChar* currentCharacter = m_currentCharacter + 1; + int length = 6; + ASSERT(*m_currentCharacter == '+'); + + while (isASCIIHexDigit(*currentCharacter) && length) { + ++currentCharacter; + --length; + } + + if (length && *currentCharacter == '?') { + // At most 5 hex digit followed by a question mark. + do { + ++currentCharacter; + --length; + } while (*currentCharacter == '?' && length); + m_currentCharacter = currentCharacter; + return true; + } + + if (length < 6) { + // At least one hex digit. + if (currentCharacter[0] == '-' && isASCIIHexDigit(currentCharacter[1])) { + // Followed by a dash and a hex digit. + ++currentCharacter; + length = 6; + do { + ++currentCharacter; + } while (--length && isASCIIHexDigit(*currentCharacter)); + } + m_currentCharacter = currentCharacter; + return true; + } + return false; +} + +bool CSSParser::parseNthChild() +{ + UChar* currentCharacter = m_currentCharacter; + + while (isASCIIDigit(*currentCharacter)) + ++currentCharacter; + if (isASCIIAlphaCaselessEqual(*currentCharacter, 'n')) { + m_currentCharacter = currentCharacter + 1; + return true; + } + return false; +} + +bool CSSParser::parseNthChildExtra() +{ + UChar* currentCharacter = skipWhiteSpace(m_currentCharacter); + if (*currentCharacter != '+' && *currentCharacter != '-') + return false; + + currentCharacter = skipWhiteSpace(currentCharacter + 1); + if (!isASCIIDigit(*currentCharacter)) + return false; + + do { + ++currentCharacter; + } while (isASCIIDigit(*currentCharacter)); + + m_currentCharacter = currentCharacter; + return true; +} + +inline void CSSParser::detectFunctionTypeToken(int length) +{ + ASSERT(length > 0); + UChar* name = m_tokenStart; + + switch (length) { + case 3: + if (isASCIIAlphaCaselessEqual(name[0], 'n') && isASCIIAlphaCaselessEqual(name[1], 'o') && isASCIIAlphaCaselessEqual(name[2], 't')) + m_token = NOTFUNCTION; + else if (isASCIIAlphaCaselessEqual(name[0], 'u') && isASCIIAlphaCaselessEqual(name[1], 'r') && isASCIIAlphaCaselessEqual(name[2], 'l')) + m_token = URI; + return; + + case 9: + if (isEqualToCSSIdentifier(name, "nth-child")) + m_parsingMode = NthChildMode; + return; + + case 11: + if (isEqualToCSSIdentifier(name, "nth-of-type")) + m_parsingMode = NthChildMode; + return; + + case 14: + if (isEqualToCSSIdentifier(name, "nth-last-child")) + m_parsingMode = NthChildMode; + return; + + case 16: + if (isEqualToCSSIdentifier(name, "nth-last-of-type")) + m_parsingMode = NthChildMode; + return; + } +} + +inline void CSSParser::detectMediaQueryToken(int length) +{ + ASSERT(m_parsingMode == MediaQueryMode); + UChar* name = m_tokenStart; + + if (length == 3) { + if (isASCIIAlphaCaselessEqual(name[0], 'a') && isASCIIAlphaCaselessEqual(name[1], 'n') && isASCIIAlphaCaselessEqual(name[2], 'd')) + m_token = MEDIA_AND; + else if (isASCIIAlphaCaselessEqual(name[0], 'n') && isASCIIAlphaCaselessEqual(name[1], 'o') && isASCIIAlphaCaselessEqual(name[2], 't')) + m_token = MEDIA_NOT; + } else if (length == 4) { + if (isASCIIAlphaCaselessEqual(name[0], 'o') && isASCIIAlphaCaselessEqual(name[1], 'n') + && isASCIIAlphaCaselessEqual(name[2], 'l') && isASCIIAlphaCaselessEqual(name[3], 'y')) + m_token = MEDIA_ONLY; + } +} + +inline void CSSParser::detectNumberToken(UChar* type, int length) +{ + ASSERT(length > 0); + + switch (toASCIILowerUnchecked(type[0])) { + case 'c': + if (length == 2 && isASCIIAlphaCaselessEqual(type[1], 'm')) + m_token = CMS; + return; + + case 'd': + if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'g')) + m_token = DEGS; + return; + + case 'e': + if (length == 2) { + if (isASCIIAlphaCaselessEqual(type[1], 'm')) + m_token = EMS; + else if (isASCIIAlphaCaselessEqual(type[1], 'x')) + m_token = EXS; + } + return; + + case 'g': + if (length == 4 && isASCIIAlphaCaselessEqual(type[1], 'r') + && isASCIIAlphaCaselessEqual(type[2], 'a') && isASCIIAlphaCaselessEqual(type[3], 'd')) + m_token = GRADS; + return; + + case 'h': + if (length == 2 && isASCIIAlphaCaselessEqual(type[1], 'z')) + m_token = HERTZ; + return; + + case 'i': + if (length == 2 && isASCIIAlphaCaselessEqual(type[1], 'n')) + m_token = INS; + return; + + case 'k': + if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'h') && isASCIIAlphaCaselessEqual(type[2], 'z')) + m_token = KHERTZ; + return; + + case 'm': + if (length == 2) { + if (isASCIIAlphaCaselessEqual(type[1], 'm')) + m_token = MMS; + else if (isASCIIAlphaCaselessEqual(type[1], 's')) + m_token = MSECS; + } + return; + + case 'p': + if (length == 2) { + if (isASCIIAlphaCaselessEqual(type[1], 'x')) + m_token = PXS; + else if (isASCIIAlphaCaselessEqual(type[1], 't')) + m_token = PTS; + else if (isASCIIAlphaCaselessEqual(type[1], 'c')) + m_token = PCS; + } + return; + + case 'r': + if (length == 3) { + if (isASCIIAlphaCaselessEqual(type[1], 'a') && isASCIIAlphaCaselessEqual(type[2], 'd')) + m_token = RADS; + else if (isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'm')) + m_token = REMS; + } + return; + + case 's': + if (length == 1) + m_token = SECS; + return; + + case 't': + if (length == 4 && isASCIIAlphaCaselessEqual(type[1], 'u') + && isASCIIAlphaCaselessEqual(type[2], 'r') && isASCIIAlphaCaselessEqual(type[3], 'n')) + m_token = TURNS; + return; + + default: + if (type[0] == '_' && length == 5 && type[1] == '_' && isASCIIAlphaCaselessEqual(type[2], 'q') + && isASCIIAlphaCaselessEqual(type[3], 'e') && isASCIIAlphaCaselessEqual(type[4], 'm')) + m_token = QEMS; + return; + } +} + +inline void CSSParser::detectDashToken(int length) +{ + UChar* name = m_tokenStart; + + if (length == 11) { + if (isASCIIAlphaCaselessEqual(name[10], 'y') && isEqualToCSSIdentifier(name + 1, "webkit-an")) + m_token = ANYFUNCTION; + else if (isASCIIAlphaCaselessEqual(name[10], 'n') && isEqualToCSSIdentifier(name + 1, "webkit-mi")) + m_token = MINFUNCTION; + else if (isASCIIAlphaCaselessEqual(name[10], 'x') && isEqualToCSSIdentifier(name + 1, "webkit-ma")) + m_token = MAXFUNCTION; + } else if (length == 12 && isEqualToCSSIdentifier(name + 1, "webkit-calc")) + m_token = CALCFUNCTION; +} + +inline void CSSParser::detectAtToken(int length, bool hasEscape) +{ + UChar* name = m_tokenStart; + ASSERT(name[0] == '@' && length >= 2); + + // charset, font-face, import, media, namespace, page, + // -webkit-keyframes, and -webkit-mediaquery are not affected by hasEscape. + switch (toASCIILowerUnchecked(name[1])) { + case 'b': + if (hasEscape) + return; + + switch (length) { + case 12: + if (isEqualToCSSIdentifier(name + 2, "ottom-left")) + m_token = BOTTOMLEFT_SYM; + return; + + case 13: + if (isEqualToCSSIdentifier(name + 2, "ottom-right")) + m_token = BOTTOMRIGHT_SYM; + return; + + case 14: + if (isEqualToCSSIdentifier(name + 2, "ottom-center")) + m_token = BOTTOMCENTER_SYM; + return; + + case 19: + if (isEqualToCSSIdentifier(name + 2, "ottom-left-corner")) + m_token = BOTTOMLEFTCORNER_SYM; + return; + + case 20: + if (isEqualToCSSIdentifier(name + 2, "ottom-right-corner")) + m_token = BOTTOMRIGHTCORNER_SYM; + return; + } + return; + + case 'c': + if (length == 8 && isEqualToCSSIdentifier(name + 2, "harset")) + m_token = CHARSET_SYM; + return; + + case 'f': + if (length == 10 && isEqualToCSSIdentifier(name + 2, "ont-face")) + m_token = FONT_FACE_SYM; + return; + + case 'i': + if (length == 7 && isEqualToCSSIdentifier(name + 2, "mport")) { + m_parsingMode = MediaQueryMode; + m_token = IMPORT_SYM; + } + return; + + case 'l': + if (hasEscape) + return; + + if (length == 9) { + if (isEqualToCSSIdentifier(name + 2, "eft-top")) + m_token = LEFTTOP_SYM; + } else if (length == 12) { + // Checking the last character first could further reduce the possibile cases. + if (isASCIIAlphaCaselessEqual(name[11], 'e') && isEqualToCSSIdentifier(name + 2, "eft-middl")) + m_token = LEFTMIDDLE_SYM; + else if (isASCIIAlphaCaselessEqual(name[11], 'm') && isEqualToCSSIdentifier(name + 2, "eft-botto")) + m_token = LEFTBOTTOM_SYM; + } + return; + + case 'm': + if (length == 6 && isEqualToCSSIdentifier(name + 2, "edia")) { + m_parsingMode = MediaQueryMode; + m_token = MEDIA_SYM; + } + return; + + case 'n': + if (length == 10 && isEqualToCSSIdentifier(name + 2, "amespace")) + m_token = NAMESPACE_SYM; + return; + + case 'p': + if (length == 5 && isEqualToCSSIdentifier(name + 2, "age")) + m_token = PAGE_SYM; + return; + + case 'r': + if (hasEscape) + return; + + if (length == 10) { + if (isEqualToCSSIdentifier(name + 2, "ight-top")) + m_token = RIGHTTOP_SYM; + } else if (length == 13) { + // Checking the last character first could further reduce the possibile cases. + if (isASCIIAlphaCaselessEqual(name[12], 'e') && isEqualToCSSIdentifier(name + 2, "ight-middl")) + m_token = RIGHTMIDDLE_SYM; + else if (isASCIIAlphaCaselessEqual(name[12], 'm') && isEqualToCSSIdentifier(name + 2, "ight-botto")) + m_token = RIGHTBOTTOM_SYM; + } + return; + + case 't': + if (hasEscape) + return; + + switch (length) { + case 9: + if (isEqualToCSSIdentifier(name + 2, "op-left")) + m_token = TOPLEFT_SYM; + return; + + case 10: + if (isEqualToCSSIdentifier(name + 2, "op-right")) + m_token = TOPRIGHT_SYM; + return; + + case 11: + if (isEqualToCSSIdentifier(name + 2, "op-center")) + m_token = TOPCENTER_SYM; + return; + + case 16: + if (isEqualToCSSIdentifier(name + 2, "op-left-corner")) + m_token = TOPLEFTCORNER_SYM; + return; + + case 17: + if (isEqualToCSSIdentifier(name + 2, "op-right-corner")) + m_token = TOPRIGHTCORNER_SYM; + return; + } + return; + + case '-': + switch (length) { + case 13: + if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-rule")) + m_token = WEBKIT_RULE_SYM; + return; + + case 14: + if (hasEscape) + return; + + // Checking the last character first could further reduce the possibile cases. + if (isASCIIAlphaCaselessEqual(name[13], 's') && isEqualToCSSIdentifier(name + 2, "webkit-decl")) + m_token = WEBKIT_DECLS_SYM; + else if (isASCIIAlphaCaselessEqual(name[13], 'e') && isEqualToCSSIdentifier(name + 2, "webkit-valu")) + m_token = WEBKIT_VALUE_SYM; + return; + + case 15: + if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-region")) + m_token = WEBKIT_REGION_RULE_SYM; + return; + + case 17: + if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-selector")) + m_token = WEBKIT_SELECTOR_SYM; + return; + + case 18: + if (isEqualToCSSIdentifier(name + 2, "webkit-keyframes")) + m_token = WEBKIT_KEYFRAMES_SYM; + return; + + case 19: + if (isEqualToCSSIdentifier(name + 2, "webkit-mediaquery")) { + m_parsingMode = MediaQueryMode; + m_token = WEBKIT_MEDIAQUERY_SYM; + } + return; + + case 22: + if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-keyframe-rule")) + m_token = WEBKIT_KEYFRAME_RULE_SYM; + return; + } + } +} + int CSSParser::lex(void* yylvalWithoutType) { YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType); - int length; + // Write pointer for the next character. + UChar* result; + bool hasEscape; - lex(); + // The input buffer is terminated by two \0, so + // it is safe to read two characters ahead anytime. - UChar* t = text(&length); +#ifndef NDEBUG + // In debug we check with an ASSERT that the length is > 0 for string types. + yylval->string.characters = 0; + yylval->string.length = 0; +#endif - switch (token()) { - case WHITESPACE: - case SGML_CD: - case INCLUDES: - case DASHMATCH: +restartAfterComment: + m_tokenStart = result = m_currentCharacter; + m_token = *m_currentCharacter; + ++m_currentCharacter; + + switch ((m_token <= 127) ? typesOfASCIICharacters[m_token] : CharacterIdentifierStart) { + case CharacterCaselessU: + if (UNLIKELY(*m_currentCharacter == '+')) + if (parseUnicodeRange()) { + m_token = UNICODERANGE; + yylval->string.characters = m_tokenStart; + yylval->string.length = m_currentCharacter - m_tokenStart; + break; + } + // Fall through to CharacterIdentifierStart. + + case CharacterIdentifierStart: + --m_currentCharacter; + parseIdentifier(result, hasEscape); + m_token = IDENT; + + yylval->string.characters = m_tokenStart; + yylval->string.length = result - m_tokenStart; + + if (UNLIKELY(*m_currentCharacter == '(')) { + m_token = FUNCTION; + if (!hasEscape) + detectFunctionTypeToken(result - m_tokenStart); + ++m_currentCharacter; + ++result; + ++yylval->string.length; + + if (token() == URI) { + m_token = FUNCTION; + // Check whether it is really an URI. + parseURI(yylval->string.characters, result); + yylval->string.length = result - yylval->string.characters; + } + } else if (UNLIKELY(m_parsingMode != NormalMode) && !hasEscape) { + if (m_parsingMode == MediaQueryMode) + detectMediaQueryToken(result - m_tokenStart); + else if (m_parsingMode == NthChildMode && isASCIIAlphaCaselessEqual(m_tokenStart[0], 'n')) { + if (result - m_tokenStart == 1) { + // String "n" is IDENT but "n+1" is NTH. + if (parseNthChildExtra()) { + m_token = NTH; + yylval->string.length = m_currentCharacter - m_tokenStart; + } + } else if (result - m_tokenStart == 2 && m_tokenStart[1] == '-') { + // String "n-" is IDENT but "n-1" is NTH. + // Speculatively decrease m_currentCharacter to detect an nth-child token. + m_currentCharacter--; + if (parseNthChildExtra()) { + m_token = NTH; + yylval->string.length = m_currentCharacter - m_tokenStart; + } else { + // Revert the change to m_currentCharacter if unsuccessful. + m_currentCharacter++; + } + } + } + } break; - case URI: - case STRING: - case IDENT: - case NTH: - case HEX: - case IDSEL: - case DIMEN: - case UNICODERANGE: - case FUNCTION: - case ANYFUNCTION: - case NOTFUNCTION: - case CALCFUNCTION: - case MINFUNCTION: - case MAXFUNCTION: - yylval->string.characters = t; - yylval->string.length = length; - break; - - case IMPORT_SYM: - case PAGE_SYM: - case MEDIA_SYM: - case FONT_FACE_SYM: - case CHARSET_SYM: - case NAMESPACE_SYM: - case WEBKIT_KEYFRAMES_SYM: - - case IMPORTANT_SYM: - break; - - case QEMS: - length--; - case GRADS: - case TURNS: - length--; - case DEGS: - case RADS: - case KHERTZ: - case REMS: - length--; - case MSECS: - case HERTZ: - case EMS: - case EXS: - case PXS: - case CMS: - case MMS: - case INS: - case PTS: - case PCS: - length--; - case SECS: - case PERCENTAGE: - length--; - case FLOATTOKEN: - case INTEGER: - yylval->number = charactersToDouble(t, length); + case CharacterDot: + if (!isASCIIDigit(m_currentCharacter[0])) + break; + // Fall through to CharacterNumber. + + case CharacterNumber: { + bool dotSeen = (m_token == '.'); + + while (true) { + if (!isASCIIDigit(m_currentCharacter[0])) { + // Only one dot is allowed for a number, + // and it must be followed by a digit. + if (m_currentCharacter[0] != '.' || dotSeen || !isASCIIDigit(m_currentCharacter[1])) + break; + dotSeen = true; + } + ++m_currentCharacter; + } + + if (UNLIKELY(m_parsingMode == NthChildMode) && !dotSeen && isASCIIAlphaCaselessEqual(*m_currentCharacter, 'n')) { + // "[0-9]+n" is always an NthChild. + ++m_currentCharacter; + parseNthChildExtra(); + m_token = NTH; + yylval->string.characters = m_tokenStart; + yylval->string.length = m_currentCharacter - m_tokenStart; + break; + } + + yylval->number = charactersToDouble(m_tokenStart, m_currentCharacter - m_tokenStart); + + // Type of the function. + if (isIdentifierStart()) { + UChar* type = m_currentCharacter; + result = m_currentCharacter; + + parseIdentifier(result, hasEscape); + if (*m_currentCharacter == '+') { + // Any identifier followed by a '+' sign is an invalid dimension. + ++m_currentCharacter; + m_token = INVALIDDIMEN; + } else { + m_token = DIMEN; + if (!hasEscape) + detectNumberToken(type, m_currentCharacter - type); + + if (m_token == DIMEN) { + // The decoded number is overwritten, but this is intentional. + yylval->string.characters = m_tokenStart; + yylval->string.length = m_currentCharacter - m_tokenStart; + } + } + } else if (*m_currentCharacter == '%') { + // Although the CSS grammar says {num}% we follow + // webkit at the moment which uses {num}%+. + do { + ++m_currentCharacter; + } while (*m_currentCharacter == '%'); + m_token = PERCENTAGE; + } else + m_token = dotSeen ? FLOATTOKEN : INTEGER; + break; + } + + case CharacterDash: + if (isIdentifierStartAfterDash(m_currentCharacter)) { + --m_currentCharacter; + parseIdentifier(result, hasEscape); + m_token = IDENT; + + if (*m_currentCharacter == '(') { + m_token = FUNCTION; + if (!hasEscape) + detectDashToken(result - m_tokenStart); + ++m_currentCharacter; + ++result; + } else if (UNLIKELY(m_parsingMode == NthChildMode) && !hasEscape && isASCIIAlphaCaselessEqual(m_tokenStart[1], 'n')) { + if (result - m_tokenStart == 2) { + // String "-n" is IDENT but "-n+1" is NTH. + if (parseNthChildExtra()) { + m_token = NTH; + result = m_currentCharacter; + } + } else if (result - m_tokenStart == 3 && m_tokenStart[2] == '-') { + // String "-n-" is IDENT but "-n-1" is NTH. + // Speculatively decrease m_currentCharacter to detect an nth-child token. + m_currentCharacter--; + if (parseNthChildExtra()) { + m_token = NTH; + yylval->string.length = m_currentCharacter - m_tokenStart; + } else { + // Revert the change to m_currentCharacter if unsuccessful. + m_currentCharacter++; + } + } + } + yylval->string.characters = m_tokenStart; + yylval->string.length = result - m_tokenStart; + } else if (m_currentCharacter[0] == '-' && m_currentCharacter[1] == '>') { + m_currentCharacter += 2; + m_token = SGML_CD; + } else if (UNLIKELY(m_parsingMode == NthChildMode)) { + // "-[0-9]+n" is always an NthChild. + if (parseNthChild()) { + parseNthChildExtra(); + m_token = NTH; + yylval->string.characters = m_tokenStart; + yylval->string.length = m_currentCharacter - m_tokenStart; + } + } break; - default: + case CharacterOther: + // m_token is simply the current character. break; - } - return token(); -} + case CharacterNull: + // Do not advance pointer at the end of input. + --m_currentCharacter; + break; -void CSSParser::recheckAtKeyword(const UChar* str, int len) -{ - String ruleName(str, len); - if (equalIgnoringCase(ruleName, "@import")) - yyTok = IMPORT_SYM; - else if (equalIgnoringCase(ruleName, "@page")) - yyTok = PAGE_SYM; - else if (equalIgnoringCase(ruleName, "@media")) - yyTok = MEDIA_SYM; - else if (equalIgnoringCase(ruleName, "@font-face")) - yyTok = FONT_FACE_SYM; - else if (equalIgnoringCase(ruleName, "@charset")) - yyTok = CHARSET_SYM; - else if (equalIgnoringCase(ruleName, "@namespace")) - yyTok = NAMESPACE_SYM; - else if (equalIgnoringCase(ruleName, "@-webkit-keyframes")) - yyTok = WEBKIT_KEYFRAMES_SYM; - else if (equalIgnoringCase(ruleName, "@-webkit-mediaquery")) - yyTok = WEBKIT_MEDIAQUERY_SYM; -} - -UChar* CSSParser::text(int *length) -{ - UChar* start = yytext; - int l = yyleng; - switch (yyTok) { - case STRING: - l--; - /* nobreak */ - case HEX: - case IDSEL: - start++; - l--; + case CharacterWhiteSpace: + m_token = WHITESPACE; + // Might start with a '\n'. + --m_currentCharacter; + do { + if (*m_currentCharacter == '\n') + ++m_lineNumber; + ++m_currentCharacter; + } while (*m_currentCharacter <= ' ' && (typesOfASCIICharacters[*m_currentCharacter] == CharacterWhiteSpace)); break; - case URI: - // "url("{w}{string}{w}")" - // "url("{w}{url}{w}")" - // strip "url(" and ")" - start += 4; - l -= 5; - // strip {w} - while (l && isHTMLSpace(*start)) { - ++start; - --l; - } - while (l && isHTMLSpace(start[l - 1])) - --l; - if (l && (*start == '"' || *start == '\'')) { - ASSERT(l >= 2 && start[l - 1] == *start); - ++start; - l -= 2; + + case CharacterEndMediaQuery: + if (m_parsingMode == MediaQueryMode) + m_parsingMode = NormalMode; + break; + + case CharacterEndNthChild: + if (m_parsingMode == NthChildMode) + m_parsingMode = NormalMode; + break; + + case CharacterQuote: + if (checkAndSkipString(m_currentCharacter, m_token)) { + ++result; + parseString(result, m_token); + m_token = STRING; + yylval->string.characters = m_tokenStart + 1; + yylval->string.length = result - (m_tokenStart + 1); } break; - default: + + case CharacterExclamationMark: { + UChar* start = skipWhiteSpace(m_currentCharacter); + if (isEqualToCSSIdentifier(start, "important")) { + m_token = IMPORTANT_SYM; + m_currentCharacter = start + 9; + } break; } - // process escapes - UChar* out = start; - UChar* escape = 0; + case CharacterHashmark: { + UChar* start = m_currentCharacter; + result = m_currentCharacter; - bool sawEscape = false; + if (isASCIIDigit(*m_currentCharacter)) { + // This must be a valid hex number token. + do { + ++m_currentCharacter; + } while (isASCIIHexDigit(*m_currentCharacter)); + m_token = HEX; + yylval->string.characters = start; + yylval->string.length = m_currentCharacter - start; + } else if (isIdentifierStart()) { + m_token = IDSEL; + parseIdentifier(result, hasEscape); + if (!hasEscape) { + // Check whether the identifier is also a valid hex number. + UChar* current = start; + m_token = HEX; + do { + if (!isASCIIHexDigit(*current)) { + m_token = IDSEL; + break; + } + ++current; + } while (current < result); + } + yylval->string.characters = start; + yylval->string.length = result - start; + } + break; + } - for (int i = 0; i < l; i++) { - UChar* current = start + i; - if (escape == current - 1) { - if (isASCIIHexDigit(*current)) - continue; - if (yyTok == STRING && - (*current == '\n' || *current == '\r' || *current == '\f')) { - // ### handle \r\n case - if (*current != '\r') - escape = 0; - continue; + case CharacterSlash: + // Ignore comments. They are not even considered as white spaces. + if (*m_currentCharacter == '*') { + ++m_currentCharacter; + while (m_currentCharacter[0] != '*' || m_currentCharacter[1] != '/') { + if (m_currentCharacter[0] == '\n') + ++m_lineNumber; + if (m_currentCharacter[0] == '\0' && m_currentCharacter[1] == '\0') { + // Unterminated comments are simply ignored. + m_currentCharacter -= 2; + break; + } + ++m_currentCharacter; } - // in all other cases copy the char to output - // ### - *out++ = *current; - escape = 0; - continue; + m_currentCharacter += 2; + goto restartAfterComment; } - if (escape == current - 2 && yyTok == STRING && - *(current-1) == '\r' && *current == '\n') { - escape = 0; - continue; + break; + + case CharacterDollar: + if (*m_currentCharacter == '=') { + ++m_currentCharacter; + m_token = ENDSWITH; } - if (escape > current - 7 && isASCIIHexDigit(*current)) - continue; - if (escape) { - // add escaped char - unsigned uc = 0; - escape++; - while (escape < current) { - uc *= 16; - uc += toASCIIHexValue(*escape); - escape++; + break; + + case CharacterAsterisk: + if (*m_currentCharacter == '=') { + ++m_currentCharacter; + m_token = CONTAINS; + } + break; + + case CharacterPlus: + if (UNLIKELY(m_parsingMode == NthChildMode)) { + // Simplest case. "+[0-9]*n" is always NthChild. + if (parseNthChild()) { + parseNthChildExtra(); + m_token = NTH; + yylval->string.characters = m_tokenStart; + yylval->string.length = m_currentCharacter - m_tokenStart; } - // can't handle chars outside ucs2 - if (uc > 0xffff) - uc = 0xfffd; - *out++ = uc; - escape = 0; - if (isHTMLSpace(*current)) - continue; } - if (!escape && *current == '\\') { - escape = current; - sawEscape = true; - continue; + break; + + case CharacterLess: + if (m_currentCharacter[0] == '!' && m_currentCharacter[1] == '-' && m_currentCharacter[2] == '-') { + m_currentCharacter += 3; + m_token = SGML_CD; } - *out++ = *current; - } - if (escape) { - // add escaped char - unsigned uc = 0; - escape++; - while (escape < start+l) { - uc *= 16; - uc += toASCIIHexValue(*escape); - escape++; + break; + + case CharacterAt: + if (isIdentifierStart()) { + m_token = ATKEYWORD; + ++result; + parseIdentifier(result, hasEscape); + detectAtToken(result - m_tokenStart, hasEscape); + } + break; + + case CharacterBackSlash: + if (isCSSEscape(*m_currentCharacter)) { + --m_currentCharacter; + parseIdentifier(result, hasEscape); + m_token = IDENT; + yylval->string.characters = m_tokenStart; + yylval->string.length = result - m_tokenStart; + } + break; + + case CharacterXor: + if (*m_currentCharacter == '=') { + ++m_currentCharacter; + m_token = BEGINSWITH; + } + break; + + case CharacterVerticalBar: + if (*m_currentCharacter == '=') { + ++m_currentCharacter; + m_token = DASHMATCH; + } + break; + + case CharacterTilde: + if (*m_currentCharacter == '=') { + ++m_currentCharacter; + m_token = INCLUDES; } - // can't handle chars outside ucs2 - if (uc > 0xffff) - uc = 0xfffd; - *out++ = uc; + break; + + default: + ASSERT_NOT_REACHED(); + break; } - *length = out - start; +#ifndef NDEBUG + switch (token()) { + case STRING: + ASSERT(yylval->string.characters == m_tokenStart + 1); + break; - // If we have an unrecognized @-keyword, and if we handled any escapes at all, then - // we should attempt to adjust yyTok to the correct type. - if (yyTok == ATKEYWORD && sawEscape) - recheckAtKeyword(start, *length); + case IDENT: + case NTH: + case DIMEN: + case UNICODERANGE: + case FUNCTION: + case ANYFUNCTION: + case NOTFUNCTION: + case CALCFUNCTION: + case MINFUNCTION: + case MAXFUNCTION: + ASSERT(yylval->string.characters == m_tokenStart && yylval->string.length > 0); + break; - return start; -} + case URI: + ASSERT(yylval->string.characters && yylval->string.characters != m_tokenStart); + break; -void CSSParser::countLines() -{ - for (UChar* current = yytext; current < yytext + yyleng; ++current) { - if (*current == '\n') - ++m_lineNumber; + case HEX: + case IDSEL: + ASSERT(yylval->string.characters == m_tokenStart + 1 && yylval->string.length > 0); + break; } +#endif + + return token(); } CSSParserSelector* CSSParser::createFloatingSelector() @@ -7862,27 +9069,27 @@ void CSSParser::updateLastMediaLine(MediaList* media) void CSSParser::markSelectorListStart() { - m_selectorListRange.start = yytext - m_data.get(); + m_selectorListRange.start = m_tokenStart - m_dataStart.get(); } void CSSParser::markSelectorListEnd() { if (!m_currentRuleData) return; - UChar* listEnd = yytext; - while (listEnd > m_data.get() + 1) { + UChar* listEnd = m_tokenStart; + while (listEnd > m_dataStart.get() + 1) { if (isHTMLSpace(*(listEnd - 1))) --listEnd; else break; } - m_selectorListRange.end = listEnd - m_data.get(); + m_selectorListRange.end = listEnd - m_dataStart.get(); } void CSSParser::markRuleBodyStart() { - unsigned offset = yytext - m_data.get(); - if (*yytext == '{') + unsigned offset = m_tokenStart - m_dataStart.get(); + if (*m_tokenStart == '{') ++offset; // Skip the rule body opening brace. if (offset > m_ruleBodyRange.start) m_ruleBodyRange.start = offset; @@ -7891,7 +9098,7 @@ void CSSParser::markRuleBodyStart() void CSSParser::markRuleBodyEnd() { - unsigned offset = yytext - m_data.get(); + unsigned offset = m_tokenStart - m_dataStart.get(); if (offset > m_ruleBodyRange.end) m_ruleBodyRange.end = offset; } @@ -7900,15 +9107,15 @@ void CSSParser::markPropertyStart() { if (!m_inStyleRuleOrDeclaration) return; - m_propertyRange.start = yytext - m_data.get(); + m_propertyRange.start = m_tokenStart - m_dataStart.get(); } void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed) { if (!m_inStyleRuleOrDeclaration) return; - unsigned offset = yytext - m_data.get(); - if (*yytext == ';') // Include semicolon into the property text. + unsigned offset = m_tokenStart - m_dataStart.get(); + if (*m_tokenStart == ';') // Include semicolon into the property text. ++offset; m_propertyRange.end = offset; if (m_propertyRange.start != UINT_MAX && m_currentRuleData) { @@ -7916,7 +9123,7 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed) const unsigned start = m_propertyRange.start; const unsigned end = m_propertyRange.end; ASSERT(start < end); - String propertyString = String(m_data.get() + start, end - start).stripWhiteSpace(); + String propertyString = String(m_dataStart.get() + start, end - start).stripWhiteSpace(); if (propertyString.endsWith(";", true)) propertyString = propertyString.left(propertyString.length() - 1); size_t colonIndex = propertyString.find(":"); @@ -8135,33 +9342,4 @@ bool isValidNthToken(const CSSParserString& token) || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n"); } -#define YY_DECL int CSSParser::lex() -#define yyconst const -typedef int yy_state_type; -typedef unsigned YY_CHAR; -// The following line makes sure we treat non-Latin-1 Unicode characters correctly. -#define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c) -#define YY_DO_BEFORE_ACTION \ - yytext = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ - *yy_cp = 0; \ - yy_c_buf_p = yy_cp; -#define YY_BREAK break; -#define ECHO -#define YY_RULE_SETUP -#define INITIAL 0 -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) -#define yyterminate() yyTok = END_TOKEN; return yyTok -#define YY_FATAL_ERROR(a) -// The following line is needed to build the tokenizer with a condition stack. -// The macro is used in the tokenizer grammar with lines containing -// BEGIN(mediaqueries) and BEGIN(initial). yy_start acts as index to -// tokenizer transition table, and 'mediaqueries' and 'initial' are -// offset multipliers that specify which transitions are active -// in the tokenizer during in each condition (tokenizer state). -#define BEGIN yy_start = 1 + 2 * - -#include "tokenizer.cpp" - } diff --git a/Source/WebCore/css/CSSParser.h b/Source/WebCore/css/CSSParser.h index adc19025a..b7384eee9 100644 --- a/Source/WebCore/css/CSSParser.h +++ b/Source/WebCore/css/CSSParser.h @@ -23,6 +23,7 @@ #ifndef CSSParser_h #define CSSParser_h +#include "CSSCalculationValue.h" #include "CSSGradientValue.h" #include "CSSParserValues.h" #include "CSSPropertySourceData.h" @@ -173,7 +174,7 @@ public: // CSS3 Parsing Routines (for properties specific to CSS3) PassRefPtr<CSSValueList> parseShadow(CSSParserValueList*, int propId); - bool parseBorderImage(int propId, RefPtr<CSSValue>&); + bool parseBorderImage(int propId, RefPtr<CSSValue>&, bool important = false); bool parseBorderImageRepeat(RefPtr<CSSValue>&); bool parseBorderImageSlice(int propId, RefPtr<CSSBorderImageSliceValue>&); bool parseBorderImageWidth(RefPtr<CSSPrimitiveValue>&); @@ -211,6 +212,7 @@ public: bool parseTextEmphasisStyle(bool important); bool parseLineBoxContain(bool important); + bool parseCalculation(CSSParserValue*); bool parseFontFeatureTag(CSSValueList*); bool parseFontFeatureSettings(bool important); @@ -218,6 +220,8 @@ public: bool parseFlowThread(int propId, bool important); bool parseRegionThread(int propId, bool important); + bool parseFontVariantLigatures(bool important); + int yyparse(); CSSParserSelector* createFloatingSelector(); @@ -315,12 +319,29 @@ public: void resetRuleBodyMarks() { m_ruleBodyRange.start = m_ruleBodyRange.end = 0; } void resetPropertyMarks() { m_propertyRange.start = m_propertyRange.end = UINT_MAX; } int lex(void* yylval); - int token() { return yyTok; } - UChar* text(int* length); - void countLines(); - int lex(); + int token() { return m_token; } + PassRefPtr<CSSPrimitiveValue> createPrimitiveNumericValue(CSSParserValue*); + PassRefPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*); + private: + inline bool isIdentifierStart(); + + static inline UChar* checkAndSkipString(UChar*, UChar); + + void parseEscape(UChar*&); + inline void parseIdentifier(UChar*&, bool&); + inline void parseString(UChar*&, UChar); + inline void parseURI(UChar*&, UChar*&); + inline bool parseUnicodeRange(); + bool parseNthChild(); + bool parseNthChildExtra(); + inline void detectFunctionTypeToken(int); + inline void detectMediaQueryToken(int); + inline void detectNumberToken(UChar*, int); + inline void detectDashToken(int); + inline void detectAtToken(int, bool); + void setStyleSheet(CSSStyleSheet*); void ensureCSSValuePool(); @@ -356,15 +377,17 @@ private: bool parseColor(const String&); - OwnArrayPtr<UChar> m_data; - UChar* yytext; - UChar* yy_c_buf_p; - UChar yy_hold_char; - int yy_last_accepting_state; - UChar* yy_last_accepting_cpos; - int yyleng; - int yyTok; - int yy_start; + enum ParsingMode { + NormalMode, + MediaQueryMode, + NthChildMode + }; + + ParsingMode m_parsingMode; + OwnArrayPtr<UChar> m_dataStart; + UChar* m_currentCharacter; + UChar* m_tokenStart; + int m_token; int m_lineNumber; int m_lastSelectorLineNumber; @@ -386,6 +409,8 @@ private: Vector<OwnPtr<CSSParserSelector> > m_reusableSelectorVector; Vector<OwnPtr<CSSParserSelector> > m_reusableRegionSelectorVector; + RefPtr<CSSCalcValue> m_parsedCalculation; + // defines units allowed for a certain property, used in parseUnit enum Units { FUnknown = 0x0000, @@ -405,13 +430,19 @@ private: return static_cast<Units>(static_cast<unsigned>(a) | static_cast<unsigned>(b)); } - static bool validUnit(CSSParserValue*, Units, bool strict); + bool validCalculationUnit(CSSParserValue*, Units); + bool validUnit(CSSParserValue*, Units, bool strict); bool parseBorderImageQuad(Units, RefPtr<CSSPrimitiveValue>&); - - PassRefPtr<CSSPrimitiveValue> createPrimitiveNumericValue(CSSParserValue*); - PassRefPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*); - + int colorIntFromValue(CSSParserValue*); + + enum ReleaseParsedCalcValueCondition { + ReleaseParsedCalcValue, + DoNotReleaseParsedCalcValue + }; + double parsedDouble(CSSParserValue*, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); + bool isCalculation(CSSParserValue*); + friend class TransformOperationInfo; #if ENABLE(CSS_FILTERS) friend class FilterOperationInfo; diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp index a439cbf52..9021a6353 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.cpp +++ b/Source/WebCore/css/CSSPrimitiveValue.cpp @@ -338,38 +338,60 @@ void CSSPrimitiveValue::cleanup() } } -template<> int CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +double CSSPrimitiveValue::computeDegrees() +{ + switch (m_primitiveUnitType) { + case CSS_DEG: + return getDoubleValue(); + case CSS_RAD: + return rad2deg(getDoubleValue()); + case CSS_GRAD: + return grad2deg(getDoubleValue()); + case CSS_TURN: + return turn2deg(getDoubleValue()); + default: + ASSERT_NOT_REACHED(); + return 0; + } +} + +template<> int CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { return roundForImpreciseConversion<int, INT_MAX, INT_MIN>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); } -template<> Length CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +template<> unsigned CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) +{ + return roundForImpreciseConversion<unsigned, UINT_MAX, 0>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); +} + +template<> Length CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { // FIXME: Length.h no longer expects 28 bit integers, so these bounds should be INT_MAX and INT_MIN return Length(roundForImpreciseConversion<int, intMaxForLength, intMinForLength>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)), Fixed); } -template<> short CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +template<> short CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { return roundForImpreciseConversion<short, SHRT_MAX, SHRT_MIN>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); } -template<> unsigned short CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +template<> unsigned short CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { return roundForImpreciseConversion<unsigned short, USHRT_MAX, 0>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); } -template<> float CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +template<> float CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize)); } -template<> double CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +template<> double CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { return computeLengthDouble(style, rootStyle, multiplier, computingFontSize); } -double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* rootStyle, float multiplier, bool computingFontSize) { unsigned short type = primitiveType(); @@ -394,7 +416,8 @@ double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* r break; case CSS_REMS: applyZoomMultiplier = false; - factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); + if (rootStyle) + factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); break; case CSS_PX: break; @@ -420,7 +443,7 @@ double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* r } double result = getDoubleValue() * factor; - if (!applyZoomMultiplier || multiplier == 1.0) + if (!applyZoomMultiplier || multiplier == 1.0f) return result; // Any original result that was >= 1 should not be allowed to fall below 1. This keeps border lines from diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h index 8fd4ad209..3f15ff78d 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.h +++ b/Source/WebCore/css/CSSPrimitiveValue.h @@ -116,12 +116,36 @@ public: UOther }; - static bool isUnitTypeLength(int type) { return (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) || - type == CSSPrimitiveValue::CSS_REMS; } + bool isAngle() const + { + return m_primitiveUnitType == CSS_DEG + || m_primitiveUnitType == CSS_RAD + || m_primitiveUnitType == CSS_GRAD + || m_primitiveUnitType == CSS_TURN; + } + bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; } + bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; } + bool isFontIndependentLength() const { return m_primitiveUnitType >= CSS_PX && m_primitiveUnitType <= CSS_PC; } + bool isFontRelativeLength() const + { + return m_primitiveUnitType == CSS_EMS || m_primitiveUnitType == CSS_EXS || m_primitiveUnitType == CSS_REMS; + } + bool isIdent() const { return m_primitiveUnitType == CSS_IDENT; } + bool isLength() const + { + return (m_primitiveUnitType >= CSS_EMS && m_primitiveUnitType <= CSS_PC) + || m_primitiveUnitType == CSS_REMS; + } + bool isNumber() const { return m_primitiveUnitType == CSS_NUMBER; } + bool isPercentage() const { return m_primitiveUnitType == CSS_PERCENTAGE; } + bool isPx() const { return m_primitiveUnitType == CSS_PX; } + bool isRect() const { return m_primitiveUnitType == CSS_RECT; } + bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; } + bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; } + bool isString() const { return m_primitiveUnitType == CSS_STRING; } + bool isTime() const { return m_primitiveUnitType == CSS_S || m_primitiveUnitType == CSS_MS; } + bool isURI() const { return m_primitiveUnitType == CSS_URI; } - bool isLength() const { return isUnitTypeLength(m_primitiveUnitType); } - bool isPercentage() const { return m_primitiveUnitType == CSSPrimitiveValue::CSS_PERCENTAGE; } - bool isNumber() const { return m_primitiveUnitType == CSSPrimitiveValue::CSS_NUMBER; } static PassRefPtr<CSSPrimitiveValue> createIdentifier(int identifier) { return adoptRef(new CSSPrimitiveValue(identifier)); } static PassRefPtr<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(new CSSPrimitiveValue(rgbValue)); } @@ -150,6 +174,23 @@ public: unsigned short primitiveType() const { return m_primitiveUnitType; } + double computeDegrees(); + + enum TimeUnit { Seconds, Milliseconds }; + template <typename T, TimeUnit timeUnit> T computeTime() + { + if (timeUnit == Seconds && m_primitiveUnitType == CSS_S) + return getValue<T>(); + if (timeUnit == Seconds && m_primitiveUnitType == CSS_MS) + return getValue<T>() / 1000; + if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_MS) + return getValue<T>(); + if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_S) + return getValue<T>() * 1000; + ASSERT_NOT_REACHED(); + return 0; + } + /* * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get * the fontinfo in case val is defined in em or ex. @@ -160,7 +201,10 @@ public: * this is screen/printer dependent, so we probably need a config option for this, * and some tool to calibrate. */ - template<typename T> T computeLength(RenderStyle* currStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false); + template<typename T> T computeLength(RenderStyle* currStyle, RenderStyle* rootStyle, float multiplier = 1.0f, bool computingFontSize = false); + + // Converts to a Length, mapping various unit types appropriately. + template<int> Length convertToLength(RenderStyle* currStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false); // use with care!!! void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; } @@ -260,7 +304,7 @@ private: bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const; - double computeLengthDouble(RenderStyle* currentStyle, RenderStyle* rootStyle, double multiplier, bool computingFontSize); + double computeLengthDouble(RenderStyle* currentStyle, RenderStyle* rootStyle, float multiplier, bool computingFontSize); union { int ident; diff --git a/Source/WebCore/css/CSSPrimitiveValueMappings.h b/Source/WebCore/css/CSSPrimitiveValueMappings.h index 6d85beeb3..c5916466c 100644 --- a/Source/WebCore/css/CSSPrimitiveValueMappings.h +++ b/Source/WebCore/css/CSSPrimitiveValueMappings.h @@ -36,6 +36,7 @@ #include "FontDescription.h" #include "FontSmoothingMode.h" #include "GraphicsTypes.h" +#include "Length.h" #include "Path.h" #include "RenderStyleConstants.h" #include "SVGRenderStyleDefs.h" @@ -284,6 +285,9 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CompositeOperator e) case CompositePlusLighter: m_value.ident = CSSValuePlusLighter; break; + case CompositeDifference: + ASSERT_NOT_REACHED(); + break; } } @@ -1217,6 +1221,9 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFlexPack e) case PackJustify: m_value.ident = CSSValueJustify; break; + case PackDistribute: + m_value.ident = CSSValueDistribute; + break; } } @@ -1231,6 +1238,8 @@ template<> inline CSSPrimitiveValue::operator EFlexPack() const return PackCenter; case CSSValueJustify: return PackJustify; + case CSSValueDistribute: + return PackDistribute; default: ASSERT_NOT_REACHED(); return PackStart; @@ -3142,8 +3151,8 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineGridSnap gridSnap) case LineGridSnapBaseline: m_value.ident = CSSValueBaseline; break; - case LineGridSnapBounds: - m_value.ident = CSSValueBounds; + case LineGridSnapContain: + m_value.ident = CSSValueContain; break; } } @@ -3155,8 +3164,8 @@ template<> inline CSSPrimitiveValue::operator LineGridSnap() const return LineGridSnapNone; case CSSValueBaseline: return LineGridSnapBaseline; - case CSSValueBounds: - return LineGridSnapBounds; + case CSSValueContain: + return LineGridSnapContain; default: ASSERT_NOT_REACHED(); return LineGridSnapNone; @@ -3673,6 +3682,21 @@ template<> inline CSSPrimitiveValue::operator WrapThrough() const } } +enum LengthConversion { UnsupportedConversion = 0, FixedConversion = 1, AutoConversion = 2, PercentConversion = 4, FractionConversion = 8}; +template<int supported> Length CSSPrimitiveValue::convertToLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize) +{ + if ((supported & FixedConversion) && isLength()) + return computeLength<Length>(style, rootStyle, multiplier, computingFontSize); + if ((supported & PercentConversion) && isPercentage()) + return Length(getDoubleValue(), Percent); + if ((supported & FractionConversion) && isNumber()) + return Length(getDoubleValue() * 100.0, Percent); + if ((supported & AutoConversion) && getIdent() == CSSValueAuto) + return Length(Auto); + ASSERT_NOT_REACHED(); + return Length(Undefined); +} + #if ENABLE(SVG) template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EColorInterpolation e) diff --git a/Source/WebCore/css/CSSProperty.cpp b/Source/WebCore/css/CSSProperty.cpp index b3d056c56..1071bbef4 100644 --- a/Source/WebCore/css/CSSProperty.cpp +++ b/Source/WebCore/css/CSSProperty.cpp @@ -320,6 +320,7 @@ bool CSSProperty::isInheritedProperty(unsigned propertyID) case CSSPropertyWebkitFontFeatureSettings: case CSSPropertyWebkitFontKerning: case CSSPropertyWebkitFontSmoothing: + case CSSPropertyWebkitFontVariantLigatures: case CSSPropertyWebkitLocale: case CSSPropertyWebkitHighlight: case CSSPropertyWebkitHyphenateCharacter: @@ -559,6 +560,7 @@ bool CSSProperty::isInheritedProperty(unsigned propertyID) #endif case CSSPropertyWebkitFlexOrder: case CSSPropertyWebkitFlexPack: + case CSSPropertyWebkitFlexAlign: case CSSPropertyWebkitFlexItemAlign: case CSSPropertyWebkitFlexDirection: case CSSPropertyWebkitFlexFlow: diff --git a/Source/WebCore/css/CSSPropertyLonghand.cpp b/Source/WebCore/css/CSSPropertyLonghand.cpp index bdd128c77..0d03b20bf 100644 --- a/Source/WebCore/css/CSSPropertyLonghand.cpp +++ b/Source/WebCore/css/CSSPropertyLonghand.cpp @@ -66,6 +66,15 @@ static void initShorthandMap(ShorthandMap& shorthandMap) }; SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderColor, borderColorProperties); + static const int borderImageProperties[] = { + CSSPropertyBorderImageSource, + CSSPropertyBorderImageSlice, + CSSPropertyBorderImageWidth, + CSSPropertyBorderImageOutset, + CSSPropertyBorderImageRepeat + }; + SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderImage, borderImageProperties); + static const int borderStyleProperties[] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in index e69875bb8..ceb2798ec 100644 --- a/Source/WebCore/css/CSSPropertyNames.in +++ b/Source/WebCore/css/CSSPropertyNames.in @@ -23,6 +23,7 @@ text-rendering -webkit-font-feature-settings -webkit-font-kerning -webkit-font-smoothing +-webkit-font-variant-ligatures -webkit-locale -webkit-text-orientation -epub-text-orientation = -webkit-text-orientation @@ -254,6 +255,7 @@ z-index #if defined(ENABLE_CSS_FILTERS) && ENABLE_CSS_FILTERS -webkit-filter #endif +-webkit-flex-align -webkit-flex-direction -webkit-flex-flow -webkit-flex-item-align diff --git a/Source/WebCore/css/CSSRule.idl b/Source/WebCore/css/CSSRule.idl index 0fda9efd4..69d7a8b45 100644 --- a/Source/WebCore/css/CSSRule.idl +++ b/Source/WebCore/css/CSSRule.idl @@ -43,7 +43,7 @@ module css { readonly attribute unsigned short type; - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString cssText setter raises (DOMException); readonly attribute CSSStyleSheet parentStyleSheet; diff --git a/Source/WebCore/css/CSSStyleApplyProperty.cpp b/Source/WebCore/css/CSSStyleApplyProperty.cpp index 0b4a63336..629470b89 100644 --- a/Source/WebCore/css/CSSStyleApplyProperty.cpp +++ b/Source/WebCore/css/CSSStyleApplyProperty.cpp @@ -35,6 +35,7 @@ #include "Document.h" #include "Element.h" #include "Pair.h" +#include "Rect.h" #include "RenderObject.h" #include "RenderStyle.h" #include "Settings.h" @@ -46,7 +47,7 @@ using namespace std; namespace WebCore { enum ExpandValueBehavior {SuppressValue = 0, ExpandValue}; -template <ExpandValueBehavior expandValue, CSSPropertyID one = CSSPropertyInvalid, CSSPropertyID two = CSSPropertyInvalid, CSSPropertyID three = CSSPropertyInvalid, CSSPropertyID four = CSSPropertyInvalid> +template <ExpandValueBehavior expandValue, CSSPropertyID one = CSSPropertyInvalid, CSSPropertyID two = CSSPropertyInvalid, CSSPropertyID three = CSSPropertyInvalid, CSSPropertyID four = CSSPropertyInvalid, CSSPropertyID five = CSSPropertyInvalid> class ApplyPropertyExpanding { public: @@ -68,6 +69,7 @@ public: applyInheritValue<two>(selector); applyInheritValue<three>(selector); applyInheritValue<four>(selector); + applyInheritValue<five>(selector); } template <CSSPropertyID id> @@ -88,6 +90,7 @@ public: applyInitialValue<two>(selector); applyInitialValue<three>(selector); applyInitialValue<four>(selector); + applyInitialValue<five>(selector); } template <CSSPropertyID id> @@ -111,6 +114,7 @@ public: applyValue<two>(selector, value); applyValue<three>(selector, value); applyValue<four>(selector, value); + applyValue<five>(selector, value); } static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); } }; @@ -212,6 +216,51 @@ public: static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); } }; +class ApplyPropertyClip { +private: + static Length convertToLength(CSSStyleSelector* selector, CSSPrimitiveValue* value) + { + return value->convertToLength<FixedConversion | PercentConversion | FractionConversion | AutoConversion>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()); + } +public: + static void applyInheritValue(CSSStyleSelector* selector) + { + RenderStyle* parentStyle = selector->parentStyle(); + if (!parentStyle->hasClip()) + return applyInitialValue(selector); + selector->style()->setClip(parentStyle->clipTop(), parentStyle->clipRight(), parentStyle->clipBottom(), parentStyle->clipLeft()); + selector->style()->setHasClip(true); + } + + static void applyInitialValue(CSSStyleSelector* selector) + { + selector->style()->setClip(Length(), Length(), Length(), Length()); + selector->style()->setHasClip(false); + } + + static void applyValue(CSSStyleSelector* selector, CSSValue* value) + { + if (!value->isPrimitiveValue()) + return; + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + + if (Rect* rect = primitiveValue->getRectValue()) { + Length top = convertToLength(selector, rect->top()); + Length right = convertToLength(selector, rect->right()); + Length bottom = convertToLength(selector, rect->bottom()); + Length left = convertToLength(selector, rect->left()); + selector->style()->setClip(top, right, bottom, left); + selector->style()->setHasClip(true); + } else if (primitiveValue->getIdent() == CSSValueAuto) { + selector->style()->setClip(Length(), Length(), Length(), Length()); + selector->style()->setHasClip(true); + } + } + + static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); } +}; + enum ColorInherit {NoInheritFromParent = 0, InheritFromParent}; Color defaultInitialColor(); Color defaultInitialColor() { return Color(); } @@ -329,12 +378,11 @@ public: else if (autoEnabled && primitiveValue->getIdent() == CSSValueAuto) setValue(selector->style(), Length()); else { - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) { + if (primitiveValue->isLength()) { Length length = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()); length.setQuirk(primitiveValue->isQuirkValue()); setValue(selector->style(), length); - } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + } else if (primitiveValue->isPercentage()) setValue(selector->style(), Length(primitiveValue->getDoubleValue(), Percent)); } } @@ -385,11 +433,11 @@ public: Length radiusWidth; Length radiusHeight; - if (pair->first()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (pair->first()->isPercentage()) radiusWidth = Length(pair->first()->getDoubleValue(), Percent); else radiusWidth = Length(max(intMinForLength, min(intMaxForLength, pair->first()->computeLength<int>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()))), Fixed); - if (pair->second()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (pair->second()->isPercentage()) radiusHeight = Length(pair->second()->getDoubleValue(), Percent); else radiusHeight = Length(max(intMinForLength, min(intMaxForLength, pair->second()->computeLength<int>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()))), Fixed); @@ -669,12 +717,8 @@ public: fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && (ident == CSSValueLarger || ident == CSSValueSmaller)); } else { - int type = primitiveValue->primitiveType(); fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize - || (type != CSSPrimitiveValue::CSS_PERCENTAGE - && type != CSSPrimitiveValue::CSS_EMS - && type != CSSPrimitiveValue::CSS_EXS - && type != CSSPrimitiveValue::CSS_REMS)); + || !(primitiveValue->isPercentage() || primitiveValue->isFontRelativeLength())); if (primitiveValue->isLength()) size = primitiveValue->computeLength<float>(selector->parentStyle(), selector->rootElementStyle(), 1.0, true); else if (primitiveValue->isPercentage()) @@ -724,6 +768,90 @@ public: } }; +class ApplyPropertyFontVariantLigatures { +public: + static void applyInheritValue(CSSStyleSelector* selector) + { + const FontDescription& parentFontDescription = selector->parentFontDescription(); + FontDescription fontDescription = selector->fontDescription(); + + fontDescription.setCommonLigaturesState(parentFontDescription.commonLigaturesState()); + fontDescription.setDiscretionaryLigaturesState(parentFontDescription.discretionaryLigaturesState()); + fontDescription.setHistoricalLigaturesState(parentFontDescription.historicalLigaturesState()); + + selector->setFontDescription(fontDescription); + } + + static void applyInitialValue(CSSStyleSelector* selector) + { + FontDescription fontDescription = selector->fontDescription(); + + fontDescription.setCommonLigaturesState(FontDescription::NormalLigaturesState); + fontDescription.setDiscretionaryLigaturesState(FontDescription::NormalLigaturesState); + fontDescription.setHistoricalLigaturesState(FontDescription::NormalLigaturesState); + + selector->setFontDescription(fontDescription); + } + + static void applyValue(CSSStyleSelector* selector, CSSValue* value) + { + FontDescription::LigaturesState commonLigaturesState = FontDescription::NormalLigaturesState; + FontDescription::LigaturesState discretionaryLigaturesState = FontDescription::NormalLigaturesState; + FontDescription::LigaturesState historicalLigaturesState = FontDescription::NormalLigaturesState; + + if (value->isValueList()) { + CSSValueList* valueList = static_cast<CSSValueList*>(value); + for (size_t i = 0; i < valueList->length(); ++i) { + CSSValue* item = valueList->itemWithoutBoundsCheck(i); + ASSERT(item->isPrimitiveValue()); + if (item->isPrimitiveValue()) { + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(item); + switch (primitiveValue->getIdent()) { + case CSSValueNoCommonLigatures: + commonLigaturesState = FontDescription::DisabledLigaturesState; + break; + case CSSValueCommonLigatures: + commonLigaturesState = FontDescription::EnabledLigaturesState; + break; + case CSSValueNoDiscretionaryLigatures: + discretionaryLigaturesState = FontDescription::DisabledLigaturesState; + break; + case CSSValueDiscretionaryLigatures: + discretionaryLigaturesState = FontDescription::EnabledLigaturesState; + break; + case CSSValueNoHistoricalLigatures: + historicalLigaturesState = FontDescription::DisabledLigaturesState; + break; + case CSSValueHistoricalLigatures: + historicalLigaturesState = FontDescription::EnabledLigaturesState; + break; + default: + ASSERT_NOT_REACHED(); + break; + } + } + } + } +#if !ASSERT_DISABLED + else { + ASSERT(value->isPrimitiveValue()); + ASSERT(static_cast<CSSPrimitiveValue*>(value)->getIdent() == CSSValueNormal); + } +#endif + + FontDescription fontDescription = selector->fontDescription(); + fontDescription.setCommonLigaturesState(commonLigaturesState); + fontDescription.setDiscretionaryLigaturesState(discretionaryLigaturesState); + fontDescription.setHistoricalLigaturesState(historicalLigaturesState); + selector->setFontDescription(fontDescription); + } + + static PropertyHandler createHandler() + { + return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); + } +}; + enum BorderImageType { Image = 0, Mask }; template <BorderImageType borderImageType, CSSPropertyID property, @@ -779,7 +907,7 @@ public: NinePieceImage image(getValue(selector->style())); switch (modifier) { case Outset: - image.setOutset(LengthBox()); + image.setOutset(LengthBox(0)); break; case Repeat: image.setHorizontalRule(StretchImageRule); @@ -939,21 +1067,19 @@ public: if (!item->isPrimitiveValue()) continue; CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(item); - int type = primitiveValue->primitiveType(); - if (type == CSSPrimitiveValue::CSS_URI) { + if (primitiveValue->isURI()) { if (primitiveValue->isCursorImageValue()) { CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue); if (image->updateIfSVGCursorIsUsed(selector->element())) // Elements with SVG cursors are not allowed to share style. selector->style()->setUnique(); selector->style()->addCursor(selector->cachedOrPendingFromValue(CSSPropertyCursor, image), image->hotSpot()); } - } else if (type == CSSPrimitiveValue::CSS_IDENT) + } else if (primitiveValue->isIdent()) selector->style()->setCursor(*primitiveValue); } } else if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); - int type = primitiveValue->primitiveType(); - if (type == CSSPrimitiveValue::CSS_IDENT && selector->style()->cursor() != ECursor(*primitiveValue)) + if (primitiveValue->isIdent() && selector->style()->cursor() != ECursor(*primitiveValue)) selector->style()->setCursor(*primitiveValue); } } @@ -1152,9 +1278,9 @@ public: pageSizeType = PAGE_SIZE_RESOLVED; width = height = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle()); } else { - if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_IDENT) - return; switch (primitiveValue->getIdent()) { + case 0: + return; case CSSValueAuto: pageSizeType = PAGE_SIZE_AUTO; break; @@ -1224,7 +1350,7 @@ public: return; CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) { + if (primitiveValue->isString()) { selector->style()->setTextEmphasisFill(TextEmphasisFillFilled); selector->style()->setTextEmphasisMark(TextEmphasisMarkCustom); selector->style()->setTextEmphasisCustomMark(primitiveValue->getStringValue()); @@ -1471,11 +1597,11 @@ public: float docZoom = selector->document()->renderer()->style()->zoom(); selector->setEffectiveZoom(docZoom); selector->setZoom(docZoom); - } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) { + } else if (primitiveValue->isPercentage()) { resetEffectiveZoom(selector); if (float percent = primitiveValue->getFloatValue()) selector->setZoom(percent / 100.0f); - } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + } else if (primitiveValue->isNumber()) { resetEffectiveZoom(selector); if (float number = primitiveValue->getFloatValue()) selector->setZoom(number); @@ -1495,6 +1621,9 @@ private: #if ENABLE(SVG) if (selector->element() && selector->element()->isSVGElement() && selector->style()->styleType() == NOPSEUDO) return (displayPropertyValue == INLINE || displayPropertyValue == BLOCK || displayPropertyValue == NONE); +#else + UNUSED_PARAM(selector); + UNUSED_PARAM(displayPropertyValue); #endif return true; } @@ -1618,12 +1747,12 @@ CSSStyleApplyProperty::CSSStyleApplyProperty() setPropertyHandler(CSSPropertyBorderBottomStyle, ApplyPropertyDefault<EBorderStyle, &RenderStyle::borderBottomStyle, EBorderStyle, &RenderStyle::setBorderBottomStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::createHandler()); setPropertyHandler(CSSPropertyBorderLeftStyle, ApplyPropertyDefault<EBorderStyle, &RenderStyle::borderLeftStyle, EBorderStyle, &RenderStyle::setBorderLeftStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::createHandler()); - setPropertyHandler(CSSPropertyBorderTopWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); - setPropertyHandler(CSSPropertyBorderRightWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); - setPropertyHandler(CSSPropertyBorderBottomWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); - setPropertyHandler(CSSPropertyBorderLeftWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); - setPropertyHandler(CSSPropertyOutlineWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); - setPropertyHandler(CSSPropertyWebkitColumnRuleWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); + setPropertyHandler(CSSPropertyBorderTopWidth, ApplyPropertyComputeLength<unsigned, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); + setPropertyHandler(CSSPropertyBorderRightWidth, ApplyPropertyComputeLength<unsigned, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); + setPropertyHandler(CSSPropertyBorderBottomWidth, ApplyPropertyComputeLength<unsigned, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); + setPropertyHandler(CSSPropertyBorderLeftWidth, ApplyPropertyComputeLength<unsigned, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth, &RenderStyle::initialBorderWidth, NormalDisabled, ThicknessEnabled>::createHandler()); + setPropertyHandler(CSSPropertyOutlineWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth, &RenderStyle::initialOutlineWidth, NormalDisabled, ThicknessEnabled>::createHandler()); + setPropertyHandler(CSSPropertyWebkitColumnRuleWidth, ApplyPropertyComputeLength<unsigned short, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth, &RenderStyle::initialColumnRuleWidth, NormalDisabled, ThicknessEnabled>::createHandler()); setPropertyHandler(CSSPropertyBorderTop, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderTopColor, CSSPropertyBorderTopStyle, CSSPropertyBorderTopWidth>::createHandler()); setPropertyHandler(CSSPropertyBorderRight, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderRightColor, CSSPropertyBorderRightStyle, CSSPropertyBorderRightWidth>::createHandler()); @@ -1635,7 +1764,7 @@ CSSStyleApplyProperty::CSSStyleApplyProperty() setPropertyHandler(CSSPropertyBorderColor, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor>::createHandler()); setPropertyHandler(CSSPropertyBorder, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderStyle, CSSPropertyBorderWidth, CSSPropertyBorderColor>::createHandler()); - setPropertyHandler(CSSPropertyBorderImage, ApplyPropertyBorderImage<Image, CSSPropertyBorderImage, &RenderStyle::borderImage, &RenderStyle::setBorderImage>::createHandler()); + setPropertyHandler(CSSPropertyBorderImage, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderImageSource, CSSPropertyBorderImageSlice, CSSPropertyBorderImageWidth, CSSPropertyBorderImageOutset, CSSPropertyBorderImageRepeat>::createHandler()); setPropertyHandler(CSSPropertyWebkitBorderImage, ApplyPropertyBorderImage<Image, CSSPropertyWebkitBorderImage, &RenderStyle::borderImage, &RenderStyle::setBorderImage>::createHandler()); setPropertyHandler(CSSPropertyWebkitMaskBoxImage, ApplyPropertyBorderImage<Mask, CSSPropertyWebkitMaskBoxImage, &RenderStyle::maskBoxImage, &RenderStyle::setMaskBoxImage>::createHandler()); @@ -1665,6 +1794,8 @@ CSSStyleApplyProperty::CSSStyleApplyProperty() setPropertyHandler(CSSPropertyLetterSpacing, ApplyPropertyComputeLength<int, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing, &RenderStyle::initialLetterWordSpacing, NormalEnabled, ThicknessDisabled, SVGZoomEnabled>::createHandler()); setPropertyHandler(CSSPropertyWordSpacing, ApplyPropertyComputeLength<int, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing, &RenderStyle::initialLetterWordSpacing, NormalEnabled, ThicknessDisabled, SVGZoomEnabled>::createHandler()); + setPropertyHandler(CSSPropertyClip, ApplyPropertyClip::createHandler()); + setPropertyHandler(CSSPropertyCursor, ApplyPropertyCursor::createHandler()); setPropertyHandler(CSSPropertyCounterIncrement, ApplyPropertyCounter<Increment>::createHandler()); @@ -1672,6 +1803,7 @@ CSSStyleApplyProperty::CSSStyleApplyProperty() setPropertyHandler(CSSPropertyWebkitFlexOrder, ApplyPropertyDefault<int, &RenderStyle::flexOrder, int, &RenderStyle::setFlexOrder, int, &RenderStyle::initialFlexOrder>::createHandler()); setPropertyHandler(CSSPropertyWebkitFlexPack, ApplyPropertyDefault<EFlexPack, &RenderStyle::flexPack, EFlexPack, &RenderStyle::setFlexPack, EFlexPack, &RenderStyle::initialFlexPack>::createHandler()); + setPropertyHandler(CSSPropertyWebkitFlexAlign, ApplyPropertyDefault<EFlexAlign, &RenderStyle::flexAlign, EFlexAlign, &RenderStyle::setFlexAlign, EFlexAlign, &RenderStyle::initialFlexAlign>::createHandler()); setPropertyHandler(CSSPropertyWebkitFlexItemAlign, ApplyPropertyDefault<EFlexAlign, &RenderStyle::flexItemAlign, EFlexAlign, &RenderStyle::setFlexItemAlign, EFlexAlign, &RenderStyle::initialFlexItemAlign>::createHandler()); setPropertyHandler(CSSPropertyWebkitFlexDirection, ApplyPropertyDefault<EFlexDirection, &RenderStyle::flexDirection, EFlexDirection, &RenderStyle::setFlexDirection, EFlexDirection, &RenderStyle::initialFlexDirection>::createHandler()); setPropertyHandler(CSSPropertyWebkitFlexWrap, ApplyPropertyDefault<EFlexWrap, &RenderStyle::flexWrap, EFlexWrap, &RenderStyle::setFlexWrap, EFlexWrap, &RenderStyle::initialFlexWrap>::createHandler()); @@ -1684,6 +1816,7 @@ CSSStyleApplyProperty::CSSStyleApplyProperty() setPropertyHandler(CSSPropertyWebkitFontKerning, ApplyPropertyFont<FontDescription::Kerning, &FontDescription::kerning, &FontDescription::setKerning, FontDescription::AutoKerning>::createHandler()); setPropertyHandler(CSSPropertyWebkitFontSmoothing, ApplyPropertyFont<FontSmoothingMode, &FontDescription::fontSmoothing, &FontDescription::setFontSmoothing, AutoSmoothing>::createHandler()); setPropertyHandler(CSSPropertyWebkitTextOrientation, ApplyPropertyFont<TextOrientation, &FontDescription::textOrientation, &FontDescription::setTextOrientation, TextOrientationVerticalRight>::createHandler()); + setPropertyHandler(CSSPropertyWebkitFontVariantLigatures, ApplyPropertyFontVariantLigatures::createHandler()); setPropertyHandler(CSSPropertyFontWeight, ApplyPropertyFontWeight::createHandler()); setPropertyHandler(CSSPropertyTextAlign, ApplyPropertyTextAlign::createHandler()); diff --git a/Source/WebCore/css/CSSStyleDeclaration.cpp b/Source/WebCore/css/CSSStyleDeclaration.cpp index a1d61b88f..133fea2b7 100644 --- a/Source/WebCore/css/CSSStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSStyleDeclaration.cpp @@ -21,7 +21,6 @@ #include "config.h" #include "CSSStyleDeclaration.h" -#include "CSSElementStyleDeclaration.h" #include "CSSMutableStyleDeclaration.h" #include "CSSParser.h" #include "CSSProperty.h" @@ -29,6 +28,7 @@ #include "CSSRule.h" #include "Node.h" #include "SVGElement.h" +#include "StyledElement.h" #include <wtf/ASCIICType.h> #include <wtf/text/CString.h> #ifndef NDEBUG @@ -39,84 +39,27 @@ using namespace WTF; namespace WebCore { -CSSStyleDeclaration::CSSStyleDeclaration(CSSRule* parent) - : m_strictParsing(!parent || parent->useStrictParsing()) -#ifndef NDEBUG - , m_iteratorCount(0) -#endif - , m_isElementStyleDeclaration(false) +CSSStyleDeclaration::CSSStyleDeclaration(CSSRule* parentRule) + : m_strictParsing(!parentRule || parentRule->useStrictParsing()) , m_isInlineStyleDeclaration(false) - , m_parentRule(parent) -{ -} - -CSSStyleSheet* CSSStyleDeclaration::parentStyleSheet() const -{ - if (parentRule()) - return parentRule()->parentStyleSheet(); - if (isElementStyleDeclaration()) - return static_cast<const CSSElementStyleDeclaration*>(this)->styleSheet(); - return 0; -} - -PassRefPtr<CSSValue> CSSStyleDeclaration::getPropertyCSSValue(const String& propertyName) -{ - int propID = cssPropertyID(propertyName); - if (!propID) - return 0; - return getPropertyCSSValue(propID); -} - -String CSSStyleDeclaration::getPropertyValue(const String &propertyName) -{ - int propID = cssPropertyID(propertyName); - if (!propID) - return String(); - return getPropertyValue(propID); -} - -String CSSStyleDeclaration::getPropertyPriority(const String& propertyName) -{ - int propID = cssPropertyID(propertyName); - if (!propID) - return String(); - return getPropertyPriority(propID) ? "important" : ""; -} - -String CSSStyleDeclaration::getPropertyShorthand(const String& propertyName) + , m_parent(parentRule) { - int propID = cssPropertyID(propertyName); - if (!propID) - return String(); - int shorthandID = getPropertyShorthand(propID); - if (!shorthandID) - return String(); - return getPropertyName(static_cast<CSSPropertyID>(shorthandID)); } -bool CSSStyleDeclaration::isPropertyImplicit(const String& propertyName) +CSSStyleDeclaration::CSSStyleDeclaration(StyledElement* parentElement) + : m_strictParsing(false) + , m_isInlineStyleDeclaration(true) + , m_parent(parentElement) { - int propID = cssPropertyID(propertyName); - if (!propID) - return false; - return isPropertyImplicit(propID); } -void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode& ec) -{ - int propID = cssPropertyID(propertyName); - if (!propID) - return; - bool important = priority.find("important", 0, false) != notFound; - setProperty(propID, value, important, ec); -} - -String CSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionCode& ec) +CSSStyleSheet* CSSStyleDeclaration::parentStyleSheet() const { - int propID = cssPropertyID(propertyName); - if (!propID) - return String(); - return removeProperty(propID, ec); + if (m_isInlineStyleDeclaration) { + Document* document = m_parent.element ? m_parent.element->document() : 0; + return document ? document->elementSheet() : 0; + } + return m_parent.rule ? m_parent.rule->parentStyleSheet() : 0; } bool CSSStyleDeclaration::isPropertyName(const String& propertyName) @@ -124,44 +67,6 @@ bool CSSStyleDeclaration::isPropertyName(const String& propertyName) return cssPropertyID(propertyName); } -bool CSSStyleDeclaration::cssPropertyMatches(const CSSProperty* property) const -{ - RefPtr<CSSValue> value = getPropertyCSSValue(property->id()); - return value && value->cssText() == property->value()->cssText(); -} - -void CSSStyleDeclaration::diff(CSSMutableStyleDeclaration* style) const -{ - if (!style) - return; - - Vector<int> propertiesToRemove; - { - CSSMutableStyleDeclaration::const_iterator end = style->end(); - for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) { - const CSSProperty& property = *it; - if (cssPropertyMatches(&property)) - propertiesToRemove.append(property.id()); - } - } - - // FIXME: This should use mass removal. - for (unsigned i = 0; i < propertiesToRemove.size(); i++) - style->removeProperty(propertiesToRemove[i]); -} - -PassRefPtr<CSSMutableStyleDeclaration> CSSStyleDeclaration::copyPropertiesInSet(const int* set, unsigned length) const -{ - Vector<CSSProperty> list; - list.reserveInitialCapacity(length); - for (unsigned i = 0; i < length; i++) { - RefPtr<CSSValue> value = getPropertyCSSValue(set[i]); - if (value) - list.append(CSSProperty(set[i], value.release(), false)); - } - return CSSMutableStyleDeclaration::create(list); -} - #ifndef NDEBUG void CSSStyleDeclaration::showStyle() { diff --git a/Source/WebCore/css/CSSStyleDeclaration.h b/Source/WebCore/css/CSSStyleDeclaration.h index a54b0c60a..12910da46 100644 --- a/Source/WebCore/css/CSSStyleDeclaration.h +++ b/Source/WebCore/css/CSSStyleDeclaration.h @@ -21,6 +21,7 @@ #ifndef CSSStyleDeclaration_h #define CSSStyleDeclaration_h +#include "CSSPropertyNames.h" #include "CSSRule.h" #include <wtf/Forward.h> @@ -30,6 +31,7 @@ class CSSMutableStyleDeclaration; class CSSProperty; class CSSStyleSheet; class CSSValue; +class StyledElement; typedef int ExceptionCode; @@ -40,70 +42,61 @@ public: static bool isPropertyName(const String&); - CSSRule* parentRule() const { return m_parentRule; } - void clearParentRule() { m_parentRule = 0; } + CSSRule* parentRule() const { return m_isInlineStyleDeclaration ? 0 : m_parent.rule; } + void clearParentRule() { ASSERT(!m_isInlineStyleDeclaration); m_parent.rule = 0; } + + StyledElement* parentElement() const { ASSERT(m_isInlineStyleDeclaration); return m_parent.element; } + void clearParentElement() { ASSERT(m_isInlineStyleDeclaration); m_parent.element = 0; } CSSStyleSheet* parentStyleSheet() const; virtual String cssText() const = 0; virtual void setCssText(const String&, ExceptionCode&) = 0; - - unsigned length() const { return virtualLength(); } - virtual unsigned virtualLength() const = 0; - bool isEmpty() const { return !length(); } + virtual unsigned length() const = 0; virtual String item(unsigned index) const = 0; - - PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName); - String getPropertyValue(const String& propertyName); - String getPropertyPriority(const String& propertyName); - String getPropertyShorthand(const String& propertyName); - bool isPropertyImplicit(const String& propertyName); - - virtual PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID) const = 0; - virtual String getPropertyValue(int propertyID) const = 0; - virtual bool getPropertyPriority(int propertyID) const = 0; - virtual int getPropertyShorthand(int propertyID) const = 0; - virtual bool isPropertyImplicit(int propertyID) const = 0; - - void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode&); - String removeProperty(const String& propertyName, ExceptionCode&); - virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&) = 0; - virtual String removeProperty(int propertyID, ExceptionCode&) = 0; + virtual PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName) = 0; + virtual String getPropertyValue(const String& propertyName) = 0; + virtual String getPropertyPriority(const String& propertyName) = 0; + virtual String getPropertyShorthand(const String& propertyName) = 0; + virtual bool isPropertyImplicit(const String& propertyName) = 0; + virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode&) = 0; + virtual String removeProperty(const String& propertyName, ExceptionCode&) = 0; + + // CSSPropertyID versions of the CSSOM functions to support bindings and editing. + // Use the non-virtual methods in the concrete subclasses when possible. + virtual PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) = 0; + virtual String getPropertyValueInternal(CSSPropertyID) = 0; + virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionCode&) = 0; virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const = 0; virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable() = 0; - void diff(CSSMutableStyleDeclaration*) const; - - PassRefPtr<CSSMutableStyleDeclaration> copyPropertiesInSet(const int* set, unsigned length) const; + virtual bool cssPropertyMatches(const CSSProperty*) const = 0; #ifndef NDEBUG void showStyle(); #endif - bool isElementStyleDeclaration() const { return m_isElementStyleDeclaration; } bool isInlineStyleDeclaration() const { return m_isInlineStyleDeclaration; } protected: CSSStyleDeclaration(CSSRule* parentRule = 0); - - virtual bool cssPropertyMatches(const CSSProperty*) const; + CSSStyleDeclaration(StyledElement* parentElement); // The bits in this section are only used by specific subclasses but kept here // to maximize struct packing. // CSSMutableStyleDeclaration bits: bool m_strictParsing : 1; -#ifndef NDEBUG - unsigned m_iteratorCount : 4; -#endif - - // CSSElementStyleDeclaration bits: - bool m_isElementStyleDeclaration : 1; bool m_isInlineStyleDeclaration : 1; private: - CSSRule* m_parentRule; + union Parent { + Parent(CSSRule* rule) : rule(rule) { } + Parent(StyledElement* element) : element(element) { } + CSSRule* rule; + StyledElement* element; + } m_parent; }; } // namespace WebCore diff --git a/Source/WebCore/css/CSSStyleDeclaration.idl b/Source/WebCore/css/CSSStyleDeclaration.idl index d1b470f87..976130499 100644 --- a/Source/WebCore/css/CSSStyleDeclaration.idl +++ b/Source/WebCore/css/CSSStyleDeclaration.idl @@ -30,7 +30,7 @@ module css { CustomGetPropertyNames, V8DependentLifetime ] CSSStyleDeclaration { - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString cssText setter raises(DOMException); [ConvertNullStringTo=Null] DOMString getPropertyValue(in [Optional=CallWithDefaultValue] DOMString propertyName); @@ -39,7 +39,7 @@ module css { raises(DOMException); [ConvertNullStringTo=Null] DOMString getPropertyPriority(in [Optional=CallWithDefaultValue] DOMString propertyName); [OldStyleObjC] void setProperty(in [Optional=CallWithDefaultValue] DOMString propertyName, - in [ConvertNullToNullString,Optional=CallWithDefaultValue] DOMString value, + in [TreatNullAs=EmptyString,Optional=CallWithDefaultValue] DOMString value, in [Optional=CallWithDefaultValue] DOMString priority) raises(DOMException); diff --git a/Source/WebCore/css/CSSStyleRule.cpp b/Source/WebCore/css/CSSStyleRule.cpp index 6296e64b7..535e9f15d 100644 --- a/Source/WebCore/css/CSSStyleRule.cpp +++ b/Source/WebCore/css/CSSStyleRule.cpp @@ -98,15 +98,8 @@ String CSSStyleRule::selectorText() const void CSSStyleRule::setSelectorText(const String& selectorText) { Document* doc = 0; - if (CSSStyleSheet* styleSheet = m_style->parentStyleSheet()) doc = styleSheet->findDocument(); - - if (!doc && m_style->isElementStyleDeclaration()) { - if (StyledElement* element = static_cast<CSSElementStyleDeclaration*>(m_style.get())->element()) - doc = element->document(); - } - if (!doc) return; @@ -135,7 +128,7 @@ String CSSStyleRule::cssText() const String result = selectorText(); result += " { "; - result += m_style->cssText(); + result += m_style->asText(); result += "}"; return result; diff --git a/Source/WebCore/css/CSSStyleRule.h b/Source/WebCore/css/CSSStyleRule.h index 111c5f1aa..713e68245 100644 --- a/Source/WebCore/css/CSSStyleRule.h +++ b/Source/WebCore/css/CSSStyleRule.h @@ -43,15 +43,15 @@ public: String selectorText() const; void setSelectorText(const String&); - CSSMutableStyleDeclaration* style() const { return m_style.get(); } + CSSStyleDeclaration* style() const { return m_style.get(); } String cssText() const; void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectors) { m_selectorList.adoptSelectorVector(selectors); } - void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) { m_style = style; } + void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) { ASSERT(style->parentRule() == this); m_style = style; } const CSSSelectorList& selectorList() const { return m_selectorList; } - CSSMutableStyleDeclaration* declaration() { return m_style.get(); } + CSSMutableStyleDeclaration* declaration() const { return m_style.get(); } void addSubresourceStyleURLs(ListHashSet<KURL>& urls); diff --git a/Source/WebCore/css/CSSStyleRule.idl b/Source/WebCore/css/CSSStyleRule.idl index 4abfbfc45..aca408e29 100644 --- a/Source/WebCore/css/CSSStyleRule.idl +++ b/Source/WebCore/css/CSSStyleRule.idl @@ -23,7 +23,7 @@ module css { // Introduced in DOM Level 2: interface CSSStyleRule : CSSRule { - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString selectorText; + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString selectorText; readonly attribute CSSStyleDeclaration style; diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp index 97f19cfba..abac39885 100644 --- a/Source/WebCore/css/CSSStyleSelector.cpp +++ b/Source/WebCore/css/CSSStyleSelector.cpp @@ -33,7 +33,7 @@ #include "ContentData.h" #include "Counter.h" #include "CounterContent.h" -#include "CSSBorderImageValue.h" +#include "CSSBorderImage.h" #include "CSSCursorImageValue.h" #include "CSSFontFaceRule.h" #include "CSSFontSelector.h" @@ -65,6 +65,7 @@ #include "HTMLInputElement.h" #include "HTMLNames.h" #include "HTMLProgressElement.h" +#include "HTMLStyleElement.h" #include "HTMLTextAreaElement.h" #include "InspectorInstrumentation.h" #include "KeyframeList.h" @@ -81,6 +82,7 @@ #include "PerspectiveTransformOperation.h" #include "QuotesData.h" #include "Rect.h" +#include "RenderRegion.h" #include "RenderScrollbar.h" #include "RenderScrollbarTheme.h" #include "RenderStyleConstants.h" @@ -123,8 +125,11 @@ #endif #if ENABLE(CSS_SHADERS) +#include "CustomFilterNumberParameter.h" #include "CustomFilterOperation.h" +#include "CustomFilterParameter.h" #include "StyleCachedShader.h" +#include "StyleCustomFilterProgram.h" #include "StylePendingShader.h" #include "StyleShader.h" #include "WebKitCSSShaderValue.h" @@ -218,16 +223,17 @@ public: typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap; - void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0); + void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const Element* = 0); - void addStyleRule(CSSStyleRule* item); - void addRule(CSSStyleRule* rule, CSSSelector* sel); + void addStyleRule(CSSStyleRule*); + void addRule(CSSStyleRule*, CSSSelector*); void addPageRule(CSSPageRule*); - void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, CSSStyleRule*, CSSSelector*); + void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&); + void addRegionRule(WebKitCSSRegionRule*); void shrinkToFit(); void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; } - void collectFeatures(CSSStyleSelector::Features&) const; + const CSSStyleSelector::Features& features() const { return m_features; } const Vector<RuleData>* idRules(AtomicStringImpl* key) const { return m_idRules.get(key); } const Vector<RuleData>* classRules(AtomicStringImpl* key) const { return m_classRules.get(key); } @@ -249,6 +255,16 @@ public: Vector<RuleData> m_pageRules; unsigned m_ruleCount; bool m_autoShrinkToFitEnabled; + CSSStyleSelector::Features m_features; + + struct RuleSetSelectorPair { + RuleSetSelectorPair(CSSSelector* selector, RuleSet* ruleSet) : selector(selector), ruleSet(adoptPtr(ruleSet)) { } + RuleSetSelectorPair(const RuleSetSelectorPair& rs) : selector(rs.selector), ruleSet(const_cast<RuleSetSelectorPair*>(&rs)->ruleSet.release()) { } + CSSSelector* selector; + OwnPtr<RuleSet> ruleSet; + }; + + Vector<RuleSetSelectorPair> m_regionSelectorsAndRuleSets; }; static RuleSet* defaultStyle; @@ -257,9 +273,6 @@ static RuleSet* defaultPrintStyle; static RuleSet* defaultViewSourceStyle; static CSSStyleSheet* simpleDefaultStyleSheet; -static RuleSet* siblingRulesInDefaultStyle; -static RuleSet* uncommonAttributeRulesInDefaultStyle; - RenderStyle* CSSStyleSelector::s_styleNotYetAvailable; static void loadFullDefaultStyle(); @@ -272,27 +285,6 @@ static inline bool elementCanUseSimpleDefaultStyle(Element* e) return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag); } -static inline void collectSpecialRulesInDefaultStyle() -{ - CSSStyleSelector::Features features; - defaultStyle->collectFeatures(features); - ASSERT(features.idsInRules.isEmpty()); - delete siblingRulesInDefaultStyle; - delete uncommonAttributeRulesInDefaultStyle; - siblingRulesInDefaultStyle = features.siblingRules.leakPtr(); - uncommonAttributeRulesInDefaultStyle = features.uncommonAttributeRules.leakPtr(); -} - -static inline void assertNoSiblingRulesInDefaultStyle() -{ -#ifndef NDEBUG - if (siblingRulesInDefaultStyle) - return; - collectSpecialRulesInDefaultStyle(); - ASSERT(!siblingRulesInDefaultStyle); -#endif -} - static const MediaQueryEvaluator& screenEval() { DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen")); @@ -308,20 +300,16 @@ static const MediaQueryEvaluator& printEval() static CSSMutableStyleDeclaration* leftToRightDeclaration() { DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create())); - if (!leftToRightDecl->length()) { - leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false); - leftToRightDecl->setStrictParsing(false); - } + if (leftToRightDecl->isEmpty()) + leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr); return leftToRightDecl.get(); } static CSSMutableStyleDeclaration* rightToLeftDeclaration() { DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create())); - if (!rightToLeftDecl->length()) { - rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false); - rightToLeftDecl->setStrictParsing(false); - } + if (rightToLeftDecl->isEmpty()) + rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl); return rightToLeftDecl.get(); } @@ -336,6 +324,7 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee , m_rootElementStyle(0) , m_element(0) , m_styledElement(0) + , m_regionForStyling(0) , m_elementLinkState(NotInsideLink) , m_parentNode(0) , m_lineHeightValue(0) @@ -349,6 +338,9 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee #if ENABLE(CSS_SHADERS) , m_hasPendingShaders(false) #endif +#if ENABLE(STYLE_SCOPED) + , m_scopingElementStackParent(0) +#endif { Element* root = document->documentElement(); @@ -380,6 +372,8 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee m_authorStyle = adoptPtr(new RuleSet); // Adding rules from multiple sheets, shrink at the end. + // Adding global rules from multiple sheets, shrink at the end. + // Note that there usually is only 1 sheet for scoped rules, so auto-shrink-to-fit is fine. m_authorStyle->disableAutoShrinkToFit(); // FIXME: This sucks! The user sheet is reparsed every time! @@ -409,43 +403,70 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee m_userStyle = tempUserStyle.release(); // Add rules from elements like SVG's <font-face> - if (mappedElementSheet) + if (mappedElementSheet) { + // FIXME: see if style scopes can/should be added here. m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this); - - // add stylesheets from document - unsigned length = styleSheets->length(); - for (unsigned i = 0; i < length; i++) { - StyleSheet* sheet = styleSheets->item(i); - if (sheet->isCSSStyleSheet() && !sheet->disabled()) - m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this); } - m_authorStyle->shrinkToFit(); - collectFeatures(); + // add stylesheets from document + appendAuthorStylesheets(0, styleSheets->vector()); +} - if (document->renderer() && document->renderer()->style()) - document->renderer()->style()->font().update(fontSelector()); +static PassOwnPtr<RuleSet> makeRuleSet(const Vector<CSSStyleSelector::RuleSelectorPair>& rules) +{ + size_t size = rules.size(); + if (!size) + return nullptr; + OwnPtr<RuleSet> ruleSet = adoptPtr(new RuleSet); + for (size_t i = 0; i < size; ++i) + ruleSet->addRule(rules[i].rule, rules[i].selector); + return ruleSet.release(); } void CSSStyleSelector::collectFeatures() { + m_features.clear(); // Collect all ids and rules using sibling selectors (:first-child and similar) // in the current set of stylesheets. Style sharing code uses this information to reject // sharing candidates. - // Usually there are no sibling rules in the default style but the MathML sheet has some. - if (siblingRulesInDefaultStyle) - siblingRulesInDefaultStyle->collectFeatures(m_features); - if (uncommonAttributeRulesInDefaultStyle) - uncommonAttributeRulesInDefaultStyle->collectFeatures(m_features); - m_authorStyle->collectFeatures(m_features); + m_features.add(defaultStyle->features()); + m_features.add(m_authorStyle->features()); +#if ENABLE(STYLE_SCOPED) + for (ScopedRuleSetMap::iterator it = m_scopedAuthorStyles.begin(); it != m_scopedAuthorStyles.end(); ++it) + m_features.add(it->second->features()); +#endif if (m_userStyle) - m_userStyle->collectFeatures(m_features); - if (m_features.siblingRules) - m_features.siblingRules->shrinkToFit(); - if (m_features.uncommonAttributeRules) - m_features.uncommonAttributeRules->shrinkToFit(); + m_features.add(m_userStyle->features()); + + m_siblingRuleSet = makeRuleSet(m_features.siblingRules); + m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules); } +#if ENABLE(STYLE_SCOPED) +Element* CSSStyleSelector::determineScopingElement(const CSSStyleSheet* sheet) +{ + ASSERT(sheet); + + Node* ownerNode = sheet->findStyleSheetOwnerNode(); + if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTMLNames::styleTag)) + return 0; + + HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode); + if (!styleElement->scoped()) + return 0; + + return styleElement->parentElement(); +} + +inline RuleSet* CSSStyleSelector::scopedRuleSetForElement(const Element* element) const +{ + if (!element->hasScopedHTMLStyleChild()) + return 0; + ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(element); + return it != m_scopedAuthorStyles.end() ? it->second.get() : 0; +} +#endif + void CSSStyleSelector::appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >& stylesheets) { // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver @@ -454,20 +475,89 @@ void CSSStyleSelector::appendAuthorStylesheets(unsigned firstNew, const Vector<R for (unsigned i = firstNew; i < size; ++i) { if (!stylesheets[i]->isCSSStyleSheet() || stylesheets[i]->disabled()) continue; - m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(stylesheets[i].get()), *m_medium, this); + CSSStyleSheet* cssSheet = static_cast<CSSStyleSheet*>(stylesheets[i].get()); +#if ENABLE(STYLE_SCOPED) + const Element* scope = determineScopingElement(cssSheet); + if (scope) { + pair<ScopedRuleSetMap::iterator, bool> addResult = m_scopedAuthorStyles.add(scope, nullptr); + if (addResult.second) + addResult.first->second = adoptPtr(new RuleSet()); + addResult.first->second->addRulesFromSheet(cssSheet, *m_medium, this, scope); + continue; + } +#endif + m_authorStyle->addRulesFromSheet(cssSheet, *m_medium, this); } m_authorStyle->shrinkToFit(); - // FIXME: This really only needs to collect the features from the newly added sheets. - m_features.clear(); collectFeatures(); if (document()->renderer() && document()->renderer()->style()) document()->renderer()->style()->font().update(fontSelector()); } -void CSSStyleSelector::addRegionRule(PassRefPtr<WebKitCSSRegionRule> regionStyleRule) +#if ENABLE(STYLE_SCOPED) +void CSSStyleSelector::setupScopingElementStack(const Element* parent) { - m_regionStyleRules.append(regionStyleRule); + // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere. + ASSERT(!m_scopedAuthorStyles.isEmpty()); + + m_scopingElementStack.shrink(0); + for (; parent; parent = parent->parentOrHostElement()) { + RuleSet* ruleSet = scopedRuleSetForElement(parent); + if (ruleSet) + m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet)); + } + m_scopingElementStack.reverse(); + m_scopingElementStackParent = parent; +} +#endif + +void CSSStyleSelector::pushParent(Element* parent) +{ + const Element* parentsParent = parent->parentOrHostElement(); + // We are not always invoked consistently. For example, script execution can cause us to enter + // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree. + // Reset the stack in this case, or if we see a new root element. + // Otherwise just push the new parent. + if (!parentsParent || m_checker.parentStackIsEmpty()) + m_checker.setupParentStack(parent); + else + m_checker.pushParent(parent); + +#if ENABLE(STYLE_SCOPED) + // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere. + if (m_scopedAuthorStyles.isEmpty()) { + ASSERT(!m_scopingElementStackParent); + ASSERT(m_scopingElementStack.isEmpty()); + return; + } + // In some wacky cases during style resolve we may get invoked for random elements. + // Recreate the whole scoping element stack in such cases. + if (!scopingElementStackIsConsistent(parentsParent)) { + setupScopingElementStack(parent); + return; + } + // Otherwise just push the parent onto the stack. + RuleSet* ruleSet = scopedRuleSetForElement(parent); + if (ruleSet) + m_scopingElementStack.append(ScopeStackFrame(parent, ruleSet)); + m_scopingElementStackParent = parent; +#endif +} + +void CSSStyleSelector::popParent(Element* parent) +{ + // Note that we may get invoked for some random elements in some wacky cases during style resolve. + // Pause maintaining the stack in this case. + if (m_checker.parentStackIsConsistent(parent)) + m_checker.popParent(); +#if ENABLE(STYLE_SCOPED) + // Only bother to update the scoping element stack if it is consistent. + if (scopingElementStackIsConsistent(parent)) { + m_scopingElementStack.removeLast(); + m_scopingElementStackParent = parent->parentOrHostElement(); + } +#endif } // This is a simplified style setting function for keyframe styles @@ -513,6 +603,21 @@ CSSStyleSelector::Features::Features() CSSStyleSelector::Features::~Features() { } + +void CSSStyleSelector::Features::add(const CSSStyleSelector::Features& other) +{ + HashSet<AtomicStringImpl*>::iterator end = other.idsInRules.end(); + for (HashSet<AtomicStringImpl*>::iterator it = other.idsInRules.begin(); it != end; ++it) + idsInRules.add(*it); + end = other.attrsInRules.end(); + for (HashSet<AtomicStringImpl*>::iterator it = other.attrsInRules.begin(); it != end; ++it) + attrsInRules.add(*it); + siblingRules.append(other.siblingRules); + uncommonAttributeRules.append(other.uncommonAttributeRules); + usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; + usesBeforeAfterRules = usesBeforeAfterRules || other.usesBeforeAfterRules; + usesLinkRules = usesLinkRules || other.usesLinkRules; +} void CSSStyleSelector::Features::clear() { @@ -591,11 +696,8 @@ static void loadViewSourceStyle() static void ensureDefaultStyleSheetsForElement(Element* element) { - if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) { + if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) loadFullDefaultStyle(); - assertNoSiblingRulesInDefaultStyle(); - collectSpecialRulesInDefaultStyle(); - } #if ENABLE(SVG) static bool loadedSVGUserAgentSheet; @@ -605,21 +707,17 @@ static void ensureDefaultStyleSheetsForElement(Element* element) CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); defaultStyle->addRulesFromSheet(svgSheet, screenEval()); defaultPrintStyle->addRulesFromSheet(svgSheet, printEval()); - assertNoSiblingRulesInDefaultStyle(); - collectSpecialRulesInDefaultStyle(); } #endif -#if ENABLE(MATHML) static bool loadedMathMLUserAgentSheet; +#if ENABLE(MATHML) if (element->isMathMLElement() && !loadedMathMLUserAgentSheet) { // MathML rules. loadedMathMLUserAgentSheet = true; CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet)); defaultStyle->addRulesFromSheet(mathMLSheet, screenEval()); defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval()); - // There are some sibling and uncommon attribute rules here. - collectSpecialRulesInDefaultStyle(); } #endif @@ -631,7 +729,6 @@ static void ensureDefaultStyleSheetsForElement(Element* element) CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules); defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval()); defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval()); - collectSpecialRulesInDefaultStyle(); } #endif @@ -643,9 +740,11 @@ static void ensureDefaultStyleSheetsForElement(Element* element) CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules); defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval()); defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval()); - collectSpecialRulesInDefaultStyle(); } #endif + + ASSERT(defaultStyle->features().idsInRules.isEmpty()); + ASSERT_UNUSED(loadedMathMLUserAgentSheet, loadedMathMLUserAgentSheet || defaultStyle->features().siblingRules.isEmpty()); } void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* styleDeclaration, unsigned linkMatchType) @@ -656,36 +755,53 @@ void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* styleDe newDeclaration.linkMatchType = linkMatchType; } -void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) +void CSSStyleSelector::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) { - m_matchedRules.clear(); - - if (!rules || !m_element) - return; + ASSERT(rules); + ASSERT(m_element); // We need to collect the rules for id, class, tag, and everything else into a buffer and // then sort the buffer. if (m_element->hasID()) - matchRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); if (m_element->hasClass()) { ASSERT(m_styledElement); const SpaceSplitString& classNames = m_styledElement->classNames(); size_t size = classNames.size(); for (size_t i = 0; i < size; ++i) - matchRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); } const AtomicString& pseudoId = m_element->shadowPseudoId(); if (!pseudoId.isEmpty()) { ASSERT(m_styledElement); - matchRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); } if (m_element->isLink()) - matchRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); if (m_checker.matchesFocusPseudoClass(m_element)) - matchRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); - matchRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); - matchRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules); +} + +void CSSStyleSelector::collectMatchingRulesForRegion(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) +{ + if (!m_regionForStyling) + return; + + unsigned size = rules->m_regionSelectorsAndRuleSets.size(); + for (unsigned i = 0; i < size; ++i) { + CSSSelector* regionSelector = rules->m_regionSelectorsAndRuleSets.at(i).selector; + if (checkRegionSelector(regionSelector, static_cast<Element*>(m_regionForStyling->node()))) { + RuleSet* regionRules = rules->m_regionSelectorsAndRuleSets.at(i).ruleSet.get(); + ASSERT(regionRules); + collectMatchingRules(regionRules, firstRuleIndex, lastRuleIndex, includeEmptyRules); + } + } +} +void CSSStyleSelector::sortAndTransferMatchedRules() +{ if (m_matchedRules.isEmpty()) return; @@ -712,6 +828,62 @@ void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& last } } +void CSSStyleSelector::matchScopedAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) +{ +#if ENABLE(STYLE_SCOPED) + if (m_scopedAuthorStyles.isEmpty()) + return; + + // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent). + const Element* parent = m_element->parentOrHostElement(); + if (!scopingElementStackIsConsistent(parent)) + setupScopingElementStack(parent); + for (size_t i = m_scopingElementStack.size(); i; --i) { + collectMatchingRules(m_scopingElementStack[i - 1].m_ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForRegion(m_scopingElementStack[i - 1].m_ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); + } + // Also include the current element. + RuleSet* ruleSet = scopedRuleSetForElement(m_element); + if (ruleSet) { + collectMatchingRules(ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForRegion(ruleSet, firstRuleIndex, lastRuleIndex, includeEmptyRules); + } +#else + UNUSED_PARAM(firstRuleIndex); + UNUSED_PARAM(lastRuleIndex); + UNUSED_PARAM(includeEmptyRules); +#endif +} + +void CSSStyleSelector::matchAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) +{ + m_matchedRules.clear(); + + if (!m_element) + return; + + // Match global author rules. + collectMatchingRules(m_authorStyle.get(), firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForRegion(m_authorStyle.get(), firstRuleIndex, lastRuleIndex, includeEmptyRules); + + matchScopedAuthorRules(firstRuleIndex, lastRuleIndex, includeEmptyRules); + + sortAndTransferMatchedRules(); +} + +void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) +{ + m_matchedRules.clear(); + + if (!rules || !m_element) + return; + + collectMatchingRules(rules, firstRuleIndex, lastRuleIndex, includeEmptyRules); + collectMatchingRulesForRegion(rules, firstRuleIndex, lastRuleIndex, includeEmptyRules); + + sortAndTransferMatchedRules(); +} + class MatchingUARulesScope { public: MatchingUARulesScope(); @@ -746,7 +918,7 @@ inline static bool matchesInTreeScope(TreeScope* treeScope, bool ruleReachesInto return MatchingUARulesScope::isMatchingUARules() || treeScope->applyAuthorSheets() || ruleReachesIntoShadowDOM; } -void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) +void CSSStyleSelector::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules) { if (!rules) return; @@ -769,7 +941,7 @@ void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& fir } // If the rule has no properties to apply, then ignore it in the non-debug mode. CSSMutableStyleDeclaration* decl = rule->declaration(); - if (!decl || (!decl->length() && !includeEmptyRules)) { + if (!decl || (decl->isEmpty() && !includeEmptyRules)) { InspectorInstrumentation::didMatchRule(cookie, false); continue; } @@ -820,42 +992,35 @@ void CSSStyleSelector::matchAllRules(MatchResult& result) // Now we check user sheet rules. if (m_matchAuthorAndUserStyles) - matchRules(m_userStyle.get(), result.firstUserRule, result.lastUserRule, false); + matchRules(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, false); // Now check author rules, beginning first with presentational attributes mapped from HTML. if (m_styledElement) { - // Ask if the HTML element has mapped attributes. - if (m_styledElement->hasMappedAttributes()) { - // Walk our attribute list and add in each decl. - const NamedNodeMap* map = m_styledElement->attributeMap(); + if (const NamedNodeMap* map = m_styledElement->attributeMap()) { + // Walk the element's attribute map and add all mapped attribute declarations. for (unsigned i = 0; i < map->length(); ++i) { - Attribute* attr = map->attributeItem(i); - if (attr->decl()) { - ASSERT(attr->isMappedAttribute()); - result.lastAuthorRule = m_matchedDecls.size(); - if (result.firstAuthorRule == -1) - result.firstAuthorRule = result.lastAuthorRule; - addMatchedDeclaration(attr->decl()); - } + Attribute* attribute = map->attributeItem(i); + if (!attribute->decl()) + continue; + ASSERT(attribute->isMappedAttribute()); + result.ranges.lastAuthorRule = m_matchedDecls.size(); + if (result.ranges.firstAuthorRule == -1) + result.ranges.firstAuthorRule = result.ranges.lastAuthorRule; + addMatchedDeclaration(attribute->decl()); } } - + // Now we check additional mapped declarations. // Tables and table cells share an additional mapped rule that must be applied // after all attributes, since their mapped style depends on the values of multiple attributes. - if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) { - Vector<CSSMutableStyleDeclaration*> additionalAttributeStyleDecls; - m_styledElement->additionalAttributeStyleDecls(additionalAttributeStyleDecls); - if (!additionalAttributeStyleDecls.isEmpty()) { - unsigned additionalDeclsSize = additionalAttributeStyleDecls.size(); - if (result.firstAuthorRule == -1) - result.firstAuthorRule = m_matchedDecls.size(); - result.lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1; - for (unsigned i = 0; i < additionalDeclsSize; ++i) - addMatchedDeclaration(additionalAttributeStyleDecls[i]); - result.isCacheable = false; - } + if (RefPtr<CSSMutableStyleDeclaration> additionalStyle = m_styledElement->additionalAttributeStyle()) { + if (result.ranges.firstAuthorRule == -1) + result.ranges.firstAuthorRule = m_matchedDecls.size(); + result.ranges.lastAuthorRule = m_matchedDecls.size(); + addMatchedDeclaration(additionalStyle.get()); + result.isCacheable = false; } + if (m_styledElement->isHTMLElement()) { bool isAuto; TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto); @@ -866,15 +1031,15 @@ void CSSStyleSelector::matchAllRules(MatchResult& result) // Check the rules in author sheets next. if (m_matchAuthorAndUserStyles) - matchRules(m_authorStyle.get(), result.firstAuthorRule, result.lastAuthorRule, false); + matchAuthorRules(result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, false); // Now check our inline style attribute. if (m_matchAuthorAndUserStyles && m_styledElement) { CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl(); if (inlineDecl) { - result.lastAuthorRule = m_matchedDecls.size(); - if (result.firstAuthorRule == -1) - result.firstAuthorRule = result.lastAuthorRule; + result.ranges.lastAuthorRule = m_matchedDecls.size(); + if (result.ranges.firstAuthorRule == -1) + result.ranges.firstAuthorRule = result.ranges.lastAuthorRule; addMatchedDeclaration(inlineDecl); result.isCacheable = false; } @@ -929,6 +1094,10 @@ Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeC return 0; if (!parent || !parent->isStyledElement()) return 0; +#if ENABLE(STYLE_SCOPED) + if (parent->hasScopedHTMLStyleChild()) + return 0; +#endif StyledElement* p = static_cast<StyledElement*>(parent); if (p->inlineStyleDecl()) return 0; @@ -1029,6 +1198,22 @@ bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const return true; } +static inline bool mappedAttributesEquivalent(NamedNodeMap* a, NamedNodeMap* b) +{ + ASSERT(a->mappedAttributeCount() == b->mappedAttributeCount()); + + for (size_t i = 0; i < a->length(); ++i) { + Attribute* attribute = a->attributeItem(i); + if (!attribute->decl()) + continue; + ASSERT(attribute->isMappedAttribute()); + Attribute* otherAttribute = b->getAttributeItem(attribute->name()); + if (!otherAttribute || attribute->value() != otherAttribute->value() || attribute->decl() != otherAttribute->decl()) + return false; + } + return true; +} + bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const { RenderStyle* style = element->renderStyle(); @@ -1043,7 +1228,8 @@ bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const return false; if (element->inlineStyleDecl()) return false; - if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes()) + size_t mappedAttributeCount = element->mappedAttributeCount(); + if (mappedAttributeCount != m_styledElement->mappedAttributeCount()) return false; if (element->isLink() != m_element->isLink()) return false; @@ -1075,6 +1261,11 @@ bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl())) return false; +#if ENABLE(STYLE_SCOPED) + if (element->hasScopedHTMLStyleChild()) + return false; +#endif + bool isControl = element->isFormControlElement(); if (isControl != m_element->isFormControlElement()) @@ -1104,7 +1295,7 @@ bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr)) return false; - if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap())) + if (mappedAttributeCount && !mappedAttributesEquivalent(element->attributeMap(), m_styledElement->attributeMap())) return false; if (element->isLink() && m_elementLinkState != style->insideLink()) @@ -1146,6 +1337,10 @@ RenderStyle* CSSStyleSelector::locateSharedStyle() return 0; if (parentStylePreventsSharing(m_parentStyle)) return 0; +#if ENABLE(STYLE_SCOPED) + if (m_styledElement->hasScopedHTMLStyleChild()) + return 0; +#endif // Check previous siblings and their cousins. unsigned count = 0; @@ -1164,10 +1359,10 @@ RenderStyle* CSSStyleSelector::locateSharedStyle() return 0; // Can't share if sibling rules apply. This is checked at the end as it should rarely fail. - if (matchesRuleSet(m_features.siblingRules.get())) + if (matchesRuleSet(m_siblingRuleSet.get())) return 0; // Can't share if attribute rules apply. - if (matchesRuleSet(m_features.uncommonAttributeRules.get())) + if (matchesRuleSet(m_uncommonAttributeRuleSet.get())) return 0; // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. if (parentStylePreventsSharing(m_parentStyle)) @@ -1184,17 +1379,17 @@ void CSSStyleSelector::matchUARules(MatchResult& result) result.isCacheable = false; RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") ? defaultPrintStyle : defaultStyle; - matchRules(userAgentStyleSheet, result.firstUARule, result.lastUARule, false); + matchRules(userAgentStyleSheet, result.ranges.firstUARule, result.ranges.lastUARule, false); // In quirks mode, we match rules from the quirks user agent sheet. if (!m_checker.strictParsing()) - matchRules(defaultQuirksStyle, result.firstUARule, result.lastUARule, false); + matchRules(defaultQuirksStyle, result.ranges.firstUARule, result.ranges.lastUARule, false); // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet. if (m_checker.document()->isViewSource()) { if (!defaultViewSourceStyle) loadViewSourceStyle(); - matchRules(defaultViewSourceStyle, result.firstUARule, result.lastUARule, false); + matchRules(defaultViewSourceStyle, result.ranges.firstUARule, result.ranges.lastUARule, false); } } @@ -1270,7 +1465,7 @@ static inline bool isAtShadowBoundary(Element* element) // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where // relative units are interpreted according to document root element style, styled only with UA stylesheet -PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault) +PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, RenderRegion* regionForStyling) { // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer // will vanish if a style recalc happens during loading. @@ -1286,6 +1481,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, Rend initElement(element); initForStyleResolve(element, defaultParent); + m_regionForStyling = regionForStyling; if (allowSharing) { RenderStyle* sharedStyle = locateSharedStyle(); if (sharedStyle) @@ -1333,7 +1529,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, Rend PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe) { if (keyframeRule->style()) - addMatchedDeclaration(keyframeRule->style()); + addMatchedDeclaration(keyframeRule->declaration()); ASSERT(!m_style); @@ -1372,10 +1568,10 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* el #endif // Add all the animating properties to the keyframe. - if (keyframeRule->style()) { - CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end(); - for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) { - int property = (*it).id(); + if (CSSMutableStyleDeclaration* styleDeclaration = keyframeRule->declaration()) { + unsigned propertyCount = styleDeclaration->propertyCount(); + for (unsigned i = 0; i < propertyCount; ++i) { + int property = styleDeclaration->propertyAt(i).id(); // Timing-function within keyframes is special, because it is not animated; it just // describes the timing function between this keyframe and the next. if (property != CSSPropertyWebkitAnimationTimingFunction) @@ -1463,8 +1659,8 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, matchUARules(matchResult); if (m_matchAuthorAndUserStyles) { - matchRules(m_userStyle.get(), matchResult.firstUserRule, matchResult.lastUserRule, false); - matchRules(m_authorStyle.get(), matchResult.firstAuthorRule, matchResult.lastAuthorRule, false); + matchRules(m_userStyle.get(), matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false); + matchAuthorRules(matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, false); } if (m_matchedDecls.isEmpty()) @@ -1501,6 +1697,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex) const String page = pageName(pageIndex); matchPageRules(defaultPrintStyle, isLeft, isFirst, page); matchPageRules(m_userStyle.get(), isLeft, isFirst, page); + // Only consider the global author RuleSet for @page rules, as per the HTML5 spec. matchPageRules(m_authorStyle.get(), isLeft, isFirst, page); m_lineHeightValue = 0; bool inheritedOnly = false; @@ -1742,15 +1939,23 @@ void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parent #endif } -bool CSSStyleSelector::checkRegionStyle(Element* e) +bool CSSStyleSelector::checkRegionStyle(Element* regionElement) { - m_checker.clearHasUnknownPseudoElements(); - m_checker.setPseudoStyle(NOPSEUDO); + // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment, + // so all region rules are global by default. Verify whether that can stand or needs changing. - for (Vector<RefPtr<WebKitCSSRegionRule> >::iterator it = m_regionStyleRules.begin(); it != m_regionStyleRules.end(); ++it) { - const CSSSelectorList& regionSelectorList = (*it)->selectorList(); - for (CSSSelector* s = regionSelectorList.first(); s; s = regionSelectorList.next(s)) { - if (m_checker.checkSelector(s, e)) + unsigned rulesSize = m_authorStyle->m_regionSelectorsAndRuleSets.size(); + for (unsigned i = 0; i < rulesSize; ++i) { + ASSERT(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get()); + if (checkRegionSelector(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement)) + return true; + } + + if (m_userStyle) { + rulesSize = m_userStyle->m_regionSelectorsAndRuleSets.size(); + for (unsigned i = 0; i < rulesSize; ++i) { + ASSERT(m_userStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get()); + if (checkRegionSelector(m_userStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement)) return true; } } @@ -1802,14 +2007,14 @@ PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, // Now we check user sheet rules. if (m_matchAuthorAndUserStyles) - matchRules(m_userStyle.get(), dummy.firstUserRule, dummy.lastUserRule, rulesToInclude & EmptyCSSRules); + matchRules(m_userStyle.get(), dummy.ranges.firstUserRule, dummy.ranges.lastUserRule, rulesToInclude & EmptyCSSRules); } if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) { m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules); // Check the rules in author sheets. - matchRules(m_authorStyle.get(), dummy.firstAuthorRule, dummy.lastAuthorRule, rulesToInclude & EmptyCSSRules); + matchAuthorRules(dummy.ranges.firstAuthorRule, dummy.ranges.lastAuthorRule, rulesToInclude & EmptyCSSRules); m_sameOriginOnly = false; } @@ -1849,6 +2054,21 @@ inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData) return false; return true; } + +bool CSSStyleSelector::checkRegionSelector(CSSSelector* regionSelector, Element* regionElement) +{ + if (!regionSelector || !regionElement) + return false; + + m_checker.clearHasUnknownPseudoElements(); + m_checker.setPseudoStyle(NOPSEUDO); + + for (CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) + if (m_checker.checkSelector(s, regionElement)) + return true; + + return false; +} bool CSSStyleSelector::determineStylesheetSelectorScopes(CSSStyleSheet* stylesheet, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes) { @@ -1953,33 +2173,79 @@ RuleSet::RuleSet() { } -void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, CSSStyleRule* rule, CSSSelector* selector) +static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector) +{ + if (selector->m_match == CSSSelector::Id) + features.idsInRules.add(selector->value().impl()); + if (selector->isAttributeSelector()) + features.attrsInRules.add(selector->attribute().localName().impl()); + switch (selector->pseudoType()) { + case CSSSelector::PseudoFirstLine: + features.usesFirstLineRules = true; + break; + case CSSSelector::PseudoBefore: + case CSSSelector::PseudoAfter: + features.usesBeforeAfterRules = true; + break; + case CSSSelector::PseudoLink: + case CSSSelector::PseudoVisited: + features.usesLinkRules = true; + break; + default: + break; + } +} + +static void collectFeaturesFromRuleData(CSSStyleSelector::Features& features, const RuleData& ruleData) +{ + bool foundSiblingSelector = false; + for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { + collectFeaturesFromSelector(features, selector); + + if (CSSSelectorList* selectorList = selector->selectorList()) { + for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + if (!foundSiblingSelector && selector->isSiblingSelector()) + foundSiblingSelector = true; + collectFeaturesFromSelector(features, subSelector); + } + } else if (!foundSiblingSelector && selector->isSiblingSelector()) + foundSiblingSelector = true; + } + if (foundSiblingSelector) + features.siblingRules.append(CSSStyleSelector::RuleSelectorPair(ruleData.rule(), ruleData.selector())); + if (ruleData.containsUncommonAttributeSelector()) + features.uncommonAttributeRules.append(CSSStyleSelector::RuleSelectorPair(ruleData.rule(), ruleData.selector())); +} + +void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleData& ruleData) { if (!key) return; OwnPtr<Vector<RuleData> >& rules = map.add(key, nullptr).first->second; if (!rules) rules = adoptPtr(new Vector<RuleData>); - rules->append(RuleData(rule, selector, m_ruleCount++)); + rules->append(ruleData); } -void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) +void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* selector) { - if (sel->m_match == CSSSelector::Id) { - addToRuleSet(sel->value().impl(), m_idRules, rule, sel); + RuleData ruleData(rule, selector, m_ruleCount++); + collectFeaturesFromRuleData(m_features, ruleData); + + if (selector->m_match == CSSSelector::Id) { + addToRuleSet(selector->value().impl(), m_idRules, ruleData); return; } - if (sel->m_match == CSSSelector::Class) { - addToRuleSet(sel->value().impl(), m_classRules, rule, sel); + if (selector->m_match == CSSSelector::Class) { + addToRuleSet(selector->value().impl(), m_classRules, ruleData); return; } - if (sel->isUnknownPseudoElement()) { - addToRuleSet(sel->value().impl(), m_shadowPseudoElementRules, rule, sel); + if (selector->isUnknownPseudoElement()) { + addToRuleSet(selector->value().impl(), m_shadowPseudoElementRules, ruleData); return; } - if (SelectorChecker::isCommonPseudoClassSelector(sel)) { - RuleData ruleData(rule, sel, m_ruleCount++); - switch (sel->pseudoType()) { + if (SelectorChecker::isCommonPseudoClassSelector(selector)) { + switch (selector->pseudoType()) { case CSSSelector::PseudoLink: case CSSSelector::PseudoVisited: case CSSSelector::PseudoAnyLink: @@ -1993,13 +2259,12 @@ void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel) } return; } - const AtomicString& localName = sel->tag().localName(); + const AtomicString& localName = selector->tag().localName(); if (localName != starAtom) { - addToRuleSet(localName.impl(), m_tagRules, rule, sel); + addToRuleSet(localName.impl(), m_tagRules, ruleData); return; } - - m_universalRules.append(RuleData(rule, sel, m_ruleCount++)); + m_universalRules.append(ruleData); } void RuleSet::addPageRule(CSSPageRule* rule) @@ -2007,7 +2272,27 @@ void RuleSet::addPageRule(CSSPageRule* rule) m_pageRules.append(RuleData(rule, rule->selectorList().first(), m_pageRules.size())); } -void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector) +void RuleSet::addRegionRule(WebKitCSSRegionRule* rule) +{ + RuleSet* regionRuleSet = new RuleSet; + // The region rule set should take into account the position inside the parent rule set. + // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from + // the stylesheet that contains the region block. + regionRuleSet->m_ruleCount = m_ruleCount; + + // Collect the region rules into a rule set + CSSRuleList* regionStylingRules = rule->cssRules(); + unsigned rulesSize = regionStylingRules->length(); + for (unsigned i = 0; i < rulesSize; ++i) { + CSSRule* regionStylingRule = regionStylingRules->item(i); + if (regionStylingRule->isStyleRule()) + regionRuleSet->addStyleRule(static_cast<CSSStyleRule*>(regionStylingRule)); + } + + m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(rule->selectorList().first(), regionRuleSet)); +} + +void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const Element* scope) { ASSERT(sheet); @@ -2027,7 +2312,7 @@ void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& else if (rule->isImportRule()) { CSSImportRule* import = static_cast<CSSImportRule*>(rule); if (import->styleSheet() && (!import->media() || medium.eval(import->media(), styleSelector))) - addRulesFromSheet(import->styleSheet(), medium, styleSelector); + addRulesFromSheet(import->styleSheet(), medium, styleSelector, scope); } else if (rule->isMediaRule()) { CSSMediaRule* r = static_cast<CSSMediaRule*>(rule); @@ -2043,24 +2328,40 @@ void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& addPageRule(static_cast<CSSPageRule*>(childItem)); else if (childItem->isFontFaceRule() && styleSelector) { // Add this font face to our set. + // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. + if (scope) + continue; const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem); styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); styleSelector->invalidateMatchedDeclarationCache(); } else if (childItem->isKeyframesRule() && styleSelector) { // Add this keyframe rule to our set. + // FIXME(BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment. + if (scope) + continue; styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem)); } } // for rules } // if rules } else if (rule->isFontFaceRule() && styleSelector) { // Add this font face to our set. + // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. + if (scope) + continue; const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule); styleSelector->fontSelector()->addFontFaceRule(fontFaceRule); styleSelector->invalidateMatchedDeclarationCache(); - } else if (rule->isKeyframesRule()) + } else if (rule->isKeyframesRule()) { + // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment. + if (scope) + continue; styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule)); - else if (rule->isRegionRule() && styleSelector) - styleSelector->addRegionRule(static_cast<WebKitCSSRegionRule*>(rule)); + } else if (rule->isRegionRule() && styleSelector) { + // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment. + if (scope) + continue; + addRegionRule(static_cast<WebKitCSSRegionRule*>(rule)); + } } if (m_autoShrinkToFitEnabled) shrinkToFit(); @@ -2072,79 +2373,6 @@ void RuleSet::addStyleRule(CSSStyleRule* rule) addRule(rule, s); } -static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector) -{ - if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty()) - features.idsInRules.add(selector->value().impl()); - if (selector->isAttributeSelector()) - features.attrsInRules.add(selector->attribute().localName().impl()); - switch (selector->pseudoType()) { - case CSSSelector::PseudoFirstLine: - features.usesFirstLineRules = true; - break; - case CSSSelector::PseudoBefore: - case CSSSelector::PseudoAfter: - features.usesBeforeAfterRules = true; - break; - case CSSSelector::PseudoLink: - case CSSSelector::PseudoVisited: - features.usesLinkRules = true; - break; - default: - break; - } -} - -static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules) -{ - unsigned size = rules.size(); - for (unsigned i = 0; i < size; ++i) { - const RuleData& ruleData = rules[i]; - bool foundSiblingSelector = false; - for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { - collectFeaturesFromSelector(features, selector); - - if (CSSSelectorList* selectorList = selector->selectorList()) { - for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { - if (selector->isSiblingSelector()) - foundSiblingSelector = true; - collectFeaturesFromSelector(features, subSelector); - } - } else if (selector->isSiblingSelector()) - foundSiblingSelector = true; - } - if (foundSiblingSelector) { - if (!features.siblingRules) - features.siblingRules = adoptPtr(new RuleSet); - features.siblingRules->addRule(ruleData.rule(), ruleData.selector()); - } - if (ruleData.containsUncommonAttributeSelector()) { - if (!features.uncommonAttributeRules) - features.uncommonAttributeRules = adoptPtr(new RuleSet); - features.uncommonAttributeRules->addRule(ruleData.rule(), ruleData.selector()); - } - } -} - -void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const -{ - AtomRuleMap::const_iterator end = m_idRules.end(); - for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it) - collectFeaturesFromList(features, *it->second); - end = m_classRules.end(); - for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it) - collectFeaturesFromList(features, *it->second); - end = m_tagRules.end(); - for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it) - collectFeaturesFromList(features, *it->second); - end = m_shadowPseudoElementRules.end(); - for (AtomRuleMap::const_iterator it = m_shadowPseudoElementRules.begin(); it != end; ++it) - collectFeaturesFromList(features, *it->second); - collectFeaturesFromList(features, m_linkPseudoClassRules); - collectFeaturesFromList(features, m_focusPseudoClassRules); - collectFeaturesFromList(features, m_universalRules); -} - static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map) { RuleSet::AtomRuleMap::iterator end = map.end(); @@ -2177,20 +2405,17 @@ static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* st if (ok) *ok = false; } else { - int type = primitiveValue->primitiveType(); - - if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) { + if (!style && primitiveValue->isFontRelativeLength()) { if (ok) *ok = false; - } else if (CSSPrimitiveValue::isUnitTypeLength(type)) { + } else if (primitiveValue->isLength()) { if (toFloat) l = Length(primitiveValue->computeLength<double>(style, rootStyle, multiplier), Fixed); else l = primitiveValue->computeLength<Length>(style, rootStyle, multiplier); - } - else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + } else if (primitiveValue->isPercentage()) l = Length(primitiveValue->getDoubleValue(), Percent); - else if (type == CSSPrimitiveValue::CSS_NUMBER) + else if (primitiveValue->isNumber()) l = Length(primitiveValue->getDoubleValue() * 100.0, Percent); else if (ok) *ok = false; @@ -2208,13 +2433,28 @@ static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyl return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok); } +static inline bool isInsideRegionRule(CSSMutableStyleDeclaration* styleDeclaration) +{ + ASSERT(styleDeclaration); + + CSSRule* parentRule = styleDeclaration->parentRule(); + while (parentRule) { + if (parentRule->isRegionRule()) + return true; + parentRule = parentRule->parentRule(); + } + return false; +} + template <bool applyFirst> void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclaration, bool isImportant, bool inheritedOnly) { InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(document(), styleDeclaration->parentRule()); - CSSMutableStyleDeclaration::const_iterator end = styleDeclaration->end(); - for (CSSMutableStyleDeclaration::const_iterator it = styleDeclaration->begin(); it != end; ++it) { - const CSSProperty& current = *it; + bool styleDeclarationInsideRegionRule = m_regionForStyling ? isInsideRegionRule(styleDeclaration) : false; + + unsigned propertyCount = styleDeclaration->propertyCount(); + for (unsigned i = 0; i < propertyCount; ++i) { + const CSSProperty& current = styleDeclaration->propertyAt(i); if (isImportant != current.isImportant()) continue; if (inheritedOnly && !current.isInherited()) { @@ -2225,9 +2465,14 @@ void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclara continue; } int property = current.id(); + + // Filter the properties that can be applied using region styling. + if (styleDeclarationInsideRegionRule && !CSSStyleSelector::isValidRegionStyleProperty(property)) + continue; + if (applyFirst) { COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property); - COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 17, CSS_zoom_is_end_of_first_prop_range); + COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 18, CSS_zoom_is_end_of_first_prop_range); COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom); // give special priority to font-xxx, color properties, etc if (property > CSSPropertyLineHeight) @@ -2275,18 +2520,17 @@ unsigned CSSStyleSelector::computeDeclarationHash(MatchedStyleDeclaration* decla return StringHasher::hashMemory(declarations, sizeof(MatchedStyleDeclaration) * size); } -bool operator==(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b) +bool operator==(const CSSStyleSelector::MatchRanges& a, const CSSStyleSelector::MatchRanges& b) { return a.firstUARule == b.firstUARule && a.lastUARule == b.lastUARule && a.firstAuthorRule == b.firstAuthorRule && a.lastAuthorRule == b.lastAuthorRule && a.firstUserRule == b.firstUserRule - && a.lastUserRule == b.lastUserRule - && a.isCacheable == b.isCacheable; + && a.lastUserRule == b.lastUserRule; } -bool operator!=(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b) +bool operator!=(const CSSStyleSelector::MatchRanges& a, const CSSStyleSelector::MatchRanges& b) { return !(a == b); } @@ -2309,8 +2553,7 @@ const CSSStyleSelector::MatchedStyleDeclarationCacheItem* CSSStyleSelector::find if (it == m_matchedStyleDeclarationCache.end()) return 0; MatchedStyleDeclarationCacheItem& cacheItem = it->second; - ASSERT(cacheItem.matchResult.isCacheable); - + size_t size = m_matchedDecls.size(); if (size != cacheItem.matchedStyleDeclarations.size()) return 0; @@ -2318,7 +2561,7 @@ const CSSStyleSelector::MatchedStyleDeclarationCacheItem* CSSStyleSelector::find if (m_matchedDecls[i] != cacheItem.matchedStyleDeclarations[i]) return 0; } - if (cacheItem.matchResult != matchResult) + if (cacheItem.ranges != matchResult.ranges) return 0; return &cacheItem; } @@ -2334,7 +2577,7 @@ void CSSStyleSelector::addToMatchedDeclarationCache(const RenderStyle* style, co ASSERT(hash); MatchedStyleDeclarationCacheItem cacheItem; cacheItem.matchedStyleDeclarations.append(m_matchedDecls); - cacheItem.matchResult = matchResult; + cacheItem.ranges = matchResult.ranges; // Note that we don't cache the original RenderStyle instance. It may be further modified. // The RenderStyle in the cache is really just a holder for the substructures and never used as-is. cacheItem.renderStyle = RenderStyle::clone(style); @@ -2388,9 +2631,9 @@ void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult) // and (4) normal important. m_lineHeightValue = 0; applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, applyInheritedOnly); - applyDeclarations<true>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly); - applyDeclarations<true>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly); - applyDeclarations<true>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly); + applyDeclarations<true>(true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); + applyDeclarations<true>(true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); + applyDeclarations<true>(true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); if (cacheItem && cacheItem->renderStyle->effectiveZoom() != m_style->effectiveZoom()) { m_fontDirty = true; @@ -2409,16 +2652,16 @@ void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult) applyInheritedOnly = false; // Now do the normal priority UA properties. - applyDeclarations<false>(false, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly); + applyDeclarations<false>(false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); // Cache our border and background so that we can examine them later. cacheBorderAndBackground(); // Now do the author and user normal priority properties and all the !important properties. - applyDeclarations<false>(false, matchResult.lastUARule + 1, m_matchedDecls.size() - 1, applyInheritedOnly); - applyDeclarations<false>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly); - applyDeclarations<false>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly); - applyDeclarations<false>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly); + applyDeclarations<false>(false, matchResult.ranges.lastUARule + 1, m_matchedDecls.size() - 1, applyInheritedOnly); + applyDeclarations<false>(true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); + applyDeclarations<false>(true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); + applyDeclarations<false>(true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); loadPendingImages(); @@ -2476,7 +2719,7 @@ void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool // If the rule has no properties to apply, then ignore it. CSSMutableStyleDeclaration* decl = rule->declaration(); - if (!decl || !decl->length()) + if (!decl || decl->isEmpty()) continue; // Add this rule to our list of matched rules. @@ -2553,6 +2796,20 @@ inline bool isValidVisitedLinkProperty(int id) return false; } +// http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule +// FIXME: add incremental support for other region styling properties. +inline bool CSSStyleSelector::isValidRegionStyleProperty(int id) +{ + switch (static_cast<CSSPropertyID>(id)) { + case CSSPropertyBackgroundColor: + return true; + default: + break; + } + + return false; +} + // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. @@ -2575,14 +2832,13 @@ static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, CSSStyleSe return true; } - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) { + if (primitiveValue->isLength()) { length = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()); length.setQuirk(primitiveValue->isQuirkValue()); return true; } - if (type == CSSPrimitiveValue::CSS_PERCENTAGE) { + if (primitiveValue->isPercentage()) { length = Length(primitiveValue->getDoubleValue(), Percent); return true; } @@ -2723,46 +2979,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyOrphans: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(orphans, Orphans) return; -// rect - case CSSPropertyClip: - { - Length top; - Length right; - Length bottom; - Length left; - bool hasClip = true; - if (isInherit) { - if (m_parentStyle->hasClip()) { - top = m_parentStyle->clipTop(); - right = m_parentStyle->clipRight(); - bottom = m_parentStyle->clipBottom(); - left = m_parentStyle->clipLeft(); - } else { - hasClip = false; - top = right = bottom = left = Length(); - } - } else if (isInitial) { - hasClip = false; - top = right = bottom = left = Length(); - } else if (!primitiveValue) { - return; - } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) { - Rect* rect = primitiveValue->getRectValue(); - if (!rect) - return; - top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor); - right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor); - bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor); - left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor); - } else if (primitiveValue->getIdent() != CSSValueAuto) { - return; - } - m_style->setClip(top, right, bottom, left); - m_style->setHasClip(hasClip); - - // rect, ident - return; - } // lists case CSSPropertyContent: @@ -2791,12 +3007,11 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) continue; CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item); - switch (contentValue->primitiveType()) { - case CSSPrimitiveValue::CSS_STRING: + + if (contentValue->isString()) { m_style->setContent(contentValue->getStringValue().impl(), didSet); didSet = true; - break; - case CSSPrimitiveValue::CSS_ATTR: { + } else if (contentValue->isAttr()) { // FIXME: Can a namespace be specified for an attr(foo)? if (m_style->styleType() == NOPSEUDO) m_style->setUnique(); @@ -2808,16 +3023,12 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) didSet = true; // register the fact that the attribute value affects the style m_features.attrsInRules.add(attr.localName().impl()); - break; - } - case CSSPrimitiveValue::CSS_URI: { + } else if (contentValue->isURI()) { if (!contentValue->isImageValue()) break; m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet); didSet = true; - break; - } - case CSSPrimitiveValue::CSS_COUNTER: { + } else if (contentValue->isCounter()) { Counter* counterValue = contentValue->getCounterValue(); EListStyleType listStyleType = NoneListStyle; int listStyleIdent = counterValue->listStyleIdent(); @@ -2826,9 +3037,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator())); m_style->setContent(counter.release(), didSet); didSet = true; - break; - } - case CSSPrimitiveValue::CSS_IDENT: + } else { switch (contentValue->getIdent()) { case CSSValueOpenQuote: m_style->setContent(OPEN_QUOTE, didSet); @@ -2876,12 +3085,12 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) CSSValue* item = i.value(); ASSERT(item->isPrimitiveValue()); primitiveValue = static_cast<CSSPrimitiveValue*>(item); - ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING); + ASSERT(primitiveValue->isString()); quotes[i.index()] = primitiveValue->getStringValue(); } m_style->setQuotes(adoptRef(data)); } else if (primitiveValue) { - ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT); + ASSERT(primitiveValue->isIdent()); if (primitiveValue->getIdent() == CSSValueNone) m_style->setQuotes(adoptRef(QuotesData::create(0))); } @@ -2927,10 +3136,10 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item); AtomicString face; Settings* settings = m_checker.document()->settings(); - if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) { + if (contentValue->isString()) { if (contentValue->isFontFamilyValue()) face = static_cast<FontFamilyValue*>(contentValue)->familyName(); - } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) { + } else if (settings) { switch (contentValue->getIdent()) { case CSSValueWebkitBody: face = settings->standardFontFamily(); @@ -3128,8 +3337,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) RefPtr<StyleReflection> reflection = StyleReflection::create(); reflection->setDirection(reflectValue->direction()); if (reflectValue->offset()) { - int type = reflectValue->offset()->primitiveType(); - if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + if (reflectValue->offset()->isPercentage()) reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent)); else reflection->setOffset(reflectValue->offset()->computeLength<Length>(style(), m_rootElementStyle, zoomFactor)); @@ -3144,7 +3352,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) } case CSSPropertyOpacity: HANDLE_INHERIT_AND_INITIAL(opacity, Opacity) - if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + if (!primitiveValue || !primitiveValue->isNumber()) return; // Error case. // Clamp opacity to the range 0-1 m_style->setOpacity(clampTo<float>(primitiveValue->getDoubleValue(), 0, 1)); @@ -3231,7 +3439,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; if (primitiveValue->getIdent() == CSSValueInfinite) m_style->setMarqueeLoopCount(-1); // -1 means repeat forever. - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + else if (primitiveValue->isNumber()) m_style->setMarqueeLoopCount(primitiveValue->getIntValue()); return; } @@ -3239,8 +3447,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed) if (!primitiveValue) return; - if (primitiveValue->getIdent()) { - switch (primitiveValue->getIdent()) { + if (int ident = primitiveValue->getIdent()) { + switch (ident) { case CSSValueSlow: m_style->setMarqueeSpeed(500); // 500 msec. break; @@ -3251,12 +3459,9 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) m_style->setMarqueeSpeed(10); // 10msec. Super fast. break; } - } - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) - m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue()); - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) - m_style->setMarqueeSpeed(primitiveValue->getIntValue()); - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. + } else if (primitiveValue->isTime()) + m_style->setMarqueeSpeed(primitiveValue->computeTime<int, CSSPrimitiveValue::Milliseconds>()); + else if (primitiveValue->isNumber()) // For scrollamount support. m_style->setMarqueeSpeed(primitiveValue->getIntValue()); return; } @@ -3276,8 +3481,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px. break; } - } - else { + } else { bool ok = true; Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok); if (ok) @@ -3314,10 +3518,9 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp) if (!primitiveValue) return; - int type = primitiveValue->primitiveType(); - if (type == CSSPrimitiveValue::CSS_NUMBER) + if (primitiveValue->isNumber()) m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount)); - else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (primitiveValue->isPercentage()) m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage)); return; } @@ -3428,10 +3631,9 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) } float perspectiveValue; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) + if (primitiveValue->isLength()) perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor); - else if (type == CSSPrimitiveValue::CSS_NUMBER) { + else if (primitiveValue->isNumber()) { // For backward compatibility, treat valueless numbers as px. perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor); } else @@ -3584,7 +3786,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; if (primitiveValue->getIdent() == CSSValueAuto) m_style->setWrapShapeInside(0); - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_SHAPE) + else if (primitiveValue->isShape()) m_style->setWrapShapeInside(primitiveValue->getShapeValue()); return; @@ -3594,7 +3796,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; if (primitiveValue->getIdent() == CSSValueAuto) m_style->setWrapShapeOutside(0); - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_SHAPE) + else if (primitiveValue->isShape()) m_style->setWrapShapeOutside(primitiveValue->getShapeValue()); return; @@ -3628,8 +3830,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyWebkitFilter: { HANDLE_INHERIT_AND_INITIAL(filter, Filter); FilterOperations operations; - createFilterOperations(value, style(), m_rootElementStyle, operations); - m_style->setFilter(operations); + if (createFilterOperations(value, style(), m_rootElementStyle, operations)) + m_style->setFilter(operations); return; } #endif @@ -3713,12 +3915,14 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyBorderSpacing: case CSSPropertyWebkitBorderHorizontalSpacing: case CSSPropertyWebkitBorderVerticalSpacing: + case CSSPropertyClip: case CSSPropertyCounterIncrement: case CSSPropertyCounterReset: case CSSPropertyLetterSpacing: case CSSPropertyWordSpacing: case CSSPropertyWebkitFlexOrder: case CSSPropertyWebkitFlexPack: + case CSSPropertyWebkitFlexAlign: case CSSPropertyWebkitFlexItemAlign: case CSSPropertyWebkitFlexDirection: case CSSPropertyWebkitFlexFlow: @@ -3812,6 +4016,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyWebkitColumnWidth: case CSSPropertyWebkitFlowInto: case CSSPropertyWebkitFlowFrom: + case CSSPropertyWebkitFontKerning: + case CSSPropertyWebkitFontVariantLigatures: case CSSPropertyWebkitHighlight: case CSSPropertyWebkitHyphenateCharacter: case CSSPropertyWebkitHyphenateLimitAfter: @@ -4002,25 +4208,23 @@ void CSSStyleSelector::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* va CSSPrimitiveValue* second = pair ? static_cast<CSSPrimitiveValue*>(pair->second()) : 0; Length firstLength, secondLength; - int firstType = first->primitiveType(); - int secondType = second ? second->primitiveType() : 0; float zoomFactor = m_style->effectiveZoom(); if (first->getIdent() == CSSValueAuto) firstLength = Length(); - else if (CSSPrimitiveValue::isUnitTypeLength(firstType)) + else if (first->isLength()) firstLength = first->computeLength<Length>(style(), m_rootElementStyle, zoomFactor); - else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (first->isPercentage()) firstLength = Length(first->getDoubleValue(), Percent); else return; if (!second || second->getIdent() == CSSValueAuto) secondLength = Length(); - else if (CSSPrimitiveValue::isUnitTypeLength(secondType)) + else if (second->isLength()) secondLength = second->computeLength<Length>(style(), m_rootElementStyle, zoomFactor); - else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (second->isPercentage()) secondLength = Length(second->getDoubleValue(), Percent); else return; @@ -4044,10 +4248,9 @@ void CSSStyleSelector::mapFillXPosition(CSSPropertyID, FillLayer* layer, CSSValu CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); Length l; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) + if (primitiveValue->isLength()) l = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, zoomFactor); - else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (primitiveValue->isPercentage()) l = Length(primitiveValue->getDoubleValue(), Percent); else return; @@ -4068,10 +4271,9 @@ void CSSStyleSelector::mapFillYPosition(CSSPropertyID, FillLayer* layer, CSSValu CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); Length l; - int type = primitiveValue->primitiveType(); - if (CSSPrimitiveValue::isUnitTypeLength(type)) + if (primitiveValue->isLength()) l = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, zoomFactor); - else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (primitiveValue->isPercentage()) l = Length(primitiveValue->getDoubleValue(), Percent); else return; @@ -4089,10 +4291,7 @@ void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value) return; CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) - animation->setDelay(primitiveValue->getFloatValue()); - else - animation->setDelay(primitiveValue->getFloatValue()/1000.0f); + animation->setDelay(primitiveValue->computeTime<float, CSSPrimitiveValue::Seconds>()); } void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value) @@ -4120,10 +4319,7 @@ void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* valu return; CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) - animation->setDuration(primitiveValue->getFloatValue()); - else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) - animation->setDuration(primitiveValue->getFloatValue()/1000.0f); + animation->setDuration(primitiveValue->computeTime<float, CSSPrimitiveValue::Seconds>()); } void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value) @@ -4271,35 +4467,47 @@ void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue void CSSStyleSelector::mapNinePieceImage(CSSPropertyID property, CSSValue* value, NinePieceImage& image) { - // If we're a primitive value, then we are "none" and don't need to alter the empty image at all. - if (!value || value->isPrimitiveValue() || !value->isBorderImageValue()) + // If we're not a value list, then we are "none" and don't need to alter the empty image at all. + if (!value || !value->isValueList()) return; // Retrieve the border image value. - CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value); + CSSValueList* borderImage = static_cast<CSSValueList*>(value); // Set the image (this kicks off the load). CSSPropertyID imageProperty; - if (property == CSSPropertyWebkitBorderImage || property == CSSPropertyBorderImage) + if (property == CSSPropertyWebkitBorderImage) imageProperty = CSSPropertyBorderImageSource; else if (property == CSSPropertyWebkitMaskBoxImage) imageProperty = CSSPropertyWebkitMaskBoxImageSource; else imageProperty = property; - if (CSSValue* imageValue = borderImage->imageValue()) - image.setImage(styleImage(imageProperty, imageValue)); - - // Map in the image slices. - mapNinePieceImageSlice(borderImage->m_imageSlice.get(), image); - - // Map in the border slices. - if (borderImage->m_borderSlice) - image.setBorderSlices(mapNinePieceImageQuad(borderImage->m_borderSlice.get())); - - // Map in the outset. - if (borderImage->m_outset) - image.setOutset(mapNinePieceImageQuad(borderImage->m_outset.get())); + for (unsigned i = 0 ; i < borderImage->length() ; ++i) { + CSSValue* current = borderImage->item(i); + + if (current->isImageValue() || current->isImageGeneratorValue()) + image.setImage(styleImage(imageProperty, current)); + else if (current->isBorderImageSliceValue()) + mapNinePieceImageSlice(current, image); + else if (current->isValueList()) { + CSSValueList* slashList = static_cast<CSSValueList*>(current); + // Map in the image slices. + if (slashList->item(0) && slashList->item(0)->isBorderImageSliceValue()) + mapNinePieceImageSlice(slashList->item(0), image); + + // Map in the border slices. + if (slashList->item(1)) + image.setBorderSlices(mapNinePieceImageQuad(slashList->item(1))); + + // Map in the outset. + if (slashList->item(2)) + image.setOutset(mapNinePieceImageQuad(slashList->item(2))); + } else if (current->isPrimitiveValue()) { + // Set the appropriate rules for stretch/round/repeat of the slices. + mapNinePieceImageRepeat(current, image); + } + } if (property == CSSPropertyWebkitBorderImage) { // We have to preserve the legacy behavior of -webkit-border-image and make the border slices @@ -4314,9 +4522,6 @@ void CSSStyleSelector::mapNinePieceImage(CSSPropertyID property, CSSValue* value if (image.borderSlices().left().isFixed()) style()->setBorderLeftWidth(image.borderSlices().left().value()); } - - // Set the appropriate rules for stretch/round/repeat of the slices - mapNinePieceImageRepeat(borderImage->m_repeat.get(), image); } void CSSStyleSelector::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& image) @@ -4330,19 +4535,19 @@ void CSSStyleSelector::mapNinePieceImageSlice(CSSValue* value, NinePieceImage& i // Set up a length box to represent our image slices. LengthBox box; Quad* slices = borderImageSlice->slices(); - if (slices->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (slices->top()->isPercentage()) box.m_top = Length(slices->top()->getDoubleValue(), Percent); else box.m_top = Length(slices->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); - if (slices->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (slices->bottom()->isPercentage()) box.m_bottom = Length(slices->bottom()->getDoubleValue(), Percent); else box.m_bottom = Length((int)slices->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); - if (slices->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (slices->left()->isPercentage()) box.m_left = Length(slices->left()->getDoubleValue(), Percent); else box.m_left = Length(slices->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); - if (slices->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (slices->right()->isPercentage()) box.m_right = Length(slices->right()->getDoubleValue(), Percent); else box.m_right = Length(slices->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); @@ -4366,30 +4571,30 @@ LengthBox CSSStyleSelector::mapNinePieceImageQuad(CSSValue* value) // Set up a length box to represent our image slices. LengthBox box; // Defaults to 'auto' so we don't have to handle that explicitly below. Quad* slices = borderWidths->getQuadValue(); - if (slices->top()->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + if (slices->top()->isNumber()) box.m_top = Length(slices->top()->getIntValue(), Relative); - else if (slices->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (slices->top()->isPercentage()) box.m_top = Length(slices->top()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else if (slices->top()->getIdent() != CSSValueAuto) box.m_top = slices->top()->computeLength<Length>(style(), rootElementStyle(), zoom); - if (slices->right()->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + if (slices->right()->isNumber()) box.m_right = Length(slices->right()->getIntValue(), Relative); - else if (slices->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (slices->right()->isPercentage()) box.m_right = Length(slices->right()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else if (slices->right()->getIdent() != CSSValueAuto) box.m_right = slices->right()->computeLength<Length>(style(), rootElementStyle(), zoom); - if (slices->bottom()->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + if (slices->bottom()->isNumber()) box.m_bottom = Length(slices->bottom()->getIntValue(), Relative); - else if (slices->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (slices->bottom()->isPercentage()) box.m_bottom = Length(slices->bottom()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else if (slices->bottom()->getIdent() != CSSValueAuto) box.m_bottom = slices->bottom()->computeLength<Length>(style(), rootElementStyle(), zoom); - if (slices->left()->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + if (slices->left()->isNumber()) box.m_left = Length(slices->left()->getIntValue(), Relative); - else if (slices->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + else if (slices->left()->isPercentage()) box.m_left = Length(slices->left()->getDoubleValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else if (slices->left()->getIdent() != CSSValueAuto) box.m_left = slices->left()->computeLength<Length>(style(), rootElementStyle(), zoom); @@ -4693,15 +4898,13 @@ static Color colorForCSSValue(int cssValueId) Color CSSStyleSelector::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forVisitedLink) const { - if (value->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) + if (value->isRGBColor()) return Color(value->getRGBA32Value()); - if (value->primitiveType() != CSSPrimitiveValue::CSS_IDENT) - return Color(); - int ident = value->getIdent(); - switch (ident) { + case 0: + return Color(); case CSSValueWebkitText: return m_element->document()->textColor(); case CSSValueWebkitLink: @@ -4898,14 +5101,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* break; } case WebKitCSSTransformValue::RotateTransformOperation: { - double angle = firstValue->getDoubleValue(); - if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) - angle = rad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) - angle = grad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) - angle = turn2deg(angle); - + double angle = firstValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType()))); break; } @@ -4915,11 +5111,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* double x = 0; double y = 0; double z = 0; - double angle = firstValue->getDoubleValue(); - if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) - angle = rad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) - angle = grad2deg(angle); + double angle = firstValue->computeDegrees(); if (transformValue->operationType() == WebKitCSSTransformValue::RotateXTransformOperation) x = 1; @@ -4939,11 +5131,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* double x = firstValue->getDoubleValue(); double y = secondValue->getDoubleValue(); double z = thirdValue->getDoubleValue(); - double angle = fourthValue->getDoubleValue(); - if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) - angle = rad2deg(angle); - else if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) - angle = grad2deg(angle); + double angle = fourthValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } @@ -4952,13 +5140,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* case WebKitCSSTransformValue::SkewYTransformOperation: { double angleX = 0; double angleY = 0; - double angle = firstValue->getDoubleValue(); - if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) - angle = rad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) - angle = grad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) - angle = turn2deg(angle); + double angle = firstValue->computeDegrees(); if (transformValue->operationType() == WebKitCSSTransformValue::SkewYTransformOperation) angleY = angle; else { @@ -4966,13 +5148,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* if (transformValue->operationType() == WebKitCSSTransformValue::SkewTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); - angleY = secondValue->getDoubleValue(); - if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) - angleY = rad2deg(angleY); - else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) - angleY = grad2deg(angleY); - else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) - angleY = turn2deg(angleY); + angleY = secondValue->computeDegrees(); } } } @@ -5016,7 +5192,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* case WebKitCSSTransformValue::PerspectiveTransformOperation: { bool ok = true; Length p = Length(0, Fixed); - if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType())) + if (firstValue->isLength()) p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); else { // This is a quirk that should go away when 3d transforms are finalized. @@ -5105,19 +5281,103 @@ void CSSStyleSelector::loadPendingShaders() RefPtr<FilterOperation> filterOperation = filterOperations.at(i); if (filterOperation->getOperationType() == FilterOperation::CUSTOM) { CustomFilterOperation* customFilter = static_cast<CustomFilterOperation*>(filterOperation.get()); - if (customFilter->vertexShader() && customFilter->vertexShader()->isPendingShader()) { - WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(customFilter->vertexShader())->cssShaderValue(); - customFilter->setVertexShader(shaderValue->cachedShader(cachedResourceLoader)); + ASSERT(customFilter->program()); + StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customFilter->program()); + if (program->vertexShader() && program->vertexShader()->isPendingShader()) { + WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->vertexShader())->cssShaderValue(); + program->setVertexShader(shaderValue->cachedShader(cachedResourceLoader)); } - if (customFilter->fragmentShader() && customFilter->fragmentShader()->isPendingShader()) { - WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(customFilter->fragmentShader())->cssShaderValue(); - customFilter->setFragmentShader(shaderValue->cachedShader(cachedResourceLoader)); + if (program->fragmentShader() && program->fragmentShader()->isPendingShader()) { + WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->fragmentShader())->cssShaderValue(); + program->setFragmentShader(shaderValue->cachedShader(cachedResourceLoader)); } } } m_hasPendingShaders = false; } +static bool sortParametersByNameComparator(const RefPtr<CustomFilterParameter>& a, const RefPtr<CustomFilterParameter>& b) +{ + return codePointCompareLessThan(a->name(), b->name()); +} + +PassRefPtr<CustomFilterParameter> CSSStyleSelector::parseCustomFilterNumberParamter(const String& name, CSSValueList* values) +{ + RefPtr<CustomFilterNumberParameter> numberParameter = CustomFilterNumberParameter::create(name); + for (unsigned i = 0; i < values->length(); ++i) { + CSSValue* value = values->itemWithoutBoundsCheck(i); + if (!value->isPrimitiveValue()) + return 0; + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) + return 0; + numberParameter->addValue(primitiveValue->getDoubleValue()); + } + return numberParameter.release(); +} + +bool CSSStyleSelector::parseCustomFilterParameterList(CSSValue* parametersValue, CustomFilterParameterList& parameterList) +{ + HashSet<String> knownParameterNames; + CSSValueListIterator parameterIterator(parametersValue); + for (; parameterIterator.hasMore(); parameterIterator.advance()) { + if (!parameterIterator.value()->isValueList()) + return false; + CSSValueListIterator iterator(parameterIterator.value()); + if (!iterator.isPrimitiveValue()) + return false; + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value()); + if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_STRING) + return false; + + String name = primitiveValue->getStringValue(); + // Do not allow duplicate parameter names. + if (knownParameterNames.contains(name)) + return false; + knownParameterNames.add(name); + + iterator.advance(); + + if (!iterator.hasMore()) + return false; + + // FIXME: Implement other parameters types parsing. + // booleans: https://bugs.webkit.org/show_bug.cgi?id=76438 + // textures: https://bugs.webkit.org/show_bug.cgi?id=71442 + // 3d-transforms: https://bugs.webkit.org/show_bug.cgi?id=71443 + // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444 + RefPtr<CustomFilterParameter> parameter; + if (iterator.value()->isValueList()) { + CSSValueList* values = static_cast<CSSValueList*>(iterator.value()); + iterator.advance(); + + // We can have only arrays of booleans or numbers, so use the first value to choose between those two. + // Make sure we have at least one value. We need up to 4 values (all booleans or all numbers). + if (!values->length() || values->length() > 4) + return false; + + if (!values->itemWithoutBoundsCheck(0)->isPrimitiveValue()) + return false; + + CSSPrimitiveValue* firstPrimitiveValue = static_cast<CSSPrimitiveValue*>(values->itemWithoutBoundsCheck(0)); + if (firstPrimitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) + parameter = parseCustomFilterNumberParamter(name, values); + // FIXME: Implement the boolean array parameter here. + // https://bugs.webkit.org/show_bug.cgi?id=76438 + } + + if (!parameter) + return false; + + parameterList.append(parameter.release()); + } + + // Make sure we sort the parameters before passing them down to the CustomFilterOperation. + std::sort(parameterList.begin(), parameterList.end(), sortParametersByNameComparator); + + return true; +} + PassRefPtr<CustomFilterOperation> CSSStyleSelector::createCustomFilterOperation(WebKitCSSFilterValue* filterValue) { ASSERT(filterValue->length()); @@ -5135,6 +5395,8 @@ PassRefPtr<CustomFilterOperation> CSSStyleSelector::createCustomFilterOperation( CustomFilterOperation::MeshBoxType meshBoxType = CustomFilterOperation::FILTER_BOX; CustomFilterOperation::MeshType meshType = CustomFilterOperation::ATTACHED; + CSSValue* parametersValue = 0; + if (filterValue->length() > 1) { CSSValueListIterator iterator(filterValue->itemWithoutBoundsCheck(1)); @@ -5144,7 +5406,7 @@ PassRefPtr<CustomFilterOperation> CSSStyleSelector::createCustomFilterOperation( if (iterator.hasMore() && iterator.isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value()); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + if (primitiveValue->isNumber()) { // If only one integer value is specified, it will set both // the rows and the columns. meshRows = meshColumns = primitiveValue->getIntValue(); @@ -5153,7 +5415,7 @@ PassRefPtr<CustomFilterOperation> CSSStyleSelector::createCustomFilterOperation( // Try to match another number for the columns. if (iterator.hasMore() && iterator.isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value()); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + if (primitiveValue->isNumber()) { meshColumns = primitiveValue->getIntValue(); iterator.advance(); } @@ -5179,9 +5441,24 @@ PassRefPtr<CustomFilterOperation> CSSStyleSelector::createCustomFilterOperation( iterator.advance(); } } + + if (!iterator.index()) { + // If no value was consumed from the mesh value, then it is just a parameter list, meaning that we end up + // having just two CSSListValues: list of shaders and list of parameters. + ASSERT(filterValue->length() == 2); + parametersValue = filterValue->itemWithoutBoundsCheck(1); + } } - return CustomFilterOperation::create(vertexShader, fragmentShader, meshRows, meshColumns, meshBoxType, meshType); + if (filterValue->length() > 2 && !parametersValue) + parametersValue = filterValue->itemWithoutBoundsCheck(2); + + CustomFilterParameterList parameterList; + if (parametersValue && !parseCustomFilterParameterList(parametersValue, parameterList)) + return 0; + + RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShader.release(), fragmentShader.release()); + return CustomFilterOperation::create(program.release(), parameterList, meshRows, meshColumns, meshBoxType, meshType); } #endif @@ -5205,8 +5482,10 @@ bool CSSStyleSelector::createFilterOperations(CSSValue* inValue, RenderStyle* st #if ENABLE(CSS_SHADERS) if (operationType == FilterOperation::CUSTOM) { RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue); - if (operation) - operations.operations().append(operation); + if (!operation) + return false; + + operations.operations().append(operation); continue; } #endif @@ -5238,7 +5517,7 @@ bool CSSStyleSelector::createFilterOperations(CSSValue* inValue, RenderStyle* st double amount = 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); - if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) + if (firstValue->isPercentage()) amount /= 100; } @@ -5247,15 +5526,8 @@ bool CSSStyleSelector::createFilterOperations(CSSValue* inValue, RenderStyle* st } case WebKitCSSFilterValue::HueRotateFilterOperation: { double angle = 0; - if (filterValue->length() == 1) { - angle = firstValue->getDoubleValue(); - if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD) - angle = rad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD) - angle = grad2deg(angle); - else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN) - angle = turn2deg(angle); - } + if (filterValue->length() == 1) + angle = firstValue->computeDegrees(); operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType)); break; @@ -5264,7 +5536,7 @@ bool CSSStyleSelector::createFilterOperations(CSSValue* inValue, RenderStyle* st case WebKitCSSFilterValue::BrightnessFilterOperation: case WebKitCSSFilterValue::ContrastFilterOperation: case WebKitCSSFilterValue::OpacityFilterOperation: { - double amount = 1; + double amount = (filterValue->operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) diff --git a/Source/WebCore/css/CSSStyleSelector.h b/Source/WebCore/css/CSSStyleSelector.h index 856193f99..633f703a7 100644 --- a/Source/WebCore/css/CSSStyleSelector.h +++ b/Source/WebCore/css/CSSStyleSelector.h @@ -54,6 +54,7 @@ class CSSStyleSheet; class CSSValue; class ContainerNode; class CustomFilterOperation; +class CustomFilterParameter; class Document; class Element; class Frame; @@ -63,6 +64,7 @@ class KeyframeList; class KeyframeValue; class MediaQueryEvaluator; class Node; +class RenderRegion; class RuleData; class RuleSet; class Settings; @@ -78,6 +80,10 @@ class WebKitCSSFilterValue; class WebKitCSSRegionRule; class WebKitCSSShaderValue; +#if ENABLE(CSS_SHADERS) +typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterList; +#endif + class MediaQueryResult { WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED; public: @@ -100,11 +106,15 @@ public: bool strictParsing, bool matchAuthorAndUserStyles); ~CSSStyleSelector(); +#if ENABLE(STYLE_SCOPED) + static Element* determineScopingElement(const CSSStyleSheet*); +#endif + // Using these during tree walk will allow style selector to optimize child and descendant selector lookups. - void pushParent(Element* parent) { m_checker.pushParent(parent); } - void popParent(Element* parent) { m_checker.popParent(parent); } + void pushParent(Element* parent); + void popParent(Element* parent); - PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false); + PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, RenderRegion* regionForStyling = 0); void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList&); @@ -197,12 +207,10 @@ public: void visitedStateChanged(LinkHash visitedHash) { m_checker.visitedStateChanged(visitedHash); } void addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule>); - void addPageStyle(PassRefPtr<CSSPageRule>); - void addRegionRule(PassRefPtr<WebKitCSSRegionRule>); - bool checkRegionStyle(Element*); + bool checkRegionStyle(Element* regionElement); - bool usesSiblingRules() const { return m_features.siblingRules; } + bool usesSiblingRules() const { return !m_features.siblingRules.isEmpty(); } bool usesFirstLineRules() const { return m_features.usesFirstLineRules; } bool usesBeforeAfterRules() const { return m_features.usesBeforeAfterRules; } bool usesLinkRules() const { return m_features.usesLinkRules; } @@ -216,19 +224,27 @@ public: #if ENABLE(CSS_SHADERS) StyleShader* styleShader(CSSValue*); StyleShader* cachedOrPendingStyleShaderFromValue(WebKitCSSShaderValue*); + bool parseCustomFilterParameterList(CSSValue*, CustomFilterParameterList&); + PassRefPtr<CustomFilterParameter> parseCustomFilterNumberParamter(const String& name, CSSValueList*); PassRefPtr<CustomFilterOperation> createCustomFilterOperation(WebKitCSSFilterValue*); void loadPendingShaders(); #endif #endif // ENABLE(CSS_FILTERS) + struct RuleSelectorPair { + RuleSelectorPair(CSSStyleRule* rule, CSSSelector* selector) : rule(rule), selector(selector) { } + CSSStyleRule* rule; + CSSSelector* selector; + }; struct Features { Features(); ~Features(); + void add(const CSSStyleSelector::Features&); void clear(); HashSet<AtomicStringImpl*> idsInRules; HashSet<AtomicStringImpl*> attrsInRules; - OwnPtr<RuleSet> siblingRules; - OwnPtr<RuleSet> uncommonAttributeRules; + Vector<RuleSelectorPair> siblingRules; + Vector<RuleSelectorPair> uncommonAttributeRules; bool usesFirstLineRules; bool usesBeforeAfterRules; bool usesLinkRules; @@ -245,31 +261,43 @@ private: void addMatchedRule(const RuleData* rule) { m_matchedRules.append(rule); } void addMatchedDeclaration(CSSMutableStyleDeclaration*, unsigned linkMatchType = SelectorChecker::MatchAll); - struct MatchResult { - MatchResult() : firstUARule(-1), lastUARule(-1), firstAuthorRule(-1), lastAuthorRule(-1), firstUserRule(-1), lastUserRule(-1), isCacheable(true) { } + struct MatchRanges { + MatchRanges() : firstUARule(-1), lastUARule(-1), firstAuthorRule(-1), lastAuthorRule(-1), firstUserRule(-1), lastUserRule(-1) { } int firstUARule; int lastUARule; int firstAuthorRule; int lastAuthorRule; int firstUserRule; int lastUserRule; + }; + + struct MatchResult { + MatchResult() : isCacheable(true) { } + MatchRanges ranges; bool isCacheable; }; void matchAllRules(MatchResult&); void matchUARules(MatchResult&); void matchRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); - void matchRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); + void matchAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); + void matchScopedAuthorRules(int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); + void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); + void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); + void collectMatchingRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); bool fastRejectSelector(const RuleData&) const; void sortMatchedRules(); + void sortAndTransferMatchedRules(); bool checkSelector(const RuleData&); - + bool checkRegionSelector(CSSSelector* regionSelector, Element* regionElement); void applyMatchedDeclarations(const MatchResult&); template <bool firstPass> void applyDeclarations(bool important, int startIndex, int endIndex, bool inheritedOnly); template <bool firstPass> void applyDeclaration(CSSMutableStyleDeclaration*, bool isImportant, bool inheritedOnly); + static bool isValidRegionStyleProperty(int id); + void matchPageRules(RuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName); void matchPageRulesForList(const Vector<RuleData>*, bool isLeftPage, bool isFirstPage, const String& pageName); bool isLeftPage(int pageIndex) const; @@ -281,6 +309,8 @@ private: OwnPtr<RuleSet> m_userStyle; Features m_features; + OwnPtr<RuleSet> m_siblingRuleSet; + OwnPtr<RuleSet> m_uncommonAttributeRuleSet; bool m_hasUAAppearance; BorderData m_borderData; @@ -290,9 +320,6 @@ private: typedef HashMap<AtomicStringImpl*, RefPtr<WebKitCSSKeyframesRule> > KeyframesRuleMap; KeyframesRuleMap m_keyframesRuleMap; - typedef Vector<RefPtr<WebKitCSSRegionRule> > RegionStyleRules; - RegionStyleRules m_regionStyleRules; - public: static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; } @@ -358,7 +385,7 @@ private: static unsigned computeDeclarationHash(MatchedStyleDeclaration*, unsigned size); struct MatchedStyleDeclarationCacheItem { Vector<MatchedStyleDeclaration> matchedStyleDeclarations; - MatchResult matchResult; + MatchRanges ranges; RefPtr<RenderStyle> renderStyle; RefPtr<RenderStyle> parentRenderStyle; }; @@ -399,6 +426,7 @@ private: RenderStyle* m_rootElementStyle; Element* m_element; StyledElement* m_styledElement; + RenderRegion* m_regionForStyling; EInsideLink m_elementLinkState; ContainerNode* m_parentNode; CSSValue* m_lineHeightValue; @@ -412,16 +440,40 @@ private: bool m_applyPropertyToRegularStyle; bool m_applyPropertyToVisitedLinkStyle; const CSSStyleApplyProperty& m_applyProperty; - + #if ENABLE(CSS_SHADERS) bool m_hasPendingShaders; #endif +#if ENABLE(STYLE_SCOPED) + typedef HashMap<const Element*, OwnPtr<RuleSet> > ScopedRuleSetMap; + + RuleSet* scopedRuleSetForElement(const Element*) const; + + void setupScopingElementStack(const Element*); + bool scopingElementStackIsConsistent(const Element* parent) const { return parent && parent == m_scopingElementStackParent; } + + ScopedRuleSetMap m_scopedAuthorStyles; + + struct ScopeStackFrame { + ScopeStackFrame() : m_element(0), m_ruleSet(0) { } + ScopeStackFrame(const Element* element, RuleSet* ruleSet) : m_element(element), m_ruleSet(ruleSet) { } + const Element* m_element; + RuleSet* m_ruleSet; + }; + // Vector (used as stack) that keeps track of scoping elements (i.e., elements with a <style scoped> child) + // encountered during tree iteration for style resolution. + Vector<ScopeStackFrame> m_scopingElementStack; + // Element last seen as parent element when updating m_scopingElementStack. + // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack. + const Element* m_scopingElementStackParent; +#endif + friend class CSSStyleApplyProperty; friend bool operator==(const MatchedStyleDeclaration&, const MatchedStyleDeclaration&); friend bool operator!=(const MatchedStyleDeclaration&, const MatchedStyleDeclaration&); - friend bool operator==(const MatchResult&, const MatchResult&); - friend bool operator!=(const MatchResult&, const MatchResult&); + friend bool operator==(const MatchRanges&, const MatchRanges&); + friend bool operator!=(const MatchRanges&, const MatchRanges&); }; } // namespace WebCore diff --git a/Source/WebCore/css/CSSValue.cpp b/Source/WebCore/css/CSSValue.cpp index 711e4c5ed..016cb0bba 100644 --- a/Source/WebCore/css/CSSValue.cpp +++ b/Source/WebCore/css/CSSValue.cpp @@ -28,8 +28,8 @@ #include "CSSValue.h" #include "CSSAspectRatioValue.h" -#include "CSSBorderImageValue.h" #include "CSSBorderImageSliceValue.h" +#include "CSSCalculationValue.h" #include "CSSCanvasValue.h" #include "CSSCrossfadeValue.h" #include "CSSCursorImageValue.h" @@ -89,8 +89,6 @@ void CSSValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSh static_cast<CSSPrimitiveValue*>(this)->addSubresourceStyleURLs(urls, styleSheet); else if (isValueList()) static_cast<CSSValueList*>(this)->addSubresourceStyleURLs(urls, styleSheet); - else if (classType() == BorderImageClass) - static_cast<CSSBorderImageValue*>(this)->addSubresourceStyleURLs(urls, styleSheet); else if (classType() == FontFaceSrcClass) static_cast<CSSFontFaceSrcValue*>(this)->addSubresourceStyleURLs(urls, styleSheet); else if (classType() == ReflectClass) @@ -102,8 +100,6 @@ String CSSValue::cssText() const switch (classType()) { case AspectRatioClass: return static_cast<const CSSAspectRatioValue*>(this)->customCssText(); - case BorderImageClass: - return static_cast<const CSSBorderImageValue*>(this)->customCssText(); case BorderImageSliceClass: return static_cast<const CSSBorderImageSliceValue*>(this)->customCssText(); case CanvasClass: @@ -154,6 +150,8 @@ String CSSValue::cssText() const return static_cast<const CSSLineBoxContainValue*>(this)->customCssText(); case FlexClass: return static_cast<const CSSFlexValue*>(this)->customCssText(); + case CalculationClass: + return static_cast<const CSSCalcValue*>(this)->customCssText(); #if ENABLE(CSS_FILTERS) case WebKitCSSFilterClass: return static_cast<const WebKitCSSFilterValue*>(this)->customCssText(); @@ -179,9 +177,6 @@ void CSSValue::destroy() case AspectRatioClass: delete static_cast<CSSAspectRatioValue*>(this); return; - case BorderImageClass: - delete static_cast<CSSBorderImageValue*>(this); - return; case BorderImageSliceClass: delete static_cast<CSSBorderImageSliceValue*>(this); return; @@ -257,6 +252,9 @@ void CSSValue::destroy() case FlexClass: delete static_cast<CSSFlexValue*>(this); return; + case CalculationClass: + delete static_cast<CSSCalcValue*>(this); + return; #if ENABLE(CSS_FILTERS) case WebKitCSSFilterClass: delete static_cast<WebKitCSSFilterValue*>(this); diff --git a/Source/WebCore/css/CSSValue.h b/Source/WebCore/css/CSSValue.h index fd5e6f520..61233212b 100644 --- a/Source/WebCore/css/CSSValue.h +++ b/Source/WebCore/css/CSSValue.h @@ -60,7 +60,6 @@ public: bool isValueList() const { return m_classType >= ValueListClass; } bool isAspectRatioValue() const { return m_classType == AspectRatioClass; } - bool isBorderImageValue() const { return m_classType == BorderImageClass; } bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; } bool isCursorImageValue() const { return m_classType == CursorImageClass; } bool isFontFamilyValue() const { return m_classType == FontFamilyClass; } @@ -77,6 +76,7 @@ public: bool isWebKitCSSTransformValue() const { return m_classType == WebKitCSSTransformClass; } bool isCSSLineBoxContainValue() const { return m_classType == LineBoxContainClass; } bool isFlexValue() const { return m_classType == FlexClass; } + bool isCalculationValue() const {return m_classType == CalculationClass; } #if ENABLE(CSS_FILTERS) bool isWebKitCSSFilterValue() const { return m_classType == WebKitCSSFilterClass; } #if ENABLE(CSS_SHADERS) @@ -113,7 +113,6 @@ protected: // Other class types. AspectRatioClass, - BorderImageClass, BorderImageSliceClass, FontFeatureClass, FontClass, @@ -128,6 +127,7 @@ protected: UnicodeRangeClass, LineBoxContainClass, FlexClass, + CalculationClass, #if ENABLE(CSS_FILTERS) && ENABLE(CSS_SHADERS) WebKitCSSShaderClass, #endif diff --git a/Source/WebCore/css/CSSValue.idl b/Source/WebCore/css/CSSValue.idl index 25eb8033c..0edc3d7bd 100644 --- a/Source/WebCore/css/CSSValue.idl +++ b/Source/WebCore/css/CSSValue.idl @@ -34,7 +34,7 @@ module css { const unsigned short CSS_VALUE_LIST = 2; const unsigned short CSS_CUSTOM = 3; - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString cssText setter raises(DOMException); readonly attribute unsigned short cssValueType; diff --git a/Source/WebCore/css/CSSValueKeywords.in b/Source/WebCore/css/CSSValueKeywords.in index ba1c5f692..fd1052886 100644 --- a/Source/WebCore/css/CSSValueKeywords.in +++ b/Source/WebCore/css/CSSValueKeywords.in @@ -52,6 +52,17 @@ all // //normal small-caps + +// -webkit-font-variant-ligatures: +// +// normal +common-ligatures +no-common-ligatures +discretionary-ligatures +no-discretionary-ligatures +historical-ligatures +no-historical-ligatures + // // CSS_PROP_FONT_WEIGHT: // @@ -481,6 +492,13 @@ multiple // baseline // stretch +// CSS_PROP_FLEX_PACK +// start +// end +// center +// justify +distribute + // CSS_PROP_FLEX_FLOW row row-reverse @@ -832,11 +850,6 @@ glyphs inline-box replaced -// -webkit-line-grid-snap -//none -//baseline -bounds - // -webkit-font-feature-settings on off diff --git a/Source/WebCore/css/MediaList.idl b/Source/WebCore/css/MediaList.idl index 2b441f00a..73b336c87 100644 --- a/Source/WebCore/css/MediaList.idl +++ b/Source/WebCore/css/MediaList.idl @@ -31,7 +31,7 @@ module stylesheets { HasIndexGetter ] MediaList { - attribute [ConvertNullToNullString, ConvertNullStringTo=Null] DOMString mediaText + attribute [TreatNullAs=EmptyString, ConvertNullStringTo=Null] DOMString mediaText setter raises(DOMException); readonly attribute unsigned long length; diff --git a/Source/WebCore/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp index 64d493392..c4be4365b 100644 --- a/Source/WebCore/css/MediaQueryEvaluator.cpp +++ b/Source/WebCore/css/MediaQueryEvaluator.cpp @@ -178,9 +178,9 @@ static bool parseAspectRatio(CSSValue* value, int& h, int& v) CSSValue* i0 = valueList->itemWithoutBoundsCheck(0); CSSValue* i1 = valueList->itemWithoutBoundsCheck(1); CSSValue* i2 = valueList->itemWithoutBoundsCheck(2); - if (i0->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i0)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER - && i1->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i1)->primitiveType() == CSSPrimitiveValue::CSS_STRING - && i2->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i2)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + if (i0->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i0)->isNumber() + && i1->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i1)->isString() + && i2->isPrimitiveValue() && static_cast<CSSPrimitiveValue*>(i2)->isNumber()) { String str = static_cast<CSSPrimitiveValue*>(i1)->getStringValue(); if (!str.isNull() && str.length() == 1 && str[0] == '/') { h = static_cast<CSSPrimitiveValue*>(i0)->getIntValue(CSSPrimitiveValue::CSS_NUMBER); @@ -210,7 +210,7 @@ bool compareValue(T a, T b, MediaFeaturePrefix op) static bool numberValue(CSSValue* value, float& result) { if (value->isPrimitiveValue() - && static_cast<CSSPrimitiveValue*>(value)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + && static_cast<CSSPrimitiveValue*>(value)->isNumber()) { result = static_cast<CSSPrimitiveValue*>(value)->getFloatValue(CSSPrimitiveValue::CSS_NUMBER); return true; } @@ -313,7 +313,7 @@ static bool computeLength(CSSValue* value, bool strict, RenderStyle* style, Rend CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); - if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) { + if (primitiveValue->isNumber()) { result = primitiveValue->getIntValue(); return !strict || !result; } @@ -332,7 +332,9 @@ static bool device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, F FloatRect sg = screenRect(frame->page()->mainFrame()->view()); RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle(); int length; - return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(static_cast<int>(sg.height()), length, op); + long height = sg.height(); + InspectorInstrumentation::applyScreenHeightOverride(frame, &height); + return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(static_cast<int>(height), length, op); } // ({,min-,max-}device-height) // assume if we have a device, assume non-zero @@ -345,7 +347,9 @@ static bool device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Fr FloatRect sg = screenRect(frame->page()->mainFrame()->view()); RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle(); int length; - return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(static_cast<int>(sg.width()), length, op); + long width = sg.width(); + InspectorInstrumentation::applyScreenWidthOverride(frame, &width); + return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(static_cast<int>(width), length, op); } // ({,min-,max-}device-width) // assume if we have a device, assume non-zero diff --git a/Source/WebCore/css/SVGCSSParser.cpp b/Source/WebCore/css/SVGCSSParser.cpp index dd738fb3c..2c295765a 100644 --- a/Source/WebCore/css/SVGCSSParser.cpp +++ b/Source/WebCore/css/SVGCSSParser.cpp @@ -314,6 +314,12 @@ bool CSSParser::parseSVGValue(int propId, bool important) parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSParserValue::Q_EMS) parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); + if (isCalculation(value)) { + // FIXME calc() http://webkit.org/b/16662 : actually create a CSSPrimitiveValue here, ie + // parsedValue = CSSPrimitiveValue::create(m_parsedCalculation.release()); + m_parsedCalculation.release(); + parsedValue = 0; + } m_valueList->next(); } if (!parsedValue || (m_valueList->current() && !inShorthand())) diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp index f74eed02c..3677fcf79 100644 --- a/Source/WebCore/css/SelectorChecker.cpp +++ b/Source/WebCore/css/SelectorChecker.cpp @@ -40,6 +40,7 @@ #include "HTMLNames.h" #include "HTMLOptionElement.h" #include "HTMLProgressElement.h" +#include "HTMLStyleElement.h" #include "InspectorInstrumentation.h" #include "NodeRenderStyle.h" #include "Page.h" @@ -125,42 +126,33 @@ void SelectorChecker::popParentStackFrame() } } -void SelectorChecker::pushParent(Element* parent) +void SelectorChecker::setupParentStack(Element* parent) { - if (m_parentStack.isEmpty()) { - ASSERT(!m_ancestorIdentifierFilter); - m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>); - // If the element is not the root itself, build the stack starting from the root. - if (parent->parentOrHostNode()) { - Vector<Element*, 30> ancestors; - for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentOrHostElement()) - ancestors.append(ancestor); - int count = ancestors.size(); - for (int n = count - 1; n >= 0; --n) - pushParentStackFrame(ancestors[n]); - return; - } - } else if (!parent->parentOrHostElement()) { - // We are not always invoked consistently. For example, script execution can cause us to enter - // style recalc in the middle of tree building. Reset the stack if we see a new root element. - ASSERT(m_ancestorIdentifierFilter); - m_ancestorIdentifierFilter->clear(); - m_parentStack.resize(0); - } else { - ASSERT(m_ancestorIdentifierFilter); - // We may get invoked for some random elements in some wacky cases during style resolve. - // Pause maintaining the stack in this case. - if (m_parentStack.last().element != parent->parentOrHostElement()) - return; + ASSERT(m_parentStack.isEmpty() == !m_ancestorIdentifierFilter); + // Kill whatever we stored before. + m_parentStack.shrink(0); + m_ancestorIdentifierFilter = adoptPtr(new BloomFilter<bloomFilterKeyBits>); + // Fast version if parent is a root element: + if (!parent->parentOrHostNode()) { + pushParentStackFrame(parent); + return; } - pushParentStackFrame(parent); + // Otherwise climb up the tree. + Vector<Element*, 30> ancestors; + for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentOrHostElement()) + ancestors.append(ancestor); + for (size_t n = ancestors.size(); n; --n) + pushParentStackFrame(ancestors[n - 1]); } -void SelectorChecker::popParent(Element* parent) +void SelectorChecker::pushParent(Element* parent) { - if (m_parentStack.isEmpty() || m_parentStack.last().element != parent) + ASSERT(m_ancestorIdentifierFilter); + // We may get invoked for some random elements in some wacky cases during style resolve. + // Pause maintaining the stack in this case. + if (m_parentStack.last().element != parent->parentOrHostElement()) return; - popParentStackFrame(); + pushParentStackFrame(parent); } static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector* selector, unsigned*& hash, const unsigned* end) @@ -715,7 +707,7 @@ bool SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& d if (sel->isAttributeSelector()) { const QualifiedName& attr = sel->attribute(); - NamedNodeMap* attributes = e->attributes(true); + NamedNodeMap* attributes = e->updatedAttributes(); if (!attributes) return false; diff --git a/Source/WebCore/css/SelectorChecker.h b/Source/WebCore/css/SelectorChecker.h index 1a01306f8..3f9469e5d 100644 --- a/Source/WebCore/css/SelectorChecker.h +++ b/Source/WebCore/css/SelectorChecker.h @@ -60,9 +60,11 @@ public: inline bool fastRejectSelector(const unsigned* identifierHashes) const; static void collectIdentifierHashes(const CSSSelector*, unsigned* identifierHashes, unsigned maximumIdentifierCount); + void setupParentStack(Element* parent); void pushParent(Element* parent); - void popParent(Element* parent); - bool parentStackIsConsistent(ContainerNode* parentNode) const { return !m_parentStack.isEmpty() && m_parentStack.last().element == parentNode; } + void popParent() { popParentStackFrame(); } + bool parentStackIsEmpty() const { return m_parentStack.isEmpty(); } + bool parentStackIsConsistent(const ContainerNode* parentNode) const { return !m_parentStack.isEmpty() && m_parentStack.last().element == parentNode; } EInsideLink determineLinkState(Element*) const; void allVisitedStateChanged(); @@ -115,7 +117,7 @@ private: mutable HashSet<LinkHash, LinkHashHash> m_linksCheckedForVisitedState; struct ParentStackFrame { - ParentStackFrame() { } + ParentStackFrame() : element(0) { } ParentStackFrame(Element* element) : element(element) { } Element* element; Vector<unsigned, 4> identifierHashes; diff --git a/Source/WebCore/css/StyleSheetList.h b/Source/WebCore/css/StyleSheetList.h index 4eb7d6a27..3f81163e6 100644 --- a/Source/WebCore/css/StyleSheetList.h +++ b/Source/WebCore/css/StyleSheetList.h @@ -46,6 +46,11 @@ public: HTMLStyleElement* getNamedItem(const String&) const; + const StyleSheetVector& vector() const + { + return m_sheets; + } + void swap(StyleSheetVector& sheets) { m_sheets.swap(sheets); diff --git a/Source/WebCore/css/WebKitCSSKeyframeRule.cpp b/Source/WebCore/css/WebKitCSSKeyframeRule.cpp index 23bdeca5f..674aa5a7b 100644 --- a/Source/WebCore/css/WebKitCSSKeyframeRule.cpp +++ b/Source/WebCore/css/WebKitCSSKeyframeRule.cpp @@ -46,7 +46,7 @@ String WebKitCSSKeyframeRule::cssText() const String result = m_key; result += " { "; - result += m_style->cssText(); + result += m_style->asText(); result += "}"; return result; diff --git a/Source/WebCore/css/WebKitCSSKeyframeRule.h b/Source/WebCore/css/WebKitCSSKeyframeRule.h index 052c86bf1..083518756 100644 --- a/Source/WebCore/css/WebKitCSSKeyframeRule.h +++ b/Source/WebCore/css/WebKitCSSKeyframeRule.h @@ -26,14 +26,13 @@ #ifndef WebKitCSSKeyframeRule_h #define WebKitCSSKeyframeRule_h +#include "CSSMutableStyleDeclaration.h" #include "CSSRule.h" #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> namespace WebCore { -class CSSMutableStyleDeclaration; - typedef int ExceptionCode; class WebKitCSSKeyframeRule : public CSSRule { @@ -54,15 +53,13 @@ public: void getKeys(Vector<float>& keys) const { parseKeyString(m_key, keys); } - CSSMutableStyleDeclaration* style() const { return m_style.get(); } + CSSStyleDeclaration* style() const { return m_style.get(); } String cssText() const; + CSSMutableStyleDeclaration* declaration() const { return m_style.get(); } void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration>); - CSSMutableStyleDeclaration* declaration() { return m_style.get(); } - const CSSMutableStyleDeclaration* declaration() const { return m_style.get(); } - private: static void parseKeyString(const String& s, Vector<float>& keys); diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.idl b/Source/WebCore/css/WebKitCSSKeyframesRule.idl index 3b081307f..87c8dd65e 100644 --- a/Source/WebCore/css/WebKitCSSKeyframesRule.idl +++ b/Source/WebCore/css/WebKitCSSKeyframesRule.idl @@ -33,7 +33,7 @@ module css { HasIndexGetter ] WebKitCSSKeyframesRule : CSSRule { - attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString name; + attribute [ConvertNullStringTo=Null, TreatNullAs=EmptyString] DOMString name; readonly attribute CSSRuleList cssRules; void insertRule(in [Optional=CallWithDefaultValue] DOMString rule); diff --git a/Source/WebCore/css/WebKitCSSRegionRule.cpp b/Source/WebCore/css/WebKitCSSRegionRule.cpp index c049ed68b..d809aafba 100644 --- a/Source/WebCore/css/WebKitCSSRegionRule.cpp +++ b/Source/WebCore/css/WebKitCSSRegionRule.cpp @@ -13,7 +13,7 @@ * disclaimer in the documentation and/or other materials * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE @@ -31,8 +31,11 @@ #include "WebKitCSSRegionRule.h" +#include "CSSParser.h" #include "CSSParserValues.h" #include "CSSRuleList.h" +#include "Document.h" +#include "ExceptionCode.h" namespace WebCore { WebKitCSSRegionRule::WebKitCSSRegionRule(CSSStyleSheet* parent, Vector<OwnPtr<CSSParserSelector> >* selectors, PassRefPtr<CSSRuleList> rules) diff --git a/Source/WebCore/css/WebKitCSSRegionRule.h b/Source/WebCore/css/WebKitCSSRegionRule.h index 6367b50f9..f4dede542 100644 --- a/Source/WebCore/css/WebKitCSSRegionRule.h +++ b/Source/WebCore/css/WebKitCSSRegionRule.h @@ -13,7 +13,7 @@ * disclaimer in the documentation and/or other materials * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE diff --git a/Source/WebCore/css/WebKitCSSRegionRule.idl b/Source/WebCore/css/WebKitCSSRegionRule.idl new file mode 100644 index 000000000..dc8b0a96d --- /dev/null +++ b/Source/WebCore/css/WebKitCSSRegionRule.idl @@ -0,0 +1,37 @@ +/* + * Copyright 2012 Adobe Systems Incorporated. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +module css { + + interface [ + ] WebKitCSSRegionRule : CSSRule { + readonly attribute CSSRuleList cssRules; + }; + +} diff --git a/Source/WebCore/css/svg.css b/Source/WebCore/css/svg.css index 171c1c41f..bc31269f8 100644 --- a/Source/WebCore/css/svg.css +++ b/Source/WebCore/css/svg.css @@ -46,11 +46,6 @@ svg:not(:root), symbol, image, marker, pattern, foreignObject { overflow: hidden } -svg { - width: 100%; - height: 100%; -} - text, foreignObject { display: block } diff --git a/Source/WebCore/css/tokenizer.flex b/Source/WebCore/css/tokenizer.flex deleted file mode 100644 index c28dbcafa..000000000 --- a/Source/WebCore/css/tokenizer.flex +++ /dev/null @@ -1,130 +0,0 @@ -%option case-insensitive -%option noyywrap -%option 8bit -%option stack -%s mediaquery -%s forkeyword -%s nthchild - -h [0-9a-fA-F] -nonascii [\200-\377] -unicode \\{h}{1,6}[ \t\r\n\f]? -escape {unicode}|\\[ -~\200-\377] -nmstart [_a-zA-Z]|{nonascii}|{escape} -nmchar [_a-zA-Z0-9-]|{nonascii}|{escape} -string1 \"([^\n\r\f\\"]|\\{nl}|{escape})*\" -string2 \'([^\n\r\f\\']|\\{nl}|{escape})*\' - -ident -?{nmstart}{nmchar}* -num [0-9]+|[0-9]*"."[0-9]+ -intnum [0-9]+ -string {string1}|{string2} -url ([!#$%&*-~]|{nonascii}|{escape})* -w [ \t\r\n\f]* -nl \n|\r\n|\r|\f -range \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h}))))) -nth [\+-]?{intnum}*n([\t\r\n ]*[\+-][\t\r\n ]*{intnum})? -nthfunc "nth-"("child"|"of-type"|"last-child"|"last-of-type") - -%% - -\/\*[^*]*\*+([^/*][^*]*\*+)*\/ {countLines(); /* ignore comments */ } - -[ \t\r\n\f]+ {countLines(); yyTok = WHITESPACE; return yyTok;} - -"<!--" {yyTok = SGML_CD; return yyTok;} -"-->" {yyTok = SGML_CD; return yyTok;} -"~=" {yyTok = INCLUDES; return yyTok;} -"|=" {yyTok = DASHMATCH; return yyTok;} -"^=" {yyTok = BEGINSWITH; return yyTok;} -"$=" {yyTok = ENDSWITH; return yyTok;} -"*=" {yyTok = CONTAINS; return yyTok;} -<mediaquery>"not" {yyTok = MEDIA_NOT; return yyTok;} -<mediaquery>"only" {yyTok = MEDIA_ONLY; return yyTok;} -<mediaquery>"and" {yyTok = MEDIA_AND; return yyTok;} - -{string} {yyTok = STRING; return yyTok;} -{ident} {yyTok = IDENT; return yyTok;} -<nthchild>{nth} {yyTok = NTH; return yyTok;} -<nthchild>")" {BEGIN(INITIAL); yyTok = *yytext; return yyTok;} - -"#"{h}+ {yyTok = HEX; return yyTok;} -"#"{ident} {yyTok = IDSEL; return yyTok;} - -"@import" {BEGIN(mediaquery); yyTok = IMPORT_SYM; return yyTok;} -"@page" {yyTok = PAGE_SYM; return yyTok;} -"@top-left-corner" {yyTok = TOPLEFTCORNER_SYM; return yyTok;} -"@top-left" {yyTok = TOPLEFT_SYM; return yyTok;} -"@top-center" {yyTok = TOPCENTER_SYM; return yyTok;} -"@top-right" {yyTok = TOPRIGHT_SYM; return yyTok;} -"@top-right-corner" {yyTok = TOPRIGHTCORNER_SYM; return yyTok;} -"@bottom-left-corner" {yyTok = BOTTOMLEFTCORNER_SYM; return yyTok;} -"@bottom-left" {yyTok = BOTTOMLEFT_SYM; return yyTok;} -"@bottom-center" {yyTok = BOTTOMCENTER_SYM; return yyTok;} -"@bottom-right" {yyTok = BOTTOMRIGHT_SYM; return yyTok;} -"@bottom-right-corner" {yyTok = BOTTOMRIGHTCORNER_SYM; return yyTok;} -"@left-top" {yyTok = LEFTTOP_SYM; return yyTok;} -"@left-middle" {yyTok = LEFTMIDDLE_SYM; return yyTok;} -"@left-bottom" {yyTok = LEFTBOTTOM_SYM; return yyTok;} -"@right-top" {yyTok = RIGHTTOP_SYM; return yyTok;} -"@right-middle" {yyTok = RIGHTMIDDLE_SYM; return yyTok;} -"@right-bottom" {yyTok = RIGHTBOTTOM_SYM; return yyTok;} -"@media" {BEGIN(mediaquery); yyTok = MEDIA_SYM; return yyTok;} -"@font-face" {yyTok = FONT_FACE_SYM; return yyTok;} -"@charset" {yyTok = CHARSET_SYM; return yyTok;} -"@namespace" {yyTok = NAMESPACE_SYM; return yyTok; } -"@-webkit-rule" {yyTok = WEBKIT_RULE_SYM; return yyTok; } -"@-webkit-decls" {yyTok = WEBKIT_DECLS_SYM; return yyTok; } -"@-webkit-value" {yyTok = WEBKIT_VALUE_SYM; return yyTok; } -"@-webkit-mediaquery" {BEGIN(mediaquery); yyTok = WEBKIT_MEDIAQUERY_SYM; return yyTok; } -"@-webkit-selector" {yyTok = WEBKIT_SELECTOR_SYM; return yyTok; } -"@-webkit-keyframes" {yyTok = WEBKIT_KEYFRAMES_SYM; return yyTok; } -"@-webkit-keyframe-rule" {yyTok = WEBKIT_KEYFRAME_RULE_SYM; return yyTok; } -"@-webkit-region" {yyTok = WEBKIT_REGION_RULE_SYM; return yyTok;} - -"@"{ident} {yyTok = ATKEYWORD; return yyTok; } - -"!"{w}"important" {yyTok = IMPORTANT_SYM; return yyTok;} - -{num}em {yyTok = EMS; return yyTok;} -{num}rem {yyTok = REMS; return yyTok;} -{num}__qem {yyTok = QEMS; return yyTok;} /* quirky ems */ -{num}ex {yyTok = EXS; return yyTok;} -{num}px {yyTok = PXS; return yyTok;} -{num}cm {yyTok = CMS; return yyTok;} -{num}mm {yyTok = MMS; return yyTok;} -{num}in {yyTok = INS; return yyTok;} -{num}pt {yyTok = PTS; return yyTok;} -{num}pc {yyTok = PCS; return yyTok;} -{num}deg {yyTok = DEGS; return yyTok;} -{num}rad {yyTok = RADS; return yyTok;} -{num}grad {yyTok = GRADS; return yyTok;} -{num}turn {yyTok = TURNS; return yyTok;} -{num}ms {yyTok = MSECS; return yyTok;} -{num}s {yyTok = SECS; return yyTok;} -{num}Hz {yyTok = HERTZ; return yyTok;} -{num}kHz {yyTok = KHERTZ; return yyTok;} -{num}{ident} {yyTok = DIMEN; return yyTok;} -{num}{ident}\+ {yyTok = INVALIDDIMEN; return yyTok;} -{num}%+ {yyTok = PERCENTAGE; return yyTok;} -{intnum} {yyTok = INTEGER; return yyTok;} -{num} {yyTok = FLOATTOKEN; return yyTok;} - -"-webkit-any(" {yyTok = ANYFUNCTION; return yyTok;} -"not(" {yyTok = NOTFUNCTION; return yyTok;} -"url("{w}{string}{w}")" {yyTok = URI; return yyTok;} -"url("{w}{url}{w}")" {yyTok = URI; return yyTok;} -"-webkit-calc(" {yyTok = CALCFUNCTION; return yyTok;} -"-webkit-min(" {yyTok = MINFUNCTION; return yyTok;} -"-webkit-max(" {yyTok = MAXFUNCTION; return yyTok;} -{nthfunc}"(" {BEGIN(nthchild); yyTok = FUNCTION; return yyTok;} -{ident}"(" {yyTok = FUNCTION; return yyTok;} - -U\+{range} {yyTok = UNICODERANGE; return yyTok;} -U\+{h}{1,6}-{h}{1,6} {yyTok = UNICODERANGE; return yyTok;} - -<mediaquery>"{" | -<mediaquery>";" {BEGIN(INITIAL); yyTok = *yytext; return yyTok; } -. {yyTok = *yytext; return yyTok;} - -%% |