summaryrefslogtreecommitdiff
path: root/Source/WebCore/css
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
commit40736c5763bf61337c8c14e16d8587db021a87d4 (patch)
treeb17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/WebCore/css
downloadqtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/WebCore/css')
-rw-r--r--Source/WebCore/css/CSSAllInOne.cpp75
-rw-r--r--Source/WebCore/css/CSSAspectRatioValue.cpp45
-rw-r--r--Source/WebCore/css/CSSAspectRatioValue.h63
-rw-r--r--Source/WebCore/css/CSSBorderImageSliceValue.cpp52
-rw-r--r--Source/WebCore/css/CSSBorderImageSliceValue.h59
-rw-r--r--Source/WebCore/css/CSSBorderImageValue.cpp81
-rw-r--r--Source/WebCore/css/CSSBorderImageValue.h70
-rw-r--r--Source/WebCore/css/CSSCanvasValue.cpp95
-rw-r--r--Source/WebCore/css/CSSCanvasValue.h98
-rw-r--r--Source/WebCore/css/CSSCharsetRule.cpp37
-rw-r--r--Source/WebCore/css/CSSCharsetRule.h50
-rw-r--r--Source/WebCore/css/CSSCharsetRule.idl33
-rw-r--r--Source/WebCore/css/CSSComputedStyleDeclaration.cpp2464
-rw-r--r--Source/WebCore/css/CSSComputedStyleDeclaration.h105
-rw-r--r--Source/WebCore/css/CSSCrossfadeValue.cpp175
-rw-r--r--Source/WebCore/css/CSSCrossfadeValue.h102
-rw-r--r--Source/WebCore/css/CSSCursorImageValue.cpp139
-rw-r--r--Source/WebCore/css/CSSCursorImageValue.h63
-rw-r--r--Source/WebCore/css/CSSElementStyleDeclaration.cpp40
-rw-r--r--Source/WebCore/css/CSSElementStyleDeclaration.h61
-rw-r--r--Source/WebCore/css/CSSFlexValue.cpp49
-rw-r--r--Source/WebCore/css/CSSFlexValue.h66
-rw-r--r--Source/WebCore/css/CSSFontFace.cpp126
-rw-r--r--Source/WebCore/css/CSSFontFace.h106
-rw-r--r--Source/WebCore/css/CSSFontFaceRule.cpp55
-rw-r--r--Source/WebCore/css/CSSFontFaceRule.h61
-rw-r--r--Source/WebCore/css/CSSFontFaceRule.idl28
-rw-r--r--Source/WebCore/css/CSSFontFaceSource.cpp215
-rw-r--r--Source/WebCore/css/CSSFontFaceSource.h90
-rw-r--r--Source/WebCore/css/CSSFontFaceSrcValue.cpp80
-rw-r--r--Source/WebCore/css/CSSFontFaceSrcValue.h89
-rw-r--r--Source/WebCore/css/CSSFontSelector.cpp621
-rw-r--r--Source/WebCore/css/CSSFontSelector.h92
-rw-r--r--Source/WebCore/css/CSSFunctionValue.cpp52
-rw-r--r--Source/WebCore/css/CSSFunctionValue.h54
-rw-r--r--Source/WebCore/css/CSSGradientValue.cpp868
-rw-r--r--Source/WebCore/css/CSSGradientValue.h173
-rw-r--r--Source/WebCore/css/CSSGrammar.y1704
-rw-r--r--Source/WebCore/css/CSSHelper.h36
-rw-r--r--Source/WebCore/css/CSSImageGeneratorValue.cpp199
-rw-r--r--Source/WebCore/css/CSSImageGeneratorValue.h82
-rw-r--r--Source/WebCore/css/CSSImageValue.cpp110
-rw-r--r--Source/WebCore/css/CSSImageValue.h62
-rw-r--r--Source/WebCore/css/CSSImportRule.cpp180
-rw-r--r--Source/WebCore/css/CSSImportRule.h88
-rw-r--r--Source/WebCore/css/CSSImportRule.idl30
-rw-r--r--Source/WebCore/css/CSSInheritedValue.cpp33
-rw-r--r--Source/WebCore/css/CSSInheritedValue.h47
-rw-r--r--Source/WebCore/css/CSSInitialValue.cpp33
-rw-r--r--Source/WebCore/css/CSSInitialValue.h52
-rw-r--r--Source/WebCore/css/CSSInlineStyleDeclaration.h58
-rw-r--r--Source/WebCore/css/CSSLineBoxContainValue.cpp75
-rw-r--r--Source/WebCore/css/CSSLineBoxContainValue.h62
-rw-r--r--Source/WebCore/css/CSSMediaRule.cpp130
-rw-r--r--Source/WebCore/css/CSSMediaRule.h63
-rw-r--r--Source/WebCore/css/CSSMediaRule.idl35
-rw-r--r--Source/WebCore/css/CSSMutableStyleDeclaration.cpp1055
-rw-r--r--Source/WebCore/css/CSSMutableStyleDeclaration.h223
-rw-r--r--Source/WebCore/css/CSSNamespace.h55
-rw-r--r--Source/WebCore/css/CSSOMUtils.cpp124
-rw-r--r--Source/WebCore/css/CSSOMUtils.h52
-rw-r--r--Source/WebCore/css/CSSPageRule.cpp47
-rw-r--r--Source/WebCore/css/CSSPageRule.h50
-rw-r--r--Source/WebCore/css/CSSPageRule.idl32
-rw-r--r--Source/WebCore/css/CSSParser.cpp8162
-rw-r--r--Source/WebCore/css/CSSParser.h450
-rw-r--r--Source/WebCore/css/CSSParserValues.cpp135
-rw-r--r--Source/WebCore/css/CSSParserValues.h146
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.cpp955
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.h281
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.idl72
-rw-r--r--Source/WebCore/css/CSSPrimitiveValueMappings.h3926
-rw-r--r--Source/WebCore/css/CSSProperty.cpp674
-rw-r--r--Source/WebCore/css/CSSProperty.h76
-rw-r--r--Source/WebCore/css/CSSPropertyLonghand.cpp247
-rw-r--r--Source/WebCore/css/CSSPropertyLonghand.h53
-rw-r--r--Source/WebCore/css/CSSPropertyNames.in375
-rw-r--r--Source/WebCore/css/CSSPropertySourceData.cpp123
-rw-r--r--Source/WebCore/css/CSSPropertySourceData.h100
-rw-r--r--Source/WebCore/css/CSSReflectValue.cpp68
-rw-r--r--Source/WebCore/css/CSSReflectValue.h70
-rw-r--r--Source/WebCore/css/CSSReflectionDirection.h35
-rw-r--r--Source/WebCore/css/CSSRule.cpp115
-rw-r--r--Source/WebCore/css/CSSRule.h146
-rw-r--r--Source/WebCore/css/CSSRule.idl54
-rw-r--r--Source/WebCore/css/CSSRuleList.cpp111
-rw-r--r--Source/WebCore/css/CSSRuleList.h71
-rw-r--r--Source/WebCore/css/CSSRuleList.idl38
-rw-r--r--Source/WebCore/css/CSSSegmentedFontFace.cpp128
-rw-r--r--Source/WebCore/css/CSSSegmentedFontFace.h69
-rw-r--r--Source/WebCore/css/CSSSelector.cpp778
-rw-r--r--Source/WebCore/css/CSSSelector.h374
-rw-r--r--Source/WebCore/css/CSSSelectorList.cpp186
-rw-r--r--Source/WebCore/css/CSSSelectorList.h71
-rw-r--r--Source/WebCore/css/CSSStyleApplyProperty.cpp1807
-rw-r--r--Source/WebCore/css/CSSStyleApplyProperty.h101
-rw-r--r--Source/WebCore/css/CSSStyleDeclaration.cpp172
-rw-r--r--Source/WebCore/css/CSSStyleDeclaration.h111
-rw-r--r--Source/WebCore/css/CSSStyleDeclaration.idl55
-rw-r--r--Source/WebCore/css/CSSStyleRule.cpp150
-rw-r--r--Source/WebCore/css/CSSStyleRule.h73
-rw-r--r--Source/WebCore/css/CSSStyleRule.idl32
-rw-r--r--Source/WebCore/css/CSSStyleSelector.cpp5400
-rw-r--r--Source/WebCore/css/CSSStyleSelector.h419
-rw-r--r--Source/WebCore/css/CSSStyleSheet.cpp314
-rw-r--r--Source/WebCore/css/CSSStyleSheet.h135
-rw-r--r--Source/WebCore/css/CSSStyleSheet.idl45
-rw-r--r--Source/WebCore/css/CSSTimingFunctionValue.cpp62
-rw-r--r--Source/WebCore/css/CSSTimingFunctionValue.h119
-rw-r--r--Source/WebCore/css/CSSUnicodeRangeValue.cpp40
-rw-r--r--Source/WebCore/css/CSSUnicodeRangeValue.h61
-rw-r--r--Source/WebCore/css/CSSUnknownRule.h36
-rw-r--r--Source/WebCore/css/CSSUnknownRule.idl29
-rw-r--r--Source/WebCore/css/CSSValue.cpp277
-rw-r--r--Source/WebCore/css/CSSValue.h189
-rw-r--r--Source/WebCore/css/CSSValue.idl44
-rw-r--r--Source/WebCore/css/CSSValueKeywords.in883
-rw-r--r--Source/WebCore/css/CSSValueList.cpp122
-rw-r--r--Source/WebCore/css/CSSValueList.h103
-rw-r--r--Source/WebCore/css/CSSValueList.idl36
-rw-r--r--Source/WebCore/css/CSSValuePool.cpp123
-rw-r--r--Source/WebCore/css/CSSValuePool.h78
-rw-r--r--Source/WebCore/css/CSSWrapShapes.cpp149
-rw-r--r--Source/WebCore/css/CSSWrapShapes.h173
-rw-r--r--Source/WebCore/css/Counter.h61
-rw-r--r--Source/WebCore/css/Counter.idl29
-rw-r--r--Source/WebCore/css/DashboardRegion.h48
-rw-r--r--Source/WebCore/css/DashboardSupportCSSPropertyNames.in1
-rw-r--r--Source/WebCore/css/FontFamilyValue.cpp72
-rw-r--r--Source/WebCore/css/FontFamilyValue.h50
-rw-r--r--Source/WebCore/css/FontFeatureValue.cpp52
-rw-r--r--Source/WebCore/css/FontFeatureValue.h54
-rw-r--r--Source/WebCore/css/FontValue.cpp68
-rw-r--r--Source/WebCore/css/FontValue.h58
-rw-r--r--Source/WebCore/css/MediaFeatureNames.cpp53
-rw-r--r--Source/WebCore/css/MediaFeatureNames.h77
-rw-r--r--Source/WebCore/css/MediaList.cpp249
-rw-r--r--Source/WebCore/css/MediaList.h102
-rw-r--r--Source/WebCore/css/MediaList.idl46
-rw-r--r--Source/WebCore/css/MediaQuery.cpp125
-rw-r--r--Source/WebCore/css/MediaQuery.h71
-rw-r--r--Source/WebCore/css/MediaQueryEvaluator.cpp566
-rw-r--r--Source/WebCore/css/MediaQueryEvaluator.h91
-rw-r--r--Source/WebCore/css/MediaQueryExp.cpp111
-rw-r--r--Source/WebCore/css/MediaQueryExp.h84
-rw-r--r--Source/WebCore/css/MediaQueryList.cpp94
-rw-r--r--Source/WebCore/css/MediaQueryList.h65
-rw-r--r--Source/WebCore/css/MediaQueryList.idl27
-rw-r--r--Source/WebCore/css/MediaQueryListListener.cpp50
-rw-r--r--Source/WebCore/css/MediaQueryListListener.h55
-rw-r--r--Source/WebCore/css/MediaQueryListListener.idl29
-rw-r--r--Source/WebCore/css/MediaQueryMatcher.cpp157
-rw-r--r--Source/WebCore/css/MediaQueryMatcher.h87
-rw-r--r--Source/WebCore/css/Pair.h63
-rw-r--r--Source/WebCore/css/RGBColor.cpp63
-rw-r--r--Source/WebCore/css/RGBColor.h59
-rw-r--r--Source/WebCore/css/RGBColor.idl38
-rw-r--r--Source/WebCore/css/Rect.h70
-rw-r--r--Source/WebCore/css/Rect.idl29
-rw-r--r--Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp211
-rw-r--r--Source/WebCore/css/SVGCSSParser.cpp366
-rw-r--r--Source/WebCore/css/SVGCSSPropertyNames.in51
-rw-r--r--Source/WebCore/css/SVGCSSStyleSelector.cpp607
-rw-r--r--Source/WebCore/css/SVGCSSValueKeywords.in277
-rw-r--r--Source/WebCore/css/SelectorChecker.cpp1428
-rw-r--r--Source/WebCore/css/SelectorChecker.h208
-rw-r--r--Source/WebCore/css/ShadowValue.cpp80
-rw-r--r--Source/WebCore/css/ShadowValue.h65
-rw-r--r--Source/WebCore/css/StyleMedia.cpp79
-rw-r--r--Source/WebCore/css/StyleMedia.h59
-rw-r--r--Source/WebCore/css/StyleMedia.idl34
-rw-r--r--Source/WebCore/css/StyleSheet.cpp91
-rw-r--r--Source/WebCore/css/StyleSheet.h89
-rw-r--r--Source/WebCore/css/StyleSheet.idl46
-rw-r--r--Source/WebCore/css/StyleSheetList.cpp75
-rw-r--r--Source/WebCore/css/StyleSheetList.h68
-rw-r--r--Source/WebCore/css/StyleSheetList.idl34
-rw-r--r--Source/WebCore/css/WebKitCSSFilterValue.cpp103
-rw-r--r--Source/WebCore/css/WebKitCSSFilterValue.h79
-rw-r--r--Source/WebCore/css/WebKitCSSFilterValue.idl54
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframeRule.cpp92
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframeRule.h77
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframeRule.idl39
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframesRule.cpp140
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframesRule.h90
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframesRule.idl44
-rw-r--r--Source/WebCore/css/WebKitCSSMatrix.cpp188
-rw-r--r--Source/WebCore/css/WebKitCSSMatrix.h161
-rw-r--r--Source/WebCore/css/WebKitCSSMatrix.idl107
-rw-r--r--Source/WebCore/css/WebKitCSSRegionRule.cpp71
-rw-r--r--Source/WebCore/css/WebKitCSSRegionRule.h67
-rw-r--r--Source/WebCore/css/WebKitCSSShaderValue.cpp78
-rw-r--r--Source/WebCore/css/WebKitCSSShaderValue.h63
-rw-r--r--Source/WebCore/css/WebKitCSSTransformValue.cpp118
-rw-r--r--Source/WebCore/css/WebKitCSSTransformValue.h80
-rw-r--r--Source/WebCore/css/WebKitCSSTransformValue.idl63
-rw-r--r--Source/WebCore/css/WebKitFontFamilyNames.in7
-rw-r--r--Source/WebCore/css/fullscreen.css41
-rw-r--r--Source/WebCore/css/fullscreenQuickTime.css170
-rw-r--r--Source/WebCore/css/html.css1013
-rwxr-xr-xSource/WebCore/css/make-css-file-arrays.pl95
-rw-r--r--Source/WebCore/css/makegrammar.pl55
-rw-r--r--Source/WebCore/css/makeprop.pl203
-rw-r--r--Source/WebCore/css/maketokenizer151
-rw-r--r--Source/WebCore/css/makevalues.pl158
-rw-r--r--Source/WebCore/css/mathml.css238
-rw-r--r--Source/WebCore/css/mediaControls.css227
-rw-r--r--Source/WebCore/css/mediaControlsChromium.css170
-rw-r--r--Source/WebCore/css/mediaControlsEfl.css182
-rw-r--r--Source/WebCore/css/mediaControlsGtk.css105
-rw-r--r--Source/WebCore/css/mediaControlsQt.css260
-rw-r--r--Source/WebCore/css/mediaControlsQtFullscreen.css101
-rw-r--r--Source/WebCore/css/mediaControlsQuickTime.css233
-rw-r--r--Source/WebCore/css/mobileThemeQt.css38
-rw-r--r--Source/WebCore/css/quirks.css54
-rw-r--r--Source/WebCore/css/svg.css70
-rw-r--r--Source/WebCore/css/themeChromium.css77
-rw-r--r--Source/WebCore/css/themeChromiumLinux.css41
-rw-r--r--Source/WebCore/css/themeChromiumSkia.css37
-rw-r--r--Source/WebCore/css/themeQtNoListboxes.css36
-rw-r--r--Source/WebCore/css/themeWin.css127
-rw-r--r--Source/WebCore/css/themeWinQuirks.css38
-rw-r--r--Source/WebCore/css/tokenizer.flex130
-rw-r--r--Source/WebCore/css/view-source.css162
224 files changed, 53631 insertions, 0 deletions
diff --git a/Source/WebCore/css/CSSAllInOne.cpp b/Source/WebCore/css/CSSAllInOne.cpp
new file mode 100644
index 000000000..50901aac7
--- /dev/null
+++ b/Source/WebCore/css/CSSAllInOne.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 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.
+ */
+
+// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build.
+
+#include "CSSAspectRatioValue.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"
+#include "CSSFontFaceSource.cpp"
+#include "CSSFontFaceSrcValue.cpp"
+#include "CSSFontSelector.cpp"
+#include "CSSFunctionValue.cpp"
+#include "CSSGradientValue.cpp"
+#include "CSSImageGeneratorValue.cpp"
+#include "CSSImageValue.cpp"
+#include "CSSImportRule.cpp"
+#include "CSSInheritedValue.cpp"
+#include "CSSInitialValue.cpp"
+#include "CSSLineBoxContainValue.cpp"
+#include "CSSMediaRule.cpp"
+#include "CSSMutableStyleDeclaration.cpp"
+#include "CSSOMUtils.cpp"
+#include "CSSPageRule.cpp"
+#include "CSSParser.cpp"
+#include "CSSParserValues.cpp"
+#include "CSSPropertyLonghand.cpp"
+#include "CSSPropertySourceData.cpp"
+#include "CSSReflectValue.cpp"
+#include "CSSRule.cpp"
+#include "CSSRuleList.cpp"
+#include "CSSSegmentedFontFace.cpp"
+#include "CSSSelector.cpp"
+#include "CSSSelectorList.cpp"
+#include "CSSStyleApplyProperty.cpp"
+#include "CSSStyleDeclaration.cpp"
+#include "CSSStyleRule.cpp"
+#include "CSSStyleSelector.cpp"
+#include "CSSStyleSheet.cpp"
+#include "CSSTimingFunctionValue.cpp"
+#include "CSSUnicodeRangeValue.cpp"
+#include "CSSValue.cpp"
+#include "CSSValueList.cpp"
+#include "CSSValuePool.cpp"
+#include "CSSWrapShapes.cpp"
diff --git a/Source/WebCore/css/CSSAspectRatioValue.cpp b/Source/WebCore/css/CSSAspectRatioValue.cpp
new file mode 100644
index 000000000..18b0ded67
--- /dev/null
+++ b/Source/WebCore/css/CSSAspectRatioValue.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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:
+ *
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "CSSAspectRatioValue.h"
+
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+String CSSAspectRatioValue::customCssText() const
+{
+ StringBuilder result;
+ result.append(String::number(m_numeratorValue));
+ result.append("/");
+ result.append(String::number(m_denominatorValue));
+ return result.toString();
+}
+
+}
diff --git a/Source/WebCore/css/CSSAspectRatioValue.h b/Source/WebCore/css/CSSAspectRatioValue.h
new file mode 100644
index 000000000..2f6b426d8
--- /dev/null
+++ b/Source/WebCore/css/CSSAspectRatioValue.h
@@ -0,0 +1,63 @@
+/*
+ * 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:
+ *
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 CSSAspectRatioValue_h
+#define CSSAspectRatioValue_h
+
+#include "CSSPrimitiveValue.h"
+#include "CSSValue.h"
+
+namespace WebCore {
+
+class CSSAspectRatioValue : public CSSValue {
+public:
+ static PassRefPtr<CSSAspectRatioValue> create(float numeratorValue, float denominatorValue)
+ {
+ return adoptRef(new CSSAspectRatioValue(numeratorValue, denominatorValue));
+ }
+
+ String customCssText() const;
+
+ float numeratorValue() const { return m_numeratorValue; }
+ float denominatorValue() const { return m_denominatorValue; }
+
+private:
+ CSSAspectRatioValue(float numeratorValue, float denominatorValue)
+ : CSSValue(AspectRatioClass)
+ , m_numeratorValue(numeratorValue)
+ , m_denominatorValue(denominatorValue)
+ {
+ }
+
+ float m_numeratorValue;
+ float m_denominatorValue;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSBorderImageSliceValue.cpp b/Source/WebCore/css/CSSBorderImageSliceValue.cpp
new file mode 100644
index 000000000..04ef2d366
--- /dev/null
+++ b/Source/WebCore/css/CSSBorderImageSliceValue.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+#include "CSSBorderImageSliceValue.h"
+
+#include "PlatformString.h"
+#include "Rect.h"
+
+namespace WebCore {
+
+CSSBorderImageSliceValue::CSSBorderImageSliceValue(PassRefPtr<CSSPrimitiveValue> slices, bool fill)
+ : CSSValue(BorderImageSliceClass)
+ , m_slices(slices)
+ , m_fill(fill)
+{
+}
+
+String CSSBorderImageSliceValue::customCssText() const
+{
+ // Dump the slices first.
+ String text = m_slices->cssText();
+
+ // Now the fill keywords if it is present.
+ if (m_fill)
+ text += " fill";
+ return text;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSBorderImageSliceValue.h b/Source/WebCore/css/CSSBorderImageSliceValue.h
new file mode 100644
index 000000000..d8230f474
--- /dev/null
+++ b/Source/WebCore/css/CSSBorderImageSliceValue.h
@@ -0,0 +1,59 @@
+/*
+ * 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 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 CSSBorderImageSliceValue_h
+#define CSSBorderImageSliceValue_h
+
+#include "CSSPrimitiveValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Rect;
+
+class CSSBorderImageSliceValue : public CSSValue {
+public:
+ static PassRefPtr<CSSBorderImageSliceValue> create(PassRefPtr<CSSPrimitiveValue> slices, bool fill)
+ {
+ return adoptRef(new CSSBorderImageSliceValue(slices, fill));
+ }
+
+ String customCssText() const;
+
+ Quad* slices() { return m_slices ? m_slices->getQuadValue() : 0; }
+
+ // These four values are used to make "cuts" in the border image. They can be numbers
+ // or percentages.
+ RefPtr<CSSPrimitiveValue> m_slices;
+ bool m_fill;
+
+private:
+ CSSBorderImageSliceValue(PassRefPtr<CSSPrimitiveValue> slices, bool fill);
+};
+
+} // namespace WebCore
+
+#endif // CSSBorderImageSliceValue_h
diff --git a/Source/WebCore/css/CSSBorderImageValue.cpp b/Source/WebCore/css/CSSBorderImageValue.cpp
new file mode 100644
index 000000000..846ea6dc5
--- /dev/null
+++ b/Source/WebCore/css/CSSBorderImageValue.cpp
@@ -0,0 +1,81 @@
+/*
+ * (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
new file mode 100644
index 000000000..675758cc3
--- /dev/null
+++ b/Source/WebCore/css/CSSBorderImageValue.h
@@ -0,0 +1,70 @@
+/*
+ * (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/CSSCanvasValue.cpp b/Source/WebCore/css/CSSCanvasValue.cpp
new file mode 100644
index 000000000..783ceef82
--- /dev/null
+++ b/Source/WebCore/css/CSSCanvasValue.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008 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 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.
+ */
+
+#include "config.h"
+#include "CSSCanvasValue.h"
+
+#include "ImageBuffer.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+CSSCanvasValue::~CSSCanvasValue()
+{
+ if (m_element)
+ m_element->removeObserver(&m_canvasObserver);
+}
+
+String CSSCanvasValue::customCssText() const
+{
+ String result = "-webkit-canvas(";
+ result += m_name + ")";
+ return result;
+}
+
+void CSSCanvasValue::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect)
+{
+ IntRect imageChangeRect = enclosingIntRect(changedRect);
+ RenderObjectSizeCountMap::const_iterator end = clients().end();
+ for (RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr)
+ const_cast<RenderObject*>(curr->first)->imageChanged(static_cast<WrappedImagePtr>(this), &imageChangeRect);
+}
+
+void CSSCanvasValue::canvasResized(HTMLCanvasElement*)
+{
+ RenderObjectSizeCountMap::const_iterator end = clients().end();
+ for (RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr)
+ const_cast<RenderObject*>(curr->first)->imageChanged(static_cast<WrappedImagePtr>(this));
+}
+
+void CSSCanvasValue::canvasDestroyed(HTMLCanvasElement* element)
+{
+ ASSERT_UNUSED(element, element == m_element);
+ m_element = 0;
+}
+
+IntSize CSSCanvasValue::fixedSize(const RenderObject* renderer)
+{
+ if (HTMLCanvasElement* elt = element(renderer->document()))
+ return IntSize(elt->width(), elt->height());
+ return IntSize();
+}
+
+HTMLCanvasElement* CSSCanvasValue::element(Document* document)
+{
+ if (!m_element) {
+ m_element = document->getCSSCanvasElement(m_name);
+ if (!m_element)
+ return 0;
+ m_element->addObserver(&m_canvasObserver);
+ }
+ return m_element;
+}
+
+PassRefPtr<Image> CSSCanvasValue::image(RenderObject* renderer, const IntSize& /*size*/)
+{
+ ASSERT(clients().contains(renderer));
+ HTMLCanvasElement* elt = element(renderer->document());
+ if (!elt || !elt->buffer())
+ return 0;
+ return elt->copiedImage();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSCanvasValue.h b/Source/WebCore/css/CSSCanvasValue.h
new file mode 100644
index 000000000..efad7e692
--- /dev/null
+++ b/Source/WebCore/css/CSSCanvasValue.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2008 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 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 CSSCanvasValue_h
+#define CSSCanvasValue_h
+
+#include "CSSImageGeneratorValue.h"
+#include "HTMLCanvasElement.h"
+
+namespace WebCore {
+
+class Document;
+
+class CSSCanvasValue : public CSSImageGeneratorValue {
+public:
+ static PassRefPtr<CSSCanvasValue> create() { return adoptRef(new CSSCanvasValue); }
+ ~CSSCanvasValue();
+
+ String customCssText() const;
+
+ PassRefPtr<Image> image(RenderObject*, const IntSize&);
+ bool isFixedSize() const { return true; }
+ IntSize fixedSize(const RenderObject*);
+
+ bool isPending() const { return false; }
+ void loadSubimages(CachedResourceLoader*) { }
+
+ void setName(const String& name) { m_name = name; }
+
+private:
+ CSSCanvasValue()
+ : CSSImageGeneratorValue(CanvasClass)
+ , m_canvasObserver(this)
+ , m_element(0)
+ {
+ }
+
+ // NOTE: We put the CanvasObserver in a member instead of inheriting from it
+ // to avoid adding a vptr to CSSCanvasValue.
+ class CanvasObserverProxy : public CanvasObserver {
+ public:
+ CanvasObserverProxy(CSSCanvasValue* ownerValue) : m_ownerValue(ownerValue) { }
+ virtual ~CanvasObserverProxy() { }
+ virtual void canvasChanged(HTMLCanvasElement* canvas, const FloatRect& changedRect)
+ {
+ m_ownerValue->canvasChanged(canvas, changedRect);
+ }
+ virtual void canvasResized(HTMLCanvasElement* canvas)
+ {
+ m_ownerValue->canvasResized(canvas);
+ }
+ virtual void canvasDestroyed(HTMLCanvasElement* canvas)
+ {
+ m_ownerValue->canvasDestroyed(canvas);
+ }
+ private:
+ CSSCanvasValue* m_ownerValue;
+ };
+
+ void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect);
+ void canvasResized(HTMLCanvasElement*);
+ void canvasDestroyed(HTMLCanvasElement*);
+
+ HTMLCanvasElement* element(Document*);
+
+ CanvasObserverProxy m_canvasObserver;
+
+ // The name of the canvas.
+ String m_name;
+ // The document supplies the element and owns it.
+ HTMLCanvasElement* m_element;
+};
+
+} // namespace WebCore
+
+#endif // CSSCanvasValue_h
diff --git a/Source/WebCore/css/CSSCharsetRule.cpp b/Source/WebCore/css/CSSCharsetRule.cpp
new file mode 100644
index 000000000..b7a77ac52
--- /dev/null
+++ b/Source/WebCore/css/CSSCharsetRule.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@macrules.ru)
+ *
+ * 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 "CSSCharsetRule.h"
+
+namespace WebCore {
+
+CSSCharsetRule::CSSCharsetRule(CSSStyleSheet* parent, const String& encoding)
+ : CSSRule(parent, CSSRule::CHARSET_RULE)
+ , m_encoding(encoding)
+{
+}
+
+String CSSCharsetRule::cssText() const
+{
+ return "@charset \"" + m_encoding + "\";";
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSCharsetRule.h b/Source/WebCore/css/CSSCharsetRule.h
new file mode 100644
index 000000000..d08efa7df
--- /dev/null
+++ b/Source/WebCore/css/CSSCharsetRule.h
@@ -0,0 +1,50 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 CSSCharsetRule_h
+#define CSSCharsetRule_h
+
+#include "CSSRule.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class CSSCharsetRule : public CSSRule {
+public:
+ static PassRefPtr<CSSCharsetRule> create(CSSStyleSheet* parent, const String& encoding)
+ {
+ return adoptRef(new CSSCharsetRule(parent, encoding));
+ }
+
+ const String& encoding() const { return m_encoding; }
+ void setEncoding(const String& encoding, ExceptionCode&) { m_encoding = encoding; }
+
+ String cssText() const;
+
+private:
+ CSSCharsetRule(CSSStyleSheet* parent, const String& encoding);
+
+ String m_encoding;
+};
+
+} // namespace WebCore
+
+#endif // CSSCharsetRule_h
diff --git a/Source/WebCore/css/CSSCharsetRule.idl b/Source/WebCore/css/CSSCharsetRule.idl
new file mode 100644
index 000000000..2b158ff8b
--- /dev/null
+++ b/Source/WebCore/css/CSSCharsetRule.idl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSCharsetRule : CSSRule {
+#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
+ readonly attribute [ConvertNullStringTo=Null] DOMString encoding;
+#else
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString encoding
+ setter raises(DOMException);
+#endif
+ };
+
+}
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
new file mode 100644
index 000000000..3e0dc8c21
--- /dev/null
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
@@ -0,0 +1,2464 @@
+/*
+ * Copyright (C) 2004 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
+ * Copyright (C) 2011 Sencha, Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+#include "CSSComputedStyleDeclaration.h"
+
+#include "AnimationController.h"
+#include "CSSAspectRatioValue.h"
+#include "CSSBorderImageValue.h"
+#include "CSSLineBoxContainValue.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSPrimitiveValueMappings.h"
+#include "CSSProperty.h"
+#include "CSSPropertyNames.h"
+#include "CSSReflectValue.h"
+#include "CSSSelector.h"
+#include "CSSTimingFunctionValue.h"
+#include "CSSValueList.h"
+#include "CSSValuePool.h"
+#include "ContentData.h"
+#include "CounterContent.h"
+#include "CursorList.h"
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterOperation.h"
+#endif
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "FontFeatureSettings.h"
+#include "FontFeatureValue.h"
+#include "FontValue.h"
+#include "Pair.h"
+#include "Rect.h"
+#include "RenderBox.h"
+#include "RenderLayer.h"
+#include "RenderStyle.h"
+#include "ShadowValue.h"
+#if ENABLE(CSS_FILTERS)
+#include "WebKitCSSFilterValue.h"
+#endif
+#include "WebKitCSSTransformValue.h"
+#include "WebKitFontFamilyNames.h"
+
+#if ENABLE(DASHBOARD_SUPPORT)
+#include "DashboardRegion.h"
+#endif
+
+namespace WebCore {
+
+// List of all properties we know how to compute, omitting shorthands.
+static const int computedProperties[] = {
+ CSSPropertyBackgroundAttachment,
+ CSSPropertyBackgroundClip,
+ CSSPropertyBackgroundColor,
+ CSSPropertyBackgroundImage,
+ CSSPropertyBackgroundOrigin,
+ CSSPropertyBackgroundPosition, // more-specific background-position-x/y are non-standard
+ CSSPropertyBackgroundRepeat,
+ CSSPropertyBackgroundSize,
+ CSSPropertyBorderBottomColor,
+ CSSPropertyBorderBottomLeftRadius,
+ CSSPropertyBorderBottomRightRadius,
+ CSSPropertyBorderBottomStyle,
+ CSSPropertyBorderBottomWidth,
+ CSSPropertyBorderCollapse,
+ CSSPropertyBorderImageOutset,
+ CSSPropertyBorderImageRepeat,
+ CSSPropertyBorderImageSlice,
+ CSSPropertyBorderImageSource,
+ CSSPropertyBorderImageWidth,
+ CSSPropertyBorderLeftColor,
+ CSSPropertyBorderLeftStyle,
+ CSSPropertyBorderLeftWidth,
+ CSSPropertyBorderRightColor,
+ CSSPropertyBorderRightStyle,
+ CSSPropertyBorderRightWidth,
+ CSSPropertyBorderTopColor,
+ CSSPropertyBorderTopLeftRadius,
+ CSSPropertyBorderTopRightRadius,
+ CSSPropertyBorderTopStyle,
+ CSSPropertyBorderTopWidth,
+ CSSPropertyBottom,
+ CSSPropertyBoxShadow,
+ CSSPropertyBoxSizing,
+ CSSPropertyCaptionSide,
+ CSSPropertyClear,
+ CSSPropertyClip,
+ CSSPropertyColor,
+ CSSPropertyCursor,
+ CSSPropertyDirection,
+ CSSPropertyDisplay,
+ CSSPropertyEmptyCells,
+ CSSPropertyFloat,
+ CSSPropertyFontFamily,
+ CSSPropertyFontSize,
+ CSSPropertyFontStyle,
+ CSSPropertyFontVariant,
+ CSSPropertyFontWeight,
+ CSSPropertyHeight,
+ CSSPropertyImageRendering,
+ CSSPropertyLeft,
+ CSSPropertyLetterSpacing,
+ CSSPropertyLineHeight,
+ CSSPropertyListStyleImage,
+ CSSPropertyListStylePosition,
+ CSSPropertyListStyleType,
+ CSSPropertyMarginBottom,
+ CSSPropertyMarginLeft,
+ CSSPropertyMarginRight,
+ CSSPropertyMarginTop,
+ CSSPropertyMaxHeight,
+ CSSPropertyMaxWidth,
+ CSSPropertyMinHeight,
+ CSSPropertyMinWidth,
+ CSSPropertyOpacity,
+ CSSPropertyOrphans,
+ CSSPropertyOutlineColor,
+ CSSPropertyOutlineStyle,
+ CSSPropertyOutlineWidth,
+ CSSPropertyOverflowX,
+ CSSPropertyOverflowY,
+ CSSPropertyPaddingBottom,
+ CSSPropertyPaddingLeft,
+ CSSPropertyPaddingRight,
+ CSSPropertyPaddingTop,
+ CSSPropertyPageBreakAfter,
+ CSSPropertyPageBreakBefore,
+ CSSPropertyPageBreakInside,
+ CSSPropertyPointerEvents,
+ CSSPropertyPosition,
+ CSSPropertyResize,
+ CSSPropertyRight,
+ CSSPropertySpeak,
+ CSSPropertyTableLayout,
+ CSSPropertyTextAlign,
+ CSSPropertyTextDecoration,
+ CSSPropertyTextIndent,
+ CSSPropertyTextRendering,
+ CSSPropertyTextShadow,
+ CSSPropertyTextOverflow,
+ CSSPropertyTextTransform,
+ CSSPropertyTop,
+ CSSPropertyUnicodeBidi,
+ CSSPropertyVerticalAlign,
+ CSSPropertyVisibility,
+ CSSPropertyWhiteSpace,
+ CSSPropertyWidows,
+ CSSPropertyWidth,
+ CSSPropertyWordBreak,
+ CSSPropertyWordSpacing,
+ CSSPropertyWordWrap,
+ CSSPropertyZIndex,
+ CSSPropertyZoom,
+
+ CSSPropertyWebkitAnimationDelay,
+ CSSPropertyWebkitAnimationDirection,
+ CSSPropertyWebkitAnimationDuration,
+ CSSPropertyWebkitAnimationFillMode,
+ CSSPropertyWebkitAnimationIterationCount,
+ CSSPropertyWebkitAnimationName,
+ CSSPropertyWebkitAnimationPlayState,
+ CSSPropertyWebkitAnimationTimingFunction,
+ CSSPropertyWebkitAppearance,
+ CSSPropertyWebkitBackfaceVisibility,
+ CSSPropertyWebkitBackgroundClip,
+ CSSPropertyWebkitBackgroundComposite,
+ CSSPropertyWebkitBackgroundOrigin,
+ CSSPropertyWebkitBackgroundSize,
+ CSSPropertyWebkitBorderFit,
+ CSSPropertyWebkitBorderHorizontalSpacing,
+ CSSPropertyWebkitBorderImage,
+ CSSPropertyWebkitBorderVerticalSpacing,
+ CSSPropertyWebkitBoxAlign,
+ CSSPropertyWebkitBoxDirection,
+ CSSPropertyWebkitBoxFlex,
+ CSSPropertyWebkitBoxFlexGroup,
+ CSSPropertyWebkitBoxLines,
+ CSSPropertyWebkitBoxOrdinalGroup,
+ CSSPropertyWebkitBoxOrient,
+ CSSPropertyWebkitBoxPack,
+ CSSPropertyWebkitBoxReflect,
+ CSSPropertyWebkitBoxShadow,
+ CSSPropertyWebkitColorCorrection,
+ CSSPropertyWebkitColumnBreakAfter,
+ CSSPropertyWebkitColumnBreakBefore,
+ CSSPropertyWebkitColumnBreakInside,
+ CSSPropertyWebkitColumnAxis,
+ CSSPropertyWebkitColumnCount,
+ CSSPropertyWebkitColumnGap,
+ CSSPropertyWebkitColumnRuleColor,
+ CSSPropertyWebkitColumnRuleStyle,
+ CSSPropertyWebkitColumnRuleWidth,
+ CSSPropertyWebkitColumnSpan,
+ CSSPropertyWebkitColumnWidth,
+#if ENABLE(DASHBOARD_SUPPORT)
+ CSSPropertyWebkitDashboardRegion,
+#endif
+ CSSPropertyWebkitFlexOrder,
+ CSSPropertyWebkitFlexPack,
+ CSSPropertyWebkitFlexAlign,
+ CSSPropertyWebkitFlexDirection,
+ CSSPropertyWebkitFlexFlow,
+ CSSPropertyWebkitFlexWrap,
+ CSSPropertyWebkitFontSmoothing,
+#if ENABLE(CSS_GRID_LAYOUT)
+ CSSPropertyWebkitGridColumns,
+ CSSPropertyWebkitGridRows,
+#endif
+ CSSPropertyWebkitHighlight,
+ CSSPropertyWebkitHyphenateCharacter,
+ CSSPropertyWebkitHyphenateLimitAfter,
+ CSSPropertyWebkitHyphenateLimitBefore,
+ CSSPropertyWebkitHyphenateLimitLines,
+ CSSPropertyWebkitHyphens,
+ CSSPropertyWebkitLineBoxContain,
+ CSSPropertyWebkitLineBreak,
+ CSSPropertyWebkitLineClamp,
+ CSSPropertyWebkitLineGrid,
+ CSSPropertyWebkitLineGridSnap,
+ CSSPropertyWebkitLocale,
+ CSSPropertyWebkitMarginBeforeCollapse,
+ CSSPropertyWebkitMarginAfterCollapse,
+ CSSPropertyWebkitMarqueeDirection,
+ CSSPropertyWebkitMarqueeIncrement,
+ CSSPropertyWebkitMarqueeRepetition,
+ CSSPropertyWebkitMarqueeStyle,
+ CSSPropertyWebkitMaskAttachment,
+ CSSPropertyWebkitMaskBoxImage,
+ CSSPropertyWebkitMaskBoxImageOutset,
+ CSSPropertyWebkitMaskBoxImageRepeat,
+ CSSPropertyWebkitMaskBoxImageSlice,
+ CSSPropertyWebkitMaskBoxImageSource,
+ CSSPropertyWebkitMaskBoxImageWidth,
+ CSSPropertyWebkitMaskClip,
+ CSSPropertyWebkitMaskComposite,
+ CSSPropertyWebkitMaskImage,
+ CSSPropertyWebkitMaskOrigin,
+ CSSPropertyWebkitMaskPosition,
+ CSSPropertyWebkitMaskRepeat,
+ CSSPropertyWebkitMaskSize,
+ CSSPropertyWebkitNbspMode,
+ CSSPropertyWebkitPerspective,
+ CSSPropertyWebkitPerspectiveOrigin,
+ CSSPropertyWebkitPrintColorAdjust,
+ CSSPropertyWebkitRtlOrdering,
+#if ENABLE(TOUCH_EVENTS)
+ CSSPropertyWebkitTapHighlightColor,
+#endif
+ CSSPropertyWebkitTextCombine,
+ CSSPropertyWebkitTextDecorationsInEffect,
+ CSSPropertyWebkitTextEmphasisColor,
+ CSSPropertyWebkitTextEmphasisPosition,
+ CSSPropertyWebkitTextEmphasisStyle,
+ CSSPropertyWebkitTextFillColor,
+ CSSPropertyWebkitTextOrientation,
+ CSSPropertyWebkitTextSecurity,
+ CSSPropertyWebkitTextStrokeColor,
+ CSSPropertyWebkitTextStrokeWidth,
+ CSSPropertyWebkitTransform,
+ CSSPropertyWebkitTransformOrigin,
+ CSSPropertyWebkitTransformStyle,
+ CSSPropertyWebkitTransitionDelay,
+ CSSPropertyWebkitTransitionDuration,
+ CSSPropertyWebkitTransitionProperty,
+ CSSPropertyWebkitTransitionTimingFunction,
+ CSSPropertyWebkitUserDrag,
+ CSSPropertyWebkitUserModify,
+ CSSPropertyWebkitUserSelect,
+ CSSPropertyWebkitWritingMode,
+ CSSPropertyWebkitFlowInto,
+ CSSPropertyWebkitFlowFrom,
+ CSSPropertyWebkitRegionOverflow,
+ CSSPropertyWebkitRegionBreakAfter,
+ CSSPropertyWebkitRegionBreakBefore,
+ CSSPropertyWebkitRegionBreakInside,
+ CSSPropertyWebkitWrapFlow,
+ CSSPropertyWebkitWrapMargin,
+ CSSPropertyWebkitWrapPadding,
+ CSSPropertyWebkitWrapThrough
+#if ENABLE(SVG)
+ ,
+ CSSPropertyClipPath,
+ CSSPropertyClipRule,
+ CSSPropertyMask,
+ CSSPropertyFilter,
+ CSSPropertyFloodColor,
+ CSSPropertyFloodOpacity,
+ CSSPropertyLightingColor,
+ CSSPropertyStopColor,
+ CSSPropertyStopOpacity,
+ CSSPropertyColorInterpolation,
+ CSSPropertyColorInterpolationFilters,
+ CSSPropertyColorRendering,
+ CSSPropertyFill,
+ CSSPropertyFillOpacity,
+ CSSPropertyFillRule,
+ CSSPropertyMarkerEnd,
+ CSSPropertyMarkerMid,
+ CSSPropertyMarkerStart,
+ CSSPropertyShapeRendering,
+ CSSPropertyStroke,
+ CSSPropertyStrokeDasharray,
+ CSSPropertyStrokeDashoffset,
+ CSSPropertyStrokeLinecap,
+ CSSPropertyStrokeLinejoin,
+ CSSPropertyStrokeMiterlimit,
+ CSSPropertyStrokeOpacity,
+ CSSPropertyStrokeWidth,
+ CSSPropertyAlignmentBaseline,
+ CSSPropertyBaselineShift,
+ CSSPropertyDominantBaseline,
+ CSSPropertyKerning,
+ CSSPropertyTextAnchor,
+ CSSPropertyWritingMode,
+ CSSPropertyGlyphOrientationHorizontal,
+ CSSPropertyGlyphOrientationVertical,
+ CSSPropertyWebkitSvgShadow,
+ CSSPropertyVectorEffect
+#endif
+};
+
+const unsigned numComputedProperties = WTF_ARRAY_LENGTH(computedProperties);
+
+static int valueForRepeatRule(int rule)
+{
+ switch (rule) {
+ case RepeatImageRule:
+ return CSSValueRepeat;
+ case RoundImageRule:
+ return CSSValueRound;
+ case SpaceImageRule:
+ return CSSValueSpace;
+ default:
+ return CSSValueStretch;
+ }
+}
+
+static PassRefPtr<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image, CSSValuePool* cssValuePool)
+{
+ // Create the slices.
+ RefPtr<CSSPrimitiveValue> top;
+ RefPtr<CSSPrimitiveValue> right;
+ RefPtr<CSSPrimitiveValue> bottom;
+ RefPtr<CSSPrimitiveValue> left;
+
+ if (image.imageSlices().top().isPercent())
+ top = cssValuePool->createValue(image.imageSlices().top().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ else
+ top = cssValuePool->createValue(image.imageSlices().top().value(), CSSPrimitiveValue::CSS_NUMBER);
+
+ if (image.imageSlices().right() == image.imageSlices().top() && image.imageSlices().bottom() == image.imageSlices().top()
+ && image.imageSlices().left() == image.imageSlices().top()) {
+ right = top;
+ bottom = top;
+ left = top;
+ } else {
+ if (image.imageSlices().right().isPercent())
+ right = cssValuePool->createValue(image.imageSlices().right().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ else
+ right = cssValuePool->createValue(image.imageSlices().right().value(), CSSPrimitiveValue::CSS_NUMBER);
+
+ if (image.imageSlices().bottom() == image.imageSlices().top() && image.imageSlices().right() == image.imageSlices().left()) {
+ bottom = top;
+ left = right;
+ } else {
+ if (image.imageSlices().bottom().isPercent())
+ bottom = cssValuePool->createValue(image.imageSlices().bottom().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ else
+ bottom = cssValuePool->createValue(image.imageSlices().bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
+
+ if (image.imageSlices().left() == image.imageSlices().right())
+ left = right;
+ else {
+ if (image.imageSlices().left().isPercent())
+ left = cssValuePool->createValue(image.imageSlices().left().value(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ else
+ left = cssValuePool->createValue(image.imageSlices().left().value(), CSSPrimitiveValue::CSS_NUMBER);
+ }
+ }
+ }
+
+ RefPtr<Quad> quad = Quad::create();
+ quad->setTop(top);
+ quad->setRight(right);
+ quad->setBottom(bottom);
+ quad->setLeft(left);
+
+ return CSSBorderImageSliceValue::create(cssValuePool->createValue(quad.release()), image.fill());
+}
+
+static PassRefPtr<CSSPrimitiveValue> valueForNinePieceImageQuad(const LengthBox& box, CSSValuePool* cssValuePool)
+{
+ // Create the slices.
+ RefPtr<CSSPrimitiveValue> top;
+ RefPtr<CSSPrimitiveValue> right;
+ RefPtr<CSSPrimitiveValue> bottom;
+ RefPtr<CSSPrimitiveValue> left;
+
+ if (box.top().isRelative())
+ top = cssValuePool->createValue(box.top().value(), CSSPrimitiveValue::CSS_NUMBER);
+ else
+ top = cssValuePool->createValue(box.top());
+
+ if (box.right() == box.top() && box.bottom() == box.top() && box.left() == box.top()) {
+ right = top;
+ bottom = top;
+ left = top;
+ } else {
+ if (box.right().isRelative())
+ right = cssValuePool->createValue(box.right().value(), CSSPrimitiveValue::CSS_NUMBER);
+ else
+ right = cssValuePool->createValue(box.right());
+
+ if (box.bottom() == box.top() && box.right() == box.left()) {
+ bottom = top;
+ left = right;
+ } else {
+ if (box.bottom().isRelative())
+ bottom = cssValuePool->createValue(box.bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
+ else
+ bottom = cssValuePool->createValue(box.bottom());
+
+ if (box.left() == box.right())
+ left = right;
+ else {
+ if (box.left().isRelative())
+ left = cssValuePool->createValue(box.left().value(), CSSPrimitiveValue::CSS_NUMBER);
+ else
+ left = cssValuePool->createValue(box.left());
+ }
+ }
+ }
+
+ RefPtr<Quad> quad = Quad::create();
+ quad->setTop(top);
+ quad->setRight(right);
+ quad->setBottom(bottom);
+ quad->setLeft(left);
+
+ return cssValuePool->createValue(quad.release());
+}
+
+static PassRefPtr<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSPrimitiveValue> horizontalRepeat;
+ RefPtr<CSSPrimitiveValue> verticalRepeat;
+
+ horizontalRepeat = cssValuePool->createIdentifierValue(valueForRepeatRule(image.horizontalRule()));
+ if (image.horizontalRule() == image.verticalRule())
+ verticalRepeat = horizontalRepeat;
+ else
+ verticalRepeat = cssValuePool->createIdentifierValue(valueForRepeatRule(image.verticalRule()));
+ return cssValuePool->createValue(Pair::create(horizontalRepeat.release(), verticalRepeat.release()));
+}
+
+static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, CSSValuePool* cssValuePool)
+{
+ if (!image.hasImage())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ // Image first.
+ RefPtr<CSSValue> imageValue;
+ if (image.image())
+ imageValue = image.image()->cssValue();
+
+ // Create the image slice.
+ RefPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image, cssValuePool);
+
+ // Create the border area slices.
+ RefPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices(), cssValuePool);
+
+ // Create the border outset.
+ RefPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset(), cssValuePool);
+
+ // Create the repeat rules.
+ RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image, cssValuePool);
+
+ return CSSBorderImageValue::create(imageValue.release(), imageSlices.release(), borderSlices.release(), outset.release(), repeat);
+}
+
+inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(int value, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ return cssValuePool->createValue(adjustForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX);
+}
+
+inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ return cssValuePool->createValue(value / style->effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER);
+}
+
+static PassRefPtr<CSSValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ if (length.isFixed())
+ return zoomAdjustedPixelValue(length.value(), style, cssValuePool);
+ return cssValuePool->createValue(length);
+}
+
+static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ if (!reflection)
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ RefPtr<CSSPrimitiveValue> offset;
+ if (reflection->offset().isPercent())
+ offset = cssValuePool->createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ else
+ offset = zoomAdjustedPixelValue(reflection->offset().value(), style, cssValuePool);
+
+ return CSSReflectValue::create(reflection->direction(), offset.release(), valueForNinePieceImage(reflection->mask(), cssValuePool));
+}
+
+static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, int propertyID, CSSValuePool* cssValuePool)
+{
+ if (!style)
+ return 0;
+
+ Length l;
+ switch (propertyID) {
+ case CSSPropertyLeft:
+ l = style->left();
+ break;
+ case CSSPropertyRight:
+ l = style->right();
+ break;
+ case CSSPropertyTop:
+ l = style->top();
+ break;
+ case CSSPropertyBottom:
+ l = style->bottom();
+ break;
+ default:
+ return 0;
+ }
+
+ if (style->position() == AbsolutePosition || style->position() == FixedPosition) {
+ if (l.type() == WebCore::Fixed)
+ return zoomAdjustedPixelValue(l.value(), style, cssValuePool);
+ return cssValuePool->createValue(l);
+ }
+
+ if (style->position() == RelativePosition)
+ // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
+ // In other words if left is auto and right is not auto, then left's computed value is negative right().
+ // So we should get the opposite length unit and see if it is auto.
+ return cssValuePool->createValue(l);
+
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+}
+
+PassRefPtr<CSSPrimitiveValue> CSSComputedStyleDeclaration::currentColorOrValidColor(RenderStyle* style, const Color& color) const
+{
+ // This function does NOT look at visited information, so that computed style doesn't expose that.
+ CSSValuePool* cssValuePool = m_node->document()->cssValuePool().get();
+ if (!color.isValid())
+ return cssValuePool->createColorValue(style->color().rgb());
+ return cssValuePool->createColorValue(color.rgb());
+}
+
+static PassRefPtr<CSSValue> getBorderRadiusCornerValue(LengthSize radius, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ if (radius.width() == radius.height()) {
+ if (radius.width().type() == Percent)
+ return cssValuePool->createValue(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
+ return zoomAdjustedPixelValue(radius.width().value(), style, cssValuePool);
+ }
+ if (radius.width().type() == Percent)
+ list->append(cssValuePool->createValue(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE));
+ else
+ list->append(zoomAdjustedPixelValue(radius.width().value(), style, cssValuePool));
+ if (radius.height().type() == Percent)
+ list->append(cssValuePool->createValue(radius.height().percent(), CSSPrimitiveValue::CSS_PERCENTAGE));
+ else
+ list->append(zoomAdjustedPixelValue(radius.height().value(), style, cssValuePool));
+ return list.release();
+}
+
+static LayoutRect sizingBox(RenderObject* renderer)
+{
+ if (!renderer->isBox())
+ return LayoutRect();
+
+ RenderBox* box = toRenderBox(renderer);
+ return box->style()->boxSizing() == CONTENT_BOX ? box->contentBoxRect() : box->borderBoxRect();
+}
+
+static inline bool hasCompositedLayer(RenderObject* renderer)
+{
+ return renderer && renderer->hasLayer() && toRenderBoxModelObject(renderer)->layer()->isComposited();
+}
+
+static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ if (!renderer || style->transform().operations().isEmpty())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ IntRect box = sizingBox(renderer);
+
+ TransformationMatrix transform;
+ style->applyTransform(transform, box.size(), RenderStyle::ExcludeTransformOrigin);
+ // Note that this does not flatten to an affine transform if ENABLE(3D_RENDERING) is off, by design.
+
+ RefPtr<WebKitCSSTransformValue> transformVal;
+
+ // FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924)
+ if (transform.isAffine()) {
+ transformVal = WebKitCSSTransformValue::create(WebKitCSSTransformValue::MatrixTransformOperation);
+
+ transformVal->append(cssValuePool->createValue(transform.a(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.b(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.c(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.d(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(zoomAdjustedNumberValue(transform.e(), style, cssValuePool));
+ transformVal->append(zoomAdjustedNumberValue(transform.f(), style, cssValuePool));
+ } else {
+ transformVal = WebKitCSSTransformValue::create(WebKitCSSTransformValue::Matrix3DTransformOperation);
+
+ transformVal->append(cssValuePool->createValue(transform.m11(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m12(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m13(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m14(), CSSPrimitiveValue::CSS_NUMBER));
+
+ transformVal->append(cssValuePool->createValue(transform.m21(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m22(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m23(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m24(), CSSPrimitiveValue::CSS_NUMBER));
+
+ transformVal->append(cssValuePool->createValue(transform.m31(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m32(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m33(), CSSPrimitiveValue::CSS_NUMBER));
+ transformVal->append(cssValuePool->createValue(transform.m34(), CSSPrimitiveValue::CSS_NUMBER));
+
+ transformVal->append(zoomAdjustedNumberValue(transform.m41(), style, cssValuePool));
+ transformVal->append(zoomAdjustedNumberValue(transform.m42(), style, cssValuePool));
+ transformVal->append(zoomAdjustedNumberValue(transform.m43(), style, cssValuePool));
+ transformVal->append(cssValuePool->createValue(transform.m44(), CSSPrimitiveValue::CSS_NUMBER));
+ }
+
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(transformVal);
+
+ return list.release();
+}
+
+#if ENABLE(CSS_FILTERS)
+PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(RenderStyle* style) const
+{
+ CSSValuePool* cssValuePool = m_node->document()->cssValuePool().get();
+
+ if (style->filter().operations().isEmpty())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+
+ RefPtr<WebKitCSSFilterValue> filterValue;
+
+ Vector<RefPtr<FilterOperation> >::const_iterator end = style->filter().operations().end();
+ for (Vector<RefPtr<FilterOperation> >::const_iterator it = style->filter().operations().begin(); it != end; ++it) {
+ FilterOperation* filterOperation = (*it).get();
+ switch (filterOperation->getOperationType()) {
+ case FilterOperation::REFERENCE: {
+ ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::ReferenceFilterOperation);
+ filterValue->append(cssValuePool->createValue(referenceOperation->reference(), CSSPrimitiveValue::CSS_STRING));
+ break;
+ }
+ case FilterOperation::GRAYSCALE: {
+ BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::GrayscaleFilterOperation);
+ filterValue->append(cssValuePool->createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::SEPIA: {
+ BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::SepiaFilterOperation);
+ filterValue->append(cssValuePool->createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::SATURATE: {
+ BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::SaturateFilterOperation);
+ filterValue->append(cssValuePool->createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::HUE_ROTATE: {
+ BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::HueRotateFilterOperation);
+ filterValue->append(cssValuePool->createValue(colorMatrixOperation->amount(), CSSPrimitiveValue::CSS_DEG));
+ break;
+ }
+ case FilterOperation::INVERT: {
+ BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::InvertFilterOperation);
+ filterValue->append(cssValuePool->createValue(componentTransferOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::OPACITY: {
+ BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::OpacityFilterOperation);
+ filterValue->append(cssValuePool->createValue(componentTransferOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::BRIGHTNESS: {
+ BasicComponentTransferFilterOperation* brightnessOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::BrightnessFilterOperation);
+ filterValue->append(cssValuePool->createValue(brightnessOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::CONTRAST: {
+ BasicComponentTransferFilterOperation* contrastOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::ContrastFilterOperation);
+ filterValue->append(cssValuePool->createValue(contrastOperation->amount(), CSSPrimitiveValue::CSS_NUMBER));
+ break;
+ }
+ case FilterOperation::BLUR: {
+ BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::BlurFilterOperation);
+ filterValue->append(zoomAdjustedPixelValue(blurOperation->stdDeviation().value(), style, cssValuePool));
+ break;
+ }
+ case FilterOperation::DROP_SHADOW: {
+ DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::DropShadowFilterOperation);
+ // We want our computed style to look like that of a text shadow (has neither spread nor inset style).
+ ShadowData shadowData = ShadowData(dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->stdDeviation(), 0, Normal, false, dropShadowOperation->color());
+ filterValue->append(valueForShadow(&shadowData, CSSPropertyTextShadow, style));
+ break;
+ }
+#if ENABLE(CSS_SHADERS)
+ case FilterOperation::CUSTOM: {
+ CustomFilterOperation* customOperation = static_cast<CustomFilterOperation*>(filterOperation);
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::CustomFilterOperation);
+
+ // The output should be verbose, even if the values are the default ones.
+
+ RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated();
+ if (customOperation->vertexShader())
+ shadersList->append(customOperation->vertexShader()->cssValue());
+ else
+ shadersList->append(cssValuePool->createIdentifierValue(CSSValueNone));
+ if (customOperation->fragmentShader())
+ shadersList->append(customOperation->fragmentShader()->cssValue());
+ else
+ shadersList->append(cssValuePool->createIdentifierValue(CSSValueNone));
+ filterValue->append(shadersList.release());
+
+ RefPtr<CSSValueList> meshParameters = CSSValueList::createSpaceSeparated();
+ meshParameters->append(cssValuePool->createValue(customOperation->meshRows(), CSSPrimitiveValue::CSS_NUMBER));
+ meshParameters->append(cssValuePool->createValue(customOperation->meshColumns(), CSSPrimitiveValue::CSS_NUMBER));
+ meshParameters->append(cssValuePool->createValue(customOperation->meshBoxType()));
+
+ // FIXME: The specification doesn't have any "attached" identifier. Should we add one?
+ // https://bugs.webkit.org/show_bug.cgi?id=72700
+ if (customOperation->meshType() == CustomFilterOperation::DETACHED)
+ meshParameters->append(cssValuePool->createIdentifierValue(CSSValueDetached));
+
+ filterValue->append(meshParameters.release());
+
+ break;
+ }
+#endif
+ default:
+ filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::UnknownFilterOperation);
+ break;
+ }
+ list->append(filterValue);
+ }
+
+ return list.release();
+}
+#endif
+
+#if ENABLE(CSS_GRID_LAYOUT)
+static PassRefPtr<CSSValue> valueForGridTrackBreadth(const Length& trackLength, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ if (trackLength.isPercent())
+ return cssValuePool->createValue(trackLength);
+ if (trackLength.isAuto())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return zoomAdjustedPixelValue(trackLength.value(), style, cssValuePool);
+}
+
+static PassRefPtr<CSSValue> valueForGridTrackList(const Vector<Length>& trackLengths, const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ // We should have at least an element!
+ ASSERT(trackLengths.size());
+
+ // Handle the 'none' case here.
+ if (trackLengths.size() == 1 && trackLengths[0].isUndefined())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (size_t i = 0; i < trackLengths.size(); ++i)
+ list->append(valueForGridTrackBreadth(trackLengths[i], style, cssValuePool));
+ return list.release();
+}
+#endif
+
+static PassRefPtr<CSSValue> getDelayValue(const AnimationList* animList, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ if (animList) {
+ for (size_t i = 0; i < animList->size(); ++i)
+ list->append(cssValuePool->createValue(animList->animation(i)->delay(), CSSPrimitiveValue::CSS_S));
+ } else {
+ // Note that initialAnimationDelay() is used for both transitions and animations
+ list->append(cssValuePool->createValue(Animation::initialAnimationDelay(), CSSPrimitiveValue::CSS_S));
+ }
+ return list.release();
+}
+
+static PassRefPtr<CSSValue> getDurationValue(const AnimationList* animList, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ if (animList) {
+ for (size_t i = 0; i < animList->size(); ++i)
+ list->append(cssValuePool->createValue(animList->animation(i)->duration(), CSSPrimitiveValue::CSS_S));
+ } else {
+ // Note that initialAnimationDuration() is used for both transitions and animations
+ list->append(cssValuePool->createValue(Animation::initialAnimationDuration(), CSSPrimitiveValue::CSS_S));
+ }
+ return list.release();
+}
+
+static PassRefPtr<CSSValue> getTimingFunctionValue(const AnimationList* animList)
+{
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ if (animList) {
+ for (size_t i = 0; i < animList->size(); ++i) {
+ const TimingFunction* tf = animList->animation(i)->timingFunction().get();
+ if (tf->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(tf);
+ list->append(CSSCubicBezierTimingFunctionValue::create(ctf->x1(), ctf->y1(), ctf->x2(), ctf->y2()));
+ } else if (tf->isStepsTimingFunction()) {
+ const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(tf);
+ list->append(CSSStepsTimingFunctionValue::create(stf->numberOfSteps(), stf->stepAtStart()));
+ } else {
+ list->append(CSSLinearTimingFunctionValue::create());
+ }
+ }
+ } else {
+ // Note that initialAnimationTimingFunction() is used for both transitions and animations
+ RefPtr<TimingFunction> tf = Animation::initialAnimationTimingFunction();
+ if (tf->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(tf.get());
+ list->append(CSSCubicBezierTimingFunctionValue::create(ctf->x1(), ctf->y1(), ctf->x2(), ctf->y2()));
+ } else if (tf->isStepsTimingFunction()) {
+ const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(tf.get());
+ list->append(CSSStepsTimingFunctionValue::create(stf->numberOfSteps(), stf->stepAtStart()));
+ } else {
+ list->append(CSSLinearTimingFunctionValue::create());
+ }
+ }
+ return list.release();
+}
+
+static PassRefPtr<CSSValue> createLineBoxContainValue(CSSValuePool* cssValuePool, unsigned lineBoxContain)
+{
+ if (!lineBoxContain)
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return CSSLineBoxContainValue::create(lineBoxContain);
+}
+
+CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n, bool allowVisitedStyle, const String& pseudoElementName)
+ : m_node(n)
+ , m_allowVisitedStyle(allowVisitedStyle)
+{
+ unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0;
+ m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoType(
+ AtomicString(pseudoElementName.substring(nameWithoutColonsStart))));
+}
+
+CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration()
+{
+}
+
+String CSSComputedStyleDeclaration::cssText() const
+{
+ String result("");
+
+ for (unsigned i = 0; i < numComputedProperties; i++) {
+ if (i)
+ result += " ";
+ result += getPropertyName(static_cast<CSSPropertyID>(computedProperties[i]));
+ result += ": ";
+ result += getPropertyValue(computedProperties[i]);
+ result += ";";
+ }
+
+ return result;
+}
+
+void CSSComputedStyleDeclaration::setCssText(const String&, ExceptionCode& ec)
+{
+ ec = NO_MODIFICATION_ALLOWED_ERR;
+}
+
+static int cssIdentifierForFontSizeKeyword(int keywordSize)
+{
+ ASSERT_ARG(keywordSize, keywordSize);
+ ASSERT_ARG(keywordSize, keywordSize <= 8);
+ return CSSValueXxSmall + keywordSize - 1;
+}
+
+PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getFontSizeCSSValuePreferringKeyword() const
+{
+ if (!m_node)
+ return 0;
+
+ m_node->document()->updateLayoutIgnorePendingStylesheets();
+
+ RefPtr<RenderStyle> style = m_node->computedStyle(m_pseudoElementSpecifier);
+ if (!style)
+ return 0;
+
+ CSSValuePool* cssValuePool = m_node->document()->cssValuePool().get();
+
+ if (int keywordSize = style->fontDescription().keywordSize())
+ return cssValuePool->createIdentifierValue(cssIdentifierForFontSizeKeyword(keywordSize));
+
+
+ return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style.get(), cssValuePool);
+}
+
+bool CSSComputedStyleDeclaration::useFixedFontDefaultSize() const
+{
+ if (!m_node)
+ return false;
+
+ RefPtr<RenderStyle> style = m_node->computedStyle(m_pseudoElementSpecifier);
+ if (!style)
+ return false;
+
+ return style->fontDescription().useFixedDefaultSize();
+}
+
+PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadow(const ShadowData* shadow, int id, RenderStyle* style) const
+{
+ CSSValuePool* cssValuePool = m_node->document()->cssValuePool().get();
+ if (!shadow)
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const ShadowData* s = shadow; s; s = s->next()) {
+ RefPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(s->x(), style, cssValuePool);
+ RefPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(s->y(), style, cssValuePool);
+ RefPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(s->blur(), style, cssValuePool);
+ RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? PassRefPtr<CSSPrimitiveValue>() : zoomAdjustedPixelValue(s->spread(), style, cssValuePool);
+ RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || s->style() == Normal ? PassRefPtr<CSSPrimitiveValue>() : cssValuePool->createIdentifierValue(CSSValueInset);
+ RefPtr<CSSPrimitiveValue> color = cssValuePool->createColorValue(s->color().rgb());
+ list->prepend(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
+ }
+ return list.release();
+}
+
+PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int propertyID) const
+{
+ return getPropertyCSSValue(propertyID, UpdateLayout);
+}
+
+static int identifierForFamily(const AtomicString& family)
+{
+ if (family == cursiveFamily)
+ return CSSValueCursive;
+ if (family == fantasyFamily)
+ return CSSValueFantasy;
+ if (family == monospaceFamily)
+ return CSSValueMonospace;
+ if (family == pictographFamily)
+ return CSSValueWebkitPictograph;
+ if (family == sansSerifFamily)
+ return CSSValueSansSerif;
+ if (family == serifFamily)
+ return CSSValueSerif;
+ return 0;
+}
+
+static PassRefPtr<CSSPrimitiveValue> valueForFamily(const AtomicString& family, CSSValuePool* cssValuePool)
+{
+ if (int familyIdentifier = identifierForFamily(family))
+ return cssValuePool->createIdentifierValue(familyIdentifier);
+ return cssValuePool->createValue(family.string(), CSSPrimitiveValue::CSS_STRING);
+}
+
+static PassRefPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ if (textDecoration & UNDERLINE)
+ list->append(cssValuePool->createIdentifierValue(CSSValueUnderline));
+ if (textDecoration & OVERLINE)
+ list->append(cssValuePool->createIdentifierValue(CSSValueOverline));
+ if (textDecoration & LINE_THROUGH)
+ list->append(cssValuePool->createIdentifierValue(CSSValueLineThrough));
+ if (textDecoration & BLINK)
+ list->append(cssValuePool->createIdentifierValue(CSSValueBlink));
+
+ if (!list->length())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return list;
+}
+
+static PassRefPtr<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepeat yRepeat, CSSValuePool* cssValuePool)
+{
+ // For backwards compatibility, if both values are equal, just return one of them. And
+ // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand.
+ if (xRepeat == yRepeat)
+ return cssValuePool->createValue(xRepeat);
+ if (xRepeat == RepeatFill && yRepeat == NoRepeatFill)
+ return cssValuePool->createIdentifierValue(CSSValueRepeatX);
+ if (xRepeat == NoRepeatFill && yRepeat == RepeatFill)
+ return cssValuePool->createIdentifierValue(CSSValueRepeatY);
+
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(cssValuePool->createValue(xRepeat));
+ list->append(cssValuePool->createValue(yRepeat));
+ return list.release();
+}
+
+static PassRefPtr<CSSValue> fillSizeToCSSValue(const FillSize& fillSize, CSSValuePool* cssValuePool)
+{
+ if (fillSize.type == Contain)
+ return cssValuePool->createIdentifierValue(CSSValueContain);
+
+ if (fillSize.type == Cover)
+ return cssValuePool->createIdentifierValue(CSSValueCover);
+
+ if (fillSize.size.height().isAuto())
+ return cssValuePool->createValue(fillSize.size.width());
+
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(cssValuePool->createValue(fillSize.size.width()));
+ list->append(cssValuePool->createValue(fillSize.size.height()));
+ return list.release();
+}
+
+static PassRefPtr<CSSValue> contentToCSSValue(const RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (const ContentData* contentData = style->contentData(); contentData; contentData = contentData->next()) {
+ if (contentData->isCounter()) {
+ const CounterContent* counter = static_cast<const CounterContentData*>(contentData)->counter();
+ ASSERT(counter);
+ list->append(cssValuePool->createValue(counter->identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME));
+ } else if (contentData->isImage()) {
+ const StyleImage* image = static_cast<const ImageContentData*>(contentData)->image();
+ ASSERT(image);
+ list->append(image->cssValue());
+ } else if (contentData->isText())
+ list->append(cssValuePool->createValue(static_cast<const TextContentData*>(contentData)->text(), CSSPrimitiveValue::CSS_STRING));
+ }
+ if (!style->regionThread().isNull())
+ list->append(cssValuePool->createValue(style->regionThread(), CSSPrimitiveValue::CSS_STRING));
+ return list.release();
+}
+
+static PassRefPtr<CSSValue> counterToCSSValue(const RenderStyle* style, int propertyID, CSSValuePool* cssValuePool)
+{
+ const CounterDirectiveMap* map = style->counterDirectives();
+ if (!map)
+ return 0;
+
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (CounterDirectiveMap::const_iterator it = map->begin(); it != map->end(); ++it) {
+ list->append(cssValuePool->createValue(it->first.get(), CSSPrimitiveValue::CSS_STRING));
+ short number = propertyID == CSSPropertyCounterIncrement ? it->second.m_incrementValue : it->second.m_resetValue;
+ list->append(cssValuePool->createValue((double)number, CSSPrimitiveValue::CSS_NUMBER));
+ }
+ return list.release();
+}
+
+static void logUnimplementedPropertyID(int propertyID)
+{
+ DEFINE_STATIC_LOCAL(HashSet<int>, propertyIDSet, ());
+ if (!propertyIDSet.add(propertyID).second)
+ return;
+
+ LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(static_cast<CSSPropertyID>(propertyID)));
+}
+
+static PassRefPtr<CSSValueList> fontFamilyFromStyle(RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ const FontFamily& firstFamily = style->fontDescription().family();
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FontFamily* family = &firstFamily; family; family = family->next())
+ list->append(valueForFamily(family->family(), cssValuePool));
+ return list.release();
+}
+
+static PassRefPtr<CSSPrimitiveValue> lineHeightFromStyle(RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ Length length = style->lineHeight();
+ if (length.isNegative())
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+ if (length.isPercent())
+ // This is imperfect, because it doesn't include the zoom factor and the real computation
+ // for how high to be in pixels does include things like minimum font size and the zoom factor.
+ // On the other hand, since font-size doesn't include the zoom factor, we really can't do
+ // that here either.
+ return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style->fontDescription().specifiedSize()) / 100, style, cssValuePool);
+ return zoomAdjustedPixelValue(length.value(), style, cssValuePool);
+}
+
+static PassRefPtr<CSSPrimitiveValue> fontSizeFromStyle(RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style, cssValuePool);
+}
+
+static PassRefPtr<CSSPrimitiveValue> fontStyleFromStyle(RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ if (style->fontDescription().italic())
+ return cssValuePool->createIdentifierValue(CSSValueItalic);
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+}
+
+static PassRefPtr<CSSPrimitiveValue> fontVariantFromStyle(RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ if (style->fontDescription().smallCaps())
+ return cssValuePool->createIdentifierValue(CSSValueSmallCaps);
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+}
+
+static PassRefPtr<CSSPrimitiveValue> fontWeightFromStyle(RenderStyle* style, CSSValuePool* cssValuePool)
+{
+ switch (style->fontDescription().weight()) {
+ case FontWeight100:
+ return cssValuePool->createIdentifierValue(CSSValue100);
+ case FontWeight200:
+ return cssValuePool->createIdentifierValue(CSSValue200);
+ case FontWeight300:
+ return cssValuePool->createIdentifierValue(CSSValue300);
+ case FontWeightNormal:
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+ case FontWeight500:
+ return cssValuePool->createIdentifierValue(CSSValue500);
+ case FontWeight600:
+ return cssValuePool->createIdentifierValue(CSSValue600);
+ case FontWeightBold:
+ return cssValuePool->createIdentifierValue(CSSValueBold);
+ case FontWeight800:
+ return cssValuePool->createIdentifierValue(CSSValue800);
+ case FontWeight900:
+ return cssValuePool->createIdentifierValue(CSSValue900);
+ }
+ ASSERT_NOT_REACHED();
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+}
+
+PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int propertyID, EUpdateLayout updateLayout) const
+{
+ Node* node = m_node.get();
+ if (!node)
+ return 0;
+
+ // Make sure our layout is up to date before we allow a query on these attributes.
+ if (updateLayout)
+ node->document()->updateLayoutIgnorePendingStylesheets();
+
+ RenderObject* renderer = node->renderer();
+
+ RefPtr<RenderStyle> style;
+ if (renderer && hasCompositedLayer(renderer) && AnimationController::supportsAcceleratedAnimationOfProperty(static_cast<CSSPropertyID>(propertyID))) {
+ style = renderer->animation()->getAnimatedStyleForRenderer(renderer);
+ if (m_pseudoElementSpecifier) {
+ // FIXME: This cached pseudo style will only exist if the animation has been run at least once.
+ style = style->getCachedPseudoStyle(m_pseudoElementSpecifier);
+ }
+ } else
+ style = node->computedStyle(m_pseudoElementSpecifier);
+
+ if (!style)
+ return 0;
+
+ CSSValuePool* cssValuePool = node->document()->cssValuePool().get();
+
+ propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode());
+
+ switch (static_cast<CSSPropertyID>(propertyID)) {
+ case CSSPropertyInvalid:
+ break;
+
+ case CSSPropertyBackgroundColor:
+ return cssValuePool->createColorValue(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor).rgb() : style->backgroundColor().rgb());
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyWebkitMaskImage: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskImage ? style->maskLayers() : style->backgroundLayers();
+ if (!layers)
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ if (!layers->next()) {
+ if (layers->image())
+ return layers->image()->cssValue();
+
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ }
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) {
+ if (currLayer->image())
+ list->append(currLayer->image()->cssValue());
+ else
+ list->append(cssValuePool->createIdentifierValue(CSSValueNone));
+ }
+ return list.release();
+ }
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitMaskSize: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskSize ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next())
+ return fillSizeToCSSValue(layers->size(), cssValuePool);
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
+ list->append(fillSizeToCSSValue(currLayer->size(), cssValuePool));
+
+ return list.release();
+ }
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyWebkitMaskRepeat: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskRepeat ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next())
+ return fillRepeatToCSSValue(layers->repeatX(), layers->repeatY(), cssValuePool);
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
+ list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY(), cssValuePool));
+
+ return list.release();
+ }
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyWebkitMaskComposite: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskComposite ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next())
+ return cssValuePool->createValue(layers->composite());
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
+ list->append(cssValuePool->createValue(currLayer->composite()));
+
+ return list.release();
+ }
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyWebkitMaskAttachment: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskAttachment ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next())
+ return cssValuePool->createValue(layers->attachment());
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
+ list->append(cssValuePool->createValue(currLayer->attachment()));
+
+ return list.release();
+ }
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskOrigin: {
+ const FillLayer* layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style->maskLayers() : style->backgroundLayers();
+ bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
+ if (!layers->next()) {
+ EFillBox box = isClip ? layers->clip() : layers->origin();
+ return cssValuePool->createValue(box);
+ }
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) {
+ EFillBox box = isClip ? currLayer->clip() : currLayer->origin();
+ list->append(cssValuePool->createValue(box));
+ }
+
+ return list.release();
+ }
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyWebkitMaskPosition: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPosition ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next()) {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(cssValuePool->createValue(layers->xPosition()));
+ list->append(cssValuePool->createValue(layers->yPosition()));
+ return list.release();
+ }
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) {
+ RefPtr<CSSValueList> positionList = CSSValueList::createSpaceSeparated();
+ positionList->append(cssValuePool->createValue(currLayer->xPosition()));
+ positionList->append(cssValuePool->createValue(currLayer->yPosition()));
+ list->append(positionList);
+ }
+
+ return list.release();
+ }
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyWebkitMaskPositionX: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionX ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next())
+ return cssValuePool->createValue(layers->xPosition());
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
+ list->append(cssValuePool->createValue(currLayer->xPosition()));
+
+ return list.release();
+ }
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyWebkitMaskPositionY: {
+ const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionY ? style->maskLayers() : style->backgroundLayers();
+ if (!layers->next())
+ return cssValuePool->createValue(layers->yPosition());
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next())
+ list->append(cssValuePool->createValue(currLayer->yPosition()));
+
+ return list.release();
+ }
+ case CSSPropertyBorderCollapse:
+ if (style->borderCollapse())
+ return cssValuePool->createIdentifierValue(CSSValueCollapse);
+ return cssValuePool->createIdentifierValue(CSSValueSeparate);
+ case CSSPropertyBorderSpacing: {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get(), cssValuePool));
+ list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get(), cssValuePool));
+ return list.release();
+ }
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ return zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get(), cssValuePool);
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ return zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get(), cssValuePool);
+ case CSSPropertyBorderImageSource:
+ if (style->borderImageSource())
+ return style->borderImageSource()->cssValue();
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ case CSSPropertyBorderTopColor:
+ return m_allowVisitedStyle ? cssValuePool->createColorValue(style->visitedDependentColor(CSSPropertyBorderTopColor).rgb()) : currentColorOrValidColor(style.get(), style->borderTopColor());
+ case CSSPropertyBorderRightColor:
+ return m_allowVisitedStyle ? cssValuePool->createColorValue(style->visitedDependentColor(CSSPropertyBorderRightColor).rgb()) : currentColorOrValidColor(style.get(), style->borderRightColor());
+ case CSSPropertyBorderBottomColor:
+ return m_allowVisitedStyle ? cssValuePool->createColorValue(style->visitedDependentColor(CSSPropertyBorderBottomColor).rgb()) : currentColorOrValidColor(style.get(), style->borderBottomColor());
+ case CSSPropertyBorderLeftColor:
+ return m_allowVisitedStyle ? cssValuePool->createColorValue(style->visitedDependentColor(CSSPropertyBorderLeftColor).rgb()) : currentColorOrValidColor(style.get(), style->borderLeftColor());
+ case CSSPropertyBorderTopStyle:
+ return cssValuePool->createValue(style->borderTopStyle());
+ case CSSPropertyBorderRightStyle:
+ return cssValuePool->createValue(style->borderRightStyle());
+ case CSSPropertyBorderBottomStyle:
+ return cssValuePool->createValue(style->borderBottomStyle());
+ case CSSPropertyBorderLeftStyle:
+ return cssValuePool->createValue(style->borderLeftStyle());
+ case CSSPropertyBorderTopWidth:
+ return zoomAdjustedPixelValue(style->borderTopWidth(), style.get(), cssValuePool);
+ case CSSPropertyBorderRightWidth:
+ return zoomAdjustedPixelValue(style->borderRightWidth(), style.get(), cssValuePool);
+ case CSSPropertyBorderBottomWidth:
+ return zoomAdjustedPixelValue(style->borderBottomWidth(), style.get(), cssValuePool);
+ case CSSPropertyBorderLeftWidth:
+ return zoomAdjustedPixelValue(style->borderLeftWidth(), style.get(), cssValuePool);
+ case CSSPropertyBottom:
+ return getPositionOffsetValue(style.get(), CSSPropertyBottom, cssValuePool);
+ case CSSPropertyWebkitBoxAlign:
+ return cssValuePool->createValue(style->boxAlign());
+ case CSSPropertyWebkitBoxDirection:
+ return cssValuePool->createValue(style->boxDirection());
+ case CSSPropertyWebkitBoxFlex:
+ return cssValuePool->createValue(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitBoxFlexGroup:
+ return cssValuePool->createValue(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitBoxLines:
+ return cssValuePool->createValue(style->boxLines());
+ case CSSPropertyWebkitBoxOrdinalGroup:
+ return cssValuePool->createValue(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitBoxOrient:
+ return cssValuePool->createValue(style->boxOrient());
+ case CSSPropertyWebkitBoxPack:
+ return cssValuePool->createValue(style->boxPack());
+ case CSSPropertyWebkitBoxReflect:
+ return valueForReflection(style->boxReflect(), style.get(), cssValuePool);
+ case CSSPropertyBoxShadow:
+ case CSSPropertyWebkitBoxShadow:
+ return valueForShadow(style->boxShadow(), propertyID, style.get());
+ case CSSPropertyCaptionSide:
+ return cssValuePool->createValue(style->captionSide());
+ case CSSPropertyClear:
+ return cssValuePool->createValue(style->clear());
+ case CSSPropertyColor:
+ return cssValuePool->createColorValue(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor).rgb() : style->color().rgb());
+ case CSSPropertyWebkitPrintColorAdjust:
+ return cssValuePool->createValue(style->printColorAdjust());
+ case CSSPropertyWebkitColumnAxis:
+ return cssValuePool->createValue(style->columnAxis());
+ case CSSPropertyWebkitColumnCount:
+ if (style->hasAutoColumnCount())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitColumnGap:
+ if (style->hasNormalColumnGap())
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+ return zoomAdjustedPixelValue(style->columnGap(), style.get(), cssValuePool);
+ case CSSPropertyWebkitColumnRuleColor:
+ return m_allowVisitedStyle ? cssValuePool->createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->columnRuleColor());
+ case CSSPropertyWebkitColumnRuleStyle:
+ return cssValuePool->createValue(style->columnRuleStyle());
+ case CSSPropertyWebkitColumnRuleWidth:
+ return zoomAdjustedPixelValue(style->columnRuleWidth(), style.get(), cssValuePool);
+ case CSSPropertyWebkitColumnSpan:
+ if (style->columnSpan())
+ return cssValuePool->createIdentifierValue(CSSValueAll);
+ return cssValuePool->createValue(1, CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitColumnBreakAfter:
+ return cssValuePool->createValue(style->columnBreakAfter());
+ case CSSPropertyWebkitColumnBreakBefore:
+ return cssValuePool->createValue(style->columnBreakBefore());
+ case CSSPropertyWebkitColumnBreakInside:
+ return cssValuePool->createValue(style->columnBreakInside());
+ case CSSPropertyWebkitColumnWidth:
+ if (style->hasAutoColumnWidth())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return zoomAdjustedPixelValue(style->columnWidth(), style.get(), cssValuePool);
+ case CSSPropertyWebkitRegionBreakAfter:
+ return cssValuePool->createValue(style->regionBreakAfter());
+ case CSSPropertyWebkitRegionBreakBefore:
+ return cssValuePool->createValue(style->regionBreakBefore());
+ case CSSPropertyWebkitRegionBreakInside:
+ return cssValuePool->createValue(style->regionBreakInside());
+ case CSSPropertyCursor: {
+ RefPtr<CSSValueList> list;
+ CursorList* cursors = style->cursors();
+ if (cursors && cursors->size() > 0) {
+ list = CSSValueList::createCommaSeparated();
+ for (unsigned i = 0; i < cursors->size(); ++i)
+ if (StyleImage* image = cursors->at(i).image())
+ list->append(image->cssValue());
+ }
+ RefPtr<CSSValue> value = cssValuePool->createValue(style->cursor());
+ if (list) {
+ list->append(value);
+ return list.release();
+ }
+ return value.release();
+ }
+ case CSSPropertyDirection:
+ return cssValuePool->createValue(style->direction());
+ case CSSPropertyDisplay:
+ return cssValuePool->createValue(style->display());
+ case CSSPropertyEmptyCells:
+ return cssValuePool->createValue(style->emptyCells());
+ case CSSPropertyWebkitFlexOrder:
+ return cssValuePool->createValue(style->flexOrder(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitFlexPack:
+ return cssValuePool->createValue(style->flexPack());
+ case CSSPropertyWebkitFlexAlign:
+ return cssValuePool->createValue(style->flexAlign());
+ case CSSPropertyWebkitFlexDirection:
+ return cssValuePool->createValue(style->flexDirection());
+ case CSSPropertyWebkitFlexWrap:
+ return cssValuePool->createValue(style->flexWrap());
+ case CSSPropertyWebkitFlexFlow: {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(cssValuePool->createValue(style->flexDirection()));
+ list->append(cssValuePool->createValue(style->flexWrap()));
+ return list.release();
+ }
+ case CSSPropertyFloat:
+ return cssValuePool->createValue(style->floating());
+ case CSSPropertyFont: {
+ RefPtr<FontValue> computedFont = FontValue::create();
+ computedFont->style = fontStyleFromStyle(style.get(), cssValuePool);
+ computedFont->variant = fontVariantFromStyle(style.get(), cssValuePool);
+ computedFont->weight = fontWeightFromStyle(style.get(), cssValuePool);
+ computedFont->size = fontSizeFromStyle(style.get(), cssValuePool);
+ computedFont->lineHeight = lineHeightFromStyle(style.get(), cssValuePool);
+ computedFont->family = fontFamilyFromStyle(style.get(), cssValuePool);
+ return computedFont.release();
+ }
+ case CSSPropertyFontFamily: {
+ RefPtr<CSSValueList> fontFamilyList = fontFamilyFromStyle(style.get(), cssValuePool);
+ // If there's only a single family, return that as a CSSPrimitiveValue.
+ // NOTE: Gecko always returns this as a comma-separated CSSPrimitiveValue string.
+ if (fontFamilyList->length() == 1)
+ return fontFamilyList->item(0);
+ return fontFamilyList.release();
+ }
+ case CSSPropertyFontSize:
+ return fontSizeFromStyle(style.get(), cssValuePool);
+ case CSSPropertyFontStyle:
+ return fontStyleFromStyle(style.get(), cssValuePool);
+ case CSSPropertyFontVariant:
+ return fontVariantFromStyle(style.get(), cssValuePool);
+ case CSSPropertyFontWeight:
+ return fontWeightFromStyle(style.get(), cssValuePool);
+ case CSSPropertyWebkitFontFeatureSettings: {
+ const FontFeatureSettings* featureSettings = style->fontDescription().featureSettings();
+ if (!featureSettings || !featureSettings->size())
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ for (unsigned i = 0; i < featureSettings->size(); ++i) {
+ const FontFeature& feature = featureSettings->at(i);
+ RefPtr<FontFeatureValue> featureValue = FontFeatureValue::create(feature.tag(), feature.value());
+ list->append(featureValue.release());
+ }
+ return list.release();
+ }
+#if ENABLE(CSS_GRID_LAYOUT)
+ case CSSPropertyWebkitGridColumns: {
+ return valueForGridTrackList(style->gridColumns(), style.get(), cssValuePool);
+ }
+ case CSSPropertyWebkitGridRows: {
+ return valueForGridTrackList(style->gridRows(), style.get(), cssValuePool);
+ }
+#endif
+ case CSSPropertyHeight:
+ if (renderer) {
+ // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
+ // the "height" property does not apply for non-replaced inline elements.
+ if (!renderer->isReplaced() && renderer->isInline())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return zoomAdjustedPixelValue(sizingBox(renderer).height(), style.get(), cssValuePool);
+ }
+ return zoomAdjustedPixelValueForLength(style->height(), style.get(), cssValuePool);
+ case CSSPropertyWebkitHighlight:
+ if (style->highlight() == nullAtom)
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return cssValuePool->createValue(style->highlight(), CSSPrimitiveValue::CSS_STRING);
+ case CSSPropertyWebkitHyphens:
+ return cssValuePool->createValue(style->hyphens());
+ case CSSPropertyWebkitHyphenateCharacter:
+ if (style->hyphenationString().isNull())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->hyphenationString(), CSSPrimitiveValue::CSS_STRING);
+ case CSSPropertyWebkitHyphenateLimitAfter:
+ if (style->hyphenationLimitAfter() < 0)
+ return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
+ return CSSPrimitiveValue::create(style->hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitHyphenateLimitBefore:
+ if (style->hyphenationLimitBefore() < 0)
+ return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
+ return CSSPrimitiveValue::create(style->hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitHyphenateLimitLines:
+ if (style->hyphenationLimitLines() < 0)
+ return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
+ return CSSPrimitiveValue::create(style->hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitBorderFit:
+ if (style->borderFit() == BorderFitBorder)
+ return cssValuePool->createIdentifierValue(CSSValueBorder);
+ return cssValuePool->createIdentifierValue(CSSValueLines);
+ case CSSPropertyImageRendering:
+ return CSSPrimitiveValue::create(style->imageRendering());
+ case CSSPropertyLeft:
+ return getPositionOffsetValue(style.get(), CSSPropertyLeft, cssValuePool);
+ case CSSPropertyLetterSpacing:
+ if (!style->letterSpacing())
+ return cssValuePool->createIdentifierValue(CSSValueNormal);
+ return zoomAdjustedPixelValue(style->letterSpacing(), style.get(), cssValuePool);
+ case CSSPropertyWebkitLineClamp:
+ if (style->lineClamp().isNone())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return cssValuePool->createValue(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyLineHeight:
+ return lineHeightFromStyle(style.get(), cssValuePool);
+ case CSSPropertyListStyleImage:
+ if (style->listStyleImage())
+ return style->listStyleImage()->cssValue();
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ case CSSPropertyListStylePosition:
+ return cssValuePool->createValue(style->listStylePosition());
+ case CSSPropertyListStyleType:
+ return cssValuePool->createValue(style->listStyleType());
+ case CSSPropertyWebkitLocale:
+ if (style->locale().isNull())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->locale(), CSSPrimitiveValue::CSS_STRING);
+ case CSSPropertyMarginTop: {
+ Length marginTop = style->marginTop();
+ if (marginTop.isFixed() || !renderer || !renderer->isBox())
+ return zoomAdjustedPixelValueForLength(marginTop, style.get(), cssValuePool);
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->marginTop(), style.get(), cssValuePool);
+ }
+ case CSSPropertyMarginRight: {
+ Length marginRight = style->marginRight();
+ if (marginRight.isFixed() || !renderer || !renderer->isBox())
+ return zoomAdjustedPixelValueForLength(marginRight, style.get(), cssValuePool);
+ int value;
+ if (marginRight.isPercent())
+ // RenderBox gives a marginRight() that is the distance between the right-edge of the child box
+ // and the right-edge of the containing box, when display == BLOCK. Let's calculate the absolute
+ // value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
+ value = marginRight.calcMinValue(toRenderBox(renderer)->containingBlockLogicalWidthForContent());
+ else
+ value = toRenderBox(renderer)->marginRight();
+ return zoomAdjustedPixelValue(value, style.get(), cssValuePool);
+ }
+ case CSSPropertyMarginBottom: {
+ Length marginBottom = style->marginBottom();
+ if (marginBottom.isFixed() || !renderer || !renderer->isBox())
+ return zoomAdjustedPixelValueForLength(marginBottom, style.get(), cssValuePool);
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->marginBottom(), style.get(), cssValuePool);
+ }
+ case CSSPropertyMarginLeft: {
+ Length marginLeft = style->marginLeft();
+ if (marginLeft.isFixed() || !renderer || !renderer->isBox())
+ return zoomAdjustedPixelValueForLength(marginLeft, style.get(), cssValuePool);
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->marginLeft(), style.get(), cssValuePool);
+ }
+ case CSSPropertyWebkitMarqueeDirection:
+ return cssValuePool->createValue(style->marqueeDirection());
+ case CSSPropertyWebkitMarqueeIncrement:
+ return cssValuePool->createValue(style->marqueeIncrement());
+ case CSSPropertyWebkitMarqueeRepetition:
+ if (style->marqueeLoopCount() < 0)
+ return cssValuePool->createIdentifierValue(CSSValueInfinite);
+ return cssValuePool->createValue(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWebkitMarqueeStyle:
+ return cssValuePool->createValue(style->marqueeBehavior());
+ case CSSPropertyWebkitUserModify:
+ return cssValuePool->createValue(style->userModify());
+ case CSSPropertyMaxHeight: {
+ const Length& maxHeight = style->maxHeight();
+ if (maxHeight.isUndefined())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return cssValuePool->createValue(maxHeight);
+ }
+ case CSSPropertyMaxWidth: {
+ const Length& maxWidth = style->maxWidth();
+ if (maxWidth.isUndefined())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return cssValuePool->createValue(maxWidth);
+ }
+ case CSSPropertyMinHeight:
+ return cssValuePool->createValue(style->minHeight());
+ case CSSPropertyMinWidth:
+ return cssValuePool->createValue(style->minWidth());
+ case CSSPropertyOpacity:
+ return cssValuePool->createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyOrphans:
+ return cssValuePool->createValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyOutlineColor:
+ return m_allowVisitedStyle ? cssValuePool->createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->outlineColor());
+ case CSSPropertyOutlineOffset:
+ return zoomAdjustedPixelValue(style->outlineOffset(), style.get(), cssValuePool);
+ case CSSPropertyOutlineStyle:
+ if (style->outlineStyleIsAuto())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->outlineStyle());
+ case CSSPropertyOutlineWidth:
+ return zoomAdjustedPixelValue(style->outlineWidth(), style.get(), cssValuePool);
+ case CSSPropertyOverflow:
+ return cssValuePool->createValue(max(style->overflowX(), style->overflowY()));
+ case CSSPropertyOverflowX:
+ return cssValuePool->createValue(style->overflowX());
+ case CSSPropertyOverflowY:
+ return cssValuePool->createValue(style->overflowY());
+ case CSSPropertyPaddingTop:
+ if (renderer && renderer->isBox())
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingTop(false), style.get(), cssValuePool);
+ return cssValuePool->createValue(style->paddingTop());
+ case CSSPropertyPaddingRight:
+ if (renderer && renderer->isBox())
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingRight(false), style.get(), cssValuePool);
+ return cssValuePool->createValue(style->paddingRight());
+ case CSSPropertyPaddingBottom:
+ if (renderer && renderer->isBox())
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingBottom(false), style.get(), cssValuePool);
+ return cssValuePool->createValue(style->paddingBottom());
+ case CSSPropertyPaddingLeft:
+ if (renderer && renderer->isBox())
+ return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingLeft(false), style.get(), cssValuePool);
+ return cssValuePool->createValue(style->paddingLeft());
+ case CSSPropertyPageBreakAfter:
+ return cssValuePool->createValue(style->pageBreakAfter());
+ case CSSPropertyPageBreakBefore:
+ return cssValuePool->createValue(style->pageBreakBefore());
+ case CSSPropertyPageBreakInside: {
+ EPageBreak pageBreak = style->pageBreakInside();
+ ASSERT(pageBreak != PBALWAYS);
+ if (pageBreak == PBALWAYS)
+ return 0;
+ return cssValuePool->createValue(style->pageBreakInside());
+ }
+ case CSSPropertyPosition:
+ return cssValuePool->createValue(style->position());
+ case CSSPropertyRight:
+ return getPositionOffsetValue(style.get(), CSSPropertyRight, cssValuePool);
+ case CSSPropertyTableLayout:
+ return cssValuePool->createValue(style->tableLayout());
+ case CSSPropertyTextAlign:
+ return cssValuePool->createValue(style->textAlign());
+ case CSSPropertyTextDecoration:
+ return renderTextDecorationFlagsToCSSValue(style->textDecoration(), cssValuePool);
+ case CSSPropertyWebkitTextDecorationsInEffect:
+ return renderTextDecorationFlagsToCSSValue(style->textDecorationsInEffect(), cssValuePool);
+ case CSSPropertyWebkitTextFillColor:
+ return currentColorOrValidColor(style.get(), style->textFillColor());
+ case CSSPropertyWebkitTextEmphasisColor:
+ return currentColorOrValidColor(style.get(), style->textEmphasisColor());
+ case CSSPropertyWebkitTextEmphasisPosition:
+ return cssValuePool->createValue(style->textEmphasisPosition());
+ case CSSPropertyWebkitTextEmphasisStyle:
+ switch (style->textEmphasisMark()) {
+ case TextEmphasisMarkNone:
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ case TextEmphasisMarkCustom:
+ return cssValuePool->createValue(style->textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING);
+ case TextEmphasisMarkAuto:
+ ASSERT_NOT_REACHED();
+ // Fall through
+ case TextEmphasisMarkDot:
+ case TextEmphasisMarkCircle:
+ case TextEmphasisMarkDoubleCircle:
+ case TextEmphasisMarkTriangle:
+ case TextEmphasisMarkSesame: {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ list->append(cssValuePool->createValue(style->textEmphasisFill()));
+ list->append(cssValuePool->createValue(style->textEmphasisMark()));
+ return list.release();
+ }
+ }
+ case CSSPropertyTextIndent:
+ return cssValuePool->createValue(style->textIndent());
+ case CSSPropertyTextShadow:
+ return valueForShadow(style->textShadow(), propertyID, style.get());
+ case CSSPropertyTextRendering:
+ return cssValuePool->createValue(style->fontDescription().textRenderingMode());
+ case CSSPropertyTextOverflow:
+ if (style->textOverflow())
+ return cssValuePool->createIdentifierValue(CSSValueEllipsis);
+ return cssValuePool->createIdentifierValue(CSSValueClip);
+ case CSSPropertyWebkitTextSecurity:
+ return cssValuePool->createValue(style->textSecurity());
+ case CSSPropertyWebkitTextSizeAdjust:
+ if (style->textSizeAdjust())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ case CSSPropertyWebkitTextStrokeColor:
+ return currentColorOrValidColor(style.get(), style->textStrokeColor());
+ case CSSPropertyWebkitTextStrokeWidth:
+ return zoomAdjustedPixelValue(style->textStrokeWidth(), style.get(), cssValuePool);
+ case CSSPropertyTextTransform:
+ return cssValuePool->createValue(style->textTransform());
+ case CSSPropertyTop:
+ return getPositionOffsetValue(style.get(), CSSPropertyTop, cssValuePool);
+ case CSSPropertyUnicodeBidi:
+ return cssValuePool->createValue(style->unicodeBidi());
+ case CSSPropertyVerticalAlign:
+ switch (style->verticalAlign()) {
+ case BASELINE:
+ return cssValuePool->createIdentifierValue(CSSValueBaseline);
+ case MIDDLE:
+ return cssValuePool->createIdentifierValue(CSSValueMiddle);
+ case SUB:
+ return cssValuePool->createIdentifierValue(CSSValueSub);
+ case SUPER:
+ return cssValuePool->createIdentifierValue(CSSValueSuper);
+ case TEXT_TOP:
+ return cssValuePool->createIdentifierValue(CSSValueTextTop);
+ case TEXT_BOTTOM:
+ return cssValuePool->createIdentifierValue(CSSValueTextBottom);
+ case TOP:
+ return cssValuePool->createIdentifierValue(CSSValueTop);
+ case BOTTOM:
+ return cssValuePool->createIdentifierValue(CSSValueBottom);
+ case BASELINE_MIDDLE:
+ return cssValuePool->createIdentifierValue(CSSValueWebkitBaselineMiddle);
+ case LENGTH:
+ return cssValuePool->createValue(style->verticalAlignLength());
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+ case CSSPropertyVisibility:
+ return cssValuePool->createValue(style->visibility());
+ case CSSPropertyWhiteSpace:
+ return cssValuePool->createValue(style->whiteSpace());
+ case CSSPropertyWidows:
+ return cssValuePool->createValue(style->widows(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyWidth:
+ if (renderer) {
+ // According to http://www.w3.org/TR/CSS2/visudet.html#the-width-property,
+ // the "width" property does not apply for non-replaced inline elements.
+ if (!renderer->isReplaced() && renderer->isInline())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return zoomAdjustedPixelValue(sizingBox(renderer).width(), style.get(), cssValuePool);
+ }
+ return zoomAdjustedPixelValueForLength(style->width(), style.get(), cssValuePool);
+ case CSSPropertyWordBreak:
+ return cssValuePool->createValue(style->wordBreak());
+ case CSSPropertyWordSpacing:
+ return zoomAdjustedPixelValue(style->wordSpacing(), style.get(), cssValuePool);
+ case CSSPropertyWordWrap:
+ return cssValuePool->createValue(style->wordWrap());
+ case CSSPropertyWebkitLineBreak:
+ return cssValuePool->createValue(style->khtmlLineBreak());
+ case CSSPropertyWebkitNbspMode:
+ return cssValuePool->createValue(style->nbspMode());
+ case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
+ return cssValuePool->createValue(style->matchNearestMailBlockquoteColor());
+ case CSSPropertyResize:
+ return cssValuePool->createValue(style->resize());
+ case CSSPropertyWebkitFontSmoothing:
+ return cssValuePool->createValue(style->fontDescription().fontSmoothing());
+ case CSSPropertyZIndex:
+ if (style->hasAutoZIndex())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyZoom:
+ return cssValuePool->createValue(style->zoom(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyBoxSizing:
+ if (style->boxSizing() == CONTENT_BOX)
+ return cssValuePool->createIdentifierValue(CSSValueContentBox);
+ return cssValuePool->createIdentifierValue(CSSValueBorderBox);
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPropertyWebkitDashboardRegion:
+ {
+ const Vector<StyleDashboardRegion>& regions = style->dashboardRegions();
+ unsigned count = regions.size();
+ if (count == 1 && regions[0].type == StyleDashboardRegion::None)
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+
+ RefPtr<DashboardRegion> firstRegion;
+ DashboardRegion* previousRegion = 0;
+ for (unsigned i = 0; i < count; i++) {
+ RefPtr<DashboardRegion> region = DashboardRegion::create();
+ StyleDashboardRegion styleRegion = regions[i];
+
+ region->m_label = styleRegion.label;
+ LengthBox offset = styleRegion.offset;
+ region->setTop(zoomAdjustedPixelValue(offset.top().value(), style.get(), cssValuePool));
+ region->setRight(zoomAdjustedPixelValue(offset.right().value(), style.get(), cssValuePool));
+ region->setBottom(zoomAdjustedPixelValue(offset.bottom().value(), style.get(), cssValuePool));
+ region->setLeft(zoomAdjustedPixelValue(offset.left().value(), style.get(), cssValuePool));
+ region->m_isRectangle = (styleRegion.type == StyleDashboardRegion::Rectangle);
+ region->m_isCircle = (styleRegion.type == StyleDashboardRegion::Circle);
+
+ if (previousRegion)
+ previousRegion->m_next = region;
+ else
+ firstRegion = region;
+ previousRegion = region.get();
+ }
+ return cssValuePool->createValue(firstRegion.release());
+ }
+#endif
+ case CSSPropertyWebkitAnimationDelay:
+ return getDelayValue(style->animations(), cssValuePool);
+ case CSSPropertyWebkitAnimationDirection: {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const AnimationList* t = style->animations();
+ if (t) {
+ for (size_t i = 0; i < t->size(); ++i) {
+ if (t->animation(i)->direction())
+ list->append(cssValuePool->createIdentifierValue(CSSValueAlternate));
+ else
+ list->append(cssValuePool->createIdentifierValue(CSSValueNormal));
+ }
+ } else
+ list->append(cssValuePool->createIdentifierValue(CSSValueNormal));
+ return list.release();
+ }
+ case CSSPropertyWebkitAnimationDuration:
+ return getDurationValue(style->animations(), cssValuePool);
+ case CSSPropertyWebkitAnimationFillMode: {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const AnimationList* t = style->animations();
+ if (t) {
+ for (size_t i = 0; i < t->size(); ++i) {
+ switch (t->animation(i)->fillMode()) {
+ case AnimationFillModeNone:
+ list->append(cssValuePool->createIdentifierValue(CSSValueNone));
+ break;
+ case AnimationFillModeForwards:
+ list->append(cssValuePool->createIdentifierValue(CSSValueForwards));
+ break;
+ case AnimationFillModeBackwards:
+ list->append(cssValuePool->createIdentifierValue(CSSValueBackwards));
+ break;
+ case AnimationFillModeBoth:
+ list->append(cssValuePool->createIdentifierValue(CSSValueBoth));
+ break;
+ }
+ }
+ } else
+ list->append(cssValuePool->createIdentifierValue(CSSValueNone));
+ return list.release();
+ }
+ case CSSPropertyWebkitAnimationIterationCount: {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const AnimationList* t = style->animations();
+ if (t) {
+ for (size_t i = 0; i < t->size(); ++i) {
+ int iterationCount = t->animation(i)->iterationCount();
+ if (iterationCount == Animation::IterationCountInfinite)
+ list->append(cssValuePool->createIdentifierValue(CSSValueInfinite));
+ else
+ list->append(cssValuePool->createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER));
+ }
+ } else
+ list->append(cssValuePool->createValue(Animation::initialAnimationIterationCount(), CSSPrimitiveValue::CSS_NUMBER));
+ return list.release();
+ }
+ case CSSPropertyWebkitAnimationName: {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const AnimationList* t = style->animations();
+ if (t) {
+ for (size_t i = 0; i < t->size(); ++i)
+ list->append(cssValuePool->createValue(t->animation(i)->name(), CSSPrimitiveValue::CSS_STRING));
+ } else
+ list->append(cssValuePool->createIdentifierValue(CSSValueNone));
+ return list.release();
+ }
+ case CSSPropertyWebkitAnimationPlayState: {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const AnimationList* t = style->animations();
+ if (t) {
+ for (size_t i = 0; i < t->size(); ++i) {
+ int prop = t->animation(i)->playState();
+ if (prop == AnimPlayStatePlaying)
+ list->append(cssValuePool->createIdentifierValue(CSSValueRunning));
+ else
+ list->append(cssValuePool->createIdentifierValue(CSSValuePaused));
+ }
+ } else
+ list->append(cssValuePool->createIdentifierValue(CSSValueRunning));
+ return list.release();
+ }
+ case CSSPropertyWebkitAnimationTimingFunction:
+ return getTimingFunctionValue(style->animations());
+ case CSSPropertyWebkitAppearance:
+ return cssValuePool->createValue(style->appearance());
+ case CSSPropertyWebkitAspectRatio:
+ if (!style->hasAspectRatio())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return CSSAspectRatioValue::create(style->aspectRatioNumerator(), style->aspectRatioDenominator());
+ case CSSPropertyWebkitBackfaceVisibility:
+ return cssValuePool->createIdentifierValue((style->backfaceVisibility() == BackfaceVisibilityHidden) ? CSSValueHidden : CSSValueVisible);
+ case CSSPropertyWebkitBorderImage:
+ return valueForNinePieceImage(style->borderImage(), cssValuePool);
+ case CSSPropertyBorderImageOutset:
+ return valueForNinePieceImageQuad(style->borderImage().outset(), cssValuePool);
+ case CSSPropertyBorderImageRepeat:
+ return valueForNinePieceImageRepeat(style->borderImage(), cssValuePool);
+ case CSSPropertyBorderImageSlice:
+ return valueForNinePieceImageSlice(style->borderImage(), cssValuePool);
+ case CSSPropertyBorderImageWidth:
+ return valueForNinePieceImageQuad(style->borderImage().borderSlices(), cssValuePool);
+ case CSSPropertyWebkitMaskBoxImage:
+ return valueForNinePieceImage(style->maskBoxImage(), cssValuePool);
+ case CSSPropertyWebkitMaskBoxImageOutset:
+ return valueForNinePieceImageQuad(style->maskBoxImage().outset(), cssValuePool);
+ case CSSPropertyWebkitMaskBoxImageRepeat:
+ return valueForNinePieceImageRepeat(style->maskBoxImage(), cssValuePool);
+ case CSSPropertyWebkitMaskBoxImageSlice:
+ return valueForNinePieceImageSlice(style->maskBoxImage(), cssValuePool);
+ case CSSPropertyWebkitMaskBoxImageWidth:
+ return valueForNinePieceImageQuad(style->maskBoxImage().borderSlices(), cssValuePool);
+ case CSSPropertyWebkitMaskBoxImageSource:
+ if (style->maskBoxImageSource())
+ return style->maskBoxImageSource()->cssValue();
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ case CSSPropertyWebkitFontSizeDelta:
+ // Not a real style property -- used by the editing engine -- so has no computed value.
+ break;
+ case CSSPropertyWebkitMarginBottomCollapse:
+ case CSSPropertyWebkitMarginAfterCollapse:
+ return cssValuePool->createValue(style->marginAfterCollapse());
+ case CSSPropertyWebkitMarginTopCollapse:
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ return cssValuePool->createValue(style->marginBeforeCollapse());
+ case CSSPropertyWebkitPerspective:
+ if (!style->hasPerspective())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return zoomAdjustedPixelValue(style->perspective(), style.get(), cssValuePool);
+ case CSSPropertyWebkitPerspectiveOrigin: {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ if (renderer) {
+ IntRect box = sizingBox(renderer);
+ list->append(zoomAdjustedPixelValue(style->perspectiveOriginX().calcMinValue(box.width()), style.get(), cssValuePool));
+ list->append(zoomAdjustedPixelValue(style->perspectiveOriginY().calcMinValue(box.height()), style.get(), cssValuePool));
+ }
+ else {
+ list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginX(), style.get(), cssValuePool));
+ list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginY(), style.get(), cssValuePool));
+
+ }
+ return list.release();
+ }
+ case CSSPropertyWebkitRtlOrdering:
+ return cssValuePool->createIdentifierValue(style->rtlOrdering() ? CSSValueVisual : CSSValueLogical);
+#if ENABLE(TOUCH_EVENTS)
+ case CSSPropertyWebkitTapHighlightColor:
+ return currentColorOrValidColor(style.get(), style->tapHighlightColor());
+#endif
+ case CSSPropertyWebkitUserDrag:
+ return cssValuePool->createValue(style->userDrag());
+ case CSSPropertyWebkitUserSelect:
+ return cssValuePool->createValue(style->userSelect());
+ case CSSPropertyBorderBottomLeftRadius:
+ return getBorderRadiusCornerValue(style->borderBottomLeftRadius(), style.get(), cssValuePool);
+ case CSSPropertyBorderBottomRightRadius:
+ return getBorderRadiusCornerValue(style->borderBottomRightRadius(), style.get(), cssValuePool);
+ case CSSPropertyBorderTopLeftRadius:
+ return getBorderRadiusCornerValue(style->borderTopLeftRadius(), style.get(), cssValuePool);
+ case CSSPropertyBorderTopRightRadius:
+ return getBorderRadiusCornerValue(style->borderTopRightRadius(), style.get(), cssValuePool);
+ case CSSPropertyClip: {
+ if (!style->hasClip())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ RefPtr<Rect> rect = Rect::create();
+ rect->setTop(zoomAdjustedPixelValue(style->clip().top().value(), style.get(), cssValuePool));
+ rect->setRight(zoomAdjustedPixelValue(style->clip().right().value(), style.get(), cssValuePool));
+ rect->setBottom(zoomAdjustedPixelValue(style->clip().bottom().value(), style.get(), cssValuePool));
+ rect->setLeft(zoomAdjustedPixelValue(style->clip().left().value(), style.get(), cssValuePool));
+ return cssValuePool->createValue(rect.release());
+ }
+ case CSSPropertySpeak:
+ return cssValuePool->createValue(style->speak());
+ case CSSPropertyWebkitTransform:
+ return computedTransform(renderer, style.get(), cssValuePool);
+ case CSSPropertyWebkitTransformOrigin: {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ if (renderer) {
+ IntRect box = sizingBox(renderer);
+ list->append(zoomAdjustedPixelValue(style->transformOriginX().calcMinValue(box.width()), style.get(), cssValuePool));
+ list->append(zoomAdjustedPixelValue(style->transformOriginY().calcMinValue(box.height()), style.get(), cssValuePool));
+ if (style->transformOriginZ() != 0)
+ list->append(zoomAdjustedPixelValue(style->transformOriginZ(), style.get(), cssValuePool));
+ } else {
+ list->append(zoomAdjustedPixelValueForLength(style->transformOriginX(), style.get(), cssValuePool));
+ list->append(zoomAdjustedPixelValueForLength(style->transformOriginY(), style.get(), cssValuePool));
+ if (style->transformOriginZ() != 0)
+ list->append(zoomAdjustedPixelValue(style->transformOriginZ(), style.get(), cssValuePool));
+ }
+ return list.release();
+ }
+ case CSSPropertyWebkitTransformStyle:
+ return cssValuePool->createIdentifierValue((style->transformStyle3D() == TransformStyle3DPreserve3D) ? CSSValuePreserve3d : CSSValueFlat);
+ case CSSPropertyWebkitTransitionDelay:
+ return getDelayValue(style->transitions(), cssValuePool);
+ case CSSPropertyWebkitTransitionDuration:
+ return getDurationValue(style->transitions(), cssValuePool);
+ case CSSPropertyWebkitTransitionProperty: {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const AnimationList* t = style->transitions();
+ if (t) {
+ for (size_t i = 0; i < t->size(); ++i) {
+ int prop = t->animation(i)->property();
+ RefPtr<CSSValue> propertyValue;
+ if (prop == cAnimateNone)
+ propertyValue = cssValuePool->createIdentifierValue(CSSValueNone);
+ else if (prop == cAnimateAll)
+ propertyValue = cssValuePool->createIdentifierValue(CSSValueAll);
+ else
+ propertyValue = cssValuePool->createValue(getPropertyName(static_cast<CSSPropertyID>(prop)), CSSPrimitiveValue::CSS_STRING);
+ list->append(propertyValue);
+ }
+ } else
+ list->append(cssValuePool->createIdentifierValue(CSSValueAll));
+ return list.release();
+ }
+ case CSSPropertyWebkitTransitionTimingFunction:
+ return getTimingFunctionValue(style->transitions());
+ case CSSPropertyPointerEvents:
+ return cssValuePool->createValue(style->pointerEvents());
+ case CSSPropertyWebkitColorCorrection:
+ return cssValuePool->createValue(style->colorSpace());
+ case CSSPropertyWebkitLineGrid:
+ if (style->lineGrid().isNull())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return cssValuePool->createValue(style->lineGrid(), CSSPrimitiveValue::CSS_STRING);
+ case CSSPropertyWebkitLineGridSnap:
+ return CSSPrimitiveValue::create(style->lineGridSnap());
+ case CSSPropertyWebkitWritingMode:
+ return cssValuePool->createValue(style->writingMode());
+ case CSSPropertyWebkitTextCombine:
+ return cssValuePool->createValue(style->textCombine());
+ case CSSPropertyWebkitTextOrientation:
+ return CSSPrimitiveValue::create(style->fontDescription().textOrientation());
+ case CSSPropertyWebkitLineBoxContain:
+ return createLineBoxContainValue(cssValuePool, style->lineBoxContain());
+ case CSSPropertyContent:
+ return contentToCSSValue(style.get(), cssValuePool);
+ case CSSPropertyCounterIncrement:
+ return counterToCSSValue(style.get(), propertyID, cssValuePool);
+ case CSSPropertyCounterReset:
+ return counterToCSSValue(style.get(), propertyID, cssValuePool);
+ case CSSPropertyWebkitFlowInto:
+ if (style->flowThread().isNull())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->flowThread(), CSSPrimitiveValue::CSS_STRING);
+ case CSSPropertyWebkitFlowFrom:
+ if (style->regionThread().isNull())
+ return cssValuePool->createIdentifierValue(CSSValueNone);
+ return cssValuePool->createValue(style->regionThread(), CSSPrimitiveValue::CSS_STRING);
+ case CSSPropertyWebkitRegionOverflow:
+ return cssValuePool->createValue(style->regionOverflow());
+ case CSSPropertyWebkitWrapFlow:
+ return cssValuePool->createValue(style->wrapFlow());
+ case CSSPropertyWebkitWrapMargin:
+ return cssValuePool->createValue(style->wrapMargin());
+ case CSSPropertyWebkitWrapPadding:
+ return cssValuePool->createValue(style->wrapPadding());
+ case CSSPropertyWebkitWrapShapeInside:
+ if (!style->wrapShapeInside())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->wrapShapeInside());
+ case CSSPropertyWebkitWrapShapeOutside:
+ if (!style->wrapShapeOutside())
+ return cssValuePool->createIdentifierValue(CSSValueAuto);
+ return cssValuePool->createValue(style->wrapShapeOutside());
+ case CSSPropertyWebkitWrapThrough:
+ return cssValuePool->createValue(style->wrapThrough());
+#if ENABLE(CSS_FILTERS)
+ case CSSPropertyWebkitFilter:
+ return valueForFilter(style.get());
+#endif
+ /* Shorthand properties, currently not supported see bug 13658*/
+ case CSSPropertyBackground: {
+ const int properties[5] = { CSSPropertyBackgroundColor, CSSPropertyBackgroundImage,
+ CSSPropertyBackgroundRepeat, CSSPropertyBackgroundAttachment,
+ CSSPropertyBackgroundPosition };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyBorder: {
+ RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyBorderTop, DoNotUpdateLayout);
+ const int properties[3] = { CSSPropertyBorderRight, CSSPropertyBorderBottom,
+ CSSPropertyBorderLeft };
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) {
+ if (value->cssText() != getPropertyCSSValue(properties[i], DoNotUpdateLayout)->cssText())
+ return 0;
+ }
+ return value.release();
+ }
+ case CSSPropertyBorderBottom: {
+ const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
+ CSSPropertyBorderBottomColor };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyBorderColor: {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
+ CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return getCSSPropertyValuesForSidesShorthand(properties);
+ }
+ case CSSPropertyBorderLeft: {
+ const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
+ CSSPropertyBorderLeftColor };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyBorderImage:
+ return valueForNinePieceImage(style->borderImage(), cssValuePool);
+ case CSSPropertyBorderRadius:
+ break;
+ case CSSPropertyBorderRight: {
+ const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
+ CSSPropertyBorderRightColor };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyBorderStyle: {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
+ CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return getCSSPropertyValuesForSidesShorthand(properties);
+ }
+ case CSSPropertyBorderTop: {
+ const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
+ CSSPropertyBorderTopColor };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyBorderWidth: {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
+ CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return getCSSPropertyValuesForSidesShorthand(properties);
+ }
+ case CSSPropertyListStyle: {
+ const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
+ CSSPropertyListStyleImage };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyMargin: {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
+ CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return getCSSPropertyValuesForSidesShorthand(properties);
+ }
+ case CSSPropertyOutline: {
+ const int properties[3] = { CSSPropertyOutlineColor, CSSPropertyOutlineStyle,
+ CSSPropertyOutlineWidth };
+ return getCSSPropertyValuesForShorthandProperties(properties, WTF_ARRAY_LENGTH(properties));
+ }
+ case CSSPropertyPadding: {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
+ CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return getCSSPropertyValuesForSidesShorthand(properties);
+ }
+ /* Individual properties not part of the spec */
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ break;
+
+ /* Unimplemented CSS 3 properties (including CSS3 shorthand properties) */
+ case CSSPropertyWebkitTextEmphasis:
+ case CSSPropertyTextLineThrough:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextLineThroughWidth:
+ case CSSPropertyTextOverline:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextOverlineWidth:
+ case CSSPropertyTextUnderline:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyTextUnderlineMode:
+ case CSSPropertyTextUnderlineStyle:
+ case CSSPropertyTextUnderlineWidth:
+ break;
+
+ /* Directional properties are resolved by resolveDirectionAwareProperty() before the switch. */
+ case CSSPropertyWebkitBorderEnd:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderEndWidth:
+ case CSSPropertyWebkitBorderStart:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitBorderStartWidth:
+ case CSSPropertyWebkitBorderAfter:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitBorderAfterWidth:
+ case CSSPropertyWebkitBorderBefore:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderBeforeWidth:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginStart:
+ case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyWebkitMaxLogicalWidth:
+ case CSSPropertyWebkitMaxLogicalHeight:
+ ASSERT_NOT_REACHED();
+ break;
+
+ /* Unimplemented @font-face properties */
+ case CSSPropertyFontStretch:
+ case CSSPropertySrc:
+ case CSSPropertyUnicodeRange:
+ break;
+
+ /* Other unimplemented properties */
+ case CSSPropertyPage: // for @page
+ case CSSPropertyQuotes: // FIXME: needs implementation
+ case CSSPropertySize: // for @page
+ break;
+
+ /* Unimplemented -webkit- properties */
+ case CSSPropertyWebkitAnimation:
+ case CSSPropertyWebkitBorderRadius:
+ case CSSPropertyWebkitColumns:
+ case CSSPropertyWebkitColumnRule:
+ case CSSPropertyWebkitMarginCollapse:
+ case CSSPropertyWebkitMarquee:
+ case CSSPropertyWebkitMarqueeSpeed:
+ case CSSPropertyWebkitMask:
+ case CSSPropertyWebkitMaskRepeatX:
+ case CSSPropertyWebkitMaskRepeatY:
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ case CSSPropertyWebkitTextStroke:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ case CSSPropertyWebkitTransition:
+ case CSSPropertyWebkitWrap:
+ break;
+
+#if ENABLE(SVG)
+ case CSSPropertyClipPath:
+ case CSSPropertyClipRule:
+ case CSSPropertyMask:
+ case CSSPropertyEnableBackground:
+ case CSSPropertyFilter:
+ case CSSPropertyFloodColor:
+ case CSSPropertyFloodOpacity:
+ case CSSPropertyLightingColor:
+ case CSSPropertyStopColor:
+ case CSSPropertyStopOpacity:
+ case CSSPropertyColorInterpolation:
+ case CSSPropertyColorInterpolationFilters:
+ case CSSPropertyColorProfile:
+ case CSSPropertyColorRendering:
+ case CSSPropertyFill:
+ case CSSPropertyFillOpacity:
+ case CSSPropertyFillRule:
+ case CSSPropertyMarker:
+ case CSSPropertyMarkerEnd:
+ case CSSPropertyMarkerMid:
+ case CSSPropertyMarkerStart:
+ case CSSPropertyShapeRendering:
+ case CSSPropertyStroke:
+ case CSSPropertyStrokeDasharray:
+ case CSSPropertyStrokeDashoffset:
+ case CSSPropertyStrokeLinecap:
+ case CSSPropertyStrokeLinejoin:
+ case CSSPropertyStrokeMiterlimit:
+ case CSSPropertyStrokeOpacity:
+ case CSSPropertyStrokeWidth:
+ case CSSPropertyAlignmentBaseline:
+ case CSSPropertyBaselineShift:
+ case CSSPropertyDominantBaseline:
+ case CSSPropertyGlyphOrientationHorizontal:
+ case CSSPropertyGlyphOrientationVertical:
+ case CSSPropertyKerning:
+ case CSSPropertyTextAnchor:
+ case CSSPropertyVectorEffect:
+ case CSSPropertyWritingMode:
+ case CSSPropertyWebkitSvgShadow:
+ return getSVGPropertyCSSValue(propertyID, DoNotUpdateLayout);
+#endif
+ }
+
+ logUnimplementedPropertyID(propertyID);
+ return 0;
+}
+
+String CSSComputedStyleDeclaration::getPropertyValue(int propertyID) const
+{
+ RefPtr<CSSValue> value = getPropertyCSSValue(propertyID);
+ if (value)
+ return value->cssText();
+ 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
+{
+ Node* node = m_node.get();
+ if (!node)
+ return 0;
+
+ RenderStyle* style = node->computedStyle(m_pseudoElementSpecifier);
+ if (!style)
+ return 0;
+
+ return numComputedProperties;
+}
+
+String CSSComputedStyleDeclaration::item(unsigned i) const
+{
+ if (i >= length())
+ return "";
+
+ return getPropertyName(static_cast<CSSPropertyID>(computedProperties[i]));
+}
+
+bool CSSComputedStyleDeclaration::cssPropertyMatches(const CSSProperty* property) const
+{
+ if (property->id() == CSSPropertyFontSize && property->value()->isPrimitiveValue() && m_node) {
+ m_node->document()->updateLayoutIgnorePendingStylesheets();
+ RenderStyle* style = m_node->computedStyle(m_pseudoElementSpecifier);
+ 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)
+ return true;
+ }
+ }
+
+ return CSSStyleDeclaration::cssPropertyMatches(property);
+}
+
+PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::copy() const
+{
+ return copyPropertiesInSet(computedProperties, numComputedProperties);
+}
+
+PassRefPtr<CSSMutableStyleDeclaration> CSSComputedStyleDeclaration::makeMutable()
+{
+ return copy();
+}
+
+PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::getCSSPropertyValuesForShorthandProperties(const int* properties, size_t size) const
+{
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (size_t i = 0; i < size; ++i) {
+ RefPtr<CSSValue> value = getPropertyCSSValue(properties[i], DoNotUpdateLayout);
+ list->append(value);
+ }
+ return list.release();
+}
+
+PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::getCSSPropertyValuesForSidesShorthand(const int* properties) const
+{
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ // Assume the properties are in the usual order top, right, bottom, left.
+ RefPtr<CSSValue> topValue = getPropertyCSSValue(properties[0], DoNotUpdateLayout);
+ RefPtr<CSSValue> rightValue = getPropertyCSSValue(properties[1], DoNotUpdateLayout);
+ RefPtr<CSSValue> bottomValue = getPropertyCSSValue(properties[2], DoNotUpdateLayout);
+ RefPtr<CSSValue> leftValue = getPropertyCSSValue(properties[3], DoNotUpdateLayout);
+
+ // All 4 properties must be specified.
+ if (!topValue || !rightValue || !bottomValue || !leftValue)
+ return 0;
+
+ bool showLeft = rightValue->cssText() != leftValue->cssText();
+ bool showBottom = (topValue->cssText() != bottomValue->cssText()) || showLeft;
+ bool showRight = (topValue->cssText() != rightValue->cssText()) || showBottom;
+
+ list->append(topValue);
+ if (showRight)
+ list->append(rightValue);
+ if (showBottom)
+ list->append(bottomValue);
+ if (showLeft)
+ list->append(leftValue);
+
+ return list.release();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.h b/Source/WebCore/css/CSSComputedStyleDeclaration.h
new file mode 100644
index 000000000..6ef90af6e
--- /dev/null
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2004 Zack Rusin <zack@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 Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef CSSComputedStyleDeclaration_h
+#define CSSComputedStyleDeclaration_h
+
+#include "CSSStyleDeclaration.h"
+#include "RenderStyleConstants.h"
+#include <wtf/RefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class Color;
+class CSSMutableStyleDeclaration;
+class CSSPrimitiveValue;
+class CSSValueList;
+class CSSValuePool;
+class Node;
+class RenderStyle;
+class ShadowData;
+class SVGPaint;
+
+enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true };
+
+class CSSComputedStyleDeclaration : public CSSStyleDeclaration {
+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; }
+
+ virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const;
+ virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable();
+
+ PassRefPtr<CSSValue> getPropertyCSSValue(int propertyID, EUpdateLayout) const;
+ PassRefPtr<CSSValue> getFontSizeCSSValuePreferringKeyword() const;
+ bool useFixedFontDefaultSize() const;
+#if ENABLE(SVG)
+ PassRefPtr<CSSValue> getSVGPropertyCSSValue(int propertyID, EUpdateLayout) const;
+#endif
+
+protected:
+ virtual bool cssPropertyMatches(const CSSProperty*) const;
+
+private:
+ CSSComputedStyleDeclaration(PassRefPtr<Node>, bool allowVisitedStyle, const String&);
+
+ virtual void setCssText(const String&, ExceptionCode&);
+
+ virtual String removeProperty(int propertyID, ExceptionCode&);
+ virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&);
+
+ PassRefPtr<CSSValue> valueForShadow(const ShadowData*, int, RenderStyle*) const;
+ PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(RenderStyle*, const Color&) const;
+#if ENABLE(SVG)
+ PassRefPtr<SVGPaint> adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint>, RenderStyle*) const;
+#endif
+
+#if ENABLE(CSS_FILTERS)
+ PassRefPtr<CSSValue> valueForFilter(RenderStyle*) const;
+#endif
+
+ PassRefPtr<CSSValueList> getCSSPropertyValuesForShorthandProperties(const int* properties, size_t) const;
+ PassRefPtr<CSSValueList> getCSSPropertyValuesForSidesShorthand(const int* properties) const;
+
+ RefPtr<Node> m_node;
+ PseudoId m_pseudoElementSpecifier;
+ bool m_allowVisitedStyle;
+};
+
+inline PassRefPtr<CSSComputedStyleDeclaration> computedStyle(PassRefPtr<Node> node, bool allowVisitedStyle = false, const String& pseudoElementName = String())
+{
+ return adoptRef(new CSSComputedStyleDeclaration(node, allowVisitedStyle, pseudoElementName));
+}
+
+} // namespace WebCore
+
+#endif // CSSComputedStyleDeclaration_h
diff --git a/Source/WebCore/css/CSSCrossfadeValue.cpp b/Source/WebCore/css/CSSCrossfadeValue.cpp
new file mode 100644
index 000000000..4ff08afca
--- /dev/null
+++ b/Source/WebCore/css/CSSCrossfadeValue.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+#include "CSSCrossfadeValue.h"
+
+#include "CSSImageValue.h"
+#include "CachedImage.h"
+#include "CachedResourceLoader.h"
+#include "CrossfadeGeneratedImage.h"
+#include "ImageBuffer.h"
+#include "RenderObject.h"
+#include "StyleCachedImage.h"
+#include "StyleGeneratedImage.h"
+
+namespace WebCore {
+
+static bool subimageIsPending(CSSValue* value)
+{
+ if (value->isImageValue())
+ return static_cast<CSSImageValue*>(value)->cachedOrPendingImage()->isPendingImage();
+
+ if (value->isImageGeneratorValue())
+ return static_cast<CSSImageGeneratorValue*>(value)->isPending();
+
+ ASSERT_NOT_REACHED();
+
+ return false;
+}
+
+static CachedImage* cachedImageForCSSValue(CSSValue* value, CachedResourceLoader* cachedResourceLoader)
+{
+ if (!value)
+ return 0;
+
+ if (value->isImageValue()) {
+ StyleCachedImage* styleCachedImage = static_cast<CSSImageValue*>(value)->cachedImage(cachedResourceLoader);
+ if (!styleCachedImage)
+ return 0;
+
+ return styleCachedImage->cachedImage();
+ }
+
+ if (value->isImageGeneratorValue()) {
+ static_cast<CSSImageGeneratorValue*>(value)->loadSubimages(cachedResourceLoader);
+ // FIXME: Handle CSSImageGeneratorValue (and thus cross-fades with gradients and canvas).
+ return 0;
+ }
+
+ ASSERT_NOT_REACHED();
+
+ return 0;
+}
+
+CSSCrossfadeValue::~CSSCrossfadeValue()
+{
+ if (m_cachedFromImage)
+ m_cachedFromImage->removeClient(&m_crossfadeSubimageObserver);
+ if (m_cachedToImage)
+ m_cachedToImage->removeClient(&m_crossfadeSubimageObserver);
+}
+
+String CSSCrossfadeValue::customCssText() const
+{
+ String result = "-webkit-cross-fade(";
+ result += m_fromValue->cssText() + ", ";
+ result += m_toValue->cssText() + ", ";
+ result += m_percentageValue->cssText();
+ result += ")";
+ return result;
+}
+
+IntSize CSSCrossfadeValue::fixedSize(const RenderObject* renderer)
+{
+ float percentage = m_percentageValue->getFloatValue();
+ float inversePercentage = 1 - percentage;
+
+ CachedResourceLoader* cachedResourceLoader = renderer->document()->cachedResourceLoader();
+ CachedImage* cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), cachedResourceLoader);
+ CachedImage* cachedToImage = cachedImageForCSSValue(m_toValue.get(), cachedResourceLoader);
+
+ if (!cachedFromImage || !cachedToImage)
+ return IntSize();
+
+ IntSize fromImageSize = cachedFromImage->imageForRenderer(renderer)->size();
+ IntSize toImageSize = cachedToImage->imageForRenderer(renderer)->size();
+
+ // Rounding issues can cause transitions between images of equal size to return
+ // a different fixed size; avoid performing the interpolation if the images are the same size.
+ if (fromImageSize == toImageSize)
+ return fromImageSize;
+
+ return IntSize(fromImageSize.width() * inversePercentage + toImageSize.width() * percentage,
+ fromImageSize.height() * inversePercentage + toImageSize.height() * percentage);
+}
+
+bool CSSCrossfadeValue::isPending() const
+{
+ return subimageIsPending(m_fromValue.get()) || subimageIsPending(m_toValue.get());
+}
+
+void CSSCrossfadeValue::loadSubimages(CachedResourceLoader* cachedResourceLoader)
+{
+ m_cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), cachedResourceLoader);
+ m_cachedToImage = cachedImageForCSSValue(m_toValue.get(), cachedResourceLoader);
+
+ if (m_cachedFromImage)
+ m_cachedFromImage->addClient(&m_crossfadeSubimageObserver);
+ if (m_cachedToImage)
+ m_cachedToImage->addClient(&m_crossfadeSubimageObserver);
+
+ m_crossfadeSubimageObserver.setReady(true);
+}
+
+PassRefPtr<Image> CSSCrossfadeValue::image(RenderObject* renderer, const IntSize& size)
+{
+ if (size.isEmpty())
+ return 0;
+
+ CachedResourceLoader* cachedResourceLoader = renderer->document()->cachedResourceLoader();
+ CachedImage* cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), cachedResourceLoader);
+ CachedImage* cachedToImage = cachedImageForCSSValue(m_toValue.get(), cachedResourceLoader);
+
+ if (!cachedFromImage || !cachedToImage)
+ return Image::nullImage();
+
+ Image* fromImage = cachedFromImage->imageForRenderer(renderer);
+ Image* toImage = cachedToImage->imageForRenderer(renderer);
+
+ if (!fromImage || !toImage)
+ return Image::nullImage();
+
+ m_generatedImage = CrossfadeGeneratedImage::create(fromImage, toImage, m_percentageValue->getFloatValue(), fixedSize(renderer), size);
+
+ return m_generatedImage.release();
+}
+
+void CSSCrossfadeValue::crossfadeChanged(const IntRect&)
+{
+ RenderObjectSizeCountMap::const_iterator end = clients().end();
+ for (RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr) {
+ RenderObject* client = const_cast<RenderObject*>(curr->first);
+ client->imageChanged(static_cast<WrappedImagePtr>(this));
+ }
+}
+
+void CSSCrossfadeValue::CrossfadeSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect)
+{
+ if (m_ready)
+ m_ownerValue->crossfadeChanged(*rect);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSCrossfadeValue.h b/Source/WebCore/css/CSSCrossfadeValue.h
new file mode 100644
index 000000000..be6066037
--- /dev/null
+++ b/Source/WebCore/css/CSSCrossfadeValue.h
@@ -0,0 +1,102 @@
+/*
+ * 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 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 CSSCrossfadeValue_h
+#define CSSCrossfadeValue_h
+
+#include "CachedImage.h"
+#include "CSSImageGeneratorValue.h"
+#include "CSSPrimitiveValue.h"
+#include "Image.h"
+#include "ImageObserver.h"
+
+namespace WebCore {
+
+class CachedImage;
+class CrossfadeSubimageObserverProxy;
+class RenderObject;
+class Document;
+
+class CSSCrossfadeValue : public CSSImageGeneratorValue {
+ friend class CrossfadeSubimageObserverProxy;
+public:
+ static PassRefPtr<CSSCrossfadeValue> create(PassRefPtr<CSSValue> fromValue, PassRefPtr<CSSValue> toValue)
+ {
+ return adoptRef(new CSSCrossfadeValue(fromValue, toValue));
+ }
+
+ ~CSSCrossfadeValue();
+
+ String customCssText() const;
+
+ PassRefPtr<Image> image(RenderObject*, const IntSize&);
+ bool isFixedSize() const { return true; }
+ IntSize fixedSize(const RenderObject*);
+
+ bool isPending() const;
+ void loadSubimages(CachedResourceLoader*);
+
+ void setPercentage(PassRefPtr<CSSPrimitiveValue> percentageValue) { m_percentageValue = percentageValue; }
+
+private:
+ CSSCrossfadeValue(PassRefPtr<CSSValue> fromValue, PassRefPtr<CSSValue> toValue)
+ : CSSImageGeneratorValue(CrossfadeClass)
+ , m_fromValue(fromValue)
+ , m_toValue(toValue)
+ , m_cachedFromImage(0)
+ , m_cachedToImage(0)
+ , m_crossfadeSubimageObserver(this) { }
+
+ class CrossfadeSubimageObserverProxy : public CachedImageClient {
+ public:
+ CrossfadeSubimageObserverProxy(CSSCrossfadeValue* ownerValue)
+ : m_ownerValue(ownerValue)
+ , m_ready(false) { }
+
+ virtual ~CrossfadeSubimageObserverProxy() { }
+ virtual void imageChanged(CachedImage*, const IntRect* = 0) OVERRIDE;
+ void setReady(bool ready) { m_ready = ready; }
+ private:
+ CSSCrossfadeValue* m_ownerValue;
+ bool m_ready;
+ };
+
+ void crossfadeChanged(const IntRect&);
+
+ RefPtr<CSSValue> m_fromValue;
+ RefPtr<CSSValue> m_toValue;
+ RefPtr<CSSPrimitiveValue> m_percentageValue;
+
+ CachedImage* m_cachedFromImage;
+ CachedImage* m_cachedToImage;
+
+ RefPtr<Image> m_generatedImage;
+
+ CrossfadeSubimageObserverProxy m_crossfadeSubimageObserver;
+};
+
+} // namespace WebCore
+
+#endif // CSSCrossfadeValue_h
diff --git a/Source/WebCore/css/CSSCursorImageValue.cpp b/Source/WebCore/css/CSSCursorImageValue.cpp
new file mode 100644
index 000000000..f41276b21
--- /dev/null
+++ b/Source/WebCore/css/CSSCursorImageValue.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2006 Rob Buis <buis@kde.org>
+ * (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 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 "CSSCursorImageValue.h"
+
+#include "CachedResourceLoader.h"
+#include "TreeScope.h"
+#include "PlatformString.h"
+#include <wtf/MathExtras.h>
+#include <wtf/UnusedParam.h>
+
+#if ENABLE(SVG)
+#include "SVGCursorElement.h"
+#include "SVGLengthContext.h"
+#include "SVGNames.h"
+#include "SVGURIReference.h"
+#endif
+
+namespace WebCore {
+
+#if ENABLE(SVG)
+static inline bool isSVGCursorIdentifier(const String& url)
+{
+ KURL kurl(ParsedURLString, url);
+ return kurl.hasFragmentIdentifier();
+}
+
+static inline SVGCursorElement* resourceReferencedByCursorElement(const String& url, Document* document)
+{
+ Element* element = SVGURIReference::targetElementFromIRIString(url, document);
+ if (element && element->hasTagName(SVGNames::cursorTag))
+ return static_cast<SVGCursorElement*>(element);
+
+ return 0;
+}
+#endif
+
+CSSCursorImageValue::CSSCursorImageValue(const String& url, const IntPoint& hotSpot)
+ : CSSImageValue(CursorImageClass, url)
+ , m_hotSpot(hotSpot)
+{
+}
+
+CSSCursorImageValue::~CSSCursorImageValue()
+{
+#if ENABLE(SVG)
+ const String& url = getStringValue();
+ if (!isSVGCursorIdentifier(url))
+ return;
+
+ HashSet<SVGElement*>::const_iterator it = m_referencedElements.begin();
+ HashSet<SVGElement*>::const_iterator end = m_referencedElements.end();
+
+ for (; it != end; ++it) {
+ SVGElement* referencedElement = *it;
+ referencedElement->cursorImageValueRemoved();
+ if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document()))
+ cursorElement->removeClient(referencedElement);
+ }
+#endif
+}
+
+bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element)
+{
+#if !ENABLE(SVG)
+ UNUSED_PARAM(element);
+#else
+ if (!element || !element->isSVGElement())
+ return false;
+
+ const String& url = getStringValue();
+ if (!isSVGCursorIdentifier(url))
+ return false;
+
+ if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, element->document())) {
+ // FIXME: This will override hot spot specified in CSS, which is probably incorrect.
+ SVGLengthContext lengthContext(0);
+ float x = roundf(cursorElement->x().value(lengthContext));
+ m_hotSpot.setX(static_cast<int>(x));
+
+ float y = roundf(cursorElement->y().value(lengthContext));
+ m_hotSpot.setY(static_cast<int>(y));
+
+ if (cachedImageURL() != element->document()->completeURL(cursorElement->href()))
+ clearCachedImage();
+
+ SVGElement* svgElement = static_cast<SVGElement*>(element);
+ m_referencedElements.add(svgElement);
+ svgElement->setCursorImageValue(this);
+ cursorElement->addClient(svgElement);
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+StyleCachedImage* CSSCursorImageValue::cachedImage(CachedResourceLoader* loader)
+{
+ String url = getStringValue();
+
+#if ENABLE(SVG)
+ if (isSVGCursorIdentifier(url) && loader && loader->document()) {
+ // FIXME: This will fail if the <cursor> element is in a shadow DOM (bug 59827)
+ if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, loader->document()))
+ url = cursorElement->href();
+ }
+#endif
+
+ return CSSImageValue::cachedImage(loader, url);
+}
+
+#if ENABLE(SVG)
+void CSSCursorImageValue::removeReferencedElement(SVGElement* element)
+{
+ m_referencedElements.remove(element);
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSCursorImageValue.h b/Source/WebCore/css/CSSCursorImageValue.h
new file mode 100644
index 000000000..cb26919e4
--- /dev/null
+++ b/Source/WebCore/css/CSSCursorImageValue.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2006 Rob Buis <buis@kde.org>
+ * Copyright (C) 2008 Apple Inc. All right 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 CSSCursorImageValue_h
+#define CSSCursorImageValue_h
+
+#include "CSSImageValue.h"
+#include "IntPoint.h"
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class Element;
+class SVGElement;
+
+class CSSCursorImageValue : public CSSImageValue {
+public:
+ static PassRefPtr<CSSCursorImageValue> create(const String& url, const IntPoint& hotSpot)
+ {
+ return adoptRef(new CSSCursorImageValue(url, hotSpot));
+ }
+
+ ~CSSCursorImageValue();
+
+ IntPoint hotSpot() const { return m_hotSpot; }
+
+ bool updateIfSVGCursorIsUsed(Element*);
+ StyleCachedImage* cachedImage(CachedResourceLoader*);
+
+#if ENABLE(SVG)
+ void removeReferencedElement(SVGElement*);
+#endif
+
+private:
+ CSSCursorImageValue(const String& url, const IntPoint& hotSpot);
+
+ IntPoint m_hotSpot;
+
+#if ENABLE(SVG)
+ HashSet<SVGElement*> m_referencedElements;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // CSSCursorImageValue_h
diff --git a/Source/WebCore/css/CSSElementStyleDeclaration.cpp b/Source/WebCore/css/CSSElementStyleDeclaration.cpp
new file mode 100644
index 000000000..81782619c
--- /dev/null
+++ b/Source/WebCore/css/CSSElementStyleDeclaration.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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
new file mode 100644
index 000000000..71ca518d5
--- /dev/null
+++ b/Source/WebCore/css/CSSElementStyleDeclaration.h
@@ -0,0 +1,61 @@
+/*
+ * 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/CSSFlexValue.cpp b/Source/WebCore/css/CSSFlexValue.cpp
new file mode 100644
index 000000000..3594507c4
--- /dev/null
+++ b/Source/WebCore/css/CSSFlexValue.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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:
+ *
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 "CSSFlexValue.h"
+
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+String CSSFlexValue::customCssText() const
+{
+ StringBuilder result;
+ result.append("-webkit-flex(");
+ result.append(String::number(m_positiveFlex));
+ result.append(" ");
+ result.append(String::number(m_negativeFlex));
+ result.append(" ");
+ result.append(m_preferredSize->cssText());
+ result.append(")");
+ return result.toString();
+}
+
+}
diff --git a/Source/WebCore/css/CSSFlexValue.h b/Source/WebCore/css/CSSFlexValue.h
new file mode 100644
index 000000000..58c6cce5a
--- /dev/null
+++ b/Source/WebCore/css/CSSFlexValue.h
@@ -0,0 +1,66 @@
+/*
+ * 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:
+ *
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 CSSFlexValue_h
+#define CSSFlexValue_h
+
+#include "CSSPrimitiveValue.h"
+#include "CSSValue.h"
+
+namespace WebCore {
+
+class CSSFlexValue : public CSSValue {
+public:
+ static PassRefPtr<CSSFlexValue> create(float positiveFlex, float negativeFlex, PassRefPtr<CSSPrimitiveValue> preferredSize)
+ {
+ return adoptRef(new CSSFlexValue(positiveFlex, negativeFlex, preferredSize));
+ }
+
+ String customCssText() const;
+
+ float positiveFlex() { return m_positiveFlex; }
+ float negativeFlex() { return m_negativeFlex; }
+ CSSPrimitiveValue* preferredSize() { return m_preferredSize.get(); }
+
+private:
+ CSSFlexValue(float positiveFlex, float negativeFlex, PassRefPtr<CSSPrimitiveValue> preferredSize)
+ : CSSValue(FlexClass)
+ , m_positiveFlex(positiveFlex)
+ , m_negativeFlex(negativeFlex)
+ , m_preferredSize(preferredSize)
+ {
+ }
+
+ float m_positiveFlex;
+ float m_negativeFlex;
+ RefPtr<CSSPrimitiveValue> m_preferredSize;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSFontFace.cpp b/Source/WebCore/css/CSSFontFace.cpp
new file mode 100644
index 000000000..67a7f7038
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFace.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007, 2008, 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 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.
+ */
+
+#include "config.h"
+#include "CSSFontFace.h"
+
+#include "CSSFontFaceSource.h"
+#include "CSSFontSelector.h"
+#include "CSSSegmentedFontFace.h"
+#include "FontDescription.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+bool CSSFontFace::isLoaded() const
+{
+ size_t size = m_sources.size();
+ for (size_t i = 0; i < size; i++) {
+ if (!m_sources[i]->isLoaded())
+ return false;
+ }
+ return true;
+}
+
+bool CSSFontFace::isValid() const
+{
+ size_t size = m_sources.size();
+ for (size_t i = 0; i < size; i++) {
+ if (m_sources[i]->isValid())
+ return true;
+ }
+ return false;
+}
+
+void CSSFontFace::addedToSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace)
+{
+ m_segmentedFontFaces.add(segmentedFontFace);
+}
+
+void CSSFontFace::removedFromSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace)
+{
+ m_segmentedFontFaces.remove(segmentedFontFace);
+}
+
+void CSSFontFace::addSource(PassOwnPtr<CSSFontFaceSource> source)
+{
+ source->setFontFace(this);
+ m_sources.append(source);
+}
+
+void CSSFontFace::fontLoaded(CSSFontFaceSource* source)
+{
+ if (source != m_activeSource)
+ return;
+
+ // FIXME: Can we assert that m_segmentedFontFaces is not empty? That may
+ // require stopping in-progress font loading when the last
+ // CSSSegmentedFontFace is removed.
+ if (m_segmentedFontFaces.isEmpty())
+ return;
+
+ HashSet<CSSSegmentedFontFace*>::iterator end = m_segmentedFontFaces.end();
+ for (HashSet<CSSSegmentedFontFace*>::iterator it = m_segmentedFontFaces.begin(); it != end; ++it)
+ (*it)->fontLoaded(this);
+
+ // Use one of the CSSSegmentedFontFaces' font selector. They all have
+ // the same font selector, so it's wasteful to store it in the CSSFontFace.
+ CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector();
+ fontSelector->fontLoaded();
+}
+
+SimpleFontData* CSSFontFace::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
+{
+ m_activeSource = 0;
+ if (!isValid())
+ return 0;
+
+ ASSERT(!m_segmentedFontFaces.isEmpty());
+ CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector();
+
+ size_t size = m_sources.size();
+ for (size_t i = 0; i < size; ++i) {
+ if (SimpleFontData* result = m_sources[i]->getFontData(fontDescription, syntheticBold, syntheticItalic, fontSelector)) {
+ m_activeSource = m_sources[i].get();
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+#if ENABLE(SVG_FONTS)
+bool CSSFontFace::hasSVGFontFaceSource() const
+{
+ size_t size = m_sources.size();
+ for (size_t i = 0; i < size; i++) {
+ if (m_sources[i]->isSVGFontFaceSource())
+ return true;
+ }
+ return false;
+}
+#endif
+
+}
diff --git a/Source/WebCore/css/CSSFontFace.h b/Source/WebCore/css/CSSFontFace.h
new file mode 100644
index 000000000..7fbbf0a5f
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFace.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2007, 2008 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 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 CSSFontFace_h
+#define CSSFontFace_h
+
+#include "FontTraitsMask.h"
+#include <wtf/Forward.h>
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class CSSFontFaceSource;
+class CSSSegmentedFontFace;
+class FontDescription;
+class SimpleFontData;
+
+class CSSFontFace : public RefCounted<CSSFontFace> {
+public:
+ static PassRefPtr<CSSFontFace> create(FontTraitsMask traitsMask, bool isLocalFallback = false) { return adoptRef(new CSSFontFace(traitsMask, isLocalFallback)); }
+
+ FontTraitsMask traitsMask() const { return m_traitsMask; }
+
+ struct UnicodeRange;
+
+ void addRange(UChar32 from, UChar32 to) { m_ranges.append(UnicodeRange(from, to)); }
+ const Vector<UnicodeRange>& ranges() const { return m_ranges; }
+
+ void addedToSegmentedFontFace(CSSSegmentedFontFace*);
+ void removedFromSegmentedFontFace(CSSSegmentedFontFace*);
+
+ bool isLoaded() const;
+ bool isValid() const;
+
+ bool isLocalFallback() const { return m_isLocalFallback; }
+
+ void addSource(PassOwnPtr<CSSFontFaceSource>);
+
+ void fontLoaded(CSSFontFaceSource*);
+
+ SimpleFontData* getFontData(const FontDescription&, bool syntheticBold, bool syntheticItalic);
+
+ struct UnicodeRange {
+ UnicodeRange(UChar32 from, UChar32 to)
+ : m_from(from)
+ , m_to(to)
+ {
+ }
+
+ UChar32 from() const { return m_from; }
+ UChar32 to() const { return m_to; }
+
+ private:
+ UChar32 m_from;
+ UChar32 m_to;
+ };
+
+#if ENABLE(SVG_FONTS)
+ bool hasSVGFontFaceSource() const;
+#endif
+
+private:
+ CSSFontFace(FontTraitsMask traitsMask, bool isLocalFallback)
+ : m_traitsMask(traitsMask)
+ , m_activeSource(0)
+ , m_isLocalFallback(isLocalFallback)
+ {
+ }
+
+ FontTraitsMask m_traitsMask;
+ Vector<UnicodeRange> m_ranges;
+ HashSet<CSSSegmentedFontFace*> m_segmentedFontFaces;
+ Vector<OwnPtr<CSSFontFaceSource> > m_sources;
+ CSSFontFaceSource* m_activeSource;
+ bool m_isLocalFallback;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSFontFaceRule.cpp b/Source/WebCore/css/CSSFontFaceRule.cpp
new file mode 100644
index 000000000..b4c697662
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceRule.cpp
@@ -0,0 +1,55 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 "CSSFontFaceRule.h"
+
+#include "CSSMutableStyleDeclaration.h"
+
+namespace WebCore {
+
+CSSFontFaceRule::CSSFontFaceRule(CSSStyleSheet* parent)
+ : CSSRule(parent, CSSRule::FONT_FACE_RULE)
+{
+}
+
+CSSFontFaceRule::~CSSFontFaceRule()
+{
+ if (m_style)
+ m_style->clearParentRule();
+}
+
+String CSSFontFaceRule::cssText() const
+{
+ String result("@font-face");
+ result += " { ";
+ result += m_style->cssText();
+ result += "}";
+ return result;
+}
+
+void CSSFontFaceRule::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
+{
+ if (m_style)
+ m_style->addSubresourceStyleURLs(urls);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSFontFaceRule.h b/Source/WebCore/css/CSSFontFaceRule.h
new file mode 100644
index 000000000..3d1f76cf3
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceRule.h
@@ -0,0 +1,61 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 CSSFontFaceRule_h
+#define CSSFontFaceRule_h
+
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSRule.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSFontFaceRule : public CSSRule {
+public:
+ static PassRefPtr<CSSFontFaceRule> create()
+ {
+ return adoptRef(new CSSFontFaceRule(0));
+ }
+ static PassRefPtr<CSSFontFaceRule> create(CSSStyleSheet* parent)
+ {
+ return adoptRef(new CSSFontFaceRule(parent));
+ }
+
+ ~CSSFontFaceRule();
+
+ CSSMutableStyleDeclaration* style() const { return m_style.get(); }
+
+ String cssText() const;
+
+ void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style) { m_style = style; }
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>& urls);
+
+private:
+ CSSFontFaceRule(CSSStyleSheet* parent);
+
+ RefPtr<CSSMutableStyleDeclaration> m_style;
+};
+
+} // namespace WebCore
+
+#endif // CSSFontFaceRule_h
diff --git a/Source/WebCore/css/CSSFontFaceRule.idl b/Source/WebCore/css/CSSFontFaceRule.idl
new file mode 100644
index 000000000..bd38a6137
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceRule.idl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSFontFaceRule : CSSRule {
+ readonly attribute CSSStyleDeclaration style;
+ };
+
+}
diff --git a/Source/WebCore/css/CSSFontFaceSource.cpp b/Source/WebCore/css/CSSFontFaceSource.cpp
new file mode 100644
index 000000000..e36735afb
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceSource.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2007, 2008, 2010, 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 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.
+ */
+
+#include "config.h"
+#include "CSSFontFaceSource.h"
+
+#include "CachedFont.h"
+#include "CSSFontFace.h"
+#include "CSSFontSelector.h"
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "FontCache.h"
+#include "FontDescription.h"
+#include "GlyphPageTreeNode.h"
+#include "SimpleFontData.h"
+
+#if ENABLE(SVG_FONTS)
+#include "FontCustomPlatformData.h"
+#include "SVGFontData.h"
+#include "SVGFontElement.h"
+#include "SVGFontFaceElement.h"
+#include "SVGNames.h"
+#include "SVGURIReference.h"
+#endif
+
+namespace WebCore {
+
+CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font)
+ : m_string(str)
+ , m_font(font)
+ , m_face(0)
+#if ENABLE(SVG_FONTS)
+ , m_hasExternalSVGFont(false)
+#endif
+{
+ if (m_font)
+ m_font->addClient(this);
+}
+
+CSSFontFaceSource::~CSSFontFaceSource()
+{
+ if (m_font)
+ m_font->removeClient(this);
+ pruneTable();
+}
+
+void CSSFontFaceSource::pruneTable()
+{
+ if (m_fontDataTable.isEmpty())
+ return;
+
+ m_fontDataTable.clear();
+}
+
+bool CSSFontFaceSource::isLoaded() const
+{
+ if (m_font)
+ return m_font->isLoaded();
+ return true;
+}
+
+bool CSSFontFaceSource::isValid() const
+{
+ if (m_font)
+ return !m_font->errorOccurred();
+ return true;
+}
+
+void CSSFontFaceSource::fontLoaded(CachedFont*)
+{
+ pruneTable();
+ if (m_face)
+ m_face->fontLoaded(this);
+}
+
+SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector* fontSelector)
+{
+ // If the font hasn't loaded or an error occurred, then we've got nothing.
+ if (!isValid())
+ return 0;
+
+ if (!m_font
+#if ENABLE(SVG_FONTS)
+ && !m_svgFontFaceElement
+#endif
+ ) {
+ // We're local. Just return a SimpleFontData from the normal cache.
+ return fontCache()->getCachedFontData(fontDescription, m_string);
+ }
+
+ // See if we have a mapping in our FontData cache.
+ unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 6 | fontDescription.widthVariant() << 4
+ | (fontDescription.textOrientation() == TextOrientationUpright ? 8 : 0) | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);
+
+ SimpleFontData*& cachedData = m_fontDataTable.add(hashKey, 0).first->second;
+ if (cachedData)
+ return cachedData;
+
+ OwnPtr<SimpleFontData> fontData;
+
+ // If we are still loading, then we let the system pick a font.
+ if (isLoaded()) {
+ if (m_font) {
+#if ENABLE(SVG_FONTS)
+ if (m_hasExternalSVGFont) {
+ // For SVG fonts parse the external SVG document, and extract the <font> element.
+ if (!m_font->ensureSVGFontData())
+ return 0;
+
+ if (!m_externalSVGFontElement) {
+ String fragmentIdentifier;
+ size_t start = m_string.find('#');
+ if (start != notFound)
+ fragmentIdentifier = m_string.string().substring(start + 1);
+ m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier);
+ }
+
+ if (!m_externalSVGFontElement)
+ return 0;
+
+ SVGFontFaceElement* fontFaceElement = 0;
+
+ // Select first <font-face> child
+ for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) {
+ if (fontChild->hasTagName(SVGNames::font_faceTag)) {
+ fontFaceElement = static_cast<SVGFontFaceElement*>(fontChild);
+ break;
+ }
+ }
+
+ if (fontFaceElement) {
+ if (!m_svgFontFaceElement) {
+ // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement.
+ // Use the imported <font-face> tag as referencing font-face element for these cases.
+ m_svgFontFaceElement = fontFaceElement;
+ }
+
+ fontData = adoptPtr(new SimpleFontData(SVGFontData::create(fontFaceElement), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic));
+ }
+ } else
+#endif
+ {
+ // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef.
+ if (!m_font->ensureCustomFontData())
+ return 0;
+
+ fontData = adoptPtr(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(),
+ fontDescription.textOrientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false));
+ }
+ } else {
+#if ENABLE(SVG_FONTS)
+ // In-Document SVG Fonts
+ if (m_svgFontFaceElement)
+ fontData = adoptPtr(new SimpleFontData(SVGFontData::create(m_svgFontFaceElement.get()), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic));
+#endif
+ }
+ } else {
+ // Kick off the load. Do it soon rather than now, because we may be in the middle of layout,
+ // and the loader may invoke arbitrary delegate or event handler code.
+ fontSelector->beginLoadingFontSoon(m_font.get());
+
+ // This temporary font is not retained and should not be returned.
+ FontCachePurgePreventer fontCachePurgePreventer;
+ SimpleFontData* temporaryFont = fontCache()->getNonRetainedLastResortFallbackFont(fontDescription);
+ fontData = adoptPtr(new SimpleFontData(temporaryFont->platformData(), true, true));
+ }
+
+ if (Document* document = fontSelector->document()) {
+ cachedData = fontData.get();
+ document->registerCustomFont(fontData.release());
+ }
+
+ return cachedData;
+}
+
+#if ENABLE(SVG_FONTS)
+SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const
+{
+ return m_svgFontFaceElement.get();
+}
+
+void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element)
+{
+ m_svgFontFaceElement = element;
+}
+
+bool CSSFontFaceSource::isSVGFontFaceSource() const
+{
+ return m_svgFontFaceElement || m_hasExternalSVGFont;
+}
+#endif
+
+}
diff --git a/Source/WebCore/css/CSSFontFaceSource.h b/Source/WebCore/css/CSSFontFaceSource.h
new file mode 100644
index 000000000..e36fe4542
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceSource.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007, 2008, 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 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 CSSFontFaceSource_h
+#define CSSFontFaceSource_h
+
+#include "CachedFont.h"
+#include "CachedResourceHandle.h"
+#include "Timer.h"
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class CachedFont;
+class CSSFontFace;
+class CSSFontSelector;
+class FontDescription;
+class SimpleFontData;
+#if ENABLE(SVG_FONTS)
+class SVGFontElement;
+class SVGFontFaceElement;
+#endif
+
+
+class CSSFontFaceSource : public CachedFontClient {
+public:
+ CSSFontFaceSource(const String&, CachedFont* = 0);
+ virtual ~CSSFontFaceSource();
+
+ bool isLoaded() const;
+ bool isValid() const;
+
+ const AtomicString& string() const { return m_string; }
+
+ void setFontFace(CSSFontFace* face) { m_face = face; }
+
+ virtual void fontLoaded(CachedFont*);
+
+ SimpleFontData* getFontData(const FontDescription&, bool syntheticBold, bool syntheticItalic, CSSFontSelector*);
+
+ void pruneTable();
+
+#if ENABLE(SVG_FONTS)
+ SVGFontFaceElement* svgFontFaceElement() const;
+ void setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement>);
+ bool isSVGFontFaceSource() const;
+ void setHasExternalSVGFont(bool value) { m_hasExternalSVGFont = value; }
+#endif
+
+private:
+ void startLoadingTimerFired(Timer<CSSFontFaceSource>*);
+
+ AtomicString m_string; // URI for remote, built-in font name for local.
+ CachedResourceHandle<CachedFont> m_font; // For remote fonts, a pointer to our cached resource.
+ CSSFontFace* m_face; // Our owning font face.
+ HashMap<unsigned, SimpleFontData*> m_fontDataTable; // The hash key is composed of size synthetic styles.
+
+#if ENABLE(SVG_FONTS)
+ RefPtr<SVGFontFaceElement> m_svgFontFaceElement;
+ RefPtr<SVGFontElement> m_externalSVGFontElement;
+ bool m_hasExternalSVGFont;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSFontFaceSrcValue.cpp b/Source/WebCore/css/CSSFontFaceSrcValue.cpp
new file mode 100644
index 000000000..57300ef71
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceSrcValue.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007, 2010 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 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.
+ */
+
+#include "config.h"
+#include "CSSFontFaceSrcValue.h"
+#include "CSSStyleSheet.h"
+#include "FontCustomPlatformData.h"
+#include "Node.h"
+
+namespace WebCore {
+
+#if ENABLE(SVG_FONTS)
+bool CSSFontFaceSrcValue::isSVGFontFaceSrc() const
+{
+ return equalIgnoringCase(m_format, "svg");
+}
+#endif
+
+bool CSSFontFaceSrcValue::isSupportedFormat() const
+{
+ // Normally we would just check the format, but in order to avoid conflicts with the old WinIE style of font-face,
+ // we will also check to see if the URL ends with .eot. If so, we'll go ahead and assume that we shouldn't load it.
+ if (m_format.isEmpty()) {
+ // Check for .eot.
+ if (!m_resource.startsWith("data:", false) && m_resource.endsWith(".eot", false))
+ return false;
+ return true;
+ }
+
+ return FontCustomPlatformData::supportsFormat(m_format)
+#if ENABLE(SVG_FONTS)
+ || isSVGFontFaceSrc()
+#endif
+ ;
+}
+
+String CSSFontFaceSrcValue::customCssText() const
+{
+ String result;
+ if (isLocal())
+ result += "local(";
+ else
+ result += "url(";
+ result += m_resource;
+ result += ")";
+ if (!m_format.isEmpty())
+ result += " format(" + m_format + ")";
+ return result;
+}
+
+void CSSFontFaceSrcValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
+{
+ if (!isLocal())
+ addSubresourceURL(urls, styleSheet->completeURL(m_resource));
+}
+
+}
+
diff --git a/Source/WebCore/css/CSSFontFaceSrcValue.h b/Source/WebCore/css/CSSFontFaceSrcValue.h
new file mode 100644
index 000000000..121f4d4e1
--- /dev/null
+++ b/Source/WebCore/css/CSSFontFaceSrcValue.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2007, 2008 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 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 CSSFontFaceSrcValue_h
+#define CSSFontFaceSrcValue_h
+
+#include "CSSValue.h"
+#include "PlatformString.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class SVGFontFaceElement;
+
+class CSSFontFaceSrcValue : public CSSValue {
+public:
+ static PassRefPtr<CSSFontFaceSrcValue> create(const String& resource)
+ {
+ return adoptRef(new CSSFontFaceSrcValue(resource, false));
+ }
+ static PassRefPtr<CSSFontFaceSrcValue> createLocal(const String& resource)
+ {
+ return adoptRef(new CSSFontFaceSrcValue(resource, true));
+ }
+
+ const String& resource() const { return m_resource; }
+ const String& format() const { return m_format; }
+ bool isLocal() const { return m_isLocal; }
+
+ void setFormat(const String& format) { m_format = format; }
+
+ bool isSupportedFormat() const;
+
+#if ENABLE(SVG_FONTS)
+ bool isSVGFontFaceSrc() const;
+
+ SVGFontFaceElement* svgFontFaceElement() const { return m_svgFontFaceElement; }
+ void setSVGFontFaceElement(SVGFontFaceElement* element) { m_svgFontFaceElement = element; }
+#endif
+
+ String customCssText() const;
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
+
+private:
+ CSSFontFaceSrcValue(const String& resource, bool local)
+ : CSSValue(FontFaceSrcClass)
+ , m_resource(resource)
+ , m_isLocal(local)
+#if ENABLE(SVG_FONTS)
+ , m_svgFontFaceElement(0)
+#endif
+ {
+ }
+
+ String m_resource;
+ String m_format;
+ bool m_isLocal;
+
+#if ENABLE(SVG_FONTS)
+ SVGFontFaceElement* m_svgFontFaceElement;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSFontSelector.cpp b/Source/WebCore/css/CSSFontSelector.cpp
new file mode 100644
index 000000000..ed715038a
--- /dev/null
+++ b/Source/WebCore/css/CSSFontSelector.cpp
@@ -0,0 +1,621 @@
+/*
+ * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
+ * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.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.
+ */
+
+#include "config.h"
+#include "CSSFontSelector.h"
+
+#include "CachedFont.h"
+#include "CSSFontFace.h"
+#include "CSSFontFaceRule.h"
+#include "CSSFontFaceSource.h"
+#include "CSSFontFaceSrcValue.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSPropertyNames.h"
+#include "CSSSegmentedFontFace.h"
+#include "CSSStyleSelector.h"
+#include "CSSUnicodeRangeValue.h"
+#include "CSSValueKeywords.h"
+#include "CSSValueList.h"
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "FontCache.h"
+#include "FontFamilyValue.h"
+#include "Frame.h"
+#include "RenderObject.h"
+#include "Settings.h"
+#include "SimpleFontData.h"
+#include "WebKitFontFamilyNames.h"
+#include <wtf/text/AtomicString.h>
+
+#if ENABLE(SVG)
+#include "SVGFontFaceElement.h"
+#include "SVGNames.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+CSSFontSelector::CSSFontSelector(Document* document)
+ : m_document(document)
+ , m_beginLoadingTimer(this, &CSSFontSelector::beginLoadTimerFired)
+{
+ // FIXME: An old comment used to say there was no need to hold a reference to m_document
+ // because "we are guaranteed to be destroyed before the document". But there does not
+ // seem to be any such guarantee.
+
+ ASSERT(m_document);
+ fontCache()->addClient(this);
+}
+
+CSSFontSelector::~CSSFontSelector()
+{
+ clearDocument();
+ fontCache()->removeClient(this);
+}
+
+bool CSSFontSelector::isEmpty() const
+{
+ return m_fonts.isEmpty();
+}
+
+void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule)
+{
+ // Obtain the font-family property and the src property. Both must be defined.
+ const CSSMutableStyleDeclaration* style = fontFaceRule->style();
+ RefPtr<CSSValue> fontFamily = style->getPropertyCSSValue(CSSPropertyFontFamily);
+ RefPtr<CSSValue> src = style->getPropertyCSSValue(CSSPropertySrc);
+ RefPtr<CSSValue> unicodeRange = style->getPropertyCSSValue(CSSPropertyUnicodeRange);
+ if (!fontFamily || !src || !fontFamily->isValueList() || !src->isValueList() || (unicodeRange && !unicodeRange->isValueList()))
+ return;
+
+ CSSValueList* familyList = static_cast<CSSValueList*>(fontFamily.get());
+ if (!familyList->length())
+ return;
+
+ CSSValueList* srcList = static_cast<CSSValueList*>(src.get());
+ if (!srcList->length())
+ return;
+
+ CSSValueList* rangeList = static_cast<CSSValueList*>(unicodeRange.get());
+
+ unsigned traitsMask = 0;
+
+ if (RefPtr<CSSValue> fontStyle = style->getPropertyCSSValue(CSSPropertyFontStyle)) {
+ if (fontStyle->isPrimitiveValue()) {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ list->append(fontStyle);
+ fontStyle = list;
+ } else if (!fontStyle->isValueList())
+ return;
+
+ CSSValueList* styleList = static_cast<CSSValueList*>(fontStyle.get());
+ unsigned numStyles = styleList->length();
+ if (!numStyles)
+ return;
+
+ for (unsigned i = 0; i < numStyles; ++i) {
+ switch (static_cast<CSSPrimitiveValue*>(styleList->itemWithoutBoundsCheck(i))->getIdent()) {
+ case CSSValueAll:
+ traitsMask |= FontStyleMask;
+ break;
+ case CSSValueNormal:
+ traitsMask |= FontStyleNormalMask;
+ break;
+ case CSSValueItalic:
+ case CSSValueOblique:
+ traitsMask |= FontStyleItalicMask;
+ break;
+ default:
+ break;
+ }
+ }
+ } else
+ traitsMask |= FontStyleMask;
+
+ if (RefPtr<CSSValue> fontWeight = style->getPropertyCSSValue(CSSPropertyFontWeight)) {
+ if (fontWeight->isPrimitiveValue()) {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ list->append(fontWeight);
+ fontWeight = list;
+ } else if (!fontWeight->isValueList())
+ return;
+
+ CSSValueList* weightList = static_cast<CSSValueList*>(fontWeight.get());
+ unsigned numWeights = weightList->length();
+ if (!numWeights)
+ return;
+
+ for (unsigned i = 0; i < numWeights; ++i) {
+ switch (static_cast<CSSPrimitiveValue*>(weightList->itemWithoutBoundsCheck(i))->getIdent()) {
+ case CSSValueAll:
+ traitsMask |= FontWeightMask;
+ break;
+ case CSSValueBolder:
+ case CSSValueBold:
+ case CSSValue700:
+ traitsMask |= FontWeight700Mask;
+ break;
+ case CSSValueNormal:
+ case CSSValue400:
+ traitsMask |= FontWeight400Mask;
+ break;
+ case CSSValue900:
+ traitsMask |= FontWeight900Mask;
+ break;
+ case CSSValue800:
+ traitsMask |= FontWeight800Mask;
+ break;
+ case CSSValue600:
+ traitsMask |= FontWeight600Mask;
+ break;
+ case CSSValue500:
+ traitsMask |= FontWeight500Mask;
+ break;
+ case CSSValue300:
+ traitsMask |= FontWeight300Mask;
+ break;
+ case CSSValueLighter:
+ case CSSValue200:
+ traitsMask |= FontWeight200Mask;
+ break;
+ case CSSValue100:
+ traitsMask |= FontWeight100Mask;
+ break;
+ default:
+ break;
+ }
+ }
+ } else
+ traitsMask |= FontWeightMask;
+
+ if (RefPtr<CSSValue> fontVariant = style->getPropertyCSSValue(CSSPropertyFontVariant)) {
+ if (fontVariant->isPrimitiveValue()) {
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ list->append(fontVariant);
+ fontVariant = list;
+ } else if (!fontVariant->isValueList())
+ return;
+
+ CSSValueList* variantList = static_cast<CSSValueList*>(fontVariant.get());
+ unsigned numVariants = variantList->length();
+ if (!numVariants)
+ return;
+
+ for (unsigned i = 0; i < numVariants; ++i) {
+ switch (static_cast<CSSPrimitiveValue*>(variantList->itemWithoutBoundsCheck(i))->getIdent()) {
+ case CSSValueAll:
+ traitsMask |= FontVariantMask;
+ break;
+ case CSSValueNormal:
+ traitsMask |= FontVariantNormalMask;
+ break;
+ case CSSValueSmallCaps:
+ traitsMask |= FontVariantSmallCapsMask;
+ break;
+ default:
+ break;
+ }
+ }
+ } else
+ traitsMask |= FontVariantMask;
+
+ // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace.
+ RefPtr<CSSFontFace> fontFace;
+
+ int srcLength = srcList->length();
+
+ bool foundSVGFont = false;
+
+ for (int i = 0; i < srcLength; i++) {
+ // An item in the list either specifies a string (local font name) or a URL (remote font to download).
+ CSSFontFaceSrcValue* item = static_cast<CSSFontFaceSrcValue*>(srcList->itemWithoutBoundsCheck(i));
+ OwnPtr<CSSFontFaceSource> source;
+
+#if ENABLE(SVG_FONTS)
+ foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement();
+#endif
+ if (!item->isLocal()) {
+ Settings* settings = m_document ? m_document->frame() ? m_document->frame()->settings() : 0 : 0;
+ bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled());
+ if (allowDownloading && item->isSupportedFormat() && m_document) {
+ ResourceRequest request(m_document->completeURL(item->resource()));
+ CachedFont* cachedFont = m_document->cachedResourceLoader()->requestFont(request);
+ if (cachedFont) {
+ source = adoptPtr(new CSSFontFaceSource(item->resource(), cachedFont));
+#if ENABLE(SVG_FONTS)
+ if (foundSVGFont)
+ source->setHasExternalSVGFont(true);
+#endif
+ }
+ }
+ } else {
+ source = adoptPtr(new CSSFontFaceSource(item->resource()));
+ }
+
+ if (!fontFace)
+ fontFace = CSSFontFace::create(static_cast<FontTraitsMask>(traitsMask));
+
+ if (source) {
+#if ENABLE(SVG_FONTS)
+ source->setSVGFontFaceElement(item->svgFontFaceElement());
+#endif
+ fontFace->addSource(source.release());
+ }
+ }
+
+ ASSERT(fontFace);
+
+ if (fontFace && !fontFace->isValid())
+ return;
+
+ if (rangeList) {
+ unsigned numRanges = rangeList->length();
+ for (unsigned i = 0; i < numRanges; i++) {
+ CSSUnicodeRangeValue* range = static_cast<CSSUnicodeRangeValue*>(rangeList->itemWithoutBoundsCheck(i));
+ fontFace->addRange(range->from(), range->to());
+ }
+ }
+
+ // Hash under every single family name.
+ int familyLength = familyList->length();
+ for (int i = 0; i < familyLength; i++) {
+ CSSPrimitiveValue* item = static_cast<CSSPrimitiveValue*>(familyList->itemWithoutBoundsCheck(i));
+ String familyName;
+ if (item->primitiveType() == CSSPrimitiveValue::CSS_STRING)
+ familyName = static_cast<FontFamilyValue*>(item)->familyName();
+ else if (item->primitiveType() == CSSPrimitiveValue::CSS_IDENT) {
+ // 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;
+ switch (item->getIdent()) {
+ case CSSValueSerif:
+ familyName = serifFamily;
+ break;
+ case CSSValueSansSerif:
+ familyName = sansSerifFamily;
+ break;
+ case CSSValueCursive:
+ familyName = cursiveFamily;
+ break;
+ case CSSValueFantasy:
+ familyName = fantasyFamily;
+ break;
+ case CSSValueMonospace:
+ familyName = monospaceFamily;
+ break;
+ case CSSValueWebkitPictograph:
+ familyName = pictographFamily;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (familyName.isEmpty())
+ continue;
+
+ OwnPtr<Vector<RefPtr<CSSFontFace> > >& familyFontFaces = m_fontFaces.add(familyName, nullptr).first->second;
+ if (!familyFontFaces) {
+ familyFontFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >);
+
+ ASSERT(!m_locallyInstalledFontFaces.contains(familyName));
+
+ Vector<unsigned> locallyInstalledFontsTraitsMasks;
+ fontCache()->getTraitsInFamily(familyName, locallyInstalledFontsTraitsMasks);
+ if (unsigned numLocallyInstalledFaces = locallyInstalledFontsTraitsMasks.size()) {
+ OwnPtr<Vector<RefPtr<CSSFontFace> > > familyLocallyInstalledFaces = adoptPtr(new Vector<RefPtr<CSSFontFace> >);
+
+ for (unsigned i = 0; i < numLocallyInstalledFaces; ++i) {
+ RefPtr<CSSFontFace> locallyInstalledFontFace = CSSFontFace::create(static_cast<FontTraitsMask>(locallyInstalledFontsTraitsMasks[i]), true);
+ locallyInstalledFontFace->addSource(adoptPtr(new CSSFontFaceSource(familyName)));
+ ASSERT(locallyInstalledFontFace->isValid());
+ familyLocallyInstalledFaces->append(locallyInstalledFontFace);
+ }
+
+ m_locallyInstalledFontFaces.set(familyName, familyLocallyInstalledFaces.release());
+ }
+ }
+
+ familyFontFaces->append(fontFace);
+ }
+}
+
+void CSSFontSelector::registerForInvalidationCallbacks(FontSelectorClient* client)
+{
+ m_clients.add(client);
+}
+
+void CSSFontSelector::unregisterForInvalidationCallbacks(FontSelectorClient* client)
+{
+ m_clients.remove(client);
+}
+
+void CSSFontSelector::dispatchInvalidationCallbacks()
+{
+ Vector<FontSelectorClient*> clients;
+ copyToVector(m_clients, clients);
+ for (size_t i = 0; i < clients.size(); ++i)
+ clients[i]->fontsNeedUpdate(this);
+
+ // FIXME: Make Document a FontSelectorClient so that it can simply register for invalidation callbacks.
+ if (!m_document)
+ return;
+ if (CSSStyleSelector* styleSelector = m_document->styleSelectorIfExists())
+ styleSelector->invalidateMatchedDeclarationCache();
+ if (m_document->inPageCache() || !m_document->renderer())
+ return;
+ m_document->scheduleForcedStyleRecalc();
+}
+
+void CSSFontSelector::fontLoaded()
+{
+ dispatchInvalidationCallbacks();
+}
+
+void CSSFontSelector::fontCacheInvalidated()
+{
+ dispatchInvalidationCallbacks();
+}
+
+static FontData* fontDataForGenericFamily(Document* document, const FontDescription& fontDescription, const AtomicString& familyName)
+{
+ if (!document || !document->frame())
+ return 0;
+
+ const Settings* settings = document->frame()->settings();
+ if (!settings)
+ return 0;
+
+ AtomicString genericFamily;
+ UScriptCode script = fontDescription.script();
+
+ if (familyName == serifFamily)
+ genericFamily = settings->serifFontFamily(script);
+ else if (familyName == sansSerifFamily)
+ genericFamily = settings->sansSerifFontFamily(script);
+ else if (familyName == cursiveFamily)
+ genericFamily = settings->cursiveFontFamily(script);
+ else if (familyName == fantasyFamily)
+ genericFamily = settings->fantasyFontFamily(script);
+ else if (familyName == monospaceFamily)
+ genericFamily = settings->fixedFontFamily(script);
+ else if (familyName == pictographFamily)
+ genericFamily = settings->pictographFontFamily(script);
+ else if (familyName == standardFamily)
+ genericFamily = settings->standardFontFamily(script);
+
+ if (!genericFamily.isEmpty())
+ return fontCache()->getCachedFontData(fontDescription, genericFamily);
+
+ return 0;
+}
+
+static FontTraitsMask desiredTraitsMaskForComparison;
+
+static inline bool compareFontFaces(CSSFontFace* first, CSSFontFace* second)
+{
+ FontTraitsMask firstTraitsMask = first->traitsMask();
+ FontTraitsMask secondTraitsMask = second->traitsMask();
+
+ bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
+ bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMaskForComparison & FontVariantMask;
+
+ if (firstHasDesiredVariant != secondHasDesiredVariant)
+ return firstHasDesiredVariant;
+
+ if ((desiredTraitsMaskForComparison & FontVariantSmallCapsMask) && !first->isLocalFallback() && !second->isLocalFallback()) {
+ // Prefer a font that has indicated that it can only support small-caps to a font that claims to support
+ // all variants. The specialized font is more likely to be true small-caps and not require synthesis.
+ bool firstRequiresSmallCaps = (firstTraitsMask & FontVariantSmallCapsMask) && !(firstTraitsMask & FontVariantNormalMask);
+ bool secondRequiresSmallCaps = (secondTraitsMask & FontVariantSmallCapsMask) && !(secondTraitsMask & FontVariantNormalMask);
+ if (firstRequiresSmallCaps != secondRequiresSmallCaps)
+ return firstRequiresSmallCaps;
+ }
+
+ bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
+ bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMaskForComparison & FontStyleMask;
+
+ if (firstHasDesiredStyle != secondHasDesiredStyle)
+ return firstHasDesiredStyle;
+
+ if ((desiredTraitsMaskForComparison & FontStyleItalicMask) && !first->isLocalFallback() && !second->isLocalFallback()) {
+ // Prefer a font that has indicated that it can only support italics to a font that claims to support
+ // all styles. The specialized font is more likely to be the one the author wants used.
+ bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask);
+ bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask);
+ if (firstRequiresItalics != secondRequiresItalics)
+ return firstRequiresItalics;
+ }
+
+ if (secondTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
+ return false;
+ if (firstTraitsMask & desiredTraitsMaskForComparison & FontWeightMask)
+ return true;
+
+ // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#q46 says: "If there are fewer then 9 weights in the family, the default algorithm
+ // for filling the "holes" is as follows. If '500' is unassigned, it will be assigned the same font as '400'. If any of the values '600',
+ // '700', '800', or '900' remains unassigned, they are assigned to the same face as the next darker assigned keyword, if any, or the next
+ // lighter one otherwise. If any of '300', '200', or '100' remains unassigned, it is assigned to the next lighter assigned keyword, if any,
+ // or the next darker otherwise."
+ // For '400', we made up our own rule (which then '500' follows).
+
+ static const unsigned fallbackRuleSets = 9;
+ static const unsigned rulesPerSet = 8;
+ static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = {
+ { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
+ { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
+ { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask },
+ { FontWeight500Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask },
+ { FontWeight400Mask, FontWeight300Mask, FontWeight600Mask, FontWeight200Mask, FontWeight700Mask, FontWeight100Mask, FontWeight800Mask, FontWeight900Mask },
+ { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
+ { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
+ { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask },
+ { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }
+ };
+
+ unsigned ruleSetIndex = 0;
+ unsigned w = FontWeight100Bit;
+ while (!(desiredTraitsMaskForComparison & (1 << w))) {
+ w++;
+ ruleSetIndex++;
+ }
+
+ ASSERT(ruleSetIndex < fallbackRuleSets);
+ const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];
+ for (unsigned i = 0; i < rulesPerSet; ++i) {
+ if (secondTraitsMask & weightFallbackRule[i])
+ return false;
+ if (firstTraitsMask & weightFallbackRule[i])
+ return true;
+ }
+
+ return false;
+}
+
+FontData* CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName)
+{
+ if (m_fontFaces.isEmpty()) {
+ if (familyName.startsWith("-webkit-"))
+ return fontDataForGenericFamily(m_document, fontDescription, familyName);
+ if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
+ return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard");
+ return 0;
+ }
+
+ String family = familyName.string();
+
+ Vector<RefPtr<CSSFontFace> >* familyFontFaces = m_fontFaces.get(family);
+ // If no face was found, then return 0 and let the OS come up with its best match for the name.
+ if (!familyFontFaces || familyFontFaces->isEmpty()) {
+ // If we were handed a generic family, but there was no match, go ahead and return the correct font based off our
+ // settings.
+ if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont())
+ return fontDataForGenericFamily(m_document, fontDescription, "-webkit-standard");
+ return fontDataForGenericFamily(m_document, fontDescription, familyName);
+ }
+
+ OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFaceCache = m_fonts.add(family, nullptr).first->second;
+ if (!segmentedFontFaceCache)
+ segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >);
+
+ FontTraitsMask traitsMask = fontDescription.traitsMask();
+
+ RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).first->second;
+ if (!face) {
+ face = CSSSegmentedFontFace::create(this);
+
+ // Collect all matching faces and sort them in order of preference.
+ Vector<CSSFontFace*, 32> candidateFontFaces;
+ for (int i = familyFontFaces->size() - 1; i >= 0; --i) {
+ CSSFontFace* candidate = familyFontFaces->at(i).get();
+ unsigned candidateTraitsMask = candidate->traitsMask();
+ if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
+ continue;
+ if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
+ continue;
+#if ENABLE(SVG_FONTS)
+ // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable
+ // of small-caps synthesis and just ignore the font face as a candidate.
+ if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask))
+ continue;
+#endif
+ candidateFontFaces.append(candidate);
+ }
+
+ if (Vector<RefPtr<CSSFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) {
+ unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size();
+ for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) {
+ CSSFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get();
+ unsigned candidateTraitsMask = candidate->traitsMask();
+ if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask))
+ continue;
+ if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask))
+ continue;
+ candidateFontFaces.append(candidate);
+ }
+ }
+
+ desiredTraitsMaskForComparison = traitsMask;
+ stable_sort(candidateFontFaces.begin(), candidateFontFaces.end(), compareFontFaces);
+ unsigned numCandidates = candidateFontFaces.size();
+ for (unsigned i = 0; i < numCandidates; ++i)
+ face->appendFontFace(candidateFontFaces[i]);
+ }
+
+ // We have a face. Ask it for a font data. If it cannot produce one, it will fail, and the OS will take over.
+ return face->getFontData(fontDescription);
+}
+
+void CSSFontSelector::clearDocument()
+{
+ if (!m_document) {
+ ASSERT(!m_beginLoadingTimer.isActive());
+ ASSERT(m_fontsToBeginLoading.isEmpty());
+ return;
+ }
+
+ m_beginLoadingTimer.stop();
+
+ CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
+ for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) {
+ // Balances incrementRequestCount() in beginLoadingFontSoon().
+ cachedResourceLoader->decrementRequestCount(m_fontsToBeginLoading[i].get());
+ }
+
+ m_fontsToBeginLoading.clear();
+
+ m_document = 0;
+}
+
+void CSSFontSelector::beginLoadingFontSoon(CachedFont* font)
+{
+ if (!m_document)
+ return;
+
+ m_fontsToBeginLoading.append(font);
+ // Increment the request count now, in order to prevent didFinishLoad from being dispatched
+ // after this font has been requested but before it began loading. Balanced by
+ // decrementRequestCount() in beginLoadTimerFired() and in clearDocument().
+ m_document->cachedResourceLoader()->incrementRequestCount(font);
+ m_beginLoadingTimer.startOneShot(0);
+}
+
+void CSSFontSelector::beginLoadTimerFired(Timer<WebCore::CSSFontSelector>*)
+{
+ Vector<CachedResourceHandle<CachedFont> > fontsToBeginLoading;
+ fontsToBeginLoading.swap(m_fontsToBeginLoading);
+
+ CachedResourceLoader* cachedResourceLoader = m_document->cachedResourceLoader();
+ for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) {
+ fontsToBeginLoading[i]->beginLoadIfNeeded(cachedResourceLoader);
+ // Balances incrementRequestCount() in beginLoadingFontSoon().
+ cachedResourceLoader->decrementRequestCount(fontsToBeginLoading[i].get());
+ }
+}
+
+}
diff --git a/Source/WebCore/css/CSSFontSelector.h b/Source/WebCore/css/CSSFontSelector.h
new file mode 100644
index 000000000..3e992cc74
--- /dev/null
+++ b/Source/WebCore/css/CSSFontSelector.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007, 2008, 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 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 CSSFontSelector_h
+#define CSSFontSelector_h
+
+#include "CachedResourceHandle.h"
+#include "FontSelector.h"
+#include "Timer.h"
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class CSSFontFace;
+class CSSFontFaceRule;
+class CSSSegmentedFontFace;
+class CachedFont;
+class Document;
+class FontDescription;
+
+class CSSFontSelector : public FontSelector {
+public:
+ static PassRefPtr<CSSFontSelector> create(Document* document)
+ {
+ return adoptRef(new CSSFontSelector(document));
+ }
+ virtual ~CSSFontSelector();
+
+ virtual FontData* getFontData(const FontDescription& fontDescription, const AtomicString& familyName);
+
+ void clearDocument();
+
+ void addFontFaceRule(const CSSFontFaceRule*);
+
+ void fontLoaded();
+ virtual void fontCacheInvalidated();
+
+ bool isEmpty() const;
+
+ virtual void registerForInvalidationCallbacks(FontSelectorClient*);
+ virtual void unregisterForInvalidationCallbacks(FontSelectorClient*);
+
+ Document* document() const { return m_document; }
+
+ void beginLoadingFontSoon(CachedFont*);
+
+private:
+ CSSFontSelector(Document*);
+
+ void dispatchInvalidationCallbacks();
+
+ void beginLoadTimerFired(Timer<CSSFontSelector>*);
+
+ Document* m_document;
+ HashMap<String, OwnPtr<Vector<RefPtr<CSSFontFace> > >, CaseFoldingHash> m_fontFaces;
+ HashMap<String, OwnPtr<Vector<RefPtr<CSSFontFace> > >, CaseFoldingHash> m_locallyInstalledFontFaces;
+ HashMap<String, OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >, CaseFoldingHash> m_fonts;
+ HashSet<FontSelectorClient*> m_clients;
+
+ Vector<CachedResourceHandle<CachedFont> > m_fontsToBeginLoading;
+ Timer<CSSFontSelector> m_beginLoadingTimer;
+};
+
+} // namespace WebCore
+
+#endif // CSSFontSelector_h
diff --git a/Source/WebCore/css/CSSFunctionValue.cpp b/Source/WebCore/css/CSSFunctionValue.cpp
new file mode 100644
index 000000000..522ad9fd1
--- /dev/null
+++ b/Source/WebCore/css/CSSFunctionValue.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008, 2010 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. ``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
+ * 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 "CSSFunctionValue.h"
+
+#include "CSSParserValues.h"
+#include "CSSValueList.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+CSSFunctionValue::CSSFunctionValue(CSSParserFunction* function)
+ : CSSValue(FunctionClass)
+ , m_name(function->name)
+{
+ if (function->args)
+ m_args = CSSValueList::createFromParserValueList(function->args.get());
+}
+
+String CSSFunctionValue::customCssText() const
+{
+ String result = m_name; // Includes the '('
+ if (m_args)
+ result += m_args->cssText();
+ result += ")";
+ return result;
+}
+
+}
diff --git a/Source/WebCore/css/CSSFunctionValue.h b/Source/WebCore/css/CSSFunctionValue.h
new file mode 100644
index 000000000..a35a1b17b
--- /dev/null
+++ b/Source/WebCore/css/CSSFunctionValue.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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. ``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
+ * 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 CSSFunctionValue_h
+#define CSSFunctionValue_h
+
+#include "CSSValue.h"
+
+namespace WebCore {
+
+class CSSValueList;
+struct CSSParserFunction;
+
+class CSSFunctionValue : public CSSValue {
+public:
+ static PassRefPtr<CSSFunctionValue> create(CSSParserFunction* function)
+ {
+ return adoptRef(new CSSFunctionValue(function));
+ }
+
+ String customCssText() const;
+
+private:
+ explicit CSSFunctionValue(CSSParserFunction*);
+
+ String m_name;
+ RefPtr<CSSValueList> m_args;
+};
+
+}
+#endif
+
diff --git a/Source/WebCore/css/CSSGradientValue.cpp b/Source/WebCore/css/CSSGradientValue.cpp
new file mode 100644
index 000000000..41977fb03
--- /dev/null
+++ b/Source/WebCore/css/CSSGradientValue.cpp
@@ -0,0 +1,868 @@
+/*
+ * Copyright (C) 2008 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 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.
+ */
+
+#include "config.h"
+#include "CSSGradientValue.h"
+
+#include "CSSStyleSelector.h"
+#include "CSSValueKeywords.h"
+#include "GeneratorGeneratedImage.h"
+#include "Gradient.h"
+#include "Image.h"
+#include "IntSize.h"
+#include "IntSizeHash.h"
+#include "NodeRenderStyle.h"
+#include "PlatformString.h"
+#include "RenderObject.h"
+
+using namespace std;
+
+namespace WebCore {
+
+PassRefPtr<Image> CSSGradientValue::image(RenderObject* renderer, const IntSize& size)
+{
+ if (size.isEmpty())
+ return 0;
+
+ bool cacheable = isCacheable();
+ if (cacheable) {
+ if (!clients().contains(renderer))
+ return 0;
+
+ // Need to look up our size. Create a string of width*height to use as a hash key.
+ Image* result = getImage(renderer, size);
+ if (result)
+ return result;
+ }
+
+ // We need to create an image.
+ RefPtr<Gradient> gradient;
+
+ if (isLinearGradient())
+ gradient = static_cast<CSSLinearGradientValue*>(this)->createGradient(renderer, size);
+ else {
+ ASSERT(isRadialGradient());
+ gradient = static_cast<CSSRadialGradientValue*>(this)->createGradient(renderer, size);
+ }
+
+ RefPtr<Image> newImage = GeneratorGeneratedImage::create(gradient, size);
+ if (cacheable)
+ putImage(size, newImage);
+
+ return newImage.release();
+}
+
+// Should only ever be called for deprecated gradients.
+static inline bool compareStops(const CSSGradientColorStop& a, const CSSGradientColorStop& b)
+{
+ double aVal = a.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER);
+ double bVal = b.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER);
+
+ return aVal < bVal;
+}
+
+void CSSGradientValue::sortStopsIfNeeded()
+{
+ ASSERT(m_deprecatedType);
+ if (!m_stopsSorted) {
+ if (m_stops.size())
+ std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
+ m_stopsSorted = true;
+ }
+}
+
+struct GradientStop {
+ Color color;
+ float offset;
+ bool specified;
+
+ GradientStop()
+ : offset(0)
+ , specified(false)
+ { }
+};
+
+void CSSGradientValue::addStops(Gradient* gradient, RenderObject* renderer, RenderStyle* rootStyle, float maxLengthForRepeat)
+{
+ RenderStyle* style = renderer->style();
+
+ if (m_deprecatedType) {
+ sortStopsIfNeeded();
+
+ // We have to resolve colors.
+ for (unsigned i = 0; i < m_stops.size(); i++) {
+ const CSSGradientColorStop& stop = m_stops[i];
+ Color color = renderer->document()->styleSelector()->colorFromPrimitiveValue(stop.m_color.get());
+
+ float offset;
+ if (stop.m_position->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100;
+ else
+ offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
+
+ gradient->addColorStop(offset, color);
+ }
+
+ // The back end already sorted the stops.
+ gradient->setStopsSorted(true);
+ return;
+ }
+
+ size_t numStops = m_stops.size();
+
+ Vector<GradientStop> stops(numStops);
+
+ float gradientLength = 0;
+ bool computedGradientLength = false;
+
+ FloatPoint gradientStart = gradient->p0();
+ FloatPoint gradientEnd;
+ if (isLinearGradient())
+ gradientEnd = gradient->p1();
+ else if (isRadialGradient())
+ gradientEnd = gradientStart + FloatSize(gradient->endRadius(), 0);
+
+ for (size_t i = 0; i < numStops; ++i) {
+ const CSSGradientColorStop& stop = m_stops[i];
+
+ 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)
+ stops[i].offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100;
+ else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+ float length = stop.m_position->computeLength<float>(style, rootStyle, style->effectiveZoom());
+ if (!computedGradientLength) {
+ FloatSize gradientSize(gradientStart - gradientEnd);
+ gradientLength = gradientSize.diagonalLength();
+ }
+ stops[i].offset = (gradientLength > 0) ? length / gradientLength : 0;
+ } else {
+ ASSERT_NOT_REACHED();
+ stops[i].offset = 0;
+ }
+ stops[i].specified = true;
+ } else {
+ // If the first color-stop does not have a position, its position defaults to 0%.
+ // If the last color-stop does not have a position, its position defaults to 100%.
+ if (!i) {
+ stops[i].offset = 0;
+ stops[i].specified = true;
+ } else if (numStops > 1 && i == numStops - 1) {
+ stops[i].offset = 1;
+ stops[i].specified = true;
+ }
+ }
+
+ // If a color-stop has a position that is less than the specified position of any
+ // color-stop before it in the list, its position is changed to be equal to the
+ // largest specified position of any color-stop before it.
+ if (stops[i].specified && i > 0) {
+ size_t prevSpecifiedIndex;
+ for (prevSpecifiedIndex = i - 1; prevSpecifiedIndex; --prevSpecifiedIndex) {
+ if (stops[prevSpecifiedIndex].specified)
+ break;
+ }
+
+ if (stops[i].offset < stops[prevSpecifiedIndex].offset)
+ stops[i].offset = stops[prevSpecifiedIndex].offset;
+ }
+ }
+
+ ASSERT(stops[0].specified && stops[numStops - 1].specified);
+
+ // If any color-stop still does not have a position, then, for each run of adjacent
+ // color-stops without positions, set their positions so that they are evenly spaced
+ // between the preceding and following color-stops with positions.
+ if (numStops > 2) {
+ size_t unspecifiedRunStart = 0;
+ bool inUnspecifiedRun = false;
+
+ for (size_t i = 0; i < numStops; ++i) {
+ if (!stops[i].specified && !inUnspecifiedRun) {
+ unspecifiedRunStart = i;
+ inUnspecifiedRun = true;
+ } else if (stops[i].specified && inUnspecifiedRun) {
+ size_t unspecifiedRunEnd = i;
+
+ if (unspecifiedRunStart < unspecifiedRunEnd) {
+ float lastSpecifiedOffset = stops[unspecifiedRunStart - 1].offset;
+ float nextSpecifiedOffset = stops[unspecifiedRunEnd].offset;
+ float delta = (nextSpecifiedOffset - lastSpecifiedOffset) / (unspecifiedRunEnd - unspecifiedRunStart + 1);
+
+ for (size_t j = unspecifiedRunStart; j < unspecifiedRunEnd; ++j)
+ stops[j].offset = lastSpecifiedOffset + (j - unspecifiedRunStart + 1) * delta;
+ }
+
+ inUnspecifiedRun = false;
+ }
+ }
+ }
+
+ // If the gradient is repeating, repeat the color stops.
+ // We can't just push this logic down into the platform-specific Gradient code,
+ // because we have to know the extent of the gradient, and possible move the end points.
+ if (m_repeating && numStops > 1) {
+ // If the difference in the positions of the first and last color-stops is 0,
+ // the gradient defines a solid-color image with the color of the last color-stop in the rule.
+ float gradientRange = stops[numStops - 1].offset - stops[0].offset;
+ if (!gradientRange) {
+ stops.first().offset = 0;
+ stops.first().color = stops.last().color;
+ stops.shrink(1);
+ numStops = 1;
+ } else {
+ float maxExtent = 1;
+
+ // Radial gradients may need to extend further than the endpoints, because they have
+ // to repeat out to the corners of the box.
+ if (isRadialGradient()) {
+ if (!computedGradientLength) {
+ FloatSize gradientSize(gradientStart - gradientEnd);
+ gradientLength = gradientSize.diagonalLength();
+ }
+
+ if (maxLengthForRepeat > gradientLength)
+ maxExtent = maxLengthForRepeat / gradientLength;
+ }
+
+ size_t originalNumStops = numStops;
+ size_t originalFirstStopIndex = 0;
+
+ // Work backwards from the first, adding stops until we get one before 0.
+ float firstOffset = stops[0].offset;
+ if (firstOffset > 0) {
+ float currOffset = firstOffset;
+ size_t srcStopOrdinal = originalNumStops - 1;
+
+ while (true) {
+ GradientStop newStop = stops[originalFirstStopIndex + srcStopOrdinal];
+ newStop.offset = currOffset;
+ stops.prepend(newStop);
+ ++originalFirstStopIndex;
+ if (currOffset < 0)
+ break;
+
+ if (srcStopOrdinal)
+ currOffset -= stops[originalFirstStopIndex + srcStopOrdinal].offset - stops[originalFirstStopIndex + srcStopOrdinal - 1].offset;
+ srcStopOrdinal = (srcStopOrdinal + originalNumStops - 1) % originalNumStops;
+ }
+ }
+
+ // Work forwards from the end, adding stops until we get one after 1.
+ float lastOffset = stops[stops.size() - 1].offset;
+ if (lastOffset < maxExtent) {
+ float currOffset = lastOffset;
+ size_t srcStopOrdinal = 0;
+
+ while (true) {
+ size_t srcStopIndex = originalFirstStopIndex + srcStopOrdinal;
+ GradientStop newStop = stops[srcStopIndex];
+ newStop.offset = currOffset;
+ stops.append(newStop);
+ if (currOffset > maxExtent)
+ break;
+ if (srcStopOrdinal < originalNumStops - 1)
+ currOffset += stops[srcStopIndex + 1].offset - stops[srcStopIndex].offset;
+ srcStopOrdinal = (srcStopOrdinal + 1) % originalNumStops;
+ }
+ }
+ }
+ }
+
+ numStops = stops.size();
+
+ // If the gradient goes outside the 0-1 range, normalize it by moving the endpoints, and adjusting the stops.
+ if (numStops > 1 && (stops[0].offset < 0 || stops[numStops - 1].offset > 1)) {
+ if (isLinearGradient()) {
+ float firstOffset = stops[0].offset;
+ float lastOffset = stops[numStops - 1].offset;
+ float scale = lastOffset - firstOffset;
+
+ for (size_t i = 0; i < numStops; ++i)
+ stops[i].offset = (stops[i].offset - firstOffset) / scale;
+
+ FloatPoint p0 = gradient->p0();
+ FloatPoint p1 = gradient->p1();
+ gradient->setP0(FloatPoint(p0.x() + firstOffset * (p1.x() - p0.x()), p0.y() + firstOffset * (p1.y() - p0.y())));
+ gradient->setP1(FloatPoint(p1.x() + (lastOffset - 1) * (p1.x() - p0.x()), p1.y() + (lastOffset - 1) * (p1.y() - p0.y())));
+ } else if (isRadialGradient()) {
+ // Rather than scaling the points < 0, we truncate them, so only scale according to the largest point.
+ float firstOffset = 0;
+ float lastOffset = stops[numStops - 1].offset;
+ float scale = lastOffset - firstOffset;
+
+ // Reset points below 0 to the first visible color.
+ size_t firstZeroOrGreaterIndex = numStops;
+ for (size_t i = 0; i < numStops; ++i) {
+ if (stops[i].offset >= 0) {
+ firstZeroOrGreaterIndex = i;
+ break;
+ }
+ }
+
+ if (firstZeroOrGreaterIndex > 0) {
+ if (firstZeroOrGreaterIndex < numStops && stops[firstZeroOrGreaterIndex].offset > 0) {
+ float prevOffset = stops[firstZeroOrGreaterIndex - 1].offset;
+ float nextOffset = stops[firstZeroOrGreaterIndex].offset;
+
+ float interStopProportion = -prevOffset / (nextOffset - prevOffset);
+ // FIXME: when we interpolate gradients using premultiplied colors, this should do premultiplication.
+ Color blendedColor = blend(stops[firstZeroOrGreaterIndex - 1].color, stops[firstZeroOrGreaterIndex].color, interStopProportion);
+
+ // Clamp the positions to 0 and set the color.
+ for (size_t i = 0; i < firstZeroOrGreaterIndex; ++i) {
+ stops[i].offset = 0;
+ stops[i].color = blendedColor;
+ }
+ } else {
+ // All stops are below 0; just clamp them.
+ for (size_t i = 0; i < firstZeroOrGreaterIndex; ++i)
+ stops[i].offset = 0;
+ }
+ }
+
+ for (size_t i = 0; i < numStops; ++i)
+ stops[i].offset /= scale;
+
+ gradient->setStartRadius(gradient->startRadius() * scale);
+ gradient->setEndRadius(gradient->endRadius() * scale);
+ }
+ }
+
+ for (unsigned i = 0; i < numStops; i++)
+ gradient->addColorStop(stops[i].offset, stops[i].color);
+
+ gradient->setStopsSorted(true);
+}
+
+static float positionFromValue(CSSPrimitiveValue* value, RenderStyle* style, RenderStyle* rootStyle, const IntSize& size, bool isHorizontal)
+{
+ float zoomFactor = style->effectiveZoom();
+
+ switch (value->primitiveType()) {
+ case CSSPrimitiveValue::CSS_NUMBER:
+ return value->getFloatValue() * zoomFactor;
+
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ 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);
+ }
+}
+
+FloatPoint CSSGradientValue::computeEndPoint(CSSPrimitiveValue* first, CSSPrimitiveValue* second, RenderStyle* style, RenderStyle* rootStyle, const IntSize& size)
+{
+ FloatPoint result;
+
+ if (first)
+ result.setX(positionFromValue(first, style, rootStyle, size, true));
+
+ if (second)
+ result.setY(positionFromValue(second, style, rootStyle, size, false));
+
+ return result;
+}
+
+bool CSSGradientValue::isCacheable() const
+{
+ for (size_t i = 0; i < m_stops.size(); ++i) {
+ const CSSGradientColorStop& stop = m_stops[i];
+
+ CSSPrimitiveValue* color = stop.m_color.get();
+ if (color->getIdent() == CSSValueCurrentcolor)
+ return false;
+
+ 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)
+ return false;
+ }
+
+ return true;
+}
+
+String CSSLinearGradientValue::customCssText() const
+{
+ String result;
+ if (m_deprecatedType) {
+ result = "-webkit-gradient(linear, ";
+ result += m_firstX->cssText() + " ";
+ result += m_firstY->cssText() + ", ";
+ result += m_secondX->cssText() + " ";
+ result += m_secondY->cssText();
+
+ for (unsigned i = 0; i < m_stops.size(); i++) {
+ const CSSGradientColorStop& stop = m_stops[i];
+ result += ", ";
+ if (stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 0)
+ result += "from(" + stop.m_color->cssText() + ")";
+ else if (stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 1)
+ result += "to(" + stop.m_color->cssText() + ")";
+ else
+ result += "color-stop(" + String::number(stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER)) + ", " + stop.m_color->cssText() + ")";
+ }
+ } else {
+ result = m_repeating ? "-webkit-repeating-linear-gradient(" : "-webkit-linear-gradient(";
+ if (m_angle)
+ result += m_angle->cssText();
+ else {
+ if (m_firstX && m_firstY)
+ result += m_firstX->cssText() + " " + m_firstY->cssText();
+ else if (m_firstX || m_firstY) {
+ if (m_firstX)
+ result += m_firstX->cssText();
+
+ if (m_firstY)
+ result += m_firstY->cssText();
+ }
+ }
+
+ for (unsigned i = 0; i < m_stops.size(); i++) {
+ const CSSGradientColorStop& stop = m_stops[i];
+ result += ", ";
+ result += stop.m_color->cssText();
+ if (stop.m_position)
+ result += " " + stop.m_position->cssText();
+ }
+ }
+
+ result += ")";
+ return result;
+}
+
+// Compute the endpoints so that a gradient of the given angle covers a box of the given size.
+static void endPointsFromAngle(float angleDeg, const IntSize& size, FloatPoint& firstPoint, FloatPoint& secondPoint)
+{
+ angleDeg = fmodf(angleDeg, 360);
+ if (angleDeg < 0)
+ angleDeg += 360;
+
+ if (!angleDeg) {
+ firstPoint.set(0, 0);
+ secondPoint.set(size.width(), 0);
+ return;
+ }
+
+ if (angleDeg == 90) {
+ firstPoint.set(0, size.height());
+ secondPoint.set(0, 0);
+ return;
+ }
+
+ if (angleDeg == 180) {
+ firstPoint.set(size.width(), 0);
+ secondPoint.set(0, 0);
+ return;
+ }
+
+ if (angleDeg == 270) {
+ firstPoint.set(0, 0);
+ secondPoint.set(0, size.height());
+ return;
+ }
+
+ float slope = tan(deg2rad(angleDeg));
+
+ // We find the endpoint by computing the intersection of the line formed by the slope,
+ // and a line perpendicular to it that intersects the corner.
+ float perpendicularSlope = -1 / slope;
+
+ // Compute start corner relative to center.
+ float halfHeight = size.height() / 2;
+ float halfWidth = size.width() / 2;
+ FloatPoint endCorner;
+ if (angleDeg < 90)
+ endCorner.set(halfWidth, halfHeight);
+ else if (angleDeg < 180)
+ endCorner.set(-halfWidth, halfHeight);
+ else if (angleDeg < 270)
+ endCorner.set(-halfWidth, -halfHeight);
+ else
+ endCorner.set(halfWidth, -halfHeight);
+
+ // Compute c (of y = mx + c) using the corner point.
+ float c = endCorner.y() - perpendicularSlope * endCorner.x();
+ float endX = c / (slope - perpendicularSlope);
+ float endY = perpendicularSlope * endX + c;
+
+ // We computed the end point, so set the second point, flipping the Y to account for angles going anticlockwise.
+ secondPoint.set(halfWidth + endX, size.height() - (halfHeight + endY));
+ // Reflect around the center for the start point.
+ firstPoint.set(size.width() - secondPoint.x(), size.height() - secondPoint.y());
+}
+
+PassRefPtr<Gradient> CSSLinearGradientValue::createGradient(RenderObject* renderer, const IntSize& size)
+{
+ ASSERT(!size.isEmpty());
+
+ RenderStyle* rootStyle = renderer->document()->documentElement()->renderStyle();
+
+ FloatPoint firstPoint;
+ FloatPoint secondPoint;
+ if (m_angle) {
+ float angle = m_angle->getFloatValue(CSSPrimitiveValue::CSS_DEG);
+ endPointsFromAngle(angle, size, firstPoint, secondPoint);
+ } else {
+ firstPoint = computeEndPoint(m_firstX.get(), m_firstY.get(), renderer->style(), rootStyle, size);
+
+ if (m_secondX || m_secondY)
+ secondPoint = computeEndPoint(m_secondX.get(), m_secondY.get(), renderer->style(), rootStyle, size);
+ else {
+ if (m_firstX)
+ secondPoint.setX(size.width() - firstPoint.x());
+ if (m_firstY)
+ secondPoint.setY(size.height() - firstPoint.y());
+ }
+ }
+
+ RefPtr<Gradient> gradient = Gradient::create(firstPoint, secondPoint);
+
+ // Now add the stops.
+ addStops(gradient.get(), renderer, rootStyle, 1);
+
+ return gradient.release();
+}
+
+String CSSRadialGradientValue::customCssText() const
+{
+ String result;
+
+ if (m_deprecatedType) {
+ result = "-webkit-gradient(radial, ";
+
+ result += m_firstX->cssText() + " ";
+ result += m_firstY->cssText() + ", ";
+ result += m_firstRadius->cssText() + ", ";
+ result += m_secondX->cssText() + " ";
+ result += m_secondY->cssText();
+ result += ", ";
+ result += m_secondRadius->cssText();
+
+ // FIXME: share?
+ for (unsigned i = 0; i < m_stops.size(); i++) {
+ const CSSGradientColorStop& stop = m_stops[i];
+ result += ", ";
+ if (stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 0)
+ result += "from(" + stop.m_color->cssText() + ")";
+ else if (stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 1)
+ result += "to(" + stop.m_color->cssText() + ")";
+ else
+ result += "color-stop(" + String::number(stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER)) + ", " + stop.m_color->cssText() + ")";
+ }
+ } else {
+
+ result = m_repeating ? "-webkit-repeating-radial-gradient(" : "-webkit-radial-gradient(";
+ if (m_firstX && m_firstY) {
+ result += m_firstX->cssText() + " " + m_firstY->cssText();
+ } else if (m_firstX)
+ result += m_firstX->cssText();
+ else if (m_firstY)
+ result += m_firstY->cssText();
+ else
+ result += "center";
+
+
+ if (m_shape || m_sizingBehavior) {
+ result += ", ";
+ if (m_shape)
+ result += m_shape->cssText() + " ";
+ else
+ result += "ellipse ";
+
+ if (m_sizingBehavior)
+ result += m_sizingBehavior->cssText();
+ else
+ result += "cover";
+
+ } else if (m_endHorizontalSize && m_endVerticalSize) {
+ result += ", ";
+ result += m_endHorizontalSize->cssText() + " " + m_endVerticalSize->cssText();
+ }
+
+ for (unsigned i = 0; i < m_stops.size(); i++) {
+ const CSSGradientColorStop& stop = m_stops[i];
+ result += ", ";
+ result += stop.m_color->cssText();
+ if (stop.m_position)
+ result += " " + stop.m_position->cssText();
+ }
+ }
+
+ result += ")";
+ return result;
+}
+
+float CSSRadialGradientValue::resolveRadius(CSSPrimitiveValue* radius, RenderStyle* style, RenderStyle* rootStyle, float* widthOrHeight)
+{
+ float zoomFactor = style->effectiveZoom();
+
+ float result = 0;
+ if (radius->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // Can the radius be a percentage?
+ result = radius->getFloatValue() * zoomFactor;
+ else if (widthOrHeight && radius->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ result = *widthOrHeight * radius->getFloatValue() / 100;
+ else
+ result = radius->computeLength<float>(style, rootStyle, zoomFactor);
+
+ return result;
+}
+
+static float distanceToClosestCorner(const FloatPoint& p, const FloatSize& size, FloatPoint& corner)
+{
+ FloatPoint topLeft;
+ float topLeftDistance = FloatSize(p - topLeft).diagonalLength();
+
+ FloatPoint topRight(size.width(), 0);
+ float topRightDistance = FloatSize(p - topRight).diagonalLength();
+
+ FloatPoint bottomLeft(0, size.height());
+ float bottomLeftDistance = FloatSize(p - bottomLeft).diagonalLength();
+
+ FloatPoint bottomRight(size.width(), size.height());
+ float bottomRightDistance = FloatSize(p - bottomRight).diagonalLength();
+
+ corner = topLeft;
+ float minDistance = topLeftDistance;
+ if (topRightDistance < minDistance) {
+ minDistance = topRightDistance;
+ corner = topRight;
+ }
+
+ if (bottomLeftDistance < minDistance) {
+ minDistance = bottomLeftDistance;
+ corner = bottomLeft;
+ }
+
+ if (bottomRightDistance < minDistance) {
+ minDistance = bottomRightDistance;
+ corner = bottomRight;
+ }
+ return minDistance;
+}
+
+static float distanceToFarthestCorner(const FloatPoint& p, const FloatSize& size, FloatPoint& corner)
+{
+ FloatPoint topLeft;
+ float topLeftDistance = FloatSize(p - topLeft).diagonalLength();
+
+ FloatPoint topRight(size.width(), 0);
+ float topRightDistance = FloatSize(p - topRight).diagonalLength();
+
+ FloatPoint bottomLeft(0, size.height());
+ float bottomLeftDistance = FloatSize(p - bottomLeft).diagonalLength();
+
+ FloatPoint bottomRight(size.width(), size.height());
+ float bottomRightDistance = FloatSize(p - bottomRight).diagonalLength();
+
+ corner = topLeft;
+ float maxDistance = topLeftDistance;
+ if (topRightDistance > maxDistance) {
+ maxDistance = topRightDistance;
+ corner = topRight;
+ }
+
+ if (bottomLeftDistance > maxDistance) {
+ maxDistance = bottomLeftDistance;
+ corner = bottomLeft;
+ }
+
+ if (bottomRightDistance > maxDistance) {
+ maxDistance = bottomRightDistance;
+ corner = bottomRight;
+ }
+ return maxDistance;
+}
+
+// Compute horizontal radius of ellipse with center at 0,0 which passes through p, and has
+// width/height given by aspectRatio.
+static inline float horizontalEllipseRadius(const FloatSize& p, float aspectRatio)
+{
+ // x^2/a^2 + y^2/b^2 = 1
+ // a/b = aspectRatio, b = a/aspectRatio
+ // a = sqrt(x^2 + y^2/(1/r^2))
+ return sqrtf(p.width() * p.width() + (p.height() * p.height()) / (1 / (aspectRatio * aspectRatio)));
+}
+
+// FIXME: share code with the linear version
+PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(RenderObject* renderer, const IntSize& size)
+{
+ ASSERT(!size.isEmpty());
+
+ RenderStyle* rootStyle = renderer->document()->documentElement()->renderStyle();
+
+ FloatPoint firstPoint = computeEndPoint(m_firstX.get(), m_firstY.get(), renderer->style(), rootStyle, size);
+ if (!m_firstX)
+ firstPoint.setX(size.width() / 2);
+ if (!m_firstY)
+ firstPoint.setY(size.height() / 2);
+
+ FloatPoint secondPoint = computeEndPoint(m_secondX.get(), m_secondY.get(), renderer->style(), rootStyle, size);
+ if (!m_secondX)
+ secondPoint.setX(size.width() / 2);
+ if (!m_secondY)
+ secondPoint.setY(size.height() / 2);
+
+ float firstRadius = 0;
+ if (m_firstRadius)
+ firstRadius = resolveRadius(m_firstRadius.get(), renderer->style(), rootStyle);
+
+ float secondRadius = 0;
+ float aspectRatio = 1; // width / height.
+ if (m_secondRadius)
+ secondRadius = resolveRadius(m_secondRadius.get(), renderer->style(), rootStyle);
+ else if (m_endHorizontalSize || m_endVerticalSize) {
+ float width = size.width();
+ float height = size.height();
+ secondRadius = resolveRadius(m_endHorizontalSize.get(), renderer->style(), rootStyle, &width);
+ aspectRatio = secondRadius / resolveRadius(m_endVerticalSize.get(), renderer->style(), rootStyle, &height);
+ } else {
+ enum GradientShape { Circle, Ellipse };
+ GradientShape shape = Ellipse;
+ if (m_shape && m_shape->primitiveType() == CSSPrimitiveValue::CSS_IDENT && 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;
+ }
+ }
+
+ // Now compute the end radii based on the second point, shape and fill.
+
+ // Horizontal
+ switch (fill) {
+ case ClosestSide: {
+ float xDist = min(secondPoint.x(), size.width() - secondPoint.x());
+ float yDist = min(secondPoint.y(), size.height() - secondPoint.y());
+ if (shape == Circle) {
+ float smaller = min(xDist, yDist);
+ xDist = smaller;
+ yDist = smaller;
+ }
+ secondRadius = xDist;
+ aspectRatio = xDist / yDist;
+ break;
+ }
+ case FarthestSide: {
+ float xDist = max(secondPoint.x(), size.width() - secondPoint.x());
+ float yDist = max(secondPoint.y(), size.height() - secondPoint.y());
+ if (shape == Circle) {
+ float larger = max(xDist, yDist);
+ xDist = larger;
+ yDist = larger;
+ }
+ secondRadius = xDist;
+ aspectRatio = xDist / yDist;
+ break;
+ }
+ case ClosestCorner: {
+ FloatPoint corner;
+ float distance = distanceToClosestCorner(secondPoint, size, corner);
+ if (shape == Circle)
+ secondRadius = distance;
+ else {
+ // If <shape> is ellipse, the gradient-shape has the same ratio of width to height
+ // that it would if closest-side or farthest-side were specified, as appropriate.
+ float xDist = min(secondPoint.x(), size.width() - secondPoint.x());
+ float yDist = min(secondPoint.y(), size.height() - secondPoint.y());
+
+ secondRadius = horizontalEllipseRadius(corner - secondPoint, xDist / yDist);
+ aspectRatio = xDist / yDist;
+ }
+ break;
+ }
+
+ case FarthestCorner: {
+ FloatPoint corner;
+ float distance = distanceToFarthestCorner(secondPoint, size, corner);
+ if (shape == Circle)
+ secondRadius = distance;
+ else {
+ // If <shape> is ellipse, the gradient-shape has the same ratio of width to height
+ // that it would if closest-side or farthest-side were specified, as appropriate.
+ float xDist = max(secondPoint.x(), size.width() - secondPoint.x());
+ float yDist = max(secondPoint.y(), size.height() - secondPoint.y());
+
+ secondRadius = horizontalEllipseRadius(corner - secondPoint, xDist / yDist);
+ aspectRatio = xDist / yDist;
+ }
+ break;
+ }
+ }
+ }
+
+ RefPtr<Gradient> gradient = Gradient::create(firstPoint, firstRadius, secondPoint, secondRadius, aspectRatio);
+
+ // addStops() only uses maxExtent for repeating gradients.
+ float maxExtent = 0;
+ if (m_repeating) {
+ FloatPoint corner;
+ maxExtent = distanceToFarthestCorner(secondPoint, size, corner);
+ }
+
+ // Now add the stops.
+ addStops(gradient.get(), renderer, rootStyle, maxExtent);
+
+ return gradient.release();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSGradientValue.h b/Source/WebCore/css/CSSGradientValue.h
new file mode 100644
index 000000000..ea10eb8c2
--- /dev/null
+++ b/Source/WebCore/css/CSSGradientValue.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2008 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 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 CSSGradientValue_h
+#define CSSGradientValue_h
+
+#include "CSSImageGeneratorValue.h"
+#include "CSSPrimitiveValue.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatPoint;
+class Gradient;
+
+enum CSSGradientType { CSSLinearGradient, CSSRadialGradient };
+enum CSSGradientRepeat { NonRepeating, Repeating };
+
+struct CSSGradientColorStop {
+ RefPtr<CSSPrimitiveValue> m_position; // percentage or length
+ RefPtr<CSSPrimitiveValue> m_color;
+};
+
+class CSSGradientValue : public CSSImageGeneratorValue {
+public:
+ PassRefPtr<Image> image(RenderObject*, const IntSize&);
+
+ void setFirstX(PassRefPtr<CSSPrimitiveValue> val) { m_firstX = val; }
+ void setFirstY(PassRefPtr<CSSPrimitiveValue> val) { m_firstY = val; }
+ void setSecondX(PassRefPtr<CSSPrimitiveValue> val) { m_secondX = val; }
+ void setSecondY(PassRefPtr<CSSPrimitiveValue> val) { m_secondY = val; }
+
+ void addStop(const CSSGradientColorStop& stop) { m_stops.append(stop); }
+
+ Vector<CSSGradientColorStop>& stops() { return m_stops; }
+
+ void sortStopsIfNeeded();
+
+ bool isLinearGradient() const { return classType() == LinearGradientClass; }
+ bool isRadialGradient() const { return classType() == RadialGradientClass; }
+
+ bool isRepeating() const { return m_repeating; }
+
+ bool deprecatedType() const { return m_deprecatedType; } // came from -webkit-gradient
+
+ bool isFixedSize() const { return false; }
+ IntSize fixedSize(const RenderObject*) const { return IntSize(); }
+
+ bool isPending() const { return false; }
+ void loadSubimages(CachedResourceLoader*) { }
+
+protected:
+ CSSGradientValue(ClassType classType, CSSGradientRepeat repeat, bool deprecatedType = false)
+ : CSSImageGeneratorValue(classType)
+ , m_stopsSorted(false)
+ , m_deprecatedType(deprecatedType)
+ , m_repeating(repeat == Repeating)
+ {
+ }
+
+ void addStops(Gradient*, RenderObject*, RenderStyle* rootStyle, float maxLengthForRepeat = 0);
+
+ // Resolve points/radii to front end values.
+ FloatPoint computeEndPoint(CSSPrimitiveValue*, CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, const IntSize&);
+
+ bool isCacheable() const;
+
+ // Points. Some of these may be null for linear gradients.
+ RefPtr<CSSPrimitiveValue> m_firstX;
+ RefPtr<CSSPrimitiveValue> m_firstY;
+
+ RefPtr<CSSPrimitiveValue> m_secondX;
+ RefPtr<CSSPrimitiveValue> m_secondY;
+
+ // Stops
+ Vector<CSSGradientColorStop> m_stops;
+ bool m_stopsSorted;
+ bool m_deprecatedType; // -webkit-gradient()
+ bool m_repeating;
+};
+
+
+class CSSLinearGradientValue : public CSSGradientValue {
+public:
+ static PassRefPtr<CSSLinearGradientValue> create(CSSGradientRepeat repeat, bool deprecatedType = false)
+ {
+ return adoptRef(new CSSLinearGradientValue(repeat, deprecatedType));
+ }
+
+ void setAngle(PassRefPtr<CSSPrimitiveValue> val) { m_angle = val; }
+
+ String customCssText() const;
+
+ // Create the gradient for a given size.
+ PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
+
+private:
+ CSSLinearGradientValue(CSSGradientRepeat repeat, bool deprecatedType = false)
+ : CSSGradientValue(LinearGradientClass, repeat, deprecatedType)
+ {
+ }
+
+ RefPtr<CSSPrimitiveValue> m_angle; // may be null.
+};
+
+class CSSRadialGradientValue : public CSSGradientValue {
+public:
+ static PassRefPtr<CSSRadialGradientValue> create(CSSGradientRepeat repeat, bool deprecatedType = false)
+ {
+ return adoptRef(new CSSRadialGradientValue(repeat, deprecatedType));
+ }
+
+ String customCssText() const;
+
+ void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; }
+ void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; }
+
+ void setShape(PassRefPtr<CSSPrimitiveValue> val) { m_shape = val; }
+ void setSizingBehavior(PassRefPtr<CSSPrimitiveValue> val) { m_sizingBehavior = val; }
+
+ void setEndHorizontalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endHorizontalSize = val; }
+ void setEndVerticalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endVerticalSize = val; }
+
+ // Create the gradient for a given size.
+ PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
+
+private:
+ CSSRadialGradientValue(CSSGradientRepeat repeat, bool deprecatedType = false)
+ : CSSGradientValue(RadialGradientClass, repeat, deprecatedType)
+ {
+ }
+
+ // Resolve points/radii to front end values.
+ float resolveRadius(CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, float* widthOrHeight = 0);
+
+ // These may be null for non-deprecated gradients.
+ RefPtr<CSSPrimitiveValue> m_firstRadius;
+ RefPtr<CSSPrimitiveValue> m_secondRadius;
+
+ // The below are only used for non-deprecated gradients.
+ RefPtr<CSSPrimitiveValue> m_shape;
+ RefPtr<CSSPrimitiveValue> m_sizingBehavior;
+
+ RefPtr<CSSPrimitiveValue> m_endHorizontalSize;
+ RefPtr<CSSPrimitiveValue> m_endVerticalSize;
+};
+
+} // namespace WebCore
+
+#endif // CSSGradientValue_h
diff --git a/Source/WebCore/css/CSSGrammar.y b/Source/WebCore/css/CSSGrammar.y
new file mode 100644
index 000000000..705c36be0
--- /dev/null
+++ b/Source/WebCore/css/CSSGrammar.y
@@ -0,0 +1,1704 @@
+%{
+
+/*
+ * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include "config.h"
+
+#include "CSSMediaRule.h"
+#include "CSSParser.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSPropertyNames.h"
+#include "CSSRuleList.h"
+#include "CSSSelector.h"
+#include "CSSSelectorList.h"
+#include "CSSStyleSheet.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "MediaList.h"
+#include "MediaQueryExp.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include <wtf/FastMalloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+using namespace WebCore;
+using namespace HTMLNames;
+
+#define YYMALLOC fastMalloc
+#define YYFREE fastFree
+
+#define YYENABLE_NLS 0
+#define YYLTYPE_IS_TRIVIAL 1
+#define YYMAXDEPTH 10000
+#define YYDEBUG 0
+
+// FIXME: Replace with %parse-param { CSSParser* parser } once we can depend on bison 2.x
+#define YYPARSE_PARAM parser
+#define YYLEX_PARAM parser
+
+%}
+
+%pure_parser
+
+%union {
+ bool boolean;
+ char character;
+ int integer;
+ double number;
+ CSSParserString string;
+
+ CSSRule* rule;
+ CSSRuleList* ruleList;
+ CSSParserSelector* selector;
+ Vector<OwnPtr<CSSParserSelector> >* selectorList;
+ CSSSelector::MarginBoxType marginBox;
+ CSSSelector::Relation relation;
+ MediaList* mediaList;
+ MediaQuery* mediaQuery;
+ MediaQuery::Restrictor mediaQueryRestrictor;
+ MediaQueryExp* mediaQueryExp;
+ CSSParserValue value;
+ CSSParserValueList* valueList;
+ Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList;
+ WebKitCSSKeyframeRule* keyframeRule;
+ WebKitCSSKeyframesRule* keyframesRule;
+ float val;
+}
+
+%{
+
+static inline int cssyyerror(const char*)
+{
+ return 1;
+}
+
+static int cssyylex(YYSTYPE* yylval, void* parser)
+{
+ return static_cast<CSSParser*>(parser)->lex(yylval);
+}
+
+%}
+
+%expect 55
+
+%nonassoc LOWEST_PREC
+
+%left UNIMPORTANT_TOK
+
+%token WHITESPACE SGML_CD
+%token TOKEN_EOF 0
+
+%token INCLUDES
+%token DASHMATCH
+%token BEGINSWITH
+%token ENDSWITH
+%token CONTAINS
+
+%token <string> STRING
+%right <string> IDENT
+%token <string> NTH
+
+%nonassoc <string> HEX
+%nonassoc <string> IDSEL
+%nonassoc ':'
+%nonassoc '.'
+%nonassoc '['
+%nonassoc <string> '*'
+%nonassoc error
+%left '|'
+
+%token IMPORT_SYM
+%token PAGE_SYM
+%token MEDIA_SYM
+%token FONT_FACE_SYM
+%token CHARSET_SYM
+%token NAMESPACE_SYM
+%token WEBKIT_RULE_SYM
+%token WEBKIT_DECLS_SYM
+%token WEBKIT_KEYFRAME_RULE_SYM
+%token WEBKIT_KEYFRAMES_SYM
+%token WEBKIT_VALUE_SYM
+%token WEBKIT_MEDIAQUERY_SYM
+%token WEBKIT_SELECTOR_SYM
+%token WEBKIT_REGION_RULE_SYM
+%token <marginBox> TOPLEFTCORNER_SYM
+%token <marginBox> TOPLEFT_SYM
+%token <marginBox> TOPCENTER_SYM
+%token <marginBox> TOPRIGHT_SYM
+%token <marginBox> TOPRIGHTCORNER_SYM
+%token <marginBox> BOTTOMLEFTCORNER_SYM
+%token <marginBox> BOTTOMLEFT_SYM
+%token <marginBox> BOTTOMCENTER_SYM
+%token <marginBox> BOTTOMRIGHT_SYM
+%token <marginBox> BOTTOMRIGHTCORNER_SYM
+%token <marginBox> LEFTTOP_SYM
+%token <marginBox> LEFTMIDDLE_SYM
+%token <marginBox> LEFTBOTTOM_SYM
+%token <marginBox> RIGHTTOP_SYM
+%token <marginBox> RIGHTMIDDLE_SYM
+%token <marginBox> RIGHTBOTTOM_SYM
+
+%token ATKEYWORD
+
+%token IMPORTANT_SYM
+%token MEDIA_ONLY
+%token MEDIA_NOT
+%token MEDIA_AND
+
+%token <number> REMS
+%token <number> QEMS
+%token <number> EMS
+%token <number> EXS
+%token <number> PXS
+%token <number> CMS
+%token <number> MMS
+%token <number> INS
+%token <number> PTS
+%token <number> PCS
+%token <number> DEGS
+%token <number> RADS
+%token <number> GRADS
+%token <number> TURNS
+%token <number> MSECS
+%token <number> SECS
+%token <number> HERTZ
+%token <number> KHERTZ
+%token <string> DIMEN
+%token <string> INVALIDDIMEN
+%token <number> PERCENTAGE
+%token <number> FLOATTOKEN
+%token <number> INTEGER
+
+%token <string> URI
+%token <string> FUNCTION
+%token <string> ANYFUNCTION
+%token <string> NOTFUNCTION
+%token <string> CALCFUNCTION
+%token <string> MINFUNCTION
+%token <string> MAXFUNCTION
+
+%token <string> UNICODERANGE
+
+%type <relation> combinator
+
+%type <rule> charset
+%type <rule> ignored_charset
+%type <rule> ruleset
+%type <rule> media
+%type <rule> import
+%type <rule> namespace
+%type <rule> page
+%type <rule> margin_box
+%type <rule> font_face
+%type <rule> keyframes
+%type <rule> invalid_rule
+%type <rule> save_block
+%type <rule> invalid_at
+%type <rule> rule
+%type <rule> valid_rule
+%type <ruleList> block_rule_list
+%type <rule> block_rule
+%type <rule> block_valid_rule
+%type <rule> region
+
+%type <string> maybe_ns_prefix
+
+%type <string> namespace_selector
+
+%type <string> string_or_uri
+%type <string> ident_or_string
+%type <string> medium
+%type <marginBox> margin_sym
+
+%type <string> media_feature
+%type <mediaList> media_list
+%type <mediaList> maybe_media_list
+%type <mediaQuery> media_query
+%type <mediaQueryRestrictor> maybe_media_restrictor
+%type <valueList> maybe_media_value
+%type <mediaQueryExp> media_query_exp
+%type <mediaQueryExpList> media_query_exp_list
+%type <mediaQueryExpList> maybe_and_media_query_exp_list
+
+%type <string> keyframe_name
+%type <keyframeRule> keyframe_rule
+%type <keyframesRule> keyframes_rule
+%type <valueList> key_list
+%type <value> key
+
+%type <integer> property
+
+%type <selector> specifier
+%type <selector> specifier_list
+%type <selector> simple_selector
+%type <selector> selector
+%type <selectorList> selector_list
+%type <selectorList> simple_selector_list
+%type <selectorList> region_selector
+%type <selector> selector_with_trailing_whitespace
+%type <selector> class
+%type <selector> attrib
+%type <selector> pseudo
+%type <selector> pseudo_page
+%type <selector> page_selector
+
+%type <boolean> declaration_list
+%type <boolean> decl_list
+%type <boolean> declaration
+%type <boolean> declarations_and_margins
+
+%type <boolean> prio
+
+%type <integer> match
+%type <integer> unary_operator
+%type <integer> maybe_unary_operator
+%type <character> operator
+
+%type <valueList> expr
+%type <value> term
+%type <value> unary_term
+%type <value> function
+%type <value> calc_func_term
+%type <character> calc_func_operator
+%type <valueList> calc_func_expr
+%type <valueList> calc_func_expr_list
+%type <valueList> calc_func_paren_expr
+%type <value> calc_function
+%type <string> min_or_max
+%type <value> min_or_max_function
+
+%type <string> element_name
+%type <string> attr_name
+
+%%
+
+stylesheet:
+ maybe_space maybe_charset maybe_sgml rule_list
+ | webkit_rule maybe_space
+ | webkit_decls maybe_space
+ | webkit_value maybe_space
+ | webkit_mediaquery maybe_space
+ | webkit_selector maybe_space
+ | webkit_keyframe_rule maybe_space
+ ;
+
+webkit_rule:
+ WEBKIT_RULE_SYM '{' maybe_space valid_rule maybe_space '}' {
+ static_cast<CSSParser*>(parser)->m_rule = $4;
+ }
+;
+
+webkit_keyframe_rule:
+ WEBKIT_KEYFRAME_RULE_SYM '{' maybe_space keyframe_rule maybe_space '}' {
+ static_cast<CSSParser*>(parser)->m_keyframe = $4;
+ }
+;
+
+webkit_decls:
+ WEBKIT_DECLS_SYM '{' maybe_space_before_declaration declaration_list '}' {
+ /* can be empty */
+ }
+;
+
+webkit_value:
+ WEBKIT_VALUE_SYM '{' maybe_space expr '}' {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($4) {
+ p->m_valueList = p->sinkFloatingValueList($4);
+ int oldParsedProperties = p->m_numParsedProperties;
+ if (!p->parseValue(p->m_id, p->m_important))
+ p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
+ p->m_valueList = nullptr;
+ }
+ }
+;
+
+webkit_mediaquery:
+ WEBKIT_MEDIAQUERY_SYM WHITESPACE maybe_space media_query '}' {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->m_mediaQuery = p->sinkFloatingMediaQuery($4);
+ }
+;
+
+webkit_selector:
+ WEBKIT_SELECTOR_SYM '{' maybe_space selector_list '}' {
+ if ($4) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (p->m_selectorListForParseSelector)
+ p->m_selectorListForParseSelector->adoptSelectorVector(*$4);
+ }
+ }
+;
+
+maybe_space:
+ /* empty */ %prec UNIMPORTANT_TOK
+ | maybe_space WHITESPACE
+ ;
+
+maybe_sgml:
+ /* empty */
+ | maybe_sgml SGML_CD
+ | maybe_sgml WHITESPACE
+ ;
+
+maybe_charset:
+ /* empty */
+ | charset {
+ }
+ ;
+
+closing_brace:
+ '}'
+ | %prec LOWEST_PREC TOKEN_EOF
+ ;
+
+charset:
+ CHARSET_SYM maybe_space STRING maybe_space ';' {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = static_cast<CSSParser*>(parser)->createCharsetRule($3);
+ if ($$ && p->m_styleSheet)
+ p->m_styleSheet->append($$);
+ }
+ | CHARSET_SYM error invalid_block {
+ }
+ | CHARSET_SYM error ';' {
+ }
+;
+
+ignored_charset:
+ CHARSET_SYM maybe_space STRING maybe_space ';' {
+ // Ignore any @charset rule not at the beginning of the style sheet.
+ $$ = 0;
+ }
+;
+
+rule_list:
+ /* empty */
+ | rule_list rule maybe_sgml {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($2 && p->m_styleSheet)
+ p->m_styleSheet->append($2);
+ }
+ ;
+
+valid_rule:
+ before_ruleset ruleset {
+ $$ = $2;
+ }
+ | media
+ | page
+ | font_face
+ | keyframes
+ | namespace
+ | import
+ | region
+ ;
+
+rule:
+ valid_rule {
+ static_cast<CSSParser*>(parser)->m_hadSyntacticallyValidCSSRule = true;
+ }
+ | ignored_charset
+ | invalid_rule
+ | invalid_at
+ ;
+
+block_rule_list:
+ /* empty */ { $$ = 0; }
+ | block_rule_list block_rule maybe_sgml {
+ $$ = $1;
+ if ($2) {
+ if (!$$)
+ $$ = static_cast<CSSParser*>(parser)->createRuleList();
+ $$->append($2);
+ }
+ }
+ ;
+
+block_valid_rule:
+ ruleset
+ | page
+ | font_face
+ | keyframes
+ ;
+
+block_rule:
+ block_valid_rule
+ | invalid_rule
+ | invalid_at
+ | namespace
+ | import
+ | media
+ ;
+
+
+import:
+ IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list ';' {
+ $$ = static_cast<CSSParser*>(parser)->createImportRule($3, $5);
+ }
+ | IMPORT_SYM maybe_space string_or_uri maybe_space maybe_media_list invalid_block {
+ $$ = 0;
+ }
+ | IMPORT_SYM error ';' {
+ $$ = 0;
+ }
+ | IMPORT_SYM error invalid_block {
+ $$ = 0;
+ }
+ ;
+
+namespace:
+NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space ';' {
+ static_cast<CSSParser*>(parser)->addNamespace($3, $4);
+ $$ = 0;
+}
+| NAMESPACE_SYM maybe_space maybe_ns_prefix string_or_uri maybe_space invalid_block {
+ $$ = 0;
+}
+| NAMESPACE_SYM error invalid_block {
+ $$ = 0;
+}
+| NAMESPACE_SYM error ';' {
+ $$ = 0;
+}
+;
+
+maybe_ns_prefix:
+/* empty */ { $$.characters = 0; }
+| IDENT maybe_space { $$ = $1; }
+;
+
+string_or_uri:
+STRING
+| URI
+;
+
+media_feature:
+ IDENT maybe_space {
+ $$ = $1;
+ }
+ ;
+
+maybe_media_value:
+ /*empty*/ {
+ $$ = 0;
+ }
+ | ':' maybe_space expr maybe_space {
+ $$ = $3;
+ }
+ ;
+
+media_query_exp:
+ '(' maybe_space media_feature maybe_space maybe_media_value ')' maybe_space {
+ $3.lower();
+ $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExp($3, $5);
+ }
+ ;
+
+media_query_exp_list:
+ media_query_exp {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingMediaQueryExpList();
+ $$->append(p->sinkFloatingMediaQueryExp($1));
+ }
+ | media_query_exp_list maybe_space MEDIA_AND maybe_space media_query_exp {
+ $$ = $1;
+ $$->append(static_cast<CSSParser*>(parser)->sinkFloatingMediaQueryExp($5));
+ }
+ ;
+
+maybe_and_media_query_exp_list:
+ /*empty*/ {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingMediaQueryExpList();
+ }
+ | MEDIA_AND maybe_space media_query_exp_list {
+ $$ = $3;
+ }
+ ;
+
+maybe_media_restrictor:
+ /*empty*/ {
+ $$ = MediaQuery::None;
+ }
+ | MEDIA_ONLY {
+ $$ = MediaQuery::Only;
+ }
+ | MEDIA_NOT {
+ $$ = MediaQuery::Not;
+ }
+ ;
+
+media_query:
+ media_query_exp_list {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingMediaQuery(p->sinkFloatingMediaQueryExpList($1));
+ }
+ |
+ maybe_media_restrictor maybe_space medium maybe_and_media_query_exp_list {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $3.lower();
+ $$ = p->createFloatingMediaQuery($1, $3, p->sinkFloatingMediaQueryExpList($4));
+ }
+ ;
+
+maybe_media_list:
+ /* empty */ {
+ $$ = static_cast<CSSParser*>(parser)->createMediaList();
+ }
+ | media_list
+ ;
+
+media_list:
+ media_query {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createMediaList();
+ $$->appendMediaQuery(p->sinkFloatingMediaQuery($1));
+ p->updateLastMediaLine($$);
+ }
+ | media_list ',' maybe_space media_query {
+ $$ = $1;
+ if ($$) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$->appendMediaQuery(p->sinkFloatingMediaQuery($4));
+ p->updateLastMediaLine($$);
+ }
+ }
+ | media_list error {
+ $$ = 0;
+ }
+ ;
+
+media:
+ MEDIA_SYM maybe_space media_list '{' maybe_space block_rule_list save_block {
+ $$ = static_cast<CSSParser*>(parser)->createMediaRule($3, $6);
+ }
+ | MEDIA_SYM maybe_space '{' maybe_space block_rule_list save_block {
+ $$ = static_cast<CSSParser*>(parser)->createMediaRule(0, $5);
+ }
+ ;
+
+medium:
+ IDENT maybe_space {
+ $$ = $1;
+ }
+ ;
+
+keyframes:
+ WEBKIT_KEYFRAMES_SYM maybe_space keyframe_name maybe_space '{' maybe_space keyframes_rule '}' {
+ $$ = $7;
+ $7->setNameInternal($3);
+ }
+ ;
+
+keyframe_name:
+ IDENT
+ | STRING
+ ;
+
+keyframes_rule:
+ /* empty */ { $$ = static_cast<CSSParser*>(parser)->createKeyframesRule(); }
+ | keyframes_rule keyframe_rule maybe_space {
+ $$ = $1;
+ if ($2)
+ $$->append($2);
+ }
+ ;
+
+keyframe_rule:
+ key_list maybe_space '{' maybe_space declaration_list '}' {
+ $$ = static_cast<CSSParser*>(parser)->createKeyframeRule($1);
+ }
+ ;
+
+key_list:
+ key {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingValueList();
+ $$->addValue(p->sinkFloatingValue($1));
+ }
+ | key_list maybe_space ',' maybe_space key {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ if ($$)
+ $$->addValue(p->sinkFloatingValue($5));
+ }
+ ;
+
+key:
+ PERCENTAGE { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | IDENT {
+ $$.id = 0; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_NUMBER;
+ CSSParserString& str = $1;
+ if (equalIgnoringCase("from", str.characters, str.length))
+ $$.fValue = 0;
+ else if (equalIgnoringCase("to", str.characters, str.length))
+ $$.fValue = 100;
+ else
+ YYERROR;
+ }
+ ;
+
+page:
+ PAGE_SYM maybe_space page_selector maybe_space
+ '{' maybe_space declarations_and_margins closing_brace {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($3)
+ $$ = p->createPageRule(p->sinkFloatingSelector($3));
+ else {
+ // Clear properties in the invalid @page rule.
+ p->clearProperties();
+ // Also clear margin at-rules here once we fully implement margin at-rules parsing.
+ $$ = 0;
+ }
+ }
+ | PAGE_SYM error invalid_block {
+ $$ = 0;
+ }
+ | PAGE_SYM error ';' {
+ $$ = 0;
+ }
+ ;
+
+page_selector:
+ IDENT {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
+ $$->setForPage();
+ }
+ | IDENT pseudo_page {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $2;
+ if ($$) {
+ $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
+ $$->setForPage();
+ }
+ }
+ | pseudo_page {
+ $$ = $1;
+ if ($$)
+ $$->setForPage();
+ }
+ | /* empty */ {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setForPage();
+ }
+ ;
+
+declarations_and_margins:
+ declaration_list
+ | declarations_and_margins margin_box maybe_space declaration_list
+ ;
+
+margin_box:
+ margin_sym {
+ static_cast<CSSParser*>(parser)->startDeclarationsForMarginBox();
+ } maybe_space '{' maybe_space declaration_list closing_brace {
+ $$ = static_cast<CSSParser*>(parser)->createMarginAtRule($1);
+ }
+ ;
+
+margin_sym :
+ TOPLEFTCORNER_SYM {
+ $$ = CSSSelector::TopLeftCornerMarginBox;
+ }
+ | TOPLEFT_SYM {
+ $$ = CSSSelector::TopLeftMarginBox;
+ }
+ | TOPCENTER_SYM {
+ $$ = CSSSelector::TopCenterMarginBox;
+ }
+ | TOPRIGHT_SYM {
+ $$ = CSSSelector::TopRightMarginBox;
+ }
+ | TOPRIGHTCORNER_SYM {
+ $$ = CSSSelector::TopRightCornerMarginBox;
+ }
+ | BOTTOMLEFTCORNER_SYM {
+ $$ = CSSSelector::BottomLeftCornerMarginBox;
+ }
+ | BOTTOMLEFT_SYM {
+ $$ = CSSSelector::BottomLeftMarginBox;
+ }
+ | BOTTOMCENTER_SYM {
+ $$ = CSSSelector::BottomCenterMarginBox;
+ }
+ | BOTTOMRIGHT_SYM {
+ $$ = CSSSelector::BottomRightMarginBox;
+ }
+ | BOTTOMRIGHTCORNER_SYM {
+ $$ = CSSSelector::BottomRightCornerMarginBox;
+ }
+ | LEFTTOP_SYM {
+ $$ = CSSSelector::LeftTopMarginBox;
+ }
+ | LEFTMIDDLE_SYM {
+ $$ = CSSSelector::LeftMiddleMarginBox;
+ }
+ | LEFTBOTTOM_SYM {
+ $$ = CSSSelector::LeftBottomMarginBox;
+ }
+ | RIGHTTOP_SYM {
+ $$ = CSSSelector::RightTopMarginBox;
+ }
+ | RIGHTMIDDLE_SYM {
+ $$ = CSSSelector::RightMiddleMarginBox;
+ }
+ | RIGHTBOTTOM_SYM {
+ $$ = CSSSelector::RightBottomMarginBox;
+ }
+ ;
+
+font_face:
+ FONT_FACE_SYM maybe_space
+ '{' maybe_space declaration_list '}' maybe_space {
+ $$ = static_cast<CSSParser*>(parser)->createFontFaceRule();
+ }
+ | FONT_FACE_SYM error invalid_block {
+ $$ = 0;
+ }
+ | FONT_FACE_SYM error ';' {
+ $$ = 0;
+ }
+;
+
+region_selector:
+ selector_list {
+ if ($1) {
+ static_cast<CSSParser*>(parser)->setReusableRegionSelectorVector($1);
+ $$ = static_cast<CSSParser*>(parser)->reusableRegionSelectorVector();
+ }
+ else
+ $$ = 0;
+ }
+;
+
+region:
+ WEBKIT_REGION_RULE_SYM WHITESPACE region_selector '{' maybe_space block_rule_list save_block {
+ if ($3)
+ $$ = static_cast<CSSParser*>(parser)->createRegionRule($3, $6);
+ else
+ $$ = 0;
+ }
+;
+
+combinator:
+ '+' maybe_space { $$ = CSSSelector::DirectAdjacent; }
+ | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; }
+ | '>' maybe_space { $$ = CSSSelector::Child; }
+ ;
+
+maybe_unary_operator:
+ unary_operator { $$ = $1; }
+ | { $$ = 1; }
+ ;
+
+unary_operator:
+ '-' { $$ = -1; }
+ | '+' { $$ = 1; }
+ ;
+
+maybe_space_before_declaration:
+ maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ }
+ ;
+
+before_ruleset:
+ /* empty */ {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markSelectorListStart();
+ }
+ ;
+
+before_rule_opening_brace:
+ /* empty */ {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markSelectorListEnd();
+ }
+ ;
+
+ruleset:
+ selector_list before_rule_opening_brace '{' maybe_space_before_declaration declaration_list closing_brace {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createStyleRule($1);
+ }
+ ;
+
+selector_list:
+ selector %prec UNIMPORTANT_TOK {
+ if ($1) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->reusableSelectorVector();
+ $$->shrink(0);
+ $$->append(p->sinkFloatingSelector($1));
+ p->updateLastSelectorLineAndPosition();
+ }
+ }
+ | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK {
+ if ($1 && $4) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ $$->append(p->sinkFloatingSelector($4));
+ p->updateLastSelectorLineAndPosition();
+ } else
+ $$ = 0;
+ }
+ | selector_list error {
+ $$ = 0;
+ }
+ ;
+
+selector_with_trailing_whitespace:
+ selector WHITESPACE {
+ $$ = $1;
+ }
+ ;
+
+selector:
+ simple_selector {
+ $$ = $1;
+ }
+ | selector_with_trailing_whitespace
+ {
+ $$ = $1;
+ }
+ | selector_with_trailing_whitespace simple_selector
+ {
+ $$ = $2;
+ if (!$1)
+ $$ = 0;
+ else if ($$) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserSelector* end = $$;
+ while (end->tagHistory())
+ end = end->tagHistory();
+ end->setRelation(CSSSelector::Descendant);
+ end->setTagHistory(p->sinkFloatingSelector($1));
+ }
+ }
+ | selector combinator simple_selector {
+ $$ = $3;
+ if (!$1)
+ $$ = 0;
+ else if ($$) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserSelector* end = $$;
+ while (end->tagHistory())
+ end = end->tagHistory();
+ end->setRelation($2);
+ end->setTagHistory(p->sinkFloatingSelector($1));
+ }
+ }
+ | selector error {
+ $$ = 0;
+ }
+ ;
+
+namespace_selector:
+ /* empty */ '|' { $$.characters = 0; $$.length = 0; }
+ | '*' '|' { static UChar star = '*'; $$.characters = &star; $$.length = 1; }
+ | IDENT '|' { $$ = $1; }
+;
+
+simple_selector:
+ element_name {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
+ }
+ | element_name specifier_list {
+ $$ = $2;
+ if ($$)
+ static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName(nullAtom, $1, $$);
+ }
+ | specifier_list {
+ $$ = $1;
+ if ($$)
+ static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName(nullAtom, starAtom, $$);
+ }
+ | namespace_selector element_name {
+ AtomicString namespacePrefix = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ if (p->m_styleSheet)
+ $$->setTag(QualifiedName(namespacePrefix, $2,
+ p->m_styleSheet->determineNamespace(namespacePrefix)));
+ else // FIXME: Shouldn't this case be an error?
+ $$->setTag(QualifiedName(nullAtom, $2, p->m_defaultNamespace));
+ }
+ | namespace_selector element_name specifier_list {
+ $$ = $3;
+ if ($$)
+ static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName($1, $2, $$);
+ }
+ | namespace_selector specifier_list {
+ $$ = $2;
+ if ($$)
+ static_cast<CSSParser*>(parser)->updateSpecifiersWithElementName($1, starAtom, $$);
+ }
+ ;
+
+simple_selector_list:
+ simple_selector %prec UNIMPORTANT_TOK {
+ if ($1) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelectorVector();
+ $$->append(p->sinkFloatingSelector($1));
+ } else
+ $$ = 0;
+ }
+ | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK {
+ if ($1 && $5) {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ $$->append(p->sinkFloatingSelector($5));
+ } else
+ $$ = 0;
+ }
+ | simple_selector_list error {
+ $$ = 0;
+ }
+ ;
+
+element_name:
+ IDENT {
+ CSSParserString& str = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ Document* doc = p->findDocument();
+ if (doc && doc->isHTMLDocument())
+ str.lower();
+ $$ = str;
+ }
+ | '*' {
+ static UChar star = '*';
+ $$.characters = &star;
+ $$.length = 1;
+ }
+ ;
+
+specifier_list:
+ specifier {
+ $$ = $1;
+ }
+ | specifier_list specifier {
+ if (!$2)
+ $$ = 0;
+ else if ($1)
+ $$ = static_cast<CSSParser*>(parser)->updateSpecifiers($1, $2);
+ }
+ | specifier_list error {
+ $$ = 0;
+ }
+;
+
+specifier:
+ IDSEL {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::Id);
+ if (!p->m_strict)
+ $1.lower();
+ $$->setValue($1);
+ }
+ | HEX {
+ if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
+ $$ = 0;
+ } else {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::Id);
+ if (!p->m_strict)
+ $1.lower();
+ $$->setValue($1);
+ }
+ }
+ | class
+ | attrib
+ | pseudo
+ ;
+
+class:
+ '.' IDENT {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::Class);
+ if (!p->m_strict)
+ $2.lower();
+ $$->setValue($2);
+ }
+ ;
+
+attr_name:
+ IDENT maybe_space {
+ CSSParserString& str = $1;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ Document* doc = p->findDocument();
+ if (doc && doc->isHTMLDocument())
+ str.lower();
+ $$ = str;
+ }
+ ;
+
+attrib:
+ '[' maybe_space attr_name ']' {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
+ $$->setMatch(CSSSelector::Set);
+ }
+ | '[' maybe_space attr_name match maybe_space ident_or_string maybe_space ']' {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
+ $$->setMatch((CSSSelector::Match)$4);
+ $$->setValue($6);
+ }
+ | '[' maybe_space namespace_selector attr_name ']' {
+ AtomicString namespacePrefix = $3;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setAttribute(QualifiedName(namespacePrefix, $4,
+ p->m_styleSheet->determineNamespace(namespacePrefix)));
+ $$->setMatch(CSSSelector::Set);
+ }
+ | '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
+ AtomicString namespacePrefix = $3;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setAttribute(QualifiedName(namespacePrefix, $4,
+ p->m_styleSheet->determineNamespace(namespacePrefix)));
+ $$->setMatch((CSSSelector::Match)$5);
+ $$->setValue($7);
+ }
+ ;
+
+match:
+ '=' {
+ $$ = CSSSelector::Exact;
+ }
+ | INCLUDES {
+ $$ = CSSSelector::List;
+ }
+ | DASHMATCH {
+ $$ = CSSSelector::Hyphen;
+ }
+ | BEGINSWITH {
+ $$ = CSSSelector::Begin;
+ }
+ | ENDSWITH {
+ $$ = CSSSelector::End;
+ }
+ | CONTAINS {
+ $$ = CSSSelector::Contain;
+ }
+ ;
+
+ident_or_string:
+ IDENT
+ | STRING
+ ;
+
+pseudo_page:
+ ':' IDENT {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setMatch(CSSSelector::PagePseudoClass);
+ $2.lower();
+ $$->setValue($2);
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ }
+
+pseudo:
+ ':' IDENT {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoClass);
+ $2.lower();
+ $$->setValue($2);
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ }
+ | ':' ':' IDENT {
+ $$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoElement);
+ $3.lower();
+ $$->setValue($3);
+ // FIXME: This call is needed to force selector to compute the pseudoType early enough.
+ $$->pseudoType();
+ }
+ // use by :-webkit-any.
+ // FIXME: should we support generic selectors here or just simple_selectors?
+ // Use simple_selector_list for now to match -moz-any.
+ // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some
+ // related discussion with respect to :not.
+ | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space ')' {
+ if ($4) {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoClass);
+ $$->adoptSelectorVector(*p->sinkFloatingSelectorVector($4));
+ $2.lower();
+ $$->setValue($2);
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type != CSSSelector::PseudoAny)
+ $$ = 0;
+ } else
+ $$ = 0;
+ }
+ // used by :nth-*(ax+b)
+ | ':' FUNCTION maybe_space NTH maybe_space ')' {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoClass);
+ $$->setArgument($4);
+ $$->setValue($2);
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ }
+ // used by :nth-*
+ | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoClass);
+ $$->setArgument(String::number($4 * $5));
+ $$->setValue($2);
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ }
+ // used by :nth-*(odd/even) and :lang
+ | ':' FUNCTION maybe_space IDENT maybe_space ')' {
+ CSSParser *p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoClass);
+ $$->setArgument($4);
+ $2.lower();
+ $$->setValue($2);
+ CSSSelector::PseudoType type = $$->pseudoType();
+ if (type == CSSSelector::PseudoUnknown)
+ $$ = 0;
+ else if (type == CSSSelector::PseudoNthChild ||
+ type == CSSSelector::PseudoNthOfType ||
+ type == CSSSelector::PseudoNthLastChild ||
+ type == CSSSelector::PseudoNthLastOfType) {
+ if (!isValidNthToken($4))
+ $$ = 0;
+ }
+ }
+ // used by :not
+ | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' {
+ if (!$4 || !$4->isSimple())
+ $$ = 0;
+ else {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingSelector();
+ $$->setMatch(CSSSelector::PseudoClass);
+
+ Vector<OwnPtr<CSSParserSelector> > selectorVector;
+ selectorVector.append(p->sinkFloatingSelector($4));
+ $$->adoptSelectorVector(selectorVector);
+
+ $2.lower();
+ $$->setValue($2);
+ }
+ }
+ ;
+
+declaration_list:
+ declaration {
+ $$ = $1;
+ }
+ | decl_list declaration {
+ $$ = $1;
+ if ( $2 )
+ $$ = $2;
+ }
+ | decl_list {
+ $$ = $1;
+ }
+ | error invalid_block_list error {
+ $$ = false;
+ }
+ | error {
+ $$ = false;
+ }
+ | decl_list error {
+ $$ = $1;
+ }
+ | decl_list invalid_block_list {
+ $$ = $1;
+ }
+ ;
+
+decl_list:
+ declaration ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ }
+ | declaration invalid_block_list maybe_space {
+ $$ = false;
+ }
+ | declaration invalid_block_list ';' maybe_space {
+ $$ = false;
+ }
+ | error ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = false;
+ }
+ | error invalid_block_list error ';' maybe_space {
+ $$ = false;
+ }
+ | decl_list declaration ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ if ($2)
+ $$ = $2;
+ }
+ | decl_list error ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ }
+ | decl_list error invalid_block_list error ';' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyStart();
+ $$ = $1;
+ }
+ ;
+
+declaration:
+ property ':' maybe_space expr prio {
+ $$ = false;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ bool isPropertyParsed = false;
+ if ($1 && $4) {
+ p->m_valueList = p->sinkFloatingValueList($4);
+ int oldParsedProperties = p->m_numParsedProperties;
+ $$ = p->parseValue($1, $5);
+ if (!$$)
+ p->rollbackLastProperties(p->m_numParsedProperties - oldParsedProperties);
+ else
+ isPropertyParsed = true;
+ p->m_valueList = nullptr;
+ }
+ p->markPropertyEnd($5, isPropertyParsed);
+ }
+ |
+ property error {
+ $$ = false;
+ }
+ |
+ property ':' maybe_space error expr prio {
+ /* The default movable type template has letter-spacing: .none; Handle this by looking for
+ error tokens at the start of an expr, recover the expr and then treat as an error, cleaning
+ up and deleting the shifted expr. */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ property ':' maybe_space expr prio error {
+ /* When we encounter something like p {color: red !important fail;} we should drop the declaration */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ IMPORTANT_SYM maybe_space {
+ /* Handle this case: div { text-align: center; !important } Just reduce away the stray !important. */
+ $$ = false;
+ }
+ |
+ property ':' maybe_space {
+ /* div { font-family: } Just reduce away this property with no value. */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ property ':' maybe_space error {
+ /* if we come across rules with invalid values like this case: p { weight: *; }, just discard the rule */
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ p->markPropertyEnd(false, false);
+ $$ = false;
+ }
+ |
+ property invalid_block {
+ /* if we come across: div { color{;color:maroon} }, ignore everything within curly brackets */
+ $$ = false;
+ }
+ ;
+
+property:
+ IDENT maybe_space {
+ $$ = cssPropertyID($1);
+ }
+ ;
+
+prio:
+ IMPORTANT_SYM maybe_space { $$ = true; }
+ | /* empty */ { $$ = false; }
+ ;
+
+expr:
+ term {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingValueList();
+ $$->addValue(p->sinkFloatingValue($1));
+ }
+ | expr operator term {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = $1;
+ if ($$) {
+ if ($2) {
+ CSSParserValue v;
+ v.id = 0;
+ v.unit = CSSParserValue::Operator;
+ v.iValue = $2;
+ $$->addValue(v);
+ }
+ $$->addValue(p->sinkFloatingValue($3));
+ }
+ }
+ | expr invalid_block_list {
+ $$ = 0;
+ }
+ | expr invalid_block_list error {
+ $$ = 0;
+ }
+ | expr error {
+ $$ = 0;
+ }
+ ;
+
+operator:
+ '/' maybe_space {
+ $$ = '/';
+ }
+ | ',' maybe_space {
+ $$ = ',';
+ }
+ | /* empty */ {
+ $$ = 0;
+ }
+ ;
+
+term:
+ unary_term { $$ = $1; }
+ | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
+ | STRING maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; }
+ | IDENT maybe_space {
+ $$.id = cssValueKeywordID($1);
+ $$.unit = CSSPrimitiveValue::CSS_IDENT;
+ $$.string = $1;
+ }
+ /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */
+ | DIMEN maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
+ | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; }
+ | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; }
+ | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; }
+ | HEX maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; }
+ | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */
+ /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */
+ | function {
+ $$ = $1;
+ }
+ | calc_function {
+ $$ = $1;
+ }
+ | min_or_max_function {
+ $$ = $1;
+ }
+ | '%' maybe_space { /* Handle width: %; */
+ $$.id = 0; $$.unit = 0;
+ }
+ ;
+
+unary_term:
+ INTEGER maybe_space { $$.id = 0; $$.isInt = true; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | FLOATTOKEN maybe_space { $$.id = 0; $$.isInt = false; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_NUMBER; }
+ | PERCENTAGE maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PERCENTAGE; }
+ | PXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PX; }
+ | CMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_CM; }
+ | MMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MM; }
+ | INS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_IN; }
+ | PTS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PT; }
+ | PCS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_PC; }
+ | DEGS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_DEG; }
+ | RADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_RAD; }
+ | GRADS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_GRAD; }
+ | TURNS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_TURN; }
+ | MSECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_MS; }
+ | SECS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_S; }
+ | HERTZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_HZ; }
+ | KHERTZ maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_KHZ; }
+ | EMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EMS; }
+ | QEMS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSParserValue::Q_EMS; }
+ | EXS maybe_space { $$.id = 0; $$.fValue = $1; $$.unit = CSSPrimitiveValue::CSS_EXS; }
+ | REMS maybe_space {
+ $$.id = 0;
+ $$.fValue = $1;
+ $$.unit = CSSPrimitiveValue::CSS_REMS;
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if (Document* doc = p->findDocument())
+ doc->setUsesRemUnits(true);
+ }
+ ;
+
+function:
+ FUNCTION maybe_space expr ')' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = p->sinkFloatingValueList($3);
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ } |
+ FUNCTION maybe_space expr TOKEN_EOF {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = p->sinkFloatingValueList($3);
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ } |
+ FUNCTION maybe_space ')' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ CSSParserValueList* valueList = p->createFloatingValueList();
+ f->args = p->sinkFloatingValueList(valueList);
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ } |
+ FUNCTION maybe_space error {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = nullptr;
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ }
+ ;
+
+calc_func_term:
+ unary_term { $$ = $1; }
+ | unary_operator unary_term { $$ = $2; $$.fValue *= $1; }
+ ;
+
+calc_func_operator:
+ '+' WHITESPACE {
+ $$ = '+';
+ }
+ | '-' WHITESPACE {
+ $$ = '-';
+ }
+ | '*' maybe_space {
+ $$ = '*';
+ }
+ | '/' maybe_space {
+ $$ = '/';
+ }
+ | IDENT maybe_space {
+ if (equalIgnoringCase("mod", $1.characters, $1.length))
+ $$ = '%';
+ else
+ $$ = 0;
+ }
+ ;
+
+calc_func_paren_expr:
+ '(' maybe_space calc_func_expr maybe_space ')' maybe_space {
+ if ($3) {
+ $$ = $3;
+ CSSParserValue v;
+ v.id = 0;
+ v.unit = CSSParserValue::Operator;
+ v.iValue = '(';
+ $$->insertValueAt(0, v);
+ v.iValue = ')';
+ $$->addValue(v);
+ } else
+ $$ = 0;
+ }
+
+calc_func_expr:
+ calc_func_term maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ $$ = p->createFloatingValueList();
+ $$->addValue(p->sinkFloatingValue($1));
+ }
+ | calc_func_expr calc_func_operator calc_func_term {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ if ($1 && $2) {
+ $$ = $1;
+ CSSParserValue v;
+ v.id = 0;
+ v.unit = CSSParserValue::Operator;
+ v.iValue = $2;
+ $$->addValue(v);
+ $$->addValue(p->sinkFloatingValue($3));
+ } else
+ $$ = 0;
+
+ }
+ | calc_func_expr calc_func_operator calc_func_paren_expr {
+ if ($1 && $2 && $3) {
+ $$ = $1;
+ CSSParserValue v;
+ v.id = 0;
+ v.unit = CSSParserValue::Operator;
+ v.iValue = $2;
+ $$->addValue(v);
+ $$->extend(*($3));
+ } else
+ $$ = 0;
+ }
+ | calc_func_paren_expr
+ | calc_func_expr error {
+ $$ = 0;
+ }
+ ;
+
+calc_func_expr_list:
+ calc_func_expr {
+ $$ = $1;
+ }
+ | calc_func_expr_list ',' maybe_space calc_func_expr {
+ if ($1 && $4) {
+ $$ = $1;
+ CSSParserValue v;
+ v.id = 0;
+ v.unit = CSSParserValue::Operator;
+ v.iValue = ',';
+ $$->addValue(v);
+ $$->extend(*($4));
+ } else
+ $$ = 0;
+ }
+
+
+calc_function:
+ CALCFUNCTION maybe_space calc_func_expr ')' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = p->sinkFloatingValueList($3);
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ }
+ | CALCFUNCTION maybe_space error {
+ YYERROR;
+ }
+ ;
+
+
+min_or_max:
+ MINFUNCTION {
+ $$ = $1;
+ }
+ | MAXFUNCTION {
+ $$ = $1;
+ }
+ ;
+
+min_or_max_function:
+ min_or_max maybe_space calc_func_expr_list ')' maybe_space {
+ CSSParser* p = static_cast<CSSParser*>(parser);
+ CSSParserFunction* f = p->createFloatingFunction();
+ f->name = $1;
+ f->args = p->sinkFloatingValueList($3);
+ $$.id = 0;
+ $$.unit = CSSParserValue::Function;
+ $$.function = f;
+ }
+ | min_or_max maybe_space error {
+ YYERROR;
+ }
+ ;
+
+/* error handling rules */
+
+save_block:
+ closing_brace {
+ $$ = 0;
+ }
+ | error closing_brace {
+ $$ = 0;
+ }
+ ;
+
+invalid_at:
+ ATKEYWORD error invalid_block {
+ $$ = 0;
+ }
+ | ATKEYWORD error ';' {
+ $$ = 0;
+ }
+ ;
+
+invalid_rule:
+ error invalid_block {
+ $$ = 0;
+ }
+
+/*
+ Seems like the two rules below are trying too much and violating
+ http://www.hixie.ch/tests/evil/mixed/csserrorhandling.html
+
+ | error ';' {
+ $$ = 0;
+ }
+ | error '}' {
+ $$ = 0;
+ }
+*/
+ ;
+
+invalid_block:
+ '{' error invalid_block_list error closing_brace {
+ static_cast<CSSParser*>(parser)->invalidBlockHit();
+ }
+ | '{' error closing_brace {
+ static_cast<CSSParser*>(parser)->invalidBlockHit();
+ }
+ ;
+
+invalid_block_list:
+ invalid_block
+ | invalid_block_list error invalid_block
+;
+
+%%
diff --git a/Source/WebCore/css/CSSHelper.h b/Source/WebCore/css/CSSHelper.h
new file mode 100644
index 000000000..6f2ffca9b
--- /dev/null
+++ b/Source/WebCore/css/CSSHelper.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2009 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 CSSHelper_h
+#define CSSHelper_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+// We always assume 96 CSS pixels in a CSS inch. This is the cold hard truth of the Web.
+// At high DPI, we may scale a CSS pixel, but the ratio of the CSS pixel to the so-called
+// "absolute" CSS length units like inch and pt is always fixed and never changes.
+const float cssPixelsPerInch = 96;
+
+} // namespace WebCore
+
+#endif // CSSHelper_h
diff --git a/Source/WebCore/css/CSSImageGeneratorValue.cpp b/Source/WebCore/css/CSSImageGeneratorValue.cpp
new file mode 100644
index 000000000..9be446bd0
--- /dev/null
+++ b/Source/WebCore/css/CSSImageGeneratorValue.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2008 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 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.
+ */
+
+#include "config.h"
+#include "CSSImageGeneratorValue.h"
+
+#include "CSSCanvasValue.h"
+#include "CSSCrossfadeValue.h"
+#include "CSSGradientValue.h"
+#include "Image.h"
+#include "RenderObject.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+CSSImageGeneratorValue::CSSImageGeneratorValue(ClassType classType)
+ : CSSValue(classType)
+{
+}
+
+CSSImageGeneratorValue::~CSSImageGeneratorValue()
+{
+}
+
+void CSSImageGeneratorValue::addClient(RenderObject* renderer, const IntSize& size)
+{
+ ref();
+
+ ASSERT(renderer);
+ if (!size.isEmpty())
+ m_sizes.add(size);
+
+ RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
+ if (it == m_clients.end())
+ m_clients.add(renderer, SizeAndCount(size, 1));
+ else {
+ SizeAndCount& sizeCount = it->second;
+ ++sizeCount.count;
+ }
+}
+
+void CSSImageGeneratorValue::removeClient(RenderObject* renderer)
+{
+ ASSERT(renderer);
+ RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
+ ASSERT(it != m_clients.end());
+
+ IntSize removedImageSize;
+ SizeAndCount& sizeCount = it->second;
+ IntSize size = sizeCount.size;
+ if (!size.isEmpty()) {
+ m_sizes.remove(size);
+ if (!m_sizes.contains(size))
+ m_images.remove(size);
+ }
+
+ if (!--sizeCount.count)
+ m_clients.remove(renderer);
+
+ deref();
+}
+
+Image* CSSImageGeneratorValue::getImage(RenderObject* renderer, const IntSize& size)
+{
+ RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
+ if (it != m_clients.end()) {
+ SizeAndCount& sizeCount = it->second;
+ IntSize oldSize = sizeCount.size;
+ if (oldSize != size) {
+ RefPtr<CSSImageGeneratorValue> protect(this);
+ removeClient(renderer);
+ addClient(renderer, size);
+ }
+ }
+
+ // Don't generate an image for empty sizes.
+ if (size.isEmpty())
+ return 0;
+
+ // Look up the image in our cache.
+ return m_images.get(size).get();
+}
+
+void CSSImageGeneratorValue::putImage(const IntSize& size, PassRefPtr<Image> image)
+{
+ m_images.add(size, image);
+}
+
+PassRefPtr<Image> CSSImageGeneratorValue::image(RenderObject* renderer, const IntSize& size)
+{
+ switch (classType()) {
+ case CanvasClass:
+ return static_cast<CSSCanvasValue*>(this)->image(renderer, size);
+ case CrossfadeClass:
+ return static_cast<CSSCrossfadeValue*>(this)->image(renderer, size);
+ case LinearGradientClass:
+ return static_cast<CSSLinearGradientValue*>(this)->image(renderer, size);
+ case RadialGradientClass:
+ return static_cast<CSSRadialGradientValue*>(this)->image(renderer, size);
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return 0;
+}
+
+bool CSSImageGeneratorValue::isFixedSize() const
+{
+ switch (classType()) {
+ case CanvasClass:
+ return static_cast<const CSSCanvasValue*>(this)->isFixedSize();
+ case CrossfadeClass:
+ return static_cast<const CSSCrossfadeValue*>(this)->isFixedSize();
+ case LinearGradientClass:
+ return static_cast<const CSSLinearGradientValue*>(this)->isFixedSize();
+ case RadialGradientClass:
+ return static_cast<const CSSRadialGradientValue*>(this)->isFixedSize();
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return false;
+}
+
+IntSize CSSImageGeneratorValue::fixedSize(const RenderObject* renderer)
+{
+ switch (classType()) {
+ case CanvasClass:
+ return static_cast<CSSCanvasValue*>(this)->fixedSize(renderer);
+ case CrossfadeClass:
+ return static_cast<CSSCrossfadeValue*>(this)->fixedSize(renderer);
+ case LinearGradientClass:
+ return static_cast<CSSLinearGradientValue*>(this)->fixedSize(renderer);
+ case RadialGradientClass:
+ return static_cast<CSSRadialGradientValue*>(this)->fixedSize(renderer);
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return IntSize();
+}
+
+bool CSSImageGeneratorValue::isPending() const
+{
+ switch (classType()) {
+ case CrossfadeClass:
+ return static_cast<const CSSCrossfadeValue*>(this)->isPending();
+ case CanvasClass:
+ return static_cast<const CSSCanvasValue*>(this)->isPending();
+ case LinearGradientClass:
+ return static_cast<const CSSLinearGradientValue*>(this)->isPending();
+ case RadialGradientClass:
+ return static_cast<const CSSRadialGradientValue*>(this)->isPending();
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return false;
+}
+
+void CSSImageGeneratorValue::loadSubimages(CachedResourceLoader* cachedResourceLoader)
+{
+ switch (classType()) {
+ case CrossfadeClass:
+ static_cast<CSSCrossfadeValue*>(this)->loadSubimages(cachedResourceLoader);
+ break;
+ case CanvasClass:
+ static_cast<CSSCanvasValue*>(this)->loadSubimages(cachedResourceLoader);
+ break;
+ case LinearGradientClass:
+ static_cast<CSSLinearGradientValue*>(this)->loadSubimages(cachedResourceLoader);
+ break;
+ case RadialGradientClass:
+ static_cast<CSSRadialGradientValue*>(this)->loadSubimages(cachedResourceLoader);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSImageGeneratorValue.h b/Source/WebCore/css/CSSImageGeneratorValue.h
new file mode 100644
index 000000000..877969a90
--- /dev/null
+++ b/Source/WebCore/css/CSSImageGeneratorValue.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2008 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 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 CSSImageGeneratorValue_h
+#define CSSImageGeneratorValue_h
+
+#include "CSSValue.h"
+#include "IntSizeHash.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CachedResourceLoader;
+class Image;
+class RenderObject;
+
+struct SizeAndCount {
+ SizeAndCount(IntSize newSize = IntSize(), int newCount = 0)
+ : size(newSize)
+ , count(newCount)
+ {
+ }
+
+ IntSize size;
+ int count;
+};
+
+typedef HashMap<const RenderObject*, SizeAndCount> RenderObjectSizeCountMap;
+
+class CSSImageGeneratorValue : public CSSValue {
+public:
+ ~CSSImageGeneratorValue();
+
+ void addClient(RenderObject*, const IntSize&);
+ void removeClient(RenderObject*);
+ PassRefPtr<Image> image(RenderObject*, const IntSize&);
+
+ bool isFixedSize() const;
+ IntSize fixedSize(const RenderObject*);
+
+ bool isPending() const;
+
+ void loadSubimages(CachedResourceLoader*);
+
+protected:
+ CSSImageGeneratorValue(ClassType);
+
+ Image* getImage(RenderObject*, const IntSize&);
+ void putImage(const IntSize&, PassRefPtr<Image>);
+ const RenderObjectSizeCountMap& clients() const { return m_clients; }
+
+ HashCountedSet<IntSize> m_sizes; // A count of how many times a given image size is in use.
+ RenderObjectSizeCountMap m_clients; // A map from RenderObjects (with entry count) to image sizes.
+ HashMap<IntSize, RefPtr<Image> > m_images; // A cache of Image objects by image size.
+};
+
+} // namespace WebCore
+
+#endif // CSSImageGeneratorValue_h
diff --git a/Source/WebCore/css/CSSImageValue.cpp b/Source/WebCore/css/CSSImageValue.cpp
new file mode 100644
index 000000000..8437f3ec0
--- /dev/null
+++ b/Source/WebCore/css/CSSImageValue.cpp
@@ -0,0 +1,110 @@
+/*
+ * (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 "CSSImageValue.h"
+
+#include "CSSCursorImageValue.h"
+#include "CSSValueKeywords.h"
+#include "Document.h"
+#include "MemoryCache.h"
+#include "CachedImage.h"
+#include "CachedResourceLoader.h"
+#include "StyleCachedImage.h"
+#include "StylePendingImage.h"
+
+namespace WebCore {
+
+CSSImageValue::CSSImageValue(ClassType classType, const String& url)
+ : CSSPrimitiveValue(classType, url, CSS_URI)
+ , m_accessedImage(false)
+{
+}
+
+CSSImageValue::CSSImageValue()
+ : CSSPrimitiveValue(ImageClass, CSSValueNone)
+ , m_accessedImage(true)
+{
+}
+
+CSSImageValue::CSSImageValue(const String& url)
+ : CSSPrimitiveValue(ImageClass, url, CSS_URI)
+ , m_accessedImage(false)
+{
+}
+
+CSSImageValue::CSSImageValue(const String& url, StyleImage* image)
+ : CSSPrimitiveValue(ImageClass, url, CSS_URI)
+ , m_image(image)
+ , m_accessedImage(true)
+{
+}
+
+CSSImageValue::~CSSImageValue()
+{
+}
+
+StyleImage* CSSImageValue::cachedOrPendingImage()
+{
+ if (getIdent() == CSSValueNone)
+ return 0;
+
+ if (!m_image)
+ m_image = StylePendingImage::create(this);
+
+ return m_image.get();
+}
+
+StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader)
+{
+ if (isCursorImageValue())
+ return static_cast<CSSCursorImageValue*>(this)->cachedImage(loader);
+ return cachedImage(loader, getStringValue());
+}
+
+StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader, const String& url)
+{
+ ASSERT(loader);
+
+ if (!m_accessedImage) {
+ m_accessedImage = true;
+
+ ResourceRequest request(loader->document()->completeURL(url));
+ if (CachedImage* cachedImage = loader->requestImage(request))
+ m_image = StyleCachedImage::create(cachedImage);
+ }
+
+ return (m_image && m_image->isCachedImage()) ? static_cast<StyleCachedImage*>(m_image.get()) : 0;
+}
+
+String CSSImageValue::cachedImageURL()
+{
+ if (!m_image || !m_image->isCachedImage())
+ return String();
+ return static_cast<StyleCachedImage*>(m_image.get())->cachedImage()->url();
+}
+
+void CSSImageValue::clearCachedImage()
+{
+ m_image = 0;
+ m_accessedImage = false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSImageValue.h b/Source/WebCore/css/CSSImageValue.h
new file mode 100644
index 000000000..82e34de4d
--- /dev/null
+++ b/Source/WebCore/css/CSSImageValue.h
@@ -0,0 +1,62 @@
+/*
+ * (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 CSSImageValue_h
+#define CSSImageValue_h
+
+#include "CSSPrimitiveValue.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CachedResourceLoader;
+class StyleCachedImage;
+class StyleImage;
+
+class CSSImageValue : public CSSPrimitiveValue {
+public:
+ static PassRefPtr<CSSImageValue> create() { return adoptRef(new CSSImageValue); }
+ static PassRefPtr<CSSImageValue> create(const String& url) { return adoptRef(new CSSImageValue(url)); }
+ static PassRefPtr<CSSImageValue> create(const String& url, StyleImage* image) { return adoptRef(new CSSImageValue(url, image)); }
+ ~CSSImageValue();
+
+ StyleCachedImage* cachedImage(CachedResourceLoader*);
+ // Returns a StyleCachedImage if the image is cached already, otherwise a StylePendingImage.
+ StyleImage* cachedOrPendingImage();
+
+protected:
+ CSSImageValue(ClassType, const String& url);
+
+ StyleCachedImage* cachedImage(CachedResourceLoader*, const String& url);
+ String cachedImageURL();
+ void clearCachedImage();
+
+private:
+ CSSImageValue();
+ explicit CSSImageValue(const String& url);
+ explicit CSSImageValue(const String& url, StyleImage*);
+
+ RefPtr<StyleImage> m_image;
+ bool m_accessedImage;
+};
+
+} // namespace WebCore
+
+#endif // CSSImageValue_h
diff --git a/Source/WebCore/css/CSSImportRule.cpp b/Source/WebCore/css/CSSImportRule.cpp
new file mode 100644
index 000000000..7e210a82c
--- /dev/null
+++ b/Source/WebCore/css/CSSImportRule.cpp
@@ -0,0 +1,180 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2005, 2006, 2008, 2009, 2010 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 "CSSImportRule.h"
+
+#include "CachedCSSStyleSheet.h"
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+CSSImportRule::CSSImportRule(CSSStyleSheet* parent, const String& href, PassRefPtr<MediaList> media)
+ : CSSRule(parent, CSSRule::IMPORT_RULE)
+ , m_styleSheetClient(this)
+ , m_strHref(href)
+ , m_lstMedia(media)
+ , m_cachedSheet(0)
+ , m_loading(false)
+{
+ ASSERT(parent);
+ if (m_lstMedia)
+ m_lstMedia->setParentStyleSheet(parent);
+ else
+ m_lstMedia = MediaList::create(parent, String());
+}
+
+CSSImportRule::~CSSImportRule()
+{
+ if (m_lstMedia)
+ m_lstMedia->setParentStyleSheet(0);
+ if (m_styleSheet)
+ m_styleSheet->clearOwnerRule();
+ if (m_cachedSheet)
+ m_cachedSheet->removeClient(&m_styleSheetClient);
+}
+
+void CSSImportRule::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet)
+{
+ if (m_styleSheet)
+ m_styleSheet->clearOwnerRule();
+ m_styleSheet = CSSStyleSheet::create(this, href, baseURL, charset);
+
+ bool crossOriginCSS = false;
+ bool validMIMEType = false;
+ CSSStyleSheet* parent = parentStyleSheet();
+ bool strict = !parent || parent->useStrictParsing();
+ bool enforceMIMEType = strict;
+ Document* document = parent ? parent->findDocument() : 0;
+ bool needsSiteSpecificQuirks = document && document->settings() && document->settings()->needsSiteSpecificQuirks();
+
+#ifdef BUILDING_ON_LEOPARD
+ if (enforceMIMEType && needsSiteSpecificQuirks) {
+ // Covers both http and https, with or without "www."
+ if (baseURL.string().contains("mcafee.com/japan/", false))
+ enforceMIMEType = false;
+ }
+#endif
+
+ String sheetText = sheet->sheetText(enforceMIMEType, &validMIMEType);
+ m_styleSheet->parseString(sheetText, strict);
+
+ if (!document || !document->securityOrigin()->canRequest(baseURL))
+ crossOriginCSS = true;
+
+ if (crossOriginCSS && !validMIMEType && !m_styleSheet->hasSyntacticallyValidCSSHeader())
+ m_styleSheet = CSSStyleSheet::create(this, href, baseURL, charset);
+
+ if (strict && needsSiteSpecificQuirks) {
+ // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>.
+ DEFINE_STATIC_LOCAL(const String, slashKHTMLFixesDotCss, ("/KHTMLFixes.css"));
+ DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, ("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"));
+ // There are two variants of KHTMLFixes.css. One is equal to mediaWikiKHTMLFixesStyleSheet,
+ // while the other lacks the second trailing newline.
+ if (baseURL.string().endsWith(slashKHTMLFixesDotCss) && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText)
+ && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) {
+ ASSERT(m_styleSheet->length() == 1);
+ ExceptionCode ec;
+ m_styleSheet->deleteRule(0, ec);
+ }
+ }
+
+ m_loading = false;
+
+ if (parent)
+ parent->checkLoaded();
+}
+
+bool CSSImportRule::isLoading() const
+{
+ return m_loading || (m_styleSheet && m_styleSheet->isLoading());
+}
+
+void CSSImportRule::requestStyleSheet()
+{
+ CSSStyleSheet* parentSheet = parentStyleSheet();
+ if (!parentSheet)
+ return;
+ Document* document = parentSheet->findDocument();
+ if (!document)
+ return;
+
+ CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
+ if (!cachedResourceLoader)
+ return;
+
+ String absHref = m_strHref;
+ if (!parentSheet->finalURL().isNull())
+ // use parent styleheet's URL as the base URL
+ absHref = KURL(parentSheet->finalURL(), m_strHref).string();
+
+ // Check for a cycle in our import chain. If we encounter a stylesheet
+ // in our parent chain with the same URL, then just bail.
+ CSSStyleSheet* rootSheet = parentSheet;
+ for (CSSStyleSheet* sheet = parentSheet; sheet; sheet = sheet->parentStyleSheet()) {
+ // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL.
+ if (absHref == sheet->finalURL().string())
+ return;
+ rootSheet = sheet;
+ }
+
+ ResourceRequest request(document->completeURL(absHref));
+ if (parentSheet->isUserStyleSheet())
+ m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parentSheet->charset());
+ else
+ m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parentSheet->charset());
+ if (m_cachedSheet) {
+ // if the import rule is issued dynamically, the sheet may be
+ // removed from the pending sheet count, so let the doc know
+ // the sheet being imported is pending.
+ if (parentSheet && parentSheet->loadCompleted() && rootSheet == parentSheet)
+ parentSheet->startLoadingDynamicSheet();
+ m_loading = true;
+ m_cachedSheet->addClient(&m_styleSheetClient);
+ }
+}
+
+String CSSImportRule::cssText() const
+{
+ String result = "@import url(\"";
+ result += m_strHref;
+ result += "\")";
+
+ if (m_lstMedia) {
+ result += " ";
+ result += m_lstMedia->mediaText();
+ }
+ result += ";";
+
+ return result;
+}
+
+void CSSImportRule::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
+{
+ if (m_styleSheet)
+ addSubresourceURL(urls, m_styleSheet->baseURL());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSImportRule.h b/Source/WebCore/css/CSSImportRule.h
new file mode 100644
index 000000000..ad15087ba
--- /dev/null
+++ b/Source/WebCore/css/CSSImportRule.h
@@ -0,0 +1,88 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 CSSImportRule_h
+#define CSSImportRule_h
+
+#include "CSSRule.h"
+#include "CachedResourceHandle.h"
+#include "CachedStyleSheetClient.h"
+#include "MediaList.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class CachedCSSStyleSheet;
+class MediaList;
+
+class CSSImportRule : public CSSRule {
+public:
+ static PassRefPtr<CSSImportRule> create(CSSStyleSheet* parent, const String& href, PassRefPtr<MediaList> media)
+ {
+ return adoptRef(new CSSImportRule(parent, href, media));
+ }
+
+ ~CSSImportRule();
+
+ String href() const { return m_strHref; }
+ MediaList* media() const { return m_lstMedia.get(); }
+ CSSStyleSheet* styleSheet() const { return m_styleSheet.get(); }
+
+ String cssText() const;
+
+ // Not part of the CSSOM
+ bool isLoading() const;
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>& urls);
+
+ void requestStyleSheet();
+
+private:
+ // NOTE: We put the CachedStyleSheetClient in a member instead of inheriting from it
+ // to avoid adding a vptr to CSSImportRule.
+ class ImportedStyleSheetClient : public CachedStyleSheetClient {
+ public:
+ ImportedStyleSheetClient(CSSImportRule* ownerRule) : m_ownerRule(ownerRule) { }
+ virtual ~ImportedStyleSheetClient() { }
+ virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet)
+ {
+ m_ownerRule->setCSSStyleSheet(href, baseURL, charset, sheet);
+ }
+ private:
+ CSSImportRule* m_ownerRule;
+ };
+
+ void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*);
+ friend class ImportedStyleSheetClient;
+
+ CSSImportRule(CSSStyleSheet* parent, const String& href, PassRefPtr<MediaList>);
+
+ ImportedStyleSheetClient m_styleSheetClient;
+ String m_strHref;
+ RefPtr<MediaList> m_lstMedia;
+ RefPtr<CSSStyleSheet> m_styleSheet;
+ CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet;
+ bool m_loading;
+};
+
+} // namespace WebCore
+
+#endif // CSSImportRule_h
diff --git a/Source/WebCore/css/CSSImportRule.idl b/Source/WebCore/css/CSSImportRule.idl
new file mode 100644
index 000000000..05654fe27
--- /dev/null
+++ b/Source/WebCore/css/CSSImportRule.idl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSImportRule : CSSRule {
+ readonly attribute [ConvertNullStringTo=Null] DOMString href;
+ readonly attribute MediaList media;
+ readonly attribute CSSStyleSheet styleSheet;
+ };
+
+}
diff --git a/Source/WebCore/css/CSSInheritedValue.cpp b/Source/WebCore/css/CSSInheritedValue.cpp
new file mode 100644
index 000000000..8c4be6d4b
--- /dev/null
+++ b/Source/WebCore/css/CSSInheritedValue.cpp
@@ -0,0 +1,33 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 "CSSInheritedValue.h"
+
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String CSSInheritedValue::customCssText() const
+{
+ return "inherit";
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSInheritedValue.h b/Source/WebCore/css/CSSInheritedValue.h
new file mode 100644
index 000000000..5aa906367
--- /dev/null
+++ b/Source/WebCore/css/CSSInheritedValue.h
@@ -0,0 +1,47 @@
+/*
+ * (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 CSSInheritedValue_h
+#define CSSInheritedValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class CSSInheritedValue : public CSSValue {
+public:
+ static PassRefPtr<CSSInheritedValue> create()
+ {
+ return adoptRef(new CSSInheritedValue);
+ }
+
+ String customCssText() const;
+
+private:
+ CSSInheritedValue()
+ : CSSValue(InheritedClass)
+ {
+ }
+};
+
+} // namespace WebCore
+
+#endif // CSSInheritedValue_h
diff --git a/Source/WebCore/css/CSSInitialValue.cpp b/Source/WebCore/css/CSSInitialValue.cpp
new file mode 100644
index 000000000..8de3f3182
--- /dev/null
+++ b/Source/WebCore/css/CSSInitialValue.cpp
@@ -0,0 +1,33 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 "CSSInitialValue.h"
+
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String CSSInitialValue::customCssText() const
+{
+ return "initial";
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSInitialValue.h b/Source/WebCore/css/CSSInitialValue.h
new file mode 100644
index 000000000..f5888903b
--- /dev/null
+++ b/Source/WebCore/css/CSSInitialValue.h
@@ -0,0 +1,52 @@
+/*
+ * (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 CSSInitialValue_h
+#define CSSInitialValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class CSSInitialValue : public CSSValue {
+public:
+ static PassRefPtr<CSSInitialValue> createExplicit()
+ {
+ return adoptRef(new CSSInitialValue(/* implicit */ false));
+ }
+ static PassRefPtr<CSSInitialValue> createImplicit()
+ {
+ return adoptRef(new CSSInitialValue(/* implicit */ true));
+ }
+
+ String customCssText() const;
+
+private:
+ CSSInitialValue(bool implicit)
+ : CSSValue(InitialClass)
+ {
+ m_isImplicitInitialValue = implicit;
+ }
+};
+
+} // namespace WebCore
+
+#endif // CSSInitialValue_h
diff --git a/Source/WebCore/css/CSSInlineStyleDeclaration.h b/Source/WebCore/css/CSSInlineStyleDeclaration.h
new file mode 100644
index 000000000..718e40959
--- /dev/null
+++ b/Source/WebCore/css/CSSInlineStyleDeclaration.h
@@ -0,0 +1,58 @@
+/*
+ * 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/CSSLineBoxContainValue.cpp b/Source/WebCore/css/CSSLineBoxContainValue.cpp
new file mode 100644
index 000000000..53132eb19
--- /dev/null
+++ b/Source/WebCore/css/CSSLineBoxContainValue.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 "CSSLineBoxContainValue.h"
+
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+CSSLineBoxContainValue::CSSLineBoxContainValue(unsigned value)
+ : CSSValue(LineBoxContainClass)
+ , m_value(value)
+{
+}
+
+String CSSLineBoxContainValue::customCssText() const
+{
+ String text("");
+
+ if (m_value & LineBoxContainBlock)
+ text += "block";
+ if (m_value & LineBoxContainInline) {
+ if (!text.isEmpty())
+ text += " ";
+ text += "inline";
+ }
+ if (m_value & LineBoxContainFont) {
+ if (!text.isEmpty())
+ text += " ";
+ text += "font";
+ }
+ if (m_value & LineBoxContainGlyphs) {
+ if (!text.isEmpty())
+ text += " ";
+ text += "glyphs";
+ }
+ if (m_value & LineBoxContainReplaced) {
+ if (!text.isEmpty())
+ text += " ";
+ text += "replaced";
+ }
+ if (m_value & LineBoxContainInlineBox) {
+ if (!text.isEmpty())
+ text += " ";
+ text += "inline-box";
+ }
+
+ return text;
+}
+
+}
diff --git a/Source/WebCore/css/CSSLineBoxContainValue.h b/Source/WebCore/css/CSSLineBoxContainValue.h
new file mode 100644
index 000000000..ddc0c60f3
--- /dev/null
+++ b/Source/WebCore/css/CSSLineBoxContainValue.h
@@ -0,0 +1,62 @@
+/*
+ * 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 CSSLineBoxContainValue_h
+#define CSSLineBoxContainValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSPrimitiveValue;
+
+enum LineBoxContainFlags { LineBoxContainNone = 0x0, LineBoxContainBlock = 0x1, LineBoxContainInline = 0x2, LineBoxContainFont = 0x4, LineBoxContainGlyphs = 0x8,
+ LineBoxContainReplaced = 0x10, LineBoxContainInlineBox = 0x20 };
+typedef unsigned LineBoxContain;
+
+// Used for text-CSSLineBoxContain and box-CSSLineBoxContain
+class CSSLineBoxContainValue : public CSSValue {
+public:
+ static PassRefPtr<CSSLineBoxContainValue> create(LineBoxContain value)
+ {
+ return adoptRef(new CSSLineBoxContainValue(value));
+ }
+
+ String customCssText() const;
+
+ LineBoxContain value() const { return m_value; }
+
+private:
+ LineBoxContain m_value;
+
+private:
+ CSSLineBoxContainValue(LineBoxContain);
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/CSSMediaRule.cpp b/Source/WebCore/css/CSSMediaRule.cpp
new file mode 100644
index 000000000..baf19b69a
--- /dev/null
+++ b/Source/WebCore/css/CSSMediaRule.cpp
@@ -0,0 +1,130 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
+ *
+ * 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 "CSSMediaRule.h"
+
+#include "CSSParser.h"
+#include "ExceptionCode.h"
+
+namespace WebCore {
+
+CSSMediaRule::CSSMediaRule(CSSStyleSheet* parent, PassRefPtr<MediaList> media, PassRefPtr<CSSRuleList> rules)
+ : CSSRule(parent, CSSRule::MEDIA_RULE)
+ , m_lstMedia(media)
+ , m_lstCSSRules(rules)
+{
+ m_lstMedia->setParentStyleSheet(parent);
+ int length = m_lstCSSRules->length();
+ for (int i = 0; i < length; i++)
+ m_lstCSSRules->item(i)->setParentRule(this);
+}
+
+CSSMediaRule::~CSSMediaRule()
+{
+ if (m_lstMedia)
+ m_lstMedia->setParentStyleSheet(0);
+
+ int length = m_lstCSSRules->length();
+ for (int i = 0; i < length; i++)
+ m_lstCSSRules->item(i)->setParentRule(0);
+}
+
+unsigned CSSMediaRule::append(CSSRule* rule)
+{
+ if (!rule)
+ return 0;
+
+ rule->setParentRule(this);
+ return m_lstCSSRules->insertRule(rule, m_lstCSSRules->length());
+}
+
+unsigned CSSMediaRule::insertRule(const String& rule, unsigned index, ExceptionCode& ec)
+{
+ if (index > m_lstCSSRules->length()) {
+ // INDEX_SIZE_ERR: Raised if the specified index is not a valid insertion point.
+ ec = INDEX_SIZE_ERR;
+ return 0;
+ }
+
+ CSSParser p(useStrictParsing());
+ RefPtr<CSSRule> newRule = p.parseRule(parentStyleSheet(), rule);
+ if (!newRule) {
+ // SYNTAX_ERR: Raised if the specified rule has a syntax error and is unparsable.
+ ec = SYNTAX_ERR;
+ return 0;
+ }
+
+ if (newRule->isImportRule()) {
+ // FIXME: an HIERARCHY_REQUEST_ERR should also be thrown for a @charset or a nested
+ // @media rule. They are currently not getting parsed, resulting in a SYNTAX_ERR
+ // to get raised above.
+
+ // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified
+ // index, e.g., if an @import rule is inserted after a standard rule set or other
+ // at-rule.
+ ec = HIERARCHY_REQUEST_ERR;
+ return 0;
+ }
+
+ newRule->setParentRule(this);
+ unsigned returnedIndex = m_lstCSSRules->insertRule(newRule.get(), index);
+
+ if (CSSStyleSheet* styleSheet = parentStyleSheet())
+ styleSheet->styleSheetChanged();
+
+ return returnedIndex;
+}
+
+void CSSMediaRule::deleteRule(unsigned index, ExceptionCode& ec)
+{
+ if (index >= m_lstCSSRules->length()) {
+ // INDEX_SIZE_ERR: Raised if the specified index does not correspond to a
+ // rule in the media rule list.
+ ec = INDEX_SIZE_ERR;
+ return;
+ }
+
+ m_lstCSSRules->item(index)->setParentRule(0);
+ m_lstCSSRules->deleteRule(index);
+
+ if (CSSStyleSheet* styleSheet = parentStyleSheet())
+ styleSheet->styleSheetChanged();
+}
+
+String CSSMediaRule::cssText() const
+{
+ String result = "@media ";
+ if (m_lstMedia) {
+ result += m_lstMedia->mediaText();
+ result += " ";
+ }
+ result += "{ \n";
+
+ if (m_lstCSSRules)
+ result += m_lstCSSRules->rulesText();
+
+ result += "}";
+ return result;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSMediaRule.h b/Source/WebCore/css/CSSMediaRule.h
new file mode 100644
index 000000000..a591192a9
--- /dev/null
+++ b/Source/WebCore/css/CSSMediaRule.h
@@ -0,0 +1,63 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
+ *
+ * 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 CSSMediaRule_h
+#define CSSMediaRule_h
+
+#include "CSSRule.h"
+#include "CSSRuleList.h"
+#include "MediaList.h"
+#include "PlatformString.h" // needed so bindings will compile
+
+namespace WebCore {
+
+class CSSRuleList;
+
+class CSSMediaRule : public CSSRule {
+public:
+ static PassRefPtr<CSSMediaRule> create(CSSStyleSheet* parent, PassRefPtr<MediaList> media, PassRefPtr<CSSRuleList> rules)
+ {
+ return adoptRef(new CSSMediaRule(parent, media, rules));
+ }
+ ~CSSMediaRule();
+
+ MediaList* media() const { return m_lstMedia.get(); }
+ CSSRuleList* cssRules() { return m_lstCSSRules.get(); }
+
+ unsigned insertRule(const String& rule, unsigned index, ExceptionCode&);
+ void deleteRule(unsigned index, ExceptionCode&);
+
+ String cssText() const;
+
+ // Not part of the CSSOM
+ unsigned append(CSSRule*);
+
+private:
+ CSSMediaRule(CSSStyleSheet* parent, PassRefPtr<MediaList>, PassRefPtr<CSSRuleList>);
+
+ RefPtr<MediaList> m_lstMedia;
+ RefPtr<CSSRuleList> m_lstCSSRules;
+};
+
+} // namespace WebCore
+
+#endif // CSSMediaRule_h
diff --git a/Source/WebCore/css/CSSMediaRule.idl b/Source/WebCore/css/CSSMediaRule.idl
new file mode 100644
index 000000000..cf1a488b5
--- /dev/null
+++ b/Source/WebCore/css/CSSMediaRule.idl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSMediaRule : CSSRule {
+ readonly attribute MediaList media;
+ readonly attribute CSSRuleList cssRules;
+
+ [OldStyleObjC] unsigned long insertRule(in [Optional=CallWithDefaultValue] DOMString rule,
+ in [Optional=CallWithDefaultValue] unsigned long index)
+ raises(DOMException);
+ void deleteRule(in [Optional=CallWithDefaultValue] unsigned long index)
+ raises(DOMException);
+ };
+
+}
diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp
new file mode 100644
index 000000000..c831b07df
--- /dev/null
+++ b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp
@@ -0,0 +1,1055 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Research In Motion Limited. 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 "CSSMutableStyleDeclaration.h"
+
+#include "CSSImageValue.h"
+#include "CSSInlineStyleDeclaration.h"
+#include "CSSParser.h"
+#include "CSSPropertyLonghand.h"
+#include "CSSPropertyNames.h"
+#include "CSSRule.h"
+#include "CSSStyleSheet.h"
+#include "CSSValueKeywords.h"
+#include "CSSValueList.h"
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "HTMLNames.h"
+#include "InspectorInstrumentation.h"
+#include "MutationObserverInterestGroup.h"
+#include "MutationRecord.h"
+#include "StyledElement.h"
+#include "WebKitMutationObserver.h"
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/WTFString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+namespace {
+
+class StyleAttributeMutationScope {
+ WTF_MAKE_NONCOPYABLE(StyleAttributeMutationScope);
+public:
+ StyleAttributeMutationScope(CSSMutableStyleDeclaration* decl)
+ {
+ ++s_scopeCount;
+
+ if (s_scopeCount != 1) {
+ ASSERT(s_currentDecl == decl);
+ return;
+ }
+
+ ASSERT(!s_currentDecl);
+ s_currentDecl = decl;
+
+#if ENABLE(MUTATION_OBSERVERS)
+ if (!s_currentDecl->isInlineStyleDeclaration())
+ return;
+
+ CSSInlineStyleDeclaration* inlineDecl = toCSSInlineStyleDeclaration(s_currentDecl);
+ if (!inlineDecl->element())
+ return;
+
+ m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(inlineDecl->element(), 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);
+#endif
+ }
+
+ ~StyleAttributeMutationScope()
+ {
+ --s_scopeCount;
+ if (s_scopeCount)
+ return;
+
+#if ENABLE(MUTATION_OBSERVERS)
+ if (m_mutation && s_shouldDeliver)
+ m_mutationRecipients->enqueueMutationRecord(m_mutation);
+ s_shouldDeliver = false;
+#endif
+
+ if (!s_shouldNotifyInspector) {
+ s_currentDecl = 0;
+ return;
+ }
+
+ CSSInlineStyleDeclaration* inlineDecl = toCSSInlineStyleDeclaration(s_currentDecl);
+ s_currentDecl = 0;
+ s_shouldNotifyInspector = false;
+ if (inlineDecl->element() && inlineDecl->element()->document())
+ InspectorInstrumentation::didInvalidateStyleAttr(inlineDecl->element()->document(), inlineDecl->element());
+ }
+
+#if ENABLE(MUTATION_OBSERVERS)
+ void enqueueMutationRecord()
+ {
+ s_shouldDeliver = true;
+ }
+#endif
+
+ void didInvalidateStyleAttr()
+ {
+ ASSERT(s_currentDecl->isInlineStyleDeclaration());
+ s_shouldNotifyInspector = true;
+ }
+
+private:
+ static unsigned s_scopeCount;
+ static CSSMutableStyleDeclaration* s_currentDecl;
+ static bool s_shouldNotifyInspector;
+#if ENABLE(MUTATION_OBSERVERS)
+ static bool s_shouldDeliver;
+
+ OwnPtr<MutationObserverInterestGroup> m_mutationRecipients;
+ RefPtr<MutationRecord> m_mutation;
+#endif
+};
+
+unsigned StyleAttributeMutationScope::s_scopeCount = 0;
+CSSMutableStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = 0;
+bool StyleAttributeMutationScope::s_shouldNotifyInspector = false;
+#if ENABLE(MUTATION_OBSERVERS)
+bool StyleAttributeMutationScope::s_shouldDeliver = false;
+#endif
+
+} // namespace
+
+CSSMutableStyleDeclaration::CSSMutableStyleDeclaration()
+ : CSSStyleDeclaration(0)
+{
+ // This constructor is used for various inline style declarations, so disable strict parsing.
+ m_strictParsing = false;
+}
+
+CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent)
+ : CSSStyleDeclaration(parent)
+{
+}
+
+CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const Vector<CSSProperty>& properties)
+ : CSSStyleDeclaration(parent)
+ , m_properties(properties)
+{
+ m_properties.shrinkToFit();
+ // FIXME: This allows duplicate properties.
+}
+
+CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CSSProperty* const * properties, int numProperties)
+ : CSSStyleDeclaration(parent)
+{
+ m_properties.reserveInitialCapacity(numProperties);
+ HashMap<int, bool> candidates;
+ for (int i = 0; i < numProperties; ++i) {
+ const CSSProperty *property = properties[i];
+ ASSERT(property);
+ bool important = property->isImportant();
+
+ HashMap<int, bool>::iterator it = candidates.find(property->id());
+ if (it != candidates.end()) {
+ if (!important && it->second)
+ continue;
+ removeProperty(property->id(), false, false);
+ }
+
+ m_properties.append(*property);
+ candidates.set(property->id(), important);
+ }
+}
+
+CSSMutableStyleDeclaration::~CSSMutableStyleDeclaration()
+{
+}
+
+void CSSMutableStyleDeclaration::copyPropertiesFrom(const CSSMutableStyleDeclaration& other)
+{
+ ASSERT(!m_iteratorCount);
+ m_properties = other.m_properties;
+}
+
+String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const
+{
+ RefPtr<CSSValue> value = getPropertyCSSValue(propertyID);
+ if (value)
+ return value->cssText();
+
+ // Shorthand and 4-values properties
+ switch (propertyID) {
+ case CSSPropertyBorderSpacing: {
+ const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing };
+ return borderSpacingValue(properties);
+ }
+ case CSSPropertyBackgroundPosition: {
+ // FIXME: Is this correct? The code in cssparser.cpp is confusing
+ const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyBackgroundRepeat: {
+ const int properties[2] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyBackground: {
+ const int properties[9] = { CSSPropertyBackgroundColor,
+ CSSPropertyBackgroundImage,
+ CSSPropertyBackgroundRepeatX,
+ CSSPropertyBackgroundRepeatY,
+ CSSPropertyBackgroundAttachment,
+ CSSPropertyBackgroundPositionX,
+ CSSPropertyBackgroundPositionY,
+ CSSPropertyBackgroundClip,
+ CSSPropertyBackgroundOrigin };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyBorder: {
+ const int properties[3][4] = {{ CSSPropertyBorderTopWidth,
+ CSSPropertyBorderRightWidth,
+ CSSPropertyBorderBottomWidth,
+ CSSPropertyBorderLeftWidth },
+ { CSSPropertyBorderTopStyle,
+ CSSPropertyBorderRightStyle,
+ CSSPropertyBorderBottomStyle,
+ CSSPropertyBorderLeftStyle },
+ { CSSPropertyBorderTopColor,
+ CSSPropertyBorderRightColor,
+ CSSPropertyBorderBottomColor,
+ CSSPropertyBorderLeftColor }};
+ String res;
+ for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) {
+ String value = getCommonValue(properties[i]);
+ if (!value.isNull()) {
+ if (!res.isNull())
+ res += " ";
+ res += value;
+ }
+ }
+ return res;
+ }
+ case CSSPropertyBorderTop: {
+ const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
+ CSSPropertyBorderTopColor};
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyBorderRight: {
+ const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
+ CSSPropertyBorderRightColor};
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyBorderBottom: {
+ const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
+ CSSPropertyBorderBottomColor};
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyBorderLeft: {
+ const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
+ CSSPropertyBorderLeftColor};
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyOutline: {
+ const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
+ CSSPropertyOutlineColor };
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyBorderColor: {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
+ CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return get4Values(properties);
+ }
+ case CSSPropertyBorderWidth: {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
+ CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return get4Values(properties);
+ }
+ case CSSPropertyBorderStyle: {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
+ CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return get4Values(properties);
+ }
+ case CSSPropertyWebkitFlexFlow: {
+ const int properties[] = { CSSPropertyWebkitFlexDirection, CSSPropertyWebkitFlexWrap };
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyFont:
+ return fontValue();
+ case CSSPropertyMargin: {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
+ CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return get4Values(properties);
+ }
+ case CSSPropertyOverflow: {
+ const int properties[2] = { CSSPropertyOverflowX, CSSPropertyOverflowY };
+ return getCommonValue(properties);
+ }
+ case CSSPropertyPadding: {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
+ CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return get4Values(properties);
+ }
+ case CSSPropertyListStyle: {
+ const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
+ CSSPropertyListStyleImage };
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyWebkitMaskPosition: {
+ // FIXME: Is this correct? The code in cssparser.cpp is confusing
+ const int properties[2] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyWebkitMaskRepeat: {
+ const int properties[2] = { CSSPropertyWebkitMaskRepeatX, CSSPropertyWebkitMaskRepeatY };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyWebkitMask: {
+ const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
+ CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskClip,
+ CSSPropertyWebkitMaskOrigin };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyWebkitTransformOrigin: {
+ const int properties[3] = { CSSPropertyWebkitTransformOriginX,
+ CSSPropertyWebkitTransformOriginY,
+ CSSPropertyWebkitTransformOriginZ };
+ return getShorthandValue(properties);
+ }
+ case CSSPropertyWebkitTransition: {
+ const int properties[4] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration,
+ CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionDelay };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyWebkitAnimation: {
+ const int properties[7] = { CSSPropertyWebkitAnimationName, CSSPropertyWebkitAnimationDuration,
+ CSSPropertyWebkitAnimationTimingFunction, CSSPropertyWebkitAnimationDelay,
+ CSSPropertyWebkitAnimationIterationCount, CSSPropertyWebkitAnimationDirection,
+ CSSPropertyWebkitAnimationFillMode };
+ return getLayeredShorthandValue(properties);
+ }
+ case CSSPropertyWebkitWrap: {
+ const int properties[3] = { CSSPropertyWebkitWrapFlow, CSSPropertyWebkitWrapMargin,
+ CSSPropertyWebkitWrapPadding };
+ return getShorthandValue(properties);
+ }
+#if ENABLE(SVG)
+ case CSSPropertyMarker: {
+ RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyMarkerStart);
+ if (value)
+ return value->cssText();
+ }
+#endif
+ }
+ return String();
+}
+
+String CSSMutableStyleDeclaration::borderSpacingValue(const int properties[2]) const
+{
+ RefPtr<CSSValue> horizontalValue = getPropertyCSSValue(properties[0]);
+ RefPtr<CSSValue> verticalValue = getPropertyCSSValue(properties[1]);
+
+ if (!horizontalValue)
+ return String();
+ ASSERT(verticalValue); // By <http://www.w3.org/TR/CSS21/tables.html#separated-borders>.
+
+ String horizontalValueCSSText = horizontalValue->cssText();
+ String verticalValueCSSText = verticalValue->cssText();
+ if (horizontalValueCSSText == verticalValueCSSText)
+ return horizontalValueCSSText;
+ return horizontalValueCSSText + ' ' + verticalValueCSSText;
+}
+
+bool CSSMutableStyleDeclaration::appendFontLonghandValueIfExplicit(int propertyId, StringBuilder& result) const
+{
+ const CSSProperty* property = findPropertyWithId(propertyId);
+ if (!property)
+ return false; // All longhands must have at least implicit values if "font" is specified.
+ if (property->isImplicit())
+ return true;
+
+ char prefix = '\0';
+ switch (propertyId) {
+ case CSSPropertyFontStyle:
+ break; // No prefix.
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontVariant:
+ case CSSPropertyFontWeight:
+ prefix = ' ';
+ break;
+ case CSSPropertyLineHeight:
+ prefix = '/';
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
+ if (prefix && !result.isEmpty())
+ result.append(prefix);
+ result.append(property->value()->cssText());
+
+ return true;
+}
+
+String CSSMutableStyleDeclaration::fontValue() const
+{
+ const CSSProperty* fontSizeProperty = findPropertyWithId(CSSPropertyFontSize);
+ if (!fontSizeProperty || fontSizeProperty->isImplicit())
+ return emptyString();
+
+ StringBuilder result;
+ bool success = true;
+ success &= appendFontLonghandValueIfExplicit(CSSPropertyFontStyle, result);
+ success &= appendFontLonghandValueIfExplicit(CSSPropertyFontVariant, result);
+ success &= appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result);
+ if (!result.isEmpty())
+ result.append(' ');
+ result.append(fontSizeProperty->value()->cssText());
+ success &= appendFontLonghandValueIfExplicit(CSSPropertyLineHeight, result);
+ success &= appendFontLonghandValueIfExplicit(CSSPropertyFontFamily, result);
+ if (!success) {
+ // An invalid "font" value has been built (should never happen, as at least implicit values
+ // for mandatory longhands are always found in the style), report empty value instead.
+ ASSERT_NOT_REACHED();
+ return emptyString();
+ }
+ return result.toString();
+}
+
+String CSSMutableStyleDeclaration::get4Values(const int* properties) const
+{
+ // Assume the properties are in the usual order top, right, bottom, left.
+ RefPtr<CSSValue> topValue = getPropertyCSSValue(properties[0]);
+ RefPtr<CSSValue> rightValue = getPropertyCSSValue(properties[1]);
+ RefPtr<CSSValue> bottomValue = getPropertyCSSValue(properties[2]);
+ RefPtr<CSSValue> leftValue = getPropertyCSSValue(properties[3]);
+
+ // All 4 properties must be specified.
+ if (!topValue || !rightValue || !bottomValue || !leftValue)
+ return String();
+
+ bool showLeft = rightValue->cssText() != leftValue->cssText();
+ bool showBottom = (topValue->cssText() != bottomValue->cssText()) || showLeft;
+ bool showRight = (topValue->cssText() != rightValue->cssText()) || showBottom;
+
+ String res = topValue->cssText();
+ if (showRight)
+ res += " " + rightValue->cssText();
+ if (showBottom)
+ res += " " + bottomValue->cssText();
+ if (showLeft)
+ res += " " + leftValue->cssText();
+
+ return res;
+}
+
+String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, size_t size) const
+{
+ String res;
+
+ // Begin by collecting the properties into an array.
+ Vector< RefPtr<CSSValue> > values(size);
+ size_t numLayers = 0;
+
+ for (size_t i = 0; i < size; ++i) {
+ values[i] = getPropertyCSSValue(properties[i]);
+ if (values[i]) {
+ if (values[i]->isValueList()) {
+ CSSValueList* valueList = static_cast<CSSValueList*>(values[i].get());
+ numLayers = max(valueList->length(), numLayers);
+ } else
+ numLayers = max<size_t>(1U, numLayers);
+ }
+ }
+
+ // Now stitch the properties together. Implicit initial values are flagged as such and
+ // can safely be omitted.
+ for (size_t i = 0; i < numLayers; i++) {
+ String layerRes;
+ bool useRepeatXShorthand = false;
+ bool useRepeatYShorthand = false;
+ bool useSingleWordShorthand = false;
+ for (size_t j = 0; j < size; j++) {
+ RefPtr<CSSValue> value;
+ if (values[j]) {
+ if (values[j]->isValueList())
+ value = static_cast<CSSValueList*>(values[j].get())->item(i);
+ else {
+ value = values[j];
+
+ // Color only belongs in the last layer.
+ if (properties[j] == CSSPropertyBackgroundColor) {
+ if (i != numLayers - 1)
+ value = 0;
+ } else if (i != 0) // Other singletons only belong in the first layer.
+ value = 0;
+ }
+ }
+
+ // We need to report background-repeat as it was written in the CSS. If the property is implicit,
+ // then it was written with only one value. Here we figure out which value that was so we can
+ // report back correctly.
+ if (properties[j] == CSSPropertyBackgroundRepeatX && isPropertyImplicit(properties[j])) {
+
+ // BUG 49055: make sure the value was not reset in the layer check just above.
+ if (j < size - 1 && properties[j + 1] == CSSPropertyBackgroundRepeatY && value) {
+ RefPtr<CSSValue> yValue;
+ RefPtr<CSSValue> nextValue = values[j + 1];
+ if (nextValue->isValueList())
+ yValue = static_cast<CSSValueList*>(nextValue.get())->itemWithoutBoundsCheck(i);
+ else
+ yValue = nextValue;
+
+ int xId = static_cast<CSSPrimitiveValue*>(value.get())->getIdent();
+ int yId = static_cast<CSSPrimitiveValue*>(yValue.get())->getIdent();
+ if (xId != yId) {
+ if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) {
+ useRepeatXShorthand = true;
+ ++j;
+ } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) {
+ useRepeatYShorthand = true;
+ continue;
+ }
+ } else {
+ useSingleWordShorthand = true;
+ ++j;
+ }
+ }
+ }
+
+ if (value && !value->isImplicitInitialValue()) {
+ if (!layerRes.isNull())
+ layerRes += " ";
+ if (useRepeatXShorthand) {
+ useRepeatXShorthand = false;
+ layerRes += getValueName(CSSValueRepeatX);
+ } else if (useRepeatYShorthand) {
+ useRepeatYShorthand = false;
+ layerRes += getValueName(CSSValueRepeatY);
+ } else if (useSingleWordShorthand) {
+ useSingleWordShorthand = false;
+ layerRes += value->cssText();
+ } else
+ layerRes += value->cssText();
+ }
+ }
+
+ if (!layerRes.isNull()) {
+ if (!res.isNull())
+ res += ", ";
+ res += layerRes;
+ }
+ }
+
+ return res;
+}
+
+String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, size_t size) const
+{
+ String res;
+ for (size_t i = 0; i < size; ++i) {
+ if (!isPropertyImplicit(properties[i])) {
+ RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
+ // FIXME: provide default value if !value
+ if (value) {
+ if (!res.isNull())
+ res += " ";
+ res += value->cssText();
+ }
+ }
+ }
+ return res;
+}
+
+// only returns a non-null value if all properties have the same, non-null value
+String CSSMutableStyleDeclaration::getCommonValue(const int* properties, size_t size) const
+{
+ String res;
+ for (size_t i = 0; i < size; ++i) {
+ RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
+ if (!value)
+ return String();
+ String text = value->cssText();
+ if (text.isNull())
+ return String();
+ if (res.isNull())
+ res = text;
+ else if (res != text)
+ return String();
+ }
+ return res;
+}
+
+PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(int propertyID) const
+{
+ const CSSProperty* property = findPropertyWithId(propertyID);
+ return property ? property->value() : 0;
+}
+
+bool CSSMutableStyleDeclaration::removeShorthandProperty(int propertyID, bool notifyChanged)
+{
+ CSSPropertyLonghand longhand = longhandForProperty(propertyID);
+ if (!longhand.length())
+ return false;
+ return removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged);
+}
+
+String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText)
+{
+ ASSERT(!m_iteratorCount);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ StyleAttributeMutationScope mutationScope(this);
+#endif
+
+ if (removeShorthandProperty(propertyID, notifyChanged)) {
+ // FIXME: Return an equivalent shorthand when possible.
+ return String();
+ }
+
+ CSSProperty* foundProperty = findPropertyWithId(propertyID);
+ if (!foundProperty)
+ return String();
+
+ String value = returnText ? foundProperty->value()->cssText() : String();
+
+ // A more efficient removal strategy would involve marking entries as empty
+ // and sweeping them when the vector grows too big.
+ m_properties.remove(foundProperty - m_properties.data());
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+
+ if (notifyChanged)
+ setNeedsStyleRecalc();
+
+ return value;
+}
+
+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();
+ }
+ return;
+ }
+
+ if (CSSStyleSheet* styleSheet = parentStyleSheet()) {
+ if (Document* document = styleSheet->findDocument())
+ document->styleSelectorChanged(DeferRecalcStyle);
+ }
+}
+
+bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const
+{
+ const CSSProperty* property = findPropertyWithId(propertyID);
+ return property ? property->isImportant() : false;
+}
+
+int CSSMutableStyleDeclaration::getPropertyShorthand(int propertyID) const
+{
+ const CSSProperty* property = findPropertyWithId(propertyID);
+ return property ? property->shorthandID() : 0;
+}
+
+bool CSSMutableStyleDeclaration::isPropertyImplicit(int propertyID) const
+{
+ const CSSProperty* property = findPropertyWithId(propertyID);
+ 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
+
+ // Setting the value to an empty string just removes the property in both IE and Gecko.
+ // Setting it to null seems to produce less consistent results, but we treat it just the same.
+ if (value.isEmpty()) {
+ removeProperty(propertyID, notifyChanged, false);
+ return true;
+ }
+
+ // When replacing an existing property value, this moves the property to the end of the list.
+ // Firefox preserves the position, and MSIE moves the property to the beginning.
+ bool success = CSSParser::parseValue(this, propertyID, value, important, useStrictParsing());
+ if (!success) {
+ // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility,
+ // see <http://bugs.webkit.org/show_bug.cgi?id=7296>.
+ return false;
+ }
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+
+ if (notifyChanged)
+ setNeedsStyleRecalc();
+
+ return true;
+}
+
+void CSSMutableStyleDeclaration::setPropertyInternal(const CSSProperty& property, CSSProperty* slot)
+{
+ ASSERT(!m_iteratorCount);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ StyleAttributeMutationScope mutationScope(this);
+#endif
+
+ if (!removeShorthandProperty(property.id(), false)) {
+ CSSProperty* toReplace = slot ? slot : findPropertyWithId(property.id());
+ if (toReplace) {
+ *toReplace = property;
+ return;
+ }
+ }
+ m_properties.append(property);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+}
+
+bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged)
+{
+ CSSProperty property(propertyID, CSSPrimitiveValue::createIdentifier(value), important);
+ setPropertyInternal(property);
+ if (notifyChanged)
+ setNeedsStyleRecalc();
+ return true;
+}
+
+bool CSSMutableStyleDeclaration::setProperty(int propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important, bool notifyChanged)
+{
+ CSSProperty property(propertyID, CSSPrimitiveValue::create(value, unit), important);
+ setPropertyInternal(property);
+ if (notifyChanged)
+ setNeedsStyleRecalc();
+ return true;
+}
+
+void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration)
+{
+ ASSERT(!m_iteratorCount);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ StyleAttributeMutationScope mutationScope(this);
+#endif
+
+ m_properties.clear();
+ CSSParser parser(useStrictParsing());
+ parser.parseDeclaration(this, styleDeclaration);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+
+ setNeedsStyleRecalc();
+}
+
+void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty* const* properties, int numProperties)
+{
+ ASSERT(!m_iteratorCount);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ StyleAttributeMutationScope mutationScope(this);
+#endif
+
+ m_properties.reserveCapacity(numProperties);
+ for (int i = 0; i < numProperties; ++i)
+ addParsedProperty(*properties[i]);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+
+ // FIXME: This probably should have a call to setNeedsStyleRecalc() if something changed. We may also wish to add
+ // a notifyChanged argument to this function to follow the model of other functions in this class.
+}
+
+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()) {
+ removeProperty(property.id(), false, false);
+ m_properties.append(property);
+ }
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+}
+
+unsigned CSSMutableStyleDeclaration::virtualLength() const
+{
+ return length();
+}
+
+String CSSMutableStyleDeclaration::item(unsigned i) const
+{
+ if (i >= m_properties.size())
+ return "";
+ return getPropertyName(static_cast<CSSPropertyID>(m_properties[i].id()));
+}
+
+String CSSMutableStyleDeclaration::cssText() const
+{
+ String result = "";
+
+ const CSSProperty* positionXProp = 0;
+ const CSSProperty* positionYProp = 0;
+ const CSSProperty* repeatXProp = 0;
+ const CSSProperty* repeatYProp = 0;
+
+ unsigned size = m_properties.size();
+ for (unsigned n = 0; n < size; ++n) {
+ const CSSProperty& prop = m_properties[n];
+ if (prop.id() == CSSPropertyBackgroundPositionX)
+ positionXProp = &prop;
+ else if (prop.id() == CSSPropertyBackgroundPositionY)
+ positionYProp = &prop;
+ else if (prop.id() == CSSPropertyBackgroundRepeatX)
+ repeatXProp = &prop;
+ else if (prop.id() == CSSPropertyBackgroundRepeatY)
+ repeatYProp = &prop;
+ else
+ result += prop.cssText();
+ }
+
+ // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output.
+ // It is required because background-position-x/y are non-standard properties and WebKit generated output
+ // would not work in Firefox (<rdar://problem/5143183>)
+ // It would be a better solution if background-position was CSS_PAIR.
+ if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) {
+ String positionValue;
+ const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
+ if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList())
+ positionValue = getLayeredShorthandValue(properties);
+ else
+ positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText();
+ result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; ";
+ } else {
+ if (positionXProp)
+ result += positionXProp->cssText();
+ if (positionYProp)
+ result += positionYProp->cssText();
+ }
+
+ // FIXME: We need to do the same for background-repeat.
+ if (repeatXProp && repeatYProp && repeatXProp->isImportant() == repeatYProp->isImportant()) {
+ String repeatValue;
+ const int repeatProperties[2] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY };
+ if (repeatXProp->value()->isValueList() || repeatYProp->value()->isValueList())
+ repeatValue = getLayeredShorthandValue(repeatProperties);
+ else
+ repeatValue = repeatXProp->value()->cssText() + " " + repeatYProp->value()->cssText();
+ result += "background-repeat: " + repeatValue + (repeatXProp->isImportant() ? " !important" : "") + "; ";
+ } else {
+ if (repeatXProp)
+ result += repeatXProp->cssText();
+ if (repeatYProp)
+ result += repeatYProp->cssText();
+ }
+
+ return result;
+}
+
+void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& ec)
+{
+ ec = 0;
+ // FIXME: Detect syntax errors and set ec.
+ parseDeclaration(text);
+}
+
+void CSSMutableStyleDeclaration::merge(const CSSMutableStyleDeclaration* other, bool argOverridesOnConflict)
+{
+ ASSERT(!m_iteratorCount);
+
+#if ENABLE(MUTATION_OBSERVERS)
+ StyleAttributeMutationScope mutationScope(this);
+#endif
+
+ unsigned size = other->m_properties.size();
+ for (unsigned n = 0; n < size; ++n) {
+ const CSSProperty& toMerge = other->m_properties[n];
+ CSSProperty* old = findPropertyWithId(toMerge.id());
+ if (old) {
+ if (!argOverridesOnConflict && old->value())
+ continue;
+ setPropertyInternal(toMerge, old);
+ } else
+ m_properties.append(toMerge);
+ }
+
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+
+ // FIXME: This probably should have a call to setNeedsStyleRecalc() if something changed. We may also wish to add
+ // a notifyChanged argument to this function to follow the model of other functions in this class.
+}
+
+void CSSMutableStyleDeclaration::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
+{
+ CSSStyleSheet* sheet = parentStyleSheet();
+ size_t size = m_properties.size();
+ for (size_t i = 0; i < size; ++i)
+ m_properties[i].value()->addSubresourceStyleURLs(urls, sheet);
+}
+
+// This is the list of properties we want to copy in the copyBlockProperties() function.
+// It is the list of CSS properties that apply specially to block-level elements.
+static const int blockProperties[] = {
+ CSSPropertyOrphans,
+ CSSPropertyOverflow, // This can be also be applied to replaced elements
+ CSSPropertyWebkitAspectRatio,
+ CSSPropertyWebkitColumnCount,
+ CSSPropertyWebkitColumnGap,
+ CSSPropertyWebkitColumnRuleColor,
+ CSSPropertyWebkitColumnRuleStyle,
+ CSSPropertyWebkitColumnRuleWidth,
+ CSSPropertyWebkitColumnBreakBefore,
+ CSSPropertyWebkitColumnBreakAfter,
+ CSSPropertyWebkitColumnBreakInside,
+ CSSPropertyWebkitColumnWidth,
+ CSSPropertyPageBreakAfter,
+ CSSPropertyPageBreakBefore,
+ CSSPropertyPageBreakInside,
+ CSSPropertyWebkitRegionBreakAfter,
+ CSSPropertyWebkitRegionBreakBefore,
+ CSSPropertyWebkitRegionBreakInside,
+ CSSPropertyTextAlign,
+ CSSPropertyTextIndent,
+ CSSPropertyWidows
+};
+
+const unsigned numBlockProperties = WTF_ARRAY_LENGTH(blockProperties);
+
+PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyBlockProperties() const
+{
+ return copyPropertiesInSet(blockProperties, numBlockProperties);
+}
+
+void CSSMutableStyleDeclaration::removeBlockProperties()
+{
+ removePropertiesInSet(blockProperties, numBlockProperties);
+}
+
+bool CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged)
+{
+ ASSERT(!m_iteratorCount);
+
+ if (m_properties.isEmpty())
+ return false;
+
+#if ENABLE(MUTATION_OBSERVERS)
+ StyleAttributeMutationScope mutationScope(this);
+#endif
+
+ // FIXME: This is always used with static sets and in that case constructing the hash repeatedly is pretty pointless.
+ HashSet<int> toRemove;
+ for (unsigned i = 0; i < length; ++i)
+ toRemove.add(set[i]);
+
+ Vector<CSSProperty, 4> newProperties;
+ newProperties.reserveInitialCapacity(m_properties.size());
+
+ unsigned size = m_properties.size();
+ for (unsigned n = 0; n < size; ++n) {
+ const CSSProperty& property = m_properties[n];
+ // Not quite sure if the isImportant test is needed but it matches the existing behavior.
+ if (!property.isImportant()) {
+ if (toRemove.contains(property.id()))
+ continue;
+ }
+ newProperties.append(property);
+ }
+
+ bool changed = newProperties.size() != m_properties.size();
+ m_properties = newProperties;
+
+ if (notifyChanged) {
+#if ENABLE(MUTATION_OBSERVERS)
+ mutationScope.enqueueMutationRecord();
+#endif
+ setNeedsStyleRecalc();
+ }
+
+ return changed;
+}
+
+PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable()
+{
+ return this;
+}
+
+PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copy() const
+{
+ return adoptRef(new CSSMutableStyleDeclaration(0, m_properties));
+}
+
+const CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID) const
+{
+ for (int n = m_properties.size() - 1 ; n >= 0; --n) {
+ if (propertyID == m_properties[n].m_id)
+ return &m_properties[n];
+ }
+ return 0;
+}
+
+CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID)
+{
+ for (int n = m_properties.size() - 1 ; n >= 0; --n) {
+ if (propertyID == m_properties[n].m_id)
+ return &m_properties[n];
+ }
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.h b/Source/WebCore/css/CSSMutableStyleDeclaration.h
new file mode 100644
index 000000000..54e08edb4
--- /dev/null
+++ b/Source/WebCore/css/CSSMutableStyleDeclaration.h
@@ -0,0 +1,223 @@
+/*
+ * (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 CSSMutableStyleDeclaration_h
+#define CSSMutableStyleDeclaration_h
+
+#include "CSSStyleDeclaration.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSProperty.h"
+#include "KURLHash.h"
+#include "PlatformString.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/Vector.h>
+
+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 CSSMutableStyleDeclaration : public CSSStyleDeclaration {
+public:
+ virtual ~CSSMutableStyleDeclaration();
+
+ static PassRefPtr<CSSMutableStyleDeclaration> create()
+ {
+ return adoptRef(new CSSMutableStyleDeclaration);
+ }
+ static PassRefPtr<CSSMutableStyleDeclaration> create(CSSRule* parentRule)
+ {
+ return adoptRef(new CSSMutableStyleDeclaration(parentRule));
+ }
+ static PassRefPtr<CSSMutableStyleDeclaration> create(CSSRule* parentRule, const CSSProperty* const* properties, int numProperties)
+ {
+ return adoptRef(new CSSMutableStyleDeclaration(parentRule, properties, numProperties));
+ }
+ static PassRefPtr<CSSMutableStyleDeclaration> create(const Vector<CSSProperty>& properties)
+ {
+ return adoptRef(new CSSMutableStyleDeclaration(0, properties));
+ }
+
+ // 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;
+
+ virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&);
+ virtual String removeProperty(int propertyID, ExceptionCode&);
+
+ 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 removeProperty(int propertyID) { removeProperty(propertyID, true, false); }
+
+ // The following parses an entire new style declaration.
+ void parseDeclaration(const String& styleDeclaration);
+
+ // Besides adding the properties, this also removes any existing properties with these IDs.
+ // It does no notification since it's called by the parser.
+ void addParsedProperties(const CSSProperty* const *, int numProperties);
+ // This does no change notifications since it's only called by createMarkup.
+ void addParsedProperty(const CSSProperty&);
+
+ PassRefPtr<CSSMutableStyleDeclaration> copyBlockProperties() const;
+ void removeBlockProperties();
+ void removePropertiesInSet(const int* set, unsigned length) { removePropertiesInSet(set, length, true); }
+
+ void merge(const CSSMutableStyleDeclaration*, bool argOverridesOnConflict = true);
+
+ void setStrictParsing(bool b) { m_strictParsing = b; }
+ bool useStrictParsing() const { return m_strictParsing; }
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>&);
+
+ bool propertiesEqual(const CSSMutableStyleDeclaration* o) const { return m_properties == o->m_properties; }
+
+protected:
+ CSSMutableStyleDeclaration(CSSRule* parentRule);
+ CSSMutableStyleDeclaration();
+
+ void setPropertyInternal(const CSSProperty&, CSSProperty* slot = 0);
+ String removeProperty(int propertyID, bool notifyChanged, bool returnText);
+
+private:
+ CSSMutableStyleDeclaration(CSSRule* parentRule, const Vector<CSSProperty>&);
+ CSSMutableStyleDeclaration(CSSRule* parentRule, const CSSProperty* const *, int numProperties);
+
+ virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable();
+
+ void setNeedsStyleRecalc();
+
+ String getShorthandValue(const int* properties, size_t) const;
+ String getCommonValue(const int* properties, size_t) const;
+ String getLayeredShorthandValue(const int* properties, size_t) const;
+ String get4Values(const int* properties) const;
+ String borderSpacingValue(const int properties[2]) const;
+ String fontValue() const;
+ bool appendFontLonghandValueIfExplicit(int propertyID, StringBuilder& result) const;
+
+ template<size_t size> String getShorthandValue(const int (&properties)[size]) const { return getShorthandValue(properties, size); }
+ template<size_t size> String getCommonValue(const int (&properties)[size]) const { return getCommonValue(properties, size); }
+ template<size_t size> String getLayeredShorthandValue(const int (&properties)[size]) const { return getLayeredShorthandValue(properties, size); }
+
+ bool setProperty(int propertyID, int value, bool important, bool notifyChanged);
+ bool setProperty(int propertyId, double value, CSSPrimitiveValue::UnitTypes, bool important, bool notifyChanged);
+ bool setProperty(int propertyID, const String& value, bool important, bool notifyChanged);
+ 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);
+
+ Vector<CSSProperty, 4> m_properties;
+
+ friend class CSSMutableStyleDeclarationConstIterator;
+};
+
+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/CSSNamespace.h b/Source/WebCore/css/CSSNamespace.h
new file mode 100644
index 000000000..92638f20e
--- /dev/null
+++ b/Source/WebCore/css/CSSNamespace.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * 1999 Waldo Bastian (bastian@kde.org)
+ * Copyright (C) 2004, 2006, 2010 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 CSSNamespace_h
+#define CSSNamespace_h
+
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+ struct CSSNamespace {
+ WTF_MAKE_NONCOPYABLE(CSSNamespace); WTF_MAKE_FAST_ALLOCATED;
+ public:
+ AtomicString prefix;
+ AtomicString uri;
+ OwnPtr<CSSNamespace> parent;
+
+ CSSNamespace(const AtomicString& prefix, const AtomicString& uri, PassOwnPtr<CSSNamespace> parent)
+ : prefix(prefix)
+ , uri(uri)
+ , parent(parent)
+ {
+ }
+
+ CSSNamespace* namespaceForPrefix(const AtomicString& prefix)
+ {
+ for (CSSNamespace* candidate = this; candidate; candidate = candidate->parent.get()) {
+ if (candidate->prefix == prefix)
+ return candidate;
+ }
+ return 0;
+ }
+ };
+
+} // namespace WebCore
+
+#endif // CSSNamespace_h
diff --git a/Source/WebCore/css/CSSOMUtils.cpp b/Source/WebCore/css/CSSOMUtils.cpp
new file mode 100644
index 000000000..33642db59
--- /dev/null
+++ b/Source/WebCore/css/CSSOMUtils.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2010 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 "CSSOMUtils.h"
+
+#include <wtf/HexNumber.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+static void appendCharacter(UChar32 c, StringBuilder& appendTo)
+{
+ if (U16_LENGTH(c) == 1)
+ appendTo.append(static_cast<UChar>(c));
+ else {
+ appendTo.append(U16_LEAD(c));
+ appendTo.append(U16_TRAIL(c));
+ }
+}
+
+void serializeCharacter(UChar32 c, StringBuilder& appendTo)
+{
+ appendTo.append('\\');
+ appendCharacter(c, appendTo);
+}
+
+void serializeCharacterAsCodePoint(UChar32 c, StringBuilder& appendTo)
+{
+ appendTo.append('\\');
+ appendUnsignedAsHex(c, appendTo, Lowercase);
+ appendTo.append(' ');
+}
+
+void serializeIdentifier(const String& identifier, String& appendTo)
+{
+ StringBuilder addend;
+ serializeIdentifier(identifier, addend);
+ appendTo.append(addend.toString());
+}
+
+void serializeIdentifier(const String& identifier, StringBuilder& appendTo)
+{
+ bool isFirst = true;
+ bool isSecond = false;
+ bool isFirstCharHyphen = false;
+ unsigned index = 0;
+ while (index < identifier.length()) {
+ UChar32 c = identifier.characterStartingAt(index);
+ index += U16_LENGTH(c);
+
+ if (c <= 0x1f || (0x30 <= c && c <= 0x39 && (isFirst || (isSecond && isFirstCharHyphen))))
+ serializeCharacterAsCodePoint(c, appendTo);
+ else if (c == 0x2d && isSecond && isFirstCharHyphen)
+ serializeCharacter(c, appendTo);
+ else if (0x80 <= c || c == 0x2d || c == 0x5f || (0x30 <= c && c <= 0x39) || (0x41 <= c && c <= 0x5a) || (0x61 <= c && c <= 0x7a))
+ appendCharacter(c, appendTo);
+ else
+ serializeCharacter(c, appendTo);
+
+ if (isFirst) {
+ isFirst = false;
+ isSecond = true;
+ isFirstCharHyphen = (c == 0x2d);
+ } else if (isSecond) {
+ isSecond = false;
+ }
+ }
+}
+
+void serializeString(const String& string, String& appendTo)
+{
+ StringBuilder addend;
+ serializeString(string, addend);
+ appendTo.append(addend.toString());
+}
+
+void serializeString(const String& string, StringBuilder& appendTo)
+{
+ appendTo.append('\"');
+
+ unsigned index = 0;
+ while (index < string.length()) {
+ UChar32 c = string.characterStartingAt(index);
+ index += U16_LENGTH(c);
+ if (c <= 0x1f)
+ serializeCharacterAsCodePoint(c, appendTo);
+ else if (c == 0x22 || c == 0x5c)
+ serializeCharacter(c, appendTo);
+ else
+ appendCharacter(c, appendTo);
+ }
+
+ appendTo.append('\"');
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSOMUtils.h b/Source/WebCore/css/CSSOMUtils.h
new file mode 100644
index 000000000..878669c37
--- /dev/null
+++ b/Source/WebCore/css/CSSOMUtils.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010 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 CSSOMUtils_h
+#define CSSOMUtils_h
+
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+// Utilities for CSSOM http://dev.w3.org/csswg/cssom/
+
+namespace WebCore {
+
+// Common serializing methods. See: http://dev.w3.org/csswg/cssom/#common-serializing-idioms
+void serializeCharacter(UChar32, StringBuilder& appendTo);
+void serializeCharacterAsCodePoint(UChar32, StringBuilder& appendTo);
+void serializeIdentifier(const String& identifier, String& appendTo);
+void serializeIdentifier(const String& identifier, StringBuilder& appendTo);
+void serializeString(const String&, String& appendTo);
+void serializeString(const String&, StringBuilder& appendTo);
+
+} // namespace WebCore
+
+#endif // CSSOMUtils_h
diff --git a/Source/WebCore/css/CSSPageRule.cpp b/Source/WebCore/css/CSSPageRule.cpp
new file mode 100644
index 000000000..8da1ec448
--- /dev/null
+++ b/Source/WebCore/css/CSSPageRule.cpp
@@ -0,0 +1,47 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 "CSSPageRule.h"
+
+#include "CSSMutableStyleDeclaration.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+CSSPageRule::CSSPageRule(CSSStyleSheet* parent, int sourceLine)
+ : CSSStyleRule(parent, sourceLine, CSSRule::PAGE_RULE)
+{
+}
+
+String CSSPageRule::pageSelectorText() const
+{
+ String text = "@page";
+ CSSSelector* selector = selectorList().first();
+ if (selector) {
+ String pageSpecification = selector->selectorText();
+ if (!pageSpecification.isEmpty() && pageSpecification != starAtom)
+ text += " " + pageSpecification;
+ }
+ return text;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSPageRule.h b/Source/WebCore/css/CSSPageRule.h
new file mode 100644
index 000000000..59e9dcf65
--- /dev/null
+++ b/Source/WebCore/css/CSSPageRule.h
@@ -0,0 +1,50 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 CSSPageRule_h
+#define CSSPageRule_h
+
+#include "CSSStyleRule.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSMutableStyleDeclaration;
+class CSSSelector;
+class CSSSelectorList;
+
+class CSSPageRule : public CSSStyleRule {
+public:
+ static PassRefPtr<CSSPageRule> create(CSSStyleSheet* parent, int sourceLine)
+ {
+ return adoptRef(new CSSPageRule(parent, sourceLine));
+ }
+
+ String pageSelectorText() const;
+
+private:
+ CSSPageRule(CSSStyleSheet* parent, int sourceLine);
+};
+
+} // namespace WebCore
+
+#endif // CSSPageRule_h
diff --git a/Source/WebCore/css/CSSPageRule.idl b/Source/WebCore/css/CSSPageRule.idl
new file mode 100644
index 000000000..989fd8d50
--- /dev/null
+++ b/Source/WebCore/css/CSSPageRule.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSPageRule : CSSRule {
+
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString selectorText;
+
+ readonly attribute CSSStyleDeclaration style;
+
+ };
+
+}
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp
new file mode 100644
index 000000000..7940b2774
--- /dev/null
+++ b/Source/WebCore/css/CSSParser.cpp
@@ -0,0 +1,8162 @@
+/*
+ * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 "CSSParser.h"
+
+#include "CSSAspectRatioValue.h"
+#include "CSSBorderImageValue.h"
+#include "CSSCanvasValue.h"
+#include "CSSCharsetRule.h"
+#include "CSSCrossfadeValue.h"
+#include "CSSCursorImageValue.h"
+#include "CSSFlexValue.h"
+#include "CSSFontFaceRule.h"
+#include "CSSFontFaceSrcValue.h"
+#include "CSSFunctionValue.h"
+#include "CSSGradientValue.h"
+#include "CSSImageValue.h"
+#include "CSSImportRule.h"
+#include "CSSInheritedValue.h"
+#include "CSSInitialValue.h"
+#include "CSSLineBoxContainValue.h"
+#include "CSSMediaRule.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPageRule.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSProperty.h"
+#include "CSSPropertyNames.h"
+#include "CSSPropertySourceData.h"
+#include "CSSReflectValue.h"
+#include "CSSRuleList.h"
+#include "CSSSelector.h"
+#include "CSSStyleRule.h"
+#include "CSSStyleSheet.h"
+#include "CSSTimingFunctionValue.h"
+#include "CSSUnicodeRangeValue.h"
+#include "CSSValueKeywords.h"
+#include "CSSValueList.h"
+#include "CSSValuePool.h"
+#include "CSSWrapShapes.h"
+#include "Counter.h"
+#include "Document.h"
+#include "FloatConversion.h"
+#include "FontFamilyValue.h"
+#include "FontFeatureValue.h"
+#include "FontValue.h"
+#include "HTMLParserIdioms.h"
+#include "HashTools.h"
+#include "MediaList.h"
+#include "MediaQueryExp.h"
+#include "Page.h"
+#include "Pair.h"
+#include "Rect.h"
+#include "RenderTheme.h"
+#include "ShadowValue.h"
+#if ENABLE(CSS_FILTERS)
+#include "WebKitCSSFilterValue.h"
+#endif
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include "WebKitCSSRegionRule.h"
+#include "WebKitCSSTransformValue.h"
+#if ENABLE(CSS_SHADERS)
+#include "WebKitCSSShaderValue.h"
+#endif
+#include <limits.h>
+#include <wtf/HexNumber.h>
+#include <wtf/dtoa.h>
+#include <wtf/text/StringBuffer.h>
+#include <wtf/text/StringBuilder.h>
+
+#if ENABLE(DASHBOARD_SUPPORT)
+#include "DashboardRegion.h"
+#endif
+
+#define YYDEBUG 0
+
+#if YYDEBUG > 0
+extern int cssyydebug;
+#endif
+
+extern int cssyyparse(void* parser);
+
+using namespace std;
+using namespace WTF;
+
+namespace {
+
+enum PropertyType {
+ PropertyExplicit,
+ PropertyImplicit
+};
+
+class ImplicitScope {
+ WTF_MAKE_NONCOPYABLE(ImplicitScope);
+public:
+ ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType)
+ : m_parser(parser)
+ {
+ m_parser->m_implicitShorthand = propertyType == PropertyImplicit;
+ }
+
+ ~ImplicitScope()
+ {
+ m_parser->m_implicitShorthand = false;
+ }
+
+private:
+ WebCore::CSSParser* m_parser;
+};
+
+} // namespace
+
+namespace WebCore {
+
+static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
+static const double MAX_SCALE = 1000000;
+
+static bool equal(const CSSParserString& a, const char* b)
+{
+ for (int i = 0; i < a.length; ++i) {
+ if (!b[i])
+ return false;
+ if (a.characters[i] != b[i])
+ return false;
+ }
+ return !b[a.length];
+}
+
+static bool equalIgnoringCase(const CSSParserString& a, const char* b)
+{
+ for (int i = 0; i < a.length; ++i) {
+ if (!b[i])
+ return false;
+ ASSERT(!isASCIIUpper(b[i]));
+ if (toASCIILower(a.characters[i]) != b[i])
+ return false;
+ }
+ return !b[a.length];
+}
+
+static bool hasPrefix(const char* string, unsigned length, const char* prefix)
+{
+ for (unsigned i = 0; i < length; ++i) {
+ if (!prefix[i])
+ return true;
+ if (string[i] != prefix[i])
+ return false;
+ }
+ return false;
+}
+
+inline void CSSParser::ensureCSSValuePool()
+{
+ if (!m_cssValuePool)
+ m_cssValuePool = CSSValuePool::create();
+}
+
+// FIXME: Can m_parsedProperties just be a Vector?
+
+CSSParser::CSSParser(bool strictParsing)
+ : m_strict(strictParsing)
+ , m_important(false)
+ , m_id(0)
+ , m_styleSheet(0)
+ , m_parsedProperties(static_cast<CSSProperty**>(fastMalloc(32 * sizeof(CSSProperty*))))
+ , m_numParsedProperties(0)
+ , m_maxParsedProperties(32)
+ , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
+ , m_inParseShorthand(0)
+ , m_currentShorthand(0)
+ , m_implicitShorthand(false)
+ , m_hasFontFaceOnlyValues(false)
+ , m_hadSyntacticallyValidCSSRule(false)
+ , m_defaultNamespace(starAtom)
+ , m_inStyleRuleOrDeclaration(false)
+ , m_selectorListRange(0, 0)
+ , m_ruleBodyRange(0, 0)
+ , m_propertyRange(UINT_MAX, UINT_MAX)
+ , m_ruleRangeMap(0)
+ , m_currentRuleData(0)
+ , yy_start(1)
+ , m_lineNumber(0)
+ , m_lastSelectorLineNumber(0)
+ , m_allowImportRules(true)
+ , m_allowNamespaceDeclarations(true)
+{
+#if YYDEBUG > 0
+ cssyydebug = 1;
+#endif
+ CSSPropertySourceData::init();
+}
+
+CSSParser::~CSSParser()
+{
+ clearProperties();
+ fastFree(m_parsedProperties);
+
+ fastDeleteAllValues(m_floatingSelectors);
+ deleteAllValues(m_floatingSelectorVectors);
+ deleteAllValues(m_floatingValueLists);
+ deleteAllValues(m_floatingFunctions);
+}
+
+void CSSParserString::lower()
+{
+ // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
+ // that can potentially change the length of the string rather than the character
+ // by character kind. If we don't need Unicode lowercasing, it would be good to
+ // simplify this function.
+
+ if (charactersAreAllASCII(characters, length)) {
+ // Fast case for all-ASCII.
+ for (int i = 0; i < length; i++)
+ characters[i] = toASCIILower(characters[i]);
+ } else {
+ for (int i = 0; i < length; i++)
+ characters[i] = Unicode::toLower(characters[i]);
+ }
+}
+
+void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix)
+{
+ int length = string.length() + strlen(prefix) + strlen(suffix) + 2;
+
+ m_data = adoptArrayPtr(new UChar[length]);
+ for (unsigned i = 0; i < strlen(prefix); i++)
+ m_data[i] = prefix[i];
+
+ memcpy(m_data.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_data[length - 1] = 0;
+ m_data[length - 2] = 0;
+
+ yy_hold_char = 0;
+ yyleng = 0;
+ yytext = m_data.get();
+ yy_c_buf_p = yytext;
+ yy_hold_char = *yy_c_buf_p;
+ resetRuleBodyMarks();
+}
+
+void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
+{
+ setStyleSheet(sheet);
+ m_defaultNamespace = starAtom; // Reset the default namespace.
+ m_ruleRangeMap = ruleRangeMap;
+ if (ruleRangeMap) {
+ m_currentRuleData = CSSRuleSourceData::create();
+ m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
+ }
+
+ m_lineNumber = startLineNumber;
+ setupParser("", string, "");
+ cssyyparse(this);
+ m_ruleRangeMap = 0;
+ m_currentRuleData = 0;
+ m_rule = 0;
+}
+
+PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
+{
+ setStyleSheet(sheet);
+ m_allowNamespaceDeclarations = false;
+ setupParser("@-webkit-rule{", string, "} ");
+ cssyyparse(this);
+ return m_rule.release();
+}
+
+PassRefPtr<WebKitCSSKeyframeRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
+{
+ setStyleSheet(sheet);
+ setupParser("@-webkit-keyframe-rule{ ", string, "} ");
+ cssyyparse(this);
+ return m_keyframe.release();
+}
+
+static inline bool isColorPropertyID(int propertyId)
+{
+ switch (propertyId) {
+ case CSSPropertyColor:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextStrokeColor:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool parseColorValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict, CSSStyleSheet* contextStyleSheet = 0)
+{
+ if (!string.length())
+ return false;
+ if (!isColorPropertyID(propertyId))
+ return false;
+ CSSParserString cssString;
+ cssString.characters = const_cast<UChar*>(string.characters());
+ cssString.length = string.length();
+ int valueID = cssValueKeywordID(cssString);
+ bool validPrimitive = false;
+ if (valueID == CSSValueWebkitText)
+ validPrimitive = true;
+ else if (valueID == CSSValueCurrentcolor)
+ validPrimitive = true;
+ else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
+ || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) {
+ validPrimitive = true;
+ }
+
+ CSSStyleSheet* styleSheet = contextStyleSheet ? contextStyleSheet : declaration->parentStyleSheet();
+ if (!styleSheet)
+ return false;
+ Document* document = styleSheet->findDocument();
+ if (!document)
+ return false;
+ if (validPrimitive) {
+ CSSProperty property(propertyId, document->cssValuePool()->createIdentifierValue(valueID), important);
+ declaration->addParsedProperty(property);
+ return true;
+ }
+ RGBA32 color;
+ if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
+ return false;
+ CSSProperty property(propertyId, document->cssValuePool()->createColorValue(color), important);
+ declaration->addParsedProperty(property);
+ return true;
+}
+
+static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers)
+{
+ switch (propertyId) {
+ case CSSPropertyFontSize:
+ case CSSPropertyHeight:
+ case CSSPropertyWidth:
+ case CSSPropertyMinHeight:
+ case CSSPropertyMinWidth:
+ case CSSPropertyPaddingBottom:
+ case CSSPropertyPaddingLeft:
+ case CSSPropertyPaddingRight:
+ case CSSPropertyPaddingTop:
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyWebkitWrapMargin:
+ case CSSPropertyWebkitWrapPadding:
+ acceptsNegativeNumbers = false;
+ return true;
+ case CSSPropertyBottom:
+ case CSSPropertyLeft:
+ case CSSPropertyMarginBottom:
+ case CSSPropertyMarginLeft:
+ case CSSPropertyMarginRight:
+ case CSSPropertyMarginTop:
+ case CSSPropertyRight:
+ case CSSPropertyTextIndent:
+ case CSSPropertyTop:
+ case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginStart:
+ acceptsNegativeNumbers = true;
+ return true;
+ default:
+ return false;
+ }
+}
+
+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))
+ return false;
+
+ 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;
+ }
+
+ // 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) {
+ if (number && strict)
+ return false;
+ unit = CSSPrimitiveValue::CSS_PX;
+ }
+ if (number < 0 && !acceptsNegativeNumbers)
+ return false;
+
+ CSSStyleSheet* styleSheet = contextStyleSheet ? contextStyleSheet : declaration->parentStyleSheet();
+ if (!styleSheet)
+ return false;
+ Document* document = styleSheet->findDocument();
+ if (!document)
+ return false;
+ CSSProperty property(propertyId, document->cssValuePool()->createValue(number, unit), important);
+ declaration->addParsedProperty(property);
+ return true;
+}
+
+bool CSSParser::parseMappedAttributeValue(CSSMappedAttributeDeclaration* declaration, StyledElement* element, int propertyId, const String& value)
+{
+ ASSERT(declaration);
+ ASSERT(element);
+ ASSERT(element->document());
+ CSSStyleSheet* elementSheet = element->document()->elementSheet();
+ if (parseSimpleLengthValue(declaration, propertyId, value, false, false, elementSheet))
+ return true;
+ if (parseColorValue(declaration, propertyId, value, false, false, elementSheet))
+ return true;
+ CSSParser parser(false);
+ return parser.parseValue(declaration, propertyId, value, false, elementSheet);
+}
+
+bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict)
+{
+ if (parseSimpleLengthValue(declaration, propertyId, string, important, strict))
+ return true;
+ if (parseColorValue(declaration, propertyId, string, important, strict))
+ return true;
+ CSSParser parser(strict);
+ return parser.parseValue(declaration, propertyId, string, important);
+}
+
+bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, CSSStyleSheet* contextStyleSheet)
+{
+ if (contextStyleSheet)
+ setStyleSheet(contextStyleSheet);
+ else
+ setStyleSheet(declaration->parentStyleSheet());
+
+ setupParser("@-webkit-value{", string, "} ");
+
+ m_id = propertyId;
+ m_important = important;
+
+ cssyyparse(this);
+
+ m_rule = 0;
+
+ bool ok = false;
+ if (m_hasFontFaceOnlyValues)
+ deleteFontFaceOnlyValues();
+ if (m_numParsedProperties) {
+ ok = true;
+ declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
+ clearProperties();
+ }
+
+ return ok;
+}
+
+// The color will only be changed when string contains a valid CSS color, so callers
+// can set it to a default color and ignore the boolean result.
+bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
+{
+ // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
+ if (fastParseColor(color, string, strict))
+ return true;
+
+ CSSParser parser(true);
+
+ // In case the fast-path parser didn't understand the color, try the full parser.
+ if (!parser.parseColor(string))
+ return false;
+
+ CSSValue* value = parser.m_parsedProperties[0]->value();
+ if (!value->isPrimitiveValue())
+ return false;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_RGBCOLOR)
+ return false;
+
+ color = primitiveValue->getRGBA32Value();
+ return true;
+}
+
+bool CSSParser::parseColor(const String& string)
+{
+ // This function may be called without a stylesheet set on the parser, so we need to
+ // make sure that we have a CSSValuePool or we'll crash below cssyyparse().
+ ensureCSSValuePool();
+
+ setupParser("@-webkit-decls{color:", string, "} ");
+ cssyyparse(this);
+ m_rule = 0;
+
+ return (m_numParsedProperties && m_parsedProperties[0]->m_id == CSSPropertyColor);
+}
+
+bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
+{
+ if (!document || !document->page())
+ return false;
+
+ CSSParserString cssColor;
+ cssColor.characters = const_cast<UChar*>(string.characters());
+ cssColor.length = string.length();
+ int id = cssValueKeywordID(cssColor);
+ if (id <= 0)
+ return false;
+
+ color = document->page()->theme()->systemColor(id).rgb();
+ return true;
+}
+
+void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
+{
+ RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
+
+ setStyleSheet(dummyStyleSheet.get());
+ m_selectorListForParseSelector = &selectorList;
+
+ setupParser("@-webkit-selector{", string, "}");
+
+ cssyyparse(this);
+
+ m_selectorListForParseSelector = 0;
+
+ // The style sheet will be deleted right away, so it won't outlive the document.
+ ASSERT(dummyStyleSheet->hasOneRef());
+}
+
+bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData, CSSStyleSheet* contextStyleSheet)
+{
+ // Length of the "@-webkit-decls{" prefix.
+ static const unsigned prefixLength = 15;
+
+ if (contextStyleSheet)
+ setStyleSheet(contextStyleSheet);
+ else
+ setStyleSheet(declaration->parentStyleSheet());
+ if (styleSourceData) {
+ m_currentRuleData = CSSRuleSourceData::create();
+ m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
+ m_inStyleRuleOrDeclaration = true;
+ }
+
+ setupParser("@-webkit-decls{", string, "} ");
+ cssyyparse(this);
+ m_rule = 0;
+
+ bool ok = false;
+ if (m_hasFontFaceOnlyValues)
+ deleteFontFaceOnlyValues();
+ if (m_numParsedProperties) {
+ ok = true;
+ declaration->addParsedProperties(m_parsedProperties, m_numParsedProperties);
+ clearProperties();
+ }
+
+ if (m_currentRuleData) {
+ m_currentRuleData->styleSourceData->styleBodyRange.start = 0;
+ m_currentRuleData->styleSourceData->styleBodyRange.end = string.length();
+ for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) {
+ (*it).range.start -= prefixLength;
+ (*it).range.end -= prefixLength;
+ }
+ }
+
+ if (styleSourceData) {
+ *styleSourceData = m_currentRuleData->styleSourceData.release();
+ m_currentRuleData = 0;
+ m_inStyleRuleOrDeclaration = false;
+ }
+ return ok;
+}
+
+bool CSSParser::parseMediaQuery(MediaList* queries, const String& string)
+{
+ if (string.isEmpty())
+ return true;
+
+ ASSERT(!m_mediaQuery);
+
+ // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
+ // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
+ setupParser("@-webkit-mediaquery ", string, "} ");
+ cssyyparse(this);
+
+ bool ok = false;
+ if (m_mediaQuery) {
+ ok = true;
+ queries->appendMediaQuery(m_mediaQuery.release());
+ }
+
+ return ok;
+}
+
+void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
+{
+ OwnPtr<CSSProperty> prop(adoptPtr(new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand || implicit)));
+ if (m_numParsedProperties >= m_maxParsedProperties) {
+ if (m_numParsedProperties > (UINT_MAX / sizeof(CSSProperty*)) - 32)
+ CRASH(); // Avoid inconsistencies with rollbackLastProperties.
+ m_maxParsedProperties += 32;
+ m_parsedProperties = static_cast<CSSProperty**>(fastRealloc(m_parsedProperties,
+ m_maxParsedProperties * sizeof(CSSProperty*)));
+ }
+ m_parsedProperties[m_numParsedProperties++] = prop.leakPtr();
+}
+
+void CSSParser::rollbackLastProperties(int num)
+{
+ ASSERT(num >= 0);
+ ASSERT(m_numParsedProperties >= static_cast<unsigned>(num));
+
+ for (int i = 0; i < num; ++i)
+ delete m_parsedProperties[--m_numParsedProperties];
+}
+
+void CSSParser::clearProperties()
+{
+ for (unsigned i = 0; i < m_numParsedProperties; i++)
+ delete m_parsedProperties[i];
+ m_numParsedProperties = 0;
+ m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
+ m_hasFontFaceOnlyValues = false;
+}
+
+void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet)
+{
+ m_styleSheet = styleSheet;
+ Document* document = findDocument();
+ m_cssValuePool = document ? document->cssValuePool() : CSSValuePool::create();
+}
+
+Document* CSSParser::findDocument() const
+{
+ if (!m_styleSheet)
+ return 0;
+ return m_styleSheet->findDocument();
+}
+
+bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, bool strict)
+{
+ bool b = false;
+ switch (value->unit) {
+ case CSSPrimitiveValue::CSS_NUMBER:
+ b = (unitflags & FNumber);
+ if (!b && ((unitflags & (FLength | FAngle | FTime)) && (value->fValue == 0 || !strict))) {
+ value->unit = (unitflags & FLength) ? CSSPrimitiveValue::CSS_PX :
+ ((unitflags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
+ b = true;
+ }
+ if (!b && (unitflags & FInteger) && value->isInt)
+ b = true;
+ break;
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ b = (unitflags & FPercent);
+ break;
+ case CSSParserValue::Q_EMS:
+ case CSSPrimitiveValue::CSS_EMS:
+ case CSSPrimitiveValue::CSS_REMS:
+ 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:
+ b = (unitflags & FLength);
+ break;
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_S:
+ b = (unitflags & FTime);
+ break;
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_RAD:
+ case CSSPrimitiveValue::CSS_GRAD:
+ case CSSPrimitiveValue::CSS_TURN:
+ b = (unitflags & FAngle);
+ break;
+ case CSSPrimitiveValue::CSS_HZ:
+ case CSSPrimitiveValue::CSS_KHZ:
+ case CSSPrimitiveValue::CSS_DIMENSION:
+ default:
+ break;
+ }
+ if (b && unitflags & FNonNeg && value->fValue < 0)
+ b = false;
+ return b;
+}
+
+inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value)
+{
+ 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));
+}
+
+inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value)
+{
+ ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT);
+ return cssValuePool()->createValue(value->string, CSSPrimitiveValue::CSS_STRING);
+}
+
+static int unitFromString(CSSParserValue* value)
+{
+ if (value->unit != CSSPrimitiveValue::CSS_IDENT || value->id)
+ return 0;
+
+ if (equal(value->string, "em"))
+ return CSSPrimitiveValue::CSS_EMS;
+ if (equal(value->string, "rem"))
+ return CSSPrimitiveValue::CSS_REMS;
+ if (equal(value->string, "ex"))
+ return CSSPrimitiveValue::CSS_EXS;
+ if (equal(value->string, "px"))
+ return CSSPrimitiveValue::CSS_PX;
+ if (equal(value->string, "cm"))
+ return CSSPrimitiveValue::CSS_CM;
+ if (equal(value->string, "mm"))
+ return CSSPrimitiveValue::CSS_MM;
+ if (equal(value->string, "in"))
+ return CSSPrimitiveValue::CSS_IN;
+ if (equal(value->string, "pt"))
+ return CSSPrimitiveValue::CSS_PT;
+ if (equal(value->string, "pc"))
+ return CSSPrimitiveValue::CSS_PC;
+ if (equal(value->string, "deg"))
+ return CSSPrimitiveValue::CSS_DEG;
+ if (equal(value->string, "rad"))
+ return CSSPrimitiveValue::CSS_RAD;
+ if (equal(value->string, "grad"))
+ return CSSPrimitiveValue::CSS_GRAD;
+ if (equal(value->string, "turn"))
+ return CSSPrimitiveValue::CSS_TURN;
+ if (equal(value->string, "ms"))
+ return CSSPrimitiveValue::CSS_MS;
+ if (equal(value->string, "s"))
+ return CSSPrimitiveValue::CSS_S;
+ if (equal(value->string, "Hz"))
+ return CSSPrimitiveValue::CSS_HZ;
+ if (equal(value->string, "kHz"))
+ return CSSPrimitiveValue::CSS_KHZ;
+
+ return 0;
+}
+
+void CSSParser::checkForOrphanedUnits()
+{
+ if (m_strict || inShorthand())
+ return;
+
+ // The purpose of this code is to implement the WinIE quirk that allows unit types to be separated from their numeric values
+ // by whitespace, so e.g., width: 20 px instead of width:20px. This is invalid CSS, so we don't do this in strict mode.
+ CSSParserValue* numericVal = 0;
+ unsigned size = m_valueList->size();
+ for (unsigned i = 0; i < size; i++) {
+ CSSParserValue* value = m_valueList->valueAt(i);
+
+ if (numericVal) {
+ // Change the unit type of the numeric val to match.
+ int unit = unitFromString(value);
+ if (unit) {
+ numericVal->unit = unit;
+ numericVal = 0;
+
+ // Now delete the bogus unit value.
+ m_valueList->deleteValueAt(i);
+ i--; // We're safe even though |i| is unsigned, since we only hit this code if we had a previous numeric value (so |i| is always > 0 here).
+ size--;
+ continue;
+ }
+ }
+
+ numericVal = (value->unit == CSSPrimitiveValue::CSS_NUMBER) ? value : 0;
+ }
+}
+
+inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int id, CSSParserValue* value)
+{
+ if (id)
+ return cssValuePool()->createIdentifierValue(id);
+ if (value->unit == CSSPrimitiveValue::CSS_STRING)
+ return createPrimitiveStringValue(value);
+ if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
+ return createPrimitiveNumericValue(value);
+ if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS)
+ return createPrimitiveNumericValue(value);
+ if (value->unit >= CSSParserValue::Q_EMS)
+ return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
+ return 0;
+}
+
+bool CSSParser::parseValue(int propId, bool important)
+{
+ if (!m_valueList)
+ return false;
+
+ CSSParserValue* value = m_valueList->current();
+
+ if (!value)
+ return false;
+
+ int id = value->id;
+
+ // In quirks mode, we will look for units that have been incorrectly separated from the number they belong to
+ // by a space. We go ahead and associate the unit with the number even though it is invalid CSS.
+ checkForOrphanedUnits();
+
+ int num = inShorthand() ? 1 : m_valueList->size();
+
+ if (id == CSSValueInherit) {
+ if (num != 1)
+ return false;
+ addProperty(propId, cssValuePool()->createInheritedValue(), important);
+ return true;
+ }
+ else if (id == CSSValueInitial) {
+ if (num != 1)
+ return false;
+ addProperty(propId, cssValuePool()->createExplicitInitialValue(), important);
+ return true;
+ }
+
+ bool validPrimitive = false;
+ RefPtr<CSSValue> parsedValue;
+
+ switch (static_cast<CSSPropertyID>(propId)) {
+ /* The comment to the left defines all valid value of this properties as defined
+ * in CSS 2, Appendix F. Property index
+ */
+
+ /* All the CSS properties are not supported by the renderer at the moment.
+ * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined
+ * (see parseAuralValues). As we don't support them at all this seems reasonable.
+ */
+
+ case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
+ return parseSize(propId, important);
+
+ case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit
+ if (id)
+ validPrimitive = true;
+ else
+ return parseQuotes(propId, important);
+ break;
+ case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | plaintext | inherit
+ if (id == CSSValueNormal
+ || id == CSSValueEmbed
+ || id == CSSValueBidiOverride
+ || id == CSSValueWebkitIsolate
+ || id == CSSValueWebkitPlaintext)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyPosition: // static | relative | absolute | fixed | inherit
+ if (id == CSSValueStatic ||
+ id == CSSValueRelative ||
+ id == CSSValueAbsolute ||
+ id == CSSValueFixed)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
+ case CSSPropertyPageBreakBefore:
+ case CSSPropertyWebkitColumnBreakAfter:
+ case CSSPropertyWebkitColumnBreakBefore:
+ case CSSPropertyWebkitRegionBreakAfter:
+ case CSSPropertyWebkitRegionBreakBefore:
+ if (id == CSSValueAuto ||
+ id == CSSValueAlways ||
+ id == CSSValueAvoid ||
+ id == CSSValueLeft ||
+ id == CSSValueRight)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyPageBreakInside: // avoid | auto | inherit
+ case CSSPropertyWebkitColumnBreakInside:
+ case CSSPropertyWebkitRegionBreakInside:
+ if (id == CSSValueAuto || id == CSSValueAvoid)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyEmptyCells: // show | hide | inherit
+ if (id == CSSValueShow ||
+ id == CSSValueHide)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyContent: // [ <string> | <uri> | <counter> | attr(X) | open-quote |
+ // close-quote | no-open-quote | no-close-quote ]+ | inherit
+ return parseContent(propId, important);
+
+ case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
+ if (id == CSSValueNormal ||
+ id == CSSValuePre ||
+ id == CSSValuePreWrap ||
+ id == CSSValuePreLine ||
+ id == CSSValueNowrap)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyClip: // <shape> | auto | inherit
+ if (id == CSSValueAuto)
+ validPrimitive = true;
+ else if (value->unit == CSSParserValue::Function)
+ return parseShape(propId, important);
+ break;
+
+ /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
+ * correctly and allows optimization in WebCore::applyRule(..)
+ */
+ case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
+ if (id == CSSValueLeft || id == CSSValueRight ||
+ id == CSSValueTop || id == CSSValueBottom)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyBorderCollapse: // collapse | separate | inherit
+ if (id == CSSValueCollapse || id == CSSValueSeparate)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyVisibility: // visible | hidden | collapse | inherit
+ if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueCollapse)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyOverflow: {
+ ShorthandScope scope(this, propId);
+ if (num != 1 || !parseValue(CSSPropertyOverflowX, important))
+ return false;
+ CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
+ addProperty(CSSPropertyOverflowY, value, important);
+ return true;
+ }
+ case CSSPropertyOverflowX:
+ case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit
+ if (id == CSSValueVisible || id == CSSValueHidden || id == CSSValueScroll || id == CSSValueAuto ||
+ id == CSSValueOverlay || id == CSSValueWebkitMarquee)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyListStylePosition: // inside | outside | inherit
+ if (id == CSSValueInside || id == CSSValueOutside)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyListStyleType:
+ // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
+ // for the list of supported list-style-types.
+ if ((id >= CSSValueDisc && id <= CSSValueKatakanaIroha) || id == CSSValueNone)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyDisplay:
+ // inline | block | list-item | run-in | inline-block | table |
+ // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
+ // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
+ // -webkit-flexbox | -webkit-inline-flexbox | -webkit-grid | -webkit-inline-grid
+ if ((id >= CSSValueInline && id <= CSSValueWebkitInlineFlexbox) || id == CSSValueNone)
+ validPrimitive = true;
+#if ENABLE(CSS_GRID_LAYOUT)
+ if (id == CSSValueWebkitGrid || id == CSSValueWebkitInlineGrid)
+ validPrimitive = true;
+#endif
+ break;
+
+ case CSSPropertyDirection: // ltr | rtl | inherit
+ if (id == CSSValueLtr || id == CSSValueRtl)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
+ if ((id >= CSSValueCapitalize && id <= CSSValueLowercase) || id == CSSValueNone)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyFloat: // left | right | none | positioned | center (for buggy CSS, maps to none)
+ if (id == CSSValueLeft || id == CSSValueRight
+ || id == CSSValueNone || id == CSSValueCenter || id == CSSValueWebkitPositioned)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyClear: // none | left | right | both | inherit
+ if (id == CSSValueNone || id == CSSValueLeft ||
+ id == CSSValueRight|| id == CSSValueBoth)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyTextAlign:
+ // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent |
+ // start | end | <string> | inherit
+ if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd
+ || value->unit == CSSPrimitiveValue::CSS_STRING)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
+ if (id == CSSValueAuto || id == CSSValueNone || (id >= CSSValueInset && id <= CSSValueDouble))
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyBorderTopStyle: //// <border-style> | inherit
+ case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
+ case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitColumnRuleStyle:
+ if (id >= CSSValueNone && id <= CSSValueDouble)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyFontWeight: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
+ return parseFontWeight(important);
+
+ case CSSPropertyBorderSpacing: {
+ const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing,
+ CSSPropertyWebkitBorderVerticalSpacing };
+ if (num == 1) {
+ ShorthandScope scope(this, CSSPropertyBorderSpacing);
+ if (!parseValue(properties[0], important))
+ return false;
+ CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
+ addProperty(properties[1], value, important);
+ return true;
+ }
+ else if (num == 2) {
+ ShorthandScope scope(this, CSSPropertyBorderSpacing);
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
+ return false;
+ return true;
+ }
+ return false;
+ }
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
+ break;
+ case CSSPropertyOutlineColor: // <color> | invert | inherit
+ // Outline color has "invert" as additional keyword.
+ // Also, we want to allow the special focus color even in strict parsing mode.
+ if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
+ validPrimitive = true;
+ break;
+ }
+ /* nobreak */
+ case CSSPropertyBackgroundColor: // <color> | inherit
+ case CSSPropertyBorderTopColor: // <color> | inherit
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyColor: // <color> | inherit
+ case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextStrokeColor:
+ if (id == CSSValueWebkitText)
+ validPrimitive = true; // Always allow this, even when strict parsing is on,
+ // since we use this in our UA sheets.
+ else if (id == CSSValueCurrentcolor)
+ validPrimitive = true;
+ else if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu ||
+ (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
+ validPrimitive = true;
+ } else {
+ parsedValue = parseColor();
+ if (parsedValue)
+ m_valueList->next();
+ }
+ break;
+
+ case CSSPropertyCursor: {
+ // [<uri>,]* [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
+ // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
+ // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
+ // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in
+ // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit
+ RefPtr<CSSValueList> list;
+ while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
+ if (!list)
+ list = CSSValueList::createCommaSeparated();
+ String uri = value->string;
+ Vector<int> coords;
+ value = m_valueList->next();
+ while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
+ coords.append(int(value->fValue));
+ value = m_valueList->next();
+ }
+ IntPoint hotSpot(-1, -1);
+ int nrcoords = coords.size();
+ if (nrcoords > 0 && nrcoords != 2)
+ return false;
+ if (nrcoords == 2)
+ hotSpot = IntPoint(coords[0], coords[1]);
+
+ if (!uri.isNull() && m_styleSheet) {
+ // FIXME: The completeURL call should be done when using the CSSCursorImageValue,
+ // not when creating it.
+ list->append(CSSCursorImageValue::create(m_styleSheet->completeURL(uri), hotSpot));
+ }
+
+ if ((m_strict && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
+ return false;
+ value = m_valueList->next(); // comma
+ }
+ if (list) {
+ if (!value) { // no value after url list (MSIE 5 compatibility)
+ if (list->length() != 1)
+ return false;
+ } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/
+ list->append(cssValuePool()->createIdentifierValue(CSSValuePointer));
+ else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone))
+ list->append(cssValuePool()->createIdentifierValue(value->id));
+ m_valueList->next();
+ parsedValue = list.release();
+ break;
+ }
+ id = value->id;
+ if (!m_strict && value->id == CSSValueHand) { // MSIE 5 compatibility :/
+ id = CSSValuePointer;
+ validPrimitive = true;
+ } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)
+ validPrimitive = true;
+ break;
+ }
+
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ case CSSPropertyWebkitMaskAttachment:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskComposite:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskOrigin:
+ case CSSPropertyWebkitMaskPosition:
+ case CSSPropertyWebkitMaskPositionX:
+ case CSSPropertyWebkitMaskPositionY:
+ case CSSPropertyWebkitMaskSize:
+ case CSSPropertyWebkitMaskRepeat:
+ case CSSPropertyWebkitMaskRepeatX:
+ case CSSPropertyWebkitMaskRepeatY: {
+ RefPtr<CSSValue> val1;
+ RefPtr<CSSValue> val2;
+ int propId1, propId2;
+ bool result = false;
+ if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
+ OwnPtr<ShorthandScope> shorthandScope;
+ if (propId == CSSPropertyBackgroundPosition ||
+ propId == CSSPropertyBackgroundRepeat ||
+ propId == CSSPropertyWebkitMaskPosition ||
+ propId == CSSPropertyWebkitMaskRepeat) {
+ shorthandScope = adoptPtr(new ShorthandScope(this, propId));
+ }
+ addProperty(propId1, val1.release(), important);
+ if (val2)
+ addProperty(propId2, val2.release(), important);
+ result = true;
+ }
+ m_implicitShorthand = false;
+ return result;
+ }
+ case CSSPropertyListStyleImage: // <uri> | none | inherit
+ case CSSPropertyBorderImageSource:
+ case CSSPropertyWebkitMaskBoxImageSource:
+ if (id == CSSValueNone) {
+ parsedValue = CSSImageValue::create();
+ m_valueList->next();
+ } else if (value->unit == CSSPrimitiveValue::CSS_URI) {
+ if (m_styleSheet) {
+ // FIXME: The completeURL call should be done when using the CSSImageValue,
+ // not when creating it.
+ parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
+ m_valueList->next();
+ }
+ } else if (isGeneratedImageValue(value)) {
+ if (parseGeneratedImage(m_valueList.get(), parsedValue))
+ m_valueList->next();
+ else
+ return false;
+ }
+ break;
+
+ case CSSPropertyWebkitTextStrokeWidth:
+ case CSSPropertyOutlineWidth: // <border-width> | inherit
+ case CSSPropertyBorderTopWidth: //// <border-width> | inherit
+ case CSSPropertyBorderRightWidth: // Which is defined as
+ case CSSPropertyBorderBottomWidth: // thin | medium | thick | <length>
+ case CSSPropertyBorderLeftWidth:
+ case CSSPropertyWebkitBorderStartWidth:
+ case CSSPropertyWebkitBorderEndWidth:
+ case CSSPropertyWebkitBorderBeforeWidth:
+ case CSSPropertyWebkitBorderAfterWidth:
+ case CSSPropertyWebkitColumnRuleWidth:
+ if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
+ break;
+
+ case CSSPropertyLetterSpacing: // normal | <length> | inherit
+ case CSSPropertyWordSpacing: // normal | <length> | inherit
+ if (id == CSSValueNormal)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FLength, m_strict);
+ break;
+
+ case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
+ if (id == CSSValueNormal || id == CSSValueBreakAll || id == CSSValueBreakWord)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWordWrap: // normal | break-word
+ if (id == CSSValueNormal || id == CSSValueBreakWord)
+ validPrimitive = true;
+ break;
+ case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
+ if (id == CSSValueNone || id == CSSValueNormal || id == CSSValueSpellOut || id == CSSValueDigits
+ || id == CSSValueLiteralPunctuation || id == CSSValueNoPunctuation)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyTextIndent: // <length> | <percentage> | inherit
+ validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
+ break;
+
+ case CSSPropertyPaddingTop: //// <padding-width> | inherit
+ case CSSPropertyPaddingRight: // Which is defined as
+ case CSSPropertyPaddingBottom: // <length> | <percentage>
+ case CSSPropertyPaddingLeft: ////
+ case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitPaddingAfter:
+ validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
+ break;
+
+ case CSSPropertyMaxHeight: // <length> | <percentage> | none | inherit
+ case CSSPropertyMaxWidth: // <length> | <percentage> | none | inherit
+ case CSSPropertyWebkitMaxLogicalWidth:
+ case CSSPropertyWebkitMaxLogicalHeight:
+ if (id == CSSValueNone || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic) {
+ validPrimitive = true;
+ break;
+ }
+ /* nobreak */
+ case CSSPropertyMinHeight: // <length> | <percentage> | inherit
+ case CSSPropertyMinWidth: // <length> | <percentage> | inherit
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
+ validPrimitive = true;
+ else
+ validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict));
+ break;
+
+ case CSSPropertyFontSize:
+ // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
+ if (id >= CSSValueXxSmall && id <= CSSValueLarger)
+ validPrimitive = true;
+ else
+ validPrimitive = (validUnit(value, FLength | FPercent | FNonNeg, m_strict));
+ break;
+
+ case CSSPropertyFontStyle: // normal | italic | oblique | inherit
+ return parseFontStyle(important);
+
+ case CSSPropertyFontVariant: // normal | small-caps | inherit
+ return parseFontVariant(important);
+
+ case CSSPropertyVerticalAlign:
+ // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
+ // <percentage> | <length> | inherit
+
+ if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
+ validPrimitive = true;
+ else
+ validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
+ break;
+
+ case CSSPropertyHeight: // <length> | <percentage> | auto | inherit
+ case CSSPropertyWidth: // <length> | <percentage> | auto | inherit
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ if (id == CSSValueAuto || id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
+ validPrimitive = true;
+ else if (!id && validUnit(value, FLength | FPercent | FNonNeg, m_strict))
+ // ### handle multilength case where we allow relative units
+ validPrimitive = true;
+ else if (value->unit == CSSParserValue::Function)
+ return parseFlex(propId, important);
+ break;
+
+ case CSSPropertyBottom: // <length> | <percentage> | auto | inherit
+ case CSSPropertyLeft: // <length> | <percentage> | auto | inherit
+ case CSSPropertyRight: // <length> | <percentage> | auto | inherit
+ case CSSPropertyTop: // <length> | <percentage> | auto | inherit
+ case CSSPropertyMarginTop: //// <margin-width> | inherit
+ case CSSPropertyMarginRight: // Which is defined as
+ case CSSPropertyMarginBottom: // <length> | <percentage> | auto | inherit
+ case CSSPropertyMarginLeft: ////
+ case CSSPropertyWebkitMarginStart:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitMarginAfter:
+ if (id == CSSValueAuto)
+ validPrimitive = true;
+ else
+ validPrimitive = (!id && validUnit(value, FLength | FPercent, m_strict));
+ break;
+
+ case CSSPropertyZIndex: // auto | <integer> | inherit
+ if (id == CSSValueAuto) {
+ validPrimitive = true;
+ break;
+ }
+ /* nobreak */
+ case CSSPropertyOrphans: // <integer> | inherit
+ case CSSPropertyWidows: // <integer> | inherit
+ // ### not supported later on
+ validPrimitive = (!id && validUnit(value, FInteger, false));
+ break;
+
+ case CSSPropertyLineHeight: // normal | <number> | <length> | <percentage> | inherit
+ if (id == CSSValueNormal)
+ validPrimitive = true;
+ else
+ validPrimitive = (!id && validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict));
+ break;
+ case CSSPropertyCounterIncrement: // [ <identifier> <integer>? ]+ | none | inherit
+ if (id != CSSValueNone)
+ return parseCounter(propId, 1, important);
+ validPrimitive = true;
+ break;
+ case CSSPropertyCounterReset: // [ <identifier> <integer>? ]+ | none | inherit
+ if (id != CSSValueNone)
+ return parseCounter(propId, 0, important);
+ validPrimitive = true;
+ break;
+ case CSSPropertyFontFamily:
+ // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
+ {
+ parsedValue = parseFontFamily();
+ break;
+ }
+
+ case CSSPropertyTextDecoration:
+ case CSSPropertyWebkitTextDecorationsInEffect:
+ // none | [ underline || overline || line-through || blink ] | inherit
+ if (id == CSSValueNone) {
+ validPrimitive = true;
+ } else {
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ bool isValid = true;
+ while (isValid && value) {
+ switch (value->id) {
+ case CSSValueBlink:
+ break;
+ case CSSValueUnderline:
+ case CSSValueOverline:
+ case CSSValueLineThrough:
+ list->append(cssValuePool()->createIdentifierValue(value->id));
+ break;
+ default:
+ isValid = false;
+ }
+ value = m_valueList->next();
+ }
+ if (list->length() && isValid) {
+ parsedValue = list.release();
+ m_valueList->next();
+ }
+ }
+ break;
+
+ case CSSPropertyZoom: // normal | reset | document | <number> | <percentage> | inherit
+ if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
+ validPrimitive = true;
+ else
+ validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg, true));
+ break;
+
+ case CSSPropertyTableLayout: // auto | fixed | inherit
+ if (id == CSSValueAuto || id == CSSValueFixed)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertySrc: // Only used within @font-face, so cannot use inherit | initial or be !important. This is a list of urls or local references.
+ return parseFontFaceSrc();
+
+ case CSSPropertyUnicodeRange:
+ return parseFontFaceUnicodeRange();
+
+ /* CSS3 properties */
+ case CSSPropertyWebkitAppearance:
+ if ((id >= CSSValueCheckbox && id <= CSSValueTextarea) || id == CSSValueNone)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyBorderImage:
+ case CSSPropertyWebkitBorderImage:
+ case CSSPropertyWebkitMaskBoxImage: {
+ RefPtr<CSSValue> result;
+ if (parseBorderImage(propId, result)) {
+ addProperty(propId, result, important);
+ return true;
+ }
+ break;
+ }
+ case CSSPropertyBorderImageOutset:
+ case CSSPropertyWebkitMaskBoxImageOutset: {
+ RefPtr<CSSPrimitiveValue> result;
+ if (parseBorderImageOutset(result)) {
+ addProperty(propId, result, important);
+ return true;
+ }
+ break;
+ }
+ case CSSPropertyBorderImageRepeat:
+ case CSSPropertyWebkitMaskBoxImageRepeat: {
+ RefPtr<CSSValue> result;
+ if (parseBorderImageRepeat(result)) {
+ addProperty(propId, result, important);
+ return true;
+ }
+ break;
+ }
+ case CSSPropertyBorderImageSlice:
+ case CSSPropertyWebkitMaskBoxImageSlice: {
+ RefPtr<CSSBorderImageSliceValue> result;
+ if (parseBorderImageSlice(propId, result)) {
+ addProperty(propId, result, important);
+ return true;
+ }
+ break;
+ }
+ case CSSPropertyBorderImageWidth:
+ case CSSPropertyWebkitMaskBoxImageWidth: {
+ RefPtr<CSSPrimitiveValue> result;
+ if (parseBorderImageWidth(result)) {
+ addProperty(propId, result, important);
+ return true;
+ }
+ break;
+ }
+ case CSSPropertyBorderTopRightRadius:
+ case CSSPropertyBorderTopLeftRadius:
+ case CSSPropertyBorderBottomLeftRadius:
+ case CSSPropertyBorderBottomRightRadius: {
+ if (num != 1 && num != 2)
+ return false;
+ validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, m_strict);
+ if (!validPrimitive)
+ return false;
+ RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value);
+ RefPtr<CSSPrimitiveValue> parsedValue2;
+ if (num == 2) {
+ value = m_valueList->next();
+ validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, m_strict);
+ if (!validPrimitive)
+ return false;
+ parsedValue2 = createPrimitiveNumericValue(value);
+ } else
+ parsedValue2 = parsedValue1;
+
+ RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release());
+ RefPtr<CSSPrimitiveValue> val = cssValuePool()->createValue(pair.release());
+ addProperty(propId, val.release(), important);
+ return true;
+ }
+ case CSSPropertyWebkitAspectRatio:
+ return parseAspectRatio(important);
+ case CSSPropertyBorderRadius:
+ case CSSPropertyWebkitBorderRadius:
+ return parseBorderRadius(propId, important);
+ case CSSPropertyOutlineOffset:
+ validPrimitive = validUnit(value, FLength | FPercent, m_strict);
+ break;
+ case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
+ case CSSPropertyBoxShadow:
+ case CSSPropertyWebkitBoxShadow:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else {
+ RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
+ if (shadowValueList) {
+ addProperty(propId, shadowValueList.release(), important);
+ m_valueList->next();
+ return true;
+ }
+ return false;
+ }
+ break;
+ case CSSPropertyWebkitBoxReflect:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else
+ return parseReflect(propId, important);
+ break;
+ case CSSPropertyOpacity:
+ validPrimitive = validUnit(value, FNumber, m_strict);
+ break;
+ case CSSPropertyWebkitBoxAlign:
+ if (id == CSSValueStretch || id == CSSValueStart || id == CSSValueEnd ||
+ id == CSSValueCenter || id == CSSValueBaseline)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitBoxDirection:
+ if (id == CSSValueNormal || id == CSSValueReverse)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitBoxLines:
+ if (id == CSSValueSingle || id == CSSValueMultiple)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitBoxOrient:
+ if (id == CSSValueHorizontal || id == CSSValueVertical ||
+ id == CSSValueInlineAxis || id == CSSValueBlockAxis)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitBoxPack:
+ if (id == CSSValueStart || id == CSSValueEnd ||
+ id == CSSValueCenter || id == CSSValueJustify)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitBoxFlex:
+ validPrimitive = validUnit(value, FNumber, m_strict);
+ break;
+ case CSSPropertyWebkitBoxFlexGroup:
+ case CSSPropertyWebkitBoxOrdinalGroup:
+ validPrimitive = validUnit(value, FInteger | FNonNeg, true);
+ break;
+ case CSSPropertyBoxSizing:
+ validPrimitive = id == CSSValueBorderBox || id == CSSValueContentBox;
+ break;
+ case CSSPropertyWebkitColorCorrection:
+ validPrimitive = id == CSSValueSrgb || id == CSSValueDefault;
+ break;
+#if ENABLE(CSS_FILTERS)
+ case CSSPropertyWebkitFilter:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else {
+ RefPtr<CSSValue> val = parseFilter();
+ if (val) {
+ addProperty(propId, val, important);
+ return true;
+ }
+ return false;
+ }
+ break;
+#endif
+ case CSSPropertyWebkitFlexOrder:
+ if (validUnit(value, FInteger, true)) {
+ // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set.
+ parsedValue = cssValuePool()->createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue),
+ static_cast<CSSPrimitiveValue::UnitTypes>(value->unit));
+ m_valueList->next();
+ }
+ break;
+ case CSSPropertyWebkitFlexPack:
+ validPrimitive = id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter || id == CSSValueJustify;
+ break;
+ case CSSPropertyWebkitFlexAlign:
+ validPrimitive = id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter || id == CSSValueBaseline || id == CSSValueStretch;
+ break;
+ case CSSPropertyWebkitFlexDirection:
+ validPrimitive = id == CSSValueRow || id == CSSValueRowReverse || id == CSSValueColumn || id == CSSValueColumnReverse;
+ break;
+ case CSSPropertyWebkitFlexWrap:
+ validPrimitive = id == CSSValueNowrap || id == CSSValueWrap || id == CSSValueWrapReverse;
+ break;
+ case CSSPropertyWebkitMarquee: {
+ const int properties[5] = { CSSPropertyWebkitMarqueeDirection, CSSPropertyWebkitMarqueeIncrement,
+ CSSPropertyWebkitMarqueeRepetition,
+ CSSPropertyWebkitMarqueeStyle, CSSPropertyWebkitMarqueeSpeed };
+ return parseShorthand(propId, properties, 5, important);
+ }
+ case CSSPropertyWebkitMarqueeDirection:
+ if (id == CSSValueForwards || id == CSSValueBackwards || id == CSSValueAhead ||
+ id == CSSValueReverse || id == CSSValueLeft || id == CSSValueRight || id == CSSValueDown ||
+ id == CSSValueUp || id == CSSValueAuto)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitMarqueeIncrement:
+ if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FLength | FPercent, m_strict);
+ break;
+ case CSSPropertyWebkitMarqueeStyle:
+ if (id == CSSValueNone || id == CSSValueSlide || id == CSSValueScroll || id == CSSValueAlternate)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitMarqueeRepetition:
+ if (id == CSSValueInfinite)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FInteger | FNonNeg, m_strict);
+ break;
+ case CSSPropertyWebkitMarqueeSpeed:
+ if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FTime | FInteger | FNonNeg, m_strict);
+ break;
+ case CSSPropertyWebkitFlowInto:
+ return parseFlowThread(propId, important);
+ case CSSPropertyWebkitFlowFrom:
+ return parseRegionThread(propId, important);
+ case CSSPropertyWebkitRegionOverflow:
+ if (id == CSSValueAuto || id == CSSValueBreak)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitUserDrag: // auto | none | element
+ if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueElement)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitUserModify: // read-only | read-write
+ if (id == CSSValueReadOnly || id == CSSValueReadWrite || id == CSSValueReadWritePlaintextOnly)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitUserSelect: // auto | none | text
+ if (id == CSSValueAuto || id == CSSValueNone || id == CSSValueText)
+ validPrimitive = true;
+ break;
+ case CSSPropertyTextOverflow: // clip | ellipsis
+ if (id == CSSValueClip || id == CSSValueEllipsis)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitTransform:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else {
+ PassRefPtr<CSSValue> val = parseTransform();
+ if (val) {
+ addProperty(propId, val, important);
+ return true;
+ }
+ return false;
+ }
+ break;
+ case CSSPropertyWebkitTransformOrigin:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ: {
+ RefPtr<CSSValue> val1;
+ RefPtr<CSSValue> val2;
+ RefPtr<CSSValue> val3;
+ int propId1, propId2, propId3;
+ if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
+ addProperty(propId1, val1.release(), important);
+ if (val2)
+ addProperty(propId2, val2.release(), important);
+ if (val3)
+ addProperty(propId3, val3.release(), important);
+ return true;
+ }
+ return false;
+ }
+ case CSSPropertyWebkitTransformStyle:
+ if (value->id == CSSValueFlat || value->id == CSSValuePreserve3d)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitBackfaceVisibility:
+ if (value->id == CSSValueVisible || value->id == CSSValueHidden)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitPrintColorAdjust:
+ if (value->id == CSSValueExact || value->id == CSSValueEconomy)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitPerspective:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else {
+ // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
+ if (validUnit(value, FNumber | FLength | FNonNeg, m_strict)) {
+ RefPtr<CSSValue> val = createPrimitiveNumericValue(value);
+ if (val) {
+ addProperty(propId, val.release(), important);
+ return true;
+ }
+ return false;
+ }
+ }
+ break;
+ case CSSPropertyWebkitPerspectiveOrigin:
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY: {
+ RefPtr<CSSValue> val1;
+ RefPtr<CSSValue> val2;
+ int propId1, propId2;
+ if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
+ addProperty(propId1, val1.release(), important);
+ if (val2)
+ addProperty(propId2, val2.release(), important);
+ return true;
+ }
+ return false;
+ }
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitAnimationDirection:
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitAnimationFillMode:
+ case CSSPropertyWebkitAnimationName:
+ case CSSPropertyWebkitAnimationPlayState:
+ case CSSPropertyWebkitAnimationIterationCount:
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitTransitionDelay:
+ case CSSPropertyWebkitTransitionDuration:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ case CSSPropertyWebkitTransitionProperty: {
+ RefPtr<CSSValue> val;
+ if (parseAnimationProperty(propId, val)) {
+ addProperty(propId, val.release(), important);
+ return true;
+ }
+ return false;
+ }
+#if ENABLE(CSS_GRID_LAYOUT)
+ case CSSPropertyWebkitGridColumns:
+ case CSSPropertyWebkitGridRows:
+ return parseGridTrackList(propId, important);
+#endif
+ case CSSPropertyWebkitMarginCollapse: {
+ const int properties[2] = { CSSPropertyWebkitMarginBeforeCollapse,
+ CSSPropertyWebkitMarginAfterCollapse };
+ if (num == 1) {
+ ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
+ if (!parseValue(properties[0], important))
+ return false;
+ CSSValue* value = m_parsedProperties[m_numParsedProperties-1]->value();
+ addProperty(properties[1], value, important);
+ return true;
+ }
+ else if (num == 2) {
+ ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
+ return false;
+ return true;
+ }
+ return false;
+ }
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ case CSSPropertyWebkitMarginAfterCollapse:
+ case CSSPropertyWebkitMarginTopCollapse:
+ case CSSPropertyWebkitMarginBottomCollapse:
+ if (id == CSSValueCollapse || id == CSSValueSeparate || id == CSSValueDiscard)
+ validPrimitive = true;
+ break;
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextUnderlineMode:
+ if (id == CSSValueContinuous || id == CSSValueSkipWhiteSpace)
+ validPrimitive = true;
+ break;
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextUnderlineStyle:
+ if (id == CSSValueNone || id == CSSValueSolid || id == CSSValueDouble ||
+ id == CSSValueDashed || id == CSSValueDotDash || id == CSSValueDotDotDash ||
+ id == CSSValueWave)
+ validPrimitive = true;
+ break;
+ case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
+ if (id == CSSValueAuto || id == CSSValueOptimizespeed || id == CSSValueOptimizelegibility
+ || id == CSSValueGeometricprecision)
+ validPrimitive = true;
+ break;
+ case CSSPropertyTextLineThroughWidth:
+ case CSSPropertyTextOverlineWidth:
+ case CSSPropertyTextUnderlineWidth:
+ if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
+ id == CSSValueMedium || id == CSSValueThick)
+ validPrimitive = true;
+ else
+ validPrimitive = !id && validUnit(value, FNumber | FLength | FPercent, m_strict);
+ break;
+ case CSSPropertyResize: // none | both | horizontal | vertical | auto
+ if (id == CSSValueNone || id == CSSValueBoth || id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitColumnCount:
+ if (id == CSSValueAuto)
+ validPrimitive = true;
+ else
+ validPrimitive = !id && validUnit(value, FInteger | FNonNeg, false);
+ break;
+ case CSSPropertyWebkitColumnGap: // normal | <length>
+ if (id == CSSValueNormal)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
+ break;
+ case CSSPropertyWebkitColumnAxis:
+ if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitColumnSpan: // all | 1
+ if (id == CSSValueAll)
+ validPrimitive = true;
+ else
+ validPrimitive = validUnit(value, FNumber | FNonNeg, m_strict) && value->fValue == 1;
+ break;
+ case CSSPropertyWebkitColumnWidth: // auto | <length>
+ if (id == CSSValueAuto)
+ validPrimitive = true;
+ else // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
+ validPrimitive = validUnit(value, FLength, true);
+ break;
+ case CSSPropertyPointerEvents:
+ // none | visiblePainted | visibleFill | visibleStroke | visible |
+ // painted | fill | stroke | auto | all | inherit
+ if (id == CSSValueVisible || id == CSSValueNone || id == CSSValueAll || id == CSSValueAuto ||
+ (id >= CSSValueVisiblepainted && id <= CSSValueStroke))
+ validPrimitive = true;
+ break;
+ case CSSPropertyImageRendering: // auto | optimizeContrast
+ if (id == CSSValueAuto || id == CSSValueWebkitOptimizeContrast)
+ validPrimitive = true;
+ break;
+ // End of CSS3 properties
+
+ // Apple specific properties. These will never be standardized and are purely to
+ // support custom WebKit-based Apple applications.
+ case CSSPropertyWebkitLineClamp:
+ // When specifying number of lines, don't allow 0 as a valid value
+ // When specifying either type of unit, require non-negative integers
+ validPrimitive = (!id && (value->unit == CSSPrimitiveValue::CSS_PERCENTAGE || value->fValue) && validUnit(value, FInteger | FPercent | FNonNeg, false));
+ break;
+ case CSSPropertyWebkitTextSizeAdjust:
+ if (id == CSSValueAuto || id == CSSValueNone)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitRtlOrdering:
+ if (id == CSSValueLogical || id == CSSValueVisual)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitFontSizeDelta: // <length>
+ validPrimitive = validUnit(value, FLength, m_strict);
+ break;
+
+ case CSSPropertyWebkitNbspMode: // normal | space
+ if (id == CSSValueNormal || id == CSSValueSpace)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitLineBreak: // normal | after-white-space
+ if (id == CSSValueNormal || id == CSSValueAfterWhiteSpace)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitMatchNearestMailBlockquoteColor: // normal | match
+ if (id == CSSValueNormal || id == CSSValueMatch)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitHighlight:
+ if (id == CSSValueNone || value->unit == CSSPrimitiveValue::CSS_STRING)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitHyphens:
+ if (id == CSSValueNone || id == CSSValueManual || id == CSSValueAuto)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitHyphenateCharacter:
+ if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitHyphenateLimitBefore:
+ case CSSPropertyWebkitHyphenateLimitAfter:
+ if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true))
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitHyphenateLimitLines:
+ if (id == CSSValueNoLimit || validUnit(value, FInteger | FNonNeg, true))
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitLineGrid:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
+ String lineGridValue = String(value->string);
+ if (!lineGridValue.isEmpty()) {
+ addProperty(propId, cssValuePool()->createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
+ return true;
+ }
+ }
+ break;
+ case CSSPropertyWebkitLineGridSnap:
+ if (id == CSSValueNone || id == CSSValueBaseline || id == CSSValueBounds)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitLocale:
+ if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitBorderFit:
+ if (id == CSSValueBorder || id == CSSValueLines)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitTextSecurity:
+ // disc | circle | square | none | inherit
+ if (id == CSSValueDisc || id == CSSValueCircle || id == CSSValueSquare|| id == CSSValueNone)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitFontSmoothing:
+ if (id == CSSValueAuto || id == CSSValueNone
+ || id == CSSValueAntialiased || id == CSSValueSubpixelAntialiased)
+ validPrimitive = true;
+ break;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
+ if (value->unit == CSSParserValue::Function || id == CSSValueNone)
+ return parseDashboardRegions(propId, important);
+ break;
+#endif
+ // End Apple-specific properties
+
+#if ENABLE(TOUCH_EVENTS)
+ case CSSPropertyWebkitTapHighlightColor:
+ if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu
+ || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && !m_strict)) {
+ validPrimitive = true;
+ } else {
+ parsedValue = parseColor();
+ if (parsedValue)
+ m_valueList->next();
+ }
+ break;
+#endif
+ /* shorthand properties */
+ case CSSPropertyBackground: {
+ // Position must come before color in this array because a plain old "0" is a legal color
+ // in quirks mode but it's usually the X coordinate of a position.
+ // FIXME: Add CSSPropertyBackgroundSize to the shorthand.
+ const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
+ CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
+ CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
+ return parseFillShorthand(propId, properties, 7, important);
+ }
+ case CSSPropertyWebkitMask: {
+ const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
+ CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
+ CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
+ return parseFillShorthand(propId, properties, 6, important);
+ }
+ case CSSPropertyBorder:
+ // [ 'border-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSSPropertyBorderWidth, CSSPropertyBorderStyle,
+ CSSPropertyBorderColor };
+ if (parseShorthand(propId, properties, 3, important)) {
+ // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
+ // though a value of none was specified for the image.
+ addProperty(CSSPropertyBorderImage, cssValuePool()->createImplicitInitialValue(), important);
+ return true;
+ }
+ return false;
+ }
+ case CSSPropertyBorderTop:
+ // [ 'border-top-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
+ CSSPropertyBorderTopColor};
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyBorderRight:
+ // [ 'border-right-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
+ CSSPropertyBorderRightColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyBorderBottom:
+ // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
+ CSSPropertyBorderBottomColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyBorderLeft:
+ // [ 'border-left-width' || 'border-style' || <color> ] | inherit
+ {
+ const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
+ CSSPropertyBorderLeftColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyWebkitBorderStart:
+ {
+ const int properties[3] = { CSSPropertyWebkitBorderStartWidth, CSSPropertyWebkitBorderStartStyle,
+ CSSPropertyWebkitBorderStartColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyWebkitBorderEnd:
+ {
+ const int properties[3] = { CSSPropertyWebkitBorderEndWidth, CSSPropertyWebkitBorderEndStyle,
+ CSSPropertyWebkitBorderEndColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyWebkitBorderBefore:
+ {
+ const int properties[3] = { CSSPropertyWebkitBorderBeforeWidth, CSSPropertyWebkitBorderBeforeStyle,
+ CSSPropertyWebkitBorderBeforeColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyWebkitBorderAfter:
+ {
+ const int properties[3] = { CSSPropertyWebkitBorderAfterWidth, CSSPropertyWebkitBorderAfterStyle,
+ CSSPropertyWebkitBorderAfterColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyOutline:
+ // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
+ {
+ const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
+ CSSPropertyOutlineColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyBorderColor:
+ // <color>{1,4} | inherit
+ {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
+ CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return parse4Values(propId, properties, important);
+ }
+ case CSSPropertyBorderWidth:
+ // <border-width>{1,4} | inherit
+ {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
+ CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return parse4Values(propId, properties, important);
+ }
+ case CSSPropertyBorderStyle:
+ // <border-style>{1,4} | inherit
+ {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
+ CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return parse4Values(propId, properties, important);
+ }
+ case CSSPropertyMargin:
+ // <margin-width>{1,4} | inherit
+ {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
+ CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return parse4Values(propId, properties, important);
+ }
+ case CSSPropertyPadding:
+ // <padding-width>{1,4} | inherit
+ {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
+ CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return parse4Values(propId, properties, important);
+ }
+ case CSSPropertyWebkitFlexFlow:
+ {
+ const int properties[] = { CSSPropertyWebkitFlexDirection, CSSPropertyWebkitFlexWrap };
+ return parseShorthand(propId, properties, 2, important);
+ }
+ case CSSPropertyFont:
+ // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
+ // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
+ if (id >= CSSValueCaption && id <= CSSValueStatusBar)
+ validPrimitive = true;
+ else
+ return parseFont(important);
+ break;
+ case CSSPropertyListStyle:
+ {
+ const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
+ CSSPropertyListStyleImage };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyWebkitColumns: {
+ const int properties[2] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
+ return parseShorthand(propId, properties, 2, important);
+ }
+ case CSSPropertyWebkitColumnRule: {
+ const int properties[3] = { CSSPropertyWebkitColumnRuleWidth, CSSPropertyWebkitColumnRuleStyle,
+ CSSPropertyWebkitColumnRuleColor };
+ return parseShorthand(propId, properties, 3, important);
+ }
+ case CSSPropertyWebkitTextStroke: {
+ const int properties[2] = { CSSPropertyWebkitTextStrokeWidth, CSSPropertyWebkitTextStrokeColor };
+ return parseShorthand(propId, properties, 2, important);
+ }
+ case CSSPropertyWebkitAnimation:
+ return parseAnimationShorthand(important);
+ case CSSPropertyWebkitTransition:
+ return parseTransitionShorthand(important);
+ case CSSPropertyInvalid:
+ return false;
+ case CSSPropertyPage:
+ return parsePage(propId, important);
+ case CSSPropertyFontStretch:
+ case CSSPropertyTextLineThrough:
+ case CSSPropertyTextOverline:
+ case CSSPropertyTextUnderline:
+ return false;
+ // CSS Text Layout Module Level 3: Vertical writing support
+ case CSSPropertyWebkitWritingMode:
+ if (id >= CSSValueHorizontalTb && id <= CSSValueHorizontalBt)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitTextCombine:
+ if (id == CSSValueNone || id == CSSValueHorizontal)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitTextEmphasis: {
+ const int properties[] = { CSSPropertyWebkitTextEmphasisStyle, CSSPropertyWebkitTextEmphasisColor };
+ return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
+ }
+
+ case CSSPropertyWebkitTextEmphasisPosition:
+ if (id == CSSValueOver || id == CSSValueUnder)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitTextEmphasisStyle:
+ return parseTextEmphasisStyle(important);
+
+ case CSSPropertyWebkitTextOrientation:
+ // FIXME: For now just support upright and vertical-right.
+ if (id == CSSValueVerticalRight || id == CSSValueUpright)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitLineBoxContain:
+ if (id == CSSValueNone)
+ validPrimitive = true;
+ else
+ return parseLineBoxContain(important);
+ break;
+ case CSSPropertyWebkitFontFeatureSettings:
+ if (id == CSSValueNormal)
+ validPrimitive = true;
+ else
+ return parseFontFeatureSettings(important);
+ break;
+
+ case CSSPropertyWebkitWrapShapeInside:
+ case CSSPropertyWebkitWrapShapeOutside:
+ if (id == CSSValueAuto)
+ validPrimitive = true;
+ else if (value->unit == CSSParserValue::Function)
+ return parseWrapShape((propId == CSSPropertyWebkitWrapShapeInside), important);
+ break;
+ case CSSPropertyWebkitWrapFlow:
+ if (id == CSSValueAuto || id == CSSValueBoth || id == CSSValueLeft || id == CSSValueRight || id == CSSValueMaximum || id == CSSValueClear)
+ validPrimitive = true;
+ break;
+
+ case CSSPropertyWebkitWrapThrough:
+ if (id == CSSValueWrap || id == CSSValueNone)
+ validPrimitive = true;
+ break;
+ case CSSPropertyWebkitWrapMargin:
+ case CSSPropertyWebkitWrapPadding:
+ validPrimitive = (!id && validUnit(value, FLength | FNonNeg, m_strict));
+ break;
+ case CSSPropertyWebkitWrap: {
+ const int properties[] = { CSSPropertyWebkitWrapFlow, CSSPropertyWebkitWrapMargin, CSSPropertyWebkitWrapPadding };
+ return parseShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
+ }
+#if ENABLE(SVG)
+ default:
+ return parseSVGValue(propId, important);
+#endif
+ }
+
+ if (validPrimitive) {
+ parsedValue = parseValidPrimitive(id, value);
+ m_valueList->next();
+ }
+ if (parsedValue) {
+ if (!m_valueList->current() || inShorthand()) {
+ addProperty(propId, parsedValue.release(), important);
+ return true;
+ }
+ }
+ return false;
+}
+
+void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
+{
+ if (lval) {
+ if (lval->isValueList())
+ static_cast<CSSValueList*>(lval.get())->append(rval);
+ else {
+ PassRefPtr<CSSValue> oldlVal(lval.release());
+ PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ list->append(oldlVal);
+ list->append(rval);
+ lval = list;
+ }
+ }
+ else
+ lval = rval;
+}
+
+static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSValuePool* cssValuePool)
+{
+ if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox
+ || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) {
+ cssValue = cssValuePool->createIdentifierValue(parserValue->id);
+ return true;
+ }
+ return false;
+}
+
+const int cMaxFillProperties = 9;
+
+bool CSSParser::parseFillShorthand(int propId, const int* properties, int numProperties, bool important)
+{
+ ASSERT(numProperties <= cMaxFillProperties);
+ if (numProperties > cMaxFillProperties)
+ return false;
+
+ ShorthandScope scope(this, propId);
+
+ bool parsedProperty[cMaxFillProperties] = { false };
+ RefPtr<CSSValue> values[cMaxFillProperties];
+ RefPtr<CSSValue> clipValue;
+ RefPtr<CSSValue> positionYValue;
+ RefPtr<CSSValue> repeatYValue;
+ bool foundClip = false;
+ int i;
+
+ while (m_valueList->current()) {
+ CSSParserValue* val = m_valueList->current();
+ if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
+ // We hit the end. Fill in all remaining values with the initial value.
+ m_valueList->next();
+ for (i = 0; i < numProperties; ++i) {
+ if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
+ // Color is not allowed except as the last item in a list for backgrounds.
+ // Reject the entire property.
+ return false;
+
+ if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
+ addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
+ if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
+ addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
+ if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
+ addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
+ if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
+ // If background-origin wasn't present, then reset background-clip also.
+ addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
+ }
+ }
+ parsedProperty[i] = false;
+ }
+ if (!m_valueList->current())
+ break;
+ }
+
+ bool found = false;
+ for (i = 0; !found && i < numProperties; ++i) {
+ if (!parsedProperty[i]) {
+ RefPtr<CSSValue> val1;
+ RefPtr<CSSValue> val2;
+ int propId1, propId2;
+ CSSParserValue* parserValue = m_valueList->current();
+ if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
+ parsedProperty[i] = found = true;
+ addFillValue(values[i], val1.release());
+ if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
+ addFillValue(positionYValue, val2.release());
+ if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
+ addFillValue(repeatYValue, val2.release());
+ if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
+ // Reparse the value as a clip, and see if we succeed.
+ if (parseBackgroundClip(parserValue, val1, cssValuePool()))
+ addFillValue(clipValue, val1.release()); // The property parsed successfully.
+ else
+ addFillValue(clipValue, cssValuePool()->createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
+ }
+ if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) {
+ // Update clipValue
+ addFillValue(clipValue, val1.release());
+ foundClip = true;
+ }
+ }
+ }
+ }
+
+ // if we didn't find at least one match, this is an
+ // invalid shorthand and we have to ignore it
+ if (!found)
+ return false;
+ }
+
+ // Fill in any remaining properties with the initial value.
+ for (i = 0; i < numProperties; ++i) {
+ if (!parsedProperty[i]) {
+ addFillValue(values[i], cssValuePool()->createImplicitInitialValue());
+ if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
+ addFillValue(positionYValue, cssValuePool()->createImplicitInitialValue());
+ if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
+ addFillValue(repeatYValue, cssValuePool()->createImplicitInitialValue());
+ if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
+ // If background-origin wasn't present, then reset background-clip also.
+ addFillValue(clipValue, cssValuePool()->createImplicitInitialValue());
+ }
+ }
+ }
+
+ // Now add all of the properties we found.
+ for (i = 0; i < numProperties; i++) {
+ if (properties[i] == CSSPropertyBackgroundPosition) {
+ addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
+ // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
+ addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
+ } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
+ addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
+ // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
+ addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
+ } else if (properties[i] == CSSPropertyBackgroundRepeat) {
+ addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
+ // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
+ addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
+ } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
+ addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
+ // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
+ addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
+ } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
+ // Value is already set while updating origin
+ continue;
+ else
+ addProperty(properties[i], values[i].release(), important);
+
+ // Add in clip values when we hit the corresponding origin property.
+ if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
+ addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
+ else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
+ addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
+ }
+
+ return true;
+}
+
+void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval)
+{
+ if (lval) {
+ if (lval->isValueList())
+ static_cast<CSSValueList*>(lval.get())->append(rval);
+ else {
+ PassRefPtr<CSSValue> oldVal(lval.release());
+ PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ list->append(oldVal);
+ list->append(rval);
+ lval = list;
+ }
+ }
+ else
+ lval = rval;
+}
+
+bool CSSParser::parseAnimationShorthand(bool important)
+{
+ const int properties[] = { CSSPropertyWebkitAnimationName,
+ CSSPropertyWebkitAnimationDuration,
+ CSSPropertyWebkitAnimationTimingFunction,
+ CSSPropertyWebkitAnimationDelay,
+ CSSPropertyWebkitAnimationIterationCount,
+ CSSPropertyWebkitAnimationDirection,
+ CSSPropertyWebkitAnimationFillMode };
+ const int numProperties = WTF_ARRAY_LENGTH(properties);
+
+ ShorthandScope scope(this, CSSPropertyWebkitAnimation);
+
+ bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
+ RefPtr<CSSValue> values[numProperties];
+
+ int i;
+ while (m_valueList->current()) {
+ CSSParserValue* val = m_valueList->current();
+ if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
+ // We hit the end. Fill in all remaining values with the initial value.
+ m_valueList->next();
+ for (i = 0; i < numProperties; ++i) {
+ if (!parsedProperty[i])
+ addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
+ parsedProperty[i] = false;
+ }
+ if (!m_valueList->current())
+ break;
+ }
+
+ bool found = false;
+ for (i = 0; !found && i < numProperties; ++i) {
+ if (!parsedProperty[i]) {
+ RefPtr<CSSValue> val;
+ if (parseAnimationProperty(properties[i], val)) {
+ parsedProperty[i] = found = true;
+ addAnimationValue(values[i], val.release());
+ }
+ }
+ }
+
+ // if we didn't find at least one match, this is an
+ // invalid shorthand and we have to ignore it
+ if (!found)
+ return false;
+ }
+
+ // Fill in any remaining properties with the initial value.
+ for (i = 0; i < numProperties; ++i) {
+ if (!parsedProperty[i])
+ addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
+ }
+
+ // Now add all of the properties we found.
+ for (i = 0; i < numProperties; i++)
+ addProperty(properties[i], values[i].release(), important);
+
+ return true;
+}
+
+bool CSSParser::parseTransitionShorthand(bool important)
+{
+ const int properties[] = { CSSPropertyWebkitTransitionProperty,
+ CSSPropertyWebkitTransitionDuration,
+ CSSPropertyWebkitTransitionTimingFunction,
+ CSSPropertyWebkitTransitionDelay };
+ const int numProperties = WTF_ARRAY_LENGTH(properties);
+
+ ShorthandScope scope(this, CSSPropertyWebkitTransition);
+
+ bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary
+ RefPtr<CSSValue> values[numProperties];
+
+ int i;
+ while (m_valueList->current()) {
+ CSSParserValue* val = m_valueList->current();
+ if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
+ // We hit the end. Fill in all remaining values with the initial value.
+ m_valueList->next();
+ for (i = 0; i < numProperties; ++i) {
+ if (!parsedProperty[i])
+ addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
+ parsedProperty[i] = false;
+ }
+ if (!m_valueList->current())
+ break;
+ }
+
+ bool found = false;
+ for (i = 0; !found && i < numProperties; ++i) {
+ if (!parsedProperty[i]) {
+ RefPtr<CSSValue> val;
+ if (parseAnimationProperty(properties[i], val)) {
+ parsedProperty[i] = found = true;
+ addAnimationValue(values[i], val.release());
+ }
+ }
+ }
+
+ // if we didn't find at least one match, this is an
+ // invalid shorthand and we have to ignore it
+ if (!found)
+ return false;
+ }
+
+ // Fill in any remaining properties with the initial value.
+ for (i = 0; i < numProperties; ++i) {
+ if (!parsedProperty[i])
+ addAnimationValue(values[i], cssValuePool()->createImplicitInitialValue());
+ }
+
+ // Now add all of the properties we found.
+ for (i = 0; i < numProperties; i++)
+ addProperty(properties[i], values[i].release(), important);
+
+ return true;
+}
+
+bool CSSParser::parseShorthand(int propId, const int *properties, int numProperties, bool important)
+{
+ // We try to match as many properties as possible
+ // We set up an array of booleans to mark which property has been found,
+ // and we try to search for properties until it makes no longer any sense.
+ ShorthandScope scope(this, propId);
+
+ bool found = false;
+ bool fnd[6]; // Trust me ;)
+ for (int i = 0; i < numProperties; i++)
+ fnd[i] = false;
+
+ while (m_valueList->current()) {
+ found = false;
+ for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) {
+ if (!fnd[propIndex]) {
+ if (parseValue(properties[propIndex], important))
+ fnd[propIndex] = found = true;
+ }
+ }
+
+ // if we didn't find at least one match, this is an
+ // invalid shorthand and we have to ignore it
+ if (!found)
+ return false;
+ }
+
+ // Fill in any remaining properties with the initial value.
+ ImplicitScope implicitScope(this, PropertyImplicit);
+ for (int i = 0; i < numProperties; ++i) {
+ if (!fnd[i])
+ addProperty(properties[i], cssValuePool()->createImplicitInitialValue(), important);
+ }
+
+ return true;
+}
+
+bool CSSParser::parse4Values(int propId, const int *properties, bool important)
+{
+ /* From the CSS 2 specs, 8.3
+ * If there is only one value, it applies to all sides. If there are two values, the top and
+ * bottom margins are set to the first value and the right and left margins are set to the second.
+ * If there are three values, the top is set to the first value, the left and right are set to the
+ * second, and the bottom is set to the third. If there are four values, they apply to the top,
+ * right, bottom, and left, respectively.
+ */
+
+ int num = inShorthand() ? 1 : m_valueList->size();
+
+ ShorthandScope scope(this, propId);
+
+ // the order is top, right, bottom, left
+ switch (num) {
+ case 1: {
+ if (!parseValue(properties[0], important))
+ return false;
+ CSSValue *value = m_parsedProperties[m_numParsedProperties-1]->value();
+ ImplicitScope implicitScope(this, PropertyImplicit);
+ addProperty(properties[1], value, important);
+ addProperty(properties[2], value, important);
+ addProperty(properties[3], value, important);
+ break;
+ }
+ case 2: {
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
+ return false;
+ CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
+ ImplicitScope implicitScope(this, PropertyImplicit);
+ addProperty(properties[2], value, important);
+ value = m_parsedProperties[m_numParsedProperties-2]->value();
+ addProperty(properties[3], value, important);
+ break;
+ }
+ case 3: {
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
+ return false;
+ CSSValue *value = m_parsedProperties[m_numParsedProperties-2]->value();
+ ImplicitScope implicitScope(this, PropertyImplicit);
+ addProperty(properties[3], value, important);
+ break;
+ }
+ case 4: {
+ if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
+ !parseValue(properties[2], important) || !parseValue(properties[3], important))
+ return false;
+ break;
+ }
+ default: {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// auto | <identifier>
+bool CSSParser::parsePage(int propId, bool important)
+{
+ ASSERT(propId == CSSPropertyPage);
+
+ if (m_valueList->size() != 1)
+ return false;
+
+ CSSParserValue* value = m_valueList->current();
+ if (!value)
+ return false;
+
+ if (value->id == CSSValueAuto) {
+ addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
+ return true;
+ } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) {
+ addProperty(propId, createPrimitiveStringValue(value), important);
+ return true;
+ }
+ return false;
+}
+
+// <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
+bool CSSParser::parseSize(int propId, bool important)
+{
+ ASSERT(propId == CSSPropertySize);
+
+ if (m_valueList->size() > 2)
+ return false;
+
+ CSSParserValue* value = m_valueList->current();
+ if (!value)
+ return false;
+
+ RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
+
+ // First parameter.
+ SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None);
+ if (paramType == None)
+ return false;
+
+ // Second parameter, if any.
+ value = m_valueList->next();
+ if (value) {
+ paramType = parseSizeParameter(parsedValues.get(), value, paramType);
+ if (paramType == None)
+ return false;
+ }
+
+ addProperty(propId, parsedValues.release(), important);
+ return true;
+}
+
+CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType)
+{
+ switch (value->id) {
+ case CSSValueAuto:
+ if (prevParamType == None) {
+ parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
+ return Auto;
+ }
+ return None;
+ case CSSValueLandscape:
+ case CSSValuePortrait:
+ if (prevParamType == None || prevParamType == PageSize) {
+ parsedValues->append(cssValuePool()->createIdentifierValue(value->id));
+ return Orientation;
+ }
+ return None;
+ case CSSValueA3:
+ case CSSValueA4:
+ case CSSValueA5:
+ case CSSValueB4:
+ case CSSValueB5:
+ case CSSValueLedger:
+ case CSSValueLegal:
+ case CSSValueLetter:
+ if (prevParamType == None || prevParamType == Orientation) {
+ // Normalize to Page Size then Orientation order by prepending.
+ // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty).
+ parsedValues->prepend(cssValuePool()->createIdentifierValue(value->id));
+ return PageSize;
+ }
+ return None;
+ case 0:
+ if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) {
+ parsedValues->append(createPrimitiveNumericValue(value));
+ return Length;
+ }
+ return None;
+ default:
+ return None;
+ }
+}
+
+// [ <string> <string> ]+ | inherit | none
+// inherit and none are handled in parseValue.
+bool CSSParser::parseQuotes(int propId, bool important)
+{
+ RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
+ while (CSSParserValue* val = m_valueList->current()) {
+ RefPtr<CSSValue> parsedValue;
+ if (val->unit == CSSPrimitiveValue::CSS_STRING)
+ parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING);
+ else
+ break;
+ values->append(parsedValue.release());
+ m_valueList->next();
+ }
+ if (values->length()) {
+ addProperty(propId, values.release(), important);
+ m_valueList->next();
+ return true;
+ }
+ return false;
+}
+
+// [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
+// in CSS 2.1 this got somewhat reduced:
+// [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
+bool CSSParser::parseContent(int propId, bool important)
+{
+ RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
+
+ while (CSSParserValue* val = m_valueList->current()) {
+ RefPtr<CSSValue> parsedValue;
+ if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
+ // url
+ // FIXME: The completeURL call should be done when using the CSSImageValue,
+ // not when creating it.
+ parsedValue = CSSImageValue::create(m_styleSheet->completeURL(val->string));
+ } else if (val->unit == CSSParserValue::Function) {
+ // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...)
+ CSSParserValueList* args = val->function->args.get();
+ if (!args)
+ return false;
+ if (equalIgnoringCase(val->function->name, "attr(")) {
+ parsedValue = parseAttr(args);
+ if (!parsedValue)
+ return false;
+ } else if (equalIgnoringCase(val->function->name, "counter(")) {
+ parsedValue = parseCounterContent(args, false);
+ if (!parsedValue)
+ return false;
+ } else if (equalIgnoringCase(val->function->name, "counters(")) {
+ parsedValue = parseCounterContent(args, true);
+ if (!parsedValue)
+ return false;
+ } else if (isGeneratedImageValue(val)) {
+ if (!parseGeneratedImage(m_valueList.get(), parsedValue))
+ return false;
+ } else
+ return false;
+ } else if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
+ // open-quote
+ // close-quote
+ // no-open-quote
+ // no-close-quote
+ // inherit
+ // FIXME: These are not yet implemented (http://bugs.webkit.org/show_bug.cgi?id=6503).
+ // none
+ // normal
+ switch (val->id) {
+ case CSSValueOpenQuote:
+ case CSSValueCloseQuote:
+ case CSSValueNoOpenQuote:
+ case CSSValueNoCloseQuote:
+ case CSSValueNone:
+ case CSSValueNormal:
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ }
+ } else if (val->unit == CSSPrimitiveValue::CSS_STRING) {
+ parsedValue = createPrimitiveStringValue(val);
+ }
+ if (!parsedValue)
+ break;
+ values->append(parsedValue.release());
+ m_valueList->next();
+ }
+
+ if (values->length()) {
+ addProperty(propId, values.release(), important);
+ m_valueList->next();
+ return true;
+ }
+
+ return false;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args)
+{
+ if (args->size() != 1)
+ return 0;
+
+ CSSParserValue* a = args->current();
+
+ if (a->unit != CSSPrimitiveValue::CSS_IDENT)
+ return 0;
+
+ String attrName = a->string;
+ // CSS allows identifiers with "-" at the start, like "-webkit-mask-image".
+ // But HTML attribute names can't have those characters, and we should not
+ // even parse them inside attr().
+ if (attrName[0] == '-')
+ return 0;
+
+ Document* document = findDocument();
+ if (document && document->isHTMLDocument())
+ attrName = attrName.lower();
+
+ return cssValuePool()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR);
+}
+
+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 parseColor();
+}
+
+bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
+{
+ if (valueList->current()->id == CSSValueNone) {
+ value = CSSImageValue::create();
+ return true;
+ }
+ if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) {
+ // FIXME: The completeURL call should be done when using the CSSImageValue,
+ // not when creating it.
+ if (m_styleSheet)
+ value = CSSImageValue::create(m_styleSheet->completeURL(valueList->current()->string));
+ return true;
+ }
+
+ if (isGeneratedImageValue(valueList->current()))
+ return parseGeneratedImage(valueList, value);
+
+ return false;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList)
+{
+ int id = valueList->current()->id;
+ if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) {
+ int percent = 0;
+ if (id == CSSValueRight)
+ percent = 100;
+ else if (id == CSSValueCenter)
+ percent = 50;
+ return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ if (validUnit(valueList->current(), FPercent | FLength, m_strict))
+ return createPrimitiveNumericValue(valueList->current());
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList)
+{
+ int id = valueList->current()->id;
+ if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) {
+ int percent = 0;
+ if (id == CSSValueBottom)
+ percent = 100;
+ else if (id == CSSValueCenter)
+ percent = 50;
+ return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ if (validUnit(valueList->current(), FPercent | FLength, m_strict))
+ return createPrimitiveNumericValue(valueList->current());
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag)
+{
+ int id = valueList->current()->id;
+ if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
+ int percent = 0;
+ if (id == CSSValueLeft || id == CSSValueRight) {
+ if (cumulativeFlags & XFillPosition)
+ return 0;
+ cumulativeFlags |= XFillPosition;
+ individualFlag = XFillPosition;
+ if (id == CSSValueRight)
+ percent = 100;
+ }
+ else if (id == CSSValueTop || id == CSSValueBottom) {
+ if (cumulativeFlags & YFillPosition)
+ return 0;
+ cumulativeFlags |= YFillPosition;
+ individualFlag = YFillPosition;
+ if (id == CSSValueBottom)
+ percent = 100;
+ } else if (id == CSSValueCenter) {
+ // Center is ambiguous, so we're not sure which position we've found yet, an x or a y.
+ percent = 50;
+ cumulativeFlags |= AmbiguousFillPosition;
+ individualFlag = AmbiguousFillPosition;
+ }
+ return cssValuePool()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
+ }
+ if (validUnit(valueList->current(), FPercent | FLength, m_strict)) {
+ if (!cumulativeFlags) {
+ cumulativeFlags |= XFillPosition;
+ individualFlag = XFillPosition;
+ } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) {
+ cumulativeFlags |= YFillPosition;
+ individualFlag = YFillPosition;
+ } else
+ return 0;
+ return createPrimitiveNumericValue(valueList->current());
+ }
+ return 0;
+}
+
+void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
+{
+ CSSParserValue* value = valueList->current();
+
+ // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
+ unsigned cumulativeFlags = 0;
+ FillPositionFlag value1Flag = InvalidFillPosition;
+ FillPositionFlag value2Flag = InvalidFillPosition;
+ value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag);
+ if (!value1)
+ return;
+
+ // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
+ // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
+ // value was explicitly specified for our property.
+ value = valueList->next();
+
+ // First check for the comma. If so, we are finished parsing this value or value pair.
+ if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
+ value = 0;
+
+ if (value) {
+ value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag);
+ if (value2)
+ valueList->next();
+ else {
+ if (!inShorthand()) {
+ value1.clear();
+ return;
+ }
+ }
+ }
+
+ if (!value2)
+ // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position
+ // is simply 50%. This is our default.
+ // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center).
+ // For left/right/center, the default of 50% in the y is still correct.
+ value2 = cssValuePool()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE);
+
+ if (value1Flag == YFillPosition || value2Flag == XFillPosition)
+ value1.swap(value2);
+}
+
+void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
+{
+ CSSParserValue* value = m_valueList->current();
+
+ int id = m_valueList->current()->id;
+ if (id == CSSValueRepeatX) {
+ m_implicitShorthand = true;
+ value1 = cssValuePool()->createIdentifierValue(CSSValueRepeat);
+ value2 = cssValuePool()->createIdentifierValue(CSSValueNoRepeat);
+ m_valueList->next();
+ return;
+ }
+ if (id == CSSValueRepeatY) {
+ m_implicitShorthand = true;
+ value1 = cssValuePool()->createIdentifierValue(CSSValueNoRepeat);
+ value2 = cssValuePool()->createIdentifierValue(CSSValueRepeat);
+ m_valueList->next();
+ return;
+ }
+ if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)
+ value1 = cssValuePool()->createIdentifierValue(id);
+ else {
+ value1 = 0;
+ return;
+ }
+
+ value = m_valueList->next();
+
+ // First check for the comma. If so, we are finished parsing this value or value pair.
+ if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
+ value = 0;
+
+ if (value)
+ id = m_valueList->current()->id;
+
+ if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) {
+ value2 = cssValuePool()->createIdentifierValue(id);
+ m_valueList->next();
+ } else {
+ // If only one value was specified, value2 is the same as value1.
+ m_implicitShorthand = true;
+ value2 = cssValuePool()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent());
+ }
+}
+
+PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma)
+{
+ allowComma = true;
+ CSSParserValue* value = m_valueList->current();
+
+ if (value->id == CSSValueContain || value->id == CSSValueCover)
+ return cssValuePool()->createIdentifierValue(value->id);
+
+ RefPtr<CSSPrimitiveValue> parsedValue1;
+
+ if (value->id == CSSValueAuto)
+ parsedValue1 = cssValuePool()->createIdentifierValue(CSSValueAuto);
+ else {
+ if (!validUnit(value, FLength | FPercent, m_strict))
+ return 0;
+ parsedValue1 = createPrimitiveNumericValue(value);
+ }
+
+ CSSPropertyID property = static_cast<CSSPropertyID>(propId);
+ RefPtr<CSSPrimitiveValue> parsedValue2;
+ if ((value = m_valueList->next())) {
+ if (value->unit == CSSParserValue::Operator && value->iValue == ',')
+ allowComma = false;
+ else if (value->id != CSSValueAuto) {
+ if (!validUnit(value, FLength | FPercent, m_strict))
+ return 0;
+ parsedValue2 = createPrimitiveNumericValue(value);
+ }
+ } else if (!parsedValue2 && property == CSSPropertyWebkitBackgroundSize) {
+ // For backwards compatibility we set the second value to the first if it is omitted.
+ // We only need to do this for -webkit-background-size. It should be safe to let masks match
+ // the real property.
+ parsedValue2 = parsedValue1;
+ }
+
+ if (!parsedValue2)
+ return parsedValue1;
+ return cssValuePool()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release()));
+}
+
+bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
+ RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2)
+{
+ RefPtr<CSSValueList> values;
+ RefPtr<CSSValueList> values2;
+ CSSParserValue* val;
+ RefPtr<CSSValue> value;
+ RefPtr<CSSValue> value2;
+
+ bool allowComma = false;
+
+ retValue1 = retValue2 = 0;
+ propId1 = propId;
+ propId2 = propId;
+ if (propId == CSSPropertyBackgroundPosition) {
+ propId1 = CSSPropertyBackgroundPositionX;
+ propId2 = CSSPropertyBackgroundPositionY;
+ } else if (propId == CSSPropertyWebkitMaskPosition) {
+ propId1 = CSSPropertyWebkitMaskPositionX;
+ propId2 = CSSPropertyWebkitMaskPositionY;
+ } else if (propId == CSSPropertyBackgroundRepeat) {
+ propId1 = CSSPropertyBackgroundRepeatX;
+ propId2 = CSSPropertyBackgroundRepeatY;
+ } else if (propId == CSSPropertyWebkitMaskRepeat) {
+ propId1 = CSSPropertyWebkitMaskRepeatX;
+ propId2 = CSSPropertyWebkitMaskRepeatY;
+ }
+
+ while ((val = m_valueList->current())) {
+ RefPtr<CSSValue> currValue;
+ RefPtr<CSSValue> currValue2;
+
+ if (allowComma) {
+ if (val->unit != CSSParserValue::Operator || val->iValue != ',')
+ return false;
+ m_valueList->next();
+ allowComma = false;
+ } else {
+ allowComma = true;
+ switch (propId) {
+ case CSSPropertyBackgroundColor:
+ currValue = parseBackgroundColor();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyWebkitMaskAttachment:
+ if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) {
+ currValue = cssValuePool()->createIdentifierValue(val->id);
+ m_valueList->next();
+ }
+ break;
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyWebkitMaskImage:
+ if (parseFillImage(m_valueList.get(), currValue))
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskOrigin:
+ // The first three values here are deprecated and do not apply to the version of the property that has
+ // the -webkit- prefix removed.
+ if (val->id == CSSValueBorder || val->id == CSSValuePadding || val->id == CSSValueContent ||
+ val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox ||
+ ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) &&
+ (val->id == CSSValueText || val->id == CSSValueWebkitText))) {
+ currValue = cssValuePool()->createIdentifierValue(val->id);
+ m_valueList->next();
+ }
+ break;
+ case CSSPropertyBackgroundClip:
+ if (parseBackgroundClip(val, currValue, cssValuePool()))
+ m_valueList->next();
+ break;
+ case CSSPropertyBackgroundOrigin:
+ if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) {
+ currValue = cssValuePool()->createIdentifierValue(val->id);
+ m_valueList->next();
+ }
+ break;
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyWebkitMaskPosition:
+ parseFillPosition(m_valueList.get(), currValue, currValue2);
+ // parseFillPosition advances the m_valueList pointer
+ break;
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyWebkitMaskPositionX: {
+ currValue = parseFillPositionX(m_valueList.get());
+ if (currValue)
+ m_valueList->next();
+ break;
+ }
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyWebkitMaskPositionY: {
+ currValue = parseFillPositionY(m_valueList.get());
+ if (currValue)
+ m_valueList->next();
+ break;
+ }
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyWebkitMaskComposite:
+ if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) {
+ currValue = cssValuePool()->createIdentifierValue(val->id);
+ m_valueList->next();
+ }
+ break;
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyWebkitMaskRepeat:
+ parseFillRepeat(currValue, currValue2);
+ // parseFillRepeat advances the m_valueList pointer
+ break;
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitMaskSize: {
+ currValue = parseFillSize(propId, allowComma);
+ if (currValue)
+ m_valueList->next();
+ break;
+ }
+ }
+ if (!currValue)
+ return false;
+
+ if (value && !values) {
+ values = CSSValueList::createCommaSeparated();
+ values->append(value.release());
+ }
+
+ if (value2 && !values2) {
+ values2 = CSSValueList::createCommaSeparated();
+ values2->append(value2.release());
+ }
+
+ if (values)
+ values->append(currValue.release());
+ else
+ value = currValue.release();
+ if (currValue2) {
+ if (values2)
+ values2->append(currValue2.release());
+ else
+ value2 = currValue2.release();
+ }
+ }
+
+ // When parsing any fill shorthand property, we let it handle building up the lists for all
+ // properties.
+ if (inShorthand())
+ break;
+ }
+
+ if (values && values->length()) {
+ retValue1 = values.release();
+ if (values2 && values2->length())
+ retValue2 = values2.release();
+ return true;
+ }
+ if (value) {
+ retValue1 = value.release();
+ retValue2 = value2.release();
+ return true;
+ }
+ return false;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationDelay()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (validUnit(value, FTime, m_strict))
+ return createPrimitiveNumericValue(value);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationDirection()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->id == CSSValueNormal || value->id == CSSValueAlternate)
+ return cssValuePool()->createIdentifierValue(value->id);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationDuration()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (validUnit(value, FTime | FNonNeg, m_strict))
+ return createPrimitiveNumericValue(value);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth)
+ return cssValuePool()->createIdentifierValue(value->id);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->id == CSSValueInfinite)
+ return cssValuePool()->createIdentifierValue(value->id);
+ if (validUnit(value, FInteger | FNonNeg, m_strict))
+ return createPrimitiveNumericValue(value);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationName()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) {
+ if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) {
+ return cssValuePool()->createIdentifierValue(CSSValueNone);
+ } else {
+ return createPrimitiveStringValue(value);
+ }
+ }
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->id == CSSValueRunning || value->id == CSSValuePaused)
+ return cssValuePool()->createIdentifierValue(value->id);
+ return 0;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->unit != CSSPrimitiveValue::CSS_IDENT)
+ return 0;
+ int result = cssPropertyID(value->string);
+ if (result)
+ return cssValuePool()->createIdentifierValue(result);
+ if (equalIgnoringCase(value->string, "all"))
+ return cssValuePool()->createIdentifierValue(CSSValueAll);
+ if (equalIgnoringCase(value->string, "none"))
+ return cssValuePool()->createIdentifierValue(CSSValueNone);
+ return 0;
+}
+
+bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
+{
+ parseFillPosition(m_valueList.get(), value1, value2);
+
+ // now get z
+ if (m_valueList->current()) {
+ if (validUnit(m_valueList->current(), FLength, m_strict)) {
+ value3 = createPrimitiveNumericValue(m_valueList->current());
+ m_valueList->next();
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result)
+{
+ CSSParserValue* v = args->current();
+ if (!validUnit(v, FNumber, m_strict))
+ return false;
+ result = v->fValue;
+ v = args->next();
+ if (!v)
+ // The last number in the function has no comma after it, so we're done.
+ return true;
+ if (v->unit != CSSParserValue::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ return true;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction()
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut
+ || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd)
+ return cssValuePool()->createIdentifierValue(value->id);
+
+ // We must be a function.
+ if (value->unit != CSSParserValue::Function)
+ return 0;
+
+ CSSParserValueList* args = value->function->args.get();
+
+ if (equalIgnoringCase(value->function->name, "steps(")) {
+ // For steps, 1 or 2 params must be specified (comma-separated)
+ if (!args || (args->size() != 1 && args->size() != 3))
+ return 0;
+
+ // There are two values.
+ int numSteps;
+ bool stepAtStart = false;
+
+ CSSParserValue* v = args->current();
+ if (!validUnit(v, FInteger, m_strict))
+ return 0;
+ numSteps = clampToInteger(v->fValue);
+ if (numSteps < 1)
+ return 0;
+ v = args->next();
+
+ if (v) {
+ // There is a comma so we need to parse the second value
+ if (v->unit != CSSParserValue::Operator && v->iValue != ',')
+ return 0;
+ v = args->next();
+ if (v->id != CSSValueStart && v->id != CSSValueEnd)
+ return 0;
+ stepAtStart = v->id == CSSValueStart;
+ }
+
+ return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart);
+ }
+
+ if (equalIgnoringCase(value->function->name, "cubic-bezier(")) {
+ // For cubic bezier, 4 values must be specified.
+ if (!args || args->size() != 7)
+ return 0;
+
+ // There are two points specified. The values must be between 0 and 1.
+ double x1, y1, x2, y2;
+
+ if (!parseCubicBezierTimingFunctionValue(args, x1))
+ return 0;
+ if (!parseCubicBezierTimingFunctionValue(args, y1))
+ return 0;
+ if (!parseCubicBezierTimingFunctionValue(args, x2))
+ return 0;
+ if (!parseCubicBezierTimingFunctionValue(args, y2))
+ return 0;
+
+ return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2);
+ }
+
+ return 0;
+}
+
+bool CSSParser::parseAnimationProperty(int propId, RefPtr<CSSValue>& result)
+{
+ RefPtr<CSSValueList> values;
+ CSSParserValue* val;
+ RefPtr<CSSValue> value;
+ bool allowComma = false;
+
+ result = 0;
+
+ while ((val = m_valueList->current())) {
+ RefPtr<CSSValue> currValue;
+ if (allowComma) {
+ if (val->unit != CSSParserValue::Operator || val->iValue != ',')
+ return false;
+ m_valueList->next();
+ allowComma = false;
+ }
+ else {
+ switch (propId) {
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitTransitionDelay:
+ currValue = parseAnimationDelay();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationDirection:
+ currValue = parseAnimationDirection();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitTransitionDuration:
+ currValue = parseAnimationDuration();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationFillMode:
+ currValue = parseAnimationFillMode();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationIterationCount:
+ currValue = parseAnimationIterationCount();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationName:
+ currValue = parseAnimationName();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationPlayState:
+ currValue = parseAnimationPlayState();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitTransitionProperty:
+ currValue = parseAnimationProperty();
+ if (currValue)
+ m_valueList->next();
+ break;
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ currValue = parseAnimationTimingFunction();
+ if (currValue)
+ m_valueList->next();
+ break;
+ }
+
+ if (!currValue)
+ return false;
+
+ if (value && !values) {
+ values = CSSValueList::createCommaSeparated();
+ values->append(value.release());
+ }
+
+ if (values)
+ values->append(currValue.release());
+ else
+ value = currValue.release();
+
+ allowComma = true;
+ }
+
+ // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
+ // properties.
+ if (inShorthand())
+ break;
+ }
+
+ if (values && values->length()) {
+ result = values.release();
+ return true;
+ }
+ if (value) {
+ result = value.release();
+ return true;
+ }
+ return false;
+}
+
+#if ENABLE(CSS_GRID_LAYOUT)
+bool CSSParser::parseGridTrackList(int propId, bool important)
+{
+ CSSParserValue* value = m_valueList->current();
+ if (value->id == CSSValueNone) {
+ if (m_valueList->next())
+ return false;
+
+ addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
+ return true;
+ }
+
+ RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
+ while (value) {
+ bool valid = validUnit(value, FLength | FPercent, m_strict) || value->id == CSSValueAuto;
+ if (!valid)
+ return false;
+
+ RefPtr<CSSPrimitiveValue> primitiveValue = value->id == CSSValueAuto ? cssValuePool()->createIdentifierValue(CSSValueAuto) : createPrimitiveNumericValue(value);
+ values->append(primitiveValue.release());
+ value = m_valueList->next();
+ }
+ addProperty(propId, values.release(), important);
+ return true;
+}
+#endif
+
+
+
+#if ENABLE(DASHBOARD_SUPPORT)
+
+#define DASHBOARD_REGION_NUM_PARAMETERS 6
+#define DASHBOARD_REGION_SHORT_NUM_PARAMETERS 2
+
+static CSSParserValue* skipCommaInDashboardRegion(CSSParserValueList *args)
+{
+ if (args->size() == (DASHBOARD_REGION_NUM_PARAMETERS*2-1) ||
+ args->size() == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
+ CSSParserValue* current = args->current();
+ if (current->unit == CSSParserValue::Operator && current->iValue == ',')
+ return args->next();
+ }
+ return args->current();
+}
+
+bool CSSParser::parseDashboardRegions(int propId, bool important)
+{
+ bool valid = true;
+
+ CSSParserValue* value = m_valueList->current();
+
+ if (value->id == CSSValueNone) {
+ if (m_valueList->next())
+ return false;
+ addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
+ return valid;
+ }
+
+ RefPtr<DashboardRegion> firstRegion = DashboardRegion::create();
+ DashboardRegion* region = 0;
+
+ while (value) {
+ if (region == 0) {
+ region = firstRegion.get();
+ } else {
+ RefPtr<DashboardRegion> nextRegion = DashboardRegion::create();
+ region->m_next = nextRegion;
+ region = nextRegion.get();
+ }
+
+ if (value->unit != CSSParserValue::Function) {
+ valid = false;
+ break;
+ }
+
+ // Commas count as values, so allow:
+ // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
+ // dashboard-region(label, type, t, r, b, l) or dashboard-region(label type t r b l)
+ // also allow
+ // dashboard-region(label, type) or dashboard-region(label type)
+ // dashboard-region(label, type) or dashboard-region(label type)
+ CSSParserValueList* args = value->function->args.get();
+ if (!equalIgnoringCase(value->function->name, "dashboard-region(") || !args) {
+ valid = false;
+ break;
+ }
+
+ int numArgs = args->size();
+ if ((numArgs != DASHBOARD_REGION_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_NUM_PARAMETERS*2-1)) &&
+ (numArgs != DASHBOARD_REGION_SHORT_NUM_PARAMETERS && numArgs != (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1))) {
+ valid = false;
+ break;
+ }
+
+ // First arg is a label.
+ CSSParserValue* arg = args->current();
+ if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
+ valid = false;
+ break;
+ }
+
+ region->m_label = arg->string;
+
+ // Second arg is a type.
+ arg = args->next();
+ arg = skipCommaInDashboardRegion(args);
+ if (arg->unit != CSSPrimitiveValue::CSS_IDENT) {
+ valid = false;
+ break;
+ }
+
+ if (equalIgnoringCase(arg->string, "circle"))
+ region->m_isCircle = true;
+ else if (equalIgnoringCase(arg->string, "rectangle"))
+ region->m_isRectangle = true;
+ else {
+ valid = false;
+ break;
+ }
+
+ region->m_geometryType = arg->string;
+
+ if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) {
+ // This originally used CSSValueInvalid by accident. It might be more logical to use something else.
+ RefPtr<CSSPrimitiveValue> amount = cssValuePool()->createIdentifierValue(CSSValueInvalid);
+
+ region->setTop(amount);
+ region->setRight(amount);
+ region->setBottom(amount);
+ region->setLeft(amount);
+ } else {
+ // Next four arguments must be offset numbers
+ int i;
+ for (i = 0; i < 4; i++) {
+ arg = args->next();
+ arg = skipCommaInDashboardRegion(args);
+
+ valid = arg->id == CSSValueAuto || validUnit(arg, FLength, m_strict);
+ if (!valid)
+ break;
+
+ RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ?
+ cssValuePool()->createIdentifierValue(CSSValueAuto) :
+ createPrimitiveNumericValue(arg);
+
+ if (i == 0)
+ region->setTop(amount);
+ else if (i == 1)
+ region->setRight(amount);
+ else if (i == 2)
+ region->setBottom(amount);
+ else
+ region->setLeft(amount);
+ }
+ }
+
+ if (args->next())
+ return false;
+
+ value = m_valueList->next();
+ }
+
+ if (valid)
+ addProperty(propId, cssValuePool()->createValue(firstRegion.release()), important);
+
+ return valid;
+}
+
+#endif /* ENABLE(DASHBOARD_SUPPORT) */
+
+PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bool counters)
+{
+ unsigned numArgs = args->size();
+ if (counters && numArgs != 3 && numArgs != 5)
+ return 0;
+ if (!counters && numArgs != 1 && numArgs != 3)
+ return 0;
+
+ CSSParserValue* i = args->current();
+ if (i->unit != CSSPrimitiveValue::CSS_IDENT)
+ return 0;
+ RefPtr<CSSPrimitiveValue> identifier = createPrimitiveStringValue(i);
+
+ RefPtr<CSSPrimitiveValue> separator;
+ if (!counters)
+ separator = cssValuePool()->createValue(String(), CSSPrimitiveValue::CSS_STRING);
+ else {
+ i = args->next();
+ if (i->unit != CSSParserValue::Operator || i->iValue != ',')
+ return 0;
+
+ i = args->next();
+ if (i->unit != CSSPrimitiveValue::CSS_STRING)
+ return 0;
+
+ separator = createPrimitiveStringValue(i);
+ }
+
+ RefPtr<CSSPrimitiveValue> listStyle;
+ i = args->next();
+ if (!i) // Make the list style default decimal
+ listStyle = cssValuePool()->createIdentifierValue(CSSValueDecimal);
+ else {
+ if (i->unit != CSSParserValue::Operator || i->iValue != ',')
+ return 0;
+
+ i = args->next();
+ if (i->unit != CSSPrimitiveValue::CSS_IDENT)
+ return 0;
+
+ int listStyleID = 0;
+ if (i->id == CSSValueNone || (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha))
+ listStyleID = i->id;
+ else
+ return 0;
+
+ listStyle = cssValuePool()->createIdentifierValue(listStyleID);
+ }
+
+ return cssValuePool()->createValue(Counter::create(identifier.release(), listStyle.release(), separator.release()));
+}
+
+bool CSSParser::parseShape(int propId, bool important)
+{
+ CSSParserValue* value = m_valueList->current();
+ CSSParserValueList* args = value->function->args.get();
+
+ if (!equalIgnoringCase(value->function->name, "rect(") || !args)
+ return false;
+
+ // rect(t, r, b, l) || rect(t r b l)
+ if (args->size() != 4 && args->size() != 7)
+ return false;
+ RefPtr<Rect> rect = Rect::create();
+ bool valid = true;
+ int i = 0;
+ CSSParserValue* a = args->current();
+ while (a) {
+ valid = a->id == CSSValueAuto || validUnit(a, FLength, m_strict);
+ if (!valid)
+ break;
+ RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ?
+ cssValuePool()->createIdentifierValue(CSSValueAuto) :
+ createPrimitiveNumericValue(a);
+ if (i == 0)
+ rect->setTop(length);
+ else if (i == 1)
+ rect->setRight(length);
+ else if (i == 2)
+ rect->setBottom(length);
+ else
+ rect->setLeft(length);
+ a = args->next();
+ if (a && args->size() == 7) {
+ if (a->unit == CSSParserValue::Operator && a->iValue == ',') {
+ a = args->next();
+ } else {
+ valid = false;
+ break;
+ }
+ }
+ i++;
+ }
+ if (valid) {
+ addProperty(propId, cssValuePool()->createValue(rect.release()), important);
+ m_valueList->next();
+ return true;
+ }
+ return false;
+}
+
+PassRefPtr<CSSWrapShape> CSSParser::parseWrapShapeRect(CSSParserValueList* args)
+{
+ ASSERT(args);
+
+ // rect(x, y, width, height, [[rx], ry])
+ if (args->size() != 7 && args->size() != 9 && args->size() != 11)
+ return 0;
+
+ RefPtr<CSSWrapShapeRect> shape = CSSWrapShapeRect::create();
+
+ unsigned argumentNumber = 0;
+ CSSParserValue* argument = args->current();
+ while (argument) {
+ if (!validUnit(argument, FLength, m_strict))
+ return 0;
+
+ RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
+ ASSERT(argumentNumber < 6);
+ switch (argumentNumber) {
+ case 0:
+ shape->setLeft(length);
+ break;
+ case 1:
+ shape->setTop(length);
+ break;
+ case 2:
+ shape->setWidth(length);
+ break;
+ case 3:
+ shape->setHeight(length);
+ break;
+ case 4:
+ shape->setRadiusX(length);
+ break;
+ case 5:
+ shape->setRadiusY(length);
+ break;
+ }
+ argument = args->next();
+ if (argument) {
+ if (argument->unit != CSSParserValue::Operator || argument->iValue != ',')
+ return 0;
+
+ argument = args->next();
+ }
+ argumentNumber++;
+ }
+
+ if (argumentNumber < 4)
+ return 0;
+ return shape;
+}
+
+PassRefPtr<CSSWrapShape> CSSParser::parseWrapShapeCircle(CSSParserValueList* args)
+{
+ ASSERT(args);
+
+ // circle(x, y, r)
+ if (args->size() != 5)
+ return 0;
+
+ RefPtr<CSSWrapShapeCircle> shape = CSSWrapShapeCircle::create();
+
+ unsigned argumentNumber = 0;
+ CSSParserValue* argument = args->current();
+ while (argument) {
+ if (!validUnit(argument, FLength, m_strict))
+ return 0;
+
+ RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
+ ASSERT(argumentNumber < 3);
+ switch (argumentNumber) {
+ case 0:
+ shape->setLeft(length);
+ break;
+ case 1:
+ shape->setTop(length);
+ break;
+ case 2:
+ shape->setRadius(length);
+ break;
+ }
+
+ argument = args->next();
+ if (argument) {
+ if (argument->unit != CSSParserValue::Operator || argument->iValue != ',')
+ return 0;
+ argument = args->next();
+ }
+ argumentNumber++;
+ }
+
+ if (argumentNumber < 3)
+ return 0;
+ return shape;
+}
+
+PassRefPtr<CSSWrapShape> CSSParser::parseWrapShapeEllipse(CSSParserValueList* args)
+{
+ ASSERT(args);
+
+ // ellipse(x, y, rx, ry)
+ if (args->size() != 7)
+ return 0;
+
+ RefPtr<CSSWrapShapeEllipse> shape = CSSWrapShapeEllipse::create();
+ unsigned argumentNumber = 0;
+ CSSParserValue* argument = args->current();
+ while (argument) {
+ if (!validUnit(argument, FLength, m_strict))
+ return 0;
+
+ RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument);
+ ASSERT(argumentNumber < 4);
+ switch (argumentNumber) {
+ case 0:
+ shape->setLeft(length);
+ break;
+ case 1:
+ shape->setTop(length);
+ break;
+ case 2:
+ shape->setRadiusX(length);
+ break;
+ case 3:
+ shape->setRadiusY(length);
+ break;
+ }
+
+ argument = args->next();
+ if (argument) {
+ if (argument->unit != CSSParserValue::Operator || argument->iValue != ',')
+ return 0;
+ argument = args->next();
+ }
+ argumentNumber++;
+ }
+
+ if (argumentNumber < 4)
+ return 0;
+ return shape;
+}
+
+PassRefPtr<CSSWrapShape> CSSParser::parseWrapShapePolygon(CSSParserValueList* args)
+{
+ ASSERT(args);
+
+ unsigned size = args->size();
+ if (!size)
+ return 0;
+
+ RefPtr<CSSWrapShapePolygon> shape = CSSWrapShapePolygon::create();
+
+ CSSParserValue* argument = args->current();
+ if (argument->id == CSSValueEvenodd || argument->id == CSSValueNonzero) {
+ shape->setWindRule(argument->id == CSSValueEvenodd ? RULE_EVENODD : RULE_NONZERO);
+
+ CSSParserValue* comma = args->next();
+ if (!comma || comma->unit != CSSParserValue::Operator || comma->iValue != ',')
+ return 0;
+
+ argument = args->next();
+ size -= 2;
+ }
+
+ // <length>, <length> ... <length>, <length> -> each pair has 3 elements
+ if (!size || (size % 3))
+ return 0;
+
+ CSSParserValue* argumentX = argument;
+ while (argumentX) {
+ if (!validUnit(argumentX, FLength, m_strict))
+ return 0;
+
+ CSSParserValue* comma = args->next();
+ if (!comma || comma->unit != CSSParserValue::Operator || comma->iValue != ',')
+ return 0;
+
+ CSSParserValue* argumentY = args->next();
+ if (!argumentY || !validUnit(argumentY, FLength, m_strict))
+ return 0;
+
+ RefPtr<CSSPrimitiveValue> xLength = createPrimitiveNumericValue(argumentX);
+ RefPtr<CSSPrimitiveValue> yLength = createPrimitiveNumericValue(argumentY);
+
+ shape->appendPoint(xLength.release(), yLength.release());
+
+ argumentX = args->next();
+ }
+
+ return shape;
+}
+
+bool CSSParser::parseWrapShape(bool shapeInside, bool important)
+{
+ CSSParserValue* value = m_valueList->current();
+ CSSParserValueList* args = value->function->args.get();
+
+ if (!args)
+ return false;
+
+ RefPtr<CSSWrapShape> shape;
+
+ if (equalIgnoringCase(value->function->name, "rect("))
+ shape = parseWrapShapeRect(args);
+ else if (equalIgnoringCase(value->function->name, "circle("))
+ shape = parseWrapShapeCircle(args);
+ else if (equalIgnoringCase(value->function->name, "ellipse("))
+ shape = parseWrapShapeEllipse(args);
+ else if (equalIgnoringCase(value->function->name, "polygon("))
+ shape = parseWrapShapePolygon(args);
+
+ if (shape) {
+ addProperty(shapeInside ? CSSPropertyWebkitWrapShapeInside : CSSPropertyWebkitWrapShapeOutside, cssValuePool()->createValue(shape.release()), important);
+ m_valueList->next();
+ return true;
+ }
+
+ return false;
+}
+
+// [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family'
+bool CSSParser::parseFont(bool important)
+{
+ bool valid = true;
+ bool styleImplicit = true;
+ bool variantImplicit = true;
+ bool weightImplicit = true;
+ bool lineHeightImplicit = true;
+ int valueOrdinal = 0;
+
+ CSSParserValue *value = m_valueList->current();
+ RefPtr<FontValue> font = FontValue::create();
+ // Optional font-style, font-variant and font-weight.
+ while (value) {
+ int id = value->id;
+ if (id) {
+ if (id == CSSValueNormal) {
+ // It's the initial value for all three, so mark the corresponding longhand as explicit.
+ switch (valueOrdinal) {
+ case 0:
+ styleImplicit = false;
+ break;
+ case 1:
+ variantImplicit = false;
+ break;
+ case 2:
+ weightImplicit = false;
+ break;
+ }
+ } else if (id == CSSValueItalic || id == CSSValueOblique) {
+ if (font->style)
+ return false;
+ font->style = cssValuePool()->createIdentifierValue(id);
+ styleImplicit = false;
+ } else if (id == CSSValueSmallCaps) {
+ if (font->variant)
+ return false;
+ font->variant = cssValuePool()->createIdentifierValue(id);
+ variantImplicit = false;
+ } else if (id >= CSSValueBold && id <= CSSValueLighter) {
+ if (font->weight)
+ return false;
+ font->weight = cssValuePool()->createIdentifierValue(id);
+ weightImplicit = false;
+ } else
+ valid = false;
+ } else if (!font->weight && validUnit(value, FInteger | FNonNeg, true)) {
+ int weight = static_cast<int>(value->fValue);
+ int val = 0;
+ if (weight == 100)
+ val = CSSValue100;
+ else if (weight == 200)
+ val = CSSValue200;
+ else if (weight == 300)
+ val = CSSValue300;
+ else if (weight == 400)
+ val = CSSValue400;
+ else if (weight == 500)
+ val = CSSValue500;
+ else if (weight == 600)
+ val = CSSValue600;
+ else if (weight == 700)
+ val = CSSValue700;
+ else if (weight == 800)
+ val = CSSValue800;
+ else if (weight == 900)
+ val = CSSValue900;
+
+ if (val) {
+ font->weight = cssValuePool()->createIdentifierValue(val);
+ weightImplicit = false;
+ } else
+ valid = false;
+ } else {
+ valid = false;
+ }
+ if (!valid)
+ break;
+ value = m_valueList->next();
+ ++valueOrdinal;
+ }
+ if (!value)
+ return false;
+
+ // Set undefined values to default.
+ if (!font->style)
+ font->style = cssValuePool()->createIdentifierValue(CSSValueNormal);
+ if (!font->variant)
+ font->variant = cssValuePool()->createIdentifierValue(CSSValueNormal);
+ if (!font->weight)
+ font->weight = cssValuePool()->createIdentifierValue(CSSValueNormal);
+
+ // Now a font size _must_ come.
+ // <absolute-size> | <relative-size> | <length> | <percentage> | inherit
+ if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger)
+ font->size = cssValuePool()->createIdentifierValue(value->id);
+ else if (validUnit(value, FLength | FPercent | FNonNeg, m_strict))
+ font->size = createPrimitiveNumericValue(value);
+ value = m_valueList->next();
+ if (!font->size || !value)
+ return false;
+
+ if (value->unit == CSSParserValue::Operator && value->iValue == '/') {
+ // The line-height property.
+ value = m_valueList->next();
+ if (!value)
+ return false;
+ if (value->id == CSSValueNormal) {
+ // Default value, just mark the property as explicit.
+ lineHeightImplicit = false;
+ } else if (validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict)) {
+ font->lineHeight = createPrimitiveNumericValue(value);
+ lineHeightImplicit = false;
+ } else
+ return false;
+ value = m_valueList->next();
+ if (!value)
+ return false;
+ }
+
+ if (!font->lineHeight)
+ font->lineHeight = cssValuePool()->createIdentifierValue(CSSValueNormal);
+
+ // Font family must come now.
+ font->family = parseFontFamily();
+
+ if (m_valueList->current() || !font->family)
+ return false;
+
+ ShorthandScope scope(this, CSSPropertyFont);
+ addProperty(CSSPropertyFontFamily, font->family, important);
+ addProperty(CSSPropertyFontSize, font->size, important);
+ addProperty(CSSPropertyFontStyle, font->style, important, styleImplicit);
+ addProperty(CSSPropertyFontVariant, font->variant, important, variantImplicit);
+ addProperty(CSSPropertyFontWeight, font->weight, important, weightImplicit);
+ addProperty(CSSPropertyLineHeight, font->lineHeight, important, lineHeightImplicit);
+
+ // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires that
+ // "font-stretch", "font-size-adjust", and "font-kerning" be reset to their initial values
+ // but we don't seem to support them at the moment. They should also be added here once implemented.
+
+ return true;
+}
+
+PassRefPtr<CSSValueList> CSSParser::parseFontFamily()
+{
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ CSSParserValue* value = m_valueList->current();
+
+ FontFamilyValue* currFamily = 0;
+ while (value) {
+ CSSParserValue* nextValue = m_valueList->next();
+ bool nextValBreaksFont = !nextValue ||
+ (nextValue->unit == CSSParserValue::Operator && nextValue->iValue == ',');
+ bool nextValIsFontName = nextValue &&
+ ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) ||
+ (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT));
+
+ if (value->id >= CSSValueSerif && value->id <= CSSValueWebkitBody) {
+ if (currFamily)
+ currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
+ else if (nextValBreaksFont || !nextValIsFontName)
+ list->append(cssValuePool()->createIdentifierValue(value->id));
+ else {
+ RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
+ currFamily = newFamily.get();
+ list->append(newFamily.release());
+ }
+ } else if (value->unit == CSSPrimitiveValue::CSS_STRING) {
+ // Strings never share in a family name.
+ currFamily = 0;
+ list->append(FontFamilyValue::create(value->string));
+ } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) {
+ if (currFamily)
+ currFamily->appendSpaceSeparated(value->string.characters, value->string.length);
+ else if (nextValBreaksFont || !nextValIsFontName)
+ list->append(FontFamilyValue::create(value->string));
+ else {
+ RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string);
+ currFamily = newFamily.get();
+ list->append(newFamily.release());
+ }
+ } else {
+ break;
+ }
+
+ if (!nextValue)
+ break;
+
+ if (nextValBreaksFont) {
+ value = m_valueList->next();
+ currFamily = 0;
+ }
+ else if (nextValIsFontName)
+ value = nextValue;
+ else
+ break;
+ }
+ if (!list->length())
+ list = 0;
+ return list.release();
+}
+
+bool CSSParser::parseFontStyle(bool important)
+{
+ RefPtr<CSSValueList> values;
+ if (m_valueList->size() > 1)
+ values = CSSValueList::createCommaSeparated();
+ CSSParserValue* val;
+ bool expectComma = false;
+ while ((val = m_valueList->current())) {
+ RefPtr<CSSPrimitiveValue> parsedValue;
+ if (!expectComma) {
+ expectComma = true;
+ if (val->id == CSSValueNormal || val->id == CSSValueItalic || val->id == CSSValueOblique)
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ else if (val->id == CSSValueAll && !values) {
+ // 'all' is only allowed in @font-face and with no other values. Make a value list to
+ // indicate that we are in the @font-face case.
+ values = CSSValueList::createCommaSeparated();
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ }
+ } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
+ expectComma = false;
+ m_valueList->next();
+ continue;
+ }
+
+ if (!parsedValue)
+ return false;
+
+ m_valueList->next();
+
+ if (values)
+ values->append(parsedValue.release());
+ else {
+ addProperty(CSSPropertyFontStyle, parsedValue.release(), important);
+ return true;
+ }
+ }
+
+ if (values && values->length()) {
+ m_hasFontFaceOnlyValues = true;
+ addProperty(CSSPropertyFontStyle, values.release(), important);
+ return true;
+ }
+
+ return false;
+}
+
+bool CSSParser::parseFontVariant(bool important)
+{
+ RefPtr<CSSValueList> values;
+ if (m_valueList->size() > 1)
+ values = CSSValueList::createCommaSeparated();
+ CSSParserValue* val;
+ bool expectComma = false;
+ while ((val = m_valueList->current())) {
+ RefPtr<CSSPrimitiveValue> parsedValue;
+ if (!expectComma) {
+ expectComma = true;
+ if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps)
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ else if (val->id == CSSValueAll && !values) {
+ // 'all' is only allowed in @font-face and with no other values. Make a value list to
+ // indicate that we are in the @font-face case.
+ values = CSSValueList::createCommaSeparated();
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ }
+ } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
+ expectComma = false;
+ m_valueList->next();
+ continue;
+ }
+
+ if (!parsedValue)
+ return false;
+
+ m_valueList->next();
+
+ if (values)
+ values->append(parsedValue.release());
+ else {
+ addProperty(CSSPropertyFontVariant, parsedValue.release(), important);
+ return true;
+ }
+ }
+
+ if (values && values->length()) {
+ m_hasFontFaceOnlyValues = true;
+ addProperty(CSSPropertyFontVariant, values.release(), important);
+ return true;
+ }
+
+ return false;
+}
+
+bool CSSParser::parseFontWeight(bool important)
+{
+ RefPtr<CSSValueList> values;
+ if (m_valueList->size() > 1)
+ values = CSSValueList::createCommaSeparated();
+ CSSParserValue* val;
+ bool expectComma = false;
+ while ((val = m_valueList->current())) {
+ RefPtr<CSSPrimitiveValue> parsedValue;
+ if (!expectComma) {
+ expectComma = true;
+ if (val->unit == CSSPrimitiveValue::CSS_IDENT) {
+ if (val->id >= CSSValueNormal && val->id <= CSSValue900)
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ else if (val->id == CSSValueAll && !values) {
+ // 'all' is only allowed in @font-face and with no other values. Make a value list to
+ // indicate that we are in the @font-face case.
+ values = CSSValueList::createCommaSeparated();
+ parsedValue = cssValuePool()->createIdentifierValue(val->id);
+ }
+ } else if (validUnit(val, FInteger | FNonNeg, false)) {
+ int weight = static_cast<int>(val->fValue);
+ if (!(weight % 100) && weight >= 100 && weight <= 900)
+ parsedValue = cssValuePool()->createIdentifierValue(CSSValue100 + weight / 100 - 1);
+ }
+ } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
+ expectComma = false;
+ m_valueList->next();
+ continue;
+ }
+
+ if (!parsedValue)
+ return false;
+
+ m_valueList->next();
+
+ if (values)
+ values->append(parsedValue.release());
+ else {
+ addProperty(CSSPropertyFontWeight, parsedValue.release(), important);
+ return true;
+ }
+ }
+
+ if (values && values->length()) {
+ m_hasFontFaceOnlyValues = true;
+ addProperty(CSSPropertyFontWeight, values.release(), important);
+ return true;
+ }
+
+ return false;
+}
+
+bool CSSParser::parseFontFaceSrcURI(CSSValueList* valueList)
+{
+ // FIXME: The completeURL call should be done when using the CSSFontFaceSrcValue,
+ // not when creating it.
+ RefPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(m_styleSheet->completeURL(m_valueList->current()->string)));
+
+ CSSParserValue* value = m_valueList->next();
+ if (!value) {
+ valueList->append(uriValue.release());
+ return true;
+ }
+ if (value->unit == CSSParserValue::Operator && value->iValue == ',') {
+ m_valueList->next();
+ valueList->append(uriValue.release());
+ return true;
+ }
+
+ if (value->unit != CSSParserValue::Function || !equalIgnoringCase(value->function->name, "format("))
+ return false;
+
+ // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20111004/ says that format() contains a comma-separated list of strings,
+ // but CSSFontFaceSrcValue stores only one format. Allowing one format for now.
+ CSSParserValueList* args = value->function->args.get();
+ if (!args || args->size() != 1 || (args->current()->unit != CSSPrimitiveValue::CSS_STRING && args->current()->unit != CSSPrimitiveValue::CSS_IDENT))
+ return false;
+ uriValue->setFormat(args->current()->string);
+ valueList->append(uriValue.release());
+ value = m_valueList->next();
+ if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
+ m_valueList->next();
+ return true;
+}
+
+bool CSSParser::parseFontFaceSrcLocal(CSSValueList* valueList)
+{
+ CSSParserValueList* args = m_valueList->current()->function->args.get();
+ if (!args || !args->size())
+ return false;
+
+ if (args->size() == 1 && args->current()->unit == CSSPrimitiveValue::CSS_STRING)
+ valueList->append(CSSFontFaceSrcValue::createLocal(args->current()->string));
+ else if (args->current()->unit == CSSPrimitiveValue::CSS_IDENT) {
+ StringBuilder builder;
+ for (CSSParserValue* localValue = args->current(); localValue; localValue = args->next()) {
+ if (localValue->unit != CSSPrimitiveValue::CSS_IDENT)
+ return false;
+ if (!builder.isEmpty())
+ builder.append(' ');
+ builder.append(localValue->string);
+ }
+ valueList->append(CSSFontFaceSrcValue::createLocal(builder.toString()));
+ } else
+ return false;
+
+ if (CSSParserValue* value = m_valueList->next()) {
+ if (value->unit == CSSParserValue::Operator && value->iValue == ',')
+ m_valueList->next();
+ }
+ return true;
+}
+
+bool CSSParser::parseFontFaceSrc()
+{
+ RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
+
+ while (CSSParserValue* value = m_valueList->current()) {
+ if (value->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
+ if (!parseFontFaceSrcURI(values.get()))
+ return false;
+ } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "local(")) {
+ if (!parseFontFaceSrcLocal(values.get()))
+ return false;
+ } else
+ return false;
+ }
+ if (!values->length())
+ return false;
+
+ addProperty(CSSPropertySrc, values.release(), m_important);
+ m_valueList->next();
+ return true;
+}
+
+bool CSSParser::parseFontFaceUnicodeRange()
+{
+ RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated();
+ bool failed = false;
+ bool operatorExpected = false;
+ for (; m_valueList->current(); m_valueList->next(), operatorExpected = !operatorExpected) {
+ if (operatorExpected) {
+ if (m_valueList->current()->unit == CSSParserValue::Operator && m_valueList->current()->iValue == ',')
+ continue;
+ failed = true;
+ break;
+ }
+ if (m_valueList->current()->unit != CSSPrimitiveValue::CSS_UNICODE_RANGE) {
+ failed = true;
+ break;
+ }
+
+ String rangeString = m_valueList->current()->string;
+ UChar32 from = 0;
+ UChar32 to = 0;
+ unsigned length = rangeString.length();
+
+ if (length < 3) {
+ failed = true;
+ break;
+ }
+
+ unsigned i = 2;
+ while (i < length) {
+ UChar c = rangeString[i];
+ if (c == '-' || c == '?')
+ break;
+ from *= 16;
+ if (c >= '0' && c <= '9')
+ from += c - '0';
+ else if (c >= 'A' && c <= 'F')
+ from += 10 + c - 'A';
+ else if (c >= 'a' && c <= 'f')
+ from += 10 + c - 'a';
+ else {
+ failed = true;
+ break;
+ }
+ i++;
+ }
+ if (failed)
+ break;
+
+ if (i == length)
+ to = from;
+ else if (rangeString[i] == '?') {
+ unsigned span = 1;
+ while (i < length && rangeString[i] == '?') {
+ span *= 16;
+ from *= 16;
+ i++;
+ }
+ if (i < length)
+ failed = true;
+ to = from + span - 1;
+ } else {
+ if (length < i + 2) {
+ failed = true;
+ break;
+ }
+ i++;
+ while (i < length) {
+ UChar c = rangeString[i];
+ to *= 16;
+ if (c >= '0' && c <= '9')
+ to += c - '0';
+ else if (c >= 'A' && c <= 'F')
+ to += 10 + c - 'A';
+ else if (c >= 'a' && c <= 'f')
+ to += 10 + c - 'a';
+ else {
+ failed = true;
+ break;
+ }
+ i++;
+ }
+ if (failed)
+ break;
+ }
+ if (from <= to)
+ values->append(CSSUnicodeRangeValue::create(from, to));
+ }
+ if (failed || !values->length())
+ return false;
+ addProperty(CSSPropertyUnicodeRange, values.release(), m_important);
+ return true;
+}
+
+// Returns the number of characters which form a valid double
+// and are terminated by the given terminator character
+static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator)
+{
+ int length = end - string;
+ if (length < 1)
+ return 0;
+
+ bool decimalMarkSeen = false;
+ int processedLength = 0;
+
+ for (int i = 0; i < length; ++i) {
+ if (string[i] == terminator) {
+ processedLength = i;
+ break;
+ }
+ if (!isASCIIDigit(string[i])) {
+ if (!decimalMarkSeen && string[i] == '.')
+ decimalMarkSeen = true;
+ else
+ return 0;
+ }
+ }
+
+ if (decimalMarkSeen && processedLength == 1)
+ return 0;
+
+ return processedLength;
+}
+
+// Returns the number of characters consumed for parsing a valid double
+// terminated by the given terminator character
+static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value)
+{
+ int length = checkForValidDouble(string, end, terminator);
+ if (!length)
+ return 0;
+
+ int position = 0;
+ double localValue = 0;
+
+ // The consumed characters here are guaranteed to be
+ // ASCII digits with or without a decimal mark
+ for (; position < length; ++position) {
+ if (string[position] == '.')
+ break;
+ localValue = localValue * 10 + string[position] - '0';
+ }
+
+ if (++position == length) {
+ value = localValue;
+ return length;
+ }
+
+ double fraction = 0;
+ double scale = 1;
+
+ while (position < length && scale < MAX_SCALE) {
+ fraction = fraction * 10 + string[position++] - '0';
+ scale *= 10;
+ }
+
+ value = localValue + fraction / scale;
+ return length;
+}
+
+static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value)
+{
+ const UChar* current = string;
+ double localValue = 0;
+ bool negative = false;
+ while (current != end && isHTMLSpace(*current))
+ current++;
+ if (current != end && *current == '-') {
+ negative = true;
+ current++;
+ }
+ if (current == end || !isASCIIDigit(*current))
+ return false;
+ while (current != end && isASCIIDigit(*current)) {
+ double newValue = localValue * 10 + *current++ - '0';
+ if (newValue >= 255) {
+ // Clamp values at 255.
+ localValue = 255;
+ while (current != end && isASCIIDigit(*current))
+ ++current;
+ break;
+ }
+ localValue = newValue;
+ }
+
+ if (current == end)
+ return false;
+
+ if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%'))
+ return false;
+
+ if (*current == '.') {
+ // We already parsed the integral part, try to parse
+ // the fraction part of the percentage value.
+ double percentage = 0;
+ int numCharactersParsed = parseDouble(current, end, '%', percentage);
+ if (!numCharactersParsed)
+ return false;
+ current += numCharactersParsed;
+ if (*current != '%')
+ return false;
+ localValue += percentage;
+ }
+
+ if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%')
+ return false;
+
+ if (*current == '%') {
+ expect = CSSPrimitiveValue::CSS_PERCENTAGE;
+ localValue = localValue / 100.0 * 256.0;
+ // Clamp values at 255 for percentages over 100%
+ if (localValue > 255)
+ localValue = 255;
+ current++;
+ } else
+ expect = CSSPrimitiveValue::CSS_NUMBER;
+
+ while (current != end && isHTMLSpace(*current))
+ current++;
+ if (current == end || *current++ != terminator)
+ return false;
+ // Clamp negative values at zero.
+ value = negative ? 0 : static_cast<int>(localValue);
+ string = current;
+ return true;
+}
+
+static inline bool isTenthAlpha(const UChar* string, const int length)
+{
+ // "0.X"
+ if (length == 3 && string[0] == '0' && string[1] == '.' && isASCIIDigit(string[2]))
+ return true;
+
+ // ".X"
+ if (length == 2 && string[0] == '.' && isASCIIDigit(string[1]))
+ return true;
+
+ return false;
+}
+
+static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value)
+{
+ while (string != end && isHTMLSpace(*string))
+ string++;
+
+ bool negative = false;
+
+ if (string != end && *string == '-') {
+ negative = true;
+ string++;
+ }
+
+ value = 0;
+
+ int length = end - string;
+ if (length < 2)
+ return false;
+
+ if (string[length - 1] != terminator)
+ return false;
+
+ if (string[0] != '0' && string[0] != '1' && string[0] != '.') {
+ if (checkForValidDouble(string, end, terminator)) {
+ value = negative ? 0 : 255;
+ string = end;
+ return true;
+ }
+ return false;
+ }
+
+ if (length == 2 && string[0] != '.') {
+ value = !negative && string[0] == '1' ? 255 : 0;
+ string = end;
+ return true;
+ }
+
+ if (isTenthAlpha(string, length - 1)) {
+ static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 };
+ value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0'];
+ string = end;
+ return true;
+ }
+
+ double alpha = 0;
+ if (!parseDouble(string, end, terminator, alpha))
+ return false;
+ value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0));
+ string = end;
+ return true;
+}
+
+static inline bool mightBeRGBA(const UChar* characters, unsigned length)
+{
+ if (length < 5)
+ return false;
+ return characters[4] == '('
+ && (characters[0] | 0x20) == 'r'
+ && (characters[1] | 0x20) == 'g'
+ && (characters[2] | 0x20) == 'b'
+ && (characters[3] | 0x20) == 'a';
+}
+
+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';
+}
+
+bool CSSParser::fastParseColor(RGBA32& rgb, const String& name, bool strict)
+{
+ const UChar* characters = name.characters();
+ unsigned length = name.length();
+ CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN;
+
+ if (!strict && length >= 3) {
+ if (name[0] == '#') {
+ if (Color::parseHexColor(characters + 1, length - 1, rgb))
+ return true;
+ } else {
+ if (Color::parseHexColor(characters, length, rgb))
+ return true;
+ }
+ }
+
+ // Try rgba() syntax.
+ if (mightBeRGBA(characters, length)) {
+ const UChar* current = characters + 5;
+ const UChar* end = characters + length;
+ int red;
+ int green;
+ int blue;
+ int alpha;
+
+ if (!parseColorIntOrPercentage(current, end, ',', expect, red))
+ return false;
+ if (!parseColorIntOrPercentage(current, end, ',', expect, green))
+ return false;
+ if (!parseColorIntOrPercentage(current, end, ',', expect, blue))
+ return false;
+ if (!parseAlphaValue(current, end, ')', alpha))
+ return false;
+ if (current != end)
+ return false;
+ rgb = makeRGBA(red, green, blue, alpha);
+ return true;
+ }
+
+ // Try rgb() syntax.
+ if (mightBeRGB(characters, length)) {
+ const UChar* current = characters + 4;
+ const UChar* end = characters + length;
+ int red;
+ int green;
+ int blue;
+ if (!parseColorIntOrPercentage(current, end, ',', expect, red))
+ return false;
+ if (!parseColorIntOrPercentage(current, end, ',', expect, green))
+ return false;
+ if (!parseColorIntOrPercentage(current, end, ')', expect, blue))
+ return false;
+ if (current != end)
+ return false;
+ rgb = makeRGB(red, green, blue);
+ return true;
+ }
+
+ // Try named colors.
+ Color tc;
+ tc.setNamedColor(name);
+ if (tc.isValid()) {
+ rgb = tc.rgb();
+ return true;
+ }
+ return false;
+}
+
+static inline int colorIntFromValue(CSSParserValue* v)
+{
+ if (v->fValue <= 0.0)
+ return 0;
+
+ if (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE) {
+ if (v->fValue >= 100.0)
+ return 255;
+ return static_cast<int>(v->fValue * 256.0 / 100.0);
+ }
+
+ if (v->fValue >= 255.0)
+ return 255;
+
+ return static_cast<int>(v->fValue);
+}
+
+bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha)
+{
+ CSSParserValueList* args = value->function->args.get();
+ CSSParserValue* v = args->current();
+ Units unitType = FUnknown;
+ // Get the first value and its type
+ if (validUnit(v, FInteger, true))
+ unitType = FInteger;
+ else if (validUnit(v, FPercent, true))
+ unitType = FPercent;
+ else
+ return false;
+ colorArray[0] = colorIntFromValue(v);
+ for (int i = 1; i < 3; i++) {
+ v = args->next();
+ if (v->unit != CSSParserValue::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, unitType, true))
+ return false;
+ colorArray[i] = colorIntFromValue(v);
+ }
+ if (parseAlpha) {
+ v = args->next();
+ if (v->unit != CSSParserValue::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, FNumber, true))
+ return false;
+ // 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));
+ }
+ return true;
+}
+
+// The CSS3 specification defines the format of a HSL color as
+// hsl(<number>, <percent>, <percent>)
+// and with alpha, the format is
+// hsla(<number>, <percent>, <percent>, <number>)
+// The first value, HUE, is in an angle with a value between 0 and 360
+bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha)
+{
+ CSSParserValueList* args = value->function->args.get();
+ CSSParserValue* v = args->current();
+ // Get the first value
+ 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;
+ for (int i = 1; i < 3; i++) {
+ v = args->next();
+ if (v->unit != CSSParserValue::Operator && v->iValue != ',')
+ return false;
+ 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
+ }
+ if (parseAlpha) {
+ v = args->next();
+ if (v->unit != CSSParserValue::Operator && v->iValue != ',')
+ return false;
+ v = args->next();
+ if (!validUnit(v, FNumber, true))
+ return false;
+ colorArray[3] = max(0.0, min(1.0, v->fValue));
+ }
+ return true;
+}
+
+PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value)
+{
+ RGBA32 c = Color::transparent;
+ if (!parseColorFromValue(value ? value : m_valueList->current(), c))
+ return 0;
+ return cssValuePool()->createColorValue(c);
+}
+
+bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c)
+{
+ if (!m_strict && value->unit == CSSPrimitiveValue::CSS_NUMBER &&
+ value->fValue >= 0. && value->fValue < 1000000.) {
+ String str = String::format("%06d", static_cast<int>((value->fValue+.5)));
+ if (!fastParseColor(c, str, m_strict))
+ return false;
+ } else if (value->unit == CSSPrimitiveValue::CSS_PARSER_HEXCOLOR ||
+ value->unit == CSSPrimitiveValue::CSS_IDENT ||
+ (!m_strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) {
+ if (!fastParseColor(c, value->string, m_strict && value->unit == CSSPrimitiveValue::CSS_IDENT))
+ return false;
+ } else if (value->unit == CSSParserValue::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 5 /* rgb + two commas */ &&
+ equalIgnoringCase(value->function->name, "rgb(")) {
+ int colorValues[3];
+ if (!parseColorParameters(value, colorValues, false))
+ return false;
+ c = makeRGB(colorValues[0], colorValues[1], colorValues[2]);
+ } else {
+ if (value->unit == CSSParserValue::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 7 /* rgba + three commas */ &&
+ equalIgnoringCase(value->function->name, "rgba(")) {
+ int colorValues[4];
+ if (!parseColorParameters(value, colorValues, true))
+ return false;
+ c = makeRGBA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
+ } else if (value->unit == CSSParserValue::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 5 /* hsl + two commas */ &&
+ equalIgnoringCase(value->function->name, "hsl(")) {
+ double colorValues[3];
+ if (!parseHSLParameters(value, colorValues, false))
+ return false;
+ c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], 1.0);
+ } else if (value->unit == CSSParserValue::Function &&
+ value->function->args != 0 &&
+ value->function->args->size() == 7 /* hsla + three commas */ &&
+ equalIgnoringCase(value->function->name, "hsla(")) {
+ double colorValues[4];
+ if (!parseHSLParameters(value, colorValues, true))
+ return false;
+ c = makeRGBAFromHSLA(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
+ } else
+ return false;
+ }
+
+ return true;
+}
+
+// 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)
+ : property(prop)
+ , m_cssValuePool(cssValuePool)
+ , allowX(true)
+ , allowY(false)
+ , allowBlur(false)
+ , allowSpread(false)
+ , allowColor(true)
+ , allowStyle(prop == CSSPropertyWebkitBoxShadow || prop == CSSPropertyBoxShadow)
+ , allowBreak(true)
+ {
+ }
+
+ bool allowLength() { return allowX || allowY || allowBlur || allowSpread; }
+
+ void commitValue()
+ {
+ // Handle the ,, case gracefully by doing nothing.
+ if (x || y || blur || spread || color || style) {
+ if (!values)
+ values = CSSValueList::createCommaSeparated();
+
+ // Construct the current shadow value and add it to the list.
+ values->append(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
+ }
+
+ // Now reset for the next shadow value.
+ x = 0;
+ y = 0;
+ blur = 0;
+ spread = 0;
+ style = 0;
+ color = 0;
+
+ allowX = true;
+ allowColor = true;
+ allowBreak = true;
+ allowY = false;
+ allowBlur = false;
+ allowSpread = false;
+ allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
+ }
+
+ void commitLength(CSSParserValue* v)
+ {
+ RefPtr<CSSPrimitiveValue> val = m_cssValuePool->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
+
+ if (allowX) {
+ x = val.release();
+ allowX = false;
+ allowY = true;
+ allowColor = false;
+ allowStyle = false;
+ allowBreak = false;
+ } else if (allowY) {
+ y = val.release();
+ allowY = false;
+ allowBlur = true;
+ allowColor = true;
+ allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
+ allowBreak = true;
+ } else if (allowBlur) {
+ blur = val.release();
+ allowBlur = false;
+ allowSpread = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
+ } else if (allowSpread) {
+ spread = val.release();
+ allowSpread = false;
+ }
+ }
+
+ void commitColor(PassRefPtr<CSSPrimitiveValue> val)
+ {
+ color = val;
+ allowColor = false;
+ if (allowX) {
+ allowStyle = false;
+ allowBreak = false;
+ } else {
+ allowBlur = false;
+ allowSpread = false;
+ allowStyle = property == CSSPropertyWebkitBoxShadow || property == CSSPropertyBoxShadow;
+ }
+ }
+
+ void commitStyle(CSSParserValue* v)
+ {
+ style = m_cssValuePool->createIdentifierValue(v->id);
+ allowStyle = false;
+ if (allowX)
+ allowBreak = false;
+ else {
+ allowBlur = false;
+ allowSpread = false;
+ allowColor = false;
+ }
+ }
+
+ CSSPropertyID property;
+ CSSValuePool* m_cssValuePool;
+
+ RefPtr<CSSValueList> values;
+ RefPtr<CSSPrimitiveValue> x;
+ RefPtr<CSSPrimitiveValue> y;
+ RefPtr<CSSPrimitiveValue> blur;
+ RefPtr<CSSPrimitiveValue> spread;
+ RefPtr<CSSPrimitiveValue> style;
+ RefPtr<CSSPrimitiveValue> color;
+
+ bool allowX;
+ bool allowY;
+ bool allowBlur;
+ bool allowSpread;
+ bool allowColor;
+ bool allowStyle; // inset or not.
+ bool allowBreak;
+};
+
+PassRefPtr<CSSValueList> CSSParser::parseShadow(CSSParserValueList* valueList, int propId)
+{
+ ShadowParseContext context(static_cast<CSSPropertyID>(propId), cssValuePool());
+ CSSParserValue* val;
+ while ((val = valueList->current())) {
+ // Check for a comma break first.
+ if (val->unit == CSSParserValue::Operator) {
+ if (val->iValue != ',' || !context.allowBreak)
+ // Other operators aren't legal or we aren't done with the current shadow
+ // value. Treat as invalid.
+ return 0;
+#if ENABLE(SVG)
+ // -webkit-svg-shadow does not support multiple values.
+ if (static_cast<CSSPropertyID>(propId) == CSSPropertyWebkitSvgShadow)
+ return 0;
+#endif
+ // The value is good. Commit it.
+ context.commitValue();
+ } else if (validUnit(val, FLength, true)) {
+ // We required a length and didn't get one. Invalid.
+ if (!context.allowLength())
+ return 0;
+
+ // A length is allowed here. Construct the value and add it.
+ context.commitLength(val);
+ } else if (val->id == CSSValueInset) {
+ if (!context.allowStyle)
+ return 0;
+
+ context.commitStyle(val);
+ } else {
+ // The only other type of value that's ok is a color value.
+ RefPtr<CSSPrimitiveValue> parsedColor;
+ bool isColor = ((val->id >= CSSValueAqua && val->id <= CSSValueWindowtext) || val->id == CSSValueMenu
+ || (val->id >= CSSValueWebkitFocusRingColor && val->id <= CSSValueWebkitText && !m_strict)
+ || val->id == CSSValueCurrentcolor);
+ if (isColor) {
+ if (!context.allowColor)
+ return 0;
+ parsedColor = cssValuePool()->createIdentifierValue(val->id);
+ }
+
+ if (!parsedColor)
+ // It's not built-in. Try to parse it as a color.
+ parsedColor = parseColor(val);
+
+ if (!parsedColor || !context.allowColor)
+ return 0; // This value is not a color or length and is invalid or
+ // it is a color, but a color isn't allowed at this point.
+
+ context.commitColor(parsedColor.release());
+ }
+
+ valueList->next();
+ }
+
+ if (context.allowBreak) {
+ context.commitValue();
+ if (context.values && context.values->length())
+ return context.values.release();
+ }
+
+ return 0;
+}
+
+bool CSSParser::parseReflect(int propId, bool important)
+{
+ // box-reflect: <direction> <offset> <mask>
+
+ // Direction comes first.
+ CSSParserValue* val = m_valueList->current();
+ CSSReflectionDirection direction;
+ switch (val->id) {
+ case CSSValueAbove:
+ direction = ReflectionAbove;
+ break;
+ case CSSValueBelow:
+ direction = ReflectionBelow;
+ break;
+ case CSSValueLeft:
+ direction = ReflectionLeft;
+ break;
+ case CSSValueRight:
+ direction = ReflectionRight;
+ break;
+ default:
+ return false;
+ }
+
+ // The offset comes next.
+ val = m_valueList->next();
+ RefPtr<CSSPrimitiveValue> offset;
+ if (!val)
+ offset = cssValuePool()->createValue(0, CSSPrimitiveValue::CSS_PX);
+ else {
+ if (!validUnit(val, FLength | FPercent, m_strict))
+ return false;
+ offset = createPrimitiveNumericValue(val);
+ }
+
+ // Now for the mask.
+ RefPtr<CSSValue> mask;
+ val = m_valueList->next();
+ if (val) {
+ if (!parseBorderImage(propId, mask))
+ return false;
+ }
+
+ RefPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction, offset.release(), mask.release());
+ addProperty(propId, reflectValue.release(), important);
+ m_valueList->next();
+ return true;
+}
+
+bool CSSParser::parseFlex(int propId, bool important)
+{
+ CSSParserValue* value = m_valueList->current();
+ CSSParserValueList* args = value->function->args.get();
+ if (!equalIgnoringCase(value->function->name, "-webkit-flex(") || !args || !args->size() || args->size() > 3 || m_valueList->next())
+ return false;
+
+ static const double unsetValue = -1;
+ double positiveFlex = unsetValue;
+ double negativeFlex = unsetValue;
+ RefPtr<CSSPrimitiveValue> preferredSize;
+
+ while (CSSParserValue* arg = args->current()) {
+ if (validUnit(arg, FNumber | FNonNeg, m_strict)) {
+ if (positiveFlex == unsetValue)
+ positiveFlex = arg->fValue;
+ else if (negativeFlex == unsetValue)
+ negativeFlex = arg->fValue;
+ else if (!arg->fValue) {
+ // flex() only allows a preferred size of 0 (sans units) if the positive and negative flex values have already been set.
+ preferredSize = cssValuePool()->createValue(0, CSSPrimitiveValue::CSS_PX);
+ } else {
+ // We only allow 3 numbers without units if the last value is 0. E.g., flex(1 1 1) is invalid.
+ return false;
+ }
+ } else if (!preferredSize && (arg->id == CSSValueAuto || validUnit(arg, FLength | FPercent | FNonNeg, m_strict)))
+ preferredSize = parseValidPrimitive(arg->id, arg);
+ else {
+ // Not a valid arg for flex().
+ return false;
+ }
+ args->next();
+ }
+
+ if (positiveFlex == unsetValue)
+ positiveFlex = 1;
+ if (negativeFlex == unsetValue)
+ negativeFlex = 0;
+ if (!preferredSize)
+ preferredSize = cssValuePool()->createValue(0, CSSPrimitiveValue::CSS_PX);
+
+ RefPtr<CSSFlexValue> flex = CSSFlexValue::create(clampToFloat(positiveFlex), clampToFloat(negativeFlex), preferredSize);
+ addProperty(propId, flex.release(), important);
+ return true;
+}
+
+struct BorderImageParseContext {
+ BorderImageParseContext(CSSValuePool* cssValuePool)
+ : m_cssValuePool(cssValuePool)
+ , m_canAdvance(false)
+ , m_allowCommit(true)
+ , m_allowImage(true)
+ , m_allowImageSlice(true)
+ , m_allowRepeat(true)
+ , m_allowSlash(false)
+ , m_requireWidth(false)
+ , m_requireOutset(false)
+ {}
+
+ bool canAdvance() const { return m_canAdvance; }
+ void setCanAdvance(bool canAdvance) { m_canAdvance = canAdvance; }
+
+ bool allowCommit() const { return m_allowCommit; }
+ bool allowImage() const { return m_allowImage; }
+ bool allowImageSlice() const { return m_allowImageSlice; }
+ bool allowRepeat() const { return m_allowRepeat; }
+ bool allowSlash() const { return m_allowSlash; }
+
+ bool requireWidth() const { return m_requireWidth; }
+ bool requireOutset() const { return m_requireOutset; }
+
+ void commitImage(PassRefPtr<CSSValue> image)
+ {
+ m_image = image;
+ m_canAdvance = true;
+ m_allowCommit = true;
+ m_allowImage = m_allowSlash = m_requireWidth = m_requireOutset = false;
+ m_allowImageSlice = !m_imageSlice;
+ m_allowRepeat = !m_repeat;
+ }
+ void commitImageSlice(PassRefPtr<CSSBorderImageSliceValue> slice)
+ {
+ m_imageSlice = slice;
+ m_canAdvance = true;
+ m_allowCommit = m_allowSlash = true;
+ m_allowImageSlice = m_requireWidth = m_requireOutset = false;
+ m_allowImage = !m_image;
+ m_allowRepeat = !m_repeat;
+ }
+ void commitSlash()
+ {
+ m_canAdvance = true;
+ m_allowCommit = m_allowImage = m_allowImageSlice = m_allowRepeat = m_allowSlash = false;
+ if (!m_borderSlice) {
+ m_requireWidth = true;
+ m_requireOutset = false;
+ } else {
+ m_requireOutset = true;
+ m_requireWidth = false;
+ }
+ }
+ void commitBorderWidth(PassRefPtr<CSSPrimitiveValue> slice)
+ {
+ m_borderSlice = slice;
+ m_canAdvance = true;
+ m_allowCommit = m_allowSlash = true;
+ m_allowImageSlice = m_requireWidth = m_requireOutset = false;
+ m_allowImage = !m_image;
+ m_allowRepeat = !m_repeat;
+ }
+ void commitBorderOutset(PassRefPtr<CSSPrimitiveValue> outset)
+ {
+ m_outset = outset;
+ m_canAdvance = true;
+ m_allowCommit = true;
+ m_allowImageSlice = m_allowSlash = m_requireWidth = m_requireOutset = false;
+ m_allowImage = !m_image;
+ m_allowRepeat = !m_repeat;
+ }
+ void commitRepeat(PassRefPtr<CSSValue> repeat)
+ {
+ m_repeat = repeat;
+ m_canAdvance = true;
+ m_allowCommit = true;
+ m_allowRepeat = m_allowSlash = m_requireWidth = m_requireOutset = false;
+ m_allowImageSlice = !m_imageSlice;
+ m_allowImage = !m_image;
+ }
+
+ PassRefPtr<CSSValue> commitBorderImage()
+ {
+ // Make our new border image value now.
+ return CSSBorderImageValue::create(m_image, m_imageSlice, m_borderSlice, m_outset, m_repeat);
+ }
+
+ CSSValuePool* m_cssValuePool;
+
+ bool m_canAdvance;
+
+ bool m_allowCommit;
+ bool m_allowImage;
+ bool m_allowImageSlice;
+ bool m_allowRepeat;
+ bool m_allowSlash;
+
+ bool m_requireWidth;
+ bool m_requireOutset;
+
+ RefPtr<CSSValue> m_image;
+ RefPtr<CSSBorderImageSliceValue> m_imageSlice;
+ RefPtr<CSSPrimitiveValue> m_borderSlice;
+ RefPtr<CSSPrimitiveValue> m_outset;
+
+ RefPtr<CSSValue> m_repeat;
+};
+
+bool CSSParser::parseBorderImage(int propId, RefPtr<CSSValue>& result)
+{
+ ShorthandScope scope(this, propId);
+ BorderImageParseContext context(cssValuePool());
+ while (CSSParserValue* val = m_valueList->current()) {
+ context.setCanAdvance(false);
+
+ if (!context.canAdvance() && context.allowSlash() && val->unit == CSSParserValue::Operator && val->iValue == '/')
+ context.commitSlash();
+
+ if (!context.canAdvance() && context.allowImage()) {
+ if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) {
+ // FIXME: The completeURL call should be done when using the CSSImageValue,
+ // not when creating it.
+ context.commitImage(CSSImageValue::create(m_styleSheet->completeURL(val->string)));
+ } else if (isGeneratedImageValue(val)) {
+ RefPtr<CSSValue> value;
+ if (parseGeneratedImage(m_valueList.get(), value))
+ context.commitImage(value);
+ else
+ return false;
+ } else if (val->id == CSSValueNone)
+ context.commitImage(CSSImageValue::create());
+ }
+
+ if (!context.canAdvance() && context.allowImageSlice()) {
+ RefPtr<CSSBorderImageSliceValue> imageSlice;
+ if (parseBorderImageSlice(propId, imageSlice))
+ context.commitImageSlice(imageSlice.release());
+ }
+
+ if (!context.canAdvance() && context.allowRepeat()) {
+ RefPtr<CSSValue> repeat;
+ if (parseBorderImageRepeat(repeat))
+ context.commitRepeat(repeat);
+ }
+
+ if (!context.canAdvance() && context.requireWidth()) {
+ RefPtr<CSSPrimitiveValue> borderSlice;
+ if (parseBorderImageWidth(borderSlice))
+ context.commitBorderWidth(borderSlice.release());
+ }
+
+ if (!context.canAdvance() && context.requireOutset()) {
+ RefPtr<CSSPrimitiveValue> borderOutset;
+ if (parseBorderImageOutset(borderOutset))
+ context.commitBorderOutset(borderOutset.release());
+ }
+
+ if (!context.canAdvance())
+ return false;
+
+ m_valueList->next();
+ }
+
+ if (context.allowCommit()) {
+ // Need to fully commit as a single value.
+ result = context.commitBorderImage();
+ return true;
+ }
+
+ return false;
+}
+
+static bool isBorderImageRepeatKeyword(int id)
+{
+ return id == CSSValueStretch || id == CSSValueRepeat || id == CSSValueSpace || id == CSSValueRound;
+}
+
+bool CSSParser::parseBorderImageRepeat(RefPtr<CSSValue>& result)
+{
+ RefPtr<CSSPrimitiveValue> firstValue;
+ RefPtr<CSSPrimitiveValue> secondValue;
+ CSSParserValue* val = m_valueList->current();
+ if (isBorderImageRepeatKeyword(val->id))
+ firstValue = cssValuePool()->createIdentifierValue(val->id);
+ else
+ return false;
+
+ val = m_valueList->next();
+ if (val) {
+ if (isBorderImageRepeatKeyword(val->id))
+ secondValue = cssValuePool()->createIdentifierValue(val->id);
+ else if (!inShorthand()) {
+ // If we're not parsing a shorthand then we are invalid.
+ return false;
+ } else {
+ // We need to rewind the value list, so that when its advanced we'll
+ // end up back at this value.
+ m_valueList->previous();
+ }
+ } else
+ secondValue = firstValue;
+
+ result = cssValuePool()->createValue(Pair::create(firstValue, secondValue));
+ return true;
+}
+
+class BorderImageSliceParseContext {
+public:
+ BorderImageSliceParseContext(CSSValuePool* cssValuePool)
+ : m_cssValuePool(cssValuePool)
+ , m_allowNumber(true)
+ , m_allowFill(false)
+ , m_allowFinalCommit(false)
+ , m_fill(false)
+ { }
+
+ bool allowNumber() const { return m_allowNumber; }
+ bool allowFill() const { return m_allowFill; }
+ bool allowFinalCommit() const { return m_allowFinalCommit; }
+ CSSPrimitiveValue* top() const { return m_top.get(); }
+
+ void commitNumber(CSSParserValue* v)
+ {
+ RefPtr<CSSPrimitiveValue> val = m_cssValuePool->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
+ if (!m_top)
+ m_top = val;
+ else if (!m_right)
+ m_right = val;
+ else if (!m_bottom)
+ m_bottom = val;
+ else {
+ ASSERT(!m_left);
+ m_left = val;
+ }
+
+ m_allowNumber = !m_left;
+ m_allowFill = true;
+ m_allowFinalCommit = true;
+ }
+
+ void commitFill() { m_fill = true; m_allowFill = false; m_allowNumber = false; }
+
+ void setAllowFinalCommit() { m_allowFinalCommit = true; }
+ void setTop(PassRefPtr<CSSPrimitiveValue> val) { m_top = val; }
+
+ PassRefPtr<CSSBorderImageSliceValue> commitBorderImageSlice()
+ {
+ // 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());
+ }
+ 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());
+ }
+ if (!m_left)
+ m_left = m_cssValuePool->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
+
+ // Now build a rect value to hold all four of our primitive values.
+ RefPtr<Quad> quad = Quad::create();
+ quad->setTop(m_top);
+ quad->setRight(m_right);
+ quad->setBottom(m_bottom);
+ quad->setLeft(m_left);
+
+ // Make our new border image value now.
+ return CSSBorderImageSliceValue::create(m_cssValuePool->createValue(quad.release()), m_fill);
+ }
+
+private:
+ CSSValuePool* m_cssValuePool;
+
+ bool m_allowNumber;
+ bool m_allowFill;
+ bool m_allowFinalCommit;
+
+ RefPtr<CSSPrimitiveValue> m_top;
+ RefPtr<CSSPrimitiveValue> m_right;
+ RefPtr<CSSPrimitiveValue> m_bottom;
+ RefPtr<CSSPrimitiveValue> m_left;
+
+ bool m_fill;
+};
+
+bool CSSParser::parseBorderImageSlice(int propId, RefPtr<CSSBorderImageSliceValue>& result)
+{
+ BorderImageSliceParseContext context(cssValuePool());
+ CSSParserValue* val;
+ while ((val = m_valueList->current())) {
+ if (context.allowNumber() && validUnit(val, FInteger | FNonNeg | FPercent, true)) {
+ context.commitNumber(val);
+ } else if (context.allowFill() && val->id == CSSValueFill)
+ context.commitFill();
+ else if (!inShorthand()) {
+ // If we're not parsing a shorthand then we are invalid.
+ return false;
+ } else {
+ if (context.allowFinalCommit()) {
+ // We're going to successfully parse, but we don't want to consume this token.
+ m_valueList->previous();
+ }
+ break;
+ }
+ m_valueList->next();
+ }
+
+ if (context.allowFinalCommit()) {
+ // FIXME: For backwards compatibility, -webkit-border-image, -webkit-mask-box-image and -webkit-box-reflect have to do a fill by default.
+ // FIXME: What do we do with -webkit-box-reflect and -webkit-mask-box-image? Probably just have to leave them filling...
+ if (propId == CSSPropertyWebkitBorderImage || propId == CSSPropertyWebkitMaskBoxImage || propId == CSSPropertyWebkitBoxReflect)
+ context.commitFill();
+
+ // Need to fully commit as a single value.
+ result = context.commitBorderImageSlice();
+ return true;
+ }
+
+ return false;
+}
+
+class BorderImageQuadParseContext {
+public:
+ BorderImageQuadParseContext(CSSValuePool* cssValuePool)
+ : m_cssValuePool(cssValuePool)
+ , m_allowNumber(true)
+ , m_allowFinalCommit(false)
+ { }
+
+ bool allowNumber() const { return m_allowNumber; }
+ bool allowFinalCommit() const { return m_allowFinalCommit; }
+ CSSPrimitiveValue* top() const { return m_top.get(); }
+
+ void commitNumber(CSSParserValue* v)
+ {
+ RefPtr<CSSPrimitiveValue> val;
+ if (v->id == CSSValueAuto)
+ val = m_cssValuePool->createIdentifierValue(v->id);
+ else
+ val = m_cssValuePool->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit);
+
+ if (!m_top)
+ m_top = val;
+ else if (!m_right)
+ m_right = val;
+ else if (!m_bottom)
+ m_bottom = val;
+ else {
+ ASSERT(!m_left);
+ m_left = val;
+ }
+
+ m_allowNumber = !m_left;
+ m_allowFinalCommit = true;
+ }
+
+ void setAllowFinalCommit() { m_allowFinalCommit = true; }
+ void setTop(PassRefPtr<CSSPrimitiveValue> val) { m_top = val; }
+
+ PassRefPtr<CSSPrimitiveValue> commitBorderImageQuad()
+ {
+ // 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());
+ }
+ 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());
+ }
+ if (!m_left)
+ m_left = m_cssValuePool->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType());
+
+ // Now build a quad value to hold all four of our primitive values.
+ RefPtr<Quad> quad = Quad::create();
+ quad->setTop(m_top);
+ quad->setRight(m_right);
+ quad->setBottom(m_bottom);
+ quad->setLeft(m_left);
+
+ // Make our new value now.
+ return m_cssValuePool->createValue(quad.release());
+ }
+
+private:
+ CSSValuePool* m_cssValuePool;
+
+ bool m_allowNumber;
+ bool m_allowFinalCommit;
+
+ RefPtr<CSSPrimitiveValue> m_top;
+ RefPtr<CSSPrimitiveValue> m_right;
+ RefPtr<CSSPrimitiveValue> m_bottom;
+ RefPtr<CSSPrimitiveValue> m_left;
+};
+
+bool CSSParser::parseBorderImageQuad(Units validUnits, RefPtr<CSSPrimitiveValue>& result)
+{
+ BorderImageQuadParseContext context(cssValuePool());
+ CSSParserValue* val;
+ while ((val = m_valueList->current())) {
+ if (context.allowNumber() && (validUnit(val, validUnits, true) || val->id == CSSValueAuto)) {
+ context.commitNumber(val);
+ } else if (!inShorthand()) {
+ // If we're not parsing a shorthand then we are invalid.
+ return false;
+ } else {
+ if (context.allowFinalCommit())
+ m_valueList->previous(); // The shorthand loop will advance back to this point.
+ break;
+ }
+ m_valueList->next();
+ }
+
+ if (context.allowFinalCommit()) {
+ // Need to fully commit as a single value.
+ result = context.commitBorderImageQuad();
+ return true;
+ }
+ return false;
+}
+
+bool CSSParser::parseBorderImageWidth(RefPtr<CSSPrimitiveValue>& result)
+{
+ return parseBorderImageQuad(FLength | FInteger | FNonNeg | FPercent, result);
+}
+
+bool CSSParser::parseBorderImageOutset(RefPtr<CSSPrimitiveValue>& result)
+{
+ return parseBorderImageQuad(FLength | FInteger | FNonNeg, result);
+}
+
+static void completeBorderRadii(RefPtr<CSSPrimitiveValue> radii[4])
+{
+ if (radii[3])
+ return;
+ if (!radii[2]) {
+ if (!radii[1])
+ radii[1] = radii[0];
+ radii[2] = radii[0];
+ }
+ radii[3] = radii[1];
+}
+
+bool CSSParser::parseBorderRadius(int propId, bool important)
+{
+ unsigned num = m_valueList->size();
+ if (num > 9)
+ return false;
+
+ ShorthandScope scope(this, propId);
+ RefPtr<CSSPrimitiveValue> radii[2][4];
+
+ unsigned indexAfterSlash = 0;
+ for (unsigned i = 0; i < num; ++i) {
+ CSSParserValue* value = m_valueList->valueAt(i);
+ if (value->unit == CSSParserValue::Operator) {
+ if (value->iValue != '/')
+ return false;
+
+ if (!i || indexAfterSlash || i + 1 == num || num > i + 5)
+ return false;
+
+ indexAfterSlash = i + 1;
+ completeBorderRadii(radii[0]);
+ continue;
+ }
+
+ if (i - indexAfterSlash >= 4)
+ return false;
+
+ if (!validUnit(value, FLength | FPercent | FNonNeg, m_strict))
+ return false;
+
+ RefPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value);
+
+ if (!indexAfterSlash) {
+ radii[0][i] = radius;
+
+ // Legacy syntax: -webkit-border-radius: l1 l2; is equivalent to border-radius: l1 / l2;
+ if (num == 2 && propId == CSSPropertyWebkitBorderRadius) {
+ indexAfterSlash = 1;
+ completeBorderRadii(radii[0]);
+ }
+ } else
+ radii[1][i - indexAfterSlash] = radius.release();
+ }
+
+ if (!indexAfterSlash) {
+ completeBorderRadii(radii[0]);
+ for (unsigned i = 0; i < 4; ++i)
+ radii[1][i] = radii[0][i];
+ } else
+ completeBorderRadii(radii[1]);
+
+ ImplicitScope implicitScope(this, PropertyImplicit);
+ addProperty(CSSPropertyBorderTopLeftRadius, cssValuePool()->createValue(Pair::create(radii[0][0].release(), radii[1][0].release())), important);
+ addProperty(CSSPropertyBorderTopRightRadius, cssValuePool()->createValue(Pair::create(radii[0][1].release(), radii[1][1].release())), important);
+ addProperty(CSSPropertyBorderBottomRightRadius, cssValuePool()->createValue(Pair::create(radii[0][2].release(), radii[1][2].release())), important);
+ addProperty(CSSPropertyBorderBottomLeftRadius, cssValuePool()->createValue(Pair::create(radii[0][3].release(), radii[1][3].release())), important);
+ return true;
+}
+
+bool CSSParser::parseAspectRatio(bool important)
+{
+ unsigned num = m_valueList->size();
+ if (num == 1 && m_valueList->valueAt(0)->id == CSSValueNone) {
+ addProperty(CSSPropertyWebkitAspectRatio, cssValuePool()->createIdentifierValue(CSSValueNone), important);
+ return true;
+ }
+
+ if (num != 3)
+ return false;
+
+ CSSParserValue* lvalue = m_valueList->valueAt(0);
+ CSSParserValue* op = m_valueList->valueAt(1);
+ CSSParserValue* rvalue = m_valueList->valueAt(2);
+
+ if (op->unit != CSSParserValue::Operator || op->iValue != '/')
+ return false;
+
+ if (!validUnit(lvalue, FNumber | FNonNeg, m_strict) || !validUnit(rvalue, FNumber | FNonNeg, m_strict))
+ return false;
+
+ if (!lvalue->fValue || !rvalue->fValue)
+ return false;
+
+ addProperty(CSSPropertyWebkitAspectRatio, CSSAspectRatioValue::create(narrowPrecisionToFloat(lvalue->fValue), narrowPrecisionToFloat(rvalue->fValue)), important);
+
+ return true;
+}
+
+bool CSSParser::parseCounter(int propId, int defaultValue, bool important)
+{
+ enum { ID, VAL } state = ID;
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ RefPtr<CSSPrimitiveValue> counterName;
+
+ while (true) {
+ CSSParserValue* val = m_valueList->current();
+ switch (state) {
+ case ID:
+ if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) {
+ counterName = createPrimitiveStringValue(val);
+ state = VAL;
+ m_valueList->next();
+ continue;
+ }
+ break;
+ case VAL: {
+ int i = defaultValue;
+ if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
+ i = clampToInteger(val->fValue);
+ m_valueList->next();
+ }
+
+ list->append(cssValuePool()->createValue(Pair::create(counterName.release(),
+ cssValuePool()->createValue(i, CSSPrimitiveValue::CSS_NUMBER))));
+ state = ID;
+ continue;
+ }
+ }
+ break;
+ }
+
+ if (list->length() > 0) {
+ addProperty(propId, list.release(), important);
+ return true;
+ }
+
+ return false;
+}
+
+// This should go away once we drop support for -webkit-gradient
+static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal, CSSValuePool* cssValuePool)
+{
+ RefPtr<CSSPrimitiveValue> result;
+ if (a->unit == CSSPrimitiveValue::CSS_IDENT) {
+ if ((equalIgnoringCase(a->string, "left") && horizontal)
+ || (equalIgnoringCase(a->string, "top") && !horizontal))
+ result = cssValuePool->createValue(0., CSSPrimitiveValue::CSS_PERCENTAGE);
+ else if ((equalIgnoringCase(a->string, "right") && horizontal)
+ || (equalIgnoringCase(a->string, "bottom") && !horizontal))
+ result = cssValuePool->createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE);
+ 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);
+ return result;
+}
+
+static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop)
+{
+ if (a->unit != CSSParserValue::Function)
+ return false;
+
+ if (!equalIgnoringCase(a->function->name, "from(") &&
+ !equalIgnoringCase(a->function->name, "to(") &&
+ !equalIgnoringCase(a->function->name, "color-stop("))
+ return false;
+
+ CSSParserValueList* args = a->function->args.get();
+ if (!args)
+ return false;
+
+ if (equalIgnoringCase(a->function->name, "from(")
+ || equalIgnoringCase(a->function->name, "to(")) {
+ // The "from" and "to" stops expect 1 argument.
+ if (args->size() != 1)
+ return false;
+
+ if (equalIgnoringCase(a->function->name, "from("))
+ stop.m_position = p->cssValuePool()->createValue(0, CSSPrimitiveValue::CSS_NUMBER);
+ else
+ stop.m_position = p->cssValuePool()->createValue(1, CSSPrimitiveValue::CSS_NUMBER);
+
+ int id = args->current()->id;
+ if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
+ stop.m_color = p->cssValuePool()->createIdentifierValue(id);
+ else
+ stop.m_color = p->parseColor(args->current());
+ if (!stop.m_color)
+ return false;
+ }
+
+ // The "color-stop" function expects 3 arguments.
+ if (equalIgnoringCase(a->function->name, "color-stop(")) {
+ if (args->size() != 3)
+ return false;
+
+ CSSParserValue* stopArg = args->current();
+ if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
+ stop.m_position = p->cssValuePool()->createValue(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER);
+ else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER)
+ stop.m_position = p->cssValuePool()->createValue(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER);
+ else
+ return false;
+
+ stopArg = args->next();
+ if (stopArg->unit != CSSParserValue::Operator || stopArg->iValue != ',')
+ return false;
+
+ stopArg = args->next();
+ int id = stopArg->id;
+ if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
+ stop.m_color = p->cssValuePool()->createIdentifierValue(id);
+ else
+ stop.m_color = p->parseColor(stopArg);
+ if (!stop.m_color)
+ return false;
+ }
+
+ return true;
+}
+
+bool CSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient)
+{
+ // Walk the arguments.
+ CSSParserValueList* args = valueList->current()->function->args.get();
+ if (!args || args->size() == 0)
+ return false;
+
+ // The first argument is the gradient type. It is an identifier.
+ CSSGradientType gradientType;
+ CSSParserValue* a = args->current();
+ if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT)
+ return false;
+ if (equalIgnoringCase(a->string, "linear"))
+ gradientType = CSSLinearGradient;
+ else if (equalIgnoringCase(a->string, "radial"))
+ gradientType = CSSRadialGradient;
+ else
+ return false;
+
+ RefPtr<CSSGradientValue> result;
+ switch (gradientType) {
+ case CSSLinearGradient:
+ result = CSSLinearGradientValue::create(NonRepeating, true);
+ break;
+ case CSSRadialGradient:
+ result = CSSRadialGradientValue::create(NonRepeating, true);
+ break;
+ }
+
+ // Comma.
+ a = args->next();
+ if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+
+ // Next comes the starting point for the gradient as an x y pair. There is no
+ // comma between the x and the y values.
+ // First X. It can be left, right, number or percent.
+ a = args->next();
+ if (!a)
+ return false;
+ RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true, cssValuePool());
+ if (!point)
+ return false;
+ result->setFirstX(point.release());
+
+ // First Y. It can be top, bottom, number or percent.
+ a = args->next();
+ if (!a)
+ return false;
+ point = parseDeprecatedGradientPoint(a, false, cssValuePool());
+ if (!point)
+ return false;
+ result->setFirstY(point.release());
+
+ // Comma after the first point.
+ a = args->next();
+ if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+
+ // For radial gradients only, we now expect a numeric radius.
+ if (gradientType == CSSRadialGradient) {
+ a = args->next();
+ if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
+ return false;
+ static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(createPrimitiveNumericValue(a));
+
+ // Comma after the first radius.
+ a = args->next();
+ if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+ }
+
+ // Next is the ending point for the gradient as an x, y pair.
+ // Second X. It can be left, right, number or percent.
+ a = args->next();
+ if (!a)
+ return false;
+ point = parseDeprecatedGradientPoint(a, true, cssValuePool());
+ if (!point)
+ return false;
+ result->setSecondX(point.release());
+
+ // Second Y. It can be top, bottom, number or percent.
+ a = args->next();
+ if (!a)
+ return false;
+ point = parseDeprecatedGradientPoint(a, false, cssValuePool());
+ if (!point)
+ return false;
+ result->setSecondY(point.release());
+
+ // For radial gradients only, we now expect the second radius.
+ if (gradientType == CSSRadialGradient) {
+ // Comma after the second point.
+ a = args->next();
+ if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+
+ a = args->next();
+ if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
+ return false;
+ static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(createPrimitiveNumericValue(a));
+ }
+
+ // We now will accept any number of stops (0 or more).
+ a = args->next();
+ while (a) {
+ // Look for the comma before the next stop.
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+
+ // Now examine the stop itself.
+ a = args->next();
+ if (!a)
+ return false;
+
+ // The function name needs to be one of "from", "to", or "color-stop."
+ CSSGradientColorStop stop;
+ if (!parseDeprecatedGradientColorStop(this, a, stop))
+ return false;
+ result->addStop(stop);
+
+ // Advance
+ a = args->next();
+ }
+
+ gradient = result.release();
+ return true;
+}
+
+static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal, CSSValuePool* cssValuePool)
+{
+ if (a->unit != CSSPrimitiveValue::CSS_IDENT)
+ return 0;
+
+ switch (a->id) {
+ case CSSValueLeft:
+ case CSSValueRight:
+ isHorizontal = true;
+ break;
+ case CSSValueTop:
+ case CSSValueBottom:
+ isHorizontal = false;
+ break;
+ default:
+ return 0;
+ }
+ return cssValuePool->createIdentifierValue(a->id);
+}
+
+static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value)
+{
+ int id = value->id;
+ if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor)
+ return p->cssValuePool()->createIdentifierValue(id);
+
+ return p->parseColor(value);
+}
+
+bool CSSParser::parseLinearGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
+{
+ RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating);
+
+ // Walk the arguments.
+ CSSParserValueList* args = valueList->current()->function->args.get();
+ if (!args || !args->size())
+ return false;
+
+ CSSParserValue* a = args->current();
+ if (!a)
+ return false;
+
+ bool expectComma = false;
+ // Look for angle.
+ if (validUnit(a, FAngle, true)) {
+ result->setAngle(createPrimitiveNumericValue(a));
+
+ a = args->next();
+ expectComma = true;
+ } else {
+ // Look one or two optional keywords that indicate a side or corner.
+ RefPtr<CSSPrimitiveValue> startX, startY;
+
+ RefPtr<CSSPrimitiveValue> location;
+ bool isHorizontal = false;
+ if ((location = valueFromSideKeyword(a, isHorizontal, cssValuePool()))) {
+ if (isHorizontal)
+ startX = location;
+ else
+ startY = location;
+
+ a = args->next();
+ if (a) {
+ if ((location = valueFromSideKeyword(a, isHorizontal, cssValuePool()))) {
+ if (isHorizontal) {
+ if (startX)
+ return false;
+ startX = location;
+ } else {
+ if (startY)
+ return false;
+ startY = location;
+ }
+
+ a = args->next();
+ }
+ }
+
+ expectComma = true;
+ }
+
+ if (!startX && !startY)
+ startY = cssValuePool()->createIdentifierValue(CSSValueTop);
+
+ result->setFirstX(startX.release());
+ result->setFirstY(startY.release());
+ }
+
+ if (!parseGradientColorStops(args, result.get(), expectComma))
+ return false;
+
+ Vector<CSSGradientColorStop>& stops = result->stops();
+ if (stops.isEmpty())
+ return false;
+
+ gradient = result.release();
+ return true;
+}
+
+bool CSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating)
+{
+ RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating);
+
+ // Walk the arguments.
+ CSSParserValueList* args = valueList->current()->function->args.get();
+ if (!args || !args->size())
+ return false;
+
+ CSSParserValue* a = args->current();
+ if (!a)
+ return false;
+
+ bool expectComma = false;
+
+ // Optional background-position
+ RefPtr<CSSValue> centerX;
+ RefPtr<CSSValue> centerY;
+ // parseFillPosition advances the args next pointer.
+ parseFillPosition(args, centerX, centerY);
+ a = args->current();
+ if (!a)
+ return false;
+
+ if (centerX || centerY) {
+ // Comma
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+
+ a = args->next();
+ if (!a)
+ return false;
+ }
+
+ ASSERT(!centerX || centerX->isPrimitiveValue());
+ ASSERT(!centerY || centerY->isPrimitiveValue());
+
+ result->setFirstX(static_cast<CSSPrimitiveValue*>(centerX.get()));
+ result->setSecondX(static_cast<CSSPrimitiveValue*>(centerX.get()));
+ // CSS3 radial gradients always share the same start and end point.
+ result->setFirstY(static_cast<CSSPrimitiveValue*>(centerY.get()));
+ result->setSecondY(static_cast<CSSPrimitiveValue*>(centerY.get()));
+
+ RefPtr<CSSPrimitiveValue> shapeValue;
+ RefPtr<CSSPrimitiveValue> sizeValue;
+
+ // Optional shape and/or size in any order.
+ for (int i = 0; i < 2; ++i) {
+ if (a->unit != CSSPrimitiveValue::CSS_IDENT)
+ break;
+
+ bool foundValue = false;
+ switch (a->id) {
+ case CSSValueCircle:
+ case CSSValueEllipse:
+ shapeValue = cssValuePool()->createIdentifierValue(a->id);
+ foundValue = true;
+ break;
+ case CSSValueClosestSide:
+ case CSSValueClosestCorner:
+ case CSSValueFarthestSide:
+ case CSSValueFarthestCorner:
+ case CSSValueContain:
+ case CSSValueCover:
+ sizeValue = cssValuePool()->createIdentifierValue(a->id);
+ foundValue = true;
+ break;
+ }
+
+ if (foundValue) {
+ a = args->next();
+ if (!a)
+ return false;
+
+ expectComma = true;
+ }
+ }
+
+ result->setShape(shapeValue);
+ result->setSizingBehavior(sizeValue);
+
+ // Or, two lengths or percentages
+ RefPtr<CSSPrimitiveValue> horizontalSize;
+ RefPtr<CSSPrimitiveValue> verticalSize;
+
+ if (!shapeValue && !sizeValue) {
+ if (validUnit(a, FLength | FPercent, m_strict)) {
+ horizontalSize = createPrimitiveNumericValue(a);
+ a = args->next();
+ if (!a)
+ return false;
+
+ expectComma = true;
+ }
+
+ if (validUnit(a, FLength | FPercent, m_strict)) {
+ verticalSize = createPrimitiveNumericValue(a);
+
+ a = args->next();
+ if (!a)
+ return false;
+ expectComma = true;
+ }
+ }
+
+ // Must have neither or both.
+ if (!horizontalSize != !verticalSize)
+ return false;
+
+ result->setEndHorizontalSize(horizontalSize);
+ result->setEndVerticalSize(verticalSize);
+
+ if (!parseGradientColorStops(args, result.get(), expectComma))
+ return false;
+
+ gradient = result.release();
+ return true;
+}
+
+bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradientValue* gradient, bool expectComma)
+{
+ CSSParserValue* a = valueList->current();
+
+ // Now look for color stops.
+ while (a) {
+ // Look for the comma before the next stop.
+ if (expectComma) {
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+
+ a = valueList->next();
+ if (!a)
+ return false;
+ }
+
+ // <color-stop> = <color> [ <percentage> | <length> ]?
+ CSSGradientColorStop stop;
+ stop.m_color = parseGradientColorOrKeyword(this, a);
+ if (!stop.m_color)
+ return false;
+
+ a = valueList->next();
+ if (a) {
+ if (validUnit(a, FLength | FPercent, m_strict)) {
+ stop.m_position = createPrimitiveNumericValue(a);
+ a = valueList->next();
+ }
+ }
+
+ gradient->addStop(stop);
+ expectComma = true;
+ }
+
+ // Must have 2 or more stops to be valid.
+ return gradient->stops().size() > 1;
+}
+
+bool CSSParser::isGeneratedImageValue(CSSParserValue* val) const
+{
+ if (val->unit != CSSParserValue::Function)
+ return false;
+
+ return equalIgnoringCase(val->function->name, "-webkit-gradient(")
+ || equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")
+ || equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")
+ || equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")
+ || equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")
+ || equalIgnoringCase(val->function->name, "-webkit-canvas(")
+ || equalIgnoringCase(val->function->name, "-webkit-cross-fade(");
+}
+
+bool CSSParser::parseGeneratedImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value)
+{
+ CSSParserValue* val = valueList->current();
+
+ if (val->unit != CSSParserValue::Function)
+ return false;
+
+ if (equalIgnoringCase(val->function->name, "-webkit-gradient("))
+ return parseDeprecatedGradient(valueList, value);
+
+ if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient("))
+ return parseLinearGradient(valueList, value, NonRepeating);
+
+ if (equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient("))
+ return parseLinearGradient(valueList, value, Repeating);
+
+ if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient("))
+ return parseRadialGradient(valueList, value, NonRepeating);
+
+ if (equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient("))
+ return parseRadialGradient(valueList, value, Repeating);
+
+ if (equalIgnoringCase(val->function->name, "-webkit-canvas("))
+ return parseCanvas(valueList, value);
+
+ if (equalIgnoringCase(val->function->name, "-webkit-cross-fade("))
+ return parseCrossfade(valueList, value);
+
+ return false;
+}
+
+bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& crossfade)
+{
+ RefPtr<CSSCrossfadeValue> result;
+
+ // Walk the arguments.
+ CSSParserValueList* args = valueList->current()->function->args.get();
+ if (!args || args->size() != 5)
+ return false;
+ CSSParserValue* a = args->current();
+ RefPtr<CSSValue> fromImageValue;
+ RefPtr<CSSValue> toImageValue;
+
+ // The first argument is the "from" image. It is a fill image.
+ if (!a || !parseFillImage(args, fromImageValue))
+ return false;
+ a = args->next();
+
+ // Skip a comma
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+ a = args->next();
+
+ // The second argument is the "to" image. It is a fill image.
+ if (!a || !parseFillImage(args, toImageValue))
+ return false;
+ a = args->next();
+
+ // Skip a comma
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return false;
+ a = args->next();
+
+ // The third argument is the crossfade value. It is a percentage or a fractional number.
+ RefPtr<CSSPrimitiveValue> percentage;
+ if (!a)
+ return false;
+
+ if (a->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
+ percentage = cssValuePool()->createValue(clampTo<double>(a->fValue / 100, 0, 1), CSSPrimitiveValue::CSS_NUMBER);
+ else if (a->unit == CSSPrimitiveValue::CSS_NUMBER)
+ percentage = cssValuePool()->createValue(clampTo<double>(a->fValue, 0, 1), CSSPrimitiveValue::CSS_NUMBER);
+ else
+ return false;
+
+ result = CSSCrossfadeValue::create(fromImageValue, toImageValue);
+ result->setPercentage(percentage);
+
+ crossfade = result;
+
+ return true;
+}
+
+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)
+ return false;
+ result->setName(a->string);
+ canvas = result;
+ return true;
+}
+
+class TransformOperationInfo {
+public:
+ TransformOperationInfo(const CSSParserString& name)
+ : m_type(WebKitCSSTransformValue::UnknownTransformOperation)
+ , m_argCount(1)
+ , m_allowSingleArgument(false)
+ , m_unit(CSSParser::FUnknown)
+ {
+ if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scalex(") || equalIgnoringCase(name, "scaley(") || equalIgnoringCase(name, "scalez(")) {
+ m_unit = CSSParser::FNumber;
+ if (equalIgnoringCase(name, "scale("))
+ m_type = WebKitCSSTransformValue::ScaleTransformOperation;
+ else if (equalIgnoringCase(name, "scalex("))
+ m_type = WebKitCSSTransformValue::ScaleXTransformOperation;
+ else if (equalIgnoringCase(name, "scaley("))
+ m_type = WebKitCSSTransformValue::ScaleYTransformOperation;
+ else
+ m_type = WebKitCSSTransformValue::ScaleZTransformOperation;
+ } else if (equalIgnoringCase(name, "scale3d(")) {
+ m_type = WebKitCSSTransformValue::Scale3DTransformOperation;
+ m_argCount = 5;
+ m_unit = CSSParser::FNumber;
+ } else if (equalIgnoringCase(name, "rotate(")) {
+ m_type = WebKitCSSTransformValue::RotateTransformOperation;
+ m_unit = CSSParser::FAngle;
+ } else if (equalIgnoringCase(name, "rotatex(") ||
+ equalIgnoringCase(name, "rotatey(") ||
+ equalIgnoringCase(name, "rotatez(")) {
+ m_unit = CSSParser::FAngle;
+ if (equalIgnoringCase(name, "rotatex("))
+ m_type = WebKitCSSTransformValue::RotateXTransformOperation;
+ else if (equalIgnoringCase(name, "rotatey("))
+ m_type = WebKitCSSTransformValue::RotateYTransformOperation;
+ else
+ m_type = WebKitCSSTransformValue::RotateZTransformOperation;
+ } else if (equalIgnoringCase(name, "rotate3d(")) {
+ m_type = WebKitCSSTransformValue::Rotate3DTransformOperation;
+ m_argCount = 7;
+ m_unit = CSSParser::FNumber;
+ } else if (equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "skewx(") || equalIgnoringCase(name, "skewy(")) {
+ m_unit = CSSParser::FAngle;
+ if (equalIgnoringCase(name, "skew("))
+ m_type = WebKitCSSTransformValue::SkewTransformOperation;
+ else if (equalIgnoringCase(name, "skewx("))
+ m_type = WebKitCSSTransformValue::SkewXTransformOperation;
+ else
+ m_type = WebKitCSSTransformValue::SkewYTransformOperation;
+ } else if (equalIgnoringCase(name, "translate(") || equalIgnoringCase(name, "translatex(") || equalIgnoringCase(name, "translatey(") || equalIgnoringCase(name, "translatez(")) {
+ m_unit = CSSParser::FLength | CSSParser::FPercent;
+ if (equalIgnoringCase(name, "translate("))
+ m_type = WebKitCSSTransformValue::TranslateTransformOperation;
+ else if (equalIgnoringCase(name, "translatex("))
+ m_type = WebKitCSSTransformValue::TranslateXTransformOperation;
+ else if (equalIgnoringCase(name, "translatey("))
+ m_type = WebKitCSSTransformValue::TranslateYTransformOperation;
+ else
+ m_type = WebKitCSSTransformValue::TranslateZTransformOperation;
+ } else if (equalIgnoringCase(name, "translate3d(")) {
+ m_type = WebKitCSSTransformValue::Translate3DTransformOperation;
+ m_argCount = 5;
+ m_unit = CSSParser::FLength | CSSParser::FPercent;
+ } else if (equalIgnoringCase(name, "matrix(")) {
+ m_type = WebKitCSSTransformValue::MatrixTransformOperation;
+ m_argCount = 11;
+ m_unit = CSSParser::FNumber;
+ } else if (equalIgnoringCase(name, "matrix3d(")) {
+ m_type = WebKitCSSTransformValue::Matrix3DTransformOperation;
+ m_argCount = 31;
+ m_unit = CSSParser::FNumber;
+ } else if (equalIgnoringCase(name, "perspective(")) {
+ m_type = WebKitCSSTransformValue::PerspectiveTransformOperation;
+ m_unit = CSSParser::FNumber;
+ }
+
+ if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "translate(")) {
+ m_allowSingleArgument = true;
+ m_argCount = 3;
+ }
+ }
+
+ WebKitCSSTransformValue::TransformOperationType type() const { return m_type; }
+ unsigned argCount() const { return m_argCount; }
+ CSSParser::Units unit() const { return m_unit; }
+
+ bool unknown() const { return m_type == WebKitCSSTransformValue::UnknownTransformOperation; }
+ bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
+
+private:
+ WebKitCSSTransformValue::TransformOperationType m_type;
+ unsigned m_argCount;
+ bool m_allowSingleArgument;
+ CSSParser::Units m_unit;
+};
+
+PassRefPtr<CSSValueList> CSSParser::parseTransform()
+{
+ if (!m_valueList)
+ return 0;
+
+ // The transform is a list of functional primitives that specify transform operations.
+ // We collect a list of WebKitCSSTransformValues, where each value specifies a single operation.
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ if (value->unit != CSSParserValue::Function || !value->function)
+ return 0;
+
+ // Every primitive requires at least one argument.
+ CSSParserValueList* args = value->function->args.get();
+ if (!args)
+ return 0;
+
+ // See if the specified primitive is one we understand.
+ TransformOperationInfo info(value->function->name);
+ if (info.unknown())
+ return 0;
+
+ if (!info.hasCorrectArgCount(args->size()))
+ return 0;
+
+ // Create the new WebKitCSSTransformValue for this operation and add it to our list.
+ RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(info.type());
+ list->append(transformValue);
+
+ // Snag our values.
+ CSSParserValue* a = args->current();
+ unsigned argNumber = 0;
+ while (a) {
+ CSSParser::Units unit = info.unit();
+
+ if (info.type() == WebKitCSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
+ // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
+ if (!validUnit(a, FAngle, true))
+ return 0;
+ } else if (info.type() == WebKitCSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
+ // 3rd param of translate3d() cannot be a percentage
+ if (!validUnit(a, FLength, true))
+ return 0;
+ } else if (info.type() == WebKitCSSTransformValue::TranslateZTransformOperation && argNumber == 0) {
+ // 1st param of translateZ() cannot be a percentage
+ if (!validUnit(a, FLength, true))
+ return 0;
+ } else if (info.type() == WebKitCSSTransformValue::PerspectiveTransformOperation && argNumber == 0) {
+ // 1st param of perspective() must be a non-negative number (deprecated) or length.
+ if (!validUnit(a, FNumber | FLength | FNonNeg, true))
+ return 0;
+ } else if (!validUnit(a, unit, true))
+ return 0;
+
+ // Add the value to the current transform operation.
+ transformValue->append(createPrimitiveNumericValue(a));
+
+ a = args->next();
+ if (!a)
+ break;
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return 0;
+ a = args->next();
+
+ argNumber++;
+ }
+ }
+
+ return list.release();
+}
+
+#if ENABLE(CSS_FILTERS)
+
+static void filterInfoForName(const CSSParserString& name, WebKitCSSFilterValue::FilterOperationType& filterType, unsigned& maximumArgumentCount)
+{
+ if (equalIgnoringCase(name, "grayscale("))
+ filterType = WebKitCSSFilterValue::GrayscaleFilterOperation;
+ else if (equalIgnoringCase(name, "sepia("))
+ filterType = WebKitCSSFilterValue::SepiaFilterOperation;
+ else if (equalIgnoringCase(name, "saturate("))
+ filterType = WebKitCSSFilterValue::SaturateFilterOperation;
+ else if (equalIgnoringCase(name, "hue-rotate("))
+ filterType = WebKitCSSFilterValue::HueRotateFilterOperation;
+ else if (equalIgnoringCase(name, "invert("))
+ filterType = WebKitCSSFilterValue::InvertFilterOperation;
+ else if (equalIgnoringCase(name, "opacity("))
+ filterType = WebKitCSSFilterValue::OpacityFilterOperation;
+ else if (equalIgnoringCase(name, "brightness("))
+ filterType = WebKitCSSFilterValue::BrightnessFilterOperation;
+ else if (equalIgnoringCase(name, "contrast("))
+ filterType = WebKitCSSFilterValue::ContrastFilterOperation;
+ else if (equalIgnoringCase(name, "blur("))
+ filterType = WebKitCSSFilterValue::BlurFilterOperation;
+ else if (equalIgnoringCase(name, "drop-shadow(")) {
+ filterType = WebKitCSSFilterValue::DropShadowFilterOperation;
+ maximumArgumentCount = 4; // x-offset, y-offset, blur-radius, color -- spread and inset style not allowed.
+ }
+#if ENABLE(CSS_SHADERS)
+ else if (equalIgnoringCase(name, "custom("))
+ filterType = WebKitCSSFilterValue::CustomFilterOperation;
+#endif
+}
+
+#if ENABLE(CSS_SHADERS)
+static bool acceptCommaOperator(CSSParserValueList* argsList)
+{
+ if (CSSParserValue* arg = argsList->current()) {
+ if (arg->unit != CSSParserValue::Operator || arg->iValue != ',')
+ return false;
+ argsList->next();
+ }
+ return true;
+}
+
+PassRefPtr<WebKitCSSFilterValue> CSSParser::parseCustomFilter(CSSParserValue* value)
+{
+ CSSParserValueList* argsList = value->function->args.get();
+ if (!argsList)
+ return 0;
+
+ RefPtr<WebKitCSSFilterValue> filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::CustomFilterOperation);
+
+ // Custom filter syntax:
+ //
+ // vertexShader: <uri> | none
+ // fragmentShader: <uri> | none
+ //
+ // box: filter-box | border-box | padding-box | content-box
+ // vertexMesh: +<integer>{1,2}[wsp<box>][wsp'detached']
+ //
+ // param-value: true|false[wsp+true|false]{0-3} |
+ // <number>[wsp+<number>]{0-3} |
+ // <array> |
+ // <transform> |
+ // <texture(<uri>)>
+ // array: 'array('<number>[wsp<number>]*')'
+ // css-3d-transform: <transform-function>;[<transform-function>]*
+ // transform: <css-3d-transform> | <mat>
+ // mat: 'mat2('<number>(,<number>){3}')' |
+ // 'mat3('<number>(,<number>){8}')' |
+ // 'mat4('<number>(,<number>){15}')' )
+ // param-def: <param-name>wsp<param-value>
+ // param-name: <ident>
+ // params: [<param-def>[,<param-def>*]]
+ //
+ // custom(<vertex-shader>[wsp<fragment-shader>][,<vertex-mesh>][,<params>])
+
+ // 1. Parse the shader URLs: <vertex-shader>[wsp<fragment-shader>]
+ RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated();
+ bool hadAtLeastOneCustomShader = false;
+ CSSParserValue* arg;
+ while ((arg = argsList->current())) {
+ RefPtr<CSSValue> value;
+ if (arg->id == CSSValueNone)
+ value = cssValuePool()->createIdentifierValue(CSSValueNone);
+ else if (arg->unit == CSSPrimitiveValue::CSS_URI) {
+ KURL shaderURL = m_styleSheet ? m_styleSheet->completeURL(arg->string) : KURL();
+ value = WebKitCSSShaderValue::create(shaderURL.string());
+ hadAtLeastOneCustomShader = true;
+ }
+ if (!value)
+ break;
+ shadersList->append(value.release());
+ argsList->next();
+ }
+
+ if (!shadersList->length() || !hadAtLeastOneCustomShader || shadersList->length() > 2 || !acceptCommaOperator(argsList))
+ return 0;
+
+ filterValue->append(shadersList.release());
+
+ // 2. Parse the mesh size <vertex-mesh>
+ RefPtr<CSSValueList> meshSizeList = CSSValueList::createSpaceSeparated();
+
+ while ((arg = argsList->current())) {
+ if (!validUnit(arg, FInteger | FNonNeg, true))
+ break;
+ int integerValue = clampToInteger(arg->fValue);
+ // According to the specification we can only accept positive non-zero values.
+ if (integerValue < 1)
+ return 0;
+ meshSizeList->append(cssValuePool()->createValue(integerValue, CSSPrimitiveValue::CSS_NUMBER));
+ argsList->next();
+ }
+
+ if (meshSizeList->length() > 2)
+ return 0;
+
+ if ((arg = argsList->current()) && (arg->id == CSSValueBorderBox || arg->id == CSSValuePaddingBox
+ || arg->id == CSSValueContentBox || arg->id == CSSValueFilterBox)) {
+ meshSizeList->append(cssValuePool()->createIdentifierValue(arg->id));
+ argsList->next();
+ }
+
+ if ((arg = argsList->current()) && arg->id == CSSValueDetached) {
+ meshSizeList->append(cssValuePool()->createIdentifierValue(arg->id));
+ argsList->next();
+ }
+
+ if (meshSizeList->length()) {
+ if (!acceptCommaOperator(argsList))
+ return 0;
+ filterValue->append(meshSizeList.release());
+ }
+
+ // 3. Parser the parameters.
+ RefPtr<CSSValueList> paramList = CSSValueList::createCommaSeparated();
+
+ while ((arg = argsList->current())) {
+ if (arg->id || arg->unit != CSSPrimitiveValue::CSS_IDENT)
+ return 0;
+
+ RefPtr<CSSValueList> parameter = CSSValueList::createSpaceSeparated();
+ parameter->append(createPrimitiveStringValue(arg));
+ argsList->next();
+
+ if (!(arg = argsList->current()))
+ return 0;
+
+ // TODO: Implement other parameters types parsing.
+ // 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<CSSValueList> paramValueList = CSSValueList::createSpaceSeparated();
+ while ((arg = argsList->current())) {
+ // If we hit a comma it means we finished this parameter's values.
+ if (arg->unit == CSSParserValue::Operator && arg->iValue == ',')
+ break;
+ if (!validUnit(arg, FNumber, true))
+ return 0;
+ paramValueList->append(cssValuePool()->createValue(arg->fValue, CSSPrimitiveValue::CSS_NUMBER));
+ argsList->next();
+ }
+ if (!paramValueList->length() || paramValueList->length() > 4)
+ return 0;
+ parameter->append(paramValueList.release());
+ paramList->append(parameter.release());
+ if (!acceptCommaOperator(argsList))
+ return 0;
+ }
+
+ if (paramList->length())
+ filterValue->append(paramList.release());
+
+ return filterValue;
+}
+#endif
+
+PassRefPtr<WebKitCSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValueList* args, WebKitCSSFilterValue::FilterOperationType filterType)
+{
+ RefPtr<WebKitCSSFilterValue> filterValue = WebKitCSSFilterValue::create(filterType);
+ ASSERT(args);
+
+ switch (filterType) {
+ case WebKitCSSFilterValue::GrayscaleFilterOperation:
+ case WebKitCSSFilterValue::SepiaFilterOperation:
+ 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)
+ return 0;
+
+ if (args->size()) {
+ CSSParserValue* value = args->current();
+ if (!validUnit(value, FNumber | FPercent | FNonNeg, true))
+ return 0;
+
+ double amount = value->fValue;
+
+ // Saturate, Brightness 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)
+ 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)
+ return 0;
+
+ if (args->size()) {
+ CSSParserValue* argument = args->current();
+ if (!validUnit(argument, FAngle, true))
+ return 0;
+
+ filterValue->append(createPrimitiveNumericValue(argument));
+ }
+ break;
+ }
+ case WebKitCSSFilterValue::BlurFilterOperation: {
+ // Blur takes a single length. Zero parameters are allowed.
+ if (args->size() > 1)
+ return 0;
+
+ if (args->size()) {
+ CSSParserValue* argument = args->current();
+ if (!validUnit(argument, FLength | FNonNeg, true))
+ return 0;
+
+ filterValue->append(createPrimitiveNumericValue(argument));
+ }
+ break;
+ }
+ case WebKitCSSFilterValue::DropShadowFilterOperation: {
+ // drop-shadow() takes a single shadow.
+ RefPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter);
+ if (!shadowValueList || shadowValueList->length() != 1)
+ return 0;
+
+ filterValue->append((shadowValueList.release())->itemWithoutBoundsCheck(0));
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return filterValue.release();
+}
+
+PassRefPtr<CSSValueList> CSSParser::parseFilter()
+{
+ if (!m_valueList)
+ return 0;
+
+ // The filter is a list of functional primitives that specify individual operations.
+ RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ if (value->unit != CSSPrimitiveValue::CSS_URI && (value->unit != CSSParserValue::Function || !value->function))
+ return 0;
+
+ WebKitCSSFilterValue::FilterOperationType filterType = WebKitCSSFilterValue::UnknownFilterOperation;
+
+ // See if the specified primitive is one we understand.
+ if (value->unit == CSSPrimitiveValue::CSS_URI) {
+ RefPtr<WebKitCSSFilterValue> referenceFilterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::ReferenceFilterOperation);
+ list->append(referenceFilterValue);
+ referenceFilterValue->append(cssValuePool()->createValue(value->string, CSSPrimitiveValue::CSS_STRING));
+ } else {
+ const CSSParserString name = value->function->name;
+ unsigned maximumArgumentCount = 1;
+
+ filterInfoForName(name, filterType, maximumArgumentCount);
+
+ if (filterType == WebKitCSSFilterValue::UnknownFilterOperation)
+ return 0;
+
+#if ENABLE(CSS_SHADERS)
+ if (filterType == WebKitCSSFilterValue::CustomFilterOperation) {
+ RefPtr<WebKitCSSFilterValue> filterValue = parseCustomFilter(value);
+ if (!filterValue)
+ return 0;
+ list->append(filterValue.release());
+ continue;
+ }
+#endif
+ CSSParserValueList* args = value->function->args.get();
+ if (!args)
+ return 0;
+
+ RefPtr<WebKitCSSFilterValue> filterValue = parseBuiltinFilterArguments(args, filterType);
+ if (!filterValue)
+ return 0;
+
+ list->append(filterValue);
+ }
+ }
+
+ return list.release();
+}
+#endif
+
+static bool validFlowName(const String& flowName)
+{
+ if (equalIgnoringCase(flowName, "auto")
+ || equalIgnoringCase(flowName, "default")
+ || equalIgnoringCase(flowName, "inherit")
+ || equalIgnoringCase(flowName, "initial")
+ || equalIgnoringCase(flowName, "none"))
+ return false;
+ return true;
+}
+
+// auto | <ident>
+bool CSSParser::parseFlowThread(int propId, bool important)
+{
+ ASSERT(propId == CSSPropertyWebkitFlowInto);
+
+ if (m_valueList->size() != 1)
+ return false;
+
+ CSSParserValue* value = m_valueList->current();
+ if (!value)
+ return false;
+
+ if (value->unit != CSSPrimitiveValue::CSS_IDENT)
+ return false;
+
+ if (value->id == CSSValueAuto) {
+ addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
+ return true;
+ }
+
+ String inputProperty = String(value->string);
+ if (!inputProperty.isEmpty()) {
+ if (!validFlowName(inputProperty))
+ return false;
+ addProperty(propId, cssValuePool()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING), important);
+ } else
+ addProperty(propId, cssValuePool()->createIdentifierValue(CSSValueAuto), important);
+
+ return true;
+}
+
+// -webkit-flow-from: none | <ident>
+bool CSSParser::parseRegionThread(int propId, bool important)
+{
+ ASSERT(propId == CSSPropertyWebkitFlowFrom);
+
+ if (m_valueList->size() != 1)
+ return false;
+
+ CSSParserValue* value = m_valueList->current();
+ if (!value)
+ return false;
+
+ if (value->unit != CSSPrimitiveValue::CSS_IDENT)
+ return false;
+
+ if (value->id == CSSValueNone)
+ addProperty(propId, cssValuePool()->createIdentifierValue(value->id), important);
+ else {
+ String inputProperty = String(value->string);
+ if (!inputProperty.isEmpty()) {
+ if (!validFlowName(inputProperty))
+ return false;
+ addProperty(propId, cssValuePool()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING), important);
+ } else
+ addProperty(propId, cssValuePool()->createIdentifierValue(CSSValueNone), important);
+ }
+
+ return true;
+}
+
+bool CSSParser::parseTransformOrigin(int propId, int& propId1, int& propId2, int& propId3, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
+{
+ propId1 = propId;
+ propId2 = propId;
+ propId3 = propId;
+ if (propId == CSSPropertyWebkitTransformOrigin) {
+ propId1 = CSSPropertyWebkitTransformOriginX;
+ propId2 = CSSPropertyWebkitTransformOriginY;
+ propId3 = CSSPropertyWebkitTransformOriginZ;
+ }
+
+ switch (propId) {
+ case CSSPropertyWebkitTransformOrigin:
+ if (!parseTransformOriginShorthand(value, value2, value3))
+ return false;
+ // parseTransformOriginShorthand advances the m_valueList pointer
+ break;
+ case CSSPropertyWebkitTransformOriginX: {
+ value = parseFillPositionX(m_valueList.get());
+ if (value)
+ m_valueList->next();
+ break;
+ }
+ case CSSPropertyWebkitTransformOriginY: {
+ value = parseFillPositionY(m_valueList.get());
+ if (value)
+ m_valueList->next();
+ break;
+ }
+ case CSSPropertyWebkitTransformOriginZ: {
+ if (validUnit(m_valueList->current(), FLength, m_strict))
+ value = createPrimitiveNumericValue(m_valueList->current());
+ if (value)
+ m_valueList->next();
+ break;
+ }
+ }
+
+ return value;
+}
+
+bool CSSParser::parsePerspectiveOrigin(int propId, int& propId1, int& propId2, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2)
+{
+ propId1 = propId;
+ propId2 = propId;
+ if (propId == CSSPropertyWebkitPerspectiveOrigin) {
+ propId1 = CSSPropertyWebkitPerspectiveOriginX;
+ propId2 = CSSPropertyWebkitPerspectiveOriginY;
+ }
+
+ switch (propId) {
+ case CSSPropertyWebkitPerspectiveOrigin:
+ parseFillPosition(m_valueList.get(), value, value2);
+ break;
+ case CSSPropertyWebkitPerspectiveOriginX: {
+ value = parseFillPositionX(m_valueList.get());
+ if (value)
+ m_valueList->next();
+ break;
+ }
+ case CSSPropertyWebkitPerspectiveOriginY: {
+ value = parseFillPositionY(m_valueList.get());
+ if (value)
+ m_valueList->next();
+ break;
+ }
+ }
+
+ return value;
+}
+
+bool CSSParser::parseTextEmphasisStyle(bool important)
+{
+ unsigned valueListSize = m_valueList->size();
+
+ RefPtr<CSSPrimitiveValue> fill;
+ RefPtr<CSSPrimitiveValue> shape;
+
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ if (value->unit == CSSPrimitiveValue::CSS_STRING) {
+ if (fill || shape || (valueListSize != 1 && !inShorthand()))
+ return false;
+ addProperty(CSSPropertyWebkitTextEmphasisStyle, createPrimitiveStringValue(value), important);
+ m_valueList->next();
+ return true;
+ }
+
+ if (value->id == CSSValueNone) {
+ if (fill || shape || (valueListSize != 1 && !inShorthand()))
+ return false;
+ addProperty(CSSPropertyWebkitTextEmphasisStyle, cssValuePool()->createIdentifierValue(CSSValueNone), important);
+ m_valueList->next();
+ return true;
+ }
+
+ if (value->id == CSSValueOpen || value->id == CSSValueFilled) {
+ if (fill)
+ return false;
+ fill = cssValuePool()->createIdentifierValue(value->id);
+ } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) {
+ if (shape)
+ return false;
+ shape = cssValuePool()->createIdentifierValue(value->id);
+ } else if (!inShorthand())
+ return false;
+ else
+ break;
+ }
+
+ if (fill && shape) {
+ RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated();
+ parsedValues->append(fill.release());
+ parsedValues->append(shape.release());
+ addProperty(CSSPropertyWebkitTextEmphasisStyle, parsedValues.release(), important);
+ return true;
+ }
+ if (fill) {
+ addProperty(CSSPropertyWebkitTextEmphasisStyle, fill.release(), important);
+ return true;
+ }
+ if (shape) {
+ addProperty(CSSPropertyWebkitTextEmphasisStyle, shape.release(), important);
+ return true;
+ }
+
+ return false;
+}
+
+bool CSSParser::parseLineBoxContain(bool important)
+{
+ LineBoxContain lineBoxContain = LineBoxContainNone;
+
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ if (value->id == CSSValueBlock) {
+ if (lineBoxContain & LineBoxContainBlock)
+ return false;
+ lineBoxContain |= LineBoxContainBlock;
+ } else if (value->id == CSSValueInline) {
+ if (lineBoxContain & LineBoxContainInline)
+ return false;
+ lineBoxContain |= LineBoxContainInline;
+ } else if (value->id == CSSValueFont) {
+ if (lineBoxContain & LineBoxContainFont)
+ return false;
+ lineBoxContain |= LineBoxContainFont;
+ } else if (value->id == CSSValueGlyphs) {
+ if (lineBoxContain & LineBoxContainGlyphs)
+ return false;
+ lineBoxContain |= LineBoxContainGlyphs;
+ } else if (value->id == CSSValueReplaced) {
+ if (lineBoxContain & LineBoxContainReplaced)
+ return false;
+ lineBoxContain |= LineBoxContainReplaced;
+ } else if (value->id == CSSValueInlineBox) {
+ if (lineBoxContain & LineBoxContainInlineBox)
+ return false;
+ lineBoxContain |= LineBoxContainInlineBox;
+ } else
+ return false;
+ }
+
+ if (!lineBoxContain)
+ return false;
+
+ addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important);
+ return true;
+}
+
+bool CSSParser::parseFontFeatureTag(CSSValueList* settings)
+{
+ // Feature tag name consists of 4-letter characters.
+ static const int tagNameLength = 4;
+
+ CSSParserValue* value = m_valueList->current();
+ // Feature tag name comes first
+ if (value->unit != CSSPrimitiveValue::CSS_STRING && value->unit != CSSPrimitiveValue::CSS_IDENT)
+ return false;
+ if (value->string.length != tagNameLength)
+ return false;
+ for (int i = 0; i < tagNameLength; ++i) {
+ // Limits the range of characters to 0x20-0x7E, following the tag name rules defiend in the OpenType specification.
+ UChar character = value->string.characters[i];
+ if (character < 0x20 || character > 0x7E)
+ return false;
+ }
+
+ String tag = value->string;
+ int tagValue = 1;
+ // Feature tag values could follow: <integer> | on | off
+ value = m_valueList->next();
+ if (value) {
+ if (value->unit == CSSPrimitiveValue::CSS_NUMBER && value->isInt && value->fValue >= 0) {
+ tagValue = clampToInteger(value->fValue);
+ if (tagValue < 0)
+ return false;
+ m_valueList->next();
+ } else if (value->id == CSSValueOn || value->id == CSSValueOff) {
+ tagValue = value->id == CSSValueOn;
+ m_valueList->next();
+ }
+ }
+ settings->append(FontFeatureValue::create(tag, tagValue));
+ return true;
+}
+
+bool CSSParser::parseFontFeatureSettings(bool important)
+{
+ if (m_valueList->size() == 1 && m_valueList->current()->id == CSSValueNormal) {
+ RefPtr<CSSPrimitiveValue> normalValue = cssValuePool()->createIdentifierValue(CSSValueNormal);
+ m_valueList->next();
+ addProperty(CSSPropertyWebkitFontFeatureSettings, normalValue.release(), important);
+ return true;
+ }
+
+ RefPtr<CSSValueList> settings = CSSValueList::createCommaSeparated();
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ if (!parseFontFeatureTag(settings.get()))
+ return false;
+
+ // If the list isn't parsed fully, the current value should be comma.
+ value = m_valueList->current();
+ if (value && !(value->unit == CSSParserValue::Operator && value->iValue == ','))
+ return false;
+ }
+ if (settings->length()) {
+ addProperty(CSSPropertyWebkitFontFeatureSettings, settings.release(), important);
+ return true;
+ }
+ return false;
+}
+
+static inline int yyerror(const char*) { return 1; }
+
+#define END_TOKEN 0
+
+#include "CSSGrammar.h"
+
+int CSSParser::lex(void* yylvalWithoutType)
+{
+ YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType);
+ int length;
+
+ lex();
+
+ UChar* t = text(&length);
+
+ switch (token()) {
+ case WHITESPACE:
+ case SGML_CD:
+ case INCLUDES:
+ case DASHMATCH:
+ 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);
+ break;
+
+ default:
+ break;
+ }
+
+ return token();
+}
+
+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--;
+ 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;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // process escapes
+ UChar* out = start;
+ UChar* escape = 0;
+
+ bool sawEscape = false;
+
+ 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;
+ }
+ // in all other cases copy the char to output
+ // ###
+ *out++ = *current;
+ escape = 0;
+ continue;
+ }
+ if (escape == current - 2 && yyTok == STRING &&
+ *(current-1) == '\r' && *current == '\n') {
+ escape = 0;
+ continue;
+ }
+ 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++;
+ }
+ // 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;
+ }
+ *out++ = *current;
+ }
+ if (escape) {
+ // add escaped char
+ unsigned uc = 0;
+ escape++;
+ while (escape < start+l) {
+ uc *= 16;
+ uc += toASCIIHexValue(*escape);
+ escape++;
+ }
+ // can't handle chars outside ucs2
+ if (uc > 0xffff)
+ uc = 0xfffd;
+ *out++ = uc;
+ }
+
+ *length = out - start;
+
+ // 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);
+
+ return start;
+}
+
+void CSSParser::countLines()
+{
+ for (UChar* current = yytext; current < yytext + yyleng; ++current) {
+ if (*current == '\n')
+ ++m_lineNumber;
+ }
+}
+
+CSSParserSelector* CSSParser::createFloatingSelector()
+{
+ CSSParserSelector* selector = new CSSParserSelector;
+ m_floatingSelectors.add(selector);
+ return selector;
+}
+
+PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* selector)
+{
+ if (selector) {
+ ASSERT(m_floatingSelectors.contains(selector));
+ m_floatingSelectors.remove(selector);
+ }
+ return adoptPtr(selector);
+}
+
+Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector()
+{
+ Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
+ m_floatingSelectorVectors.add(selectorVector);
+ return selectorVector;
+}
+
+PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
+{
+ if (selectorVector) {
+ ASSERT(m_floatingSelectorVectors.contains(selectorVector));
+ m_floatingSelectorVectors.remove(selectorVector);
+ }
+ return adoptPtr(selectorVector);
+}
+
+CSSParserValueList* CSSParser::createFloatingValueList()
+{
+ CSSParserValueList* list = new CSSParserValueList;
+ m_floatingValueLists.add(list);
+ return list;
+}
+
+PassOwnPtr<CSSParserValueList> CSSParser::sinkFloatingValueList(CSSParserValueList* list)
+{
+ if (list) {
+ ASSERT(m_floatingValueLists.contains(list));
+ m_floatingValueLists.remove(list);
+ }
+ return adoptPtr(list);
+}
+
+CSSParserFunction* CSSParser::createFloatingFunction()
+{
+ CSSParserFunction* function = new CSSParserFunction;
+ m_floatingFunctions.add(function);
+ return function;
+}
+
+PassOwnPtr<CSSParserFunction> CSSParser::sinkFloatingFunction(CSSParserFunction* function)
+{
+ if (function) {
+ ASSERT(m_floatingFunctions.contains(function));
+ m_floatingFunctions.remove(function);
+ }
+ return adoptPtr(function);
+}
+
+CSSParserValue& CSSParser::sinkFloatingValue(CSSParserValue& value)
+{
+ if (value.unit == CSSParserValue::Function) {
+ ASSERT(m_floatingFunctions.contains(value.function));
+ m_floatingFunctions.remove(value.function);
+ }
+ return value;
+}
+
+MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
+{
+ m_floatingMediaQueryExp = MediaQueryExp::create(mediaFeature, values);
+ return m_floatingMediaQueryExp.get();
+}
+
+PassOwnPtr<MediaQueryExp> CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
+{
+ ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
+ return m_floatingMediaQueryExp.release();
+}
+
+Vector<OwnPtr<MediaQueryExp> >* CSSParser::createFloatingMediaQueryExpList()
+{
+ m_floatingMediaQueryExpList = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >);
+ return m_floatingMediaQueryExpList.get();
+}
+
+PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > CSSParser::sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >* list)
+{
+ ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
+ return m_floatingMediaQueryExpList.release();
+}
+
+MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const String& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
+{
+ m_floatingMediaQuery = adoptPtr(new MediaQuery(restrictor, mediaType, expressions));
+ return m_floatingMediaQuery.get();
+}
+
+MediaQuery* CSSParser::createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions)
+{
+ return createFloatingMediaQuery(MediaQuery::None, "all", expressions);
+}
+
+PassOwnPtr<MediaQuery> CSSParser::sinkFloatingMediaQuery(MediaQuery* query)
+{
+ ASSERT_UNUSED(query, query == m_floatingMediaQuery);
+ return m_floatingMediaQuery.release();
+}
+
+MediaList* CSSParser::createMediaList()
+{
+ RefPtr<MediaList> list = MediaList::create();
+ MediaList* result = list.get();
+ m_parsedMediaLists.append(list.release());
+ return result;
+}
+
+CSSRule* CSSParser::createCharsetRule(const CSSParserString& charset)
+{
+ if (!m_styleSheet)
+ return 0;
+ RefPtr<CSSCharsetRule> rule = CSSCharsetRule::create(m_styleSheet, charset);
+ CSSCharsetRule* result = rule.get();
+ m_parsedRules.append(rule.release());
+ return result;
+}
+
+CSSRule* CSSParser::createImportRule(const CSSParserString& url, MediaList* media)
+{
+ if (!media || !m_styleSheet || !m_allowImportRules)
+ return 0;
+ RefPtr<CSSImportRule> rule = CSSImportRule::create(m_styleSheet, url, media);
+ CSSImportRule* result = rule.get();
+ m_parsedRules.append(rule.release());
+ return result;
+}
+
+CSSRule* CSSParser::createMediaRule(MediaList* media, CSSRuleList* rules)
+{
+ if (!media || !rules || !m_styleSheet)
+ return 0;
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ RefPtr<CSSMediaRule> rule = CSSMediaRule::create(m_styleSheet, media, rules);
+ CSSMediaRule* result = rule.get();
+ m_parsedRules.append(rule.release());
+ return result;
+}
+
+CSSRuleList* CSSParser::createRuleList()
+{
+ RefPtr<CSSRuleList> list = CSSRuleList::create();
+ CSSRuleList* listPtr = list.get();
+
+ m_parsedRuleLists.append(list.release());
+ return listPtr;
+}
+
+WebKitCSSKeyframesRule* CSSParser::createKeyframesRule()
+{
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ RefPtr<WebKitCSSKeyframesRule> rule = WebKitCSSKeyframesRule::create(m_styleSheet);
+ WebKitCSSKeyframesRule* rulePtr = rule.get();
+ m_parsedRules.append(rule.release());
+ return rulePtr;
+}
+
+CSSRule* CSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
+{
+ CSSStyleRule* result = 0;
+ markRuleBodyEnd();
+ if (selectors) {
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ RefPtr<CSSStyleRule> rule = CSSStyleRule::create(m_styleSheet, m_lastSelectorLineNumber);
+ rule->adoptSelectorVector(*selectors);
+ if (m_hasFontFaceOnlyValues)
+ deleteFontFaceOnlyValues();
+ rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties));
+ result = rule.get();
+ m_parsedRules.append(rule.release());
+ if (m_ruleRangeMap) {
+ ASSERT(m_currentRuleData);
+ m_currentRuleData->styleSourceData->styleBodyRange = m_ruleBodyRange;
+ m_currentRuleData->selectorListRange = m_selectorListRange;
+ m_ruleRangeMap->set(result, m_currentRuleData.release());
+ m_currentRuleData = CSSRuleSourceData::create();
+ m_currentRuleData->styleSourceData = CSSStyleSourceData::create();
+ m_inStyleRuleOrDeclaration = false;
+ }
+ }
+ resetSelectorListMarks();
+ resetRuleBodyMarks();
+ clearProperties();
+ return result;
+}
+
+CSSRule* CSSParser::createFontFaceRule()
+{
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ for (unsigned i = 0; i < m_numParsedProperties; ++i) {
+ CSSProperty* property = m_parsedProperties[i];
+ int id = property->id();
+ if ((id == CSSPropertyFontWeight || id == CSSPropertyFontStyle || id == CSSPropertyFontVariant) && property->value()->isPrimitiveValue()) {
+ RefPtr<CSSValue> value = property->m_value.release();
+ property->m_value = CSSValueList::createCommaSeparated();
+ static_cast<CSSValueList*>(property->value())->append(value.release());
+ } else if (id == CSSPropertyFontFamily && (!property->value()->isValueList() || static_cast<CSSValueList*>(property->value())->length() != 1)) {
+ // Unlike font-family property, font-family descriptor in @font-face rule
+ // has to be a value list with exactly one family name. It cannot have a
+ // have 'initial' value and cannot 'inherit' from parent.
+ // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
+ clearProperties();
+ return 0;
+ }
+ }
+ RefPtr<CSSFontFaceRule> rule = CSSFontFaceRule::create(m_styleSheet);
+ rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties));
+ clearProperties();
+ CSSFontFaceRule* result = rule.get();
+ m_parsedRules.append(rule.release());
+ return result;
+}
+
+void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
+{
+ if (!m_styleSheet || !m_allowNamespaceDeclarations)
+ return;
+ m_allowImportRules = false;
+ m_styleSheet->addNamespace(this, prefix, uri);
+}
+
+void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers)
+{
+ AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
+ QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace);
+ if (!specifiers->isUnknownPseudoElement()) {
+ specifiers->setTag(tag);
+ return;
+ }
+
+ CSSParserSelector* lastShadowDescendant = specifiers;
+ CSSParserSelector* history = specifiers;
+ while (history->tagHistory()) {
+ history = history->tagHistory();
+ if (history->hasShadowDescendant())
+ lastShadowDescendant = history;
+ }
+
+ if (lastShadowDescendant->tagHistory()) {
+ lastShadowDescendant->tagHistory()->setTag(tag);
+ return;
+ }
+
+ // For shadow-ID pseudo-elements to be correctly matched, the ShadowDescendant combinator has to be used.
+ // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
+ OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector);
+ elementNameSelector->setTag(tag);
+ lastShadowDescendant->setTagHistory(elementNameSelector.release());
+ lastShadowDescendant->setRelation(CSSSelector::ShadowDescendant);
+}
+
+CSSParserSelector* CSSParser::updateSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
+{
+ if (newSpecifier->isUnknownPseudoElement()) {
+ // Unknown pseudo element always goes at the top of selector chain.
+ newSpecifier->appendTagHistory(CSSSelector::ShadowDescendant, sinkFloatingSelector(specifiers));
+ return newSpecifier;
+ }
+ if (specifiers->isUnknownPseudoElement()) {
+ // Specifiers for unknown pseudo element go right behind it in the chain.
+ specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowDescendant);
+ return specifiers;
+ }
+ specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
+ return specifiers;
+}
+
+CSSRule* CSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
+{
+ // FIXME: Margin at-rules are ignored.
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ CSSPageRule* pageRule = 0;
+ if (pageSelector) {
+ RefPtr<CSSPageRule> rule = CSSPageRule::create(m_styleSheet, m_lastSelectorLineNumber);
+ Vector<OwnPtr<CSSParserSelector> > selectorVector;
+ selectorVector.append(pageSelector);
+ rule->adoptSelectorVector(selectorVector);
+ rule->setDeclaration(CSSMutableStyleDeclaration::create(rule.get(), m_parsedProperties, m_numParsedProperties));
+ pageRule = rule.get();
+ m_parsedRules.append(rule.release());
+ }
+ clearProperties();
+ return pageRule;
+}
+
+void CSSParser::setReusableRegionSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectors)
+{
+ if (selectors)
+ m_reusableRegionSelectorVector.swap(*selectors);
+}
+
+CSSRule* CSSParser::createRegionRule(Vector<OwnPtr<CSSParserSelector> >* regionSelector, CSSRuleList* rules)
+{
+ if (!regionSelector || !rules)
+ return 0;
+
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+
+ RefPtr<WebKitCSSRegionRule> regionRule = WebKitCSSRegionRule::create(m_styleSheet, regionSelector, rules);
+
+ WebKitCSSRegionRule* result = regionRule.get();
+ m_parsedRules.append(regionRule.release());
+
+ return result;
+}
+
+CSSRule* CSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
+{
+ // FIXME: Implement margin at-rule here, using:
+ // - marginBox: margin box
+ // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_numParsedProperties) are for this at-rule.
+ // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
+
+ endDeclarationsForMarginBox();
+ return 0; // until this method is implemented.
+}
+
+void CSSParser::startDeclarationsForMarginBox()
+{
+ m_numParsedPropertiesBeforeMarginBox = m_numParsedProperties;
+}
+
+void CSSParser::endDeclarationsForMarginBox()
+{
+ ASSERT(m_numParsedPropertiesBeforeMarginBox != INVALID_NUM_PARSED_PROPERTIES);
+ rollbackLastProperties(m_numParsedProperties - m_numParsedPropertiesBeforeMarginBox);
+ m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
+}
+
+void CSSParser::deleteFontFaceOnlyValues()
+{
+ ASSERT(m_hasFontFaceOnlyValues);
+ int deletedProperties = 0;
+
+ for (unsigned i = 0; i < m_numParsedProperties; ++i) {
+ CSSProperty* property = m_parsedProperties[i];
+ int id = property->id();
+ if ((id == CSSPropertyFontWeight || id == CSSPropertyFontStyle || id == CSSPropertyFontVariant) && property->value()->isValueList()) {
+ delete property;
+ deletedProperties++;
+ } else if (deletedProperties)
+ m_parsedProperties[i - deletedProperties] = m_parsedProperties[i];
+ }
+
+ m_numParsedProperties -= deletedProperties;
+}
+
+WebKitCSSKeyframeRule* CSSParser::createKeyframeRule(CSSParserValueList* keys)
+{
+ // Create a key string from the passed keys
+ String keyString;
+ for (unsigned i = 0; i < keys->size(); ++i) {
+ float key = static_cast<float>(keys->valueAt(i)->fValue);
+ if (i != 0)
+ keyString += ",";
+ keyString += String::number(key);
+ keyString += "%";
+ }
+
+ RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create(m_styleSheet);
+ keyframe->setKeyText(keyString);
+ keyframe->setDeclaration(CSSMutableStyleDeclaration::create(keyframe.get(), m_parsedProperties, m_numParsedProperties));
+
+ clearProperties();
+
+ WebKitCSSKeyframeRule* keyframePtr = keyframe.get();
+ m_parsedRules.append(keyframe.release());
+ return keyframePtr;
+}
+
+void CSSParser::invalidBlockHit()
+{
+ if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
+ m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
+}
+
+void CSSParser::updateLastSelectorLineAndPosition()
+{
+ m_lastSelectorLineNumber = m_lineNumber;
+ markRuleBodyStart();
+}
+
+void CSSParser::updateLastMediaLine(MediaList* media)
+{
+ media->setLastLine(m_lineNumber);
+}
+
+void CSSParser::markSelectorListStart()
+{
+ m_selectorListRange.start = yytext - m_data.get();
+}
+
+void CSSParser::markSelectorListEnd()
+{
+ if (!m_currentRuleData)
+ return;
+ UChar* listEnd = yytext;
+ while (listEnd > m_data.get() + 1) {
+ if (isHTMLSpace(*(listEnd - 1)))
+ --listEnd;
+ else
+ break;
+ }
+ m_selectorListRange.end = listEnd - m_data.get();
+}
+
+void CSSParser::markRuleBodyStart()
+{
+ unsigned offset = yytext - m_data.get();
+ if (*yytext == '{')
+ ++offset; // Skip the rule body opening brace.
+ if (offset > m_ruleBodyRange.start)
+ m_ruleBodyRange.start = offset;
+ m_inStyleRuleOrDeclaration = true;
+}
+
+void CSSParser::markRuleBodyEnd()
+{
+ unsigned offset = yytext - m_data.get();
+ if (offset > m_ruleBodyRange.end)
+ m_ruleBodyRange.end = offset;
+}
+
+void CSSParser::markPropertyStart()
+{
+ if (!m_inStyleRuleOrDeclaration)
+ return;
+ m_propertyRange.start = yytext - m_data.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.
+ ++offset;
+ m_propertyRange.end = offset;
+ if (m_propertyRange.start != UINT_MAX && m_currentRuleData) {
+ // This stuff is only executed when the style data retrieval is requested by client.
+ 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();
+ if (propertyString.endsWith(";", true))
+ propertyString = propertyString.left(propertyString.length() - 1);
+ size_t colonIndex = propertyString.find(":");
+ ASSERT(colonIndex != notFound);
+
+ String name = propertyString.left(colonIndex).stripWhiteSpace();
+ String value = propertyString.substring(colonIndex + 1, propertyString.length()).stripWhiteSpace();
+ // The property range is relative to the declaration start offset.
+ m_currentRuleData->styleSourceData->propertyData.append(
+ CSSPropertySourceData(name, value, isImportantFound, isPropertyParsed, SourceRange(start - m_ruleBodyRange.start, end - m_ruleBodyRange.start)));
+ }
+ resetPropertyMarks();
+}
+
+static int cssPropertyID(const UChar* propertyName, unsigned length)
+{
+ if (!length)
+ return 0;
+ if (length > maxCSSPropertyNameLength)
+ return 0;
+
+ char buffer[maxCSSPropertyNameLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
+
+ for (unsigned i = 0; i != length; ++i) {
+ UChar c = propertyName[i];
+ if (c == 0 || c >= 0x7F)
+ return 0; // illegal character
+ buffer[i] = toASCIILower(c);
+ }
+ buffer[length] = '\0';
+
+ const char* name = buffer;
+ if (buffer[0] == '-') {
+ // If the prefix is -apple- or -khtml-, change it to -webkit-.
+ // This makes the string one character longer.
+ if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) {
+ memmove(buffer + 7, buffer + 6, length + 1 - 6);
+ memcpy(buffer, "-webkit", 7);
+ ++length;
+ }
+
+#if PLATFORM(IOS)
+ if (!strcmp(buffer, "-webkit-hyphenate-locale")) {
+ // Worked in iOS 4.2.
+ const char* const webkitLocale = "-webkit-locale";
+ name = webkitLocale;
+ length = strlen(webkitLocale);
+ }
+#endif
+ }
+
+ const Property* hashTableEntry = findProperty(name, length);
+ return hashTableEntry ? hashTableEntry->id : 0;
+}
+
+int cssPropertyID(const String& string)
+{
+ return cssPropertyID(string.characters(), string.length());
+}
+
+int cssPropertyID(const CSSParserString& string)
+{
+ return cssPropertyID(string.characters, string.length);
+}
+
+int cssValueKeywordID(const CSSParserString& string)
+{
+ unsigned length = string.length;
+ if (!length)
+ return 0;
+ if (length > maxCSSValueKeywordLength)
+ return 0;
+
+ char buffer[maxCSSValueKeywordLength + 1 + 1]; // 1 to turn "apple"/"khtml" into "webkit", 1 for null character
+
+ for (unsigned i = 0; i != length; ++i) {
+ UChar c = string.characters[i];
+ if (c == 0 || c >= 0x7F)
+ return 0; // illegal character
+ buffer[i] = WTF::toASCIILower(c);
+ }
+ buffer[length] = '\0';
+
+ if (buffer[0] == '-') {
+ // If the prefix is -apple- or -khtml-, change it to -webkit-.
+ // This makes the string one character longer.
+ if (hasPrefix(buffer, length, "-apple-") || hasPrefix(buffer, length, "-khtml-")) {
+ memmove(buffer + 7, buffer + 6, length + 1 - 6);
+ memcpy(buffer, "-webkit", 7);
+ ++length;
+ }
+ }
+
+ const Value* hashTableEntry = findValue(buffer, length);
+ return hashTableEntry ? hashTableEntry->id : 0;
+}
+
+// "ident" from the CSS tokenizer, minus backslash-escape sequences
+static bool isCSSTokenizerIdentifier(const String& string)
+{
+ const UChar* p = string.characters();
+ const UChar* end = p + string.length();
+
+ // -?
+ if (p != end && p[0] == '-')
+ ++p;
+
+ // {nmstart}
+ if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0])))
+ return false;
+ ++p;
+
+ // {nmchar}*
+ for (; p != end; ++p) {
+ if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0])))
+ return false;
+ }
+
+ return true;
+}
+
+// "url" from the CSS tokenizer, minus backslash-escape sequences
+static bool isCSSTokenizerURL(const String& string)
+{
+ const UChar* p = string.characters();
+ const UChar* end = p + string.length();
+
+ for (; p != end; ++p) {
+ UChar c = p[0];
+ switch (c) {
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ break;
+ default:
+ if (c < '*')
+ return false;
+ if (c <= '~')
+ break;
+ if (c < 128)
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// We use single quotes for now because markup.cpp uses double quotes.
+String quoteCSSString(const String& string)
+{
+ // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one.
+ // Please see below for the actual logic.
+ unsigned quotedStringSize = 2; // Two quotes surrounding the entire string.
+ bool afterEscape = false;
+ for (unsigned i = 0; i < string.length(); ++i) {
+ UChar ch = string[i];
+ if (ch == '\\' || ch == '\'') {
+ quotedStringSize += 2;
+ afterEscape = false;
+ } else if (ch < 0x20 || ch == 0x7F) {
+ quotedStringSize += 2 + (ch >= 0x10);
+ afterEscape = true;
+ } else {
+ quotedStringSize += 1 + (afterEscape && (isASCIIHexDigit(ch) || ch == ' '));
+ afterEscape = false;
+ }
+ }
+
+ StringBuffer<UChar> buffer(quotedStringSize);
+ unsigned index = 0;
+ buffer[index++] = '\'';
+ afterEscape = false;
+ for (unsigned i = 0; i < string.length(); ++i) {
+ UChar ch = string[i];
+ if (ch == '\\' || ch == '\'') {
+ buffer[index++] = '\\';
+ buffer[index++] = ch;
+ afterEscape = false;
+ } else if (ch < 0x20 || ch == 0x7F) { // Control characters.
+ buffer[index++] = '\\';
+ placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase);
+ afterEscape = true;
+ } else {
+ // Space character may be required to separate backslash-escape sequence and normal characters.
+ if (afterEscape && (isASCIIHexDigit(ch) || ch == ' '))
+ buffer[index++] = ' ';
+ buffer[index++] = ch;
+ afterEscape = false;
+ }
+ }
+ buffer[index++] = '\'';
+
+ ASSERT(quotedStringSize == index);
+ return String::adopt(buffer);
+}
+
+String quoteCSSStringIfNeeded(const String& string)
+{
+ return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string);
+}
+
+String quoteCSSURLIfNeeded(const String& string)
+{
+ return isCSSTokenizerURL(string) ? string : quoteCSSString(string);
+}
+
+bool isValidNthToken(const CSSParserString& token)
+{
+ // The tokenizer checks for the construct of an+b.
+ // However, since the {ident} rule precedes the {nth} rule, some of those
+ // tokens are identified as string literal. Furthermore we need to accept
+ // "odd" and "even" which does not match to an+b.
+ return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even")
+ || 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
new file mode 100644
index 000000000..adc19025a
--- /dev/null
+++ b/Source/WebCore/css/CSSParser.h
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 CSSParser_h
+#define CSSParser_h
+
+#include "CSSGradientValue.h"
+#include "CSSParserValues.h"
+#include "CSSPropertySourceData.h"
+#include "CSSSelector.h"
+#include "Color.h"
+#include "MediaQuery.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
+
+#if ENABLE(CSS_FILTERS)
+#include "WebKitCSSFilterValue.h"
+#endif
+
+namespace WebCore {
+
+class CSSBorderImageSliceValue;
+class CSSMappedAttributeDeclaration;
+class CSSMutableStyleDeclaration;
+class CSSPrimitiveValue;
+class CSSValuePool;
+class CSSProperty;
+class CSSRule;
+class CSSRuleList;
+class CSSSelectorList;
+class CSSStyleSheet;
+class CSSValue;
+class CSSValueList;
+class CSSWrapShape;
+class Document;
+class MediaList;
+class MediaQueryExp;
+class StyledElement;
+class WebKitCSSKeyframeRule;
+class WebKitCSSKeyframesRule;
+
+class CSSParser {
+public:
+ CSSParser(bool strictParsing = true);
+ ~CSSParser();
+
+ void parseSheet(CSSStyleSheet*, const String&, int startLineNumber = 0, StyleRuleRangeMap* ruleRangeMap = 0);
+ PassRefPtr<CSSRule> parseRule(CSSStyleSheet*, const String&);
+ PassRefPtr<WebKitCSSKeyframeRule> parseKeyframeRule(CSSStyleSheet*, const String&);
+ static bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important, bool strict);
+ static bool parseColor(RGBA32& color, const String&, bool strict = false);
+ static bool parseSystemColor(RGBA32& color, const String&, Document*);
+ PassRefPtr<CSSPrimitiveValue> parseValidPrimitive(int propId, CSSParserValue*);
+ bool parseDeclaration(CSSMutableStyleDeclaration*, const String&, RefPtr<CSSStyleSourceData>* = 0, CSSStyleSheet* contextStyleSheet = 0);
+ bool parseMediaQuery(MediaList*, const String&);
+
+ static bool parseMappedAttributeValue(CSSMappedAttributeDeclaration*, StyledElement*, int propertyId, const String&);
+
+ Document* findDocument() const;
+
+ CSSValuePool* cssValuePool() const { return m_cssValuePool.get(); }
+
+ void addProperty(int propId, PassRefPtr<CSSValue>, bool important, bool implicit = false);
+ void rollbackLastProperties(int num);
+ bool hasProperties() const { return m_numParsedProperties > 0; }
+
+ bool parseValue(int propId, bool important);
+ bool parseShorthand(int propId, const int* properties, int numProperties, bool important);
+ bool parse4Values(int propId, const int* properties, bool important);
+ bool parseContent(int propId, bool important);
+ bool parseQuotes(int propId, bool important);
+
+ PassRefPtr<CSSValue> parseAttr(CSSParserValueList* args);
+
+ PassRefPtr<CSSValue> parseBackgroundColor();
+
+ bool parseFillImage(CSSParserValueList*, RefPtr<CSSValue>&);
+
+ enum FillPositionFlag { InvalidFillPosition = 0, AmbiguousFillPosition = 1, XFillPosition = 2, YFillPosition = 4 };
+ PassRefPtr<CSSValue> parseFillPositionComponent(CSSParserValueList*, unsigned& cumulativeFlags, FillPositionFlag& individualFlag);
+ PassRefPtr<CSSValue> parseFillPositionX(CSSParserValueList*);
+ PassRefPtr<CSSValue> parseFillPositionY(CSSParserValueList*);
+ void parseFillPosition(CSSParserValueList*, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
+
+ void parseFillRepeat(RefPtr<CSSValue>&, RefPtr<CSSValue>&);
+ PassRefPtr<CSSValue> parseFillSize(int propId, bool &allowComma);
+
+ bool parseFillProperty(int propId, int& propId1, int& propId2, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
+ bool parseFillShorthand(int propId, const int* properties, int numProperties, bool important);
+
+ void addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval);
+
+ void addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval);
+
+ PassRefPtr<CSSValue> parseAnimationDelay();
+ PassRefPtr<CSSValue> parseAnimationDirection();
+ PassRefPtr<CSSValue> parseAnimationDuration();
+ PassRefPtr<CSSValue> parseAnimationFillMode();
+ PassRefPtr<CSSValue> parseAnimationIterationCount();
+ PassRefPtr<CSSValue> parseAnimationName();
+ PassRefPtr<CSSValue> parseAnimationPlayState();
+ PassRefPtr<CSSValue> parseAnimationProperty();
+ PassRefPtr<CSSValue> parseAnimationTimingFunction();
+
+ bool parseTransformOriginShorthand(RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
+ bool parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result);
+ bool parseAnimationProperty(int propId, RefPtr<CSSValue>&);
+ bool parseTransitionShorthand(bool important);
+ bool parseAnimationShorthand(bool important);
+
+#if ENABLE(CSS_GRID_LAYOUT)
+ bool parseGridTrackList(int propId, bool important);
+#endif
+
+ bool parseDashboardRegions(int propId, bool important);
+
+ bool parseShape(int propId, bool important);
+
+ bool parseWrapShape(bool shapeInside, bool important);
+ PassRefPtr<CSSWrapShape> parseWrapShapeRect(CSSParserValueList* args);
+ PassRefPtr<CSSWrapShape> parseWrapShapeCircle(CSSParserValueList* args);
+ PassRefPtr<CSSWrapShape> parseWrapShapeEllipse(CSSParserValueList* args);
+ PassRefPtr<CSSWrapShape> parseWrapShapePolygon(CSSParserValueList* args);
+
+ bool parseFont(bool important);
+ PassRefPtr<CSSValueList> parseFontFamily();
+
+ bool parseCounter(int propId, int defaultValue, bool important);
+ PassRefPtr<CSSValue> parseCounterContent(CSSParserValueList* args, bool counters);
+
+ bool parseColorParameters(CSSParserValue*, int* colorValues, bool parseAlpha);
+ bool parseHSLParameters(CSSParserValue*, double* colorValues, bool parseAlpha);
+ PassRefPtr<CSSPrimitiveValue> parseColor(CSSParserValue* = 0);
+ bool parseColorFromValue(CSSParserValue*, RGBA32&);
+ void parseSelector(const String&, Document* doc, CSSSelectorList&);
+
+ static bool fastParseColor(RGBA32&, const String&, bool strict);
+
+ bool parseFontStyle(bool important);
+ bool parseFontVariant(bool important);
+ bool parseFontWeight(bool important);
+ bool parseFontFaceSrc();
+ bool parseFontFaceUnicodeRange();
+
+#if ENABLE(SVG)
+ bool parseSVGValue(int propId, bool important);
+ PassRefPtr<CSSValue> parseSVGPaint();
+ PassRefPtr<CSSValue> parseSVGColor();
+ PassRefPtr<CSSValue> parseSVGStrokeDasharray();
+#endif
+
+ // CSS3 Parsing Routines (for properties specific to CSS3)
+ PassRefPtr<CSSValueList> parseShadow(CSSParserValueList*, int propId);
+ bool parseBorderImage(int propId, RefPtr<CSSValue>&);
+ bool parseBorderImageRepeat(RefPtr<CSSValue>&);
+ bool parseBorderImageSlice(int propId, RefPtr<CSSBorderImageSliceValue>&);
+ bool parseBorderImageWidth(RefPtr<CSSPrimitiveValue>&);
+ bool parseBorderImageOutset(RefPtr<CSSPrimitiveValue>&);
+ bool parseBorderRadius(int propId, bool important);
+
+ bool parseAspectRatio(bool important);
+
+ bool parseReflect(int propId, bool important);
+
+ bool parseFlex(int propId, bool important);
+
+ // Image generators
+ bool parseCanvas(CSSParserValueList*, RefPtr<CSSValue>&);
+
+ bool parseDeprecatedGradient(CSSParserValueList*, RefPtr<CSSValue>&);
+ bool parseLinearGradient(CSSParserValueList*, RefPtr<CSSValue>&, CSSGradientRepeat repeating);
+ bool parseRadialGradient(CSSParserValueList*, RefPtr<CSSValue>&, CSSGradientRepeat repeating);
+ bool parseGradientColorStops(CSSParserValueList*, CSSGradientValue*, bool expectComma);
+
+ bool parseCrossfade(CSSParserValueList*, RefPtr<CSSValue>&);
+
+#if ENABLE(CSS_FILTERS)
+ PassRefPtr<CSSValueList> parseFilter();
+ PassRefPtr<WebKitCSSFilterValue> parseBuiltinFilterArguments(CSSParserValueList*, WebKitCSSFilterValue::FilterOperationType);
+#if ENABLE(CSS_SHADERS)
+ PassRefPtr<WebKitCSSFilterValue> parseCustomFilter(CSSParserValue*);
+#endif
+#endif
+
+ PassRefPtr<CSSValueList> parseTransform();
+ bool parseTransformOrigin(int propId, int& propId1, int& propId2, int& propId3, RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
+ bool parsePerspectiveOrigin(int propId, int& propId1, int& propId2, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
+
+ bool parseTextEmphasisStyle(bool important);
+
+ bool parseLineBoxContain(bool important);
+
+ bool parseFontFeatureTag(CSSValueList*);
+ bool parseFontFeatureSettings(bool important);
+
+ bool parseFlowThread(int propId, bool important);
+ bool parseRegionThread(int propId, bool important);
+
+ int yyparse();
+
+ CSSParserSelector* createFloatingSelector();
+ PassOwnPtr<CSSParserSelector> sinkFloatingSelector(CSSParserSelector*);
+
+ Vector<OwnPtr<CSSParserSelector> >* createFloatingSelectorVector();
+ PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >*);
+
+ CSSParserValueList* createFloatingValueList();
+ PassOwnPtr<CSSParserValueList> sinkFloatingValueList(CSSParserValueList*);
+
+ CSSParserFunction* createFloatingFunction();
+ PassOwnPtr<CSSParserFunction> sinkFloatingFunction(CSSParserFunction*);
+
+ CSSParserValue& sinkFloatingValue(CSSParserValue&);
+
+ MediaList* createMediaList();
+ CSSRule* createCharsetRule(const CSSParserString&);
+ CSSRule* createImportRule(const CSSParserString&, MediaList*);
+ WebKitCSSKeyframeRule* createKeyframeRule(CSSParserValueList*);
+ WebKitCSSKeyframesRule* createKeyframesRule();
+ CSSRule* createMediaRule(MediaList*, CSSRuleList*);
+ CSSRuleList* createRuleList();
+ CSSRule* createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors);
+ CSSRule* createFontFaceRule();
+ CSSRule* createPageRule(PassOwnPtr<CSSParserSelector> pageSelector);
+ CSSRule* createRegionRule(Vector<OwnPtr<CSSParserSelector> >* regionSelector, CSSRuleList* rules);
+ CSSRule* createMarginAtRule(CSSSelector::MarginBoxType marginBox);
+ void startDeclarationsForMarginBox();
+ void endDeclarationsForMarginBox();
+
+ MediaQueryExp* createFloatingMediaQueryExp(const AtomicString&, CSSParserValueList*);
+ PassOwnPtr<MediaQueryExp> sinkFloatingMediaQueryExp(MediaQueryExp*);
+ Vector<OwnPtr<MediaQueryExp> >* createFloatingMediaQueryExpList();
+ PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >*);
+ MediaQuery* createFloatingMediaQuery(MediaQuery::Restrictor, const String&, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > >);
+ MediaQuery* createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > >);
+ PassOwnPtr<MediaQuery> sinkFloatingMediaQuery(MediaQuery*);
+
+ void addNamespace(const AtomicString& prefix, const AtomicString& uri);
+ void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*);
+ CSSParserSelector* updateSpecifiers(CSSParserSelector*, CSSParserSelector*);
+
+ void invalidBlockHit();
+
+ Vector<OwnPtr<CSSParserSelector> >* reusableSelectorVector() { return &m_reusableSelectorVector; }
+
+ void setReusableRegionSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectors);
+ Vector<OwnPtr<CSSParserSelector> >* reusableRegionSelectorVector() { return &m_reusableRegionSelectorVector; }
+
+ void updateLastSelectorLineAndPosition();
+ void updateLastMediaLine(MediaList*);
+
+ void clearProperties();
+
+ bool m_strict;
+ bool m_important;
+ int m_id;
+ CSSStyleSheet* m_styleSheet;
+ RefPtr<CSSRule> m_rule;
+ RefPtr<WebKitCSSKeyframeRule> m_keyframe;
+ OwnPtr<MediaQuery> m_mediaQuery;
+ OwnPtr<CSSParserValueList> m_valueList;
+ CSSProperty** m_parsedProperties;
+ CSSSelectorList* m_selectorListForParseSelector;
+
+ RefPtr<CSSValuePool> m_cssValuePool;
+ unsigned m_numParsedProperties;
+ unsigned m_maxParsedProperties;
+ unsigned m_numParsedPropertiesBeforeMarginBox;
+
+ int m_inParseShorthand;
+ int m_currentShorthand;
+ bool m_implicitShorthand;
+
+ bool m_hasFontFaceOnlyValues;
+ bool m_hadSyntacticallyValidCSSRule;
+
+ AtomicString m_defaultNamespace;
+
+ // tokenizer methods and data
+ bool m_inStyleRuleOrDeclaration;
+ SourceRange m_selectorListRange;
+ SourceRange m_ruleBodyRange;
+ SourceRange m_propertyRange;
+ StyleRuleRangeMap* m_ruleRangeMap;
+ RefPtr<CSSRuleSourceData> m_currentRuleData;
+ void markSelectorListStart();
+ void markSelectorListEnd();
+ void markRuleBodyStart();
+ void markRuleBodyEnd();
+ void markPropertyStart();
+ void markPropertyEnd(bool isImportantFound, bool isPropertyParsed);
+ void resetSelectorListMarks() { m_selectorListRange.start = m_selectorListRange.end = 0; }
+ 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();
+
+private:
+ void setStyleSheet(CSSStyleSheet*);
+ void ensureCSSValuePool();
+
+ void recheckAtKeyword(const UChar* str, int len);
+
+ void setupParser(const char* prefix, const String&, const char* suffix);
+
+ bool inShorthand() const { return m_inParseShorthand; }
+
+ void checkForOrphanedUnits();
+
+ void deleteFontFaceOnlyValues();
+
+ bool isGeneratedImageValue(CSSParserValue*) const;
+ bool parseGeneratedImage(CSSParserValueList*, RefPtr<CSSValue>&);
+
+ bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important, CSSStyleSheet* contextStyleSheet = 0);
+
+ enum SizeParameterType {
+ None,
+ Auto,
+ Length,
+ PageSize,
+ Orientation,
+ };
+
+ bool parsePage(int propId, bool important);
+ bool parseSize(int propId, bool important);
+ SizeParameterType parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType);
+
+ bool parseFontFaceSrcURI(CSSValueList*);
+ bool parseFontFaceSrcLocal(CSSValueList*);
+
+ 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;
+ int m_lineNumber;
+ int m_lastSelectorLineNumber;
+
+ bool m_allowImportRules;
+ bool m_allowNamespaceDeclarations;
+
+ Vector<RefPtr<CSSRule> > m_parsedRules;
+ Vector<RefPtr<MediaList> > m_parsedMediaLists;
+ Vector<RefPtr<CSSRuleList> > m_parsedRuleLists;
+ HashSet<CSSParserSelector*> m_floatingSelectors;
+ HashSet<Vector<OwnPtr<CSSParserSelector> >*> m_floatingSelectorVectors;
+ HashSet<CSSParserValueList*> m_floatingValueLists;
+ HashSet<CSSParserFunction*> m_floatingFunctions;
+
+ OwnPtr<MediaQuery> m_floatingMediaQuery;
+ OwnPtr<MediaQueryExp> m_floatingMediaQueryExp;
+ OwnPtr<Vector<OwnPtr<MediaQueryExp> > > m_floatingMediaQueryExpList;
+
+ Vector<OwnPtr<CSSParserSelector> > m_reusableSelectorVector;
+ Vector<OwnPtr<CSSParserSelector> > m_reusableRegionSelectorVector;
+
+ // defines units allowed for a certain property, used in parseUnit
+ enum Units {
+ FUnknown = 0x0000,
+ FInteger = 0x0001,
+ FNumber = 0x0002, // Real Numbers
+ FPercent = 0x0004,
+ FLength = 0x0008,
+ FAngle = 0x0010,
+ FTime = 0x0020,
+ FFrequency = 0x0040,
+ FRelative = 0x0100,
+ FNonNeg = 0x0200
+ };
+
+ friend inline Units operator|(Units a, Units b)
+ {
+ return static_cast<Units>(static_cast<unsigned>(a) | static_cast<unsigned>(b));
+ }
+
+ static bool validUnit(CSSParserValue*, Units, bool strict);
+
+ bool parseBorderImageQuad(Units, RefPtr<CSSPrimitiveValue>&);
+
+ PassRefPtr<CSSPrimitiveValue> createPrimitiveNumericValue(CSSParserValue*);
+ PassRefPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*);
+
+ friend class TransformOperationInfo;
+#if ENABLE(CSS_FILTERS)
+ friend class FilterOperationInfo;
+#endif
+};
+
+int cssPropertyID(const CSSParserString&);
+int cssPropertyID(const String&);
+int cssValueKeywordID(const CSSParserString&);
+
+class ShorthandScope {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ ShorthandScope(CSSParser* parser, int propId) : m_parser(parser)
+ {
+ if (!(m_parser->m_inParseShorthand++))
+ m_parser->m_currentShorthand = propId;
+ }
+ ~ShorthandScope()
+ {
+ if (!(--m_parser->m_inParseShorthand))
+ m_parser->m_currentShorthand = 0;
+ }
+
+private:
+ CSSParser* m_parser;
+};
+
+String quoteCSSString(const String&);
+String quoteCSSStringIfNeeded(const String&);
+String quoteCSSURLIfNeeded(const String&);
+
+bool isValidNthToken(const CSSParserString&);
+} // namespace WebCore
+
+#endif // CSSParser_h
diff --git a/Source/WebCore/css/CSSParserValues.cpp b/Source/WebCore/css/CSSParserValues.cpp
new file mode 100644
index 000000000..5af2a9a16
--- /dev/null
+++ b/Source/WebCore/css/CSSParserValues.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 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 "CSSParserValues.h"
+
+#include "CSSPrimitiveValue.h"
+#include "CSSFunctionValue.h"
+#include "CSSSelector.h"
+#include "CSSSelectorList.h"
+
+namespace WebCore {
+
+using namespace WTF;
+
+CSSParserValueList::~CSSParserValueList()
+{
+ size_t numValues = m_values.size();
+ for (size_t i = 0; i < numValues; i++) {
+ if (m_values[i].unit == CSSParserValue::Function)
+ delete m_values[i].function;
+ }
+}
+
+void CSSParserValueList::addValue(const CSSParserValue& v)
+{
+ m_values.append(v);
+}
+
+void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v)
+{
+ m_values.insert(i, v);
+}
+
+void CSSParserValueList::deleteValueAt(unsigned i)
+{
+ m_values.remove(i);
+}
+
+void CSSParserValueList::extend(CSSParserValueList& valueList)
+{
+ for (unsigned int i = 0; i < valueList.size(); ++i)
+ m_values.append(*(valueList.valueAt(i)));
+}
+
+PassRefPtr<CSSValue> CSSParserValue::createCSSValue()
+{
+ RefPtr<CSSValue> parsedValue;
+ if (id)
+ parsedValue = CSSPrimitiveValue::createIdentifier(id);
+ else if (unit == CSSPrimitiveValue::CSS_IDENT)
+ parsedValue = CSSPrimitiveValue::create(string, CSSPrimitiveValue::CSS_PARSER_IDENTIFIER);
+ else if (unit == CSSPrimitiveValue::CSS_NUMBER && isInt)
+ parsedValue = CSSPrimitiveValue::create(fValue, CSSPrimitiveValue::CSS_PARSER_INTEGER);
+ else if (unit == CSSParserValue::Operator) {
+ RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::createIdentifier(iValue);
+ primitiveValue->setPrimitiveType(CSSPrimitiveValue::CSS_PARSER_OPERATOR);
+ parsedValue = primitiveValue;
+ } else if (unit == CSSParserValue::Function)
+ parsedValue = CSSFunctionValue::create(function);
+ else if (unit == CSSPrimitiveValue::CSS_STRING || unit == CSSPrimitiveValue::CSS_URI || unit == CSSPrimitiveValue::CSS_PARSER_HEXCOLOR)
+ parsedValue = CSSPrimitiveValue::create(string, (CSSPrimitiveValue::UnitTypes)unit);
+ else if (unit >= CSSPrimitiveValue::CSS_NUMBER && unit <= CSSPrimitiveValue::CSS_KHZ)
+ parsedValue = CSSPrimitiveValue::create(fValue, (CSSPrimitiveValue::UnitTypes)unit);
+ else if (unit >= CSSPrimitiveValue::CSS_TURN && unit <= CSSPrimitiveValue::CSS_REMS) // CSS3 Values and Units
+ parsedValue = CSSPrimitiveValue::create(fValue, (CSSPrimitiveValue::UnitTypes)unit);
+ else if (unit >= CSSParserValue::Q_EMS)
+ parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS);
+ return parsedValue;
+}
+
+CSSParserSelector::CSSParserSelector()
+ : m_selector(adoptPtr(fastNew<CSSSelector>()))
+{
+}
+
+CSSParserSelector::~CSSParserSelector()
+{
+ if (!m_tagHistory)
+ return;
+ Vector<OwnPtr<CSSParserSelector>, 16> toDelete;
+ OwnPtr<CSSParserSelector> selector = m_tagHistory.release();
+ while (true) {
+ OwnPtr<CSSParserSelector> next = selector->m_tagHistory.release();
+ toDelete.append(selector.release());
+ if (!next)
+ break;
+ selector = next.release();
+ }
+}
+
+void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
+{
+ CSSSelectorList* selectorList = fastNew<CSSSelectorList>();
+ selectorList->adoptSelectorVector(selectorVector);
+ m_selector->setSelectorList(adoptPtr(selectorList));
+}
+
+void CSSParserSelector::insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector> selector, CSSSelector::Relation after)
+{
+ if (m_tagHistory)
+ selector->setTagHistory(m_tagHistory.release());
+ setRelation(before);
+ selector->setRelation(after);
+ m_tagHistory = selector;
+}
+
+void CSSParserSelector::appendTagHistory(CSSSelector::Relation relation, PassOwnPtr<CSSParserSelector> selector)
+{
+ CSSParserSelector* end = this;
+ while (end->tagHistory())
+ end = end->tagHistory();
+ end->setRelation(relation);
+ end->setTagHistory(selector);
+}
+
+}
+
diff --git a/Source/WebCore/css/CSSParserValues.h b/Source/WebCore/css/CSSParserValues.h
new file mode 100644
index 000000000..90d26a46d
--- /dev/null
+++ b/Source/WebCore/css/CSSParserValues.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 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 CSSParserValues_h
+#define CSSParserValues_h
+
+#include "CSSSelector.h"
+#include "CSSValueList.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class CSSValue;
+class QualifiedName;
+
+struct CSSParserString {
+ UChar* characters;
+ int length;
+
+ void lower();
+
+ operator String() const { return String(characters, length); }
+ operator AtomicString() const { return AtomicString(characters, length); }
+};
+
+struct CSSParserFunction;
+
+struct CSSParserValue {
+ int id;
+ bool isInt;
+ union {
+ double fValue;
+ int iValue;
+ CSSParserString string;
+ CSSParserFunction* function;
+ };
+ enum {
+ Operator = 0x100000,
+ Function = 0x100001,
+ Q_EMS = 0x100002
+ };
+ int unit;
+
+
+ PassRefPtr<CSSValue> createCSSValue();
+};
+
+class CSSParserValueList {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ CSSParserValueList()
+ : m_current(0)
+ {
+ }
+ ~CSSParserValueList();
+
+ void addValue(const CSSParserValue&);
+ void insertValueAt(unsigned, const CSSParserValue&);
+ void deleteValueAt(unsigned);
+ void extend(CSSParserValueList&);
+
+ unsigned size() const { return m_values.size(); }
+ CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; }
+ CSSParserValue* next() { ++m_current; return current(); }
+ CSSParserValue* previous()
+ {
+ if (!m_current)
+ return 0;
+ --m_current;
+ return current();
+ }
+
+ CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; }
+
+ void clear() { m_values.clear(); }
+
+private:
+ unsigned m_current;
+ Vector<CSSParserValue, 4> m_values;
+};
+
+struct CSSParserFunction {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ CSSParserString name;
+ OwnPtr<CSSParserValueList> args;
+};
+
+class CSSParserSelector {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ CSSParserSelector();
+ ~CSSParserSelector();
+
+ PassOwnPtr<CSSSelector> releaseSelector() { return m_selector.release(); }
+
+ void setTag(const QualifiedName& value) { m_selector->setTag(value); }
+ void setValue(const AtomicString& value) { m_selector->setValue(value); }
+ void setAttribute(const QualifiedName& value) { m_selector->setAttribute(value); }
+ void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
+ void setMatch(CSSSelector::Match value) { m_selector->m_match = value; }
+ void setRelation(CSSSelector::Relation value) { m_selector->m_relation = value; }
+ void setForPage() { m_selector->setForPage(); }
+
+ void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
+
+ CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); }
+ bool isUnknownPseudoElement() const { return m_selector->isUnknownPseudoElement(); }
+ bool isSimple() const { return !m_tagHistory && m_selector->isSimple(); }
+ bool hasShadowDescendant() const;
+
+ CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
+ void setTagHistory(PassOwnPtr<CSSParserSelector> selector) { m_tagHistory = selector; }
+ void insertTagHistory(CSSSelector::Relation before, PassOwnPtr<CSSParserSelector>, CSSSelector::Relation after);
+ void appendTagHistory(CSSSelector::Relation, PassOwnPtr<CSSParserSelector>);
+
+private:
+ OwnPtr<CSSSelector> m_selector;
+ OwnPtr<CSSParserSelector> m_tagHistory;
+};
+
+inline bool CSSParserSelector::hasShadowDescendant() const
+{
+ return m_selector->relation() == CSSSelector::ShadowDescendant;
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp
new file mode 100644
index 000000000..a439cbf52
--- /dev/null
+++ b/Source/WebCore/css/CSSPrimitiveValue.cpp
@@ -0,0 +1,955 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 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 "CSSPrimitiveValue.h"
+
+#include "CSSHelper.h"
+#include "CSSParser.h"
+#include "CSSPropertyNames.h"
+#include "CSSStyleSheet.h"
+#include "CSSValueKeywords.h"
+#include "CSSWrapShapes.h"
+#include "Color.h"
+#include "Counter.h"
+#include "ExceptionCode.h"
+#include "Node.h"
+#include "Pair.h"
+#include "RGBColor.h"
+#include "Rect.h"
+#include "RenderStyle.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/DecimalNumber.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringBuffer.h>
+#include <wtf/text/StringBuilder.h>
+
+#if ENABLE(DASHBOARD_SUPPORT)
+#include "DashboardRegion.h"
+#endif
+
+using namespace WTF;
+
+namespace WebCore {
+
+static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitTypes unitType)
+{
+ switch (unitType) {
+ case CSSPrimitiveValue:: CSS_CM:
+ case CSSPrimitiveValue:: CSS_DEG:
+ case CSSPrimitiveValue:: CSS_DIMENSION:
+ case CSSPrimitiveValue:: CSS_EMS:
+ case CSSPrimitiveValue:: CSS_EXS:
+ case CSSPrimitiveValue:: CSS_GRAD:
+ case CSSPrimitiveValue:: CSS_HZ:
+ case CSSPrimitiveValue:: CSS_IN:
+ case CSSPrimitiveValue:: CSS_KHZ:
+ case CSSPrimitiveValue:: CSS_MM:
+ case CSSPrimitiveValue:: CSS_MS:
+ case CSSPrimitiveValue:: CSS_NUMBER:
+ case CSSPrimitiveValue:: CSS_PERCENTAGE:
+ case CSSPrimitiveValue:: CSS_PC:
+ case CSSPrimitiveValue:: CSS_PT:
+ case CSSPrimitiveValue:: CSS_PX:
+ case CSSPrimitiveValue:: CSS_RAD:
+ case CSSPrimitiveValue:: CSS_REMS:
+ case CSSPrimitiveValue:: CSS_S:
+ case CSSPrimitiveValue:: CSS_TURN:
+ return true;
+ case CSSPrimitiveValue:: CSS_ATTR:
+ case CSSPrimitiveValue:: CSS_COUNTER:
+ case CSSPrimitiveValue:: CSS_COUNTER_NAME:
+ case CSSPrimitiveValue:: CSS_DASHBOARD_REGION:
+ case CSSPrimitiveValue:: CSS_IDENT:
+ case CSSPrimitiveValue:: CSS_PAIR:
+ case CSSPrimitiveValue:: CSS_PARSER_HEXCOLOR:
+ case CSSPrimitiveValue:: CSS_PARSER_IDENTIFIER:
+ case CSSPrimitiveValue:: CSS_PARSER_INTEGER:
+ case CSSPrimitiveValue:: CSS_PARSER_OPERATOR:
+ case CSSPrimitiveValue:: CSS_RECT:
+ case CSSPrimitiveValue:: CSS_QUAD:
+ case CSSPrimitiveValue:: CSS_RGBCOLOR:
+ case CSSPrimitiveValue:: CSS_SHAPE:
+ case CSSPrimitiveValue:: CSS_STRING:
+ case CSSPrimitiveValue:: CSS_UNICODE_RANGE:
+ case CSSPrimitiveValue:: CSS_UNKNOWN:
+ case CSSPrimitiveValue:: CSS_URI:
+ return false;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes type)
+{
+ // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
+ // between CSS_PX and relative lengths (see cssPixelsPerInch comment in CSSHelper.h for the topic treatment).
+ switch (type) {
+ case CSSPrimitiveValue::CSS_NUMBER:
+ return CSSPrimitiveValue::UNumber;
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ return CSSPrimitiveValue::UPercent;
+ case CSSPrimitiveValue::CSS_PX:
+ case CSSPrimitiveValue::CSS_CM:
+ case CSSPrimitiveValue::CSS_MM:
+ case CSSPrimitiveValue::CSS_IN:
+ case CSSPrimitiveValue::CSS_PT:
+ case CSSPrimitiveValue::CSS_PC:
+ return CSSPrimitiveValue::ULength;
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_S:
+ return CSSPrimitiveValue::UTime;
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_RAD:
+ case CSSPrimitiveValue::CSS_GRAD:
+ case CSSPrimitiveValue::CSS_TURN:
+ return CSSPrimitiveValue::UAngle;
+ case CSSPrimitiveValue::CSS_HZ:
+ case CSSPrimitiveValue::CSS_KHZ:
+ return CSSPrimitiveValue::UFrequency;
+ default:
+ return CSSPrimitiveValue::UOther;
+ }
+}
+
+typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
+static CSSTextCache& cssTextCache()
+{
+ DEFINE_STATIC_LOCAL(CSSTextCache, cache, ());
+ return cache;
+}
+
+static const AtomicString& valueOrPropertyName(int valueOrPropertyID)
+{
+ ASSERT_ARG(valueOrPropertyID, valueOrPropertyID >= 0);
+ ASSERT_ARG(valueOrPropertyID, valueOrPropertyID < numCSSValueKeywords || (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties));
+
+ if (valueOrPropertyID < 0)
+ return nullAtom;
+
+ if (valueOrPropertyID < numCSSValueKeywords) {
+ static AtomicString* keywordStrings = new AtomicString[numCSSValueKeywords]; // Leaked intentionally.
+ AtomicString& keywordString = keywordStrings[valueOrPropertyID];
+ if (keywordString.isNull())
+ keywordString = getValueName(valueOrPropertyID);
+ return keywordString;
+ }
+
+ if (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties) {
+ static AtomicString* propertyStrings = new AtomicString[numCSSProperties]; // Leaked intentionally.
+ AtomicString& propertyString = propertyStrings[valueOrPropertyID - firstCSSProperty];
+ if (propertyString.isNull())
+ propertyString = getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID));
+ return propertyString;
+ }
+
+ return nullAtom;
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue()
+ : CSSValue(PrimitiveClass)
+{
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(int ident)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ m_value.ident = ident;
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(ClassType classType, int ident)
+ : CSSValue(classType)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ m_value.ident = ident;
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = type;
+ ASSERT(isfinite(num));
+ m_value.num = num;
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = type;
+ if ((m_value.string = str.impl()))
+ m_value.string->ref();
+}
+
+
+CSSPrimitiveValue::CSSPrimitiveValue(ClassType classType, const String& str, UnitTypes type)
+ : CSSValue(classType)
+{
+ m_primitiveUnitType = type;
+ if ((m_value.string = str.impl()))
+ m_value.string->ref();
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_RGBCOLOR;
+ m_value.rgbcolor = color;
+}
+
+CSSPrimitiveValue::CSSPrimitiveValue(const Length& length)
+ : CSSValue(PrimitiveClass)
+{
+ switch (length.type()) {
+ case Auto:
+ m_primitiveUnitType = CSS_IDENT;
+ m_value.ident = CSSValueAuto;
+ break;
+ case WebCore::Fixed:
+ m_primitiveUnitType = CSS_PX;
+ m_value.num = length.value();
+ break;
+ case Intrinsic:
+ m_primitiveUnitType = CSS_IDENT;
+ m_value.ident = CSSValueIntrinsic;
+ break;
+ case MinIntrinsic:
+ m_primitiveUnitType = CSS_IDENT;
+ m_value.ident = CSSValueMinIntrinsic;
+ break;
+ case Percent:
+ m_primitiveUnitType = CSS_PERCENTAGE;
+ ASSERT(isfinite(length.percent()));
+ m_value.num = length.percent();
+ break;
+ case Relative:
+ case Undefined:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+void CSSPrimitiveValue::init(PassRefPtr<Counter> c)
+{
+ m_primitiveUnitType = CSS_COUNTER;
+ m_hasCachedCSSText = false;
+ m_value.counter = c.leakRef();
+}
+
+void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
+{
+ m_primitiveUnitType = CSS_RECT;
+ m_hasCachedCSSText = false;
+ m_value.rect = r.leakRef();
+}
+
+void CSSPrimitiveValue::init(PassRefPtr<Quad> quad)
+{
+ m_primitiveUnitType = CSS_QUAD;
+ m_hasCachedCSSText = false;
+ m_value.quad = quad.leakRef();
+}
+
+#if ENABLE(DASHBOARD_SUPPORT)
+void CSSPrimitiveValue::init(PassRefPtr<DashboardRegion> r)
+{
+ m_primitiveUnitType = CSS_DASHBOARD_REGION;
+ m_hasCachedCSSText = false;
+ m_value.region = r.leakRef();
+}
+#endif
+
+void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
+{
+ m_primitiveUnitType = CSS_PAIR;
+ m_hasCachedCSSText = false;
+ m_value.pair = p.leakRef();
+}
+
+void CSSPrimitiveValue::init(PassRefPtr<CSSWrapShape> shape)
+{
+ m_primitiveUnitType = CSS_SHAPE;
+ m_hasCachedCSSText = false;
+ m_value.shape = shape.leakRef();
+}
+
+CSSPrimitiveValue::~CSSPrimitiveValue()
+{
+ cleanup();
+}
+
+void CSSPrimitiveValue::cleanup()
+{
+ switch (m_primitiveUnitType) {
+ case CSS_STRING:
+ case CSS_URI:
+ case CSS_ATTR:
+ case CSS_PARSER_HEXCOLOR:
+ if (m_value.string)
+ m_value.string->deref();
+ break;
+ case CSS_COUNTER:
+ m_value.counter->deref();
+ break;
+ case CSS_RECT:
+ m_value.rect->deref();
+ break;
+ case CSS_QUAD:
+ m_value.quad->deref();
+ break;
+ case CSS_PAIR:
+ m_value.pair->deref();
+ break;
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSS_DASHBOARD_REGION:
+ if (m_value.region)
+ m_value.region->deref();
+ break;
+#endif
+ case CSS_SHAPE:
+ m_value.shape->deref();
+ break;
+ default:
+ break;
+ }
+
+ m_primitiveUnitType = 0;
+ if (m_hasCachedCSSText) {
+ cssTextCache().remove(this);
+ m_hasCachedCSSText = false;
+ }
+}
+
+template<> int CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double 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)
+{
+ // 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)
+{
+ 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)
+{
+ return roundForImpreciseConversion<unsigned short, USHRT_MAX, 0>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
+}
+
+template<> float CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
+{
+ return static_cast<float>(computeLengthDouble(style, rootStyle, multiplier, computingFontSize));
+}
+
+template<> double CSSPrimitiveValue::computeLength(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
+{
+ return computeLengthDouble(style, rootStyle, multiplier, computingFontSize);
+}
+
+double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* rootStyle, double multiplier, bool computingFontSize)
+{
+ unsigned short type = primitiveType();
+
+ // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
+ // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
+ // as well as enforcing the implicit "smart minimum." In addition the CSS property text-size-adjust is used to
+ // prevent text from zooming at all. Therefore we will not apply the zoom here if we are computing font-size.
+ bool applyZoomMultiplier = !computingFontSize;
+
+ double factor = 1.0;
+ switch (type) {
+ case CSS_EMS:
+ applyZoomMultiplier = false;
+ factor = computingFontSize ? style->fontDescription().specifiedSize() : style->fontDescription().computedSize();
+ break;
+ case CSS_EXS:
+ // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
+ // We really need to compute EX using fontMetrics for the original specifiedSize and not use
+ // our actual constructed rendering font.
+ applyZoomMultiplier = false;
+ factor = style->fontMetrics().xHeight();
+ break;
+ case CSS_REMS:
+ applyZoomMultiplier = false;
+ factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
+ break;
+ case CSS_PX:
+ break;
+ case CSS_CM:
+ factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
+ break;
+ case CSS_MM:
+ factor = cssPixelsPerInch / 25.4;
+ break;
+ case CSS_IN:
+ factor = cssPixelsPerInch;
+ break;
+ case CSS_PT:
+ factor = cssPixelsPerInch / 72.0;
+ break;
+ case CSS_PC:
+ // 1 pc == 12 pt
+ factor = cssPixelsPerInch * 12.0 / 72.0;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return -1.0;
+ }
+
+ double result = getDoubleValue() * factor;
+ if (!applyZoomMultiplier || multiplier == 1.0)
+ return result;
+
+ // Any original result that was >= 1 should not be allowed to fall below 1. This keeps border lines from
+ // vanishing.
+ double zoomedResult = result * multiplier;
+ if (result >= 1.0)
+ zoomedResult = max(1.0, zoomedResult);
+ return zoomedResult;
+}
+
+void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionCode& ec)
+{
+ // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
+ // No other engine supports mutating style through this API. Computed style is always read-only anyway.
+ // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
+ ec = NO_MODIFICATION_ALLOWED_ERR;
+}
+
+static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
+{
+ double factor = 1.0;
+ // FIXME: the switch can be replaced by an array of scale factors.
+ switch (unitType) {
+ // These are "canonical" units in their respective categories.
+ case CSSPrimitiveValue::CSS_PX:
+ case CSSPrimitiveValue::CSS_DEG:
+ case CSSPrimitiveValue::CSS_MS:
+ case CSSPrimitiveValue::CSS_HZ:
+ break;
+ case CSSPrimitiveValue::CSS_CM:
+ factor = cssPixelsPerInch / 2.54; // (2.54 cm/in)
+ break;
+ case CSSPrimitiveValue::CSS_MM:
+ factor = cssPixelsPerInch / 25.4;
+ break;
+ case CSSPrimitiveValue::CSS_IN:
+ factor = cssPixelsPerInch;
+ break;
+ case CSSPrimitiveValue::CSS_PT:
+ factor = cssPixelsPerInch / 72.0;
+ break;
+ case CSSPrimitiveValue::CSS_PC:
+ factor = cssPixelsPerInch * 12.0 / 72.0; // 1 pc == 12 pt
+ break;
+ case CSSPrimitiveValue::CSS_RAD:
+ factor = 180 / piDouble;
+ break;
+ case CSSPrimitiveValue::CSS_GRAD:
+ factor = 0.9;
+ break;
+ case CSSPrimitiveValue::CSS_TURN:
+ factor = 360;
+ break;
+ case CSSPrimitiveValue::CSS_S:
+ case CSSPrimitiveValue::CSS_KHZ:
+ factor = 1000;
+ break;
+ default:
+ break;
+ }
+
+ return factor;
+}
+
+double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionCode& ec) const
+{
+ double result = 0;
+ bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
+ if (!success) {
+ ec = INVALID_ACCESS_ERR;
+ return 0.0;
+ }
+
+ ec = 0;
+ return result;
+}
+
+double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
+{
+ double result = 0;
+ getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
+ return result;
+}
+
+CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
+{
+ // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit
+ // in each category (based on unitflags).
+ switch (category) {
+ case UNumber:
+ return CSS_NUMBER;
+ case ULength:
+ return CSS_PX;
+ case UPercent:
+ return CSS_UNKNOWN; // Cannot convert between numbers and percent.
+ case UTime:
+ return CSS_MS;
+ case UAngle:
+ return CSS_DEG;
+ case UFrequency:
+ return CSS_HZ;
+ default:
+ return CSS_UNKNOWN;
+ }
+}
+
+bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const
+{
+ if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitTypes>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType))
+ return false;
+ if (requestedUnitType == static_cast<UnitTypes>(m_primitiveUnitType) || requestedUnitType == CSS_DIMENSION) {
+ *result = m_value.num;
+ return true;
+ }
+
+ UnitTypes sourceUnitType = static_cast<UnitTypes>(m_primitiveUnitType);
+ UnitCategory sourceCategory = unitCategory(sourceUnitType);
+ ASSERT(sourceCategory != UOther);
+
+ UnitTypes targetUnitType = requestedUnitType;
+ UnitCategory targetCategory = unitCategory(targetUnitType);
+ ASSERT(targetCategory != UOther);
+
+ // Cannot convert between unrelated unit categories if one of them is not UNumber.
+ if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
+ return false;
+
+ if (targetCategory == UNumber) {
+ // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
+ targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
+ if (targetUnitType == CSS_UNKNOWN)
+ return false;
+ }
+
+ if (sourceUnitType == CSS_NUMBER) {
+ // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode.
+ sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
+ if (sourceUnitType == CSS_UNKNOWN)
+ return false;
+ }
+
+ double convertedValue = m_value.num;
+
+ // First convert the value from m_primitiveUnitType to canonical type.
+ double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
+ convertedValue *= factor;
+
+ // Now convert from canonical type to the target unitType.
+ factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
+ convertedValue /= factor;
+
+ *result = convertedValue;
+ return true;
+}
+
+void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionCode& ec)
+{
+ // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
+ // No other engine supports mutating style through this API. Computed style is always read-only anyway.
+ // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
+ ec = NO_MODIFICATION_ALLOWED_ERR;
+}
+
+String CSSPrimitiveValue::getStringValue(ExceptionCode& ec) const
+{
+ ec = 0;
+ switch (m_primitiveUnitType) {
+ case CSS_STRING:
+ case CSS_ATTR:
+ case CSS_URI:
+ return m_value.string;
+ case CSS_IDENT:
+ return valueOrPropertyName(m_value.ident);
+ default:
+ ec = INVALID_ACCESS_ERR;
+ break;
+ }
+
+ return String();
+}
+
+String CSSPrimitiveValue::getStringValue() const
+{
+ switch (m_primitiveUnitType) {
+ case CSS_STRING:
+ case CSS_ATTR:
+ case CSS_URI:
+ return m_value.string;
+ case CSS_IDENT:
+ return valueOrPropertyName(m_value.ident);
+ default:
+ break;
+ }
+
+ return String();
+}
+
+Counter* CSSPrimitiveValue::getCounterValue(ExceptionCode& ec) const
+{
+ ec = 0;
+ if (m_primitiveUnitType != CSS_COUNTER) {
+ ec = INVALID_ACCESS_ERR;
+ return 0;
+ }
+
+ return m_value.counter;
+}
+
+Rect* CSSPrimitiveValue::getRectValue(ExceptionCode& ec) const
+{
+ ec = 0;
+ if (m_primitiveUnitType != CSS_RECT) {
+ ec = INVALID_ACCESS_ERR;
+ return 0;
+ }
+
+ return m_value.rect;
+}
+
+Quad* CSSPrimitiveValue::getQuadValue(ExceptionCode& ec) const
+{
+ ec = 0;
+ if (m_primitiveUnitType != CSS_QUAD) {
+ ec = INVALID_ACCESS_ERR;
+ return 0;
+ }
+
+ return m_value.quad;
+}
+
+PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionCode& ec) const
+{
+ ec = 0;
+ if (m_primitiveUnitType != CSS_RGBCOLOR) {
+ ec = INVALID_ACCESS_ERR;
+ return 0;
+ }
+
+ // FIMXE: This should not return a new object for each invocation.
+ return RGBColor::create(m_value.rgbcolor);
+}
+
+Pair* CSSPrimitiveValue::getPairValue(ExceptionCode& ec) const
+{
+ ec = 0;
+ if (m_primitiveUnitType != CSS_PAIR) {
+ ec = INVALID_ACCESS_ERR;
+ return 0;
+ }
+
+ return m_value.pair;
+}
+
+static String formatNumber(double number)
+{
+ DecimalNumber decimal(number);
+
+ StringBuffer<UChar> buffer(decimal.bufferLengthForStringDecimal());
+ unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length());
+ ASSERT_UNUSED(length, length == buffer.length());
+
+ return String::adopt(buffer);
+}
+
+String CSSPrimitiveValue::customCssText() const
+{
+ // FIXME: return the original value instead of a generated one (e.g. color
+ // name if it was specified) - check what spec says about this
+
+ if (m_hasCachedCSSText) {
+ ASSERT(cssTextCache().contains(this));
+ return cssTextCache().get(this);
+ }
+
+ String text;
+ switch (m_primitiveUnitType) {
+ case CSS_UNKNOWN:
+ // FIXME
+ break;
+ case CSS_NUMBER:
+ case CSS_PARSER_INTEGER:
+ text = formatNumber(m_value.num);
+ break;
+ case CSS_PERCENTAGE:
+ text = formatNumber(m_value.num) + "%";
+ break;
+ case CSS_EMS:
+ text = formatNumber(m_value.num) + "em";
+ break;
+ case CSS_EXS:
+ text = formatNumber(m_value.num) + "ex";
+ break;
+ case CSS_REMS:
+ text = formatNumber(m_value.num) + "rem";
+ break;
+ case CSS_PX:
+ text = formatNumber(m_value.num) + "px";
+ break;
+ case CSS_CM:
+ text = formatNumber(m_value.num) + "cm";
+ break;
+ case CSS_MM:
+ text = formatNumber(m_value.num) + "mm";
+ break;
+ case CSS_IN:
+ text = formatNumber(m_value.num) + "in";
+ break;
+ case CSS_PT:
+ text = formatNumber(m_value.num) + "pt";
+ break;
+ case CSS_PC:
+ text = formatNumber(m_value.num) + "pc";
+ break;
+ case CSS_DEG:
+ text = formatNumber(m_value.num) + "deg";
+ break;
+ case CSS_RAD:
+ text = formatNumber(m_value.num) + "rad";
+ break;
+ case CSS_GRAD:
+ text = formatNumber(m_value.num) + "grad";
+ break;
+ case CSS_MS:
+ text = formatNumber(m_value.num) + "ms";
+ break;
+ case CSS_S:
+ text = formatNumber(m_value.num) + "s";
+ break;
+ case CSS_HZ:
+ text = formatNumber(m_value.num) + "hz";
+ break;
+ case CSS_KHZ:
+ text = formatNumber(m_value.num) + "khz";
+ break;
+ case CSS_TURN:
+ text = formatNumber(m_value.num) + "turn";
+ break;
+ case CSS_DIMENSION:
+ // FIXME
+ break;
+ case CSS_STRING:
+ text = quoteCSSStringIfNeeded(m_value.string);
+ break;
+ case CSS_URI:
+ text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
+ break;
+ case CSS_IDENT:
+ text = valueOrPropertyName(m_value.ident);
+ break;
+ case CSS_ATTR: {
+ DEFINE_STATIC_LOCAL(const String, attrParen, ("attr("));
+
+ StringBuilder result;
+ result.reserveCapacity(6 + m_value.string->length());
+
+ result.append(attrParen);
+ result.append(m_value.string);
+ result.append(')');
+
+ text = result.toString();
+ break;
+ }
+ case CSS_COUNTER_NAME:
+ text = "counter(";
+ text += m_value.string;
+ text += ")";
+ break;
+ case CSS_COUNTER: {
+ DEFINE_STATIC_LOCAL(const String, counterParen, ("counter("));
+ DEFINE_STATIC_LOCAL(const String, countersParen, ("counters("));
+ DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
+
+ StringBuilder result;
+ String separator = m_value.counter->separator();
+ result.append(separator.isEmpty() ? counterParen : countersParen);
+
+ result.append(m_value.counter->identifier());
+ if (!separator.isEmpty()) {
+ result.append(commaSpace);
+ result.append(quoteCSSStringIfNeeded(separator));
+ }
+ String listStyle = m_value.counter->listStyle();
+ if (!listStyle.isEmpty()) {
+ result.append(commaSpace);
+ result.append(listStyle);
+ }
+ result.append(')');
+
+ text = result.toString();
+ break;
+ }
+ case CSS_RECT: {
+ DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));
+
+ Rect* rectVal = getRectValue();
+ StringBuilder result;
+ result.reserveCapacity(32);
+ result.append(rectParen);
+
+ result.append(rectVal->top()->cssText());
+ result.append(' ');
+
+ result.append(rectVal->right()->cssText());
+ result.append(' ');
+
+ result.append(rectVal->bottom()->cssText());
+ result.append(' ');
+
+ result.append(rectVal->left()->cssText());
+ result.append(')');
+
+ text = result.toString();
+ break;
+ }
+ case CSS_QUAD: {
+ Quad* quadVal = getQuadValue();
+ Vector<UChar> result;
+ result.reserveInitialCapacity(32);
+ append(result, quadVal->top()->cssText());
+ if (quadVal->right() != quadVal->top() || quadVal->bottom() != quadVal->top() || quadVal->left() != quadVal->top()) {
+ result.append(' ');
+ append(result, quadVal->right()->cssText());
+ if (quadVal->bottom() != quadVal->top() || quadVal->right() != quadVal->left()) {
+ result.append(' ');
+ append(result, quadVal->bottom()->cssText());
+ if (quadVal->left() != quadVal->right()) {
+ result.append(' ');
+ append(result, quadVal->left()->cssText());
+ }
+ }
+ }
+ text = String::adopt(result);
+ break;
+ }
+ case CSS_RGBCOLOR:
+ case CSS_PARSER_HEXCOLOR: {
+ DEFINE_STATIC_LOCAL(const String, commaSpace, (", "));
+ DEFINE_STATIC_LOCAL(const String, rgbParen, ("rgb("));
+ DEFINE_STATIC_LOCAL(const String, rgbaParen, ("rgba("));
+
+ RGBA32 rgbColor = m_value.rgbcolor;
+ if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
+ Color::parseHexColor(m_value.string, rgbColor);
+ Color color(rgbColor);
+
+ Vector<UChar> result;
+ result.reserveInitialCapacity(32);
+ if (color.hasAlpha())
+ append(result, rgbaParen);
+ else
+ append(result, rgbParen);
+
+ appendNumber(result, static_cast<unsigned char>(color.red()));
+ append(result, commaSpace);
+
+ appendNumber(result, static_cast<unsigned char>(color.green()));
+ append(result, commaSpace);
+
+ appendNumber(result, static_cast<unsigned char>(color.blue()));
+ if (color.hasAlpha()) {
+ append(result, commaSpace);
+ append(result, String::number(color.alpha() / 256.0f));
+ }
+
+ result.append(')');
+ text = String::adopt(result);
+ break;
+ }
+ case CSS_PAIR:
+ text = m_value.pair->first()->cssText();
+ if (m_value.pair->second() != m_value.pair->first()) {
+ text += " ";
+ text += m_value.pair->second()->cssText();
+ }
+ break;
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSS_DASHBOARD_REGION:
+ for (DashboardRegion* region = getDashboardRegionValue(); region; region = region->m_next.get()) {
+ if (!text.isEmpty())
+ text.append(' ');
+ text += "dashboard-region(";
+ text += region->m_label;
+ if (region->m_isCircle)
+ text += " circle";
+ else if (region->m_isRectangle)
+ text += " rectangle";
+ else
+ break;
+ if (region->top()->m_primitiveUnitType == CSS_IDENT && region->top()->getIdent() == CSSValueInvalid) {
+ ASSERT(region->right()->m_primitiveUnitType == CSS_IDENT);
+ ASSERT(region->bottom()->m_primitiveUnitType == CSS_IDENT);
+ ASSERT(region->left()->m_primitiveUnitType == CSS_IDENT);
+ ASSERT(region->right()->getIdent() == CSSValueInvalid);
+ ASSERT(region->bottom()->getIdent() == CSSValueInvalid);
+ ASSERT(region->left()->getIdent() == CSSValueInvalid);
+ } else {
+ text.append(' ');
+ text += region->top()->cssText() + " ";
+ text += region->right()->cssText() + " ";
+ text += region->bottom()->cssText() + " ";
+ text += region->left()->cssText();
+ }
+ text += ")";
+ }
+ break;
+#endif
+ case CSS_PARSER_OPERATOR: {
+ char c = static_cast<char>(m_value.ident);
+ text = String(&c, 1U);
+ break;
+ }
+ case CSS_PARSER_IDENTIFIER:
+ text = quoteCSSStringIfNeeded(m_value.string);
+ break;
+ case CSS_SHAPE:
+ text = m_value.shape->cssText();
+ break;
+ }
+
+ ASSERT(!cssTextCache().contains(this));
+ cssTextCache().set(this, text);
+ m_hasCachedCSSText = true;
+ return text;
+}
+
+void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
+{
+ if (m_primitiveUnitType == CSS_URI)
+ addSubresourceURL(urls, styleSheet->completeURL(m_value.string));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h
new file mode 100644
index 000000000..8fd4ad209
--- /dev/null
+++ b/Source/WebCore/css/CSSPrimitiveValue.h
@@ -0,0 +1,281 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ *
+ * 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 CSSPrimitiveValue_h
+#define CSSPrimitiveValue_h
+
+#include "CSSValue.h"
+#include "Color.h"
+#include <wtf/Forward.h>
+#include <wtf/MathExtras.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class Counter;
+class DashboardRegion;
+class Pair;
+class Quad;
+class RGBColor;
+class Rect;
+class RenderStyle;
+class CSSWrapShape;
+
+struct Length;
+
+template<typename T, T max, T min> inline T roundForImpreciseConversion(double value)
+{
+ // Dimension calculations are imprecise, often resulting in values of e.g.
+ // 44.99998. We need to go ahead and round if we're really close to the
+ // next integer value.
+ value += (value < 0) ? -0.01 : +0.01;
+ return ((value > max) || (value < min)) ? 0 : static_cast<T>(value);
+}
+
+class CSSPrimitiveValue : public CSSValue {
+public:
+ enum UnitTypes {
+ CSS_UNKNOWN = 0,
+ CSS_NUMBER = 1,
+ CSS_PERCENTAGE = 2,
+ CSS_EMS = 3,
+ CSS_EXS = 4,
+ CSS_PX = 5,
+ CSS_CM = 6,
+ CSS_MM = 7,
+ CSS_IN = 8,
+ CSS_PT = 9,
+ CSS_PC = 10,
+ CSS_DEG = 11,
+ CSS_RAD = 12,
+ CSS_GRAD = 13,
+ CSS_MS = 14,
+ CSS_S = 15,
+ CSS_HZ = 16,
+ CSS_KHZ = 17,
+ CSS_DIMENSION = 18,
+ CSS_STRING = 19,
+ CSS_URI = 20,
+ CSS_IDENT = 21,
+ CSS_ATTR = 22,
+ CSS_COUNTER = 23,
+ CSS_RECT = 24,
+ CSS_RGBCOLOR = 25,
+ CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.)
+ CSS_DASHBOARD_REGION = 101, // FIXME: Dashboard region should not be a primitive value.
+ CSS_UNICODE_RANGE = 102,
+
+ // These next types are just used internally to allow us to translate back and forth from CSSPrimitiveValues to CSSParserValues.
+ CSS_PARSER_OPERATOR = 103,
+ CSS_PARSER_INTEGER = 104,
+ CSS_PARSER_HEXCOLOR = 105,
+
+ // This is used internally for unknown identifiers
+ CSS_PARSER_IDENTIFIER = 106,
+
+ // These are from CSS3 Values and Units, but that isn't a finished standard yet
+ CSS_TURN = 107,
+ CSS_REMS = 108,
+
+ // This is used internally for counter names (as opposed to counter values)
+ CSS_COUNTER_NAME = 109,
+
+ // This is used by the CSS Exclusions draft
+ CSS_SHAPE = 110,
+
+ // Used by border images.
+ CSS_QUAD = 111
+ };
+
+ // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies.
+ enum UnitCategory {
+ UNumber,
+ UPercent,
+ ULength,
+ UAngle,
+ UTime,
+ UFrequency,
+ UOther
+ };
+
+ static bool isUnitTypeLength(int type) { return (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) ||
+ type == CSSPrimitiveValue::CSS_REMS; }
+
+ 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)); }
+ static PassRefPtr<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
+ static PassRefPtr<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); }
+
+ template<typename T> static PassRefPtr<CSSPrimitiveValue> create(T value)
+ {
+ return adoptRef(new CSSPrimitiveValue(value));
+ }
+
+ // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE.
+ // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em.
+ // When the quirky value is used, if you're in quirks mode, the margin will collapse away
+ // inside a table cell.
+ static PassRefPtr<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitTypes type)
+ {
+ CSSPrimitiveValue* quirkValue = new CSSPrimitiveValue(value, type);
+ quirkValue->m_isQuirkValue = true;
+ return adoptRef(quirkValue);
+ }
+
+ ~CSSPrimitiveValue();
+
+ void cleanup();
+
+ unsigned short primitiveType() const { return m_primitiveUnitType; }
+
+ /*
+ * 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.
+ *
+ * The metrics have to be a bit different for screen and printer output.
+ * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi
+ *
+ * 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);
+
+ // use with care!!!
+ void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; }
+
+ double getDoubleValue(unsigned short unitType, ExceptionCode&) const;
+ double getDoubleValue(unsigned short unitType) const;
+ double getDoubleValue() const { return m_value.num; }
+
+ void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&);
+ float getFloatValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<float>(unitType, ec); }
+ float getFloatValue(unsigned short unitType) const { return getValue<float>(unitType); }
+ float getFloatValue() const { return getValue<float>(); }
+
+ int getIntValue(unsigned short unitType, ExceptionCode& ec) const { return getValue<int>(unitType, ec); }
+ int getIntValue(unsigned short unitType) const { return getValue<int>(unitType); }
+ int getIntValue() const { return getValue<int>(); }
+
+ template<typename T> inline T getValue(unsigned short unitType, ExceptionCode& ec) const { return clampTo<T>(getDoubleValue(unitType, ec)); }
+ template<typename T> inline T getValue(unsigned short unitType) const { return clampTo<T>(getDoubleValue(unitType)); }
+ template<typename T> inline T getValue() const { return clampTo<T>(m_value.num); }
+
+ void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&);
+ String getStringValue(ExceptionCode&) const;
+ String getStringValue() const;
+
+ Counter* getCounterValue(ExceptionCode&) const;
+ Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; }
+
+ Rect* getRectValue(ExceptionCode&) const;
+ Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; }
+
+ Quad* getQuadValue(ExceptionCode&) const;
+ Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; }
+
+ PassRefPtr<RGBColor> getRGBColorValue(ExceptionCode&) const;
+ RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; }
+
+ Pair* getPairValue(ExceptionCode&) const;
+ Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; }
+
+ DashboardRegion* getDashboardRegionValue() const { return m_primitiveUnitType != CSS_DASHBOARD_REGION ? 0 : m_value.region; }
+
+ CSSWrapShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; }
+
+ int getIdent() const { return m_primitiveUnitType == CSS_IDENT ? m_value.ident : 0; }
+
+ template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h
+
+ String customCssText() const;
+
+ bool isQuirkValue() { return m_isQuirkValue; }
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
+
+protected:
+ CSSPrimitiveValue(ClassType, int ident);
+ CSSPrimitiveValue(ClassType, const String&, UnitTypes);
+
+private:
+ CSSPrimitiveValue();
+ // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and identifier cases.
+ CSSPrimitiveValue(int ident);
+ CSSPrimitiveValue(unsigned color); // RGB value
+ CSSPrimitiveValue(const Length&);
+ CSSPrimitiveValue(const String&, UnitTypes);
+ CSSPrimitiveValue(double, UnitTypes);
+
+ template<typename T> CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h
+ template<typename T> CSSPrimitiveValue(T* val)
+ : CSSValue(PrimitiveClass)
+ {
+ init(PassRefPtr<T>(val));
+ }
+
+ template<typename T> CSSPrimitiveValue(PassRefPtr<T> val)
+ : CSSValue(PrimitiveClass)
+ {
+ init(val);
+ }
+
+ static void create(int); // compile-time guard
+ static void create(unsigned); // compile-time guard
+ template<typename T> operator T*(); // compile-time guard
+
+ static PassRefPtr<CSSPrimitiveValue> createUncachedIdentifier(int identifier);
+ static PassRefPtr<CSSPrimitiveValue> createUncachedColor(unsigned rgbValue);
+ static PassRefPtr<CSSPrimitiveValue> createUncached(double value, UnitTypes type);
+
+ static UnitTypes canonicalUnitTypeForCategory(UnitCategory category);
+
+ void init(PassRefPtr<Counter>);
+ void init(PassRefPtr<Rect>);
+ void init(PassRefPtr<Pair>);
+ void init(PassRefPtr<Quad>);
+ void init(PassRefPtr<DashboardRegion>); // FIXME: Dashboard region should not be a primitive value.
+ void init(PassRefPtr<CSSWrapShape>);
+
+ bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const;
+
+ double computeLengthDouble(RenderStyle* currentStyle, RenderStyle* rootStyle, double multiplier, bool computingFontSize);
+
+ union {
+ int ident;
+ double num;
+ StringImpl* string;
+ Counter* counter;
+ Rect* rect;
+ Quad* quad;
+ unsigned rgbcolor;
+ Pair* pair;
+ DashboardRegion* region;
+ CSSWrapShape* shape;
+ } m_value;
+};
+
+} // namespace WebCore
+
+#endif // CSSPrimitiveValue_h
diff --git a/Source/WebCore/css/CSSPrimitiveValue.idl b/Source/WebCore/css/CSSPrimitiveValue.idl
new file mode 100644
index 000000000..04f17048c
--- /dev/null
+++ b/Source/WebCore/css/CSSPrimitiveValue.idl
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 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.
+ */
+
+module css {
+
+ interface CSSPrimitiveValue : CSSValue {
+
+ // UnitTypes
+ const unsigned short CSS_UNKNOWN = 0;
+ const unsigned short CSS_NUMBER = 1;
+ const unsigned short CSS_PERCENTAGE = 2;
+ const unsigned short CSS_EMS = 3;
+ const unsigned short CSS_EXS = 4;
+ const unsigned short CSS_PX = 5;
+ const unsigned short CSS_CM = 6;
+ const unsigned short CSS_MM = 7;
+ const unsigned short CSS_IN = 8;
+ const unsigned short CSS_PT = 9;
+ const unsigned short CSS_PC = 10;
+ const unsigned short CSS_DEG = 11;
+ const unsigned short CSS_RAD = 12;
+ const unsigned short CSS_GRAD = 13;
+ const unsigned short CSS_MS = 14;
+ const unsigned short CSS_S = 15;
+ const unsigned short CSS_HZ = 16;
+ const unsigned short CSS_KHZ = 17;
+ const unsigned short CSS_DIMENSION = 18;
+ const unsigned short CSS_STRING = 19;
+ const unsigned short CSS_URI = 20;
+ const unsigned short CSS_IDENT = 21;
+ const unsigned short CSS_ATTR = 22;
+ const unsigned short CSS_COUNTER = 23;
+ const unsigned short CSS_RECT = 24;
+ const unsigned short CSS_RGBCOLOR = 25;
+
+ readonly attribute unsigned short primitiveType;
+
+ [OldStyleObjC] void setFloatValue(in [Optional=CallWithDefaultValue] unsigned short unitType,
+ in [Optional=CallWithDefaultValue] float floatValue)
+ raises(DOMException);
+ float getFloatValue(in [Optional=CallWithDefaultValue] unsigned short unitType)
+ raises(DOMException);
+ [OldStyleObjC] void setStringValue(in [Optional=CallWithDefaultValue] unsigned short stringType,
+ in [Optional=CallWithDefaultValue] DOMString stringValue)
+ raises(DOMException);
+ DOMString getStringValue()
+ raises(DOMException);
+ Counter getCounterValue()
+ raises(DOMException);
+ Rect getRectValue()
+ raises(DOMException);
+ RGBColor getRGBColorValue()
+ raises(DOMException);
+ };
+
+}
diff --git a/Source/WebCore/css/CSSPrimitiveValueMappings.h b/Source/WebCore/css/CSSPrimitiveValueMappings.h
new file mode 100644
index 000000000..f8444ca6a
--- /dev/null
+++ b/Source/WebCore/css/CSSPrimitiveValueMappings.h
@@ -0,0 +1,3926 @@
+/*
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@nypop.com>.
+ * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
+ * Copyright (C) Research In Motion Limited 2010. 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 AUTHOR ``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 AUTHOR 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 CSSPrimitiveValueMappings_h
+#define CSSPrimitiveValueMappings_h
+
+#include "ColorSpace.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSValueKeywords.h"
+#include "FontDescription.h"
+#include "FontSmoothingMode.h"
+#include "GraphicsTypes.h"
+#include "Path.h"
+#include "RenderStyleConstants.h"
+#include "SVGRenderStyleDefs.h"
+#include "TextDirection.h"
+#include "TextOrientation.h"
+#include "TextRenderingMode.h"
+#include "ThemeTypes.h"
+#include "UnicodeBidi.h"
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterOperation.h"
+#endif
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(short i)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_NUMBER;
+ m_value.num = static_cast<double>(i);
+}
+
+template<> inline CSSPrimitiveValue::operator short() const
+{
+ if (m_primitiveUnitType == CSS_NUMBER)
+ return clampTo<short>(m_value.num);
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(unsigned short i)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_NUMBER;
+ m_value.num = static_cast<double>(i);
+}
+
+template<> inline CSSPrimitiveValue::operator unsigned short() const
+{
+ if (m_primitiveUnitType == CSS_NUMBER)
+ return clampTo<unsigned short>(m_value.num);
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(int i)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_NUMBER;
+ m_value.num = static_cast<double>(i);
+}
+
+template<> inline CSSPrimitiveValue::operator int() const
+{
+ if (m_primitiveUnitType == CSS_NUMBER)
+ return clampTo<int>(m_value.num);
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(unsigned i)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_NUMBER;
+ m_value.num = static_cast<double>(i);
+}
+
+template<> inline CSSPrimitiveValue::operator unsigned() const
+{
+ if (m_primitiveUnitType == CSS_NUMBER)
+ return clampTo<unsigned>(m_value.num);
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(float i)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_NUMBER;
+ m_value.num = static_cast<double>(i);
+}
+
+template<> inline CSSPrimitiveValue::operator float() const
+{
+ if (m_primitiveUnitType == CSS_NUMBER)
+ return clampTo<float>(m_value.num);
+
+ ASSERT_NOT_REACHED();
+ return 0.0f;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColumnSpan columnSpan)
+ : CSSValue(PrimitiveClass)
+{
+ switch (columnSpan) {
+ case ColumnSpanAll:
+ m_primitiveUnitType = CSS_IDENT;
+ m_value.ident = CSSValueAll;
+ break;
+ case ColumnSpanOne:
+ m_primitiveUnitType = CSS_NUMBER;
+ m_value.num = 1;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ColumnSpan() const
+{
+ if (m_primitiveUnitType == CSS_IDENT && m_value.ident == CSSValueAll)
+ return ColumnSpanAll;
+ if (m_primitiveUnitType == CSS_NUMBER && m_value.num == 1)
+ return ColumnSpanOne;
+ ASSERT_NOT_REACHED();
+ return ColumnSpanOne;
+}
+
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(PrintColorAdjust value)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (value) {
+ case PrintColorAdjustExact:
+ m_value.ident = CSSValueExact;
+ break;
+ case PrintColorAdjustEconomy:
+ m_value.ident = CSSValueEconomy;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator PrintColorAdjust() const
+{
+ switch (m_value.ident) {
+ case CSSValueEconomy:
+ return PrintColorAdjustEconomy;
+ case CSSValueExact:
+ return PrintColorAdjustExact;
+ default:
+ ASSERT_NOT_REACHED();
+ return PrintColorAdjustEconomy;
+ }
+}
+
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBorderStyle e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BNONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case BHIDDEN:
+ m_value.ident = CSSValueHidden;
+ break;
+ case INSET:
+ m_value.ident = CSSValueInset;
+ break;
+ case GROOVE:
+ m_value.ident = CSSValueGroove;
+ break;
+ case RIDGE:
+ m_value.ident = CSSValueRidge;
+ break;
+ case OUTSET:
+ m_value.ident = CSSValueOutset;
+ break;
+ case DOTTED:
+ m_value.ident = CSSValueDotted;
+ break;
+ case DASHED:
+ m_value.ident = CSSValueDashed;
+ break;
+ case SOLID:
+ m_value.ident = CSSValueSolid;
+ break;
+ case DOUBLE:
+ m_value.ident = CSSValueDouble;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBorderStyle() const
+{
+ if (m_value.ident == CSSValueAuto) // Valid for CSS outline-style
+ return DOTTED;
+ return (EBorderStyle)(m_value.ident - CSSValueNone);
+}
+
+template<> inline CSSPrimitiveValue::operator OutlineIsAuto() const
+{
+ if (m_value.ident == CSSValueAuto)
+ return AUTO_ON;
+ return AUTO_OFF;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CompositeOperator e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CompositeClear:
+ m_value.ident = CSSValueClear;
+ break;
+ case CompositeCopy:
+ m_value.ident = CSSValueCopy;
+ break;
+ case CompositeSourceOver:
+ m_value.ident = CSSValueSourceOver;
+ break;
+ case CompositeSourceIn:
+ m_value.ident = CSSValueSourceIn;
+ break;
+ case CompositeSourceOut:
+ m_value.ident = CSSValueSourceOut;
+ break;
+ case CompositeSourceAtop:
+ m_value.ident = CSSValueSourceAtop;
+ break;
+ case CompositeDestinationOver:
+ m_value.ident = CSSValueDestinationOver;
+ break;
+ case CompositeDestinationIn:
+ m_value.ident = CSSValueDestinationIn;
+ break;
+ case CompositeDestinationOut:
+ m_value.ident = CSSValueDestinationOut;
+ break;
+ case CompositeDestinationAtop:
+ m_value.ident = CSSValueDestinationAtop;
+ break;
+ case CompositeXOR:
+ m_value.ident = CSSValueXor;
+ break;
+ case CompositePlusDarker:
+ m_value.ident = CSSValuePlusDarker;
+ break;
+ case CompositePlusLighter:
+ m_value.ident = CSSValuePlusLighter;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator CompositeOperator() const
+{
+ switch (m_value.ident) {
+ case CSSValueClear:
+ return CompositeClear;
+ case CSSValueCopy:
+ return CompositeCopy;
+ case CSSValueSourceOver:
+ return CompositeSourceOver;
+ case CSSValueSourceIn:
+ return CompositeSourceIn;
+ case CSSValueSourceOut:
+ return CompositeSourceOut;
+ case CSSValueSourceAtop:
+ return CompositeSourceAtop;
+ case CSSValueDestinationOver:
+ return CompositeDestinationOver;
+ case CSSValueDestinationIn:
+ return CompositeDestinationIn;
+ case CSSValueDestinationOut:
+ return CompositeDestinationOut;
+ case CSSValueDestinationAtop:
+ return CompositeDestinationAtop;
+ case CSSValueXor:
+ return CompositeXOR;
+ case CSSValuePlusDarker:
+ return CompositePlusDarker;
+ case CSSValuePlusLighter:
+ return CompositePlusLighter;
+ default:
+ ASSERT_NOT_REACHED();
+ return CompositeClear;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case NoControlPart:
+ m_value.ident = CSSValueNone;
+ break;
+ case CheckboxPart:
+ m_value.ident = CSSValueCheckbox;
+ break;
+ case RadioPart:
+ m_value.ident = CSSValueRadio;
+ break;
+ case PushButtonPart:
+ m_value.ident = CSSValuePushButton;
+ break;
+ case SquareButtonPart:
+ m_value.ident = CSSValueSquareButton;
+ break;
+ case ButtonPart:
+ m_value.ident = CSSValueButton;
+ break;
+ case ButtonBevelPart:
+ m_value.ident = CSSValueButtonBevel;
+ break;
+ case DefaultButtonPart:
+ m_value.ident = CSSValueDefaultButton;
+ break;
+ case InnerSpinButtonPart:
+ m_value.ident = CSSValueInnerSpinButton;
+ break;
+ case ListboxPart:
+ m_value.ident = CSSValueListbox;
+ break;
+ case ListButtonPart:
+#if ENABLE(DATALIST)
+ m_value.ident = CSSValueListButton;
+#endif
+ break;
+ case ListItemPart:
+ m_value.ident = CSSValueListitem;
+ break;
+ case MediaFullscreenButtonPart:
+ m_value.ident = CSSValueMediaFullscreenButton;
+ break;
+ case MediaPlayButtonPart:
+ m_value.ident = CSSValueMediaPlayButton;
+ break;
+ case MediaMuteButtonPart:
+ m_value.ident = CSSValueMediaMuteButton;
+ break;
+ case MediaSeekBackButtonPart:
+ m_value.ident = CSSValueMediaSeekBackButton;
+ break;
+ case MediaSeekForwardButtonPart:
+ m_value.ident = CSSValueMediaSeekForwardButton;
+ break;
+ case MediaRewindButtonPart:
+ m_value.ident = CSSValueMediaRewindButton;
+ break;
+ case MediaReturnToRealtimeButtonPart:
+ m_value.ident = CSSValueMediaReturnToRealtimeButton;
+ break;
+ case MediaToggleClosedCaptionsButtonPart:
+ m_value.ident = CSSValueMediaToggleClosedCaptionsButton;
+ break;
+ case MediaSliderPart:
+ m_value.ident = CSSValueMediaSlider;
+ break;
+ case MediaSliderThumbPart:
+ m_value.ident = CSSValueMediaSliderthumb;
+ break;
+ case MediaVolumeSliderContainerPart:
+ m_value.ident = CSSValueMediaVolumeSliderContainer;
+ break;
+ case MediaVolumeSliderPart:
+ m_value.ident = CSSValueMediaVolumeSlider;
+ break;
+ case MediaVolumeSliderMuteButtonPart:
+ m_value.ident = CSSValueMediaVolumeSliderMuteButton;
+ break;
+ case MediaVolumeSliderThumbPart:
+ m_value.ident = CSSValueMediaVolumeSliderthumb;
+ break;
+ case MediaControlsBackgroundPart:
+ m_value.ident = CSSValueMediaControlsBackground;
+ break;
+ case MediaControlsFullscreenBackgroundPart:
+ m_value.ident = CSSValueMediaControlsFullscreenBackground;
+ break;
+ case MediaCurrentTimePart:
+ m_value.ident = CSSValueMediaCurrentTimeDisplay;
+ break;
+ case MediaTimeRemainingPart:
+ m_value.ident = CSSValueMediaTimeRemainingDisplay;
+ break;
+ case MenulistPart:
+ m_value.ident = CSSValueMenulist;
+ break;
+ case MenulistButtonPart:
+ m_value.ident = CSSValueMenulistButton;
+ break;
+ case MenulistTextPart:
+ m_value.ident = CSSValueMenulistText;
+ break;
+ case MenulistTextFieldPart:
+ m_value.ident = CSSValueMenulistTextfield;
+ break;
+ case MeterPart:
+ m_value.ident = CSSValueMeter;
+ break;
+ case RelevancyLevelIndicatorPart:
+ m_value.ident = CSSValueRelevancyLevelIndicator;
+ break;
+ case ContinuousCapacityLevelIndicatorPart:
+ m_value.ident = CSSValueContinuousCapacityLevelIndicator;
+ break;
+ case DiscreteCapacityLevelIndicatorPart:
+ m_value.ident = CSSValueDiscreteCapacityLevelIndicator;
+ break;
+ case RatingLevelIndicatorPart:
+ m_value.ident = CSSValueRatingLevelIndicator;
+ break;
+ case ProgressBarPart:
+#if ENABLE(PROGRESS_TAG)
+ m_value.ident = CSSValueProgressBar;
+#endif
+ break;
+ case ProgressBarValuePart:
+#if ENABLE(PROGRESS_TAG)
+ m_value.ident = CSSValueProgressBarValue;
+#endif
+ break;
+ case SliderHorizontalPart:
+ m_value.ident = CSSValueSliderHorizontal;
+ break;
+ case SliderVerticalPart:
+ m_value.ident = CSSValueSliderVertical;
+ break;
+ case SliderThumbHorizontalPart:
+ m_value.ident = CSSValueSliderthumbHorizontal;
+ break;
+ case SliderThumbVerticalPart:
+ m_value.ident = CSSValueSliderthumbVertical;
+ break;
+ case CaretPart:
+ m_value.ident = CSSValueCaret;
+ break;
+ case SearchFieldPart:
+ m_value.ident = CSSValueSearchfield;
+ break;
+ case SearchFieldDecorationPart:
+ m_value.ident = CSSValueSearchfieldDecoration;
+ break;
+ case SearchFieldResultsDecorationPart:
+ m_value.ident = CSSValueSearchfieldResultsDecoration;
+ break;
+ case SearchFieldResultsButtonPart:
+ m_value.ident = CSSValueSearchfieldResultsButton;
+ break;
+ case SearchFieldCancelButtonPart:
+ m_value.ident = CSSValueSearchfieldCancelButton;
+ break;
+ case TextFieldPart:
+ m_value.ident = CSSValueTextfield;
+ break;
+ case TextAreaPart:
+ m_value.ident = CSSValueTextarea;
+ break;
+ case CapsLockIndicatorPart:
+ m_value.ident = CSSValueCapsLockIndicator;
+ break;
+ case InputSpeechButtonPart:
+#if ENABLE(INPUT_SPEECH)
+ m_value.ident = CSSValueWebkitInputSpeechButton;
+#endif
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ControlPart() const
+{
+ if (m_value.ident == CSSValueNone)
+ return NoControlPart;
+ else
+ return ControlPart(m_value.ident - CSSValueCheckbox + 1);
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBackfaceVisibility e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BackfaceVisibilityVisible:
+ m_value.ident = CSSValueVisible;
+ break;
+ case BackfaceVisibilityHidden:
+ m_value.ident = CSSValueHidden;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBackfaceVisibility() const
+{
+ switch (m_value.ident) {
+ case CSSValueVisible:
+ return BackfaceVisibilityVisible;
+ case CSSValueHidden:
+ return BackfaceVisibilityHidden;
+ default:
+ ASSERT_NOT_REACHED();
+ return BackfaceVisibilityHidden;
+ }
+}
+
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFillAttachment e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case ScrollBackgroundAttachment:
+ m_value.ident = CSSValueScroll;
+ break;
+ case LocalBackgroundAttachment:
+ m_value.ident = CSSValueLocal;
+ break;
+ case FixedBackgroundAttachment:
+ m_value.ident = CSSValueFixed;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFillAttachment() const
+{
+ switch (m_value.ident) {
+ case CSSValueScroll:
+ return ScrollBackgroundAttachment;
+ case CSSValueLocal:
+ return LocalBackgroundAttachment;
+ case CSSValueFixed:
+ return FixedBackgroundAttachment;
+ default:
+ ASSERT_NOT_REACHED();
+ return ScrollBackgroundAttachment;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFillBox e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BorderFillBox:
+ m_value.ident = CSSValueBorderBox;
+ break;
+ case PaddingFillBox:
+ m_value.ident = CSSValuePaddingBox;
+ break;
+ case ContentFillBox:
+ m_value.ident = CSSValueContentBox;
+ break;
+ case TextFillBox:
+ m_value.ident = CSSValueText;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFillBox() const
+{
+ switch (m_value.ident) {
+ case CSSValueBorder:
+ case CSSValueBorderBox:
+ return BorderFillBox;
+ case CSSValuePadding:
+ case CSSValuePaddingBox:
+ return PaddingFillBox;
+ case CSSValueContent:
+ case CSSValueContentBox:
+ return ContentFillBox;
+ case CSSValueText:
+ case CSSValueWebkitText:
+ return TextFillBox;
+ default:
+ ASSERT_NOT_REACHED();
+ return BorderFillBox;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFillRepeat e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case RepeatFill:
+ m_value.ident = CSSValueRepeat;
+ break;
+ case NoRepeatFill:
+ m_value.ident = CSSValueNoRepeat;
+ break;
+ case RoundFill:
+ m_value.ident = CSSValueRound;
+ break;
+ case SpaceFill:
+ m_value.ident = CSSValueSpace;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFillRepeat() const
+{
+ switch (m_value.ident) {
+ case CSSValueRepeat:
+ return RepeatFill;
+ case CSSValueNoRepeat:
+ return NoRepeatFill;
+ case CSSValueRound:
+ return RoundFill;
+ case CSSValueSpace:
+ return SpaceFill;
+ default:
+ ASSERT_NOT_REACHED();
+ return RepeatFill;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxPack e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case Start:
+ m_value.ident = CSSValueStart;
+ break;
+ case Center:
+ m_value.ident = CSSValueCenter;
+ break;
+ case End:
+ m_value.ident = CSSValueEnd;
+ break;
+ case Justify:
+ m_value.ident = CSSValueJustify;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBoxPack() const
+{
+ switch (m_value.ident) {
+ case CSSValueStart:
+ return Start;
+ case CSSValueEnd:
+ return End;
+ case CSSValueCenter:
+ return Center;
+ case CSSValueJustify:
+ return Justify;
+ default:
+ ASSERT_NOT_REACHED();
+ return Justify;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxAlignment e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BSTRETCH:
+ m_value.ident = CSSValueStretch;
+ break;
+ case BSTART:
+ m_value.ident = CSSValueStart;
+ break;
+ case BCENTER:
+ m_value.ident = CSSValueCenter;
+ break;
+ case BEND:
+ m_value.ident = CSSValueEnd;
+ break;
+ case BBASELINE:
+ m_value.ident = CSSValueBaseline;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBoxAlignment() const
+{
+ switch (m_value.ident) {
+ case CSSValueStretch:
+ return BSTRETCH;
+ case CSSValueStart:
+ return BSTART;
+ case CSSValueEnd:
+ return BEND;
+ case CSSValueCenter:
+ return BCENTER;
+ case CSSValueBaseline:
+ return BBASELINE;
+ default:
+ ASSERT_NOT_REACHED();
+ return BSTRETCH;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxSizing e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BORDER_BOX:
+ m_value.ident = CSSValueBorderBox;
+ break;
+ case CONTENT_BOX:
+ m_value.ident = CSSValueContentBox;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBoxSizing() const
+{
+ switch (m_value.ident) {
+ case CSSValueBorderBox:
+ return BORDER_BOX;
+ case CSSValueContentBox:
+ return CONTENT_BOX;
+ default:
+ ASSERT_NOT_REACHED();
+ return BORDER_BOX;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxDirection e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BNORMAL:
+ m_value.ident = CSSValueNormal;
+ break;
+ case BREVERSE:
+ m_value.ident = CSSValueReverse;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBoxDirection() const
+{
+ switch (m_value.ident) {
+ case CSSValueNormal:
+ return BNORMAL;
+ case CSSValueReverse:
+ return BREVERSE;
+ default:
+ ASSERT_NOT_REACHED();
+ return BNORMAL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxLines e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case SINGLE:
+ m_value.ident = CSSValueSingle;
+ break;
+ case MULTIPLE:
+ m_value.ident = CSSValueMultiple;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBoxLines() const
+{
+ switch (m_value.ident) {
+ case CSSValueSingle:
+ return SINGLE;
+ case CSSValueMultiple:
+ return MULTIPLE;
+ default:
+ ASSERT_NOT_REACHED();
+ return SINGLE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBoxOrient e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case HORIZONTAL:
+ m_value.ident = CSSValueHorizontal;
+ break;
+ case VERTICAL:
+ m_value.ident = CSSValueVertical;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBoxOrient() const
+{
+ switch (m_value.ident) {
+ case CSSValueHorizontal:
+ case CSSValueInlineAxis:
+ return HORIZONTAL;
+ case CSSValueVertical:
+ case CSSValueBlockAxis:
+ return VERTICAL;
+ default:
+ ASSERT_NOT_REACHED();
+ return HORIZONTAL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ECaptionSide e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CAPLEFT:
+ m_value.ident = CSSValueLeft;
+ break;
+ case CAPRIGHT:
+ m_value.ident = CSSValueRight;
+ break;
+ case CAPTOP:
+ m_value.ident = CSSValueTop;
+ break;
+ case CAPBOTTOM:
+ m_value.ident = CSSValueBottom;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ECaptionSide() const
+{
+ switch (m_value.ident) {
+ case CSSValueLeft:
+ return CAPLEFT;
+ case CSSValueRight:
+ return CAPRIGHT;
+ case CSSValueTop:
+ return CAPTOP;
+ case CSSValueBottom:
+ return CAPBOTTOM;
+ default:
+ ASSERT_NOT_REACHED();
+ return CAPTOP;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EClear e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CNONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case CLEFT:
+ m_value.ident = CSSValueLeft;
+ break;
+ case CRIGHT:
+ m_value.ident = CSSValueRight;
+ break;
+ case CBOTH:
+ m_value.ident = CSSValueBoth;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EClear() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return CNONE;
+ case CSSValueLeft:
+ return CLEFT;
+ case CSSValueRight:
+ return CRIGHT;
+ case CSSValueBoth:
+ return CBOTH;
+ default:
+ ASSERT_NOT_REACHED();
+ return CNONE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ECursor e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CURSOR_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case CURSOR_CROSS:
+ m_value.ident = CSSValueCrosshair;
+ break;
+ case CURSOR_DEFAULT:
+ m_value.ident = CSSValueDefault;
+ break;
+ case CURSOR_POINTER:
+ m_value.ident = CSSValuePointer;
+ break;
+ case CURSOR_MOVE:
+ m_value.ident = CSSValueMove;
+ break;
+ case CURSOR_CELL:
+ m_value.ident = CSSValueCell;
+ break;
+ case CURSOR_VERTICAL_TEXT:
+ m_value.ident = CSSValueVerticalText;
+ break;
+ case CURSOR_CONTEXT_MENU:
+ m_value.ident = CSSValueContextMenu;
+ break;
+ case CURSOR_ALIAS:
+ m_value.ident = CSSValueAlias;
+ break;
+ case CURSOR_COPY:
+ m_value.ident = CSSValueCopy;
+ break;
+ case CURSOR_NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case CURSOR_PROGRESS:
+ m_value.ident = CSSValueProgress;
+ break;
+ case CURSOR_NO_DROP:
+ m_value.ident = CSSValueNoDrop;
+ break;
+ case CURSOR_NOT_ALLOWED:
+ m_value.ident = CSSValueNotAllowed;
+ break;
+ case CURSOR_WEBKIT_ZOOM_IN:
+ m_value.ident = CSSValueWebkitZoomIn;
+ break;
+ case CURSOR_WEBKIT_ZOOM_OUT:
+ m_value.ident = CSSValueWebkitZoomOut;
+ break;
+ case CURSOR_E_RESIZE:
+ m_value.ident = CSSValueEResize;
+ break;
+ case CURSOR_NE_RESIZE:
+ m_value.ident = CSSValueNeResize;
+ break;
+ case CURSOR_NW_RESIZE:
+ m_value.ident = CSSValueNwResize;
+ break;
+ case CURSOR_N_RESIZE:
+ m_value.ident = CSSValueNResize;
+ break;
+ case CURSOR_SE_RESIZE:
+ m_value.ident = CSSValueSeResize;
+ break;
+ case CURSOR_SW_RESIZE:
+ m_value.ident = CSSValueSwResize;
+ break;
+ case CURSOR_S_RESIZE:
+ m_value.ident = CSSValueSResize;
+ break;
+ case CURSOR_W_RESIZE:
+ m_value.ident = CSSValueWResize;
+ break;
+ case CURSOR_EW_RESIZE:
+ m_value.ident = CSSValueEwResize;
+ break;
+ case CURSOR_NS_RESIZE:
+ m_value.ident = CSSValueNsResize;
+ break;
+ case CURSOR_NESW_RESIZE:
+ m_value.ident = CSSValueNeswResize;
+ break;
+ case CURSOR_NWSE_RESIZE:
+ m_value.ident = CSSValueNwseResize;
+ break;
+ case CURSOR_COL_RESIZE:
+ m_value.ident = CSSValueColResize;
+ break;
+ case CURSOR_ROW_RESIZE:
+ m_value.ident = CSSValueRowResize;
+ break;
+ case CURSOR_TEXT:
+ m_value.ident = CSSValueText;
+ break;
+ case CURSOR_WAIT:
+ m_value.ident = CSSValueWait;
+ break;
+ case CURSOR_HELP:
+ m_value.ident = CSSValueHelp;
+ break;
+ case CURSOR_ALL_SCROLL:
+ m_value.ident = CSSValueAllScroll;
+ break;
+ case CURSOR_WEBKIT_GRAB:
+ m_value.ident = CSSValueWebkitGrab;
+ break;
+ case CURSOR_WEBKIT_GRABBING:
+ m_value.ident = CSSValueWebkitGrabbing;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ECursor() const
+{
+ if (m_value.ident == CSSValueCopy)
+ return CURSOR_COPY;
+ if (m_value.ident == CSSValueNone)
+ return CURSOR_NONE;
+ return static_cast<ECursor>(m_value.ident - CSSValueAuto);
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EDisplay e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case INLINE:
+ m_value.ident = CSSValueInline;
+ break;
+ case BLOCK:
+ m_value.ident = CSSValueBlock;
+ break;
+ case LIST_ITEM:
+ m_value.ident = CSSValueListItem;
+ break;
+ case RUN_IN:
+ m_value.ident = CSSValueRunIn;
+ break;
+ case COMPACT:
+ m_value.ident = CSSValueCompact;
+ break;
+ case INLINE_BLOCK:
+ m_value.ident = CSSValueInlineBlock;
+ break;
+ case TABLE:
+ m_value.ident = CSSValueTable;
+ break;
+ case INLINE_TABLE:
+ m_value.ident = CSSValueInlineTable;
+ break;
+ case TABLE_ROW_GROUP:
+ m_value.ident = CSSValueTableRowGroup;
+ break;
+ case TABLE_HEADER_GROUP:
+ m_value.ident = CSSValueTableHeaderGroup;
+ break;
+ case TABLE_FOOTER_GROUP:
+ m_value.ident = CSSValueTableFooterGroup;
+ break;
+ case TABLE_ROW:
+ m_value.ident = CSSValueTableRow;
+ break;
+ case TABLE_COLUMN_GROUP:
+ m_value.ident = CSSValueTableColumnGroup;
+ break;
+ case TABLE_COLUMN:
+ m_value.ident = CSSValueTableColumn;
+ break;
+ case TABLE_CELL:
+ m_value.ident = CSSValueTableCell;
+ break;
+ case TABLE_CAPTION:
+ m_value.ident = CSSValueTableCaption;
+ break;
+ case BOX:
+ m_value.ident = CSSValueWebkitBox;
+ break;
+ case INLINE_BOX:
+ m_value.ident = CSSValueWebkitInlineBox;
+ break;
+ case FLEXBOX:
+ m_value.ident = CSSValueWebkitFlexbox;
+ break;
+ case INLINE_FLEXBOX:
+ m_value.ident = CSSValueWebkitInlineFlexbox;
+ break;
+#if ENABLE(CSS_GRID_LAYOUT)
+ case GRID:
+ m_value.ident = CSSValueWebkitGrid;
+ break;
+ case INLINE_GRID:
+ m_value.ident = CSSValueWebkitInlineGrid;
+ break;
+#endif
+ case NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EDisplay() const
+{
+ if (m_value.ident == CSSValueNone)
+ return NONE;
+
+ EDisplay display = static_cast<EDisplay>(m_value.ident - CSSValueInline);
+ ASSERT(display >= INLINE && display <= NONE);
+ return display;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EEmptyCell e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case SHOW:
+ m_value.ident = CSSValueShow;
+ break;
+ case HIDE:
+ m_value.ident = CSSValueHide;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EEmptyCell() const
+{
+ switch (m_value.ident) {
+ case CSSValueShow:
+ return SHOW;
+ case CSSValueHide:
+ return HIDE;
+ default:
+ ASSERT_NOT_REACHED();
+ return SHOW;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFlexAlign e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case AlignStart:
+ m_value.ident = CSSValueStart;
+ break;
+ case AlignEnd:
+ m_value.ident = CSSValueEnd;
+ break;
+ case AlignCenter:
+ m_value.ident = CSSValueCenter;
+ break;
+ case AlignStretch:
+ m_value.ident = CSSValueStretch;
+ break;
+ case AlignBaseline:
+ m_value.ident = CSSValueBaseline;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFlexAlign() const
+{
+ switch (m_value.ident) {
+ case CSSValueStart:
+ return AlignStart;
+ case CSSValueEnd:
+ return AlignEnd;
+ case CSSValueCenter:
+ return AlignCenter;
+ case CSSValueStretch:
+ return AlignStretch;
+ case CSSValueBaseline:
+ return AlignBaseline;
+ default:
+ ASSERT_NOT_REACHED();
+ return AlignStart;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFlexPack e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case PackStart:
+ m_value.ident = CSSValueStart;
+ break;
+ case PackEnd:
+ m_value.ident = CSSValueEnd;
+ break;
+ case PackCenter:
+ m_value.ident = CSSValueCenter;
+ break;
+ case PackJustify:
+ m_value.ident = CSSValueJustify;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFlexPack() const
+{
+ switch (m_value.ident) {
+ case CSSValueStart:
+ return PackStart;
+ case CSSValueEnd:
+ return PackEnd;
+ case CSSValueCenter:
+ return PackCenter;
+ case CSSValueJustify:
+ return PackJustify;
+ default:
+ ASSERT_NOT_REACHED();
+ return PackStart;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFlexDirection e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case FlowRow:
+ m_value.ident = CSSValueRow;
+ break;
+ case FlowRowReverse:
+ m_value.ident = CSSValueRowReverse;
+ break;
+ case FlowColumn:
+ m_value.ident = CSSValueColumn;
+ break;
+ case FlowColumnReverse:
+ m_value.ident = CSSValueColumnReverse;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFlexDirection() const
+{
+ switch (m_value.ident) {
+ case CSSValueRow:
+ return FlowRow;
+ case CSSValueRowReverse:
+ return FlowRowReverse;
+ case CSSValueColumn:
+ return FlowColumn;
+ case CSSValueColumnReverse:
+ return FlowColumnReverse;
+ default:
+ ASSERT_NOT_REACHED();
+ return FlowRow;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFlexWrap e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case FlexNoWrap:
+ m_value.ident = CSSValueNowrap;
+ break;
+ case FlexWrap:
+ m_value.ident = CSSValueWrap;
+ break;
+ case FlexWrapReverse:
+ m_value.ident = CSSValueWrapReverse;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFlexWrap() const
+{
+ switch (m_value.ident) {
+ case CSSValueNowrap:
+ return FlexNoWrap;
+ case CSSValueWrap:
+ return FlexWrap;
+ case CSSValueWrapReverse:
+ return FlexWrapReverse;
+ default:
+ ASSERT_NOT_REACHED();
+ return FlexNoWrap;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFloat e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case NoFloat:
+ m_value.ident = CSSValueNone;
+ break;
+ case LeftFloat:
+ m_value.ident = CSSValueLeft;
+ break;
+ case RightFloat:
+ m_value.ident = CSSValueRight;
+ break;
+ case PositionedFloat:
+ m_value.ident = CSSValueWebkitPositioned;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EFloat() const
+{
+ switch (m_value.ident) {
+ case CSSValueLeft:
+ return LeftFloat;
+ case CSSValueRight:
+ return RightFloat;
+ case CSSValueNone:
+ case CSSValueCenter: // Non-standard CSS value
+ return NoFloat;
+ case CSSValueWebkitPositioned:
+ return PositionedFloat;
+ default:
+ ASSERT_NOT_REACHED();
+ return NoFloat;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EKHTMLLineBreak e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case LBNORMAL:
+ m_value.ident = CSSValueNormal;
+ break;
+ case AFTER_WHITE_SPACE:
+ m_value.ident = CSSValueAfterWhiteSpace;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EKHTMLLineBreak() const
+{
+ switch (m_value.ident) {
+ case CSSValueAfterWhiteSpace:
+ return AFTER_WHITE_SPACE;
+ case CSSValueNormal:
+ return LBNORMAL;
+ default:
+ ASSERT_NOT_REACHED();
+ return LBNORMAL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EListStylePosition e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case OUTSIDE:
+ m_value.ident = CSSValueOutside;
+ break;
+ case INSIDE:
+ m_value.ident = CSSValueInside;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EListStylePosition() const
+{
+ return (EListStylePosition)(m_value.ident - CSSValueOutside);
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EListStyleType e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case Afar:
+ m_value.ident = CSSValueAfar;
+ break;
+ case Amharic:
+ m_value.ident = CSSValueAmharic;
+ break;
+ case AmharicAbegede:
+ m_value.ident = CSSValueAmharicAbegede;
+ break;
+ case ArabicIndic:
+ m_value.ident = CSSValueArabicIndic;
+ break;
+ case Armenian:
+ m_value.ident = CSSValueArmenian;
+ break;
+ case Asterisks:
+ m_value.ident = CSSValueAsterisks;
+ break;
+ case BinaryListStyle:
+ m_value.ident = CSSValueBinary;
+ break;
+ case Bengali:
+ m_value.ident = CSSValueBengali;
+ break;
+ case Cambodian:
+ m_value.ident = CSSValueCambodian;
+ break;
+ case Circle:
+ m_value.ident = CSSValueCircle;
+ break;
+ case CjkEarthlyBranch:
+ m_value.ident = CSSValueCjkEarthlyBranch;
+ break;
+ case CjkHeavenlyStem:
+ m_value.ident = CSSValueCjkHeavenlyStem;
+ break;
+ case CJKIdeographic:
+ m_value.ident = CSSValueCjkIdeographic;
+ break;
+ case DecimalLeadingZero:
+ m_value.ident = CSSValueDecimalLeadingZero;
+ break;
+ case DecimalListStyle:
+ m_value.ident = CSSValueDecimal;
+ break;
+ case Devanagari:
+ m_value.ident = CSSValueDevanagari;
+ break;
+ case Disc:
+ m_value.ident = CSSValueDisc;
+ break;
+ case Ethiopic:
+ m_value.ident = CSSValueEthiopic;
+ break;
+ case EthiopicAbegede:
+ m_value.ident = CSSValueEthiopicAbegede;
+ break;
+ case EthiopicAbegedeAmEt:
+ m_value.ident = CSSValueEthiopicAbegedeAmEt;
+ break;
+ case EthiopicAbegedeGez:
+ m_value.ident = CSSValueEthiopicAbegedeGez;
+ break;
+ case EthiopicAbegedeTiEr:
+ m_value.ident = CSSValueEthiopicAbegedeTiEr;
+ break;
+ case EthiopicAbegedeTiEt:
+ m_value.ident = CSSValueEthiopicAbegedeTiEt;
+ break;
+ case EthiopicHalehameAaEr:
+ m_value.ident = CSSValueEthiopicHalehameAaEr;
+ break;
+ case EthiopicHalehameAaEt:
+ m_value.ident = CSSValueEthiopicHalehameAaEt;
+ break;
+ case EthiopicHalehameAmEt:
+ m_value.ident = CSSValueEthiopicHalehameAmEt;
+ break;
+ case EthiopicHalehameGez:
+ m_value.ident = CSSValueEthiopicHalehameGez;
+ break;
+ case EthiopicHalehameOmEt:
+ m_value.ident = CSSValueEthiopicHalehameOmEt;
+ break;
+ case EthiopicHalehameSidEt:
+ m_value.ident = CSSValueEthiopicHalehameSidEt;
+ break;
+ case EthiopicHalehameSoEt:
+ m_value.ident = CSSValueEthiopicHalehameSoEt;
+ break;
+ case EthiopicHalehameTiEr:
+ m_value.ident = CSSValueEthiopicHalehameTiEr;
+ break;
+ case EthiopicHalehameTiEt:
+ m_value.ident = CSSValueEthiopicHalehameTiEt;
+ break;
+ case EthiopicHalehameTig:
+ m_value.ident = CSSValueEthiopicHalehameTig;
+ break;
+ case Footnotes:
+ m_value.ident = CSSValueFootnotes;
+ break;
+ case Georgian:
+ m_value.ident = CSSValueGeorgian;
+ break;
+ case Gujarati:
+ m_value.ident = CSSValueGujarati;
+ break;
+ case Gurmukhi:
+ m_value.ident = CSSValueGurmukhi;
+ break;
+ case Hangul:
+ m_value.ident = CSSValueHangul;
+ break;
+ case HangulConsonant:
+ m_value.ident = CSSValueHangulConsonant;
+ break;
+ case Hebrew:
+ m_value.ident = CSSValueHebrew;
+ break;
+ case Hiragana:
+ m_value.ident = CSSValueHiragana;
+ break;
+ case HiraganaIroha:
+ m_value.ident = CSSValueHiraganaIroha;
+ break;
+ case Kannada:
+ m_value.ident = CSSValueKannada;
+ break;
+ case Katakana:
+ m_value.ident = CSSValueKatakana;
+ break;
+ case KatakanaIroha:
+ m_value.ident = CSSValueKatakanaIroha;
+ break;
+ case Khmer:
+ m_value.ident = CSSValueKhmer;
+ break;
+ case Lao:
+ m_value.ident = CSSValueLao;
+ break;
+ case LowerAlpha:
+ m_value.ident = CSSValueLowerAlpha;
+ break;
+ case LowerArmenian:
+ m_value.ident = CSSValueLowerArmenian;
+ break;
+ case LowerGreek:
+ m_value.ident = CSSValueLowerGreek;
+ break;
+ case LowerHexadecimal:
+ m_value.ident = CSSValueLowerHexadecimal;
+ break;
+ case LowerLatin:
+ m_value.ident = CSSValueLowerLatin;
+ break;
+ case LowerNorwegian:
+ m_value.ident = CSSValueLowerNorwegian;
+ break;
+ case LowerRoman:
+ m_value.ident = CSSValueLowerRoman;
+ break;
+ case Malayalam:
+ m_value.ident = CSSValueMalayalam;
+ break;
+ case Mongolian:
+ m_value.ident = CSSValueMongolian;
+ break;
+ case Myanmar:
+ m_value.ident = CSSValueMyanmar;
+ break;
+ case NoneListStyle:
+ m_value.ident = CSSValueNone;
+ break;
+ case Octal:
+ m_value.ident = CSSValueOctal;
+ break;
+ case Oriya:
+ m_value.ident = CSSValueOriya;
+ break;
+ case Oromo:
+ m_value.ident = CSSValueOromo;
+ break;
+ case Persian:
+ m_value.ident = CSSValuePersian;
+ break;
+ case Sidama:
+ m_value.ident = CSSValueSidama;
+ break;
+ case Somali:
+ m_value.ident = CSSValueSomali;
+ break;
+ case Square:
+ m_value.ident = CSSValueSquare;
+ break;
+ case Telugu:
+ m_value.ident = CSSValueTelugu;
+ break;
+ case Thai:
+ m_value.ident = CSSValueThai;
+ break;
+ case Tibetan:
+ m_value.ident = CSSValueTibetan;
+ break;
+ case Tigre:
+ m_value.ident = CSSValueTigre;
+ break;
+ case TigrinyaEr:
+ m_value.ident = CSSValueTigrinyaEr;
+ break;
+ case TigrinyaErAbegede:
+ m_value.ident = CSSValueTigrinyaErAbegede;
+ break;
+ case TigrinyaEt:
+ m_value.ident = CSSValueTigrinyaEt;
+ break;
+ case TigrinyaEtAbegede:
+ m_value.ident = CSSValueTigrinyaEtAbegede;
+ break;
+ case UpperAlpha:
+ m_value.ident = CSSValueUpperAlpha;
+ break;
+ case UpperArmenian:
+ m_value.ident = CSSValueUpperArmenian;
+ break;
+ case UpperGreek:
+ m_value.ident = CSSValueUpperGreek;
+ break;
+ case UpperHexadecimal:
+ m_value.ident = CSSValueUpperHexadecimal;
+ break;
+ case UpperLatin:
+ m_value.ident = CSSValueUpperLatin;
+ break;
+ case UpperNorwegian:
+ m_value.ident = CSSValueUpperNorwegian;
+ break;
+ case UpperRoman:
+ m_value.ident = CSSValueUpperRoman;
+ break;
+ case Urdu:
+ m_value.ident = CSSValueUrdu;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EListStyleType() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return NoneListStyle;
+ default:
+ return static_cast<EListStyleType>(m_value.ident - CSSValueDisc);
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarginCollapse e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case MCOLLAPSE:
+ m_value.ident = CSSValueCollapse;
+ break;
+ case MSEPARATE:
+ m_value.ident = CSSValueSeparate;
+ break;
+ case MDISCARD:
+ m_value.ident = CSSValueDiscard;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EMarginCollapse() const
+{
+ switch (m_value.ident) {
+ case CSSValueCollapse:
+ return MCOLLAPSE;
+ case CSSValueSeparate:
+ return MSEPARATE;
+ case CSSValueDiscard:
+ return MDISCARD;
+ default:
+ ASSERT_NOT_REACHED();
+ return MCOLLAPSE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarqueeBehavior e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case MNONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case MSCROLL:
+ m_value.ident = CSSValueScroll;
+ break;
+ case MSLIDE:
+ m_value.ident = CSSValueSlide;
+ break;
+ case MALTERNATE:
+ m_value.ident = CSSValueAlternate;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EMarqueeBehavior() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return MNONE;
+ case CSSValueScroll:
+ return MSCROLL;
+ case CSSValueSlide:
+ return MSLIDE;
+ case CSSValueAlternate:
+ return MALTERNATE;
+ default:
+ ASSERT_NOT_REACHED();
+ return MNONE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(RegionOverflow e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case AutoRegionOverflow:
+ m_value.ident = CSSValueAuto;
+ break;
+ case BreakRegionOverflow:
+ m_value.ident = CSSValueBreak;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator RegionOverflow() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return AutoRegionOverflow;
+ case CSSValueBreak:
+ return BreakRegionOverflow;
+ default:
+ ASSERT_NOT_REACHED();
+ return AutoRegionOverflow;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarqueeDirection e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case MFORWARD:
+ m_value.ident = CSSValueForwards;
+ break;
+ case MBACKWARD:
+ m_value.ident = CSSValueBackwards;
+ break;
+ case MAUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case MUP:
+ m_value.ident = CSSValueUp;
+ break;
+ case MDOWN:
+ m_value.ident = CSSValueDown;
+ break;
+ case MLEFT:
+ m_value.ident = CSSValueLeft;
+ break;
+ case MRIGHT:
+ m_value.ident = CSSValueRight;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EMarqueeDirection() const
+{
+ switch (m_value.ident) {
+ case CSSValueForwards:
+ return MFORWARD;
+ case CSSValueBackwards:
+ return MBACKWARD;
+ case CSSValueAuto:
+ return MAUTO;
+ case CSSValueAhead:
+ case CSSValueUp: // We don't support vertical languages, so AHEAD just maps to UP.
+ return MUP;
+ case CSSValueReverse:
+ case CSSValueDown: // REVERSE just maps to DOWN, since we don't do vertical text.
+ return MDOWN;
+ case CSSValueLeft:
+ return MLEFT;
+ case CSSValueRight:
+ return MRIGHT;
+ default:
+ ASSERT_NOT_REACHED();
+ return MAUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMatchNearestMailBlockquoteColor e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BCNORMAL:
+ m_value.ident = CSSValueNormal;
+ break;
+ case MATCH:
+ m_value.ident = CSSValueMatch;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EMatchNearestMailBlockquoteColor() const
+{
+ switch (m_value.ident) {
+ case CSSValueNormal:
+ return BCNORMAL;
+ case CSSValueMatch:
+ return MATCH;
+ default:
+ ASSERT_NOT_REACHED();
+ return BCNORMAL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ENBSPMode e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case NBNORMAL:
+ m_value.ident = CSSValueNormal;
+ break;
+ case SPACE:
+ m_value.ident = CSSValueSpace;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ENBSPMode() const
+{
+ switch (m_value.ident) {
+ case CSSValueSpace:
+ return SPACE;
+ case CSSValueNormal:
+ return NBNORMAL;
+ default:
+ ASSERT_NOT_REACHED();
+ return NBNORMAL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EOverflow e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case OVISIBLE:
+ m_value.ident = CSSValueVisible;
+ break;
+ case OHIDDEN:
+ m_value.ident = CSSValueHidden;
+ break;
+ case OSCROLL:
+ m_value.ident = CSSValueScroll;
+ break;
+ case OAUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case OMARQUEE:
+ m_value.ident = CSSValueWebkitMarquee;
+ break;
+ case OOVERLAY:
+ m_value.ident = CSSValueOverlay;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EOverflow() const
+{
+ switch (m_value.ident) {
+ case CSSValueVisible:
+ return OVISIBLE;
+ case CSSValueHidden:
+ return OHIDDEN;
+ case CSSValueScroll:
+ return OSCROLL;
+ case CSSValueAuto:
+ return OAUTO;
+ case CSSValueWebkitMarquee:
+ return OMARQUEE;
+ case CSSValueOverlay:
+ return OOVERLAY;
+ default:
+ ASSERT_NOT_REACHED();
+ return OVISIBLE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPageBreak e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case PBAUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case PBALWAYS:
+ m_value.ident = CSSValueAlways;
+ break;
+ case PBAVOID:
+ m_value.ident = CSSValueAvoid;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EPageBreak() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return PBAUTO;
+ case CSSValueLeft:
+ case CSSValueRight:
+ case CSSValueAlways:
+ return PBALWAYS; // CSS2.1: "Conforming user agents may map left/right to always."
+ case CSSValueAvoid:
+ return PBAVOID;
+ default:
+ ASSERT_NOT_REACHED();
+ return PBAUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPosition e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case StaticPosition:
+ m_value.ident = CSSValueStatic;
+ break;
+ case RelativePosition:
+ m_value.ident = CSSValueRelative;
+ break;
+ case AbsolutePosition:
+ m_value.ident = CSSValueAbsolute;
+ break;
+ case FixedPosition:
+ m_value.ident = CSSValueFixed;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EPosition() const
+{
+ switch (m_value.ident) {
+ case CSSValueStatic:
+ return StaticPosition;
+ case CSSValueRelative:
+ return RelativePosition;
+ case CSSValueAbsolute:
+ return AbsolutePosition;
+ case CSSValueFixed:
+ return FixedPosition;
+ default:
+ ASSERT_NOT_REACHED();
+ return StaticPosition;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EResize e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case RESIZE_BOTH:
+ m_value.ident = CSSValueBoth;
+ break;
+ case RESIZE_HORIZONTAL:
+ m_value.ident = CSSValueHorizontal;
+ break;
+ case RESIZE_VERTICAL:
+ m_value.ident = CSSValueVertical;
+ break;
+ case RESIZE_NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EResize() const
+{
+ switch (m_value.ident) {
+ case CSSValueBoth:
+ return RESIZE_BOTH;
+ case CSSValueHorizontal:
+ return RESIZE_HORIZONTAL;
+ case CSSValueVertical:
+ return RESIZE_VERTICAL;
+ case CSSValueAuto:
+ ASSERT_NOT_REACHED(); // Depends on settings, thus should be handled by the caller.
+ return RESIZE_NONE;
+ case CSSValueNone:
+ return RESIZE_NONE;
+ default:
+ ASSERT_NOT_REACHED();
+ return RESIZE_NONE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETableLayout e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TAUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case TFIXED:
+ m_value.ident = CSSValueFixed;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETableLayout() const
+{
+ switch (m_value.ident) {
+ case CSSValueFixed:
+ return TFIXED;
+ case CSSValueAuto:
+ return TAUTO;
+ default:
+ ASSERT_NOT_REACHED();
+ return TAUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextAlign e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TAAUTO:
+ m_value.ident = CSSValueWebkitAuto;
+ break;
+ case TASTART:
+ m_value.ident = CSSValueStart;
+ break;
+ case TAEND:
+ m_value.ident = CSSValueEnd;
+ break;
+ case LEFT:
+ m_value.ident = CSSValueLeft;
+ break;
+ case RIGHT:
+ m_value.ident = CSSValueRight;
+ break;
+ case CENTER:
+ m_value.ident = CSSValueCenter;
+ break;
+ case JUSTIFY:
+ m_value.ident = CSSValueJustify;
+ break;
+ case WEBKIT_LEFT:
+ m_value.ident = CSSValueWebkitLeft;
+ break;
+ case WEBKIT_RIGHT:
+ m_value.ident = CSSValueWebkitRight;
+ break;
+ case WEBKIT_CENTER:
+ m_value.ident = CSSValueWebkitCenter;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETextAlign() const
+{
+ switch (m_value.ident) {
+ case CSSValueStart:
+ return TASTART;
+ case CSSValueEnd:
+ return TAEND;
+ default:
+ return static_cast<ETextAlign>(m_value.ident - CSSValueWebkitAuto);
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETextDecoration() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return TDNONE;
+ case CSSValueUnderline:
+ return UNDERLINE;
+ case CSSValueOverline:
+ return OVERLINE;
+ case CSSValueLineThrough:
+ return LINE_THROUGH;
+ case CSSValueBlink:
+ return BLINK;
+ default:
+ ASSERT_NOT_REACHED();
+ return TDNONE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextSecurity e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TSNONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case TSDISC:
+ m_value.ident = CSSValueDisc;
+ break;
+ case TSCIRCLE:
+ m_value.ident = CSSValueCircle;
+ break;
+ case TSSQUARE:
+ m_value.ident = CSSValueSquare;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETextSecurity() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return TSNONE;
+ case CSSValueDisc:
+ return TSDISC;
+ case CSSValueCircle:
+ return TSCIRCLE;
+ case CSSValueSquare:
+ return TSSQUARE;
+ default:
+ ASSERT_NOT_REACHED();
+ return TSNONE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextTransform e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CAPITALIZE:
+ m_value.ident = CSSValueCapitalize;
+ break;
+ case UPPERCASE:
+ m_value.ident = CSSValueUppercase;
+ break;
+ case LOWERCASE:
+ m_value.ident = CSSValueLowercase;
+ break;
+ case TTNONE:
+ m_value.ident = CSSValueNone;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETextTransform() const
+{
+ switch (m_value.ident) {
+ case CSSValueCapitalize:
+ return CAPITALIZE;
+ case CSSValueUppercase:
+ return UPPERCASE;
+ case CSSValueLowercase:
+ return LOWERCASE;
+ case CSSValueNone:
+ return TTNONE;
+ default:
+ ASSERT_NOT_REACHED();
+ return TTNONE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUnicodeBidi e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case UBNormal:
+ m_value.ident = CSSValueNormal;
+ break;
+ case Embed:
+ m_value.ident = CSSValueEmbed;
+ break;
+ case Override:
+ m_value.ident = CSSValueBidiOverride;
+ break;
+ case Isolate:
+ m_value.ident = CSSValueWebkitIsolate;
+ break;
+ case Plaintext:
+ m_value.ident = CSSValueWebkitPlaintext;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EUnicodeBidi() const
+{
+ switch (m_value.ident) {
+ case CSSValueNormal:
+ return UBNormal;
+ case CSSValueEmbed:
+ return Embed;
+ case CSSValueBidiOverride:
+ return Override;
+ case CSSValueWebkitIsolate:
+ return Isolate;
+ case CSSValueWebkitPlaintext:
+ return Plaintext;
+ default:
+ ASSERT_NOT_REACHED();
+ return UBNormal;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUserDrag e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case DRAG_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case DRAG_NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case DRAG_ELEMENT:
+ m_value.ident = CSSValueElement;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EUserDrag() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return DRAG_AUTO;
+ case CSSValueNone:
+ return DRAG_NONE;
+ case CSSValueElement:
+ return DRAG_ELEMENT;
+ default:
+ ASSERT_NOT_REACHED();
+ return DRAG_AUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUserModify e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case READ_ONLY:
+ m_value.ident = CSSValueReadOnly;
+ break;
+ case READ_WRITE:
+ m_value.ident = CSSValueReadWrite;
+ break;
+ case READ_WRITE_PLAINTEXT_ONLY:
+ m_value.ident = CSSValueReadWritePlaintextOnly;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EUserModify() const
+{
+ return static_cast<EUserModify>(m_value.ident - CSSValueReadOnly);
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUserSelect e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case SELECT_NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case SELECT_TEXT:
+ m_value.ident = CSSValueText;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EUserSelect() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return SELECT_TEXT;
+ case CSSValueNone:
+ return SELECT_NONE;
+ case CSSValueText:
+ return SELECT_TEXT;
+ default:
+ ASSERT_NOT_REACHED();
+ return SELECT_TEXT;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EVerticalAlign a)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (a) {
+ case TOP:
+ m_value.ident = CSSValueTop;
+ break;
+ case BOTTOM:
+ m_value.ident = CSSValueBottom;
+ break;
+ case MIDDLE:
+ m_value.ident = CSSValueMiddle;
+ break;
+ case BASELINE:
+ m_value.ident = CSSValueBaseline;
+ break;
+ case TEXT_BOTTOM:
+ m_value.ident = CSSValueTextBottom;
+ break;
+ case TEXT_TOP:
+ m_value.ident = CSSValueTextTop;
+ break;
+ case SUB:
+ m_value.ident = CSSValueSub;
+ break;
+ case SUPER:
+ m_value.ident = CSSValueSuper;
+ break;
+ case BASELINE_MIDDLE:
+ m_value.ident = CSSValueWebkitBaselineMiddle;
+ break;
+ case LENGTH:
+ m_value.ident = CSSValueInvalid;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EVerticalAlign() const
+{
+ switch (m_value.ident) {
+ case CSSValueTop:
+ return TOP;
+ case CSSValueBottom:
+ return BOTTOM;
+ case CSSValueMiddle:
+ return MIDDLE;
+ case CSSValueBaseline:
+ return BASELINE;
+ case CSSValueTextBottom:
+ return TEXT_BOTTOM;
+ case CSSValueTextTop:
+ return TEXT_TOP;
+ case CSSValueSub:
+ return SUB;
+ case CSSValueSuper:
+ return SUPER;
+ case CSSValueWebkitBaselineMiddle:
+ return BASELINE_MIDDLE;
+ default:
+ ASSERT_NOT_REACHED();
+ return TOP;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EVisibility e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case VISIBLE:
+ m_value.ident = CSSValueVisible;
+ break;
+ case HIDDEN:
+ m_value.ident = CSSValueHidden;
+ break;
+ case COLLAPSE:
+ m_value.ident = CSSValueCollapse;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EVisibility() const
+{
+ switch (m_value.ident) {
+ case CSSValueHidden:
+ return HIDDEN;
+ case CSSValueVisible:
+ return VISIBLE;
+ case CSSValueCollapse:
+ return COLLAPSE;
+ default:
+ ASSERT_NOT_REACHED();
+ return VISIBLE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWhiteSpace e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case NORMAL:
+ m_value.ident = CSSValueNormal;
+ break;
+ case PRE:
+ m_value.ident = CSSValuePre;
+ break;
+ case PRE_WRAP:
+ m_value.ident = CSSValuePreWrap;
+ break;
+ case PRE_LINE:
+ m_value.ident = CSSValuePreLine;
+ break;
+ case NOWRAP:
+ m_value.ident = CSSValueNowrap;
+ break;
+ case KHTML_NOWRAP:
+ m_value.ident = CSSValueWebkitNowrap;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EWhiteSpace() const
+{
+ switch (m_value.ident) {
+ case CSSValueWebkitNowrap:
+ return KHTML_NOWRAP;
+ case CSSValueNowrap:
+ return NOWRAP;
+ case CSSValuePre:
+ return PRE;
+ case CSSValuePreWrap:
+ return PRE_WRAP;
+ case CSSValuePreLine:
+ return PRE_LINE;
+ case CSSValueNormal:
+ return NORMAL;
+ default:
+ ASSERT_NOT_REACHED();
+ return NORMAL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWordBreak e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case NormalWordBreak:
+ m_value.ident = CSSValueNormal;
+ break;
+ case BreakAllWordBreak:
+ m_value.ident = CSSValueBreakAll;
+ break;
+ case BreakWordBreak:
+ m_value.ident = CSSValueBreakWord;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EWordBreak() const
+{
+ switch (m_value.ident) {
+ case CSSValueBreakAll:
+ return BreakAllWordBreak;
+ case CSSValueBreakWord:
+ return BreakWordBreak;
+ case CSSValueNormal:
+ return NormalWordBreak;
+ default:
+ ASSERT_NOT_REACHED();
+ return NormalWordBreak;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EWordWrap e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case NormalWordWrap:
+ m_value.ident = CSSValueNormal;
+ break;
+ case BreakWordWrap:
+ m_value.ident = CSSValueBreakWord;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EWordWrap() const
+{
+ switch (m_value.ident) {
+ case CSSValueBreakWord:
+ return BreakWordWrap;
+ case CSSValueNormal:
+ return NormalWordWrap;
+ default:
+ ASSERT_NOT_REACHED();
+ return NormalWordWrap;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextDirection e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case LTR:
+ m_value.ident = CSSValueLtr;
+ break;
+ case RTL:
+ m_value.ident = CSSValueRtl;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextDirection() const
+{
+ switch (m_value.ident) {
+ case CSSValueLtr:
+ return LTR;
+ case CSSValueRtl:
+ return RTL;
+ default:
+ ASSERT_NOT_REACHED();
+ return LTR;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WritingMode e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TopToBottomWritingMode:
+ m_value.ident = CSSValueHorizontalTb;
+ break;
+ case RightToLeftWritingMode:
+ m_value.ident = CSSValueVerticalRl;
+ break;
+ case LeftToRightWritingMode:
+ m_value.ident = CSSValueVerticalLr;
+ break;
+ case BottomToTopWritingMode:
+ m_value.ident = CSSValueHorizontalBt;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator WritingMode() const
+{
+ switch (m_value.ident) {
+ case CSSValueHorizontalTb:
+ return TopToBottomWritingMode;
+ case CSSValueVerticalRl:
+ return RightToLeftWritingMode;
+ case CSSValueVerticalLr:
+ return LeftToRightWritingMode;
+ case CSSValueHorizontalBt:
+ return BottomToTopWritingMode;
+ default:
+ ASSERT_NOT_REACHED();
+ return TopToBottomWritingMode;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextCombine e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TextCombineNone:
+ m_value.ident = CSSValueNone;
+ break;
+ case TextCombineHorizontal:
+ m_value.ident = CSSValueHorizontal;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextCombine() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return TextCombineNone;
+ case CSSValueHorizontal:
+ return TextCombineHorizontal;
+ default:
+ ASSERT_NOT_REACHED();
+ return TextCombineNone;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextEmphasisPosition position)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (position) {
+ case TextEmphasisPositionOver:
+ m_value.ident = CSSValueOver;
+ break;
+ case TextEmphasisPositionUnder:
+ m_value.ident = CSSValueUnder;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextEmphasisPosition() const
+{
+ switch (m_value.ident) {
+ case CSSValueOver:
+ return TextEmphasisPositionOver;
+ case CSSValueUnder:
+ return TextEmphasisPositionUnder;
+ default:
+ ASSERT_NOT_REACHED();
+ return TextEmphasisPositionOver;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextOverflow overflow)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (overflow) {
+ case TextOverflowClip:
+ m_value.ident = CSSValueClip;
+ break;
+ case TextOverflowEllipsis:
+ m_value.ident = CSSValueEllipsis;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextOverflow() const
+{
+ switch (m_value.ident) {
+ case CSSValueClip:
+ return TextOverflowClip;
+ case CSSValueEllipsis:
+ return TextOverflowEllipsis;
+ default:
+ ASSERT_NOT_REACHED();
+ return TextOverflowClip;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextEmphasisFill fill)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (fill) {
+ case TextEmphasisFillFilled:
+ m_value.ident = CSSValueFilled;
+ break;
+ case TextEmphasisFillOpen:
+ m_value.ident = CSSValueOpen;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextEmphasisFill() const
+{
+ switch (m_value.ident) {
+ case CSSValueFilled:
+ return TextEmphasisFillFilled;
+ case CSSValueOpen:
+ return TextEmphasisFillOpen;
+ default:
+ ASSERT_NOT_REACHED();
+ return TextEmphasisFillFilled;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextEmphasisMark mark)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (mark) {
+ case TextEmphasisMarkDot:
+ m_value.ident = CSSValueDot;
+ break;
+ case TextEmphasisMarkCircle:
+ m_value.ident = CSSValueCircle;
+ break;
+ case TextEmphasisMarkDoubleCircle:
+ m_value.ident = CSSValueDoubleCircle;
+ break;
+ case TextEmphasisMarkTriangle:
+ m_value.ident = CSSValueTriangle;
+ break;
+ case TextEmphasisMarkSesame:
+ m_value.ident = CSSValueSesame;
+ break;
+ case TextEmphasisMarkNone:
+ case TextEmphasisMarkAuto:
+ case TextEmphasisMarkCustom:
+ ASSERT_NOT_REACHED();
+ m_value.ident = CSSValueNone;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextEmphasisMark() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return TextEmphasisMarkNone;
+ case CSSValueDot:
+ return TextEmphasisMarkDot;
+ case CSSValueCircle:
+ return TextEmphasisMarkCircle;
+ case CSSValueDoubleCircle:
+ return TextEmphasisMarkDoubleCircle;
+ case CSSValueTriangle:
+ return TextEmphasisMarkTriangle;
+ case CSSValueSesame:
+ return TextEmphasisMarkSesame;
+ default:
+ ASSERT_NOT_REACHED();
+ return TextEmphasisMarkNone;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextOrientation e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TextOrientationVerticalRight:
+ m_value.ident = CSSValueVerticalRight;
+ break;
+ case TextOrientationUpright:
+ m_value.ident = CSSValueUpright;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextOrientation() const
+{
+ switch (m_value.ident) {
+ case CSSValueVerticalRight:
+ return TextOrientationVerticalRight;
+ case CSSValueUpright:
+ return TextOrientationUpright;
+ default:
+ ASSERT_NOT_REACHED();
+ return TextOrientationVerticalRight;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPointerEvents e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case PE_NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case PE_STROKE:
+ m_value.ident = CSSValueStroke;
+ break;
+ case PE_FILL:
+ m_value.ident = CSSValueFill;
+ break;
+ case PE_PAINTED:
+ m_value.ident = CSSValuePainted;
+ break;
+ case PE_VISIBLE:
+ m_value.ident = CSSValueVisible;
+ break;
+ case PE_VISIBLE_STROKE:
+ m_value.ident = CSSValueVisiblestroke;
+ break;
+ case PE_VISIBLE_FILL:
+ m_value.ident = CSSValueVisiblefill;
+ break;
+ case PE_VISIBLE_PAINTED:
+ m_value.ident = CSSValueVisiblepainted;
+ break;
+ case PE_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case PE_ALL:
+ m_value.ident = CSSValueAll;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EPointerEvents() const
+{
+ switch (m_value.ident) {
+ case CSSValueAll:
+ return PE_ALL;
+ case CSSValueAuto:
+ return PE_AUTO;
+ case CSSValueNone:
+ return PE_NONE;
+ case CSSValueVisiblepainted:
+ return PE_VISIBLE_PAINTED;
+ case CSSValueVisiblefill:
+ return PE_VISIBLE_FILL;
+ case CSSValueVisiblestroke:
+ return PE_VISIBLE_STROKE;
+ case CSSValueVisible:
+ return PE_VISIBLE;
+ case CSSValuePainted:
+ return PE_PAINTED;
+ case CSSValueFill:
+ return PE_FILL;
+ case CSSValueStroke:
+ return PE_STROKE;
+ default:
+ ASSERT_NOT_REACHED();
+ return PE_ALL;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontSmoothingMode smoothing)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (smoothing) {
+ case AutoSmoothing:
+ m_value.ident = CSSValueAuto;
+ return;
+ case NoSmoothing:
+ m_value.ident = CSSValueNone;
+ return;
+ case Antialiased:
+ m_value.ident = CSSValueAntialiased;
+ return;
+ case SubpixelAntialiased:
+ m_value.ident = CSSValueSubpixelAntialiased;
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+ m_value.ident = CSSValueAuto;
+}
+
+template<> inline CSSPrimitiveValue::operator FontSmoothingMode() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return AutoSmoothing;
+ case CSSValueNone:
+ return NoSmoothing;
+ case CSSValueAntialiased:
+ return Antialiased;
+ case CSSValueSubpixelAntialiased:
+ return SubpixelAntialiased;
+ }
+
+ ASSERT_NOT_REACHED();
+ return AutoSmoothing;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontWeight weight)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (weight) {
+ case FontWeight900:
+ m_value.ident = CSSValue900;
+ return;
+ case FontWeight800:
+ m_value.ident = CSSValue800;
+ return;
+ case FontWeight700:
+ m_value.ident = CSSValue700;
+ return;
+ case FontWeight600:
+ m_value.ident = CSSValue600;
+ return;
+ case FontWeight500:
+ m_value.ident = CSSValue500;
+ return;
+ case FontWeight400:
+ m_value.ident = CSSValue400;
+ return;
+ case FontWeight300:
+ m_value.ident = CSSValue300;
+ return;
+ case FontWeight200:
+ m_value.ident = CSSValue200;
+ return;
+ case FontWeight100:
+ m_value.ident = CSSValue100;
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+ m_value.ident = CSSValueNormal;
+}
+
+template<> inline CSSPrimitiveValue::operator FontWeight() const
+{
+ switch (m_value.ident) {
+ case CSSValueBold:
+ return FontWeightBold;
+ case CSSValueNormal:
+ return FontWeightNormal;
+ case CSSValue900:
+ return FontWeight900;
+ case CSSValue800:
+ return FontWeight800;
+ case CSSValue700:
+ return FontWeight700;
+ case CSSValue600:
+ return FontWeight600;
+ case CSSValue500:
+ return FontWeight500;
+ case CSSValue400:
+ return FontWeight400;
+ case CSSValue300:
+ return FontWeight300;
+ case CSSValue200:
+ return FontWeight200;
+ case CSSValue100:
+ return FontWeight100;
+ }
+
+ ASSERT_NOT_REACHED();
+ return FontWeightNormal;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontItalic italic)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (italic) {
+ case FontItalicOff:
+ m_value.ident = CSSValueNormal;
+ return;
+ case FontItalicOn:
+ m_value.ident = CSSValueItalic;
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+ m_value.ident = CSSValueNormal;
+}
+
+template<> inline CSSPrimitiveValue::operator FontItalic() const
+{
+ switch (m_value.ident) {
+ case CSSValueOblique:
+ // FIXME: oblique is the same as italic for the moment...
+ case CSSValueItalic:
+ return FontItalicOn;
+ case CSSValueNormal:
+ return FontItalicOff;
+ }
+ ASSERT_NOT_REACHED();
+ return FontItalicOff;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontSmallCaps smallCaps)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (smallCaps) {
+ case FontSmallCapsOff:
+ m_value.ident = CSSValueNormal;
+ return;
+ case FontSmallCapsOn:
+ m_value.ident = CSSValueSmallCaps;
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+ m_value.ident = CSSValueNormal;
+}
+
+template<> inline CSSPrimitiveValue::operator FontSmallCaps() const
+{
+ switch (m_value.ident) {
+ case CSSValueSmallCaps:
+ return FontSmallCapsOn;
+ case CSSValueNormal:
+ return FontSmallCapsOff;
+ }
+ ASSERT_NOT_REACHED();
+ return FontSmallCapsOff;
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextRenderingMode e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case AutoTextRendering:
+ m_value.ident = CSSValueAuto;
+ break;
+ case OptimizeSpeed:
+ m_value.ident = CSSValueOptimizespeed;
+ break;
+ case OptimizeLegibility:
+ m_value.ident = CSSValueOptimizelegibility;
+ break;
+ case GeometricPrecision:
+ m_value.ident = CSSValueGeometricprecision;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator TextRenderingMode() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return AutoTextRendering;
+ case CSSValueOptimizespeed:
+ return OptimizeSpeed;
+ case CSSValueOptimizelegibility:
+ return OptimizeLegibility;
+ case CSSValueGeometricprecision:
+ return GeometricPrecision;
+ default:
+ ASSERT_NOT_REACHED();
+ return AutoTextRendering;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColorSpace space)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (space) {
+ case ColorSpaceDeviceRGB:
+ m_value.ident = CSSValueDefault;
+ break;
+ case ColorSpaceSRGB:
+ m_value.ident = CSSValueSrgb;
+ break;
+ case ColorSpaceLinearRGB:
+ // CSS color correction does not support linearRGB yet.
+ ASSERT_NOT_REACHED();
+ m_value.ident = CSSValueDefault;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ColorSpace() const
+{
+ switch (m_value.ident) {
+ case CSSValueDefault:
+ return ColorSpaceDeviceRGB;
+ case CSSValueSrgb:
+ return ColorSpaceSRGB;
+ default:
+ ASSERT_NOT_REACHED();
+ return ColorSpaceDeviceRGB;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Hyphens hyphens)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (hyphens) {
+ case HyphensNone:
+ m_value.ident = CSSValueNone;
+ break;
+ case HyphensManual:
+ m_value.ident = CSSValueManual;
+ break;
+ case HyphensAuto:
+ m_value.ident = CSSValueAuto;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator Hyphens() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return HyphensNone;
+ case CSSValueManual:
+ return HyphensManual;
+ case CSSValueAuto:
+ return HyphensAuto;
+ default:
+ ASSERT_NOT_REACHED();
+ return HyphensAuto;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineGridSnap gridSnap)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (gridSnap) {
+ case LineGridSnapNone:
+ m_value.ident = CSSValueNone;
+ break;
+ case LineGridSnapBaseline:
+ m_value.ident = CSSValueBaseline;
+ break;
+ case LineGridSnapBounds:
+ m_value.ident = CSSValueBounds;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator LineGridSnap() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return LineGridSnapNone;
+ case CSSValueBaseline:
+ return LineGridSnapBaseline;
+ case CSSValueBounds:
+ return LineGridSnapBounds;
+ default:
+ ASSERT_NOT_REACHED();
+ return LineGridSnapNone;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ESpeak e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case SpeakNone:
+ m_value.ident = CSSValueNone;
+ break;
+ case SpeakNormal:
+ m_value.ident = CSSValueNormal;
+ break;
+ case SpeakSpellOut:
+ m_value.ident = CSSValueSpellOut;
+ break;
+ case SpeakDigits:
+ m_value.ident = CSSValueDigits;
+ break;
+ case SpeakLiteralPunctuation:
+ m_value.ident = CSSValueLiteralPunctuation;
+ break;
+ case SpeakNoPunctuation:
+ m_value.ident = CSSValueNoPunctuation;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator Order() const
+{
+ switch (m_value.ident) {
+ case CSSValueLogical:
+ return LogicalOrder;
+ case CSSValueVisual:
+ return VisualOrder;
+ default:
+ ASSERT_NOT_REACHED();
+ return LogicalOrder;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(Order e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case LogicalOrder:
+ m_value.ident = CSSValueLogical;
+ break;
+ case VisualOrder:
+ m_value.ident = CSSValueVisual;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ESpeak() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return SpeakNone;
+ case CSSValueNormal:
+ return SpeakNormal;
+ case CSSValueSpellOut:
+ return SpeakSpellOut;
+ case CSSValueDigits:
+ return SpeakDigits;
+ case CSSValueLiteralPunctuation:
+ return SpeakLiteralPunctuation;
+ case CSSValueNoPunctuation:
+ return SpeakNoPunctuation;
+ default:
+ ASSERT_NOT_REACHED();
+ return SpeakNormal;
+ }
+}
+
+#if ENABLE(CSS_SHADERS)
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CustomFilterOperation::MeshBoxType meshBoxType)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (meshBoxType) {
+ case CustomFilterOperation::FILTER_BOX:
+ m_value.ident = CSSValueFilterBox;
+ break;
+ case CustomFilterOperation::BORDER_BOX:
+ m_value.ident = CSSValueBorderBox;
+ break;
+ case CustomFilterOperation::PADDING_BOX:
+ m_value.ident = CSSValuePaddingBox;
+ break;
+ case CustomFilterOperation::CONTENT_BOX:
+ m_value.ident = CSSValueContentBox;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator CustomFilterOperation::MeshBoxType() const
+{
+ switch (m_value.ident) {
+ case CSSValueFilterBox:
+ return CustomFilterOperation::FILTER_BOX;
+ case CSSValueBorderBox:
+ return CustomFilterOperation::BORDER_BOX;
+ case CSSValuePaddingBox:
+ return CustomFilterOperation::PADDING_BOX;
+ case CSSValueContentBox:
+ return CustomFilterOperation::CONTENT_BOX;
+ default:
+ ASSERT_NOT_REACHED();
+ return CustomFilterOperation::FILTER_BOX;
+ }
+}
+#endif // ENABLE(CSS_SHADERS)
+
+#if ENABLE(SVG)
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineCap e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case ButtCap:
+ m_value.ident = CSSValueButt;
+ break;
+ case RoundCap:
+ m_value.ident = CSSValueRound;
+ break;
+ case SquareCap:
+ m_value.ident = CSSValueSquare;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator LineCap() const
+{
+ switch (m_value.ident) {
+ case CSSValueButt:
+ return ButtCap;
+ case CSSValueRound:
+ return RoundCap;
+ case CSSValueSquare:
+ return SquareCap;
+ default:
+ ASSERT_NOT_REACHED();
+ return ButtCap;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineJoin e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case MiterJoin:
+ m_value.ident = CSSValueMiter;
+ break;
+ case RoundJoin:
+ m_value.ident = CSSValueRound;
+ break;
+ case BevelJoin:
+ m_value.ident = CSSValueBevel;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator LineJoin() const
+{
+ switch (m_value.ident) {
+ case CSSValueMiter:
+ return MiterJoin;
+ case CSSValueRound:
+ return RoundJoin;
+ case CSSValueBevel:
+ return BevelJoin;
+ default:
+ ASSERT_NOT_REACHED();
+ return MiterJoin;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WindRule e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case RULE_NONZERO:
+ m_value.ident = CSSValueNonzero;
+ break;
+ case RULE_EVENODD:
+ m_value.ident = CSSValueEvenodd;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator WindRule() const
+{
+ switch (m_value.ident) {
+ case CSSValueNonzero:
+ return RULE_NONZERO;
+ case CSSValueEvenodd:
+ return RULE_EVENODD;
+ default:
+ ASSERT_NOT_REACHED();
+ return RULE_NONZERO;
+ }
+}
+
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EAlignmentBaseline e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case AB_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case AB_BASELINE:
+ m_value.ident = CSSValueBaseline;
+ break;
+ case AB_BEFORE_EDGE:
+ m_value.ident = CSSValueBeforeEdge;
+ break;
+ case AB_TEXT_BEFORE_EDGE:
+ m_value.ident = CSSValueTextBeforeEdge;
+ break;
+ case AB_MIDDLE:
+ m_value.ident = CSSValueMiddle;
+ break;
+ case AB_CENTRAL:
+ m_value.ident = CSSValueCentral;
+ break;
+ case AB_AFTER_EDGE:
+ m_value.ident = CSSValueAfterEdge;
+ break;
+ case AB_TEXT_AFTER_EDGE:
+ m_value.ident = CSSValueTextAfterEdge;
+ break;
+ case AB_IDEOGRAPHIC:
+ m_value.ident = CSSValueIdeographic;
+ break;
+ case AB_ALPHABETIC:
+ m_value.ident = CSSValueAlphabetic;
+ break;
+ case AB_HANGING:
+ m_value.ident = CSSValueHanging;
+ break;
+ case AB_MATHEMATICAL:
+ m_value.ident = CSSValueMathematical;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EAlignmentBaseline() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return AB_AUTO;
+ case CSSValueBaseline:
+ return AB_BASELINE;
+ case CSSValueBeforeEdge:
+ return AB_BEFORE_EDGE;
+ case CSSValueTextBeforeEdge:
+ return AB_TEXT_BEFORE_EDGE;
+ case CSSValueMiddle:
+ return AB_MIDDLE;
+ case CSSValueCentral:
+ return AB_CENTRAL;
+ case CSSValueAfterEdge:
+ return AB_AFTER_EDGE;
+ case CSSValueTextAfterEdge:
+ return AB_TEXT_AFTER_EDGE;
+ case CSSValueIdeographic:
+ return AB_IDEOGRAPHIC;
+ case CSSValueAlphabetic:
+ return AB_ALPHABETIC;
+ case CSSValueHanging:
+ return AB_HANGING;
+ case CSSValueMathematical:
+ return AB_MATHEMATICAL;
+ default:
+ ASSERT_NOT_REACHED();
+ return AB_AUTO;
+ }
+}
+
+#endif
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBorderCollapse e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BSEPARATE:
+ m_value.ident = CSSValueSeparate;
+ break;
+ case BCOLLAPSE:
+ m_value.ident = CSSValueCollapse;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBorderCollapse() const
+{
+ switch (m_value.ident) {
+ case CSSValueSeparate:
+ return BSEPARATE;
+ case CSSValueCollapse:
+ return BCOLLAPSE;
+ default:
+ ASSERT_NOT_REACHED();
+ return BSEPARATE;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBorderFit e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case BorderFitBorder:
+ m_value.ident = CSSValueBorder;
+ break;
+ case BorderFitLines:
+ m_value.ident = CSSValueLines;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EBorderFit() const
+{
+ switch (m_value.ident) {
+ case CSSValueBorder:
+ return BorderFitBorder;
+ case CSSValueLines:
+ return BorderFitLines;
+ default:
+ ASSERT_NOT_REACHED();
+ return BorderFitLines;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EImageRendering e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case ImageRenderingAuto:
+ m_value.ident = CSSValueAuto;
+ break;
+ case ImageRenderingOptimizeSpeed:
+ m_value.ident = CSSValueOptimizespeed;
+ break;
+ case ImageRenderingOptimizeQuality:
+ m_value.ident = CSSValueOptimizequality;
+ break;
+ case ImageRenderingOptimizeContrast:
+ m_value.ident = CSSValueWebkitOptimizeContrast;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EImageRendering() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return ImageRenderingAuto;
+ case CSSValueOptimizespeed:
+ return ImageRenderingOptimizeSpeed;
+ case CSSValueOptimizequality:
+ return ImageRenderingOptimizeQuality;
+ case CSSValueWebkitOptimizeContrast:
+ return ImageRenderingOptimizeContrast;
+ default:
+ ASSERT_NOT_REACHED();
+ return ImageRenderingAuto;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETransformStyle3D e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TransformStyle3DFlat:
+ m_value.ident = CSSValueFlat;
+ break;
+ case TransformStyle3DPreserve3D:
+ m_value.ident = CSSValuePreserve3d;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETransformStyle3D() const
+{
+ switch (m_value.ident) {
+ case CSSValueFlat:
+ return TransformStyle3DFlat;
+ case CSSValuePreserve3d:
+ return TransformStyle3DPreserve3D;
+ default:
+ ASSERT_NOT_REACHED();
+ return TransformStyle3DFlat;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColumnAxis e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case HorizontalColumnAxis:
+ m_value.ident = CSSValueHorizontal;
+ break;
+ case VerticalColumnAxis:
+ m_value.ident = CSSValueVertical;
+ break;
+ case AutoColumnAxis:
+ m_value.ident = CSSValueAuto;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ColumnAxis() const
+{
+ switch (m_value.ident) {
+ case CSSValueHorizontal:
+ return HorizontalColumnAxis;
+ case CSSValueVertical:
+ return VerticalColumnAxis;
+ case CSSValueAuto:
+ return AutoColumnAxis;
+ default:
+ ASSERT_NOT_REACHED();
+ return AutoColumnAxis;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WrapFlow wrapFlow)
+: CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (wrapFlow) {
+ case WrapFlowAuto:
+ m_value.ident = CSSValueAuto;
+ break;
+ case WrapFlowBoth:
+ m_value.ident = CSSValueBoth;
+ break;
+ case WrapFlowLeft:
+ m_value.ident = CSSValueLeft;
+ break;
+ case WrapFlowRight:
+ m_value.ident = CSSValueRight;
+ break;
+ case WrapFlowMaximum:
+ m_value.ident = CSSValueMaximum;
+ break;
+ case WrapFlowClear:
+ m_value.ident = CSSValueClear;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator WrapFlow() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return WrapFlowAuto;
+ case CSSValueBoth:
+ return WrapFlowBoth;
+ case CSSValueLeft:
+ return WrapFlowLeft;
+ case CSSValueRight:
+ return WrapFlowRight;
+ case CSSValueMaximum:
+ return WrapFlowMaximum;
+ case CSSValueClear:
+ return WrapFlowClear;
+ default:
+ ASSERT_NOT_REACHED();
+ return WrapFlowAuto;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WrapThrough wrapThrough)
+: CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (wrapThrough) {
+ case WrapThroughWrap:
+ m_value.ident = CSSValueWrap;
+ break;
+ case WrapThroughNone:
+ m_value.ident = CSSValueNone;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator WrapThrough() const
+{
+ switch (m_value.ident) {
+ case CSSValueWrap:
+ return WrapThroughWrap;
+ case CSSValueNone:
+ return WrapThroughNone;
+ default:
+ ASSERT_NOT_REACHED();
+ return WrapThroughWrap;
+ }
+}
+
+#if ENABLE(SVG)
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EColorInterpolation e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CI_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case CI_SRGB:
+ m_value.ident = CSSValueSrgb;
+ break;
+ case CI_LINEARRGB:
+ m_value.ident = CSSValueLinearrgb;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EColorInterpolation() const
+{
+ switch (m_value.ident) {
+ case CSSValueSrgb:
+ return CI_SRGB;
+ case CSSValueLinearrgb:
+ return CI_LINEARRGB;
+ case CSSValueAuto:
+ return CI_AUTO;
+ default:
+ ASSERT_NOT_REACHED();
+ return CI_AUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EColorRendering e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case CR_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case CR_OPTIMIZESPEED:
+ m_value.ident = CSSValueOptimizespeed;
+ break;
+ case CR_OPTIMIZEQUALITY:
+ m_value.ident = CSSValueOptimizequality;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EColorRendering() const
+{
+ switch (m_value.ident) {
+ case CSSValueOptimizespeed:
+ return CR_OPTIMIZESPEED;
+ case CSSValueOptimizequality:
+ return CR_OPTIMIZEQUALITY;
+ case CSSValueAuto:
+ return CR_AUTO;
+ default:
+ ASSERT_NOT_REACHED();
+ return CR_AUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EDominantBaseline e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case DB_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case DB_USE_SCRIPT:
+ m_value.ident = CSSValueUseScript;
+ break;
+ case DB_NO_CHANGE:
+ m_value.ident = CSSValueNoChange;
+ break;
+ case DB_RESET_SIZE:
+ m_value.ident = CSSValueResetSize;
+ break;
+ case DB_CENTRAL:
+ m_value.ident = CSSValueCentral;
+ break;
+ case DB_MIDDLE:
+ m_value.ident = CSSValueMiddle;
+ break;
+ case DB_TEXT_BEFORE_EDGE:
+ m_value.ident = CSSValueTextBeforeEdge;
+ break;
+ case DB_TEXT_AFTER_EDGE:
+ m_value.ident = CSSValueTextAfterEdge;
+ break;
+ case DB_IDEOGRAPHIC:
+ m_value.ident = CSSValueIdeographic;
+ break;
+ case DB_ALPHABETIC:
+ m_value.ident = CSSValueAlphabetic;
+ break;
+ case DB_HANGING:
+ m_value.ident = CSSValueHanging;
+ break;
+ case DB_MATHEMATICAL:
+ m_value.ident = CSSValueMathematical;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EDominantBaseline() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return DB_AUTO;
+ case CSSValueUseScript:
+ return DB_USE_SCRIPT;
+ case CSSValueNoChange:
+ return DB_NO_CHANGE;
+ case CSSValueResetSize:
+ return DB_RESET_SIZE;
+ case CSSValueIdeographic:
+ return DB_IDEOGRAPHIC;
+ case CSSValueAlphabetic:
+ return DB_ALPHABETIC;
+ case CSSValueHanging:
+ return DB_HANGING;
+ case CSSValueMathematical:
+ return DB_MATHEMATICAL;
+ case CSSValueCentral:
+ return DB_CENTRAL;
+ case CSSValueMiddle:
+ return DB_MIDDLE;
+ case CSSValueTextAfterEdge:
+ return DB_TEXT_AFTER_EDGE;
+ case CSSValueTextBeforeEdge:
+ return DB_TEXT_BEFORE_EDGE;
+ default:
+ ASSERT_NOT_REACHED();
+ return DB_AUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EShapeRendering e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case SR_AUTO:
+ m_value.ident = CSSValueAuto;
+ break;
+ case SR_OPTIMIZESPEED:
+ m_value.ident = CSSValueOptimizespeed;
+ break;
+ case SR_CRISPEDGES:
+ m_value.ident = CSSValueCrispedges;
+ break;
+ case SR_GEOMETRICPRECISION:
+ m_value.ident = CSSValueGeometricprecision;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EShapeRendering() const
+{
+ switch (m_value.ident) {
+ case CSSValueAuto:
+ return SR_AUTO;
+ case CSSValueOptimizespeed:
+ return SR_OPTIMIZESPEED;
+ case CSSValueCrispedges:
+ return SR_CRISPEDGES;
+ case CSSValueGeometricprecision:
+ return SR_GEOMETRICPRECISION;
+ default:
+ ASSERT_NOT_REACHED();
+ return SR_AUTO;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextAnchor e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case TA_START:
+ m_value.ident = CSSValueStart;
+ break;
+ case TA_MIDDLE:
+ m_value.ident = CSSValueMiddle;
+ break;
+ case TA_END:
+ m_value.ident = CSSValueEnd;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator ETextAnchor() const
+{
+ switch (m_value.ident) {
+ case CSSValueStart:
+ return TA_START;
+ case CSSValueMiddle:
+ return TA_MIDDLE;
+ case CSSValueEnd:
+ return TA_END;
+ default:
+ ASSERT_NOT_REACHED();
+ return TA_START;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(SVGWritingMode e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case WM_LRTB:
+ m_value.ident = CSSValueLrTb;
+ break;
+ case WM_LR:
+ m_value.ident = CSSValueLr;
+ break;
+ case WM_RLTB:
+ m_value.ident = CSSValueRlTb;
+ break;
+ case WM_RL:
+ m_value.ident = CSSValueRl;
+ break;
+ case WM_TBRL:
+ m_value.ident = CSSValueTbRl;
+ break;
+ case WM_TB:
+ m_value.ident = CSSValueTb;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator SVGWritingMode() const
+{
+ switch (m_value.ident) {
+ case CSSValueLrTb:
+ return WM_LRTB;
+ case CSSValueLr:
+ return WM_LR;
+ case CSSValueRlTb:
+ return WM_RLTB;
+ case CSSValueRl:
+ return WM_RL;
+ case CSSValueTbRl:
+ return WM_TBRL;
+ case CSSValueTb:
+ return WM_TB;
+ default:
+ ASSERT_NOT_REACHED();
+ return WM_LRTB;
+ }
+}
+
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EVectorEffect e)
+ : CSSValue(PrimitiveClass)
+{
+ m_primitiveUnitType = CSS_IDENT;
+ switch (e) {
+ case VE_NONE:
+ m_value.ident = CSSValueNone;
+ break;
+ case VE_NON_SCALING_STROKE:
+ m_value.ident = CSSValueNonScalingStroke;
+ break;
+ }
+}
+
+template<> inline CSSPrimitiveValue::operator EVectorEffect() const
+{
+ switch (m_value.ident) {
+ case CSSValueNone:
+ return VE_NONE;
+ case CSSValueNonScalingStroke:
+ return VE_NON_SCALING_STROKE;
+ default:
+ ASSERT_NOT_REACHED();
+ return VE_NONE;
+ }
+}
+
+#endif // ENABLE(SVG)
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSProperty.cpp b/Source/WebCore/css/CSSProperty.cpp
new file mode 100644
index 000000000..3bbf03227
--- /dev/null
+++ b/Source/WebCore/css/CSSProperty.cpp
@@ -0,0 +1,674 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 "CSSProperty.h"
+
+#include "CSSPropertyNames.h"
+#include "PlatformString.h"
+#include "RenderStyleConstants.h"
+
+namespace WebCore {
+
+String CSSProperty::cssText() const
+{
+ return String(getPropertyName(static_cast<CSSPropertyID>(id()))) + ": " + m_value->cssText() + (isImportant() ? " !important" : "") + "; ";
+}
+
+enum LogicalBoxSide { BeforeSide, EndSide, AfterSide, StartSide };
+enum PhysicalBoxSide { TopSide, RightSide, BottomSide, LeftSide };
+
+static int resolveToPhysicalProperty(TextDirection direction, WritingMode writingMode, LogicalBoxSide logicalSide, const int* properties)
+{
+ if (direction == LTR) {
+ if (writingMode == TopToBottomWritingMode) {
+ // The common case. The logical and physical box sides match.
+ // Left = Start, Right = End, Before = Top, After = Bottom
+ return properties[logicalSide];
+ }
+
+ if (writingMode == BottomToTopWritingMode) {
+ // Start = Left, End = Right, Before = Bottom, After = Top.
+ switch (logicalSide) {
+ case StartSide:
+ return properties[LeftSide];
+ case EndSide:
+ return properties[RightSide];
+ case BeforeSide:
+ return properties[BottomSide];
+ default:
+ return properties[TopSide];
+ }
+ }
+
+ if (writingMode == LeftToRightWritingMode) {
+ // Start = Top, End = Bottom, Before = Left, After = Right.
+ switch (logicalSide) {
+ case StartSide:
+ return properties[TopSide];
+ case EndSide:
+ return properties[BottomSide];
+ case BeforeSide:
+ return properties[LeftSide];
+ default:
+ return properties[RightSide];
+ }
+ }
+
+ // Start = Top, End = Bottom, Before = Right, After = Left
+ switch (logicalSide) {
+ case StartSide:
+ return properties[TopSide];
+ case EndSide:
+ return properties[BottomSide];
+ case BeforeSide:
+ return properties[RightSide];
+ default:
+ return properties[LeftSide];
+ }
+ }
+
+ if (writingMode == TopToBottomWritingMode) {
+ // Start = Right, End = Left, Before = Top, After = Bottom
+ switch (logicalSide) {
+ case StartSide:
+ return properties[RightSide];
+ case EndSide:
+ return properties[LeftSide];
+ case BeforeSide:
+ return properties[TopSide];
+ default:
+ return properties[BottomSide];
+ }
+ }
+
+ if (writingMode == BottomToTopWritingMode) {
+ // Start = Right, End = Left, Before = Bottom, After = Top
+ switch (logicalSide) {
+ case StartSide:
+ return properties[RightSide];
+ case EndSide:
+ return properties[LeftSide];
+ case BeforeSide:
+ return properties[BottomSide];
+ default:
+ return properties[TopSide];
+ }
+ }
+
+ if (writingMode == LeftToRightWritingMode) {
+ // Start = Bottom, End = Top, Before = Left, After = Right
+ switch (logicalSide) {
+ case StartSide:
+ return properties[BottomSide];
+ case EndSide:
+ return properties[TopSide];
+ case BeforeSide:
+ return properties[LeftSide];
+ default:
+ return properties[RightSide];
+ }
+ }
+
+ // Start = Bottom, End = Top, Before = Right, After = Left
+ switch (logicalSide) {
+ case StartSide:
+ return properties[BottomSide];
+ case EndSide:
+ return properties[TopSide];
+ case BeforeSide:
+ return properties[RightSide];
+ default:
+ return properties[LeftSide];
+ }
+}
+
+enum LogicalExtent { LogicalWidth, LogicalHeight };
+
+static int resolveToPhysicalProperty(WritingMode writingMode, LogicalExtent logicalSide, const int* properties)
+{
+ if (writingMode == TopToBottomWritingMode || writingMode == BottomToTopWritingMode)
+ return properties[logicalSide];
+ return logicalSide == LogicalWidth ? properties[1] : properties[0];
+}
+
+int CSSProperty::resolveDirectionAwareProperty(int propertyID, TextDirection direction, WritingMode writingMode)
+{
+ switch (static_cast<CSSPropertyID>(propertyID)) {
+ case CSSPropertyWebkitMarginEnd: {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight, CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return resolveToPhysicalProperty(direction, writingMode, EndSide, properties);
+ }
+ case CSSPropertyWebkitMarginStart: {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight, CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return resolveToPhysicalProperty(direction, writingMode, StartSide, properties);
+ }
+ case CSSPropertyWebkitMarginBefore: {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight, CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return resolveToPhysicalProperty(direction, writingMode, BeforeSide, properties);
+ }
+ case CSSPropertyWebkitMarginAfter: {
+ const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight, CSSPropertyMarginBottom, CSSPropertyMarginLeft };
+ return resolveToPhysicalProperty(direction, writingMode, AfterSide, properties);
+ }
+ case CSSPropertyWebkitPaddingEnd: {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight, CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return resolveToPhysicalProperty(direction, writingMode, EndSide, properties);
+ }
+ case CSSPropertyWebkitPaddingStart: {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight, CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return resolveToPhysicalProperty(direction, writingMode, StartSide, properties);
+ }
+ case CSSPropertyWebkitPaddingBefore: {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight, CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return resolveToPhysicalProperty(direction, writingMode, BeforeSide, properties);
+ }
+ case CSSPropertyWebkitPaddingAfter: {
+ const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight, CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
+ return resolveToPhysicalProperty(direction, writingMode, AfterSide, properties);
+ }
+ case CSSPropertyWebkitBorderEnd: {
+ const int properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
+ return resolveToPhysicalProperty(direction, writingMode, EndSide, properties);
+ }
+ case CSSPropertyWebkitBorderStart: {
+ const int properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
+ return resolveToPhysicalProperty(direction, writingMode, StartSide, properties);
+ }
+ case CSSPropertyWebkitBorderBefore: {
+ const int properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
+ return resolveToPhysicalProperty(direction, writingMode, BeforeSide, properties);
+ }
+ case CSSPropertyWebkitBorderAfter: {
+ const int properties[4] = { CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
+ return resolveToPhysicalProperty(direction, writingMode, AfterSide, properties);
+ }
+ case CSSPropertyWebkitBorderEndColor: {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return resolveToPhysicalProperty(direction, writingMode, EndSide, properties);
+ }
+ case CSSPropertyWebkitBorderStartColor: {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return resolveToPhysicalProperty(direction, writingMode, StartSide, properties);
+ }
+ case CSSPropertyWebkitBorderBeforeColor: {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return resolveToPhysicalProperty(direction, writingMode, BeforeSide, properties);
+ }
+ case CSSPropertyWebkitBorderAfterColor: {
+ const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
+ return resolveToPhysicalProperty(direction, writingMode, AfterSide, properties);
+ }
+ case CSSPropertyWebkitBorderEndStyle: {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return resolveToPhysicalProperty(direction, writingMode, EndSide, properties);
+ }
+ case CSSPropertyWebkitBorderStartStyle: {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return resolveToPhysicalProperty(direction, writingMode, StartSide, properties);
+ }
+ case CSSPropertyWebkitBorderBeforeStyle: {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return resolveToPhysicalProperty(direction, writingMode, BeforeSide, properties);
+ }
+ case CSSPropertyWebkitBorderAfterStyle: {
+ const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
+ return resolveToPhysicalProperty(direction, writingMode, AfterSide, properties);
+ }
+ case CSSPropertyWebkitBorderEndWidth: {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return resolveToPhysicalProperty(direction, writingMode, EndSide, properties);
+ }
+ case CSSPropertyWebkitBorderStartWidth: {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return resolveToPhysicalProperty(direction, writingMode, StartSide, properties);
+ }
+ case CSSPropertyWebkitBorderBeforeWidth: {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return resolveToPhysicalProperty(direction, writingMode, BeforeSide, properties);
+ }
+ case CSSPropertyWebkitBorderAfterWidth: {
+ const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
+ return resolveToPhysicalProperty(direction, writingMode, AfterSide, properties);
+ }
+ case CSSPropertyWebkitLogicalWidth: {
+ const int properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
+ return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
+ }
+ case CSSPropertyWebkitLogicalHeight: {
+ const int properties[2] = { CSSPropertyWidth, CSSPropertyHeight };
+ return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
+ }
+ case CSSPropertyWebkitMinLogicalWidth: {
+ const int properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
+ return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
+ }
+ case CSSPropertyWebkitMinLogicalHeight: {
+ const int properties[2] = { CSSPropertyMinWidth, CSSPropertyMinHeight };
+ return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
+ }
+ case CSSPropertyWebkitMaxLogicalWidth: {
+ const int properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
+ return resolveToPhysicalProperty(writingMode, LogicalWidth, properties);
+ }
+ case CSSPropertyWebkitMaxLogicalHeight: {
+ const int properties[2] = { CSSPropertyMaxWidth, CSSPropertyMaxHeight };
+ return resolveToPhysicalProperty(writingMode, LogicalHeight, properties);
+ }
+ default:
+ return propertyID;
+ }
+}
+
+bool CSSProperty::isInheritedProperty(unsigned propertyID)
+{
+ switch (static_cast<CSSPropertyID>(propertyID)) {
+ case CSSPropertyBorderCollapse:
+ case CSSPropertyBorderSpacing:
+ case CSSPropertyCaptionSide:
+ case CSSPropertyColor:
+ case CSSPropertyCursor:
+ case CSSPropertyDirection:
+ case CSSPropertyEmptyCells:
+ case CSSPropertyFont:
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontVariant:
+ case CSSPropertyFontWeight:
+ case CSSPropertyImageRendering:
+ case CSSPropertyLetterSpacing:
+ case CSSPropertyLineHeight:
+ case CSSPropertyListStyle:
+ case CSSPropertyListStyleImage:
+ case CSSPropertyListStyleType:
+ case CSSPropertyListStylePosition:
+ case CSSPropertyOrphans:
+ case CSSPropertyPointerEvents:
+ case CSSPropertyQuotes:
+ case CSSPropertyResize:
+ case CSSPropertySpeak:
+ case CSSPropertyTextAlign:
+ case CSSPropertyTextDecoration:
+ case CSSPropertyTextIndent:
+ case CSSPropertyTextRendering:
+ case CSSPropertyTextShadow:
+ case CSSPropertyTextTransform:
+ case CSSPropertyVisibility:
+ case CSSPropertyWebkitAspectRatio:
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ case CSSPropertyWebkitBoxDirection:
+ case CSSPropertyWebkitColorCorrection:
+ case CSSPropertyWebkitFontFeatureSettings:
+ case CSSPropertyWebkitFontSmoothing:
+ case CSSPropertyWebkitLocale:
+ case CSSPropertyWebkitHighlight:
+ case CSSPropertyWebkitHyphenateCharacter:
+ case CSSPropertyWebkitHyphenateLimitAfter:
+ case CSSPropertyWebkitHyphenateLimitBefore:
+ case CSSPropertyWebkitHyphenateLimitLines:
+ case CSSPropertyWebkitHyphens:
+ case CSSPropertyWebkitLineBoxContain:
+ case CSSPropertyWebkitLineBreak:
+ case CSSPropertyWebkitLineGrid:
+ case CSSPropertyWebkitLineGridSnap:
+ case CSSPropertyWebkitNbspMode:
+ case CSSPropertyWebkitPrintColorAdjust:
+ case CSSPropertyWebkitRtlOrdering:
+ case CSSPropertyWebkitTextCombine:
+ case CSSPropertyWebkitTextDecorationsInEffect:
+ case CSSPropertyWebkitTextEmphasis:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextEmphasisPosition:
+ case CSSPropertyWebkitTextEmphasisStyle:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextOrientation:
+ case CSSPropertyWebkitTextSecurity:
+ case CSSPropertyWebkitTextSizeAdjust:
+ case CSSPropertyWebkitTextStroke:
+ case CSSPropertyWebkitTextStrokeColor:
+ case CSSPropertyWebkitTextStrokeWidth:
+ case CSSPropertyWebkitUserModify:
+ case CSSPropertyWebkitUserSelect:
+ case CSSPropertyWebkitWritingMode:
+ case CSSPropertyWhiteSpace:
+ case CSSPropertyWidows:
+ case CSSPropertyWordBreak:
+ case CSSPropertyWordSpacing:
+ case CSSPropertyWordWrap:
+#if ENABLE(SVG)
+ case CSSPropertyClipRule:
+ case CSSPropertyColorInterpolation:
+ case CSSPropertyColorInterpolationFilters:
+ case CSSPropertyColorRendering:
+ case CSSPropertyFill:
+ case CSSPropertyFillOpacity:
+ case CSSPropertyFillRule:
+ case CSSPropertyGlyphOrientationHorizontal:
+ case CSSPropertyGlyphOrientationVertical:
+ case CSSPropertyKerning:
+ case CSSPropertyMarker:
+ case CSSPropertyMarkerEnd:
+ case CSSPropertyMarkerMid:
+ case CSSPropertyMarkerStart:
+ case CSSPropertyStroke:
+ case CSSPropertyStrokeDasharray:
+ case CSSPropertyStrokeDashoffset:
+ case CSSPropertyStrokeLinecap:
+ case CSSPropertyStrokeLinejoin:
+ case CSSPropertyStrokeMiterlimit:
+ case CSSPropertyStrokeOpacity:
+ case CSSPropertyStrokeWidth:
+ case CSSPropertyShapeRendering:
+ case CSSPropertyTextAnchor:
+ case CSSPropertyWritingMode:
+#endif
+#if ENABLE(TOUCH_EVENTS)
+ case CSSPropertyWebkitTapHighlightColor:
+#endif
+ return true;
+ case CSSPropertyDisplay:
+ case CSSPropertyZoom:
+ case CSSPropertyBackground:
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyBorder:
+ case CSSPropertyBorderBottom:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderBottomLeftRadius:
+ case CSSPropertyBorderBottomRightRadius:
+ case CSSPropertyBorderBottomStyle:
+ case CSSPropertyBorderBottomWidth:
+ case CSSPropertyBorderColor:
+ case CSSPropertyBorderImage:
+ case CSSPropertyBorderImageOutset:
+ case CSSPropertyBorderImageRepeat:
+ case CSSPropertyBorderImageSlice:
+ case CSSPropertyBorderImageSource:
+ case CSSPropertyBorderImageWidth:
+ case CSSPropertyBorderLeft:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyBorderLeftWidth:
+ case CSSPropertyBorderRadius:
+ case CSSPropertyBorderRight:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderRightStyle:
+ case CSSPropertyBorderRightWidth:
+ case CSSPropertyBorderStyle:
+ case CSSPropertyBorderTop:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyBorderTopLeftRadius:
+ case CSSPropertyBorderTopRightRadius:
+ case CSSPropertyBorderTopStyle:
+ case CSSPropertyBorderTopWidth:
+ case CSSPropertyBorderWidth:
+ case CSSPropertyBottom:
+ case CSSPropertyBoxShadow:
+ case CSSPropertyBoxSizing:
+ case CSSPropertyClear:
+ case CSSPropertyClip:
+ case CSSPropertyContent:
+ case CSSPropertyCounterIncrement:
+ case CSSPropertyCounterReset:
+ case CSSPropertyFloat:
+ case CSSPropertyFontStretch:
+ case CSSPropertyHeight:
+ case CSSPropertyLeft:
+ case CSSPropertyMargin:
+ case CSSPropertyMarginBottom:
+ case CSSPropertyMarginLeft:
+ case CSSPropertyMarginRight:
+ case CSSPropertyMarginTop:
+ case CSSPropertyMaxHeight:
+ case CSSPropertyMaxWidth:
+ case CSSPropertyMinHeight:
+ case CSSPropertyMinWidth:
+ case CSSPropertyOpacity:
+ case CSSPropertyOutline:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyOutlineOffset:
+ case CSSPropertyOutlineStyle:
+ case CSSPropertyOutlineWidth:
+ case CSSPropertyOverflow:
+ case CSSPropertyOverflowX:
+ case CSSPropertyOverflowY:
+ case CSSPropertyPadding:
+ case CSSPropertyPaddingBottom:
+ case CSSPropertyPaddingLeft:
+ case CSSPropertyPaddingRight:
+ case CSSPropertyPaddingTop:
+ case CSSPropertyPage:
+ case CSSPropertyPageBreakAfter:
+ case CSSPropertyPageBreakBefore:
+ case CSSPropertyPageBreakInside:
+ case CSSPropertyPosition:
+ case CSSPropertyRight:
+ case CSSPropertySize:
+ case CSSPropertySrc:
+ case CSSPropertyTableLayout:
+ case CSSPropertyTextLineThrough:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextLineThroughWidth:
+ case CSSPropertyTextOverflow:
+ case CSSPropertyTextOverline:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextOverlineWidth:
+ case CSSPropertyTextUnderline:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyTextUnderlineMode:
+ case CSSPropertyTextUnderlineStyle:
+ case CSSPropertyTextUnderlineWidth:
+ case CSSPropertyTop:
+ case CSSPropertyUnicodeBidi:
+ case CSSPropertyUnicodeRange:
+ case CSSPropertyVerticalAlign:
+ case CSSPropertyWidth:
+ case CSSPropertyZIndex:
+ case CSSPropertyWebkitAnimation:
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitAnimationDirection:
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitAnimationFillMode:
+ case CSSPropertyWebkitAnimationIterationCount:
+ case CSSPropertyWebkitAnimationName:
+ case CSSPropertyWebkitAnimationPlayState:
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitAppearance:
+ case CSSPropertyWebkitBackfaceVisibility:
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitBorderAfter:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitBorderAfterWidth:
+ case CSSPropertyWebkitBorderBefore:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderBeforeWidth:
+ case CSSPropertyWebkitBorderEnd:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderEndWidth:
+ case CSSPropertyWebkitBorderFit:
+ case CSSPropertyWebkitBorderImage:
+ case CSSPropertyWebkitBorderRadius:
+ case CSSPropertyWebkitBorderStart:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitBorderStartWidth:
+ case CSSPropertyWebkitBoxAlign:
+ case CSSPropertyWebkitBoxFlex:
+ case CSSPropertyWebkitBoxFlexGroup:
+ case CSSPropertyWebkitBoxLines:
+ case CSSPropertyWebkitBoxOrdinalGroup:
+ case CSSPropertyWebkitBoxOrient:
+ case CSSPropertyWebkitBoxPack:
+ case CSSPropertyWebkitBoxReflect:
+ case CSSPropertyWebkitBoxShadow:
+ case CSSPropertyWebkitColumnAxis:
+ case CSSPropertyWebkitColumnBreakAfter:
+ case CSSPropertyWebkitColumnBreakBefore:
+ case CSSPropertyWebkitColumnBreakInside:
+ case CSSPropertyWebkitColumnCount:
+ case CSSPropertyWebkitColumnGap:
+ case CSSPropertyWebkitColumnRule:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitColumnRuleStyle:
+ case CSSPropertyWebkitColumnRuleWidth:
+ case CSSPropertyWebkitColumnSpan:
+ case CSSPropertyWebkitColumnWidth:
+ case CSSPropertyWebkitColumns:
+#if ENABLE(CSS_FILTERS)
+ case CSSPropertyWebkitFilter:
+#endif
+ case CSSPropertyWebkitFlexOrder:
+ case CSSPropertyWebkitFlexPack:
+ case CSSPropertyWebkitFlexAlign:
+ case CSSPropertyWebkitFlexDirection:
+ case CSSPropertyWebkitFlexFlow:
+ case CSSPropertyWebkitFlexWrap:
+ case CSSPropertyWebkitFontSizeDelta:
+#if ENABLE(CSS_GRID_LAYOUT)
+ case CSSPropertyWebkitGridColumns:
+ case CSSPropertyWebkitGridRows:
+#endif
+ case CSSPropertyWebkitLineClamp:
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyWebkitMarginAfterCollapse:
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ case CSSPropertyWebkitMarginBottomCollapse:
+ case CSSPropertyWebkitMarginTopCollapse:
+ case CSSPropertyWebkitMarginCollapse:
+ case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginStart:
+ case CSSPropertyWebkitMarquee:
+ case CSSPropertyWebkitMarqueeDirection:
+ case CSSPropertyWebkitMarqueeIncrement:
+ case CSSPropertyWebkitMarqueeRepetition:
+ case CSSPropertyWebkitMarqueeSpeed:
+ case CSSPropertyWebkitMarqueeStyle:
+ case CSSPropertyWebkitMask:
+ case CSSPropertyWebkitMaskAttachment:
+ case CSSPropertyWebkitMaskBoxImage:
+ case CSSPropertyWebkitMaskBoxImageOutset:
+ case CSSPropertyWebkitMaskBoxImageRepeat:
+ case CSSPropertyWebkitMaskBoxImageSlice:
+ case CSSPropertyWebkitMaskBoxImageSource:
+ case CSSPropertyWebkitMaskBoxImageWidth:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskComposite:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskOrigin:
+ case CSSPropertyWebkitMaskPosition:
+ case CSSPropertyWebkitMaskPositionX:
+ case CSSPropertyWebkitMaskPositionY:
+ case CSSPropertyWebkitMaskRepeat:
+ case CSSPropertyWebkitMaskRepeatX:
+ case CSSPropertyWebkitMaskRepeatY:
+ case CSSPropertyWebkitMaskSize:
+ case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
+ case CSSPropertyWebkitMaxLogicalWidth:
+ case CSSPropertyWebkitMaxLogicalHeight:
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyWebkitPerspective:
+ case CSSPropertyWebkitPerspectiveOrigin:
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ case CSSPropertyWebkitTransform:
+ case CSSPropertyWebkitTransformOrigin:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ case CSSPropertyWebkitTransformStyle:
+ case CSSPropertyWebkitTransition:
+ case CSSPropertyWebkitTransitionDelay:
+ case CSSPropertyWebkitTransitionDuration:
+ case CSSPropertyWebkitTransitionProperty:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ case CSSPropertyWebkitUserDrag:
+ case CSSPropertyWebkitFlowInto:
+ case CSSPropertyWebkitFlowFrom:
+ case CSSPropertyWebkitRegionOverflow:
+ case CSSPropertyWebkitRegionBreakAfter:
+ case CSSPropertyWebkitRegionBreakBefore:
+ case CSSPropertyWebkitRegionBreakInside:
+ case CSSPropertyWebkitWrap:
+ case CSSPropertyWebkitWrapFlow:
+ case CSSPropertyWebkitWrapMargin:
+ case CSSPropertyWebkitWrapPadding:
+ case CSSPropertyWebkitWrapShapeInside:
+ case CSSPropertyWebkitWrapShapeOutside:
+ case CSSPropertyWebkitWrapThrough:
+#if ENABLE(SVG)
+ case CSSPropertyClipPath:
+ case CSSPropertyMask:
+ case CSSPropertyEnableBackground:
+ case CSSPropertyFilter:
+ case CSSPropertyFloodColor:
+ case CSSPropertyFloodOpacity:
+ case CSSPropertyLightingColor:
+ case CSSPropertyStopColor:
+ case CSSPropertyStopOpacity:
+ case CSSPropertyColorProfile:
+ case CSSPropertyAlignmentBaseline:
+ case CSSPropertyBaselineShift:
+ case CSSPropertyDominantBaseline:
+ case CSSPropertyVectorEffect:
+ case CSSPropertyWebkitSvgShadow:
+#endif
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPropertyWebkitDashboardRegion:
+#endif
+ return false;
+ case CSSPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSProperty.h b/Source/WebCore/css/CSSProperty.h
new file mode 100644
index 000000000..2674544d1
--- /dev/null
+++ b/Source/WebCore/css/CSSProperty.h
@@ -0,0 +1,76 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 CSSProperty_h
+#define CSSProperty_h
+
+#include "CSSValue.h"
+#include "RenderStyleConstants.h"
+#include "TextDirection.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSProperty {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ CSSProperty(unsigned propID, PassRefPtr<CSSValue> value, bool important = false, int shorthandID = 0, bool implicit = false)
+ : m_id(propID)
+ , m_shorthandID(shorthandID)
+ , m_important(important)
+ , m_implicit(implicit)
+ , m_inherited(isInheritedProperty(propID))
+ , m_value(value)
+ {
+ }
+
+ int id() const { return m_id; }
+ int shorthandID() const { return m_shorthandID; }
+
+ bool isImportant() const { return m_important; }
+ bool isImplicit() const { return m_implicit; }
+ bool isInherited() const { return m_inherited; }
+
+ CSSValue* value() const { return m_value.get(); }
+
+ String cssText() const;
+
+ static int resolveDirectionAwareProperty(int propertyID, TextDirection, WritingMode);
+ static bool isInheritedProperty(unsigned propertyID);
+
+ // Make sure the following fits in 4 bytes. Really.
+ unsigned m_id : 14;
+ unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand.
+ bool m_important : 1;
+ bool m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand.
+ bool m_inherited : 1;
+
+ RefPtr<CSSValue> m_value;
+};
+
+} // namespace WebCore
+
+namespace WTF {
+ // Properties in Vector can be initialized with memset and moved using memcpy.
+ template<> struct VectorTraits<WebCore::CSSProperty> : SimpleClassVectorTraits { };
+}
+
+#endif // CSSProperty_h
diff --git a/Source/WebCore/css/CSSPropertyLonghand.cpp b/Source/WebCore/css/CSSPropertyLonghand.cpp
new file mode 100644
index 000000000..bdd128c77
--- /dev/null
+++ b/Source/WebCore/css/CSSPropertyLonghand.cpp
@@ -0,0 +1,247 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 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 "CSSPropertyLonghand.h"
+
+#include "CSSPropertyNames.h"
+#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+typedef HashMap<int, CSSPropertyLonghand> ShorthandMap;
+
+static void initShorthandMap(ShorthandMap& shorthandMap)
+{
+ #define SET_SHORTHAND_MAP_ENTRY(map, propID, array) \
+ map.set(propID, CSSPropertyLonghand(array, WTF_ARRAY_LENGTH(array)))
+
+ static const int fontProperties[] = {
+ CSSPropertyFontFamily,
+ CSSPropertyFontSize,
+ CSSPropertyFontStyle,
+ CSSPropertyFontVariant,
+ CSSPropertyFontWeight,
+ CSSPropertyLineHeight
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyFont, fontProperties);
+
+ // Do not change the order of the following four shorthands, and keep them together.
+ static const int borderProperties[4][3] = {
+ { CSSPropertyBorderTopColor, CSSPropertyBorderTopStyle, CSSPropertyBorderTopWidth },
+ { CSSPropertyBorderRightColor, CSSPropertyBorderRightStyle, CSSPropertyBorderRightWidth },
+ { CSSPropertyBorderBottomColor, CSSPropertyBorderBottomStyle, CSSPropertyBorderBottomWidth },
+ { CSSPropertyBorderLeftColor, CSSPropertyBorderLeftStyle, CSSPropertyBorderLeftWidth }
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderTop, borderProperties[0]);
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderRight, borderProperties[1]);
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderBottom, borderProperties[2]);
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderLeft, borderProperties[3]);
+
+ shorthandMap.set(CSSPropertyBorder, CSSPropertyLonghand(borderProperties[0], sizeof(borderProperties) / sizeof(borderProperties[0][0])));
+
+ static const int borderColorProperties[] = {
+ CSSPropertyBorderTopColor,
+ CSSPropertyBorderRightColor,
+ CSSPropertyBorderBottomColor,
+ CSSPropertyBorderLeftColor
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderColor, borderColorProperties);
+
+ static const int borderStyleProperties[] = {
+ CSSPropertyBorderTopStyle,
+ CSSPropertyBorderRightStyle,
+ CSSPropertyBorderBottomStyle,
+ CSSPropertyBorderLeftStyle
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderStyle, borderStyleProperties);
+
+ static const int borderWidthProperties[] = {
+ CSSPropertyBorderTopWidth,
+ CSSPropertyBorderRightWidth,
+ CSSPropertyBorderBottomWidth,
+ CSSPropertyBorderLeftWidth
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderWidth, borderWidthProperties);
+
+ static const int backgroundPositionProperties[] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackgroundPosition, backgroundPositionProperties);
+
+ static const int backgroundRepeatProperties[] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackgroundRepeat, backgroundRepeatProperties);
+
+ static const int borderSpacingProperties[] = { CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderSpacing, borderSpacingProperties);
+
+ static const int flexFlowProperties[] = { CSSPropertyWebkitFlexDirection, CSSPropertyWebkitFlexWrap };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitFlexFlow, flexFlowProperties);
+
+ static const int listStyleProperties[] = {
+ CSSPropertyListStyleImage,
+ CSSPropertyListStylePosition,
+ CSSPropertyListStyleType
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyListStyle, listStyleProperties);
+
+ static const int marginProperties[] = {
+ CSSPropertyMarginTop,
+ CSSPropertyMarginRight,
+ CSSPropertyMarginBottom,
+ CSSPropertyMarginLeft
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyMargin, marginProperties);
+
+ static const int marginCollapseProperties[] = { CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginAfterCollapse };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMarginCollapse, marginCollapseProperties);
+
+ static const int marqueeProperties[] = {
+ CSSPropertyWebkitMarqueeDirection,
+ CSSPropertyWebkitMarqueeIncrement,
+ CSSPropertyWebkitMarqueeRepetition,
+ CSSPropertyWebkitMarqueeStyle,
+ CSSPropertyWebkitMarqueeSpeed
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMarquee, marqueeProperties);
+
+ static const int outlineProperties[] = {
+ CSSPropertyOutlineColor,
+ CSSPropertyOutlineOffset,
+ CSSPropertyOutlineStyle,
+ CSSPropertyOutlineWidth
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyOutline, outlineProperties);
+
+ static const int paddingProperties[] = {
+ CSSPropertyPaddingTop,
+ CSSPropertyPaddingRight,
+ CSSPropertyPaddingBottom,
+ CSSPropertyPaddingLeft
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyPadding, paddingProperties);
+
+ static const int webkitWrapProperties[] = {
+ CSSPropertyWebkitWrapFlow,
+ CSSPropertyWebkitWrapMargin,
+ CSSPropertyWebkitWrapPadding
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitWrap, webkitWrapProperties);
+
+ static const int textStrokeProperties[] = { CSSPropertyWebkitTextStrokeColor, CSSPropertyWebkitTextStrokeWidth };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTextStroke, textStrokeProperties);
+
+ static const int backgroundProperties[] = {
+ CSSPropertyBackgroundAttachment,
+ CSSPropertyBackgroundClip,
+ CSSPropertyBackgroundColor,
+ CSSPropertyBackgroundImage,
+ CSSPropertyBackgroundOrigin,
+ CSSPropertyBackgroundPositionX,
+ CSSPropertyBackgroundPositionY,
+ CSSPropertyBackgroundRepeatX,
+ CSSPropertyBackgroundRepeatY
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackground, backgroundProperties);
+
+ static const int columnsProperties[] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitColumns, columnsProperties);
+
+ static const int columnRuleProperties[] = {
+ CSSPropertyWebkitColumnRuleColor,
+ CSSPropertyWebkitColumnRuleStyle,
+ CSSPropertyWebkitColumnRuleWidth
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitColumnRule, columnRuleProperties);
+
+ static const int overflowProperties[] = { CSSPropertyOverflowX, CSSPropertyOverflowY };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyOverflow, overflowProperties);
+
+ static const int borderRadiusProperties[] = {
+ CSSPropertyBorderTopRightRadius,
+ CSSPropertyBorderTopLeftRadius,
+ CSSPropertyBorderBottomLeftRadius,
+ CSSPropertyBorderBottomRightRadius
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderRadius, borderRadiusProperties);
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitBorderRadius, borderRadiusProperties);
+
+ static const int maskPositionProperties[] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMaskPosition, maskPositionProperties);
+
+ static const int maskRepeatProperties[] = { CSSPropertyWebkitMaskRepeatX, CSSPropertyWebkitMaskRepeatY };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMaskRepeat, maskRepeatProperties);
+
+ static const int maskProperties[] = {
+ CSSPropertyWebkitMaskAttachment,
+ CSSPropertyWebkitMaskClip,
+ CSSPropertyWebkitMaskImage,
+ CSSPropertyWebkitMaskOrigin,
+ CSSPropertyWebkitMaskPositionX,
+ CSSPropertyWebkitMaskPositionY,
+ CSSPropertyWebkitMaskRepeatX,
+ CSSPropertyWebkitMaskRepeatY
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMask, maskProperties);
+
+ static const int animationProperties[] = {
+ CSSPropertyWebkitAnimationName,
+ CSSPropertyWebkitAnimationDuration,
+ CSSPropertyWebkitAnimationTimingFunction,
+ CSSPropertyWebkitAnimationDelay,
+ CSSPropertyWebkitAnimationIterationCount,
+ CSSPropertyWebkitAnimationDirection,
+ CSSPropertyWebkitAnimationFillMode
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitAnimation, animationProperties);
+
+ static const int transitionProperties[] = {
+ CSSPropertyWebkitTransitionProperty,
+ CSSPropertyWebkitTransitionDuration,
+ CSSPropertyWebkitTransitionTimingFunction,
+ CSSPropertyWebkitTransitionDelay
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTransition, transitionProperties);
+
+ static const int transformOriginProperties[] = {
+ CSSPropertyWebkitTransformOriginX,
+ CSSPropertyWebkitTransformOriginY
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTransformOrigin, transformOriginProperties);
+
+ static const int textEmphasisProperties[] = {
+ CSSPropertyWebkitTextEmphasisColor,
+ CSSPropertyWebkitTextEmphasisStyle
+ };
+ SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTextEmphasis, textEmphasisProperties);
+
+ #undef SET_SHORTHAND_MAP_ENTRY
+}
+
+CSSPropertyLonghand longhandForProperty(int propertyID)
+{
+ DEFINE_STATIC_LOCAL(ShorthandMap, shorthandMap, ());
+ if (shorthandMap.isEmpty())
+ initShorthandMap(shorthandMap);
+
+ return shorthandMap.get(propertyID);
+}
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSPropertyLonghand.h b/Source/WebCore/css/CSSPropertyLonghand.h
new file mode 100644
index 000000000..9633c025a
--- /dev/null
+++ b/Source/WebCore/css/CSSPropertyLonghand.h
@@ -0,0 +1,53 @@
+/*
+ * (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 CSSPropertyLonghand_h
+#define CSSPropertyLonghand_h
+
+namespace WebCore {
+
+class CSSPropertyLonghand {
+public:
+ CSSPropertyLonghand()
+ : m_properties(0)
+ , m_length(0)
+ {
+ }
+
+ CSSPropertyLonghand(const int* firstProperty, unsigned numProperties)
+ : m_properties(firstProperty)
+ , m_length(numProperties)
+ {
+ }
+
+ const int* properties() const { return m_properties; }
+ unsigned length() const { return m_length; }
+
+private:
+ const int* m_properties;
+ unsigned m_length;
+};
+
+// Returns an empty list if the property is not a shorthand
+CSSPropertyLonghand longhandForProperty(int);
+
+} // namespace WebCore
+
+#endif // CSSPropertyLonghand_h
diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in
new file mode 100644
index 000000000..c0299da60
--- /dev/null
+++ b/Source/WebCore/css/CSSPropertyNames.in
@@ -0,0 +1,375 @@
+//
+// CSS property names
+//
+// Some properties are used internally, but are not part of CSS. They are used to get
+// HTML4 compatibility in the rendering engine.
+//
+// Microsoft extensions are documented here:
+// http://msdn.microsoft.com/workshop/author/css/reference/attributes.asp
+//
+
+// high-priority property names have to be listed first, to simplify the check
+// for applying them first.
+color
+direction
+display
+font
+font-family
+font-size
+font-style
+font-variant
+font-weight
+text-rendering
+-webkit-font-feature-settings
+-webkit-font-smoothing
+-webkit-locale
+-webkit-text-orientation
+-epub-text-orientation = -webkit-text-orientation
+-webkit-text-size-adjust
+-webkit-writing-mode
+-epub-writing-mode = -webkit-writing-mode
+zoom
+
+// line height needs to be right after the above high-priority properties
+line-height
+
+// The remaining properties are listed in alphabetical order
+background
+background-attachment
+background-clip
+background-color
+background-image
+background-origin
+background-position
+background-position-x
+background-position-y
+background-repeat
+background-repeat-x
+background-repeat-y
+background-size
+border
+border-bottom
+border-bottom-color
+border-bottom-left-radius
+-webkit-border-bottom-left-radius = border-bottom-left-radius
+border-bottom-right-radius
+-webkit-border-bottom-right-radius = border-bottom-right-radius
+border-bottom-style
+border-bottom-width
+border-collapse
+border-color
+border-image
+border-image-outset
+border-image-repeat
+border-image-slice
+border-image-source
+border-image-width
+border-left
+border-left-color
+border-left-style
+border-left-width
+border-radius
+border-right
+border-right-color
+border-right-style
+border-right-width
+border-spacing
+border-style
+border-top
+border-top-color
+border-top-left-radius
+-webkit-border-top-left-radius = border-top-left-radius
+border-top-right-radius
+-webkit-border-top-right-radius = border-top-right-radius
+border-top-style
+border-top-width
+border-width
+bottom
+box-shadow
+box-sizing
+// -webkit-box-sizing worked in Safari 4 and earlier.
+-webkit-box-sizing = box-sizing
+caption-side
+-epub-caption-side = caption-side
+clear
+clip
+content
+counter-increment
+counter-reset
+cursor
+empty-cells
+float
+font-stretch
+height
+image-rendering
+left
+letter-spacing
+list-style
+list-style-image
+list-style-position
+list-style-type
+margin
+margin-bottom
+margin-left
+margin-right
+margin-top
+max-height
+max-width
+min-height
+min-width
+opacity
+// Honor -webkit-opacity as a synonym for opacity. This was the only syntax that worked in Safari 1.1,
+// and may be in use on some websites and widgets.
+-webkit-opacity = opacity
+orphans
+outline
+outline-color
+outline-offset
+outline-style
+outline-width
+overflow
+overflow-x
+overflow-y
+padding
+padding-bottom
+padding-left
+padding-right
+padding-top
+page
+page-break-after
+page-break-before
+page-break-inside
+pointer-events
+position
+quotes
+resize
+right
+size
+src
+speak
+table-layout
+text-align
+text-decoration
+text-indent
+text-line-through
+text-line-through-color
+text-line-through-mode
+text-line-through-style
+text-line-through-width
+text-overflow
+text-overline
+text-overline-color
+text-overline-mode
+text-overline-style
+text-overline-width
+text-shadow
+text-transform
+-epub-text-transform = text-transform
+text-underline
+text-underline-color
+text-underline-mode
+text-underline-style
+text-underline-width
+top
+unicode-bidi
+unicode-range
+vertical-align
+visibility
+white-space
+widows
+width
+word-break
+-epub-word-break = word-break
+word-spacing
+word-wrap
+z-index
+-webkit-animation
+-webkit-animation-delay
+-webkit-animation-direction
+-webkit-animation-duration
+-webkit-animation-fill-mode
+-webkit-animation-iteration-count
+-webkit-animation-name
+-webkit-animation-play-state
+-webkit-animation-timing-function
+-webkit-appearance
+-webkit-aspect-ratio
+-webkit-backface-visibility
+-webkit-background-clip
+-webkit-background-composite
+-webkit-background-origin
+// -webkit-background-size differs from background-size only in the interpretation of
+// a single value: -webkit-background-size: l; is equivalent to background-size: l l;
+// whereas background-size: l; is equivalent to background-size: l auto;
+-webkit-background-size
+-webkit-border-after
+-webkit-border-after-color
+-webkit-border-after-style
+-webkit-border-after-width
+-webkit-border-before
+-webkit-border-before-color
+-webkit-border-before-style
+-webkit-border-before-width
+-webkit-border-end
+-webkit-border-end-color
+-webkit-border-end-style
+-webkit-border-end-width
+-webkit-border-fit
+-webkit-border-horizontal-spacing
+-webkit-border-image
+// -webkit-border-radius differs from border-radius only in the interpretation of
+// a value consisting of two lengths: "-webkit-border-radius: l1 l2;" is equivalent
+// to "border-radius: l1 / l2;"
+-webkit-border-radius
+-webkit-border-start
+-webkit-border-start-color
+-webkit-border-start-style
+-webkit-border-start-width
+-webkit-border-vertical-spacing
+-webkit-box-align
+-webkit-box-direction
+-webkit-box-flex
+-webkit-box-flex-group
+-webkit-box-lines
+-webkit-box-ordinal-group
+-webkit-box-orient
+-webkit-box-pack
+-webkit-box-reflect
+-webkit-box-shadow
+-webkit-color-correction
+-webkit-column-axis
+-webkit-column-break-after
+-webkit-column-break-before
+-webkit-column-break-inside
+-webkit-column-count
+-webkit-column-gap
+-webkit-column-rule
+-webkit-column-rule-color
+-webkit-column-rule-style
+-webkit-column-rule-width
+-webkit-column-span
+-webkit-column-width
+-webkit-columns
+#if defined(ENABLE_CSS_FILTERS) && ENABLE_CSS_FILTERS
+-webkit-filter
+#endif
+-webkit-flex-align
+-webkit-flex-direction
+-webkit-flex-flow
+-webkit-flex-order
+-webkit-flex-pack
+-webkit-flex-wrap
+-webkit-font-size-delta
+-webkit-highlight
+-webkit-hyphenate-character
+-webkit-hyphenate-limit-after
+-webkit-hyphenate-limit-before
+-webkit-hyphenate-limit-lines
+-webkit-hyphens
+-epub-hyphens = -webkit-hyphens
+-webkit-line-box-contain
+-webkit-line-break
+-webkit-line-clamp
+-webkit-line-grid
+-webkit-line-grid-snap
+-webkit-logical-width
+-webkit-logical-height
+-webkit-margin-after-collapse
+-webkit-margin-before-collapse
+-webkit-margin-bottom-collapse
+-webkit-margin-top-collapse
+-webkit-margin-collapse
+-webkit-margin-after
+-webkit-margin-before
+-webkit-margin-end
+-webkit-margin-start
+-webkit-marquee
+-webkit-marquee-direction
+-webkit-marquee-increment
+-webkit-marquee-repetition
+-webkit-marquee-speed
+-webkit-marquee-style
+-webkit-mask
+-webkit-mask-attachment
+-webkit-mask-box-image
+-webkit-mask-box-image-outset
+-webkit-mask-box-image-repeat
+-webkit-mask-box-image-slice
+-webkit-mask-box-image-source
+-webkit-mask-box-image-width
+-webkit-mask-clip
+-webkit-mask-composite
+-webkit-mask-image
+-webkit-mask-origin
+-webkit-mask-position
+-webkit-mask-position-x
+-webkit-mask-position-y
+-webkit-mask-repeat
+-webkit-mask-repeat-x
+-webkit-mask-repeat-y
+-webkit-mask-size
+-webkit-match-nearest-mail-blockquote-color
+-webkit-max-logical-width
+-webkit-max-logical-height
+-webkit-min-logical-width
+-webkit-min-logical-height
+-webkit-nbsp-mode
+-webkit-padding-after
+-webkit-padding-before
+-webkit-padding-end
+-webkit-padding-start
+-webkit-perspective
+-webkit-perspective-origin
+-webkit-perspective-origin-x
+-webkit-perspective-origin-y
+-webkit-print-color-adjust
+-webkit-rtl-ordering
+-webkit-text-combine
+-epub-text-combine = -webkit-text-combine
+-webkit-text-decorations-in-effect
+-webkit-text-emphasis
+-epub-text-emphasis = -webkit-text-emphasis
+-webkit-text-emphasis-color
+-epub-text-emphasis-color = -webkit-text-emphasis-color
+-webkit-text-emphasis-position
+-webkit-text-emphasis-style
+-epub-text-emphasis-style = -webkit-text-emphasis-style
+-webkit-text-fill-color
+-webkit-text-security
+-webkit-text-stroke
+-webkit-text-stroke-color
+-webkit-text-stroke-width
+-webkit-transform
+-webkit-transform-origin
+-webkit-transform-origin-x
+-webkit-transform-origin-y
+-webkit-transform-origin-z
+-webkit-transform-style
+-webkit-transition
+-webkit-transition-delay
+-webkit-transition-duration
+-webkit-transition-property
+-webkit-transition-timing-function
+-webkit-user-drag
+-webkit-user-modify
+-webkit-user-select
+-webkit-flow-into
+-webkit-flow-from
+-webkit-region-overflow
+-webkit-wrap-shape-inside
+-webkit-wrap-shape-outside
+-webkit-wrap-margin
+-webkit-wrap-padding
+-webkit-region-break-after
+-webkit-region-break-before
+-webkit-region-break-inside
+-webkit-wrap-flow
+-webkit-wrap-through
+-webkit-wrap
+#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS
+-webkit-tap-highlight-color
+#endif
+#if defined(ENABLE_CSS_GRID_LAYOUT) && ENABLE_CSS_GRID_LAYOUT
+-webkit-grid-columns
+-webkit-grid-rows
+#endif
diff --git a/Source/WebCore/css/CSSPropertySourceData.cpp b/Source/WebCore/css/CSSPropertySourceData.cpp
new file mode 100644
index 000000000..d17ac8db6
--- /dev/null
+++ b/Source/WebCore/css/CSSPropertySourceData.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2010 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"
+
+#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
+#define CSSPROPERTYSOURCEDATA_HIDE_GLOBALS 1
+#endif
+
+#include "CSSPropertySourceData.h"
+
+#include "PlatformString.h"
+#include <wtf/StaticConstructors.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+SourceRange::SourceRange()
+ : start(0)
+ , end(0)
+{
+}
+
+SourceRange::SourceRange(unsigned start, unsigned end)
+ : start(start)
+ , end(end)
+{
+}
+
+unsigned SourceRange::length() const
+{
+ return end - start;
+}
+
+CSSPropertySourceData::CSSPropertySourceData(const String& name, const String& value, bool important, bool parsedOk, const SourceRange& range)
+ : name(name)
+ , value(value)
+ , important(important)
+ , parsedOk(parsedOk)
+ , range(range)
+{
+}
+
+CSSPropertySourceData::CSSPropertySourceData(const CSSPropertySourceData& other)
+ : name(other.name)
+ , value(other.value)
+ , important(other.important)
+ , parsedOk(other.parsedOk)
+ , range(other.range)
+{
+}
+
+CSSPropertySourceData::CSSPropertySourceData()
+ : name("")
+ , value("")
+ , important(false)
+ , parsedOk(false)
+ , range(SourceRange(0, 0))
+{
+}
+
+String CSSPropertySourceData::toString() const
+{
+ DEFINE_STATIC_LOCAL(String, emptyValue, ("e"));
+ DEFINE_STATIC_LOCAL(String, importantSuffix, (" !important"));
+ if (!name && value == emptyValue)
+ return String();
+
+ String result = name;
+ result += ": ";
+ result += value;
+ if (important)
+ result += importantSuffix;
+ result += ";";
+ return result;
+}
+
+unsigned CSSPropertySourceData::hash() const
+{
+ return StringHash::hash(name) + 3 * StringHash::hash(value) + 7 * important + 13 * parsedOk + 31;
+}
+
+// Global init routines
+DEFINE_GLOBAL(CSSPropertySourceData, emptyCSSPropertySourceData, "", "e", false, false)
+
+// static
+void CSSPropertySourceData::init()
+{
+ static bool initialized;
+ if (!initialized) {
+ new ((void *) &emptyCSSPropertySourceData) CSSPropertySourceData("", "e", false, false, SourceRange(0, 0));
+ initialized = true;
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSPropertySourceData.h b/Source/WebCore/css/CSSPropertySourceData.h
new file mode 100644
index 000000000..f20af1af8
--- /dev/null
+++ b/Source/WebCore/css/CSSPropertySourceData.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 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 CSSPropertySourceData_h
+#define CSSPropertySourceData_h
+
+#include "PlatformString.h"
+#include <utility>
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSStyleRule;
+
+struct SourceRange {
+ SourceRange();
+ SourceRange(unsigned start, unsigned end);
+ unsigned length() const;
+
+ unsigned start;
+ unsigned end;
+};
+
+struct CSSPropertySourceData {
+ static void init();
+
+ CSSPropertySourceData(const String& name, const String& value, bool important, bool parsedOk, const SourceRange& range);
+ CSSPropertySourceData(const CSSPropertySourceData& other);
+ CSSPropertySourceData();
+
+ String toString() const;
+ unsigned hash() const;
+
+ String name;
+ String value;
+ bool important;
+ bool parsedOk;
+ SourceRange range;
+};
+
+#ifndef CSSPROPERTYSOURCEDATA_HIDE_GLOBALS
+extern const CSSPropertySourceData emptyCSSPropertySourceData;
+#endif
+
+struct CSSStyleSourceData : public RefCounted<CSSStyleSourceData> {
+ static PassRefPtr<CSSStyleSourceData> create()
+ {
+ return adoptRef(new CSSStyleSourceData());
+ }
+
+ // Range of the style text in the enclosing source.
+ SourceRange styleBodyRange;
+ Vector<CSSPropertySourceData> propertyData;
+};
+
+struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> {
+ static PassRefPtr<CSSRuleSourceData> create()
+ {
+ return adoptRef(new CSSRuleSourceData());
+ }
+
+ // Range of the selector list in the enclosing source.
+ SourceRange selectorListRange;
+ RefPtr<CSSStyleSourceData> styleSourceData;
+};
+typedef HashMap<CSSStyleRule*, RefPtr<CSSRuleSourceData> > StyleRuleRangeMap;
+
+} // namespace WebCore
+
+#endif // CSSPropertySourceData_h
diff --git a/Source/WebCore/css/CSSReflectValue.cpp b/Source/WebCore/css/CSSReflectValue.cpp
new file mode 100644
index 000000000..911d110b9
--- /dev/null
+++ b/Source/WebCore/css/CSSReflectValue.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2008 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. ``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.
+ */
+
+#include "config.h"
+#include "CSSReflectValue.h"
+
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+
+using namespace std;
+
+namespace WebCore {
+
+String CSSReflectValue::customCssText() const
+{
+ String result;
+ switch (m_direction) {
+ case ReflectionBelow:
+ result += "below ";
+ break;
+ case ReflectionAbove:
+ result += "above ";
+ break;
+ case ReflectionLeft:
+ result += "left ";
+ break;
+ case ReflectionRight:
+ result += "right ";
+ break;
+ default:
+ break;
+ }
+
+ result += m_offset->cssText() + " ";
+ if (m_mask)
+ result += m_mask->cssText();
+ return result;
+}
+
+void CSSReflectValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
+{
+ if (m_mask)
+ m_mask->addSubresourceStyleURLs(urls, styleSheet);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSReflectValue.h b/Source/WebCore/css/CSSReflectValue.h
new file mode 100644
index 000000000..5b03efe89
--- /dev/null
+++ b/Source/WebCore/css/CSSReflectValue.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2008 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. ``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 CSSReflectValue_h
+#define CSSReflectValue_h
+
+#include "CSSReflectionDirection.h"
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSPrimitiveValue;
+
+class CSSReflectValue : public CSSValue {
+public:
+ static PassRefPtr<CSSReflectValue> create(CSSReflectionDirection direction,
+ PassRefPtr<CSSPrimitiveValue> offset, PassRefPtr<CSSValue> mask)
+ {
+ return adoptRef(new CSSReflectValue(direction, offset, mask));
+ }
+
+ CSSReflectionDirection direction() const { return m_direction; }
+ CSSPrimitiveValue* offset() const { return m_offset.get(); }
+ CSSValue* mask() const { return m_mask.get(); }
+
+ String customCssText() const;
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
+
+private:
+ CSSReflectValue(CSSReflectionDirection direction, PassRefPtr<CSSPrimitiveValue> offset, PassRefPtr<CSSValue> mask)
+ : CSSValue(ReflectClass)
+ , m_direction(direction)
+ , m_offset(offset)
+ , m_mask(mask)
+ {
+ }
+
+ CSSReflectionDirection m_direction;
+ RefPtr<CSSPrimitiveValue> m_offset;
+ RefPtr<CSSValue> m_mask;
+};
+
+} // namespace WebCore
+
+#endif // CSSReflectValue_h
diff --git a/Source/WebCore/css/CSSReflectionDirection.h b/Source/WebCore/css/CSSReflectionDirection.h
new file mode 100644
index 000000000..e30bc1c13
--- /dev/null
+++ b/Source/WebCore/css/CSSReflectionDirection.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 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. ``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 CSSReflectionDirection_h
+#define CSSReflectionDirection_h
+
+namespace WebCore {
+
+enum CSSReflectionDirection { ReflectionBelow, ReflectionAbove, ReflectionLeft, ReflectionRight };
+
+} // namespace WebCore
+
+#endif // CSSReflectionDirection_h
diff --git a/Source/WebCore/css/CSSRule.cpp b/Source/WebCore/css/CSSRule.cpp
new file mode 100644
index 000000000..5399848da
--- /dev/null
+++ b/Source/WebCore/css/CSSRule.cpp
@@ -0,0 +1,115 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2005, 2006, 2007 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 "CSSRule.h"
+
+#include "CSSCharsetRule.h"
+#include "CSSFontFaceRule.h"
+#include "CSSImportRule.h"
+#include "CSSMediaRule.h"
+#include "CSSPageRule.h"
+#include "CSSStyleRule.h"
+#include "CSSUnknownRule.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include "WebKitCSSRegionRule.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+struct SameSizeAsCSSRule : public RefCounted<SameSizeAsCSSRule> {
+ unsigned bitfields;
+ void* pointerUnion;
+};
+
+COMPILE_ASSERT(sizeof(CSSRule) == sizeof(SameSizeAsCSSRule), CSSRule_should_stay_small);
+
+void CSSRule::setCssText(const String& /*cssText*/, ExceptionCode& /*ec*/)
+{
+ notImplemented();
+}
+
+String CSSRule::cssText() const
+{
+ switch (type()) {
+ case UNKNOWN_RULE:
+ return String();
+ case STYLE_RULE:
+ case PAGE_RULE:
+ return static_cast<const CSSStyleRule*>(this)->cssText();
+ case CHARSET_RULE:
+ return static_cast<const CSSCharsetRule*>(this)->cssText();
+ case IMPORT_RULE:
+ return static_cast<const CSSImportRule*>(this)->cssText();
+ case MEDIA_RULE:
+ return static_cast<const CSSMediaRule*>(this)->cssText();
+ case FONT_FACE_RULE:
+ return static_cast<const CSSFontFaceRule*>(this)->cssText();
+ case WEBKIT_KEYFRAMES_RULE:
+ return static_cast<const WebKitCSSKeyframesRule*>(this)->cssText();
+ case WEBKIT_KEYFRAME_RULE:
+ return static_cast<const WebKitCSSKeyframeRule*>(this)->cssText();
+ case WEBKIT_REGION_RULE:
+ return static_cast<const WebKitCSSRegionRule*>(this)->cssText();
+ }
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+void CSSRule::destroy()
+{
+ switch (type()) {
+ case UNKNOWN_RULE:
+ delete static_cast<CSSUnknownRule*>(this);
+ return;
+ case STYLE_RULE:
+ delete static_cast<CSSStyleRule*>(this);
+ return;
+ case PAGE_RULE:
+ delete static_cast<CSSPageRule*>(this);
+ return;
+ case CHARSET_RULE:
+ delete static_cast<CSSCharsetRule*>(this);
+ return;
+ case IMPORT_RULE:
+ delete static_cast<CSSImportRule*>(this);
+ return;
+ case MEDIA_RULE:
+ delete static_cast<CSSMediaRule*>(this);
+ return;
+ case FONT_FACE_RULE:
+ delete static_cast<CSSFontFaceRule*>(this);
+ return;
+ case WEBKIT_KEYFRAMES_RULE:
+ delete static_cast<WebKitCSSKeyframesRule*>(this);
+ return;
+ case WEBKIT_KEYFRAME_RULE:
+ delete static_cast<WebKitCSSKeyframeRule*>(this);
+ return;
+ case WEBKIT_REGION_RULE:
+ delete static_cast<WebKitCSSRegionRule*>(this);
+ return;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSRule.h b/Source/WebCore/css/CSSRule.h
new file mode 100644
index 000000000..4f3ca3b74
--- /dev/null
+++ b/Source/WebCore/css/CSSRule.h
@@ -0,0 +1,146 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Andreas Kling (kling@webkit.org)
+ *
+ * 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 CSSRule_h
+#define CSSRule_h
+
+#include "CSSStyleSheet.h"
+#include "KURLHash.h"
+#include <wtf/ListHashSet.h>
+
+namespace WebCore {
+
+typedef int ExceptionCode;
+
+class CSSRule : public RefCounted<CSSRule> {
+public:
+ // Override RefCounted's deref() to ensure operator delete is called on
+ // the appropriate subclass type.
+ void deref()
+ {
+ if (derefBase())
+ destroy();
+ }
+
+ enum Type {
+ UNKNOWN_RULE,
+ STYLE_RULE,
+ CHARSET_RULE,
+ IMPORT_RULE,
+ MEDIA_RULE,
+ FONT_FACE_RULE,
+ PAGE_RULE,
+ // 7 used to be VARIABLES_RULE
+ WEBKIT_KEYFRAMES_RULE = 8,
+ WEBKIT_KEYFRAME_RULE,
+ WEBKIT_REGION_RULE
+ };
+
+ Type type() const { return static_cast<Type>(m_type); }
+
+ bool isCharsetRule() const { return type() == CHARSET_RULE; }
+ bool isFontFaceRule() const { return type() == FONT_FACE_RULE; }
+ bool isKeyframeRule() const { return type() == WEBKIT_KEYFRAME_RULE; }
+ bool isKeyframesRule() const { return type() == WEBKIT_KEYFRAMES_RULE; }
+ bool isMediaRule() const { return type() == MEDIA_RULE; }
+ bool isPageRule() const { return type() == PAGE_RULE; }
+ bool isStyleRule() const { return type() == STYLE_RULE; }
+ bool isRegionRule() const { return type() == WEBKIT_REGION_RULE; }
+ bool isImportRule() const { return type() == IMPORT_RULE; }
+
+ bool useStrictParsing() const
+ {
+ if (parentRule())
+ return parentRule()->useStrictParsing();
+ if (parentStyleSheet())
+ return parentStyleSheet()->useStrictParsing();
+ return true;
+ }
+
+ void setParentStyleSheet(CSSStyleSheet* styleSheet)
+ {
+ m_parentIsRule = false;
+ m_parentStyleSheet = styleSheet;
+ }
+
+ void setParentRule(CSSRule* rule)
+ {
+ m_parentIsRule = true;
+ m_parentRule = rule;
+ }
+
+ CSSStyleSheet* parentStyleSheet() const
+ {
+ if (m_parentIsRule)
+ return m_parentRule ? m_parentRule->parentStyleSheet() : 0;
+ return m_parentStyleSheet;
+ }
+
+ CSSRule* parentRule() const { return m_parentIsRule ? m_parentRule : 0; }
+
+ String cssText() const;
+ void setCssText(const String&, ExceptionCode&);
+
+ KURL baseURL() const
+ {
+ if (CSSStyleSheet* parentSheet = parentStyleSheet())
+ return parentSheet->baseURL();
+ return KURL();
+ }
+
+protected:
+ CSSRule(CSSStyleSheet* parent, Type type)
+ : m_sourceLine(0)
+ , m_hasCachedSelectorText(false)
+ , m_parentIsRule(false)
+ , m_type(type)
+ , m_parentStyleSheet(parent)
+ {
+ }
+
+ // NOTE: This class is non-virtual for memory and performance reasons.
+ // Don't go making it virtual again unless you know exactly what you're doing!
+
+ ~CSSRule() { }
+
+ int sourceLine() const { return m_sourceLine; }
+ void setSourceLine(int sourceLine) { m_sourceLine = sourceLine; }
+ bool hasCachedSelectorText() const { return m_hasCachedSelectorText; }
+ void setHasCachedSelectorText(bool hasCachedSelectorText) const { m_hasCachedSelectorText = hasCachedSelectorText; }
+
+private:
+ // Only used by CSSStyleRule but kept here to maximize struct packing.
+ signed m_sourceLine : 26;
+ mutable unsigned m_hasCachedSelectorText : 1;
+ unsigned m_parentIsRule : 1;
+ unsigned m_type : 4;
+ union {
+ CSSRule* m_parentRule;
+ CSSStyleSheet* m_parentStyleSheet;
+ };
+
+ void destroy();
+};
+
+} // namespace WebCore
+
+#endif // CSSRule_h
diff --git a/Source/WebCore/css/CSSRule.idl b/Source/WebCore/css/CSSRule.idl
new file mode 100644
index 000000000..0fda9efd4
--- /dev/null
+++ b/Source/WebCore/css/CSSRule.idl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface [
+ CustomMarkFunction,
+ GenerateIsReachable,
+ CustomToJS,
+ Polymorphic,
+ V8DependentLifetime
+ ] CSSRule {
+
+ // RuleType
+ const unsigned short UNKNOWN_RULE = 0;
+ const unsigned short STYLE_RULE = 1;
+ const unsigned short CHARSET_RULE = 2;
+ const unsigned short IMPORT_RULE = 3;
+ const unsigned short MEDIA_RULE = 4;
+ const unsigned short FONT_FACE_RULE = 5;
+ const unsigned short PAGE_RULE = 6;
+ const unsigned short WEBKIT_KEYFRAMES_RULE = 8;
+ const unsigned short WEBKIT_KEYFRAME_RULE = 9;
+ const unsigned short WEBKIT_REGION_RULE = 10;
+
+ readonly attribute unsigned short type;
+
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText
+ setter raises (DOMException);
+
+ readonly attribute CSSStyleSheet parentStyleSheet;
+ readonly attribute CSSRule parentRule;
+
+ };
+
+}
diff --git a/Source/WebCore/css/CSSRuleList.cpp b/Source/WebCore/css/CSSRuleList.cpp
new file mode 100644
index 000000000..6b080ef0b
--- /dev/null
+++ b/Source/WebCore/css/CSSRuleList.cpp
@@ -0,0 +1,111 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 "CSSRuleList.h"
+
+#include "CSSRule.h"
+#include "CSSStyleSheet.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+CSSRuleList::CSSRuleList()
+{
+}
+
+CSSRuleList::CSSRuleList(CSSStyleSheet* styleSheet, bool omitCharsetRules)
+ : m_styleSheet(styleSheet)
+{
+ if (styleSheet && omitCharsetRules) {
+ m_styleSheet = 0;
+ for (unsigned i = 0; i < styleSheet->length(); ++i) {
+ CSSRule* rule = styleSheet->item(i);
+ if (!rule->isCharsetRule())
+ append(static_cast<CSSRule*>(rule));
+ }
+ }
+}
+
+CSSRuleList::~CSSRuleList()
+{
+}
+
+unsigned CSSRuleList::length() const
+{
+ return m_styleSheet ? m_styleSheet->length() : m_lstCSSRules.size();
+}
+
+CSSRule* CSSRuleList::item(unsigned index) const
+{
+ if (m_styleSheet)
+ return m_styleSheet->item(index);
+
+ if (index < m_lstCSSRules.size())
+ return m_lstCSSRules[index].get();
+ return 0;
+}
+
+void CSSRuleList::deleteRule(unsigned index)
+{
+ ASSERT(!m_styleSheet);
+
+ if (index >= m_lstCSSRules.size())
+ return;
+
+ m_lstCSSRules.remove(index);
+}
+
+void CSSRuleList::append(CSSRule* rule)
+{
+ ASSERT(!m_styleSheet);
+
+ if (!rule)
+ return;
+
+ m_lstCSSRules.append(rule);
+}
+
+unsigned CSSRuleList::insertRule(CSSRule* rule, unsigned index)
+{
+ ASSERT(!m_styleSheet);
+
+ if (!rule || index > m_lstCSSRules.size())
+ return 0;
+
+ m_lstCSSRules.insert(index, rule);
+ return index;
+}
+
+String CSSRuleList::rulesText() const
+{
+ StringBuilder result;
+
+ for (unsigned index = 0; index < length(); ++index) {
+ result.append(" ");
+ result.append(item(index)->cssText());
+ result.append("\n");
+ }
+
+ return result.toString();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSRuleList.h b/Source/WebCore/css/CSSRuleList.h
new file mode 100644
index 000000000..ea52c8607
--- /dev/null
+++ b/Source/WebCore/css/CSSRuleList.h
@@ -0,0 +1,71 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2006 Apple Computer, Inc.
+ *
+ * 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 CSSRuleList_h
+#define CSSRuleList_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CSSRule;
+class CSSStyleSheet;
+
+class CSSRuleList : public RefCounted<CSSRuleList> {
+public:
+ static PassRefPtr<CSSRuleList> create(CSSStyleSheet* styleSheet, bool omitCharsetRules = false)
+ {
+ return adoptRef(new CSSRuleList(styleSheet, omitCharsetRules));
+ }
+ static PassRefPtr<CSSRuleList> create()
+ {
+ return adoptRef(new CSSRuleList);
+ }
+ ~CSSRuleList();
+
+ unsigned length() const;
+ CSSRule* item(unsigned index) const;
+
+ // FIXME: Not part of the CSSOM. Only used by @media and @-webkit-keyframes rules.
+ unsigned insertRule(CSSRule*, unsigned index);
+ void deleteRule(unsigned index);
+
+ void append(CSSRule*);
+
+ CSSStyleSheet* styleSheet() { return m_styleSheet.get(); }
+
+ String rulesText() const;
+
+private:
+ CSSRuleList();
+ CSSRuleList(CSSStyleSheet*, bool omitCharsetRules);
+
+ RefPtr<CSSStyleSheet> m_styleSheet;
+ Vector<RefPtr<CSSRule> > m_lstCSSRules; // FIXME: Want to eliminate, but used by IE rules() extension and still used by media rules.
+};
+
+} // namespace WebCore
+
+#endif // CSSRuleList_h
diff --git a/Source/WebCore/css/CSSRuleList.idl b/Source/WebCore/css/CSSRuleList.idl
new file mode 100644
index 000000000..ed86eaa26
--- /dev/null
+++ b/Source/WebCore/css/CSSRuleList.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 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 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface [
+ CustomIsReachable,
+ HasIndexGetter,
+ V8DependentLifetime
+ ] CSSRuleList {
+ readonly attribute unsigned long length;
+ CSSRule item(in [Optional=CallWithDefaultValue] unsigned long index);
+ };
+
+}
diff --git a/Source/WebCore/css/CSSSegmentedFontFace.cpp b/Source/WebCore/css/CSSSegmentedFontFace.cpp
new file mode 100644
index 000000000..f462c24c4
--- /dev/null
+++ b/Source/WebCore/css/CSSSegmentedFontFace.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 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 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.
+ */
+
+#include "config.h"
+#include "CSSSegmentedFontFace.h"
+
+#include "CSSFontFace.h"
+#include "CSSFontFaceSource.h"
+#include "CSSFontSelector.h"
+#include "Document.h"
+#include "FontDescription.h"
+#include "SegmentedFontData.h"
+#include "SimpleFontData.h"
+
+namespace WebCore {
+
+CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector* fontSelector)
+ : m_fontSelector(fontSelector)
+{
+}
+
+CSSSegmentedFontFace::~CSSSegmentedFontFace()
+{
+ pruneTable();
+ unsigned size = m_fontFaces.size();
+ for (unsigned i = 0; i < size; i++)
+ m_fontFaces[i]->removedFromSegmentedFontFace(this);
+}
+
+void CSSSegmentedFontFace::pruneTable()
+{
+ // Make sure the glyph page tree prunes out all uses of this custom font.
+ if (m_fontDataTable.isEmpty())
+ return;
+
+ m_fontDataTable.clear();
+}
+
+bool CSSSegmentedFontFace::isValid() const
+{
+ // Valid if at least one font face is valid.
+ unsigned size = m_fontFaces.size();
+ for (unsigned i = 0; i < size; i++) {
+ if (m_fontFaces[i]->isValid())
+ return true;
+ }
+ return false;
+}
+
+void CSSSegmentedFontFace::fontLoaded(CSSFontFace*)
+{
+ pruneTable();
+}
+
+void CSSSegmentedFontFace::appendFontFace(PassRefPtr<CSSFontFace> fontFace)
+{
+ pruneTable();
+ fontFace->addedToSegmentedFontFace(this);
+ m_fontFaces.append(fontFace);
+}
+
+FontData* CSSSegmentedFontFace::getFontData(const FontDescription& fontDescription)
+{
+ if (!isValid())
+ return 0;
+
+ FontTraitsMask desiredTraitsMask = fontDescription.traitsMask();
+ unsigned hashKey = ((fontDescription.computedPixelSize() + 1) << (FontTraitsMaskWidth + 1)) | ((fontDescription.orientation() == Vertical ? 1 : 0) << FontTraitsMaskWidth) | desiredTraitsMask;
+
+ SegmentedFontData*& fontData = m_fontDataTable.add(hashKey, 0).first->second;
+ if (fontData)
+ return fontData;
+
+ OwnPtr<SegmentedFontData> newFontData = adoptPtr(new SegmentedFontData);
+
+ unsigned size = m_fontFaces.size();
+ for (unsigned i = 0; i < size; i++) {
+ if (!m_fontFaces[i]->isValid())
+ continue;
+ FontTraitsMask traitsMask = m_fontFaces[i]->traitsMask();
+ bool syntheticBold = !(traitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask)) && (desiredTraitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask));
+ bool syntheticItalic = !(traitsMask & FontStyleItalicMask) && (desiredTraitsMask & FontStyleItalicMask);
+ if (const SimpleFontData* faceFontData = m_fontFaces[i]->getFontData(fontDescription, syntheticBold, syntheticItalic)) {
+ ASSERT(!faceFontData->isSegmented());
+ const Vector<CSSFontFace::UnicodeRange>& ranges = m_fontFaces[i]->ranges();
+ unsigned numRanges = ranges.size();
+ if (!numRanges)
+ newFontData->appendRange(FontDataRange(0, 0x7FFFFFFF, faceFontData));
+ else {
+ for (unsigned j = 0; j < numRanges; ++j)
+ newFontData->appendRange(FontDataRange(ranges[j].from(), ranges[j].to(), faceFontData));
+ }
+ }
+ }
+ if (newFontData->numRanges()) {
+ ASSERT(m_fontSelector->document());
+ if (Document* document = m_fontSelector->document()) {
+ fontData = newFontData.get();
+ document->registerCustomFont(newFontData.release());
+ }
+ }
+
+ return fontData;
+}
+
+}
diff --git a/Source/WebCore/css/CSSSegmentedFontFace.h b/Source/WebCore/css/CSSSegmentedFontFace.h
new file mode 100644
index 000000000..3efc47a63
--- /dev/null
+++ b/Source/WebCore/css/CSSSegmentedFontFace.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 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 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 CSSSegmentedFontFace_h
+#define CSSSegmentedFontFace_h
+
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class CSSFontFace;
+class CSSFontSelector;
+class FontData;
+class FontDescription;
+class SegmentedFontData;
+
+class CSSSegmentedFontFace : public RefCounted<CSSSegmentedFontFace> {
+public:
+ static PassRefPtr<CSSSegmentedFontFace> create(CSSFontSelector* selector) { return adoptRef(new CSSSegmentedFontFace(selector)); }
+ ~CSSSegmentedFontFace();
+
+ CSSFontSelector* fontSelector() const { return m_fontSelector; }
+
+ void fontLoaded(CSSFontFace*);
+
+ void appendFontFace(PassRefPtr<CSSFontFace>);
+
+ FontData* getFontData(const FontDescription&);
+
+private:
+ CSSSegmentedFontFace(CSSFontSelector*);
+
+ void pruneTable();
+ bool isValid() const;
+
+ CSSFontSelector* m_fontSelector;
+ HashMap<unsigned, SegmentedFontData*> m_fontDataTable;
+ Vector<RefPtr<CSSFontFace>, 1> m_fontFaces;
+};
+
+} // namespace WebCore
+
+#endif // CSSSegmentedFontFace_h
diff --git a/Source/WebCore/css/CSSSelector.cpp b/Source/WebCore/css/CSSSelector.cpp
new file mode 100644
index 000000000..be28c601b
--- /dev/null
+++ b/Source/WebCore/css/CSSSelector.cpp
@@ -0,0 +1,778 @@
+/*
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * 1999 Waldo Bastian (bastian@kde.org)
+ * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch)
+ * 2001-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2010 Google 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 "CSSSelector.h"
+
+#include "CSSOMUtils.h"
+#include "CSSSelectorList.h"
+#include "HTMLNames.h"
+#include <wtf/Assertions.h>
+#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+void CSSSelector::createRareData()
+{
+ if (m_hasRareData)
+ return;
+ // Move the value to the rare data stucture.
+ m_data.m_rareData = new RareData(adoptRef(m_data.m_value));
+ m_hasRareData = true;
+}
+
+unsigned CSSSelector::specificity() const
+{
+ // make sure the result doesn't overflow
+ static const unsigned maxValueMask = 0xffffff;
+ unsigned total = 0;
+ for (const CSSSelector* selector = this; selector; selector = selector->tagHistory()) {
+ if (selector->m_isForPage)
+ return (total + selector->specificityForPage()) & maxValueMask;
+ total = (total + selector->specificityForOneSelector()) & maxValueMask;
+ }
+ return total;
+}
+
+inline unsigned CSSSelector::specificityForOneSelector() const
+{
+ // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
+ // isn't quite correct.
+ unsigned s = (m_tag.localName() == starAtom ? 0 : 1);
+ switch (m_match) {
+ case Id:
+ s += 0x10000;
+ break;
+ case Exact:
+ case Class:
+ case Set:
+ case List:
+ case Hyphen:
+ case PseudoClass:
+ case PseudoElement:
+ case Contain:
+ case Begin:
+ case End:
+ // FIXME: PsuedoAny should base the specificity on the sub-selectors.
+ // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html
+ if (pseudoType() == PseudoNot) {
+ ASSERT(selectorList());
+ s += selectorList()->first()->specificityForOneSelector();
+ } else
+ s += 0x100;
+ case None:
+ break;
+ }
+ return s;
+}
+
+unsigned CSSSelector::specificityForPage() const
+{
+ // See http://dev.w3.org/csswg/css3-page/#cascading-and-page-context
+ unsigned s = (m_tag.localName() == starAtom ? 0 : 4);
+
+ switch (pseudoType()) {
+ case PseudoFirstPage:
+ s += 2;
+ break;
+ case PseudoLeftPage:
+ case PseudoRightPage:
+ s += 1;
+ break;
+ case PseudoNotParsed:
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return s;
+}
+
+PseudoId CSSSelector::pseudoId(PseudoType type)
+{
+ switch (type) {
+ case PseudoFirstLine:
+ return FIRST_LINE;
+ case PseudoFirstLetter:
+ return FIRST_LETTER;
+ case PseudoSelection:
+ return SELECTION;
+ case PseudoBefore:
+ return BEFORE;
+ case PseudoAfter:
+ return AFTER;
+ case PseudoScrollbar:
+ return SCROLLBAR;
+ case PseudoScrollbarButton:
+ return SCROLLBAR_BUTTON;
+ case PseudoScrollbarCorner:
+ return SCROLLBAR_CORNER;
+ case PseudoScrollbarThumb:
+ return SCROLLBAR_THUMB;
+ case PseudoScrollbarTrack:
+ return SCROLLBAR_TRACK;
+ case PseudoScrollbarTrackPiece:
+ return SCROLLBAR_TRACK_PIECE;
+ case PseudoResizer:
+ return RESIZER;
+#if ENABLE(FULLSCREEN_API)
+ case PseudoFullScreen:
+ return FULL_SCREEN;
+ case PseudoFullScreenDocument:
+ return FULL_SCREEN_DOCUMENT;
+ case PseudoFullScreenAncestor:
+ return FULL_SCREEN_ANCESTOR;
+ case PseudoAnimatingFullScreenTransition:
+ return ANIMATING_FULL_SCREEN_TRANSITION;
+#endif
+
+ case PseudoInputListButton:
+#if ENABLE(DATALIST)
+ return INPUT_LIST_BUTTON;
+#endif
+ case PseudoUnknown:
+ case PseudoEmpty:
+ case PseudoFirstChild:
+ case PseudoFirstOfType:
+ case PseudoLastChild:
+ case PseudoLastOfType:
+ case PseudoOnlyChild:
+ case PseudoOnlyOfType:
+ case PseudoNthChild:
+ case PseudoNthOfType:
+ case PseudoNthLastChild:
+ case PseudoNthLastOfType:
+ case PseudoLink:
+ case PseudoVisited:
+ case PseudoAny:
+ case PseudoAnyLink:
+ case PseudoAutofill:
+ case PseudoHover:
+ case PseudoDrag:
+ case PseudoFocus:
+ case PseudoActive:
+ case PseudoChecked:
+ case PseudoEnabled:
+ case PseudoFullPageMedia:
+ case PseudoDefault:
+ case PseudoDisabled:
+ case PseudoOptional:
+ case PseudoRequired:
+ case PseudoReadOnly:
+ case PseudoReadWrite:
+ case PseudoValid:
+ case PseudoInvalid:
+ case PseudoIndeterminate:
+ case PseudoTarget:
+ case PseudoLang:
+ case PseudoNot:
+ case PseudoRoot:
+ case PseudoScrollbarBack:
+ case PseudoScrollbarForward:
+ case PseudoWindowInactive:
+ case PseudoCornerPresent:
+ case PseudoDecrement:
+ case PseudoIncrement:
+ case PseudoHorizontal:
+ case PseudoVertical:
+ case PseudoStart:
+ case PseudoEnd:
+ case PseudoDoubleButton:
+ case PseudoSingleButton:
+ case PseudoNoButton:
+ case PseudoFirstPage:
+ case PseudoLeftPage:
+ case PseudoRightPage:
+ case PseudoInRange:
+ case PseudoOutOfRange:
+ return NOPSEUDO;
+ case PseudoNotParsed:
+ ASSERT_NOT_REACHED();
+ return NOPSEUDO;
+ }
+
+ ASSERT_NOT_REACHED();
+ return NOPSEUDO;
+}
+
+static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap()
+{
+ DEFINE_STATIC_LOCAL(AtomicString, active, ("active"));
+ DEFINE_STATIC_LOCAL(AtomicString, after, ("after"));
+ DEFINE_STATIC_LOCAL(AtomicString, any, ("-webkit-any("));
+ DEFINE_STATIC_LOCAL(AtomicString, anyLink, ("-webkit-any-link"));
+ DEFINE_STATIC_LOCAL(AtomicString, autofill, ("-webkit-autofill"));
+ DEFINE_STATIC_LOCAL(AtomicString, before, ("before"));
+ DEFINE_STATIC_LOCAL(AtomicString, checked, ("checked"));
+ DEFINE_STATIC_LOCAL(AtomicString, defaultString, ("default"));
+ DEFINE_STATIC_LOCAL(AtomicString, disabled, ("disabled"));
+ DEFINE_STATIC_LOCAL(AtomicString, readOnly, ("read-only"));
+ DEFINE_STATIC_LOCAL(AtomicString, readWrite, ("read-write"));
+ DEFINE_STATIC_LOCAL(AtomicString, valid, ("valid"));
+ DEFINE_STATIC_LOCAL(AtomicString, invalid, ("invalid"));
+ DEFINE_STATIC_LOCAL(AtomicString, drag, ("-webkit-drag"));
+ DEFINE_STATIC_LOCAL(AtomicString, dragAlias, ("-khtml-drag")); // was documented with this name in Apple documentation, so keep an alia
+ DEFINE_STATIC_LOCAL(AtomicString, empty, ("empty"));
+ DEFINE_STATIC_LOCAL(AtomicString, enabled, ("enabled"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstChild, ("first-child"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstLetter, ("first-letter"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstLine, ("first-line"));
+ DEFINE_STATIC_LOCAL(AtomicString, firstOfType, ("first-of-type"));
+ DEFINE_STATIC_LOCAL(AtomicString, fullPageMedia, ("-webkit-full-page-media"));
+ DEFINE_STATIC_LOCAL(AtomicString, nthChild, ("nth-child("));
+ DEFINE_STATIC_LOCAL(AtomicString, nthOfType, ("nth-of-type("));
+ DEFINE_STATIC_LOCAL(AtomicString, nthLastChild, ("nth-last-child("));
+ DEFINE_STATIC_LOCAL(AtomicString, nthLastOfType, ("nth-last-of-type("));
+ DEFINE_STATIC_LOCAL(AtomicString, focus, ("focus"));
+ DEFINE_STATIC_LOCAL(AtomicString, hover, ("hover"));
+ DEFINE_STATIC_LOCAL(AtomicString, indeterminate, ("indeterminate"));
+#if ENABLE(DATALIST)
+ DEFINE_STATIC_LOCAL(AtomicString, inputListButton, ("-webkit-input-list-button"));
+#endif
+ DEFINE_STATIC_LOCAL(AtomicString, lastChild, ("last-child"));
+ DEFINE_STATIC_LOCAL(AtomicString, lastOfType, ("last-of-type"));
+ DEFINE_STATIC_LOCAL(AtomicString, link, ("link"));
+ DEFINE_STATIC_LOCAL(AtomicString, lang, ("lang("));
+ DEFINE_STATIC_LOCAL(AtomicString, notStr, ("not("));
+ DEFINE_STATIC_LOCAL(AtomicString, onlyChild, ("only-child"));
+ DEFINE_STATIC_LOCAL(AtomicString, onlyOfType, ("only-of-type"));
+ DEFINE_STATIC_LOCAL(AtomicString, optional, ("optional"));
+ DEFINE_STATIC_LOCAL(AtomicString, required, ("required"));
+ DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer"));
+ DEFINE_STATIC_LOCAL(AtomicString, root, ("root"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbar, ("-webkit-scrollbar"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarButton, ("-webkit-scrollbar-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarCorner, ("-webkit-scrollbar-corner"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarThumb, ("-webkit-scrollbar-thumb"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrack, ("-webkit-scrollbar-track"));
+ DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrackPiece, ("-webkit-scrollbar-track-piece"));
+ DEFINE_STATIC_LOCAL(AtomicString, selection, ("selection"));
+ DEFINE_STATIC_LOCAL(AtomicString, target, ("target"));
+ DEFINE_STATIC_LOCAL(AtomicString, visited, ("visited"));
+ DEFINE_STATIC_LOCAL(AtomicString, windowInactive, ("window-inactive"));
+ DEFINE_STATIC_LOCAL(AtomicString, decrement, ("decrement"));
+ DEFINE_STATIC_LOCAL(AtomicString, increment, ("increment"));
+ DEFINE_STATIC_LOCAL(AtomicString, start, ("start"));
+ DEFINE_STATIC_LOCAL(AtomicString, end, ("end"));
+ DEFINE_STATIC_LOCAL(AtomicString, horizontal, ("horizontal"));
+ DEFINE_STATIC_LOCAL(AtomicString, vertical, ("vertical"));
+ DEFINE_STATIC_LOCAL(AtomicString, doubleButton, ("double-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, singleButton, ("single-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, noButton, ("no-button"));
+ DEFINE_STATIC_LOCAL(AtomicString, cornerPresent, ("corner-present"));
+ // Paged Media pseudo-classes
+ DEFINE_STATIC_LOCAL(AtomicString, firstPage, ("first"));
+ DEFINE_STATIC_LOCAL(AtomicString, leftPage, ("left"));
+ DEFINE_STATIC_LOCAL(AtomicString, rightPage, ("right"));
+#if ENABLE(FULLSCREEN_API)
+ DEFINE_STATIC_LOCAL(AtomicString, fullScreen, ("-webkit-full-screen"));
+ DEFINE_STATIC_LOCAL(AtomicString, fullScreenDocument, ("-webkit-full-screen-document"));
+ DEFINE_STATIC_LOCAL(AtomicString, fullScreenAncestor, ("-webkit-full-screen-ancestor"));
+ DEFINE_STATIC_LOCAL(AtomicString, animatingFullScreenTransition, ("-webkit-animating-full-screen-transition"));
+#endif
+ DEFINE_STATIC_LOCAL(AtomicString, inRange, ("in-range"));
+ DEFINE_STATIC_LOCAL(AtomicString, outOfRange, ("out-of-range"));
+
+ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = 0;
+ if (!nameToPseudoType) {
+ nameToPseudoType = new HashMap<AtomicStringImpl*, CSSSelector::PseudoType>;
+ nameToPseudoType->set(active.impl(), CSSSelector::PseudoActive);
+ nameToPseudoType->set(after.impl(), CSSSelector::PseudoAfter);
+ nameToPseudoType->set(anyLink.impl(), CSSSelector::PseudoAnyLink);
+ nameToPseudoType->set(any.impl(), CSSSelector::PseudoAny);
+ nameToPseudoType->set(autofill.impl(), CSSSelector::PseudoAutofill);
+ nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore);
+ nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked);
+ nameToPseudoType->set(defaultString.impl(), CSSSelector::PseudoDefault);
+ nameToPseudoType->set(disabled.impl(), CSSSelector::PseudoDisabled);
+ nameToPseudoType->set(readOnly.impl(), CSSSelector::PseudoReadOnly);
+ nameToPseudoType->set(readWrite.impl(), CSSSelector::PseudoReadWrite);
+ nameToPseudoType->set(valid.impl(), CSSSelector::PseudoValid);
+ nameToPseudoType->set(invalid.impl(), CSSSelector::PseudoInvalid);
+ nameToPseudoType->set(drag.impl(), CSSSelector::PseudoDrag);
+ nameToPseudoType->set(dragAlias.impl(), CSSSelector::PseudoDrag);
+ nameToPseudoType->set(enabled.impl(), CSSSelector::PseudoEnabled);
+ nameToPseudoType->set(empty.impl(), CSSSelector::PseudoEmpty);
+ nameToPseudoType->set(firstChild.impl(), CSSSelector::PseudoFirstChild);
+ nameToPseudoType->set(fullPageMedia.impl(), CSSSelector::PseudoFullPageMedia);
+#if ENABLE(DATALIST)
+ nameToPseudoType->set(inputListButton.impl(), CSSSelector::PseudoInputListButton);
+#endif
+ nameToPseudoType->set(lastChild.impl(), CSSSelector::PseudoLastChild);
+ nameToPseudoType->set(lastOfType.impl(), CSSSelector::PseudoLastOfType);
+ nameToPseudoType->set(onlyChild.impl(), CSSSelector::PseudoOnlyChild);
+ nameToPseudoType->set(onlyOfType.impl(), CSSSelector::PseudoOnlyOfType);
+ nameToPseudoType->set(firstLetter.impl(), CSSSelector::PseudoFirstLetter);
+ nameToPseudoType->set(firstLine.impl(), CSSSelector::PseudoFirstLine);
+ nameToPseudoType->set(firstOfType.impl(), CSSSelector::PseudoFirstOfType);
+ nameToPseudoType->set(focus.impl(), CSSSelector::PseudoFocus);
+ nameToPseudoType->set(hover.impl(), CSSSelector::PseudoHover);
+ nameToPseudoType->set(indeterminate.impl(), CSSSelector::PseudoIndeterminate);
+ nameToPseudoType->set(link.impl(), CSSSelector::PseudoLink);
+ nameToPseudoType->set(lang.impl(), CSSSelector::PseudoLang);
+ nameToPseudoType->set(notStr.impl(), CSSSelector::PseudoNot);
+ nameToPseudoType->set(nthChild.impl(), CSSSelector::PseudoNthChild);
+ nameToPseudoType->set(nthOfType.impl(), CSSSelector::PseudoNthOfType);
+ nameToPseudoType->set(nthLastChild.impl(), CSSSelector::PseudoNthLastChild);
+ nameToPseudoType->set(nthLastOfType.impl(), CSSSelector::PseudoNthLastOfType);
+ nameToPseudoType->set(root.impl(), CSSSelector::PseudoRoot);
+ nameToPseudoType->set(windowInactive.impl(), CSSSelector::PseudoWindowInactive);
+ nameToPseudoType->set(decrement.impl(), CSSSelector::PseudoDecrement);
+ nameToPseudoType->set(increment.impl(), CSSSelector::PseudoIncrement);
+ nameToPseudoType->set(start.impl(), CSSSelector::PseudoStart);
+ nameToPseudoType->set(end.impl(), CSSSelector::PseudoEnd);
+ nameToPseudoType->set(horizontal.impl(), CSSSelector::PseudoHorizontal);
+ nameToPseudoType->set(vertical.impl(), CSSSelector::PseudoVertical);
+ nameToPseudoType->set(doubleButton.impl(), CSSSelector::PseudoDoubleButton);
+ nameToPseudoType->set(singleButton.impl(), CSSSelector::PseudoSingleButton);
+ nameToPseudoType->set(noButton.impl(), CSSSelector::PseudoNoButton);
+ nameToPseudoType->set(optional.impl(), CSSSelector::PseudoOptional);
+ nameToPseudoType->set(required.impl(), CSSSelector::PseudoRequired);
+ nameToPseudoType->set(resizer.impl(), CSSSelector::PseudoResizer);
+ nameToPseudoType->set(scrollbar.impl(), CSSSelector::PseudoScrollbar);
+ nameToPseudoType->set(scrollbarButton.impl(), CSSSelector::PseudoScrollbarButton);
+ nameToPseudoType->set(scrollbarCorner.impl(), CSSSelector::PseudoScrollbarCorner);
+ nameToPseudoType->set(scrollbarThumb.impl(), CSSSelector::PseudoScrollbarThumb);
+ nameToPseudoType->set(scrollbarTrack.impl(), CSSSelector::PseudoScrollbarTrack);
+ nameToPseudoType->set(scrollbarTrackPiece.impl(), CSSSelector::PseudoScrollbarTrackPiece);
+ nameToPseudoType->set(cornerPresent.impl(), CSSSelector::PseudoCornerPresent);
+ nameToPseudoType->set(selection.impl(), CSSSelector::PseudoSelection);
+ nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget);
+ nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited);
+ nameToPseudoType->set(firstPage.impl(), CSSSelector::PseudoFirstPage);
+ nameToPseudoType->set(leftPage.impl(), CSSSelector::PseudoLeftPage);
+ nameToPseudoType->set(rightPage.impl(), CSSSelector::PseudoRightPage);
+#if ENABLE(FULLSCREEN_API)
+ nameToPseudoType->set(fullScreen.impl(), CSSSelector::PseudoFullScreen);
+ nameToPseudoType->set(fullScreenDocument.impl(), CSSSelector::PseudoFullScreenDocument);
+ nameToPseudoType->set(fullScreenAncestor.impl(), CSSSelector::PseudoFullScreenAncestor);
+ nameToPseudoType->set(animatingFullScreenTransition.impl(), CSSSelector::PseudoAnimatingFullScreenTransition);
+#endif
+ nameToPseudoType->set(inRange.impl(), CSSSelector::PseudoInRange);
+ nameToPseudoType->set(outOfRange.impl(), CSSSelector::PseudoOutOfRange);
+ }
+ return nameToPseudoType;
+}
+
+CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name)
+{
+ if (name.isNull())
+ return PseudoUnknown;
+ HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseudoTypeMap();
+ HashMap<AtomicStringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoType->find(name.impl());
+ return slot == nameToPseudoType->end() ? PseudoUnknown : slot->second;
+}
+
+bool CSSSelector::isUnknownPseudoType(const AtomicString& name)
+{
+ return parsePseudoType(name) == PseudoUnknown;
+}
+
+void CSSSelector::extractPseudoType() const
+{
+ if (m_match != PseudoClass && m_match != PseudoElement && m_match != PagePseudoClass)
+ return;
+
+ m_pseudoType = parsePseudoType(value());
+
+ bool element = false; // pseudo-element
+ bool compat = false; // single colon compatbility mode
+ bool isPagePseudoClass = false; // Page pseudo-class
+
+ switch (m_pseudoType) {
+ case PseudoAfter:
+ case PseudoBefore:
+ case PseudoFirstLetter:
+ case PseudoFirstLine:
+ compat = true;
+ case PseudoInputListButton:
+ case PseudoResizer:
+ case PseudoScrollbar:
+ case PseudoScrollbarCorner:
+ case PseudoScrollbarButton:
+ case PseudoScrollbarThumb:
+ case PseudoScrollbarTrack:
+ case PseudoScrollbarTrackPiece:
+ case PseudoSelection:
+ element = true;
+ break;
+ case PseudoUnknown:
+ case PseudoEmpty:
+ case PseudoFirstChild:
+ case PseudoFirstOfType:
+ case PseudoLastChild:
+ case PseudoLastOfType:
+ case PseudoOnlyChild:
+ case PseudoOnlyOfType:
+ case PseudoNthChild:
+ case PseudoNthOfType:
+ case PseudoNthLastChild:
+ case PseudoNthLastOfType:
+ case PseudoLink:
+ case PseudoVisited:
+ case PseudoAny:
+ case PseudoAnyLink:
+ case PseudoAutofill:
+ case PseudoHover:
+ case PseudoDrag:
+ case PseudoFocus:
+ case PseudoActive:
+ case PseudoChecked:
+ case PseudoEnabled:
+ case PseudoFullPageMedia:
+ case PseudoDefault:
+ case PseudoDisabled:
+ case PseudoOptional:
+ case PseudoRequired:
+ case PseudoReadOnly:
+ case PseudoReadWrite:
+ case PseudoValid:
+ case PseudoInvalid:
+ case PseudoIndeterminate:
+ case PseudoTarget:
+ case PseudoLang:
+ case PseudoNot:
+ case PseudoRoot:
+ case PseudoScrollbarBack:
+ case PseudoScrollbarForward:
+ case PseudoWindowInactive:
+ case PseudoCornerPresent:
+ case PseudoDecrement:
+ case PseudoIncrement:
+ case PseudoHorizontal:
+ case PseudoVertical:
+ case PseudoStart:
+ case PseudoEnd:
+ case PseudoDoubleButton:
+ case PseudoSingleButton:
+ case PseudoNoButton:
+ case PseudoNotParsed:
+#if ENABLE(FULLSCREEN_API)
+ case PseudoFullScreen:
+ case PseudoFullScreenDocument:
+ case PseudoFullScreenAncestor:
+ case PseudoAnimatingFullScreenTransition:
+#endif
+ case PseudoInRange:
+ case PseudoOutOfRange:
+ break;
+ case PseudoFirstPage:
+ case PseudoLeftPage:
+ case PseudoRightPage:
+ isPagePseudoClass = true;
+ break;
+ }
+
+ bool matchPagePseudoClass = (m_match == PagePseudoClass);
+ if (matchPagePseudoClass != isPagePseudoClass)
+ m_pseudoType = PseudoUnknown;
+ else if (m_match == PseudoClass && element) {
+ if (!compat)
+ m_pseudoType = PseudoUnknown;
+ else
+ m_match = PseudoElement;
+ } else if (m_match == PseudoElement && !element)
+ m_pseudoType = PseudoUnknown;
+}
+
+bool CSSSelector::operator==(const CSSSelector& other)
+{
+ const CSSSelector* sel1 = this;
+ const CSSSelector* sel2 = &other;
+
+ while (sel1 && sel2) {
+ if (sel1->m_tag != sel2->m_tag || sel1->attribute() != sel2->attribute() ||
+ sel1->relation() != sel2->relation() || sel1->m_match != sel2->m_match ||
+ sel1->value() != sel2->value() ||
+ sel1->pseudoType() != sel2->pseudoType() ||
+ sel1->argument() != sel2->argument())
+ return false;
+ sel1 = sel1->tagHistory();
+ sel2 = sel2->tagHistory();
+ }
+
+ if (sel1 || sel2)
+ return false;
+
+ return true;
+}
+
+String CSSSelector::selectorText() const
+{
+ String str = "";
+
+ const AtomicString& prefix = m_tag.prefix();
+ const AtomicString& localName = m_tag.localName();
+ if (m_match == CSSSelector::None || !prefix.isNull() || localName != starAtom) {
+ if (prefix.isNull())
+ str = localName;
+ else {
+ str = prefix.string();
+ str.append("|");
+ str.append(localName);
+ }
+ }
+
+ const CSSSelector* cs = this;
+ while (true) {
+ if (cs->m_match == CSSSelector::Id) {
+ str += "#";
+ serializeIdentifier(cs->value(), str);
+ } else if (cs->m_match == CSSSelector::Class) {
+ str += ".";
+ serializeIdentifier(cs->value(), str);
+ } else if (cs->m_match == CSSSelector::PseudoClass || cs->m_match == CSSSelector::PagePseudoClass) {
+ str += ":";
+ str += cs->value();
+
+ switch (cs->pseudoType()) {
+ case PseudoNot:
+ ASSERT(cs->selectorList());
+ str += cs->selectorList()->first()->selectorText();
+ str += ")";
+ break;
+ case PseudoLang:
+ case PseudoNthChild:
+ case PseudoNthLastChild:
+ case PseudoNthOfType:
+ case PseudoNthLastOfType:
+ str += cs->argument();
+ str += ")";
+ break;
+ case PseudoAny: {
+ CSSSelector* firstSubSelector = cs->selectorList()->first();
+ for (CSSSelector* subSelector = firstSubSelector; subSelector; subSelector = CSSSelectorList::next(subSelector)) {
+ if (subSelector != firstSubSelector)
+ str += ",";
+ str += subSelector->selectorText();
+ }
+ str += ")";
+ break;
+ }
+ default:
+ break;
+ }
+ } else if (cs->m_match == CSSSelector::PseudoElement) {
+ str += "::";
+ str += cs->value();
+ } else if (cs->isAttributeSelector()) {
+ str += "[";
+ const AtomicString& prefix = cs->attribute().prefix();
+ if (!prefix.isNull()) {
+ str.append(prefix);
+ str.append("|");
+ }
+ str += cs->attribute().localName();
+ switch (cs->m_match) {
+ case CSSSelector::Exact:
+ str += "=";
+ break;
+ case CSSSelector::Set:
+ // set has no operator or value, just the attrName
+ str += "]";
+ break;
+ case CSSSelector::List:
+ str += "~=";
+ break;
+ case CSSSelector::Hyphen:
+ str += "|=";
+ break;
+ case CSSSelector::Begin:
+ str += "^=";
+ break;
+ case CSSSelector::End:
+ str += "$=";
+ break;
+ case CSSSelector::Contain:
+ str += "*=";
+ break;
+ default:
+ break;
+ }
+ if (cs->m_match != CSSSelector::Set) {
+ serializeString(cs->value(), str);
+ str += "]";
+ }
+ }
+ if (cs->relation() != CSSSelector::SubSelector || !cs->tagHistory())
+ break;
+ cs = cs->tagHistory();
+ }
+
+ if (CSSSelector* tagHistory = cs->tagHistory()) {
+ String tagHistoryText = tagHistory->selectorText();
+ if (cs->relation() == CSSSelector::DirectAdjacent)
+ str = tagHistoryText + " + " + str;
+ else if (cs->relation() == CSSSelector::IndirectAdjacent)
+ str = tagHistoryText + " ~ " + str;
+ else if (cs->relation() == CSSSelector::Child)
+ str = tagHistoryText + " > " + str;
+ else if (cs->relation() == CSSSelector::ShadowDescendant)
+ str = tagHistoryText + str;
+ else
+ // Descendant
+ str = tagHistoryText + " " + str;
+ }
+
+ return str;
+}
+
+void CSSSelector::setAttribute(const QualifiedName& value)
+{
+ createRareData();
+ m_data.m_rareData->m_attribute = value;
+}
+
+void CSSSelector::setArgument(const AtomicString& value)
+{
+ createRareData();
+ m_data.m_rareData->m_argument = value;
+}
+
+void CSSSelector::setSelectorList(PassOwnPtr<CSSSelectorList> selectorList)
+{
+ createRareData();
+ m_data.m_rareData->m_selectorList = selectorList;
+}
+
+bool CSSSelector::parseNth()
+{
+ if (!m_hasRareData)
+ return false;
+ if (m_parsedNth)
+ return true;
+ m_parsedNth = m_data.m_rareData->parseNth();
+ return m_parsedNth;
+}
+
+bool CSSSelector::matchNth(int count)
+{
+ ASSERT(m_hasRareData);
+ return m_data.m_rareData->matchNth(count);
+}
+
+bool CSSSelector::isSimple() const
+{
+ if (selectorList() || tagHistory() || matchesPseudoElement())
+ return false;
+
+ int numConditions = 0;
+
+ // hasTag() cannot be be used here because namespace may not be nullAtom.
+ // Example:
+ // @namespace "http://www.w3.org/2000/svg";
+ // svg:not(:root) { ...
+ if (m_tag != starAtom)
+ numConditions++;
+
+ if (m_match == Id || m_match == Class || m_match == PseudoClass)
+ numConditions++;
+
+ if (m_hasRareData && m_data.m_rareData->m_attribute != anyQName())
+ numConditions++;
+
+ // numConditions is 0 for a universal selector.
+ // numConditions is 1 for other simple selectors.
+ return numConditions <= 1;
+}
+
+CSSSelector::RareData::RareData(PassRefPtr<AtomicStringImpl> value)
+ : m_value(value.leakRef())
+ , m_a(0)
+ , m_b(0)
+ , m_attribute(anyQName())
+ , m_argument(nullAtom)
+{
+}
+
+CSSSelector::RareData::~RareData()
+{
+ if (m_value)
+ m_value->deref();
+}
+
+// a helper function for parsing nth-arguments
+bool CSSSelector::RareData::parseNth()
+{
+ String argument = m_argument.lower();
+
+ if (argument.isEmpty())
+ return false;
+
+ m_a = 0;
+ m_b = 0;
+ if (argument == "odd") {
+ m_a = 2;
+ m_b = 1;
+ } else if (argument == "even") {
+ m_a = 2;
+ m_b = 0;
+ } else {
+ size_t n = argument.find('n');
+ if (n != notFound) {
+ if (argument[0] == '-') {
+ if (n == 1)
+ m_a = -1; // -n == -1n
+ else
+ m_a = argument.substring(0, n).toInt();
+ } else if (!n)
+ m_a = 1; // n == 1n
+ else
+ m_a = argument.substring(0, n).toInt();
+
+ size_t p = argument.find('+', n);
+ if (p != notFound)
+ m_b = argument.substring(p + 1, argument.length() - p - 1).toInt();
+ else {
+ p = argument.find('-', n);
+ if (p != notFound)
+ m_b = -argument.substring(p + 1, argument.length() - p - 1).toInt();
+ }
+ } else
+ m_b = argument.toInt();
+ }
+ return true;
+}
+
+// a helper function for checking nth-arguments
+bool CSSSelector::RareData::matchNth(int count)
+{
+ if (!m_a)
+ return count == m_b;
+ else if (m_a > 0) {
+ if (count < m_b)
+ return false;
+ return (count - m_b) % m_a == 0;
+ } else {
+ if (count > m_b)
+ return false;
+ return (m_b - count) % (-m_a) == 0;
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h
new file mode 100644
index 000000000..afd52def9
--- /dev/null
+++ b/Source/WebCore/css/CSSSelector.h
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * 1999 Waldo Bastian (bastian@kde.org)
+ * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 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 CSSSelector_h
+#define CSSSelector_h
+
+#include "QualifiedName.h"
+#include "RenderStyleConstants.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+ class CSSSelectorList;
+
+ // this class represents a selector for a StyleRule
+ class CSSSelector {
+ WTF_MAKE_NONCOPYABLE(CSSSelector); WTF_MAKE_FAST_ALLOCATED;
+ public:
+ CSSSelector()
+ : m_relation(Descendant)
+ , m_match(None)
+ , m_pseudoType(PseudoNotParsed)
+ , m_parsedNth(false)
+ , m_isLastInSelectorList(false)
+ , m_isLastInTagHistory(true)
+ , m_hasRareData(false)
+ , m_isForPage(false)
+ , m_tag(anyQName())
+ {
+ }
+
+ CSSSelector(const QualifiedName& qName)
+ : m_relation(Descendant)
+ , m_match(None)
+ , m_pseudoType(PseudoNotParsed)
+ , m_parsedNth(false)
+ , m_isLastInSelectorList(false)
+ , m_isLastInTagHistory(true)
+ , m_hasRareData(false)
+ , m_isForPage(false)
+ , m_tag(qName)
+ {
+ }
+
+ ~CSSSelector()
+ {
+ if (m_hasRareData)
+ delete m_data.m_rareData;
+ else if (m_data.m_value)
+ m_data.m_value->deref();
+ }
+
+ /**
+ * Re-create selector text from selector's data
+ */
+ String selectorText() const;
+
+ // checks if the 2 selectors (including sub selectors) agree.
+ bool operator==(const CSSSelector&);
+
+ // tag == -1 means apply to all elements (Selector = *)
+
+ unsigned specificity() const;
+
+ /* how the attribute value has to match.... Default is Exact */
+ enum Match {
+ None = 0,
+ Id,
+ Class,
+ Exact,
+ Set,
+ List,
+ Hyphen,
+ PseudoClass,
+ PseudoElement,
+ Contain, // css3: E[foo*="bar"]
+ Begin, // css3: E[foo^="bar"]
+ End, // css3: E[foo$="bar"]
+ PagePseudoClass
+ };
+
+ enum Relation {
+ Descendant = 0,
+ Child,
+ DirectAdjacent,
+ IndirectAdjacent,
+ SubSelector,
+ ShadowDescendant
+ };
+
+ enum PseudoType {
+ PseudoNotParsed = 0,
+ PseudoUnknown,
+ PseudoEmpty,
+ PseudoFirstChild,
+ PseudoFirstOfType,
+ PseudoLastChild,
+ PseudoLastOfType,
+ PseudoOnlyChild,
+ PseudoOnlyOfType,
+ PseudoFirstLine,
+ PseudoFirstLetter,
+ PseudoNthChild,
+ PseudoNthOfType,
+ PseudoNthLastChild,
+ PseudoNthLastOfType,
+ PseudoLink,
+ PseudoVisited,
+ PseudoAny,
+ PseudoAnyLink,
+ PseudoAutofill,
+ PseudoHover,
+ PseudoDrag,
+ PseudoFocus,
+ PseudoActive,
+ PseudoChecked,
+ PseudoEnabled,
+ PseudoFullPageMedia,
+ PseudoDefault,
+ PseudoDisabled,
+ PseudoOptional,
+ PseudoRequired,
+ PseudoReadOnly,
+ PseudoReadWrite,
+ PseudoValid,
+ PseudoInvalid,
+ PseudoIndeterminate,
+ PseudoTarget,
+ PseudoBefore,
+ PseudoAfter,
+ PseudoLang,
+ PseudoNot,
+ PseudoResizer,
+ PseudoRoot,
+ PseudoScrollbar,
+ PseudoScrollbarBack,
+ PseudoScrollbarButton,
+ PseudoScrollbarCorner,
+ PseudoScrollbarForward,
+ PseudoScrollbarThumb,
+ PseudoScrollbarTrack,
+ PseudoScrollbarTrackPiece,
+ PseudoWindowInactive,
+ PseudoCornerPresent,
+ PseudoDecrement,
+ PseudoIncrement,
+ PseudoHorizontal,
+ PseudoVertical,
+ PseudoStart,
+ PseudoEnd,
+ PseudoDoubleButton,
+ PseudoSingleButton,
+ PseudoNoButton,
+ PseudoSelection,
+ PseudoInputListButton,
+ PseudoLeftPage,
+ PseudoRightPage,
+ PseudoFirstPage,
+#if ENABLE(FULLSCREEN_API)
+ PseudoFullScreen,
+ PseudoFullScreenDocument,
+ PseudoFullScreenAncestor,
+ PseudoAnimatingFullScreenTransition,
+#endif
+ PseudoInRange,
+ PseudoOutOfRange,
+ };
+
+ enum MarginBoxType {
+ TopLeftCornerMarginBox,
+ TopLeftMarginBox,
+ TopCenterMarginBox,
+ TopRightMarginBox,
+ TopRightCornerMarginBox,
+ BottomLeftCornerMarginBox,
+ BottomLeftMarginBox,
+ BottomCenterMarginBox,
+ BottomRightMarginBox,
+ BottomRightCornerMarginBox,
+ LeftTopMarginBox,
+ LeftMiddleMarginBox,
+ LeftBottomMarginBox,
+ RightTopMarginBox,
+ RightMiddleMarginBox,
+ RightBottomMarginBox,
+ };
+
+ PseudoType pseudoType() const
+ {
+ if (m_pseudoType == PseudoNotParsed)
+ extractPseudoType();
+ return static_cast<PseudoType>(m_pseudoType);
+ }
+
+ static PseudoType parsePseudoType(const AtomicString&);
+ static bool isUnknownPseudoType(const AtomicString&);
+ static PseudoId pseudoId(PseudoType);
+
+ // Selectors are kept in an array by CSSSelectorList. The next component of the selector is
+ // the next item in the array.
+ CSSSelector* tagHistory() const { return m_isLastInTagHistory ? 0 : const_cast<CSSSelector*>(this + 1); }
+
+ bool hasTag() const { return m_tag != anyQName(); }
+
+ const QualifiedName& tag() const { return m_tag; }
+ // AtomicString is really just an AtomicStringImpl* so the cast below is safe.
+ // FIXME: Perhaps call sites could be changed to accept AtomicStringImpl?
+ const AtomicString& value() const { return *reinterpret_cast<const AtomicString*>(m_hasRareData ? &m_data.m_rareData->m_value : &m_data.m_value); }
+ const QualifiedName& attribute() const;
+ const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; }
+ CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : 0; }
+
+ void setTag(const QualifiedName& value) { m_tag = value; }
+ void setValue(const AtomicString&);
+ void setAttribute(const QualifiedName&);
+ void setArgument(const AtomicString&);
+ void setSelectorList(PassOwnPtr<CSSSelectorList>);
+
+ bool parseNth();
+ bool matchNth(int count);
+
+ bool matchesPseudoElement() const;
+ bool isUnknownPseudoElement() const;
+ bool isSiblingSelector() const;
+ bool isAttributeSelector() const;
+
+ Relation relation() const { return static_cast<Relation>(m_relation); }
+
+ bool isLastInSelectorList() const { return m_isLastInSelectorList; }
+ void setLastInSelectorList() { m_isLastInSelectorList = true; }
+ bool isLastInTagHistory() const { return m_isLastInTagHistory; }
+ void setNotLastInTagHistory() { m_isLastInTagHistory = false; }
+
+ bool isSimple() const;
+
+ bool isForPage() const { return m_isForPage; }
+ void setForPage() { m_isForPage = true; }
+
+ unsigned m_relation : 3; // enum Relation
+ mutable unsigned m_match : 4; // enum Match
+ mutable unsigned m_pseudoType : 8; // PseudoType
+
+ private:
+ bool m_parsedNth : 1; // Used for :nth-*
+ bool m_isLastInSelectorList : 1;
+ bool m_isLastInTagHistory : 1;
+ bool m_hasRareData : 1;
+ bool m_isForPage : 1;
+
+ unsigned specificityForOneSelector() const;
+ unsigned specificityForPage() const;
+ void extractPseudoType() const;
+
+ struct RareData {
+ WTF_MAKE_NONCOPYABLE(RareData); WTF_MAKE_FAST_ALLOCATED;
+ public:
+ RareData(PassRefPtr<AtomicStringImpl> value);
+ ~RareData();
+
+ bool parseNth();
+ bool matchNth(int count);
+
+ AtomicStringImpl* m_value; // Plain pointer to keep things uniform with the union.
+ int m_a; // Used for :nth-*
+ int m_b; // Used for :nth-*
+ QualifiedName m_attribute; // used for attribute selector
+ AtomicString m_argument; // Used for :contains, :lang and :nth-*
+ OwnPtr<CSSSelectorList> m_selectorList; // Used for :-webkit-any and :not
+ };
+ void createRareData();
+
+ union DataUnion {
+ DataUnion() : m_value(0) { }
+ AtomicStringImpl* m_value;
+ RareData* m_rareData;
+ } m_data;
+
+ QualifiedName m_tag;
+ };
+
+inline const QualifiedName& CSSSelector::attribute() const
+{
+ ASSERT(isAttributeSelector());
+ ASSERT(m_hasRareData);
+ return m_data.m_rareData->m_attribute;
+}
+
+inline bool CSSSelector::matchesPseudoElement() const
+{
+ if (m_pseudoType == PseudoUnknown)
+ extractPseudoType();
+ return m_match == PseudoElement;
+}
+
+inline bool CSSSelector::isUnknownPseudoElement() const
+{
+ return m_match == PseudoElement && m_pseudoType == PseudoUnknown;
+}
+
+inline bool CSSSelector::isSiblingSelector() const
+{
+ PseudoType type = pseudoType();
+ return m_relation == DirectAdjacent
+ || m_relation == IndirectAdjacent
+ || type == PseudoEmpty
+ || type == PseudoFirstChild
+ || type == PseudoFirstOfType
+ || type == PseudoLastChild
+ || type == PseudoLastOfType
+ || type == PseudoOnlyChild
+ || type == PseudoOnlyOfType
+ || type == PseudoNthChild
+ || type == PseudoNthOfType
+ || type == PseudoNthLastChild
+ || type == PseudoNthLastOfType;
+}
+
+inline bool CSSSelector::isAttributeSelector() const
+{
+ return m_match == CSSSelector::Exact
+ || m_match == CSSSelector::Set
+ || m_match == CSSSelector::List
+ || m_match == CSSSelector::Hyphen
+ || m_match == CSSSelector::Contain
+ || m_match == CSSSelector::Begin
+ || m_match == CSSSelector::End;
+}
+
+inline void CSSSelector::setValue(const AtomicString& value)
+{
+ // Need to do ref counting manually for the union.
+ if (m_hasRareData) {
+ if (m_data.m_rareData->m_value)
+ m_data.m_rareData->m_value->deref();
+ m_data.m_rareData->m_value = value.impl();
+ m_data.m_rareData->m_value->ref();
+ return;
+ }
+ if (m_data.m_value)
+ m_data.m_value->deref();
+ m_data.m_value = value.impl();
+ m_data.m_value->ref();
+}
+
+inline void move(PassOwnPtr<CSSSelector> from, CSSSelector* to)
+{
+ memcpy(to, from.get(), sizeof(CSSSelector));
+ // We want to free the memory (which was allocated with fastNew), but we
+ // don't want the destructor to run since it will affect the copy we've just made.
+ fastDeleteSkippingDestructor(from.leakPtr());
+}
+
+} // namespace WebCore
+
+#endif // CSSSelector_h
diff --git a/Source/WebCore/css/CSSSelectorList.cpp b/Source/WebCore/css/CSSSelectorList.cpp
new file mode 100644
index 000000000..80430537a
--- /dev/null
+++ b/Source/WebCore/css/CSSSelectorList.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 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:
+ * 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. ``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
+ * 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 "CSSSelectorList.h"
+
+#include "CSSParserValues.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+CSSSelectorList::~CSSSelectorList()
+{
+ deleteSelectors();
+}
+
+void CSSSelectorList::adopt(CSSSelectorList& list)
+{
+ deleteSelectors();
+ m_selectorArray = list.m_selectorArray;
+ list.m_selectorArray = 0;
+}
+
+void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
+{
+ deleteSelectors();
+ const size_t vectorSize = selectorVector.size();
+ size_t flattenedSize = 0;
+ for (size_t i = 0; i < vectorSize; ++i) {
+ for (CSSParserSelector* selector = selectorVector[i].get(); selector; selector = selector->tagHistory())
+ ++flattenedSize;
+ }
+ ASSERT(flattenedSize);
+ if (flattenedSize == 1) {
+ m_selectorArray = selectorVector[0]->releaseSelector().leakPtr();
+ m_selectorArray->setLastInSelectorList();
+ ASSERT(m_selectorArray->isLastInTagHistory());
+ selectorVector.shrink(0);
+ return;
+ }
+ m_selectorArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * flattenedSize));
+ size_t arrayIndex = 0;
+ for (size_t i = 0; i < vectorSize; ++i) {
+ CSSParserSelector* current = selectorVector[i].get();
+ while (current) {
+ OwnPtr<CSSSelector> selector = current->releaseSelector();
+ current = current->tagHistory();
+ move(selector.release(), &m_selectorArray[arrayIndex]);
+ ASSERT(!m_selectorArray[arrayIndex].isLastInSelectorList());
+ if (current)
+ m_selectorArray[arrayIndex].setNotLastInTagHistory();
+ ++arrayIndex;
+ }
+ ASSERT(m_selectorArray[arrayIndex - 1].isLastInTagHistory());
+ }
+ ASSERT(flattenedSize == arrayIndex);
+ m_selectorArray[arrayIndex - 1].setLastInSelectorList();
+ selectorVector.shrink(0);
+}
+
+void CSSSelectorList::deleteSelectors()
+{
+ if (!m_selectorArray)
+ return;
+
+ // We had two cases in adoptSelectVector. The fast case of a 1 element
+ // vector took the CSSSelector directly, which was allocated with new.
+ // The second case we allocated a new fastMalloc buffer, which should be
+ // freed with fastFree, and the destructors called manually.
+ CSSSelector* s = m_selectorArray;
+ bool done = s->isLastInSelectorList();
+ if (done)
+ delete s;
+ else {
+ while (1) {
+ s->~CSSSelector();
+ if (done)
+ break;
+ ++s;
+ done = s->isLastInSelectorList();
+ }
+ fastFree(m_selectorArray);
+ }
+}
+
+String CSSSelectorList::selectorsText() const
+{
+ StringBuilder result;
+
+ for (CSSSelector* s = first(); s; s = next(s)) {
+ if (s != first())
+ result.append(", ");
+ result.append(s->selectorText());
+ }
+
+ return result.toString();
+}
+
+template <typename Functor>
+static bool forEachTagSelector(Functor& functor, CSSSelector* selector)
+{
+ ASSERT(selector);
+
+ do {
+ if (functor(selector))
+ return true;
+ if (CSSSelectorList* selectorList = selector->selectorList()) {
+ for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
+ if (forEachTagSelector(functor, subSelector))
+ return true;
+ }
+ }
+ } while ((selector = selector->tagHistory()));
+
+ return false;
+}
+
+template <typename Functor>
+static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList)
+{
+ for (CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) {
+ if (forEachTagSelector(functor, selector))
+ return true;
+ }
+
+ return false;
+}
+
+class SelectorNeedsNamespaceResolutionFunctor {
+public:
+ bool operator()(CSSSelector* selector)
+ {
+ if (selector->hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom)
+ return true;
+ if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
+ return true;
+ return false;
+ }
+};
+
+bool CSSSelectorList::selectorsNeedNamespaceResolution()
+{
+ SelectorNeedsNamespaceResolutionFunctor functor;
+ return forEachSelector(functor, this);
+}
+
+class SelectorHasUnknownPseudoElementFunctor {
+public:
+ bool operator()(CSSSelector* selector)
+ {
+ return selector->isUnknownPseudoElement();
+ }
+};
+
+bool CSSSelectorList::hasUnknownPseudoElements() const
+{
+ SelectorHasUnknownPseudoElementFunctor functor;
+ return forEachSelector(functor, this);
+}
+
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSSelectorList.h b/Source/WebCore/css/CSSSelectorList.h
new file mode 100644
index 000000000..7d45a6a54
--- /dev/null
+++ b/Source/WebCore/css/CSSSelectorList.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 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. ``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
+ * 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 CSSSelectorList_h
+#define CSSSelectorList_h
+
+#include "CSSSelector.h"
+
+namespace WebCore {
+
+class CSSParserSelector;
+
+class CSSSelectorList {
+ WTF_MAKE_NONCOPYABLE(CSSSelectorList); WTF_MAKE_FAST_ALLOCATED;
+public:
+ CSSSelectorList() : m_selectorArray(0) { }
+ ~CSSSelectorList();
+
+ void adopt(CSSSelectorList& list);
+ void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
+
+ CSSSelector* first() const { return m_selectorArray ? m_selectorArray : 0; }
+ static CSSSelector* next(CSSSelector*);
+ bool hasOneSelector() const { return m_selectorArray && !next(m_selectorArray); }
+
+ bool selectorsNeedNamespaceResolution();
+ bool hasUnknownPseudoElements() const;
+
+ String selectorsText() const;
+
+private:
+ void deleteSelectors();
+
+ // End of a multipart selector is indicated by m_isLastInTagHistory bit in the last item.
+ // End of the array is indicated by m_isLastInSelectorList bit in the last item.
+ CSSSelector* m_selectorArray;
+};
+
+inline CSSSelector* CSSSelectorList::next(CSSSelector* current)
+{
+ // Skip subparts of compound selectors.
+ while (!current->isLastInTagHistory())
+ current++;
+ return current->isLastInSelectorList() ? 0 : current + 1;
+}
+
+} // namespace WebCore
+
+#endif // CSSSelectorList_h
diff --git a/Source/WebCore/css/CSSStyleApplyProperty.cpp b/Source/WebCore/css/CSSStyleApplyProperty.cpp
new file mode 100644
index 000000000..389f25c4a
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleApplyProperty.cpp
@@ -0,0 +1,1807 @@
+/*
+ * 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:
+ * 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 "CSSStyleApplyProperty.h"
+
+#include "CSSAspectRatioValue.h"
+#include "CSSCursorImageValue.h"
+#include "CSSFlexValue.h"
+#include "CSSPrimitiveValueMappings.h"
+#include "CSSStyleSelector.h"
+#include "CSSValueList.h"
+#include "CursorList.h"
+#include "Document.h"
+#include "Element.h"
+#include "Pair.h"
+#include "RenderObject.h"
+#include "RenderStyle.h"
+#include "Settings.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/UnusedParam.h>
+
+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>
+class ApplyPropertyExpanding {
+public:
+
+ template <CSSPropertyID id>
+ static inline void applyInheritValue(CSSStyleSelector* selector)
+ {
+ if (id == CSSPropertyInvalid)
+ return;
+
+ const CSSStyleApplyProperty& table = CSSStyleApplyProperty::sharedCSSStyleApplyProperty();
+ const PropertyHandler& handler = table.propertyHandler(id);
+ if (handler.isValid())
+ handler.applyInheritValue(selector);
+ }
+
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ applyInheritValue<one>(selector);
+ applyInheritValue<two>(selector);
+ applyInheritValue<three>(selector);
+ applyInheritValue<four>(selector);
+ }
+
+ template <CSSPropertyID id>
+ static inline void applyInitialValue(CSSStyleSelector* selector)
+ {
+ if (id == CSSPropertyInvalid)
+ return;
+
+ const CSSStyleApplyProperty& table = CSSStyleApplyProperty::sharedCSSStyleApplyProperty();
+ const PropertyHandler& handler = table.propertyHandler(id);
+ if (handler.isValid())
+ handler.applyInitialValue(selector);
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ applyInitialValue<one>(selector);
+ applyInitialValue<two>(selector);
+ applyInitialValue<three>(selector);
+ applyInitialValue<four>(selector);
+ }
+
+ template <CSSPropertyID id>
+ static inline void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (id == CSSPropertyInvalid)
+ return;
+
+ const CSSStyleApplyProperty& table = CSSStyleApplyProperty::sharedCSSStyleApplyProperty();
+ const PropertyHandler& handler = table.propertyHandler(id);
+ if (handler.isValid())
+ handler.applyValue(selector, value);
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!expandValue)
+ return;
+
+ applyValue<one>(selector, value);
+ applyValue<two>(selector, value);
+ applyValue<three>(selector, value);
+ applyValue<four>(selector, value);
+ }
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+template <typename GetterType, GetterType (RenderStyle::*getterFunction)() const, typename SetterType, void (RenderStyle::*setterFunction)(SetterType), typename InitialType, InitialType (*initialFunction)()>
+class ApplyPropertyDefaultBase {
+public:
+ static void setValue(RenderStyle* style, SetterType value) { (style->*setterFunction)(value); }
+ static GetterType value(RenderStyle* style) { return (style->*getterFunction)(); }
+ static InitialType initial() { return (*initialFunction)(); }
+ static void applyInheritValue(CSSStyleSelector* selector) { setValue(selector->style(), value(selector->parentStyle())); }
+ static void applyInitialValue(CSSStyleSelector* selector) { setValue(selector->style(), initial()); }
+ static void applyValue(CSSStyleSelector*, CSSValue*) { }
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+template <typename GetterType, GetterType (RenderStyle::*getterFunction)() const, typename SetterType, void (RenderStyle::*setterFunction)(SetterType), typename InitialType, InitialType (*initialFunction)()>
+class ApplyPropertyDefault {
+public:
+ static void setValue(RenderStyle* style, SetterType value) { (style->*setterFunction)(value); }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (value->isPrimitiveValue())
+ setValue(selector->style(), *static_cast<CSSPrimitiveValue*>(value));
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<GetterType, getterFunction, SetterType, setterFunction, InitialType, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+template <typename NumberType, NumberType (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(NumberType), NumberType (*initialFunction)(), int idMapsToMinusOne = CSSValueAuto>
+class ApplyPropertyNumber {
+public:
+ static void setValue(RenderStyle* style, NumberType value) { (style->*setterFunction)(value); }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == idMapsToMinusOne)
+ setValue(selector->style(), -1);
+ else
+ setValue(selector->style(), primitiveValue->getValue<NumberType>(CSSPrimitiveValue::CSS_NUMBER));
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<NumberType, getterFunction, NumberType, setterFunction, NumberType, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+template <StyleImage* (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(PassRefPtr<StyleImage>), StyleImage* (*initialFunction)(), CSSPropertyID property>
+class ApplyPropertyStyleImage {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value) { (selector->style()->*setterFunction)(selector->styleImage(property, value)); }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<StyleImage*, getterFunction, PassRefPtr<StyleImage>, setterFunction, StyleImage*, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+enum AutoValueType {Number = 0, ComputeLength};
+template <typename T, T (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(T), bool (RenderStyle::*hasAutoFunction)() const, void (RenderStyle::*setAutoFunction)(), AutoValueType valueType = Number, int autoIdentity = CSSValueAuto>
+class ApplyPropertyAuto {
+public:
+ static void setValue(RenderStyle* style, T value) { (style->*setterFunction)(value); }
+ static T value(RenderStyle* style) { return (style->*getterFunction)(); }
+ static bool hasAuto(RenderStyle* style) { return (style->*hasAutoFunction)(); }
+ static void setAuto(RenderStyle* style) { (style->*setAutoFunction)(); }
+
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ if (hasAuto(selector->parentStyle()))
+ setAuto(selector->style());
+ else
+ setValue(selector->style(), value(selector->parentStyle()));
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector) { setAuto(selector->style()); }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == autoIdentity)
+ setAuto(selector->style());
+ else if (valueType == Number)
+ setValue(selector->style(), *primitiveValue);
+ else if (valueType == ComputeLength)
+ setValue(selector->style(), primitiveValue->computeLength<T>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom()));
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+enum ColorInherit {NoInheritFromParent = 0, InheritFromParent};
+Color defaultInitialColor();
+Color defaultInitialColor() { return Color(); }
+template <ColorInherit inheritColorFromParent,
+ const Color& (RenderStyle::*getterFunction)() const,
+ void (RenderStyle::*setterFunction)(const Color&),
+ void (RenderStyle::*visitedLinkSetterFunction)(const Color&),
+ const Color& (RenderStyle::*defaultFunction)() const,
+ Color (*initialFunction)() = &defaultInitialColor>
+class ApplyPropertyColor {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ // Visited link style can never explicitly inherit from parent visited link style so no separate getters are needed.
+ const Color& color = (selector->parentStyle()->*getterFunction)();
+ applyColorValue(selector, color.isValid() ? color : (selector->parentStyle()->*defaultFunction)());
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ applyColorValue(selector, initialFunction());
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (inheritColorFromParent && primitiveValue->getIdent() == CSSValueCurrentcolor)
+ applyInheritValue(selector);
+ else {
+ if (selector->applyPropertyToRegularStyle())
+ (selector->style()->*setterFunction)(selector->colorFromPrimitiveValue(primitiveValue));
+ if (selector->applyPropertyToVisitedLinkStyle())
+ (selector->style()->*visitedLinkSetterFunction)(selector->colorFromPrimitiveValue(primitiveValue, /* forVisitedLink */ true));
+ }
+ }
+
+ static void applyColorValue(CSSStyleSelector* selector, const Color& color)
+ {
+ if (selector->applyPropertyToRegularStyle())
+ (selector->style()->*setterFunction)(color);
+ if (selector->applyPropertyToVisitedLinkStyle())
+ (selector->style()->*visitedLinkSetterFunction)(color);
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+template <TextDirection (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(TextDirection), TextDirection (*initialFunction)()>
+class ApplyPropertyDirection {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ ApplyPropertyDefault<TextDirection, getterFunction, TextDirection, setterFunction, TextDirection, initialFunction>::applyValue(selector, value);
+ Element* element = selector->element();
+ if (element && selector->element() == element->document()->documentElement())
+ element->document()->setDirectionSetOnDocumentElement(true);
+ }
+
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefault<TextDirection, getterFunction, TextDirection, setterFunction, TextDirection, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+enum LengthAuto { AutoDisabled = 0, AutoEnabled };
+enum LengthIntrinsic { IntrinsicDisabled = 0, IntrinsicEnabled };
+enum LengthMinIntrinsic { MinIntrinsicDisabled = 0, MinIntrinsicEnabled };
+enum LengthNone { NoneDisabled = 0, NoneEnabled };
+enum LengthUndefined { UndefinedDisabled = 0, UndefinedEnabled };
+enum LengthFlexDirection { FlexDirectionDisabled = 0, FlexWidth, FlexHeight };
+template <Length (RenderStyle::*getterFunction)() const,
+ void (RenderStyle::*setterFunction)(Length),
+ Length (*initialFunction)(),
+ LengthAuto autoEnabled = AutoDisabled,
+ LengthIntrinsic intrinsicEnabled = IntrinsicDisabled,
+ LengthMinIntrinsic minIntrinsicEnabled = MinIntrinsicDisabled,
+ LengthNone noneEnabled = NoneDisabled,
+ LengthUndefined noneUndefined = UndefinedDisabled,
+ LengthFlexDirection flexDirection = FlexDirectionDisabled>
+class ApplyPropertyLength {
+public:
+ static void setValue(RenderStyle* style, Length value) { (style->*setterFunction)(value); }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue()) {
+ if (!flexDirection || !value->isFlexValue())
+ return;
+
+ CSSFlexValue* flexValue = static_cast<CSSFlexValue*>(value);
+ value = flexValue->preferredSize();
+
+ if (flexDirection == FlexWidth) {
+ selector->style()->setFlexboxWidthPositiveFlex(flexValue->positiveFlex());
+ selector->style()->setFlexboxWidthNegativeFlex(flexValue->negativeFlex());
+ } else if (flexDirection == FlexHeight) {
+ selector->style()->setFlexboxHeightPositiveFlex(flexValue->positiveFlex());
+ selector->style()->setFlexboxHeightNegativeFlex(flexValue->negativeFlex());
+ }
+ }
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (noneEnabled && primitiveValue->getIdent() == CSSValueNone)
+ if (noneUndefined)
+ setValue(selector->style(), Length(Undefined));
+ else
+ setValue(selector->style(), Length());
+ else if (intrinsicEnabled && primitiveValue->getIdent() == CSSValueIntrinsic)
+ setValue(selector->style(), Length(Intrinsic));
+ else if (minIntrinsicEnabled && primitiveValue->getIdent() == CSSValueMinIntrinsic)
+ setValue(selector->style(), Length(MinIntrinsic));
+ else if (autoEnabled && primitiveValue->getIdent() == CSSValueAuto)
+ setValue(selector->style(), Length());
+ else {
+ int type = primitiveValue->primitiveType();
+ if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+ 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)
+ setValue(selector->style(), Length(primitiveValue->getDoubleValue(), Percent));
+ }
+ }
+
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<Length, getterFunction, Length, setterFunction, Length, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+enum StringIdentBehavior { NothingMapsToNull = 0, MapNoneToNull, MapAutoToNull };
+template <StringIdentBehavior identBehavior, const AtomicString& (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(const AtomicString&), const AtomicString& (*initialFunction)()>
+class ApplyPropertyString {
+public:
+ static void setValue(RenderStyle* style, const AtomicString& value) { (style->*setterFunction)(value); }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if ((identBehavior == MapNoneToNull && primitiveValue->getIdent() == CSSValueNone)
+ || (identBehavior == MapAutoToNull && primitiveValue->getIdent() == CSSValueAuto))
+ setValue(selector->style(), nullAtom);
+ else
+ setValue(selector->style(), primitiveValue->getStringValue());
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<const AtomicString&, getterFunction, const AtomicString&, setterFunction, const AtomicString&, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+template <LengthSize (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(LengthSize), LengthSize (*initialFunction)()>
+class ApplyPropertyBorderRadius {
+public:
+ static void setValue(RenderStyle* style, LengthSize value) { (style->*setterFunction)(value); }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ Pair* pair = primitiveValue->getPairValue();
+ if (!pair || !pair->first() || !pair->second())
+ return;
+
+ Length radiusWidth;
+ Length radiusHeight;
+ if (pair->first()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ 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)
+ 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);
+ int width = radiusWidth.value();
+ int height = radiusHeight.value();
+ if (width < 0 || height < 0)
+ return;
+ if (!width)
+ radiusHeight = radiusWidth; // Null out the other value.
+ else if (!height)
+ radiusWidth = radiusHeight; // Null out the other value.
+
+ LengthSize size(radiusWidth, radiusHeight);
+ setValue(selector->style(), size);
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<LengthSize, getterFunction, LengthSize, setterFunction, LengthSize, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+template <typename T>
+struct FillLayerAccessorTypes {
+ typedef T Setter;
+ typedef T Getter;
+};
+
+template <>
+struct FillLayerAccessorTypes<StyleImage*> {
+ typedef PassRefPtr<StyleImage> Setter;
+ typedef StyleImage* Getter;
+};
+
+template <typename T,
+ CSSPropertyID propertyId,
+ EFillLayerType fillLayerType,
+ FillLayer* (RenderStyle::*accessLayersFunction)(),
+ const FillLayer* (RenderStyle::*layersFunction)() const,
+ bool (FillLayer::*testFunction)() const,
+ typename FillLayerAccessorTypes<T>::Getter (FillLayer::*getFunction)() const,
+ void (FillLayer::*setFunction)(typename FillLayerAccessorTypes<T>::Setter),
+ void (FillLayer::*clearFunction)(),
+ typename FillLayerAccessorTypes<T>::Getter (*initialFunction)(EFillLayerType),
+ void (CSSStyleSelector::*mapFillFunction)(CSSPropertyID, FillLayer*, CSSValue*)>
+class ApplyPropertyFillLayer {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ FillLayer* currChild = (selector->style()->*accessLayersFunction)();
+ FillLayer* prevChild = 0;
+ const FillLayer* currParent = (selector->parentStyle()->*layersFunction)();
+ while (currParent && (currParent->*testFunction)()) {
+ if (!currChild) {
+ /* Need to make a new layer.*/
+ currChild = new FillLayer(fillLayerType);
+ prevChild->setNext(currChild);
+ }
+ (currChild->*setFunction)((currParent->*getFunction)());
+ prevChild = currChild;
+ currChild = prevChild->next();
+ currParent = currParent->next();
+ }
+
+ while (currChild) {
+ /* Reset any remaining layers to not have the property set. */
+ (currChild->*clearFunction)();
+ currChild = currChild->next();
+ }
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ FillLayer* currChild = (selector->style()->*accessLayersFunction)();
+ (currChild->*setFunction)((*initialFunction)(fillLayerType));
+ for (currChild = currChild->next(); currChild; currChild = currChild->next())
+ (currChild->*clearFunction)();
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ FillLayer* currChild = (selector->style()->*accessLayersFunction)();
+ FillLayer* prevChild = 0;
+ if (value->isValueList()) {
+ /* Walk each value and put it into a layer, creating new layers as needed. */
+ CSSValueList* valueList = static_cast<CSSValueList*>(value);
+ for (unsigned int i = 0; i < valueList->length(); i++) {
+ if (!currChild) {
+ /* Need to make a new layer to hold this value */
+ currChild = new FillLayer(fillLayerType);
+ prevChild->setNext(currChild);
+ }
+ (selector->*mapFillFunction)(propertyId, currChild, valueList->itemWithoutBoundsCheck(i));
+ prevChild = currChild;
+ currChild = currChild->next();
+ }
+ } else {
+ (selector->*mapFillFunction)(propertyId, currChild, value);
+ currChild = currChild->next();
+ }
+ while (currChild) {
+ /* Reset all remaining layers to not have the property set. */
+ (currChild->*clearFunction)();
+ currChild = currChild->next();
+ }
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+enum ComputeLengthNormal {NormalDisabled = 0, NormalEnabled};
+enum ComputeLengthThickness {ThicknessDisabled = 0, ThicknessEnabled};
+enum ComputeLengthSVGZoom {SVGZoomDisabled = 0, SVGZoomEnabled};
+template <typename T,
+ T (RenderStyle::*getterFunction)() const,
+ void (RenderStyle::*setterFunction)(T),
+ T (*initialFunction)(),
+ ComputeLengthNormal normalEnabled = NormalDisabled,
+ ComputeLengthThickness thicknessEnabled = ThicknessDisabled,
+ ComputeLengthSVGZoom svgZoomEnabled = SVGZoomDisabled>
+class ApplyPropertyComputeLength {
+public:
+ static void setValue(RenderStyle* style, T value) { (style->*setterFunction)(value); }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ // note: CSSPropertyLetter/WordSpacing right now sets to zero if it's not a primitive value for some reason...
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ int ident = primitiveValue->getIdent();
+ T length;
+ if (normalEnabled && ident == CSSValueNormal) {
+ length = 0;
+ } else if (thicknessEnabled && ident == CSSValueThin) {
+ length = 1;
+ } else if (thicknessEnabled && ident == CSSValueMedium) {
+ length = 3;
+ } else if (thicknessEnabled && ident == CSSValueThick) {
+ length = 5;
+ } else if (ident == CSSValueInvalid) {
+ float zoom = (svgZoomEnabled && selector->useSVGZoomRules()) ? 1.0f : selector->style()->effectiveZoom();
+ length = primitiveValue->computeLength<T>(selector->style(), selector->rootElementStyle(), zoom);
+ } else {
+ ASSERT_NOT_REACHED();
+ length = 0;
+ }
+
+ setValue(selector->style(), length);
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<T, getterFunction, T, setterFunction, T, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+template <typename T, T (FontDescription::*getterFunction)() const, void (FontDescription::*setterFunction)(T), T initialValue>
+class ApplyPropertyFont {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ FontDescription fontDescription = selector->fontDescription();
+ (fontDescription.*setterFunction)((selector->parentFontDescription().*getterFunction)());
+ selector->setFontDescription(fontDescription);
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ FontDescription fontDescription = selector->fontDescription();
+ (fontDescription.*setterFunction)(initialValue);
+ selector->setFontDescription(fontDescription);
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ FontDescription fontDescription = selector->fontDescription();
+ (fontDescription.*setterFunction)(*primitiveValue);
+ selector->setFontDescription(fontDescription);
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+class ApplyPropertyFontSize {
+private:
+ // When the CSS keyword "larger" is used, this function will attempt to match within the keyword
+ // table, and failing that, will simply multiply by 1.2.
+ static float largerFontSize(float size)
+ {
+ // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
+ // the next size level.
+ return size * 1.2f;
+ }
+
+ // Like the previous function, but for the keyword "smaller".
+ static float smallerFontSize(float size)
+ {
+ // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
+ // the next size level.
+ return size / 1.2f;
+ }
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ float size = selector->parentStyle()->fontDescription().specifiedSize();
+
+ if (size < 0)
+ return;
+
+ FontDescription fontDescription = selector->style()->fontDescription();
+ fontDescription.setKeywordSize(selector->parentStyle()->fontDescription().keywordSize());
+ selector->setFontSize(fontDescription, size);
+ selector->setFontDescription(fontDescription);
+ return;
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ FontDescription fontDescription = selector->style()->fontDescription();
+ float size = selector->fontSizeForKeyword(selector->document(), CSSValueMedium, fontDescription.useFixedDefaultSize());
+
+ if (size < 0)
+ return;
+
+ fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
+ selector->setFontSize(fontDescription, size);
+ selector->setFontDescription(fontDescription);
+ return;
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ FontDescription fontDescription = selector->style()->fontDescription();
+ fontDescription.setKeywordSize(0);
+ float parentSize = 0;
+ bool parentIsAbsoluteSize = false;
+ float size = 0;
+
+ if (selector->hasParentNode()) {
+ parentSize = selector->parentStyle()->fontDescription().specifiedSize();
+ parentIsAbsoluteSize = selector->parentStyle()->fontDescription().isAbsoluteSize();
+ }
+
+ if (int ident = primitiveValue->getIdent()) {
+ // Keywords are being used.
+ switch (ident) {
+ case CSSValueXxSmall:
+ case CSSValueXSmall:
+ case CSSValueSmall:
+ case CSSValueMedium:
+ case CSSValueLarge:
+ case CSSValueXLarge:
+ case CSSValueXxLarge:
+ case CSSValueWebkitXxxLarge:
+ size = selector->fontSizeForKeyword(selector->document(), ident, fontDescription.useFixedDefaultSize());
+ fontDescription.setKeywordSize(ident - CSSValueXxSmall + 1);
+ break;
+ case CSSValueLarger:
+ size = largerFontSize(parentSize);
+ break;
+ case CSSValueSmaller:
+ size = smallerFontSize(parentSize);
+ break;
+ default:
+ return;
+ }
+
+ 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));
+ if (primitiveValue->isLength())
+ size = primitiveValue->computeLength<float>(selector->parentStyle(), selector->rootElementStyle(), 1.0, true);
+ else if (primitiveValue->isPercentage())
+ size = (primitiveValue->getFloatValue() * parentSize) / 100.0f;
+ else
+ return;
+ }
+
+ if (size < 0)
+ return;
+
+ selector->setFontSize(fontDescription, size);
+ selector->setFontDescription(fontDescription);
+ return;
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+class ApplyPropertyFontWeight {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ FontDescription fontDescription = selector->fontDescription();
+ switch (primitiveValue->getIdent()) {
+ case CSSValueInvalid:
+ ASSERT_NOT_REACHED();
+ break;
+ case CSSValueBolder:
+ fontDescription.setWeight(fontDescription.bolderWeight());
+ break;
+ case CSSValueLighter:
+ fontDescription.setWeight(fontDescription.lighterWeight());
+ break;
+ default:
+ fontDescription.setWeight(*primitiveValue);
+ }
+ selector->setFontDescription(fontDescription);
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyFont<FontWeight, &FontDescription::weight, &FontDescription::setWeight, FontWeightNormal>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+enum BorderImageType { Image = 0, Mask };
+template <BorderImageType borderImageType,
+ CSSPropertyID property,
+ const NinePieceImage& (RenderStyle::*getterFunction)() const,
+ void (RenderStyle::*setterFunction)(const NinePieceImage&)>
+class ApplyPropertyBorderImage {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ NinePieceImage image;
+ if (borderImageType == Mask)
+ image.setMaskDefaults();
+ selector->mapNinePieceImage(property, value, image);
+ (selector->style()->*setterFunction)(image);
+ }
+
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<const NinePieceImage&, getterFunction, const NinePieceImage&, setterFunction, NinePieceImage, &RenderStyle::initialNinePieceImage>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+enum BorderImageModifierType { Outset, Repeat, Slice, Width };
+template <BorderImageType type, BorderImageModifierType modifier>
+class ApplyPropertyBorderImageModifier {
+private:
+ static inline const NinePieceImage& getValue(RenderStyle* style) { return type == Image ? style->borderImage() : style->maskBoxImage(); }
+ static inline void setValue(RenderStyle* style, const NinePieceImage& value) { return type == Image ? style->setBorderImage(value) : style->setMaskBoxImage(value); }
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ NinePieceImage image(getValue(selector->style()));
+ switch (modifier) {
+ case Outset:
+ image.copyOutsetFrom(getValue(selector->parentStyle()));
+ break;
+ case Repeat:
+ image.copyRepeatFrom(getValue(selector->parentStyle()));
+ break;
+ case Slice:
+ image.copyImageSlicesFrom(getValue(selector->parentStyle()));
+ break;
+ case Width:
+ image.copyBorderSlicesFrom(getValue(selector->parentStyle()));
+ break;
+ }
+ setValue(selector->style(), image);
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ NinePieceImage image(getValue(selector->style()));
+ switch (modifier) {
+ case Outset:
+ image.setOutset(LengthBox());
+ break;
+ case Repeat:
+ image.setHorizontalRule(StretchImageRule);
+ image.setVerticalRule(StretchImageRule);
+ break;
+ case Slice:
+ // Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
+ image.setImageSlices(type == Image ? LengthBox(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent)) : LengthBox());
+ image.setFill(false);
+ break;
+ case Width:
+ // Masks have a different initial value for widths. They use an 'auto' value rather than trying to fit to the border.
+ image.setBorderSlices(type == Image ? LengthBox(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative)) : LengthBox());
+ break;
+ }
+ setValue(selector->style(), image);
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ NinePieceImage image(getValue(selector->style()));
+ switch (modifier) {
+ case Outset:
+ image.setOutset(selector->mapNinePieceImageQuad(value));
+ break;
+ case Repeat:
+ selector->mapNinePieceImageRepeat(value, image);
+ break;
+ case Slice:
+ selector->mapNinePieceImageSlice(value, image);
+ break;
+ case Width:
+ image.setBorderSlices(selector->mapNinePieceImageQuad(value));
+ break;
+ }
+ setValue(selector->style(), image);
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+template <CSSPropertyID id, StyleImage* (RenderStyle::*getterFunction)() const, void (RenderStyle::*setterFunction)(PassRefPtr<StyleImage>), StyleImage* (*initialFunction)()>
+class ApplyPropertyBorderImageSource {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value) { (selector->style()->*setterFunction)(selector->styleImage(id, value)); }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<StyleImage*, getterFunction, PassRefPtr<StyleImage>, setterFunction, StyleImage*, initialFunction>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+enum CounterBehavior {Increment = 0, Reset};
+template <CounterBehavior counterBehavior>
+class ApplyPropertyCounter {
+public:
+ static void emptyFunction(CSSStyleSelector*) { }
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ CounterDirectiveMap& map = selector->style()->accessCounterDirectives();
+ CounterDirectiveMap& parentMap = selector->parentStyle()->accessCounterDirectives();
+
+ typedef CounterDirectiveMap::iterator Iterator;
+ Iterator end = parentMap.end();
+ for (Iterator it = parentMap.begin(); it != end; ++it) {
+ CounterDirectives& directives = map.add(it->first, CounterDirectives()).first->second;
+ if (counterBehavior == Reset) {
+ directives.m_reset = it->second.m_reset;
+ directives.m_resetValue = it->second.m_resetValue;
+ } else {
+ // Inheriting a counter-increment means taking the parent's current value for the counter
+ // and adding it to itself.
+ directives.m_increment = it->second.m_increment;
+ directives.m_incrementValue = 0;
+ if (directives.m_increment) {
+ float incrementValue = directives.m_incrementValue;
+ directives.m_incrementValue = clampToInteger(incrementValue + it->second.m_incrementValue);
+ } else {
+ directives.m_increment = true;
+ directives.m_incrementValue = it->second.m_incrementValue;
+ }
+ }
+ }
+ }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isValueList())
+ return;
+
+ CSSValueList* list = static_cast<CSSValueList*>(value);
+
+ CounterDirectiveMap& map = selector->style()->accessCounterDirectives();
+ typedef CounterDirectiveMap::iterator Iterator;
+
+ Iterator end = map.end();
+ for (Iterator it = map.begin(); it != end; ++it)
+ if (counterBehavior == Reset)
+ it->second.m_reset = false;
+ else
+ it->second.m_increment = false;
+
+ int length = list ? list->length() : 0;
+ for (int i = 0; i < length; ++i) {
+ CSSValue* currValue = list->itemWithoutBoundsCheck(i);
+ if (!currValue->isPrimitiveValue())
+ continue;
+
+ Pair* pair = static_cast<CSSPrimitiveValue*>(currValue)->getPairValue();
+ if (!pair || !pair->first() || !pair->second())
+ continue;
+
+ AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
+ int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
+ CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
+ if (counterBehavior == Reset) {
+ directives.m_reset = true;
+ directives.m_resetValue = value;
+ } else {
+ if (directives.m_increment) {
+ float incrementValue = directives.m_incrementValue;
+ directives.m_incrementValue = clampToInteger(incrementValue + value);
+ } else {
+ directives.m_increment = true;
+ directives.m_incrementValue = value;
+ }
+ }
+
+ }
+ }
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &emptyFunction, &applyValue); }
+};
+
+
+class ApplyPropertyCursor {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ selector->style()->setCursor(selector->parentStyle()->cursor());
+ selector->style()->setCursorList(selector->parentStyle()->cursors());
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ selector->style()->clearCursorList();
+ selector->style()->setCursor(RenderStyle::initialCursor());
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ selector->style()->clearCursorList();
+ if (value->isValueList()) {
+ CSSValueList* list = static_cast<CSSValueList*>(value);
+ int len = list->length();
+ selector->style()->setCursor(CURSOR_AUTO);
+ for (int i = 0; i < len; i++) {
+ CSSValue* item = list->itemWithoutBoundsCheck(i);
+ if (!item->isPrimitiveValue())
+ continue;
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(item);
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI) {
+ 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)
+ 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))
+ selector->style()->setCursor(*primitiveValue);
+ }
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+class ApplyPropertyTextAlign {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ if (primitiveValue->getIdent() != CSSValueWebkitMatchParent)
+ selector->style()->setTextAlign(*primitiveValue);
+ else if (selector->parentStyle()->textAlign() == TASTART)
+ selector->style()->setTextAlign(selector->parentStyle()->isLeftToRightDirection() ? LEFT : RIGHT);
+ else if (selector->parentStyle()->textAlign() == TAEND)
+ selector->style()->setTextAlign(selector->parentStyle()->isLeftToRightDirection() ? RIGHT : LEFT);
+ else
+ selector->style()->setTextAlign(selector->parentStyle()->textAlign());
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<ETextAlign, &RenderStyle::textAlign, ETextAlign, &RenderStyle::setTextAlign, ETextAlign, &RenderStyle::initialTextAlign>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+class ApplyPropertyTextDecoration {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ ETextDecoration t = RenderStyle::initialTextDecoration();
+ for (CSSValueListIterator i(value); i.hasMore(); i.advance()) {
+ CSSValue* item = i.value();
+ ASSERT(item->isPrimitiveValue());
+ t |= *static_cast<CSSPrimitiveValue*>(item);
+ }
+ selector->style()->setTextDecoration(t);
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<ETextDecoration, &RenderStyle::textDecoration, ETextDecoration, &RenderStyle::setTextDecoration, ETextDecoration, &RenderStyle::initialTextDecoration>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+class ApplyPropertyLineHeight {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ Length lineHeight;
+
+ if (primitiveValue->getIdent() == CSSValueNormal)
+ lineHeight = Length(-100.0, Percent);
+ else if (primitiveValue->isLength()) {
+ double multiplier = selector->style()->effectiveZoom();
+ if (selector->style()->textSizeAdjust()) {
+ if (Frame* frame = selector->document()->frame())
+ multiplier *= frame->textZoomFactor();
+ }
+ lineHeight = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle(), multiplier);
+ } else if (primitiveValue->isPercentage()) {
+ // FIXME: percentage should not be restricted to an integer here.
+ lineHeight = Length((selector->style()->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
+ } else if (primitiveValue->isNumber()) {
+ // FIXME: number and percentage values should produce the same type of Length (ie. Fixed or Percent).
+ lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
+ } else
+ return;
+ selector->style()->setLineHeight(lineHeight);
+ }
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<Length, &RenderStyle::lineHeight, Length, &RenderStyle::setLineHeight, Length, &RenderStyle::initialLineHeight>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+class ApplyPropertyPageSize {
+private:
+ static Length mmLength(double mm) { return CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM)->computeLength<Length>(0, 0); }
+ static Length inchLength(double inch) { return CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN)->computeLength<Length>(0, 0); }
+ static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
+ {
+ static const Length a5Width = mmLength(148), a5Height = mmLength(210);
+ static const Length a4Width = mmLength(210), a4Height = mmLength(297);
+ static const Length a3Width = mmLength(297), a3Height = mmLength(420);
+ static const Length b5Width = mmLength(176), b5Height = mmLength(250);
+ static const Length b4Width = mmLength(250), b4Height = mmLength(353);
+ static const Length letterWidth = inchLength(8.5), letterHeight = inchLength(11);
+ static const Length legalWidth = inchLength(8.5), legalHeight = inchLength(14);
+ static const Length ledgerWidth = inchLength(11), ledgerHeight = inchLength(17);
+
+ if (!pageSizeName)
+ return false;
+
+ switch (pageSizeName->getIdent()) {
+ case CSSValueA5:
+ width = a5Width;
+ height = a5Height;
+ break;
+ case CSSValueA4:
+ width = a4Width;
+ height = a4Height;
+ break;
+ case CSSValueA3:
+ width = a3Width;
+ height = a3Height;
+ break;
+ case CSSValueB5:
+ width = b5Width;
+ height = b5Height;
+ break;
+ case CSSValueB4:
+ width = b4Width;
+ height = b4Height;
+ break;
+ case CSSValueLetter:
+ width = letterWidth;
+ height = letterHeight;
+ break;
+ case CSSValueLegal:
+ width = legalWidth;
+ height = legalHeight;
+ break;
+ case CSSValueLedger:
+ width = ledgerWidth;
+ height = ledgerHeight;
+ break;
+ default:
+ return false;
+ }
+
+ if (pageOrientation) {
+ switch (pageOrientation->getIdent()) {
+ case CSSValueLandscape:
+ std::swap(width, height);
+ break;
+ case CSSValuePortrait:
+ // Nothing to do.
+ break;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+public:
+ static void applyInheritValue(CSSStyleSelector*) { }
+ static void applyInitialValue(CSSStyleSelector*) { }
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ selector->style()->resetPageSizeType();
+ Length width;
+ Length height;
+ PageSizeType pageSizeType = PAGE_SIZE_AUTO;
+ CSSValueListInspector inspector(value);
+ switch (inspector.length()) {
+ case 2: {
+ // <length>{2} | <page-size> <orientation>
+ if (!inspector.first()->isPrimitiveValue() || !inspector.second()->isPrimitiveValue())
+ return;
+ CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(inspector.first());
+ CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(inspector.second());
+ if (first->isLength()) {
+ // <length>{2}
+ if (!second->isLength())
+ return;
+ width = first->computeLength<Length>(selector->style(), selector->rootElementStyle());
+ height = second->computeLength<Length>(selector->style(), selector->rootElementStyle());
+ } else {
+ // <page-size> <orientation>
+ // The value order is guaranteed. See CSSParser::parseSizeParameter.
+ if (!getPageSizeFromName(first, second, width, height))
+ return;
+ }
+ pageSizeType = PAGE_SIZE_RESOLVED;
+ break;
+ }
+ case 1: {
+ // <length> | auto | <page-size> | [ portrait | landscape]
+ if (!inspector.first()->isPrimitiveValue())
+ return;
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(inspector.first());
+ if (primitiveValue->isLength()) {
+ // <length>
+ 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 CSSValueAuto:
+ pageSizeType = PAGE_SIZE_AUTO;
+ break;
+ case CSSValuePortrait:
+ pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
+ break;
+ case CSSValueLandscape:
+ pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
+ break;
+ default:
+ // <page-size>
+ pageSizeType = PAGE_SIZE_RESOLVED;
+ if (!getPageSizeFromName(primitiveValue, 0, width, height))
+ return;
+ }
+ }
+ break;
+ }
+ default:
+ return;
+ }
+ selector->style()->setPageSizeType(pageSizeType);
+ selector->style()->setPageSize(LengthSize(width, height));
+ }
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+class ApplyPropertyTextEmphasisStyle {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ selector->style()->setTextEmphasisFill(selector->parentStyle()->textEmphasisFill());
+ selector->style()->setTextEmphasisMark(selector->parentStyle()->textEmphasisMark());
+ selector->style()->setTextEmphasisCustomMark(selector->parentStyle()->textEmphasisCustomMark());
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ selector->style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill());
+ selector->style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark());
+ selector->style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark());
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (value->isValueList()) {
+ CSSValueList* list = static_cast<CSSValueList*>(value);
+ ASSERT(list->length() == 2);
+ if (list->length() != 2)
+ return;
+ for (unsigned i = 0; i < 2; ++i) {
+ CSSValue* item = list->itemWithoutBoundsCheck(i);
+ if (!item->isPrimitiveValue())
+ continue;
+
+ CSSPrimitiveValue* value = static_cast<CSSPrimitiveValue*>(item);
+ if (value->getIdent() == CSSValueFilled || value->getIdent() == CSSValueOpen)
+ selector->style()->setTextEmphasisFill(*value);
+ else
+ selector->style()->setTextEmphasisMark(*value);
+ }
+ selector->style()->setTextEmphasisCustomMark(nullAtom);
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
+ selector->style()->setTextEmphasisFill(TextEmphasisFillFilled);
+ selector->style()->setTextEmphasisMark(TextEmphasisMarkCustom);
+ selector->style()->setTextEmphasisCustomMark(primitiveValue->getStringValue());
+ return;
+ }
+
+ selector->style()->setTextEmphasisCustomMark(nullAtom);
+
+ if (primitiveValue->getIdent() == CSSValueFilled || primitiveValue->getIdent() == CSSValueOpen) {
+ selector->style()->setTextEmphasisFill(*primitiveValue);
+ selector->style()->setTextEmphasisMark(TextEmphasisMarkAuto);
+ } else {
+ selector->style()->setTextEmphasisFill(TextEmphasisFillFilled);
+ selector->style()->setTextEmphasisMark(*primitiveValue);
+ }
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+template <typename T,
+ T (Animation::*getterFunction)() const,
+ void (Animation::*setterFunction)(T),
+ bool (Animation::*testFunction)() const,
+ void (Animation::*clearFunction)(),
+ T (*initialFunction)(),
+ void (CSSStyleSelector::*mapFunction)(Animation*, CSSValue*),
+ AnimationList* (RenderStyle::*animationGetterFunction)(),
+ const AnimationList* (RenderStyle::*immutableAnimationGetterFunction)() const>
+class ApplyPropertyAnimation {
+public:
+ static void setValue(Animation* animation, T value) { (animation->*setterFunction)(value); }
+ static T value(const Animation* animation) { return (animation->*getterFunction)(); }
+ static bool test(const Animation* animation) { return (animation->*testFunction)(); }
+ static void clear(Animation* animation) { (animation->*clearFunction)(); }
+ static T initial() { return (*initialFunction)(); }
+ static void map(CSSStyleSelector* selector, Animation* animation, CSSValue* value) { (selector->*mapFunction)(animation, value); }
+ static AnimationList* accessAnimations(RenderStyle* style) { return (style->*animationGetterFunction)(); }
+ static const AnimationList* animations(RenderStyle* style) { return (style->*immutableAnimationGetterFunction)(); }
+
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ AnimationList* list = accessAnimations(selector->style());
+ const AnimationList* parentList = animations(selector->parentStyle());
+ size_t i = 0, parentSize = parentList ? parentList->size() : 0;
+ for ( ; i < parentSize && test(parentList->animation(i)); ++i) {
+ if (list->size() <= i)
+ list->append(Animation::create());
+ setValue(list->animation(i), value(parentList->animation(i)));
+ }
+
+ /* Reset any remaining animations to not have the property set. */
+ for ( ; i < list->size(); ++i)
+ clear(list->animation(i));
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ AnimationList* list = accessAnimations(selector->style());
+ if (list->isEmpty())
+ list->append(Animation::create());
+ setValue(list->animation(0), initial());
+ for (size_t i = 1; i < list->size(); ++i)
+ clear(list->animation(i));
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ AnimationList* list = accessAnimations(selector->style());
+ size_t childIndex = 0;
+ if (value->isValueList()) {
+ /* Walk each value and put it into an animation, creating new animations as needed. */
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ if (childIndex <= list->size())
+ list->append(Animation::create());
+ map(selector, list->animation(childIndex), i.value());
+ ++childIndex;
+ }
+ } else {
+ if (list->isEmpty())
+ list->append(Animation::create());
+ map(selector, list->animation(childIndex), value);
+ childIndex = 1;
+ }
+ for ( ; childIndex < list->size(); ++childIndex) {
+ /* Reset all remaining animations to not have the property set. */
+ clear(list->animation(childIndex));
+ }
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+class ApplyPropertyOutlineStyle {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ ApplyPropertyDefaultBase<OutlineIsAuto, &RenderStyle::outlineStyleIsAuto, OutlineIsAuto, &RenderStyle::setOutlineStyleIsAuto, OutlineIsAuto, &RenderStyle::initialOutlineStyleIsAuto>::applyInheritValue(selector);
+ ApplyPropertyDefaultBase<EBorderStyle, &RenderStyle::outlineStyle, EBorderStyle, &RenderStyle::setOutlineStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::applyInheritValue(selector);
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ ApplyPropertyDefaultBase<OutlineIsAuto, &RenderStyle::outlineStyleIsAuto, OutlineIsAuto, &RenderStyle::setOutlineStyleIsAuto, OutlineIsAuto, &RenderStyle::initialOutlineStyleIsAuto>::applyInitialValue(selector);
+ ApplyPropertyDefaultBase<EBorderStyle, &RenderStyle::outlineStyle, EBorderStyle, &RenderStyle::setOutlineStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::applyInitialValue(selector);
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ ApplyPropertyDefault<OutlineIsAuto, &RenderStyle::outlineStyleIsAuto, OutlineIsAuto, &RenderStyle::setOutlineStyleIsAuto, OutlineIsAuto, &RenderStyle::initialOutlineStyleIsAuto>::applyValue(selector, value);
+ ApplyPropertyDefault<EBorderStyle, &RenderStyle::outlineStyle, EBorderStyle, &RenderStyle::setOutlineStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::applyValue(selector, value);
+ }
+
+ static PropertyHandler createHandler() { return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue); }
+};
+
+class ApplyPropertyResize {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ EResize r = RESIZE_NONE;
+ switch (primitiveValue->getIdent()) {
+ case 0:
+ return;
+ case CSSValueAuto:
+ if (Settings* settings = selector->document()->settings())
+ r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
+ break;
+ default:
+ r = *primitiveValue;
+ }
+ selector->style()->setResize(r);
+ }
+
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<EResize, &RenderStyle::resize, EResize, &RenderStyle::setResize, EResize, &RenderStyle::initialResize>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+class ApplyPropertyVerticalAlign {
+public:
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ if (primitiveValue->getIdent())
+ return selector->style()->setVerticalAlign(*primitiveValue);
+
+ Length length;
+ if (primitiveValue->isLength())
+ length = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom());
+ else if (primitiveValue->isPercentage())
+ length = Length(primitiveValue->getDoubleValue(), Percent);
+
+ selector->style()->setVerticalAlignLength(length);
+ }
+
+ static PropertyHandler createHandler()
+ {
+ PropertyHandler handler = ApplyPropertyDefaultBase<EVerticalAlign, &RenderStyle::verticalAlign, EVerticalAlign, &RenderStyle::setVerticalAlign, EVerticalAlign, &RenderStyle::initialVerticalAlign>::createHandler();
+ return PropertyHandler(handler.inheritFunction(), handler.initialFunction(), &applyValue);
+ }
+};
+
+class ApplyPropertyAspectRatio {
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ if (!selector->parentStyle()->hasAspectRatio())
+ return;
+ selector->style()->setHasAspectRatio(true);
+ selector->style()->setAspectRatioDenominator(selector->parentStyle()->aspectRatioDenominator());
+ selector->style()->setAspectRatioNumerator(selector->parentStyle()->aspectRatioNumerator());
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ selector->style()->setHasAspectRatio(RenderStyle::initialHasAspectRatio());
+ selector->style()->setAspectRatioDenominator(RenderStyle::initialAspectRatioDenominator());
+ selector->style()->setAspectRatioNumerator(RenderStyle::initialAspectRatioNumerator());
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isAspectRatioValue()) {
+ selector->style()->setHasAspectRatio(false);
+ return;
+ }
+ CSSAspectRatioValue* aspectRatioValue = static_cast<CSSAspectRatioValue*>(value);
+ selector->style()->setHasAspectRatio(true);
+ selector->style()->setAspectRatioDenominator(aspectRatioValue->denominatorValue());
+ selector->style()->setAspectRatioNumerator(aspectRatioValue->numeratorValue());
+ }
+
+ static PropertyHandler createHandler()
+ {
+ return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue);
+ }
+};
+
+class ApplyPropertyZoom {
+private:
+ static void resetEffectiveZoom(CSSStyleSelector* selector)
+ {
+ // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect.
+ selector->setEffectiveZoom(selector->parentStyle() ? selector->parentStyle()->effectiveZoom() : RenderStyle::initialZoom());
+ }
+
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ resetEffectiveZoom(selector);
+ selector->setZoom(selector->parentStyle()->zoom());
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ resetEffectiveZoom(selector);
+ selector->setZoom(RenderStyle::initialZoom());
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ ASSERT(value->isPrimitiveValue());
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ if (primitiveValue->getIdent() == CSSValueNormal) {
+ resetEffectiveZoom(selector);
+ selector->setZoom(RenderStyle::initialZoom());
+ } else if (primitiveValue->getIdent() == CSSValueReset) {
+ selector->setEffectiveZoom(RenderStyle::initialZoom());
+ selector->setZoom(RenderStyle::initialZoom());
+ } else if (primitiveValue->getIdent() == CSSValueDocument) {
+ float docZoom = selector->document()->renderer()->style()->zoom();
+ selector->setEffectiveZoom(docZoom);
+ selector->setZoom(docZoom);
+ } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) {
+ resetEffectiveZoom(selector);
+ if (float percent = primitiveValue->getFloatValue())
+ selector->setZoom(percent / 100.0f);
+ } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
+ resetEffectiveZoom(selector);
+ if (float number = primitiveValue->getFloatValue())
+ selector->setZoom(number);
+ }
+ }
+
+ static PropertyHandler createHandler()
+ {
+ return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue);
+ }
+};
+
+class ApplyPropertyDisplay {
+private:
+ static inline bool isValidDisplayValue(CSSStyleSelector* selector, EDisplay displayPropertyValue)
+ {
+#if ENABLE(SVG)
+ if (selector->element() && selector->element()->isSVGElement() && selector->style()->styleType() == NOPSEUDO)
+ return (displayPropertyValue == INLINE || displayPropertyValue == BLOCK || displayPropertyValue == NONE);
+#endif
+ return true;
+ }
+public:
+ static void applyInheritValue(CSSStyleSelector* selector)
+ {
+ EDisplay display = selector->parentStyle()->display();
+ if (!isValidDisplayValue(selector, display))
+ return;
+ selector->style()->setDisplay(display);
+ }
+
+ static void applyInitialValue(CSSStyleSelector* selector)
+ {
+ selector->style()->setDisplay(RenderStyle::initialDisplay());
+ }
+
+ static void applyValue(CSSStyleSelector* selector, CSSValue* value)
+ {
+ if (!value->isPrimitiveValue())
+ return;
+
+ EDisplay display = *static_cast<CSSPrimitiveValue*>(value);
+
+ if (!isValidDisplayValue(selector, display))
+ return;
+
+ selector->style()->setDisplay(display);
+ }
+
+ static PropertyHandler createHandler()
+ {
+ return PropertyHandler(&applyInheritValue, &applyInitialValue, &applyValue);
+ }
+};
+
+const CSSStyleApplyProperty& CSSStyleApplyProperty::sharedCSSStyleApplyProperty()
+{
+ DEFINE_STATIC_LOCAL(CSSStyleApplyProperty, cssStyleApplyPropertyInstance, ());
+ return cssStyleApplyPropertyInstance;
+}
+
+CSSStyleApplyProperty::CSSStyleApplyProperty()
+{
+ for (int i = 0; i < numCSSProperties; ++i)
+ m_propertyMap[i] = PropertyHandler();
+
+ setPropertyHandler(CSSPropertyWebkitAspectRatio, ApplyPropertyAspectRatio::createHandler());
+
+ setPropertyHandler(CSSPropertyColor, ApplyPropertyColor<InheritFromParent, &RenderStyle::color, &RenderStyle::setColor, &RenderStyle::setVisitedLinkColor, &RenderStyle::invalidColor, RenderStyle::initialColor>::createHandler());
+ setPropertyHandler(CSSPropertyDirection, ApplyPropertyDirection<&RenderStyle::direction, &RenderStyle::setDirection, RenderStyle::initialDirection>::createHandler());
+
+ setPropertyHandler(CSSPropertyBackgroundAttachment, ApplyPropertyFillLayer<EFillAttachment, CSSPropertyBackgroundAttachment, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isAttachmentSet, &FillLayer::attachment, &FillLayer::setAttachment, &FillLayer::clearAttachment, &FillLayer::initialFillAttachment, &CSSStyleSelector::mapFillAttachment>::createHandler());
+ setPropertyHandler(CSSPropertyBackgroundClip, ApplyPropertyFillLayer<EFillBox, CSSPropertyBackgroundClip, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isClipSet, &FillLayer::clip, &FillLayer::setClip, &FillLayer::clearClip, &FillLayer::initialFillClip, &CSSStyleSelector::mapFillClip>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitBackgroundClip, CSSPropertyBackgroundClip);
+ setPropertyHandler(CSSPropertyWebkitBackgroundComposite, ApplyPropertyFillLayer<CompositeOperator, CSSPropertyWebkitBackgroundComposite, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isCompositeSet, &FillLayer::composite, &FillLayer::setComposite, &FillLayer::clearComposite, &FillLayer::initialFillComposite, &CSSStyleSelector::mapFillComposite>::createHandler());
+
+ setPropertyHandler(CSSPropertyDisplay, ApplyPropertyDisplay::createHandler());
+
+ setPropertyHandler(CSSPropertyBackgroundImage, ApplyPropertyFillLayer<StyleImage*, CSSPropertyBackgroundImage, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isImageSet, &FillLayer::image, &FillLayer::setImage, &FillLayer::clearImage, &FillLayer::initialFillImage, &CSSStyleSelector::mapFillImage>::createHandler());
+
+ setPropertyHandler(CSSPropertyBackgroundOrigin, ApplyPropertyFillLayer<EFillBox, CSSPropertyBackgroundOrigin, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isOriginSet, &FillLayer::origin, &FillLayer::setOrigin, &FillLayer::clearOrigin, &FillLayer::initialFillOrigin, &CSSStyleSelector::mapFillOrigin>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitBackgroundOrigin, CSSPropertyBackgroundOrigin);
+
+ setPropertyHandler(CSSPropertyBackgroundPositionX, ApplyPropertyFillLayer<Length, CSSPropertyBackgroundPositionX, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isXPositionSet, &FillLayer::xPosition, &FillLayer::setXPosition, &FillLayer::clearXPosition, &FillLayer::initialFillXPosition, &CSSStyleSelector::mapFillXPosition>::createHandler());
+ setPropertyHandler(CSSPropertyBackgroundPositionY, ApplyPropertyFillLayer<Length, CSSPropertyBackgroundPositionY, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isYPositionSet, &FillLayer::yPosition, &FillLayer::setYPosition, &FillLayer::clearYPosition, &FillLayer::initialFillYPosition, &CSSStyleSelector::mapFillYPosition>::createHandler());
+ setPropertyHandler(CSSPropertyBackgroundPosition, ApplyPropertyExpanding<SuppressValue, CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY>::createHandler());
+
+ setPropertyHandler(CSSPropertyBackgroundRepeatX, ApplyPropertyFillLayer<EFillRepeat, CSSPropertyBackgroundRepeatX, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isRepeatXSet, &FillLayer::repeatX, &FillLayer::setRepeatX, &FillLayer::clearRepeatX, &FillLayer::initialFillRepeatX, &CSSStyleSelector::mapFillRepeatX>::createHandler());
+ setPropertyHandler(CSSPropertyBackgroundRepeatY, ApplyPropertyFillLayer<EFillRepeat, CSSPropertyBackgroundRepeatY, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isRepeatYSet, &FillLayer::repeatY, &FillLayer::setRepeatY, &FillLayer::clearRepeatY, &FillLayer::initialFillRepeatY, &CSSStyleSelector::mapFillRepeatY>::createHandler());
+ setPropertyHandler(CSSPropertyBackgroundRepeat, ApplyPropertyExpanding<SuppressValue, CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY>::createHandler());
+
+ setPropertyHandler(CSSPropertyBackgroundSize, ApplyPropertyFillLayer<FillSize, CSSPropertyBackgroundSize, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers,
+ &FillLayer::isSizeSet, &FillLayer::size, &FillLayer::setSize, &FillLayer::clearSize, &FillLayer::initialFillSize, &CSSStyleSelector::mapFillSize>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitBackgroundSize, CSSPropertyBackgroundSize);
+
+ setPropertyHandler(CSSPropertyWebkitMaskAttachment, ApplyPropertyFillLayer<EFillAttachment, CSSPropertyWebkitMaskAttachment, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isAttachmentSet, &FillLayer::attachment, &FillLayer::setAttachment, &FillLayer::clearAttachment, &FillLayer::initialFillAttachment, &CSSStyleSelector::mapFillAttachment>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskClip, ApplyPropertyFillLayer<EFillBox, CSSPropertyWebkitMaskClip, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isClipSet, &FillLayer::clip, &FillLayer::setClip, &FillLayer::clearClip, &FillLayer::initialFillClip, &CSSStyleSelector::mapFillClip>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskComposite, ApplyPropertyFillLayer<CompositeOperator, CSSPropertyWebkitMaskComposite, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isCompositeSet, &FillLayer::composite, &FillLayer::setComposite, &FillLayer::clearComposite, &FillLayer::initialFillComposite, &CSSStyleSelector::mapFillComposite>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitMaskImage, ApplyPropertyFillLayer<StyleImage*, CSSPropertyWebkitMaskImage, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isImageSet, &FillLayer::image, &FillLayer::setImage, &FillLayer::clearImage, &FillLayer::initialFillImage, &CSSStyleSelector::mapFillImage>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitMaskOrigin, ApplyPropertyFillLayer<EFillBox, CSSPropertyWebkitMaskOrigin, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isOriginSet, &FillLayer::origin, &FillLayer::setOrigin, &FillLayer::clearOrigin, &FillLayer::initialFillOrigin, &CSSStyleSelector::mapFillOrigin>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskSize, ApplyPropertyFillLayer<FillSize, CSSPropertyWebkitMaskSize, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isSizeSet, &FillLayer::size, &FillLayer::setSize, &FillLayer::clearSize, &FillLayer::initialFillSize, &CSSStyleSelector::mapFillSize>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitMaskPositionX, ApplyPropertyFillLayer<Length, CSSPropertyWebkitMaskPositionX, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isXPositionSet, &FillLayer::xPosition, &FillLayer::setXPosition, &FillLayer::clearXPosition, &FillLayer::initialFillXPosition, &CSSStyleSelector::mapFillXPosition>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskPositionY, ApplyPropertyFillLayer<Length, CSSPropertyWebkitMaskPositionY, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isYPositionSet, &FillLayer::yPosition, &FillLayer::setYPosition, &FillLayer::clearYPosition, &FillLayer::initialFillYPosition, &CSSStyleSelector::mapFillYPosition>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskPosition, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitMaskRepeatX, ApplyPropertyFillLayer<EFillRepeat, CSSPropertyWebkitMaskRepeatX, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isRepeatXSet, &FillLayer::repeatX, &FillLayer::setRepeatX, &FillLayer::clearRepeatX, &FillLayer::initialFillRepeatX, &CSSStyleSelector::mapFillRepeatX>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskRepeatY, ApplyPropertyFillLayer<EFillRepeat, CSSPropertyWebkitMaskRepeatY, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers,
+ &FillLayer::isRepeatYSet, &FillLayer::repeatY, &FillLayer::setRepeatY, &FillLayer::clearRepeatY, &FillLayer::initialFillRepeatY, &CSSStyleSelector::mapFillRepeatY>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskRepeat, ApplyPropertyExpanding<SuppressValue, CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY>::createHandler());
+
+ setPropertyHandler(CSSPropertyBackgroundColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor, &RenderStyle::setVisitedLinkBackgroundColor, &RenderStyle::invalidColor>::createHandler());
+ setPropertyHandler(CSSPropertyBorderBottomColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor, &RenderStyle::setVisitedLinkBorderBottomColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyBorderLeftColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor, &RenderStyle::setVisitedLinkBorderLeftColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyBorderRightColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor, &RenderStyle::setVisitedLinkBorderRightColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyBorderTopColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor, &RenderStyle::setVisitedLinkBorderTopColor, &RenderStyle::color>::createHandler());
+
+ setPropertyHandler(CSSPropertyBorderTopStyle, ApplyPropertyDefault<EBorderStyle, &RenderStyle::borderTopStyle, EBorderStyle, &RenderStyle::setBorderTopStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::createHandler());
+ setPropertyHandler(CSSPropertyBorderRightStyle, ApplyPropertyDefault<EBorderStyle, &RenderStyle::borderRightStyle, EBorderStyle, &RenderStyle::setBorderRightStyle, EBorderStyle, &RenderStyle::initialBorderStyle>::createHandler());
+ 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(CSSPropertyBorderTop, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderTopColor, CSSPropertyBorderTopStyle, CSSPropertyBorderTopWidth>::createHandler());
+ setPropertyHandler(CSSPropertyBorderRight, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderRightColor, CSSPropertyBorderRightStyle, CSSPropertyBorderRightWidth>::createHandler());
+ setPropertyHandler(CSSPropertyBorderBottom, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderBottomColor, CSSPropertyBorderBottomStyle, CSSPropertyBorderBottomWidth>::createHandler());
+ setPropertyHandler(CSSPropertyBorderLeft, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderLeftColor, CSSPropertyBorderLeftStyle, CSSPropertyBorderLeftWidth>::createHandler());
+
+ setPropertyHandler(CSSPropertyBorderStyle, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle, CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle>::createHandler());
+ setPropertyHandler(CSSPropertyBorderWidth, ApplyPropertyExpanding<SuppressValue, CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth, CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth>::createHandler());
+ 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(CSSPropertyWebkitBorderImage, ApplyPropertyBorderImage<Image, CSSPropertyWebkitBorderImage, &RenderStyle::borderImage, &RenderStyle::setBorderImage>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskBoxImage, ApplyPropertyBorderImage<Mask, CSSPropertyWebkitMaskBoxImage, &RenderStyle::maskBoxImage, &RenderStyle::setMaskBoxImage>::createHandler());
+
+ setPropertyHandler(CSSPropertyBorderImageOutset, ApplyPropertyBorderImageModifier<Image, Outset>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskBoxImageOutset, ApplyPropertyBorderImageModifier<Mask, Outset>::createHandler());
+ setPropertyHandler(CSSPropertyBorderImageRepeat, ApplyPropertyBorderImageModifier<Image, Repeat>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskBoxImageRepeat, ApplyPropertyBorderImageModifier<Mask, Repeat>::createHandler());
+ setPropertyHandler(CSSPropertyBorderImageSlice, ApplyPropertyBorderImageModifier<Image, Slice>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskBoxImageSlice, ApplyPropertyBorderImageModifier<Mask, Slice>::createHandler());
+ setPropertyHandler(CSSPropertyBorderImageWidth, ApplyPropertyBorderImageModifier<Image, Width>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskBoxImageWidth, ApplyPropertyBorderImageModifier<Mask, Width>::createHandler());
+
+ setPropertyHandler(CSSPropertyBorderImageSource, ApplyPropertyBorderImageSource<CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource, &RenderStyle::initialBorderImageSource>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMaskBoxImageSource, ApplyPropertyBorderImageSource<CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource, &RenderStyle::initialMaskBoxImageSource>::createHandler());
+
+ setPropertyHandler(CSSPropertyBorderTopLeftRadius, ApplyPropertyBorderRadius<&RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius, &RenderStyle::initialBorderRadius>::createHandler());
+ setPropertyHandler(CSSPropertyBorderTopRightRadius, ApplyPropertyBorderRadius<&RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius, &RenderStyle::initialBorderRadius>::createHandler());
+ setPropertyHandler(CSSPropertyBorderBottomLeftRadius, ApplyPropertyBorderRadius<&RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius, &RenderStyle::initialBorderRadius>::createHandler());
+ setPropertyHandler(CSSPropertyBorderBottomRightRadius, ApplyPropertyBorderRadius<&RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius, &RenderStyle::initialBorderRadius>::createHandler());
+ setPropertyHandler(CSSPropertyBorderRadius, ApplyPropertyExpanding<ExpandValue, CSSPropertyBorderTopLeftRadius, CSSPropertyBorderTopRightRadius, CSSPropertyBorderBottomLeftRadius, CSSPropertyBorderBottomRightRadius>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitBorderRadius, CSSPropertyBorderRadius);
+
+ setPropertyHandler(CSSPropertyWebkitBorderHorizontalSpacing, ApplyPropertyComputeLength<short, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing, &RenderStyle::initialHorizontalBorderSpacing>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitBorderVerticalSpacing, ApplyPropertyComputeLength<short, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing, &RenderStyle::initialVerticalBorderSpacing>::createHandler());
+ setPropertyHandler(CSSPropertyBorderSpacing, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing>::createHandler());
+
+ 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(CSSPropertyCursor, ApplyPropertyCursor::createHandler());
+
+ setPropertyHandler(CSSPropertyCounterIncrement, ApplyPropertyCounter<Increment>::createHandler());
+ setPropertyHandler(CSSPropertyCounterReset, ApplyPropertyCounter<Reset>::createHandler());
+
+ 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(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());
+ setPropertyHandler(CSSPropertyWebkitFlexFlow, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitFlexDirection, CSSPropertyWebkitFlexWrap>::createHandler());
+
+ setPropertyHandler(CSSPropertyFontSize, ApplyPropertyFontSize::createHandler());
+ setPropertyHandler(CSSPropertyFontStyle, ApplyPropertyFont<FontItalic, &FontDescription::italic, &FontDescription::setItalic, FontItalicOff>::createHandler());
+ setPropertyHandler(CSSPropertyFontVariant, ApplyPropertyFont<FontSmallCaps, &FontDescription::smallCaps, &FontDescription::setSmallCaps, FontSmallCapsOff>::createHandler());
+ setPropertyHandler(CSSPropertyTextRendering, ApplyPropertyFont<TextRenderingMode, &FontDescription::textRenderingMode, &FontDescription::setTextRenderingMode, AutoTextRendering>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitFontSmoothing, ApplyPropertyFont<FontSmoothingMode, &FontDescription::fontSmoothing, &FontDescription::setFontSmoothing, AutoSmoothing>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTextOrientation, ApplyPropertyFont<TextOrientation, &FontDescription::textOrientation, &FontDescription::setTextOrientation, TextOrientationVerticalRight>::createHandler());
+ setPropertyHandler(CSSPropertyFontWeight, ApplyPropertyFontWeight::createHandler());
+
+ setPropertyHandler(CSSPropertyTextAlign, ApplyPropertyTextAlign::createHandler());
+ setPropertyHandler(CSSPropertyTextDecoration, ApplyPropertyTextDecoration::createHandler());
+
+ setPropertyHandler(CSSPropertyOutlineStyle, ApplyPropertyOutlineStyle::createHandler());
+ setPropertyHandler(CSSPropertyOutlineColor, ApplyPropertyColor<InheritFromParent, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor, &RenderStyle::setVisitedLinkOutlineColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyOutlineOffset, ApplyPropertyComputeLength<int, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset, &RenderStyle::initialOutlineOffset>::createHandler());
+
+ setPropertyHandler(CSSPropertyOutline, ApplyPropertyExpanding<SuppressValue, CSSPropertyOutlineWidth, CSSPropertyOutlineColor, CSSPropertyOutlineStyle>::createHandler());
+
+ setPropertyHandler(CSSPropertyOverflowX, ApplyPropertyDefault<EOverflow, &RenderStyle::overflowX, EOverflow, &RenderStyle::setOverflowX, EOverflow, &RenderStyle::initialOverflowX>::createHandler());
+ setPropertyHandler(CSSPropertyOverflowY, ApplyPropertyDefault<EOverflow, &RenderStyle::overflowY, EOverflow, &RenderStyle::setOverflowY, EOverflow, &RenderStyle::initialOverflowY>::createHandler());
+ setPropertyHandler(CSSPropertyOverflow, ApplyPropertyExpanding<ExpandValue, CSSPropertyOverflowX, CSSPropertyOverflowY>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitColumnRuleColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTextEmphasisColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::textEmphasisColor, &RenderStyle::setTextEmphasisColor, &RenderStyle::setVisitedLinkTextEmphasisColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTextFillColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::textFillColor, &RenderStyle::setTextFillColor, &RenderStyle::setVisitedLinkTextFillColor, &RenderStyle::color>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTextStrokeColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor, &RenderStyle::setVisitedLinkTextStrokeColor, &RenderStyle::color>::createHandler());
+
+ setPropertyHandler(CSSPropertyTop, ApplyPropertyLength<&RenderStyle::top, &RenderStyle::setTop, &RenderStyle::initialOffset, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyRight, ApplyPropertyLength<&RenderStyle::right, &RenderStyle::setRight, &RenderStyle::initialOffset, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyBottom, ApplyPropertyLength<&RenderStyle::bottom, &RenderStyle::setBottom, &RenderStyle::initialOffset, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyLeft, ApplyPropertyLength<&RenderStyle::left, &RenderStyle::setLeft, &RenderStyle::initialOffset, AutoEnabled>::createHandler());
+
+ setPropertyHandler(CSSPropertyWidth, ApplyPropertyLength<&RenderStyle::width, &RenderStyle::setWidth, &RenderStyle::initialSize, AutoEnabled, IntrinsicEnabled, MinIntrinsicEnabled, NoneDisabled, UndefinedDisabled, FlexWidth>::createHandler());
+ setPropertyHandler(CSSPropertyHeight, ApplyPropertyLength<&RenderStyle::height, &RenderStyle::setHeight, &RenderStyle::initialSize, AutoEnabled, IntrinsicEnabled, MinIntrinsicEnabled, NoneDisabled, UndefinedDisabled, FlexHeight>::createHandler());
+
+ setPropertyHandler(CSSPropertyTextIndent, ApplyPropertyLength<&RenderStyle::textIndent, &RenderStyle::setTextIndent, &RenderStyle::initialTextIndent>::createHandler());
+
+ setPropertyHandler(CSSPropertyLineHeight, ApplyPropertyLineHeight::createHandler());
+
+ setPropertyHandler(CSSPropertyListStyleImage, ApplyPropertyStyleImage<&RenderStyle::listStyleImage, &RenderStyle::setListStyleImage, &RenderStyle::initialListStyleImage, CSSPropertyListStyleImage>::createHandler());
+ setPropertyHandler(CSSPropertyListStylePosition, ApplyPropertyDefault<EListStylePosition, &RenderStyle::listStylePosition, EListStylePosition, &RenderStyle::setListStylePosition, EListStylePosition, &RenderStyle::initialListStylePosition>::createHandler());
+ setPropertyHandler(CSSPropertyListStyleType, ApplyPropertyDefault<EListStyleType, &RenderStyle::listStyleType, EListStyleType, &RenderStyle::setListStyleType, EListStyleType, &RenderStyle::initialListStyleType>::createHandler());
+ setPropertyHandler(CSSPropertyListStyle, ApplyPropertyExpanding<SuppressValue, CSSPropertyListStyleType, CSSPropertyListStyleImage, CSSPropertyListStylePosition>::createHandler());
+
+ setPropertyHandler(CSSPropertyMaxHeight, ApplyPropertyLength<&RenderStyle::maxHeight, &RenderStyle::setMaxHeight, &RenderStyle::initialMaxSize, AutoEnabled, IntrinsicEnabled, MinIntrinsicEnabled, NoneEnabled, UndefinedEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMaxWidth, ApplyPropertyLength<&RenderStyle::maxWidth, &RenderStyle::setMaxWidth, &RenderStyle::initialMaxSize, AutoEnabled, IntrinsicEnabled, MinIntrinsicEnabled, NoneEnabled, UndefinedEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMinHeight, ApplyPropertyLength<&RenderStyle::minHeight, &RenderStyle::setMinHeight, &RenderStyle::initialMinSize, AutoEnabled, IntrinsicEnabled, MinIntrinsicEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMinWidth, ApplyPropertyLength<&RenderStyle::minWidth, &RenderStyle::setMinWidth, &RenderStyle::initialMinSize, AutoEnabled, IntrinsicEnabled, MinIntrinsicEnabled>::createHandler());
+
+ setPropertyHandler(CSSPropertyMarginTop, ApplyPropertyLength<&RenderStyle::marginTop, &RenderStyle::setMarginTop, &RenderStyle::initialMargin, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMarginRight, ApplyPropertyLength<&RenderStyle::marginRight, &RenderStyle::setMarginRight, &RenderStyle::initialMargin, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMarginBottom, ApplyPropertyLength<&RenderStyle::marginBottom, &RenderStyle::setMarginBottom, &RenderStyle::initialMargin, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMarginLeft, ApplyPropertyLength<&RenderStyle::marginLeft, &RenderStyle::setMarginLeft, &RenderStyle::initialMargin, AutoEnabled>::createHandler());
+ setPropertyHandler(CSSPropertyMargin, ApplyPropertyExpanding<SuppressValue, CSSPropertyMarginTop, CSSPropertyMarginRight, CSSPropertyMarginBottom, CSSPropertyMarginLeft>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitMarginBeforeCollapse, ApplyPropertyDefault<EMarginCollapse, &RenderStyle::marginBeforeCollapse, EMarginCollapse, &RenderStyle::setMarginBeforeCollapse, EMarginCollapse, &RenderStyle::initialMarginBeforeCollapse>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMarginAfterCollapse, ApplyPropertyDefault<EMarginCollapse, &RenderStyle::marginAfterCollapse, EMarginCollapse, &RenderStyle::setMarginAfterCollapse, EMarginCollapse, &RenderStyle::initialMarginAfterCollapse>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitMarginTopCollapse, CSSPropertyWebkitMarginBeforeCollapse);
+ setPropertyHandler(CSSPropertyWebkitMarginBottomCollapse, CSSPropertyWebkitMarginAfterCollapse);
+ setPropertyHandler(CSSPropertyWebkitMarginCollapse, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginAfterCollapse>::createHandler());
+
+ setPropertyHandler(CSSPropertyPaddingTop, ApplyPropertyLength<&RenderStyle::paddingTop, &RenderStyle::setPaddingTop, &RenderStyle::initialPadding>::createHandler());
+ setPropertyHandler(CSSPropertyPaddingRight, ApplyPropertyLength<&RenderStyle::paddingRight, &RenderStyle::setPaddingRight, &RenderStyle::initialPadding>::createHandler());
+ setPropertyHandler(CSSPropertyPaddingBottom, ApplyPropertyLength<&RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom, &RenderStyle::initialPadding>::createHandler());
+ setPropertyHandler(CSSPropertyPaddingLeft, ApplyPropertyLength<&RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft, &RenderStyle::initialPadding>::createHandler());
+ setPropertyHandler(CSSPropertyPadding, ApplyPropertyExpanding<SuppressValue, CSSPropertyPaddingTop, CSSPropertyPaddingRight, CSSPropertyPaddingBottom, CSSPropertyPaddingLeft>::createHandler());
+
+ setPropertyHandler(CSSPropertyResize, ApplyPropertyResize::createHandler());
+
+ setPropertyHandler(CSSPropertyVerticalAlign, ApplyPropertyVerticalAlign::createHandler());
+
+ setPropertyHandler(CSSPropertySize, ApplyPropertyPageSize::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitPerspectiveOriginX, ApplyPropertyLength<&RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX, &RenderStyle::initialPerspectiveOriginX>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitPerspectiveOriginY, ApplyPropertyLength<&RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY, &RenderStyle::initialPerspectiveOriginY>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitPerspectiveOrigin, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitPerspectiveOriginX, CSSPropertyWebkitPerspectiveOriginY>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransformOriginX, ApplyPropertyLength<&RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX, &RenderStyle::initialTransformOriginX>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransformOriginY, ApplyPropertyLength<&RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY, &RenderStyle::initialTransformOriginY>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransformOriginZ, ApplyPropertyComputeLength<float, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ, &RenderStyle::initialTransformOriginZ>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransformOrigin, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitTransformOriginX, CSSPropertyWebkitTransformOriginY, CSSPropertyWebkitTransformOriginZ>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitAnimationDelay, ApplyPropertyAnimation<double, &Animation::delay, &Animation::setDelay, &Animation::isDelaySet, &Animation::clearDelay, &Animation::initialAnimationDelay, &CSSStyleSelector::mapAnimationDelay, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationDirection, ApplyPropertyAnimation<Animation::AnimationDirection, &Animation::direction, &Animation::setDirection, &Animation::isDirectionSet, &Animation::clearDirection, &Animation::initialAnimationDirection, &CSSStyleSelector::mapAnimationDirection, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationDuration, ApplyPropertyAnimation<double, &Animation::duration, &Animation::setDuration, &Animation::isDurationSet, &Animation::clearDuration, &Animation::initialAnimationDuration, &CSSStyleSelector::mapAnimationDuration, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationFillMode, ApplyPropertyAnimation<unsigned, &Animation::fillMode, &Animation::setFillMode, &Animation::isFillModeSet, &Animation::clearFillMode, &Animation::initialAnimationFillMode, &CSSStyleSelector::mapAnimationFillMode, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationIterationCount, ApplyPropertyAnimation<int, &Animation::iterationCount, &Animation::setIterationCount, &Animation::isIterationCountSet, &Animation::clearIterationCount, &Animation::initialAnimationIterationCount, &CSSStyleSelector::mapAnimationIterationCount, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationName, ApplyPropertyAnimation<const String&, &Animation::name, &Animation::setName, &Animation::isNameSet, &Animation::clearName, &Animation::initialAnimationName, &CSSStyleSelector::mapAnimationName, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationPlayState, ApplyPropertyAnimation<EAnimPlayState, &Animation::playState, &Animation::setPlayState, &Animation::isPlayStateSet, &Animation::clearPlayState, &Animation::initialAnimationPlayState, &CSSStyleSelector::mapAnimationPlayState, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitAnimationTimingFunction, ApplyPropertyAnimation<const PassRefPtr<TimingFunction>, &Animation::timingFunction, &Animation::setTimingFunction, &Animation::isTimingFunctionSet, &Animation::clearTimingFunction, &Animation::initialAnimationTimingFunction, &CSSStyleSelector::mapAnimationTimingFunction, &RenderStyle::accessAnimations, &RenderStyle::animations>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitTransitionDelay, ApplyPropertyAnimation<double, &Animation::delay, &Animation::setDelay, &Animation::isDelaySet, &Animation::clearDelay, &Animation::initialAnimationDelay, &CSSStyleSelector::mapAnimationDelay, &RenderStyle::accessTransitions, &RenderStyle::transitions>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransitionDuration, ApplyPropertyAnimation<double, &Animation::duration, &Animation::setDuration, &Animation::isDurationSet, &Animation::clearDuration, &Animation::initialAnimationDuration, &CSSStyleSelector::mapAnimationDuration, &RenderStyle::accessTransitions, &RenderStyle::transitions>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransitionProperty, ApplyPropertyAnimation<int, &Animation::property, &Animation::setProperty, &Animation::isPropertySet, &Animation::clearProperty, &Animation::initialAnimationProperty, &CSSStyleSelector::mapAnimationProperty, &RenderStyle::accessTransitions, &RenderStyle::transitions>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTransitionTimingFunction, ApplyPropertyAnimation<const PassRefPtr<TimingFunction>, &Animation::timingFunction, &Animation::setTimingFunction, &Animation::isTimingFunctionSet, &Animation::clearTimingFunction, &Animation::initialAnimationTimingFunction, &CSSStyleSelector::mapAnimationTimingFunction, &RenderStyle::accessTransitions, &RenderStyle::transitions>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitColumnCount, ApplyPropertyAuto<unsigned short, &RenderStyle::columnCount, &RenderStyle::setColumnCount, &RenderStyle::hasAutoColumnCount, &RenderStyle::setHasAutoColumnCount>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitColumnGap, ApplyPropertyAuto<float, &RenderStyle::columnGap, &RenderStyle::setColumnGap, &RenderStyle::hasNormalColumnGap, &RenderStyle::setHasNormalColumnGap, ComputeLength, CSSValueNormal>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitColumnWidth, ApplyPropertyAuto<float, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth, &RenderStyle::hasAutoColumnWidth, &RenderStyle::setHasAutoColumnWidth, ComputeLength>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitColumns, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitFlowInto, ApplyPropertyString<MapAutoToNull, &RenderStyle::flowThread, &RenderStyle::setFlowThread, &RenderStyle::initialFlowThread>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitFlowFrom, ApplyPropertyString<MapNoneToNull, &RenderStyle::regionThread, &RenderStyle::setRegionThread, &RenderStyle::initialRegionThread>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitHighlight, ApplyPropertyString<MapNoneToNull, &RenderStyle::highlight, &RenderStyle::setHighlight, &RenderStyle::initialHighlight>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitHyphenateCharacter, ApplyPropertyString<MapAutoToNull, &RenderStyle::hyphenationString, &RenderStyle::setHyphenationString, &RenderStyle::initialHyphenationString>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitHyphenateLimitAfter, ApplyPropertyNumber<short, &RenderStyle::hyphenationLimitAfter, &RenderStyle::setHyphenationLimitAfter, &RenderStyle::initialHyphenationLimitAfter>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitHyphenateLimitBefore, ApplyPropertyNumber<short, &RenderStyle::hyphenationLimitBefore, &RenderStyle::setHyphenationLimitBefore, &RenderStyle::initialHyphenationLimitBefore>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitHyphenateLimitLines, ApplyPropertyNumber<short, &RenderStyle::hyphenationLimitLines, &RenderStyle::setHyphenationLimitLines, &RenderStyle::initialHyphenationLimitLines, CSSValueNoLimit>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitLineGrid, ApplyPropertyString<MapNoneToNull, &RenderStyle::lineGrid, &RenderStyle::setLineGrid, &RenderStyle::initialLineGrid>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitLineGridSnap, ApplyPropertyDefault<LineGridSnap, &RenderStyle::lineGridSnap, LineGridSnap, &RenderStyle::setLineGridSnap, LineGridSnap, &RenderStyle::initialLineGridSnap>::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitTextCombine, ApplyPropertyDefault<TextCombine, &RenderStyle::textCombine, TextCombine, &RenderStyle::setTextCombine, TextCombine, &RenderStyle::initialTextCombine>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTextEmphasisPosition, ApplyPropertyDefault<TextEmphasisPosition, &RenderStyle::textEmphasisPosition, TextEmphasisPosition, &RenderStyle::setTextEmphasisPosition, TextEmphasisPosition, &RenderStyle::initialTextEmphasisPosition>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitTextEmphasisStyle, ApplyPropertyTextEmphasisStyle::createHandler());
+
+ setPropertyHandler(CSSPropertyWebkitWrapMargin, ApplyPropertyLength<&RenderStyle::wrapMargin, &RenderStyle::setWrapMargin, &RenderStyle::initialWrapMargin>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitWrapPadding, ApplyPropertyLength<&RenderStyle::wrapPadding, &RenderStyle::setWrapPadding, &RenderStyle::initialWrapPadding>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitWrapFlow, ApplyPropertyDefault<WrapFlow, &RenderStyle::wrapFlow, WrapFlow, &RenderStyle::setWrapFlow, WrapFlow, &RenderStyle::initialWrapFlow>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitWrapThrough, ApplyPropertyDefault<WrapThrough, &RenderStyle::wrapThrough, WrapThrough, &RenderStyle::setWrapThrough, WrapThrough, &RenderStyle::initialWrapThrough>::createHandler());
+ setPropertyHandler(CSSPropertyWebkitWrap, ApplyPropertyExpanding<SuppressValue, CSSPropertyWebkitWrapFlow, CSSPropertyWebkitWrapMargin, CSSPropertyWebkitWrapPadding>::createHandler());
+
+ setPropertyHandler(CSSPropertyZIndex, ApplyPropertyAuto<int, &RenderStyle::zIndex, &RenderStyle::setZIndex, &RenderStyle::hasAutoZIndex, &RenderStyle::setHasAutoZIndex>::createHandler());
+ setPropertyHandler(CSSPropertyZoom, ApplyPropertyZoom::createHandler());
+}
+
+
+}
diff --git a/Source/WebCore/css/CSSStyleApplyProperty.h b/Source/WebCore/css/CSSStyleApplyProperty.h
new file mode 100644
index 000000000..2e83d0fc1
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleApplyProperty.h
@@ -0,0 +1,101 @@
+/*
+ * 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:
+ * 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 CSSStyleApplyProperty_h
+#define CSSStyleApplyProperty_h
+
+#include "CSSPropertyNames.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CSSStyleSelector;
+class CSSValue;
+class CSSStyleApplyProperty;
+
+class PropertyHandler {
+public:
+ typedef void (*InheritFunction)(CSSStyleSelector*);
+ typedef void (*InitialFunction)(CSSStyleSelector*);
+ typedef void (*ApplyFunction)(CSSStyleSelector*, CSSValue*);
+ PropertyHandler() : m_inherit(0), m_initial(0), m_apply(0) { }
+ PropertyHandler(InheritFunction inherit, InitialFunction initial, ApplyFunction apply) : m_inherit(inherit), m_initial(initial), m_apply(apply) { }
+ void applyInheritValue(CSSStyleSelector* selector) const { ASSERT(m_inherit); (*m_inherit)(selector); }
+ void applyInitialValue(CSSStyleSelector* selector) const { ASSERT(m_initial); (*m_initial)(selector); }
+ void applyValue(CSSStyleSelector* selector, CSSValue* value) const { ASSERT(m_apply); (*m_apply)(selector, value); }
+ bool isValid() const { return m_inherit && m_initial && m_apply; }
+ InheritFunction inheritFunction() const { return m_inherit; }
+ InitialFunction initialFunction() { return m_initial; }
+ ApplyFunction applyFunction() { return m_apply; }
+private:
+ InheritFunction m_inherit;
+ InitialFunction m_initial;
+ ApplyFunction m_apply;
+};
+
+class CSSStyleApplyProperty {
+ WTF_MAKE_NONCOPYABLE(CSSStyleApplyProperty);
+public:
+ static const CSSStyleApplyProperty& sharedCSSStyleApplyProperty();
+
+ const PropertyHandler& propertyHandler(CSSPropertyID property) const
+ {
+ ASSERT(valid(property));
+ return m_propertyMap[index(property)];
+ }
+private:
+ CSSStyleApplyProperty();
+ static int index(CSSPropertyID property)
+ {
+ return property - firstCSSProperty;
+ }
+
+ static bool valid(CSSPropertyID property)
+ {
+ int i = index(property);
+ return i >= 0 && i < numCSSProperties;
+ }
+
+ void setPropertyHandler(CSSPropertyID property, PropertyHandler handler)
+ {
+ ASSERT(valid(property));
+ ASSERT(!propertyHandler(property).isValid());
+ m_propertyMap[index(property)] = handler;
+ }
+
+ void setPropertyHandler(CSSPropertyID newProperty, CSSPropertyID equivalentProperty)
+ {
+ ASSERT(valid(newProperty));
+ ASSERT(valid(equivalentProperty));
+ ASSERT(!propertyHandler(newProperty).isValid());
+ m_propertyMap[index(newProperty)] = m_propertyMap[index(equivalentProperty)];
+ }
+
+ PropertyHandler m_propertyMap[numCSSProperties];
+};
+
+}
+
+#endif // CSSStyleApplyProperty_h
diff --git a/Source/WebCore/css/CSSStyleDeclaration.cpp b/Source/WebCore/css/CSSStyleDeclaration.cpp
new file mode 100644
index 000000000..a1d61b88f
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleDeclaration.cpp
@@ -0,0 +1,172 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 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 "CSSStyleDeclaration.h"
+
+#include "CSSElementStyleDeclaration.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSParser.h"
+#include "CSSProperty.h"
+#include "CSSPropertyNames.h"
+#include "CSSRule.h"
+#include "Node.h"
+#include "SVGElement.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/text/CString.h>
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace WTF;
+
+namespace WebCore {
+
+CSSStyleDeclaration::CSSStyleDeclaration(CSSRule* parent)
+ : m_strictParsing(!parent || parent->useStrictParsing())
+#ifndef NDEBUG
+ , m_iteratorCount(0)
+#endif
+ , m_isElementStyleDeclaration(false)
+ , 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)
+{
+ 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)
+{
+ 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)
+{
+ int propID = cssPropertyID(propertyName);
+ if (!propID)
+ return String();
+ return removeProperty(propID, ec);
+}
+
+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()
+{
+ fprintf(stderr, "%s\n", cssText().ascii().data());
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSStyleDeclaration.h b/Source/WebCore/css/CSSStyleDeclaration.h
new file mode 100644
index 000000000..a54b0c60a
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleDeclaration.h
@@ -0,0 +1,111 @@
+/*
+ * (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 CSSStyleDeclaration_h
+#define CSSStyleDeclaration_h
+
+#include "CSSRule.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class CSSMutableStyleDeclaration;
+class CSSProperty;
+class CSSStyleSheet;
+class CSSValue;
+
+typedef int ExceptionCode;
+
+class CSSStyleDeclaration : public RefCounted<CSSStyleDeclaration> {
+ WTF_MAKE_NONCOPYABLE(CSSStyleDeclaration);
+public:
+ virtual ~CSSStyleDeclaration() { }
+
+ static bool isPropertyName(const String&);
+
+ CSSRule* parentRule() const { return m_parentRule; }
+ void clearParentRule() { m_parentRule = 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 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<CSSMutableStyleDeclaration> copy() const = 0;
+ virtual PassRefPtr<CSSMutableStyleDeclaration> makeMutable() = 0;
+
+ void diff(CSSMutableStyleDeclaration*) const;
+
+ PassRefPtr<CSSMutableStyleDeclaration> copyPropertiesInSet(const int* set, unsigned length) const;
+
+#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;
+
+ // 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;
+};
+
+} // namespace WebCore
+
+#endif // CSSStyleDeclaration_h
diff --git a/Source/WebCore/css/CSSStyleDeclaration.idl b/Source/WebCore/css/CSSStyleDeclaration.idl
new file mode 100644
index 000000000..d1b470f87
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleDeclaration.idl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface [
+ CustomMarkFunction,
+ GenerateIsReachable=ImplRoot,
+ DelegatingPutFunction,
+ HasNameGetter,
+ HasIndexGetter,
+ CustomGetPropertyNames,
+ V8DependentLifetime
+ ] CSSStyleDeclaration {
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText
+ setter raises(DOMException);
+
+ [ConvertNullStringTo=Null] DOMString getPropertyValue(in [Optional=CallWithDefaultValue] DOMString propertyName);
+ [JSCCustom] CSSValue getPropertyCSSValue(in [Optional=CallWithDefaultValue] DOMString propertyName);
+ [ConvertNullStringTo=Null] DOMString removeProperty(in [Optional=CallWithDefaultValue] DOMString propertyName)
+ 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 [Optional=CallWithDefaultValue] DOMString priority)
+ raises(DOMException);
+
+ readonly attribute unsigned long length;
+ DOMString item(in [Optional=CallWithDefaultValue] unsigned long index);
+ readonly attribute CSSRule parentRule;
+
+ // Extensions
+ [ConvertNullStringTo=Null] DOMString getPropertyShorthand(in [Optional=CallWithDefaultValue] DOMString propertyName);
+ boolean isPropertyImplicit(in [Optional=CallWithDefaultValue] DOMString propertyName);
+ };
+
+}
diff --git a/Source/WebCore/css/CSSStyleRule.cpp b/Source/WebCore/css/CSSStyleRule.cpp
new file mode 100644
index 000000000..6296e64b7
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleRule.cpp
@@ -0,0 +1,150 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 "CSSStyleRule.h"
+
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPageRule.h"
+#include "CSSParser.h"
+#include "CSSSelector.h"
+#include "CSSStyleSheet.h"
+#include "Document.h"
+#include "StyledElement.h"
+#include "StyleSheet.h"
+
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+CSSStyleRule::CSSStyleRule(CSSStyleSheet* parent, int line, CSSRule::Type type)
+ : CSSRule(parent, type)
+{
+ setSourceLine(line);
+
+ // m_sourceLine is a bitfield, so let's catch any overflow early in debug mode.
+ ASSERT(sourceLine() == line);
+}
+
+CSSStyleRule::~CSSStyleRule()
+{
+ if (m_style)
+ m_style->clearParentRule();
+ cleanup();
+}
+
+typedef HashMap<const CSSStyleRule*, String> SelectorTextCache;
+static SelectorTextCache& selectorTextCache()
+{
+ DEFINE_STATIC_LOCAL(SelectorTextCache, cache, ());
+ return cache;
+}
+
+inline void CSSStyleRule::cleanup()
+{
+ if (hasCachedSelectorText()) {
+ selectorTextCache().remove(this);
+ setHasCachedSelectorText(false);
+ }
+}
+
+String CSSStyleRule::generateSelectorText() const
+{
+ if (isPageRule())
+ return static_cast<const CSSPageRule*>(this)->pageSelectorText();
+ else {
+ StringBuilder builder;
+ for (CSSSelector* s = selectorList().first(); s; s = CSSSelectorList::next(s)) {
+ if (s != selectorList().first())
+ builder.append(", ");
+ builder.append(s->selectorText());
+ }
+ return builder.toString();
+ }
+}
+
+String CSSStyleRule::selectorText() const
+{
+ if (hasCachedSelectorText()) {
+ ASSERT(selectorTextCache().contains(this));
+ return selectorTextCache().get(this);
+ }
+
+ ASSERT(!selectorTextCache().contains(this));
+ String text = generateSelectorText();
+ selectorTextCache().set(this, text);
+ setHasCachedSelectorText(true);
+ return text;
+}
+
+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;
+
+ CSSParser p;
+ CSSSelectorList selectorList;
+ p.parseSelector(selectorText, doc, selectorList);
+ if (!selectorList.first())
+ return;
+
+ String oldSelectorText = this->selectorText();
+ m_selectorList.adopt(selectorList);
+
+ if (hasCachedSelectorText()) {
+ ASSERT(selectorTextCache().contains(this));
+ selectorTextCache().set(this, generateSelectorText());
+ }
+
+ if (this->selectorText() == oldSelectorText)
+ return;
+
+ doc->styleSelectorChanged(DeferRecalcStyle);
+}
+
+String CSSStyleRule::cssText() const
+{
+ String result = selectorText();
+
+ result += " { ";
+ result += m_style->cssText();
+ result += "}";
+
+ return result;
+}
+
+void CSSStyleRule::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
+{
+ if (m_style)
+ m_style->addSubresourceStyleURLs(urls);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSStyleRule.h b/Source/WebCore/css/CSSStyleRule.h
new file mode 100644
index 000000000..111c5f1aa
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleRule.h
@@ -0,0 +1,73 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 CSSStyleRule_h
+#define CSSStyleRule_h
+
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSRule.h"
+#include "CSSSelectorList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSSelector;
+
+class CSSStyleRule : public CSSRule {
+public:
+ static PassRefPtr<CSSStyleRule> create(CSSStyleSheet* parent, int sourceLine)
+ {
+ return adoptRef(new CSSStyleRule(parent, sourceLine));
+ }
+ ~CSSStyleRule();
+
+ String selectorText() const;
+ void setSelectorText(const String&);
+
+ CSSMutableStyleDeclaration* 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; }
+
+ const CSSSelectorList& selectorList() const { return m_selectorList; }
+ CSSMutableStyleDeclaration* declaration() { return m_style.get(); }
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>& urls);
+
+ using CSSRule::sourceLine;
+
+protected:
+ CSSStyleRule(CSSStyleSheet* parent, int sourceLine, CSSRule::Type = CSSRule::STYLE_RULE);
+
+private:
+ void cleanup();
+ String generateSelectorText() const;
+
+ RefPtr<CSSMutableStyleDeclaration> m_style;
+ CSSSelectorList m_selectorList;
+};
+
+} // namespace WebCore
+
+#endif // CSSStyleRule_h
diff --git a/Source/WebCore/css/CSSStyleRule.idl b/Source/WebCore/css/CSSStyleRule.idl
new file mode 100644
index 000000000..4abfbfc45
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleRule.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSStyleRule : CSSRule {
+
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString selectorText;
+
+ readonly attribute CSSStyleDeclaration style;
+
+ };
+
+}
diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp
new file mode 100644
index 000000000..b0282c120
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleSelector.cpp
@@ -0,0 +1,5400 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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 "CSSStyleSelector.h"
+
+#include "Attribute.h"
+#include "CachedImage.h"
+#include "ContentData.h"
+#include "Counter.h"
+#include "CounterContent.h"
+#include "CSSBorderImageValue.h"
+#include "CSSCursorImageValue.h"
+#include "CSSFontFaceRule.h"
+#include "CSSFontSelector.h"
+#include "CSSImportRule.h"
+#include "CSSLineBoxContainValue.h"
+#include "CSSMediaRule.h"
+#include "CSSPageRule.h"
+#include "CSSParser.h"
+#include "CSSPrimitiveValueMappings.h"
+#include "CSSPropertyNames.h"
+#include "CSSReflectValue.h"
+#include "CSSRuleList.h"
+#include "CSSSelector.h"
+#include "CSSSelectorList.h"
+#include "CSSStyleApplyProperty.h"
+#include "CSSStyleRule.h"
+#include "CSSStyleSheet.h"
+#include "CSSTimingFunctionValue.h"
+#include "CSSValueList.h"
+#include "CursorList.h"
+#include "FontFamilyValue.h"
+#include "FontFeatureValue.h"
+#include "FontValue.h"
+#include "Frame.h"
+#include "FrameSelection.h"
+#include "FrameView.h"
+#include "HTMLDocument.h"
+#include "HTMLElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "HTMLProgressElement.h"
+#include "HTMLTextAreaElement.h"
+#include "InspectorInstrumentation.h"
+#include "KeyframeList.h"
+#include "LinkHash.h"
+#include "LocaleToScriptMapping.h"
+#include "Matrix3DTransformOperation.h"
+#include "MatrixTransformOperation.h"
+#include "MediaList.h"
+#include "MediaQueryEvaluator.h"
+#include "NodeRenderStyle.h"
+#include "Page.h"
+#include "PageGroup.h"
+#include "Pair.h"
+#include "PerspectiveTransformOperation.h"
+#include "QuotesData.h"
+#include "Rect.h"
+#include "RenderScrollbar.h"
+#include "RenderScrollbarTheme.h"
+#include "RenderStyleConstants.h"
+#include "RenderTheme.h"
+#include "RotateTransformOperation.h"
+#include "ScaleTransformOperation.h"
+#include "SecurityOrigin.h"
+#include "Settings.h"
+#include "ShadowData.h"
+#include "ShadowValue.h"
+#include "SkewTransformOperation.h"
+#include "StyleCachedImage.h"
+#include "StylePendingImage.h"
+#include "StyleGeneratedImage.h"
+#include "StyleSheetList.h"
+#include "Text.h"
+#include "TransformationMatrix.h"
+#include "TranslateTransformOperation.h"
+#include "UserAgentStyleSheets.h"
+#include "WebKitCSSKeyframeRule.h"
+#include "WebKitCSSKeyframesRule.h"
+#include "WebKitCSSRegionRule.h"
+#include "WebKitCSSTransformValue.h"
+#include "WebKitFontFamilyNames.h"
+#include "XMLNames.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(CSS_FILTERS)
+#include "FilterOperation.h"
+#include "WebKitCSSFilterValue.h"
+#endif
+
+#if ENABLE(DASHBOARD_SUPPORT)
+#include "DashboardRegion.h"
+#endif
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+#if ENABLE(CSS_SHADERS)
+#include "CustomFilterOperation.h"
+#include "StyleCachedShader.h"
+#include "StylePendingShader.h"
+#include "StyleShader.h"
+#include "WebKitCSSShaderValue.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+#define HANDLE_INHERIT(prop, Prop) \
+if (isInherit) { \
+ m_style->set##Prop(m_parentStyle->prop()); \
+ return; \
+}
+
+#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
+HANDLE_INHERIT(prop, Prop) \
+if (isInitial) { \
+ m_style->set##Prop(RenderStyle::initial##Prop()); \
+ return; \
+}
+
+#define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
+HANDLE_INHERIT(prop, Prop) \
+if (isInitial) { \
+ m_style->set##Prop(RenderStyle::initial##Value());\
+ return;\
+}
+
+#define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
+HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
+if (primitiveValue) \
+ m_style->set##Prop(*primitiveValue);
+
+#define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
+HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
+if (primitiveValue) \
+ m_style->set##Prop(*primitiveValue);
+
+class RuleData {
+public:
+ RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
+
+ unsigned position() const { return m_position; }
+ CSSStyleRule* rule() const { return m_rule; }
+ CSSSelector* selector() const { return m_selector; }
+
+ bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
+ bool hasMultipartSelector() const { return m_hasMultipartSelector; }
+ bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
+ bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
+ unsigned specificity() const { return m_specificity; }
+ unsigned linkMatchType() const { return m_linkMatchType; }
+
+ // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
+ static const unsigned maximumIdentifierCount = 4;
+ const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
+
+private:
+ CSSStyleRule* m_rule;
+ CSSSelector* m_selector;
+ unsigned m_specificity;
+ // This number was picked fairly arbitrarily. We can probably lower it if we need to.
+ // Some simple testing showed <100,000 RuleData's on large sites.
+ unsigned m_position : 26;
+ unsigned m_hasFastCheckableSelector : 1;
+ unsigned m_hasMultipartSelector : 1;
+ unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
+ unsigned m_containsUncommonAttributeSelector : 1;
+ unsigned m_linkMatchType : 2; // SelectorChecker::LinkMatchMask
+ // Use plain array instead of a Vector to minimize memory overhead.
+ unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
+};
+
+struct SameSizeAsRuleData {
+ void* a;
+ void* b;
+ unsigned c;
+ unsigned d;
+ unsigned e[4];
+};
+
+COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
+
+class RuleSet {
+ WTF_MAKE_NONCOPYABLE(RuleSet);
+public:
+ RuleSet();
+
+ typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap;
+
+ void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
+
+ void addStyleRule(CSSStyleRule* item);
+ void addRule(CSSStyleRule* rule, CSSSelector* sel);
+ void addPageRule(CSSPageRule*);
+ void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, CSSStyleRule*, CSSSelector*);
+ void shrinkToFit();
+ void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
+
+ void collectFeatures(CSSStyleSelector::Features&) const;
+
+ const Vector<RuleData>* idRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
+ const Vector<RuleData>* classRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
+ const Vector<RuleData>* tagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
+ const Vector<RuleData>* shadowPseudoElementRules(AtomicStringImpl* key) const { return m_shadowPseudoElementRules.get(key); }
+ const Vector<RuleData>* linkPseudoClassRules() const { return &m_linkPseudoClassRules; }
+ const Vector<RuleData>* focusPseudoClassRules() const { return &m_focusPseudoClassRules; }
+ const Vector<RuleData>* universalRules() const { return &m_universalRules; }
+ const Vector<RuleData>* pageRules() const { return &m_pageRules; }
+
+public:
+ AtomRuleMap m_idRules;
+ AtomRuleMap m_classRules;
+ AtomRuleMap m_tagRules;
+ AtomRuleMap m_shadowPseudoElementRules;
+ Vector<RuleData> m_linkPseudoClassRules;
+ Vector<RuleData> m_focusPseudoClassRules;
+ Vector<RuleData> m_universalRules;
+ Vector<RuleData> m_pageRules;
+ unsigned m_ruleCount;
+ bool m_autoShrinkToFitEnabled;
+};
+
+static RuleSet* defaultStyle;
+static RuleSet* defaultQuirksStyle;
+static RuleSet* defaultPrintStyle;
+static RuleSet* defaultViewSourceStyle;
+static CSSStyleSheet* simpleDefaultStyleSheet;
+
+static RuleSet* siblingRulesInDefaultStyle;
+static RuleSet* uncommonAttributeRulesInDefaultStyle;
+
+RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
+
+static void loadFullDefaultStyle();
+static void loadSimpleDefaultStyle();
+// FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
+static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
+
+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"));
+ return staticScreenEval;
+}
+
+static const MediaQueryEvaluator& printEval()
+{
+ DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
+ return staticPrintEval;
+}
+
+static CSSMutableStyleDeclaration* leftToRightDeclaration()
+{
+ DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create()));
+ if (!leftToRightDecl->length()) {
+ leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false);
+ leftToRightDecl->setStrictParsing(false);
+ }
+ 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);
+ }
+ return rightToLeftDecl.get();
+}
+
+CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
+ CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets,
+ bool strictParsing, bool matchAuthorAndUserStyles)
+ : m_hasUAAppearance(false)
+ , m_backgroundData(BackgroundFillLayer)
+ , m_checker(document, strictParsing)
+ , m_parentStyle(0)
+ , m_rootElementStyle(0)
+ , m_element(0)
+ , m_styledElement(0)
+ , m_elementLinkState(NotInsideLink)
+ , m_parentNode(0)
+ , m_lineHeightValue(0)
+ , m_fontDirty(false)
+ , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
+ , m_sameOriginOnly(false)
+ , m_fontSelector(CSSFontSelector::create(document))
+ , m_applyPropertyToRegularStyle(true)
+ , m_applyPropertyToVisitedLinkStyle(false)
+ , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
+#if ENABLE(CSS_SHADERS)
+ , m_hasPendingShaders(false)
+#endif
+{
+ Element* root = document->documentElement();
+
+ if (!defaultStyle) {
+ if (!root || elementCanUseSimpleDefaultStyle(root))
+ loadSimpleDefaultStyle();
+ else {
+ loadFullDefaultStyle();
+ }
+ }
+
+ // construct document root element default style. this is needed
+ // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
+ // This is here instead of constructor, because when constructor is run,
+ // document doesn't have documentElement
+ // NOTE: this assumes that element that gets passed to styleForElement -call
+ // is always from the document that owns the style selector
+ FrameView* view = document->view();
+ if (view)
+ m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
+ else
+ m_medium = adoptPtr(new MediaQueryEvaluator("all"));
+
+ if (root)
+ m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
+
+ if (m_rootDefaultStyle && view)
+ m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
+
+ m_authorStyle = adoptPtr(new RuleSet);
+ // Adding rules from multiple sheets, shrink at the end.
+ m_authorStyle->disableAutoShrinkToFit();
+
+ // FIXME: This sucks! The user sheet is reparsed every time!
+ OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
+ if (pageUserSheet)
+ tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
+ if (pageGroupUserSheets) {
+ unsigned length = pageGroupUserSheets->size();
+ for (unsigned i = 0; i < length; i++) {
+ if (pageGroupUserSheets->at(i)->isUserStyleSheet())
+ tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
+ else
+ m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
+ }
+ }
+ if (documentUserSheets) {
+ unsigned length = documentUserSheets->size();
+ for (unsigned i = 0; i < length; i++) {
+ if (documentUserSheets->at(i)->isUserStyleSheet())
+ tempUserStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
+ else
+ m_authorStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
+ }
+ }
+
+ if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
+ m_userStyle = tempUserStyle.release();
+
+ // Add rules from elements like SVG's <font-face>
+ if (mappedElementSheet)
+ 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();
+
+ if (document->renderer() && document->renderer()->style())
+ document->renderer()->style()->font().update(fontSelector());
+}
+
+void CSSStyleSelector::collectFeatures()
+{
+ // 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);
+ if (m_userStyle)
+ m_userStyle->collectFeatures(m_features);
+ if (m_features.siblingRules)
+ m_features.siblingRules->shrinkToFit();
+ if (m_features.uncommonAttributeRules)
+ m_features.uncommonAttributeRules->shrinkToFit();
+}
+
+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
+ // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
+ unsigned size = stylesheets.size();
+ 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);
+ }
+ 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)
+{
+ m_regionStyleRules.append(regionStyleRule);
+}
+
+// This is a simplified style setting function for keyframe styles
+void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
+{
+ AtomicString s(rule->name());
+ m_keyframesRuleMap.set(s.impl(), rule);
+}
+
+CSSStyleSelector::~CSSStyleSelector()
+{
+ m_fontSelector->clearDocument();
+ deleteAllValues(m_viewportDependentMediaQueryResults);
+}
+
+CSSStyleSelector::Features::Features()
+ : usesFirstLineRules(false)
+ , usesBeforeAfterRules(false)
+ , usesLinkRules(false)
+{
+}
+
+CSSStyleSelector::Features::~Features()
+{
+}
+
+void CSSStyleSelector::Features::clear()
+{
+ idsInRules.clear();
+ attrsInRules.clear();
+ siblingRules.clear();
+ uncommonAttributeRules.clear();
+ usesFirstLineRules = false;
+ usesBeforeAfterRules = false;
+ usesLinkRules = false;
+}
+
+static CSSStyleSheet* parseUASheet(const String& str)
+{
+ CSSStyleSheet* sheet = CSSStyleSheet::create().leakRef(); // leak the sheet on purpose
+ sheet->parseString(str);
+ return sheet;
+}
+
+static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
+{
+ return parseUASheet(String(characters, size));
+}
+
+static void loadFullDefaultStyle()
+{
+ if (simpleDefaultStyleSheet) {
+ ASSERT(defaultStyle);
+ ASSERT(defaultPrintStyle == defaultStyle);
+ delete defaultStyle;
+ simpleDefaultStyleSheet->deref();
+ defaultStyle = new RuleSet;
+ defaultPrintStyle = new RuleSet;
+ simpleDefaultStyleSheet = 0;
+ } else {
+ ASSERT(!defaultStyle);
+ defaultStyle = new RuleSet;
+ defaultPrintStyle = new RuleSet;
+ defaultQuirksStyle = new RuleSet;
+ }
+
+ // Strict-mode rules.
+ String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
+ CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
+ defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
+ defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
+
+ // Quirks-mode rules.
+ String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
+ CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
+ defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
+}
+
+static void loadSimpleDefaultStyle()
+{
+ ASSERT(!defaultStyle);
+ ASSERT(!simpleDefaultStyleSheet);
+
+ defaultStyle = new RuleSet;
+ // There are no media-specific rules in the simple default style.
+ defaultPrintStyle = defaultStyle;
+ defaultQuirksStyle = new RuleSet;
+
+ simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
+ defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
+
+ // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
+}
+
+static void loadViewSourceStyle()
+{
+ ASSERT(!defaultViewSourceStyle);
+ defaultViewSourceStyle = new RuleSet;
+ defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
+}
+
+static void ensureDefaultStyleSheetsForElement(Element* element)
+{
+ if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) {
+ loadFullDefaultStyle();
+ assertNoSiblingRulesInDefaultStyle();
+ collectSpecialRulesInDefaultStyle();
+ }
+
+#if ENABLE(SVG)
+ static bool loadedSVGUserAgentSheet;
+ if (element->isSVGElement() && !loadedSVGUserAgentSheet) {
+ // SVG rules.
+ loadedSVGUserAgentSheet = true;
+ CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
+ defaultStyle->addRulesFromSheet(svgSheet, screenEval());
+ defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
+ assertNoSiblingRulesInDefaultStyle();
+ collectSpecialRulesInDefaultStyle();
+ }
+#endif
+
+#if ENABLE(MATHML)
+ static bool loadedMathMLUserAgentSheet;
+ 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
+
+#if ENABLE(VIDEO)
+ static bool loadedMediaStyleSheet;
+ if (!loadedMediaStyleSheet && (element->hasTagName(videoTag) || element->hasTagName(audioTag))) {
+ loadedMediaStyleSheet = true;
+ String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
+ CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
+ defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
+ defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
+ collectSpecialRulesInDefaultStyle();
+ }
+#endif
+
+#if ENABLE(FULLSCREEN_API)
+ static bool loadedFullScreenStyleSheet;
+ if (!loadedFullScreenStyleSheet && element->document()->webkitIsFullScreen()) {
+ loadedFullScreenStyleSheet = true;
+ String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
+ CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
+ defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
+ defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
+ collectSpecialRulesInDefaultStyle();
+ }
+#endif
+}
+
+CSSStyleSelector::MatchedStyleDeclaration::MatchedStyleDeclaration()
+{
+ // Make sure all memory is zero initializes as we calculate hash over the bytes of this object.
+ memset(this, 0, sizeof(*this));
+}
+
+void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* styleDeclaration, unsigned linkMatchType)
+{
+ m_matchedDecls.grow(m_matchedDecls.size() + 1);
+ MatchedStyleDeclaration& newDeclaration = m_matchedDecls.last();
+ newDeclaration.styleDeclaration = styleDeclaration;
+ newDeclaration.linkMatchType = linkMatchType;
+}
+
+void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
+{
+ m_matchedRules.clear();
+
+ if (!rules || !m_element)
+ return;
+
+ // 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);
+ 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);
+ }
+ const AtomicString& pseudoId = m_element->shadowPseudoId();
+ if (!pseudoId.isEmpty()) {
+ ASSERT(m_styledElement);
+ matchRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
+ }
+ if (m_element->isLink())
+ matchRulesForList(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);
+
+ if (m_matchedRules.isEmpty())
+ return;
+
+ sortMatchedRules();
+
+ if (m_checker.isCollectingRulesOnly()) {
+ if (!m_ruleList)
+ m_ruleList = CSSRuleList::create();
+ for (unsigned i = 0; i < m_matchedRules.size(); ++i)
+ m_ruleList->append(m_matchedRules[i]->rule());
+ return;
+ }
+
+ // Now transfer the set of matched rules over to our list of declarations.
+ // FIXME: This sucks, the inspector should get the style from the visited style itself.
+ bool swapVisitedUnvisited = InspectorInstrumentation::forcePseudoState(m_element, CSSSelector::PseudoVisited);
+ for (unsigned i = 0; i < m_matchedRules.size(); i++) {
+ if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector())
+ m_style->setAffectedByUncommonAttributeSelectors();
+ unsigned linkMatchType = m_matchedRules[i]->linkMatchType();
+ if (swapVisitedUnvisited && linkMatchType && linkMatchType != SelectorChecker::MatchAll)
+ linkMatchType = (linkMatchType == SelectorChecker::MatchVisited) ? SelectorChecker::MatchLink : SelectorChecker::MatchVisited;
+ addMatchedDeclaration(m_matchedRules[i]->rule()->declaration(), linkMatchType);
+ }
+}
+
+class MatchingUARulesScope {
+public:
+ MatchingUARulesScope();
+ ~MatchingUARulesScope();
+
+ static bool isMatchingUARules();
+
+private:
+ static bool m_matchingUARules;
+};
+
+MatchingUARulesScope::MatchingUARulesScope()
+{
+ ASSERT(!m_matchingUARules);
+ m_matchingUARules = true;
+}
+
+MatchingUARulesScope::~MatchingUARulesScope()
+{
+ m_matchingUARules = false;
+}
+
+inline bool MatchingUARulesScope::isMatchingUARules()
+{
+ return m_matchingUARules;
+}
+
+bool MatchingUARulesScope::m_matchingUARules = false;
+
+inline static bool matchesInTreeScope(TreeScope* treeScope, bool ruleReachesIntoShadowDOM)
+{
+ return MatchingUARulesScope::isMatchingUARules() || treeScope->applyAuthorSheets() || ruleReachesIntoShadowDOM;
+}
+
+void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
+{
+ if (!rules)
+ return;
+ // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
+ // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
+ bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
+
+ unsigned size = rules->size();
+ for (unsigned i = 0; i < size; ++i) {
+ const RuleData& ruleData = rules->at(i);
+ if (canUseFastReject && m_checker.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
+ continue;
+
+ CSSStyleRule* rule = ruleData.rule();
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
+ if (checkSelector(ruleData)) {
+ if (!matchesInTreeScope(m_element->treeScope(), m_checker.hasUnknownPseudoElements())) {
+ InspectorInstrumentation::didMatchRule(cookie, false);
+ continue;
+ }
+ // 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)) {
+ InspectorInstrumentation::didMatchRule(cookie, false);
+ continue;
+ }
+ if (m_sameOriginOnly && !m_checker.document()->securityOrigin()->canRequest(rule->baseURL())) {
+ InspectorInstrumentation::didMatchRule(cookie, false);
+ continue;
+ }
+ // If we're matching normal rules, set a pseudo bit if
+ // we really just matched a pseudo-element.
+ if (m_dynamicPseudo != NOPSEUDO && m_checker.pseudoStyle() == NOPSEUDO) {
+ if (m_checker.isCollectingRulesOnly()) {
+ InspectorInstrumentation::didMatchRule(cookie, false);
+ continue;
+ }
+ if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
+ m_style->setHasPseudoStyle(m_dynamicPseudo);
+ } else {
+ // Update our first/last rule indices in the matched rules array.
+ lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
+ if (firstRuleIndex == -1)
+ firstRuleIndex = lastRuleIndex;
+
+ // Add this rule to our list of matched rules.
+ addMatchedRule(&ruleData);
+ InspectorInstrumentation::didMatchRule(cookie, true);
+ continue;
+ }
+ }
+ InspectorInstrumentation::didMatchRule(cookie, false);
+ }
+}
+
+static inline bool compareRules(const RuleData* r1, const RuleData* r2)
+{
+ unsigned specificity1 = r1->specificity();
+ unsigned specificity2 = r2->specificity();
+ return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
+}
+
+void CSSStyleSelector::sortMatchedRules()
+{
+ std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
+}
+
+void CSSStyleSelector::matchAllRules(MatchResult& result)
+{
+ matchUARules(result);
+
+ // Now we check user sheet rules.
+ if (m_matchAuthorAndUserStyles)
+ matchRules(m_userStyle.get(), result.firstUserRule, result.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();
+ for (unsigned i = 0; i < map->length(); ++i) {
+ Attribute* attr = map->attributeItem(i);
+ if (attr->isMappedAttribute() && attr->decl()) {
+ result.lastAuthorRule = m_matchedDecls.size();
+ if (result.firstAuthorRule == -1)
+ result.firstAuthorRule = result.lastAuthorRule;
+ addMatchedDeclaration(attr->decl());
+ result.isCacheable = false;
+ }
+ }
+ }
+
+ // 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 (m_styledElement->isHTMLElement()) {
+ bool isAuto;
+ TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
+ if (isAuto)
+ addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
+ }
+ }
+
+ // Check the rules in author sheets next.
+ if (m_matchAuthorAndUserStyles)
+ matchRules(m_authorStyle.get(), result.firstAuthorRule, result.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;
+ addMatchedDeclaration(inlineDecl);
+ result.isCacheable = false;
+ }
+ }
+}
+
+inline void CSSStyleSelector::initElement(Element* e)
+{
+ if (m_element != e) {
+ m_element = e;
+ m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
+ m_elementLinkState = m_checker.determineLinkState(m_element);
+ if (e && e == e->document()->documentElement()) {
+ e->document()->setDirectionSetOnDocumentElement(false);
+ e->document()->setWritingModeSetOnDocumentElement(false);
+ }
+ }
+}
+
+inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
+{
+ m_checker.setPseudoStyle(pseudoID);
+
+ m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
+
+ if (parentStyle)
+ m_parentStyle = parentStyle;
+ else
+ m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
+
+ Node* docElement = e ? e->document()->documentElement() : 0;
+ RenderStyle* docStyle = m_checker.document()->renderStyle();
+ m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
+
+ m_style = 0;
+
+ m_matchedDecls.clear();
+
+ m_pendingImageProperties.clear();
+
+ m_ruleList = 0;
+
+ m_fontDirty = false;
+}
+
+static const unsigned cStyleSearchThreshold = 10;
+static const unsigned cStyleSearchLevelThreshold = 10;
+
+Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
+{
+ if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
+ return 0;
+ if (!parent || !parent->isStyledElement())
+ return 0;
+ StyledElement* p = static_cast<StyledElement*>(parent);
+ if (p->inlineStyleDecl())
+ return 0;
+ if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
+ return 0;
+
+ RenderStyle* parentStyle = p->renderStyle();
+ unsigned subcount = 0;
+ Node* thisCousin = p;
+ Node* currentNode = p->previousSibling();
+
+ // Reserve the tries for this level. This effectively makes sure that the algorithm
+ // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
+ visitedNodeCount += cStyleSearchThreshold;
+ while (thisCousin) {
+ while (currentNode) {
+ ++subcount;
+ if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
+ // Adjust for unused reserved tries.
+ visitedNodeCount -= cStyleSearchThreshold - subcount;
+ return currentNode->lastChild();
+ }
+ if (subcount >= cStyleSearchThreshold)
+ return 0;
+ currentNode = currentNode->previousSibling();
+ }
+ currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
+ thisCousin = currentNode;
+ }
+
+ return 0;
+}
+
+bool CSSStyleSelector::matchesRuleSet(RuleSet* ruleSet)
+{
+ int firstSiblingRule = -1, lastSiblingRule = -1;
+ matchRules(ruleSet, firstSiblingRule, lastSiblingRule, false);
+ if (m_matchedDecls.isEmpty())
+ return false;
+ m_matchedDecls.clear();
+ return true;
+}
+
+bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const
+{
+#if ENABLE(PROGRESS_TAG)
+ if (element->hasTagName(progressTag)) {
+ if (!m_element->hasTagName(progressTag))
+ return false;
+
+ HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
+ HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
+ if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
+ return false;
+
+ return true;
+ }
+#endif
+
+ HTMLInputElement* thisInputElement = element->toInputElement();
+ HTMLInputElement* otherInputElement = m_element->toInputElement();
+
+ if (!thisInputElement || !otherInputElement)
+ return false;
+
+ if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
+ return false;
+ if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
+ return false;
+ if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
+ return false;
+ if (thisInputElement->required() != otherInputElement->required())
+ return false;
+
+ if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
+ return false;
+
+ if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
+ return false;
+
+ if (!m_element->document()->containsValidityStyleRules())
+ return false;
+
+ bool willValidate = element->willValidate();
+
+ if (willValidate != m_element->willValidate())
+ return false;
+
+ if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
+ return false;
+
+ if (element->isInRange() != m_element->isInRange())
+ return false;
+
+ if (element->isOutOfRange() != m_element->isOutOfRange())
+ return false;
+
+ return true;
+}
+
+bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const
+{
+ RenderStyle* style = element->renderStyle();
+
+ if (!style)
+ return false;
+ if (style->unique())
+ return false;
+ if (element->tagQName() != m_element->tagQName())
+ return false;
+ if (element->hasClass() != m_element->hasClass())
+ return false;
+ if (element->inlineStyleDecl())
+ return false;
+ if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes())
+ return false;
+ if (element->isLink() != m_element->isLink())
+ return false;
+ if (style->affectedByUncommonAttributeSelectors())
+ return false;
+ if (element->hovered() != m_element->hovered())
+ return false;
+ if (element->active() != m_element->active())
+ return false;
+ if (element->focused() != m_element->focused())
+ return false;
+ if (element->shadowPseudoId() != m_element->shadowPseudoId())
+ return false;
+ if (element == element->document()->cssTarget())
+ return false;
+ if (m_element == m_element->document()->cssTarget())
+ return false;
+ if (element->getAttribute(typeAttr) != m_element->getAttribute(typeAttr))
+ return false;
+ if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
+ return false;
+ if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
+ return false;
+ if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
+ return false;
+ if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
+ return false;
+
+ if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
+ return false;
+
+ bool isControl = element->isFormControlElement();
+
+ if (isControl != m_element->isFormControlElement())
+ return false;
+
+ if (isControl && !canShareStyleWithControl(element))
+ return false;
+
+ if (style->transitions() || style->animations())
+ return false;
+
+#if USE(ACCELERATED_COMPOSITING)
+ // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
+ // See comments in RenderObject::setStyle().
+ if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)
+#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
+ // With proxying, the media elements are backed by a RenderEmbeddedObject.
+ || element->hasTagName(videoTag) || element->hasTagName(audioTag)
+#endif
+ )
+ return false;
+#endif
+
+ if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto"))
+ return false;
+
+ if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr))
+ return false;
+
+ if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()))
+ return false;
+
+ if (element->isLink() && m_elementLinkState != style->insideLink())
+ return false;
+
+ return true;
+}
+
+inline StyledElement* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
+{
+ for (; node; node = node->previousSibling()) {
+ if (!node->isStyledElement())
+ continue;
+ if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
+ break;
+ if (count++ == cStyleSearchThreshold)
+ return 0;
+ }
+ return static_cast<StyledElement*>(node);
+}
+
+static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
+{
+ return parentStyle->childrenAffectedByPositionalRules()
+ || parentStyle->childrenAffectedByFirstChildRules()
+ || parentStyle->childrenAffectedByLastChildRules()
+ || parentStyle->childrenAffectedByDirectAdjacentRules();
+}
+
+RenderStyle* CSSStyleSelector::locateSharedStyle()
+{
+ if (!m_styledElement || !m_parentStyle)
+ return 0;
+ // If the element has inline style it is probably unique.
+ if (m_styledElement->inlineStyleDecl())
+ return 0;
+ // Ids stop style sharing if they show up in the stylesheets.
+ if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
+ return 0;
+ if (parentStylePreventsSharing(m_parentStyle))
+ return 0;
+
+ // Check previous siblings and their cousins.
+ unsigned count = 0;
+ unsigned visitedNodeCount = 0;
+ StyledElement* shareElement = 0;
+ Node* cousinList = m_styledElement->previousSibling();
+ while (cousinList) {
+ shareElement = findSiblingForStyleSharing(cousinList, count);
+ if (shareElement)
+ break;
+ cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
+ }
+
+ // If we have exhausted all our budget or our cousins.
+ if (!shareElement)
+ 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()))
+ return 0;
+ // Can't share if attribute rules apply.
+ if (matchesRuleSet(m_features.uncommonAttributeRules.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))
+ return 0;
+ return shareElement->renderStyle();
+}
+
+void CSSStyleSelector::matchUARules(MatchResult& result)
+{
+ MatchingUARulesScope scope;
+
+ // First we match rules from the user agent sheet.
+ if (simpleDefaultStyleSheet)
+ result.isCacheable = false;
+ RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
+ ? defaultPrintStyle : defaultStyle;
+ matchRules(userAgentStyleSheet, result.firstUARule, result.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);
+
+ // 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);
+ }
+}
+
+PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document, CSSFontSelector* fontSelector)
+{
+ Frame* frame = document->frame();
+
+ RefPtr<RenderStyle> documentStyle = RenderStyle::create();
+ documentStyle->setDisplay(BLOCK);
+ documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
+ documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
+ documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
+ documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
+
+ Element* docElement = document->documentElement();
+ RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
+ if (docElementRenderer) {
+ // Use the direction and writing-mode of the body to set the
+ // viewport's direction and writing-mode unless the property is set on the document element.
+ // If there is no body, then use the document element.
+ RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
+ if (bodyRenderer && !document->writingModeSetOnDocumentElement())
+ documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
+ else
+ documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
+ if (bodyRenderer && !document->directionSetOnDocumentElement())
+ documentStyle->setDirection(bodyRenderer->style()->direction());
+ else
+ documentStyle->setDirection(docElementRenderer->style()->direction());
+ }
+
+ if (frame) {
+ if (Page* page = frame->page()) {
+ const Page::Pagination& pagination = page->pagination();
+ if (pagination.mode != Page::Pagination::Unpaginated) {
+ documentStyle->setColumnAxis(pagination.mode == Page::Pagination::HorizontallyPaginated ? HorizontalColumnAxis : VerticalColumnAxis);
+ documentStyle->setColumnGap(pagination.gap);
+ }
+ }
+ }
+
+ FontDescription fontDescription;
+ fontDescription.setUsePrinterFont(document->printing());
+ if (Settings* settings = document->settings()) {
+ fontDescription.setRenderingMode(settings->fontRenderingMode());
+ const AtomicString& stdfont = settings->standardFontFamily();
+ if (!stdfont.isEmpty()) {
+ fontDescription.setGenericFamily(FontDescription::StandardFamily);
+ fontDescription.firstFamily().setFamily(stdfont);
+ fontDescription.firstFamily().appendFamily(0);
+ }
+ fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
+ int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
+ fontDescription.setSpecifiedSize(size);
+ bool useSVGZoomRules = document->isSVGDocument();
+ fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
+ }
+
+ documentStyle->setFontDescription(fontDescription);
+ documentStyle->font().update(fontSelector);
+
+ return documentStyle.release();
+}
+
+static inline bool isAtShadowBoundary(Element* element)
+{
+ if (!element)
+ return false;
+ ContainerNode* parentNode = element->parentNode();
+ return parentNode && parentNode->isShadowRoot();
+}
+
+// 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)
+{
+ // 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.
+ if (allowSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
+ if (!s_styleNotYetAvailable) {
+ s_styleNotYetAvailable = RenderStyle::create().leakRef();
+ s_styleNotYetAvailable->setDisplay(NONE);
+ s_styleNotYetAvailable->font().update(m_fontSelector);
+ }
+ element->document()->setHasNodesWithPlaceholderStyle();
+ return s_styleNotYetAvailable;
+ }
+
+ initElement(element);
+ initForStyleResolve(element, defaultParent);
+ if (allowSharing) {
+ RenderStyle* sharedStyle = locateSharedStyle();
+ if (sharedStyle)
+ return sharedStyle;
+ }
+
+ m_style = RenderStyle::create();
+
+ if (m_parentStyle)
+ m_style->inheritFrom(m_parentStyle);
+ else {
+ m_parentStyle = style();
+ // Make sure our fonts are initialized if we don't inherit them from our parent style.
+ m_style->font().update(0);
+ }
+
+ // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
+ if (isAtShadowBoundary(element))
+ m_style->setUserModify(RenderStyle::initialUserModify());
+
+ if (element->isLink()) {
+ m_style->setIsLink(true);
+ m_style->setInsideLink(m_elementLinkState);
+ }
+
+ ensureDefaultStyleSheetsForElement(element);
+
+ MatchResult matchResult;
+ if (resolveForRootDefault)
+ matchUARules(matchResult);
+ else
+ matchAllRules(matchResult);
+
+ applyMatchedDeclarations(matchResult);
+
+ // Clean up our style object's display and text decorations (among other fixups).
+ adjustRenderStyle(style(), m_parentStyle, element);
+
+ initElement(0); // Clear out for the next resolve.
+
+ // Now return the style.
+ return m_style.release();
+}
+
+PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
+{
+ if (keyframeRule->style())
+ addMatchedDeclaration(keyframeRule->style());
+
+ ASSERT(!m_style);
+
+ // Create the style
+ m_style = RenderStyle::clone(elementStyle);
+
+ m_lineHeightValue = 0;
+
+ // We don't need to bother with !important. Since there is only ever one
+ // decl, there's nothing to override. So just add the first properties.
+ bool inheritedOnly = false;
+ if (keyframeRule->style())
+ applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
+
+ // If our font got dirtied, go ahead and update it now.
+ updateFont();
+
+ // Line-height is set when we are sure we decided on the font-size
+ if (m_lineHeightValue)
+ applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
+
+ // Now do rest of the properties.
+ if (keyframeRule->style())
+ applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
+
+ // If our font got dirtied by one of the non-essential font props,
+ // go ahead and update it a second time.
+ updateFont();
+
+ // Start loading images referenced by this style.
+ loadPendingImages();
+
+#if ENABLE(CSS_SHADERS)
+ // Start loading the shaders referenced by this style.
+ loadPendingShaders();
+#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();
+ // 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)
+ keyframe.addProperty(property);
+ }
+ }
+
+ return m_style.release();
+}
+
+void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
+{
+ list.clear();
+
+ // Get the keyframesRule for this name
+ if (!e || list.animationName().isEmpty())
+ return;
+
+ m_keyframesRuleMap.checkConsistency();
+
+ KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
+ if (it == m_keyframesRuleMap.end())
+ return;
+
+ const WebKitCSSKeyframesRule* rule = it->second.get();
+
+ // Construct and populate the style for each keyframe
+ for (unsigned i = 0; i < rule->length(); ++i) {
+ // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
+ initElement(e);
+ initForStyleResolve(e);
+
+ const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
+
+ KeyframeValue keyframe(0, 0);
+ keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
+
+ // Add this keyframe style to all the indicated key times
+ Vector<float> keys;
+ keyframeRule->getKeys(keys);
+ for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
+ keyframe.setKey(keys[keyIndex]);
+ list.insert(keyframe);
+ }
+ }
+
+ // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
+ int initialListSize = list.size();
+ if (initialListSize > 0 && list[0].key() != 0) {
+ RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
+ keyframeRule->setKeyText("0%");
+ KeyframeValue keyframe(0, 0);
+ keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
+ list.insert(keyframe);
+ }
+
+ // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
+ if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
+ RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
+ keyframeRule->setKeyText("100%");
+ KeyframeValue keyframe(1, 0);
+ keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
+ list.insert(keyframe);
+ }
+}
+
+PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
+{
+ if (!e)
+ return 0;
+
+ initElement(e);
+
+ initForStyleResolve(e, parentStyle, pseudo);
+ m_style = RenderStyle::create();
+
+ if (m_parentStyle)
+ m_style->inheritFrom(m_parentStyle);
+
+ // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
+ // those rules.
+
+ // Check UA, user and author rules.
+ MatchResult matchResult;
+ matchUARules(matchResult);
+
+ if (m_matchAuthorAndUserStyles) {
+ matchRules(m_userStyle.get(), matchResult.firstUserRule, matchResult.lastUserRule, false);
+ matchRules(m_authorStyle.get(), matchResult.firstAuthorRule, matchResult.lastAuthorRule, false);
+ }
+
+ if (m_matchedDecls.isEmpty())
+ return 0;
+
+ m_style->setStyleType(pseudo);
+
+ applyMatchedDeclarations(matchResult);
+
+ // Clean up our style object's display and text decorations (among other fixups).
+ adjustRenderStyle(style(), parentStyle, 0);
+
+ // Start loading images referenced by this style.
+ loadPendingImages();
+
+#if ENABLE(CSS_SHADERS)
+ // Start loading the shaders referenced by this style.
+ loadPendingShaders();
+#endif
+
+ // Now return the style.
+ return m_style.release();
+}
+
+PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
+{
+ initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
+
+ m_style = RenderStyle::create();
+ m_style->inheritFrom(m_rootElementStyle);
+
+ const bool isLeft = isLeftPage(pageIndex);
+ const bool isFirst = isFirstPage(pageIndex);
+ const String page = pageName(pageIndex);
+ matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
+ matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
+ matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
+ m_lineHeightValue = 0;
+ bool inheritedOnly = false;
+ applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
+
+ // If our font got dirtied, go ahead and update it now.
+ updateFont();
+
+ // Line-height is set when we are sure we decided on the font-size.
+ if (m_lineHeightValue)
+ applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
+
+ applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
+
+ // Start loading images referenced by this style.
+ loadPendingImages();
+
+#if ENABLE(CSS_SHADERS)
+ // Start loading the shaders referenced by this style.
+ loadPendingShaders();
+#endif
+
+ // Now return the style.
+ return m_style.release();
+}
+
+static void addIntrinsicMargins(RenderStyle* style)
+{
+ // Intrinsic margin value.
+ const int intrinsicMargin = 2 * style->effectiveZoom();
+
+ // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
+ // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
+ if (style->width().isIntrinsicOrAuto()) {
+ if (style->marginLeft().quirk())
+ style->setMarginLeft(Length(intrinsicMargin, Fixed));
+ if (style->marginRight().quirk())
+ style->setMarginRight(Length(intrinsicMargin, Fixed));
+ }
+
+ if (style->height().isAuto()) {
+ if (style->marginTop().quirk())
+ style->setMarginTop(Length(intrinsicMargin, Fixed));
+ if (style->marginBottom().quirk())
+ style->setMarginBottom(Length(intrinsicMargin, Fixed));
+ }
+}
+
+void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
+{
+ // Cache our original display.
+ style->setOriginalDisplay(style->display());
+
+ if (style->display() != NONE) {
+ // If we have a <td> that specifies a float property, in quirks mode we just drop the float
+ // property.
+ // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
+ // these tags to retain their display types.
+ if (!m_checker.strictParsing() && e) {
+ if (e->hasTagName(tdTag)) {
+ style->setDisplay(TABLE_CELL);
+ style->setFloating(NoFloat);
+ }
+ else if (e->hasTagName(tableTag))
+ style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
+ }
+
+ if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
+ if (style->whiteSpace() == KHTML_NOWRAP) {
+ // Figure out if we are really nowrapping or if we should just
+ // use normal instead. If the width of the cell is fixed, then
+ // we don't actually use NOWRAP.
+ if (style->width().isFixed())
+ style->setWhiteSpace(NORMAL);
+ else
+ style->setWhiteSpace(NOWRAP);
+ }
+ }
+
+ // Tables never support the -webkit-* values for text-align and will reset back to the default.
+ if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
+ style->setTextAlign(TAAUTO);
+
+ // Frames and framesets never honor position:relative or position:absolute. This is necessary to
+ // fix a crash where a site tries to position these objects. They also never honor display.
+ if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
+ style->setPosition(StaticPosition);
+ style->setDisplay(BLOCK);
+ }
+
+ // Table headers with a text-align of auto will change the text-align to center.
+ if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
+ style->setTextAlign(CENTER);
+
+ if (e && e->hasTagName(legendTag))
+ style->setDisplay(BLOCK);
+
+ // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
+ // position or float an inline, compact, or run-in. Cache the original display, since it
+ // may be needed for positioned elements that have to compute their static normal flow
+ // positions. We also force inline-level roots to be block-level.
+ if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
+ (style->position() == AbsolutePosition || style->position() == FixedPosition || style->isFloating() ||
+ (e && e->document()->documentElement() == e))) {
+ if (style->display() == INLINE_TABLE)
+ style->setDisplay(TABLE);
+ else if (style->display() == INLINE_BOX)
+ style->setDisplay(BOX);
+ else if (style->display() == LIST_ITEM) {
+ // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
+ // but only in quirks mode.
+ if (!m_checker.strictParsing() && style->isFloating())
+ style->setDisplay(BLOCK);
+ }
+ else
+ style->setDisplay(BLOCK);
+ }
+
+ // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
+ // clear how that should work.
+ if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
+ style->setDisplay(INLINE_BLOCK);
+
+ // After performing the display mutation, check table rows. We do not honor position:relative on
+ // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
+ // on some sites).
+ if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
+ || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
+ style->position() == RelativePosition)
+ style->setPosition(StaticPosition);
+
+ // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
+ // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
+ if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
+ || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
+ || style->display() == TABLE_CELL)
+ style->setWritingMode(parentStyle->writingMode());
+
+ // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
+ // of block-flow to anything other than TopToBottomWritingMode.
+ // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
+ if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
+ style->setWritingMode(TopToBottomWritingMode);
+ }
+
+ // Make sure our z-index value is only applied if the object is positioned.
+ if (style->position() == StaticPosition)
+ style->setHasAutoZIndex();
+
+ // Auto z-index becomes 0 for the root element and transparent objects. This prevents
+ // cases where objects that should be blended as a single unit end up with a non-transparent
+ // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
+ if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f
+ || style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect() || style->hasFilter()))
+ style->setZIndex(0);
+
+ // Textarea considers overflow visible as auto.
+ if (e && e->hasTagName(textareaTag)) {
+ style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
+ style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
+ }
+
+ // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
+ // tables, inline blocks, inline tables, run-ins, or shadow DOM.
+ if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
+ || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
+ style->setTextDecorationsInEffect(style->textDecoration());
+ else
+ style->addToTextDecorationsInEffect(style->textDecoration());
+
+ // If either overflow value is not visible, change to auto.
+ if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
+ style->setOverflowY(OMARQUEE);
+ else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
+ style->setOverflowX(OMARQUEE);
+ else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
+ style->setOverflowX(OAUTO);
+ else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
+ style->setOverflowY(OAUTO);
+
+ // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
+ // FIXME: Eventually table sections will support auto and scroll.
+ if (style->display() == TABLE || style->display() == INLINE_TABLE ||
+ style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
+ if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
+ style->setOverflowX(OVISIBLE);
+ if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
+ style->setOverflowY(OVISIBLE);
+ }
+
+ // Menulists should have visible overflow
+ if (style->appearance() == MenulistPart) {
+ style->setOverflowX(OVISIBLE);
+ style->setOverflowY(OVISIBLE);
+ }
+
+ // Cull out any useless layers and also repeat patterns into additional layers.
+ style->adjustBackgroundLayers();
+ style->adjustMaskLayers();
+
+ // Do the same for animations and transitions.
+ style->adjustAnimations();
+ style->adjustTransitions();
+
+ // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
+ // alter fonts and heights/widths.
+ if (e && e->isFormControlElement() && style->fontSize() >= 11) {
+ // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
+ // so we have to treat all image buttons as though they were explicitly sized.
+ if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
+ addIntrinsicMargins(style);
+ }
+
+ // Let the theme also have a crack at adjusting the style.
+ if (style->hasAppearance())
+ RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
+
+ // If we have first-letter pseudo style, do not share this style.
+ if (style->hasPseudoStyle(FIRST_LETTER))
+ style->setUnique();
+
+#if ENABLE(SVG)
+ if (e && e->isSVGElement()) {
+ // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
+ if (style->overflowY() == OSCROLL)
+ style->setOverflowY(OHIDDEN);
+ else if (style->overflowY() == OAUTO)
+ style->setOverflowY(OVISIBLE);
+
+ if (style->overflowX() == OSCROLL)
+ style->setOverflowX(OHIDDEN);
+ else if (style->overflowX() == OAUTO)
+ style->setOverflowX(OVISIBLE);
+
+ // Only the root <svg> element in an SVG document fragment tree honors css position
+ if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
+ style->setPosition(RenderStyle::initialPosition());
+ }
+#endif
+}
+
+bool CSSStyleSelector::checkRegionStyle(Element* e)
+{
+ m_checker.clearHasUnknownPseudoElements();
+ m_checker.setPseudoStyle(NOPSEUDO);
+
+ 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))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void CSSStyleSelector::updateFont()
+{
+ if (!m_fontDirty)
+ return;
+
+ checkForTextSizeAdjust();
+ checkForGenericFamilyChange(style(), m_parentStyle);
+ checkForZoomChange(style(), m_parentStyle);
+ m_style->font().update(m_fontSelector);
+ m_fontDirty = false;
+}
+
+void CSSStyleSelector::cacheBorderAndBackground()
+{
+ m_hasUAAppearance = m_style->hasAppearance();
+ if (m_hasUAAppearance) {
+ m_borderData = m_style->border();
+ m_backgroundData = *m_style->backgroundLayers();
+ m_backgroundColor = m_style->backgroundColor();
+ }
+}
+
+PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
+{
+ return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
+}
+
+PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
+{
+ if (!e || !e->document()->haveStylesheetsLoaded())
+ return 0;
+
+ m_checker.setCollectingRulesOnly(true);
+
+ initElement(e);
+ initForStyleResolve(e, 0, pseudoId);
+
+ MatchResult dummy;
+ if (rulesToInclude & UAAndUserCSSRules) {
+ // First we match rules from the user agent sheet.
+ matchUARules(dummy);
+
+ // Now we check user sheet rules.
+ if (m_matchAuthorAndUserStyles)
+ matchRules(m_userStyle.get(), dummy.firstUserRule, dummy.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);
+
+ m_sameOriginOnly = false;
+ }
+
+ m_checker.setCollectingRulesOnly(false);
+
+ return m_ruleList.release();
+}
+
+inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
+{
+ m_dynamicPseudo = NOPSEUDO;
+ m_checker.clearHasUnknownPseudoElements();
+
+ // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
+ if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
+ // We know this selector does not include any pseudo elements.
+ if (m_checker.pseudoStyle() != NOPSEUDO)
+ return false;
+ // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
+ // This is limited to HTML only so we don't need to check the namespace.
+ if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
+ if (!ruleData.hasMultipartSelector())
+ return true;
+ } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
+ return false;
+ if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
+ return false;
+ return m_checker.fastCheckSelector(ruleData.selector(), m_element);
+ }
+
+ // Slow path.
+ SelectorChecker::SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
+ if (match != SelectorChecker::SelectorMatches)
+ return false;
+ if (m_checker.pseudoStyle() != NOPSEUDO && m_checker.pseudoStyle() != m_dynamicPseudo)
+ return false;
+ return true;
+}
+
+bool CSSStyleSelector::determineStylesheetSelectorScopes(CSSStyleSheet* stylesheet, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes)
+{
+ ASSERT(!stylesheet->isLoading());
+
+ size_t size = stylesheet->length();
+ for (size_t i = 0; i < size; i++) {
+ CSSRule* rule = stylesheet->item(i);
+ if (rule->isStyleRule()) {
+ CSSStyleRule* styleRule = static_cast<CSSStyleRule*>(rule);
+ if (!SelectorChecker::determineSelectorScopes(styleRule->selectorList(), idScopes, classScopes))
+ return false;
+ continue;
+ }
+ if (rule->isImportRule()) {
+ CSSImportRule* importRule = static_cast<CSSImportRule*>(rule);
+ if (importRule->styleSheet()) {
+ if (!determineStylesheetSelectorScopes(importRule->styleSheet(), idScopes, classScopes))
+ return false;
+ }
+ continue;
+ }
+ // FIXME: Media rules and maybe some others could be allowed.
+ return false;
+ }
+ return true;
+}
+
+// -----------------------------------------------------------------
+
+static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
+{
+ const AtomicString& selectorNamespace = selector->tag().namespaceURI();
+ if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
+ return false;
+ if (selector->m_match == CSSSelector::None)
+ return true;
+ if (selector->tag() != starAtom)
+ return false;
+ if (SelectorChecker::isCommonPseudoClassSelector(selector))
+ return true;
+ return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
+}
+
+static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector)
+{
+ CSSSelectorList* selectorList = selector->selectorList();
+ if (!selectorList)
+ return false;
+ for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
+ if (subSelector->isAttributeSelector())
+ return true;
+ }
+ return false;
+}
+
+static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute)
+{
+ // These are explicitly tested for equality in canShareStyleWithElement.
+ return attribute == typeAttr || attribute == readonlyAttr;
+}
+
+static inline bool containsUncommonAttributeSelector(const CSSSelector* selector)
+{
+ while (selector) {
+ // Allow certain common attributes (used in the default style) in the selectors that match the current element.
+ if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute()))
+ return true;
+ if (selectorListContainsUncommonAttributeSelector(selector))
+ return true;
+ if (selector->relation() != CSSSelector::SubSelector)
+ break;
+ selector = selector->tagHistory();
+ };
+
+ for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
+ if (selector->isAttributeSelector())
+ return true;
+ if (selectorListContainsUncommonAttributeSelector(selector))
+ return true;
+ }
+ return false;
+}
+
+RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
+ : m_rule(rule)
+ , m_selector(selector)
+ , m_specificity(selector->specificity())
+ , m_position(position)
+ , m_hasFastCheckableSelector(SelectorChecker::isFastCheckableSelector(selector))
+ , m_hasMultipartSelector(!!selector->tagHistory())
+ , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
+ , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector))
+ , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector))
+{
+ SelectorChecker::collectIdentifierHashes(m_selector, m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
+}
+
+RuleSet::RuleSet()
+ : m_ruleCount(0)
+ , m_autoShrinkToFitEnabled(true)
+{
+}
+
+void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, CSSStyleRule* rule, CSSSelector* selector)
+{
+ 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++));
+}
+
+void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
+{
+ if (sel->m_match == CSSSelector::Id) {
+ addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
+ return;
+ }
+ if (sel->m_match == CSSSelector::Class) {
+ addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
+ return;
+ }
+ if (sel->isUnknownPseudoElement()) {
+ addToRuleSet(sel->value().impl(), m_shadowPseudoElementRules, rule, sel);
+ return;
+ }
+ if (SelectorChecker::isCommonPseudoClassSelector(sel)) {
+ RuleData ruleData(rule, sel, m_ruleCount++);
+ switch (sel->pseudoType()) {
+ case CSSSelector::PseudoLink:
+ case CSSSelector::PseudoVisited:
+ case CSSSelector::PseudoAnyLink:
+ m_linkPseudoClassRules.append(ruleData);
+ return;
+ case CSSSelector::PseudoFocus:
+ m_focusPseudoClassRules.append(ruleData);
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return;
+ }
+ const AtomicString& localName = sel->tag().localName();
+ if (localName != starAtom) {
+ addToRuleSet(localName.impl(), m_tagRules, rule, sel);
+ return;
+ }
+
+ m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
+}
+
+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)
+{
+ ASSERT(sheet);
+
+ // No media implies "all", but if a media list exists it must
+ // contain our current medium
+ if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
+ return; // the style sheet doesn't apply
+
+ int len = sheet->length();
+
+ for (int i = 0; i < len; i++) {
+ CSSRule* rule = sheet->item(i);
+ if (rule->isStyleRule())
+ addStyleRule(static_cast<CSSStyleRule*>(rule));
+ else if (rule->isPageRule())
+ addPageRule(static_cast<CSSPageRule*>(rule));
+ 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);
+ }
+ else if (rule->isMediaRule()) {
+ CSSMediaRule* r = static_cast<CSSMediaRule*>(rule);
+ CSSRuleList* rules = r->cssRules();
+
+ if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
+ // Traverse child elements of the @media rule.
+ for (unsigned j = 0; j < rules->length(); j++) {
+ CSSRule *childItem = rules->item(j);
+ if (childItem->isStyleRule())
+ addStyleRule(static_cast<CSSStyleRule*>(childItem));
+ else if (childItem->isPageRule())
+ addPageRule(static_cast<CSSPageRule*>(childItem));
+ else if (childItem->isFontFaceRule() && styleSelector) {
+ // Add this font face to our set.
+ 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.
+ styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
+ }
+ } // for rules
+ } // if rules
+ } else if (rule->isFontFaceRule() && styleSelector) {
+ // Add this font face to our set.
+ const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule);
+ styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
+ styleSelector->invalidateMatchedDeclarationCache();
+ } else if (rule->isKeyframesRule())
+ styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule));
+ else if (rule->isRegionRule() && styleSelector)
+ styleSelector->addRegionRule(static_cast<WebKitCSSRegionRule*>(rule));
+ }
+ if (m_autoShrinkToFitEnabled)
+ shrinkToFit();
+}
+
+void RuleSet::addStyleRule(CSSStyleRule* rule)
+{
+ for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
+ 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();
+ for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
+ it->second->shrinkToFit();
+}
+
+void RuleSet::shrinkToFit()
+{
+ shrinkMapVectorsToFit(m_idRules);
+ shrinkMapVectorsToFit(m_classRules);
+ shrinkMapVectorsToFit(m_tagRules);
+ shrinkMapVectorsToFit(m_shadowPseudoElementRules);
+ m_linkPseudoClassRules.shrinkToFit();
+ m_focusPseudoClassRules.shrinkToFit();
+ m_universalRules.shrinkToFit();
+ m_pageRules.shrinkToFit();
+}
+
+// -------------------------------------------------------------------------------------
+// this is mostly boring stuff on how to apply a certain rule to the renderstyle...
+
+static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0)
+{
+ // This function is tolerant of a null style value. The only place style is used is in
+ // length measurements, like 'ems' and 'px'. And in those cases style is only used
+ // when the units are EMS or EXS. So we will just fail in those cases.
+ Length l;
+ if (!primitiveValue) {
+ if (ok)
+ *ok = false;
+ } else {
+ int type = primitiveValue->primitiveType();
+
+ if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
+ if (ok)
+ *ok = false;
+ } else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+ 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)
+ l = Length(primitiveValue->getDoubleValue(), Percent);
+ else if (type == CSSPrimitiveValue::CSS_NUMBER)
+ l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
+ else if (ok)
+ *ok = false;
+ }
+ return l;
+}
+
+static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
+{
+ return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok);
+}
+
+static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
+{
+ return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok);
+}
+
+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;
+ if (isImportant != current.isImportant())
+ continue;
+ if (inheritedOnly && !current.isInherited()) {
+ // If the property value is explicitly inherited, we need to apply further non-inherited properties
+ // as they might override the value inherited here. For this reason we don't allow declarations with
+ // explicitly inherited properties to be cached.
+ ASSERT(!current.value()->isInheritedValue());
+ continue;
+ }
+ int property = current.id();
+ if (applyFirst) {
+ COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
+ COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 16, 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)
+ continue;
+ // we apply line-height later
+ if (property == CSSPropertyLineHeight) {
+ m_lineHeightValue = current.value();
+ continue;
+ }
+ applyProperty(current.id(), current.value());
+ continue;
+ }
+ if (property > CSSPropertyLineHeight)
+ applyProperty(current.id(), current.value());
+ }
+ InspectorInstrumentation::didProcessRule(cookie);
+}
+
+template <bool applyFirst>
+void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
+{
+ if (startIndex == -1)
+ return;
+
+ if (m_style->insideLink() != NotInsideLink) {
+ for (int i = startIndex; i <= endIndex; ++i) {
+ CSSMutableStyleDeclaration* styleDeclaration = m_matchedDecls[i].styleDeclaration;
+ unsigned linkMatchType = m_matchedDecls[i].linkMatchType;
+ // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
+ m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
+ m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
+
+ applyDeclaration<applyFirst>(styleDeclaration, isImportant, inheritedOnly);
+ }
+ m_applyPropertyToRegularStyle = true;
+ m_applyPropertyToVisitedLinkStyle = false;
+ return;
+ }
+ for (int i = startIndex; i <= endIndex; ++i)
+ applyDeclaration<applyFirst>(m_matchedDecls[i].styleDeclaration, isImportant, inheritedOnly);
+}
+
+unsigned CSSStyleSelector::computeDeclarationHash(MatchedStyleDeclaration* declarations, unsigned size)
+{
+ return StringHasher::hashMemory(declarations, sizeof(MatchedStyleDeclaration) * size);
+}
+
+bool operator==(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& 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;
+}
+
+bool operator!=(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
+{
+ return !(a == b);
+}
+
+bool operator==(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
+{
+ return a.styleDeclaration == b.styleDeclaration && a.linkMatchType == b.linkMatchType;
+}
+
+bool operator!=(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
+{
+ return !(a == b);
+}
+
+const CSSStyleSelector::MatchedStyleDeclarationCacheItem* CSSStyleSelector::findFromMatchedDeclarationCache(unsigned hash, const MatchResult& matchResult)
+{
+ ASSERT(hash);
+
+ MatchedStyleDeclarationCache::iterator it = m_matchedStyleDeclarationCache.find(hash);
+ 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;
+ for (size_t i = 0; i < size; ++i) {
+ if (m_matchedDecls[i] != cacheItem.matchedStyleDeclarations[i])
+ return 0;
+ }
+ if (cacheItem.matchResult != matchResult)
+ return 0;
+ return &cacheItem;
+}
+
+void CSSStyleSelector::addToMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
+{
+ ASSERT(hash);
+ MatchedStyleDeclarationCacheItem cacheItem;
+ cacheItem.matchedStyleDeclarations.append(m_matchedDecls);
+ cacheItem.matchResult = matchResult;
+ // 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);
+ cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
+ m_matchedStyleDeclarationCache.add(hash, cacheItem);
+}
+
+void CSSStyleSelector::invalidateMatchedDeclarationCache()
+{
+ m_matchedStyleDeclarationCache.clear();
+}
+
+static bool isCacheableInMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle)
+{
+ if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
+ return false;
+ if (style->hasAppearance())
+ return false;
+ if (style->zoom() != RenderStyle::initialZoom())
+ return false;
+ // The cache assumes static knowledge about which properties are inherited.
+ if (parentStyle->hasExplicitlyInheritedProperties())
+ return false;
+ return true;
+}
+
+void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult)
+{
+ unsigned cacheHash = matchResult.isCacheable ? computeDeclarationHash(m_matchedDecls.data(), m_matchedDecls.size()) : 0;
+ bool applyInheritedOnly = false;
+ const MatchedStyleDeclarationCacheItem* cacheItem = 0;
+ if (cacheHash && (cacheItem = findFromMatchedDeclarationCache(cacheHash, matchResult))) {
+ // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
+ // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
+ // element context. This is fast and saves memory by reusing the style data structures.
+ m_style->copyNonInheritedFrom(cacheItem->renderStyle.get());
+ if (m_parentStyle->inheritedDataShared(cacheItem->parentRenderStyle.get())) {
+ EInsideLink linkStatus = m_style->insideLink();
+ // If the cache item parent style has identical inherited properties to the current parent style then the
+ // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
+ m_style->inheritFrom(cacheItem->renderStyle.get());
+ // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
+ m_style->setInsideLink(linkStatus);
+ return;
+ }
+ applyInheritedOnly = true;
+ }
+ // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
+ // high-priority properties first, i.e., those properties that other properties depend on.
+ // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
+ // 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);
+
+ if (cacheItem && cacheItem->renderStyle->effectiveZoom() != m_style->effectiveZoom()) {
+ m_fontDirty = true;
+ applyInheritedOnly = false;
+ }
+
+ // If our font got dirtied, go ahead and update it now.
+ updateFont();
+
+ // Line-height is set when we are sure we decided on the font-size.
+ if (m_lineHeightValue)
+ applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
+
+ // Many properties depend on the font. If it changes we just apply all properties.
+ if (cacheItem && cacheItem->renderStyle->fontDescription() != m_style->fontDescription())
+ applyInheritedOnly = false;
+
+ // Now do the normal priority UA properties.
+ applyDeclarations<false>(false, matchResult.firstUARule, matchResult.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);
+
+ loadPendingImages();
+
+#if ENABLE(CSS_SHADERS)
+ loadPendingShaders();
+#endif
+
+ ASSERT(!m_fontDirty);
+
+ if (cacheItem || !cacheHash)
+ return;
+ if (!isCacheableInMatchedDeclarationCache(m_style.get(), m_parentStyle))
+ return;
+ addToMatchedDeclarationCache(m_style.get(), m_parentStyle, cacheHash, matchResult);
+}
+
+void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+ m_matchedRules.clear();
+
+ if (!rules)
+ return;
+
+ matchPageRulesForList(rules->pageRules(), isLeftPage, isFirstPage, pageName);
+
+ // If we didn't match any rules, we're done.
+ if (m_matchedRules.isEmpty())
+ return;
+
+ // Sort the set of matched rules.
+ sortMatchedRules();
+
+ // Now transfer the set of matched rules over to our list of decls.
+ for (unsigned i = 0; i < m_matchedRules.size(); i++)
+ addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
+}
+
+void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+{
+ if (!rules)
+ return;
+
+ unsigned size = rules->size();
+ for (unsigned i = 0; i < size; ++i) {
+ const RuleData& ruleData = rules->at(i);
+ CSSStyleRule* rule = ruleData.rule();
+ const AtomicString& selectorLocalName = ruleData.selector()->tag().localName();
+ if (selectorLocalName != starAtom && selectorLocalName != pageName)
+ continue;
+ CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
+ if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
+ || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
+ || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
+ continue;
+
+ // If the rule has no properties to apply, then ignore it.
+ CSSMutableStyleDeclaration* decl = rule->declaration();
+ if (!decl || !decl->length())
+ continue;
+
+ // Add this rule to our list of matched rules.
+ addMatchedRule(&ruleData);
+ }
+}
+
+bool CSSStyleSelector::isLeftPage(int pageIndex) const
+{
+ bool isFirstPageLeft = false;
+ if (!m_rootElementStyle->isLeftToRightDirection())
+ isFirstPageLeft = true;
+
+ return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
+}
+
+bool CSSStyleSelector::isFirstPage(int pageIndex) const
+{
+ // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
+ return (!pageIndex);
+}
+
+String CSSStyleSelector::pageName(int /* pageIndex */) const
+{
+ // FIXME: Implement page index to page name mapping.
+ return "";
+}
+
+void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue* value, RenderStyle* style)
+{
+ initElement(0);
+ initForStyleResolve(0, style);
+ m_style = style;
+ applyPropertyToCurrentStyle(id, value);
+}
+
+void CSSStyleSelector::applyPropertyToCurrentStyle(int id, CSSValue* value)
+{
+ if (value)
+ applyProperty(id, value);
+}
+
+inline bool isValidVisitedLinkProperty(int id)
+{
+ switch(static_cast<CSSPropertyID>(id)) {
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyColor:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextStrokeColor:
+ // Also allow shorthands so that inherit/initial still work.
+ case CSSPropertyBackground:
+ case CSSPropertyBorderLeft:
+ case CSSPropertyBorderRight:
+ case CSSPropertyBorderTop:
+ case CSSPropertyBorderBottom:
+ case CSSPropertyOutline:
+ case CSSPropertyWebkitColumnRule:
+#if ENABLE(SVG)
+ case CSSPropertyFill:
+ case CSSPropertyStroke:
+#endif
+ 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.
+// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
+// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
+// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
+// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
+// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
+bool CSSStyleSelector::useSVGZoomRules()
+{
+ return m_element && m_element->isSVGElement();
+}
+
+#if ENABLE(CSS_GRID_LAYOUT)
+
+static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, CSSStyleSelector* selector, Length& length)
+{
+ if (primitiveValue->getIdent() == CSSValueAuto) {
+ length = Length();
+ return true;
+ }
+
+ int type = primitiveValue->primitiveType();
+ if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+ length = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom());
+ length.setQuirk(primitiveValue->isQuirkValue());
+ return true;
+ }
+
+ if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
+ length = Length(primitiveValue->getDoubleValue(), Percent);
+ return true;
+ }
+
+ return false;
+}
+
+static bool createGridTrackList(CSSValue* value, Vector<Length>& lengths, CSSStyleSelector* selector)
+{
+ // Handle 'none'.
+ if (value->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == CSSValueNone) {
+ lengths.append(Length(Undefined));
+ return true;
+ }
+ return false;
+ }
+
+ if (value->isValueList()) {
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (!currValue->isPrimitiveValue())
+ return false;
+
+ Length length;
+ if (!createGridTrackBreadth(static_cast<CSSPrimitiveValue*>(currValue), selector, length))
+ return false;
+
+ lengths.append(length);
+ }
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+void CSSStyleSelector::applyProperty(int id, CSSValue *value)
+{
+ bool isInherit = m_parentNode && value->isInheritedValue();
+ bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
+
+ ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
+
+ if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
+ // Limit the properties that can be applied to only the ones honored by :visited.
+ return;
+ }
+
+ CSSPropertyID property = static_cast<CSSPropertyID>(id);
+
+ if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(property))
+ m_parentStyle->setHasExplicitlyInheritedProperties();
+
+ // check lookup table for implementations and use when available
+ const PropertyHandler& handler = m_applyProperty.propertyHandler(property);
+ if (handler.isValid()) {
+ if (isInherit)
+ handler.applyInheritValue(this);
+ else if (isInitial)
+ handler.applyInitialValue(this);
+ else
+ handler.applyValue(this, value);
+ return;
+ }
+
+ CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
+
+ float zoomFactor = m_style->effectiveZoom();
+
+ // What follows is a list that maps the CSS properties into their corresponding front-end
+ // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
+ // are only hit when mapping "inherit" or "initial" into front-end values.
+ switch (property) {
+// ident only properties
+ case CSSPropertyBorderCollapse:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderCollapse, BorderCollapse)
+ return;
+ case CSSPropertyCaptionSide:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
+ return;
+ case CSSPropertyClear:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
+ return;
+ case CSSPropertyEmptyCells:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
+ return;
+ case CSSPropertyFloat:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
+ return;
+ case CSSPropertyPageBreakBefore:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
+ return;
+ case CSSPropertyPageBreakAfter:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
+ return;
+ case CSSPropertyPageBreakInside:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
+ return;
+ case CSSPropertyPosition:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
+ return;
+ case CSSPropertyTableLayout:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(tableLayout, TableLayout)
+ return;
+ case CSSPropertyUnicodeBidi:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
+ return;
+ case CSSPropertyTextTransform:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
+ return;
+ case CSSPropertyVisibility:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
+ return;
+ case CSSPropertyWhiteSpace:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
+ return;
+// uri || inherit
+ case CSSPropertyWordBreak:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
+ return;
+ case CSSPropertyWordWrap:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
+ return;
+ case CSSPropertyWebkitNbspMode:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
+ return;
+ case CSSPropertyWebkitLineBreak:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
+ return;
+ case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
+ return;
+ case CSSPropertyWidows:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(widows, Widows)
+ return;
+ 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:
+ // list of string, uri, counter, attr, i
+ {
+ // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
+ // note is a reminder that eventually "inherit" needs to be supported.
+
+ if (isInitial) {
+ m_style->clearContent();
+ return;
+ }
+
+ if (!value->isValueList())
+ return;
+
+ bool didSet = false;
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* item = i.value();
+ if (item->isImageGeneratorValue()) {
+ m_style->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
+ didSet = true;
+ }
+
+ if (!item->isPrimitiveValue())
+ continue;
+
+ CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
+ switch (contentValue->primitiveType()) {
+ case CSSPrimitiveValue::CSS_STRING:
+ m_style->setContent(contentValue->getStringValue().impl(), didSet);
+ didSet = true;
+ break;
+ case CSSPrimitiveValue::CSS_ATTR: {
+ // FIXME: Can a namespace be specified for an attr(foo)?
+ if (m_style->styleType() == NOPSEUDO)
+ m_style->setUnique();
+ else
+ m_parentStyle->setUnique();
+ QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
+ const AtomicString& value = m_element->getAttribute(attr);
+ m_style->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
+ didSet = true;
+ // register the fact that the attribute value affects the style
+ m_features.attrsInRules.add(attr.localName().impl());
+ break;
+ }
+ case CSSPrimitiveValue::CSS_URI: {
+ if (!contentValue->isImageValue())
+ break;
+ m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet);
+ didSet = true;
+ break;
+ }
+ case CSSPrimitiveValue::CSS_COUNTER: {
+ Counter* counterValue = contentValue->getCounterValue();
+ EListStyleType listStyleType = NoneListStyle;
+ int listStyleIdent = counterValue->listStyleIdent();
+ if (listStyleIdent != CSSValueNone)
+ listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
+ OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
+ m_style->setContent(counter.release(), didSet);
+ didSet = true;
+ break;
+ }
+ case CSSPrimitiveValue::CSS_IDENT:
+ switch (contentValue->getIdent()) {
+ case CSSValueOpenQuote:
+ m_style->setContent(OPEN_QUOTE, didSet);
+ didSet = true;
+ break;
+ case CSSValueCloseQuote:
+ m_style->setContent(CLOSE_QUOTE, didSet);
+ didSet = true;
+ break;
+ case CSSValueNoOpenQuote:
+ m_style->setContent(NO_OPEN_QUOTE, didSet);
+ didSet = true;
+ break;
+ case CSSValueNoCloseQuote:
+ m_style->setContent(NO_CLOSE_QUOTE, didSet);
+ didSet = true;
+ break;
+ default:
+ // normal and none do not have any effect.
+ {}
+ }
+ }
+ }
+ if (!didSet)
+ m_style->clearContent();
+ return;
+ }
+ case CSSPropertyQuotes:
+ if (isInherit) {
+ if (m_parentStyle)
+ m_style->setQuotes(m_parentStyle->quotes());
+ return;
+ }
+ if (isInitial) {
+ m_style->setQuotes(0);
+ return;
+ }
+ if (value->isValueList()) {
+ CSSValueList* list = static_cast<CSSValueList*>(value);
+ QuotesData* data = QuotesData::create(list->length());
+ if (!data)
+ return; // Out of memory
+ String* quotes = data->data();
+ for (CSSValueListIterator i = list; i.hasMore(); i.advance()) {
+ CSSValue* item = i.value();
+ ASSERT(item->isPrimitiveValue());
+ primitiveValue = static_cast<CSSPrimitiveValue*>(item);
+ ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING);
+ quotes[i.index()] = primitiveValue->getStringValue();
+ }
+ m_style->setQuotes(adoptRef(data));
+ } else if (primitiveValue) {
+ ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT);
+ if (primitiveValue->getIdent() == CSSValueNone)
+ m_style->setQuotes(adoptRef(QuotesData::create(0)));
+ }
+ return;
+ case CSSPropertyFontFamily: {
+ // list of strings and ids
+ if (isInherit) {
+ FontDescription parentFontDescription = m_parentStyle->fontDescription();
+ FontDescription fontDescription = m_style->fontDescription();
+ fontDescription.setGenericFamily(parentFontDescription.genericFamily());
+ fontDescription.setFamily(parentFontDescription.firstFamily());
+ fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
+ setFontDescription(fontDescription);
+ return;
+ } else if (isInitial) {
+ FontDescription initialDesc = FontDescription();
+ FontDescription fontDescription = m_style->fontDescription();
+ // We need to adjust the size to account for the generic family change from monospace
+ // to non-monospace.
+ if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
+ setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
+ fontDescription.setGenericFamily(initialDesc.genericFamily());
+ if (!initialDesc.firstFamily().familyIsEmpty())
+ fontDescription.setFamily(initialDesc.firstFamily());
+ setFontDescription(fontDescription);
+ return;
+ }
+
+ if (!value->isValueList())
+ return;
+ FontDescription fontDescription = m_style->fontDescription();
+ FontFamily& firstFamily = fontDescription.firstFamily();
+ FontFamily* currFamily = 0;
+
+ // Before mapping in a new font-family property, we should reset the generic family.
+ bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* item = i.value();
+ if (!item->isPrimitiveValue())
+ continue;
+ CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
+ AtomicString face;
+ Settings* settings = m_checker.document()->settings();
+ if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
+ if (contentValue->isFontFamilyValue())
+ face = static_cast<FontFamilyValue*>(contentValue)->familyName();
+ } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
+ switch (contentValue->getIdent()) {
+ case CSSValueWebkitBody:
+ face = settings->standardFontFamily();
+ break;
+ case CSSValueSerif:
+ face = serifFamily;
+ fontDescription.setGenericFamily(FontDescription::SerifFamily);
+ break;
+ case CSSValueSansSerif:
+ face = sansSerifFamily;
+ fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
+ break;
+ case CSSValueCursive:
+ face = cursiveFamily;
+ fontDescription.setGenericFamily(FontDescription::CursiveFamily);
+ break;
+ case CSSValueFantasy:
+ face = fantasyFamily;
+ fontDescription.setGenericFamily(FontDescription::FantasyFamily);
+ break;
+ case CSSValueMonospace:
+ face = monospaceFamily;
+ fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
+ break;
+ case CSSValueWebkitPictograph:
+ face = pictographFamily;
+ fontDescription.setGenericFamily(FontDescription::PictographFamily);
+ break;
+ }
+ }
+
+ if (!face.isEmpty()) {
+ if (!currFamily) {
+ // Filling in the first family.
+ firstFamily.setFamily(face);
+ firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
+ currFamily = &firstFamily;
+ fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
+ } else {
+ RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
+ newFamily->setFamily(face);
+ currFamily->appendFamily(newFamily);
+ currFamily = newFamily.get();
+ }
+ }
+ }
+
+ // We can't call useFixedDefaultSize() until all new font families have been added
+ // If currFamily is non-zero then we set at least one family on this description.
+ if (currFamily) {
+ if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
+ setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
+
+ setFontDescription(fontDescription);
+ }
+ return;
+ }
+// shorthand properties
+ case CSSPropertyBackground:
+ if (isInitial) {
+ m_style->clearBackgroundLayers();
+ m_style->setBackgroundColor(Color());
+ }
+ else if (isInherit) {
+ m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
+ m_style->setBackgroundColor(m_parentStyle->backgroundColor());
+ }
+ return;
+ case CSSPropertyWebkitMask:
+ if (isInitial)
+ m_style->clearMaskLayers();
+ else if (isInherit)
+ m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
+ return;
+ case CSSPropertyFont:
+ if (isInherit) {
+ FontDescription fontDescription = m_parentStyle->fontDescription();
+ m_style->setLineHeight(m_parentStyle->lineHeight());
+ m_lineHeightValue = 0;
+ setFontDescription(fontDescription);
+ } else if (isInitial) {
+ Settings* settings = m_checker.document()->settings();
+ ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
+ if (!settings)
+ return;
+ FontDescription fontDescription;
+ fontDescription.setGenericFamily(FontDescription::StandardFamily);
+ fontDescription.setRenderingMode(settings->fontRenderingMode());
+ fontDescription.setUsePrinterFont(m_checker.document()->printing());
+ const AtomicString& standardFontFamily = m_checker.document()->settings()->standardFontFamily();
+ if (!standardFontFamily.isEmpty()) {
+ fontDescription.firstFamily().setFamily(standardFontFamily);
+ fontDescription.firstFamily().appendFamily(0);
+ }
+ fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
+ setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueMedium, false));
+ m_style->setLineHeight(RenderStyle::initialLineHeight());
+ m_lineHeightValue = 0;
+ setFontDescription(fontDescription);
+ } else if (primitiveValue) {
+ m_style->setLineHeight(RenderStyle::initialLineHeight());
+ m_lineHeightValue = 0;
+
+ FontDescription fontDescription;
+ RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
+
+ // Double-check and see if the theme did anything. If not, don't bother updating the font.
+ if (fontDescription.isAbsoluteSize()) {
+ // Make sure the rendering mode and printer font settings are updated.
+ Settings* settings = m_checker.document()->settings();
+ ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
+ if (!settings)
+ return;
+ fontDescription.setRenderingMode(settings->fontRenderingMode());
+ fontDescription.setUsePrinterFont(m_checker.document()->printing());
+
+ // Handle the zoom factor.
+ fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
+ setFontDescription(fontDescription);
+ }
+ } else if (value->isFontValue()) {
+ FontValue *font = static_cast<FontValue*>(value);
+ if (!font->style || !font->variant || !font->weight ||
+ !font->size || !font->lineHeight || !font->family)
+ return;
+ applyProperty(CSSPropertyFontStyle, font->style.get());
+ applyProperty(CSSPropertyFontVariant, font->variant.get());
+ applyProperty(CSSPropertyFontWeight, font->weight.get());
+ // The previous properties can dirty our font but they don't try to read the font's
+ // properties back, which is safe. However if font-size is using the 'ex' unit, it will
+ // need query the dirtied font's x-height to get the computed size. To be safe in this
+ // case, let's just update the font now.
+ updateFont();
+ applyProperty(CSSPropertyFontSize, font->size.get());
+
+ m_lineHeightValue = font->lineHeight.get();
+
+ applyProperty(CSSPropertyFontFamily, font->family.get());
+ }
+ return;
+
+ // CSS3 Properties
+ case CSSPropertyWebkitAppearance:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(appearance, Appearance)
+ return;
+ case CSSPropertyImageRendering:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(imageRendering, ImageRendering);
+ return;
+ case CSSPropertyTextShadow:
+ case CSSPropertyBoxShadow:
+ case CSSPropertyWebkitBoxShadow: {
+ if (isInherit) {
+ if (id == CSSPropertyTextShadow)
+ return m_style->setTextShadow(m_parentStyle->textShadow() ? adoptPtr(new ShadowData(*m_parentStyle->textShadow())) : nullptr);
+ return m_style->setBoxShadow(m_parentStyle->boxShadow() ? adoptPtr(new ShadowData(*m_parentStyle->boxShadow())) : nullptr);
+ }
+ if (isInitial || primitiveValue) // initial | none
+ return id == CSSPropertyTextShadow ? m_style->setTextShadow(nullptr) : m_style->setBoxShadow(nullptr);
+
+ if (!value->isValueList())
+ return;
+
+ for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (!currValue->isShadowValue())
+ continue;
+ ShadowValue* item = static_cast<ShadowValue*>(currValue);
+ int x = item->x->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
+ int y = item->y->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
+ int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
+ int spread = item->spread ? item->spread->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
+ ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
+ Color color;
+ if (item->color)
+ color = colorFromPrimitiveValue(item->color.get());
+ OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
+ if (id == CSSPropertyTextShadow)
+ m_style->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
+ else
+ m_style->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
+ }
+ return;
+ }
+ case CSSPropertyWebkitBoxReflect: {
+ HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
+ if (primitiveValue) {
+ m_style->setBoxReflect(RenderStyle::initialBoxReflect());
+ return;
+ }
+
+ if (!value->isReflectValue())
+ return;
+
+ CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
+ RefPtr<StyleReflection> reflection = StyleReflection::create();
+ reflection->setDirection(reflectValue->direction());
+ if (reflectValue->offset()) {
+ int type = reflectValue->offset()->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
+ else
+ reflection->setOffset(reflectValue->offset()->computeLength<Length>(style(), m_rootElementStyle, zoomFactor));
+ }
+ NinePieceImage mask;
+ mask.setMaskDefaults();
+ mapNinePieceImage(property, reflectValue->mask(), mask);
+ reflection->setMask(mask);
+
+ m_style->setBoxReflect(reflection.release());
+ return;
+ }
+ case CSSPropertyOpacity:
+ HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
+ if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
+ return; // Error case.
+ // Clamp opacity to the range 0-1
+ m_style->setOpacity(clampTo<float>(primitiveValue->getDoubleValue(), 0, 1));
+ return;
+ case CSSPropertyWebkitBoxAlign:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxAlign, BoxAlign)
+ return;
+ case CSSPropertySrc: // Only used in @font-face rules.
+ return;
+ case CSSPropertyUnicodeRange: // Only used in @font-face rules.
+ return;
+ case CSSPropertyWebkitBackfaceVisibility:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(backfaceVisibility, BackfaceVisibility)
+ return;
+ case CSSPropertyWebkitBoxDirection:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
+ return;
+ case CSSPropertyWebkitBoxLines:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
+ return;
+ case CSSPropertyWebkitBoxOrient:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
+ return;
+ case CSSPropertyWebkitBoxPack:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxPack, BoxPack)
+ return;
+ case CSSPropertyWebkitBoxFlex:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlex, BoxFlex)
+ return;
+ case CSSPropertyWebkitBoxFlexGroup:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlexGroup, BoxFlexGroup)
+ return;
+ case CSSPropertyWebkitBoxOrdinalGroup:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrdinalGroup, BoxOrdinalGroup)
+ return;
+ case CSSPropertyBoxSizing:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxSizing, BoxSizing);
+ return;
+ case CSSPropertyWebkitColumnSpan:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(columnSpan, ColumnSpan)
+ return;
+ case CSSPropertyWebkitColumnRuleStyle:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
+ return;
+ case CSSPropertyWebkitColumnBreakBefore:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
+ return;
+ case CSSPropertyWebkitColumnBreakAfter:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
+ return;
+ case CSSPropertyWebkitColumnBreakInside:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
+ return;
+ case CSSPropertyWebkitColumnRule:
+ if (isInherit) {
+ m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
+ m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
+ m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
+ }
+ else if (isInitial)
+ m_style->resetColumnRule();
+ return;
+ case CSSPropertyWebkitRegionBreakBefore:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakBefore, RegionBreakBefore, PageBreak)
+ return;
+ case CSSPropertyWebkitRegionBreakAfter:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakAfter, RegionBreakAfter, PageBreak)
+ return;
+ case CSSPropertyWebkitRegionBreakInside:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakInside, RegionBreakInside, PageBreak)
+ return;
+ case CSSPropertyWebkitMarquee:
+ if (!m_parentNode || !value->isInheritedValue())
+ return;
+ m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
+ m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
+ m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
+ m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
+ m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
+ return;
+ case CSSPropertyWebkitMarqueeRepetition: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
+ if (!primitiveValue)
+ return;
+ if (primitiveValue->getIdent() == CSSValueInfinite)
+ m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
+ m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
+ return;
+ }
+ case CSSPropertyWebkitMarqueeSpeed: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
+ if (!primitiveValue)
+ return;
+ if (primitiveValue->getIdent()) {
+ switch (primitiveValue->getIdent()) {
+ case CSSValueSlow:
+ m_style->setMarqueeSpeed(500); // 500 msec.
+ break;
+ case CSSValueNormal:
+ m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
+ break;
+ case CSSValueFast:
+ 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.
+ m_style->setMarqueeSpeed(primitiveValue->getIntValue());
+ return;
+ }
+ case CSSPropertyWebkitMarqueeIncrement: {
+ HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
+ if (!primitiveValue)
+ return;
+ if (primitiveValue->getIdent()) {
+ switch (primitiveValue->getIdent()) {
+ case CSSValueSmall:
+ m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
+ break;
+ case CSSValueNormal:
+ m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
+ break;
+ case CSSValueLarge:
+ m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
+ break;
+ }
+ }
+ else {
+ bool ok = true;
+ Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
+ if (ok)
+ m_style->setMarqueeIncrement(marqueeLength);
+ }
+ return;
+ }
+ case CSSPropertyWebkitMarqueeStyle:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
+ return;
+ case CSSPropertyWebkitRegionOverflow:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(regionOverflow, RegionOverflow);
+ return;
+ case CSSPropertyWebkitMarqueeDirection:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
+ return;
+ case CSSPropertyWebkitUserDrag:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
+ return;
+ case CSSPropertyWebkitUserModify:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
+ return;
+ case CSSPropertyWebkitUserSelect:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
+ return;
+
+ case CSSPropertyTextOverflow: {
+ // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
+ // work with WinIE-specific pages that use the property.
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textOverflow, TextOverflow)
+ return;
+ }
+ case CSSPropertyWebkitLineClamp: {
+ HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
+ if (!primitiveValue)
+ return;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_NUMBER)
+ m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
+ else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
+ return;
+ }
+ case CSSPropertyWebkitHyphens:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(hyphens, Hyphens);
+ return;
+ case CSSPropertyWebkitLocale: {
+ HANDLE_INHERIT_AND_INITIAL(locale, Locale);
+ if (primitiveValue->getIdent() == CSSValueAuto)
+ m_style->setLocale(nullAtom);
+ else
+ m_style->setLocale(primitiveValue->getStringValue());
+ FontDescription fontDescription = m_style->fontDescription();
+ fontDescription.setScript(localeToScriptCodeForFontSelection(m_style->locale()));
+ setFontDescription(fontDescription);
+ return;
+ }
+ case CSSPropertyWebkitBorderFit:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderFit, BorderFit);
+ return;
+ case CSSPropertyWebkitTextSizeAdjust: {
+ HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
+ if (!primitiveValue || !primitiveValue->getIdent())
+ return;
+ setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
+ return;
+ }
+ case CSSPropertyWebkitTextSecurity:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
+ return;
+
+#if ENABLE(DASHBOARD_SUPPORT)
+ case CSSPropertyWebkitDashboardRegion: {
+ HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
+ if (!primitiveValue)
+ return;
+
+ if (primitiveValue->getIdent() == CSSValueNone) {
+ m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
+ return;
+ }
+
+ DashboardRegion *region = primitiveValue->getDashboardRegionValue();
+ if (!region)
+ return;
+
+ DashboardRegion *first = region;
+ while (region) {
+ Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
+ Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
+ Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
+ Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
+ if (region->m_isCircle)
+ m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
+ else if (region->m_isRectangle)
+ m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
+ region = region->m_next.get();
+ }
+
+ m_element->document()->setHasDashboardRegions(true);
+
+ return;
+ }
+#endif
+ case CSSPropertyWebkitRtlOrdering:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(rtlOrdering, RTLOrdering)
+ return;
+ case CSSPropertyWebkitTextStrokeWidth: {
+ HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
+ float width = 0;
+ switch (primitiveValue->getIdent()) {
+ case CSSValueThin:
+ case CSSValueMedium:
+ case CSSValueThick: {
+ double result = 1.0 / 48;
+ if (primitiveValue->getIdent() == CSSValueMedium)
+ result *= 3;
+ else if (primitiveValue->getIdent() == CSSValueThick)
+ result *= 5;
+ width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
+ break;
+ }
+ default:
+ width = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
+ break;
+ }
+ m_style->setTextStrokeWidth(width);
+ return;
+ }
+ case CSSPropertyWebkitTransform: {
+ HANDLE_INHERIT_AND_INITIAL(transform, Transform);
+ TransformOperations operations;
+ createTransformOperations(value, style(), m_rootElementStyle, operations);
+ m_style->setTransform(operations);
+ return;
+ }
+ case CSSPropertyWebkitTransformStyle:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(transformStyle3D, TransformStyle3D)
+ return;
+ case CSSPropertyWebkitPrintColorAdjust:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(printColorAdjust, PrintColorAdjust);
+ return;
+ case CSSPropertyWebkitPerspective: {
+ HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
+ if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
+ m_style->setPerspective(0);
+ return;
+ }
+
+ float perspectiveValue;
+ int type = primitiveValue->primitiveType();
+ if (CSSPrimitiveValue::isUnitTypeLength(type))
+ perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
+ else if (type == CSSPrimitiveValue::CSS_NUMBER) {
+ // For backward compatibility, treat valueless numbers as px.
+ perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
+ } else
+ return;
+
+ if (perspectiveValue >= 0.0f)
+ m_style->setPerspective(perspectiveValue);
+ return;
+ }
+ case CSSPropertyWebkitAnimation:
+ if (isInitial)
+ m_style->clearAnimations();
+ else if (isInherit)
+ m_style->inheritAnimations(m_parentStyle->animations());
+ return;
+ case CSSPropertyWebkitTransition:
+ if (isInitial)
+ m_style->clearTransitions();
+ else if (isInherit)
+ m_style->inheritTransitions(m_parentStyle->transitions());
+ return;
+ case CSSPropertyPointerEvents:
+ {
+#if ENABLE(DASHBOARD_SUPPORT)
+ // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
+ // pointer-events property by not applying it in Dashboard.
+ Settings* settings = m_checker.document()->settings();
+ if (settings && settings->usesDashboardBackwardCompatibilityMode())
+ return;
+#endif
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(pointerEvents, PointerEvents)
+ return;
+ }
+#if ENABLE(TOUCH_EVENTS)
+ case CSSPropertyWebkitTapHighlightColor: {
+ HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
+ if (!primitiveValue)
+ break;
+
+ Color col = colorFromPrimitiveValue(primitiveValue);
+ m_style->setTapHighlightColor(col);
+ return;
+ }
+#endif
+ case CSSPropertyWebkitColorCorrection:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(colorSpace, ColorSpace);
+ return;
+ case CSSPropertySpeak:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(speak, Speak);
+ return;
+ case CSSPropertyInvalid:
+ return;
+ // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
+ case CSSPropertyWebkitBorderEnd:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderEndWidth:
+ case CSSPropertyWebkitBorderStart:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitBorderStartWidth:
+ case CSSPropertyWebkitBorderBefore:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderBeforeWidth:
+ case CSSPropertyWebkitBorderAfter:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitBorderAfterWidth:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginStart:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyWebkitMarginCollapse:
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ case CSSPropertyWebkitMarginTopCollapse:
+ case CSSPropertyWebkitMarginAfterCollapse:
+ case CSSPropertyWebkitMarginBottomCollapse:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyWebkitMaxLogicalWidth:
+ case CSSPropertyWebkitMaxLogicalHeight:
+ {
+ int newId = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
+ ASSERT(newId != id);
+ return applyProperty(newId, value);
+ }
+ case CSSPropertyFontStretch:
+ case CSSPropertyPage:
+ case CSSPropertyTextLineThrough:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextLineThroughWidth:
+ case CSSPropertyTextOverline:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextOverlineWidth:
+ case CSSPropertyTextUnderline:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyTextUnderlineMode:
+ case CSSPropertyTextUnderlineStyle:
+ case CSSPropertyTextUnderlineWidth:
+ case CSSPropertyWebkitFontSizeDelta:
+ case CSSPropertyWebkitTextDecorationsInEffect:
+ case CSSPropertyWebkitTextStroke:
+ case CSSPropertyWebkitTextEmphasis:
+ return;
+
+ // CSS Text Layout Module Level 3: Vertical writing support
+ case CSSPropertyWebkitWritingMode: {
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
+ if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
+ m_element->document()->setWritingModeSetOnDocumentElement(true);
+ FontDescription fontDescription = m_style->fontDescription();
+ fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
+ setFontDescription(fontDescription);
+ return;
+ }
+
+ case CSSPropertyWebkitLineBoxContain: {
+ HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
+ if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
+ m_style->setLineBoxContain(LineBoxContainNone);
+ return;
+ }
+
+ if (!value->isCSSLineBoxContainValue())
+ return;
+
+ CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
+ m_style->setLineBoxContain(lineBoxContainValue->value());
+ return;
+ }
+
+ case CSSPropertyWebkitColumnAxis:
+ HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(columnAxis, ColumnAxis);
+ return;
+
+ case CSSPropertyWebkitWrapShapeInside:
+ HANDLE_INHERIT_AND_INITIAL(wrapShapeInside, WrapShapeInside);
+ if (!primitiveValue)
+ return;
+ if (primitiveValue->getIdent() == CSSValueAuto)
+ m_style->setWrapShapeInside(0);
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_SHAPE)
+ m_style->setWrapShapeInside(primitiveValue->getShapeValue());
+ return;
+
+ case CSSPropertyWebkitWrapShapeOutside:
+ HANDLE_INHERIT_AND_INITIAL(wrapShapeOutside, WrapShapeOutside);
+ if (!primitiveValue)
+ return;
+ if (primitiveValue->getIdent() == CSSValueAuto)
+ m_style->setWrapShapeOutside(0);
+ else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_SHAPE)
+ m_style->setWrapShapeOutside(primitiveValue->getShapeValue());
+ return;
+
+ // CSS Fonts Module Level 3
+ case CSSPropertyWebkitFontFeatureSettings: {
+ if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
+ setFontDescription(m_style->fontDescription().makeNormalFeatureSettings());
+ return;
+ }
+
+ if (!value->isValueList())
+ return;
+
+ FontDescription fontDescription = m_style->fontDescription();
+ CSSValueList* list = static_cast<CSSValueList*>(value);
+ RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
+ int len = list->length();
+ for (int i = 0; i < len; ++i) {
+ CSSValue* item = list->itemWithoutBoundsCheck(i);
+ if (!item->isFontFeatureValue())
+ continue;
+ FontFeatureValue* feature = static_cast<FontFeatureValue*>(item);
+ settings->append(FontFeature(feature->tag(), feature->value()));
+ }
+ fontDescription.setFeatureSettings(settings.release());
+ setFontDescription(fontDescription);
+ return;
+ }
+
+#if ENABLE(CSS_FILTERS)
+ case CSSPropertyWebkitFilter: {
+ HANDLE_INHERIT_AND_INITIAL(filter, Filter);
+ FilterOperations operations;
+ createFilterOperations(value, style(), m_rootElementStyle, operations);
+ m_style->setFilter(operations);
+ return;
+ }
+#endif
+#if ENABLE(CSS_GRID_LAYOUT)
+ case CSSPropertyWebkitGridColumns: {
+ Vector<Length> lengths;
+ if (!createGridTrackList(value, lengths, this))
+ return;
+ m_style->setGridColumns(lengths);
+ return;
+ }
+ case CSSPropertyWebkitGridRows: {
+ Vector<Length> lengths;
+ if (!createGridTrackList(value, lengths, this))
+ return;
+ m_style->setGridRows(lengths);
+ return;
+ }
+#endif
+
+ // These properties are implemented in the CSSStyleApplyProperty lookup table.
+ case CSSPropertyColor:
+ case CSSPropertyDirection:
+ case CSSPropertyDisplay:
+ case CSSPropertyBackgroundAttachment:
+ case CSSPropertyBackgroundClip:
+ case CSSPropertyWebkitBackgroundClip:
+ case CSSPropertyWebkitBackgroundComposite:
+ case CSSPropertyBackgroundOrigin:
+ case CSSPropertyWebkitBackgroundOrigin:
+ case CSSPropertyBackgroundImage:
+ case CSSPropertyWebkitAspectRatio:
+ case CSSPropertyBackgroundSize:
+ case CSSPropertyWebkitBackgroundSize:
+ case CSSPropertyWebkitMaskAttachment:
+ case CSSPropertyWebkitMaskClip:
+ case CSSPropertyWebkitMaskComposite:
+ case CSSPropertyWebkitMaskOrigin:
+ case CSSPropertyWebkitMaskImage:
+ case CSSPropertyWebkitMaskSize:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyBorderTopStyle:
+ case CSSPropertyBorderRightStyle:
+ case CSSPropertyBorderBottomStyle:
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyBorderTopWidth:
+ case CSSPropertyBorderRightWidth:
+ case CSSPropertyBorderBottomWidth:
+ case CSSPropertyBorderLeftWidth:
+ case CSSPropertyBorder:
+ case CSSPropertyBorderStyle:
+ case CSSPropertyBorderWidth:
+ case CSSPropertyBorderColor:
+ case CSSPropertyBorderImage:
+ case CSSPropertyWebkitBorderImage:
+ case CSSPropertyWebkitMaskBoxImage:
+ case CSSPropertyBorderImageOutset:
+ case CSSPropertyWebkitMaskBoxImageOutset:
+ case CSSPropertyBorderImageRepeat:
+ case CSSPropertyWebkitMaskBoxImageRepeat:
+ case CSSPropertyBorderImageSlice:
+ case CSSPropertyWebkitMaskBoxImageSlice:
+ case CSSPropertyBorderImageWidth:
+ case CSSPropertyWebkitMaskBoxImageWidth:
+ case CSSPropertyBorderImageSource:
+ case CSSPropertyWebkitMaskBoxImageSource:
+ case CSSPropertyBorderTop:
+ case CSSPropertyBorderRight:
+ case CSSPropertyBorderBottom:
+ case CSSPropertyBorderLeft:
+ case CSSPropertyBorderRadius:
+ case CSSPropertyWebkitBorderRadius:
+ case CSSPropertyBorderTopLeftRadius:
+ case CSSPropertyBorderTopRightRadius:
+ case CSSPropertyBorderBottomLeftRadius:
+ case CSSPropertyBorderBottomRightRadius:
+ case CSSPropertyBorderSpacing:
+ case CSSPropertyWebkitBorderHorizontalSpacing:
+ case CSSPropertyWebkitBorderVerticalSpacing:
+ case CSSPropertyCounterIncrement:
+ case CSSPropertyCounterReset:
+ case CSSPropertyLetterSpacing:
+ case CSSPropertyWordSpacing:
+ case CSSPropertyWebkitFlexOrder:
+ case CSSPropertyWebkitFlexPack:
+ case CSSPropertyWebkitFlexAlign:
+ case CSSPropertyWebkitFlexDirection:
+ case CSSPropertyWebkitFlexFlow:
+ case CSSPropertyWebkitFlexWrap:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontVariant:
+ case CSSPropertyTextRendering:
+ case CSSPropertyWebkitTextOrientation:
+ case CSSPropertyWebkitFontSmoothing:
+ case CSSPropertyFontWeight:
+ case CSSPropertyOutline:
+ case CSSPropertyOutlineStyle:
+ case CSSPropertyOutlineWidth:
+ case CSSPropertyOutlineOffset:
+ case CSSPropertyWebkitColumnRuleWidth:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextStrokeColor:
+ case CSSPropertyBackgroundPosition:
+ case CSSPropertyBackgroundPositionX:
+ case CSSPropertyBackgroundPositionY:
+ case CSSPropertyWebkitMaskPosition:
+ case CSSPropertyWebkitMaskPositionX:
+ case CSSPropertyWebkitMaskPositionY:
+ case CSSPropertyBackgroundRepeat:
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ case CSSPropertyWebkitMaskRepeat:
+ case CSSPropertyWebkitMaskRepeatX:
+ case CSSPropertyWebkitMaskRepeatY:
+ case CSSPropertyOverflow:
+ case CSSPropertyOverflowX:
+ case CSSPropertyOverflowY:
+ case CSSPropertyMaxWidth:
+ case CSSPropertyTop:
+ case CSSPropertyLeft:
+ case CSSPropertyRight:
+ case CSSPropertyBottom:
+ case CSSPropertyWidth:
+ case CSSPropertyMinWidth:
+ case CSSPropertyLineHeight:
+ case CSSPropertyListStyle:
+ case CSSPropertyListStyleImage:
+ case CSSPropertyListStylePosition:
+ case CSSPropertyListStyleType:
+ case CSSPropertyMarginTop:
+ case CSSPropertyMarginRight:
+ case CSSPropertyMarginBottom:
+ case CSSPropertyMarginLeft:
+ case CSSPropertyMargin:
+ case CSSPropertyPaddingTop:
+ case CSSPropertyPaddingRight:
+ case CSSPropertyPaddingBottom:
+ case CSSPropertyPaddingLeft:
+ case CSSPropertyPadding:
+ case CSSPropertyResize:
+ case CSSPropertySize:
+ case CSSPropertyTextAlign:
+ case CSSPropertyTextDecoration:
+ case CSSPropertyTextIndent:
+ case CSSPropertyMaxHeight:
+ case CSSPropertyHeight:
+ case CSSPropertyMinHeight:
+ case CSSPropertyVerticalAlign:
+ case CSSPropertyWebkitTransformOriginX:
+ case CSSPropertyWebkitTransformOriginY:
+ case CSSPropertyWebkitTransformOriginZ:
+ case CSSPropertyWebkitTransformOrigin:
+ case CSSPropertyWebkitPerspectiveOriginX:
+ case CSSPropertyWebkitPerspectiveOriginY:
+ case CSSPropertyWebkitPerspectiveOrigin:
+ case CSSPropertyWebkitAnimationDelay:
+ case CSSPropertyWebkitAnimationDirection:
+ case CSSPropertyWebkitAnimationDuration:
+ case CSSPropertyWebkitAnimationFillMode:
+ case CSSPropertyWebkitAnimationIterationCount:
+ case CSSPropertyWebkitAnimationName:
+ case CSSPropertyWebkitAnimationPlayState:
+ case CSSPropertyWebkitAnimationTimingFunction:
+ case CSSPropertyWebkitTransitionDelay:
+ case CSSPropertyWebkitTransitionDuration:
+ case CSSPropertyWebkitTransitionProperty:
+ case CSSPropertyWebkitTransitionTimingFunction:
+ case CSSPropertyCursor:
+ case CSSPropertyWebkitColumns:
+ case CSSPropertyWebkitColumnCount:
+ case CSSPropertyWebkitColumnGap:
+ case CSSPropertyWebkitColumnWidth:
+ case CSSPropertyWebkitFlowInto:
+ case CSSPropertyWebkitFlowFrom:
+ case CSSPropertyWebkitHighlight:
+ case CSSPropertyWebkitHyphenateCharacter:
+ case CSSPropertyWebkitHyphenateLimitAfter:
+ case CSSPropertyWebkitHyphenateLimitBefore:
+ case CSSPropertyWebkitHyphenateLimitLines:
+ case CSSPropertyWebkitLineGrid:
+ case CSSPropertyWebkitLineGridSnap:
+ case CSSPropertyWebkitTextCombine:
+ case CSSPropertyWebkitTextEmphasisPosition:
+ case CSSPropertyWebkitTextEmphasisStyle:
+ case CSSPropertyWebkitWrapMargin:
+ case CSSPropertyWebkitWrapPadding:
+ case CSSPropertyWebkitWrapFlow:
+ case CSSPropertyWebkitWrapThrough:
+ case CSSPropertyWebkitWrap:
+ case CSSPropertyZIndex:
+ case CSSPropertyZoom:
+ ASSERT_NOT_REACHED();
+ return;
+#if ENABLE(SVG)
+ default:
+ // Try the SVG properties
+ applySVGProperty(id, value);
+ return;
+#endif
+ }
+}
+
+void CSSStyleSelector::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ switch (primitiveValue->getIdent()) {
+ case CSSValueFixed:
+ layer->setAttachment(FixedBackgroundAttachment);
+ break;
+ case CSSValueScroll:
+ layer->setAttachment(ScrollBackgroundAttachment);
+ break;
+ case CSSValueLocal:
+ layer->setAttachment(LocalBackgroundAttachment);
+ break;
+ default:
+ return;
+ }
+}
+
+void CSSStyleSelector::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setClip(FillLayer::initialFillClip(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ layer->setClip(*primitiveValue);
+}
+
+void CSSStyleSelector::mapFillComposite(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setComposite(FillLayer::initialFillComposite(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ layer->setComposite(*primitiveValue);
+}
+
+void CSSStyleSelector::mapFillOrigin(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ layer->setOrigin(*primitiveValue);
+}
+
+PassRefPtr<StyleImage> CSSStyleSelector::styleImage(CSSPropertyID property, CSSValue* value)
+{
+ if (value->isImageValue())
+ return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(value));
+
+ if (value->isImageGeneratorValue())
+ return generatedOrPendingFromValue(property, static_cast<CSSImageGeneratorValue*>(value));
+
+ return 0;
+}
+
+PassRefPtr<StyleImage> CSSStyleSelector::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
+{
+ RefPtr<StyleImage> image = value->cachedOrPendingImage();
+ if (image && image->isPendingImage())
+ m_pendingImageProperties.add(property);
+ return image.release();
+}
+
+PassRefPtr<StyleImage> CSSStyleSelector::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue* value)
+{
+ if (value->isPending()) {
+ m_pendingImageProperties.add(property);
+ return StylePendingImage::create(value);
+ }
+ return StyleGeneratedImage::create(value);
+}
+
+void CSSStyleSelector::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setImage(FillLayer::initialFillImage(layer->type()));
+ return;
+ }
+
+ layer->setImage(styleImage(property, value));
+}
+
+void CSSStyleSelector::mapFillRepeatX(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ layer->setRepeatX(*primitiveValue);
+}
+
+void CSSStyleSelector::mapFillRepeatY(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ layer->setRepeatY(*primitiveValue);
+}
+
+void CSSStyleSelector::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (!value->isPrimitiveValue()) {
+ layer->setSizeType(SizeNone);
+ return;
+ }
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == CSSValueContain)
+ layer->setSizeType(Contain);
+ else if (primitiveValue->getIdent() == CSSValueCover)
+ layer->setSizeType(Cover);
+ else
+ layer->setSizeType(SizeLength);
+
+ LengthSize b = FillLayer::initialFillSizeLength(layer->type());
+
+ if (value->isInitialValue() || primitiveValue->getIdent() == CSSValueContain || primitiveValue->getIdent() == CSSValueCover) {
+ layer->setSizeLength(b);
+ return;
+ }
+
+ Pair* pair = primitiveValue->getPairValue();
+
+ CSSPrimitiveValue* first = pair ? static_cast<CSSPrimitiveValue*>(pair->first()) : primitiveValue;
+ 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))
+ firstLength = first->computeLength<Length>(style(), m_rootElementStyle, zoomFactor);
+ else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
+ firstLength = Length(first->getDoubleValue(), Percent);
+ else
+ return;
+
+ if (!second || second->getIdent() == CSSValueAuto)
+ secondLength = Length();
+ else if (CSSPrimitiveValue::isUnitTypeLength(secondType))
+ secondLength = second->computeLength<Length>(style(), m_rootElementStyle, zoomFactor);
+ else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
+ secondLength = Length(second->getDoubleValue(), Percent);
+ else
+ return;
+
+ b.setWidth(firstLength);
+ b.setHeight(secondLength);
+ layer->setSizeLength(b);
+}
+
+void CSSStyleSelector::mapFillXPosition(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ float zoomFactor = m_style->effectiveZoom();
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ Length l;
+ int type = primitiveValue->primitiveType();
+ if (CSSPrimitiveValue::isUnitTypeLength(type))
+ l = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, zoomFactor);
+ else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length(primitiveValue->getDoubleValue(), Percent);
+ else
+ return;
+ layer->setXPosition(l);
+}
+
+void CSSStyleSelector::mapFillYPosition(CSSPropertyID, FillLayer* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ float zoomFactor = m_style->effectiveZoom();
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ Length l;
+ int type = primitiveValue->primitiveType();
+ if (CSSPrimitiveValue::isUnitTypeLength(type))
+ l = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, zoomFactor);
+ else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ l = Length(primitiveValue->getDoubleValue(), Percent);
+ else
+ return;
+ layer->setYPosition(l);
+}
+
+void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ animation->setDelay(Animation::initialAnimationDelay());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
+ animation->setDelay(primitiveValue->getFloatValue());
+ else
+ animation->setDelay(primitiveValue->getFloatValue()/1000.0f);
+}
+
+void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setDirection(Animation::initialAnimationDirection());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal);
+}
+
+void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ animation->setDuration(Animation::initialAnimationDuration());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ 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);
+}
+
+void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setFillMode(Animation::initialAnimationFillMode());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ switch (primitiveValue->getIdent()) {
+ case CSSValueNone:
+ layer->setFillMode(AnimationFillModeNone);
+ break;
+ case CSSValueForwards:
+ layer->setFillMode(AnimationFillModeForwards);
+ break;
+ case CSSValueBackwards:
+ layer->setFillMode(AnimationFillModeBackwards);
+ break;
+ case CSSValueBoth:
+ layer->setFillMode(AnimationFillModeBoth);
+ break;
+ }
+}
+
+void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ animation->setIterationCount(Animation::initialAnimationIterationCount());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == CSSValueInfinite)
+ animation->setIterationCount(-1);
+ else
+ animation->setIterationCount(int(primitiveValue->getFloatValue()));
+}
+
+void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setName(Animation::initialAnimationName());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == CSSValueNone)
+ layer->setIsNoneAnimation(true);
+ else
+ layer->setName(primitiveValue->getStringValue());
+}
+
+void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ layer->setPlayState(Animation::initialAnimationPlayState());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying;
+ layer->setPlayState(playState);
+}
+
+void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ animation->setProperty(Animation::initialAnimationProperty());
+ return;
+ }
+
+ if (!value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->getIdent() == CSSValueAll)
+ animation->setProperty(cAnimateAll);
+ else if (primitiveValue->getIdent() == CSSValueNone)
+ animation->setProperty(cAnimateNone);
+ else
+ animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
+}
+
+void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
+{
+ if (value->isInitialValue()) {
+ animation->setTimingFunction(Animation::initialAnimationTimingFunction());
+ return;
+ }
+
+ if (value->isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ switch (primitiveValue->getIdent()) {
+ case CSSValueLinear:
+ animation->setTimingFunction(LinearTimingFunction::create());
+ break;
+ case CSSValueEase:
+ animation->setTimingFunction(CubicBezierTimingFunction::create());
+ break;
+ case CSSValueEaseIn:
+ animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 1.0, 1.0));
+ break;
+ case CSSValueEaseOut:
+ animation->setTimingFunction(CubicBezierTimingFunction::create(0.0, 0.0, 0.58, 1.0));
+ break;
+ case CSSValueEaseInOut:
+ animation->setTimingFunction(CubicBezierTimingFunction::create(0.42, 0.0, 0.58, 1.0));
+ break;
+ case CSSValueStepStart:
+ animation->setTimingFunction(StepsTimingFunction::create(1, true));
+ break;
+ case CSSValueStepEnd:
+ animation->setTimingFunction(StepsTimingFunction::create(1, false));
+ break;
+ }
+ return;
+ }
+
+ if (value->isTimingFunctionValue()) {
+ CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value);
+ if (timingFunction->isCubicBezierTimingFunctionValue()) {
+ CSSCubicBezierTimingFunctionValue* cubicTimingFunction = static_cast<CSSCubicBezierTimingFunctionValue*>(value);
+ animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2()));
+ } else if (timingFunction->isStepsTimingFunctionValue()) {
+ CSSStepsTimingFunctionValue* stepsTimingFunction = static_cast<CSSStepsTimingFunctionValue*>(value);
+ animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart()));
+ } else
+ animation->setTimingFunction(LinearTimingFunction::create());
+ }
+}
+
+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())
+ return;
+
+ // Retrieve the border image value.
+ CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
+
+ // Set the image (this kicks off the load).
+ CSSPropertyID imageProperty;
+ if (property == CSSPropertyWebkitBorderImage || property == CSSPropertyBorderImage)
+ 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()));
+
+ if (property == CSSPropertyWebkitBorderImage) {
+ // We have to preserve the legacy behavior of -webkit-border-image and make the border slices
+ // also set the border widths. We don't need to worry about percentages, since we don't even support
+ // those on real borders yet.
+ if (image.borderSlices().top().isFixed())
+ style()->setBorderTopWidth(image.borderSlices().top().value());
+ if (image.borderSlices().right().isFixed())
+ style()->setBorderRightWidth(image.borderSlices().right().value());
+ if (image.borderSlices().bottom().isFixed())
+ style()->setBorderBottomWidth(image.borderSlices().bottom().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)
+{
+ if (!value || !value->isBorderImageSliceValue())
+ return;
+
+ // Retrieve the border image value.
+ CSSBorderImageSliceValue* borderImageSlice = static_cast<CSSBorderImageSliceValue*>(value);
+
+ // Set up a length box to represent our image slices.
+ LengthBox box;
+ Quad* slices = borderImageSlice->slices();
+ if (slices->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ 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)
+ 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)
+ 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)
+ box.m_right = Length(slices->right()->getDoubleValue(), Percent);
+ else
+ box.m_right = Length(slices->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
+ image.setImageSlices(box);
+
+ // Set our fill mode.
+ image.setFill(borderImageSlice->m_fill);
+}
+
+LengthBox CSSStyleSelector::mapNinePieceImageQuad(CSSValue* value)
+{
+ if (!value || !value->isPrimitiveValue())
+ return LengthBox();
+
+ // Get our zoom value.
+ float zoom = useSVGZoomRules() ? 1.0f : style()->effectiveZoom();
+
+ // Retrieve the primitive value.
+ CSSPrimitiveValue* borderWidths = static_cast<CSSPrimitiveValue*>(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)
+ box.m_top = Length(slices->top()->getIntValue(), Relative);
+ else if (slices->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ 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)
+ box.m_right = Length(slices->right()->getIntValue(), Relative);
+ else if (slices->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ 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)
+ box.m_bottom = Length(slices->bottom()->getIntValue(), Relative);
+ else if (slices->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ 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)
+ box.m_left = Length(slices->left()->getIntValue(), Relative);
+ else if (slices->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ 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);
+
+ return box;
+}
+
+void CSSStyleSelector::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image)
+{
+ if (!value || !value->isPrimitiveValue())
+ return;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ Pair* pair = primitiveValue->getPairValue();
+ if (!pair || !pair->first() || !pair->second())
+ return;
+
+ int firstIdentifier = pair->first()->getIdent();
+ int secondIdentifier = pair->second()->getIdent();
+
+ ENinePieceImageRule horizontalRule;
+ switch (firstIdentifier) {
+ case CSSValueStretch:
+ horizontalRule = StretchImageRule;
+ break;
+ case CSSValueRound:
+ horizontalRule = RoundImageRule;
+ break;
+ case CSSValueSpace:
+ horizontalRule = SpaceImageRule;
+ break;
+ default: // CSSValueRepeat
+ horizontalRule = RepeatImageRule;
+ break;
+ }
+ image.setHorizontalRule(horizontalRule);
+
+ ENinePieceImageRule verticalRule;
+ switch (secondIdentifier) {
+ case CSSValueStretch:
+ verticalRule = StretchImageRule;
+ break;
+ case CSSValueRound:
+ verticalRule = RoundImageRule;
+ break;
+ case CSSValueSpace:
+ verticalRule = SpaceImageRule;
+ break;
+ default: // CSSValueRepeat
+ verticalRule = RepeatImageRule;
+ break;
+ }
+ image.setVerticalRule(verticalRule);
+}
+
+void CSSStyleSelector::checkForTextSizeAdjust()
+{
+ if (m_style->textSizeAdjust())
+ return;
+
+ FontDescription newFontDescription(m_style->fontDescription());
+ newFontDescription.setComputedSize(newFontDescription.specifiedSize());
+ m_style->setFontDescription(newFontDescription);
+}
+
+void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
+{
+ if (style->effectiveZoom() == parentStyle->effectiveZoom())
+ return;
+
+ const FontDescription& childFont = style->fontDescription();
+ FontDescription newFontDescription(childFont);
+ setFontSize(newFontDescription, childFont.specifiedSize());
+ style->setFontDescription(newFontDescription);
+}
+
+void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
+{
+ const FontDescription& childFont = style->fontDescription();
+
+ if (childFont.isAbsoluteSize() || !parentStyle)
+ return;
+
+ const FontDescription& parentFont = parentStyle->fontDescription();
+ if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
+ return;
+
+ // For now, lump all families but monospace together.
+ if (childFont.genericFamily() != FontDescription::MonospaceFamily &&
+ parentFont.genericFamily() != FontDescription::MonospaceFamily)
+ return;
+
+ // We know the parent is monospace or the child is monospace, and that font
+ // size was unspecified. We want to scale our font size as appropriate.
+ // If the font uses a keyword size, then we refetch from the table rather than
+ // multiplying by our scale factor.
+ float size;
+ if (childFont.keywordSize())
+ size = fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize());
+ else {
+ Settings* settings = m_checker.document()->settings();
+ float fixedScaleFactor = settings
+ ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
+ : 1;
+ size = parentFont.useFixedDefaultSize() ?
+ childFont.specifiedSize() / fixedScaleFactor :
+ childFont.specifiedSize() * fixedScaleFactor;
+ }
+
+ FontDescription newFontDescription(childFont);
+ setFontSize(newFontDescription, size);
+ style->setFontDescription(newFontDescription);
+}
+
+void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size)
+{
+ fontDescription.setSpecifiedSize(size);
+ fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules()));
+}
+
+float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules)
+{
+ float zoomFactor = 1.0f;
+ if (!useSVGZoomRules) {
+ zoomFactor = style->effectiveZoom();
+ if (Frame* frame = document->frame())
+ zoomFactor *= frame->textZoomFactor();
+ }
+
+ return CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, zoomFactor, isAbsoluteSize, specifiedSize);
+}
+
+float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, float zoomFactor, bool isAbsoluteSize, float specifiedSize, ESmartMinimumForFontSize useSmartMinimumForFontSize)
+{
+ // Text with a 0px font size should not be visible and therefore needs to be
+ // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect
+ // rendering. This is also compatible with other browsers that have minimum
+ // font size settings (e.g. Firefox).
+ if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon())
+ return 0.0f;
+
+ // We support two types of minimum font size. The first is a hard override that applies to
+ // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum"
+ // that is applied only when the Web page can't know what size it really asked for, e.g.,
+ // when it uses logical sizes like "small" or expresses the font-size as a percentage of
+ // the user's default font setting.
+
+ // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
+ // However we always allow the page to set an explicit pixel size that is smaller,
+ // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
+
+ Settings* settings = document->settings();
+ if (!settings)
+ return 1.0f;
+
+ int minSize = settings->minimumFontSize();
+ int minLogicalSize = settings->minimumLogicalFontSize();
+ float zoomedSize = specifiedSize * zoomFactor;
+
+ // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small.
+ if (zoomedSize < minSize)
+ zoomedSize = minSize;
+
+ // Now apply the "smart minimum." This minimum is also only applied if we're still too small
+ // after zooming. The font size must either be relative to the user default or the original size
+ // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive
+ // doing so won't disrupt the layout.
+ if (useSmartMinimumForFontSize && zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
+ zoomedSize = minLogicalSize;
+
+ // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
+ // platforms (I'm looking at you, Windows.)
+ return min(1000000.0f, zoomedSize);
+}
+
+const int fontSizeTableMax = 16;
+const int fontSizeTableMin = 9;
+const int totalKeywords = 8;
+
+// WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML.
+static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
+{
+ { 9, 9, 9, 9, 11, 14, 18, 28 },
+ { 9, 9, 9, 10, 12, 15, 20, 31 },
+ { 9, 9, 9, 11, 13, 17, 22, 34 },
+ { 9, 9, 10, 12, 14, 18, 24, 37 },
+ { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13)
+ { 9, 9, 11, 14, 17, 21, 28, 42 },
+ { 9, 10, 12, 15, 17, 23, 30, 45 },
+ { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
+};
+// HTML 1 2 3 4 5 6 7
+// CSS xxs xs s m l xl xxl
+// |
+// user pref
+
+// Strict mode table matches MacIE and Mozilla's settings exactly.
+static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
+{
+ { 9, 9, 9, 9, 11, 14, 18, 27 },
+ { 9, 9, 9, 10, 12, 15, 20, 30 },
+ { 9, 9, 10, 11, 13, 17, 22, 33 },
+ { 9, 9, 10, 12, 14, 18, 24, 36 },
+ { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13)
+ { 9, 10, 12, 14, 17, 21, 28, 42 },
+ { 9, 10, 13, 15, 18, 23, 30, 45 },
+ { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
+};
+// HTML 1 2 3 4 5 6 7
+// CSS xxs xs s m l xl xxl
+// |
+// user pref
+
+// For values outside the range of the table, we use Todd Fahrner's suggested scale
+// factors for each keyword value.
+static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
+
+float CSSStyleSelector::fontSizeForKeyword(Document* document, int keyword, bool shouldUseFixedDefaultSize)
+{
+ Settings* settings = document->settings();
+ if (!settings)
+ return 1.0f;
+
+ bool quirksMode = document->inQuirksMode();
+ int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
+ if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
+ // Look up the entry in the table.
+ int row = mediumSize - fontSizeTableMin;
+ int col = (keyword - CSSValueXxSmall);
+ return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
+ }
+
+ // Value is outside the range of the table. Apply the scale factor instead.
+ float minLogicalSize = max(settings->minimumLogicalFontSize(), 1);
+ return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize);
+}
+
+template<typename T>
+static int findNearestLegacyFontSize(int pixelFontSize, const T* table, int multiplier)
+{
+ // Ignore table[0] because xx-small does not correspond to any legacy font size.
+ for (int i = 1; i < totalKeywords - 1; i++) {
+ if (pixelFontSize * 2 < (table[i] + table[i + 1]) * multiplier)
+ return i;
+ }
+ return totalKeywords - 1;
+}
+
+int CSSStyleSelector::legacyFontSize(Document* document, int pixelFontSize, bool shouldUseFixedDefaultSize)
+{
+ Settings* settings = document->settings();
+ if (!settings)
+ return 1;
+
+ bool quirksMode = document->inQuirksMode();
+ int mediumSize = shouldUseFixedDefaultSize ? settings->defaultFixedFontSize() : settings->defaultFontSize();
+ if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
+ int row = mediumSize - fontSizeTableMin;
+ return findNearestLegacyFontSize<int>(pixelFontSize, quirksMode ? quirksFontSizeTable[row] : strictFontSizeTable[row], 1);
+ }
+
+ return findNearestLegacyFontSize<float>(pixelFontSize, fontSizeFactors, mediumSize);
+}
+
+static Color colorForCSSValue(int cssValueId)
+{
+ struct ColorValue {
+ int cssValueId;
+ RGBA32 color;
+ };
+
+ static const ColorValue colorValues[] = {
+ { CSSValueAqua, 0xFF00FFFF },
+ { CSSValueBlack, 0xFF000000 },
+ { CSSValueBlue, 0xFF0000FF },
+ { CSSValueFuchsia, 0xFFFF00FF },
+ { CSSValueGray, 0xFF808080 },
+ { CSSValueGreen, 0xFF008000 },
+ { CSSValueGrey, 0xFF808080 },
+ { CSSValueLime, 0xFF00FF00 },
+ { CSSValueMaroon, 0xFF800000 },
+ { CSSValueNavy, 0xFF000080 },
+ { CSSValueOlive, 0xFF808000 },
+ { CSSValueOrange, 0xFFFFA500 },
+ { CSSValuePurple, 0xFF800080 },
+ { CSSValueRed, 0xFFFF0000 },
+ { CSSValueSilver, 0xFFC0C0C0 },
+ { CSSValueTeal, 0xFF008080 },
+ { CSSValueTransparent, 0x00000000 },
+ { CSSValueWhite, 0xFFFFFFFF },
+ { CSSValueYellow, 0xFFFFFF00 },
+ { 0, 0 }
+ };
+
+ for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
+ if (col->cssValueId == cssValueId)
+ return col->color;
+ }
+ return RenderTheme::defaultTheme()->systemColor(cssValueId);
+}
+
+Color CSSStyleSelector::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forVisitedLink) const
+{
+ if (value->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
+ return Color(value->getRGBA32Value());
+
+ if (value->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
+ return Color();
+
+ int ident = value->getIdent();
+
+ switch (ident) {
+ case CSSValueWebkitText:
+ return m_element->document()->textColor();
+ case CSSValueWebkitLink:
+ return (m_element->isLink() && forVisitedLink) ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor();
+ case CSSValueWebkitActivelink:
+ return m_element->document()->activeLinkColor();
+ case CSSValueWebkitFocusRingColor:
+ return RenderTheme::focusRingColor();
+ case CSSValueCurrentcolor:
+ return m_style->color();
+ default:
+ return colorForCSSValue(ident);
+ }
+}
+
+bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname) const
+{
+ return m_features.attrsInRules.contains(attrname.impl());
+}
+
+void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
+{
+ m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result));
+}
+
+bool CSSStyleSelector::affectedByViewportChange() const
+{
+ unsigned s = m_viewportDependentMediaQueryResults.size();
+ for (unsigned i = 0; i < s; i++) {
+ if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
+ return true;
+ }
+ return false;
+}
+
+static TransformOperation::OperationType getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type)
+{
+ switch (type) {
+ case WebKitCSSTransformValue::ScaleTransformOperation: return TransformOperation::SCALE;
+ case WebKitCSSTransformValue::ScaleXTransformOperation: return TransformOperation::SCALE_X;
+ case WebKitCSSTransformValue::ScaleYTransformOperation: return TransformOperation::SCALE_Y;
+ case WebKitCSSTransformValue::ScaleZTransformOperation: return TransformOperation::SCALE_Z;
+ case WebKitCSSTransformValue::Scale3DTransformOperation: return TransformOperation::SCALE_3D;
+ case WebKitCSSTransformValue::TranslateTransformOperation: return TransformOperation::TRANSLATE;
+ case WebKitCSSTransformValue::TranslateXTransformOperation: return TransformOperation::TRANSLATE_X;
+ case WebKitCSSTransformValue::TranslateYTransformOperation: return TransformOperation::TRANSLATE_Y;
+ case WebKitCSSTransformValue::TranslateZTransformOperation: return TransformOperation::TRANSLATE_Z;
+ case WebKitCSSTransformValue::Translate3DTransformOperation: return TransformOperation::TRANSLATE_3D;
+ case WebKitCSSTransformValue::RotateTransformOperation: return TransformOperation::ROTATE;
+ case WebKitCSSTransformValue::RotateXTransformOperation: return TransformOperation::ROTATE_X;
+ case WebKitCSSTransformValue::RotateYTransformOperation: return TransformOperation::ROTATE_Y;
+ case WebKitCSSTransformValue::RotateZTransformOperation: return TransformOperation::ROTATE_Z;
+ case WebKitCSSTransformValue::Rotate3DTransformOperation: return TransformOperation::ROTATE_3D;
+ case WebKitCSSTransformValue::SkewTransformOperation: return TransformOperation::SKEW;
+ case WebKitCSSTransformValue::SkewXTransformOperation: return TransformOperation::SKEW_X;
+ case WebKitCSSTransformValue::SkewYTransformOperation: return TransformOperation::SKEW_Y;
+ case WebKitCSSTransformValue::MatrixTransformOperation: return TransformOperation::MATRIX;
+ case WebKitCSSTransformValue::Matrix3DTransformOperation: return TransformOperation::MATRIX_3D;
+ case WebKitCSSTransformValue::PerspectiveTransformOperation: return TransformOperation::PERSPECTIVE;
+ case WebKitCSSTransformValue::UnknownTransformOperation: return TransformOperation::NONE;
+ }
+ return TransformOperation::NONE;
+}
+
+bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations)
+{
+ if (!inValue || !inValue->isValueList()) {
+ outOperations.clear();
+ return false;
+ }
+
+ float zoomFactor = style ? style->effectiveZoom() : 1;
+ TransformOperations operations;
+ for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (!currValue->isWebKitCSSTransformValue())
+ continue;
+
+ WebKitCSSTransformValue* transformValue = static_cast<WebKitCSSTransformValue*>(i.value());
+ if (!transformValue->length())
+ continue;
+
+ bool haveNonPrimitiveValue = false;
+ for (unsigned j = 0; j < transformValue->length(); ++j) {
+ if (!transformValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) {
+ haveNonPrimitiveValue = true;
+ break;
+ }
+ }
+ if (haveNonPrimitiveValue)
+ continue;
+
+ CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0));
+
+ switch (transformValue->operationType()) {
+ case WebKitCSSTransformValue::ScaleTransformOperation:
+ case WebKitCSSTransformValue::ScaleXTransformOperation:
+ case WebKitCSSTransformValue::ScaleYTransformOperation: {
+ double sx = 1.0;
+ double sy = 1.0;
+ if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
+ sy = firstValue->getDoubleValue();
+ else {
+ sx = firstValue->getDoubleValue();
+ if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
+ if (transformValue->length() > 1) {
+ CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
+ sy = secondValue->getDoubleValue();
+ } else
+ sy = sx;
+ }
+ }
+ operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::ScaleZTransformOperation:
+ case WebKitCSSTransformValue::Scale3DTransformOperation: {
+ double sx = 1.0;
+ double sy = 1.0;
+ double sz = 1.0;
+ if (transformValue->operationType() == WebKitCSSTransformValue::ScaleZTransformOperation)
+ sz = firstValue->getDoubleValue();
+ else if (transformValue->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
+ sy = firstValue->getDoubleValue();
+ else {
+ sx = firstValue->getDoubleValue();
+ if (transformValue->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
+ if (transformValue->length() > 2) {
+ CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
+ sz = thirdValue->getDoubleValue();
+ }
+ if (transformValue->length() > 1) {
+ CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
+ sy = secondValue->getDoubleValue();
+ } else
+ sy = sx;
+ }
+ }
+ operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::TranslateTransformOperation:
+ case WebKitCSSTransformValue::TranslateXTransformOperation:
+ case WebKitCSSTransformValue::TranslateYTransformOperation: {
+ bool ok = true;
+ Length tx = Length(0, Fixed);
+ Length ty = Length(0, Fixed);
+ if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
+ ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ else {
+ tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
+ if (transformValue->length() > 1) {
+ CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
+ ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok);
+ }
+ }
+ }
+
+ if (!ok)
+ return false;
+
+ operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::TranslateZTransformOperation:
+ case WebKitCSSTransformValue::Translate3DTransformOperation: {
+ bool ok = true;
+ Length tx = Length(0, Fixed);
+ Length ty = Length(0, Fixed);
+ Length tz = Length(0, Fixed);
+ if (transformValue->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation)
+ tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ else if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
+ ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ else {
+ tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
+ if (transformValue->length() > 2) {
+ CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
+ tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor, &ok);
+ }
+ if (transformValue->length() > 1) {
+ CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
+ ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok);
+ }
+ }
+ }
+
+ if (!ok)
+ return false;
+
+ operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType())));
+ 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);
+
+ operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::RotateXTransformOperation:
+ case WebKitCSSTransformValue::RotateYTransformOperation:
+ case WebKitCSSTransformValue::RotateZTransformOperation: {
+ 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);
+
+ if (transformValue->operationType() == WebKitCSSTransformValue::RotateXTransformOperation)
+ x = 1;
+ else if (transformValue->operationType() == WebKitCSSTransformValue::RotateYTransformOperation)
+ y = 1;
+ else
+ z = 1;
+ operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::Rotate3DTransformOperation: {
+ if (transformValue->length() < 4)
+ break;
+ CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1));
+ CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2));
+ CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3));
+ 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);
+ operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::SkewTransformOperation:
+ case WebKitCSSTransformValue::SkewXTransformOperation:
+ 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);
+ if (transformValue->operationType() == WebKitCSSTransformValue::SkewYTransformOperation)
+ angleY = angle;
+ else {
+ angleX = angle;
+ 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);
+ }
+ }
+ }
+ operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType())));
+ break;
+ }
+ case WebKitCSSTransformValue::MatrixTransformOperation: {
+ if (transformValue->length() < 6)
+ break;
+ double a = firstValue->getDoubleValue();
+ double b = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue();
+ double c = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue();
+ double d = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue();
+ double e = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue();
+ double f = zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue();
+ operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f));
+ break;
+ }
+ case WebKitCSSTransformValue::Matrix3DTransformOperation: {
+ if (transformValue->length() < 16)
+ break;
+ TransformationMatrix matrix(static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(0))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(6))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(7))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(8))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(9))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(10))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(11))->getDoubleValue(),
+ zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(12))->getDoubleValue(),
+ zoomFactor * static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(13))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(14))->getDoubleValue(),
+ static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(15))->getDoubleValue());
+ operations.operations().append(Matrix3DTransformOperation::create(matrix));
+ break;
+ }
+ case WebKitCSSTransformValue::PerspectiveTransformOperation: {
+ bool ok = true;
+ Length p = Length(0, Fixed);
+ if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType()))
+ p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ else {
+ // This is a quirk that should go away when 3d transforms are finalized.
+ double val = firstValue->getDoubleValue();
+ ok = val >= 0;
+ p = Length(clampToPositiveInteger(val), Fixed);
+ }
+
+ if (!ok)
+ return false;
+
+ operations.operations().append(PerspectiveTransformOperation::create(p));
+ break;
+ }
+ case WebKitCSSTransformValue::UnknownTransformOperation:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ outOperations = operations;
+ return true;
+}
+
+#if ENABLE(CSS_FILTERS)
+static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type)
+{
+ switch (type) {
+ case WebKitCSSFilterValue::ReferenceFilterOperation:
+ return FilterOperation::REFERENCE;
+ case WebKitCSSFilterValue::GrayscaleFilterOperation:
+ return FilterOperation::GRAYSCALE;
+ case WebKitCSSFilterValue::SepiaFilterOperation:
+ return FilterOperation::SEPIA;
+ case WebKitCSSFilterValue::SaturateFilterOperation:
+ return FilterOperation::SATURATE;
+ case WebKitCSSFilterValue::HueRotateFilterOperation:
+ return FilterOperation::HUE_ROTATE;
+ case WebKitCSSFilterValue::InvertFilterOperation:
+ return FilterOperation::INVERT;
+ case WebKitCSSFilterValue::OpacityFilterOperation:
+ return FilterOperation::OPACITY;
+ case WebKitCSSFilterValue::BrightnessFilterOperation:
+ return FilterOperation::BRIGHTNESS;
+ case WebKitCSSFilterValue::ContrastFilterOperation:
+ return FilterOperation::CONTRAST;
+ case WebKitCSSFilterValue::BlurFilterOperation:
+ return FilterOperation::BLUR;
+ case WebKitCSSFilterValue::DropShadowFilterOperation:
+ return FilterOperation::DROP_SHADOW;
+#if ENABLE(CSS_SHADERS)
+ case WebKitCSSFilterValue::CustomFilterOperation:
+ return FilterOperation::CUSTOM;
+#endif
+ case WebKitCSSFilterValue::UnknownFilterOperation:
+ return FilterOperation::NONE;
+ }
+ return FilterOperation::NONE;
+}
+
+#if ENABLE(CSS_SHADERS)
+StyleShader* CSSStyleSelector::styleShader(CSSValue* value)
+{
+ if (value->isWebKitCSSShaderValue())
+ return cachedOrPendingStyleShaderFromValue(static_cast<WebKitCSSShaderValue*>(value));
+ return 0;
+}
+
+StyleShader* CSSStyleSelector::cachedOrPendingStyleShaderFromValue(WebKitCSSShaderValue* value)
+{
+ StyleShader* shader = value->cachedOrPendingShader();
+ if (shader && shader->isPendingShader())
+ m_hasPendingShaders = true;
+ return shader;
+}
+
+void CSSStyleSelector::loadPendingShaders()
+{
+ if (!m_style->hasFilter() || !m_hasPendingShaders)
+ return;
+
+ CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader();
+
+ Vector<RefPtr<FilterOperation> >& filterOperations = m_style->filter().operations();
+ for (unsigned i = 0; i < filterOperations.size(); ++i) {
+ 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));
+ }
+ if (customFilter->fragmentShader() && customFilter->fragmentShader()->isPendingShader()) {
+ WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(customFilter->fragmentShader())->cssShaderValue();
+ customFilter->setFragmentShader(shaderValue->cachedShader(cachedResourceLoader));
+ }
+ }
+ }
+ m_hasPendingShaders = false;
+}
+
+PassRefPtr<CustomFilterOperation> CSSStyleSelector::createCustomFilterOperation(WebKitCSSFilterValue* filterValue)
+{
+ ASSERT(filterValue->length());
+
+ CSSValue* shadersValue = filterValue->itemWithoutBoundsCheck(0);
+ ASSERT(shadersValue->isValueList());
+ CSSValueList* shadersList = static_cast<CSSValueList*>(shadersValue);
+
+ ASSERT(shadersList->length());
+ RefPtr<StyleShader> vertexShader = styleShader(shadersList->itemWithoutBoundsCheck(0));
+ RefPtr<StyleShader> fragmentShader = (shadersList->length() > 1) ? styleShader(shadersList->itemWithoutBoundsCheck(1)) : 0;
+
+ unsigned meshRows = 1;
+ unsigned meshColumns = 1;
+ CustomFilterOperation::MeshBoxType meshBoxType = CustomFilterOperation::FILTER_BOX;
+ CustomFilterOperation::MeshType meshType = CustomFilterOperation::ATTACHED;
+
+ if (filterValue->length() > 1) {
+ CSSValueListIterator iterator(filterValue->itemWithoutBoundsCheck(1));
+
+ // The second value might be the mesh box or the list of parameters:
+ // If it starts with a number or any of the mesh-box identifiers it is
+ // the mesh-box list, if not it means it is the parameters list.
+
+ if (iterator.hasMore() && iterator.isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value());
+ if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
+ // If only one integer value is specified, it will set both
+ // the rows and the columns.
+ meshRows = meshColumns = primitiveValue->getIntValue();
+ iterator.advance();
+
+ // 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) {
+ meshColumns = primitiveValue->getIntValue();
+ iterator.advance();
+ }
+ }
+ }
+ }
+
+ if (iterator.hasMore() && iterator.isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value());
+ if (primitiveValue->getIdent() == CSSValueBorderBox
+ || primitiveValue->getIdent() == CSSValuePaddingBox
+ || primitiveValue->getIdent() == CSSValueContentBox
+ || primitiveValue->getIdent() == CSSValueFilterBox) {
+ meshBoxType = *primitiveValue;
+ iterator.advance();
+ }
+ }
+
+ if (iterator.hasMore() && iterator.isPrimitiveValue()) {
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value());
+ if (primitiveValue->getIdent() == CSSValueDetached) {
+ meshType = CustomFilterOperation::DETACHED;
+ iterator.advance();
+ }
+ }
+ }
+
+ return CustomFilterOperation::create(vertexShader, fragmentShader, meshRows, meshColumns, meshBoxType, meshType);
+}
+#endif
+
+bool CSSStyleSelector::createFilterOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, FilterOperations& outOperations)
+{
+ if (!inValue || !inValue->isValueList()) {
+ outOperations.clear();
+ return false;
+ }
+
+ float zoomFactor = style ? style->effectiveZoom() : 1;
+ FilterOperations operations;
+ for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) {
+ CSSValue* currValue = i.value();
+ if (!currValue->isWebKitCSSFilterValue())
+ continue;
+
+ WebKitCSSFilterValue* filterValue = static_cast<WebKitCSSFilterValue*>(i.value());
+ FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType());
+
+#if ENABLE(CSS_SHADERS)
+ if (operationType == FilterOperation::CUSTOM) {
+ RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue);
+ if (operation)
+ operations.operations().append(operation);
+ continue;
+ }
+#endif
+
+ // Check that all parameters are primitive values, with the
+ // exception of drop shadow which has a ShadowValue parameter.
+ if (operationType != FilterOperation::DROP_SHADOW) {
+ bool haveNonPrimitiveValue = false;
+ for (unsigned j = 0; j < filterValue->length(); ++j) {
+ if (!filterValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) {
+ haveNonPrimitiveValue = true;
+ break;
+ }
+ }
+ if (haveNonPrimitiveValue)
+ continue;
+ }
+
+ CSSPrimitiveValue* firstValue = filterValue->length() ? static_cast<CSSPrimitiveValue*>(filterValue->itemWithoutBoundsCheck(0)) : 0;
+ switch (filterValue->operationType()) {
+ case WebKitCSSFilterValue::ReferenceFilterOperation: {
+ if (firstValue)
+ operations.operations().append(ReferenceFilterOperation::create(firstValue->getStringValue(), operationType));
+ break;
+ }
+ case WebKitCSSFilterValue::GrayscaleFilterOperation:
+ case WebKitCSSFilterValue::SepiaFilterOperation:
+ case WebKitCSSFilterValue::SaturateFilterOperation: {
+ double amount = 1;
+ if (filterValue->length() == 1) {
+ amount = firstValue->getDoubleValue();
+ if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+ amount /= 100;
+ }
+
+ operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
+ break;
+ }
+ 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);
+ }
+
+ operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
+ break;
+ }
+ case WebKitCSSFilterValue::InvertFilterOperation:
+ case WebKitCSSFilterValue::BrightnessFilterOperation:
+ case WebKitCSSFilterValue::ContrastFilterOperation:
+ case WebKitCSSFilterValue::OpacityFilterOperation: {
+ double amount = 1;
+ if (filterValue->length() == 1) {
+ amount = firstValue->getDoubleValue();
+ if (firstValue->isPercentage())
+ amount /= 100;
+ }
+
+ operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
+ break;
+ }
+ case WebKitCSSFilterValue::BlurFilterOperation: {
+ bool ok = true;
+ Length stdDeviation = Length(0, Fixed);
+ if (filterValue->length() >= 1) {
+ stdDeviation = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok);
+ }
+ if (!ok)
+ return false;
+
+ operations.operations().append(BlurFilterOperation::create(stdDeviation, operationType));
+ break;
+ }
+ case WebKitCSSFilterValue::DropShadowFilterOperation: {
+ if (filterValue->length() != 1)
+ return false;
+
+ CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0);
+ if (!cssValue->isShadowValue())
+ continue;
+
+ ShadowValue* item = static_cast<ShadowValue*>(cssValue);
+ int x = item->x->computeLength<int>(style, rootStyle, zoomFactor);
+ int y = item->y->computeLength<int>(style, rootStyle, zoomFactor);
+ int blur = item->blur ? item->blur->computeLength<int>(style, rootStyle, zoomFactor) : 0;
+ Color color;
+ if (item->color)
+ color = colorFromPrimitiveValue(item->color.get());
+
+ operations.operations().append(DropShadowFilterOperation::create(x, y, blur, color.isValid() ? color : Color::transparent, operationType));
+ break;
+ }
+ case WebKitCSSFilterValue::UnknownFilterOperation:
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ outOperations = operations;
+ return true;
+}
+
+#endif
+
+PassRefPtr<StyleImage> CSSStyleSelector::loadPendingImage(StylePendingImage* pendingImage)
+{
+ CachedResourceLoader* cachedResourceLoader = m_element->document()->cachedResourceLoader();
+
+ if (pendingImage->cssImageValue()) {
+ CSSImageValue* imageValue = pendingImage->cssImageValue();
+ return imageValue->cachedImage(cachedResourceLoader);
+ }
+
+ if (pendingImage->cssImageGeneratorValue()) {
+ CSSImageGeneratorValue* imageGeneratorValue = pendingImage->cssImageGeneratorValue();
+ imageGeneratorValue->loadSubimages(cachedResourceLoader);
+ return StyleGeneratedImage::create(imageGeneratorValue);
+ }
+
+ return 0;
+}
+
+void CSSStyleSelector::loadPendingImages()
+{
+ if (m_pendingImageProperties.isEmpty())
+ return;
+
+ HashSet<int>::const_iterator end = m_pendingImageProperties.end();
+ for (HashSet<int>::const_iterator it = m_pendingImageProperties.begin(); it != end; ++it) {
+ CSSPropertyID currentProperty = static_cast<CSSPropertyID>(*it);
+
+ switch (currentProperty) {
+ case CSSPropertyBackgroundImage: {
+ for (FillLayer* backgroundLayer = m_style->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
+ if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
+ backgroundLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(backgroundLayer->image())));
+ }
+ break;
+ }
+ case CSSPropertyContent: {
+ for (ContentData* contentData = const_cast<ContentData*>(m_style->contentData()); contentData; contentData = contentData->next()) {
+ if (contentData->isImage()) {
+ StyleImage* image = static_cast<ImageContentData*>(contentData)->image();
+ if (image->isPendingImage()) {
+ RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(image));
+ if (loadedImage)
+ static_cast<ImageContentData*>(contentData)->setImage(loadedImage.release());
+ }
+ }
+ }
+ break;
+ }
+ case CSSPropertyCursor: {
+ if (CursorList* cursorList = m_style->cursors()) {
+ for (size_t i = 0; i < cursorList->size(); ++i) {
+ CursorData& currentCursor = cursorList->at(i);
+ if (StyleImage* image = currentCursor.image()) {
+ if (image->isPendingImage())
+ currentCursor.setImage(loadPendingImage(static_cast<StylePendingImage*>(image)));
+ }
+ }
+ }
+ break;
+ }
+ case CSSPropertyListStyleImage: {
+ if (m_style->listStyleImage() && m_style->listStyleImage()->isPendingImage())
+ m_style->setListStyleImage(loadPendingImage(static_cast<StylePendingImage*>(m_style->listStyleImage())));
+ break;
+ }
+ case CSSPropertyBorderImageSource: {
+ if (m_style->borderImageSource() && m_style->borderImageSource()->isPendingImage())
+ m_style->setBorderImageSource(loadPendingImage(static_cast<StylePendingImage*>(m_style->borderImageSource())));
+ break;
+ }
+ case CSSPropertyWebkitBoxReflect: {
+ if (StyleReflection* reflection = m_style->boxReflect()) {
+ const NinePieceImage& maskImage = reflection->mask();
+ if (maskImage.image() && maskImage.image()->isPendingImage()) {
+ RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(maskImage.image()));
+ reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
+ }
+ }
+ break;
+ }
+ case CSSPropertyWebkitMaskBoxImageSource: {
+ if (m_style->maskBoxImageSource() && m_style->maskBoxImageSource()->isPendingImage())
+ m_style->setMaskBoxImageSource(loadPendingImage(static_cast<StylePendingImage*>(m_style->maskBoxImageSource())));
+ break;
+ }
+ case CSSPropertyWebkitMaskImage: {
+ for (FillLayer* maskLayer = m_style->accessMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
+ if (maskLayer->image() && maskLayer->image()->isPendingImage())
+ maskLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(maskLayer->image())));
+ }
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+
+ m_pendingImageProperties.clear();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSStyleSelector.h b/Source/WebCore/css/CSSStyleSelector.h
new file mode 100644
index 000000000..872b634f5
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleSelector.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 CSSStyleSelector_h
+#define CSSStyleSelector_h
+
+#include "CSSRule.h"
+#include "LinkHash.h"
+#include "MediaQueryExp.h"
+#include "RenderStyle.h"
+#include "SelectorChecker.h"
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+enum ESmartMinimumForFontSize { DoNotUseSmartMinimumForFontSize, UseSmartMinimumForFontFize };
+
+class CSSFontSelector;
+class CSSMutableStyleDeclaration;
+class CSSPageRule;
+class CSSPrimitiveValue;
+class CSSProperty;
+class CSSFontFace;
+class CSSFontFaceRule;
+class CSSImageGeneratorValue;
+class CSSImageValue;
+class CSSRuleList;
+class CSSSelector;
+class CSSStyleApplyProperty;
+class CSSStyleRule;
+class CSSStyleSheet;
+class CSSValue;
+class ContainerNode;
+class CustomFilterOperation;
+class Document;
+class Element;
+class Frame;
+class FrameView;
+class KURL;
+class KeyframeList;
+class KeyframeValue;
+class MediaQueryEvaluator;
+class Node;
+class RuleData;
+class RuleSet;
+class Settings;
+class StyleImage;
+class StylePendingImage;
+class StyleShader;
+class StyleSheet;
+class StyleSheetList;
+class StyledElement;
+class WebKitCSSKeyframeRule;
+class WebKitCSSKeyframesRule;
+class WebKitCSSFilterValue;
+class WebKitCSSRegionRule;
+class WebKitCSSShaderValue;
+
+class MediaQueryResult {
+ WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED;
+public:
+ MediaQueryResult(const MediaQueryExp& expr, bool result)
+ : m_expression(expr)
+ , m_result(result)
+ {
+ }
+
+ MediaQueryExp m_expression;
+ bool m_result;
+};
+
+// This class selects a RenderStyle for a given element based on a collection of stylesheets.
+class CSSStyleSelector {
+ WTF_MAKE_NONCOPYABLE(CSSStyleSelector); WTF_MAKE_FAST_ALLOCATED;
+public:
+ CSSStyleSelector(Document*, StyleSheetList* authorSheets, CSSStyleSheet* mappedElementSheet,
+ CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets,
+ bool strictParsing, bool matchAuthorAndUserStyles);
+ ~CSSStyleSelector();
+
+ // 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); }
+
+ PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false);
+
+ void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList&);
+
+ PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId, Element*, RenderStyle* parentStyle = 0);
+
+ PassRefPtr<RenderStyle> styleForPage(int pageIndex);
+
+ static PassRefPtr<RenderStyle> styleForDocument(Document*, CSSFontSelector* = 0);
+
+ RenderStyle* style() const { return m_style.get(); }
+ RenderStyle* parentStyle() const { return m_parentStyle; }
+ RenderStyle* rootElementStyle() const { return m_rootElementStyle; }
+ Element* element() const { return m_element; }
+ Document* document() const { return m_checker.document(); }
+ FontDescription fontDescription() { return style()->fontDescription(); }
+ FontDescription parentFontDescription() {return parentStyle()->fontDescription(); }
+ void setFontDescription(FontDescription fontDescription) { m_fontDirty |= style()->setFontDescription(fontDescription); }
+ void setZoom(float f) { m_fontDirty |= style()->setZoom(f); }
+ void setEffectiveZoom(float f) { m_fontDirty |= style()->setEffectiveZoom(f); }
+ void setTextSizeAdjust(bool b) { m_fontDirty |= style()->setTextSizeAdjust(b); }
+ bool hasParentNode() const { return m_parentNode; }
+
+ void appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >&);
+
+ // Find the ids or classes the selectors on a stylesheet are scoped to. The selectors only apply to elements in subtrees where the root element matches the scope.
+ static bool determineStylesheetSelectorScopes(CSSStyleSheet*, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes);
+
+private:
+ void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO);
+ void initElement(Element*);
+ void collectFeatures();
+ RenderStyle* locateSharedStyle();
+ bool matchesRuleSet(RuleSet*);
+ Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const;
+ StyledElement* findSiblingForStyleSharing(Node*, unsigned& count) const;
+ bool canShareStyleWithElement(StyledElement*) const;
+
+ PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&);
+
+public:
+ // These methods will give back the set of rules that matched for a given element (or a pseudo-element).
+ enum CSSRuleFilter {
+ UAAndUserCSSRules = 1 << 1,
+ AuthorCSSRules = 1 << 2,
+ EmptyCSSRules = 1 << 3,
+ CrossOriginCSSRules = 1 << 4,
+ AllButEmptyCSSRules = UAAndUserCSSRules | AuthorCSSRules | CrossOriginCSSRules,
+ AllCSSRules = AllButEmptyCSSRules | EmptyCSSRules,
+ };
+ PassRefPtr<CSSRuleList> styleRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules);
+ PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules);
+
+ // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return
+ // the correct font size scaled relative to the user's default (medium).
+ static float fontSizeForKeyword(Document*, int keyword, bool shouldUseFixedDefaultSize);
+
+ // Given a font size in pixel, this function will return legacy font size between 1 and 7.
+ static int legacyFontSize(Document*, int pixelFontSize, bool shouldUseFixedDefaultSize);
+
+public:
+ void setStyle(PassRefPtr<RenderStyle> s) { m_style = s; } // Used by the document when setting up its root style.
+
+ void applyPropertyToStyle(int id, CSSValue*, RenderStyle*);
+
+ void applyPropertyToCurrentStyle(int id, CSSValue*);
+
+ void updateFont();
+
+ static float getComputedSizeFromSpecifiedSize(Document*, float zoomFactor, bool isAbsoluteSize, float specifiedSize, ESmartMinimumForFontSize = UseSmartMinimumForFontFize);
+
+ void setFontSize(FontDescription&, float size);
+
+private:
+ static float getComputedSizeFromSpecifiedSize(Document*, RenderStyle*, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules);
+
+public:
+ bool useSVGZoomRules();
+
+ Color colorFromPrimitiveValue(CSSPrimitiveValue*, bool forVisitedLink = false) const;
+
+ bool hasSelectorForAttribute(const AtomicString&) const;
+
+ CSSFontSelector* fontSelector() const { return m_fontSelector.get(); }
+
+ void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result);
+
+ bool affectedByViewportChange() const;
+
+ void allVisitedStateChanged() { m_checker.allVisitedStateChanged(); }
+ void visitedStateChanged(LinkHash visitedHash) { m_checker.visitedStateChanged(visitedHash); }
+
+ void addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule>);
+ void addPageStyle(PassRefPtr<CSSPageRule>);
+ void addRegionRule(PassRefPtr<WebKitCSSRegionRule>);
+
+ bool checkRegionStyle(Element*);
+
+ bool usesSiblingRules() const { return m_features.siblingRules; }
+ bool usesFirstLineRules() const { return m_features.usesFirstLineRules; }
+ bool usesBeforeAfterRules() const { return m_features.usesBeforeAfterRules; }
+ bool usesLinkRules() const { return m_features.usesLinkRules; }
+
+ static bool createTransformOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, TransformOperations& outOperations);
+
+ void invalidateMatchedDeclarationCache();
+
+#if ENABLE(CSS_FILTERS)
+ bool createFilterOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, FilterOperations& outOperations);
+#if ENABLE(CSS_SHADERS)
+ StyleShader* styleShader(CSSValue*);
+ StyleShader* cachedOrPendingStyleShaderFromValue(WebKitCSSShaderValue*);
+ PassRefPtr<CustomFilterOperation> createCustomFilterOperation(WebKitCSSFilterValue*);
+ void loadPendingShaders();
+#endif
+#endif // ENABLE(CSS_FILTERS)
+
+ struct Features {
+ Features();
+ ~Features();
+ void clear();
+ HashSet<AtomicStringImpl*> idsInRules;
+ HashSet<AtomicStringImpl*> attrsInRules;
+ OwnPtr<RuleSet> siblingRules;
+ OwnPtr<RuleSet> uncommonAttributeRules;
+ bool usesFirstLineRules;
+ bool usesBeforeAfterRules;
+ bool usesLinkRules;
+ };
+
+private:
+ // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
+ void checkForGenericFamilyChange(RenderStyle*, RenderStyle* parentStyle);
+ void checkForZoomChange(RenderStyle*, RenderStyle* parentStyle);
+ void checkForTextSizeAdjust();
+
+ void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*);
+
+ 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) { }
+ int firstUARule;
+ int lastUARule;
+ int firstAuthorRule;
+ int lastAuthorRule;
+ int firstUserRule;
+ int lastUserRule;
+ 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);
+ bool fastRejectSelector(const RuleData&) const;
+ void sortMatchedRules();
+
+ bool checkSelector(const RuleData&);
+
+ 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);
+
+ 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;
+ bool isRightPage(int pageIndex) const { return !isLeftPage(pageIndex); }
+ bool isFirstPage(int pageIndex) const;
+ String pageName(int pageIndex) const;
+
+ OwnPtr<RuleSet> m_authorStyle;
+ OwnPtr<RuleSet> m_userStyle;
+
+ Features m_features;
+
+ bool m_hasUAAppearance;
+ BorderData m_borderData;
+ FillLayer m_backgroundData;
+ Color m_backgroundColor;
+
+ typedef HashMap<AtomicStringImpl*, RefPtr<WebKitCSSKeyframesRule> > KeyframesRuleMap;
+ KeyframesRuleMap m_keyframesRuleMap;
+
+ typedef Vector<RefPtr<WebKitCSSRegionRule> > RegionStyleRules;
+ RegionStyleRules m_regionStyleRules;
+
+public:
+ static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; }
+
+ PassRefPtr<StyleImage> styleImage(CSSPropertyID, CSSValue*);
+ PassRefPtr<StyleImage> cachedOrPendingFromValue(CSSPropertyID, CSSImageValue*);
+ PassRefPtr<StyleImage> generatedOrPendingFromValue(CSSPropertyID, CSSImageGeneratorValue*);
+
+ bool applyPropertyToRegularStyle() const { return m_applyPropertyToRegularStyle; }
+ bool applyPropertyToVisitedLinkStyle() const { return m_applyPropertyToVisitedLinkStyle; }
+
+private:
+ static RenderStyle* s_styleNotYetAvailable;
+
+ void cacheBorderAndBackground();
+
+ void mapFillAttachment(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillClip(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillComposite(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillOrigin(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillImage(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillRepeatX(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillRepeatY(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillSize(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillXPosition(CSSPropertyID, FillLayer*, CSSValue*);
+ void mapFillYPosition(CSSPropertyID, FillLayer*, CSSValue*);
+
+ void mapAnimationDelay(Animation*, CSSValue*);
+ void mapAnimationDirection(Animation*, CSSValue*);
+ void mapAnimationDuration(Animation*, CSSValue*);
+ void mapAnimationFillMode(Animation*, CSSValue*);
+ void mapAnimationIterationCount(Animation*, CSSValue*);
+ void mapAnimationName(Animation*, CSSValue*);
+ void mapAnimationPlayState(Animation*, CSSValue*);
+ void mapAnimationProperty(Animation*, CSSValue*);
+ void mapAnimationTimingFunction(Animation*, CSSValue*);
+
+public:
+ void mapNinePieceImage(CSSPropertyID, CSSValue*, NinePieceImage&);
+ void mapNinePieceImageSlice(CSSValue*, NinePieceImage&);
+ LengthBox mapNinePieceImageQuad(CSSValue*);
+ void mapNinePieceImageRepeat(CSSValue*, NinePieceImage&);
+private:
+ bool canShareStyleWithControl(StyledElement*) const;
+
+ void applyProperty(int id, CSSValue*);
+#if ENABLE(SVG)
+ void applySVGProperty(int id, CSSValue*);
+#endif
+
+ PassRefPtr<StyleImage> loadPendingImage(StylePendingImage*);
+ void loadPendingImages();
+
+ struct MatchedStyleDeclaration {
+ MatchedStyleDeclaration();
+ CSSMutableStyleDeclaration* styleDeclaration;
+ unsigned linkMatchType;
+ };
+ static unsigned computeDeclarationHash(MatchedStyleDeclaration*, unsigned size);
+ struct MatchedStyleDeclarationCacheItem {
+ Vector<MatchedStyleDeclaration> matchedStyleDeclarations;
+ MatchResult matchResult;
+ RefPtr<RenderStyle> renderStyle;
+ RefPtr<RenderStyle> parentRenderStyle;
+ };
+ const MatchedStyleDeclarationCacheItem* findFromMatchedDeclarationCache(unsigned hash, const MatchResult&);
+ void addToMatchedDeclarationCache(const RenderStyle*, const RenderStyle* parentStyle, unsigned hash, const MatchResult&);
+
+ // We collect the set of decls that match in |m_matchedDecls|. We then walk the
+ // set of matched decls four times, once for those properties that others depend on (like font-size),
+ // and then a second time for all the remaining properties. We then do the same two passes
+ // for any !important rules.
+ Vector<MatchedStyleDeclaration, 64> m_matchedDecls;
+
+ typedef HashMap<unsigned, MatchedStyleDeclarationCacheItem> MatchedStyleDeclarationCache;
+ MatchedStyleDeclarationCache m_matchedStyleDeclarationCache;
+
+ // A buffer used to hold the set of matched rules for an element, and a temporary buffer used for
+ // merge sorting.
+ Vector<const RuleData*, 32> m_matchedRules;
+
+ RefPtr<CSSRuleList> m_ruleList;
+
+ HashSet<int> m_pendingImageProperties; // Hash of CSSPropertyIDs
+
+ OwnPtr<MediaQueryEvaluator> m_medium;
+ RefPtr<RenderStyle> m_rootDefaultStyle;
+
+ PseudoId m_dynamicPseudo;
+
+ SelectorChecker m_checker;
+
+ RefPtr<RenderStyle> m_style;
+ RenderStyle* m_parentStyle;
+ RenderStyle* m_rootElementStyle;
+ Element* m_element;
+ StyledElement* m_styledElement;
+ EInsideLink m_elementLinkState;
+ ContainerNode* m_parentNode;
+ CSSValue* m_lineHeightValue;
+ bool m_fontDirty;
+ bool m_matchAuthorAndUserStyles;
+ bool m_sameOriginOnly;
+
+ RefPtr<CSSFontSelector> m_fontSelector;
+ Vector<MediaQueryResult*> m_viewportDependentMediaQueryResults;
+
+ bool m_applyPropertyToRegularStyle;
+ bool m_applyPropertyToVisitedLinkStyle;
+ const CSSStyleApplyProperty& m_applyProperty;
+
+#if ENABLE(CSS_SHADERS)
+ bool m_hasPendingShaders;
+#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&);
+};
+
+} // namespace WebCore
+
+#endif // CSSStyleSelector_h
diff --git a/Source/WebCore/css/CSSStyleSheet.cpp b/Source/WebCore/css/CSSStyleSheet.cpp
new file mode 100644
index 000000000..707ca4c3c
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleSheet.cpp
@@ -0,0 +1,314 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2007 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 "CSSStyleSheet.h"
+
+#include "CSSFontFaceRule.h"
+#include "CSSImportRule.h"
+#include "CSSNamespace.h"
+#include "CSSParser.h"
+#include "CSSRuleList.h"
+#include "CSSStyleRule.h"
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "HTMLNames.h"
+#include "Node.h"
+#include "SVGNames.h"
+#include "SecurityOrigin.h"
+#include "TextEncoding.h"
+#include <wtf/Deque.h>
+
+namespace WebCore {
+
+#if !ASSERT_DISABLED
+static bool isAcceptableCSSStyleSheetParent(Node* parentNode)
+{
+ // Only these nodes can be parents of StyleSheets, and they need to call clearOwnerNode() when moved out of document.
+ return !parentNode
+ || parentNode->isDocumentNode()
+ || parentNode->hasTagName(HTMLNames::linkTag)
+ || parentNode->hasTagName(HTMLNames::styleTag)
+#if ENABLE(SVG)
+ || parentNode->hasTagName(SVGNames::styleTag)
+#endif
+ || parentNode->nodeType() == Node::PROCESSING_INSTRUCTION_NODE;
+}
+#endif
+
+CSSStyleSheet::CSSStyleSheet(Node* parentNode, const String& href, const KURL& baseURL, const String& charset)
+ : StyleSheet(parentNode, href, baseURL)
+ , m_charset(charset)
+ , m_loadCompleted(false)
+ , m_strictParsing(false)
+ , m_isUserStyleSheet(false)
+ , m_hasSyntacticallyValidCSSHeader(true)
+{
+ ASSERT(isAcceptableCSSStyleSheetParent(parentNode));
+}
+
+CSSStyleSheet::CSSStyleSheet(CSSImportRule* ownerRule, const String& href, const KURL& baseURL, const String& charset)
+ : StyleSheet(ownerRule, href, baseURL)
+ , m_charset(charset)
+ , m_loadCompleted(false)
+ , m_strictParsing(!ownerRule || ownerRule->useStrictParsing())
+ , m_hasSyntacticallyValidCSSHeader(true)
+{
+ CSSStyleSheet* parentSheet = ownerRule ? ownerRule->parentStyleSheet() : 0;
+ m_isUserStyleSheet = parentSheet ? parentSheet->isUserStyleSheet() : false;
+}
+
+CSSStyleSheet::~CSSStyleSheet()
+{
+ // For style rules outside the document, .parentStyleSheet can become null even if the style rule
+ // is still observable from JavaScript. This matches the behavior of .parentNode for nodes, but
+ // it's not ideal because it makes the CSSOM's behavior depend on the timing of garbage collection.
+ for (unsigned i = 0; i < m_children.size(); ++i) {
+ ASSERT(m_children.at(i)->parentStyleSheet() == this);
+ m_children.at(i)->setParentStyleSheet(0);
+ }
+}
+
+void CSSStyleSheet::append(PassRefPtr<CSSRule> child)
+{
+ CSSRule* c = child.get();
+ m_children.append(child);
+ if (c->isImportRule())
+ static_cast<CSSImportRule*>(c)->requestStyleSheet();
+}
+
+void CSSStyleSheet::remove(unsigned index)
+{
+ m_children.remove(index);
+}
+
+unsigned CSSStyleSheet::insertRule(const String& rule, unsigned index, ExceptionCode& ec)
+{
+ ec = 0;
+ if (index > m_children.size()) {
+ ec = INDEX_SIZE_ERR;
+ return 0;
+ }
+ CSSParser p(useStrictParsing());
+ RefPtr<CSSRule> r = p.parseRule(this, rule);
+
+ if (!r) {
+ ec = SYNTAX_ERR;
+ return 0;
+ }
+
+ // Throw a HIERARCHY_REQUEST_ERR exception if the rule cannot be inserted at the specified index. The best
+ // example of this is an @import rule inserted after regular rules.
+ if (index > 0) {
+ if (r->isImportRule()) {
+ // Check all the rules that come before this one to make sure they are only @charset and @import rules.
+ for (unsigned i = 0; i < index; ++i) {
+ if (!m_children.at(i)->isCharsetRule() && !m_children.at(i)->isImportRule()) {
+ ec = HIERARCHY_REQUEST_ERR;
+ return 0;
+ }
+ }
+ } else if (r->isCharsetRule()) {
+ // The @charset rule has to come first and there can be only one.
+ ec = HIERARCHY_REQUEST_ERR;
+ return 0;
+ }
+ }
+
+ CSSRule* c = r.get();
+ m_children.insert(index, r.release());
+ if (c->isImportRule())
+ static_cast<CSSImportRule*>(c)->requestStyleSheet();
+
+ styleSheetChanged();
+
+ return index;
+}
+
+int CSSStyleSheet::addRule(const String& selector, const String& style, int index, ExceptionCode& ec)
+{
+ insertRule(selector + " { " + style + " }", index, ec);
+
+ // As per Microsoft documentation, always return -1.
+ return -1;
+}
+
+int CSSStyleSheet::addRule(const String& selector, const String& style, ExceptionCode& ec)
+{
+ return addRule(selector, style, m_children.size(), ec);
+}
+
+PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules(bool omitCharsetRules)
+{
+ KURL url = finalURL();
+ Document* document = findDocument();
+ if (!url.isEmpty() && document && !document->securityOrigin()->canRequest(url))
+ return 0;
+ return CSSRuleList::create(this, omitCharsetRules);
+}
+
+void CSSStyleSheet::deleteRule(unsigned index, ExceptionCode& ec)
+{
+ if (index >= m_children.size()) {
+ ec = INDEX_SIZE_ERR;
+ return;
+ }
+
+ ec = 0;
+ m_children.at(index)->setParentStyleSheet(0);
+ m_children.remove(index);
+ styleSheetChanged();
+}
+
+void CSSStyleSheet::addNamespace(CSSParser* p, const AtomicString& prefix, const AtomicString& uri)
+{
+ if (uri.isNull())
+ return;
+
+ m_namespaces = adoptPtr(new CSSNamespace(prefix, uri, m_namespaces.release()));
+
+ if (prefix.isEmpty())
+ // Set the default namespace on the parser so that selectors that omit namespace info will
+ // be able to pick it up easily.
+ p->m_defaultNamespace = uri;
+}
+
+const AtomicString& CSSStyleSheet::determineNamespace(const AtomicString& prefix)
+{
+ if (prefix.isNull())
+ return nullAtom; // No namespace. If an element/attribute has a namespace, we won't match it.
+ if (prefix == starAtom)
+ return starAtom; // We'll match any namespace.
+ if (m_namespaces) {
+ if (CSSNamespace* namespaceForPrefix = m_namespaces->namespaceForPrefix(prefix))
+ return namespaceForPrefix->uri;
+ }
+ return nullAtom; // Assume we won't match any namespaces.
+}
+
+bool CSSStyleSheet::parseString(const String &string, bool strict)
+{
+ return parseStringAtLine(string, strict, 0);
+}
+
+bool CSSStyleSheet::parseStringAtLine(const String& string, bool strict, int startLineNumber)
+{
+ setStrictParsing(strict);
+ CSSParser p(strict);
+ p.parseSheet(this, string, startLineNumber);
+ return true;
+}
+
+bool CSSStyleSheet::isLoading()
+{
+ for (unsigned i = 0; i < m_children.size(); ++i) {
+ CSSRule* rule = m_children.at(i).get();
+ if (rule->isImportRule() && static_cast<CSSImportRule*>(rule)->isLoading())
+ return true;
+ }
+ return false;
+}
+
+void CSSStyleSheet::checkLoaded()
+{
+ if (isLoading())
+ return;
+
+ // Avoid |this| being deleted by scripts that run via
+ // ScriptableDocumentParser::executeScriptsWaitingForStylesheets().
+ // See <rdar://problem/6622300>.
+ RefPtr<CSSStyleSheet> protector(this);
+ if (CSSStyleSheet* styleSheet = parentStyleSheet())
+ styleSheet->checkLoaded();
+ m_loadCompleted = ownerNode() ? ownerNode()->sheetLoaded() : true;
+}
+
+void CSSStyleSheet::startLoadingDynamicSheet()
+{
+ if (Node* owner = ownerNode())
+ owner->startLoadingDynamicSheet();
+}
+
+Node* CSSStyleSheet::findStyleSheetOwnerNode() const
+{
+ for (const CSSStyleSheet* sheet = this; sheet; sheet = sheet->parentStyleSheet()) {
+ if (Node* ownerNode = sheet->ownerNode())
+ return ownerNode;
+ }
+ return 0;
+}
+
+Document* CSSStyleSheet::findDocument()
+{
+ Node* ownerNode = findStyleSheetOwnerNode();
+
+ return ownerNode ? ownerNode->document() : 0;
+}
+
+void CSSStyleSheet::styleSheetChanged()
+{
+ CSSStyleSheet* rootSheet = this;
+ while (CSSStyleSheet* parent = rootSheet->parentStyleSheet())
+ rootSheet = parent;
+
+ /* FIXME: We don't need to do everything updateStyleSelector does,
+ * basically we just need to recreate the document's selector with the
+ * already existing style sheets.
+ */
+ if (Document* documentToUpdate = rootSheet->findDocument())
+ documentToUpdate->styleSelectorChanged(DeferRecalcStyle);
+}
+
+KURL CSSStyleSheet::completeURL(const String& url) const
+{
+ // Always return a null URL when passed a null string.
+ // FIXME: Should we change the KURL constructor to have this behavior?
+ // See also Document::completeURL(const String&)
+ if (url.isNull())
+ return KURL();
+ if (m_charset.isEmpty())
+ return KURL(baseURL(), url);
+ const TextEncoding encoding = TextEncoding(m_charset);
+ return KURL(baseURL(), url, encoding);
+}
+
+void CSSStyleSheet::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
+{
+ Deque<CSSStyleSheet*> styleSheetQueue;
+ styleSheetQueue.append(this);
+
+ while (!styleSheetQueue.isEmpty()) {
+ CSSStyleSheet* styleSheet = styleSheetQueue.takeFirst();
+
+ for (unsigned i = 0; i < styleSheet->m_children.size(); ++i) {
+ CSSRule* rule = styleSheet->m_children.at(i).get();
+ if (rule->isImportRule()) {
+ if (CSSStyleSheet* ruleStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet())
+ styleSheetQueue.append(ruleStyleSheet);
+ static_cast<CSSImportRule*>(rule)->addSubresourceStyleURLs(urls);
+ } else if (rule->isFontFaceRule())
+ static_cast<CSSFontFaceRule*>(rule)->addSubresourceStyleURLs(urls);
+ else if (rule->isStyleRule() || rule->isPageRule())
+ static_cast<CSSStyleRule*>(rule)->addSubresourceStyleURLs(urls);
+ }
+ }
+}
+
+}
diff --git a/Source/WebCore/css/CSSStyleSheet.h b/Source/WebCore/css/CSSStyleSheet.h
new file mode 100644
index 000000000..b027365f2
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleSheet.h
@@ -0,0 +1,135 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 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 CSSStyleSheet_h
+#define CSSStyleSheet_h
+
+#include "CSSRuleList.h"
+#include "StyleSheet.h"
+
+namespace WebCore {
+
+struct CSSNamespace;
+class CSSParser;
+class CSSRule;
+class CachedResourceLoader;
+class Document;
+
+typedef int ExceptionCode;
+
+class CSSStyleSheet : public StyleSheet {
+public:
+ static PassRefPtr<CSSStyleSheet> create()
+ {
+ return adoptRef(new CSSStyleSheet(static_cast<CSSImportRule*>(0), String(), KURL(), String()));
+ }
+ static PassRefPtr<CSSStyleSheet> create(Node* ownerNode)
+ {
+ return adoptRef(new CSSStyleSheet(ownerNode, String(), KURL(), String()));
+ }
+ static PassRefPtr<CSSStyleSheet> create(Node* ownerNode, const String& originalURL, const KURL& finalURL, const String& charset)
+ {
+ return adoptRef(new CSSStyleSheet(ownerNode, originalURL, finalURL, charset));
+ }
+ static PassRefPtr<CSSStyleSheet> create(CSSImportRule* ownerRule, const String& originalURL, const KURL& finalURL, const String& charset)
+ {
+ return adoptRef(new CSSStyleSheet(ownerRule, originalURL, finalURL, charset));
+ }
+ static PassRefPtr<CSSStyleSheet> createInline(Node* ownerNode, const KURL& finalURL)
+ {
+ return adoptRef(new CSSStyleSheet(ownerNode, finalURL.string(), finalURL, String()));
+ }
+
+ virtual ~CSSStyleSheet();
+
+ CSSStyleSheet* parentStyleSheet() const
+ {
+ StyleSheet* parentSheet = StyleSheet::parentStyleSheet();
+ ASSERT(!parentSheet || parentSheet->isCSSStyleSheet());
+ return static_cast<CSSStyleSheet*>(parentSheet);
+ }
+
+ PassRefPtr<CSSRuleList> cssRules(bool omitCharsetRules = false);
+ unsigned insertRule(const String& rule, unsigned index, ExceptionCode&);
+ void deleteRule(unsigned index, ExceptionCode&);
+
+ // IE Extensions
+ PassRefPtr<CSSRuleList> rules() { return cssRules(true); }
+ int addRule(const String& selector, const String& style, int index, ExceptionCode&);
+ int addRule(const String& selector, const String& style, ExceptionCode&);
+ void removeRule(unsigned index, ExceptionCode& ec) { deleteRule(index, ec); }
+
+ void addNamespace(CSSParser*, const AtomicString& prefix, const AtomicString& uri);
+ const AtomicString& determineNamespace(const AtomicString& prefix);
+
+ void styleSheetChanged();
+
+ virtual bool parseString(const String&, bool strict = true);
+
+ bool parseStringAtLine(const String&, bool strict, int startLineNumber);
+
+ virtual bool isLoading();
+
+ void checkLoaded();
+ void startLoadingDynamicSheet();
+
+ Node* findStyleSheetOwnerNode() const;
+ Document* findDocument();
+
+ const String& charset() const { return m_charset; }
+
+ bool loadCompleted() const { return m_loadCompleted; }
+
+ KURL completeURL(const String& url) const;
+ void addSubresourceStyleURLs(ListHashSet<KURL>&);
+
+ void setStrictParsing(bool b) { m_strictParsing = b; }
+ bool useStrictParsing() const { return m_strictParsing; }
+
+ void setIsUserStyleSheet(bool b) { m_isUserStyleSheet = b; }
+ bool isUserStyleSheet() const { return m_isUserStyleSheet; }
+ void setHasSyntacticallyValidCSSHeader(bool b) { m_hasSyntacticallyValidCSSHeader = b; }
+ bool hasSyntacticallyValidCSSHeader() const { return m_hasSyntacticallyValidCSSHeader; }
+
+ void append(PassRefPtr<CSSRule>);
+ void remove(unsigned index);
+
+ unsigned length() const { return m_children.size(); }
+ CSSRule* item(unsigned index) { return index < length() ? m_children.at(index).get() : 0; }
+
+private:
+ CSSStyleSheet(Node* ownerNode, const String& originalURL, const KURL& finalURL, const String& charset);
+ CSSStyleSheet(CSSImportRule* ownerRule, const String& originalURL, const KURL& finalURL, const String& charset);
+
+ virtual bool isCSSStyleSheet() const { return true; }
+ virtual String type() const { return "text/css"; }
+
+ Vector<RefPtr<CSSRule> > m_children;
+ OwnPtr<CSSNamespace> m_namespaces;
+ String m_charset;
+ bool m_loadCompleted : 1;
+ bool m_strictParsing : 1;
+ bool m_isUserStyleSheet : 1;
+ bool m_hasSyntacticallyValidCSSHeader : 1;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/CSSStyleSheet.idl b/Source/WebCore/css/CSSStyleSheet.idl
new file mode 100644
index 000000000..34978275e
--- /dev/null
+++ b/Source/WebCore/css/CSSStyleSheet.idl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface CSSStyleSheet : StyleSheet {
+ readonly attribute CSSRule ownerRule;
+ readonly attribute CSSRuleList cssRules;
+
+ [OldStyleObjC] unsigned long insertRule(in [Optional=CallWithDefaultValue] DOMString rule,
+ in [Optional=CallWithDefaultValue] unsigned long index)
+ raises(DOMException);
+ void deleteRule(in [Optional=CallWithDefaultValue] unsigned long index)
+ raises(DOMException);
+
+ // IE Extensions
+ readonly attribute CSSRuleList rules;
+
+ long addRule(in [Optional=CallWithDefaultValue] DOMString selector,
+ in [Optional=CallWithDefaultValue] DOMString style,
+ in [Optional] unsigned long index)
+ raises(DOMException);
+ void removeRule(in [Optional=CallWithDefaultValue] unsigned long index)
+ raises(DOMException);
+ };
+
+}
diff --git a/Source/WebCore/css/CSSTimingFunctionValue.cpp b/Source/WebCore/css/CSSTimingFunctionValue.cpp
new file mode 100644
index 000000000..dcf7bb29b
--- /dev/null
+++ b/Source/WebCore/css/CSSTimingFunctionValue.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007 Apple Computer, 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 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.
+ */
+
+#include "config.h"
+#include "CSSTimingFunctionValue.h"
+
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String CSSLinearTimingFunctionValue::customCssText() const
+{
+ return "linear";
+}
+
+String CSSCubicBezierTimingFunctionValue::customCssText() const
+{
+ String text("cubic-bezier(");
+ text += String::number(m_x1);
+ text += ", ";
+ text += String::number(m_y1);
+ text += ", ";
+ text += String::number(m_x2);
+ text += ", ";
+ text += String::number(m_y2);
+ text += ")";
+ return text;
+}
+
+String CSSStepsTimingFunctionValue::customCssText() const
+{
+ String text("steps(");
+ text += String::number(m_steps);
+ text += ", ";
+ text += m_stepAtStart ? "start" : "end";
+ text += ")";
+ return text;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSTimingFunctionValue.h b/Source/WebCore/css/CSSTimingFunctionValue.h
new file mode 100644
index 000000000..9958a8c21
--- /dev/null
+++ b/Source/WebCore/css/CSSTimingFunctionValue.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2007, 2008 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 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 CSSTimingFunctionValue_h
+#define CSSTimingFunctionValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class CSSTimingFunctionValue : public CSSValue {
+public:
+ bool isLinearTimingFunctionValue() const { return classType() == LinearTimingFunctionClass; }
+ bool isCubicBezierTimingFunctionValue() const { return classType() == CubicBezierTimingFunctionClass; }
+ bool isStepsTimingFunctionValue() const { return classType() == StepsTimingFunctionClass; }
+
+protected:
+ CSSTimingFunctionValue(ClassType classType)
+ : CSSValue(classType)
+ {
+ }
+};
+
+class CSSLinearTimingFunctionValue : public CSSTimingFunctionValue {
+public:
+ static PassRefPtr<CSSLinearTimingFunctionValue> create()
+ {
+ return adoptRef(new CSSLinearTimingFunctionValue);
+ }
+
+ String customCssText() const;
+
+private:
+ CSSLinearTimingFunctionValue()
+ : CSSTimingFunctionValue(LinearTimingFunctionClass)
+ {
+ }
+};
+
+class CSSCubicBezierTimingFunctionValue : public CSSTimingFunctionValue {
+public:
+ static PassRefPtr<CSSCubicBezierTimingFunctionValue> create(double x1, double y1, double x2, double y2)
+ {
+ return adoptRef(new CSSCubicBezierTimingFunctionValue(x1, y1, x2, y2));
+ }
+
+ String customCssText() const;
+
+ double x1() const { return m_x1; }
+ double y1() const { return m_y1; }
+ double x2() const { return m_x2; }
+ double y2() const { return m_y2; }
+
+private:
+ CSSCubicBezierTimingFunctionValue(double x1, double y1, double x2, double y2)
+ : CSSTimingFunctionValue(CubicBezierTimingFunctionClass)
+ , m_x1(x1)
+ , m_y1(y1)
+ , m_x2(x2)
+ , m_y2(y2)
+ {
+ }
+
+ double m_x1;
+ double m_y1;
+ double m_x2;
+ double m_y2;
+};
+
+class CSSStepsTimingFunctionValue : public CSSTimingFunctionValue {
+public:
+ static PassRefPtr<CSSStepsTimingFunctionValue> create(int steps, bool stepAtStart)
+ {
+ return adoptRef(new CSSStepsTimingFunctionValue(steps, stepAtStart));
+ }
+
+ int numberOfSteps() const { return m_steps; }
+ bool stepAtStart() const { return m_stepAtStart; }
+
+ String customCssText() const;
+
+private:
+ CSSStepsTimingFunctionValue(int steps, bool stepAtStart)
+ : CSSTimingFunctionValue(StepsTimingFunctionClass)
+ , m_steps(steps)
+ , m_stepAtStart(stepAtStart)
+ {
+ }
+
+ int m_steps;
+ bool m_stepAtStart;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/CSSUnicodeRangeValue.cpp b/Source/WebCore/css/CSSUnicodeRangeValue.cpp
new file mode 100644
index 000000000..2c2c44d27
--- /dev/null
+++ b/Source/WebCore/css/CSSUnicodeRangeValue.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 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 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.
+ */
+
+#include "config.h"
+#include "CSSUnicodeRangeValue.h"
+
+#include "PlatformString.h"
+
+namespace WebCore {
+
+String CSSUnicodeRangeValue::customCssText() const
+{
+ String result;
+ // FIXME: Implement.
+ return result;
+}
+
+}
diff --git a/Source/WebCore/css/CSSUnicodeRangeValue.h b/Source/WebCore/css/CSSUnicodeRangeValue.h
new file mode 100644
index 000000000..4fe1db77c
--- /dev/null
+++ b/Source/WebCore/css/CSSUnicodeRangeValue.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 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 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 CSSUnicodeRangeValue_h
+#define CSSUnicodeRangeValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class CSSUnicodeRangeValue : public CSSValue {
+public:
+ static PassRefPtr<CSSUnicodeRangeValue> create(UChar32 from, UChar32 to)
+ {
+ return adoptRef(new CSSUnicodeRangeValue(from, to));
+ }
+
+ UChar32 from() const { return m_from; }
+ UChar32 to() const { return m_to; }
+
+ String customCssText() const;
+
+private:
+ CSSUnicodeRangeValue(UChar32 from, UChar32 to)
+ : CSSValue(UnicodeRangeClass)
+ , m_from(from)
+ , m_to(to)
+ {
+ }
+
+ UChar32 m_from;
+ UChar32 m_to;
+};
+
+} // namespace WebCore
+
+#endif // CSSUnicodeRangeValue_h
diff --git a/Source/WebCore/css/CSSUnknownRule.h b/Source/WebCore/css/CSSUnknownRule.h
new file mode 100644
index 000000000..9f746ba0e
--- /dev/null
+++ b/Source/WebCore/css/CSSUnknownRule.h
@@ -0,0 +1,36 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2002, 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 CSSUnknownRule_h
+#define CSSUnknownRule_h
+
+#include "CSSRule.h"
+
+namespace WebCore {
+
+class CSSUnknownRule : public CSSRule {
+public:
+ CSSUnknownRule() : CSSRule(0, CSSRule::UNKNOWN_RULE) { }
+};
+
+} // namespace WebCore
+
+#endif // CSSUnknownRule_h
diff --git a/Source/WebCore/css/CSSUnknownRule.idl b/Source/WebCore/css/CSSUnknownRule.idl
new file mode 100644
index 000000000..b62ceb873
--- /dev/null
+++ b/Source/WebCore/css/CSSUnknownRule.idl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface [
+ OmitConstructor
+ ] CSSUnknownRule : CSSRule {
+ };
+
+}
diff --git a/Source/WebCore/css/CSSValue.cpp b/Source/WebCore/css/CSSValue.cpp
new file mode 100644
index 000000000..0e83c0818
--- /dev/null
+++ b/Source/WebCore/css/CSSValue.cpp
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ *
+ */
+
+#include "config.h"
+#include "CSSValue.h"
+
+#include "CSSAspectRatioValue.h"
+#include "CSSBorderImageValue.h"
+#include "CSSBorderImageSliceValue.h"
+#include "CSSCanvasValue.h"
+#include "CSSCrossfadeValue.h"
+#include "CSSCursorImageValue.h"
+#include "CSSFlexValue.h"
+#include "CSSFontFaceSrcValue.h"
+#include "CSSFunctionValue.h"
+#include "CSSGradientValue.h"
+#include "CSSImageGeneratorValue.h"
+#include "CSSImageValue.h"
+#include "CSSInheritedValue.h"
+#include "CSSInitialValue.h"
+#include "CSSLineBoxContainValue.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSReflectValue.h"
+#include "CSSTimingFunctionValue.h"
+#include "CSSUnicodeRangeValue.h"
+#include "CSSValueList.h"
+#include "FontValue.h"
+#include "FontFamilyValue.h"
+#include "FontFeatureValue.h"
+#include "ShadowValue.h"
+#include "SVGColor.h"
+#include "SVGPaint.h"
+#include "WebKitCSSFilterValue.h"
+#include "WebKitCSSShaderValue.h"
+#include "WebKitCSSTransformValue.h"
+
+namespace WebCore {
+
+class SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> {
+ unsigned char bitfields[2];
+};
+
+COMPILE_ASSERT(sizeof(CSSValue) == sizeof(SameSizeAsCSSValue), CSS_value_should_stay_small);
+
+CSSValue::Type CSSValue::cssValueType() const
+{
+ if (isInheritedValue())
+ return CSS_INHERIT;
+ if (isPrimitiveValue())
+ return CSS_PRIMITIVE_VALUE;
+ if (isValueList())
+ return CSS_VALUE_LIST;
+ if (isInitialValue())
+ return CSS_INITIAL;
+ return CSS_CUSTOM;
+}
+
+void CSSValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
+{
+ if (isPrimitiveValue())
+ 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)
+ static_cast<CSSReflectValue*>(this)->addSubresourceStyleURLs(urls, styleSheet);
+}
+
+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:
+ return static_cast<const CSSCanvasValue*>(this)->customCssText();
+ case CursorImageClass:
+ return static_cast<const CSSCursorImageValue*>(this)->customCssText();
+ case FontClass:
+ return static_cast<const FontValue*>(this)->customCssText();
+ case FontFaceSrcClass:
+ return static_cast<const CSSFontFaceSrcValue*>(this)->customCssText();
+ case FontFamilyClass:
+ return static_cast<const FontFamilyValue*>(this)->customCssText();
+ case FontFeatureClass:
+ return static_cast<const FontFeatureValue*>(this)->customCssText();
+ case FunctionClass:
+ return static_cast<const CSSFunctionValue*>(this)->customCssText();
+ case LinearGradientClass:
+ return static_cast<const CSSLinearGradientValue*>(this)->customCssText();
+ case RadialGradientClass:
+ return static_cast<const CSSRadialGradientValue*>(this)->customCssText();
+ case CrossfadeClass:
+ return static_cast<const CSSCrossfadeValue*>(this)->customCssText();
+ case ImageClass:
+ return static_cast<const CSSImageValue*>(this)->customCssText();
+ case InheritedClass:
+ return static_cast<const CSSInheritedValue*>(this)->customCssText();
+ case InitialClass:
+ return static_cast<const CSSInitialValue*>(this)->customCssText();
+ case PrimitiveClass:
+ return static_cast<const CSSPrimitiveValue*>(this)->customCssText();
+ case ReflectClass:
+ return static_cast<const CSSReflectValue*>(this)->customCssText();
+ case ShadowClass:
+ return static_cast<const ShadowValue*>(this)->customCssText();
+ case LinearTimingFunctionClass:
+ return static_cast<const CSSLinearTimingFunctionValue*>(this)->customCssText();
+ case CubicBezierTimingFunctionClass:
+ return static_cast<const CSSCubicBezierTimingFunctionValue*>(this)->customCssText();
+ case StepsTimingFunctionClass:
+ return static_cast<const CSSStepsTimingFunctionValue*>(this)->customCssText();
+ case UnicodeRangeClass:
+ return static_cast<const CSSUnicodeRangeValue*>(this)->customCssText();
+ case ValueListClass:
+ return static_cast<const CSSValueList*>(this)->customCssText();
+ case WebKitCSSTransformClass:
+ return static_cast<const WebKitCSSTransformValue*>(this)->customCssText();
+ case LineBoxContainClass:
+ return static_cast<const CSSLineBoxContainValue*>(this)->customCssText();
+ case FlexClass:
+ return static_cast<const CSSFlexValue*>(this)->customCssText();
+#if ENABLE(CSS_FILTERS)
+ case WebKitCSSFilterClass:
+ return static_cast<const WebKitCSSFilterValue*>(this)->customCssText();
+#if ENABLE(CSS_SHADERS)
+ case WebKitCSSShaderClass:
+ return static_cast<const WebKitCSSShaderValue*>(this)->customCssText();
+#endif
+#endif
+#if ENABLE(SVG)
+ case SVGColorClass:
+ return static_cast<const SVGColor*>(this)->customCssText();
+ case SVGPaintClass:
+ return static_cast<const SVGPaint*>(this)->customCssText();
+#endif
+ }
+ ASSERT_NOT_REACHED();
+ return String();
+}
+
+void CSSValue::destroy()
+{
+ switch (classType()) {
+ case AspectRatioClass:
+ delete static_cast<CSSAspectRatioValue*>(this);
+ return;
+ case BorderImageClass:
+ delete static_cast<CSSBorderImageValue*>(this);
+ return;
+ case BorderImageSliceClass:
+ delete static_cast<CSSBorderImageSliceValue*>(this);
+ return;
+ case CanvasClass:
+ delete static_cast<CSSCanvasValue*>(this);
+ return;
+ case CursorImageClass:
+ delete static_cast<CSSCursorImageValue*>(this);
+ return;
+ case FontClass:
+ delete static_cast<FontValue*>(this);
+ return;
+ case FontFaceSrcClass:
+ delete static_cast<CSSFontFaceSrcValue*>(this);
+ return;
+ case FontFamilyClass:
+ delete static_cast<FontFamilyValue*>(this);
+ return;
+ case FontFeatureClass:
+ delete static_cast<FontFeatureValue*>(this);
+ return;
+ case FunctionClass:
+ delete static_cast<CSSFunctionValue*>(this);
+ return;
+ case LinearGradientClass:
+ delete static_cast<CSSLinearGradientValue*>(this);
+ return;
+ case RadialGradientClass:
+ delete static_cast<CSSRadialGradientValue*>(this);
+ return;
+ case CrossfadeClass:
+ delete static_cast<CSSCrossfadeValue*>(this);
+ return;
+ case ImageClass:
+ delete static_cast<CSSImageValue*>(this);
+ return;
+ case InheritedClass:
+ delete static_cast<CSSInheritedValue*>(this);
+ return;
+ case InitialClass:
+ delete static_cast<CSSInitialValue*>(this);
+ return;
+ case PrimitiveClass:
+ delete static_cast<CSSPrimitiveValue*>(this);
+ return;
+ case ReflectClass:
+ delete static_cast<CSSReflectValue*>(this);
+ return;
+ case ShadowClass:
+ delete static_cast<ShadowValue*>(this);
+ return;
+ case LinearTimingFunctionClass:
+ delete static_cast<CSSLinearTimingFunctionValue*>(this);
+ return;
+ case CubicBezierTimingFunctionClass:
+ delete static_cast<CSSCubicBezierTimingFunctionValue*>(this);
+ return;
+ case StepsTimingFunctionClass:
+ delete static_cast<CSSStepsTimingFunctionValue*>(this);
+ return;
+ case UnicodeRangeClass:
+ delete static_cast<CSSUnicodeRangeValue*>(this);
+ return;
+ case ValueListClass:
+ delete static_cast<CSSValueList*>(this);
+ return;
+ case WebKitCSSTransformClass:
+ delete static_cast<WebKitCSSTransformValue*>(this);
+ return;
+ case LineBoxContainClass:
+ delete static_cast<CSSLineBoxContainValue*>(this);
+ return;
+ case FlexClass:
+ delete static_cast<CSSFlexValue*>(this);
+ return;
+#if ENABLE(CSS_FILTERS)
+ case WebKitCSSFilterClass:
+ delete static_cast<WebKitCSSFilterValue*>(this);
+ return;
+#if ENABLE(CSS_SHADERS)
+ case WebKitCSSShaderClass:
+ delete static_cast<WebKitCSSShaderValue*>(this);
+ return;
+#endif
+#endif
+#if ENABLE(SVG)
+ case SVGColorClass:
+ delete static_cast<SVGColor*>(this);
+ return;
+ case SVGPaintClass:
+ delete static_cast<SVGPaint*>(this);
+ return;
+#endif
+ }
+ ASSERT_NOT_REACHED();
+}
+
+}
diff --git a/Source/WebCore/css/CSSValue.h b/Source/WebCore/css/CSSValue.h
new file mode 100644
index 000000000..ce95369ab
--- /dev/null
+++ b/Source/WebCore/css/CSSValue.h
@@ -0,0 +1,189 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 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 CSSValue_h
+#define CSSValue_h
+
+#include "KURLHash.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSStyleSheet;
+
+typedef int ExceptionCode;
+
+class CSSValue : public RefCounted<CSSValue> {
+public:
+ enum Type {
+ CSS_INHERIT = 0,
+ CSS_PRIMITIVE_VALUE = 1,
+ CSS_VALUE_LIST = 2,
+ CSS_CUSTOM = 3,
+ CSS_INITIAL = 4
+
+ };
+
+ // Override RefCounted's deref() to ensure operator delete is called on
+ // the appropriate subclass type.
+ void deref()
+ {
+ if (derefBase())
+ destroy();
+ }
+
+ Type cssValueType() const;
+
+ String cssText() const;
+ void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented.
+
+ bool isPrimitiveValue() const { return m_classType <= PrimitiveClass; }
+ 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; }
+ bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
+ bool isFontValue() const { return m_classType == FontClass; }
+ bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; }
+ bool isImageValue() const { return m_classType == ImageClass || m_classType == CursorImageClass; }
+ bool isImplicitInitialValue() const { return m_classType == InitialClass && m_isImplicitInitialValue; }
+ bool isInheritedValue() const { return m_classType == InheritedClass; }
+ bool isInitialValue() const { return m_classType == InitialClass; }
+ bool isReflectValue() const { return m_classType == ReflectClass; }
+ bool isShadowValue() const { return m_classType == ShadowClass; }
+ bool isTimingFunctionValue() const { return m_classType >= CubicBezierTimingFunctionClass && m_classType <= StepsTimingFunctionClass; }
+ bool isWebKitCSSTransformValue() const { return m_classType == WebKitCSSTransformClass; }
+ bool isCSSLineBoxContainValue() const { return m_classType == LineBoxContainClass; }
+ bool isFlexValue() const { return m_classType == FlexClass; }
+#if ENABLE(CSS_FILTERS)
+ bool isWebKitCSSFilterValue() const { return m_classType == WebKitCSSFilterClass; }
+#if ENABLE(CSS_SHADERS)
+ bool isWebKitCSSShaderValue() const { return m_classType == WebKitCSSShaderClass; }
+#endif
+#endif // ENABLE(CSS_FILTERS)
+#if ENABLE(SVG)
+ bool isSVGColor() const { return m_classType == SVGColorClass || m_classType == SVGPaintClass; }
+ bool isSVGPaint() const { return m_classType == SVGPaintClass; }
+#endif
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
+
+protected:
+
+ static const size_t ClassTypeBits = 5;
+ enum ClassType {
+ // Primitive class types must appear before PrimitiveClass.
+ ImageClass,
+ CursorImageClass,
+ FontFamilyClass,
+ PrimitiveClass,
+
+ // Image generator classes.
+ CanvasClass,
+ CrossfadeClass,
+ LinearGradientClass,
+ RadialGradientClass,
+
+ // Timing function classes.
+ CubicBezierTimingFunctionClass,
+ LinearTimingFunctionClass,
+ StepsTimingFunctionClass,
+
+ // Other class types.
+ AspectRatioClass,
+ BorderImageClass,
+ BorderImageSliceClass,
+ FontFeatureClass,
+ FontClass,
+ FontFaceSrcClass,
+ FunctionClass,
+
+ InheritedClass,
+ InitialClass,
+
+ ReflectClass,
+ ShadowClass,
+ UnicodeRangeClass,
+ LineBoxContainClass,
+ FlexClass,
+#if ENABLE(CSS_FILTERS) && ENABLE(CSS_SHADERS)
+ WebKitCSSShaderClass,
+#endif
+#if ENABLE(SVG)
+ SVGColorClass,
+ SVGPaintClass,
+#endif
+
+ // List class types must appear after ValueListClass.
+ ValueListClass,
+#if ENABLE(CSS_FILTERS)
+ WebKitCSSFilterClass,
+#endif
+ WebKitCSSTransformClass,
+ // Do not append non-list class types here.
+ };
+
+ ClassType classType() const { return static_cast<ClassType>(m_classType); }
+
+ explicit CSSValue(ClassType classType)
+ : m_primitiveUnitType(0)
+ , m_hasCachedCSSText(false)
+ , m_isQuirkValue(false)
+ , m_isImplicitInitialValue(false)
+ , m_isSpaceSeparatedValueList(false)
+ , m_classType(classType)
+ {
+ }
+
+ // NOTE: This class is non-virtual for memory and performance reasons.
+ // Don't go making it virtual again unless you know exactly what you're doing!
+
+ ~CSSValue() { }
+
+private:
+ void destroy();
+
+protected:
+ // The bits in this section are only used by specific subclasses but kept here
+ // to maximize struct packing.
+
+ // CSSPrimitiveValue bits:
+ unsigned char m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes
+ mutable bool m_hasCachedCSSText : 1;
+ bool m_isQuirkValue : 1;
+
+ // CSSInitialValue bits:
+ bool m_isImplicitInitialValue : 1;
+
+ // CSSValueList bits:
+ bool m_isSpaceSeparatedValueList : 1;
+
+private:
+ unsigned char m_classType : ClassTypeBits; // ClassType
+};
+
+} // namespace WebCore
+
+#endif // CSSValue_h
diff --git a/Source/WebCore/css/CSSValue.idl b/Source/WebCore/css/CSSValue.idl
new file mode 100644
index 000000000..25eb8033c
--- /dev/null
+++ b/Source/WebCore/css/CSSValue.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ interface [
+ CustomToJS,
+ CustomIsReachable,
+ CustomFinalize,
+ Polymorphic,
+ V8DependentLifetime
+ ] CSSValue {
+
+ // UnitTypes
+ const unsigned short CSS_INHERIT = 0;
+ const unsigned short CSS_PRIMITIVE_VALUE = 1;
+ const unsigned short CSS_VALUE_LIST = 2;
+ const unsigned short CSS_CUSTOM = 3;
+
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString cssText
+ setter raises(DOMException);
+
+ readonly attribute unsigned short cssValueType;
+
+ };
+
+}
diff --git a/Source/WebCore/css/CSSValueKeywords.in b/Source/WebCore/css/CSSValueKeywords.in
new file mode 100644
index 000000000..ba1c5f692
--- /dev/null
+++ b/Source/WebCore/css/CSSValueKeywords.in
@@ -0,0 +1,883 @@
+// These are all values accepted for CSS2.
+//
+// WARNING:
+// --------
+//
+// The Values are sorted according to the properties they belong to,
+// and have to be in the same order as the enums in RenderStyleConstants.h.
+//
+// If not, the optimizations in the cssparser and style selector will fail,
+// and produce incorrect results.
+//
+inherit
+initial
+//
+// CSS_PROP_OUTLINE_STYLE
+// CSS_PROP_BORDER_TOP_STYLE
+// CSS_PROP_BORDER_BOTTOM_STYLE
+// CSS_PROP_BORDER_LEFT_STYLE
+none
+hidden
+inset
+groove
+outset
+ridge
+dotted
+dashed
+solid
+double
+//
+// CSS_PROP_FONT:
+//
+caption
+icon
+menu
+message-box
+small-caption
+-webkit-mini-control
+-webkit-small-control
+-webkit-control
+status-bar
+
+//
+// CSS_PROP_FONT_STYLE:
+//
+//normal
+italic
+oblique
+// The following is only allowed in @font-face:
+all
+//
+// CSS_PROP_FONT_VARIANT:
+//
+//normal
+small-caps
+//
+// CSS_PROP_FONT_WEIGHT:
+//
+normal
+bold
+bolder
+lighter
+100
+200
+300
+400
+500
+600
+700
+800
+900
+//
+// CSS_PROP_FONT_SIZE:
+//
+xx-small
+x-small
+small
+medium
+large
+x-large
+xx-large
+-webkit-xxx-large
+smaller
+larger
+//
+// CSS_PROP_FONT_STRETCH:
+//
+//normal
+wider
+narrower
+ultra-condensed
+extra-condensed
+condensed
+semi-condensed
+semi-expanded
+expanded
+extra-expanded
+ultra-expanded
+//
+// CSS_PROP_GENERIC_FONT_FAMILY:
+//
+serif
+sans-serif
+cursive
+fantasy
+monospace
+-webkit-body
+-webkit-pictograph
+//
+//
+// CSS_PROP_*_COLOR
+//
+aqua
+black
+blue
+fuchsia
+gray
+green
+lime
+maroon
+navy
+olive
+orange
+purple
+red
+silver
+teal
+white
+yellow
+transparent
+-webkit-link
+-webkit-activelink
+activeborder
+activecaption
+appworkspace
+background
+buttonface
+buttonhighlight
+buttonshadow
+buttontext
+captiontext
+graytext
+highlight
+highlighttext
+inactiveborder
+inactivecaption
+inactivecaptiontext
+infobackground
+infotext
+match
+menutext
+scrollbar
+threeddarkshadow
+threedface
+threedhighlight
+threedlightshadow
+threedshadow
+window
+windowframe
+windowtext
+-webkit-focus-ring-color
+currentcolor
+//
+// colors in non strict mode
+grey
+-webkit-text
+//
+// CSS_PROP_BACKGROUND_REPEAT:
+//
+repeat
+repeat-x
+repeat-y
+no-repeat
+// round
+// space
+//
+// CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE:
+//
+clear
+copy
+source-over
+source-in
+source-out
+source-atop
+destination-over
+destination-in
+destination-out
+destination-atop
+xor
+plus-darker
+// highlight
+plus-lighter
+//
+// CSS_PROP_VERTICAL_ALIGN:
+//
+baseline
+middle
+sub
+super
+text-top
+text-bottom
+top
+bottom
+// HTML alignment MIDDLE has no corresponding CSS alignment
+-webkit-baseline-middle
+//
+// CSS_PROP_TEXT_ALIGN:
+//
+-webkit-auto
+left
+right
+center
+justify
+-webkit-left
+-webkit-right
+-webkit-center
+-webkit-match-parent
+//
+// CSS_PROP_LIST_STYLE_POSITION:
+//
+outside
+inside
+//
+// CSS_PROP_LIST_STYLE_TYPE:
+//
+disc
+circle
+square
+decimal
+decimal-leading-zero
+arabic-indic
+binary
+bengali
+cambodian
+khmer
+devanagari
+gujarati
+gurmukhi
+kannada
+lower-hexadecimal
+lao
+malayalam
+mongolian
+myanmar
+octal
+oriya
+persian
+urdu
+telugu
+tibetan
+thai
+upper-hexadecimal
+lower-roman
+upper-roman
+lower-greek
+lower-alpha
+lower-latin
+upper-alpha
+upper-latin
+afar
+ethiopic-halehame-aa-et
+ethiopic-halehame-aa-er
+amharic
+ethiopic-halehame-am-et
+amharic-abegede
+ethiopic-abegede-am-et
+cjk-earthly-branch
+cjk-heavenly-stem
+ethiopic
+ethiopic-halehame-gez
+ethiopic-abegede
+ethiopic-abegede-gez
+hangul-consonant
+hangul
+lower-norwegian
+oromo
+ethiopic-halehame-om-et
+sidama
+ethiopic-halehame-sid-et
+somali
+ethiopic-halehame-so-et
+tigre
+ethiopic-halehame-tig
+tigrinya-er
+ethiopic-halehame-ti-er
+tigrinya-er-abegede
+ethiopic-abegede-ti-er
+tigrinya-et
+ethiopic-halehame-ti-et
+tigrinya-et-abegede
+ethiopic-abegede-ti-et
+upper-greek
+upper-norwegian
+asterisks
+footnotes
+hebrew
+armenian
+lower-armenian
+upper-armenian
+georgian
+cjk-ideographic
+hiragana
+katakana
+hiragana-iroha
+katakana-iroha
+//none
+//
+// CSS_PROP_DISPLAY:
+//
+inline
+block
+list-item
+run-in
+compact
+inline-block
+table
+inline-table
+table-row-group
+table-header-group
+table-footer-group
+table-row
+table-column-group
+table-column
+table-cell
+table-caption
+-webkit-box
+-webkit-inline-box
+-webkit-flexbox
+-webkit-inline-flexbox
+#if defined(ENABLE_CSS_GRID_LAYOUT) && ENABLE_CSS_GRID_LAYOUT
+-webkit-grid
+-webkit-inline-grid
+#endif
+//none
+//
+// CSS_PROP_CURSOR:
+//
+auto
+crosshair
+default
+pointer
+move
+vertical-text
+cell
+context-menu
+alias
+// copy
+progress
+no-drop
+not-allowed
+-webkit-zoom-in
+-webkit-zoom-out
+e-resize
+ne-resize
+nw-resize
+n-resize
+se-resize
+sw-resize
+s-resize
+w-resize
+ew-resize
+ns-resize
+nesw-resize
+nwse-resize
+col-resize
+row-resize
+text
+wait
+help
+all-scroll
+-webkit-grab
+-webkit-grabbing
+// none
+//
+// CSS_PROP_DIRECTION:
+//
+ltr
+rtl
+//
+// CSS_PROP_TEXT_TRANSFORM:
+//
+capitalize
+uppercase
+lowercase
+//none
+//
+// CSS_PROP_VISIBILITY:
+//
+visible
+//hidden
+collapse
+//
+// Unordered rest
+//
+a3
+a4
+a5
+above
+absolute
+always
+avoid
+b4
+b5
+below
+bidi-override
+blink
+both
+close-quote
+crop
+cross
+embed
+fixed
+hand
+hide
+higher
+invert
+-webkit-isolate
+-webkit-plaintext
+landscape
+ledger
+legal
+letter
+level
+line-through
+local
+loud
+lower
+-webkit-marquee
+mix
+no-close-quote
+no-open-quote
+nowrap
+open-quote
+overlay
+overline
+portrait
+pre
+pre-line
+pre-wrap
+relative
+scroll
+separate
+show
+static
+thick
+thin
+underline
+-webkit-nowrap
+
+// CSS3 Values
+// CSS_PROP_BOX_ALIGN
+stretch
+start
+end
+//center
+//baseline
+
+// CSS_PROP_BOX_DIRECTION
+// normal
+reverse
+
+// CSS_PROP_BOX_ORIENT
+horizontal
+vertical
+inline-axis
+block-axis
+
+// CSS_PROP_BOX_PACK
+// start
+// end
+// center
+// justify
+
+// CSS_PROP_BOX_LINES
+single
+multiple
+
+// CSS_PROP_FLEX_ALIGN
+// start
+// end
+// center
+// baseline
+// stretch
+
+// CSS_PROP_FLEX_FLOW
+row
+row-reverse
+column
+column-reverse
+// nowrap
+// wrap
+wrap-reverse
+
+// CSS_PROP_MARQUEE_DIRECTION
+forwards
+backwards
+ahead
+// reverse
+// left
+// right
+up
+down
+// auto
+
+// CSS_PROP_MARQUEE_SPEED
+slow
+// normal
+fast
+
+// CSS_PROP_MARQUEE_REPETITION
+infinite
+
+// CSS_PROP_MARQUEE_STYLE
+// none
+slide
+// scroll
+alternate
+
+//
+// CSS_PROP__KHTML_USER_MODIFY
+//
+read-only
+read-write
+read-write-plaintext-only
+
+//
+// CSS_PROP__KHTML_USER_DRAG
+//
+element
+
+//
+// CSS_PROP__KHTML_USER_SELECT
+//
+ignore
+
+//
+// CSS_PROP_WIDTH/MIN_WIDTH/MAX_WIDTH
+//
+intrinsic
+min-intrinsic
+
+//
+// CSS_PROP_TEXT_OVERFLOW
+//
+clip
+ellipsis
+
+//
+// CSS_PROP__KHTML_MARGIN_COLLAPSE
+//
+// collapse
+// separate
+discard
+
+//
+// CSS_PROP_TEXT_*_COLOR
+//
+dot-dash
+dot-dot-dash
+wave
+
+//
+// CSS_PROP_TEXT_*_MODE
+//
+continuous
+skip-white-space
+
+//
+// CSS_PROP_WORD_BREAK
+//
+break-all
+
+//
+// CSS_PROP_WORD_WRAP
+//
+break-word
+
+//
+// CSS_PROP__KHTML_NBSP_MODE
+//
+space
+
+//
+// CSS_PROP__KHTML_LINE_BREAK
+//
+after-white-space
+
+// -webkit-appearance
+// The order here should match the order in the ControlPart enum in ThemeTypes.h.
+// All appearance values that should be accepted by the parser should be listed between 'checkbox' and 'textarea':
+checkbox
+radio
+push-button
+square-button
+button
+button-bevel
+default-button
+inner-spin-button
+-webkit-input-speech-button
+list-button
+listbox
+listitem
+media-fullscreen-button
+media-mute-button
+media-play-button
+media-seek-back-button
+media-seek-forward-button
+media-rewind-button
+media-return-to-realtime-button
+media-toggle-closed-captions-button
+media-slider
+media-sliderthumb
+media-volume-slider-container
+media-volume-slider
+media-volume-sliderthumb
+media-volume-slider-mute-button
+media-controls-background
+media-controls-fullscreen-background
+media-current-time-display
+media-time-remaining-display
+menulist
+menulist-button
+menulist-text
+menulist-textfield
+meter
+progress-bar
+progress-bar-value
+slider-horizontal
+slider-vertical
+sliderthumb-horizontal
+sliderthumb-vertical
+caret
+searchfield
+searchfield-decoration
+searchfield-results-decoration
+searchfield-results-button
+searchfield-cancel-button
+textfield
+relevancy-level-indicator
+continuous-capacity-level-indicator
+discrete-capacity-level-indicator
+rating-level-indicator
+textarea
+// An appearance value that should not be accepted by the parser:
+caps-lock-indicator
+
+//
+// CSS_PROP_BORDER_IMAGE
+//
+// stretch
+// repeat
+round
+
+//
+// CSS_PROP_BACKGROUND_CLIP/ORIGIN
+//
+// border/content/padding are deprecated and ultimately will only apply to the -webkit- form of these properties.
+// border-box/content-box/padding-box should be used instead.
+//
+border
+border-box
+content
+content-box
+padding
+padding-box
+
+//
+// background-size
+//
+contain
+cover
+
+//
+// CSS_PROP__KHTML_RTL_ORDERING
+//
+logical
+visual
+
+//
+// CSS_PROP__WEBKIT_BORDER_FIT
+//
+lines
+
+//
+// CSS_PROP__WEBKIT_ANIMATION_DIRECTION
+//
+// alternate
+
+//
+// CSS_PROP__WEBKIT_ANIMATION_FILL_MODE
+//
+// forwards
+// backwards
+// both
+
+//
+// CSS_PROP__WEBKIT_ANIMATION_ITERATION_COUNT
+//
+// infinite
+
+//
+// CSS_PROP__WEBKIT_ANIMATION_PLAY_STATE
+//
+running
+paused
+
+//
+// CSS_PROP__WEBKIT_TRANSFORM_STYLE
+//
+flat
+preserve-3d
+
+//
+// CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION
+// CSS_PROP__WEBKIT_ANIMATION_TIMING_FUNCTION
+//
+ease
+linear
+ease-in
+ease-out
+ease-in-out
+step-start
+step-end
+
+//
+// CSS_PROP_ZOOM
+//
+document
+reset
+
+//
+// CSS_PROP_POINTER_EVENTS
+//
+visiblePainted
+visibleFill
+visibleStroke
+//visible
+painted
+fill
+stroke
+//all
+//none
+
+//
+// CSS_PROP_SPEECH
+//
+spell-out
+digits
+literal-punctuation
+no-punctuation
+
+//
+// -webkit-font-smoothing
+//
+// auto
+// none
+antialiased
+subpixel-antialiased
+
+// text-rendering
+//auto
+optimizeSpeed
+optimizeLegibility
+geometricPrecision
+
+// -webkit-color-adjust
+economy
+exact
+
+// -webkit-color-correction
+//default
+sRGB
+
+// (-webkit-view-mode:) media feature:
+floating
+fullscreen
+maximized
+minimized
+windowed
+
+// -webkit-hyphenate-limit-lines
+no-limit
+
+// -webkit-hyphens
+// none
+manual
+// auto
+
+// -webkit-writing-mode
+// SVG compatibility
+lr
+rl
+tb
+lr-tb
+rl-tb
+tb-rl
+// Standard values from CSS3
+horizontal-tb
+vertical-rl
+vertical-lr
+horizontal-bt
+
+// -webkit-text-emphasis-position
+over
+under
+
+// -webkit-text-emphasis-style
+filled
+open
+dot
+// circle
+double-circle
+triangle
+sesame
+
+// -webkit-radial-gradient
+// circle
+ellipse
+closest-side
+closest-corner
+farthest-side
+farthest-corner
+// contain
+// cover
+
+// -webkit-text-orientation
+upright
+vertical-right
+
+// -webkit-line-box-contain
+font
+glyphs
+inline-box
+replaced
+
+// -webkit-line-grid-snap
+//none
+//baseline
+bounds
+
+// -webkit-font-feature-settings
+on
+off
+
+// image-rendering
+//auto
+//optimizeSpeed
+optimizeQuality
+-webkit-optimize-contrast
+
+// Positioned Floats
+-webkit-positioned
+
+// -webkit-wrap-shape
+nonzero
+evenodd
+
+// -webkit-region-overflow
+// auto
+break
+
+// -webkit-wrap-flow
+// auto
+// both
+// left
+// right
+maximum
+// clear
+
+// -webkit-wrap-through
+wrap
+// none
+
+#if defined(ENABLE_CSS_FILTERS) && ENABLE_CSS_FILTERS
+// -webkit-filter
+#if defined(ENABLE_CSS_SHADERS) && ENABLE_CSS_SHADERS
+// values for the custom() function
+// border-box
+// padding-box
+// content-box
+filter-box
+detached
+#endif // CSS_SHADERS
+#endif // CSS_FILTERS
diff --git a/Source/WebCore/css/CSSValueList.cpp b/Source/WebCore/css/CSSValueList.cpp
new file mode 100644
index 000000000..661e183a7
--- /dev/null
+++ b/Source/WebCore/css/CSSValueList.cpp
@@ -0,0 +1,122 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2010 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 "CSSValueList.h"
+
+#include "CSSParserValues.h"
+#include "PlatformString.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+CSSValueList::CSSValueList(ClassType classType, bool isSpaceSeparated)
+ : CSSValue(classType)
+{
+ m_isSpaceSeparatedValueList = isSpaceSeparated;
+}
+
+CSSValueList::CSSValueList(bool isSpaceSeparated)
+ : CSSValue(ValueListClass)
+{
+ m_isSpaceSeparatedValueList = isSpaceSeparated;
+}
+
+CSSValueList::CSSValueList(CSSParserValueList* list)
+ : CSSValue(ValueListClass)
+{
+ m_isSpaceSeparatedValueList = true;
+ if (list) {
+ size_t size = list->size();
+ for (unsigned i = 0; i < size; ++i)
+ append(list->valueAt(i)->createCSSValue());
+ }
+}
+
+void CSSValueList::append(PassRefPtr<CSSValue> val)
+{
+ m_values.append(val);
+}
+
+void CSSValueList::prepend(PassRefPtr<CSSValue> val)
+{
+ m_values.prepend(val);
+}
+
+bool CSSValueList::removeAll(CSSValue* val)
+{
+ bool found = false;
+ // FIXME: we should be implementing operator== to CSSValue and its derived classes
+ // to make comparison more flexible and fast.
+ for (size_t index = 0; index < m_values.size(); index++) {
+ if (m_values.at(index)->cssText() == val->cssText()) {
+ m_values.remove(index);
+ found = true;
+ }
+ }
+
+ return found;
+}
+
+bool CSSValueList::hasValue(CSSValue* val) const
+{
+ // FIXME: we should be implementing operator== to CSSValue and its derived classes
+ // to make comparison more flexible and fast.
+ for (size_t index = 0; index < m_values.size(); index++) {
+ if (m_values.at(index)->cssText() == val->cssText())
+ return true;
+ }
+ return false;
+}
+
+PassRefPtr<CSSValueList> CSSValueList::copy()
+{
+ PassRefPtr<CSSValueList> newList = isSpaceSeparated() ? createSpaceSeparated() : createCommaSeparated();
+ for (size_t index = 0; index < m_values.size(); index++)
+ newList->append(m_values[index]);
+ return newList;
+}
+
+String CSSValueList::customCssText() const
+{
+ String result = "";
+
+ unsigned size = m_values.size();
+ for (unsigned i = 0; i < size; i++) {
+ if (!result.isEmpty()) {
+ if (isSpaceSeparated())
+ result += " ";
+ else
+ result += ", ";
+ }
+ result += m_values[i]->cssText();
+ }
+
+ return result;
+}
+
+void CSSValueList::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
+{
+ size_t size = m_values.size();
+ for (size_t i = 0; i < size; ++i)
+ m_values[i]->addSubresourceStyleURLs(urls, styleSheet);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/CSSValueList.h b/Source/WebCore/css/CSSValueList.h
new file mode 100644
index 000000000..c62262a9e
--- /dev/null
+++ b/Source/WebCore/css/CSSValueList.h
@@ -0,0 +1,103 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 CSSValueList_h
+#define CSSValueList_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSParserValueList;
+
+class CSSValueList : public CSSValue {
+public:
+ static PassRefPtr<CSSValueList> createCommaSeparated()
+ {
+ return adoptRef(new CSSValueList(false));
+ }
+ static PassRefPtr<CSSValueList> createSpaceSeparated()
+ {
+ return adoptRef(new CSSValueList(true));
+ }
+ static PassRefPtr<CSSValueList> createFromParserValueList(CSSParserValueList* list)
+ {
+ return adoptRef(new CSSValueList(list));
+ }
+
+ size_t length() const { return m_values.size(); }
+ CSSValue* item(size_t index) { return index < m_values.size() ? m_values[index].get() : 0; }
+ CSSValue* itemWithoutBoundsCheck(size_t index) { return m_values[index].get(); }
+
+ void append(PassRefPtr<CSSValue>);
+ void prepend(PassRefPtr<CSSValue>);
+ bool removeAll(CSSValue*);
+ bool hasValue(CSSValue*) const;
+ PassRefPtr<CSSValueList> copy();
+
+ String customCssText() const;
+
+ void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
+
+protected:
+ CSSValueList(ClassType, bool isSpaceSeparated);
+
+private:
+ explicit CSSValueList(bool isSpaceSeparated);
+ explicit CSSValueList(CSSParserValueList*);
+
+ bool isSpaceSeparated() const { return m_isSpaceSeparatedValueList; }
+
+ Vector<RefPtr<CSSValue> > m_values;
+};
+
+// Objects of this class are intended to be stack-allocated and scoped to a single function.
+// Please take care not to pass these around as they do hold onto a raw pointer.
+class CSSValueListInspector {
+public:
+ CSSValueListInspector(CSSValue* value) : m_list((value && value->isValueList()) ? static_cast<CSSValueList*>(value) : 0) { }
+ CSSValue* item(size_t index) const { ASSERT(index < length()); return m_list->itemWithoutBoundsCheck(index); }
+ CSSValue* first() const { return item(0); }
+ CSSValue* second() const { return item(1); }
+ size_t length() const { return m_list ? m_list->length() : 0; }
+private:
+ CSSValueList* m_list;
+};
+
+// Wrapper that can be used to iterate over any CSSValue. Non-list values and 0 behave as zero-length lists.
+// Objects of this class are intended to be stack-allocated and scoped to a single function.
+// Please take care not to pass these around as they do hold onto a raw pointer.
+class CSSValueListIterator {
+public:
+ CSSValueListIterator(CSSValue* value) : m_inspector(value), m_position(0) { }
+ bool hasMore() const { return m_position < m_inspector.length(); }
+ CSSValue* value() const { return m_inspector.item(m_position); }
+ bool isPrimitiveValue() const { return value()->isPrimitiveValue(); }
+ void advance() { m_position++; ASSERT(m_position <= m_inspector.length());}
+ size_t index() const { return m_position; }
+private:
+ CSSValueListInspector m_inspector;
+ size_t m_position;
+};
+} // namespace WebCore
+
+#endif // CSSValueList_h
diff --git a/Source/WebCore/css/CSSValueList.idl b/Source/WebCore/css/CSSValueList.idl
new file mode 100644
index 000000000..63c8514de
--- /dev/null
+++ b/Source/WebCore/css/CSSValueList.idl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2006, 2007 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 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface [
+ HasIndexGetter
+ ] CSSValueList : CSSValue {
+ readonly attribute unsigned long length;
+ CSSValue item(in [Optional=CallWithDefaultValue] unsigned long index);
+ };
+
+}
diff --git a/Source/WebCore/css/CSSValuePool.cpp b/Source/WebCore/css/CSSValuePool.cpp
new file mode 100644
index 000000000..3d8893ea8
--- /dev/null
+++ b/Source/WebCore/css/CSSValuePool.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 "CSSValuePool.h"
+#include "CSSValueKeywords.h"
+
+namespace WebCore {
+
+CSSValuePool::CSSValuePool()
+ : m_inheritedValue(CSSInheritedValue::create())
+ , m_implicitInitialValue(CSSInitialValue::createImplicit())
+ , m_explicitInitialValue(CSSInitialValue::createExplicit())
+ , m_colorTransparent(CSSPrimitiveValue::createColor(Color::transparent))
+ , m_colorWhite(CSSPrimitiveValue::createColor(Color::white))
+ , m_colorBlack(CSSPrimitiveValue::createColor(Color::black))
+ , m_pixelZero(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX))
+ , m_percentZero(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PERCENTAGE))
+ , m_numberZero(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER))
+{
+}
+
+CSSValuePool::~CSSValuePool()
+{
+}
+
+PassRefPtr<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(int ident)
+{
+ if (ident <= 0 || ident >= numCSSValueKeywords)
+ return CSSPrimitiveValue::createIdentifier(ident);
+
+ RefPtr<CSSPrimitiveValue> dummyValue;
+ pair<IdentifierValueCache::iterator, bool> entry = m_identifierValueCache.add(ident, dummyValue);
+ if (entry.second)
+ entry.first->second = CSSPrimitiveValue::createIdentifier(ident);
+ return entry.first->second;
+}
+
+PassRefPtr<CSSPrimitiveValue> CSSValuePool::createColorValue(unsigned rgbValue)
+{
+ // These are the empty and deleted values of the hash table.
+ if (rgbValue == Color::transparent)
+ return m_colorTransparent;
+ if (rgbValue == Color::white)
+ return m_colorWhite;
+ // Just because it is common.
+ if (rgbValue == Color::black)
+ return m_colorBlack;
+
+ // Just wipe out the cache and start rebuilding if it gets too big.
+ const int maximumColorCacheSize = 512;
+ if (m_colorValueCache.size() > maximumColorCacheSize)
+ m_colorValueCache.clear();
+
+ RefPtr<CSSPrimitiveValue> dummyValue;
+ pair<ColorValueCache::iterator, bool> entry = m_colorValueCache.add(rgbValue, dummyValue);
+ if (entry.second)
+ entry.first->second = CSSPrimitiveValue::createColor(rgbValue);
+ return entry.first->second;
+}
+
+PassRefPtr<CSSPrimitiveValue> CSSValuePool::createValue(double value, CSSPrimitiveValue::UnitTypes type)
+{
+ // Small positive integers repeat often.
+ static const int maximumCacheableValue = 256;
+ if (value < 0 || value > maximumCacheableValue)
+ return CSSPrimitiveValue::create(value, type);
+
+ int intValue = static_cast<int>(value);
+ if (value != intValue)
+ return CSSPrimitiveValue::create(value, type);
+
+ IntegerValueCache* cache;
+ switch (type) {
+ case CSSPrimitiveValue::CSS_PX:
+ if (intValue == 0)
+ return m_pixelZero;
+ cache = &m_pixelValueCache;
+ break;
+ case CSSPrimitiveValue::CSS_PERCENTAGE:
+ if (intValue == 0)
+ return m_percentZero;
+ cache = &m_percentValueCache;
+ break;
+ case CSSPrimitiveValue::CSS_NUMBER:
+ if (intValue == 0)
+ return m_numberZero;
+ cache = &m_numberValueCache;
+ break;
+ default:
+ return CSSPrimitiveValue::create(value, type);
+ }
+
+ RefPtr<CSSPrimitiveValue> dummyValue;
+ pair<IntegerValueCache::iterator, bool> entry = cache->add(intValue, dummyValue);
+ if (entry.second)
+ entry.first->second = CSSPrimitiveValue::create(value, type);
+ return entry.first->second;
+}
+
+}
diff --git a/Source/WebCore/css/CSSValuePool.h b/Source/WebCore/css/CSSValuePool.h
new file mode 100644
index 000000000..bc751ebf7
--- /dev/null
+++ b/Source/WebCore/css/CSSValuePool.h
@@ -0,0 +1,78 @@
+/*
+ * 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 CSSValuePool_h
+#define CSSValuePool_h
+
+#include "CSSInheritedValue.h"
+#include "CSSInitialValue.h"
+#include "CSSPrimitiveValue.h"
+#include <wtf/HashMap.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSValuePool : public RefCounted<CSSValuePool> {
+public:
+ static PassRefPtr<CSSValuePool> create() { return adoptRef(new CSSValuePool); }
+ ~CSSValuePool();
+
+ PassRefPtr<CSSInheritedValue> createInheritedValue() { return m_inheritedValue; }
+ PassRefPtr<CSSInitialValue> createImplicitInitialValue() { return m_implicitInitialValue; }
+ PassRefPtr<CSSInitialValue> createExplicitInitialValue() { return m_explicitInitialValue; }
+ PassRefPtr<CSSPrimitiveValue> createIdentifierValue(int identifier);
+ PassRefPtr<CSSPrimitiveValue> createColorValue(unsigned rgbValue);
+ PassRefPtr<CSSPrimitiveValue> createValue(double value, CSSPrimitiveValue::UnitTypes);
+ PassRefPtr<CSSPrimitiveValue> createValue(const String& value, CSSPrimitiveValue::UnitTypes type) { return CSSPrimitiveValue::create(value, type); }
+ template<typename T> static PassRefPtr<CSSPrimitiveValue> createValue(T value) { return CSSPrimitiveValue::create(value); }
+
+private:
+ CSSValuePool();
+
+ RefPtr<CSSInheritedValue> m_inheritedValue;
+ RefPtr<CSSInitialValue> m_implicitInitialValue;
+ RefPtr<CSSInitialValue> m_explicitInitialValue;
+
+ typedef HashMap<int, RefPtr<CSSPrimitiveValue> > IdentifierValueCache;
+ IdentifierValueCache m_identifierValueCache;
+
+ typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache;
+ ColorValueCache m_colorValueCache;
+ RefPtr<CSSPrimitiveValue> m_colorTransparent;
+ RefPtr<CSSPrimitiveValue> m_colorWhite;
+ RefPtr<CSSPrimitiveValue> m_colorBlack;
+
+ typedef HashMap<int, RefPtr<CSSPrimitiveValue> > IntegerValueCache;
+ RefPtr<CSSPrimitiveValue> m_pixelZero;
+ RefPtr<CSSPrimitiveValue> m_percentZero;
+ RefPtr<CSSPrimitiveValue> m_numberZero;
+ IntegerValueCache m_pixelValueCache;
+ IntegerValueCache m_percentValueCache;
+ IntegerValueCache m_numberValueCache;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/CSSWrapShapes.cpp b/Source/WebCore/css/CSSWrapShapes.cpp
new file mode 100644
index 000000000..e5e9f98c3
--- /dev/null
+++ b/Source/WebCore/css/CSSWrapShapes.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2011 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.
+ */
+
+#include "config.h"
+
+#include "CSSWrapShapes.h"
+
+#include <wtf/text/StringBuilder.h>
+
+using namespace WTF;
+
+namespace WebCore {
+
+String CSSWrapShapeRect::cssText() const
+{
+ DEFINE_STATIC_LOCAL(const String, rectParen, ("rect("));
+ DEFINE_STATIC_LOCAL(const String, comma, (", "));
+
+ StringBuilder result;
+ result.reserveCapacity(32);
+ result.append(rectParen);
+
+ result.append(m_left->cssText());
+ result.append(comma);
+
+ result.append(m_top->cssText());
+ result.append(comma);
+
+ result.append(m_width->cssText());
+ result.append(comma);
+
+ result.append(m_height->cssText());
+
+ if (m_radiusX.get()) {
+ result.append(comma);
+ result.append(m_radiusX->cssText());
+
+ if (m_radiusY.get()) {
+ result.append(comma);
+ result.append(m_radiusY->cssText());
+ }
+ }
+
+ result.append(')');
+
+ return result.toString();
+}
+
+String CSSWrapShapeCircle::cssText() const
+{
+ DEFINE_STATIC_LOCAL(const String, circleParen, ("circle("));
+ DEFINE_STATIC_LOCAL(const String, comma, (", "));
+
+ StringBuilder result;
+ result.reserveCapacity(32);
+ result.append(circleParen);
+
+ result.append(m_left->cssText());
+ result.append(comma);
+
+ result.append(m_top->cssText());
+ result.append(comma);
+
+ result.append(m_radius->cssText());
+ result.append(')');
+
+ return result.toString();
+}
+
+String CSSWrapShapeEllipse::cssText() const
+{
+ DEFINE_STATIC_LOCAL(const String, ellipseParen, ("ellipse("));
+ DEFINE_STATIC_LOCAL(const String, comma, (", "));
+
+ StringBuilder result;
+ result.reserveCapacity(32);
+ result.append(ellipseParen);
+
+ result.append(m_left->cssText());
+ result.append(comma);
+
+ result.append(m_top->cssText());
+ result.append(comma);
+
+ result.append(m_radiusX->cssText());
+ result.append(comma);
+
+ result.append(m_radiusY->cssText());
+ result.append(')');
+
+ return result.toString();
+}
+
+String CSSWrapShapePolygon::cssText() const
+{
+ DEFINE_STATIC_LOCAL(const String, polygonParenEvenOdd, ("polygon(evenodd, "));
+ DEFINE_STATIC_LOCAL(const String, polygonParenNonZero, ("polygon(nonzero, "));
+ DEFINE_STATIC_LOCAL(const String, comma, (", "));
+
+ StringBuilder result;
+ result.reserveCapacity(32);
+ if (m_windRule == RULE_EVENODD)
+ result.append(polygonParenEvenOdd);
+ else
+ result.append(polygonParenNonZero);
+
+ ASSERT(!(m_values.size() % 2));
+
+ for (unsigned i = 0; i < m_values.size(); i += 2) {
+ if (i)
+ result.append(' ');
+ result.append(m_values.at(i)->cssText());
+ result.append(comma);
+ result.append(m_values.at(i + 1)->cssText());
+ }
+
+ result.append(')');
+
+ return result.toString();
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/css/CSSWrapShapes.h b/Source/WebCore/css/CSSWrapShapes.h
new file mode 100644
index 000000000..3ff9fab83
--- /dev/null
+++ b/Source/WebCore/css/CSSWrapShapes.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2011 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.
+ */
+
+#ifndef CSSWrapShapes_h
+#define CSSWrapShapes_h
+
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+#include "WindRule.h"
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSWrapShape : public RefCounted<CSSWrapShape> {
+public:
+ enum Type {
+ CSS_WRAP_SHAPE_RECT = 1,
+ CSS_WRAP_SHAPE_CIRCLE = 2,
+ CSS_WRAP_SHAPE_ELLIPSE = 3,
+ CSS_WRAP_SHAPE_POLYGON = 4,
+ CSS_WRAP_SHAPE_PATH = 5
+ };
+
+ virtual Type type() = 0;
+ virtual String cssText() const = 0;
+
+public:
+ virtual ~CSSWrapShape() { }
+
+protected:
+ CSSWrapShape() { }
+};
+
+class CSSWrapShapeRect : public CSSWrapShape {
+public:
+ static PassRefPtr<CSSWrapShapeRect> create() { return adoptRef(new CSSWrapShapeRect); }
+
+ CSSPrimitiveValue* left() const { return m_left.get(); }
+ CSSPrimitiveValue* top() const { return m_top.get(); }
+ CSSPrimitiveValue* width() const { return m_width.get(); }
+ CSSPrimitiveValue* height() const { return m_height.get(); }
+ CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); }
+ CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); }
+
+ void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; }
+ void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; }
+ void setWidth(PassRefPtr<CSSPrimitiveValue> width) { m_width = width; }
+ void setHeight(PassRefPtr<CSSPrimitiveValue> height) { m_height = height; }
+ void setRadiusX(PassRefPtr<CSSPrimitiveValue> radiusX) { m_radiusX = radiusX; }
+ void setRadiusY(PassRefPtr<CSSPrimitiveValue> radiusY) { m_radiusY = radiusY; }
+
+ virtual Type type() { return CSS_WRAP_SHAPE_RECT; }
+ virtual String cssText() const;
+
+private:
+ CSSWrapShapeRect() { }
+
+ RefPtr<CSSPrimitiveValue> m_top;
+ RefPtr<CSSPrimitiveValue> m_left;
+ RefPtr<CSSPrimitiveValue> m_width;
+ RefPtr<CSSPrimitiveValue> m_height;
+ RefPtr<CSSPrimitiveValue> m_radiusX;
+ RefPtr<CSSPrimitiveValue> m_radiusY;
+};
+
+class CSSWrapShapeCircle : public CSSWrapShape {
+public:
+ static PassRefPtr<CSSWrapShapeCircle> create() { return adoptRef(new CSSWrapShapeCircle); }
+
+ CSSPrimitiveValue* left() const { return m_left.get(); }
+ CSSPrimitiveValue* top() const { return m_top.get(); }
+ CSSPrimitiveValue* radius() const { return m_radius.get(); }
+
+ void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; }
+ void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; }
+ void setRadius(PassRefPtr<CSSPrimitiveValue> radius) { m_radius = radius; }
+
+ virtual Type type() { return CSS_WRAP_SHAPE_CIRCLE; }
+ virtual String cssText() const;
+
+private:
+ CSSWrapShapeCircle() { }
+
+ RefPtr<CSSPrimitiveValue> m_top;
+ RefPtr<CSSPrimitiveValue> m_left;
+ RefPtr<CSSPrimitiveValue> m_radius;
+};
+
+class CSSWrapShapeEllipse : public CSSWrapShape {
+public:
+ static PassRefPtr<CSSWrapShapeEllipse> create() { return adoptRef(new CSSWrapShapeEllipse); }
+
+ CSSPrimitiveValue* left() const { return m_left.get(); }
+ CSSPrimitiveValue* top() const { return m_top.get(); }
+ CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); }
+ CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); }
+
+ void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; }
+ void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; }
+ void setRadiusX(PassRefPtr<CSSPrimitiveValue> radiusX) { m_radiusX = radiusX; }
+ void setRadiusY(PassRefPtr<CSSPrimitiveValue> radiusY) { m_radiusY = radiusY; }
+
+ virtual Type type() { return CSS_WRAP_SHAPE_ELLIPSE; }
+ virtual String cssText() const;
+
+private:
+ CSSWrapShapeEllipse() { }
+
+ RefPtr<CSSPrimitiveValue> m_top;
+ RefPtr<CSSPrimitiveValue> m_left;
+ RefPtr<CSSPrimitiveValue> m_radiusX;
+ RefPtr<CSSPrimitiveValue> m_radiusY;
+};
+
+class CSSWrapShapePolygon : public CSSWrapShape {
+public:
+ static PassRefPtr<CSSWrapShapePolygon> create() { return adoptRef(new CSSWrapShapePolygon); }
+
+ void appendPoint(PassRefPtr<CSSPrimitiveValue> x, PassRefPtr<CSSPrimitiveValue> y)
+ {
+ m_values.append(x);
+ m_values.append(y);
+ }
+
+ PassRefPtr<CSSPrimitiveValue> getXAt(unsigned i) { return m_values.at(i * 2); }
+ PassRefPtr<CSSPrimitiveValue> getYAt(unsigned i) { return m_values.at(i * 2 + 1); }
+
+ void setWindRule(WindRule w) { m_windRule = w; }
+ WindRule windRule() const { return m_windRule; }
+
+ virtual Type type() { return CSS_WRAP_SHAPE_POLYGON; }
+ virtual String cssText() const;
+
+private:
+ CSSWrapShapePolygon()
+ : m_windRule(RULE_NONZERO)
+ {
+ }
+
+ Vector<RefPtr<CSSPrimitiveValue> > m_values;
+ WindRule m_windRule;
+};
+
+} // namespace WebCore
+
+#endif // CSSWrapShapes_h
diff --git a/Source/WebCore/css/Counter.h b/Source/WebCore/css/Counter.h
new file mode 100644
index 000000000..c5c8176aa
--- /dev/null
+++ b/Source/WebCore/css/Counter.h
@@ -0,0 +1,61 @@
+/*
+ * (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 Counter_h
+#define Counter_h
+
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class Counter : public RefCounted<Counter> {
+public:
+ static PassRefPtr<Counter> create(PassRefPtr<CSSPrimitiveValue> identifier, PassRefPtr<CSSPrimitiveValue> listStyle, PassRefPtr<CSSPrimitiveValue> separator)
+ {
+ return adoptRef(new Counter(identifier, listStyle, separator));
+ }
+
+ String identifier() const { return m_identifier ? m_identifier->getStringValue() : String(); }
+ String listStyle() const { return m_listStyle ? m_listStyle->getStringValue() : String(); }
+ String separator() const { return m_separator ? m_separator->getStringValue() : String(); }
+
+ int listStyleIdent() const { return m_listStyle ? m_listStyle->getIdent() : 0; }
+
+ void setIdentifier(PassRefPtr<CSSPrimitiveValue> identifier) { m_identifier = identifier; }
+ void setListStyle(PassRefPtr<CSSPrimitiveValue> listStyle) { m_listStyle = listStyle; }
+ void setSeparator(PassRefPtr<CSSPrimitiveValue> separator) { m_separator = separator; }
+
+private:
+ Counter(PassRefPtr<CSSPrimitiveValue> identifier, PassRefPtr<CSSPrimitiveValue> listStyle, PassRefPtr<CSSPrimitiveValue> separator)
+ : m_identifier(identifier)
+ , m_listStyle(listStyle)
+ , m_separator(separator)
+ {
+ }
+
+ RefPtr<CSSPrimitiveValue> m_identifier; // string
+ RefPtr<CSSPrimitiveValue> m_listStyle; // ident
+ RefPtr<CSSPrimitiveValue> m_separator; // string
+};
+
+} // namespace WebCore
+
+#endif // Counter_h
diff --git a/Source/WebCore/css/Counter.idl b/Source/WebCore/css/Counter.idl
new file mode 100644
index 000000000..6236c454e
--- /dev/null
+++ b/Source/WebCore/css/Counter.idl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2006, 2007 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface Counter {
+ readonly attribute DOMString identifier;
+ readonly attribute DOMString listStyle;
+ readonly attribute DOMString separator;
+ };
+
+}
diff --git a/Source/WebCore/css/DashboardRegion.h b/Source/WebCore/css/DashboardRegion.h
new file mode 100644
index 000000000..91e5d7ae1
--- /dev/null
+++ b/Source/WebCore/css/DashboardRegion.h
@@ -0,0 +1,48 @@
+/*
+ * (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 DashboardRegion_h
+#define DashboardRegion_h
+
+#include "Rect.h"
+
+#if ENABLE(DASHBOARD_SUPPORT)
+
+namespace WebCore {
+
+class DashboardRegion : public RectBase, public RefCounted<DashboardRegion> {
+public:
+ static PassRefPtr<DashboardRegion> create() { return adoptRef(new DashboardRegion); }
+
+ RefPtr<DashboardRegion> m_next;
+ String m_label;
+ String m_geometryType;
+ bool m_isCircle : 1;
+ bool m_isRectangle : 1;
+
+private:
+ DashboardRegion() : m_isCircle(false), m_isRectangle(false) { }
+};
+
+} // namespace
+
+#endif
+
+#endif
diff --git a/Source/WebCore/css/DashboardSupportCSSPropertyNames.in b/Source/WebCore/css/DashboardSupportCSSPropertyNames.in
new file mode 100644
index 000000000..615bd6cf5
--- /dev/null
+++ b/Source/WebCore/css/DashboardSupportCSSPropertyNames.in
@@ -0,0 +1 @@
+-webkit-dashboard-region
diff --git a/Source/WebCore/css/FontFamilyValue.cpp b/Source/WebCore/css/FontFamilyValue.cpp
new file mode 100644
index 000000000..665895d3a
--- /dev/null
+++ b/Source/WebCore/css/FontFamilyValue.cpp
@@ -0,0 +1,72 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 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 "FontFamilyValue.h"
+
+#include "CSSParser.h"
+
+namespace WebCore {
+
+FontFamilyValue::FontFamilyValue(const String& familyName)
+ : CSSPrimitiveValue(FontFamilyClass, String(), CSS_STRING)
+ , m_familyName(familyName)
+{
+ // If there is anything in parentheses or square brackets at the end, delete it.
+ // FIXME: Do we really need this? The original code mentioned "a language tag in
+ // braces at the end" and "[Xft] qualifiers", but it's not clear either of those
+ // is in active use on the web.
+ unsigned length = m_familyName.length();
+ while (length >= 3) {
+ UChar startCharacter = 0;
+ switch (m_familyName[length - 1]) {
+ case ']':
+ startCharacter = '[';
+ break;
+ case ')':
+ startCharacter = '(';
+ break;
+ }
+ if (!startCharacter)
+ break;
+ unsigned first = 0;
+ for (unsigned i = length - 2; i > 0; --i) {
+ if (m_familyName[i - 1] == ' ' && m_familyName[i] == startCharacter)
+ first = i - 1;
+ }
+ if (!first)
+ break;
+ length = first;
+ }
+ m_familyName.truncate(length);
+}
+
+void FontFamilyValue::appendSpaceSeparated(const UChar* characters, unsigned length)
+{
+ m_familyName.append(' ');
+ m_familyName.append(characters, length);
+}
+
+String FontFamilyValue::customCssText() const
+{
+ return quoteCSSStringIfNeeded(m_familyName);
+}
+
+}
diff --git a/Source/WebCore/css/FontFamilyValue.h b/Source/WebCore/css/FontFamilyValue.h
new file mode 100644
index 000000000..b2fbaa29b
--- /dev/null
+++ b/Source/WebCore/css/FontFamilyValue.h
@@ -0,0 +1,50 @@
+/*
+ * (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 FontFamilyValue_h
+#define FontFamilyValue_h
+
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class FontFamilyValue : public CSSPrimitiveValue {
+public:
+ static PassRefPtr<FontFamilyValue> create(const String& familyName)
+ {
+ return adoptRef(new FontFamilyValue(familyName));
+ }
+
+ void appendSpaceSeparated(const UChar* characters, unsigned length);
+
+ const String& familyName() const { return m_familyName; }
+
+ String customCssText() const;
+
+private:
+ FontFamilyValue(const String& familyName);
+
+ String m_familyName;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/FontFeatureValue.cpp b/Source/WebCore/css/FontFeatureValue.cpp
new file mode 100644
index 000000000..62c396068
--- /dev/null
+++ b/Source/WebCore/css/FontFeatureValue.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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:
+ * 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.
+ */
+
+#include "config.h"
+#include "FontFeatureValue.h"
+
+#include "CSSParser.h"
+#include "CSSValueKeywords.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+FontFeatureValue::FontFeatureValue(const String& tag, int value)
+ : CSSValue(FontFeatureClass)
+ , m_tag(tag)
+ , m_value(value)
+{
+}
+
+String FontFeatureValue::customCssText() const
+{
+ StringBuilder builder;
+ builder.append("'");
+ builder.append(m_tag);
+ builder.append("' ");
+ builder.append(String::number(m_value));
+ return builder.toString();
+}
+
+}
diff --git a/Source/WebCore/css/FontFeatureValue.h b/Source/WebCore/css/FontFeatureValue.h
new file mode 100644
index 000000000..7d5e036c0
--- /dev/null
+++ b/Source/WebCore/css/FontFeatureValue.h
@@ -0,0 +1,54 @@
+/*
+ * 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:
+ * 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 FontFeatureValue_h
+#define FontFeatureValue_h
+
+#include "CSSValue.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+class FontFeatureValue : public CSSValue {
+public:
+ static PassRefPtr<FontFeatureValue> create(const String& tag, int value)
+ {
+ return adoptRef(new FontFeatureValue(tag, value));
+ }
+
+ const String& tag() const { return m_tag; }
+ int value() const { return m_value; }
+ String customCssText() const;
+
+private:
+ FontFeatureValue(const String&, int);
+
+ String m_tag;
+ const int m_value;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/FontValue.cpp b/Source/WebCore/css/FontValue.cpp
new file mode 100644
index 000000000..8841a7993
--- /dev/null
+++ b/Source/WebCore/css/FontValue.cpp
@@ -0,0 +1,68 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 "FontValue.h"
+
+#include "CSSValueList.h"
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+String FontValue::customCssText() const
+{
+ // font variant weight size / line-height family
+
+ StringBuilder result;
+
+ if (style)
+ result.append(style->cssText());
+ if (variant) {
+ if (!result.isEmpty())
+ result.append(' ');
+ result.append(variant->cssText());
+ }
+ if (weight) {
+ if (!result.isEmpty())
+ result.append(' ');
+ result.append(weight->cssText());
+ }
+ if (size) {
+ if (!result.isEmpty())
+ result.append(' ');
+ result.append(size->cssText());
+ }
+ if (lineHeight) {
+ if (!size)
+ result.append(' ');
+ result.append('/');
+ result.append(lineHeight->cssText());
+ }
+ if (family) {
+ if (!result.isEmpty())
+ result.append(' ');
+ result.append(family->cssText());
+ }
+
+ return result.toString();
+}
+
+}
diff --git a/Source/WebCore/css/FontValue.h b/Source/WebCore/css/FontValue.h
new file mode 100644
index 000000000..5f8336921
--- /dev/null
+++ b/Source/WebCore/css/FontValue.h
@@ -0,0 +1,58 @@
+/*
+ * (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 FontValue_h
+#define FontValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSPrimitiveValue;
+class CSSValueList;
+
+class FontValue : public CSSValue {
+public:
+ static PassRefPtr<FontValue> create()
+ {
+ return adoptRef(new FontValue);
+ }
+
+ String customCssText() const;
+
+ RefPtr<CSSPrimitiveValue> style;
+ RefPtr<CSSPrimitiveValue> variant;
+ RefPtr<CSSPrimitiveValue> weight;
+ RefPtr<CSSPrimitiveValue> size;
+ RefPtr<CSSPrimitiveValue> lineHeight;
+ RefPtr<CSSValueList> family;
+
+private:
+ FontValue()
+ : CSSValue(FontClass)
+ {
+ }
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/MediaFeatureNames.cpp b/Source/WebCore/css/MediaFeatureNames.cpp
new file mode 100644
index 000000000..85b8cbc1a
--- /dev/null
+++ b/Source/WebCore/css/MediaFeatureNames.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.
+ *
+ * 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"
+
+#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC
+#define CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS 1
+#endif
+
+#include "MediaFeatureNames.h"
+#include <wtf/StaticConstructors.h>
+
+namespace WebCore {
+namespace MediaFeatureNames {
+
+#define DEFINE_MEDIAFEATURE_GLOBAL(name, str) \
+ DEFINE_GLOBAL(AtomicString, name##MediaFeature, str)
+CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(DEFINE_MEDIAFEATURE_GLOBAL)
+#undef DEFINE_MEDIAFEATURE_GLOBAL
+
+void init()
+{
+ static bool initialized;
+ if (!initialized) {
+ // Use placement new to initialize the globals.
+
+ AtomicString::init();
+ #define INITIALIZE_GLOBAL(name, str) new ((void*)&name##MediaFeature) AtomicString(str);
+ CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(INITIALIZE_GLOBAL)
+ #undef INITIALIZE_GLOBAL
+ initialized = true;
+ }
+}
+
+} // namespace MediaFeatureNames
+} // namespace WebCore
diff --git a/Source/WebCore/css/MediaFeatureNames.h b/Source/WebCore/css/MediaFeatureNames.h
new file mode 100644
index 000000000..1daa4e9e1
--- /dev/null
+++ b/Source/WebCore/css/MediaFeatureNames.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc.
+ *
+ * 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 MediaFeatureNames_h
+#define MediaFeatureNames_h
+
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+ namespace MediaFeatureNames {
+
+#define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \
+ macro(color, "color") \
+ macro(grid, "grid") \
+ macro(monochrome, "monochrome") \
+ macro(height, "height") \
+ macro(width, "width") \
+ macro(orientation, "orientation") \
+ macro(aspect_ratio, "aspect-ratio") \
+ macro(device_aspect_ratio, "device-aspect-ratio") \
+ macro(device_pixel_ratio, "-webkit-device-pixel-ratio") \
+ macro(device_height, "device-height") \
+ macro(device_width, "device-width") \
+ macro(max_color, "max-color") \
+ macro(max_aspect_ratio, "max-aspect-ratio") \
+ macro(max_device_aspect_ratio, "max-device-aspect-ratio") \
+ macro(max_device_pixel_ratio, "-webkit-max-device-pixel-ratio") \
+ macro(max_device_height, "max-device-height") \
+ macro(max_device_width, "max-device-width") \
+ macro(max_height, "max-height") \
+ macro(max_monochrome, "max-monochrome") \
+ macro(max_width, "max-width") \
+ macro(min_color, "min-color") \
+ macro(min_aspect_ratio, "min-aspect-ratio") \
+ macro(min_device_aspect_ratio, "min-device-aspect-ratio") \
+ macro(min_device_pixel_ratio, "-webkit-min-device-pixel-ratio") \
+ macro(min_device_height, "min-device-height") \
+ macro(min_device_width, "min-device-width") \
+ macro(min_height, "min-height") \
+ macro(min_monochrome, "min-monochrome") \
+ macro(min_width, "min-width") \
+ macro(transform_2d, "-webkit-transform-2d") \
+ macro(transform_3d, "-webkit-transform-3d") \
+ macro(transition, "-webkit-transition") \
+ macro(animation, "-webkit-animation") \
+ macro(view_mode, "-webkit-view-mode")
+
+// end of macro
+
+#ifndef CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS
+ #define CSS_MEDIAQUERY_NAMES_DECLARE(name, str) extern const AtomicString name##MediaFeature;
+ CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(CSS_MEDIAQUERY_NAMES_DECLARE)
+ #undef CSS_MEDIAQUERY_NAMES_DECLARE
+#endif
+
+ void init();
+
+ } // namespace MediaFeatureNames
+} // namespace WebCore
+
+#endif // MediaFeatureNames_h
diff --git a/Source/WebCore/css/MediaList.cpp b/Source/WebCore/css/MediaList.cpp
new file mode 100644
index 000000000..e4650c842
--- /dev/null
+++ b/Source/WebCore/css/MediaList.cpp
@@ -0,0 +1,249 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2010 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 "MediaList.h"
+
+#include "CSSImportRule.h"
+#include "CSSParser.h"
+#include "CSSStyleSheet.h"
+#include "ExceptionCode.h"
+#include "MediaQuery.h"
+#include "MediaQueryExp.h"
+
+namespace WebCore {
+
+/* MediaList is used to store 3 types of media related entities which mean the same:
+ * Media Queries, Media Types and Media Descriptors.
+ * Currently MediaList always tries to parse media queries and if parsing fails,
+ * tries to fallback to Media Descriptors if m_fallback flag is set.
+ * Slight problem with syntax error handling:
+ * CSS 2.1 Spec (http://www.w3.org/TR/CSS21/media.html)
+ * specifies that failing media type parsing is a syntax error
+ * CSS 3 Media Queries Spec (http://www.w3.org/TR/css3-mediaqueries/)
+ * specifies that failing media query is a syntax error
+ * HTML 4.01 spec (http://www.w3.org/TR/REC-html40/present/styles.html#adef-media)
+ * specifies that Media Descriptors should be parsed with forward-compatible syntax
+ * DOM Level 2 Style Sheet spec (http://www.w3.org/TR/DOM-Level-2-Style/)
+ * talks about MediaList.mediaText and refers
+ * - to Media Descriptors of HTML 4.0 in context of StyleSheet
+ * - to Media Types of CSS 2.0 in context of CSSMediaRule and CSSImportRule
+ *
+ * These facts create situation where same (illegal) media specification may result in
+ * different parses depending on whether it is media attr of style element or part of
+ * css @media rule.
+ * <style media="screen and resolution > 40dpi"> ..</style> will be enabled on screen devices where as
+ * @media screen and resolution > 40dpi {..} will not.
+ * This gets more counter-intuitive in JavaScript:
+ * document.styleSheets[0].media.mediaText = "screen and resolution > 40dpi" will be ok and
+ * enabled, while
+ * document.styleSheets[0].cssRules[0].media.mediaText = "screen and resolution > 40dpi" will
+ * throw SYNTAX_ERR exception.
+ */
+
+MediaList::MediaList(CSSStyleSheet* parentStyleSheet, bool fallbackToDescriptor)
+ : m_fallback(fallbackToDescriptor)
+ , m_parentStyleSheet(parentStyleSheet)
+ , m_lastLine(0)
+{
+}
+
+MediaList::MediaList(CSSStyleSheet* parentStyleSheet, const String& media, bool fallbackToDescriptor)
+ : m_fallback(fallbackToDescriptor)
+ , m_parentStyleSheet(parentStyleSheet)
+ , m_lastLine(0)
+{
+ ExceptionCode ec = 0;
+ setMediaText(media, ec);
+ // FIXME: parsing can fail. The problem with failing constructor is that
+ // we would need additional flag saying MediaList is not valid
+ // Parse can fail only when fallbackToDescriptor == false, i.e when HTML4 media descriptor
+ // forward-compatible syntax is not in use.
+ // DOMImplementationCSS seems to mandate that media descriptors are used
+ // for both html and svg, even though svg:style doesn't use media descriptors
+ // Currently the only places where parsing can fail are
+ // creating <svg:style>, creating css media / import rules from js
+ if (ec)
+ setMediaText("invalid", ec);
+}
+
+MediaList::~MediaList()
+{
+ deleteAllValues(m_queries);
+}
+
+static String parseMediaDescriptor(const String& s)
+{
+ int len = s.length();
+
+ // http://www.w3.org/TR/REC-html40/types.html#type-media-descriptors
+ // "Each entry is truncated just before the first character that isn't a
+ // US ASCII letter [a-zA-Z] (ISO 10646 hex 41-5a, 61-7a), digit [0-9] (hex 30-39),
+ // or hyphen (hex 2d)."
+ int i;
+ unsigned short c;
+ for (i = 0; i < len; ++i) {
+ c = s[i];
+ if (! ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '1' && c <= '9')
+ || (c == '-')))
+ break;
+ }
+ return s.left(i);
+}
+
+void MediaList::deleteMedium(const String& oldMedium, ExceptionCode& ec)
+{
+ RefPtr<MediaList> tempMediaList = MediaList::create();
+ CSSParser p(true);
+
+ MediaQuery* oldQuery = 0;
+ OwnPtr<MediaQuery> createdQuery;
+
+ if (p.parseMediaQuery(tempMediaList.get(), oldMedium)) {
+ if (tempMediaList->m_queries.size() > 0)
+ oldQuery = tempMediaList->m_queries[0];
+ } else if (m_fallback) {
+ String medium = parseMediaDescriptor(oldMedium);
+ if (!medium.isNull()) {
+ createdQuery = adoptPtr(new MediaQuery(MediaQuery::None, medium, nullptr));
+ oldQuery = createdQuery.get();
+ }
+ }
+
+ // DOM Style Sheets spec doesn't allow SYNTAX_ERR to be thrown in deleteMedium
+ ec = NOT_FOUND_ERR;
+
+ if (oldQuery) {
+ for (size_t i = 0; i < m_queries.size(); ++i) {
+ MediaQuery* a = m_queries[i];
+ if (*a == *oldQuery) {
+ m_queries.remove(i);
+ delete a;
+ ec = 0;
+ break;
+ }
+ }
+ }
+
+ if (!ec)
+ notifyChanged();
+}
+
+String MediaList::mediaText() const
+{
+ String text("");
+
+ bool first = true;
+ for (size_t i = 0; i < m_queries.size(); ++i) {
+ if (!first)
+ text += ", ";
+ else
+ first = false;
+ text += m_queries[i]->cssText();
+ }
+
+ return text;
+}
+
+void MediaList::setMediaText(const String& value, ExceptionCode& ec)
+{
+ RefPtr<MediaList> tempMediaList = MediaList::create();
+ CSSParser p(true);
+
+ Vector<String> list;
+ value.split(',', list);
+ Vector<String>::const_iterator end = list.end();
+ for (Vector<String>::const_iterator it = list.begin(); it != end; ++it) {
+ String medium = (*it).stripWhiteSpace();
+ if (!medium.isEmpty()) {
+ if (!p.parseMediaQuery(tempMediaList.get(), medium)) {
+ if (m_fallback) {
+ String mediaDescriptor = parseMediaDescriptor(medium);
+ if (!mediaDescriptor.isNull())
+ tempMediaList->m_queries.append(new MediaQuery(MediaQuery::None, mediaDescriptor, nullptr));
+ } else {
+ ec = SYNTAX_ERR;
+ return;
+ }
+ }
+ } else if (!m_fallback) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+ }
+ // ",,,," falls straight through, but is not valid unless fallback
+ if (!m_fallback && list.begin() == list.end()) {
+ String s = value.stripWhiteSpace();
+ if (!s.isEmpty()) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+ }
+
+ ec = 0;
+ deleteAllValues(m_queries);
+ m_queries = tempMediaList->m_queries;
+ tempMediaList->m_queries.clear();
+ notifyChanged();
+}
+
+String MediaList::item(unsigned index) const
+{
+ if (index < m_queries.size()) {
+ MediaQuery* query = m_queries[index];
+ return query->cssText();
+ }
+
+ return String();
+}
+
+void MediaList::appendMedium(const String& newMedium, ExceptionCode& ec)
+{
+ ec = INVALID_CHARACTER_ERR;
+ CSSParser p(true);
+ if (p.parseMediaQuery(this, newMedium)) {
+ ec = 0;
+ } else if (m_fallback) {
+ String medium = parseMediaDescriptor(newMedium);
+ if (!medium.isNull()) {
+ m_queries.append(new MediaQuery(MediaQuery::None, medium, nullptr));
+ ec = 0;
+ }
+ }
+
+ if (!ec)
+ notifyChanged();
+}
+
+void MediaList::appendMediaQuery(PassOwnPtr<MediaQuery> mediaQuery)
+{
+ m_queries.append(mediaQuery.leakPtr());
+}
+
+void MediaList::notifyChanged()
+{
+ if (!m_parentStyleSheet)
+ return;
+
+ m_parentStyleSheet->styleSheetChanged();
+}
+
+}
diff --git a/Source/WebCore/css/MediaList.h b/Source/WebCore/css/MediaList.h
new file mode 100644
index 000000000..a0e0fca01
--- /dev/null
+++ b/Source/WebCore/css/MediaList.h
@@ -0,0 +1,102 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2008, 2009, 2010 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 MediaList_h
+#define MediaList_h
+
+#include <wtf/Forward.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSImportRule;
+class CSSRule;
+class CSSStyleSheet;
+class MediaQuery;
+
+typedef int ExceptionCode;
+
+class MediaList : public RefCounted<MediaList> {
+public:
+ static PassRefPtr<MediaList> create()
+ {
+ return adoptRef(new MediaList(0, false));
+ }
+ static PassRefPtr<MediaList> create(CSSStyleSheet* parentSheet, const String& media)
+ {
+ return adoptRef(new MediaList(parentSheet, media, false));
+ }
+
+ static PassRefPtr<MediaList> createAllowingDescriptionSyntax(const String& mediaQueryOrDescription)
+ {
+ return adoptRef(new MediaList(0, mediaQueryOrDescription, true));
+ }
+ static PassRefPtr<MediaList> createAllowingDescriptionSyntax(CSSStyleSheet* parentSheet, const String& mediaQueryOrDescription)
+ {
+ return adoptRef(new MediaList(parentSheet, mediaQueryOrDescription, true));
+ }
+
+ static PassRefPtr<MediaList> create(const String& media, bool allowDescriptionSyntax)
+ {
+ return adoptRef(new MediaList(0, media, allowDescriptionSyntax));
+ }
+
+ ~MediaList();
+
+ unsigned length() const { return m_queries.size(); }
+ String item(unsigned index) const;
+ void deleteMedium(const String& oldMedium, ExceptionCode&);
+ void appendMedium(const String& newMedium, ExceptionCode&);
+
+ String mediaText() const;
+ void setMediaText(const String&, ExceptionCode&xo);
+
+ void appendMediaQuery(PassOwnPtr<MediaQuery>);
+ const Vector<MediaQuery*>& mediaQueries() const { return m_queries; }
+
+ CSSStyleSheet* parentStyleSheet() const { return m_parentStyleSheet; }
+ void setParentStyleSheet(CSSStyleSheet* styleSheet)
+ {
+ // MediaList should never be moved between style sheets.
+ ASSERT(styleSheet == m_parentStyleSheet || !m_parentStyleSheet || !styleSheet);
+ m_parentStyleSheet = styleSheet;
+ }
+
+ int lastLine() const { return m_lastLine; }
+ void setLastLine(int lastLine) { m_lastLine = lastLine; }
+
+private:
+ MediaList(CSSStyleSheet* parentSheet, bool fallbackToDescription);
+ MediaList(CSSStyleSheet* parentSheet, const String& media, bool fallbackToDescription);
+
+ void notifyChanged();
+
+ bool m_fallback; // true if failed media query parsing should fallback to media description parsing.
+
+ CSSStyleSheet* m_parentStyleSheet;
+ Vector<MediaQuery*> m_queries;
+ int m_lastLine;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/MediaList.idl b/Source/WebCore/css/MediaList.idl
new file mode 100644
index 000000000..2b441f00a
--- /dev/null
+++ b/Source/WebCore/css/MediaList.idl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006, 2007 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 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.
+ */
+
+module stylesheets {
+
+ // Introduced in DOM Level 2:
+ interface [
+ GenerateIsReachable,
+ HasIndexGetter
+ ] MediaList {
+
+ attribute [ConvertNullToNullString, ConvertNullStringTo=Null] DOMString mediaText
+ setter raises(DOMException);
+ readonly attribute unsigned long length;
+
+ [ConvertNullStringTo=Null] DOMString item(in [Optional=CallWithDefaultValue] unsigned long index);
+ void deleteMedium(in [Optional=CallWithDefaultValue] DOMString oldMedium)
+ raises(DOMException);
+ void appendMedium(in [Optional=CallWithDefaultValue] DOMString newMedium)
+ raises(DOMException);
+
+ };
+
+}
diff --git a/Source/WebCore/css/MediaQuery.cpp b/Source/WebCore/css/MediaQuery.cpp
new file mode 100644
index 000000000..8fa5820df
--- /dev/null
+++ b/Source/WebCore/css/MediaQuery.cpp
@@ -0,0 +1,125 @@
+/*
+ * CSS Media Query
+ *
+ * Copyright (C) 2005, 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 AUTHOR ``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.
+ */
+
+#include "config.h"
+#include "MediaQuery.h"
+
+#include "MediaQueryExp.h"
+#include <wtf/NonCopyingSort.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+// http://dev.w3.org/csswg/cssom/#serialize-a-media-query
+String MediaQuery::serialize() const
+{
+ StringBuilder result;
+
+ switch (m_restrictor) {
+ case MediaQuery::Only:
+ result.append("only ");
+ break;
+ case MediaQuery::Not:
+ result.append("not ");
+ break;
+ case MediaQuery::None:
+ break;
+ }
+
+ if (m_expressions->isEmpty()) {
+ result.append(m_mediaType);
+ return result.toString();
+ }
+
+ if (m_mediaType != "all" || m_restrictor != None) {
+ result.append(m_mediaType);
+ result.append(" and ");
+ }
+
+ result.append(m_expressions->at(0)->serialize());
+ for (size_t i = 1; i < m_expressions->size(); ++i) {
+ result.append(" and ");
+ result.append(m_expressions->at(i)->serialize());
+ }
+ return result.toString();
+}
+
+static bool expressionCompare(const OwnPtr<MediaQueryExp>& a, const OwnPtr<MediaQueryExp>& b)
+{
+ return codePointCompare(a->serialize(), b->serialize()) < 0;
+}
+
+
+MediaQuery::MediaQuery(Restrictor r, const String& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > exprs)
+ : m_restrictor(r)
+ , m_mediaType(mediaType.lower())
+ , m_expressions(exprs)
+ , m_ignored(false)
+{
+ if (!m_expressions) {
+ m_expressions = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >);
+ return;
+ }
+
+ nonCopyingSort(m_expressions->begin(), m_expressions->end(), expressionCompare);
+
+ // remove all duplicated expressions
+ String key;
+ for (int i = m_expressions->size() - 1; i >= 0; --i) {
+
+ // if not all of the expressions is valid the media query must be ignored.
+ if (!m_ignored)
+ m_ignored = !m_expressions->at(i)->isValid();
+
+ if (m_expressions->at(i)->serialize() == key)
+ m_expressions->remove(i);
+ else
+ key = m_expressions->at(i)->serialize();
+ }
+}
+
+MediaQuery::~MediaQuery()
+{
+}
+
+// http://dev.w3.org/csswg/cssom/#compare-media-queries
+bool MediaQuery::operator==(const MediaQuery& other) const
+{
+ return cssText() == other.cssText();
+}
+
+// http://dev.w3.org/csswg/cssom/#serialize-a-list-of-media-queries
+String MediaQuery::cssText() const
+{
+ if (m_serializationCache.isNull())
+ const_cast<MediaQuery*>(this)->m_serializationCache = serialize();
+
+ return m_serializationCache;
+}
+
+} //namespace
diff --git a/Source/WebCore/css/MediaQuery.h b/Source/WebCore/css/MediaQuery.h
new file mode 100644
index 000000000..cb14154df
--- /dev/null
+++ b/Source/WebCore/css/MediaQuery.h
@@ -0,0 +1,71 @@
+/*
+ * CSS Media Query
+ *
+ * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 AUTHOR ``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 MediaQuery_h
+#define MediaQuery_h
+
+#include "PlatformString.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+class MediaQueryExp;
+
+class MediaQuery {
+ WTF_MAKE_NONCOPYABLE(MediaQuery); WTF_MAKE_FAST_ALLOCATED;
+public:
+ enum Restrictor {
+ Only, Not, None
+ };
+
+ typedef Vector<OwnPtr<MediaQueryExp> > ExpressionVector;
+
+ MediaQuery(Restrictor, const String& mediaType, PassOwnPtr<ExpressionVector> exprs);
+ ~MediaQuery();
+
+ Restrictor restrictor() const { return m_restrictor; }
+ const Vector<OwnPtr<MediaQueryExp> >* expressions() const { return m_expressions.get(); }
+ String mediaType() const { return m_mediaType; }
+ bool operator==(const MediaQuery& other) const;
+ String cssText() const;
+ bool ignored() const { return m_ignored; }
+
+ private:
+ Restrictor m_restrictor;
+ String m_mediaType;
+ OwnPtr<ExpressionVector> m_expressions;
+ bool m_ignored;
+ String m_serializationCache;
+
+ String serialize() const;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp
new file mode 100644
index 000000000..64d493392
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryEvaluator.cpp
@@ -0,0 +1,566 @@
+/*
+ * CSS Media Query Evaluator
+ *
+ * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ *
+ * 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 AUTHOR ``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.
+ */
+
+#include "config.h"
+#include "MediaQueryEvaluator.h"
+
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSStyleSelector.h"
+#include "CSSValueList.h"
+#include "FloatRect.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "IntRect.h"
+#include "MediaFeatureNames.h"
+#include "MediaList.h"
+#include "MediaQuery.h"
+#include "MediaQueryExp.h"
+#include "NodeRenderStyle.h"
+#include "Page.h"
+#include "RenderView.h"
+#include "RenderStyle.h"
+#include "PlatformScreen.h"
+#include <wtf/HashMap.h>
+
+#if ENABLE(3D_RENDERING) && USE(ACCELERATED_COMPOSITING)
+#include "RenderLayerCompositor.h"
+#endif
+
+namespace WebCore {
+
+using namespace MediaFeatureNames;
+
+enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix };
+
+typedef bool (*EvalFunc)(CSSValue*, RenderStyle*, Frame*, MediaFeaturePrefix);
+typedef HashMap<AtomicStringImpl*, EvalFunc> FunctionMap;
+static FunctionMap* gFunctionMap;
+
+/*
+ * FIXME: following media features are not implemented: color_index, scan, resolution
+ *
+ * color_index, min-color-index, max_color_index: It's unknown how to retrieve
+ * the information if the display mode is indexed
+ * scan: The "scan" media feature describes the scanning process of
+ * tv output devices. It's unknown how to retrieve this information from
+ * the platform
+ * resolution, min-resolution, max-resolution: css parser doesn't seem to
+ * support CSS_DIMENSION
+ */
+
+MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult)
+ : m_frame(0)
+ , m_style(0)
+ , m_expResult(mediaFeatureResult)
+{
+}
+
+MediaQueryEvaluator:: MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult)
+ : m_mediaType(acceptedMediaType)
+ , m_frame(0)
+ , m_style(0)
+ , m_expResult(mediaFeatureResult)
+{
+}
+
+MediaQueryEvaluator:: MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult)
+ : m_mediaType(acceptedMediaType)
+ , m_frame(0)
+ , m_style(0)
+ , m_expResult(mediaFeatureResult)
+{
+}
+
+MediaQueryEvaluator:: MediaQueryEvaluator(const String& acceptedMediaType, Frame* frame, RenderStyle* style)
+ : m_mediaType(acceptedMediaType)
+ , m_frame(frame)
+ , m_style(style)
+ , m_expResult(false) // doesn't matter when we have m_frame and m_style
+{
+}
+
+MediaQueryEvaluator::~MediaQueryEvaluator()
+{
+}
+
+bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const
+{
+ return mediaTypeToMatch.isEmpty()
+ || equalIgnoringCase(mediaTypeToMatch, "all")
+ || equalIgnoringCase(mediaTypeToMatch, m_mediaType);
+}
+
+bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) const
+{
+ // Like mediaTypeMatch, but without the special cases for "" and "all".
+ ASSERT(mediaTypeToMatch);
+ ASSERT(mediaTypeToMatch[0] != '\0');
+ ASSERT(!equalIgnoringCase(mediaTypeToMatch, String("all")));
+ return equalIgnoringCase(mediaTypeToMatch, m_mediaType);
+}
+
+static bool applyRestrictor(MediaQuery::Restrictor r, bool value)
+{
+ return r == MediaQuery::Not ? !value : value;
+}
+
+bool MediaQueryEvaluator::eval(const MediaList* mediaList, CSSStyleSelector* styleSelector) const
+{
+ if (!mediaList)
+ return true;
+
+ const Vector<MediaQuery*>& queries = mediaList->mediaQueries();
+ if (!queries.size())
+ return true; // empty query list evaluates to true
+
+ // iterate over queries, stop if any of them eval to true (OR semantics)
+ bool result = false;
+ for (size_t i = 0; i < queries.size() && !result; ++i) {
+ MediaQuery* query = queries.at(i);
+
+ if (query->ignored())
+ continue;
+
+ if (mediaTypeMatch(query->mediaType())) {
+ const Vector<OwnPtr<MediaQueryExp> >* exps = query->expressions();
+ // iterate through expressions, stop if any of them eval to false
+ // (AND semantics)
+ size_t j = 0;
+ for (; j < exps->size(); ++j) {
+ bool exprResult = eval(exps->at(j).get());
+ if (styleSelector && exps->at(j)->isViewportDependent())
+ styleSelector->addViewportDependentMediaQueryResult(exps->at(j).get(), exprResult);
+ if (!exprResult)
+ break;
+ }
+
+ // assume true if we are at the end of the list,
+ // otherwise assume false
+ result = applyRestrictor(query->restrictor(), exps->size() == j);
+ } else
+ result = applyRestrictor(query->restrictor(), false);
+ }
+
+ return result;
+}
+
+static bool parseAspectRatio(CSSValue* value, int& h, int& v)
+{
+ if (value->isValueList()) {
+ CSSValueList* valueList = static_cast<CSSValueList*>(value);
+ if (valueList->length() == 3) {
+ 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) {
+ String str = static_cast<CSSPrimitiveValue*>(i1)->getStringValue();
+ if (!str.isNull() && str.length() == 1 && str[0] == '/') {
+ h = static_cast<CSSPrimitiveValue*>(i0)->getIntValue(CSSPrimitiveValue::CSS_NUMBER);
+ v = static_cast<CSSPrimitiveValue*>(i2)->getIntValue(CSSPrimitiveValue::CSS_NUMBER);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+template<typename T>
+bool compareValue(T a, T b, MediaFeaturePrefix op)
+{
+ switch (op) {
+ case MinPrefix:
+ return a >= b;
+ case MaxPrefix:
+ return a <= b;
+ case NoPrefix:
+ return a == b;
+ }
+ return false;
+}
+
+static bool numberValue(CSSValue* value, float& result)
+{
+ if (value->isPrimitiveValue()
+ && static_cast<CSSPrimitiveValue*>(value)->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
+ result = static_cast<CSSPrimitiveValue*>(value)->getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
+ return true;
+ }
+ return false;
+}
+
+static bool colorMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+{
+ int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame()->view());
+ float number;
+ if (value)
+ return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op);
+
+ return bitsPerComponent != 0;
+}
+
+static bool monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+{
+ if (!screenIsMonochrome(frame->page()->mainFrame()->view())) {
+ if (value) {
+ float number;
+ return numberValue(value, number) && compareValue(0, static_cast<int>(number), op);
+ }
+ return false;
+ }
+
+ return colorMediaFeatureEval(value, style, frame, op);
+}
+
+static bool orientationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix)
+{
+ // A missing parameter should fail
+ if (!value)
+ return false;
+
+ FrameView* view = frame->view();
+ int width = view->layoutWidth();
+ int height = view->layoutHeight();
+ if (width > height) // Square viewport is portrait
+ return "landscape" == static_cast<CSSPrimitiveValue*>(value)->getStringValue();
+ return "portrait" == static_cast<CSSPrimitiveValue*>(value)->getStringValue();
+}
+
+static bool aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+{
+ if (value) {
+ FrameView* view = frame->view();
+ int width = view->layoutWidth();
+ int height = view->layoutHeight();
+ int h = 0;
+ int v = 0;
+ if (parseAspectRatio(value, h, v))
+ return v != 0 && compareValue(width * v, height * h, op);
+ return false;
+ }
+
+ // ({,min-,max-}aspect-ratio)
+ // assume if we have a device, its aspect ratio is non-zero
+ return true;
+}
+
+static bool device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+{
+ if (value) {
+ FloatRect sg = screenRect(frame->page()->mainFrame()->view());
+ int h = 0;
+ int v = 0;
+ if (parseAspectRatio(value, h, v))
+ return v != 0 && compareValue(static_cast<int>(sg.width()) * v, static_cast<int>(sg.height()) * h, op);
+ return false;
+ }
+
+ // ({,min-,max-}device-aspect-ratio)
+ // assume if we have a device, its aspect ratio is non-zero
+ return true;
+}
+
+static bool device_pixel_ratioMediaFeatureEval(CSSValue *value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+{
+ if (value)
+ return value->isPrimitiveValue() && compareValue(frame->page()->deviceScaleFactor(), static_cast<CSSPrimitiveValue*>(value)->getFloatValue(), op);
+
+ return frame->page()->deviceScaleFactor() != 0;
+}
+
+static bool gridMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+{
+ // if output device is bitmap, grid: 0 == true
+ // assume we have bitmap device
+ float number;
+ if (value && numberValue(value, number))
+ return compareValue(static_cast<int>(number), 0, op);
+ return false;
+}
+
+static bool computeLength(CSSValue* value, bool strict, RenderStyle* style, RenderStyle* rootStyle, int& result)
+{
+ if (!value->isPrimitiveValue())
+ return false;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
+ result = primitiveValue->getIntValue();
+ return !strict || !result;
+ }
+
+ if (primitiveValue->isLength()) {
+ result = primitiveValue->computeLength<int>(style, rootStyle);
+ return true;
+ }
+
+ return false;
+}
+
+static bool device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+{
+ if (value) {
+ 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);
+ }
+ // ({,min-,max-}device-height)
+ // assume if we have a device, assume non-zero
+ return true;
+}
+
+static bool device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+{
+ if (value) {
+ 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);
+ }
+ // ({,min-,max-}device-width)
+ // assume if we have a device, assume non-zero
+ return true;
+}
+
+static bool heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+{
+ FrameView* view = frame->view();
+
+ if (value) {
+ RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
+ int length;
+ return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(view->layoutHeight(), length, op);
+ }
+
+ return view->layoutHeight() != 0;
+}
+
+static bool widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op)
+{
+ FrameView* view = frame->view();
+
+ if (value) {
+ RenderStyle* rootStyle = frame->document()->documentElement()->renderStyle();
+ int length;
+ return computeLength(value, !frame->document()->inQuirksMode(), style, rootStyle, length) && compareValue(view->layoutWidth(), length, op);
+ }
+
+ return view->layoutWidth() != 0;
+}
+
+// rest of the functions are trampolines which set the prefix according to the media feature expression used
+
+static bool min_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return colorMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_colorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return colorMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return monochromeMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return monochromeMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_aspect_ratioMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_aspect_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_pixel_ratioMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_device_pixel_ratioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_pixel_ratioMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return heightMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return heightMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return widthMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return widthMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_heightMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_device_heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_heightMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool min_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_widthMediaFeatureEval(value, style, frame, MinPrefix);
+}
+
+static bool max_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix)
+{
+ return device_widthMediaFeatureEval(value, style, frame, MaxPrefix);
+}
+
+static bool animationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+{
+ if (value) {
+ float number;
+ return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
+ }
+ return true;
+}
+
+static bool transitionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+{
+ if (value) {
+ float number;
+ return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
+ }
+ return true;
+}
+
+static bool transform_2dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op)
+{
+ if (value) {
+ float number;
+ return numberValue(value, number) && compareValue(1, static_cast<int>(number), op);
+ }
+ return true;
+}
+
+static bool transform_3dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+{
+ bool returnValueIfNoParameter;
+ int have3dRendering;
+
+#if ENABLE(3D_RENDERING)
+ bool threeDEnabled = false;
+#if USE(ACCELERATED_COMPOSITING)
+ if (RenderView* view = frame->contentRenderer())
+ threeDEnabled = view->compositor()->canRender3DTransforms();
+#endif
+
+ returnValueIfNoParameter = threeDEnabled;
+ have3dRendering = threeDEnabled ? 1 : 0;
+#else
+ UNUSED_PARAM(frame);
+ returnValueIfNoParameter = false;
+ have3dRendering = 0;
+#endif
+
+ if (value) {
+ float number;
+ return numberValue(value, number) && compareValue(have3dRendering, static_cast<int>(number), op);
+ }
+ return returnValueIfNoParameter;
+}
+
+static bool view_modeMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
+{
+ UNUSED_PARAM(op);
+ if (!value)
+ return true;
+ return Page::stringToViewMode(static_cast<CSSPrimitiveValue*>(value)->getStringValue()) == frame->page()->viewMode();
+}
+
+static void createFunctionMap()
+{
+ // Create the table.
+ gFunctionMap = new FunctionMap;
+#define ADD_TO_FUNCTIONMAP(name, str) \
+ gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval);
+ CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
+#undef ADD_TO_FUNCTIONMAP
+}
+
+bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
+{
+ if (!m_frame || !m_style)
+ return m_expResult;
+
+ if (!expr->isValid())
+ return false;
+
+ if (!gFunctionMap)
+ createFunctionMap();
+
+ // call the media feature evaluation function. Assume no prefix
+ // and let trampoline functions override the prefix if prefix is
+ // used
+ EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
+ if (func)
+ return func(expr->value(), m_style.get(), m_frame, NoPrefix);
+
+ return false;
+}
+
+} // namespace
diff --git a/Source/WebCore/css/MediaQueryEvaluator.h b/Source/WebCore/css/MediaQueryEvaluator.h
new file mode 100644
index 000000000..ba838f207
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryEvaluator.h
@@ -0,0 +1,91 @@
+/*
+ * CSS Media Query Evaluator
+ *
+ * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ *
+ * 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 AUTHOR ``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 MediaQueryEvaluator_h
+#define MediaQueryEvaluator_h
+
+#include "PlatformString.h"
+
+namespace WebCore {
+class CSSStyleSelector;
+class Frame;
+class RenderStyle;
+class MediaList;
+class MediaQueryExp;
+
+/**
+ * Class that evaluates css media queries as defined in
+ * CSS3 Module "Media Queries" (http://www.w3.org/TR/css3-mediaqueries/)
+ * Special constructors are needed, if simple media queries are to be
+ * evaluated without knowledge of the medium features. This can happen
+ * for example when parsing UA stylesheets, if evaluation is done
+ * right after parsing.
+ *
+ * the boolean parameter is used to approximate results of evaluation, if
+ * the device characteristics are not known. This can be used to prune the loading
+ * of stylesheets to only those which are probable to match.
+ */
+class MediaQueryEvaluator {
+ WTF_MAKE_NONCOPYABLE(MediaQueryEvaluator); WTF_MAKE_FAST_ALLOCATED;
+public:
+ /** Creates evaluator which evaluates only simple media queries
+ * Evaluator returns true for "all", and returns value of \mediaFeatureResult
+ * for any media features
+ */
+ MediaQueryEvaluator(bool mediaFeatureResult = false);
+
+ /** Creates evaluator which evaluates only simple media queries
+ * Evaluator returns true for acceptedMediaType and returns value of \mediafeatureResult
+ * for any media features
+ */
+ MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult = false);
+ MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult = false);
+
+ /** Creates evaluator which evaluates full media queries
+ */
+ MediaQueryEvaluator(const String& acceptedMediaType, Frame*, RenderStyle*);
+
+ ~MediaQueryEvaluator();
+
+ bool mediaTypeMatch(const String& mediaTypeToMatch) const;
+ bool mediaTypeMatchSpecific(const char* mediaTypeToMatch) const;
+
+ /** Evaluates a list of media queries */
+ bool eval(const MediaList*, CSSStyleSelector* = 0) const;
+
+ /** Evaluates media query subexpression, ie "and (media-feature: value)" part */
+ bool eval(const MediaQueryExp*) const;
+
+private:
+ String m_mediaType;
+ Frame* m_frame; // not owned
+ RefPtr<RenderStyle> m_style;
+ bool m_expResult;
+};
+
+} // namespace
+#endif
diff --git a/Source/WebCore/css/MediaQueryExp.cpp b/Source/WebCore/css/MediaQueryExp.cpp
new file mode 100644
index 000000000..1f5322183
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryExp.cpp
@@ -0,0 +1,111 @@
+/*
+ * CSS Media Query
+ *
+ * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 AUTHOR ``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.
+ */
+
+#include "config.h"
+#include "MediaQueryExp.h"
+
+#include "CSSParser.h"
+#include "CSSPrimitiveValue.h"
+#include "CSSValueList.h"
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+inline MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* valueList)
+ : m_mediaFeature(mediaFeature)
+ , m_value(0)
+ , m_isValid(true)
+{
+ if (valueList) {
+ if (valueList->size() == 1) {
+ CSSParserValue* value = valueList->current();
+
+ if (value->id != 0)
+ m_value = CSSPrimitiveValue::createIdentifier(value->id);
+ else if (value->unit == CSSPrimitiveValue::CSS_STRING)
+ m_value = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
+ else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER &&
+ value->unit <= CSSPrimitiveValue::CSS_KHZ)
+ m_value = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
+
+ valueList->next();
+ } else if (valueList->size() > 1) {
+ // create list of values
+ // currently accepts only <integer>/<integer>
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ CSSParserValue* value = 0;
+ bool isValid = true;
+
+ while ((value = valueList->current()) && isValid) {
+ if (value->unit == CSSParserValue::Operator && value->iValue == '/')
+ list->append(CSSPrimitiveValue::create("/", CSSPrimitiveValue::CSS_STRING));
+ else if (value->unit == CSSPrimitiveValue::CSS_NUMBER)
+ list->append(CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER));
+ else
+ isValid = false;
+
+ value = valueList->next();
+ }
+
+ if (isValid)
+ m_value = list.release();
+ }
+ m_isValid = m_value;
+ }
+}
+
+
+PassOwnPtr<MediaQueryExp> MediaQueryExp::create(const AtomicString& mediaFeature, CSSParserValueList* values)
+{
+ return adoptPtr(new MediaQueryExp(mediaFeature, values));
+}
+
+MediaQueryExp::~MediaQueryExp()
+{
+}
+
+String MediaQueryExp::serialize() const
+{
+ if (!m_serializationCache.isNull())
+ return m_serializationCache;
+
+ StringBuilder result;
+ result.append("(");
+ result.append(m_mediaFeature.lower());
+ if (m_value) {
+ result.append(": ");
+ result.append(m_value->cssText());
+ }
+ result.append(")");
+
+ const_cast<MediaQueryExp*>(this)->m_serializationCache = result.toString();
+ return m_serializationCache;
+}
+
+} // namespace
diff --git a/Source/WebCore/css/MediaQueryExp.h b/Source/WebCore/css/MediaQueryExp.h
new file mode 100644
index 000000000..feb61c084
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryExp.h
@@ -0,0 +1,84 @@
+/*
+ * CSS Media Query
+ *
+ * Copyright (C) 2006 Kimmo Kinnunen <kimmo.t.kinnunen@nokia.com>.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 AUTHOR ``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 MediaQueryExp_h
+#define MediaQueryExp_h
+
+#include "CSSValue.h"
+#include "MediaFeatureNames.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+class CSSParserValueList;
+
+class MediaQueryExp {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ static PassOwnPtr<MediaQueryExp> create(const AtomicString& mediaFeature, CSSParserValueList* values);
+ ~MediaQueryExp();
+
+ AtomicString mediaFeature() const { return m_mediaFeature; }
+
+ CSSValue* value() const { return m_value.get(); }
+
+ bool operator==(const MediaQueryExp& other) const
+ {
+ return (other.m_mediaFeature == m_mediaFeature)
+ && ((!other.m_value && !m_value)
+ || (other.m_value && m_value && other.m_value->cssText() == m_value->cssText()));
+ }
+
+ bool isValid() const { return m_isValid; }
+
+ bool isViewportDependent() const { return m_mediaFeature == MediaFeatureNames::widthMediaFeature
+ || m_mediaFeature == MediaFeatureNames::heightMediaFeature
+ || m_mediaFeature == MediaFeatureNames::min_widthMediaFeature
+ || m_mediaFeature == MediaFeatureNames::min_heightMediaFeature
+ || m_mediaFeature == MediaFeatureNames::max_widthMediaFeature
+ || m_mediaFeature == MediaFeatureNames::max_heightMediaFeature
+ || m_mediaFeature == MediaFeatureNames::orientationMediaFeature
+ || m_mediaFeature == MediaFeatureNames::aspect_ratioMediaFeature
+ || m_mediaFeature == MediaFeatureNames::min_aspect_ratioMediaFeature
+ || m_mediaFeature == MediaFeatureNames::max_aspect_ratioMediaFeature; }
+
+ String serialize() const;
+
+private:
+ MediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values);
+
+ AtomicString m_mediaFeature;
+ RefPtr<CSSValue> m_value;
+ bool m_isValid;
+ String m_serializationCache;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/MediaQueryList.cpp b/Source/WebCore/css/MediaQueryList.cpp
new file mode 100644
index 000000000..aa3ef60d8
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryList.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 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 "MediaQueryList.h"
+
+#include "MediaList.h"
+#include "MediaQueryEvaluator.h"
+#include "MediaQueryListListener.h"
+#include "MediaQueryMatcher.h"
+
+namespace WebCore {
+
+PassRefPtr<MediaQueryList> MediaQueryList::create(PassRefPtr<MediaQueryMatcher> vector, PassRefPtr<MediaList> media, bool matches)
+{
+ return adoptRef(new MediaQueryList(vector, media, matches));
+}
+
+MediaQueryList::MediaQueryList(PassRefPtr<MediaQueryMatcher> vector, PassRefPtr<MediaList> media, bool matches)
+ : m_matcher(vector)
+ , m_media(media)
+ , m_evaluationRound(m_matcher->evaluationRound())
+ , m_changeRound(m_evaluationRound - 1) // m_evaluationRound and m_changeRound initial values must be different.
+ , m_matches(matches)
+{
+}
+
+MediaQueryList::~MediaQueryList()
+{
+}
+
+String MediaQueryList::media() const
+{
+ return m_media->mediaText();
+}
+
+void MediaQueryList::addListener(PassRefPtr<MediaQueryListListener> listener)
+{
+ if (!listener)
+ return;
+
+ m_matcher->addListener(listener, this);
+}
+
+void MediaQueryList::removeListener(PassRefPtr<MediaQueryListListener> listener)
+{
+ if (!listener)
+ return;
+
+ m_matcher->removeListener(listener.get(), this);
+}
+
+void MediaQueryList::evaluate(MediaQueryEvaluator* evaluator, bool& notificationNeeded)
+{
+ if (m_evaluationRound != m_matcher->evaluationRound() && evaluator)
+ setMatches(evaluator->eval(m_media.get()));
+ notificationNeeded = m_changeRound == m_matcher->evaluationRound();
+}
+
+void MediaQueryList::setMatches(bool newValue)
+{
+ m_evaluationRound = m_matcher->evaluationRound();
+
+ if (newValue == m_matches)
+ return;
+
+ m_matches = newValue;
+ m_changeRound = m_evaluationRound;
+}
+
+bool MediaQueryList::matches()
+{
+ if (m_evaluationRound != m_matcher->evaluationRound())
+ setMatches(m_matcher->evaluate(m_media.get()));
+ return m_matches;
+}
+
+}
diff --git a/Source/WebCore/css/MediaQueryList.h b/Source/WebCore/css/MediaQueryList.h
new file mode 100644
index 000000000..8ff498859
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryList.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 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 MediaQueryList_h
+#define MediaQueryList_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class MediaList;
+class MediaQueryListListener;
+class MediaQueryEvaluator;
+class MediaQueryMatcher;
+
+// MediaQueryList interface is specified at http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface
+// The objects of this class are returned by window.matchMedia. They may be used to
+// retrieve the current value of the given media query and to add/remove listeners that
+// will be called whenever the value of the query changes.
+
+class MediaQueryList : public RefCounted<MediaQueryList> {
+public:
+ static PassRefPtr<MediaQueryList> create(PassRefPtr<MediaQueryMatcher>, PassRefPtr<MediaList>, bool);
+ ~MediaQueryList();
+
+ String media() const;
+ bool matches();
+
+ void addListener(PassRefPtr<MediaQueryListListener>);
+ void removeListener(PassRefPtr<MediaQueryListListener>);
+
+ void evaluate(MediaQueryEvaluator*, bool& notificationNeeded);
+
+private:
+ MediaQueryList(PassRefPtr<MediaQueryMatcher>, PassRefPtr<MediaList>, bool matches);
+ void setMatches(bool);
+
+ RefPtr<MediaQueryMatcher> m_matcher;
+ RefPtr<MediaList> m_media;
+ unsigned m_evaluationRound; // Indicates if the query has been evaluated after the last style selector change.
+ unsigned m_changeRound; // Used to know if the query has changed in the last style selector change.
+ bool m_matches;
+};
+
+}
+
+#endif // MediaQueryList_h
diff --git a/Source/WebCore/css/MediaQueryList.idl b/Source/WebCore/css/MediaQueryList.idl
new file mode 100644
index 000000000..0d8b1f22d
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryList.idl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+module view {
+ interface MediaQueryList {
+ readonly attribute DOMString media;
+ readonly attribute boolean matches;
+ void addListener(in [Optional=CallWithDefaultValue] MediaQueryListListener listener);
+ void removeListener(in [Optional=CallWithDefaultValue] MediaQueryListListener listener);
+ };
+}
diff --git a/Source/WebCore/css/MediaQueryListListener.cpp b/Source/WebCore/css/MediaQueryListListener.cpp
new file mode 100644
index 000000000..6f86bc2a4
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryListListener.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 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 "MediaQueryListListener.h"
+
+#include "MediaQueryList.h"
+#include "ScriptFunctionCall.h"
+
+#if USE(JSC)
+#include "JSMediaQueryList.h"
+#else
+#include "V8MediaQueryList.h"
+#endif
+
+namespace WebCore {
+
+void MediaQueryListListener::queryChanged(ScriptState* state, MediaQueryList* query)
+{
+ ScriptCallback callback(state, m_value);
+#if USE(JSC)
+ callback.appendArgument(toJS(state, deprecatedGlobalObjectForPrototype(state), query));
+#else
+ v8::HandleScope handleScope;
+ v8::Handle<v8::Context> context = state->context();
+ if (context.IsEmpty())
+ return; // JS may not be enabled.
+ v8::Context::Scope scope(context);
+ callback.appendArgument(toV8(query));
+#endif
+ callback.call();
+}
+
+}
diff --git a/Source/WebCore/css/MediaQueryListListener.h b/Source/WebCore/css/MediaQueryListListener.h
new file mode 100644
index 000000000..de62683c0
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryListListener.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 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 MediaQueryListListener_h
+#define MediaQueryListListener_h
+
+#include "PlatformString.h"
+#include "ScriptState.h"
+#include "ScriptValue.h"
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class MediaQueryList;
+
+// See http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface
+
+class MediaQueryListListener : public RefCounted<MediaQueryListListener> {
+public:
+ static PassRefPtr<MediaQueryListListener> create(ScriptValue value)
+ {
+ if (!value.isFunction())
+ return 0;
+ return adoptRef(new MediaQueryListListener(value));
+ }
+ void queryChanged(ScriptState*, MediaQueryList*);
+
+ bool operator==(const MediaQueryListListener& other) const { return m_value == other.m_value; }
+
+private:
+ MediaQueryListListener(ScriptValue value) : m_value(value) { }
+
+ ScriptValue m_value;
+};
+
+}
+
+#endif // MediaQueryListListener_h
diff --git a/Source/WebCore/css/MediaQueryListListener.idl b/Source/WebCore/css/MediaQueryListListener.idl
new file mode 100644
index 000000000..dfe659b0d
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryListListener.idl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+module view {
+ interface [
+ NoStaticTables,
+ ObjCProtocol,
+ PureInterface,
+ OmitConstructor
+ ] MediaQueryListListener {
+ void queryChanged(in [Optional=CallWithDefaultValue] MediaQueryList list);
+ };
+}
diff --git a/Source/WebCore/css/MediaQueryMatcher.cpp b/Source/WebCore/css/MediaQueryMatcher.cpp
new file mode 100644
index 000000000..a5f35dd77
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryMatcher.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2010 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 "MediaQueryMatcher.h"
+
+#include "CSSStyleSelector.h"
+#include "Document.h"
+#include "Element.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "MediaList.h"
+#include "MediaQueryEvaluator.h"
+#include "MediaQueryList.h"
+#include "MediaQueryListListener.h"
+
+namespace WebCore {
+
+MediaQueryMatcher::Listener::Listener(PassRefPtr<MediaQueryListListener> listener, PassRefPtr<MediaQueryList> query)
+ : m_listener(listener)
+ , m_query(query)
+{
+}
+
+MediaQueryMatcher::Listener::~Listener()
+{
+}
+
+void MediaQueryMatcher::Listener::evaluate(ScriptState* state, MediaQueryEvaluator* evaluator)
+{
+ bool notify;
+ m_query->evaluate(evaluator, notify);
+ if (notify)
+ m_listener->queryChanged(state, m_query.get());
+}
+
+MediaQueryMatcher::MediaQueryMatcher(Document* document)
+ : m_document(document)
+ , m_evaluationRound(1)
+{
+ ASSERT(m_document);
+}
+
+MediaQueryMatcher::~MediaQueryMatcher()
+{
+}
+
+void MediaQueryMatcher::documentDestroyed()
+{
+ m_listeners.clear();
+ m_document = 0;
+}
+
+String MediaQueryMatcher::mediaType() const
+{
+ if (!m_document || !m_document->frame() || !m_document->frame()->view())
+ return String();
+
+ return m_document->frame()->view()->mediaType();
+}
+
+PassOwnPtr<MediaQueryEvaluator> MediaQueryMatcher::prepareEvaluator() const
+{
+ if (!m_document || !m_document->frame())
+ return nullptr;
+
+ Element* documentElement = m_document->documentElement();
+ if (!documentElement)
+ return nullptr;
+
+ CSSStyleSelector* styleSelector = m_document->styleSelector();
+ if (!styleSelector)
+ return nullptr;
+
+ RefPtr<RenderStyle> rootStyle = styleSelector->styleForElement(documentElement, 0 /*defaultParent*/, false /*allowSharing*/, true /*resolveForRootDefault*/);
+
+ return adoptPtr(new MediaQueryEvaluator(mediaType(), m_document->frame(), rootStyle.get()));
+}
+
+bool MediaQueryMatcher::evaluate(MediaList* media)
+{
+ if (!media)
+ return false;
+
+ OwnPtr<MediaQueryEvaluator> evaluator(prepareEvaluator());
+ return evaluator && evaluator->eval(media);
+}
+
+PassRefPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query)
+{
+ if (!m_document)
+ return 0;
+
+ RefPtr<MediaList> media = MediaList::create(query, false);
+ return MediaQueryList::create(this, media, evaluate(media.get()));
+}
+
+void MediaQueryMatcher::addListener(PassRefPtr<MediaQueryListListener> listener, PassRefPtr<MediaQueryList> query)
+{
+ if (!m_document)
+ return;
+
+ for (size_t i = 0; i < m_listeners.size(); ++i) {
+ if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query)
+ return;
+ }
+
+ m_listeners.append(adoptPtr(new Listener(listener, query)));
+}
+
+void MediaQueryMatcher::removeListener(MediaQueryListListener* listener, MediaQueryList* query)
+{
+ if (!m_document)
+ return;
+
+ for (size_t i = 0; i < m_listeners.size(); ++i) {
+ if (*m_listeners[i]->listener() == *listener && m_listeners[i]->query() == query) {
+ m_listeners.remove(i);
+ return;
+ }
+ }
+}
+
+void MediaQueryMatcher::styleSelectorChanged()
+{
+ ASSERT(m_document);
+
+ ScriptState* scriptState = mainWorldScriptState(m_document->frame());
+ if (!scriptState)
+ return;
+
+ ++m_evaluationRound;
+ OwnPtr<MediaQueryEvaluator> evaluator = prepareEvaluator();
+ if (!evaluator)
+ return;
+
+ for (size_t i = 0; i < m_listeners.size(); ++i)
+ m_listeners[i]->evaluate(scriptState, evaluator.get());
+}
+
+}
diff --git a/Source/WebCore/css/MediaQueryMatcher.h b/Source/WebCore/css/MediaQueryMatcher.h
new file mode 100644
index 000000000..96bbf8337
--- /dev/null
+++ b/Source/WebCore/css/MediaQueryMatcher.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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 MediaQueryMatcher_h
+#define MediaQueryMatcher_h
+
+#include "ScriptState.h"
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Document;
+class MediaList;
+class MediaQueryList;
+class MediaQueryListListener;
+class MediaQueryEvaluator;
+
+// MediaQueryMatcher class is responsible for keeping a vector of pairs
+// MediaQueryList x MediaQueryListListener. It is responsible for evaluating the queries
+// whenever it is needed and to call the listeners if the corresponding query has changed.
+// The listeners must be called in the very same order in which they have been added.
+
+class MediaQueryMatcher : public RefCounted<MediaQueryMatcher> {
+public:
+ static PassRefPtr<MediaQueryMatcher> create(Document* document) { return adoptRef(new MediaQueryMatcher(document)); }
+ ~MediaQueryMatcher();
+ void documentDestroyed();
+
+ void addListener(PassRefPtr<MediaQueryListListener>, PassRefPtr<MediaQueryList>);
+ void removeListener(MediaQueryListListener*, MediaQueryList*);
+
+ PassRefPtr<MediaQueryList> matchMedia(const String&);
+
+ unsigned evaluationRound() const { return m_evaluationRound; }
+ void styleSelectorChanged();
+ bool evaluate(MediaList*);
+
+private:
+ class Listener {
+ public:
+ Listener(PassRefPtr<MediaQueryListListener>, PassRefPtr<MediaQueryList>);
+ ~Listener();
+
+ void evaluate(ScriptState*, MediaQueryEvaluator*);
+
+ MediaQueryListListener* listener() { return m_listener.get(); }
+ MediaQueryList* query() { return m_query.get(); }
+
+ private:
+ RefPtr<MediaQueryListListener> m_listener;
+ RefPtr<MediaQueryList> m_query;
+ };
+
+ MediaQueryMatcher(Document*);
+ PassOwnPtr<MediaQueryEvaluator> prepareEvaluator() const;
+ String mediaType() const;
+
+ Document* m_document;
+ Vector<OwnPtr<Listener> > m_listeners;
+
+ // This value is incremented at style selector changes.
+ // It is used to avoid evaluating queries more then once and to make sure
+ // that a media query result change is notified exactly once.
+ unsigned m_evaluationRound;
+};
+
+}
+
+#endif // MediaQueryMatcher_h
diff --git a/Source/WebCore/css/Pair.h b/Source/WebCore/css/Pair.h
new file mode 100644
index 000000000..a95370dc3
--- /dev/null
+++ b/Source/WebCore/css/Pair.h
@@ -0,0 +1,63 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+ *
+ * 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 Pair_h
+#define Pair_h
+
+#include <wtf/RefCounted.h>
+#include "CSSPrimitiveValue.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+// A primitive value representing a pair. This is useful for properties like border-radius, background-size/position,
+// and border-spacing (all of which are space-separated sets of two values). At the moment we are only using it for
+// border-radius and background-size, but (FIXME) border-spacing and background-position could be converted over to use
+// it (eliminating some extra -webkit- internal properties).
+class Pair : public RefCounted<Pair> {
+public:
+ static PassRefPtr<Pair> create()
+ {
+ return adoptRef(new Pair);
+ }
+ static PassRefPtr<Pair> create(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second)
+ {
+ return adoptRef(new Pair(first, second));
+ }
+ virtual ~Pair() { }
+
+ CSSPrimitiveValue* first() const { return m_first.get(); }
+ CSSPrimitiveValue* second() const { return m_second.get(); }
+
+ void setFirst(PassRefPtr<CSSPrimitiveValue> first) { m_first = first; }
+ void setSecond(PassRefPtr<CSSPrimitiveValue> second) { m_second = second; }
+
+private:
+ Pair() : m_first(0), m_second(0) { }
+ Pair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second)
+ : m_first(first), m_second(second) { }
+
+ RefPtr<CSSPrimitiveValue> m_first;
+ RefPtr<CSSPrimitiveValue> m_second;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/RGBColor.cpp b/Source/WebCore/css/RGBColor.cpp
new file mode 100644
index 000000000..11ebfe4fa
--- /dev/null
+++ b/Source/WebCore/css/RGBColor.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008, 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2009 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 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.
+ */
+
+#include "config.h"
+#include "RGBColor.h"
+#include "CSSPrimitiveValue.h"
+
+namespace WebCore {
+
+PassRefPtr<RGBColor> RGBColor::create(unsigned rgbColor)
+{
+ return adoptRef(new RGBColor(rgbColor));
+}
+
+PassRefPtr<CSSPrimitiveValue> RGBColor::red()
+{
+ unsigned value = (m_rgbColor >> 16) & 0xFF;
+ return CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER);
+}
+
+PassRefPtr<CSSPrimitiveValue> RGBColor::green()
+{
+ unsigned value = (m_rgbColor >> 8) & 0xFF;
+ return CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER);
+}
+
+PassRefPtr<CSSPrimitiveValue> RGBColor::blue()
+{
+ unsigned value = m_rgbColor & 0xFF;
+ return CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER);
+}
+
+PassRefPtr<CSSPrimitiveValue> RGBColor::alpha()
+{
+ float value = static_cast<float>((m_rgbColor >> 24) & 0xFF) / 0xFF;
+ return WebCore::CSSPrimitiveValue::create(value, WebCore::CSSPrimitiveValue::CSS_NUMBER);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/css/RGBColor.h b/Source/WebCore/css/RGBColor.h
new file mode 100644
index 000000000..875eb3715
--- /dev/null
+++ b/Source/WebCore/css/RGBColor.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2009 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 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 RGBColor_h
+#define RGBColor_h
+
+#include "Color.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+ class CSSPrimitiveValue;
+
+ class RGBColor : public RefCounted<RGBColor> {
+ public:
+ static PassRefPtr<RGBColor> create(unsigned rgbColor);
+
+ PassRefPtr<CSSPrimitiveValue> red();
+ PassRefPtr<CSSPrimitiveValue> green();
+ PassRefPtr<CSSPrimitiveValue> blue();
+ PassRefPtr<CSSPrimitiveValue> alpha();
+
+ Color color() const { return Color(m_rgbColor); }
+
+ private:
+ RGBColor(unsigned rgbColor)
+ : m_rgbColor(rgbColor)
+ {
+ }
+
+ RGBA32 m_rgbColor;
+ };
+
+} // namespace WebCore
+
+#endif // RGBColor_h
diff --git a/Source/WebCore/css/RGBColor.idl b/Source/WebCore/css/RGBColor.idl
new file mode 100644
index 000000000..1dc87bcfd
--- /dev/null
+++ b/Source/WebCore/css/RGBColor.idl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level 2:
+ interface RGBColor {
+ readonly attribute CSSPrimitiveValue red;
+ readonly attribute CSSPrimitiveValue green;
+ readonly attribute CSSPrimitiveValue blue;
+
+ // WebKit extensions
+#if !defined(LANGUAGE_JAVASCRIPT) || !LANGUAGE_JAVASCRIPT
+ readonly attribute CSSPrimitiveValue alpha;
+#endif
+#if defined(LANGUAGE_OBJECTIVE_C) && LANGUAGE_OBJECTIVE_C
+ readonly attribute Color color;
+#endif
+ };
+
+}
diff --git a/Source/WebCore/css/Rect.h b/Source/WebCore/css/Rect.h
new file mode 100644
index 000000000..b70c6c45f
--- /dev/null
+++ b/Source/WebCore/css/Rect.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 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 Rect_h
+#define Rect_h
+
+#include "CSSPrimitiveValue.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class RectBase {
+public:
+ CSSPrimitiveValue* top() const { return m_top.get(); }
+ CSSPrimitiveValue* right() const { return m_right.get(); }
+ CSSPrimitiveValue* bottom() const { return m_bottom.get(); }
+ CSSPrimitiveValue* left() const { return m_left.get(); }
+
+ void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; }
+ void setRight(PassRefPtr<CSSPrimitiveValue> right) { m_right = right; }
+ void setBottom(PassRefPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; }
+ void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; }
+
+protected:
+ RectBase() { }
+ ~RectBase() { }
+
+private:
+ RefPtr<CSSPrimitiveValue> m_top;
+ RefPtr<CSSPrimitiveValue> m_right;
+ RefPtr<CSSPrimitiveValue> m_bottom;
+ RefPtr<CSSPrimitiveValue> m_left;
+};
+
+class Rect : public RectBase, public RefCounted<Rect> {
+public:
+ static PassRefPtr<Rect> create() { return adoptRef(new Rect); }
+
+private:
+ Rect() { }
+};
+
+class Quad : public RectBase, public RefCounted<Quad> {
+public:
+ static PassRefPtr<Quad> create() { return adoptRef(new Quad); }
+
+private:
+ Quad() { }
+};
+
+} // namespace WebCore
+
+#endif // Rect_h
diff --git a/Source/WebCore/css/Rect.idl b/Source/WebCore/css/Rect.idl
new file mode 100644
index 000000000..60eb70e31
--- /dev/null
+++ b/Source/WebCore/css/Rect.idl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2006, 2007 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.
+ */
+
+module css {
+
+ interface Rect {
+ readonly attribute CSSPrimitiveValue top;
+ readonly attribute CSSPrimitiveValue right;
+ readonly attribute CSSPrimitiveValue bottom;
+ readonly attribute CSSPrimitiveValue left;
+ };
+
+}
diff --git a/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp b/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp
new file mode 100644
index 000000000..7ef3b07d3
--- /dev/null
+++ b/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp
@@ -0,0 +1,211 @@
+/*
+ Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+
+ 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"
+
+#if ENABLE(SVG)
+#include "CSSComputedStyleDeclaration.h"
+
+#include "CSSPrimitiveValueMappings.h"
+#include "CSSPropertyNames.h"
+#include "Document.h"
+#include "RenderStyle.h"
+#include "SVGPaint.h"
+
+namespace WebCore {
+
+static PassRefPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation)
+{
+ switch (orientation) {
+ case GO_0DEG:
+ return CSSPrimitiveValue::create(0.0f, CSSPrimitiveValue::CSS_DEG);
+ case GO_90DEG:
+ return CSSPrimitiveValue::create(90.0f, CSSPrimitiveValue::CSS_DEG);
+ case GO_180DEG:
+ return CSSPrimitiveValue::create(180.0f, CSSPrimitiveValue::CSS_DEG);
+ case GO_270DEG:
+ return CSSPrimitiveValue::create(270.0f, CSSPrimitiveValue::CSS_DEG);
+ default:
+ return 0;
+ }
+}
+
+static PassRefPtr<CSSValue> strokeDashArrayToCSSValueList(const Vector<SVGLength>& dashes)
+{
+ if (dashes.isEmpty())
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+
+ RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
+ const Vector<SVGLength>::const_iterator end = dashes.end();
+ for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
+ list->append(SVGLength::toCSSPrimitiveValue(*it));
+
+ return list.release();
+}
+
+PassRefPtr<SVGPaint> CSSComputedStyleDeclaration::adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint> newPaint, RenderStyle* style) const
+{
+ RefPtr<SVGPaint> paint = newPaint;
+ if (paint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR || paint->paintType() == SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR)
+ paint->setColor(style->color());
+ return paint.release();
+}
+
+PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int propertyID, EUpdateLayout updateLayout) const
+{
+ Node* node = m_node.get();
+ if (!node)
+ return 0;
+
+ // Make sure our layout is up to date before we allow a query on these attributes.
+ if (updateLayout)
+ node->document()->updateLayout();
+
+ RenderStyle* style = node->computedStyle();
+ if (!style)
+ return 0;
+
+ const SVGRenderStyle* svgStyle = style->svgStyle();
+ if (!svgStyle)
+ return 0;
+
+ switch (static_cast<CSSPropertyID>(propertyID)) {
+ case CSSPropertyClipRule:
+ return CSSPrimitiveValue::create(svgStyle->clipRule());
+ case CSSPropertyFloodOpacity:
+ return CSSPrimitiveValue::create(svgStyle->floodOpacity(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyStopOpacity:
+ return CSSPrimitiveValue::create(svgStyle->stopOpacity(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyColorInterpolation:
+ return CSSPrimitiveValue::create(svgStyle->colorInterpolation());
+ case CSSPropertyColorInterpolationFilters:
+ return CSSPrimitiveValue::create(svgStyle->colorInterpolationFilters());
+ case CSSPropertyFillOpacity:
+ return CSSPrimitiveValue::create(svgStyle->fillOpacity(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyFillRule:
+ return CSSPrimitiveValue::create(svgStyle->fillRule());
+ case CSSPropertyColorRendering:
+ return CSSPrimitiveValue::create(svgStyle->colorRendering());
+ case CSSPropertyShapeRendering:
+ return CSSPrimitiveValue::create(svgStyle->shapeRendering());
+ case CSSPropertyStrokeLinecap:
+ return CSSPrimitiveValue::create(svgStyle->capStyle());
+ case CSSPropertyStrokeLinejoin:
+ return CSSPrimitiveValue::create(svgStyle->joinStyle());
+ case CSSPropertyStrokeMiterlimit:
+ return CSSPrimitiveValue::create(svgStyle->strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyStrokeOpacity:
+ return CSSPrimitiveValue::create(svgStyle->strokeOpacity(), CSSPrimitiveValue::CSS_NUMBER);
+ case CSSPropertyAlignmentBaseline:
+ return CSSPrimitiveValue::create(svgStyle->alignmentBaseline());
+ case CSSPropertyDominantBaseline:
+ return CSSPrimitiveValue::create(svgStyle->dominantBaseline());
+ case CSSPropertyTextAnchor:
+ return CSSPrimitiveValue::create(svgStyle->textAnchor());
+ case CSSPropertyWritingMode:
+ return CSSPrimitiveValue::create(svgStyle->writingMode());
+ case CSSPropertyClipPath:
+ if (!svgStyle->clipperResource().isEmpty())
+ return CSSPrimitiveValue::create(svgStyle->clipperResource(), CSSPrimitiveValue::CSS_URI);
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+ case CSSPropertyMask:
+ if (!svgStyle->maskerResource().isEmpty())
+ return CSSPrimitiveValue::create(svgStyle->maskerResource(), CSSPrimitiveValue::CSS_URI);
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+ case CSSPropertyFilter:
+ if (!svgStyle->filterResource().isEmpty())
+ return CSSPrimitiveValue::create(svgStyle->filterResource(), CSSPrimitiveValue::CSS_URI);
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+ case CSSPropertyFloodColor:
+ return currentColorOrValidColor(style, svgStyle->floodColor());
+ case CSSPropertyLightingColor:
+ return currentColorOrValidColor(style, svgStyle->lightingColor());
+ case CSSPropertyStopColor:
+ return currentColorOrValidColor(style, svgStyle->stopColor());
+ case CSSPropertyFill:
+ return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle->fillPaintType(), svgStyle->fillPaintUri(), svgStyle->fillPaintColor()), style);
+ case CSSPropertyKerning:
+ return SVGLength::toCSSPrimitiveValue(svgStyle->kerning());
+ case CSSPropertyMarkerEnd:
+ if (!svgStyle->markerEndResource().isEmpty())
+ return CSSPrimitiveValue::create(svgStyle->markerEndResource(), CSSPrimitiveValue::CSS_URI);
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+ case CSSPropertyMarkerMid:
+ if (!svgStyle->markerMidResource().isEmpty())
+ return CSSPrimitiveValue::create(svgStyle->markerMidResource(), CSSPrimitiveValue::CSS_URI);
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+ case CSSPropertyMarkerStart:
+ if (!svgStyle->markerStartResource().isEmpty())
+ return CSSPrimitiveValue::create(svgStyle->markerStartResource(), CSSPrimitiveValue::CSS_URI);
+ return CSSPrimitiveValue::createIdentifier(CSSValueNone);
+ case CSSPropertyStroke:
+ return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle->strokePaintType(), svgStyle->strokePaintUri(), svgStyle->strokePaintColor()), style);
+ case CSSPropertyStrokeDasharray:
+ return strokeDashArrayToCSSValueList(svgStyle->strokeDashArray());
+ case CSSPropertyStrokeDashoffset:
+ return SVGLength::toCSSPrimitiveValue(svgStyle->strokeDashOffset());
+ case CSSPropertyStrokeWidth:
+ return SVGLength::toCSSPrimitiveValue(svgStyle->strokeWidth());
+ case CSSPropertyBaselineShift: {
+ switch (svgStyle->baselineShift()) {
+ case BS_BASELINE:
+ return CSSPrimitiveValue::createIdentifier(CSSValueBaseline);
+ case BS_SUPER:
+ return CSSPrimitiveValue::createIdentifier(CSSValueSuper);
+ case BS_SUB:
+ return CSSPrimitiveValue::createIdentifier(CSSValueSub);
+ case BS_LENGTH:
+ return SVGLength::toCSSPrimitiveValue(svgStyle->baselineShiftValue());
+ }
+ }
+ case CSSPropertyGlyphOrientationHorizontal:
+ return glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationHorizontal());
+ case CSSPropertyGlyphOrientationVertical: {
+ if (RefPtr<CSSPrimitiveValue> value = glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationVertical()))
+ return value.release();
+
+ if (svgStyle->glyphOrientationVertical() == GO_AUTO)
+ return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
+
+ return 0;
+ }
+ case CSSPropertyWebkitSvgShadow:
+ return valueForShadow(svgStyle->shadow(), propertyID, style);
+ case CSSPropertyVectorEffect:
+ return CSSPrimitiveValue::create(svgStyle->vectorEffect());
+ case CSSPropertyMarker:
+ case CSSPropertyEnableBackground:
+ case CSSPropertyColorProfile:
+ // the above properties are not yet implemented in the engine
+ break;
+ default:
+ // If you crash here, it's because you added a css property and are not handling it
+ // in either this switch statement or the one in CSSComputedStyleDelcaration::getPropertyCSSValue
+ ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propertyID);
+ }
+ LOG_ERROR("unimplemented propertyID: %d", propertyID);
+ return 0;
+}
+
+}
+
+#endif // ENABLE(SVG)
+
+// vim:ts=4:noet
diff --git a/Source/WebCore/css/SVGCSSParser.cpp b/Source/WebCore/css/SVGCSSParser.cpp
new file mode 100644
index 000000000..dd738fb3c
--- /dev/null
+++ b/Source/WebCore/css/SVGCSSParser.cpp
@@ -0,0 +1,366 @@
+/*
+ Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ 2004, 2005, 2007, 2010 Rob Buis <buis@kde.org>
+ Copyright (C) 2005, 2006 Apple Computer, Inc.
+
+ 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"
+
+#if ENABLE(SVG)
+#include "CSSInheritedValue.h"
+#include "CSSInitialValue.h"
+#include "CSSParser.h"
+#include "CSSProperty.h"
+#include "CSSPropertyNames.h"
+#include "CSSValueKeywords.h"
+#include "CSSValueList.h"
+#include "RenderTheme.h"
+#include "SVGPaint.h"
+
+using namespace std;
+
+namespace WebCore {
+
+bool CSSParser::parseSVGValue(int propId, bool important)
+{
+ CSSParserValue* value = m_valueList->current();
+ if (!value)
+ return false;
+
+ int id = value->id;
+
+ bool valid_primitive = false;
+ RefPtr<CSSValue> parsedValue;
+
+ switch (propId) {
+ /* The comment to the right defines all valid value of these
+ * properties as defined in SVG 1.1, Appendix N. Property index */
+ case CSSPropertyAlignmentBaseline:
+ // auto | baseline | before-edge | text-before-edge | middle |
+ // central | after-edge | text-after-edge | ideographic | alphabetic |
+ // hanging | mathematical | inherit
+ if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle ||
+ (id >= CSSValueBeforeEdge && id <= CSSValueMathematical))
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyBaselineShift:
+ // baseline | super | sub | <percentage> | <length> | inherit
+ if (id == CSSValueBaseline || id == CSSValueSub ||
+ id >= CSSValueSuper)
+ valid_primitive = true;
+ else
+ valid_primitive = validUnit(value, FLength|FPercent, false);
+ break;
+
+ case CSSPropertyDominantBaseline:
+ // auto | use-script | no-change | reset-size | ideographic |
+ // alphabetic | hanging | mathematical | central | middle |
+ // text-after-edge | text-before-edge | inherit
+ if (id == CSSValueAuto || id == CSSValueMiddle ||
+ (id >= CSSValueUseScript && id <= CSSValueResetSize) ||
+ (id >= CSSValueCentral && id <= CSSValueMathematical))
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyEnableBackground:
+ // accumulate | new [x] [y] [width] [height] | inherit
+ if (id == CSSValueAccumulate) // TODO : new
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyMarkerStart:
+ case CSSPropertyMarkerMid:
+ case CSSPropertyMarkerEnd:
+ case CSSPropertyMask:
+ if (id == CSSValueNone)
+ valid_primitive = true;
+ else if (value->unit == CSSPrimitiveValue::CSS_URI) {
+ parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI);
+ if (parsedValue)
+ m_valueList->next();
+ }
+ break;
+
+ case CSSPropertyClipRule: // nonzero | evenodd | inherit
+ case CSSPropertyFillRule:
+ if (id == CSSValueNonzero || id == CSSValueEvenodd)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit
+ valid_primitive = validUnit(value, FNumber|FNonNeg, false);
+ break;
+
+ case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit
+ if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyStrokeLinecap: // butt | round | square | inherit
+ if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyStrokeOpacity: // <opacity-value> | inherit
+ case CSSPropertyFillOpacity:
+ case CSSPropertyStopOpacity:
+ case CSSPropertyFloodOpacity:
+ valid_primitive = (!id && validUnit(value, FNumber|FPercent, false));
+ break;
+
+ case CSSPropertyShapeRendering:
+ // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit
+ if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
+ id == CSSValueCrispedges || id == CSSValueGeometricprecision)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyImageRendering: // auto | optimizeSpeed |
+ case CSSPropertyColorRendering: // optimizeQuality | inherit
+ if (id == CSSValueAuto || id == CSSValueOptimizespeed ||
+ id == CSSValueOptimizequality)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit
+ if (id == CSSValueAuto || id == CSSValueSrgb)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit
+ case CSSPropertyColorInterpolationFilters:
+ if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb)
+ valid_primitive = true;
+ break;
+
+ /* Start of supported CSS properties with validation. This is needed for parseShortHand to work
+ * correctly and allows optimization in applyRule(..)
+ */
+
+ case CSSPropertyTextAnchor: // start | middle | end | inherit
+ if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit
+ if (id == CSSValueAuto) {
+ valid_primitive = true;
+ break;
+ }
+ /* fallthrough intentional */
+ case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit
+ if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) {
+ parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_DEG);
+
+ if (parsedValue)
+ m_valueList->next();
+ }
+ break;
+
+ case CSSPropertyFill: // <paint> | inherit
+ case CSSPropertyStroke: // <paint> | inherit
+ {
+ if (id == CSSValueNone)
+ parsedValue = SVGPaint::createNone();
+ else if (id == CSSValueCurrentcolor)
+ parsedValue = SVGPaint::createCurrentColor();
+ else if ((id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu)
+ parsedValue = SVGPaint::createColor(RenderTheme::defaultTheme()->systemColor(id));
+ else if (value->unit == CSSPrimitiveValue::CSS_URI) {
+ RGBA32 c = Color::transparent;
+ if (m_valueList->next()) {
+ if (parseColorFromValue(m_valueList->current(), c))
+ parsedValue = SVGPaint::createURIAndColor(value->string, c);
+ else if (m_valueList->current()->id == CSSValueNone)
+ parsedValue = SVGPaint::createURIAndNone(value->string);
+ }
+ if (!parsedValue)
+ parsedValue = SVGPaint::createURI(value->string);
+ } else
+ parsedValue = parseSVGPaint();
+
+ if (parsedValue)
+ m_valueList->next();
+ }
+ break;
+
+ case CSSPropertyColor: // <color> | inherit
+ if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
+ (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
+ parsedValue = SVGColor::createFromString(value->string);
+ else
+ parsedValue = parseSVGColor();
+
+ if (parsedValue)
+ m_valueList->next();
+ break;
+
+ case CSSPropertyStopColor: // TODO : icccolor
+ case CSSPropertyFloodColor:
+ case CSSPropertyLightingColor:
+ if ((id >= CSSValueAqua && id <= CSSValueWindowtext) ||
+ (id >= CSSValueAliceblue && id <= CSSValueYellowgreen))
+ parsedValue = SVGColor::createFromString(value->string);
+ else if (id == CSSValueCurrentcolor)
+ parsedValue = SVGColor::createCurrentColor();
+ else // TODO : svgcolor (iccColor)
+ parsedValue = parseSVGColor();
+
+ if (parsedValue)
+ m_valueList->next();
+
+ break;
+
+ case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit
+ if (id == CSSValueNone || id == CSSValueNonScalingStroke)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyWritingMode:
+ // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit
+ if (id == CSSValueLrTb || id == CSSValueRlTb || id == CSSValueTbRl || id == CSSValueLr || id == CSSValueRl || id == CSSValueTb)
+ valid_primitive = true;
+ break;
+
+ case CSSPropertyStrokeWidth: // <length> | inherit
+ case CSSPropertyStrokeDashoffset:
+ valid_primitive = validUnit(value, FLength | FPercent, false);
+ break;
+ case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit
+ if (id == CSSValueNone)
+ valid_primitive = true;
+ else
+ parsedValue = parseSVGStrokeDasharray();
+
+ break;
+
+ case CSSPropertyKerning: // auto | normal | <length> | inherit
+ if (id == CSSValueAuto || id == CSSValueNormal)
+ valid_primitive = true;
+ else
+ valid_primitive = validUnit(value, FLength, false);
+ break;
+
+ case CSSPropertyClipPath: // <uri> | none | inherit
+ case CSSPropertyFilter:
+ if (id == CSSValueNone)
+ valid_primitive = true;
+ else if (value->unit == CSSPrimitiveValue::CSS_URI) {
+ parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
+ if (parsedValue)
+ m_valueList->next();
+ }
+ break;
+ case CSSPropertyWebkitSvgShadow:
+ if (id == CSSValueNone)
+ valid_primitive = true;
+ else {
+ RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId);
+ if (shadowValueList) {
+ addProperty(propId, shadowValueList.release(), important);
+ m_valueList->next();
+ return true;
+ }
+ return false;
+ }
+
+ /* shorthand properties */
+ case CSSPropertyMarker:
+ {
+ ShorthandScope scope(this, propId);
+ m_implicitShorthand = true;
+ if (!parseValue(CSSPropertyMarkerStart, important))
+ return false;
+ if (m_valueList->current()) {
+ rollbackLastProperties(1);
+ return false;
+ }
+ CSSValue* value = m_parsedProperties[m_numParsedProperties - 1]->value();
+ addProperty(CSSPropertyMarkerMid, value, important);
+ addProperty(CSSPropertyMarkerEnd, value, important);
+ m_implicitShorthand = false;
+ return true;
+ }
+ default:
+ // If you crash here, it's because you added a css property and are not handling it
+ // in either this switch statement or the one in CSSParser::parseValue
+ ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId);
+ return false;
+ }
+
+ if (valid_primitive) {
+ if (id != 0)
+ parsedValue = CSSPrimitiveValue::createIdentifier(id);
+ else if (value->unit == CSSPrimitiveValue::CSS_STRING)
+ parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit);
+ else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
+ parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit);
+ else if (value->unit >= CSSParserValue::Q_EMS)
+ parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS);
+ m_valueList->next();
+ }
+ if (!parsedValue || (m_valueList->current() && !inShorthand()))
+ return false;
+
+ addProperty(propId, parsedValue.release(), important);
+ return true;
+}
+
+PassRefPtr<CSSValue> CSSParser::parseSVGStrokeDasharray()
+{
+ RefPtr<CSSValueList> ret = CSSValueList::createCommaSeparated();
+ CSSParserValue* value = m_valueList->current();
+ bool valid_primitive = true;
+ while (value) {
+ valid_primitive = validUnit(value, FLength | FPercent |FNonNeg, false);
+ if (!valid_primitive)
+ break;
+ if (value->id != 0)
+ ret->append(CSSPrimitiveValue::createIdentifier(value->id));
+ else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
+ ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit));
+ value = m_valueList->next();
+ if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
+ value = m_valueList->next();
+ }
+ if (!valid_primitive)
+ return 0;
+ return ret.release();
+}
+
+PassRefPtr<CSSValue> CSSParser::parseSVGPaint()
+{
+ RGBA32 c = Color::transparent;
+ if (!parseColorFromValue(m_valueList->current(), c))
+ return SVGPaint::createUnknown();
+ return SVGPaint::createColor(Color(c));
+}
+
+PassRefPtr<CSSValue> CSSParser::parseSVGColor()
+{
+ RGBA32 c = Color::transparent;
+ if (!parseColorFromValue(m_valueList->current(), c))
+ return 0;
+ return SVGColor::createFromColor(Color(c));
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/WebCore/css/SVGCSSPropertyNames.in b/Source/WebCore/css/SVGCSSPropertyNames.in
new file mode 100644
index 000000000..8c8c1544f
--- /dev/null
+++ b/Source/WebCore/css/SVGCSSPropertyNames.in
@@ -0,0 +1,51 @@
+//
+// all valid SVG CSS2 properties.
+//
+
+// SVG style props
+clip-path
+clip-rule
+mask
+// opacity
+enable-background
+filter
+flood-color
+flood-opacity
+lighting-color
+stop-color
+stop-opacity
+// pointer-events
+color-interpolation
+color-interpolation-filters
+color-profile
+color-rendering
+fill
+fill-opacity
+fill-rule
+//font-size-adjust
+//image-rendering
+marker
+marker-end
+marker-mid
+marker-start
+shape-rendering
+stroke
+stroke-dasharray
+stroke-dashoffset
+stroke-linecap
+stroke-linejoin
+stroke-miterlimit
+stroke-opacity
+stroke-width
+// text-rendering
+alignment-baseline
+baseline-shift
+dominant-baseline
+glyph-orientation-horizontal
+glyph-orientation-vertical
+kerning
+text-anchor
+vector-effect
+writing-mode
+
+-webkit-svg-shadow
diff --git a/Source/WebCore/css/SVGCSSStyleSelector.cpp b/Source/WebCore/css/SVGCSSStyleSelector.cpp
new file mode 100644
index 000000000..318d72b73
--- /dev/null
+++ b/Source/WebCore/css/SVGCSSStyleSelector.cpp
@@ -0,0 +1,607 @@
+/*
+ Copyright (C) 2005 Apple Computer, Inc.
+ Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ 2004, 2005, 2008 Rob Buis <buis@kde.org>
+ Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+
+ Based on khtml css code by:
+ Copyright(C) 1999-2003 Lars Knoll(knoll@kde.org)
+ (C) 2003 Apple Computer, Inc.
+ (C) 2004 Allan Sandfeld Jensen(kde@carewolf.com)
+ (C) 2004 Germain Garand(germain@ebooksfrance.org)
+
+ 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"
+
+#if ENABLE(SVG)
+#include "CSSStyleSelector.h"
+
+#include "CSSPrimitiveValueMappings.h"
+#include "CSSPropertyNames.h"
+#include "CSSValueList.h"
+#include "Document.h"
+#include "ShadowValue.h"
+#include "SVGColor.h"
+#include "SVGNames.h"
+#include "SVGPaint.h"
+#include "SVGRenderStyle.h"
+#include "SVGRenderStyleDefs.h"
+#include "SVGStyledElement.h"
+#include "SVGURIReference.h"
+#include <stdlib.h>
+#include <wtf/MathExtras.h>
+
+#define HANDLE_INHERIT(prop, Prop) \
+if (isInherit) \
+{ \
+ svgstyle->set##Prop(m_parentStyle->svgStyle()->prop()); \
+ return; \
+}
+
+#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
+HANDLE_INHERIT(prop, Prop) \
+if (isInitial) { \
+ svgstyle->set##Prop(SVGRenderStyle::initial##Prop()); \
+ return; \
+}
+
+namespace WebCore {
+
+static float roundToNearestGlyphOrientationAngle(float angle)
+{
+ angle = fabsf(fmodf(angle, 360.0f));
+
+ if (angle <= 45.0f || angle > 315.0f)
+ return 0.0f;
+ else if (angle > 45.0f && angle <= 135.0f)
+ return 90.0f;
+ else if (angle > 135.0f && angle <= 225.0f)
+ return 180.0f;
+
+ return 270.0f;
+}
+
+static int angleToGlyphOrientation(float angle)
+{
+ angle = roundToNearestGlyphOrientationAngle(angle);
+
+ if (angle == 0.0f)
+ return GO_0DEG;
+ else if (angle == 90.0f)
+ return GO_90DEG;
+ else if (angle == 180.0f)
+ return GO_180DEG;
+ else if (angle == 270.0f)
+ return GO_270DEG;
+
+ return -1;
+}
+
+static Color colorFromSVGColorCSSValue(SVGColor* svgColor, const Color& fgColor)
+{
+ Color color;
+ if (svgColor->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR)
+ color = fgColor;
+ else
+ color = svgColor->color();
+ return color;
+}
+
+void CSSStyleSelector::applySVGProperty(int id, CSSValue* value)
+{
+ ASSERT(value);
+ CSSPrimitiveValue* primitiveValue = 0;
+ if (value->isPrimitiveValue())
+ primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+
+ SVGRenderStyle* svgstyle = m_style->accessSVGStyle();
+
+ bool isInherit = m_parentNode && value->isInheritedValue();
+ bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
+
+ // What follows is a list that maps the CSS properties into their
+ // corresponding front-end RenderStyle values. Shorthands(e.g. border,
+ // background) occur in this list as well and are only hit when mapping
+ // "inherit" or "initial" into front-end values.
+ switch (id)
+ {
+ // ident only properties
+ case CSSPropertyAlignmentBaseline:
+ {
+ HANDLE_INHERIT_AND_INITIAL(alignmentBaseline, AlignmentBaseline)
+ if (!primitiveValue)
+ break;
+
+ svgstyle->setAlignmentBaseline(*primitiveValue);
+ break;
+ }
+ case CSSPropertyBaselineShift:
+ {
+ HANDLE_INHERIT_AND_INITIAL(baselineShift, BaselineShift);
+ if (!primitiveValue)
+ break;
+
+ if (primitiveValue->getIdent()) {
+ switch (primitiveValue->getIdent()) {
+ case CSSValueBaseline:
+ svgstyle->setBaselineShift(BS_BASELINE);
+ break;
+ case CSSValueSub:
+ svgstyle->setBaselineShift(BS_SUB);
+ break;
+ case CSSValueSuper:
+ svgstyle->setBaselineShift(BS_SUPER);
+ break;
+ default:
+ break;
+ }
+ } else {
+ svgstyle->setBaselineShift(BS_LENGTH);
+ svgstyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue));
+ }
+
+ break;
+ }
+ case CSSPropertyKerning:
+ {
+ HANDLE_INHERIT_AND_INITIAL(kerning, Kerning);
+ if (primitiveValue)
+ svgstyle->setKerning(SVGLength::fromCSSPrimitiveValue(primitiveValue));
+ break;
+ }
+ case CSSPropertyDominantBaseline:
+ {
+ HANDLE_INHERIT_AND_INITIAL(dominantBaseline, DominantBaseline)
+ if (primitiveValue)
+ svgstyle->setDominantBaseline(*primitiveValue);
+ break;
+ }
+ case CSSPropertyColorInterpolation:
+ {
+ HANDLE_INHERIT_AND_INITIAL(colorInterpolation, ColorInterpolation)
+ if (primitiveValue)
+ svgstyle->setColorInterpolation(*primitiveValue);
+ break;
+ }
+ case CSSPropertyColorInterpolationFilters:
+ {
+ HANDLE_INHERIT_AND_INITIAL(colorInterpolationFilters, ColorInterpolationFilters)
+ if (primitiveValue)
+ svgstyle->setColorInterpolationFilters(*primitiveValue);
+ break;
+ }
+ case CSSPropertyColorRendering:
+ {
+ HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering)
+ if (primitiveValue)
+ svgstyle->setColorRendering(*primitiveValue);
+ break;
+ }
+ case CSSPropertyClipRule:
+ {
+ HANDLE_INHERIT_AND_INITIAL(clipRule, ClipRule)
+ if (primitiveValue)
+ svgstyle->setClipRule(*primitiveValue);
+ break;
+ }
+ case CSSPropertyFillRule:
+ {
+ HANDLE_INHERIT_AND_INITIAL(fillRule, FillRule)
+ if (primitiveValue)
+ svgstyle->setFillRule(*primitiveValue);
+ break;
+ }
+ case CSSPropertyStrokeLinejoin:
+ {
+ HANDLE_INHERIT_AND_INITIAL(joinStyle, JoinStyle)
+ if (primitiveValue)
+ svgstyle->setJoinStyle(*primitiveValue);
+ break;
+ }
+ case CSSPropertyShapeRendering:
+ {
+ HANDLE_INHERIT_AND_INITIAL(shapeRendering, ShapeRendering)
+ if (primitiveValue)
+ svgstyle->setShapeRendering(*primitiveValue);
+ break;
+ }
+ // end of ident only properties
+ case CSSPropertyFill:
+ {
+ if (isInherit) {
+ const SVGRenderStyle* svgParentStyle = m_parentStyle->svgStyle();
+ svgstyle->setFillPaint(svgParentStyle->fillPaintType(), svgParentStyle->fillPaintColor(), svgParentStyle->fillPaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
+ return;
+ }
+ if (isInitial) {
+ svgstyle->setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRenderStyle::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
+ return;
+ }
+ if (value->isSVGPaint()) {
+ SVGPaint* svgPaint = static_cast<SVGPaint*>(value);
+ svgstyle->setFillPaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, m_style->color()), svgPaint->uri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
+ }
+ break;
+ }
+ case CSSPropertyStroke:
+ {
+ if (isInherit) {
+ const SVGRenderStyle* svgParentStyle = m_parentStyle->svgStyle();
+ svgstyle->setStrokePaint(svgParentStyle->strokePaintType(), svgParentStyle->strokePaintColor(), svgParentStyle->strokePaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
+ return;
+ }
+ if (isInitial) {
+ svgstyle->setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRenderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
+ return;
+ }
+ if (value->isSVGPaint()) {
+ SVGPaint* svgPaint = static_cast<SVGPaint*>(value);
+ svgstyle->setStrokePaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, m_style->color()), svgPaint->uri(), applyPropertyToRegularStyle(), applyPropertyToVisitedLinkStyle());
+ }
+ break;
+ }
+ case CSSPropertyStrokeWidth:
+ {
+ HANDLE_INHERIT_AND_INITIAL(strokeWidth, StrokeWidth)
+ if (primitiveValue)
+ svgstyle->setStrokeWidth(SVGLength::fromCSSPrimitiveValue(primitiveValue));
+ break;
+ }
+ case CSSPropertyStrokeDasharray:
+ {
+ HANDLE_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray)
+ if (!value->isValueList()) {
+ svgstyle->setStrokeDashArray(SVGRenderStyle::initialStrokeDashArray());
+ break;
+ }
+
+ CSSValueList* dashes = static_cast<CSSValueList*>(value);
+
+ Vector<SVGLength> array;
+ size_t length = dashes->length();
+ for (size_t i = 0; i < length; ++i) {
+ CSSValue* currValue = dashes->itemWithoutBoundsCheck(i);
+ if (!currValue->isPrimitiveValue())
+ continue;
+
+ CSSPrimitiveValue* dash = static_cast<CSSPrimitiveValue*>(dashes->itemWithoutBoundsCheck(i));
+ array.append(SVGLength::fromCSSPrimitiveValue(dash));
+ }
+
+ svgstyle->setStrokeDashArray(array);
+ break;
+ }
+ case CSSPropertyStrokeDashoffset:
+ {
+ HANDLE_INHERIT_AND_INITIAL(strokeDashOffset, StrokeDashOffset)
+ if (primitiveValue)
+ svgstyle->setStrokeDashOffset(SVGLength::fromCSSPrimitiveValue(primitiveValue));
+ break;
+ }
+ case CSSPropertyFillOpacity:
+ {
+ HANDLE_INHERIT_AND_INITIAL(fillOpacity, FillOpacity)
+ if (!primitiveValue)
+ return;
+
+ float f = 0.0f;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ f = primitiveValue->getFloatValue() / 100.0f;
+ else if (type == CSSPrimitiveValue::CSS_NUMBER)
+ f = primitiveValue->getFloatValue();
+ else
+ return;
+
+ svgstyle->setFillOpacity(f);
+ break;
+ }
+ case CSSPropertyStrokeOpacity:
+ {
+ HANDLE_INHERIT_AND_INITIAL(strokeOpacity, StrokeOpacity)
+ if (!primitiveValue)
+ return;
+
+ float f = 0.0f;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ f = primitiveValue->getFloatValue() / 100.0f;
+ else if (type == CSSPrimitiveValue::CSS_NUMBER)
+ f = primitiveValue->getFloatValue();
+ else
+ return;
+
+ svgstyle->setStrokeOpacity(f);
+ break;
+ }
+ case CSSPropertyStopOpacity:
+ {
+ HANDLE_INHERIT_AND_INITIAL(stopOpacity, StopOpacity)
+ if (!primitiveValue)
+ return;
+
+ float f = 0.0f;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ f = primitiveValue->getFloatValue() / 100.0f;
+ else if (type == CSSPrimitiveValue::CSS_NUMBER)
+ f = primitiveValue->getFloatValue();
+ else
+ return;
+
+ svgstyle->setStopOpacity(f);
+ break;
+ }
+ case CSSPropertyMarkerStart:
+ {
+ HANDLE_INHERIT_AND_INITIAL(markerStartResource, MarkerStartResource)
+ if (!primitiveValue)
+ return;
+
+ String s;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI)
+ s = primitiveValue->getStringValue();
+ else
+ return;
+
+ svgstyle->setMarkerStartResource(SVGURIReference::fragmentIdentifierFromIRIString(s, m_element->document()));
+ break;
+ }
+ case CSSPropertyMarkerMid:
+ {
+ HANDLE_INHERIT_AND_INITIAL(markerMidResource, MarkerMidResource)
+ if (!primitiveValue)
+ return;
+
+ String s;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI)
+ s = primitiveValue->getStringValue();
+ else
+ return;
+
+ svgstyle->setMarkerMidResource(SVGURIReference::fragmentIdentifierFromIRIString(s, m_element->document()));
+ break;
+ }
+ case CSSPropertyMarkerEnd:
+ {
+ HANDLE_INHERIT_AND_INITIAL(markerEndResource, MarkerEndResource)
+ if (!primitiveValue)
+ return;
+
+ String s;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI)
+ s = primitiveValue->getStringValue();
+ else
+ return;
+
+ svgstyle->setMarkerEndResource(SVGURIReference::fragmentIdentifierFromIRIString(s, m_element->document()));
+ break;
+ }
+ case CSSPropertyStrokeLinecap:
+ {
+ HANDLE_INHERIT_AND_INITIAL(capStyle, CapStyle)
+ if (primitiveValue)
+ svgstyle->setCapStyle(*primitiveValue);
+ break;
+ }
+ case CSSPropertyStrokeMiterlimit:
+ {
+ HANDLE_INHERIT_AND_INITIAL(strokeMiterLimit, StrokeMiterLimit)
+ if (!primitiveValue)
+ return;
+
+ float f = 0.0f;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_NUMBER)
+ f = primitiveValue->getFloatValue();
+ else
+ return;
+
+ svgstyle->setStrokeMiterLimit(f);
+ break;
+ }
+ case CSSPropertyFilter:
+ {
+ HANDLE_INHERIT_AND_INITIAL(filterResource, FilterResource)
+ if (!primitiveValue)
+ return;
+
+ String s;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI)
+ s = primitiveValue->getStringValue();
+ else
+ return;
+
+ svgstyle->setFilterResource(SVGURIReference::fragmentIdentifierFromIRIString(s, m_element->document()));
+ break;
+ }
+ case CSSPropertyMask:
+ {
+ HANDLE_INHERIT_AND_INITIAL(maskerResource, MaskerResource)
+ if (!primitiveValue)
+ return;
+
+ String s;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI)
+ s = primitiveValue->getStringValue();
+ else
+ return;
+
+ svgstyle->setMaskerResource(SVGURIReference::fragmentIdentifierFromIRIString(s, m_element->document()));
+ break;
+ }
+ case CSSPropertyClipPath:
+ {
+ HANDLE_INHERIT_AND_INITIAL(clipperResource, ClipperResource)
+ if (!primitiveValue)
+ return;
+
+ String s;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_URI)
+ s = primitiveValue->getStringValue();
+ else
+ return;
+
+ svgstyle->setClipperResource(SVGURIReference::fragmentIdentifierFromIRIString(s, m_element->document()));
+ break;
+ }
+ case CSSPropertyTextAnchor:
+ {
+ HANDLE_INHERIT_AND_INITIAL(textAnchor, TextAnchor)
+ if (primitiveValue)
+ svgstyle->setTextAnchor(*primitiveValue);
+ break;
+ }
+ case CSSPropertyWritingMode:
+ {
+ HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode)
+ if (primitiveValue)
+ svgstyle->setWritingMode(*primitiveValue);
+ break;
+ }
+ case CSSPropertyStopColor:
+ {
+ HANDLE_INHERIT_AND_INITIAL(stopColor, StopColor);
+ if (value->isSVGColor())
+ svgstyle->setStopColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
+ break;
+ }
+ case CSSPropertyLightingColor:
+ {
+ HANDLE_INHERIT_AND_INITIAL(lightingColor, LightingColor);
+ if (value->isSVGColor())
+ svgstyle->setLightingColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
+ break;
+ }
+ case CSSPropertyFloodOpacity:
+ {
+ HANDLE_INHERIT_AND_INITIAL(floodOpacity, FloodOpacity)
+ if (!primitiveValue)
+ return;
+
+ float f = 0.0f;
+ int type = primitiveValue->primitiveType();
+ if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+ f = primitiveValue->getFloatValue() / 100.0f;
+ else if (type == CSSPrimitiveValue::CSS_NUMBER)
+ f = primitiveValue->getFloatValue();
+ else
+ return;
+
+ svgstyle->setFloodOpacity(f);
+ break;
+ }
+ case CSSPropertyFloodColor:
+ {
+ HANDLE_INHERIT_AND_INITIAL(floodColor, FloodColor);
+ if (value->isSVGColor())
+ svgstyle->setFloodColor(colorFromSVGColorCSSValue(static_cast<SVGColor*>(value), m_style->color()));
+ break;
+ }
+ case CSSPropertyGlyphOrientationHorizontal:
+ {
+ HANDLE_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal)
+ if (!primitiveValue)
+ return;
+
+ if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
+ int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
+ ASSERT(orientation != -1);
+
+ svgstyle->setGlyphOrientationHorizontal((EGlyphOrientation) orientation);
+ }
+
+ break;
+ }
+ case CSSPropertyGlyphOrientationVertical:
+ {
+ HANDLE_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical)
+ if (!primitiveValue)
+ return;
+
+ if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_DEG) {
+ int orientation = angleToGlyphOrientation(primitiveValue->getFloatValue());
+ ASSERT(orientation != -1);
+
+ svgstyle->setGlyphOrientationVertical((EGlyphOrientation) orientation);
+ } else if (primitiveValue->getIdent() == CSSValueAuto)
+ svgstyle->setGlyphOrientationVertical(GO_AUTO);
+
+ break;
+ }
+ case CSSPropertyEnableBackground:
+ // Silently ignoring this property for now
+ // http://bugs.webkit.org/show_bug.cgi?id=6022
+ break;
+ case CSSPropertyWebkitSvgShadow: {
+ if (isInherit)
+ return svgstyle->setShadow(adoptPtr(m_parentStyle->svgStyle()->shadow() ? new ShadowData(*m_parentStyle->svgStyle()->shadow()) : 0));
+ if (isInitial || primitiveValue) // initial | none
+ return svgstyle->setShadow(nullptr);
+
+ if (!value->isValueList())
+ return;
+
+ CSSValueList *list = static_cast<CSSValueList*>(value);
+ if (!list->length())
+ return;
+
+ CSSValue* firstValue = list->itemWithoutBoundsCheck(0);
+ if (!firstValue->isShadowValue())
+ return;
+ ShadowValue* item = static_cast<ShadowValue*>(firstValue);
+ int x = item->x->computeLength<int>(style(), m_rootElementStyle);
+ int y = item->y->computeLength<int>(style(), m_rootElementStyle);
+ int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle) : 0;
+ Color color;
+ if (item->color)
+ color = colorFromPrimitiveValue(item->color.get());
+
+ // -webkit-svg-shadow does should not have a spread or style
+ ASSERT(!item->spread);
+ ASSERT(!item->style);
+
+ OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(x, y, blur, 0, Normal, false, color.isValid() ? color : Color::transparent));
+ svgstyle->setShadow(shadowData.release());
+ return;
+ }
+ case CSSPropertyVectorEffect: {
+ HANDLE_INHERIT_AND_INITIAL(vectorEffect, VectorEffect)
+ if (!primitiveValue)
+ break;
+
+ svgstyle->setVectorEffect(*primitiveValue);
+ break;
+ }
+ default:
+ // If you crash here, it's because you added a css property and are not handling it
+ // in either this switch statement or the one in CSSStyleSelector::applyProperty
+ ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", id);
+ return;
+ }
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/css/SVGCSSValueKeywords.in b/Source/WebCore/css/SVGCSSValueKeywords.in
new file mode 100644
index 000000000..4fac4baf8
--- /dev/null
+++ b/Source/WebCore/css/SVGCSSValueKeywords.in
@@ -0,0 +1,277 @@
+// These are all values accepted for CSS2.
+//
+// WARNING:
+// --------
+//
+// The Values are sorted according to the properties they belong to,
+// and have to be in the same order as the enums in RenderStyle.h.
+//
+// If not, the optimizations in the cssparser and style selector will fail,
+// and produce incorrect results.
+//
+//
+// CSS_PROP_*_COLOR
+//
+aliceblue
+antiquewhite
+// aqua
+aquamarine
+azure
+beige
+bisque
+// black
+blanchedalmond
+// blue
+blueviolet
+brown
+burlywood
+cadetblue
+chartreuse
+chocolate
+coral
+cornflowerblue
+cornsilk
+crimson
+cyan
+darkblue
+darkcyan
+darkgoldenrod
+darkgray
+darkgreen
+darkgrey
+darkkhaki
+darkmagenta
+darkolivegreen
+darkorange
+darkorchid
+darkred
+darksalmon
+darkseagreen
+darkslateblue
+darkslategray
+darkslategrey
+darkturquoise
+darkviolet
+deeppink
+deepskyblue
+dimgray
+dimgrey
+dodgerblue
+firebrick
+floralwhite
+forestgreen
+// fuchsia
+gainsboro
+ghostwhite
+gold
+goldenrod
+// gray
+// grey
+// green
+greenyellow
+honeydew
+hotpink
+indianred
+indigo
+ivory
+khaki
+lavender
+lavenderblush
+lawngreen
+lemonchiffon
+lightblue
+lightcoral
+lightcyan
+lightgoldenrodyellow
+lightgray
+lightgreen
+lightgrey
+lightpink
+lightsalmon
+lightseagreen
+lightskyblue
+lightslategray
+lightslategrey
+lightsteelblue
+lightyellow
+// lime
+limegreen
+linen
+magenta
+// maroon
+mediumaquamarine
+mediumblue
+mediumorchid
+mediumpurple
+mediumseagreen
+mediumslateblue
+mediumspringgreen
+mediumturquoise
+mediumvioletred
+midnightblue
+mintcream
+mistyrose
+moccasin
+navajowhite
+// navy
+oldlace
+// olive
+olivedrab
+// orange
+orangered
+orchid
+palegoldenrod
+palegreen
+paleturquoise
+palevioletred
+papayawhip
+peachpuff
+peru
+pink
+plum
+powderblue
+// purple
+// red
+rosybrown
+royalblue
+saddlebrown
+salmon
+sandybrown
+seagreen
+seashell
+sienna
+// silver
+skyblue
+slateblue
+slategray
+slategrey
+snow
+springgreen
+steelblue
+tan
+// teal
+thistle
+tomato
+turquoise
+violet
+wheat
+// white
+whitesmoke
+// yellow
+yellowgreen
+
+// CSS_PROP_CLIP_PATH
+// CSS_PROP_CLIP_RULE
+// nonzero and evenodd part of core CSS values now.
+
+// CSS_PROP_MASK
+// CSS_PROP_OPACITY
+// CSS_PROP_ENABLE_BACKGROUND
+accumulate
+new
+
+// CSS_PROP_FILTER
+// CSS_PROP_FLOOD_COLOR
+//currentColor
+
+// CSS_PROP_FLOOD_OPACITY
+// CSS_PROP_LIGHTING_COLOR
+//currentColor
+
+// CSS_PROP_STOP_COLOR
+// CSS_PROP_STOP_OPACITY
+// CSS_PROP_COLOR_INTERPOLATION
+//auto
+//sRGB
+linearRGB
+
+// CSS_PROP_COLOR_INTERPOLATION_FILTERS
+//auto
+//sRGB
+//linearRGB
+
+// CSS_PROP_COLOR_PROFILE
+//sRGB
+
+// CSS_PROP_COLOR_RENDERING
+//auto
+//optimizeSpeed
+//optimizeQuality
+
+//// CSS_PROP_FILL
+//currentColor
+
+// CSS_PROP_FILL_OPACITY
+// CSS_PROP_FILL_RULE
+//nonzero
+//evenodd
+
+// CSS_PROP_IMAGE_RENDERING
+//auto
+//optimizeSpeed
+//optimizeQuality
+
+// CSS_PROP_MARKER
+// CSS_PROP_MARKER_END
+// CSS_PROP_MARKER_MID
+// CSS_PROP_MARKER_START
+// CSS_PROP_SHAPE_RENDERING
+//auto
+//optimizeSpeed
+crispEdges
+//geometricPrecision
+
+// CSS_PROP_STROKE
+// CSS_PROP_STROKE_DASHARRAY
+// CSS_PROP_STROKE_DASHOFFSET
+// CSS_PROP_STROKE_LINECAP
+butt
+// round
+// square
+
+// CSS_PROP_STROKE_LINEJOIN
+miter
+// round
+bevel
+
+// CSS_PROP_STROKE_MITERLIMIT
+// CSS_PROP_STROKE_OPACITY
+// CSS_PROP_STROKE_WIDTH
+
+// CSS_PROP_ALIGNMENT_BASELINE
+//auto
+// baseline
+before-edge
+after-edge
+//middle
+central
+text-before-edge
+text-after-edge
+ideographic
+alphabetic
+hanging
+mathematical
+
+// CSS_PROP_BASELINE_SHIFT
+//baseline
+// sub
+// super
+
+// CSS_PROP_DOMINANT_BASELINE
+//auto
+use-script
+no-change
+reset-size
+
+// CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL
+
+// CSS_PROP_GLYPH_ORIENTATION_VERTICAL
+// CSS_PROP_KERNING
+// CSS_PROP_TEXT_ANCHOR
+// start
+// middle
+// end
+
+// CSS_PROP_VECTOR_EFFECT
+// none
+non-scaling-stroke
diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp
new file mode 100644
index 000000000..f74eed02c
--- /dev/null
+++ b/Source/WebCore/css/SelectorChecker.cpp
@@ -0,0 +1,1428 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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 "SelectorChecker.h"
+
+#include "CSSSelector.h"
+#include "CSSSelectorList.h"
+#include "Document.h"
+#include "FocusController.h"
+#include "Frame.h"
+#include "FrameSelection.h"
+#include "HTMLAnchorElement.h"
+#include "HTMLFrameElementBase.h"
+#include "HTMLInputElement.h"
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "HTMLProgressElement.h"
+#include "InspectorInstrumentation.h"
+#include "NodeRenderStyle.h"
+#include "Page.h"
+#include "PageGroup.h"
+#include "RenderObject.h"
+#include "RenderScrollbar.h"
+#include "RenderStyle.h"
+#include "ScrollableArea.h"
+#include "ScrollbarTheme.h"
+#include "StyledElement.h"
+#include "Text.h"
+
+#if USE(PLATFORM_STRATEGIES)
+#include "PlatformStrategies.h"
+#include "VisitedLinkStrategy.h"
+#endif
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "XLinkNames.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr);
+
+SelectorChecker::SelectorChecker(Document* document, bool strictParsing)
+ : m_document(document)
+ , m_strictParsing(strictParsing)
+ , m_documentIsHTML(document->isHTMLDocument())
+ , m_isCollectingRulesOnly(false)
+ , m_pseudoStyle(NOPSEUDO)
+ , m_hasUnknownPseudoElements(false)
+{
+}
+
+// Salt to separate otherwise identical string hashes so a class-selector like .article won't match <article> elements.
+enum { TagNameSalt = 13, IdAttributeSalt = 17, ClassAttributeSalt = 19 };
+
+static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes)
+{
+ identifierHashes.append(element->localName().impl()->existingHash() * TagNameSalt);
+ if (element->hasID())
+ identifierHashes.append(element->idForStyleResolution().impl()->existingHash() * IdAttributeSalt);
+ const StyledElement* styledElement = element->isStyledElement() ? static_cast<const StyledElement*>(element) : 0;
+ if (styledElement && styledElement->hasClass()) {
+ const SpaceSplitString& classNames = styledElement->classNames();
+ size_t count = classNames.size();
+ for (size_t i = 0; i < count; ++i)
+ identifierHashes.append(classNames[i].impl()->existingHash() * ClassAttributeSalt);
+ }
+}
+
+void SelectorChecker::pushParentStackFrame(Element* parent)
+{
+ ASSERT(m_ancestorIdentifierFilter);
+ ASSERT(m_parentStack.isEmpty() || m_parentStack.last().element == parent->parentOrHostElement());
+ ASSERT(!m_parentStack.isEmpty() || !parent->parentOrHostElement());
+ m_parentStack.append(ParentStackFrame(parent));
+ ParentStackFrame& parentFrame = m_parentStack.last();
+ // Mix tags, class names and ids into some sort of weird bouillabaisse.
+ // The filter is used for fast rejection of child and descendant selectors.
+ collectElementIdentifierHashes(parent, parentFrame.identifierHashes);
+ size_t count = parentFrame.identifierHashes.size();
+ for (size_t i = 0; i < count; ++i)
+ m_ancestorIdentifierFilter->add(parentFrame.identifierHashes[i]);
+}
+
+void SelectorChecker::popParentStackFrame()
+{
+ ASSERT(!m_parentStack.isEmpty());
+ ASSERT(m_ancestorIdentifierFilter);
+ const ParentStackFrame& parentFrame = m_parentStack.last();
+ size_t count = parentFrame.identifierHashes.size();
+ for (size_t i = 0; i < count; ++i)
+ m_ancestorIdentifierFilter->remove(parentFrame.identifierHashes[i]);
+ m_parentStack.removeLast();
+ if (m_parentStack.isEmpty()) {
+ ASSERT(m_ancestorIdentifierFilter->likelyEmpty());
+ m_ancestorIdentifierFilter.clear();
+ }
+}
+
+void SelectorChecker::pushParent(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;
+ }
+ pushParentStackFrame(parent);
+}
+
+void SelectorChecker::popParent(Element* parent)
+{
+ if (m_parentStack.isEmpty() || m_parentStack.last().element != parent)
+ return;
+ popParentStackFrame();
+}
+
+static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector* selector, unsigned*& hash, const unsigned* end)
+{
+ switch (selector->m_match) {
+ case CSSSelector::Id:
+ if (!selector->value().isEmpty())
+ (*hash++) = selector->value().impl()->existingHash() * IdAttributeSalt;
+ break;
+ case CSSSelector::Class:
+ if (!selector->value().isEmpty())
+ (*hash++) = selector->value().impl()->existingHash() * ClassAttributeSalt;
+ break;
+ default:
+ break;
+ }
+ if (hash == end)
+ return;
+ const AtomicString& localName = selector->tag().localName();
+ if (localName != starAtom)
+ (*hash++) = localName.impl()->existingHash() * TagNameSalt;
+}
+
+void SelectorChecker::collectIdentifierHashes(const CSSSelector* selector, unsigned* identifierHashes, unsigned maximumIdentifierCount)
+{
+ unsigned* hash = identifierHashes;
+ unsigned* end = identifierHashes + maximumIdentifierCount;
+ CSSSelector::Relation relation = selector->relation();
+
+ // Skip the topmost selector. It is handled quickly by the rule hashes.
+ bool skipOverSubselectors = true;
+ for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
+ // Only collect identifiers that match ancestors.
+ switch (relation) {
+ case CSSSelector::SubSelector:
+ if (!skipOverSubselectors)
+ collectDescendantSelectorIdentifierHashes(selector, hash, end);
+ break;
+ case CSSSelector::DirectAdjacent:
+ case CSSSelector::IndirectAdjacent:
+ case CSSSelector::ShadowDescendant:
+ skipOverSubselectors = true;
+ break;
+ case CSSSelector::Descendant:
+ case CSSSelector::Child:
+ skipOverSubselectors = false;
+ collectDescendantSelectorIdentifierHashes(selector, hash, end);
+ break;
+ }
+ if (hash == end)
+ return;
+ relation = selector->relation();
+ }
+ *hash = 0;
+}
+
+static inline const AtomicString* linkAttribute(Node* node)
+{
+ if (!node->isLink())
+ return 0;
+
+ ASSERT(node->isElementNode());
+ Element* element = static_cast<Element*>(node);
+ if (element->isHTMLElement())
+ return &element->fastGetAttribute(hrefAttr);
+
+#if ENABLE(SVG)
+ if (element->isSVGElement())
+ return &element->getAttribute(XLinkNames::hrefAttr);
+#endif
+
+ return 0;
+}
+
+EInsideLink SelectorChecker::determineLinkStateSlowCase(Element* element) const
+{
+ ASSERT(element->isLink());
+
+ const AtomicString* attribute = linkAttribute(element);
+ if (!attribute || attribute->isNull())
+ return NotInsideLink;
+
+ // An empty href refers to the document itself which is always visited. It is useful to check this explicitly so
+ // that visited links can be tested in platform independent manner, without explicit support in the test harness.
+ if (attribute->isEmpty())
+ return InsideVisitedLink;
+
+ LinkHash hash;
+ if (element->hasTagName(aTag))
+ hash = static_cast<HTMLAnchorElement*>(element)->visitedLinkHash();
+ else
+ hash = visitedLinkHash(m_document->baseURL(), *attribute);
+
+ if (!hash)
+ return InsideUnvisitedLink;
+
+ Frame* frame = m_document->frame();
+ if (!frame)
+ return InsideUnvisitedLink;
+
+ Page* page = frame->page();
+ if (!page)
+ return InsideUnvisitedLink;
+
+ m_linksCheckedForVisitedState.add(hash);
+
+#if USE(PLATFORM_STRATEGIES)
+ return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash, m_document->baseURL(), *attribute) ? InsideVisitedLink : InsideUnvisitedLink;
+#else
+ return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
+#endif
+}
+
+bool SelectorChecker::checkSelector(CSSSelector* sel, Element* element, bool isFastCheckableSelector) const
+{
+ PseudoId dynamicPseudo = NOPSEUDO;
+ if (isFastCheckableSelector && !element->isSVGElement()) {
+ if (!fastCheckRightmostSelector(sel, element, VisitedMatchDisabled))
+ return false;
+ return fastCheckSelector(sel, element);
+ }
+ return checkSelector(sel, element, dynamicPseudo, false, VisitedMatchDisabled) == SelectorMatches;
+}
+
+namespace {
+
+template <bool checkValue(const Element*, AtomicStringImpl*, const QualifiedName&), bool initAttributeName>
+inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement)
+{
+ AtomicStringImpl* value = selector->value().impl();
+ const QualifiedName& attribute = initAttributeName ? selector->attribute() : anyQName();
+ for (; element; element = element->parentElement()) {
+ if (checkValue(element, value, attribute) && SelectorChecker::tagMatches(element, selector)) {
+ if (selector->relation() == CSSSelector::Descendant)
+ topChildOrSubselector = 0;
+ else if (!topChildOrSubselector) {
+ ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector);
+ topChildOrSubselector = selector;
+ topChildOrSubselectorMatchElement = element;
+ }
+ if (selector->relation() != CSSSelector::SubSelector)
+ element = element->parentElement();
+ selector = selector->tagHistory();
+ return true;
+ }
+ if (topChildOrSubselector) {
+ // Child or subselector check failed.
+ // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match
+ // the original element we were checking.
+ if (!topChildOrSubselectorMatchElement)
+ return false;
+ // There may be other matches down the ancestor chain.
+ // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors.
+ selector = topChildOrSubselector;
+ element = topChildOrSubselectorMatchElement->parentElement();
+ topChildOrSubselector = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool checkClassValue(const Element* element, AtomicStringImpl* value, const QualifiedName&)
+{
+ return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(value);
+}
+
+inline bool checkIDValue(const Element* element, AtomicStringImpl* value, const QualifiedName&)
+{
+ return element->hasID() && element->idForStyleResolution().impl() == value;
+}
+
+inline bool checkExactAttributeValue(const Element* element, AtomicStringImpl* value, const QualifiedName& attributeName)
+{
+ return SelectorChecker::checkExactAttribute(element, attributeName, value);
+}
+
+inline bool checkTagValue(const Element*, AtomicStringImpl*, const QualifiedName&)
+{
+ return true;
+}
+
+}
+
+inline bool SelectorChecker::fastCheckRightmostSelector(const CSSSelector* selector, const Element* element, VisitedMatchType visitedMatchType) const
+{
+ ASSERT(isFastCheckableSelector(selector));
+
+ if (!SelectorChecker::tagMatches(element, selector))
+ return false;
+ switch (selector->m_match) {
+ case CSSSelector::None:
+ return true;
+ case CSSSelector::Class:
+ return checkClassValue(element, selector->value().impl(), anyQName());
+ case CSSSelector::Id:
+ return checkIDValue(element, selector->value().impl(), anyQName());
+ case CSSSelector::Exact:
+ case CSSSelector::Set:
+ return checkExactAttributeValue(element, selector->value().impl(), selector->attribute());
+ case CSSSelector::PseudoClass:
+ return commonPseudoClassSelectorMatches(element, selector, visitedMatchType);
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return false;
+}
+
+bool SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element) const
+{
+ ASSERT(fastCheckRightmostSelector(selector, element, VisitedMatchEnabled));
+
+ const CSSSelector* topChildOrSubselector = 0;
+ const Element* topChildOrSubselectorMatchElement = 0;
+ if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector)
+ topChildOrSubselector = selector;
+
+ if (selector->relation() != CSSSelector::SubSelector)
+ element = element->parentElement();
+
+ selector = selector->tagHistory();
+
+ // We know this compound selector has descendant, child and subselector combinators only and all components are simple.
+ while (selector) {
+ switch (selector->m_match) {
+ case CSSSelector::Class:
+ if (!fastCheckSingleSelector<checkClassValue, false>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+ return false;
+ break;
+ case CSSSelector::Id:
+ if (!fastCheckSingleSelector<checkIDValue, false>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+ return false;
+ break;
+ case CSSSelector::None:
+ if (!fastCheckSingleSelector<checkTagValue, false>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+ return false;
+ break;
+ case CSSSelector::Set:
+ case CSSSelector::Exact:
+ if (!fastCheckSingleSelector<checkExactAttributeValue, true>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement))
+ return false;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+ return true;
+}
+
+static inline bool isFastCheckableRelation(CSSSelector::Relation relation)
+{
+ return relation == CSSSelector::Descendant || relation == CSSSelector::Child || relation == CSSSelector::SubSelector;
+}
+
+static inline bool isFastCheckableMatch(const CSSSelector* selector)
+{
+ if (selector->m_match == CSSSelector::Set)
+ return true;
+ if (selector->m_match == CSSSelector::Exact)
+ return !htmlAttributeHasCaseInsensitiveValue(selector->attribute());
+ return selector->m_match == CSSSelector::None || selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
+}
+
+static inline bool isFastCheckableRightmostSelector(const CSSSelector* selector)
+{
+ if (!isFastCheckableRelation(selector->relation()))
+ return false;
+ return isFastCheckableMatch(selector) || SelectorChecker::isCommonPseudoClassSelector(selector);
+}
+
+bool SelectorChecker::isFastCheckableSelector(const CSSSelector* selector)
+{
+ if (!isFastCheckableRightmostSelector(selector))
+ return false;
+ for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
+ if (!isFastCheckableRelation(selector->relation()))
+ return false;
+ if (!isFastCheckableMatch(selector))
+ return false;
+ }
+ return true;
+}
+
+// Recursive check of selectors and combinators
+// It can return 4 different values:
+// * SelectorMatches - the selector matches the element e
+// * SelectorFailsLocally - the selector fails for the element e
+// * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
+// * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
+SelectorChecker::SelectorMatch SelectorChecker::checkSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType visitedMatchType, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
+{
+#if ENABLE(SVG)
+ // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
+ // because its contents are not part of the formal document structure.
+ if (e->isSVGShadowRoot())
+ return SelectorFailsCompletely;
+#endif
+
+ // first selector has to match
+ if (!checkOneSelector(sel, e, dynamicPseudo, isSubSelector, visitedMatchType, elementStyle, elementParentStyle))
+ return SelectorFailsLocally;
+
+ // The rest of the selectors has to match
+ CSSSelector::Relation relation = sel->relation();
+
+ // Prepare next sel
+ sel = sel->tagHistory();
+ if (!sel)
+ return SelectorMatches;
+
+ if (relation != CSSSelector::SubSelector) {
+ // Bail-out if this selector is irrelevant for the pseudoStyle
+ if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
+ return SelectorFailsCompletely;
+
+ // Disable :visited matching when we see the first link or try to match anything else than an ancestors.
+ if (!isSubSelector && (e->isLink() || (relation != CSSSelector::Descendant && relation != CSSSelector::Child)))
+ visitedMatchType = VisitedMatchDisabled;
+ }
+
+ switch (relation) {
+ case CSSSelector::Descendant:
+ while (true) {
+ ContainerNode* n = e->parentNode();
+ if (!n || !n->isElementNode())
+ return SelectorFailsCompletely;
+ e = static_cast<Element*>(n);
+ SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, visitedMatchType);
+ if (match == SelectorMatches || match == SelectorFailsCompletely)
+ return match;
+ }
+ break;
+ case CSSSelector::Child:
+ {
+ ContainerNode* n = e->parentNode();
+ if (!n || !n->isElementNode())
+ return SelectorFailsCompletely;
+ e = static_cast<Element*>(n);
+ return checkSelector(sel, e, dynamicPseudo, false, visitedMatchType);
+ }
+ case CSSSelector::DirectAdjacent:
+ {
+ if (!m_isCollectingRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByDirectAdjacentRules();
+ }
+ Node* n = e->previousSibling();
+ while (n && !n->isElementNode())
+ n = n->previousSibling();
+ if (!n)
+ return SelectorFailsAllSiblings;
+ e = static_cast<Element*>(n);
+ return checkSelector(sel, e, dynamicPseudo, false, visitedMatchType);
+ }
+ case CSSSelector::IndirectAdjacent:
+ if (!m_isCollectingRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByForwardPositionalRules();
+ }
+ while (true) {
+ Node* n = e->previousSibling();
+ while (n && !n->isElementNode())
+ n = n->previousSibling();
+ if (!n)
+ return SelectorFailsAllSiblings;
+ e = static_cast<Element*>(n);
+ SelectorMatch match = checkSelector(sel, e, dynamicPseudo, false, visitedMatchType);
+ if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely)
+ return match;
+ };
+ break;
+ case CSSSelector::SubSelector:
+ // a selector is invalid if something follows a pseudo-element
+ // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
+ // to follow the pseudo elements.
+ if ((elementStyle || m_isCollectingRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION
+ && !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
+ return SelectorFailsCompletely;
+ return checkSelector(sel, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle);
+ case CSSSelector::ShadowDescendant:
+ {
+ Node* shadowHostNode = e->shadowAncestorNode();
+ if (shadowHostNode == e || !shadowHostNode->isElementNode())
+ return SelectorFailsCompletely;
+ e = static_cast<Element*>(shadowHostNode);
+ return checkSelector(sel, e, dynamicPseudo, false, visitedMatchType);
+ }
+ }
+
+ return SelectorFailsCompletely;
+}
+
+static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
+{
+ set->add(qName.localName().impl());
+}
+
+static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
+{
+ // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
+ // Mozilla treats all other values as case-sensitive, thus so do we.
+ HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
+
+ addLocalNameToSet(attrSet, accept_charsetAttr);
+ addLocalNameToSet(attrSet, acceptAttr);
+ addLocalNameToSet(attrSet, alignAttr);
+ addLocalNameToSet(attrSet, alinkAttr);
+ addLocalNameToSet(attrSet, axisAttr);
+ addLocalNameToSet(attrSet, bgcolorAttr);
+ addLocalNameToSet(attrSet, charsetAttr);
+ addLocalNameToSet(attrSet, checkedAttr);
+ addLocalNameToSet(attrSet, clearAttr);
+ addLocalNameToSet(attrSet, codetypeAttr);
+ addLocalNameToSet(attrSet, colorAttr);
+ addLocalNameToSet(attrSet, compactAttr);
+ addLocalNameToSet(attrSet, declareAttr);
+ addLocalNameToSet(attrSet, deferAttr);
+ addLocalNameToSet(attrSet, dirAttr);
+ addLocalNameToSet(attrSet, disabledAttr);
+ addLocalNameToSet(attrSet, enctypeAttr);
+ addLocalNameToSet(attrSet, faceAttr);
+ addLocalNameToSet(attrSet, frameAttr);
+ addLocalNameToSet(attrSet, hreflangAttr);
+ addLocalNameToSet(attrSet, http_equivAttr);
+ addLocalNameToSet(attrSet, langAttr);
+ addLocalNameToSet(attrSet, languageAttr);
+ addLocalNameToSet(attrSet, linkAttr);
+ addLocalNameToSet(attrSet, mediaAttr);
+ addLocalNameToSet(attrSet, methodAttr);
+ addLocalNameToSet(attrSet, multipleAttr);
+ addLocalNameToSet(attrSet, nohrefAttr);
+ addLocalNameToSet(attrSet, noresizeAttr);
+ addLocalNameToSet(attrSet, noshadeAttr);
+ addLocalNameToSet(attrSet, nowrapAttr);
+ addLocalNameToSet(attrSet, readonlyAttr);
+ addLocalNameToSet(attrSet, relAttr);
+ addLocalNameToSet(attrSet, revAttr);
+ addLocalNameToSet(attrSet, rulesAttr);
+ addLocalNameToSet(attrSet, scopeAttr);
+ addLocalNameToSet(attrSet, scrollingAttr);
+ addLocalNameToSet(attrSet, selectedAttr);
+ addLocalNameToSet(attrSet, shapeAttr);
+ addLocalNameToSet(attrSet, targetAttr);
+ addLocalNameToSet(attrSet, textAttr);
+ addLocalNameToSet(attrSet, typeAttr);
+ addLocalNameToSet(attrSet, valignAttr);
+ addLocalNameToSet(attrSet, valuetypeAttr);
+ addLocalNameToSet(attrSet, vlinkAttr);
+
+ return attrSet;
+}
+
+bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
+{
+ static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
+ bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
+ return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
+}
+
+static bool attributeValueMatches(Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive)
+{
+ const AtomicString& value = attributeItem->value();
+ if (value.isNull())
+ return false;
+
+ switch (match) {
+ case CSSSelector::Exact:
+ if (caseSensitive ? selectorValue != value : !equalIgnoringCase(selectorValue, value))
+ return false;
+ break;
+ case CSSSelector::List:
+ {
+ // Ignore empty selectors or selectors containing spaces
+ if (selectorValue.contains(' ') || selectorValue.isEmpty())
+ return false;
+
+ unsigned startSearchAt = 0;
+ while (true) {
+ size_t foundPos = value.find(selectorValue, startSearchAt, caseSensitive);
+ if (foundPos == notFound)
+ return false;
+ if (!foundPos || value[foundPos - 1] == ' ') {
+ unsigned endStr = foundPos + selectorValue.length();
+ if (endStr == value.length() || value[endStr] == ' ')
+ break; // We found a match.
+ }
+
+ // No match. Keep looking.
+ startSearchAt = foundPos + 1;
+ }
+ break;
+ }
+ case CSSSelector::Contain:
+ if (!value.contains(selectorValue, caseSensitive) || selectorValue.isEmpty())
+ return false;
+ break;
+ case CSSSelector::Begin:
+ if (!value.startsWith(selectorValue, caseSensitive) || selectorValue.isEmpty())
+ return false;
+ break;
+ case CSSSelector::End:
+ if (!value.endsWith(selectorValue, caseSensitive) || selectorValue.isEmpty())
+ return false;
+ break;
+ case CSSSelector::Hyphen:
+ if (value.length() < selectorValue.length())
+ return false;
+ if (!value.startsWith(selectorValue, caseSensitive))
+ return false;
+ // It they start the same, check for exact match or following '-':
+ if (value.length() != selectorValue.length() && value[selectorValue.length()] != '-')
+ return false;
+ break;
+ case CSSSelector::PseudoClass:
+ case CSSSelector::PseudoElement:
+ default:
+ break;
+ }
+
+ return true;
+}
+
+static bool anyAttributeMatches(NamedNodeMap* attributes, CSSSelector::Match match, const QualifiedName& selectorAttr, const AtomicString& selectorValue, bool caseSensitive)
+{
+ for (size_t i = 0; i < attributes->length(); ++i) {
+ Attribute* attributeItem = attributes->attributeItem(i);
+
+ if (!SelectorChecker::attributeNameMatches(attributeItem, selectorAttr))
+ continue;
+
+ if (attributeValueMatches(attributeItem, match, selectorValue, caseSensitive))
+ return true;
+ }
+
+ return false;
+}
+
+bool SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType visitedMatchType, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
+{
+ ASSERT(e);
+ if (!SelectorChecker::tagMatches(e, sel))
+ return false;
+
+ if (sel->m_match == CSSSelector::Class)
+ return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value());
+
+ if (sel->m_match == CSSSelector::Id)
+ return e->hasID() && e->idForStyleResolution() == sel->value();
+
+ if (sel->isAttributeSelector()) {
+ const QualifiedName& attr = sel->attribute();
+
+ NamedNodeMap* attributes = e->attributes(true);
+ if (!attributes)
+ return false;
+
+ bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
+
+ if (!anyAttributeMatches(attributes, static_cast<CSSSelector::Match>(sel->m_match), attr, sel->value(), caseSensitive))
+ return false;
+ }
+
+ if (sel->m_match == CSSSelector::PseudoClass) {
+ // Handle :not up front.
+ if (sel->pseudoType() == CSSSelector::PseudoNot) {
+ ASSERT(sel->selectorList());
+ for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) {
+ // :not cannot nest. I don't really know why this is a
+ // restriction in CSS3, but it is, so let's honor it.
+ // the parser enforces that this never occurs
+ ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot);
+ // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
+ if (subSel->pseudoType() == CSSSelector::PseudoVisited || (subSel->pseudoType() == CSSSelector::PseudoLink && visitedMatchType == VisitedMatchEnabled))
+ return true;
+ if (!checkOneSelector(subSel, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle))
+ return true;
+ }
+ } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
+ // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
+ // (since there are no elements involved).
+ return checkScrollbarPseudoClass(sel, dynamicPseudo);
+ } else if (dynamicPseudo == SELECTION) {
+ if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
+ return !m_document->page()->focusController()->isActive();
+ }
+
+ // Normal element pseudo class checking.
+ switch (sel->pseudoType()) {
+ // Pseudo classes:
+ case CSSSelector::PseudoNot:
+ break; // Already handled up above.
+ case CSSSelector::PseudoEmpty:
+ {
+ bool result = true;
+ for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
+ if (n->isElementNode()) {
+ result = false;
+ break;
+ }
+ if (n->isTextNode()) {
+ Text* textNode = static_cast<Text*>(n);
+ if (!textNode->data().isEmpty()) {
+ result = false;
+ break;
+ }
+ }
+ }
+ if (!m_isCollectingRulesOnly) {
+ if (elementStyle)
+ elementStyle->setEmptyState(result);
+ else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
+ e->renderStyle()->setEmptyState(result);
+ }
+ return result;
+ }
+ case CSSSelector::PseudoFirstChild:
+ // first-child matches the first child that is an element
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ bool result = false;
+ Node* n = e->previousSibling();
+ while (n && !n->isElementNode())
+ n = n->previousSibling();
+ if (!n)
+ result = true;
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByFirstChildRules();
+ if (result && childStyle)
+ childStyle->setFirstChildState();
+ }
+ return result;
+ }
+ break;
+ case CSSSelector::PseudoFirstOfType:
+ // first-of-type matches the first element of its type
+ if (e->parentNode() && e->parentNode()->isElementNode()) {
+ bool result = false;
+ const QualifiedName& type = e->tagQName();
+ Node* n = e->previousSibling();
+ while (n) {
+ if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
+ break;
+ n = n->previousSibling();
+ }
+ if (!n)
+ result = true;
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByForwardPositionalRules();
+ }
+ return result;
+ }
+ break;
+ case CSSSelector::PseudoLastChild:
+ // last-child matches the last child that is an element
+ if (Element* parentElement = e->parentElement()) {
+ bool result = false;
+ if (parentElement->isFinishedParsingChildren()) {
+ Node* n = e->nextSibling();
+ while (n && !n->isElementNode())
+ n = n->nextSibling();
+ if (!n)
+ result = true;
+ }
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByLastChildRules();
+ if (result && childStyle)
+ childStyle->setLastChildState();
+ }
+ return result;
+ }
+ break;
+ case CSSSelector::PseudoLastOfType:
+ // last-of-type matches the last element of its type
+ if (Element* parentElement = e->parentElement()) {
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByBackwardPositionalRules();
+ }
+ if (!parentElement->isFinishedParsingChildren())
+ return false;
+ bool result = false;
+ const QualifiedName& type = e->tagQName();
+ Node* n = e->nextSibling();
+ while (n) {
+ if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
+ break;
+ n = n->nextSibling();
+ }
+ if (!n)
+ result = true;
+ return result;
+ }
+ break;
+ case CSSSelector::PseudoOnlyChild:
+ if (Element* parentElement = e->parentElement()) {
+ bool firstChild = false;
+ bool lastChild = false;
+
+ Node* n = e->previousSibling();
+ while (n && !n->isElementNode())
+ n = n->previousSibling();
+ if (!n)
+ firstChild = true;
+ if (firstChild && parentElement->isFinishedParsingChildren()) {
+ n = e->nextSibling();
+ while (n && !n->isElementNode())
+ n = n->nextSibling();
+ if (!n)
+ lastChild = true;
+ }
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle) {
+ parentStyle->setChildrenAffectedByFirstChildRules();
+ parentStyle->setChildrenAffectedByLastChildRules();
+ }
+ if (firstChild && childStyle)
+ childStyle->setFirstChildState();
+ if (lastChild && childStyle)
+ childStyle->setLastChildState();
+ }
+ return firstChild && lastChild;
+ }
+ break;
+ case CSSSelector::PseudoOnlyOfType:
+ // FIXME: This selector is very slow.
+ if (Element* parentElement = e->parentElement()) {
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle) {
+ parentStyle->setChildrenAffectedByForwardPositionalRules();
+ parentStyle->setChildrenAffectedByBackwardPositionalRules();
+ }
+ }
+ if (!parentElement->isFinishedParsingChildren())
+ return false;
+ bool firstChild = false;
+ bool lastChild = false;
+ const QualifiedName& type = e->tagQName();
+ Node* n = e->previousSibling();
+ while (n) {
+ if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
+ break;
+ n = n->previousSibling();
+ }
+ if (!n)
+ firstChild = true;
+ if (firstChild) {
+ n = e->nextSibling();
+ while (n) {
+ if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
+ break;
+ n = n->nextSibling();
+ }
+ if (!n)
+ lastChild = true;
+ }
+ return firstChild && lastChild;
+ }
+ break;
+ case CSSSelector::PseudoNthChild:
+ if (!sel->parseNth())
+ break;
+ if (Element* parentElement = e->parentElement()) {
+ int count = 1;
+ Node* n = e->previousSibling();
+ while (n) {
+ if (n->isElementNode()) {
+ RenderStyle* s = n->renderStyle();
+ unsigned index = s ? s->childIndex() : 0;
+ if (index) {
+ count += index;
+ break;
+ }
+ count++;
+ }
+ n = n->previousSibling();
+ }
+
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (childStyle)
+ childStyle->setChildIndex(count);
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByForwardPositionalRules();
+ }
+
+ if (sel->matchNth(count))
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoNthOfType:
+ if (!sel->parseNth())
+ break;
+ if (Element* parentElement = e->parentElement()) {
+ int count = 1;
+ const QualifiedName& type = e->tagQName();
+ Node* n = e->previousSibling();
+ while (n) {
+ if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
+ count++;
+ n = n->previousSibling();
+ }
+
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByForwardPositionalRules();
+ }
+
+ if (sel->matchNth(count))
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoNthLastChild:
+ if (!sel->parseNth())
+ break;
+ if (Element* parentElement = e->parentElement()) {
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByBackwardPositionalRules();
+ }
+ if (!parentElement->isFinishedParsingChildren())
+ return false;
+ int count = 1;
+ Node* n = e->nextSibling();
+ while (n) {
+ if (n->isElementNode())
+ count++;
+ n = n->nextSibling();
+ }
+ if (sel->matchNth(count))
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoNthLastOfType:
+ if (!sel->parseNth())
+ break;
+ if (Element* parentElement = e->parentElement()) {
+ if (!m_isCollectingRulesOnly) {
+ RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
+ if (parentStyle)
+ parentStyle->setChildrenAffectedByBackwardPositionalRules();
+ }
+ if (!parentElement->isFinishedParsingChildren())
+ return false;
+ int count = 1;
+ const QualifiedName& type = e->tagQName();
+ Node* n = e->nextSibling();
+ while (n) {
+ if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
+ count++;
+ n = n->nextSibling();
+ }
+ if (sel->matchNth(count))
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoTarget:
+ if (e == e->document()->cssTarget())
+ return true;
+ break;
+ case CSSSelector::PseudoAny:
+ for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) {
+ if (checkSelector(selector, e, dynamicPseudo, true, visitedMatchType, elementStyle, elementParentStyle) == SelectorMatches)
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoAutofill:
+ if (!e || !e->isFormControlElement())
+ break;
+ if (HTMLInputElement* inputElement = e->toInputElement())
+ return inputElement->isAutofilled();
+ break;
+ case CSSSelector::PseudoAnyLink:
+ case CSSSelector::PseudoLink:
+ // :visited and :link matches are separated later when applying the style. Here both classes match all links...
+ return e->isLink();
+ case CSSSelector::PseudoVisited:
+ // ...except if :visited matching is disabled for ancestor/sibling matching.
+ return e->isLink() && visitedMatchType == VisitedMatchEnabled;
+ case CSSSelector::PseudoDrag:
+ if (elementStyle)
+ elementStyle->setAffectedByDragRules(true);
+ else if (e->renderStyle())
+ e->renderStyle()->setAffectedByDragRules(true);
+ if (e->renderer() && e->renderer()->isDragging())
+ return true;
+ break;
+ case CSSSelector::PseudoFocus:
+ return matchesFocusPseudoClass(e);
+ case CSSSelector::PseudoHover:
+ // If we're in quirks mode, then hover should never match anchors with no
+ // href and *:hover should not match anything. This is important for sites like wsj.com.
+ if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
+ if (elementStyle)
+ elementStyle->setAffectedByHoverRules(true);
+ else if (e->renderStyle())
+ e->renderStyle()->setAffectedByHoverRules(true);
+ if (e->hovered() || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoHover))
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoActive:
+ // If we're in quirks mode, then :active should never match anchors with no
+ // href and *:active should not match anything.
+ if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
+ if (elementStyle)
+ elementStyle->setAffectedByActiveRules(true);
+ else if (e->renderStyle())
+ e->renderStyle()->setAffectedByActiveRules(true);
+ if (e->active() || InspectorInstrumentation::forcePseudoState(e, CSSSelector::PseudoActive))
+ return true;
+ }
+ break;
+ case CSSSelector::PseudoEnabled:
+ if (e && e->isFormControlElement())
+ return e->isEnabledFormControl();
+ break;
+ case CSSSelector::PseudoFullPageMedia:
+ return e && e->document() && e->document()->isMediaDocument();
+ break;
+ case CSSSelector::PseudoDefault:
+ return e && e->isDefaultButtonForForm();
+ case CSSSelector::PseudoDisabled:
+ if (e && e->isFormControlElement())
+ return !e->isEnabledFormControl();
+ break;
+ case CSSSelector::PseudoReadOnly:
+ if (!e || !e->isFormControlElement())
+ return false;
+ return e->isTextFormControl() && e->isReadOnlyFormControl();
+ case CSSSelector::PseudoReadWrite:
+ if (!e || !e->isFormControlElement())
+ return false;
+ return e->isTextFormControl() && !e->isReadOnlyFormControl();
+ case CSSSelector::PseudoOptional:
+ return e && e->isOptionalFormControl();
+ case CSSSelector::PseudoRequired:
+ return e && e->isRequiredFormControl();
+ case CSSSelector::PseudoValid:
+ if (!e)
+ return false;
+ e->document()->setContainsValidityStyleRules();
+ return e->willValidate() && e->isValidFormControlElement();
+ case CSSSelector::PseudoInvalid:
+ if (!e)
+ return false;
+ e->document()->setContainsValidityStyleRules();
+ return (e->willValidate() && !e->isValidFormControlElement()) || e->hasUnacceptableValue();
+ case CSSSelector::PseudoChecked:
+ {
+ if (!e || !e->isFormControlElement())
+ break;
+ // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
+ // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
+ // obey the CSS spec here in the test for matching the pseudo.
+ HTMLInputElement* inputElement = e->toInputElement();
+ if (inputElement && inputElement->shouldAppearChecked() && !inputElement->isIndeterminate())
+ return true;
+ if (e->hasTagName(optionTag) && toHTMLOptionElement(e)->selected())
+ return true;
+ break;
+ }
+ case CSSSelector::PseudoIndeterminate:
+ {
+ if (!e || !e->isFormControlElement())
+ break;
+#if ENABLE(PROGRESS_TAG)
+ if (e->hasTagName(progressTag)) {
+ HTMLProgressElement* progress = static_cast<HTMLProgressElement*>(e);
+ if (progress && !progress->isDeterminate())
+ return true;
+ break;
+ }
+#endif
+ HTMLInputElement* inputElement = e->toInputElement();
+ if (inputElement && inputElement->isIndeterminate())
+ return true;
+ break;
+ }
+ case CSSSelector::PseudoRoot:
+ if (e == e->document()->documentElement())
+ return true;
+ break;
+ case CSSSelector::PseudoLang:
+ {
+ AtomicString value = e->computeInheritedLanguage();
+ const AtomicString& argument = sel->argument();
+ if (value.isEmpty() || !value.startsWith(argument, false))
+ break;
+ if (value.length() != argument.length() && value[argument.length()] != '-')
+ break;
+ return true;
+ }
+#if ENABLE(FULLSCREEN_API)
+ case CSSSelector::PseudoFullScreen:
+ // While a Document is in the fullscreen state, and the document's current fullscreen
+ // element is an element in the document, the 'full-screen' pseudoclass applies to
+ // that element. Also, an <iframe>, <object> or <embed> element whose child browsing
+ // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied.
+ if (e->isFrameElementBase() && static_cast<HTMLFrameElementBase*>(e)->containsFullScreenElement())
+ return true;
+ if (!e->document()->webkitIsFullScreen())
+ return false;
+ return e == e->document()->webkitCurrentFullScreenElement();
+ case CSSSelector::PseudoAnimatingFullScreenTransition:
+ if (e != e->document()->webkitCurrentFullScreenElement())
+ return false;
+ return e->document()->isAnimatingFullScreen();
+ case CSSSelector::PseudoFullScreenAncestor:
+ return e->containsFullScreenElement();
+ case CSSSelector::PseudoFullScreenDocument:
+ // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies
+ // to all elements of that Document.
+ if (!e->document()->webkitIsFullScreen())
+ return false;
+ return true;
+#endif
+ case CSSSelector::PseudoInRange:
+ if (!e)
+ return false;
+ e->document()->setContainsValidityStyleRules();
+ return e->isInRange();
+ case CSSSelector::PseudoOutOfRange:
+ if (!e)
+ return false;
+ e->document()->setContainsValidityStyleRules();
+ return e->isOutOfRange();
+ case CSSSelector::PseudoUnknown:
+ case CSSSelector::PseudoNotParsed:
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ return false;
+ }
+ if (sel->m_match == CSSSelector::PseudoElement) {
+ if (!elementStyle && !m_isCollectingRulesOnly)
+ return false;
+
+ if (sel->isUnknownPseudoElement()) {
+ m_hasUnknownPseudoElements = true;
+ return e->shadowPseudoId() == sel->value();
+ }
+
+ PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
+ if (pseudoId == FIRST_LETTER) {
+ if (Document* document = e->document())
+ document->setUsesFirstLetterRules(true);
+ }
+ if (pseudoId != NOPSEUDO)
+ dynamicPseudo = pseudoId;
+ }
+ // ### add the rest of the checks...
+ return true;
+}
+
+bool SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const
+{
+ RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve();
+ ScrollbarPart part = RenderScrollbar::partForStyleResolve();
+
+ // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real
+ // pseudo class and just apply to everything.
+ if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
+ return !m_document->page()->focusController()->isActive();
+
+ if (!scrollbar)
+ return false;
+
+ ASSERT(sel->m_match == CSSSelector::PseudoClass);
+ switch (sel->pseudoType()) {
+ case CSSSelector::PseudoEnabled:
+ return scrollbar->enabled();
+ case CSSSelector::PseudoDisabled:
+ return !scrollbar->enabled();
+ case CSSSelector::PseudoHover:
+ {
+ ScrollbarPart hoveredPart = scrollbar->hoveredPart();
+ if (part == ScrollbarBGPart)
+ return hoveredPart != NoPart;
+ if (part == TrackBGPart)
+ return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
+ return part == hoveredPart;
+ }
+ case CSSSelector::PseudoActive:
+ {
+ ScrollbarPart pressedPart = scrollbar->pressedPart();
+ if (part == ScrollbarBGPart)
+ return pressedPart != NoPart;
+ if (part == TrackBGPart)
+ return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
+ return part == pressedPart;
+ }
+ case CSSSelector::PseudoHorizontal:
+ return scrollbar->orientation() == HorizontalScrollbar;
+ case CSSSelector::PseudoVertical:
+ return scrollbar->orientation() == VerticalScrollbar;
+ case CSSSelector::PseudoDecrement:
+ return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
+ case CSSSelector::PseudoIncrement:
+ return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
+ case CSSSelector::PseudoStart:
+ return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
+ case CSSSelector::PseudoEnd:
+ return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
+ case CSSSelector::PseudoDoubleButton:
+ {
+ ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
+ if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
+ return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
+ if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
+ return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
+ return false;
+ }
+ case CSSSelector::PseudoSingleButton:
+ {
+ ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
+ if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
+ return buttonsPlacement == ScrollbarButtonsSingle;
+ return false;
+ }
+ case CSSSelector::PseudoNoButton:
+ {
+ ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
+ if (part == BackTrackPart)
+ return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
+ if (part == ForwardTrackPart)
+ return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
+ return false;
+ }
+ case CSSSelector::PseudoCornerPresent:
+ return scrollbar->scrollableArea()->isScrollCornerVisible();
+ default:
+ return false;
+ }
+}
+
+void SelectorChecker::allVisitedStateChanged()
+{
+ if (m_linksCheckedForVisitedState.isEmpty())
+ return;
+ for (Node* node = m_document; node; node = node->traverseNextNode()) {
+ if (node->isLink())
+ node->setNeedsStyleRecalc();
+ }
+}
+
+void SelectorChecker::visitedStateChanged(LinkHash visitedHash)
+{
+ if (!m_linksCheckedForVisitedState.contains(visitedHash))
+ return;
+ for (Node* node = m_document; node; node = node->traverseNextNode()) {
+ LinkHash hash = 0;
+ if (node->hasTagName(aTag))
+ hash = static_cast<HTMLAnchorElement*>(node)->visitedLinkHash();
+ else if (const AtomicString* attr = linkAttribute(node))
+ hash = visitedLinkHash(m_document->baseURL(), *attr);
+ if (hash == visitedHash)
+ node->setNeedsStyleRecalc();
+ }
+}
+
+bool SelectorChecker::commonPseudoClassSelectorMatches(const Element* element, const CSSSelector* selector, VisitedMatchType visitedMatchType) const
+{
+ ASSERT(isCommonPseudoClassSelector(selector));
+ switch (selector->pseudoType()) {
+ case CSSSelector::PseudoLink:
+ case CSSSelector::PseudoAnyLink:
+ return element->isLink();
+ case CSSSelector::PseudoVisited:
+ return element->isLink() && visitedMatchType == VisitedMatchEnabled;
+ case CSSSelector::PseudoFocus:
+ return matchesFocusPseudoClass(element);
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ return true;
+}
+
+unsigned SelectorChecker::determineLinkMatchType(const CSSSelector* selector)
+{
+ unsigned linkMatchType = MatchAll;
+
+ // Statically determine if this selector will match a link in visited, unvisited or any state, or never.
+ // :visited never matches other elements than the innermost link element.
+ for (; selector; selector = selector->tagHistory()) {
+ switch (selector->pseudoType()) {
+ case CSSSelector::PseudoNot:
+ // :not(:visited) is equivalent to :link. Parser enforces that :not can't nest.
+ for (CSSSelector* subSelector = selector->selectorList()->first(); subSelector; subSelector = subSelector->tagHistory()) {
+ CSSSelector::PseudoType subType = subSelector->pseudoType();
+ if (subType == CSSSelector::PseudoVisited)
+ linkMatchType &= ~SelectorChecker::MatchVisited;
+ else if (subType == CSSSelector::PseudoLink)
+ linkMatchType &= ~SelectorChecker::MatchLink;
+ }
+ break;
+ case CSSSelector::PseudoLink:
+ linkMatchType &= ~SelectorChecker::MatchVisited;
+ break;
+ case CSSSelector::PseudoVisited:
+ linkMatchType &= ~SelectorChecker::MatchLink;
+ break;
+ default:
+ // We don't support :link and :visited inside :-webkit-any.
+ break;
+ }
+ CSSSelector::Relation relation = selector->relation();
+ if (relation == CSSSelector::SubSelector)
+ continue;
+ if (relation != CSSSelector::Descendant && relation != CSSSelector::Child)
+ return linkMatchType;
+ if (linkMatchType != MatchAll)
+ return linkMatchType;
+ }
+ return linkMatchType;
+}
+
+bool SelectorChecker::isFrameFocused(const Element* element)
+{
+ return element->document()->frame() && element->document()->frame()->selection()->isFocusedAndActive();
+}
+
+bool SelectorChecker::determineSelectorScopes(const CSSSelectorList& selectorList, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes)
+{
+ for (CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
+ CSSSelector* scopeSelector = 0;
+ // This picks the widest scope, not the narrowest, to minimize the number of found scopes.
+ for (CSSSelector* current = selector; current; current = current->tagHistory()) {
+ // Prefer ids over classes.
+ if (current->m_match == CSSSelector::Id)
+ scopeSelector = current;
+ else if (current->m_match == CSSSelector::Class && (!scopeSelector || scopeSelector->m_match != CSSSelector::Id))
+ scopeSelector = current;
+ CSSSelector::Relation relation = current->relation();
+ if (relation != CSSSelector::Descendant && relation != CSSSelector::Child && relation != CSSSelector::SubSelector)
+ break;
+ }
+ if (!scopeSelector)
+ return false;
+ ASSERT(scopeSelector->m_match == CSSSelector::Class || scopeSelector->m_match == CSSSelector::Id);
+ if (scopeSelector->m_match == CSSSelector::Id)
+ idScopes.add(scopeSelector->value().impl());
+ else
+ classScopes.add(scopeSelector->value().impl());
+ }
+ return true;
+}
+
+}
diff --git a/Source/WebCore/css/SelectorChecker.h b/Source/WebCore/css/SelectorChecker.h
new file mode 100644
index 000000000..1a01306f8
--- /dev/null
+++ b/Source/WebCore/css/SelectorChecker.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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 SelectorChecker_h
+#define SelectorChecker_h
+
+#include "Attribute.h"
+#include "CSSSelector.h"
+#include "Element.h"
+#include "InspectorInstrumentation.h"
+#include "LinkHash.h"
+#include "RenderStyleConstants.h"
+#include <wtf/BloomFilter.h>
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSSelector;
+class Document;
+class RenderStyle;
+
+class SelectorChecker {
+ WTF_MAKE_NONCOPYABLE(SelectorChecker);
+public:
+ SelectorChecker(Document*, bool strictParsing);
+
+ enum SelectorMatch { SelectorMatches, SelectorFailsLocally, SelectorFailsAllSiblings, SelectorFailsCompletely };
+ enum VisitedMatchType { VisitedMatchDisabled, VisitedMatchEnabled };
+ bool checkSelector(CSSSelector*, Element*, bool isFastCheckableSelector = false) const;
+ SelectorMatch checkSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
+ static bool isFastCheckableSelector(const CSSSelector*);
+ bool fastCheckSelector(const CSSSelector*, const Element*) const;
+
+ template <unsigned maximumIdentifierCount>
+ inline bool fastRejectSelector(const unsigned* identifierHashes) const;
+ static void collectIdentifierHashes(const CSSSelector*, unsigned* identifierHashes, unsigned maximumIdentifierCount);
+
+ void pushParent(Element* parent);
+ void popParent(Element* parent);
+ bool parentStackIsConsistent(ContainerNode* parentNode) const { return !m_parentStack.isEmpty() && m_parentStack.last().element == parentNode; }
+
+ EInsideLink determineLinkState(Element*) const;
+ void allVisitedStateChanged();
+ void visitedStateChanged(LinkHash visitedHash);
+
+ Document* document() const { return m_document; }
+ bool strictParsing() const { return m_strictParsing; }
+
+ bool isCollectingRulesOnly() const { return m_isCollectingRulesOnly; }
+ void setCollectingRulesOnly(bool b) { m_isCollectingRulesOnly = b; }
+
+ PseudoId pseudoStyle() const { return m_pseudoStyle; }
+ void setPseudoStyle(PseudoId pseudoId) { m_pseudoStyle = pseudoId; }
+
+ bool hasUnknownPseudoElements() const { return m_hasUnknownPseudoElements; }
+ void clearHasUnknownPseudoElements() { m_hasUnknownPseudoElements = false; }
+
+ static bool tagMatches(const Element*, const CSSSelector*);
+ static bool attributeNameMatches(const Attribute*, const QualifiedName&);
+ static bool isCommonPseudoClassSelector(const CSSSelector*);
+ bool matchesFocusPseudoClass(const Element*) const;
+ static bool fastCheckRightmostAttributeSelector(const Element*, const CSSSelector*);
+ static bool checkExactAttribute(const Element*, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value);
+
+ enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited };
+ static unsigned determineLinkMatchType(const CSSSelector*);
+
+ // Find the ids or classes selectors are scoped to. The selectors only apply to elements in subtrees where the root element matches the scope.
+ static bool determineSelectorScopes(const CSSSelectorList&, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes);
+
+private:
+ bool checkOneSelector(CSSSelector*, Element*, PseudoId& dynamicPseudo, bool isSubSelector, VisitedMatchType, RenderStyle*, RenderStyle* elementParentStyle) const;
+ bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
+ static bool isFrameFocused(const Element*);
+
+ bool fastCheckRightmostSelector(const CSSSelector*, const Element*, VisitedMatchType) const;
+ bool commonPseudoClassSelectorMatches(const Element*, const CSSSelector*, VisitedMatchType) const;
+
+ EInsideLink determineLinkStateSlowCase(Element*) const;
+
+ void pushParentStackFrame(Element* parent);
+ void popParentStackFrame();
+
+ Document* m_document;
+ bool m_strictParsing;
+ bool m_documentIsHTML;
+ bool m_isCollectingRulesOnly;
+ PseudoId m_pseudoStyle;
+ mutable bool m_hasUnknownPseudoElements;
+ mutable HashSet<LinkHash, LinkHashHash> m_linksCheckedForVisitedState;
+
+ struct ParentStackFrame {
+ ParentStackFrame() { }
+ ParentStackFrame(Element* element) : element(element) { }
+ Element* element;
+ Vector<unsigned, 4> identifierHashes;
+ };
+ Vector<ParentStackFrame> m_parentStack;
+
+ // With 100 unique strings in the filter, 2^12 slot table has false positive rate of ~0.2%.
+ static const unsigned bloomFilterKeyBits = 12;
+ OwnPtr<BloomFilter<bloomFilterKeyBits> > m_ancestorIdentifierFilter;
+};
+
+inline EInsideLink SelectorChecker::determineLinkState(Element* element) const
+{
+ if (!element || !element->isLink())
+ return NotInsideLink;
+ return determineLinkStateSlowCase(element);
+}
+
+template <unsigned maximumIdentifierCount>
+inline bool SelectorChecker::fastRejectSelector(const unsigned* identifierHashes) const
+{
+ ASSERT(m_ancestorIdentifierFilter);
+ for (unsigned n = 0; n < maximumIdentifierCount && identifierHashes[n]; ++n) {
+ if (!m_ancestorIdentifierFilter->mayContain(identifierHashes[n]))
+ return true;
+ }
+ return false;
+}
+
+inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector* selector)
+{
+ if (selector->m_match != CSSSelector::PseudoClass)
+ return false;
+ CSSSelector::PseudoType pseudoType = selector->pseudoType();
+ return pseudoType == CSSSelector::PseudoLink
+ || pseudoType == CSSSelector::PseudoAnyLink
+ || pseudoType == CSSSelector::PseudoVisited
+ || pseudoType == CSSSelector::PseudoFocus;
+}
+
+inline bool SelectorChecker::matchesFocusPseudoClass(const Element* element) const
+{
+ if (InspectorInstrumentation::forcePseudoState(const_cast<Element*>(element), CSSSelector::PseudoFocus))
+ return true;
+ return element->focused() && isFrameFocused(element);
+}
+
+inline bool SelectorChecker::tagMatches(const Element* element, const CSSSelector* selector)
+{
+ if (!selector->hasTag())
+ return true;
+ const AtomicString& localName = selector->tag().localName();
+ if (localName != starAtom && localName != element->localName())
+ return false;
+ const AtomicString& namespaceURI = selector->tag().namespaceURI();
+ return namespaceURI == starAtom || namespaceURI == element->namespaceURI();
+}
+
+inline bool SelectorChecker::attributeNameMatches(const Attribute* attribute, const QualifiedName& selectorAttributeName)
+{
+ if (selectorAttributeName.localName() != attribute->localName())
+ return false;
+ return selectorAttributeName.prefix() == starAtom || selectorAttributeName.namespaceURI() == attribute->namespaceURI();
+}
+
+inline bool SelectorChecker::checkExactAttribute(const Element* element, const QualifiedName& selectorAttributeName, const AtomicStringImpl* value)
+{
+ NamedNodeMap* attributeMap = element->attributeMap();
+ if (!attributeMap)
+ return false;
+ unsigned size = attributeMap->length();
+ for (unsigned i = 0; i < size; ++i) {
+ Attribute* attribute = attributeMap->attributeItem(i);
+ if (attributeNameMatches(attribute, selectorAttributeName) && (!value || attribute->value().impl() == value))
+ return true;
+ }
+ return false;
+}
+
+inline bool SelectorChecker::fastCheckRightmostAttributeSelector(const Element* element, const CSSSelector* selector)
+{
+ if (selector->m_match == CSSSelector::Exact || selector->m_match == CSSSelector::Set)
+ return checkExactAttribute(element, selector->attribute(), selector->value().impl());
+ ASSERT(!selector->isAttributeSelector());
+ return true;
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/css/ShadowValue.cpp b/Source/WebCore/css/ShadowValue.cpp
new file mode 100644
index 000000000..14c7cda8c
--- /dev/null
+++ b/Source/WebCore/css/ShadowValue.cpp
@@ -0,0 +1,80 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Computer, Inc.
+ *
+ * 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 "ShadowValue.h"
+
+#include "CSSPrimitiveValue.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+// Used for text-shadow and box-shadow
+ShadowValue::ShadowValue(PassRefPtr<CSSPrimitiveValue> _x,
+ PassRefPtr<CSSPrimitiveValue> _y,
+ PassRefPtr<CSSPrimitiveValue> _blur,
+ PassRefPtr<CSSPrimitiveValue> _spread,
+ PassRefPtr<CSSPrimitiveValue> _style,
+ PassRefPtr<CSSPrimitiveValue> _color)
+ : CSSValue(ShadowClass)
+ , x(_x)
+ , y(_y)
+ , blur(_blur)
+ , spread(_spread)
+ , style(_style)
+ , color(_color)
+{
+}
+
+String ShadowValue::customCssText() const
+{
+ String text("");
+
+ if (color)
+ text += color->cssText();
+ if (x) {
+ if (!text.isEmpty())
+ text += " ";
+ text += x->cssText();
+ }
+ if (y) {
+ if (!text.isEmpty())
+ text += " ";
+ text += y->cssText();
+ }
+ if (blur) {
+ if (!text.isEmpty())
+ text += " ";
+ text += blur->cssText();
+ }
+ if (spread) {
+ if (!text.isEmpty())
+ text += " ";
+ text += spread->cssText();
+ }
+ if (style) {
+ if (!text.isEmpty())
+ text += " ";
+ text += style->cssText();
+ }
+
+ return text;
+}
+
+}
diff --git a/Source/WebCore/css/ShadowValue.h b/Source/WebCore/css/ShadowValue.h
new file mode 100644
index 000000000..21547a571
--- /dev/null
+++ b/Source/WebCore/css/ShadowValue.h
@@ -0,0 +1,65 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009 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 ShadowValue_h
+#define ShadowValue_h
+
+#include "CSSValue.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSPrimitiveValue;
+
+// Used for text-shadow and box-shadow
+class ShadowValue : public CSSValue {
+public:
+ static PassRefPtr<ShadowValue> create(PassRefPtr<CSSPrimitiveValue> x,
+ PassRefPtr<CSSPrimitiveValue> y,
+ PassRefPtr<CSSPrimitiveValue> blur,
+ PassRefPtr<CSSPrimitiveValue> spread,
+ PassRefPtr<CSSPrimitiveValue> style,
+ PassRefPtr<CSSPrimitiveValue> color)
+ {
+ return adoptRef(new ShadowValue(x, y, blur, spread, style, color));
+ }
+
+ String customCssText() const;
+
+ RefPtr<CSSPrimitiveValue> x;
+ RefPtr<CSSPrimitiveValue> y;
+ RefPtr<CSSPrimitiveValue> blur;
+ RefPtr<CSSPrimitiveValue> spread;
+ RefPtr<CSSPrimitiveValue> style;
+ RefPtr<CSSPrimitiveValue> color;
+
+private:
+ ShadowValue(PassRefPtr<CSSPrimitiveValue> x,
+ PassRefPtr<CSSPrimitiveValue> y,
+ PassRefPtr<CSSPrimitiveValue> blur,
+ PassRefPtr<CSSPrimitiveValue> spread,
+ PassRefPtr<CSSPrimitiveValue> style,
+ PassRefPtr<CSSPrimitiveValue> color);
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/StyleMedia.cpp b/Source/WebCore/css/StyleMedia.cpp
new file mode 100644
index 000000000..90b574017
--- /dev/null
+++ b/Source/WebCore/css/StyleMedia.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 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 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.
+ */
+
+#include "config.h"
+#include "StyleMedia.h"
+
+#include "CSSStyleSelector.h"
+#include "Document.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "MediaList.h"
+#include "MediaQueryEvaluator.h"
+
+namespace WebCore {
+
+StyleMedia::StyleMedia(Frame* frame)
+ : m_frame(frame)
+{
+}
+
+String StyleMedia::type() const
+{
+ FrameView* view = m_frame ? m_frame->view() : 0;
+ if (view)
+ return view->mediaType();
+
+ return String();
+}
+
+bool StyleMedia::matchMedium(const String& query) const
+{
+ if (!m_frame)
+ return false;
+
+ Document* document = m_frame->document();
+ ASSERT(document);
+ Element* documentElement = document->documentElement();
+ if (!documentElement)
+ return false;
+
+ CSSStyleSelector* styleSelector = document->styleSelector();
+ if (!styleSelector)
+ return false;
+
+ RefPtr<RenderStyle> rootStyle = styleSelector->styleForElement(documentElement, 0 /*defaultParent*/, false /*allowSharing*/, true /*resolveForRootDefault*/);
+ RefPtr<MediaList> media = MediaList::create();
+
+ ExceptionCode ec = 0;
+ media->setMediaText(query, ec);
+ if (ec)
+ return false;
+
+ MediaQueryEvaluator screenEval(type(), m_frame, rootStyle.get());
+ return screenEval.eval(media.get());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/StyleMedia.h b/Source/WebCore/css/StyleMedia.h
new file mode 100644
index 000000000..760524271
--- /dev/null
+++ b/Source/WebCore/css/StyleMedia.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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 StyleMedia_h
+#define StyleMedia_h
+
+#include "PlatformString.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class Frame;
+
+class StyleMedia : public RefCounted<StyleMedia> {
+public:
+ static PassRefPtr<StyleMedia> create(Frame* frame)
+ {
+ return adoptRef(new StyleMedia(frame));
+ }
+
+ Frame* frame() { return m_frame; }
+ void disconnectFrame() { m_frame = 0; }
+
+ String type() const;
+
+ bool matchMedium(const String&) const;
+
+private:
+ StyleMedia(Frame*);
+
+ Frame* m_frame;
+};
+
+} // namespace
+
+#endif // StyleMedia_h
diff --git a/Source/WebCore/css/StyleMedia.idl b/Source/WebCore/css/StyleMedia.idl
new file mode 100644
index 000000000..09f2ae1e5
--- /dev/null
+++ b/Source/WebCore/css/StyleMedia.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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.
+ */
+
+module view {
+ interface [
+ GenerateIsReachable=ImplFrame
+ ] StyleMedia {
+ readonly attribute DOMString type;
+ boolean matchMedium(in [Optional=CallWithDefaultValue] DOMString mediaquery);
+ };
+}
diff --git a/Source/WebCore/css/StyleSheet.cpp b/Source/WebCore/css/StyleSheet.cpp
new file mode 100644
index 000000000..9813c3cf9
--- /dev/null
+++ b/Source/WebCore/css/StyleSheet.cpp
@@ -0,0 +1,91 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006 Apple Computer, Inc.
+ *
+ * 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 "StyleSheet.h"
+
+#include "CSSImportRule.h"
+#include "CSSStyleSheet.h"
+#include "Document.h"
+#include "MediaList.h"
+#include "Node.h"
+
+namespace WebCore {
+
+StyleSheet::StyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL)
+ : m_disabled(false)
+ , m_ownerRule(0)
+ , m_ownerNode(parentNode)
+ , m_originalURL(originalURL)
+ , m_finalURL(finalURL)
+{
+}
+
+StyleSheet::StyleSheet(CSSImportRule* parentRule, const String& originalURL, const KURL& finalURL)
+ : m_disabled(false)
+ , m_ownerRule(parentRule)
+ , m_ownerNode(0)
+ , m_originalURL(originalURL)
+ , m_finalURL(finalURL)
+{
+}
+
+StyleSheet::~StyleSheet()
+{
+ if (m_media)
+ m_media->setParentStyleSheet(0);
+}
+
+StyleSheet* StyleSheet::parentStyleSheet() const
+{
+ ASSERT(isCSSStyleSheet());
+ return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0;
+}
+
+void StyleSheet::setMedia(PassRefPtr<MediaList> media)
+{
+ ASSERT(isCSSStyleSheet());
+ ASSERT(!media->parentStyleSheet() || media->parentStyleSheet() == this);
+
+ if (m_media)
+ m_media->setParentStyleSheet(0);
+
+ m_media = media;
+ m_media->setParentStyleSheet(static_cast<CSSStyleSheet*>(this));
+}
+
+KURL StyleSheet::baseURL() const
+{
+ if (!m_finalURL.isNull())
+ return m_finalURL;
+ if (StyleSheet* parentSheet = parentStyleSheet())
+ return parentSheet->baseURL();
+ if (!m_ownerNode)
+ return KURL();
+ return m_ownerNode->document()->baseURL();
+}
+
+void StyleSheet::setDisabled(bool disabled)
+{
+ m_disabled = disabled;
+ if (isCSSStyleSheet())
+ static_cast<CSSStyleSheet*>(this)->styleSheetChanged();
+}
+
+}
diff --git a/Source/WebCore/css/StyleSheet.h b/Source/WebCore/css/StyleSheet.h
new file mode 100644
index 000000000..b28749a2c
--- /dev/null
+++ b/Source/WebCore/css/StyleSheet.h
@@ -0,0 +1,89 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 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 StyleSheet_h
+#define StyleSheet_h
+
+#include "KURLHash.h"
+#include "PlatformString.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CSSImportRule;
+class MediaList;
+class Node;
+
+class StyleSheet : public RefCounted<StyleSheet> {
+public:
+ virtual ~StyleSheet();
+
+ bool disabled() const { return m_disabled; }
+ void setDisabled(bool);
+
+ Node* ownerNode() const { return m_ownerNode; }
+ void clearOwnerNode() { m_ownerNode = 0; }
+
+ CSSImportRule* ownerRule() const { return m_ownerRule; }
+ void clearOwnerRule() { m_ownerRule = 0; }
+
+ StyleSheet* parentStyleSheet() const;
+
+ // Note that href is the URL that started the redirect chain that led to
+ // this style sheet. This property probably isn't useful for much except
+ // the JavaScript binding (which needs to use this value for security).
+ const String& href() const { return m_originalURL; }
+
+ void setFinalURL(const KURL& finalURL) { m_finalURL = finalURL; }
+ const KURL& finalURL() const { return m_finalURL; }
+
+ const String& title() const { return m_strTitle; }
+ void setTitle(const String& s) { m_strTitle = s; }
+ MediaList* media() const { return m_media.get(); }
+ void setMedia(PassRefPtr<MediaList>);
+
+ virtual String type() const = 0;
+ virtual bool isLoading() = 0;
+
+ virtual bool parseString(const String&, bool strict = true) = 0;
+
+ virtual bool isCSSStyleSheet() const { return false; }
+ virtual bool isXSLStyleSheet() const { return false; }
+
+ KURL baseURL() const;
+
+protected:
+ StyleSheet(Node* ownerNode, const String& href, const KURL& finalURL);
+ StyleSheet(CSSImportRule* parentRule, const String& href, const KURL& finalURL);
+
+private:
+ bool m_disabled;
+ CSSImportRule* m_ownerRule;
+ Node* m_ownerNode;
+ String m_originalURL;
+ KURL m_finalURL;
+ String m_strTitle;
+ RefPtr<MediaList> m_media;
+};
+
+} // namespace
+
+#endif
diff --git a/Source/WebCore/css/StyleSheet.idl b/Source/WebCore/css/StyleSheet.idl
new file mode 100644
index 000000000..6d5df8076
--- /dev/null
+++ b/Source/WebCore/css/StyleSheet.idl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module stylesheets {
+
+ // Introduced in DOM Level 2:
+ interface [
+ CustomMarkFunction,
+ GenerateIsReachable,
+ CustomToJS,
+ Polymorphic,
+ V8DependentLifetime
+ ] StyleSheet {
+ readonly attribute [ConvertNullStringTo=Null] DOMString type;
+ attribute boolean disabled;
+ readonly attribute Node ownerNode;
+ readonly attribute StyleSheet parentStyleSheet;
+ readonly attribute [ConvertNullStringTo=Null] DOMString href;
+ readonly attribute [ConvertNullStringTo=Null] DOMString title;
+ readonly attribute MediaList media;
+
+#if defined(LANGUAGE_CPP) && LANGUAGE_CPP
+ // Extra WebCore methods exposed to allowe compile-time casting in C++
+ boolean isCSSStyleSheet();
+#endif
+
+ };
+
+}
diff --git a/Source/WebCore/css/StyleSheetList.cpp b/Source/WebCore/css/StyleSheetList.cpp
new file mode 100644
index 000000000..bbefd318b
--- /dev/null
+++ b/Source/WebCore/css/StyleSheetList.cpp
@@ -0,0 +1,75 @@
+/**
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2007 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 "StyleSheetList.h"
+
+#include "CSSStyleSheet.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "HTMLStyleElement.h"
+#include "PlatformString.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+StyleSheetList::StyleSheetList(Document* doc)
+ : m_doc(doc)
+{
+}
+
+StyleSheetList::~StyleSheetList()
+{
+}
+
+void StyleSheetList::documentDestroyed()
+{
+ m_doc = 0;
+}
+
+unsigned StyleSheetList::length() const
+{
+ return m_sheets.size();
+}
+
+StyleSheet* StyleSheetList::item(unsigned index)
+{
+ return index < length() ? m_sheets[index].get() : 0;
+}
+
+HTMLStyleElement* StyleSheetList::getNamedItem(const String& name) const
+{
+ if (!m_doc)
+ return 0;
+
+ // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag
+ // (this is consistent with all the other collections)
+ // ### Bad implementation because returns a single element (are IDs always unique?)
+ // and doesn't look for name attribute.
+ // But unicity of stylesheet ids is good practice anyway ;)
+
+ Element* element = m_doc->getElementById(name);
+ if (element && element->hasTagName(styleTag))
+ return static_cast<HTMLStyleElement*>(element);
+ return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/StyleSheetList.h b/Source/WebCore/css/StyleSheetList.h
new file mode 100644
index 000000000..4eb7d6a27
--- /dev/null
+++ b/Source/WebCore/css/StyleSheetList.h
@@ -0,0 +1,68 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2007 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 StyleSheetList_h
+#define StyleSheetList_h
+
+#include <wtf/Forward.h>
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class Document;
+class HTMLStyleElement;
+class StyleSheet;
+
+typedef Vector<RefPtr<StyleSheet> > StyleSheetVector;
+
+class StyleSheetList : public RefCounted<StyleSheetList> {
+public:
+ static PassRefPtr<StyleSheetList> create(Document* doc) { return adoptRef(new StyleSheetList(doc)); }
+ ~StyleSheetList();
+
+ void documentDestroyed();
+
+ unsigned length() const;
+ StyleSheet* item(unsigned index);
+
+ HTMLStyleElement* getNamedItem(const String&) const;
+
+ void swap(StyleSheetVector& sheets)
+ {
+ m_sheets.swap(sheets);
+ }
+
+ Document* document()
+ {
+ return m_doc;
+ }
+
+private:
+ StyleSheetList(Document*);
+
+ Document* m_doc;
+ StyleSheetVector m_sheets;
+};
+
+} // namespace WebCore
+
+#endif // StyleSheetList_h
diff --git a/Source/WebCore/css/StyleSheetList.idl b/Source/WebCore/css/StyleSheetList.idl
new file mode 100644
index 000000000..a7048d998
--- /dev/null
+++ b/Source/WebCore/css/StyleSheetList.idl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ *
+ * 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.
+ */
+
+module stylesheets {
+
+ // Introduced in DOM Level 2:
+ interface [
+ GenerateIsReachable=ImplDocument,
+ HasIndexGetter,
+ HasNameGetter,
+ V8DependentLifetime
+ ] StyleSheetList {
+ readonly attribute unsigned long length;
+ StyleSheet item(in [Optional=CallWithDefaultValue] unsigned long index);
+ };
+
+}
diff --git a/Source/WebCore/css/WebKitCSSFilterValue.cpp b/Source/WebCore/css/WebKitCSSFilterValue.cpp
new file mode 100644
index 000000000..b8e39933a
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSFilterValue.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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 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.
+ */
+
+#include "config.h"
+#include "WebKitCSSFilterValue.h"
+
+#if ENABLE(CSS_FILTERS)
+
+#include "CSSValueList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+WebKitCSSFilterValue::WebKitCSSFilterValue(FilterOperationType operationType)
+ : CSSValueList(WebKitCSSFilterClass, typeUsesSpaceSeparator(operationType))
+ , m_type(operationType)
+{
+}
+
+bool WebKitCSSFilterValue::typeUsesSpaceSeparator(FilterOperationType operationType)
+{
+#if ENABLE(CSS_SHADERS)
+ return operationType != CustomFilterOperation;
+#else
+ return true;
+#endif
+}
+
+String WebKitCSSFilterValue::customCssText() const
+{
+ String result;
+ switch (m_type) {
+ case ReferenceFilterOperation:
+ result = "url(";
+ break;
+ case GrayscaleFilterOperation:
+ result = "grayscale(";
+ break;
+ case SepiaFilterOperation:
+ result = "sepia(";
+ break;
+ case SaturateFilterOperation:
+ result = "saturate(";
+ break;
+ case HueRotateFilterOperation:
+ result = "hue-rotate(";
+ break;
+ case InvertFilterOperation:
+ result = "invert(";
+ break;
+ case OpacityFilterOperation:
+ result = "opacity(";
+ break;
+ case BrightnessFilterOperation:
+ result = "brightness(";
+ break;
+ case ContrastFilterOperation:
+ result = "contrast(";
+ break;
+ case BlurFilterOperation:
+ result = "blur(";
+ break;
+ case DropShadowFilterOperation:
+ result = "drop-shadow(";
+ break;
+#if ENABLE(CSS_SHADERS)
+ case CustomFilterOperation:
+ result = "custom(";
+ break;
+#endif
+ default:
+ break;
+ }
+
+ return result + CSSValueList::customCssText() + ")";
+}
+
+}
+
+#endif // ENABLE(CSS_FILTERS)
diff --git a/Source/WebCore/css/WebKitCSSFilterValue.h b/Source/WebCore/css/WebKitCSSFilterValue.h
new file mode 100644
index 000000000..640ea36cb
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSFilterValue.h
@@ -0,0 +1,79 @@
+/*
+ * 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 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 WebKitCSSFilterValue_h
+#define WebKitCSSFilterValue_h
+
+#if ENABLE(CSS_FILTERS)
+
+#include "CSSValueList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class WebKitCSSFilterValue : public CSSValueList {
+public:
+ // NOTE: these have to match the values in the IDL
+ enum FilterOperationType {
+ UnknownFilterOperation,
+ ReferenceFilterOperation,
+ GrayscaleFilterOperation,
+ SepiaFilterOperation,
+ SaturateFilterOperation,
+ HueRotateFilterOperation,
+ InvertFilterOperation,
+ OpacityFilterOperation,
+ BrightnessFilterOperation,
+ ContrastFilterOperation,
+ BlurFilterOperation,
+ DropShadowFilterOperation
+#if ENABLE(CSS_SHADERS)
+ , CustomFilterOperation
+#endif
+ };
+
+ static bool typeUsesSpaceSeparator(FilterOperationType);
+
+ static PassRefPtr<WebKitCSSFilterValue> create(FilterOperationType type)
+ {
+ return adoptRef(new WebKitCSSFilterValue(type));
+ }
+
+ String customCssText() const;
+
+ FilterOperationType operationType() const { return m_type; }
+
+private:
+ WebKitCSSFilterValue(FilterOperationType);
+
+ FilterOperationType m_type;
+};
+
+}
+
+#endif // ENABLE(CSS_FILTERS)
+
+#endif
diff --git a/Source/WebCore/css/WebKitCSSFilterValue.idl b/Source/WebCore/css/WebKitCSSFilterValue.idl
new file mode 100644
index 000000000..475a80383
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSFilterValue.idl
@@ -0,0 +1,54 @@
+/*
+ * 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 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.
+ */
+
+module css {
+
+ interface [
+ Conditional=CSS_FILTERS,
+ HasIndexGetter,
+ DontCheckEnums
+ ] WebKitCSSFilterValue : CSSValueList {
+
+ // OperationTypes
+
+ const unsigned short CSS_FILTER_REFERENCE = 1;
+ const unsigned short CSS_FILTER_GRAYSCALE = 2;
+ const unsigned short CSS_FILTER_SEPIA = 3;
+ const unsigned short CSS_FILTER_SATURATE = 4;
+ const unsigned short CSS_FILTER_HUE_ROTATE = 5;
+ const unsigned short CSS_FILTER_INVERT = 6;
+ const unsigned short CSS_FILTER_OPACITY = 7;
+ const unsigned short CSS_FILTER_BRIGHTNESS = 8;
+ const unsigned short CSS_FILTER_CONTRAST = 9;
+ const unsigned short CSS_FILTER_BLUR = 10;
+ const unsigned short CSS_FILTER_DROP_SHADOW = 11;
+
+#if defined(ENABLE_CSS_SHADERS) && ENABLE_CSS_SHADERS
+ const unsigned short CSS_FILTER_CUSTOM = 12;
+#endif
+
+ readonly attribute unsigned short operationType;
+ };
+}
diff --git a/Source/WebCore/css/WebKitCSSKeyframeRule.cpp b/Source/WebCore/css/WebKitCSSKeyframeRule.cpp
new file mode 100644
index 000000000..23bdeca5f
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSKeyframeRule.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007, 2008 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 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.
+ */
+
+#include "config.h"
+#include "WebKitCSSKeyframeRule.h"
+
+#include "CSSMutableStyleDeclaration.h"
+
+namespace WebCore {
+
+WebKitCSSKeyframeRule::WebKitCSSKeyframeRule(CSSStyleSheet* parent)
+ : CSSRule(parent, CSSRule::WEBKIT_KEYFRAME_RULE)
+{
+}
+
+WebKitCSSKeyframeRule::~WebKitCSSKeyframeRule()
+{
+ if (m_style)
+ m_style->clearParentRule();
+}
+
+String WebKitCSSKeyframeRule::cssText() const
+{
+ String result = m_key;
+
+ result += " { ";
+ result += m_style->cssText();
+ result += "}";
+
+ return result;
+}
+
+void WebKitCSSKeyframeRule::setDeclaration(PassRefPtr<CSSMutableStyleDeclaration> style)
+{
+ ASSERT(style->parentRule() == this);
+ m_style = style;
+}
+
+/* static */
+void WebKitCSSKeyframeRule::parseKeyString(const String& s, Vector<float>& keys)
+{
+ keys.clear();
+ Vector<String> strings;
+ s.split(',', strings);
+
+ for (size_t i = 0; i < strings.size(); ++i) {
+ float key = -1;
+ String cur = strings[i].stripWhiteSpace();
+
+ // For now the syntax MUST be 'xxx%' or 'from' or 'to', where xxx is a legal floating point number
+ if (cur == "from")
+ key = 0;
+ else if (cur == "to")
+ key = 1;
+ else if (cur.endsWith("%")) {
+ float k = cur.substring(0, cur.length() - 1).toFloat();
+ if (k >= 0 && k <= 100)
+ key = k/100;
+ }
+
+ if (key < 0) {
+ keys.clear();
+ return;
+ }
+ else
+ keys.append(key);
+ }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/WebKitCSSKeyframeRule.h b/Source/WebCore/css/WebKitCSSKeyframeRule.h
new file mode 100644
index 000000000..052c86bf1
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSKeyframeRule.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007, 2008 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 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 WebKitCSSKeyframeRule_h
+#define WebKitCSSKeyframeRule_h
+
+#include "CSSRule.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CSSMutableStyleDeclaration;
+
+typedef int ExceptionCode;
+
+class WebKitCSSKeyframeRule : public CSSRule {
+public:
+ static PassRefPtr<WebKitCSSKeyframeRule> create()
+ {
+ return adoptRef(new WebKitCSSKeyframeRule(0));
+ }
+ static PassRefPtr<WebKitCSSKeyframeRule> create(CSSStyleSheet* parent)
+ {
+ return adoptRef(new WebKitCSSKeyframeRule(parent));
+ }
+
+ ~WebKitCSSKeyframeRule();
+
+ String keyText() const { return m_key; }
+ void setKeyText(const String& s) { m_key = s; }
+
+ void getKeys(Vector<float>& keys) const { parseKeyString(m_key, keys); }
+
+ CSSMutableStyleDeclaration* style() const { return m_style.get(); }
+
+ String cssText() const;
+
+ 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);
+
+ WebKitCSSKeyframeRule(CSSStyleSheet* parent);
+
+ RefPtr<CSSMutableStyleDeclaration> m_style;
+ String m_key; // comma separated list of keys
+};
+
+} // namespace WebCore
+
+#endif // WebKitCSSKeyframeRule_h
diff --git a/Source/WebCore/css/WebKitCSSKeyframeRule.idl b/Source/WebCore/css/WebKitCSSKeyframeRule.idl
new file mode 100644
index 000000000..f6eac7741
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSKeyframeRule.idl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level ?:
+ interface WebKitCSSKeyframeRule : CSSRule {
+
+ attribute DOMString keyText;
+ readonly attribute CSSStyleDeclaration style;
+
+ };
+
+}
diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
new file mode 100644
index 000000000..486cf1f0d
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2007, 2008 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 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.
+ */
+
+#include "config.h"
+#include "WebKitCSSKeyframesRule.h"
+
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSParser.h"
+#include "CSSRuleList.h"
+#include "StyleSheet.h"
+#include "WebKitCSSKeyframeRule.h"
+
+namespace WebCore {
+
+WebKitCSSKeyframesRule::WebKitCSSKeyframesRule(CSSStyleSheet* parent)
+ : CSSRule(parent, CSSRule::WEBKIT_KEYFRAMES_RULE)
+ , m_lstCSSRules(CSSRuleList::create())
+{
+}
+
+WebKitCSSKeyframesRule::~WebKitCSSKeyframesRule()
+{
+ for (unsigned i = 0; i < length(); ++i) {
+ WebKitCSSKeyframeRule* rule = item(i);
+ rule->setParentRule(0);
+ }
+}
+
+void WebKitCSSKeyframesRule::setName(const String& name)
+{
+ m_name = name;
+
+ // Since the name is used in the keyframe map list in CSSStyleSelector, we need
+ // to recompute the style sheet to get the updated name.
+ if (CSSStyleSheet* styleSheet = parentStyleSheet())
+ styleSheet->styleSheetChanged();
+}
+
+WebKitCSSKeyframeRule* WebKitCSSKeyframesRule::item(unsigned index)
+{
+ CSSRule* rule = m_lstCSSRules->item(index);
+ ASSERT(rule->isKeyframeRule());
+ return static_cast<WebKitCSSKeyframeRule*>(rule);
+}
+
+const WebKitCSSKeyframeRule* WebKitCSSKeyframesRule::item(unsigned index) const
+{
+ const CSSRule* rule = m_lstCSSRules->item(index);
+ ASSERT(rule->isKeyframeRule());
+ return static_cast<const WebKitCSSKeyframeRule*>(rule);
+}
+
+void WebKitCSSKeyframesRule::append(WebKitCSSKeyframeRule* rule)
+{
+ if (!rule)
+ return;
+
+ m_lstCSSRules->append(rule);
+ rule->setParentRule(this);
+}
+
+void WebKitCSSKeyframesRule::insertRule(const String& rule)
+{
+ CSSParser p(useStrictParsing());
+ RefPtr<WebKitCSSKeyframeRule> newRule = p.parseKeyframeRule(parentStyleSheet(), rule);
+ if (newRule)
+ append(newRule.get());
+}
+
+void WebKitCSSKeyframesRule::deleteRule(const String& s)
+{
+ int i = findRuleIndex(s);
+ if (i < 0)
+ return;
+
+ WebKitCSSKeyframeRule* rule = item(i);
+ rule->setParentRule(0);
+ m_lstCSSRules->deleteRule(i);
+}
+
+WebKitCSSKeyframeRule* WebKitCSSKeyframesRule::findRule(const String& s)
+{
+ int i = findRuleIndex(s);
+ return (i >= 0) ? item(i) : 0;
+}
+
+int WebKitCSSKeyframesRule::findRuleIndex(const String& key) const
+{
+ String percentageString;
+ if (equalIgnoringCase(key, "from"))
+ percentageString = "0%";
+ else if (equalIgnoringCase(key, "to"))
+ percentageString = "100%";
+ else
+ percentageString = key;
+
+ for (unsigned i = 0; i < length(); ++i) {
+ if (item(i)->keyText() == percentageString)
+ return i;
+ }
+
+ return -1;
+}
+
+String WebKitCSSKeyframesRule::cssText() const
+{
+ String result = "@-webkit-keyframes ";
+ result += m_name;
+ result += " { \n";
+
+ if (m_lstCSSRules)
+ result += m_lstCSSRules->rulesText();
+
+ result += "}";
+ return result;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.h b/Source/WebCore/css/WebKitCSSKeyframesRule.h
new file mode 100644
index 000000000..b1a1b8f10
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSKeyframesRule.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2007, 2008 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 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 WebKitCSSKeyframesRule_h
+#define WebKitCSSKeyframesRule_h
+
+#include "CSSRule.h"
+#include <wtf/Forward.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class CSSRuleList;
+class WebKitCSSKeyframeRule;
+
+typedef int ExceptionCode;
+
+class WebKitCSSKeyframesRule : public CSSRule {
+public:
+ static PassRefPtr<WebKitCSSKeyframesRule> create()
+ {
+ return adoptRef(new WebKitCSSKeyframesRule(0));
+ }
+ static PassRefPtr<WebKitCSSKeyframesRule> create(CSSStyleSheet* parent)
+ {
+ return adoptRef(new WebKitCSSKeyframesRule(parent));
+ }
+
+ ~WebKitCSSKeyframesRule();
+
+ String name() const { return m_name; }
+ void setName(const String&);
+
+ // This version of setName does not call styleSheetChanged to avoid
+ // unnecessary work. It assumes callers will either make that call
+ // themselves, or know that it will get called later.
+ void setNameInternal(const String& name)
+ {
+ m_name = AtomicString(name);
+ }
+
+ CSSRuleList* cssRules() { return m_lstCSSRules.get(); }
+
+ void insertRule(const String& rule);
+ void deleteRule(const String& key);
+ WebKitCSSKeyframeRule* findRule(const String& key);
+
+ String cssText() const;
+
+ // Not part of the CSSOM.
+ unsigned length() const { return m_lstCSSRules->length(); }
+ WebKitCSSKeyframeRule* item(unsigned index);
+ const WebKitCSSKeyframeRule* item(unsigned index) const;
+ void append(WebKitCSSKeyframeRule*);
+
+private:
+ WebKitCSSKeyframesRule(CSSStyleSheet* parent);
+
+ int findRuleIndex(const String& key) const;
+
+ RefPtr<CSSRuleList> m_lstCSSRules;
+ AtomicString m_name;
+};
+
+} // namespace WebCore
+
+#endif // WebKitCSSKeyframesRule_h
diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.idl b/Source/WebCore/css/WebKitCSSKeyframesRule.idl
new file mode 100644
index 000000000..3b081307f
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSKeyframesRule.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level ?:
+ interface [
+ HasIndexGetter
+ ] WebKitCSSKeyframesRule : CSSRule {
+
+ attribute [ConvertNullStringTo=Null, ConvertNullToNullString] DOMString name;
+ readonly attribute CSSRuleList cssRules;
+
+ void insertRule(in [Optional=CallWithDefaultValue] DOMString rule);
+ void deleteRule(in [Optional=CallWithDefaultValue] DOMString key);
+ WebKitCSSKeyframeRule findRule(in [Optional=CallWithDefaultValue] DOMString key);
+ };
+
+}
diff --git a/Source/WebCore/css/WebKitCSSMatrix.cpp b/Source/WebCore/css/WebKitCSSMatrix.cpp
new file mode 100644
index 000000000..f61719e7f
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSMatrix.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2008 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. ``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
+ * 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 "WebKitCSSMatrix.h"
+
+#include "CSSParser.h"
+#include "CSSStyleSelector.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPropertyNames.h"
+#include "CSSValueKeywords.h"
+#include "ExceptionCode.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+WebKitCSSMatrix::WebKitCSSMatrix(const TransformationMatrix& m)
+ : m_matrix(m)
+{
+}
+
+WebKitCSSMatrix::WebKitCSSMatrix(const String& s, ExceptionCode& ec)
+{
+ setMatrixValue(s, ec);
+}
+
+WebKitCSSMatrix::~WebKitCSSMatrix()
+{
+}
+
+void WebKitCSSMatrix::setMatrixValue(const String& string, ExceptionCode& ec)
+{
+ RefPtr<CSSMutableStyleDeclaration> styleDeclaration = CSSMutableStyleDeclaration::create();
+ if (CSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, true)) {
+ // Convert to TransformOperations. This can fail if a property
+ // requires style (i.e., param uses 'ems' or 'exs')
+ RefPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform);
+
+ // Check for a "none" or empty transform. In these cases we can use the default identity matrix.
+ if (!value || (value->isPrimitiveValue() && (static_cast<CSSPrimitiveValue*>(value.get()))->getIdent() == CSSValueNone))
+ return;
+
+ TransformOperations operations;
+ if (!CSSStyleSelector::createTransformOperations(value.get(), 0, 0, operations)) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+
+ // Convert transform operations to a TransformationMatrix. This can fail
+ // if a param has a percentage ('%')
+ TransformationMatrix t;
+ for (unsigned i = 0; i < operations.operations().size(); ++i) {
+ if (operations.operations()[i].get()->apply(t, IntSize(0, 0))) {
+ ec = SYNTAX_ERR;
+ return;
+ }
+ }
+
+ // set the matrix
+ m_matrix = t;
+ } else if (!string.isEmpty()) // There is something there but parsing failed
+ ec = SYNTAX_ERR;
+}
+
+// Perform a concatenation of the matrices (this * secondMatrix)
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::multiply(WebKitCSSMatrix* secondMatrix) const
+{
+ if (!secondMatrix)
+ return 0;
+
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).multiply(secondMatrix->m_matrix));
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::inverse(ExceptionCode& ec) const
+{
+ if (!m_matrix.isInvertible()) {
+ ec = NOT_SUPPORTED_ERR;
+ return 0;
+ }
+
+ return WebKitCSSMatrix::create(m_matrix.inverse());
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::translate(double x, double y, double z) const
+{
+ if (isnan(x))
+ x = 0;
+ if (isnan(y))
+ y = 0;
+ if (isnan(z))
+ z = 0;
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).translate3d(x, y, z));
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::scale(double scaleX, double scaleY, double scaleZ) const
+{
+ if (isnan(scaleX))
+ scaleX = 1;
+ if (isnan(scaleY))
+ scaleY = scaleX;
+ if (isnan(scaleZ))
+ scaleZ = 1;
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).scale3d(scaleX, scaleY, scaleZ));
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::rotate(double rotX, double rotY, double rotZ) const
+{
+ if (isnan(rotX))
+ rotX = 0;
+
+ if (isnan(rotY) && isnan(rotZ)) {
+ rotZ = rotX;
+ rotX = 0;
+ rotY = 0;
+ }
+
+ if (isnan(rotY))
+ rotY = 0;
+ if (isnan(rotZ))
+ rotZ = 0;
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(rotX, rotY, rotZ));
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::rotateAxisAngle(double x, double y, double z, double angle) const
+{
+ if (isnan(x))
+ x = 0;
+ if (isnan(y))
+ y = 0;
+ if (isnan(z))
+ z = 0;
+ if (isnan(angle))
+ angle = 0;
+ if (x == 0 && y == 0 && z == 0)
+ z = 1;
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(x, y, z, angle));
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::skewX(double angle) const
+{
+ if (isnan(angle))
+ angle = 0;
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).skewX(angle));
+}
+
+PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::skewY(double angle) const
+{
+ if (isnan(angle))
+ angle = 0;
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).skewY(angle));
+}
+
+String WebKitCSSMatrix::toString() const
+{
+ // FIXME - Need to ensure valid CSS floating point values (https://bugs.webkit.org/show_bug.cgi?id=20674)
+ if (m_matrix.isAffine())
+ return String::format("matrix(%f, %f, %f, %f, %f, %f)",
+ m_matrix.a(), m_matrix.b(), m_matrix.c(), m_matrix.d(), m_matrix.e(), m_matrix.f());
+ return String::format("matrix3d(%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f)",
+ m_matrix.m11(), m_matrix.m12(), m_matrix.m13(), m_matrix.m14(),
+ m_matrix.m21(), m_matrix.m22(), m_matrix.m23(), m_matrix.m24(),
+ m_matrix.m31(), m_matrix.m32(), m_matrix.m33(), m_matrix.m34(),
+ m_matrix.m41(), m_matrix.m42(), m_matrix.m43(), m_matrix.m44());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/WebKitCSSMatrix.h b/Source/WebCore/css/WebKitCSSMatrix.h
new file mode 100644
index 000000000..56b0a7bc0
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSMatrix.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2008 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. ``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
+ * 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 WebKitCSSMatrix_h
+#define WebKitCSSMatrix_h
+
+#include "PlatformString.h"
+#include "TransformationMatrix.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+typedef int ExceptionCode;
+
+class WebKitCSSMatrix : public RefCounted<WebKitCSSMatrix> {
+public:
+ static PassRefPtr<WebKitCSSMatrix> create(const TransformationMatrix& m)
+ {
+ return adoptRef(new WebKitCSSMatrix(m));
+ }
+ static PassRefPtr<WebKitCSSMatrix> create(const String& s, ExceptionCode& ec)
+ {
+ return adoptRef(new WebKitCSSMatrix(s, ec));
+ }
+
+ virtual ~WebKitCSSMatrix();
+
+ double a() const { return m_matrix.a(); }
+ double b() const { return m_matrix.b(); }
+ double c() const { return m_matrix.c(); }
+ double d() const { return m_matrix.d(); }
+ double e() const { return m_matrix.e(); }
+ double f() const { return m_matrix.f(); }
+
+ void setA(double f) { m_matrix.setA(f); }
+ void setB(double f) { m_matrix.setB(f); }
+ void setC(double f) { m_matrix.setC(f); }
+ void setD(double f) { m_matrix.setD(f); }
+ void setE(double f) { m_matrix.setE(f); }
+ void setF(double f) { m_matrix.setF(f); }
+
+ double m11() const { return m_matrix.m11(); }
+ double m12() const { return m_matrix.m12(); }
+ double m13() const { return m_matrix.m13(); }
+ double m14() const { return m_matrix.m14(); }
+ double m21() const { return m_matrix.m21(); }
+ double m22() const { return m_matrix.m22(); }
+ double m23() const { return m_matrix.m23(); }
+ double m24() const { return m_matrix.m24(); }
+ double m31() const { return m_matrix.m31(); }
+ double m32() const { return m_matrix.m32(); }
+ double m33() const { return m_matrix.m33(); }
+ double m34() const { return m_matrix.m34(); }
+ double m41() const { return m_matrix.m41(); }
+ double m42() const { return m_matrix.m42(); }
+ double m43() const { return m_matrix.m43(); }
+ double m44() const { return m_matrix.m44(); }
+
+ void setM11(double f) { m_matrix.setM11(f); }
+ void setM12(double f) { m_matrix.setM12(f); }
+ void setM13(double f) { m_matrix.setM13(f); }
+ void setM14(double f) { m_matrix.setM14(f); }
+ void setM21(double f) { m_matrix.setM21(f); }
+ void setM22(double f) { m_matrix.setM22(f); }
+ void setM23(double f) { m_matrix.setM23(f); }
+ void setM24(double f) { m_matrix.setM24(f); }
+ void setM31(double f) { m_matrix.setM31(f); }
+ void setM32(double f) { m_matrix.setM32(f); }
+ void setM33(double f) { m_matrix.setM33(f); }
+ void setM34(double f) { m_matrix.setM34(f); }
+ void setM41(double f) { m_matrix.setM41(f); }
+ void setM42(double f) { m_matrix.setM42(f); }
+ void setM43(double f) { m_matrix.setM43(f); }
+ void setM44(double f) { m_matrix.setM44(f); }
+
+ void setMatrixValue(const String&, ExceptionCode&);
+
+ // The following math function return a new matrix with the
+ // specified operation applied. The this value is not modified.
+
+ // Multiply this matrix by secondMatrix, on the right (result = this * secondMatrix)
+ PassRefPtr<WebKitCSSMatrix> multiply(WebKitCSSMatrix* secondMatrix) const;
+
+ // Return the inverse of this matrix. Throw an exception if the matrix is not invertible
+ PassRefPtr<WebKitCSSMatrix> inverse(ExceptionCode&) const;
+
+ // Return this matrix translated by the passed values.
+ // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations
+ // Operation is performed as though the this matrix is multiplied by a matrix with
+ // the translation values on the left (result = translation(x,y,z) * this)
+ PassRefPtr<WebKitCSSMatrix> translate(double x, double y, double z) const;
+
+ // Returns this matrix scaled by the passed values.
+ // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN
+ // makes it the same as scaleX. This allows the 3D form to used for 2D operations
+ // Operation is performed as though the this matrix is multiplied by a matrix with
+ // the scale values on the left (result = scale(x,y,z) * this)
+ PassRefPtr<WebKitCSSMatrix> scale(double scaleX, double scaleY, double scaleZ) const;
+
+ // Returns this matrix rotated by the passed values.
+ // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX).
+ // Otherwise use a rotation value of 0 for any passed NaN.
+ // Operation is performed as though the this matrix is multiplied by a matrix with
+ // the rotation values on the left (result = rotation(x,y,z) * this)
+ PassRefPtr<WebKitCSSMatrix> rotate(double rotX, double rotY, double rotZ) const;
+
+ // Returns this matrix rotated about the passed axis by the passed angle.
+ // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value
+ // Operation is performed as though the this matrix is multiplied by a matrix with
+ // the rotation values on the left (result = rotation(x,y,z,angle) * this)
+ PassRefPtr<WebKitCSSMatrix> rotateAxisAngle(double x, double y, double z, double angle) const;
+
+ // Return this matrix skewed along the X axis by the passed values.
+ // Passing a NaN will use a value of 0.
+ // Operation is performed as though the this matrix is multiplied by a matrix with
+ // the skew values on the left (result = skewX(angle) * this)
+ PassRefPtr<WebKitCSSMatrix> skewX(double angle) const;
+
+ // Return this matrix skewed along the Y axis by the passed values.
+ // Passing a NaN will use a value of 0.
+ // Operation is performed as though the this matrix is multiplied by a matrix with
+ // the skew values on the left (result = skewY(angle) * this)
+ PassRefPtr<WebKitCSSMatrix> skewY(double angle) const;
+
+ const TransformationMatrix& transform() const { return m_matrix; }
+
+ String toString() const;
+
+protected:
+ WebKitCSSMatrix(const TransformationMatrix&);
+ WebKitCSSMatrix(const String&, ExceptionCode&);
+
+ TransformationMatrix m_matrix;
+};
+
+} // namespace WebCore
+
+#endif // WebKitCSSMatrix_h
diff --git a/Source/WebCore/css/WebKitCSSMatrix.idl b/Source/WebCore/css/WebKitCSSMatrix.idl
new file mode 100644
index 000000000..f2173bf19
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSMatrix.idl
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008, 2010 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. ``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
+ * 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.
+ */
+
+module css {
+
+ // Introduced in DOM Level ?:
+ interface [
+ ConstructorParameters=1,
+ Constructor(in [Optional=CallWithNullValue] DOMString cssValue),
+ ConstructorRaisesException,
+ ] WebKitCSSMatrix {
+
+ // These attributes are simple aliases for certain elements of the 4x4 matrix
+ attribute double a; // alias for m11
+ attribute double b; // alias for m12
+ attribute double c; // alias for m21
+ attribute double d; // alias for m22
+ attribute double e; // alias for m41
+ attribute double f; // alias for m42
+
+ attribute double m11;
+ attribute double m12;
+ attribute double m13;
+ attribute double m14;
+ attribute double m21;
+ attribute double m22;
+ attribute double m23;
+ attribute double m24;
+ attribute double m31;
+ attribute double m32;
+ attribute double m33;
+ attribute double m34;
+ attribute double m41;
+ attribute double m42;
+ attribute double m43;
+ attribute double m44;
+
+ void setMatrixValue(in [Optional=CallWithDefaultValue] DOMString string) raises (DOMException);
+
+ // Multiply this matrix by secondMatrix, on the right (result = this * secondMatrix)
+ [Immutable] WebKitCSSMatrix multiply(in [Optional=CallWithDefaultValue] WebKitCSSMatrix secondMatrix);
+
+ // Return the inverse of this matrix. Throw an exception if the matrix is not invertible
+ [Immutable] WebKitCSSMatrix inverse() raises (DOMException);
+
+ // Return this matrix translated by the passed values.
+ // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations
+ [Immutable] WebKitCSSMatrix translate(in [Optional=CallWithDefaultValue] double x,
+ in [Optional=CallWithDefaultValue] double y,
+ in [Optional=CallWithDefaultValue] double z);
+
+ // Returns this matrix scaled by the passed values.
+ // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN
+ // makes it the same as scaleX. This allows the 3D form to used for 2D operations
+ [Immutable] WebKitCSSMatrix scale(in [Optional=CallWithDefaultValue] double scaleX,
+ in [Optional=CallWithDefaultValue] double scaleY,
+ in [Optional=CallWithDefaultValue] double scaleZ);
+
+ // Returns this matrix rotated by the passed values.
+ // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX).
+ // Otherwise use a rotation value of 0 for any passed NaN.
+ [Immutable] WebKitCSSMatrix rotate(in [Optional=CallWithDefaultValue] double rotX,
+ in [Optional=CallWithDefaultValue] double rotY,
+ in [Optional=CallWithDefaultValue] double rotZ);
+
+ // Returns this matrix rotated about the passed axis by the passed angle.
+ // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value
+ // of (0,0,1).
+ [Immutable] WebKitCSSMatrix rotateAxisAngle(in [Optional=CallWithDefaultValue] double x,
+ in [Optional=CallWithDefaultValue] double y,
+ in [Optional=CallWithDefaultValue] double z,
+ in [Optional=CallWithDefaultValue] double angle);
+
+ // Returns this matrix skewed along the X axis by the passed values.
+ // Passing a NaN will use a value of 0.
+ [Immutable] WebKitCSSMatrix skewX(in [Optional=CallWithDefaultValue] double angle);
+
+ // Returns this matrix skewed along the Y axis by the passed values.
+ // Passing a NaN will use a value of 0.
+ [Immutable] WebKitCSSMatrix skewY(in [Optional=CallWithDefaultValue] double angle);
+
+ [DontEnum] DOMString toString();
+ };
+
+}
diff --git a/Source/WebCore/css/WebKitCSSRegionRule.cpp b/Source/WebCore/css/WebKitCSSRegionRule.cpp
new file mode 100644
index 000000000..c049ed68b
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSRegionRule.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2011 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.
+ */
+
+#include "config.h"
+
+#include "WebKitCSSRegionRule.h"
+
+#include "CSSParserValues.h"
+#include "CSSRuleList.h"
+
+namespace WebCore {
+WebKitCSSRegionRule::WebKitCSSRegionRule(CSSStyleSheet* parent, Vector<OwnPtr<CSSParserSelector> >* selectors, PassRefPtr<CSSRuleList> rules)
+ : CSSRule(parent, CSSRule::WEBKIT_REGION_RULE)
+ , m_ruleList(rules)
+{
+ for (unsigned index = 0; index < m_ruleList->length(); ++index)
+ m_ruleList->item(index)->setParentRule(this);
+
+ m_selectorList.adoptSelectorVector(*selectors);
+}
+
+WebKitCSSRegionRule::~WebKitCSSRegionRule()
+{
+ for (unsigned index = 0; index < m_ruleList->length(); ++index)
+ m_ruleList->item(index)->setParentRule(0);
+}
+
+String WebKitCSSRegionRule::cssText() const
+{
+ String result = "@-webkit-region ";
+
+ // First add the selectors.
+ result += m_selectorList.selectorsText();
+
+ // Then add the rules.
+ result += " { \n";
+
+ if (m_ruleList)
+ result += m_ruleList->rulesText();
+
+ result += "}";
+ return result;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/css/WebKitCSSRegionRule.h b/Source/WebCore/css/WebKitCSSRegionRule.h
new file mode 100644
index 000000000..6367b50f9
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSRegionRule.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011 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.
+ */
+
+#ifndef WebKitCSSRegionRule_h
+#define WebKitCSSRegionRule_h
+
+#include "CSSSelectorList.h"
+#include "CSSStyleRule.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSParserSelector;
+class CSSRuleList;
+
+class WebKitCSSRegionRule: public CSSRule {
+public:
+ static PassRefPtr<WebKitCSSRegionRule> create(CSSStyleSheet* parent, Vector<OwnPtr<CSSParserSelector> >* selectors, PassRefPtr<CSSRuleList> rules)
+ {
+ return adoptRef(new WebKitCSSRegionRule(parent, selectors, rules));
+ }
+
+ ~WebKitCSSRegionRule();
+
+ String cssText() const;
+ const CSSSelectorList& selectorList() const { return m_selectorList; }
+ CSSRuleList* cssRules() const { return m_ruleList.get(); }
+
+private:
+ WebKitCSSRegionRule(CSSStyleSheet* parent, Vector<OwnPtr<CSSParserSelector> >* selectors, PassRefPtr<CSSRuleList> rules);
+
+ CSSSelectorList m_selectorList;
+ RefPtr<CSSRuleList> m_ruleList;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/WebKitCSSShaderValue.cpp b/Source/WebCore/css/WebKitCSSShaderValue.cpp
new file mode 100644
index 000000000..51cf8a30f
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSShaderValue.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_SHADERS)
+#include "WebKitCSSShaderValue.h"
+
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "StyleCachedShader.h"
+#include "StylePendingShader.h"
+
+namespace WebCore {
+
+WebKitCSSShaderValue::WebKitCSSShaderValue(const String& url)
+ : CSSPrimitiveValue(WebKitCSSShaderClass, url, CSS_URI)
+ , m_accessedShader(false)
+{
+}
+
+WebKitCSSShaderValue::~WebKitCSSShaderValue()
+{
+}
+
+StyleCachedShader* WebKitCSSShaderValue::cachedShader(CachedResourceLoader* loader)
+{
+ ASSERT(loader);
+
+ if (!m_accessedShader) {
+ m_accessedShader = true;
+
+ ResourceRequest request(loader->document()->completeURL(getStringValue()));
+ if (CachedShader* cachedShader = loader->requestShader(request))
+ m_shader = StyleCachedShader::create(cachedShader);
+ }
+
+ return (m_shader && m_shader->isCachedShader()) ? static_cast<StyleCachedShader*>(m_shader.get()) : 0;
+}
+
+StyleShader* WebKitCSSShaderValue::cachedOrPendingShader()
+{
+ if (!m_shader)
+ m_shader = StylePendingShader::create(this);
+
+ return m_shader.get();
+}
+
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
diff --git a/Source/WebCore/css/WebKitCSSShaderValue.h b/Source/WebCore/css/WebKitCSSShaderValue.h
new file mode 100644
index 000000000..825482db3
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSShaderValue.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011 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.
+ */
+
+#ifndef WebKitCSSShaderValue_h
+#define WebKitCSSShaderValue_h
+
+#if ENABLE(CSS_SHADERS)
+
+#include "CachedResourceHandle.h"
+#include "CSSPrimitiveValue.h"
+
+namespace WebCore {
+
+class CachedResourceLoader;
+class StyleCachedShader;
+class StyleShader;
+
+class WebKitCSSShaderValue : public CSSPrimitiveValue {
+public:
+ static PassRefPtr<WebKitCSSShaderValue> create(const String& url) { return adoptRef(new WebKitCSSShaderValue(url)); }
+ ~WebKitCSSShaderValue();
+
+ StyleCachedShader* cachedShader(CachedResourceLoader*);
+ StyleShader* cachedOrPendingShader();
+
+private:
+ WebKitCSSShaderValue(const String& url);
+
+ RefPtr<StyleShader> m_shader;
+ bool m_accessedShader;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)
+
+#endif // WebKitCSSShaderValue_h
diff --git a/Source/WebCore/css/WebKitCSSTransformValue.cpp b/Source/WebCore/css/WebKitCSSTransformValue.cpp
new file mode 100644
index 000000000..6a391ac85
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSTransformValue.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2007, 2008 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 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.
+ */
+
+#include "config.h"
+#include "WebKitCSSTransformValue.h"
+
+#include "CSSValueList.h"
+#include "PlatformString.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+WebKitCSSTransformValue::WebKitCSSTransformValue(TransformOperationType op)
+ : CSSValueList(WebKitCSSTransformClass, false)
+ , m_type(op)
+{
+}
+
+String WebKitCSSTransformValue::customCssText() const
+{
+ String result;
+ switch (m_type) {
+ case TranslateTransformOperation:
+ result += "translate(";
+ break;
+ case TranslateXTransformOperation:
+ result += "translateX(";
+ break;
+ case TranslateYTransformOperation:
+ result += "translateY(";
+ break;
+ case RotateTransformOperation:
+ result += "rotate(";
+ break;
+ case ScaleTransformOperation:
+ result += "scale(";
+ break;
+ case ScaleXTransformOperation:
+ result += "scaleX(";
+ break;
+ case ScaleYTransformOperation:
+ result += "scaleY(";
+ break;
+ case SkewTransformOperation:
+ result += "skew(";
+ break;
+ case SkewXTransformOperation:
+ result += "skewX(";
+ break;
+ case SkewYTransformOperation:
+ result += "skewY(";
+ break;
+ case MatrixTransformOperation:
+ result += "matrix(";
+ break;
+ case TranslateZTransformOperation:
+ result += "translateZ(";
+ break;
+ case Translate3DTransformOperation:
+ result += "translate3d(";
+ break;
+ case RotateXTransformOperation:
+ result += "rotateX(";
+ break;
+ case RotateYTransformOperation:
+ result += "rotateY(";
+ break;
+ case RotateZTransformOperation:
+ result += "rotateZ(";
+ break;
+ case Rotate3DTransformOperation:
+ result += "rotate3d(";
+ break;
+ case ScaleZTransformOperation:
+ result += "scaleZ(";
+ break;
+ case Scale3DTransformOperation:
+ result += "scale3d(";
+ break;
+ case PerspectiveTransformOperation:
+ result += "perspective(";
+ break;
+ case Matrix3DTransformOperation:
+ result += "matrix3d(";
+ break;
+ default:
+ break;
+ }
+
+ result += CSSValueList::customCssText();
+
+ result += ")";
+ return result;
+}
+
+}
diff --git a/Source/WebCore/css/WebKitCSSTransformValue.h b/Source/WebCore/css/WebKitCSSTransformValue.h
new file mode 100644
index 000000000..89e014155
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSTransformValue.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007, 2008 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 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 WebKitCSSTransformValue_h
+#define WebKitCSSTransformValue_h
+
+#include "CSSValueList.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class WebKitCSSTransformValue : public CSSValueList {
+public:
+ // NOTE: these have to match the values in the IDL
+ enum TransformOperationType {
+ UnknownTransformOperation,
+ TranslateTransformOperation,
+ TranslateXTransformOperation,
+ TranslateYTransformOperation,
+ RotateTransformOperation,
+ ScaleTransformOperation,
+ ScaleXTransformOperation,
+ ScaleYTransformOperation,
+ SkewTransformOperation,
+ SkewXTransformOperation,
+ SkewYTransformOperation,
+ MatrixTransformOperation,
+ TranslateZTransformOperation,
+ Translate3DTransformOperation,
+ RotateXTransformOperation,
+ RotateYTransformOperation,
+ RotateZTransformOperation,
+ Rotate3DTransformOperation,
+ ScaleZTransformOperation,
+ Scale3DTransformOperation,
+ PerspectiveTransformOperation,
+ Matrix3DTransformOperation
+ };
+
+ static PassRefPtr<WebKitCSSTransformValue> create(TransformOperationType type)
+ {
+ return adoptRef(new WebKitCSSTransformValue(type));
+ }
+
+ String customCssText() const;
+
+ TransformOperationType operationType() const { return m_type; }
+
+private:
+ WebKitCSSTransformValue(TransformOperationType);
+
+ TransformOperationType m_type;
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/css/WebKitCSSTransformValue.idl b/Source/WebCore/css/WebKitCSSTransformValue.idl
new file mode 100644
index 000000000..007097e7c
--- /dev/null
+++ b/Source/WebCore/css/WebKitCSSTransformValue.idl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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.
+ */
+
+module css {
+
+ interface [
+ HasIndexGetter,
+ DontCheckEnums
+ ] WebKitCSSTransformValue : CSSValueList {
+
+ // OperationTypes
+
+ const unsigned short CSS_TRANSLATE = 1;
+ const unsigned short CSS_TRANSLATEX = 2;
+ const unsigned short CSS_TRANSLATEY = 3;
+ const unsigned short CSS_ROTATE = 4;
+ const unsigned short CSS_SCALE = 5;
+ const unsigned short CSS_SCALEX = 6;
+ const unsigned short CSS_SCALEY = 7;
+ const unsigned short CSS_SKEW = 8;
+ const unsigned short CSS_SKEWX = 9;
+ const unsigned short CSS_SKEWY = 10;
+ const unsigned short CSS_MATRIX = 11;
+ const unsigned short CSS_TRANSLATEZ = 12;
+ const unsigned short CSS_TRANSLATE3D = 13;
+ const unsigned short CSS_ROTATEX = 14;
+ const unsigned short CSS_ROTATEY = 15;
+ const unsigned short CSS_ROTATEZ = 16;
+ const unsigned short CSS_ROTATE3D = 17;
+ const unsigned short CSS_SCALEZ = 18;
+ const unsigned short CSS_SCALE3D = 19;
+ const unsigned short CSS_PERSPECTIVE = 20;
+ const unsigned short CSS_MATRIX3D = 21;
+
+ readonly attribute unsigned short operationType;
+ };
+
+}
diff --git a/Source/WebCore/css/WebKitFontFamilyNames.in b/Source/WebCore/css/WebKitFontFamilyNames.in
new file mode 100644
index 000000000..f1b878e27
--- /dev/null
+++ b/Source/WebCore/css/WebKitFontFamilyNames.in
@@ -0,0 +1,7 @@
+cursiveFamily="-webkit-cursive"
+fantasyFamily="-webkit-fantasy"
+monospaceFamily="-webkit-monospace"
+sansSerifFamily="-webkit-sans-serif"
+serifFamily="-webkit-serif"
+pictographFamily="-webkit-pictograph"
+standardFamily="-webkit-standard"
diff --git a/Source/WebCore/css/fullscreen.css b/Source/WebCore/css/fullscreen.css
new file mode 100644
index 000000000..f4987f53f
--- /dev/null
+++ b/Source/WebCore/css/fullscreen.css
@@ -0,0 +1,41 @@
+:-webkit-full-screen {
+ background-color: white;
+ z-index: 2147483647;
+}
+
+:root:-webkit-full-screen-document:not(:-webkit-full-screen), :root:-webkit-full-screen-ancestor {
+ overflow: hidden !important;
+}
+
+:-webkit-full-screen-ancestor:not(iframe) {
+ z-index: auto !important;
+ opacity: 1 !important;
+ -webkit-transform: none !important;
+}
+
+video:-webkit-full-screen {
+ background-color: transparent !important;
+ position: static !important;
+ margin: 0 !important;
+ height: 100% !important;
+ width: 100% !important;
+ -webkit-box-flex: 1 !important;
+ display: block !important;
+}
+
+img:-webkit-full-screen {
+ width: auto;
+ height: 100%;
+ max-width: 100%;
+}
+
+iframe:-webkit-full-screen {
+ margin: 0 !important;
+ padding: 0 !important;
+ border: 0 !important;
+ position: fixed !important;
+ height: 100% !important;
+ width: 100% !important;
+ left: 0 !important;
+ top: 0 !important;
+}
diff --git a/Source/WebCore/css/fullscreenQuickTime.css b/Source/WebCore/css/fullscreenQuickTime.css
new file mode 100644
index 000000000..a5559768d
--- /dev/null
+++ b/Source/WebCore/css/fullscreenQuickTime.css
@@ -0,0 +1,170 @@
+/*
+ * 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 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,
+ * 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.
+ */
+
+/* alternate media controls - Extend fullscreen.css */
+
+video:-webkit-full-screen::-webkit-media-controls-panel {
+ -webkit-box-align: start !important;
+ -webkit-box-pack: end !important;
+ -webkit-appearance: none !important;
+
+ bottom: 50px !important;
+ left: 50% !important;
+ margin-left: -220px !important;
+ padding: 12px 0 0 10px !important;
+ width: 430px !important;
+ height: 48px !important;
+
+ background-image: -webkit-gradient(
+ linear,
+ left top,
+ left bottom,
+ color-stop(0, rgba(30, 30, 30, .97)),
+ color-stop(0.333, rgba(45, 45, 45, .97)),
+ color-stop(0.35, rgba(25, 25, 25, .97)),
+ color-stop(0.366, rgba(25, 25, 25, .97)),
+ color-stop(0.366, rgba(12, 12, 12, .97)),
+ color-stop(1, rgba(19, 19, 19, .97))
+ ) !important;
+
+ -webkit-box-shadow:
+ inset 0 -1px 1px rgba(0, 0, 0, 0.5),
+ inset 0 1px 0 0px rgba(255, 255, 255, 0.15),
+ inset 0 -1px 0 0px rgba(202, 202, 202, 0.09),
+ 0 0 0 1px rgba(0, 0, 0, 0.5);
+ -webkit-border-radius: 8px !important;
+
+ -webkit-transition: opacity 0.3s linear !important;
+}
+
+video:-webkit-animating-full-screen-transition::-webkit-media-controls-panel {
+ opacity: 0 ! important;
+ -webkit-transition: opacity 0 ! important;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-mute-button {
+ display: none;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-volume-slider-container {
+ display: none;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-volume-slider {
+ display: none;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-volume-slider-mute-button {
+ display: none;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-fullscreen-volume-min-button {
+ -webkit-appearance: media-mute-button;
+ display: block;
+ position: absolute;
+ left: 11px;
+ top: 15px;
+ width: 14px;
+ height: 12px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-fullscreen-volume-slider {
+ -webkit-appearance: media-slider;
+ display: block;
+ position: absolute;
+ left: 28px;
+ top: 15px;
+ height: 12px;
+ width: 50px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-fullscreen-volume-max-button {
+ -webkit-appearance: media-mute-button;
+ display: block;
+ position: absolute;
+ left: 84px;
+ top: 15px;
+ width: 14px;
+ height: 12px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-play-button {
+ position: absolute;
+ width: 22px;
+ height: 23px;
+ left: 209px;
+ top: 9px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-rewind-button {
+ position: absolute;
+ left: 162px;
+ top: 13px;
+ width: 18px;
+ height: 18px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-seek-back-button {
+ position: absolute;
+ display: -webkit-box;
+ width: 23px;
+ height: 16px;
+ left: 162px;
+ top: 13px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-return-to-realtime-button {
+ position: absolute;
+ display: -webkit-box;
+ width: 29px;
+ height: 16px;
+ left: 262px;
+ top: 13px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-seek-forward-button {
+ position: absolute;
+ display: -webkit-box;
+ width: 23px;
+ height: 16px;
+ left: 262px;
+ top: 13px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-timeline-container {
+ height: auto;
+ width: 420px;
+ position: absolute;
+ bottom: 9px;
+ left: 8px;
+ right: 8px;
+}
+
+video:-webkit-full-screen::-webkit-media-controls-status-display {
+ width: 420px;
+ position: absolute;
+ bottom: 9px;
+ left: 8px;
+ right: 8px;
+}
diff --git a/Source/WebCore/css/html.css b/Source/WebCore/css/html.css
new file mode 100644
index 000000000..60cec9c5f
--- /dev/null
+++ b/Source/WebCore/css/html.css
@@ -0,0 +1,1013 @@
+/*
+ * The default style sheet used to render HTML.
+ *
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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.
+ *
+ */
+
+@namespace "http://www.w3.org/1999/xhtml";
+
+html {
+ display: block
+}
+
+/* children of the <head> element all have display:none */
+head {
+ display: none
+}
+
+meta {
+ display: none
+}
+
+title {
+ display: none
+}
+
+link {
+ display: none
+}
+
+style {
+ display: none
+}
+
+script {
+ display: none
+}
+
+/* generic block-level elements */
+
+body {
+ display: block;
+ margin: 8px
+}
+
+p {
+ display: block;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1__qem;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+}
+
+div {
+ display: block
+}
+
+layer {
+ display: block
+}
+
+article, aside, footer, header, hgroup, nav, section {
+ display: block
+}
+
+marquee {
+ display: inline-block;
+ overflow: -webkit-marquee
+}
+
+address {
+ display: block
+}
+
+blockquote {
+ display: block;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 40px;
+ -webkit-margin-end: 40px;
+}
+
+figcaption {
+ display: block
+}
+
+figure {
+ display: block;
+ -webkit-margin-before: 1em;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 40px;
+ -webkit-margin-end: 40px;
+}
+
+q {
+ display: inline
+}
+
+q:before {
+ content: open-quote;
+}
+
+q:after {
+ content: close-quote;
+}
+
+center {
+ display: block;
+ /* special centering to be able to emulate the html4/netscape behaviour */
+ text-align: -webkit-center
+}
+
+hr {
+ display: block;
+ -webkit-margin-before: 0.5em;
+ -webkit-margin-after: 0.5em;
+ -webkit-margin-start: auto;
+ -webkit-margin-end: auto;
+ border-style: inset;
+ border-width: 1px
+}
+
+map {
+ display: inline
+}
+
+/* heading elements */
+
+h1 {
+ display: block;
+ font-size: 2em;
+ -webkit-margin-before: 0.67__qem;
+ -webkit-margin-after: 0.67em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ font-weight: bold
+}
+
+:-webkit-any(article,aside,nav,section) h1 {
+ font-size: 1.5em;
+ -webkit-margin-before: 0.83__qem;
+ -webkit-margin-after: 0.83em;
+}
+
+:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 {
+ font-size: 1.17em;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+}
+
+:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 {
+ font-size: 1.00em;
+ -webkit-margin-before: 1.33__qem;
+ -webkit-margin-after: 1.33em;
+}
+
+:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 {
+ font-size: .83em;
+ -webkit-margin-before: 1.67__qem;
+ -webkit-margin-after: 1.67em;
+}
+
+:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 {
+ font-size: .67em;
+ -webkit-margin-before: 2.33__qem;
+ -webkit-margin-after: 2.33em;
+}
+
+h2 {
+ display: block;
+ font-size: 1.5em;
+ -webkit-margin-before: 0.83__qem;
+ -webkit-margin-after: 0.83em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ font-weight: bold
+}
+
+h3 {
+ display: block;
+ font-size: 1.17em;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ font-weight: bold
+}
+
+h4 {
+ display: block;
+ -webkit-margin-before: 1.33__qem;
+ -webkit-margin-after: 1.33em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ font-weight: bold
+}
+
+h5 {
+ display: block;
+ font-size: .83em;
+ -webkit-margin-before: 1.67__qem;
+ -webkit-margin-after: 1.67em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ font-weight: bold
+}
+
+h6 {
+ display: block;
+ font-size: .67em;
+ -webkit-margin-before: 2.33__qem;
+ -webkit-margin-after: 2.33em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ font-weight: bold
+}
+
+/* tables */
+
+table {
+ display: table;
+ border-collapse: separate;
+ border-spacing: 2px;
+ border-color: gray
+}
+
+thead {
+ display: table-header-group;
+ vertical-align: middle;
+ border-color: inherit
+}
+
+tbody {
+ display: table-row-group;
+ vertical-align: middle;
+ border-color: inherit
+}
+
+tfoot {
+ display: table-footer-group;
+ vertical-align: middle;
+ border-color: inherit
+}
+
+/* for tables without table section elements (can happen with XHTML or dynamically created tables) */
+table > tr {
+ vertical-align: middle;
+}
+
+col {
+ display: table-column
+}
+
+colgroup {
+ display: table-column-group
+}
+
+tr {
+ display: table-row;
+ vertical-align: inherit;
+ border-color: inherit
+}
+
+td, th {
+ display: table-cell;
+ vertical-align: inherit
+}
+
+th {
+ font-weight: bold
+}
+
+caption {
+ display: table-caption;
+ text-align: -webkit-center
+}
+
+/* lists */
+
+ul, menu, dir {
+ display: block;
+ list-style-type: disc;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ -webkit-padding-start: 40px
+}
+
+ol {
+ display: block;
+ list-style-type: decimal;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+ -webkit-padding-start: 40px
+}
+
+li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+}
+
+ul ul, ol ul {
+ list-style-type: circle
+}
+
+ol ol ul, ol ul ul, ul ol ul, ul ul ul {
+ list-style-type: square
+}
+
+dd {
+ display: block;
+ -webkit-margin-start: 40px
+}
+
+dl {
+ display: block;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
+}
+
+dt {
+ display: block
+}
+
+ol ul, ul ol, ul ul, ol ol {
+ -webkit-margin-before: 0;
+ -webkit-margin-after: 0
+}
+
+/* form elements */
+
+form {
+ display: block;
+ margin-top: 0__qem;
+}
+
+label {
+ cursor: default;
+}
+
+legend {
+ display: block;
+ -webkit-padding-start: 2px;
+ -webkit-padding-end: 2px;
+ border: none
+}
+
+fieldset {
+ display: block;
+ -webkit-margin-start: 2px;
+ -webkit-margin-end: 2px;
+ -webkit-padding-before: 0.35em;
+ -webkit-padding-start: 0.75em;
+ -webkit-padding-end: 0.75em;
+ -webkit-padding-after: 0.625em;
+ border: 2px groove ThreeDFace
+}
+
+button {
+ -webkit-appearance: button;
+}
+
+/* Form controls don't go vertical. */
+input, textarea, keygen, select, button, isindex, meter, progress {
+ -webkit-block-flow: tb !important;
+}
+
+input, textarea, keygen, select, button, isindex {
+ margin: 0__qem;
+ font: -webkit-small-control;
+ color: initial;
+ letter-spacing: normal;
+ word-spacing: normal;
+ line-height: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-shadow: none;
+ display: inline-block;
+ text-align: -webkit-auto;
+}
+
+input[type="hidden"] {
+ display: none
+}
+
+input, input[type="password"], input[type="search"], isindex {
+ -webkit-appearance: textfield;
+ padding: 1px;
+ background-color: white;
+ border: 2px inset;
+ -webkit-rtl-ordering: logical;
+ -webkit-user-select: text;
+ cursor: auto;
+}
+
+input[type="search"] {
+ -webkit-appearance: searchfield;
+ -webkit-box-sizing: border-box;
+}
+
+input::-webkit-textfield-decoration-container {
+ display: -webkit-box;
+ -webkit-box-align: center;
+}
+
+input[type="search"]::-webkit-textfield-decoration-container {
+ direction: ltr;
+}
+
+input[type="search"]::-webkit-search-cancel-button {
+ -webkit-appearance: searchfield-cancel-button;
+ display: block;
+ -webkit-box-flex: 0;
+}
+
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: searchfield-decoration;
+ display: block;
+ -webkit-box-flex: 0;
+}
+
+input[type="search"]::-webkit-search-results-decoration {
+ -webkit-appearance: searchfield-results-decoration;
+ display: block;
+ -webkit-box-flex: 0;
+}
+
+input[type="search"]::-webkit-search-results-button {
+ -webkit-appearance: searchfield-results-button;
+ display: block;
+ -webkit-box-flex: 0;
+}
+
+#if defined(ENABLE_DATALIST) && ENABLE_DATALIST
+input::-webkit-input-list-button {
+ -webkit-appearance: list-button;
+ display: inline-block;
+}
+#endif
+
+input::-webkit-inner-spin-button {
+ -webkit-appearance: inner-spin-button;
+ display: block;
+ position: relative;
+ cursor: default;
+ vertical-align: top;
+ -webkit-box-flex: 0;
+ -webkit-user-select: none;
+}
+
+#if defined(ENABLE_INPUT_SPEECH) && ENABLE_INPUT_SPEECH
+input::-webkit-input-speech-button {
+ -webkit-appearance: -webkit-input-speech-button;
+ display: block;
+ vertical-align: top;
+ -webkit-box-flex: 0;
+}
+#endif
+
+keygen, select {
+ -webkit-border-radius: 5px;
+}
+
+keygen::-webkit-keygen-select {
+ margin: 0px;
+}
+
+textarea {
+ -webkit-appearance: textarea;
+ background-color: white;
+ border: 1px solid;
+ -webkit-rtl-ordering: logical;
+ -webkit-user-select: text;
+ -webkit-box-orient: vertical;
+ resize: auto;
+ cursor: auto;
+ padding: 2px;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+::-webkit-input-placeholder {
+ -webkit-text-security: none;
+ color: darkGray;
+ display: block !important;
+ pointer-events: none !important;
+}
+
+input::-webkit-input-placeholder, isindex::-webkit-input-placeholder {
+ white-space: pre;
+ word-wrap: normal;
+ overflow: hidden;
+ padding-left: 1px;
+ padding-right: 1px;
+}
+
+input[type="password"] {
+ -webkit-text-security: disc !important;
+}
+
+input[type="hidden"], input[type="image"], input[type="file"] {
+ -webkit-appearance: initial;
+ padding: initial;
+ background-color: initial;
+ border: initial;
+}
+
+input[type="file"] {
+ -webkit-box-align: baseline;
+ color: inherit;
+ text-align: start !important;
+}
+
+input:-webkit-autofill {
+ background-color: #FAFFBD !important;
+ background-image:none !important;
+ color: #000000 !important;
+}
+
+input[type="radio"], input[type="checkbox"] {
+ margin: 3px 0.5ex;
+ padding: initial;
+ background-color: initial;
+ border: initial;
+}
+
+input[type="button"], input[type="submit"], input[type="reset"] {
+ -webkit-appearance: push-button;
+ white-space: pre
+}
+
+input[type="file"]::-webkit-file-upload-button {
+ -webkit-appearance: push-button;
+ white-space: nowrap;
+ margin: 0;
+ font-size: inherit;
+}
+
+input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button, button {
+ -webkit-box-align: center;
+ text-align: center;
+ cursor: default;
+ color: ButtonText;
+ padding: 2px 6px 3px 6px;
+ border: 2px outset ButtonFace;
+ background-color: ButtonFace;
+ -webkit-box-sizing: border-box
+}
+
+input[type="range"] {
+ -webkit-appearance: slider-horizontal;
+ padding: initial;
+ border: initial;
+ margin: 2px;
+}
+
+input[type="range"]::-webkit-slider-container {
+ -webkit-box-align: center;
+ -webkit-box-orient: horizontal; /* This property is updated by C++ code. */
+ -webkit-box-sizing: border-box;
+ display: -webkit-box;
+ height: 100%;
+ width: 100%;
+}
+
+input[type="range"]::-webkit-slider-runnable-track {
+ -webkit-box-flex: 1;
+ -webkit-box-sizing: border-box;
+ display: block;
+}
+
+input[type="range"]::-webkit-slider-thumb {
+ -webkit-appearance: sliderthumb-horizontal;
+ -webkit-box-sizing: border-box;
+ display: block;
+ position: relative;
+}
+
+input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled,
+input[type="file"]:disabled::-webkit-file-upload-button, button:disabled,
+select:disabled, keygen:disabled, optgroup:disabled, option:disabled {
+ color: GrayText
+}
+
+input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active, input[type="file"]:active::-webkit-file-upload-button, button:active {
+ border-style: inset
+}
+
+input[type="button"]:active:disabled, input[type="submit"]:active:disabled, input[type="reset"]:active:disabled, input[type="file"]:active:disabled::-webkit-file-upload-button, button:active:disabled {
+ border-style: outset
+}
+
+area, param {
+ display: none
+}
+
+input[type="checkbox"] {
+ -webkit-appearance: checkbox;
+ -webkit-box-sizing: border-box;
+}
+
+input[type="radio"] {
+ -webkit-appearance: radio;
+ -webkit-box-sizing: border-box;
+}
+
+#if defined(ENABLE_INPUT_COLOR) && ENABLE_INPUT_COLOR
+
+input[type="color"] {
+ -webkit-appearance: square-button;
+ width: 44px;
+ height: 23px;
+}
+
+input[type="color"]::-webkit-color-swatch-wrapper {
+ display:-webkit-box;
+ padding: 4px 2px;
+ -webkit-box-sizing: border-box;
+ width: 100%;
+ height: 100%
+}
+
+input[type="color"]::-webkit-color-swatch {
+ background-color: #000000;
+ border: 1px solid #777777;
+ -webkit-box-flex: 1;
+}
+
+#if defined(ENABLE_DATALIST) && ENABLE_DATALIST
+
+input[type="color"][list] {
+ -webkit-appearance: menulist;
+ width: 88px;
+ height: 23px;
+}
+
+input[type="color"][list]::-webkit-color-swatch-wrapper {
+ padding-left: 8px;
+ padding-right: 24px;
+}
+
+input[type="color"][list]::-webkit-color-swatch {
+ border-color: #000000;
+}
+
+#endif // defined(ENABLE_DATALIST) && ENABLE_DATALIST
+
+#endif // defined(ENABLE_INPUT_COLOR) && ENABLE_INPUT_COLOR
+
+select {
+ -webkit-appearance: menulist;
+ -webkit-box-sizing: border-box;
+ -webkit-box-align: center;
+ border: 1px solid;
+ white-space: pre;
+ -webkit-rtl-ordering: logical;
+ color: black;
+ background-color: white;
+ cursor: default;
+}
+
+select[size],
+select[multiple],
+select[size][multiple] {
+ -webkit-appearance: listbox;
+ -webkit-box-align: start;
+ border: 1px inset gray;
+ -webkit-border-radius: initial;
+ white-space: initial;
+}
+
+select[size="0"],
+select[size="1"] {
+ -webkit-appearance: menulist;
+ -webkit-box-align: center;
+ border: 1px solid;
+ -webkit-border-radius: 5px;
+ white-space: pre;
+}
+
+optgroup {
+ font-weight: bolder;
+}
+
+option {
+ font-weight: normal;
+}
+
+output {
+ display: inline;
+}
+
+/* form validation message bubble */
+
+::-webkit-validation-bubble {
+ display: inline-block;
+ z-index: 2147483647;
+ position: absolute;
+ opacity: 0.95;
+ line-height: 0;
+ margin: 0;
+ -webkit-text-security: none;
+ -webkit-transition: opacity 05.5s ease;
+}
+
+::-webkit-validation-bubble-message {
+ display: -webkit-box;
+ position: relative;
+ top: -4px;
+ font: message-box;
+ color: black;
+ min-width: 50px;
+ max-width: 200px;
+ border: solid 2px #400;
+ background: -webkit-gradient(linear, left top, left bottom, from(#f8ecec), to(#e8cccc));
+ padding: 8px;
+ -webkit-border-radius: 8px;
+ -webkit-box-shadow: 4px 4px 4px rgba(100,100,100,0.6),
+ inset -2px -2px 1px #d0c4c4,
+ inset 2px 2px 1px white;
+ line-height: normal;
+ white-space: normal;
+ z-index: 2147483644;
+}
+
+::-webkit-validation-bubble-text-block {
+ -webkit-box-flex: 1;
+}
+
+::-webkit-validation-bubble-heading {
+ font-weight: bold;
+}
+
+::-webkit-validation-bubble-arrow {
+ display: inline-block;
+ position: relative;
+ left: 32px;
+ width: 16px;
+ height: 16px;
+ background-color: #f8ecec;
+ border-width: 2px 0 0 2px;
+ border-style: solid;
+ border-color: #400;
+ box-shadow: inset 2px 2px 1px white;
+ -webkit-transform-origin: 0 0;
+ -webkit-transform: rotate(45deg);
+ z-index: 2147483645;
+}
+
+::-webkit-validation-bubble-arrow-clipper {
+ display: block;
+ overflow: hidden;
+ height: 16px;
+}
+
+#if defined(ENABLE_METER_TAG) && ENABLE_METER_TAG
+/* meter */
+
+meter {
+ -webkit-appearance: meter;
+ -webkit-box-sizing: border-box;
+ display: inline-box;
+ height: 1em;
+ width: 5em;
+ vertical-align: -0.2em;
+}
+
+meter::-webkit-meter-bar {
+ background: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#ddd), color-stop(0.20, #eee), color-stop(0.45, #ccc), color-stop(0.55, #ccc));
+ height: 100%;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+}
+
+meter::-webkit-meter-optimum-value {
+ background: -webkit-gradient(linear, left top, left bottom, from(#ad7), to(#ad7), color-stop(0.20, #cea), color-stop(0.45, #7a3), color-stop(0.55, #7a3));
+ height: 100%;
+ -webkit-box-sizing: border-box;
+}
+
+meter::-webkit-meter-suboptimum-value {
+ background: -webkit-gradient(linear, left top, left bottom, from(#fe7), to(#fe7), color-stop(0.20, #ffc), color-stop(0.45, #db3), color-stop(0.55, #db3));
+ height: 100%;
+ -webkit-box-sizing: border-box;
+}
+
+meter::-webkit-meter-even-less-good-value {
+ background: -webkit-gradient(linear, left top, left bottom, from(#f77), to(#f77), color-stop(0.20, #fcc), color-stop(0.45, #d44), color-stop(0.55, #d44));
+ height: 100%;
+ -webkit-box-sizing: border-box;
+}
+#endif
+
+#if defined(ENABLE_PROGRESS_TAG) && ENABLE_PROGRESS_TAG
+/* progress */
+
+progress {
+ -webkit-appearance: progress-bar;
+ -webkit-box-sizing: border-box;
+ display: inline-block;
+ height: 1em;
+ width: 10em;
+ vertical-align: -0.2em;
+}
+
+progress::-webkit-progress-bar {
+ background-color: gray;
+ height: 100%;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+}
+
+progress::-webkit-progress-value {
+ background-color: green;
+ height: 100%;
+ width: 50%; /* should be removed later */
+ -webkit-box-sizing: border-box;
+}
+#endif
+
+/* inline elements */
+
+u, ins {
+ text-decoration: underline
+}
+
+strong, b {
+ font-weight: bold
+}
+
+i, cite, em, var, address, dfn {
+ font-style: italic
+}
+
+tt, code, kbd, samp {
+ font-family: monospace
+}
+
+pre, xmp, plaintext, listing {
+ display: block;
+ font-family: monospace;
+ white-space: pre;
+ margin: 1__qem 0
+}
+
+mark {
+ background-color: yellow;
+ color: black
+}
+
+big {
+ font-size: larger
+}
+
+small {
+ font-size: smaller
+}
+
+s, strike, del {
+ text-decoration: line-through
+}
+
+sub {
+ vertical-align: sub;
+ font-size: smaller
+}
+
+sup {
+ vertical-align: super;
+ font-size: smaller
+}
+
+nobr {
+ white-space: nowrap
+}
+
+/* states */
+
+:focus {
+ outline: auto 5px -webkit-focus-ring-color
+}
+
+/* Read-only text fields do not show a focus ring but do still receive focus */
+html:focus, body:focus, input[readonly]:focus {
+ outline: none
+}
+
+applet:focus, embed:focus, iframe:focus, object:focus {
+ outline: none
+}
+
+input:focus, textarea:focus, isindex:focus, keygen:focus, select:focus {
+ outline-offset: -2px
+}
+
+input[type="button"]:focus,
+input[type="checkbox"]:focus,
+input[type="file"]:focus,
+input[type="hidden"]:focus,
+input[type="image"]:focus,
+input[type="radio"]:focus,
+input[type="reset"]:focus,
+input[type="search"]:focus,
+input[type="submit"]:focus,
+input[type="file"]:focus::-webkit-file-upload-button {
+ outline-offset: 0
+}
+
+a:-webkit-any-link {
+ color: -webkit-link;
+ text-decoration: underline;
+ cursor: auto;
+}
+
+a:-webkit-any-link:active {
+ color: -webkit-activelink
+}
+
+/* HTML5 ruby elements */
+
+ruby, rt {
+ text-indent: 0; /* blocks used for ruby rendering should not trigger this */
+}
+
+rt {
+ line-height: normal;
+ -webkit-text-emphasis: none;
+}
+
+ruby > rt {
+ display: block;
+ font-size: 50%;
+ text-align: -webkit-auto;
+}
+
+ruby > rp {
+ display: none;
+}
+
+/* other elements */
+
+noframes {
+ display: none
+}
+
+frameset, frame {
+ display: block
+}
+
+frameset {
+ border-color: inherit
+}
+
+iframe {
+ border: 2px inset
+}
+
+details {
+ display: block
+}
+
+summary {
+ display: block
+}
+
+summary::-webkit-details-marker {
+ display: inline-block;
+ width: 0.66em;
+ height: 0.66em;
+ margin-right: 0.4em;
+}
+
+bdi, output {
+ unicode-bidi: -webkit-isolate;
+}
+
+bdo {
+ unicode-bidi: bidi-override;
+}
+
+/* page */
+
+@page {
+ /* FIXME: Define the right default values for page properties. */
+ size: auto;
+ margin: auto;
+ padding: 0px;
+ border-width: 0px;
+}
+
+/* noscript is handled internally, as it depends on settings. */
+
diff --git a/Source/WebCore/css/make-css-file-arrays.pl b/Source/WebCore/css/make-css-file-arrays.pl
new file mode 100755
index 000000000..3ac1ece4e
--- /dev/null
+++ b/Source/WebCore/css/make-css-file-arrays.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2006 Apple Computer, Inc.
+#
+# 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.
+#
+
+# Usage: make-css-file-arrays.pl <header> <output> <input> ...
+
+use strict;
+use Getopt::Long;
+
+my $defines;
+my $preprocessor;
+GetOptions('defines=s' => \$defines,
+ 'preprocessor=s' => \$preprocessor);
+
+my $header = $ARGV[0];
+shift;
+
+my $out = $ARGV[0];
+shift;
+
+open HEADER, ">", $header or die;
+open OUT, ">", $out or die;
+
+print HEADER "namespace WebCore {\n";
+print OUT "namespace WebCore {\n";
+
+for my $in (@ARGV) {
+ $in =~ /(\w+)\.css$/ or die;
+ my $name = $1;
+
+ # Slurp in the CSS file.
+ my $text;
+ # We should not set --defines option and run "moc" preprocessor on Qt.
+ # See http://webkit.org/b/37296.
+ if (!$defines) {
+ open IN, "<", $in or die;
+ { local $/; $text = <IN>; }
+ close IN;
+ # Remove preprocessor directives.
+ $text =~ s|^#.*?$||mg;
+ } else {
+ require preprocessor;
+ $text = join('', applyPreprocessor($in, $defines, $preprocessor));
+ }
+
+ # Remove comments in a simple-minded way that will work fine for our files.
+ # Could do this a fancier way if we were worried about arbitrary CSS source.
+ $text =~ s|/\*.*?\*/||gs;
+
+ # Crunch whitespace just to make it a little smaller.
+ # Could do work to avoid doing this inside quote marks but our files don't have runs of spaces in quotes.
+ # Could crunch further based on places where whitespace is optional.
+ $text =~ s|\s+| |gs;
+ $text =~ s|^ ||;
+ $text =~ s| $||;
+
+ # Write out a C array of the characters.
+ my $length = length $text;
+ print HEADER "extern const char ${name}UserAgentStyleSheet[${length}];\n";
+ print OUT "extern const char ${name}UserAgentStyleSheet[${length}] = {\n";
+ my $i = 0;
+ while ($i < $length) {
+ print OUT " ";
+ my $j = 0;
+ while ($j < 16 && $i < $length) {
+ print OUT ", " unless $j == 0;
+ print OUT ord substr $text, $i, 1;
+ ++$i;
+ ++$j;
+ }
+ print OUT "," unless $i == $length;
+ print OUT "\n";
+ }
+ print OUT "};\n";
+
+}
+
+print HEADER "}\n";
+print OUT "}\n";
diff --git a/Source/WebCore/css/makegrammar.pl b/Source/WebCore/css/makegrammar.pl
new file mode 100644
index 000000000..06faaa93d
--- /dev/null
+++ b/Source/WebCore/css/makegrammar.pl
@@ -0,0 +1,55 @@
+#! /usr/bin/perl
+#
+# This file is part of the WebKit project
+#
+# Copyright (C) 2008 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.
+use strict;
+use warnings;
+
+my $grammar = $ARGV[0];
+my $fileBase = $ARGV[1];
+
+system("bison -d -p cssyy " . $grammar . " -o " . $fileBase . ".tab.c");
+
+open HEADER, ">" . $fileBase . ".h" or die;
+print HEADER << "EOF";
+#ifndef CSSGRAMMAR_H
+#define CSSGRAMMAR_H
+EOF
+
+open HPP, "<" . $fileBase . ".tab.h" or die;
+while (<HPP>) {
+ print HEADER;
+}
+close HPP;
+
+print HEADER "#endif\n";
+
+close HEADER;
+
+unlink($fileBase . ".tab.h");
+
+open CPP, ">" . $fileBase . ".cpp" or die;
+open GENSRC, "<" . $fileBase . ".tab.c" or die;
+while (<GENSRC>) {
+ print CPP;
+}
+close GENSRC;
+close CPP;
+
+unlink($fileBase . ".tab.c");
diff --git a/Source/WebCore/css/makeprop.pl b/Source/WebCore/css/makeprop.pl
new file mode 100644
index 000000000..6de7b7d56
--- /dev/null
+++ b/Source/WebCore/css/makeprop.pl
@@ -0,0 +1,203 @@
+#! /usr/bin/perl
+#
+# This file is part of the WebKit project
+#
+# Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
+# Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+# Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged
+#
+# 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.
+use Getopt::Long;
+use preprocessor;
+use strict;
+use warnings;
+
+my $defines;
+my $preprocessor;
+GetOptions('defines=s' => \$defines,
+ 'preprocessor=s' => \$preprocessor);
+
+my @NAMES = applyPreprocessor("CSSPropertyNames.in", $defines, $preprocessor);
+
+my %namesHash;
+my @duplicates = ();
+
+my @names = ();
+my @aliases = ();
+foreach (@NAMES) {
+ next if (m/(^\s*$)/);
+ # Input may use a different EOL sequence than $/, so avoid chomp.
+ $_ =~ s/[\r\n]+$//g;
+ if (exists $namesHash{$_}) {
+ push @duplicates, $_;
+ } else {
+ $namesHash{$_} = 1;
+ }
+ if ($_ =~ /=/) {
+ push @aliases, $_;
+ } else {
+ push @names, $_;
+ }
+}
+
+if (@duplicates > 0) {
+ die 'Duplicate CSS property names: ', join(', ', @duplicates) . "\n";
+}
+
+open GPERF, ">CSSPropertyNames.gperf" || die "Could not open CSSPropertyNames.gperf for writing";
+print GPERF << "EOF";
+%{
+/* This file is automatically generated from CSSPropertyNames.in by makeprop, do not edit */
+#include "config.h"
+#include \"CSSPropertyNames.h\"
+#include \"HashTools.h\"
+#include <string.h>
+
+#include <wtf/ASCIICType.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+%}
+%struct-type
+struct Property;
+%omit-struct-type
+%language=C++
+%readonly-tables
+%global-table
+%compare-strncmp
+%define class-name CSSPropertyNamesHash
+%define lookup-function-name findPropertyImpl
+%define hash-function-name propery_hash_function
+%define word-array-name property_wordlist
+%enum
+%%
+EOF
+
+foreach my $name (@names) {
+ my $id = $name;
+ $id =~ s/(^[^-])|-(.)/uc($1||$2)/ge;
+ print GPERF $name . ", CSSProperty" . $id . "\n";
+}
+
+foreach my $alias (@aliases) {
+ $alias =~ /^([^\s]*)[\s]*=[\s]*([^\s]*)/;
+ my $name = $1;
+ my $id = $2;
+ $id =~ s/(^[^-])|-(.)/uc($1||$2)/ge;
+ print GPERF $name . ", CSSProperty" . $id . "\n";
+}
+
+print GPERF<< "EOF";
+%%
+const Property* findProperty(register const char* str, register unsigned int len)
+{
+ return CSSPropertyNamesHash::findPropertyImpl(str, len);
+}
+
+const char* getPropertyName(CSSPropertyID id)
+{
+ if (id < firstCSSProperty)
+ return 0;
+ int index = id - firstCSSProperty;
+ if (index >= numCSSProperties)
+ return 0;
+ return propertyNameStrings[index];
+}
+
+WTF::String getJSPropertyName(CSSPropertyID id)
+{
+ char result[maxCSSPropertyNameLength + 1];
+ const char* cssPropertyName = getPropertyName(id);
+ const char* propertyNamePointer = cssPropertyName;
+ if (!propertyNamePointer)
+ return emptyString();
+
+ char* resultPointer = result;
+ while (char character = *propertyNamePointer++) {
+ if (character == '-') {
+ char nextCharacter = *propertyNamePointer++;
+ if (!nextCharacter)
+ break;
+ character = (propertyNamePointer - 2 != cssPropertyName) ? toASCIIUpper(nextCharacter) : nextCharacter;
+ }
+ *resultPointer++ = character;
+ }
+ *resultPointer = '\\0';
+ return WTF::String(result);
+}
+
+} // namespace WebCore
+EOF
+
+open HEADER, ">CSSPropertyNames.h" || die "Could not open CSSPropertyNames.h for writing";
+print HEADER << "EOF";
+/* This file is automatically generated from CSSPropertyNames.in by makeprop, do not edit */
+
+#ifndef CSSPropertyNames_h
+#define CSSPropertyNames_h
+
+#include <string.h>
+
+namespace WTF {
+class String;
+}
+
+namespace WebCore {
+
+enum CSSPropertyID {
+ CSSPropertyInvalid = 0,
+EOF
+
+my $first = 1001;
+my $i = 1001;
+my $maxLen = 0;
+foreach my $name (@names) {
+ my $id = $name;
+ $id =~ s/(^[^-])|-(.)/uc($1||$2)/ge;
+ print HEADER " CSSProperty" . $id . " = " . $i . ",\n";
+ $i = $i + 1;
+ if (length($name) > $maxLen) {
+ $maxLen = length($name);
+ }
+}
+my $num = $i - $first;
+
+print HEADER "};\n\n";
+print HEADER "const int firstCSSProperty = $first;\n";
+print HEADER "const int numCSSProperties = $num;\n";
+print HEADER "const size_t maxCSSPropertyNameLength = $maxLen;\n";
+
+print HEADER "const char* const propertyNameStrings[$num] = {\n";
+foreach my $name (@names) {
+ print HEADER "\"$name\",\n";
+}
+print HEADER "};\n";
+
+print HEADER << "EOF";
+
+const char* getPropertyName(CSSPropertyID);
+WTF::String getJSPropertyName(CSSPropertyID);
+
+} // namespace WebCore
+
+#endif // CSSPropertyNames_h
+
+EOF
+
+close HEADER;
+
+system("gperf --key-positions=\"*\" -D -n -s 2 CSSPropertyNames.gperf --output-file=CSSPropertyNames.cpp") == 0 || die "calling gperf failed: $?";
diff --git a/Source/WebCore/css/maketokenizer b/Source/WebCore/css/maketokenizer
new file mode 100644
index 000000000..d2a786f75
--- /dev/null
+++ b/Source/WebCore/css/maketokenizer
@@ -0,0 +1,151 @@
+print <<END;
+/*
+ * Copyright (C) 2003 Lars Knoll (knoll\@kde.org)
+ *
+ *
+ * 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.
+ */
+
+/* This file is mostly data generated by flex. Unfortunately flex
+ can't handle 16bit strings directly, so we just copy the part of
+ the code we need and modify it to our needs.
+
+ Most of the defines below are to make sure we can easily use the
+ flex generated code, using as little editing as possible.
+
+ The flex syntax to generate the lexer are more or less directly
+ copied from the CSS2.1 specs, with some fixes for comments and
+ the important symbol.
+
+ To regenerate, run flex on tokenizer.flex. After this, copy the
+ data tables and the YY_DECL method over to this file. Remove the
+ init code from YY_DECL and change the YY_END_OF_BUFFER to only call
+ yyterminate().
+
+*/
+
+// --------- begin generated code -------------------
+
+END
+
+{
+print<<END
+
+#include "CSSGrammar.h"
+
+#define INITIAL 0
+#define mediaquery 1
+#define forkeyword 2
+#define nthchild 3
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+END
+}
+
+# Skip over the flex output prologue: the above typedefs, forward declarations, etc.
+# Stop when we get to the declarations of tables.
+while (<>) {
+ last if /YY_NUM_RULES/;
+}
+
+# Dump the generated tables. /yy_last_accepting/ matches the first declaration after the tables.
+print;
+while (<>) {
+ last if /yy_last_accepting/;
+ print;
+}
+
+# Skip down the the declaration of yytext; the body of the flex output begins after it.
+while (<>) {
+ last if /yytext/;
+}
+# Dump the definitions of states (INITIAL, media query, tokenizer state support).
+while (<>) {
+ last if not (/define/ || /line/) ;
+ print;
+}
+
+# Skip to main scanner function.
+while (<>) {
+ last if /^YY_DECL/;
+}
+
+# Dump main scanner declarations, substituting in our 16-bit character type.
+# Declarations end with the declaration matching /yy_act/.
+print;
+while (<>) {
+ s/char/UChar/;
+ print;
+ last if /yy_act/;
+}
+
+# Skip past initialization code, down to main loop.
+while (<>) {
+ last if /while \( 1 \)/;
+}
+
+# Dump the main loop, skipping over labels we don't use.
+# Stop before dumping the end-of-buffer handling, because we output our own custom end-of-buffer handling.
+print;
+while (<>) {
+ next if /^yy_match:/;
+ next if /^do_action:/;
+ last if /YY_END_OF_BUFFER/;
+ if (/^case YY_STATE_EOF\(INITIAL\):/) {
+ print "case YY_END_OF_BUFFER:\n";
+ # flex outputs a ton of logic related to end-of-buffer handling; we just want to fall through to
+ # the yyterminate() found in other EOF states. But we need to be careful to back up to behind
+ # the terminating double-NUL so that subsequent calls to flex will have the pointers in order,
+ # so this logic is a reduction of the normal flex-generated YY_END_OF_BUFFER code.
+ print "\tyy_c_buf_p = yy_cp - 1;\n";
+ print "\tyy_cp = yy_c_buf_p;\n";
+ }
+ print;
+}
+
+# Skip over the end-of-buffer handling; dump the rest of the function.
+while (<>) {
+ last if /default:/;
+}
+print;
+while (<>) {
+ print;
+ last if /end of yylex/;
+}
+
+# We don't want the remainder of flex's output.
+# However, flex may choke with "flex: error writing output file <stdout>"
+# if its stdout is unexpectedly closed on it.
+# Consume the remaining output.
+while (<>) {
+}
diff --git a/Source/WebCore/css/makevalues.pl b/Source/WebCore/css/makevalues.pl
new file mode 100644
index 000000000..ced2416aa
--- /dev/null
+++ b/Source/WebCore/css/makevalues.pl
@@ -0,0 +1,158 @@
+#! /usr/bin/perl
+#
+# This file is part of the WebKit project
+#
+# Copyright (C) 1999 Waldo Bastian (bastian@kde.org)
+# Copyright (C) 2007 Apple Inc. All rights reserved.
+# Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+# Copyright (C) 2010 Andras Becsi (abecsi@inf.u-szeged.hu), University of Szeged
+#
+# 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.
+use Getopt::Long;
+use preprocessor;
+use strict;
+use warnings;
+
+my $defines;
+my $preprocessor;
+GetOptions('defines=s' => \$defines,
+ 'preprocessor=s' => \$preprocessor);
+
+my @NAMES = applyPreprocessor("CSSValueKeywords.in", $defines, $preprocessor);
+
+my %namesHash;
+my @duplicates = ();
+
+my @names = ();
+foreach (@NAMES) {
+ next if (m/(^\s*$)/);
+ # Input may use a different EOL sequence than $/, so avoid chomp.
+ $_ =~ s/[\r\n]+$//g;
+ # CSS values need to be lower case.
+ $_ = lc $_;
+ if (exists $namesHash{$_}) {
+ push @duplicates, $_;
+ } else {
+ $namesHash{$_} = 1;
+ }
+ push @names, $_;
+}
+
+if (@duplicates > 0) {
+ die 'Duplicate CSS value keywords values: ', join(', ', @duplicates) . "\n";
+}
+
+open GPERF, ">CSSValueKeywords.gperf" || die "Could not open CSSValueKeywords.gperf for writing";
+print GPERF << "EOF";
+%{
+/* This file is automatically generated from CSSValueKeywords.in by makevalues, do not edit */
+
+#include \"CSSValueKeywords.h\"
+#include \"HashTools.h\"
+#include <string.h>
+
+namespace WebCore {
+%}
+%struct-type
+struct Value;
+%omit-struct-type
+%language=C++
+%readonly-tables
+%compare-strncmp
+%define class-name CSSValueKeywordsHash
+%define lookup-function-name findValueImpl
+%define hash-function-name value_hash_function
+%define word-array-name value_word_list
+%enum
+%%
+EOF
+
+foreach my $name (@names) {
+ my $id = $name;
+ $id =~ s/(^[^-])|-(.)/uc($1||$2)/ge;
+ print GPERF $name . ", CSSValue" . $id . "\n";
+}
+
+print GPERF << "EOF";
+%%
+static const char* const valueList[] = {
+ "",
+EOF
+
+foreach my $name (@names) {
+ print GPERF " \"" . $name . "\",\n";
+}
+
+print GPERF << "EOF";
+ 0
+};
+
+const Value* findValue(register const char* str, register unsigned int len)
+{
+ return CSSValueKeywordsHash::findValueImpl(str, len);
+}
+
+const char* getValueName(unsigned short id)
+{
+ if (id >= numCSSValueKeywords || id <= 0)
+ return 0;
+ return valueList[id];
+}
+
+} // namespace WebCore
+EOF
+close GPERF;
+
+
+open HEADER, ">CSSValueKeywords.h" || die "Could not open CSSValueKeywords.h for writing";
+print HEADER << "EOF";
+/* This file is automatically generated from CSSValueKeywords.in by makevalues, do not edit */
+
+#ifndef CSSValueKeywords_h
+#define CSSValueKeywords_h
+
+#include <string.h>
+
+namespace WebCore {
+
+const int CSSValueInvalid = 0;
+EOF
+
+my $i = 1;
+my $maxLen = 0;
+foreach my $name (@names) {
+ my $id = $name;
+ $id =~ s/(^[^-])|-(.)/uc($1||$2)/ge;
+ print HEADER "const int CSSValue" . $id . " = " . $i . ";\n";
+ $i = $i + 1;
+ if (length($name) > $maxLen) {
+ $maxLen = length($name);
+ }
+}
+print HEADER "const int numCSSValueKeywords = " . $i . ";\n";
+print HEADER "const size_t maxCSSValueKeywordLength = " . $maxLen . ";\n";
+print HEADER << "EOF";
+
+const char* getValueName(unsigned short id);
+
+} // namespace WebCore
+
+#endif // CSSValueKeywords_h
+
+EOF
+close HEADER;
+
+system("gperf --key-positions=\"*\" -D -n -s 2 CSSValueKeywords.gperf --output-file=CSSValueKeywords.cpp") == 0 || die "calling gperf failed: $?";
diff --git a/Source/WebCore/css/mathml.css b/Source/WebCore/css/mathml.css
new file mode 100644
index 000000000..b797b21a9
--- /dev/null
+++ b/Source/WebCore/css/mathml.css
@@ -0,0 +1,238 @@
+@namespace "http://www.w3.org/1998/Math/MathML";
+
+math {
+ font-family: STIXGeneral, Symbol, "Times New Roman", sans-serif;
+ display: inline-block;
+ padding: 0px;
+ margin: 0px;
+ text-align: left;
+ vertical-align: baseline;
+ line-height: 1.0;
+ padding-left: 1px;
+ padding-right: 1px;
+}
+
+math[display="block"] {
+ display: block;
+ page-break-inside: avoid;
+ margin-bottom: 1em;
+ text-align: center;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+mrow, mfenced {
+ display: inline-block;
+ white-space: nowrap;
+ vertical-align: baseline;
+}
+
+mfenced {
+ padding-left: 1px;
+ padding-right: 1px;
+}
+
+mi {
+ font-style: italic;
+ padding-right: 0.1em;
+}
+
+mi + mrow {
+ margin-left: 0.1em;
+}
+
+mfrac {
+ display: inline-block;
+}
+
+msub, msup {
+ display: inline-block;
+ vertical-align: baseline;
+}
+
+msub > * + * {
+ vertical-align: sub;
+ font-size: 0.75em;
+}
+
+msup > * + * {
+ vertical-align: super;
+ font-size: 0.75em;
+}
+
+msubsup {
+ display: inline-block;
+ vertical-align: baseline;
+}
+
+msubsup > * {
+ margin: 0px;
+ padding: 0px;
+}
+
+msubsup > * + * {
+ font-size: 0.75em;
+}
+
+munder, mover, munderover {
+ display: inline-block;
+ vertical-align: baseline;
+}
+
+munderover > * + *, mover > * + *, munder > * + * {
+ font-size: 0.75em;
+}
+
+mo, mn, mi, mtext {
+ padding: 0px;
+ margin: 0px;
+}
+
+mo {
+ display: inline-block;
+}
+
+math > mo, mrow > mo, mfenced > mo {
+ padding-right: 0.1em;
+}
+
+math[mathvariant="normal"], mstyle[mathvariant="normal"], mo[mathvariant="normal"], mn[mathvariant="normal"], mi[mathvariant="normal"], mtext[mathvariant="normal"], mspace[mathvariant="normal"], ms[mathvariant="normal"] {
+ font-style: normal;
+ font-weight: normal;
+}
+
+math[mathvariant="bold"], mstyle[mathvariant="bold"], mo[mathvariant="bold"], mn[mathvariant="bold"], mi[mathvariant="bold"], mtext[mathvariant="bold"], mspace[mathvariant="bold"], ms[mathvariant="bold"] {
+ font-style: normal;
+ font-weight: bold;
+}
+
+math[mathvariant="italic"], mstyle[mathvariant="italic"], mo[mathvariant="italic"], mn[mathvariant="italic"], mi[mathvariant="italic"], mtext[mathvariant="italic"], mspace[mathvariant="italic"], ms[mathvariant="italic"] {
+ font-style: italic;
+ font-weight: normal;
+}
+
+math[mathvariant="bold-italic"], mstyle[mathvariant="bold-italic"], mo[mathvariant="bold-italic"], mn[mathvariant="bold-italic"], mi[mathvariant="bold-italic"], mtext[mathvariant="bold-italic"], mspace[mathvariant="bold-italic"], ms[mathvariant="bold-italic"] {
+ font-weight: bold;
+ font-style: italic;
+}
+
+math[mathsize="small"], mstyle[mathsize="small"], mo[mathsize="small"], mn[mathsize="small"], mi[mathsize="small"], mtext[mathsize="small"], mspace[mathsize="small"], ms[mathsize="small"] {
+ font-size: 0.75em;
+}
+
+math[mathsize="normal"], mstyle[mathsize="normal"], mo[mathsize="normal"], mn[mathsize="normal"], mi[mathsize="normal"], mtext[mathsize="normal"], mspace[mathsize="normal"], ms[mathsize="normal"] {
+ font-size: 1em;
+}
+
+math[mathsize="big"], mstyle[mathsize="big"], mo[mathsize="big"], mn[mathsize="big"], mi[mathsize="big"], mtext[mathsize="big"], mspace[mathsize="big"], ms[mathsize="big"] {
+ font-size: 1.5em;
+}
+
+annotation, annotation-xml {
+ display:none;
+}
+
+mphantom {
+ visibility: hidden;
+}
+
+merror {
+ outline: solid thin red;
+ font-weight: bold;
+ font-family: sans-serif;
+ background-color: lightYellow;
+}
+
+msqrt {
+ display: inline-block;
+ padding-top: 0.2em;
+ padding-left: 0.75em;
+}
+
+mroot {
+ display: inline-block;
+ position: relative;
+ padding-top: 0.2em;
+ padding-left: 0.2em;
+}
+
+mroot > * + * {
+ font-size: 0.75em;
+ vertical-align: bottom;
+ position: absolute;
+ left: 0px;
+ padding-right: 0.4em;
+ padding-left: 0.2em;
+ padding-bottom: 0.2em;
+}
+
+mroot > * + mrow, mroot > * + mfenced {
+ padding-bottom: 0.4em;
+}
+
+mtable {
+ display: inline-table;
+ text-align: center;
+ vertical-align: -40%;
+}
+
+mtr {
+ display: table-row;
+}
+
+mtd {
+ display: table-cell;
+ padding: 0 0.5ex;
+}
+
+mtable[columnalign="left"], mtr[columnalign="left"], mtd[columnalign="left"] {
+ text-align: left;
+}
+
+mtable[columnalign="right"], mtr[columnalign="right"], mtd[columnalign="right"] {
+ text-align: right;
+}
+
+mtable[rowalign="top"] mtd, mtable mtr[rowalign="top"] mtd, mtable mtr mtd[rowalign="top"] {
+ vertical-align: top;
+}
+
+mtable[rowalign="bottom"] mtd, mtable mtr[rowalign="bottom"] mtd, mtable mtr mtd[rowalign="bottom"] {
+ vertical-align: bottom;
+}
+
+mtable[rowalign="center"] mtd, mtable mtr[rowalign="center"] mtd, mtable mtr mtd[rowalign="center"] {
+ vertical-align: middle;
+}
+
+mtable[frame="solid"] {
+ border: solid thin;
+}
+
+mtable[frame="dashed"] {
+ border: dashed thin;
+}
+
+mtable[rowlines="solid"], mtable[rowlines="dashed"], mtable[columnlines="solid"], mtable[columnlines="dashed"] {
+ border-collapse: collapse;
+}
+
+mtable[rowlines="solid"] > mtr + mtr {
+ border-top: solid thin;
+}
+
+mtable[rowlines="dashed"] > mtr + mtr {
+ border-top: dashed thin;
+}
+
+mtable[columnlines="solid"] > mtr > mtd + mtd {
+ border-left: solid thin;
+}
+
+mtable[columnlines="dashed"] > mtr > mtd + mtd {
+ border-left: dashed thin;
+}
+
+mspace[linebreak="newline"] {
+ display: block;
+}
diff --git a/Source/WebCore/css/mediaControls.css b/Source/WebCore/css/mediaControls.css
new file mode 100644
index 000000000..31c9d4326
--- /dev/null
+++ b/Source/WebCore/css/mediaControls.css
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2009, 2010, 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 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,
+ * 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.
+ */
+
+/* media controls */
+
+body:-webkit-full-page-media {
+ background-color: rgb(38, 38, 38);
+}
+
+audio {
+ width: 200px;
+ height: 16px;
+}
+
+::-webkit-media-controls {
+ width: inherit;
+ height: inherit;
+ position: relative;
+ display: block;
+ direction: ltr;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-user-select: none;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ z-index: 0;
+ overflow: hidden;
+ height: 16px;
+ text-align: right;
+}
+
+video:-webkit-full-page-media {
+ margin: auto;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+ bottom: 0px;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+ -webkit-appearance: media-mute-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+ -webkit-appearance: media-play-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+ -webkit-appearance: media-controls-background;
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-box-pack: end;
+ -webkit-box-flex: 1;
+ -webkit-user-select: none;
+ height: 16px;
+}
+
+audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
+ display: none;
+}
+
+audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display {
+ display: none;
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+ -webkit-appearance: media-slider;
+ display: -webkit-box;
+ -webkit-box-flex: 1;
+ height: 16px;
+ padding: 0px 2px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+ margin: initial;
+}
+
+audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
+ background-color: initial;
+ border: initial;
+ color: inherit;
+ margin: initial;
+}
+
+audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button {
+ -webkit-appearance: media-seek-back-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button {
+ -webkit-appearance: media-seek-forward-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
+ -webkit-appearance: media-fullscreen-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-rewind-button, video::-webkit-media-controls-rewind-button {
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-controls-return-to-realtime-button {
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button {
+ -webkit-appearance: media-toggle-closed-captions-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-volume-slider-mute-button, video::-webkit-media-controls-volume-slider-mute-button {
+ -webkit-appearance: media-volume-slider-mute-button;
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-fullscreen-volume-slider, video::-webkit-media-controls-fullscreen-volume-slider {
+ display: none;
+}
+
+audio::-webkit-media-controls-fullscreen-volume-min-button, video::-webkit-media-controls-fullscreen-volume-min-button {
+ display: none;
+}
+
+audio::-webkit-media-controls-fullscreen-volume-max-button, video::-webkit-media-controls-fullscreen-volume-max-button {
+ display: none;
+}
+
+video::-webkit-media-text-track-container {
+ position: absolute;
+ width: 100%;
+ overflow: hidden;
+
+ font-size: 22px;
+ font-family: sans-serif;
+ text-align: center;
+ color: rgba(255, 255, 255, 0);
+
+ letter-spacing: normal;
+ word-spacing: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-decoration: none;
+ pointer-events: none;
+ -webkit-user-select: none;
+}
+
+video::-webkit-media-text-track-display {
+ display: inline;
+ background-color: rgba(0, 0, 0, 0.8);
+ color: yellow;
+ padding: 0px 2px;
+}
diff --git a/Source/WebCore/css/mediaControlsChromium.css b/Source/WebCore/css/mediaControlsChromium.css
new file mode 100644
index 000000000..508d7445e
--- /dev/null
+++ b/Source/WebCore/css/mediaControlsChromium.css
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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,
+ * 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.
+ */
+
+/* Chromium default media controls */
+
+body:-webkit-full-page-media {
+ background-color: rgb(0, 0, 0);
+}
+
+audio {
+ width: 300px;
+ height: 32px;
+}
+
+audio:-webkit-full-page-media, video:-webkit-full-page-media {
+ max-height: 100%;
+ max-width: 100%;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+ -webkit-user-select: none;
+ position: absolute;
+ overflow: visible;
+ bottom: 0;
+ width: 100%;
+ height: 32px;
+ z-index: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+ bottom: 0px;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+ -webkit-appearance: media-mute-button;
+ position: absolute;
+ top: auto;
+ bottom: 0;
+ right: 0;
+ left: auto;
+
+ width: 34px;
+ height: 32px;
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+ -webkit-appearance: media-play-button;
+
+ position: absolute;
+ top: auto;
+ bottom: 7px;
+ left: 7px;
+ right: 6px;
+
+ width: 18px;
+ height: 19px;
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+ -webkit-appearance: media-timeline-container;
+ -webkit-user-select: none;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-box-pack: center;
+ -webkit-box-flex: 1;
+
+ position: absolute;
+ top: auto;
+ bottom: 0;
+ left: 30px;
+ right: 34px;
+
+ width: auto;
+ height: 32px;
+
+ border-left: 1px solid rgba(255, 255, 255, 0.2);
+ border-right: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
+ -webkit-appearance: media-current-time-display;
+ -webkit-user-select: none;
+ display: -webkit-box;
+ -webkit-box-flex: 0;
+ -webkit-box-pack: center;
+ -webkit-box-align: center;
+
+ overflow: hidden;
+ cursor: default;
+
+ line-height: 21px;
+ height: 20px;
+ width: 58px;
+
+ text-align: center;
+ font-family: Arial;
+ font-size: 16px;
+ font-weight: bold;
+ color: white;
+
+ letter-spacing: normal;
+ word-spacing: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-shadow: none;
+ text-decoration: none;
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+ -webkit-appearance: media-slider;
+ display: -webkit-box;
+ box-sizing: border-box;
+ -webkit-box-flex: 1;
+
+ padding: 0px;
+ margin: 0px 6px;
+ height: 18px;
+
+ border-color: rgba(255, 255, 255, 0.2);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 2px;
+ background-color: rgba(255, 255, 255, 0.08);
+ color: rgb(50, 140, 223);
+}
+
+audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container {
+ -webkit-appearance: media-volume-slider-container;
+ position: absolute;
+
+ width: 34px;
+ height: 100px;
+
+ background-color: rgba(0, 0, 0, 0.6);
+}
+
+audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
+ -webkit-appearance: media-volume-slider;
+ display: inline;
+ position: absolute;
+
+ top: 10px;
+ left: 12px;
+
+ width: 10px;
+ height: 80px;
+}
diff --git a/Source/WebCore/css/mediaControlsEfl.css b/Source/WebCore/css/mediaControlsEfl.css
new file mode 100644
index 000000000..e5d58089c
--- /dev/null
+++ b/Source/WebCore/css/mediaControlsEfl.css
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * 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,
+ * 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.
+ */
+
+/* EFLWebKit media controls. Extends mediaControls.css */
+
+audio {
+ width: 300px;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-user-select: none;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ z-index: 0;
+ overflow: hidden;
+ height: 20px;
+ text-align: right;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+ bottom: 0px;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+ -webkit-appearance: media-mute-button;
+ display: -webkit-box;
+ width: 20px;
+ height: 20px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+ -webkit-appearance: media-play-button;
+ display: -webkit-box;
+ width: 20px;
+ height: 20px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+ -webkit-appearance: media-controls-background;
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-box-pack: end;
+ -webkit-box-flex: 1;
+ -webkit-user-select: none;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
+ -webkit-appearance: media-current-time-display;
+ -webkit-user-select: none;
+ display: inline-block;
+ height: 20px;
+
+ padding: 4px;
+
+ text-align: center;
+ font-size: 10px;
+}
+
+audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display {
+ display: none;
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+ -webkit-appearance: media-slider;
+ display: -webkit-box;
+ -webkit-box-flex: 1;
+ height: 20px;
+ padding: 0px 2px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+ margin: initial;
+}
+
+audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container {
+ display: none;
+}
+
+audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+ margin: initial;
+}
+
+audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button {
+ -webkit-appearance: media-seek-back-button;
+ display: -webkit-box;
+ width: 20px;
+ height: 20px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button {
+ -webkit-appearance: media-seek-forward-button;
+ display: -webkit-box;
+ width: 20px;
+ height: 20px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
+ -webkit-appearance: media-fullscreen-button;
+ display: -webkit-box;
+ width: 20px;
+ height: 20px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-rewind-button, video::-webkit-media-controls-rewind-button {
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-controls-return-to-realtime-button {
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button {
+ -webkit-appearance: media-toggle-closed-captions-button;
+ display: -webkit-box;
+ width: 20px;
+ height: 20px;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
+
+audio::-webkit-media-controls-volume-slider-mute-button, video::-webkit-media-controls-volume-slider-mute-button {
+ -webkit-appearance: media-volume-slider-mute-button;
+ display: none;
+ background-color: initial;
+ border: initial;
+ color: inherit;
+}
diff --git a/Source/WebCore/css/mediaControlsGtk.css b/Source/WebCore/css/mediaControlsGtk.css
new file mode 100644
index 000000000..aba4412ef
--- /dev/null
+++ b/Source/WebCore/css/mediaControlsGtk.css
@@ -0,0 +1,105 @@
+/*
+ * WebKitGTK+ specific overrides for HTML5 media elements.
+ *
+ * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+audio {
+ height: 20px;
+ width: 300px;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: end;
+ -webkit-user-select: none;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ z-index: 0;
+ overflow: hidden;
+ text-align: right;
+ height: 100%;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+ width: 20px;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+ width: 20px;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+ height: 20px;
+ border-left: 1px solid rgba(255, 255, 255, 0.2);
+ border-right: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+ height: 20px;
+}
+
+audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
+ -webkit-appearance: media-current-time-display;
+ -webkit-user-select: none;
+ display: inline-block;
+ height: 20px;
+
+ padding: 5px;
+
+ text-align: center;
+ font-size: 10px;
+}
+
+audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button {
+ width: 20px;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button {
+ width: 20px;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
+ width: 20px;
+ height: 20px;
+}
+
+audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container {
+ -webkit-appearance: media-volume-slider-container;
+ position: absolute;
+ height: 100px;
+ width: 20px;
+}
+
+audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
+ -webkit-appearance: media-volume-slider;
+ display: inline;
+ position: absolute;
+ width: 14px;
+ height: 95px;
+
+ left: 3px;
+ top: 5px;
+}
diff --git a/Source/WebCore/css/mediaControlsQt.css b/Source/WebCore/css/mediaControlsQt.css
new file mode 100644
index 000000000..64e0ec524
--- /dev/null
+++ b/Source/WebCore/css/mediaControlsQt.css
@@ -0,0 +1,260 @@
+/*
+ * QtWebKit specific overrides for HTML5 media elements.
+ *
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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,
+ * 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.
+ */
+
+ /* QtWebKit media controls. Extends mediaControls.css */
+
+audio {
+ height: 34px;
+ width: 400px;
+}
+
+audio::-webkit-media-controls-panel {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: end;
+ -webkit-user-select: none;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ z-index: 0;
+ overflow: visible;
+ height: 100%;
+ text-align: right;
+}
+
+video::-webkit-media-controls-panel {
+ display: -webkit-box;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: end;
+ -webkit-user-select: none;
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ z-index: 0;
+ overflow: hidden;
+ height: 100%;
+ text-align: right;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+ bottom: 0px;
+}
+
+audio::-webkit-media-controls-mute-button {
+ width: 12px;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 5px 5px 3px;
+ border: none !important;
+}
+
+video::-webkit-media-controls-mute-button {
+ width: 12px;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 5px 5px 3px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-play-button {
+ width: 9px;
+ height: 12px;
+ padding: 6px 12px 6px 11px;
+ margin: 5px 3px 5px 5px;
+ border: none !important;
+}
+
+video::-webkit-media-controls-play-button {
+ width: 9px;
+ height: 12px;
+ padding: 6px 12px 6px 11px;
+ margin: 5px 3px 5px 5px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-timeline-container {
+ height: 34px;
+}
+
+video::-webkit-media-controls-timeline-container {
+ height: 34px;
+}
+
+audio::-webkit-media-controls-current-time-display {
+ -webkit-appearance: media-current-time-display;
+ -webkit-user-select: none;
+ display: inline-block;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 3px;
+
+ overflow: hidden;
+ cursor: default;
+
+ text-align: center;
+ font-size: 10px;
+ font-family: Verdana;
+ font-weight: bold;
+ color: white;
+}
+
+video::-webkit-media-controls-current-time-display {
+ -webkit-appearance: media-current-time-display;
+ -webkit-user-select: none;
+ display: inline-block;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 3px;
+
+ overflow: hidden;
+ cursor: default;
+
+ text-align: center;
+ font-size: 10px;
+ font-family: Verdana;
+ font-weight: bold;
+ color: white;
+}
+
+audio::-webkit-media-controls-time-remaining-display {
+ display: none;
+}
+
+video::-webkit-media-controls-time-remaining-display {
+ display: none;
+}
+
+audio::-webkit-media-controls-timeline {
+ height: 12px; /* See RenderThemeQt::adjustSliderThumbSize(). */
+ padding: 6px 8px;
+ margin: 5px 3px;
+}
+
+video::-webkit-media-controls-timeline {
+ height: 12px; /* See RenderThemeQt::adjustSliderThumbSize(). */
+ padding: 6px 8px;
+ margin: 5px 3px;
+}
+
+audio::-webkit-media-controls-volume-slider-container {
+ -webkit-appearance: media-volume-slider-container;
+ position: absolute;
+ height: 103px;
+ width: 24px;
+}
+
+video::-webkit-media-controls-volume-slider-container {
+ -webkit-appearance: media-volume-slider-container;
+ position: absolute;
+ height: 103px;
+ width: 24px;
+}
+
+audio::-webkit-media-controls-volume-slider {
+ -webkit-appearance: media-volume-slider;
+ display: inline;
+ position: absolute;
+
+ width: 12px; /* See RenderThemeQt::adjustSliderThumbSize(). */
+ padding: 6px;
+ height: 88px;
+ margin: 0 0 3px 0;
+}
+
+video::-webkit-media-controls-volume-slider {
+ -webkit-appearance: media-volume-slider;
+ display: inline;
+ position: absolute;
+
+ width: 12px; /* See RenderThemeQt::adjustSliderThumbSize(). */
+ padding: 6px;
+ height: 88px;
+ margin: 0 0 3px 0;
+}
+
+audio::-webkit-media-controls-seek-back-button {
+ display: none;
+}
+
+video::-webkit-media-controls-seek-back-button {
+ display: none;
+}
+
+audio::-webkit-media-controls-seek-forward-button {
+ display: none;
+}
+
+video::-webkit-media-controls-seek-forward-button {
+ display: none;
+}
+
+audio::-webkit-media-controls-fullscreen-button {
+ display: none;
+}
+
+video::-webkit-media-controls-fullscreen-button {
+ top: 0px;
+ right: 0px;
+ width: 12px;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 5px 5px 3px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-rewind-button {
+ display: none;
+}
+
+video::-webkit-media-controls-rewind-button {
+ display: none;
+}
+
+audio::-webkit-media-controls-return-to-realtime-button {
+ display: none;
+}
+
+video::-webkit-media-controls-return-to-realtime-button {
+ display: none;
+}
+
+audio::-webkit-media-controls-toggle-closed-captions-button {
+ display: none;
+}
+
+video::-webkit-media-controls-toggle-closed-captions-button {
+ display: none;
+}
+
+::-webkit-media-controls-mute-button,
+::-webkit-media-controls-play-button,
+::-webkit-media-controls-timeline,
+::-webkit-media-controls-volume-slider,
+::-webkit-media-controls-fullscreen-button
+{
+ box-sizing: content-box !important;
+}
diff --git a/Source/WebCore/css/mediaControlsQtFullscreen.css b/Source/WebCore/css/mediaControlsQtFullscreen.css
new file mode 100644
index 000000000..35cbf75d8
--- /dev/null
+++ b/Source/WebCore/css/mediaControlsQtFullscreen.css
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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,
+ * 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.
+ */
+video::-webkit-media-controls-panel {
+/* The control panel is only play button for full screen */
+ display: -webkit-box;
+ -webkit-box-align: center;
+ -webkit-box-pack: center;
+ width: 100%;
+ height: 100%;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+ display: none;
+}
+
+video::-webkit-media-controls-mute-button {
+ display: none;
+}
+
+video::-webkit-media-controls-play-button {
+ display: -webkit-box;
+ -webkit-box-align: center;
+ -webkit-box-pack: center;
+ width: 50px;
+ height: 50px;
+ padding: 20px;
+}
+
+video::-webkit-media-controls-timeline-container {
+ display: none;
+}
+
+video::-webkit-media-controls-current-time-display {
+ -webkit-appearance: media-current-time-display;
+ -webkit-user-select: none;
+ display: none;
+}
+
+video::-webkit-media-controls-time-remaining-display {
+ display: none;
+}
+
+video::-webkit-media-controls-timeline {
+ display: none;
+}
+
+video::-webkit-media-controls-volume-slider-container {
+ -webkit-appearance: media-volume-slider-container;
+ display: none;
+}
+
+video::-webkit-media-controls-volume-slider {
+ -webkit-appearance: media-volume-slider;
+ display: none;
+}
+
+video::-webkit-media-controls-seek-back-button {
+ display: none;
+}
+
+video::-webkit-media-controls-seek-forward-button {
+ display: none;
+}
+
+video::-webkit-media-controls-fullscreen-button {
+ display: none;
+}
+
+video::-webkit-media-controls-rewind-button {
+ display: none;
+}
+
+video::-webkit-media-controls-return-to-realtime-button {
+ display: none;
+}
+
+video::-webkit-media-controls-toggle-closed-captions-button {
+ display: none;
+}
+
diff --git a/Source/WebCore/css/mediaControlsQuickTime.css b/Source/WebCore/css/mediaControlsQuickTime.css
new file mode 100644
index 000000000..5866a916f
--- /dev/null
+++ b/Source/WebCore/css/mediaControlsQuickTime.css
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2009, 2010, 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 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,
+ * 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.
+ */
+
+/* alternate media controls - Extend mediaControls.css */
+
+audio {
+ width: 200px;
+ height: 25px;
+}
+
+audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel {
+ /* In mediaControls.css */
+ -webkit-appearance: media-controls-background;
+ overflow: visible;
+ height: 25px;
+}
+
+video:-webkit-full-page-media::-webkit-media-controls-panel {
+ bottom: 0px;
+}
+
+audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
+ -webkit-box-ordinal-group: 2; /* Before the fullscreen button */
+
+ width: 14px;
+ height: 12px;
+ margin-left: 2px;
+ margin-right: 9px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
+ width: 16px;
+ height: 16px;
+ margin-left: 6px;
+ margin-right: 1px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container {
+ -webkit-appearance: none;
+ -webkit-box-orient: horizontal;
+ -webkit-box-align: center;
+ -webkit-box-pack: center;
+ -webkit-box-flex: 1;
+ text-align: right;
+ height: auto;
+}
+
+audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display {
+ -webkit-user-select: none;
+ display: -webkit-box;
+ -webkit-box-flex: 0;
+ -webkit-box-pack: center;
+ -webkit-box-align: center;
+ cursor: default;
+ font: -webkit-small-control;
+ font-size: 9px;
+ overflow: hidden;
+ width: 45px;
+ color: white;
+ text-shadow: black 0px 1px 1px;
+
+ letter-spacing: normal;
+ word-spacing: normal;
+ line-height: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-decoration: none;
+}
+
+audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display {
+ -webkit-user-select: none;
+ display: -webkit-box;
+ -webkit-box-flex: 0;
+ -webkit-box-pack: center;
+ -webkit-box-align: center;
+ cursor: default;
+ font: -webkit-small-control;
+ font-size: 9px;
+ overflow: hidden;
+ width: 45px;
+ color: white;
+ text-shadow: black 0px 1px 1px;
+
+ letter-spacing: normal;
+ word-spacing: normal;
+ line-height: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-decoration: none;
+}
+
+audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
+ display: -webkit-box;
+ -webkit-box-flex: 1;
+ height: 13px;
+ padding: 0px;
+ margin: 0px;
+ margin-top: 2px;
+}
+
+audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button {
+ display: none;
+ width: 0px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button {
+ display: none;
+ width: 0px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button {
+ width: 16px;
+ height: 16px;
+ margin-left: 7px;
+ margin-right: 7px;
+ -webkit-box-ordinal-group: 4; /* At the very end */
+ border: none !important;
+}
+
+audio::-webkit-media-controls-rewind-button, video::-webkit-media-controls-rewind-button {
+ display: -webkit-box;
+ -webkit-appearance: media-rewind-button;
+ width: 18px;
+ height: 18px;
+ margin-bottom: 1px;
+ margin-left: 6px;
+ margin-right: 2px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-controls-return-to-realtime-button {
+ display: none;
+ -webkit-appearance: media-return-to-realtime-button;
+ width: 16px;
+ height: 11px;
+ margin-left: 6px;
+ margin-right: 2px;
+ border: none !important;
+}
+
+audio::-webkit-media-controls-status-display, video::-webkit-media-controls-status-display {
+ -webkit-user-select: none;
+ cursor: default;
+ display: -webkit-box;
+ -webkit-box-flex: 1;
+ font: -webkit-small-control;
+ color: white;
+ font-size: 10px;
+ line-height: 13px;
+ overflow: hidden;
+ text-shadow: black 0px 1px 1px;
+ margin-left: 10px;
+ margin-right: 10px;
+
+ letter-spacing: normal;
+ word-spacing: normal;
+ line-height: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-decoration: none;
+}
+
+audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button {
+ -webkit-appearance: media-toggle-closed-captions-button;
+ display: -webkit-box;
+ width: 16px;
+ height: 16px;
+ margin-left: 7px;
+ margin-right: 7px;
+ -webkit-box-ordinal-group: 3; /* between mute and fullscreen */
+ border: none !important;
+}
+
+audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container {
+ -webkit-appearance: media-volume-slider-container;
+ position: absolute;
+
+ top: 0;
+ left: 0;
+
+ width: 22px;
+ height: 114px;
+}
+
+audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider {
+ -webkit-appearance: media-volume-slider;
+ display: inline;
+ position: absolute;
+
+ top: 7px;
+ left: 6px;
+
+ width: 10px;
+ height: 80px;
+}
+
+audio::-webkit-media-controls-volume-slider-mute-button, video::-webkit-media-controls-volume-slider-mute-button {
+ -webkit-appearance: media-volume-slider-mute-button;
+ display: inline;
+ position: absolute;
+
+ bottom: 5px;
+ left: 4px;
+
+ width: 14px;
+ height: 12px;
+ border: none !important;
+}
diff --git a/Source/WebCore/css/mobileThemeQt.css b/Source/WebCore/css/mobileThemeQt.css
new file mode 100644
index 000000000..f0378de70
--- /dev/null
+++ b/Source/WebCore/css/mobileThemeQt.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+input[type="submit"], select {
+ font-family: "Nokia Pure Text", Arial, sans-serif;
+}
+
+input[type="submit"]:disabled, input[type="submit"]:disabled:active, select:disabled, input[type="text"]:disabled {
+ color: #808080;
+}
+
+input[type="submit"]:active {
+ color: white;
+}
diff --git a/Source/WebCore/css/quirks.css b/Source/WebCore/css/quirks.css
new file mode 100644
index 000000000..52d07e678
--- /dev/null
+++ b/Source/WebCore/css/quirks.css
@@ -0,0 +1,54 @@
+/*
+ * Additonal style sheet used to render HTML pages in quirks mode.
+ *
+ * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2006, 2007 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.
+ *
+ */
+
+/* Give floated images margins of 3px */
+img[align="left"] {
+ margin-right: 3px;
+}
+img[align="right"] {
+ margin-left: 3px;
+}
+
+/* Tables reset both line-height and white-space in quirks mode. */
+/* Compatible with WinIE. Note that font-family is *not* reset. */
+table {
+ white-space: normal;
+ line-height: normal;
+ font-weight: normal;
+ font-size: medium;
+ font-variant: normal;
+ font-style: normal;
+ color: -webkit-text;
+ text-align: -webkit-auto
+}
+
+/* This will apply only to text fields, since all other inputs already use border box sizing */
+input:not([type=image]), textarea {
+ box-sizing: border-box;
+}
+
+/* Set margin-bottom for form element in quirks mode. */
+/* Compatible with Gecko. (Doing this only for quirks mode is a fix for bug 17696.) */
+form {
+ margin-bottom: 1em
+}
diff --git a/Source/WebCore/css/svg.css b/Source/WebCore/css/svg.css
new file mode 100644
index 000000000..171c1c41f
--- /dev/null
+++ b/Source/WebCore/css/svg.css
@@ -0,0 +1,70 @@
+/*
+ * The default style sheet used to render SVG.
+ *
+ * Copyright (C) 2005, 2006 Apple Computer, 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 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.
+ */
+
+@namespace "http://www.w3.org/2000/svg";
+
+/*
+ When an outermost SVG 'svg' element is stand-alone or embedded inline within a parent XML grammar
+ which does not use CSS layout [CSS2-LAYOUT] or XSL formatting [XSL], the 'overflow' property on the
+ outermost 'svg' element is ignored for the purposes of visual rendering and the initial clipping path is set
+ to the bounds of the initial viewport.
+
+ When an outermost 'svg' element is embedded inline within a parent XML grammar which uses CSS layout
+ [CSS2-LAYOUT] or XSL formatting [XSL], if the 'overflow' property has the value hidden or scroll, then
+ the user agent will establish an initial clipping path equal to the bounds of the initial viewport; otherwise,
+ the initial clipping path is set according to the clipping rules as defined in [CSS2-overflow].
+
+ Opera/Firefox & WebKit agreed on NOT setting "overflow: hidden" for the outermost svg element - SVG 1.1 Errata
+ contains these changes as well as all future SVG specifications: see http://lists.w3.org/Archives/Public/public-svg-wg/2008JulSep/0347.html
+*/
+
+svg:not(:root), symbol, image, marker, pattern, foreignObject {
+ overflow: hidden
+}
+
+svg {
+ width: 100%;
+ height: 100%;
+}
+
+text, foreignObject {
+ display: block
+}
+
+text, tspan, textPath {
+ white-space: nowrap
+}
+
+text, tspan, tref {
+ -webkit-text-size-adjust: none;
+}
+
+/* states */
+
+:focus {
+ outline: auto 5px -webkit-focus-ring-color
+}
diff --git a/Source/WebCore/css/themeChromium.css b/Source/WebCore/css/themeChromium.css
new file mode 100644
index 000000000..761ddab0a
--- /dev/null
+++ b/Source/WebCore/css/themeChromium.css
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+/* These styles override other user-agent styles for Chromium. */
+
+::-webkit-validation-bubble {
+ opacity: 1;
+}
+
+::-webkit-validation-bubble-message {
+ background: white;
+ border-color: #ccc #aaa #888;
+ border-width: 1px;
+ box-shadow: 2px 2px 4px rgba(100,100,100,0.3);
+ max-width: 300px;
+ top: -1px;
+}
+
+::-webkit-validation-bubble-arrow {
+ background: white;
+ border-color: #ccc;
+ border-width: 1px;
+ box-shadow: none;
+}
+
+::-webkit-validation-bubble-arrow-clipper {
+ height: 13px;
+}
+
+::-webkit-validation-bubble-icon {
+ /* The image was taken from http://src.chromium.org/viewvc/chrome/trunk/src/chrome/app/theme/update_available.png?revision=50754&view=markup */
+ background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAACVklEQVQ4T6WRMWsUURSFv/t2ZjObZNUkREUFlYiIYGWl2Cj+AEs7wdZG0NpGwcJGxcpaWwWttbMQAmqRwoAEEiKohGTXdXdnZ+YeizebRAsbHzweXO4995zvmST+99izm+3EjOt7p+zhfDu0shQwgUAOKF4J5HVd8e10Bw8OXbp3J8mazKYN7h+fb7QOzxnNxs6glwVeFFhoYKGJ3GthQxLdtLx96NzV10mWWJo1ac+3oZWAezQyKks6xQx5coQk/05b38iaAXdAwgTTTUyj7rEQTAqmqhF2Wxa9zS7pqRssXHvH3otP2NjoURVCLrwCLwUVAEmQx+zuUUAuJFGOIEwdAWBi31EGfTHKHVzIHXdtM0u2wVVAJVSBrG7wEoCqGOIlVIXA4lI89sIuEeTILcaxKCoZAEJ1VHYc1AkQJDGCxaEq5pSJAJTDTQCK/iZVAVSCymqB2jUai9TFmg0Sk5MTdD4+5cv6JzqrSwSlBItO3PWXE9Uwq4BqJi4IIaXaWGZrZYkgY3ZfRiD+ihQXjZkEtvN5LLrARW+rx8TZm5y51+XglceMBoPIawy1nvtTpGYyFipHoMkDWNamMbtArwdloehg1wzCklG/TzqdNfAdYO7QmmyytfiUldUP/Fz7DJ6ACx9/MWMm2hMu3HrbIWQv8199ymEfzweU+YBEI/Z0lrHF52Tri8xNlViZ48Mc5Tk+yGnsP/HDWjMTJsm+fnx1uvf+0ZO5tHcmCRbGm/AdiNubEapKs2x2OH357pvm0fMvTFIKzAALwElgqpb41wmAgDVg8TfGt7U0pM19vgAAAABJRU5ErkJggg==');
+ height: 17px;
+ margin-right: 6px;
+ width: 17px;
+}
+
+::-webkit-validation-bubble-heading {
+ font-weight: normal;
+}
+
+::-webkit-validation-bubble-body {
+ font-size: smaller;
+ color: #444;
+}
+
+input:disabled, isindex:disabled, textarea:disabled {
+ color: #545454; /* Color::light() for #000000. See RenderTextControl.cpp:disabledTextColor */
+}
+
diff --git a/Source/WebCore/css/themeChromiumLinux.css b/Source/WebCore/css/themeChromiumLinux.css
new file mode 100644
index 000000000..a6a88284d
--- /dev/null
+++ b/Source/WebCore/css/themeChromiumLinux.css
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+/* These styles override other user-agent styles for Chromium on Linux. */
+
+select {
+ background-color: #dddddd;
+}
+
+select:not([size]):not([multiple]) option,
+select[size="0"] option,
+select[size="1"] option {
+ background-color: #f7f7f7;
+}
diff --git a/Source/WebCore/css/themeChromiumSkia.css b/Source/WebCore/css/themeChromiumSkia.css
new file mode 100644
index 000000000..bcd05f0f4
--- /dev/null
+++ b/Source/WebCore/css/themeChromiumSkia.css
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+/* These styles override other user-agent styles for Chromium using Skia. */
+
+/* Option elements inherit their font (see themeWin.css). However, their
+ * font weight should always be normal, to distinguish from optgroup labels. */
+option {
+ font-weight: normal !important;
+}
diff --git a/Source/WebCore/css/themeQtNoListboxes.css b/Source/WebCore/css/themeQtNoListboxes.css
new file mode 100644
index 000000000..4c5e44ad7
--- /dev/null
+++ b/Source/WebCore/css/themeQtNoListboxes.css
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+select[size],
+select[multiple],
+select[size][multiple] {
+ -webkit-appearance: menulist;
+ -webkit-box-align: center;
+ border: 1px solid;
+ -webkit-border-radius: 5px;
+ white-space: pre;
+}
diff --git a/Source/WebCore/css/themeWin.css b/Source/WebCore/css/themeWin.css
new file mode 100644
index 000000000..0838b1126
--- /dev/null
+++ b/Source/WebCore/css/themeWin.css
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/* These styles override the default styling for HTML elements as defined in
+ WebCore/css/html.css. So far we have used this file exclusively for
+ making our form elements match Firefox's. */
+
+input:not([type]),
+input[type="color"],
+input[type="date"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="email"],
+input[type="month"],
+input[type="number"],
+input[type="password"],
+input[type="tel"],
+input[type="text"],
+input[type="time"],
+input[type="url"],
+input[type="week"] {
+ padding:1px 0;
+}
+
+input[type="search"] {
+ padding:1px;
+}
+
+input[type="checkbox"] {
+ margin:3px 3px 3px 4px;
+}
+
+input[type="radio"] {
+ margin:3px 3px 0 5px;
+}
+
+/* Not sure this is the right color. #EBEBE4 is what Firefox uses.
+ FIXME: Figure out how to support legacy input rendering.
+ FIXME: Add input[type="file"] once we figure out our file inputs.
+ FIXME: Add input[type="image"] once we figure out our image inputs.
+ FIXME: We probably do the wrong thing if you put an invalid input type.
+ do we care?
+*/
+textarea:disabled,
+input:not([type]):disabled,
+input[type="color"]:disabled,
+input[type="date"]:disabled,
+input[type="datetime"]:disabled,
+input[type="datetime-local"]:disabled,
+input[type="email"]:disabled,
+input[type="month"]:disabled,
+input[type="password"]:disabled,
+input[type="number"]:disabled,
+input[type="search"]:disabled,
+input[type="tel"]:disabled,
+input[type="text"]:disabled,
+input[type="time"]:disabled,
+input[type="url"]:disabled,
+input[type="week"]:disabled {
+ background-color: #EBEBE4;
+}
+
+input[type="search"]::-webkit-search-cancel-button {
+ margin-right: 3px;
+}
+
+input[type="search"]::-webkit-search-results-decoration {
+ margin: 0 3px 0 2px;
+}
+
+input[type="search"]::-webkit-search-results-button {
+ margin: 0 3px 0 2px;
+}
+
+input::-webkit-outer-spin-button {
+ margin: 0;
+}
+
+input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button, button {
+ padding: 1px 6px;
+}
+
+/* Windows selects are not rounded. Custom borders for them shouldn't be either. */
+keygen,
+select,
+select[size="0"],
+select[size="1"] {
+ -webkit-border-radius: 0;
+}
+
+/* Option font must be inherited because we depend on computing the size of the
+ <select> based on the size of the options, and they must use the same font
+ for that computation to be correct */
+option {
+ font: inherit !important;
+}
+
+textarea {
+ font-family: monospace;
+}
diff --git a/Source/WebCore/css/themeWinQuirks.css b/Source/WebCore/css/themeWinQuirks.css
new file mode 100644
index 000000000..c69b74c71
--- /dev/null
+++ b/Source/WebCore/css/themeWinQuirks.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+/* These styles override the default styling for HTML elements in quirks-mode
+ as defined in WebCore/css/quirks.css. So far we have used this file exclusively for
+ making our form elements match Firefox's. */
+
+textarea {
+ /* Matches IE's text offsets in quirksmode (causes text to wrap the same as IE). */
+ padding: 2px 0 0 2px;
+}
diff --git a/Source/WebCore/css/tokenizer.flex b/Source/WebCore/css/tokenizer.flex
new file mode 100644
index 000000000..c28dbcafa
--- /dev/null
+++ b/Source/WebCore/css/tokenizer.flex
@@ -0,0 +1,130 @@
+%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;}
+
+%%
diff --git a/Source/WebCore/css/view-source.css b/Source/WebCore/css/view-source.css
new file mode 100644
index 000000000..129d28219
--- /dev/null
+++ b/Source/WebCore/css/view-source.css
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2006 Apple Computer, 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 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,
+ * 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.
+ */
+
+body {
+ margin: 0
+}
+
+table {
+ width: 100%;
+ border-spacing: 0;
+ counter-reset: lines;
+ white-space: pre-wrap !important;
+ margin: 0;
+ word-break: break-word;
+ font-size: initial;
+ font-family: monospace;
+}
+
+td {
+ padding: 0 !important;
+ vertical-align: baseline
+}
+
+.webkit-line-gutter-backdrop, .webkit-line-number {
+ /* Keep this in sync with inspector.css (.webkit-line-gutter-backdrop) */
+ box-sizing: border-box;
+ padding: 0 4px !important;
+ width: 31px;
+ background-color: rgb(240, 240, 240);
+ border-right: 1px solid rgb(187, 187, 187) !important;
+ -webkit-user-select: none;
+}
+
+.webkit-line-gutter-backdrop {
+ /* Keep this in sync with inspector.css (.webkit-line-gutter-backdrop) */
+ position: absolute;
+ z-index: -1;
+ left: 0;
+ top: 0;
+ height: 100%
+}
+
+.webkit-line-number {
+ text-align: right;
+ color: rgb(128, 128, 128);
+ word-break: normal;
+ white-space: nowrap;
+ font-size: 9px;
+ font-family: Helvetica
+}
+
+.webkit-line-number::before {
+ content: counter(lines);
+ counter-increment: lines;
+ -webkit-user-select: none
+}
+
+tbody:last-child .webkit-line-content:empty:before {
+ content: " ";
+}
+
+.webkit-line-content {
+ padding: 0 5px !important;
+}
+
+.webkit-html-tag {
+ /* Keep this in sync with inspector.css (.webkit-html-tag) */
+ color: rgb(136, 18, 128);
+}
+
+.webkit-html-attribute-name {
+ /* Keep this in sync with inspector.css (.webkit-html-attribute-name) */
+ color: rgb(153, 69, 0);
+}
+
+.webkit-html-attribute-value {
+ /* Keep this in sync with inspector.css (.webkit-html-attribute-value) */
+ color: rgb(26, 26, 166);
+}
+
+.webkit-html-external-link, .webkit-html-resource-link {
+ /* Keep this in sync with inspector.css (.webkit-html-external-link, .webkit-html-resource-link) */
+ color: #00e;
+}
+
+.webkit-html-external-link {
+ /* Keep this in sync with inspector.css (.webkit-html-external-link) */
+ text-decoration: none;
+}
+
+.webkit-html-external-link:hover {
+ /* Keep this in sync with inspector.css (.webkit-html-external-link:hover) */
+ text-decoration: underline;
+}
+
+.webkit-html-comment {
+ /* Keep this in sync with inspector.css (.webkit-html-comment) */
+ color: rgb(35, 110, 37);
+}
+
+.webkit-html-doctype {
+ /* Keep this in sync with inspector.css (.webkit-html-doctype) */
+ color: rgb(192, 192, 192);
+}
+
+.webkit-html-entity {
+ rgb(136, 18, 128);
+}
+
+.webkit-html-message-bubble {
+ -webkit-box-shadow: black 0px 2px 5px;
+ -webkit-border-radius: 9px;
+ -webkit-border-fit: lines;
+ min-height: 13px;
+ font-size: 9px;
+ font-family: Lucida Grande, sans-serif;
+ font-weight: bold;
+ margin: 6px 25px;
+ padding: 0 7px 1px;
+}
+
+.webkit-html-warning-message {
+ background-color: rgb(100%, 62%, 42%);
+ border: 2px solid rgb(100%, 52%, 21%);
+}
+
+.webkit-html-error-message {
+ background-color: rgb(100%, 42%, 42%);
+ border: 2px solid rgb(100%, 31%, 31%);
+}
+
+.webkit-html-message-line {
+ padding-left: 23px;
+ text-indent: -20px;
+}
+
+.webkit-html-message-icon {
+ position: relative;
+ top: 2px;
+ margin: 0 4px;
+}