summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/css
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-18 13:36:51 +0100
committerSteve Block <steveblock@google.com>2011-05-24 15:38:28 +0100
commit2fc2651226baac27029e38c9d6ef883fa32084db (patch)
treee396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/css
parentb3725cedeb43722b3b175aaeff70552e562d2c94 (diff)
downloadexternal_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/css')
-rw-r--r--Source/WebCore/css/CSSCanvasValue.cpp2
-rw-r--r--Source/WebCore/css/CSSCanvasValue.h2
-rw-r--r--Source/WebCore/css/CSSComputedStyleDeclaration.cpp45
-rw-r--r--Source/WebCore/css/CSSFontFaceSource.cpp16
-rw-r--r--Source/WebCore/css/CSSFontFaceSource.h6
-rw-r--r--Source/WebCore/css/CSSFunctionValue.cpp15
-rw-r--r--Source/WebCore/css/CSSFunctionValue.h2
-rw-r--r--Source/WebCore/css/CSSGradientValue.cpp48
-rw-r--r--Source/WebCore/css/CSSGradientValue.h4
-rw-r--r--Source/WebCore/css/CSSGrammar.y85
-rw-r--r--Source/WebCore/css/CSSImageGeneratorValue.h2
-rw-r--r--Source/WebCore/css/CSSImageValue.cpp4
-rw-r--r--Source/WebCore/css/CSSMediaRule.cpp8
-rw-r--r--Source/WebCore/css/CSSPageRule.cpp5
-rw-r--r--Source/WebCore/css/CSSPageRule.h6
-rw-r--r--Source/WebCore/css/CSSParser.cpp99
-rw-r--r--Source/WebCore/css/CSSParser.h17
-rw-r--r--Source/WebCore/css/CSSParserValues.cpp25
-rw-r--r--Source/WebCore/css/CSSParserValues.h31
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.cpp87
-rw-r--r--Source/WebCore/css/CSSPrimitiveValue.h2
-rw-r--r--Source/WebCore/css/CSSRuleList.cpp7
-rw-r--r--Source/WebCore/css/CSSSelector.cpp197
-rw-r--r--Source/WebCore/css/CSSSelector.h124
-rw-r--r--Source/WebCore/css/CSSSelectorList.cpp44
-rw-r--r--Source/WebCore/css/CSSSelectorList.h17
-rw-r--r--Source/WebCore/css/CSSStyleRule.h2
-rw-r--r--Source/WebCore/css/CSSStyleSelector.cpp620
-rw-r--r--Source/WebCore/css/CSSStyleSelector.h52
-rw-r--r--Source/WebCore/css/CSSStyleSheet.cpp21
-rw-r--r--Source/WebCore/css/CSSStyleSheet.h3
-rw-r--r--Source/WebCore/css/CSSValue.h3
-rw-r--r--Source/WebCore/css/CSSValueList.cpp11
-rw-r--r--Source/WebCore/css/CSSValueList.h2
-rw-r--r--Source/WebCore/css/WebKitCSSKeyframesRule.cpp12
-rw-r--r--Source/WebCore/css/WebKitCSSMatrix.cpp4
-rw-r--r--Source/WebCore/css/html.css66
-rw-r--r--Source/WebCore/css/mediaControls.css35
-rw-r--r--Source/WebCore/css/mediaControlsChromium.css3
-rw-r--r--Source/WebCore/css/mediaControlsQt.css15
-rw-r--r--Source/WebCore/css/themeChromiumLinux.css5
-rw-r--r--Source/WebCore/css/themeWin.css34
42 files changed, 1047 insertions, 741 deletions
diff --git a/Source/WebCore/css/CSSCanvasValue.cpp b/Source/WebCore/css/CSSCanvasValue.cpp
index e28def9..7f61d25 100644
--- a/Source/WebCore/css/CSSCanvasValue.cpp
+++ b/Source/WebCore/css/CSSCanvasValue.cpp
@@ -83,7 +83,7 @@ HTMLCanvasElement* CSSCanvasValue::element(Document* document)
return m_element;
}
-Image* CSSCanvasValue::image(RenderObject* renderer, const IntSize& /*size*/)
+PassRefPtr<Image> CSSCanvasValue::image(RenderObject* renderer, const IntSize& /*size*/)
{
ASSERT(m_clients.contains(renderer));
HTMLCanvasElement* elt = element(renderer->document());
diff --git a/Source/WebCore/css/CSSCanvasValue.h b/Source/WebCore/css/CSSCanvasValue.h
index 4cd4280..27b8f2b 100644
--- a/Source/WebCore/css/CSSCanvasValue.h
+++ b/Source/WebCore/css/CSSCanvasValue.h
@@ -40,7 +40,7 @@ public:
virtual String cssText() const;
- virtual Image* image(RenderObject*, const IntSize&);
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&);
virtual bool isFixedSize() const { return true; }
virtual IntSize fixedSize(const RenderObject*);
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
index 89564c3..f1c7fdf 100644
--- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -1148,26 +1149,30 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
return CSSPrimitiveValue::create(style->listStylePosition());
case CSSPropertyListStyleType:
return CSSPrimitiveValue::create(style->listStyleType());
- case CSSPropertyMarginTop:
- if (renderer && renderer->isBox())
- // FIXME: Supposed to return the percentage if percentage was specified.
- return zoomAdjustedPixelValue(toRenderBox(renderer)->marginTop(), style.get());
- return CSSPrimitiveValue::create(style->marginTop());
- case CSSPropertyMarginRight:
- if (renderer && renderer->isBox())
- // FIXME: Supposed to return the percentage if percentage was specified.
- return zoomAdjustedPixelValue(toRenderBox(renderer)->marginRight(), style.get());
- return CSSPrimitiveValue::create(style->marginRight());
- case CSSPropertyMarginBottom:
- if (renderer && renderer->isBox())
- // FIXME: Supposed to return the percentage if percentage was specified.
- return zoomAdjustedPixelValue(toRenderBox(renderer)->marginBottom(), style.get());
- return CSSPrimitiveValue::create(style->marginBottom());
- case CSSPropertyMarginLeft:
- if (renderer && renderer->isBox())
- // FIXME: Supposed to return the percentage if percentage was specified.
- return zoomAdjustedPixelValue(toRenderBox(renderer)->marginLeft(), style.get());
- return CSSPrimitiveValue::create(style->marginLeft());
+ case CSSPropertyMarginTop: {
+ Length marginTop = style->marginTop();
+ if (marginTop.isPercent())
+ return CSSPrimitiveValue::create(marginTop);
+ return zoomAdjustedPixelValue(marginTop.value(), style.get());
+ }
+ case CSSPropertyMarginRight: {
+ Length marginRight = style->marginRight();
+ if (marginRight.isPercent())
+ return CSSPrimitiveValue::create(marginRight);
+ return zoomAdjustedPixelValue(marginRight.value(), style.get());
+ }
+ case CSSPropertyMarginBottom: {
+ Length marginBottom = style->marginBottom();
+ if (marginBottom.isPercent())
+ return CSSPrimitiveValue::create(marginBottom);
+ return zoomAdjustedPixelValue(marginBottom.value(), style.get());
+ }
+ case CSSPropertyMarginLeft: {
+ Length marginLeft = style->marginLeft();
+ if (marginLeft.isPercent())
+ return CSSPrimitiveValue::create(marginLeft);
+ return zoomAdjustedPixelValue(marginLeft.value(), style.get());
+ }
case CSSPropertyWebkitMarqueeDirection:
return CSSPrimitiveValue::create(style->marqueeDirection());
case CSSPropertyWebkitMarqueeIncrement:
diff --git a/Source/WebCore/css/CSSFontFaceSource.cpp b/Source/WebCore/css/CSSFontFaceSource.cpp
index 034b22e..681a94b 100644
--- a/Source/WebCore/css/CSSFontFaceSource.cpp
+++ b/Source/WebCore/css/CSSFontFaceSource.cpp
@@ -115,7 +115,7 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
}
// See if we have a mapping in our FontData cache.
- unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 3 | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);
+ unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 5 | fontDescription.widthVariant() << 3 | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);
if (SimpleFontData* cachedData = m_fontDataTable.get(hashKey))
return cachedData;
@@ -162,13 +162,13 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
if (!m_font->ensureCustomFontData())
return 0;
- fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(), fontDescription.renderingMode()), true, false));
+ fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false));
}
} else {
#if ENABLE(SVG_FONTS)
// In-Document SVG Fonts
if (m_svgFontFaceElement)
- fontData.set(new SimpleFontData(adoptPtr(new SVGFontData(m_svgFontFaceElement)), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic));
+ fontData.set(new SimpleFontData(adoptPtr(new SVGFontData(m_svgFontFaceElement.get())), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic));
#endif
}
} else {
@@ -190,6 +190,16 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
}
#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_font && m_font->isSVGFont());
diff --git a/Source/WebCore/css/CSSFontFaceSource.h b/Source/WebCore/css/CSSFontFaceSource.h
index e2057cc..a5c3e61 100644
--- a/Source/WebCore/css/CSSFontFaceSource.h
+++ b/Source/WebCore/css/CSSFontFaceSource.h
@@ -63,8 +63,8 @@ public:
void pruneTable();
#if ENABLE(SVG_FONTS)
- SVGFontFaceElement* svgFontFaceElement() const { return m_svgFontFaceElement; }
- void setSVGFontFaceElement(SVGFontFaceElement* element) { m_svgFontFaceElement = element; }
+ SVGFontFaceElement* svgFontFaceElement() const;
+ void setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement>);
bool isSVGFontFaceSource() const;
#endif
@@ -75,7 +75,7 @@ private:
HashMap<unsigned, SimpleFontData*> m_fontDataTable; // The hash key is composed of size synthetic styles.
#if ENABLE(SVG_FONTS)
- SVGFontFaceElement* m_svgFontFaceElement;
+ RefPtr<SVGFontFaceElement> m_svgFontFaceElement;
RefPtr<SVGFontElement> m_externalSVGFontElement;
#endif
};
diff --git a/Source/WebCore/css/CSSFunctionValue.cpp b/Source/WebCore/css/CSSFunctionValue.cpp
index 70e8174..52a2953 100644
--- a/Source/WebCore/css/CSSFunctionValue.cpp
+++ b/Source/WebCore/css/CSSFunctionValue.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "CSSFunctionValue.h"
+#include "CSSParserValues.h"
#include "CSSValueList.h"
#include <wtf/PassOwnPtr.h>
@@ -51,18 +52,4 @@ String CSSFunctionValue::cssText() const
return result;
}
-CSSParserValue CSSFunctionValue::parserValue() const
-{
- CSSParserValue val;
- val.id = 0;
- val.isInt = false;
- val.unit = CSSParserValue::Function;
- val.function = new CSSParserFunction;
- val.function->name.characters = const_cast<UChar*>(m_name.characters());
- val.function->name.length = m_name.length();
- if (m_args)
- val.function->args = m_args->createParserValueList();
- return val;
-}
-
}
diff --git a/Source/WebCore/css/CSSFunctionValue.h b/Source/WebCore/css/CSSFunctionValue.h
index 1d73f33..be38206 100644
--- a/Source/WebCore/css/CSSFunctionValue.h
+++ b/Source/WebCore/css/CSSFunctionValue.h
@@ -44,8 +44,6 @@ public:
virtual String cssText() const;
- virtual CSSParserValue parserValue() const;
-
private:
explicit CSSFunctionValue(CSSParserFunction*);
diff --git a/Source/WebCore/css/CSSGradientValue.cpp b/Source/WebCore/css/CSSGradientValue.cpp
index b6b9ebe..ede76da 100644
--- a/Source/WebCore/css/CSSGradientValue.cpp
+++ b/Source/WebCore/css/CSSGradientValue.cpp
@@ -41,27 +41,28 @@ using namespace std;
namespace WebCore {
-Image* CSSGradientValue::image(RenderObject* renderer, const IntSize& size)
+PassRefPtr<Image> CSSGradientValue::image(RenderObject* renderer, const IntSize& size)
{
- if (!m_clients.contains(renderer))
- return 0;
-
- // Need to look up our size. Create a string of width*height to use as a hash key.
- // FIXME: hashing based only on size is not sufficient. Color stops may use context-sensitive units (like em)
- // that should force the color stop positions to be recomputed.
- Image* result = getImage(renderer, size);
- if (result)
- return result;
-
if (size.isEmpty())
return 0;
+ bool cacheable = isCacheable();
+ if (cacheable) {
+ if (!m_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<Image> newImage = GeneratedImage::create(createGradient(renderer, size), size);
- result = newImage.get();
- putImage(size, newImage.release());
+ if (cacheable)
+ putImage(size, newImage);
- return result;
+ return newImage.release();
}
// Should only ever be called for deprecated gradients.
@@ -280,7 +281,7 @@ void CSSGradientValue::addStops(Gradient* gradient, RenderObject* renderer, Rend
float lastOffset = stops[stops.size() - 1].offset;
if (lastOffset < maxExtent) {
float currOffset = lastOffset;
- size_t srcStopOrdinal = 0;
+ size_t srcStopOrdinal = originalFirstStopIndex;
while (true) {
GradientStop newStop = stops[srcStopOrdinal];
@@ -289,7 +290,7 @@ void CSSGradientValue::addStops(Gradient* gradient, RenderObject* renderer, Rend
if (currOffset > maxExtent)
break;
if (srcStopOrdinal < originalNumStops - 1)
- currOffset += stops[originalFirstStopIndex + srcStopOrdinal + 1].offset - stops[originalFirstStopIndex + srcStopOrdinal].offset;
+ currOffset += stops[srcStopOrdinal + 1].offset - stops[srcStopOrdinal].offset;
srcStopOrdinal = (srcStopOrdinal + 1) % originalNumStops;
}
}
@@ -406,6 +407,21 @@ FloatPoint CSSGradientValue::computeEndPoint(CSSPrimitiveValue* first, CSSPrimit
return result;
}
+bool CSSGradientValue::isCacheable() const
+{
+ for (size_t i = 0; i < m_stops.size(); ++i) {
+ const CSSGradientColorStop& stop = m_stops[i];
+ 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::cssText() const
{
String result;
diff --git a/Source/WebCore/css/CSSGradientValue.h b/Source/WebCore/css/CSSGradientValue.h
index 0b5ca77..b19548e 100644
--- a/Source/WebCore/css/CSSGradientValue.h
+++ b/Source/WebCore/css/CSSGradientValue.h
@@ -46,7 +46,7 @@ struct CSSGradientColorStop {
class CSSGradientValue : public CSSImageGeneratorValue {
public:
- virtual Image* image(RenderObject*, const IntSize&);
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&);
void setFirstX(PassRefPtr<CSSPrimitiveValue> val) { m_firstX = val; }
void setFirstY(PassRefPtr<CSSPrimitiveValue> val) { m_firstY = val; }
@@ -81,6 +81,8 @@ protected:
// 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;
diff --git a/Source/WebCore/css/CSSGrammar.y b/Source/WebCore/css/CSSGrammar.y
index a5fe795..03d25d9 100644
--- a/Source/WebCore/css/CSSGrammar.y
+++ b/Source/WebCore/css/CSSGrammar.y
@@ -69,8 +69,8 @@ using namespace HTMLNames;
CSSRule* rule;
CSSRuleList* ruleList;
- CSSSelector* selector;
- Vector<CSSSelector*>* selectorList;
+ CSSParserSelector* selector;
+ Vector<OwnPtr<CSSParserSelector> >* selectorList;
CSSSelector::MarginBoxType marginBox;
CSSSelector::Relation relation;
MediaList* mediaList;
@@ -663,14 +663,14 @@ page_selector:
IDENT {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
$$->setForPage();
}
| IDENT pseudo_page {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = $2;
if ($$) {
- $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
$$->setForPage();
}
}
@@ -812,7 +812,6 @@ selector_list:
if ($1) {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->reusableSelectorVector();
- deleteAllValues(*$$);
$$->shrink(0);
$$->append(p->sinkFloatingSelector($1));
p->updateLastSelectorLineAndPosition();
@@ -853,10 +852,10 @@ selector:
$$ = 0;
else if ($$) {
CSSParser* p = static_cast<CSSParser*>(parser);
- CSSSelector* end = $$;
+ CSSParserSelector* end = $$;
while (end->tagHistory())
end = end->tagHistory();
- end->m_relation = CSSSelector::Descendant;
+ end->setRelation(CSSSelector::Descendant);
end->setTagHistory(p->sinkFloatingSelector($1));
if (Document* doc = p->document())
doc->setUsesDescendantRules(true);
@@ -868,10 +867,10 @@ selector:
$$ = 0;
else if ($$) {
CSSParser* p = static_cast<CSSParser*>(parser);
- CSSSelector* end = $$;
+ CSSParserSelector* end = $$;
while (end->tagHistory())
end = end->tagHistory();
- end->m_relation = $2;
+ end->setRelation($2);
end->setTagHistory(p->sinkFloatingSelector($1));
if ($2 == CSSSelector::Child) {
if (Document* doc = p->document())
@@ -897,7 +896,7 @@ simple_selector:
element_name {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_tag = QualifiedName(nullAtom, $1, p->m_defaultNamespace);
+ $$->setTag(QualifiedName(nullAtom, $1, p->m_defaultNamespace));
}
| element_name specifier_list {
$$ = $2;
@@ -914,10 +913,10 @@ simple_selector:
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
if (p->m_styleSheet)
- $$->m_tag = QualifiedName(namespacePrefix, $2,
- p->m_styleSheet->determineNamespace(namespacePrefix));
+ $$->setTag(QualifiedName(namespacePrefix, $2,
+ p->m_styleSheet->determineNamespace(namespacePrefix)));
else // FIXME: Shouldn't this case be an error?
- $$->m_tag = QualifiedName(nullAtom, $2, p->m_defaultNamespace);
+ $$->setTag(QualifiedName(nullAtom, $2, p->m_defaultNamespace));
}
| namespace_selector element_name specifier_list {
$$ = $3;
@@ -956,8 +955,8 @@ specifier_list:
$$ = 0;
else if ($1) {
CSSParser* p = static_cast<CSSParser*>(parser);
- CSSSelector* end;
- CSSSelector* history;
+ CSSParserSelector* end;
+ CSSParserSelector* history;
// Ensure that unknown pseudo element always stays at the top of selector chain.
if ($2->isUnknownPseudoElement()) {
end = $2;
@@ -969,7 +968,7 @@ specifier_list:
$$ = end;
while(end->tagHistory())
end = end->tagHistory();
- end->m_relation = CSSSelector::SubSelector;
+ end->setRelation(CSSSelector::SubSelector);
end->setTagHistory(p->sinkFloatingSelector(history));
}
}
@@ -982,10 +981,10 @@ specifier:
IDSEL {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::Id;
+ $$->setMatch(CSSSelector::Id);
if (!p->m_strict)
$1.lower();
- $$->m_value = $1;
+ $$->setValue($1);
}
| HEX {
if ($1.characters[0] >= '0' && $1.characters[0] <= '9') {
@@ -993,10 +992,10 @@ specifier:
} else {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::Id;
+ $$->setMatch(CSSSelector::Id);
if (!p->m_strict)
$1.lower();
- $$->m_value = $1;
+ $$->setValue($1);
}
}
| class
@@ -1008,10 +1007,10 @@ class:
'.' IDENT {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::Class;
+ $$->setMatch(CSSSelector::Class);
if (!p->m_strict)
$2.lower();
- $$->m_value = $2;
+ $$->setValue($2);
}
;
@@ -1030,13 +1029,13 @@ attrib:
'[' maybe_space attr_name ']' {
$$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
$$->setAttribute(QualifiedName(nullAtom, $3, nullAtom));
- $$->m_match = CSSSelector::Set;
+ $$->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));
- $$->m_match = (CSSSelector::Match)$4;
- $$->m_value = $6;
+ $$->setMatch((CSSSelector::Match)$4);
+ $$->setValue($6);
}
| '[' maybe_space namespace_selector attr_name ']' {
AtomicString namespacePrefix = $3;
@@ -1044,7 +1043,7 @@ attrib:
$$ = p->createFloatingSelector();
$$->setAttribute(QualifiedName(namespacePrefix, $4,
p->m_styleSheet->determineNamespace(namespacePrefix)));
- $$->m_match = CSSSelector::Set;
+ $$->setMatch(CSSSelector::Set);
}
| '[' maybe_space namespace_selector attr_name match maybe_space ident_or_string maybe_space ']' {
AtomicString namespacePrefix = $3;
@@ -1052,8 +1051,8 @@ attrib:
$$ = p->createFloatingSelector();
$$->setAttribute(QualifiedName(namespacePrefix, $4,
p->m_styleSheet->determineNamespace(namespacePrefix)));
- $$->m_match = (CSSSelector::Match)$5;
- $$->m_value = $7;
+ $$->setMatch((CSSSelector::Match)$5);
+ $$->setValue($7);
}
;
@@ -1086,9 +1085,9 @@ ident_or_string:
pseudo_page:
':' IDENT {
$$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
- $$->m_match = CSSSelector::PagePseudoClass;
+ $$->setMatch(CSSSelector::PagePseudoClass);
$2.lower();
- $$->m_value = $2;
+ $$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
$$ = 0;
@@ -1097,9 +1096,9 @@ pseudo_page:
pseudo:
':' IDENT {
$$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
- $$->m_match = CSSSelector::PseudoClass;
+ $$->setMatch(CSSSelector::PseudoClass);
$2.lower();
- $$->m_value = $2;
+ $$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
$$ = 0;
@@ -1131,9 +1130,9 @@ pseudo:
}
| ':' ':' IDENT {
$$ = static_cast<CSSParser*>(parser)->createFloatingSelector();
- $$->m_match = CSSSelector::PseudoElement;
+ $$->setMatch(CSSSelector::PseudoElement);
$3.lower();
- $$->m_value = $3;
+ $$->setValue($3);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoFirstLine) {
CSSParser* p = static_cast<CSSParser*>(parser);
@@ -1150,9 +1149,9 @@ pseudo:
| ':' FUNCTION maybe_space NTH maybe_space ')' {
CSSParser *p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::PseudoClass;
+ $$->setMatch(CSSSelector::PseudoClass);
$$->setArgument($4);
- $$->m_value = $2;
+ $$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
$$ = 0;
@@ -1168,9 +1167,9 @@ pseudo:
| ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' {
CSSParser *p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::PseudoClass;
+ $$->setMatch(CSSSelector::PseudoClass);
$$->setArgument(String::number($4 * $5));
- $$->m_value = $2;
+ $$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
$$ = 0;
@@ -1186,10 +1185,10 @@ pseudo:
| ':' FUNCTION maybe_space IDENT maybe_space ')' {
CSSParser *p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::PseudoClass;
+ $$->setMatch(CSSSelector::PseudoClass);
$$->setArgument($4);
$2.lower();
- $$->m_value = $2;
+ $$->setValue($2);
CSSSelector::PseudoType type = $$->pseudoType();
if (type == CSSSelector::PseudoUnknown)
$$ = 0;
@@ -1211,10 +1210,10 @@ pseudo:
else {
CSSParser* p = static_cast<CSSParser*>(parser);
$$ = p->createFloatingSelector();
- $$->m_match = CSSSelector::PseudoClass;
- $$->setSimpleSelector(p->sinkFloatingSelector($4));
+ $$->setMatch(CSSSelector::PseudoClass);
+ $$->setSimpleSelector(p->sinkFloatingSelector($4)->releaseSelector());
$2.lower();
- $$->m_value = $2;
+ $$->setValue($2);
}
}
;
diff --git a/Source/WebCore/css/CSSImageGeneratorValue.h b/Source/WebCore/css/CSSImageGeneratorValue.h
index c053bfe..f5c17f5 100644
--- a/Source/WebCore/css/CSSImageGeneratorValue.h
+++ b/Source/WebCore/css/CSSImageGeneratorValue.h
@@ -44,7 +44,7 @@ public:
void addClient(RenderObject*, const IntSize&);
void removeClient(RenderObject*);
- virtual Image* image(RenderObject*, const IntSize&) = 0;
+ virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) = 0;
StyleGeneratedImage* generatedImage();
diff --git a/Source/WebCore/css/CSSImageValue.cpp b/Source/WebCore/css/CSSImageValue.cpp
index a9038b9..6896596 100644
--- a/Source/WebCore/css/CSSImageValue.cpp
+++ b/Source/WebCore/css/CSSImageValue.cpp
@@ -67,6 +67,10 @@ StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader)
StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader, const String& url)
{
ASSERT(loader);
+ if (!loader) {
+ // FIXME: Remove when http://webkit.org/b/53045 is fixed.
+ CRASH();
+ }
if (!m_accessedImage) {
m_accessedImage = true;
diff --git a/Source/WebCore/css/CSSMediaRule.cpp b/Source/WebCore/css/CSSMediaRule.cpp
index 6348762..46dc780 100644
--- a/Source/WebCore/css/CSSMediaRule.cpp
+++ b/Source/WebCore/css/CSSMediaRule.cpp
@@ -88,8 +88,8 @@ unsigned CSSMediaRule::insertRule(const String& rule, unsigned index, ExceptionC
newRule->setParent(this);
unsigned returnedIndex = m_lstCSSRules->insertRule(newRule.get(), index);
- // stylesheet() can only return 0 for computed style declarations.
- stylesheet()->styleSheetChanged();
+ if (stylesheet())
+ stylesheet()->styleSheetChanged();
return returnedIndex;
}
@@ -105,8 +105,8 @@ void CSSMediaRule::deleteRule(unsigned index, ExceptionCode& ec)
m_lstCSSRules->deleteRule(index);
- // stylesheet() can only return 0 for computed style declarations.
- stylesheet()->styleSheetChanged();
+ if (stylesheet())
+ stylesheet()->styleSheetChanged();
}
String CSSMediaRule::cssText() const
diff --git a/Source/WebCore/css/CSSPageRule.cpp b/Source/WebCore/css/CSSPageRule.cpp
index c85c1aa..c3dbcaa 100644
--- a/Source/WebCore/css/CSSPageRule.cpp
+++ b/Source/WebCore/css/CSSPageRule.cpp
@@ -27,12 +27,9 @@
namespace WebCore {
-CSSPageRule::CSSPageRule(CSSStyleSheet* parent, CSSSelector* selector, int sourceLine)
+CSSPageRule::CSSPageRule(CSSStyleSheet* parent, int sourceLine)
: CSSStyleRule(parent, sourceLine)
{
- Vector<CSSSelector*> selectors;
- selectors.append(selector);
- adoptSelectorVector(selectors);
}
CSSPageRule::~CSSPageRule()
diff --git a/Source/WebCore/css/CSSPageRule.h b/Source/WebCore/css/CSSPageRule.h
index bdfb751..9c1c41f 100644
--- a/Source/WebCore/css/CSSPageRule.h
+++ b/Source/WebCore/css/CSSPageRule.h
@@ -34,9 +34,9 @@ class CSSSelectorList;
class CSSPageRule : public CSSStyleRule {
public:
- static PassRefPtr<CSSPageRule> create(CSSStyleSheet* parent, CSSSelector* selector, int sourceLine)
+ static PassRefPtr<CSSPageRule> create(CSSStyleSheet* parent, int sourceLine)
{
- return adoptRef(new CSSPageRule(parent, selector, sourceLine));
+ return adoptRef(new CSSPageRule(parent, sourceLine));
}
virtual ~CSSPageRule();
@@ -44,7 +44,7 @@ public:
virtual String selectorText() const;
private:
- CSSPageRule(CSSStyleSheet* parent, CSSSelector* selector, int sourceLine);
+ CSSPageRule(CSSStyleSheet* parent, int sourceLine);
virtual bool isPageRule() { return true; }
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp
index 9142e67..55175a2 100644
--- a/Source/WebCore/css/CSSParser.cpp
+++ b/Source/WebCore/css/CSSParser.cpp
@@ -62,8 +62,10 @@
#include "HashTools.h"
#include "MediaList.h"
#include "MediaQueryExp.h"
+#include "Page.h"
#include "Pair.h"
#include "Rect.h"
+#include "RenderTheme.h"
#include "ShadowValue.h"
#include "WebKitCSSKeyframeRule.h"
#include "WebKitCSSKeyframesRule.h"
@@ -129,13 +131,6 @@ static bool hasPrefix(const char* string, unsigned length, const char* prefix)
return false;
}
-static int clampToSignedInteger(double d)
-{
- const double minIntAsDouble = std::numeric_limits<int>::min();
- const double maxIntAsDouble = std::numeric_limits<int>::max();
- return static_cast<int>(max(minIntAsDouble, min(d, maxIntAsDouble)));
-}
-
CSSParser::CSSParser(bool strictParsing)
: m_strict(strictParsing)
, m_important(false)
@@ -183,7 +178,6 @@ CSSParser::~CSSParser()
fastDeleteAllValues(m_floatingSelectors);
deleteAllValues(m_floatingValueLists);
deleteAllValues(m_floatingFunctions);
- deleteAllValues(m_reusableSelectorVector);
}
void CSSParserString::lower()
@@ -330,11 +324,14 @@ bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
return false;
CSSValue* value = parser.m_parsedProperties[0]->value();
- if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
- CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
- color = primitiveValue->getRGBA32Value();
- }
+ if (value->cssValueType() != CSSValue::CSS_PRIMITIVE_VALUE)
+ return false;
+
+ CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
+ if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_RGBCOLOR)
+ return false;
+ color = primitiveValue->getRGBA32Value();
return true;
}
@@ -356,6 +353,22 @@ bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String
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)
{
#ifdef ANDROID_INSTRUMENT
@@ -1675,14 +1688,14 @@ bool CSSParser::parseValue(int propId, bool important)
// FIXME: Add CSSPropertyBackgroundSize to the shorthand.
const int properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
- CSSPropertyBackgroundColor };
- return parseFillShorthand(propId, properties, 6, important);
+ CSSPropertyBackgroundClip, CSSPropertyBackgroundColor };
+ return parseFillShorthand(propId, properties, 7, important);
}
case CSSPropertyWebkitMask: {
const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition,
- CSSPropertyWebkitMaskOrigin };
- return parseFillShorthand(propId, properties, 5, important);
+ CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip };
+ return parseFillShorthand(propId, properties, 6, important);
}
case CSSPropertyBorder:
// [ 'border-width' || 'border-style' || <color> ] | inherit
@@ -1988,6 +2001,7 @@ bool CSSParser::parseFillShorthand(int propId, const int* properties, int numPro
RefPtr<CSSValue> clipValue;
RefPtr<CSSValue> positionYValue;
RefPtr<CSSValue> repeatYValue;
+ bool foundClip = false;
int i;
while (m_valueList->current()) {
@@ -2010,7 +2024,7 @@ bool CSSParser::parseFillShorthand(int propId, const int* properties, int numPro
if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
// If background-origin wasn't present, then reset background-clip also.
addFillValue(clipValue, CSSInitialValue::createImplicit());
- }
+ }
}
parsedProperty[i] = false;
}
@@ -2039,6 +2053,11 @@ bool CSSParser::parseFillShorthand(int propId, const int* properties, int numPro
else
addFillValue(clipValue, CSSInitialValue::createImplicit()); // 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;
+ }
}
}
}
@@ -2082,13 +2101,16 @@ bool CSSParser::parseFillShorthand(int propId, const int* properties, int numPro
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
+ } 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)
+ if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
- else if (properties[i] == CSSPropertyWebkitMaskOrigin)
+ else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
}
@@ -4722,7 +4744,7 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important)
case VAL: {
int i = defaultValue;
if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) {
- i = clampToSignedInteger(val->fValue);
+ i = clampToInteger(val->fValue);
m_valueList->next();
}
@@ -5409,6 +5431,10 @@ PassRefPtr<CSSValueList> CSSParser::parseTransform()
// 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;
@@ -5789,20 +5815,20 @@ void CSSParser::countLines()
}
}
-CSSSelector* CSSParser::createFloatingSelector()
+CSSParserSelector* CSSParser::createFloatingSelector()
{
- CSSSelector* selector = fastNew<CSSSelector>();
+ CSSParserSelector* selector = new CSSParserSelector;
m_floatingSelectors.add(selector);
return selector;
}
-CSSSelector* CSSParser::sinkFloatingSelector(CSSSelector* selector)
+PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* selector)
{
if (selector) {
ASSERT(m_floatingSelectors.contains(selector));
m_floatingSelectors.remove(selector);
}
- return selector;
+ return adoptPtr(selector);
}
CSSParserValueList* CSSParser::createFloatingValueList()
@@ -5944,7 +5970,7 @@ WebKitCSSKeyframesRule* CSSParser::createKeyframesRule()
return rulePtr;
}
-CSSRule* CSSParser::createStyleRule(Vector<CSSSelector*>* selectors)
+CSSRule* CSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
{
CSSStyleRule* result = 0;
markRuleBodyEnd();
@@ -6006,21 +6032,21 @@ void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri
m_styleSheet->addNamespace(this, prefix, uri);
}
-void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSSelector* specifiers)
+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->m_tag = tag;
+ specifiers->setTag(tag);
return;
}
if (Document* doc = document())
doc->setUsesDescendantRules(true);
- specifiers->m_relation = CSSSelector::ShadowDescendant;
- if (CSSSelector* history = specifiers->tagHistory()) {
- history->m_tag = tag;
+ specifiers->setRelation(CSSSelector::ShadowDescendant);
+ if (CSSParserSelector* history = specifiers->tagHistory()) {
+ history->setTag(tag);
return;
}
@@ -6029,19 +6055,22 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre
if (elementName == starAtom && m_defaultNamespace == starAtom)
return;
- CSSSelector* elementNameSelector = fastNew<CSSSelector>();
- elementNameSelector->m_tag = tag;
+ CSSParserSelector* elementNameSelector = new CSSParserSelector;
+ elementNameSelector->setTag(tag);
specifiers->setTagHistory(elementNameSelector);
}
-CSSRule* CSSParser::createPageRule(CSSSelector* pageSelector)
+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, pageSelector, m_lastSelectorLineNumber);
+ 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_parsedStyleObjects.append(rule.release());
diff --git a/Source/WebCore/css/CSSParser.h b/Source/WebCore/css/CSSParser.h
index d326812..6ccfbe2 100644
--- a/Source/WebCore/css/CSSParser.h
+++ b/Source/WebCore/css/CSSParser.h
@@ -64,6 +64,7 @@ namespace WebCore {
PassRefPtr<CSSRule> parseKeyframeRule(CSSStyleSheet*, const String&);
bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important);
static bool parseColor(RGBA32& color, const String&, bool strict = false);
+ static bool parseSystemColor(RGBA32& color, const String&, Document*);
bool parseColor(CSSMutableStyleDeclaration*, const String&);
bool parseDeclaration(CSSMutableStyleDeclaration*, const String&, RefPtr<CSSStyleSourceData>* styleSourceData = 0);
bool parseMediaQuery(MediaList*, const String&);
@@ -170,8 +171,8 @@ namespace WebCore {
int yyparse();
- CSSSelector* createFloatingSelector();
- CSSSelector* sinkFloatingSelector(CSSSelector*);
+ CSSParserSelector* createFloatingSelector();
+ PassOwnPtr<CSSParserSelector> sinkFloatingSelector(CSSParserSelector*);
CSSParserValueList* createFloatingValueList();
CSSParserValueList* sinkFloatingValueList(CSSParserValueList*);
@@ -188,9 +189,9 @@ namespace WebCore {
WebKitCSSKeyframesRule* createKeyframesRule();
CSSRule* createMediaRule(MediaList*, CSSRuleList*);
CSSRuleList* createRuleList();
- CSSRule* createStyleRule(Vector<CSSSelector*>* selectors);
+ CSSRule* createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors);
CSSRule* createFontFaceRule();
- CSSRule* createPageRule(CSSSelector* pageSelector);
+ CSSRule* createPageRule(PassOwnPtr<CSSParserSelector> pageSelector);
CSSRule* createMarginAtRule(CSSSelector::MarginBoxType marginBox);
void startDeclarationsForMarginBox();
void endDeclarationsForMarginBox();
@@ -204,11 +205,11 @@ namespace WebCore {
PassOwnPtr<MediaQuery> sinkFloatingMediaQuery(MediaQuery*);
void addNamespace(const AtomicString& prefix, const AtomicString& uri);
- void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSSelector*);
+ void updateSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*);
void invalidBlockHit();
- Vector<CSSSelector*>* reusableSelectorVector() { return &m_reusableSelectorVector; }
+ Vector<OwnPtr<CSSParserSelector> >* reusableSelectorVector() { return &m_reusableSelectorVector; }
void updateLastSelectorLineAndPosition();
@@ -302,7 +303,7 @@ namespace WebCore {
Vector<RefPtr<StyleBase> > m_parsedStyleObjects;
Vector<RefPtr<CSSRuleList> > m_parsedRuleLists;
- HashSet<CSSSelector*> m_floatingSelectors;
+ HashSet<CSSParserSelector*> m_floatingSelectors;
HashSet<CSSParserValueList*> m_floatingValueLists;
HashSet<CSSParserFunction*> m_floatingFunctions;
@@ -310,7 +311,7 @@ namespace WebCore {
OwnPtr<MediaQueryExp> m_floatingMediaQueryExp;
OwnPtr<Vector<OwnPtr<MediaQueryExp> > > m_floatingMediaQueryExpList;
- Vector<CSSSelector*> m_reusableSelectorVector;
+ Vector<OwnPtr<CSSParserSelector> > m_reusableSelectorVector;
// defines units allowed for a certain property, used in parseUnit
enum Units {
diff --git a/Source/WebCore/css/CSSParserValues.cpp b/Source/WebCore/css/CSSParserValues.cpp
index 06651f1..dc0e82b 100644
--- a/Source/WebCore/css/CSSParserValues.cpp
+++ b/Source/WebCore/css/CSSParserValues.cpp
@@ -20,11 +20,15 @@
#include "config.h"
#include "CSSParserValues.h"
+
#include "CSSPrimitiveValue.h"
#include "CSSFunctionValue.h"
#include "CSSQuirkPrimitiveValue.h"
+#include "CSSSelector.h"
namespace WebCore {
+
+using namespace WTF;
CSSParserValueList::~CSSParserValueList()
{
@@ -70,6 +74,27 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue()
parsedValue = CSSQuirkPrimitiveValue::create(fValue, CSSPrimitiveValue::CSS_EMS);
return parsedValue;
}
+
+CSSParserSelector::CSSParserSelector()
+ : m_selector(adoptPtr(fastNew<CSSSelector>()))
+{
+}
+
+CSSParserSelector::~CSSParserSelector()
+{
+ if (!m_tagHistory)
+ return;
+ Vector<CSSParserSelector*, 16> toDelete;
+ CSSParserSelector* selector = m_tagHistory.leakPtr();
+ while (true) {
+ toDelete.append(selector);
+ CSSParserSelector* next = selector->m_tagHistory.leakPtr();
+ if (!next)
+ break;
+ selector = next;
+ }
+ deleteAllValues(toDelete);
+}
}
diff --git a/Source/WebCore/css/CSSParserValues.h b/Source/WebCore/css/CSSParserValues.h
index 996e783..d084091 100644
--- a/Source/WebCore/css/CSSParserValues.h
+++ b/Source/WebCore/css/CSSParserValues.h
@@ -21,11 +21,13 @@
#ifndef CSSParserValues_h
#define CSSParserValues_h
+#include "CSSSelector.h"
#include <wtf/text/AtomicString.h>
namespace WebCore {
class CSSValue;
+class QualifiedName;
struct CSSParserString {
UChar* characters;
@@ -91,6 +93,35 @@ public:
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 setSimpleSelector(PassOwnPtr<CSSSelector> value) { m_selector->setSimpleSelector(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(); }
+
+ CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); }
+ bool isUnknownPseudoElement() const { return m_selector->isUnknownPseudoElement(); }
+ bool isSimple() const { return !m_tagHistory && m_selector->isSimple(); }
+
+ CSSParserSelector* tagHistory() const { return m_tagHistory.get(); }
+ void setTagHistory(PassOwnPtr<CSSParserSelector> selector) { m_tagHistory = selector; }
+
+private:
+ OwnPtr<CSSSelector> m_selector;
+ OwnPtr<CSSParserSelector> m_tagHistory;
+};
+
}
#endif
diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp
index ce1b87b..6d930bd 100644
--- a/Source/WebCore/css/CSSPrimitiveValue.cpp
+++ b/Source/WebCore/css/CSSPrimitiveValue.cpp
@@ -127,10 +127,20 @@ PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createColor(unsigned rgbValue)
// These are the empty and deleted values of the hash table.
if (rgbValue == Color::transparent) {
static CSSPrimitiveValue* colorTransparent = createUncachedColor(Color::transparent).releaseRef();
+#if CPU(ARM) && OS(LINUX)
+ // A workaround for gcc bug on ARM.
+ if (!colorTransparent)
+ return 0;
+#endif
return colorTransparent;
}
if (rgbValue == Color::white) {
static CSSPrimitiveValue* colorWhite = createUncachedColor(Color::white).releaseRef();
+#if CPU(ARM) && OS(LINUX)
+ // A workaround for gcc bug on ARM.
+ if (!colorWhite)
+ return 0;
+#endif
return colorWhite;
}
RefPtr<CSSPrimitiveValue> primitiveValue = colorValueCache->get(rgbValue);
@@ -400,7 +410,7 @@ double CSSPrimitiveValue::computeLengthDouble(RenderStyle* style, RenderStyle* r
// We really need to compute EX using fontMetrics for the original specifiedSize and not use
// our actual constructed rendering font.
applyZoomMultiplier = false;
- factor = style->font().xHeight();
+ factor = style->fontMetrics().xHeight();
break;
case CSS_REMS:
applyZoomMultiplier = false;
@@ -914,81 +924,6 @@ String CSSPrimitiveValue::cssText() const
return text;
}
-CSSParserValue CSSPrimitiveValue::parserValue() const
-{
- // We only have to handle a subset of types.
- CSSParserValue value;
- value.id = 0;
- value.isInt = false;
- value.unit = CSSPrimitiveValue::CSS_IDENT;
- switch (m_type) {
- case CSS_NUMBER:
- case CSS_PERCENTAGE:
- case CSS_EMS:
- case CSS_EXS:
- case CSS_REMS:
- case CSS_PX:
- case CSS_CM:
- case CSS_MM:
- case CSS_IN:
- case CSS_PT:
- case CSS_PC:
- case CSS_DEG:
- case CSS_RAD:
- case CSS_GRAD:
- case CSS_MS:
- case CSS_S:
- case CSS_HZ:
- case CSS_KHZ:
- case CSS_DIMENSION:
- case CSS_TURN:
- value.fValue = m_value.num;
- value.unit = m_type;
- break;
- case CSS_STRING:
- case CSS_URI:
- case CSS_PARSER_HEXCOLOR:
- value.string.characters = const_cast<UChar*>(m_value.string->characters());
- value.string.length = m_value.string->length();
- value.unit = m_type;
- break;
- case CSS_IDENT: {
- value.id = m_value.ident;
- const AtomicString& name = valueOrPropertyName(m_value.ident);
- value.string.characters = const_cast<UChar*>(name.characters());
- value.string.length = name.length();
- break;
- }
- case CSS_PARSER_OPERATOR:
- value.iValue = m_value.ident;
- value.unit = CSSParserValue::Operator;
- break;
- case CSS_PARSER_INTEGER:
- value.fValue = m_value.num;
- value.unit = CSSPrimitiveValue::CSS_NUMBER;
- value.isInt = true;
- break;
- case CSS_PARSER_IDENTIFIER:
- value.string.characters = const_cast<UChar*>(m_value.string->characters());
- value.string.length = m_value.string->length();
- value.unit = CSSPrimitiveValue::CSS_IDENT;
- break;
- case CSS_UNKNOWN:
- case CSS_ATTR:
- case CSS_COUNTER:
- case CSS_RECT:
- case CSS_RGBCOLOR:
- case CSS_PAIR:
-#if ENABLE(DASHBOARD_SUPPORT)
- case CSS_DASHBOARD_REGION:
-#endif
- ASSERT_NOT_REACHED();
- break;
- }
-
- return value;
-}
-
void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
{
if (m_type == CSS_URI)
diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h
index e12cd4c..c9892e8 100644
--- a/Source/WebCore/css/CSSPrimitiveValue.h
+++ b/Source/WebCore/css/CSSPrimitiveValue.h
@@ -185,8 +185,6 @@ public:
virtual bool isQuirkValue() { return false; }
- virtual CSSParserValue parserValue() const;
-
virtual void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
protected:
diff --git a/Source/WebCore/css/CSSRuleList.cpp b/Source/WebCore/css/CSSRuleList.cpp
index 0a312af..da65632 100644
--- a/Source/WebCore/css/CSSRuleList.cpp
+++ b/Source/WebCore/css/CSSRuleList.cpp
@@ -22,8 +22,10 @@
#include "config.h"
#include "CSSRuleList.h"
+#include "CSSMutableStyleDeclaration.h"
#include "CSSRule.h"
#include "StyleList.h"
+#include "WebKitCSSKeyframeRule.h"
namespace WebCore {
@@ -76,6 +78,11 @@ void CSSRuleList::deleteRule(unsigned index)
return;
}
+ if (m_lstCSSRules[index]->isKeyframeRule()) {
+ if (CSSMutableStyleDeclaration* style = static_cast<WebKitCSSKeyframeRule*>(m_lstCSSRules[index].get())->style())
+ style->setParent(0);
+ }
+
m_lstCSSRules[index]->setParent(0);
m_lstCSSRules.remove(index);
}
diff --git a/Source/WebCore/css/CSSSelector.cpp b/Source/WebCore/css/CSSSelector.cpp
index ca3814a..c804697 100644
--- a/Source/WebCore/css/CSSSelector.cpp
+++ b/Source/WebCore/css/CSSSelector.cpp
@@ -36,38 +36,15 @@
namespace WebCore {
using namespace HTMLNames;
-
-class CSSSelectorBag {
- WTF_MAKE_NONCOPYABLE(CSSSelectorBag);
-public:
- CSSSelectorBag() { }
- ~CSSSelectorBag()
- {
- ASSERT(isEmpty());
- }
-
- bool isEmpty() const
- {
- return m_stack.isEmpty();
- }
-
- void add(PassOwnPtr<CSSSelector> selector)
- {
- if (selector)
- m_stack.append(selector.leakPtr());
- }
-
- PassOwnPtr<CSSSelector> takeAny()
- {
- ASSERT(!isEmpty());
- OwnPtr<CSSSelector> selector = adoptPtr(m_stack.last());
- m_stack.removeLast();
- return selector.release();
- }
-
-private:
- Vector<CSSSelector*, 16> m_stack;
-};
+
+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
{
@@ -161,40 +138,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type)
return SEARCH_RESULTS_DECORATION;
case PseudoSearchResultsButton:
return SEARCH_RESULTS_BUTTON;
- case PseudoMediaControlsPanel:
- return MEDIA_CONTROLS_PANEL;
- case PseudoMediaControlsMuteButton:
- return MEDIA_CONTROLS_MUTE_BUTTON;
- case PseudoMediaControlsPlayButton:
- return MEDIA_CONTROLS_PLAY_BUTTON;
- case PseudoMediaControlsTimelineContainer:
- return MEDIA_CONTROLS_TIMELINE_CONTAINER;
- case PseudoMediaControlsVolumeSliderContainer:
- return MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER;
- case PseudoMediaControlsCurrentTimeDisplay:
- return MEDIA_CONTROLS_CURRENT_TIME_DISPLAY;
- case PseudoMediaControlsTimeRemainingDisplay:
- return MEDIA_CONTROLS_TIME_REMAINING_DISPLAY;
- case PseudoMediaControlsTimeline:
- return MEDIA_CONTROLS_TIMELINE;
- case PseudoMediaControlsVolumeSlider:
- return MEDIA_CONTROLS_VOLUME_SLIDER;
- case PseudoMediaControlsVolumeSliderMuteButton:
- return MEDIA_CONTROLS_VOLUME_SLIDER_MUTE_BUTTON;
- case PseudoMediaControlsSeekBackButton:
- return MEDIA_CONTROLS_SEEK_BACK_BUTTON;
- case PseudoMediaControlsSeekForwardButton:
- return MEDIA_CONTROLS_SEEK_FORWARD_BUTTON;
- case PseudoMediaControlsRewindButton:
- return MEDIA_CONTROLS_REWIND_BUTTON;
- case PseudoMediaControlsReturnToRealtimeButton:
- return MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON;
- case PseudoMediaControlsToggleClosedCaptions:
- return MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON;
- case PseudoMediaControlsStatusDisplay:
- return MEDIA_CONTROLS_STATUS_DISPLAY;
- case PseudoMediaControlsFullscreenButton:
- return MEDIA_CONTROLS_FULLSCREEN_BUTTON;
case PseudoScrollbar:
return SCROLLBAR;
case PseudoScrollbarButton:
@@ -213,14 +156,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type)
return INNER_SPIN_BUTTON;
case PseudoOuterSpinButton:
return OUTER_SPIN_BUTTON;
- case PseudoProgressBarValue:
-#if ENABLE(PROGRESS_TAG)
- return PROGRESS_BAR_VALUE;
-#else
- ASSERT_NOT_REACHED();
- return NOPSEUDO;
-#endif
-
#if ENABLE(METER_TAG)
case PseudoMeterHorizontalBar:
return METER_HORIZONTAL_BAR;
@@ -369,32 +304,11 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
DEFINE_STATIC_LOCAL(AtomicString, lastOfType, ("last-of-type"));
DEFINE_STATIC_LOCAL(AtomicString, link, ("link"));
DEFINE_STATIC_LOCAL(AtomicString, lang, ("lang("));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsPanel, ("-webkit-media-controls-panel"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsMuteButton, ("-webkit-media-controls-mute-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsPlayButton, ("-webkit-media-controls-play-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimeline, ("-webkit-media-controls-timeline"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsVolumeSlider, ("-webkit-media-controls-volume-slider"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsVolumeSliderMuteButton, ("-webkit-media-controls-volume-slider-mute-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsSeekBackButton, ("-webkit-media-controls-seek-back-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsSeekForwardButton, ("-webkit-media-controls-seek-forward-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsRewindButton, ("-webkit-media-controls-rewind-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsReturnToRealtimeButton, ("-webkit-media-controls-return-to-realtime-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsToggleClosedCaptionsButton, ("-webkit-media-controls-toggle-closed-captions-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsStatusDisplay, ("-webkit-media-controls-status-display"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsFullscreenButton, ("-webkit-media-controls-fullscreen-button"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimelineContainer, ("-webkit-media-controls-timeline-container"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsVolumeSliderContainer, ("-webkit-media-controls-volume-slider-container"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsCurrentTimeDisplay, ("-webkit-media-controls-current-time-display"));
- DEFINE_STATIC_LOCAL(AtomicString, mediaControlsTimeRemainingDisplay, ("-webkit-media-controls-time-remaining-display"));
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, outerSpinButton, ("-webkit-outer-spin-button"));
-#if ENABLE(PROGRESS_TAG)
- DEFINE_STATIC_LOCAL(AtomicString, progressBarValue, ("-webkit-progress-bar-value"));
-#endif
-
#if ENABLE(METER_TAG)
DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalBar, ("-webkit-meter-horizontal-bar"));
DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalOptimumValue, ("-webkit-meter-horizontal-optimum-value"));
@@ -486,32 +400,12 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap(
nameToPseudoType->set(innerSpinButton.impl(), CSSSelector::PseudoInnerSpinButton);
nameToPseudoType->set(link.impl(), CSSSelector::PseudoLink);
nameToPseudoType->set(lang.impl(), CSSSelector::PseudoLang);
- nameToPseudoType->set(mediaControlsPanel.impl(), CSSSelector::PseudoMediaControlsPanel);
- nameToPseudoType->set(mediaControlsMuteButton.impl(), CSSSelector::PseudoMediaControlsMuteButton);
- nameToPseudoType->set(mediaControlsPlayButton.impl(), CSSSelector::PseudoMediaControlsPlayButton);
- nameToPseudoType->set(mediaControlsCurrentTimeDisplay.impl(), CSSSelector::PseudoMediaControlsCurrentTimeDisplay);
- nameToPseudoType->set(mediaControlsTimeRemainingDisplay.impl(), CSSSelector::PseudoMediaControlsTimeRemainingDisplay);
- nameToPseudoType->set(mediaControlsTimeline.impl(), CSSSelector::PseudoMediaControlsTimeline);
- nameToPseudoType->set(mediaControlsVolumeSlider.impl(), CSSSelector::PseudoMediaControlsVolumeSlider);
- nameToPseudoType->set(mediaControlsVolumeSliderMuteButton.impl(), CSSSelector::PseudoMediaControlsVolumeSliderMuteButton);
- nameToPseudoType->set(mediaControlsSeekBackButton.impl(), CSSSelector::PseudoMediaControlsSeekBackButton);
- nameToPseudoType->set(mediaControlsSeekForwardButton.impl(), CSSSelector::PseudoMediaControlsSeekForwardButton);
- nameToPseudoType->set(mediaControlsRewindButton.impl(), CSSSelector::PseudoMediaControlsRewindButton);
- nameToPseudoType->set(mediaControlsReturnToRealtimeButton.impl(), CSSSelector::PseudoMediaControlsReturnToRealtimeButton);
- nameToPseudoType->set(mediaControlsToggleClosedCaptionsButton.impl(), CSSSelector::PseudoMediaControlsToggleClosedCaptions);
- nameToPseudoType->set(mediaControlsStatusDisplay.impl(), CSSSelector::PseudoMediaControlsStatusDisplay);
- nameToPseudoType->set(mediaControlsFullscreenButton.impl(), CSSSelector::PseudoMediaControlsFullscreenButton);
- nameToPseudoType->set(mediaControlsTimelineContainer.impl(), CSSSelector::PseudoMediaControlsTimelineContainer);
- nameToPseudoType->set(mediaControlsVolumeSliderContainer.impl(), CSSSelector::PseudoMediaControlsVolumeSliderContainer);
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(outerSpinButton.impl(), CSSSelector::PseudoOuterSpinButton);
-#if ENABLE(PROGRESS_TAG)
- nameToPseudoType->set(progressBarValue.impl(), CSSSelector::PseudoProgressBarValue);
-#endif
#if ENABLE(METER_TAG)
nameToPseudoType->set(meterHorizontalBar.impl(), CSSSelector::PseudoMeterHorizontalBar);
nameToPseudoType->set(meterHorizontalOptimumValue.impl(), CSSSelector::PseudoMeterHorizontalOptimum);
@@ -577,7 +471,7 @@ void CSSSelector::extractPseudoType() const
if (m_match != PseudoClass && m_match != PseudoElement && m_match != PagePseudoClass)
return;
- m_pseudoType = parsePseudoType(m_value);
+ m_pseudoType = parsePseudoType(value());
bool element = false; // pseudo-element
bool compat = false; // single colon compatbility mode
@@ -596,23 +490,6 @@ void CSSSelector::extractPseudoType() const
case PseudoInputSpeechButton:
#endif
case PseudoInnerSpinButton:
- case PseudoMediaControlsPanel:
- case PseudoMediaControlsMuteButton:
- case PseudoMediaControlsPlayButton:
- case PseudoMediaControlsCurrentTimeDisplay:
- case PseudoMediaControlsTimeRemainingDisplay:
- case PseudoMediaControlsTimeline:
- case PseudoMediaControlsVolumeSlider:
- case PseudoMediaControlsVolumeSliderMuteButton:
- case PseudoMediaControlsSeekBackButton:
- case PseudoMediaControlsSeekForwardButton:
- case PseudoMediaControlsRewindButton:
- case PseudoMediaControlsReturnToRealtimeButton:
- case PseudoMediaControlsToggleClosedCaptions:
- case PseudoMediaControlsStatusDisplay:
- case PseudoMediaControlsFullscreenButton:
- case PseudoMediaControlsTimelineContainer:
- case PseudoMediaControlsVolumeSliderContainer:
case PseudoMeterHorizontalBar:
case PseudoMeterHorizontalOptimum:
case PseudoMeterHorizontalSuboptimal:
@@ -622,7 +499,6 @@ void CSSSelector::extractPseudoType() const
case PseudoMeterVerticalSuboptimal:
case PseudoMeterVerticalEvenLessGood:
case PseudoOuterSpinButton:
- case PseudoProgressBarValue:
case PseudoResizer:
case PseudoScrollbar:
case PseudoScrollbarCorner:
@@ -721,7 +597,7 @@ bool CSSSelector::operator==(const CSSSelector& 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->m_value != sel2->m_value ||
+ sel1->value() != sel2->value() ||
sel1->pseudoType() != sel2->pseudoType() ||
sel1->argument() != sel2->argument())
return false;
@@ -755,13 +631,13 @@ String CSSSelector::selectorText() const
while (true) {
if (cs->m_match == CSSSelector::Id) {
str += "#";
- serializeIdentifier(cs->m_value, str);
+ serializeIdentifier(cs->value(), str);
} else if (cs->m_match == CSSSelector::Class) {
str += ".";
- serializeIdentifier(cs->m_value, str);
+ serializeIdentifier(cs->value(), str);
} else if (cs->m_match == CSSSelector::PseudoClass || cs->m_match == CSSSelector::PagePseudoClass) {
str += ":";
- str += cs->m_value;
+ str += cs->value();
if (cs->pseudoType() == PseudoNot) {
if (CSSSelector* subSel = cs->simpleSelector())
str += subSel->selectorText();
@@ -776,7 +652,7 @@ String CSSSelector::selectorText() const
}
} else if (cs->m_match == CSSSelector::PseudoElement) {
str += "::";
- str += cs->m_value;
+ str += cs->value();
} else if (cs->hasAttribute()) {
str += "[";
const AtomicString& prefix = cs->attribute().prefix();
@@ -812,7 +688,7 @@ String CSSSelector::selectorText() const
break;
}
if (cs->m_match != CSSSelector::Set) {
- serializeString(cs->m_value, str);
+ serializeString(cs->value(), str);
str += "]";
}
}
@@ -836,14 +712,6 @@ String CSSSelector::selectorText() const
return str;
}
-
-void CSSSelector::setTagHistory(CSSSelector* tagHistory)
-{
- if (m_hasRareData)
- m_data.m_rareData->m_tagHistory.set(tagHistory);
- else
- m_data.m_tagHistory = tagHistory;
-}
const QualifiedName& CSSSelector::attribute() const
{
@@ -869,10 +737,10 @@ void CSSSelector::setArgument(const AtomicString& value)
m_data.m_rareData->m_argument = value;
}
-void CSSSelector::setSimpleSelector(CSSSelector* value)
+void CSSSelector::setSimpleSelector(PassOwnPtr<CSSSelector> value)
{
createRareData();
- m_data.m_rareData->m_simpleSelector.set(value);
+ m_data.m_rareData->m_simpleSelector = value;
}
bool CSSSelector::parseNth()
@@ -975,33 +843,4 @@ bool CSSSelector::RareData::matchNth(int count)
}
}
-inline void CSSSelector::releaseOwnedSelectorsToBag(CSSSelectorBag& bag)
-{
- if (m_hasRareData) {
- ASSERT(m_data.m_rareData);
- bag.add(m_data.m_rareData->m_tagHistory.release());
- bag.add(m_data.m_rareData->m_simpleSelector.release());
- delete m_data.m_rareData;
- // Clear the pointer so that a destructor of this selector will not
- // traverse this chain.
- m_data.m_rareData = 0;
- } else {
- bag.add(adoptPtr(m_data.m_tagHistory));
- // Clear the pointer for the same reason.
- m_data.m_tagHistory = 0;
- }
-}
-
-void CSSSelector::deleteReachableSelectors()
-{
- // Traverse the chain of selectors and delete each iteratively.
- CSSSelectorBag selectorsToBeDeleted;
- releaseOwnedSelectorsToBag(selectorsToBeDeleted);
- while (!selectorsToBeDeleted.isEmpty()) {
- OwnPtr<CSSSelector> selector(selectorsToBeDeleted.takeAny());
- ASSERT(selector);
- selector->releaseOwnedSelectorsToBag(selectorsToBeDeleted);
- }
-}
-
} // namespace WebCore
diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h
index b930353..ea161c3 100644
--- a/Source/WebCore/css/CSSSelector.h
+++ b/Source/WebCore/css/CSSSelector.h
@@ -30,8 +30,6 @@
namespace WebCore {
- class CSSSelectorBag;
-
// this class represents a selector for a StyleRule
class CSSSelector {
WTF_MAKE_NONCOPYABLE(CSSSelector); WTF_MAKE_FAST_ALLOCATED;
@@ -42,6 +40,7 @@ namespace WebCore {
, m_pseudoType(PseudoNotParsed)
, m_parsedNth(false)
, m_isLastInSelectorList(false)
+ , m_isLastInTagHistory(true)
, m_hasRareData(false)
, m_isForPage(false)
, m_tag(anyQName())
@@ -54,6 +53,7 @@ namespace WebCore {
, m_pseudoType(PseudoNotParsed)
, m_parsedNth(false)
, m_isLastInSelectorList(false)
+ , m_isLastInTagHistory(true)
, m_hasRareData(false)
, m_isForPage(false)
, m_tag(qName)
@@ -62,18 +62,10 @@ namespace WebCore {
~CSSSelector()
{
- // Exit if this selector does not own any objects to be deleted.
- if (m_hasRareData) {
- if (!m_data.m_rareData)
- return;
- } else if (!m_data.m_tagHistory)
- return;
-
- // We can not delete the owned object(s) by simply calling delete
- // directly on them. That would lead to recursive destructor calls
- // which might cause stack overflow. We have to delete them
- // iteratively.
- deleteReachableSelectors();
+ if (m_hasRareData)
+ delete m_data.m_rareData;
+ else if (m_data.m_value)
+ m_data.m_value->deref();
}
/**
@@ -183,23 +175,6 @@ namespace WebCore {
PseudoSearchDecoration,
PseudoSearchResultsDecoration,
PseudoSearchResultsButton,
- PseudoMediaControlsPanel,
- PseudoMediaControlsMuteButton,
- PseudoMediaControlsPlayButton,
- PseudoMediaControlsTimelineContainer,
- PseudoMediaControlsVolumeSliderContainer,
- PseudoMediaControlsVolumeSliderMuteButton,
- PseudoMediaControlsCurrentTimeDisplay,
- PseudoMediaControlsTimeRemainingDisplay,
- PseudoMediaControlsToggleClosedCaptions,
- PseudoMediaControlsTimeline,
- PseudoMediaControlsVolumeSlider,
- PseudoMediaControlsSeekBackButton,
- PseudoMediaControlsSeekForwardButton,
- PseudoMediaControlsRewindButton,
- PseudoMediaControlsReturnToRealtimeButton,
- PseudoMediaControlsStatusDisplay,
- PseudoMediaControlsFullscreenButton,
PseudoMeterHorizontalBar,
PseudoMeterVerticalBar,
PseudoMeterHorizontalOptimum,
@@ -214,7 +189,6 @@ namespace WebCore {
#endif
PseudoInnerSpinButton,
PseudoOuterSpinButton,
- PseudoProgressBarValue,
PseudoLeftPage,
PseudoRightPage,
PseudoFirstPage,
@@ -255,29 +229,31 @@ namespace WebCore {
static PseudoType parsePseudoType(const AtomicString&);
static PseudoId pseudoId(PseudoType);
- CSSSelector* tagHistory() const { return m_hasRareData ? m_data.m_rareData->m_tagHistory.get() : m_data.m_tagHistory; }
- void setTagHistory(CSSSelector* tagHistory);
+ // 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(); }
bool hasAttribute() const { return m_match == Id || m_match == Class || (m_hasRareData && m_data.m_rareData->m_attribute != 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; }
CSSSelector* simpleSelector() const { return m_hasRareData ? m_data.m_rareData->m_simpleSelector.get() : 0; }
- void setAttribute(const QualifiedName& value);
- void setArgument(const AtomicString& value);
- void setSimpleSelector(CSSSelector* value);
+ void setTag(const QualifiedName& value) { m_tag = value; }
+ void setValue(const AtomicString&);
+ void setAttribute(const QualifiedName&);
+ void setArgument(const AtomicString&);
+ void setSimpleSelector(PassOwnPtr<CSSSelector>);
bool parseNth();
bool matchNth(int count);
- bool matchesPseudoElement() const
- {
- if (m_pseudoType == PseudoUnknown)
- extractPseudoType();
- return m_match == PseudoElement;
- }
+ bool matchesPseudoElement() const;
bool isUnknownPseudoElement() const;
bool isSiblingSelector() const;
@@ -285,6 +261,9 @@ namespace WebCore {
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; }
@@ -297,12 +276,10 @@ namespace WebCore {
private:
bool m_parsedNth : 1; // Used for :nth-*
bool m_isLastInSelectorList : 1;
+ bool m_isLastInTagHistory : 1;
bool m_hasRareData : 1;
bool m_isForPage : 1;
- void releaseOwnedSelectorsToBag(CSSSelectorBag&);
- void deleteReachableSelectors();
-
unsigned specificityForOneSelector() const;
unsigned specificityForPage() const;
void extractPseudoType() const;
@@ -310,44 +287,47 @@ namespace WebCore {
struct RareData {
WTF_MAKE_NONCOPYABLE(RareData); WTF_MAKE_FAST_ALLOCATED;
public:
- RareData(PassOwnPtr<CSSSelector> tagHistory)
- : m_a(0)
+ RareData(PassRefPtr<AtomicStringImpl> value)
+ : m_value(value.leakRef())
+ , m_a(0)
, m_b(0)
- , m_tagHistory(tagHistory)
, m_attribute(anyQName())
, m_argument(nullAtom)
{
}
+ ~RareData()
+ {
+ if (m_value)
+ m_value->deref();
+ }
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-*
- OwnPtr<CSSSelector> m_tagHistory;
OwnPtr<CSSSelector> m_simpleSelector; // Used for :not.
QualifiedName m_attribute; // used for attribute selector
AtomicString m_argument; // Used for :contains, :lang and :nth-*
};
-
- void createRareData()
- {
- if (m_hasRareData)
- return;
- m_data.m_rareData = new RareData(adoptPtr(m_data.m_tagHistory));
- m_hasRareData = true;
- }
+ void createRareData();
union DataUnion {
- DataUnion() : m_tagHistory(0) { }
- CSSSelector* m_tagHistory;
+ DataUnion() : m_value(0) { }
+ AtomicStringImpl* m_value;
RareData* m_rareData;
} m_data;
- public:
- mutable AtomicString m_value;
QualifiedName m_tag;
};
+
+inline bool CSSSelector::matchesPseudoElement() const
+{
+ if (m_pseudoType == PseudoUnknown)
+ extractPseudoType();
+ return m_match == PseudoElement;
+}
inline bool CSSSelector::isUnknownPseudoElement() const
{
@@ -371,6 +351,26 @@ inline bool CSSSelector::isSiblingSelector() const
|| type == PseudoNthLastChild
|| type == PseudoNthLastOfType;
}
+
+inline void CSSSelector::setValue(const AtomicString& value)
+{
+ // Need to do ref counting manually for the union.
+ if (m_hasRareData) {
+ m_data.m_rareData->m_value = value.impl();
+ m_data.m_rareData->m_value->ref();
+ return;
+ }
+ 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
diff --git a/Source/WebCore/css/CSSSelectorList.cpp b/Source/WebCore/css/CSSSelectorList.cpp
index 7cb4df4..f4a8165 100644
--- a/Source/WebCore/css/CSSSelectorList.cpp
+++ b/Source/WebCore/css/CSSSelectorList.cpp
@@ -27,6 +27,8 @@
#include "config.h"
#include "CSSSelectorList.h"
+#include "CSSParserValues.h"
+
namespace WebCore {
CSSSelectorList::~CSSSelectorList()
@@ -41,26 +43,40 @@ void CSSSelectorList::adopt(CSSSelectorList& list)
list.m_selectorArray = 0;
}
-void CSSSelectorList::adoptSelectorVector(Vector<CSSSelector*>& selectorVector)
+void CSSSelectorList::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector)
{
deleteSelectors();
- const size_t size = selectorVector.size();
- ASSERT(size);
- if (size == 1) {
- m_selectorArray = selectorVector[0];
+ 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) * selectorVector.size()));
- for (size_t i = 0; i < size; ++i) {
- memcpy(&m_selectorArray[i], selectorVector[i], 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(selectorVector[i]);
- ASSERT(!m_selectorArray[i].isLastInSelectorList());
+ 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());
}
- m_selectorArray[size - 1].setLastInSelectorList();
+ ASSERT(flattenedSize == arrayIndex);
+ m_selectorArray[arrayIndex - 1].setLastInSelectorList();
selectorVector.shrink(0);
}
@@ -122,7 +138,7 @@ class SelectorNeedsNamespaceResolutionFunctor {
public:
bool operator()(CSSSelector* selector)
{
- if (selector->hasTag() && selector->m_tag.prefix() != nullAtom && selector->m_tag.prefix() != starAtom)
+ if (selector->hasTag() && selector->tag().prefix() != nullAtom && selector->tag().prefix() != starAtom)
return true;
if (selector->hasAttribute() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom)
return true;
diff --git a/Source/WebCore/css/CSSSelectorList.h b/Source/WebCore/css/CSSSelectorList.h
index abd9bc8..2b96d92 100644
--- a/Source/WebCore/css/CSSSelectorList.h
+++ b/Source/WebCore/css/CSSSelectorList.h
@@ -30,6 +30,8 @@
namespace WebCore {
+class CSSParserSelector;
+
class CSSSelectorList {
WTF_MAKE_NONCOPYABLE(CSSSelectorList); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -37,11 +39,11 @@ public:
~CSSSelectorList();
void adopt(CSSSelectorList& list);
- void adoptSelectorVector(Vector<CSSSelector*>& selectorVector);
+ void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
CSSSelector* first() const { return m_selectorArray ? m_selectorArray : 0; }
- static CSSSelector* next(CSSSelector* previous) { return previous->isLastInSelectorList() ? 0 : previous + 1; }
- bool hasOneSelector() const { return m_selectorArray ? m_selectorArray->isLastInSelectorList() : false; }
+ static CSSSelector* next(CSSSelector*);
+ bool hasOneSelector() const { return m_selectorArray && !next(m_selectorArray); }
bool selectorsNeedNamespaceResolution();
bool hasUnknownPseudoElements() const;
@@ -49,10 +51,19 @@ public:
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/CSSStyleRule.h b/Source/WebCore/css/CSSStyleRule.h
index 171b636..2d35043 100644
--- a/Source/WebCore/css/CSSStyleRule.h
+++ b/Source/WebCore/css/CSSStyleRule.h
@@ -50,7 +50,7 @@ public:
// Not part of the CSSOM
virtual bool parseString(const String&, bool = false);
- void adoptSelectorVector(Vector<CSSSelector*>& selectors) { m_selectorList.adoptSelectorVector(selectors); }
+ void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectors) { m_selectorList.adoptSelectorVector(selectors); }
void setDeclaration(PassRefPtr<CSSMutableStyleDeclaration>);
const CSSSelectorList& selectorList() const { return m_selectorList; }
diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp
index 5a21615..02cf8d3 100644
--- a/Source/WebCore/css/CSSStyleSelector.cpp
+++ b/Source/WebCore/css/CSSStyleSelector.cpp
@@ -2,7 +2,7 @@
* 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 Apple Inc. All rights reserved.
+ * 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/)
@@ -352,73 +352,43 @@ if (id == propID) { \
return; \
}
-class CSSRuleData {
- WTF_MAKE_NONCOPYABLE(CSSRuleData);
+class RuleData {
public:
- CSSRuleData(unsigned pos, CSSStyleRule* r, CSSSelector* sel, CSSRuleData* prev = 0)
- : m_position(pos)
- , m_rule(r)
- , m_selector(sel)
- , m_next(0)
- {
- if (prev)
- prev->m_next = this;
- }
-
- ~CSSRuleData()
- {
- }
+ RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
- unsigned position() { return m_position; }
- CSSStyleRule* rule() { return m_rule; }
- CSSSelector* selector() { return m_selector; }
- CSSRuleData* next() { return m_next; }
+ 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 hasTopSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasTopSelectorMatchingHTMLBasedOnRuleHash; }
+
+ // 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:
- unsigned m_position;
+ void collectDescendantSelectorIdentifierHashes();
+ void collectIdentifierHashes(const CSSSelector*, unsigned& identifierCount);
+
CSSStyleRule* m_rule;
CSSSelector* m_selector;
- CSSRuleData* m_next;
+ unsigned m_position : 29;
+ bool m_hasFastCheckableSelector : 1;
+ bool m_hasMultipartSelector : 1;
+ bool m_hasTopSelectorMatchingHTMLBasedOnRuleHash : 1;
+ // Use plain array instead of a Vector to minimize memory overhead.
+ unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
};
-class CSSRuleDataList {
- WTF_MAKE_NONCOPYABLE(CSSRuleDataList);
+class RuleSet {
+ WTF_MAKE_NONCOPYABLE(RuleSet);
public:
- CSSRuleDataList(unsigned pos, CSSStyleRule* rule, CSSSelector* sel)
- : m_first(new CSSRuleData(pos, rule, sel))
- , m_last(m_first)
- {
- }
-
- ~CSSRuleDataList()
- {
- CSSRuleData* ptr;
- CSSRuleData* next;
- ptr = m_first;
- while (ptr) {
- next = ptr->next();
- delete ptr;
- ptr = next;
- }
- }
-
- CSSRuleData* first() const { return m_first; }
- CSSRuleData* last() const { return m_last; }
-
- void append(unsigned pos, CSSStyleRule* rule, CSSSelector* sel) { m_last = new CSSRuleData(pos, rule, sel, m_last); }
-
-private:
- CSSRuleData* m_first;
- CSSRuleData* m_last;
-};
-
-class CSSRuleSet {
- WTF_MAKE_NONCOPYABLE(CSSRuleSet);
-public:
- CSSRuleSet();
- ~CSSRuleSet();
+ RuleSet();
+ ~RuleSet();
- typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
+ typedef HashMap<AtomicStringImpl*, Vector<RuleData>*> AtomRuleMap;
void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
@@ -427,34 +397,36 @@ public:
void addPageRule(CSSStyleRule* rule, CSSSelector* sel);
void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
CSSStyleRule* rule, CSSSelector* sel);
+ void shrinkToFit();
+ void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
- void collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules) const;
+ void collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<RuleSet>& siblingRules) const;
- CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
- CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
- CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
- CSSRuleDataList* getPseudoRules(AtomicStringImpl* key) { return m_pseudoRules.get(key); }
- CSSRuleDataList* getUniversalRules() { return m_universalRules.get(); }
- CSSRuleDataList* getPageRules() { return m_pageRules.get(); }
+ const Vector<RuleData>* getIDRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
+ const Vector<RuleData>* getClassRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
+ const Vector<RuleData>* getTagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
+ const Vector<RuleData>* getPseudoRules(AtomicStringImpl* key) const { return m_pseudoRules.get(key); }
+ const Vector<RuleData>* getUniversalRules() const { return &m_universalRules; }
+ const Vector<RuleData>* getPageRules() const { return &m_pageRules; }
public:
AtomRuleMap m_idRules;
AtomRuleMap m_classRules;
AtomRuleMap m_tagRules;
AtomRuleMap m_pseudoRules;
- OwnPtr<CSSRuleDataList> m_universalRules;
- OwnPtr<CSSRuleDataList> m_pageRules;
+ Vector<RuleData> m_universalRules;
+ Vector<RuleData> m_pageRules;
unsigned m_ruleCount;
- unsigned m_pageRuleCount;
+ bool m_autoShrinkToFitEnabled;
};
-static CSSRuleSet* defaultStyle;
-static CSSRuleSet* defaultQuirksStyle;
-static CSSRuleSet* defaultPrintStyle;
-static CSSRuleSet* defaultViewSourceStyle;
+static RuleSet* defaultStyle;
+static RuleSet* defaultQuirksStyle;
+static RuleSet* defaultPrintStyle;
+static RuleSet* defaultViewSourceStyle;
static CSSStyleSheet* simpleDefaultStyleSheet;
-static CSSRuleSet* siblingRulesInDefaultStyle;
+static RuleSet* siblingRulesInDefaultStyle;
RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
@@ -473,7 +445,7 @@ static inline bool elementCanUseSimpleDefaultStyle(Element* e)
static inline void collectSiblingRulesInDefaultStyle()
{
- OwnPtr<CSSRuleSet> siblingRules;
+ OwnPtr<RuleSet> siblingRules;
HashSet<AtomicStringImpl*> ids;
defaultStyle->collectIdsAndSiblingRules(ids, siblingRules);
ASSERT(ids.isEmpty());
@@ -546,10 +518,12 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee
if (m_rootDefaultStyle && view)
m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
- m_authorStyle = adoptPtr(new CSSRuleSet);
+ 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<CSSRuleSet> tempUserStyle = adoptPtr(new CSSRuleSet);
+ OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
if (pageUserSheet)
tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
if (pageGroupUserSheets) {
@@ -562,7 +536,7 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee
}
}
- if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRuleCount > 0)
+ if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
m_userStyle = tempUserStyle.release();
// Add rules from elements like SVG's <font-face>
@@ -575,8 +549,7 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee
StyleSheet* sheet = styleSheets->item(i);
if (sheet->isCSSStyleSheet() && !sheet->disabled())
m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
- }
-
+ }
// 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.
@@ -587,6 +560,10 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee
if (m_userStyle)
m_userStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules);
+ m_authorStyle->shrinkToFit();
+ if (m_siblingRules)
+ m_siblingRules->shrinkToFit();
+
if (document->renderer() && document->renderer()->style())
document->renderer()->style()->font().update(fontSelector());
}
@@ -622,13 +599,13 @@ static void loadFullDefaultStyle()
ASSERT(defaultStyle);
delete defaultStyle;
simpleDefaultStyleSheet->deref();
- defaultStyle = new CSSRuleSet;
+ defaultStyle = new RuleSet;
simpleDefaultStyleSheet = 0;
} else {
ASSERT(!defaultStyle);
- defaultStyle = new CSSRuleSet;
- defaultPrintStyle = new CSSRuleSet;
- defaultQuirksStyle = new CSSRuleSet;
+ defaultStyle = new RuleSet;
+ defaultPrintStyle = new RuleSet;
+ defaultQuirksStyle = new RuleSet;
}
// Strict-mode rules.
@@ -661,9 +638,9 @@ static void loadSimpleDefaultStyle()
ASSERT(!defaultStyle);
ASSERT(!simpleDefaultStyleSheet);
- defaultStyle = new CSSRuleSet;
- defaultPrintStyle = new CSSRuleSet;
- defaultQuirksStyle = new CSSRuleSet;
+ defaultStyle = new RuleSet;
+ defaultPrintStyle = new RuleSet;
+ defaultQuirksStyle = new RuleSet;
simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
@@ -674,16 +651,98 @@ static void loadSimpleDefaultStyle()
static void loadViewSourceStyle()
{
ASSERT(!defaultViewSourceStyle);
- defaultViewSourceStyle = new CSSRuleSet;
+ defaultViewSourceStyle = new RuleSet;
defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
}
+
+static inline void collectElementIdentifierHashes(const Element* element, Vector<unsigned, 4>& identifierHashes)
+{
+ identifierHashes.append(element->localName().impl()->existingHash());
+ if (element->hasID())
+ identifierHashes.append(element->idForStyleResolution().impl()->existingHash());
+ 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());
+ }
+}
+
+void CSSStyleSelector::pushParentStackFrame(Element* parent)
+{
+ ASSERT(m_ancestorIdentifierFilter);
+ ASSERT(m_parentStack.isEmpty() || m_parentStack.last().element == parent->parentElement());
+ ASSERT(!m_parentStack.isEmpty() || !parent->parentElement());
+ 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 CSSStyleSelector::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 CSSStyleSelector::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->parentElement()) {
+ Vector<Element*, 30> ancestors;
+ for (Element* ancestor = parent; ancestor; ancestor = ancestor->parentElement())
+ ancestors.append(ancestor);
+ int count = ancestors.size();
+ for (int n = count - 1; n >= 0; --n)
+ pushParentStackFrame(ancestors[n]);
+ return;
+ }
+ } else if (!parent->parentElement()) {
+ // 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->parentElement())
+ return;
+ }
+ pushParentStackFrame(parent);
+}
+
+void CSSStyleSelector::popParent(Element* parent)
+{
+ if (m_parentStack.isEmpty() || m_parentStack.last().element != parent)
+ return;
+ popParentStackFrame();
+}
void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
{
m_matchedDecls.append(decl);
}
-void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
+void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
{
m_matchedRules.clear();
@@ -728,21 +787,38 @@ void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& l
}
}
-void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
+inline bool CSSStyleSelector::fastRejectSelector(const RuleData& ruleData) const
+{
+ ASSERT(m_ancestorIdentifierFilter);
+ const unsigned* descendantSelectorIdentifierHashes = ruleData.descendantSelectorIdentifierHashes();
+ for (unsigned n = 0; n < RuleData::maximumIdentifierCount && descendantSelectorIdentifierHashes[n]; ++n) {
+ if (!m_ancestorIdentifierFilter->mayContain(descendantSelectorIdentifierHashes[n]))
+ return true;
+ }
+ return false;
+}
+
+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_parentStack.isEmpty() && m_parentStack.last().element == m_parentNode;
- for (CSSRuleData* d = rules->first(); d; d = d->next()) {
- CSSStyleRule* rule = d->rule();
- if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL()))
- continue;
- if (checkSelector(d->selector())) {
+ unsigned size = rules->size();
+ for (unsigned i = 0; i < size; ++i) {
+ const RuleData& ruleData = rules->at(i);
+ if (canUseFastReject && fastRejectSelector(ruleData))
+ continue;
+ if (checkSelector(ruleData)) {
// If the rule has no properties to apply, then ignore it in the non-debug mode.
+ CSSStyleRule* rule = ruleData.rule();
CSSMutableStyleDeclaration* decl = rule->declaration();
if (!decl || (!decl->length() && !includeEmptyRules))
continue;
-
+ if (m_checker.m_sameOriginOnly && !m_checker.m_document->securityOrigin()->canRequest(rule->baseURL()))
+ 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.m_pseudoStyle == NOPSEUDO) {
@@ -757,20 +833,20 @@ void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleI
firstRuleIndex = lastRuleIndex;
// Add this rule to our list of matched rules.
- addMatchedRule(d);
+ addMatchedRule(&ruleData);
}
}
}
}
-static bool operator >(CSSRuleData& r1, CSSRuleData& r2)
+static bool operator >(const RuleData& r1, const RuleData& r2)
{
int spec1 = r1.selector()->specificity();
int spec2 = r2.selector()->specificity();
return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
}
-static bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
+static bool operator <=(const RuleData& r1, const RuleData& r2)
{
return !(r1 > r2);
}
@@ -785,8 +861,8 @@ void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
for (unsigned i = end - 1; i > start; i--) {
bool sorted = true;
for (unsigned j = start; j < i; j++) {
- CSSRuleData* elt = m_matchedRules[j];
- CSSRuleData* elt2 = m_matchedRules[j + 1];
+ const RuleData* elt = m_matchedRules[j];
+ const RuleData* elt2 = m_matchedRules[j + 1];
if (*elt > *elt2) {
sorted = false;
m_matchedRules[j] = elt2;
@@ -804,8 +880,8 @@ void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
sortMatchedRules(start, mid);
sortMatchedRules(mid, end);
- CSSRuleData* elt = m_matchedRules[mid - 1];
- CSSRuleData* elt2 = m_matchedRules[mid];
+ const RuleData* elt = m_matchedRules[mid - 1];
+ const RuleData* elt2 = m_matchedRules[mid];
// Handle the fast common case (of equal specificity). The list may already
// be completely sorted.
@@ -814,7 +890,7 @@ void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
// We have to merge sort. Ensure our merge buffer is big enough to hold
// all the items.
- Vector<CSSRuleData*> rulesMergeBuffer;
+ Vector<const RuleData*> rulesMergeBuffer;
rulesMergeBuffer.reserveInitialCapacity(end - start);
unsigned i1 = start;
@@ -1129,6 +1205,14 @@ inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned&
return node;
}
+static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
+{
+ return parentStyle->childrenAffectedByPositionalRules()
+ || parentStyle->childrenAffectedByFirstChildRules()
+ || parentStyle->childrenAffectedByLastChildRules()
+ || parentStyle->childrenAffectedByDirectAdjacentRules();
+}
+
ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
{
if (!m_styledElement || !m_parentStyle)
@@ -1139,6 +1223,8 @@ ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
// Ids stop style sharing if they show up in the stylesheets.
if (m_styledElement->hasID() && m_idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
return 0;
+ if (parentStylePreventsSharing(m_parentStyle))
+ return 0;
// Check previous siblings.
unsigned count = 0;
Node* shareNode = findSiblingForStyleSharing(m_styledElement->previousSibling(), count);
@@ -1152,7 +1238,7 @@ ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
if (matchesSiblingRules())
return 0;
// Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
- if (m_parentStyle->childrenAffectedByPositionalRules())
+ if (parentStylePreventsSharing(m_parentStyle))
return 0;
return shareNode->renderStyle();
}
@@ -1160,7 +1246,7 @@ ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
{
// First we match rules from the user agent sheet.
- CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
+ RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
? defaultPrintStyle : defaultStyle;
matchRules(userAgentStyleSheet, firstUARule, lastUARule, false);
@@ -2010,21 +2096,103 @@ PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e,
return m_ruleList.release();
}
-bool CSSStyleSelector::checkSelector(CSSSelector* sel)
+inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
{
m_dynamicPseudo = NOPSEUDO;
- // Check the selector
- SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
+ if (ruleData.hasFastCheckableSelector()) {
+ // We know this selector does not include any pseudo selectors.
+ if (m_checker.m_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.hasTopSelectorMatchingHTMLBasedOnRuleHash() && !ruleData.hasMultipartSelector() && m_element->isHTMLElement())
+ return true;
+ return SelectorChecker::fastCheckSelector(ruleData.selector(), m_element);
+ }
+
+ // Slow path.
+ SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
if (match != SelectorMatches)
return false;
-
if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
return false;
+ return true;
+}
+
+static inline bool selectorTagMatches(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();
+}
+static inline bool isFastCheckableSelector(const CSSSelector* selector)
+{
+ for (; selector; selector = selector->tagHistory()) {
+ if (selector->relation() != CSSSelector::Descendant)
+ return false;
+ if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
+ return false;
+ }
return true;
}
+bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element)
+{
+ ASSERT(isFastCheckableSelector(selector));
+
+ // The top selector requires tag check only as rule hashes have already handled id and class matches.
+ if (!selectorTagMatches(element, selector))
+ return false;
+
+ selector = selector->tagHistory();
+ if (!selector)
+ return true;
+ const Element* ancestor = element;
+ // We know this compound selector has descendant combinators only and all components are simple.
+ for (; selector; selector = selector->tagHistory()) {
+ AtomicStringImpl* value;
+ switch (selector->m_match) {
+ case CSSSelector::Class:
+ value = selector->value().impl();
+ while (true) {
+ if (!(ancestor = ancestor->parentElement()))
+ return false;
+ const StyledElement* styledElement = static_cast<const StyledElement*>(ancestor);
+ if (ancestor->hasClass() && styledElement->classNames().contains(value) && selectorTagMatches(ancestor, selector))
+ break;
+ }
+ break;
+ case CSSSelector::Id:
+ value = selector->value().impl();
+ while (true) {
+ if (!(ancestor = ancestor->parentElement()))
+ return false;
+ if (ancestor->hasID() && ancestor->idForStyleResolution().impl() == value && selectorTagMatches(ancestor, selector))
+ break;
+ }
+ break;
+ case CSSSelector::None:
+ while (true) {
+ if (!(ancestor = ancestor->parentElement()))
+ return false;
+ if (selectorTagMatches(ancestor, selector))
+ break;
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ }
+ return true;
+}
+
+
// Recursive check of selectors and combinators
// It can return 3 different values:
// * SelectorMatches - the selector matches the element e
@@ -2216,21 +2384,15 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
if (!e)
return false;
- if (sel->hasTag()) {
- const AtomicString& selLocalName = sel->m_tag.localName();
- if (selLocalName != starAtom && selLocalName != e->localName())
- return false;
- const AtomicString& selNS = sel->m_tag.namespaceURI();
- if (selNS != starAtom && selNS != e->namespaceURI())
- return false;
- }
+ if (!selectorTagMatches(e, sel))
+ return false;
if (sel->hasAttribute()) {
if (sel->m_match == CSSSelector::Class)
- return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->m_value);
+ return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->value());
if (sel->m_match == CSSSelector::Id)
- return e->hasID() && e->idForStyleResolution() == sel->m_value;
+ return e->hasID() && e->idForStyleResolution() == sel->value();
const QualifiedName& attr = sel->attribute();
@@ -2249,22 +2411,22 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
switch (sel->m_match) {
case CSSSelector::Exact:
- if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value))
+ if (caseSensitive ? sel->value() != value : !equalIgnoringCase(sel->value(), value))
return false;
break;
case CSSSelector::List:
{
// Ignore empty selectors or selectors containing spaces
- if (sel->m_value.contains(' ') || sel->m_value.isEmpty())
+ if (sel->value().contains(' ') || sel->value().isEmpty())
return false;
unsigned startSearchAt = 0;
while (true) {
- size_t foundPos = value.find(sel->m_value, startSearchAt, caseSensitive);
+ size_t foundPos = value.find(sel->value(), startSearchAt, caseSensitive);
if (foundPos == notFound)
return false;
if (foundPos == 0 || value[foundPos - 1] == ' ') {
- unsigned endStr = foundPos + sel->m_value.length();
+ unsigned endStr = foundPos + sel->value().length();
if (endStr == value.length() || value[endStr] == ' ')
break; // We found a match.
}
@@ -2275,24 +2437,24 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme
break;
}
case CSSSelector::Contain:
- if (!value.contains(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
+ if (!value.contains(sel->value(), caseSensitive) || sel->value().isEmpty())
return false;
break;
case CSSSelector::Begin:
- if (!value.startsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
+ if (!value.startsWith(sel->value(), caseSensitive) || sel->value().isEmpty())
return false;
break;
case CSSSelector::End:
- if (!value.endsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
+ if (!value.endsWith(sel->value(), caseSensitive) || sel->value().isEmpty())
return false;
break;
case CSSSelector::Hyphen:
- if (value.length() < sel->m_value.length())
+ if (value.length() < sel->value().length())
return false;
- if (!value.startsWith(sel->m_value, caseSensitive))
+ if (!value.startsWith(sel->value(), caseSensitive))
return false;
// It they start the same, check for exact match or following '-':
- if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-')
+ if (value.length() != sel->value().length() && value[sel->value().length()] != '-')
return false;
break;
case CSSSelector::PseudoClass:
@@ -2875,70 +3037,130 @@ bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* s
// -----------------------------------------------------------------
-CSSRuleSet::CSSRuleSet()
+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->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class)
+ return false;
+ return selector->tag() == starAtom;
+}
+
+RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
+ : m_rule(rule)
+ , m_selector(selector)
+ , m_position(position)
+ , m_hasFastCheckableSelector(isFastCheckableSelector(selector))
+ , m_hasMultipartSelector(selector->tagHistory())
+ , m_hasTopSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
+{
+ collectDescendantSelectorIdentifierHashes();
+}
+
+inline void RuleData::collectIdentifierHashes(const CSSSelector* selector, unsigned& identifierCount)
+{
+ if ((selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class) && !selector->value().isEmpty())
+ m_descendantSelectorIdentifierHashes[identifierCount++] = selector->value().impl()->existingHash();
+ if (identifierCount == maximumIdentifierCount)
+ return;
+ const AtomicString& localName = selector->tag().localName();
+ if (localName != starAtom)
+ m_descendantSelectorIdentifierHashes[identifierCount++] = localName.impl()->existingHash();
+}
+
+inline void RuleData::collectDescendantSelectorIdentifierHashes()
+{
+ unsigned identifierCount = 0;
+ CSSSelector::Relation relation = m_selector->relation();
+
+ // Skip the topmost selector. It is handled quickly by the rule hashes.
+ bool skipOverSubselectors = true;
+ for (const CSSSelector* selector = m_selector->tagHistory(); selector; selector = selector->tagHistory()) {
+ // Only collect identifiers that match ancestors.
+ switch (relation) {
+ case CSSSelector::SubSelector:
+ if (!skipOverSubselectors)
+ collectIdentifierHashes(selector, identifierCount);
+ break;
+ case CSSSelector::DirectAdjacent:
+ case CSSSelector::IndirectAdjacent:
+ case CSSSelector::ShadowDescendant:
+ skipOverSubselectors = true;
+ break;
+ case CSSSelector::Descendant:
+ case CSSSelector::Child:
+ skipOverSubselectors = false;
+ collectIdentifierHashes(selector, identifierCount);
+ break;
+ }
+ if (identifierCount == maximumIdentifierCount)
+ return;
+ relation = selector->relation();
+ }
+ m_descendantSelectorIdentifierHashes[identifierCount] = 0;
+}
+
+RuleSet::RuleSet()
: m_ruleCount(0)
- , m_pageRuleCount(0)
+ , m_autoShrinkToFitEnabled(true)
{
}
-CSSRuleSet::~CSSRuleSet()
+RuleSet::~RuleSet()
{
deleteAllValues(m_idRules);
deleteAllValues(m_classRules);
+ deleteAllValues(m_pseudoRules);
deleteAllValues(m_tagRules);
}
-void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
+void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
CSSStyleRule* rule, CSSSelector* sel)
{
if (!key) return;
- CSSRuleDataList* rules = map.get(key);
+ Vector<RuleData>* rules = map.get(key);
if (!rules) {
- rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
+ rules = new Vector<RuleData>;
map.set(key, rules);
- } else
- rules->append(m_ruleCount++, rule, sel);
+ }
+ rules->append(RuleData(rule, sel, m_ruleCount++));
}
-void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
+void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
{
if (sel->m_match == CSSSelector::Id) {
- addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel);
+ addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
return;
}
if (sel->m_match == CSSSelector::Class) {
- addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel);
+ addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
return;
}
if (sel->isUnknownPseudoElement()) {
- addToRuleSet(sel->m_value.impl(), m_pseudoRules, rule, sel);
+ addToRuleSet(sel->value().impl(), m_pseudoRules, rule, sel);
return;
}
- const AtomicString& localName = sel->m_tag.localName();
+ const AtomicString& localName = sel->tag().localName();
if (localName != starAtom) {
addToRuleSet(localName.impl(), m_tagRules, rule, sel);
return;
}
- // Just put it in the universal rule set.
- if (!m_universalRules)
- m_universalRules = adoptPtr(new CSSRuleDataList(m_ruleCount++, rule, sel));
- else
- m_universalRules->append(m_ruleCount++, rule, sel);
+ m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
}
-void CSSRuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
+void RuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
{
- if (!m_pageRules)
- m_pageRules = adoptPtr(new CSSRuleDataList(m_pageRuleCount++, rule, sel));
- else
- m_pageRules->append(m_pageRuleCount++, rule, sel);
+ m_pageRules.append(RuleData(rule, sel, m_pageRules.size()));
}
-void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
+void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
{
if (!sheet)
return;
@@ -2987,9 +3209,11 @@ void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluat
} else if (item->isKeyframesRule())
styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item));
}
+ if (m_autoShrinkToFitEnabled)
+ shrinkToFit();
}
-void CSSRuleSet::addStyleRule(CSSStyleRule* rule)
+void RuleSet::addStyleRule(CSSStyleRule* rule)
{
if (rule->isPageRule()) {
CSSPageRule* pageRule = static_cast<CSSPageRule*>(rule);
@@ -3000,45 +3224,63 @@ void CSSRuleSet::addStyleRule(CSSStyleRule* rule)
}
}
-static void collectIdsAndSiblingRulesFromList(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules, const CSSRuleDataList* rules)
+static void collectIdsAndSiblingRulesFromList(HashSet<AtomicStringImpl*>& ids, OwnPtr<RuleSet>& siblingRules, const Vector<RuleData>& rules)
{
- for (CSSRuleData* data = rules->first(); data; data = data->next()) {
+ unsigned size = rules.size();
+ for (unsigned i = 0; i < size; ++i) {
+ const RuleData& ruleData = rules[i];
bool foundSiblingSelector = false;
- for (CSSSelector* selector = data->selector(); selector; selector = selector->tagHistory()) {
- if (selector->m_match == CSSSelector::Id && !selector->m_value.isEmpty())
- ids.add(selector->m_value.impl());
+ for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
+ if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty())
+ ids.add(selector->value().impl());
if (CSSSelector* simpleSelector = selector->simpleSelector()) {
ASSERT(!simpleSelector->simpleSelector());
- if (simpleSelector->m_match == CSSSelector::Id && !simpleSelector->m_value.isEmpty())
- ids.add(simpleSelector->m_value.impl());
+ if (simpleSelector->m_match == CSSSelector::Id && !simpleSelector->value().isEmpty())
+ ids.add(simpleSelector->value().impl());
}
if (selector->isSiblingSelector())
foundSiblingSelector = true;
}
if (foundSiblingSelector) {
if (!siblingRules)
- siblingRules = adoptPtr(new CSSRuleSet);
- siblingRules->addRule(data->rule(), data->selector());
+ siblingRules = adoptPtr(new RuleSet);
+ siblingRules->addRule(ruleData.rule(), ruleData.selector());
}
}
}
-void CSSRuleSet::collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<CSSRuleSet>& siblingRules) const
+void RuleSet::collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<RuleSet>& siblingRules) const
{
AtomRuleMap::const_iterator end = m_idRules.end();
for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
- collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+ collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second);
end = m_classRules.end();
for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
- collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+ collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second);
end = m_tagRules.end();
for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
- collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
+ collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second);
end = m_pseudoRules.end();
for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it)
- collectIdsAndSiblingRulesFromList(ids, siblingRules, it->second);
- if (m_universalRules)
- collectIdsAndSiblingRulesFromList(ids, siblingRules, m_universalRules.get());
+ collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second);
+ collectIdsAndSiblingRulesFromList(ids, siblingRules, 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_pseudoRules);
+ m_universalRules.shrinkToFit();
+ m_pageRules.shrinkToFit();
}
// -------------------------------------------------------------------------------------
@@ -3107,7 +3349,7 @@ void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int e
}
}
-void CSSStyleSelector::matchPageRules(CSSRuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
{
m_matchedRules.clear();
@@ -3128,17 +3370,19 @@ void CSSStyleSelector::matchPageRules(CSSRuleSet* rules, bool isLeftPage, bool i
addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
}
-void CSSStyleSelector::matchPageRulesForList(CSSRuleDataList* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
+void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
{
if (!rules)
return;
- for (CSSRuleData* d = rules->first(); d; d = d->next()) {
- CSSStyleRule* rule = d->rule();
- const AtomicString& selectorLocalName = d->selector()->m_tag.localName();
+ 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 = d->selector()->pseudoType();
+ CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
|| (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
|| (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
@@ -3150,7 +3394,7 @@ void CSSStyleSelector::matchPageRulesForList(CSSRuleDataList* rules, bool isLeft
continue;
// Add this rule to our list of matched rules.
- addMatchedRule(d);
+ addMatchedRule(&ruleData);
}
}
@@ -4295,9 +4539,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
}
// FIXME: Should clamp all sorts of other integer properties too.
- const double minIntAsDouble = INT_MIN;
- const double maxIntAsDouble = INT_MAX;
- m_style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble))));
+ m_style->setZIndex(clampToInteger(primitiveValue->getDoubleValue()));
return;
}
case CSSPropertyWidows:
@@ -5763,6 +6005,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
case CSSPropertyWebkitTextCombine:
HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textCombine, TextCombine)
+ if (m_style->hasTextCombine())
+ m_style->setUnique(); // The style could be modified in RenderCombineText depending on text metrics.
return;
case CSSPropertyWebkitTextEmphasisPosition:
@@ -7196,9 +7440,21 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle*
break;
}
case WebKitCSSTransformValue::PerspectiveTransformOperation: {
- double p = firstValue->getDoubleValue();
- if (p < 0.0)
+ bool ok = true;
+ Length p = Length(0, Fixed);
+ if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType()))
+ p = convertToLength(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;
+ val = clampToPositiveInteger(val);
+ p = Length(static_cast<int>(val), Fixed);
+ }
+
+ if (!ok)
return false;
+
operations.operations().append(PerspectiveTransformOperation::create(p));
break;
}
diff --git a/Source/WebCore/css/CSSStyleSelector.h b/Source/WebCore/css/CSSStyleSelector.h
index e035af2..6065c2c 100644
--- a/Source/WebCore/css/CSSStyleSelector.h
+++ b/Source/WebCore/css/CSSStyleSelector.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * 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
@@ -27,6 +27,7 @@
#include "LinkHash.h"
#include "MediaQueryExp.h"
#include "RenderStyle.h"
+#include <wtf/BloomFilter.h>
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/RefPtr.h>
@@ -42,10 +43,7 @@ class CSSProperty;
class CSSFontFace;
class CSSFontFaceRule;
class CSSImageValue;
-class CSSRuleData;
-class CSSRuleDataList;
class CSSRuleList;
-class CSSRuleSet;
class CSSSelector;
class CSSStyleRule;
class CSSStyleSheet;
@@ -61,6 +59,8 @@ class KeyframeList;
class KeyframeValue;
class MediaQueryEvaluator;
class Node;
+class RuleData;
+class RuleSet;
class Settings;
class StyleImage;
class StyleSheet;
@@ -90,6 +90,10 @@ public:
CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets,
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);
+ void popParent(Element* parent);
PassRefPtr<RenderStyle> styleForElement(Element* e, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, bool matchVisitedPseudoClass = false);
@@ -115,6 +119,9 @@ public:
Node* locateCousinList(Element* parent, unsigned depth = 1) const;
Node* findSiblingForStyleSharing(Node*, unsigned& count) const;
bool canShareStyleWithElement(Node*) const;
+
+ void pushParentStackFrame(Element* parent);
+ void popParentStackFrame();
RenderStyle* style() const { return m_style.get(); }
@@ -157,9 +164,6 @@ public:
CSSFontSelector* fontSelector() const { return m_fontSelector.get(); }
- // Checks if a compound selector (which can consist of multiple simple selectors) matches the current element.
- bool checkSelector(CSSSelector*);
-
void addViewportDependentMediaQueryResult(const MediaQueryExp*, bool result);
bool affectedByViewportChange() const;
@@ -182,28 +186,43 @@ public:
void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*);
- void addMatchedRule(CSSRuleData* rule) { m_matchedRules.append(rule); }
+ void addMatchedRule(const RuleData* rule) { m_matchedRules.append(rule); }
void addMatchedDeclaration(CSSMutableStyleDeclaration* decl);
- void matchRules(CSSRuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
- void matchRulesForList(CSSRuleDataList*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules);
+ 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(unsigned start, unsigned end);
+
+ bool checkSelector(const RuleData&);
template <bool firstPass>
void applyDeclarations(bool important, int startIndex, int endIndex);
- void matchPageRules(CSSRuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName);
- void matchPageRulesForList(CSSRuleDataList*, bool isLeftPage, bool isFirstPage, const String& pageName);
+ 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<CSSRuleSet> m_authorStyle;
- OwnPtr<CSSRuleSet> m_userStyle;
+ OwnPtr<RuleSet> m_authorStyle;
+ OwnPtr<RuleSet> m_userStyle;
- OwnPtr<CSSRuleSet> m_siblingRules;
+ OwnPtr<RuleSet> m_siblingRules;
HashSet<AtomicStringImpl*> m_idsInRules;
+
+ 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;
bool m_hasUAAppearance;
BorderData m_borderData;
@@ -225,6 +244,7 @@ public:
SelectorMatch checkSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const;
bool checkOneSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle*, RenderStyle* elementParentStyle) const;
bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const;
+ static bool fastCheckSelector(const CSSSelector*, const Element*);
EInsideLink determineLinkState(Element* element) const;
EInsideLink determineLinkStateSlowCase(Element* element) const;
@@ -293,7 +313,7 @@ public:
// A buffer used to hold the set of matched rules for an element, and a temporary buffer used for
// merge sorting.
- Vector<CSSRuleData*, 32> m_matchedRules;
+ Vector<const RuleData*, 32> m_matchedRules;
RefPtr<CSSRuleList> m_ruleList;
diff --git a/Source/WebCore/css/CSSStyleSheet.cpp b/Source/WebCore/css/CSSStyleSheet.cpp
index d5487a1..16c2ba8 100644
--- a/Source/WebCore/css/CSSStyleSheet.cpp
+++ b/Source/WebCore/css/CSSStyleSheet.cpp
@@ -53,7 +53,6 @@ static bool isAcceptableCSSStyleSheetParent(Node* parentNode)
CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href, const KURL& baseURL, const String& charset)
: StyleSheet(parentSheet, href, baseURL)
- , m_document(parentSheet ? parentSheet->document() : 0)
, m_charset(charset)
, m_loadCompleted(false)
, m_strictParsing(!parentSheet || parentSheet->useStrictParsing())
@@ -64,7 +63,6 @@ CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href, con
CSSStyleSheet::CSSStyleSheet(Node* parentNode, const String& href, const KURL& baseURL, const String& charset)
: StyleSheet(parentNode, href, baseURL)
- , m_document(parentNode->document())
, m_charset(charset)
, m_loadCompleted(false)
, m_strictParsing(false)
@@ -82,7 +80,6 @@ CSSStyleSheet::CSSStyleSheet(CSSRule* ownerRule, const String& href, const KURL&
, m_hasSyntacticallyValidCSSHeader(true)
{
CSSStyleSheet* parentSheet = ownerRule ? ownerRule->parentStyleSheet() : 0;
- m_document = parentSheet ? parentSheet->document() : 0;
m_isUserStyleSheet = parentSheet ? parentSheet->isUserStyleSheet() : false;
}
@@ -233,6 +230,24 @@ void CSSStyleSheet::checkLoaded()
m_loadCompleted = ownerNode() ? ownerNode()->sheetLoaded() : true;
}
+Document* CSSStyleSheet::document()
+{
+ StyleBase* styleObject = this;
+ while (styleObject) {
+ if (styleObject->isCSSStyleSheet()) {
+ Node* ownerNode = static_cast<CSSStyleSheet*>(styleObject)->ownerNode();
+ if (ownerNode)
+ return ownerNode->document();
+ }
+ if (styleObject->isRule())
+ styleObject = static_cast<CSSRule*>(styleObject)->parentStyleSheet();
+ else
+ styleObject = styleObject->parent();
+ }
+
+ return 0;
+}
+
void CSSStyleSheet::styleSheetChanged()
{
StyleBase* root = this;
diff --git a/Source/WebCore/css/CSSStyleSheet.h b/Source/WebCore/css/CSSStyleSheet.h
index 725518f..062886a 100644
--- a/Source/WebCore/css/CSSStyleSheet.h
+++ b/Source/WebCore/css/CSSStyleSheet.h
@@ -87,7 +87,7 @@ public:
virtual void checkLoaded();
- Document* document() { return m_document; }
+ Document* document();
const String& charset() const { return m_charset; }
@@ -112,7 +112,6 @@ private:
virtual bool isCSSStyleSheet() const { return true; }
virtual String type() const { return "text/css"; }
- Document* m_document;
OwnPtr<CSSNamespace> m_namespaces;
String m_charset;
bool m_loadCompleted : 1;
diff --git a/Source/WebCore/css/CSSValue.h b/Source/WebCore/css/CSSValue.h
index d1464ca..e8053fe 100644
--- a/Source/WebCore/css/CSSValue.h
+++ b/Source/WebCore/css/CSSValue.h
@@ -21,7 +21,6 @@
#ifndef CSSValue_h
#define CSSValue_h
-#include "CSSParserValues.h"
#include "KURLHash.h"
#include <wtf/ListHashSet.h>
#include <wtf/RefPtr.h>
@@ -70,8 +69,6 @@ public:
virtual bool isSVGPaint() const { return false; }
#endif
- virtual CSSParserValue parserValue() const { ASSERT_NOT_REACHED(); return CSSParserValue(); }
-
virtual void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*) { }
};
diff --git a/Source/WebCore/css/CSSValueList.cpp b/Source/WebCore/css/CSSValueList.cpp
index f8d8457..e107fb4 100644
--- a/Source/WebCore/css/CSSValueList.cpp
+++ b/Source/WebCore/css/CSSValueList.cpp
@@ -120,17 +120,6 @@ String CSSValueList::cssText() const
return result;
}
-PassOwnPtr<CSSParserValueList> CSSValueList::createParserValueList() const
-{
- size_t size = m_values.size();
- if (!size)
- return 0;
- OwnPtr<CSSParserValueList> result = adoptPtr(new CSSParserValueList);
- for (size_t i = 0; i < size; ++i)
- result->addValue(m_values[i]->parserValue());
- return result.release();
-}
-
void CSSValueList::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const CSSStyleSheet* styleSheet)
{
size_t size = m_values.size();
diff --git a/Source/WebCore/css/CSSValueList.h b/Source/WebCore/css/CSSValueList.h
index 0d5c882..b2e6063 100644
--- a/Source/WebCore/css/CSSValueList.h
+++ b/Source/WebCore/css/CSSValueList.h
@@ -58,8 +58,6 @@ public:
virtual String cssText() const;
- PassOwnPtr<CSSParserValueList> createParserValueList() const;
-
virtual void addSubresourceStyleURLs(ListHashSet<KURL>&, const CSSStyleSheet*);
protected:
diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
index 23f9f34..bf0c463 100644
--- a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
+++ b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
@@ -24,12 +24,13 @@
*/
#include "config.h"
+#include "WebKitCSSKeyframesRule.h"
+#include "CSSMutableStyleDeclaration.h"
#include "CSSParser.h"
-#include "WebKitCSSKeyframesRule.h"
-#include "WebKitCSSKeyframeRule.h"
#include "CSSRuleList.h"
#include "StyleSheet.h"
+#include "WebKitCSSKeyframeRule.h"
namespace WebCore {
@@ -45,8 +46,13 @@ WebKitCSSKeyframesRule::~WebKitCSSKeyframesRule()
if (length == 0)
return;
- for (int i = 0; i < length; i++)
+ for (int i = 0; i < length; i++) {
+ if (m_lstCSSRules->item(i)->isKeyframeRule()) {
+ if (CSSMutableStyleDeclaration* style = static_cast<WebKitCSSKeyframeRule*>(m_lstCSSRules->item(i))->style())
+ style->setParent(0);
+ }
m_lstCSSRules->item(i)->setParent(0);
+ }
}
String WebKitCSSKeyframesRule::name() const
diff --git a/Source/WebCore/css/WebKitCSSMatrix.cpp b/Source/WebCore/css/WebKitCSSMatrix.cpp
index 14f6b4e..163eac8 100644
--- a/Source/WebCore/css/WebKitCSSMatrix.cpp
+++ b/Source/WebCore/css/WebKitCSSMatrix.cpp
@@ -91,9 +91,7 @@ PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::multiply(WebKitCSSMatrix* secondMat
if (!secondMatrix)
return 0;
- TransformationMatrix tmp(secondMatrix->m_matrix);
- tmp.multiply(m_matrix);
- return WebKitCSSMatrix::create(tmp);
+ return WebKitCSSMatrix::create(TransformationMatrix(m_matrix).multiply(secondMatrix->m_matrix));
}
PassRefPtr<WebKitCSSMatrix> WebKitCSSMatrix::inverse(ExceptionCode& ec) const
diff --git a/Source/WebCore/css/html.css b/Source/WebCore/css/html.css
index 3c75559..0f13fcb 100644
--- a/Source/WebCore/css/html.css
+++ b/Source/WebCore/css/html.css
@@ -61,7 +61,10 @@ body {
p {
display: block;
- margin: 1.0__qem 0px
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1__qem;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
}
div {
@@ -87,7 +90,10 @@ address {
blockquote {
display: block;
- margin: 1__qem 40px 1em 40px
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 40px;
+ -webkit-margin-end: 40px;
}
figcaption {
@@ -96,7 +102,10 @@ figcaption {
figure {
display: block;
- margin: 1em 40px 1em 40px
+ -webkit-margin-before: 1em;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 40px;
+ -webkit-margin-end: 40px;
}
q {
@@ -121,7 +130,10 @@ center {
hr {
display: block;
- margin: 0.5em auto;
+ -webkit-margin-before: 0.5em;
+ -webkit-margin-after: 0.5em;
+ -webkit-margin-start: auto;
+ -webkit-margin-end: auto;
border-style: inset;
border-width: 1px
}
@@ -135,41 +147,59 @@ map {
h1 {
display: block;
font-size: 2em;
- margin: .67__qem 0 .67em 0;
+ -webkit-margin-before: 0.67__qem;
+ -webkit-margin-after: 0.67em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
font-weight: bold
}
h2 {
display: block;
font-size: 1.5em;
- margin: .83__qem 0 .83em 0;
+ -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;
- margin: 1__qem 0 1em 0;
+ -webkit-margin-before: 1__qem;
+ -webkit-margin-after: 1em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
font-weight: bold
}
h4 {
display: block;
- margin: 1.33__qem 0 1.33em 0;
+ -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;
- margin: 1.67__qem 0 1.67em 0;
+ -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;
- margin: 2.33__qem 0 2.33em 0;
+ -webkit-margin-before: 2.33__qem;
+ -webkit-margin-after: 2.33em;
+ -webkit-margin-start: 0;
+ -webkit-margin-end: 0;
font-weight: bold
}
@@ -293,7 +323,7 @@ ol ul, ul ol, ul ul, ol ol {
form {
display: block;
- margin-top: 0__qem
+ margin-top: 0__qem;
}
label {
@@ -403,6 +433,14 @@ input::-webkit-input-speech-button {
display: inline-block;
}
+keygen, select {
+ -webkit-border-radius: 5px;
+}
+
+keygen::-webkit-keygen-select {
+ margin: 0px;
+}
+
textarea {
-webkit-appearance: textarea;
background-color: white;
@@ -505,12 +543,11 @@ input[type="radio"] {
-webkit-box-sizing: border-box;
}
-keygen, select {
+select {
-webkit-appearance: menulist;
-webkit-box-sizing: border-box;
-webkit-box-align: center;
border: 1px solid;
- -webkit-border-radius: 5px;
white-space: pre;
-webkit-rtl-ordering: logical;
color: black;
@@ -557,6 +594,7 @@ output {
position: absolute;
opacity: 0.9;
line-height: 0;
+ -webkit-text-security: none;
-webkit-transition: opacity 05.5s ease;
}
@@ -793,7 +831,7 @@ rt {
ruby > rt {
display: block;
- font-size: 60%; /* make slightly larger than 50% for better readability */
+ font-size: 50%;
text-align: center;
}
diff --git a/Source/WebCore/css/mediaControls.css b/Source/WebCore/css/mediaControls.css
index 6a0f14b..88144b4 100644
--- a/Source/WebCore/css/mediaControls.css
+++ b/Source/WebCore/css/mediaControls.css
@@ -52,6 +52,9 @@ audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-bu
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 {
@@ -59,6 +62,9 @@ audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-bu
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 {
@@ -86,6 +92,10 @@ audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline {
-webkit-box-flex: 1;
height: 16px;
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 {
@@ -94,6 +104,10 @@ audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-cont
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 {
@@ -101,6 +115,9 @@ audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-se
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 {
@@ -108,6 +125,9 @@ audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls
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 {
@@ -115,14 +135,23 @@ audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-f
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 {
@@ -130,9 +159,15 @@ audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-medi
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;
}
diff --git a/Source/WebCore/css/mediaControlsChromium.css b/Source/WebCore/css/mediaControlsChromium.css
index 61cbb0d..b8adc2c 100644
--- a/Source/WebCore/css/mediaControlsChromium.css
+++ b/Source/WebCore/css/mediaControlsChromium.css
@@ -153,11 +153,12 @@ audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-contr
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: 16px;
+ height: 18px;
border-color: rgba(255, 255, 255, 0.2);
border-style: solid;
diff --git a/Source/WebCore/css/mediaControlsQt.css b/Source/WebCore/css/mediaControlsQt.css
index 871a5b8..9ca3313 100644
--- a/Source/WebCore/css/mediaControlsQt.css
+++ b/Source/WebCore/css/mediaControlsQt.css
@@ -213,7 +213,12 @@ audio::-webkit-media-controls-fullscreen-button {
}
video::-webkit-media-controls-fullscreen-button {
- display: none;
+ top: 0px;
+ right: 0px;
+ width: 12px;
+ height: 12px;
+ padding: 6px;
+ margin: 5px 5px 5px 3px;
}
audio::-webkit-media-controls-rewind-button {
@@ -240,3 +245,11 @@ 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/themeChromiumLinux.css b/Source/WebCore/css/themeChromiumLinux.css
index f8210c3..bd7f961 100644
--- a/Source/WebCore/css/themeChromiumLinux.css
+++ b/Source/WebCore/css/themeChromiumLinux.css
@@ -34,3 +34,8 @@ select {
background-color: #dddddd;
border: 0px;
}
+
+select[size="0"] option,
+select[size="1"] option {
+ background-color: #f7f7f7;
+}
diff --git a/Source/WebCore/css/themeWin.css b/Source/WebCore/css/themeWin.css
index f2ad669..0838b11 100644
--- a/Source/WebCore/css/themeWin.css
+++ b/Source/WebCore/css/themeWin.css
@@ -33,8 +33,19 @@
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="password"] {
+input[type="time"],
+input[type="url"],
+input[type="week"] {
padding:1px 0;
}
@@ -59,14 +70,25 @@ input[type="radio"] {
*/
textarea:disabled,
input:not([type]):disabled,
-input[type="text"]: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="search"]: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;
+ margin-right: 3px;
}
input[type="search"]::-webkit-search-results-decoration {
@@ -77,6 +99,10 @@ 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;
}