diff options
Diffstat (limited to 'Source/WebCore/css')
58 files changed, 2032 insertions, 719 deletions
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp index 586c133ea..1e6d2079a 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -34,7 +34,6 @@ #include "CSSParser.h" #include "CSSPrimitiveValue.h" #include "CSSPrimitiveValueMappings.h" -#include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSReflectValue.h" #include "CSSSelector.h" @@ -905,6 +904,10 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObj break; } #if ENABLE(CSS_SHADERS) + case FilterOperation::VALIDATED_CUSTOM: + // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle. + ASSERT_NOT_REACHED(); + break; case FilterOperation::CUSTOM: { CustomFilterOperation* customOperation = static_cast<CustomFilterOperation*>(filterOperation); filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::CustomFilterOperation); @@ -921,27 +924,29 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObj shadersList->append(cssValuePool().createIdentifierValue(CSSValueNone)); const CustomFilterProgramMixSettings mixSettings = program->mixSettings(); - if (program->programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) { - RefPtr<WebKitCSSMixFunctionValue> mixFunction = WebKitCSSMixFunctionValue::create(); - mixFunction->append(program->fragmentShader()->cssValue()); - mixFunction->append(cssValuePool().createValue(mixSettings.blendMode)); - mixFunction->append(cssValuePool().createValue(mixSettings.compositeOperator)); - shadersList->append(mixFunction.release()); - } else if (program->fragmentShader()) - shadersList->append(program->fragmentShader()->cssValue()); + if (program->fragmentShader()) { + if (program->programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) { + RefPtr<WebKitCSSMixFunctionValue> mixFunction = WebKitCSSMixFunctionValue::create(); + mixFunction->append(program->fragmentShader()->cssValue()); + mixFunction->append(cssValuePool().createValue(mixSettings.blendMode)); + mixFunction->append(cssValuePool().createValue(mixSettings.compositeOperator)); + shadersList->append(mixFunction.release()); + } else + shadersList->append(program->fragmentShader()->cssValue()); + } else shadersList->append(cssValuePool().createIdentifierValue(CSSValueNone)); filterValue->append(shadersList.release()); RefPtr<CSSValueList> meshParameters = CSSValueList::createSpaceSeparated(); - meshParameters->append(cssValuePool().createValue(customOperation->meshRows(), CSSPrimitiveValue::CSS_NUMBER)); meshParameters->append(cssValuePool().createValue(customOperation->meshColumns(), CSSPrimitiveValue::CSS_NUMBER)); + meshParameters->append(cssValuePool().createValue(customOperation->meshRows(), CSSPrimitiveValue::CSS_NUMBER)); meshParameters->append(cssValuePool().createValue(customOperation->meshBoxType())); // FIXME: The specification doesn't have any "attached" identifier. Should we add one? // https://bugs.webkit.org/show_bug.cgi?id=72700 - if (customOperation->meshType() == CustomFilterOperation::DETACHED) + if (customOperation->meshType() == MeshTypeDetached) meshParameters->append(cssValuePool().createIdentifierValue(CSSValueDetached)); filterValue->append(meshParameters.release()); @@ -2133,7 +2138,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyWordWrap: return cssValuePool().createValue(style->overflowWrap()); case CSSPropertyWebkitLineBreak: - return cssValuePool().createValue(style->khtmlLineBreak()); + return cssValuePool().createValue(style->lineBreak()); case CSSPropertyWebkitNbspMode: return cssValuePool().createValue(style->nbspMode()); case CSSPropertyResize: @@ -2644,6 +2649,14 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert #endif break; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case CSSPropertyMaxZoom: + case CSSPropertyMinZoom: + case CSSPropertyOrientation: + case CSSPropertyUserZoom: + break; +#endif + #if ENABLE(SVG) case CSSPropertyClipPath: case CSSPropertyClipRule: @@ -2724,20 +2737,20 @@ String CSSComputedStyleDeclaration::item(unsigned i) const return getPropertyNameString(computedProperties[i]); } -bool CSSComputedStyleDeclaration::cssPropertyMatches(const CSSProperty* property) const +bool CSSComputedStyleDeclaration::cssPropertyMatches(const StylePropertySet::PropertyReference& property) const { - if (property->id() == CSSPropertyFontSize && property->value()->isPrimitiveValue() && m_node) { + if (property.id() == CSSPropertyFontSize && property.value()->isPrimitiveValue() && m_node) { m_node->document()->updateLayoutIgnorePendingStylesheets(); RenderStyle* style = m_node->computedStyle(m_pseudoElementSpecifier); if (style && style->fontDescription().keywordSize()) { int sizeValue = cssIdentifierForFontSizeKeyword(style->fontDescription().keywordSize()); - CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(property->value()); + const CSSPrimitiveValue* primitiveValue = static_cast<const CSSPrimitiveValue*>(property.value()); if (primitiveValue->isIdent() && primitiveValue->getIdent() == sizeValue) return true; } } - RefPtr<CSSValue> value = getPropertyCSSValue(property->id()); - return value && value->cssText() == property->value()->cssText(); + RefPtr<CSSValue> value = getPropertyCSSValue(property.id()); + return value && value->cssText() == property.value()->cssText(); } PassRefPtr<StylePropertySet> CSSComputedStyleDeclaration::copy() const diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.h b/Source/WebCore/css/CSSComputedStyleDeclaration.h index cfc837b9f..6b239e956 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.h +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.h @@ -95,7 +95,7 @@ private: virtual String getPropertyValueInternal(CSSPropertyID); virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionCode&); - virtual bool cssPropertyMatches(const CSSProperty*) const; + virtual bool cssPropertyMatches(const StylePropertySet::PropertyReference&) const OVERRIDE; PassRefPtr<CSSValue> valueForShadow(const ShadowData*, CSSPropertyID, const RenderStyle*) const; PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(RenderStyle*, const Color&) const; diff --git a/Source/WebCore/css/CSSCursorImageValue.cpp b/Source/WebCore/css/CSSCursorImageValue.cpp index 06d93ea60..0faa813b1 100644 --- a/Source/WebCore/css/CSSCursorImageValue.cpp +++ b/Source/WebCore/css/CSSCursorImageValue.cpp @@ -56,8 +56,9 @@ static inline SVGCursorElement* resourceReferencedByCursorElement(const String& } #endif -CSSCursorImageValue::CSSCursorImageValue(const String& url, const IntPoint& hotSpot) +CSSCursorImageValue::CSSCursorImageValue(const String& url, bool hasHotSpot, const IntPoint& hotSpot) : CSSImageValue(CursorImageClass, url) + , m_hasHotSpot(hasHotSpot) , m_hotSpot(hotSpot) { } @@ -80,6 +81,19 @@ CSSCursorImageValue::~CSSCursorImageValue() #endif } +String CSSCursorImageValue::customCssText() const +{ + StringBuilder result; + result.append(CSSImageValue::customCssText()); + if (m_hasHotSpot) { + result.append(' '); + result.appendNumber(m_hotSpot.x()); + result.append(' '); + result.appendNumber(m_hotSpot.y()); + } + return result.toString(); +} + bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element) { #if !ENABLE(SVG) @@ -94,6 +108,7 @@ bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element) if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url(), element->document())) { // FIXME: This will override hot spot specified in CSS, which is probably incorrect. SVGLengthContext lengthContext(0); + m_hasHotSpot = true; float x = roundf(cursorElement->x().value(lengthContext)); m_hotSpot.setX(static_cast<int>(x)); diff --git a/Source/WebCore/css/CSSCursorImageValue.h b/Source/WebCore/css/CSSCursorImageValue.h index dc8d1ff4c..80d3f15e0 100644 --- a/Source/WebCore/css/CSSCursorImageValue.h +++ b/Source/WebCore/css/CSSCursorImageValue.h @@ -32,14 +32,23 @@ class SVGElement; class CSSCursorImageValue : public CSSImageValue { public: - static PassRefPtr<CSSCursorImageValue> create(const String& url, const IntPoint& hotSpot) + static PassRefPtr<CSSCursorImageValue> create(const String& url, bool hasHotSpot, const IntPoint& hotSpot) { - return adoptRef(new CSSCursorImageValue(url, hotSpot)); + return adoptRef(new CSSCursorImageValue(url, hasHotSpot, hotSpot)); } ~CSSCursorImageValue(); - IntPoint hotSpot() const { return m_hotSpot; } + bool hasHotSpot() const { return m_hasHotSpot; } + + IntPoint hotSpot() const + { + if (m_hasHotSpot) + return m_hotSpot; + return IntPoint(-1, -1); + } + + String customCssText() const; bool updateIfSVGCursorIsUsed(Element*); StyleCachedImage* cachedImage(CachedResourceLoader*); @@ -51,8 +60,9 @@ public: void reportDescendantMemoryUsage(MemoryObjectInfo*) const; private: - CSSCursorImageValue(const String& url, const IntPoint& hotSpot); + CSSCursorImageValue(const String& url, bool hasHotSpot, const IntPoint& hotSpot); + bool m_hasHotSpot; IntPoint m_hotSpot; #if ENABLE(SVG) diff --git a/Source/WebCore/css/CSSFontFaceSource.cpp b/Source/WebCore/css/CSSFontFaceSource.cpp index 5e5289f6d..2fd63f6fa 100644 --- a/Source/WebCore/css/CSSFontFaceSource.cpp +++ b/Source/WebCore/css/CSSFontFaceSource.cpp @@ -106,7 +106,8 @@ PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& #endif ) { // We're local. Just return a SimpleFontData from the normal cache. - return fontCache()->getCachedFontData(fontDescription, m_string); + // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter. + return fontCache()->getCachedFontData(fontDescription, m_string, true); } // See if we have a mapping in our FontData cache. diff --git a/Source/WebCore/css/CSSGrammar.y.in b/Source/WebCore/css/CSSGrammar.y.in index 4b894fb95..9eedcc394 100644 --- a/Source/WebCore/css/CSSGrammar.y.in +++ b/Source/WebCore/css/CSSGrammar.y.in @@ -3,6 +3,7 @@ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2012 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -95,6 +96,9 @@ static inline int cssyyerror(void*, const char*) %token SUPPORTS_SYM #endif %token FONT_FACE_SYM +#if ENABLE_SHADOW_DOM +%token HOST_SYM +#endif %token CHARSET_SYM %token NAMESPACE_SYM %token VARFUNCTION @@ -106,6 +110,7 @@ static inline int cssyyerror(void*, const char*) %token WEBKIT_MEDIAQUERY_SYM %token WEBKIT_SELECTOR_SYM %token WEBKIT_REGION_RULE_SYM +%token WEBKIT_VIEWPORT_RULE_SYM %token <marginBox> TOPLEFTCORNER_SYM %token <marginBox> TOPLEFT_SYM %token <marginBox> TOPCENTER_SYM @@ -187,6 +192,9 @@ static inline int cssyyerror(void*, const char*) %type <rule> page %type <rule> margin_box %type <rule> font_face +#if ENABLE_SHADOW_DOM +%type <rule> host +#endif %type <rule> keyframes %type <rule> invalid_rule %type <rule> save_block @@ -200,6 +208,9 @@ static inline int cssyyerror(void*, const char*) #if ENABLE_CSS3_CONDITIONAL_RULES %type <rule> supports #endif +#if ENABLE_CSS_DEVICE_ADAPTATION +%type <rule> viewport +#endif %type <string> maybe_ns_prefix @@ -402,6 +413,12 @@ valid_rule: #if ENABLE_CSS3_CONDITIONAL_RULES | supports #endif +#if ENABLE_SHADOW_DOM + | host +#endif +#if ENABLE_CSS_DEVICE_ADAPTATION + | viewport +#endif ; rule: @@ -430,6 +447,9 @@ block_valid_rule: | page | font_face | keyframes +#if ENABLE_CSS_DEVICE_ADAPTATION + | viewport +#endif ; block_rule: @@ -901,6 +921,52 @@ font_face: } ; +#if ENABLE_SHADOW_DOM +before_host_rule: + /* empty */ { + parser->markRuleHeaderStart(CSSRuleSourceData::HOST_RULE); + } + ; + +host: + before_host_rule HOST_SYM at_rule_header_end_maybe_space + '{' at_rule_body_start maybe_space block_rule_list save_block { + $$ = parser->createHostRule($7); + } + | before_host_rule HOST_SYM at_rule_header_end_maybe_space ';' { + $$ = 0; + parser->popRuleData(); + } + ; +#endif + +#if ENABLE_CSS_DEVICE_ADAPTATION +before_viewport_rule: + /* empty */ { + parser->markViewportRuleBodyStart(); + parser->markRuleHeaderStart(CSSRuleSourceData::VIEWPORT_RULE); + } + ; + +viewport: + before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM at_rule_header_end_maybe_space + '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { + $$ = parser->createViewportRule(); + parser->markViewportRuleBodyEnd(); + } + | before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM error invalid_block { + $$ = 0; + parser->popRuleData(); + parser->markViewportRuleBodyEnd(); + } + | before_viewport_rule WEBKIT_VIEWPORT_RULE_SYM error ';' { + $$ = 0; + parser->popRuleData(); + parser->markViewportRuleBodyEnd(); + } +; +#endif + region_selector: selector_list { if ($1) { @@ -1241,7 +1307,9 @@ pseudo: $3.lower(); $$->setValue($3); // FIXME: This call is needed to force selector to compute the pseudoType early enough. - $$->pseudoType(); + CSSSelector::PseudoType type = $$->pseudoType(); + if (type == CSSSelector::PseudoUnknown) + $$ = 0; } // use by :-webkit-any. // FIXME: should we support generic selectors here or just simple_selectors? diff --git a/Source/WebCore/css/CSSImageGeneratorValue.cpp b/Source/WebCore/css/CSSImageGeneratorValue.cpp index 8cf47f06d..6c460a768 100644 --- a/Source/WebCore/css/CSSImageGeneratorValue.cpp +++ b/Source/WebCore/css/CSSImageGeneratorValue.cpp @@ -36,6 +36,15 @@ #include <wtf/MemoryInstrumentationHashMap.h> #include <wtf/text/WTFString.h> + +namespace WTF { + +template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RenderObject*> { + template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } +}; + +} + namespace WebCore { CSSImageGeneratorValue::CSSImageGeneratorValue(ClassType classType) diff --git a/Source/WebCore/css/CSSImageSetValue.cpp b/Source/WebCore/css/CSSImageSetValue.cpp index 6dc76f580..f7d401f5c 100644 --- a/Source/WebCore/css/CSSImageSetValue.cpp +++ b/Source/WebCore/css/CSSImageSetValue.cpp @@ -140,7 +140,32 @@ StyleImage* CSSImageSetValue::cachedOrPendingImageSet(Document* document) String CSSImageSetValue::customCssText() const { - return "-webkit-image-set(" + CSSValueList::customCssText() + ")"; + StringBuilder result; + result.append("-webkit-image-set("); + + size_t length = this->length(); + size_t i = 0; + while (i < length) { + if (i > 0) + result.append(", "); + + const CSSValue* imageValue = item(i); + result.append(imageValue->cssText()); + result.append(' '); + + ++i; + ASSERT(i < length); + const CSSValue* scaleFactorValue = item(i); + result.append(scaleFactorValue->cssText()); + // FIXME: Eventually the scale factor should contain it's own unit http://wkb.ug/100120. + // For now 'x' is hard-coded in the parser, so we hard-code it here too. + result.append('x'); + + ++i; + } + + result.append(")"); + return result.toString(); } bool CSSImageSetValue::hasFailedOrCanceledSubresources() const diff --git a/Source/WebCore/css/CSSImportRule.cpp b/Source/WebCore/css/CSSImportRule.cpp index 3bbe650a5..8697f668f 100644 --- a/Source/WebCore/css/CSSImportRule.cpp +++ b/Source/WebCore/css/CSSImportRule.cpp @@ -69,8 +69,11 @@ String CSSImportRule::cssText() const result.append("\")"); if (m_importRule->mediaQueries()) { - result.append(' '); - result.append(m_importRule->mediaQueries()->mediaText()); + String mediaText = m_importRule->mediaQueries()->mediaText(); + if (!mediaText.isEmpty()) { + result.append(' '); + result.append(mediaText); + } } result.append(';'); diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index d16537e6c..8ff97b8e9 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -6,6 +6,7 @@ * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2012 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -43,7 +44,6 @@ #include "CSSMediaRule.h" #include "CSSPageRule.h" #include "CSSPrimitiveValue.h" -#include "CSSProperty.h" #include "CSSPropertySourceData.h" #include "CSSReflectValue.h" #include "CSSSelector.h" @@ -53,7 +53,6 @@ #include "CSSValueKeywords.h" #include "CSSValueList.h" #include "CSSValuePool.h" -#include "StylePropertyShorthand.h" #if ENABLE(CSS_VARIABLES) #include "CSSVariableValue.h" #endif @@ -271,6 +270,9 @@ CSSParser::CSSParser(const CSSParserContext& context) , m_lastSelectorLineNumber(0) , m_allowImportRules(true) , m_allowNamespaceDeclarations(true) +#if ENABLE(CSS_DEVICE_ADAPTATION) + , m_inViewport(false) +#endif , m_selectorVector(adoptPtr(new CSSSelectorVector)) { #if YYDEBUG > 0 @@ -337,11 +339,12 @@ AtomicString CSSParserString::lowerSubstring(unsigned position, unsigned length) return AtomicString(result); } -void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix) +void CSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength) { - m_parsedTextPrefixLength = strlen(prefix); + m_parsedTextPrefixLength = prefixLength; unsigned stringLength = string.length(); - unsigned length = stringLength + m_parsedTextPrefixLength + strlen(suffix) + 1; + unsigned length = stringLength + m_parsedTextPrefixLength + suffixLength + 1; + m_length = length; if (!stringLength || string.is8Bit()) { m_dataStart8 = adoptArrayPtr(new LChar[length]); @@ -352,7 +355,7 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char memcpy(m_dataStart8.get() + m_parsedTextPrefixLength, string.characters8(), stringLength * sizeof(LChar)); unsigned start = m_parsedTextPrefixLength + stringLength; - unsigned end = start + strlen(suffix); + unsigned end = start + suffixLength; for (unsigned i = start; i < end; i++) m_dataStart8[i] = suffix[i - start]; @@ -362,7 +365,6 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char m_currentCharacter8 = m_dataStart8.get(); m_currentCharacter16 = 0; setTokenStart<LChar>(m_currentCharacter8); - m_length = length; m_lexFunc = &CSSParser::realLex<LChar>; return; } @@ -374,7 +376,7 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char memcpy(m_dataStart16.get() + m_parsedTextPrefixLength, string.characters(), stringLength * sizeof(UChar)); unsigned start = m_parsedTextPrefixLength + stringLength; - unsigned end = start + strlen(suffix); + unsigned end = start + suffixLength; for (unsigned i = start; i < end; i++) m_dataStart16[i] = suffix[i - start]; @@ -384,7 +386,6 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char m_currentCharacter8 = 0; m_currentCharacter16 = m_dataStart16.get(); setTokenStart<UChar>(m_currentCharacter16); - m_length = length; m_lexFunc = &CSSParser::realLex<UChar>; } @@ -829,8 +830,8 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int if (valueID == CSSValueNone || valueID == CSSValueEdges) return true; break; - case CSSPropertyWebkitLineBreak: // normal | after-white-space - if (valueID == CSSValueNormal || valueID == CSSValueAfterWhiteSpace) + case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space + if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace) return true; break; case CSSPropertyWebkitLineSnap: @@ -1572,7 +1573,7 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode case CSSPrimitiveValue::CSS_TURN: b = (unitflags & FAngle); break; -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSSPrimitiveValue::CSS_DPPX: case CSSPrimitiveValue::CSS_DPI: case CSSPrimitiveValue::CSS_DPCM: @@ -1601,8 +1602,8 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSP ASSERT(isCalculation(value)); return CSSPrimitiveValue::create(m_parsedCalculation.release()); } - -#if ENABLE(CSS_IMAGE_RESOLUTION) + +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS) || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN) @@ -1664,7 +1665,7 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifi return createPrimitiveNumericValue(value); if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN) return createPrimitiveNumericValue(value); -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM) return createPrimitiveNumericValue(value); #endif @@ -1729,6 +1730,11 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return true; } +#if ENABLE(CSS_DEVICE_ADAPTATION) + if (inViewport()) + return parseViewportProperty(propId, important); +#endif + bool validPrimitive = false; RefPtr<CSSValue> parsedValue; @@ -1876,15 +1882,18 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) coords.append(int(value->fValue)); value = m_valueList->next(); } + bool hasHotSpot = false; IntPoint hotSpot(-1, -1); int nrcoords = coords.size(); if (nrcoords > 0 && nrcoords != 2) return false; - if (nrcoords == 2) + if (nrcoords == 2) { + hasHotSpot = true; hotSpot = IntPoint(coords[0], coords[1]); + } if (!uri.isNull()) - list->append(CSSCursorImageValue::create(completeURL(uri), hotSpot)); + list->append(CSSCursorImageValue::create(completeURL(uri), hasHotSpot, hotSpot)); if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ','))) return false; @@ -2853,6 +2862,17 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) // These properties should be handled before in isValidKeywordPropertyAndValue(). ASSERT_NOT_REACHED(); return false; +#if ENABLE(CSS_DEVICE_ADAPTATION) + // Properties bellow are validated inside parseViewportProperty, because we + // check for parser state inViewportScope. We need to invalidate if someone + // adds them outside a @viewport rule. + case CSSPropertyMaxZoom: + case CSSPropertyMinZoom: + case CSSPropertyOrientation: + case CSSPropertyUserZoom: + validPrimitive = false; + break; +#endif #if ENABLE(SVG) default: return parseSVGValue(propId, important); @@ -7210,76 +7230,241 @@ public: , m_allowSingleArgument(false) , m_unit(CSSParser::FUnknown) { - if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "scalex(") || equalIgnoringCase(name, "scaley(") || equalIgnoringCase(name, "scalez(")) { - m_unit = CSSParser::FNumber; - if (equalIgnoringCase(name, "scale(")) - m_type = WebKitCSSTransformValue::ScaleTransformOperation; - else if (equalIgnoringCase(name, "scalex(")) - m_type = WebKitCSSTransformValue::ScaleXTransformOperation; - else if (equalIgnoringCase(name, "scaley(")) - m_type = WebKitCSSTransformValue::ScaleYTransformOperation; - else - m_type = WebKitCSSTransformValue::ScaleZTransformOperation; - } else if (equalIgnoringCase(name, "scale3d(")) { - m_type = WebKitCSSTransformValue::Scale3DTransformOperation; - m_argCount = 5; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "rotate(")) { - m_type = WebKitCSSTransformValue::RotateTransformOperation; - m_unit = CSSParser::FAngle; - } else if (equalIgnoringCase(name, "rotatex(") || - equalIgnoringCase(name, "rotatey(") || - equalIgnoringCase(name, "rotatez(")) { - m_unit = CSSParser::FAngle; - if (equalIgnoringCase(name, "rotatex(")) - m_type = WebKitCSSTransformValue::RotateXTransformOperation; - else if (equalIgnoringCase(name, "rotatey(")) - m_type = WebKitCSSTransformValue::RotateYTransformOperation; - else - m_type = WebKitCSSTransformValue::RotateZTransformOperation; - } else if (equalIgnoringCase(name, "rotate3d(")) { - m_type = WebKitCSSTransformValue::Rotate3DTransformOperation; - m_argCount = 7; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "skewx(") || equalIgnoringCase(name, "skewy(")) { - m_unit = CSSParser::FAngle; - if (equalIgnoringCase(name, "skew(")) + const UChar* characters; + unsigned nameLength = name.length(); + + const unsigned longestNameLength = 12; + UChar characterBuffer[longestNameLength]; + if (name.is8Bit()) { + unsigned length = std::min(longestNameLength, nameLength); + const LChar* characters8 = name.characters8(); + for (unsigned i = 0; i < length; ++i) + characterBuffer[i] = characters8[i]; + characters = characterBuffer; + } else + characters = name.characters16(); + + switch (nameLength) { + case 5: + // Valid name: skew(. + if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[1] == 'k') || (characters[1] == 'K')) + & ((characters[2] == 'e') || (characters[2] == 'E')) + & ((characters[3] == 'w') || (characters[3] == 'W')) + & (characters[4] == '(')) { + m_unit = CSSParser::FAngle; m_type = WebKitCSSTransformValue::SkewTransformOperation; - else if (equalIgnoringCase(name, "skewx(")) - m_type = WebKitCSSTransformValue::SkewXTransformOperation; - else - m_type = WebKitCSSTransformValue::SkewYTransformOperation; - } else if (equalIgnoringCase(name, "translate(") || equalIgnoringCase(name, "translatex(") || equalIgnoringCase(name, "translatey(") || equalIgnoringCase(name, "translatez(")) { - m_unit = CSSParser::FLength | CSSParser::FPercent; - if (equalIgnoringCase(name, "translate(")) + m_allowSingleArgument = true; + m_argCount = 3; + } + break; + case 6: + // Valid names: skewx(, skewy(, scale(. + if ((characters[1] == 'c') || (characters[1] == 'C')) { + if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'l') || (characters[3] == 'L')) + & ((characters[4] == 'e') || (characters[4] == 'E')) + & (characters[5] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleTransformOperation; + m_allowSingleArgument = true; + m_argCount = 3; + } + } else if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[1] == 'k') || (characters[1] == 'K')) + & ((characters[2] == 'e') || (characters[2] == 'E')) + & ((characters[3] == 'w') || (characters[3] == 'W')) + & (characters[5] == '(')) { + if ((characters[4] == 'x') || (characters[4] == 'X')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::SkewXTransformOperation; + } else if ((characters[4] == 'y') || (characters[4] == 'Y')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::SkewYTransformOperation; + } + } + break; + case 7: + // Valid names: matrix(, rotate(, scalex(, scaley(, scalez(. + if ((characters[0] == 'm') || (characters[0] == 'M')) { + if (((characters[1] == 'a') || (characters[1] == 'A')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'r') || (characters[3] == 'R')) + & ((characters[4] == 'i') || (characters[4] == 'I')) + & ((characters[5] == 'x') || (characters[5] == 'X')) + & (characters[6] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::MatrixTransformOperation; + m_argCount = 11; + } + } else if ((characters[0] == 'r') || (characters[0] == 'R')) { + if (((characters[1] == 'o') || (characters[1] == 'O')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'a') || (characters[3] == 'A')) + & ((characters[4] == 't') || (characters[4] == 'T')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & (characters[6] == '(')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateTransformOperation; + } + } else if (((characters[0] == 's') || (characters[0] == 'S')) + & ((characters[1] == 'c') || (characters[1] == 'C')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'l') || (characters[3] == 'L')) + & ((characters[4] == 'e') || (characters[4] == 'E')) + & (characters[6] == '(')) { + if ((characters[5] == 'x') || (characters[5] == 'X')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleXTransformOperation; + } else if ((characters[5] == 'y') || (characters[5] == 'Y')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleYTransformOperation; + } else if ((characters[5] == 'z') || (characters[5] == 'Z')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::ScaleZTransformOperation; + } + } + break; + case 8: + // Valid names: rotatex(, rotatey(, rotatez(, scale3d(. + if ((characters[0] == 's') || (characters[0] == 'S')) { + if (((characters[1] == 'c') || (characters[1] == 'C')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'l') || (characters[3] == 'L')) + & ((characters[4] == 'e') || (characters[4] == 'E')) + & (characters[5] == '3') + & ((characters[6] == 'd') || (characters[6] == 'D')) + & (characters[7] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::Scale3DTransformOperation; + m_argCount = 5; + } + } else if (((characters[0] == 'r') || (characters[0] == 'R')) + & ((characters[1] == 'o') || (characters[1] == 'O')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'a') || (characters[3] == 'A')) + & ((characters[4] == 't') || (characters[4] == 'T')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & (characters[7] == '(')) { + if ((characters[6] == 'x') || (characters[6] == 'X')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateXTransformOperation; + } else if ((characters[6] == 'y') || (characters[6] == 'Y')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateYTransformOperation; + } else if ((characters[6] == 'z') || (characters[6] == 'Z')) { + m_unit = CSSParser::FAngle; + m_type = WebKitCSSTransformValue::RotateZTransformOperation; + } + } + break; + case 9: + // Valid names: matrix3d(, rotate3d(. + if ((characters[0] == 'm') || (characters[0] == 'M')) { + if (((characters[1] == 'a') || (characters[1] == 'A')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'r') || (characters[3] == 'R')) + & ((characters[4] == 'i') || (characters[4] == 'I')) + & ((characters[5] == 'x') || (characters[5] == 'X')) + & (characters[6] == '3') + & ((characters[7] == 'd') || (characters[7] == 'D')) + & (characters[8] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::Matrix3DTransformOperation; + m_argCount = 31; + } + } else if (((characters[0] == 'r') || (characters[0] == 'R')) + & ((characters[1] == 'o') || (characters[1] == 'O')) + & ((characters[2] == 't') || (characters[2] == 'T')) + & ((characters[3] == 'a') || (characters[3] == 'A')) + & ((characters[4] == 't') || (characters[4] == 'T')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & (characters[6] == '3') + & ((characters[7] == 'd') || (characters[7] == 'D')) + & (characters[8] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::Rotate3DTransformOperation; + m_argCount = 7; + } + break; + case 10: + // Valid name: translate(. + if (((characters[0] == 't') || (characters[0] == 'T')) + & ((characters[1] == 'r') || (characters[1] == 'R')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'n') || (characters[3] == 'N')) + & ((characters[4] == 's') || (characters[4] == 'S')) + & ((characters[5] == 'l') || (characters[5] == 'L')) + & ((characters[6] == 'a') || (characters[6] == 'A')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'e') || (characters[8] == 'E')) + & (characters[9] == '(')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; m_type = WebKitCSSTransformValue::TranslateTransformOperation; - else if (equalIgnoringCase(name, "translatex(")) - m_type = WebKitCSSTransformValue::TranslateXTransformOperation; - else if (equalIgnoringCase(name, "translatey(")) - m_type = WebKitCSSTransformValue::TranslateYTransformOperation; - else - m_type = WebKitCSSTransformValue::TranslateZTransformOperation; - } else if (equalIgnoringCase(name, "translate3d(")) { - m_type = WebKitCSSTransformValue::Translate3DTransformOperation; - m_argCount = 5; - m_unit = CSSParser::FLength | CSSParser::FPercent; - } else if (equalIgnoringCase(name, "matrix(")) { - m_type = WebKitCSSTransformValue::MatrixTransformOperation; - m_argCount = 11; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "matrix3d(")) { - m_type = WebKitCSSTransformValue::Matrix3DTransformOperation; - m_argCount = 31; - m_unit = CSSParser::FNumber; - } else if (equalIgnoringCase(name, "perspective(")) { - m_type = WebKitCSSTransformValue::PerspectiveTransformOperation; - m_unit = CSSParser::FNumber; - } - - if (equalIgnoringCase(name, "scale(") || equalIgnoringCase(name, "skew(") || equalIgnoringCase(name, "translate(")) { - m_allowSingleArgument = true; - m_argCount = 3; - } + m_allowSingleArgument = true; + m_argCount = 3; + } + break; + case 11: + // Valid names: translatex(, translatey(, translatez(. + if (((characters[0] == 't') || (characters[0] == 'T')) + & ((characters[1] == 'r') || (characters[1] == 'R')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'n') || (characters[3] == 'N')) + & ((characters[4] == 's') || (characters[4] == 'S')) + & ((characters[5] == 'l') || (characters[5] == 'L')) + & ((characters[6] == 'a') || (characters[6] == 'A')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'e') || (characters[8] == 'E')) + & (characters[10] == '(')) { + if ((characters[9] == 'x') || (characters[9] == 'X')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::TranslateXTransformOperation; + } else if ((characters[9] == 'y') || (characters[9] == 'Y')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::TranslateYTransformOperation; + } else if ((characters[9] == 'z') || (characters[9] == 'Z')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::TranslateZTransformOperation; + } + } + break; + case 12: + // Valid names: perspective(, translate3d(. + if ((characters[0] == 'p') || (characters[0] == 'P')) { + if (((characters[1] == 'e') || (characters[1] == 'E')) + & ((characters[2] == 'r') || (characters[2] == 'R')) + & ((characters[3] == 's') || (characters[3] == 'S')) + & ((characters[4] == 'p') || (characters[4] == 'P')) + & ((characters[5] == 'e') || (characters[5] == 'E')) + & ((characters[6] == 'c') || (characters[6] == 'C')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'i') || (characters[8] == 'I')) + & ((characters[9] == 'v') || (characters[9] == 'V')) + & ((characters[10] == 'e') || (characters[10] == 'E')) + & (characters[11] == '(')) { + m_unit = CSSParser::FNumber; + m_type = WebKitCSSTransformValue::PerspectiveTransformOperation; + } + } else if (((characters[0] == 't') || (characters[0] == 'T')) + & ((characters[1] == 'r') || (characters[1] == 'R')) + & ((characters[2] == 'a') || (characters[2] == 'A')) + & ((characters[3] == 'n') || (characters[3] == 'N')) + & ((characters[4] == 's') || (characters[4] == 'S')) + & ((characters[5] == 'l') || (characters[5] == 'L')) + & ((characters[6] == 'a') || (characters[6] == 'A')) + & ((characters[7] == 't') || (characters[7] == 'T')) + & ((characters[8] == 'e') || (characters[8] == 'E')) + & (characters[9] == '3') + & ((characters[10] == 'd') || (characters[10] == 'D')) + & (characters[11] == '(')) { + m_unit = CSSParser::FLength | CSSParser::FPercent; + m_type = WebKitCSSTransformValue::Translate3DTransformOperation; + m_argCount = 5; + } + break; + } // end switch () } WebKitCSSTransformValue::TransformOperationType type() const { return m_type; } @@ -8009,6 +8194,8 @@ bool CSSParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& prop switch (propId) { case CSSPropertyWebkitPerspectiveOrigin: + if (m_valueList->size() > 2) + return false; parseFillPosition(m_valueList.get(), value, value2); break; case CSSPropertyWebkitPerspectiveOriginX: { @@ -9010,7 +9197,7 @@ inline void CSSParser::detectNumberToken(CharacterType* type, int length) case 'd': if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'g')) m_token = DEGS; -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) else if (length > 2 && isASCIIAlphaCaselessEqual(type[1], 'p')) { if (length == 4) { // There is a discussion about the name of this unit on www-style. @@ -9185,6 +9372,13 @@ inline void CSSParser::detectAtToken(int length, bool hasEscape) m_token = FONT_FACE_SYM; return; +#if ENABLE(SHADOW_DOM) + case 'h': + if (length == 5 && isEqualToCSSIdentifier(name + 2, "ost")) + m_token = HOST_SYM; + return; +#endif + case 'i': if (length == 7 && isEqualToCSSIdentifier(name + 2, "mport")) { m_parsingMode = MediaQueryMode; @@ -9308,8 +9502,15 @@ inline void CSSParser::detectAtToken(int length, bool hasEscape) return; case 17: - if (!hasEscape && isEqualToCSSIdentifier(name + 2, "webkit-selector")) + if (hasEscape) + return; + + if (isASCIIAlphaCaselessEqual(name[16], 'r') && isEqualToCSSIdentifier(name + 2, "webkit-selecto")) m_token = WEBKIT_SELECTOR_SYM; +#if ENABLE(CSS_DEVICE_ADAPTATION) + else if (isASCIIAlphaCaselessEqual(name[16], 't') && isEqualToCSSIdentifier(name + 2, "webkit-viewpor")) + m_token = WEBKIT_VIEWPORT_RULE_SYM; +#endif return; case 18: @@ -10017,6 +10218,24 @@ StyleRuleBase* CSSParser::createFontFaceRule() return result; } +#if ENABLE(SHADOW_DOM) +StyleRuleBase* CSSParser::createHostRule(RuleList* rules) +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + RefPtr<StyleRuleHost> rule; + if (rules) + rule = StyleRuleHost::create(*rules); + else { + RuleList emptyRules; + rule = StyleRuleHost::create(emptyRules); + } + StyleRuleHost* result = rule.get(); + m_parsedRules.append(rule.release()); + processAndAddNewRuleToSourceTreeIfNeeded(); + return result; +} +#endif + void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri) { if (!m_styleSheet || !m_allowNamespaceDeclarations) @@ -10038,7 +10257,7 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre { AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace; QualifiedName tag = QualifiedName(namespacePrefix, elementName, determinedNamespace); - if (!specifiers->isUnknownPseudoElement()) { + if (!specifiers->isCustomPseudoElement()) { specifiers->setTag(tag); return; } @@ -10047,7 +10266,7 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre CSSParserSelector* history = specifiers; while (history->tagHistory()) { history = history->tagHistory(); - if (history->isUnknownPseudoElement() || history->hasShadowDescendant()) + if (history->isCustomPseudoElement() || history->hasShadowDescendant()) lastShadowDescendant = history; } @@ -10066,12 +10285,12 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre CSSParserSelector* CSSParser::updateSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier) { - if (newSpecifier->isUnknownPseudoElement()) { + if (newSpecifier->isCustomPseudoElement()) { // Unknown pseudo element always goes at the top of selector chain. newSpecifier->appendTagHistory(CSSSelector::ShadowDescendant, sinkFloatingSelector(specifiers)); return newSpecifier; } - if (specifiers->isUnknownPseudoElement()) { + if (specifiers->isCustomPseudoElement()) { // Specifiers for unknown pseudo element go right behind it in the chain. specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowDescendant); return specifiers; @@ -10364,6 +10583,102 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed) resetPropertyRange(); } +#if ENABLE(CSS_DEVICE_ADAPTATION) +StyleRuleBase* CSSParser::createViewportRule() +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + + RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); + + rule->setProperties(createStylePropertySet()); + clearProperties(); + + StyleRuleViewport* result = rule.get(); + m_parsedRules.append(rule.release()); + processAndAddNewRuleToSourceTreeIfNeeded(); + + return result; +} + +bool CSSParser::parseViewportProperty(CSSPropertyID propId, bool important) +{ + CSSParserValue* value = m_valueList->current(); + if (!value) + return false; + + int id = value->id; + bool validPrimitive = false; + + switch (propId) { + case CSSPropertyMinWidth: // auto | device-width | device-height | <length> | <percentage> + case CSSPropertyMaxWidth: + case CSSPropertyMinHeight: + case CSSPropertyMaxHeight: + if (id == CSSValueAuto || id == CSSValueDeviceWidth || id == CSSValueDeviceHeight) + validPrimitive = true; + else + validPrimitive = (!id && validUnit(value, FLength | FPercent | FNonNeg)); + break; + case CSSPropertyWidth: // shorthand + return parseViewportShorthand(propId, CSSPropertyMinWidth, CSSPropertyMaxWidth, important); + case CSSPropertyHeight: + return parseViewportShorthand(propId, CSSPropertyMinHeight, CSSPropertyMaxHeight, important); + case CSSPropertyMinZoom: // auto | <number> | <percentage> + case CSSPropertyMaxZoom: + case CSSPropertyZoom: + if (id == CSSValueAuto) + validPrimitive = true; + else + validPrimitive = (!id && validUnit(value, FNumber | FPercent | FNonNeg)); + break; + case CSSPropertyUserZoom: // zoom | fixed + if (id == CSSValueZoom || id == CSSValueFixed) + validPrimitive = true; + break; + case CSSPropertyOrientation: // auto | portrait | landscape + if (id == CSSValueAuto || id == CSSValuePortrait || id == CSSValueLandscape) + validPrimitive = true; + default: + break; + } + + RefPtr<CSSValue> parsedValue; + if (validPrimitive) { + parsedValue = parseValidPrimitive(id, value); + m_valueList->next(); + } + + if (parsedValue) { + if (!m_valueList->current() || inShorthand()) { + addProperty(propId, parsedValue.release(), important); + return true; + } + } + + return false; +} + +bool CSSParser::parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important) +{ + unsigned numValues = m_valueList->size(); + + if (numValues > 2) + return false; + + ShorthandScope scope(this, propId); + + if (!parseViewportProperty(first, important)) + return false; + + // If just one value is supplied, the second value + // is implicitly initialized with the first value. + if (numValues == 1) + m_valueList->previous(); + + return parseViewportProperty(second, important); +} +#endif + template <typename CharacterType> static CSSPropertyID cssPropertyID(const CharacterType* propertyName, unsigned length) { @@ -10556,20 +10871,16 @@ static bool isCSSTokenizerURL(const String& string) return isCSSTokenizerURL(string.characters(), length); } -// We use single quotes for now because markup.cpp uses double quotes. -String quoteCSSString(const String& string) -{ - // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds - // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned. - if (string.length() >= (std::numeric_limits<unsigned>::max() / 3) - 2) - return ""; +template <typename CharacterType> +static inline String quoteCSSStringInternal(const CharacterType* characters, unsigned length) +{ // 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]; + for (unsigned i = 0; i < length; ++i) { + CharacterType ch = characters[i]; if (ch == '\\' || ch == '\'') { quotedStringSize += 2; afterEscape = false; @@ -10582,12 +10893,12 @@ String quoteCSSString(const String& string) } } - StringBuffer<UChar> buffer(quotedStringSize); + StringBuffer<CharacterType> buffer(quotedStringSize); unsigned index = 0; buffer[index++] = '\''; afterEscape = false; - for (unsigned i = 0; i < string.length(); ++i) { - UChar ch = string[i]; + for (unsigned i = 0; i < length; ++i) { + CharacterType ch = characters[i]; if (ch == '\\' || ch == '\'') { buffer[index++] = '\\'; buffer[index++] = ch; @@ -10610,6 +10921,25 @@ String quoteCSSString(const String& string) return String::adopt(buffer); } +// We use single quotes for now because markup.cpp uses double quotes. +String quoteCSSString(const String& string) +{ + // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds + // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned. + + unsigned length = string.length(); + + if (!length) + return String("\'\'"); + + if (length > std::numeric_limits<unsigned>::max() / 3 - 2) + return emptyString(); + + if (string.is8Bit()) + return quoteCSSStringInternal(string.characters8(), length); + return quoteCSSStringInternal(string.characters16(), length); +} + String quoteCSSStringIfNeeded(const String& string) { return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string); diff --git a/Source/WebCore/css/CSSParser.h b/Source/WebCore/css/CSSParser.h index 75668cf30..2c31794ca 100644 --- a/Source/WebCore/css/CSSParser.h +++ b/Source/WebCore/css/CSSParser.h @@ -47,7 +47,6 @@ namespace WebCore { class CSSBorderImageSliceValue; class CSSPrimitiveValue; -class CSSProperty; class CSSSelectorList; class CSSValue; class CSSValueList; @@ -282,6 +281,9 @@ public: StyleRuleBase* createPageRule(PassOwnPtr<CSSParserSelector> pageSelector); StyleRuleBase* createRegionRule(CSSSelectorVector* regionSelector, RuleList* rules); StyleRuleBase* createMarginAtRule(CSSSelector::MarginBoxType); +#if ENABLE(SHADOW_DOM) + StyleRuleBase* createHostRule(RuleList* rules); +#endif void startDeclarationsForMarginBox(); void endDeclarationsForMarginBox(); @@ -364,6 +366,12 @@ public: int token() { return m_token; } +#if ENABLE(CSS_DEVICE_ADAPTATION) + void markViewportRuleBodyStart() { m_inViewport = true; } + void markViewportRuleBodyEnd() { m_inViewport = false; } + StyleRuleBase* createViewportRule(); +#endif + PassRefPtr<CSSPrimitiveValue> createPrimitiveNumericValue(CSSParserValue*); PassRefPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*); #if ENABLE(CSS_VARIABLES) @@ -452,8 +460,12 @@ private: void recheckAtKeyword(const UChar* str, int len); - void setupParser(const char* prefix, const String&, const char* suffix); - + template<unsigned prefixLength, unsigned suffixLength> + inline void setupParser(const char (&prefix)[prefixLength], const String& string, const char (&suffix)[suffixLength]) + { + setupParser(prefix, prefixLength - 1, string, suffix, suffixLength - 1); + } + void setupParser(const char* prefix, unsigned prefixLength, const String&, const char* suffix, unsigned suffixLength); bool inShorthand() const { return m_inParseShorthand; } bool validWidth(CSSParserValue*); @@ -511,6 +523,14 @@ private: bool m_allowImportRules; bool m_allowNamespaceDeclarations; +#if ENABLE(CSS_DEVICE_ADAPTATION) + bool parseViewportProperty(CSSPropertyID propId, bool important); + bool parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important); + + bool inViewport() const { return m_inViewport; } + bool m_inViewport; +#endif + int (CSSParser::*m_lexFunc)(void*); Vector<RefPtr<StyleRuleBase> > m_parsedRules; @@ -545,7 +565,7 @@ private: FFrequency = 0x0040, FPositiveInteger = 0x0080, FRelative = 0x0100, -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) FResolution = 0x0200, #endif FNonNeg = 0x0400 diff --git a/Source/WebCore/css/CSSParserValues.h b/Source/WebCore/css/CSSParserValues.h index d3fc40353..60986a830 100644 --- a/Source/WebCore/css/CSSParserValues.h +++ b/Source/WebCore/css/CSSParserValues.h @@ -191,7 +191,8 @@ public: void adoptSelectorVector(CSSSelectorVector&); CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); } - bool isUnknownPseudoElement() const { return m_selector->isUnknownPseudoElement(); } + bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); } + bool isSimple() const { return !m_tagHistory && m_selector->isSimple(); } bool hasShadowDescendant() const; diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp index 55ede8b37..c6726cdf2 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.cpp +++ b/Source/WebCore/css/CSSPrimitiveValue.cpp @@ -62,7 +62,7 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit case CSSPrimitiveValue::CSS_CM: case CSSPrimitiveValue::CSS_DEG: case CSSPrimitiveValue::CSS_DIMENSION: -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSSPrimitiveValue::CSS_DPPX: case CSSPrimitiveValue::CSS_DPI: case CSSPrimitiveValue::CSS_DPCM: @@ -94,7 +94,7 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit #if ENABLE(DASHBOARD_SUPPORT) case CSSPrimitiveValue::CSS_DASHBOARD_REGION: #endif -#if !ENABLE(CSS_IMAGE_RESOLUTION) +#if !ENABLE(CSS_IMAGE_RESOLUTION) && !ENABLE(RESOLUTION_MEDIA_QUERY) case CSSPrimitiveValue::CSS_DPPX: case CSSPrimitiveValue::CSS_DPI: case CSSPrimitiveValue::CSS_DPCM: @@ -154,7 +154,7 @@ static CSSPrimitiveValue::UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes case CSSPrimitiveValue::CSS_VH: case CSSPrimitiveValue::CSS_VMIN: return CSSPrimitiveValue::UViewportPercentageLength; -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSSPrimitiveValue::CSS_DPPX: case CSSPrimitiveValue::CSS_DPI: case CSSPrimitiveValue::CSS_DPCM: @@ -676,7 +676,7 @@ CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(Uni return CSS_HZ; case UViewportPercentageLength: return CSS_UNKNOWN; // Cannot convert between numbers and relative lengths. -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case UResolution: return CSS_DPPX; #endif @@ -896,7 +896,7 @@ String CSSPrimitiveValue::customCssText() const case CSS_CM: text = formatNumber(m_value.num, "cm"); break; -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSS_DPPX: text = formatNumber(m_value.num, "dppx"); break; @@ -1228,7 +1228,7 @@ PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const case CSS_VW: case CSS_VH: case CSS_VMIN: -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) case CSS_DPPX: case CSS_DPI: case CSS_DPCM: diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h index aa2dbeac3..fcc5b83b8 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.h +++ b/Source/WebCore/css/CSSPrimitiveValue.h @@ -143,7 +143,7 @@ public: UTime, UFrequency, UViewportPercentageLength, -#if ENABLE(CSS_IMAGE_RESOLUTION) +#if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY) UResolution, #endif UOther @@ -181,6 +181,10 @@ public: bool isCalculated() const { return m_primitiveUnitType == CSS_CALC; } bool isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; } bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; } + bool isDotsPerInch() const { return primitiveType() == CSS_DPI; } + bool isDotsPerPixel() const { return primitiveType() == CSS_DPPX; } + bool isDotsPerCentimeter() const { return primitiveType() == CSS_DPCM; } + #if ENABLE(CSS_VARIABLES) bool isVariableName() const { return primitiveType() == CSS_VARIABLE_NAME; } #endif diff --git a/Source/WebCore/css/CSSPrimitiveValueMappings.h b/Source/WebCore/css/CSSPrimitiveValueMappings.h index 984c0826e..9b198aacd 100644 --- a/Source/WebCore/css/CSSPrimitiveValueMappings.h +++ b/Source/WebCore/css/CSSPrimitiveValueMappings.h @@ -1440,31 +1440,46 @@ template<> inline CSSPrimitiveValue::operator EFloat() const return NoFloat; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EKHTMLLineBreak e) +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineBreak e) : CSSValue(PrimitiveClass) { m_primitiveUnitType = CSS_IDENT; switch (e) { - case LBNORMAL: - m_value.ident = CSSValueNormal; - break; - case AFTER_WHITE_SPACE: - m_value.ident = CSSValueAfterWhiteSpace; - break; + case LineBreakAuto: + m_value.ident = CSSValueAuto; + break; + case LineBreakLoose: + m_value.ident = CSSValueLoose; + break; + case LineBreakNormal: + m_value.ident = CSSValueNormal; + break; + case LineBreakStrict: + m_value.ident = CSSValueStrict; + break; + case LineBreakAfterWhiteSpace: + m_value.ident = CSSValueAfterWhiteSpace; + break; } } -template<> inline CSSPrimitiveValue::operator EKHTMLLineBreak() const +template<> inline CSSPrimitiveValue::operator LineBreak() const { switch (m_value.ident) { - case CSSValueAfterWhiteSpace: - return AFTER_WHITE_SPACE; - case CSSValueNormal: - return LBNORMAL; + case CSSValueAuto: + return LineBreakAuto; + case CSSValueLoose: + return LineBreakLoose; + case CSSValueNormal: + return LineBreakNormal; + case CSSValueStrict: + return LineBreakStrict; + case CSSValueAfterWhiteSpace: + return LineBreakAfterWhiteSpace; } ASSERT_NOT_REACHED(); - return LBNORMAL; + return LineBreakAuto; } template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EListStylePosition e) @@ -3400,41 +3415,41 @@ template<> inline CSSPrimitiveValue::operator ESpeak() const } #if ENABLE(CSS_SHADERS) -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CustomFilterOperation::MeshBoxType meshBoxType) +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CustomFilterMeshBoxType meshBoxType) : CSSValue(PrimitiveClass) { m_primitiveUnitType = CSS_IDENT; switch (meshBoxType) { - case CustomFilterOperation::FILTER_BOX: + case MeshBoxTypeFilter: m_value.ident = CSSValueFilterBox; break; - case CustomFilterOperation::BORDER_BOX: + case MeshBoxTypeBorder: m_value.ident = CSSValueBorderBox; break; - case CustomFilterOperation::PADDING_BOX: + case MeshBoxTypePadding: m_value.ident = CSSValuePaddingBox; break; - case CustomFilterOperation::CONTENT_BOX: + case MeshBoxTypeContent: m_value.ident = CSSValueContentBox; break; } } -template<> inline CSSPrimitiveValue::operator CustomFilterOperation::MeshBoxType() const +template<> inline CSSPrimitiveValue::operator CustomFilterMeshBoxType() const { switch (m_value.ident) { case CSSValueFilterBox: - return CustomFilterOperation::FILTER_BOX; + return MeshBoxTypeFilter; case CSSValueBorderBox: - return CustomFilterOperation::BORDER_BOX; + return MeshBoxTypeBorder; case CSSValuePaddingBox: - return CustomFilterOperation::PADDING_BOX; + return MeshBoxTypePadding; case CSSValueContentBox: - return CustomFilterOperation::CONTENT_BOX; + return MeshBoxTypeContent; } ASSERT_NOT_REACHED(); - return CustomFilterOperation::FILTER_BOX; + return MeshBoxTypeFilter; } #endif // ENABLE(CSS_SHADERS) diff --git a/Source/WebCore/css/CSSProperty.cpp b/Source/WebCore/css/CSSProperty.cpp index b412fdbfa..79be67b46 100644 --- a/Source/WebCore/css/CSSProperty.cpp +++ b/Source/WebCore/css/CSSProperty.cpp @@ -41,29 +41,6 @@ struct SameSizeAsCSSProperty { COMPILE_ASSERT(sizeof(CSSProperty) == sizeof(SameSizeAsCSSProperty), CSSProperty_should_stay_small); -String CSSProperty::cssName() const -{ -#if ENABLE(CSS_VARIABLES) - if (id() == CSSPropertyVariable) { - ASSERT(value()->isVariableValue()); - return "-webkit-var-" + static_cast<CSSVariableValue*>(value())->name(); - } -#endif - return getPropertyNameString(id()); -} - -String CSSProperty::cssText() const -{ - StringBuilder result; - result.append(cssName()); - result.appendLiteral(": "); - result.append(m_value->cssText()); - if (isImportant()) - result.appendLiteral(" !important"); - result.append(';'); - return result.toString(); -} - void CSSProperty::wrapValueInCommaSeparatedList() { RefPtr<CSSValue> value = m_value.release(); @@ -704,6 +681,12 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) #if ENABLE(DRAGGABLE_REGION) case CSSPropertyWebkitAppRegion: #endif +#if ENABLE(CSS_DEVICE_ADAPTATION) + case CSSPropertyMaxZoom: + case CSSPropertyMinZoom: + case CSSPropertyOrientation: + case CSSPropertyUserZoom: +#endif return false; case CSSPropertyInvalid: ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/css/CSSProperty.h b/Source/WebCore/css/CSSProperty.h index fe76e846a..27650ef74 100644 --- a/Source/WebCore/css/CSSProperty.h +++ b/Source/WebCore/css/CSSProperty.h @@ -31,30 +31,47 @@ namespace WebCore { -class CSSProperty { -public: - CSSProperty(CSSPropertyID propID, PassRefPtr<CSSValue> value, bool important = false, CSSPropertyID shorthandID = CSSPropertyInvalid, bool implicit = false) - : m_id(propID) +union StylePropertyMetadata { + StylePropertyMetadata(CSSPropertyID propertyID, CSSPropertyID shorthandID, bool important, bool implicit, bool inherited) + : m_propertyID(propertyID) , m_shorthandID(shorthandID) , m_important(important) , m_implicit(implicit) - , m_inherited(isInheritedProperty(propID)) + , m_inherited(inherited) + { + } + + unsigned m_bits; + struct { + unsigned m_propertyID : 14; + unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand. + unsigned m_important : 1; + unsigned m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand. + unsigned m_inherited : 1; + }; +}; + +class CSSProperty { +public: + CSSProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue> value, bool important = false, CSSPropertyID shorthandID = CSSPropertyInvalid, bool implicit = false) + : m_metadata(propertyID, shorthandID, important, implicit, isInheritedProperty(propertyID)) , m_value(value) { } - CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_id); } - CSSPropertyID shorthandID() const { return static_cast<CSSPropertyID>(m_shorthandID); } + // FIXME: Remove this. + CSSProperty(StylePropertyMetadata metadata, CSSValue* value) + : m_metadata(metadata) + , m_value(value) + { + } - bool isImportant() const { return m_important; } - bool isImplicit() const { return m_implicit; } - bool isInherited() const { return m_inherited; } + CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); } + CSSPropertyID shorthandID() const { return static_cast<CSSPropertyID>(m_metadata.m_shorthandID); } + bool isImportant() const { return m_metadata.m_important; } CSSValue* value() const { return m_value.get(); } - String cssName() const; - String cssText() const; - void wrapValueInCommaSeparatedList(); static CSSPropertyID resolveDirectionAwareProperty(CSSPropertyID, TextDirection, WritingMode); @@ -62,14 +79,10 @@ public: void reportMemoryUsage(MemoryObjectInfo*) const; -private: - // Make sure the following fits in 4 bytes. Really. - unsigned m_id : 14; - unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand. - unsigned m_important : 1; - unsigned m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand. - unsigned m_inherited : 1; + StylePropertyMetadata metadata() const { return m_metadata; } +private: + StylePropertyMetadata m_metadata; RefPtr<CSSValue> m_value; }; diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in index 8776e04be..7f699e383 100644 --- a/Source/WebCore/css/CSSPropertyNames.in +++ b/Source/WebCore/css/CSSPropertyNames.in @@ -402,6 +402,12 @@ z-index -webkit-wrap-through -webkit-wrap #endif +#if defined(ENABLE_CSS_DEVICE_ADAPTATION) && ENABLE_CSS_DEVICE_ADAPTATION +max-zoom +min-zoom +orientation +user-zoom +#endif #if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS -webkit-tap-highlight-color #endif diff --git a/Source/WebCore/css/CSSPropertySourceData.h b/Source/WebCore/css/CSSPropertySourceData.h index 469bdb630..8982acf73 100644 --- a/Source/WebCore/css/CSSPropertySourceData.h +++ b/Source/WebCore/css/CSSPropertySourceData.h @@ -94,7 +94,9 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { FONT_FACE_RULE, PAGE_RULE, KEYFRAMES_RULE, - REGION_RULE + REGION_RULE, + HOST_RULE, + VIEWPORT_RULE }; static PassRefPtr<CSSRuleSourceData> create(Type type) diff --git a/Source/WebCore/css/CSSRule.cpp b/Source/WebCore/css/CSSRule.cpp index cd533d9a8..6c522bd03 100644 --- a/Source/WebCore/css/CSSRule.cpp +++ b/Source/WebCore/css/CSSRule.cpp @@ -30,12 +30,13 @@ #include "CSSStyleRule.h" #include "CSSStyleSheet.h" #include "CSSUnknownRule.h" -#include "WebKitCSSKeyframeRule.h" -#include "WebKitCSSKeyframesRule.h" -#include "WebKitCSSRegionRule.h" #include "NotImplemented.h" #include "StyleRule.h" #include "StyleSheetContents.h" +#include "WebKitCSSKeyframeRule.h" +#include "WebKitCSSKeyframesRule.h" +#include "WebKitCSSRegionRule.h" +#include "WebKitCSSViewportRule.h" namespace WebCore { @@ -50,6 +51,10 @@ COMPILE_ASSERT(sizeof(CSSRule) == sizeof(SameSizeAsCSSRule), CSSRule_should_stay COMPILE_ASSERT(StyleRuleBase::Region == static_cast<StyleRuleBase::Type>(CSSRule::WEBKIT_REGION_RULE), enums_should_match); #endif +#if ENABLE(CSS_DEVICE_ADAPTATION) +COMPILE_ASSERT(StyleRuleBase::Viewport == static_cast<StyleRuleBase::Type>(CSSRule::WEBKIT_VIEWPORT_RULE), enums_should_match); +#endif + void CSSRule::setCssText(const String& /*cssText*/, ExceptionCode& /*ec*/) { notImplemented(); @@ -76,6 +81,10 @@ String CSSRule::cssText() const return static_cast<const WebKitCSSKeyframesRule*>(this)->cssText(); case WEBKIT_KEYFRAME_RULE: return static_cast<const WebKitCSSKeyframeRule*>(this)->cssText(); +#if ENABLE(CSS_DEVICE_ADAPTATION) + case WEBKIT_VIEWPORT_RULE: + return static_cast<const WebKitCSSViewportRule*>(this)->cssText(); +#endif #if ENABLE(CSS_REGIONS) case WEBKIT_REGION_RULE: return static_cast<const WebKitCSSRegionRule*>(this)->cssText(); @@ -115,6 +124,11 @@ void CSSRule::destroy() case WEBKIT_KEYFRAME_RULE: delete static_cast<WebKitCSSKeyframeRule*>(this); return; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case WEBKIT_VIEWPORT_RULE: + delete static_cast<WebKitCSSViewportRule*>(this); + return; +#endif #if ENABLE(CSS_REGIONS) case WEBKIT_REGION_RULE: delete static_cast<WebKitCSSRegionRule*>(this); @@ -155,6 +169,11 @@ void CSSRule::reattach(StyleRuleBase* rule) // No need to reattach, the underlying data is shareable on mutation. ASSERT_NOT_REACHED(); return; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case WEBKIT_VIEWPORT_RULE: + static_cast<WebKitCSSViewportRule*>(this)->reattach(static_cast<StyleRuleViewport*>(rule)); + return; +#endif #if ENABLE(CSS_REGIONS) case WEBKIT_REGION_RULE: static_cast<WebKitCSSRegionRule*>(this)->reattach(static_cast<StyleRuleRegion*>(rule)); @@ -194,6 +213,11 @@ void CSSRule::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const case WEBKIT_KEYFRAME_RULE: static_cast<const WebKitCSSKeyframeRule*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); return; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case WEBKIT_VIEWPORT_RULE: + static_cast<const WebKitCSSViewportRule*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); + return; +#endif #if ENABLE(CSS_REGIONS) case WEBKIT_REGION_RULE: static_cast<const WebKitCSSRegionRule*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); diff --git a/Source/WebCore/css/CSSRule.h b/Source/WebCore/css/CSSRule.h index b31fe7b8d..ab3004887 100644 --- a/Source/WebCore/css/CSSRule.h +++ b/Source/WebCore/css/CSSRule.h @@ -57,6 +57,9 @@ public: // <https://bugs.webkit.org/show_bug.cgi?id=71293>. WEBKIT_KEYFRAMES_RULE, WEBKIT_KEYFRAME_RULE, +#if ENABLE(CSS_DEVICE_ADAPTATION) + WEBKIT_VIEWPORT_RULE = 15, +#endif #if ENABLE(CSS_REGIONS) WEBKIT_REGION_RULE = 16 #endif @@ -73,6 +76,10 @@ public: bool isStyleRule() const { return type() == STYLE_RULE; } bool isImportRule() const { return type() == IMPORT_RULE; } +#if ENABLE(CSS_DEVICE_ADAPTATION) + bool isViewportRule() const { return type() == WEBKIT_VIEWPORT_RULE; } +#endif + #if ENABLE(CSS_REGIONS) bool isRegionRule() const { return type() == WEBKIT_REGION_RULE; } #endif diff --git a/Source/WebCore/css/CSSSelector.cpp b/Source/WebCore/css/CSSSelector.cpp index d2ba75677..c9dd1937a 100644 --- a/Source/WebCore/css/CSSSelector.cpp +++ b/Source/WebCore/css/CSSSelector.cpp @@ -218,6 +218,8 @@ PseudoId CSSSelector::pseudoId(PseudoType type) case PseudoRightPage: case PseudoInRange: case PseudoOutOfRange: + case PseudoUserAgentCustomElement: + case PseudoWebKitCustomElement: return NOPSEUDO; case PseudoNotParsed: ASSERT_NOT_REACHED(); @@ -387,12 +389,22 @@ CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) return PseudoUnknown; HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseudoTypeMap(); HashMap<AtomicStringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoType->find(name.impl()); - return slot == nameToPseudoType->end() ? PseudoUnknown : slot->value; + + if (slot != nameToPseudoType->end()) + return slot->value; + + if (name.startsWith("-webkit-")) + return PseudoWebKitCustomElement; + if (name.startsWith("x-")) + return PseudoUserAgentCustomElement; + + return PseudoUnknown; } -bool CSSSelector::isUnknownPseudoType(const AtomicString& name) +bool CSSSelector::isCustomPseudoType(const AtomicString& name) { - return parsePseudoType(name) == PseudoUnknown; + CSSSelector::PseudoType type = parsePseudoType(name); + return type == PseudoUserAgentCustomElement || type == PseudoWebKitCustomElement; } void CSSSelector::extractPseudoType() const @@ -420,6 +432,8 @@ void CSSSelector::extractPseudoType() const case PseudoScrollbarTrack: case PseudoScrollbarTrackPiece: case PseudoSelection: + case PseudoUserAgentCustomElement: + case PseudoWebKitCustomElement: element = true; break; case PseudoUnknown: @@ -627,17 +641,19 @@ String CSSSelector::selectorText() const if (CSSSelector* tagHistory = cs->tagHistory()) { String tagHistoryText = tagHistory->selectorText(); - if (cs->relation() == CSSSelector::DirectAdjacent) + switch (cs->relation()) { + case CSSSelector::Descendant: + return tagHistoryText + " " + str.toString(); + case CSSSelector::Child: + return tagHistoryText + " > " + str.toString(); + case CSSSelector::DirectAdjacent: return tagHistoryText + " + " + str.toString(); - else if (cs->relation() == CSSSelector::IndirectAdjacent) + case CSSSelector::IndirectAdjacent: return tagHistoryText + " ~ " + str.toString(); - else if (cs->relation() == CSSSelector::Child) - return tagHistoryText + " > " + str.toString(); - else if (cs->relation() == CSSSelector::ShadowDescendant) + case CSSSelector::SubSelector: + ASSERT_NOT_REACHED(); + case CSSSelector::ShadowDescendant: return tagHistoryText + str.toString(); - else { - // Descendant - return tagHistoryText + " " + str.toString(); } } diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h index 5ca24f4e0..aee5074d7 100644 --- a/Source/WebCore/css/CSSSelector.h +++ b/Source/WebCore/css/CSSSelector.h @@ -154,6 +154,8 @@ namespace WebCore { #endif PseudoInRange, PseudoOutOfRange, + PseudoUserAgentCustomElement, + PseudoWebKitCustomElement, }; enum MarginBoxType { @@ -183,7 +185,7 @@ namespace WebCore { } static PseudoType parsePseudoType(const AtomicString&); - static bool isUnknownPseudoType(const AtomicString&); + static bool isCustomPseudoType(const AtomicString&); static PseudoId pseudoId(PseudoType); // Selectors are kept in an array by CSSSelectorList. The next component of the selector is @@ -211,6 +213,7 @@ namespace WebCore { bool matchesPseudoElement() const; bool isUnknownPseudoElement() const; + bool isCustomPseudoElement() const; bool isSiblingSelector() const; bool isAttributeSelector() const; @@ -291,6 +294,11 @@ inline bool CSSSelector::isUnknownPseudoElement() const return m_match == PseudoElement && m_pseudoType == PseudoUnknown; } +inline bool CSSSelector::isCustomPseudoElement() const +{ + return m_match == PseudoElement && (m_pseudoType == PseudoUserAgentCustomElement || m_pseudoType == PseudoWebKitCustomElement); +} + inline bool CSSSelector::isSiblingSelector() const { PseudoType type = pseudoType(); diff --git a/Source/WebCore/css/CSSSelectorList.cpp b/Source/WebCore/css/CSSSelectorList.cpp index 56d2859d2..6a8db4f3a 100644 --- a/Source/WebCore/css/CSSSelectorList.cpp +++ b/Source/WebCore/css/CSSSelectorList.cpp @@ -197,17 +197,17 @@ bool CSSSelectorList::selectorsNeedNamespaceResolution() return forEachSelector(functor, this); } -class SelectorHasUnknownPseudoElementFunctor { +class SelectorHasInvalidSelectorFunctor { public: bool operator()(CSSSelector* selector) { - return selector->isUnknownPseudoElement(); + return selector->isUnknownPseudoElement() || selector->isCustomPseudoElement(); } }; -bool CSSSelectorList::hasUnknownPseudoElements() const +bool CSSSelectorList::hasInvalidSelector() const { - SelectorHasUnknownPseudoElementFunctor functor; + SelectorHasInvalidSelectorFunctor functor; return forEachSelector(functor, this); } diff --git a/Source/WebCore/css/CSSSelectorList.h b/Source/WebCore/css/CSSSelectorList.h index d2ce1134c..83ecf9b3f 100644 --- a/Source/WebCore/css/CSSSelectorList.h +++ b/Source/WebCore/css/CSSSelectorList.h @@ -59,7 +59,7 @@ public: } bool selectorsNeedNamespaceResolution(); - bool hasUnknownPseudoElements() const; + bool hasInvalidSelector() const; String selectorsText() const; diff --git a/Source/WebCore/css/CSSStyleDeclaration.h b/Source/WebCore/css/CSSStyleDeclaration.h index 3247d1eae..0cd794c3f 100644 --- a/Source/WebCore/css/CSSStyleDeclaration.h +++ b/Source/WebCore/css/CSSStyleDeclaration.h @@ -23,6 +23,7 @@ #include "CSSPropertyNames.h" #include "CSSRule.h" +#include "StylePropertySet.h" #include <wtf/Forward.h> namespace WebCore { @@ -30,7 +31,6 @@ namespace WebCore { class CSSProperty; class CSSStyleSheet; class CSSValue; -class StylePropertySet; class StyledElement; typedef int ExceptionCode; @@ -66,7 +66,7 @@ public: virtual PassRefPtr<StylePropertySet> copy() const = 0; virtual PassRefPtr<StylePropertySet> makeMutable() = 0; - virtual bool cssPropertyMatches(const CSSProperty*) const = 0; + virtual bool cssPropertyMatches(const StylePropertySet::PropertyReference&) const = 0; virtual CSSStyleSheet* parentStyleSheet() const { return 0; } virtual void reportMemoryUsage(MemoryObjectInfo*) const = 0; diff --git a/Source/WebCore/css/CSSValueKeywords.in b/Source/WebCore/css/CSSValueKeywords.in index c60aa586d..4b9cc6ea6 100644 --- a/Source/WebCore/css/CSSValueKeywords.in +++ b/Source/WebCore/css/CSSValueKeywords.in @@ -621,6 +621,10 @@ space // // CSS_PROP__KHTML_LINE_BREAK // +// auto +loose +// normal +strict after-white-space // -webkit-appearance @@ -771,6 +775,24 @@ step-end document reset +#if defined(ENABLE_CSS_DEVICE_ADAPTATION) && ENABLE_CSS_DEVICE_ADAPTATION +// +// CSS_PROP_USER_ZOOM +// +// fixed +zoom + +// +// CSS_PROP_MIN_WIDTH +// CSS_PROP_MAX_WIDTH +// CSS_PROP_MIN_HEIGHT +// CSS_PROP_MAX_HEIGHT +// +// auto +device-width +device-height +#endif + // // CSS_PROP_POINTER_EVENTS // diff --git a/Source/WebCore/css/CSSValueList.h b/Source/WebCore/css/CSSValueList.h index 06415fb18..3d897bcfe 100644 --- a/Source/WebCore/css/CSSValueList.h +++ b/Source/WebCore/css/CSSValueList.h @@ -50,6 +50,7 @@ public: size_t length() const { return m_values.size(); } CSSValue* item(size_t index) { return index < m_values.size() ? m_values[index].get() : 0; } + const CSSValue* item(size_t index) const { return index < m_values.size() ? m_values[index].get() : 0; } CSSValue* itemWithoutBoundsCheck(size_t index) { return m_values[index].get(); } void append(PassRefPtr<CSSValue> value) { m_values.append(value); } diff --git a/Source/WebCore/css/CachedSVGDocumentReference.h b/Source/WebCore/css/CachedSVGDocumentReference.h new file mode 100644 index 000000000..2a253abd4 --- /dev/null +++ b/Source/WebCore/css/CachedSVGDocumentReference.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CachedSVGDocumentReference_h +#define CachedSVGDocumentReference_h + +#if ENABLE(SVG) && ENABLE(CSS_FILTERS) +#include "CachedResourceHandle.h" +#include "FilterOperation.h" + +namespace WebCore { + +class CachedSVGDocument; + +class CachedSVGDocumentReference : public ReferenceFilterOperation::Data, public CachedSVGDocumentClient { +public: + CachedSVGDocumentReference(CachedSVGDocument* document) : m_document(document) { m_document->addClient(this); } + virtual ~CachedSVGDocumentReference() { m_document->removeClient(this); } + CachedSVGDocument* document() { return m_document.get(); } +private: + CachedResourceHandle<CachedSVGDocument> m_document; +}; + +}; + +#endif + +#endif diff --git a/Source/WebCore/css/MediaFeatureNames.h b/Source/WebCore/css/MediaFeatureNames.h index b08439e4a..26668ae46 100644 --- a/Source/WebCore/css/MediaFeatureNames.h +++ b/Source/WebCore/css/MediaFeatureNames.h @@ -47,6 +47,7 @@ namespace WebCore { macro(max_height, "max-height") \ macro(max_monochrome, "max-monochrome") \ macro(max_width, "max-width") \ + macro(max_resolution, "max-resolution") \ macro(min_color, "min-color") \ macro(min_aspect_ratio, "min-aspect-ratio") \ macro(min_device_aspect_ratio, "min-device-aspect-ratio") \ @@ -56,7 +57,9 @@ namespace WebCore { macro(min_height, "min-height") \ macro(min_monochrome, "min-monochrome") \ macro(min_width, "min-width") \ + macro(min_resolution, "min-resolution") \ macro(pointer, "pointer") \ + macro(resolution, "resolution") \ macro(transform_2d, "-webkit-transform-2d") \ macro(transform_3d, "-webkit-transform-3d") \ macro(transition, "-webkit-transition") \ diff --git a/Source/WebCore/css/MediaQueryEvaluator.cpp b/Source/WebCore/css/MediaQueryEvaluator.cpp index daa490b8b..2cf69990d 100644 --- a/Source/WebCore/css/MediaQueryEvaluator.cpp +++ b/Source/WebCore/css/MediaQueryEvaluator.cpp @@ -29,11 +29,12 @@ #include "MediaQueryEvaluator.h" #include "CSSAspectRatioValue.h" -#include "Chrome.h" -#include "ChromeClient.h" #include "CSSPrimitiveValue.h" #include "CSSValueKeywords.h" #include "CSSValueList.h" +#include "Chrome.h" +#include "ChromeClient.h" +#include "DOMWindow.h" #include "FloatRect.h" #include "Frame.h" #include "FrameView.h" @@ -45,8 +46,9 @@ #include "NodeRenderStyle.h" #include "Page.h" #include "PlatformScreen.h" -#include "RenderView.h" #include "RenderStyle.h" +#include "RenderView.h" +#include "Screen.h" #include "Settings.h" #include "StyleResolver.h" #include <wtf/HashMap.h> @@ -66,15 +68,13 @@ typedef HashMap<AtomicStringImpl*, EvalFunc> FunctionMap; static FunctionMap* gFunctionMap; /* - * FIXME: following media features are not implemented: color_index, scan, resolution + * FIXME: following media features are not implemented: color_index, scan * * color_index, min-color-index, max_color_index: It's unknown how to retrieve * the information if the display mode is indexed * scan: The "scan" media feature describes the scanning process of * tv output devices. It's unknown how to retrieve this information from * the platform - * resolution, min-resolution, max-resolution: css parser doesn't seem to - * support CSS_DIMENSION */ MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult) @@ -197,6 +197,23 @@ static bool compareAspectRatioValue(CSSValue* value, int width, int height, Medi return false; } +#if ENABLE(RESOLUTION_MEDIA_QUERY) +static bool compareResolution(float min, float max, float value, MediaFeaturePrefix op) +{ + switch (op) { + case NoPrefix: + // A 'resolution' (without a "min-" or "max-" prefix) query + // never matches a device with non-square pixels. + return value == min && value == max; + case MinPrefix: + return min >= value; + case MaxPrefix: + return max <= value; + } + return false; +} +#endif + static bool numberValue(CSSValue* value, float& result) { if (value->isPrimitiveValue() @@ -272,10 +289,128 @@ static bool device_aspect_ratioMediaFeatureEval(CSSValue* value, RenderStyle*, F static bool device_pixel_ratioMediaFeatureEval(CSSValue *value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) { - if (value) - return value->isPrimitiveValue() && compareValue(frame->page()->deviceScaleFactor(), static_cast<CSSPrimitiveValue*>(value)->getFloatValue(), op); + // FIXME: Possible handle other media types than 'screen' and 'print'. + float deviceScaleFactor = 0; + + // This checks the actual media type applied to the document, and we know + // this method only got called if this media type matches the one defined + // in the query. Thus, if if the document's media type is "print", the + // media type of the query will either be "print" or "all". + String mediaType = frame->view()->mediaType(); + if (equalIgnoringCase(mediaType, "screen")) + deviceScaleFactor = frame->page()->deviceScaleFactor(); + else if (equalIgnoringCase(mediaType, "print")) { + // The resolution of images while printing should not depend on the dpi + // of the screen. Until we support proper ways of querying this info + // we use 300px which is considered minimum for current printers. + deviceScaleFactor = 3.125; // 300dpi / 96dpi; + } - return frame->page()->deviceScaleFactor() != 0; + if (!value) + return !!deviceScaleFactor; + + return value->isPrimitiveValue() && compareValue(deviceScaleFactor, static_cast<CSSPrimitiveValue*>(value)->getFloatValue(), op); +} + +static bool resolutionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +{ +#if ENABLE(RESOLUTION_MEDIA_QUERY) + // The DPI below is dots per CSS inch and thus not device inch. The + // functions should respect this. + // + // For square pixels, it is simply the device scale factor (dppx) times 96, + // per definition. + // + // The device scale factor is a predefined value which is calculated per + // device given the preferred distance in arms length (considered one arms + // length for desktop computers and usually 0.6 arms length for phones). + // + // The value can be calculated as follows (rounded to quarters): + // round((deviceDotsPerInch * distanceInArmsLength / 96) * 4) / 4. + // Example (mid-range resolution phone): + // round((244 * 0.6 / 96) * 4) / 4 = 1.5 + // Example (high-range resolution laptop): + // round((220 * 1.0 / 96) * 4) / 4 = 2.0 + + float horiDPI; + float vertDPI; + + // This checks the actual media type applied to the document, and we know + // this method only got called if this media type matches the one defined + // in the query. Thus, if if the document's media type is "print", the + // media type of the query will either be "print" or "all". + String mediaType = frame->view()->mediaType(); + if (equalIgnoringCase(mediaType, "screen")) { + Screen* screen = frame->document()->domWindow()->screen(); + horiDPI = screen->horizontalDPI(); + vertDPI = screen->verticalDPI(); + } else if (equalIgnoringCase(mediaType, "print")) { + // The resolution of images while printing should not depend on the dpi + // of the screen. Until we support proper ways of querying this info + // we use 300px which is considered minimum for current printers. + horiDPI = vertDPI = 300; + } else { + // FIXME: Possible handle other media types than 'screen' and 'print'. + // For now, do not match. + return false; + } + + float leastDenseDPI = std::min(horiDPI, vertDPI); + float mostDenseDPI = std::max(horiDPI, vertDPI); + + // According to spec, (resolution) will evaluate to true if (resolution:x) + // will evaluate to true for a value x other than zero or zero followed by + // a valid unit identifier (i.e., other than 0, 0dpi, 0dpcm, or 0dppx.), + // which is always the case. But the spec special cases 'resolution' to + // never matches a device with non-square pixels. + if (!value) { + ASSERT(op == NoPrefix); + return leastDenseDPI == mostDenseDPI; + } + + if (!value->isPrimitiveValue()) + return false; + + // http://dev.w3.org/csswg/css3-values/#resolution defines resolution as a + // dimension, which contains a number (decimal point allowed), not just an + // integer. Also, http://dev.w3.org/csswg/css3-values/#numeric-types says + // "CSS theoretically supports infinite precision and infinite ranges for + // all value types; + CSSPrimitiveValue* rawValue = static_cast<CSSPrimitiveValue*>(value); + + if (rawValue->isDotsPerPixel()) { + // http://dev.w3.org/csswg/css3-values/#absolute-lengths recommends + // "that the pixel unit refer to the whole number of device pixels that + // best approximates the reference pixel". We compare with 3 decimal + // points, which aligns with current device-pixel-ratio's in use. + float leastDenseDensity = floorf(leastDenseDPI * 1000 / 96) / 1000; + float mostDenseDensity = floorf(leastDenseDPI * 1000 / 96) / 1000; + float testedDensity = rawValue->getFloatValue(CSSPrimitiveValue::CSS_DPPX); + return compareResolution(leastDenseDensity, mostDenseDensity, testedDensity, op); + } + + if (rawValue->isDotsPerInch()) { + unsigned testedDensity = rawValue->getFloatValue(CSSPrimitiveValue::CSS_DPI); + return compareResolution(leastDenseDPI, mostDenseDPI, testedDensity, op); + } + + // http://dev.w3.org/csswg/css3-values/#absolute-lengths recommends "that + // the pixel unit refer to the whole number of device pixels that best + // approximates the reference pixel". + float leastDenseDPCM = roundf(leastDenseDPI / 2.54); // (2.54 cm/in) + float mostDenseDPCM = roundf(mostDenseDPI / 2.54); + + if (rawValue->isDotsPerCentimeter()) { + float testedDensity = rawValue->getFloatValue(CSSPrimitiveValue::CSS_DPCM); + return compareResolution(leastDenseDPCM, mostDenseDPCM, testedDensity, op); + } +#else + UNUSED_PARAM(value); + UNUSED_PARAM(frame); + UNUSED_PARAM(op); +#endif + + return false; } static bool gridMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op) @@ -456,6 +591,16 @@ static bool max_device_widthMediaFeatureEval(CSSValue* value, RenderStyle* style return device_widthMediaFeatureEval(value, style, frame, MaxPrefix); } +static bool min_resolutionMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +{ + return resolutionMediaFeatureEval(value, style, frame, MinPrefix); +} + +static bool max_resolutionMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +{ + return resolutionMediaFeatureEval(value, style, frame, MaxPrefix); +} + static bool animationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op) { if (value) { diff --git a/Source/WebCore/css/MediaQueryExp.cpp b/Source/WebCore/css/MediaQueryExp.cpp index 1a06b7965..23be429ca 100644 --- a/Source/WebCore/css/MediaQueryExp.cpp +++ b/Source/WebCore/css/MediaQueryExp.cpp @@ -67,6 +67,16 @@ static inline bool featureWithValidPositiveLenghtOrNumber(const AtomicString& me || mediaFeature == MediaFeatureNames::min_device_widthMediaFeature; } +static inline bool featureWithValidDensity(const AtomicString& mediaFeature, const CSSParserValue* value) +{ + if ((value->unit != CSSPrimitiveValue::CSS_DPPX && value->unit != CSSPrimitiveValue::CSS_DPI && value->unit != CSSPrimitiveValue::CSS_DPCM) || value->fValue <= 0) + return false; + + return mediaFeature == MediaFeatureNames::resolutionMediaFeature + || mediaFeature == MediaFeatureNames::max_resolutionMediaFeature + || mediaFeature == MediaFeatureNames::min_resolutionMediaFeature; +} + static inline bool featureWithPositiveInteger(const AtomicString& mediaFeature, const CSSParserValue* value) { if (!value->isInt || value->fValue < 0) @@ -114,6 +124,7 @@ static inline bool featureWithAspectRatio(const AtomicString& mediaFeature) static inline bool featureWithoutValue(const AtomicString& mediaFeature) { + // Media features that are prefixed by min/max cannot be used without a value. return mediaFeature == MediaFeatureNames::monochromeMediaFeature || mediaFeature == MediaFeatureNames::colorMediaFeature || mediaFeature == MediaFeatureNames::gridMediaFeature @@ -131,7 +142,8 @@ static inline bool featureWithoutValue(const AtomicString& mediaFeature) || mediaFeature == MediaFeatureNames::animationMediaFeature || mediaFeature == MediaFeatureNames::view_modeMediaFeature || mediaFeature == MediaFeatureNames::pointerMediaFeature - || mediaFeature == MediaFeatureNames::device_pixel_ratioMediaFeature; + || mediaFeature == MediaFeatureNames::device_pixel_ratioMediaFeature + || mediaFeature == MediaFeatureNames::resolutionMediaFeature; } inline MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* valueList) @@ -148,6 +160,10 @@ inline MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, CSSParserV if (featureWithCSSValueID(mediaFeature, value)) m_value = CSSPrimitiveValue::createIdentifier(value->id); + // Media features that must have non-negative <density>, ie. dppx, dpi or dpcm. + else if (featureWithValidDensity(mediaFeature, value)) + m_value = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + // Media features that must have non-negative <lenght> or number value. else if (featureWithValidPositiveLenghtOrNumber(mediaFeature, value)) m_value = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); diff --git a/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp b/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp index 93d4e4538..824d90fb2 100644 --- a/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp +++ b/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp @@ -30,7 +30,6 @@ #include "MutationRecord.h" #include "StylePropertySet.h" #include "StyledElement.h" -#include "UndoManager.h" #include "WebCoreMemoryInstrumentation.h" #include <wtf/MemoryInstrumentationHashMap.h> @@ -55,39 +54,25 @@ public: ASSERT(!s_currentDecl); s_currentDecl = decl; -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) if (!s_currentDecl->parentElement()) return; bool shouldReadOldValue = false; -#if ENABLE(MUTATION_OBSERVERS) m_mutationRecipients = MutationObserverInterestGroup::createForAttributesMutation(s_currentDecl->parentElement(), HTMLNames::styleAttr); if (m_mutationRecipients && m_mutationRecipients->isOldValueRequested()) shouldReadOldValue = true; -#endif -#if ENABLE(UNDO_MANAGER) - m_isRecordingAutomaticTransaction = UndoManager::isRecordingAutomaticTransaction(s_currentDecl->parentElement()); - if (m_isRecordingAutomaticTransaction) - shouldReadOldValue = true; -#endif AtomicString oldValue; if (shouldReadOldValue) oldValue = s_currentDecl->parentElement()->getAttribute(HTMLNames::styleAttr); -#if ENABLE(MUTATION_OBSERVERS) if (m_mutationRecipients) { AtomicString requestedOldValue = m_mutationRecipients->isOldValueRequested() ? oldValue : nullAtom; m_mutation = MutationRecord::createAttributes(s_currentDecl->parentElement(), HTMLNames::styleAttr, requestedOldValue); } #endif -#if ENABLE(UNDO_MANAGER) - if (m_isRecordingAutomaticTransaction) - m_oldValue = oldValue; -#endif - -#endif } ~StyleAttributeMutationScope() @@ -99,14 +84,7 @@ public: #if ENABLE(MUTATION_OBSERVERS) if (m_mutation && s_shouldDeliver) m_mutationRecipients->enqueueMutationRecord(m_mutation); -#endif -#if ENABLE(UNDO_MANAGER) - if (m_isRecordingAutomaticTransaction && s_shouldDeliver) { - UndoManager::addTransactionStep(AttrChangingDOMTransactionStep::create( - s_currentDecl->parentElement(), HTMLNames::styleAttr, m_oldValue, s_currentDecl->parentElement()->getAttribute(HTMLNames::styleAttr))); - } -#endif -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) + s_shouldDeliver = false; #endif if (!s_shouldNotifyInspector) { @@ -121,7 +99,7 @@ public: InspectorInstrumentation::didInvalidateStyleAttr(localCopyStyleDecl->parentElement()->document(), localCopyStyleDecl->parentElement()); } -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) void enqueueMutationRecord() { s_shouldDeliver = true; @@ -137,7 +115,7 @@ private: static unsigned s_scopeCount; static PropertySetCSSStyleDeclaration* s_currentDecl; static bool s_shouldNotifyInspector; -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) static bool s_shouldDeliver; #endif @@ -145,16 +123,12 @@ private: OwnPtr<MutationObserverInterestGroup> m_mutationRecipients; RefPtr<MutationRecord> m_mutation; #endif -#if ENABLE(UNDO_MANAGER) - bool m_isRecordingAutomaticTransaction; - AtomicString m_oldValue; -#endif }; unsigned StyleAttributeMutationScope::s_scopeCount = 0; PropertySetCSSStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = 0; bool StyleAttributeMutationScope::s_shouldNotifyInspector = false; -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) bool StyleAttributeMutationScope::s_shouldDeliver = false; #endif @@ -196,7 +170,7 @@ String PropertySetCSSStyleDeclaration::cssText() const void PropertySetCSSStyleDeclaration::setCssText(const String& text, ExceptionCode& ec) { -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif willMutate(); @@ -207,7 +181,7 @@ void PropertySetCSSStyleDeclaration::setCssText(const String& text, ExceptionCod didMutate(PropertyChanged); -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) mutationScope.enqueueMutationRecord(); #endif } @@ -257,7 +231,7 @@ bool PropertySetCSSStyleDeclaration::isPropertyImplicit(const String& propertyNa void PropertySetCSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode& ec) { -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif CSSPropertyID propertyID = cssPropertyID(propertyName); @@ -276,7 +250,7 @@ void PropertySetCSSStyleDeclaration::setProperty(const String& propertyName, con if (changed) { // CSS DOM requires raising SYNTAX_ERR of parsing failed, but this is too dangerous for compatibility, // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) mutationScope.enqueueMutationRecord(); #endif } @@ -284,7 +258,7 @@ void PropertySetCSSStyleDeclaration::setProperty(const String& propertyName, con String PropertySetCSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionCode& ec) { -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif CSSPropertyID propertyID = cssPropertyID(propertyName); @@ -300,7 +274,7 @@ String PropertySetCSSStyleDeclaration::removeProperty(const String& propertyName didMutate(changed ? PropertyChanged : NoChanges); if (changed) { -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) mutationScope.enqueueMutationRecord(); #endif } @@ -319,7 +293,7 @@ String PropertySetCSSStyleDeclaration::getPropertyValueInternal(CSSPropertyID pr void PropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID propertyID, const String& value, bool important, ExceptionCode& ec) { -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) StyleAttributeMutationScope mutationScope(this); #endif willMutate(); @@ -330,7 +304,7 @@ void PropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID propertyI didMutate(changed ? PropertyChanged : NoChanges); if (changed) { -#if ENABLE(MUTATION_OBSERVERS) || ENABLE(UNDO_MANAGER) +#if ENABLE(MUTATION_OBSERVERS) mutationScope.enqueueMutationRecord(); #endif } @@ -369,7 +343,7 @@ PassRefPtr<StylePropertySet> PropertySetCSSStyleDeclaration::makeMutable() return m_propertySet; } -bool PropertySetCSSStyleDeclaration::cssPropertyMatches(const CSSProperty* property) const +bool PropertySetCSSStyleDeclaration::cssPropertyMatches(const StylePropertySet::PropertyReference& property) const { return m_propertySet->propertyMatches(property); } diff --git a/Source/WebCore/css/PropertySetCSSStyleDeclaration.h b/Source/WebCore/css/PropertySetCSSStyleDeclaration.h index 0bbd64b7c..cb10437df 100644 --- a/Source/WebCore/css/PropertySetCSSStyleDeclaration.h +++ b/Source/WebCore/css/PropertySetCSSStyleDeclaration.h @@ -67,7 +67,7 @@ private: virtual String getPropertyValueInternal(CSSPropertyID) OVERRIDE; virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionCode&) OVERRIDE; - virtual bool cssPropertyMatches(const CSSProperty*) const OVERRIDE; + virtual bool cssPropertyMatches(const StylePropertySet::PropertyReference&) const OVERRIDE; virtual PassRefPtr<StylePropertySet> copy() const OVERRIDE; virtual PassRefPtr<StylePropertySet> makeMutable() OVERRIDE; diff --git a/Source/WebCore/css/RuleFeature.cpp b/Source/WebCore/css/RuleFeature.cpp index 663b94613..b1f929687 100644 --- a/Source/WebCore/css/RuleFeature.cpp +++ b/Source/WebCore/css/RuleFeature.cpp @@ -38,11 +38,14 @@ namespace WebCore { void RuleFeatureSet::add(const RuleFeatureSet& other) { - HashSet<AtomicStringImpl*>::iterator end = other.idsInRules.end(); - for (HashSet<AtomicStringImpl*>::iterator it = other.idsInRules.begin(); it != end; ++it) + HashSet<AtomicStringImpl*>::const_iterator end = other.idsInRules.end(); + for (HashSet<AtomicStringImpl*>::const_iterator it = other.idsInRules.begin(); it != end; ++it) idsInRules.add(*it); + end = other.classesInRules.end(); + for (HashSet<AtomicStringImpl*>::const_iterator it = other.classesInRules.begin(); it != end; ++it) + classesInRules.add(*it); end = other.attrsInRules.end(); - for (HashSet<AtomicStringImpl*>::iterator it = other.attrsInRules.begin(); it != end; ++it) + for (HashSet<AtomicStringImpl*>::const_iterator it = other.attrsInRules.begin(); it != end; ++it) attrsInRules.add(*it); siblingRules.append(other.siblingRules); uncommonAttributeRules.append(other.uncommonAttributeRules); @@ -53,6 +56,7 @@ void RuleFeatureSet::add(const RuleFeatureSet& other) void RuleFeatureSet::clear() { idsInRules.clear(); + classesInRules.clear(); attrsInRules.clear(); siblingRules.clear(); uncommonAttributeRules.clear(); @@ -64,6 +68,7 @@ void RuleFeatureSet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); info.addMember(idsInRules); + info.addMember(classesInRules); info.addMember(attrsInRules); info.addMember(siblingRules); info.addMember(uncommonAttributeRules); diff --git a/Source/WebCore/css/RuleFeature.h b/Source/WebCore/css/RuleFeature.h index 5f16288c0..ce6d04e66 100644 --- a/Source/WebCore/css/RuleFeature.h +++ b/Source/WebCore/css/RuleFeature.h @@ -31,8 +31,7 @@ namespace WebCore { class StyleRule; -class RuleFeature { -public: +struct RuleFeature { RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin) : rule(rule) , selectorIndex(selectorIndex) @@ -44,8 +43,7 @@ public: bool hasDocumentSecurityOrigin; }; -class RuleFeatureSet { -public: +struct RuleFeatureSet { RuleFeatureSet() : usesFirstLineRules(false) , usesBeforeAfterRules(false) @@ -55,6 +53,7 @@ public: void clear(); void reportMemoryUsage(MemoryObjectInfo*) const; HashSet<AtomicStringImpl*> idsInRules; + HashSet<AtomicStringImpl*> classesInRules; HashSet<AtomicStringImpl*> attrsInRules; Vector<RuleFeature> siblingRules; Vector<RuleFeature> uncommonAttributeRules; diff --git a/Source/WebCore/css/RuleSet.cpp b/Source/WebCore/css/RuleSet.cpp index e2be5771e..e92d1768b 100644 --- a/Source/WebCore/css/RuleSet.cpp +++ b/Source/WebCore/css/RuleSet.cpp @@ -107,18 +107,18 @@ static inline bool containsUncommonAttributeSelector(const CSSSelector* selector return false; } -RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule) +RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, AddRuleFlags addRuleFlags) : m_rule(rule) , m_selectorIndex(selectorIndex) , m_position(position) , m_specificity(selector()->specificity()) - , m_hasFastCheckableSelector(canUseFastCheckSelector && SelectorChecker::isFastCheckableSelector(selector())) + , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorChecker::isFastCheckableSelector(selector())) , m_hasMultipartSelector(!!selector()->tagHistory()) , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector())) , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector())) , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector())) - , m_hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) - , m_isInRegionRule(inRegionRule) + , m_hasDocumentSecurityOrigin(addRuleFlags & RuleHasDocumentSecurityOrigin) + , m_isInRegionRule(addRuleFlags & RuleIsInRegionRule) { ASSERT(m_position == position); ASSERT(m_selectorIndex == selectorIndex); @@ -161,7 +161,9 @@ static inline void collectFeaturesFromSelector(RuleFeatureSet& features, const C { if (selector->m_match == CSSSelector::Id) features.idsInRules.add(selector->value().impl()); - if (selector->isAttributeSelector()) + else if (selector->m_match == CSSSelector::Class) + features.classesInRules.add(selector->value().impl()); + else if (selector->isAttributeSelector()) features.attrsInRules.add(selector->attribute().localName().impl()); switch (selector->pseudoType()) { case CSSSelector::PseudoFirstLine: @@ -207,9 +209,14 @@ void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleDa rules->append(ruleData); } -void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule) +void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) { - RuleData ruleData(rule, selectorIndex, m_ruleCount++, hasDocumentSecurityOrigin, canUseFastCheckSelector, inRegionRule); + RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); + static const unsigned athostRuleSpecificity = 0x100000; + + if (addRuleFlags & RuleIsHostRule) + ruleData.increaseSpecificity(athostRuleSpecificity); + collectFeaturesFromRuleData(m_features, ruleData); CSSSelector* selector = ruleData.selector(); @@ -222,7 +229,7 @@ void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, bool hasDocumentS addToRuleSet(selector->value().impl(), m_classRules, ruleData); return; } - if (selector->isUnknownPseudoElement()) { + if (selector->isCustomPseudoElement()) { addToRuleSet(selector->value().impl(), m_shadowPseudoElementRules, ruleData); return; } @@ -264,10 +271,12 @@ void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurit // Collect the region rules into a rule set const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules(); + AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState; + addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckSelector | RuleIsInRegionRule); for (unsigned i = 0; i < childRules.size(); ++i) { StyleRuleBase* regionStylingRule = childRules[i].get(); if (regionStylingRule->isStyleRule()) - regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), hasDocumentSecurityOrigin, true, true); + regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), addRuleFlags); } // Update the "global" rule count so that proper order is maintained m_ruleCount = regionRuleSet->m_ruleCount; @@ -286,6 +295,7 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu addRulesFromSheet(importRule->styleSheet(), medium, resolver, scope); } bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL()); + AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0)); const Vector<RefPtr<StyleRuleBase> >& rules = sheet->childRules(); for (unsigned i = 0; i < rules.size(); ++i) { @@ -293,7 +303,7 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu ASSERT(!rule->isImportRule()); if (rule->isStyleRule()) - addStyleRule(static_cast<StyleRule*>(rule), hasDocumentSecurityOrigin, !scope); + addStyleRule(static_cast<StyleRule*>(rule), addRuleFlags); else if (rule->isPageRule()) addPageRule(static_cast<StyleRulePage*>(rule)); else if (rule->isMediaRule()) { @@ -305,7 +315,7 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu for (unsigned j = 0; j < childRules.size(); ++j) { StyleRuleBase* childRule = childRules[j].get(); if (childRule->isStyleRule()) - addStyleRule(static_cast<StyleRule*>(childRule), hasDocumentSecurityOrigin, !scope); + addStyleRule(static_cast<StyleRule*>(childRule), addRuleFlags); else if (childRule->isPageRule()) addPageRule(static_cast<StyleRulePage*>(childRule)); else if (childRule->isFontFaceRule() && resolver) { @@ -347,15 +357,19 @@ void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvalu addRegionRule(static_cast<StyleRuleRegion*>(rule), hasDocumentSecurityOrigin); } #endif +#if ENABLE(SHADOW_DOM) + else if (rule->isHostRule()) + resolver->addHostRule(static_cast<StyleRuleHost*>(rule), hasDocumentSecurityOrigin, scope); +#endif } if (m_autoShrinkToFitEnabled) shrinkToFit(); } -void RuleSet::addStyleRule(StyleRule* rule, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule) +void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) { for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = rule->selectorList().indexOfNextSelectorAfter(selectorIndex)) - addRule(rule, selectorIndex, hasDocumentSecurityOrigin, canUseFastCheckSelector, isInRegionRule); + addRule(rule, selectorIndex, addRuleFlags); } static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map) diff --git a/Source/WebCore/css/RuleSet.h b/Source/WebCore/css/RuleSet.h index 6577238ba..a2fbecbc0 100644 --- a/Source/WebCore/css/RuleSet.h +++ b/Source/WebCore/css/RuleSet.h @@ -31,6 +31,14 @@ namespace WebCore { +enum AddRuleFlags { + RuleHasNoSpecialState = 0, + RuleHasDocumentSecurityOrigin = 1, + RuleCanUseFastCheckSelector = 1 << 1, + RuleIsInRegionRule = 1 << 2, + RuleIsHostRule = 1 << 3, +}; + class CSSSelector; class ContainerNode; class MediaQueryEvaluator; @@ -40,7 +48,7 @@ class StyleSheetContents; class RuleData { public: - RuleData(StyleRule*, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule); + RuleData(StyleRule*, unsigned selectorIndex, unsigned position, AddRuleFlags); unsigned position() const { return m_position; } StyleRule* rule() const { return m_rule; } @@ -55,6 +63,7 @@ public: unsigned linkMatchType() const { return m_linkMatchType; } bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; } bool isInRegionRule() const { return m_isInRegionRule; } + void increaseSpecificity(unsigned value) { m_specificity += value; } // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance. static const unsigned maximumIdentifierCount = 4; @@ -98,8 +107,8 @@ public: void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, StyleResolver* = 0, const ContainerNode* = 0); - void addStyleRule(StyleRule*, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false); - void addRule(StyleRule*, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false); + void addStyleRule(StyleRule*, AddRuleFlags); + void addRule(StyleRule*, unsigned selectorIndex, AddRuleFlags); void addPageRule(StyleRulePage*); void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&); void addRegionRule(StyleRuleRegion*, bool hasDocumentSecurityOrigin); diff --git a/Source/WebCore/css/SVGCSSParser.cpp b/Source/WebCore/css/SVGCSSParser.cpp index 26d44e462..7200f218d 100644 --- a/Source/WebCore/css/SVGCSSParser.cpp +++ b/Source/WebCore/css/SVGCSSParser.cpp @@ -26,7 +26,6 @@ #include "CSSInheritedValue.h" #include "CSSInitialValue.h" #include "CSSParser.h" -#include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" #include "CSSValueList.h" diff --git a/Source/WebCore/css/SVGCSSStyleSelector.cpp b/Source/WebCore/css/SVGCSSStyleSelector.cpp index eaedc1065..6145bb1f1 100644 --- a/Source/WebCore/css/SVGCSSStyleSelector.cpp +++ b/Source/WebCore/css/SVGCSSStyleSelector.cpp @@ -185,6 +185,11 @@ void StyleResolver::applySVGProperty(CSSPropertyID id, CSSValue* value) svgstyle->setColorInterpolationFilters(*primitiveValue); break; } + case CSSPropertyColorProfile: + { + // Not implemented. + break; + } case CSSPropertyColorRendering: { HANDLE_INHERIT_AND_INITIAL(colorRendering, ColorRendering) diff --git a/Source/WebCore/css/SelectorChecker.cpp b/Source/WebCore/css/SelectorChecker.cpp index eb5b9f387..38d41f784 100644 --- a/Source/WebCore/css/SelectorChecker.cpp +++ b/Source/WebCore/css/SelectorChecker.cpp @@ -51,6 +51,7 @@ #include "RenderStyle.h" #include "ScrollableArea.h" #include "ScrollbarTheme.h" +#include "ShadowRoot.h" #include "SiblingTraversalStrategies.h" #include "StyledElement.h" #include "Text.h" @@ -268,8 +269,7 @@ bool SelectorChecker::checkSelector(CSSSelector* sel, Element* element, bool isF } PseudoId ignoreDynamicPseudo = NOPSEUDO; - bool hasUnknownPseudoElements = false; - return checkSelector(SelectorCheckingContext(sel, element, SelectorChecker::VisitedMatchDisabled), ignoreDynamicPseudo, hasUnknownPseudoElements) == SelectorMatches; + return checkSelector(SelectorCheckingContext(sel, element, SelectorChecker::VisitedMatchDisabled), ignoreDynamicPseudo) == SelectorMatches; } namespace { @@ -440,16 +440,21 @@ bool SelectorChecker::isFastCheckableSelector(const CSSSelector* selector) // * SelectorFailsLocally - the selector fails for the element e // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e -SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorCheckingContext& context, PseudoId& dynamicPseudo, bool& hasUnknownPseudoElements) const +SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorCheckingContext& context, PseudoId& dynamicPseudo) const { // first selector has to match if (!checkOneSelector(context, DOMSiblingTraversalStrategy())) return SelectorFailsLocally; if (context.selector->m_match == CSSSelector::PseudoElement) { - if (context.selector->isUnknownPseudoElement()) { - hasUnknownPseudoElements = true; - if (context.element->shadowPseudoId() != context.selector->value()) + if (context.selector->isCustomPseudoElement()) { + if (ShadowRoot* root = context.element->shadowRoot()) { + if (context.element->shadowPseudoId() != context.selector->value()) + return SelectorFailsLocally; + + if (context.selector->pseudoType() == CSSSelector::PseudoWebKitCustomElement && root->type() != ShadowRoot::UserAgentShadowRoot) + return SelectorFailsLocally; + } else return SelectorFailsLocally; } else { if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules) @@ -500,7 +505,7 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorChec nextContext.elementStyle = 0; nextContext.elementParentStyle = 0; for (; nextContext.element; nextContext.element = nextContext.element->parentElement()) { - SelectorMatch match = checkSelector(nextContext, ignoreDynamicPseudo, hasUnknownPseudoElements); + SelectorMatch match = checkSelector(nextContext, ignoreDynamicPseudo); if (match == SelectorMatches || match == SelectorFailsCompletely) return match; if (nextContext.element == nextContext.scope) @@ -515,7 +520,7 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorChec nextContext.isSubSelector = false; nextContext.elementStyle = 0; nextContext.elementParentStyle = 0; - return checkSelector(nextContext, ignoreDynamicPseudo, hasUnknownPseudoElements); + return checkSelector(nextContext, ignoreDynamicPseudo); case CSSSelector::DirectAdjacent: if (m_mode == ResolvingStyle && context.element->parentElement()) { @@ -529,7 +534,7 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorChec nextContext.isSubSelector = false; nextContext.elementStyle = 0; nextContext.elementParentStyle = 0; - return checkSelector(nextContext, ignoreDynamicPseudo, hasUnknownPseudoElements); + return checkSelector(nextContext, ignoreDynamicPseudo); case CSSSelector::IndirectAdjacent: if (m_mode == ResolvingStyle && context.element->parentElement()) { @@ -542,7 +547,7 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorChec nextContext.elementStyle = 0; nextContext.elementParentStyle = 0; for (; nextContext.element; nextContext.element = nextContext.element->previousElementSibling()) { - SelectorMatch match = checkSelector(nextContext, ignoreDynamicPseudo, hasUnknownPseudoElements); + SelectorMatch match = checkSelector(nextContext, ignoreDynamicPseudo); if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) return match; }; @@ -559,7 +564,7 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorChec && !(nextContext.hasScrollbarPseudo && nextContext.selector->m_match == CSSSelector::PseudoClass)) return SelectorFailsCompletely; nextContext.isSubSelector = true; - return checkSelector(nextContext, dynamicPseudo, hasUnknownPseudoElements); + return checkSelector(nextContext, dynamicPseudo); case CSSSelector::ShadowDescendant: { @@ -573,7 +578,7 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorChec nextContext.isSubSelector = false; nextContext.elementStyle = 0; nextContext.elementParentStyle = 0; - return checkSelector(nextContext, ignoreDynamicPseudo, hasUnknownPseudoElements); + return checkSelector(nextContext, ignoreDynamicPseudo); } } @@ -979,10 +984,9 @@ bool SelectorChecker::checkOneSelector(const SelectorCheckingContext& context, c { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; - bool hasUnknownPseudoElements = false; PseudoId ignoreDynamicPseudo = NOPSEUDO; for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { - if (checkSelector(subContext, ignoreDynamicPseudo, hasUnknownPseudoElements) == SelectorMatches) + if (checkSelector(subContext, ignoreDynamicPseudo) == SelectorMatches) return true; } } diff --git a/Source/WebCore/css/SelectorChecker.h b/Source/WebCore/css/SelectorChecker.h index 9eadada59..9bdb669b2 100644 --- a/Source/WebCore/css/SelectorChecker.h +++ b/Source/WebCore/css/SelectorChecker.h @@ -82,7 +82,7 @@ public: }; bool checkSelector(CSSSelector*, Element*, bool isFastCheckableSelector = false) const; - SelectorMatch checkSelector(const SelectorCheckingContext&, PseudoId&, bool& hasUnknownPseudoElements) const; + SelectorMatch checkSelector(const SelectorCheckingContext&, PseudoId&) const; template<typename SiblingTraversalStrategy> bool checkOneSelector(const SelectorCheckingContext&, const SiblingTraversalStrategy&) const; diff --git a/Source/WebCore/css/StyleBuilder.cpp b/Source/WebCore/css/StyleBuilder.cpp index 5795defc4..0501dc9d1 100644 --- a/Source/WebCore/css/StyleBuilder.cpp +++ b/Source/WebCore/css/StyleBuilder.cpp @@ -2002,7 +2002,7 @@ StyleBuilder::StyleBuilder() setPropertyHandler(CSSPropertyWebkitHyphenateLimitLines, ApplyPropertyNumber<short, &RenderStyle::hyphenationLimitLines, &RenderStyle::setHyphenationLimitLines, &RenderStyle::initialHyphenationLimitLines, CSSValueNoLimit>::createHandler()); setPropertyHandler(CSSPropertyWebkitHyphens, ApplyPropertyDefault<Hyphens, &RenderStyle::hyphens, Hyphens, &RenderStyle::setHyphens, Hyphens, &RenderStyle::initialHyphens>::createHandler()); setPropertyHandler(CSSPropertyWebkitLineAlign, ApplyPropertyDefault<LineAlign, &RenderStyle::lineAlign, LineAlign, &RenderStyle::setLineAlign, LineAlign, &RenderStyle::initialLineAlign>::createHandler()); - setPropertyHandler(CSSPropertyWebkitLineBreak, ApplyPropertyDefault<EKHTMLLineBreak, &RenderStyle::khtmlLineBreak, EKHTMLLineBreak, &RenderStyle::setKHTMLLineBreak, EKHTMLLineBreak, &RenderStyle::initialKHTMLLineBreak>::createHandler()); + setPropertyHandler(CSSPropertyWebkitLineBreak, ApplyPropertyDefault<LineBreak, &RenderStyle::lineBreak, LineBreak, &RenderStyle::setLineBreak, LineBreak, &RenderStyle::initialLineBreak>::createHandler()); setPropertyHandler(CSSPropertyWebkitLineClamp, ApplyPropertyDefault<const LineClampValue&, &RenderStyle::lineClamp, LineClampValue, &RenderStyle::setLineClamp, LineClampValue, &RenderStyle::initialLineClamp>::createHandler()); setPropertyHandler(CSSPropertyWebkitLineGrid, ApplyPropertyString<MapNoneToNull, &RenderStyle::lineGrid, &RenderStyle::setLineGrid, &RenderStyle::initialLineGrid>::createHandler()); setPropertyHandler(CSSPropertyWebkitLineSnap, ApplyPropertyDefault<LineSnap, &RenderStyle::lineSnap, LineSnap, &RenderStyle::setLineSnap, LineSnap, &RenderStyle::initialLineSnap>::createHandler()); diff --git a/Source/WebCore/css/StylePropertySet.cpp b/Source/WebCore/css/StylePropertySet.cpp index 5e522af92..110b802c9 100644 --- a/Source/WebCore/css/StylePropertySet.cpp +++ b/Source/WebCore/css/StylePropertySet.cpp @@ -34,6 +34,10 @@ #include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> +#if ENABLE(CSS_VARIABLES) +#include "CSSVariableValue.h" +#endif + #ifndef NDEBUG #include <stdio.h> #include <wtf/ASCIICType.h> @@ -51,14 +55,14 @@ static PropertySetCSSOMWrapperMap& propertySetCSSOMWrapperMap() return propertySetCSSOMWrapperMapInstance; } -static size_t immutableStylePropertySetSize(unsigned count) +static size_t sizeForImmutableStylePropertySetWithPropertyCount(unsigned count) { - return sizeof(ImmutableStylePropertySet) + sizeof(CSSProperty) * count; + return sizeof(ImmutableStylePropertySet) - sizeof(void*) + sizeof(CSSValue*) * count + sizeof(StylePropertyMetadata) * count; } PassRefPtr<StylePropertySet> StylePropertySet::createImmutable(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode) { - void* slot = WTF::fastMalloc(immutableStylePropertySetSize(count)); + void* slot = WTF::fastMalloc(sizeForImmutableStylePropertySetWithPropertyCount(count)); return adoptRef(new (slot) ImmutableStylePropertySet(properties, count, cssParserMode)); } @@ -80,8 +84,20 @@ MutableStylePropertySet::MutableStylePropertySet(const CSSProperty* properties, ImmutableStylePropertySet::ImmutableStylePropertySet(const CSSProperty* properties, unsigned length, CSSParserMode cssParserMode) : StylePropertySet(cssParserMode, length) { - for (unsigned i = 0; i < length; ++i) - new (&reinterpret_cast<CSSProperty*>(&m_propertyArray)[i]) CSSProperty(properties[i]); + StylePropertyMetadata* metadataArray = const_cast<StylePropertyMetadata*>(immutableMetadataArray()); + CSSValue** valueArray = const_cast<CSSValue**>(immutableValueArray()); + for (unsigned i = 0; i < length; ++i) { + metadataArray[i] = properties[i].metadata(); + valueArray[i] = properties[i].value(); + valueArray[i]->ref(); + } +} + +ImmutableStylePropertySet::~ImmutableStylePropertySet() +{ + CSSValue** valueArray = const_cast<CSSValue**>(immutableValueArray()); + for (unsigned i = 0; i < m_arraySize; ++i) + valueArray[i]->deref(); } MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other) @@ -92,16 +108,10 @@ MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other) else { m_propertyVector.reserveInitialCapacity(other.propertyCount()); for (unsigned i = 0; i < other.propertyCount(); ++i) - m_propertyVector.uncheckedAppend(other.immutablePropertyArray()[i]); + m_propertyVector.uncheckedAppend(other.propertyAt(i).toCSSProperty()); } } -ImmutableStylePropertySet::~ImmutableStylePropertySet() -{ - for (unsigned i = 0; i < m_arraySize; ++i) - immutablePropertyArray()[i].~CSSProperty(); -} - StylePropertySet::~StylePropertySet() { ASSERT(!m_ownsCSSOMWrapper || propertySetCSSOMWrapperMap().contains(this)); @@ -206,16 +216,17 @@ String StylePropertySet::borderSpacingValue(const StylePropertyShorthand& shorth return horizontalValueCSSText + ' ' + verticalValueCSSText; } -bool StylePropertySet::appendFontLonghandValueIfExplicit(CSSPropertyID propertyId, StringBuilder& result) const +bool StylePropertySet::appendFontLonghandValueIfExplicit(CSSPropertyID propertyID, StringBuilder& result) const { - const CSSProperty* property = findPropertyWithId(propertyId); - if (!property) + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) return false; // All longhands must have at least implicit values if "font" is specified. - if (property->isImplicit()) + + if (propertyAt(foundPropertyIndex).isImplicit()) return true; char prefix = '\0'; - switch (propertyId) { + switch (propertyID) { case CSSPropertyFontStyle: break; // No prefix. case CSSPropertyFontFamily: @@ -232,15 +243,19 @@ bool StylePropertySet::appendFontLonghandValueIfExplicit(CSSPropertyID propertyI if (prefix && !result.isEmpty()) result.append(prefix); - result.append(property->value()->cssText()); + result.append(propertyAt(foundPropertyIndex).value()->cssText()); return true; } String StylePropertySet::fontValue() const { - const CSSProperty* fontSizeProperty = findPropertyWithId(CSSPropertyFontSize); - if (!fontSizeProperty || fontSizeProperty->isImplicit()) + int foundPropertyIndex = findPropertyIndex(CSSPropertyFontSize); + if (foundPropertyIndex == -1) + return emptyString(); + + PropertyReference fontSizeProperty = propertyAt(foundPropertyIndex); + if (fontSizeProperty.isImplicit()) return emptyString(); StringBuilder result; @@ -250,7 +265,7 @@ String StylePropertySet::fontValue() const success &= appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result); if (!result.isEmpty()) result.append(' '); - result.append(fontSizeProperty->value()->cssText()); + result.append(fontSizeProperty.value()->cssText()); success &= appendFontLonghandValueIfExplicit(CSSPropertyLineHeight, result); success &= appendFontLonghandValueIfExplicit(CSSPropertyFontFamily, result); if (!success) { @@ -265,36 +280,44 @@ String StylePropertySet::fontValue() const String StylePropertySet::get4Values(const StylePropertyShorthand& shorthand) const { // Assume the properties are in the usual order top, right, bottom, left. - const CSSProperty* top = findPropertyWithId(shorthand.properties()[0]); - const CSSProperty* right = findPropertyWithId(shorthand.properties()[1]); - const CSSProperty* bottom = findPropertyWithId(shorthand.properties()[2]); - const CSSProperty* left = findPropertyWithId(shorthand.properties()[3]); + int topValueIndex = findPropertyIndex(shorthand.properties()[0]); + int rightValueIndex = findPropertyIndex(shorthand.properties()[1]); + int bottomValueIndex = findPropertyIndex(shorthand.properties()[2]); + int leftValueIndex = findPropertyIndex(shorthand.properties()[3]); + + if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 || leftValueIndex == -1) + return String(); + + PropertyReference top = propertyAt(topValueIndex); + PropertyReference right = propertyAt(rightValueIndex); + PropertyReference bottom = propertyAt(bottomValueIndex); + PropertyReference left = propertyAt(leftValueIndex); // All 4 properties must be specified. - if (!top || !top->value() || !right || !right->value() || !bottom || !bottom->value() || !left || !left->value()) + if (!top.value() || !right.value() || !bottom.value() || !left.value()) return String(); - if (top->value()->isInitialValue() || right->value()->isInitialValue() || bottom->value()->isInitialValue() || left->value()->isInitialValue()) + if (top.value()->isInitialValue() || right.value()->isInitialValue() || bottom.value()->isInitialValue() || left.value()->isInitialValue()) return String(); - if (top->isImportant() != right->isImportant() || right->isImportant() != bottom->isImportant() || bottom->isImportant() != left->isImportant()) + if (top.isImportant() != right.isImportant() || right.isImportant() != bottom.isImportant() || bottom.isImportant() != left.isImportant()) return String(); - bool showLeft = right->value()->cssText() != left->value()->cssText(); - bool showBottom = (top->value()->cssText() != bottom->value()->cssText()) || showLeft; - bool showRight = (top->value()->cssText() != right->value()->cssText()) || showBottom; + bool showLeft = right.value()->cssText() != left.value()->cssText(); + bool showBottom = (top.value()->cssText() != bottom.value()->cssText()) || showLeft; + bool showRight = (top.value()->cssText() != right.value()->cssText()) || showBottom; StringBuilder result; - result.append(top->value()->cssText()); + result.append(top.value()->cssText()); if (showRight) { result.append(' '); - result.append(right->value()->cssText()); + result.append(right.value()->cssText()); } if (showBottom) { result.append(' '); - result.append(bottom->value()->cssText()); + result.append(bottom.value()->cssText()); } if (showLeft) { result.append(' '); - result.append(left->value()->cssText()); + result.append(left.value()->cssText()); } return result.toString(); } @@ -480,8 +503,10 @@ String StylePropertySet::borderPropertyValue(CommonValueMode valueMode) const PassRefPtr<CSSValue> StylePropertySet::getPropertyCSSValue(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->value() : 0; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return 0; + return propertyAt(foundPropertyIndex).value(); } bool StylePropertySet::removeShorthandProperty(CSSPropertyID propertyID) @@ -503,28 +528,28 @@ bool StylePropertySet::removeProperty(CSSPropertyID propertyID, String* returnTe return true; } - CSSProperty* foundProperty = findPropertyWithId(propertyID); - if (!foundProperty) { + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) { if (returnText) *returnText = ""; return false; } if (returnText) - *returnText = foundProperty->value()->cssText(); + *returnText = propertyAt(foundPropertyIndex).value()->cssText(); // A more efficient removal strategy would involve marking entries as empty // and sweeping them when the vector grows too big. - mutablePropertyVector().remove(foundProperty - mutablePropertyVector().data()); + mutablePropertyVector().remove(foundPropertyIndex); return true; } bool StylePropertySet::propertyIsImportant(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - if (property) - return property->isImportant(); + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex != -1) + return propertyAt(foundPropertyIndex).isImportant(); StylePropertyShorthand shorthand = shorthandForProperty(propertyID); if (!shorthand.length()) @@ -539,14 +564,18 @@ bool StylePropertySet::propertyIsImportant(CSSPropertyID propertyID) const CSSPropertyID StylePropertySet::getPropertyShorthand(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->shorthandID() : CSSPropertyInvalid; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return CSSPropertyInvalid; + return propertyAt(foundPropertyIndex).shorthandID(); } bool StylePropertySet::isPropertyImplicit(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->isImplicit() : false; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return false; + return propertyAt(foundPropertyIndex).isImplicit(); } bool StylePropertySet::setProperty(CSSPropertyID propertyID, const String& value, bool important, StyleSheetContents* contextStyleSheet) @@ -577,20 +606,20 @@ void StylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue RefPtr<CSSValue> value = prpValue; for (unsigned i = 0; i < shorthand.length(); ++i) - append(CSSProperty(shorthand.properties()[i], value, important)); + mutablePropertyVector().append(CSSProperty(shorthand.properties()[i], value, important)); } void StylePropertySet::setProperty(const CSSProperty& property, CSSProperty* slot) { ASSERT(isMutable()); if (!removeShorthandProperty(property.id())) { - CSSProperty* toReplace = slot ? slot : findPropertyWithId(property.id()); + CSSProperty* toReplace = slot ? slot : findMutableCSSPropertyWithID(property.id()); if (toReplace) { *toReplace = property; return; } } - append(property); + mutablePropertyVector().append(property); } bool StylePropertySet::setProperty(CSSPropertyID propertyID, int identifier, bool important) @@ -635,10 +664,10 @@ String StylePropertySet::asText() const { StringBuilder result; - const CSSProperty* positionXProp = 0; - const CSSProperty* positionYProp = 0; - const CSSProperty* repeatXProp = 0; - const CSSProperty* repeatYProp = 0; + int positionXPropertyIndex = -1; + int positionYPropertyIndex = -1; + int repeatXPropertyIndex = -1; + int repeatYPropertyIndex = -1; BitArray<numCSSProperties> shorthandPropertyUsed; BitArray<numCSSProperties> shorthandPropertyAppeared; @@ -646,8 +675,8 @@ String StylePropertySet::asText() const unsigned size = propertyCount(); unsigned numDecls = 0; for (unsigned n = 0; n < size; ++n) { - const CSSProperty& prop = propertyAt(n); - CSSPropertyID propertyID = prop.id(); + PropertyReference property = propertyAt(n); + CSSPropertyID propertyID = property.id(); CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; String value; @@ -657,20 +686,20 @@ String StylePropertySet::asText() const case CSSPropertyVariable: if (numDecls++) result.append(' '); - result.append(prop.cssText()); + result.append(property.cssText()); continue; #endif case CSSPropertyBackgroundPositionX: - positionXProp = ∝ + positionXPropertyIndex = n; continue; case CSSPropertyBackgroundPositionY: - positionYProp = ∝ + positionYPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatX: - repeatXProp = ∝ + repeatXPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatY: - repeatYProp = ∝ + repeatYPropertyIndex = n; continue; case CSSPropertyBorderTopWidth: case CSSPropertyBorderRightWidth: @@ -806,7 +835,7 @@ String StylePropertySet::asText() const propertyID = shorthandPropertyID; shorthandPropertyUsed.set(shortPropertyIndex); } else - value = prop.value()->cssText(); + value = property.value()->cssText(); if (value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) continue; @@ -816,7 +845,7 @@ String StylePropertySet::asText() const result.append(getPropertyName(propertyID)); result.appendLiteral(": "); result.append(value); - if (prop.isImportant()) + if (property.isImportant()) result.appendLiteral(" !important"); result.append(';'); } @@ -825,58 +854,64 @@ String StylePropertySet::asText() const // It is required because background-position-x/y are non-standard properties and WebKit generated output // would not work in Firefox (<rdar://problem/5143183>) // It would be a better solution if background-position was CSS_PAIR. - if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) { + if (positionXPropertyIndex != -1 && positionYPropertyIndex != -1 && propertyAt(positionXPropertyIndex).isImportant() == propertyAt(positionYPropertyIndex).isImportant()) { + PropertyReference positionXProperty = propertyAt(positionXPropertyIndex); + PropertyReference positionYProperty = propertyAt(positionYPropertyIndex); + if (numDecls++) result.append(' '); result.appendLiteral("background-position: "); - if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList()) + if (positionXProperty.value()->isValueList() || positionYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundPositionShorthand())); else { - result.append(positionXProp->value()->cssText()); + result.append(positionXProperty.value()->cssText()); result.append(' '); - result.append(positionYProp->value()->cssText()); + result.append(positionYProperty.value()->cssText()); } - if (positionXProp->isImportant()) + if (positionXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { - if (positionXProp) { + if (positionXPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(positionXProp->cssText()); + result.append(propertyAt(positionXPropertyIndex).cssText()); } - if (positionYProp) { + if (positionYPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(positionYProp->cssText()); + result.append(propertyAt(positionYPropertyIndex).cssText()); } } // FIXME: We need to do the same for background-repeat. - if (repeatXProp && repeatYProp && repeatXProp->isImportant() == repeatYProp->isImportant()) { + if (repeatXPropertyIndex != -1 && repeatYPropertyIndex != -1 && propertyAt(repeatXPropertyIndex).isImportant() == propertyAt(repeatYPropertyIndex).isImportant()) { + PropertyReference repeatXProperty = propertyAt(repeatXPropertyIndex); + PropertyReference repeatYProperty = propertyAt(repeatYPropertyIndex); + if (numDecls++) result.append(' '); result.appendLiteral("background-repeat: "); - if (repeatXProp->value()->isValueList() || repeatYProp->value()->isValueList()) + if (repeatXProperty.value()->isValueList() || repeatYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundRepeatShorthand())); else { - result.append(repeatXProp->value()->cssText()); + result.append(repeatXProperty.value()->cssText()); result.append(' '); - result.append(repeatYProp->value()->cssText()); + result.append(repeatYProperty.value()->cssText()); } - if (repeatXProp->isImportant()) + if (repeatXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { - if (repeatXProp) { + if (repeatXPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(repeatXProp->cssText()); + result.append(propertyAt(repeatXPropertyIndex).cssText()); } - if (repeatYProp) { + if (repeatYPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(repeatYProp->cssText()); + result.append(propertyAt(repeatYPropertyIndex).cssText()); } } @@ -889,12 +924,12 @@ void StylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) ASSERT(isMutable()); unsigned size = other->propertyCount(); for (unsigned n = 0; n < size; ++n) { - const CSSProperty& toMerge = other->propertyAt(n); - CSSProperty* old = findPropertyWithId(toMerge.id()); + PropertyReference toMerge = other->propertyAt(n); + CSSProperty* old = findMutableCSSPropertyWithID(toMerge.id()); if (old) - setProperty(toMerge, old); + setProperty(toMerge.toCSSProperty(), old); else - append(toMerge); + mutablePropertyVector().append(toMerge.toCSSProperty()); } } @@ -943,6 +978,12 @@ static const CSSPropertyID blockProperties[] = { CSSPropertyWidows }; +void StylePropertySet::clear() +{ + ASSERT(isMutable()); + mutablePropertyVector().clear(); +} + const unsigned numBlockProperties = WTF_ARRAY_LENGTH(blockProperties); PassRefPtr<StylePropertySet> StylePropertySet::copyBlockProperties() const @@ -985,29 +1026,30 @@ bool StylePropertySet::removePropertiesInSet(const CSSPropertyID* set, unsigned return changed; } -const CSSProperty* StylePropertySet::findPropertyWithId(CSSPropertyID propertyID) const +int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const { for (int n = propertyCount() - 1 ; n >= 0; --n) { if (propertyID == propertyAt(n).id()) - return &propertyAt(n); + return n; } - return 0; + return -1; } -CSSProperty* StylePropertySet::findPropertyWithId(CSSPropertyID propertyID) +CSSProperty* StylePropertySet::findMutableCSSPropertyWithID(CSSPropertyID propertyID) { ASSERT(isMutable()); - for (int n = propertyCount() - 1 ; n >= 0; --n) { - if (propertyID == propertyAt(n).id()) - return &propertyAt(n); - } - return 0; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return 0; + return &mutablePropertyVector().at(foundPropertyIndex); } -bool StylePropertySet::propertyMatches(const CSSProperty* property) const +bool StylePropertySet::propertyMatches(const PropertyReference& property) const { - RefPtr<CSSValue> value = getPropertyCSSValue(property->id()); - return value && value->cssText() == property->value()->cssText(); + int foundPropertyIndex = findPropertyIndex(property.id()); + if (foundPropertyIndex == -1) + return false; + return propertyAt(foundPropertyIndex).value()->cssText() == property.value()->cssText(); } void StylePropertySet::removeEquivalentProperties(const StylePropertySet* style) @@ -1016,8 +1058,8 @@ void StylePropertySet::removeEquivalentProperties(const StylePropertySet* style) Vector<CSSPropertyID> propertiesToRemove; unsigned size = mutablePropertyVector().size(); for (unsigned i = 0; i < size; ++i) { - const CSSProperty& property = mutablePropertyVector().at(i); - if (style->propertyMatches(&property)) + PropertyReference property = propertyAt(i); + if (style->propertyMatches(property)) propertiesToRemove.append(property.id()); } // FIXME: This should use mass removal. @@ -1031,8 +1073,8 @@ void StylePropertySet::removeEquivalentProperties(const CSSStyleDeclaration* sty Vector<CSSPropertyID> propertiesToRemove; unsigned size = mutablePropertyVector().size(); for (unsigned i = 0; i < size; ++i) { - const CSSProperty& property = mutablePropertyVector().at(i); - if (style->cssPropertyMatches(&property)) + PropertyReference property = propertyAt(i); + if (style->cssPropertyMatches(property)) propertiesToRemove.append(property.id()); } // FIXME: This should use mass removal. @@ -1097,19 +1139,19 @@ void StylePropertySet::clearParentElement(StyledElement* element) unsigned StylePropertySet::averageSizeInBytes() { // Please update this if the storage scheme changes so that this longer reflects the actual size. - return sizeof(StylePropertySet) + sizeof(CSSProperty) * 2; + return sizeForImmutableStylePropertySetWithPropertyCount(2); } void StylePropertySet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - size_t actualSize = m_isMutable ? sizeof(StylePropertySet) : immutableStylePropertySetSize(m_arraySize); + size_t actualSize = m_isMutable ? sizeof(StylePropertySet) : sizeForImmutableStylePropertySetWithPropertyCount(m_arraySize); MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS, actualSize); if (m_isMutable) info.addMember(mutablePropertyVector()); - - unsigned count = propertyCount(); - for (unsigned i = 0; i < count; ++i) - info.addMember(propertyAt(i)); + else { + for (unsigned i = 0; i < propertyCount(); ++i) + info.addMember(propertyAt(i).value()); + } } // See the function above if you need to update this. @@ -1125,12 +1167,6 @@ void StylePropertySet::showStyle() } #endif -inline void StylePropertySet::append(const CSSProperty& property) -{ - ASSERT(isMutable()); - mutablePropertyVector().append(property); -} - PassRefPtr<StylePropertySet> StylePropertySet::create(CSSParserMode cssParserMode) { return adoptRef(new MutableStylePropertySet(cssParserMode)); @@ -1141,4 +1177,28 @@ PassRefPtr<StylePropertySet> StylePropertySet::create(const CSSProperty* propert return adoptRef(new MutableStylePropertySet(properties, count)); } +String StylePropertySet::PropertyReference::cssName() const +{ +#if ENABLE(CSS_VARIABLES) + if (id() == CSSPropertyVariable) { + ASSERT(propertyValue()->isVariableValue()); + return "-webkit-var-" + static_cast<const CSSVariableValue*>(propertyValue())->name(); + } +#endif + return getPropertyNameString(id()); +} + +String StylePropertySet::PropertyReference::cssText() const +{ + StringBuilder result; + result.append(cssName()); + result.appendLiteral(": "); + result.append(propertyValue()->cssText()); + if (isImportant()) + result.appendLiteral(" !important"); + result.append(';'); + return result.toString(); +} + + } // namespace WebCore diff --git a/Source/WebCore/css/StylePropertySet.h b/Source/WebCore/css/StylePropertySet.h index 44b6b19fc..f70f1ff7b 100644 --- a/Source/WebCore/css/StylePropertySet.h +++ b/Source/WebCore/css/StylePropertySet.h @@ -42,6 +42,7 @@ class StylePropertyShorthand; class StyleSheetContents; class StylePropertySet : public RefCounted<StylePropertySet> { + friend class PropertyReference; public: ~StylePropertySet(); @@ -53,10 +54,53 @@ public: static PassRefPtr<StylePropertySet> create(const CSSProperty* properties, unsigned count); static PassRefPtr<StylePropertySet> createImmutable(const CSSProperty* properties, unsigned count, CSSParserMode); + class PropertyReference { + public: + PropertyReference(const StylePropertySet& propertySet, unsigned index) + : m_propertySet(propertySet) + , m_index(index) + { + } + + CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); } + CSSPropertyID shorthandID() const { return static_cast<CSSPropertyID>(propertyMetadata().m_shorthandID); } + + bool isImportant() const { return propertyMetadata().m_important; } + bool isInherited() const { return propertyMetadata().m_inherited; } + bool isImplicit() const { return propertyMetadata().m_implicit; } + + String cssName() const; + String cssText() const; + + const CSSValue* value() const { return propertyValue(); } + // FIXME: We should try to remove this mutable overload. + CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); } + + // FIXME: Remove this. + CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); } + + private: + StylePropertyMetadata propertyMetadata() const + { + if (m_propertySet.isMutable()) + return m_propertySet.mutablePropertyVector().at(m_index).metadata(); + return m_propertySet.immutableMetadataArray()[m_index]; + } + + const CSSValue* propertyValue() const + { + if (m_propertySet.isMutable()) + return m_propertySet.mutablePropertyVector().at(m_index).value(); + return m_propertySet.immutableValueArray()[m_index]; + } + + const StylePropertySet& m_propertySet; + unsigned m_index; + }; + unsigned propertyCount() const; bool isEmpty() const; - const CSSProperty& propertyAt(unsigned index) const; - CSSProperty& propertyAt(unsigned index); + PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); } PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; String getPropertyValue(CSSPropertyID) const; @@ -79,6 +123,7 @@ public: void addParsedProperties(const Vector<CSSProperty>&); void addParsedProperty(const CSSProperty&); + void clear(); PassRefPtr<StylePropertySet> copyBlockProperties() const; void removeBlockProperties(); bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); @@ -115,7 +160,8 @@ public: void showStyle(); #endif - const CSSProperty* immutablePropertyArray() const; + const CSSValue** immutableValueArray() const; + const StylePropertyMetadata* immutableMetadataArray() const; protected: StylePropertySet(CSSParserMode cssParserMode) @@ -154,12 +200,10 @@ private: bool appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result) const; bool removeShorthandProperty(CSSPropertyID); - bool propertyMatches(const CSSProperty*) const; - - const CSSProperty* findPropertyWithId(CSSPropertyID) const; - CSSProperty* findPropertyWithId(CSSPropertyID); + bool propertyMatches(const PropertyReference&) const; - void append(const CSSProperty&); + int findPropertyIndex(CSSPropertyID) const; + CSSProperty* findMutableCSSPropertyWithID(CSSPropertyID); friend class PropertySetCSSStyleDeclaration; }; @@ -169,9 +213,21 @@ public: ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode); ~ImmutableStylePropertySet(); - void* m_propertyArray; + void* m_storage; }; +inline const CSSValue** StylePropertySet::immutableValueArray() const +{ + ASSERT(!m_isMutable); + return reinterpret_cast<const CSSValue**>(const_cast<const void**>((&static_cast<const ImmutableStylePropertySet*>(this)->m_storage))); +} + +inline const StylePropertyMetadata* StylePropertySet::immutableMetadataArray() const +{ + ASSERT(!m_isMutable); + return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>((&static_cast<const ImmutableStylePropertySet*>(this)->m_storage))[m_arraySize * sizeof(CSSValue*)]); +} + class MutableStylePropertySet : public StylePropertySet { public: MutableStylePropertySet(CSSParserMode cssParserMode) @@ -195,24 +251,6 @@ inline const Vector<CSSProperty, 4>& StylePropertySet::mutablePropertyVector() c return static_cast<const MutableStylePropertySet*>(this)->m_propertyVector; } -inline const CSSProperty* StylePropertySet::immutablePropertyArray() const -{ - ASSERT(!m_isMutable); - return reinterpret_cast<const CSSProperty*>(&static_cast<const ImmutableStylePropertySet*>(this)->m_propertyArray); -} - -inline CSSProperty& StylePropertySet::propertyAt(unsigned index) -{ - return mutablePropertyVector().at(index); -} - -inline const CSSProperty& StylePropertySet::propertyAt(unsigned index) const -{ - if (m_isMutable) - return mutablePropertyVector().at(index); - return immutablePropertyArray()[index]; -} - inline unsigned StylePropertySet::propertyCount() const { if (m_isMutable) diff --git a/Source/WebCore/css/StyleResolver.cpp b/Source/WebCore/css/StyleResolver.cpp index ad8ddcb3c..7ccdfffd7 100644 --- a/Source/WebCore/css/StyleResolver.cpp +++ b/Source/WebCore/css/StyleResolver.cpp @@ -117,7 +117,6 @@ #include "StylePendingImage.h" #include "StyleRule.h" #include "StyleRuleImport.h" -#include "StyleScopeResolver.h" #include "StyleSheetContents.h" #include "StyleSheetList.h" #include "Text.h" @@ -148,6 +147,7 @@ #if ENABLE(SVG) #include "CachedSVGDocument.h" +#include "CachedSVGDocumentReference.h" #include "SVGDocument.h" #include "SVGElement.h" #include "SVGNames.h" @@ -157,6 +157,7 @@ #if ENABLE(CSS_SHADERS) #include "CustomFilterArrayParameter.h" +#include "CustomFilterConstants.h" #include "CustomFilterNumberParameter.h" #include "CustomFilterOperation.h" #include "CustomFilterParameter.h" @@ -176,6 +177,14 @@ using namespace std; +namespace WTF { + +template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RuleData*> { + template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { } +}; + +} + namespace WebCore { using namespace HTMLNames; @@ -273,7 +282,6 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles) , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles) , m_sameOriginOnly(false) , m_distributedToInsertionPoint(false) - , m_hasUnknownPseudoElements(false) , m_fontSelector(CSSFontSelector::create(document)) , m_applyPropertyToRegularStyle(true) , m_applyPropertyToVisitedLinkStyle(false) @@ -331,25 +339,9 @@ StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles) } #endif - addStylesheetsFromSeamlessParents(); appendAuthorStyleSheets(0, styleSheetCollection->activeAuthorStyleSheets()); } -void StyleResolver::addStylesheetsFromSeamlessParents() -{ - // Build a list of stylesheet lists from our ancestors, and walk that - // list in reverse order so that the root-most sheets are appended first. - Document* childDocument = document(); - Vector<const Vector<RefPtr<CSSStyleSheet> >* > ancestorSheets; - while (HTMLIFrameElement* parentIFrame = childDocument->seamlessParentIFrame()) { - Document* parentDocument = parentIFrame->document(); - ancestorSheets.append(&parentDocument->styleSheetCollection()->activeAuthorStyleSheets()); - childDocument = parentDocument; - } - for (int i = ancestorSheets.size() - 1; i >= 0; i--) - appendAuthorStyleSheets(0, *ancestorSheets[i]); -} - void StyleResolver::addAuthorRulesAndCollectUserRulesFromSheets(const Vector<RefPtr<CSSStyleSheet> >* userSheets, RuleSet& userStyle) { if (!userSheets) @@ -372,7 +364,7 @@ static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules) return nullptr; OwnPtr<RuleSet> ruleSet = RuleSet::create(); for (size_t i = 0; i < size; ++i) - ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin, false); + ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState); ruleSet->shrinkToFit(); return ruleSet.release(); } @@ -411,12 +403,12 @@ void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefP if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), this)) continue; StyleSheetContents* sheet = cssSheet->contents(); +#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) { - if (!m_scopeResolver) - m_scopeResolver = adoptPtr(new StyleScopeResolver()); - m_scopeResolver->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *m_medium, this, scope); + ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *m_medium, this, scope); continue; } +#endif m_authorStyle->addRulesFromSheet(sheet, *m_medium, this); if (!m_styleRuleToCSSOMWrapperMap.isEmpty()) @@ -637,11 +629,56 @@ inline void StyleResolver::addElementStyleProperties(MatchResult& result, const result.isCacheable = false; } +class MatchingUARulesScope { +public: + MatchingUARulesScope(); + ~MatchingUARulesScope(); + + static bool isMatchingUARules(); + +private: + static bool m_matchingUARules; +}; + +MatchingUARulesScope::MatchingUARulesScope() +{ + ASSERT(!m_matchingUARules); + m_matchingUARules = true; +} + +MatchingUARulesScope::~MatchingUARulesScope() +{ + m_matchingUARules = false; +} + +inline bool MatchingUARulesScope::isMatchingUARules() +{ + return m_matchingUARules; +} + +bool MatchingUARulesScope::m_matchingUARules = false; + void StyleResolver::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options) { ASSERT(rules); ASSERT(m_element); + const AtomicString& pseudoId = m_element->shadowPseudoId(); + if (!pseudoId.isEmpty()) { + ASSERT(m_styledElement); + collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options); + } + + // Check whether other types of rules are applicable in the current tree scope. Criteria for this: + // a) it's a UA rule + // b) the tree scope allows author rules + // c) the rules comes from a scoped style sheet within the same tree scope + TreeScope* treeScope = m_element->treeScope(); + if (!MatchingUARulesScope::isMatchingUARules() + && !treeScope->applyAuthorStyles() + && (!options.scope || options.scope->treeScope() != treeScope)) + return; + // We need to collect the rules for id, class, tag, and everything else into a buffer and // then sort the buffer. if (m_element->hasID()) @@ -650,11 +687,7 @@ void StyleResolver::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, in for (size_t i = 0; i < m_styledElement->classNames().size(); ++i) collectMatchingRulesForList(rules->classRules(m_styledElement->classNames()[i].impl()), firstRuleIndex, lastRuleIndex, options); } - const AtomicString& pseudoId = m_element->shadowPseudoId(); - if (!pseudoId.isEmpty()) { - ASSERT(m_styledElement); - collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options); - } + if (m_element->isLink()) collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, options); if (m_checker.matchesFocusPseudoClass(m_element)) @@ -710,7 +743,12 @@ void StyleResolver::sortAndTransferMatchedRules(MatchResult& result) void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules) { #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) - if (!m_scopeResolver || !m_scopeResolver->hasScopedStyles()) + if (!m_scopeResolver) + return; + + matchHostRules(result, includeEmptyRules); + + if (!m_scopeResolver->hasScopedStyles()) return; // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent). @@ -742,6 +780,35 @@ void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmpt #endif } +inline bool StyleResolver::styleSharingCandidateMatchesHostRules() +{ +#if ENABLE(SHADOW_DOM) + return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_element); +#else + return false; +#endif +} + +void StyleResolver::matchHostRules(MatchResult& result, bool includeEmptyRules) +{ +#if ENABLE(SHADOW_DOM) + ASSERT(m_scopeResolver); + + Vector<RuleSet*> matchedRules; + m_scopeResolver->matchHostRules(m_element, matchedRules); + if (matchedRules.isEmpty()) + return; + + MatchOptions options(includeEmptyRules); + options.scope = m_element; + for (unsigned i = matchedRules.size(); i > 0; --i) + collectMatchingRules(matchedRules.at(i-1), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options); +#else + UNUSED_PARAM(result); + UNUSED_PARAM(includeEmptyRules); +#endif +} + void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules) { m_matchedRules.clear(); @@ -784,42 +851,11 @@ void StyleResolver::matchUARules(MatchResult& result, RuleSet* rules) sortAndTransferMatchedRules(result); } -class MatchingUARulesScope { -public: - MatchingUARulesScope(); - ~MatchingUARulesScope(); - - static bool isMatchingUARules(); - -private: - static bool m_matchingUARules; -}; - -MatchingUARulesScope::MatchingUARulesScope() -{ - ASSERT(!m_matchingUARules); - m_matchingUARules = true; -} - -MatchingUARulesScope::~MatchingUARulesScope() -{ - m_matchingUARules = false; -} - -inline bool MatchingUARulesScope::isMatchingUARules() -{ - return m_matchingUARules; -} - -bool MatchingUARulesScope::m_matchingUARules = false; - void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options) { if (!rules) return; - TreeScope* treeScope = m_element->treeScope(); - // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve. // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path. bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode); @@ -833,19 +869,6 @@ void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, i StyleRule* rule = ruleData.rule(); InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule); if (checkSelector(ruleData, options.scope)) { - // Check whether the rule is applicable in the current tree scope. Criteria for this: - // a) it's a UA rule - // b) the tree scope allows author rules - // c) the rules comes from a scoped style sheet within the same tree scope - // d) the rule contains shadow-ID pseudo elements - if (!MatchingUARulesScope::isMatchingUARules() - && !treeScope->applyAuthorStyles() - && (!options.scope || options.scope->treeScope() != treeScope) - && !m_hasUnknownPseudoElements) { - - InspectorInstrumentation::didMatchRule(cookie, false); - continue; - } // If the rule has no properties to apply, then ignore it in the non-debug mode. const StylePropertySet* properties = rule->properties(); if (!properties || (properties->isEmpty() && !options.includeEmptyRules)) { @@ -959,21 +982,10 @@ inline bool shouldResetStyleInheritance(NodeRenderingContext& context) if (context.resetStyleInheritance()) return true; - InsertionPoint* insertionPoint = context.insertionPoint(); - if (!insertionPoint) - return false; - - ASSERT(parentElementForDistribution(context.node())); - ElementShadow* shadow = parentElementForDistribution(context.node())->shadow(); - ASSERT(shadow); + if (InsertionPoint* insertionPoint = context.insertionPoint()) + return insertionPoint->resetStyleInheritance(); - for ( ; insertionPoint; ) { - InsertionPoint* youngerInsertionPoint = shadow->insertionPointFor(insertionPoint); - if (!youngerInsertionPoint) - break; - insertionPoint = youngerInsertionPoint; - } - return insertionPoint->resetStyleInheritance(); + return false; } inline void StyleResolver::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID) @@ -1124,10 +1136,10 @@ static inline bool attributeStylesEqual(const StylePropertySet* a, const StylePr return false; unsigned propertyCount = a->propertyCount(); for (unsigned i = 0; i < propertyCount; ++i) { - const CSSProperty& aProperty = a->propertyAt(i); + StylePropertySet::PropertyReference aProperty = a->propertyAt(i); unsigned j; for (j = 0; j < propertyCount; ++j) { - const CSSProperty& bProperty = b->propertyAt(j); + StylePropertySet::PropertyReference bProperty = b->propertyAt(j); if (aProperty.id() != bProperty.id()) continue; // We could get a few more hits by comparing cssText() here, but that gets expensive quickly. @@ -1187,8 +1199,6 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const return false; if (element == element->document()->cssTarget()) return false; - if (m_element == m_element->document()->cssTarget()) - return false; if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr)) return false; if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr)) @@ -1204,9 +1214,7 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const #if ENABLE(PROGRESS_ELEMENT) if (element->hasTagName(progressTag)) { - if (!m_element->hasTagName(progressTag)) - return false; - + ASSERT(m_element->hasTagName(progressTag)); HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element); HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element); if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate()) @@ -1243,7 +1251,7 @@ bool StyleResolver::canShareStyleWithElement(StyledElement* element) const return false; #endif - if (elementHasDirectionAuto(element) || elementHasDirectionAuto(m_element)) + if (elementHasDirectionAuto(element)) return false; if (element->hasClass()) { @@ -1309,6 +1317,10 @@ RenderStyle* StyleResolver::locateSharedStyle() return 0; if (m_styledElement->hasScopedHTMLStyleChild()) return 0; + if (m_element == m_element->document()->cssTarget()) + return 0; + if (elementHasDirectionAuto(m_element)) + return 0; // Check previous siblings and their cousins. unsigned count = 0; @@ -1332,6 +1344,9 @@ RenderStyle* StyleResolver::locateSharedStyle() // Can't share if attribute rules apply. if (styleSharingCandidateMatchesRuleSet(m_uncommonAttributeRuleSet.get())) return 0; + // Can't share if @host @-rules apply. + if (styleSharingCandidateMatchesHostRules()) + return 0; // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. if (parentStylePreventsSharing(m_parentStyle)) return 0; @@ -1539,9 +1554,10 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS // contenteditable attribute (implemented by -webkit-user-modify) should // be propagated from shadow host to distributed node. if (m_distributedToInsertionPoint) { - ASSERT(element->parentElement()); - if (RenderStyle* styleOfShadowHost = element->parentElement()->renderStyle()) - m_style->setUserModify(styleOfShadowHost->userModify()); + if (Element* parent = element->parentElement()) { + if (RenderStyle* styleOfShadowHost = parent->renderStyle()) + m_style->setUserModify(styleOfShadowHost->userModify()); + } } if (element->isLink()) { @@ -2159,7 +2175,6 @@ PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, Ps inline bool StyleResolver::checkSelector(const RuleData& ruleData, const ContainerNode* scope) { m_dynamicPseudo = NOPSEUDO; - m_hasUnknownPseudoElements = false; if (ruleData.hasFastCheckableSelector()) { // We know this selector does not include any pseudo elements. @@ -2183,7 +2198,7 @@ inline bool StyleResolver::checkSelector(const RuleData& ruleData, const Contain context.elementParentStyle = m_parentNode ? m_parentNode->renderStyle() : 0; context.scope = scope; context.pseudoStyle = m_pseudoStyle; - SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo, m_hasUnknownPseudoElements); + SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo); if (match != SelectorChecker::SelectorMatches) return false; if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != m_dynamicPseudo) @@ -2196,7 +2211,6 @@ bool StyleResolver::checkRegionSelector(CSSSelector* regionSelector, Element* re if (!regionSelector || !regionElement) return false; - m_hasUnknownPseudoElements = false; m_pseudoStyle = NOPSEUDO; for (CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) @@ -2227,7 +2241,7 @@ void StyleResolver::applyProperties(const StylePropertySet* properties, StyleRul unsigned propertyCount = properties->propertyCount(); for (unsigned i = 0; i < propertyCount; ++i) { - const CSSProperty& current = properties->propertyAt(i); + StylePropertySet::PropertyReference current = properties->propertyAt(i); if (isImportant != current.isImportant()) continue; if (inheritedOnly && !current.isInherited()) { @@ -2780,7 +2794,7 @@ void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<s return; // expression failed to parse. for (unsigned i = 0; i < resultSet->propertyCount(); i++) { - const CSSProperty& property = resultSet->propertyAt(i); + StylePropertySet::PropertyReference property = resultSet->propertyAt(i); if (property.id() != CSSPropertyVariable && hasVariableReference(property.value())) resolveVariables(property.id(), property.value(), knownExpressions); else @@ -4235,11 +4249,6 @@ Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forV } } -bool StyleResolver::hasSelectorForAttribute(const AtomicString &attrname) const -{ - return m_features.attrsInRules.contains(attrname.impl()); -} - void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result) { m_viewportDependentMediaQueryResults.append(adoptPtr(new MediaQueryResult(*expr, result))); @@ -4586,7 +4595,7 @@ void StyleResolver::loadPendingSVGDocuments() continue; // Stash the CachedSVGDocument on the reference filter. - referenceFilter->setData(cachedDocument); + referenceFilter->setData(adoptPtr(new CachedSVGDocumentReference(cachedDocument))); } } m_pendingSVGDocuments.clear(); @@ -4765,16 +4774,18 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web ASSERT(shadersValue->isValueList()); CSSValueList* shadersList = static_cast<CSSValueList*>(shadersValue); - ASSERT(shadersList->length()); - RefPtr<StyleShader> vertexShader = styleShader(shadersList->itemWithoutBoundsCheck(0)); + unsigned shadersListLength = shadersList->length(); + ASSERT(shadersListLength); + RefPtr<StyleShader> vertexShader = styleShader(shadersList->itemWithoutBoundsCheck(0)); RefPtr<StyleShader> fragmentShader; - CustomFilterProgramType programType = PROGRAM_TYPE_NO_ELEMENT_TEXTURE; + CustomFilterProgramType programType = PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE; CustomFilterProgramMixSettings mixSettings; - if (shadersList->length() > 1) { + + if (shadersListLength > 1) { CSSValue* fragmentShaderOrMixFunction = shadersList->itemWithoutBoundsCheck(1); + if (fragmentShaderOrMixFunction->isWebKitCSSMixFunctionValue()) { - programType = PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE; WebKitCSSMixFunctionValue* mixFunction = static_cast<WebKitCSSMixFunctionValue*>(fragmentShaderOrMixFunction); CSSValueListIterator iterator(mixFunction); @@ -4793,14 +4804,16 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web ASSERT_NOT_REACHED(); iterator.advance(); } - } else + } else { + programType = PROGRAM_TYPE_NO_ELEMENT_TEXTURE; fragmentShader = styleShader(fragmentShaderOrMixFunction); + } } unsigned meshRows = 1; unsigned meshColumns = 1; - CustomFilterOperation::MeshBoxType meshBoxType = CustomFilterOperation::FILTER_BOX; - CustomFilterOperation::MeshType meshType = CustomFilterOperation::ATTACHED; + CustomFilterMeshBoxType meshBoxType = MeshBoxTypeFilter; + CustomFilterMeshType meshType = MeshTypeAttached; CSSValue* parametersValue = 0; @@ -4816,14 +4829,14 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web if (primitiveValue->isNumber()) { // If only one integer value is specified, it will set both // the rows and the columns. - meshRows = meshColumns = primitiveValue->getIntValue(); + meshColumns = meshRows = primitiveValue->getIntValue(); iterator.advance(); - // Try to match another number for the columns. + // Try to match another number for the rows. if (iterator.hasMore() && iterator.isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value()); if (primitiveValue->isNumber()) { - meshColumns = primitiveValue->getIntValue(); + meshRows = primitiveValue->getIntValue(); iterator.advance(); } } @@ -4844,7 +4857,7 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web if (iterator.hasMore() && iterator.isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(iterator.value()); if (primitiveValue->getIdent() == CSSValueDetached) { - meshType = CustomFilterOperation::DETACHED; + meshType = MeshTypeDetached; iterator.advance(); } } @@ -4864,7 +4877,7 @@ PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(Web if (parametersValue && !parseCustomFilterParameterList(parametersValue, parameterList)) return 0; - RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShader.release(), fragmentShader.release(), programType, mixSettings); + RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShader.release(), fragmentShader.release(), programType, mixSettings, meshType); return CustomFilterOperation::create(program.release(), parameterList, meshRows, meshColumns, meshBoxType, meshType); } #endif @@ -4896,6 +4909,11 @@ bool StyleResolver::createFilterOperations(CSSValue* inValue, RenderStyle* style FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType()); #if ENABLE(CSS_SHADERS) + if (operationType == FilterOperation::VALIDATED_CUSTOM) { + // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle. + ASSERT_NOT_REACHED(); + continue; + } if (operationType == FilterOperation::CUSTOM) { RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue); if (!operation) @@ -4921,8 +4939,8 @@ bool StyleResolver::createFilterOperations(CSSValue* inValue, RenderStyle* style if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), m_element->document())) { if (!svgDocumentValue->loadRequested()) m_pendingSVGDocuments.set(operation.get(), svgDocumentValue); - else - operation->setData(svgDocumentValue->cachedSVGDocument()); + else if (svgDocumentValue->cachedSVGDocument()) + operation->setData(adoptPtr(new CachedSVGDocumentReference(svgDocumentValue->cachedSVGDocument()))); } operations.operations().append(operation); #endif diff --git a/Source/WebCore/css/StyleResolver.h b/Source/WebCore/css/StyleResolver.h index 5b514ce55..f76993442 100644 --- a/Source/WebCore/css/StyleResolver.h +++ b/Source/WebCore/css/StyleResolver.h @@ -29,8 +29,10 @@ #include "MediaQueryExp.h" #include "RenderStyle.h" #include "RuleFeature.h" +#include "RuntimeEnabledFeatures.h" #include "SelectorChecker.h" #include "StyleInheritedData.h" +#include "StyleScopeResolver.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/RefPtr.h> @@ -59,6 +61,7 @@ class CSSValue; class ContainerNode; class CustomFilterOperation; class CustomFilterParameter; +class CustomFilterParameterList; class Document; class Element; class Frame; @@ -80,6 +83,7 @@ class StyleKeyframe; class StylePendingImage; class StylePropertySet; class StyleRule; +class StyleRuleHost; class StyleRuleKeyframes; class StyleRulePage; class StyleRuleRegion; @@ -92,10 +96,6 @@ class WebKitCSSFilterValue; class WebKitCSSShaderValue; class WebKitCSSSVGDocumentValue; -#if ENABLE(CSS_SHADERS) -typedef Vector<RefPtr<CustomFilterParameter> > CustomFilterParameterList; -#endif - class MediaQueryResult { WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED; public: @@ -137,6 +137,9 @@ public: void popParentElement(Element*); void pushParentShadowRoot(const ShadowRoot*); void popParentShadowRoot(const ShadowRoot*); +#if ENABLE(SHADOW_DOM) + void addHostRule(StyleRuleHost* rule, bool hasDocumentSecurityOrigin, const ContainerNode* scope) { ensureScopeResolver()->addHostRule(rule, hasDocumentSecurityOrigin, scope); } +#endif PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, StyleSharingBehavior = AllowStyleSharing, RuleMatchingBehavior = MatchAllRules, RenderRegion* regionForStyling = 0); @@ -166,11 +169,30 @@ public: void appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >&); private: +#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) + StyleScopeResolver* ensureScopeResolver() + { +#if ENABLE(STYLE_SCOPED) +#if ENABLE(SHADOW_DOM) + ASSERT(RuntimeEnabledFeatures::shadowDOMEnabled() || RuntimeEnabledFeatures::styleScopedEnabled()); +#else + ASSERT(RuntimeEnabledFeatures::styleScopedEnabled()); +#endif +#else + ASSERT(RuntimeEnabledFeatures::shadowDOMEnabled()); +#endif + if (!m_scopeResolver) + m_scopeResolver = adoptPtr(new StyleScopeResolver()); + return m_scopeResolver.get(); + } +#endif + void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO); void initElement(Element*); void collectFeatures(); RenderStyle* locateSharedStyle(); bool styleSharingCandidateMatchesRuleSet(RuleSet*); + bool styleSharingCandidateMatchesHostRules(); Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const; StyledElement* findSiblingForStyleSharing(Node*, unsigned& count) const; bool canShareStyleWithElement(StyledElement*) const; @@ -218,6 +240,8 @@ public: static bool colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue*); Color colorFromPrimitiveValue(CSSPrimitiveValue*, bool forVisitedLink = false) const; + bool hasSelectorForId(const AtomicString&) const; + bool hasSelectorForClass(const AtomicString&) const; bool hasSelectorForAttribute(const AtomicString&) const; CSSFontSelector* fontSelector() const { return m_fontSelector.get(); } @@ -323,6 +347,7 @@ private: void matchAuthorRules(MatchResult&, bool includeEmptyRules); void matchUserRules(MatchResult&, bool includeEmptyRules); void matchScopedAuthorRules(MatchResult&, bool includeEmptyRules); + void matchHostRules(MatchResult&, bool includeEmptyRules); void collectMatchingRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&); void collectMatchingRulesForRegion(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&); void collectMatchingRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions&); @@ -330,7 +355,7 @@ private: void sortMatchedRules(); void sortAndTransferMatchedRules(MatchResult&); - bool checkSelector(const RuleData&, const ContainerNode* scope = 0); + bool checkSelector(const RuleData&, const ContainerNode* scope); bool checkRegionSelector(CSSSelector* regionSelector, Element* regionElement); void applyMatchedProperties(const MatchResult&, const Element*); enum StyleApplicationPass { @@ -396,7 +421,6 @@ public: private: static RenderStyle* s_styleNotYetAvailable; - void addStylesheetsFromSeamlessParents(); void addAuthorRulesAndCollectUserRulesFromSheets(const Vector<RefPtr<CSSStyleSheet> >*, RuleSet& userStyle); void cacheBorderAndBackground(); @@ -465,7 +489,6 @@ private: bool m_matchAuthorAndUserStyles; bool m_sameOriginOnly; bool m_distributedToInsertionPoint; - bool m_hasUnknownPseudoElements; RefPtr<CSSFontSelector> m_fontSelector; Vector<OwnPtr<MediaQueryResult> > m_viewportDependentMediaQueryResults; @@ -495,6 +518,24 @@ private: friend bool operator!=(const MatchRanges&, const MatchRanges&); }; +inline bool StyleResolver::hasSelectorForAttribute(const AtomicString &attributeName) const +{ + ASSERT(!attributeName.isEmpty()); + return m_features.attrsInRules.contains(attributeName.impl()); +} + +inline bool StyleResolver::hasSelectorForClass(const AtomicString& classValue) const +{ + ASSERT(!classValue.isEmpty()); + return m_features.classesInRules.contains(classValue.impl()); +} + +inline bool StyleResolver::hasSelectorForId(const AtomicString& idValue) const +{ + ASSERT(!idValue.isEmpty()); + return m_features.idsInRules.contains(idValue.impl()); +} + } // namespace WebCore #endif // StyleResolver_h diff --git a/Source/WebCore/css/StyleRule.cpp b/Source/WebCore/css/StyleRule.cpp index 73b0af26c..713c97146 100644 --- a/Source/WebCore/css/StyleRule.cpp +++ b/Source/WebCore/css/StyleRule.cpp @@ -33,6 +33,7 @@ #include "WebKitCSSKeyframeRule.h" #include "WebKitCSSKeyframesRule.h" #include "WebKitCSSRegionRule.h" +#include "WebKitCSSViewportRule.h" #include <wtf/MemoryInstrumentationVector.h> namespace WebCore { @@ -79,6 +80,14 @@ void StyleRuleBase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const case Keyframes: static_cast<const StyleRuleKeyframes*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); return; + case Host: + static_cast<const StyleRuleBlock*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); + return; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case Viewport: + static_cast<const StyleRuleViewport*>(this)->reportDescendantMemoryUsage(memoryObjectInfo); + return; +#endif case Unknown: case Charset: case Keyframe: @@ -117,6 +126,14 @@ void StyleRuleBase::destroy() case Keyframes: delete static_cast<StyleRuleKeyframes*>(this); return; + case Host: + delete static_cast<StyleRuleHost*>(this); + return; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case Viewport: + delete static_cast<StyleRuleViewport*>(this); + return; +#endif case Unknown: case Charset: case Keyframe: @@ -150,6 +167,12 @@ PassRefPtr<StyleRuleBase> StyleRuleBase::copy() const return 0; case Keyframes: return static_cast<const StyleRuleKeyframes*>(this)->copy(); + case Host: + return static_cast<const StyleRuleHost*>(this)->copy(); +#if ENABLE(CSS_DEVICE_ADAPTATION) + case Viewport: + return static_cast<const StyleRuleViewport*>(this)->copy(); +#endif case Unknown: case Charset: case Keyframe: @@ -191,6 +214,12 @@ PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet case Keyframes: rule = WebKitCSSKeyframesRule::create(static_cast<StyleRuleKeyframes*>(self), parentSheet); break; +#if ENABLE(CSS_DEVICE_ADAPTATION) + case Viewport: + rule = WebKitCSSViewportRule::create(static_cast<StyleRuleViewport*>(self), parentSheet); + break; +#endif + case Host: case Unknown: case Charset: case Keyframe: @@ -381,4 +410,39 @@ void StyleRuleRegion::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObject info.addMember(m_selectorList); } +#if ENABLE(CSS_DEVICE_ADAPTATION) +StyleRuleViewport::StyleRuleViewport() + : StyleRuleBase(Viewport, 0) +{ +} + +StyleRuleViewport::StyleRuleViewport(const StyleRuleViewport& o) + : StyleRuleBase(o) + , m_properties(o.m_properties->copy()) +{ +} + +StyleRuleViewport::~StyleRuleViewport() +{ +} + +StylePropertySet* StyleRuleViewport::mutableProperties() +{ + if (!m_properties->isMutable()) + m_properties = m_properties->copy(); + return m_properties.get(); +} + +void StyleRuleViewport::setProperties(PassRefPtr<StylePropertySet> properties) +{ + m_properties = properties; +} + +void StyleRuleViewport::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); + info.addMember(m_properties); +} +#endif // ENABLE(CSS_DEVICE_ADAPTATION) + } // namespace WebCore diff --git a/Source/WebCore/css/StyleRule.h b/Source/WebCore/css/StyleRule.h index e15f32e40..4d4340a6d 100644 --- a/Source/WebCore/css/StyleRule.h +++ b/Source/WebCore/css/StyleRule.h @@ -46,6 +46,10 @@ public: Page, Keyframes, Keyframe, // Not used. These are internally non-rule StyleKeyframe objects. + Host, +#if ENABLE(CSS_DEVICE_ADAPTATION) + Viewport = 15, +#endif Region = 16 }; Type type() const { return static_cast<Type>(m_type); } @@ -57,7 +61,11 @@ public: bool isPageRule() const { return type() == Page; } bool isStyleRule() const { return type() == Style; } bool isRegionRule() const { return type() == Region; } +#if ENABLE(CSS_DEVICE_ADAPTATION) + bool isViewportRule() const { return type() == Viewport; } +#endif bool isImportRule() const { return type() == Import; } + bool isHostRule() const { return type() == Host; } PassRefPtr<StyleRuleBase> copy() const; @@ -223,6 +231,44 @@ private: CSSSelectorList m_selectorList; }; +class StyleRuleHost : public StyleRuleBlock { +public: + static PassRefPtr<StyleRuleHost> create(Vector<RefPtr<StyleRuleBase> >& adoptRules) + { + return adoptRef(new StyleRuleHost(adoptRules)); + } + + PassRefPtr<StyleRuleHost> copy() const { return adoptRef(new StyleRuleHost(*this)); } + +private: + StyleRuleHost(Vector<RefPtr<StyleRuleBase> >& adoptRules) : StyleRuleBlock(Host, adoptRules) { } + StyleRuleHost(const StyleRuleHost& o) : StyleRuleBlock(o) { } +}; + +#if ENABLE(CSS_DEVICE_ADAPTATION) +class StyleRuleViewport : public StyleRuleBase { +public: + static PassRefPtr<StyleRuleViewport> create() { return adoptRef(new StyleRuleViewport); } + + ~StyleRuleViewport(); + + const StylePropertySet* properties() const { return m_properties.get(); } + StylePropertySet* mutableProperties(); + + void setProperties(PassRefPtr<StylePropertySet>); + + PassRefPtr<StyleRuleViewport> copy() const { return adoptRef(new StyleRuleViewport(*this)); } + + void reportDescendantMemoryUsage(MemoryObjectInfo*) const; + +private: + StyleRuleViewport(); + StyleRuleViewport(const StyleRuleViewport&); + + RefPtr<StylePropertySet> m_properties; +}; +#endif // ENABLE(CSS_DEVICE_ADAPTATION) + } // namespace WebCore #endif // StyleRule_h diff --git a/Source/WebCore/css/StyleScopeResolver.cpp b/Source/WebCore/css/StyleScopeResolver.cpp index 87402baa5..5ff2b3e0b 100644 --- a/Source/WebCore/css/StyleScopeResolver.cpp +++ b/Source/WebCore/css/StyleScopeResolver.cpp @@ -29,8 +29,10 @@ #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) +#include "CSSStyleRule.h" #include "CSSStyleSheet.h" #include "ContextFeatures.h" +#include "ElementShadow.h" #include "HTMLNames.h" #include "HTMLStyleElement.h" #include "RuleFeature.h" @@ -154,11 +156,91 @@ void StyleScopeResolver::collectFeaturesTo(RuleFeatureSet& features) features.add(it->value->features()); } +inline RuleSet* StyleScopeResolver::ensureAtHostRuleSetFor(const ShadowRoot* shadowRoot) +{ + ScopedRuleSetMap::AddResult addResult = m_atHostRules.add(shadowRoot, nullptr); + if (addResult.isNewEntry) + addResult.iterator->value = RuleSet::create(); + return addResult.iterator->value.get(); +} + +inline RuleSet* StyleScopeResolver::atHostRuleSetFor(const ShadowRoot* shadowRoot) const +{ + ScopedRuleSetMap::const_iterator it = m_atHostRules.find(shadowRoot); + return it != m_atHostRules.end() ? it->value.get() : 0; +} + +void StyleScopeResolver::addHostRule(StyleRuleHost* hostRule, bool hasDocumentSecurityOrigin, const ContainerNode* scope) +{ + if (!scope || !scope->isInShadowTree()) + return; + + ShadowRoot* shadowRoot = scope->shadowRoot(); + if (!shadowRoot || !shadowRoot->host()) + return; + + RuleSet* rule = ensureAtHostRuleSetFor(shadowRoot); + + const Vector<RefPtr<StyleRuleBase> >& childRules = hostRule->childRules(); + AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState; + addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckSelector | RuleIsHostRule); + for (unsigned i = 0; i < childRules.size(); ++i) { + StyleRuleBase* hostStylingRule = childRules[i].get(); + if (hostStylingRule->isStyleRule()) + rule->addStyleRule(static_cast<StyleRule*>(hostStylingRule), addRuleFlags); + } +} + +bool StyleScopeResolver::styleSharingCandidateMatchesHostRules(const Element* element) +{ + if (m_atHostRules.isEmpty()) + return false; + + ElementShadow* shadow = element->shadow(); + if (!shadow) + return false; + + // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827 + // add a new flag to ElementShadow and cache whether any@host @-rules are + // applied to the element or not. So we can avoid always traversing + // shadow roots. + for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { + if (atHostRuleSetFor(shadowRoot)) + return true; + + if (!shadowRoot->hasShadowInsertionPoint()) + break; + } + return false; +} + +void StyleScopeResolver::matchHostRules(const Element* element, Vector<RuleSet*>& matchedRules) +{ + if (m_atHostRules.isEmpty()) + return; + + ElementShadow* shadow = element->shadow(); + if (!shadow) + return; + + // FIXME(99827): https://bugs.webkit.org/show_bug.cgi?id=99827 + // add a new flag to ElementShadow and cache whether any @host @-rules are + // applied to the element or not. So we can quickly exit this method + // by using the flag. + for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { + if (RuleSet* ruleSet = atHostRuleSetFor(shadowRoot)) + matchedRules.append(ruleSet); + if (!shadowRoot->hasShadowInsertionPoint()) + break; + } +} + void StyleScopeResolver::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); info.addMember(m_authorStyles); info.addMember(m_stack); + info.addMember(m_atHostRules); } } diff --git a/Source/WebCore/css/StyleScopeResolver.h b/Source/WebCore/css/StyleScopeResolver.h index 5a32dfe79..3be3ff4f7 100644 --- a/Source/WebCore/css/StyleScopeResolver.h +++ b/Source/WebCore/css/StyleScopeResolver.h @@ -37,8 +37,11 @@ namespace WebCore { class ContainerNode; class CSSStyleSheet; +class Element; class RuleSet; -class RuleFeatureSet; +class ShadowRoot; +class StyleRuleHost; +struct RuleFeatureSet; #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) @@ -72,12 +75,18 @@ public: bool matchesStyleBounds(const StackFrame& frame) const { return frame.m_authorStyleBoundsIndex == m_stackParentBoundsIndex; } void collectFeaturesTo(RuleFeatureSet&); + void addHostRule(StyleRuleHost*, bool hasDocumentSecurityOrigin, const ContainerNode* scope); + bool styleSharingCandidateMatchesHostRules(const Element*); + void matchHostRules(const Element*, Vector<RuleSet*>& matchedRules); + void reportMemoryUsage(MemoryObjectInfo*) const; private: RuleSet* ruleSetFor(const ContainerNode* scope) const; void setupStack(const ContainerNode*); bool stackIsConsistent(const ContainerNode* parent) const { return parent && parent == m_stackParent; } + RuleSet* ensureAtHostRuleSetFor(const ShadowRoot*); + RuleSet* atHostRuleSetFor(const ShadowRoot*) const; ScopedRuleSetMap m_authorStyles; @@ -88,6 +97,8 @@ private: // This is used to decide whether m_scopingElementStack is consistent, separately from SelectorChecker::m_parentStack. const ContainerNode* m_stackParent; int m_stackParentBoundsIndex; + + ScopedRuleSetMap m_atHostRules; }; inline bool StyleScopeResolver::ensureStackConsistency(ContainerNode* parent) diff --git a/Source/WebCore/css/StyleSheetContents.cpp b/Source/WebCore/css/StyleSheetContents.cpp index e7ce81eaa..2f07fce83 100644 --- a/Source/WebCore/css/StyleSheetContents.cpp +++ b/Source/WebCore/css/StyleSheetContents.cpp @@ -435,6 +435,10 @@ static bool childRulesHaveFailedOrCanceledSubresources(const Vector<RefPtr<Style if (childRulesHaveFailedOrCanceledSubresources(static_cast<const StyleRuleRegion*>(rule)->childRules())) return true; break; + case StyleRuleBase::Host: + if (childRulesHaveFailedOrCanceledSubresources(static_cast<const StyleRuleHost*>(rule)->childRules())) + return true; + break; case StyleRuleBase::Import: ASSERT_NOT_REACHED(); case StyleRuleBase::Page: @@ -442,6 +446,9 @@ static bool childRulesHaveFailedOrCanceledSubresources(const Vector<RefPtr<Style case StyleRuleBase::Unknown: case StyleRuleBase::Charset: case StyleRuleBase::Keyframe: +#if ENABLE(CSS_DEVICE_ADAPTATION) + case StyleRuleBase::Viewport: +#endif break; } } diff --git a/Source/WebCore/css/WebKitCSSViewportRule.cpp b/Source/WebCore/css/WebKitCSSViewportRule.cpp new file mode 100644 index 000000000..c815b56b5 --- /dev/null +++ b/Source/WebCore/css/WebKitCSSViewportRule.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#include "WebKitCSSViewportRule.h" + +#if ENABLE(CSS_DEVICE_ADAPTATION) + +#include "PropertySetCSSStyleDeclaration.h" +#include "StylePropertySet.h" +#include "StyleRule.h" +#include "WebCoreMemoryInstrumentation.h" +#include <wtf/text/StringBuilder.h> + +namespace WebCore { + +WebKitCSSViewportRule::WebKitCSSViewportRule(StyleRuleViewport* viewportRule, CSSStyleSheet* sheet) + : CSSRule(sheet, CSSRule::WEBKIT_VIEWPORT_RULE) + , m_viewportRule(viewportRule) +{ +} + +WebKitCSSViewportRule::~WebKitCSSViewportRule() +{ + if (m_propertiesCSSOMWrapper) + m_propertiesCSSOMWrapper->clearParentRule(); +} + +CSSStyleDeclaration* WebKitCSSViewportRule::style() const +{ + if (!m_propertiesCSSOMWrapper) + m_propertiesCSSOMWrapper = StyleRuleCSSStyleDeclaration::create(m_viewportRule->mutableProperties(), const_cast<WebKitCSSViewportRule*>(this)); + + return m_propertiesCSSOMWrapper.get(); +} + +String WebKitCSSViewportRule::cssText() const +{ + StringBuilder result; + result.appendLiteral("@-webkit-viewport { "); + + String decls = m_viewportRule->properties()->asText(); + result.append(decls); + if (!decls.isEmpty()) + result.append(' '); + + result.append('}'); + + return result.toString(); +} + +void WebKitCSSViewportRule::reattach(StyleRuleViewport* rule) +{ + ASSERT(rule); + m_viewportRule = rule; + + if (m_propertiesCSSOMWrapper) + m_propertiesCSSOMWrapper->reattach(m_viewportRule->mutableProperties()); +} + +void WebKitCSSViewportRule::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); + CSSRule::reportBaseClassMemoryUsage(memoryObjectInfo); + info.addMember(m_viewportRule); + info.addMember(m_propertiesCSSOMWrapper); +} + +} // namespace WebCore + +#endif // ENABLE(CSS_DEVICE_ADAPTATION) diff --git a/Source/WebCore/css/WebKitCSSViewportRule.h b/Source/WebCore/css/WebKitCSSViewportRule.h new file mode 100644 index 000000000..e8a27d18c --- /dev/null +++ b/Source/WebCore/css/WebKitCSSViewportRule.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef WebKitCSSViewportRule_h +#define WebKitCSSViewportRule_h + +#if ENABLE(CSS_DEVICE_ADAPTATION) + +#include "CSSRule.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSStyleDeclaration; +class StyleRuleViewport; +class StyleRuleCSSStyleDeclaration; + +class WebKitCSSViewportRule: public CSSRule { +public: + static PassRefPtr<WebKitCSSViewportRule> create(StyleRuleViewport* viewportRule, CSSStyleSheet* sheet) + { + return adoptRef(new WebKitCSSViewportRule(viewportRule, sheet)); + } + ~WebKitCSSViewportRule(); + + CSSStyleDeclaration* style() const; + + String cssText() const; + + void reattach(StyleRuleViewport*); + + void reportDescendantMemoryUsage(MemoryObjectInfo*) const; + +private: + WebKitCSSViewportRule(StyleRuleViewport*, CSSStyleSheet*); + + RefPtr<StyleRuleViewport> m_viewportRule; + + mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; +}; + +} // namespace WebCore + +#endif // WebKitCSSViewportRule_h + +#endif // ENABLE(CSS_DEVICE_ADAPTATION) diff --git a/Source/WebCore/css/html.css b/Source/WebCore/css/html.css index f07fed67b..6b3f258f7 100644 --- a/Source/WebCore/css/html.css +++ b/Source/WebCore/css/html.css @@ -482,7 +482,8 @@ input[type="date"] { -webkit-align-items: stretch; display: -webkit-inline-flex; font-family: monospace; - padding: 0 0 0 1px; + padding: 0; + -webkit-padding-start: 1px; } #endif #if defined(ENABLE_INPUT_TYPE_DATETIME) && ENABLE_INPUT_TYPE_DATETIME @@ -490,7 +491,8 @@ input[type="datetime"] { -webkit-align-items: stretch; display: -webkit-inline-flex; font-family: monospace; - padding: 0 0 0 1px; + padding: 0; + -webkit-padding-start: 1px; } #endif #if defined(ENABLE_INPUT_TYPE_DATETIMELOCAL) && ENABLE_INPUT_TYPE_DATETIMELOCAL @@ -498,7 +500,8 @@ input[type="datetime-local"] { -webkit-align-items: stretch; display: -webkit-inline-flex; font-family: monospace; - padding: 0 0 0 1px; + padding: 0; + -webkit-padding-start: 1px; } #endif #if defined(ENABLE_INPUT_TYPE_MONTH) && ENABLE_INPUT_TYPE_MONTH @@ -506,7 +509,8 @@ input[type="month"] { -webkit-align-items: stretch; display: -webkit-inline-flex; font-family: monospace; - padding: 0 0 0 1px; + padding: 0; + -webkit-padding-start: 1px; } #endif #if defined(ENABLE_INPUT_TYPE_TIME) && ENABLE_INPUT_TYPE_TIME @@ -514,7 +518,8 @@ input[type="time"] { -webkit-align-items: stretch; display: -webkit-inline-flex; font-family: monospace; - padding: 0 0 0 1px; + padding: 0; + -webkit-padding-start: 1px; } #endif #if defined(ENABLE_INPUT_TYPE_WEEK) && ENABLE_INPUT_TYPE_WEEK @@ -522,64 +527,47 @@ input[type="week"] { -webkit-align-items: stretch; display: -webkit-inline-flex; font-family: monospace; - padding: 0 0 0 1px; + padding: 0; + -webkit-padding-start: 1px; } #endif input::-webkit-datetime-edit { - -webkit-align-items: center; -webkit-flex: 1; -webkit-user-modify: read-only !important; - display: -webkit-flex; - white-space: pre; -} - -input::-webkit-datetime-edit-ampm-field { - -webkit-user-modify: read-only !important; - border: none; - padding: 0.15em; - display: inline-block; - text-align: center; -} - -input::-webkit-datetime-edit-day-field { - -webkit-user-modify: read-only !important; display: inline-block; - border: none; - text-align: center; - padding: 0.15em; -} - -input::-webkit-datetime-edit-hour-field { - -webkit-user-modify: read-only !important; - display: inline-block; - border: none; - text-align: center; - padding: 0.15em; + white-space: pre; } -input::-webkit-datetime-edit-millisecond-field { +input::-webkit-datetime-edit-ampm-field, +input::-webkit-datetime-edit-day-field, +input::-webkit-datetime-edit-hour-field, +input::-webkit-datetime-edit-millisecond-field, +input::-webkit-datetime-edit-minute-field, +input::-webkit-datetime-edit-month-field, +input::-webkit-datetime-edit-second-field, +input::-webkit-datetime-edit-week-field, +input::-webkit-datetime-edit-year-field { -webkit-user-modify: read-only !important; - display: inline-block; border: none; - text-align: center; - padding: 0.15em; -} - -input::-webkit-datetime-edit-minute-field { - -webkit-user-modify: read-only !important; display: inline-block; - border: none; + margin: 1px; text-align: center; - padding: 0.15em; } -input::-webkit-datetime-edit-month-field { - -webkit-user-modify: read-only !important; - display: inline-block; - border: none; - text-align: center; - padding: 0.15em; +/* Remove focus ring from fields and use highlight color */ +input::-webkit-datetime-edit-ampm-field:focus, +input::-webkit-datetime-edit-day-field:focus, +input::-webkit-datetime-edit-hour-field:focus, +input::-webkit-datetime-edit-millisecond-field:focus, +input::-webkit-datetime-edit-minute-field:focus, +input::-webkit-datetime-edit-month-field:focus, +input::-webkit-datetime-edit-second-field:focus, +input::-webkit-datetime-edit-week-field:focus, +input::-webkit-datetime-edit-year-field:focus { + background-color: highlight; + color: highlighttext; + outline: none; } /* This selector is used when step >= 3600 second but format contains minute field. */ @@ -587,28 +575,9 @@ input::-webkit-datetime-edit-minute-field[readonly] { color: GrayText; } -input::-webkit-datetime-edit-second-field { - -webkit-user-modify: read-only !important; - display: inline-block; - border: none; - text-align: center; - padding: 0.15em; -} - -input::-webkit-datetime-edit-week-field { - -webkit-user-modify: read-only !important; - display: inline-block; - border: none; - text-align: center; - padding: 0.15em; -} - -input::-webkit-datetime-edit-year-field { - -webkit-user-modify: read-only !important; - display: inline-block; - border: none; - text-align: center; - padding: 0.15em; +/* This selector is used when step >= 60 second but format contains second field. */ +input::-webkit-datetime-edit-second-field[readonly] { + color: GrayText; } input::-webkit-datetime-edit-text { @@ -616,36 +585,10 @@ input::-webkit-datetime-edit-text { display: inline-block; } -input::-webkit-datetime-edit-gap { - -webkit-flex: 1; - -webkit-user-modify: read-only !important; - display: inline-block; -} - input::-webkit-date-and-time-container { -webkit-align-items: center; -webkit-flex: 1; - display: -webkit-flex; -} - -/* Remove focus ring from fields and use highlight color */ -input::-webkit-datetime-edit-ampm-field:focus, -input::-webkit-datetime-edit-day-field:focus, -input::-webkit-datetime-edit-hour-field:focus, -input::-webkit-datetime-edit-millisecond-field:focus, -input::-webkit-datetime-edit-minute-field:focus, -input::-webkit-datetime-edit-month-field:focus, -input::-webkit-datetime-edit-second-field:focus, -input::-webkit-datetime-edit-week-field:focus, -input::-webkit-datetime-edit-year-field:focus { - background-color: highlight; - color: highlighttext; - outline: none; -} - -/* This selector is used when step >= 60 second but format contains second field. */ -input::-webkit-datetime-edit-second-field[readonly] { - color: GrayText; + display: -webkit-inline-flex; } input[type="date"]::-webkit-inner-spin-button, @@ -655,8 +598,8 @@ input[type="month"]::-webkit-inner-spin-button, input[type="time"]::-webkit-inner-spin-button, input[type="week"]::-webkit-inner-spin-button { display: inline-block; - margin-left: 0.2em; position: static; + -webkit-margin-start: 2px; } #endif diff --git a/Source/WebCore/css/mathml.css b/Source/WebCore/css/mathml.css index 205f07688..7c3118ef0 100644 --- a/Source/WebCore/css/mathml.css +++ b/Source/WebCore/css/mathml.css @@ -8,8 +8,16 @@ mtext { line-height: 1.0; } +/* Keep font-family and other defaults here consistent with http://mxr.mozilla.org/mozilla-central/source/layout/mathml/mathml.css and feedback from www-math. */ +math, mfenced > * { + font-family: MathJax_Main, STIXGeneral, "DejaVu Serif", Cambria, "Cambria Math", Times, serif; +} +mo, mfenced { + font-family: MathJax_Main, STIXGeneral, STIXSizeOneSym, "DejaVu Sans", "DejaVu Serif", Cambria, "Cambria Math", + "Lucida Sans Unicode", "Arial Unicode MS", "Lucida Grande", OpenSymbol, "Standard Symbols L", sans-serif; +} + math { - font-family: STIXGeneral, Symbol, "Times New Roman", sans-serif; display: -webkit-inline-flex !important; padding-left: 1px; padding-right: 1px; diff --git a/Source/WebCore/css/mediaControls.css b/Source/WebCore/css/mediaControls.css index 81b0e16b9..6df03402d 100644 --- a/Source/WebCore/css/mediaControls.css +++ b/Source/WebCore/css/mediaControls.css @@ -216,7 +216,7 @@ video::-webkit-media-text-track-container { font-size: 22px; font-family: sans-serif; text-align: center; - color: rgba(255, 255, 255, 0); + color: rgba(255, 255, 255, 1); letter-spacing: normal; word-spacing: normal; @@ -234,8 +234,6 @@ video::-webkit-media-text-track-past-nodes { background-color: rgba(0, 0, 0, 0.8); padding: 2px 2px; - - white-space: pre-wrap; } video::-webkit-media-text-track-future-nodes { @@ -246,11 +244,10 @@ video::-webkit-media-text-track-future-nodes { margin-left: -2px; padding: 2px 2px 2px 0px; - - white-space: pre-wrap; } video::-webkit-media-text-track-display { position: absolute; - color: rgba(255, 255, 255, 1); + overflow: hidden; + white-space: pre-wrap; } diff --git a/Source/WebCore/css/themeBlackBerry.css b/Source/WebCore/css/themeBlackBerry.css index 120ce4981..c4d8f73bb 100644 --- a/Source/WebCore/css/themeBlackBerry.css +++ b/Source/WebCore/css/themeBlackBerry.css @@ -20,10 +20,6 @@ textarea { font-family: monospace; } -input, textarea { - border-radius: 3px; -} - input[type="datetime"], input[type="date"], input[type="week"], @@ -35,22 +31,35 @@ input[type="color"] { border: solid 2px blue; } -select:focus { - border: 1px solid black; - outline: none; +select { + border-radius: 0; +} + +select[size="0"], +select[size="1"] { + border-radius: 0; +} + +::-webkit-validation-bubble-message { + padding-left: 10px; + padding-right: 10px; + background: #fafafa; + border-color: #ffffff; + border-width: 1px; + box-shadow: 2px 2px 4px rgba(100,100,100,0.3), 0 0 4px rgba(100,100,100,0.6); + -webkit-border-radius: 4px; + top: -1px; } -select[size], -select[multiple], -select[size][multiple] { - padding: 5px; - border-radius: 5px; - border: 1px solid rgb(139,139,139); +::-webkit-validation-bubble-arrow { + left: 40px; + top: 3px; + background: #fafafa; + border-color: #ffffff; + border-width: 1px; + box-shadow: 0 0 4px rgba(100,100,100,0.6); } -select[size]:focus, -select[multiple]:focus, -select[size][multiple]:focus { - border: 1px solid black; - outline: none; +::-webkit-validation-bubble-heading { + font-weight: normal; } |