diff options
Diffstat (limited to 'WebCore/css')
32 files changed, 1221 insertions, 737 deletions
diff --git a/WebCore/css/CSSComputedStyleDeclaration.cpp b/WebCore/css/CSSComputedStyleDeclaration.cpp index 7ed9385..d7f585f 100644 --- a/WebCore/css/CSSComputedStyleDeclaration.cpp +++ b/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -31,6 +31,7 @@ #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSReflectValue.h" +#include "CSSSelector.h" #include "CSSTimingFunctionValue.h" #include "CSSValueList.h" #include "Document.h" @@ -150,6 +151,7 @@ static const int computedProperties[] = { CSSPropertyWebkitAnimationDelay, CSSPropertyWebkitAnimationDirection, CSSPropertyWebkitAnimationDuration, + CSSPropertyWebkitAnimationFillMode, CSSPropertyWebkitAnimationIterationCount, CSSPropertyWebkitAnimationName, CSSPropertyWebkitAnimationPlayState, @@ -299,28 +301,28 @@ static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image) // Create the slices. RefPtr<CSSPrimitiveValue> top; - if (image.m_slices.top().isPercent()) - top = CSSPrimitiveValue::create(image.m_slices.top().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + if (image.slices().top().isPercent()) + top = CSSPrimitiveValue::create(image.slices().top().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - top = CSSPrimitiveValue::create(image.m_slices.top().value(), CSSPrimitiveValue::CSS_NUMBER); + top = CSSPrimitiveValue::create(image.slices().top().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<CSSPrimitiveValue> right; - if (image.m_slices.right().isPercent()) - right = CSSPrimitiveValue::create(image.m_slices.right().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + if (image.slices().right().isPercent()) + right = CSSPrimitiveValue::create(image.slices().right().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - right = CSSPrimitiveValue::create(image.m_slices.right().value(), CSSPrimitiveValue::CSS_NUMBER); + right = CSSPrimitiveValue::create(image.slices().right().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<CSSPrimitiveValue> bottom; - if (image.m_slices.bottom().isPercent()) - bottom = CSSPrimitiveValue::create(image.m_slices.bottom().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + if (image.slices().bottom().isPercent()) + bottom = CSSPrimitiveValue::create(image.slices().bottom().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - bottom = CSSPrimitiveValue::create(image.m_slices.bottom().value(), CSSPrimitiveValue::CSS_NUMBER); + bottom = CSSPrimitiveValue::create(image.slices().bottom().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<CSSPrimitiveValue> left; - if (image.m_slices.left().isPercent()) - left = CSSPrimitiveValue::create(image.m_slices.left().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + if (image.slices().left().isPercent()) + left = CSSPrimitiveValue::create(image.slices().left().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - left = CSSPrimitiveValue::create(image.m_slices.left().value(), CSSPrimitiveValue::CSS_NUMBER); + left = CSSPrimitiveValue::create(image.slices().left().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<Rect> rect = Rect::create(); rect->setTop(top); @@ -328,7 +330,7 @@ static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image) rect->setBottom(bottom); rect->setLeft(left); - return CSSBorderImageValue::create(imageValue, rect, valueForRepeatRule(image.m_horizontalRule), valueForRepeatRule(image.m_verticalRule)); + return CSSBorderImageValue::create(imageValue, rect, valueForRepeatRule(image.horizontalRule()), valueForRepeatRule(image.verticalRule())); } static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection) @@ -507,9 +509,13 @@ static PassRefPtr<CSSValue> getTimingFunctionValue(const AnimationList* animList return list.release(); } -CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n) +CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n, bool allowVisitedStyle, const String& pseudoElementName) : m_node(n) + , m_allowVisitedStyle(allowVisitedStyle) { + unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0; + m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoType( + AtomicString(pseudoElementName.substring(nameWithoutColonsStart)))); } CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration() @@ -552,7 +558,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getFontSizeCSSValuePreferringK node->document()->updateLayoutIgnorePendingStylesheets(); - RefPtr<RenderStyle> style = node->computedStyle(); + RefPtr<RenderStyle> style = node->computedStyle(m_pseudoElementSpecifier); if (!style) return 0; @@ -570,13 +576,13 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadow(const ShadowDat CSSPropertyID propertyID = static_cast<CSSPropertyID>(id); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - for (const ShadowData* s = shadow; s; s = s->next) { - RefPtr<CSSPrimitiveValue> x = CSSPrimitiveValue::create(s->x, CSSPrimitiveValue::CSS_PX); - RefPtr<CSSPrimitiveValue> y = CSSPrimitiveValue::create(s->y, CSSPrimitiveValue::CSS_PX); - RefPtr<CSSPrimitiveValue> blur = CSSPrimitiveValue::create(s->blur, CSSPrimitiveValue::CSS_PX); - RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? 0 : CSSPrimitiveValue::create(s->spread, CSSPrimitiveValue::CSS_PX); - RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || s->style == Normal ? 0 : CSSPrimitiveValue::createIdentifier(CSSValueInset); - RefPtr<CSSPrimitiveValue> color = CSSPrimitiveValue::createColor(s->color.rgb()); + for (const ShadowData* s = shadow; s; s = s->next()) { + RefPtr<CSSPrimitiveValue> x = CSSPrimitiveValue::create(s->x(), CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> y = CSSPrimitiveValue::create(s->y(), CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> blur = CSSPrimitiveValue::create(s->blur(), CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? 0 : CSSPrimitiveValue::create(s->spread(), CSSPrimitiveValue::CSS_PX); + RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || s->style() == Normal ? 0 : CSSPrimitiveValue::createIdentifier(CSSValueInset); + RefPtr<CSSPrimitiveValue> color = CSSPrimitiveValue::createColor(s->color().rgb()); list->prepend(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release())); } return list.release(); @@ -637,9 +643,9 @@ static PassRefPtr<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepea // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand. if (xRepeat == yRepeat) return CSSPrimitiveValue::create(xRepeat); - if (xRepeat == CSSValueRepeat && yRepeat == CSSValueNoRepeat) + if (xRepeat == RepeatFill && yRepeat == NoRepeatFill) return CSSPrimitiveValue::createIdentifier(CSSValueRepeatX); - if (xRepeat == CSSValueNoRepeat && yRepeat == CSSValueRepeat) + if (xRepeat == NoRepeatFill && yRepeat == RepeatFill) return CSSPrimitiveValue::createIdentifier(CSSValueRepeatY); RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); @@ -670,10 +676,15 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper RenderObject* renderer = node->renderer(); RefPtr<RenderStyle> style; - if (renderer && hasCompositedLayer(renderer) && AnimationController::supportsAcceleratedAnimationOfProperty(static_cast<CSSPropertyID>(propertyID))) + if (renderer && hasCompositedLayer(renderer) && AnimationController::supportsAcceleratedAnimationOfProperty(static_cast<CSSPropertyID>(propertyID))) { style = renderer->animation()->getAnimatedStyleForRenderer(renderer); - else - style = node->computedStyle(); + if (m_pseudoElementSpecifier) { + // FIXME: This cached pseudo style will only exist if the animation has been run at least once. + style = style->getCachedPseudoStyle(m_pseudoElementSpecifier); + } + } else + style = node->computedStyle(m_pseudoElementSpecifier); + if (!style) return 0; @@ -686,7 +697,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper break; case CSSPropertyBackgroundColor: - return CSSPrimitiveValue::createColor(style->backgroundColor().rgb()); + return CSSPrimitiveValue::createColor(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor).rgb() : style->backgroundColor().rgb()); case CSSPropertyBackgroundImage: if (style->backgroundImage()) return style->backgroundImage()->cssValue(); @@ -743,13 +754,13 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitBorderVerticalSpacing: return CSSPrimitiveValue::create(style->verticalBorderSpacing(), CSSPrimitiveValue::CSS_PX); case CSSPropertyBorderTopColor: - return currentColorOrValidColor(style.get(), style->borderTopColor()); + return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderTopColor).rgb()) : currentColorOrValidColor(style.get(), style->borderTopColor()); case CSSPropertyBorderRightColor: - return currentColorOrValidColor(style.get(), style->borderRightColor()); + return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderRightColor).rgb()) : currentColorOrValidColor(style.get(), style->borderRightColor()); case CSSPropertyBorderBottomColor: - return currentColorOrValidColor(style.get(), style->borderBottomColor()); + return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderBottomColor).rgb()) : currentColorOrValidColor(style.get(), style->borderBottomColor()); case CSSPropertyBorderLeftColor: - return currentColorOrValidColor(style.get(), style->borderLeftColor()); + return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderLeftColor).rgb()) : currentColorOrValidColor(style.get(), style->borderLeftColor()); case CSSPropertyBorderTopStyle: return CSSPrimitiveValue::create(style->borderTopStyle()); case CSSPropertyBorderRightStyle: @@ -799,7 +810,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyClear: return CSSPrimitiveValue::create(style->clear()); case CSSPropertyColor: - return CSSPrimitiveValue::createColor(style->color().rgb()); + return CSSPrimitiveValue::createColor(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor).rgb() : style->color().rgb()); case CSSPropertyWebkitColumnCount: if (style->hasAutoColumnCount()) return CSSPrimitiveValue::createIdentifier(CSSValueAuto); @@ -809,7 +820,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper return CSSPrimitiveValue::createIdentifier(CSSValueNormal); return CSSPrimitiveValue::create(style->columnGap(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitColumnRuleColor: - return currentColorOrValidColor(style.get(), style->columnRuleColor()); + return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->columnRuleColor()); case CSSPropertyWebkitColumnRuleStyle: return CSSPrimitiveValue::create(style->columnRuleStyle()); case CSSPropertyWebkitColumnRuleWidth: @@ -830,7 +841,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper if (cursors && cursors->size() > 0) { list = CSSValueList::createCommaSeparated(); for (unsigned i = 0; i < cursors->size(); ++i) - list->append(CSSPrimitiveValue::create((*cursors)[i].cursorImage->url(), CSSPrimitiveValue::CSS_URI)); + list->append(CSSPrimitiveValue::create((*cursors)[i].image()->url(), CSSPrimitiveValue::CSS_URI)); } RefPtr<CSSValue> value = CSSPrimitiveValue::create(style->cursor()); if (list) { @@ -972,9 +983,14 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper return style->maskImage()->cssValue(); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyWebkitMaskSize: { + EFillSizeType size = style->maskSizeType(); + if (size == Contain) + return CSSPrimitiveValue::createIdentifier(CSSValueContain); + if (size == Cover) + return CSSPrimitiveValue::createIdentifier(CSSValueCover); RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - list->append(CSSPrimitiveValue::create(style->maskSize().width())); - list->append(CSSPrimitiveValue::create(style->maskSize().height())); + list->append(CSSPrimitiveValue::create(style->maskSizeLength().width())); + list->append(CSSPrimitiveValue::create(style->maskSizeLength().height())); return list.release(); } case CSSPropertyWebkitMaskRepeat: @@ -1023,7 +1039,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyOrphans: return CSSPrimitiveValue::create(style->orphans(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyOutlineColor: - return currentColorOrValidColor(style.get(), style->outlineColor()); + return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->outlineColor()); case CSSPropertyOutlineStyle: if (style->outlineStyleIsAuto()) return CSSPrimitiveValue::createIdentifier(CSSValueAuto); @@ -1241,6 +1257,30 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper } case CSSPropertyWebkitAnimationDuration: return getDurationValue(style->animations()); + case CSSPropertyWebkitAnimationFillMode: { + RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + const AnimationList* t = style->animations(); + if (t) { + for (size_t i = 0; i < t->size(); ++i) { + switch (t->animation(i)->fillMode()) { + case AnimationFillModeNone: + list->append(CSSPrimitiveValue::createIdentifier(CSSValueNone)); + break; + case AnimationFillModeForwards: + list->append(CSSPrimitiveValue::createIdentifier(CSSValueForwards)); + break; + case AnimationFillModeBackwards: + list->append(CSSPrimitiveValue::createIdentifier(CSSValueBackwards)); + break; + case AnimationFillModeBoth: + list->append(CSSPrimitiveValue::createIdentifier(CSSValueBoth)); + break; + } + } + } else + list->append(CSSPrimitiveValue::createIdentifier(CSSValueNone)); + return list.release(); + } case CSSPropertyWebkitAnimationIterationCount: { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); const AnimationList* t = style->animations(); @@ -1512,7 +1552,7 @@ unsigned CSSComputedStyleDeclaration::length() const if (!node) return 0; - RenderStyle* style = node->computedStyle(); + RenderStyle* style = node->computedStyle(m_pseudoElementSpecifier); if (!style) return 0; @@ -1531,7 +1571,7 @@ bool CSSComputedStyleDeclaration::cssPropertyMatches(const CSSProperty* property { if (property->id() == CSSPropertyFontSize && property->value()->isPrimitiveValue() && m_node) { m_node->document()->updateLayoutIgnorePendingStylesheets(); - RenderStyle* style = m_node->computedStyle(); + RenderStyle* style = m_node->computedStyle(m_pseudoElementSpecifier); if (style && style->fontDescription().keywordSize()) { int sizeValue = cssIdentifierForFontSizeKeyword(style->fontDescription().keywordSize()); CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(property->value()); diff --git a/WebCore/css/CSSComputedStyleDeclaration.h b/WebCore/css/CSSComputedStyleDeclaration.h index 842a995..eb93bad 100644 --- a/WebCore/css/CSSComputedStyleDeclaration.h +++ b/WebCore/css/CSSComputedStyleDeclaration.h @@ -23,6 +23,7 @@ #include "CSSStyleDeclaration.h" #include "Node.h" +#include "RenderStyleConstants.h" namespace WebCore { @@ -33,7 +34,7 @@ enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true }; class CSSComputedStyleDeclaration : public CSSStyleDeclaration { public: - friend PassRefPtr<CSSComputedStyleDeclaration> computedStyle(PassRefPtr<Node>); + friend PassRefPtr<CSSComputedStyleDeclaration> computedStyle(PassRefPtr<Node>, bool allowVisitedStyle, const String& pseudoElementName); virtual ~CSSComputedStyleDeclaration(); virtual String cssText() const; @@ -60,7 +61,7 @@ protected: virtual bool cssPropertyMatches(const CSSProperty*) const; private: - CSSComputedStyleDeclaration(PassRefPtr<Node>); + CSSComputedStyleDeclaration(PassRefPtr<Node>, bool allowVisitedStyle, const String&); virtual void setCssText(const String&, ExceptionCode&); @@ -70,11 +71,13 @@ private: PassRefPtr<CSSValue> valueForShadow(const ShadowData*, int) const; RefPtr<Node> m_node; + PseudoId m_pseudoElementSpecifier; + bool m_allowVisitedStyle; }; -inline PassRefPtr<CSSComputedStyleDeclaration> computedStyle(PassRefPtr<Node> node) +inline PassRefPtr<CSSComputedStyleDeclaration> computedStyle(PassRefPtr<Node> node, bool allowVisitedStyle = false, const String& pseudoElementName = String()) { - return adoptRef(new CSSComputedStyleDeclaration(node)); + return adoptRef(new CSSComputedStyleDeclaration(node, allowVisitedStyle, pseudoElementName)); } } // namespace WebCore diff --git a/WebCore/css/CSSFontFaceSource.cpp b/WebCore/css/CSSFontFaceSource.cpp index 1354e68..921b149 100644 --- a/WebCore/css/CSSFontFaceSource.cpp +++ b/WebCore/css/CSSFontFaceSource.cpp @@ -36,7 +36,9 @@ #include "SimpleFontData.h" #if ENABLE(SVG_FONTS) +#if !PLATFORM(WX) #include "FontCustomPlatformData.h" +#endif #include "HTMLNames.h" #include "SVGFontData.h" #include "SVGFontElement.h" diff --git a/WebCore/css/CSSGrammar.y b/WebCore/css/CSSGrammar.y index 9d5eb6e..ec0c141 100644 --- a/WebCore/css/CSSGrammar.y +++ b/WebCore/css/CSSGrammar.y @@ -246,6 +246,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <integer> match %type <integer> unary_operator +%type <integer> maybe_unary_operator %type <character> operator %type <valueList> expr @@ -767,6 +768,11 @@ combinator: | '>' maybe_space { $$ = CSSSelector::Child; } ; +maybe_unary_operator: + unary_operator { $$ = $1; } + | { $$ = 1; } + ; + unary_operator: '-' { $$ = -1; } | '+' { $$ = 1; } @@ -786,6 +792,7 @@ selector_list: deleteAllValues(*$$); $$->shrink(0); $$->append(p->sinkFloatingSelector($1)); + p->updateLastSelectorLine(); } } | selector_list ',' maybe_space selector %prec UNIMPORTANT_TOK { @@ -793,6 +800,7 @@ selector_list: CSSParser* p = static_cast<CSSParser*>(parser); $$ = $1; $$->append(p->sinkFloatingSelector($4)); + p->updateLastSelectorLine(); } else $$ = 0; } @@ -1087,6 +1095,10 @@ pseudo: CSSParser* p = static_cast<CSSParser*>(parser); if (Document* doc = p->document()) doc->setUsesBeforeAfterRules(true); + } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) { + CSSParser* p = static_cast<CSSParser*>(parser); + if (Document* doc = p->document()) + doc->setUsesLinkRules(true); } } | ':' ':' IDENT { @@ -1127,11 +1139,11 @@ pseudo: } } // used by :nth-* - | ':' FUNCTION maybe_space INTEGER maybe_space ')' { + | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' { CSSParser *p = static_cast<CSSParser*>(parser); $$ = p->createFloatingSelector(); $$->m_match = CSSSelector::PseudoClass; - $$->setArgument(String::number($4)); + $$->setArgument(String::number($4 * $5)); $$->m_value = $2; CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) @@ -1165,7 +1177,7 @@ pseudo: } // used by :not | ':' NOTFUNCTION maybe_space simple_selector maybe_space ')' { - if (!$4 || $4->simpleSelector() || $4->tagHistory()) + if (!$4 || !$4->isSimple()) $$ = 0; else { CSSParser* p = static_cast<CSSParser*>(parser); diff --git a/WebCore/css/CSSImportRule.cpp b/WebCore/css/CSSImportRule.cpp index 95ed032..b4d7e69 100644 --- a/WebCore/css/CSSImportRule.cpp +++ b/WebCore/css/CSSImportRule.cpp @@ -88,7 +88,10 @@ void CSSImportRule::setCSSStyleSheet(const String& href, const KURL& baseURL, co // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>. DEFINE_STATIC_LOCAL(const String, slashKHTMLFixesDotCss, ("/KHTMLFixes.css")); DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, ("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n")); - if (baseURL.string().endsWith(slashKHTMLFixesDotCss) && sheetText == mediaWikiKHTMLFixesStyleSheet) { + // There are two variants of KHTMLFixes.css. One is equal to mediaWikiKHTMLFixesStyleSheet, + // while the other lacks the second trailing newline. + if (baseURL.string().endsWith(slashKHTMLFixesDotCss) && !sheetText.isNull() && mediaWikiKHTMLFixesStyleSheet.startsWith(sheetText) + && sheetText.length() >= mediaWikiKHTMLFixesStyleSheet.length() - 1) { ASSERT(m_styleSheet->length() == 1); ExceptionCode ec; m_styleSheet->deleteRule(0, ec); diff --git a/WebCore/css/CSSParser.cpp b/WebCore/css/CSSParser.cpp index f5b2cbc..466e741 100644 --- a/WebCore/css/CSSParser.cpp +++ b/WebCore/css/CSSParser.cpp @@ -25,7 +25,6 @@ #include "config.h" #include "CSSParser.h" -#include "CString.h" #include "CSSTimingFunctionValue.h" #include "CSSBorderImageValue.h" #include "CSSCanvasValue.h" @@ -66,6 +65,7 @@ #include "Pair.h" #include "Rect.h" #include "ShadowValue.h" +#include "StringBuffer.h" #include "WebKitCSSKeyframeRule.h" #include "WebKitCSSKeyframesRule.h" #include "WebKitCSSTransformValue.h" @@ -147,6 +147,8 @@ CSSParser::CSSParser(bool strictParsing) , m_defaultNamespace(starAtom) , m_data(0) , yy_start(1) + , m_line(0) + , m_lastSelectorLine(0) , m_allowImportRules(true) , m_allowVariablesRules(true) , m_allowNamespaceDeclarations(true) @@ -421,7 +423,7 @@ bool CSSParser::parseMediaQuery(MediaList* queries, const String& string) void CSSParser::addProperty(int propId, PassRefPtr<CSSValue> value, bool important) { - auto_ptr<CSSProperty> prop(new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand)); + OwnPtr<CSSProperty> prop(new CSSProperty(propId, value, important, m_currentShorthand, m_implicitShorthand)); if (m_numParsedProperties >= m_maxParsedProperties) { m_maxParsedProperties += 32; if (m_maxParsedProperties > UINT_MAX / sizeof(CSSProperty*)) @@ -993,7 +995,7 @@ bool CSSParser::parseValue(int propId, bool important) if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick) validPrimitive = true; else - validPrimitive = validUnit(value, FLength, m_strict); + validPrimitive = validUnit(value, FLength | FNonNeg, m_strict); break; case CSSPropertyLetterSpacing: // normal | <length> | inherit @@ -1445,6 +1447,7 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyWebkitAnimationDelay: case CSSPropertyWebkitAnimationDirection: case CSSPropertyWebkitAnimationDuration: + case CSSPropertyWebkitAnimationFillMode: case CSSPropertyWebkitAnimationName: case CSSPropertyWebkitAnimationPlayState: case CSSPropertyWebkitAnimationIterationCount: @@ -1950,7 +1953,8 @@ bool CSSParser::parseAnimationShorthand(bool important) CSSPropertyWebkitAnimationTimingFunction, CSSPropertyWebkitAnimationDelay, CSSPropertyWebkitAnimationIterationCount, - CSSPropertyWebkitAnimationDirection }; + CSSPropertyWebkitAnimationDirection, + CSSPropertyWebkitAnimationFillMode }; const int numProperties = sizeof(properties) / sizeof(properties[0]); ShorthandScope scope(this, CSSPropertyWebkitAnimation); @@ -2631,6 +2635,14 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDuration() return 0; } +PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode() +{ + CSSParserValue* value = m_valueList->current(); + if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth) + return CSSPrimitiveValue::createIdentifier(value->id); + return 0; +} + PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount() { CSSParserValue* value = m_valueList->current(); @@ -2773,6 +2785,11 @@ bool CSSParser::parseAnimationProperty(int propId, RefPtr<CSSValue>& result) if (currValue) m_valueList->next(); break; + case CSSPropertyWebkitAnimationFillMode: + currValue = parseAnimationFillMode(); + if (currValue) + m_valueList->next(); + break; case CSSPropertyWebkitAnimationIterationCount: currValue = parseAnimationIterationCount(); if (currValue) @@ -3551,19 +3568,66 @@ bool CSSParser::parseFontFaceUnicodeRange() return true; } +static inline bool isCSSWhitespace(UChar c) +{ + return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f'; +} + +static inline bool parseInt(const UChar*& string, const UChar* end, UChar terminator, int& value) +{ + const UChar* current = string; + int localValue = 0; + bool negative = false; + while (current != end && isCSSWhitespace(*current)) + current++; + if (current != end && *current == '-') { + negative = true; + current++; + } + if (current == end || !isASCIIDigit(*current)) + return false; + while (current != end && isASCIIDigit(*current)) + localValue = localValue * 10 + *current++ - '0'; + while (current != end && isCSSWhitespace(*current)) + current++; + if (current == end || *current++ != terminator) + return false; + // Clamp negative values at zero. + value = negative ? 0 : localValue; + string = current; + return true; +} + bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) { if (!strict && Color::parseHexColor(name, rgb)) return true; - // try a little harder + // Try rgb() syntax. + if (name.startsWith("rgb(")) { + const UChar* current = name.characters() + 4; + const UChar* end = name.characters() + name.length(); + int red; + int green; + int blue; + if (!parseInt(current, end, ',', red)) + return false; + if (!parseInt(current, end, ',', green)) + return false; + if (!parseInt(current, end, ')', blue)) + return false; + if (current != end) + return false; + rgb = makeRGB(red, green, blue); + return true; + } + // Try named colors. Color tc; tc.setNamedColor(name); if (tc.isValid()) { rgb = tc.rgb(); return true; } - return false; } @@ -3596,7 +3660,9 @@ bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, boo v = args->next(); if (!validUnit(v, FNumber, true)) return false; - colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * 255); + // Convert the floating pointer number of alpha to an integer in the range [0, 256), + // with an equal distribution across all 256 values. + colorArray[3] = static_cast<int>(max(0.0, min(1.0, v->fValue)) * nextafter(256.0, 0.0)); } return true; } @@ -4688,7 +4754,7 @@ int CSSParser::lex(void* yylvalWithoutType) { YYSTYPE* yylval = static_cast<YYSTYPE*>(yylvalWithoutType); int length; - + lex(); UChar* t = text(&length); @@ -4762,11 +4828,6 @@ int CSSParser::lex(void* yylvalWithoutType) return token(); } -static inline bool isCSSWhitespace(UChar c) -{ - return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f'; -} - void CSSParser::recheckAtKeyword(const UChar* str, int len) { String ruleName(str, len); @@ -4918,6 +4979,14 @@ UChar* CSSParser::text(int *length) return start; } +void CSSParser::countLines() +{ + for (UChar* current = yytext; current < yytext + yyleng; ++current) { + if (*current == '\n') + ++m_line; + } +} + CSSSelector* CSSParser::createFloatingSelector() { CSSSelector* selector = fastNew<CSSSelector>(); @@ -5087,7 +5156,7 @@ CSSRule* CSSParser::createStyleRule(Vector<CSSSelector*>* selectors) m_allowImportRules = m_allowNamespaceDeclarations = m_allowVariablesRules = false; CSSStyleRule* result = 0; if (selectors) { - RefPtr<CSSStyleRule> rule = CSSStyleRule::create(m_styleSheet); + RefPtr<CSSStyleRule> rule = CSSStyleRule::create(m_styleSheet, m_lastSelectorLine); rule->adoptSelectorVector(*selectors); if (m_hasFontFaceOnlyValues) deleteFontFaceOnlyValues(); @@ -5398,6 +5467,120 @@ int cssValueKeywordID(const CSSParserString& string) return hashTableEntry ? hashTableEntry->id : 0; } +// "ident" from the CSS tokenizer, minus backslash-escape sequences +static bool isCSSTokenizerIdentifier(const String& string) +{ + const UChar* p = string.characters(); + const UChar* end = p + string.length(); + + // -? + if (p != end && p[0] == '-') + ++p; + + // {nmstart} + if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0]))) + return false; + ++p; + + // {nmchar}* + for (; p != end; ++p) { + if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0]))) + return false; + } + + return true; +} + +// "url" from the CSS tokenizer, minus backslash-escape sequences +static bool isCSSTokenizerURL(const String& string) +{ + const UChar* p = string.characters(); + const UChar* end = p + string.length(); + + for (; p != end; ++p) { + UChar c = p[0]; + switch (c) { + case '!': + case '#': + case '$': + case '%': + case '&': + break; + default: + if (c < '*') + return false; + if (c <= '~') + break; + if (c < 128) + return false; + } + } + + return true; +} + +// We use single quotes for now because markup.cpp uses double quotes. +String quoteCSSString(const String& string) +{ + // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one. + // Please see below for the actual logic. + unsigned quotedStringSize = 2; // Two quotes surrounding the entire string. + bool afterEscape = false; + for (unsigned i = 0; i < string.length(); ++i) { + UChar ch = string[i]; + if (ch == '\\' || ch == '\'') { + quotedStringSize += 2; + afterEscape = false; + } else if (ch < 0x20 || ch == 0x7F) { + quotedStringSize += 2 + (ch >= 0x10); + afterEscape = true; + } else { + quotedStringSize += 1 + (afterEscape && (isASCIIHexDigit(ch) || ch == ' ')); + afterEscape = false; + } + } + + StringBuffer buffer(quotedStringSize); + unsigned index = 0; + buffer[index++] = '\''; + afterEscape = false; + for (unsigned i = 0; i < string.length(); ++i) { + UChar ch = string[i]; + if (ch == '\\' || ch == '\'') { + buffer[index++] = '\\'; + buffer[index++] = ch; + afterEscape = false; + } else if (ch < 0x20 || ch == 0x7F) { // Control characters. + static const char hexDigits[17] = "0123456789abcdef"; + buffer[index++] = '\\'; + if (ch >= 0x10) + buffer[index++] = hexDigits[ch >> 4]; + buffer[index++] = hexDigits[ch & 0xF]; + afterEscape = true; + } else { + // Space character may be required to separate backslash-escape sequence and normal characters. + if (afterEscape && (isASCIIHexDigit(ch) || ch == ' ')) + buffer[index++] = ' '; + buffer[index++] = ch; + afterEscape = false; + } + } + buffer[index++] = '\''; + + ASSERT(quotedStringSize == index); + return String::adopt(buffer); +} + +String quoteCSSStringIfNeeded(const String& string) +{ + return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string); +} + +String quoteCSSURLIfNeeded(const String& string) +{ + return isCSSTokenizerURL(string) ? string : quoteCSSString(string); +} + #define YY_DECL int CSSParser::lex() #define yyconst const typedef int yy_state_type; diff --git a/WebCore/css/CSSParser.h b/WebCore/css/CSSParser.h index 3922a2a..ca8c66a 100644 --- a/WebCore/css/CSSParser.h +++ b/WebCore/css/CSSParser.h @@ -95,6 +95,7 @@ namespace WebCore { PassRefPtr<CSSValue> parseAnimationDelay(); PassRefPtr<CSSValue> parseAnimationDirection(); PassRefPtr<CSSValue> parseAnimationDuration(); + PassRefPtr<CSSValue> parseAnimationFillMode(); PassRefPtr<CSSValue> parseAnimationIterationCount(); PassRefPtr<CSSValue> parseAnimationName(); PassRefPtr<CSSValue> parseAnimationPlayState(); @@ -194,9 +195,11 @@ namespace WebCore { bool checkForVariables(CSSParserValueList*); void addUnresolvedProperty(int propId, bool important); void invalidBlockHit(); - + Vector<CSSSelector*>* reusableSelectorVector() { return &m_reusableSelectorVector; } + void updateLastSelectorLine() { m_lastSelectorLine = m_line; } + bool m_strict; bool m_important; int m_id; @@ -226,6 +229,7 @@ namespace WebCore { int lex(void* yylval); int token() { return yyTok; } UChar* text(int* length); + void countLines(); int lex(); private: @@ -252,6 +256,8 @@ namespace WebCore { int yyleng; int yyTok; int yy_start; + int m_line; + int m_lastSelectorLine; bool m_allowImportRules; bool m_allowVariablesRules; @@ -314,6 +320,10 @@ namespace WebCore { CSSParser* m_parser; }; + String quoteCSSString(const String&); + String quoteCSSStringIfNeeded(const String&); + String quoteCSSURLIfNeeded(const String&); + } // namespace WebCore #endif // CSSParser_h diff --git a/WebCore/css/CSSPrimitiveValue.cpp b/WebCore/css/CSSPrimitiveValue.cpp index 012aa56..210d6f5 100644 --- a/WebCore/css/CSSPrimitiveValue.cpp +++ b/WebCore/css/CSSPrimitiveValue.cpp @@ -22,6 +22,7 @@ #include "CSSPrimitiveValue.h" #include "CSSHelper.h" +#include "CSSParser.h" #include "CSSPropertyNames.h" #include "CSSStyleSheet.h" #include "CSSValueKeywords.h" @@ -116,83 +117,30 @@ PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(const String& value, Uni return adoptRef(new CSSPrimitiveValue(value, type)); } -static const char* valueOrPropertyName(int valueOrPropertyID) +static const AtomicString& valueOrPropertyName(int valueOrPropertyID) { - if (const char* valueName = getValueName(valueOrPropertyID)) - return valueName; - return getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID)); -} - -// "ident" from the CSS tokenizer, minus backslash-escape sequences -static bool isCSSTokenizerIdentifier(const String& string) -{ - const UChar* p = string.characters(); - const UChar* end = p + string.length(); + ASSERT_ARG(valueOrPropertyID, valueOrPropertyID >= 0); + ASSERT_ARG(valueOrPropertyID, valueOrPropertyID < numCSSValueKeywords || (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties)); - // -? - if (p != end && p[0] == '-') - ++p; + if (valueOrPropertyID < 0) + return nullAtom; - // {nmstart} - if (p == end || !(p[0] == '_' || p[0] >= 128 || isASCIIAlpha(p[0]))) - return false; - ++p; - - // {nmchar}* - for (; p != end; ++p) { - if (!(p[0] == '_' || p[0] == '-' || p[0] >= 128 || isASCIIAlphanumeric(p[0]))) - return false; + if (valueOrPropertyID < numCSSValueKeywords) { + static AtomicString* cssValueKeywordStrings[numCSSValueKeywords]; + if (!cssValueKeywordStrings[valueOrPropertyID]) + cssValueKeywordStrings[valueOrPropertyID] = new AtomicString(getValueName(valueOrPropertyID)); + return *cssValueKeywordStrings[valueOrPropertyID]; } - return true; -} - -// "url" from the CSS tokenizer, minus backslash-escape sequences -static bool isCSSTokenizerURL(const String& string) -{ - const UChar* p = string.characters(); - const UChar* end = p + string.length(); - - for (; p != end; ++p) { - UChar c = p[0]; - switch (c) { - case '!': - case '#': - case '$': - case '%': - case '&': - break; - default: - if (c < '*') - return false; - if (c <= '~') - break; - if (c < 128) - return false; - } + if (valueOrPropertyID >= firstCSSProperty && valueOrPropertyID < firstCSSProperty + numCSSProperties) { + static AtomicString* cssPropertyStrings[numCSSProperties]; + int propertyIndex = valueOrPropertyID - firstCSSProperty; + if (!cssPropertyStrings[propertyIndex]) + cssPropertyStrings[propertyIndex] = new AtomicString(getPropertyName(static_cast<CSSPropertyID>(valueOrPropertyID))); + return *cssPropertyStrings[propertyIndex]; } - return true; -} - -// We use single quotes for now because markup.cpp uses double quotes. -static String quoteString(const String& string) -{ - // FIXME: Also need to escape characters like '\n'. - String s = string; - s.replace('\\', "\\\\"); - s.replace('\'', "\\'"); - return "'" + s + "'"; -} - -static String quoteStringIfNeeded(const String& string) -{ - return isCSSTokenizerIdentifier(string) ? string : quoteString(string); -} - -static String quoteURLIfNeeded(const String& string) -{ - return isCSSTokenizerURL(string) ? string : quoteString(string); + return nullAtom; } CSSPrimitiveValue::CSSPrimitiveValue() @@ -317,6 +265,7 @@ void CSSPrimitiveValue::cleanup() } m_type = 0; + m_cachedCSSText = String(); } int CSSPrimitiveValue::computeLengthInt(RenderStyle* style, RenderStyle* rootStyle) @@ -484,7 +433,6 @@ void CSSPrimitiveValue::setFloatValue(unsigned short unitType, double floatValue cleanup(); - //if(m_type > CSS_DIMENSION) throw DOMException(INVALID_ACCESS_ERR); m_value.num = floatValue; m_type = unitType; } @@ -685,6 +633,9 @@ String CSSPrimitiveValue::cssText() const { // FIXME: return the original value instead of a generated one (e.g. color // name if it was specified) - check what spec says about this + if (!m_cachedCSSText.isNull()) + return m_cachedCSSText; + String text; switch (m_type) { case CSS_UNKNOWN: @@ -752,10 +703,10 @@ String CSSPrimitiveValue::cssText() const // FIXME break; case CSS_STRING: - text = quoteStringIfNeeded(m_value.string); + text = quoteCSSStringIfNeeded(m_value.string); break; case CSS_URI: - text = "url(" + quoteURLIfNeeded(m_value.string) + ")"; + text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")"; break; case CSS_IDENT: text = valueOrPropertyName(m_value.ident); @@ -770,7 +721,8 @@ String CSSPrimitiveValue::cssText() const append(result, m_value.string); result.uncheckedAppend(')'); - return String::adopt(result); + text = String::adopt(result); + break; } case CSS_COUNTER: text = "counter("; @@ -798,7 +750,8 @@ String CSSPrimitiveValue::cssText() const append(result, rectVal->left()->cssText()); result.append(')'); - return String::adopt(result); + text = String::adopt(result); + break; } case CSS_RGBCOLOR: case CSS_PARSER_HEXCOLOR: { @@ -827,11 +780,12 @@ String CSSPrimitiveValue::cssText() const appendNumber(result, static_cast<unsigned char>(color.blue())); if (color.hasAlpha()) { append(result, commaSpace); - append(result, String::number(static_cast<float>(color.alpha()) / 256.0f)); + append(result, String::number(color.alpha() / 256.0f)); } result.append(')'); - return String::adopt(result); + text = String::adopt(result); + break; } case CSS_PAIR: text = m_value.pair->first()->cssText(); @@ -880,9 +834,10 @@ String CSSPrimitiveValue::cssText() const break; } case CSS_PARSER_IDENTIFIER: - text = quoteStringIfNeeded(m_value.string); + text = quoteCSSStringIfNeeded(m_value.string); break; } + m_cachedCSSText = text; return text; } @@ -927,7 +882,7 @@ CSSParserValue CSSPrimitiveValue::parserValue() const break; case CSS_IDENT: { value.id = m_value.ident; - String name = valueOrPropertyName(m_value.ident); + const AtomicString& name = valueOrPropertyName(m_value.ident); value.string.characters = const_cast<UChar*>(name.characters()); value.string.length = name.length(); break; diff --git a/WebCore/css/CSSPrimitiveValue.h b/WebCore/css/CSSPrimitiveValue.h index d417619..943ad04 100644 --- a/WebCore/css/CSSPrimitiveValue.h +++ b/WebCore/css/CSSPrimitiveValue.h @@ -211,6 +211,7 @@ private: Pair* pair; DashboardRegion* region; } m_value; + mutable String m_cachedCSSText; }; } // namespace WebCore diff --git a/WebCore/css/CSSPrimitiveValueMappings.h b/WebCore/css/CSSPrimitiveValueMappings.h index c20448e..223b515 100644 --- a/WebCore/css/CSSPrimitiveValueMappings.h +++ b/WebCore/css/CSSPrimitiveValueMappings.h @@ -275,6 +275,11 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e) case OuterSpinButtonPart: m_value.ident = CSSValueOuterSpinButton; break; + case ProgressBarPart: +#if ENABLE(PROGRESS_BAR) + m_value.ident = CSSValueProgressBar; +#endif + break; case SliderHorizontalPart: m_value.ident = CSSValueSliderHorizontal; break; diff --git a/WebCore/css/CSSPropertyNames.in b/WebCore/css/CSSPropertyNames.in index fe610de..aed7063 100644 --- a/WebCore/css/CSSPropertyNames.in +++ b/WebCore/css/CSSPropertyNames.in @@ -151,6 +151,7 @@ zoom -webkit-animation-delay -webkit-animation-direction -webkit-animation-duration +-webkit-animation-fill-mode -webkit-animation-iteration-count -webkit-animation-name -webkit-animation-play-state diff --git a/WebCore/css/CSSSelector.cpp b/WebCore/css/CSSSelector.cpp index 9ae9b9f..23a89f6 100644 --- a/WebCore/css/CSSSelector.cpp +++ b/WebCore/css/CSSSelector.cpp @@ -28,6 +28,7 @@ #include "wtf/Assertions.h" #include "HTMLNames.h" +#include <wtf/HashMap.h> #include <wtf/StdLibExtras.h> namespace WebCore { @@ -65,11 +66,148 @@ unsigned int CSSSelector::specificity() return s & 0xffffff; } -void CSSSelector::extractPseudoType() const +PseudoId CSSSelector::pseudoId(PseudoType type) { - if (m_match != PseudoClass && m_match != PseudoElement) - return; + switch (type) { + case PseudoFirstLine: + return FIRST_LINE; + case PseudoFirstLetter: + return FIRST_LETTER; + case PseudoSelection: + return SELECTION; + case PseudoBefore: + return BEFORE; + case PseudoAfter: + return AFTER; + case PseudoFileUploadButton: + return FILE_UPLOAD_BUTTON; + case PseudoInputPlaceholder: + return INPUT_PLACEHOLDER; + case PseudoSliderThumb: + return SLIDER_THUMB; + case PseudoSearchCancelButton: + return SEARCH_CANCEL_BUTTON; + case PseudoSearchDecoration: + return SEARCH_DECORATION; + case PseudoSearchResultsDecoration: + 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 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: + return SCROLLBAR_BUTTON; + case PseudoScrollbarCorner: + return SCROLLBAR_CORNER; + case PseudoScrollbarThumb: + return SCROLLBAR_THUMB; + case PseudoScrollbarTrack: + return SCROLLBAR_TRACK; + case PseudoScrollbarTrackPiece: + return SCROLLBAR_TRACK_PIECE; + case PseudoResizer: + return RESIZER; + case PseudoInnerSpinButton: + return INNER_SPIN_BUTTON; + case PseudoOuterSpinButton: + return OUTER_SPIN_BUTTON; + case PseudoInputListButton: +#if ENABLE(DATALIST) + return INPUT_LIST_BUTTON; +#endif + case PseudoUnknown: + case PseudoEmpty: + case PseudoFirstChild: + case PseudoFirstOfType: + case PseudoLastChild: + case PseudoLastOfType: + case PseudoOnlyChild: + case PseudoOnlyOfType: + case PseudoNthChild: + case PseudoNthOfType: + case PseudoNthLastChild: + case PseudoNthLastOfType: + case PseudoLink: + case PseudoVisited: + case PseudoAnyLink: + case PseudoAutofill: + case PseudoHover: + case PseudoDrag: + case PseudoFocus: + case PseudoActive: + case PseudoChecked: + case PseudoEnabled: + case PseudoFullPageMedia: + case PseudoDefault: + case PseudoDisabled: + case PseudoOptional: + case PseudoRequired: + case PseudoReadOnly: + case PseudoReadWrite: + case PseudoValid: + case PseudoInvalid: + case PseudoIndeterminate: + case PseudoTarget: + case PseudoLang: + case PseudoNot: + case PseudoRoot: + case PseudoScrollbarBack: + case PseudoScrollbarForward: + case PseudoWindowInactive: + case PseudoCornerPresent: + case PseudoDecrement: + case PseudoIncrement: + case PseudoHorizontal: + case PseudoVertical: + case PseudoStart: + case PseudoEnd: + case PseudoDoubleButton: + case PseudoSingleButton: + case PseudoNoButton: + return NOPSEUDO; + case PseudoNotParsed: + ASSERT_NOT_REACHED(); + return NOPSEUDO; + } + + ASSERT_NOT_REACHED(); + return NOPSEUDO; +} +static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap() +{ DEFINE_STATIC_LOCAL(AtomicString, active, ("active")); DEFINE_STATIC_LOCAL(AtomicString, after, ("after")); DEFINE_STATIC_LOCAL(AtomicString, anyLink, ("-webkit-any-link")); @@ -129,6 +267,9 @@ void CSSSelector::extractPseudoType() const 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_BAR) + DEFINE_STATIC_LOCAL(AtomicString, progressBar, ("-webkit-progress-bar")); +#endif DEFINE_STATIC_LOCAL(AtomicString, required, ("required")); DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer")); DEFINE_STATIC_LOCAL(AtomicString, root, ("root")); @@ -158,232 +299,218 @@ void CSSSelector::extractPseudoType() const DEFINE_STATIC_LOCAL(AtomicString, noButton, ("no-button")); DEFINE_STATIC_LOCAL(AtomicString, cornerPresent, ("corner-present")); + static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = 0; + if (!nameToPseudoType) { + nameToPseudoType = new HashMap<AtomicStringImpl*, CSSSelector::PseudoType>; + nameToPseudoType->set(active.impl(), CSSSelector::PseudoActive); + nameToPseudoType->set(after.impl(), CSSSelector::PseudoAfter); + nameToPseudoType->set(anyLink.impl(), CSSSelector::PseudoAnyLink); + nameToPseudoType->set(autofill.impl(), CSSSelector::PseudoAutofill); + nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore); + nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked); + nameToPseudoType->set(fileUploadButton.impl(), CSSSelector::PseudoFileUploadButton); + nameToPseudoType->set(defaultString.impl(), CSSSelector::PseudoDefault); + nameToPseudoType->set(disabled.impl(), CSSSelector::PseudoDisabled); + nameToPseudoType->set(readOnly.impl(), CSSSelector::PseudoReadOnly); + nameToPseudoType->set(readWrite.impl(), CSSSelector::PseudoReadWrite); + nameToPseudoType->set(valid.impl(), CSSSelector::PseudoValid); + nameToPseudoType->set(invalid.impl(), CSSSelector::PseudoInvalid); + nameToPseudoType->set(drag.impl(), CSSSelector::PseudoDrag); + nameToPseudoType->set(dragAlias.impl(), CSSSelector::PseudoDrag); + nameToPseudoType->set(enabled.impl(), CSSSelector::PseudoEnabled); + nameToPseudoType->set(empty.impl(), CSSSelector::PseudoEmpty); + nameToPseudoType->set(firstChild.impl(), CSSSelector::PseudoFirstChild); + nameToPseudoType->set(fullPageMedia.impl(), CSSSelector::PseudoFullPageMedia); +#if ENABLE(DATALIST) + nameToPseudoType->set(inputListButton.impl(), CSSSelector::PseudoInputListButton); +#endif + nameToPseudoType->set(inputPlaceholder.impl(), CSSSelector::PseudoInputPlaceholder); + nameToPseudoType->set(lastChild.impl(), CSSSelector::PseudoLastChild); + nameToPseudoType->set(lastOfType.impl(), CSSSelector::PseudoLastOfType); + nameToPseudoType->set(onlyChild.impl(), CSSSelector::PseudoOnlyChild); + nameToPseudoType->set(onlyOfType.impl(), CSSSelector::PseudoOnlyOfType); + nameToPseudoType->set(firstLetter.impl(), CSSSelector::PseudoFirstLetter); + nameToPseudoType->set(firstLine.impl(), CSSSelector::PseudoFirstLine); + nameToPseudoType->set(firstOfType.impl(), CSSSelector::PseudoFirstOfType); + nameToPseudoType->set(focus.impl(), CSSSelector::PseudoFocus); + nameToPseudoType->set(hover.impl(), CSSSelector::PseudoHover); + nameToPseudoType->set(indeterminate.impl(), CSSSelector::PseudoIndeterminate); + nameToPseudoType->set(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(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); + nameToPseudoType->set(root.impl(), CSSSelector::PseudoRoot); + nameToPseudoType->set(windowInactive.impl(), CSSSelector::PseudoWindowInactive); + nameToPseudoType->set(decrement.impl(), CSSSelector::PseudoDecrement); + nameToPseudoType->set(increment.impl(), CSSSelector::PseudoIncrement); + nameToPseudoType->set(start.impl(), CSSSelector::PseudoStart); + nameToPseudoType->set(end.impl(), CSSSelector::PseudoEnd); + nameToPseudoType->set(horizontal.impl(), CSSSelector::PseudoHorizontal); + nameToPseudoType->set(vertical.impl(), CSSSelector::PseudoVertical); + nameToPseudoType->set(doubleButton.impl(), CSSSelector::PseudoDoubleButton); + nameToPseudoType->set(singleButton.impl(), CSSSelector::PseudoSingleButton); + nameToPseudoType->set(noButton.impl(), CSSSelector::PseudoNoButton); + nameToPseudoType->set(optional.impl(), CSSSelector::PseudoOptional); + nameToPseudoType->set(required.impl(), CSSSelector::PseudoRequired); + nameToPseudoType->set(resizer.impl(), CSSSelector::PseudoResizer); + nameToPseudoType->set(scrollbar.impl(), CSSSelector::PseudoScrollbar); + nameToPseudoType->set(scrollbarButton.impl(), CSSSelector::PseudoScrollbarButton); + nameToPseudoType->set(scrollbarCorner.impl(), CSSSelector::PseudoScrollbarCorner); + nameToPseudoType->set(scrollbarThumb.impl(), CSSSelector::PseudoScrollbarThumb); + nameToPseudoType->set(scrollbarTrack.impl(), CSSSelector::PseudoScrollbarTrack); + nameToPseudoType->set(scrollbarTrackPiece.impl(), CSSSelector::PseudoScrollbarTrackPiece); + nameToPseudoType->set(cornerPresent.impl(), CSSSelector::PseudoCornerPresent); + nameToPseudoType->set(searchCancelButton.impl(), CSSSelector::PseudoSearchCancelButton); + nameToPseudoType->set(searchDecoration.impl(), CSSSelector::PseudoSearchDecoration); + nameToPseudoType->set(searchResultsDecoration.impl(), CSSSelector::PseudoSearchResultsDecoration); + nameToPseudoType->set(searchResultsButton.impl(), CSSSelector::PseudoSearchResultsButton); + nameToPseudoType->set(selection.impl(), CSSSelector::PseudoSelection); + nameToPseudoType->set(sliderThumb.impl(), CSSSelector::PseudoSliderThumb); + nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget); + nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited); + } + return nameToPseudoType; +} + +CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) +{ + if (name.isNull()) + return PseudoUnknown; + HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseudoTypeMap(); + HashMap<AtomicStringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoType->find(name.impl()); + return slot == nameToPseudoType->end() ? PseudoUnknown : slot->second; +} + +void CSSSelector::extractPseudoType() const +{ + if (m_match != PseudoClass && m_match != PseudoElement) + return; + + m_pseudoType = parsePseudoType(m_value); + bool element = false; // pseudo-element bool compat = false; // single colon compatbility mode - m_pseudoType = PseudoUnknown; - if (m_value == active) - m_pseudoType = PseudoActive; - else if (m_value == after) { - m_pseudoType = PseudoAfter; - element = true; - compat = true; - } else if (m_value == anyLink) - m_pseudoType = PseudoAnyLink; - else if (m_value == autofill) - m_pseudoType = PseudoAutofill; - else if (m_value == before) { - m_pseudoType = PseudoBefore; - element = true; - compat = true; - } else if (m_value == checked) - m_pseudoType = PseudoChecked; - else if (m_value == fileUploadButton) { - m_pseudoType = PseudoFileUploadButton; - element = true; - } else if (m_value == defaultString) - m_pseudoType = PseudoDefault; - else if (m_value == disabled) - m_pseudoType = PseudoDisabled; - else if (m_value == readOnly) - m_pseudoType = PseudoReadOnly; - else if (m_value == readWrite) - m_pseudoType = PseudoReadWrite; - else if (m_value == valid) - m_pseudoType = PseudoValid; - else if (m_value == invalid) - m_pseudoType = PseudoInvalid; - else if (m_value == drag || m_value == dragAlias) - m_pseudoType = PseudoDrag; - else if (m_value == enabled) - m_pseudoType = PseudoEnabled; - else if (m_value == empty) - m_pseudoType = PseudoEmpty; - else if (m_value == firstChild) - m_pseudoType = PseudoFirstChild; - else if (m_value == fullPageMedia) - m_pseudoType = PseudoFullPageMedia; - else -#if ENABLE(DATALIST) - if (m_value == inputListButton) { - m_pseudoType = PseudoInputListButton; - element = true; - } else -#endif - if (m_value == inputPlaceholder) { - m_pseudoType = PseudoInputPlaceholder; - element = true; - } else if (m_value == lastChild) - m_pseudoType = PseudoLastChild; - else if (m_value == lastOfType) - m_pseudoType = PseudoLastOfType; - else if (m_value == onlyChild) - m_pseudoType = PseudoOnlyChild; - else if (m_value == onlyOfType) - m_pseudoType = PseudoOnlyOfType; - else if (m_value == firstLetter) { - m_pseudoType = PseudoFirstLetter; - element = true; - compat = true; - } else if (m_value == firstLine) { - m_pseudoType = PseudoFirstLine; - element = true; + switch (m_pseudoType) { + case PseudoAfter: + case PseudoBefore: + case PseudoFirstLetter: + case PseudoFirstLine: compat = true; - } else if (m_value == firstOfType) - m_pseudoType = PseudoFirstOfType; - else if (m_value == focus) - m_pseudoType = PseudoFocus; - else if (m_value == hover) - m_pseudoType = PseudoHover; - else if (m_value == indeterminate) - m_pseudoType = PseudoIndeterminate; - else if (m_value == innerSpinButton) { - m_pseudoType = PseudoInnerSpinButton; - element = true; - } else if (m_value == link) - m_pseudoType = PseudoLink; - else if (m_value == lang) - m_pseudoType = PseudoLang; - else if (m_value == mediaControlsPanel) { - m_pseudoType = PseudoMediaControlsPanel; - element = true; - } else if (m_value == mediaControlsMuteButton) { - m_pseudoType = PseudoMediaControlsMuteButton; - element = true; - } else if (m_value == mediaControlsPlayButton) { - m_pseudoType = PseudoMediaControlsPlayButton; - element = true; - } else if (m_value == mediaControlsCurrentTimeDisplay) { - m_pseudoType = PseudoMediaControlsCurrentTimeDisplay; - element = true; - } else if (m_value == mediaControlsTimeRemainingDisplay) { - m_pseudoType = PseudoMediaControlsTimeRemainingDisplay; - element = true; - } else if (m_value == mediaControlsTimeline) { - m_pseudoType = PseudoMediaControlsTimeline; - element = true; - } else if (m_value == mediaControlsVolumeSlider) { - m_pseudoType = PseudoMediaControlsVolumeSlider; - element = true; - } else if (m_value == mediaControlsSeekBackButton) { - m_pseudoType = PseudoMediaControlsSeekBackButton; - element = true; - } else if (m_value == mediaControlsSeekForwardButton) { - m_pseudoType = PseudoMediaControlsSeekForwardButton; - element = true; - } else if (m_value == mediaControlsRewindButton) { - m_pseudoType = PseudoMediaControlsRewindButton; - element = true; - } else if (m_value == mediaControlsReturnToRealtimeButton) { - m_pseudoType = PseudoMediaControlsReturnToRealtimeButton; - element = true; - } else if (m_value == mediaControlsToggleClosedCaptionsButton) { - m_pseudoType = PseudoMediaControlsToggleClosedCaptions; - element = true; - } else if (m_value == mediaControlsStatusDisplay) { - m_pseudoType = PseudoMediaControlsStatusDisplay; - element = true; - } else if (m_value == mediaControlsFullscreenButton) { - m_pseudoType = PseudoMediaControlsFullscreenButton; - element = true; - } else if (m_value == mediaControlsTimelineContainer) { - m_pseudoType = PseudoMediaControlsTimelineContainer; - element = true; - } else if (m_value == mediaControlsVolumeSliderContainer) { - m_pseudoType = PseudoMediaControlsVolumeSliderContainer; - element = true; - } else if (m_value == notStr) - m_pseudoType = PseudoNot; - else if (m_value == nthChild) - m_pseudoType = PseudoNthChild; - else if (m_value == nthOfType) - m_pseudoType = PseudoNthOfType; - else if (m_value == nthLastChild) - m_pseudoType = PseudoNthLastChild; - else if (m_value == nthLastOfType) - m_pseudoType = PseudoNthLastOfType; - else if (m_value == outerSpinButton) { - m_pseudoType = PseudoOuterSpinButton; - element = true; - } else if (m_value == root) - m_pseudoType = PseudoRoot; - else if (m_value == windowInactive) - m_pseudoType = PseudoWindowInactive; - else if (m_value == decrement) - m_pseudoType = PseudoDecrement; - else if (m_value == increment) - m_pseudoType = PseudoIncrement; - else if (m_value == start) - m_pseudoType = PseudoStart; - else if (m_value == end) - m_pseudoType = PseudoEnd; - else if (m_value == horizontal) - m_pseudoType = PseudoHorizontal; - else if (m_value == vertical) - m_pseudoType = PseudoVertical; - else if (m_value == doubleButton) - m_pseudoType = PseudoDoubleButton; - else if (m_value == singleButton) - m_pseudoType = PseudoSingleButton; - else if (m_value == noButton) - m_pseudoType = PseudoNoButton; - else if (m_value == optional) - m_pseudoType = PseudoOptional; - else if (m_value == required) - m_pseudoType = PseudoRequired; - else if (m_value == scrollbarCorner) { - element = true; - m_pseudoType = PseudoScrollbarCorner; - } else if (m_value == resizer) { - element = true; - m_pseudoType = PseudoResizer; - } else if (m_value == scrollbar) { - element = true; - m_pseudoType = PseudoScrollbar; - } else if (m_value == scrollbarButton) { - element = true; - m_pseudoType = PseudoScrollbarButton; - } else if (m_value == scrollbarCorner) { - element = true; - m_pseudoType = PseudoScrollbarCorner; - } else if (m_value == scrollbarThumb) { - element = true; - m_pseudoType = PseudoScrollbarThumb; - } else if (m_value == scrollbarTrack) { - element = true; - m_pseudoType = PseudoScrollbarTrack; - } else if (m_value == scrollbarTrackPiece) { - element = true; - m_pseudoType = PseudoScrollbarTrackPiece; - } else if (m_value == cornerPresent) - m_pseudoType = PseudoCornerPresent; - else if (m_value == searchCancelButton) { - m_pseudoType = PseudoSearchCancelButton; - element = true; - } else if (m_value == searchDecoration) { - m_pseudoType = PseudoSearchDecoration; - element = true; - } else if (m_value == searchResultsDecoration) { - m_pseudoType = PseudoSearchResultsDecoration; - element = true; - } else if (m_value == searchResultsButton) { - m_pseudoType = PseudoSearchResultsButton; - element = true; - } else if (m_value == selection) { - m_pseudoType = PseudoSelection; - element = true; - } else if (m_value == sliderThumb) { - m_pseudoType = PseudoSliderThumb; - element = true; - } else if (m_value == target) - m_pseudoType = PseudoTarget; - else if (m_value == visited) - m_pseudoType = PseudoVisited; + case PseudoFileUploadButton: + case PseudoInputListButton: + case PseudoInputPlaceholder: + case PseudoInnerSpinButton: + case PseudoMediaControlsPanel: + case PseudoMediaControlsMuteButton: + case PseudoMediaControlsPlayButton: + case PseudoMediaControlsCurrentTimeDisplay: + case PseudoMediaControlsTimeRemainingDisplay: + case PseudoMediaControlsTimeline: + case PseudoMediaControlsVolumeSlider: + case PseudoMediaControlsSeekBackButton: + case PseudoMediaControlsSeekForwardButton: + case PseudoMediaControlsRewindButton: + case PseudoMediaControlsReturnToRealtimeButton: + case PseudoMediaControlsToggleClosedCaptions: + case PseudoMediaControlsStatusDisplay: + case PseudoMediaControlsFullscreenButton: + case PseudoMediaControlsTimelineContainer: + case PseudoMediaControlsVolumeSliderContainer: + case PseudoOuterSpinButton: + case PseudoResizer: + case PseudoScrollbar: + case PseudoScrollbarCorner: + case PseudoScrollbarButton: + case PseudoScrollbarThumb: + case PseudoScrollbarTrack: + case PseudoScrollbarTrackPiece: + case PseudoSearchCancelButton: + case PseudoSearchDecoration: + case PseudoSearchResultsDecoration: + case PseudoSearchResultsButton: + case PseudoSelection: + case PseudoSliderThumb: + element = true; + break; + case PseudoUnknown: + case PseudoEmpty: + case PseudoFirstChild: + case PseudoFirstOfType: + case PseudoLastChild: + case PseudoLastOfType: + case PseudoOnlyChild: + case PseudoOnlyOfType: + case PseudoNthChild: + case PseudoNthOfType: + case PseudoNthLastChild: + case PseudoNthLastOfType: + case PseudoLink: + case PseudoVisited: + case PseudoAnyLink: + case PseudoAutofill: + case PseudoHover: + case PseudoDrag: + case PseudoFocus: + case PseudoActive: + case PseudoChecked: + case PseudoEnabled: + case PseudoFullPageMedia: + case PseudoDefault: + case PseudoDisabled: + case PseudoOptional: + case PseudoRequired: + case PseudoReadOnly: + case PseudoReadWrite: + case PseudoValid: + case PseudoInvalid: + case PseudoIndeterminate: + case PseudoTarget: + case PseudoLang: + case PseudoNot: + case PseudoRoot: + case PseudoScrollbarBack: + case PseudoScrollbarForward: + case PseudoWindowInactive: + case PseudoCornerPresent: + case PseudoDecrement: + case PseudoIncrement: + case PseudoHorizontal: + case PseudoVertical: + case PseudoStart: + case PseudoEnd: + case PseudoDoubleButton: + case PseudoSingleButton: + case PseudoNoButton: + case PseudoNotParsed: + break; + } if (m_match == PseudoClass && element) { - if (!compat) + if (!compat) m_pseudoType = PseudoUnknown; - else + else m_match = PseudoElement; } else if (m_match == PseudoElement && !element) m_pseudoType = PseudoUnknown; @@ -563,10 +690,35 @@ bool CSSSelector::matchNth(int count) return m_data.m_rareData->matchNth(count); } +bool CSSSelector::isSimple() const +{ + if (simpleSelector() || tagHistory() || matchesPseudoElement()) + return false; + + int numConditions = 0; + + // hasTag() cannot be be used here because namespace may not be nullAtom. + // Example: + // @namespace "http://www.w3.org/2000/svg"; + // svg:not(:root) { ... + if (m_tag != starAtom) + numConditions++; + + if (m_match == Id || m_match == Class || m_match == PseudoClass) + numConditions++; + + if (m_hasRareData && m_data.m_rareData->m_attribute != anyQName()) + numConditions++; + + // numConditions is 0 for a universal selector. + // numConditions is 1 for other simple selectors. + return numConditions <= 1; +} + // a helper function for parsing nth-arguments bool CSSSelector::RareData::parseNth() -{ - const String& argument = m_argument; +{ + String argument = m_argument.lower(); if (argument.isEmpty()) return false; diff --git a/WebCore/css/CSSSelector.h b/WebCore/css/CSSSelector.h index 70f2574..f8748c7 100644 --- a/WebCore/css/CSSSelector.h +++ b/WebCore/css/CSSSelector.h @@ -22,6 +22,7 @@ #ifndef CSSSelector_h #define CSSSelector_h +#include "RenderStyleConstants.h" #include "QualifiedName.h" #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> @@ -194,7 +195,10 @@ namespace WebCore { extractPseudoType(); return static_cast<PseudoType>(m_pseudoType); } - + + 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); @@ -212,10 +216,18 @@ namespace WebCore { bool parseNth(); bool matchNth(int count); + bool matchesPseudoElement() const + { + if (m_pseudoType == PseudoUnknown) + extractPseudoType(); + return m_match == PseudoElement; + } + Relation relation() const { return static_cast<Relation>(m_relation); } bool isLastInSelectorList() const { return m_isLastInSelectorList; } void setLastInSelectorList() { m_isLastInSelectorList = true; } + bool isSimple() const; mutable AtomicString m_value; QualifiedName m_tag; diff --git a/WebCore/css/CSSStyleRule.cpp b/WebCore/css/CSSStyleRule.cpp index aaac254..1036e8f 100644 --- a/WebCore/css/CSSStyleRule.cpp +++ b/WebCore/css/CSSStyleRule.cpp @@ -27,8 +27,9 @@ namespace WebCore { -CSSStyleRule::CSSStyleRule(CSSStyleSheet* parent) +CSSStyleRule::CSSStyleRule(CSSStyleSheet* parent, int sourceLine) : CSSRule(parent) + , m_sourceLine(sourceLine) { } diff --git a/WebCore/css/CSSStyleRule.h b/WebCore/css/CSSStyleRule.h index 23d8648..835f2a2 100644 --- a/WebCore/css/CSSStyleRule.h +++ b/WebCore/css/CSSStyleRule.h @@ -34,9 +34,9 @@ class CSSSelector; class CSSStyleRule : public CSSRule { public: - static PassRefPtr<CSSStyleRule> create(CSSStyleSheet* parent) + static PassRefPtr<CSSStyleRule> create(CSSStyleSheet* parent, int sourceLine) { - return adoptRef(new CSSStyleRule(parent)); + return adoptRef(new CSSStyleRule(parent, sourceLine)); } virtual ~CSSStyleRule(); @@ -58,8 +58,10 @@ public: virtual void addSubresourceStyleURLs(ListHashSet<KURL>& urls); + int sourceLine() { return m_sourceLine; } + private: - CSSStyleRule(CSSStyleSheet* parent); + CSSStyleRule(CSSStyleSheet* parent, int sourceLine); virtual bool isStyleRule() { return true; } @@ -68,6 +70,7 @@ private: RefPtr<CSSMutableStyleDeclaration> m_style; CSSSelectorList m_selectorList; + int m_sourceLine; }; } // namespace WebCore diff --git a/WebCore/css/CSSStyleSelector.cpp b/WebCore/css/CSSStyleSelector.cpp index f7f2707..dd4fed9 100644 --- a/WebCore/css/CSSStyleSelector.cpp +++ b/WebCore/css/CSSStyleSelector.cpp @@ -361,9 +361,9 @@ public: void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, CSSStyleRule* rule, CSSSelector* sel); - CSSRuleDataList* getIDRules(AtomicStringImpl* key) { m_idRules.checkConsistency(); return m_idRules.get(key); } - CSSRuleDataList* getClassRules(AtomicStringImpl* key) { m_classRules.checkConsistency(); return m_classRules.get(key); } - CSSRuleDataList* getTagRules(AtomicStringImpl* key) { m_tagRules.checkConsistency(); return m_tagRules.get(key); } + 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* getUniversalRules() { return m_universalRules; } public: @@ -382,8 +382,6 @@ static CSSStyleSheet* simpleDefaultStyleSheet; RenderStyle* CSSStyleSelector::s_styleNotYetAvailable; -static PseudoState pseudoState; - static void loadFullDefaultStyle(); static void loadSimpleDefaultStyle(); // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet. @@ -710,7 +708,7 @@ void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleI // we really just matched a pseudo-element. if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) { if (m_checker.m_collectRulesOnly) - return; + continue; if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID) m_style->setHasPseudoStyle(m_dynamicPseudo); } else { @@ -802,14 +800,10 @@ void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end) m_matchedRules[i] = rulesMergeBuffer[i - start]; } -void CSSStyleSelector::initElementAndPseudoState(Element* e) +void CSSStyleSelector::initElement(Element* e) { m_element = e; - if (m_element && m_element->isStyledElement()) - m_styledElement = static_cast<StyledElement*>(m_element); - else - m_styledElement = 0; - pseudoState = PseudoUnknown; + m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0; } void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID) @@ -876,57 +870,56 @@ CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool stri , m_collectRulesOnly(false) , m_pseudoStyle(NOPSEUDO) , m_documentIsHTML(document->isHTMLDocument()) + , m_matchVisitedPseudoClass(false) { } -PseudoState CSSStyleSelector::SelectorChecker::checkPseudoState(Element* element, bool checkVisited) const +EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const { + if (!element->isLink()) + return NotInsideLink; + const AtomicString* attr = linkAttribute(element); if (!attr || attr->isNull()) - return PseudoNone; - - if (!checkVisited) - return PseudoAnyLink; + return NotInsideLink; #if PLATFORM(QT) Vector<UChar, 512> url; visitedURL(m_document->baseURL(), *attr, url); if (url.isEmpty()) - return PseudoLink; + return InsideUnvisitedLink; // If the Qt4.4 interface for the history is used, we will have to fallback // to the old global history. QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface(); if (iface) - return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? PseudoVisited : PseudoLink; + return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink; LinkHash hash = visitedLinkHash(url.data(), url.size()); if (!hash) - return PseudoLink; + return InsideUnvisitedLink; #else LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr); if (!hash) - return PseudoLink; + return InsideUnvisitedLink; #endif Frame* frame = m_document->frame(); if (!frame) - return PseudoLink; + return InsideUnvisitedLink; Page* page = frame->page(); if (!page) - return PseudoLink; + return InsideUnvisitedLink; m_linksCheckedForVisitedState.add(hash); - return page->group().isLinkVisited(hash) ? PseudoVisited : PseudoLink; + return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink; } bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const { - pseudoState = PseudoUnknown; PseudoId dynamicPseudo = NOPSEUDO; - - return checkSelector(sel, element, 0, dynamicPseudo, true, false) == SelectorMatches; + return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches; } #ifdef STYLE_SHARING_STATS @@ -1031,20 +1024,11 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) if (s->hasMappedAttributes()) mappedAttrsMatch = s->mappedAttributes()->mapsEquivalent(m_styledElement->mappedAttributes()); if (mappedAttrsMatch) { - bool linksMatch = true; - if (s->isLink()) { - // We need to check to see if the visited state matches. - if (pseudoState == PseudoUnknown) { - const Color& linkColor = m_element->document()->linkColor(); - const Color& visitedColor = m_element->document()->visitedLinkColor(); - pseudoState = m_checker.checkPseudoState(m_element, style->pseudoState() != PseudoAnyLink || linkColor != visitedColor); - } - linksMatch = (pseudoState == style->pseudoState()); + if (m_checker.determineLinkState(m_element) != style->insideLink()) + return false; } - - if (linksMatch) - return true; + return true; } } } @@ -1134,7 +1118,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document) // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where // relative units are interpreted according to document root element style, styled only with UA stylesheet -PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault) +PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedRules) { // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer // will vanish if a style recalc happens during loading. @@ -1150,7 +1134,7 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl return s_styleNotYetAvailable; } - initElementAndPseudoState(e); + initElement(e); if (allowSharing) { RenderStyle* sharedStyle = locateSharedStyle(); if (sharedStyle) @@ -1158,6 +1142,24 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl } initForStyleResolve(e, defaultParent); + // Compute our style allowing :visited to match first. + RefPtr<RenderStyle> visitedStyle; + if (!matchVisitedRules && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) { + // Fetch our parent style. + RenderStyle* parentStyle = m_parentStyle; + if (!e->isLink()) { + // Use the parent's visited style if one exists. + RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK); + if (parentVisitedStyle) + parentStyle = parentVisitedStyle; + } + visitedStyle = styleForElement(e, parentStyle, false, false, true); + visitedStyle->setStyleType(VISITED_LINK); + initForStyleResolve(e, defaultParent); + } + + m_checker.m_matchVisitedPseudoClass = matchVisitedRules; + m_style = RenderStyle::create(); if (m_parentStyle) @@ -1165,6 +1167,11 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl else m_parentStyle = style(); + if (e->isLink()) { + m_style->setIsLink(true); + m_style->setInsideLink(m_checker.determineLinkState(e)); + } + if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) loadFullDefaultStyle(); @@ -1276,6 +1283,9 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl } } + // Reset the value back before applying properties, so that -webkit-link knows what color to use. + m_checker.m_matchVisitedPseudoClass = matchVisitedRules; + // Now we have all of the matched rules in the appropriate order. Walk the rules and apply // high-priority properties first, i.e., those properties that other properties depend on. // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important @@ -1318,14 +1328,23 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl // Clean up our style object's display and text decorations (among other fixups). adjustRenderStyle(style(), e); - // If we are a link, cache the determined pseudo-state. - if (e->isLink()) - m_style->setPseudoState(pseudoState); - // If we have first-letter pseudo style, do not share this style if (m_style->hasPseudoStyle(FIRST_LETTER)) m_style->setUnique(); + if (visitedStyle) { + // Copy any pseudo bits that the visited style has to the primary style so that + // pseudo element styles will continue to work for pseudo elements inside :visited + // links. + for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) { + if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo))) + m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo)); + } + + // Add the visited style off the main style. + m_style->addCachedPseudoStyle(visitedStyle.release()); + } + // Now return the style. return m_style.release(); } @@ -1348,7 +1367,7 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* // Construct and populate the style for each keyframe for (unsigned i = 0; i < rule->length(); ++i) { // Apply the declaration to the style. This is a simplified version of the logic in styleForElement - initElementAndPseudoState(e); + initElement(e); initForStyleResolve(e); const WebKitCSSKeyframeRule* kf = rule->item(i); @@ -1412,15 +1431,28 @@ void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* list.clear(); } -PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle) +PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedLinks) { if (!e) return 0; - initElementAndPseudoState(e); + // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it + // off of. + RefPtr<RenderStyle> visitedStyle; + if (!matchVisitedLinks && parentStyle && parentStyle->insideLink()) { + // Fetch our parent style with :visited in effect. + RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK); + visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true); + if (visitedStyle) + visitedStyle->setStyleType(VISITED_LINK); + } + + initElement(e); initForStyleResolve(e, parentStyle, pseudo); m_style = parentStyle; + m_checker.m_matchVisitedPseudoClass = matchVisitedLinks; + // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking // those rules. @@ -1433,16 +1465,20 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule); } - if (m_matchedDecls.isEmpty()) + if (m_matchedDecls.isEmpty() && !visitedStyle) return 0; - + m_style = RenderStyle::create(); if (parentStyle) m_style->inheritFrom(parentStyle); - m_style->noninherited_flags._styleType = pseudo; + m_style->setStyleType(pseudo); m_lineHeightValue = 0; + + // Reset the value back before applying properties, so that -webkit-link knows what color to use. + m_checker.m_matchVisitedPseudoClass = matchVisitedLinks; + // High-priority properties. applyDeclarations(true, false, 0, m_matchedDecls.size() - 1); applyDeclarations(true, true, firstAuthorRule, lastAuthorRule); @@ -1472,9 +1508,14 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, // go ahead and update it a second time. if (m_fontDirty) updateFont(); + // Clean up our style object's display and text decorations (among other fixups). adjustRenderStyle(style(), 0); + // Hang our visited style off m_style. + if (visitedStyle) + m_style->addCachedPseudoStyle(visitedStyle.release()); + // Now return the style. return m_style.release(); } @@ -1722,13 +1763,18 @@ void CSSStyleSelector::cacheBorderAndBackground() PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly) { + return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly); +} + +PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly) +{ if (!e || !e->document()->haveStylesheetsLoaded()) return 0; m_checker.m_collectRulesOnly = true; - initElementAndPseudoState(e); - initForStyleResolve(e); + initElement(e); + initForStyleResolve(e, 0, pseudoId); if (!authorOnly) { int firstUARule = -1, lastUARule = -1; @@ -1753,18 +1799,12 @@ PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool return m_ruleList.release(); } -PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element*, const String&, bool) -{ - // FIXME: Implement this. - return 0; -} - bool CSSStyleSelector::checkSelector(CSSSelector* sel) { m_dynamicPseudo = NOPSEUDO; // Check the selector - SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, true, false, style(), m_parentStyle); + SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentStyle); if (match != SelectorMatches) return false; @@ -1779,7 +1819,7 @@ bool CSSStyleSelector::checkSelector(CSSSelector* sel) // * SelectorMatches - the selector matches the element e // * SelectorFailsLocally - the selector fails for the element e // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e -CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const +CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const { #if ENABLE(SVG) // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree @@ -1789,7 +1829,7 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector #endif // first selector has to match - if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isAncestor, isSubSelector, elementStyle, elementParentStyle)) + if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, elementStyle, elementParentStyle)) return SelectorFailsLocally; // The rest of the selectors has to match @@ -1805,6 +1845,17 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo) return SelectorFailsCompletely; + // Check for nested links. + if (m_matchVisitedPseudoClass && !isSubSelector) { + RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle(); + if (currentStyle && currentStyle->insideLink() && e->isLink()) { + if (encounteredLink) + m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching. + else + encounteredLink = true; + } + } + switch (relation) { case CSSSelector::Descendant: while (true) { @@ -1812,7 +1863,7 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector if (!n || !n->isElementNode()) return SelectorFailsCompletely; e = static_cast<Element*>(n); - SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, false); + SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); if (match != SelectorFailsLocally) return match; } @@ -1823,7 +1874,7 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector if (!n || !n->isElementNode()) return SelectorFailsCompletely; e = static_cast<Element*>(n); - return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, false); + return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); } case CSSSelector::DirectAdjacent: { @@ -1838,7 +1889,8 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector if (!n) return SelectorFailsLocally; e = static_cast<Element*>(n); - return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, false); + m_matchVisitedPseudoClass = false; + return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); } case CSSSelector::IndirectAdjacent: if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) { @@ -1853,7 +1905,8 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector if (!n) return SelectorFailsLocally; e = static_cast<Element*>(n); - SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, false); + m_matchVisitedPseudoClass = false; + SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink); if (match != SelectorFailsLocally) return match; }; @@ -1862,10 +1915,10 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector // a selector is invalid if something follows a pseudo-element // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else) // to follow the pseudo elements. - if (elementStyle && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION && + if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION && !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass)) return SelectorFailsCompletely; - return checkSelector(sel, e, selectorAttrs, dynamicPseudo, isAncestor, true, elementStyle, elementParentStyle); + return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle); } return SelectorFailsCompletely; @@ -1938,7 +1991,7 @@ static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr) return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl()); } -bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const +bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const { if (!e) return false; @@ -2039,7 +2092,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme // the parser enforces that this never occurs ASSERT(!subSel->simpleSelector()); - if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, isAncestor, true, elementStyle, elementParentStyle)) + if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, elementStyle, elementParentStyle)) return true; } } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) { @@ -2347,9 +2400,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme return true; break; case CSSSelector::PseudoAnyLink: - if (pseudoState == PseudoUnknown) - pseudoState = checkPseudoState(e, false); - if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited) + if (e && e->isLink()) return true; break; case CSSSelector::PseudoAutofill: { @@ -2360,16 +2411,12 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme break; } case CSSSelector::PseudoLink: - if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) - pseudoState = checkPseudoState(e); - if (pseudoState == PseudoLink) - return true; + if (e && e->isLink()) + return !m_matchVisitedPseudoClass; break; case CSSSelector::PseudoVisited: - if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) - pseudoState = checkPseudoState(e); - if (pseudoState == PseudoVisited) - return true; + if (e && e->isLink()) + return m_matchVisitedPseudoClass; break; case CSSSelector::PseudoDrag: { if (elementStyle) @@ -2410,15 +2457,8 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme } break; case CSSSelector::PseudoEnabled: - if (e && e->isFormControlElement()) { - InputElement* inputElement = toInputElement(e); - if (inputElement && inputElement->isInputTypeHidden()) - break; - // The UI spec states that you can't match :enabled unless you are an object that can - // "receive focus and be activated." We will limit matching of this pseudo-class to elements - // that are non-"hidden" controls. + if (e && e->isFormControlElement()) return e->isEnabledFormControl(); - } break; case CSSSelector::PseudoFullPageMedia: return e && e->document() && e->document()->isMediaDocument(); @@ -2426,16 +2466,8 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme case CSSSelector::PseudoDefault: return e && e->isDefaultButtonForForm(); case CSSSelector::PseudoDisabled: - if (e && e->isFormControlElement()) { - InputElement* inputElement = toInputElement(e); - if (inputElement && inputElement->isInputTypeHidden()) - break; - - // The UI spec states that you can't match :enabled unless you are an object that can - // "receive focus and be activated." We will limit matching of this pseudo-class to elements - // that are non-"hidden" controls. + if (e && e->isFormControlElement()) return !e->isEnabledFormControl(); - } break; case CSSSelector::PseudoReadOnly: { if (!e || !e->isFormControlElement()) @@ -2517,135 +2549,19 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme return false; } if (sel->m_match == CSSSelector::PseudoElement) { - if (!elementStyle) + if (!elementStyle && !m_collectRulesOnly) return false; - switch (sel->pseudoType()) { - // Pseudo-elements: - case CSSSelector::PseudoFirstLine: - dynamicPseudo = FIRST_LINE; - return true; - case CSSSelector::PseudoFirstLetter: - dynamicPseudo = FIRST_LETTER; - if (Document* doc = e->document()) - doc->setUsesFirstLetterRules(true); - return true; - case CSSSelector::PseudoSelection: - dynamicPseudo = SELECTION; - return true; - case CSSSelector::PseudoBefore: - dynamicPseudo = BEFORE; - return true; - case CSSSelector::PseudoAfter: - dynamicPseudo = AFTER; - return true; - case CSSSelector::PseudoFileUploadButton: - dynamicPseudo = FILE_UPLOAD_BUTTON; - return true; -#if ENABLE(DATALIST) - case CSSSelector::PseudoInputListButton: - dynamicPseudo = INPUT_LIST_BUTTON; - return true; -#endif - case CSSSelector::PseudoInputPlaceholder: - dynamicPseudo = INPUT_PLACEHOLDER; - return true; - case CSSSelector::PseudoSliderThumb: - dynamicPseudo = SLIDER_THUMB; - return true; - case CSSSelector::PseudoSearchCancelButton: - dynamicPseudo = SEARCH_CANCEL_BUTTON; - return true; - case CSSSelector::PseudoSearchDecoration: - dynamicPseudo = SEARCH_DECORATION; - return true; - case CSSSelector::PseudoSearchResultsDecoration: - dynamicPseudo = SEARCH_RESULTS_DECORATION; - return true; - case CSSSelector::PseudoSearchResultsButton: - dynamicPseudo = SEARCH_RESULTS_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsPanel: - dynamicPseudo = MEDIA_CONTROLS_PANEL; - return true; - case CSSSelector::PseudoMediaControlsMuteButton: - dynamicPseudo = MEDIA_CONTROLS_MUTE_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsPlayButton: - dynamicPseudo = MEDIA_CONTROLS_PLAY_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsTimelineContainer: - dynamicPseudo = MEDIA_CONTROLS_TIMELINE_CONTAINER; - return true; - case CSSSelector::PseudoMediaControlsVolumeSliderContainer: - dynamicPseudo = MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER; - return true; - case CSSSelector::PseudoMediaControlsCurrentTimeDisplay: - dynamicPseudo = MEDIA_CONTROLS_CURRENT_TIME_DISPLAY; - return true; - case CSSSelector::PseudoMediaControlsTimeRemainingDisplay: - dynamicPseudo = MEDIA_CONTROLS_TIME_REMAINING_DISPLAY; - return true; - case CSSSelector::PseudoMediaControlsTimeline: - dynamicPseudo = MEDIA_CONTROLS_TIMELINE; - return true; - case CSSSelector::PseudoMediaControlsVolumeSlider: - dynamicPseudo = MEDIA_CONTROLS_VOLUME_SLIDER; - return true; - case CSSSelector::PseudoMediaControlsSeekBackButton: - dynamicPseudo = MEDIA_CONTROLS_SEEK_BACK_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsSeekForwardButton: - dynamicPseudo = MEDIA_CONTROLS_SEEK_FORWARD_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsRewindButton: - dynamicPseudo = MEDIA_CONTROLS_REWIND_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsReturnToRealtimeButton: - dynamicPseudo = MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsToggleClosedCaptions: - dynamicPseudo = MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON; - return true; - case CSSSelector::PseudoMediaControlsStatusDisplay: - dynamicPseudo = MEDIA_CONTROLS_STATUS_DISPLAY; - return true; - case CSSSelector::PseudoMediaControlsFullscreenButton: - dynamicPseudo = MEDIA_CONTROLS_FULLSCREEN_BUTTON; - return true; - case CSSSelector::PseudoScrollbar: - dynamicPseudo = SCROLLBAR; - return true; - case CSSSelector::PseudoScrollbarButton: - dynamicPseudo = SCROLLBAR_BUTTON; - return true; - case CSSSelector::PseudoScrollbarCorner: - dynamicPseudo = SCROLLBAR_CORNER; - return true; - case CSSSelector::PseudoScrollbarThumb: - dynamicPseudo = SCROLLBAR_THUMB; - return true; - case CSSSelector::PseudoScrollbarTrack: - dynamicPseudo = SCROLLBAR_TRACK; - return true; - case CSSSelector::PseudoScrollbarTrackPiece: - dynamicPseudo = SCROLLBAR_TRACK_PIECE; - return true; - case CSSSelector::PseudoResizer: - dynamicPseudo = RESIZER; - return true; - case CSSSelector::PseudoInnerSpinButton: - dynamicPseudo = INNER_SPIN_BUTTON; - return true; - case CSSSelector::PseudoOuterSpinButton: - dynamicPseudo = OUTER_SPIN_BUTTON; - return true; - case CSSSelector::PseudoUnknown: - case CSSSelector::PseudoNotParsed: - default: - ASSERT_NOT_REACHED(); - break; + PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType()); + if (pseudoId == FIRST_LETTER) { + if (Document* document = e->document()) + document->setUsesFirstLetterRules(true); } + if (pseudoId != NOPSEUDO) { + dynamicPseudo = pseudoId; + return true; + } + ASSERT_NOT_REACHED(); return false; } // ### add the rest of the checks... @@ -2970,7 +2886,7 @@ static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isRese void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style) { - initElementAndPseudoState(0); + initElement(0); initForStyleResolve(0, style); m_style = style; applyProperty(id, value); @@ -5291,6 +5207,9 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyWebkitAnimationDuration: HANDLE_ANIMATION_VALUE(duration, Duration, value) return; + case CSSPropertyWebkitAnimationFillMode: + HANDLE_ANIMATION_VALUE(fillMode, FillMode, value) + return; case CSSPropertyWebkitAnimationIterationCount: HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value) return; @@ -5661,6 +5580,30 @@ void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* valu animation->setDuration(primitiveValue->getFloatValue()/1000.0f); } +void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value) +{ + if (value->cssValueType() == CSSValue::CSS_INITIAL) { + layer->setFillMode(Animation::initialAnimationFillMode()); + return; + } + + CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); + switch (primitiveValue->getIdent()) { + case CSSValueNone: + layer->setFillMode(AnimationFillModeNone); + break; + case CSSValueForwards: + layer->setFillMode(AnimationFillModeForwards); + break; + case CSSValueBackwards: + layer->setFillMode(AnimationFillModeBackwards); + break; + case CSSValueBoth: + layer->setFillMode(AnimationFillModeBoth); + break; + } +} + void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { @@ -5769,10 +5712,10 @@ void CSSStyleSelector::mapNinePieceImage(CSSValue* value, NinePieceImage& image) CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value); // Set the image (this kicks off the load). - image.m_image = styleImage(borderImage->imageValue()); + image.setImage(styleImage(borderImage->imageValue())); // Set up a length box to represent our image slices. - LengthBox& l = image.m_slices; + LengthBox l; Rect* r = borderImage->m_imageSliceRect.get(); if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) l.m_top = Length(r->top()->getDoubleValue(), Percent); @@ -5790,31 +5733,36 @@ void CSSStyleSelector::mapNinePieceImage(CSSValue* value, NinePieceImage& image) l.m_right = Length(r->right()->getDoubleValue(), Percent); else l.m_right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed); - + image.setSlices(l); + // Set the appropriate rules for stretch/round/repeat of the slices + ENinePieceImageRule horizontalRule; switch (borderImage->m_horizontalSizeRule) { case CSSValueStretch: - image.m_horizontalRule = StretchImageRule; + horizontalRule = StretchImageRule; break; case CSSValueRound: - image.m_horizontalRule = RoundImageRule; + horizontalRule = RoundImageRule; break; default: // CSSValueRepeat - image.m_horizontalRule = RepeatImageRule; + horizontalRule = RepeatImageRule; break; } + image.setHorizontalRule(horizontalRule); + ENinePieceImageRule verticalRule; switch (borderImage->m_verticalSizeRule) { case CSSValueStretch: - image.m_verticalRule = StretchImageRule; + verticalRule = StretchImageRule; break; case CSSValueRound: - image.m_verticalRule = RoundImageRule; + verticalRule = RoundImageRule; break; default: // CSSValueRepeat - image.m_verticalRule = RepeatImageRule; + verticalRule = RepeatImageRule; break; } + image.setVerticalRule(verticalRule); } void CSSStyleSelector::checkForTextSizeAdjust() @@ -6047,17 +5995,9 @@ Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveV if (ident) { if (ident == CSSValueWebkitText) col = m_element->document()->textColor(); - else if (ident == CSSValueWebkitLink) { - const Color& linkColor = m_element->document()->linkColor(); - const Color& visitedColor = m_element->document()->visitedLinkColor(); - if (linkColor == visitedColor) - col = linkColor; - else { - if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink) - pseudoState = m_checker.checkPseudoState(m_element); - col = (pseudoState == PseudoLink) ? linkColor : visitedColor; - } - } else if (ident == CSSValueWebkitActivelink) + else if (ident == CSSValueWebkitLink) + col = m_element->isLink() && m_checker.m_matchVisitedPseudoClass ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor(); + else if (ident == CSSValueWebkitActivelink) col = m_element->document()->activeLinkColor(); else if (ident == CSSValueWebkitFocusRingColor) col = RenderTheme::focusRingColor(); diff --git a/WebCore/css/CSSStyleSelector.h b/WebCore/css/CSSStyleSelector.h index 644051c..80a186b 100644 --- a/WebCore/css/CSSStyleSelector.h +++ b/WebCore/css/CSSStyleSelector.h @@ -85,12 +85,12 @@ public: bool strictParsing, bool matchAuthorAndUserStyles); ~CSSStyleSelector(); - void initElementAndPseudoState(Element*); + void initElement(Element*); void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO); - PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false); + PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, bool matchVisitedLinks = false); void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList& list); - PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId, Element*, RenderStyle* parentStyle = 0); + PassRefPtr<RenderStyle> pseudoStyleForElement(PseudoId, Element*, RenderStyle* parentStyle = 0, bool matchVisitedLinks = false); static PassRefPtr<RenderStyle> styleForDocument(Document*); @@ -110,7 +110,7 @@ public: public: // These methods will give back the set of rules that matched for a given element (or a pseudo-element). PassRefPtr<CSSRuleList> styleRulesForElement(Element*, bool authorOnly); - PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, const String& pseudoStyle, bool authorOnly); + PassRefPtr<CSSRuleList> pseudoStyleRulesForElement(Element*, PseudoId, bool authorOnly); // Given a CSS keyword in the range (xx-small to -webkit-xxx-large), this function will return // the correct font size scaled relative to the user's default (medium). @@ -196,11 +196,11 @@ public: SelectorChecker(Document*, bool strictParsing); bool checkSelector(CSSSelector*, Element*) const; - SelectorMatch checkSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const; - bool checkOneSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isAncestor, bool isSubSelector, RenderStyle*, RenderStyle* elementParentStyle) const; - PseudoState checkPseudoState(Element*, bool checkVisited = true) const; + 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; + EInsideLink determineLinkState(Element* element) const; void allVisitedStateChanged(); void visitedStateChanged(LinkHash visitedHash); @@ -209,6 +209,7 @@ public: bool m_collectRulesOnly; PseudoId m_pseudoStyle; bool m_documentIsHTML; + mutable bool m_matchVisitedPseudoClass; mutable HashSet<LinkHash, LinkHashHash> m_linksCheckedForVisitedState; }; @@ -235,6 +236,7 @@ public: void mapAnimationDelay(Animation*, CSSValue*); void mapAnimationDirection(Animation*, CSSValue*); void mapAnimationDuration(Animation*, CSSValue*); + void mapAnimationFillMode(Animation*, CSSValue*); void mapAnimationIterationCount(Animation*, CSSValue*); void mapAnimationName(Animation*, CSSValue*); void mapAnimationPlayState(Animation*, CSSValue*); @@ -278,7 +280,7 @@ public: CSSValue* m_lineHeightValue; bool m_fontDirty; bool m_matchAuthorAndUserStyles; - + RefPtr<CSSFontSelector> m_fontSelector; HashSet<AtomicStringImpl*> m_selectorAttrs; Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls; diff --git a/WebCore/css/CSSStyleSheet.cpp b/WebCore/css/CSSStyleSheet.cpp index 9c9aa18..fb25374 100644 --- a/WebCore/css/CSSStyleSheet.cpp +++ b/WebCore/css/CSSStyleSheet.cpp @@ -96,9 +96,24 @@ unsigned CSSStyleSheet::insertRule(const String& rule, unsigned index, Exception return 0; } - // ### - // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified index e.g. if an - //@import rule is inserted after a standard rule set or other at-rule. + // Throw a HIERARCHY_REQUEST_ERR exception if the rule cannot be inserted at the specified index. The best + // example of this is an @import rule inserted after regular rules. + if (index > 0) { + if (r->isImportRule()) { + // Check all the rules that come before this one to make sure they are only @charset and @import rules. + for (unsigned i = 0; i < index; ++i) { + if (!item(i)->isCharsetRule() && !item(i)->isImportRule()) { + ec = HIERARCHY_REQUEST_ERR; + return 0; + } + } + } else if (r->isCharsetRule()) { + // The @charset rule has to come first and there can be only one. + ec = HIERARCHY_REQUEST_ERR; + return 0; + } + } + insert(index, r.release()); styleSheetChanged(); diff --git a/WebCore/css/CSSValueKeywords.in b/WebCore/css/CSSValueKeywords.in index ca2a47a..09d969a 100644 --- a/WebCore/css/CSSValueKeywords.in +++ b/WebCore/css/CSSValueKeywords.in @@ -582,6 +582,7 @@ menulist-button menulist-text menulist-textfield outer-spin-button +progress-bar slider-horizontal slider-vertical sliderthumb-horizontal @@ -639,6 +640,13 @@ lines # alternate # +# CSS_PROP__WEBKIT_ANIMATION_FILL_MODE +# +# forwards +# backwards +# both + +# # CSS_PROP__WEBKIT_ANIMATION_ITERATION_COUNT # # infinite @@ -701,3 +709,9 @@ geometricPrecision # -webkit-color-correction #default sRGB + +# (-webkit-view-mode:) media feature: +mini +floating +application +fullscreen diff --git a/WebCore/css/FontFamilyValue.cpp b/WebCore/css/FontFamilyValue.cpp index 90a8c9d..ebe9645 100644 --- a/WebCore/css/FontFamilyValue.cpp +++ b/WebCore/css/FontFamilyValue.cpp @@ -21,44 +21,9 @@ #include "config.h" #include "FontFamilyValue.h" -namespace WebCore { - -// FIXME: This appears identical to isCSSTokenizerIdentifier from CSSPrimitiveValue.cpp, we should use a single function. -static bool isValidCSSIdentifier(const String& string) -{ - unsigned length = string.length(); - if (!length) - return false; - - const UChar* characters = string.characters(); - UChar c = characters[0]; - if (!(c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '-' || c >= 0x80)) - return false; - - for (unsigned i = 1; i < length; ++i) { - c = characters[i]; - if (!(c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c >= 0x80)) - return false; - } +#include "CSSParser.h" - return true; -} - -// Quotes the string if it needs quoting. -// We use single quotes because serialization code uses double quotes, and it's nice to -// avoid having to turn all the quote marks into " as we would have to. -static String quoteStringIfNeeded(const String& string) -{ - if (isValidCSSIdentifier(string)) - return string; - - // FIXME: Also need to transform control characters (00-1F) into \ sequences. - // FIXME: This is inefficient -- should use a Vector<UChar> instead. - String quotedString = string; - quotedString.replace('\\', "\\\\"); - quotedString.replace('\'', "\\'"); - return "'" + quotedString + "'"; -} +namespace WebCore { FontFamilyValue::FontFamilyValue(const String& familyName) : CSSPrimitiveValue(String(), CSS_STRING) @@ -101,7 +66,7 @@ void FontFamilyValue::appendSpaceSeparated(const UChar* characters, unsigned len String FontFamilyValue::cssText() const { - return quoteStringIfNeeded(m_familyName); + return quoteCSSStringIfNeeded(m_familyName); } } diff --git a/WebCore/css/MediaFeatureNames.cpp b/WebCore/css/MediaFeatureNames.cpp index a7799c1..85b8cbc 100644 --- a/WebCore/css/MediaFeatureNames.cpp +++ b/WebCore/css/MediaFeatureNames.cpp @@ -25,7 +25,7 @@ #endif #include "MediaFeatureNames.h" -#include "StaticConstructors.h" +#include <wtf/StaticConstructors.h> namespace WebCore { namespace MediaFeatureNames { diff --git a/WebCore/css/MediaFeatureNames.h b/WebCore/css/MediaFeatureNames.h index 2799004..8aaedb2 100644 --- a/WebCore/css/MediaFeatureNames.h +++ b/WebCore/css/MediaFeatureNames.h @@ -25,6 +25,13 @@ namespace WebCore { namespace MediaFeatureNames { +#if ENABLE(WIDGETS_10_SUPPORT) +#define CSS_MEDIAQUERY_NAMES_FOR_WIDGETS_10_MEDIAFEATURE(macro) \ + macro(view_mode, "-webkit-view-mode") +#else +#define CSS_MEDIAQUERY_NAMES_FOR_WIDGETS_10_MEDIAFEATURE(macro) +#endif + #define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \ macro(color, "color") \ macro(grid, "grid") \ @@ -59,6 +66,8 @@ namespace WebCore { macro(transform_3d, "-webkit-transform-3d") \ macro(transition, "-webkit-transition") \ macro(animation, "-webkit-animation") \ + CSS_MEDIAQUERY_NAMES_FOR_WIDGETS_10_MEDIAFEATURE(macro) + // end of macro #ifndef CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS diff --git a/WebCore/css/MediaQueryEvaluator.cpp b/WebCore/css/MediaQueryEvaluator.cpp index 4963ed4..ded40b5 100644 --- a/WebCore/css/MediaQueryEvaluator.cpp +++ b/WebCore/css/MediaQueryEvaluator.cpp @@ -29,6 +29,7 @@ #include "MediaQueryEvaluator.h" #include "Chrome.h" +#include "ChromeClient.h" #include "CSSPrimitiveValue.h" #include "CSSStyleSelector.h" #include "CSSValueList.h" @@ -47,7 +48,7 @@ #include "PlatformScreen.h" #include <wtf/HashMap.h> -#if ENABLE(3D_RENDERING) +#if ENABLE(3D_RENDERING) && USE(ACCELERATED_COMPOSITING) #include "RenderLayerCompositor.h" #endif @@ -474,8 +475,10 @@ static bool transform_3dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* f #if ENABLE(3D_RENDERING) bool threeDEnabled = false; +#if USE(ACCELERATED_COMPOSITING) if (RenderView* view = frame->contentRenderer()) threeDEnabled = view->compositor()->hasAcceleratedCompositing(); +#endif returnValueIfNoParameter = threeDEnabled; have3dRendering = threeDEnabled ? 1 : 0; @@ -492,6 +495,29 @@ static bool transform_3dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* f return returnValueIfNoParameter; } +#if ENABLE(WIDGETS_10_SUPPORT) +static bool view_modeMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +{ + if (value) { + String mode = static_cast<CSSPrimitiveValue*>(value)->getStringValue(); + if (ChromeClient* client = frame->page()->chrome()->client()) { + if (mode == "windowed" && client->isWindowed()) + return true; + if (mode == "floating" && client->isFloating()) + return true; + if (mode == "fullscreen" && client->isFullscreen()) + return true; + if (mode == "maximized" && client->isMaximized()) + return true; + if (mode == "minimized" && client->isMinimized()) + return true; + return false; + } + } + return true; +} +#endif + static void createFunctionMap() { // Create the table. diff --git a/WebCore/css/SVGCSSComputedStyleDeclaration.cpp b/WebCore/css/SVGCSSComputedStyleDeclaration.cpp index f184b1b..25da148 100644 --- a/WebCore/css/SVGCSSComputedStyleDeclaration.cpp +++ b/WebCore/css/SVGCSSComputedStyleDeclaration.cpp @@ -102,16 +102,16 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int pro case CSSPropertyWritingMode: return CSSPrimitiveValue::create(svgStyle->writingMode()); case CSSPropertyClipPath: - if (!svgStyle->clipPath().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->clipPath(), CSSPrimitiveValue::CSS_URI); + if (!svgStyle->clipperResource().isEmpty()) + return CSSPrimitiveValue::create(svgStyle->clipperResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyMask: - if (!svgStyle->maskElement().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->maskElement(), CSSPrimitiveValue::CSS_URI); + if (!svgStyle->maskerResource().isEmpty()) + return CSSPrimitiveValue::create(svgStyle->maskerResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyFilter: - if (!svgStyle->filter().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->filter(), CSSPrimitiveValue::CSS_URI); + if (!svgStyle->filterResource().isEmpty()) + return CSSPrimitiveValue::create(svgStyle->filterResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyFloodColor: return CSSPrimitiveValue::createColor(svgStyle->floodColor().rgb()); @@ -124,16 +124,16 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int pro case CSSPropertyKerning: return svgStyle->kerning(); case CSSPropertyMarkerEnd: - if (!svgStyle->endMarker().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->endMarker(), CSSPrimitiveValue::CSS_URI); + if (!svgStyle->markerEndResource().isEmpty()) + return CSSPrimitiveValue::create(svgStyle->markerEndResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyMarkerMid: - if (!svgStyle->midMarker().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->midMarker(), CSSPrimitiveValue::CSS_URI); + if (!svgStyle->markerMidResource().isEmpty()) + return CSSPrimitiveValue::create(svgStyle->markerMidResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyMarkerStart: - if (!svgStyle->startMarker().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->startMarker(), CSSPrimitiveValue::CSS_URI); + if (!svgStyle->markerStartResource().isEmpty()) + return CSSPrimitiveValue::create(svgStyle->markerStartResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyStroke: return svgStyle->strokePaint(); diff --git a/WebCore/css/SVGCSSStyleSelector.cpp b/WebCore/css/SVGCSSStyleSelector.cpp index 5651a0a..75d48b7 100644 --- a/WebCore/css/SVGCSSStyleSelector.cpp +++ b/WebCore/css/SVGCSSStyleSelector.cpp @@ -58,7 +58,6 @@ HANDLE_INHERIT(prop, Prop) \ else if (isInitial) \ svgstyle->set##Prop(SVGRenderStyle::initial##Prop()); - namespace WebCore { static float roundToNearestGlyphOrientationAngle(float angle) @@ -321,7 +320,7 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) } case CSSPropertyMarkerStart: { - HANDLE_INHERIT_AND_INITIAL(startMarker, StartMarker) + HANDLE_INHERIT_AND_INITIAL(markerStartResource, MarkerStartResource) if (!primitiveValue) return; @@ -332,12 +331,12 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) else return; - svgstyle->setStartMarker(SVGURIReference::getTarget(s)); + svgstyle->setMarkerStartResource(SVGURIReference::getTarget(s)); break; } case CSSPropertyMarkerMid: { - HANDLE_INHERIT_AND_INITIAL(midMarker, MidMarker) + HANDLE_INHERIT_AND_INITIAL(markerMidResource, MarkerMidResource) if (!primitiveValue) return; @@ -348,12 +347,12 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) else return; - svgstyle->setMidMarker(SVGURIReference::getTarget(s)); + svgstyle->setMarkerMidResource(SVGURIReference::getTarget(s)); break; } case CSSPropertyMarkerEnd: { - HANDLE_INHERIT_AND_INITIAL(endMarker, EndMarker) + HANDLE_INHERIT_AND_INITIAL(markerEndResource, MarkerEndResource) if (!primitiveValue) return; @@ -364,7 +363,7 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) else return; - svgstyle->setEndMarker(SVGURIReference::getTarget(s)); + svgstyle->setMarkerEndResource(SVGURIReference::getTarget(s)); break; } case CSSPropertyStrokeLinecap: @@ -392,7 +391,7 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) } case CSSPropertyFilter: { - HANDLE_INHERIT_AND_INITIAL(filter, Filter) + HANDLE_INHERIT_AND_INITIAL(filterResource, FilterResource) if (!primitiveValue) return; @@ -402,12 +401,13 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) s = primitiveValue->getStringValue(); else return; - svgstyle->setFilter(SVGURIReference::getTarget(s)); + + svgstyle->setFilterResource(SVGURIReference::getTarget(s)); break; } case CSSPropertyMask: { - HANDLE_INHERIT_AND_INITIAL(maskElement, MaskElement) + HANDLE_INHERIT_AND_INITIAL(maskerResource, MaskerResource) if (!primitiveValue) return; @@ -417,13 +417,13 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) s = primitiveValue->getStringValue(); else return; - - svgstyle->setMaskElement(SVGURIReference::getTarget(s)); + + svgstyle->setMaskerResource(SVGURIReference::getTarget(s)); break; } case CSSPropertyClipPath: { - HANDLE_INHERIT_AND_INITIAL(clipPath, ClipPath) + HANDLE_INHERIT_AND_INITIAL(clipperResource, ClipperResource) if (!primitiveValue) return; @@ -434,7 +434,7 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) else return; - svgstyle->setClipPath(SVGURIReference::getTarget(s)); + svgstyle->setClipperResource(SVGURIReference::getTarget(s)); break; } case CSSPropertyTextAnchor: diff --git a/WebCore/css/html.css b/WebCore/css/html.css index 9d9225c..3f7818e 100644 --- a/WebCore/css/html.css +++ b/WebCore/css/html.css @@ -72,7 +72,7 @@ layer { display: block } -article, aside, footer, header, nav, section { +article, aside, footer, header, hgroup, nav, section { display: block } @@ -515,6 +515,20 @@ option { font-weight: normal; } +/* progress */ + +progress { + -webkit-appearance: progress-bar; + display: inline-block; + height: 1em; + width: 10em; + vertical-align: -0.2em; +} + +progress::-webkit-progress-bar { + -webkit-appearance: progress-bar; +} + /* datagrid */ datagrid { diff --git a/WebCore/css/make-css-file-arrays.pl b/WebCore/css/make-css-file-arrays.pl index 05c8fd1..dad530c 100755 --- a/WebCore/css/make-css-file-arrays.pl +++ b/WebCore/css/make-css-file-arrays.pl @@ -23,14 +23,6 @@ use strict; use Getopt::Long; -my $preprocessor; - -GetOptions('preprocessor=s' => \$preprocessor); - -if (!$preprocessor) { - $preprocessor = "/usr/bin/gcc -E -P -x c++"; -} - my $header = $ARGV[0]; shift; @@ -48,7 +40,7 @@ for my $in (@ARGV) { my $name = $1; # Slurp in the CSS file. - open IN, $preprocessor . " " . $in . "|" or die; + open IN, "<", $in or die; my $text; { local $/; $text = <IN>; } close IN; diff --git a/WebCore/css/mathml.css b/WebCore/css/mathml.css index b56a24b..8b4da3e 100644 --- a/WebCore/css/mathml.css +++ b/WebCore/css/mathml.css @@ -1,7 +1,7 @@ @namespace "http://www.w3.org/1998/Math/MathML"; math { - font-family: Symbol, STIXGeneral, "Times New Roman"; + font-family: Symbol, "Times New Roman"; display: inline-block; padding: 0px; margin: 0px; diff --git a/WebCore/css/mediaControlsQt.css b/WebCore/css/mediaControlsQt.css index a9c3609..d49fe96 100644 --- a/WebCore/css/mediaControlsQt.css +++ b/WebCore/css/mediaControlsQt.css @@ -51,8 +51,6 @@ video:-webkit-full-page-media::-webkit-media-controls-panel { } audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { - left: auto; - right: 5px; width: 12px; height: 12px; padding: 6px; @@ -60,7 +58,6 @@ audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-bu } audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { - left: 5px; width: 9px; height: 12px; padding: 6px 12px 6px 11px; @@ -72,7 +69,21 @@ audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls- } audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display { - display: none; + -webkit-appearance: media-current-time-display; + -webkit-user-select: none; + display: inline-block; + height: 12px; + padding: 6px; + margin: 5px 3px; + + overflow: hidden; + cursor: default; + + text-align: center; + font-size: 10px; + font-family: Verdana; + font-weight: bold; + color: white; } audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display { @@ -80,51 +91,38 @@ audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-contr } audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline { - left: 42px; - right: 34px; height: 12px; padding: 6px 8px; - margin: 5px 0px; + margin: 5px 3px; } audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container { - display: none; + -webkit-appearance: media-volume-slider-container; + position: absolute; + height: 103px; + width: 24px; } audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider { - display: none; + -webkit-appearance: media-volume-slider; + display: inline; + position: absolute; + + width: 12px; + padding: 6px; + height: 88px; + margin: 0 0 3px 0; } audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button { - /* Since MediaControlElements are always created with a renderer we have to hide - the controls we don't use, so they don't mess up activation and event handling */ - left: 0px; - top: 0px; - width: 0px; - height: 0px; - display: none; } audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button { - /* Since MediaControlElements are always created with a renderer we have to hide - the controls we don't use, so they don't mess up activation and event handling */ - left: 0px; - top: 0px; - width: 0px; - height: 0px; - display: none; } audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button { - /* Since MediaControlElements are always created with a renderer we have to hide - the controls we don't use, so they don't mess up activation and event handling */ - left: 0px; - top: 0px; - width: 0px; - height: 0px; - display: none; } @@ -136,3 +134,7 @@ audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-co display: none; } +audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button { + display: none; +} + diff --git a/WebCore/css/themeQtMaemo5.css b/WebCore/css/themeQtMaemo5.css new file mode 100644 index 0000000..c568d5d --- /dev/null +++ b/WebCore/css/themeQtMaemo5.css @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +input[type="button"], +input[type="submit"], +input[type="reset"], +input[type="file"]::-webkit-file-upload-button, button, +select { + padding: 2px 18px 3px 18px; + border: 1px solid black; + -webkit-border-radius:5px; + background-color: ButtonFace; +} + +input[type="button"]:disabled, +input[type="submit"]:disabled, +input[type="reset"]:disabled, +input[type="file"]:disabled::-webkit-file-upload-button, +button:disabled, +select:disabled { + border: 1px solid gray; +} + +input[type="button"]:active, +input[type="submit"]:active, +input[type="reset"]:active, +input[type="file"]:active::-webkit-file-upload-button, +button:active, +select:active{ + background-color: ButtonShadow; +} + +input[type="button"]:active:disabled, +input[type="submit"]:active:disabled, +input[type="reset"]:active:disabled, +input[type="file"]:active:disabled::-webkit-file-upload-button, +button:active:disabled, +select:active:disabled { + border: 1px solid gray; +} + +input:not([type]), +input[type="text"], +input[type="password"], +textarea { + border: 1px solid black; +} + +input:not([type]):disabled, +input[type="text"]:disabled, +input[type="password"]:disabled, +textarea:disabled { + border: 1px solid grey; + background-color:ButtonHighlight; +} + +input:not([type]):active, +input[type="text"]:active, +input[type="password"]:active, +textarea:active { + background-color:ButtonShadow; +} diff --git a/WebCore/css/themeQtNoListboxes.css b/WebCore/css/themeQtNoListboxes.css new file mode 100644 index 0000000..4c5e44a --- /dev/null +++ b/WebCore/css/themeQtNoListboxes.css @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +select[size], +select[multiple], +select[size][multiple] { + -webkit-appearance: menulist; + -webkit-box-align: center; + border: 1px solid; + -webkit-border-radius: 5px; + white-space: pre; +} diff --git a/WebCore/css/tokenizer.flex b/WebCore/css/tokenizer.flex index 1569ee2..3af725c 100644 --- a/WebCore/css/tokenizer.flex +++ b/WebCore/css/tokenizer.flex @@ -24,13 +24,13 @@ url ([!#$%&*-~]|{nonascii}|{escape})* w [ \t\r\n\f]* nl \n|\r\n|\r|\f range \?{1,6}|{h}(\?{0,5}|{h}(\?{0,4}|{h}(\?{0,3}|{h}(\?{0,2}|{h}(\??|{h}))))) -nth (-?[0-9]*n[\+-][0-9]+)|(-?[0-9]*n) +nth [\+-]?{intnum}*n([\+-]{intnum})? %% -\/\*[^*]*\*+([^/*][^*]*\*+)*\/ /* ignore comments */ +\/\*[^*]*\*+([^/*][^*]*\*+)*\/ {countLines(); /* ignore comments */ } -[ \t\r\n\f]+ {yyTok = WHITESPACE; return yyTok;} +[ \t\r\n\f]+ {countLines(); yyTok = WHITESPACE; return yyTok;} "<!--" {yyTok = SGML_CD; return yyTok;} "-->" {yyTok = SGML_CD; return yyTok;} |