diff options
Diffstat (limited to 'Source/WebCore/css')
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; } |