diff options
Diffstat (limited to 'Source/WebCore/css')
54 files changed, 3896 insertions, 1944 deletions
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp index f1c7fdf..4c0571d 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp @@ -25,10 +25,14 @@ #include "CSSComputedStyleDeclaration.h" #include "AnimationController.h" +#include "ContentData.h" +#include "CounterContent.h" #include "CursorList.h" #include "CSSBorderImageValue.h" +#include "CSSLineBoxContainValue.h" #include "CSSMutableStyleDeclaration.h" #include "CSSPrimitiveValue.h" +#include "CSSPrimitiveValueCache.h" #include "CSSPrimitiveValueMappings.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" @@ -197,8 +201,14 @@ static const int computedProperties[] = { #endif CSSPropertyWebkitFontSmoothing, CSSPropertyWebkitHighlight, + CSSPropertyWebkitHyphenateCharacter, + CSSPropertyWebkitHyphenateLimitAfter, + CSSPropertyWebkitHyphenateLimitBefore, + CSSPropertyWebkitHyphens, + CSSPropertyWebkitLineBoxContain, CSSPropertyWebkitLineBreak, CSSPropertyWebkitLineClamp, + CSSPropertyWebkitLocale, CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarqueeDirection, @@ -220,7 +230,11 @@ static const int computedProperties[] = { CSSPropertyWebkitRtlOrdering, CSSPropertyWebkitTextCombine, CSSPropertyWebkitTextDecorationsInEffect, + CSSPropertyWebkitTextEmphasisColor, + CSSPropertyWebkitTextEmphasisPosition, + CSSPropertyWebkitTextEmphasisStyle, CSSPropertyWebkitTextFillColor, + CSSPropertyWebkitTextOrientation, CSSPropertyWebkitTextSecurity, CSSPropertyWebkitTextStrokeColor, CSSPropertyWebkitTextStrokeWidth, @@ -309,10 +323,10 @@ static int valueForRepeatRule(int rule) } } -static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image) +static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, CSSPrimitiveValueCache* primitiveValueCache) { if (!image.hasImage()) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); // Image first. RefPtr<CSSValue> imageValue; @@ -322,27 +336,27 @@ static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image) // Create the slices. RefPtr<CSSPrimitiveValue> top; if (image.slices().top().isPercent()) - top = CSSPrimitiveValue::create(image.slices().top().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + top = primitiveValueCache->createValue(image.slices().top().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - top = CSSPrimitiveValue::create(image.slices().top().value(), CSSPrimitiveValue::CSS_NUMBER); + top = primitiveValueCache->createValue(image.slices().top().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<CSSPrimitiveValue> right; if (image.slices().right().isPercent()) - right = CSSPrimitiveValue::create(image.slices().right().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + right = primitiveValueCache->createValue(image.slices().right().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - right = CSSPrimitiveValue::create(image.slices().right().value(), CSSPrimitiveValue::CSS_NUMBER); + right = primitiveValueCache->createValue(image.slices().right().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<CSSPrimitiveValue> bottom; if (image.slices().bottom().isPercent()) - bottom = CSSPrimitiveValue::create(image.slices().bottom().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + bottom = primitiveValueCache->createValue(image.slices().bottom().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - bottom = CSSPrimitiveValue::create(image.slices().bottom().value(), CSSPrimitiveValue::CSS_NUMBER); + bottom = primitiveValueCache->createValue(image.slices().bottom().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<CSSPrimitiveValue> left; if (image.slices().left().isPercent()) - left = CSSPrimitiveValue::create(image.slices().left().value(), CSSPrimitiveValue::CSS_PERCENTAGE); + left = primitiveValueCache->createValue(image.slices().left().value(), CSSPrimitiveValue::CSS_PERCENTAGE); else - left = CSSPrimitiveValue::create(image.slices().left().value(), CSSPrimitiveValue::CSS_NUMBER); + left = primitiveValueCache->createValue(image.slices().left().value(), CSSPrimitiveValue::CSS_NUMBER); RefPtr<Rect> rect = Rect::create(); rect->setTop(top); @@ -353,38 +367,38 @@ static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image) return CSSBorderImageValue::create(imageValue, rect, valueForRepeatRule(image.horizontalRule()), valueForRepeatRule(image.verticalRule())); } -inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(int value, const RenderStyle* style) +inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(int value, const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) { - return CSSPrimitiveValue::create(adjustForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX); + return primitiveValueCache->createValue(adjustForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX); } -inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle* style) +inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) { - return CSSPrimitiveValue::create(value / style->effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(value / style->effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER); } -static PassRefPtr<CSSValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle* style) +static PassRefPtr<CSSValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) { if (length.isFixed()) - return zoomAdjustedPixelValue(length.value(), style); - return CSSPrimitiveValue::create(length); + return zoomAdjustedPixelValue(length.value(), style, primitiveValueCache); + return primitiveValueCache->createValue(length); } -static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle* style) +static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) { if (!reflection) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); RefPtr<CSSPrimitiveValue> offset; if (reflection->offset().isPercent()) - offset = CSSPrimitiveValue::create(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE); + offset = primitiveValueCache->createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE); else - offset = zoomAdjustedPixelValue(reflection->offset().value(), style); + offset = zoomAdjustedPixelValue(reflection->offset().value(), style, primitiveValueCache); - return CSSReflectValue::create(reflection->direction(), offset.release(), valueForNinePieceImage(reflection->mask())); + return CSSReflectValue::create(reflection->direction(), offset.release(), valueForNinePieceImage(reflection->mask(), primitiveValueCache)); } -static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, int propertyID) +static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, int propertyID, CSSPrimitiveValueCache* primitiveValueCache) { if (!style) return 0; @@ -409,43 +423,44 @@ static PassRefPtr<CSSValue> getPositionOffsetValue(RenderStyle* style, int prope if (style->position() == AbsolutePosition || style->position() == FixedPosition) { if (l.type() == WebCore::Fixed) - return zoomAdjustedPixelValue(l.value(), style); - return CSSPrimitiveValue::create(l); + return zoomAdjustedPixelValue(l.value(), style, primitiveValueCache); + return primitiveValueCache->createValue(l); } if (style->position() == RelativePosition) // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined. // In other words if left is auto and right is not auto, then left's computed value is negative right(). // So we should get the opposite length unit and see if it is auto. - return CSSPrimitiveValue::create(l); + return primitiveValueCache->createValue(l); - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); } PassRefPtr<CSSPrimitiveValue> CSSComputedStyleDeclaration::currentColorOrValidColor(RenderStyle* style, const Color& color) const { // This function does NOT look at visited information, so that computed style doesn't expose that. + CSSPrimitiveValueCache* primitiveValueCache = m_node->document()->cssPrimitiveValueCache().get(); if (!color.isValid()) - return CSSPrimitiveValue::createColor(style->color().rgb()); - return CSSPrimitiveValue::createColor(color.rgb()); + return primitiveValueCache->createColorValue(style->color().rgb()); + return primitiveValueCache->createColorValue(color.rgb()); } -static PassRefPtr<CSSValue> getBorderRadiusCornerValue(LengthSize radius, const RenderStyle* style) +static PassRefPtr<CSSValue> getBorderRadiusCornerValue(LengthSize radius, const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (radius.width() == radius.height()) { if (radius.width().type() == Percent) - return CSSPrimitiveValue::create(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE); - return zoomAdjustedPixelValue(radius.width().value(), style); + return primitiveValueCache->createValue(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE); + return zoomAdjustedPixelValue(radius.width().value(), style, primitiveValueCache); } if (radius.width().type() == Percent) - list->append(CSSPrimitiveValue::create(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE)); + list->append(primitiveValueCache->createValue(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE)); else - list->append(zoomAdjustedPixelValue(radius.width().value(), style)); + list->append(zoomAdjustedPixelValue(radius.width().value(), style, primitiveValueCache)); if (radius.height().type() == Percent) - list->append(CSSPrimitiveValue::create(radius.height().percent(), CSSPrimitiveValue::CSS_PERCENTAGE)); + list->append(primitiveValueCache->createValue(radius.height().percent(), CSSPrimitiveValue::CSS_PERCENTAGE)); else - list->append(zoomAdjustedPixelValue(radius.height().value(), style)); + list->append(zoomAdjustedPixelValue(radius.height().value(), style, primitiveValueCache)); return list.release(); } @@ -463,10 +478,10 @@ static inline bool hasCompositedLayer(RenderObject* renderer) return renderer && renderer->hasLayer() && toRenderBoxModelObject(renderer)->layer()->isComposited(); } -static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle* style) +static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) { if (!renderer || style->transform().operations().isEmpty()) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); IntRect box = sizingBox(renderer); @@ -480,34 +495,34 @@ static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const Rend if (transform.isAffine()) { transformVal = WebKitCSSTransformValue::create(WebKitCSSTransformValue::MatrixTransformOperation); - transformVal->append(CSSPrimitiveValue::create(transform.a(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.b(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.c(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.d(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(zoomAdjustedNumberValue(transform.e(), style)); - transformVal->append(zoomAdjustedNumberValue(transform.f(), style)); + transformVal->append(primitiveValueCache->createValue(transform.a(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.b(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.c(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.d(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(zoomAdjustedNumberValue(transform.e(), style, primitiveValueCache)); + transformVal->append(zoomAdjustedNumberValue(transform.f(), style, primitiveValueCache)); } else { transformVal = WebKitCSSTransformValue::create(WebKitCSSTransformValue::Matrix3DTransformOperation); - transformVal->append(CSSPrimitiveValue::create(transform.m11(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m12(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m13(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m14(), CSSPrimitiveValue::CSS_NUMBER)); - - transformVal->append(CSSPrimitiveValue::create(transform.m21(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m22(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m23(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m24(), CSSPrimitiveValue::CSS_NUMBER)); - - transformVal->append(CSSPrimitiveValue::create(transform.m31(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m32(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m33(), CSSPrimitiveValue::CSS_NUMBER)); - transformVal->append(CSSPrimitiveValue::create(transform.m34(), CSSPrimitiveValue::CSS_NUMBER)); - - transformVal->append(zoomAdjustedNumberValue(transform.m41(), style)); - transformVal->append(zoomAdjustedNumberValue(transform.m42(), style)); - transformVal->append(zoomAdjustedNumberValue(transform.m43(), style)); - transformVal->append(CSSPrimitiveValue::create(transform.m44(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m11(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m12(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m13(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m14(), CSSPrimitiveValue::CSS_NUMBER)); + + transformVal->append(primitiveValueCache->createValue(transform.m21(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m22(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m23(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m24(), CSSPrimitiveValue::CSS_NUMBER)); + + transformVal->append(primitiveValueCache->createValue(transform.m31(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m32(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m33(), CSSPrimitiveValue::CSS_NUMBER)); + transformVal->append(primitiveValueCache->createValue(transform.m34(), CSSPrimitiveValue::CSS_NUMBER)); + + transformVal->append(zoomAdjustedNumberValue(transform.m41(), style, primitiveValueCache)); + transformVal->append(zoomAdjustedNumberValue(transform.m42(), style, primitiveValueCache)); + transformVal->append(zoomAdjustedNumberValue(transform.m43(), style, primitiveValueCache)); + transformVal->append(primitiveValueCache->createValue(transform.m44(), CSSPrimitiveValue::CSS_NUMBER)); } RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); @@ -516,28 +531,28 @@ static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const Rend return list.release(); } -static PassRefPtr<CSSValue> getDelayValue(const AnimationList* animList) +static PassRefPtr<CSSValue> getDelayValue(const AnimationList* animList, CSSPrimitiveValueCache* primitiveValueCache) { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); if (animList) { for (size_t i = 0; i < animList->size(); ++i) - list->append(CSSPrimitiveValue::create(animList->animation(i)->delay(), CSSPrimitiveValue::CSS_S)); + list->append(primitiveValueCache->createValue(animList->animation(i)->delay(), CSSPrimitiveValue::CSS_S)); } else { // Note that initialAnimationDelay() is used for both transitions and animations - list->append(CSSPrimitiveValue::create(Animation::initialAnimationDelay(), CSSPrimitiveValue::CSS_S)); + list->append(primitiveValueCache->createValue(Animation::initialAnimationDelay(), CSSPrimitiveValue::CSS_S)); } return list.release(); } -static PassRefPtr<CSSValue> getDurationValue(const AnimationList* animList) +static PassRefPtr<CSSValue> getDurationValue(const AnimationList* animList, CSSPrimitiveValueCache* primitiveValueCache) { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); if (animList) { for (size_t i = 0; i < animList->size(); ++i) - list->append(CSSPrimitiveValue::create(animList->animation(i)->duration(), CSSPrimitiveValue::CSS_S)); + list->append(primitiveValueCache->createValue(animList->animation(i)->duration(), CSSPrimitiveValue::CSS_S)); } else { // Note that initialAnimationDuration() is used for both transitions and animations - list->append(CSSPrimitiveValue::create(Animation::initialAnimationDuration(), CSSPrimitiveValue::CSS_S)); + list->append(primitiveValueCache->createValue(Animation::initialAnimationDuration(), CSSPrimitiveValue::CSS_S)); } return list.release(); } @@ -574,6 +589,13 @@ static PassRefPtr<CSSValue> getTimingFunctionValue(const AnimationList* animList return list.release(); } +static PassRefPtr<CSSValue> createLineBoxContainValue(CSSPrimitiveValueCache* primitiveValueCache, unsigned lineBoxContain) +{ + if (!lineBoxContain) + return primitiveValueCache->createIdentifierValue(CSSValueNone); + return CSSLineBoxContainValue::create(lineBoxContain); +} + CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n, bool allowVisitedStyle, const String& pseudoElementName) : m_node(n) , m_allowVisitedStyle(allowVisitedStyle) @@ -625,12 +647,14 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getFontSizeCSSValuePreferringK RefPtr<RenderStyle> style = m_node->computedStyle(m_pseudoElementSpecifier); if (!style) return 0; + + CSSPrimitiveValueCache* primitiveValueCache = m_node->document()->cssPrimitiveValueCache().get(); if (int keywordSize = style->fontDescription().keywordSize()) - return CSSPrimitiveValue::createIdentifier(cssIdentifierForFontSizeKeyword(keywordSize)); + return primitiveValueCache->createIdentifierValue(cssIdentifierForFontSizeKeyword(keywordSize)); - return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style.get()); + return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style.get(), primitiveValueCache); } bool CSSComputedStyleDeclaration::useFixedFontDefaultSize() const @@ -647,19 +671,20 @@ bool CSSComputedStyleDeclaration::useFixedFontDefaultSize() const PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadow(const ShadowData* shadow, int id, RenderStyle* style) const { + CSSPrimitiveValueCache* primitiveValueCache = m_node->document()->cssPrimitiveValueCache().get(); if (!shadow) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); CSSPropertyID propertyID = static_cast<CSSPropertyID>(id); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const ShadowData* s = shadow; s; s = s->next()) { - RefPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(s->x(), style); - RefPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(s->y(), style); - RefPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(s->blur(), style); - RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? 0 : zoomAdjustedPixelValue(s->spread(), style); - RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || s->style() == Normal ? 0 : CSSPrimitiveValue::createIdentifier(CSSValueInset); - RefPtr<CSSPrimitiveValue> color = CSSPrimitiveValue::createColor(s->color().rgb()); + RefPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(s->x(), style, primitiveValueCache); + RefPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(s->y(), style, primitiveValueCache); + RefPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(s->blur(), style, primitiveValueCache); + RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? PassRefPtr<CSSPrimitiveValue>() : zoomAdjustedPixelValue(s->spread(), style, primitiveValueCache); + RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || s->style() == Normal ? PassRefPtr<CSSPrimitiveValue>() : primitiveValueCache->createIdentifierValue(CSSValueInset); + RefPtr<CSSPrimitiveValue> color = primitiveValueCache->createColorValue(s->color().rgb()); list->prepend(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release())); } return list.release(); @@ -690,58 +715,91 @@ static int identifierForFamily(const AtomicString& family) return 0; } -static PassRefPtr<CSSPrimitiveValue> valueForFamily(const AtomicString& family) +static PassRefPtr<CSSPrimitiveValue> valueForFamily(const AtomicString& family, CSSPrimitiveValueCache* primitiveValueCache) { if (int familyIdentifier = identifierForFamily(family)) - return CSSPrimitiveValue::createIdentifier(familyIdentifier); - return CSSPrimitiveValue::create(family.string(), CSSPrimitiveValue::CSS_STRING); + return primitiveValueCache->createIdentifierValue(familyIdentifier); + return primitiveValueCache->createValue(family.string(), CSSPrimitiveValue::CSS_STRING); } -static PassRefPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration) +static PassRefPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration, CSSPrimitiveValueCache* primitiveValueCache) { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (textDecoration & UNDERLINE) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueUnderline)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueUnderline)); if (textDecoration & OVERLINE) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueOverline)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueOverline)); if (textDecoration & LINE_THROUGH) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueLineThrough)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueLineThrough)); if (textDecoration & BLINK) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueBlink)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueBlink)); if (!list->length()) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); return list; } -static PassRefPtr<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepeat yRepeat) +static PassRefPtr<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepeat yRepeat, CSSPrimitiveValueCache* primitiveValueCache) { // For backwards compatibility, if both values are equal, just return one of them. And // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand. if (xRepeat == yRepeat) - return CSSPrimitiveValue::create(xRepeat); + return primitiveValueCache->createValue(xRepeat); if (xRepeat == RepeatFill && yRepeat == NoRepeatFill) - return CSSPrimitiveValue::createIdentifier(CSSValueRepeatX); + return primitiveValueCache->createIdentifierValue(CSSValueRepeatX); if (xRepeat == NoRepeatFill && yRepeat == RepeatFill) - return CSSPrimitiveValue::createIdentifier(CSSValueRepeatY); + return primitiveValueCache->createIdentifierValue(CSSValueRepeatY); RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - list->append(CSSPrimitiveValue::create(xRepeat)); - list->append(CSSPrimitiveValue::create(yRepeat)); + list->append(primitiveValueCache->createValue(xRepeat)); + list->append(primitiveValueCache->createValue(yRepeat)); return list.release(); } -static PassRefPtr<CSSValue> fillSizeToCSSValue(const FillSize& fillSize) +static PassRefPtr<CSSValue> fillSizeToCSSValue(const FillSize& fillSize, CSSPrimitiveValueCache* primitiveValueCache) { if (fillSize.type == Contain) - return CSSPrimitiveValue::createIdentifier(CSSValueContain); + return primitiveValueCache->createIdentifierValue(CSSValueContain); if (fillSize.type == Cover) - return CSSPrimitiveValue::createIdentifier(CSSValueCover); + return primitiveValueCache->createIdentifierValue(CSSValueCover); + + RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + list->append(primitiveValueCache->createValue(fillSize.size.width())); + list->append(primitiveValueCache->createValue(fillSize.size.height())); + return list.release(); +} + +static PassRefPtr<CSSValue> contentToCSSValue(const RenderStyle* style, CSSPrimitiveValueCache* primitiveValueCache) +{ + RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + for (const ContentData* contentData = style->contentData(); contentData; contentData = contentData->next()) { + if (contentData->isCounter()) { + const CounterContent* counter = contentData->counter(); + ASSERT(counter); + list->append(primitiveValueCache->createValue(counter->identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME)); + } else if (contentData->isImage()) { + const StyleImage* image = contentData->image(); + ASSERT(image); + list->append(image->cssValue()); + } else if (contentData->isText()) + list->append(primitiveValueCache->createValue(contentData->text(), CSSPrimitiveValue::CSS_STRING)); + } + return list.release(); +} + +static PassRefPtr<CSSValue> counterToCSSValue(const RenderStyle* style, int propertyID, CSSPrimitiveValueCache* primitiveValueCache) +{ + const CounterDirectiveMap* map = style->counterDirectives(); + if (!map) + return 0; RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - list->append(CSSPrimitiveValue::create(fillSize.size.width())); - list->append(CSSPrimitiveValue::create(fillSize.size.height())); + for (CounterDirectiveMap::const_iterator it = map->begin(); it != map->end(); ++it) { + list->append(primitiveValueCache->createValue(it->first.get(), CSSPrimitiveValue::CSS_STRING)); + short number = propertyID == CSSPropertyCounterIncrement ? it->second.m_incrementValue : it->second.m_resetValue; + list->append(primitiveValueCache->createValue((double)number, CSSPrimitiveValue::CSS_NUMBER)); + } return list.release(); } @@ -778,6 +836,8 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper if (!style) return 0; + + CSSPrimitiveValueCache* primitiveValueCache = node->document()->cssPrimitiveValueCache().get(); propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode()); #ifdef ANDROID_LAYOUT @@ -789,18 +849,18 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper break; case CSSPropertyBackgroundColor: - return CSSPrimitiveValue::createColor(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor).rgb() : style->backgroundColor().rgb()); + return primitiveValueCache->createColorValue(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor).rgb() : style->backgroundColor().rgb()); case CSSPropertyBackgroundImage: case CSSPropertyWebkitMaskImage: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskImage ? style->maskLayers() : style->backgroundLayers(); if (!layers) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); if (!layers->next()) { if (layers->image()) return layers->image()->cssValue(); - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); } RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); @@ -808,7 +868,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper if (currLayer->image()) list->append(currLayer->image()->cssValue()); else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueNone)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueNone)); } return list.release(); } @@ -817,11 +877,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMaskSize: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskSize ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return fillSizeToCSSValue(layers->size()); + return fillSizeToCSSValue(layers->size(), primitiveValueCache); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(fillSizeToCSSValue(currLayer->size())); + list->append(fillSizeToCSSValue(currLayer->size(), primitiveValueCache)); return list.release(); } @@ -829,11 +889,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMaskRepeat: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskRepeat ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return fillRepeatToCSSValue(layers->repeatX(), layers->repeatY()); + return fillRepeatToCSSValue(layers->repeatX(), layers->repeatY(), primitiveValueCache); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY())); + list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY(), primitiveValueCache)); return list.release(); } @@ -841,11 +901,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMaskComposite: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskComposite ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return CSSPrimitiveValue::create(layers->composite()); + return primitiveValueCache->createValue(layers->composite()); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(CSSPrimitiveValue::create(currLayer->composite())); + list->append(primitiveValueCache->createValue(currLayer->composite())); return list.release(); } @@ -853,11 +913,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMaskAttachment: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskAttachment ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return CSSPrimitiveValue::create(layers->attachment()); + return primitiveValueCache->createValue(layers->attachment()); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(CSSPrimitiveValue::create(currLayer->attachment())); + list->append(primitiveValueCache->createValue(currLayer->attachment())); return list.release(); } @@ -871,13 +931,13 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip; if (!layers->next()) { EFillBox box = isClip ? layers->clip() : layers->origin(); - return CSSPrimitiveValue::create(box); + return primitiveValueCache->createValue(box); } RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) { EFillBox box = isClip ? currLayer->clip() : currLayer->origin(); - list->append(CSSPrimitiveValue::create(box)); + list->append(primitiveValueCache->createValue(box)); } return list.release(); @@ -887,16 +947,16 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPosition ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - list->append(CSSPrimitiveValue::create(layers->xPosition())); - list->append(CSSPrimitiveValue::create(layers->yPosition())); + list->append(primitiveValueCache->createValue(layers->xPosition())); + list->append(primitiveValueCache->createValue(layers->yPosition())); return list.release(); } RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) { RefPtr<CSSValueList> positionList = CSSValueList::createSpaceSeparated(); - positionList->append(CSSPrimitiveValue::create(currLayer->xPosition())); - positionList->append(CSSPrimitiveValue::create(currLayer->yPosition())); + positionList->append(primitiveValueCache->createValue(currLayer->xPosition())); + positionList->append(primitiveValueCache->createValue(currLayer->yPosition())); list->append(positionList); } @@ -906,11 +966,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMaskPositionX: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionX ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return CSSPrimitiveValue::create(layers->xPosition()); + return primitiveValueCache->createValue(layers->xPosition()); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(CSSPrimitiveValue::create(currLayer->xPosition())); + list->append(primitiveValueCache->createValue(currLayer->xPosition())); return list.release(); } @@ -918,115 +978,115 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyWebkitMaskPositionY: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionY ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return CSSPrimitiveValue::create(layers->yPosition()); + return primitiveValueCache->createValue(layers->yPosition()); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(CSSPrimitiveValue::create(currLayer->yPosition())); + list->append(primitiveValueCache->createValue(currLayer->yPosition())); return list.release(); } case CSSPropertyBorderCollapse: if (style->borderCollapse()) - return CSSPrimitiveValue::createIdentifier(CSSValueCollapse); - return CSSPrimitiveValue::createIdentifier(CSSValueSeparate); + return primitiveValueCache->createIdentifierValue(CSSValueCollapse); + return primitiveValueCache->createIdentifierValue(CSSValueSeparate); case CSSPropertyBorderSpacing: { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get())); - list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get())); + list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get(), primitiveValueCache)); + list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get(), primitiveValueCache)); return list.release(); } case CSSPropertyWebkitBorderHorizontalSpacing: - return zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get()); + return zoomAdjustedPixelValue(style->horizontalBorderSpacing(), style.get(), primitiveValueCache); case CSSPropertyWebkitBorderVerticalSpacing: - return zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get()); + return zoomAdjustedPixelValue(style->verticalBorderSpacing(), style.get(), primitiveValueCache); case CSSPropertyBorderTopColor: - return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderTopColor).rgb()) : currentColorOrValidColor(style.get(), style->borderTopColor()); + return m_allowVisitedStyle ? primitiveValueCache->createColorValue(style->visitedDependentColor(CSSPropertyBorderTopColor).rgb()) : currentColorOrValidColor(style.get(), style->borderTopColor()); case CSSPropertyBorderRightColor: - return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderRightColor).rgb()) : currentColorOrValidColor(style.get(), style->borderRightColor()); + return m_allowVisitedStyle ? primitiveValueCache->createColorValue(style->visitedDependentColor(CSSPropertyBorderRightColor).rgb()) : currentColorOrValidColor(style.get(), style->borderRightColor()); case CSSPropertyBorderBottomColor: - return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderBottomColor).rgb()) : currentColorOrValidColor(style.get(), style->borderBottomColor()); + return m_allowVisitedStyle ? primitiveValueCache->createColorValue(style->visitedDependentColor(CSSPropertyBorderBottomColor).rgb()) : currentColorOrValidColor(style.get(), style->borderBottomColor()); case CSSPropertyBorderLeftColor: - return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyBorderLeftColor).rgb()) : currentColorOrValidColor(style.get(), style->borderLeftColor()); + return m_allowVisitedStyle ? primitiveValueCache->createColorValue(style->visitedDependentColor(CSSPropertyBorderLeftColor).rgb()) : currentColorOrValidColor(style.get(), style->borderLeftColor()); case CSSPropertyBorderTopStyle: - return CSSPrimitiveValue::create(style->borderTopStyle()); + return primitiveValueCache->createValue(style->borderTopStyle()); case CSSPropertyBorderRightStyle: - return CSSPrimitiveValue::create(style->borderRightStyle()); + return primitiveValueCache->createValue(style->borderRightStyle()); case CSSPropertyBorderBottomStyle: - return CSSPrimitiveValue::create(style->borderBottomStyle()); + return primitiveValueCache->createValue(style->borderBottomStyle()); case CSSPropertyBorderLeftStyle: - return CSSPrimitiveValue::create(style->borderLeftStyle()); + return primitiveValueCache->createValue(style->borderLeftStyle()); case CSSPropertyBorderTopWidth: - return zoomAdjustedPixelValue(style->borderTopWidth(), style.get()); + return zoomAdjustedPixelValue(style->borderTopWidth(), style.get(), primitiveValueCache); case CSSPropertyBorderRightWidth: - return zoomAdjustedPixelValue(style->borderRightWidth(), style.get()); + return zoomAdjustedPixelValue(style->borderRightWidth(), style.get(), primitiveValueCache); case CSSPropertyBorderBottomWidth: - return zoomAdjustedPixelValue(style->borderBottomWidth(), style.get()); + return zoomAdjustedPixelValue(style->borderBottomWidth(), style.get(), primitiveValueCache); case CSSPropertyBorderLeftWidth: - return zoomAdjustedPixelValue(style->borderLeftWidth(), style.get()); + return zoomAdjustedPixelValue(style->borderLeftWidth(), style.get(), primitiveValueCache); case CSSPropertyBottom: - return getPositionOffsetValue(style.get(), CSSPropertyBottom); + return getPositionOffsetValue(style.get(), CSSPropertyBottom, primitiveValueCache); case CSSPropertyWebkitBoxAlign: - return CSSPrimitiveValue::create(style->boxAlign()); + return primitiveValueCache->createValue(style->boxAlign()); case CSSPropertyWebkitBoxDirection: - return CSSPrimitiveValue::create(style->boxDirection()); + return primitiveValueCache->createValue(style->boxDirection()); case CSSPropertyWebkitBoxFlex: - return CSSPrimitiveValue::create(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitBoxFlexGroup: - return CSSPrimitiveValue::create(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitBoxLines: - return CSSPrimitiveValue::create(style->boxLines()); + return primitiveValueCache->createValue(style->boxLines()); case CSSPropertyWebkitBoxOrdinalGroup: - return CSSPrimitiveValue::create(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitBoxOrient: - return CSSPrimitiveValue::create(style->boxOrient()); + return primitiveValueCache->createValue(style->boxOrient()); case CSSPropertyWebkitBoxPack: { EBoxAlignment boxPack = style->boxPack(); ASSERT(boxPack != BSTRETCH); ASSERT(boxPack != BBASELINE); if (boxPack == BJUSTIFY || boxPack== BBASELINE) return 0; - return CSSPrimitiveValue::create(boxPack); + return primitiveValueCache->createValue(boxPack); } case CSSPropertyWebkitBoxReflect: - return valueForReflection(style->boxReflect(), style.get()); + return valueForReflection(style->boxReflect(), style.get(), primitiveValueCache); case CSSPropertyBoxShadow: case CSSPropertyWebkitBoxShadow: return valueForShadow(style->boxShadow(), propertyID, style.get()); case CSSPropertyCaptionSide: - return CSSPrimitiveValue::create(style->captionSide()); + return primitiveValueCache->createValue(style->captionSide()); case CSSPropertyClear: - return CSSPrimitiveValue::create(style->clear()); + return primitiveValueCache->createValue(style->clear()); case CSSPropertyColor: - return CSSPrimitiveValue::createColor(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor).rgb() : style->color().rgb()); + return primitiveValueCache->createColorValue(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor).rgb() : style->color().rgb()); case CSSPropertyWebkitColumnCount: if (style->hasAutoColumnCount()) - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::create(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createValue(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitColumnGap: if (style->hasNormalColumnGap()) - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); - return CSSPrimitiveValue::create(style->columnGap(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); + return primitiveValueCache->createValue(style->columnGap(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitColumnRuleColor: - return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->columnRuleColor()); + return m_allowVisitedStyle ? primitiveValueCache->createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->columnRuleColor()); case CSSPropertyWebkitColumnRuleStyle: - return CSSPrimitiveValue::create(style->columnRuleStyle()); + return primitiveValueCache->createValue(style->columnRuleStyle()); case CSSPropertyWebkitColumnRuleWidth: - return zoomAdjustedPixelValue(style->columnRuleWidth(), style.get()); + return zoomAdjustedPixelValue(style->columnRuleWidth(), style.get(), primitiveValueCache); case CSSPropertyWebkitColumnSpan: if (style->columnSpan()) - return CSSPrimitiveValue::createIdentifier(CSSValueAll); - return CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueAll); + return primitiveValueCache->createValue(1, CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitColumnBreakAfter: - return CSSPrimitiveValue::create(style->columnBreakAfter()); + return primitiveValueCache->createValue(style->columnBreakAfter()); case CSSPropertyWebkitColumnBreakBefore: - return CSSPrimitiveValue::create(style->columnBreakBefore()); + return primitiveValueCache->createValue(style->columnBreakBefore()); case CSSPropertyWebkitColumnBreakInside: - return CSSPrimitiveValue::create(style->columnBreakInside()); + return primitiveValueCache->createValue(style->columnBreakInside()); case CSSPropertyWebkitColumnWidth: if (style->hasAutoColumnWidth()) - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::create(style->columnWidth(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createValue(style->columnWidth(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyCursor: { RefPtr<CSSValueList> list; CursorList* cursors = style->cursors(); @@ -1036,7 +1096,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper if (StyleImage* image = cursors->at(i).image()) list->append(image->cssValue()); } - RefPtr<CSSValue> value = CSSPrimitiveValue::create(style->cursor()); + RefPtr<CSSValue> value = primitiveValueCache->createValue(style->cursor()); if (list) { list->append(value); return list.release(); @@ -1044,240 +1104,250 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper return value.release(); } case CSSPropertyDirection: - return CSSPrimitiveValue::create(style->direction()); + return primitiveValueCache->createValue(style->direction()); case CSSPropertyDisplay: - return CSSPrimitiveValue::create(style->display()); + return primitiveValueCache->createValue(style->display()); case CSSPropertyEmptyCells: - return CSSPrimitiveValue::create(style->emptyCells()); + return primitiveValueCache->createValue(style->emptyCells()); case CSSPropertyFloat: #ifdef ANDROID_LAYOUT if (settings && settings->layoutAlgorithm() == Settings::kLayoutSSR) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); #endif - return CSSPrimitiveValue::create(style->floating()); + return primitiveValueCache->createValue(style->floating()); case CSSPropertyFontFamily: { const FontFamily& firstFamily = style->fontDescription().family(); if (!firstFamily.next()) - return valueForFamily(firstFamily.family()); + return valueForFamily(firstFamily.family(), primitiveValueCache); RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FontFamily* family = &firstFamily; family; family = family->next()) - list->append(valueForFamily(family->family())); + list->append(valueForFamily(family->family(), primitiveValueCache)); return list.release(); } case CSSPropertyFontSize: - return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style.get()); + return zoomAdjustedPixelValue(style->fontDescription().computedPixelSize(), style.get(), primitiveValueCache); case CSSPropertyFontStyle: if (style->fontDescription().italic()) - return CSSPrimitiveValue::createIdentifier(CSSValueItalic); - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); + return primitiveValueCache->createIdentifierValue(CSSValueItalic); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); case CSSPropertyFontVariant: if (style->fontDescription().smallCaps()) - return CSSPrimitiveValue::createIdentifier(CSSValueSmallCaps); - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); + return primitiveValueCache->createIdentifierValue(CSSValueSmallCaps); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); case CSSPropertyFontWeight: switch (style->fontDescription().weight()) { case FontWeight100: - return CSSPrimitiveValue::createIdentifier(CSSValue100); + return primitiveValueCache->createIdentifierValue(CSSValue100); case FontWeight200: - return CSSPrimitiveValue::createIdentifier(CSSValue200); + return primitiveValueCache->createIdentifierValue(CSSValue200); case FontWeight300: - return CSSPrimitiveValue::createIdentifier(CSSValue300); + return primitiveValueCache->createIdentifierValue(CSSValue300); case FontWeightNormal: - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); case FontWeight500: - return CSSPrimitiveValue::createIdentifier(CSSValue500); + return primitiveValueCache->createIdentifierValue(CSSValue500); case FontWeight600: - return CSSPrimitiveValue::createIdentifier(CSSValue600); + return primitiveValueCache->createIdentifierValue(CSSValue600); case FontWeightBold: - return CSSPrimitiveValue::createIdentifier(CSSValueBold); + return primitiveValueCache->createIdentifierValue(CSSValueBold); case FontWeight800: - return CSSPrimitiveValue::createIdentifier(CSSValue800); + return primitiveValueCache->createIdentifierValue(CSSValue800); case FontWeight900: - return CSSPrimitiveValue::createIdentifier(CSSValue900); + return primitiveValueCache->createIdentifierValue(CSSValue900); } ASSERT_NOT_REACHED(); - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); case CSSPropertyHeight: if (renderer) - return zoomAdjustedPixelValue(sizingBox(renderer).height(), style.get()); - return zoomAdjustedPixelValueForLength(style->height(), style.get()); + return zoomAdjustedPixelValue(sizingBox(renderer).height(), style.get(), primitiveValueCache); + return zoomAdjustedPixelValueForLength(style->height(), style.get(), primitiveValueCache); case CSSPropertyWebkitHighlight: if (style->highlight() == nullAtom) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); - return CSSPrimitiveValue::create(style->highlight(), CSSPrimitiveValue::CSS_STRING); + return primitiveValueCache->createIdentifierValue(CSSValueNone); + return primitiveValueCache->createValue(style->highlight(), CSSPrimitiveValue::CSS_STRING); case CSSPropertyWebkitHyphens: - return CSSPrimitiveValue::create(style->hyphens()); + return primitiveValueCache->createValue(style->hyphens()); case CSSPropertyWebkitHyphenateCharacter: if (style->hyphenationString().isNull()) + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createValue(style->hyphenationString(), CSSPrimitiveValue::CSS_STRING); + case CSSPropertyWebkitHyphenateLimitAfter: + if (style->hyphenationLimitAfter() < 0) return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::create(style->hyphenationString(), CSSPrimitiveValue::CSS_STRING); - case CSSPropertyWebkitHyphenateLocale: - if (style->hyphenationLocale().isNull()) + return CSSPrimitiveValue::create(style->hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER); + case CSSPropertyWebkitHyphenateLimitBefore: + if (style->hyphenationLimitBefore() < 0) return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::create(style->hyphenationLocale(), CSSPrimitiveValue::CSS_STRING); + return CSSPrimitiveValue::create(style->hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitBorderFit: if (style->borderFit() == BorderFitBorder) - return CSSPrimitiveValue::createIdentifier(CSSValueBorder); - return CSSPrimitiveValue::createIdentifier(CSSValueLines); + return primitiveValueCache->createIdentifierValue(CSSValueBorder); + return primitiveValueCache->createIdentifierValue(CSSValueLines); case CSSPropertyLeft: - return getPositionOffsetValue(style.get(), CSSPropertyLeft); + return getPositionOffsetValue(style.get(), CSSPropertyLeft, primitiveValueCache); case CSSPropertyLetterSpacing: if (!style->letterSpacing()) - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); - return zoomAdjustedPixelValue(style->letterSpacing(), style.get()); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); + return zoomAdjustedPixelValue(style->letterSpacing(), style.get(), primitiveValueCache); case CSSPropertyWebkitLineClamp: if (style->lineClamp().isNone()) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); - return CSSPrimitiveValue::create(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueNone); + return primitiveValueCache->createValue(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyLineHeight: { Length length = style->lineHeight(); if (length.isNegative()) - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); if (length.isPercent()) // This is imperfect, because it doesn't include the zoom factor and the real computation // for how high to be in pixels does include things like minimum font size and the zoom factor. // On the other hand, since font-size doesn't include the zoom factor, we really can't do // that here either. - return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style->fontDescription().specifiedSize()) / 100, style.get()); - return zoomAdjustedPixelValue(length.value(), style.get()); + return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style->fontDescription().specifiedSize()) / 100, style.get(), primitiveValueCache); + return zoomAdjustedPixelValue(length.value(), style.get(), primitiveValueCache); } case CSSPropertyListStyleImage: if (style->listStyleImage()) return style->listStyleImage()->cssValue(); - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); case CSSPropertyListStylePosition: - return CSSPrimitiveValue::create(style->listStylePosition()); + return primitiveValueCache->createValue(style->listStylePosition()); case CSSPropertyListStyleType: - return CSSPrimitiveValue::create(style->listStyleType()); + return primitiveValueCache->createValue(style->listStyleType()); + case CSSPropertyWebkitLocale: + if (style->locale().isNull()) + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createValue(style->locale(), CSSPrimitiveValue::CSS_STRING); case CSSPropertyMarginTop: { Length marginTop = style->marginTop(); if (marginTop.isPercent()) - return CSSPrimitiveValue::create(marginTop); - return zoomAdjustedPixelValue(marginTop.value(), style.get()); + return primitiveValueCache->createValue(marginTop); + return zoomAdjustedPixelValue(marginTop.value(), style.get(), primitiveValueCache); } case CSSPropertyMarginRight: { Length marginRight = style->marginRight(); if (marginRight.isPercent()) - return CSSPrimitiveValue::create(marginRight); - return zoomAdjustedPixelValue(marginRight.value(), style.get()); + return primitiveValueCache->createValue(marginRight); + return zoomAdjustedPixelValue(marginRight.value(), style.get(), primitiveValueCache); } case CSSPropertyMarginBottom: { Length marginBottom = style->marginBottom(); if (marginBottom.isPercent()) - return CSSPrimitiveValue::create(marginBottom); - return zoomAdjustedPixelValue(marginBottom.value(), style.get()); + return primitiveValueCache->createValue(marginBottom); + return zoomAdjustedPixelValue(marginBottom.value(), style.get(), primitiveValueCache); } case CSSPropertyMarginLeft: { Length marginLeft = style->marginLeft(); if (marginLeft.isPercent()) - return CSSPrimitiveValue::create(marginLeft); - return zoomAdjustedPixelValue(marginLeft.value(), style.get()); + return primitiveValueCache->createValue(marginLeft); + return zoomAdjustedPixelValue(marginLeft.value(), style.get(), primitiveValueCache); } case CSSPropertyWebkitMarqueeDirection: - return CSSPrimitiveValue::create(style->marqueeDirection()); + return primitiveValueCache->createValue(style->marqueeDirection()); case CSSPropertyWebkitMarqueeIncrement: - return CSSPrimitiveValue::create(style->marqueeIncrement()); + return primitiveValueCache->createValue(style->marqueeIncrement()); case CSSPropertyWebkitMarqueeRepetition: if (style->marqueeLoopCount() < 0) - return CSSPrimitiveValue::createIdentifier(CSSValueInfinite); - return CSSPrimitiveValue::create(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueInfinite); + return primitiveValueCache->createValue(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitMarqueeStyle: - return CSSPrimitiveValue::create(style->marqueeBehavior()); + return primitiveValueCache->createValue(style->marqueeBehavior()); case CSSPropertyWebkitUserModify: - return CSSPrimitiveValue::create(style->userModify()); + return primitiveValueCache->createValue(style->userModify()); case CSSPropertyMaxHeight: { const Length& maxHeight = style->maxHeight(); if (maxHeight.isFixed() && maxHeight.value() == undefinedLength) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); - return CSSPrimitiveValue::create(maxHeight); + return primitiveValueCache->createIdentifierValue(CSSValueNone); + return primitiveValueCache->createValue(maxHeight); } case CSSPropertyMaxWidth: { const Length& maxWidth = style->maxWidth(); if (maxWidth.isFixed() && maxWidth.value() == undefinedLength) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); - return CSSPrimitiveValue::create(maxWidth); + return primitiveValueCache->createIdentifierValue(CSSValueNone); + return primitiveValueCache->createValue(maxWidth); } case CSSPropertyMinHeight: - return CSSPrimitiveValue::create(style->minHeight()); + return primitiveValueCache->createValue(style->minHeight()); case CSSPropertyMinWidth: - return CSSPrimitiveValue::create(style->minWidth()); + return primitiveValueCache->createValue(style->minWidth()); case CSSPropertyOpacity: - return CSSPrimitiveValue::create(style->opacity(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyOrphans: - return CSSPrimitiveValue::create(style->orphans(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyOutlineColor: - return m_allowVisitedStyle ? CSSPrimitiveValue::createColor(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->outlineColor()); + return m_allowVisitedStyle ? primitiveValueCache->createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(style.get(), style->outlineColor()); + case CSSPropertyOutlineOffset: + return zoomAdjustedPixelValue(style->outlineOffset(), style.get(), primitiveValueCache); case CSSPropertyOutlineStyle: if (style->outlineStyleIsAuto()) - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::create(style->outlineStyle()); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createValue(style->outlineStyle()); case CSSPropertyOutlineWidth: - return zoomAdjustedPixelValue(style->outlineWidth(), style.get()); + return zoomAdjustedPixelValue(style->outlineWidth(), style.get(), primitiveValueCache); case CSSPropertyOverflow: - return CSSPrimitiveValue::create(max(style->overflowX(), style->overflowY())); + return primitiveValueCache->createValue(max(style->overflowX(), style->overflowY())); case CSSPropertyOverflowX: - return CSSPrimitiveValue::create(style->overflowX()); + return primitiveValueCache->createValue(style->overflowX()); case CSSPropertyOverflowY: #ifdef ANDROID_LAYOUT if (settings && settings->layoutAlgorithm() == Settings::kLayoutSSR) - return CSSPrimitiveValue::createIdentifier(CSSValueVisible); + return primitiveValueCache->createIdentifierValue(CSSValueVisible); #endif - return CSSPrimitiveValue::create(style->overflowY()); + return primitiveValueCache->createValue(style->overflowY()); case CSSPropertyPaddingTop: if (renderer && renderer->isBox()) - return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingTop(false), style.get()); - return CSSPrimitiveValue::create(style->paddingTop()); + return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingTop(false), style.get(), primitiveValueCache); + return primitiveValueCache->createValue(style->paddingTop()); case CSSPropertyPaddingRight: if (renderer && renderer->isBox()) - return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingRight(false), style.get()); - return CSSPrimitiveValue::create(style->paddingRight()); + return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingRight(false), style.get(), primitiveValueCache); + return primitiveValueCache->createValue(style->paddingRight()); case CSSPropertyPaddingBottom: if (renderer && renderer->isBox()) - return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingBottom(false), style.get()); - return CSSPrimitiveValue::create(style->paddingBottom()); + return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingBottom(false), style.get(), primitiveValueCache); + return primitiveValueCache->createValue(style->paddingBottom()); case CSSPropertyPaddingLeft: if (renderer && renderer->isBox()) - return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingLeft(false), style.get()); - return CSSPrimitiveValue::create(style->paddingLeft()); + return zoomAdjustedPixelValue(toRenderBox(renderer)->paddingLeft(false), style.get(), primitiveValueCache); + return primitiveValueCache->createValue(style->paddingLeft()); case CSSPropertyPageBreakAfter: - return CSSPrimitiveValue::create(style->pageBreakAfter()); + return primitiveValueCache->createValue(style->pageBreakAfter()); case CSSPropertyPageBreakBefore: - return CSSPrimitiveValue::create(style->pageBreakBefore()); + return primitiveValueCache->createValue(style->pageBreakBefore()); case CSSPropertyPageBreakInside: { EPageBreak pageBreak = style->pageBreakInside(); ASSERT(pageBreak != PBALWAYS); if (pageBreak == PBALWAYS) return 0; - return CSSPrimitiveValue::create(style->pageBreakInside()); + return primitiveValueCache->createValue(style->pageBreakInside()); } case CSSPropertyPosition: #ifdef ANDROID_LAYOUT if (settings && settings->layoutAlgorithm() == Settings::kLayoutSSR) - return CSSPrimitiveValue::createIdentifier(CSSValueStatic); + return primitiveValueCache->createIdentifierValue(CSSValueStatic); #endif - return CSSPrimitiveValue::create(style->position()); + return primitiveValueCache->createValue(style->position()); case CSSPropertyRight: - return getPositionOffsetValue(style.get(), CSSPropertyRight); + return getPositionOffsetValue(style.get(), CSSPropertyRight, primitiveValueCache); case CSSPropertyTableLayout: - return CSSPrimitiveValue::create(style->tableLayout()); + return primitiveValueCache->createValue(style->tableLayout()); case CSSPropertyTextAlign: - return CSSPrimitiveValue::create(style->textAlign()); + return primitiveValueCache->createValue(style->textAlign()); case CSSPropertyTextDecoration: - return renderTextDecorationFlagsToCSSValue(style->textDecoration()); + return renderTextDecorationFlagsToCSSValue(style->textDecoration(), primitiveValueCache); case CSSPropertyWebkitTextDecorationsInEffect: - return renderTextDecorationFlagsToCSSValue(style->textDecorationsInEffect()); + return renderTextDecorationFlagsToCSSValue(style->textDecorationsInEffect(), primitiveValueCache); case CSSPropertyWebkitTextFillColor: return currentColorOrValidColor(style.get(), style->textFillColor()); case CSSPropertyWebkitTextEmphasisColor: return currentColorOrValidColor(style.get(), style->textEmphasisColor()); case CSSPropertyWebkitTextEmphasisPosition: - return CSSPrimitiveValue::create(style->textEmphasisPosition()); + return primitiveValueCache->createValue(style->textEmphasisPosition()); case CSSPropertyWebkitTextEmphasisStyle: switch (style->textEmphasisMark()) { case TextEmphasisMarkNone: - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); case TextEmphasisMarkCustom: - return CSSPrimitiveValue::create(style->textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING); + return primitiveValueCache->createValue(style->textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING); case TextEmphasisMarkAuto: ASSERT_NOT_REACHED(); // Fall through @@ -1287,68 +1357,68 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case TextEmphasisMarkTriangle: case TextEmphasisMarkSesame: { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - list->append(CSSPrimitiveValue::create(style->textEmphasisFill())); - list->append(CSSPrimitiveValue::create(style->textEmphasisMark())); + list->append(primitiveValueCache->createValue(style->textEmphasisFill())); + list->append(primitiveValueCache->createValue(style->textEmphasisMark())); return list.release(); } } case CSSPropertyTextIndent: - return CSSPrimitiveValue::create(style->textIndent()); + return primitiveValueCache->createValue(style->textIndent()); case CSSPropertyTextShadow: return valueForShadow(style->textShadow(), propertyID, style.get()); case CSSPropertyTextRendering: - return CSSPrimitiveValue::create(style->fontDescription().textRenderingMode()); + return primitiveValueCache->createValue(style->fontDescription().textRenderingMode()); case CSSPropertyTextOverflow: if (style->textOverflow()) - return CSSPrimitiveValue::createIdentifier(CSSValueEllipsis); - return CSSPrimitiveValue::createIdentifier(CSSValueClip); + return primitiveValueCache->createIdentifierValue(CSSValueEllipsis); + return primitiveValueCache->createIdentifierValue(CSSValueClip); case CSSPropertyWebkitTextSecurity: - return CSSPrimitiveValue::create(style->textSecurity()); + return primitiveValueCache->createValue(style->textSecurity()); case CSSPropertyWebkitTextSizeAdjust: if (style->textSizeAdjust()) - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createIdentifierValue(CSSValueNone); case CSSPropertyWebkitTextStrokeColor: return currentColorOrValidColor(style.get(), style->textStrokeColor()); case CSSPropertyWebkitTextStrokeWidth: - return zoomAdjustedPixelValue(style->textStrokeWidth(), style.get()); + return zoomAdjustedPixelValue(style->textStrokeWidth(), style.get(), primitiveValueCache); case CSSPropertyTextTransform: - return CSSPrimitiveValue::create(style->textTransform()); + return primitiveValueCache->createValue(style->textTransform()); case CSSPropertyTop: - return getPositionOffsetValue(style.get(), CSSPropertyTop); + return getPositionOffsetValue(style.get(), CSSPropertyTop, primitiveValueCache); case CSSPropertyUnicodeBidi: - return CSSPrimitiveValue::create(style->unicodeBidi()); + return primitiveValueCache->createValue(style->unicodeBidi()); case CSSPropertyVerticalAlign: switch (style->verticalAlign()) { case BASELINE: - return CSSPrimitiveValue::createIdentifier(CSSValueBaseline); + return primitiveValueCache->createIdentifierValue(CSSValueBaseline); case MIDDLE: - return CSSPrimitiveValue::createIdentifier(CSSValueMiddle); + return primitiveValueCache->createIdentifierValue(CSSValueMiddle); case SUB: - return CSSPrimitiveValue::createIdentifier(CSSValueSub); + return primitiveValueCache->createIdentifierValue(CSSValueSub); case SUPER: - return CSSPrimitiveValue::createIdentifier(CSSValueSuper); + return primitiveValueCache->createIdentifierValue(CSSValueSuper); case TEXT_TOP: - return CSSPrimitiveValue::createIdentifier(CSSValueTextTop); + return primitiveValueCache->createIdentifierValue(CSSValueTextTop); case TEXT_BOTTOM: - return CSSPrimitiveValue::createIdentifier(CSSValueTextBottom); + return primitiveValueCache->createIdentifierValue(CSSValueTextBottom); case TOP: - return CSSPrimitiveValue::createIdentifier(CSSValueTop); + return primitiveValueCache->createIdentifierValue(CSSValueTop); case BOTTOM: - return CSSPrimitiveValue::createIdentifier(CSSValueBottom); + return primitiveValueCache->createIdentifierValue(CSSValueBottom); case BASELINE_MIDDLE: - return CSSPrimitiveValue::createIdentifier(CSSValueWebkitBaselineMiddle); + return primitiveValueCache->createIdentifierValue(CSSValueWebkitBaselineMiddle); case LENGTH: - return CSSPrimitiveValue::create(style->verticalAlignLength()); + return primitiveValueCache->createValue(style->verticalAlignLength()); } ASSERT_NOT_REACHED(); return 0; case CSSPropertyVisibility: #ifdef ANDROID_LAYOUT if (settings && settings->layoutAlgorithm() == Settings::kLayoutSSR) - return CSSPrimitiveValue::createIdentifier(CSSValueVisible); + return primitiveValueCache->createIdentifierValue(CSSValueVisible); #endif - return CSSPrimitiveValue::create(style->visibility()); + return primitiveValueCache->createValue(style->visibility()); case CSSPropertyWhiteSpace: #ifdef ANDROID_LAYOUT if (settings && settings->layoutAlgorithm() == Settings::kLayoutSSR) @@ -1356,55 +1426,55 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case NORMAL: case NOWRAP: case KHTML_NOWRAP: - return CSSPrimitiveValue::createIdentifier(CSSValueNormal); + return primitiveValueCache->createIdentifierValue(CSSValueNormal); case PRE: case PRE_WRAP: - return CSSPrimitiveValue::createIdentifier(CSSValuePreWrap); + return primitiveValueCache->createIdentifierValue(CSSValuePreWrap); case PRE_LINE: - return CSSPrimitiveValue::createIdentifier(CSSValuePreLine); + return primitiveValueCache->createIdentifierValue(CSSValuePreLine); } else #endif - return CSSPrimitiveValue::create(style->whiteSpace()); + return primitiveValueCache->createValue(style->whiteSpace()); case CSSPropertyWidows: - return CSSPrimitiveValue::create(style->widows(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->widows(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWidth: if (renderer) - return zoomAdjustedPixelValue(sizingBox(renderer).width(), style.get()); - return zoomAdjustedPixelValueForLength(style->width(), style.get()); + return zoomAdjustedPixelValue(sizingBox(renderer).width(), style.get(), primitiveValueCache); + return zoomAdjustedPixelValueForLength(style->width(), style.get(), primitiveValueCache); case CSSPropertyWordBreak: - return CSSPrimitiveValue::create(style->wordBreak()); + return primitiveValueCache->createValue(style->wordBreak()); case CSSPropertyWordSpacing: - return zoomAdjustedPixelValue(style->wordSpacing(), style.get()); + return zoomAdjustedPixelValue(style->wordSpacing(), style.get(), primitiveValueCache); case CSSPropertyWordWrap: - return CSSPrimitiveValue::create(style->wordWrap()); + return primitiveValueCache->createValue(style->wordWrap()); case CSSPropertyWebkitLineBreak: - return CSSPrimitiveValue::create(style->khtmlLineBreak()); + return primitiveValueCache->createValue(style->khtmlLineBreak()); case CSSPropertyWebkitNbspMode: - return CSSPrimitiveValue::create(style->nbspMode()); + return primitiveValueCache->createValue(style->nbspMode()); case CSSPropertyWebkitMatchNearestMailBlockquoteColor: - return CSSPrimitiveValue::create(style->matchNearestMailBlockquoteColor()); + return primitiveValueCache->createValue(style->matchNearestMailBlockquoteColor()); case CSSPropertyResize: - return CSSPrimitiveValue::create(style->resize()); + return primitiveValueCache->createValue(style->resize()); case CSSPropertyWebkitFontSmoothing: - return CSSPrimitiveValue::create(style->fontDescription().fontSmoothing()); + return primitiveValueCache->createValue(style->fontDescription().fontSmoothing()); case CSSPropertyZIndex: if (style->hasAutoZIndex()) - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return CSSPrimitiveValue::create(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); + return primitiveValueCache->createValue(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyZoom: - return CSSPrimitiveValue::create(style->zoom(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createValue(style->zoom(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyBoxSizing: if (style->boxSizing() == CONTENT_BOX) - return CSSPrimitiveValue::createIdentifier(CSSValueContentBox); - return CSSPrimitiveValue::createIdentifier(CSSValueBorderBox); + return primitiveValueCache->createIdentifierValue(CSSValueContentBox); + return primitiveValueCache->createIdentifierValue(CSSValueBorderBox); #if ENABLE(DASHBOARD_SUPPORT) case CSSPropertyWebkitDashboardRegion: { const Vector<StyleDashboardRegion>& regions = style->dashboardRegions(); unsigned count = regions.size(); if (count == 1 && regions[0].type == StyleDashboardRegion::None) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache->createIdentifierValue(CSSValueNone); RefPtr<DashboardRegion> firstRegion; DashboardRegion* previousRegion = 0; @@ -1414,10 +1484,10 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper region->m_label = styleRegion.label; LengthBox offset = styleRegion.offset; - region->setTop(zoomAdjustedPixelValue(offset.top().value(), style.get())); - region->setRight(zoomAdjustedPixelValue(offset.right().value(), style.get())); - region->setBottom(zoomAdjustedPixelValue(offset.bottom().value(), style.get())); - region->setLeft(zoomAdjustedPixelValue(offset.left().value(), style.get())); + region->setTop(zoomAdjustedPixelValue(offset.top().value(), style.get(), primitiveValueCache)); + region->setRight(zoomAdjustedPixelValue(offset.right().value(), style.get(), primitiveValueCache)); + region->setBottom(zoomAdjustedPixelValue(offset.bottom().value(), style.get(), primitiveValueCache)); + region->setLeft(zoomAdjustedPixelValue(offset.left().value(), style.get(), primitiveValueCache)); region->m_isRectangle = (styleRegion.type == StyleDashboardRegion::Rectangle); region->m_isCircle = (styleRegion.type == StyleDashboardRegion::Circle); @@ -1427,27 +1497,27 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper firstRegion = region; previousRegion = region.get(); } - return CSSPrimitiveValue::create(firstRegion.release()); + return primitiveValueCache->createValue(firstRegion.release()); } #endif case CSSPropertyWebkitAnimationDelay: - return getDelayValue(style->animations()); + return getDelayValue(style->animations(), primitiveValueCache); case CSSPropertyWebkitAnimationDirection: { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); const AnimationList* t = style->animations(); if (t) { for (size_t i = 0; i < t->size(); ++i) { if (t->animation(i)->direction()) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueAlternate)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueAlternate)); else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueNormal)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueNormal)); } } else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueNormal)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueNormal)); return list.release(); } case CSSPropertyWebkitAnimationDuration: - return getDurationValue(style->animations()); + return getDurationValue(style->animations(), primitiveValueCache); case CSSPropertyWebkitAnimationFillMode: { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); const AnimationList* t = style->animations(); @@ -1455,21 +1525,21 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper for (size_t i = 0; i < t->size(); ++i) { switch (t->animation(i)->fillMode()) { case AnimationFillModeNone: - list->append(CSSPrimitiveValue::createIdentifier(CSSValueNone)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueNone)); break; case AnimationFillModeForwards: - list->append(CSSPrimitiveValue::createIdentifier(CSSValueForwards)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueForwards)); break; case AnimationFillModeBackwards: - list->append(CSSPrimitiveValue::createIdentifier(CSSValueBackwards)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueBackwards)); break; case AnimationFillModeBoth: - list->append(CSSPrimitiveValue::createIdentifier(CSSValueBoth)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueBoth)); break; } } } else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueNone)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueNone)); return list.release(); } case CSSPropertyWebkitAnimationIterationCount: { @@ -1479,12 +1549,12 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper for (size_t i = 0; i < t->size(); ++i) { int iterationCount = t->animation(i)->iterationCount(); if (iterationCount == Animation::IterationCountInfinite) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueInfinite)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueInfinite)); else - list->append(CSSPrimitiveValue::create(iterationCount, CSSPrimitiveValue::CSS_NUMBER)); + list->append(primitiveValueCache->createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER)); } } else - list->append(CSSPrimitiveValue::create(Animation::initialAnimationIterationCount(), CSSPrimitiveValue::CSS_NUMBER)); + list->append(primitiveValueCache->createValue(Animation::initialAnimationIterationCount(), CSSPrimitiveValue::CSS_NUMBER)); return list.release(); } case CSSPropertyWebkitAnimationName: { @@ -1492,9 +1562,9 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper const AnimationList* t = style->animations(); if (t) { for (size_t i = 0; i < t->size(); ++i) - list->append(CSSPrimitiveValue::create(t->animation(i)->name(), CSSPrimitiveValue::CSS_STRING)); + list->append(primitiveValueCache->createValue(t->animation(i)->name(), CSSPrimitiveValue::CSS_STRING)); } else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueNone)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueNone)); return list.release(); } case CSSPropertyWebkitAnimationPlayState: { @@ -1504,103 +1574,103 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper for (size_t i = 0; i < t->size(); ++i) { int prop = t->animation(i)->playState(); if (prop == AnimPlayStatePlaying) - list->append(CSSPrimitiveValue::createIdentifier(CSSValueRunning)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueRunning)); else - list->append(CSSPrimitiveValue::createIdentifier(CSSValuePaused)); + list->append(primitiveValueCache->createIdentifierValue(CSSValuePaused)); } } else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueRunning)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueRunning)); return list.release(); } case CSSPropertyWebkitAnimationTimingFunction: return getTimingFunctionValue(style->animations()); case CSSPropertyWebkitAppearance: - return CSSPrimitiveValue::create(style->appearance()); + return primitiveValueCache->createValue(style->appearance()); case CSSPropertyWebkitBackfaceVisibility: - return CSSPrimitiveValue::createIdentifier((style->backfaceVisibility() == BackfaceVisibilityHidden) ? CSSValueHidden : CSSValueVisible); + return primitiveValueCache->createIdentifierValue((style->backfaceVisibility() == BackfaceVisibilityHidden) ? CSSValueHidden : CSSValueVisible); case CSSPropertyWebkitBorderImage: - return valueForNinePieceImage(style->borderImage()); + return valueForNinePieceImage(style->borderImage(), primitiveValueCache); case CSSPropertyWebkitMaskBoxImage: - return valueForNinePieceImage(style->maskBoxImage()); + return valueForNinePieceImage(style->maskBoxImage(), primitiveValueCache); case CSSPropertyWebkitFontSizeDelta: // Not a real style property -- used by the editing engine -- so has no computed value. break; case CSSPropertyWebkitMarginBottomCollapse: case CSSPropertyWebkitMarginAfterCollapse: - return CSSPrimitiveValue::create(style->marginAfterCollapse()); + return primitiveValueCache->createValue(style->marginAfterCollapse()); case CSSPropertyWebkitMarginTopCollapse: case CSSPropertyWebkitMarginBeforeCollapse: - return CSSPrimitiveValue::create(style->marginBeforeCollapse()); + return primitiveValueCache->createValue(style->marginBeforeCollapse()); case CSSPropertyWebkitPerspective: if (!style->hasPerspective()) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); - return CSSPrimitiveValue::create(style->perspective(), CSSPrimitiveValue::CSS_NUMBER); + return primitiveValueCache->createIdentifierValue(CSSValueNone); + return primitiveValueCache->createValue(style->perspective(), CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyWebkitPerspectiveOrigin: { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (renderer) { IntRect box = sizingBox(renderer); - list->append(zoomAdjustedPixelValue(style->perspectiveOriginX().calcMinValue(box.width()), style.get())); - list->append(zoomAdjustedPixelValue(style->perspectiveOriginY().calcMinValue(box.height()), style.get())); + list->append(zoomAdjustedPixelValue(style->perspectiveOriginX().calcMinValue(box.width()), style.get(), primitiveValueCache)); + list->append(zoomAdjustedPixelValue(style->perspectiveOriginY().calcMinValue(box.height()), style.get(), primitiveValueCache)); } else { - list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginX(), style.get())); - list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginY(), style.get())); + list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginX(), style.get(), primitiveValueCache)); + list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginY(), style.get(), primitiveValueCache)); } return list.release(); } case CSSPropertyWebkitRtlOrdering: if (style->visuallyOrdered()) - return CSSPrimitiveValue::createIdentifier(CSSValueVisual); - return CSSPrimitiveValue::createIdentifier(CSSValueLogical); + return primitiveValueCache->createIdentifierValue(CSSValueVisual); + return primitiveValueCache->createIdentifierValue(CSSValueLogical); case CSSPropertyWebkitUserDrag: - return CSSPrimitiveValue::create(style->userDrag()); + return primitiveValueCache->createValue(style->userDrag()); case CSSPropertyWebkitUserSelect: - return CSSPrimitiveValue::create(style->userSelect()); + return primitiveValueCache->createValue(style->userSelect()); case CSSPropertyBorderBottomLeftRadius: - return getBorderRadiusCornerValue(style->borderBottomLeftRadius(), style.get()); + return getBorderRadiusCornerValue(style->borderBottomLeftRadius(), style.get(), primitiveValueCache); case CSSPropertyBorderBottomRightRadius: - return getBorderRadiusCornerValue(style->borderBottomRightRadius(), style.get()); + return getBorderRadiusCornerValue(style->borderBottomRightRadius(), style.get(), primitiveValueCache); case CSSPropertyBorderTopLeftRadius: - return getBorderRadiusCornerValue(style->borderTopLeftRadius(), style.get()); + return getBorderRadiusCornerValue(style->borderTopLeftRadius(), style.get(), primitiveValueCache); case CSSPropertyBorderTopRightRadius: - return getBorderRadiusCornerValue(style->borderTopRightRadius(), style.get()); + return getBorderRadiusCornerValue(style->borderTopRightRadius(), style.get(), primitiveValueCache); case CSSPropertyClip: { if (!style->hasClip()) - return CSSPrimitiveValue::createIdentifier(CSSValueAuto); + return primitiveValueCache->createIdentifierValue(CSSValueAuto); RefPtr<Rect> rect = Rect::create(); - rect->setTop(zoomAdjustedPixelValue(style->clip().top().value(), style.get())); - rect->setRight(zoomAdjustedPixelValue(style->clip().right().value(), style.get())); - rect->setBottom(zoomAdjustedPixelValue(style->clip().bottom().value(), style.get())); - rect->setLeft(zoomAdjustedPixelValue(style->clip().left().value(), style.get())); - return CSSPrimitiveValue::create(rect.release()); + rect->setTop(zoomAdjustedPixelValue(style->clip().top().value(), style.get(), primitiveValueCache)); + rect->setRight(zoomAdjustedPixelValue(style->clip().right().value(), style.get(), primitiveValueCache)); + rect->setBottom(zoomAdjustedPixelValue(style->clip().bottom().value(), style.get(), primitiveValueCache)); + rect->setLeft(zoomAdjustedPixelValue(style->clip().left().value(), style.get(), primitiveValueCache)); + return primitiveValueCache->createValue(rect.release()); } case CSSPropertySpeak: - return CSSPrimitiveValue::create(style->speak()); + return primitiveValueCache->createValue(style->speak()); case CSSPropertyWebkitTransform: - return computedTransform(renderer, style.get()); + return computedTransform(renderer, style.get(), primitiveValueCache); case CSSPropertyWebkitTransformOrigin: { RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (renderer) { IntRect box = sizingBox(renderer); - list->append(zoomAdjustedPixelValue(style->transformOriginX().calcMinValue(box.width()), style.get())); - list->append(zoomAdjustedPixelValue(style->transformOriginY().calcMinValue(box.height()), style.get())); + list->append(zoomAdjustedPixelValue(style->transformOriginX().calcMinValue(box.width()), style.get(), primitiveValueCache)); + list->append(zoomAdjustedPixelValue(style->transformOriginY().calcMinValue(box.height()), style.get(), primitiveValueCache)); if (style->transformOriginZ() != 0) - list->append(zoomAdjustedPixelValue(style->transformOriginZ(), style.get())); + list->append(zoomAdjustedPixelValue(style->transformOriginZ(), style.get(), primitiveValueCache)); } else { - list->append(zoomAdjustedPixelValueForLength(style->transformOriginX(), style.get())); - list->append(zoomAdjustedPixelValueForLength(style->transformOriginY(), style.get())); + list->append(zoomAdjustedPixelValueForLength(style->transformOriginX(), style.get(), primitiveValueCache)); + list->append(zoomAdjustedPixelValueForLength(style->transformOriginY(), style.get(), primitiveValueCache)); if (style->transformOriginZ() != 0) - list->append(zoomAdjustedPixelValue(style->transformOriginZ(), style.get())); + list->append(zoomAdjustedPixelValue(style->transformOriginZ(), style.get(), primitiveValueCache)); } return list.release(); } case CSSPropertyWebkitTransformStyle: - return CSSPrimitiveValue::createIdentifier((style->transformStyle3D() == TransformStyle3DPreserve3D) ? CSSValuePreserve3d : CSSValueFlat); + return primitiveValueCache->createIdentifierValue((style->transformStyle3D() == TransformStyle3DPreserve3D) ? CSSValuePreserve3d : CSSValueFlat); case CSSPropertyWebkitTransitionDelay: - return getDelayValue(style->transitions()); + return getDelayValue(style->transitions(), primitiveValueCache); case CSSPropertyWebkitTransitionDuration: - return getDurationValue(style->transitions()); + return getDurationValue(style->transitions(), primitiveValueCache); case CSSPropertyWebkitTransitionProperty: { RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); const AnimationList* t = style->transitions(); @@ -1609,27 +1679,37 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper int prop = t->animation(i)->property(); RefPtr<CSSValue> propertyValue; if (prop == cAnimateNone) - propertyValue = CSSPrimitiveValue::createIdentifier(CSSValueNone); + propertyValue = primitiveValueCache->createIdentifierValue(CSSValueNone); else if (prop == cAnimateAll) - propertyValue = CSSPrimitiveValue::createIdentifier(CSSValueAll); + propertyValue = primitiveValueCache->createIdentifierValue(CSSValueAll); else - propertyValue = CSSPrimitiveValue::create(getPropertyName(static_cast<CSSPropertyID>(prop)), CSSPrimitiveValue::CSS_STRING); + propertyValue = primitiveValueCache->createValue(getPropertyName(static_cast<CSSPropertyID>(prop)), CSSPrimitiveValue::CSS_STRING); list->append(propertyValue); } } else - list->append(CSSPrimitiveValue::createIdentifier(CSSValueAll)); + list->append(primitiveValueCache->createIdentifierValue(CSSValueAll)); return list.release(); } case CSSPropertyWebkitTransitionTimingFunction: return getTimingFunctionValue(style->transitions()); case CSSPropertyPointerEvents: - return CSSPrimitiveValue::create(style->pointerEvents()); + return primitiveValueCache->createValue(style->pointerEvents()); case CSSPropertyWebkitColorCorrection: - return CSSPrimitiveValue::create(style->colorSpace()); + return primitiveValueCache->createValue(style->colorSpace()); case CSSPropertyWebkitWritingMode: - return CSSPrimitiveValue::create(style->writingMode()); + return primitiveValueCache->createValue(style->writingMode()); case CSSPropertyWebkitTextCombine: - return CSSPrimitiveValue::create(style->textCombine()); + return primitiveValueCache->createValue(style->textCombine()); + case CSSPropertyWebkitTextOrientation: + return CSSPrimitiveValue::create(style->fontDescription().textOrientation()); + case CSSPropertyWebkitLineBoxContain: + return createLineBoxContainValue(primitiveValueCache, style->lineBoxContain()); + case CSSPropertyContent: + return contentToCSSValue(style.get(), primitiveValueCache); + case CSSPropertyCounterIncrement: + return counterToCSSValue(style.get(), propertyID, primitiveValueCache); + case CSSPropertyCounterReset: + return counterToCSSValue(style.get(), propertyID, primitiveValueCache); /* Shorthand properties, currently not supported see bug 13658*/ case CSSPropertyBackground: @@ -1645,9 +1725,15 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper case CSSPropertyFont: case CSSPropertyListStyle: case CSSPropertyMargin: + case CSSPropertyOutline: case CSSPropertyPadding: break; + /* Individual properties not part of the spec */ + case CSSPropertyBackgroundRepeatX: + case CSSPropertyBackgroundRepeatY: + break; + /* Unimplemented CSS 3 properties (including CSS3 shorthand properties) */ case CSSPropertyWebkitTextEmphasis: case CSSPropertyTextLineThrough: @@ -1708,13 +1794,6 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper break; /* Other unimplemented properties */ - case CSSPropertyBackgroundRepeatX: - case CSSPropertyBackgroundRepeatY: - case CSSPropertyContent: // FIXME: needs implementation, bug 23668 - case CSSPropertyCounterIncrement: - case CSSPropertyCounterReset: - case CSSPropertyOutline: // FIXME: needs implementation - case CSSPropertyOutlineOffset: // FIXME: needs implementation case CSSPropertyPage: // for @page case CSSPropertyQuotes: // FIXME: needs implementation case CSSPropertySize: // for @page @@ -1744,27 +1823,27 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper // shorthand property currently not supported see bug 13658 break; case CSSPropertyWebkitRingFillColor: - return CSSPrimitiveValue::createColor(style->ringFillColor().rgb()); + return primitiveValueCache->createColorValue(style->ringFillColor().rgb()); case CSSPropertyWebkitRingInnerWidth: - return CSSPrimitiveValue::create(style->ringInnerWidth()); + return primitiveValueCache->createValue(style->ringInnerWidth()); case CSSPropertyWebkitRingOuterWidth: - return CSSPrimitiveValue::create(style->ringOuterWidth()); + return primitiveValueCache->createValue(style->ringOuterWidth()); case CSSPropertyWebkitRingOutset: - return CSSPrimitiveValue::create(style->ringOutset()); + return primitiveValueCache->createValue(style->ringOutset()); case CSSPropertyWebkitRingPressedInnerColor: - return CSSPrimitiveValue::createColor(style->ringPressedInnerColor().rgb()); + return primitiveValueCache->createColorValue(style->ringPressedInnerColor().rgb()); case CSSPropertyWebkitRingPressedOuterColor: - return CSSPrimitiveValue::createColor(style->ringPressedOuterColor().rgb()); + return primitiveValueCache->createColorValue(style->ringPressedOuterColor().rgb()); case CSSPropertyWebkitRingRadius: - return CSSPrimitiveValue::create(style->ringRadius()); + return primitiveValueCache->createValue(style->ringRadius()); case CSSPropertyWebkitRingSelectedInnerColor: - return CSSPrimitiveValue::createColor(style->ringSelectedInnerColor().rgb()); + return primitiveValueCache->createColorValue(style->ringSelectedInnerColor().rgb()); case CSSPropertyWebkitRingSelectedOuterColor: - return CSSPrimitiveValue::createColor(style->ringSelectedOuterColor().rgb()); + return primitiveValueCache->createColorValue(style->ringSelectedOuterColor().rgb()); #endif #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR case CSSPropertyWebkitTapHighlightColor: - return CSSPrimitiveValue::createColor(style->tapHighlightColor().rgb()); + return primitiveValueCache->createColorValue(style->tapHighlightColor().rgb()); #endif #if ENABLE(SVG) case CSSPropertyClipPath: diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.h b/Source/WebCore/css/CSSComputedStyleDeclaration.h index 718eb2d..4bf5a03 100644 --- a/Source/WebCore/css/CSSComputedStyleDeclaration.h +++ b/Source/WebCore/css/CSSComputedStyleDeclaration.h @@ -22,9 +22,9 @@ #define CSSComputedStyleDeclaration_h #include "CSSStyleDeclaration.h" -#include "PlatformString.h" #include "RenderStyleConstants.h" #include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -34,6 +34,7 @@ class CSSPrimitiveValue; class Node; class RenderStyle; class ShadowData; +class SVGPaint; enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true }; @@ -76,7 +77,10 @@ private: PassRefPtr<CSSValue> valueForShadow(const ShadowData*, int, RenderStyle*) const; PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(RenderStyle*, const Color&) const; - +#if ENABLE(SVG) + PassRefPtr<SVGPaint> adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint>, RenderStyle*) const; +#endif + RefPtr<Node> m_node; PseudoId m_pseudoElementSpecifier; bool m_allowVisitedStyle; diff --git a/Source/WebCore/css/CSSFontFaceSource.cpp b/Source/WebCore/css/CSSFontFaceSource.cpp index 681a94b..eeb90a4 100644 --- a/Source/WebCore/css/CSSFontFaceSource.cpp +++ b/Source/WebCore/css/CSSFontFaceSource.cpp @@ -51,7 +51,7 @@ CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font) , m_font(font) , m_face(0) #if ENABLE(SVG_FONTS) - , m_svgFontFaceElement(0) + , m_hasExternalSVGFont(false) #endif { if (m_font) @@ -115,7 +115,8 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri } // See if we have a mapping in our FontData cache. - unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 5 | fontDescription.widthVariant() << 3 | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0); + unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 6 | fontDescription.widthVariant() << 4 + | (fontDescription.textOrientation() == TextOrientationUpright ? 8 : 0) | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0); if (SimpleFontData* cachedData = m_fontDataTable.get(hashKey)) return cachedData; @@ -125,7 +126,7 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri if (isLoaded()) { if (m_font) { #if ENABLE(SVG_FONTS) - if (m_font->isSVGFont()) { + if (m_hasExternalSVGFont) { // For SVG fonts parse the external SVG document, and extract the <font> element. if (!m_font->ensureSVGFontData()) return 0; @@ -162,7 +163,8 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri if (!m_font->ensureCustomFontData()) return 0; - fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false)); + fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(), + fontDescription.textOrientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false)); } } else { #if ENABLE(SVG_FONTS) @@ -202,7 +204,7 @@ void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> ele bool CSSFontFaceSource::isSVGFontFaceSource() const { - return m_svgFontFaceElement || (m_font && m_font->isSVGFont()); + return m_svgFontFaceElement || m_hasExternalSVGFont; } #endif diff --git a/Source/WebCore/css/CSSFontFaceSource.h b/Source/WebCore/css/CSSFontFaceSource.h index a5c3e61..e87fbfc 100644 --- a/Source/WebCore/css/CSSFontFaceSource.h +++ b/Source/WebCore/css/CSSFontFaceSource.h @@ -66,6 +66,7 @@ public: SVGFontFaceElement* svgFontFaceElement() const; void setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement>); bool isSVGFontFaceSource() const; + void setHasExternalSVGFont(bool value) { m_hasExternalSVGFont = value; } #endif private: @@ -77,6 +78,7 @@ private: #if ENABLE(SVG_FONTS) RefPtr<SVGFontFaceElement> m_svgFontFaceElement; RefPtr<SVGFontElement> m_externalSVGFontElement; + bool m_hasExternalSVGFont; #endif }; diff --git a/Source/WebCore/css/CSSFontSelector.cpp b/Source/WebCore/css/CSSFontSelector.cpp index 9c9a844..8024afa 100644 --- a/Source/WebCore/css/CSSFontSelector.cpp +++ b/Source/WebCore/css/CSSFontSelector.cpp @@ -247,11 +247,11 @@ void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) if (allowDownloading && item->isSupportedFormat() && m_document) { CachedFont* cachedFont = m_document->cachedResourceLoader()->requestFont(item->resource()); if (cachedFont) { + source = new CSSFontFaceSource(item->resource(), cachedFont); #if ENABLE(SVG_FONTS) if (foundSVGFont) - cachedFont->setSVGFont(true); + source->setHasExternalSVGFont(true); #endif - source = new CSSFontFaceSource(item->resource(), cachedFont); } } } else { @@ -345,18 +345,37 @@ void CSSFontSelector::addFontFaceRule(const CSSFontFaceRule* fontFaceRule) } } -void CSSFontSelector::fontLoaded() +void CSSFontSelector::registerForInvalidationCallbacks(FontSelectorClient* client) +{ + m_clients.add(client); +} + +void CSSFontSelector::unregisterForInvalidationCallbacks(FontSelectorClient* client) +{ + m_clients.remove(client); +} + +void CSSFontSelector::dispatchInvalidationCallbacks() { + Vector<FontSelectorClient*> clients; + copyToVector(m_clients, clients); + for (size_t i = 0; i < clients.size(); ++i) + clients[i]->fontsNeedUpdate(this); + + // FIXME: Make Document a FontSelectorClient so that it can simply register for invalidation callbacks. if (!m_document || m_document->inPageCache() || !m_document->renderer()) return; m_document->scheduleForcedStyleRecalc(); } +void CSSFontSelector::fontLoaded() +{ + dispatchInvalidationCallbacks(); +} + void CSSFontSelector::fontCacheInvalidated() { - if (!m_document || m_document->inPageCache() || !m_document->renderer()) - return; - m_document->scheduleForcedStyleRecalc(); + dispatchInvalidationCallbacks(); } static FontData* fontDataForGenericFamily(Document* document, const FontDescription& fontDescription, const AtomicString& familyName) diff --git a/Source/WebCore/css/CSSFontSelector.h b/Source/WebCore/css/CSSFontSelector.h index 93ee274..f50ea42 100644 --- a/Source/WebCore/css/CSSFontSelector.h +++ b/Source/WebCore/css/CSSFontSelector.h @@ -29,6 +29,7 @@ #include "FontSelector.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> +#include <wtf/HashSet.h> #include <wtf/RefPtr.h> #include <wtf/text/StringHash.h> @@ -62,13 +63,19 @@ public: CachedResourceLoader* cachedResourceLoader() const; + virtual void registerForInvalidationCallbacks(FontSelectorClient*); + virtual void unregisterForInvalidationCallbacks(FontSelectorClient*); + private: CSSFontSelector(Document*); + void dispatchInvalidationCallbacks(); + Document* m_document; HashMap<String, Vector<RefPtr<CSSFontFace> >*, CaseFoldingHash> m_fontFaces; HashMap<String, Vector<RefPtr<CSSFontFace> >*, CaseFoldingHash> m_locallyInstalledFontFaces; HashMap<String, HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >*, CaseFoldingHash> m_fonts; + HashSet<FontSelectorClient*> m_clients; }; } // namespace WebCore diff --git a/Source/WebCore/css/CSSGrammar.y b/Source/WebCore/css/CSSGrammar.y index 03d25d9..269eaf0 100644 --- a/Source/WebCore/css/CSSGrammar.y +++ b/Source/WebCore/css/CSSGrammar.y @@ -99,7 +99,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %} -%expect 51 +%expect 54 %nonassoc LOWEST_PREC @@ -183,13 +183,18 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %token <number> HERTZ %token <number> KHERTZ %token <string> DIMEN +%token <string> INVALIDDIMEN %token <number> PERCENTAGE %token <number> FLOATTOKEN %token <number> INTEGER %token <string> URI %token <string> FUNCTION +%token <string> ANYFUNCTION %token <string> NOTFUNCTION +%token <string> CALCFUNCTION +%token <string> MINFUNCTION +%token <string> MAXFUNCTION %token <string> UNICODERANGE @@ -221,7 +226,6 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <string> string_or_uri %type <string> ident_or_string %type <string> medium -%type <string> hexcolor %type <marginBox> margin_sym %type <string> media_feature @@ -247,6 +251,7 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <selector> simple_selector %type <selector> selector %type <selectorList> selector_list +%type <selectorList> simple_selector_list %type <selector> selector_with_trailing_whitespace %type <selector> class %type <selector> attrib @@ -270,6 +275,14 @@ static int cssyylex(YYSTYPE* yylval, void* parser) %type <value> term %type <value> unary_term %type <value> function +%type <value> calc_func_term +%type <character> calc_func_operator +%type <valueList> calc_func_expr +%type <valueList> calc_func_expr_list +%type <valueList> calc_func_paren_expr +%type <value> calc_function +%type <string> min_or_max +%type <value> min_or_max_function %type <string> element_name %type <string> attr_name @@ -857,8 +870,6 @@ selector: end = end->tagHistory(); end->setRelation(CSSSelector::Descendant); end->setTagHistory(p->sinkFloatingSelector($1)); - if (Document* doc = p->document()) - doc->setUsesDescendantRules(true); } } | selector combinator simple_selector { @@ -872,13 +883,6 @@ selector: end = end->tagHistory(); end->setRelation($2); end->setTagHistory(p->sinkFloatingSelector($1)); - if ($2 == CSSSelector::Child) { - if (Document* doc = p->document()) - doc->setUsesDescendantRules(true); - } else if ($2 == CSSSelector::DirectAdjacent || $2 == CSSSelector::IndirectAdjacent) { - if (Document* doc = p->document()) - doc->setUsesSiblingRules(true); - } } } | selector error { @@ -930,6 +934,28 @@ simple_selector: } ; +simple_selector_list: + simple_selector %prec UNIMPORTANT_TOK { + if ($1) { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelectorVector(); + $$->append(p->sinkFloatingSelector($1)); + } else + $$ = 0 + } + | simple_selector_list maybe_space ',' maybe_space simple_selector %prec UNIMPORTANT_TOK { + if ($1 && $5) { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = $1; + $$->append(p->sinkFloatingSelector($5)); + } else + $$ = 0; + } + | simple_selector_list error { + $$ = 0; + } + ; + element_name: IDENT { CSSParserString& str = $1; @@ -1102,48 +1128,33 @@ pseudo: CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) $$ = 0; - else if (type == CSSSelector::PseudoEmpty || - type == CSSSelector::PseudoFirstChild || - type == CSSSelector::PseudoFirstOfType || - type == CSSSelector::PseudoLastChild || - type == CSSSelector::PseudoLastOfType || - type == CSSSelector::PseudoOnlyChild || - type == CSSSelector::PseudoOnlyOfType) { - CSSParser* p = static_cast<CSSParser*>(parser); - Document* doc = p->document(); - if (doc) - doc->setUsesSiblingRules(true); - } else if (type == CSSSelector::PseudoFirstLine) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesFirstLineRules(true); - } else if (type == CSSSelector::PseudoBefore || - type == CSSSelector::PseudoAfter) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesBeforeAfterRules(true); - } else if (type == CSSSelector::PseudoLink || type == CSSSelector::PseudoVisited) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesLinkRules(true); - } } | ':' ':' IDENT { $$ = static_cast<CSSParser*>(parser)->createFloatingSelector(); $$->setMatch(CSSSelector::PseudoElement); $3.lower(); $$->setValue($3); - CSSSelector::PseudoType type = $$->pseudoType(); - if (type == CSSSelector::PseudoFirstLine) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesFirstLineRules(true); - } else if (type == CSSSelector::PseudoBefore || - type == CSSSelector::PseudoAfter) { - CSSParser* p = static_cast<CSSParser*>(parser); - if (Document* doc = p->document()) - doc->setUsesBeforeAfterRules(true); - } + // FIXME: This call is needed to force selector to compute the pseudoType early enough. + $$->pseudoType(); + } + // use by :-webkit-any. + // FIXME: should we support generic selectors here or just simple_selectors? + // Use simple_selector_list for now to match -moz-any. + // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0566.html for some + // related discussion with respect to :not. + | ':' ANYFUNCTION maybe_space simple_selector_list maybe_space ')' { + if ($4) { + CSSParser *p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingSelector(); + $$->setMatch(CSSSelector::PseudoClass); + $$->adoptSelectorVector(*p->sinkFloatingSelectorVector($4)); + $2.lower(); + $$->setValue($2); + CSSSelector::PseudoType type = $$->pseudoType(); + if (type != CSSSelector::PseudoAny) + $$ = 0; + } else + $$ = 0; } // used by :nth-*(ax+b) | ':' FUNCTION maybe_space NTH maybe_space ')' { @@ -1155,13 +1166,6 @@ pseudo: CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) $$ = 0; - else if (type == CSSSelector::PseudoNthChild || - type == CSSSelector::PseudoNthOfType || - type == CSSSelector::PseudoNthLastChild || - type == CSSSelector::PseudoNthLastOfType) { - if (p->document()) - p->document()->setUsesSiblingRules(true); - } } // used by :nth-* | ':' FUNCTION maybe_space maybe_unary_operator INTEGER maybe_space ')' { @@ -1173,13 +1177,6 @@ pseudo: CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) $$ = 0; - else if (type == CSSSelector::PseudoNthChild || - type == CSSSelector::PseudoNthOfType || - type == CSSSelector::PseudoNthLastChild || - type == CSSSelector::PseudoNthLastOfType) { - if (p->document()) - p->document()->setUsesSiblingRules(true); - } } // used by :nth-*(odd/even) and :lang | ':' FUNCTION maybe_space IDENT maybe_space ')' { @@ -1196,10 +1193,7 @@ pseudo: type == CSSSelector::PseudoNthOfType || type == CSSSelector::PseudoNthLastChild || type == CSSSelector::PseudoNthLastOfType) { - if (isValidNthToken($4)) { - if (p->document()) - p->document()->setUsesSiblingRules(true); - } else + if (!isValidNthToken($4)) $$ = 0; } } @@ -1211,7 +1205,11 @@ pseudo: CSSParser* p = static_cast<CSSParser*>(parser); $$ = p->createFloatingSelector(); $$->setMatch(CSSSelector::PseudoClass); - $$->setSimpleSelector(p->sinkFloatingSelector($4)->releaseSelector()); + + Vector<OwnPtr<CSSParserSelector> > selectorVector; + selectorVector.append(p->sinkFloatingSelector($4)); + $$->adoptSelectorVector(selectorVector); + $2.lower(); $$->setValue($2); } @@ -1415,12 +1413,18 @@ term: | unary_operator DIMEN maybe_space { $$.id = 0; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } | URI maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; } | UNICODERANGE maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; } - | hexcolor { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } + | HEX maybe_space { $$.id = 0; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } | '#' maybe_space { $$.id = 0; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */ /* FIXME: according to the specs a function can have a unary_operator in front. I know no case where this makes sense */ | function { $$ = $1; } + | calc_function { + $$ = $1; + } + | min_or_max_function { + $$ = $1; + } | '%' maybe_space { /* Handle width: %; */ $$.id = 0; $$.unit = 0; } @@ -1477,16 +1481,143 @@ function: $$.function = f; } ; -/* - * There is a constraint on the color that it must - * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F]) - * after the "#"; e.g., "#000" is OK, but "#abcd" is not. - */ -hexcolor: - HEX maybe_space { $$ = $1; } - | IDSEL maybe_space { $$ = $1; } + +calc_func_term: + unary_term { $$ = $1; } + | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } ; +calc_func_operator: + '+' WHITESPACE { + $$ = '+'; + } + | '-' WHITESPACE { + $$ = '-'; + } + | '*' maybe_space { + $$ = '*'; + } + | '/' maybe_space { + $$ = '/'; + } + | IDENT maybe_space { + if (equalIgnoringCase("mod", $1.characters, $1.length)) + $$ = '%'; + else + $$ = 0; + } + ; + +calc_func_paren_expr: + '(' maybe_space calc_func_expr maybe_space ')' maybe_space { + if ($3) { + $$ = $3; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = '('; + $$->insertValueAt(0, v); + v.iValue = ')'; + $$->addValue(v); + } else + $$ = 0; + } + +calc_func_expr: + calc_func_term maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + $$ = p->createFloatingValueList(); + $$->addValue(p->sinkFloatingValue($1)); + } + | calc_func_expr calc_func_operator calc_func_term { + CSSParser* p = static_cast<CSSParser*>(parser); + if ($1 && $2) { + $$ = $1; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = $2; + $$->addValue(v); + $$->addValue(p->sinkFloatingValue($3)); + } else + $$ = 0; + + } + | calc_func_expr calc_func_operator calc_func_paren_expr { + if ($1 && $2 && $3) { + $$ = $1; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = $2; + $$->addValue(v); + $$->extend(*($3)); + } else + $$ = 0; + } + | calc_func_paren_expr + | calc_func_expr error { + $$ = 0; + } + ; + +calc_func_expr_list: + calc_func_expr { + $$ = $1; + } + | calc_func_expr_list ',' maybe_space calc_func_expr { + if ($1 && $4) { + $$ = $1; + CSSParserValue v; + v.id = 0; + v.unit = CSSParserValue::Operator; + v.iValue = ','; + $$->addValue(v); + $$->extend(*($4)); + } else + $$ = 0; + } + + +calc_function: + CALCFUNCTION maybe_space calc_func_expr ')' maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + CSSParserFunction* f = p->createFloatingFunction(); + f->name = $1; + f->args = p->sinkFloatingValueList($3); + $$.id = 0; + $$.unit = CSSParserValue::Function; + $$.function = f; + } + | CALCFUNCTION maybe_space error { + YYERROR; + } + ; + + +min_or_max: + MINFUNCTION { + $$ = $1; + } + | MAXFUNCTION { + $$ = $1; + } + ; + +min_or_max_function: + min_or_max maybe_space calc_func_expr_list ')' maybe_space { + CSSParser* p = static_cast<CSSParser*>(parser); + CSSParserFunction* f = p->createFloatingFunction(); + f->name = $1; + f->args = p->sinkFloatingValueList($3); + $$.id = 0; + $$.unit = CSSParserValue::Function; + $$.function = f; + } + | min_or_max maybe_space error { + YYERROR; + } + ; /* error handling rules */ diff --git a/Source/WebCore/css/CSSImageValue.cpp b/Source/WebCore/css/CSSImageValue.cpp index 6896596..a9038b9 100644 --- a/Source/WebCore/css/CSSImageValue.cpp +++ b/Source/WebCore/css/CSSImageValue.cpp @@ -67,10 +67,6 @@ StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader) StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader, const String& url) { ASSERT(loader); - if (!loader) { - // FIXME: Remove when http://webkit.org/b/53045 is fixed. - CRASH(); - } if (!m_accessedImage) { m_accessedImage = true; diff --git a/Source/WebCore/css/CSSLineBoxContainValue.cpp b/Source/WebCore/css/CSSLineBoxContainValue.cpp new file mode 100644 index 0000000..b029285 --- /dev/null +++ b/Source/WebCore/css/CSSLineBoxContainValue.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSLineBoxContainValue.h" + +#include "CSSPrimitiveValue.h" +#include "PlatformString.h" + +namespace WebCore { + +CSSLineBoxContainValue::CSSLineBoxContainValue(unsigned value) + : m_value(value) +{ +} + +String CSSLineBoxContainValue::cssText() const +{ + String text(""); + + if (m_value & LineBoxContainBlock) + text += "block"; + if (m_value & LineBoxContainInline) { + if (!text.isEmpty()) + text += " "; + text += "inline"; + } + if (m_value & LineBoxContainFont) { + if (!text.isEmpty()) + text += " "; + text += "font"; + } + if (m_value & LineBoxContainGlyphs) { + if (!text.isEmpty()) + text += " "; + text += "glyphs"; + } + if (m_value & LineBoxContainReplaced) { + if (!text.isEmpty()) + text += " "; + text += "replaced"; + } + if (m_value & LineBoxContainInlineBox) { + if (!text.isEmpty()) + text += " "; + text += "inline-box"; + } + + return text; +} + +} diff --git a/Source/WebCore/css/CSSLineBoxContainValue.h b/Source/WebCore/css/CSSLineBoxContainValue.h new file mode 100644 index 0000000..8d62b11 --- /dev/null +++ b/Source/WebCore/css/CSSLineBoxContainValue.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSLineBoxContainValue_h +#define CSSLineBoxContainValue_h + +#include "CSSValue.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSPrimitiveValue; + +enum LineBoxContainFlags { LineBoxContainNone = 0x0, LineBoxContainBlock = 0x1, LineBoxContainInline = 0x2, LineBoxContainFont = 0x4, LineBoxContainGlyphs = 0x8, + LineBoxContainReplaced = 0x10, LineBoxContainInlineBox = 0x20 }; +typedef unsigned LineBoxContain; + +// Used for text-CSSLineBoxContain and box-CSSLineBoxContain +class CSSLineBoxContainValue : public CSSValue { +public: + static PassRefPtr<CSSLineBoxContainValue> create(LineBoxContain value) + { + return adoptRef(new CSSLineBoxContainValue(value)); + } + + virtual String cssText() const; + + LineBoxContain value() const { return m_value; } + +private: + LineBoxContain m_value; + +private: + CSSLineBoxContainValue(LineBoxContain); + virtual bool isCSSLineBoxContainValue() const { return true; } +}; + +} // namespace + +#endif diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp index 573f4c0..8c8d5ba 100644 --- a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp @@ -1,6 +1,7 @@ /* * (C) 1999-2003 Lars Knoll (knoll@kde.org) * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2011 Research In Motion Limited. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,6 +23,7 @@ #include "CSSMutableStyleDeclaration.h" #include "CSSImageValue.h" +#include "CSSMutableValue.h" #include "CSSParser.h" #include "CSSPropertyLonghand.h" #include "CSSPropertyNames.h" @@ -31,7 +33,9 @@ #include "CSSValueList.h" #include "Document.h" #include "ExceptionCode.h" +#include "InspectorInstrumentation.h" #include "StyledElement.h" +#include <wtf/text/StringConcatenate.h> using namespace std; @@ -78,18 +82,32 @@ CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CS #endif { m_properties.reserveInitialCapacity(numProperties); - HashSet<int> candidates; + HashMap<int, bool> candidates; for (int i = 0; i < numProperties; ++i) { const CSSProperty *property = properties[i]; ASSERT(property); - if (candidates.contains(property->id())) - removeProperty(properties[i]->id(), false); + bool important = property->isImportant(); + if (candidates.contains(property->id())) { + if (!important && candidates.get(property->id())) + continue; + removeProperty(property->id(), false); + } m_properties.append(*property); - if (!getPropertyPriority(property->id()) && !property->isImportant()) - candidates.add(property->id()); + candidates.set(property->id(), important); } } +CSSMutableStyleDeclaration::~CSSMutableStyleDeclaration() +{ + const CSSMutableStyleDeclarationConstIterator end = this->end(); + for (CSSMutableStyleDeclarationConstIterator it = begin(); it != end; ++it) { + CSSValue* value = it->value(); + if (!value || !value->isMutableValue()) + continue; + static_cast<CSSMutableValue*>(value)->setNode(0); + } +} + CSSMutableStyleDeclaration& CSSMutableStyleDeclaration::operator=(const CSSMutableStyleDeclaration& other) { ASSERT(!m_iteratorCount); @@ -107,14 +125,18 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const // Shorthand and 4-values properties switch (propertyID) { + case CSSPropertyBorderSpacing: { + const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing }; + return borderSpacingValue(properties); + } case CSSPropertyBackgroundPosition: { // FIXME: Is this correct? The code in cssparser.cpp is confusing const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY }; - return getLayeredShorthandValue(properties, 2); + return getLayeredShorthandValue(properties); } case CSSPropertyBackgroundRepeat: { const int properties[2] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY }; - return getLayeredShorthandValue(properties, 2); + return getLayeredShorthandValue(properties); } case CSSPropertyBackground: { const int properties[9] = { CSSPropertyBackgroundColor, @@ -126,7 +148,7 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const CSSPropertyBackgroundPositionY, CSSPropertyBackgroundClip, CSSPropertyBackgroundOrigin }; - return getLayeredShorthandValue(properties, 9); + return getLayeredShorthandValue(properties); } case CSSPropertyBorder: { const int properties[3][4] = {{ CSSPropertyBorderTopWidth, @@ -143,7 +165,7 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const CSSPropertyBorderLeftColor }}; String res; for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) { - String value = getCommonValue(properties[i], 4); + String value = getCommonValue(properties[i]); if (!value.isNull()) { if (!res.isNull()) res += " "; @@ -155,27 +177,27 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const case CSSPropertyBorderTop: { const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle, CSSPropertyBorderTopColor}; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyBorderRight: { const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle, CSSPropertyBorderRightColor}; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyBorderBottom: { const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle, CSSPropertyBorderBottomColor}; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyBorderLeft: { const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle, CSSPropertyBorderLeftColor}; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyOutline: { const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle, CSSPropertyOutlineColor }; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyBorderColor: { const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor, @@ -199,7 +221,7 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const } case CSSPropertyOverflow: { const int properties[2] = { CSSPropertyOverflowX, CSSPropertyOverflowY }; - return getCommonValue(properties, 2); + return getCommonValue(properties); } case CSSPropertyPadding: { const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight, @@ -209,40 +231,40 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const case CSSPropertyListStyle: { const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition, CSSPropertyListStyleImage }; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyWebkitMaskPosition: { // FIXME: Is this correct? The code in cssparser.cpp is confusing const int properties[2] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY }; - return getLayeredShorthandValue(properties, 2); + return getLayeredShorthandValue(properties); } case CSSPropertyWebkitMaskRepeat: { const int properties[2] = { CSSPropertyWebkitMaskRepeatX, CSSPropertyWebkitMaskRepeatY }; - return getLayeredShorthandValue(properties, 2); + return getLayeredShorthandValue(properties); } case CSSPropertyWebkitMask: { const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat, CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskClip, CSSPropertyWebkitMaskOrigin }; - return getLayeredShorthandValue(properties, 6); + return getLayeredShorthandValue(properties); } case CSSPropertyWebkitTransformOrigin: { const int properties[3] = { CSSPropertyWebkitTransformOriginX, CSSPropertyWebkitTransformOriginY, CSSPropertyWebkitTransformOriginZ }; - return getShorthandValue(properties, 3); + return getShorthandValue(properties); } case CSSPropertyWebkitTransition: { const int properties[4] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration, CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionDelay }; - return getLayeredShorthandValue(properties, 4); + return getLayeredShorthandValue(properties); } case CSSPropertyWebkitAnimation: { const int properties[7] = { CSSPropertyWebkitAnimationName, CSSPropertyWebkitAnimationDuration, CSSPropertyWebkitAnimationTimingFunction, CSSPropertyWebkitAnimationDelay, CSSPropertyWebkitAnimationIterationCount, CSSPropertyWebkitAnimationDirection, CSSPropertyWebkitAnimationFillMode }; - return getLayeredShorthandValue(properties, 7); + return getLayeredShorthandValue(properties); } #if ENABLE(SVG) case CSSPropertyMarker: { @@ -269,6 +291,22 @@ String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const return String(); } +String CSSMutableStyleDeclaration::borderSpacingValue(const int properties[2]) const +{ + RefPtr<CSSValue> horizontalValue = getPropertyCSSValue(properties[0]); + RefPtr<CSSValue> verticalValue = getPropertyCSSValue(properties[1]); + + if (!horizontalValue) + return String(); + ASSERT(verticalValue); // By <http://www.w3.org/TR/CSS21/tables.html#separated-borders>. + + String horizontalValueCSSText = horizontalValue->cssText(); + String verticalValueCSSText = verticalValue->cssText(); + if (horizontalValueCSSText == verticalValueCSSText) + return horizontalValueCSSText; + return makeString(horizontalValueCSSText, ' ', verticalValueCSSText); +} + String CSSMutableStyleDeclaration::get4Values(const int* properties) const { // Assume the properties are in the usual order top, right, bottom, left. @@ -296,15 +334,15 @@ String CSSMutableStyleDeclaration::get4Values(const int* properties) const return res; } -String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, unsigned number) const +String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, size_t size) const { String res; // Begin by collecting the properties into an array. - Vector< RefPtr<CSSValue> > values(number); + Vector< RefPtr<CSSValue> > values(size); size_t numLayers = 0; - for (size_t i = 0; i < number; ++i) { + for (size_t i = 0; i < size; ++i) { values[i] = getPropertyCSSValue(properties[i]); if (values[i]) { if (values[i]->isValueList()) { @@ -322,7 +360,7 @@ String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* propertie bool useRepeatXShorthand = false; bool useRepeatYShorthand = false; bool useSingleWordShorthand = false; - for (size_t j = 0; j < number; j++) { + for (size_t j = 0; j < size; j++) { RefPtr<CSSValue> value; if (values[j]) { if (values[j]->isValueList()) @@ -345,7 +383,7 @@ String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* propertie if (properties[j] == CSSPropertyBackgroundRepeatX && isPropertyImplicit(properties[j])) { // BUG 49055: make sure the value was not reset in the layer check just above. - if (j < number - 1 && properties[j + 1] == CSSPropertyBackgroundRepeatY && value) { + if (j < size - 1 && properties[j + 1] == CSSPropertyBackgroundRepeatY && value) { RefPtr<CSSValue> yValue; RefPtr<CSSValue> nextValue = values[j + 1]; if (nextValue->isValueList()) @@ -397,10 +435,10 @@ String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* propertie return res; } -String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, int number) const +String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, size_t size) const { String res; - for (int i = 0; i < number; ++i) { + for (size_t i = 0; i < size; ++i) { if (!isPropertyImplicit(properties[i])) { RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); // FIXME: provide default value if !value @@ -415,10 +453,10 @@ String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, int } // only returns a non-null value if all properties have the same, non-null value -String CSSMutableStyleDeclaration::getCommonValue(const int* properties, int number) const +String CSSMutableStyleDeclaration::getCommonValue(const int* properties, size_t size) const { String res; - for (int i = 0; i < number; ++i) { + for (size_t i = 0; i < size; ++i) { RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); if (!value) return String(); @@ -474,16 +512,22 @@ String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyCha return value; } +bool CSSMutableStyleDeclaration::isInlineStyleDeclaration() +{ + // FIXME: Ideally, this should be factored better and there + // should be a subclass of CSSMutableStyleDeclaration just + // for inline style declarations that handles this + return m_node && m_node->isStyledElement() && static_cast<StyledElement*>(m_node)->inlineStyleDecl() == this; +} + void CSSMutableStyleDeclaration::setNeedsStyleRecalc() { if (m_node) { - // FIXME: Ideally, this should be factored better and there - // should be a subclass of CSSMutableStyleDeclaration just - // for inline style declarations that handles this - bool isInlineStyleDeclaration = m_node->isStyledElement() && this == static_cast<StyledElement*>(m_node)->inlineStyleDecl(); - if (isInlineStyleDeclaration) { + if (isInlineStyleDeclaration()) { m_node->setNeedsStyleRecalc(InlineStyleChange); static_cast<StyledElement*>(m_node)->invalidateStyleAttribute(); + if (m_node->document()) + InspectorInstrumentation::didInvalidateStyleAttr(m_node->document(), m_node); } else m_node->setNeedsStyleRecalc(FullStyleChange); return; @@ -541,8 +585,7 @@ bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value // When replacing an existing property value, this moves the property to the end of the list. // Firefox preserves the position, and MSIE moves the property to the beginning. - CSSParser parser(useStrictParsing()); - bool success = parser.parseValue(this, propertyID, value, important); + bool success = CSSParser::parseValue(this, propertyID, value, important, useStrictParsing()); if (!success) { // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility, // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. @@ -575,6 +618,15 @@ bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool imp return true; } +bool CSSMutableStyleDeclaration::setProperty(int propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important, bool notifyChanged) +{ + CSSProperty property(propertyID, CSSPrimitiveValue::create(value, unit), important); + setPropertyInternal(property); + if (notifyChanged) + setNeedsStyleRecalc(); + return true; +} + void CSSMutableStyleDeclaration::setStringProperty(int propertyId, const String &value, CSSPrimitiveValue::UnitTypes type, bool important) { ASSERT(!m_iteratorCount); @@ -680,7 +732,7 @@ String CSSMutableStyleDeclaration::cssText() const String positionValue; const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY }; if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList()) - positionValue = getLayeredShorthandValue(properties, 2); + positionValue = getLayeredShorthandValue(properties); else positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText(); result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; "; @@ -696,7 +748,7 @@ String CSSMutableStyleDeclaration::cssText() const String repeatValue; const int repeatProperties[2] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY }; if (repeatXProp->value()->isValueList() || repeatYProp->value()->isValueList()) - repeatValue = getLayeredShorthandValue(repeatProperties, 2); + repeatValue = getLayeredShorthandValue(repeatProperties); else repeatValue = repeatXProp->value()->cssText() + " " + repeatYProp->value()->cssText(); result += "background-repeat: " + repeatValue + (repeatXProp->isImportant() ? " !important" : "") + "; "; diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.h b/Source/WebCore/css/CSSMutableStyleDeclaration.h index 35f1cc4..ea8ab3f 100644 --- a/Source/WebCore/css/CSSMutableStyleDeclaration.h +++ b/Source/WebCore/css/CSSMutableStyleDeclaration.h @@ -57,6 +57,8 @@ private: class CSSMutableStyleDeclaration : public CSSStyleDeclaration { public: + virtual ~CSSMutableStyleDeclaration(); + static PassRefPtr<CSSMutableStyleDeclaration> create() { return adoptRef(new CSSMutableStyleDeclaration); @@ -107,6 +109,7 @@ public: virtual PassRefPtr<CSSMutableStyleDeclaration> copy() const; bool setProperty(int propertyID, int value, bool important = false, bool notifyChanged = true); + bool setProperty(int propertyId, double value, CSSPrimitiveValue::UnitTypes, bool important = false, bool notifyChanged = true); bool setProperty(int propertyID, const String& value, bool important = false, bool notifyChanged = true); String removeProperty(int propertyID, bool notifyChanged = true, bool returnText = false); @@ -115,7 +118,7 @@ public: void setLengthProperty(int propertyId, const String& value, bool important, bool multiLength = false); void setStringProperty(int propertyId, const String& value, CSSPrimitiveValue::UnitTypes, bool important = false); // parsed string value void setImageProperty(int propertyId, const String& url, bool important = false); - + // The following parses an entire new style declaration. void parseDeclaration(const String& styleDeclaration); @@ -138,6 +141,8 @@ public: bool propertiesEqual(const CSSMutableStyleDeclaration* o) const { return m_properties == o->m_properties; } + bool isInlineStyleDeclaration(); + protected: CSSMutableStyleDeclaration(CSSRule* parentRule); @@ -150,11 +155,16 @@ private: void setNeedsStyleRecalc(); - String getShorthandValue(const int* properties, int number) const; - String getCommonValue(const int* properties, int number) const; - String getLayeredShorthandValue(const int* properties, unsigned number) const; + String getShorthandValue(const int* properties, size_t) const; + String getCommonValue(const int* properties, size_t) const; + String getLayeredShorthandValue(const int* properties, size_t) const; String get4Values(const int* properties) const; - + String borderSpacingValue(const int properties[2]) const; + + template<size_t size> String getShorthandValue(const int (&properties)[size]) const { return getShorthandValue(properties, size); } + template<size_t size> String getCommonValue(const int (&properties)[size]) const { return getCommonValue(properties, size); } + template<size_t size> String getLayeredShorthandValue(const int (&properties)[size]) const { return getLayeredShorthandValue(properties, size); } + void setPropertyInternal(const CSSProperty&, CSSProperty* slot = 0); bool removeShorthandProperty(int propertyID, bool notifyChanged); diff --git a/Source/WebCore/css/CSSMutableValue.h b/Source/WebCore/css/CSSMutableValue.h new file mode 100644 index 0000000..8a3aa72 --- /dev/null +++ b/Source/WebCore/css/CSSMutableValue.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) Research In Motion Limited 2011. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSMutableValue_h +#define CSSMutableValue_h + +#include "CSSValue.h" +#include "Node.h" + +namespace WebCore { + +class CSSMutableValue : public CSSValue { +public: + CSSMutableValue() + : m_node(0) + { + } + + virtual ~CSSMutableValue() { } + virtual bool isMutableValue() const { return true; } + + Node* node() const { return m_node; } + void setNode(Node* node) { m_node = node; } + + void setNeedsStyleRecalc() + { + if (!m_node) + return; + m_node->setNeedsStyleRecalc(FullStyleChange); + } + +private: + Node* m_node; +}; + +} // namespace WebCore + +#endif // CSSMutableValue_h diff --git a/Source/WebCore/css/CSSOMUtils.cpp b/Source/WebCore/css/CSSOMUtils.cpp index d1e9638..7ecd938 100644 --- a/Source/WebCore/css/CSSOMUtils.cpp +++ b/Source/WebCore/css/CSSOMUtils.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "CSSOMUtils.h" -#include "PlatformString.h" +#include <wtf/HexNumber.h> namespace WebCore { @@ -53,7 +53,9 @@ void serializeCharacter(UChar32 c, Vector<UChar>& appendTo) void serializeCharacterAsCodePoint(UChar32 c, Vector<UChar>& appendTo) { - append(appendTo, String::format("\\%x ", c)); + appendTo.append('\\'); + appendUnsignedAsHex(c, appendTo, Lowercase); + appendTo.append(' '); } void serializeIdentifier(const String& identifier, String& appendTo) diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index 55175a2..b7030b2 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -36,10 +36,12 @@ #include "CSSImportRule.h" #include "CSSInheritedValue.h" #include "CSSInitialValue.h" +#include "CSSLineBoxContainValue.h" #include "CSSMediaRule.h" #include "CSSMutableStyleDeclaration.h" #include "CSSPageRule.h" #include "CSSPrimitiveValue.h" +#include "CSSPrimitiveValueCache.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSPropertySourceData.h" @@ -71,6 +73,7 @@ #include "WebKitCSSKeyframesRule.h" #include "WebKitCSSTransformValue.h" #include <limits.h> +#include <wtf/HexNumber.h> #include <wtf/dtoa.h> #include <wtf/text/StringBuffer.h> @@ -96,6 +99,7 @@ using namespace WTF; namespace WebCore { static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; +static const double MAX_SCALE = 1000000; static bool equal(const CSSParserString& a, const char* b) { @@ -176,6 +180,7 @@ CSSParser::~CSSParser() fastFree(m_data); fastDeleteAllValues(m_floatingSelectors); + deleteAllValues(m_floatingSelectorVectors); deleteAllValues(m_floatingValueLists); deleteAllValues(m_floatingFunctions); } @@ -228,7 +233,7 @@ void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int start #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif - m_styleSheet = sheet; + setStyleSheet(sheet); m_defaultNamespace = starAtom; // Reset the default namespace. m_ruleRangeMap = ruleRangeMap; if (ruleRangeMap) { @@ -252,7 +257,7 @@ PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& str #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif - m_styleSheet = sheet; + setStyleSheet(sheet); m_allowNamespaceDeclarations = false; setupParser("@-webkit-rule{", string, "} "); cssyyparse(this); @@ -267,7 +272,7 @@ PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const Str #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif - m_styleSheet = sheet; + setStyleSheet(sheet); setupParser("@-webkit-keyframe-rule{ ", string, "} "); cssyyparse(this); #ifdef ANDROID_INSTRUMENT @@ -276,17 +281,174 @@ PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const Str return m_keyframe.release(); } -bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int id, const String& string, bool important) +static inline bool isColorPropertyID(int propertyId) +{ + switch (propertyId) { + case CSSPropertyColor: + case CSSPropertyBackgroundColor: + case CSSPropertyBorderBottomColor: + case CSSPropertyBorderLeftColor: + case CSSPropertyBorderRightColor: + case CSSPropertyBorderTopColor: + case CSSPropertyOutlineColor: + case CSSPropertyTextLineThroughColor: + case CSSPropertyTextOverlineColor: + case CSSPropertyTextUnderlineColor: + case CSSPropertyWebkitBorderAfterColor: + case CSSPropertyWebkitBorderBeforeColor: + case CSSPropertyWebkitBorderEndColor: + case CSSPropertyWebkitBorderStartColor: + case CSSPropertyWebkitColumnRuleColor: + case CSSPropertyWebkitTextEmphasisColor: + case CSSPropertyWebkitTextFillColor: + case CSSPropertyWebkitTextStrokeColor: + return true; + default: + return false; + } +} + +static bool parseColorValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) +{ + if (!string.length()) + return false; + if (!isColorPropertyID(propertyId)) + return false; + CSSParserString cssString; + cssString.characters = const_cast<UChar*>(string.characters()); + cssString.length = string.length(); + int valueID = cssValueKeywordID(cssString); + bool validPrimitive = false; + if (valueID == CSSValueWebkitText) + validPrimitive = true; + else if (valueID == CSSValueCurrentcolor) + validPrimitive = true; + else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu + || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict)) { + validPrimitive = true; + } + + CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + if (!stylesheet || !stylesheet->document()) + return false; + if (validPrimitive) { + CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createIdentifierValue(valueID), important); + declaration->addParsedProperty(property); + return true; + } + RGBA32 color; + if (!CSSParser::parseColor(string, color, strict && string[0] != '#')) + return false; + CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createColorValue(color), important); + declaration->addParsedProperty(property); + return true; +} + +static inline bool isSimpleLengthPropertyID(int propertyId, bool& acceptsNegativeNumbers) +{ + switch (propertyId) { + case CSSPropertyFontSize: + case CSSPropertyHeight: + case CSSPropertyWidth: + case CSSPropertyMinHeight: + case CSSPropertyMinWidth: + case CSSPropertyPaddingBottom: + case CSSPropertyPaddingLeft: + case CSSPropertyPaddingRight: + case CSSPropertyPaddingTop: + case CSSPropertyWebkitLogicalWidth: + case CSSPropertyWebkitLogicalHeight: + case CSSPropertyWebkitMinLogicalWidth: + case CSSPropertyWebkitMinLogicalHeight: + case CSSPropertyWebkitPaddingAfter: + case CSSPropertyWebkitPaddingBefore: + case CSSPropertyWebkitPaddingEnd: + case CSSPropertyWebkitPaddingStart: + acceptsNegativeNumbers = false; + return true; + case CSSPropertyBottom: + case CSSPropertyLeft: + case CSSPropertyMarginBottom: + case CSSPropertyMarginLeft: + case CSSPropertyMarginRight: + case CSSPropertyMarginTop: + case CSSPropertyRight: + case CSSPropertyTextIndent: + case CSSPropertyTop: + case CSSPropertyWebkitMarginAfter: + case CSSPropertyWebkitMarginBefore: + case CSSPropertyWebkitMarginEnd: + case CSSPropertyWebkitMarginStart: + acceptsNegativeNumbers = true; + return true; + default: + return false; + } +} + +static bool parseSimpleLengthValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) +{ + const UChar* characters = string.characters(); + unsigned length = string.length(); + if (!characters || !length) + return false; + bool acceptsNegativeNumbers; + if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) + return false; + + CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; + if (length > 2 && characters[length - 2] == 'p' && characters[length - 1] == 'x') { + length -= 2; + unit = CSSPrimitiveValue::CSS_PX; + } else if (length > 1 && characters[length - 1] == '%') { + length -= 1; + unit = CSSPrimitiveValue::CSS_PERCENTAGE; + } + + // We rely on charactersToDouble for validation as well. The function + // will set "ok" to "false" if the entire passed-in character range does + // not represent a double. + bool ok; + double number = charactersToDouble(characters, length, &ok); + if (!ok) + return false; + if (unit == CSSPrimitiveValue::CSS_NUMBER) { + if (number && strict) + return false; + unit = CSSPrimitiveValue::CSS_PX; + } + if (number < 0 && !acceptsNegativeNumbers) + return false; + + CSSStyleSheet* stylesheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + if (!stylesheet || !stylesheet->document()) + return false; + CSSProperty property(propertyId, stylesheet->document()->cssPrimitiveValueCache()->createValue(number, unit), important); + declaration->addParsedProperty(property); + return true; +} + +bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important, bool strict) +{ + if (parseSimpleLengthValue(declaration, propertyId, string, important, strict)) + return true; + if (parseColorValue(declaration, propertyId, string, important, strict)) + return true; + CSSParser parser(strict); + return parser.parseValue(declaration, propertyId, string, important); +} + +bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important) { #ifdef ANDROID_INSTRUMENT android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); - m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); setupParser("@-webkit-value{", string, "} "); - m_id = id; + m_id = propertyId; m_important = important; cssyyparse(this); @@ -341,7 +503,7 @@ bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter); #endif ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); - m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); setupParser("@-webkit-decls{color:", string, "} "); cssyyparse(this); @@ -376,7 +538,7 @@ void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorLi #endif RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc); - m_styleSheet = dummyStyleSheet.get(); + setStyleSheet(dummyStyleSheet.get()); m_selectorListForParseSelector = &selectorList; setupParser("@-webkit-selector{", string, "}"); @@ -403,7 +565,7 @@ bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const static const unsigned prefixLength = 15; ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet()); - m_styleSheet = static_cast<CSSStyleSheet*>(declaration->stylesheet()); + setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet())); if (styleSourceData) { m_currentRuleData = CSSRuleSourceData::create(); m_currentRuleData->styleSourceData = CSSStyleSourceData::create(); @@ -501,6 +663,12 @@ void CSSParser::clearProperties() m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; m_hasFontFaceOnlyValues = false; } + +void CSSParser::setStyleSheet(CSSStyleSheet* styleSheet) +{ + m_styleSheet = styleSheet; + m_primitiveValueCache = document() ? document()->cssPrimitiveValueCache() : CSSPrimitiveValueCache::create(); +} Document* CSSParser::document() const { @@ -688,11 +856,14 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyQuotes: // [<string> <string>]+ | none | inherit if (id) validPrimitive = true; + else + return parseQuotes(propId, important); break; - case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | inherit - if (id == CSSValueNormal || - id == CSSValueEmbed || - id == CSSValueBidiOverride) + case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | inherit + if (id == CSSValueNormal + || id == CSSValueEmbed + || id == CSSValueBidiOverride + || id == CSSValueWebkitIsolate) validPrimitive = true; break; @@ -829,9 +1000,10 @@ bool CSSParser::parseValue(int propId, bool important) break; case CSSPropertyTextAlign: - // left | right | center | justify | webkit_left | webkit_right | webkit_center | start | end | <string> | inherit - if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitCenter) || id == CSSValueStart || id == CSSValueEnd || - value->unit == CSSPrimitiveValue::CSS_STRING) + // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent | + // start | end | <string> | inherit + if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd + || value->unit == CSSPrimitiveValue::CSS_STRING) validPrimitive = true; break; @@ -958,9 +1130,9 @@ bool CSSParser::parseValue(int propId, bool important) if (list->length() != 1) return false; } else if (!m_strict && value->id == CSSValueHand) // MSIE 5 compatibility :/ - list->append(CSSPrimitiveValue::createIdentifier(CSSValuePointer)); + list->append(primitiveValueCache()->createIdentifierValue(CSSValuePointer)); else if (value && ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone)) - list->append(CSSPrimitiveValue::createIdentifier(value->id)); + list->append(primitiveValueCache()->createIdentifierValue(value->id)); m_valueList->next(); parsedValue = list.release(); break; @@ -1217,7 +1389,7 @@ bool CSSParser::parseValue(int propId, bool important) case CSSValueUnderline: case CSSValueOverline: case CSSValueLineThrough: - list->append(CSSPrimitiveValue::createIdentifier(value->id)); + list->append(primitiveValueCache()->createIdentifierValue(value->id)); break; default: isValid = false; @@ -1276,19 +1448,19 @@ bool CSSParser::parseValue(int propId, bool important) validPrimitive = validUnit(value, FLength | FPercent, m_strict); if (!validPrimitive) return false; - RefPtr<CSSPrimitiveValue> parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + RefPtr<CSSPrimitiveValue> parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); RefPtr<CSSPrimitiveValue> parsedValue2; if (num == 2) { value = m_valueList->next(); validPrimitive = validUnit(value, FLength | FPercent, m_strict); if (!validPrimitive) return false; - parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } else parsedValue2 = parsedValue1; RefPtr<Pair> pair = Pair::create(parsedValue1.release(), parsedValue2.release()); - RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(pair.release()); + RefPtr<CSSPrimitiveValue> val = primitiveValueCache()->createValue(pair.release()); addProperty(propId, val.release(), important); return true; } @@ -1467,7 +1639,7 @@ bool CSSParser::parseValue(int propId, bool important) else { // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property. if (validUnit(value, FNumber | FLength | FNonNeg, m_strict)) { - RefPtr<CSSValue> val = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + RefPtr<CSSValue> val = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); if (val) { addProperty(propId, val.release(), important); return true; @@ -1651,7 +1823,13 @@ bool CSSParser::parseValue(int propId, bool important) validPrimitive = true; break; - case CSSPropertyWebkitHyphenateLocale: + case CSSPropertyWebkitHyphenateLimitBefore: + case CSSPropertyWebkitHyphenateLimitAfter: + if (id == CSSValueAuto || validUnit(value, FInteger | FNonNeg, true)) + validPrimitive = true; + break; + + case CSSPropertyWebkitLocale: if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING) validPrimitive = true; break; @@ -1872,6 +2050,19 @@ bool CSSParser::parseValue(int propId, bool important) case CSSPropertyWebkitTextEmphasisStyle: return parseTextEmphasisStyle(important); + case CSSPropertyWebkitTextOrientation: + // FIXME: For now just support upright and vertical-right. + if (id == CSSValueVerticalRight || id == CSSValueUpright) + validPrimitive = true; + break; + + case CSSPropertyWebkitLineBoxContain: + if (id == CSSValueNone) + validPrimitive = true; + else + return parseLineBoxContain(important); + break; + #ifdef ANDROID_CSS_RING case CSSPropertyWebkitRing: { @@ -1918,13 +2109,13 @@ bool CSSParser::parseValue(int propId, bool important) if (validPrimitive) { if (id != 0) - parsedValue = CSSPrimitiveValue::createIdentifier(id); + parsedValue = primitiveValueCache()->createIdentifierValue(id); else if (value->unit == CSSPrimitiveValue::CSS_STRING) - parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); + parsedValue = primitiveValueCache()->createValue(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) - parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS) - parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + parsedValue = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else if (value->unit >= CSSParserValue::Q_EMS) parsedValue = CSSQuirkPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_EMS); m_valueList->next(); @@ -1948,7 +2139,7 @@ PassRefPtr<CSSValue> CSSParser::parseWCSSInputProperty() inputProperty = String(value->string); if (!inputProperty.isEmpty()) - parsedValue = CSSPrimitiveValue::create(inputProperty, CSSPrimitiveValue::CSS_STRING); + parsedValue = primitiveValueCache()->createValue(inputProperty, CSSPrimitiveValue::CSS_STRING); while (m_valueList->next()) { // pass all other values, if any. If we don't do this, @@ -1976,11 +2167,11 @@ void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) lval = rval; } -static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue) +static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue, CSSPrimitiveValueCache* primitiveValueCache) { if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) { - cssValue = CSSPrimitiveValue::createIdentifier(parserValue->id); + cssValue = primitiveValueCache->createIdentifierValue(parserValue->id); return true; } return false; @@ -2048,7 +2239,7 @@ bool CSSParser::parseFillShorthand(int propId, const int* properties, int numPro addFillValue(repeatYValue, val2.release()); if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) { // Reparse the value as a clip, and see if we succeed. - if (parseBackgroundClip(parserValue, val1)) + if (parseBackgroundClip(parserValue, val1, primitiveValueCache())) addFillValue(clipValue, val1.release()); // The property parsed successfully. else addFillValue(clipValue, CSSInitialValue::createImplicit()); // Some value was used for origin that is not supported by clip. Just reset clip instead. @@ -2365,10 +2556,10 @@ bool CSSParser::parsePage(int propId, bool important) return false; if (value->id == CSSValueAuto) { - addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important); + addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important); return true; } else if (value->id == 0 && value->unit == CSSPrimitiveValue::CSS_IDENT) { - addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING), important); + addProperty(propId, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important); return true; } return false; @@ -2410,14 +2601,14 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV switch (value->id) { case CSSValueAuto: if (prevParamType == None) { - parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id)); return Auto; } return None; case CSSValueLandscape: case CSSValuePortrait: if (prevParamType == None || prevParamType == PageSize) { - parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + parsedValues->append(primitiveValueCache()->createIdentifierValue(value->id)); return Orientation; } return None; @@ -2432,13 +2623,13 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV if (prevParamType == None || prevParamType == Orientation) { // Normalize to Page Size then Orientation order by prepending. // This is not specified by the CSS3 Paged Media specification, but for simpler processing later (CSSStyleSelector::applyPageSizeProperty). - parsedValues->prepend(CSSPrimitiveValue::createIdentifier(value->id)); + parsedValues->prepend(primitiveValueCache()->createIdentifierValue(value->id)); return PageSize; } return None; case 0: if (validUnit(value, FLength | FNonNeg, m_strict) && (prevParamType == None || prevParamType == Length)) { - parsedValues->append(CSSPrimitiveValue::create(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); + parsedValues->append(primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); return Length; } return None; @@ -2447,6 +2638,28 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV } } +// [ <string> <string> ]+ | inherit | none +// inherit and none are handled in parseValue. +bool CSSParser::parseQuotes(int propId, bool important) +{ + RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); + while (CSSParserValue* val = m_valueList->current()) { + RefPtr<CSSValue> parsedValue; + if (val->unit == CSSPrimitiveValue::CSS_STRING) + parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); + else + break; + values->append(parsedValue.release()); + m_valueList->next(); + } + if (values->length()) { + addProperty(propId, values.release(), important); + m_valueList->next(); + return true; + } + return false; +} + // [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit // in CSS 2.1 this got somewhat reduced: // [ <string> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit @@ -2499,10 +2712,10 @@ bool CSSParser::parseContent(int propId, bool important) case CSSValueNoCloseQuote: case CSSValueNone: case CSSValueNormal: - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (val->unit == CSSPrimitiveValue::CSS_STRING) { - parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); + parsedValue = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING); } if (!parsedValue) break; @@ -2539,7 +2752,7 @@ PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args) if (document() && document()->isHTMLDocument()) attrName = attrName.lower(); - return CSSPrimitiveValue::create(attrName, CSSPrimitiveValue::CSS_ATTR); + return primitiveValueCache()->createValue(attrName, CSSPrimitiveValue::CSS_ATTR); } PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() @@ -2547,7 +2760,7 @@ PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() int id = m_valueList->current()->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor || (id >= CSSValueGrey && id < CSSValueWebkitText && !m_strict)) - return CSSPrimitiveValue::createIdentifier(id); + return primitiveValueCache()->createIdentifierValue(id); return parseColor(); } @@ -2571,34 +2784,80 @@ bool CSSParser::parseFillImage(RefPtr<CSSValue>& value) return false; } -PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(CSSParserValueList* valueList, bool& xFound, bool& yFound) +PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList) +{ + int id = valueList->current()->id; + if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) { + int percent = 0; + if (id == CSSValueRight) + percent = 100; + else if (id == CSSValueCenter) + percent = 50; + return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent | FLength, m_strict)) + return primitiveValueCache()->createValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); + return 0; +} + +PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList) +{ + int id = valueList->current()->id; + if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) { + int percent = 0; + if (id == CSSValueBottom) + percent = 100; + else if (id == CSSValueCenter) + percent = 50; + return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent | FLength, m_strict)) + return primitiveValueCache()->createValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); + return 0; +} + +PassRefPtr<CSSValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag) { int id = valueList->current()->id; if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) { int percent = 0; if (id == CSSValueLeft || id == CSSValueRight) { - if (xFound) + if (cumulativeFlags & XFillPosition) return 0; - xFound = true; + cumulativeFlags |= XFillPosition; + individualFlag = XFillPosition; if (id == CSSValueRight) percent = 100; } else if (id == CSSValueTop || id == CSSValueBottom) { - if (yFound) + if (cumulativeFlags & YFillPosition) return 0; - yFound = true; + cumulativeFlags |= YFillPosition; + individualFlag = YFillPosition; if (id == CSSValueBottom) percent = 100; - } - else if (id == CSSValueCenter) + } else if (id == CSSValueCenter) { // Center is ambiguous, so we're not sure which position we've found yet, an x or a y. percent = 50; - return CSSPrimitiveValue::create(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + cumulativeFlags |= AmbiguousFillPosition; + individualFlag = AmbiguousFillPosition; + } + return primitiveValueCache()->createValue(percent, CSSPrimitiveValue::CSS_PERCENTAGE); + } + if (validUnit(valueList->current(), FPercent | FLength, m_strict)) { + if (!cumulativeFlags) { + cumulativeFlags |= XFillPosition; + individualFlag = XFillPosition; + } else if (cumulativeFlags & (XFillPosition | AmbiguousFillPosition)) { + cumulativeFlags |= YFillPosition; + individualFlag = YFillPosition; + } else + return 0; + return primitiveValueCache()->createValue(valueList->current()->fValue, + (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); } - if (validUnit(valueList->current(), FPercent | FLength, m_strict)) - return CSSPrimitiveValue::create(valueList->current()->fValue, - (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); - return 0; } @@ -2607,8 +2866,10 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue CSSParserValue* value = valueList->current(); // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length. - bool value1IsX = false, value1IsY = false; - value1 = parseFillPositionXY(valueList, value1IsX, value1IsY); + unsigned cumulativeFlags = 0; + FillPositionFlag value1Flag = InvalidFillPosition; + FillPositionFlag value2Flag = InvalidFillPosition; + value1 = parseFillPositionComponent(valueList, cumulativeFlags, value1Flag); if (!value1) return; @@ -2621,9 +2882,8 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue if (value && value->unit == CSSParserValue::Operator && value->iValue == ',') value = 0; - bool value2IsX = false, value2IsY = false; if (value) { - value2 = parseFillPositionXY(valueList, value2IsX, value2IsY); + value2 = parseFillPositionComponent(valueList, cumulativeFlags, value2Flag); if (value2) valueList->next(); else { @@ -2639,9 +2899,9 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue // is simply 50%. This is our default. // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center). // For left/right/center, the default of 50% in the y is still correct. - value2 = CSSPrimitiveValue::create(50, CSSPrimitiveValue::CSS_PERCENTAGE); + value2 = primitiveValueCache()->createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE); - if (value1IsY || value2IsX) + if (value1Flag == YFillPosition || value2Flag == XFillPosition) value1.swap(value2); } @@ -2652,20 +2912,20 @@ void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& valu int id = m_valueList->current()->id; if (id == CSSValueRepeatX) { m_implicitShorthand = true; - value1 = CSSPrimitiveValue::createIdentifier(CSSValueRepeat); - value2 = CSSPrimitiveValue::createIdentifier(CSSValueNoRepeat); + value1 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat); + value2 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat); m_valueList->next(); return; } if (id == CSSValueRepeatY) { m_implicitShorthand = true; - value1 = CSSPrimitiveValue::createIdentifier(CSSValueNoRepeat); - value2 = CSSPrimitiveValue::createIdentifier(CSSValueRepeat); + value1 = primitiveValueCache()->createIdentifierValue(CSSValueNoRepeat); + value2 = primitiveValueCache()->createIdentifierValue(CSSValueRepeat); m_valueList->next(); return; } if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace) - value1 = CSSPrimitiveValue::createIdentifier(id); + value1 = primitiveValueCache()->createIdentifierValue(id); else { value1 = 0; return; @@ -2681,12 +2941,12 @@ void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& valu id = m_valueList->current()->id; if (value && (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace)) { - value2 = CSSPrimitiveValue::createIdentifier(id); + value2 = primitiveValueCache()->createIdentifierValue(id); m_valueList->next(); } else { // If only one value was specified, value2 is the same as value1. m_implicitShorthand = true; - value2 = CSSPrimitiveValue::createIdentifier(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent()); + value2 = primitiveValueCache()->createIdentifierValue(static_cast<CSSPrimitiveValue*>(value1.get())->getIdent()); } } @@ -2696,39 +2956,39 @@ PassRefPtr<CSSValue> CSSParser::parseFillSize(int propId, bool& allowComma) CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueContain || value->id == CSSValueCover) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); RefPtr<CSSPrimitiveValue> parsedValue1; if (value->id == CSSValueAuto) - parsedValue1 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN); + parsedValue1 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN); else { if (!validUnit(value, FLength | FPercent, m_strict)) return 0; - parsedValue1 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + parsedValue1 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } CSSPropertyID property = static_cast<CSSPropertyID>(propId); RefPtr<CSSPrimitiveValue> parsedValue2; if ((value = m_valueList->next())) { if (value->id == CSSValueAuto) - parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN); + parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN); else if (value->unit == CSSParserValue::Operator && value->iValue == ',') allowComma = false; else { if (!validUnit(value, FLength | FPercent, m_strict)) return 0; - parsedValue2 = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + parsedValue2 = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } } if (!parsedValue2) { if (property == CSSPropertyWebkitBackgroundSize || property == CSSPropertyWebkitMaskSize) parsedValue2 = parsedValue1; else - parsedValue2 = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_UNKNOWN); + parsedValue2 = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_UNKNOWN); } - return CSSPrimitiveValue::create(Pair::create(parsedValue1.release(), parsedValue2.release())); + return primitiveValueCache()->createValue(Pair::create(parsedValue1.release(), parsedValue2.release())); } bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, @@ -2779,7 +3039,7 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, case CSSPropertyBackgroundAttachment: case CSSPropertyWebkitMaskAttachment: if (val->id == CSSValueScroll || val->id == CSSValueFixed || val->id == CSSValueLocal) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; @@ -2798,17 +3058,17 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox || ((propId == CSSPropertyWebkitBackgroundClip || propId == CSSPropertyWebkitMaskClip) && (val->id == CSSValueText || val->id == CSSValueWebkitText))) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; case CSSPropertyBackgroundClip: - if (parseBackgroundClip(val, currValue)) + if (parseBackgroundClip(val, currValue, primitiveValueCache())) m_valueList->next(); break; case CSSPropertyBackgroundOrigin: if (val->id == CSSValueBorderBox || val->id == CSSValuePaddingBox || val->id == CSSValueContentBox) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; @@ -2819,16 +3079,14 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, break; case CSSPropertyBackgroundPositionX: case CSSPropertyWebkitMaskPositionX: { - bool xFound = false, yFound = true; - currValue = parseFillPositionXY(m_valueList, xFound, yFound); + currValue = parseFillPositionX(m_valueList); if (currValue) m_valueList->next(); break; } case CSSPropertyBackgroundPositionY: case CSSPropertyWebkitMaskPositionY: { - bool xFound = true, yFound = false; - currValue = parseFillPositionXY(m_valueList, xFound, yFound); + currValue = parseFillPositionY(m_valueList); if (currValue) m_valueList->next(); break; @@ -2836,7 +3094,7 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2, case CSSPropertyWebkitBackgroundComposite: case CSSPropertyWebkitMaskComposite: if ((val->id >= CSSValueClear && val->id <= CSSValuePlusLighter) || val->id == CSSValueHighlight) { - currValue = CSSPrimitiveValue::createIdentifier(val->id); + currValue = primitiveValueCache()->createIdentifierValue(val->id); m_valueList->next(); } break; @@ -2903,7 +3161,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDelay() { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FTime, m_strict)) - return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); return 0; } @@ -2911,7 +3169,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDirection() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNormal || value->id == CSSValueAlternate) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); return 0; } @@ -2919,7 +3177,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationDuration() { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FTime | FNonNeg, m_strict)) - return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); return 0; } @@ -2927,7 +3185,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); return 0; } @@ -2935,9 +3193,9 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueInfinite) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); if (validUnit(value, FInteger | FNonNeg, m_strict)) - return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); + return primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); return 0; } @@ -2946,9 +3204,9 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationName() CSSParserValue* value = m_valueList->current(); if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) { if (value->id == CSSValueNone || (value->unit == CSSPrimitiveValue::CSS_STRING && equalIgnoringCase(value->string, "none"))) { - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache()->createIdentifierValue(CSSValueNone); } else { - return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING); + return primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING); } } return 0; @@ -2958,7 +3216,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueRunning || value->id == CSSValuePaused) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); return 0; } @@ -2969,11 +3227,11 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationProperty() return 0; int result = cssPropertyID(value->string); if (result) - return CSSPrimitiveValue::createIdentifier(result); + return primitiveValueCache()->createIdentifierValue(result); if (equalIgnoringCase(value->string, "all")) - return CSSPrimitiveValue::createIdentifier(CSSValueAll); + return primitiveValueCache()->createIdentifierValue(CSSValueAll); if (equalIgnoringCase(value->string, "none")) - return CSSPrimitiveValue::createIdentifier(CSSValueNone); + return primitiveValueCache()->createIdentifierValue(CSSValueNone); return 0; } @@ -2984,7 +3242,7 @@ bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<C // now get z if (m_valueList->current()) { if (validUnit(m_valueList->current(), FLength, m_strict)) { - value3 = CSSPrimitiveValue::create(m_valueList->current()->fValue, + value3 = primitiveValueCache()->createValue(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit); m_valueList->next(); return true; @@ -3017,7 +3275,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction() CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd) - return CSSPrimitiveValue::createIdentifier(value->id); + return primitiveValueCache()->createIdentifierValue(value->id); // We must be a function. if (value->unit != CSSParserValue::Function) @@ -3207,7 +3465,7 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) if (value->id == CSSValueNone) { if (m_valueList->next()) return false; - addProperty(propId, CSSPrimitiveValue::createIdentifier(value->id), important); + addProperty(propId, primitiveValueCache()->createIdentifierValue(value->id), important); return valid; } @@ -3277,7 +3535,7 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) if (numArgs == DASHBOARD_REGION_SHORT_NUM_PARAMETERS || numArgs == (DASHBOARD_REGION_SHORT_NUM_PARAMETERS*2-1)) { // This originally used CSSValueInvalid by accident. It might be more logical to use something else. - RefPtr<CSSPrimitiveValue> amount = CSSPrimitiveValue::createIdentifier(CSSValueInvalid); + RefPtr<CSSPrimitiveValue> amount = primitiveValueCache()->createIdentifierValue(CSSValueInvalid); region->setTop(amount); region->setRight(amount); @@ -3295,8 +3553,8 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) break; RefPtr<CSSPrimitiveValue> amount = arg->id == CSSValueAuto ? - CSSPrimitiveValue::createIdentifier(CSSValueAuto) : - CSSPrimitiveValue::create(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit); + primitiveValueCache()->createIdentifierValue(CSSValueAuto) : + primitiveValueCache()->createValue(arg->fValue, (CSSPrimitiveValue::UnitTypes) arg->unit); if (i == 0) region->setTop(amount); @@ -3316,7 +3574,7 @@ bool CSSParser::parseDashboardRegions(int propId, bool important) } if (valid) - addProperty(propId, CSSPrimitiveValue::create(firstRegion.release()), important); + addProperty(propId, primitiveValueCache()->createValue(firstRegion.release()), important); return valid; } @@ -3334,11 +3592,11 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo CSSParserValue* i = args->current(); if (i->unit != CSSPrimitiveValue::CSS_IDENT) return 0; - RefPtr<CSSPrimitiveValue> identifier = CSSPrimitiveValue::create(i->string, CSSPrimitiveValue::CSS_STRING); + RefPtr<CSSPrimitiveValue> identifier = primitiveValueCache()->createValue(i->string, CSSPrimitiveValue::CSS_STRING); RefPtr<CSSPrimitiveValue> separator; if (!counters) - separator = CSSPrimitiveValue::create(String(), CSSPrimitiveValue::CSS_STRING); + separator = primitiveValueCache()->createValue(String(), CSSPrimitiveValue::CSS_STRING); else { i = args->next(); if (i->unit != CSSParserValue::Operator || i->iValue != ',') @@ -3348,13 +3606,13 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo if (i->unit != CSSPrimitiveValue::CSS_STRING) return 0; - separator = CSSPrimitiveValue::create(i->string, (CSSPrimitiveValue::UnitTypes) i->unit); + separator = primitiveValueCache()->createValue(i->string, (CSSPrimitiveValue::UnitTypes) i->unit); } RefPtr<CSSPrimitiveValue> listStyle; i = args->next(); if (!i) // Make the list style default decimal - listStyle = CSSPrimitiveValue::create(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER); + listStyle = primitiveValueCache()->createValue(CSSValueDecimal - CSSValueDisc, CSSPrimitiveValue::CSS_NUMBER); else { if (i->unit != CSSParserValue::Operator || i->iValue != ',') return 0; @@ -3371,10 +3629,10 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo else return 0; - listStyle = CSSPrimitiveValue::create(ls, (CSSPrimitiveValue::UnitTypes) i->unit); + listStyle = primitiveValueCache()->createValue(ls, (CSSPrimitiveValue::UnitTypes) i->unit); } - return CSSPrimitiveValue::create(Counter::create(identifier.release(), listStyle.release(), separator.release())); + return primitiveValueCache()->createValue(Counter::create(identifier.release(), listStyle.release(), separator.release())); } bool CSSParser::parseShape(int propId, bool important) @@ -3397,8 +3655,8 @@ bool CSSParser::parseShape(int propId, bool important) if (!valid) break; RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ? - CSSPrimitiveValue::createIdentifier(CSSValueAuto) : - CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + primitiveValueCache()->createIdentifierValue(CSSValueAuto) : + primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); if (i == 0) rect->setTop(length); else if (i == 1) @@ -3419,7 +3677,7 @@ bool CSSParser::parseShape(int propId, bool important) i++; } if (valid) { - addProperty(propId, CSSPrimitiveValue::create(rect.release()), important); + addProperty(propId, primitiveValueCache()->createValue(rect.release()), important); m_valueList->next(); return true; } @@ -3441,15 +3699,15 @@ bool CSSParser::parseFont(bool important) } else if (id == CSSValueItalic || id == CSSValueOblique) { if (font->style) return false; - font->style = CSSPrimitiveValue::createIdentifier(id); + font->style = primitiveValueCache()->createIdentifierValue(id); } else if (id == CSSValueSmallCaps) { if (font->variant) return false; - font->variant = CSSPrimitiveValue::createIdentifier(id); + font->variant = primitiveValueCache()->createIdentifierValue(id); } else if (id >= CSSValueBold && id <= CSSValueLighter) { if (font->weight) return false; - font->weight = CSSPrimitiveValue::createIdentifier(id); + font->weight = primitiveValueCache()->createIdentifierValue(id); } else { valid = false; } @@ -3476,7 +3734,7 @@ bool CSSParser::parseFont(bool important) val = CSSValue900; if (val) - font->weight = CSSPrimitiveValue::createIdentifier(val); + font->weight = primitiveValueCache()->createIdentifierValue(val); else valid = false; } else { @@ -3491,18 +3749,18 @@ bool CSSParser::parseFont(bool important) // set undefined values to default if (!font->style) - font->style = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->style = primitiveValueCache()->createIdentifierValue(CSSValueNormal); if (!font->variant) - font->variant = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->variant = primitiveValueCache()->createIdentifierValue(CSSValueNormal); if (!font->weight) - font->weight = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->weight = primitiveValueCache()->createIdentifierValue(CSSValueNormal); // now a font size _must_ come // <absolute-size> | <relative-size> | <length> | <percentage> | inherit if (value->id >= CSSValueXxSmall && value->id <= CSSValueLarger) - font->size = CSSPrimitiveValue::createIdentifier(value->id); + font->size = primitiveValueCache()->createIdentifierValue(value->id); else if (validUnit(value, FLength | FPercent | FNonNeg, m_strict)) - font->size = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + font->size = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); value = m_valueList->next(); if (!font->size || !value) return false; @@ -3515,7 +3773,7 @@ bool CSSParser::parseFont(bool important) if (value->id == CSSValueNormal) { // default value, nothing to do } else if (validUnit(value, FNumber | FLength | FPercent | FNonNeg, m_strict)) - font->lineHeight = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); + font->lineHeight = primitiveValueCache()->createValue(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); else return false; value = m_valueList->next(); @@ -3524,7 +3782,7 @@ bool CSSParser::parseFont(bool important) } if (!font->lineHeight) - font->lineHeight = CSSPrimitiveValue::createIdentifier(CSSValueNormal); + font->lineHeight = primitiveValueCache()->createIdentifierValue(CSSValueNormal); // font family must come now font->family = parseFontFamily(); @@ -3554,7 +3812,7 @@ PassRefPtr<CSSValueList> CSSParser::parseFontFamily() if (currFamily) currFamily->appendSpaceSeparated(value->string.characters, value->string.length); else if (nextValBreaksFont || !nextValIsFontName) - list->append(CSSPrimitiveValue::createIdentifier(value->id)); + list->append(primitiveValueCache()->createIdentifierValue(value->id)); else { RefPtr<FontFamilyValue> newFamily = FontFamilyValue::create(value->string); currFamily = newFamily.get(); @@ -3607,12 +3865,12 @@ bool CSSParser::parseFontStyle(bool important) if (!expectComma) { expectComma = true; if (val->id == CSSValueNormal || val->id == CSSValueItalic || val->id == CSSValueOblique) - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { // 'all' is only allowed in @font-face and with no other values. Make a value list to // indicate that we are in the @font-face case. values = CSSValueList::createCommaSeparated(); - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') { expectComma = false; @@ -3654,12 +3912,12 @@ bool CSSParser::parseFontVariant(bool important) if (!expectComma) { expectComma = true; if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps) - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { // 'all' is only allowed in @font-face and with no other values. Make a value list to // indicate that we are in the @font-face case. values = CSSValueList::createCommaSeparated(); - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') { expectComma = false; @@ -3702,17 +3960,17 @@ bool CSSParser::parseFontWeight(bool important) expectComma = true; if (val->unit == CSSPrimitiveValue::CSS_IDENT) { if (val->id >= CSSValueNormal && val->id <= CSSValue900) - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { // 'all' is only allowed in @font-face and with no other values. Make a value list to // indicate that we are in the @font-face case. values = CSSValueList::createCommaSeparated(); - parsedValue = CSSPrimitiveValue::createIdentifier(val->id); + parsedValue = primitiveValueCache()->createIdentifierValue(val->id); } } else if (validUnit(val, FInteger | FNonNeg, false)) { int weight = static_cast<int>(val->fValue); if (!(weight % 100) && weight >= 100 && weight <= 900) - parsedValue = CSSPrimitiveValue::createIdentifier(CSSValue100 + weight / 100 - 1); + parsedValue = primitiveValueCache()->createIdentifierValue(CSSValue100 + weight / 100 - 1); } } else if (val->unit == CSSParserValue::Operator && val->iValue == ',') { expectComma = false; @@ -3903,10 +4161,76 @@ bool CSSParser::parseFontFaceUnicodeRange() return true; } -static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar terminator, int& value) +// Returns the number of characters which form a valid double +// and are terminated by the given terminator character +static int checkForValidDouble(const UChar* string, const UChar* end, const char terminator) +{ + int length = end - string; + if (length < 1) + return 0; + + bool decimalMarkSeen = false; + int processedLength = 0; + + for (int i = 0; i < length; ++i) { + if (string[i] == terminator) { + processedLength = i; + break; + } + if (!isASCIIDigit(string[i])) { + if (!decimalMarkSeen && string[i] == '.') + decimalMarkSeen = true; + else + return 0; + } + } + + if (decimalMarkSeen && processedLength == 1) + return 0; + + return processedLength; +} + +// Returns the number of characters consumed for parsing a valid double +// terminated by the given terminator character +static int parseDouble(const UChar* string, const UChar* end, const char terminator, double& value) +{ + int length = checkForValidDouble(string, end, terminator); + if (!length) + return 0; + + int position = 0; + double localValue = 0; + + // The consumed characters here are guaranteed to be + // ASCII digits with or without a decimal mark + for (; position < length; ++position) { + if (string[position] == '.') + break; + localValue = localValue * 10 + string[position] - '0'; + } + + if (++position == length) { + value = localValue; + return length; + } + + double fraction = 0; + double scale = 1; + + while (position < length && scale < MAX_SCALE) { + fraction = fraction * 10 + string[position++] - '0'; + scale *= 10; + } + + value = localValue + fraction / scale; + return length; +} + +static bool parseColorIntOrPercentage(const UChar*& string, const UChar* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value) { const UChar* current = string; - int localValue = 0; + double localValue = 0; bool negative = false; while (current != end && isHTMLSpace(*current)) current++; @@ -3917,7 +4241,7 @@ static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar t if (current == end || !isASCIIDigit(*current)) return false; while (current != end && isASCIIDigit(*current)) { - int newValue = localValue * 10 + *current++ - '0'; + double newValue = localValue * 10 + *current++ - '0'; if (newValue >= 255) { // Clamp values at 255. localValue = 255; @@ -3927,12 +4251,42 @@ static inline bool parseColorInt(const UChar*& string, const UChar* end, UChar t } localValue = newValue; } + + if (expect == CSSPrimitiveValue::CSS_NUMBER && (*current == '.' || *current == '%')) + return false; + + if (*current == '.') { + // We already parsed the integral part, try to parse + // the fraction part of the percentage value. + double percentage = 0; + int numCharactersParsed = parseDouble(current, end, '%', percentage); + if (!numCharactersParsed) + return false; + current += numCharactersParsed; + if (*current != '%') + return false; + localValue += percentage; + } + + if (expect == CSSPrimitiveValue::CSS_PERCENTAGE && *current != '%') + return false; + + if (*current == '%') { + expect = CSSPrimitiveValue::CSS_PERCENTAGE; + localValue = localValue / 100.0 * 256.0; + // Clamp values at 255 for percentages over 100% + if (localValue > 255) + localValue = 255; + current++; + } else + expect = CSSPrimitiveValue::CSS_NUMBER; + while (current != end && isHTMLSpace(*current)) current++; if (current == end || *current++ != terminator) return false; // Clamp negative values at zero. - value = negative ? 0 : localValue; + value = negative ? 0 : static_cast<int>(localValue); string = current; return true; } @@ -3950,48 +4304,55 @@ static inline bool isTenthAlpha(const UChar* string, const int length) return false; } -static inline bool parseAlphaValue(const UChar*& string, const UChar* end, UChar terminator, int& value) +static inline bool parseAlphaValue(const UChar*& string, const UChar* end, const char terminator, int& value) { while (string != end && isHTMLSpace(*string)) string++; + bool negative = false; + + if (string != end && *string == '-') { + negative = true; + string++; + } + value = 0; int length = end - string; if (length < 2) return false; - if (string[0] != '0' && string[0] != '1' && string[0] != '.') + if (string[length - 1] != terminator) return false; - if (string[length - 1] != terminator) + if (string[0] != '0' && string[0] != '1' && string[0] != '.') { + if (checkForValidDouble(string, end, terminator)) { + value = negative ? 0 : 255; + string = end; + return true; + } return false; + } if (length == 2 && string[0] != '.') { - value = string[0] == '1' ? 255 : 0; + value = !negative && string[0] == '1' ? 255 : 0; string = end; return true; } if (isTenthAlpha(string, length - 1)) { static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 }; - value = tenthAlphaValues[string[length - 2] - '0']; + value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0']; string = end; return true; } - Vector<char, 8> bytes(length + 1); - for (int i = 0; i < length; ++i) { - if (!isASCIIDigit(string[i]) && string[i] != '.' && string[i] != terminator) - return false; - bytes[i] = string[i]; - } - bytes[length] = '\0'; - char* foundTerminator; - double d = WTF::strtod(bytes.data(), &foundTerminator); - value = static_cast<int>(d * nextafter(256.0, 0.0)); - string += (foundTerminator - bytes.data()) + 1; - return *foundTerminator == terminator; + double alpha = 0; + if (!parseDouble(string, end, terminator, alpha)) + return false; + value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0)); + string = end; + return true; } static inline bool mightBeRGBA(const UChar* characters, unsigned length) @@ -4019,6 +4380,7 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) { const UChar* characters = name.characters(); unsigned length = name.length(); + CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN; if (!strict && length >= 3) { if (name[0] == '#') { @@ -4038,11 +4400,12 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) int green; int blue; int alpha; - if (!parseColorInt(current, end, ',', red)) + + if (!parseColorIntOrPercentage(current, end, ',', expect, red)) return false; - if (!parseColorInt(current, end, ',', green)) + if (!parseColorIntOrPercentage(current, end, ',', expect, green)) return false; - if (!parseColorInt(current, end, ',', blue)) + if (!parseColorIntOrPercentage(current, end, ',', expect, blue)) return false; if (!parseAlphaValue(current, end, ')', alpha)) return false; @@ -4059,11 +4422,11 @@ bool CSSParser::parseColor(const String &name, RGBA32& rgb, bool strict) int red; int green; int blue; - if (!parseColorInt(current, end, ',', red)) + if (!parseColorIntOrPercentage(current, end, ',', expect, red)) return false; - if (!parseColorInt(current, end, ',', green)) + if (!parseColorIntOrPercentage(current, end, ',', expect, green)) return false; - if (!parseColorInt(current, end, ')', blue)) + if (!parseColorIntOrPercentage(current, end, ')', expect, blue)) return false; if (current != end) return false; @@ -4174,7 +4537,7 @@ PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value) RGBA32 c = Color::transparent; if (!parseColorFromValue(value ? value : m_valueList->current(), c)) return 0; - return CSSPrimitiveValue::createColor(c); + return primitiveValueCache()->createColorValue(c); } bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) @@ -4232,8 +4595,9 @@ bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) // This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return) // without the allowBreak bit being set, then it will clean up all of the objects and destroy them. struct ShadowParseContext { - ShadowParseContext(CSSPropertyID prop) + ShadowParseContext(CSSPropertyID prop, CSSPrimitiveValueCache* primitiveValueCache) : property(prop) + , m_primitiveValueCache(primitiveValueCache) , allowX(true) , allowY(false) , allowBlur(false) @@ -4276,7 +4640,7 @@ struct ShadowParseContext { void commitLength(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + RefPtr<CSSPrimitiveValue> val = m_primitiveValueCache->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); if (allowX) { x = val.release(); @@ -4318,7 +4682,7 @@ struct ShadowParseContext { void commitStyle(CSSParserValue* v) { - style = CSSPrimitiveValue::createIdentifier(v->id); + style = m_primitiveValueCache->createIdentifierValue(v->id); allowStyle = false; if (allowX) allowBreak = false; @@ -4330,6 +4694,7 @@ struct ShadowParseContext { } CSSPropertyID property; + CSSPrimitiveValueCache* m_primitiveValueCache; RefPtr<CSSValueList> values; RefPtr<CSSPrimitiveValue> x; @@ -4350,7 +4715,7 @@ struct ShadowParseContext { bool CSSParser::parseShadow(int propId, bool important) { - ShadowParseContext context(static_cast<CSSPropertyID>(propId)); + ShadowParseContext context(static_cast<CSSPropertyID>(propId), primitiveValueCache()); CSSParserValue* val; while ((val = m_valueList->current())) { // Check for a comma break first. @@ -4386,7 +4751,7 @@ bool CSSParser::parseShadow(int propId, bool important) if (isColor) { if (!context.allowColor) return false; - parsedColor = CSSPrimitiveValue::createIdentifier(val->id); + parsedColor = primitiveValueCache()->createIdentifierValue(val->id); } if (!parsedColor) @@ -4443,11 +4808,11 @@ bool CSSParser::parseReflect(int propId, bool important) val = m_valueList->next(); RefPtr<CSSPrimitiveValue> offset; if (!val) - offset = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX); + offset = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_PX); else { if (!validUnit(val, FLength | FPercent, m_strict)) return false; - offset = CSSPrimitiveValue::create(val->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(val->unit)); + offset = primitiveValueCache()->createValue(val->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(val->unit)); } // Now for the mask. @@ -4465,8 +4830,9 @@ bool CSSParser::parseReflect(int propId, bool important) } struct BorderImageParseContext { - BorderImageParseContext() - : m_allowBreak(false) + BorderImageParseContext(CSSPrimitiveValueCache* primitiveValueCache) + : m_primitiveValueCache(primitiveValueCache) + , m_allowBreak(false) , m_allowNumber(false) , m_allowSlash(false) , m_allowWidth(false) @@ -4488,7 +4854,7 @@ struct BorderImageParseContext { void commitImage(PassRefPtr<CSSValue> image) { m_image = image; m_allowNumber = true; } void commitNumber(CSSParserValue* v) { - PassRefPtr<CSSPrimitiveValue> val = CSSPrimitiveValue::create(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); + PassRefPtr<CSSPrimitiveValue> val = m_primitiveValueCache->createValue(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); if (!m_top) m_top = val; else if (!m_right) @@ -4532,16 +4898,16 @@ struct BorderImageParseContext { { // We need to clone and repeat values for any omissions. if (!m_right) { - m_right = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_bottom = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_right = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_bottom = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_left = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); } if (!m_bottom) { - m_bottom = CSSPrimitiveValue::create(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); - m_left = CSSPrimitiveValue::create(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_bottom = m_primitiveValueCache->createValue(m_top->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_top->primitiveType()); + m_left = m_primitiveValueCache->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); } if (!m_left) - m_left = CSSPrimitiveValue::create(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); + m_left = m_primitiveValueCache->createValue(m_right->getDoubleValue(), (CSSPrimitiveValue::UnitTypes)m_right->primitiveType()); // Now build a rect value to hold all four of our primitive values. RefPtr<Rect> rect = Rect::create(); @@ -4578,6 +4944,8 @@ struct BorderImageParseContext { // Make our new border image value now. return CSSBorderImageValue::create(m_image, rect.release(), m_horizontalRule, m_verticalRule); } + + CSSPrimitiveValueCache* m_primitiveValueCache; bool m_allowBreak; bool m_allowNumber; @@ -4604,7 +4972,7 @@ struct BorderImageParseContext { bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& result) { // Look for an image initially. If the first value is not a URI, then we're done. - BorderImageParseContext context; + BorderImageParseContext context(primitiveValueCache()); CSSParserValue* val = m_valueList->current(); if (val->unit == CSSPrimitiveValue::CSS_URI && m_styleSheet) { // FIXME: The completeURL call should be done when using the CSSImageValue, @@ -4638,7 +5006,7 @@ bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& r if (context.allowNumber() && propId != CSSPropertyWebkitBorderImage) { // Allow the slices to be omitted for images that don't fit to a border. We just set the slices to be 0. - context.m_top = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER); + context.m_top = primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_NUMBER); context.m_allowBreak = true; } @@ -4693,7 +5061,7 @@ bool CSSParser::parseBorderRadius(int propId, bool important) if (!validUnit(value, FLength | FPercent, m_strict)) return false; - RefPtr<CSSPrimitiveValue> radius = CSSPrimitiveValue::create(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); + RefPtr<CSSPrimitiveValue> radius = primitiveValueCache()->createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); if (!indexAfterSlash) { radii[0][i] = radius; @@ -4715,10 +5083,10 @@ bool CSSParser::parseBorderRadius(int propId, bool important) completeBorderRadii(radii[1]); m_implicitShorthand = true; - addProperty(CSSPropertyBorderTopLeftRadius, CSSPrimitiveValue::create(Pair::create(radii[0][0].release(), radii[1][0].release())), important); - addProperty(CSSPropertyBorderTopRightRadius, CSSPrimitiveValue::create(Pair::create(radii[0][1].release(), radii[1][1].release())), important); - addProperty(CSSPropertyBorderBottomRightRadius, CSSPrimitiveValue::create(Pair::create(radii[0][2].release(), radii[1][2].release())), important); - addProperty(CSSPropertyBorderBottomLeftRadius, CSSPrimitiveValue::create(Pair::create(radii[0][3].release(), radii[1][3].release())), important); + addProperty(CSSPropertyBorderTopLeftRadius, primitiveValueCache()->createValue(Pair::create(radii[0][0].release(), radii[1][0].release())), important); + addProperty(CSSPropertyBorderTopRightRadius, primitiveValueCache()->createValue(Pair::create(radii[0][1].release(), radii[1][1].release())), important); + addProperty(CSSPropertyBorderBottomRightRadius, primitiveValueCache()->createValue(Pair::create(radii[0][2].release(), radii[1][2].release())), important); + addProperty(CSSPropertyBorderBottomLeftRadius, primitiveValueCache()->createValue(Pair::create(radii[0][3].release(), radii[1][3].release())), important); m_implicitShorthand = false; return true; } @@ -4735,7 +5103,7 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important) switch (state) { case ID: if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) { - counterName = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); + counterName = primitiveValueCache()->createValue(val->string, CSSPrimitiveValue::CSS_STRING); state = VAL; m_valueList->next(); continue; @@ -4748,8 +5116,8 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important) m_valueList->next(); } - list->append(CSSPrimitiveValue::create(Pair::create(counterName.release(), - CSSPrimitiveValue::create(i, CSSPrimitiveValue::CSS_NUMBER)))); + list->append(primitiveValueCache()->createValue(Pair::create(counterName.release(), + primitiveValueCache()->createValue(i, CSSPrimitiveValue::CSS_NUMBER)))); state = ID; continue; } @@ -4766,20 +5134,20 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important) } // This should go away once we drop support for -webkit-gradient -static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal) +static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal, CSSPrimitiveValueCache* primitiveValueCache) { RefPtr<CSSPrimitiveValue> result; if (a->unit == CSSPrimitiveValue::CSS_IDENT) { if ((equalIgnoringCase(a->string, "left") && horizontal) || (equalIgnoringCase(a->string, "top") && !horizontal)) - result = CSSPrimitiveValue::create(0., CSSPrimitiveValue::CSS_PERCENTAGE); + result = primitiveValueCache->createValue(0., CSSPrimitiveValue::CSS_PERCENTAGE); else if ((equalIgnoringCase(a->string, "right") && horizontal) || (equalIgnoringCase(a->string, "bottom") && !horizontal)) - result = CSSPrimitiveValue::create(100., CSSPrimitiveValue::CSS_PERCENTAGE); + result = primitiveValueCache->createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE); else if (equalIgnoringCase(a->string, "center")) - result = CSSPrimitiveValue::create(50., CSSPrimitiveValue::CSS_PERCENTAGE); + result = primitiveValueCache->createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE); } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE) - result = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); + result = primitiveValueCache->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); return result; } @@ -4804,13 +5172,13 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS return false; if (equalIgnoringCase(a->function->name, "from(")) - stop.m_position = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(0, CSSPrimitiveValue::CSS_NUMBER); else - stop.m_position = CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(1, CSSPrimitiveValue::CSS_NUMBER); int id = args->current()->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu) - stop.m_color = CSSPrimitiveValue::createIdentifier(id); + stop.m_color = p->primitiveValueCache()->createIdentifierValue(id); else stop.m_color = p->parseColor(args->current()); if (!stop.m_color) @@ -4824,9 +5192,9 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS CSSParserValue* stopArg = args->current(); if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE) - stop.m_position = CSSPrimitiveValue::create(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER); else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER) - stop.m_position = CSSPrimitiveValue::create(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER); + stop.m_position = p->primitiveValueCache()->createValue(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER); else return false; @@ -4837,7 +5205,7 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS stopArg = args->next(); int id = stopArg->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu) - stop.m_color = CSSPrimitiveValue::createIdentifier(id); + stop.m_color = p->primitiveValueCache()->createIdentifierValue(id); else stop.m_color = p->parseColor(stopArg); if (!stop.m_color) @@ -4887,7 +5255,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true); + RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true, primitiveValueCache()); if (!point) return false; result->setFirstX(point.release()); @@ -4896,7 +5264,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - point = parseDeprecatedGradientPoint(a, false); + point = parseDeprecatedGradientPoint(a, false, primitiveValueCache()); if (!point) return false; result->setFirstY(point.release()); @@ -4911,7 +5279,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER) return false; - static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); + static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(primitiveValueCache()->createValue(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); // Comma after the first radius. a = args->next(); @@ -4924,7 +5292,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - point = parseDeprecatedGradientPoint(a, true); + point = parseDeprecatedGradientPoint(a, true, primitiveValueCache()); if (!point) return false; result->setSecondX(point.release()); @@ -4933,7 +5301,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a) return false; - point = parseDeprecatedGradientPoint(a, false); + point = parseDeprecatedGradientPoint(a, false, primitiveValueCache()); if (!point) return false; result->setSecondY(point.release()); @@ -4948,7 +5316,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) a = args->next(); if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER) return false; - static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); + static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(primitiveValueCache()->createValue(a->fValue, CSSPrimitiveValue::CSS_NUMBER)); } // We now will accept any number of stops (0 or more). @@ -4977,7 +5345,7 @@ bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient) return true; } -static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal) +static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal, CSSPrimitiveValueCache* primitiveValueCache) { if (a->unit != CSSPrimitiveValue::CSS_IDENT) return 0; @@ -4994,14 +5362,14 @@ static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, boo default: return 0; } - return CSSPrimitiveValue::createIdentifier(a->id); + return primitiveValueCache->createIdentifierValue(a->id); } static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value) { int id = value->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu) - return CSSPrimitiveValue::createIdentifier(id); + return p->primitiveValueCache()->createIdentifierValue(id); return p->parseColor(value); } @@ -5022,7 +5390,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea bool expectComma = false; // Look for angle. if (validUnit(a, FAngle, true)) { - result->setAngle(CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit)); + result->setAngle(primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit)); a = args->next(); expectComma = true; @@ -5032,7 +5400,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea RefPtr<CSSPrimitiveValue> location; bool isHorizontal = false; - if ((location = valueFromSideKeyword(a, isHorizontal))) { + if ((location = valueFromSideKeyword(a, isHorizontal, primitiveValueCache()))) { if (isHorizontal) startX = location; else @@ -5040,7 +5408,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea a = args->next(); if (a) { - if ((location = valueFromSideKeyword(a, isHorizontal))) { + if ((location = valueFromSideKeyword(a, isHorizontal, primitiveValueCache()))) { if (isHorizontal) { if (startX) return false; @@ -5059,7 +5427,7 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea } if (!startX && !startY) - startY = CSSPrimitiveValue::createIdentifier(CSSValueTop); + startY = primitiveValueCache()->createIdentifierValue(CSSValueTop); result->setFirstX(startX.release()); result->setFirstY(startY.release()); @@ -5129,7 +5497,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea switch (a->id) { case CSSValueCircle: case CSSValueEllipse: - shapeValue = CSSPrimitiveValue::createIdentifier(a->id); + shapeValue = primitiveValueCache()->createIdentifierValue(a->id); foundValue = true; break; case CSSValueClosestSide: @@ -5138,7 +5506,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea case CSSValueFarthestCorner: case CSSValueContain: case CSSValueCover: - sizeValue = CSSPrimitiveValue::createIdentifier(a->id); + sizeValue = primitiveValueCache()->createIdentifierValue(a->id); foundValue = true; break; } @@ -5161,7 +5529,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea if (!shapeValue && !sizeValue) { if (validUnit(a, FLength | FPercent, m_strict)) { - horizontalSize = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + horizontalSize = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); a = args->next(); if (!a) return false; @@ -5170,7 +5538,7 @@ bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient, CSSGradientRepea } if (validUnit(a, FLength | FPercent, m_strict)) { - verticalSize = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); + verticalSize = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit); a = args->next(); if (!a) @@ -5218,7 +5586,7 @@ bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradie a = valueList->next(); if (a) { if (validUnit(a, FLength | FPercent, m_strict)) { - stop.m_position = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); + stop.m_position = primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit); a = valueList->next(); } } @@ -5439,7 +5807,7 @@ PassRefPtr<CSSValueList> CSSParser::parseTransform() return 0; // Add the value to the current transform operation. - transformValue->append(CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit)); + transformValue->append(primitiveValueCache()->createValue(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit)); a = args->next(); if (!a) @@ -5473,22 +5841,20 @@ bool CSSParser::parseTransformOrigin(int propId, int& propId1, int& propId2, int // parseTransformOriginShorthand advances the m_valueList pointer break; case CSSPropertyWebkitTransformOriginX: { - bool xFound = false, yFound = true; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionX(m_valueList); if (value) m_valueList->next(); break; } case CSSPropertyWebkitTransformOriginY: { - bool xFound = true, yFound = false; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionY(m_valueList); if (value) m_valueList->next(); break; } case CSSPropertyWebkitTransformOriginZ: { if (validUnit(m_valueList->current(), FLength, m_strict)) - value = CSSPrimitiveValue::create(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit); + value = primitiveValueCache()->createValue(m_valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit); if (value) m_valueList->next(); break; @@ -5512,15 +5878,13 @@ bool CSSParser::parsePerspectiveOrigin(int propId, int& propId1, int& propId2, R parseFillPosition(m_valueList, value, value2); break; case CSSPropertyWebkitPerspectiveOriginX: { - bool xFound = false, yFound = true; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionX(m_valueList); if (value) m_valueList->next(); break; } case CSSPropertyWebkitPerspectiveOriginY: { - bool xFound = true, yFound = false; - value = parseFillPositionXY(m_valueList, xFound, yFound); + value = parseFillPositionY(m_valueList); if (value) m_valueList->next(); break; @@ -5541,7 +5905,7 @@ bool CSSParser::parseTextEmphasisStyle(bool important) if (value->unit == CSSPrimitiveValue::CSS_STRING) { if (fill || shape || (valueListSize != 1 && !inShorthand())) return false; - addProperty(CSSPropertyWebkitTextEmphasisStyle, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_STRING), important); + addProperty(CSSPropertyWebkitTextEmphasisStyle, primitiveValueCache()->createValue(value->string, CSSPrimitiveValue::CSS_STRING), important); m_valueList->next(); return true; } @@ -5549,7 +5913,7 @@ bool CSSParser::parseTextEmphasisStyle(bool important) if (value->id == CSSValueNone) { if (fill || shape || (valueListSize != 1 && !inShorthand())) return false; - addProperty(CSSPropertyWebkitTextEmphasisStyle, CSSPrimitiveValue::createIdentifier(CSSValueNone), important); + addProperty(CSSPropertyWebkitTextEmphasisStyle, primitiveValueCache()->createIdentifierValue(CSSValueNone), important); m_valueList->next(); return true; } @@ -5557,11 +5921,11 @@ bool CSSParser::parseTextEmphasisStyle(bool important) if (value->id == CSSValueOpen || value->id == CSSValueFilled) { if (fill) return false; - fill = CSSPrimitiveValue::createIdentifier(value->id); + fill = primitiveValueCache()->createIdentifierValue(value->id); } else if (value->id == CSSValueDot || value->id == CSSValueCircle || value->id == CSSValueDoubleCircle || value->id == CSSValueTriangle || value->id == CSSValueSesame) { if (shape) return false; - shape = CSSPrimitiveValue::createIdentifier(value->id); + shape = primitiveValueCache()->createIdentifierValue(value->id); } else if (!inShorthand()) return false; else @@ -5587,6 +5951,46 @@ bool CSSParser::parseTextEmphasisStyle(bool important) return false; } +bool CSSParser::parseLineBoxContain(bool important) +{ + LineBoxContain lineBoxContain = LineBoxContainNone; + + for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { + if (value->id == CSSValueBlock) { + if (lineBoxContain & LineBoxContainBlock) + return false; + lineBoxContain |= LineBoxContainBlock; + } else if (value->id == CSSValueInline) { + if (lineBoxContain & LineBoxContainInline) + return false; + lineBoxContain |= LineBoxContainInline; + } else if (value->id == CSSValueFont) { + if (lineBoxContain & LineBoxContainFont) + return false; + lineBoxContain |= LineBoxContainFont; + } else if (value->id == CSSValueGlyphs) { + if (lineBoxContain & LineBoxContainGlyphs) + return false; + lineBoxContain |= LineBoxContainGlyphs; + } else if (value->id == CSSValueReplaced) { + if (lineBoxContain & LineBoxContainReplaced) + return false; + lineBoxContain |= LineBoxContainReplaced; + } else if (value->id == CSSValueInlineBox) { + if (lineBoxContain & LineBoxContainInlineBox) + return false; + lineBoxContain |= LineBoxContainInlineBox; + } else + return false; + } + + if (!lineBoxContain) + return false; + + addProperty(CSSPropertyWebkitLineBoxContain, CSSLineBoxContainValue::create(lineBoxContain), important); + return true; +} + static inline int yyerror(const char*) { return 1; } #define END_TOKEN 0 @@ -5618,6 +6022,7 @@ int CSSParser::lex(void* yylvalWithoutType) case DIMEN: case UNICODERANGE: case FUNCTION: + case ANYFUNCTION: case NOTFUNCTION: yylval->string.characters = t; yylval->string.length = length; @@ -5831,6 +6236,22 @@ PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* return adoptPtr(selector); } +Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector() +{ + Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >; + m_floatingSelectorVectors.add(selectorVector); + return selectorVector; +} + +PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector) +{ + if (selectorVector) { + ASSERT(m_floatingSelectorVectors.contains(selectorVector)); + m_floatingSelectorVectors.remove(selectorVector); + } + return adoptPtr(selectorVector); +} + CSSParserValueList* CSSParser::createFloatingValueList() { CSSParserValueList* list = new CSSParserValueList; @@ -6041,9 +6462,6 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre return; } - if (Document* doc = document()) - doc->setUsesDescendantRules(true); - specifiers->setRelation(CSSSelector::ShadowDescendant); if (CSSParserSelector* history = specifiers->tagHistory()) { history->setTag(tag); @@ -6266,6 +6684,13 @@ static int cssPropertyID(const UChar* propertyName, unsigned length) const char* const opacity = "opacity"; name = opacity; length = strlen(opacity); +#if PLATFORM(IOS) + } else if (!strcmp(buffer, "-webkit-hyphenate-locale")) { + // Worked in iOS 4.2. + const char* const webkitLocale = "-webkit-locale"; + name = webkitLocale; + length = strlen(webkitLocale); +#endif } else if (hasPrefix(buffer + 7, length - 7, "-border-")) { // -webkit-border-*-*-radius worked in Safari 4 and earlier. -webkit-border-radius syntax // differs from border-radius, so it is remains as a distinct property. @@ -6410,11 +6835,8 @@ String quoteCSSString(const String& string) buffer[index++] = ch; afterEscape = false; } else if (ch < 0x20 || ch == 0x7F) { // Control characters. - static const char hexDigits[17] = "0123456789abcdef"; buffer[index++] = '\\'; - if (ch >= 0x10) - buffer[index++] = hexDigits[ch >> 4]; - buffer[index++] = hexDigits[ch & 0xF]; + placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase); afterEscape = true; } else { // Space character may be required to separate backslash-escape sequence and normal characters. diff --git a/Source/WebCore/css/CSSParser.h b/Source/WebCore/css/CSSParser.h index 6ccfbe2..4b1fad6 100644 --- a/Source/WebCore/css/CSSParser.h +++ b/Source/WebCore/css/CSSParser.h @@ -38,6 +38,7 @@ namespace WebCore { class CSSMutableStyleDeclaration; class CSSPrimitiveValue; + class CSSPrimitiveValueCache; class CSSProperty; class CSSRule; class CSSRuleList; @@ -62,7 +63,7 @@ namespace WebCore { void parseSheet(CSSStyleSheet*, const String&, int startLineNumber = 0, StyleRuleRangeMap* ruleRangeMap = 0); PassRefPtr<CSSRule> parseRule(CSSStyleSheet*, const String&); PassRefPtr<CSSRule> parseKeyframeRule(CSSStyleSheet*, const String&); - bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important); + static bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important, bool strict); static bool parseColor(RGBA32& color, const String&, bool strict = false); static bool parseSystemColor(RGBA32& color, const String&, Document*); bool parseColor(CSSMutableStyleDeclaration*, const String&); @@ -70,6 +71,8 @@ namespace WebCore { bool parseMediaQuery(MediaList*, const String&); Document* document() const; + + CSSPrimitiveValueCache* primitiveValueCache() const { return m_primitiveValueCache.get(); } void addProperty(int propId, PassRefPtr<CSSValue>, bool important); void rollbackLastProperties(int num); @@ -79,14 +82,20 @@ namespace WebCore { bool parseShorthand(int propId, const int* properties, int numProperties, bool important); bool parse4Values(int propId, const int* properties, bool important); bool parseContent(int propId, bool important); + bool parseQuotes(int propId, bool important); PassRefPtr<CSSValue> parseAttr(CSSParserValueList* args); PassRefPtr<CSSValue> parseBackgroundColor(); bool parseFillImage(RefPtr<CSSValue>&); - PassRefPtr<CSSValue> parseFillPositionXY(CSSParserValueList*, bool& xFound, bool& yFound); + + enum FillPositionFlag { InvalidFillPosition = 0, AmbiguousFillPosition = 1, XFillPosition = 2, YFillPosition = 4 }; + PassRefPtr<CSSValue> parseFillPositionComponent(CSSParserValueList*, unsigned& cumulativeFlags, FillPositionFlag& individualFlag); + PassRefPtr<CSSValue> parseFillPositionX(CSSParserValueList*); + PassRefPtr<CSSValue> parseFillPositionY(CSSParserValueList*); void parseFillPosition(CSSParserValueList*, RefPtr<CSSValue>&, RefPtr<CSSValue>&); + void parseFillRepeat(RefPtr<CSSValue>&, RefPtr<CSSValue>&); PassRefPtr<CSSValue> parseFillSize(int propId, bool &allowComma); @@ -169,11 +178,16 @@ namespace WebCore { bool parseTextEmphasisStyle(bool important); + bool parseLineBoxContain(bool important); + int yyparse(); CSSParserSelector* createFloatingSelector(); PassOwnPtr<CSSParserSelector> sinkFloatingSelector(CSSParserSelector*); + Vector<OwnPtr<CSSParserSelector> >* createFloatingSelectorVector(); + PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >*); + CSSParserValueList* createFloatingValueList(); CSSParserValueList* sinkFloatingValueList(CSSParserValueList*); @@ -225,6 +239,7 @@ namespace WebCore { CSSParserValueList* m_valueList; CSSProperty** m_parsedProperties; CSSSelectorList* m_selectorListForParseSelector; + RefPtr<CSSPrimitiveValueCache> m_primitiveValueCache; unsigned m_numParsedProperties; unsigned m_maxParsedProperties; unsigned m_numParsedPropertiesBeforeMarginBox; @@ -261,6 +276,8 @@ namespace WebCore { int lex(); private: + void setStyleSheet(CSSStyleSheet*); + void recheckAtKeyword(const UChar* str, int len); void setupParser(const char* prefix, const String&, const char* suffix); @@ -274,6 +291,8 @@ namespace WebCore { bool isGeneratedImageValue(CSSParserValue*) const; bool parseGeneratedImage(RefPtr<CSSValue>&); + bool parseValue(CSSMutableStyleDeclaration*, int propId, const String&, bool important); + enum SizeParameterType { None, Auto, @@ -304,6 +323,7 @@ namespace WebCore { Vector<RefPtr<StyleBase> > m_parsedStyleObjects; Vector<RefPtr<CSSRuleList> > m_parsedRuleLists; HashSet<CSSParserSelector*> m_floatingSelectors; + HashSet<Vector<OwnPtr<CSSParserSelector> >*> m_floatingSelectorVectors; HashSet<CSSParserValueList*> m_floatingValueLists; HashSet<CSSParserFunction*> m_floatingFunctions; diff --git a/Source/WebCore/css/CSSParserValues.cpp b/Source/WebCore/css/CSSParserValues.cpp index dc0e82b..94dcd3c 100644 --- a/Source/WebCore/css/CSSParserValues.cpp +++ b/Source/WebCore/css/CSSParserValues.cpp @@ -25,6 +25,7 @@ #include "CSSFunctionValue.h" #include "CSSQuirkPrimitiveValue.h" #include "CSSSelector.h" +#include "CSSSelectorList.h" namespace WebCore { @@ -43,12 +44,23 @@ void CSSParserValueList::addValue(const CSSParserValue& v) { m_values.append(v); } - + +void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v) +{ + m_values.insert(i, v); +} + void CSSParserValueList::deleteValueAt(unsigned i) { m_values.remove(i); } +void CSSParserValueList::extend(CSSParserValueList& valueList) +{ + for (unsigned int i = 0; i < valueList.size(); ++i) + m_values.append(*(valueList.valueAt(i))); +} + PassRefPtr<CSSValue> CSSParserValue::createCSSValue() { RefPtr<CSSValue> parsedValue; @@ -96,5 +108,11 @@ CSSParserSelector::~CSSParserSelector() deleteAllValues(toDelete); } +void CSSParserSelector::adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector) +{ + CSSSelectorList* selectorList = fastNew<CSSSelectorList>(); + selectorList->adoptSelectorVector(selectorVector); + m_selector->setSelectorList(adoptPtr(selectorList)); +} } diff --git a/Source/WebCore/css/CSSParserValues.h b/Source/WebCore/css/CSSParserValues.h index d084091..81ecbc3 100644 --- a/Source/WebCore/css/CSSParserValues.h +++ b/Source/WebCore/css/CSSParserValues.h @@ -71,7 +71,9 @@ public: ~CSSParserValueList(); void addValue(const CSSParserValue&); + void insertValueAt(unsigned, const CSSParserValue&); void deleteValueAt(unsigned); + void extend(CSSParserValueList&); unsigned size() const { return m_values.size(); } CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; } @@ -105,11 +107,12 @@ public: void setValue(const AtomicString& value) { m_selector->setValue(value); } void setAttribute(const QualifiedName& value) { m_selector->setAttribute(value); } void setArgument(const AtomicString& value) { m_selector->setArgument(value); } - void setSimpleSelector(PassOwnPtr<CSSSelector> value) { m_selector->setSimpleSelector(value); } void setMatch(CSSSelector::Match value) { m_selector->m_match = value; } void setRelation(CSSSelector::Relation value) { m_selector->m_relation = value; } void setForPage() { m_selector->setForPage(); } - + + void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector); + CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); } bool isUnknownPseudoElement() const { return m_selector->isUnknownPseudoElement(); } bool isSimple() const { return !m_tagHistory && m_selector->isSimple(); } diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp index 6d930bd..04f1089 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.cpp +++ b/Source/WebCore/css/CSSPrimitiveValue.cpp @@ -87,103 +87,6 @@ static CSSTextCache& cssTextCache() return cache; } -// A more stylish solution than sharing would be to turn CSSPrimitiveValue (or CSSValues in general) into non-virtual, -// non-refcounted simple type with value semantics. In practice these sharing tricks get similar memory benefits -// with less need for refactoring. - -inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncachedIdentifier(int identifier) -{ - return adoptRef(new CSSPrimitiveValue(identifier)); -} - -inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncachedColor(unsigned rgbValue) -{ - return adoptRef(new CSSPrimitiveValue(rgbValue)); -} - -inline PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createUncached(double value, UnitTypes type) -{ - return adoptRef(new CSSPrimitiveValue(value, type)); -} - -PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createIdentifier(int ident) -{ - static RefPtr<CSSPrimitiveValue>* identValueCache = new RefPtr<CSSPrimitiveValue>[numCSSValueKeywords]; - if (ident >= 0 && ident < numCSSValueKeywords) { - RefPtr<CSSPrimitiveValue> primitiveValue = identValueCache[ident]; - if (!primitiveValue) { - primitiveValue = createUncachedIdentifier(ident); - identValueCache[ident] = primitiveValue; - } - return primitiveValue.release(); - } - return createUncachedIdentifier(ident); -} - -PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::createColor(unsigned rgbValue) -{ - typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache; - static ColorValueCache* colorValueCache = new ColorValueCache; - // These are the empty and deleted values of the hash table. - if (rgbValue == Color::transparent) { - static CSSPrimitiveValue* colorTransparent = createUncachedColor(Color::transparent).releaseRef(); -#if CPU(ARM) && OS(LINUX) - // A workaround for gcc bug on ARM. - if (!colorTransparent) - return 0; -#endif - return colorTransparent; - } - if (rgbValue == Color::white) { - static CSSPrimitiveValue* colorWhite = createUncachedColor(Color::white).releaseRef(); -#if CPU(ARM) && OS(LINUX) - // A workaround for gcc bug on ARM. - if (!colorWhite) - return 0; -#endif - return colorWhite; - } - RefPtr<CSSPrimitiveValue> primitiveValue = colorValueCache->get(rgbValue); - if (primitiveValue) - return primitiveValue.release(); - primitiveValue = createUncachedColor(rgbValue); - // Just wipe out the cache and start rebuilding when it gets too big. - const int maxColorCacheSize = 512; - if (colorValueCache->size() >= maxColorCacheSize) - colorValueCache->clear(); - colorValueCache->add(rgbValue, primitiveValue); - - return primitiveValue.release(); -} - -PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(double value, UnitTypes type) -{ - // Small integers are very common. Try to share them. - const int cachedIntegerCount = 128; - // Other common primitive types have UnitTypes smaller than this. - const int maxCachedUnitType = CSS_PX; - typedef RefPtr<CSSPrimitiveValue>(* IntegerValueCache)[maxCachedUnitType + 1]; - static IntegerValueCache integerValueCache = new RefPtr<CSSPrimitiveValue>[cachedIntegerCount][maxCachedUnitType + 1]; - if (type <= maxCachedUnitType && value >= 0 && value < cachedIntegerCount) { - int intValue = static_cast<int>(value); - if (value == intValue) { - RefPtr<CSSPrimitiveValue> primitiveValue = integerValueCache[intValue][type]; - if (!primitiveValue) { - primitiveValue = createUncached(value, type); - integerValueCache[intValue][type] = primitiveValue; - } - return primitiveValue.release(); - } - } - - return createUncached(value, type); -} - -PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::create(const String& value, UnitTypes type) -{ - return adoptRef(new CSSPrimitiveValue(value, type)); -} - static const AtomicString& valueOrPropertyName(int valueOrPropertyID) { ASSERT_ARG(valueOrPropertyID, valueOrPropertyID >= 0); @@ -270,7 +173,6 @@ CSSPrimitiveValue::CSSPrimitiveValue(const Length& length) m_value.num = length.percent(); break; case Relative: - case Static: ASSERT_NOT_REACHED(); break; } @@ -809,6 +711,11 @@ String CSSPrimitiveValue::cssText() const text = String::adopt(result); break; } + case CSS_COUNTER_NAME: + text = "counter("; + text += m_value.string; + text += ")"; + break; case CSS_COUNTER: text = "counter("; text += String::number(m_value.num); diff --git a/Source/WebCore/css/CSSPrimitiveValue.h b/Source/WebCore/css/CSSPrimitiveValue.h index c9892e8..499e95c 100644 --- a/Source/WebCore/css/CSSPrimitiveValue.h +++ b/Source/WebCore/css/CSSPrimitiveValue.h @@ -90,7 +90,10 @@ public: // These are from CSS3 Values and Units, but that isn't a finished standard yet CSS_TURN = 107, - CSS_REMS = 108 + CSS_REMS = 108, + + // This is used internally for counter names (as opposed to counter values) + CSS_COUNTER_NAME = 109 }; // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies. @@ -107,10 +110,10 @@ public: static bool isUnitTypeLength(int type) { return (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) || type == CSSPrimitiveValue::CSS_REMS; } - static PassRefPtr<CSSPrimitiveValue> createIdentifier(int ident); - static PassRefPtr<CSSPrimitiveValue> createColor(unsigned rgbValue); - static PassRefPtr<CSSPrimitiveValue> create(double value, UnitTypes type); - static PassRefPtr<CSSPrimitiveValue> create(const String& value, UnitTypes type); + static PassRefPtr<CSSPrimitiveValue> createIdentifier(int identifier) { return adoptRef(new CSSPrimitiveValue(identifier)); } + static PassRefPtr<CSSPrimitiveValue> createColor(unsigned rgbValue) { return adoptRef(new CSSPrimitiveValue(rgbValue)); } + static PassRefPtr<CSSPrimitiveValue> create(double value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); } + static PassRefPtr<CSSPrimitiveValue> create(const String& value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); } template<typename T> static PassRefPtr<CSSPrimitiveValue> create(T value) { diff --git a/Source/WebCore/css/CSSPrimitiveValueCache.cpp b/Source/WebCore/css/CSSPrimitiveValueCache.cpp new file mode 100644 index 0000000..5c7a4c0 --- /dev/null +++ b/Source/WebCore/css/CSSPrimitiveValueCache.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSPrimitiveValueCache.h" + +namespace WebCore { + +CSSPrimitiveValueCache::CSSPrimitiveValueCache() + : m_colorTransparent(CSSPrimitiveValue::createColor(Color::transparent)) + , m_colorWhite(CSSPrimitiveValue::createColor(Color::white)) + , m_colorBlack(CSSPrimitiveValue::createColor(Color::black)) + , m_pixelZero(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX)) + , m_percentZero(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PERCENTAGE)) + , m_numberZero(CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER)) +{ +} + +CSSPrimitiveValueCache::~CSSPrimitiveValueCache() +{ +} + +PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValueCache::createIdentifierValue(int ident) +{ + if (ident <= 0 || ident >= numCSSValueKeywords) + return CSSPrimitiveValue::createIdentifier(ident); + + RefPtr<CSSPrimitiveValue> dummyValue; + pair<IdentifierValueCache::iterator, bool> entry = m_identifierValueCache.add(ident, dummyValue); + if (entry.second) + entry.first->second = CSSPrimitiveValue::createIdentifier(ident); + return entry.first->second; +} + +PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValueCache::createColorValue(unsigned rgbValue) +{ + // These are the empty and deleted values of the hash table. + if (rgbValue == Color::transparent) + return m_colorTransparent; + if (rgbValue == Color::white) + return m_colorWhite; + // Just because it is common. + if (rgbValue == Color::black) + return m_colorBlack; + + // Just wipe out the cache and start rebuilding if it gets too big. + const int maximumColorCacheSize = 512; + if (m_colorValueCache.size() > maximumColorCacheSize) + m_colorValueCache.clear(); + + RefPtr<CSSPrimitiveValue> dummyValue; + pair<ColorValueCache::iterator, bool> entry = m_colorValueCache.add(rgbValue, dummyValue); + if (entry.second) + entry.first->second = CSSPrimitiveValue::createColor(rgbValue); + return entry.first->second; +} + +PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValueCache::createValue(double value, CSSPrimitiveValue::UnitTypes type) +{ + // Small positive integers repeat often. + static const int maximumCacheableValue = 256; + if (value < 0 || value > maximumCacheableValue) + return CSSPrimitiveValue::create(value, type); + + int intValue = static_cast<int>(value); + if (value != intValue) + return CSSPrimitiveValue::create(value, type); + + IntegerValueCache* cache; + switch (type) { + case CSSPrimitiveValue::CSS_PX: + if (intValue == 0) + return m_pixelZero; + cache = &m_pixelValueCache; + break; + case CSSPrimitiveValue::CSS_PERCENTAGE: + if (intValue == 0) + return m_percentZero; + cache = &m_percentValueCache; + break; + case CSSPrimitiveValue::CSS_NUMBER: + if (intValue == 0) + return m_numberZero; + cache = &m_numberValueCache; + break; + default: + return CSSPrimitiveValue::create(value, type); + } + + RefPtr<CSSPrimitiveValue> dummyValue; + pair<IntegerValueCache::iterator, bool> entry = cache->add(intValue, dummyValue); + if (entry.second) + entry.first->second = CSSPrimitiveValue::create(value, type); + return entry.first->second; +} + +} diff --git a/Source/WebCore/css/CSSPrimitiveValueCache.h b/Source/WebCore/css/CSSPrimitiveValueCache.h new file mode 100644 index 0000000..0290e40 --- /dev/null +++ b/Source/WebCore/css/CSSPrimitiveValueCache.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSPrimitiveValueCache_h +#define CSSPrimitiveValueCache_h + +#include "CSSPrimitiveValue.h" +#include "CSSValueKeywords.h" +#include <wtf/HashMap.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class CSSPrimitiveValue; + +class CSSPrimitiveValueCache : public RefCounted<CSSPrimitiveValueCache> { +public: + static PassRefPtr<CSSPrimitiveValueCache> create() { return adoptRef(new CSSPrimitiveValueCache); } + ~CSSPrimitiveValueCache(); + + PassRefPtr<CSSPrimitiveValue> createIdentifierValue(int identifier); + PassRefPtr<CSSPrimitiveValue> createColorValue(unsigned rgbValue); + PassRefPtr<CSSPrimitiveValue> createValue(double value, CSSPrimitiveValue::UnitTypes); + PassRefPtr<CSSPrimitiveValue> createValue(String value, CSSPrimitiveValue::UnitTypes type) { return CSSPrimitiveValue::create(value, type); } + template<typename T> static PassRefPtr<CSSPrimitiveValue> createValue(T value) { return CSSPrimitiveValue::create(value); } + +private: + CSSPrimitiveValueCache(); + + typedef HashMap<int, RefPtr<CSSPrimitiveValue> > IdentifierValueCache; + IdentifierValueCache m_identifierValueCache; + + typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache; + ColorValueCache m_colorValueCache; + RefPtr<CSSPrimitiveValue> m_colorTransparent; + RefPtr<CSSPrimitiveValue> m_colorWhite; + RefPtr<CSSPrimitiveValue> m_colorBlack; + + typedef HashMap<int, RefPtr<CSSPrimitiveValue> > IntegerValueCache; + RefPtr<CSSPrimitiveValue> m_pixelZero; + RefPtr<CSSPrimitiveValue> m_percentZero; + RefPtr<CSSPrimitiveValue> m_numberZero; + IntegerValueCache m_pixelValueCache; + IntegerValueCache m_percentValueCache; + IntegerValueCache m_numberValueCache; +}; + +} + +#endif diff --git a/Source/WebCore/css/CSSPrimitiveValueMappings.h b/Source/WebCore/css/CSSPrimitiveValueMappings.h index fb4aff3..b1f9aec 100644 --- a/Source/WebCore/css/CSSPrimitiveValueMappings.h +++ b/Source/WebCore/css/CSSPrimitiveValueMappings.h @@ -39,8 +39,10 @@ #include "RenderStyleConstants.h" #include "SVGRenderStyleDefs.h" #include "TextDirection.h" +#include "TextOrientation.h" #include "TextRenderingMode.h" #include "ThemeTypes.h" +#include "UnicodeBidi.h" namespace WebCore { @@ -1616,30 +1618,36 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ETextAlign e) , m_hasCachedCSSText(false) { switch (e) { - case TAAUTO: - m_value.ident = CSSValueWebkitAuto; - break; - case LEFT: - m_value.ident = CSSValueLeft; - break; - case RIGHT: - m_value.ident = CSSValueRight; - break; - case CENTER: - m_value.ident = CSSValueCenter; - break; - case JUSTIFY: - m_value.ident = CSSValueJustify; - break; - case WEBKIT_LEFT: - m_value.ident = CSSValueWebkitLeft; - break; - case WEBKIT_RIGHT: - m_value.ident = CSSValueWebkitRight; - break; - case WEBKIT_CENTER: - m_value.ident = CSSValueWebkitCenter; - break; + case TAAUTO: + m_value.ident = CSSValueWebkitAuto; + break; + case TASTART: + m_value.ident = CSSValueStart; + break; + case TAEND: + m_value.ident = CSSValueEnd; + break; + case LEFT: + m_value.ident = CSSValueLeft; + break; + case RIGHT: + m_value.ident = CSSValueRight; + break; + case CENTER: + m_value.ident = CSSValueCenter; + break; + case JUSTIFY: + m_value.ident = CSSValueJustify; + break; + case WEBKIT_LEFT: + m_value.ident = CSSValueWebkitLeft; + break; + case WEBKIT_RIGHT: + m_value.ident = CSSValueWebkitRight; + break; + case WEBKIT_CENTER: + m_value.ident = CSSValueWebkitCenter; + break; } } @@ -1647,9 +1655,9 @@ template<> inline CSSPrimitiveValue::operator ETextAlign() const { switch (m_value.ident) { case CSSValueStart: + return TASTART; case CSSValueEnd: - ASSERT_NOT_REACHED(); // Depends on direction, thus should be handled by the caller. - return LEFT; + return TAEND; default: return static_cast<ETextAlign>(m_value.ident - CSSValueWebkitAuto); } @@ -1734,30 +1742,34 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EUnicodeBidi e) , m_hasCachedCSSText(false) { switch (e) { - case UBNormal: - m_value.ident = CSSValueNormal; - break; - case Embed: - m_value.ident = CSSValueEmbed; - break; - case Override: - m_value.ident = CSSValueBidiOverride; - break; + case UBNormal: + m_value.ident = CSSValueNormal; + break; + case Embed: + m_value.ident = CSSValueEmbed; + break; + case Override: + m_value.ident = CSSValueBidiOverride; + break; + case Isolate: + m_value.ident = CSSValueWebkitIsolate; } } template<> inline CSSPrimitiveValue::operator EUnicodeBidi() const { switch (m_value.ident) { - case CSSValueNormal: - return UBNormal; - case CSSValueEmbed: - return Embed; - case CSSValueBidiOverride: - return Override; - default: - ASSERT_NOT_REACHED(); - return UBNormal; + case CSSValueNormal: + return UBNormal; + case CSSValueEmbed: + return Embed; + case CSSValueBidiOverride: + return Override; + case CSSValueWebkitIsolate: + return Isolate; + default: + ASSERT_NOT_REACHED(); + return UBNormal; } } @@ -2177,6 +2189,33 @@ template<> inline CSSPrimitiveValue::operator TextEmphasisMark() const } } +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextOrientation e) + : m_type(CSS_IDENT) + , m_hasCachedCSSText(false) +{ + switch (e) { + case TextOrientationVerticalRight: + m_value.ident = CSSValueVerticalRight; + break; + case TextOrientationUpright: + m_value.ident = CSSValueUpright; + break; + } +} + +template<> inline CSSPrimitiveValue::operator TextOrientation() const +{ + switch (m_value.ident) { + case CSSValueVerticalRight: + return TextOrientationVerticalRight; + case CSSValueUpright: + return TextOrientationUpright; + default: + ASSERT_NOT_REACHED(); + return TextOrientationVerticalRight; + } +} + template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EPointerEvents e) : m_type(CSS_IDENT) , m_hasCachedCSSText(false) diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in index b04c6d6..a62d2f3 100644 --- a/Source/WebCore/css/CSSPropertyNames.in +++ b/Source/WebCore/css/CSSPropertyNames.in @@ -21,6 +21,7 @@ font-variant font-weight text-rendering -webkit-font-smoothing +-webkit-text-orientation -webkit-text-size-adjust -webkit-writing-mode zoom @@ -227,10 +228,13 @@ z-index -webkit-font-size-delta -webkit-highlight -webkit-hyphenate-character --webkit-hyphenate-locale +-webkit-hyphenate-limit-after +-webkit-hyphenate-limit-before -webkit-hyphens +-webkit-line-box-contain -webkit-line-break -webkit-line-clamp +-webkit-locale -webkit-logical-width -webkit-logical-height -webkit-margin-after-collapse diff --git a/Source/WebCore/css/CSSRuleList.h b/Source/WebCore/css/CSSRuleList.h index a355c4a..87996a9 100644 --- a/Source/WebCore/css/CSSRuleList.h +++ b/Source/WebCore/css/CSSRuleList.h @@ -53,6 +53,11 @@ public: void deleteRule(unsigned index); void append(CSSRule*); + StyleList* styleList() + { + return m_list.get(); + } + private: CSSRuleList(); CSSRuleList(StyleList*, bool omitCharsetRules); diff --git a/Source/WebCore/css/CSSSelector.cpp b/Source/WebCore/css/CSSSelector.cpp index c804697..9cf8c99 100644 --- a/Source/WebCore/css/CSSSelector.cpp +++ b/Source/WebCore/css/CSSSelector.cpp @@ -27,6 +27,7 @@ #include "CSSSelector.h" #include "CSSOMUtils.h" +#include "CSSSelectorList.h" #include "HTMLNames.h" #include <wtf/Assertions.h> #include <wtf/HashMap.h> @@ -78,9 +79,12 @@ inline unsigned CSSSelector::specificityForOneSelector() const case Contain: case Begin: case End: - if (pseudoType() == PseudoNot && simpleSelector()) - s += simpleSelector()->specificityForOneSelector(); - else + // FIXME: PsuedoAny should base the specificity on the sub-selectors. + // See http://lists.w3.org/Archives/Public/www-style/2010Sep/0530.html + if (pseudoType() == PseudoNot) { + ASSERT(selectorList()); + s += selectorList()->first()->specificityForOneSelector(); + } else s += 0x100; case None: break; @@ -156,36 +160,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type) return INNER_SPIN_BUTTON; case PseudoOuterSpinButton: return OUTER_SPIN_BUTTON; -#if ENABLE(METER_TAG) - case PseudoMeterHorizontalBar: - return METER_HORIZONTAL_BAR; - case PseudoMeterHorizontalOptimum: - return METER_HORIZONTAL_OPTIMUM; - case PseudoMeterHorizontalSuboptimal: - return METER_HORIZONTAL_SUBOPTIMAL; - case PseudoMeterHorizontalEvenLessGood: - return METER_HORIZONTAL_EVEN_LESS_GOOD; - case PseudoMeterVerticalBar: - return METER_VERTICAL_BAR; - case PseudoMeterVerticalOptimum: - return METER_VERTICAL_OPTIMUM; - case PseudoMeterVerticalSuboptimal: - return METER_VERTICAL_SUBOPTIMAL; - case PseudoMeterVerticalEvenLessGood: - return METER_VERTICAL_EVEN_LESS_GOOD; -#else - case PseudoMeterHorizontalBar: - case PseudoMeterHorizontalOptimum: - case PseudoMeterHorizontalSuboptimal: - case PseudoMeterHorizontalEvenLessGood: - case PseudoMeterVerticalBar: - case PseudoMeterVerticalOptimum: - case PseudoMeterVerticalSuboptimal: - case PseudoMeterVerticalEvenLessGood: - ASSERT_NOT_REACHED(); - return NOPSEUDO; -#endif - #if ENABLE(FULLSCREEN_API) case PseudoFullScreen: return FULL_SCREEN; @@ -211,6 +185,7 @@ PseudoId CSSSelector::pseudoId(PseudoType type) case PseudoNthLastOfType: case PseudoLink: case PseudoVisited: + case PseudoAny: case PseudoAnyLink: case PseudoAutofill: case PseudoHover: @@ -265,6 +240,7 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( { DEFINE_STATIC_LOCAL(AtomicString, active, ("active")); DEFINE_STATIC_LOCAL(AtomicString, after, ("after")); + DEFINE_STATIC_LOCAL(AtomicString, any, ("-webkit-any(")); DEFINE_STATIC_LOCAL(AtomicString, anyLink, ("-webkit-any-link")); DEFINE_STATIC_LOCAL(AtomicString, autofill, ("-webkit-autofill")); DEFINE_STATIC_LOCAL(AtomicString, before, ("before")); @@ -309,17 +285,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( DEFINE_STATIC_LOCAL(AtomicString, onlyOfType, ("only-of-type")); DEFINE_STATIC_LOCAL(AtomicString, optional, ("optional")); DEFINE_STATIC_LOCAL(AtomicString, outerSpinButton, ("-webkit-outer-spin-button")); -#if ENABLE(METER_TAG) - DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalBar, ("-webkit-meter-horizontal-bar")); - DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalOptimumValue, ("-webkit-meter-horizontal-optimum-value")); - DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalSuboptimalValue, ("-webkit-meter-horizontal-suboptimal-value")); - DEFINE_STATIC_LOCAL(AtomicString, meterHorizontalEvenLessGoodValue, ("-webkit-meter-horizontal-even-less-good-value")); - DEFINE_STATIC_LOCAL(AtomicString, meterVerticalBar, ("-webkit-meter-vertical-bar")); - DEFINE_STATIC_LOCAL(AtomicString, meterVerticalOptimumValue, ("-webkit-meter-vertical-optimum-value")); - DEFINE_STATIC_LOCAL(AtomicString, meterVerticalSuboptimalValue, ("-webkit-meter-vertical-suboptimal-value")); - DEFINE_STATIC_LOCAL(AtomicString, meterVerticalEvenLessGoodValue, ("-webkit-meter-vertical-even-less-good-value")); -#endif - DEFINE_STATIC_LOCAL(AtomicString, required, ("required")); DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer")); DEFINE_STATIC_LOCAL(AtomicString, root, ("root")); @@ -364,6 +329,7 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( nameToPseudoType->set(active.impl(), CSSSelector::PseudoActive); nameToPseudoType->set(after.impl(), CSSSelector::PseudoAfter); nameToPseudoType->set(anyLink.impl(), CSSSelector::PseudoAnyLink); + nameToPseudoType->set(any.impl(), CSSSelector::PseudoAny); nameToPseudoType->set(autofill.impl(), CSSSelector::PseudoAutofill); nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore); nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked); @@ -406,16 +372,6 @@ static HashMap<AtomicStringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap( nameToPseudoType->set(nthLastChild.impl(), CSSSelector::PseudoNthLastChild); nameToPseudoType->set(nthLastOfType.impl(), CSSSelector::PseudoNthLastOfType); nameToPseudoType->set(outerSpinButton.impl(), CSSSelector::PseudoOuterSpinButton); -#if ENABLE(METER_TAG) - nameToPseudoType->set(meterHorizontalBar.impl(), CSSSelector::PseudoMeterHorizontalBar); - nameToPseudoType->set(meterHorizontalOptimumValue.impl(), CSSSelector::PseudoMeterHorizontalOptimum); - nameToPseudoType->set(meterHorizontalSuboptimalValue.impl(), CSSSelector::PseudoMeterHorizontalSuboptimal); - nameToPseudoType->set(meterHorizontalEvenLessGoodValue.impl(), CSSSelector::PseudoMeterHorizontalEvenLessGood); - nameToPseudoType->set(meterVerticalBar.impl(), CSSSelector::PseudoMeterVerticalBar); - nameToPseudoType->set(meterVerticalOptimumValue.impl(), CSSSelector::PseudoMeterVerticalOptimum); - nameToPseudoType->set(meterVerticalSuboptimalValue.impl(), CSSSelector::PseudoMeterVerticalSuboptimal); - nameToPseudoType->set(meterVerticalEvenLessGoodValue.impl(), CSSSelector::PseudoMeterVerticalEvenLessGood); -#endif nameToPseudoType->set(root.impl(), CSSSelector::PseudoRoot); nameToPseudoType->set(windowInactive.impl(), CSSSelector::PseudoWindowInactive); nameToPseudoType->set(decrement.impl(), CSSSelector::PseudoDecrement); @@ -490,15 +446,7 @@ void CSSSelector::extractPseudoType() const case PseudoInputSpeechButton: #endif case PseudoInnerSpinButton: - case PseudoMeterHorizontalBar: - case PseudoMeterHorizontalOptimum: - case PseudoMeterHorizontalSuboptimal: - case PseudoMeterHorizontalEvenLessGood: - case PseudoMeterVerticalBar: - case PseudoMeterVerticalOptimum: - case PseudoMeterVerticalSuboptimal: - case PseudoMeterVerticalEvenLessGood: - case PseudoOuterSpinButton: + case PseudoOuterSpinButton: case PseudoResizer: case PseudoScrollbar: case PseudoScrollbarCorner: @@ -527,6 +475,7 @@ void CSSSelector::extractPseudoType() const case PseudoNthLastOfType: case PseudoLink: case PseudoVisited: + case PseudoAny: case PseudoAnyLink: case PseudoAutofill: case PseudoHover: @@ -638,17 +587,33 @@ String CSSSelector::selectorText() const } else if (cs->m_match == CSSSelector::PseudoClass || cs->m_match == CSSSelector::PagePseudoClass) { str += ":"; str += cs->value(); - if (cs->pseudoType() == PseudoNot) { - if (CSSSelector* subSel = cs->simpleSelector()) - str += subSel->selectorText(); + + switch (cs->pseudoType()) { + case PseudoNot: + ASSERT(cs->selectorList()); + str += cs->selectorList()->first()->selectorText(); str += ")"; - } else if (cs->pseudoType() == PseudoLang - || cs->pseudoType() == PseudoNthChild - || cs->pseudoType() == PseudoNthLastChild - || cs->pseudoType() == PseudoNthOfType - || cs->pseudoType() == PseudoNthLastOfType) { + break; + case PseudoLang: + case PseudoNthChild: + case PseudoNthLastChild: + case PseudoNthOfType: + case PseudoNthLastOfType: str += cs->argument(); str += ")"; + break; + case PseudoAny: { + CSSSelector* firstSubSelector = cs->selectorList()->first(); + for (CSSSelector* subSelector = firstSubSelector; subSelector; subSelector = CSSSelectorList::next(subSelector)) { + if (subSelector != firstSubSelector) + str += ","; + str += subSelector->selectorText(); + } + str += ")"; + break; + } + default: + break; } } else if (cs->m_match == CSSSelector::PseudoElement) { str += "::"; @@ -736,11 +701,11 @@ void CSSSelector::setArgument(const AtomicString& value) createRareData(); m_data.m_rareData->m_argument = value; } - -void CSSSelector::setSimpleSelector(PassOwnPtr<CSSSelector> value) + +void CSSSelector::setSelectorList(PassOwnPtr<CSSSelectorList> selectorList) { createRareData(); - m_data.m_rareData->m_simpleSelector = value; + m_data.m_rareData->m_selectorList = selectorList; } bool CSSSelector::parseNth() @@ -761,7 +726,7 @@ bool CSSSelector::matchNth(int count) bool CSSSelector::isSimple() const { - if (simpleSelector() || tagHistory() || matchesPseudoElement()) + if (selectorList() || tagHistory() || matchesPseudoElement()) return false; int numConditions = 0; @@ -784,6 +749,21 @@ bool CSSSelector::isSimple() const return numConditions <= 1; } +CSSSelector::RareData::RareData(PassRefPtr<AtomicStringImpl> value) + : m_value(value.leakRef()) + , m_a(0) + , m_b(0) + , m_attribute(anyQName()) + , m_argument(nullAtom) +{ +} + +CSSSelector::RareData::~RareData() +{ + if (m_value) + m_value->deref(); +} + // a helper function for parsing nth-arguments bool CSSSelector::RareData::parseNth() { diff --git a/Source/WebCore/css/CSSSelector.h b/Source/WebCore/css/CSSSelector.h index ea161c3..43e6d80 100644 --- a/Source/WebCore/css/CSSSelector.h +++ b/Source/WebCore/css/CSSSelector.h @@ -29,6 +29,7 @@ #include <wtf/PassOwnPtr.h> namespace WebCore { + class CSSSelectorList; // this class represents a selector for a StyleRule class CSSSelector { @@ -43,6 +44,7 @@ namespace WebCore { , m_isLastInTagHistory(true) , m_hasRareData(false) , m_isForPage(false) + , m_deleted(false) , m_tag(anyQName()) { } @@ -56,12 +58,16 @@ namespace WebCore { , m_isLastInTagHistory(true) , m_hasRareData(false) , m_isForPage(false) + , m_deleted(false) , m_tag(qName) { } ~CSSSelector() { + if (m_deleted) + CRASH(); + m_deleted = true; if (m_hasRareData) delete m_data.m_rareData; else if (m_data.m_value) @@ -124,6 +130,7 @@ namespace WebCore { PseudoNthLastOfType, PseudoLink, PseudoVisited, + PseudoAny, PseudoAnyLink, PseudoAutofill, PseudoHover, @@ -175,14 +182,6 @@ namespace WebCore { PseudoSearchDecoration, PseudoSearchResultsDecoration, PseudoSearchResultsButton, - PseudoMeterHorizontalBar, - PseudoMeterVerticalBar, - PseudoMeterHorizontalOptimum, - PseudoMeterHorizontalSuboptimal, - PseudoMeterHorizontalEvenLessGood, - PseudoMeterVerticalOptimum, - PseudoMeterVerticalSuboptimal, - PseudoMeterVerticalEvenLessGood, PseudoInputListButton, #if ENABLE(INPUT_SPEECH) PseudoInputSpeechButton, @@ -242,13 +241,13 @@ namespace WebCore { const AtomicString& value() const { return *reinterpret_cast<const AtomicString*>(m_hasRareData ? &m_data.m_rareData->m_value : &m_data.m_value); } const QualifiedName& attribute() const; const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; } - CSSSelector* simpleSelector() const { return m_hasRareData ? m_data.m_rareData->m_simpleSelector.get() : 0; } + CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : 0; } void setTag(const QualifiedName& value) { m_tag = value; } void setValue(const AtomicString&); void setAttribute(const QualifiedName&); void setArgument(const AtomicString&); - void setSimpleSelector(PassOwnPtr<CSSSelector>); + void setSelectorList(PassOwnPtr<CSSSelectorList>); bool parseNth(); bool matchNth(int count); @@ -279,6 +278,8 @@ namespace WebCore { bool m_isLastInTagHistory : 1; bool m_hasRareData : 1; bool m_isForPage : 1; + // FIXME: Remove once http://webkit.org/b/56124 is fixed. + bool m_deleted : 1; unsigned specificityForOneSelector() const; unsigned specificityForPage() const; @@ -287,19 +288,8 @@ namespace WebCore { struct RareData { WTF_MAKE_NONCOPYABLE(RareData); WTF_MAKE_FAST_ALLOCATED; public: - RareData(PassRefPtr<AtomicStringImpl> value) - : m_value(value.leakRef()) - , m_a(0) - , m_b(0) - , m_attribute(anyQName()) - , m_argument(nullAtom) - { - } - ~RareData() - { - if (m_value) - m_value->deref(); - } + RareData(PassRefPtr<AtomicStringImpl> value); + ~RareData(); bool parseNth(); bool matchNth(int count); @@ -307,9 +297,9 @@ namespace WebCore { AtomicStringImpl* m_value; // Plain pointer to keep things uniform with the union. int m_a; // Used for :nth-* int m_b; // Used for :nth-* - OwnPtr<CSSSelector> m_simpleSelector; // Used for :not. QualifiedName m_attribute; // used for attribute selector AtomicString m_argument; // Used for :contains, :lang and :nth-* + OwnPtr<CSSSelectorList> m_selectorList; // Used for :-webkit-any and :not }; void createRareData(); diff --git a/Source/WebCore/css/CSSSelectorList.cpp b/Source/WebCore/css/CSSSelectorList.cpp index f4a8165..c0ffdd5 100644 --- a/Source/WebCore/css/CSSSelectorList.cpp +++ b/Source/WebCore/css/CSSSelectorList.cpp @@ -31,6 +31,8 @@ namespace WebCore { +static CSSSelector* const freedSelectorArrayMarker = reinterpret_cast<CSSSelector*>(0xbbadbeef); + CSSSelectorList::~CSSSelectorList() { deleteSelectors(); @@ -85,6 +87,10 @@ void CSSSelectorList::deleteSelectors() if (!m_selectorArray) return; + // FIXME: Remove once http://webkit.org/b/56124 is fixed. + if (m_selectorArray == freedSelectorArrayMarker) + CRASH(); + // We had two cases in adoptSelectVector. The fast case of a 1 element // vector took the CSSSelector directly, which was allocated with new. // The second case we allocated a new fastMalloc buffer, which should be @@ -103,6 +109,8 @@ void CSSSelectorList::deleteSelectors() } fastFree(m_selectorArray); } + + m_selectorArray = freedSelectorArrayMarker; } @@ -114,9 +122,11 @@ static bool forEachTagSelector(Functor& functor, CSSSelector* selector) do { if (functor(selector)) return true; - if (CSSSelector* simpleSelector = selector->simpleSelector()) { - if (forEachTagSelector(functor, simpleSelector)) - return true; + if (CSSSelectorList* selectorList = selector->selectorList()) { + for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + if (forEachTagSelector(functor, subSelector)) + return true; + } } } while ((selector = selector->tagHistory())); diff --git a/Source/WebCore/css/CSSStyleApplyProperty.cpp b/Source/WebCore/css/CSSStyleApplyProperty.cpp new file mode 100644 index 0000000..6051334 --- /dev/null +++ b/Source/WebCore/css/CSSStyleApplyProperty.cpp @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CSSStyleApplyProperty.h" + +#include "CSSPrimitiveValueMappings.h" +#include "CSSStyleSelector.h" +#include "CSSValueList.h" +#include "Document.h" +#include "Element.h" +#include "RenderStyle.h" +#include <wtf/StdLibExtras.h> +#include <wtf/UnusedParam.h> + +using namespace std; + +namespace WebCore { + +class ApplyPropertyExpanding : public ApplyPropertyBase { +public: + ApplyPropertyExpanding(ApplyPropertyBase* one = 0, ApplyPropertyBase* two = 0, ApplyPropertyBase *three = 0, ApplyPropertyBase* four = 0) + { + m_propertyMap[0] = one; + m_propertyMap[1] = two; + m_propertyMap[2] = three; + m_propertyMap[3] = four; + m_propertyMap[4] = 0; // always null terminated + } + + virtual void applyInheritValue(CSSStyleSelector* selector) const + { + for (ApplyPropertyBase* const* e = m_propertyMap; *e; e++) + (*e)->applyInheritValue(selector); + } + + virtual void applyInitialValue(CSSStyleSelector* selector) const + { + for (ApplyPropertyBase* const* e = m_propertyMap; *e; e++) + (*e)->applyInitialValue(selector); + } + + virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const + { + for (ApplyPropertyBase* const* e = m_propertyMap; *e; e++) + (*e)->applyValue(selector, value); + } +private: + ApplyPropertyBase* m_propertyMap[5]; +}; + +class ApplyPropertyExpandingSuppressValue : public ApplyPropertyExpanding { +public: + ApplyPropertyExpandingSuppressValue(ApplyPropertyBase* one = 0, ApplyPropertyBase* two = 0, ApplyPropertyBase *three = 0, ApplyPropertyBase* four = 0) + : ApplyPropertyExpanding(one, two, three, four) {} + + virtual void applyValue(CSSStyleSelector*, CSSValue*) const + { + ASSERT_NOT_REACHED(); + } +}; + +template <typename T> +class ApplyPropertyDefault : public ApplyPropertyBase { +public: + ApplyPropertyDefault(T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T), T (*initial)()) + : m_getter(getter) + , m_setter(setter) + , m_initial(initial) + { + } + + virtual void applyInheritValue(CSSStyleSelector* selector) const + { + (selector->style()->*m_setter)((selector->parentStyle()->*m_getter)()); + } + + virtual void applyInitialValue(CSSStyleSelector* selector) const + { + (selector->style()->*m_setter)((*m_initial)()); + } + + virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const + { + if (value->isPrimitiveValue()) + (selector->style()->*m_setter)(*(static_cast<CSSPrimitiveValue*>(value))); + } + +protected: + T (RenderStyle::*m_getter)() const; + void (RenderStyle::*m_setter)(T); + T (*m_initial)(); +}; + +// CSSPropertyColor +class ApplyPropertyColorBase : public ApplyPropertyBase { +public: + ApplyPropertyColorBase(const Color& (RenderStyle::*getter)() const, const Color& (RenderStyle::*defaultValue)() const, void (RenderStyle::*setter)(const Color&)) + : m_getter(getter) + , m_defaultValue(defaultValue) + , m_setter(setter) + { + } + virtual void applyInheritValue(CSSStyleSelector* selector) const + { + const Color& color = (selector->parentStyle()->*m_getter)(); + if (m_defaultValue && !color.isValid()) + (selector->style()->*m_setter)((selector->parentStyle()->*m_defaultValue)()); + else + (selector->style()->*m_setter)(color); + } + virtual void applyInitialValue(CSSStyleSelector* selector) const + { + Color color; + (selector->style()->*m_setter)(color); + } + virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const + { + if (value->isPrimitiveValue()) + (selector->style()->*m_setter)(selector->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValue*>(value))); + } +protected: + const Color& (RenderStyle::*m_getter)() const; + const Color& (RenderStyle::*m_defaultValue)() const; + void (RenderStyle::*m_setter)(const Color&); +}; + +class ApplyPropertyColor : public ApplyPropertyColorBase { +public: + ApplyPropertyColor(const Color& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), Color (*initialValue)()) + : ApplyPropertyColorBase(getter, 0, setter) + , m_initialValue(initialValue) + { + } + + virtual void applyInitialValue(CSSStyleSelector* selector) const + { + (selector->style()->*m_setter)(m_initialValue()); + } + + virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const + { + if (!value->isPrimitiveValue()) + return; + + if ((static_cast<CSSPrimitiveValue*>(value))->getIdent() == CSSValueCurrentcolor) + applyInheritValue(selector); + else + ApplyPropertyColorBase::applyValue(selector, value); + } +protected: + Color (*m_initialValue)(); +}; + +// CSSPropertyDirection +class ApplyPropertyDirection : public ApplyPropertyDefault<TextDirection> { +public: + ApplyPropertyDirection(TextDirection (RenderStyle::*getter)() const, void (RenderStyle::*setter)(TextDirection), TextDirection (*initial)()) + : ApplyPropertyDefault<TextDirection>(getter, setter, initial) + { + } + + virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const + { + ApplyPropertyDefault<TextDirection>::applyValue(selector, value); + Element* element = selector->element(); + if (element && selector->element() == element->document()->documentElement()) + element->document()->setDirectionSetOnDocumentElement(true); + } +}; + +template <typename T> +class ApplyPropertyFillLayer : public ApplyPropertyBase { +public: + ApplyPropertyFillLayer(CSSPropertyID propertyId, EFillLayerType fillLayerType, FillLayer* (RenderStyle::*accessLayers)(), + const FillLayer* (RenderStyle::*layers)() const, bool (FillLayer::*test)() const, T (FillLayer::*get)() const, + void (FillLayer::*set)(T), void (FillLayer::*clear)(), T (*initial)(EFillLayerType), + void (CSSStyleSelector::*mapFill)(CSSPropertyID, FillLayer*, CSSValue*)) + : m_propertyId(propertyId) + , m_fillLayerType(fillLayerType) + , m_accessLayers(accessLayers) + , m_layers(layers) + , m_test(test) + , m_get(get) + , m_set(set) + , m_clear(clear) + , m_initial(initial) + , m_mapFill(mapFill) + { + } + + virtual void applyInheritValue(CSSStyleSelector* selector) const + { + FillLayer* currChild = (selector->style()->*m_accessLayers)(); + FillLayer* prevChild = 0; + const FillLayer* currParent = (selector->parentStyle()->*m_layers)(); + while (currParent && (currParent->*m_test)()) { + if (!currChild) { + /* Need to make a new layer.*/ + currChild = new FillLayer(m_fillLayerType); + prevChild->setNext(currChild); + } + (currChild->*m_set)((currParent->*m_get)()); + prevChild = currChild; + currChild = prevChild->next(); + currParent = currParent->next(); + } + + while (currChild) { + /* Reset any remaining layers to not have the property set. */ + (currChild->*m_clear)(); + currChild = currChild->next(); + } + } + + virtual void applyInitialValue(CSSStyleSelector* selector) const + { + FillLayer* currChild = (selector->style()->*m_accessLayers)(); + (currChild->*m_set)((*m_initial)(m_fillLayerType)); + for (currChild = currChild->next(); currChild; currChild = currChild->next()) + (currChild->*m_clear)(); + } + + virtual void applyValue(CSSStyleSelector* selector, CSSValue* value) const + { + FillLayer* currChild = (selector->style()->*m_accessLayers)(); + FillLayer* prevChild = 0; + if (value->isValueList()) { + /* Walk each value and put it into a layer, creating new layers as needed. */ + CSSValueList* valueList = static_cast<CSSValueList*>(value); + for (unsigned int i = 0; i < valueList->length(); i++) { + if (!currChild) { + /* Need to make a new layer to hold this value */ + currChild = new FillLayer(m_fillLayerType); + prevChild->setNext(currChild); + } + (selector->*m_mapFill)(m_propertyId, currChild, valueList->itemWithoutBoundsCheck(i)); + prevChild = currChild; + currChild = currChild->next(); + } + } else { + (selector->*m_mapFill)(m_propertyId, currChild, value); + currChild = currChild->next(); + } + while (currChild) { + /* Reset all remaining layers to not have the property set. */ + (currChild->*m_clear)(); + currChild = currChild->next(); + } + } + +protected: + CSSPropertyID m_propertyId; + EFillLayerType m_fillLayerType; + FillLayer* (RenderStyle::*m_accessLayers)(); + const FillLayer* (RenderStyle::*m_layers)() const; + bool (FillLayer::*m_test)() const; + T (FillLayer::*m_get)() const; + void (FillLayer::*m_set)(T); + void (FillLayer::*m_clear)(); + T (*m_initial)(EFillLayerType); + void (CSSStyleSelector::*m_mapFill)(CSSPropertyID, FillLayer*, CSSValue*); +}; + +const CSSStyleApplyProperty& CSSStyleApplyProperty::sharedCSSStyleApplyProperty() +{ + DEFINE_STATIC_LOCAL(CSSStyleApplyProperty, cssStyleApplyPropertyInstance, ()); + return cssStyleApplyPropertyInstance; +} + +CSSStyleApplyProperty::CSSStyleApplyProperty() +{ + for (int i = 0; i < numCSSProperties; ++i) + m_propertyMap[i] = 0; + + setPropertyValue(CSSPropertyColor, new ApplyPropertyColor(&RenderStyle::color, &RenderStyle::setColor, RenderStyle::initialColor)); + setPropertyValue(CSSPropertyDirection, new ApplyPropertyDirection(&RenderStyle::direction, &RenderStyle::setDirection, RenderStyle::initialDirection)); + + setPropertyValue(CSSPropertyBackgroundAttachment, new ApplyPropertyFillLayer<EFillAttachment>(CSSPropertyBackgroundAttachment, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isAttachmentSet, &FillLayer::attachment, &FillLayer::setAttachment, &FillLayer::clearAttachment, &FillLayer::initialFillAttachment, &CSSStyleSelector::mapFillAttachment)); + setPropertyValue(CSSPropertyBackgroundClip, new ApplyPropertyFillLayer<EFillBox>(CSSPropertyBackgroundClip, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isClipSet, &FillLayer::clip, &FillLayer::setClip, &FillLayer::clearClip, &FillLayer::initialFillClip, &CSSStyleSelector::mapFillClip)); + setPropertyValue(CSSPropertyWebkitBackgroundClip, CSSPropertyBackgroundClip); + setPropertyValue(CSSPropertyWebkitBackgroundComposite, new ApplyPropertyFillLayer<CompositeOperator>(CSSPropertyWebkitBackgroundComposite, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isCompositeSet, &FillLayer::composite, &FillLayer::setComposite, &FillLayer::clearComposite, &FillLayer::initialFillComposite, &CSSStyleSelector::mapFillComposite)); + + setPropertyValue(CSSPropertyBackgroundImage, new ApplyPropertyFillLayer<StyleImage*>(CSSPropertyBackgroundImage, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isImageSet, &FillLayer::image, &FillLayer::setImage, &FillLayer::clearImage, &FillLayer::initialFillImage, &CSSStyleSelector::mapFillImage)); + + setPropertyValue(CSSPropertyBackgroundOrigin, new ApplyPropertyFillLayer<EFillBox>(CSSPropertyBackgroundOrigin, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isOriginSet, &FillLayer::origin, &FillLayer::setOrigin, &FillLayer::clearOrigin, &FillLayer::initialFillOrigin, &CSSStyleSelector::mapFillOrigin)); + setPropertyValue(CSSPropertyWebkitBackgroundOrigin, CSSPropertyBackgroundOrigin); + + setPropertyValue(CSSPropertyBackgroundPositionX, new ApplyPropertyFillLayer<Length>(CSSPropertyBackgroundPositionX, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isXPositionSet, &FillLayer::xPosition, &FillLayer::setXPosition, &FillLayer::clearXPosition, &FillLayer::initialFillXPosition, &CSSStyleSelector::mapFillXPosition)); + setPropertyValue(CSSPropertyBackgroundPositionY, new ApplyPropertyFillLayer<Length>(CSSPropertyBackgroundPositionY, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isYPositionSet, &FillLayer::yPosition, &FillLayer::setYPosition, &FillLayer::clearYPosition, &FillLayer::initialFillYPosition, &CSSStyleSelector::mapFillYPosition)); + setPropertyValue(CSSPropertyBackgroundPosition, new ApplyPropertyExpandingSuppressValue(propertyValue(CSSPropertyBackgroundPositionX), propertyValue(CSSPropertyBackgroundPositionY))); + + setPropertyValue(CSSPropertyBackgroundRepeatX, new ApplyPropertyFillLayer<EFillRepeat>(CSSPropertyBackgroundRepeatX, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isRepeatXSet, &FillLayer::repeatX, &FillLayer::setRepeatX, &FillLayer::clearRepeatX, &FillLayer::initialFillRepeatX, &CSSStyleSelector::mapFillRepeatX)); + setPropertyValue(CSSPropertyBackgroundRepeatY, new ApplyPropertyFillLayer<EFillRepeat>(CSSPropertyBackgroundRepeatY, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isRepeatYSet, &FillLayer::repeatY, &FillLayer::setRepeatY, &FillLayer::clearRepeatY, &FillLayer::initialFillRepeatY, &CSSStyleSelector::mapFillRepeatY)); + setPropertyValue(CSSPropertyBackgroundRepeat, new ApplyPropertyExpandingSuppressValue(propertyValue(CSSPropertyBackgroundRepeatX), propertyValue(CSSPropertyBackgroundRepeatY))); + + setPropertyValue(CSSPropertyBackgroundSize, new ApplyPropertyFillLayer<FillSize>(CSSPropertyBackgroundSize, BackgroundFillLayer, &RenderStyle::accessBackgroundLayers, &RenderStyle::backgroundLayers, + &FillLayer::isSizeSet, &FillLayer::size, &FillLayer::setSize, &FillLayer::clearSize, &FillLayer::initialFillSize, &CSSStyleSelector::mapFillSize)); + setPropertyValue(CSSPropertyWebkitBackgroundSize, CSSPropertyBackgroundSize); + + setPropertyValue(CSSPropertyWebkitMaskAttachment, new ApplyPropertyFillLayer<EFillAttachment>(CSSPropertyWebkitMaskAttachment, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isAttachmentSet, &FillLayer::attachment, &FillLayer::setAttachment, &FillLayer::clearAttachment, &FillLayer::initialFillAttachment, &CSSStyleSelector::mapFillAttachment)); + setPropertyValue(CSSPropertyWebkitMaskClip, new ApplyPropertyFillLayer<EFillBox>(CSSPropertyWebkitMaskClip, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isClipSet, &FillLayer::clip, &FillLayer::setClip, &FillLayer::clearClip, &FillLayer::initialFillClip, &CSSStyleSelector::mapFillClip)); + setPropertyValue(CSSPropertyWebkitMaskComposite, new ApplyPropertyFillLayer<CompositeOperator>(CSSPropertyWebkitMaskComposite, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isCompositeSet, &FillLayer::composite, &FillLayer::setComposite, &FillLayer::clearComposite, &FillLayer::initialFillComposite, &CSSStyleSelector::mapFillComposite)); + + setPropertyValue(CSSPropertyWebkitMaskImage, new ApplyPropertyFillLayer<StyleImage*>(CSSPropertyWebkitMaskImage, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isImageSet, &FillLayer::image, &FillLayer::setImage, &FillLayer::clearImage, &FillLayer::initialFillImage, &CSSStyleSelector::mapFillImage)); + + setPropertyValue(CSSPropertyWebkitMaskOrigin, new ApplyPropertyFillLayer<EFillBox>(CSSPropertyWebkitMaskOrigin, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isOriginSet, &FillLayer::origin, &FillLayer::setOrigin, &FillLayer::clearOrigin, &FillLayer::initialFillOrigin, &CSSStyleSelector::mapFillOrigin)); + setPropertyValue(CSSPropertyWebkitMaskSize, new ApplyPropertyFillLayer<FillSize>(CSSPropertyWebkitMaskSize, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isSizeSet, &FillLayer::size, &FillLayer::setSize, &FillLayer::clearSize, &FillLayer::initialFillSize, &CSSStyleSelector::mapFillSize)); + + setPropertyValue(CSSPropertyWebkitMaskPositionX, new ApplyPropertyFillLayer<Length>(CSSPropertyWebkitMaskPositionX, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isXPositionSet, &FillLayer::xPosition, &FillLayer::setXPosition, &FillLayer::clearXPosition, &FillLayer::initialFillXPosition, &CSSStyleSelector::mapFillXPosition)); + setPropertyValue(CSSPropertyWebkitMaskPositionY, new ApplyPropertyFillLayer<Length>(CSSPropertyWebkitMaskPositionY, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isYPositionSet, &FillLayer::yPosition, &FillLayer::setYPosition, &FillLayer::clearYPosition, &FillLayer::initialFillYPosition, &CSSStyleSelector::mapFillYPosition)); + setPropertyValue(CSSPropertyWebkitMaskPosition, new ApplyPropertyExpandingSuppressValue(propertyValue(CSSPropertyWebkitMaskPositionX), propertyValue(CSSPropertyWebkitMaskPositionY))); + + setPropertyValue(CSSPropertyWebkitMaskRepeatX, new ApplyPropertyFillLayer<EFillRepeat>(CSSPropertyWebkitMaskRepeatX, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isRepeatXSet, &FillLayer::repeatX, &FillLayer::setRepeatX, &FillLayer::clearRepeatX, &FillLayer::initialFillRepeatX, &CSSStyleSelector::mapFillRepeatX)); + setPropertyValue(CSSPropertyWebkitMaskRepeatY, new ApplyPropertyFillLayer<EFillRepeat>(CSSPropertyWebkitMaskRepeatY, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isRepeatYSet, &FillLayer::repeatY, &FillLayer::setRepeatY, &FillLayer::clearRepeatY, &FillLayer::initialFillRepeatY, &CSSStyleSelector::mapFillRepeatY)); + setPropertyValue(CSSPropertyWebkitMaskRepeat, new ApplyPropertyExpandingSuppressValue(propertyValue(CSSPropertyBackgroundRepeatX), propertyValue(CSSPropertyBackgroundRepeatY))); + + setPropertyValue(CSSPropertyWebkitMaskSize, new ApplyPropertyFillLayer<FillSize>(CSSPropertyWebkitMaskSize, MaskFillLayer, &RenderStyle::accessMaskLayers, &RenderStyle::maskLayers, + &FillLayer::isSizeSet, &FillLayer::size, &FillLayer::setSize, &FillLayer::clearSize, &FillLayer::initialFillSize, &CSSStyleSelector::mapFillSize)); + + setPropertyValue(CSSPropertyBackgroundColor, new ApplyPropertyColorBase(&RenderStyle::backgroundColor, 0, &RenderStyle::setBackgroundColor)); + setPropertyValue(CSSPropertyBorderBottomColor, new ApplyPropertyColorBase(&RenderStyle::borderBottomColor, &RenderStyle::color, &RenderStyle::setBorderBottomColor)); + setPropertyValue(CSSPropertyBorderLeftColor, new ApplyPropertyColorBase(&RenderStyle::borderLeftColor, &RenderStyle::color, &RenderStyle::setBorderLeftColor)); + setPropertyValue(CSSPropertyBorderRightColor, new ApplyPropertyColorBase(&RenderStyle::borderRightColor, &RenderStyle::color, &RenderStyle::setBorderRightColor)); + setPropertyValue(CSSPropertyBorderTopColor, new ApplyPropertyColorBase(&RenderStyle::borderTopColor, &RenderStyle::color, &RenderStyle::setBorderTopColor)); + + setPropertyValue(CSSPropertyBorderTopStyle, new ApplyPropertyDefault<EBorderStyle>(&RenderStyle::borderTopStyle, &RenderStyle::setBorderTopStyle, &RenderStyle::initialBorderStyle)); + setPropertyValue(CSSPropertyBorderRightStyle, new ApplyPropertyDefault<EBorderStyle>(&RenderStyle::borderRightStyle, &RenderStyle::setBorderRightStyle, &RenderStyle::initialBorderStyle)); + setPropertyValue(CSSPropertyBorderBottomStyle, new ApplyPropertyDefault<EBorderStyle>(&RenderStyle::borderBottomStyle, &RenderStyle::setBorderBottomStyle, &RenderStyle::initialBorderStyle)); + setPropertyValue(CSSPropertyBorderLeftStyle, new ApplyPropertyDefault<EBorderStyle>(&RenderStyle::borderLeftStyle, &RenderStyle::setBorderLeftStyle, &RenderStyle::initialBorderStyle)); + + setPropertyValue(CSSPropertyOutlineColor, new ApplyPropertyColorBase(&RenderStyle::outlineColor, &RenderStyle::color, &RenderStyle::setOutlineColor)); + + setPropertyValue(CSSPropertyOverflowX, new ApplyPropertyDefault<EOverflow>(&RenderStyle::overflowX, &RenderStyle::setOverflowX, &RenderStyle::initialOverflowX)); + setPropertyValue(CSSPropertyOverflowY, new ApplyPropertyDefault<EOverflow>(&RenderStyle::overflowY, &RenderStyle::setOverflowY, &RenderStyle::initialOverflowY)); + setPropertyValue(CSSPropertyOverflow, new ApplyPropertyExpanding(propertyValue(CSSPropertyOverflowX), propertyValue(CSSPropertyOverflowY))); + + setPropertyValue(CSSPropertyWebkitColumnRuleColor, new ApplyPropertyColorBase(&RenderStyle::columnRuleColor, &RenderStyle::color, &RenderStyle::setColumnRuleColor)); + setPropertyValue(CSSPropertyWebkitTextEmphasisColor, new ApplyPropertyColorBase(&RenderStyle::textEmphasisColor, &RenderStyle::color, &RenderStyle::setTextEmphasisColor)); + setPropertyValue(CSSPropertyWebkitTextFillColor, new ApplyPropertyColorBase(&RenderStyle::textFillColor, &RenderStyle::color, &RenderStyle::setTextFillColor)); + setPropertyValue(CSSPropertyWebkitTextStrokeColor, new ApplyPropertyColorBase(&RenderStyle::textStrokeColor, &RenderStyle::color, &RenderStyle::setTextStrokeColor)); +} + + +} diff --git a/Source/WebCore/css/CSSStyleApplyProperty.h b/Source/WebCore/css/CSSStyleApplyProperty.h new file mode 100644 index 0000000..860a4f8 --- /dev/null +++ b/Source/WebCore/css/CSSStyleApplyProperty.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CSSStyleApplyProperty_h +#define CSSStyleApplyProperty_h + +#include "CSSPropertyNames.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class CSSStyleSelector; +class CSSValue; +class ApplyPropertyBase { + WTF_MAKE_NONCOPYABLE(ApplyPropertyBase); + WTF_MAKE_FAST_ALLOCATED; +public: + ApplyPropertyBase() { } + virtual ~ApplyPropertyBase() { } + virtual void applyInheritValue(CSSStyleSelector*) const = 0; + virtual void applyInitialValue(CSSStyleSelector*) const = 0; + virtual void applyValue(CSSStyleSelector*, CSSValue*) const = 0; +}; + +class CSSStyleApplyProperty { + WTF_MAKE_NONCOPYABLE(CSSStyleApplyProperty); +public: + static const CSSStyleApplyProperty& sharedCSSStyleApplyProperty(); + + void applyInheritValue(CSSPropertyID property, CSSStyleSelector* selector) const + { + ASSERT(implements(property)); + propertyValue(property)->applyInheritValue(selector); + } + + void applyInitialValue(CSSPropertyID property, CSSStyleSelector* selector) const + { + ASSERT(implements(property)); + propertyValue(property)->applyInitialValue(selector); + } + + void applyValue(CSSPropertyID property, CSSStyleSelector* selector, CSSValue* value) const + { + ASSERT(implements(property)); + propertyValue(property)->applyValue(selector, value); + } + + bool implements(CSSPropertyID property) const + { + return propertyValue(property); + } + +private: + CSSStyleApplyProperty(); + static int index(CSSPropertyID property) + { + return property - firstCSSProperty; + } + + static bool valid(CSSPropertyID property) + { + int i = index(property); + return i >= 0 && i < numCSSProperties; + } + + void setPropertyValue(CSSPropertyID property, ApplyPropertyBase* value) + { + ASSERT(valid(property)); + m_propertyMap[index(property)] = value; + } + + void setPropertyValue(CSSPropertyID newProperty, CSSPropertyID equivalentProperty) + { + ASSERT(valid(newProperty)); + ASSERT(valid(equivalentProperty)); + m_propertyMap[index(newProperty)] = m_propertyMap[index(equivalentProperty)]; + } + + ApplyPropertyBase* propertyValue(CSSPropertyID property) const + { + ASSERT(valid(property)); + return m_propertyMap[index(property)]; + } + + ApplyPropertyBase* m_propertyMap[numCSSProperties]; +}; + +} + +#endif // CSSStyleApplyProperty_h diff --git a/Source/WebCore/css/CSSStyleDeclaration.cpp b/Source/WebCore/css/CSSStyleDeclaration.cpp index 422dd0d..67dc6e0 100644 --- a/Source/WebCore/css/CSSStyleDeclaration.cpp +++ b/Source/WebCore/css/CSSStyleDeclaration.cpp @@ -22,10 +22,13 @@ #include "CSSStyleDeclaration.h" #include "CSSMutableStyleDeclaration.h" +#include "CSSMutableValue.h" #include "CSSParser.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSRule.h" +#include "Node.h" +#include "SVGElement.h" #include <wtf/ASCIICType.h> using namespace WTF; @@ -42,7 +45,28 @@ PassRefPtr<CSSValue> CSSStyleDeclaration::getPropertyCSSValue(const String& prop int propID = cssPropertyID(propertyName); if (!propID) return 0; - return getPropertyCSSValue(propID); + + // Short-cut, not involving any change to the refcount. + if (!isMutableStyleDeclaration()) + return getPropertyCSSValue(propID); + + // Slow path. + RefPtr<CSSValue> value = getPropertyCSSValue(propID); + if (!value || !value->isMutableValue()) + return value.release(); + + Node* node = static_cast<CSSMutableStyleDeclaration*>(this)->node(); + if (!node || !node->isStyledElement()) + return value.release(); + + Node* associatedNode = static_cast<CSSMutableValue*>(value.get())->node(); + if (associatedNode) { + ASSERT(associatedNode == node); + return value.release(); + } + + static_cast<CSSMutableValue*>(value.get())->setNode(node); + return value.release(); } String CSSStyleDeclaration::getPropertyValue(const String &propertyName) @@ -83,10 +107,13 @@ bool CSSStyleDeclaration::isPropertyImplicit(const String& propertyName) void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, ExceptionCode& ec) { size_t important = value.find("!important", 0, false); + int propertyID = cssPropertyID(propertyName); + if (!propertyID) + return; if (important == notFound) - setProperty(propertyName, value, "", ec); + setProperty(propertyID, value, false, ec); else - setProperty(propertyName, value.left(important - 1), "important", ec); + setProperty(propertyID, value.left(important - 1), true, ec); } void CSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode& ec) diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp index 5ff5066..b79f2dc 100644 --- a/Source/WebCore/css/CSSStyleSelector.cpp +++ b/Source/WebCore/css/CSSStyleSelector.cpp @@ -6,6 +6,7 @@ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (c) 2011, Code Aurora Forum. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -34,6 +35,7 @@ #include "CSSCursorImageValue.h" #include "CSSFontFaceRule.h" #include "CSSImportRule.h" +#include "CSSLineBoxContainValue.h" #include "CSSMediaRule.h" #include "CSSPageRule.h" #include "CSSParser.h" @@ -43,6 +45,7 @@ #include "CSSRuleList.h" #include "CSSSelector.h" #include "CSSSelectorList.h" +#include "CSSStyleApplyProperty.h" #include "CSSStyleRule.h" #include "CSSStyleSheet.h" #include "CSSTimingFunctionValue.h" @@ -70,6 +73,7 @@ #include "PageGroup.h" #include "Pair.h" #include "PerspectiveTransformOperation.h" +#include "QuotesData.h" #include "Rect.h" #include "RenderScrollbar.h" #include "RenderScrollbarTheme.h" @@ -155,76 +159,6 @@ HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ if (primitiveValue) \ m_style->set##Prop(*primitiveValue); -#define HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \ -if (isInherit) { \ - FillLayer* currChild = m_style->access##LayerType##Layers(); \ - FillLayer* prevChild = 0; \ - const FillLayer* currParent = m_parentStyle->layerType##Layers(); \ - while (currParent && currParent->is##Prop##Set()) { \ - if (!currChild) { \ - /* Need to make a new layer.*/ \ - currChild = new FillLayer(LayerType##FillLayer); \ - prevChild->setNext(currChild); \ - } \ - currChild->set##Prop(currParent->prop()); \ - prevChild = currChild; \ - currChild = prevChild->next(); \ - currParent = currParent->next(); \ - } \ - \ - while (currChild) { \ - /* Reset any remaining layers to not have the property set. */ \ - currChild->clear##Prop(); \ - currChild = currChild->next(); \ - } \ -} else if (isInitial) { \ - FillLayer* currChild = m_style->access##LayerType##Layers(); \ - currChild->set##Prop(FillLayer::initialFill##Prop(LayerType##FillLayer)); \ - for (currChild = currChild->next(); currChild; currChild = currChild->next()) \ - currChild->clear##Prop(); \ -} - -#define HANDLE_FILL_LAYER_VALUE(layerType, LayerType, prop, Prop, value) { \ -HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \ -if (isInherit || isInitial) \ - return; \ -FillLayer* currChild = m_style->access##LayerType##Layers(); \ -FillLayer* prevChild = 0; \ -if (value->isValueList()) { \ - /* Walk each value and put it into a layer, creating new layers as needed. */ \ - CSSValueList* valueList = static_cast<CSSValueList*>(value); \ - for (unsigned int i = 0; i < valueList->length(); i++) { \ - if (!currChild) { \ - /* Need to make a new layer to hold this value */ \ - currChild = new FillLayer(LayerType##FillLayer); \ - prevChild->setNext(currChild); \ - } \ - mapFill##Prop(property, currChild, valueList->itemWithoutBoundsCheck(i)); \ - prevChild = currChild; \ - currChild = currChild->next(); \ - } \ -} else { \ - mapFill##Prop(property, currChild, value); \ - currChild = currChild->next(); \ -} \ -while (currChild) { \ - /* Reset all remaining layers to not have the property set. */ \ - currChild->clear##Prop(); \ - currChild = currChild->next(); \ -} } - -#define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ -HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(background, Background, prop, Prop) - -#define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \ -HANDLE_FILL_LAYER_VALUE(background, Background, prop, Prop, value) - -#define HANDLE_MASK_INHERIT_AND_INITIAL(prop, Prop) \ -HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(mask, Mask, prop, Prop) - -#define HANDLE_MASK_VALUE(prop, Prop, value) \ -HANDLE_FILL_LAYER_VALUE(mask, Mask, prop, Prop, value) - #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \ if (isInherit) { \ AnimationList* list = m_style->accessAnimations(); \ @@ -363,6 +297,7 @@ public: bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; } bool hasMultipartSelector() const { return m_hasMultipartSelector; } bool hasTopSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasTopSelectorMatchingHTMLBasedOnRuleHash; } + unsigned specificity() const { return m_specificity; } // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance. static const unsigned maximumIdentifierCount = 4; @@ -374,6 +309,7 @@ private: CSSStyleRule* m_rule; CSSSelector* m_selector; + unsigned m_specificity; unsigned m_position : 29; bool m_hasFastCheckableSelector : 1; bool m_hasMultipartSelector : 1; @@ -399,8 +335,8 @@ public: CSSStyleRule* rule, CSSSelector* sel); void shrinkToFit(); void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; } - - void collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<RuleSet>& siblingRules) const; + + void collectFeatures(CSSStyleSelector::Features&) const; const Vector<RuleData>* getIDRules(AtomicStringImpl* key) const { return m_idRules.get(key); } const Vector<RuleData>* getClassRules(AtomicStringImpl* key) const { return m_classRules.get(key); } @@ -431,26 +367,22 @@ static RuleSet* siblingRulesInDefaultStyle; RenderStyle* CSSStyleSelector::s_styleNotYetAvailable; static void loadFullDefaultStyle(); -#if ENABLE(FULLSCREEN_API) -static void loadFullScreenRulesIfNeeded(Document*); -#endif static void loadSimpleDefaultStyle(); // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet. -static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}"; +static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}"; static inline bool elementCanUseSimpleDefaultStyle(Element* e) { - return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag); + return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag); } static inline void collectSiblingRulesInDefaultStyle() { - OwnPtr<RuleSet> siblingRules; - HashSet<AtomicStringImpl*> ids; - defaultStyle->collectIdsAndSiblingRules(ids, siblingRules); - ASSERT(ids.isEmpty()); + CSSStyleSelector::Features features; + defaultStyle->collectFeatures(features); + ASSERT(features.idsInRules.isEmpty()); delete siblingRulesInDefaultStyle; - siblingRulesInDefaultStyle = siblingRules.leakPtr(); + siblingRulesInDefaultStyle = features.siblingRules.leakPtr(); } static inline void assertNoSiblingRulesInDefaultStyle() @@ -475,6 +407,26 @@ static const MediaQueryEvaluator& printEval() return staticPrintEval; } +static CSSMutableStyleDeclaration* leftToRightDeclaration() +{ + DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create())); + if (!leftToRightDecl->length()) { + leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false, false); + leftToRightDecl->setStrictParsing(false); + } + return leftToRightDecl.get(); +} + +static CSSMutableStyleDeclaration* rightToLeftDeclaration() +{ + DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create())); + if (!rightToLeftDecl->length()) { + rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false, false); + rightToLeftDecl->setStrictParsing(false); + } + return rightToLeftDecl.get(); +} + CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet, CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, bool strictParsing, bool matchAuthorAndUserStyles) @@ -484,6 +436,7 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee , m_styledElement(0) , m_elementLinkState(NotInsideLink) , m_fontSelector(CSSFontSelector::create(document)) + , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty()) { m_matchAuthorAndUserStyles = matchAuthorAndUserStyles; @@ -494,9 +447,6 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee loadSimpleDefaultStyle(); else { loadFullDefaultStyle(); -#if ENABLE(FULLSCREEN_API) - loadFullScreenRulesIfNeeded(document); -#endif } } @@ -555,14 +505,14 @@ CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleShee // sharing candidates. // Usually there are no sibling rules in the default style but the MathML sheet has some. if (siblingRulesInDefaultStyle) - siblingRulesInDefaultStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules); - m_authorStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules); + siblingRulesInDefaultStyle->collectFeatures(m_features); + m_authorStyle->collectFeatures(m_features); if (m_userStyle) - m_userStyle->collectIdsAndSiblingRules(m_idsInRules, m_siblingRules); + m_userStyle->collectFeatures(m_features); m_authorStyle->shrinkToFit(); - if (m_siblingRules) - m_siblingRules->shrinkToFit(); + if (m_features.siblingRules) + m_features.siblingRules->shrinkToFit(); if (document->renderer() && document->renderer()->style()) document->renderer()->style()->font().update(fontSelector()); @@ -580,6 +530,17 @@ CSSStyleSelector::~CSSStyleSelector() m_fontSelector->clearDocument(); deleteAllValues(m_viewportDependentMediaQueryResults); } + +CSSStyleSelector::Features::Features() + : usesFirstLineRules(false) + , usesBeforeAfterRules(false) + , usesLinkRules(false) +{ +} + +CSSStyleSelector::Features::~Features() +{ +} static CSSStyleSheet* parseUASheet(const String& str) { @@ -620,19 +581,6 @@ static void loadFullDefaultStyle() defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval()); } -#if ENABLE(FULLSCREEN_API) -static void loadFullScreenRulesIfNeeded(Document* document) -{ - if (!document->webkitIsFullScreen()) - return; - // Full-screen rules. - String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet(); - CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules); - defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval()); - defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval()); -} -#endif - static void loadSimpleDefaultStyle() { ASSERT(!defaultStyle); @@ -772,7 +720,7 @@ void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& last return; // Sort the set of matched rules. - sortMatchedRules(0, m_matchedRules.size()); + sortMatchedRules(); // Now transfer the set of matched rules over to our list of decls. if (!m_checker.m_collectRulesOnly) { @@ -839,80 +787,16 @@ void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& fir } } -static bool operator >(const RuleData& r1, const RuleData& r2) -{ - int spec1 = r1.selector()->specificity(); - int spec2 = r2.selector()->specificity(); - return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; -} - -static bool operator <=(const RuleData& r1, const RuleData& r2) +static inline bool compareRules(const RuleData* r1, const RuleData* r2) { - return !(r1 > r2); + unsigned specificity1 = r1->specificity(); + unsigned specificity2 = r2->specificity(); + return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2; } -void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end) +void CSSStyleSelector::sortMatchedRules() { - if (start >= end || (end - start == 1)) - return; // Sanity check. - - if (end - start <= 6) { - // Apply a bubble sort for smaller lists. - for (unsigned i = end - 1; i > start; i--) { - bool sorted = true; - for (unsigned j = start; j < i; j++) { - const RuleData* elt = m_matchedRules[j]; - const RuleData* elt2 = m_matchedRules[j + 1]; - if (*elt > *elt2) { - sorted = false; - m_matchedRules[j] = elt2; - m_matchedRules[j + 1] = elt; - } - } - if (sorted) - return; - } - return; - } - - // Perform a merge sort for larger lists. - unsigned mid = (start + end) / 2; - sortMatchedRules(start, mid); - sortMatchedRules(mid, end); - - const RuleData* elt = m_matchedRules[mid - 1]; - const RuleData* elt2 = m_matchedRules[mid]; - - // Handle the fast common case (of equal specificity). The list may already - // be completely sorted. - if (*elt <= *elt2) - return; - - // We have to merge sort. Ensure our merge buffer is big enough to hold - // all the items. - Vector<const RuleData*> rulesMergeBuffer; - rulesMergeBuffer.reserveInitialCapacity(end - start); - - unsigned i1 = start; - unsigned i2 = mid; - - elt = m_matchedRules[i1]; - elt2 = m_matchedRules[i2]; - - while (i1 < mid || i2 < end) { - if (i1 < mid && (i2 == end || *elt <= *elt2)) { - rulesMergeBuffer.append(elt); - if (++i1 < mid) - elt = m_matchedRules[i1]; - } else { - rulesMergeBuffer.append(elt2); - if (++i2 < end) - elt2 = m_matchedRules[i2]; - } - } - - for (unsigned i = start; i < end; i++) - m_matchedRules[i] = rulesMergeBuffer[i - start]; + std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules); } inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const @@ -939,7 +823,7 @@ inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* paren { m_checker.m_pseudoStyle = pseudoID; - m_parentNode = e ? e->parentOrHostNode() : 0; + m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0; if (parentStyle) m_parentStyle = parentStyle; @@ -1054,142 +938,173 @@ bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* } static const unsigned cStyleSearchThreshold = 10; +static const unsigned cStyleSearchLevelThreshold = 10; -Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth) const +Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const { + if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold) + return 0; if (!parent || !parent->isStyledElement()) return 0; StyledElement* p = static_cast<StyledElement*>(parent); if (p->inlineStyleDecl()) return 0; - if (p->hasID() && m_idsInRules.contains(p->idForStyleResolution().impl())) + if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl())) return 0; - Node* r = p->previousSibling(); + + RenderStyle* parentStyle = p->renderStyle(); unsigned subcount = 0; - RenderStyle* st = p->renderStyle(); - while (r) { - if (r->renderStyle() == st) - return r->lastChild(); - if (subcount++ == cStyleSearchThreshold) - return 0; - r = r->previousSibling(); - } - if (!r && depth < cStyleSearchThreshold) - r = locateCousinList(parent->parentElement(), depth + 1); - while (r) { - if (r->renderStyle() == st) - return r->lastChild(); - if (subcount++ == cStyleSearchThreshold) - return 0; - r = r->previousSibling(); + Node* thisCousin = p; + Node* currentNode = p->previousSibling(); + + // Reserve the tries for this level. This effectively makes sure that the algorithm + // will never go deeper than cStyleSearchLevelThreshold levels into recursion. + visitedNodeCount += cStyleSearchThreshold; + while (thisCousin) { + while (currentNode) { + ++subcount; + if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) { + // Adjust for unused reserved tries. + visitedNodeCount -= cStyleSearchThreshold - subcount; + return currentNode->lastChild(); + } + if (subcount >= cStyleSearchThreshold) + return 0; + currentNode = currentNode->previousSibling(); + } + currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount); + thisCousin = currentNode; } + return 0; } bool CSSStyleSelector::matchesSiblingRules() { int firstSiblingRule = -1, lastSiblingRule = -1; - matchRules(m_siblingRules.get(), firstSiblingRule, lastSiblingRule, false); + matchRules(m_features.siblingRules.get(), firstSiblingRule, lastSiblingRule, false); if (m_matchedDecls.isEmpty()) return false; m_matchedDecls.clear(); return true; } -bool CSSStyleSelector::canShareStyleWithElement(Node* n) const -{ - if (n->isStyledElement()) { - StyledElement* s = static_cast<StyledElement*>(n); - RenderStyle* style = s->renderStyle(); - if (style && !style->unique() && - (s->tagQName() == m_element->tagQName()) && - (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() && - (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) && - (s->isLink() == m_element->isLink()) && - !style->affectedByAttributeSelectors() && - (s->hovered() == m_element->hovered()) && - (s->active() == m_element->active()) && - (s->focused() == m_element->focused()) && - (s->shadowPseudoId() == m_element->shadowPseudoId()) && - (s != s->document()->cssTarget() && m_element != m_element->document()->cssTarget()) && - (s->fastGetAttribute(typeAttr) == m_element->fastGetAttribute(typeAttr)) && - (s->fastGetAttribute(XMLNames::langAttr) == m_element->fastGetAttribute(XMLNames::langAttr)) && - (s->fastGetAttribute(langAttr) == m_element->fastGetAttribute(langAttr)) && - (s->fastGetAttribute(readonlyAttr) == m_element->fastGetAttribute(readonlyAttr)) && - (s->fastGetAttribute(cellpaddingAttr) == m_element->fastGetAttribute(cellpaddingAttr))) { - - if (s->hasID() && m_idsInRules.contains(s->idForStyleResolution().impl())) - return 0; - - bool isControl = s->isFormControlElement(); - if (isControl != m_element->isFormControlElement()) - return false; - if (isControl) { - InputElement* thisInputElement = toInputElement(s); - InputElement* otherInputElement = toInputElement(m_element); - if (thisInputElement && otherInputElement) { - if ((thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) || - (thisInputElement->isChecked() != otherInputElement->isChecked()) || - (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())) - return false; - } else - return false; +bool CSSStyleSelector::canShareStyleWithElement(Node* node) const +{ + if (!node->isStyledElement()) + return false; - if (s->isEnabledFormControl() != m_element->isEnabledFormControl()) - return false; + StyledElement* element = static_cast<StyledElement*>(node); + RenderStyle* style = element->renderStyle(); - if (s->isDefaultButtonForForm() != m_element->isDefaultButtonForForm()) - return false; - - if (!m_element->document()->containsValidityStyleRules()) - return false; - - bool willValidate = s->willValidate(); - if (willValidate != m_element->willValidate()) - return false; - - if (willValidate && (s->isValidFormControlElement() != m_element->isValidFormControlElement())) - return false; + if (!style) + return false; + if (style->unique()) + return false; + if (element->tagQName() != m_element->tagQName()) + return false; + if (element->hasClass() != m_element->hasClass()) + return false; + if (element->inlineStyleDecl()) + return false; + if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes()) + return false; + if (element->isLink() != m_element->isLink()) + return false; + if (style->affectedByAttributeSelectors()) + return false; + if (element->hovered() != m_element->hovered()) + return false; + if (element->active() != m_element->active()) + return false; + if (element->focused() != m_element->focused()) + return false; + if (element->shadowPseudoId() != m_element->shadowPseudoId()) + return false; + if (element == element->document()->cssTarget()) + return false; + if (m_element == m_element->document()->cssTarget()) + return false; + if (element->fastGetAttribute(typeAttr) != m_element->fastGetAttribute(typeAttr)) + return false; + if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr)) + return false; + if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr)) + return false; + if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr)) + return false; + if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr)) + return false; - if (s->isInRange() != m_element->isInRange()) - return false; + if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl())) + return false; - if (s->isOutOfRange() != m_element->isOutOfRange()) - return false; - } + bool isControl = element->isFormControlElement(); - if (style->transitions() || style->animations()) - return false; + if (isControl != m_element->isFormControlElement()) + return false; + + if (isControl) { + InputElement* thisInputElement = element->toInputElement(); + InputElement* otherInputElement = m_element->toInputElement(); + + if (!thisInputElement || !otherInputElement) + return false; + + if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) + return false; + if (thisInputElement->isChecked() != otherInputElement->isChecked()) + return false; + if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate()) + return false; + + if (element->isEnabledFormControl() != m_element->isEnabledFormControl()) + return false; + + if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm()) + return false; + + if (!m_element->document()->containsValidityStyleRules()) + return false; + + bool willValidate = element->willValidate(); + + if (willValidate != m_element->willValidate()) + return false; + + if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement())) + return false; + + if (element->isInRange() != m_element->isInRange()) + return false; + + if (element->isOutOfRange() != m_element->isOutOfRange()) + return false; + } + + if (style->transitions() || style->animations()) + return false; #if USE(ACCELERATED_COMPOSITING) - // Turn off style sharing for elements that can gain layers for reasons outside of the style system. - // See comments in RenderObject::setStyle(). - if (s->hasTagName(iframeTag) || s->hasTagName(embedTag) || s->hasTagName(objectTag) || s->hasTagName(appletTag)) - return false; + // Turn off style sharing for elements that can gain layers for reasons outside of the style system. + // See comments in RenderObject::setStyle(). + if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)) + return false; #endif - bool classesMatch = true; - if (s->hasClass()) { - const AtomicString& class1 = m_element->fastGetAttribute(classAttr); - const AtomicString& class2 = s->fastGetAttribute(classAttr); - classesMatch = (class1 == class2); - } - - if (classesMatch) { - bool mappedAttrsMatch = true; - if (s->hasMappedAttributes()) - mappedAttrsMatch = s->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()); - if (mappedAttrsMatch) { - if (s->isLink()) { - if (m_elementLinkState != style->insideLink()) - return false; - } - return true; - } - } - } - } - return false; + if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto")) + return false; + + if (element->hasClass() && m_element->fastGetAttribute(classAttr) != element->fastGetAttribute(classAttr)) + return false; + + if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap())) + return false; + + if (element->isLink() && m_elementLinkState != style->insideLink()) + return false; + + return true; } inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const @@ -1221,19 +1136,27 @@ ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle() if (m_styledElement->inlineStyleDecl()) return 0; // Ids stop style sharing if they show up in the stylesheets. - if (m_styledElement->hasID() && m_idsInRules.contains(m_styledElement->idForStyleResolution().impl())) + if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl())) return 0; if (parentStylePreventsSharing(m_parentStyle)) return 0; - // Check previous siblings. + + // Check previous siblings and their cousins. unsigned count = 0; - Node* shareNode = findSiblingForStyleSharing(m_styledElement->previousSibling(), count); - if (!shareNode) { - Node* cousinList = locateCousinList(m_styledElement->parentElement()); - shareNode = findSiblingForStyleSharing(cousinList, count); - if (!shareNode) - return 0; + unsigned visitedNodeCount = 0; + Node* shareNode = 0; + Node* cousinList = m_styledElement->previousSibling(); + while (cousinList) { + shareNode = findSiblingForStyleSharing(cousinList, count); + if (shareNode) + break; + cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount); } + + // If we have exhausted all our budget or our cousins. + if (!shareNode) + return 0; + // Can't share if sibling rules apply. This is checked at the end as it should rarely fail. if (matchesSiblingRules()) return 0; @@ -1254,8 +1177,8 @@ void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule) if (!m_checker.m_strictParsing) matchRules(defaultQuirksStyle, firstUARule, lastUARule, false); - // If we're in view source mode, then we match rules from the view source style sheet. - if (m_checker.m_document->frame() && m_checker.m_document->frame()->inViewSourceMode()) { + // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet. + if (m_checker.m_document->usesViewSourceStyles()) { if (!defaultViewSourceStyle) loadViewSourceStyle(); matchRules(defaultViewSourceStyle, firstUARule, lastUARule, false); @@ -1352,12 +1275,6 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl parentStyle = parentVisitedStyle; } visitedStyle = styleForElement(e, parentStyle, false, false, true); - if (visitedStyle) { - if (m_elementLinkState == InsideUnvisitedLink) - visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it. - else - visitedStyle->setStyleType(VISITED_LINK); - } initForStyleResolve(e, defaultParent); } @@ -1375,11 +1292,22 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl m_style->setInsideLink(m_elementLinkState); } + if (visitedStyle) { + // Copy any pseudo bits that the visited style has to the primary style so that + // pseudo element styles will continue to work for pseudo elements inside :visited + // links. + for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) { + if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo))) + m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo)); + } + if (m_elementLinkState == InsideUnvisitedLink) + visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it. + else + visitedStyle->setStyleType(VISITED_LINK); + } + if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e)) { loadFullDefaultStyle(); -#if ENABLE(FULLSCREEN_API) - loadFullScreenRulesIfNeeded(e->document()); -#endif assertNoSiblingRulesInDefaultStyle(); } @@ -1432,6 +1360,17 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl } #endif +#if ENABLE(FULLSCREEN_API) + static bool loadedFullScreenStyleSheet; + if (!loadedFullScreenStyleSheet && e->document()->webkitIsFullScreen()) { + loadedFullScreenStyleSheet = true; + String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet(); + CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules); + defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval()); + defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval()); + } +#endif + int firstUARule = -1, lastUARule = -1; int firstUserRule = -1, lastUserRule = -1; int firstAuthorRule = -1, lastAuthorRule = -1; @@ -1475,6 +1414,12 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl addMatchedDeclaration(m_additionalAttributeStyleDecls[i]); } } + if (m_styledElement->isHTMLElement()) { + bool isAuto; + TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto); + if (isAuto) + addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration()); + } } // 6. Check the rules in author sheets next. @@ -1547,14 +1492,6 @@ PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyl m_style->setUnique(); if (visitedStyle) { - // Copy any pseudo bits that the visited style has to the primary style so that - // pseudo element styles will continue to work for pseudo elements inside :visited - // links. - for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) { - if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo))) - m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo)); - } - // Add the visited style off the main style. m_style->addCachedPseudoStyle(visitedStyle.release()); } @@ -1687,12 +1624,8 @@ PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, // Fetch our parent style with :visited in effect. RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK); visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true); - if (visitedStyle) { - if (m_elementLinkState == InsideUnvisitedLink) - visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that. - else - visitedStyle->setStyleType(VISITED_LINK); - } + if (visitedStyle) + visitedStyle->setStyleType(VISITED_LINK); } initForStyleResolve(e, parentStyle, pseudo); @@ -1839,6 +1772,15 @@ static void addIntrinsicMargins(RenderStyle* style) } } +static inline bool isAtShadowBoundary(Element* element) +{ + if (!element) + return false; + + ContainerNode* parentNode = element->parentNode(); + return parentNode && parentNode->isShadowBoundary(); +} + void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e) { // Cache our original display. @@ -1917,8 +1859,8 @@ void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parent // After performing the display mutation, check table rows. We do not honor position:relative on // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock() // on some sites). - if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP || - style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) && + if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP + || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) && style->position() == RelativePosition) style->setPosition(StaticPosition); @@ -1961,9 +1903,9 @@ void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parent } // Finally update our text decorations in effect, but don't allow text-decoration to percolate through - // tables, inline blocks, inline tables, or run-ins. + // tables, inline blocks, inline tables, run-ins, or shadow DOM. if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN - || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX) + || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)) style->setTextDecorationsInEffect(style->textDecoration()); else style->addToTextDecorationsInEffect(style->textDecoration()); @@ -2100,7 +2042,8 @@ inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData) { m_dynamicPseudo = NOPSEUDO; - if (ruleData.hasFastCheckableSelector()) { + // Let the slow path handle SVG as it has some additional rules regarding shadow trees. + if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) { // We know this selector does not include any pseudo selectors. if (m_checker.m_pseudoStyle != NOPSEUDO) return false; @@ -2134,13 +2077,67 @@ static inline bool selectorTagMatches(const Element* element, const CSSSelector* static inline bool isFastCheckableSelector(const CSSSelector* selector) { for (; selector; selector = selector->tagHistory()) { - if (selector->relation() != CSSSelector::Descendant) + if (selector->relation() != CSSSelector::Descendant && selector->relation() != CSSSelector::Child && selector->relation() != CSSSelector::SubSelector) return false; if (selector->m_match != CSSSelector::None && selector->m_match != CSSSelector::Id && selector->m_match != CSSSelector::Class) return false; } return true; } + +template <class ValueChecker> +inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement) +{ + AtomicStringImpl* value = selector->value().impl(); + for (; element; element = element->parentElement()) { + if (ValueChecker::checkValue(element, value) && selectorTagMatches(element, selector)) { + if (selector->relation() == CSSSelector::Descendant) + topChildOrSubselector = 0; + else if (!topChildOrSubselector) { + ASSERT(selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector); + topChildOrSubselector = selector; + topChildOrSubselectorMatchElement = element; + } + if (selector->relation() != CSSSelector::SubSelector) + element = element->parentElement(); + selector = selector->tagHistory(); + return true; + } + if (topChildOrSubselector) { + // Child or subselector check failed. + // If the match element is null, topChildOrSubselector was also the very topmost selector and had to match + // the original element we were checking. + if (!topChildOrSubselectorMatchElement) + return false; + // There may be other matches down the ancestor chain. + // Rewind to the topmost child or subselector and the element it matched, continue checking ancestors. + selector = topChildOrSubselector; + element = topChildOrSubselectorMatchElement->parentElement(); + topChildOrSubselector = 0; + return true; + } + } + return false; +} + +struct ClassCheck { + static bool checkValue(const Element* element, AtomicStringImpl* value) + { + return element->hasClass() && static_cast<const StyledElement*>(element)->classNames().contains(value); + } +}; +struct IdCheck { + static bool checkValue(const Element* element, AtomicStringImpl* value) + { + return element->hasID() && element->idForStyleResolution().impl() == value; + } +}; +struct TagCheck { + static bool checkValue(const Element*, AtomicStringImpl*) + { + return true; + } +}; bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* selector, const Element* element) { @@ -2150,40 +2147,30 @@ bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* sel if (!selectorTagMatches(element, selector)) return false; + const CSSSelector* topChildOrSubselector = 0; + const Element* topChildOrSubselectorMatchElement = 0; + if (selector->relation() == CSSSelector::Child || selector->relation() == CSSSelector::SubSelector) + topChildOrSubselector = selector; + + if (selector->relation() != CSSSelector::SubSelector) + element = element->parentElement(); + selector = selector->tagHistory(); - if (!selector) - return true; - const Element* ancestor = element; - // We know this compound selector has descendant combinators only and all components are simple. - for (; selector; selector = selector->tagHistory()) { - AtomicStringImpl* value; + + // We know this compound selector has descendant, child and subselector combinators only and all components are simple. + while (selector) { switch (selector->m_match) { case CSSSelector::Class: - value = selector->value().impl(); - while (true) { - if (!(ancestor = ancestor->parentElement())) - return false; - const StyledElement* styledElement = static_cast<const StyledElement*>(ancestor); - if (ancestor->hasClass() && styledElement->classNames().contains(value) && selectorTagMatches(ancestor, selector)) - break; - } + if (!fastCheckSingleSelector<ClassCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) + return false; break; case CSSSelector::Id: - value = selector->value().impl(); - while (true) { - if (!(ancestor = ancestor->parentElement())) - return false; - if (ancestor->hasID() && ancestor->idForStyleResolution().impl() == value && selectorTagMatches(ancestor, selector)) - break; - } + if (!fastCheckSingleSelector<IdCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) + return false; break; case CSSSelector::None: - while (true) { - if (!(ancestor = ancestor->parentElement())) - return false; - if (selectorTagMatches(ancestor, selector)) - break; - } + if (!fastCheckSingleSelector<TagCheck>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) + return false; break; default: ASSERT_NOT_REACHED(); @@ -2191,7 +2178,6 @@ bool CSSStyleSelector::SelectorChecker::fastCheckSelector(const CSSSelector* sel } return true; } - // Recursive check of selectors and combinators // It can return 3 different values: @@ -2208,7 +2194,7 @@ CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector #endif // first selector has to match - if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, elementStyle, elementParentStyle)) + if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, encounteredLink, elementStyle, elementParentStyle)) return SelectorFailsLocally; // The rest of the selectors has to match @@ -2378,7 +2364,7 @@ static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr) return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl()); } -bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const +bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const { ASSERT(e); if (!e) @@ -2467,14 +2453,14 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme if (sel->m_match == CSSSelector::PseudoClass) { // Handle :not up front. if (sel->pseudoType() == CSSSelector::PseudoNot) { - // check the simple selector - for (CSSSelector* subSel = sel->simpleSelector(); subSel; subSel = subSel->tagHistory()) { + ASSERT(sel->selectorList()); + for (CSSSelector* subSel = sel->selectorList()->first(); subSel; subSel = subSel->tagHistory()) { // :not cannot nest. I don't really know why this is a // restriction in CSS3, but it is, so let's honor it. // the parser enforces that this never occurs - ASSERT(!subSel->simpleSelector()); + ASSERT(subSel->pseudoType() != CSSSelector::PseudoNot); - if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, elementStyle, elementParentStyle)) + if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle)) return true; } } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) { @@ -2781,6 +2767,12 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme if (e == e->document()->cssTarget()) return true; break; + case CSSSelector::PseudoAny: + for (CSSSelector* selector = sel->selectorList()->first(); selector; selector = CSSSelectorList::next(selector)) { + if (checkSelector(selector, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle) == SelectorMatches) + return true; + } + break; case CSSSelector::PseudoAnyLink: if (e && e->isLink()) return true; @@ -2788,7 +2780,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme case CSSSelector::PseudoAutofill: { if (!e || !e->isFormControlElement()) break; - if (InputElement* inputElement = toInputElement(e)) + if (InputElement* inputElement = e->toInputElement()) return inputElement->isAutofilled(); break; } @@ -2881,7 +2873,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just // obey the CSS spec here in the test for matching the pseudo. - InputElement* inputElement = toInputElement(e); + InputElement* inputElement = e->toInputElement(); if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate()) return true; break; @@ -2889,7 +2881,7 @@ bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Eleme case CSSSelector::PseudoIndeterminate: { if (!e || !e->isFormControlElement()) break; - InputElement* inputElement = toInputElement(e); + InputElement* inputElement = e->toInputElement(); if (inputElement && inputElement->isIndeterminate()) return true; break; @@ -3029,7 +3021,7 @@ bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* s return false; } case CSSSelector::PseudoCornerPresent: - return scrollbar->scrollableArea()->scrollbarCornerPresent(); + return scrollbar->scrollableArea()->isScrollCornerVisible(); default: return false; } @@ -3052,6 +3044,7 @@ static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* sele RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position) : m_rule(rule) , m_selector(selector) + , m_specificity(selector->specificity()) , m_position(position) , m_hasFastCheckableSelector(isFastCheckableSelector(selector)) , m_hasMultipartSelector(selector->tagHistory()) @@ -3223,47 +3216,69 @@ void RuleSet::addStyleRule(CSSStyleRule* rule) addRule(rule, s); } } + +static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector) +{ + if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty()) + features.idsInRules.add(selector->value().impl()); + switch (selector->pseudoType()) { + case CSSSelector::PseudoFirstLine: + features.usesFirstLineRules = true; + break; + case CSSSelector::PseudoBefore: + case CSSSelector::PseudoAfter: + features.usesBeforeAfterRules = true; + break; + case CSSSelector::PseudoLink: + case CSSSelector::PseudoVisited: + features.usesLinkRules = true; + break; + default: + break; + } +} -static void collectIdsAndSiblingRulesFromList(HashSet<AtomicStringImpl*>& ids, OwnPtr<RuleSet>& siblingRules, const Vector<RuleData>& rules) +static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules) { unsigned size = rules.size(); for (unsigned i = 0; i < size; ++i) { const RuleData& ruleData = rules[i]; bool foundSiblingSelector = false; for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { - if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty()) - ids.add(selector->value().impl()); - if (CSSSelector* simpleSelector = selector->simpleSelector()) { - ASSERT(!simpleSelector->simpleSelector()); - if (simpleSelector->m_match == CSSSelector::Id && !simpleSelector->value().isEmpty()) - ids.add(simpleSelector->value().impl()); - } - if (selector->isSiblingSelector()) + collectFeaturesFromSelector(features, selector); + + if (CSSSelectorList* selectorList = selector->selectorList()) { + for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { + if (selector->isSiblingSelector()) + foundSiblingSelector = true; + collectFeaturesFromSelector(features, subSelector); + } + } else if (selector->isSiblingSelector()) foundSiblingSelector = true; } if (foundSiblingSelector) { - if (!siblingRules) - siblingRules = adoptPtr(new RuleSet); - siblingRules->addRule(ruleData.rule(), ruleData.selector()); + if (!features.siblingRules) + features.siblingRules = adoptPtr(new RuleSet); + features.siblingRules->addRule(ruleData.rule(), ruleData.selector()); } } } -void RuleSet::collectIdsAndSiblingRules(HashSet<AtomicStringImpl*>& ids, OwnPtr<RuleSet>& siblingRules) const +void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const { AtomRuleMap::const_iterator end = m_idRules.end(); for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it) - collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second); + collectFeaturesFromList(features, *it->second); end = m_classRules.end(); for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it) - collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second); + collectFeaturesFromList(features, *it->second); end = m_tagRules.end(); for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it) - collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second); + collectFeaturesFromList(features, *it->second); end = m_pseudoRules.end(); for (AtomRuleMap::const_iterator it = m_pseudoRules.begin(); it != end; ++it) - collectIdsAndSiblingRulesFromList(ids, siblingRules, *it->second); - collectIdsAndSiblingRulesFromList(ids, siblingRules, m_universalRules); + collectFeaturesFromList(features, *it->second); + collectFeaturesFromList(features, m_universalRules); } static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map) @@ -3286,7 +3301,7 @@ void RuleSet::shrinkToFit() // ------------------------------------------------------------------------------------- // this is mostly boring stuff on how to apply a certain rule to the renderstyle... -static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0) +static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0) { // This function is tolerant of a null style value. The only place style is used is in // length measurements, like 'ems' and 'px'. And in those cases style is only used @@ -3301,8 +3316,12 @@ static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* st if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) { if (ok) *ok = false; - } else if (CSSPrimitiveValue::isUnitTypeLength(type)) - l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed); + } else if (CSSPrimitiveValue::isUnitTypeLength(type)) { + if (toFloat) + l = Length(primitiveValue->computeLengthDouble(style, rootStyle, multiplier), Fixed); + else + l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed); + } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length(primitiveValue->getDoubleValue(), Percent); else if (type == CSSPrimitiveValue::CSS_NUMBER) @@ -3312,6 +3331,16 @@ static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* st } return l; } + +static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0) +{ + return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok); +} + +static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0) +{ + return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok); +} template <bool applyFirst> void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex) @@ -3329,7 +3358,7 @@ void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int e if (applyFirst) { COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property); - COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 13, CSS_zoom_is_end_of_first_prop_range); + COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 14, CSS_zoom_is_end_of_first_prop_range); COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom); // give special priority to font-xxx, color properties, etc @@ -3363,7 +3392,7 @@ void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFi return; // Sort the set of matched rules. - sortMatchedRules(0, m_matchedRules.size()); + sortMatchedRules(); // Now transfer the set of matched rules over to our list of decls. for (unsigned i = 0; i < m_matchedRules.size(); i++) @@ -3502,6 +3531,19 @@ inline bool isValidVisitedLinkProperty(int id) return false; } +// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead +// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() +// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. +// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...) +// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like +// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale, +// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific +// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size). +static inline bool useSVGZoomRules(const Element* e) +{ + return e && e->isSVGElement(); +} + void CSSStyleSelector::applyProperty(int id, CSSValue *value) { CSSPrimitiveValue* primitiveValue = 0; @@ -3510,16 +3552,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) float zoomFactor = m_style->effectiveZoom(); - // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead - // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*() - // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that. - // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...) - // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like - // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale, - // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific - // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size). - bool useSVGZoomRules = m_element && m_element->isSVGElement(); - Length l; bool apply = false; @@ -3535,45 +3567,24 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; } + CSSPropertyID property = static_cast<CSSPropertyID>(id); + + // check lookup table for implementations and use when available + if (m_applyProperty.implements(property)) { + if (isInherit) + m_applyProperty.applyInheritValue(property, this); + else if (isInitial) + m_applyProperty.applyInitialValue(property, this); + else + m_applyProperty.applyValue(property, this, value); + return; + } + // What follows is a list that maps the CSS properties into their corresponding front-end // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and // are only hit when mapping "inherit" or "initial" into front-end values. - CSSPropertyID property = static_cast<CSSPropertyID>(id); switch (property) { // ident only properties - case CSSPropertyBackgroundAttachment: - HANDLE_BACKGROUND_VALUE(attachment, Attachment, value) - return; - case CSSPropertyBackgroundClip: - case CSSPropertyWebkitBackgroundClip: - HANDLE_BACKGROUND_VALUE(clip, Clip, value) - return; - case CSSPropertyWebkitBackgroundComposite: - HANDLE_BACKGROUND_VALUE(composite, Composite, value) - return; - case CSSPropertyBackgroundOrigin: - case CSSPropertyWebkitBackgroundOrigin: - HANDLE_BACKGROUND_VALUE(origin, Origin, value) - return; - case CSSPropertyBackgroundSize: - case CSSPropertyWebkitBackgroundSize: - HANDLE_BACKGROUND_VALUE(size, Size, value) - return; - case CSSPropertyWebkitMaskAttachment: - HANDLE_MASK_VALUE(attachment, Attachment, value) - return; - case CSSPropertyWebkitMaskClip: - HANDLE_MASK_VALUE(clip, Clip, value) - return; - case CSSPropertyWebkitMaskComposite: - HANDLE_MASK_VALUE(composite, Composite, value) - return; - case CSSPropertyWebkitMaskOrigin: - HANDLE_MASK_VALUE(origin, Origin, value) - return; - case CSSPropertyWebkitMaskSize: - HANDLE_MASK_VALUE(size, Size, value) - return; case CSSPropertyBorderCollapse: HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse) if (!primitiveValue) @@ -3589,18 +3600,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; } return; - case CSSPropertyBorderTopStyle: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle) - return; - case CSSPropertyBorderRightStyle: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle) - return; - case CSSPropertyBorderBottomStyle: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle) - return; - case CSSPropertyBorderLeftStyle: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle) - return; case CSSPropertyOutlineStyle: HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) if (primitiveValue) { @@ -3616,11 +3615,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyClear: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear) return; - case CSSPropertyDirection: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(direction, Direction) - if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement()) - m_element->document()->setDirectionSetOnDocumentElement(true); - return; case CSSPropertyDisplay: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display) #if ENABLE(WCSS) @@ -3765,33 +3759,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyListStyleType: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStyleType, ListStyleType) return; - case CSSPropertyOverflow: - { - if (isInherit) { - m_style->setOverflowX(m_parentStyle->overflowX()); - m_style->setOverflowY(m_parentStyle->overflowY()); - return; - } - - if (isInitial) { - m_style->setOverflowX(RenderStyle::initialOverflowX()); - m_style->setOverflowY(RenderStyle::initialOverflowY()); - return; - } - - EOverflow o = *primitiveValue; - - m_style->setOverflowX(o); - m_style->setOverflowY(o); - return; - } - - case CSSPropertyOverflowX: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(overflowX, OverflowX) - return; - case CSSPropertyOverflowY: - HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(overflowY, OverflowY) - return; case CSSPropertyPageBreakBefore: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak) return; @@ -3834,51 +3801,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyWhiteSpace: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace) return; - - case CSSPropertyBackgroundPosition: - HANDLE_BACKGROUND_INHERIT_AND_INITIAL(xPosition, XPosition); - HANDLE_BACKGROUND_INHERIT_AND_INITIAL(yPosition, YPosition); - return; - case CSSPropertyBackgroundPositionX: { - HANDLE_BACKGROUND_VALUE(xPosition, XPosition, value) - return; - } - case CSSPropertyBackgroundPositionY: { - HANDLE_BACKGROUND_VALUE(yPosition, YPosition, value) - return; - } - case CSSPropertyWebkitMaskPosition: - HANDLE_MASK_INHERIT_AND_INITIAL(xPosition, XPosition); - HANDLE_MASK_INHERIT_AND_INITIAL(yPosition, YPosition); - return; - case CSSPropertyWebkitMaskPositionX: { - HANDLE_MASK_VALUE(xPosition, XPosition, value) - return; - } - case CSSPropertyWebkitMaskPositionY: { - HANDLE_MASK_VALUE(yPosition, YPosition, value) - return; - } - case CSSPropertyBackgroundRepeat: - HANDLE_BACKGROUND_INHERIT_AND_INITIAL(repeatX, RepeatX); - HANDLE_BACKGROUND_INHERIT_AND_INITIAL(repeatY, RepeatY); - return; - case CSSPropertyBackgroundRepeatX: - HANDLE_BACKGROUND_VALUE(repeatX, RepeatX, value) - return; - case CSSPropertyBackgroundRepeatY: - HANDLE_BACKGROUND_VALUE(repeatY, RepeatY, value) - return; - case CSSPropertyWebkitMaskRepeat: - HANDLE_MASK_INHERIT_AND_INITIAL(repeatX, RepeatX); - HANDLE_MASK_INHERIT_AND_INITIAL(repeatY, RepeatY); - return; - case CSSPropertyWebkitMaskRepeatX: - HANDLE_MASK_VALUE(repeatX, RepeatX, value) - return; - case CSSPropertyWebkitMaskRepeatY: - HANDLE_MASK_VALUE(repeatY, RepeatY, value) - return; case CSSPropertyBorderSpacing: { if (isInherit) { m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing()); @@ -3943,95 +3865,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) m_style->setCursor(*primitiveValue); } return; -// colors || inherit - case CSSPropertyColor: - // If the 'currentColor' keyword is set on the 'color' property itself, - // it is treated as 'color:inherit' at parse time - if (primitiveValue && primitiveValue->getIdent() == CSSValueCurrentcolor) - isInherit = true; - case CSSPropertyBackgroundColor: - case CSSPropertyBorderTopColor: - case CSSPropertyBorderRightColor: - case CSSPropertyBorderBottomColor: - case CSSPropertyBorderLeftColor: - case CSSPropertyOutlineColor: - case CSSPropertyWebkitColumnRuleColor: - case CSSPropertyWebkitTextStrokeColor: - case CSSPropertyWebkitTextEmphasisColor: - case CSSPropertyWebkitTextFillColor: { - Color col; - if (isInherit) { - HANDLE_INHERIT_COND(CSSPropertyBackgroundColor, backgroundColor, BackgroundColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderTopColor, borderTopColor, color, BorderTopColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderBottomColor, borderBottomColor, color, BorderBottomColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderRightColor, borderRightColor, color, BorderRightColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderLeftColor, borderLeftColor, color, BorderLeftColor) - HANDLE_INHERIT_COND(CSSPropertyColor, color, Color) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyOutlineColor, outlineColor, color, OutlineColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitColumnRuleColor, columnRuleColor, color, ColumnRuleColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextStrokeColor, textStrokeColor, color, TextStrokeColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextEmphasisColor, textEmphasisColor, color, TextEmphasisColor) - HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextFillColor, textFillColor, color, TextFillColor) - return; - } - if (isInitial) { - // The border/outline colors will just map to the invalid color |col| above. This will have the - // effect of forcing the use of the currentColor when it comes time to draw the borders (and of - // not painting the background since the color won't be valid). - if (id == CSSPropertyColor) - col = RenderStyle::initialColor(); - } else { - if (!primitiveValue) - return; - col = getColorFromPrimitiveValue(primitiveValue); - } - - switch (id) { - case CSSPropertyBackgroundColor: - m_style->setBackgroundColor(col); - break; - case CSSPropertyBorderTopColor: - m_style->setBorderTopColor(col); - break; - case CSSPropertyBorderRightColor: - m_style->setBorderRightColor(col); - break; - case CSSPropertyBorderBottomColor: - m_style->setBorderBottomColor(col); - break; - case CSSPropertyBorderLeftColor: - m_style->setBorderLeftColor(col); - break; - case CSSPropertyColor: - m_style->setColor(col); - break; - case CSSPropertyOutlineColor: - m_style->setOutlineColor(col); - break; - case CSSPropertyWebkitColumnRuleColor: - m_style->setColumnRuleColor(col); - break; - case CSSPropertyWebkitTextStrokeColor: - m_style->setTextStrokeColor(col); - break; - case CSSPropertyWebkitTextEmphasisColor: - m_style->setTextEmphasisColor(col); - break; - case CSSPropertyWebkitTextFillColor: - m_style->setTextFillColor(col); - break; - } - - return; - } // uri || inherit - case CSSPropertyBackgroundImage: - HANDLE_BACKGROUND_VALUE(image, Image, value) - return; - case CSSPropertyWebkitMaskImage: - HANDLE_MASK_VALUE(image, Image, value) - return; case CSSPropertyListStyleImage: { HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage) @@ -4150,7 +3985,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyLetterSpacing: case CSSPropertyWordSpacing: { - if (isInherit) { HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing) HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing) @@ -4168,7 +4002,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) } else { if (!primitiveValue) return; - width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules ? 1.0f : zoomFactor); + width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules(m_element) ? 1.0f : zoomFactor); } switch (id) { case CSSPropertyLetterSpacing: @@ -4220,8 +4054,10 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) // length, percent case CSSPropertyMaxWidth: // +none +inherit - if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) + if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { + l = Length(undefinedLength, Fixed); apply = true; + } case CSSPropertyTop: case CSSPropertyLeft: case CSSPropertyRight: @@ -4593,13 +4429,16 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign) if (!primitiveValue) return; - int id = primitiveValue->getIdent(); - if (id == CSSValueStart) - m_style->setTextAlign(m_style->isLeftToRightDirection() ? LEFT : RIGHT); - else if (id == CSSValueEnd) - m_style->setTextAlign(m_style->isLeftToRightDirection() ? RIGHT : LEFT); - else - m_style->setTextAlign(*primitiveValue); + if (primitiveValue->getIdent() == CSSValueWebkitMatchParent) { + if (m_parentStyle->textAlign() == TASTART) + m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? LEFT : RIGHT); + else if (m_parentStyle->textAlign() == TAEND) + m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? RIGHT : LEFT); + else + m_style->setTextAlign(m_parentStyle->textAlign()); + return; + } + m_style->setTextAlign(*primitiveValue); return; } @@ -4630,10 +4469,10 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) Rect* rect = primitiveValue->getRectValue(); if (!rect) return; - top = convertToLength(rect->top(), style(), m_rootElementStyle, zoomFactor); - right = convertToLength(rect->right(), style(), m_rootElementStyle, zoomFactor); - bottom = convertToLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor); - left = convertToLength(rect->left(), style(), m_rootElementStyle, zoomFactor); + top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor); + right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor); + bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor); + left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor); } else if (primitiveValue->getIdent() != CSSValueAuto) { return; } @@ -4675,36 +4514,59 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item); switch (contentValue->primitiveType()) { - case CSSPrimitiveValue::CSS_STRING: - m_style->setContent(contentValue->getStringValue().impl(), didSet); + case CSSPrimitiveValue::CSS_STRING: + m_style->setContent(contentValue->getStringValue().impl(), didSet); + didSet = true; + break; + case CSSPrimitiveValue::CSS_ATTR: { + // FIXME: Can a namespace be specified for an attr(foo)? + if (m_style->styleType() == NOPSEUDO) + m_style->setUnique(); + else + m_parentStyle->setUnique(); + QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom); + m_style->setContent(m_element->getAttribute(attr).impl(), didSet); + didSet = true; + // register the fact that the attribute value affects the style + m_selectorAttrs.add(attr.localName().impl()); + break; + } + case CSSPrimitiveValue::CSS_URI: { + if (!contentValue->isImageValue()) + break; + m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet); + didSet = true; + break; + } + case CSSPrimitiveValue::CSS_COUNTER: { + Counter* counterValue = contentValue->getCounterValue(); + OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), + (EListStyleType)counterValue->listStyleNumber(), counterValue->separator())); + m_style->setContent(counter.release(), didSet); + didSet = true; + break; + } + case CSSPrimitiveValue::CSS_IDENT: + switch (contentValue->getIdent()) { + case CSSValueOpenQuote: + m_style->setContent(OPEN_QUOTE, didSet); didSet = true; break; - case CSSPrimitiveValue::CSS_ATTR: { - // FIXME: Can a namespace be specified for an attr(foo)? - if (m_style->styleType() == NOPSEUDO) - m_style->setUnique(); - else - m_parentStyle->setUnique(); - QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom); - m_style->setContent(m_element->getAttribute(attr).impl(), didSet); + case CSSValueCloseQuote: + m_style->setContent(CLOSE_QUOTE, didSet); didSet = true; - // register the fact that the attribute value affects the style - m_selectorAttrs.add(attr.localName().impl()); break; - } - case CSSPrimitiveValue::CSS_URI: { - if (!contentValue->isImageValue()) - break; - m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet); + case CSSValueNoOpenQuote: + m_style->setContent(NO_OPEN_QUOTE, didSet); didSet = true; break; - } - case CSSPrimitiveValue::CSS_COUNTER: { - Counter* counterValue = contentValue->getCounterValue(); - OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), - (EListStyleType)counterValue->listStyleNumber(), counterValue->separator())); - m_style->setContent(counter.release(), didSet); + case CSSValueNoCloseQuote: + m_style->setContent(NO_CLOSE_QUOTE, didSet); didSet = true; + break; + default: + // normal and none do not have any effect. + {} } } } @@ -4712,6 +4574,37 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) m_style->clearContent(); return; } + case CSSPropertyQuotes: + if (isInherit) { + if (m_parentStyle) + m_style->setQuotes(m_parentStyle->quotes()); + return; + } + if (isInitial) { + m_style->setQuotes(0); + return; + } + if (value->isValueList()) { + CSSValueList* list = static_cast<CSSValueList*>(value); + size_t length = list->length(); + QuotesData* data = QuotesData::create(length); + if (!data) + return; // Out of memory + String* quotes = data->data(); + for (size_t i = 0; i < length; i++) { + CSSValue* item = list->itemWithoutBoundsCheck(i); + ASSERT(item->isPrimitiveValue()); + primitiveValue = static_cast<CSSPrimitiveValue*>(item); + ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING); + quotes[i] = primitiveValue->getStringValue(); + } + m_style->setQuotes(adoptRef(data)); + } else if (primitiveValue) { + ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT); + if (primitiveValue->getIdent() == CSSValueNone) + m_style->setQuotes(adoptRef(QuotesData::create(0))); + } + return; case CSSPropertyCounterIncrement: applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false); @@ -5061,7 +4954,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) fontDescription.setUsePrinterFont(m_checker.m_document->printing()); // Handle the zoom factor. - fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules)); + fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules(m_element))); if (m_style->setFontDescription(fontDescription)) m_fontDirty = true; } @@ -5185,8 +5078,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) radiusHeight = Length(pair->second()->getDoubleValue(), Percent); else radiusHeight = Length(max(intMinForLength, min(intMaxForLength, pair->second()->computeLengthInt(style(), m_rootElementStyle, zoomFactor))), Fixed); - int width = radiusWidth.rawValue(); - int height = radiusHeight.rawValue(); + int width = radiusWidth.value(); + int height = radiusHeight.value(); if (width < 0 || height < 0) return; if (width == 0) @@ -5522,9 +5415,9 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) } else { bool ok = true; - Length l = convertToLength(primitiveValue, style(), m_rootElementStyle, 1, &ok); + Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok); if (ok) - m_style->setMarqueeIncrement(l); + m_style->setMarqueeIncrement(marqueeLength); } return; } @@ -5626,12 +5519,28 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) m_style->setHyphenationString(primitiveValue->getStringValue()); return; } - case CSSPropertyWebkitHyphenateLocale: { - HANDLE_INHERIT_AND_INITIAL(hyphenationLocale, HyphenationLocale); + case CSSPropertyWebkitHyphenateLimitAfter: { + HANDLE_INHERIT_AND_INITIAL(hyphenationLimitAfter, HyphenationLimitAfter); + if (primitiveValue->getIdent() == CSSValueAuto) + m_style->setHyphenationLimitAfter(-1); + else + m_style->setHyphenationLimitAfter(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max()))); + return; + } + case CSSPropertyWebkitHyphenateLimitBefore: { + HANDLE_INHERIT_AND_INITIAL(hyphenationLimitBefore, HyphenationLimitBefore); + if (primitiveValue->getIdent() == CSSValueAuto) + m_style->setHyphenationLimitBefore(-1); + else + m_style->setHyphenationLimitBefore(min(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), static_cast<int>(numeric_limits<short>::max()))); + return; + } + case CSSPropertyWebkitLocale: { + HANDLE_INHERIT_AND_INITIAL(locale, Locale); if (primitiveValue->getIdent() == CSSValueAuto) - m_style->setHyphenationLocale(nullAtom); + m_style->setLocale(nullAtom); else - m_style->setHyphenationLocale(primitiveValue->getStringValue()); + m_style->setLocale(primitiveValue->getStringValue()); return; } case CSSPropertyWebkitBorderFit: { @@ -5670,10 +5579,10 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) DashboardRegion *first = region; while (region) { - Length top = convertToLength(region->top(), style(), m_rootElementStyle); - Length right = convertToLength(region->right(), style(), m_rootElementStyle); - Length bottom = convertToLength(region->bottom(), style(), m_rootElementStyle); - Length left = convertToLength(region->left(), style(), m_rootElementStyle); + Length top = convertToIntLength(region->top(), style(), m_rootElementStyle); + Length right = convertToIntLength(region->right(), style(), m_rootElementStyle); + Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle); + Length left = convertToIntLength(region->left(), style(), m_rootElementStyle); if (region->m_isCircle) m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true); else if (region->m_isRectangle) @@ -5953,7 +5862,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyFontStretch: case CSSPropertyPage: - case CSSPropertyQuotes: case CSSPropertyTextLineThrough: case CSSPropertyTextLineThroughColor: case CSSPropertyTextLineThroughMode: @@ -6005,8 +5913,6 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) case CSSPropertyWebkitTextCombine: HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textCombine, TextCombine) - if (m_style->hasTextCombine()) - m_style->setUnique(); // The style could be modified in RenderCombineText depending on text metrics. return; case CSSPropertyWebkitTextEmphasisPosition: @@ -6026,8 +5932,11 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) if (list->length() != 2) return; for (unsigned i = 0; i < 2; ++i) { - ASSERT(list->itemWithoutBoundsCheck(i)->isPrimitiveValue()); - CSSPrimitiveValue* value = static_cast<CSSPrimitiveValue*>(list->itemWithoutBoundsCheck(i)); + CSSValue* item = list->itemWithoutBoundsCheck(i); + if (!item->isPrimitiveValue()) + continue; + + CSSPrimitiveValue* value = static_cast<CSSPrimitiveValue*>(item); if (value->getIdent() == CSSValueFilled || value->getIdent() == CSSValueOpen) m_style->setTextEmphasisFill(*value); else @@ -6059,6 +5968,92 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) return; + case CSSPropertyWebkitTextOrientation: { + if (!isInherit && !isInitial && !primitiveValue) + return; + + TextOrientation result; + if (isInherit) + result = m_parentStyle->fontDescription().textOrientation(); + else if (isInitial) + result = RenderStyle::initialTextOrientation(); + else + result = *primitiveValue; + + FontDescription fontDescription = m_style->fontDescription(); + if (fontDescription.textOrientation() != result) { + fontDescription.setTextOrientation(result); + if (m_style->setFontDescription(fontDescription)) + m_fontDirty = true; + } + return; + } + + case CSSPropertyWebkitLineBoxContain: { + HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain) + if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) { + m_style->setLineBoxContain(LineBoxContainNone); + return; + } + + if (!value->isCSSLineBoxContainValue()) + return; + + CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value); + m_style->setLineBoxContain(lineBoxContainValue->value()); + return; + } + + // These properties are implemented in the CSSStyleApplyProperty lookup table. + case CSSPropertyColor: + case CSSPropertyDirection: + case CSSPropertyBackgroundAttachment: + case CSSPropertyBackgroundClip: + case CSSPropertyWebkitBackgroundClip: + case CSSPropertyWebkitBackgroundComposite: + case CSSPropertyBackgroundOrigin: + case CSSPropertyWebkitBackgroundOrigin: + case CSSPropertyBackgroundImage: + case CSSPropertyBackgroundSize: + case CSSPropertyWebkitBackgroundSize: + case CSSPropertyWebkitMaskAttachment: + case CSSPropertyWebkitMaskClip: + case CSSPropertyWebkitMaskComposite: + case CSSPropertyWebkitMaskOrigin: + case CSSPropertyWebkitMaskImage: + case CSSPropertyWebkitMaskSize: + case CSSPropertyBackgroundColor: + case CSSPropertyBorderBottomColor: + case CSSPropertyBorderLeftColor: + case CSSPropertyBorderRightColor: + case CSSPropertyBorderTopColor: + case CSSPropertyBorderTopStyle: + case CSSPropertyBorderRightStyle: + case CSSPropertyBorderBottomStyle: + case CSSPropertyBorderLeftStyle: + case CSSPropertyOutlineColor: + case CSSPropertyWebkitColumnRuleColor: + case CSSPropertyWebkitTextEmphasisColor: + case CSSPropertyWebkitTextFillColor: + case CSSPropertyWebkitTextStrokeColor: + case CSSPropertyBackgroundPosition: + case CSSPropertyBackgroundPositionX: + case CSSPropertyBackgroundPositionY: + case CSSPropertyWebkitMaskPosition: + case CSSPropertyWebkitMaskPositionX: + case CSSPropertyWebkitMaskPositionY: + case CSSPropertyBackgroundRepeat: + case CSSPropertyBackgroundRepeatX: + case CSSPropertyBackgroundRepeatY: + case CSSPropertyWebkitMaskRepeat: + case CSSPropertyWebkitMaskRepeatX: + case CSSPropertyWebkitMaskRepeatY: + case CSSPropertyOverflow: + case CSSPropertyOverflowX: + case CSSPropertyOverflowY: + ASSERT_NOT_REACHED(); + return; + #ifdef ANDROID_CSS_RING case CSSPropertyWebkitRing: if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return; @@ -6207,6 +6202,7 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value) default: // Try the SVG properties applySVGProperty(id, value); + return; #endif } } @@ -6930,6 +6926,13 @@ void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size) float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules) { + // Text with a 0px font size should not be visible and therefore needs to be + // exempt from minimum font size rules. Acid3 relies on this for pixel-perfect + // rendering. This is also compatible with other browsers that have minimum + // font size settings (e.g. Firefox). + if (fabsf(specifiedSize) < std::numeric_limits<float>::epsilon()) + return 0.0f; + float zoomFactor = 1.0f; if (!useSVGZoomRules) { zoomFactor = style->effectiveZoom(); @@ -7289,13 +7292,13 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation) - ty = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); + ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); else { - tx = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); + tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); - ty = convertToLength(secondValue, style, rootStyle, zoomFactor, &ok); + ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok); } } } @@ -7313,19 +7316,19 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* Length ty = Length(0, Fixed); Length tz = Length(0, Fixed); if (transformValue->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation) - tz = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); + tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); else if (transformValue->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation) - ty = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); + ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); else { - tx = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); + tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); if (transformValue->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(2)); - tz = convertToLength(thirdValue, style, rootStyle, zoomFactor, &ok); + tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor, &ok); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(transformValue->itemWithoutBoundsCheck(1)); - ty = convertToLength(secondValue, style, rootStyle, zoomFactor, &ok); + ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor, &ok); } } } @@ -7456,7 +7459,7 @@ bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* bool ok = true; Length p = Length(0, Fixed); if (CSSPrimitiveValue::isUnitTypeLength(firstValue->primitiveType())) - p = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok); + p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor, &ok); else { // This is a quirk that should go away when 3d transforms are finalized. double val = firstValue->getDoubleValue(); diff --git a/Source/WebCore/css/CSSStyleSelector.h b/Source/WebCore/css/CSSStyleSelector.h index 6065c2c..ca512fd 100644 --- a/Source/WebCore/css/CSSStyleSelector.h +++ b/Source/WebCore/css/CSSStyleSelector.h @@ -45,6 +45,7 @@ class CSSFontFaceRule; class CSSImageValue; class CSSRuleList; class CSSSelector; +class CSSStyleApplyProperty; class CSSStyleRule; class CSSStyleSheet; class CSSValue; @@ -84,6 +85,7 @@ public: // This class selects a RenderStyle for a given element based on a collection of stylesheets. class CSSStyleSelector { + friend class CSSStyleApplyProperty; WTF_MAKE_NONCOPYABLE(CSSStyleSelector); WTF_MAKE_FAST_ALLOCATED; public: CSSStyleSelector(Document*, StyleSheetList* authorSheets, CSSStyleSheet* mappedElementSheet, @@ -95,6 +97,7 @@ public: void pushParent(Element* parent); void popParent(Element* parent); + PassRefPtr<RenderStyle> styleForElement(Element* e, RenderStyle* parentStyle = 0, bool allowSharing = true, bool resolveForRootDefault = false, bool matchVisitedPseudoClass = false); void keyframeStylesForAnimation(Element*, const RenderStyle*, KeyframeList& list); @@ -111,20 +114,22 @@ public: PassRefPtr<RenderStyle> pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle* parentStyle); #endif + RenderStyle* style() const { return m_style.get(); } + RenderStyle* parentStyle() const { return m_parentStyle; } + Element* element() const { return m_element; } + private: void initForStyleResolve(Element*, RenderStyle* parentStyle = 0, PseudoId = NOPSEUDO); void initElement(Element*); RenderStyle* locateSharedStyle(); bool matchesSiblingRules(); - Node* locateCousinList(Element* parent, unsigned depth = 1) const; + Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const; Node* findSiblingForStyleSharing(Node*, unsigned& count) const; bool canShareStyleWithElement(Node*) const; void pushParentStackFrame(Element* parent); void popParentStackFrame(); - RenderStyle* style() const { return m_style.get(); } - PassRefPtr<RenderStyle> styleForKeyframe(const RenderStyle*, const WebKitCSSKeyframeRule*, KeyframeValue&); public: @@ -156,7 +161,6 @@ public: private: void setFontSize(FontDescription&, float size); static float getComputedSizeFromSpecifiedSize(Document*, RenderStyle*, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules); - public: Color getColorFromPrimitiveValue(CSSPrimitiveValue*) const; @@ -174,8 +178,23 @@ public: void addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule); void addPageStyle(PassRefPtr<CSSPageRule>); + bool usesSiblingRules() const { return m_features.siblingRules; } + bool usesFirstLineRules() const { return m_features.usesFirstLineRules; } + bool usesBeforeAfterRules() const { return m_features.usesBeforeAfterRules; } + bool usesLinkRules() const { return m_features.usesLinkRules; } + static bool createTransformOperations(CSSValue* inValue, RenderStyle* inStyle, RenderStyle* rootStyle, TransformOperations& outOperations); + struct Features { + Features(); + ~Features(); + HashSet<AtomicStringImpl*> idsInRules; + OwnPtr<RuleSet> siblingRules; + bool usesFirstLineRules; + bool usesBeforeAfterRules; + bool usesLinkRules; + }; + private: enum SelectorMatch { SelectorMatches, SelectorFailsLocally, SelectorFailsCompletely }; @@ -192,7 +211,7 @@ public: void matchRules(RuleSet*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); void matchRulesForList(const Vector<RuleData>*, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules); bool fastRejectSelector(const RuleData&) const; - void sortMatchedRules(unsigned start, unsigned end); + void sortMatchedRules(); bool checkSelector(const RuleData&); @@ -208,10 +227,9 @@ public: OwnPtr<RuleSet> m_authorStyle; OwnPtr<RuleSet> m_userStyle; - - OwnPtr<RuleSet> m_siblingRules; - HashSet<AtomicStringImpl*> m_idsInRules; - + + Features m_features; + struct ParentStackFrame { ParentStackFrame() {} ParentStackFrame(Element* element) : element(element) {} @@ -242,7 +260,7 @@ public: bool checkSelector(CSSSelector*, Element*) const; SelectorMatch checkSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* = 0, RenderStyle* elementParentStyle = 0) const; - bool checkOneSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle*, RenderStyle* elementParentStyle) const; + bool checkOneSelector(CSSSelector*, Element*, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle*, RenderStyle* elementParentStyle) const; bool checkScrollbarPseudoClass(CSSSelector*, PseudoId& dynamicPseudo) const; static bool fastCheckSelector(const CSSSelector*, const Element*); @@ -341,6 +359,8 @@ public: HashSet<AtomicStringImpl*> m_selectorAttrs; Vector<CSSMutableStyleDeclaration*> m_additionalAttributeStyleDecls; Vector<MediaQueryResult*> m_viewportDependentMediaQueryResults; + + const CSSStyleApplyProperty& m_applyProperty; }; } // namespace WebCore diff --git a/Source/WebCore/css/CSSValue.h b/Source/WebCore/css/CSSValue.h index e8053fe..de46ff9 100644 --- a/Source/WebCore/css/CSSValue.h +++ b/Source/WebCore/css/CSSValue.h @@ -50,6 +50,8 @@ public: virtual String cssText() const = 0; void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented. + virtual bool isMutableValue() const { return false; } + virtual bool isBorderImageValue() const { return false; } virtual bool isCursorImageValue() const { return false; } virtual bool isFontFamilyValue() const { return false; } @@ -63,7 +65,8 @@ public: virtual bool isTimingFunctionValue() const { return false; } virtual bool isValueList() const { return false; } virtual bool isWebKitCSSTransformValue() const { return false; } - + virtual bool isCSSLineBoxContainValue() const { return false; } + #if ENABLE(SVG) virtual bool isSVGColor() const { return false; } virtual bool isSVGPaint() const { return false; } diff --git a/Source/WebCore/css/CSSValueKeywords.in b/Source/WebCore/css/CSSValueKeywords.in index 4fce4f3..6dac06f 100644 --- a/Source/WebCore/css/CSSValueKeywords.in +++ b/Source/WebCore/css/CSSValueKeywords.in @@ -4,7 +4,7 @@ # -------- # # The Values are sorted according to the properties they belong to, -# and have to be in the same order as the enums in RenderStyle.h. +# and have to be in the same order as the enums in RenderStyleConstants.h. # # If not, the optimizations in the cssparser and style selector will fail, # and produce incorrect results. @@ -212,6 +212,7 @@ justify -webkit-left -webkit-right -webkit-center +-webkit-match-parent # # CSS_PROP_LIST_STYLE_POSITION: # @@ -406,6 +407,7 @@ hand hide higher invert +-webkit-isolate landscape ledger legal @@ -790,3 +792,15 @@ farthest-side farthest-corner # contain # cover + +# -webkit-text-orientation +upright +vertical-right + +# -webkit-line-box-contain +font +glyphs +inline-box +replaced + + diff --git a/Source/WebCore/css/MediaQueryListListener.cpp b/Source/WebCore/css/MediaQueryListListener.cpp index ab73b1d..7512161 100644 --- a/Source/WebCore/css/MediaQueryListListener.cpp +++ b/Source/WebCore/css/MediaQueryListListener.cpp @@ -37,6 +37,11 @@ void MediaQueryListListener::queryChanged(ScriptState* state, MediaQueryList* qu #if USE(JSC) callback.appendArgument(toJS(state, query)); #else + v8::HandleScope handleScope; + v8::Handle<v8::Context> context = state->context(); + if (context.IsEmpty()) + return; // JS may not be enabled. + v8::Context::Scope scope(context); callback.appendArgument(toV8(query)); #endif callback.call(); diff --git a/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp b/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp index 0cf6181..5dfe03e 100644 --- a/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp +++ b/Source/WebCore/css/SVGCSSComputedStyleDeclaration.cpp @@ -27,6 +27,7 @@ #include "CSSPropertyNames.h" #include "Document.h" #include "RenderStyle.h" +#include "SVGPaint.h" namespace WebCore { @@ -59,6 +60,14 @@ static PassRefPtr<CSSValue> strokeDashArrayToCSSValueList(const Vector<SVGLength return list.release(); } +PassRefPtr<SVGPaint> CSSComputedStyleDeclaration::adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint> newPaint, RenderStyle* style) const +{ + RefPtr<SVGPaint> paint = newPaint; + if (paint->paintType() == SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR || paint->paintType() == SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR) + paint->setColor(style->color()); + return paint.release(); +} + PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int propertyID, EUpdateLayout updateLayout) const { Node* node = m_node.get(); @@ -127,13 +136,13 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int pro return CSSPrimitiveValue::create(svgStyle->filterResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyFloodColor: - return CSSPrimitiveValue::createColor(svgStyle->floodColor().rgb()); + return currentColorOrValidColor(style, svgStyle->floodColor()); case CSSPropertyLightingColor: - return CSSPrimitiveValue::createColor(svgStyle->lightingColor().rgb()); + return currentColorOrValidColor(style, svgStyle->lightingColor()); case CSSPropertyStopColor: - return CSSPrimitiveValue::createColor(svgStyle->stopColor().rgb()); + return currentColorOrValidColor(style, svgStyle->stopColor()); case CSSPropertyFill: - return svgStyle->fillPaint(); + return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle->fillPaintType(), svgStyle->fillPaintUri(), svgStyle->fillPaintColor()), style); case CSSPropertyKerning: return SVGLength::toCSSPrimitiveValue(svgStyle->kerning()); case CSSPropertyMarkerEnd: @@ -149,7 +158,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(int pro return CSSPrimitiveValue::create(svgStyle->markerStartResource(), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyStroke: - return svgStyle->strokePaint(); + return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle->strokePaintType(), svgStyle->strokePaintUri(), svgStyle->strokePaintColor()), style); case CSSPropertyStrokeDasharray: return strokeDashArrayToCSSValueList(svgStyle->strokeDashArray()); case CSSPropertyStrokeDashoffset: diff --git a/Source/WebCore/css/SVGCSSParser.cpp b/Source/WebCore/css/SVGCSSParser.cpp index 3c42d40..47f9845 100644 --- a/Source/WebCore/css/SVGCSSParser.cpp +++ b/Source/WebCore/css/SVGCSSParser.cpp @@ -179,17 +179,17 @@ bool CSSParser::parseSVGValue(int propId, bool important) case CSSPropertyStroke: // <paint> | inherit { if (id == CSSValueNone) - parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_NONE); + parsedValue = SVGPaint::createNone(); else if (id == CSSValueCurrentcolor) - parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR); + parsedValue = SVGPaint::createCurrentColor(); else if ((id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu) - parsedValue = SVGPaint::create(RenderTheme::defaultTheme()->systemColor(id)); + parsedValue = SVGPaint::createColor(RenderTheme::defaultTheme()->systemColor(id)); else if (value->unit == CSSPrimitiveValue::CSS_URI) { RGBA32 c = Color::transparent; if (m_valueList->next() && parseColorFromValue(m_valueList->current(), c)) { - parsedValue = SVGPaint::create(value->string, c); + parsedValue = SVGPaint::createURIAndColor(value->string, c); } else - parsedValue = SVGPaint::create(SVGPaint::SVG_PAINTTYPE_URI, value->string); + parsedValue = SVGPaint::createURI(value->string); } else parsedValue = parseSVGPaint(); @@ -201,7 +201,7 @@ bool CSSParser::parseSVGValue(int propId, bool important) case CSSPropertyColor: // <color> | inherit if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen)) - parsedValue = SVGColor::create(value->string); + parsedValue = SVGColor::createFromString(value->string); else parsedValue = parseSVGColor(); @@ -214,7 +214,7 @@ bool CSSParser::parseSVGValue(int propId, bool important) case CSSPropertyLightingColor: if ((id >= CSSValueAqua && id <= CSSValueWindowtext) || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen)) - parsedValue = SVGColor::create(value->string); + parsedValue = SVGColor::createFromString(value->string); else if (id == CSSValueCurrentcolor) parsedValue = SVGColor::createCurrentColor(); else // TODO : svgcolor (iccColor) @@ -339,8 +339,8 @@ PassRefPtr<CSSValue> CSSParser::parseSVGPaint() { RGBA32 c = Color::transparent; if (!parseColorFromValue(m_valueList->current(), c)) - return SVGPaint::create(); - return SVGPaint::create(Color(c)); + return SVGPaint::createUnknown(); + return SVGPaint::createColor(Color(c)); } PassRefPtr<CSSValue> CSSParser::parseSVGColor() @@ -348,11 +348,9 @@ PassRefPtr<CSSValue> CSSParser::parseSVGColor() RGBA32 c = Color::transparent; if (!parseColorFromValue(m_valueList->current(), c)) return 0; - return SVGColor::create(Color(c)); + return SVGColor::createFromColor(Color(c)); } } #endif // ENABLE(SVG) - -// vim:ts=4:noet diff --git a/Source/WebCore/css/SVGCSSStyleSelector.cpp b/Source/WebCore/css/SVGCSSStyleSelector.cpp index 64665d4..47e3fc3 100644 --- a/Source/WebCore/css/SVGCSSStyleSelector.cpp +++ b/Source/WebCore/css/SVGCSSStyleSelector.cpp @@ -231,17 +231,36 @@ void CSSStyleSelector::applySVGProperty(int id, CSSValue* value) // end of ident only properties case CSSPropertyFill: { - HANDLE_INHERIT_AND_INITIAL(fillPaint, FillPaint) - if (value->isSVGPaint()) - svgstyle->setFillPaint(static_cast<SVGPaint*>(value)); + if (isInherit) { + const SVGRenderStyle* svgParentStyle = m_parentStyle->svgStyle(); + svgstyle->setFillPaint(svgParentStyle->fillPaintType(), svgParentStyle->fillPaintColor(), svgParentStyle->fillPaintUri()); + return; + } + if (isInitial) { + svgstyle->setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRenderStyle::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri()); + return; + } + if (value->isSVGPaint()) { + SVGPaint* svgPaint = static_cast<SVGPaint*>(value); + svgstyle->setFillPaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, m_style->color()), svgPaint->uri()); + } break; } case CSSPropertyStroke: { - HANDLE_INHERIT_AND_INITIAL(strokePaint, StrokePaint) - if (value->isSVGPaint()) - svgstyle->setStrokePaint(static_cast<SVGPaint*>(value)); - + if (isInherit) { + const SVGRenderStyle* svgParentStyle = m_parentStyle->svgStyle(); + svgstyle->setStrokePaint(svgParentStyle->strokePaintType(), svgParentStyle->strokePaintColor(), svgParentStyle->strokePaintUri()); + return; + } + if (isInitial) { + svgstyle->setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRenderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri()); + return; + } + if (value->isSVGPaint()) { + SVGPaint* svgPaint = static_cast<SVGPaint*>(value); + svgstyle->setStrokePaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, m_style->color()), svgPaint->uri()); + } break; } case CSSPropertyStrokeWidth: diff --git a/Source/WebCore/css/StyleSheetList.h b/Source/WebCore/css/StyleSheetList.h index a486511..a019691 100644 --- a/Source/WebCore/css/StyleSheetList.h +++ b/Source/WebCore/css/StyleSheetList.h @@ -50,6 +50,11 @@ public: { m_sheets.swap(sheets); } + + Document* document() + { + return m_doc; + } private: StyleSheetList(Document*); diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp index bf0c463..3b41f43 100644 --- a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp +++ b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp @@ -88,7 +88,14 @@ const WebKitCSSKeyframeRule* WebKitCSSKeyframesRule::item(unsigned index) const void WebKitCSSKeyframesRule::append(WebKitCSSKeyframeRule* rule) { - m_lstCSSRules.get()->append(rule); + if (!rule) + return; + + m_lstCSSRules->append(rule); + rule->setParent(this); + + if (CSSMutableStyleDeclaration* style = rule->style()) + style->setParent(this); } void WebKitCSSKeyframesRule::insertRule(const String& rule) diff --git a/Source/WebCore/css/WebKitCSSMatrix.cpp b/Source/WebCore/css/WebKitCSSMatrix.cpp index 163eac8..26fe286 100644 --- a/Source/WebCore/css/WebKitCSSMatrix.cpp +++ b/Source/WebCore/css/WebKitCSSMatrix.cpp @@ -52,9 +52,8 @@ WebKitCSSMatrix::~WebKitCSSMatrix() void WebKitCSSMatrix::setMatrixValue(const String& string, ExceptionCode& ec) { - CSSParser p(true); RefPtr<CSSMutableStyleDeclaration> styleDeclaration = CSSMutableStyleDeclaration::create(); - if (p.parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true)) { + if (CSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, true)) { // Convert to TransformOperations. This can fail if a property // requires style (i.e., param uses 'ems' or 'exs') RefPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform); diff --git a/Source/WebCore/css/fullscreen.css b/Source/WebCore/css/fullscreen.css index 2e38c95..537024c 100644 --- a/Source/WebCore/css/fullscreen.css +++ b/Source/WebCore/css/fullscreen.css @@ -7,10 +7,13 @@ } video:-webkit-full-screen { - background-color: black; - width: auto; - height: 100%; - max-width: 100%; + background-color: black !important; + position: static !important; + margin: 0 !important; + height: 100% !important; + width: 100% !important; + -webkit-box-flex: 1 !important; + display: block !important; } img:-webkit-full-screen { diff --git a/Source/WebCore/css/fullscreenQuickTime.css b/Source/WebCore/css/fullscreenQuickTime.css new file mode 100644 index 0000000..80cf9e4 --- /dev/null +++ b/Source/WebCore/css/fullscreenQuickTime.css @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* alternate media controls - Extend fullscreen.css */ + +video:-webkit-full-screen::-webkit-media-controls-panel { + -webkit-box-align: start; + -webkit-box-pack: end; + -webkit-appearance: none; + + bottom: 50px; + left: 50%; + margin-left: -220px; + padding: 12px 0 0 10px; + width: 430px; + height: 48px; + + background-image: -webkit-gradient( + linear, + left top, + left bottom, + color-stop(0, rgba(30, 30, 30, .97)), + color-stop(0.333, rgba(45, 45, 45, .97)), + color-stop(0.35, rgba(25, 25, 25, .97)), + color-stop(0.366, rgba(25, 25, 25, .97)), + color-stop(0.366, rgba(12, 12, 12, .97)), + color-stop(1, rgba(19, 19, 19, .97)) + ); + + -webkit-box-shadow: + inset 0 -1px 1px rgba(0, 0, 0, 0.5), + inset 0 1px 0 0px rgba(255, 255, 255, 0.15), + inset 0 -1px 0 0px rgba(202, 202, 202, 0.09), + 0 0 0 1px rgba(0, 0, 0, 0.5); + -webkit-border-radius: 8px; +} + +video:-webkit-full-screen::-webkit-media-controls-mute-button { + display: none; +} + +video:-webkit-full-screen::-webkit-media-controls-volume-slider-container { + display: none; +} + +video:-webkit-full-screen::-webkit-media-controls-volume-slider { + display: none; +} + +video:-webkit-full-screen::-webkit-media-controls-volume-slider-mute-button { + display: none; +} + +video:-webkit-full-screen::-webkit-media-controls-fullscreen-volume-min-button { + -webkit-appearance: media-mute-button; + display: block; + position: absolute; + left: 11px; + top: 15px; + width: 14px; + height: 12px; +} + +video:-webkit-full-screen::-webkit-media-controls-fullscreen-volume-slider { + -webkit-appearance: media-slider; + display: block; + position: absolute; + left: 28px; + top: 15px; + height: 12px; + width: 50px; +} + +video:-webkit-full-screen::-webkit-media-controls-fullscreen-volume-max-button { + -webkit-appearance: media-mute-button; + display: block; + position: absolute; + left: 84px; + top: 15px; + width: 14px; + height: 12px; +} + +video:-webkit-full-screen::-webkit-media-controls-play-button { + position: absolute; + width: 22px; + height: 23px; + left: 209px; + top: 9px; +} + +video:-webkit-full-screen::-webkit-media-controls-rewind-button { + position: absolute; + left: 162px; + top: 13px; + width: 18px; + height: 18px; +} + +video:-webkit-full-screen::-webkit-media-controls-seek-back-button { + position: absolute; + display: -webkit-box; + width: 23px; + height: 16px; + left: 162px; + top: 13px; +} + +video:-webkit-full-screen::-webkit-media-controls-seek-forward-button { + position: absolute; + display: -webkit-box; + width: 23px; + height: 16px; + left: 262px; + top: 13px; +} + +video:-webkit-full-screen::-webkit-media-controls-timeline-container { + height: auto; + width: 420px; + position: absolute; + bottom: 9px; + left: 8px; + right: 8px; +} + +video:-webkit-full-screen::video::-webkit-media-controls-status-display { + width: 420px; + position: absolute; + bottom: 9px; + left: 8px; + right: 8px; +} diff --git a/Source/WebCore/css/html.css b/Source/WebCore/css/html.css index 0f13fcb..ecbaef9 100644 --- a/Source/WebCore/css/html.css +++ b/Source/WebCore/css/html.css @@ -113,13 +113,11 @@ q { } q:before { - content: '"' - /* FIXME: content: open-quote; */ + content: open-quote; } q:after { - content: '"' - /* FIXME: content: close-quote; */ + content: close-quote; } center { @@ -154,6 +152,36 @@ h1 { font-weight: bold } +:-webkit-any(article,aside,nav,section) h1 { + font-size: 1.5em; + -webkit-margin-before: 0.83__qem; + -webkit-margin-after: 0.83em; +} + +:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { + font-size: 1.17em; + -webkit-margin-before: 1__qem; + -webkit-margin-after: 1em; +} + +:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { + font-size: 1.00em; + -webkit-margin-before: 1.33__qem; + -webkit-margin-after: 1.33em; +} + +:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { + font-size: .83em; + -webkit-margin-before: 1.67__qem; + -webkit-margin-after: 1.67em; +} + +:-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { + font-size: .67em; + -webkit-margin-before: 2.33__qem; + -webkit-margin-after: 2.33em; +} + h2 { display: block; font-size: 1.5em; @@ -418,12 +446,16 @@ input::-webkit-input-list-button { input::-webkit-inner-spin-button { -webkit-appearance: inner-spin-button; display: inline-block; + position: relative; + cursor: default; -webkit-user-select: none; } input::-webkit-outer-spin-button { -webkit-appearance: outer-spin-button; display: inline-block; + position: relative; + cursor: default; margin-left: 2px; -webkit-user-select: none; } @@ -478,6 +510,7 @@ input[type="file"] { input:-webkit-autofill { background-color: #FAFFBD !important; background-image:none !important; + color: #000000 !important; } input[type="radio"], input[type="checkbox"] { @@ -589,125 +622,114 @@ output { /* form validation message bubble */ ::-webkit-validation-bubble { - display: block; + display: inline-block; z-index: 2147483647; position: absolute; - opacity: 0.9; + opacity: 0.95; line-height: 0; + margin: 0; -webkit-text-security: none; -webkit-transition: opacity 05.5s ease; } ::-webkit-validation-bubble-message { display: block; + position: relative; + top: -4px; font: message-box; + color: black; min-width: 50px; max-width: 200px; - border: solid 2px black; - background: -webkit-gradient(linear, left top, left bottom, from(#fbf9f9), to(#f0e4e4)); + border: solid 2px #400; + background: -webkit-gradient(linear, left top, left bottom, from(#f8ecec), to(#e8cccc)); padding: 8px; -webkit-border-radius: 8px; - -webkit-box-shadow: 4px 4px 4px rgba(204,204,204,0.7); + -webkit-box-shadow: 4px 4px 4px rgba(100,100,100,0.6), + inset -2px -2px 1px #d0c4c4, + inset 2px 2px 1px white; line-height: normal; + z-index: 2147483644; } -::-webkit-validation-bubble-top-outer-arrow { +::-webkit-validation-bubble-arrow { display: inline-block; position: relative; - left: 14px; - height: 0; - width: 0; + left: 32px; + width: 16px; + height: 16px; + background-color: #f8ecec; + border-width: 2px 0 0 2px; border-style: solid; - border-width: 14px; - border-bottom-color: black; - border-right-color: transparent; - border-top-width: 0; - border-left-width: 0; + border-color: #400; + box-shadow: inset 2px 2px 1px white; + -webkit-transform-origin: 0 0; + -webkit-transform: rotate(45deg); + z-index: 2147483645; } -::-webkit-validation-bubble-top-inner-arrow { - display: inline-block; - height: 0; - width: 0; - border-style: solid; - border-width: 10px; /* <border box width of outer-arrow> - <message border width> * 2 */ - border-bottom-color: #fbf9f9; - border-right-color: transparent; - border-top-width: 0; - border-left-width: 0; - position: relative; - top: 2px; /* <message border width> */ - left: 2px; /* <outer-arrow position> + <message border width> - <border box width of outer-arrow> */ +::-webkit-validation-bubble-arrow-clipper { + display: block; + overflow: hidden; + height: 16px; } /* meter */ meter { -webkit-appearance: meter; - display: inline-block; + -webkit-box-sizing: border-box; + display: inline-box; height: 1em; width: 5em; vertical-align: -0.2em; } -meter::-webkit-meter { - -webkit-appearance: meter; -} - -meter::-webkit-meter-horizontal-bar { - -webkit-appearance: meter; +meter::-webkit-meter-bar { background: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#ddd), color-stop(0.20, #eee), color-stop(0.45, #ccc), color-stop(0.55, #ccc)); + height: 100%; + -webkit-box-sizing: border-box; } -meter::-webkit-meter-vertical-bar { - -webkit-appearance: meter; - background: -webkit-gradient(linear, left top, right top, from(#ddd), to(#ddd), color-stop(0.20, #eee), color-stop(0.45, #ccc), color-stop(0.55, #ccc)); -} - -meter::-webkit-meter-horizontal-optimum-value { - -webkit-appearance: meter; +meter::-webkit-meter-optimum-value { background: -webkit-gradient(linear, left top, left bottom, from(#ad7), to(#ad7), color-stop(0.20, #cea), color-stop(0.45, #7a3), color-stop(0.55, #7a3)); + height: 100%; + -webkit-box-sizing: border-box; } -meter::-webkit-meter-horizontal-suboptimal-value { - -webkit-appearance: meter; +meter::-webkit-meter-suboptimum-value { background: -webkit-gradient(linear, left top, left bottom, from(#fe7), to(#fe7), color-stop(0.20, #ffc), color-stop(0.45, #db3), color-stop(0.55, #db3)); + height: 100%; + -webkit-box-sizing: border-box; } -meter::-webkit-meter-horizontal-even-less-good-value { - -webkit-appearance: meter; +meter::-webkit-meter-even-less-good-value { background: -webkit-gradient(linear, left top, left bottom, from(#f77), to(#f77), color-stop(0.20, #fcc), color-stop(0.45, #d44), color-stop(0.55, #d44)); -} - -meter::-webkit-meter-vertical-optimum-value { - -webkit-appearance: meter; - background: -webkit-gradient(linear, left top, right top, from(#ad7), to(#ad7), color-stop(0.20, #cea), color-stop(0.45, #7a3), color-stop(0.55, #7a3)); -} - -meter::-webkit-meter-vertical-suboptimal-value { - -webkit-appearance: meter; - background: -webkit-gradient(linear, left top, right top, from(#fe7), to(#fe7), color-stop(0.20, #ffc), color-stop(0.45, #db3), color-stop(0.55, #db3)); -} - -meter::-webkit-meter-vertical-even-less-good-value { - -webkit-appearance: meter; - background: -webkit-gradient(linear, left top, right top, from(#f77), to(#f77), color-stop(0.20, #fcc), color-stop(0.45, #d44), color-stop(0.55, #d44)); + height: 100%; + -webkit-box-sizing: border-box; } /* progress */ progress { -webkit-appearance: progress-bar; + -webkit-box-sizing: border-box; display: inline-block; height: 1em; width: 10em; vertical-align: -0.2em; +} + +progress::-webkit-progress-bar { background-color: gray; + height: 100%; + -webkit-box-sizing: border-box; } -progress::-webkit-progress-bar-value { - -webkit-appearance: progress-bar; +progress::-webkit-progress-value { background-color: green; + height: 100%; + width: 50%; /* should be removed later */ + -webkit-box-sizing: border-box; } /* datagrid */ @@ -832,7 +854,7 @@ rt { ruby > rt { display: block; font-size: 50%; - text-align: center; + text-align: -webkit-auto; } ruby > rp { @@ -865,6 +887,13 @@ summary { display: block } +summary::-webkit-details-marker { + display: inline-block; + width: 0.66em; + height: 0.66em; + margin-right: 0.4em; +} + /* page */ @page { diff --git a/Source/WebCore/css/mediaControls.css b/Source/WebCore/css/mediaControls.css index 88144b4..da61460 100644 --- a/Source/WebCore/css/mediaControls.css +++ b/Source/WebCore/css/mediaControls.css @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +29,13 @@ audio { height: 16px; } +::-webkit-media-controls { + width: inherit; + height: inherit; + position: relative; + display: block; +} + audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { display: -webkit-box; -webkit-box-orient: horizontal; @@ -44,7 +51,7 @@ audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { } video:-webkit-full-page-media::-webkit-media-controls-panel { - bottom: -16px; + bottom: 0px; } audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { @@ -98,12 +105,7 @@ audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline { margin: initial; } -audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container { - display: none; -} - audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider { - display: none; background-color: initial; border: initial; color: inherit; @@ -171,3 +173,15 @@ audio::-webkit-media-controls-volume-slider-mute-button, video::-webkit-media-co border: initial; color: inherit; } + +audio::-webkit-media-controls-fullscreen-volume-slider, video::-webkit-media-controls-fullscreen-volume-slider { + display: none; +} + +audio::-webkit-media-controls-fullscreen-volume-min-button, video::-webkit-media-controls-fullscreen-volume-min-button { + display: none; +} + +audio::-webkit-media-controls-fullscreen-volume-max-button, video::-webkit-media-controls-fullscreen-volume-max-button { + display: none; +} diff --git a/Source/WebCore/css/mediaControlsChromium.css b/Source/WebCore/css/mediaControlsChromium.css index b8adc2c..60c7d62 100644 --- a/Source/WebCore/css/mediaControlsChromium.css +++ b/Source/WebCore/css/mediaControlsChromium.css @@ -42,7 +42,7 @@ audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { } video:-webkit-full-page-media::-webkit-media-controls-panel { - bottom: -32px; + bottom: 0px; } audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { diff --git a/Source/WebCore/css/mediaControlsEfl.css b/Source/WebCore/css/mediaControlsEfl.css new file mode 100644 index 0000000..43d2698 --- /dev/null +++ b/Source/WebCore/css/mediaControlsEfl.css @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* EFLWebKit media controls. Extends mediaControls.css */ + +audio { + width: 200px; + height: 25px; +} + +audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: center; + -webkit-user-select: none; + position: absolute; + bottom: 0; + width: 100%; + z-index: 0; + overflow: hidden; + height: 25px; + text-align: right; +} + +video:-webkit-full-page-media::-webkit-media-controls-panel { + bottom: 0px; +} + +audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { + -webkit-appearance: media-mute-button; + display: -webkit-box; + width: 25px; + height: 25px; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { + -webkit-appearance: media-play-button; + display: -webkit-box; + width: 25px; + height: 25px; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container { + -webkit-appearance: media-controls-background; + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: center; + -webkit-box-pack: end; + -webkit-box-flex: 1; + -webkit-user-select: none; + height: 25px; +} + +audio::-webkit-media-controls-current-time-display, video::-webkit-media-controls-current-time-display { + display: none; +} + +audio::-webkit-media-controls-time-remaining-display, video::-webkit-media-controls-time-remaining-display { + display: none; +} + +audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline { + -webkit-appearance: media-slider; + display: -webkit-box; + -webkit-box-flex: 1; + height: 25px; + padding: 0px 2px; + background-color: initial; + border: initial; + color: inherit; + margin: initial; +} + +audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container { + display: none; +} + +audio::-webkit-media-controls-volume-slider, video::-webkit-media-controls-volume-slider { + display: none; + background-color: initial; + border: initial; + color: inherit; + margin: initial; +} + +audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button { + -webkit-appearance: media-seek-back-button; + display: -webkit-box; + width: 25px; + height: 25px; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button { + -webkit-appearance: media-seek-forward-button; + display: -webkit-box; + width: 25px; + height: 25px; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button { + -webkit-appearance: media-fullscreen-button; + display: -webkit-box; + width: 25px; + height: 25px; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-rewind-button, video::-webkit-media-controls-rewind-button { + display: none; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-controls-return-to-realtime-button { + display: none; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-media-controls-toggle-closed-captions-button { + -webkit-appearance: media-toggle-closed-captions-button; + display: -webkit-box; + width: 25px; + height: 25px; + background-color: initial; + border: initial; + color: inherit; +} + +audio::-webkit-media-controls-volume-slider-mute-button, video::-webkit-media-controls-volume-slider-mute-button { + -webkit-appearance: media-volume-slider-mute-button; + display: none; + background-color: initial; + border: initial; + color: inherit; +} diff --git a/Source/WebCore/css/mediaControlsQt.css b/Source/WebCore/css/mediaControlsQt.css index 9ca3313..e32fcd5 100644 --- a/Source/WebCore/css/mediaControlsQt.css +++ b/Source/WebCore/css/mediaControlsQt.css @@ -69,6 +69,7 @@ audio::-webkit-media-controls-mute-button { height: 12px; padding: 6px; margin: 5px 5px 5px 3px; + border: none !important; } video::-webkit-media-controls-mute-button { @@ -76,6 +77,7 @@ video::-webkit-media-controls-mute-button { height: 12px; padding: 6px; margin: 5px 5px 5px 3px; + border: none !important; } audio::-webkit-media-controls-play-button { @@ -83,6 +85,7 @@ audio::-webkit-media-controls-play-button { height: 12px; padding: 6px 12px 6px 11px; margin: 5px 3px 5px 5px; + border: none !important; } video::-webkit-media-controls-play-button { @@ -90,6 +93,7 @@ video::-webkit-media-controls-play-button { height: 12px; padding: 6px 12px 6px 11px; margin: 5px 3px 5px 5px; + border: none !important; } audio::-webkit-media-controls-timeline-container { @@ -219,6 +223,7 @@ video::-webkit-media-controls-fullscreen-button { height: 12px; padding: 6px; margin: 5px 5px 5px 3px; + border: none !important; } audio::-webkit-media-controls-rewind-button { diff --git a/Source/WebCore/css/mediaControlsQuickTime.css b/Source/WebCore/css/mediaControlsQuickTime.css index 06f31ae..5866a91 100644 --- a/Source/WebCore/css/mediaControlsQuickTime.css +++ b/Source/WebCore/css/mediaControlsQuickTime.css @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,7 +37,7 @@ audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { } video:-webkit-full-page-media::-webkit-media-controls-panel { - bottom: -25px; + bottom: 0px; } audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button { @@ -47,6 +47,7 @@ audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-bu height: 12px; margin-left: 2px; margin-right: 9px; + border: none !important; } audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { @@ -54,6 +55,7 @@ audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-bu height: 16px; margin-left: 6px; margin-right: 1px; + border: none !important; } audio::-webkit-media-controls-timeline-container, video::-webkit-media-controls-timeline-container { @@ -122,11 +124,13 @@ audio::-webkit-media-controls-timeline, video::-webkit-media-controls-timeline { audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button { display: none; width: 0px; + border: none !important; } audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button { display: none; width: 0px; + border: none !important; } audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button { @@ -135,6 +139,7 @@ audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-f margin-left: 7px; margin-right: 7px; -webkit-box-ordinal-group: 4; /* At the very end */ + border: none !important; } audio::-webkit-media-controls-rewind-button, video::-webkit-media-controls-rewind-button { @@ -145,6 +150,7 @@ audio::-webkit-media-controls-rewind-button, video::-webkit-media-controls-rewin margin-bottom: 1px; margin-left: 6px; margin-right: 2px; + border: none !important; } audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-controls-return-to-realtime-button { @@ -154,6 +160,7 @@ audio::-webkit-media-controls-return-to-realtime-button, video::-webkit-media-co height: 11px; margin-left: 6px; margin-right: 2px; + border: none !important; } audio::-webkit-media-controls-status-display, video::-webkit-media-controls-status-display { @@ -186,6 +193,7 @@ audio::-webkit-media-controls-toggle-closed-captions-button, video::-webkit-medi margin-left: 7px; margin-right: 7px; -webkit-box-ordinal-group: 3; /* between mute and fullscreen */ + border: none !important; } audio::-webkit-media-controls-volume-slider-container, video::-webkit-media-controls-volume-slider-container { @@ -221,4 +229,5 @@ audio::-webkit-media-controls-volume-slider-mute-button, video::-webkit-media-co width: 14px; height: 12px; + border: none !important; } diff --git a/Source/WebCore/css/themeChromiumLinux.css b/Source/WebCore/css/themeChromiumLinux.css index bd7f961..a6a8828 100644 --- a/Source/WebCore/css/themeChromiumLinux.css +++ b/Source/WebCore/css/themeChromiumLinux.css @@ -32,9 +32,9 @@ select { background-color: #dddddd; - border: 0px; } +select:not([size]):not([multiple]) option, select[size="0"] option, select[size="1"] option { background-color: #f7f7f7; diff --git a/Source/WebCore/css/themeQtMobile.css b/Source/WebCore/css/themeQtMobile.css deleted file mode 100644 index 27be523..0000000 --- a/Source/WebCore/css/themeQtMobile.css +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -input[type="button"], -input[type="submit"], -input[type="reset"], -input[type="file"]::-webkit-file-upload-button, button, -select { - padding: 2px 18px 3px 18px; - border: 1px solid gray; - -webkit-border-radius:5px; - background: -webkit-gradient(linear, left bottom, left top, color-stop(0.0, rgba(0, 0, 0, 0.35)), color-stop(0.4, rgba(0, 0, 0, 0.0))); - background-color: #ffffff; - color: #3e3e3e; -} - -input[type="button"]:disabled, -input[type="submit"]:disabled, -input[type="reset"]:disabled, -input[type="file"]:disabled::-webkit-file-upload-button, -button:disabled, -select:disabled { - border: 1px solid gray; -} - -input[type="button"]:active, -input[type="submit"]:active, -input[type="reset"]:active, -input[type="file"]:active::-webkit-file-upload-button, -button:active, -select:active { - background: ButtonShadow; -} - -input[type="button"]:active:disabled, -input[type="submit"]:active:disabled, -input[type="reset"]:active:disabled, -input[type="file"]:active:disabled::-webkit-file-upload-button, -button:active:disabled, -select:active:disabled { - border: 1px solid gray; -} - -input:not([type]), -input[type="text"], -input[type="password"], -input[type="email"], -input[type="tel"], -input[type="color"], -input[type="search"], -input[type="date"], -input[type="datetime"], -input[type="datetime-local"], -input[type="month"], -input[type="week"], -input[type="time"], -input[type="number"], -input[type="url"], -textarea { - border: 1px solid gray; - background: -webkit-gradient(linear, left top, left 30, color-stop(0.0, rgba(0, 0, 0, 0.35)), color-stop(0.2, rgba(0, 0, 0, 0.0))); - background-color: #ffffff; - color: #3e3e3e; - -webkit-border-radius:5px; -} - -input:not([type]):disabled, -input[type="text"]:disabled, -input[type="password"]:disabled, -input[type="email"]:disabled, -input[type="tel"]:disabled, -input[type="color"]:disabled, -input[type="search"]:disabled, -input[type="date"]:disabled, -input[type="datetime"]:disabled, -input[type="datetime-local"]:disabled, -input[type="month"]:disabled, -input[type="week"]:disabled, -input[type="time"]:disabled, -input[type="number"]:disabled, -input[type="url"]:disabled, -textarea:disabled { - border: 1px solid gray; - background: -webkit-gradient(linear, left top, left 30, color-stop(0.0, rgba(0, 0, 0, 0.3)), color-stop(0.2, rgba(0, 0, 0, 0.0))); - background-color: #ffffff; - color: #e5e5e5; -} - -input:not([type]):active, -input[type="text"]:active, -input[type="password"]:active, -input[type="email"]:active, -input[type="tel"]:active, -input[type="color"]:active, -input[type="search"]:active, -input[type="date"]:active, -input[type="datetime"]:active, -input[type="datetime-local"]:active, -input[type="month"]:active, -input[type="week"]:active, -input[type="time"]:active, -input[type="number"]:active, -input[type="url"]:active, -textarea:active { - background: ButtonShadow; -} - -video { - background-color: #000000; -} diff --git a/Source/WebCore/css/tokenizer.flex b/Source/WebCore/css/tokenizer.flex index eb18cb9..3285d2f 100644 --- a/Source/WebCore/css/tokenizer.flex +++ b/Source/WebCore/css/tokenizer.flex @@ -15,7 +15,6 @@ string1 \"([\t !#$%&(-~]|\\{nl}|\'|{nonascii}|{escape})*\" string2 \'([\t !#$%&(-~]|\\{nl}|\"|{nonascii}|{escape})*\' ident -?{nmstart}{nmchar}* -name {nmchar}+ num [0-9]+|[0-9]*"."[0-9]+ intnum [0-9]+ string {string1}|{string2} @@ -46,8 +45,8 @@ nth [\+-]?{intnum}*n([\t\r\n ]*[\+-][\t\r\n ]*{intnum})? {ident} {yyTok = IDENT; return yyTok;} {nth} {yyTok = NTH; return yyTok;} +"#"{h}+ {yyTok = HEX; return yyTok;} "#"{ident} {yyTok = IDSEL; return yyTok;} -"#"{name} {yyTok = HEX; return yyTok;} "@import" {BEGIN(mediaquery); yyTok = IMPORT_SYM; return yyTok;} "@page" {yyTok = PAGE_SYM; return yyTok;} @@ -102,13 +101,18 @@ nth [\+-]?{intnum}*n([\t\r\n ]*[\+-][\t\r\n ]*{intnum})? {num}Hz {yyTok = HERTZ; return yyTok;} {num}kHz {yyTok = KHERTZ; return yyTok;} {num}{ident} {yyTok = DIMEN; return yyTok;} +{num}{ident}\+ {yyTok = INVALIDDIMEN; return yyTok;} {num}%+ {yyTok = PERCENTAGE; return yyTok;} {intnum} {yyTok = INTEGER; return yyTok;} {num} {yyTok = FLOATTOKEN; return yyTok;} +"-webkit-any(" {yyTok = ANYFUNCTION; return yyTok;} "not(" {yyTok = NOTFUNCTION; return yyTok;} "url("{w}{string}{w}")" {yyTok = URI; return yyTok;} "url("{w}{url}{w}")" {yyTok = URI; return yyTok;} +"-webkit-calc(" {yyTok = CALCFUNCTION; return yyTok;} +"-webkit-min(" {yyTok = MINFUNCTION; return yyTok;} +"-webkit-max(" {yyTok = MAXFUNCTION; return yyTok;} {ident}"(" {yyTok = FUNCTION; return yyTok;} U\+{range} {yyTok = UNICODERANGE; return yyTok;} diff --git a/Source/WebCore/css/wml.css b/Source/WebCore/css/wml.css index 4bcf08f..38169fc 100644 --- a/Source/WebCore/css/wml.css +++ b/Source/WebCore/css/wml.css @@ -147,6 +147,7 @@ input[type="password"] { input:-webkit-autofill { background-color: #FAFFBD !important; background-image:none !important; + color: #000000 !important; } do:disabled, select:disabled, optgroup:disabled, option:disabled { |