diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/css | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/css')
371 files changed, 22809 insertions, 17401 deletions
diff --git a/chromium/third_party/WebKit/Source/core/css/AffectedByFocusTest.cpp b/chromium/third_party/WebKit/Source/core/css/AffectedByFocusTest.cpp new file mode 100644 index 00000000000..c2c4467ba29 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/AffectedByFocusTest.cpp @@ -0,0 +1,316 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/HTMLNames.h" +#include "core/dom/Element.h" +#include "core/dom/ElementTraversal.h" +#include "core/dom/NodeRenderStyle.h" +#include "core/frame/FrameView.h" +#include "core/html/HTMLDocument.h" +#include "core/html/HTMLElement.h" +#include "core/testing/DummyPageHolder.h" +#include <gtest/gtest.h> + +using namespace WebCore; +using namespace HTMLNames; + +namespace { + +class AffectedByFocusTest : public ::testing::Test { + +protected: + + struct ElementResult { + const WebCore::QualifiedName tag; + bool affectedBy; + bool childrenOrSiblingsAffectedBy; + }; + + virtual void SetUp() OVERRIDE; + + HTMLDocument& document() const { return *m_document; } + + void setHtmlInnerHTML(const char* htmlContent); + + void checkElements(ElementResult expected[], unsigned expectedCount) const; + +private: + OwnPtr<DummyPageHolder> m_dummyPageHolder; + + HTMLDocument* m_document; +}; + +void AffectedByFocusTest::SetUp() +{ + m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); + m_document = toHTMLDocument(&m_dummyPageHolder->document()); + ASSERT(m_document); +} + +void AffectedByFocusTest::setHtmlInnerHTML(const char* htmlContent) +{ + document().documentElement()->setInnerHTML(String::fromUTF8(htmlContent), ASSERT_NO_EXCEPTION); + document().view()->updateLayoutAndStyleIfNeededRecursive(); +} + +void AffectedByFocusTest::checkElements(ElementResult expected[], unsigned expectedCount) const +{ + unsigned i = 0; + Element* elm = document().body(); + + for (; elm && i < expectedCount; elm = ElementTraversal::next(*elm), ++i) { + ASSERT_TRUE(elm->hasTagName(expected[i].tag)); + ASSERT(elm->renderStyle()); + ASSERT_EQ(expected[i].affectedBy, elm->renderStyle()->affectedByFocus()); + ASSERT_EQ(expected[i].childrenOrSiblingsAffectedBy, elm->childrenOrSiblingsAffectedByFocus()); + } + + ASSERT(!elm && i == expectedCount); +} + +// A global :focus rule in html.css currently causes every single element to be +// affectedByFocus. Check that all elements in a document with no :focus rules +// gets the affectedByFocus set on RenderStyle and not childrenOrSiblingsAffectedByFocus. +TEST_F(AffectedByFocusTest, UAUniversalFocusRule) +{ + ElementResult expected[] = { + { bodyTag, true, false }, + { divTag, true, false }, + { divTag, true, false }, + { divTag, true, false }, + { spanTag, true, false } + }; + + setHtmlInnerHTML("<body>" + "<div><div></div></div>" + "<div><span></span></div>" + "</body>"); + + checkElements(expected, sizeof(expected) / sizeof(ElementResult)); +} + +// ":focus div" will mark ascendants of all divs with childrenOrSiblingsAffectedByFocus. +TEST_F(AffectedByFocusTest, FocusedAscendant) +{ + ElementResult expected[] = { + { bodyTag, true, true }, + { divTag, true, true }, + { divTag, true, false }, + { divTag, true, false }, + { spanTag, true, false } + }; + + setHtmlInnerHTML("<head>" + "<style>:focus div { background-color: pink }</style>" + "</head>" + "<body>" + "<div><div></div></div>" + "<div><span></span></div>" + "</body>"); + + checkElements(expected, sizeof(expected) / sizeof(ElementResult)); +} + +// "body:focus div" will mark the body element with childrenOrSiblingsAffectedByFocus. +TEST_F(AffectedByFocusTest, FocusedAscendantWithType) +{ + ElementResult expected[] = { + { bodyTag, true, true }, + { divTag, true, false }, + { divTag, true, false }, + { divTag, true, false }, + { spanTag, true, false } + }; + + setHtmlInnerHTML("<head>" + "<style>body:focus div { background-color: pink }</style>" + "</head>" + "<body>" + "<div><div></div></div>" + "<div><span></span></div>" + "</body>"); + + checkElements(expected, sizeof(expected) / sizeof(ElementResult)); +} + +// ":not(body):focus div" should not mark the body element with childrenOrSiblingsAffectedByFocus. +// Note that currently ":focus:not(body)" does not do the same. Then the :focus is +// checked and the childrenOrSiblingsAffectedByFocus flag set before the negated type selector +// is found. +TEST_F(AffectedByFocusTest, FocusedAscendantWithNegatedType) +{ + ElementResult expected[] = { + { bodyTag, true, false }, + { divTag, true, true }, + { divTag, true, false }, + { divTag, true, false }, + { spanTag, true, false } + }; + + setHtmlInnerHTML("<head>" + "<style>:not(body):focus div { background-color: pink }</style>" + "</head>" + "<body>" + "<div><div></div></div>" + "<div><span></span></div>" + "</body>"); + + checkElements(expected, sizeof(expected) / sizeof(ElementResult)); +} + +// Checking current behavior for ":focus + div", but this is a BUG or at best +// sub-optimal. The focused element will also in this case get childrenOrSiblingsAffectedByFocus +// even if it's really a sibling. Effectively, the whole sub-tree of the focused +// element will have styles recalculated even though none of the children are +// affected. There are other mechanisms that makes sure the sibling also gets its +// styles recalculated. +TEST_F(AffectedByFocusTest, FocusedSibling) +{ + ElementResult expected[] = { + { bodyTag, true, false }, + { divTag, true, true }, + { spanTag, true, false }, + { divTag, true, false } + }; + + setHtmlInnerHTML("<head>" + "<style>:focus + div { background-color: pink }</style>" + "</head>" + "<body>" + "<div>" + " <span></span>" + "</div>" + "<div></div>" + "</body>"); + + checkElements(expected, sizeof(expected) / sizeof(ElementResult)); +} + +TEST_F(AffectedByFocusTest, AffectedByFocusUpdate) +{ + // Check that when focussing the outer div in the document below, you only + // get a single element style recalc. + + setHtmlInnerHTML("<style>:focus { border: 1px solid lime; }</style>" + "<div id=d tabIndex=1>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "</div>"); + + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned startCount = document().styleEngine()->resolverAccessCount(); + + document().getElementById("d")->focus(); + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned accessCount = document().styleEngine()->resolverAccessCount() - startCount; + + ASSERT_EQ(1U, accessCount); +} + +TEST_F(AffectedByFocusTest, ChildrenOrSiblingsAffectedByFocusUpdate) +{ + // Check that when focussing the outer div in the document below, you get a + // style recalc for the whole subtree. + + setHtmlInnerHTML("<style>:focus div { border: 1px solid lime; }</style>" + "<div id=d tabIndex=1>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "</div>"); + + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned startCount = document().styleEngine()->resolverAccessCount(); + + document().getElementById("d")->focus(); + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned accessCount = document().styleEngine()->resolverAccessCount() - startCount; + + ASSERT_EQ(11U, accessCount); +} + +TEST_F(AffectedByFocusTest, InvalidationSetFocusUpdate) +{ + // Check that when focussing the outer div in the document below, you get a + // style recalc for the outer div and the class=a div only. + + setHtmlInnerHTML("<style>:focus .a { border: 1px solid lime; }</style>" + "<div id=d tabIndex=1>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div class='a'></div>" + "</div>"); + + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned startCount = document().styleEngine()->resolverAccessCount(); + + document().getElementById("d")->focus(); + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned accessCount = document().styleEngine()->resolverAccessCount() - startCount; + + ASSERT_EQ(2U, accessCount); +} + +TEST_F(AffectedByFocusTest, NoInvalidationSetFocusUpdate) +{ + // Check that when focussing the outer div in the document below, you get a + // style recalc for the outer div only. The invalidation set for :focus will + // include 'a', but the id=d div should be affectedByFocus, not childrenOrSiblingsAffectedByFocus. + + setHtmlInnerHTML("<style>#nomatch:focus .a { border: 1px solid lime; }</style>" + "<div id=d tabIndex=1>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div></div>" + "<div class='a'></div>" + "</div>"); + + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned startCount = document().styleEngine()->resolverAccessCount(); + + document().getElementById("d")->focus(); + document().view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned accessCount = document().styleEngine()->resolverAccessCount() - startCount; + + ASSERT_EQ(1U, accessCount); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp b/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp index a49ea1495f1..e6399b99187 100644 --- a/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp +++ b/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.cpp @@ -33,58 +33,68 @@ #include "core/css/CSSBasicShapes.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSValuePool.h" +#include "core/css/Pair.h" #include "core/css/resolver/StyleResolverState.h" #include "core/rendering/style/BasicShapes.h" #include "core/rendering/style/RenderStyle.h" namespace WebCore { -PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForCenterCoordinate(CSSValuePool& pool, const RenderStyle& style, const BasicShapeCenterCoordinate& center, EBoxOrient orientation) +{ + if (center.direction() == BasicShapeCenterCoordinate::TopLeft) + return pool.createValue(center.length(), style); + + CSSValueID keyword = orientation == HORIZONTAL ? CSSValueRight : CSSValueBottom; + + return pool.createValue(Pair::create(pool.createIdentifierValue(keyword), pool.createValue(center.length(), style), Pair::DropIdenticalValues)); +} + +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> basicShapeRadiusToCSSValue(CSSValuePool& pool, const RenderStyle& style, const BasicShapeRadius& radius) +{ + switch (radius.type()) { + case BasicShapeRadius::Value: + return pool.createValue(radius.value(), style); + case BasicShapeRadius::ClosestSide: + return pool.createIdentifierValue(CSSValueClosestSide); + case BasicShapeRadius::FarthestSide: + return pool.createIdentifierValue(CSSValueFarthestSide); + } + + ASSERT_NOT_REACHED(); + return nullptr; +} + +PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicShape* basicShape) { CSSValuePool& pool = cssValuePool(); - RefPtr<CSSBasicShape> basicShapeValue; + RefPtrWillBeRawPtr<CSSBasicShape> basicShapeValue = nullptr; switch (basicShape->type()) { - case BasicShape::BasicShapeRectangleType: { - const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape); - RefPtr<CSSBasicShapeRectangle> rectangleValue = CSSBasicShapeRectangle::create(); - - rectangleValue->setX(pool.createValue(rectangle->x(), style)); - rectangleValue->setY(pool.createValue(rectangle->y(), style)); - rectangleValue->setWidth(pool.createValue(rectangle->width(), style)); - rectangleValue->setHeight(pool.createValue(rectangle->height(), style)); - rectangleValue->setRadiusX(pool.createValue(rectangle->cornerRadiusX(), style)); - rectangleValue->setRadiusY(pool.createValue(rectangle->cornerRadiusY(), style)); - - basicShapeValue = rectangleValue.release(); - break; - } case BasicShape::BasicShapeCircleType: { const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape); - RefPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); - - circleValue->setCenterX(pool.createValue(circle->centerX(), style)); - circleValue->setCenterY(pool.createValue(circle->centerY(), style)); - circleValue->setRadius(pool.createValue(circle->radius(), style)); + RefPtrWillBeRawPtr<CSSBasicShapeCircle> circleValue = CSSBasicShapeCircle::create(); + circleValue->setCenterX(valueForCenterCoordinate(pool, style, circle->centerX(), HORIZONTAL)); + circleValue->setCenterY(valueForCenterCoordinate(pool, style, circle->centerY(), VERTICAL)); + circleValue->setRadius(basicShapeRadiusToCSSValue(pool, style, circle->radius())); basicShapeValue = circleValue.release(); break; } case BasicShape::BasicShapeEllipseType: { const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape); - RefPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); - - ellipseValue->setCenterX(pool.createValue(ellipse->centerX(), style)); - ellipseValue->setCenterY(pool.createValue(ellipse->centerY(), style)); - ellipseValue->setRadiusX(pool.createValue(ellipse->radiusX(), style)); - ellipseValue->setRadiusY(pool.createValue(ellipse->radiusY(), style)); + RefPtrWillBeRawPtr<CSSBasicShapeEllipse> ellipseValue = CSSBasicShapeEllipse::create(); + ellipseValue->setCenterX(valueForCenterCoordinate(pool, style, ellipse->centerX(), HORIZONTAL)); + ellipseValue->setCenterY(valueForCenterCoordinate(pool, style, ellipse->centerY(), VERTICAL)); + ellipseValue->setRadiusX(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusX())); + ellipseValue->setRadiusY(basicShapeRadiusToCSSValue(pool, style, ellipse->radiusY())); basicShapeValue = ellipseValue.release(); break; } case BasicShape::BasicShapePolygonType: { const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape); - RefPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); + RefPtrWillBeRawPtr<CSSBasicShapePolygon> polygonValue = CSSBasicShapePolygon::create(); polygonValue->setWindRule(polygon->windRule()); const Vector<Length>& values = polygon->values(); @@ -94,65 +104,117 @@ PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle& style, const BasicSha basicShapeValue = polygonValue.release(); break; } - case BasicShape::BasicShapeInsetRectangleType: { - const BasicShapeInsetRectangle* rectangle = static_cast<const BasicShapeInsetRectangle*>(basicShape); - RefPtr<CSSBasicShapeInsetRectangle> rectangleValue = CSSBasicShapeInsetRectangle::create(); - - rectangleValue->setTop(cssValuePool().createValue(rectangle->top())); - rectangleValue->setRight(cssValuePool().createValue(rectangle->right())); - rectangleValue->setBottom(cssValuePool().createValue(rectangle->bottom())); - rectangleValue->setLeft(cssValuePool().createValue(rectangle->left())); - rectangleValue->setRadiusX(cssValuePool().createValue(rectangle->cornerRadiusX())); - rectangleValue->setRadiusY(cssValuePool().createValue(rectangle->cornerRadiusY())); - - basicShapeValue = rectangleValue.release(); + case BasicShape::BasicShapeInsetType: { + const BasicShapeInset* inset = static_cast<const BasicShapeInset*>(basicShape); + RefPtrWillBeRawPtr<CSSBasicShapeInset> insetValue = CSSBasicShapeInset::create(); + + insetValue->setTop(pool.createValue(inset->top(), style)); + insetValue->setRight(pool.createValue(inset->right(), style)); + insetValue->setBottom(pool.createValue(inset->bottom(), style)); + insetValue->setLeft(pool.createValue(inset->left(), style)); + + insetValue->setTopLeftRadius(CSSPrimitiveValue::create(inset->topLeftRadius(), style)); + insetValue->setTopRightRadius(CSSPrimitiveValue::create(inset->topRightRadius(), style)); + insetValue->setBottomRightRadius(CSSPrimitiveValue::create(inset->bottomRightRadius(), style)); + insetValue->setBottomLeftRadius(CSSPrimitiveValue::create(inset->bottomLeftRadius(), style)); + + basicShapeValue = insetValue.release(); break; } default: break; } + return pool.createValue(basicShapeValue.release()); } static Length convertToLength(const StyleResolverState& state, CSSPrimitiveValue* value) { + if (!value) + return Length(0, Fixed); return value->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); } +static LengthSize convertToLengthSize(const StyleResolverState& state, CSSPrimitiveValue* value) +{ + if (!value) + return LengthSize(Length(0, Fixed), Length(0, Fixed)); + + Pair* pair = value->getPairValue(); + return LengthSize(convertToLength(state, pair->first()), convertToLength(state, pair->second())); +} + +static BasicShapeCenterCoordinate convertToCenterCoordinate(const StyleResolverState& state, CSSPrimitiveValue* value) +{ + BasicShapeCenterCoordinate::Direction direction; + Length offset = Length(0, Fixed); + + CSSValueID keyword = CSSValueTop; + if (!value) { + keyword = CSSValueCenter; + } else if (value->isValueID()) { + keyword = value->getValueID(); + } else if (Pair* pair = value->getPairValue()) { + keyword = pair->first()->getValueID(); + offset = convertToLength(state, pair->second()); + } else { + offset = convertToLength(state, value); + } + + switch (keyword) { + case CSSValueTop: + case CSSValueLeft: + direction = BasicShapeCenterCoordinate::TopLeft; + break; + case CSSValueRight: + case CSSValueBottom: + direction = BasicShapeCenterCoordinate::BottomRight; + break; + case CSSValueCenter: + direction = BasicShapeCenterCoordinate::TopLeft; + offset = Length(50, Percent); + break; + default: + ASSERT_NOT_REACHED(); + direction = BasicShapeCenterCoordinate::TopLeft; + break; + } + + return BasicShapeCenterCoordinate(direction, offset); +} + +static BasicShapeRadius cssValueToBasicShapeRadius(const StyleResolverState& state, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) +{ + if (!radius) + return BasicShapeRadius(BasicShapeRadius::ClosestSide); + + if (radius->isValueID()) { + switch (radius->getValueID()) { + case CSSValueClosestSide: + return BasicShapeRadius(BasicShapeRadius::ClosestSide); + case CSSValueFarthestSide: + return BasicShapeRadius(BasicShapeRadius::FarthestSide); + default: + ASSERT_NOT_REACHED(); + break; + } + } + + return BasicShapeRadius(convertToLength(state, radius.get())); +} + PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const CSSBasicShape* basicShapeValue) { RefPtr<BasicShape> basicShape; switch (basicShapeValue->type()) { - case CSSBasicShape::CSSBasicShapeRectangleType: { - const CSSBasicShapeRectangle* rectValue = static_cast<const CSSBasicShapeRectangle *>(basicShapeValue); - RefPtr<BasicShapeRectangle> rect = BasicShapeRectangle::create(); - - rect->setX(convertToLength(state, rectValue->x())); - rect->setY(convertToLength(state, rectValue->y())); - rect->setWidth(convertToLength(state, rectValue->width())); - rect->setHeight(convertToLength(state, rectValue->height())); - if (rectValue->radiusX()) { - Length radiusX = convertToLength(state, rectValue->radiusX()); - rect->setCornerRadiusX(radiusX); - if (rectValue->radiusY()) - rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); - else - rect->setCornerRadiusY(radiusX); - } else { - rect->setCornerRadiusX(Length(0, Fixed)); - rect->setCornerRadiusY(Length(0, Fixed)); - } - basicShape = rect.release(); - break; - } case CSSBasicShape::CSSBasicShapeCircleType: { const CSSBasicShapeCircle* circleValue = static_cast<const CSSBasicShapeCircle *>(basicShapeValue); RefPtr<BasicShapeCircle> circle = BasicShapeCircle::create(); - circle->setCenterX(convertToLength(state, circleValue->centerX())); - circle->setCenterY(convertToLength(state, circleValue->centerY())); - circle->setRadius(convertToLength(state, circleValue->radius())); + circle->setCenterX(convertToCenterCoordinate(state, circleValue->centerX())); + circle->setCenterY(convertToCenterCoordinate(state, circleValue->centerY())); + circle->setRadius(cssValueToBasicShapeRadius(state, circleValue->radius())); basicShape = circle.release(); break; @@ -161,10 +223,10 @@ PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const const CSSBasicShapeEllipse* ellipseValue = static_cast<const CSSBasicShapeEllipse *>(basicShapeValue); RefPtr<BasicShapeEllipse> ellipse = BasicShapeEllipse::create(); - ellipse->setCenterX(convertToLength(state, ellipseValue->centerX())); - ellipse->setCenterY(convertToLength(state, ellipseValue->centerY())); - ellipse->setRadiusX(convertToLength(state, ellipseValue->radiusX())); - ellipse->setRadiusY(convertToLength(state, ellipseValue->radiusY())); + ellipse->setCenterX(convertToCenterCoordinate(state, ellipseValue->centerX())); + ellipse->setCenterY(convertToCenterCoordinate(state, ellipseValue->centerY())); + ellipse->setRadiusX(cssValueToBasicShapeRadius(state, ellipseValue->radiusX())); + ellipse->setRadiusY(cssValueToBasicShapeRadius(state, ellipseValue->radiusY())); basicShape = ellipse.release(); break; @@ -174,38 +236,45 @@ PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState& state, const RefPtr<BasicShapePolygon> polygon = BasicShapePolygon::create(); polygon->setWindRule(polygonValue->windRule()); - const Vector<RefPtr<CSSPrimitiveValue> >& values = polygonValue->values(); + const WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> >& values = polygonValue->values(); for (unsigned i = 0; i < values.size(); i += 2) polygon->appendPoint(convertToLength(state, values.at(i).get()), convertToLength(state, values.at(i + 1).get())); basicShape = polygon.release(); break; } - case CSSBasicShape::CSSBasicShapeInsetRectangleType: { - const CSSBasicShapeInsetRectangle* rectValue = static_cast<const CSSBasicShapeInsetRectangle *>(basicShapeValue); - RefPtr<BasicShapeInsetRectangle> rect = BasicShapeInsetRectangle::create(); + case CSSBasicShape::CSSBasicShapeInsetType: { + const CSSBasicShapeInset* rectValue = static_cast<const CSSBasicShapeInset* >(basicShapeValue); + RefPtr<BasicShapeInset> rect = BasicShapeInset::create(); rect->setTop(convertToLength(state, rectValue->top())); rect->setRight(convertToLength(state, rectValue->right())); rect->setBottom(convertToLength(state, rectValue->bottom())); rect->setLeft(convertToLength(state, rectValue->left())); - if (rectValue->radiusX()) { - Length radiusX = convertToLength(state, rectValue->radiusX()); - rect->setCornerRadiusX(radiusX); - if (rectValue->radiusY()) - rect->setCornerRadiusY(convertToLength(state, rectValue->radiusY())); - else - rect->setCornerRadiusY(radiusX); - } else { - rect->setCornerRadiusX(Length(0, Fixed)); - rect->setCornerRadiusY(Length(0, Fixed)); - } + + rect->setTopLeftRadius(convertToLengthSize(state, rectValue->topLeftRadius())); + rect->setTopRightRadius(convertToLengthSize(state, rectValue->topRightRadius())); + rect->setBottomRightRadius(convertToLengthSize(state, rectValue->bottomRightRadius())); + rect->setBottomLeftRadius(convertToLengthSize(state, rectValue->bottomLeftRadius())); + basicShape = rect.release(); break; } default: break; } + return basicShape.release(); } + +FloatPoint floatPointForCenterCoordinate(const BasicShapeCenterCoordinate& centerX, const BasicShapeCenterCoordinate& centerY, FloatSize boxSize) +{ + FloatPoint p; + float offset = floatValueForLength(centerX.length(), boxSize.width()); + p.setX(centerX.direction() == BasicShapeCenterCoordinate::TopLeft ? offset : boxSize.width() - offset); + offset = floatValueForLength(centerY.length(), boxSize.height()); + p.setY(centerY.direction() == BasicShapeCenterCoordinate::TopLeft ? offset : boxSize.height() - offset); + return p; +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.h b/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.h index 7d07e311a2e..ab1fdcc93ca 100644 --- a/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.h +++ b/chromium/third_party/WebKit/Source/core/css/BasicShapeFunctions.h @@ -30,6 +30,8 @@ #ifndef BasicShapeFunctions_h #define BasicShapeFunctions_h +#include "core/rendering/style/BasicShapes.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" namespace WebCore { @@ -37,11 +39,13 @@ namespace WebCore { class BasicShape; class CSSBasicShape; class CSSValue; +class FloatPoint; class StyleResolverState; class RenderStyle; -PassRefPtr<CSSValue> valueForBasicShape(const RenderStyle&, const BasicShape*); +PassRefPtrWillBeRawPtr<CSSValue> valueForBasicShape(const RenderStyle&, const BasicShape*); PassRefPtr<BasicShape> basicShapeForValue(const StyleResolverState&, const CSSBasicShape*); +FloatPoint floatPointForCenterCoordinate(const BasicShapeCenterCoordinate&, const BasicShapeCenterCoordinate&, FloatSize); } #endif diff --git a/chromium/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp b/chromium/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp new file mode 100644 index 00000000000..c32f8ede4e9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.cpp @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/BinaryDataFontFaceSource.h" + +#include "platform/SharedBuffer.h" +#include "platform/fonts/FontCustomPlatformData.h" +#include "platform/fonts/FontDescription.h" +#include "platform/fonts/SimpleFontData.h" + +namespace WebCore { + +BinaryDataFontFaceSource::BinaryDataFontFaceSource(SharedBuffer* data) + : m_customPlatformData(FontCustomPlatformData::create(data)) +{ +} + +BinaryDataFontFaceSource::~BinaryDataFontFaceSource() +{ +} + +bool BinaryDataFontFaceSource::isValid() const +{ + return m_customPlatformData; +} + +PassRefPtr<SimpleFontData> BinaryDataFontFaceSource::createFontData(const FontDescription& fontDescription) +{ + return SimpleFontData::create( + m_customPlatformData->fontPlatformData(fontDescription.effectiveFontSize(), + fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(), + fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.h b/chromium/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.h new file mode 100644 index 00000000000..766bbbb3b32 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/BinaryDataFontFaceSource.h @@ -0,0 +1,30 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BinaryDataFontFaceSource_h +#define BinaryDataFontFaceSource_h + +#include "core/css/CSSFontFaceSource.h" +#include "wtf/OwnPtr.h" + +namespace WebCore { + +class FontCustomPlatformData; +class SharedBuffer; + +class BinaryDataFontFaceSource FINAL : public CSSFontFaceSource { +public: + explicit BinaryDataFontFaceSource(SharedBuffer*); + virtual ~BinaryDataFontFaceSource(); + virtual bool isValid() const OVERRIDE; + +private: + virtual PassRefPtr<SimpleFontData> createFontData(const FontDescription&) OVERRIDE; + + OwnPtr<FontCustomPlatformData> m_customPlatformData; +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/css/CSS.idl b/chromium/third_party/WebKit/Source/core/css/CSS.idl index 4ba9ba74af4..36fe6dacce8 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSS.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSS.idl @@ -29,7 +29,8 @@ [ NoInterfaceObject, - ImplementedAs=DOMWindowCSS + ImplementedAs=DOMWindowCSS, + WillBeGarbageCollected ] interface CSS { boolean supports(DOMString property, DOMString value); boolean supports(DOMString conditionText); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.cpp index 3ead9d8137b..1c1d6c44fe6 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.cpp @@ -47,9 +47,9 @@ String CSSArrayFunctionValue::customCSSText() const return "array(" + CSSValueList::customCSSText() + ')'; } -PassRefPtr<CSSArrayFunctionValue> CSSArrayFunctionValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSArrayFunctionValue> CSSArrayFunctionValue::cloneForCSSOM() const { - return adoptRef(new CSSArrayFunctionValue(*this)); + return adoptRefWillBeNoop(new CSSArrayFunctionValue(*this)); } bool CSSArrayFunctionValue::equals(const CSSArrayFunctionValue& other) const diff --git a/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.h b/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.h index fffc616c32d..ebf1575a8e4 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSArrayFunctionValue.h @@ -37,17 +37,19 @@ namespace WebCore { class CSSArrayFunctionValue : public CSSValueList { public: - static PassRefPtr<CSSArrayFunctionValue> create() + static PassRefPtrWillBeRawPtr<CSSArrayFunctionValue> create() { - return adoptRef(new CSSArrayFunctionValue()); + return adoptRefWillBeNoop(new CSSArrayFunctionValue()); } String customCSSText() const; - PassRefPtr<CSSArrayFunctionValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSArrayFunctionValue> cloneForCSSOM() const; bool equals(const CSSArrayFunctionValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValueList::traceAfterDispatch(visitor); } + private: CSSArrayFunctionValue(); explicit CSSArrayFunctionValue(const CSSArrayFunctionValue& cloneFrom); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSAspectRatioValue.h b/chromium/third_party/WebKit/Source/core/css/CSSAspectRatioValue.h index a92ac34c2bb..bb86a0bffc9 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSAspectRatioValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSAspectRatioValue.h @@ -35,9 +35,9 @@ namespace WebCore { class CSSAspectRatioValue : public CSSValue { public: - static PassRefPtr<CSSAspectRatioValue> create(float numeratorValue, float denominatorValue) + static PassRefPtrWillBeRawPtr<CSSAspectRatioValue> create(float numeratorValue, float denominatorValue) { - return adoptRef(new CSSAspectRatioValue(numeratorValue, denominatorValue)); + return adoptRefWillBeNoop(new CSSAspectRatioValue(numeratorValue, denominatorValue)); } String customCSSText() const; @@ -47,6 +47,8 @@ public: bool equals(const CSSAspectRatioValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSAspectRatioValue(float numeratorValue, float denominatorValue) : CSSValue(AspectRatioClass) diff --git a/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.cpp b/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.cpp index 1104f176ef9..2f326c9e0f2 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.cpp @@ -30,91 +30,98 @@ #include "config.h" #include "core/css/CSSBasicShapes.h" +#include "core/css/CSSValuePool.h" +#include "core/css/Pair.h" +#include "platform/Length.h" #include "wtf/text/StringBuilder.h" using namespace WTF; namespace WebCore { -static String buildRectangleString(const String& x, const String& y, const String& width, const String& height, const String& radiusX, const String& radiusY) +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CSSBasicShape) + +static String buildCircleString(const String& radius, const String& centerX, const String& centerY, const String& box) { - char opening[] = "rectangle("; - char separator[] = ", "; + char at[] = "at"; + char separator[] = " "; StringBuilder result; - // Compute the required capacity in advance to reduce allocations. - result.reserveCapacity((sizeof(opening) - 1) + (5 * (sizeof(separator) - 1)) + 1 + x.length() + y.length() + width.length() + height.length() + radiusX.length() + radiusY.length()); - result.appendLiteral(opening); - result.append(x); - result.appendLiteral(separator); - result.append(y); - result.appendLiteral(separator); - result.append(width); - result.appendLiteral(separator); - result.append(height); - if (!radiusX.isNull()) { - result.appendLiteral(separator); - result.append(radiusX); - if (!radiusY.isNull()) { + result.appendLiteral("circle("); + if (!radius.isNull()) + result.append(radius); + + if (!centerX.isNull() || !centerY.isNull()) { + if (!radius.isNull()) result.appendLiteral(separator); - result.append(radiusY); - } + result.append(at); + result.appendLiteral(separator); + result.append(centerX); + result.appendLiteral(separator); + result.append(centerY); + } + result.append(")"); + if (box.length()) { + result.appendLiteral(separator); + result.append(box); } - result.append(')'); return result.toString(); } -String CSSBasicShapeRectangle::cssText() const +static String serializePositionOffset(const Pair& offset, const Pair& other) { - return buildRectangleString(m_x->cssText(), - m_y->cssText(), - m_width->cssText(), - m_height->cssText(), - m_radiusX.get() ? m_radiusX->cssText() : String(), - m_radiusY.get() ? m_radiusY->cssText() : String()); + if ((offset.first()->getValueID() == CSSValueLeft && other.first()->getValueID() == CSSValueTop) + || (offset.first()->getValueID() == CSSValueTop && other.first()->getValueID() == CSSValueLeft)) + return offset.second()->cssText(); + return offset.cssText(); } -bool CSSBasicShapeRectangle::equals(const CSSBasicShape& shape) const +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> buildSerializablePositionOffset(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> offset, CSSValueID defaultSide) { - if (shape.type() != CSSBasicShapeRectangleType) - return false; + CSSValueID side = defaultSide; + RefPtrWillBeRawPtr<CSSPrimitiveValue> amount = nullptr; + + if (!offset) { + side = CSSValueCenter; + } else if (offset->isValueID()) { + side = offset->getValueID(); + } else if (Pair* pair = offset->getPairValue()) { + side = pair->first()->getValueID(); + amount = pair->second(); + } else { + amount = offset; + } - const CSSBasicShapeRectangle& other = static_cast<const CSSBasicShapeRectangle&>(shape); - return compareCSSValuePtr(m_x, other.m_x) - && compareCSSValuePtr(m_y, other.m_y) - && compareCSSValuePtr(m_width, other.m_width) - && compareCSSValuePtr(m_height, other.m_height) - && compareCSSValuePtr(m_radiusX, other.m_radiusX) - && compareCSSValuePtr(m_radiusY, other.m_radiusY); -} + if (side == CSSValueCenter) { + side = defaultSide; + amount = cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE); + } else if ((side == CSSValueRight || side == CSSValueBottom) + && amount->isPercentage()) { + side = defaultSide; + amount = cssValuePool().createValue(100 - amount->getFloatValue(), CSSPrimitiveValue::CSS_PERCENTAGE); + } else if (amount->isLength() && !amount->getFloatValue()) { + if (side == CSSValueRight || side == CSSValueBottom) + amount = cssValuePool().createValue(100, CSSPrimitiveValue::CSS_PERCENTAGE); + else + amount = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PERCENTAGE); + side = defaultSide; + } -String CSSBasicShapeRectangle::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - return buildRectangleString(m_x->serializeResolvingVariables(variables), - m_y->serializeResolvingVariables(variables), - m_width->serializeResolvingVariables(variables), - m_height->serializeResolvingVariables(variables), - m_radiusX.get() ? m_radiusX->serializeResolvingVariables(variables) : String(), - m_radiusY.get() ? m_radiusY->serializeResolvingVariables(variables) : String()); + return cssValuePool().createValue(Pair::create(cssValuePool().createValue(side), amount.release(), Pair::KeepIdenticalValues)); } -bool CSSBasicShapeRectangle::hasVariableReference() const +String CSSBasicShapeCircle::cssText() const { - return m_x->hasVariableReference() - || m_y->hasVariableReference() - || m_width->hasVariableReference() - || m_height->hasVariableReference() - || (m_radiusX.get() && m_radiusX->hasVariableReference()) - || (m_radiusY.get() && m_radiusY->hasVariableReference()); -} + RefPtrWillBeRawPtr<CSSPrimitiveValue> normalizedCX = buildSerializablePositionOffset(m_centerX, CSSValueLeft); + RefPtrWillBeRawPtr<CSSPrimitiveValue> normalizedCY = buildSerializablePositionOffset(m_centerY, CSSValueTop); -static String buildCircleString(const String& x, const String& y, const String& radius) -{ - return "circle(" + x + ", " + y + ", " + radius + ')'; -} + String radius; + if (m_radius && m_radius->getValueID() != CSSValueClosestSide) + radius = m_radius->cssText(); -String CSSBasicShapeCircle::cssText() const -{ - return buildCircleString(m_centerX->cssText(), m_centerY->cssText(), m_radius->cssText()); + return buildCircleString(radius, + serializePositionOffset(*normalizedCX->getPairValue(), *normalizedCY->getPairValue()), + serializePositionOffset(*normalizedCY->getPairValue(), *normalizedCX->getPairValue()), + m_referenceBox ? m_referenceBox->cssText() : String()); } bool CSSBasicShapeCircle::equals(const CSSBasicShape& shape) const @@ -125,31 +132,77 @@ bool CSSBasicShapeCircle::equals(const CSSBasicShape& shape) const const CSSBasicShapeCircle& other = static_cast<const CSSBasicShapeCircle&>(shape); return compareCSSValuePtr(m_centerX, other.m_centerX) && compareCSSValuePtr(m_centerY, other.m_centerY) - && compareCSSValuePtr(m_radius, other.m_radius); + && compareCSSValuePtr(m_radius, other.m_radius) + && compareCSSValuePtr(m_referenceBox, other.m_referenceBox); } -String CSSBasicShapeCircle::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const +void CSSBasicShapeCircle::trace(Visitor* visitor) { - return buildCircleString(m_centerX->serializeResolvingVariables(variables), - m_centerY->serializeResolvingVariables(variables), - m_radius->serializeResolvingVariables(variables)); + visitor->trace(m_centerX); + visitor->trace(m_centerY); + visitor->trace(m_radius); + CSSBasicShape::trace(visitor); } -bool CSSBasicShapeCircle::hasVariableReference() const +static String buildEllipseString(const String& radiusX, const String& radiusY, const String& centerX, const String& centerY, const String& box) { - return m_centerX->hasVariableReference() - || m_centerY->hasVariableReference() - || m_radius->hasVariableReference(); -} + char at[] = "at"; + char separator[] = " "; + StringBuilder result; + result.appendLiteral("ellipse("); + bool needsSeparator = false; + if (!radiusX.isNull()) { + result.append(radiusX); + needsSeparator = true; + } + if (!radiusY.isNull()) { + if (needsSeparator) + result.appendLiteral(separator); + result.append(radiusY); + needsSeparator = true; + } -static String buildEllipseString(const String& x, const String& y, const String& radiusX, const String& radiusY) -{ - return "ellipse(" + x + ", " + y + ", " + radiusX + ", " + radiusY + ')'; + if (!centerX.isNull() || !centerY.isNull()) { + if (needsSeparator) + result.appendLiteral(separator); + result.appendLiteral(at); + result.appendLiteral(separator); + result.append(centerX); + result.appendLiteral(separator); + result.append(centerY); + } + result.append(")"); + if (box.length()) { + result.appendLiteral(separator); + result.append(box); + } + return result.toString(); } String CSSBasicShapeEllipse::cssText() const { - return buildEllipseString(m_centerX->cssText(), m_centerY->cssText(), m_radiusX->cssText(), m_radiusY->cssText()); + RefPtrWillBeRawPtr<CSSPrimitiveValue> normalizedCX = buildSerializablePositionOffset(m_centerX, CSSValueLeft); + RefPtrWillBeRawPtr<CSSPrimitiveValue> normalizedCY = buildSerializablePositionOffset(m_centerY, CSSValueTop); + + String radiusX; + String radiusY; + if (m_radiusX) { + bool shouldSerializeRadiusXValue = m_radiusX->getValueID() != CSSValueClosestSide; + bool shouldSerializeRadiusYValue = false; + + if (m_radiusY) { + shouldSerializeRadiusYValue = m_radiusY->getValueID() != CSSValueClosestSide; + if (shouldSerializeRadiusYValue) + radiusY = m_radiusY->cssText(); + } + if (shouldSerializeRadiusXValue || (!shouldSerializeRadiusXValue && shouldSerializeRadiusYValue)) + radiusX = m_radiusX->cssText(); + } + + return buildEllipseString(radiusX, radiusY, + serializePositionOffset(*normalizedCX->getPairValue(), *normalizedCY->getPairValue()), + serializePositionOffset(*normalizedCY->getPairValue(), *normalizedCX->getPairValue()), + m_referenceBox ? m_referenceBox->cssText() : String()); } bool CSSBasicShapeEllipse::equals(const CSSBasicShape& shape) const @@ -161,34 +214,28 @@ bool CSSBasicShapeEllipse::equals(const CSSBasicShape& shape) const return compareCSSValuePtr(m_centerX, other.m_centerX) && compareCSSValuePtr(m_centerY, other.m_centerY) && compareCSSValuePtr(m_radiusX, other.m_radiusX) - && compareCSSValuePtr(m_radiusY, other.m_radiusY); -} - -String CSSBasicShapeEllipse::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - return buildEllipseString(m_centerX->serializeResolvingVariables(variables), - m_centerY->serializeResolvingVariables(variables), - m_radiusX->serializeResolvingVariables(variables), - m_radiusY->serializeResolvingVariables(variables)); + && compareCSSValuePtr(m_radiusY, other.m_radiusY) + && compareCSSValuePtr(m_referenceBox, other.m_referenceBox); } -bool CSSBasicShapeEllipse::hasVariableReference() const +void CSSBasicShapeEllipse::trace(Visitor* visitor) { - return m_centerX->hasVariableReference() - || m_centerY->hasVariableReference() - || m_radiusX->hasVariableReference() - || m_radiusY->hasVariableReference(); + visitor->trace(m_centerX); + visitor->trace(m_centerY); + visitor->trace(m_radiusX); + visitor->trace(m_radiusY); + CSSBasicShape::trace(visitor); } -static String buildPolygonString(const WindRule& windRule, const Vector<String>& points) +static String buildPolygonString(const WindRule& windRule, const Vector<String>& points, const String& box) { ASSERT(!(points.size() % 2)); StringBuilder result; - char evenOddOpening[] = "polygon(evenodd, "; - char nonZeroOpening[] = "polygon(nonzero, "; - char commaSeparator[] = ", "; - COMPILE_ASSERT(sizeof(evenOddOpening) == sizeof(nonZeroOpening), polygon_string_openings_have_same_length); + const char evenOddOpening[] = "polygon(evenodd, "; + const char nonZeroOpening[] = "polygon("; + const char commaSeparator[] = ", "; + COMPILE_ASSERT(sizeof(evenOddOpening) > sizeof(nonZeroOpening), polygon_string_openings_have_same_length); // Compute the required capacity in advance to reduce allocations. size_t length = sizeof(evenOddOpening) - 1; @@ -198,6 +245,8 @@ static String buildPolygonString(const WindRule& windRule, const Vector<String>& // add length of two strings, plus one for the space separator. length += points[i].length() + 1 + points[i + 1].length(); } + if (!box.isEmpty()) + length += box.length() + 1; result.reserveCapacity(length); if (windRule == RULE_EVENODD) @@ -215,6 +264,11 @@ static String buildPolygonString(const WindRule& windRule, const Vector<String>& result.append(')'); + if (!box.isEmpty()) { + result.append(' '); + result.append(box); + } + return result.toString(); } @@ -226,7 +280,7 @@ String CSSBasicShapePolygon::cssText() const for (size_t i = 0; i < m_values.size(); ++i) points.append(m_values.at(i)->cssText()); - return buildPolygonString(m_windRule, points); + return buildPolygonString(m_windRule, points, m_referenceBox ? m_referenceBox->cssText() : String()); } bool CSSBasicShapePolygon::equals(const CSSBasicShape& shape) const @@ -235,98 +289,163 @@ bool CSSBasicShapePolygon::equals(const CSSBasicShape& shape) const return false; const CSSBasicShapePolygon& rhs = static_cast<const CSSBasicShapePolygon&>(shape); - return compareCSSValueVector<CSSPrimitiveValue>(m_values, rhs.m_values); -} -String CSSBasicShapePolygon::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - Vector<String> points; - points.reserveInitialCapacity(m_values.size()); + if (!compareCSSValuePtr(m_referenceBox, rhs.m_referenceBox)) + return false; - for (size_t i = 0; i < m_values.size(); ++i) - points.append(m_values.at(i)->serializeResolvingVariables(variables)); + return compareCSSValueVector(m_values, rhs.m_values); +} - return buildPolygonString(m_windRule, points); +void CSSBasicShapePolygon::trace(Visitor* visitor) +{ + visitor->trace(m_values); + CSSBasicShape::trace(visitor); } -bool CSSBasicShapePolygon::hasVariableReference() const +static bool buildInsetRadii(Vector<String> &radii, const String& topLeftRadius, const String& topRightRadius, const String& bottomRightRadius, const String& bottomLeftRadius) { - for (size_t i = 0; i < m_values.size(); ++i) { - if (m_values.at(i)->hasVariableReference()) - return true; - } - return false; + bool showBottomLeft = topRightRadius != bottomLeftRadius; + bool showBottomRight = showBottomLeft || (bottomRightRadius != topLeftRadius); + bool showTopRight = showBottomRight || (topRightRadius != topLeftRadius); + + radii.append(topLeftRadius); + if (showTopRight) + radii.append(topRightRadius); + if (showBottomRight) + radii.append(bottomRightRadius); + if (showBottomLeft) + radii.append(bottomLeftRadius); + + return radii.size() == 1 && radii[0] == "0px"; } -static String buildInsetRectangleString(const String& top, const String& right, const String& bottom, const String& left, const String& radiusX, const String& radiusY) +static String buildInsetString(const String& top, const String& right, const String& bottom, const String& left, + const String& topLeftRadiusWidth, const String& topLeftRadiusHeight, + const String& topRightRadiusWidth, const String& topRightRadiusHeight, + const String& bottomRightRadiusWidth, const String& bottomRightRadiusHeight, + const String& bottomLeftRadiusWidth, const String& bottomLeftRadiusHeight) { - char opening[] = "inset-rectangle("; - char separator[] = ", "; + char opening[] = "inset("; + char separator[] = " "; + char cornersSeparator[] = "round"; StringBuilder result; - // Compute the required capacity in advance to reduce allocations. - result.reserveCapacity((sizeof(opening) - 1) + (5 * (sizeof(separator) - 1)) + 1 + top.length() + right.length() + bottom.length() + left.length() + radiusX.length() + radiusY.length()); result.appendLiteral(opening); result.append(top); - result.appendLiteral(separator); - result.append(right); - result.appendLiteral(separator); - result.append(bottom); - result.appendLiteral(separator); - result.append(left); - if (!radiusX.isNull()) { + bool showLeftArg = !left.isNull() && left != right; + bool showBottomArg = !bottom.isNull() && (bottom != top || showLeftArg); + bool showRightArg = !right.isNull() && (right != top || showBottomArg); + if (showRightArg) { result.appendLiteral(separator); - result.append(radiusX); - if (!radiusY.isNull()) { + result.append(right); + } + if (showBottomArg) { + result.appendLiteral(separator); + result.append(bottom); + } + if (showLeftArg) { + result.appendLiteral(separator); + result.append(left); + } + + if (!topLeftRadiusWidth.isNull() && !topLeftRadiusHeight.isNull()) { + Vector<String> horizontalRadii; + bool areDefaultCornerRadii = buildInsetRadii(horizontalRadii, topLeftRadiusWidth, topRightRadiusWidth, bottomRightRadiusWidth, bottomLeftRadiusWidth); + + Vector<String> verticalRadii; + areDefaultCornerRadii &= buildInsetRadii(verticalRadii, topLeftRadiusHeight, topRightRadiusHeight, bottomRightRadiusHeight, bottomLeftRadiusHeight); + + if (!areDefaultCornerRadii) { result.appendLiteral(separator); - result.append(radiusY); + result.appendLiteral(cornersSeparator); + + for (size_t i = 0; i < horizontalRadii.size(); ++i) { + result.appendLiteral(separator); + result.append(horizontalRadii[i]); + } + if (horizontalRadii != verticalRadii) { + result.appendLiteral(separator); + result.appendLiteral("/"); + + for (size_t i = 0; i < verticalRadii.size(); ++i) { + result.appendLiteral(separator); + result.append(verticalRadii[i]); + } + } } } result.append(')'); + return result.toString(); } -String CSSBasicShapeInsetRectangle::cssText() const +static inline void updateCornerRadiusWidthAndHeight(CSSPrimitiveValue* corner, String& width, String& height) +{ + if (!corner) + return; + + Pair* radius = corner->getPairValue(); + width = radius->first() ? radius->first()->cssText() : String("0"); + if (radius->second()) + height = radius->second()->cssText(); +} + +String CSSBasicShapeInset::cssText() const { - return buildInsetRectangleString(m_top->cssText(), - m_right->cssText(), - m_bottom->cssText(), - m_left->cssText(), - m_radiusX.get() ? m_radiusX->cssText() : String(), - m_radiusY.get() ? m_radiusY->cssText() : String()); + String topLeftRadiusWidth; + String topLeftRadiusHeight; + String topRightRadiusWidth; + String topRightRadiusHeight; + String bottomRightRadiusWidth; + String bottomRightRadiusHeight; + String bottomLeftRadiusWidth; + String bottomLeftRadiusHeight; + + updateCornerRadiusWidthAndHeight(topLeftRadius(), topLeftRadiusWidth, topLeftRadiusHeight); + updateCornerRadiusWidthAndHeight(topRightRadius(), topRightRadiusWidth, topRightRadiusHeight); + updateCornerRadiusWidthAndHeight(bottomRightRadius(), bottomRightRadiusWidth, bottomRightRadiusHeight); + updateCornerRadiusWidthAndHeight(bottomLeftRadius(), bottomLeftRadiusWidth, bottomLeftRadiusHeight); + + return buildInsetString(m_top ? m_top->cssText() : String(), + m_right ? m_right->cssText() : String(), + m_bottom ? m_bottom->cssText() : String(), + m_left ? m_left->cssText() : String(), + topLeftRadiusWidth, + topLeftRadiusHeight, + topRightRadiusWidth, + topRightRadiusHeight, + bottomRightRadiusWidth, + bottomRightRadiusHeight, + bottomLeftRadiusWidth, + bottomLeftRadiusHeight); } -bool CSSBasicShapeInsetRectangle::equals(const CSSBasicShape& shape) const +bool CSSBasicShapeInset::equals(const CSSBasicShape& shape) const { - if (shape.type() != CSSBasicShapeInsetRectangleType) + if (shape.type() != CSSBasicShapeInsetType) return false; - const CSSBasicShapeInsetRectangle& other = static_cast<const CSSBasicShapeInsetRectangle&>(shape); + const CSSBasicShapeInset& other = static_cast<const CSSBasicShapeInset&>(shape); return compareCSSValuePtr(m_top, other.m_top) && compareCSSValuePtr(m_right, other.m_right) && compareCSSValuePtr(m_bottom, other.m_bottom) && compareCSSValuePtr(m_left, other.m_left) - && compareCSSValuePtr(m_radiusX, other.m_radiusX) - && compareCSSValuePtr(m_radiusY, other.m_radiusY); -} - -String CSSBasicShapeInsetRectangle::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - return buildInsetRectangleString(m_top->serializeResolvingVariables(variables), - m_right->serializeResolvingVariables(variables), - m_bottom->serializeResolvingVariables(variables), - m_left->serializeResolvingVariables(variables), - m_radiusX.get() ? m_radiusX->serializeResolvingVariables(variables) : String(), - m_radiusY.get() ? m_radiusY->serializeResolvingVariables(variables) : String()); + && compareCSSValuePtr(m_topLeftRadius, other.m_topLeftRadius) + && compareCSSValuePtr(m_topRightRadius, other.m_topRightRadius) + && compareCSSValuePtr(m_bottomRightRadius, other.m_bottomRightRadius) + && compareCSSValuePtr(m_bottomLeftRadius, other.m_bottomLeftRadius); } -bool CSSBasicShapeInsetRectangle::hasVariableReference() const +void CSSBasicShapeInset::trace(Visitor* visitor) { - return m_top->hasVariableReference() - || m_right->hasVariableReference() - || m_bottom->hasVariableReference() - || m_left->hasVariableReference() - || (m_radiusX.get() && m_radiusX->hasVariableReference()) - || (m_radiusY.get() && m_radiusY->hasVariableReference()); + visitor->trace(m_top); + visitor->trace(m_right); + visitor->trace(m_bottom); + visitor->trace(m_left); + visitor->trace(m_topLeftRadius); + visitor->trace(m_topRightRadius); + visitor->trace(m_bottomRightRadius); + visitor->trace(m_bottomLeftRadius); + CSSBasicShape::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.h b/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.h index ca8c661fc47..4c510e0ca5c 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSBasicShapes.h @@ -38,181 +38,107 @@ namespace WebCore { -class CSSBasicShape : public RefCounted<CSSBasicShape> { +class CSSBasicShape : public RefCountedWillBeGarbageCollected<CSSBasicShape> { + DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(CSSBasicShape); public: enum Type { - CSSBasicShapeRectangleType = 1, - CSSBasicShapeCircleType = 2, - CSSBasicShapeEllipseType = 3, - CSSBasicShapePolygonType = 4, - CSSBasicShapeInsetRectangleType = 5 + CSSBasicShapeEllipseType, + CSSBasicShapePolygonType, + CSSBasicShapeCircleType, + CSSBasicShapeInsetType }; virtual Type type() const = 0; virtual String cssText() const = 0; virtual bool equals(const CSSBasicShape&) const = 0; - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const = 0; - virtual bool hasVariableReference() const = 0; + CSSPrimitiveValue* referenceBox() const { return m_referenceBox.get(); } + void setReferenceBox(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> referenceBox) { m_referenceBox = referenceBox; } -public: - virtual ~CSSBasicShape() { } + virtual void trace(Visitor* visitor) { visitor->trace(m_referenceBox); } protected: CSSBasicShape() { } + RefPtrWillBeMember<CSSPrimitiveValue> m_referenceBox; }; -class CSSBasicShapeRectangle : public CSSBasicShape { +class CSSBasicShapeCircle FINAL : public CSSBasicShape { public: - static PassRefPtr<CSSBasicShapeRectangle> create() { return adoptRef(new CSSBasicShapeRectangle); } - - CSSPrimitiveValue* x() const { return m_x.get(); } - CSSPrimitiveValue* y() const { return m_y.get(); } - CSSPrimitiveValue* width() const { return m_width.get(); } - CSSPrimitiveValue* height() const { return m_height.get(); } - CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); } - CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); } - - void setX(PassRefPtr<CSSPrimitiveValue> x) { m_x = x; } - void setY(PassRefPtr<CSSPrimitiveValue> y) { m_y = y; } - void setWidth(PassRefPtr<CSSPrimitiveValue> width) { m_width = width; } - void setHeight(PassRefPtr<CSSPrimitiveValue> height) { m_height = height; } - void setRadiusX(PassRefPtr<CSSPrimitiveValue> radiusX) { m_radiusX = radiusX; } - void setRadiusY(PassRefPtr<CSSPrimitiveValue> radiusY) { m_radiusY = radiusY; } - - virtual Type type() const { return CSSBasicShapeRectangleType; } - virtual String cssText() const; - virtual bool equals(const CSSBasicShape&) const; - - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const; - virtual bool hasVariableReference() const; - -private: - CSSBasicShapeRectangle() { } - - RefPtr<CSSPrimitiveValue> m_y; - RefPtr<CSSPrimitiveValue> m_x; - RefPtr<CSSPrimitiveValue> m_width; - RefPtr<CSSPrimitiveValue> m_height; - RefPtr<CSSPrimitiveValue> m_radiusX; - RefPtr<CSSPrimitiveValue> m_radiusY; -}; - -class CSSBasicShapeInsetRectangle : public CSSBasicShape { -public: - static PassRefPtr<CSSBasicShapeInsetRectangle> create() { return adoptRef(new CSSBasicShapeInsetRectangle); } - - CSSPrimitiveValue* top() const { return m_top.get(); } - CSSPrimitiveValue* right() const { return m_right.get(); } - CSSPrimitiveValue* bottom() const { return m_bottom.get(); } - CSSPrimitiveValue* left() const { return m_left.get(); } - CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); } - CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); } + static PassRefPtrWillBeRawPtr<CSSBasicShapeCircle> create() { return adoptRefWillBeNoop(new CSSBasicShapeCircle); } - void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; } - void setRight(PassRefPtr<CSSPrimitiveValue> right) { m_right = right; } - void setBottom(PassRefPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; } - void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; } - void setRadiusX(PassRefPtr<CSSPrimitiveValue> radiusX) { m_radiusX = radiusX; } - void setRadiusY(PassRefPtr<CSSPrimitiveValue> radiusY) { m_radiusY = radiusY; } - - virtual Type type() const { return CSSBasicShapeInsetRectangleType; } - virtual String cssText() const; - virtual bool equals(const CSSBasicShape&) const; - - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const; - virtual bool hasVariableReference() const; - -private: - CSSBasicShapeInsetRectangle() { } - - RefPtr<CSSPrimitiveValue> m_right; - RefPtr<CSSPrimitiveValue> m_top; - RefPtr<CSSPrimitiveValue> m_bottom; - RefPtr<CSSPrimitiveValue> m_left; - RefPtr<CSSPrimitiveValue> m_radiusX; - RefPtr<CSSPrimitiveValue> m_radiusY; -}; - -class CSSBasicShapeCircle : public CSSBasicShape { -public: - static PassRefPtr<CSSBasicShapeCircle> create() { return adoptRef(new CSSBasicShapeCircle); } + virtual Type type() const OVERRIDE { return CSSBasicShapeCircleType; } + virtual String cssText() const OVERRIDE; + virtual bool equals(const CSSBasicShape&) const OVERRIDE; CSSPrimitiveValue* centerX() const { return m_centerX.get(); } CSSPrimitiveValue* centerY() const { return m_centerY.get(); } CSSPrimitiveValue* radius() const { return m_radius.get(); } - void setCenterX(PassRefPtr<CSSPrimitiveValue> centerX) { m_centerX = centerX; } - void setCenterY(PassRefPtr<CSSPrimitiveValue> centerY) { m_centerY = centerY; } - void setRadius(PassRefPtr<CSSPrimitiveValue> radius) { m_radius = radius; } - - virtual Type type() const { return CSSBasicShapeCircleType; } - virtual String cssText() const; - virtual bool equals(const CSSBasicShape&) const; + void setCenterX(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> centerX) { m_centerX = centerX; } + void setCenterY(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> centerY) { m_centerY = centerY; } + void setRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) { m_radius = radius; } - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const; - virtual bool hasVariableReference() const; + virtual void trace(Visitor*); private: CSSBasicShapeCircle() { } - RefPtr<CSSPrimitiveValue> m_centerY; - RefPtr<CSSPrimitiveValue> m_centerX; - RefPtr<CSSPrimitiveValue> m_radius; + RefPtrWillBeMember<CSSPrimitiveValue> m_centerX; + RefPtrWillBeMember<CSSPrimitiveValue> m_centerY; + RefPtrWillBeMember<CSSPrimitiveValue> m_radius; }; -class CSSBasicShapeEllipse : public CSSBasicShape { +class CSSBasicShapeEllipse FINAL : public CSSBasicShape { public: - static PassRefPtr<CSSBasicShapeEllipse> create() { return adoptRef(new CSSBasicShapeEllipse); } + static PassRefPtrWillBeRawPtr<CSSBasicShapeEllipse> create() { return adoptRefWillBeNoop(new CSSBasicShapeEllipse); } + + virtual Type type() const OVERRIDE { return CSSBasicShapeEllipseType; } + virtual String cssText() const OVERRIDE; + virtual bool equals(const CSSBasicShape&) const OVERRIDE; CSSPrimitiveValue* centerX() const { return m_centerX.get(); } CSSPrimitiveValue* centerY() const { return m_centerY.get(); } CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); } CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); } - void setCenterX(PassRefPtr<CSSPrimitiveValue> centerX) { m_centerX = centerX; } - void setCenterY(PassRefPtr<CSSPrimitiveValue> centerY) { m_centerY = centerY; } - void setRadiusX(PassRefPtr<CSSPrimitiveValue> radiusX) { m_radiusX = radiusX; } - void setRadiusY(PassRefPtr<CSSPrimitiveValue> radiusY) { m_radiusY = radiusY; } - - virtual Type type() const { return CSSBasicShapeEllipseType; } - virtual String cssText() const; - virtual bool equals(const CSSBasicShape&) const; + void setCenterX(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> centerX) { m_centerX = centerX; } + void setCenterY(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> centerY) { m_centerY = centerY; } + void setRadiusX(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radiusX) { m_radiusX = radiusX; } + void setRadiusY(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radiusY) { m_radiusY = radiusY; } - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const; - virtual bool hasVariableReference() const; + virtual void trace(Visitor*); private: CSSBasicShapeEllipse() { } - RefPtr<CSSPrimitiveValue> m_centerX; - RefPtr<CSSPrimitiveValue> m_centerY; - RefPtr<CSSPrimitiveValue> m_radiusX; - RefPtr<CSSPrimitiveValue> m_radiusY; + RefPtrWillBeMember<CSSPrimitiveValue> m_centerX; + RefPtrWillBeMember<CSSPrimitiveValue> m_centerY; + RefPtrWillBeMember<CSSPrimitiveValue> m_radiusX; + RefPtrWillBeMember<CSSPrimitiveValue> m_radiusY; }; -class CSSBasicShapePolygon : public CSSBasicShape { +class CSSBasicShapePolygon FINAL : public CSSBasicShape { public: - static PassRefPtr<CSSBasicShapePolygon> create() { return adoptRef(new CSSBasicShapePolygon); } + static PassRefPtrWillBeRawPtr<CSSBasicShapePolygon> create() { return adoptRefWillBeNoop(new CSSBasicShapePolygon); } - void appendPoint(PassRefPtr<CSSPrimitiveValue> x, PassRefPtr<CSSPrimitiveValue> y) + void appendPoint(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> x, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> y) { m_values.append(x); m_values.append(y); } - PassRefPtr<CSSPrimitiveValue> getXAt(unsigned i) const { return m_values.at(i * 2); } - PassRefPtr<CSSPrimitiveValue> getYAt(unsigned i) const { return m_values.at(i * 2 + 1); } - const Vector<RefPtr<CSSPrimitiveValue> >& values() const { return m_values; } + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> getXAt(unsigned i) const { return m_values.at(i * 2); } + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> getYAt(unsigned i) const { return m_values.at(i * 2 + 1); } + const WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> >& values() const { return m_values; } void setWindRule(WindRule w) { m_windRule = w; } WindRule windRule() const { return m_windRule; } - virtual Type type() const { return CSSBasicShapePolygonType; } - virtual String cssText() const; - virtual bool equals(const CSSBasicShape&) const; - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const; - virtual bool hasVariableReference() const; + virtual Type type() const OVERRIDE { return CSSBasicShapePolygonType; } + virtual String cssText() const OVERRIDE; + virtual bool equals(const CSSBasicShape&) const OVERRIDE; + + virtual void trace(Visitor*); private: CSSBasicShapePolygon() @@ -220,10 +146,78 @@ private: { } - Vector<RefPtr<CSSPrimitiveValue> > m_values; + WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> > m_values; WindRule m_windRule; }; +class CSSBasicShapeInset : public CSSBasicShape { +public: + static PassRefPtrWillBeRawPtr<CSSBasicShapeInset> create() { return adoptRefWillBeNoop(new CSSBasicShapeInset); } + + CSSPrimitiveValue* top() const { return m_top.get(); } + CSSPrimitiveValue* right() const { return m_right.get(); } + CSSPrimitiveValue* bottom() const { return m_bottom.get(); } + CSSPrimitiveValue* left() const { return m_left.get(); } + + CSSPrimitiveValue* topLeftRadius() const { return m_topLeftRadius.get(); } + CSSPrimitiveValue* topRightRadius() const { return m_topRightRadius.get(); } + CSSPrimitiveValue* bottomRightRadius() const { return m_bottomRightRadius.get(); } + CSSPrimitiveValue* bottomLeftRadius() const { return m_bottomLeftRadius.get(); } + + void setTop(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> top) { m_top = top; } + void setRight(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> right) { m_right = right; } + void setBottom(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; } + void setLeft(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> left) { m_left = left; } + + void updateShapeSize4Values(CSSPrimitiveValue* top, CSSPrimitiveValue* right, CSSPrimitiveValue* bottom, CSSPrimitiveValue* left) + { + setTop(top); + setRight(right); + setBottom(bottom); + setLeft(left); + } + + void updateShapeSize1Value(CSSPrimitiveValue* value1) + { + updateShapeSize4Values(value1, value1, value1, value1); + } + + void updateShapeSize2Values(CSSPrimitiveValue* value1, CSSPrimitiveValue* value2) + { + updateShapeSize4Values(value1, value2, value1, value2); + } + + void updateShapeSize3Values(CSSPrimitiveValue* value1, CSSPrimitiveValue* value2, CSSPrimitiveValue* value3) + { + updateShapeSize4Values(value1, value2, value3, value2); + } + + + void setTopLeftRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) { m_topLeftRadius = radius; } + void setTopRightRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) { m_topRightRadius = radius; } + void setBottomRightRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) { m_bottomRightRadius = radius; } + void setBottomLeftRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> radius) { m_bottomLeftRadius = radius; } + + virtual Type type() const OVERRIDE { return CSSBasicShapeInsetType; } + virtual String cssText() const OVERRIDE; + virtual bool equals(const CSSBasicShape&) const OVERRIDE; + + virtual void trace(Visitor*); + +private: + CSSBasicShapeInset() { } + + RefPtrWillBeMember<CSSPrimitiveValue> m_top; + RefPtrWillBeMember<CSSPrimitiveValue> m_right; + RefPtrWillBeMember<CSSPrimitiveValue> m_bottom; + RefPtrWillBeMember<CSSPrimitiveValue> m_left; + + RefPtrWillBeMember<CSSPrimitiveValue> m_topLeftRadius; + RefPtrWillBeMember<CSSPrimitiveValue> m_topRightRadius; + RefPtrWillBeMember<CSSPrimitiveValue> m_bottomRightRadius; + RefPtrWillBeMember<CSSPrimitiveValue> m_bottomLeftRadius; +}; + } // namespace WebCore #endif // CSSBasicShapes_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.cpp b/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.cpp index d62711ddef7..fd05d0f5ff8 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.cpp @@ -22,15 +22,15 @@ namespace WebCore { -PassRefPtr<CSSValueList> createBorderImageValue(PassRefPtr<CSSValue> image, PassRefPtr<CSSValue> imageSlice, PassRefPtr<CSSValue> borderSlice, - PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat) +PassRefPtrWillBeRawPtr<CSSValueList> createBorderImageValue(PassRefPtrWillBeRawPtr<CSSValue> image, PassRefPtrWillBeRawPtr<CSSValue> imageSlice, + PassRefPtrWillBeRawPtr<CSSValue> borderSlice, PassRefPtrWillBeRawPtr<CSSValue> outset, PassRefPtrWillBeRawPtr<CSSValue> repeat) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (image) list->append(image); if (borderSlice || outset) { - RefPtr<CSSValueList> listSlash = CSSValueList::createSlashSeparated(); + RefPtrWillBeRawPtr<CSSValueList> listSlash = CSSValueList::createSlashSeparated(); if (imageSlice) listSlash->append(imageSlice); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.h b/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.h index bdf13fefd19..b9066fa29bf 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSBorderImage.h @@ -26,8 +26,8 @@ namespace WebCore { -PassRefPtr<CSSValueList> createBorderImageValue(PassRefPtr<CSSValue> image, PassRefPtr<CSSValue> imageSlice, PassRefPtr<CSSValue> borderSlice, - PassRefPtr<CSSValue> outset, PassRefPtr<CSSValue> repeat); +PassRefPtrWillBeRawPtr<CSSValueList> createBorderImageValue(PassRefPtrWillBeRawPtr<CSSValue> image, PassRefPtrWillBeRawPtr<CSSValue> imageSlice, PassRefPtrWillBeRawPtr<CSSValue> borderSlice, + PassRefPtrWillBeRawPtr<CSSValue> outset, PassRefPtrWillBeRawPtr<CSSValue> repeat); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.cpp index 7ffac3afb9b..34400a81137 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.cpp @@ -30,7 +30,7 @@ namespace WebCore { -CSSBorderImageSliceValue::CSSBorderImageSliceValue(PassRefPtr<CSSPrimitiveValue> slices, bool fill) +CSSBorderImageSliceValue::CSSBorderImageSliceValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> slices, bool fill) : CSSValue(BorderImageSliceClass) , m_slices(slices) , m_fill(fill) @@ -53,4 +53,10 @@ bool CSSBorderImageSliceValue::equals(const CSSBorderImageSliceValue& other) con return m_fill == other.m_fill && compareCSSValuePtr(m_slices, other.m_slices); } +void CSSBorderImageSliceValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_slices); + CSSValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.h b/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.h index 7d297ea9be0..c2b4716d790 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSBorderImageSliceValue.h @@ -36,9 +36,9 @@ class Rect; class CSSBorderImageSliceValue : public CSSValue { public: - static PassRefPtr<CSSBorderImageSliceValue> create(PassRefPtr<CSSPrimitiveValue> slices, bool fill) + static PassRefPtrWillBeRawPtr<CSSBorderImageSliceValue> create(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> slices, bool fill) { - return adoptRef(new CSSBorderImageSliceValue(slices, fill)); + return adoptRefWillBeNoop(new CSSBorderImageSliceValue(slices, fill)); } String customCSSText() const; @@ -47,13 +47,15 @@ public: bool equals(const CSSBorderImageSliceValue&) const; + void traceAfterDispatch(Visitor*); + // These four values are used to make "cuts" in the border image. They can be numbers // or percentages. - RefPtr<CSSPrimitiveValue> m_slices; + RefPtrWillBeMember<CSSPrimitiveValue> m_slices; bool m_fill; private: - CSSBorderImageSliceValue(PassRefPtr<CSSPrimitiveValue> slices, bool fill); + CSSBorderImageSliceValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> slices, bool fill); }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSBorderImageSliceValue, isBorderImageSliceValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp index e27cba3a66d..79de5eb33bf 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.cpp @@ -47,7 +47,7 @@ enum ParseState { namespace WebCore { -static CalculationCategory unitCategory(CSSPrimitiveValue::UnitTypes type) +static CalculationCategory unitCategory(CSSPrimitiveValue::UnitType type) { switch (type) { case CSSPrimitiveValue::CSS_NUMBER: @@ -65,15 +65,19 @@ static CalculationCategory unitCategory(CSSPrimitiveValue::UnitTypes type) case CSSPrimitiveValue::CSS_PC: case CSSPrimitiveValue::CSS_REMS: case CSSPrimitiveValue::CSS_CHS: + case CSSPrimitiveValue::CSS_VW: + case CSSPrimitiveValue::CSS_VH: + case CSSPrimitiveValue::CSS_VMIN: + case CSSPrimitiveValue::CSS_VMAX: return CalcLength; - case CSSPrimitiveValue::CSS_VARIABLE_NAME: - return CalcVariable; + // FIXME: Support angle, time and frequency units. + // http://www.w3.org/TR/css3-values/#calc-notation default: return CalcOther; } } -static bool hasDoubleValue(CSSPrimitiveValue::UnitTypes type) +static bool hasDoubleValue(CSSPrimitiveValue::UnitType type) { switch (type) { case CSSPrimitiveValue::CSS_NUMBER: @@ -126,7 +130,6 @@ static bool hasDoubleValue(CSSPrimitiveValue::UnitTypes type) case CSSPrimitiveValue::CSS_CALC: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: - case CSSPrimitiveValue::CSS_VARIABLE_NAME: case CSSPrimitiveValue::CSS_PROPERTY_ID: case CSSPrimitiveValue::CSS_VALUE_ID: return false; @@ -158,16 +161,6 @@ bool CSSCalcValue::equals(const CSSCalcValue& other) const return compareCSSValuePtr(m_expression, other.m_expression); } -String CSSCalcValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - return buildCSSText(m_expression->serializeResolvingVariables(variables)); -} - -bool CSSCalcValue::hasVariableReference() const -{ - return m_expression->hasVariableReference(); -} - double CSSCalcValue::clampToPermittedRange(double value) const { return m_nonNegative && value < 0 ? 0 : value; @@ -183,71 +176,50 @@ double CSSCalcValue::computeLengthPx(const CSSToLengthConversionData& conversion return clampToPermittedRange(m_expression->computeLengthPx(conversionData)); } -CSSCalcExpressionNode::~CSSCalcExpressionNode() -{ -} +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(CSSCalcExpressionNode) -class CSSCalcPrimitiveValue : public CSSCalcExpressionNode { - WTF_MAKE_FAST_ALLOCATED; +class CSSCalcPrimitiveValue FINAL : public CSSCalcExpressionNode { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<CSSCalcPrimitiveValue> create(PassRefPtr<CSSPrimitiveValue> value, bool isInteger) + static PassRefPtrWillBeRawPtr<CSSCalcPrimitiveValue> create(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) { - return adoptRef(new CSSCalcPrimitiveValue(value, isInteger)); + return adoptRefWillBeNoop(new CSSCalcPrimitiveValue(value, isInteger)); } - static PassRefPtr<CSSCalcPrimitiveValue> create(double value, CSSPrimitiveValue::UnitTypes type, bool isInteger) + static PassRefPtrWillBeRawPtr<CSSCalcPrimitiveValue> create(double value, CSSPrimitiveValue::UnitType type, bool isInteger) { if (std::isnan(value) || std::isinf(value)) - return 0; - return adoptRef(new CSSCalcPrimitiveValue(CSSPrimitiveValue::create(value, type).get(), isInteger)); + return nullptr; + return adoptRefWillBeNoop(new CSSCalcPrimitiveValue(CSSPrimitiveValue::create(value, type).get(), isInteger)); } - virtual bool isZero() const + virtual bool isZero() const OVERRIDE { return !m_value->getDoubleValue(); } - virtual String customCSSText() const + virtual String customCSSText() const OVERRIDE { return m_value->cssText(); } - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const - { - return m_value->customSerializeResolvingVariables(variables); - } - - virtual bool hasVariableReference() const - { - return m_value->isVariableName(); - } - - virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const CSSToLengthConversionData& conversionData) const + virtual void accumulatePixelsAndPercent(const CSSToLengthConversionData& conversionData, PixelsAndPercent& value, float multiplier) const OVERRIDE { switch (m_category) { - case CalcNumber: - return adoptPtr(new CalcExpressionNumber(m_value->getFloatValue())); case CalcLength: - return adoptPtr(new CalcExpressionLength(Length(m_value->computeLength<float>(conversionData), WebCore::Fixed))); + value.pixels += m_value->computeLength<float>(conversionData) * multiplier; + break; case CalcPercent: - case CalcPercentLength: { - CSSPrimitiveValue* primitiveValue = m_value.get(); - return adoptPtr(new CalcExpressionLength(primitiveValue - ? primitiveValue->convertToLength<FixedConversion | PercentConversion>(conversionData) - : Length(Undefined))); - } - // Only types that could be part of a Length expression can be converted - // to a CalcExpressionNode. CalcPercentNumber makes no sense as a Length. - case CalcPercentNumber: - case CalcVariable: - case CalcOther: + ASSERT(m_value->isPercentage()); + value.percent += m_value->getDoubleValue() * multiplier; + break; + default: ASSERT_NOT_REACHED(); } - return nullptr; } - virtual double doubleValue() const + virtual double doubleValue() const OVERRIDE { if (hasDoubleValue(primitiveType())) return m_value->getDoubleValue(); @@ -255,7 +227,7 @@ public: return 0; } - virtual double computeLengthPx(const CSSToLengthConversionData& conversionData) const + virtual double computeLengthPx(const CSSToLengthConversionData& conversionData) const OVERRIDE { switch (m_category) { case CalcLength: @@ -265,7 +237,6 @@ public: return m_value->getDoubleValue(); case CalcPercentLength: case CalcPercentNumber: - case CalcVariable: case CalcOther: ASSERT_NOT_REACHED(); break; @@ -274,7 +245,13 @@ public: return 0; } - virtual bool equals(const CSSCalcExpressionNode& other) const + virtual void accumulateLengthArray(CSSLengthArray& lengthArray, double multiplier) const + { + ASSERT(category() != CalcNumber); + m_value->accumulateLengthArray(lengthArray, multiplier); + } + + virtual bool equals(const CSSCalcExpressionNode& other) const OVERRIDE { if (type() != other.type()) return false; @@ -282,20 +259,27 @@ public: return compareCSSValuePtr(m_value, static_cast<const CSSCalcPrimitiveValue&>(other).m_value); } - virtual Type type() const { return CssCalcPrimitiveValue; } - virtual CSSPrimitiveValue::UnitTypes primitiveType() const + virtual Type type() const OVERRIDE { return CssCalcPrimitiveValue; } + virtual CSSPrimitiveValue::UnitType primitiveType() const OVERRIDE { - return CSSPrimitiveValue::UnitTypes(m_value->primitiveType()); + return m_value->primitiveType(); + } + + + virtual void trace(Visitor* visitor) + { + visitor->trace(m_value); + CSSCalcExpressionNode::trace(visitor); } private: - explicit CSSCalcPrimitiveValue(PassRefPtr<CSSPrimitiveValue> value, bool isInteger) - : CSSCalcExpressionNode(unitCategory((CSSPrimitiveValue::UnitTypes)value->primitiveType()), isInteger) + CSSCalcPrimitiveValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) + : CSSCalcExpressionNode(unitCategory(value->primitiveType()), isInteger) , m_value(value) { } - RefPtr<CSSPrimitiveValue> m_value; + RefPtrWillBeMember<CSSPrimitiveValue> m_value; }; static const CalculationCategory addSubtractResult[CalcOther][CalcOther] = { @@ -315,9 +299,6 @@ static CalculationCategory determineCategory(const CSSCalcExpressionNode& leftSi if (leftCategory == CalcOther || rightCategory == CalcOther) return CalcOther; - if (leftCategory == CalcVariable || rightCategory == CalcVariable) - return CalcVariable; - switch (op) { case CalcAdd: case CalcSubtract: @@ -344,21 +325,20 @@ static bool isIntegerResult(const CSSCalcExpressionNode* leftSide, const CSSCalc return op != CalcDivide && leftSide->isInteger() && rightSide->isInteger(); } -class CSSCalcBinaryOperation : public CSSCalcExpressionNode { - +class CSSCalcBinaryOperation FINAL : public CSSCalcExpressionNode { public: - static PassRefPtr<CSSCalcExpressionNode> create(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) + static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> create(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) { ASSERT(leftSide->category() != CalcOther && rightSide->category() != CalcOther); CalculationCategory newCategory = determineCategory(*leftSide, *rightSide, op); if (newCategory == CalcOther) - return 0; + return nullptr; - return adoptRef(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory)); + return adoptRefWillBeNoop(new CSSCalcBinaryOperation(leftSide, rightSide, op, newCategory)); } - static PassRefPtr<CSSCalcExpressionNode> createSimplified(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) + static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createSimplified(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) { CalculationCategory leftCategory = leftSide->category(); CalculationCategory rightCategory = rightSide->category(); @@ -368,21 +348,21 @@ public: // Simplify numbers. if (leftCategory == CalcNumber && rightCategory == CalcNumber) { - CSSPrimitiveValue::UnitTypes evaluationType = isInteger ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER; + CSSPrimitiveValue::UnitType evaluationType = isInteger ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER; return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), evaluationType, isInteger); } // Simplify addition and subtraction between same types. if (op == CalcAdd || op == CalcSubtract) { if (leftCategory == rightSide->category()) { - CSSPrimitiveValue::UnitTypes leftType = leftSide->primitiveType(); + CSSPrimitiveValue::UnitType leftType = leftSide->primitiveType(); if (hasDoubleValue(leftType)) { - CSSPrimitiveValue::UnitTypes rightType = rightSide->primitiveType(); + CSSPrimitiveValue::UnitType rightType = rightSide->primitiveType(); if (leftType == rightType) return CSSCalcPrimitiveValue::create(evaluateOperator(leftSide->doubleValue(), rightSide->doubleValue(), op), leftType, isInteger); CSSPrimitiveValue::UnitCategory leftUnitCategory = CSSPrimitiveValue::unitCategory(leftType); if (leftUnitCategory != CSSPrimitiveValue::UOther && leftUnitCategory == CSSPrimitiveValue::unitCategory(rightType)) { - CSSPrimitiveValue::UnitTypes canonicalType = CSSPrimitiveValue::canonicalUnitTypeForCategory(leftUnitCategory); + CSSPrimitiveValue::UnitType canonicalType = CSSPrimitiveValue::canonicalUnitTypeForCategory(leftUnitCategory); if (canonicalType != CSSPrimitiveValue::CSS_UNKNOWN) { double leftValue = leftSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(leftType); double rightValue = rightSide->doubleValue() * CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(rightType); @@ -398,16 +378,16 @@ public: if (!numberSide) return create(leftSide, rightSide, op); if (numberSide == leftSide && op == CalcDivide) - return 0; + return nullptr; CSSCalcExpressionNode* otherSide = leftSide == numberSide ? rightSide.get() : leftSide.get(); double number = numberSide->doubleValue(); if (std::isnan(number) || std::isinf(number)) - return 0; + return nullptr; if (op == CalcDivide && !number) - return 0; + return nullptr; - CSSPrimitiveValue::UnitTypes otherType = otherSide->primitiveType(); + CSSPrimitiveValue::UnitType otherType = otherSide->primitiveType(); if (hasDoubleValue(otherType)) return CSSCalcPrimitiveValue::create(evaluateOperator(otherSide->doubleValue(), number, op), otherType, isInteger); } @@ -415,34 +395,77 @@ public: return create(leftSide, rightSide, op); } - virtual bool isZero() const + virtual bool isZero() const OVERRIDE { return !doubleValue(); } - virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const CSSToLengthConversionData& conversionData) const + virtual void accumulatePixelsAndPercent(const CSSToLengthConversionData& conversionData, PixelsAndPercent& value, float multiplier) const OVERRIDE { - OwnPtr<CalcExpressionNode> left(m_leftSide->toCalcValue(conversionData)); - if (!left) - return nullptr; - OwnPtr<CalcExpressionNode> right(m_rightSide->toCalcValue(conversionData)); - if (!right) - return nullptr; - return adoptPtr(new CalcExpressionBinaryOperation(left.release(), right.release(), m_operator)); + switch (m_operator) { + case CalcAdd: + m_leftSide->accumulatePixelsAndPercent(conversionData, value, multiplier); + m_rightSide->accumulatePixelsAndPercent(conversionData, value, multiplier); + break; + case CalcSubtract: + m_leftSide->accumulatePixelsAndPercent(conversionData, value, multiplier); + m_rightSide->accumulatePixelsAndPercent(conversionData, value, -multiplier); + break; + case CalcMultiply: + ASSERT((m_leftSide->category() == CalcNumber) != (m_rightSide->category() == CalcNumber)); + if (m_leftSide->category() == CalcNumber) + m_rightSide->accumulatePixelsAndPercent(conversionData, value, multiplier * m_leftSide->doubleValue()); + else + m_leftSide->accumulatePixelsAndPercent(conversionData, value, multiplier * m_rightSide->doubleValue()); + break; + case CalcDivide: + ASSERT(m_rightSide->category() == CalcNumber); + m_leftSide->accumulatePixelsAndPercent(conversionData, value, multiplier / m_rightSide->doubleValue()); + break; + default: + ASSERT_NOT_REACHED(); + } } - virtual double doubleValue() const + virtual double doubleValue() const OVERRIDE { return evaluate(m_leftSide->doubleValue(), m_rightSide->doubleValue()); } - virtual double computeLengthPx(const CSSToLengthConversionData& conversionData) const + virtual double computeLengthPx(const CSSToLengthConversionData& conversionData) const OVERRIDE { const double leftValue = m_leftSide->computeLengthPx(conversionData); const double rightValue = m_rightSide->computeLengthPx(conversionData); return evaluate(leftValue, rightValue); } + virtual void accumulateLengthArray(CSSLengthArray& lengthArray, double multiplier) const + { + switch (m_operator) { + case CalcAdd: + m_leftSide->accumulateLengthArray(lengthArray, multiplier); + m_rightSide->accumulateLengthArray(lengthArray, multiplier); + break; + case CalcSubtract: + m_leftSide->accumulateLengthArray(lengthArray, multiplier); + m_rightSide->accumulateLengthArray(lengthArray, -multiplier); + break; + case CalcMultiply: + ASSERT((m_leftSide->category() == CalcNumber) != (m_rightSide->category() == CalcNumber)); + if (m_leftSide->category() == CalcNumber) + m_rightSide->accumulateLengthArray(lengthArray, multiplier * m_leftSide->doubleValue()); + else + m_leftSide->accumulateLengthArray(lengthArray, multiplier * m_rightSide->doubleValue()); + break; + case CalcDivide: + ASSERT(m_rightSide->category() == CalcNumber); + m_leftSide->accumulateLengthArray(lengthArray, multiplier / m_rightSide->doubleValue()); + break; + default: + ASSERT_NOT_REACHED(); + } + } + static String buildCSSText(const String& leftExpression, const String& rightExpression, CalcOperator op) { StringBuilder result; @@ -457,22 +480,12 @@ public: return result.toString(); } - virtual String customCSSText() const + virtual String customCSSText() const OVERRIDE { return buildCSSText(m_leftSide->customCSSText(), m_rightSide->customCSSText(), m_operator); } - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const - { - return buildCSSText(m_leftSide->serializeResolvingVariables(variables), m_rightSide->serializeResolvingVariables(variables), m_operator); - } - - virtual bool hasVariableReference() const - { - return m_leftSide->hasVariableReference() || m_rightSide->hasVariableReference(); - } - - virtual bool equals(const CSSCalcExpressionNode& exp) const + virtual bool equals(const CSSCalcExpressionNode& exp) const OVERRIDE { if (type() != exp.type()) return false; @@ -483,9 +496,9 @@ public: && m_operator == other.m_operator; } - virtual Type type() const { return CssCalcBinaryOperation; } + virtual Type type() const OVERRIDE { return CssCalcBinaryOperation; } - virtual CSSPrimitiveValue::UnitTypes primitiveType() const + virtual CSSPrimitiveValue::UnitType primitiveType() const OVERRIDE { switch (m_category) { case CalcNumber: @@ -499,13 +512,11 @@ public: return m_rightSide->primitiveType(); if (m_rightSide->category() == CalcNumber) return m_leftSide->primitiveType(); - CSSPrimitiveValue::UnitTypes leftType = m_leftSide->primitiveType(); + CSSPrimitiveValue::UnitType leftType = m_leftSide->primitiveType(); if (leftType == m_rightSide->primitiveType()) return leftType; return CSSPrimitiveValue::CSS_UNKNOWN; } - case CalcVariable: - return CSSPrimitiveValue::CSS_VARIABLE_NAME; case CalcPercentLength: case CalcPercentNumber: case CalcOther: @@ -515,9 +526,15 @@ public: return CSSPrimitiveValue::CSS_UNKNOWN; } + virtual void trace(Visitor* visitor) + { + visitor->trace(m_leftSide); + visitor->trace(m_rightSide); + CSSCalcExpressionNode::trace(visitor); + } private: - CSSCalcBinaryOperation(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op, CalculationCategory category) + CSSCalcBinaryOperation(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op, CalculationCategory category) : CSSCalcExpressionNode(category, isIntegerResult(leftSide.get(), rightSide.get(), op)) , m_leftSide(leftSide) , m_rightSide(rightSide) @@ -556,8 +573,8 @@ private: return 0; } - const RefPtr<CSSCalcExpressionNode> m_leftSide; - const RefPtr<CSSCalcExpressionNode> m_rightSide; + const RefPtrWillBeMember<CSSCalcExpressionNode> m_leftSide; + const RefPtrWillBeMember<CSSCalcExpressionNode> m_rightSide; const CalcOperator m_operator; }; @@ -572,21 +589,24 @@ static ParseState checkDepthAndIndex(int* depth, unsigned index, CSSParserValueL } class CSSCalcExpressionNodeParser { + STACK_ALLOCATED(); public: - PassRefPtr<CSSCalcExpressionNode> parseCalc(CSSParserValueList* tokens) + PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> parseCalc(CSSParserValueList* tokens) { unsigned index = 0; Value result; bool ok = parseValueExpression(tokens, 0, &index, &result); ASSERT_WITH_SECURITY_IMPLICATION(index <= tokens->size()); if (!ok || index != tokens->size()) - return 0; + return nullptr; return result.value; } private: struct Value { - RefPtr<CSSCalcExpressionNode> value; + STACK_ALLOCATED(); + public: + RefPtrWillBeMember<CSSCalcExpressionNode> value; }; char operatorValue(CSSParserValueList* tokens, unsigned index) @@ -603,14 +623,18 @@ private: bool parseValue(CSSParserValueList* tokens, unsigned* index, Value* result) { CSSParserValue* parserValue = tokens->valueAt(*index); - if (parserValue->unit == CSSParserValue::Operator || parserValue->unit == CSSParserValue::Function) + if (parserValue->unit == CSSParserValue::Operator) return false; - RefPtr<CSSValue> value = parserValue->createCSSValue(); + RefPtrWillBeRawPtr<CSSValue> value = parserValue->createCSSValue(); if (!value || !value->isPrimitiveValue()) return false; - result->value = CSSCalcPrimitiveValue::create(toCSSPrimitiveValue(value.get()), parserValue->isInt); + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get()); + if (unitCategory(primitiveValue->primitiveType()) == CalcOther) + return false; + + result->value = CSSCalcPrimitiveValue::create(primitiveValue, parserValue->isInt); ++*index; return true; @@ -695,96 +719,45 @@ private: } }; -PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtr<CSSPrimitiveValue> value, bool isInteger) +PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> value, bool isInteger) { return CSSCalcPrimitiveValue::create(value, isInteger); } -PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtr<CSSCalcExpressionNode> leftSide, PassRefPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) +PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> leftSide, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> rightSide, CalcOperator op) { return CSSCalcBinaryOperation::create(leftSide, rightSide, op); } -PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(const CalcExpressionNode* node, float zoom) -{ - switch (node->type()) { - case CalcExpressionNodeNumber: { - float value = toCalcExpressionNumber(node)->value(); - return createExpressionNode(CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER), value == trunc(value)); - } - case CalcExpressionNodeLength: - return createExpressionNode(toCalcExpressionLength(node)->length(), zoom); - case CalcExpressionNodeBinaryOperation: { - const CalcExpressionBinaryOperation* binaryNode = toCalcExpressionBinaryOperation(node); - return createExpressionNode(createExpressionNode(binaryNode->leftSide(), zoom), createExpressionNode(binaryNode->rightSide(), zoom), binaryNode->getOperator()); - } - case CalcExpressionNodeBlendLength: { - // FIXME(crbug.com/269320): Create a CSSCalcExpressionNode equivalent of CalcExpressionBlendLength. - const CalcExpressionBlendLength* blendNode = toCalcExpressionBlendLength(node); - const double progress = blendNode->progress(); - const bool isInteger = !progress || (progress == 1); - return createExpressionNode( - createExpressionNode( - createExpressionNode(blendNode->from(), zoom), - createExpressionNode(CSSPrimitiveValue::create(1 - progress, CSSPrimitiveValue::CSS_NUMBER), isInteger), - CalcMultiply), - createExpressionNode( - createExpressionNode(blendNode->to(), zoom), - createExpressionNode(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER), isInteger), - CalcMultiply), - CalcAdd); - } - case CalcExpressionNodeUndefined: - ASSERT_NOT_REACHED(); - return 0; - } - ASSERT_NOT_REACHED(); - return 0; -} - -PassRefPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(const Length& length, float zoom) +PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> CSSCalcValue::createExpressionNode(double pixels, double percent) { - switch (length.type()) { - case Percent: - case ViewportPercentageWidth: - case ViewportPercentageHeight: - case ViewportPercentageMin: - case ViewportPercentageMax: - case Fixed: - return createExpressionNode(CSSPrimitiveValue::create(length, zoom), length.value() == trunc(length.value())); - case Calculated: - return createExpressionNode(length.calculationValue()->expression(), zoom); - case Auto: - case Intrinsic: - case MinIntrinsic: - case MinContent: - case MaxContent: - case FillAvailable: - case FitContent: - case ExtendToZoom: - case Undefined: - ASSERT_NOT_REACHED(); - return 0; - } - ASSERT_NOT_REACHED(); - return 0; + return createExpressionNode( + createExpressionNode(CSSPrimitiveValue::create(pixels, CSSPrimitiveValue::CSS_PX), pixels == trunc(pixels)), + createExpressionNode(CSSPrimitiveValue::create(percent, CSSPrimitiveValue::CSS_PERCENTAGE), percent == trunc(percent)), + CalcAdd); } -PassRefPtr<CSSCalcValue> CSSCalcValue::create(CSSParserString name, CSSParserValueList* parserValueList, ValueRange range) +PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(CSSParserString name, CSSParserValueList* parserValueList, ValueRange range) { CSSCalcExpressionNodeParser parser; - RefPtr<CSSCalcExpressionNode> expression; + RefPtrWillBeRawPtr<CSSCalcExpressionNode> expression = nullptr; if (equalIgnoringCase(name, "calc(") || equalIgnoringCase(name, "-webkit-calc(")) expression = parser.parseCalc(parserValueList); // FIXME calc (http://webkit.org/b/16662) Add parsing for min and max here - return expression ? adoptRef(new CSSCalcValue(expression, range)) : 0; + return expression ? adoptRefWillBeNoop(new CSSCalcValue(expression, range)) : nullptr; +} + +PassRefPtrWillBeRawPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> expression, ValueRange range) +{ + return adoptRefWillBeNoop(new CSSCalcValue(expression, range)); } -PassRefPtr<CSSCalcValue> CSSCalcValue::create(PassRefPtr<CSSCalcExpressionNode> expression, ValueRange range) +void CSSCalcValue::traceAfterDispatch(Visitor* visitor) { - return adoptRef(new CSSCalcValue(expression, range)); + visitor->trace(m_expression); + CSSValue::traceAfterDispatch(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.h b/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.h index 6d58d608931..a7678850ffb 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSCalculationValue.h @@ -47,43 +47,51 @@ class CalculationValue; class CalcExpressionNode; class Length; +enum CalcOperator { + CalcAdd = '+', + CalcSubtract = '-', + CalcMultiply = '*', + CalcDivide = '/' +}; + enum CalculationCategory { CalcNumber = 0, CalcLength, CalcPercent, CalcPercentNumber, CalcPercentLength, - CalcVariable, CalcOther }; -class CSSCalcExpressionNode : public RefCounted<CSSCalcExpressionNode> { +class CSSCalcExpressionNode : public RefCountedWillBeGarbageCollected<CSSCalcExpressionNode> { + DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(CSSCalcExpressionNode); public: enum Type { CssCalcPrimitiveValue = 1, CssCalcBinaryOperation }; - virtual ~CSSCalcExpressionNode() = 0; virtual bool isZero() const = 0; - virtual PassOwnPtr<CalcExpressionNode> toCalcValue(const CSSToLengthConversionData&) const = 0; virtual double doubleValue() const = 0; virtual double computeLengthPx(const CSSToLengthConversionData&) const = 0; + virtual void accumulateLengthArray(CSSLengthArray&, double multiplier) const = 0; + virtual void accumulatePixelsAndPercent(const CSSToLengthConversionData&, PixelsAndPercent&, float multiplier = 1) const = 0; virtual String customCSSText() const = 0; - virtual String serializeResolvingVariables(const HashMap<AtomicString, String>&) const = 0; - virtual bool hasVariableReference() const = 0; virtual bool equals(const CSSCalcExpressionNode& other) const { return m_category == other.m_category && m_isInteger == other.m_isInteger; } virtual Type type() const = 0; CalculationCategory category() const { return m_category; } - virtual CSSPrimitiveValue::UnitTypes primitiveType() const = 0; + virtual CSSPrimitiveValue::UnitType primitiveType() const = 0; bool isInteger() const { return m_isInteger; } + virtual void trace(Visitor*) { } + protected: CSSCalcExpressionNode(CalculationCategory category, bool isInteger) : m_category(category) , m_isInteger(isInteger) { + ASSERT(category != CalcOther); } CalculationCategory m_category; @@ -92,18 +100,18 @@ protected: class CSSCalcValue : public CSSValue { public: - static PassRefPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList*, ValueRange); - static PassRefPtr<CSSCalcValue> create(PassRefPtr<CSSCalcExpressionNode>, ValueRange = ValueRangeAll); - static PassRefPtr<CSSCalcValue> create(const CalculationValue* value, float zoom) { return adoptRef(new CSSCalcValue(value, zoom)); } + static PassRefPtrWillBeRawPtr<CSSCalcValue> create(CSSParserString name, CSSParserValueList*, ValueRange); + static PassRefPtrWillBeRawPtr<CSSCalcValue> create(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode>, ValueRange = ValueRangeAll); - static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSPrimitiveValue>, bool isInteger = false); - static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtr<CSSCalcExpressionNode>, PassRefPtr<CSSCalcExpressionNode>, CalcOperator); - static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const CalcExpressionNode*, float zoom); - static PassRefPtr<CSSCalcExpressionNode> createExpressionNode(const Length&, float zoom); + static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtrWillBeRawPtr<CSSPrimitiveValue>, bool isInteger = false); + static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createExpressionNode(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode>, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode>, CalcOperator); + static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createExpressionNode(double pixels, double percent); PassRefPtr<CalculationValue> toCalcValue(const CSSToLengthConversionData& conversionData) const { - return CalculationValue::create(m_expression->toCalcValue(conversionData), m_nonNegative ? ValueRangeNonNegative : ValueRangeAll); + PixelsAndPercent value(0, 0); + m_expression->accumulatePixelsAndPercent(conversionData, value); + return CalculationValue::create(value, m_nonNegative ? ValueRangeNonNegative : ValueRangeAll); } CalculationCategory category() const { return m_expression->category(); } bool isInt() const { return m_expression->isInteger(); } @@ -111,30 +119,25 @@ public: bool isNegative() const { return m_expression->doubleValue() < 0; } ValueRange permittedValueRange() { return m_nonNegative ? ValueRangeNonNegative : ValueRangeAll; } double computeLengthPx(const CSSToLengthConversionData&) const; + void accumulateLengthArray(CSSLengthArray& lengthArray, double multiplier) const { m_expression->accumulateLengthArray(lengthArray, multiplier); } CSSCalcExpressionNode* expressionNode() const { return m_expression.get(); } String customCSSText() const; bool equals(const CSSCalcValue&) const; - String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const; - bool hasVariableReference() const; + + void traceAfterDispatch(Visitor*); private: - CSSCalcValue(PassRefPtr<CSSCalcExpressionNode> expression, ValueRange range) + CSSCalcValue(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> expression, ValueRange range) : CSSValue(CalculationClass) , m_expression(expression) , m_nonNegative(range == ValueRangeNonNegative) { } - CSSCalcValue(const CalculationValue* value, float zoom) - : CSSValue(CalculationClass) - , m_expression(createExpressionNode(value->expression(), zoom)) - , m_nonNegative(value->isNonNegative()) - { - } double clampToPermittedRange(double) const; - const RefPtr<CSSCalcExpressionNode> m_expression; + const RefPtrWillBeMember<CSSCalcExpressionNode> m_expression; const bool m_nonNegative; }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp b/chromium/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp index 57875523784..76179e5c653 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp @@ -33,116 +33,166 @@ #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSToLengthConversionData.h" +#include "core/css/StylePropertySet.h" #include "core/rendering/style/RenderStyle.h" #include "core/rendering/style/StyleInheritedData.h" #include <gtest/gtest.h> + +namespace WebCore { + +void PrintTo(const CSSLengthArray& lengthArray, ::std::ostream* os) +{ + for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i) + *os << lengthArray.at(i) << ' '; +} + +} + using namespace WebCore; namespace { -void testExpression(PassRefPtr<CSSCalcExpressionNode> expression, const RenderStyle* style) +void testAccumulatePixelsAndPercent(const CSSToLengthConversionData& conversionData, PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> expression, float expectedPixels, float expectedPercent) { - EXPECT_TRUE( - expression->equals( - *CSSCalcValue::createExpressionNode( - expression->toCalcValue(CSSToLengthConversionData(style, style)).get(), - style->effectiveZoom()).get())); + PixelsAndPercent value(0, 0); + expression->accumulatePixelsAndPercent(conversionData, value); + EXPECT_EQ(expectedPixels, value.pixels); + EXPECT_EQ(expectedPercent, value.percent); } -TEST(CSSCalculationValue, CreateExpressionNodeFromLength) +void initLengthArray(CSSLengthArray& lengthArray) { - RefPtr<RenderStyle> style = RenderStyle::create(); - RefPtr<CSSCalcExpressionNode> expected; - RefPtr<CSSCalcExpressionNode> actual; + lengthArray.resize(CSSPrimitiveValue::LengthUnitTypeCount); + for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i) + lengthArray.at(i) = 0; +} - expected = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(10, CSSPrimitiveValue::CSS_PX), true); - actual = CSSCalcValue::createExpressionNode(Length(10, WebCore::Fixed), style->effectiveZoom()); - EXPECT_TRUE(actual->equals(*expected.get())); +CSSLengthArray& setLengthArray(CSSLengthArray& lengthArray, String text) +{ + initLengthArray(lengthArray); + RefPtr<MutableStylePropertySet> propertySet = MutableStylePropertySet::create(); + propertySet->setProperty(CSSPropertyLeft, text); + toCSSPrimitiveValue(propertySet->getPropertyCSSValue(CSSPropertyLeft).get())->accumulateLengthArray(lengthArray); + return lengthArray; +} - expected = CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(10, CSSPrimitiveValue::CSS_PX), true), - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(20, CSSPrimitiveValue::CSS_PX), true), - CalcAdd); - actual = CSSCalcValue::createExpressionNode( - Length(CalculationValue::create( - adoptPtr(new CalcExpressionBinaryOperation( - adoptPtr(new CalcExpressionLength(Length(10, WebCore::Fixed))), - adoptPtr(new CalcExpressionLength(Length(20, WebCore::Fixed))), - CalcAdd)), - ValueRangeAll)), - style->effectiveZoom()); - EXPECT_TRUE(actual->equals(*expected.get())); - - expected = CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(30, CSSPrimitiveValue::CSS_PX), true), - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(40, CSSPrimitiveValue::CSS_NUMBER), true), - CalcMultiply); - actual = CSSCalcValue::createExpressionNode( - Length(CalculationValue::create( - adoptPtr(new CalcExpressionBinaryOperation( - adoptPtr(new CalcExpressionLength(Length(30, WebCore::Fixed))), - adoptPtr(new CalcExpressionNumber(40)), - CalcMultiply)), - ValueRangeAll)), - style->effectiveZoom()); - EXPECT_TRUE(actual->equals(*expected.get())); - - expected = CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(50, CSSPrimitiveValue::CSS_PX), true), - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(0.25, CSSPrimitiveValue::CSS_NUMBER), false), - CalcMultiply), - CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(60, CSSPrimitiveValue::CSS_PX), true), - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(0.75, CSSPrimitiveValue::CSS_NUMBER), false), - CalcMultiply), - CalcAdd); - actual = CSSCalcValue::createExpressionNode( - Length(CalculationValue::create( - adoptPtr(new CalcExpressionBlendLength(Length(50, WebCore::Fixed), Length(60, WebCore::Fixed), 0.75)), - ValueRangeAll)), - style->effectiveZoom()); - EXPECT_TRUE(actual->equals(*expected.get())); +bool lengthArraysEqual(CSSLengthArray& a, CSSLengthArray& b) +{ + for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i) { + if (a.at(i) != b.at(i)) + return false; + } + return true; } -TEST(CSSCalculationValue, CreateExpressionNodeFromLengthFromExpressionNode) +TEST(CSSCalculationValue, AccumulatePixelsAndPercent) { - RefPtr<CSSCalcExpressionNode> expression; RefPtr<RenderStyle> style = RenderStyle::createDefaultStyle(); style->setEffectiveZoom(5); + CSSToLengthConversionData conversionData(style.get(), style.get(), 0); - testExpression( + testAccumulatePixelsAndPercent(conversionData, CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(10, CSSPrimitiveValue::CSS_PX), true), - style.get()); + 50, 0); - testExpression( + testAccumulatePixelsAndPercent(conversionData, CSSCalcValue::createExpressionNode( CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(10, CSSPrimitiveValue::CSS_PX), true), CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(20, CSSPrimitiveValue::CSS_PX), true), CalcAdd), - style.get()); + 150, 0); - testExpression( + testAccumulatePixelsAndPercent(conversionData, CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(30, CSSPrimitiveValue::CSS_PX), true), - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(40, CSSPrimitiveValue::CSS_NUMBER), true), + CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_IN), true), + CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(2, CSSPrimitiveValue::CSS_NUMBER), true), CalcMultiply), - style.get()); + 960, 0); - testExpression( + testAccumulatePixelsAndPercent(conversionData, CSSCalcValue::createExpressionNode( CSSCalcValue::createExpressionNode( CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(50, CSSPrimitiveValue::CSS_PX), true), CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(0.25, CSSPrimitiveValue::CSS_NUMBER), false), CalcMultiply), CSSCalcValue::createExpressionNode( - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(60, CSSPrimitiveValue::CSS_PX), true), - CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(0.75, CSSPrimitiveValue::CSS_NUMBER), false), - CalcMultiply), - CalcAdd), - style.get()); + CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(20, CSSPrimitiveValue::CSS_PX), true), + CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(40, CSSPrimitiveValue::CSS_PERCENTAGE), false), + CalcSubtract), + CalcSubtract), + -37.5, 40); +} + +TEST(CSSCalculationValue, RefCount) +{ + RefPtr<CalculationValue> calc = CalculationValue::create(PixelsAndPercent(1, 2), ValueRangeAll); + Length lengthA(calc); + EXPECT_EQ(calc->refCount(), 2); + + Length lengthB; + lengthB = lengthA; + EXPECT_EQ(calc->refCount(), 3); + + Length lengthC(calc); + lengthC = lengthA; + EXPECT_EQ(calc->refCount(), 4); + + Length lengthD(CalculationValue::create(PixelsAndPercent(1, 2), ValueRangeAll)); + lengthD = lengthA; + EXPECT_EQ(calc->refCount(), 5); +} + +TEST(CSSCalculationValue, RefCountLeak) +{ + RefPtr<CalculationValue> calc = CalculationValue::create(PixelsAndPercent(1, 2), ValueRangeAll); + Length lengthA(calc); + + Length lengthB = lengthA; + for (int i = 0; i < 100; ++i) + lengthB = lengthA; + EXPECT_EQ(calc->refCount(), 3); + + Length lengthC(lengthA); + for (int i = 0; i < 100; ++i) + lengthC = lengthA; + EXPECT_EQ(calc->refCount(), 4); + + Length lengthD(calc); + for (int i = 0; i < 100; ++i) + lengthD = lengthA; + EXPECT_EQ(calc->refCount(), 5); + + lengthD = Length(); + EXPECT_EQ(calc->refCount(), 4); +} + +TEST(CSSCalculationValue, AddToLengthUnitValues) +{ + CSSLengthArray expectation, actual; + initLengthArray(expectation); + EXPECT_TRUE(lengthArraysEqual(expectation, setLengthArray(actual, "0"))); + + expectation.at(CSSPrimitiveValue::UnitTypePixels) = 10; + EXPECT_TRUE(lengthArraysEqual(expectation, setLengthArray(actual, "10px"))); + + expectation.at(CSSPrimitiveValue::UnitTypePixels) = 0; + expectation.at(CSSPrimitiveValue::UnitTypePercentage) = 20; + EXPECT_TRUE(lengthArraysEqual(expectation, setLengthArray(actual, "20%%"))); + + expectation.at(CSSPrimitiveValue::UnitTypePixels) = 30; + expectation.at(CSSPrimitiveValue::UnitTypePercentage) = -40; + EXPECT_TRUE(lengthArraysEqual(expectation, setLengthArray(actual, "calc(30px - 40%%)"))); + + expectation.at(CSSPrimitiveValue::UnitTypePixels) = 90; + expectation.at(CSSPrimitiveValue::UnitTypePercentage) = 10; + EXPECT_TRUE(lengthArraysEqual(expectation, setLengthArray(actual, "calc(1in + 10%% - 6px)"))); + + expectation.at(CSSPrimitiveValue::UnitTypePixels) = 15; + expectation.at(CSSPrimitiveValue::UnitTypeFontSize) = 20; + expectation.at(CSSPrimitiveValue::UnitTypePercentage) = -40; + EXPECT_TRUE(lengthArraysEqual(expectation, setLengthArray(actual, "calc((1 * 2) * (5px + 20em / 2) - 80%% / (3 - 1) + 5px)"))); } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.cpp index ce46f047472..d770846aa40 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.cpp @@ -33,8 +33,10 @@ namespace WebCore { CSSCanvasValue::~CSSCanvasValue() { +#if !ENABLE(OILPAN) if (m_element) - m_element->removeObserver(&m_canvasObserver); + m_element->removeObserver(m_canvasObserver.get()); +#endif } String CSSCanvasValue::customCSSText() const @@ -61,11 +63,13 @@ void CSSCanvasValue::canvasResized(HTMLCanvasElement*) const_cast<RenderObject*>(curr->key)->imageChanged(static_cast<WrappedImagePtr>(this)); } +#if !ENABLE(OILPAN) void CSSCanvasValue::canvasDestroyed(HTMLCanvasElement* element) { ASSERT_UNUSED(element, element == m_element); - m_element = 0; + m_element = nullptr; } +#endif IntSize CSSCanvasValue::fixedSize(const RenderObject* renderer) { @@ -77,10 +81,8 @@ IntSize CSSCanvasValue::fixedSize(const RenderObject* renderer) HTMLCanvasElement* CSSCanvasValue::element(Document* document) { if (!m_element) { - m_element = document->getCSSCanvasElement(m_name); - if (!m_element) - return 0; - m_element->addObserver(&m_canvasObserver); + m_element = &document->getCSSCanvasElement(m_name); + m_element->addObserver(m_canvasObserver.get()); } return m_element; } @@ -90,7 +92,7 @@ PassRefPtr<Image> CSSCanvasValue::image(RenderObject* renderer, const IntSize& / ASSERT(clients().contains(renderer)); HTMLCanvasElement* elt = element(&renderer->document()); if (!elt || !elt->buffer()) - return 0; + return nullptr; return elt->copiedImage(); } @@ -99,4 +101,11 @@ bool CSSCanvasValue::equals(const CSSCanvasValue& other) const return m_name == other.m_name; } +void CSSCanvasValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_canvasObserver); + visitor->trace(m_element); + CSSImageGeneratorValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.h b/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.h index bb2325f2b8b..3e23b7eb0eb 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSCanvasValue.h @@ -35,7 +35,10 @@ class Document; class CSSCanvasValue : public CSSImageGeneratorValue { public: - static PassRefPtr<CSSCanvasValue> create(const String& name) { return adoptRef(new CSSCanvasValue(name)); } + static PassRefPtrWillBeRawPtr<CSSCanvasValue> create(const String& name) + { + return adoptRefWillBeNoop(new CSSCanvasValue(name)); + } ~CSSCanvasValue(); String customCSSText() const; @@ -49,49 +52,63 @@ public: bool equals(const CSSCanvasValue&) const; + void traceAfterDispatch(Visitor*); + private: explicit CSSCanvasValue(const String& name) : CSSImageGeneratorValue(CanvasClass) - , m_canvasObserver(this) + , m_canvasObserver(adoptPtrWillBeNoop(new CanvasObserverProxy(this))) , m_name(name) - , m_element(0) + , m_element(nullptr) { } // NOTE: We put the CanvasObserver in a member instead of inheriting from it // to avoid adding a vptr to CSSCanvasValue. - class CanvasObserverProxy : public CanvasObserver { + class CanvasObserverProxy FINAL : public NoBaseWillBeGarbageCollected<CanvasObserverProxy>, public CanvasObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(CanvasObserverProxy); public: - CanvasObserverProxy(CSSCanvasValue* ownerValue) : m_ownerValue(ownerValue) { } - virtual ~CanvasObserverProxy() { } - virtual void canvasChanged(HTMLCanvasElement* canvas, const FloatRect& changedRect) + explicit CanvasObserverProxy(CSSCanvasValue* ownerValue) : m_ownerValue(ownerValue) { } + + virtual void canvasChanged(HTMLCanvasElement* canvas, const FloatRect& changedRect) OVERRIDE { m_ownerValue->canvasChanged(canvas, changedRect); } - virtual void canvasResized(HTMLCanvasElement* canvas) + virtual void canvasResized(HTMLCanvasElement* canvas) OVERRIDE { m_ownerValue->canvasResized(canvas); } - virtual void canvasDestroyed(HTMLCanvasElement* canvas) +#if !ENABLE(OILPAN) + virtual void canvasDestroyed(HTMLCanvasElement* canvas) OVERRIDE { m_ownerValue->canvasDestroyed(canvas); } +#endif + virtual void trace(Visitor* visitor) OVERRIDE + { + visitor->trace(m_ownerValue); + CanvasObserver::trace(visitor); + } + private: - CSSCanvasValue* m_ownerValue; + RawPtrWillBeMember<CSSCanvasValue> m_ownerValue; }; void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect); void canvasResized(HTMLCanvasElement*); + +#if !ENABLE(OILPAN) void canvasDestroyed(HTMLCanvasElement*); +#endif HTMLCanvasElement* element(Document*); - CanvasObserverProxy m_canvasObserver; + OwnPtrWillBeMember<CanvasObserverProxy> m_canvasObserver; // The name of the canvas. String m_name; // The document supplies the element and owns it. - HTMLCanvasElement* m_element; + RawPtrWillBeWeakMember<HTMLCanvasElement> m_element; }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSCanvasValue, isCanvasValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.h b/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.h index 26ae5fd793f..01c3a306c4a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.h @@ -28,11 +28,11 @@ namespace WebCore { class ExceptionState; -class CSSCharsetRule : public CSSRule { +class CSSCharsetRule FINAL : public CSSRule { public: - static PassRefPtr<CSSCharsetRule> create(CSSStyleSheet* parent, const String& encoding) + static PassRefPtrWillBeRawPtr<CSSCharsetRule> create(CSSStyleSheet* parent, const String& encoding) { - return adoptRef(new CSSCharsetRule(parent, encoding)); + return adoptRefWillBeNoop(new CSSCharsetRule(parent, encoding)); } virtual ~CSSCharsetRule() { } @@ -44,6 +44,8 @@ public: const String& encoding() const { return m_encoding; } void setEncoding(const String& encoding) { m_encoding = encoding; } + virtual void trace(Visitor* visitor) OVERRIDE { CSSRule::trace(visitor); } + private: CSSCharsetRule(CSSStyleSheet* parent, const String& encoding); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.idl b/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.idl index 18216075aba..1635a719012 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSCharsetRule.idl @@ -19,5 +19,5 @@ */ interface CSSCharsetRule : CSSRule { - attribute DOMString encoding; + [MeasureAs=CSSCharsetRuleEncoding] attribute DOMString encoding; }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp b/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp index d5888386226..733191a5147 100755..100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp @@ -24,11 +24,9 @@ #include "config.h" #include "core/css/CSSComputedStyleDeclaration.h" -#include "CSSPropertyNames.h" -#include "FontFamilyNames.h" -#include "RuntimeEnabledFeatures.h" -#include "StylePropertyShorthand.h" #include "bindings/v8/ExceptionState.h" +#include "core/CSSPropertyNames.h" +#include "core/StylePropertyShorthand.h" #include "core/animation/DocumentAnimations.h" #include "core/css/BasicShapeFunctions.h" #include "core/css/CSSArrayFunctionValue.h" @@ -39,10 +37,9 @@ #include "core/css/CSSFontValue.h" #include "core/css/CSSFunctionValue.h" #include "core/css/CSSGridLineNamesValue.h" -#include "core/css/CSSGridTemplateValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" #include "core/css/CSSLineBoxContainValue.h" -#include "core/css/CSSMixFunctionValue.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSReflectValue.h" @@ -60,23 +57,16 @@ #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/PseudoElement.h" -#include "core/frame/animation/AnimationController.h" #include "core/rendering/RenderBox.h" #include "core/rendering/RenderGrid.h" -#include "core/rendering/RenderView.h" #include "core/rendering/style/ContentData.h" #include "core/rendering/style/CounterContent.h" -#include "core/rendering/style/CursorList.h" #include "core/rendering/style/RenderStyle.h" #include "core/rendering/style/ShadowList.h" #include "core/rendering/style/ShapeValue.h" -#include "core/rendering/style/StyleCustomFilterProgram.h" +#include "platform/FontFamilyNames.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/fonts/FontFeatureSettings.h" -#include "platform/graphics/filters/custom/CustomFilterArrayParameter.h" -#include "platform/graphics/filters/custom/CustomFilterNumberParameter.h" -#include "platform/graphics/filters/custom/CustomFilterOperation.h" -#include "platform/graphics/filters/custom/CustomFilterParameter.h" -#include "platform/graphics/filters/custom/CustomFilterTransformParameter.h" #include "wtf/text/StringBuilder.h" namespace WebCore { @@ -141,10 +131,12 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyFontSize, CSSPropertyFontStyle, CSSPropertyFontVariant, + CSSPropertyFontVariantLigatures, CSSPropertyFontWeight, CSSPropertyHeight, CSSPropertyImageRendering, CSSPropertyIsolation, + CSSPropertyJustifySelf, CSSPropertyLeft, CSSPropertyLetterSpacing, CSSPropertyLineHeight, @@ -182,6 +174,7 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyPosition, CSSPropertyResize, CSSPropertyRight, + CSSPropertyScrollBehavior, CSSPropertySpeak, CSSPropertyTableLayout, CSSPropertyTabSize, @@ -211,6 +204,7 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyWhiteSpace, CSSPropertyWidows, CSSPropertyWidth, + CSSPropertyWillChange, CSSPropertyWordBreak, CSSPropertyWordSpacing, CSSPropertyWordWrap, @@ -226,6 +220,7 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyWebkitAnimationPlayState, CSSPropertyWebkitAnimationTimingFunction, CSSPropertyWebkitAppearance, + CSSPropertyBackfaceVisibility, CSSPropertyWebkitBackfaceVisibility, CSSPropertyWebkitBackgroundClip, CSSPropertyWebkitBackgroundComposite, @@ -250,10 +245,8 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyWebkitColumnBreakAfter, CSSPropertyWebkitColumnBreakBefore, CSSPropertyWebkitColumnBreakInside, - CSSPropertyWebkitColumnAxis, CSSPropertyWebkitColumnCount, CSSPropertyWebkitColumnGap, - CSSPropertyWebkitColumnProgression, CSSPropertyWebkitColumnRuleColor, CSSPropertyWebkitColumnRuleStyle, CSSPropertyWebkitColumnRuleWidth, @@ -270,24 +263,21 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyFlexWrap, CSSPropertyJustifyContent, CSSPropertyWebkitFontSmoothing, - CSSPropertyWebkitFontVariantLigatures, CSSPropertyGridAutoColumns, CSSPropertyGridAutoFlow, CSSPropertyGridAutoRows, CSSPropertyGridColumnEnd, CSSPropertyGridColumnStart, - CSSPropertyGridDefinitionColumns, - CSSPropertyGridDefinitionRows, + CSSPropertyGridTemplateAreas, + CSSPropertyGridTemplateColumns, + CSSPropertyGridTemplateRows, CSSPropertyGridRowEnd, CSSPropertyGridRowStart, CSSPropertyWebkitHighlight, CSSPropertyWebkitHyphenateCharacter, - CSSPropertyWebkitLineAlign, CSSPropertyWebkitLineBoxContain, CSSPropertyWebkitLineBreak, CSSPropertyWebkitLineClamp, - CSSPropertyWebkitLineGrid, - CSSPropertyWebkitLineSnap, CSSPropertyWebkitLocale, CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginAfterCollapse, @@ -305,13 +295,13 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyWebkitMaskRepeat, CSSPropertyWebkitMaskSize, CSSPropertyOrder, + CSSPropertyPerspective, CSSPropertyWebkitPerspective, + CSSPropertyPerspectiveOrigin, CSSPropertyWebkitPerspectiveOrigin, CSSPropertyWebkitPrintColorAdjust, CSSPropertyWebkitRtlOrdering, - CSSPropertyShapeInside, CSSPropertyShapeOutside, - CSSPropertyShapePadding, CSSPropertyShapeImageThreshold, CSSPropertyShapeMargin, CSSPropertyWebkitTapHighlightColor, @@ -325,8 +315,11 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyWebkitTextSecurity, CSSPropertyWebkitTextStrokeColor, CSSPropertyWebkitTextStrokeWidth, + CSSPropertyTransform, CSSPropertyWebkitTransform, + CSSPropertyTransformOrigin, CSSPropertyWebkitTransformOrigin, + CSSPropertyTransformStyle, CSSPropertyWebkitTransformStyle, CSSPropertyWebkitTransitionDelay, CSSPropertyWebkitTransitionDuration, @@ -336,12 +329,6 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyWebkitUserModify, CSSPropertyWebkitUserSelect, CSSPropertyWebkitWritingMode, - CSSPropertyWebkitFlowInto, - CSSPropertyWebkitFlowFrom, - CSSPropertyWebkitRegionBreakAfter, - CSSPropertyWebkitRegionBreakBefore, - CSSPropertyWebkitRegionBreakInside, - CSSPropertyWebkitRegionFragment, CSSPropertyWebkitAppRegion, CSSPropertyWebkitWrapFlow, CSSPropertyWebkitWrapThrough, @@ -378,7 +365,6 @@ static const CSSPropertyID staticComputableProperties[] = { CSSPropertyAlignmentBaseline, CSSPropertyBaselineShift, CSSPropertyDominantBaseline, - CSSPropertyKerning, CSSPropertyTextAnchor, CSSPropertyWritingMode, CSSPropertyGlyphOrientationHorizontal, @@ -409,13 +395,13 @@ static CSSValueID valueForRepeatRule(int rule) } } -static PassRefPtr<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image) +static PassRefPtrWillBeRawPtr<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image) { // Create the slices. - RefPtr<CSSPrimitiveValue> top; - RefPtr<CSSPrimitiveValue> right; - RefPtr<CSSPrimitiveValue> bottom; - RefPtr<CSSPrimitiveValue> left; + RefPtrWillBeRawPtr<CSSPrimitiveValue> top = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> right = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> bottom = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> left = nullptr; if (image.imageSlices().top().isPercent()) top = cssValuePool().createValue(image.imageSlices().top().value(), CSSPrimitiveValue::CSS_PERCENTAGE); @@ -453,7 +439,7 @@ static PassRefPtr<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const Ni } } - RefPtr<Quad> quad = Quad::create(); + RefPtrWillBeRawPtr<Quad> quad = Quad::create(); quad->setTop(top); quad->setRight(right); quad->setBottom(bottom); @@ -462,13 +448,13 @@ static PassRefPtr<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const Ni return CSSBorderImageSliceValue::create(cssValuePool().createValue(quad.release()), image.fill()); } -static PassRefPtr<CSSPrimitiveValue> valueForNinePieceImageQuad(const BorderImageLengthBox& box, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForNinePieceImageQuad(const BorderImageLengthBox& box, const RenderStyle& style) { // Create the slices. - RefPtr<CSSPrimitiveValue> top; - RefPtr<CSSPrimitiveValue> right; - RefPtr<CSSPrimitiveValue> bottom; - RefPtr<CSSPrimitiveValue> left; + RefPtrWillBeRawPtr<CSSPrimitiveValue> top = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> right = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> bottom = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> left = nullptr; if (box.top().isNumber()) top = cssValuePool().createValue(box.top().number(), CSSPrimitiveValue::CSS_NUMBER); @@ -505,7 +491,7 @@ static PassRefPtr<CSSPrimitiveValue> valueForNinePieceImageQuad(const BorderImag } } - RefPtr<Quad> quad = Quad::create(); + RefPtrWillBeRawPtr<Quad> quad = Quad::create(); quad->setTop(top); quad->setRight(right); quad->setBottom(bottom); @@ -514,10 +500,10 @@ static PassRefPtr<CSSPrimitiveValue> valueForNinePieceImageQuad(const BorderImag return cssValuePool().createValue(quad.release()); } -static PassRefPtr<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image) +static PassRefPtrWillBeRawPtr<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image) { - RefPtr<CSSPrimitiveValue> horizontalRepeat; - RefPtr<CSSPrimitiveValue> verticalRepeat; + RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalRepeat = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalRepeat = nullptr; horizontalRepeat = cssValuePool().createIdentifierValue(valueForRepeatRule(image.horizontalRule())); if (image.horizontalRule() == image.verticalRule()) @@ -527,60 +513,60 @@ static PassRefPtr<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& i return cssValuePool().createValue(Pair::create(horizontalRepeat.release(), verticalRepeat.release(), Pair::DropIdenticalValues)); } -static PassRefPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValue> valueForNinePieceImage(const NinePieceImage& image, const RenderStyle& style) { if (!image.hasImage()) return cssValuePool().createIdentifierValue(CSSValueNone); // Image first. - RefPtr<CSSValue> imageValue; + RefPtrWillBeRawPtr<CSSValue> imageValue = nullptr; if (image.image()) imageValue = image.image()->cssValue(); // Create the image slice. - RefPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image); + RefPtrWillBeRawPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image); // Create the border area slices. - RefPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices(), style); + RefPtrWillBeRawPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices(), style); // Create the border outset. - RefPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset(), style); + RefPtrWillBeRawPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset(), style); // Create the repeat rules. - RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image); + RefPtrWillBeRawPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image); return createBorderImageValue(imageValue.release(), imageSlices.release(), borderSlices.release(), outset.release(), repeat.release()); } -inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(double value, const RenderStyle& style) +inline static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> zoomAdjustedPixelValue(double value, const RenderStyle& style) { return cssValuePool().createValue(adjustFloatForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX); } -inline static PassRefPtr<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle& style) +inline static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle& style) { return cssValuePool().createValue(value / style.effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER); } -static PassRefPtr<CSSPrimitiveValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle& style) { if (length.isFixed()) return zoomAdjustedPixelValue(length.value(), style); return cssValuePool().createValue(length, style); } -static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle& style) { if (!reflection) return cssValuePool().createIdentifierValue(CSSValueNone); - RefPtr<CSSPrimitiveValue> offset; + RefPtrWillBeRawPtr<CSSPrimitiveValue> offset = nullptr; if (reflection->offset().isPercent()) offset = cssValuePool().createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE); else offset = zoomAdjustedPixelValue(reflection->offset().value(), style); - RefPtr<CSSPrimitiveValue> direction; + RefPtrWillBeRawPtr<CSSPrimitiveValue> direction = nullptr; switch (reflection->direction()) { case ReflectionBelow: direction = cssValuePool().createIdentifierValue(CSSValueBelow); @@ -599,9 +585,9 @@ static PassRefPtr<CSSValue> valueForReflection(const StyleReflection* reflection return CSSReflectValue::create(direction.release(), offset.release(), valueForNinePieceImage(reflection->mask(), style)); } -static PassRefPtr<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, const FillLayer* layer, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, const FillLayer* layer, const RenderStyle& style) { - RefPtr<CSSValueList> positionList = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> positionList = CSSValueList::createSpaceSeparated(); if (layer->isBackgroundXOriginSet()) { ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition); positionList->append(cssValuePool().createValue(layer->backgroundXOrigin())); @@ -615,7 +601,7 @@ static PassRefPtr<CSSValueList> createPositionListForLayer(CSSPropertyID propert return positionList.release(); } -static PassRefPtr<CSSValue> valueForPositionOffset(RenderStyle& style, CSSPropertyID propertyID, const RenderObject* renderer, RenderView* renderView) +static PassRefPtrWillBeRawPtr<CSSValue> valueForPositionOffset(RenderStyle& style, CSSPropertyID propertyID, const RenderObject* renderer) { Length l; switch (propertyID) { @@ -632,38 +618,34 @@ static PassRefPtr<CSSValue> valueForPositionOffset(RenderStyle& style, CSSProper l = style.bottom(); break; default: - return 0; + return nullptr; } if (l.isPercent() && renderer && renderer->isBox()) { LayoutUnit containingBlockSize = (propertyID == CSSPropertyLeft || propertyID == CSSPropertyRight) ? toRenderBox(renderer)->containingBlockLogicalWidthForContent() : toRenderBox(renderer)->containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding); - return zoomAdjustedPixelValue(valueForLength(l, containingBlockSize, 0), style); + return zoomAdjustedPixelValue(valueForLength(l, containingBlockSize), style); } - if (l.isViewportPercentage()) - return zoomAdjustedPixelValue(valueForLength(l, 0, renderView), style); if (l.isAuto()) { // 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 cssValuePool().createValue(l); + return cssValuePool().createIdentifierValue(CSSValueAuto); } return zoomAdjustedPixelValueForLength(l, style); } -PassRefPtr<CSSPrimitiveValue> CSSComputedStyleDeclaration::currentColorOrValidColor(const RenderStyle& style, const Color& color) const +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSComputedStyleDeclaration::currentColorOrValidColor(const RenderStyle& style, const StyleColor& color) const { // This function does NOT look at visited information, so that computed style doesn't expose that. - if (!color.isValid()) - return cssValuePool().createColorValue(style.color().rgb()); - return cssValuePool().createColorValue(color.rgb()); + return cssValuePool().createColorValue(color.resolve(style.color()).rgb()); } -static PassRefPtr<CSSValueList> valuesForBorderRadiusCorner(LengthSize radius, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValueList> valuesForBorderRadiusCorner(LengthSize radius, const RenderStyle& style) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (radius.width().type() == Percent) list->append(cssValuePool().createValue(radius.width().percent(), CSSPrimitiveValue::CSS_PERCENTAGE)); else @@ -675,17 +657,17 @@ static PassRefPtr<CSSValueList> valuesForBorderRadiusCorner(LengthSize radius, c return list.release(); } -static PassRefPtr<CSSValue> valueForBorderRadiusCorner(LengthSize radius, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValue> valueForBorderRadiusCorner(LengthSize radius, const RenderStyle& style) { - RefPtr<CSSValueList> list = valuesForBorderRadiusCorner(radius, style); + RefPtrWillBeRawPtr<CSSValueList> list = valuesForBorderRadiusCorner(radius, style); if (list->item(0)->equals(*list->item(1))) return list->item(0); return list.release(); } -static PassRefPtr<CSSValueList> valueForBorderRadiusShorthand(const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValueList> valueForBorderRadiusShorthand(const RenderStyle& style) { - RefPtr<CSSValueList> list = CSSValueList::createSlashSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSlashSeparated(); bool showHorizontalBottomLeft = style.borderTopRightRadius().width() != style.borderBottomLeftRadius().width(); bool showHorizontalBottomRight = showHorizontalBottomLeft || (style.borderBottomRightRadius().width() != style.borderTopLeftRadius().width()); @@ -695,12 +677,12 @@ static PassRefPtr<CSSValueList> valueForBorderRadiusShorthand(const RenderStyle& bool showVerticalBottomRight = showVerticalBottomLeft || (style.borderBottomRightRadius().height() != style.borderTopLeftRadius().height()); bool showVerticalTopRight = showVerticalBottomRight || (style.borderTopRightRadius().height() != style.borderTopLeftRadius().height()); - RefPtr<CSSValueList> topLeftRadius = valuesForBorderRadiusCorner(style.borderTopLeftRadius(), style); - RefPtr<CSSValueList> topRightRadius = valuesForBorderRadiusCorner(style.borderTopRightRadius(), style); - RefPtr<CSSValueList> bottomRightRadius = valuesForBorderRadiusCorner(style.borderBottomRightRadius(), style); - RefPtr<CSSValueList> bottomLeftRadius = valuesForBorderRadiusCorner(style.borderBottomLeftRadius(), style); + RefPtrWillBeRawPtr<CSSValueList> topLeftRadius = valuesForBorderRadiusCorner(style.borderTopLeftRadius(), style); + RefPtrWillBeRawPtr<CSSValueList> topRightRadius = valuesForBorderRadiusCorner(style.borderTopRightRadius(), style); + RefPtrWillBeRawPtr<CSSValueList> bottomRightRadius = valuesForBorderRadiusCorner(style.borderBottomRightRadius(), style); + RefPtrWillBeRawPtr<CSSValueList> bottomLeftRadius = valuesForBorderRadiusCorner(style.borderBottomLeftRadius(), style); - RefPtr<CSSValueList> horizontalRadii = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> horizontalRadii = CSSValueList::createSpaceSeparated(); horizontalRadii->append(topLeftRadius->item(0)); if (showHorizontalTopRight) horizontalRadii->append(topRightRadius->item(0)); @@ -711,7 +693,7 @@ static PassRefPtr<CSSValueList> valueForBorderRadiusShorthand(const RenderStyle& list->append(horizontalRadii.release()); - RefPtr<CSSValueList> verticalRadii = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> verticalRadii = CSSValueList::createSpaceSeparated(); verticalRadii->append(topLeftRadius->item(1)); if (showVerticalTopRight) verticalRadii->append(topRightRadius->item(1)); @@ -735,9 +717,9 @@ static LayoutRect sizingBox(RenderObject* renderer) return box->style()->boxSizing() == BORDER_BOX ? box->borderBoxRect() : box->computedCSSContentBoxRect(); } -static PassRefPtr<CSSTransformValue> valueForMatrixTransform(const TransformationMatrix& transform, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSTransformValue> valueForMatrixTransform(const TransformationMatrix& transform, const RenderStyle& style) { - RefPtr<CSSTransformValue> transformValue; + RefPtrWillBeRawPtr<CSSTransformValue> transformValue = nullptr; if (transform.isAffine()) { transformValue = CSSTransformValue::create(CSSTransformValue::MatrixTransformOperation); @@ -774,7 +756,7 @@ static PassRefPtr<CSSTransformValue> valueForMatrixTransform(const Transformatio return transformValue.release(); } -static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle& style) { if (!renderer || !renderer->hasTransform() || !style.hasTransform()) return cssValuePool().createIdentifierValue(CSSValueNone); @@ -787,69 +769,24 @@ static PassRefPtr<CSSValue> computedTransform(RenderObject* renderer, const Rend style.applyTransform(transform, box.size(), RenderStyle::ExcludeTransformOrigin); // FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924) - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); list->append(valueForMatrixTransform(transform, style)); return list.release(); } -static PassRefPtr<CSSValue> valueForCustomFilterArrayParameter(const CustomFilterArrayParameter* arrayParameter) -{ - RefPtr<CSSArrayFunctionValue> arrayParameterValue = CSSArrayFunctionValue::create(); - for (unsigned i = 0, size = arrayParameter->size(); i < size; ++i) - arrayParameterValue->append(cssValuePool().createValue(arrayParameter->valueAt(i), CSSPrimitiveValue::CSS_NUMBER)); - return arrayParameterValue.release(); -} - -static PassRefPtr<CSSValue> valueForCustomFilterNumberParameter(const CustomFilterNumberParameter* numberParameter) -{ - RefPtr<CSSValueList> numberParameterValue = CSSValueList::createSpaceSeparated(); - for (unsigned i = 0; i < numberParameter->size(); ++i) - numberParameterValue->append(cssValuePool().createValue(numberParameter->valueAt(i), CSSPrimitiveValue::CSS_NUMBER)); - return numberParameterValue.release(); -} - -static PassRefPtr<CSSValue> valueForCustomFilterTransformParameter(const RenderObject* renderer, const RenderStyle& style, const CustomFilterTransformParameter* transformParameter) -{ - IntSize size; - if (renderer && renderer->isBox()) - size = pixelSnappedIntRect(toRenderBox(renderer)->borderBoxRect()).size(); - - TransformationMatrix transform; - transformParameter->applyTransform(transform, size); - // FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924) - return valueForMatrixTransform(transform, style); -} - -static PassRefPtr<CSSValue> valueForCustomFilterParameter(const RenderObject* renderer, const RenderStyle& style, const CustomFilterParameter* parameter) -{ - // FIXME: Add here computed style for the other types: boolean, transform, matrix, texture. - ASSERT(parameter); - switch (parameter->parameterType()) { - case CustomFilterParameter::Array: - return valueForCustomFilterArrayParameter(static_cast<const CustomFilterArrayParameter*>(parameter)); - case CustomFilterParameter::Number: - return valueForCustomFilterNumberParameter(static_cast<const CustomFilterNumberParameter*>(parameter)); - case CustomFilterParameter::Transform: - return valueForCustomFilterTransformParameter(renderer, style, static_cast<const CustomFilterTransformParameter*>(parameter)); - } - - ASSERT_NOT_REACHED(); - return 0; -} - -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObject* renderer, const RenderStyle& style) const +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObject* renderer, const RenderStyle& style) const { if (style.filter().operations().isEmpty()) return cssValuePool().createIdentifierValue(CSSValueNone); - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - RefPtr<CSSFilterValue> filterValue; + RefPtrWillBeRawPtr<CSSFilterValue> filterValue = nullptr; Vector<RefPtr<FilterOperation> >::const_iterator end = style.filter().operations().end(); for (Vector<RefPtr<FilterOperation> >::const_iterator it = style.filter().operations().begin(); it != end; ++it) { - FilterOperation* filterOperation = (*it).get(); + FilterOperation* filterOperation = it->get(); switch (filterOperation->type()) { case FilterOperation::REFERENCE: filterValue = CSSFilterValue::create(CSSFilterValue::ReferenceFilterOperation); @@ -899,68 +836,6 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObj filterValue->append(valueForShadowData(shadow, style, false)); break; } - case FilterOperation::VALIDATED_CUSTOM: - // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle. - ASSERT_NOT_REACHED(); - break; - case FilterOperation::CUSTOM: { - CustomFilterOperation* customOperation = toCustomFilterOperation(filterOperation); - filterValue = CSSFilterValue::create(CSSFilterValue::CustomFilterOperation); - - // The output should be verbose, even if the values are the default ones. - - ASSERT(customOperation->program()); - StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customOperation->program()); - - RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated(); - if (program->vertexShader()) - shadersList->append(program->vertexShader()->cssValue()); - else - shadersList->append(cssValuePool().createIdentifierValue(CSSValueNone)); - - const CustomFilterProgramMixSettings mixSettings = program->mixSettings(); - if (program->fragmentShader()) { - if (program->programType() == ProgramTypeBlendsElementTexture) { - RefPtr<CSSMixFunctionValue> mixFunction = CSSMixFunctionValue::create(); - mixFunction->append(program->fragmentShader()->cssValue()); - mixFunction->append(cssValuePool().createValue(mixSettings.blendMode)); - mixFunction->append(cssValuePool().createValue(mixSettings.compositeOperator)); - shadersList->append(mixFunction.release()); - } else - shadersList->append(program->fragmentShader()->cssValue()); - } - else - shadersList->append(cssValuePool().createIdentifierValue(CSSValueNone)); - - filterValue->append(shadersList.release()); - - RefPtr<CSSValueList> meshParameters = CSSValueList::createSpaceSeparated(); - meshParameters->append(cssValuePool().createValue(customOperation->meshColumns(), CSSPrimitiveValue::CSS_NUMBER)); - meshParameters->append(cssValuePool().createValue(customOperation->meshRows(), CSSPrimitiveValue::CSS_NUMBER)); - - // FIXME: The specification doesn't have any "attached" identifier. Should we add one? - // https://bugs.webkit.org/show_bug.cgi?id=72700 - if (customOperation->meshType() == MeshTypeDetached) - meshParameters->append(cssValuePool().createIdentifierValue(CSSValueDetached)); - - filterValue->append(meshParameters.release()); - - const CustomFilterParameterList& parameters = customOperation->parameters(); - size_t parametersSize = parameters.size(); - if (!parametersSize) - break; - RefPtr<CSSValueList> parametersCSSValue = CSSValueList::createCommaSeparated(); - for (size_t i = 0; i < parametersSize; ++i) { - const CustomFilterParameter* parameter = parameters.at(i).get(); - RefPtr<CSSValueList> parameterCSSNameAndValue = CSSValueList::createSpaceSeparated(); - parameterCSSNameAndValue->append(cssValuePool().createValue(parameter->name(), CSSPrimitiveValue::CSS_STRING)); - parameterCSSNameAndValue->append(valueForCustomFilterParameter(renderer, style, parameter)); - parametersCSSValue->append(parameterCSSNameAndValue.release()); - } - - filterValue->append(parametersCSSValue.release()); - break; - } default: filterValue = CSSFilterValue::create(CSSFilterValue::UnknownFilterOperation); break; @@ -971,7 +846,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForFilter(const RenderObj return list.release(); } -static PassRefPtr<CSSValue> specifiedValueForGridTrackBreadth(const GridLength& trackBreadth, const RenderStyle& style, RenderView* renderView) +static PassRefPtrWillBeRawPtr<CSSValue> specifiedValueForGridTrackBreadth(const GridLength& trackBreadth, const RenderStyle& style) { if (!trackBreadth.isLength()) return cssValuePool().createValue(trackBreadth.flex(), CSSPrimitiveValue::CSS_FR); @@ -979,24 +854,22 @@ static PassRefPtr<CSSValue> specifiedValueForGridTrackBreadth(const GridLength& const Length& trackBreadthLength = trackBreadth.length(); if (trackBreadthLength.isAuto()) return cssValuePool().createIdentifierValue(CSSValueAuto); - if (trackBreadthLength.isViewportPercentage()) - return zoomAdjustedPixelValue(valueForLength(trackBreadthLength, 0, renderView), style); return zoomAdjustedPixelValueForLength(trackBreadthLength, style); } -static PassRefPtr<CSSValue> specifiedValueForGridTrackSize(const GridTrackSize& trackSize, const RenderStyle& style, RenderView* renderView) +static PassRefPtrWillBeRawPtr<CSSValue> specifiedValueForGridTrackSize(const GridTrackSize& trackSize, const RenderStyle& style) { switch (trackSize.type()) { case LengthTrackSizing: - return specifiedValueForGridTrackBreadth(trackSize.length(), style, renderView); + return specifiedValueForGridTrackBreadth(trackSize.length(), style); case MinMaxTrackSizing: - RefPtr<CSSValueList> minMaxTrackBreadths = CSSValueList::createCommaSeparated(); - minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style, renderView)); - minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.maxTrackBreadth(), style, renderView)); + RefPtrWillBeRawPtr<CSSValueList> minMaxTrackBreadths = CSSValueList::createCommaSeparated(); + minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style)); + minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.maxTrackBreadth(), style)); return CSSFunctionValue::create("minmax(", minMaxTrackBreadths); } ASSERT_NOT_REACHED(); - return 0; + return nullptr; } static void addValuesForNamedGridLinesAtIndex(const OrderedNamedGridLines& orderedNamedGridLines, size_t i, CSSValueList& list) @@ -1005,15 +878,15 @@ static void addValuesForNamedGridLinesAtIndex(const OrderedNamedGridLines& order if (namedGridLines.isEmpty()) return; - RefPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create(); + RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create(); for (size_t j = 0; j < namedGridLines.size(); ++j) lineNames->append(cssValuePool().createValue(namedGridLines[j], CSSPrimitiveValue::CSS_STRING)); list.append(lineNames.release()); } -static PassRefPtr<CSSValue> valueForGridTrackList(GridTrackSizingDirection direction, RenderObject* renderer, const RenderStyle& style, RenderView* renderView) +static PassRefPtrWillBeRawPtr<CSSValue> valueForGridTrackList(GridTrackSizingDirection direction, RenderObject* renderer, const RenderStyle& style) { - const Vector<GridTrackSize>& trackSizes = direction == ForColumns ? style.gridDefinitionColumns() : style.gridDefinitionRows(); + const Vector<GridTrackSize>& trackSizes = direction == ForColumns ? style.gridTemplateColumns() : style.gridTemplateRows(); const OrderedNamedGridLines& orderedNamedGridLines = direction == ForColumns ? style.orderedNamedGridColumnLines() : style.orderedNamedGridRowLines(); // Handle the 'none' case here. @@ -1022,7 +895,7 @@ static PassRefPtr<CSSValue> valueForGridTrackList(GridTrackSizingDirection direc return cssValuePool().createIdentifierValue(CSSValueNone); } - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (renderer && renderer->isRenderGrid()) { const Vector<LayoutUnit>& trackPositions = direction == ForColumns ? toRenderGrid(renderer)->columnPositions() : toRenderGrid(renderer)->rowPositions(); // There are at least #tracks + 1 grid lines (trackPositions). Apart from that, the grid container can generate implicit grid tracks, @@ -1036,7 +909,7 @@ static PassRefPtr<CSSValue> valueForGridTrackList(GridTrackSizingDirection direc } else { for (size_t i = 0; i < trackSizes.size(); ++i) { addValuesForNamedGridLinesAtIndex(orderedNamedGridLines, i, *list); - list->append(specifiedValueForGridTrackSize(trackSizes[i], style, renderView)); + list->append(specifiedValueForGridTrackSize(trackSizes[i], style)); } } // Those are the trailing <string>* allowed in the syntax. @@ -1044,7 +917,7 @@ static PassRefPtr<CSSValue> valueForGridTrackList(GridTrackSizingDirection direc return list.release(); } -static PassRefPtr<CSSValue> valueForGridPosition(const GridPosition& position) +static PassRefPtrWillBeRawPtr<CSSValue> valueForGridPosition(const GridPosition& position) { if (position.isAuto()) return cssValuePool().createIdentifierValue(CSSValueAuto); @@ -1052,7 +925,7 @@ static PassRefPtr<CSSValue> valueForGridPosition(const GridPosition& position) if (position.isNamedGridArea()) return cssValuePool().createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING); - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (position.isSpan()) { list->append(cssValuePool().createIdentifierValue(CSSValueSpan)); list->append(cssValuePool().createValue(position.spanPosition(), CSSPrimitiveValue::CSS_NUMBER)); @@ -1063,55 +936,71 @@ static PassRefPtr<CSSValue> valueForGridPosition(const GridPosition& position) list->append(cssValuePool().createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING)); return list; } -static PassRefPtr<CSSValue> createTransitionPropertyValue(const CSSAnimationData* animation) + +static PassRefPtrWillBeRawPtr<CSSValue> createTransitionPropertyValue(const CSSTransitionData::TransitionProperty& property) { - RefPtr<CSSValue> propertyValue; - if (animation->animationMode() == CSSAnimationData::AnimateNone) - propertyValue = cssValuePool().createIdentifierValue(CSSValueNone); - else if (animation->animationMode() == CSSAnimationData::AnimateAll) - propertyValue = cssValuePool().createIdentifierValue(CSSValueAll); - else - propertyValue = cssValuePool().createValue(getPropertyNameString(animation->property()), CSSPrimitiveValue::CSS_STRING); - return propertyValue.release(); + if (property.propertyType == CSSTransitionData::TransitionNone) + return cssValuePool().createIdentifierValue(CSSValueNone); + if (property.propertyType == CSSTransitionData::TransitionAll) + return cssValuePool().createIdentifierValue(CSSValueAll); + if (property.propertyType == CSSTransitionData::TransitionUnknown) + return cssValuePool().createValue(property.propertyString, CSSPrimitiveValue::CSS_STRING); + ASSERT(property.propertyType == CSSTransitionData::TransitionSingleProperty); + return cssValuePool().createValue(getPropertyNameString(property.propertyId), CSSPrimitiveValue::CSS_STRING); } -static PassRefPtr<CSSValue> valueForTransitionProperty(const CSSAnimationDataList* animList) + +static PassRefPtrWillBeRawPtr<CSSValue> valueForTransitionProperty(const CSSTransitionData* transitionData) { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - if (animList) { - for (size_t i = 0; i < animList->size(); ++i) - list->append(createTransitionPropertyValue(animList->animation(i))); - } else + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + if (transitionData) { + for (size_t i = 0; i < transitionData->propertyList().size(); ++i) + list->append(createTransitionPropertyValue(transitionData->propertyList()[i])); + } else { list->append(cssValuePool().createIdentifierValue(CSSValueAll)); + } return list.release(); } -static PassRefPtr<CSSValue> valueForAnimationDelay(const CSSAnimationDataList* animList) +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationDelay(const CSSTimingData* timingData) { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - if (animList) { - for (size_t i = 0; i < animList->size(); ++i) - list->append(cssValuePool().createValue(animList->animation(i)->delay(), CSSPrimitiveValue::CSS_S)); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + if (timingData) { + for (size_t i = 0; i < timingData->delayList().size(); ++i) + list->append(cssValuePool().createValue(timingData->delayList()[i], CSSPrimitiveValue::CSS_S)); } else { - // Note that initialAnimationDelay() is used for both transitions and animations - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDelay(), CSSPrimitiveValue::CSS_S)); + list->append(cssValuePool().createValue(CSSTimingData::initialDelay(), CSSPrimitiveValue::CSS_S)); } return list.release(); } -static PassRefPtr<CSSValue> valueForAnimationDuration(const CSSAnimationDataList* animList) +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationDuration(const CSSTimingData* timingData) { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - if (animList) { - for (size_t i = 0; i < animList->size(); ++i) - list->append(cssValuePool().createValue(animList->animation(i)->duration(), CSSPrimitiveValue::CSS_S)); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + if (timingData) { + for (size_t i = 0; i < timingData->durationList().size(); ++i) + list->append(cssValuePool().createValue(timingData->durationList()[i], CSSPrimitiveValue::CSS_S)); } else { - // Note that initialAnimationDuration() is used for both transitions and animations - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDuration(), CSSPrimitiveValue::CSS_S)); + list->append(cssValuePool().createValue(CSSTimingData::initialDuration(), CSSPrimitiveValue::CSS_S)); } return list.release(); } -static PassRefPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timingFunction) +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationIterationCount(double iterationCount) +{ + if (iterationCount == std::numeric_limits<double>::infinity()) + return cssValuePool().createIdentifierValue(CSSValueInfinite); + return cssValuePool().createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER); +} + +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationPlayState(EAnimPlayState playState) +{ + if (playState == AnimPlayStatePlaying) + return cssValuePool().createIdentifierValue(CSSValueRunning); + ASSERT(playState == AnimPlayStatePaused); + return cssValuePool().createIdentifierValue(CSSValuePaused); +} + +static PassRefPtrWillBeRawPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timingFunction) { switch (timingFunction->type()) { case TimingFunction::CubicBezierFunction: @@ -1134,7 +1023,7 @@ static PassRefPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timi break; default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } return cssValuePool().createIdentifierValue(valueId); } @@ -1145,7 +1034,8 @@ static PassRefPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timi { const StepsTimingFunction* stepsTimingFunction = toStepsTimingFunction(timingFunction); if (stepsTimingFunction->subType() == StepsTimingFunction::Custom) - return CSSStepsTimingFunctionValue::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart()); + return CSSStepsTimingFunctionValue::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtPosition()); + CSSValueID valueId; switch (stepsTimingFunction->subType()) { case StepsTimingFunction::Start: @@ -1156,7 +1046,7 @@ static PassRefPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timi break; default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } return cssValuePool().createIdentifierValue(valueId); } @@ -1166,63 +1056,79 @@ static PassRefPtr<CSSValue> createTimingFunctionValue(const TimingFunction* timi } } -static PassRefPtr<CSSValue> valueForAnimationTimingFunction(const CSSAnimationDataList* animList) +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationTimingFunction(const CSSTimingData* timingData) { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - if (animList) { - for (size_t i = 0; i < animList->size(); ++i) - list->append(createTimingFunctionValue(animList->animation(i)->timingFunction())); - } else - // Note that initialAnimationTimingFunction() is used for both transitions and animations - list->append(createTimingFunctionValue(CSSAnimationData::initialAnimationTimingFunction().get())); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + if (timingData) { + for (size_t i = 0; i < timingData->timingFunctionList().size(); ++i) + list->append(createTimingFunctionValue(timingData->timingFunctionList()[i].get())); + } else { + list->append(createTimingFunctionValue(CSSTimingData::initialTimingFunction().get())); + } return list.release(); } -static PassRefPtr<CSSValue> valueForAnimationFillMode(unsigned fillMode) +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationFillMode(Timing::FillMode fillMode) { switch (fillMode) { - case AnimationFillModeNone: + case Timing::FillModeNone: return cssValuePool().createIdentifierValue(CSSValueNone); - case AnimationFillModeForwards: + case Timing::FillModeForwards: return cssValuePool().createIdentifierValue(CSSValueForwards); - case AnimationFillModeBackwards: + case Timing::FillModeBackwards: return cssValuePool().createIdentifierValue(CSSValueBackwards); - case AnimationFillModeBoth: + case Timing::FillModeBoth: return cssValuePool().createIdentifierValue(CSSValueBoth); default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } -static PassRefPtr<CSSValue> valueForAnimationDirection(CSSAnimationData::AnimationDirection direction) +static PassRefPtrWillBeRawPtr<CSSValue> valueForAnimationDirection(Timing::PlaybackDirection direction) { switch (direction) { - case CSSAnimationData::AnimationDirectionNormal: + case Timing::PlaybackDirectionNormal: return cssValuePool().createIdentifierValue(CSSValueNormal); - case CSSAnimationData::AnimationDirectionAlternate: + case Timing::PlaybackDirectionAlternate: return cssValuePool().createIdentifierValue(CSSValueAlternate); - case CSSAnimationData::AnimationDirectionReverse: + case Timing::PlaybackDirectionReverse: return cssValuePool().createIdentifierValue(CSSValueReverse); - case CSSAnimationData::AnimationDirectionAlternateReverse: + case Timing::PlaybackDirectionAlternateReverse: return cssValuePool().createIdentifierValue(CSSValueAlternateReverse); default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } -static PassRefPtr<CSSValue> createLineBoxContainValue(unsigned lineBoxContain) +static PassRefPtrWillBeRawPtr<CSSValue> valueForWillChange(const Vector<CSSPropertyID>& willChangeProperties, bool willChangeContents, bool willChangeScrollPosition) +{ + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + if (willChangeContents) + list->append(cssValuePool().createIdentifierValue(CSSValueContents)); + if (willChangeScrollPosition) + list->append(cssValuePool().createIdentifierValue(CSSValueScrollPosition)); + for (size_t i = 0; i < willChangeProperties.size(); ++i) + list->append(cssValuePool().createIdentifierValue(willChangeProperties[i])); + if (!list->length()) + list->append(cssValuePool().createIdentifierValue(CSSValueAuto)); + return list.release(); +} + +static PassRefPtrWillBeRawPtr<CSSValue> createLineBoxContainValue(unsigned lineBoxContain) { if (!lineBoxContain) return cssValuePool().createIdentifierValue(CSSValueNone); return CSSLineBoxContainValue::create(lineBoxContain); } -CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtr<Node> n, bool allowVisitedStyle, const String& pseudoElementName) +CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(PassRefPtrWillBeRawPtr<Node> n, bool allowVisitedStyle, const String& pseudoElementName) : m_node(n) , m_allowVisitedStyle(allowVisitedStyle) +#if !ENABLE(OILPAN) , m_refCount(1) +#endif { unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0; m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoType( @@ -1233,6 +1139,7 @@ CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration() { } +#if !ENABLE(OILPAN) void CSSComputedStyleDeclaration::ref() { ++m_refCount; @@ -1244,6 +1151,7 @@ void CSSComputedStyleDeclaration::deref() if (!--m_refCount) delete this; } +#endif String CSSComputedStyleDeclaration::cssText() const { @@ -1274,16 +1182,16 @@ static CSSValueID cssIdentifierForFontSizeKeyword(int keywordSize) return static_cast<CSSValueID>(CSSValueXxSmall + keywordSize - 1); } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getFontSizeCSSValuePreferringKeyword() const +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::getFontSizeCSSValuePreferringKeyword() const { if (!m_node) - return 0; + return nullptr; m_node->document().updateLayoutIgnorePendingStylesheets(); RefPtr<RenderStyle> style = m_node->computedStyle(m_pseudoElementSpecifier); if (!style) - return 0; + return nullptr; if (int keywordSize = style->fontDescription().keywordSize()) return cssValuePool().createIdentifierValue(cssIdentifierForFontSizeKeyword(keywordSize)); @@ -1304,34 +1212,29 @@ bool CSSComputedStyleDeclaration::useFixedFontDefaultSize() const return style->fontDescription().useFixedDefaultSize(); } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadowData(const ShadowData& shadow, const RenderStyle& style, bool useSpread) const +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadowData(const ShadowData& shadow, const RenderStyle& style, bool useSpread) const { - RefPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(shadow.x(), style); - RefPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(shadow.y(), style); - RefPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(shadow.blur(), style); - RefPtr<CSSPrimitiveValue> spread = useSpread ? zoomAdjustedPixelValue(shadow.spread(), style) : PassRefPtr<CSSPrimitiveValue>(); - RefPtr<CSSPrimitiveValue> shadowStyle = shadow.style() == Normal ? PassRefPtr<CSSPrimitiveValue>() : cssValuePool().createIdentifierValue(CSSValueInset); - RefPtr<CSSPrimitiveValue> color = currentColorOrValidColor(style, shadow.color()); + RefPtrWillBeRawPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(shadow.x(), style); + RefPtrWillBeRawPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(shadow.y(), style); + RefPtrWillBeRawPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(shadow.blur(), style); + RefPtrWillBeRawPtr<CSSPrimitiveValue> spread = useSpread ? zoomAdjustedPixelValue(shadow.spread(), style) : PassRefPtrWillBeRawPtr<CSSPrimitiveValue>(nullptr); + RefPtrWillBeRawPtr<CSSPrimitiveValue> shadowStyle = shadow.style() == Normal ? PassRefPtrWillBeRawPtr<CSSPrimitiveValue>(nullptr) : cssValuePool().createIdentifierValue(CSSValueInset); + RefPtrWillBeRawPtr<CSSPrimitiveValue> color = currentColorOrValidColor(style, shadow.color()); return CSSShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), shadowStyle.release(), color.release()); } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadowList(const ShadowList* shadowList, const RenderStyle& style, bool useSpread) const +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::valueForShadowList(const ShadowList* shadowList, const RenderStyle& style, bool useSpread) const { if (!shadowList) return cssValuePool().createIdentifierValue(CSSValueNone); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); size_t shadowCount = shadowList->shadows().size(); for (size_t i = 0; i < shadowCount; ++i) list->append(valueForShadowData(shadowList->shadows()[i], style, useSpread)); return list.release(); } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID) const -{ - return getPropertyCSSValue(propertyID, UpdateLayout); -} - static CSSValueID identifierForFamily(const AtomicString& family) { if (family == FontFamilyNames::webkit_cursive) @@ -1349,17 +1252,17 @@ static CSSValueID identifierForFamily(const AtomicString& family) return CSSValueInvalid; } -static PassRefPtr<CSSPrimitiveValue> valueForFamily(const AtomicString& family) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForFamily(const AtomicString& family) { if (CSSValueID familyIdentifier = identifierForFamily(family)) return cssValuePool().createIdentifierValue(familyIdentifier); return cssValuePool().createValue(family.string(), CSSPrimitiveValue::CSS_STRING); } -static PassRefPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration) +static PassRefPtrWillBeRawPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration) { // Blink value is ignored. - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (textDecoration & TextDecorationUnderline) list->append(cssValuePool().createIdentifierValue(CSSValueUnderline)); if (textDecoration & TextDecorationOverline) @@ -1372,7 +1275,7 @@ static PassRefPtr<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecorati return list.release(); } -static PassRefPtr<CSSValue> valueForTextDecorationStyle(TextDecorationStyle textDecorationStyle) +static PassRefPtrWillBeRawPtr<CSSValue> valueForTextDecorationStyle(TextDecorationStyle textDecorationStyle) { switch (textDecorationStyle) { case TextDecorationStyleSolid: @@ -1391,7 +1294,7 @@ static PassRefPtr<CSSValue> valueForTextDecorationStyle(TextDecorationStyle text return cssValuePool().createExplicitInitialValue(); } -static PassRefPtr<CSSValue> valueForFillRepeat(EFillRepeat xRepeat, EFillRepeat yRepeat) +static PassRefPtrWillBeRawPtr<CSSValue> valueForFillRepeat(EFillRepeat xRepeat, EFillRepeat yRepeat) { // 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. @@ -1402,13 +1305,13 @@ static PassRefPtr<CSSValue> valueForFillRepeat(EFillRepeat xRepeat, EFillRepeat if (xRepeat == NoRepeatFill && yRepeat == RepeatFill) return cssValuePool().createIdentifierValue(CSSValueRepeatY); - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); list->append(cssValuePool().createValue(xRepeat)); list->append(cssValuePool().createValue(yRepeat)); return list.release(); } -static PassRefPtr<CSSValue> valueForFillSourceType(EMaskSourceType type) +static PassRefPtrWillBeRawPtr<CSSValue> valueForFillSourceType(EMaskSourceType type) { switch (type) { case MaskAlpha: @@ -1419,10 +1322,10 @@ static PassRefPtr<CSSValue> valueForFillSourceType(EMaskSourceType type) ASSERT_NOT_REACHED(); - return 0; + return nullptr; } -static PassRefPtr<CSSValue> valueForFillSize(const FillSize& fillSize, const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValue> valueForFillSize(const FillSize& fillSize, const RenderStyle& style) { if (fillSize.type == Contain) return cssValuePool().createIdentifierValue(CSSValueContain); @@ -1433,15 +1336,15 @@ static PassRefPtr<CSSValue> valueForFillSize(const FillSize& fillSize, const Ren if (fillSize.size.height().isAuto()) return zoomAdjustedPixelValueForLength(fillSize.size.width(), style); - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); list->append(zoomAdjustedPixelValueForLength(fillSize.size.width(), style)); list->append(zoomAdjustedPixelValueForLength(fillSize.size.height(), style)); return list.release(); } -static PassRefPtr<CSSValue> valueForContentData(const RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValue> valueForContentData(const RenderStyle& style) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); for (const ContentData* contentData = style.contentData(); contentData; contentData = contentData->next()) { if (contentData->isCounter()) { const CounterContent* counter = static_cast<const CounterContentData*>(contentData)->counter(); @@ -1454,18 +1357,16 @@ static PassRefPtr<CSSValue> valueForContentData(const RenderStyle& style) } else if (contentData->isText()) list->append(cssValuePool().createValue(static_cast<const TextContentData*>(contentData)->text(), CSSPrimitiveValue::CSS_STRING)); } - if (style.hasFlowFrom()) - list->append(cssValuePool().createValue(style.regionThread(), CSSPrimitiveValue::CSS_STRING)); return list.release(); } -static PassRefPtr<CSSValue> valueForCounterDirectives(const RenderStyle& style, CSSPropertyID propertyID) +static PassRefPtrWillBeRawPtr<CSSValue> valueForCounterDirectives(const RenderStyle& style, CSSPropertyID propertyID) { const CounterDirectiveMap* map = style.counterDirectives(); if (!map) - return 0; + return nullptr; - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); for (CounterDirectiveMap::const_iterator it = map->begin(); it != map->end(); ++it) { list->append(cssValuePool().createValue(it->key, CSSPrimitiveValue::CSS_STRING)); short number = propertyID == CSSPropertyCounterIncrement ? it->value.incrementValue() : it->value.resetValue(); @@ -1483,44 +1384,44 @@ static void logUnimplementedPropertyID(CSSPropertyID propertyID) WTF_LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(propertyID)); } -static PassRefPtr<CSSValueList> valueForFontFamily(RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSValueList> valueForFontFamily(RenderStyle& style) { const FontFamily& firstFamily = style.fontDescription().family(); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FontFamily* family = &firstFamily; family; family = family->next()) list->append(valueForFamily(family->family())); return list.release(); } -static PassRefPtr<CSSPrimitiveValue> valueForLineHeight(RenderStyle& style, RenderView* renderView) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForLineHeight(RenderStyle& style) { Length length = style.lineHeight(); if (length.isNegative()) return cssValuePool().createIdentifierValue(CSSValueNormal); - return zoomAdjustedPixelValue(floatValueForLength(length, style.fontDescription().specifiedSize(), renderView), style); + return zoomAdjustedPixelValue(floatValueForLength(length, style.fontDescription().specifiedSize()), style); } -static PassRefPtr<CSSPrimitiveValue> valueForFontSize(RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForFontSize(RenderStyle& style) { return zoomAdjustedPixelValue(style.fontDescription().computedPixelSize(), style); } -static PassRefPtr<CSSPrimitiveValue> valueForFontStyle(RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForFontStyle(RenderStyle& style) { - if (style.fontDescription().italic()) + if (style.fontDescription().style() == FontStyleItalic) return cssValuePool().createIdentifierValue(CSSValueItalic); return cssValuePool().createIdentifierValue(CSSValueNormal); } -static PassRefPtr<CSSPrimitiveValue> valueForFontVariant(RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForFontVariant(RenderStyle& style) { - if (style.fontDescription().smallCaps()) + if (style.fontDescription().variant() == FontVariantSmallCaps) return cssValuePool().createIdentifierValue(CSSValueSmallCaps); return cssValuePool().createIdentifierValue(CSSValueNormal); } -static PassRefPtr<CSSPrimitiveValue> valueForFontWeight(RenderStyle& style) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueForFontWeight(RenderStyle& style) { switch (style.fontDescription().weight()) { case FontWeight100: @@ -1546,20 +1447,44 @@ static PassRefPtr<CSSPrimitiveValue> valueForFontWeight(RenderStyle& style) return cssValuePool().createIdentifierValue(CSSValueNormal); } -static PassRefPtr<CSSValue> touchActionFlagsToCSSValue(TouchAction touchAction) +static PassRefPtrWillBeRawPtr<CSSValue> valueForShape(const RenderStyle& style, ShapeValue* shapeValue) +{ + if (!shapeValue) + return cssValuePool().createIdentifierValue(CSSValueNone); + if (shapeValue->type() == ShapeValue::Box) + return cssValuePool().createValue(shapeValue->cssBox()); + if (shapeValue->type() == ShapeValue::Image) { + if (shapeValue->image()) + return shapeValue->image()->cssValue(); + return cssValuePool().createIdentifierValue(CSSValueNone); + } + + ASSERT(shapeValue->type() == ShapeValue::Shape); + + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + list->append(valueForBasicShape(style, shapeValue->shape())); + if (shapeValue->cssBox() != BoxMissing) + list->append(cssValuePool().createValue(shapeValue->cssBox())); + return list.release(); +} + +static PassRefPtrWillBeRawPtr<CSSValue> touchActionFlagsToCSSValue(TouchAction touchAction) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (touchAction == TouchActionAuto) list->append(cssValuePool().createIdentifierValue(CSSValueAuto)); if (touchAction & TouchActionNone) { ASSERT(touchAction == TouchActionNone); list->append(cssValuePool().createIdentifierValue(CSSValueNone)); } - if (touchAction & TouchActionPanX) - list->append(cssValuePool().createIdentifierValue(CSSValuePanX)); - if (touchAction & TouchActionPanY) - list->append(cssValuePool().createIdentifierValue(CSSValuePanY)); - + if (touchAction == (TouchActionPanX | TouchActionPanY | TouchActionPinchZoom)) { + list->append(cssValuePool().createIdentifierValue(CSSValueManipulation)); + } else { + if (touchAction & TouchActionPanX) + list->append(cssValuePool().createIdentifierValue(CSSValuePanX)); + if (touchAction & TouchActionPanY) + list->append(cssValuePool().createIdentifierValue(CSSValuePanY)); + } ASSERT(list->length()); return list.release(); } @@ -1573,14 +1498,17 @@ static bool isLayoutDependent(CSSPropertyID propertyID, PassRefPtr<RenderStyle> // FIXME: Some of these cases could be narrowed down or optimized better. switch (propertyID) { case CSSPropertyBottom: - case CSSPropertyGridDefinitionColumns: - case CSSPropertyGridDefinitionRows: + case CSSPropertyGridTemplateColumns: + case CSSPropertyGridTemplateRows: case CSSPropertyHeight: case CSSPropertyLeft: case CSSPropertyRight: case CSSPropertyTop: + case CSSPropertyPerspectiveOrigin: case CSSPropertyWebkitPerspectiveOrigin: + case CSSPropertyTransform: case CSSPropertyWebkitTransform: + case CSSPropertyTransformOrigin: case CSSPropertyWebkitTransformOrigin: case CSSPropertyWidth: case CSSPropertyWebkitFilter: @@ -1614,16 +1542,6 @@ PassRefPtr<RenderStyle> CSSComputedStyleDeclaration::computeRenderStyle(CSSPrope { Node* styledNode = this->styledNode(); ASSERT(styledNode); - RenderObject* renderer = styledNode->renderer(); - if (renderer && renderer->compositingState() == PaintsIntoOwnBacking - && !RuntimeEnabledFeatures::webAnimationsCSSEnabled() && AnimationController::supportsAcceleratedAnimationOfProperty(propertyID)) { - AnimationUpdateBlock animationUpdateBlock(renderer->animation()); - if (m_pseudoElementSpecifier && !styledNode->isPseudoElement()) { - // FIXME: This cached pseudo style will only exist if the animation has been run at least once. - return renderer->animation().getAnimatedStyleForRenderer(renderer)->getCachedPseudoStyle(m_pseudoElementSpecifier); - } - return renderer->animation().getAnimatedStyleForRenderer(renderer); - } return styledNode->computedStyle(styledNode->isPseudoElement() ? NOPSEUDO : m_pseudoElementSpecifier); } @@ -1638,22 +1556,30 @@ Node* CSSComputedStyleDeclaration::styledNode() const return m_node.get(); } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const +static PassRefPtrWillBeRawPtr<CSSValueList> valueForItemPositionWithOverflowAlignment(ItemPosition itemPosition, OverflowAlignment overflowAlignment) +{ + RefPtrWillBeRawPtr<CSSValueList> result = CSSValueList::createSpaceSeparated(); + result->append(CSSPrimitiveValue::create(itemPosition)); + if (itemPosition >= ItemPositionCenter && overflowAlignment != OverflowAlignmentDefault) + result->append(CSSPrimitiveValue::create(overflowAlignment)); + return result.release(); +} + +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const { Node* styledNode = this->styledNode(); if (!styledNode) - return 0; + return nullptr; RenderObject* renderer = styledNode->renderer(); RefPtr<RenderStyle> style; if (updateLayout) { Document& document = styledNode->document(); - // If a compositor animation is running we may need to service animations - // in order to generate an up to date value. - DocumentAnimations::serviceBeforeGetComputedStyle(*styledNode, propertyID); + // A timing update may be required if a compositor animation is running. + DocumentAnimations::updateAnimationTimingForGetComputedStyle(*styledNode, propertyID); - document.updateStyleForNodeIfNeeded(styledNode); + document.updateRenderTreeForNodeIfNeeded(styledNode); // The style recalc could have caused the styled node to be discarded or replaced // if it was a PseudoElement so we need to update it. @@ -1664,8 +1590,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert bool forceFullLayout = isLayoutDependent(propertyID, style, renderer) || styledNode->isInShadowTree() - || (document.ownerElement() && document.ensureStyleResolver().hasViewportDependentMediaQueries()) - || document.seamlessParentIFrame(); + || (document.ownerElement() && document.ensureStyleResolver().hasViewportDependentMediaQueries()); if (forceFullLayout) { document.updateLayoutIgnorePendingStylesheets(); @@ -1678,17 +1603,16 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert } if (!style) - return 0; + return nullptr; propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode()); switch (propertyID) { case CSSPropertyInvalid: - case CSSPropertyVariable: break; case CSSPropertyBackgroundColor: - return cssValuePool().createColorValue(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor).rgb() : style->backgroundColor().rgb()); + return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyBackgroundColor).rgb()) : currentColorOrValidColor(*style, style->backgroundColor()); case CSSPropertyBackgroundImage: case CSSPropertyWebkitMaskImage: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskImage ? style->maskLayers() : style->backgroundLayers(); @@ -1702,7 +1626,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createIdentifierValue(CSSValueNone); } - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) { if (currLayer->image()) list->append(currLayer->image()->cssValue()); @@ -1718,7 +1642,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return valueForFillSize(layers->size(), *style); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(valueForFillSize(currLayer->size(), *style)); @@ -1730,7 +1654,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return valueForFillRepeat(layers->repeatX(), layers->repeatY()); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(valueForFillRepeat(currLayer->repeatX(), currLayer->repeatY())); @@ -1745,7 +1669,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return valueForFillSourceType(layers->maskSourceType()); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(valueForFillSourceType(currLayer->maskSourceType())); @@ -1757,7 +1681,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return cssValuePool().createValue(layers->composite()); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(cssValuePool().createValue(currLayer->composite())); @@ -1768,7 +1692,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return cssValuePool().createValue(layers->attachment()); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(cssValuePool().createValue(currLayer->attachment())); @@ -1787,7 +1711,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createValue(box); } - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) { EFillBox box = isClip ? currLayer->clip() : currLayer->origin(); list->append(cssValuePool().createValue(box)); @@ -1801,7 +1725,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return createPositionListForLayer(propertyID, layers, *style); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(createPositionListForLayer(propertyID, currLayer, *style)); return list.release(); @@ -1810,11 +1734,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyWebkitMaskPositionX: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionX ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return cssValuePool().createValue(layers->xPosition()); + return zoomAdjustedPixelValueForLength(layers->xPosition(), *style); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(cssValuePool().createValue(currLayer->xPosition())); + list->append(zoomAdjustedPixelValueForLength(currLayer->xPosition(), *style)); return list.release(); } @@ -1822,11 +1746,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyWebkitMaskPositionY: { const FillLayer* layers = propertyID == CSSPropertyWebkitMaskPositionY ? style->maskLayers() : style->backgroundLayers(); if (!layers->next()) - return cssValuePool().createValue(layers->yPosition()); + return zoomAdjustedPixelValueForLength(layers->yPosition(), *style); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) - list->append(cssValuePool().createValue(currLayer->yPosition())); + list->append(zoomAdjustedPixelValueForLength(currLayer->yPosition(), *style)); return list.release(); } @@ -1835,7 +1759,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createIdentifierValue(CSSValueCollapse); return cssValuePool().createIdentifierValue(CSSValueSeparate); case CSSPropertyBorderSpacing: { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), *style)); list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), *style)); return list.release(); @@ -1873,7 +1797,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyBorderLeftWidth: return zoomAdjustedPixelValue(style->borderLeftWidth(), *style); case CSSPropertyBottom: - return valueForPositionOffset(*style, CSSPropertyBottom, renderer, m_node->document().renderView()); + return valueForPositionOffset(*style, CSSPropertyBottom, renderer); case CSSPropertyWebkitBoxAlign: return cssValuePool().createValue(style->boxAlign()); case CSSPropertyWebkitBoxDecorationBreak: @@ -1907,8 +1831,6 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createColorValue(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor).rgb() : style->color().rgb()); case CSSPropertyWebkitPrintColorAdjust: return cssValuePool().createValue(style->printColorAdjust()); - case CSSPropertyWebkitColumnAxis: - return cssValuePool().createValue(style->columnAxis()); case CSSPropertyWebkitColumnCount: if (style->hasAutoColumnCount()) return cssValuePool().createIdentifierValue(CSSValueAuto); @@ -1916,13 +1838,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyColumnFill: if (RuntimeEnabledFeatures::regionBasedColumnsEnabled()) return cssValuePool().createValue(style->columnFill()); - return 0; + return nullptr; case CSSPropertyWebkitColumnGap: if (style->hasNormalColumnGap()) return cssValuePool().createIdentifierValue(CSSValueNormal); return zoomAdjustedPixelValue(style->columnGap(), *style); - case CSSPropertyWebkitColumnProgression: - return cssValuePool().createValue(style->columnProgression()); case CSSPropertyWebkitColumnRuleColor: return m_allowVisitedStyle ? cssValuePool().createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor).rgb()) : currentColorOrValidColor(*style, style->columnRuleColor()); case CSSPropertyWebkitColumnRuleStyle: @@ -1943,14 +1863,8 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return zoomAdjustedPixelValue(style->columnWidth(), *style); case CSSPropertyTabSize: return cssValuePool().createValue(style->tabSize(), CSSPrimitiveValue::CSS_NUMBER); - case CSSPropertyWebkitRegionBreakAfter: - return cssValuePool().createValue(style->regionBreakAfter()); - case CSSPropertyWebkitRegionBreakBefore: - return cssValuePool().createValue(style->regionBreakBefore()); - case CSSPropertyWebkitRegionBreakInside: - return cssValuePool().createValue(style->regionBreakInside()); case CSSPropertyCursor: { - RefPtr<CSSValueList> list; + RefPtrWillBeRawPtr<CSSValueList> list = nullptr; CursorList* cursors = style->cursors(); if (cursors && cursors->size() > 0) { list = CSSValueList::createCommaSeparated(); @@ -1958,7 +1872,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (StyleImage* image = cursors->at(i).image()) list->append(image->cssValue()); } - RefPtr<CSSValue> value = cssValuePool().createValue(style->cursor()); + RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(style->cursor()); if (list) { list->append(value.release()); return list.release(); @@ -1974,19 +1888,22 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyAlignContent: return cssValuePool().createValue(style->alignContent()); case CSSPropertyAlignItems: - return cssValuePool().createValue(style->alignItems()); - case CSSPropertyAlignSelf: - if (style->alignSelf() == AlignAuto) { + return valueForItemPositionWithOverflowAlignment(style->alignItems(), style->alignItemsOverflowAlignment()); + case CSSPropertyAlignSelf: { + ItemPosition alignSelf = style->alignSelf(); + if (alignSelf == ItemPositionAuto) { Node* parent = styledNode->parentNode(); if (parent && parent->computedStyle()) - return cssValuePool().createValue(parent->computedStyle()->alignItems()); - return cssValuePool().createValue(AlignStretch); + alignSelf = parent->computedStyle()->alignItems(); + else + alignSelf = ItemPositionStretch; } - return cssValuePool().createValue(style->alignSelf()); + return valueForItemPositionWithOverflowAlignment(alignSelf, style->alignSelfOverflowAlignment()); + } case CSSPropertyFlex: return valuesForShorthandProperty(flexShorthand()); case CSSPropertyFlexBasis: - return cssValuePool().createValue(style->flexBasis()); + return zoomAdjustedPixelValueForLength(style->flexBasis(), *style); case CSSPropertyFlexDirection: return cssValuePool().createValue(style->flexDirection()); case CSSPropertyFlexFlow: @@ -2006,17 +1923,17 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createIdentifierValue(CSSValueNone); return cssValuePool().createValue(style->floating()); case CSSPropertyFont: { - RefPtr<CSSFontValue> computedFont = CSSFontValue::create(); + RefPtrWillBeRawPtr<CSSFontValue> computedFont = CSSFontValue::create(); computedFont->style = valueForFontStyle(*style); computedFont->variant = valueForFontVariant(*style); computedFont->weight = valueForFontWeight(*style); computedFont->size = valueForFontSize(*style); - computedFont->lineHeight = valueForLineHeight(*style, m_node->document().renderView()); + computedFont->lineHeight = valueForLineHeight(*style); computedFont->family = valueForFontFamily(*style); return computedFont.release(); } case CSSPropertyFontFamily: { - RefPtr<CSSValueList> fontFamilyList = valueForFontFamily(*style); + RefPtrWillBeRawPtr<CSSValueList> fontFamilyList = valueForFontFamily(*style); // If there's only a single family, return that as a CSSPrimitiveValue. // NOTE: Gecko always returns this as a comma-separated CSSPrimitiveValue string. if (fontFamilyList->length() == 1) @@ -2035,10 +1952,10 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert const FontFeatureSettings* featureSettings = style->fontDescription().featureSettings(); if (!featureSettings || !featureSettings->size()) return cssValuePool().createIdentifierValue(CSSValueNormal); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (unsigned i = 0; i < featureSettings->size(); ++i) { const FontFeature& feature = featureSettings->at(i); - RefPtr<CSSFontFeatureValue> featureValue = CSSFontFeatureValue::create(feature.tag(), feature.value()); + RefPtrWillBeRawPtr<CSSFontFeatureValue> featureValue = CSSFontFeatureValue::create(feature.tag(), feature.value()); list->append(featureValue.release()); } return list.release(); @@ -2052,14 +1969,14 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html case CSSPropertyGridAutoColumns: - return specifiedValueForGridTrackSize(style->gridAutoColumns(), *style, m_node->document().renderView()); + return specifiedValueForGridTrackSize(style->gridAutoColumns(), *style); case CSSPropertyGridAutoRows: - return specifiedValueForGridTrackSize(style->gridAutoRows(), *style, m_node->document().renderView()); + return specifiedValueForGridTrackSize(style->gridAutoRows(), *style); - case CSSPropertyGridDefinitionColumns: - return valueForGridTrackList(ForColumns, renderer, *style, m_node->document().renderView()); - case CSSPropertyGridDefinitionRows: - return valueForGridTrackList(ForRows, renderer, *style, m_node->document().renderView()); + case CSSPropertyGridTemplateColumns: + return valueForGridTrackList(ForColumns, renderer, *style); + case CSSPropertyGridTemplateRows: + return valueForGridTrackList(ForRows, renderer, *style); case CSSPropertyGridColumnStart: return valueForGridPosition(style->gridColumnStart()); @@ -2075,14 +1992,17 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return valuesForGridShorthand(gridRowShorthand()); case CSSPropertyGridArea: return valuesForGridShorthand(gridAreaShorthand()); - case CSSPropertyGridTemplate: + return valuesForGridShorthand(gridTemplateShorthand()); + case CSSPropertyGrid: + return valuesForGridShorthand(gridShorthand()); + case CSSPropertyGridTemplateAreas: if (!style->namedGridAreaRowCount()) { ASSERT(!style->namedGridAreaColumnCount()); return cssValuePool().createIdentifierValue(CSSValueNone); } - return CSSGridTemplateValue::create(style->namedGridArea(), style->namedGridAreaRowCount(), style->namedGridAreaColumnCount()); + return CSSGridTemplateAreasValue::create(style->namedGridArea(), style->namedGridAreaRowCount(), style->namedGridAreaColumnCount()); case CSSPropertyHeight: if (renderer) { @@ -2109,8 +2029,10 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return CSSPrimitiveValue::create(style->imageRendering()); case CSSPropertyIsolation: return cssValuePool().createValue(style->isolation()); + case CSSPropertyJustifySelf: + return valueForItemPositionWithOverflowAlignment(style->justifySelf(), style->justifySelfOverflowAlignment()); case CSSPropertyLeft: - return valueForPositionOffset(*style, CSSPropertyLeft, renderer, m_node->document().renderView()); + return valueForPositionOffset(*style, CSSPropertyLeft, renderer); case CSSPropertyLetterSpacing: if (!style->letterSpacing()) return cssValuePool().createIdentifierValue(CSSValueNormal); @@ -2120,7 +2042,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createIdentifierValue(CSSValueNone); return cssValuePool().createValue(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER); case CSSPropertyLineHeight: - return valueForLineHeight(*style, m_node->document().renderView()); + return valueForLineHeight(*style); case CSSPropertyListStyleImage: if (style->listStyleImage()) return style->listStyleImage()->cssValue(); @@ -2144,13 +2066,13 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (marginRight.isFixed() || !renderer || !renderer->isBox()) return zoomAdjustedPixelValueForLength(marginRight, *style); float value; - if (marginRight.isPercent() || marginRight.isViewportPercentage()) { + if (marginRight.isPercent()) { // RenderBox gives a marginRight() that is the distance between the right-edge of the child box // and the right-edge of the containing box, when display == BLOCK. Let's calculate the absolute // value of the specified margin-right % instead of relying on RenderBox's marginRight() value. - value = minimumValueForLength(marginRight, toRenderBox(renderer)->containingBlockLogicalWidthForContent(), m_node->document().renderView()); + value = minimumValueForLength(marginRight, toRenderBox(renderer)->containingBlockLogicalWidthForContent()).toFloat(); } else { - value = toRenderBox(renderer)->marginRight(); + value = toRenderBox(renderer)->marginRight().toFloat(); } return zoomAdjustedPixelValue(value, *style); } @@ -2254,15 +2176,17 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert EPageBreak pageBreak = style->pageBreakInside(); ASSERT(pageBreak != PBALWAYS); if (pageBreak == PBALWAYS) - return 0; + return nullptr; return cssValuePool().createValue(style->pageBreakInside()); } case CSSPropertyPosition: return cssValuePool().createValue(style->position()); case CSSPropertyRight: - return valueForPositionOffset(*style, CSSPropertyRight, renderer, m_node->document().renderView()); + return valueForPositionOffset(*style, CSSPropertyRight, renderer); case CSSPropertyWebkitRubyPosition: return cssValuePool().createValue(style->rubyPosition()); + case CSSPropertyScrollBehavior: + return cssValuePool().createValue(style->scrollBehavior()); case CSSPropertyTableLayout: return cssValuePool().createValue(style->tableLayout()); case CSSPropertyTextAlign: @@ -2270,7 +2194,9 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyTextAlignLast: return cssValuePool().createValue(style->textAlignLast()); case CSSPropertyTextDecoration: - return valuesForShorthandProperty(textDecorationShorthand()); + if (RuntimeEnabledFeatures::css3TextDecorationsEnabled()) + return valuesForShorthandProperty(textDecorationShorthand()); + // Fall through. case CSSPropertyTextDecorationLine: return renderTextDecorationFlagsToCSSValue(style->textDecoration()); case CSSPropertyTextDecorationStyle: @@ -2303,18 +2229,25 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case TextEmphasisMarkDoubleCircle: case TextEmphasisMarkTriangle: case TextEmphasisMarkSesame: { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); list->append(cssValuePool().createValue(style->textEmphasisFill())); list->append(cssValuePool().createValue(style->textEmphasisMark())); return list.release(); } } case CSSPropertyTextIndent: { - RefPtr<CSSValue> textIndent = zoomAdjustedPixelValueForLength(style->textIndent(), *style); - if (RuntimeEnabledFeatures::css3TextEnabled() && style->textIndentLine() == TextIndentEachLine) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + // If RuntimeEnabledFeatures::css3TextEnabled() returns false or text-indent has only one value(<length> | <percentage>), + // getPropertyCSSValue() returns CSSValue. + // If RuntimeEnabledFeatures::css3TextEnabled() returns true and text-indent has each-line or hanging, + // getPropertyCSSValue() returns CSSValueList. + RefPtrWillBeRawPtr<CSSValue> textIndent = zoomAdjustedPixelValueForLength(style->textIndent(), *style); + if (RuntimeEnabledFeatures::css3TextEnabled() && (style->textIndentLine() == TextIndentEachLine || style->textIndentType() == TextIndentHanging)) { + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); list->append(textIndent.release()); - list->append(cssValuePool().createIdentifierValue(CSSValueEachLine)); + if (style->textIndentLine() == TextIndentEachLine) + list->append(cssValuePool().createIdentifierValue(CSSValueEachLine)); + if (style->textIndentType() == TextIndentHanging) + list->append(cssValuePool().createIdentifierValue(CSSValueHanging)); return list.release(); } return textIndent.release(); @@ -2322,7 +2255,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyTextShadow: return valueForShadowList(style->textShadow(), *style, false); case CSSPropertyTextRendering: - return cssValuePool().createValue(style->fontDescription().textRenderingMode()); + return cssValuePool().createValue(style->fontDescription().textRendering()); case CSSPropertyTextOverflow: if (style->textOverflow()) return cssValuePool().createIdentifierValue(CSSValueEllipsis); @@ -2336,7 +2269,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyTextTransform: return cssValuePool().createValue(style->textTransform()); case CSSPropertyTop: - return valueForPositionOffset(*style, CSSPropertyTop, renderer, m_node->document().renderView()); + return valueForPositionOffset(*style, CSSPropertyTop, renderer); case CSSPropertyTouchAction: return touchActionFlagsToCSSValue(style->touchAction()); case CSSPropertyTouchActionDelay: @@ -2364,10 +2297,10 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case BASELINE_MIDDLE: return cssValuePool().createIdentifierValue(CSSValueWebkitBaselineMiddle); case LENGTH: - return cssValuePool().createValue(style->verticalAlignLength()); + return zoomAdjustedPixelValueForLength(style->verticalAlignLength(), *style); } ASSERT_NOT_REACHED(); - return 0; + return nullptr; case CSSPropertyVisibility: return cssValuePool().createValue(style->visibility()); case CSSPropertyWhiteSpace: @@ -2385,6 +2318,8 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return zoomAdjustedPixelValue(sizingBox(renderer).width(), *style); } return zoomAdjustedPixelValueForLength(style->width(), *style); + case CSSPropertyWillChange: + return valueForWillChange(style->willChangeProperties(), style->willChangeContents(), style->willChangeScrollPosition()); case CSSPropertyWordBreak: return cssValuePool().createValue(style->wordBreak()); case CSSPropertyWordSpacing: @@ -2399,21 +2334,24 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return cssValuePool().createValue(style->fontDescription().kerning()); case CSSPropertyWebkitFontSmoothing: return cssValuePool().createValue(style->fontDescription().fontSmoothing()); - case CSSPropertyWebkitFontVariantLigatures: { + case CSSPropertyFontVariantLigatures: { FontDescription::LigaturesState commonLigaturesState = style->fontDescription().commonLigaturesState(); FontDescription::LigaturesState discretionaryLigaturesState = style->fontDescription().discretionaryLigaturesState(); FontDescription::LigaturesState historicalLigaturesState = style->fontDescription().historicalLigaturesState(); + FontDescription::LigaturesState contextualLigaturesState = style->fontDescription().contextualLigaturesState(); if (commonLigaturesState == FontDescription::NormalLigaturesState && discretionaryLigaturesState == FontDescription::NormalLigaturesState - && historicalLigaturesState == FontDescription::NormalLigaturesState) + && historicalLigaturesState == FontDescription::NormalLigaturesState && contextualLigaturesState == FontDescription::NormalLigaturesState) return cssValuePool().createIdentifierValue(CSSValueNormal); - RefPtr<CSSValueList> valueList = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> valueList = CSSValueList::createSpaceSeparated(); if (commonLigaturesState != FontDescription::NormalLigaturesState) valueList->append(cssValuePool().createIdentifierValue(commonLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoCommonLigatures : CSSValueCommonLigatures)); if (discretionaryLigaturesState != FontDescription::NormalLigaturesState) valueList->append(cssValuePool().createIdentifierValue(discretionaryLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoDiscretionaryLigatures : CSSValueDiscretionaryLigatures)); if (historicalLigaturesState != FontDescription::NormalLigaturesState) valueList->append(cssValuePool().createIdentifierValue(historicalLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoHistoricalLigatures : CSSValueHistoricalLigatures)); + if (contextualLigaturesState != FontDescription::NormalLigaturesState) + valueList->append(cssValuePool().createIdentifierValue(contextualLigaturesState == FontDescription::DisabledLigaturesState ? CSSValueNoContextual : CSSValueContextual)); return valueList; } case CSSPropertyZIndex: @@ -2435,13 +2373,14 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyAnimationDirection: ASSERT(RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()); case CSSPropertyWebkitAnimationDirection: { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - const CSSAnimationDataList* t = style->animations(); - if (t) { - for (size_t i = 0; i < t->size(); ++i) - list->append(valueForAnimationDirection(t->animation(i)->direction())); - } else + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + const CSSAnimationData* animationData = style->animations(); + if (animationData) { + for (size_t i = 0; i < animationData->directionList().size(); ++i) + list->append(valueForAnimationDirection(animationData->directionList()[i])); + } else { list->append(cssValuePool().createIdentifierValue(CSSValueNormal)); + } return list.release(); } case CSSPropertyAnimationDuration: @@ -2451,59 +2390,53 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyAnimationFillMode: ASSERT(RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()); case CSSPropertyWebkitAnimationFillMode: { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - const CSSAnimationDataList* t = style->animations(); - if (t) { - for (size_t i = 0; i < t->size(); ++i) - list->append(valueForAnimationFillMode(t->animation(i)->fillMode())); - } else + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + const CSSAnimationData* animationData = style->animations(); + if (animationData) { + for (size_t i = 0; i < animationData->fillModeList().size(); ++i) + list->append(valueForAnimationFillMode(animationData->fillModeList()[i])); + } else { list->append(cssValuePool().createIdentifierValue(CSSValueNone)); + } return list.release(); } case CSSPropertyAnimationIterationCount: ASSERT(RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()); case CSSPropertyWebkitAnimationIterationCount: { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - const CSSAnimationDataList* t = style->animations(); - if (t) { - for (size_t i = 0; i < t->size(); ++i) { - double iterationCount = t->animation(i)->iterationCount(); - if (iterationCount == CSSAnimationData::IterationCountInfinite) - list->append(cssValuePool().createIdentifierValue(CSSValueInfinite)); - else - list->append(cssValuePool().createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER)); - } - } else - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationIterationCount(), CSSPrimitiveValue::CSS_NUMBER)); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + const CSSAnimationData* animationData = style->animations(); + if (animationData) { + for (size_t i = 0; i < animationData->iterationCountList().size(); ++i) + list->append(valueForAnimationIterationCount(animationData->iterationCountList()[i])); + } else { + list->append(cssValuePool().createValue(CSSAnimationData::initialIterationCount(), CSSPrimitiveValue::CSS_NUMBER)); + } return list.release(); } case CSSPropertyAnimationName: ASSERT(RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()); case CSSPropertyWebkitAnimationName: { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - const CSSAnimationDataList* t = style->animations(); - if (t) { - for (size_t i = 0; i < t->size(); ++i) - list->append(cssValuePool().createValue(t->animation(i)->name(), CSSPrimitiveValue::CSS_STRING)); - } else + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + const CSSAnimationData* animationData = style->animations(); + if (animationData) { + for (size_t i = 0; i < animationData->nameList().size(); ++i) + list->append(cssValuePool().createValue(animationData->nameList()[i], CSSPrimitiveValue::CSS_STRING)); + } else { list->append(cssValuePool().createIdentifierValue(CSSValueNone)); + } return list.release(); } case CSSPropertyAnimationPlayState: ASSERT(RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()); case CSSPropertyWebkitAnimationPlayState: { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - const CSSAnimationDataList* t = style->animations(); - if (t) { - for (size_t i = 0; i < t->size(); ++i) { - int prop = t->animation(i)->playState(); - if (prop == AnimPlayStatePlaying) - list->append(cssValuePool().createIdentifierValue(CSSValueRunning)); - else - list->append(cssValuePool().createIdentifierValue(CSSValuePaused)); - } - } else + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + const CSSAnimationData* animationData = style->animations(); + if (animationData) { + for (size_t i = 0; i < animationData->playStateList().size(); ++i) + list->append(valueForAnimationPlayState(animationData->playStateList()[i])); + } else { list->append(cssValuePool().createIdentifierValue(CSSValueRunning)); + } return list.release(); } case CSSPropertyAnimationTimingFunction: @@ -2512,40 +2445,33 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return valueForAnimationTimingFunction(style->animations()); case CSSPropertyAnimation: case CSSPropertyWebkitAnimation: { - const CSSAnimationDataList* animations = style->animations(); - if (animations) { - RefPtr<CSSValueList> animationsList = CSSValueList::createCommaSeparated(); - for (size_t i = 0; i < animations->size(); ++i) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - const CSSAnimationData* animation = animations->animation(i); - list->append(cssValuePool().createValue(animation->name(), CSSPrimitiveValue::CSS_STRING)); - list->append(cssValuePool().createValue(animation->duration(), CSSPrimitiveValue::CSS_S)); - list->append(createTimingFunctionValue(animation->timingFunction())); - list->append(cssValuePool().createValue(animation->delay(), CSSPrimitiveValue::CSS_S)); - if (animation->iterationCount() == CSSAnimationData::IterationCountInfinite) - list->append(cssValuePool().createIdentifierValue(CSSValueInfinite)); - else - list->append(cssValuePool().createValue(animation->iterationCount(), CSSPrimitiveValue::CSS_NUMBER)); - list->append(valueForAnimationDirection(animation->direction())); - list->append(valueForAnimationFillMode(animation->fillMode())); - if (animation->playState() == AnimPlayStatePaused) - list->append(cssValuePool().createIdentifierValue(CSSValuePaused)); - else - list->append(cssValuePool().createIdentifierValue(CSSValueRunning)); + const CSSAnimationData* animationData = style->animations(); + if (animationData) { + RefPtrWillBeRawPtr<CSSValueList> animationsList = CSSValueList::createCommaSeparated(); + for (size_t i = 0; i < animationData->nameList().size(); ++i) { + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + list->append(cssValuePool().createValue(animationData->nameList()[i], CSSPrimitiveValue::CSS_STRING)); + list->append(cssValuePool().createValue(CSSTimingData::getRepeated(animationData->durationList(), i), CSSPrimitiveValue::CSS_S)); + list->append(createTimingFunctionValue(CSSTimingData::getRepeated(animationData->timingFunctionList(), i).get())); + list->append(cssValuePool().createValue(CSSTimingData::getRepeated(animationData->delayList(), i), CSSPrimitiveValue::CSS_S)); + list->append(valueForAnimationIterationCount(CSSTimingData::getRepeated(animationData->iterationCountList(), i))); + list->append(valueForAnimationDirection(CSSTimingData::getRepeated(animationData->directionList(), i))); + list->append(valueForAnimationFillMode(CSSTimingData::getRepeated(animationData->fillModeList(), i))); + list->append(valueForAnimationPlayState(CSSTimingData::getRepeated(animationData->playStateList(), i))); animationsList->append(list); } return animationsList.release(); } - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); // animation-name default value. list->append(cssValuePool().createIdentifierValue(CSSValueNone)); - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDuration(), CSSPrimitiveValue::CSS_S)); - list->append(createTimingFunctionValue(CSSAnimationData::initialAnimationTimingFunction().get())); - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDelay(), CSSPrimitiveValue::CSS_S)); - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationIterationCount(), CSSPrimitiveValue::CSS_NUMBER)); - list->append(valueForAnimationDirection(CSSAnimationData::initialAnimationDirection())); - list->append(valueForAnimationFillMode(CSSAnimationData::initialAnimationFillMode())); + list->append(cssValuePool().createValue(CSSAnimationData::initialDuration(), CSSPrimitiveValue::CSS_S)); + list->append(createTimingFunctionValue(CSSAnimationData::initialTimingFunction().get())); + list->append(cssValuePool().createValue(CSSAnimationData::initialDelay(), CSSPrimitiveValue::CSS_S)); + list->append(cssValuePool().createValue(CSSAnimationData::initialIterationCount(), CSSPrimitiveValue::CSS_NUMBER)); + list->append(valueForAnimationDirection(CSSAnimationData::initialDirection())); + list->append(valueForAnimationFillMode(CSSAnimationData::initialFillMode())); // Initial animation-play-state. list->append(cssValuePool().createIdentifierValue(CSSValueRunning)); return list.release(); @@ -2556,6 +2482,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!style->hasAspectRatio()) return cssValuePool().createIdentifierValue(CSSValueNone); return CSSAspectRatioValue::create(style->aspectRatioNumerator(), style->aspectRatioDenominator()); + case CSSPropertyBackfaceVisibility: case CSSPropertyWebkitBackfaceVisibility: return cssValuePool().createIdentifierValue((style->backfaceVisibility() == BackfaceVisibilityHidden) ? CSSValueHidden : CSSValueVisible); case CSSPropertyWebkitBorderImage: @@ -2591,20 +2518,21 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyWebkitMarginTopCollapse: case CSSPropertyWebkitMarginBeforeCollapse: return cssValuePool().createValue(style->marginBeforeCollapse()); + case CSSPropertyPerspective: case CSSPropertyWebkitPerspective: if (!style->hasPerspective()) return cssValuePool().createIdentifierValue(CSSValueNone); return zoomAdjustedPixelValue(style->perspective(), *style); + case CSSPropertyPerspectiveOrigin: case CSSPropertyWebkitPerspectiveOrigin: { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (renderer) { LayoutRect box; if (renderer->isBox()) box = toRenderBox(renderer)->borderBoxRect(); - RenderView* renderView = m_node->document().renderView(); - list->append(zoomAdjustedPixelValue(minimumValueForLength(style->perspectiveOriginX(), box.width(), renderView), *style)); - list->append(zoomAdjustedPixelValue(minimumValueForLength(style->perspectiveOriginY(), box.height(), renderView), *style)); + list->append(zoomAdjustedPixelValue(minimumValueForLength(style->perspectiveOriginX(), box.width()), *style)); + list->append(zoomAdjustedPixelValue(minimumValueForLength(style->perspectiveOriginY(), box.height()), *style)); } else { list->append(zoomAdjustedPixelValueForLength(style->perspectiveOriginX(), *style)); @@ -2632,7 +2560,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyClip: { if (!style->hasClip()) return cssValuePool().createIdentifierValue(CSSValueAuto); - RefPtr<Rect> rect = Rect::create(); + RefPtrWillBeRawPtr<Rect> rect = Rect::create(); rect->setTop(zoomAdjustedPixelValue(style->clip().top().value(), *style)); rect->setRight(zoomAdjustedPixelValue(style->clip().right().value(), *style)); rect->setBottom(zoomAdjustedPixelValue(style->clip().bottom().value(), *style)); @@ -2641,18 +2569,19 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert } case CSSPropertySpeak: return cssValuePool().createValue(style->speak()); + case CSSPropertyTransform: case CSSPropertyWebkitTransform: return computedTransform(renderer, *style); + case CSSPropertyTransformOrigin: case CSSPropertyWebkitTransformOrigin: { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); if (renderer) { LayoutRect box; if (renderer->isBox()) box = toRenderBox(renderer)->borderBoxRect(); - RenderView* renderView = m_node->document().renderView(); - list->append(zoomAdjustedPixelValue(minimumValueForLength(style->transformOriginX(), box.width(), renderView), *style)); - list->append(zoomAdjustedPixelValue(minimumValueForLength(style->transformOriginY(), box.height(), renderView), *style)); + list->append(zoomAdjustedPixelValue(minimumValueForLength(style->transformOriginX(), box.width()), *style)); + list->append(zoomAdjustedPixelValue(minimumValueForLength(style->transformOriginY(), box.height()), *style)); if (style->transformOriginZ() != 0) list->append(zoomAdjustedPixelValue(style->transformOriginZ(), *style)); } else { @@ -2663,6 +2592,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert } return list.release(); } + case CSSPropertyTransformStyle: case CSSPropertyWebkitTransformStyle: return cssValuePool().createIdentifierValue((style->transformStyle3D() == TransformStyle3DPreserve3D) ? CSSValuePreserve3d : CSSValueFlat); case CSSPropertyTransitionDelay: @@ -2679,39 +2609,30 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return valueForAnimationTimingFunction(style->transitions()); case CSSPropertyTransition: case CSSPropertyWebkitTransition: { - const CSSAnimationDataList* animList = style->transitions(); - if (animList) { - RefPtr<CSSValueList> transitionsList = CSSValueList::createCommaSeparated(); - for (size_t i = 0; i < animList->size(); ++i) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - const CSSAnimationData* animation = animList->animation(i); - list->append(createTransitionPropertyValue(animation)); - list->append(cssValuePool().createValue(animation->duration(), CSSPrimitiveValue::CSS_S)); - list->append(createTimingFunctionValue(animation->timingFunction())); - list->append(cssValuePool().createValue(animation->delay(), CSSPrimitiveValue::CSS_S)); + const CSSTransitionData* transitionData = style->transitions(); + if (transitionData) { + RefPtrWillBeRawPtr<CSSValueList> transitionsList = CSSValueList::createCommaSeparated(); + for (size_t i = 0; i < transitionData->propertyList().size(); ++i) { + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + list->append(createTransitionPropertyValue(transitionData->propertyList()[i])); + list->append(cssValuePool().createValue(CSSTimingData::getRepeated(transitionData->durationList(), i), CSSPrimitiveValue::CSS_S)); + list->append(createTimingFunctionValue(CSSTimingData::getRepeated(transitionData->timingFunctionList(), i).get())); + list->append(cssValuePool().createValue(CSSTimingData::getRepeated(transitionData->delayList(), i), CSSPrimitiveValue::CSS_S)); transitionsList->append(list); } return transitionsList.release(); } - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); // transition-property default value. list->append(cssValuePool().createIdentifierValue(CSSValueAll)); - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDuration(), CSSPrimitiveValue::CSS_S)); - list->append(createTimingFunctionValue(CSSAnimationData::initialAnimationTimingFunction().get())); - list->append(cssValuePool().createValue(CSSAnimationData::initialAnimationDelay(), CSSPrimitiveValue::CSS_S)); + list->append(cssValuePool().createValue(CSSTransitionData::initialDuration(), CSSPrimitiveValue::CSS_S)); + list->append(createTimingFunctionValue(CSSTransitionData::initialTimingFunction().get())); + list->append(cssValuePool().createValue(CSSTransitionData::initialDelay(), CSSPrimitiveValue::CSS_S)); return list.release(); } case CSSPropertyPointerEvents: return cssValuePool().createValue(style->pointerEvents()); - case CSSPropertyWebkitLineGrid: - if (style->lineGrid().isNull()) - return cssValuePool().createIdentifierValue(CSSValueNone); - return cssValuePool().createValue(style->lineGrid(), CSSPrimitiveValue::CSS_STRING); - case CSSPropertyWebkitLineSnap: - return CSSPrimitiveValue::create(style->lineSnap()); - case CSSPropertyWebkitLineAlign: - return CSSPrimitiveValue::create(style->lineAlign()); case CSSPropertyWebkitWritingMode: return cssValuePool().createValue(style->writingMode()); case CSSPropertyWebkitTextCombine: @@ -2734,50 +2655,14 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert return CSSPrimitiveValue::create(toReferenceClipPathOperation(operation)->url(), CSSPrimitiveValue::CSS_URI); } return cssValuePool().createIdentifierValue(CSSValueNone); - case CSSPropertyWebkitFlowInto: - if (style->flowThread().isNull()) - return cssValuePool().createIdentifierValue(CSSValueNone); - return cssValuePool().createValue(style->flowThread(), CSSPrimitiveValue::CSS_STRING); - case CSSPropertyWebkitFlowFrom: - if (!style->hasFlowFrom()) - return cssValuePool().createIdentifierValue(CSSValueNone); - return cssValuePool().createValue(style->regionThread(), CSSPrimitiveValue::CSS_STRING); - case CSSPropertyWebkitRegionFragment: - return cssValuePool().createValue(style->regionFragment()); case CSSPropertyWebkitWrapFlow: return cssValuePool().createValue(style->wrapFlow()); case CSSPropertyShapeMargin: - return cssValuePool().createValue(style->shapeMargin()); - case CSSPropertyShapePadding: - return cssValuePool().createValue(style->shapePadding()); + return cssValuePool().createValue(style->shapeMargin(), *style); case CSSPropertyShapeImageThreshold: return cssValuePool().createValue(style->shapeImageThreshold(), CSSPrimitiveValue::CSS_NUMBER); - case CSSPropertyShapeInside: - if (!style->shapeInside()) - return cssValuePool().createIdentifierValue(CSSValueAuto); - if (style->shapeInside()->type() == ShapeValue::Box) - return cssValuePool().createValue(style->shapeInside()->layoutBox()); - if (style->shapeInside()->type() == ShapeValue::Outside) - return cssValuePool().createIdentifierValue(CSSValueOutsideShape); - if (style->shapeInside()->type() == ShapeValue::Image) { - if (style->shapeInside()->image()) - return style->shapeInside()->image()->cssValue(); - return cssValuePool().createIdentifierValue(CSSValueNone); - } - ASSERT(style->shapeInside()->type() == ShapeValue::Shape); - return valueForBasicShape(*style, style->shapeInside()->shape()); case CSSPropertyShapeOutside: - if (!style->shapeOutside()) - return cssValuePool().createIdentifierValue(CSSValueAuto); - if (style->shapeOutside()->type() == ShapeValue::Box) - return cssValuePool().createValue(style->shapeOutside()->layoutBox()); - if (style->shapeOutside()->type() == ShapeValue::Image) { - if (style->shapeOutside()->image()) - return style->shapeOutside()->image()->cssValue(); - return cssValuePool().createIdentifierValue(CSSValueNone); - } - ASSERT(style->shapeOutside()->type() == ShapeValue::Shape); - return valueForBasicShape(*style, style->shapeOutside()->shape()); + return valueForShape(*style, style->shapeOutside()); case CSSPropertyWebkitWrapThrough: return cssValuePool().createValue(style->wrapThrough()); case CSSPropertyWebkitFilter: @@ -2790,7 +2675,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert if (!layers->next()) return cssValuePool().createValue(layers->blendMode()); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); for (const FillLayer* currLayer = layers; currLayer; currLayer = currLayer->next()) list->append(cssValuePool().createValue(currLayer->blendMode())); @@ -2799,12 +2684,12 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyBackground: return valuesForBackgroundShorthand(); case CSSPropertyBorder: { - RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyBorderTop, DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyBorderTop, DoNotUpdateLayout); const CSSPropertyID properties[3] = { CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft }; for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) { if (!compareCSSValuePtr<CSSValue>(value, getPropertyCSSValue(properties[i], DoNotUpdateLayout))) - return 0; + return nullptr; } return value.release(); } @@ -2844,7 +2729,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert break; case CSSPropertyInternalCallback: // This property is hidden from the web. - return 0; + return nullptr; /* Unimplemented CSS 3 properties (including CSS3 shorthand properties) */ case CSSPropertyWebkitTextEmphasis: @@ -2936,7 +2821,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyInternalMarqueeSpeed: case CSSPropertyInternalMarqueeStyle: ASSERT_NOT_REACHED(); - return 0; + return nullptr; case CSSPropertyBufferedRendering: case CSSPropertyClipPath: @@ -2951,7 +2836,6 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyStopOpacity: case CSSPropertyColorInterpolation: case CSSPropertyColorInterpolationFilters: - case CSSPropertyColorProfile: case CSSPropertyColorRendering: case CSSPropertyFill: case CSSPropertyFillOpacity: @@ -2975,21 +2859,23 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropert case CSSPropertyDominantBaseline: case CSSPropertyGlyphOrientationHorizontal: case CSSPropertyGlyphOrientationVertical: - case CSSPropertyKerning: case CSSPropertyTextAnchor: case CSSPropertyVectorEffect: case CSSPropertyPaintOrder: case CSSPropertyWritingMode: return getSVGPropertyCSSValue(propertyID, DoNotUpdateLayout); + + case CSSPropertyAll: + return nullptr; } logUnimplementedPropertyID(propertyID); - return 0; + return nullptr; } String CSSComputedStyleDeclaration::getPropertyValue(CSSPropertyID propertyID) const { - RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(propertyID); if (value) return value->cssText(); return ""; @@ -3029,37 +2915,37 @@ bool CSSComputedStyleDeclaration::cssPropertyMatches(CSSPropertyID propertyID, c return true; } } - RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(propertyID); return value && propertyValue && value->equals(*propertyValue); } -PassRefPtr<MutableStylePropertySet> CSSComputedStyleDeclaration::copyProperties() const +PassRefPtrWillBeRawPtr<MutableStylePropertySet> CSSComputedStyleDeclaration::copyProperties() const { return copyPropertiesInSet(computableProperties()); } -PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForShorthandProperty(const StylePropertyShorthand& shorthand) const +PassRefPtrWillBeRawPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForShorthandProperty(const StylePropertyShorthand& shorthand) const { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); for (size_t i = 0; i < shorthand.length(); ++i) { - RefPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i], DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i], DoNotUpdateLayout); list->append(value); } return list.release(); } -PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForSidesShorthand(const StylePropertyShorthand& shorthand) const +PassRefPtrWillBeRawPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForSidesShorthand(const StylePropertyShorthand& shorthand) const { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); // Assume the properties are in the usual order top, right, bottom, left. - RefPtr<CSSValue> topValue = getPropertyCSSValue(shorthand.properties()[0], DoNotUpdateLayout); - RefPtr<CSSValue> rightValue = getPropertyCSSValue(shorthand.properties()[1], DoNotUpdateLayout); - RefPtr<CSSValue> bottomValue = getPropertyCSSValue(shorthand.properties()[2], DoNotUpdateLayout); - RefPtr<CSSValue> leftValue = getPropertyCSSValue(shorthand.properties()[3], DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> topValue = getPropertyCSSValue(shorthand.properties()[0], DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> rightValue = getPropertyCSSValue(shorthand.properties()[1], DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> bottomValue = getPropertyCSSValue(shorthand.properties()[2], DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> leftValue = getPropertyCSSValue(shorthand.properties()[3], DoNotUpdateLayout); // All 4 properties must be specified. if (!topValue || !rightValue || !bottomValue || !leftValue) - return 0; + return nullptr; bool showLeft = !compareCSSValuePtr(rightValue, leftValue); bool showBottom = !compareCSSValuePtr(topValue, bottomValue) || showLeft; @@ -3076,22 +2962,22 @@ PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForSidesShorthand(co return list.release(); } -PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForGridShorthand(const StylePropertyShorthand& shorthand) const +PassRefPtrWillBeRawPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForGridShorthand(const StylePropertyShorthand& shorthand) const { - RefPtr<CSSValueList> list = CSSValueList::createSlashSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSlashSeparated(); for (size_t i = 0; i < shorthand.length(); ++i) { - RefPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i], DoNotUpdateLayout); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i], DoNotUpdateLayout); list->append(value.release()); } return list.release(); } -PassRefPtr<MutableStylePropertySet> CSSComputedStyleDeclaration::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const +PassRefPtrWillBeRawPtr<MutableStylePropertySet> CSSComputedStyleDeclaration::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const { - Vector<CSSProperty, 256> list; + WillBeHeapVector<CSSProperty, 256> list; list.reserveInitialCapacity(properties.size()); for (unsigned i = 0; i < properties.size(); ++i) { - RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(properties[i]); if (value) list.append(CSSProperty(properties[i], value.release(), false)); } @@ -3103,13 +2989,13 @@ CSSRule* CSSComputedStyleDeclaration::parentRule() const return 0; } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(const String& propertyName) +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) - return 0; - RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); - return value ? value->cloneForCSSOM() : 0; + return nullptr; + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(propertyID); + return value ? value->cloneForCSSOM() : nullptr; } String CSSComputedStyleDeclaration::getPropertyValue(const String& propertyName) @@ -3147,7 +3033,7 @@ String CSSComputedStyleDeclaration::removeProperty(const String& name, Exception return String(); } -PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID) +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID) { return getPropertyCSSValue(propertyID); } @@ -3162,89 +3048,7 @@ void CSSComputedStyleDeclaration::setPropertyInternal(CSSPropertyID id, const St exceptionState.throwDOMException(NoModificationAllowedError, "These styles are computed, and therefore the '" + getPropertyNameString(id) + "' property is read-only."); } -const HashMap<AtomicString, String>* CSSComputedStyleDeclaration::variableMap() const -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - Node* styledNode = this->styledNode(); - if (!styledNode) - return 0; - RefPtr<RenderStyle> style = styledNode->computedStyle(styledNode->isPseudoElement() ? NOPSEUDO : m_pseudoElementSpecifier); - if (!style) - return 0; - return style->variables(); -} - -unsigned CSSComputedStyleDeclaration::variableCount() const -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - const HashMap<AtomicString, String>* variables = variableMap(); - if (!variables) - return 0; - return variables->size(); -} - -String CSSComputedStyleDeclaration::variableValue(const AtomicString& name) const -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - const HashMap<AtomicString, String>* variables = variableMap(); - if (!variables) - return emptyString(); - HashMap<AtomicString, String>::const_iterator it = variables->find(name); - if (it == variables->end()) - return emptyString(); - return it->value; -} - -bool CSSComputedStyleDeclaration::setVariableValue(const AtomicString& name, const String&, ExceptionState& exceptionState) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - exceptionState.throwDOMException(NoModificationAllowedError, "These styles are computed, and therefore the '" + name + "' property is read-only."); - return false; -} - -bool CSSComputedStyleDeclaration::removeVariable(const AtomicString&) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - return false; -} - -bool CSSComputedStyleDeclaration::clearVariables(ExceptionState& exceptionState) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - exceptionState.throwDOMException(NoModificationAllowedError, "These styles are computed, and therefore variables may not be cleared."); - return false; -} - -CSSComputedStyleDeclaration::ComputedCSSVariablesIterator::ComputedCSSVariablesIterator(const HashMap<AtomicString, String>* variables) - : m_active(variables) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - if (m_active) { - m_it = variables->begin(); - m_end = variables->end(); - } -} - -void CSSComputedStyleDeclaration::ComputedCSSVariablesIterator::advance() -{ - ASSERT(m_active); - ++m_it; - m_active = !atEnd(); -} - -AtomicString CSSComputedStyleDeclaration::ComputedCSSVariablesIterator::name() const -{ - ASSERT(m_active); - return m_it->key; -} - -String CSSComputedStyleDeclaration::ComputedCSSVariablesIterator::value() const -{ - ASSERT(m_active); - return m_it->value; -} - -PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForBackgroundShorthand() const +PassRefPtrWillBeRawPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForBackgroundShorthand() const { static const CSSPropertyID propertiesBeforeSlashSeperator[5] = { CSSPropertyBackgroundColor, CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat, CSSPropertyBackgroundAttachment, @@ -3252,10 +3056,16 @@ PassRefPtr<CSSValueList> CSSComputedStyleDeclaration::valuesForBackgroundShortha static const CSSPropertyID propertiesAfterSlashSeperator[3] = { CSSPropertyBackgroundSize, CSSPropertyBackgroundOrigin, CSSPropertyBackgroundClip }; - RefPtr<CSSValueList> list = CSSValueList::createSlashSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSlashSeparated(); list->append(valuesForShorthandProperty(StylePropertyShorthand(CSSPropertyBackground, propertiesBeforeSlashSeperator, WTF_ARRAY_LENGTH(propertiesBeforeSlashSeperator)))); list->append(valuesForShorthandProperty(StylePropertyShorthand(CSSPropertyBackground, propertiesAfterSlashSeperator, WTF_ARRAY_LENGTH(propertiesAfterSlashSeperator)))); return list.release(); } +void CSSComputedStyleDeclaration::trace(Visitor* visitor) +{ + visitor->trace(m_node); + CSSStyleDeclaration::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h b/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h index a3ff8770319..d60072ab91a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.h @@ -33,9 +33,6 @@ namespace WebCore { class CSSPrimitiveValue; class CSSValueList; -class Color; -class CustomFilterNumberParameter; -class CustomFilterParameter; class ExceptionState; class MutableStylePropertySet; class Node; @@ -44,54 +41,41 @@ class RenderStyle; class SVGPaint; class ShadowData; class ShadowList; +class StyleColor; class StylePropertySet; class StylePropertyShorthand; enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true }; -class CSSComputedStyleDeclaration : public CSSStyleDeclaration { -private: - class ComputedCSSVariablesIterator : public CSSVariablesIterator { - public: - virtual ~ComputedCSSVariablesIterator() { } - static PassRefPtr<ComputedCSSVariablesIterator> create(const HashMap<AtomicString, String>* variableMap) { return adoptRef(new ComputedCSSVariablesIterator(variableMap)); } - private: - explicit ComputedCSSVariablesIterator(const HashMap<AtomicString, String>* variableMap); - virtual void advance() OVERRIDE; - virtual bool atEnd() const OVERRIDE { return m_it == m_end; } - virtual AtomicString name() const OVERRIDE; - virtual String value() const OVERRIDE; - bool m_active; - typedef HashMap<AtomicString, String>::const_iterator VariablesMapIterator; - VariablesMapIterator m_it; - VariablesMapIterator m_end; - }; - +class CSSComputedStyleDeclaration FINAL : public CSSStyleDeclaration { public: - static PassRefPtr<CSSComputedStyleDeclaration> create(PassRefPtr<Node> node, bool allowVisitedStyle = false, const String& pseudoElementName = String()) + static PassRefPtrWillBeRawPtr<CSSComputedStyleDeclaration> create(PassRefPtrWillBeRawPtr<Node> node, bool allowVisitedStyle = false, const String& pseudoElementName = String()) { - return adoptRef(new CSSComputedStyleDeclaration(node, allowVisitedStyle, pseudoElementName)); + return adoptRefWillBeNoop(new CSSComputedStyleDeclaration(node, allowVisitedStyle, pseudoElementName)); } virtual ~CSSComputedStyleDeclaration(); +#if !ENABLE(OILPAN) virtual void ref() OVERRIDE; virtual void deref() OVERRIDE; +#endif - PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; String getPropertyValue(CSSPropertyID) const; bool getPropertyPriority(CSSPropertyID) const; - virtual PassRefPtr<MutableStylePropertySet> copyProperties() const OVERRIDE; + virtual PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyProperties() const OVERRIDE; - PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID, EUpdateLayout) const; - PassRefPtr<CSSValue> getFontSizeCSSValuePreferringKeyword() const; + PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(CSSPropertyID, EUpdateLayout = UpdateLayout) const; + PassRefPtrWillBeRawPtr<CSSValue> getFontSizeCSSValuePreferringKeyword() const; bool useFixedFontDefaultSize() const; - PassRefPtr<CSSValue> getSVGPropertyCSSValue(CSSPropertyID, EUpdateLayout) const; + PassRefPtrWillBeRawPtr<CSSValue> getSVGPropertyCSSValue(CSSPropertyID, EUpdateLayout) const; + + PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; - PassRefPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; + virtual void trace(Visitor*) OVERRIDE; private: - CSSComputedStyleDeclaration(PassRefPtr<Node>, bool allowVisitedStyle, const String&); + CSSComputedStyleDeclaration(PassRefPtrWillBeRawPtr<Node>, bool allowVisitedStyle, const String&); // The styled node is either the node passed into getComputedStyle, or the // PseudoElement for :before and :after if they exist. @@ -101,49 +85,43 @@ private: Node* styledNode() const; // CSSOM functions. Don't make these public. - virtual CSSRule* parentRule() const; - virtual unsigned length() const; - virtual String item(unsigned index) const; + virtual CSSRule* parentRule() const OVERRIDE; + virtual unsigned length() const OVERRIDE; + virtual String item(unsigned index) const OVERRIDE; PassRefPtr<RenderStyle> computeRenderStyle(CSSPropertyID) const; - virtual PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName); - virtual String getPropertyValue(const String& propertyName); - virtual String getPropertyPriority(const String& propertyName); - virtual String getPropertyShorthand(const String& propertyName); - virtual bool isPropertyImplicit(const String& propertyName); - virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState&); - virtual String removeProperty(const String& propertyName, ExceptionState&); - virtual String cssText() const; - virtual void setCSSText(const String&, ExceptionState&); - virtual PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID); - virtual String getPropertyValueInternal(CSSPropertyID); - virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&); - - const HashMap<AtomicString, String>* variableMap() const; - virtual unsigned variableCount() const OVERRIDE; - virtual String variableValue(const AtomicString& name) const OVERRIDE; - virtual bool setVariableValue(const AtomicString& name, const String& value, ExceptionState&) OVERRIDE; - virtual bool removeVariable(const AtomicString& name) OVERRIDE; - virtual bool clearVariables(ExceptionState&) OVERRIDE; - virtual PassRefPtr<CSSVariablesIterator> variablesIterator() const OVERRIDE { return ComputedCSSVariablesIterator::create(variableMap()); } + virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(const String& propertyName) OVERRIDE; + virtual String getPropertyValue(const String& propertyName) OVERRIDE; + virtual String getPropertyPriority(const String& propertyName) OVERRIDE; + virtual String getPropertyShorthand(const String& propertyName) OVERRIDE; + virtual bool isPropertyImplicit(const String& propertyName) OVERRIDE; + virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState&) OVERRIDE; + virtual String removeProperty(const String& propertyName, ExceptionState&) OVERRIDE; + virtual String cssText() const OVERRIDE; + virtual void setCSSText(const String&, ExceptionState&) OVERRIDE; + virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) OVERRIDE; + virtual String getPropertyValueInternal(CSSPropertyID) OVERRIDE; + virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) OVERRIDE; virtual bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const OVERRIDE; - PassRefPtr<CSSValue> valueForShadowData(const ShadowData&, const RenderStyle&, bool useSpread) const; - PassRefPtr<CSSValue> valueForShadowList(const ShadowList*, const RenderStyle&, bool useSpread) const; - PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(const RenderStyle&, const Color&) const; - PassRefPtr<SVGPaint> adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint>, RenderStyle&) const; + PassRefPtrWillBeRawPtr<CSSValue> valueForShadowData(const ShadowData&, const RenderStyle&, bool useSpread) const; + PassRefPtrWillBeRawPtr<CSSValue> valueForShadowList(const ShadowList*, const RenderStyle&, bool useSpread) const; + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> currentColorOrValidColor(const RenderStyle&, const StyleColor&) const; + PassRefPtrWillBeRawPtr<SVGPaint> adjustSVGPaintForCurrentColor(PassRefPtrWillBeRawPtr<SVGPaint>, RenderStyle&) const; - PassRefPtr<CSSValue> valueForFilter(const RenderObject*, const RenderStyle&) const; + PassRefPtrWillBeRawPtr<CSSValue> valueForFilter(const RenderObject*, const RenderStyle&) const; - PassRefPtr<CSSValueList> valuesForShorthandProperty(const StylePropertyShorthand&) const; - PassRefPtr<CSSValueList> valuesForSidesShorthand(const StylePropertyShorthand&) const; - PassRefPtr<CSSValueList> valuesForBackgroundShorthand() const; - PassRefPtr<CSSValueList> valuesForGridShorthand(const StylePropertyShorthand&) const; + PassRefPtrWillBeRawPtr<CSSValueList> valuesForShorthandProperty(const StylePropertyShorthand&) const; + PassRefPtrWillBeRawPtr<CSSValueList> valuesForSidesShorthand(const StylePropertyShorthand&) const; + PassRefPtrWillBeRawPtr<CSSValueList> valuesForBackgroundShorthand() const; + PassRefPtrWillBeRawPtr<CSSValueList> valuesForGridShorthand(const StylePropertyShorthand&) const; - RefPtr<Node> m_node; + RefPtrWillBeMember<Node> m_node; PseudoId m_pseudoElementSpecifier; bool m_allowVisitedStyle; +#if !ENABLE(OILPAN) unsigned m_refCount; +#endif }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp index 801cbb66f99..daa45df9d05 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.cpp @@ -167,7 +167,7 @@ void CSSCrossfadeValue::loadSubimages(ResourceFetcher* fetcher) PassRefPtr<Image> CSSCrossfadeValue::image(RenderObject* renderer, const IntSize& size) { if (size.isEmpty()) - return 0; + return nullptr; ResourceFetcher* fetcher = renderer->document().fetcher(); ImageResource* cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), fetcher); @@ -218,4 +218,12 @@ bool CSSCrossfadeValue::equals(const CSSCrossfadeValue& other) const && compareCSSValuePtr(m_percentageValue, other.m_percentageValue); } +void CSSCrossfadeValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_fromValue); + visitor->trace(m_toValue); + visitor->trace(m_percentageValue); + CSSImageGeneratorValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h b/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h index ffb46aed9f1..617a5d25ff1 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSCrossfadeValue.h @@ -43,9 +43,9 @@ class Document; class CSSCrossfadeValue : public CSSImageGeneratorValue { friend class CrossfadeSubimageObserverProxy; public: - static PassRefPtr<CSSCrossfadeValue> create(PassRefPtr<CSSValue> fromValue, PassRefPtr<CSSValue> toValue) + static PassRefPtrWillBeRawPtr<CSSCrossfadeValue> create(PassRefPtrWillBeRawPtr<CSSValue> fromValue, PassRefPtrWillBeRawPtr<CSSValue> toValue) { - return adoptRef(new CSSCrossfadeValue(fromValue, toValue)); + return adoptRefWillBeNoop(new CSSCrossfadeValue(fromValue, toValue)); } ~CSSCrossfadeValue(); @@ -61,14 +61,16 @@ public: void loadSubimages(ResourceFetcher*); - void setPercentage(PassRefPtr<CSSPrimitiveValue> percentageValue) { m_percentageValue = percentageValue; } + void setPercentage(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> percentageValue) { m_percentageValue = percentageValue; } bool hasFailedOrCanceledSubresources() const; bool equals(const CSSCrossfadeValue&) const; + void traceAfterDispatch(Visitor*); + private: - CSSCrossfadeValue(PassRefPtr<CSSValue> fromValue, PassRefPtr<CSSValue> toValue) + CSSCrossfadeValue(PassRefPtrWillBeRawPtr<CSSValue> fromValue, PassRefPtrWillBeRawPtr<CSSValue> toValue) : CSSImageGeneratorValue(CrossfadeClass) , m_fromValue(fromValue) , m_toValue(toValue) @@ -76,7 +78,7 @@ private: , m_cachedToImage(0) , m_crossfadeSubimageObserver(this) { } - class CrossfadeSubimageObserverProxy : public ImageResourceClient { + class CrossfadeSubimageObserverProxy FINAL : public ImageResourceClient { public: CrossfadeSubimageObserverProxy(CSSCrossfadeValue* ownerValue) : m_ownerValue(ownerValue) @@ -92,9 +94,9 @@ private: void crossfadeChanged(const IntRect&); - RefPtr<CSSValue> m_fromValue; - RefPtr<CSSValue> m_toValue; - RefPtr<CSSPrimitiveValue> m_percentageValue; + RefPtrWillBeMember<CSSValue> m_fromValue; + RefPtrWillBeMember<CSSValue> m_toValue; + RefPtrWillBeMember<CSSPrimitiveValue> m_percentageValue; ResourcePtr<ImageResource> m_cachedFromImage; ResourcePtr<ImageResource> m_cachedToImage; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.cpp index 878fd8910de..296375b29b9 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "core/css/CSSCursorImageValue.h" -#include "SVGNames.h" +#include "core/SVGNames.h" #include "core/css/CSSImageSetValue.h" #include "core/fetch/ImageResource.h" #include "core/fetch/ResourceFetcher.h" @@ -34,20 +34,18 @@ #include "core/svg/SVGLengthContext.h" #include "core/svg/SVGURIReference.h" #include "wtf/MathExtras.h" +#include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" namespace WebCore { -static inline SVGCursorElement* resourceReferencedByCursorElement(const String& url, Document& document) +static inline SVGCursorElement* resourceReferencedByCursorElement(const String& url, TreeScope& treeScope) { - Element* element = SVGURIReference::targetElementFromIRIString(url, document); - if (element && element->hasTagName(SVGNames::cursorTag)) - return static_cast<SVGCursorElement*>(element); - - return 0; + Element* element = SVGURIReference::targetElementFromIRIString(url, treeScope); + return isSVGCursorElement(element) ? toSVGCursorElement(element) : 0; } -CSSCursorImageValue::CSSCursorImageValue(PassRefPtr<CSSValue> imageValue, bool hasHotSpot, const IntPoint& hotSpot) +CSSCursorImageValue::CSSCursorImageValue(PassRefPtrWillBeRawPtr<CSSValue> imageValue, bool hasHotSpot, const IntPoint& hotSpot) : CSSValue(CursorImageClass) , m_imageValue(imageValue) , m_hasHotSpot(hasHotSpot) @@ -58,6 +56,8 @@ CSSCursorImageValue::CSSCursorImageValue(PassRefPtr<CSSValue> imageValue, bool h CSSCursorImageValue::~CSSCursorImageValue() { + // The below teardown is all handled by weak pointer processing in oilpan. +#if !ENABLE(OILPAN) if (!isSVGCursor()) return; @@ -68,9 +68,10 @@ CSSCursorImageValue::~CSSCursorImageValue() for (; it != end; ++it) { SVGElement* referencedElement = *it; referencedElement->cursorImageValueRemoved(); - if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document())) + if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->treeScope())) cursorElement->removeClient(referencedElement); } +#endif } String CSSCursorImageValue::customCSSText() const @@ -95,21 +96,23 @@ bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element) return false; String url = toCSSImageValue(m_imageValue.get())->url(); - if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, element->document())) { + if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, element->treeScope())) { // FIXME: This will override hot spot specified in CSS, which is probably incorrect. SVGLengthContext lengthContext(0); m_hasHotSpot = true; - float x = roundf(cursorElement->xCurrentValue().value(lengthContext)); + float x = roundf(cursorElement->x()->currentValue()->value(lengthContext)); m_hotSpot.setX(static_cast<int>(x)); - float y = roundf(cursorElement->yCurrentValue().value(lengthContext)); + float y = roundf(cursorElement->y()->currentValue()->value(lengthContext)); m_hotSpot.setY(static_cast<int>(y)); - if (cachedImageURL() != element->document().completeURL(cursorElement->hrefCurrentValue())) + if (cachedImageURL() != element->document().completeURL(cursorElement->href()->currentValue()->value())) clearImageResource(); SVGElement* svgElement = toSVGElement(element); +#if !ENABLE(OILPAN) m_referencedElements.add(svgElement); +#endif svgElement->setCursorImageValue(this); cursorElement->addClient(svgElement); return true; @@ -130,10 +133,11 @@ StyleImage* CSSCursorImageValue::cachedImage(ResourceFetcher* loader, float devi // to change the URL of the CSSImageValue (which would then change behavior like cssText), // we create an alternate CSSImageValue to use. if (isSVGCursor() && loader && loader->document()) { - RefPtr<CSSImageValue> imageValue = toCSSImageValue(m_imageValue.get()); + RefPtrWillBeRawPtr<CSSImageValue> imageValue = toCSSImageValue(m_imageValue.get()); // FIXME: This will fail if the <cursor> element is in a shadow DOM (bug 59827) if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(imageValue->url(), *loader->document())) { - RefPtr<CSSImageValue> svgImageValue = CSSImageValue::create(cursorElement->hrefCurrentValue()); + RefPtrWillBeRawPtr<CSSImageValue> svgImageValue = CSSImageValue::create(loader->document()->completeURL(cursorElement->href()->currentValue()->value())); + svgImageValue->setReferrer(imageValue->referrer()); StyleFetchedImage* cachedImage = svgImageValue->cachedImage(loader); m_image = cachedImage; return cachedImage; @@ -164,7 +168,7 @@ StyleImage* CSSCursorImageValue::cachedOrPendingImage(float deviceScaleFactor) bool CSSCursorImageValue::isSVGCursor() const { if (m_imageValue->isImageValue()) { - RefPtr<CSSImageValue> imageValue = toCSSImageValue(m_imageValue.get()); + RefPtrWillBeRawPtr<CSSImageValue> imageValue = toCSSImageValue(m_imageValue.get()); KURL kurl(ParsedURLString, imageValue->url()); return kurl.hasFragmentIdentifier(); } @@ -180,14 +184,16 @@ String CSSCursorImageValue::cachedImageURL() void CSSCursorImageValue::clearImageResource() { - m_image = 0; + m_image = nullptr; m_accessedImage = false; } +#if !ENABLE(OILPAN) void CSSCursorImageValue::removeReferencedElement(SVGElement* element) { m_referencedElements.remove(element); } +#endif bool CSSCursorImageValue::equals(const CSSCursorImageValue& other) const { @@ -195,4 +201,10 @@ bool CSSCursorImageValue::equals(const CSSCursorImageValue& other) const && compareCSSValuePtr(m_imageValue, other.m_imageValue); } +void CSSCursorImageValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_imageValue); + CSSValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.h b/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.h index 17bba3188a1..abc54f73a3f 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSCursorImageValue.h @@ -32,9 +32,9 @@ class SVGElement; class CSSCursorImageValue : public CSSValue { public: - static PassRefPtr<CSSCursorImageValue> create(PassRefPtr<CSSValue> imageValue, bool hasHotSpot, const IntPoint& hotSpot) + static PassRefPtrWillBeRawPtr<CSSCursorImageValue> create(PassRefPtrWillBeRawPtr<CSSValue> imageValue, bool hasHotSpot, const IntPoint& hotSpot) { - return adoptRef(new CSSCursorImageValue(imageValue, hasHotSpot, hotSpot)); + return adoptRefWillBeNoop(new CSSCursorImageValue(imageValue, hasHotSpot, hotSpot)); } ~CSSCursorImageValue(); @@ -54,25 +54,31 @@ public: StyleImage* cachedImage(ResourceFetcher*, float deviceScaleFactor); StyleImage* cachedOrPendingImage(float deviceScaleFactor); +#if !ENABLE(OILPAN) void removeReferencedElement(SVGElement*); +#endif bool equals(const CSSCursorImageValue&) const; + void traceAfterDispatch(Visitor*); + private: - CSSCursorImageValue(PassRefPtr<CSSValue> imageValue, bool hasHotSpot, const IntPoint& hotSpot); + CSSCursorImageValue(PassRefPtrWillBeRawPtr<CSSValue> imageValue, bool hasHotSpot, const IntPoint& hotSpot); bool isSVGCursor() const; String cachedImageURL(); void clearImageResource(); - RefPtr<CSSValue> m_imageValue; + RefPtrWillBeMember<CSSValue> m_imageValue; bool m_hasHotSpot; IntPoint m_hotSpot; RefPtr<StyleImage> m_image; bool m_accessedImage; +#if !ENABLE(OILPAN) HashSet<SVGElement*> m_referencedElements; +#endif }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSCursorImageValue, isCursorImageValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSCustomFontData.h b/chromium/third_party/WebKit/Source/core/css/CSSCustomFontData.h index 9436927cabb..ec2bb6dc885 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSCustomFontData.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSCustomFontData.h @@ -28,32 +28,45 @@ namespace WebCore { class CSSCustomFontData FINAL : public CustomFontData { public: - static PassRefPtr<CSSCustomFontData> create(bool isLoadingFallback = false) + enum FallbackVisibility { InvisibleFallback, VisibleFallback }; + + static PassRefPtr<CSSCustomFontData> create(RemoteFontFaceSource* source, FallbackVisibility visibility) { - return adoptRef(new CSSCustomFontData(isLoadingFallback)); + return adoptRef(new CSSCustomFontData(source, visibility)); } virtual ~CSSCustomFontData() { } + virtual bool shouldSkipDrawing() const OVERRIDE + { + if (m_fontFaceSource) + m_fontFaceSource->paintRequested(); + return m_fallbackVisibility == InvisibleFallback && m_isUsed; + } + virtual void beginLoadIfNeeded() const OVERRIDE { - if (!m_isUsed && m_isLoadingFallback && m_fontFaceSource) { + if (!m_isUsed && m_fontFaceSource) { m_isUsed = true; m_fontFaceSource->beginLoadIfNeeded(); } } - virtual void setCSSFontFaceSource(CSSFontFaceSource* source) OVERRIDE { m_fontFaceSource = source; } - virtual void clearCSSFontFaceSource() OVERRIDE { m_fontFaceSource = 0; } + virtual bool isLoading() const OVERRIDE { return m_isUsed; } + virtual bool isLoadingFallback() const OVERRIDE { return true; } + virtual void clearFontFaceSource() OVERRIDE { m_fontFaceSource = 0; } private: - CSSCustomFontData(bool isLoadingFallback) - : CustomFontData(isLoadingFallback) - , m_fontFaceSource(0) + CSSCustomFontData(RemoteFontFaceSource* source, FallbackVisibility visibility) + : m_fontFaceSource(source) + , m_fallbackVisibility(visibility) + , m_isUsed(false) { } - CSSFontFaceSource* m_fontFaceSource; + RemoteFontFaceSource* m_fontFaceSource; + FallbackVisibility m_fallbackVisibility; + mutable bool m_isUsed; }; } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp b/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp index cdd794828a7..1137f9b7ad9 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.cpp @@ -29,33 +29,31 @@ #include "config.h" #include "core/css/CSSDefaultStyleSheets.h" -#include "UserAgentStyleSheets.h" +#include "core/MathMLNames.h" +#include "core/UserAgentStyleSheets.h" #include "core/css/MediaQueryEvaluator.h" #include "core/css/RuleSet.h" #include "core/css/StyleSheetContents.h" #include "core/dom/FullscreenElementStack.h" #include "core/html/HTMLAnchorElement.h" #include "core/html/HTMLHtmlElement.h" -#include "core/html/HTMLVideoElement.h" #include "core/rendering/RenderTheme.h" +#include "wtf/LeakAnnotations.h" namespace WebCore { using namespace HTMLNames; -RuleSet* CSSDefaultStyleSheets::defaultStyle; -RuleSet* CSSDefaultStyleSheets::defaultViewportStyle; -RuleSet* CSSDefaultStyleSheets::defaultQuirksStyle; -RuleSet* CSSDefaultStyleSheets::defaultPrintStyle; -RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle; -RuleSet* CSSDefaultStyleSheets::defaultXHTMLMobileProfileStyle; - -StyleSheetContents* CSSDefaultStyleSheets::defaultStyleSheet; -StyleSheetContents* CSSDefaultStyleSheets::viewportStyleSheet; -StyleSheetContents* CSSDefaultStyleSheets::quirksStyleSheet; -StyleSheetContents* CSSDefaultStyleSheets::svgStyleSheet; -StyleSheetContents* CSSDefaultStyleSheets::mediaControlsStyleSheet; -StyleSheetContents* CSSDefaultStyleSheets::fullscreenStyleSheet; +CSSDefaultStyleSheets& CSSDefaultStyleSheets::instance() +{ +#if ENABLE(OILPAN) + DEFINE_STATIC_LOCAL(Persistent<CSSDefaultStyleSheets>, cssDefaultStyleSheets, (new CSSDefaultStyleSheets())); + return *cssDefaultStyleSheets; +#else + DEFINE_STATIC_LOCAL(CSSDefaultStyleSheets, cssDefaultStyleSheets, ()); + return cssDefaultStyleSheets; +#endif +} static const MediaQueryEvaluator& screenEval() { @@ -69,100 +67,153 @@ static const MediaQueryEvaluator& printEval() return staticPrintEval; } -static StyleSheetContents* parseUASheet(const String& str) +static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const String& str) { - StyleSheetContents* sheet = StyleSheetContents::create(CSSParserContext(UASheetMode)).leakRef(); // leak the sheet on purpose + RefPtrWillBeRawPtr<StyleSheetContents> sheet = StyleSheetContents::create(CSSParserContext(UASheetMode, 0)); sheet->parseString(str); - return sheet; + // User Agent stylesheets are parsed once for the lifetime of the renderer + // and are intentionally leaked. + WTF_ANNOTATE_LEAKING_OBJECT_PTR(sheet.get()); + return sheet.release(); } -static StyleSheetContents* parseUASheet(const char* characters, unsigned size) +static PassRefPtrWillBeRawPtr<StyleSheetContents> parseUASheet(const char* characters, unsigned size) { return parseUASheet(String(characters, size)); } -void CSSDefaultStyleSheets::loadDefaultStylesheetIfNecessary() +CSSDefaultStyleSheets::CSSDefaultStyleSheets() + : m_defaultStyle(nullptr) + , m_defaultViewportStyle(nullptr) + , m_defaultQuirksStyle(nullptr) + , m_defaultPrintStyle(nullptr) + , m_defaultViewSourceStyle(nullptr) + , m_defaultXHTMLMobileProfileStyle(nullptr) + , m_defaultTransitionStyle(nullptr) + , m_defaultStyleSheet(nullptr) + , m_viewportStyleSheet(nullptr) + , m_quirksStyleSheet(nullptr) + , m_svgStyleSheet(nullptr) + , m_mathmlStyleSheet(nullptr) + , m_mediaControlsStyleSheet(nullptr) + , m_fullscreenStyleSheet(nullptr) { - if (!defaultStyle) - loadDefaultStyle(); -} - -void CSSDefaultStyleSheets::loadDefaultStyle() -{ - ASSERT(!defaultStyle); - defaultStyle = RuleSet::create().leakPtr(); - defaultViewportStyle = RuleSet::create().leakPtr(); - defaultPrintStyle = RuleSet::create().leakPtr(); - defaultQuirksStyle = RuleSet::create().leakPtr(); + m_defaultStyle = RuleSet::create(); + m_defaultViewportStyle = RuleSet::create(); + m_defaultPrintStyle = RuleSet::create(); + m_defaultQuirksStyle = RuleSet::create(); // Strict-mode rules. String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::theme().extraDefaultStyleSheet(); - defaultStyleSheet = parseUASheet(defaultRules); - defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval()); + m_defaultStyleSheet = parseUASheet(defaultRules); + m_defaultStyle->addRulesFromSheet(defaultStyleSheet(), screenEval()); #if OS(ANDROID) String viewportRules(viewportAndroidUserAgentStyleSheet, sizeof(viewportAndroidUserAgentStyleSheet)); #else String viewportRules; #endif - viewportStyleSheet = parseUASheet(viewportRules); - defaultViewportStyle->addRulesFromSheet(viewportStyleSheet, screenEval()); - defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval()); + m_viewportStyleSheet = parseUASheet(viewportRules); + m_defaultViewportStyle->addRulesFromSheet(viewportStyleSheet(), screenEval()); + m_defaultPrintStyle->addRulesFromSheet(defaultStyleSheet(), printEval()); // Quirks-mode rules. String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::theme().extraQuirksStyleSheet(); - quirksStyleSheet = parseUASheet(quirksRules); - defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval()); + m_quirksStyleSheet = parseUASheet(quirksRules); + m_defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet(), screenEval()); +} + +RuleSet* CSSDefaultStyleSheets::defaultViewSourceStyle() +{ + if (!m_defaultViewSourceStyle) { + m_defaultViewSourceStyle = RuleSet::create(); + // Loaded stylesheet is leaked on purpose. + RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)); + m_defaultViewSourceStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval()); + } + return m_defaultViewSourceStyle.get(); } -RuleSet* CSSDefaultStyleSheets::viewSourceStyle() +RuleSet* CSSDefaultStyleSheets::defaultTransitionStyle() { - if (!defaultViewSourceStyle) { - defaultViewSourceStyle = RuleSet::create().leakPtr(); - defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval()); + if (!m_defaultTransitionStyle) { + m_defaultTransitionStyle = RuleSet::create(); + // Loaded stylesheet is leaked on purpose. + RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(navigationTransitionsUserAgentStyleSheet, sizeof(navigationTransitionsUserAgentStyleSheet)); + m_defaultTransitionStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval()); } - return defaultViewSourceStyle; + return m_defaultTransitionStyle.get(); } -RuleSet* CSSDefaultStyleSheets::xhtmlMobileProfileStyle() +RuleSet* CSSDefaultStyleSheets::defaultXHTMLMobileProfileStyle() { - if (!defaultXHTMLMobileProfileStyle) { - defaultXHTMLMobileProfileStyle = RuleSet::create().leakPtr(); - defaultXHTMLMobileProfileStyle->addRulesFromSheet(parseUASheet(xhtmlmpUserAgentStyleSheet, sizeof(xhtmlmpUserAgentStyleSheet)), screenEval()); + if (!m_defaultXHTMLMobileProfileStyle) { + m_defaultXHTMLMobileProfileStyle = RuleSet::create(); + // Loaded stylesheet is leaked on purpose. + RefPtrWillBeRawPtr<StyleSheetContents> stylesheet = parseUASheet(xhtmlmpUserAgentStyleSheet, sizeof(xhtmlmpUserAgentStyleSheet)); + m_defaultXHTMLMobileProfileStyle->addRulesFromSheet(stylesheet.release().leakRef(), screenEval()); } - return defaultXHTMLMobileProfileStyle; + return m_defaultXHTMLMobileProfileStyle.get(); } void CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(Element* element, bool& changedDefaultStyle) { // FIXME: We should assert that the sheet only styles SVG elements. - if (element->isSVGElement() && !svgStyleSheet) { - svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); - defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval()); - defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval()); + if (element->isSVGElement() && !m_svgStyleSheet) { + m_svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet)); + m_defaultStyle->addRulesFromSheet(svgStyleSheet(), screenEval()); + m_defaultPrintStyle->addRulesFromSheet(svgStyleSheet(), printEval()); + changedDefaultStyle = true; + } + + // FIXME: We should assert that the sheet only styles MathML elements. + if (element->namespaceURI() == MathMLNames::mathmlNamespaceURI + && !m_mathmlStyleSheet) { + m_mathmlStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, + sizeof(mathmlUserAgentStyleSheet)); + m_defaultStyle->addRulesFromSheet(mathmlStyleSheet(), screenEval()); + m_defaultPrintStyle->addRulesFromSheet(mathmlStyleSheet(), printEval()); changedDefaultStyle = true; } // FIXME: We should assert that this sheet only contains rules for <video> and <audio>. - if (!mediaControlsStyleSheet && (isHTMLVideoElement(element) || element->hasTagName(audioTag))) { + if (!m_mediaControlsStyleSheet && (isHTMLVideoElement(*element) || isHTMLAudioElement(*element))) { String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::theme().extraMediaControlsStyleSheet(); - mediaControlsStyleSheet = parseUASheet(mediaRules); - defaultStyle->addRulesFromSheet(mediaControlsStyleSheet, screenEval()); - defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet, printEval()); + m_mediaControlsStyleSheet = parseUASheet(mediaRules); + m_defaultStyle->addRulesFromSheet(mediaControlsStyleSheet(), screenEval()); + m_defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet(), printEval()); changedDefaultStyle = true; } // FIXME: This only works because we Force recalc the entire document so the new sheet // is loaded for <html> and the correct styles apply to everyone. - if (!fullscreenStyleSheet && FullscreenElementStack::isFullScreen(&element->document())) { + if (!m_fullscreenStyleSheet && FullscreenElementStack::isFullScreen(element->document())) { String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::theme().extraFullScreenStyleSheet(); - fullscreenStyleSheet = parseUASheet(fullscreenRules); - defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval()); - defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval()); + m_fullscreenStyleSheet = parseUASheet(fullscreenRules); + m_defaultStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval()); + m_defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet(), screenEval()); changedDefaultStyle = true; } - ASSERT(defaultStyle->features().idsInRules.isEmpty()); - ASSERT(defaultStyle->features().siblingRules.isEmpty()); + ASSERT(!m_defaultStyle->features().hasIdsInSelectors()); + ASSERT(m_defaultStyle->features().siblingRules.isEmpty()); +} + +void CSSDefaultStyleSheets::trace(Visitor* visitor) +{ + visitor->trace(m_defaultStyle); + visitor->trace(m_defaultViewportStyle); + visitor->trace(m_defaultQuirksStyle); + visitor->trace(m_defaultPrintStyle); + visitor->trace(m_defaultViewSourceStyle); + visitor->trace(m_defaultXHTMLMobileProfileStyle); + visitor->trace(m_defaultTransitionStyle); + visitor->trace(m_defaultStyleSheet); + visitor->trace(m_viewportStyleSheet); + visitor->trace(m_quirksStyleSheet); + visitor->trace(m_svgStyleSheet); + visitor->trace(m_mathmlStyleSheet); + visitor->trace(m_mediaControlsStyleSheet); + visitor->trace(m_fullscreenStyleSheet); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h b/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h index c85fd226340..0efccd191ec 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSDefaultStyleSheets.h @@ -23,39 +23,58 @@ #ifndef CSSDefaultStyleSheets_h #define CSSDefaultStyleSheets_h +#include "platform/heap/Handle.h" + namespace WebCore { class Element; class RuleSet; class StyleSheetContents; -class CSSDefaultStyleSheets { +class CSSDefaultStyleSheets : public NoBaseWillBeGarbageCollected<CSSDefaultStyleSheets> { public: - static RuleSet* defaultStyle; - static RuleSet* defaultViewportStyle; - static RuleSet* defaultQuirksStyle; - static RuleSet* defaultPrintStyle; - static RuleSet* defaultViewSourceStyle; - static RuleSet* defaultXHTMLMobileProfileStyle; - - static StyleSheetContents* defaultStyleSheet; - static StyleSheetContents* viewportStyleSheet; - static StyleSheetContents* quirksStyleSheet; - static StyleSheetContents* svgStyleSheet; - static StyleSheetContents* mediaControlsStyleSheet; - static StyleSheetContents* fullscreenStyleSheet; - - static void ensureDefaultStyleSheetsForElement(Element*, bool& changedDefaultStyle); - // FIXME: defaultStyleSheet should have an accessor which incorporates this branch: - static void loadDefaultStylesheetIfNecessary(); - - static RuleSet* viewSourceStyle(); + static CSSDefaultStyleSheets& instance(); + + void ensureDefaultStyleSheetsForElement(Element*, bool& changedDefaultStyle); + + RuleSet* defaultStyle() { return m_defaultStyle.get(); } + RuleSet* defaultViewportStyle() { return m_defaultViewportStyle.get(); } + RuleSet* defaultQuirksStyle() { return m_defaultQuirksStyle.get(); } + RuleSet* defaultPrintStyle() { return m_defaultPrintStyle.get(); } + RuleSet* defaultViewSourceStyle(); + RuleSet* defaultTransitionStyle(); // FIXME: Remove WAP support. - static RuleSet* xhtmlMobileProfileStyle(); + RuleSet* defaultXHTMLMobileProfileStyle(); + + StyleSheetContents* defaultStyleSheet() { return m_defaultStyleSheet.get(); } + StyleSheetContents* viewportStyleSheet() { return m_viewportStyleSheet.get(); } + StyleSheetContents* quirksStyleSheet() { return m_quirksStyleSheet.get(); } + StyleSheetContents* svgStyleSheet() { return m_svgStyleSheet.get(); } + StyleSheetContents* mathmlStyleSheet() { return m_mathmlStyleSheet.get(); } + StyleSheetContents* mediaControlsStyleSheet() { return m_mediaControlsStyleSheet.get(); } + StyleSheetContents* fullscreenStyleSheet() { return m_fullscreenStyleSheet.get(); } + + void trace(Visitor*); private: - static void loadDefaultStyle(); + CSSDefaultStyleSheets(); + + OwnPtrWillBeMember<RuleSet> m_defaultStyle; + OwnPtrWillBeMember<RuleSet> m_defaultViewportStyle; + OwnPtrWillBeMember<RuleSet> m_defaultQuirksStyle; + OwnPtrWillBeMember<RuleSet> m_defaultPrintStyle; + OwnPtrWillBeMember<RuleSet> m_defaultViewSourceStyle; + OwnPtrWillBeMember<RuleSet> m_defaultXHTMLMobileProfileStyle; + OwnPtrWillBeMember<RuleSet> m_defaultTransitionStyle; + + RefPtrWillBeMember<StyleSheetContents> m_defaultStyleSheet; + RefPtrWillBeMember<StyleSheetContents> m_viewportStyleSheet; + RefPtrWillBeMember<StyleSheetContents> m_quirksStyleSheet; + RefPtrWillBeMember<StyleSheetContents> m_svgStyleSheet; + RefPtrWillBeMember<StyleSheetContents> m_mathmlStyleSheet; + RefPtrWillBeMember<StyleSheetContents> m_mediaControlsStyleSheet; + RefPtrWillBeMember<StyleSheetContents> m_fullscreenStyleSheet; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.cpp index dc44874be19..90b3390fcad 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.cpp @@ -45,8 +45,10 @@ CSSFilterRule::CSSFilterRule(StyleRuleFilter* filterRule, CSSStyleSheet* parent) CSSFilterRule::~CSSFilterRule() { +#if !ENABLE(OILPAN) if (m_propertiesCSSOMWrapper) m_propertiesCSSOMWrapper->clearParentRule(); +#endif } CSSStyleDeclaration* CSSFilterRule::style() const @@ -65,7 +67,7 @@ String CSSFilterRule::cssText() const result.append(filterName); result.appendLiteral(" { "); - String descs = m_filterRule->properties()->asText(); + String descs = m_filterRule->properties().asText(); result.append(descs); if (!descs.isEmpty()) result.append(' '); @@ -82,5 +84,12 @@ void CSSFilterRule::reattach(StyleRuleBase* rule) m_propertiesCSSOMWrapper->reattach(m_filterRule->mutableProperties()); } +void CSSFilterRule::trace(Visitor* visitor) +{ + visitor->trace(m_filterRule); + visitor->trace(m_propertiesCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.h b/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.h index 9bb1b192c2a..bd3be8dfe3b 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFilterRule.h @@ -31,6 +31,7 @@ #define CSSFilterRule_h #include "core/css/CSSRule.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -38,9 +39,12 @@ class CSSStyleDeclaration; class StyleRuleFilter; class StyleRuleCSSStyleDeclaration; -class CSSFilterRule : public CSSRule { +class CSSFilterRule FINAL : public CSSRule { public: - static PassRefPtr<CSSFilterRule> create(StyleRuleFilter* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSFilterRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSFilterRule> create(StyleRuleFilter* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSFilterRule(rule, sheet)); + } virtual ~CSSFilterRule(); @@ -50,11 +54,13 @@ public: CSSStyleDeclaration* style() const; + virtual void trace(Visitor*) OVERRIDE; + private: CSSFilterRule(StyleRuleFilter*, CSSStyleSheet* parent); - RefPtr<StyleRuleFilter> m_filterRule; - mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; + RefPtrWillBeMember<StyleRuleFilter> m_filterRule; + mutable RefPtrWillBeMember<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSFilterRule, WEBKIT_FILTER_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.cpp index 75567a7eeb8..3f71adecdcb 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.cpp @@ -26,66 +26,60 @@ #include "config.h" #include "core/css/CSSFilterValue.h" -#include "wtf/text/WTFString.h" +#include "wtf/text/StringBuilder.h" namespace WebCore { CSSFilterValue::CSSFilterValue(FilterOperationType operationType) - : CSSValueList(CSSFilterClass, typeUsesSpaceSeparator(operationType) ? SpaceSeparator : CommaSeparator) + : CSSValueList(CSSFilterClass, CommaSeparator) , m_type(operationType) { } -bool CSSFilterValue::typeUsesSpaceSeparator(FilterOperationType operationType) -{ - return operationType != CustomFilterOperation; -} - String CSSFilterValue::customCSSText() const { - String result; + StringBuilder result; switch (m_type) { case ReferenceFilterOperation: - result = "url("; + result.append("url("); break; case GrayscaleFilterOperation: - result = "grayscale("; + result.append("grayscale("); break; case SepiaFilterOperation: - result = "sepia("; + result.append("sepia("); break; case SaturateFilterOperation: - result = "saturate("; + result.append("saturate("); break; case HueRotateFilterOperation: - result = "hue-rotate("; + result.append("hue-rotate("); break; case InvertFilterOperation: - result = "invert("; + result.append("invert("); break; case OpacityFilterOperation: - result = "opacity("; + result.append("opacity("); break; case BrightnessFilterOperation: - result = "brightness("; + result.append("brightness("); break; case ContrastFilterOperation: - result = "contrast("; + result.append("contrast("); break; case BlurFilterOperation: - result = "blur("; + result.append("blur("); break; case DropShadowFilterOperation: - result = "drop-shadow("; - break; - case CustomFilterOperation: - result = "custom("; + result.append("drop-shadow("); break; default: break; } - return result + CSSValueList::customCSSText() + ")"; + result.append(CSSValueList::customCSSText()); + result.append(')'); + return result.toString(); } CSSFilterValue::CSSFilterValue(const CSSFilterValue& cloneFrom) @@ -94,9 +88,9 @@ CSSFilterValue::CSSFilterValue(const CSSFilterValue& cloneFrom) { } -PassRefPtr<CSSFilterValue> CSSFilterValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSFilterValue> CSSFilterValue::cloneForCSSOM() const { - return adoptRef(new CSSFilterValue(*this)); + return adoptRefWillBeNoop(new CSSFilterValue(*this)); } bool CSSFilterValue::equals(const CSSFilterValue& other) const diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.h b/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.h index 7a2f80c1a4c..4304e144cd4 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFilterValue.h @@ -47,24 +47,25 @@ public: ContrastFilterOperation, BlurFilterOperation, DropShadowFilterOperation, - CustomFilterOperation }; static bool typeUsesSpaceSeparator(FilterOperationType); - static PassRefPtr<CSSFilterValue> create(FilterOperationType type) + static PassRefPtrWillBeRawPtr<CSSFilterValue> create(FilterOperationType type) { - return adoptRef(new CSSFilterValue(type)); + return adoptRefWillBeNoop(new CSSFilterValue(type)); } String customCSSText() const; FilterOperationType operationType() const { return m_type; } - PassRefPtr<CSSFilterValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSFilterValue> cloneForCSSOM() const; bool equals(const CSSFilterValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValueList::traceAfterDispatch(visitor); } + private: explicit CSSFilterValue(FilterOperationType); explicit CSSFilterValue(const CSSFilterValue& cloneFrom); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFace.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontFace.cpp index c21c9125afb..9dddf489a46 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFace.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFace.cpp @@ -26,60 +26,19 @@ #include "config.h" #include "core/css/CSSFontFace.h" +#include "core/css/CSSFontFaceSource.h" #include "core/css/CSSFontSelector.h" #include "core/css/CSSSegmentedFontFace.h" #include "core/css/FontFaceSet.h" +#include "core/css/RemoteFontFaceSource.h" #include "core/dom/Document.h" #include "core/frame/UseCounter.h" +#include "platform/fonts/FontDescription.h" #include "platform/fonts/SimpleFontData.h" namespace WebCore { -CSSFontFace::~CSSFontFace() -{ - m_fontFace->cssFontFaceDestroyed(); -} - -PassRefPtr<CSSFontFace> CSSFontFace::createFromStyleRule(Document* document, const StyleRuleFontFace* fontFaceRule) -{ - RefPtr<FontFace> fontFace = FontFace::create(fontFaceRule); - if (!fontFace || fontFace->family().isEmpty()) - return 0; - - unsigned traitsMask = fontFace->traitsMask(); - if (!traitsMask) - return 0; - - // FIXME: Plumbing back into createCSSFontFace seems odd. - // Maybe move FontFace::createCSSFontFace logic here? - RefPtr<CSSFontFace> cssFontFace = fontFace->createCSSFontFace(document); - if (!cssFontFace || !cssFontFace->isValid()) - return 0; - - return cssFontFace; -} - -bool CSSFontFace::isLoaded() const -{ - size_t size = m_sources.size(); - for (size_t i = 0; i < size; i++) { - if (!m_sources[i]->isLoaded()) - return false; - } - return true; -} - -bool CSSFontFace::isValid() const -{ - size_t size = m_sources.size(); - for (size_t i = 0; i < size; i++) { - if (m_sources[i]->isValid()) - return true; - } - return false; -} - -void CSSFontFace::addSource(PassOwnPtr<CSSFontFaceSource> source) +void CSSFontFace::addSource(PassOwnPtrWillBeRawPtr<CSSFontFaceSource> source) { source->setFontFace(this); m_sources.append(source); @@ -91,99 +50,112 @@ void CSSFontFace::setSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace) m_segmentedFontFace = segmentedFontFace; } -void CSSFontFace::beginLoadIfNeeded(CSSFontFaceSource* source) +void CSSFontFace::didBeginLoad() { - if (!m_segmentedFontFace) - return; - - if (source->resource() && source->resource()->stillNeedsLoad()) { - CSSFontSelector* fontSelector = m_segmentedFontFace->fontSelector(); - fontSelector->beginLoadingFontSoon(source->resource()); - } - if (loadStatus() == FontFace::Unloaded) setLoadStatus(FontFace::Loading); } -void CSSFontFace::fontLoaded(CSSFontFaceSource* source) +void CSSFontFace::fontLoaded(RemoteFontFaceSource* source) { - if (source != m_activeSource) + if (!isValid() || source != m_sources.first()) return; - m_activeSource = 0; - // FIXME: Can we assert that m_segmentedFontFace is non-null? That may - // require stopping in-progress font loading when the last - // CSSSegmentedFontFace is removed. - if (!m_segmentedFontFace) - return; - - CSSFontSelector* fontSelector = m_segmentedFontFace->fontSelector(); - fontSelector->fontLoaded(); - - if (fontSelector->document() && loadStatus() == FontFace::Loading) { + if (loadStatus() == FontFace::Loading) { if (source->ensureFontData()) { setLoadStatus(FontFace::Loaded); - if (source->isSVGFontFaceSource()) - UseCounter::count(*fontSelector->document(), UseCounter::SVGFontInCSS); +#if ENABLE(SVG_FONTS) + Document* document = m_segmentedFontFace ? m_segmentedFontFace->fontSelector()->document() : 0; + if (document && source->isSVGFontFaceSource()) + UseCounter::count(*document, UseCounter::SVGFontInCSS); +#endif + } else { + m_sources.removeFirst(); + load(); } - else if (!isValid()) - setLoadStatus(FontFace::Error); } - m_segmentedFontFace->fontLoaded(this); + if (m_segmentedFontFace) + m_segmentedFontFace->fontLoaded(this); +} + +void CSSFontFace::fontLoadWaitLimitExceeded(RemoteFontFaceSource* source) +{ + if (!isValid() || source != m_sources.first()) + return; + if (m_segmentedFontFace) + m_segmentedFontFace->fontLoadWaitLimitExceeded(this); } PassRefPtr<SimpleFontData> CSSFontFace::getFontData(const FontDescription& fontDescription) { - m_activeSource = 0; if (!isValid()) - return 0; + return nullptr; - size_t size = m_sources.size(); - for (size_t i = 0; i < size; ++i) { - if (RefPtr<SimpleFontData> result = m_sources[i]->getFontData(fontDescription)) { - m_activeSource = m_sources[i].get(); - if (loadStatus() == FontFace::Unloaded && (m_sources[i]->isLoading() || m_sources[i]->isLoaded())) + while (!m_sources.isEmpty()) { + OwnPtrWillBeMember<CSSFontFaceSource>& source = m_sources.first(); + if (RefPtr<SimpleFontData> result = source->getFontData(fontDescription)) { + if (loadStatus() == FontFace::Unloaded && (source->isLoading() || source->isLoaded())) setLoadStatus(FontFace::Loading); - if (loadStatus() == FontFace::Loading && m_sources[i]->isLoaded()) + if (loadStatus() == FontFace::Loading && source->isLoaded()) setLoadStatus(FontFace::Loaded); return result.release(); } + m_sources.removeFirst(); } if (loadStatus() == FontFace::Unloaded) setLoadStatus(FontFace::Loading); if (loadStatus() == FontFace::Loading) setLoadStatus(FontFace::Error); - return 0; + return nullptr; } -void CSSFontFace::willUseFontData(const FontDescription& fontDescription) +bool CSSFontFace::maybeScheduleFontLoad(const FontDescription& fontDescription, UChar32 character) { - if (loadStatus() != FontFace::Unloaded || m_activeSource) - return; - - // Kicks off font load here only if the @font-face has no unicode-range. - // @font-faces with unicode-range will be loaded when a GlyphPage for the - // font is created. - // FIXME: Pass around the text to render from RenderText, and kick download - // if m_ranges intersects with the text. Make sure this does not cause - // performance regression. - if (!m_ranges.isEntireRange()) - return; + if (m_ranges.contains(character)) { + if (loadStatus() == FontFace::Unloaded) + load(fontDescription); + return true; + } + return false; +} - ASSERT(m_segmentedFontFace); +void CSSFontFace::load() +{ + FontDescription fontDescription; + FontFamily fontFamily; + fontFamily.setFamily(m_fontFace->family()); + fontDescription.setFamily(fontFamily); + fontDescription.setTraits(m_fontFace->traits()); + load(fontDescription); +} - size_t size = m_sources.size(); - for (size_t i = 0; i < size; ++i) { - if (!m_sources[i]->isValid() || (m_sources[i]->isLocal() && !m_sources[i]->isLocalFontAvailable(fontDescription))) - continue; - if (!m_sources[i]->isLocal() && !m_sources[i]->isLoaded()) { - m_activeSource = m_sources[i].get(); - beginLoadIfNeeded(m_activeSource); +void CSSFontFace::load(const FontDescription& fontDescription) +{ + if (loadStatus() == FontFace::Unloaded) + setLoadStatus(FontFace::Loading); + ASSERT(loadStatus() == FontFace::Loading); + + while (!m_sources.isEmpty()) { + OwnPtrWillBeMember<CSSFontFaceSource>& source = m_sources.first(); + if (source->isValid()) { + if (source->isLocal()) { + if (source->isLocalFontAvailable(fontDescription)) { + setLoadStatus(FontFace::Loaded); + return; + } + } else { + if (!source->isLoaded()) + source->beginLoadIfNeeded(); + else + setLoadStatus(FontFace::Loaded); + return; + } } - break; + m_sources.removeFirst(); } + setLoadStatus(FontFace::Error); } void CSSFontFace::setLoadStatus(FontFace::LoadStatus newStatus) @@ -199,38 +171,76 @@ void CSSFontFace::setLoadStatus(FontFace::LoadStatus newStatus) switch (newStatus) { case FontFace::Loading: - FontFaceSet::from(document)->beginFontLoading(m_fontFace.get()); + FontFaceSet::from(*document)->beginFontLoading(m_fontFace); break; case FontFace::Loaded: - FontFaceSet::from(document)->fontLoaded(m_fontFace.get()); + FontFaceSet::from(*document)->fontLoaded(m_fontFace); break; case FontFace::Error: - FontFaceSet::from(document)->loadError(m_fontFace.get()); + FontFaceSet::from(*document)->loadError(m_fontFace); break; default: break; } } +CSSFontFace::UnicodeRangeSet::UnicodeRangeSet(const Vector<UnicodeRange>& ranges) + : m_ranges(ranges) +{ + if (m_ranges.isEmpty()) + return; + + std::sort(m_ranges.begin(), m_ranges.end()); + + // Unify overlapping ranges. + UChar32 from = m_ranges[0].from(); + UChar32 to = m_ranges[0].to(); + size_t targetIndex = 0; + for (size_t i = 1; i < m_ranges.size(); i++) { + if (to + 1 >= m_ranges[i].from()) { + to = std::max(to, m_ranges[i].to()); + } else { + m_ranges[targetIndex++] = UnicodeRange(from, to); + from = m_ranges[i].from(); + to = m_ranges[i].to(); + } + } + m_ranges[targetIndex++] = UnicodeRange(from, to); + m_ranges.shrink(targetIndex); +} + +bool CSSFontFace::UnicodeRangeSet::contains(UChar32 c) const +{ + if (isEntireRange()) + return true; + Vector<UnicodeRange>::const_iterator it = std::lower_bound(m_ranges.begin(), m_ranges.end(), c); + return it != m_ranges.end() && it->contains(c); +} + bool CSSFontFace::UnicodeRangeSet::intersectsWith(const String& text) const { if (text.isEmpty()) return false; if (isEntireRange()) return true; + if (text.is8Bit() && m_ranges[0].from() >= 0x100) + return false; - // FIXME: This takes O(text.length() * m_ranges.size()) time. It would be - // better to make m_ranges sorted and use binary search. unsigned index = 0; while (index < text.length()) { UChar32 c = text.characterStartingAt(index); index += U16_LENGTH(c); - for (unsigned i = 0; i < m_ranges.size(); i++) { - if (m_ranges[i].contains(c)) - return true; - } + if (contains(c)) + return true; } return false; } +void CSSFontFace::trace(Visitor* visitor) +{ + visitor->trace(m_segmentedFontFace); + visitor->trace(m_sources); + visitor->trace(m_fontFace); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFace.h b/chromium/third_party/WebKit/Source/core/css/CSSFontFace.h index e4ad5f048a1..96ddbf52601 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFace.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFace.h @@ -27,44 +27,49 @@ #define CSSFontFace_h #include "core/css/CSSFontFaceSource.h" +#include "core/css/CSSSegmentedFontFace.h" #include "core/css/FontFace.h" +#include "wtf/Deque.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" #include "wtf/Vector.h" namespace WebCore { -class CSSSegmentedFontFace; +class CSSFontSelector; class Document; class FontDescription; +class RemoteFontFaceSource; class SimpleFontData; class StyleRuleFontFace; -// FIXME: Can this be a subclass of FontFace? -class CSSFontFace : public RefCounted<CSSFontFace> { +class CSSFontFace FINAL : public NoBaseWillBeGarbageCollectedFinalized<CSSFontFace> { public: - static PassRefPtr<CSSFontFace> create(PassRefPtr<FontFace> fontFace) { return adoptRef(new CSSFontFace(fontFace)); } - static PassRefPtr<CSSFontFace> createFromStyleRule(Document*, const StyleRuleFontFace*); - + struct UnicodeRange; class UnicodeRangeSet; - ~CSSFontFace(); + CSSFontFace(FontFace* fontFace, Vector<UnicodeRange>& ranges) + : m_ranges(ranges) + , m_segmentedFontFace(nullptr) + , m_fontFace(fontFace) + { + ASSERT(m_fontFace); + } - FontFace* fontFace() const { return m_fontFace.get(); } + FontFace* fontFace() const { return m_fontFace; } UnicodeRangeSet& ranges() { return m_ranges; } void setSegmentedFontFace(CSSSegmentedFontFace*); - void clearSegmentedFontFace() { m_segmentedFontFace = 0; } + void clearSegmentedFontFace() { m_segmentedFontFace = nullptr; } - bool isLoaded() const; - bool isValid() const; + bool isValid() const { return !m_sources.isEmpty(); } - void addSource(PassOwnPtr<CSSFontFaceSource>); + void addSource(PassOwnPtrWillBeRawPtr<CSSFontFaceSource>); - void beginLoadIfNeeded(CSSFontFaceSource*); - void fontLoaded(CSSFontFaceSource*); + void didBeginLoad(); + void fontLoaded(RemoteFontFaceSource*); + void fontLoadWaitLimitExceeded(RemoteFontFaceSource*); PassRefPtr<SimpleFontData> getFontData(const FontDescription&); @@ -78,6 +83,8 @@ public: UChar32 from() const { return m_from; } UChar32 to() const { return m_to; } bool contains(UChar32 c) const { return m_from <= c && c <= m_to; } + bool operator<(const UnicodeRange& other) const { return m_from < other.m_from; } + bool operator<(UChar32 c) const { return m_to < c; } private: UChar32 m_from; @@ -86,7 +93,8 @@ public: class UnicodeRangeSet { public: - void add(UChar32 from, UChar32 to) { m_ranges.append(UnicodeRange(from, to)); } + explicit UnicodeRangeSet(const Vector<UnicodeRange>&); + bool contains(UChar32) const; bool intersectsWith(const String&) const; bool isEntireRange() const { return m_ranges.isEmpty(); } size_t size() const { return m_ranges.size(); } @@ -96,23 +104,21 @@ public: }; FontFace::LoadStatus loadStatus() const { return m_fontFace->loadStatus(); } - void willUseFontData(const FontDescription&); + bool maybeScheduleFontLoad(const FontDescription&, UChar32); + void load(); + void load(const FontDescription&); + + bool hadBlankText() { return isValid() && m_sources.first()->hadBlankText(); } + + void trace(Visitor*); private: - CSSFontFace(PassRefPtr<FontFace> fontFace) - : m_segmentedFontFace(0) - , m_activeSource(0) - , m_fontFace(fontFace) - { - ASSERT(m_fontFace); - } void setLoadStatus(FontFace::LoadStatus); UnicodeRangeSet m_ranges; - CSSSegmentedFontFace* m_segmentedFontFace; - Vector<OwnPtr<CSSFontFaceSource> > m_sources; - CSSFontFaceSource* m_activeSource; - RefPtr<FontFace> m_fontFace; + RawPtrWillBeMember<CSSSegmentedFontFace> m_segmentedFontFace; + WillBeHeapDeque<OwnPtrWillBeMember<CSSFontFaceSource> > m_sources; + RawPtrWillBeMember<FontFace> m_fontFace; }; } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.cpp index 95aa3b27328..5d0d06b1d96 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.cpp @@ -61,4 +61,10 @@ const AtomicString& CSSFontFaceLoadEvent::interfaceName() const return EventNames::CSSFontFaceLoadEvent; } +void CSSFontFaceLoadEvent::trace(Visitor* visitor) +{ + visitor->trace(m_fontfaces); + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.h b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.h index e77ca32e86b..8597efc2b24 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceLoadEvent.h @@ -34,7 +34,6 @@ #include "core/css/FontFace.h" #include "core/dom/DOMError.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -44,28 +43,30 @@ struct CSSFontFaceLoadEventInit : public EventInit { FontFaceArray fontfaces; }; -class CSSFontFaceLoadEvent : public Event { +class CSSFontFaceLoadEvent FINAL : public Event { public: - static PassRefPtr<CSSFontFaceLoadEvent> create() + static PassRefPtrWillBeRawPtr<CSSFontFaceLoadEvent> create() { - return adoptRef<CSSFontFaceLoadEvent>(new CSSFontFaceLoadEvent()); + return adoptRefWillBeNoop(new CSSFontFaceLoadEvent()); } - static PassRefPtr<CSSFontFaceLoadEvent> create(const AtomicString& type, const CSSFontFaceLoadEventInit& initializer) + static PassRefPtrWillBeRawPtr<CSSFontFaceLoadEvent> create(const AtomicString& type, const CSSFontFaceLoadEventInit& initializer) { - return adoptRef<CSSFontFaceLoadEvent>(new CSSFontFaceLoadEvent(type, initializer)); + return adoptRefWillBeNoop(new CSSFontFaceLoadEvent(type, initializer)); } - static PassRefPtr<CSSFontFaceLoadEvent> createForFontFaces(const AtomicString& type, const FontFaceArray& fontfaces = FontFaceArray()) + static PassRefPtrWillBeRawPtr<CSSFontFaceLoadEvent> createForFontFaces(const AtomicString& type, const FontFaceArray& fontfaces = FontFaceArray()) { - return adoptRef<CSSFontFaceLoadEvent>(new CSSFontFaceLoadEvent(type, fontfaces)); + return adoptRefWillBeNoop(new CSSFontFaceLoadEvent(type, fontfaces)); } virtual ~CSSFontFaceLoadEvent(); FontFaceArray fontfaces() const { return m_fontfaces; } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: CSSFontFaceLoadEvent(); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.cpp index d6357bd3250..276ffbfc578 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.cpp @@ -37,8 +37,10 @@ CSSFontFaceRule::CSSFontFaceRule(StyleRuleFontFace* fontFaceRule, CSSStyleSheet* CSSFontFaceRule::~CSSFontFaceRule() { +#if !ENABLE(OILPAN) if (m_propertiesCSSOMWrapper) m_propertiesCSSOMWrapper->clearParentRule(); +#endif } CSSStyleDeclaration* CSSFontFaceRule::style() const @@ -52,7 +54,7 @@ String CSSFontFaceRule::cssText() const { StringBuilder result; result.appendLiteral("@font-face { "); - String descs = m_fontFaceRule->properties()->asText(); + String descs = m_fontFaceRule->properties().asText(); result.append(descs); if (!descs.isEmpty()) result.append(' '); @@ -68,4 +70,11 @@ void CSSFontFaceRule::reattach(StyleRuleBase* rule) m_propertiesCSSOMWrapper->reattach(m_fontFaceRule->mutableProperties()); } +void CSSFontFaceRule::trace(Visitor* visitor) +{ + visitor->trace(m_fontFaceRule); + visitor->trace(m_propertiesCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.h b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.h index 0b88f9b2eee..866389828bd 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceRule.h @@ -23,6 +23,7 @@ #define CSSFontFaceRule_h #include "core/css/CSSRule.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -30,9 +31,12 @@ class CSSStyleDeclaration; class StyleRuleFontFace; class StyleRuleCSSStyleDeclaration; -class CSSFontFaceRule : public CSSRule { +class CSSFontFaceRule FINAL : public CSSRule { public: - static PassRefPtr<CSSFontFaceRule> create(StyleRuleFontFace* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSFontFaceRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSFontFaceRule> create(StyleRuleFontFace* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSFontFaceRule(rule, sheet)); + } virtual ~CSSFontFaceRule(); @@ -44,11 +48,13 @@ public: StyleRuleFontFace* styleRule() const { return m_fontFaceRule.get(); } + virtual void trace(Visitor*) OVERRIDE; + private: CSSFontFaceRule(StyleRuleFontFace*, CSSStyleSheet* parent); - RefPtr<StyleRuleFontFace> m_fontFaceRule; - mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; + RefPtrWillBeMember<StyleRuleFontFace> m_fontFaceRule; + mutable RefPtrWillBeMember<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSFontFaceRule, FONT_FACE_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp index d235aea7edf..39dfcd7c291 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.cpp @@ -26,292 +26,46 @@ #include "config.h" #include "core/css/CSSFontFaceSource.h" -#include "RuntimeEnabledFeatures.h" -#include "core/css/CSSCustomFontData.h" #include "core/css/CSSFontFace.h" -#include "platform/fonts/FontCache.h" +#include "platform/fonts/FontCacheKey.h" #include "platform/fonts/FontDescription.h" #include "platform/fonts/SimpleFontData.h" -#include "public/platform/Platform.h" -#include "wtf/CurrentTime.h" - -#if ENABLE(SVG_FONTS) -#include "SVGNames.h" -#include "core/svg/SVGFontData.h" -#include "core/svg/SVGFontElement.h" -#include "core/svg/SVGFontFaceElement.h" -#endif namespace WebCore { -CSSFontFaceSource::CSSFontFaceSource(const String& str, FontResource* font) - : m_string(str) - , m_font(font) - , m_face(0) -#if ENABLE(SVG_FONTS) - , m_hasExternalSVGFont(false) -#endif +CSSFontFaceSource::CSSFontFaceSource() + : m_face(nullptr) { - if (m_font) - m_font->addClient(this); } CSSFontFaceSource::~CSSFontFaceSource() { - if (m_font) - m_font->removeClient(this); - pruneTable(); -} - -void CSSFontFaceSource::pruneTable() -{ - if (m_fontDataTable.isEmpty()) - return; - - for (FontDataTable::iterator it = m_fontDataTable.begin(); it != m_fontDataTable.end(); ++it) { - SimpleFontData* fontData = it->value.get(); - if (fontData && fontData->customFontData()) - fontData->customFontData()->clearCSSFontFaceSource(); - } - m_fontDataTable.clear(); -} - -bool CSSFontFaceSource::isLocal() const -{ - if (m_font) - return false; -#if ENABLE(SVG_FONTS) - if (m_svgFontFaceElement) - return false; -#endif - return true; -} - -bool CSSFontFaceSource::isLoading() const -{ - if (m_font) - return !m_font->stillNeedsLoad() && !m_font->isLoaded(); - return false; -} - -bool CSSFontFaceSource::isLoaded() const -{ - if (m_font) - return m_font->isLoaded(); - return true; -} - -bool CSSFontFaceSource::isValid() const -{ - if (m_font) - return !m_font->errorOccurred(); - return true; -} - -void CSSFontFaceSource::didStartFontLoad(FontResource*) -{ - // Avoid duplicated reports when multiple CSSFontFaceSource are registered - // at this FontResource. - if (!m_fontDataTable.isEmpty()) - m_histograms.loadStarted(); -} - -void CSSFontFaceSource::fontLoaded(FontResource*) -{ - if (!m_fontDataTable.isEmpty()) - m_histograms.recordRemoteFont(m_font.get()); - - pruneTable(); - if (m_face) - m_face->fontLoaded(this); } PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription) { // If the font hasn't loaded or an error occurred, then we've got nothing. if (!isValid()) - return 0; + return nullptr; if (isLocal()) { // We're local. Just return a SimpleFontData from the normal cache. - // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter. - RefPtr<SimpleFontData> fontData = FontCache::fontCache()->getFontData(fontDescription, m_string, true); - m_histograms.recordLocalFont(fontData); - return fontData; + return createFontData(fontDescription); } // See if we have a mapping in our FontData cache. AtomicString emptyFontFamily = ""; FontCacheKey key = fontDescription.cacheKey(emptyFontFamily); - RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(key.hash(), 0).iterator->value; - if (fontData) - return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable. - - // If we are still loading, then we let the system pick a font. - if (isLoaded()) { - if (m_font) { -#if ENABLE(SVG_FONTS) - if (m_hasExternalSVGFont) { - // For SVG fonts parse the external SVG document, and extract the <font> element. - if (!m_font->ensureSVGFontData()) - return 0; - - if (!m_externalSVGFontElement) { - String fragmentIdentifier; - size_t start = m_string.find('#'); - if (start != kNotFound) - fragmentIdentifier = m_string.string().substring(start + 1); - m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier); - } - - if (!m_externalSVGFontElement) - return 0; - - SVGFontFaceElement* fontFaceElement = 0; - - // Select first <font-face> child - for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) { - if (fontChild->hasTagName(SVGNames::font_faceTag)) { - fontFaceElement = toSVGFontFaceElement(fontChild); - break; - } - } - - if (fontFaceElement) { - if (!m_svgFontFaceElement) { - // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement. - // Use the imported <font-face> tag as referencing font-face element for these cases. - m_svgFontFaceElement = fontFaceElement; - } - - fontData = SimpleFontData::create( - SVGFontData::create(fontFaceElement), - fontDescription.effectiveFontSize(), - fontDescription.isSyntheticBold(), - fontDescription.isSyntheticItalic()); - } - } else -#endif - { - // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. - if (!m_font->ensureCustomFontData()) - return 0; - - fontData = SimpleFontData::create( - m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(), - fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(), - fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create(false)); - } - } else { -#if ENABLE(SVG_FONTS) - // In-Document SVG Fonts - if (m_svgFontFaceElement) { - fontData = SimpleFontData::create( - SVGFontData::create(m_svgFontFaceElement.get()), - fontDescription.effectiveFontSize(), - fontDescription.isSyntheticBold(), - fontDescription.isSyntheticItalic()); - } -#endif - } - } else { - // This temporary font is not retained and should not be returned. - FontCachePurgePreventer fontCachePurgePreventer; - SimpleFontData* temporaryFont = FontCache::fontCache()->getNonRetainedLastResortFallbackFont(fontDescription); - RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(true); - cssFontData->setCSSFontFaceSource(this); - fontData = SimpleFontData::create(temporaryFont->platformData(), cssFontData); - } - + RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(key.hash(), nullptr).storedValue->value; + if (!fontData) + fontData = createFontData(fontDescription); return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable. } -#if ENABLE(SVG_FONTS) -SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const -{ - return m_svgFontFaceElement.get(); -} - -void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element) -{ - m_svgFontFaceElement = element; -} - -bool CSSFontFaceSource::isSVGFontFaceSource() const -{ - return m_svgFontFaceElement || m_hasExternalSVGFont; -} -#endif - -bool CSSFontFaceSource::ensureFontData() -{ - if (!m_font) - return false; -#if ENABLE(SVG_FONTS) - if (m_hasExternalSVGFont) - return m_font->ensureSVGFontData(); -#endif - return m_font->ensureCustomFontData(); -} - -bool CSSFontFaceSource::isLocalFontAvailable(const FontDescription& fontDescription) -{ - if (!isLocal()) - return false; - return FontCache::fontCache()->isPlatformFontAvailable(fontDescription, m_string); -} - -void CSSFontFaceSource::beginLoadIfNeeded() +void CSSFontFaceSource::trace(Visitor* visitor) { - if (m_face && m_font) - m_face->beginLoadIfNeeded(this); -} - -void CSSFontFaceSource::FontLoadHistograms::loadStarted() -{ - if (!m_loadStartTime) - m_loadStartTime = currentTimeMS(); -} - -void CSSFontFaceSource::FontLoadHistograms::recordLocalFont(bool loadSuccess) -{ - if (!m_loadStartTime) { - blink::Platform::current()->histogramEnumeration("WebFont.LocalFontUsed", loadSuccess ? 1 : 0, 2); - m_loadStartTime = -1; // Do not count this font again. - } -} - -void CSSFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font) -{ - if (m_loadStartTime > 0 && font && !font->isLoading()) { - int duration = static_cast<int>(currentTimeMS() - m_loadStartTime); - blink::Platform::current()->histogramCustomCounts(histogramName(font), duration, 0, 10000, 50); - m_loadStartTime = -1; - - enum { Miss, Hit, DataUrl, CacheHitEnumMax }; - int histogramValue = font->url().protocolIsData() ? DataUrl - : font->response().wasCached() ? Hit - : Miss; - blink::Platform::current()->histogramEnumeration("WebFont.CacheHit", histogramValue, CacheHitEnumMax); - } -} - -const char* CSSFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font) -{ - if (font->errorOccurred()) - return "WebFont.DownloadTime.LoadError"; - - unsigned size = font->encodedSize(); - if (size < 10 * 1024) - return "WebFont.DownloadTime.0.Under10KB"; - if (size < 50 * 1024) - return "WebFont.DownloadTime.1.10KBTo50KB"; - if (size < 100 * 1024) - return "WebFont.DownloadTime.2.50KBTo100KB"; - if (size < 1024 * 1024) - return "WebFont.DownloadTime.3.100KBTo1MB"; - return "WebFont.DownloadTime.4.Over1MB"; + visitor->trace(m_face); } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.h b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.h index 8ba3f027534..47da18a1ae2 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSource.h @@ -26,11 +26,8 @@ #ifndef CSSFontFaceSource_h #define CSSFontFaceSource_h -#include "core/fetch/FontResource.h" -#include "core/fetch/ResourcePtr.h" -#include "platform/Timer.h" +#include "platform/heap/Handle.h" #include "wtf/HashMap.h" -#include "wtf/text/AtomicString.h" namespace WebCore { @@ -38,69 +35,37 @@ class FontResource; class CSSFontFace; class FontDescription; class SimpleFontData; -#if ENABLE(SVG_FONTS) -class SVGFontElement; -class SVGFontFaceElement; -#endif - -class CSSFontFaceSource : public FontResourceClient { +class CSSFontFaceSource : public NoBaseWillBeGarbageCollectedFinalized<CSSFontFaceSource> { public: - CSSFontFaceSource(const String&, FontResource* = 0); virtual ~CSSFontFaceSource(); - bool isLocal() const; - bool isLoading() const; - bool isLoaded() const; - bool isValid() const; + virtual bool isLocal() const { return false; } + virtual bool isLoading() const { return false; } + virtual bool isLoaded() const { return true; } + virtual bool isValid() const { return true; } - FontResource* resource() { return m_font.get(); } + virtual FontResource* resource() { return 0; } void setFontFace(CSSFontFace* face) { m_face = face; } - virtual void didStartFontLoad(FontResource*) OVERRIDE; - virtual void fontLoaded(FontResource*); - PassRefPtr<SimpleFontData> getFontData(const FontDescription&); -#if ENABLE(SVG_FONTS) - SVGFontFaceElement* svgFontFaceElement() const; - void setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement>); - bool isSVGFontFaceSource() const; - void setHasExternalSVGFont(bool value) { m_hasExternalSVGFont = value; } -#endif + virtual bool isLocalFontAvailable(const FontDescription&) { return false; } + virtual void beginLoadIfNeeded() { } - bool ensureFontData(); - bool isLocalFontAvailable(const FontDescription&); - void beginLoadIfNeeded(); + // For UMA reporting + virtual bool hadBlankText() { return false; } + + virtual void trace(Visitor*); + +protected: + CSSFontFaceSource(); + virtual PassRefPtr<SimpleFontData> createFontData(const FontDescription&) = 0; -private: typedef HashMap<unsigned, RefPtr<SimpleFontData> > FontDataTable; // The hash key is composed of size synthetic styles. - class FontLoadHistograms { - public: - FontLoadHistograms() : m_loadStartTime(0) { } - void loadStarted(); - void recordLocalFont(bool loadSuccess); - void recordRemoteFont(const FontResource*); - private: - const char* histogramName(const FontResource*); - double m_loadStartTime; - }; - - void pruneTable(); - void startLoadingTimerFired(Timer<CSSFontFaceSource>*); - - AtomicString m_string; // URI for remote, built-in font name for local. - ResourcePtr<FontResource> m_font; // For remote fonts, a pointer to our cached resource. - CSSFontFace* m_face; // Our owning font face. + RawPtrWillBeMember<CSSFontFace> m_face; // Our owning font face. FontDataTable m_fontDataTable; - FontLoadHistograms m_histograms; - -#if ENABLE(SVG_FONTS) - RefPtr<SVGFontFaceElement> m_svgFontFaceElement; - RefPtr<SVGFontElement> m_externalSVGFontElement; - bool m_hasExternalSVGFont; -#endif }; } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp index 9e7f212554a..f0cde2c59ab 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/css/CSSFontFaceSrcValue.h" -#include "FetchInitiatorTypeNames.h" +#include "core/FetchInitiatorTypeNames.h" #include "core/css/StyleSheetContents.h" #include "core/dom/Document.h" #include "core/dom/Node.h" @@ -81,12 +81,6 @@ String CSSFontFaceSrcValue::customCSSText() const return result.toString(); } -void CSSFontFaceSrcValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const -{ - if (!isLocal()) - addSubresourceURL(urls, styleSheet->completeURL(m_resource)); -} - bool CSSFontFaceSrcValue::hasFailedOrCanceledSubresources() const { if (!m_fetched) @@ -94,15 +88,44 @@ bool CSSFontFaceSrcValue::hasFailedOrCanceledSubresources() const return m_fetched->loadFailedOrCanceled(); } +bool CSSFontFaceSrcValue::shouldSetCrossOriginAccessControl(const KURL& resource, SecurityOrigin* securityOrigin) +{ + if (resource.isLocalFile() || resource.protocolIsData()) + return false; + return !securityOrigin->canRequest(resource); +} + FontResource* CSSFontFaceSrcValue::fetch(Document* document) { if (!m_fetched) { FetchRequest request(ResourceRequest(document->completeURL(m_resource)), FetchInitiatorTypeNames::css); + SecurityOrigin* securityOrigin = document->securityOrigin(); + if (shouldSetCrossOriginAccessControl(request.url(), securityOrigin)) { + request.setCrossOriginAccessControl(securityOrigin, DoNotAllowStoredCredentials); + } + request.mutableResourceRequest().setHTTPReferrer(m_referrer); m_fetched = document->fetcher()->fetchFont(request); + } else { + // FIXME: CSSFontFaceSrcValue::fetch is invoked when @font-face rule + // is processed by StyleResolver / StyleEngine. + restoreCachedResourceIfNeeded(document); } return m_fetched.get(); } +void CSSFontFaceSrcValue::restoreCachedResourceIfNeeded(Document* document) +{ + ASSERT(m_fetched); + ASSERT(document && document->fetcher()); + + const String resourceURL = document->completeURL(m_resource); + if (document->fetcher()->cachedResource(KURL(ParsedURLString, resourceURL))) + return; + + FetchRequest request(ResourceRequest(resourceURL), FetchInitiatorTypeNames::css); + document->fetcher()->requestLoadStarted(m_fetched.get(), request, ResourceFetcher::ResourceLoadingFromCache); +} + bool CSSFontFaceSrcValue::equals(const CSSFontFaceSrcValue& other) const { return m_isLocal == other.m_isLocal && m_format == other.m_format && m_resource == other.m_resource; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h index 1be94d687ff..83f26f7ee64 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.h @@ -28,6 +28,7 @@ #include "core/css/CSSValue.h" #include "core/fetch/ResourcePtr.h" +#include "platform/weborigin/Referrer.h" #include "wtf/PassRefPtr.h" #include "wtf/text/WTFString.h" @@ -39,13 +40,13 @@ class SVGFontFaceElement; class CSSFontFaceSrcValue : public CSSValue { public: - static PassRefPtr<CSSFontFaceSrcValue> create(const String& resource) + static PassRefPtrWillBeRawPtr<CSSFontFaceSrcValue> create(const String& resource) { - return adoptRef(new CSSFontFaceSrcValue(resource, false)); + return adoptRefWillBeNoop(new CSSFontFaceSrcValue(resource, false)); } - static PassRefPtr<CSSFontFaceSrcValue> createLocal(const String& resource) + static PassRefPtrWillBeRawPtr<CSSFontFaceSrcValue> createLocal(const String& resource) { - return adoptRef(new CSSFontFaceSrcValue(resource, true)); + return adoptRefWillBeNoop(new CSSFontFaceSrcValue(resource, true)); } const String& resource() const { return m_resource; } @@ -53,6 +54,7 @@ public: bool isLocal() const { return m_isLocal; } void setFormat(const String& format) { m_format = format; } + void setReferrer(const Referrer& referrer) { m_referrer = referrer; } bool isSupportedFormat() const; @@ -65,14 +67,14 @@ public: String customCSSText() const; - void addSubresourceStyleURLs(ListHashSet<KURL>&, const StyleSheetContents*) const; - bool hasFailedOrCanceledSubresources() const; FontResource* fetch(Document*); bool equals(const CSSFontFaceSrcValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSFontFaceSrcValue(const String& resource, bool local) : CSSValue(FontFaceSrcClass) @@ -84,8 +86,12 @@ private: { } + void restoreCachedResourceIfNeeded(Document*); + bool shouldSetCrossOriginAccessControl(const KURL& resource, SecurityOrigin*); + String m_resource; String m_format; + Referrer m_referrer; bool m_isLocal; ResourcePtr<FontResource> m_fetched; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFaceTest.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceTest.cpp new file mode 100644 index 00000000000..87b0bab86fd --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFaceTest.cpp @@ -0,0 +1,90 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/CSSFontFace.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +static const UChar hiraganaA[2] = { 0x3042, 0 }; + +TEST(CSSFontFace, UnicodeRangeSetEmpty) +{ + Vector<CSSFontFace::UnicodeRange> ranges; + CSSFontFace::UnicodeRangeSet set(ranges); + EXPECT_TRUE(set.isEntireRange()); + EXPECT_EQ(0u, set.size()); + EXPECT_FALSE(set.intersectsWith(String())); + EXPECT_TRUE(set.intersectsWith(String("a"))); + EXPECT_TRUE(set.intersectsWith(String(hiraganaA))); +} + +TEST(CSSFontFace, UnicodeRangeSetSingleCharacter) +{ + Vector<CSSFontFace::UnicodeRange> ranges; + ranges.append(CSSFontFace::UnicodeRange('b', 'b')); + CSSFontFace::UnicodeRangeSet set(ranges); + EXPECT_FALSE(set.isEntireRange()); + EXPECT_FALSE(set.intersectsWith(String())); + EXPECT_FALSE(set.intersectsWith(String("a"))); + EXPECT_TRUE(set.intersectsWith(String("b"))); + EXPECT_FALSE(set.intersectsWith(String("c"))); + EXPECT_TRUE(set.intersectsWith(String("abc"))); + EXPECT_FALSE(set.intersectsWith(String(hiraganaA))); + ASSERT_EQ(1u, set.size()); + EXPECT_EQ('b', set.rangeAt(0).from()); + EXPECT_EQ('b', set.rangeAt(0).to()); +} + +TEST(CSSFontFace, UnicodeRangeSetTwoRanges) +{ + Vector<CSSFontFace::UnicodeRange> ranges; + ranges.append(CSSFontFace::UnicodeRange('6', '7')); + ranges.append(CSSFontFace::UnicodeRange('2', '4')); + CSSFontFace::UnicodeRangeSet set(ranges); + EXPECT_FALSE(set.isEntireRange()); + EXPECT_FALSE(set.intersectsWith(String())); + EXPECT_FALSE(set.intersectsWith(String("1"))); + EXPECT_TRUE(set.intersectsWith(String("2"))); + EXPECT_TRUE(set.intersectsWith(String("3"))); + EXPECT_TRUE(set.intersectsWith(String("4"))); + EXPECT_FALSE(set.intersectsWith(String("5"))); + EXPECT_TRUE(set.intersectsWith(String("6"))); + EXPECT_TRUE(set.intersectsWith(String("7"))); + EXPECT_FALSE(set.intersectsWith(String("8"))); + ASSERT_EQ(2u, set.size()); + EXPECT_EQ('2', set.rangeAt(0).from()); + EXPECT_EQ('4', set.rangeAt(0).to()); + EXPECT_EQ('6', set.rangeAt(1).from()); + EXPECT_EQ('7', set.rangeAt(1).to()); +} + +TEST(CSSFontFace, UnicodeRangeSetOverlap) +{ + Vector<CSSFontFace::UnicodeRange> ranges; + ranges.append(CSSFontFace::UnicodeRange('0', '2')); + ranges.append(CSSFontFace::UnicodeRange('1', '1')); + ranges.append(CSSFontFace::UnicodeRange('3', '5')); + ranges.append(CSSFontFace::UnicodeRange('4', '6')); + CSSFontFace::UnicodeRangeSet set(ranges); + ASSERT_EQ(1u, set.size()); + EXPECT_EQ('0', set.rangeAt(0).from()); + EXPECT_EQ('6', set.rangeAt(0).to()); +} + +TEST(CSSFontFace, UnicodeRangeSetNon8Bit) +{ + Vector<CSSFontFace::UnicodeRange> ranges; + ranges.append(CSSFontFace::UnicodeRange(0x3042, 0x3042)); + CSSFontFace::UnicodeRangeSet set(ranges); + ASSERT_EQ(1u, set.size()); + EXPECT_EQ(0x3042, set.rangeAt(0).from()); + EXPECT_EQ(0x3042, set.rangeAt(0).to()); + EXPECT_FALSE(set.intersectsWith(String("a"))); + EXPECT_TRUE(set.intersectsWith(String(hiraganaA))); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontFeatureValue.h b/chromium/third_party/WebKit/Source/core/css/CSSFontFeatureValue.h index 8a0367fabe3..fc841792619 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontFeatureValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontFeatureValue.h @@ -33,9 +33,9 @@ namespace WebCore { class CSSFontFeatureValue : public CSSValue { public: - static PassRefPtr<CSSFontFeatureValue> create(const AtomicString& tag, int value) + static PassRefPtrWillBeRawPtr<CSSFontFeatureValue> create(const AtomicString& tag, int value) { - return adoptRef(new CSSFontFeatureValue(tag, value)); + return adoptRefWillBeNoop(new CSSFontFeatureValue(tag, value)); } const AtomicString& tag() const { return m_tag; } @@ -44,6 +44,8 @@ public: bool equals(const CSSFontFeatureValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSFontFeatureValue(const AtomicString& tag, int value); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.cpp index 9b83e9e2182..2f1019c3312 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.cpp @@ -27,87 +27,25 @@ #include "config.h" #include "core/css/CSSFontSelector.h" -#include "RuntimeEnabledFeatures.h" -#include "core/css/CSSFontFace.h" -#include "core/css/CSSFontFaceRule.h" -#include "core/css/CSSFontFaceSource.h" +#include "core/css/CSSFontSelectorClient.h" #include "core/css/CSSSegmentedFontFace.h" #include "core/css/CSSValueList.h" +#include "core/css/FontFaceSet.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/Document.h" -#include "core/fetch/FontResource.h" -#include "core/fetch/ResourceFetcher.h" -#include "core/loader/FrameLoader.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/loader/FrameLoader.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/fonts/FontCache.h" #include "platform/fonts/SimpleFontData.h" #include "wtf/text/AtomicString.h" -using namespace std; - namespace WebCore { -FontLoader::FontLoader(ResourceFetcher* resourceFetcher) - : m_beginLoadingTimer(this, &FontLoader::beginLoadTimerFired) - , m_resourceFetcher(resourceFetcher) -{ -} - -void FontLoader::addFontToBeginLoading(FontResource* fontResource) -{ - if (!m_resourceFetcher || !fontResource->stillNeedsLoad()) - return; - - m_fontsToBeginLoading.append(fontResource); - // FIXME: Use RequestCountTracker??!! - // Increment the request count now, in order to prevent didFinishLoad from being dispatched - // after this font has been requested but before it began loading. Balanced by - // decrementRequestCount() in beginLoadTimerFired() and in clearDocument(). - m_resourceFetcher->incrementRequestCount(fontResource); - m_beginLoadingTimer.startOneShot(0); -} - -void FontLoader::beginLoadTimerFired(Timer<WebCore::FontLoader>*) -{ - loadPendingFonts(); -} - -void FontLoader::loadPendingFonts() -{ - ASSERT(m_resourceFetcher); - - Vector<ResourcePtr<FontResource> > fontsToBeginLoading; - fontsToBeginLoading.swap(m_fontsToBeginLoading); - - for (size_t i = 0; i < fontsToBeginLoading.size(); ++i) { - fontsToBeginLoading[i]->beginLoadIfNeeded(m_resourceFetcher); - // Balances incrementRequestCount() in beginLoadingFontSoon(). - m_resourceFetcher->decrementRequestCount(fontsToBeginLoading[i].get()); - } -} - -void FontLoader::clearResourceFetcher() -{ - if (!m_resourceFetcher) { - ASSERT(m_fontsToBeginLoading.isEmpty()); - return; - } - - m_beginLoadingTimer.stop(); - - for (size_t i = 0; i < m_fontsToBeginLoading.size(); ++i) { - // Balances incrementRequestCount() in beginLoadingFontSoon(). - m_resourceFetcher->decrementRequestCount(m_fontsToBeginLoading[i].get()); - } - - m_fontsToBeginLoading.clear(); - m_resourceFetcher = 0; -} - CSSFontSelector::CSSFontSelector(Document* document) : m_document(document) - , m_fontLoader(document->fetcher()) + , m_fontLoader(FontLoader::create(this, document->fetcher())) , m_genericFontFamilySettings(document->frame()->settings()->genericFontFamilySettings()) { // FIXME: An old comment used to say there was no need to hold a reference to m_document @@ -117,33 +55,38 @@ CSSFontSelector::CSSFontSelector(Document* document) ASSERT(m_document); ASSERT(m_document->frame()); FontCache::fontCache()->addClient(this); + FontFaceSet::from(*document)->addFontFacesToFontFaceCache(&m_fontFaceCache, this); } CSSFontSelector::~CSSFontSelector() { +#if !ENABLE(OILPAN) clearDocument(); FontCache::fontCache()->removeClient(this); +#endif } -void CSSFontSelector::registerForInvalidationCallbacks(FontSelectorClient* client) +void CSSFontSelector::registerForInvalidationCallbacks(CSSFontSelectorClient* client) { m_clients.add(client); } -void CSSFontSelector::unregisterForInvalidationCallbacks(FontSelectorClient* client) +#if !ENABLE(OILPAN) +void CSSFontSelector::unregisterForInvalidationCallbacks(CSSFontSelectorClient* client) { m_clients.remove(client); } +#endif void CSSFontSelector::dispatchInvalidationCallbacks() { - Vector<FontSelectorClient*> clients; + WillBeHeapVector<RawPtrWillBeMember<CSSFontSelectorClient> > clients; copyToVector(m_clients, clients); for (size_t i = 0; i < clients.size(); ++i) clients[i]->fontsNeedUpdate(this); } -void CSSFontSelector::fontLoaded() +void CSSFontSelector::fontFaceInvalidated() { dispatchInvalidationCallbacks(); } @@ -153,28 +96,18 @@ void CSSFontSelector::fontCacheInvalidated() dispatchInvalidationCallbacks(); } -void CSSFontSelector::addFontFaceRule(const StyleRuleFontFace* fontFaceRule, PassRefPtr<CSSFontFace> cssFontFace) -{ - m_cssSegmentedFontFaceCache.add(this, fontFaceRule, cssFontFace); -} - -void CSSFontSelector::removeFontFaceRule(const StyleRuleFontFace* fontFaceRule) -{ - m_cssSegmentedFontFaceCache.remove(fontFaceRule); -} - static AtomicString familyNameFromSettings(const GenericFontFamilySettings& settings, const FontDescription& fontDescription, const AtomicString& genericFamilyName) { UScriptCode script = fontDescription.script(); #if OS(ANDROID) - if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont()) + if (fontDescription.genericFamily() == FontDescription::StandardFamily) return FontCache::getGenericFamilyNameForScript(FontFamilyNames::webkit_standard, script); if (genericFamilyName.startsWith("-webkit-")) return FontCache::getGenericFamilyNameForScript(genericFamilyName, script); #else - if (fontDescription.genericFamily() == FontDescription::StandardFamily && !fontDescription.isSpecifiedFont()) + if (fontDescription.genericFamily() == FontDescription::StandardFamily) return settings.standard(script); if (genericFamilyName == FontFamilyNames::webkit_serif) return settings.serif(script); @@ -196,43 +129,56 @@ static AtomicString familyNameFromSettings(const GenericFontFamilySettings& sett PassRefPtr<FontData> CSSFontSelector::getFontData(const FontDescription& fontDescription, const AtomicString& familyName) { - if (CSSSegmentedFontFace* face = m_cssSegmentedFontFaceCache.get(fontDescription, familyName)) + if (CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, familyName)) return face->getFontData(fontDescription); // Try to return the correct font based off our settings, in case we were handed the generic font family name. AtomicString settingsFamilyName = familyNameFromSettings(m_genericFontFamilySettings, fontDescription, familyName); if (settingsFamilyName.isEmpty()) - return 0; + return nullptr; return FontCache::fontCache()->getFontData(fontDescription, settingsFamilyName); } -CSSSegmentedFontFace* CSSFontSelector::getFontFace(const FontDescription& fontDescription, const AtomicString& familyName) +void CSSFontSelector::willUseFontData(const FontDescription& fontDescription, const AtomicString& family, UChar32 character) { - return m_cssSegmentedFontFaceCache.get(fontDescription, familyName); + CSSSegmentedFontFace* face = m_fontFaceCache.get(fontDescription, family); + if (face) + face->willUseFontData(fontDescription, character); } -void CSSFontSelector::willUseFontData(const FontDescription& fontDescription, const AtomicString& family) +bool CSSFontSelector::isPlatformFontAvailable(const FontDescription& fontDescription, const AtomicString& passedFamily) { - CSSSegmentedFontFace* face = getFontFace(fontDescription, family); - if (face) - face->willUseFontData(fontDescription); + AtomicString family = familyNameFromSettings(m_genericFontFamilySettings, fontDescription, passedFamily); + if (family.isEmpty()) + family = passedFamily; + return FontCache::fontCache()->isPlatformFontAvailable(fontDescription, family); } +#if !ENABLE(OILPAN) void CSSFontSelector::clearDocument() { - m_fontLoader.clearResourceFetcher(); - m_document = 0; + m_fontLoader->clearResourceFetcherAndFontSelector(); + m_document = nullptr; } +#endif -void CSSFontSelector::beginLoadingFontSoon(FontResource* font) +void CSSFontSelector::updateGenericFontFamilySettings(Document& document) { - m_fontLoader.addFontToBeginLoading(font); + if (!document.settings()) + return; + m_genericFontFamilySettings = document.settings()->genericFontFamilySettings(); + // Need to increment FontFaceCache version to update RenderStyles. + m_fontFaceCache.incrementVersion(); } -void CSSFontSelector::loadPendingFonts() +void CSSFontSelector::trace(Visitor* visitor) { - m_fontLoader.loadPendingFonts(); + visitor->trace(m_document); + visitor->trace(m_fontFaceCache); + visitor->trace(m_clients); + visitor->trace(m_fontLoader); + FontSelector::trace(visitor); } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.h b/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.h index 34d33a8809d..94e2578ca1d 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontSelector.h @@ -26,11 +26,11 @@ #ifndef CSSFontSelector_h #define CSSFontSelector_h -#include "core/css/CSSSegmentedFontFaceCache.h" -#include "core/fetch/ResourcePtr.h" -#include "platform/Timer.h" +#include "core/css/FontFaceCache.h" +#include "core/css/FontLoader.h" #include "platform/fonts/FontSelector.h" #include "platform/fonts/GenericFontFamilySettings.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" #include "wtf/HashSet.h" @@ -39,72 +39,63 @@ namespace WebCore { class CSSFontFace; class CSSFontFaceRule; +class CSSFontSelectorClient; class CSSSegmentedFontFace; -class FontResource; class Document; class FontDescription; class StyleRuleFontFace; -class FontLoader { +class CSSFontSelector FINAL : public FontSelector { public: - explicit FontLoader(ResourceFetcher*); - - void addFontToBeginLoading(FontResource*); - void loadPendingFonts(); - - void clearResourceFetcher(); - -private: - void beginLoadTimerFired(Timer<FontLoader>*); - - Timer<FontLoader> m_beginLoadingTimer; - Vector<ResourcePtr<FontResource> > m_fontsToBeginLoading; - ResourceFetcher* m_resourceFetcher; -}; - -class CSSFontSelector : public FontSelector { -public: - static PassRefPtr<CSSFontSelector> create(Document* document) + static PassRefPtrWillBeRawPtr<CSSFontSelector> create(Document* document) { - return adoptRef(new CSSFontSelector(document)); + return adoptRefWillBeNoop(new CSSFontSelector(document)); } virtual ~CSSFontSelector(); - virtual unsigned version() const OVERRIDE { return m_cssSegmentedFontFaceCache.version(); } + virtual unsigned version() const OVERRIDE { return m_fontFaceCache.version(); } - virtual PassRefPtr<FontData> getFontData(const FontDescription&, const AtomicString&); - CSSSegmentedFontFace* getFontFace(const FontDescription&, const AtomicString& family); - virtual void willUseFontData(const FontDescription&, const AtomicString& family) OVERRIDE; + virtual PassRefPtr<FontData> getFontData(const FontDescription&, const AtomicString&) OVERRIDE; + virtual void willUseFontData(const FontDescription&, const AtomicString& family, UChar32) OVERRIDE; + bool isPlatformFontAvailable(const FontDescription&, const AtomicString& family); +#if !ENABLE(OILPAN) void clearDocument(); +#endif - void addFontFaceRule(const StyleRuleFontFace*, PassRefPtr<CSSFontFace>); - void removeFontFaceRule(const StyleRuleFontFace*); + void fontFaceInvalidated(); - void fontLoaded(); - virtual void fontCacheInvalidated(); + // FontCacheClient implementation + virtual void fontCacheInvalidated() OVERRIDE; - virtual void registerForInvalidationCallbacks(FontSelectorClient*); - virtual void unregisterForInvalidationCallbacks(FontSelectorClient*); + void registerForInvalidationCallbacks(CSSFontSelectorClient*); +#if !ENABLE(OILPAN) + void unregisterForInvalidationCallbacks(CSSFontSelectorClient*); +#endif Document* document() const { return m_document; } + FontFaceCache* fontFaceCache() { return &m_fontFaceCache; } + FontLoader* fontLoader() { return m_fontLoader.get(); } const GenericFontFamilySettings& genericFontFamilySettings() const { return m_genericFontFamilySettings; } + void updateGenericFontFamilySettings(Document&); - void beginLoadingFontSoon(FontResource*); - void loadPendingFonts(); + virtual void trace(Visitor*); private: explicit CSSFontSelector(Document*); void dispatchInvalidationCallbacks(); - Document* m_document; + // FIXME: Oilpan: Ideally this should just be a traced Member but that will + // currently leak because RenderStyle and its data are not on the heap. + // See crbug.com/383860 for details. + RawPtrWillBeWeakMember<Document> m_document; // FIXME: Move to Document or StyleEngine. - CSSSegmentedFontFaceCache m_cssSegmentedFontFaceCache; - HashSet<FontSelectorClient*> m_clients; + FontFaceCache m_fontFaceCache; + WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSFontSelectorClient> > m_clients; - FontLoader m_fontLoader; + RefPtrWillBeMember<FontLoader> m_fontLoader; GenericFontFamilySettings m_genericFontFamilySettings; }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMapForEachCallback.h b/chromium/third_party/WebKit/Source/core/css/CSSFontSelectorClient.h index 001ccbdcf74..5a8c1c0892a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMapForEachCallback.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontSelectorClient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -11,6 +11,9 @@ * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,24 +28,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CSSVariablesMapForEachCallback_h -#define CSSVariablesMapForEachCallback_h +#ifndef CSSFontSelectorClient_h +#define CSSFontSelectorClient_h -#include "bindings/v8/ScriptValue.h" -#include "wtf/RefCounted.h" -#include "wtf/text/WTFString.h" +#include "platform/heap/Handle.h" namespace WebCore { -class CSSVariablesMap; +class CSSFontSelector; +class Visitor; -class CSSVariablesMapForEachCallback { +class CSSFontSelectorClient : public NoBaseWillBeGarbageCollectedFinalized<CSSFontSelectorClient> { public: - virtual ~CSSVariablesMapForEachCallback() { } - virtual void handleItem(ScriptValue thisValue, const String& value, const String& name, CSSVariablesMap*) = 0; - virtual void handleItem(const String& value, const String& name, CSSVariablesMap*) = 0; + virtual ~CSSFontSelectorClient() { } + + virtual void fontsNeedUpdate(CSSFontSelector*) = 0; + + virtual void trace(Visitor*) { } }; } // namespace WebCore -#endif // CSSVariablesMapForEachCallback_h +#endif // CSSFontSelectorClient_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFontValue.cpp index aee5a9726d6..522c7f81a53 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontValue.cpp @@ -74,4 +74,16 @@ bool CSSFontValue::equals(const CSSFontValue& other) const && compareCSSValuePtr(family, other.family); } +void CSSFontValue::traceAfterDispatch(Visitor* visitor) +{ + + visitor->trace(style); + visitor->trace(variant); + visitor->trace(weight); + visitor->trace(size); + visitor->trace(lineHeight); + visitor->trace(family); + CSSValue::traceAfterDispatch(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFontValue.h b/chromium/third_party/WebKit/Source/core/css/CSSFontValue.h index f0c99d55326..892d4e24b82 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFontValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFontValue.h @@ -32,21 +32,23 @@ class CSSValueList; class CSSFontValue : public CSSValue { public: - static PassRefPtr<CSSFontValue> create() + static PassRefPtrWillBeRawPtr<CSSFontValue> create() { - return adoptRef(new CSSFontValue); + return adoptRefWillBeNoop(new CSSFontValue); } String customCSSText() const; bool equals(const CSSFontValue&) const; - RefPtr<CSSPrimitiveValue> style; - RefPtr<CSSPrimitiveValue> variant; - RefPtr<CSSPrimitiveValue> weight; - RefPtr<CSSPrimitiveValue> size; - RefPtr<CSSPrimitiveValue> lineHeight; - RefPtr<CSSValueList> family; + void traceAfterDispatch(Visitor*); + + RefPtrWillBeMember<CSSPrimitiveValue> style; + RefPtrWillBeMember<CSSPrimitiveValue> variant; + RefPtrWillBeMember<CSSPrimitiveValue> weight; + RefPtrWillBeMember<CSSPrimitiveValue> size; + RefPtrWillBeMember<CSSPrimitiveValue> lineHeight; + RefPtrWillBeMember<CSSValueList> family; private: CSSFontValue() diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.cpp index 7cbbf86d06f..9fb04dc43e2 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.cpp @@ -40,7 +40,7 @@ CSSFunctionValue::CSSFunctionValue(CSSParserFunction* function) m_args = CSSValueList::createFromParserValueList(function->args.get()); } -CSSFunctionValue::CSSFunctionValue(String name, PassRefPtr<CSSValueList> args) +CSSFunctionValue::CSSFunctionValue(String name, PassRefPtrWillBeRawPtr<CSSValueList> args) : CSSValue(FunctionClass) , m_name(name) , m_args(args) @@ -62,4 +62,10 @@ bool CSSFunctionValue::equals(const CSSFunctionValue& other) const return m_name == other.m_name && compareCSSValuePtr(m_args, other.m_args); } +void CSSFunctionValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_args); + CSSValue::traceAfterDispatch(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.h b/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.h index 87fa8afacfb..aa678635978 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSFunctionValue.h @@ -35,14 +35,14 @@ struct CSSParserFunction; class CSSFunctionValue : public CSSValue { public: - static PassRefPtr<CSSFunctionValue> create(CSSParserFunction* function) + static PassRefPtrWillBeRawPtr<CSSFunctionValue> create(CSSParserFunction* function) { - return adoptRef(new CSSFunctionValue(function)); + return adoptRefWillBeNoop(new CSSFunctionValue(function)); } - static PassRefPtr<CSSFunctionValue> create(String name, PassRefPtr<CSSValueList> args) + static PassRefPtrWillBeRawPtr<CSSFunctionValue> create(String name, PassRefPtrWillBeRawPtr<CSSValueList> args) { - return adoptRef(new CSSFunctionValue(name, args)); + return adoptRefWillBeNoop(new CSSFunctionValue(name, args)); } String customCSSText() const; @@ -51,12 +51,14 @@ public: CSSValueList* arguments() const { return m_args.get(); } + void traceAfterDispatch(Visitor*); + private: explicit CSSFunctionValue(CSSParserFunction*); - CSSFunctionValue(String, PassRefPtr<CSSValueList>); + CSSFunctionValue(String, PassRefPtrWillBeRawPtr<CSSValueList>); String m_name; - RefPtr<CSSValueList> m_args; + RefPtrWillBeMember<CSSValueList> m_args; }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSFunctionValue, isFunctionValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.cpp index 68269972045..277162fd89b 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/css/CSSGradientValue.h" -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" #include "core/css/CSSCalculationValue.h" #include "core/css/CSSToLengthConversionData.h" #include "core/dom/NodeRenderStyle.h" @@ -39,19 +39,23 @@ #include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" -using namespace std; - namespace WebCore { +void CSSGradientColorStop::trace(Visitor* visitor) +{ + visitor->trace(m_position); + visitor->trace(m_color); +} + PassRefPtr<Image> CSSGradientValue::image(RenderObject* renderer, const IntSize& size) { if (size.isEmpty()) - return 0; + return nullptr; bool cacheable = isCacheable(); if (cacheable) { if (!clients().contains(renderer)) - return 0; + return nullptr; // Need to look up our size. Create a string of width*height to use as a hash key. Image* result = getImage(renderer, size); @@ -63,7 +67,7 @@ PassRefPtr<Image> CSSGradientValue::image(RenderObject* renderer, const IntSize& RefPtr<Gradient> gradient; RenderStyle* rootStyle = renderer->document().documentElement()->renderStyle(); - CSSToLengthConversionData conversionData(renderer->style(), rootStyle); + CSSToLengthConversionData conversionData(renderer->style(), rootStyle, renderer->view()); if (isLinearGradientValue()) gradient = toCSSLinearGradientValue(this)->createGradient(conversionData, size); else @@ -106,7 +110,7 @@ struct GradientStop { { } }; -PassRefPtr<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const TextLinkColors& textLinkColors, Color currentColor) +PassRefPtrWillBeRawPtr<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const TextLinkColors& textLinkColors, Color currentColor) { bool derived = false; for (unsigned i = 0; i < m_stops.size(); i++) @@ -116,7 +120,7 @@ PassRefPtr<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const break; } - RefPtr<CSSGradientValue> result; + RefPtrWillBeRawPtr<CSSGradientValue> result = nullptr; if (!derived) result = this; else if (isLinearGradientValue()) @@ -125,7 +129,7 @@ PassRefPtr<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const result = toCSSRadialGradientValue(this)->clone(); else { ASSERT_NOT_REACHED(); - return 0; + return nullptr; } for (unsigned i = 0; i < result->m_stops.size(); i++) @@ -151,8 +155,6 @@ void CSSGradientValue::addStops(Gradient* gradient, const CSSToLengthConversionD gradient->addColorStop(offset, stop.m_resolvedColor); } - // The back end already sorted the stops. - gradient->setStopsSorted(true); return; } @@ -262,7 +264,6 @@ void CSSGradientValue::addStops(Gradient* gradient, const CSSToLengthConversionD stops.first().offset = 0; stops.first().color = stops.last().color; stops.shrink(1); - numStops = 1; } else { float maxExtent = 1; @@ -384,8 +385,6 @@ void CSSGradientValue::addStops(Gradient* gradient, const CSSToLengthConversionD for (unsigned i = 0; i < numStops; i++) gradient->addColorStop(stops[i].offset, stops[i].color); - - gradient->setStopsSorted(true); } static float positionFromValue(CSSPrimitiveValue* value, const CSSToLengthConversionData& conversionData, const IntSize& size, bool isHorizontal) @@ -460,6 +459,16 @@ bool CSSGradientValue::knownToBeOpaque(const RenderObject*) const return true; } +void CSSGradientValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_firstX); + visitor->trace(m_firstY); + visitor->trace(m_secondX); + visitor->trace(m_secondY); + visitor->trace(m_stops); + CSSImageGeneratorValue::traceAfterDispatch(visitor); +} + String CSSLinearGradientValue::customCSSText() const { StringBuilder result; @@ -733,6 +742,12 @@ bool CSSLinearGradientValue::equals(const CSSLinearGradientValue& other) const return equalXandY && m_stops == other.m_stops; } +void CSSLinearGradientValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_angle); + CSSGradientValue::traceAfterDispatch(visitor); +} + String CSSRadialGradientValue::customCSSText() const { StringBuilder result; @@ -1039,10 +1054,10 @@ PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(const CSSToLengthCon // Horizontal switch (fill) { case ClosestSide: { - float xDist = min(secondPoint.x(), size.width() - secondPoint.x()); - float yDist = min(secondPoint.y(), size.height() - secondPoint.y()); + float xDist = std::min(secondPoint.x(), size.width() - secondPoint.x()); + float yDist = std::min(secondPoint.y(), size.height() - secondPoint.y()); if (shape == Circle) { - float smaller = min(xDist, yDist); + float smaller = std::min(xDist, yDist); xDist = smaller; yDist = smaller; } @@ -1051,10 +1066,10 @@ PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(const CSSToLengthCon break; } case FarthestSide: { - float xDist = max(secondPoint.x(), size.width() - secondPoint.x()); - float yDist = max(secondPoint.y(), size.height() - secondPoint.y()); + float xDist = std::max(secondPoint.x(), size.width() - secondPoint.x()); + float yDist = std::max(secondPoint.y(), size.height() - secondPoint.y()); if (shape == Circle) { - float larger = max(xDist, yDist); + float larger = std::max(xDist, yDist); xDist = larger; yDist = larger; } @@ -1070,8 +1085,8 @@ PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(const CSSToLengthCon else { // If <shape> is ellipse, the gradient-shape has the same ratio of width to height // that it would if closest-side or farthest-side were specified, as appropriate. - float xDist = min(secondPoint.x(), size.width() - secondPoint.x()); - float yDist = min(secondPoint.y(), size.height() - secondPoint.y()); + float xDist = std::min(secondPoint.x(), size.width() - secondPoint.x()); + float yDist = std::min(secondPoint.y(), size.height() - secondPoint.y()); secondRadius = horizontalEllipseRadius(corner - secondPoint, xDist / yDist); aspectRatio = xDist / yDist; @@ -1087,8 +1102,8 @@ PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(const CSSToLengthCon else { // If <shape> is ellipse, the gradient-shape has the same ratio of width to height // that it would if closest-side or farthest-side were specified, as appropriate. - float xDist = max(secondPoint.x(), size.width() - secondPoint.x()); - float yDist = max(secondPoint.y(), size.height() - secondPoint.y()); + float xDist = std::max(secondPoint.x(), size.width() - secondPoint.x()); + float yDist = std::max(secondPoint.y(), size.height() - secondPoint.y()); secondRadius = horizontalEllipseRadius(corner - secondPoint, xDist / yDist); aspectRatio = xDist / yDist; @@ -1161,4 +1176,15 @@ bool CSSRadialGradientValue::equals(const CSSRadialGradientValue& other) const return equalShape && equalSizingBehavior && equalHorizontalAndVerticalSize && m_stops == other.m_stops; } +void CSSRadialGradientValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_firstRadius); + visitor->trace(m_secondRadius); + visitor->trace(m_shape); + visitor->trace(m_sizingBehavior); + visitor->trace(m_endHorizontalSize); + visitor->trace(m_endVerticalSize); + CSSGradientValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.h b/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.h index 7179b6fff80..4e3af429fc7 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSGradientValue.h @@ -47,10 +47,17 @@ enum CSSGradientType { }; enum CSSGradientRepeat { NonRepeating, Repeating }; +// This struct is stack allocated and allocated as part of vectors. +// When allocated on the stack its members are found by conservative +// stack scanning. When allocated as part of Vectors in heap-allocated +// objects its members are visited via the containing object's +// (CSSGradientValue) traceAfterDispatch method. struct CSSGradientColorStop { + ALLOW_ONLY_INLINE_ALLOCATION(); +public: CSSGradientColorStop() : m_colorIsDerivedFromElement(false) { }; - RefPtr<CSSPrimitiveValue> m_position; // percentage or length - RefPtr<CSSPrimitiveValue> m_color; + RefPtrWillBeMember<CSSPrimitiveValue> m_position; // percentage or length + RefPtrWillBeMember<CSSPrimitiveValue> m_color; Color m_resolvedColor; bool m_colorIsDerivedFromElement; bool operator==(const CSSGradientColorStop& other) const @@ -58,16 +65,27 @@ struct CSSGradientColorStop { return compareCSSValuePtr(m_color, other.m_color) && compareCSSValuePtr(m_position, other.m_position); } + + void trace(Visitor*); }; +} // namespace WebCore + + +// We have to declare the VectorTraits specialization before CSSGradientValue +// declares its inline capacity vector below. +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::CSSGradientColorStop); + +namespace WebCore { + class CSSGradientValue : public CSSImageGeneratorValue { public: PassRefPtr<Image> image(RenderObject*, const IntSize&); - void setFirstX(PassRefPtr<CSSPrimitiveValue> val) { m_firstX = val; } - void setFirstY(PassRefPtr<CSSPrimitiveValue> val) { m_firstY = val; } - void setSecondX(PassRefPtr<CSSPrimitiveValue> val) { m_secondX = val; } - void setSecondY(PassRefPtr<CSSPrimitiveValue> val) { m_secondY = val; } + void setFirstX(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_firstX = val; } + void setFirstY(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_firstY = val; } + void setSecondX(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_secondX = val; } + void setSecondY(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_secondY = val; } void addStop(const CSSGradientColorStop& stop) { m_stops.append(stop); } @@ -86,7 +104,9 @@ public: bool knownToBeOpaque(const RenderObject*) const; void loadSubimages(ResourceFetcher*) { } - PassRefPtr<CSSGradientValue> gradientWithStylesResolved(const TextLinkColors&, Color currentColor); + PassRefPtrWillBeRawPtr<CSSGradientValue> gradientWithStylesResolved(const TextLinkColors&, Color currentColor); + + void traceAfterDispatch(Visitor*); protected: CSSGradientValue(ClassType classType, CSSGradientRepeat repeat, CSSGradientType gradientType) @@ -118,14 +138,14 @@ protected: bool isCacheable() const; // Points. Some of these may be null. - RefPtr<CSSPrimitiveValue> m_firstX; - RefPtr<CSSPrimitiveValue> m_firstY; + RefPtrWillBeMember<CSSPrimitiveValue> m_firstX; + RefPtrWillBeMember<CSSPrimitiveValue> m_firstY; - RefPtr<CSSPrimitiveValue> m_secondX; - RefPtr<CSSPrimitiveValue> m_secondY; + RefPtrWillBeMember<CSSPrimitiveValue> m_secondX; + RefPtrWillBeMember<CSSPrimitiveValue> m_secondY; // Stops - Vector<CSSGradientColorStop, 2> m_stops; + WillBeHeapVector<CSSGradientColorStop, 2> m_stops; bool m_stopsSorted; CSSGradientType m_gradientType; bool m_repeating; @@ -136,25 +156,27 @@ DEFINE_CSS_VALUE_TYPE_CASTS(CSSGradientValue, isGradientValue()); class CSSLinearGradientValue : public CSSGradientValue { public: - static PassRefPtr<CSSLinearGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient) + static PassRefPtrWillBeRawPtr<CSSLinearGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient) { - return adoptRef(new CSSLinearGradientValue(repeat, gradientType)); + return adoptRefWillBeNoop(new CSSLinearGradientValue(repeat, gradientType)); } - void setAngle(PassRefPtr<CSSPrimitiveValue> val) { m_angle = val; } + void setAngle(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_angle = val; } String customCSSText() const; // Create the gradient for a given size. PassRefPtr<Gradient> createGradient(const CSSToLengthConversionData&, const IntSize&); - PassRefPtr<CSSLinearGradientValue> clone() const + PassRefPtrWillBeRawPtr<CSSLinearGradientValue> clone() const { - return adoptRef(new CSSLinearGradientValue(*this)); + return adoptRefWillBeNoop(new CSSLinearGradientValue(*this)); } bool equals(const CSSLinearGradientValue&) const; + void traceAfterDispatch(Visitor*); + private: CSSLinearGradientValue(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient) : CSSGradientValue(LinearGradientClass, repeat, gradientType) @@ -167,39 +189,41 @@ private: { } - RefPtr<CSSPrimitiveValue> m_angle; // may be null. + RefPtrWillBeMember<CSSPrimitiveValue> m_angle; // may be null. }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSLinearGradientValue, isLinearGradientValue()); class CSSRadialGradientValue : public CSSGradientValue { public: - static PassRefPtr<CSSRadialGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient) + static PassRefPtrWillBeRawPtr<CSSRadialGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient) { - return adoptRef(new CSSRadialGradientValue(repeat, gradientType)); + return adoptRefWillBeNoop(new CSSRadialGradientValue(repeat, gradientType)); } - PassRefPtr<CSSRadialGradientValue> clone() const + PassRefPtrWillBeRawPtr<CSSRadialGradientValue> clone() const { - return adoptRef(new CSSRadialGradientValue(*this)); + return adoptRefWillBeNoop(new CSSRadialGradientValue(*this)); } String customCSSText() const; - void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; } - void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; } + void setFirstRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_firstRadius = val; } + void setSecondRadius(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_secondRadius = val; } - void setShape(PassRefPtr<CSSPrimitiveValue> val) { m_shape = val; } - void setSizingBehavior(PassRefPtr<CSSPrimitiveValue> val) { m_sizingBehavior = val; } + void setShape(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_shape = val; } + void setSizingBehavior(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_sizingBehavior = val; } - void setEndHorizontalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endHorizontalSize = val; } - void setEndVerticalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endVerticalSize = val; } + void setEndHorizontalSize(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_endHorizontalSize = val; } + void setEndVerticalSize(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_endVerticalSize = val; } // Create the gradient for a given size. PassRefPtr<Gradient> createGradient(const CSSToLengthConversionData&, const IntSize&); bool equals(const CSSRadialGradientValue&) const; + void traceAfterDispatch(Visitor*); + private: CSSRadialGradientValue(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient) : CSSGradientValue(RadialGradientClass, repeat, gradientType) @@ -222,15 +246,15 @@ private: float resolveRadius(CSSPrimitiveValue*, const CSSToLengthConversionData&, float* widthOrHeight = 0); // These may be null for non-deprecated gradients. - RefPtr<CSSPrimitiveValue> m_firstRadius; - RefPtr<CSSPrimitiveValue> m_secondRadius; + RefPtrWillBeMember<CSSPrimitiveValue> m_firstRadius; + RefPtrWillBeMember<CSSPrimitiveValue> m_secondRadius; // The below are only used for non-deprecated gradients. Any of them may be null. - RefPtr<CSSPrimitiveValue> m_shape; - RefPtr<CSSPrimitiveValue> m_sizingBehavior; + RefPtrWillBeMember<CSSPrimitiveValue> m_shape; + RefPtrWillBeMember<CSSPrimitiveValue> m_sizingBehavior; - RefPtr<CSSPrimitiveValue> m_endHorizontalSize; - RefPtr<CSSPrimitiveValue> m_endVerticalSize; + RefPtrWillBeMember<CSSPrimitiveValue> m_endHorizontalSize; + RefPtrWillBeMember<CSSPrimitiveValue> m_endVerticalSize; }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSRadialGradientValue, isRadialGradientValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGrammar.y b/chromium/third_party/WebKit/Source/core/css/CSSGrammar.y index 2c2c3753094..e006812e9a4 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGrammar.y +++ b/chromium/third_party/WebKit/Source/core/css/CSSGrammar.y @@ -29,7 +29,7 @@ #include "HTMLNames.h" #include "core/css/CSSKeyframeRule.h" #include "core/css/CSSKeyframesRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSParserMode.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSSelector.h" @@ -60,10 +60,10 @@ using namespace HTMLNames; %} -%pure_parser +%pure-parser -%parse-param { CSSParser* parser } -%lex-param { CSSParser* parser } +%parse-param { BisonCSSParser* parser } +%lex-param { BisonCSSParser* parser } %union { bool boolean; @@ -73,7 +73,12 @@ using namespace HTMLNames; CSSParserString string; StyleRuleBase* rule; - Vector<RefPtr<StyleRuleBase> >* ruleList; + // The content of the three below HeapVectors are guaranteed to be kept alive by + // the corresponding m_parsedRules, m_floatingMediaQueryExpList, and m_parsedKeyFrames + // lists in BisonCSSParser.h. + WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >* ruleList; + WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* mediaQueryExpList; + WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeRuleList; CSSParserSelector* selector; Vector<OwnPtr<CSSParserSelector> >* selectorList; CSSSelector::MarginBoxType marginBox; @@ -84,9 +89,7 @@ using namespace HTMLNames; MediaQueryExp* mediaQueryExp; CSSParserValue value; CSSParserValueList* valueList; - Vector<OwnPtr<MediaQueryExp> >* mediaQueryExpList; StyleKeyframe* keyframe; - Vector<RefPtr<StyleKeyframe> >* keyframeRuleList; float val; CSSPropertyID id; CSSParserLocation location; @@ -114,12 +117,9 @@ static inline bool isCSSTokenAString(int yytype) case FUNCTION: case ANYFUNCTION: case HOSTFUNCTION: + case HOSTCONTEXTFUNCTION: case NOTFUNCTION: case CALCFUNCTION: - case MINFUNCTION: - case MAXFUNCTION: - case VARFUNCTION: - case VAR_DEFINITION: case UNICODERANGE: return true; default: @@ -132,6 +132,7 @@ inline static CSSParserValue makeOperatorValue(int value) { CSSParserValue v; v.id = CSSValueInvalid; + v.isInt = false; v.unit = CSSParserValue::Operator; v.iValue = value; return v; @@ -141,6 +142,7 @@ inline static CSSParserValue makeIdentValue(CSSParserString string) { CSSParserValue v; v.id = cssValueKeywordID(string); + v.isInt = false; v.unit = CSSPrimitiveValue::CSS_IDENT; v.string = string; return v; @@ -194,8 +196,6 @@ inline static CSSParserValue makeIdentValue(CSSParserString string) %token INTERNAL_SUPPORTS_CONDITION_SYM %token KEYFRAMES_SYM %token WEBKIT_KEYFRAMES_SYM -%token WEBKIT_REGION_RULE_SYM -%token WEBKIT_FILTER_RULE_SYM %token <marginBox> TOPLEFTCORNER_SYM %token <marginBox> TOPLEFT_SYM %token <marginBox> TOPCENTER_SYM @@ -265,11 +265,8 @@ inline static CSSParserValue makeIdentValue(CSSParserString string) %token <string> NOTFUNCTION %token <string> DISTRIBUTEDFUNCTION %token <string> CALCFUNCTION -%token <string> MINFUNCTION -%token <string> MAXFUNCTION -%token <string> VARFUNCTION -%token <string> VAR_DEFINITION %token <string> HOSTFUNCTION +%token <string> HOSTCONTEXTFUNCTION %token <string> UNICODERANGE @@ -287,16 +284,10 @@ inline static CSSParserValue makeIdentValue(CSSParserString string) %type <rule> valid_rule %type <ruleList> block_rule_body %type <ruleList> block_rule_list -%type <ruleList> region_block_rule_body -%type <ruleList> region_block_rule_list %type <rule> block_rule %type <rule> block_valid_rule -%type <rule> region_block_rule -%type <rule> region_block_valid_rule -%type <rule> region %type <rule> supports %type <rule> viewport -%type <rule> filter %type <boolean> keyframes_rule_start %type <string> maybe_ns_prefix @@ -339,10 +330,8 @@ inline static CSSParserValue makeIdentValue(CSSParserString string) %type <selector> specifier_list %type <selector> simple_selector %type <selector> selector -%type <selector> relative_selector %type <selectorList> selector_list %type <selectorList> simple_selector_list -%type <selectorList> region_selector %type <selector> class %type <selector> attrib %type <selector> pseudo @@ -368,11 +357,8 @@ inline static CSSParserValue makeIdentValue(CSSParserString string) %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 @@ -511,10 +497,8 @@ valid_rule: | keyframes | namespace | import - | region | supports | viewport - | filter ; before_rule: @@ -547,46 +531,12 @@ block_rule_list: } ; -region_block_rule_body: - region_block_rule_list - | region_block_rule_list block_rule_recovery - ; - -region_block_rule_list: - /* empty */ { $$ = 0; } - | region_block_rule_list region_block_rule maybe_sgml { - $$ = parser->appendRule($1, $2); - } - ; - -region_block_rule: - before_rule region_block_valid_rule { - $$ = $2; - parser->endRule(!!$$); - } - | before_rule invalid_rule { - $$ = 0; - parser->endRule(false); - } - ; - block_rule_recovery: before_rule invalid_rule_header { parser->endRule(false); } ; -region_block_valid_rule: - ruleset - | page - | font_face - | media - | keyframes - | supports - | viewport - | filter - ; - block_valid_rule: ruleset | page @@ -595,9 +545,7 @@ block_valid_rule: | keyframes | supports | viewport - | filter | namespace - | region ; block_rule: @@ -716,11 +664,11 @@ valid_media_query: media_query: valid_media_query | valid_media_query error error_location rule_error_recovery { - parser->reportError(parser->lastLocationLabel(), CSSParser::InvalidMediaQueryError); + parser->reportError(parser->lastLocationLabel(), InvalidMediaQueryCSSError); $$ = parser->createFloatingNotAllQuery(); } | error error_location rule_error_recovery { - parser->reportError(parser->lastLocationLabel(), CSSParser::InvalidMediaQueryError); + parser->reportError(parser->lastLocationLabel(), InvalidMediaQueryCSSError); $$ = parser->createFloatingNotAllQuery(); } ; @@ -846,7 +794,7 @@ supports_condition_in_parens: } | supports_declaration_condition | '(' error error_location error_recovery closing_parenthesis maybe_space { - parser->reportError($3, CSSParser::InvalidSupportsConditionError); + parser->reportError($3, InvalidSupportsConditionCSSError); $$ = false; } ; @@ -868,7 +816,7 @@ supports_declaration_condition: } | '(' maybe_space IDENT maybe_space ':' maybe_space error error_recovery closing_parenthesis maybe_space { $$ = false; - parser->endProperty(false, false, CSSParser::GeneralError); + parser->endProperty(false, false, GeneralCSSError); } ; @@ -953,7 +901,7 @@ key: keyframes_error_recovery: error rule_error_recovery { - parser->reportError(parser->lastLocationLabel(), CSSParser::InvalidKeyframeSelectorError); + parser->reportError(parser->lastLocationLabel(), InvalidKeyframeSelectorCSSError); } ; @@ -1089,53 +1037,15 @@ viewport: } ; -region_selector: - selector_list { - parser->setReusableRegionSelectorVector($1); - $$ = parser->reusableRegionSelectorVector(); - } -; - -before_region_rule: - /* empty */ { - parser->startRuleHeader(CSSRuleSourceData::REGION_RULE); - } - ; - -region: - before_region_rule WEBKIT_REGION_RULE_SYM maybe_space region_selector at_rule_header_end '{' at_rule_body_start maybe_space region_block_rule_body closing_brace { - $$ = parser->createRegionRule($4, $9); - } -; - -before_filter_rule: - /* empty */ { - parser->startRuleHeader(CSSRuleSourceData::FILTER_RULE); - parser->m_inFilterRule = true; - } - ; - -filter: - before_filter_rule WEBKIT_FILTER_RULE_SYM maybe_space IDENT at_rule_header_end_maybe_space - '{' at_rule_body_start maybe_space_before_declaration declaration_list closing_brace { - parser->m_inFilterRule = false; - $$ = parser->createFilterRule($4); - } - ; - combinator: '+' maybe_space { $$ = CSSSelector::DirectAdjacent; } | '~' maybe_space { $$ = CSSSelector::IndirectAdjacent; } | '>' maybe_space { $$ = CSSSelector::Child; } - | '^' maybe_space { - if (!RuntimeEnabledFeatures::shadowDOMEnabled()) + | '/' IDENT '/' maybe_space { + if ($2.equalIgnoringCase("deep")) + $$ = CSSSelector::ShadowDeep; + else YYERROR; - $$ = CSSSelector::ChildTree; - } - | '^' '^' maybe_space { - if (!RuntimeEnabledFeatures::shadowDOMEnabled()) - YYERROR; - $$ = CSSSelector::DescendantTree; } ; @@ -1197,17 +1107,6 @@ selector_list: } ; -relative_selector: - combinator selector { - $$ = $2; - CSSParserSelector* end = $$; - while (end->tagHistory()) - end = end->tagHistory(); - end->setRelation($1); - } - | selector - ; - selector: simple_selector | selector WHITESPACE @@ -1420,7 +1319,7 @@ pseudo: $$->setValue($3); CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) { - parser->reportError($2, CSSParser::InvalidSelectorPseudoError); + parser->reportError($2, InvalidSelectorPseudoCSSError); YYERROR; } } @@ -1434,7 +1333,7 @@ pseudo: // FIXME: This call is needed to force selector to compute the pseudoType early enough. CSSSelector::PseudoType type = $$->pseudoType(); if (type == CSSSelector::PseudoUnknown) { - parser->reportError($3, CSSParser::InvalidSelectorPseudoError); + parser->reportError($3, InvalidSelectorPseudoCSSError); YYERROR; } } @@ -1451,16 +1350,6 @@ pseudo: | ':' ':' CUEFUNCTION selector_recovery closing_parenthesis { YYERROR; } - | ':' ':' DISTRIBUTEDFUNCTION maybe_space relative_selector closing_parenthesis { - $$ = parser->createFloatingSelector(); - $$->setMatch(CSSSelector::PseudoElement); - $$->setFunctionArgumentSelector($5); - parser->tokenToLowerCase($3); - $$->setValue($3); - } - | ':' ':' DISTRIBUTEDFUNCTION selector_recovery closing_parenthesis { - YYERROR; - } // 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. @@ -1549,17 +1438,21 @@ pseudo: if (type != CSSSelector::PseudoHost) YYERROR; } - // used by :host() - | ':' HOSTFUNCTION maybe_space closing_parenthesis { + | ':' HOSTFUNCTION selector_recovery closing_parenthesis { + YYERROR; + } + // used by :host-context() + | ':' HOSTCONTEXTFUNCTION maybe_space simple_selector_list maybe_space closing_parenthesis { $$ = parser->createFloatingSelector(); $$->setMatch(CSSSelector::PseudoClass); + $$->adoptSelectorVector(*parser->sinkFloatingSelectorVector($4)); parser->tokenToLowerCase($2); - $$->setValue($2.atomicSubstring(0, $2.length() - 1)); + $$->setValue($2); CSSSelector::PseudoType type = $$->pseudoType(); - if (type != CSSSelector::PseudoHost) + if (type != CSSSelector::PseudoHostContext) YYERROR; } - | ':' HOSTFUNCTION selector_recovery closing_parenthesis { + | ':' HOSTCONTEXTFUNCTION selector_recovery closing_parenthesis { YYERROR; } ; @@ -1588,12 +1481,6 @@ decl_list: ; declaration: - VAR_DEFINITION maybe_space ':' maybe_space expr prio { - parser->storeVariableDeclaration($1, parser->sinkFloatingValueList($5), $6); - $$ = true; - parser->endProperty($6, true); - } - | property ':' maybe_space error_location expr prio { $$ = false; bool isPropertyParsed = false; @@ -1603,7 +1490,7 @@ declaration: $$ = parser->parseValue($1, $6); if (!$$) { parser->rollbackLastProperties(parser->m_parsedProperties.size() - oldParsedProperties); - parser->reportError($4, CSSParser::InvalidPropertyValueError); + parser->reportError($4, InvalidPropertyValueCSSError); } else isPropertyParsed = true; parser->m_valueList = nullptr; @@ -1613,25 +1500,25 @@ declaration: | property ':' maybe_space error_location expr prio error error_recovery { /* When we encounter something like p {color: red !important fail;} we should drop the declaration */ - parser->reportError($4, CSSParser::InvalidPropertyValueError); + parser->reportError($4, InvalidPropertyValueCSSError); parser->endProperty(false, false); $$ = false; } | property ':' maybe_space error_location error error_recovery { - parser->reportError($4, CSSParser::InvalidPropertyValueError); + parser->reportError($4, InvalidPropertyValueCSSError); parser->endProperty(false, false); $$ = false; } | property error error_location error_recovery { - parser->reportError($3, CSSParser::PropertyDeclarationError); - parser->endProperty(false, false, CSSParser::GeneralError); + parser->reportError($3, PropertyDeclarationCSSError); + parser->endProperty(false, false, GeneralCSSError); $$ = false; } | error error_location error_recovery { - parser->reportError($2, CSSParser::PropertyDeclarationError); + parser->reportError($2, PropertyDeclarationCSSError); $$ = false; } ; @@ -1641,7 +1528,7 @@ property: $$ = cssPropertyID($2); parser->setCurrentProperty($$); if ($$ == CSSPropertyInvalid) - parser->reportError($1, CSSParser::InvalidPropertyError); + parser->reportError($1, InvalidPropertyCSSError); } ; @@ -1691,7 +1578,7 @@ expr: expr_recovery: error error_location error_recovery { - parser->reportError($2, CSSParser::PropertyDeclarationError); + parser->reportError($2, PropertyDeclarationCSSError); } ; @@ -1707,29 +1594,20 @@ operator: term: unary_term maybe_space | unary_operator unary_term maybe_space { $$ = $2; $$.fValue *= $1; } - | STRING maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; } + | STRING maybe_space { $$.id = CSSValueInvalid; $$.isInt = false; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_STRING; } | IDENT maybe_space { $$ = makeIdentValue($1); } /* We might need to actually parse the number from a dimension, but we can't just put something that uses $$.string into unary_term. */ - | DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } - | unary_operator DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $2; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } - | URI maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_URI; } - | UNICODERANGE maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; } - | HEX maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } - | '#' maybe_space { $$.id = CSSValueInvalid; $$.string = CSSParserString(); $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } /* Handle error case: "color: #;" */ - | VARFUNCTION maybe_space IDENT closing_parenthesis maybe_space { - $$.id = CSSValueInvalid; - $$.string = $3; - $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME; - } - | VARFUNCTION maybe_space expr_recovery closing_parenthesis { - YYERROR; - } + | DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } + | unary_operator DIMEN maybe_space { $$.id = CSSValueInvalid; $$.string = $2; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_DIMENSION; } + | URI maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_URI; } + | UNICODERANGE maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_UNICODE_RANGE; } + | HEX maybe_space { $$.id = CSSValueInvalid; $$.string = $1; $$.isInt = false; $$.unit = CSSPrimitiveValue::CSS_PARSER_HEXCOLOR; } + | '#' maybe_space { $$.id = CSSValueInvalid; $$.string = CSSParserString(); $$.isInt = false; $$.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 maybe_space | calc_function maybe_space - | min_or_max_function maybe_space | '%' maybe_space { /* Handle width: %; */ - $$.id = CSSValueInvalid; $$.unit = 0; + $$.id = CSSValueInvalid; $$.isInt = false; $$.unit = 0; } | track_names_list maybe_space ; @@ -1785,11 +1663,6 @@ function: calc_func_term: unary_term - | VARFUNCTION maybe_space IDENT closing_parenthesis { - $$.id = CSSValueInvalid; - $$.string = $3; - $$.unit = CSSPrimitiveValue::CSS_VARIABLE_NAME; - } | unary_operator unary_term { $$ = $2; $$.fValue *= $1; } ; @@ -1837,20 +1710,11 @@ calc_func_expr: | calc_func_expr calc_func_operator calc_func_paren_expr { $$ = $1; $$->addValue(makeOperatorValue($2)); - $$->extend(*($3)); + $$->stealValues(*($3)); } | calc_func_paren_expr ; -calc_func_expr_list: - calc_func_expr calc_maybe_space - | calc_func_expr_list ',' maybe_space calc_func_expr calc_maybe_space { - $$ = $1; - $$->addValue(makeOperatorValue(',')); - $$->extend(*($4)); - } - ; - calc_function: CALCFUNCTION maybe_space calc_func_expr calc_maybe_space closing_parenthesis { $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3))); @@ -1861,20 +1725,6 @@ calc_function: ; -min_or_max: - MINFUNCTION - | MAXFUNCTION - ; - -min_or_max_function: - min_or_max maybe_space calc_func_expr_list closing_parenthesis { - $$.setFromFunction(parser->createFloatingFunction($1, parser->sinkFloatingValueList($3))); - } - | min_or_max maybe_space expr_recovery closing_parenthesis { - YYERROR; - } - ; - invalid_at: ATKEYWORD | margin_sym @@ -1886,7 +1736,7 @@ at_rule_recovery: at_rule_header_recovery: error error_location rule_error_recovery { - parser->reportError($2, CSSParser::InvalidRuleError); + parser->reportError($2, InvalidRuleCSSError); } ; @@ -1900,25 +1750,23 @@ regular_invalid_at_rule_header: | before_page_rule PAGE_SYM at_rule_header_recovery | before_font_face_rule FONT_FACE_SYM at_rule_header_recovery | before_supports_rule SUPPORTS_SYM error error_location rule_error_recovery { - parser->reportError($4, CSSParser::InvalidSupportsConditionError); + parser->reportError($4, InvalidSupportsConditionCSSError); parser->popSupportsRuleData(); } | before_viewport_rule VIEWPORT_RULE_SYM at_rule_header_recovery { parser->markViewportRuleBodyEnd(); } - | before_filter_rule WEBKIT_FILTER_RULE_SYM at_rule_header_recovery | import_rule_start at_rule_header_recovery | NAMESPACE_SYM at_rule_header_recovery - | before_region_rule WEBKIT_REGION_RULE_SYM at_rule_header_recovery | error_location invalid_at at_rule_header_recovery { parser->resumeErrorLogging(); - parser->reportError($1, CSSParser::InvalidRuleError); + parser->reportError($1, InvalidRuleCSSError); } ; invalid_rule: error error_location rule_error_recovery at_invalid_rule_header_end invalid_block { - parser->reportError($2, CSSParser::InvalidRuleError); + parser->reportError($2, InvalidRuleCSSError); } | regular_invalid_at_rule_header at_invalid_rule_header_end ';' | regular_invalid_at_rule_header at_invalid_rule_header_end invalid_block @@ -1927,7 +1775,7 @@ invalid_rule: invalid_rule_header: error error_location rule_error_recovery at_invalid_rule_header_end { - parser->reportError($2, CSSParser::InvalidRuleError); + parser->reportError($2, InvalidRuleCSSError); } | regular_invalid_at_rule_header at_invalid_rule_header_end | media_rule_start maybe_media_list @@ -1953,7 +1801,7 @@ invalid_parentheses_block: opening_parenthesis error_recovery closing_parenthesis; opening_parenthesis: - '(' | FUNCTION | CALCFUNCTION | VARFUNCTION | MINFUNCTION | MAXFUNCTION | ANYFUNCTION | NOTFUNCTION | CUEFUNCTION | DISTRIBUTEDFUNCTION | HOSTFUNCTION + '(' | FUNCTION | CALCFUNCTION | ANYFUNCTION | NOTFUNCTION | CUEFUNCTION | DISTRIBUTEDFUNCTION | HOSTFUNCTION ; error_location: { @@ -1982,4 +1830,3 @@ rule_error_recovery: ; %% - diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.cpp index 3a2877d9ae9..5b100a553d8 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.cpp @@ -43,9 +43,9 @@ CSSGridLineNamesValue::CSSGridLineNamesValue() { } -PassRefPtr<CSSGridLineNamesValue> CSSGridLineNamesValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSGridLineNamesValue> CSSGridLineNamesValue::cloneForCSSOM() const { - return adoptRef(new CSSGridLineNamesValue(*this)); + return adoptRefWillBeNoop(new CSSGridLineNamesValue(*this)); } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.h b/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.h index da97e059579..3e4298fa39f 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSGridLineNamesValue.h @@ -38,14 +38,16 @@ namespace WebCore { class CSSGridLineNamesValue : public CSSValueList { public: - static PassRefPtr<CSSGridLineNamesValue> create() + static PassRefPtrWillBeRawPtr<CSSGridLineNamesValue> create() { - return adoptRef(new CSSGridLineNamesValue()); + return adoptRefWillBeNoop(new CSSGridLineNamesValue()); } String customCSSText() const; - PassRefPtr<CSSGridLineNamesValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSGridLineNamesValue> cloneForCSSOM() const; + + void traceAfterDispatch(Visitor* visitor) { CSSValueList::traceAfterDispatch(visitor); } private: CSSGridLineNamesValue(); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateAreasValue.cpp index d1ad1d8d056..9541f52715a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateAreasValue.cpp @@ -29,14 +29,14 @@ */ #include "config.h" -#include "core/css/CSSGridTemplateValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" #include "wtf/text/StringBuilder.h" namespace WebCore { -CSSGridTemplateValue::CSSGridTemplateValue(const NamedGridAreaMap& gridAreaMap, size_t rowCount, size_t columnCount) - : CSSValue(GridTemplateClass) +CSSGridTemplateAreasValue::CSSGridTemplateAreasValue(const NamedGridAreaMap& gridAreaMap, size_t rowCount, size_t columnCount) + : CSSValue(GridTemplateAreasClass) , m_gridAreaMap(gridAreaMap) , m_rowCount(rowCount) , m_columnCount(columnCount) @@ -52,21 +52,21 @@ static String stringForPosition(const NamedGridAreaMap& gridAreaMap, size_t row, NamedGridAreaMap::const_iterator end = gridAreaMap.end(); for (NamedGridAreaMap::const_iterator it = gridAreaMap.begin(); it != end; ++it) { const GridCoordinate& coordinate = it->value; - if (row >= coordinate.rows.initialPositionIndex && row <= coordinate.rows.finalPositionIndex) + if (row >= coordinate.rows.resolvedInitialPosition.toInt() && row <= coordinate.rows.resolvedFinalPosition.toInt()) candidates.append(it->key); } end = gridAreaMap.end(); for (NamedGridAreaMap::const_iterator it = gridAreaMap.begin(); it != end; ++it) { const GridCoordinate& coordinate = it->value; - if (column >= coordinate.columns.initialPositionIndex && column <= coordinate.columns.finalPositionIndex && candidates.contains(it->key)) + if (column >= coordinate.columns.resolvedInitialPosition.toInt() && column <= coordinate.columns.resolvedFinalPosition.toInt() && candidates.contains(it->key)) return it->key; } return "."; } -String CSSGridTemplateValue::customCSSText() const +String CSSGridTemplateAreasValue::customCSSText() const { StringBuilder builder; for (size_t row = 0; row < m_rowCount; ++row) { diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateValue.h b/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateAreasValue.h index faa988053f6..070cc8488cd 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSGridTemplateAreasValue.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CSSGridTemplateValue_h -#define CSSGridTemplateValue_h +#ifndef CSSGridTemplateAreasValue_h +#define CSSGridTemplateAreasValue_h #include "core/css/CSSValue.h" #include "core/rendering/style/GridCoordinate.h" @@ -37,10 +37,13 @@ namespace WebCore { -class CSSGridTemplateValue : public CSSValue { +class CSSGridTemplateAreasValue : public CSSValue { public: - static PassRefPtr<CSSGridTemplateValue> create(const NamedGridAreaMap& gridAreaMap, size_t rowCount, size_t columnCount) { return adoptRef(new CSSGridTemplateValue(gridAreaMap, rowCount, columnCount)); } - ~CSSGridTemplateValue() { } + static PassRefPtrWillBeRawPtr<CSSGridTemplateAreasValue> create(const NamedGridAreaMap& gridAreaMap, size_t rowCount, size_t columnCount) + { + return adoptRefWillBeNoop(new CSSGridTemplateAreasValue(gridAreaMap, rowCount, columnCount)); + } + ~CSSGridTemplateAreasValue() { } String customCSSText() const; @@ -48,16 +51,18 @@ public: size_t rowCount() const { return m_rowCount; } size_t columnCount() const { return m_columnCount; } + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: - CSSGridTemplateValue(const NamedGridAreaMap&, size_t rowCount, size_t columnCount); + CSSGridTemplateAreasValue(const NamedGridAreaMap&, size_t rowCount, size_t columnCount); NamedGridAreaMap m_gridAreaMap; size_t m_rowCount; size_t m_columnCount; }; -DEFINE_CSS_VALUE_TYPE_CASTS(CSSGridTemplateValue, isGridTemplateValue()); +DEFINE_CSS_VALUE_TYPE_CASTS(CSSGridTemplateAreasValue, isGridTemplateAreasValue()); } // namespace WebCore -#endif // CSSGridTemplateValue_h +#endif // CSSGridTemplateAreasValue_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp index 0c0bf2a9d20..ec56762b027 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.cpp @@ -32,10 +32,11 @@ #include "core/css/CSSGroupingRule.h" #include "bindings/v8/ExceptionState.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSRuleList.h" #include "core/css/CSSStyleSheet.h" #include "core/dom/ExceptionCode.h" +#include "core/frame/UseCounter.h" #include "wtf/text/StringBuilder.h" namespace WebCore { @@ -49,11 +50,13 @@ CSSGroupingRule::CSSGroupingRule(StyleRuleGroup* groupRule, CSSStyleSheet* paren CSSGroupingRule::~CSSGroupingRule() { +#if !ENABLE(OILPAN) ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { if (m_childRuleCSSOMWrappers[i]) m_childRuleCSSOMWrappers[i]->setParentRule(0); } +#endif } unsigned CSSGroupingRule::insertRule(const String& ruleString, unsigned index, ExceptionState& exceptionState) @@ -66,8 +69,9 @@ unsigned CSSGroupingRule::insertRule(const String& ruleString, unsigned index, E } CSSStyleSheet* styleSheet = parentStyleSheet(); - CSSParser parser(parserContext(), UseCounter::getFrom(styleSheet)); - RefPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? styleSheet->contents() : 0, ruleString); + CSSParserContext context(parserContext(), UseCounter::getFrom(styleSheet)); + BisonCSSParser parser(context); + RefPtrWillBeRawPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? styleSheet->contents() : 0, ruleString); if (!newRule) { exceptionState.throwDOMException(SyntaxError, "the rule '" + ruleString + "' is invalid and cannot be parsed."); return 0; @@ -84,7 +88,7 @@ unsigned CSSGroupingRule::insertRule(const String& ruleString, unsigned index, E m_groupRule->wrapperInsertRule(index, newRule); - m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>()); + m_childRuleCSSOMWrappers.insert(index, RefPtrWillBeMember<CSSRule>(nullptr)); return index; } @@ -126,7 +130,7 @@ CSSRule* CSSGroupingRule::item(unsigned index) const if (index >= length()) return 0; ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); - RefPtr<CSSRule>& rule = m_childRuleCSSOMWrappers[index]; + RefPtrWillBeMember<CSSRule>& rule = m_childRuleCSSOMWrappers[index]; if (!rule) rule = m_groupRule->childRules()[index]->createCSSOMWrapper(const_cast<CSSGroupingRule*>(this)); return rule.get(); @@ -135,7 +139,7 @@ CSSRule* CSSGroupingRule::item(unsigned index) const CSSRuleList* CSSGroupingRule::cssRules() const { if (!m_ruleListCSSOMWrapper) - m_ruleListCSSOMWrapper = adoptPtr(new LiveCSSRuleList<CSSGroupingRule>(const_cast<CSSGroupingRule*>(this))); + m_ruleListCSSOMWrapper = LiveCSSRuleList<CSSGroupingRule>::create(const_cast<CSSGroupingRule*>(this)); return m_ruleListCSSOMWrapper.get(); } @@ -149,4 +153,14 @@ void CSSGroupingRule::reattach(StyleRuleBase* rule) } } +void CSSGroupingRule::trace(Visitor* visitor) +{ + CSSRule::trace(visitor); +#if ENABLE(OILPAN) + visitor->trace(m_childRuleCSSOMWrappers); +#endif + visitor->trace(m_groupRule); + visitor->trace(m_ruleListCSSOMWrapper); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.h b/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.h index 9ba64484b95..cdc98da3477 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSGroupingRule.h @@ -47,14 +47,16 @@ public: unsigned length() const; CSSRule* item(unsigned index) const; + virtual void trace(Visitor*) OVERRIDE; + protected: CSSGroupingRule(StyleRuleGroup* groupRule, CSSStyleSheet* parent); void appendCSSTextForItems(StringBuilder&) const; - RefPtr<StyleRuleGroup> m_groupRule; - mutable Vector<RefPtr<CSSRule> > m_childRuleCSSOMWrappers; - mutable OwnPtr<CSSRuleList> m_ruleListCSSOMWrapper; + RefPtrWillBeMember<StyleRuleGroup> m_groupRule; + mutable WillBeHeapVector<RefPtrWillBeMember<CSSRule> > m_childRuleCSSOMWrappers; + mutable OwnPtrWillBeMember<CSSRuleList> m_ruleListCSSOMWrapper; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp index fa3f22a05e6..41b0ea18c95 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp @@ -44,9 +44,16 @@ CSSImageGeneratorValue::~CSSImageGeneratorValue() void CSSImageGeneratorValue::addClient(RenderObject* renderer, const IntSize& size) { + ASSERT(renderer); +#if !ENABLE(OILPAN) ref(); +#else + if (m_clients.isEmpty()) { + ASSERT(!m_keepAlive); + m_keepAlive = adoptPtr(new Persistent<CSSImageGeneratorValue>(this)); + } +#endif - ASSERT(renderer); if (!size.isEmpty()) m_sizes.add(size); @@ -77,7 +84,14 @@ void CSSImageGeneratorValue::removeClient(RenderObject* renderer) if (!--sizeCount.count) m_clients.remove(renderer); +#if !ENABLE(OILPAN) deref(); +#else + if (m_clients.isEmpty()) { + ASSERT(m_keepAlive); + m_keepAlive = nullptr; + } +#endif } Image* CSSImageGeneratorValue::getImage(RenderObject* renderer, const IntSize& size) @@ -87,7 +101,9 @@ Image* CSSImageGeneratorValue::getImage(RenderObject* renderer, const IntSize& s SizeAndCount& sizeCount = it->value; IntSize oldSize = sizeCount.size; if (oldSize != size) { +#if !ENABLE_OILPAN RefPtr<CSSImageGeneratorValue> protect(this); +#endif removeClient(renderer); addClient(renderer, size); } @@ -120,7 +136,7 @@ PassRefPtr<Image> CSSImageGeneratorValue::image(RenderObject* renderer, const In default: ASSERT_NOT_REACHED(); } - return 0; + return nullptr; } bool CSSImageGeneratorValue::isFixedSize() const diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h b/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h index d5803d3d52f..09b63b08cff 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h @@ -67,6 +67,8 @@ public: void loadSubimages(ResourceFetcher*); + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + protected: explicit CSSImageGeneratorValue(ClassType); @@ -77,6 +79,14 @@ protected: HashCountedSet<IntSize> m_sizes; // A count of how many times a given image size is in use. RenderObjectSizeCountMap m_clients; // A map from RenderObjects (with entry count) to image sizes. HashMap<IntSize, RefPtr<Image> > m_images; // A cache of Image objects by image size. + +#if ENABLE(OILPAN) + // FIXME: Oilpan: when/if we can make the renderer point directly to the CSSImageGenerator value using + // a member we don't need to have this hack where we keep a persistent to the instance as long as + // there are clients in the RenderObjectSizeCountMap. + GC_PLUGIN_IGNORE("366546") + OwnPtr<Persistent<CSSImageGeneratorValue> > m_keepAlive; +#endif }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSImageGeneratorValue, isImageGeneratorValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp index ef6321908a1..c081fbeea4c 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/css/CSSImageSetValue.h" -#include "FetchInitiatorTypeNames.h" +#include "core/FetchInitiatorTypeNames.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSPrimitiveValue.h" #include "core/dom/Document.h" @@ -57,8 +57,8 @@ void CSSImageSetValue::fillImageSet() size_t length = this->length(); size_t i = 0; while (i < length) { - CSSValue* imageValue = item(i); - String imageURL = toCSSImageValue(imageValue)->url(); + CSSImageValue* imageValue = toCSSImageValue(item(i)); + String imageURL = imageValue->url(); ++i; ASSERT_WITH_SECURITY_IMPLICATION(i < length); @@ -67,6 +67,7 @@ void CSSImageSetValue::fillImageSet() ImageWithScale image; image.imageURL = imageURL; + image.referrer = imageValue->referrer(); image.scaleFactor = scaleFactor; m_imagesInSet.append(image); ++i; @@ -88,7 +89,7 @@ CSSImageSetValue::ImageWithScale CSSImageSetValue::bestImageForScaleFactor() return image; } -StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* loader, float deviceScaleFactor) +StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* loader, float deviceScaleFactor, const ResourceLoaderOptions& options) { ASSERT(loader); @@ -99,11 +100,16 @@ StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* loader, if (!m_accessedBestFitImage) { // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here. - // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(), + // All forms of scale should be included: Page::pageScaleFactor(), LocalFrame::pageZoomFactor(), // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698 ImageWithScale image = bestImageForScaleFactor(); if (Document* document = loader->document()) { - FetchRequest request(ResourceRequest(document->completeURL(image.imageURL)), FetchInitiatorTypeNames::css); + FetchRequest request(ResourceRequest(document->completeURL(image.imageURL)), FetchInitiatorTypeNames::css, options); + request.mutableResourceRequest().setHTTPReferrer(image.referrer); + + if (options.corsEnabled == IsCORSEnabled) + request.setCrossOriginAccessControl(loader->document()->securityOrigin(), options.allowCredentials, options.credentialsRequested); + if (ResourcePtr<ImageResource> cachedImage = loader->fetchImage(request)) { m_imageSet = StyleFetchedImageSet::create(cachedImage.get(), image.scaleFactor, this); m_accessedBestFitImage = true; @@ -114,6 +120,11 @@ StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* loader, return (m_imageSet && m_imageSet->isImageResourceSet()) ? toStyleFetchedImageSet(m_imageSet) : 0; } +StyleFetchedImageSet* CSSImageSetValue::cachedImageSet(ResourceFetcher* fetcher, float deviceScaleFactor) +{ + return cachedImageSet(fetcher, deviceScaleFactor, ResourceFetcher::defaultResourceOptions()); +} + StyleImage* CSSImageSetValue::cachedOrPendingImageSet(float deviceScaleFactor) { if (!m_imageSet) { @@ -176,9 +187,9 @@ CSSImageSetValue::CSSImageSetValue(const CSSImageSetValue& cloneFrom) // Non-CSSValueList data is not accessible through CSS OM, no need to clone. } -PassRefPtr<CSSImageSetValue> CSSImageSetValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSImageSetValue> CSSImageSetValue::cloneForCSSOM() const { - return adoptRef(new CSSImageSetValue(*this)); + return adoptRefWillBeNoop(new CSSImageSetValue(*this)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.h b/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.h index ee6e86b4313..2b9ea861607 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSImageSetValue.h @@ -27,6 +27,8 @@ #define CSSImageSetValue_h #include "core/css/CSSValueList.h" +#include "core/fetch/ResourceFetcher.h" +#include "platform/weborigin/Referrer.h" namespace WebCore { @@ -37,12 +39,13 @@ class StyleImage; class CSSImageSetValue : public CSSValueList { public: - static PassRefPtr<CSSImageSetValue> create() + static PassRefPtrWillBeRawPtr<CSSImageSetValue> create() { - return adoptRef(new CSSImageSetValue()); + return adoptRefWillBeNoop(new CSSImageSetValue()); } ~CSSImageSetValue(); + StyleFetchedImageSet* cachedImageSet(ResourceFetcher*, float deviceScaleFactor, const ResourceLoaderOptions&); StyleFetchedImageSet* cachedImageSet(ResourceFetcher*, float deviceScaleFactor); // Returns a StyleFetchedImageSet if the best fit image has been cached already, otherwise a StylePendingImage. @@ -54,12 +57,15 @@ public: struct ImageWithScale { String imageURL; + Referrer referrer; float scaleFactor; }; bool hasFailedOrCanceledSubresources() const; - PassRefPtr<CSSImageSetValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSImageSetValue> cloneForCSSOM() const; + + void traceAfterDispatch(Visitor* visitor) { CSSValueList::traceAfterDispatch(visitor); } protected: ImageWithScale bestImageForScaleFactor(); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImageValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSImageValue.cpp index 4dd0799e101..7163e58c6f6 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImageValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSImageValue.cpp @@ -21,29 +21,24 @@ #include "config.h" #include "core/css/CSSImageValue.h" -#include "FetchInitiatorTypeNames.h" -#include "core/css/CSSParser.h" +#include "core/FetchInitiatorTypeNames.h" +#include "core/css/CSSMarkup.h" #include "core/dom/Document.h" #include "core/fetch/CrossOriginAccessControl.h" #include "core/fetch/FetchRequest.h" #include "core/fetch/ImageResource.h" #include "core/rendering/style/StyleFetchedImage.h" #include "core/rendering/style/StylePendingImage.h" +#include "platform/weborigin/KURL.h" namespace WebCore { -CSSImageValue::CSSImageValue(const String& url) +CSSImageValue::CSSImageValue(const String& rawValue, const KURL& url, StyleImage* image) : CSSValue(ImageClass) - , m_url(url) - , m_accessedImage(false) -{ -} - -CSSImageValue::CSSImageValue(const String& url, StyleImage* image) - : CSSValue(ImageClass) - , m_url(url) + , m_relativeURL(rawValue) + , m_absoluteURL(url.string()) , m_image(image) - , m_accessedImage(true) + , m_accessedImage(image) { } @@ -59,17 +54,18 @@ StyleImage* CSSImageValue::cachedOrPendingImage() return m_image.get(); } -StyleFetchedImage* CSSImageValue::cachedImage(ResourceFetcher* fetcher, const ResourceLoaderOptions& options, CORSEnabled corsEnabled) +StyleFetchedImage* CSSImageValue::cachedImage(ResourceFetcher* fetcher, const ResourceLoaderOptions& options) { ASSERT(fetcher); if (!m_accessedImage) { m_accessedImage = true; - FetchRequest request(ResourceRequest(fetcher->document()->completeURL(m_url)), m_initiatorName.isEmpty() ? FetchInitiatorTypeNames::css : m_initiatorName, options); + FetchRequest request(ResourceRequest(m_absoluteURL), m_initiatorName.isEmpty() ? FetchInitiatorTypeNames::css : m_initiatorName, options); + request.mutableResourceRequest().setHTTPReferrer(m_referrer); - if (corsEnabled == PotentiallyCORSEnabled) - updateRequestForAccessControl(request.mutableResourceRequest(), fetcher->document()->securityOrigin(), options.allowCredentials); + if (options.corsEnabled == IsCORSEnabled) + request.setCrossOriginAccessControl(fetcher->document()->securityOrigin(), options.allowCredentials, options.credentialsRequested); if (ResourcePtr<ImageResource> cachedImage = fetcher->fetchImage(request)) m_image = StyleFetchedImage::create(cachedImage.get()); @@ -78,6 +74,21 @@ StyleFetchedImage* CSSImageValue::cachedImage(ResourceFetcher* fetcher, const Re return (m_image && m_image->isImageResource()) ? toStyleFetchedImage(m_image) : 0; } +void CSSImageValue::restoreCachedResourceIfNeeded(Document& document) +{ + if (!m_accessedImage || !m_image->isImageResource() || !document.fetcher()) + return; + if (document.fetcher()->cachedResource(KURL(ParsedURLString, m_absoluteURL))) + return; + + ImageResource* resource = m_image->cachedImage(); + if (!resource) + return; + + FetchRequest request(ResourceRequest(m_absoluteURL), m_initiatorName.isEmpty() ? FetchInitiatorTypeNames::css : m_initiatorName, resource->options()); + document.fetcher()->requestLoadStarted(resource, request, ResourceFetcher::ResourceLoadingFromCache); +} + bool CSSImageValue::hasFailedOrCanceledSubresources() const { if (!m_image || !m_image->isImageResource()) @@ -89,18 +100,18 @@ bool CSSImageValue::hasFailedOrCanceledSubresources() const bool CSSImageValue::equals(const CSSImageValue& other) const { - return m_url == other.m_url; + return m_absoluteURL == other.m_absoluteURL; } String CSSImageValue::customCSSText() const { - return "url(" + quoteCSSURLIfNeeded(m_url) + ")"; + return "url(" + quoteCSSURLIfNeeded(m_absoluteURL) + ")"; } -PassRefPtr<CSSValue> CSSImageValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSValue> CSSImageValue::cloneForCSSOM() const { // NOTE: We expose CSSImageValues as URI primitive values in CSSOM to maintain old behavior. - RefPtr<CSSPrimitiveValue> uriValue = CSSPrimitiveValue::create(m_url, CSSPrimitiveValue::CSS_URI); + RefPtrWillBeRawPtr<CSSPrimitiveValue> uriValue = CSSPrimitiveValue::create(m_absoluteURL, CSSPrimitiveValue::CSS_URI); uriValue->setCSSOMSafe(); return uriValue.release(); } @@ -110,4 +121,19 @@ bool CSSImageValue::knownToBeOpaque(const RenderObject* renderer) const return m_image ? m_image->knownToBeOpaque(renderer) : false; } +void CSSImageValue::traceAfterDispatch(Visitor* visitor) +{ + CSSValue::traceAfterDispatch(visitor); +} + +void CSSImageValue::reResolveURL(const Document& document) +{ + KURL url = document.completeURL(m_relativeURL); + if (url == m_absoluteURL) + return; + m_absoluteURL = url.string(); + m_accessedImage = false; + m_image.clear(); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImageValue.h b/chromium/third_party/WebKit/Source/core/css/CSSImageValue.h index a84afa5947a..4dce66191bb 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImageValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSImageValue.h @@ -23,31 +23,45 @@ #include "core/css/CSSValue.h" #include "core/fetch/ResourceFetcher.h" +#include "platform/weborigin/Referrer.h" #include "wtf/RefPtr.h" namespace WebCore { +class Document; class Element; +class KURL; class StyleFetchedImage; class StyleImage; class RenderObject; class CSSImageValue : public CSSValue { public: - static PassRefPtr<CSSImageValue> create(const String& url) { return adoptRef(new CSSImageValue(url)); } - static PassRefPtr<CSSImageValue> create(const String& url, StyleImage* image) { return adoptRef(new CSSImageValue(url, image)); } + static PassRefPtrWillBeRawPtr<CSSImageValue> create(const KURL& url, StyleImage* image = 0) + { + return adoptRefWillBeNoop(new CSSImageValue(url, url, image)); + } + static PassRefPtrWillBeRawPtr<CSSImageValue> create(const String& rawValue, const KURL& url, StyleImage* image = 0) + { + return adoptRefWillBeNoop(new CSSImageValue(rawValue, url, image)); + } ~CSSImageValue(); - StyleFetchedImage* cachedImage(ResourceFetcher*, const ResourceLoaderOptions&, CORSEnabled); - StyleFetchedImage* cachedImage(ResourceFetcher* fetcher) { return cachedImage(fetcher, ResourceFetcher::defaultResourceOptions(), NotCORSEnabled); } + StyleFetchedImage* cachedImage(ResourceFetcher*, const ResourceLoaderOptions&); + StyleFetchedImage* cachedImage(ResourceFetcher* fetcher) { return cachedImage(fetcher, ResourceFetcher::defaultResourceOptions()); } // Returns a StyleFetchedImage if the image is cached already, otherwise a StylePendingImage. StyleImage* cachedOrPendingImage(); - const String& url() { return m_url; } + const String& url() { return m_absoluteURL; } + + void setReferrer(const Referrer& referrer) { m_referrer = referrer; } + const Referrer& referrer() const { return m_referrer; } + + void reResolveURL(const Document&); String customCSSText() const; - PassRefPtr<CSSValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSValue> cloneForCSSOM() const; bool hasFailedOrCanceledSubresources() const; @@ -57,11 +71,15 @@ public: void setInitiator(const AtomicString& name) { m_initiatorName = name; } + void traceAfterDispatch(Visitor*); + void restoreCachedResourceIfNeeded(Document&); + private: - explicit CSSImageValue(const String& url); - CSSImageValue(const String& url, StyleImage*); + CSSImageValue(const String& rawValue, const KURL&, StyleImage*); - String m_url; + String m_relativeURL; + String m_absoluteURL; + Referrer m_referrer; RefPtr<StyleImage> m_image; bool m_accessedImage; AtomicString m_initiatorName; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImportRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSImportRule.cpp index cf733f70f3c..e7d6219cbc1 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImportRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSImportRule.cpp @@ -38,10 +38,13 @@ CSSImportRule::CSSImportRule(StyleRuleImport* importRule, CSSStyleSheet* parent) CSSImportRule::~CSSImportRule() { +#if !ENABLE(OILPAN) if (m_styleSheetCSSOMWrapper) m_styleSheetCSSOMWrapper->clearOwnerRule(); + if (m_mediaCSSOMWrapper) m_mediaCSSOMWrapper->clearParentRule(); +#endif // ENABLE(OILPAN) } String CSSImportRule::href() const @@ -91,4 +94,12 @@ void CSSImportRule::reattach(StyleRuleBase*) ASSERT_NOT_REACHED(); } +void CSSImportRule::trace(Visitor* visitor) +{ + visitor->trace(m_importRule); + visitor->trace(m_mediaCSSOMWrapper); + visitor->trace(m_styleSheetCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSImportRule.h b/chromium/third_party/WebKit/Source/core/css/CSSImportRule.h index 0abfc9a3284..117e60de469 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSImportRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSImportRule.h @@ -23,6 +23,7 @@ #define CSSImportRule_h #include "core/css/CSSRule.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -31,9 +32,12 @@ class MediaList; class MediaQuerySet; class StyleRuleImport; -class CSSImportRule : public CSSRule { +class CSSImportRule FINAL : public CSSRule { public: - static PassRefPtr<CSSImportRule> create(StyleRuleImport* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSImportRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSImportRule> create(StyleRuleImport* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSImportRule(rule, sheet)); + } virtual ~CSSImportRule(); @@ -45,12 +49,14 @@ public: MediaList* media() const; CSSStyleSheet* styleSheet() const; + virtual void trace(Visitor*) OVERRIDE; + private: CSSImportRule(StyleRuleImport*, CSSStyleSheet*); - RefPtr<StyleRuleImport> m_importRule; - mutable RefPtr<MediaList> m_mediaCSSOMWrapper; - mutable RefPtr<CSSStyleSheet> m_styleSheetCSSOMWrapper; + RefPtrWillBeMember<StyleRuleImport> m_importRule; + mutable RefPtrWillBeMember<MediaList> m_mediaCSSOMWrapper; + mutable RefPtrWillBeMember<CSSStyleSheet> m_styleSheetCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSImportRule, IMPORT_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSInheritedValue.h b/chromium/third_party/WebKit/Source/core/css/CSSInheritedValue.h index 7367707daf6..8f1fe97225a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSInheritedValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSInheritedValue.h @@ -28,15 +28,17 @@ namespace WebCore { class CSSInheritedValue : public CSSValue { public: - static PassRefPtr<CSSInheritedValue> create() + static PassRefPtrWillBeRawPtr<CSSInheritedValue> create() { - return adoptRef(new CSSInheritedValue); + return adoptRefWillBeNoop(new CSSInheritedValue); } String customCSSText() const; bool equals(const CSSInheritedValue&) const { return true; } + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSInheritedValue() : CSSValue(InheritedClass) diff --git a/chromium/third_party/WebKit/Source/core/css/CSSInitialValue.h b/chromium/third_party/WebKit/Source/core/css/CSSInitialValue.h index f8f9e512fce..43d82de9631 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSInitialValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSInitialValue.h @@ -28,13 +28,13 @@ namespace WebCore { class CSSInitialValue : public CSSValue { public: - static PassRefPtr<CSSInitialValue> createExplicit() + static PassRefPtrWillBeRawPtr<CSSInitialValue> createExplicit() { - return adoptRef(new CSSInitialValue(/* implicit */ false)); + return adoptRefWillBeNoop(new CSSInitialValue(/* implicit */ false)); } - static PassRefPtr<CSSInitialValue> createImplicit() + static PassRefPtrWillBeRawPtr<CSSInitialValue> createImplicit() { - return adoptRef(new CSSInitialValue(/* implicit */ true)); + return adoptRefWillBeNoop(new CSSInitialValue(/* implicit */ true)); } String customCSSText() const; @@ -43,6 +43,8 @@ public: bool equals(const CSSInitialValue&) const { return true; } + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: explicit CSSInitialValue(bool implicit) : CSSValue(InitialClass) diff --git a/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.cpp index 65aa3077c93..34e395660ad 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.cpp @@ -27,9 +27,10 @@ #include "core/css/CSSKeyframeRule.h" #include "core/css/CSSKeyframesRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/PropertySetCSSStyleDeclaration.h" #include "core/css/StylePropertySet.h" +#include "core/frame/UseCounter.h" #include "wtf/text/StringBuilder.h" namespace WebCore { @@ -76,7 +77,7 @@ const Vector<double>& StyleKeyframe::keys() const // Keys can only be cleared by setting the key text from JavaScript // and this can never be null. ASSERT(!m_keyText.isNull()); - m_keys = CSSParser(HTMLStandardMode).parseKeyframeKeyList(m_keyText); + m_keys = BisonCSSParser(strictCSSParserContext()).parseKeyframeKeyList(m_keyText); } // If an invalid key string was set, m_keys may be empty. ASSERT(m_keys); @@ -91,15 +92,16 @@ void StyleKeyframe::setKeys(PassOwnPtr<Vector<double> > keys) ASSERT(m_keyText.isNull()); } -MutableStylePropertySet* StyleKeyframe::mutableProperties() +MutableStylePropertySet& StyleKeyframe::mutableProperties() { if (!m_properties->isMutable()) m_properties = m_properties->mutableCopy(); - return toMutableStylePropertySet(m_properties); + return *toMutableStylePropertySet(m_properties); } void StyleKeyframe::setProperties(PassRefPtr<StylePropertySet> properties) { + ASSERT(properties); m_properties = properties; } @@ -144,8 +146,10 @@ CSSKeyframeRule::CSSKeyframeRule(StyleKeyframe* keyframe, CSSKeyframesRule* pare CSSKeyframeRule::~CSSKeyframeRule() { +#if !ENABLE(OILPAN) if (m_propertiesCSSOMWrapper) m_propertiesCSSOMWrapper->clearParentRule(); +#endif } CSSStyleDeclaration* CSSKeyframeRule::style() const @@ -161,4 +165,11 @@ void CSSKeyframeRule::reattach(StyleRuleBase*) ASSERT_NOT_REACHED(); } +void CSSKeyframeRule::trace(Visitor* visitor) +{ + visitor->trace(m_keyframe); + visitor->trace(m_propertiesCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.h b/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.h index 594314808f9..48f1bfaf0a5 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSKeyframeRule.h @@ -37,12 +37,12 @@ class MutableStylePropertySet; class StylePropertySet; class StyleRuleCSSStyleDeclaration; -class StyleKeyframe FINAL : public RefCounted<StyleKeyframe> { - WTF_MAKE_FAST_ALLOCATED; +class StyleKeyframe FINAL : public RefCountedWillBeGarbageCollectedFinalized<StyleKeyframe> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<StyleKeyframe> create() + static PassRefPtrWillBeRawPtr<StyleKeyframe> create() { - return adoptRef(new StyleKeyframe()); + return adoptRefWillBeNoop(new StyleKeyframe()); } ~StyleKeyframe(); @@ -52,15 +52,17 @@ public: // Used by StyleResolver. const Vector<double>& keys() const; - // Used by CSSParser when constructing a new StyleKeyframe. + // Used by BisonCSSParser when constructing a new StyleKeyframe. void setKeys(PassOwnPtr<Vector<double> >); - const StylePropertySet* properties() const { return m_properties.get(); } - MutableStylePropertySet* mutableProperties(); + const StylePropertySet& properties() const { return *m_properties; } + MutableStylePropertySet& mutableProperties(); void setProperties(PassRefPtr<StylePropertySet>); String cssText() const; + void trace(Visitor*) { } + static PassOwnPtr<Vector<double> > createKeyList(CSSParserValueList*); private: @@ -85,11 +87,13 @@ public: CSSStyleDeclaration* style() const; + virtual void trace(Visitor*) OVERRIDE; + private: CSSKeyframeRule(StyleKeyframe*, CSSKeyframesRule* parent); - RefPtr<StyleKeyframe> m_keyframe; - mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; + RefPtrWillBeMember<StyleKeyframe> m_keyframe; + mutable RefPtrWillBeMember<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; friend class CSSKeyframesRule; }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp index 94d5dff8e6a..cd78e79f272 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.cpp @@ -27,9 +27,10 @@ #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSKeyframeRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSRuleList.h" #include "core/css/CSSStyleSheet.h" +#include "core/frame/UseCounter.h" #include "wtf/text/StringBuilder.h" namespace WebCore { @@ -51,14 +52,14 @@ StyleRuleKeyframes::~StyleRuleKeyframes() { } -void StyleRuleKeyframes::parserAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe) +void StyleRuleKeyframes::parserAppendKeyframe(PassRefPtrWillBeRawPtr<StyleKeyframe> keyframe) { if (!keyframe) return; m_keyframes.append(keyframe); } -void StyleRuleKeyframes::wrapperAppendKeyframe(PassRefPtr<StyleKeyframe> keyframe) +void StyleRuleKeyframes::wrapperAppendKeyframe(PassRefPtrWillBeRawPtr<StyleKeyframe> keyframe) { m_keyframes.append(keyframe); } @@ -85,6 +86,12 @@ int StyleRuleKeyframes::findKeyframeIndex(const String& key) const return -1; } +void StyleRuleKeyframes::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_keyframes); + StyleRuleBase::traceAfterDispatch(visitor); +} + CSSKeyframesRule::CSSKeyframesRule(StyleRuleKeyframes* keyframesRule, CSSStyleSheet* parent) : CSSRule(parent) , m_keyframesRule(keyframesRule) @@ -95,12 +102,13 @@ CSSKeyframesRule::CSSKeyframesRule(StyleRuleKeyframes* keyframesRule, CSSStyleSh CSSKeyframesRule::~CSSKeyframesRule() { +#if !ENABLE(OILPAN) ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size()); - for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { if (m_childRuleCSSOMWrappers[i]) m_childRuleCSSOMWrappers[i]->setParentRule(0); } +#endif } void CSSKeyframesRule::setName(const String& name) @@ -115,8 +123,9 @@ void CSSKeyframesRule::insertRule(const String& ruleText) ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size()); CSSStyleSheet* styleSheet = parentStyleSheet(); - CSSParser parser(parserContext(), UseCounter::getFrom(styleSheet)); - RefPtr<StyleKeyframe> keyframe = parser.parseKeyframeRule(styleSheet ? styleSheet->contents() : 0, ruleText); + CSSParserContext context(parserContext(), UseCounter::getFrom(styleSheet)); + BisonCSSParser parser(context); + RefPtrWillBeRawPtr<StyleKeyframe> keyframe = parser.parseKeyframeRule(styleSheet ? styleSheet->contents() : 0, ruleText); if (!keyframe) return; @@ -181,9 +190,9 @@ CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const return 0; ASSERT(m_childRuleCSSOMWrappers.size() == m_keyframesRule->keyframes().size()); - RefPtr<CSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index]; + RefPtrWillBeMember<CSSKeyframeRule>& rule = m_childRuleCSSOMWrappers[index]; if (!rule) - rule = adoptRef(new CSSKeyframeRule(m_keyframesRule->keyframes()[index].get(), const_cast<CSSKeyframesRule*>(this))); + rule = adoptRefWillBeNoop(new CSSKeyframeRule(m_keyframesRule->keyframes()[index].get(), const_cast<CSSKeyframesRule*>(this))); return rule.get(); } @@ -191,7 +200,7 @@ CSSKeyframeRule* CSSKeyframesRule::item(unsigned index) const CSSRuleList* CSSKeyframesRule::cssRules() { if (!m_ruleListCSSOMWrapper) - m_ruleListCSSOMWrapper = adoptPtr(new LiveCSSRuleList<CSSKeyframesRule>(this)); + m_ruleListCSSOMWrapper = LiveCSSRuleList<CSSKeyframesRule>::create(this); return m_ruleListCSSOMWrapper.get(); } @@ -201,4 +210,14 @@ void CSSKeyframesRule::reattach(StyleRuleBase* rule) m_keyframesRule = toStyleRuleKeyframes(rule); } +void CSSKeyframesRule::trace(Visitor* visitor) +{ + CSSRule::trace(visitor); +#if ENABLE(OILPAN) + visitor->trace(m_childRuleCSSOMWrappers); +#endif + visitor->trace(m_keyframesRule); + visitor->trace(m_ruleListCSSOMWrapper); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.h b/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.h index d74cf686e75..aebdc196933 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.h @@ -39,14 +39,14 @@ class CSSKeyframeRule; class StyleRuleKeyframes FINAL : public StyleRuleBase { public: - static PassRefPtr<StyleRuleKeyframes> create() { return adoptRef(new StyleRuleKeyframes()); } + static PassRefPtrWillBeRawPtr<StyleRuleKeyframes> create() { return adoptRefWillBeNoop(new StyleRuleKeyframes()); } ~StyleRuleKeyframes(); - const Vector<RefPtr<StyleKeyframe> >& keyframes() const { return m_keyframes; } + const WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >& keyframes() const { return m_keyframes; } - void parserAppendKeyframe(PassRefPtr<StyleKeyframe>); - void wrapperAppendKeyframe(PassRefPtr<StyleKeyframe>); + void parserAppendKeyframe(PassRefPtrWillBeRawPtr<StyleKeyframe>); + void wrapperAppendKeyframe(PassRefPtrWillBeRawPtr<StyleKeyframe>); void wrapperRemoveKeyframe(unsigned); String name() const { return m_name; } @@ -57,13 +57,15 @@ public: int findKeyframeIndex(const String& key) const; - PassRefPtr<StyleRuleKeyframes> copy() const { return adoptRef(new StyleRuleKeyframes(*this)); } + PassRefPtrWillBeRawPtr<StyleRuleKeyframes> copy() const { return adoptRefWillBeNoop(new StyleRuleKeyframes(*this)); } + + void traceAfterDispatch(Visitor*); private: StyleRuleKeyframes(); explicit StyleRuleKeyframes(const StyleRuleKeyframes&); - Vector<RefPtr<StyleKeyframe> > m_keyframes; + WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > m_keyframes; AtomicString m_name; bool m_isPrefixed; }; @@ -72,7 +74,10 @@ DEFINE_STYLE_RULE_TYPE_CASTS(Keyframes); class CSSKeyframesRule FINAL : public CSSRule { public: - static PassRefPtr<CSSKeyframesRule> create(StyleRuleKeyframes* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSKeyframesRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSKeyframesRule> create(StyleRuleKeyframes* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSKeyframesRule(rule, sheet)); + } virtual ~CSSKeyframesRule(); @@ -96,12 +101,14 @@ public: bool isVendorPrefixed() const { return m_isPrefixed; } void setVendorPrefixed(bool isPrefixed) { m_isPrefixed = isPrefixed; } + virtual void trace(Visitor*) OVERRIDE; + private: CSSKeyframesRule(StyleRuleKeyframes*, CSSStyleSheet* parent); - RefPtr<StyleRuleKeyframes> m_keyframesRule; - mutable Vector<RefPtr<CSSKeyframeRule> > m_childRuleCSSOMWrappers; - mutable OwnPtr<CSSRuleList> m_ruleListCSSOMWrapper; + RefPtrWillBeMember<StyleRuleKeyframes> m_keyframesRule; + mutable WillBeHeapVector<RefPtrWillBeMember<CSSKeyframeRule> > m_childRuleCSSOMWrappers; + mutable OwnPtrWillBeMember<CSSRuleList> m_ruleListCSSOMWrapper; bool m_isPrefixed; }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl b/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl index d97dd4aae3b..d85f8d19f17 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSKeyframesRule.idl @@ -31,7 +31,7 @@ interface CSSKeyframesRule : CSSRule { attribute DOMString name; readonly attribute CSSRuleList cssRules; - [ImplementedAs=item, NotEnumerable] getter CSSKeyframeRule(unsigned long index); + [ImplementedAs=item, NotEnumerable] getter CSSKeyframeRule (unsigned long index); void insertRule([Default=Undefined] optional DOMString rule); void deleteRule([Default=Undefined] optional DOMString key); CSSKeyframeRule findRule([Default=Undefined] optional DOMString key); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSLengthFunctions.cpp b/chromium/third_party/WebKit/Source/core/css/CSSLengthFunctions.cpp deleted file mode 100644 index 94acda3c866..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSLengthFunctions.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (C) 1999 Lars Knoll (knoll@kde.org) - Copyright (C) 2006, 2008 Apple Inc. All rights reserved. - Copyright (C) 2011 Rik Cabanier (cabanier@adobe.com) - Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - Copyright (C) 2012 Motorola Mobility, Inc. All rights reserved. - Copyright (C) 2013 Google, Inc. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - 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. -*/ - -#include "config.h" -#include "core/css/CSSLengthFunctions.h" - -#include "core/rendering/RenderView.h" -#include "platform/LayoutUnit.h" -#include "platform/Length.h" -#include "platform/LengthFunctions.h" - -namespace WebCore { - -int minimumIntValueForLength(const Length& length, LayoutUnit maximumValue, RenderView* renderView, bool roundPercentages) -{ - return static_cast<int>(minimumValueForLength(length, maximumValue, renderView, roundPercentages)); -} - -int intValueForLength(const Length& length, LayoutUnit maximumValue, RenderView* renderView, bool roundPercentages) -{ - return static_cast<int>(valueForLength(length, maximumValue, renderView, roundPercentages)); -} - -LayoutUnit minimumValueForLength(const Length& length, LayoutUnit maximumValue, RenderView* renderView, bool roundPercentages) -{ - switch (length.type()) { - case Fixed: - return length.value(); - case Percent: - if (roundPercentages) - return static_cast<LayoutUnit>(round(maximumValue * length.percent() / 100.0f)); - // Don't remove the extra cast to float. It is needed for rounding on 32-bit Intel machines that use the FPU stack. - return static_cast<float>(maximumValue * length.percent() / 100.0f); - case Calculated: - return length.nonNanCalculatedValue(maximumValue); - case ViewportPercentageWidth: - return renderView ? renderView->viewportPercentageWidth(length.viewportPercentageLength()) : LayoutUnit(0); - case ViewportPercentageHeight: - return renderView ? renderView->viewportPercentageHeight(length.viewportPercentageLength()) : LayoutUnit(0); - case ViewportPercentageMin: - return renderView ? renderView->viewportPercentageMin(length.viewportPercentageLength()) : LayoutUnit(0); - case ViewportPercentageMax: - return renderView ? renderView->viewportPercentageMax(length.viewportPercentageLength()) : LayoutUnit(0); - case FillAvailable: - case Auto: - return 0; - case Intrinsic: - case MinIntrinsic: - case MinContent: - case MaxContent: - case FitContent: - case ExtendToZoom: - case Undefined: - ASSERT_NOT_REACHED(); - return 0; - } - ASSERT_NOT_REACHED(); - return 0; -} - -LayoutUnit valueForLength(const Length& length, LayoutUnit maximumValue, RenderView* renderView, bool roundPercentages) -{ - switch (length.type()) { - case Fixed: - case Percent: - case Calculated: - case ViewportPercentageWidth: - case ViewportPercentageHeight: - case ViewportPercentageMin: - case ViewportPercentageMax: - return minimumValueForLength(length, maximumValue, renderView, roundPercentages); - case FillAvailable: - case Auto: - return maximumValue; - case Intrinsic: - case MinIntrinsic: - case MinContent: - case MaxContent: - case FitContent: - case ExtendToZoom: - case Undefined: - ASSERT_NOT_REACHED(); - return 0; - } - ASSERT_NOT_REACHED(); - return 0; -} - -// This method has code duplicated in platform/LengthFunctions.cpp. -// Any changes here most likely also need to be applied there. -float floatValueForLength(const Length& length, float maximumValue, RenderView* renderView) -{ - if (!renderView) - return floatValueForLength(length, maximumValue); - - switch (length.type()) { - case Fixed: - return length.getFloatValue(); - case Percent: - return static_cast<float>(maximumValue * length.percent() / 100.0f); - case FillAvailable: - case Auto: - return static_cast<float>(maximumValue); - case Calculated: - return length.nonNanCalculatedValue(maximumValue); - case ViewportPercentageWidth: - return static_cast<int>(renderView->viewportPercentageWidth(length.viewportPercentageLength())); - case ViewportPercentageHeight: - return static_cast<int>(renderView->viewportPercentageHeight(length.viewportPercentageLength())); - case ViewportPercentageMin: - return static_cast<int>(renderView->viewportPercentageMin(length.viewportPercentageLength())); - case ViewportPercentageMax: - return static_cast<int>(renderView->viewportPercentageMax(length.viewportPercentageLength())); - case Intrinsic: - case MinIntrinsic: - case MinContent: - case MaxContent: - case FitContent: - case ExtendToZoom: - case Undefined: - ASSERT_NOT_REACHED(); - return 0; - } - ASSERT_NOT_REACHED(); - return 0; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSLengthFunctions.h b/chromium/third_party/WebKit/Source/core/css/CSSLengthFunctions.h deleted file mode 100644 index 46e3540c180..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSLengthFunctions.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 1999 Lars Knoll (knoll@kde.org) - Copyright (C) 2006, 2008 Apple Inc. All rights reserved. - Copyright (C) 2011 Rik Cabanier (cabanier@adobe.com) - Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - Copyright (C) 2012 Motorola Mobility, Inc. All rights reserved. - Copyright (C) 2013 Google, Inc. All rights reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - 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 CSSLengthFunctions_h -#define CSSLengthFunctions_h - -namespace WebCore { - -class LayoutUnit; -class Length; -class RenderView; - -int minimumIntValueForLength(const Length&, LayoutUnit maximumValue, RenderView* = 0, bool roundPercentages = false); -int intValueForLength(const Length&, LayoutUnit maximumValue, RenderView* = 0, bool roundPercentages = false); -LayoutUnit minimumValueForLength(const Length&, LayoutUnit maximumValue, RenderView* = 0, bool roundPercentages = false); -LayoutUnit valueForLength(const Length&, LayoutUnit maximumValue, RenderView* = 0, bool roundPercentages = false); -float floatValueForLength(const Length&, float maximumValue, RenderView*); - -} // namespace WebCore - -#endif // CSSLengthFunctions_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSLineBoxContainValue.h b/chromium/third_party/WebKit/Source/core/css/CSSLineBoxContainValue.h index 657578ab251..92d6de2203f 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSLineBoxContainValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSLineBoxContainValue.h @@ -40,15 +40,17 @@ typedef unsigned LineBoxContain; // Used for text-CSSLineBoxContain and box-CSSLineBoxContain class CSSLineBoxContainValue : public CSSValue { public: - static PassRefPtr<CSSLineBoxContainValue> create(LineBoxContain value) + static PassRefPtrWillBeRawPtr<CSSLineBoxContainValue> create(LineBoxContain value) { - return adoptRef(new CSSLineBoxContainValue(value)); + return adoptRefWillBeNoop(new CSSLineBoxContainValue(value)); } String customCSSText() const; bool equals(const CSSLineBoxContainValue& other) const { return m_value == other.m_value; } LineBoxContain value() const { return m_value; } + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: LineBoxContain m_value; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMarkup.cpp b/chromium/third_party/WebKit/Source/core/css/CSSMarkup.cpp new file mode 100644 index 00000000000..cc473538a06 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/CSSMarkup.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * 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. + */ + +#include "config.h" +#include "core/css/CSSMarkup.h" + +#include "wtf/HexNumber.h" +#include "wtf/text/StringBuffer.h" + +namespace WebCore { + +template <typename CharacterType> +static inline bool isCSSTokenizerIdentifier(const CharacterType* characters, unsigned length) +{ + const CharacterType* end = characters + length; + + // -? + if (characters != end && characters[0] == '-') + ++characters; + + // {nmstart} + if (characters == end || !(characters[0] == '_' || characters[0] >= 128 || isASCIIAlpha(characters[0]))) + return false; + ++characters; + + // {nmchar}* + for (; characters != end; ++characters) { + if (!(characters[0] == '_' || characters[0] == '-' || characters[0] >= 128 || isASCIIAlphanumeric(characters[0]))) + return false; + } + + return true; +} + +// "ident" from the CSS tokenizer, minus backslash-escape sequences +static bool isCSSTokenizerIdentifier(const String& string) +{ + unsigned length = string.length(); + + if (!length) + return false; + + if (string.is8Bit()) + return isCSSTokenizerIdentifier(string.characters8(), length); + return isCSSTokenizerIdentifier(string.characters16(), length); +} + +template <typename CharacterType> +static inline bool isCSSTokenizerURL(const CharacterType* characters, unsigned length) +{ + const CharacterType* end = characters + length; + + for (; characters != end; ++characters) { + CharacterType c = characters[0]; + switch (c) { + case '!': + case '#': + case '$': + case '%': + case '&': + break; + default: + if (c < '*') + return false; + if (c <= '~') + break; + if (c < 128) + return false; + } + } + + return true; +} + +// "url" from the CSS tokenizer, minus backslash-escape sequences +static bool isCSSTokenizerURL(const String& string) +{ + unsigned length = string.length(); + + if (!length) + return true; + + if (string.is8Bit()) + return isCSSTokenizerURL(string.characters8(), length); + return isCSSTokenizerURL(string.characters16(), length); +} + +template <typename CharacterType> +static inline String quoteCSSStringInternal(const CharacterType* characters, unsigned length) +{ + // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one. + // Please see below for the actual logic. + unsigned quotedStringSize = 2; // Two quotes surrounding the entire string. + bool afterEscape = false; + for (unsigned i = 0; i < length; ++i) { + CharacterType ch = characters[i]; + if (ch == '\\' || ch == '\'') { + quotedStringSize += 2; + afterEscape = false; + } else if (ch < 0x20 || ch == 0x7F) { + quotedStringSize += 2 + (ch >= 0x10); + afterEscape = true; + } else { + quotedStringSize += 1 + (afterEscape && (isASCIIHexDigit(ch) || ch == ' ')); + afterEscape = false; + } + } + + StringBuffer<CharacterType> buffer(quotedStringSize); + unsigned index = 0; + buffer[index++] = '\''; + afterEscape = false; + for (unsigned i = 0; i < length; ++i) { + CharacterType ch = characters[i]; + if (ch == '\\' || ch == '\'') { + buffer[index++] = '\\'; + buffer[index++] = ch; + afterEscape = false; + } else if (ch < 0x20 || ch == 0x7F) { // Control characters. + buffer[index++] = '\\'; + placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase); + afterEscape = true; + } else { + // Space character may be required to separate backslash-escape sequence and normal characters. + if (afterEscape && (isASCIIHexDigit(ch) || ch == ' ')) + buffer[index++] = ' '; + buffer[index++] = ch; + afterEscape = false; + } + } + buffer[index++] = '\''; + + ASSERT(quotedStringSize == index); + return String::adopt(buffer); +} + +// We use single quotes for now because markup.cpp uses double quotes. +String quoteCSSString(const String& string) +{ + // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds + // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned. + + unsigned length = string.length(); + + if (!length) + return String("\'\'"); + + if (length > std::numeric_limits<unsigned>::max() / 3 - 2) + return emptyString(); + + if (string.is8Bit()) + return quoteCSSStringInternal(string.characters8(), length); + return quoteCSSStringInternal(string.characters16(), length); +} + +String quoteCSSStringIfNeeded(const String& string) +{ + return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string); +} + +String quoteCSSURLIfNeeded(const String& string) +{ + return isCSSTokenizerURL(string) ? string : quoteCSSString(string); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.cpp b/chromium/third_party/WebKit/Source/core/css/CSSMarkup.h index 2db2bd92e9d..9d37fff3336 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSMarkup.h @@ -1,5 +1,8 @@ /* - * Copyright (C) 2005 Apple Computer, Inc. + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 @@ -15,33 +18,23 @@ * 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. - * */ -#include "config.h" - -#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC -#define CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS 1 -#endif +#ifndef CSSMarkup_h +#define CSSMarkup_h -#include "core/css/MediaFeatureNames.h" +#include "wtf/text/WTFString.h" -#include "wtf/StaticConstructors.h" +// Helper functions for converting from CSSValues to text. +// FIXME: This file has a similar purpose to +// CSSOMUtils.h. Perhaps the two should be combined? namespace WebCore { -namespace MediaFeatureNames { -#define DEFINE_MEDIAFEATURE_GLOBAL(name, str) \ - DEFINE_GLOBAL(AtomicString, name##MediaFeature, str) -CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(DEFINE_MEDIAFEATURE_GLOBAL) -#undef DEFINE_MEDIAFEATURE_GLOBAL +String quoteCSSString(const String&); +String quoteCSSStringIfNeeded(const String&); +String quoteCSSURLIfNeeded(const String&); -void init() -{ -#define INITIALIZE_GLOBAL(name, str) new (NotNull, (void*)&name##MediaFeature) AtomicString(str, AtomicString::ConstructFromLiteral); - CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(INITIALIZE_GLOBAL) -#undef INITIALIZE_GLOBAL -} - -} // namespace MediaFeatureNames } // namespace WebCore + +#endif // CSSMarkup_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMatrix.cpp b/chromium/third_party/WebKit/Source/core/css/CSSMatrix.cpp index 4926df97629..dc974c1a003 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSMatrix.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSMatrix.cpp @@ -26,10 +26,10 @@ #include "config.h" #include "core/css/CSSMatrix.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" #include "bindings/v8/ExceptionState.h" -#include "core/css/CSSParser.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSToLengthConversionData.h" #include "core/css/StylePropertySet.h" #include "core/css/resolver/TransformBuilder.h" @@ -57,11 +57,12 @@ void CSSMatrix::setMatrixValue(const String& string, ExceptionState& exceptionSt if (string.isEmpty()) return; - RefPtr<MutableStylePropertySet> styleDeclaration = MutableStylePropertySet::create(); - if (CSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, HTMLStandardMode, 0)) { + // FIXME: crbug.com/154722 - should this continue to use legacy style parsing? + RefPtrWillBeRawPtr<MutableStylePropertySet> styleDeclaration = MutableStylePropertySet::create(); + if (BisonCSSParser::parseValue(styleDeclaration.get(), CSSPropertyWebkitTransform, string, true, HTMLStandardMode, 0)) { // Convert to TransformOperations. This can fail if a property // requires style (i.e., param uses 'ems' or 'exs') - RefPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform); + RefPtrWillBeRawPtr<CSSValue> value = styleDeclaration->getPropertyCSSValue(CSSPropertyWebkitTransform); // Check for a "none" or empty transform. In these cases we can use the default identity matrix. if (!value || (value->isPrimitiveValue() && (toCSSPrimitiveValue(value.get()))->getValueID() == CSSValueNone)) @@ -69,45 +70,45 @@ void CSSMatrix::setMatrixValue(const String& string, ExceptionState& exceptionSt DEFINE_STATIC_REF(RenderStyle, defaultStyle, RenderStyle::createDefaultStyle()); TransformOperations operations; - if (!TransformBuilder::createTransformOperations(value.get(), CSSToLengthConversionData(defaultStyle, defaultStyle), operations)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + if (!TransformBuilder::createTransformOperations(value.get(), CSSToLengthConversionData(defaultStyle, defaultStyle, 0, 0, 1.0f), operations)) { + exceptionState.throwDOMException(SyntaxError, "Failed to interpret '" + string + "' as a transformation operation."); return; } // Convert transform operations to a TransformationMatrix. This can fail // if a param has a percentage ('%') if (operations.dependsOnBoxSize()) - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The transformation depends on the box size, which is not supported."); TransformationMatrix t; operations.apply(FloatSize(0, 0), t); // set the matrix m_matrix = t; } else { // There is something there but parsing failed. - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Failed to parse '" + string + "'."); } } // Perform a concatenation of the matrices (this * secondMatrix) -PassRefPtr<CSSMatrix> CSSMatrix::multiply(CSSMatrix* secondMatrix) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::multiply(CSSMatrix* secondMatrix) const { if (!secondMatrix) - return 0; + return nullptr; return CSSMatrix::create(TransformationMatrix(m_matrix).multiply(secondMatrix->m_matrix)); } -PassRefPtr<CSSMatrix> CSSMatrix::inverse(ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::inverse(ExceptionState& exceptionState) const { if (!m_matrix.isInvertible()) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; + exceptionState.throwDOMException(NotSupportedError, "The matrix is not invertable."); + return nullptr; } return CSSMatrix::create(m_matrix.inverse()); } -PassRefPtr<CSSMatrix> CSSMatrix::translate(double x, double y, double z) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::translate(double x, double y, double z) const { if (std::isnan(x)) x = 0; @@ -118,7 +119,7 @@ PassRefPtr<CSSMatrix> CSSMatrix::translate(double x, double y, double z) const return CSSMatrix::create(TransformationMatrix(m_matrix).translate3d(x, y, z)); } -PassRefPtr<CSSMatrix> CSSMatrix::scale(double scaleX, double scaleY, double scaleZ) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::scale(double scaleX, double scaleY, double scaleZ) const { if (std::isnan(scaleX)) scaleX = 1; @@ -129,7 +130,7 @@ PassRefPtr<CSSMatrix> CSSMatrix::scale(double scaleX, double scaleY, double scal return CSSMatrix::create(TransformationMatrix(m_matrix).scale3d(scaleX, scaleY, scaleZ)); } -PassRefPtr<CSSMatrix> CSSMatrix::rotate(double rotX, double rotY, double rotZ) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::rotate(double rotX, double rotY, double rotZ) const { if (std::isnan(rotX)) rotX = 0; @@ -147,7 +148,7 @@ PassRefPtr<CSSMatrix> CSSMatrix::rotate(double rotX, double rotY, double rotZ) c return CSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(rotX, rotY, rotZ)); } -PassRefPtr<CSSMatrix> CSSMatrix::rotateAxisAngle(double x, double y, double z, double angle) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::rotateAxisAngle(double x, double y, double z, double angle) const { if (std::isnan(x)) x = 0; @@ -162,14 +163,14 @@ PassRefPtr<CSSMatrix> CSSMatrix::rotateAxisAngle(double x, double y, double z, d return CSSMatrix::create(TransformationMatrix(m_matrix).rotate3d(x, y, z, angle)); } -PassRefPtr<CSSMatrix> CSSMatrix::skewX(double angle) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::skewX(double angle) const { if (std::isnan(angle)) angle = 0; return CSSMatrix::create(TransformationMatrix(m_matrix).skewX(angle)); } -PassRefPtr<CSSMatrix> CSSMatrix::skewY(double angle) const +PassRefPtrWillBeRawPtr<CSSMatrix> CSSMatrix::skewY(double angle) const { if (std::isnan(angle)) angle = 0; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMatrix.h b/chromium/third_party/WebKit/Source/core/css/CSSMatrix.h index 92c6cb1ab08..e62009791c2 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSMatrix.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSMatrix.h @@ -35,15 +35,15 @@ namespace WebCore { class ExceptionState; -class CSSMatrix FINAL : public ScriptWrappable, public RefCounted<CSSMatrix> { +class CSSMatrix FINAL : public RefCountedWillBeGarbageCollectedFinalized<CSSMatrix>, public ScriptWrappable { public: - static PassRefPtr<CSSMatrix> create(const TransformationMatrix& m) + static PassRefPtrWillBeRawPtr<CSSMatrix> create(const TransformationMatrix& m) { - return adoptRef(new CSSMatrix(m)); + return adoptRefWillBeNoop(new CSSMatrix(m)); } - static PassRefPtr<CSSMatrix> create(const String& s, ExceptionState& exceptionState) + static PassRefPtrWillBeRawPtr<CSSMatrix> create(const String& s, ExceptionState& exceptionState) { - return adoptRef(new CSSMatrix(s, exceptionState)); + return adoptRefWillBeNoop(new CSSMatrix(s, exceptionState)); } double a() const { return m_matrix.a(); } @@ -100,53 +100,55 @@ public: // specified operation applied. The this value is not modified. // Multiply this matrix by secondMatrix, on the right (result = this * secondMatrix) - PassRefPtr<CSSMatrix> multiply(CSSMatrix* secondMatrix) const; + PassRefPtrWillBeRawPtr<CSSMatrix> multiply(CSSMatrix* secondMatrix) const; // Return the inverse of this matrix. Throw an exception if the matrix is not invertible - PassRefPtr<CSSMatrix> inverse(ExceptionState&) const; + PassRefPtrWillBeRawPtr<CSSMatrix> inverse(ExceptionState&) const; // Return this matrix translated by the passed values. // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations // Operation is performed as though the this matrix is multiplied by a matrix with // the translation values on the left (result = translation(x,y,z) * this) - PassRefPtr<CSSMatrix> translate(double x, double y, double z) const; + PassRefPtrWillBeRawPtr<CSSMatrix> translate(double x, double y, double z) const; // Returns this matrix scaled by the passed values. // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN // makes it the same as scaleX. This allows the 3D form to used for 2D operations // Operation is performed as though the this matrix is multiplied by a matrix with // the scale values on the left (result = scale(x,y,z) * this) - PassRefPtr<CSSMatrix> scale(double scaleX, double scaleY, double scaleZ) const; + PassRefPtrWillBeRawPtr<CSSMatrix> scale(double scaleX, double scaleY, double scaleZ) const; // Returns this matrix rotated by the passed values. // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX). // Otherwise use a rotation value of 0 for any passed NaN. // Operation is performed as though the this matrix is multiplied by a matrix with // the rotation values on the left (result = rotation(x,y,z) * this) - PassRefPtr<CSSMatrix> rotate(double rotX, double rotY, double rotZ) const; + PassRefPtrWillBeRawPtr<CSSMatrix> rotate(double rotX, double rotY, double rotZ) const; // Returns this matrix rotated about the passed axis by the passed angle. // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value // Operation is performed as though the this matrix is multiplied by a matrix with // the rotation values on the left (result = rotation(x,y,z,angle) * this) - PassRefPtr<CSSMatrix> rotateAxisAngle(double x, double y, double z, double angle) const; + PassRefPtrWillBeRawPtr<CSSMatrix> rotateAxisAngle(double x, double y, double z, double angle) const; // Return this matrix skewed along the X axis by the passed values. // Passing a NaN will use a value of 0. // Operation is performed as though the this matrix is multiplied by a matrix with // the skew values on the left (result = skewX(angle) * this) - PassRefPtr<CSSMatrix> skewX(double angle) const; + PassRefPtrWillBeRawPtr<CSSMatrix> skewX(double angle) const; // Return this matrix skewed along the Y axis by the passed values. // Passing a NaN will use a value of 0. // Operation is performed as though the this matrix is multiplied by a matrix with // the skew values on the left (result = skewY(angle) * this) - PassRefPtr<CSSMatrix> skewY(double angle) const; + PassRefPtrWillBeRawPtr<CSSMatrix> skewY(double angle) const; const TransformationMatrix& transform() const { return m_matrix; } String toString() const; + void trace(Visitor*) { } + protected: CSSMatrix(const TransformationMatrix&); CSSMatrix(const String&, ExceptionState&); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.cpp index 7e8c34a5945..dedea18c4a3 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.cpp @@ -35,8 +35,10 @@ CSSMediaRule::CSSMediaRule(StyleRuleMedia* mediaRule, CSSStyleSheet* parent) CSSMediaRule::~CSSMediaRule() { +#if !ENABLE(OILPAN) if (m_mediaCSSOMWrapper) m_mediaCSSOMWrapper->clearParentRule(); +#endif } MediaQuerySet* CSSMediaRule::mediaQueries() const @@ -74,4 +76,9 @@ void CSSMediaRule::reattach(StyleRuleBase* rule) m_mediaCSSOMWrapper->reattach(mediaQueries()); } +void CSSMediaRule::trace(Visitor* visitor) +{ + visitor->trace(m_mediaCSSOMWrapper); + CSSGroupingRule::trace(visitor); +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.h b/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.h index 380c062c122..fb6895816d6 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSMediaRule.h @@ -30,9 +30,12 @@ namespace WebCore { class StyleRuleMedia; -class CSSMediaRule : public CSSGroupingRule { +class CSSMediaRule FINAL : public CSSGroupingRule { public: - static PassRefPtr<CSSMediaRule> create(StyleRuleMedia* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSMediaRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSMediaRule> create(StyleRuleMedia* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSMediaRule(rule, sheet)); + } virtual ~CSSMediaRule(); @@ -42,12 +45,14 @@ public: MediaList* media() const; + virtual void trace(Visitor*) OVERRIDE; + private: CSSMediaRule(StyleRuleMedia*, CSSStyleSheet*); MediaQuerySet* mediaQueries() const; - mutable RefPtr<MediaList> m_mediaCSSOMWrapper; + mutable RefPtrWillBeMember<MediaList> m_mediaCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSMediaRule, MEDIA_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMixFunctionValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSMixFunctionValue.cpp deleted file mode 100644 index 0dd07a58fee..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSMixFunctionValue.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" -#include "core/css/CSSMixFunctionValue.h" - -namespace WebCore { - -CSSMixFunctionValue::CSSMixFunctionValue() - : CSSValueList(CSSMixFunctionValueClass, SpaceSeparator) -{ -} - -CSSMixFunctionValue::CSSMixFunctionValue(const CSSMixFunctionValue& cloneFrom) - : CSSValueList(cloneFrom) -{ -} - -String CSSMixFunctionValue::customCSSText() const -{ - return "mix(" + CSSValueList::customCSSText() + ")"; -} - -PassRefPtr<CSSMixFunctionValue> CSSMixFunctionValue::cloneForCSSOM() const -{ - return adoptRef(new CSSMixFunctionValue(*this)); -} - -bool CSSMixFunctionValue::equals(const CSSMixFunctionValue& other) const -{ - return CSSValueList::equals(other); -} - -} // namespace WebCore - diff --git a/chromium/third_party/WebKit/Source/core/css/CSSMixFunctionValue.h b/chromium/third_party/WebKit/Source/core/css/CSSMixFunctionValue.h deleted file mode 100644 index 04a5e2d6020..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSMixFunctionValue.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef CSSMixFunctionValue_h -#define CSSMixFunctionValue_h - -#include "core/css/CSSValueList.h" -#include "wtf/PassRefPtr.h" - -namespace WebCore { - -class CSSMixFunctionValue : public CSSValueList { -public: - static PassRefPtr<CSSMixFunctionValue> create() - { - return adoptRef(new CSSMixFunctionValue()); - } - - String customCSSText() const; - - PassRefPtr<CSSMixFunctionValue> cloneForCSSOM() const; - - bool equals(const CSSMixFunctionValue&) const; - -private: - CSSMixFunctionValue(); - CSSMixFunctionValue(const CSSMixFunctionValue& cloneFrom); -}; - -DEFINE_CSS_VALUE_TYPE_CASTS(CSSMixFunctionValue, isMixFunctionValue()); - -} // namespace WebCore - - -#endif diff --git a/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.cpp b/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.cpp index 36545dd12bc..1e7882f2c1c 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.cpp @@ -49,13 +49,6 @@ void serializeCharacterAsCodePoint(UChar32 c, StringBuilder& appendTo) appendTo.append(' '); } -void serializeIdentifier(const String& identifier, String& appendTo) -{ - StringBuilder addend; - serializeIdentifier(identifier, addend); - appendTo.append(addend.toString()); -} - void serializeIdentifier(const String& identifier, StringBuilder& appendTo) { bool isFirst = true; @@ -85,13 +78,6 @@ void serializeIdentifier(const String& identifier, StringBuilder& appendTo) } } -void serializeString(const String& string, String& appendTo) -{ - StringBuilder addend; - serializeString(string, addend); - appendTo.append(addend.toString()); -} - void serializeString(const String& string, StringBuilder& appendTo) { appendTo.append('\"'); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.h b/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.h index 3239ada94b4..813396b1e11 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSOMUtils.h @@ -35,15 +35,15 @@ #include "wtf/unicode/Unicode.h" // Utilities for CSSOM http://dev.w3.org/csswg/cssom/ +// FIXME: This file has a similar purpose to +// CSSMarkup.h. Perhaps the two should be combined? namespace WebCore { // Common serializing methods. See: http://dev.w3.org/csswg/cssom/#common-serializing-idioms void serializeCharacter(UChar32, StringBuilder& appendTo); void serializeCharacterAsCodePoint(UChar32, StringBuilder& appendTo); -void serializeIdentifier(const String& identifier, String& appendTo); void serializeIdentifier(const String& identifier, StringBuilder& appendTo); -void serializeString(const String&, String& appendTo); void serializeString(const String&, StringBuilder& appendTo); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPageRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSPageRule.cpp index 0513e92dd99..20237e62c8b 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPageRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSPageRule.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "core/css/CSSPageRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSSelector.h" #include "core/css/CSSStyleSheet.h" #include "core/css/PropertySetCSSStyleDeclaration.h" @@ -40,8 +40,10 @@ CSSPageRule::CSSPageRule(StyleRulePage* pageRule, CSSStyleSheet* parent) CSSPageRule::~CSSPageRule() { +#if !ENABLE(OILPAN) if (m_propertiesCSSOMWrapper) m_propertiesCSSOMWrapper->clearParentRule(); +#endif } CSSStyleDeclaration* CSSPageRule::style() const @@ -68,7 +70,8 @@ String CSSPageRule::selectorText() const void CSSPageRule::setSelectorText(const String& selectorText) { - CSSParser parser(parserContext()); + CSSParserContext context(parserContext(), 0); + BisonCSSParser parser(context); CSSSelectorList selectorList; parser.parseSelector(selectorText, selectorList); if (!selectorList.isValid()) @@ -84,7 +87,7 @@ String CSSPageRule::cssText() const StringBuilder result; result.append(selectorText()); result.appendLiteral(" { "); - String decls = m_pageRule->properties()->asText(); + String decls = m_pageRule->properties().asText(); result.append(decls); if (!decls.isEmpty()) result.append(' '); @@ -100,4 +103,11 @@ void CSSPageRule::reattach(StyleRuleBase* rule) m_propertiesCSSOMWrapper->reattach(m_pageRule->mutableProperties()); } +void CSSPageRule::trace(Visitor* visitor) +{ + visitor->trace(m_pageRule); + visitor->trace(m_propertiesCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPageRule.h b/chromium/third_party/WebKit/Source/core/css/CSSPageRule.h index 4aa0f696e63..4fc9b1be4ba 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPageRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSPageRule.h @@ -23,6 +23,7 @@ #define CSSPageRule_h #include "core/css/CSSRule.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -31,9 +32,12 @@ class CSSStyleSheet; class StyleRulePage; class StyleRuleCSSStyleDeclaration; -class CSSPageRule : public CSSRule { +class CSSPageRule FINAL : public CSSRule { public: - static PassRefPtr<CSSPageRule> create(StyleRulePage* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSPageRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSPageRule> create(StyleRulePage* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSPageRule(rule, sheet)); + } virtual ~CSSPageRule(); @@ -46,11 +50,13 @@ public: String selectorText() const; void setSelectorText(const String&); + virtual void trace(Visitor*) OVERRIDE; + private: CSSPageRule(StyleRulePage*, CSSStyleSheet*); - RefPtr<StyleRulePage> m_pageRule; - mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; + RefPtrWillBeMember<StyleRulePage> m_pageRule; + mutable RefPtrWillBeMember<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSPageRule, PAGE_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParser.h b/chromium/third_party/WebKit/Source/core/css/CSSParser.h deleted file mode 100755 index de263102892..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSParser.h +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (C) 2003 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2008 Eric Seidel <eric@webkit.org> - * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 CSSParser_h -#define CSSParser_h - -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "core/css/CSSCalculationValue.h" -#include "core/css/CSSFilterValue.h" -#include "core/css/CSSGradientValue.h" -#include "core/css/CSSParserMode.h" -#include "core/css/CSSParserValues.h" -#include "core/css/CSSProperty.h" -#include "core/css/CSSPropertySourceData.h" -#include "core/css/CSSSelector.h" -#include "core/css/CSSTokenizer.h" -#include "core/css/MediaQuery.h" -#include "core/css/StylePropertySet.h" -#include "core/frame/UseCounter.h" -#include "platform/graphics/Color.h" -#include "wtf/HashSet.h" -#include "wtf/OwnPtr.h" -#include "wtf/Vector.h" -#include "wtf/text/AtomicString.h" -#include "wtf/text/TextPosition.h" - -namespace WebCore { - -class AnimationParseContext; -class CSSArrayFunctionValue; -class CSSBorderImageSliceValue; -class CSSMixFunctionValue; -class CSSPrimitiveValue; -class CSSSelectorList; -class CSSShaderValue; -class CSSValue; -class CSSValueList; -class CSSBasicShape; -class Document; -class Element; -class ImmutableStylePropertySet; -class MediaQueryExp; -class MediaQuerySet; -class MutableStylePropertySet; -class StyleKeyframe; -class StylePropertyShorthand; -class StyleRuleBase; -class StyleRuleKeyframes; -class StyleKeyframe; -class StyleSheetContents; - -// FIXME: This class is shared with CSSTokenizer so should we rename it to CSSSourceLocation? -struct CSSParserLocation { - unsigned offset; - unsigned lineNumber; - CSSParserString token; -}; - -class CSSParser { - friend inline int cssyylex(void*, CSSParser*); - -public: - class SourceDataHandler; - enum ErrorType { - NoError, - PropertyDeclarationError, - InvalidPropertyValueError, - InvalidPropertyError, - InvalidSelectorError, - InvalidSupportsConditionError, - InvalidRuleError, - InvalidMediaQueryError, - InvalidKeyframeSelectorError, - InvalidSelectorPseudoError, - UnterminatedCommentError, - GeneralError - }; - - CSSParser(const CSSParserContext&, UseCounter* = 0); - - ~CSSParser(); - - void parseSheet(StyleSheetContents*, const String&, const TextPosition& startPosition = TextPosition::minimumPosition(), SourceDataHandler* = 0, bool = false); - PassRefPtr<StyleRuleBase> parseRule(StyleSheetContents*, const String&); - PassRefPtr<StyleKeyframe> parseKeyframeRule(StyleSheetContents*, const String&); - bool parseSupportsCondition(const String&); - static bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, CSSParserMode, StyleSheetContents*); - static bool parseColor(RGBA32& color, const String&, bool strict = false); - static bool parseSystemColor(RGBA32& color, const String&, Document*); - static PassRefPtr<CSSValueList> parseFontFaceValue(const AtomicString&); - PassRefPtr<CSSPrimitiveValue> parseValidPrimitive(CSSValueID ident, CSSParserValue*); - bool parseDeclaration(MutableStylePropertySet*, const String&, SourceDataHandler*, StyleSheetContents* contextStyleSheet); - static PassRefPtr<ImmutableStylePropertySet> parseInlineStyleDeclaration(const String&, Element*); - PassRefPtr<MediaQuerySet> parseMediaQueryList(const String&); - PassOwnPtr<Vector<double> > parseKeyframeKeyList(const String&); - - void addPropertyWithPrefixingVariant(CSSPropertyID, PassRefPtr<CSSValue>, bool important, bool implicit = false); - void addProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important, bool implicit = false); - void rollbackLastProperties(int num); - bool hasProperties() const { return !m_parsedProperties.isEmpty(); } - void addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtr<CSSValue>, bool); - void setCurrentProperty(CSSPropertyID); - - bool parseValue(CSSPropertyID, bool important); - bool parseShorthand(CSSPropertyID, const StylePropertyShorthand&, bool important); - bool parse4Values(CSSPropertyID, const CSSPropertyID* properties, bool important); - bool parseContent(CSSPropertyID, bool important); - bool parseQuotes(CSSPropertyID, bool important); - - static bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, const Document&); - void storeVariableDeclaration(const CSSParserString&, PassOwnPtr<CSSParserValueList>, bool important); - - PassRefPtr<CSSValue> parseAttr(CSSParserValueList* args); - - PassRefPtr<CSSValue> parseBackgroundColor(); - - bool parseFillImage(CSSParserValueList*, RefPtr<CSSValue>&); - - enum FillPositionFlag { InvalidFillPosition = 0, AmbiguousFillPosition = 1, XFillPosition = 2, YFillPosition = 4 }; - enum FillPositionParsingMode { ResolveValuesAsPercent = 0, ResolveValuesAsKeyword = 1 }; - PassRefPtr<CSSPrimitiveValue> parseFillPositionComponent(CSSParserValueList*, unsigned& cumulativeFlags, FillPositionFlag& individualFlag, FillPositionParsingMode = ResolveValuesAsPercent); - PassRefPtr<CSSValue> parseFillPositionX(CSSParserValueList*); - PassRefPtr<CSSValue> parseFillPositionY(CSSParserValueList*); - void parse2ValuesFillPosition(CSSParserValueList*, RefPtr<CSSValue>&, RefPtr<CSSValue>&); - bool isPotentialPositionValue(CSSParserValue*); - void parseFillPosition(CSSParserValueList*, RefPtr<CSSValue>&, RefPtr<CSSValue>&); - void parse3ValuesFillPosition(CSSParserValueList*, RefPtr<CSSValue>&, RefPtr<CSSValue>&, PassRefPtr<CSSPrimitiveValue>, PassRefPtr<CSSPrimitiveValue>); - void parse4ValuesFillPosition(CSSParserValueList*, RefPtr<CSSValue>&, RefPtr<CSSValue>&, PassRefPtr<CSSPrimitiveValue>, PassRefPtr<CSSPrimitiveValue>); - - void parseFillRepeat(RefPtr<CSSValue>&, RefPtr<CSSValue>&); - PassRefPtr<CSSValue> parseFillSize(CSSPropertyID, bool &allowComma); - - bool parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtr<CSSValue>&, RefPtr<CSSValue>&); - bool parseFillShorthand(CSSPropertyID, const CSSPropertyID* properties, int numProperties, bool important); - - void addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval); - - void addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval); - - PassRefPtr<CSSValue> parseAnimationDelay(); - PassRefPtr<CSSValue> parseAnimationDirection(); - PassRefPtr<CSSValue> parseAnimationDuration(); - PassRefPtr<CSSValue> parseAnimationFillMode(); - PassRefPtr<CSSValue> parseAnimationIterationCount(); - PassRefPtr<CSSValue> parseAnimationName(); - PassRefPtr<CSSValue> parseAnimationPlayState(); - PassRefPtr<CSSValue> parseAnimationProperty(AnimationParseContext&); - PassRefPtr<CSSValue> parseAnimationTimingFunction(); - - bool parseTransformOriginShorthand(RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&); - bool parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result); - bool parseAnimationProperty(CSSPropertyID, RefPtr<CSSValue>&, AnimationParseContext&); - bool parseTransitionShorthand(CSSPropertyID, bool important); - bool parseAnimationShorthand(CSSPropertyID, bool important); - - PassRefPtr<CSSValue> parseColumnWidth(); - PassRefPtr<CSSValue> parseColumnCount(); - bool parseColumnsShorthand(bool important); - - PassRefPtr<CSSValue> parseGridPosition(); - bool parseIntegerOrStringFromGridPosition(RefPtr<CSSPrimitiveValue>& numericValue, RefPtr<CSSPrimitiveValue>& gridLineName); - bool parseGridItemPositionShorthand(CSSPropertyID, bool important); - bool parseGridAreaShorthand(bool important); - bool parseSingleGridAreaLonghand(RefPtr<CSSValue>&); - bool parseGridTrackList(CSSPropertyID, bool important); - bool parseGridTrackRepeatFunction(CSSValueList&); - PassRefPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList); - PassRefPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue*); - PassRefPtr<CSSValue> parseGridTemplate(); - void parseGridLineNames(CSSParserValueList* inputList, CSSValueList&); - - bool parseClipShape(CSSPropertyID, bool important); - - bool parseBasicShape(CSSPropertyID, bool important); - PassRefPtr<CSSBasicShape> parseBasicShapeRectangle(CSSParserValueList* args); - PassRefPtr<CSSBasicShape> parseBasicShapeCircle(CSSParserValueList* args); - PassRefPtr<CSSBasicShape> parseBasicShapeEllipse(CSSParserValueList* args); - PassRefPtr<CSSBasicShape> parseBasicShapePolygon(CSSParserValueList* args); - PassRefPtr<CSSBasicShape> parseBasicShapeInsetRectangle(CSSParserValueList* args); - - bool parseFont(bool important); - PassRefPtr<CSSValueList> parseFontFamily(); - - bool parseCounter(CSSPropertyID, int defaultValue, bool important); - PassRefPtr<CSSValue> parseCounterContent(CSSParserValueList* args, bool counters); - - bool parseColorParameters(CSSParserValue*, int* colorValues, bool parseAlpha); - bool parseHSLParameters(CSSParserValue*, double* colorValues, bool parseAlpha); - PassRefPtr<CSSPrimitiveValue> parseColor(CSSParserValue* = 0); - bool parseColorFromValue(CSSParserValue*, RGBA32&); - void parseSelector(const String&, CSSSelectorList&); - - template<typename StringType> - static bool fastParseColor(RGBA32&, const StringType&, bool strict); - - bool parseLineHeight(bool important); - bool parseFontSize(bool important); - bool parseFontVariant(bool important); - bool parseFontWeight(bool important); - bool parseFontFaceSrc(); - bool parseFontFaceUnicodeRange(); - - bool parseSVGValue(CSSPropertyID propId, bool important); - PassRefPtr<CSSValue> parseSVGPaint(); - PassRefPtr<CSSValue> parseSVGColor(); - PassRefPtr<CSSValue> parseSVGStrokeDasharray(); - - PassRefPtr<CSSValue> parsePaintOrder() const; - - // CSS3 Parsing Routines (for properties specific to CSS3) - PassRefPtr<CSSValueList> parseShadow(CSSParserValueList*, CSSPropertyID); - bool parseBorderImageShorthand(CSSPropertyID, bool important); - PassRefPtr<CSSValue> parseBorderImage(CSSPropertyID); - bool parseBorderImageRepeat(RefPtr<CSSValue>&); - bool parseBorderImageSlice(CSSPropertyID, RefPtr<CSSBorderImageSliceValue>&); - bool parseBorderImageWidth(RefPtr<CSSPrimitiveValue>&); - bool parseBorderImageOutset(RefPtr<CSSPrimitiveValue>&); - bool parseBorderRadius(CSSPropertyID, bool important); - - bool parseAspectRatio(bool important); - - bool parseReflect(CSSPropertyID, bool important); - - bool parseFlex(CSSParserValueList* args, bool important); - - bool parseObjectPosition(bool important); - - // Image generators - bool parseCanvas(CSSParserValueList*, RefPtr<CSSValue>&); - - bool parseDeprecatedGradient(CSSParserValueList*, RefPtr<CSSValue>&); - bool parseDeprecatedLinearGradient(CSSParserValueList*, RefPtr<CSSValue>&, CSSGradientRepeat repeating); - bool parseDeprecatedRadialGradient(CSSParserValueList*, RefPtr<CSSValue>&, CSSGradientRepeat repeating); - bool parseLinearGradient(CSSParserValueList*, RefPtr<CSSValue>&, CSSGradientRepeat repeating); - bool parseRadialGradient(CSSParserValueList*, RefPtr<CSSValue>&, CSSGradientRepeat repeating); - bool parseGradientColorStops(CSSParserValueList*, CSSGradientValue*, bool expectComma); - - bool parseCrossfade(CSSParserValueList*, RefPtr<CSSValue>&); - - PassRefPtr<CSSValue> parseImageSet(CSSParserValueList*); - - PassRefPtr<CSSValueList> parseFilter(); - PassRefPtr<CSSFilterValue> parseBuiltinFilterArguments(CSSParserValueList*, CSSFilterValue::FilterOperationType); - PassRefPtr<CSSMixFunctionValue> parseMixFunction(CSSParserValue*); - PassRefPtr<CSSArrayFunctionValue> parseCustomFilterArrayFunction(CSSParserValue*); - PassRefPtr<CSSValueList> parseCustomFilterTransform(CSSParserValueList*); - PassRefPtr<CSSValueList> parseCustomFilterParameters(CSSParserValueList*); - PassRefPtr<CSSFilterValue> parseCustomFilterFunctionWithAtRuleReferenceSyntax(CSSParserValue*); - PassRefPtr<CSSFilterValue> parseCustomFilterFunctionWithInlineSyntax(CSSParserValue*); - PassRefPtr<CSSFilterValue> parseCustomFilterFunction(CSSParserValue*); - bool parseFilterRuleSrc(); - PassRefPtr<CSSShaderValue> parseFilterRuleSrcUriAndFormat(CSSParserValueList*); - - static bool isBlendMode(CSSValueID); - static bool isCompositeOperator(CSSValueID); - - PassRefPtr<CSSValueList> parseTransform(); - PassRefPtr<CSSValue> parseTransformValue(CSSParserValue*); - bool parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&); - bool parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtr<CSSValue>&, RefPtr<CSSValue>&); - - bool parseTextEmphasisStyle(bool important); - - bool parseTouchAction(bool important); - - void addTextDecorationProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important); - bool parseTextDecoration(CSSPropertyID propId, bool important); - bool parseTextUnderlinePosition(bool important); - - PassRefPtr<CSSValue> parseTextIndent(); - - bool parseLineBoxContain(bool important); - bool parseCalculation(CSSParserValue*, ValueRange); - - bool parseFontFeatureTag(CSSValueList*); - bool parseFontFeatureSettings(bool important); - - bool parseFlowThread(const String& flowName); - bool parseFlowThread(CSSPropertyID, bool important); - bool parseRegionThread(CSSPropertyID, bool important); - - bool parseFontVariantLigatures(bool important); - - bool parseGeneratedImage(CSSParserValueList*, RefPtr<CSSValue>&); - - CSSParserSelector* createFloatingSelector(); - CSSParserSelector* createFloatingSelectorWithTagName(const QualifiedName&); - PassOwnPtr<CSSParserSelector> sinkFloatingSelector(CSSParserSelector*); - - Vector<OwnPtr<CSSParserSelector> >* createFloatingSelectorVector(); - PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >*); - - CSSParserValueList* createFloatingValueList(); - PassOwnPtr<CSSParserValueList> sinkFloatingValueList(CSSParserValueList*); - - CSSParserFunction* createFloatingFunction(); - CSSParserFunction* createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args); - PassOwnPtr<CSSParserFunction> sinkFloatingFunction(CSSParserFunction*); - - CSSParserValue& sinkFloatingValue(CSSParserValue&); - - MediaQuerySet* createMediaQuerySet(); - StyleRuleBase* createImportRule(const CSSParserString&, MediaQuerySet*); - StyleKeyframe* createKeyframe(CSSParserValueList*); - StyleRuleKeyframes* createKeyframesRule(const String&, PassOwnPtr<Vector<RefPtr<StyleKeyframe> > >, bool isPrefixed); - - typedef Vector<RefPtr<StyleRuleBase> > RuleList; - StyleRuleBase* createMediaRule(MediaQuerySet*, RuleList*); - RuleList* createRuleList(); - RuleList* appendRule(RuleList*, StyleRuleBase*); - StyleRuleBase* createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors); - StyleRuleBase* createFontFaceRule(); - StyleRuleBase* createPageRule(PassOwnPtr<CSSParserSelector> pageSelector); - StyleRuleBase* createRegionRule(Vector<OwnPtr<CSSParserSelector> >* regionSelector, RuleList* rules); - StyleRuleBase* createMarginAtRule(CSSSelector::MarginBoxType); - StyleRuleBase* createSupportsRule(bool conditionIsSupported, RuleList*); - void markSupportsRuleHeaderStart(); - void markSupportsRuleHeaderEnd(); - PassRefPtr<CSSRuleSourceData> popSupportsRuleData(); - StyleRuleBase* createHostRule(RuleList* rules); - StyleRuleBase* createFilterRule(const CSSParserString&); - - void startDeclarationsForMarginBox(); - void endDeclarationsForMarginBox(); - - MediaQueryExp* createFloatingMediaQueryExp(const AtomicString&, CSSParserValueList*); - PassOwnPtr<MediaQueryExp> sinkFloatingMediaQueryExp(MediaQueryExp*); - Vector<OwnPtr<MediaQueryExp> >* createFloatingMediaQueryExpList(); - PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >*); - MediaQuery* createFloatingMediaQuery(MediaQuery::Restrictor, const AtomicString&, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > >); - MediaQuery* createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > >); - MediaQuery* createFloatingNotAllQuery(); - PassOwnPtr<MediaQuery> sinkFloatingMediaQuery(MediaQuery*); - - Vector<RefPtr<StyleKeyframe> >* createFloatingKeyframeVector(); - PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > sinkFloatingKeyframeVector(Vector<RefPtr<StyleKeyframe> >*); - - void addNamespace(const AtomicString& prefix, const AtomicString& uri); - QualifiedName determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName); - - CSSParserSelector* rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*, bool isNamespacePlaceholder = false); - CSSParserSelector* rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule); - CSSParserSelector* rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule); - CSSParserSelector* rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector*); - CSSParserSelector* rewriteSpecifiers(CSSParserSelector*, CSSParserSelector*); - CSSParserSelector* rewriteSpecifiersForShadowDistributed(CSSParserSelector* specifiers, CSSParserSelector* distributedPseudoElementSelector); - - void invalidBlockHit(); - - Vector<OwnPtr<CSSParserSelector> >* reusableSelectorVector() { return &m_reusableSelectorVector; } - - void setReusableRegionSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectors); - Vector<OwnPtr<CSSParserSelector> >* reusableRegionSelectorVector() { return &m_reusableRegionSelectorVector; } - - void clearProperties(); - - PassRefPtr<ImmutableStylePropertySet> createStylePropertySet(); - - CSSParserContext m_context; - - bool m_important; - CSSPropertyID m_id; - StyleSheetContents* m_styleSheet; - RefPtr<StyleRuleBase> m_rule; - RefPtr<StyleKeyframe> m_keyframe; - RefPtr<MediaQuerySet> m_mediaList; - OwnPtr<CSSParserValueList> m_valueList; - bool m_supportsCondition; - - typedef Vector<CSSProperty, 256> ParsedPropertyVector; - ParsedPropertyVector m_parsedProperties; - CSSSelectorList* m_selectorListForParseSelector; - - unsigned m_numParsedPropertiesBeforeMarginBox; - - int m_inParseShorthand; - CSSPropertyID m_currentShorthand; - bool m_implicitShorthand; - - bool m_hasFontFaceOnlyValues; - bool m_hadSyntacticallyValidCSSRule; - bool m_logErrors; - bool m_ignoreErrors; - - bool m_inFilterRule; - - AtomicString m_defaultNamespace; - - // tokenizer methods and data - SourceDataHandler* m_sourceDataHandler; - - void startRule(); - void endRule(bool valid); - void startRuleHeader(CSSRuleSourceData::Type); - void endRuleHeader(); - void startSelector(); - void endSelector(); - void startRuleBody(); - void startProperty(); - void endProperty(bool isImportantFound, bool isPropertyParsed, ErrorType = NoError); - void startEndUnknownRule(); - - void endInvalidRuleHeader(); - void reportError(const CSSParserLocation&, ErrorType = GeneralError); - void resumeErrorLogging() { m_ignoreErrors = false; } - void setLocationLabel(const CSSParserLocation& location) { m_locationLabel = location; } - const CSSParserLocation& lastLocationLabel() const { return m_locationLabel; } - - void tokenToLowerCase(const CSSParserString& token); - - void markViewportRuleBodyStart() { m_inViewport = true; } - void markViewportRuleBodyEnd() { m_inViewport = false; } - StyleRuleBase* createViewportRule(); - - PassRefPtr<CSSPrimitiveValue> createPrimitiveNumericValue(CSSParserValue*); - PassRefPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*); - PassRefPtr<CSSPrimitiveValue> createPrimitiveVariableNameValue(CSSParserValue*); - - static KURL completeURL(const CSSParserContext&, const String& url); - - CSSParserLocation currentLocation() { return m_tokenizer.currentLocation(); } - -private: - enum PropertyType { - PropertyExplicit, - PropertyImplicit - }; - - class ImplicitScope { - WTF_MAKE_NONCOPYABLE(ImplicitScope); - public: - ImplicitScope(WebCore::CSSParser* parser, PropertyType propertyType) - : m_parser(parser) - { - m_parser->m_implicitShorthand = propertyType == CSSParser::PropertyImplicit; - } - - ~ImplicitScope() - { - m_parser->m_implicitShorthand = false; - } - - private: - WebCore::CSSParser* m_parser; - }; - - class StyleDeclarationScope { - WTF_MAKE_NONCOPYABLE(StyleDeclarationScope); - public: - StyleDeclarationScope(CSSParser* parser, const StylePropertySet* declaration) - : m_parser(parser) - , m_mode(declaration->cssParserMode()) - { - if (isCSSViewportParsingEnabledForMode(m_mode)) { - ASSERT(!m_parser->inViewport()); - m_parser->markViewportRuleBodyStart(); - } - } - - ~StyleDeclarationScope() - { - if (isCSSViewportParsingEnabledForMode(m_mode)) - m_parser->markViewportRuleBodyEnd(); - } - - private: - CSSParser* m_parser; - CSSParserMode m_mode; - }; - - inline void ensureLineEndings(); - - void setStyleSheet(StyleSheetContents* styleSheet) { m_styleSheet = styleSheet; } - - bool inQuirksMode() const { return isQuirksModeBehavior(m_context.mode()); } - bool inViewport() const { return m_inViewport; } - - KURL completeURL(const String& url) const; - - void recheckAtKeyword(const UChar* str, int len); - - template<unsigned prefixLength, unsigned suffixLength> - inline void setupParser(const char (&prefix)[prefixLength], const String& string, const char (&suffix)[suffixLength]) - { - setupParser(prefix, prefixLength - 1, string, suffix, suffixLength - 1); - } - void setupParser(const char* prefix, unsigned prefixLength, const String&, const char* suffix, unsigned suffixLength); - bool inShorthand() const { return m_inParseShorthand; } - - bool validWidthOrHeight(CSSParserValue*); - - void deleteFontFaceOnlyValues(); - - bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, StyleSheetContents* contextStyleSheet); - PassRefPtr<ImmutableStylePropertySet> parseDeclaration(const String&, StyleSheetContents* contextStyleSheet); - - enum SizeParameterType { - None, - Auto, - Length, - PageSize, - Orientation, - }; - - bool parsePage(CSSPropertyID propId, bool important); - bool parseSize(CSSPropertyID propId, bool important); - SizeParameterType parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType); - - bool parseFontFaceSrcURI(CSSValueList*); - bool parseFontFaceSrcLocal(CSSValueList*); - - bool parseColor(const String&); - - const String* m_source; - TextPosition m_startPosition; - CSSRuleSourceData::Type m_ruleHeaderType; - unsigned m_ruleHeaderStartOffset; - int m_ruleHeaderStartLineNumber; - OwnPtr<Vector<unsigned> > m_lineEndings; - - bool m_ruleHasHeader; - - bool m_allowImportRules; - bool m_allowNamespaceDeclarations; - - bool parseViewportProperty(CSSPropertyID propId, bool important); - bool parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important); - - bool m_inViewport; - - CSSParserLocation m_locationLabel; - - bool useLegacyBackgroundSizeShorthandBehavior() const; - - Vector<RefPtr<StyleRuleBase> > m_parsedRules; - Vector<RefPtr<StyleKeyframe> > m_parsedKeyframes; - Vector<RefPtr<MediaQuerySet> > m_parsedMediaQuerySets; - Vector<OwnPtr<RuleList> > m_parsedRuleLists; - Vector<CSSParserSelector*> m_floatingSelectors; - Vector<Vector<OwnPtr<CSSParserSelector> >*> m_floatingSelectorVectors; - Vector<CSSParserValueList*> m_floatingValueLists; - Vector<CSSParserFunction*> m_floatingFunctions; - - OwnPtr<MediaQuery> m_floatingMediaQuery; - OwnPtr<MediaQueryExp> m_floatingMediaQueryExp; - OwnPtr<Vector<OwnPtr<MediaQueryExp> > > m_floatingMediaQueryExpList; - - OwnPtr<Vector<RefPtr<StyleKeyframe> > > m_floatingKeyframeVector; - - Vector<OwnPtr<CSSParserSelector> > m_reusableSelectorVector; - Vector<OwnPtr<CSSParserSelector> > m_reusableRegionSelectorVector; - - RefPtr<CSSCalcValue> m_parsedCalculation; - - OwnPtr<RuleSourceDataList> m_supportsRuleDataStack; - - // defines units allowed for a certain property, used in parseUnit - enum Units { - FUnknown = 0x0000, - FInteger = 0x0001, - FNumber = 0x0002, // Real Numbers - FPercent = 0x0004, - FLength = 0x0008, - FAngle = 0x0010, - FTime = 0x0020, - FFrequency = 0x0040, - FPositiveInteger = 0x0080, - FRelative = 0x0100, - FResolution = 0x0200, - FNonNeg = 0x0400 - }; - - friend inline Units operator|(Units a, Units b) - { - return static_cast<Units>(static_cast<unsigned>(a) | static_cast<unsigned>(b)); - } - - enum ReleaseParsedCalcValueCondition { - ReleaseParsedCalcValue, - DoNotReleaseParsedCalcValue - }; - - bool isLoggingErrors(); - void logError(const String& message, const CSSParserLocation&); - - bool validCalculationUnit(CSSParserValue*, Units, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); - - bool shouldAcceptUnitLessValues(CSSParserValue*, Units, CSSParserMode); - - inline bool validUnit(CSSParserValue* value, Units unitflags, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue) { return validUnit(value, unitflags, m_context.mode(), releaseCalc); } - bool validUnit(CSSParserValue*, Units, CSSParserMode, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); - - bool parseBorderImageQuad(Units, RefPtr<CSSPrimitiveValue>&); - int colorIntFromValue(CSSParserValue*); - double parsedDouble(CSSParserValue*, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); - bool isCalculation(CSSParserValue*); - - UseCounter* m_useCounter; - - CSSTokenizer m_tokenizer; - - friend class TransformOperationInfo; - friend class FilterOperationInfo; -}; - -CSSPropertyID cssPropertyID(const CSSParserString&); -CSSPropertyID cssPropertyID(const String&); -CSSValueID cssValueKeywordID(const CSSParserString&); - -class ShorthandScope { - WTF_MAKE_FAST_ALLOCATED; -public: - ShorthandScope(CSSParser* parser, CSSPropertyID propId) : m_parser(parser) - { - if (!(m_parser->m_inParseShorthand++)) - m_parser->m_currentShorthand = propId; - } - ~ShorthandScope() - { - if (!(--m_parser->m_inParseShorthand)) - m_parser->m_currentShorthand = CSSPropertyInvalid; - } - -private: - CSSParser* m_parser; -}; - -class CSSParser::SourceDataHandler { -public: - virtual void startRuleHeader(CSSRuleSourceData::Type, unsigned offset) = 0; - virtual void endRuleHeader(unsigned offset) = 0; - virtual void startSelector(unsigned offset) = 0; - virtual void endSelector(unsigned offset) = 0; - virtual void startRuleBody(unsigned offset) = 0; - virtual void endRuleBody(unsigned offset, bool error) = 0; - virtual void startEndUnknownRule() = 0; - virtual void startProperty(unsigned offset) = 0; - virtual void endProperty(bool isImportant, bool isParsed, unsigned offset, CSSParser::ErrorType) = 0; - virtual void startComment(unsigned offset) = 0; - virtual void endComment(unsigned offset) = 0; -}; - -String quoteCSSString(const String&); -String quoteCSSStringIfNeeded(const String&); -String quoteCSSURLIfNeeded(const String&); - -bool isValidNthToken(const CSSParserString&); - -inline int cssyylex(void* yylval, CSSParser* parser) -{ - return parser->m_tokenizer.lex(yylval); -} - -} // namespace WebCore - -#endif // CSSParser_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParserMode.cpp b/chromium/third_party/WebKit/Source/core/css/CSSParserMode.cpp index b4d94f8a135..d403eb81fee 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSParserMode.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSParserMode.cpp @@ -32,19 +32,33 @@ namespace WebCore { -CSSParserContext::CSSParserContext(CSSParserMode mode) +CSSParserContext::CSSParserContext(CSSParserMode mode, UseCounter* useCounter) : m_mode(mode) , m_isHTMLDocument(false) , m_useLegacyBackgroundSizeShorthandBehavior(false) + , m_useCounter(useCounter) { } -CSSParserContext::CSSParserContext(const Document& document, const KURL& baseURL, const String& charset) +CSSParserContext::CSSParserContext(const Document& document, UseCounter* useCounter, const KURL& baseURL, const String& charset) : m_baseURL(baseURL.isNull() ? document.baseURL() : baseURL) , m_charset(charset) , m_mode(document.inQuirksMode() ? HTMLQuirksMode : HTMLStandardMode) + , m_referrer(m_baseURL.strippedForUseAsReferrer(), document.referrerPolicy()) , m_isHTMLDocument(document.isHTMLDocument()) , m_useLegacyBackgroundSizeShorthandBehavior(document.settings() ? document.settings()->useLegacyBackgroundSizeShorthandBehavior() : false) + , m_useCounter(useCounter) +{ +} + +CSSParserContext::CSSParserContext(const CSSParserContext& other, UseCounter* useCounter) + : m_baseURL(other.m_baseURL) + , m_charset(other.m_charset) + , m_mode(other.m_mode) + , m_referrer(other.m_referrer) + , m_isHTMLDocument(other.m_isHTMLDocument) + , m_useLegacyBackgroundSizeShorthandBehavior(other.m_useLegacyBackgroundSizeShorthandBehavior) + , m_useCounter(useCounter) { } @@ -59,8 +73,17 @@ bool CSSParserContext::operator==(const CSSParserContext& other) const const CSSParserContext& strictCSSParserContext() { - DEFINE_STATIC_LOCAL(CSSParserContext, strictContext, (HTMLStandardMode)); + DEFINE_STATIC_LOCAL(CSSParserContext, strictContext, (HTMLStandardMode, 0)); return strictContext; } +KURL CSSParserContext::completeURL(const String& url) const +{ + if (url.isNull()) + return KURL(); + if (charset().isEmpty()) + return KURL(baseURL(), url); + return KURL(baseURL(), url, charset()); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParserMode.h b/chromium/third_party/WebKit/Source/core/css/CSSParserMode.h index efcac21a195..b379a68c77f 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSParserMode.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSParserMode.h @@ -32,12 +32,13 @@ #define CSSParserMode_h #include "platform/weborigin/KURL.h" +#include "platform/weborigin/Referrer.h" namespace WebCore { class Document; -// Must not grow beyond 3 bytes, due to packing in StylePropertySet. +// Must not grow beyond 3 bits, due to packing in StylePropertySet. enum CSSParserMode { HTMLStandardMode, HTMLQuirksMode, @@ -88,11 +89,18 @@ inline bool isUseCounterEnabledForMode(CSSParserMode mode) return mode != UASheetMode; } +class UseCounter; + class CSSParserContext { WTF_MAKE_FAST_ALLOCATED; public: - CSSParserContext(CSSParserMode); - CSSParserContext(const Document&, const KURL& baseURL = KURL(), const String& charset = emptyString()); + CSSParserContext(CSSParserMode, UseCounter*); + // FIXME: We shouldn't need the UseCounter argument as we could infer it from the Document + // but some callers want to disable use counting (e.g. the WebInspector). + CSSParserContext(const Document&, UseCounter*, const KURL& baseURL = KURL(), const String& charset = emptyString()); + // FIXME: This constructor shouldn't exist if we properly piped the UseCounter through the CSS + // subsystem. Currently the UseCounter life time is too crazy and we need a way to override it. + CSSParserContext(const CSSParserContext&, UseCounter*); bool operator==(const CSSParserContext&) const; bool operator!=(const CSSParserContext& other) const { return !(*this == other); } @@ -100,6 +108,7 @@ public: CSSParserMode mode() const { return m_mode; } const KURL& baseURL() const { return m_baseURL; } const String& charset() const { return m_charset; } + const Referrer& referrer() const { return m_referrer; } bool isHTMLDocument() const { return m_isHTMLDocument; } // This quirk is to maintain compatibility with Android apps built on @@ -112,13 +121,21 @@ public: void setMode(CSSParserMode mode) { m_mode = mode; } void setBaseURL(const KURL& baseURL) { m_baseURL = baseURL; } void setCharset(const String& charset) { m_charset = charset; } + void setReferrer(const Referrer& referrer) { m_referrer = referrer; } + + KURL completeURL(const String& url) const; + + UseCounter* useCounter() const { return m_useCounter; } private: KURL m_baseURL; String m_charset; CSSParserMode m_mode; + Referrer m_referrer; bool m_isHTMLDocument; bool m_useLegacyBackgroundSizeShorthandBehavior; + + UseCounter* m_useCounter; }; const CSSParserContext& strictCSSParserContext(); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParserValues.cpp b/chromium/third_party/WebKit/Source/core/css/CSSParserValues.cpp index 10a940a6588..62196a77252 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSParserValues.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSParserValues.cpp @@ -29,35 +29,26 @@ namespace WebCore { using namespace WTF; -AtomicString CSSParserString::atomicSubstring(unsigned position, unsigned length) const +static void destroy(Vector<CSSParserValue, 4>& values) { - ASSERT(m_length >= position + length); - - if (is8Bit()) - return AtomicString(characters8() + position, length); - return AtomicString(characters16() + position, length); + size_t numValues = values.size(); + for (size_t i = 0; i < numValues; i++) { + if (values[i].unit == CSSParserValue::Function) + delete values[i].function; + else if (values[i].unit == CSSParserValue::ValueList) + delete values[i].valueList; + } } -void CSSParserString::trimTrailingWhitespace() +void CSSParserValueList::destroyAndClear() { - if (is8Bit()) { - while (m_length > 0 && isHTMLSpace<LChar>(m_data.characters8[m_length - 1])) - --m_length; - } else { - while (m_length > 0 && isHTMLSpace<UChar>(m_data.characters16[m_length - 1])) - --m_length; - } + destroy(m_values); + clearAndLeakValues(); } CSSParserValueList::~CSSParserValueList() { - size_t numValues = m_values.size(); - for (size_t i = 0; i < numValues; i++) { - if (m_values[i].unit == CSSParserValue::Function) - delete m_values[i].function; - else if (m_values[i].unit == CSSParserValue::ValueList) - delete m_values[i].valueList; - } + destroy(m_values); } void CSSParserValueList::addValue(const CSSParserValue& v) @@ -70,28 +61,20 @@ void CSSParserValueList::insertValueAt(unsigned i, const CSSParserValue& v) m_values.insert(i, v); } -void CSSParserValueList::deleteValueAt(unsigned i) +void CSSParserValueList::stealValues(CSSParserValueList& valueList) { - m_values.remove(i); -} - -void CSSParserValueList::extend(CSSParserValueList& valueList) -{ - for (unsigned int i = 0; i < valueList.size(); ++i) + for (unsigned i = 0; i < valueList.size(); ++i) m_values.append(*(valueList.valueAt(i))); + valueList.clearAndLeakValues(); } -PassRefPtr<CSSValue> CSSParserValue::createCSSValue() +PassRefPtrWillBeRawPtr<CSSValue> CSSParserValue::createCSSValue() { - RefPtr<CSSValue> parsedValue; if (id) return CSSPrimitiveValue::createIdentifier(id); - if (unit == CSSParserValue::Operator) { - RefPtr<CSSPrimitiveValue> primitiveValue = CSSPrimitiveValue::createParserOperator(iValue); - primitiveValue->setPrimitiveType(CSSPrimitiveValue::CSS_PARSER_OPERATOR); - return primitiveValue; - } + if (unit == CSSParserValue::Operator) + return CSSPrimitiveValue::createParserOperator(iValue); if (unit == CSSParserValue::Function) return CSSFunctionValue::create(function); if (unit == CSSParserValue::ValueList) @@ -99,7 +82,7 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() if (unit >= CSSParserValue::Q_EMS) return CSSPrimitiveValue::createAllowingMarginQuirk(fValue, CSSPrimitiveValue::CSS_EMS); - CSSPrimitiveValue::UnitTypes primitiveUnit = static_cast<CSSPrimitiveValue::UnitTypes>(unit); + CSSPrimitiveValue::UnitType primitiveUnit = static_cast<CSSPrimitiveValue::UnitType>(unit); switch (primitiveUnit) { case CSSPrimitiveValue::CSS_IDENT: case CSSPrimitiveValue::CSS_PROPERTY_ID: @@ -109,7 +92,6 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() return CSSPrimitiveValue::create(fValue, isInt ? CSSPrimitiveValue::CSS_PARSER_INTEGER : CSSPrimitiveValue::CSS_NUMBER); case CSSPrimitiveValue::CSS_STRING: case CSSPrimitiveValue::CSS_URI: - case CSSPrimitiveValue::CSS_VARIABLE_NAME: case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR: return CSSPrimitiveValue::create(string, primitiveUnit); case CSSPrimitiveValue::CSS_PERCENTAGE: @@ -148,31 +130,29 @@ PassRefPtr<CSSValue> CSSParserValue::createCSSValue() case CSSPrimitiveValue::CSS_DPCM: case CSSPrimitiveValue::CSS_PAIR: case CSSPrimitiveValue::CSS_UNICODE_RANGE: - case CSSPrimitiveValue::CSS_PARSER_OPERATOR: case CSSPrimitiveValue::CSS_PARSER_INTEGER: case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER: + case CSSPrimitiveValue::CSS_PARSER_OPERATOR: case CSSPrimitiveValue::CSS_COUNTER_NAME: case CSSPrimitiveValue::CSS_SHAPE: case CSSPrimitiveValue::CSS_QUAD: case CSSPrimitiveValue::CSS_CALC: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER: case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH: - return 0; + return nullptr; } ASSERT_NOT_REACHED(); - return 0; + return nullptr; } CSSParserSelector::CSSParserSelector() : m_selector(adoptPtr(new CSSSelector())) - , m_functionArgumentSelector(0) { } CSSParserSelector::CSSParserSelector(const QualifiedName& tagQName) : m_selector(adoptPtr(new CSSSelector(tagQName))) - , m_functionArgumentSelector(0) { } @@ -206,7 +186,7 @@ bool CSSParserSelector::isSimple() const if (!m_tagHistory) return true; - if (m_selector->m_match == CSSSelector::Tag) { + if (m_selector->match() == CSSSelector::Tag) { // We can't check against anyQName() here because namespace may not be nullAtom. // Example: // @namespace "http://www.w3.org/2000/svg"; @@ -244,17 +224,17 @@ void CSSParserSelector::prependTagSelector(const QualifiedName& tagQName, bool t m_tagHistory = second.release(); m_selector = adoptPtr(new CSSSelector(tagQName, tagIsForNamespaceRule)); - m_selector->m_relation = CSSSelector::SubSelector; + m_selector->setRelation(CSSSelector::SubSelector); } -CSSParserSelector* CSSParserSelector::findDistributedPseudoElementSelector() const +bool CSSParserSelector::hasHostPseudoSelector() const { CSSParserSelector* selector = const_cast<CSSParserSelector*>(this); do { - if (selector->isDistributedPseudoElement()) - return selector; + if (selector->pseudoType() == CSSSelector::PseudoHost || selector->pseudoType() == CSSSelector::PseudoHostContext) + return true; } while ((selector = selector->tagHistory())); - return 0; + return false; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParserValues.h b/chromium/third_party/WebKit/Source/core/css/CSSParserValues.h index 8efd3250dcf..7ab5836b858 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSParserValues.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSParserValues.h @@ -21,7 +21,7 @@ #ifndef CSSParserValues_h #define CSSParserValues_h -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSSelector.h" #include "core/css/CSSValueList.h" @@ -77,8 +77,6 @@ struct CSSParserString { m_is8Bit = true; } - void trimTrailingWhitespace(); - bool is8Bit() const { return m_is8Bit; } const LChar* characters8() const { ASSERT(is8Bit()); return m_data.characters8; } const UChar* characters16() const { ASSERT(!is8Bit()); return m_data.characters16; } @@ -98,9 +96,11 @@ struct CSSParserString { bool equalIgnoringCase(const char* str) const { - if (is8Bit()) - return WTF::equalIgnoringCase(str, characters8(), length()); - return WTF::equalIgnoringCase(str, characters16(), length()); + bool match = is8Bit() ? WTF::equalIgnoringCase(str, characters8(), length()) : WTF::equalIgnoringCase(str, characters16(), length()); + if (!match) + return false; + ASSERT(strlen(str) >= length()); + return str[length()] == '\0'; } template <size_t strLength> @@ -119,8 +119,6 @@ struct CSSParserString { operator String() const { return is8Bit() ? String(m_data.characters8, m_length) : StringImpl::create8BitIfPossible(m_data.characters16, m_length); } operator AtomicString() const { return is8Bit() ? AtomicString(m_data.characters8, m_length) : AtomicString(m_data.characters16, m_length); } - AtomicString atomicSubstring(unsigned position, unsigned length) const; - bool isFunction() const { return length() > 0 && (*this)[length() - 1] == '('; } union { @@ -161,7 +159,7 @@ struct CSSParserValue { inline void setFromFunction(CSSParserFunction*); inline void setFromValueList(PassOwnPtr<CSSParserValueList>); - PassRefPtr<CSSValue> createCSSValue(); + PassRefPtrWillBeRawPtr<CSSValue> createCSSValue(); }; class CSSParserValueList { @@ -175,8 +173,7 @@ public: void addValue(const CSSParserValue&); void insertValueAt(unsigned, const CSSParserValue&); - void deleteValueAt(unsigned); - void extend(CSSParserValueList&); + void stealValues(CSSParserValueList&); unsigned size() const { return m_values.size(); } unsigned currentIndex() { return m_current; } @@ -189,10 +186,17 @@ public: --m_current; return current(); } + void setCurrentIndex(unsigned index) + { + ASSERT(index < m_values.size()); + if (index < m_values.size()) + m_current = index; + } CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; } - void clear() { m_values.clear(); } + void clearAndLeakValues() { m_values.clear(); m_current = 0;} + void destroyAndClear(); private: unsigned m_current; @@ -219,23 +223,20 @@ 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 setMatch(CSSSelector::Match value) { m_selector->m_match = value; } - void setRelation(CSSSelector::Relation value) { m_selector->m_relation = value; } + void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); } + void setRelation(CSSSelector::Relation value) { m_selector->setRelation(value); } void setForPage() { m_selector->setForPage(); } void setRelationIsAffectedByPseudoContent() { m_selector->setRelationIsAffectedByPseudoContent(); } bool relationIsAffectedByPseudoContent() const { return m_selector->relationIsAffectedByPseudoContent(); } void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector); - CSSParserSelector* functionArgumentSelector() const { return m_functionArgumentSelector; } - void setFunctionArgumentSelector(CSSParserSelector* selector) { m_functionArgumentSelector = selector; } - bool isDistributedPseudoElement() const { return m_selector->isDistributedPseudoElement(); } - CSSParserSelector* findDistributedPseudoElementSelector() const; + bool hasHostPseudoSelector() const; bool isContentPseudoElement() const { return m_selector->isContentPseudoElement(); } CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); } bool isCustomPseudoElement() const { return m_selector->isCustomPseudoElement(); } - bool needsCrossingTreeScopeBoundary() const { return isCustomPseudoElement() || pseudoType() == CSSSelector::PseudoCue; } + bool crossesTreeScopes() const { return isCustomPseudoElement() || pseudoType() == CSSSelector::PseudoCue || pseudoType() == CSSSelector::PseudoShadow; } bool isSimple() const; bool hasShadowPseudo() const; @@ -250,7 +251,6 @@ public: private: OwnPtr<CSSSelector> m_selector; OwnPtr<CSSParserSelector> m_tagHistory; - CSSParserSelector* m_functionArgumentSelector; }; inline bool CSSParserSelector::hasShadowPseudo() const @@ -274,6 +274,7 @@ inline void CSSParserValue::setFromFunction(CSSParserFunction* function) id = CSSValueInvalid; this->function = function; unit = Function; + isInt = false; } inline void CSSParserValue::setFromValueList(PassOwnPtr<CSSParserValueList> valueList) @@ -281,6 +282,7 @@ inline void CSSParserValue::setFromValueList(PassOwnPtr<CSSParserValueList> valu id = CSSValueInvalid; this->valueList = valueList.leakPtr(); unit = ValueList; + isInt = false; } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParserValuesTest.cpp b/chromium/third_party/WebKit/Source/core/css/CSSParserValuesTest.cpp index 6d1ac8b939d..5e7bd926f40 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSParserValuesTest.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSParserValuesTest.cpp @@ -56,4 +56,45 @@ TEST(CSSParserValuesTest, InitWithEmpty16BitsString) ASSERT_EQ(0u, cssParserString.length()); } +TEST(CSSParserValuesTest, EqualIgnoringCase8BitsString) +{ + CSSParserString cssParserString; + String string8bit("sHaDOw"); + cssParserString.init(string8bit, 0, string8bit.length()); + + ASSERT_TRUE(cssParserString.equalIgnoringCase("shadow")); + ASSERT_TRUE(cssParserString.equalIgnoringCase("ShaDow")); + ASSERT_FALSE(cssParserString.equalIgnoringCase("shadow-all")); + ASSERT_FALSE(cssParserString.equalIgnoringCase("sha")); + ASSERT_FALSE(cssParserString.equalIgnoringCase("abCD")); +} + +TEST(CSSParserValuesTest, EqualIgnoringCase16BitsString) +{ + String string16bit("sHaDOw"); + string16bit.ensure16Bit(); + + CSSParserString cssParserString; + cssParserString.init(string16bit, 0, string16bit.length()); + + ASSERT_TRUE(cssParserString.equalIgnoringCase("shadow")); + ASSERT_TRUE(cssParserString.equalIgnoringCase("ShaDow")); + ASSERT_FALSE(cssParserString.equalIgnoringCase("shadow-all")); + ASSERT_FALSE(cssParserString.equalIgnoringCase("sha")); + ASSERT_FALSE(cssParserString.equalIgnoringCase("abCD")); +} + +TEST(CSSParserValuesTest, CSSParserValuelistClear) +{ + CSSParserValueList list; + for (int i = 0; i < 3; ++i) { + CSSParserValue value; + value.setFromNumber(3); + list.addValue(value); + } + list.clearAndLeakValues(); + ASSERT_FALSE(list.size()); + ASSERT_FALSE(list.currentIndex()); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp index eb350e7a9c0..97497512b54 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.cpp @@ -25,7 +25,7 @@ #include "core/css/CSSBasicShapes.h" #include "core/css/CSSCalculationValue.h" #include "core/css/CSSHelper.h" -#include "core/css/CSSParser.h" +#include "core/css/CSSMarkup.h" #include "core/css/CSSToLengthConversionData.h" #include "core/css/Counter.h" #include "core/css/Pair.h" @@ -35,8 +35,9 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/Node.h" #include "core/rendering/style/RenderStyle.h" +#include "platform/Decimal.h" #include "platform/LayoutUnit.h" -#include "wtf/DecimalNumber.h" +#include "platform/fonts/FontMetrics.h" #include "wtf/StdLibExtras.h" #include "wtf/text/StringBuffer.h" #include "wtf/text/StringBuilder.h" @@ -50,7 +51,7 @@ namespace WebCore { const int maxValueForCssLength = INT_MAX / kFixedPointDenominator - 2; const int minValueForCssLength = INT_MIN / kFixedPointDenominator + 2; -static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitTypes unitType) +static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitType unitType) { switch (unitType) { case CSSPrimitiveValue::CSS_CALC: @@ -105,7 +106,6 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit case CSSPrimitiveValue::CSS_UNICODE_RANGE: case CSSPrimitiveValue::CSS_UNKNOWN: case CSSPrimitiveValue::CSS_URI: - case CSSPrimitiveValue::CSS_VARIABLE_NAME: return false; } @@ -113,7 +113,44 @@ static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::Unit return false; } -CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValue::UnitTypes type) +typedef HashMap<String, CSSPrimitiveValue::UnitType> StringToUnitTable; + +StringToUnitTable createStringToUnitTable() +{ + StringToUnitTable table; + table.set(String("em"), CSSPrimitiveValue::CSS_EMS); + table.set(String("ex"), CSSPrimitiveValue::CSS_EXS); + table.set(String("px"), CSSPrimitiveValue::CSS_PX); + table.set(String("cm"), CSSPrimitiveValue::CSS_CM); + table.set(String("mm"), CSSPrimitiveValue::CSS_MM); + table.set(String("in"), CSSPrimitiveValue::CSS_IN); + table.set(String("pt"), CSSPrimitiveValue::CSS_PT); + table.set(String("pc"), CSSPrimitiveValue::CSS_PC); + table.set(String("deg"), CSSPrimitiveValue::CSS_DEG); + table.set(String("rad"), CSSPrimitiveValue::CSS_RAD); + table.set(String("grad"), CSSPrimitiveValue::CSS_GRAD); + table.set(String("ms"), CSSPrimitiveValue::CSS_MS); + table.set(String("s"), CSSPrimitiveValue::CSS_S); + table.set(String("hz"), CSSPrimitiveValue::CSS_HZ); + table.set(String("khz"), CSSPrimitiveValue::CSS_KHZ); + table.set(String("dpi"), CSSPrimitiveValue::CSS_DPI); + table.set(String("dpcm"), CSSPrimitiveValue::CSS_DPCM); + table.set(String("dppx"), CSSPrimitiveValue::CSS_DPPX); + table.set(String("vw"), CSSPrimitiveValue::CSS_VW); + table.set(String("vh"), CSSPrimitiveValue::CSS_VH); + table.set(String("vmax"), CSSPrimitiveValue::CSS_VMIN); + table.set(String("vmin"), CSSPrimitiveValue::CSS_VMAX); + return table; +} + + +CSSPrimitiveValue::UnitType CSSPrimitiveValue::fromName(const String& unit) +{ + DEFINE_STATIC_LOCAL(StringToUnitTable, unitTable, (createStringToUnitTable())); + return unitTable.get(unit.lower()); +} + +CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(UnitType type) { // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions // between CSS_PX and relative lengths (see cssPixelsPerInch comment in core/css/CSSHelper.h for the topic treatment). @@ -140,11 +177,6 @@ CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValu case CSS_HZ: case CSS_KHZ: return CSSPrimitiveValue::UFrequency; - case CSS_VW: - case CSS_VH: - case CSS_VMIN: - case CSS_VMAX: - return CSSPrimitiveValue::UViewportPercentageLength; case CSS_DPPX: case CSS_DPI: case CSS_DPCM: @@ -175,13 +207,13 @@ static CSSTextCache& cssTextCache() return cache; } -unsigned short CSSPrimitiveValue::primitiveType() const +CSSPrimitiveValue::UnitType CSSPrimitiveValue::primitiveType() const { if (m_primitiveUnitType == CSS_PROPERTY_ID || m_primitiveUnitType == CSS_VALUE_ID) return CSS_IDENT; if (m_primitiveUnitType != CSS_CALC) - return m_primitiveUnitType; + return static_cast<UnitType>(m_primitiveUnitType); switch (m_value.calc->category()) { case CalcNumber: @@ -194,8 +226,6 @@ unsigned short CSSPrimitiveValue::primitiveType() const return CSS_CALC_PERCENTAGE_WITH_NUMBER; case CalcPercentLength: return CSS_CALC_PERCENTAGE_WITH_LENGTH; - case CalcVariable: - return CSS_UNKNOWN; // The type of a calculation containing a variable cannot be known until the value of the variable is determined. case CalcOther: return CSS_UNKNOWN; } @@ -242,14 +272,15 @@ CSSPrimitiveValue::CSSPrimitiveValue(CSSPropertyID propertyID) m_value.propertyID = propertyID; } -CSSPrimitiveValue::CSSPrimitiveValue(int parserOperator) +CSSPrimitiveValue::CSSPrimitiveValue(int parserOperator, UnitType type) : CSSValue(PrimitiveClass) { + ASSERT(type == CSS_PARSER_OPERATOR); m_primitiveUnitType = CSS_PARSER_OPERATOR; m_value.parserOperator = parserOperator; } -CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type) +CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitType type) : CSSValue(PrimitiveClass) { m_primitiveUnitType = type; @@ -257,7 +288,7 @@ CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type) m_value.num = num; } -CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type) +CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitType type) : CSSValue(PrimitiveClass) { m_primitiveUnitType = type; @@ -265,10 +296,16 @@ CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type) m_value.string->ref(); } +CSSPrimitiveValue::CSSPrimitiveValue(const LengthSize& lengthSize, const RenderStyle& style) + : CSSValue(PrimitiveClass) +{ + init(lengthSize, style); +} -CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color) +CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color, UnitType type) : CSSValue(PrimitiveClass) { + ASSERT(type == CSS_RGBCOLOR); m_primitiveUnitType = CSS_RGBCOLOR; m_value.rgbcolor = color; } @@ -278,136 +315,116 @@ CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, float zoom) { switch (length.type()) { case Auto: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueAuto; + break; case Intrinsic: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueIntrinsic; + break; case MinIntrinsic: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueMinIntrinsic; + break; case MinContent: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueMinContent; + break; case MaxContent: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueMaxContent; + break; case FillAvailable: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueWebkitFillAvailable; + break; case FitContent: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueWebkitFitContent; + break; case ExtendToZoom: + m_primitiveUnitType = CSS_VALUE_ID; + m_value.valueID = CSSValueInternalExtendToZoom; + break; case Percent: - case ViewportPercentageWidth: - case ViewportPercentageHeight: - case ViewportPercentageMin: - case ViewportPercentageMax: - init(length); - return; + m_primitiveUnitType = CSS_PERCENTAGE; + ASSERT(std::isfinite(length.percent())); + m_value.num = length.percent(); + break; case Fixed: m_primitiveUnitType = CSS_PX; m_value.num = length.value() / zoom; - return; - case Calculated: - init(CSSCalcValue::create(length.calculationValue(), zoom)); - return; + break; + case Calculated: { + const CalculationValue& calc = length.calculationValue(); + if (calc.pixels() && calc.percent()) { + init(CSSCalcValue::create( + CSSCalcValue::createExpressionNode(calc.pixels() / zoom, calc.percent()), + calc.isNonNegative() ? ValueRangeNonNegative : ValueRangeAll)); + break; + } + if (calc.percent()) { + m_primitiveUnitType = CSS_PERCENTAGE; + m_value.num = calc.percent(); + } else { + m_primitiveUnitType = CSS_PX; + m_value.num = calc.pixels() / zoom; + } + if (m_value.num < 0 && calc.isNonNegative()) + m_value.num = 0; + break; + } + case DeviceWidth: + case DeviceHeight: case Undefined: ASSERT_NOT_REACHED(); break; } } -void CSSPrimitiveValue::init(const Length& length) +void CSSPrimitiveValue::init(const LengthSize& lengthSize, const RenderStyle& style) { - switch (length.type()) { - case Auto: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueAuto; - break; - case Fixed: - m_primitiveUnitType = CSS_PX; - m_value.num = length.value(); - break; - case Intrinsic: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueIntrinsic; - break; - case MinIntrinsic: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueMinIntrinsic; - break; - case MinContent: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueMinContent; - break; - case MaxContent: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueMaxContent; - break; - case FillAvailable: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueWebkitFillAvailable; - break; - case FitContent: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueWebkitFitContent; - break; - case ExtendToZoom: - m_primitiveUnitType = CSS_VALUE_ID; - m_value.valueID = CSSValueInternalExtendToZoom; - break; - case Percent: - m_primitiveUnitType = CSS_PERCENTAGE; - ASSERT(std::isfinite(length.percent())); - m_value.num = length.percent(); - break; - case ViewportPercentageWidth: - m_primitiveUnitType = CSS_VW; - m_value.num = length.viewportPercentageLength(); - break; - case ViewportPercentageHeight: - m_primitiveUnitType = CSS_VH; - m_value.num = length.viewportPercentageLength(); - break; - case ViewportPercentageMin: - m_primitiveUnitType = CSS_VMIN; - m_value.num = length.viewportPercentageLength(); - break; - case ViewportPercentageMax: - m_primitiveUnitType = CSS_VMAX; - m_value.num = length.viewportPercentageLength(); - break; - case Calculated: - case Undefined: - ASSERT_NOT_REACHED(); - break; - } + m_primitiveUnitType = CSS_PAIR; + m_hasCachedCSSText = false; + m_value.pair = Pair::create(create(lengthSize.width(), style.effectiveZoom()), create(lengthSize.height(), style.effectiveZoom()), Pair::KeepIdenticalValues).leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Counter> c) +void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr<Counter> c) { m_primitiveUnitType = CSS_COUNTER; m_hasCachedCSSText = false; m_value.counter = c.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Rect> r) +void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr<Rect> r) { m_primitiveUnitType = CSS_RECT; m_hasCachedCSSText = false; m_value.rect = r.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Quad> quad) +void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr<Quad> quad) { m_primitiveUnitType = CSS_QUAD; m_hasCachedCSSText = false; m_value.quad = quad.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<Pair> p) +void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr<Pair> p) { m_primitiveUnitType = CSS_PAIR; m_hasCachedCSSText = false; m_value.pair = p.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<CSSCalcValue> c) +void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr<CSSCalcValue> c) { m_primitiveUnitType = CSS_CALC; m_hasCachedCSSText = false; m_value.calc = c.leakRef(); } -void CSSPrimitiveValue::init(PassRefPtr<CSSBasicShape> shape) +void CSSPrimitiveValue::init(PassRefPtrWillBeRawPtr<CSSBasicShape> shape) { m_primitiveUnitType = CSS_SHAPE; m_hasCachedCSSText = false; @@ -421,37 +438,54 @@ CSSPrimitiveValue::~CSSPrimitiveValue() void CSSPrimitiveValue::cleanup() { - switch (static_cast<UnitTypes>(m_primitiveUnitType)) { + switch (static_cast<UnitType>(m_primitiveUnitType)) { case CSS_STRING: case CSS_URI: case CSS_ATTR: case CSS_COUNTER_NAME: - case CSS_VARIABLE_NAME: case CSS_PARSER_HEXCOLOR: if (m_value.string) m_value.string->deref(); break; case CSS_COUNTER: + // We must not call deref() when oilpan is enabled because m_value.counter is traced. +#if !ENABLE(OILPAN) m_value.counter->deref(); +#endif break; case CSS_RECT: + // We must not call deref() when oilpan is enabled because m_value.rect is traced. +#if !ENABLE(OILPAN) m_value.rect->deref(); +#endif break; case CSS_QUAD: + // We must not call deref() when oilpan is enabled because m_value.quad is traced. +#if !ENABLE(OILPAN) m_value.quad->deref(); +#endif break; case CSS_PAIR: + // We must not call deref() when oilpan is enabled because m_value.pair is traced. +#if !ENABLE(OILPAN) m_value.pair->deref(); +#endif break; case CSS_CALC: + // We must not call deref() when oilpan is enabled because m_value.calc is traced. +#if !ENABLE(OILPAN) m_value.calc->deref(); +#endif break; case CSS_CALC_PERCENTAGE_WITH_NUMBER: case CSS_CALC_PERCENTAGE_WITH_LENGTH: ASSERT_NOT_REACHED(); break; case CSS_SHAPE: + // We must not call deref() when oilpan is enabled because m_value.shape is traced. +#if !ENABLE(OILPAN) m_value.shape->deref(); +#endif break; case CSS_NUMBER: case CSS_PARSER_INTEGER: @@ -554,11 +588,14 @@ template<> double CSSPrimitiveValue::computeLength(const CSSToLengthConversionDa double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& conversionData) { + // The logic in this function is duplicated in MediaValues::computeLength + // because MediaValues::computeLength needs nearly identical logic, but we haven't found a way to make + // CSSPrimitiveValue::computeLengthDouble more generic (to solve both cases) without hurting performance. if (m_primitiveUnitType == CSS_CALC) return m_value.calc->computeLengthPx(conversionData); const RenderStyle& style = conversionData.style(); - const RenderStyle& rootStyle = conversionData.rootStyle(); + const RenderStyle* rootStyle = conversionData.rootStyle(); bool computingFontSize = conversionData.computingFontSize(); double factor; @@ -577,7 +614,10 @@ double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& c factor = (computingFontSize ? style.fontDescription().specifiedSize() : style.fontDescription().computedSize()) / 2.0; break; case CSS_REMS: - factor = computingFontSize ? rootStyle.fontDescription().specifiedSize() : rootStyle.fontDescription().computedSize(); + if (rootStyle) + factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize(); + else + factor = 1.0; break; case CSS_CHS: factor = style.fontMetrics().zeroWidth(); @@ -600,6 +640,18 @@ double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& c case CSS_PC: factor = cssPixelsPerPica; break; + case CSS_VW: + factor = conversionData.viewportWidthPercent(); + break; + case CSS_VH: + factor = conversionData.viewportHeightPercent(); + break; + case CSS_VMIN: + factor = conversionData.viewportMinPercent(); + break; + case CSS_VMAX: + factor = conversionData.viewportMaxPercent(); + break; case CSS_CALC_PERCENTAGE_WITH_LENGTH: case CSS_CALC_PERCENTAGE_WITH_NUMBER: ASSERT_NOT_REACHED(); @@ -619,15 +671,29 @@ double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& c return result * conversionData.zoom(); } +void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray& lengthArray, double multiplier) const +{ + ASSERT(lengthArray.size() == LengthUnitTypeCount); + + if (m_primitiveUnitType == CSS_CALC) { + cssCalcValue()->accumulateLengthArray(lengthArray, multiplier); + return; + } + + LengthUnitType lengthType; + if (unitTypeToLengthUnitType(static_cast<UnitType>(m_primitiveUnitType), lengthType)) + lengthArray.at(lengthType) += m_value.num * conversionToCanonicalUnitsScaleFactor(static_cast<UnitType>(m_primitiveUnitType)) * multiplier; +} + void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionState& exceptionState) { // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. // No other engine supports mutating style through this API. Computed style is always read-only anyway. // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation. - exceptionState.throwUninformativeAndGenericDOMException(NoModificationAllowedError); + exceptionState.throwDOMException(NoModificationAllowedError, "CSSPrimitiveValue objects are read-only."); } -double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(unsigned short unitType) +double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(UnitType unitType) { double factor = 1.0; // FIXME: the switch can be replaced by an array of scale factors. @@ -679,22 +745,22 @@ double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(unsigned short u return factor; } -double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionState& exceptionState) const +double CSSPrimitiveValue::getDoubleValue(UnitType unitType, ExceptionState& exceptionState) const { double result = 0; - bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result); + bool success = getDoubleValueInternal(unitType, &result); if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "Failed to obtain a double value."); return 0.0; } return result; } -double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const +double CSSPrimitiveValue::getDoubleValue(UnitType unitType) const { double result = 0; - getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result); + getDoubleValueInternal(unitType, &result); return result; } @@ -703,9 +769,9 @@ double CSSPrimitiveValue::getDoubleValue() const return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue(); } -CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category) +CSSPrimitiveValue::UnitType CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category) { - // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit + // The canonical unit type is chosen according to the way BisonCSSParser::validUnit() chooses the default unit // in each category (based on unitflags). switch (category) { case UNumber: @@ -720,8 +786,6 @@ CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(Uni return CSS_DEG; case UFrequency: return CSS_HZ; - case UViewportPercentageLength: - return CSS_UNKNOWN; // Cannot convert between numbers and relative lengths. case UResolution: return CSS_DPPX; default: @@ -729,12 +793,12 @@ CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(Uni } } -bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const +bool CSSPrimitiveValue::getDoubleValueInternal(UnitType requestedUnitType, double* result) const { - if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitTypes>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType)) + if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitType>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType)) return false; - UnitTypes sourceUnitType = static_cast<UnitTypes>(primitiveType()); + UnitType sourceUnitType = primitiveType(); if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) { *result = getDoubleValue(); return true; @@ -743,7 +807,7 @@ bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, doub UnitCategory sourceCategory = unitCategory(sourceUnitType); ASSERT(sourceCategory != UOther); - UnitTypes targetUnitType = requestedUnitType; + UnitType targetUnitType = requestedUnitType; UnitCategory targetCategory = unitCategory(targetUnitType); ASSERT(targetCategory != UOther); @@ -759,7 +823,7 @@ bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, doub } if (sourceUnitType == CSS_NUMBER) { - // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode. + // We interpret conversion from CSS_NUMBER in the same way as BisonCSSParser::validUnit() while using non-strict mode. sourceUnitType = canonicalUnitTypeForCategory(targetCategory); if (sourceUnitType == CSS_UNKNOWN) return false; @@ -779,12 +843,85 @@ bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, doub return true; } +bool CSSPrimitiveValue::unitTypeToLengthUnitType(UnitType unitType, LengthUnitType& lengthType) +{ + switch (unitType) { + case CSSPrimitiveValue::CSS_PX: + case CSSPrimitiveValue::CSS_CM: + case CSSPrimitiveValue::CSS_MM: + case CSSPrimitiveValue::CSS_IN: + case CSSPrimitiveValue::CSS_PT: + case CSSPrimitiveValue::CSS_PC: + lengthType = UnitTypePixels; + return true; + case CSSPrimitiveValue::CSS_EMS: + lengthType = UnitTypeFontSize; + return true; + case CSSPrimitiveValue::CSS_EXS: + lengthType = UnitTypeFontXSize; + return true; + case CSSPrimitiveValue::CSS_REMS: + lengthType = UnitTypeRootFontSize; + return true; + case CSSPrimitiveValue::CSS_CHS: + lengthType = UnitTypeZeroCharacterWidth; + return true; + case CSSPrimitiveValue::CSS_PERCENTAGE: + lengthType = UnitTypePercentage; + return true; + case CSSPrimitiveValue::CSS_VW: + lengthType = UnitTypeViewportWidth; + return true; + case CSSPrimitiveValue::CSS_VH: + lengthType = UnitTypeViewportHeight; + return true; + case CSSPrimitiveValue::CSS_VMIN: + lengthType = UnitTypeViewportMin; + return true; + case CSSPrimitiveValue::CSS_VMAX: + lengthType = UnitTypeViewportMax; + return true; + default: + return false; + } +} + +CSSPrimitiveValue::UnitType CSSPrimitiveValue::lengthUnitTypeToUnitType(LengthUnitType type) +{ + switch (type) { + case UnitTypePixels: + return CSSPrimitiveValue::CSS_PX; + case UnitTypeFontSize: + return CSSPrimitiveValue::CSS_EMS; + case UnitTypeFontXSize: + return CSSPrimitiveValue::CSS_EXS; + case UnitTypeRootFontSize: + return CSSPrimitiveValue::CSS_REMS; + case UnitTypeZeroCharacterWidth: + return CSSPrimitiveValue::CSS_CHS; + case UnitTypePercentage: + return CSSPrimitiveValue::CSS_PERCENTAGE; + case UnitTypeViewportWidth: + return CSSPrimitiveValue::CSS_VW; + case UnitTypeViewportHeight: + return CSSPrimitiveValue::CSS_VH; + case UnitTypeViewportMin: + return CSSPrimitiveValue::CSS_VMIN; + case UnitTypeViewportMax: + return CSSPrimitiveValue::CSS_VMAX; + case LengthUnitTypeCount: + break; + } + ASSERT_NOT_REACHED(); + return CSSPrimitiveValue::CSS_UNKNOWN; +} + void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionState& exceptionState) { // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects. // No other engine supports mutating style through this API. Computed style is always read-only anyway. // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation. - exceptionState.throwUninformativeAndGenericDOMException(NoModificationAllowedError); + exceptionState.throwDOMException(NoModificationAllowedError, "CSSPrimitiveValue objects are read-only."); } String CSSPrimitiveValue::getStringValue(ExceptionState& exceptionState) const @@ -793,14 +930,13 @@ String CSSPrimitiveValue::getStringValue(ExceptionState& exceptionState) const case CSS_STRING: case CSS_ATTR: case CSS_URI: - case CSS_VARIABLE_NAME: return m_value.string; case CSS_VALUE_ID: return valueName(m_value.valueID); case CSS_PROPERTY_ID: return propertyName(m_value.propertyID); default: - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "This object's value cannot be represented as a string."); break; } @@ -813,7 +949,6 @@ String CSSPrimitiveValue::getStringValue() const case CSS_STRING: case CSS_ATTR: case CSS_URI: - case CSS_VARIABLE_NAME: return m_value.string; case CSS_VALUE_ID: return valueName(m_value.valueID); @@ -829,7 +964,7 @@ String CSSPrimitiveValue::getStringValue() const Counter* CSSPrimitiveValue::getCounterValue(ExceptionState& exceptionState) const { if (m_primitiveUnitType != CSS_COUNTER) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "This object is not a counter value."); return 0; } @@ -839,7 +974,7 @@ Counter* CSSPrimitiveValue::getCounterValue(ExceptionState& exceptionState) cons Rect* CSSPrimitiveValue::getRectValue(ExceptionState& exceptionState) const { if (m_primitiveUnitType != CSS_RECT) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "This object is not a rect value."); return 0; } @@ -849,18 +984,18 @@ Rect* CSSPrimitiveValue::getRectValue(ExceptionState& exceptionState) const Quad* CSSPrimitiveValue::getQuadValue(ExceptionState& exceptionState) const { if (m_primitiveUnitType != CSS_QUAD) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "This object is not a quad value."); return 0; } return m_value.quad; } -PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionState& exceptionState) const { if (m_primitiveUnitType != CSS_RGBCOLOR) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); - return 0; + exceptionState.throwDOMException(InvalidAccessError, "This object is not an RGB color value."); + return nullptr; } // FIMXE: This should not return a new object for each invocation. @@ -870,7 +1005,7 @@ PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionState& excepti Pair* CSSPrimitiveValue::getPairValue(ExceptionState& exceptionState) const { if (m_primitiveUnitType != CSS_PAIR) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); + exceptionState.throwDOMException(InvalidAccessError, "This object is not a pair value."); return 0; } @@ -879,16 +1014,10 @@ Pair* CSSPrimitiveValue::getPairValue(ExceptionState& exceptionState) const static String formatNumber(double number, const char* suffix, unsigned suffixLength) { - DecimalNumber decimal(number); - - StringBuffer<LChar> buffer(decimal.bufferLengthForStringDecimal() + suffixLength); - unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length()); - ASSERT(length + suffixLength == buffer.length()); - - for (unsigned i = 0; i < suffixLength; ++i) - buffer[length + i] = static_cast<LChar>(suffix[i]); - - return String::adopt(buffer); + Decimal decimal = Decimal::fromDouble(number); + String result = decimal.toString(); + result.append(suffix, suffixLength); + return result; } template <unsigned characterCount> @@ -897,6 +1026,99 @@ ALWAYS_INLINE static String formatNumber(double number, const char (&characters) return formatNumber(number, characters, characterCount - 1); } +static String formatNumber(double number, const char* characters) +{ + return formatNumber(number, characters, strlen(characters)); +} + +const char* CSSPrimitiveValue::unitTypeToString(UnitType type) +{ + switch (type) { + case CSS_NUMBER: + case CSS_PARSER_INTEGER: + return ""; + case CSS_PERCENTAGE: + return "%"; + case CSS_EMS: + return "em"; + case CSS_EXS: + return "ex"; + case CSS_REMS: + return "rem"; + case CSS_CHS: + return "ch"; + case CSS_PX: + return "px"; + case CSS_CM: + return "cm"; + case CSS_DPPX: + return "dppx"; + case CSS_DPI: + return "dpi"; + case CSS_DPCM: + return "dpcm"; + case CSS_MM: + return "mm"; + case CSS_IN: + return "in"; + case CSS_PT: + return "pt"; + case CSS_PC: + return "pc"; + case CSS_DEG: + return "deg"; + case CSS_RAD: + return "rad"; + case CSS_GRAD: + return "grad"; + case CSS_MS: + return "ms"; + case CSS_S: + return "s"; + case CSS_HZ: + return "hz"; + case CSS_KHZ: + return "khz"; + case CSS_TURN: + return "turn"; + case CSS_FR: + return "fr"; + case CSS_VW: + return "vw"; + case CSS_VH: + return "vh"; + case CSS_VMIN: + return "vmin"; + case CSS_VMAX: + return "vmax"; + case CSS_UNKNOWN: + case CSS_DIMENSION: + case CSS_STRING: + case CSS_URI: + case CSS_VALUE_ID: + case CSS_PROPERTY_ID: + case CSS_ATTR: + case CSS_COUNTER_NAME: + case CSS_COUNTER: + case CSS_RECT: + case CSS_QUAD: + case CSS_RGBCOLOR: + case CSS_PARSER_HEXCOLOR: + case CSS_PAIR: + case CSS_PARSER_OPERATOR: + case CSS_PARSER_IDENTIFIER: + case CSS_CALC: + case CSS_SHAPE: + case CSS_IDENT: + case CSS_UNICODE_RANGE: + case CSS_CALC_PERCENTAGE_WITH_NUMBER: + case CSS_CALC_PERCENTAGE_WITH_LENGTH: + break; + }; + ASSERT_NOT_REACHED(); + return ""; +} + String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) const { // FIXME: return the original value instead of a generated one (e.g. color @@ -914,74 +1136,34 @@ String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) c break; case CSS_NUMBER: case CSS_PARSER_INTEGER: - text = formatNumber(m_value.num, ""); - break; case CSS_PERCENTAGE: - text = formatNumber(m_value.num, "%"); - break; case CSS_EMS: - text = formatNumber(m_value.num, "em"); - break; case CSS_EXS: - text = formatNumber(m_value.num, "ex"); - break; case CSS_REMS: - text = formatNumber(m_value.num, "rem"); - break; case CSS_CHS: - text = formatNumber(m_value.num, "ch"); - break; case CSS_PX: - text = formatNumber(m_value.num, "px"); - break; case CSS_CM: - text = formatNumber(m_value.num, "cm"); - break; case CSS_DPPX: - text = formatNumber(m_value.num, "dppx"); - break; case CSS_DPI: - text = formatNumber(m_value.num, "dpi"); - break; case CSS_DPCM: - text = formatNumber(m_value.num, "dpcm"); - break; case CSS_MM: - text = formatNumber(m_value.num, "mm"); - break; case CSS_IN: - text = formatNumber(m_value.num, "in"); - break; case CSS_PT: - text = formatNumber(m_value.num, "pt"); - break; case CSS_PC: - text = formatNumber(m_value.num, "pc"); - break; case CSS_DEG: - text = formatNumber(m_value.num, "deg"); - break; case CSS_RAD: - text = formatNumber(m_value.num, "rad"); - break; case CSS_GRAD: - text = formatNumber(m_value.num, "grad"); - break; case CSS_MS: - text = formatNumber(m_value.num, "ms"); - break; case CSS_S: - text = formatNumber(m_value.num, "s"); - break; case CSS_HZ: - text = formatNumber(m_value.num, "hz"); - break; case CSS_KHZ: - text = formatNumber(m_value.num, "khz"); - break; case CSS_TURN: - text = formatNumber(m_value.num, "turn"); - break; + case CSS_FR: + case CSS_VW: + case CSS_VH: + case CSS_VMIN: + case CSS_VMAX: + text = formatNumber(m_value.num, unitTypeToString((UnitType)m_primitiveUnitType)); case CSS_DIMENSION: // FIXME: We currently don't handle CSS_DIMENSION properly as we don't store // the actual dimension, just the numeric value as a string. @@ -1046,37 +1228,9 @@ String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) c if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR) Color::parseHexColor(m_value.string, rgbColor); Color color(rgbColor); - - StringBuilder result; - result.reserveCapacity(32); - bool colorHasAlpha = color.hasAlpha(); - if (colorHasAlpha) - result.append("rgba(", 5); - else - result.append("rgb(", 4); - - result.appendNumber(static_cast<unsigned char>(color.red())); - result.append(", ", 2); - - result.appendNumber(static_cast<unsigned char>(color.green())); - result.append(", ", 2); - - result.appendNumber(static_cast<unsigned char>(color.blue())); - if (colorHasAlpha) { - result.append(", ", 2); - - NumberToStringBuffer buffer; - const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true); - result.append(alphaString, strlen(alphaString)); - } - - result.append(')'); - text = result.toString(); + text = color.serializedAsCSSComponentValue(); break; } - case CSS_FR: - text = formatNumber(m_value.num, "fr"); - break; case CSS_PAIR: text = getPairValue()->cssText(); break; @@ -1094,21 +1248,6 @@ String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) c case CSS_SHAPE: text = m_value.shape->cssText(); break; - case CSS_VW: - text = formatNumber(m_value.num, "vw"); - break; - case CSS_VH: - text = formatNumber(m_value.num, "vh"); - break; - case CSS_VMIN: - text = formatNumber(m_value.num, "vmin"); - break; - case CSS_VMAX: - text = formatNumber(m_value.num, "vmax"); - break; - case CSS_VARIABLE_NAME: - text = "var(" + String(m_value.string) + ")"; - break; } ASSERT(!cssTextCache().contains(this)); @@ -1117,80 +1256,16 @@ String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) c return text; } -String CSSPrimitiveValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const { - if (isVariableName()) { - AtomicString variableName(m_value.string); - if (variables.contains(variableName)) - return variables.get(variableName); - } - if (CSSCalcValue* calcValue = cssCalcValue()) - return calcValue->customSerializeResolvingVariables(variables); - if (Pair* pairValue = getPairValue()) - return pairValue->serializeResolvingVariables(variables); - if (Rect* rectVal = getRectValue()) - return rectVal->serializeResolvingVariables(variables); - if (Quad* quadVal = getQuadValue()) - return quadVal->serializeResolvingVariables(variables); - if (CSSBasicShape* shapeValue = getShapeValue()) - return shapeValue->serializeResolvingVariables(variables); - return customCSSText(); -} - -bool CSSPrimitiveValue::hasVariableReference() const -{ - if (CSSCalcValue* calcValue = cssCalcValue()) - return calcValue->hasVariableReference(); - if (Pair* pairValue = getPairValue()) - return pairValue->hasVariableReference(); - if (Quad* quadValue = getQuadValue()) - return quadValue->hasVariableReference(); - if (Rect* rectValue = getRectValue()) - return rectValue->hasVariableReference(); - if (CSSBasicShape* shapeValue = getShapeValue()) - return shapeValue->hasVariableReference(); - return isVariableName(); -} - -void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const -{ - if (m_primitiveUnitType == CSS_URI) - addSubresourceURL(urls, styleSheet->completeURL(m_value.string)); -} - -Length CSSPrimitiveValue::viewportPercentageLength() -{ - ASSERT(isViewportPercentageLength()); - Length viewportLength; - switch (m_primitiveUnitType) { - case CSS_VW: - viewportLength = Length(getDoubleValue(), ViewportPercentageWidth); - break; - case CSS_VH: - viewportLength = Length(getDoubleValue(), ViewportPercentageHeight); - break; - case CSS_VMIN: - viewportLength = Length(getDoubleValue(), ViewportPercentageMin); - break; - case CSS_VMAX: - viewportLength = Length(getDoubleValue(), ViewportPercentageMax); - break; - default: - break; - } - return viewportLength; -} - -PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const -{ - RefPtr<CSSPrimitiveValue> result; + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = nullptr; switch (m_primitiveUnitType) { case CSS_STRING: case CSS_URI: case CSS_ATTR: case CSS_COUNTER_NAME: - result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitTypes>(m_primitiveUnitType)); + result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitType>(m_primitiveUnitType)); break; case CSS_COUNTER: result = CSSPrimitiveValue::create(m_value.counter->cloneForCSSOM()); @@ -1242,7 +1317,7 @@ PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const case CSS_DPI: case CSS_DPCM: case CSS_FR: - result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitTypes>(m_primitiveUnitType)); + result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitType>(m_primitiveUnitType)); break; case CSS_PROPERTY_ID: result = CSSPrimitiveValue::createIdentifier(m_value.propertyID); @@ -1315,7 +1390,6 @@ bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const case CSS_COUNTER_NAME: case CSS_PARSER_IDENTIFIER: case CSS_PARSER_HEXCOLOR: - case CSS_VARIABLE_NAME: return equal(m_value.string, other.m_value.string); case CSS_COUNTER: return m_value.counter && other.m_value.counter && m_value.counter->equals(*other.m_value.counter); @@ -1337,4 +1411,31 @@ bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const return false; } +void CSSPrimitiveValue::traceAfterDispatch(Visitor* visitor) +{ + switch (m_primitiveUnitType) { + case CSS_COUNTER: + visitor->trace(m_value.counter); + break; + case CSS_RECT: + visitor->trace(m_value.rect); + break; + case CSS_QUAD: + visitor->trace(m_value.quad); + break; + case CSS_PAIR: + visitor->trace(m_value.pair); + break; + case CSS_CALC: + visitor->trace(m_value.calc); + break; + case CSS_SHAPE: + visitor->trace(m_value.shape); + break; + default: + break; + } + CSSValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.h b/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.h index 65b1cfbf66f..76846ab687d 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValue.h @@ -22,8 +22,8 @@ #ifndef CSSPrimitiveValue_h #define CSSPrimitiveValue_h -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" #include "core/css/CSSValue.h" #include "platform/graphics/Color.h" #include "wtf/Forward.h" @@ -38,6 +38,7 @@ class CSSToLengthConversionData; class Counter; class ExceptionState; class Length; +class LengthSize; class Pair; class Quad; class RGBColor; @@ -64,9 +65,13 @@ template<> inline float roundForImpreciseConversion(double value) return static_cast<float>(value); } +// CSSPrimitiveValues are immutable. This class has manual ref-counting +// of unioned types and does not have the code necessary +// to handle any kind of mutations. All DOM-exposed "setters" just throw +// exceptions. class CSSPrimitiveValue : public CSSValue { public: - enum UnitTypes { + enum UnitType { CSS_UNKNOWN = 0, CSS_NUMBER = 1, CSS_PERCENTAGE = 2, @@ -130,13 +135,31 @@ public: CSS_CALC = 113, CSS_CALC_PERCENTAGE_WITH_NUMBER = 114, CSS_CALC_PERCENTAGE_WITH_LENGTH = 115, - CSS_VARIABLE_NAME = 116, CSS_PROPERTY_ID = 117, CSS_VALUE_ID = 118 }; - // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies. + enum LengthUnitType { + UnitTypePixels = 0, + UnitTypePercentage, + UnitTypeFontSize, + UnitTypeFontXSize, + UnitTypeRootFontSize, + UnitTypeZeroCharacterWidth, + UnitTypeViewportWidth, + UnitTypeViewportHeight, + UnitTypeViewportMin, + UnitTypeViewportMax, + + // This value must come after the last length unit type to enable iteration over the length unit types. + LengthUnitTypeCount, + }; + + typedef Vector<double, CSSPrimitiveValue::LengthUnitTypeCount> CSSLengthArray; + void accumulateLengthArray(CSSLengthArray&, double multiplier = 1) const; + + // This enum follows the BisonCSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies. enum UnitCategory { UNumber, UPercent, @@ -144,11 +167,12 @@ public: UAngle, UTime, UFrequency, - UViewportPercentageLength, UResolution, UOther }; - static UnitCategory unitCategory(CSSPrimitiveValue::UnitTypes); + static UnitCategory unitCategory(UnitType); + + static UnitType fromName(const String& unit); bool isAngle() const { @@ -167,11 +191,13 @@ public: || m_primitiveUnitType == CSS_REMS || m_primitiveUnitType == CSS_CHS; } - bool isLength() const + bool isViewportPercentageLength() const { return isViewportPercentageLength(static_cast<UnitType>(m_primitiveUnitType)); } + static bool isViewportPercentageLength(UnitType type) { return type >= CSS_VW && type <= CSS_VMAX; } + static bool isLength(UnitType type) { - unsigned short type = primitiveType(); - return (type >= CSS_EMS && type <= CSS_PC) || type == CSS_REMS || type == CSS_CHS; + return (type >= CSS_EMS && type <= CSS_PC) || type == CSS_REMS || type == CSS_CHS || isViewportPercentageLength(type); } + bool isLength() const { return isLength(primitiveType()); } bool isNumber() const { return primitiveType() == CSS_NUMBER; } bool isPercentage() const { return primitiveType() == CSS_PERCENTAGE; } bool isPx() const { return primitiveType() == CSS_PX; } @@ -184,49 +210,67 @@ public: bool isCalculated() const { return m_primitiveUnitType == CSS_CALC; } bool isCalculatedPercentageWithNumber() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_NUMBER; } bool isCalculatedPercentageWithLength() const { return primitiveType() == CSS_CALC_PERCENTAGE_WITH_LENGTH; } - bool isDotsPerInch() const { return primitiveType() == CSS_DPI; } - bool isDotsPerPixel() const { return primitiveType() == CSS_DPPX; } - bool isDotsPerCentimeter() const { return primitiveType() == CSS_DPCM; } - bool isResolution() const - { - unsigned short type = primitiveType(); - return type >= CSS_DPPX && type <= CSS_DPCM; - } - bool isVariableName() const { return primitiveType() == CSS_VARIABLE_NAME; } - bool isViewportPercentageLength() const { return m_primitiveUnitType >= CSS_VW && m_primitiveUnitType <= CSS_VMAX; } + static bool isDotsPerInch(UnitType type) { return type == CSS_DPI; } + static bool isDotsPerPixel(UnitType type) { return type == CSS_DPPX; } + static bool isDotsPerCentimeter(UnitType type) { return type == CSS_DPCM; } + static bool isResolution(UnitType type) { return type >= CSS_DPPX && type <= CSS_DPCM; } bool isFlex() const { return primitiveType() == CSS_FR; } bool isValueID() const { return m_primitiveUnitType == CSS_VALUE_ID; } bool colorIsDerivedFromElement() const; - static PassRefPtr<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) { return adoptRef(new CSSPrimitiveValue(valueID)); } - static PassRefPtr<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID) { return adoptRef(new CSSPrimitiveValue(propertyID)); } - static PassRefPtr<CSSPrimitiveValue> createParserOperator(int parserOperator) { return adoptRef(new CSSPrimitiveValue(parserOperator)); } - 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)); } - static PassRefPtr<CSSPrimitiveValue> create(const Length& value, float zoom) { return adoptRef(new CSSPrimitiveValue(value, zoom)); } - - template<typename T> static PassRefPtr<CSSPrimitiveValue> create(T value) + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifier(CSSValueID valueID) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(valueID)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifier(CSSPropertyID propertyID) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(propertyID)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createParserOperator(int parserOperator) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(parserOperator, CSS_PARSER_OPERATOR)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createColor(unsigned rgbValue) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(rgbValue, CSS_RGBCOLOR)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(double value, UnitType type) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(value, type)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(const String& value, UnitType type) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(value, type)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(const Length& value, float zoom) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(value, zoom)); + } + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(const LengthSize& value, const RenderStyle& style) + { + return adoptRefWillBeNoop(new CSSPrimitiveValue(value, style)); + } + template<typename T> static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> create(T value) { - return adoptRef(new CSSPrimitiveValue(value)); + return adoptRefWillBeNoop(new CSSPrimitiveValue(value)); } // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE. // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em. // When the quirky value is used, if you're in quirks mode, the margin will collapse away // inside a table cell. - static PassRefPtr<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitTypes type) + static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createAllowingMarginQuirk(double value, UnitType type) { CSSPrimitiveValue* quirkValue = new CSSPrimitiveValue(value, type); quirkValue->m_isQuirkValue = true; - return adoptRef(quirkValue); + return adoptRefWillBeNoop(quirkValue); } ~CSSPrimitiveValue(); void cleanup(); - unsigned short primitiveType() const; + UnitType primitiveType() const; double computeDegrees(); @@ -259,24 +303,22 @@ public: // Converts to a Length, mapping various unit types appropriately. template<int> Length convertToLength(const CSSToLengthConversionData&); - // use with care!!! - void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; } - - double getDoubleValue(unsigned short unitType, ExceptionState&) const; - double getDoubleValue(unsigned short unitType) const; + double getDoubleValue(UnitType, ExceptionState&) const; + double getDoubleValue(UnitType) const; double getDoubleValue() const; + // setFloatValue(..., ExceptionState&) and setStringValue() must use unsigned short instead of UnitType to match IDL bindings. void setFloatValue(unsigned short unitType, double floatValue, ExceptionState&); - float getFloatValue(unsigned short unitType, ExceptionState& exceptionState) const { return getValue<float>(unitType, exceptionState); } - float getFloatValue(unsigned short unitType) const { return getValue<float>(unitType); } + float getFloatValue(unsigned short unitType, ExceptionState& exceptionState) const { return getValue<float>(static_cast<UnitType>(unitType), exceptionState); } + float getFloatValue(UnitType type) const { return getValue<float>(type); } float getFloatValue() const { return getValue<float>(); } - int getIntValue(unsigned short unitType, ExceptionState& exceptionState) const { return getValue<int>(unitType, exceptionState); } - int getIntValue(unsigned short unitType) const { return getValue<int>(unitType); } + int getIntValue(UnitType type, ExceptionState& exceptionState) const { return getValue<int>(type, exceptionState); } + int getIntValue(UnitType type) const { return getValue<int>(type); } int getIntValue() const { return getValue<int>(); } - template<typename T> inline T getValue(unsigned short unitType, ExceptionState& exceptionState) const { return clampTo<T>(getDoubleValue(unitType, exceptionState)); } - template<typename T> inline T getValue(unsigned short unitType) const { return clampTo<T>(getDoubleValue(unitType)); } + template<typename T> inline T getValue(UnitType type, ExceptionState& exceptionState) const { return clampTo<T>(getDoubleValue(type, exceptionState)); } + template<typename T> inline T getValue(UnitType type) const { return clampTo<T>(getDoubleValue(type)); } template<typename T> inline T getValue() const { return clampTo<T>(getDoubleValue()); } void setStringValue(unsigned short stringType, const String& stringValue, ExceptionState&); @@ -292,7 +334,7 @@ public: Quad* getQuadValue(ExceptionState&) const; Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; } - PassRefPtr<RGBColor> getRGBColorValue(ExceptionState&) const; + PassRefPtrWillBeRawPtr<RGBColor> getRGBColorValue(ExceptionState&) const; RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; } Pair* getPairValue(ExceptionState&) const; @@ -307,47 +349,44 @@ public: template<typename T> inline operator T() const; // Defined in CSSPrimitiveValueMappings.h + static const char* unitTypeToString(UnitType); String customCSSText(CSSTextFormattingFlags = QuoteCSSStringIfNeeded) const; - String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const; - bool hasVariableReference() const; bool isQuirkValue() { return m_isQuirkValue; } - void addSubresourceStyleURLs(ListHashSet<KURL>&, const StyleSheetContents*) const; - - Length viewportPercentageLength(); - - PassRefPtr<CSSPrimitiveValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> cloneForCSSOM() const; void setCSSOMSafe() { m_isCSSOMSafe = true; } bool equals(const CSSPrimitiveValue&) const; - static UnitTypes canonicalUnitTypeForCategory(UnitCategory); - static double conversionToCanonicalUnitsScaleFactor(unsigned short unitType); + void traceAfterDispatch(Visitor*); + + static UnitType canonicalUnitTypeForCategory(UnitCategory); + static double conversionToCanonicalUnitsScaleFactor(UnitType); + + // Returns true and populates lengthUnitType, if unitType is a length unit. Otherwise, returns false. + static bool unitTypeToLengthUnitType(UnitType, LengthUnitType&); + static UnitType lengthUnitTypeToUnitType(LengthUnitType); private: CSSPrimitiveValue(CSSValueID); CSSPrimitiveValue(CSSPropertyID); - // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and operator cases. - CSSPrimitiveValue(int parserOperator); - CSSPrimitiveValue(unsigned color); // RGB value - CSSPrimitiveValue(const Length& length) - : CSSValue(PrimitiveClass) - { - init(length); - } + // int vs. unsigned is too subtle to distinguish types, so require a UnitType. + CSSPrimitiveValue(int parserOperator, UnitType); + CSSPrimitiveValue(unsigned color, UnitType); // RGB value CSSPrimitiveValue(const Length&, float zoom); - CSSPrimitiveValue(const String&, UnitTypes); - CSSPrimitiveValue(double, UnitTypes); + CSSPrimitiveValue(const LengthSize&, const RenderStyle&); + CSSPrimitiveValue(const String&, UnitType); + CSSPrimitiveValue(double, UnitType); template<typename T> CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h template<typename T> CSSPrimitiveValue(T* val) : CSSValue(PrimitiveClass) { - init(PassRefPtr<T>(val)); + init(PassRefPtrWillBeRawPtr<T>(val)); } - template<typename T> CSSPrimitiveValue(PassRefPtr<T> val) + template<typename T> CSSPrimitiveValue(PassRefPtrWillBeRawPtr<T> val) : CSSValue(PrimitiveClass) { init(val); @@ -358,13 +397,14 @@ private: template<typename T> operator T*(); // compile-time guard void init(const Length&); - void init(PassRefPtr<Counter>); - void init(PassRefPtr<Rect>); - void init(PassRefPtr<Pair>); - void init(PassRefPtr<Quad>); - void init(PassRefPtr<CSSBasicShape>); - void init(PassRefPtr<CSSCalcValue>); - bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const; + void init(const LengthSize&, const RenderStyle&); + void init(PassRefPtrWillBeRawPtr<Counter>); + void init(PassRefPtrWillBeRawPtr<Rect>); + void init(PassRefPtrWillBeRawPtr<Pair>); + void init(PassRefPtrWillBeRawPtr<Quad>); + void init(PassRefPtrWillBeRawPtr<CSSBasicShape>); + void init(PassRefPtrWillBeRawPtr<CSSCalcValue>); + bool getDoubleValueInternal(UnitType targetUnitType, double* result) const; double computeLengthDouble(const CSSToLengthConversionData&); @@ -374,16 +414,19 @@ private: int parserOperator; double num; StringImpl* string; - Counter* counter; - Rect* rect; - Quad* quad; unsigned rgbcolor; - Pair* pair; + // FIXME: oilpan: Should be members, but no support for members in unions. Just trace the raw ptr for now. CSSBasicShape* shape; CSSCalcValue* calc; + Counter* counter; + Pair* pair; + Rect* rect; + Quad* quad; } m_value; }; +typedef CSSPrimitiveValue::CSSLengthArray CSSLengthArray; + DEFINE_CSS_VALUE_TYPE_CASTS(CSSPrimitiveValue, isPrimitiveValue()); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h index 3f386133793..c2bf9d8e714 100755..100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h @@ -30,7 +30,7 @@ #ifndef CSSPrimitiveValueMappings_h #define CSSPrimitiveValueMappings_h -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" #include "core/css/CSSCalculationValue.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSReflectionDirection.h" @@ -45,6 +45,7 @@ #include "platform/fonts/TextRenderingMode.h" #include "platform/graphics/GraphicsTypes.h" #include "platform/graphics/Path.h" +#include "platform/scroll/ScrollableArea.h" #include "platform/text/TextDirection.h" #include "platform/text/UnicodeBidi.h" #include "platform/text/WritingMode.h" @@ -61,11 +62,8 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(short i) template<> inline CSSPrimitiveValue::operator short() const { - if (m_primitiveUnitType == CSS_NUMBER) - return clampTo<short>(m_value.num); - - ASSERT_NOT_REACHED(); - return 0; + ASSERT(isNumber()); + return clampTo<short>(getDoubleValue()); } template<> inline CSSPrimitiveValue::CSSPrimitiveValue(unsigned short i) @@ -77,29 +75,20 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(unsigned short i) template<> inline CSSPrimitiveValue::operator unsigned short() const { - if (m_primitiveUnitType == CSS_NUMBER) - return clampTo<unsigned short>(m_value.num); - - ASSERT_NOT_REACHED(); - return 0; + ASSERT(isNumber()); + return clampTo<unsigned short>(getDoubleValue()); } template<> inline CSSPrimitiveValue::operator int() const { - if (m_primitiveUnitType == CSS_NUMBER) - return clampTo<int>(m_value.num); - - ASSERT_NOT_REACHED(); - return 0; + ASSERT(isNumber()); + return clampTo<int>(getDoubleValue()); } template<> inline CSSPrimitiveValue::operator unsigned() const { - if (m_primitiveUnitType == CSS_NUMBER) - return clampTo<unsigned>(m_value.num); - - ASSERT_NOT_REACHED(); - return 0; + ASSERT(isNumber()); + return clampTo<unsigned>(getDoubleValue()); } @@ -112,11 +101,8 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(float i) template<> inline CSSPrimitiveValue::operator float() const { - if (m_primitiveUnitType == CSS_NUMBER) - return clampTo<float>(m_value.num); - - ASSERT_NOT_REACHED(); - return 0.0f; + ASSERT(isNumber()); + return clampTo<float>(getDoubleValue()); } template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineClampValue i) @@ -460,18 +446,6 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e) case MediaMuteButtonPart: m_value.valueID = CSSValueMediaMuteButton; break; - case MediaSeekBackButtonPart: - m_value.valueID = CSSValueMediaSeekBackButton; - break; - case MediaSeekForwardButtonPart: - m_value.valueID = CSSValueMediaSeekForwardButton; - break; - case MediaRewindButtonPart: - m_value.valueID = CSSValueMediaRewindButton; - break; - case MediaReturnToRealtimeButtonPart: - m_value.valueID = CSSValueMediaReturnToRealtimeButton; - break; case MediaToggleClosedCaptionsButtonPart: m_value.valueID = CSSValueMediaToggleClosedCaptionsButton; break; @@ -487,9 +461,6 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e) case MediaVolumeSliderPart: m_value.valueID = CSSValueMediaVolumeSlider; break; - case MediaVolumeSliderMuteButtonPart: - m_value.valueID = CSSValueMediaVolumeSliderMuteButton; - break; case MediaVolumeSliderThumbPart: m_value.valueID = CSSValueMediaVolumeSliderthumb; break; @@ -580,11 +551,6 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ControlPart e) case CapsLockIndicatorPart: m_value.valueID = CSSValueCapsLockIndicator; break; - case InputSpeechButtonPart: -#if ENABLE(INPUT_SPEECH) - m_value.valueID = CSSValueWebkitInputSpeechButton; -#endif - break; } } @@ -1150,11 +1116,11 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ECursor e) case CURSOR_NOT_ALLOWED: m_value.valueID = CSSValueNotAllowed; break; - case CURSOR_WEBKIT_ZOOM_IN: - m_value.valueID = CSSValueWebkitZoomIn; + case CURSOR_ZOOM_IN: + m_value.valueID = CSSValueZoomIn; break; - case CURSOR_WEBKIT_ZOOM_OUT: - m_value.valueID = CSSValueWebkitZoomOut; + case CURSOR_ZOOM_OUT: + m_value.valueID = CSSValueZoomOut; break; case CURSOR_E_RESIZE: m_value.valueID = CSSValueEResize; @@ -1222,11 +1188,18 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ECursor e) template<> inline CSSPrimitiveValue::operator ECursor() const { ASSERT(isValueID()); - if (m_value.valueID == CSSValueCopy) + switch (m_value.valueID) { + case CSSValueCopy: return CURSOR_COPY; - if (m_value.valueID == CSSValueNone) + case CSSValueWebkitZoomIn: + return CURSOR_ZOOM_IN; + case CSSValueWebkitZoomOut: + return CURSOR_ZOOM_OUT; + case CSSValueNone: return CURSOR_NONE; - return static_cast<ECursor>(m_value.valueID - CSSValueAuto); + default: + return static_cast<ECursor>(m_value.valueID - CSSValueAuto); + } } template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EDisplay e) @@ -1346,56 +1319,6 @@ template<> inline CSSPrimitiveValue::operator EEmptyCell() const return SHOW; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EAlignItems e) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_VALUE_ID; - switch (e) { - case AlignAuto: - m_value.valueID = CSSValueAuto; - break; - case AlignFlexStart: - m_value.valueID = CSSValueFlexStart; - break; - case AlignFlexEnd: - m_value.valueID = CSSValueFlexEnd; - break; - case AlignCenter: - m_value.valueID = CSSValueCenter; - break; - case AlignStretch: - m_value.valueID = CSSValueStretch; - break; - case AlignBaseline: - m_value.valueID = CSSValueBaseline; - break; - } -} - -template<> inline CSSPrimitiveValue::operator EAlignItems() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueAuto: - return AlignAuto; - case CSSValueFlexStart: - return AlignFlexStart; - case CSSValueFlexEnd: - return AlignFlexEnd; - case CSSValueCenter: - return AlignCenter; - case CSSValueStretch: - return AlignStretch; - case CSSValueBaseline: - return AlignBaseline; - default: - break; - } - - ASSERT_NOT_REACHED(); - return AlignFlexStart; -} - template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EJustifyContent e) : CSSValue(PrimitiveClass) { @@ -2014,36 +1937,6 @@ template<> inline CSSPrimitiveValue::operator EMarqueeBehavior() const return MNONE; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(RegionFragment e) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_VALUE_ID; - switch (e) { - case AutoRegionFragment: - m_value.valueID = CSSValueAuto; - break; - case BreakRegionFragment: - m_value.valueID = CSSValueBreak; - break; - } -} - -template<> inline CSSPrimitiveValue::operator RegionFragment() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueAuto: - return AutoRegionFragment; - case CSSValueBreak: - return BreakRegionFragment; - default: - break; - } - - ASSERT_NOT_REACHED(); - return AutoRegionFragment; -} - template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EMarqueeDirection e) : CSSValue(PrimitiveClass) { @@ -3591,15 +3484,15 @@ template<> inline CSSPrimitiveValue::operator FontWeight() const return FontWeightNormal; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontItalic italic) +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontStyle italic) : CSSValue(PrimitiveClass) { m_primitiveUnitType = CSS_VALUE_ID; switch (italic) { - case FontItalicOff: + case FontStyleNormal: m_value.valueID = CSSValueNormal; return; - case FontItalicOn: + case FontStyleItalic: m_value.valueID = CSSValueItalic; return; } @@ -3608,32 +3501,32 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontItalic italic) m_value.valueID = CSSValueNormal; } -template<> inline CSSPrimitiveValue::operator FontItalic() const +template<> inline CSSPrimitiveValue::operator FontStyle() const { ASSERT(isValueID()); switch (m_value.valueID) { case CSSValueOblique: // FIXME: oblique is the same as italic for the moment... case CSSValueItalic: - return FontItalicOn; + return FontStyleItalic; case CSSValueNormal: - return FontItalicOff; + return FontStyleNormal; default: break; } ASSERT_NOT_REACHED(); - return FontItalicOff; + return FontStyleNormal; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontSmallCaps smallCaps) +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontVariant smallCaps) : CSSValue(PrimitiveClass) { m_primitiveUnitType = CSS_VALUE_ID; switch (smallCaps) { - case FontSmallCapsOff: + case FontVariantNormal: m_value.valueID = CSSValueNormal; return; - case FontSmallCapsOn: + case FontVariantSmallCaps: m_value.valueID = CSSValueSmallCaps; return; } @@ -3642,19 +3535,19 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(FontSmallCaps smallCaps) m_value.valueID = CSSValueNormal; } -template<> inline CSSPrimitiveValue::operator FontSmallCaps() const +template<> inline CSSPrimitiveValue::operator FontVariant() const { ASSERT(isValueID()); switch (m_value.valueID) { case CSSValueSmallCaps: - return FontSmallCapsOn; + return FontVariantSmallCaps; case CSSValueNormal: - return FontSmallCapsOff; + return FontVariantNormal; default: break; } ASSERT_NOT_REACHED(); - return FontSmallCapsOff; + return FontVariantNormal; } template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextRenderingMode e) @@ -3697,71 +3590,6 @@ template<> inline CSSPrimitiveValue::operator TextRenderingMode() const return AutoTextRendering; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineSnap gridSnap) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_VALUE_ID; - switch (gridSnap) { - case LineSnapNone: - m_value.valueID = CSSValueNone; - break; - case LineSnapBaseline: - m_value.valueID = CSSValueBaseline; - break; - case LineSnapContain: - m_value.valueID = CSSValueContain; - break; - } -} - -template<> inline CSSPrimitiveValue::operator LineSnap() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueNone: - return LineSnapNone; - case CSSValueBaseline: - return LineSnapBaseline; - case CSSValueContain: - return LineSnapContain; - default: - break; - } - - ASSERT_NOT_REACHED(); - return LineSnapNone; -} - -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LineAlign lineAlign) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_VALUE_ID; - switch (lineAlign) { - case LineAlignNone: - m_value.valueID = CSSValueNone; - break; - case LineAlignEdges: - m_value.valueID = CSSValueEdges; - break; - } -} - -template<> inline CSSPrimitiveValue::operator LineAlign() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueNone: - return LineAlignNone; - case CSSValueEdges: - return LineAlignEdges; - default: - break; - } - - ASSERT_NOT_REACHED(); - return LineAlignNone; -} - template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ESpeak e) : CSSValue(PrimitiveClass) { @@ -4253,71 +4081,6 @@ template<> inline CSSPrimitiveValue::operator ETransformStyle3D() const return TransformStyle3DFlat; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColumnAxis e) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_VALUE_ID; - switch (e) { - case HorizontalColumnAxis: - m_value.valueID = CSSValueHorizontal; - break; - case VerticalColumnAxis: - m_value.valueID = CSSValueVertical; - break; - case AutoColumnAxis: - m_value.valueID = CSSValueAuto; - break; - } -} - -template<> inline CSSPrimitiveValue::operator ColumnAxis() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueHorizontal: - return HorizontalColumnAxis; - case CSSValueVertical: - return VerticalColumnAxis; - case CSSValueAuto: - return AutoColumnAxis; - default: - break; - } - - ASSERT_NOT_REACHED(); - return AutoColumnAxis; -} - -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ColumnProgression e) - : CSSValue(PrimitiveClass) -{ - m_primitiveUnitType = CSS_VALUE_ID; - switch (e) { - case NormalColumnProgression: - m_value.valueID = CSSValueNormal; - break; - case ReverseColumnProgression: - m_value.valueID = CSSValueReverse; - break; - } -} - -template<> inline CSSPrimitiveValue::operator ColumnProgression() const -{ - ASSERT(isValueID()); - switch (m_value.valueID) { - case CSSValueNormal: - return NormalColumnProgression; - case CSSValueReverse: - return ReverseColumnProgression; - default: - break; - } - - ASSERT_NOT_REACHED(); - return NormalColumnProgression; -} - template<> inline CSSPrimitiveValue::CSSPrimitiveValue(WrapFlow wrapFlow) : CSSValue(PrimitiveClass) { @@ -4443,7 +4206,6 @@ enum LengthConversion { template<int supported> Length CSSPrimitiveValue::convertToLength(const CSSToLengthConversionData& conversionData) { - ASSERT(!hasVariableReference()); if ((supported & FixedConversion) && isLength()) return computeLength<Length>(conversionData); if ((supported & PercentConversion) && isPercentage()) @@ -4452,9 +4214,8 @@ template<int supported> Length CSSPrimitiveValue::convertToLength(const CSSToLen return Length(Auto); if ((supported & FixedConversion) && (supported & PercentConversion) && isCalculated()) return Length(cssCalcValue()->toCalcValue(conversionData)); - if ((supported & FixedConversion) && isViewportPercentageLength()) - return viewportPercentageLength(); - return Length(Undefined); + ASSERT_NOT_REACHED(); + return Length(0, Fixed); } template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EBufferedRendering e) @@ -4878,6 +4639,8 @@ template<> inline CSSPrimitiveValue::operator TouchAction() const return TouchActionPanX; case CSSValuePanY: return TouchActionPanY; + case CSSValueManipulation: + return TouchActionPanX | TouchActionPanY | TouchActionPinchZoom; default: break; } @@ -4945,11 +4708,11 @@ template<> inline CSSPrimitiveValue::operator TouchActionDelay() const return TouchActionDelayNone; } -template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LayoutBox layoutBox) +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(CSSBoxType cssBox) : CSSValue(PrimitiveClass) { m_primitiveUnitType = CSS_VALUE_ID; - switch (layoutBox) { + switch (cssBox) { case MarginBox: m_value.valueID = CSSValueMarginBox; break; @@ -4962,10 +4725,13 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(LayoutBox layoutBox) case ContentBox: m_value.valueID = CSSValueContentBox; break; + case BoxMissing: + // The missing box should convert to a null primitive value. + ASSERT_NOT_REACHED(); } } -template<> inline CSSPrimitiveValue::operator LayoutBox() const +template<> inline CSSPrimitiveValue::operator CSSBoxType() const { switch (getValueID()) { case CSSValueMarginBox: @@ -4983,6 +4749,147 @@ template<> inline CSSPrimitiveValue::operator LayoutBox() const return ContentBox; } +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ItemPosition itemPosition) + : CSSValue(PrimitiveClass) +{ + m_primitiveUnitType = CSS_VALUE_ID; + switch (itemPosition) { + case ItemPositionAuto: + m_value.valueID = CSSValueAuto; + break; + case ItemPositionStretch: + m_value.valueID = CSSValueStretch; + break; + case ItemPositionBaseline: + m_value.valueID = CSSValueBaseline; + break; + case ItemPositionCenter: + m_value.valueID = CSSValueCenter; + break; + case ItemPositionStart: + m_value.valueID = CSSValueStart; + break; + case ItemPositionEnd: + m_value.valueID = CSSValueEnd; + break; + case ItemPositionSelfStart: + m_value.valueID = CSSValueSelfStart; + break; + case ItemPositionSelfEnd: + m_value.valueID = CSSValueSelfEnd; + break; + case ItemPositionFlexStart: + m_value.valueID = CSSValueFlexStart; + break; + case ItemPositionFlexEnd: + m_value.valueID = CSSValueFlexEnd; + break; + case ItemPositionLeft: + m_value.valueID = CSSValueLeft; + break; + case ItemPositionRight: + m_value.valueID = CSSValueRight; + break; + } +} + +template<> inline CSSPrimitiveValue::operator ItemPosition() const +{ + switch (m_value.valueID) { + case CSSValueAuto: + return ItemPositionAuto; + case CSSValueStretch: + return ItemPositionStretch; + case CSSValueBaseline: + return ItemPositionBaseline; + case CSSValueCenter: + return ItemPositionCenter; + case CSSValueStart: + return ItemPositionStart; + case CSSValueEnd: + return ItemPositionEnd; + case CSSValueSelfStart: + return ItemPositionSelfStart; + case CSSValueSelfEnd: + return ItemPositionSelfEnd; + case CSSValueFlexStart: + return ItemPositionFlexStart; + case CSSValueFlexEnd: + return ItemPositionFlexEnd; + case CSSValueLeft: + return ItemPositionLeft; + case CSSValueRight: + return ItemPositionRight; + default: + break; + } + ASSERT_NOT_REACHED(); + return ItemPositionAuto; +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(OverflowAlignment overflowAlignment) + : CSSValue(PrimitiveClass) +{ + m_primitiveUnitType = CSS_VALUE_ID; + switch (overflowAlignment) { + case OverflowAlignmentDefault: + m_value.valueID = CSSValueDefault; + break; + case OverflowAlignmentTrue: + m_value.valueID = CSSValueTrue; + break; + case OverflowAlignmentSafe: + m_value.valueID = CSSValueSafe; + break; + } +} + +template<> inline CSSPrimitiveValue::operator OverflowAlignment() const +{ + switch (m_value.valueID) { + case CSSValueTrue: + return OverflowAlignmentTrue; + case CSSValueSafe: + return OverflowAlignmentSafe; + default: + break; + } + ASSERT_NOT_REACHED(); + return OverflowAlignmentTrue; +} + +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ScrollBehavior behavior) + : CSSValue(PrimitiveClass) +{ + m_primitiveUnitType = CSS_VALUE_ID; + switch (behavior) { + case ScrollBehaviorInstant: + m_value.valueID = CSSValueInstant; + break; + case ScrollBehaviorSmooth: + m_value.valueID = CSSValueSmooth; + break; + case ScrollBehaviorAuto: + // Behavior 'auto' is only allowed in ScrollOptions arguments passed to + // CSSOM scroll APIs. + ASSERT_NOT_REACHED(); + } +} + +template<> inline CSSPrimitiveValue::operator ScrollBehavior() const +{ + switch (getValueID()) { + case CSSValueInstant: + return ScrollBehaviorInstant; + case CSSValueSmooth: + return ScrollBehaviorSmooth; + default: + break; + } + ASSERT_NOT_REACHED(); + return ScrollBehaviorInstant; +} + } #endif diff --git a/chromium/third_party/WebKit/Source/core/css/CSSProperties.in b/chromium/third_party/WebKit/Source/core/css/CSSProperties.in index 26318517545..ef861db7d13 100755..100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSProperties.in +++ b/chromium/third_party/WebKit/Source/core/css/CSSProperties.in @@ -1,10 +1,12 @@ // FIXME: When we have all the properties using the new StyleBuilder, we // should use this for make_css_property_names.py +// Note that type_name is currently only used for non-custom value application +// and when explicitly referred to in generated applicators. // Note: Mandatory blank line to skip parameter parsing phase align-content -align-items -align-self type_name=EAlignItems +align-items custom_value +align-self custom_value background-attachment custom_all background-blend-mode custom_all background-clip custom_all @@ -45,6 +47,7 @@ caption-side clear clip custom_all color custom_all +content custom_all counter-increment custom_all counter-reset custom_all cursor custom_all @@ -57,17 +60,30 @@ flex-grow type_name=float flex-shrink type_name=float flex-wrap float type_name=EFloat, name_for_methods=Floating +font custom_all font-family custom_all -font-kerning custom_all +font-kerning font, type_name=FontDescription::Kerning, name_for_methods=Kerning font-size custom_all -font-style custom_all -font-variant custom_all +font-style font, type_name=FontStyle, name_for_methods=Style +font-variant font, type_name=FontVariant, name_for_methods=Variant +font-variant-ligatures custom_all font-weight custom_all grid-auto-flow type_name=GridAutoFlow +grid-auto-columns converter=convertGridTrackSize +grid-auto-rows converter=convertGridTrackSize +grid-column-start converter=convertGridPosition +grid-column-end converter=convertGridPosition +grid-row-start converter=convertGridPosition +grid-row-end converter=convertGridPosition +grid-template-columns custom_all +grid-template-rows custom_all +grid-template-areas custom_all height type_name=Length, initial=initialSize, converter=convertLengthSizing justify-content image-rendering +internal-callback custom_all isolation +justify-self custom_value left type_name=Length, initial=initialOffset, converter=convertLengthOrAuto letter-spacing type_name=float, initial=initialLetterWordSpacing, converter=convertSpacing line-height getter=specifiedLineHeight, custom_value @@ -103,15 +119,16 @@ padding-top type_name=Length, initial=initialPadding, converter=convertLength page-break-after type_name=EPageBreak, initial=initialPageBreak page-break-before type_name=EPageBreak, initial=initialPageBreak page-break-inside type_name=EPageBreak, initial=initialPageBreak +perspective custom_value pointer-events position +quotes converter=convertQuotes resize custom_value right type_name=Length, initial=initialOffset, converter=convertLengthOrAuto +scroll-behavior type_name=ScrollBehavior shape-image-threshold type_name=float -shape-inside type_name=ShapeValue*, custom_value shape-margin type_name=Length, converter=convertLength shape-outside type_name=ShapeValue*, custom_value -shape-padding type_name=Length, converter=convertLength size custom_all speak table-layout @@ -125,18 +142,19 @@ text-decoration-style type_name=TextDecorationStyle text-indent custom_all text-justify type_name=TextJustify text-overflow type_name=TextOverflow -text-rendering custom_all +text-rendering font, type_name=TextRenderingMode text-shadow converter=convertShadow text-transform top type_name=Length, initial=initialOffset, converter=convertLengthOrAuto touch-action type_name=TouchAction, custom_value touch-action-delay type_name=TouchActionDelay, initial=initialTouchActionDelay unicode-bidi -vertical-align custom_value +vertical-align custom_inherit, custom_value visibility white-space widows type_name=short, custom_all width type_name=Length, initial=initialSize, converter=convertLengthSizing +will-change custom_all word-break word-spacing type_name=float, initial=initialLetterWordSpacing, converter=convertSpacing // UAs must treat 'word-wrap' as an alternate name for the 'overflow-wrap' property. So using the same handlers. @@ -152,8 +170,10 @@ z-index type_name=int, custom_all -webkit-animation-name custom_all -webkit-animation-play-state custom_all -webkit-animation-timing-function custom_all +-webkit-app-region custom_all -webkit-appearance type_name=ControlPart -webkit-aspect-ratio custom_all +backface-visibility -webkit-backface-visibility -webkit-background-clip use_handlers_for=CSSPropertyBackgroundClip -webkit-background-composite custom_all @@ -172,32 +192,29 @@ z-index type_name=int, custom_all -webkit-box-ordinal-group type_name=unsigned int -webkit-box-orient -webkit-box-pack +-webkit-box-reflect converter=convertBoxReflect -webkit-box-shadow use_handlers_for=CSSPropertyBoxShadow -webkit-clip-path custom_value --webkit-column-axis type_name=ColumnAxis -webkit-column-break-after type_name=EPageBreak, initial=initialPageBreak -webkit-column-break-before type_name=EPageBreak, initial=initialPageBreak -webkit-column-break-inside type_name=EPageBreak, initial=initialPageBreak -webkit-column-count type_name=unsigned short, custom_all column-fill type_name=ColumnFill -webkit-column-gap type_name=float, custom_all --webkit-column-progression type_name=ColumnProgression -webkit-column-rule-color custom_all -webkit-column-rule-style type_name=EBorderStyle, initial=initialBorderStyle -webkit-column-rule-width type_name=unsigned short, converter=convertLineWidth<unsigned short> -webkit-column-span type_name=ColumnSpan -webkit-column-width type_name=float, custom_all --webkit-flow-from type_name=AtomicString, name_for_methods=RegionThread, converter=convertString<CSSValueNone> --webkit-flow-into type_name=AtomicString, name_for_methods=FlowThread, converter=convertString<CSSValueNone> --webkit-font-smoothing custom_all --webkit-font-variant-ligatures custom_all +-webkit-filter custom_value +-webkit-font-feature-settings custom_all +-webkit-font-smoothing font, type_name=FontSmoothingMode -webkit-highlight type_name=AtomicString, converter=convertString<CSSValueNone> -webkit-hyphenate-character type_name=AtomicString, name_for_methods=HyphenationString, converter=convertString<CSSValueAuto> --webkit-line-align type_name=LineAlign +-webkit-line-box-contain converter=convertLineBoxContain -webkit-line-break type_name=LineBreak -webkit-line-clamp type_name=LineClampValue --webkit-line-grid type_name=AtomicString, converter=convertString<CSSValueNone> --webkit-line-snap type_name=LineSnap +-webkit-locale custom_value -webkit-margin-after-collapse type_name=EMarginCollapse -webkit-margin-before-collapse type_name=EMarginCollapse -webkit-margin-bottom-collapse type_name=EMarginCollapse, name_for_methods=MarginAfterCollapse @@ -221,27 +238,32 @@ column-fill type_name=ColumnFill -webkit-mask-repeat-x custom_all -webkit-mask-repeat-y custom_all -webkit-mask-size custom_all +-webkit-perspective custom_all +perspective-origin custom_all -webkit-perspective-origin custom_all -webkit-perspective-origin-x type_name=Length, converter=convertLength -webkit-perspective-origin-y type_name=Length, converter=convertLength -webkit-print-color-adjust type_name=PrintColorAdjust --webkit-region-break-after type_name=EPageBreak, initial=initialPageBreak --webkit-region-break-before type_name=EPageBreak, initial=initialPageBreak --webkit-region-break-inside type_name=EPageBreak, initial=initialPageBreak --webkit-region-fragment type_name=RegionFragment -webkit-rtl-ordering type_name=Order, getter=rtlOrdering, setter=setRTLOrdering, initial=initialRTLOrdering -webkit-ruby-position type_name=RubyPosition +-webkit-tap-highlight-color custom_value -webkit-text-combine type_name=TextCombine -webkit-text-emphasis-color custom_all -webkit-text-emphasis-position type_name=TextEmphasisPosition -webkit-text-emphasis-style custom_all -webkit-text-fill-color custom_all +-webkit-text-orientation custom_value -webkit-text-security -webkit-text-stroke-color custom_all +-webkit-text-stroke-width converter=convertTextStrokeWidth text-underline-position custom_value +transform custom_value +-webkit-transform use_handlers_for=CSSPropertyTransform +transform-origin custom_all -webkit-transform-origin-x type_name=Length, converter=convertLength -webkit-transform-origin-y type_name=Length, converter=convertLength -webkit-transform-origin-z type_name=float, converter=convertComputedLength<float> +transform-style name_for_methods=TransformStyle3D -webkit-transform-style name_for_methods=TransformStyle3D -webkit-transition-delay custom_all -webkit-transition-duration custom_all @@ -252,8 +274,10 @@ text-underline-position custom_value -webkit-user-select -webkit-wrap-flow type_name=WrapFlow -webkit-wrap-through type_name=WrapThrough +-webkit-writing-mode custom_value alignment-baseline svg +baseline-shift svg, custom_value buffered-rendering svg clip-path svg, type_name=String, name_for_methods=ClipperResource, converter=convertFragmentIdentifier clip-rule svg, type_name=WindRule @@ -261,18 +285,26 @@ color-interpolation svg color-interpolation-filters svg, type_name=EColorInterpolation color-rendering svg dominant-baseline svg +fill svg, setter=setFillPaint, custom_all fill-opacity svg, type_name=float, converter=convertNumberOrPercentage fill-rule svg, type_name=WindRule filter svg, type_name=String, name_for_methods=FilterResource, converter=convertFragmentIdentifier +flood-color svg, converter=convertSVGColor flood-opacity svg, type_name=float, converter=convertNumberOrPercentage -kerning svg, type_name=SVGLength, converter=convertSVGLength +glyph-orientation-horizontal svg, converter=convertGlyphOrientation +glyph-orientation-vertical svg, custom_value +lighting-color svg, converter=convertSVGColor marker-start svg, type_name=String, name_for_methods=MarkerStartResource, converter=convertFragmentIdentifier marker-mid svg, type_name=String, name_for_methods=MarkerMidResource, converter=convertFragmentIdentifier marker-end svg, type_name=String, name_for_methods=MarkerEndResource, converter=convertFragmentIdentifier mask svg, type_name=String, name_for_methods=MaskerResource, converter=convertFragmentIdentifier mask-type svg +paint-order svg, converter=convertPaintOrder shape-rendering svg +stop-color svg, converter=convertSVGColor stop-opacity svg, type_name=float, converter=convertNumberOrPercentage +stroke svg, setter=setStrokePaint, custom_all +stroke-dasharray svg, name_for_methods=StrokeDashArray, converter=convertStrokeDasharray stroke-dashoffset svg, type_name=SVGLength, name_for_methods=StrokeDashOffset, converter=convertSVGLength stroke-linecap svg, type_name=LineCap, name_for_methods=CapStyle stroke-linejoin svg, type_name=LineJoin, name_for_methods=JoinStyle @@ -282,3 +314,70 @@ stroke-width svg, type_name=SVGLength, converter=convertSVGLength text-anchor svg vector-effect svg writing-mode svg, type_name=SVGWritingMode + +-webkit-border-end-color direction_aware +-webkit-border-end-style direction_aware +-webkit-border-end-width direction_aware +-webkit-border-start-color direction_aware +-webkit-border-start-style direction_aware +-webkit-border-start-width direction_aware +-webkit-border-before-color direction_aware +-webkit-border-before-style direction_aware +-webkit-border-before-width direction_aware +-webkit-border-after-color direction_aware +-webkit-border-after-style direction_aware +-webkit-border-after-width direction_aware +-webkit-margin-end direction_aware +-webkit-margin-start direction_aware +-webkit-margin-before direction_aware +-webkit-margin-after direction_aware +-webkit-padding-end direction_aware +-webkit-padding-start direction_aware +-webkit-padding-before direction_aware +-webkit-padding-after direction_aware +-webkit-logical-width direction_aware +-webkit-logical-height direction_aware +-webkit-min-logical-width direction_aware +-webkit-min-logical-height direction_aware +-webkit-max-logical-width direction_aware +-webkit-max-logical-height direction_aware + +// FIXME: We should look over these and see if some should actually be +// marked as unreachable. +animation-delay skip +animation-direction skip +animation-duration skip +animation-fill-mode skip +animation-iteration-count skip +animation-name skip +animation-play-state skip +animation-timing-function skip +transition-delay skip +transition-duration skip +transition-property skip +transition-timing-function skip +font-stretch skip +page skip +src skip +text-line-through-color skip +text-line-through-mode skip +text-line-through-style skip +text-line-through-width skip +text-overline-color skip +text-overline-mode skip +text-overline-style skip +text-overline-width skip +text-underline-color skip +text-underline-mode skip +text-underline-style skip +text-underline-width skip +unicode-range skip +-webkit-font-size-delta skip +-webkit-text-decorations-in-effect skip +max-zoom skip +min-zoom skip +user-zoom skip +orientation skip +enable-background skip +invalid skip +all skip diff --git a/chromium/third_party/WebKit/Source/core/css/CSSProperty.cpp b/chromium/third_party/WebKit/Source/core/css/CSSProperty.cpp index 59e3d9e68af..f36f4897f92 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSProperty.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSProperty.cpp @@ -21,7 +21,7 @@ #include "config.h" #include "core/css/CSSProperty.h" -#include "StylePropertyShorthand.h" +#include "core/StylePropertyShorthand.h" #include "core/css/CSSValueList.h" #include "core/rendering/style/RenderStyleConstants.h" @@ -47,7 +47,7 @@ CSSPropertyID StylePropertyMetadata::shorthandID() const void CSSProperty::wrapValueInCommaSeparatedList() { - RefPtr<CSSValue> value = m_value.release(); + RefPtrWillBeRawPtr<CSSValue> value = m_value.release(); m_value = CSSValueList::createCommaSeparated(); toCSSValueList(m_value.get())->append(value.release()); } @@ -282,7 +282,6 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyGlyphOrientationHorizontal: case CSSPropertyGlyphOrientationVertical: case CSSPropertyImageRendering: - case CSSPropertyKerning: case CSSPropertyLetterSpacing: case CSSPropertyLineHeight: case CSSPropertyListStyle: @@ -317,7 +316,6 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyTextShadow: case CSSPropertyTextTransform: case CSSPropertyTouchActionDelay: - case CSSPropertyVariable: case CSSPropertyVisibility: case CSSPropertyWebkitAspectRatio: case CSSPropertyWebkitBorderHorizontalSpacing: @@ -326,15 +324,12 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyWebkitFontFeatureSettings: case CSSPropertyFontKerning: case CSSPropertyWebkitFontSmoothing: - case CSSPropertyWebkitFontVariantLigatures: + case CSSPropertyFontVariantLigatures: case CSSPropertyWebkitLocale: case CSSPropertyWebkitHighlight: case CSSPropertyWebkitHyphenateCharacter: - case CSSPropertyWebkitLineAlign: case CSSPropertyWebkitLineBoxContain: case CSSPropertyWebkitLineBreak: - case CSSPropertyWebkitLineGrid: - case CSSPropertyWebkitLineSnap: case CSSPropertyWebkitPrintColorAdjust: case CSSPropertyWebkitRtlOrdering: case CSSPropertyWebkitRubyPosition: @@ -425,7 +420,6 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyClear: case CSSPropertyClip: case CSSPropertyClipPath: - case CSSPropertyColorProfile: case CSSPropertyContent: case CSSPropertyCounterIncrement: case CSSPropertyCounterReset: @@ -439,6 +433,7 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyFontStretch: case CSSPropertyHeight: case CSSPropertyIsolation: + case CSSPropertyJustifySelf: case CSSPropertyLeft: case CSSPropertyLightingColor: case CSSPropertyMargin: @@ -478,6 +473,7 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyPaintOrder: case CSSPropertyPosition: case CSSPropertyRight: + case CSSPropertyScrollBehavior: case CSSPropertySize: case CSSPropertySrc: case CSSPropertyStopColor: @@ -524,6 +520,7 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyWebkitAnimationPlayState: case CSSPropertyWebkitAnimationTimingFunction: case CSSPropertyWebkitAppearance: + case CSSPropertyBackfaceVisibility: case CSSPropertyWebkitBackfaceVisibility: case CSSPropertyWebkitBackgroundClip: case CSSPropertyWebkitBackgroundComposite: @@ -560,14 +557,12 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyWebkitBoxShadow: case CSSPropertyInternalCallback: case CSSPropertyWebkitClipPath: - case CSSPropertyWebkitColumnAxis: case CSSPropertyWebkitColumnBreakAfter: case CSSPropertyWebkitColumnBreakBefore: case CSSPropertyWebkitColumnBreakInside: case CSSPropertyWebkitColumnCount: case CSSPropertyColumnFill: case CSSPropertyWebkitColumnGap: - case CSSPropertyWebkitColumnProgression: case CSSPropertyWebkitColumnRule: case CSSPropertyWebkitColumnRuleColor: case CSSPropertyWebkitColumnRuleStyle: @@ -591,12 +586,14 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyGridColumn: case CSSPropertyGridColumnEnd: case CSSPropertyGridColumnStart: - case CSSPropertyGridDefinitionColumns: - case CSSPropertyGridDefinitionRows: + case CSSPropertyGrid: + case CSSPropertyGridTemplate: + case CSSPropertyGridTemplateColumns: + case CSSPropertyGridTemplateRows: case CSSPropertyGridRow: case CSSPropertyGridRowEnd: case CSSPropertyGridRowStart: - case CSSPropertyGridTemplate: + case CSSPropertyGridTemplateAreas: case CSSPropertyJustifyContent: case CSSPropertyWebkitLineClamp: case CSSPropertyWebkitLogicalHeight: @@ -642,15 +639,20 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyWebkitPaddingBefore: case CSSPropertyWebkitPaddingEnd: case CSSPropertyWebkitPaddingStart: + case CSSPropertyPerspective: case CSSPropertyWebkitPerspective: + case CSSPropertyPerspectiveOrigin: case CSSPropertyWebkitPerspectiveOrigin: case CSSPropertyWebkitPerspectiveOriginX: case CSSPropertyWebkitPerspectiveOriginY: + case CSSPropertyTransform: case CSSPropertyWebkitTransform: + case CSSPropertyTransformOrigin: case CSSPropertyWebkitTransformOrigin: case CSSPropertyWebkitTransformOriginX: case CSSPropertyWebkitTransformOriginY: case CSSPropertyWebkitTransformOriginZ: + case CSSPropertyTransformStyle: case CSSPropertyWebkitTransformStyle: case CSSPropertyWebkitTransition: case CSSPropertyWebkitTransitionDelay: @@ -658,27 +660,21 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) case CSSPropertyWebkitTransitionProperty: case CSSPropertyWebkitTransitionTimingFunction: case CSSPropertyWebkitUserDrag: - case CSSPropertyWebkitFlowInto: - case CSSPropertyWebkitFlowFrom: - case CSSPropertyWebkitRegionBreakAfter: - case CSSPropertyWebkitRegionBreakBefore: - case CSSPropertyWebkitRegionBreakInside: - case CSSPropertyWebkitRegionFragment: case CSSPropertyWebkitWrapFlow: case CSSPropertyShapeMargin: case CSSPropertyShapeImageThreshold: - case CSSPropertyShapePadding: - case CSSPropertyShapeInside: case CSSPropertyShapeOutside: case CSSPropertyWebkitWrapThrough: case CSSPropertyWebkitAppRegion: case CSSPropertyWidth: + case CSSPropertyWillChange: case CSSPropertyMaxZoom: case CSSPropertyMinZoom: case CSSPropertyOrientation: case CSSPropertyUserZoom: case CSSPropertyZIndex: case CSSPropertyZoom: + case CSSPropertyAll: return false; case CSSPropertyInvalid: ASSERT_NOT_REACHED(); @@ -688,4 +684,18 @@ bool CSSProperty::isInheritedProperty(CSSPropertyID propertyID) return false; } +bool CSSProperty::isAffectedByAllProperty(CSSPropertyID propertyID) +{ + if (propertyID == CSSPropertyAll) + return false; + + // all shorthand spec says: + // The all property is a shorthand that resets all CSS properties except + // direction and unicode-bidi. It only accepts the CSS-wide keywords. + // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand + // So CSSPropertyUnicodeBidi and CSSPropertyDirection are not + // affected by all property. + return propertyID != CSSPropertyUnicodeBidi && propertyID != CSSPropertyDirection; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSProperty.h b/chromium/third_party/WebKit/Source/core/css/CSSProperty.h index a0fb377ce3f..bb54c659988 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSProperty.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSProperty.h @@ -21,9 +21,9 @@ #ifndef CSSProperty_h #define CSSProperty_h -#include "CSSPropertyNames.h" -#include "RuntimeEnabledFeatures.h" +#include "core/CSSPropertyNames.h" #include "core/css/CSSValue.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/text/TextDirection.h" #include "platform/text/WritingMode.h" #include "wtf/PassRefPtr.h" @@ -53,12 +53,12 @@ struct StylePropertyMetadata { }; class CSSProperty { + ALLOW_ONLY_INLINE_ALLOCATION(); public: - CSSProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue> value, bool important = false, bool isSetFromShorthand = false, int indexInShorthandsVector = 0, bool implicit = false) + CSSProperty(CSSPropertyID propertyID, PassRefPtrWillBeRawPtr<CSSValue> value, bool important = false, bool isSetFromShorthand = false, int indexInShorthandsVector = 0, bool implicit = false) : m_metadata(propertyID, isSetFromShorthand, indexInShorthandsVector, important, implicit, isInheritedProperty(propertyID)) , m_value(value) { - ASSERT((propertyID == CSSPropertyVariable) == (m_value && m_value->isVariableValue())); } // FIXME: Remove this. @@ -66,7 +66,6 @@ public: : m_metadata(metadata) , m_value(value) { - ASSERT((metadata.m_propertyID == CSSPropertyVariable) == (m_value && m_value->isVariableValue())); } CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); } @@ -80,12 +79,15 @@ public: static CSSPropertyID resolveDirectionAwareProperty(CSSPropertyID, TextDirection, WritingMode); static bool isInheritedProperty(CSSPropertyID); + static bool isAffectedByAllProperty(CSSPropertyID); const StylePropertyMetadata& metadata() const { return m_metadata; } + void trace(Visitor* visitor) { visitor->trace(m_value); } + private: StylePropertyMetadata m_metadata; - RefPtr<CSSValue> m_value; + RefPtrWillBeMember<CSSValue> m_value; }; inline CSSPropertyID prefixingVariantForPropertyId(CSSPropertyID propId) @@ -189,11 +191,6 @@ inline CSSPropertyID prefixingVariantForPropertyId(CSSPropertyID propId) } // namespace WebCore -namespace WTF { -template <> struct VectorTraits<WebCore::CSSProperty> : VectorTraitsBase<false, WebCore::CSSProperty> { - static const bool canInitializeWithMemset = true; - static const bool canMoveWithMemcpy = true; -}; -} +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::CSSProperty); #endif // CSSProperty_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPropertyNames.in b/chromium/third_party/WebKit/Source/core/css/CSSPropertyNames.in index 880cb61d86b..d5c0ace1c6c 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPropertyNames.in +++ b/chromium/third_party/WebKit/Source/core/css/CSSPropertyNames.in @@ -49,11 +49,11 @@ font-kerning font-size font-style font-variant +font-variant-ligatures font-weight text-rendering -webkit-font-feature-settings -webkit-font-smoothing --webkit-font-variant-ligatures -webkit-locale -webkit-text-orientation -epub-text-orientation alias_for=-webkit-text-orientation @@ -136,6 +136,7 @@ font-stretch height image-rendering isolation +justify-self left letter-spacing list-style @@ -183,6 +184,7 @@ position quotes resize right +scroll-behavior size src speak @@ -224,6 +226,7 @@ visibility white-space widows width +will-change word-break -epub-word-break alias_for=word-break word-spacing @@ -231,6 +234,7 @@ word-wrap z-index -webkit-appearance -webkit-aspect-ratio +backface-visibility -webkit-backface-visibility -webkit-background-clip -webkit-background-composite @@ -274,14 +278,12 @@ z-index -webkit-box-reflect -webkit-box-shadow -internal-callback --webkit-column-axis -webkit-column-break-after -webkit-column-break-before -webkit-column-break-inside -webkit-column-count column-fill -webkit-column-gap --webkit-column-progression -webkit-column-rule -webkit-column-rule-color -webkit-column-rule-style @@ -321,20 +323,19 @@ grid-area grid-column grid-column-end grid-column-start -grid-definition-columns -grid-definition-rows +grid +grid-template +grid-template-columns +grid-template-rows grid-row grid-row-end grid-row-start -grid-template +grid-template-areas -webkit-highlight -webkit-hyphenate-character -webkit-line-box-contain --webkit-line-align -webkit-line-break -webkit-line-clamp --webkit-line-grid --webkit-line-snap -webkit-logical-width -webkit-logical-height -webkit-margin-after-collapse @@ -374,7 +375,9 @@ order -webkit-padding-before -webkit-padding-end -webkit-padding-start +perspective -webkit-perspective +perspective-origin -webkit-perspective-origin -webkit-perspective-origin-x -webkit-perspective-origin-y @@ -396,30 +399,23 @@ order -webkit-text-stroke -webkit-text-stroke-color -webkit-text-stroke-width +transform -webkit-transform +transform-origin -webkit-transform-origin -webkit-transform-origin-x -webkit-transform-origin-y -webkit-transform-origin-z +transform-style -webkit-transform-style -webkit-user-drag -webkit-user-modify -webkit-user-select --webkit-flow-into --webkit-flow-from --webkit-region-fragment --webkit-region-break-after --webkit-region-break-before --webkit-region-break-inside --webkit-shape-inside alias_for=shape-inside -webkit-shape-outside alias_for=shape-outside -webkit-shape-margin alias_for=shape-margin --webkit-shape-padding alias_for=shape-padding -webkit-shape-image-threshold alias_for=shape-image-threshold -shape-inside shape-outside shape-margin -shape-padding shape-image-threshold -webkit-wrap-flow -webkit-wrap-through @@ -429,6 +425,7 @@ orientation user-zoom -webkit-tap-highlight-color -webkit-app-region +all // Internal properties. -internal-marquee-direction diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.cpp b/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.cpp index 6a5ff1b31bf..26bf1b68d75 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.cpp @@ -30,10 +30,6 @@ #include "config.h" -#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC -#define CSSPROPERTYSOURCEDATA_HIDE_GLOBALS 1 -#endif - #include "core/css/CSSPropertySourceData.h" #include "wtf/StaticConstructors.h" @@ -114,17 +110,13 @@ unsigned CSSPropertySourceData::hash() const return StringHash::hash(name) + 3 * StringHash::hash(value) + 7 * important + 13 * parsedOk + 31; } -// Global init routines -DEFINE_GLOBAL(CSSPropertySourceData, emptyCSSPropertySourceData, "", "e", false, false) - -// static -void CSSPropertySourceData::init() +void CSSRuleSourceData::trace(Visitor* visitor) { - static bool initialized; - if (!initialized) { - new ((void *) &emptyCSSPropertySourceData) CSSPropertySourceData("", "e", false, false, false, SourceRange(0, 0)); - initialized = true; - } + visitor->trace(ruleHeaderRange); + visitor->trace(ruleBodyRange); + visitor->trace(selectorRanges); + visitor->trace(styleSourceData); + visitor->trace(childRules); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.h b/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.h index 7b964d45f26..704235a23a2 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSPropertySourceData.h @@ -31,6 +31,7 @@ #ifndef CSSPropertySourceData_h #define CSSPropertySourceData_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" @@ -41,17 +42,21 @@ namespace WebCore { class StyleRuleBase; struct SourceRange { + ALLOW_ONLY_INLINE_ALLOCATION(); +public: SourceRange(); SourceRange(unsigned start, unsigned end); unsigned length() const; + void trace(Visitor*) { } + unsigned start; unsigned end; }; struct CSSPropertySourceData { - static void init(); - + ALLOW_ONLY_INLINE_ALLOCATION(); +public: CSSPropertySourceData(const String& name, const String& value, bool important, bool disabled, bool parsedOk, const SourceRange& range); CSSPropertySourceData(const CSSPropertySourceData& other); CSSPropertySourceData(); @@ -59,6 +64,8 @@ struct CSSPropertySourceData { String toString() const; unsigned hash() const; + void trace(Visitor* visitor) { visitor->trace(range); } + String name; String value; bool important; @@ -67,24 +74,22 @@ struct CSSPropertySourceData { SourceRange range; }; -#ifndef CSSPROPERTYSOURCEDATA_HIDE_GLOBALS -extern const CSSPropertySourceData emptyCSSPropertySourceData; -#endif - -struct CSSStyleSourceData : public RefCounted<CSSStyleSourceData> { - static PassRefPtr<CSSStyleSourceData> create() +struct CSSStyleSourceData : public RefCountedWillBeGarbageCollected<CSSStyleSourceData> { + static PassRefPtrWillBeRawPtr<CSSStyleSourceData> create() { - return adoptRef(new CSSStyleSourceData()); + return adoptRefWillBeNoop(new CSSStyleSourceData()); } - Vector<CSSPropertySourceData> propertyData; + void trace(Visitor* visitor) { visitor->trace(propertyData); } + + WillBeHeapVector<CSSPropertySourceData> propertyData; }; struct CSSRuleSourceData; -typedef Vector<RefPtr<CSSRuleSourceData> > RuleSourceDataList; -typedef Vector<SourceRange> SelectorRangeList; +typedef WillBeHeapVector<RefPtrWillBeMember<CSSRuleSourceData> > RuleSourceDataList; +typedef WillBeHeapVector<SourceRange> SelectorRangeList; -struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { +struct CSSRuleSourceData : public RefCountedWillBeGarbageCollected<CSSRuleSourceData> { enum Type { UNKNOWN_RULE, STYLE_RULE, @@ -94,20 +99,19 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { FONT_FACE_RULE, PAGE_RULE, KEYFRAMES_RULE, - REGION_RULE, VIEWPORT_RULE, SUPPORTS_RULE, FILTER_RULE }; - static PassRefPtr<CSSRuleSourceData> create(Type type) + static PassRefPtrWillBeRawPtr<CSSRuleSourceData> create(Type type) { - return adoptRef(new CSSRuleSourceData(type)); + return adoptRefWillBeNoop(new CSSRuleSourceData(type)); } - static PassRefPtr<CSSRuleSourceData> createUnknown() + static PassRefPtrWillBeRawPtr<CSSRuleSourceData> createUnknown() { - return adoptRef(new CSSRuleSourceData(UNKNOWN_RULE)); + return adoptRefWillBeNoop(new CSSRuleSourceData(UNKNOWN_RULE)); } CSSRuleSourceData(Type type) @@ -117,6 +121,8 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { styleSourceData = CSSStyleSourceData::create(); } + void trace(Visitor*); + Type type; // Range of the selector list in the enclosing source. @@ -129,7 +135,7 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { SelectorRangeList selectorRanges; // Only for CSSStyleRules, CSSFontFaceRules, and CSSPageRules. - RefPtr<CSSStyleSourceData> styleSourceData; + RefPtrWillBeMember<CSSStyleSourceData> styleSourceData; // Only for CSSMediaRules. RuleSourceDataList childRules; @@ -137,4 +143,7 @@ struct CSSRuleSourceData : public RefCounted<CSSRuleSourceData> { } // namespace WebCore +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::SourceRange); +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::CSSPropertySourceData); + #endif // CSSPropertySourceData_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.cpp index b13006ccc5e..066d6439862 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.cpp @@ -28,8 +28,6 @@ #include "core/css/CSSPrimitiveValue.h" -using namespace std; - namespace WebCore { String CSSReflectValue::customCSSText() const @@ -39,19 +37,6 @@ String CSSReflectValue::customCSSText() const return m_direction->cssText() + ' ' + m_offset->cssText(); } -String CSSReflectValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - if (m_mask) - return m_direction->customSerializeResolvingVariables(variables) + ' ' + m_offset->customSerializeResolvingVariables(variables) + ' ' + m_mask->serializeResolvingVariables(variables); - return m_direction->customSerializeResolvingVariables(variables) + ' ' + m_offset->customSerializeResolvingVariables(variables); -} - -void CSSReflectValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const -{ - if (m_mask) - m_mask->addSubresourceStyleURLs(urls, styleSheet); -} - bool CSSReflectValue::equals(const CSSReflectValue& other) const { return m_direction == other.m_direction @@ -59,4 +44,12 @@ bool CSSReflectValue::equals(const CSSReflectValue& other) const && compareCSSValuePtr(m_mask, other.m_mask); } +void CSSReflectValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_direction); + visitor->trace(m_offset); + visitor->trace(m_mask); + CSSValue::traceAfterDispatch(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.h b/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.h index 0fd92a07da2..b85d430c002 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSReflectValue.h @@ -36,10 +36,10 @@ class CSSPrimitiveValue; class CSSReflectValue : public CSSValue { public: - static PassRefPtr<CSSReflectValue> create(PassRefPtr<CSSPrimitiveValue> direction, - PassRefPtr<CSSPrimitiveValue> offset, PassRefPtr<CSSValue> mask) + static PassRefPtrWillBeRawPtr<CSSReflectValue> create(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> direction, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> offset, PassRefPtrWillBeRawPtr<CSSValue> mask) { - return adoptRef(new CSSReflectValue(direction, offset, mask)); + return adoptRefWillBeNoop(new CSSReflectValue(direction, offset, mask)); } CSSPrimitiveValue* direction() const { return m_direction.get(); } @@ -47,14 +47,13 @@ public: CSSValue* mask() const { return m_mask.get(); } String customCSSText() const; - String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const; - - void addSubresourceStyleURLs(ListHashSet<KURL>&, const StyleSheetContents*) const; bool equals(const CSSReflectValue&) const; + void traceAfterDispatch(Visitor*); + private: - CSSReflectValue(PassRefPtr<CSSPrimitiveValue> direction, PassRefPtr<CSSPrimitiveValue> offset, PassRefPtr<CSSValue> mask) + CSSReflectValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> direction, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> offset, PassRefPtrWillBeRawPtr<CSSValue> mask) : CSSValue(ReflectClass) , m_direction(direction) , m_offset(offset) @@ -62,9 +61,9 @@ private: { } - RefPtr<CSSPrimitiveValue> m_direction; - RefPtr<CSSPrimitiveValue> m_offset; - RefPtr<CSSValue> m_mask; + RefPtrWillBeMember<CSSPrimitiveValue> m_direction; + RefPtrWillBeMember<CSSPrimitiveValue> m_offset; + RefPtrWillBeMember<CSSValue> m_mask; }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSReflectValue, isReflectValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRegionRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSRegionRule.cpp deleted file mode 100644 index 94e9d0bae8c..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSRegionRule.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * Copyright (C) 2012 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 THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include "core/css/CSSRegionRule.h" - -#include "RuntimeEnabledFeatures.h" -#include "core/css/StyleRule.h" -#include "wtf/text/StringBuilder.h" - -namespace WebCore { -CSSRegionRule::CSSRegionRule(StyleRuleRegion* regionRule, CSSStyleSheet* parent) - : CSSGroupingRule(regionRule, parent) -{ - ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled()); -} - -String CSSRegionRule::cssText() const -{ - StringBuilder result; - result.appendLiteral("@-webkit-region "); - - // First add the selectors. - result.append(toStyleRuleRegion(m_groupRule.get())->selectorList().selectorsText()); - - // Then add the rules. - result.appendLiteral(" { \n"); - appendCSSTextForItems(result); - result.append('}'); - return result.toString(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRegionRule.h b/chromium/third_party/WebKit/Source/core/css/CSSRegionRule.h deleted file mode 100644 index e095da44af4..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSRegionRule.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * Copyright (C) 2012 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 THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef CSSRegionRule_h -#define CSSRegionRule_h - -#include "core/css/CSSGroupingRule.h" - -namespace WebCore { - -class StyleRuleRegion; - -class CSSRegionRule : public CSSGroupingRule { -public: - static PassRefPtr<CSSRegionRule> create(StyleRuleRegion* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSRegionRule(rule, sheet)); } - - virtual CSSRule::Type type() const OVERRIDE { return WEBKIT_REGION_RULE; } - virtual String cssText() const OVERRIDE; - -private: - CSSRegionRule(StyleRuleRegion*, CSSStyleSheet* parent); -}; - -DEFINE_CSS_RULE_TYPE_CASTS(CSSRegionRule, WEBKIT_REGION_RULE); - -} - -#endif // CSSRegionRule_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSRule.cpp index 7673640a990..60aa695022e 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSRule.cpp @@ -29,7 +29,7 @@ namespace WebCore { -struct SameSizeAsCSSRule : public RefCounted<SameSizeAsCSSRule> { +struct SameSizeAsCSSRule : public RefCountedWillBeGarbageCollectedFinalized<SameSizeAsCSSRule> { virtual ~SameSizeAsCSSRule(); unsigned char bitfields; void* pointerUnion; @@ -37,8 +37,6 @@ struct SameSizeAsCSSRule : public RefCounted<SameSizeAsCSSRule> { COMPILE_ASSERT(sizeof(CSSRule) == sizeof(SameSizeAsCSSRule), CSSRule_should_stay_small); -COMPILE_ASSERT(StyleRuleBase::Region == static_cast<StyleRuleBase::Type>(CSSRule::WEBKIT_REGION_RULE), enums_should_match); - COMPILE_ASSERT(StyleRuleBase::Viewport == static_cast<StyleRuleBase::Type>(CSSRule::VIEWPORT_RULE), enums_should_match); void CSSRule::setCSSText(const String&) @@ -52,4 +50,15 @@ const CSSParserContext& CSSRule::parserContext() const return styleSheet ? styleSheet->contents()->parserContext() : strictCSSParserContext(); } +void CSSRule::trace(Visitor* visitor) +{ + // This makes the parent link strong, which is different from the + // pre-oilpan world, where the parent link is mysteriously zeroed under + // some circumstances. + if (m_parentIsRule) + visitor->trace(m_parentRule); + else + visitor->trace(m_parentStyleSheet); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRule.h b/chromium/third_party/WebKit/Source/core/css/CSSRule.h index 9cd66086e23..b160a9e82da 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSRule.h @@ -23,6 +23,7 @@ #ifndef CSSRule_h #define CSSRule_h +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -32,7 +33,7 @@ class CSSParserContext; class CSSStyleSheet; class StyleRuleBase; -class CSSRule : public RefCounted<CSSRule> { +class CSSRule : public RefCountedWillBeGarbageCollectedFinalized<CSSRule> { public: virtual ~CSSRule() { } @@ -53,7 +54,6 @@ public: WEBKIT_KEYFRAME_RULE = KEYFRAME_RULE, SUPPORTS_RULE = 12, VIEWPORT_RULE = 15, - WEBKIT_REGION_RULE = 16, WEBKIT_FILTER_RULE = 17 }; @@ -73,6 +73,8 @@ public: m_parentRule = rule; } + virtual void trace(Visitor*); + CSSStyleSheet* parentStyleSheet() const { if (m_parentIsRule) @@ -102,6 +104,7 @@ private: mutable unsigned char m_hasCachedSelectorText : 1; unsigned char m_parentIsRule : 1; + // These should be Members, but no Members in unions. union { CSSRule* m_parentRule; CSSStyleSheet* m_parentStyleSheet; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRule.idl b/chromium/third_party/WebKit/Source/core/css/CSSRule.idl index 9dadad92a10..a70bd3ec983 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSRule.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSRule.idl @@ -22,6 +22,7 @@ [ Custom=Wrap, DependentLifetime, + WillBeGarbageCollected, ] interface CSSRule { // RuleType @@ -38,7 +39,6 @@ const unsigned short WEBKIT_KEYFRAME_RULE = 8; const unsigned short SUPPORTS_RULE = 12; [RuntimeEnabled=CSSViewport] const unsigned short VIEWPORT_RULE = 15; - [RuntimeEnabled=CSSRegions] const unsigned short WEBKIT_REGION_RULE = 16; const unsigned short WEBKIT_FILTER_RULE = 17; readonly attribute unsigned short type; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRuleList.cpp b/chromium/third_party/WebKit/Source/core/css/CSSRuleList.cpp index 499518bde5d..bfdf30c8719 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSRuleList.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSRuleList.cpp @@ -35,7 +35,9 @@ CSSRuleList::~CSSRuleList() } StaticCSSRuleList::StaticCSSRuleList() +#if !ENABLE(OILPAN) : m_refCount(1) +#endif { } @@ -43,11 +45,20 @@ StaticCSSRuleList::~StaticCSSRuleList() { } +#if !ENABLE(OILPAN) void StaticCSSRuleList::deref() { ASSERT(m_refCount); if (!--m_refCount) delete this; } +#endif + +void StaticCSSRuleList::trace(Visitor* visitor) +{ + visitor->trace(m_rules); + CSSRuleList::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRuleList.h b/chromium/third_party/WebKit/Source/core/css/CSSRuleList.h index f65b3667a4f..81b0fcf9775 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSRuleList.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSRuleList.h @@ -22,6 +22,7 @@ #ifndef CSSRuleList_h #define CSSRuleList_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" @@ -31,60 +32,86 @@ namespace WebCore { class CSSRule; class CSSStyleSheet; -class CSSRuleList { - WTF_MAKE_NONCOPYABLE(CSSRuleList); WTF_MAKE_FAST_ALLOCATED; +class CSSRuleList : public NoBaseWillBeGarbageCollectedFinalized<CSSRuleList> { + WTF_MAKE_NONCOPYABLE(CSSRuleList); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: virtual ~CSSRuleList(); +#if !ENABLE(OILPAN) virtual void ref() = 0; virtual void deref() = 0; +#endif virtual unsigned length() const = 0; virtual CSSRule* item(unsigned index) const = 0; virtual CSSStyleSheet* styleSheet() const = 0; + virtual void trace(Visitor*) { } + protected: CSSRuleList(); }; -class StaticCSSRuleList : public CSSRuleList { +class StaticCSSRuleList FINAL : public CSSRuleList { public: - static PassRefPtr<StaticCSSRuleList> create() { return adoptRef(new StaticCSSRuleList()); } + static PassRefPtrWillBeRawPtr<StaticCSSRuleList> create() + { + return adoptRefWillBeNoop(new StaticCSSRuleList()); + } + +#if !ENABLE(OILPAN) + virtual void ref() OVERRIDE { ++m_refCount; } + virtual void deref() OVERRIDE; +#endif - virtual void ref() { ++m_refCount; } - virtual void deref(); + WillBeHeapVector<RefPtrWillBeMember<CSSRule> >& rules() { return m_rules; } - Vector<RefPtr<CSSRule> >& rules() { return m_rules; } + virtual CSSStyleSheet* styleSheet() const OVERRIDE { return 0; } - virtual CSSStyleSheet* styleSheet() const { return 0; } + virtual void trace(Visitor*) OVERRIDE; private: StaticCSSRuleList(); - ~StaticCSSRuleList(); + virtual ~StaticCSSRuleList(); - virtual unsigned length() const { return m_rules.size(); } - virtual CSSRule* item(unsigned index) const { return index < m_rules.size() ? m_rules[index].get() : 0; } + virtual unsigned length() const OVERRIDE { return m_rules.size(); } + virtual CSSRule* item(unsigned index) const OVERRIDE { return index < m_rules.size() ? m_rules[index].get() : 0; } - Vector<RefPtr<CSSRule> > m_rules; + WillBeHeapVector<RefPtrWillBeMember<CSSRule> > m_rules; +#if !ENABLE(OILPAN) unsigned m_refCount; +#endif }; -// The rule owns the live list. template <class Rule> -class LiveCSSRuleList : public CSSRuleList { +class LiveCSSRuleList FINAL : public CSSRuleList { public: - LiveCSSRuleList(Rule* rule) : m_rule(rule) { } - - virtual void ref() { m_rule->ref(); } - virtual void deref() { m_rule->deref(); } + static PassOwnPtrWillBeRawPtr<LiveCSSRuleList> create(Rule* rule) + { + return adoptPtrWillBeNoop(new LiveCSSRuleList(rule)); + } + +#if !ENABLE(OILPAN) + virtual void ref() OVERRIDE { m_rule->ref(); } + virtual void deref() OVERRIDE { m_rule->deref(); } +#endif + + virtual void trace(Visitor* visitor) OVERRIDE + { + visitor->trace(m_rule); + CSSRuleList::trace(visitor); + } private: - virtual unsigned length() const { return m_rule->length(); } - virtual CSSRule* item(unsigned index) const { return m_rule->item(index); } - virtual CSSStyleSheet* styleSheet() const { return m_rule->parentStyleSheet(); } + LiveCSSRuleList(Rule* rule) : m_rule(rule) { } + + virtual unsigned length() const OVERRIDE { return m_rule->length(); } + virtual CSSRule* item(unsigned index) const OVERRIDE { return m_rule->item(index); } + virtual CSSStyleSheet* styleSheet() const OVERRIDE { return m_rule->parentStyleSheet(); } - Rule* m_rule; + RawPtrWillBeMember<Rule> m_rule; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSRuleList.idl b/chromium/third_party/WebKit/Source/core/css/CSSRuleList.idl index dd189108786..35fb40069fe 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSRuleList.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSRuleList.idl @@ -25,7 +25,8 @@ // Introduced in DOM Level 2: [ - DependentLifetime + DependentLifetime, + WillBeGarbageCollected, ] interface CSSRuleList { readonly attribute unsigned long length; getter CSSRule item(unsigned long index); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp index d0912d4263f..db01c5bbf62 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.cpp @@ -26,8 +26,8 @@ #include "core/css/CSSSVGDocumentValue.h" -#include "FetchInitiatorTypeNames.h" -#include "core/css/CSSParser.h" +#include "core/FetchInitiatorTypeNames.h" +#include "core/css/CSSMarkup.h" #include "core/dom/Document.h" #include "core/fetch/FetchRequest.h" #include "core/fetch/ResourceFetcher.h" diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h b/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h index d2decc42d88..389b1797f60 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSSVGDocumentValue.h @@ -35,7 +35,10 @@ class ResourceFetcher; class CSSSVGDocumentValue : public CSSValue { public: - static PassRefPtr<CSSSVGDocumentValue> create(const String& url) { return adoptRef(new CSSSVGDocumentValue(url)); } + static PassRefPtrWillBeRawPtr<CSSSVGDocumentValue> create(const String& url) + { + return adoptRefWillBeNoop(new CSSSVGDocumentValue(url)); + } ~CSSSVGDocumentValue(); DocumentResource* cachedSVGDocument() const { return m_document.get(); } @@ -46,6 +49,8 @@ public: bool loadRequested() const { return m_loadRequested; } bool equals(const CSSSVGDocumentValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSSVGDocumentValue(const String& url); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp b/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp index eaa1223b132..edb36fa9809 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.cpp @@ -26,8 +26,9 @@ #include "config.h" #include "core/css/CSSSegmentedFontFace.h" -#include "RuntimeEnabledFeatures.h" #include "core/css/CSSFontFace.h" +#include "core/css/CSSFontSelector.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/fonts/FontCache.h" #include "platform/fonts/FontDescription.h" #include "platform/fonts/SegmentedFontData.h" @@ -35,18 +36,20 @@ namespace WebCore { -CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector* fontSelector, FontTraitsMask traitsMask) +CSSSegmentedFontFace::CSSSegmentedFontFace(CSSFontSelector* fontSelector, FontTraits traits) : m_fontSelector(fontSelector) - , m_traitsMask(traitsMask) + , m_traits(traits) + , m_firstNonCssConnectedFace(m_fontFaces.end()) { } CSSSegmentedFontFace::~CSSSegmentedFontFace() { pruneTable(); - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) - m_fontFaces[i]->clearSegmentedFontFace(); +#if !ENABLE(OILPAN) + for (FontFaceList::iterator it = m_fontFaces.begin(); it != m_fontFaces.end(); ++it) + (*it)->cssFontFace()->clearSegmentedFontFace(); +#endif } void CSSSegmentedFontFace::pruneTable() @@ -61,9 +64,8 @@ void CSSSegmentedFontFace::pruneTable() bool CSSSegmentedFontFace::isValid() const { // Valid if at least one font face is valid. - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) { - if (m_fontFaces[i]->isValid()) + for (FontFaceList::const_iterator it = m_fontFaces.begin(); it != m_fontFaces.end(); ++it) { + if ((*it)->cssFontFace()->isValid()) return true; } return false; @@ -72,36 +74,43 @@ bool CSSSegmentedFontFace::isValid() const void CSSSegmentedFontFace::fontLoaded(CSSFontFace*) { pruneTable(); - - if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && !isLoading()) { - Vector<RefPtr<LoadFontCallback> > callbacks; - m_callbacks.swap(callbacks); - for (size_t index = 0; index < callbacks.size(); ++index) { - if (isLoaded()) - callbacks[index]->notifyLoaded(this); - else - callbacks[index]->notifyError(this); - } - } } -void CSSSegmentedFontFace::appendFontFace(PassRefPtr<CSSFontFace> fontFace) +void CSSSegmentedFontFace::fontLoadWaitLimitExceeded(CSSFontFace*) { pruneTable(); - fontFace->setSegmentedFontFace(this); - m_fontFaces.append(fontFace); } -void CSSSegmentedFontFace::removeFontFace(PassRefPtr<CSSFontFace> fontFace) +void CSSSegmentedFontFace::addFontFace(PassRefPtrWillBeRawPtr<FontFace> prpFontFace, bool cssConnected) { - size_t index = m_fontFaces.find(fontFace); - if (index != kNotFound) { - pruneTable(); - m_fontFaces.remove(index); - fontFace->clearSegmentedFontFace(); + RefPtrWillBeRawPtr<FontFace> fontFace = prpFontFace; + pruneTable(); + fontFace->cssFontFace()->setSegmentedFontFace(this); + if (cssConnected) { + m_fontFaces.insertBefore(m_firstNonCssConnectedFace, fontFace); + } else { + // This is the only place in Blink that is using addReturnIterator. + FontFaceList::iterator iterator = m_fontFaces.addReturnIterator(fontFace); + if (m_firstNonCssConnectedFace == m_fontFaces.end()) + m_firstNonCssConnectedFace = iterator; } } +void CSSSegmentedFontFace::removeFontFace(PassRefPtrWillBeRawPtr<FontFace> prpFontFace) +{ + RefPtrWillBeRawPtr<FontFace> fontFace = prpFontFace; + FontFaceList::iterator it = m_fontFaces.find(fontFace); + if (it == m_fontFaces.end()) + return; + + if (it == m_firstNonCssConnectedFace) + ++m_firstNonCssConnectedFace; + m_fontFaces.remove(it); + + pruneTable(); + fontFace->cssFontFace()->clearSegmentedFontFace(); +} + static void appendFontData(SegmentedFontData* newFontData, PassRefPtr<SimpleFontData> prpFaceFontData, const CSSFontFace::UnicodeRangeSet& ranges) { RefPtr<SimpleFontData> faceFontData = prpFaceFontData; @@ -118,13 +127,13 @@ static void appendFontData(SegmentedFontData* newFontData, PassRefPtr<SimpleFont PassRefPtr<FontData> CSSSegmentedFontFace::getFontData(const FontDescription& fontDescription) { if (!isValid()) - return 0; + return nullptr; - FontTraitsMask desiredTraitsMask = fontDescription.traitsMask(); + FontTraits desiredTraits = fontDescription.traits(); AtomicString emptyFontFamily = ""; - FontCacheKey key = fontDescription.cacheKey(emptyFontFamily, desiredTraitsMask); + FontCacheKey key = fontDescription.cacheKey(emptyFontFamily, desiredTraits); - RefPtr<SegmentedFontData>& fontData = m_fontDataTable.add(key.hash(), 0).iterator->value; + RefPtr<SegmentedFontData>& fontData = m_fontDataTable.add(key.hash(), nullptr).storedValue->value; if (fontData && fontData->numRanges()) return fontData; // No release, we have a reference to an object in the cache which should retain the ref count it has. @@ -132,35 +141,34 @@ PassRefPtr<FontData> CSSSegmentedFontFace::getFontData(const FontDescription& fo fontData = SegmentedFontData::create(); FontDescription requestedFontDescription(fontDescription); - requestedFontDescription.setTraitsMask(m_traitsMask); - requestedFontDescription.setSyntheticBold(!(m_traitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask)) && (desiredTraitsMask & (FontWeight600Mask | FontWeight700Mask | FontWeight800Mask | FontWeight900Mask))); - requestedFontDescription.setSyntheticItalic(!(m_traitsMask & FontStyleItalicMask) && (desiredTraitsMask & FontStyleItalicMask)); + requestedFontDescription.setTraits(m_traits); + requestedFontDescription.setSyntheticBold(m_traits.weight() < FontWeight600 && desiredTraits.weight() >= FontWeight600); + requestedFontDescription.setSyntheticItalic(m_traits.style() == FontStyleNormal && desiredTraits.style() == FontStyleItalic); - for (int i = m_fontFaces.size() - 1; i >= 0; --i) { - if (!m_fontFaces[i]->isValid()) + for (FontFaceList::reverse_iterator it = m_fontFaces.rbegin(); it != m_fontFaces.rend(); ++it) { + if (!(*it)->cssFontFace()->isValid()) continue; - if (RefPtr<SimpleFontData> faceFontData = m_fontFaces[i]->getFontData(requestedFontDescription)) { + if (RefPtr<SimpleFontData> faceFontData = (*it)->cssFontFace()->getFontData(requestedFontDescription)) { ASSERT(!faceFontData->isSegmented()); #if ENABLE(SVG_FONTS) // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable // of small-caps synthesis and just ignore the font face. - if (faceFontData->isSVGFont() && (desiredTraitsMask & FontVariantSmallCapsMask) && !(m_traitsMask & FontVariantSmallCapsMask)) + if (faceFontData->isSVGFont() && desiredTraits.variant() == FontVariantSmallCaps && m_traits.variant() == FontVariantNormal) continue; #endif - appendFontData(fontData.get(), faceFontData.release(), m_fontFaces[i]->ranges()); + appendFontData(fontData.get(), faceFontData.release(), (*it)->cssFontFace()->ranges()); } } if (fontData->numRanges()) return fontData; // No release, we have a reference to an object in the cache which should retain the ref count it has. - return 0; + return nullptr; } bool CSSSegmentedFontFace::isLoading() const { - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) { - if (m_fontFaces[i]->loadStatus() == FontFace::Loading) + for (FontFaceList::const_iterator it = m_fontFaces.begin(); it != m_fontFaces.end(); ++it) { + if ((*it)->loadStatus() == FontFace::Loading) return true; } return false; @@ -168,61 +176,44 @@ bool CSSSegmentedFontFace::isLoading() const bool CSSSegmentedFontFace::isLoaded() const { - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) { - if (m_fontFaces[i]->loadStatus() != FontFace::Loaded) + for (FontFaceList::const_iterator it = m_fontFaces.begin(); it != m_fontFaces.end(); ++it) { + if ((*it)->loadStatus() != FontFace::Loaded) return false; } return true; } -void CSSSegmentedFontFace::willUseFontData(const FontDescription& fontDescription) +void CSSSegmentedFontFace::willUseFontData(const FontDescription& fontDescription, UChar32 character) { - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) - m_fontFaces[i]->willUseFontData(fontDescription); + for (FontFaceList::reverse_iterator it = m_fontFaces.rbegin(); it != m_fontFaces.rend(); ++it) { + if ((*it)->loadStatus() != FontFace::Unloaded) + break; + if ((*it)->cssFontFace()->maybeScheduleFontLoad(fontDescription, character)) + break; + } } bool CSSSegmentedFontFace::checkFont(const String& text) const { - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) { - if (m_fontFaces[i]->loadStatus() != FontFace::Loaded && m_fontFaces[i]->ranges().intersectsWith(text)) + for (FontFaceList::const_iterator it = m_fontFaces.begin(); it != m_fontFaces.end(); ++it) { + if ((*it)->loadStatus() != FontFace::Loaded && (*it)->cssFontFace()->ranges().intersectsWith(text)) return false; } return true; } -void CSSSegmentedFontFace::loadFont(const FontDescription& fontDescription, const String& text, PassRefPtr<LoadFontCallback> callback) +void CSSSegmentedFontFace::match(const String& text, WillBeHeapVector<RefPtrWillBeMember<FontFace> >& faces) const { - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) { - if (m_fontFaces[i]->loadStatus() == FontFace::Unloaded && m_fontFaces[i]->ranges().intersectsWith(text)) { - RefPtr<SimpleFontData> fontData = m_fontFaces[i]->getFontData(fontDescription); - if (fontData->customFontData()) - fontData->customFontData()->beginLoadIfNeeded(); - } - } - - if (callback) { - if (isLoading()) - m_callbacks.append(callback); - else if (isLoaded()) - callback->notifyLoaded(this); - else - callback->notifyError(this); + for (FontFaceList::const_iterator it = m_fontFaces.begin(); it != m_fontFaces.end(); ++it) { + if ((*it)->cssFontFace()->ranges().intersectsWith(text)) + faces.append(*it); } } -Vector<RefPtr<FontFace> > CSSSegmentedFontFace::fontFaces(const String& text) const +void CSSSegmentedFontFace::trace(Visitor* visitor) { - Vector<RefPtr<FontFace> > fontFaces; - unsigned size = m_fontFaces.size(); - for (unsigned i = 0; i < size; i++) { - if (m_fontFaces[i]->ranges().intersectsWith(text)) - fontFaces.append(m_fontFaces[i]->fontFace()); - } - return fontFaces; + visitor->trace(m_fontSelector); + visitor->trace(m_fontFaces); } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h b/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h index 26c5bb1e0b0..a3630e38aa7 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFace.h @@ -26,8 +26,10 @@ #ifndef CSSSegmentedFontFace_h #define CSSSegmentedFontFace_h -#include "platform/fonts/FontTraitsMask.h" +#include "platform/fonts/FontTraits.h" +#include "platform/heap/Handle.h" #include "wtf/HashMap.h" +#include "wtf/ListHashSet.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" @@ -42,47 +44,48 @@ class FontDescription; class FontFace; class SegmentedFontData; -class CSSSegmentedFontFace : public RefCounted<CSSSegmentedFontFace> { +class CSSSegmentedFontFace FINAL : public RefCountedWillBeGarbageCollectedFinalized<CSSSegmentedFontFace> { public: - static PassRefPtr<CSSSegmentedFontFace> create(CSSFontSelector* selector, FontTraitsMask traitsMask) { return adoptRef(new CSSSegmentedFontFace(selector, traitsMask)); } + static PassRefPtrWillBeRawPtr<CSSSegmentedFontFace> create(CSSFontSelector* selector, FontTraits traits) + { + return adoptRefWillBeNoop(new CSSSegmentedFontFace(selector, traits)); + } ~CSSSegmentedFontFace(); CSSFontSelector* fontSelector() const { return m_fontSelector; } - FontTraitsMask traitsMask() const { return m_traitsMask; } + FontTraits traits() const { return m_traits; } void fontLoaded(CSSFontFace*); + void fontLoadWaitLimitExceeded(CSSFontFace*); - void appendFontFace(PassRefPtr<CSSFontFace>); - void removeFontFace(PassRefPtr<CSSFontFace>); + void addFontFace(PassRefPtrWillBeRawPtr<FontFace>, bool cssConnected); + void removeFontFace(PassRefPtrWillBeRawPtr<FontFace>); bool isEmpty() const { return m_fontFaces.isEmpty(); } PassRefPtr<FontData> getFontData(const FontDescription&); - class LoadFontCallback : public RefCounted<LoadFontCallback> { - public: - virtual ~LoadFontCallback() { } - virtual void notifyLoaded(CSSSegmentedFontFace*) = 0; - virtual void notifyError(CSSSegmentedFontFace*) = 0; - }; - bool checkFont(const String&) const; - void loadFont(const FontDescription&, const String&, PassRefPtr<LoadFontCallback>); - Vector<RefPtr<FontFace> > fontFaces(const String& text) const; - void willUseFontData(const FontDescription&); + void match(const String&, WillBeHeapVector<RefPtrWillBeMember<FontFace> >&) const; + void willUseFontData(const FontDescription&, UChar32); + + void trace(Visitor*); private: - CSSSegmentedFontFace(CSSFontSelector*, FontTraitsMask); + CSSSegmentedFontFace(CSSFontSelector*, FontTraits); void pruneTable(); bool isValid() const; bool isLoading() const; bool isLoaded() const; - CSSFontSelector* m_fontSelector; - FontTraitsMask m_traitsMask; + typedef WillBeHeapListHashSet<RefPtrWillBeMember<FontFace> > FontFaceList; + + RawPtrWillBeMember<CSSFontSelector> m_fontSelector; + FontTraits m_traits; HashMap<unsigned, RefPtr<SegmentedFontData> > m_fontDataTable; - Vector<RefPtr<CSSFontFace>, 1> m_fontFaces; - Vector<RefPtr<LoadFontCallback> > m_callbacks; + // All non-CSS-connected FontFaces are stored after the CSS-connected ones. + FontFaceList m_fontFaces; + FontFaceList::iterator m_firstNonCssConnectedFace; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFaceCache.cpp b/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFaceCache.cpp deleted file mode 100644 index 17803d82821..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFaceCache.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved. - * Copyright (C) 2013 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 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, - * 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 "CSSSegmentedFontFaceCache.h" - -#include "FontFamilyNames.h" -#include "core/css/CSSFontFace.h" -#include "core/css/CSSFontFaceSource.h" -#include "core/css/CSSFontSelector.h" -#include "core/css/CSSSegmentedFontFace.h" -#include "core/css/CSSValueList.h" -#include "core/css/StyleRule.h" -#include "core/fetch/FontResource.h" -#include "core/fetch/ResourceFetcher.h" -#include "platform/fonts/FontDescription.h" -#include "wtf/text/AtomicString.h" - -namespace WebCore { - -CSSSegmentedFontFaceCache::CSSSegmentedFontFaceCache() - : m_version(0) -{ -} - -void CSSSegmentedFontFaceCache::add(CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule, PassRefPtr<CSSFontFace> prpCssFontFace) -{ - RefPtr<CSSFontFace> cssFontFace = prpCssFontFace; - - if (!m_styleRuleToFontFace.add(fontFaceRule, cssFontFace).isNewEntry) - return; - - FontFace* fontFace = cssFontFace->fontFace(); - - OwnPtr<TraitsMap>& familyFontFaces = m_fontFaces.add(fontFace->family(), nullptr).iterator->value; - if (!familyFontFaces) - familyFontFaces = adoptPtr(new TraitsMap); - - RefPtr<CSSSegmentedFontFace>& segmentedFontFace = familyFontFaces->add(fontFace->traitsMask(), 0).iterator->value; - if (!segmentedFontFace) - segmentedFontFace = CSSSegmentedFontFace::create(cssFontSelector, static_cast<FontTraitsMask>(fontFace->traitsMask())); - - segmentedFontFace->appendFontFace(cssFontFace); - - ++m_version; -} - -void CSSSegmentedFontFaceCache::remove(const StyleRuleFontFace* fontFaceRule) -{ - StyleRuleToFontFace::iterator styleRuleToFontFaceIter = m_styleRuleToFontFace.find(fontFaceRule); - if (styleRuleToFontFaceIter == m_styleRuleToFontFace.end()) - return; - RefPtr<CSSFontFace> cssFontFace = styleRuleToFontFaceIter->value; - - FamilyToTraitsMap::iterator fontFacesIter = m_fontFaces.find(cssFontFace->fontFace()->family()); - if (fontFacesIter == m_fontFaces.end()) - return; - TraitsMap* familyFontFaces = fontFacesIter->value.get(); - - TraitsMap::iterator familyFontFacesIter = familyFontFaces->find(cssFontFace->fontFace()->traitsMask()); - if (familyFontFacesIter == familyFontFaces->end()) - return; - RefPtr<CSSSegmentedFontFace> segmentedFontFace = familyFontFacesIter->value; - - segmentedFontFace->removeFontFace(cssFontFace); - if (segmentedFontFace->isEmpty()) { - familyFontFaces->remove(familyFontFacesIter); - if (familyFontFaces->isEmpty()) - m_fontFaces.remove(fontFacesIter); - } - m_styleRuleToFontFace.remove(styleRuleToFontFaceIter); - m_fonts.clear(); - ++m_version; -} - -static inline bool compareFontFaces(CSSSegmentedFontFace* first, CSSSegmentedFontFace* second, FontTraitsMask desiredTraitsMask) -{ - FontTraitsMask firstTraitsMask = first->traitsMask(); - FontTraitsMask secondTraitsMask = second->traitsMask(); - - bool firstHasDesiredVariant = firstTraitsMask & desiredTraitsMask & FontVariantMask; - bool secondHasDesiredVariant = secondTraitsMask & desiredTraitsMask & FontVariantMask; - - if (firstHasDesiredVariant != secondHasDesiredVariant) - return firstHasDesiredVariant; - - // We need to check font-variant css property for CSS2.1 compatibility. - if (desiredTraitsMask & FontVariantSmallCapsMask) { - // Prefer a font that has indicated that it can only support small-caps to a font that claims to support - // all variants. The specialized font is more likely to be true small-caps and not require synthesis. - bool firstRequiresSmallCaps = (firstTraitsMask & FontVariantSmallCapsMask) && !(firstTraitsMask & FontVariantNormalMask); - bool secondRequiresSmallCaps = (secondTraitsMask & FontVariantSmallCapsMask) && !(secondTraitsMask & FontVariantNormalMask); - if (firstRequiresSmallCaps != secondRequiresSmallCaps) - return firstRequiresSmallCaps; - } - - bool firstHasDesiredStyle = firstTraitsMask & desiredTraitsMask & FontStyleMask; - bool secondHasDesiredStyle = secondTraitsMask & desiredTraitsMask & FontStyleMask; - - if (firstHasDesiredStyle != secondHasDesiredStyle) - return firstHasDesiredStyle; - - if (desiredTraitsMask & FontStyleItalicMask) { - // Prefer a font that has indicated that it can only support italics to a font that claims to support - // all styles. The specialized font is more likely to be the one the author wants used. - bool firstRequiresItalics = (firstTraitsMask & FontStyleItalicMask) && !(firstTraitsMask & FontStyleNormalMask); - bool secondRequiresItalics = (secondTraitsMask & FontStyleItalicMask) && !(secondTraitsMask & FontStyleNormalMask); - if (firstRequiresItalics != secondRequiresItalics) - return firstRequiresItalics; - } - - if (secondTraitsMask & desiredTraitsMask & FontWeightMask) - return false; - if (firstTraitsMask & desiredTraitsMask & FontWeightMask) - return true; - - // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says : - // - If the desired weight is less than 400, weights below the desired weight are checked in descending order followed by weights above the desired weight in ascending order until a match is found. - // - If the desired weight is greater than 500, weights above the desired weight are checked in ascending order followed by weights below the desired weight in descending order until a match is found. - // - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used. - // - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used. - - static const unsigned fallbackRuleSets = 9; - static const unsigned rulesPerSet = 8; - static const FontTraitsMask weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = { - { FontWeight200Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, - { FontWeight100Mask, FontWeight300Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, - { FontWeight200Mask, FontWeight100Mask, FontWeight400Mask, FontWeight500Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, - { FontWeight500Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, - { FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask, FontWeight600Mask, FontWeight700Mask, FontWeight800Mask, FontWeight900Mask }, - { FontWeight700Mask, FontWeight800Mask, FontWeight900Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, - { FontWeight800Mask, FontWeight900Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, - { FontWeight900Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask }, - { FontWeight800Mask, FontWeight700Mask, FontWeight600Mask, FontWeight500Mask, FontWeight400Mask, FontWeight300Mask, FontWeight200Mask, FontWeight100Mask } - }; - - unsigned ruleSetIndex = 0; - unsigned w = FontWeight100Bit; - while (!(desiredTraitsMask & (1 << w))) { - w++; - ruleSetIndex++; - } - - ASSERT(ruleSetIndex < fallbackRuleSets); - const FontTraitsMask* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex]; - for (unsigned i = 0; i < rulesPerSet; ++i) { - if (secondTraitsMask & weightFallbackRule[i]) - return false; - if (firstTraitsMask & weightFallbackRule[i]) - return true; - } - - return false; -} - -CSSSegmentedFontFace* CSSSegmentedFontFaceCache::get(const FontDescription& fontDescription, const AtomicString& family) -{ - TraitsMap* familyFontFaces = m_fontFaces.get(family); - if (!familyFontFaces || familyFontFaces->isEmpty()) - return 0; - - OwnPtr<TraitsMap>& segmentedFontFaceCache = m_fonts.add(family, nullptr).iterator->value; - if (!segmentedFontFaceCache) - segmentedFontFaceCache = adoptPtr(new TraitsMap); - - FontTraitsMask traitsMask = fontDescription.traitsMask(); - - RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).iterator->value; - if (!face) { - for (TraitsMap::const_iterator i = familyFontFaces->begin(); i != familyFontFaces->end(); ++i) { - CSSSegmentedFontFace* candidate = i->value.get(); - unsigned candidateTraitsMask = candidate->traitsMask(); - if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) - continue; - if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) - continue; - if (!face || compareFontFaces(candidate, face.get(), traitsMask)) - face = candidate; - } - } - return face.get(); -} - -} diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSelector.cpp b/chromium/third_party/WebKit/Source/core/css/CSSSelector.cpp index b744726355b..293cb2fd7f9 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSelector.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSSelector.cpp @@ -26,15 +26,18 @@ #include "config.h" #include "core/css/CSSSelector.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" +#include "core/HTMLNames.h" #include "core/css/CSSOMUtils.h" #include "core/css/CSSSelectorList.h" +#include "platform/RuntimeEnabledFeatures.h" #include "wtf/Assertions.h" #include "wtf/HashMap.h" #include "wtf/StdLibExtras.h" #include "wtf/text/StringBuilder.h" -#include "wtf/text/StringHash.h" + +#ifndef NDEBUG +#include <stdio.h> +#endif namespace WebCore { @@ -52,8 +55,10 @@ void CSSSelector::createRareData() ASSERT(m_match != Tag); if (m_hasRareData) return; - // Move the value to the rare data stucture. - m_data.m_rareData = RareData::create(adoptRef(m_data.m_value)).leakRef(); + AtomicString value(m_data.m_value); + if (m_data.m_value) + m_data.m_value->deref(); + m_data.m_rareData = RareData::create(value).leakRef(); m_hasRareData = true; } @@ -94,7 +99,7 @@ inline unsigned CSSSelector::specificityForOneSelector() const case Id: return 0x10000; case PseudoClass: - if (pseudoType() == PseudoHost) + if (pseudoType() == PseudoHost || pseudoType() == PseudoHostContext) return 0; // fall through. case Exact: @@ -183,12 +188,6 @@ PseudoId CSSSelector::pseudoId(PseudoType type) return SCROLLBAR_TRACK_PIECE; case PseudoResizer: return RESIZER; - case PseudoFullScreen: - return FULL_SCREEN; - case PseudoFullScreenDocument: - return FULL_SCREEN_DOCUMENT; - case PseudoFullScreenAncestor: - return FULL_SCREEN_ANCESTOR; case PseudoUnknown: case PseudoEmpty: case PseudoFirstChild: @@ -250,11 +249,14 @@ PseudoId CSSSelector::pseudoId(PseudoType type) case PseudoCue: case PseudoFutureCue: case PseudoPastCue: - case PseudoSeamlessDocument: - case PseudoDistributed: case PseudoUnresolved: case PseudoContent: case PseudoHost: + case PseudoHostContext: + case PseudoShadow: + case PseudoFullScreen: + case PseudoFullScreenDocument: + case PseudoFullScreenAncestor: return NOPSEUDO; case PseudoNotParsed: ASSERT_NOT_REACHED(); @@ -265,191 +267,168 @@ PseudoId CSSSelector::pseudoId(PseudoType type) return NOPSEUDO; } -static HashMap<StringImpl*, CSSSelector::PseudoType>* nameToPseudoTypeMap() +// Could be made smaller and faster by replacing pointer with an +// offset into a string buffer and making the bit fields smaller but +// that could not be maintained by hand. +struct NameToPseudoStruct { + const char* string; + unsigned type:8; +}; + +// This table should be kept sorted. +const static NameToPseudoStruct pseudoTypeMap[] = { +{"-webkit-any(", CSSSelector::PseudoAny}, +{"-webkit-any-link", CSSSelector::PseudoAnyLink}, +{"-webkit-autofill", CSSSelector::PseudoAutofill}, +{"-webkit-drag", CSSSelector::PseudoDrag}, +{"-webkit-full-page-media", CSSSelector::PseudoFullPageMedia}, +{"-webkit-full-screen", CSSSelector::PseudoFullScreen}, +{"-webkit-full-screen-ancestor", CSSSelector::PseudoFullScreenAncestor}, +{"-webkit-full-screen-document", CSSSelector::PseudoFullScreenDocument}, +{"-webkit-resizer", CSSSelector::PseudoResizer}, +{"-webkit-scrollbar", CSSSelector::PseudoScrollbar}, +{"-webkit-scrollbar-button", CSSSelector::PseudoScrollbarButton}, +{"-webkit-scrollbar-corner", CSSSelector::PseudoScrollbarCorner}, +{"-webkit-scrollbar-thumb", CSSSelector::PseudoScrollbarThumb}, +{"-webkit-scrollbar-track", CSSSelector::PseudoScrollbarTrack}, +{"-webkit-scrollbar-track-piece", CSSSelector::PseudoScrollbarTrackPiece}, +{"active", CSSSelector::PseudoActive}, +{"after", CSSSelector::PseudoAfter}, +{"backdrop", CSSSelector::PseudoBackdrop}, +{"before", CSSSelector::PseudoBefore}, +{"checked", CSSSelector::PseudoChecked}, +{"content", CSSSelector::PseudoContent}, +{"corner-present", CSSSelector::PseudoCornerPresent}, +{"cue", CSSSelector::PseudoWebKitCustomElement}, +{"cue(", CSSSelector::PseudoCue}, +{"decrement", CSSSelector::PseudoDecrement}, +{"default", CSSSelector::PseudoDefault}, +{"disabled", CSSSelector::PseudoDisabled}, +{"double-button", CSSSelector::PseudoDoubleButton}, +{"empty", CSSSelector::PseudoEmpty}, +{"enabled", CSSSelector::PseudoEnabled}, +{"end", CSSSelector::PseudoEnd}, +{"first", CSSSelector::PseudoFirstPage}, +{"first-child", CSSSelector::PseudoFirstChild}, +{"first-letter", CSSSelector::PseudoFirstLetter}, +{"first-line", CSSSelector::PseudoFirstLine}, +{"first-of-type", CSSSelector::PseudoFirstOfType}, +{"focus", CSSSelector::PseudoFocus}, +{"future", CSSSelector::PseudoFutureCue}, +{"horizontal", CSSSelector::PseudoHorizontal}, +{"host", CSSSelector::PseudoHost}, +{"host(", CSSSelector::PseudoHost}, +{"host-context(", CSSSelector::PseudoHostContext}, +{"hover", CSSSelector::PseudoHover}, +{"in-range", CSSSelector::PseudoInRange}, +{"increment", CSSSelector::PseudoIncrement}, +{"indeterminate", CSSSelector::PseudoIndeterminate}, +{"invalid", CSSSelector::PseudoInvalid}, +{"lang(", CSSSelector::PseudoLang}, +{"last-child", CSSSelector::PseudoLastChild}, +{"last-of-type", CSSSelector::PseudoLastOfType}, +{"left", CSSSelector::PseudoLeftPage}, +{"link", CSSSelector::PseudoLink}, +{"no-button", CSSSelector::PseudoNoButton}, +{"not(", CSSSelector::PseudoNot}, +{"nth-child(", CSSSelector::PseudoNthChild}, +{"nth-last-child(", CSSSelector::PseudoNthLastChild}, +{"nth-last-of-type(", CSSSelector::PseudoNthLastOfType}, +{"nth-of-type(", CSSSelector::PseudoNthOfType}, +{"only-child", CSSSelector::PseudoOnlyChild}, +{"only-of-type", CSSSelector::PseudoOnlyOfType}, +{"optional", CSSSelector::PseudoOptional}, +{"out-of-range", CSSSelector::PseudoOutOfRange}, +{"past", CSSSelector::PseudoPastCue}, +{"read-only", CSSSelector::PseudoReadOnly}, +{"read-write", CSSSelector::PseudoReadWrite}, +{"required", CSSSelector::PseudoRequired}, +{"right", CSSSelector::PseudoRightPage}, +{"root", CSSSelector::PseudoRoot}, +{"scope", CSSSelector::PseudoScope}, +{"selection", CSSSelector::PseudoSelection}, +{"shadow", CSSSelector::PseudoShadow}, +{"single-button", CSSSelector::PseudoSingleButton}, +{"start", CSSSelector::PseudoStart}, +{"target", CSSSelector::PseudoTarget}, +{"unresolved", CSSSelector::PseudoUnresolved}, +{"valid", CSSSelector::PseudoValid}, +{"vertical", CSSSelector::PseudoVertical}, +{"visited", CSSSelector::PseudoVisited}, +{"window-inactive", CSSSelector::PseudoWindowInactive}, +}; + +class NameToPseudoCompare { +public: + NameToPseudoCompare(const AtomicString& key) : m_key(key) { ASSERT(m_key.is8Bit()); } + + bool operator()(const NameToPseudoStruct& entry, const NameToPseudoStruct&) + { + ASSERT(entry.string); + const char* key = reinterpret_cast<const char*>(m_key.characters8()); + // If strncmp returns 0, then either the keys are equal, or |m_key| sorts before |entry|. + return strncmp(entry.string, key, m_key.length()) < 0; + } + +private: + const AtomicString& m_key; +}; + +static CSSSelector::PseudoType nameToPseudoType(const AtomicString& name) { - DEFINE_STATIC_LOCAL(AtomicString, active, ("active", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, after, ("after", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, any, ("-webkit-any(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, anyLink, ("-webkit-any-link", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, autofill, ("-webkit-autofill", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, backdrop, ("backdrop", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, before, ("before", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, checked, ("checked", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, defaultString, ("default", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, disabled, ("disabled", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, readOnly, ("read-only", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, readWrite, ("read-write", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, valid, ("valid", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, invalid, ("invalid", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, drag, ("-webkit-drag", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, empty, ("empty", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, enabled, ("enabled", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, firstChild, ("first-child", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, firstLetter, ("first-letter", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, firstLine, ("first-line", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, firstOfType, ("first-of-type", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, fullPageMedia, ("-webkit-full-page-media", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, nthChild, ("nth-child(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, nthOfType, ("nth-of-type(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, nthLastChild, ("nth-last-child(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, nthLastOfType, ("nth-last-of-type(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, focus, ("focus", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, hover, ("hover", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, indeterminate, ("indeterminate", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, lastChild, ("last-child", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, lastOfType, ("last-of-type", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, link, ("link", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, lang, ("lang(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, notStr, ("not(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, onlyChild, ("only-child", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, onlyOfType, ("only-of-type", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, optional, ("optional", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, required, ("required", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, resizer, ("-webkit-resizer", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, root, ("root", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scrollbar, ("-webkit-scrollbar", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scrollbarButton, ("-webkit-scrollbar-button", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scrollbarCorner, ("-webkit-scrollbar-corner", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scrollbarThumb, ("-webkit-scrollbar-thumb", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrack, ("-webkit-scrollbar-track", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scrollbarTrackPiece, ("-webkit-scrollbar-track-piece", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, selection, ("selection", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, target, ("target", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, visited, ("visited", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, windowInactive, ("window-inactive", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, decrement, ("decrement", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, increment, ("increment", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, start, ("start", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, end, ("end", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, horizontal, ("horizontal", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, vertical, ("vertical", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, doubleButton, ("double-button", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, singleButton, ("single-button", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, noButton, ("no-button", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, cornerPresent, ("corner-present", AtomicString::ConstructFromLiteral)); - // Paged Media pseudo-classes - DEFINE_STATIC_LOCAL(AtomicString, firstPage, ("first", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, leftPage, ("left", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, rightPage, ("right", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, fullScreen, ("-webkit-full-screen", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, fullScreenDocument, ("-webkit-full-screen-document", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, fullScreenAncestor, ("-webkit-full-screen-ancestor", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, cue, ("cue(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, cueWithoutParen, ("cue", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, futureCue, ("future", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, pastCue, ("past", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, seamlessDocument, ("-webkit-seamless-document", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, distributed, ("-webkit-distributed(", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, inRange, ("in-range", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, outOfRange, ("out-of-range", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, scope, ("scope", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, unresolved, ("unresolved", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, content, ("content", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, host, ("host", AtomicString::ConstructFromLiteral)); - DEFINE_STATIC_LOCAL(AtomicString, hostWithParams, ("host(", AtomicString::ConstructFromLiteral)); - - static HashMap<StringImpl*, CSSSelector::PseudoType>* nameToPseudoType = 0; - if (!nameToPseudoType) { - nameToPseudoType = new HashMap<StringImpl*, CSSSelector::PseudoType>; - 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(backdrop.impl(), CSSSelector::PseudoBackdrop); - nameToPseudoType->set(before.impl(), CSSSelector::PseudoBefore); - nameToPseudoType->set(checked.impl(), CSSSelector::PseudoChecked); - nameToPseudoType->set(defaultString.impl(), CSSSelector::PseudoDefault); - nameToPseudoType->set(disabled.impl(), CSSSelector::PseudoDisabled); - nameToPseudoType->set(readOnly.impl(), CSSSelector::PseudoReadOnly); - nameToPseudoType->set(readWrite.impl(), CSSSelector::PseudoReadWrite); - nameToPseudoType->set(valid.impl(), CSSSelector::PseudoValid); - nameToPseudoType->set(invalid.impl(), CSSSelector::PseudoInvalid); - nameToPseudoType->set(drag.impl(), CSSSelector::PseudoDrag); - nameToPseudoType->set(enabled.impl(), CSSSelector::PseudoEnabled); - nameToPseudoType->set(empty.impl(), CSSSelector::PseudoEmpty); - nameToPseudoType->set(firstChild.impl(), CSSSelector::PseudoFirstChild); - nameToPseudoType->set(fullPageMedia.impl(), CSSSelector::PseudoFullPageMedia); - nameToPseudoType->set(lastChild.impl(), CSSSelector::PseudoLastChild); - nameToPseudoType->set(lastOfType.impl(), CSSSelector::PseudoLastOfType); - nameToPseudoType->set(onlyChild.impl(), CSSSelector::PseudoOnlyChild); - nameToPseudoType->set(onlyOfType.impl(), CSSSelector::PseudoOnlyOfType); - nameToPseudoType->set(firstLetter.impl(), CSSSelector::PseudoFirstLetter); - nameToPseudoType->set(firstLine.impl(), CSSSelector::PseudoFirstLine); - nameToPseudoType->set(firstOfType.impl(), CSSSelector::PseudoFirstOfType); - nameToPseudoType->set(focus.impl(), CSSSelector::PseudoFocus); - nameToPseudoType->set(hover.impl(), CSSSelector::PseudoHover); - nameToPseudoType->set(indeterminate.impl(), CSSSelector::PseudoIndeterminate); - nameToPseudoType->set(link.impl(), CSSSelector::PseudoLink); - nameToPseudoType->set(lang.impl(), CSSSelector::PseudoLang); - nameToPseudoType->set(notStr.impl(), CSSSelector::PseudoNot); - nameToPseudoType->set(nthChild.impl(), CSSSelector::PseudoNthChild); - nameToPseudoType->set(nthOfType.impl(), CSSSelector::PseudoNthOfType); - nameToPseudoType->set(nthLastChild.impl(), CSSSelector::PseudoNthLastChild); - nameToPseudoType->set(nthLastOfType.impl(), CSSSelector::PseudoNthLastOfType); - nameToPseudoType->set(root.impl(), CSSSelector::PseudoRoot); - nameToPseudoType->set(windowInactive.impl(), CSSSelector::PseudoWindowInactive); - nameToPseudoType->set(decrement.impl(), CSSSelector::PseudoDecrement); - nameToPseudoType->set(increment.impl(), CSSSelector::PseudoIncrement); - nameToPseudoType->set(start.impl(), CSSSelector::PseudoStart); - nameToPseudoType->set(end.impl(), CSSSelector::PseudoEnd); - nameToPseudoType->set(horizontal.impl(), CSSSelector::PseudoHorizontal); - nameToPseudoType->set(vertical.impl(), CSSSelector::PseudoVertical); - nameToPseudoType->set(doubleButton.impl(), CSSSelector::PseudoDoubleButton); - nameToPseudoType->set(singleButton.impl(), CSSSelector::PseudoSingleButton); - nameToPseudoType->set(noButton.impl(), CSSSelector::PseudoNoButton); - nameToPseudoType->set(optional.impl(), CSSSelector::PseudoOptional); - nameToPseudoType->set(required.impl(), CSSSelector::PseudoRequired); - nameToPseudoType->set(resizer.impl(), CSSSelector::PseudoResizer); - nameToPseudoType->set(scope.impl(), CSSSelector::PseudoScope); - nameToPseudoType->set(scrollbar.impl(), CSSSelector::PseudoScrollbar); - nameToPseudoType->set(scrollbarButton.impl(), CSSSelector::PseudoScrollbarButton); - nameToPseudoType->set(scrollbarCorner.impl(), CSSSelector::PseudoScrollbarCorner); - nameToPseudoType->set(scrollbarThumb.impl(), CSSSelector::PseudoScrollbarThumb); - nameToPseudoType->set(scrollbarTrack.impl(), CSSSelector::PseudoScrollbarTrack); - nameToPseudoType->set(scrollbarTrackPiece.impl(), CSSSelector::PseudoScrollbarTrackPiece); - nameToPseudoType->set(cornerPresent.impl(), CSSSelector::PseudoCornerPresent); - nameToPseudoType->set(selection.impl(), CSSSelector::PseudoSelection); - nameToPseudoType->set(target.impl(), CSSSelector::PseudoTarget); - nameToPseudoType->set(visited.impl(), CSSSelector::PseudoVisited); - nameToPseudoType->set(firstPage.impl(), CSSSelector::PseudoFirstPage); - nameToPseudoType->set(leftPage.impl(), CSSSelector::PseudoLeftPage); - nameToPseudoType->set(rightPage.impl(), CSSSelector::PseudoRightPage); - nameToPseudoType->set(fullScreen.impl(), CSSSelector::PseudoFullScreen); - nameToPseudoType->set(fullScreenDocument.impl(), CSSSelector::PseudoFullScreenDocument); - nameToPseudoType->set(fullScreenAncestor.impl(), CSSSelector::PseudoFullScreenAncestor); - nameToPseudoType->set(cue.impl(), CSSSelector::PseudoCue); - nameToPseudoType->set(cueWithoutParen.impl(), CSSSelector::PseudoWebKitCustomElement); - nameToPseudoType->set(futureCue.impl(), CSSSelector::PseudoFutureCue); - nameToPseudoType->set(pastCue.impl(), CSSSelector::PseudoPastCue); - nameToPseudoType->set(seamlessDocument.impl(), CSSSelector::PseudoSeamlessDocument); - nameToPseudoType->set(distributed.impl(), CSSSelector::PseudoDistributed); - nameToPseudoType->set(inRange.impl(), CSSSelector::PseudoInRange); - nameToPseudoType->set(outOfRange.impl(), CSSSelector::PseudoOutOfRange); - if (RuntimeEnabledFeatures::shadowDOMEnabled()) { - nameToPseudoType->set(host.impl(), CSSSelector::PseudoHost); - nameToPseudoType->set(hostWithParams.impl(), CSSSelector::PseudoHost); - nameToPseudoType->set(content.impl(), CSSSelector::PseudoContent); - } - if (RuntimeEnabledFeatures::customElementsEnabled()) - nameToPseudoType->set(unresolved.impl(), CSSSelector::PseudoUnresolved); + if (name.isNull() || !name.is8Bit()) + return CSSSelector::PseudoUnknown; + + const NameToPseudoStruct* pseudoTypeMapEnd = pseudoTypeMap + WTF_ARRAY_LENGTH(pseudoTypeMap); + NameToPseudoStruct dummyKey = { 0, CSSSelector::PseudoUnknown }; + const NameToPseudoStruct* match = std::lower_bound(pseudoTypeMap, pseudoTypeMapEnd, dummyKey, NameToPseudoCompare(name)); + if (match == pseudoTypeMapEnd || match->string != name.string()) + return CSSSelector::PseudoUnknown; + + return static_cast<CSSSelector::PseudoType>(match->type); +} + +#ifndef NDEBUG +void CSSSelector::show(int indent) const +{ + printf("%*sselectorText(): %s\n", indent, "", selectorText().ascii().data()); + printf("%*sm_match: %d\n", indent, "", m_match); + printf("%*sisCustomPseudoElement(): %d\n", indent, "", isCustomPseudoElement()); + if (m_match != Tag) + printf("%*svalue(): %s\n", indent, "", value().ascii().data()); + printf("%*spseudoType(): %d\n", indent, "", pseudoType()); + if (m_match == Tag) + printf("%*stagQName().localName: %s\n", indent, "", tagQName().localName().ascii().data()); + printf("%*sisAttributeSelector(): %d\n", indent, "", isAttributeSelector()); + if (isAttributeSelector()) + printf("%*sattribute(): %s\n", indent, "", attribute().localName().ascii().data()); + printf("%*sargument(): %s\n", indent, "", argument().ascii().data()); + printf("%*sspecificity(): %u\n", indent, "", specificity()); + if (tagHistory()) { + printf("\n%*s--> (relation == %d)\n", indent, "", relation()); + tagHistory()->show(indent + 2); + } else { + printf("\n%*s--> (relation == %d)\n", indent, "", relation()); } - return nameToPseudoType; } -CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) +void CSSSelector::show() const { - if (name.isNull()) - return PseudoUnknown; - HashMap<StringImpl*, CSSSelector::PseudoType>* nameToPseudoType = nameToPseudoTypeMap(); - HashMap<StringImpl*, CSSSelector::PseudoType>::iterator slot = nameToPseudoType->find(name.impl()); + printf("\n******* CSSSelector::show(\"%s\") *******\n", selectorText().ascii().data()); + show(2); + printf("******* end *******\n"); +} +#endif - if (slot != nameToPseudoType->end()) - return slot->value; +CSSSelector::PseudoType CSSSelector::parsePseudoType(const AtomicString& name) +{ + CSSSelector::PseudoType pseudoType = nameToPseudoType(name); + if (pseudoType != PseudoUnknown) + return pseudoType; if (name.startsWith("-webkit-")) return PseudoWebKitCustomElement; - if (name.startsWith("x-") || name.startsWith("cue")) + if (name.startsWith("cue")) return PseudoUserAgentCustomElement; return PseudoUnknown; @@ -474,7 +453,6 @@ void CSSSelector::extractPseudoType() const case PseudoFirstLine: compat = true; case PseudoBackdrop: - case PseudoDistributed: case PseudoResizer: case PseudoScrollbar: case PseudoScrollbarCorner: @@ -486,6 +464,7 @@ void CSSSelector::extractPseudoType() const case PseudoUserAgentCustomElement: case PseudoWebKitCustomElement: case PseudoContent: + case PseudoShadow: element = true; break; case PseudoUnknown: @@ -543,12 +522,12 @@ void CSSSelector::extractPseudoType() const case PseudoFullScreen: case PseudoFullScreenDocument: case PseudoFullScreenAncestor: - case PseudoSeamlessDocument: case PseudoInRange: case PseudoOutOfRange: case PseudoFutureCue: case PseudoPastCue: case PseudoHost: + case PseudoHostContext: case PseudoUnresolved: break; case PseudoFirstPage: @@ -640,7 +619,7 @@ String CSSSelector::selectorText(const String& rightSide) const break; case PseudoAny: { const CSSSelector* firstSubSelector = cs->selectorList()->first(); - for (const CSSSelector* subSelector = firstSubSelector; subSelector; subSelector = CSSSelectorList::next(subSelector)) { + for (const CSSSelector* subSelector = firstSubSelector; subSelector; subSelector = CSSSelectorList::next(*subSelector)) { if (subSelector != firstSubSelector) str.append(','); str.append(subSelector->selectorText()); @@ -648,10 +627,11 @@ String CSSSelector::selectorText(const String& rightSide) const str.append(')'); break; } - case PseudoHost: { + case PseudoHost: + case PseudoHostContext: { if (cs->selectorList()) { const CSSSelector* firstSubSelector = cs->selectorList()->first(); - for (const CSSSelector* subSelector = firstSubSelector; subSelector; subSelector = CSSSelectorList::next(subSelector)) { + for (const CSSSelector* subSelector = firstSubSelector; subSelector; subSelector = CSSSelectorList::next(*subSelector)) { if (subSelector != firstSubSelector) str.append(','); str.append(subSelector->selectorText()); @@ -718,17 +698,11 @@ String CSSSelector::selectorText(const String& rightSide) const if (const CSSSelector* tagHistory = cs->tagHistory()) { switch (cs->relation()) { case CSSSelector::Descendant: - if (cs->relationIsAffectedByPseudoContent() && tagHistory->pseudoType() != CSSSelector::PseudoContent) - return tagHistory->selectorText("::-webkit-distributed(" + str.toString() + rightSide + ")"); return tagHistory->selectorText(" " + str.toString() + rightSide); case CSSSelector::Child: - if (cs->relationIsAffectedByPseudoContent() && tagHistory->pseudoType() != CSSSelector::PseudoContent) - return tagHistory->selectorText("::-webkit-distributed(> " + str.toString() + rightSide + ")"); return tagHistory->selectorText(" > " + str.toString() + rightSide); - case CSSSelector::ChildTree: - return tagHistory->selectorText(" ^ " + str.toString() + rightSide); - case CSSSelector::DescendantTree: - return tagHistory->selectorText(" ^^ " + str.toString() + rightSide); + case CSSSelector::ShadowDeep: + return tagHistory->selectorText(" /deep/ " + str.toString() + rightSide); case CSSSelector::DirectAdjacent: return tagHistory->selectorText(" + " + str.toString() + rightSide); case CSSSelector::IndirectAdjacent: @@ -762,7 +736,7 @@ void CSSSelector::setSelectorList(PassOwnPtr<CSSSelectorList> selectorList) static bool validateSubSelector(const CSSSelector* selector) { - switch (selector->m_match) { + switch (selector->match()) { case CSSSelector::Tag: case CSSSelector::Id: case CSSSelector::Class: @@ -775,6 +749,7 @@ static bool validateSubSelector(const CSSSelector* selector) case CSSSelector::End: return true; case CSSSelector::PseudoElement: + case CSSSelector::Unknown: return false; case CSSSelector::PagePseudoClass: case CSSSelector::PseudoClass: @@ -800,6 +775,8 @@ static bool validateSubSelector(const CSSSelector* selector) case CSSSelector::PseudoLastOfType: case CSSSelector::PseudoOnlyOfType: case CSSSelector::PseudoHost: + case CSSSelector::PseudoHostContext: + case CSSSelector::PseudoNot: return true; default: return false; @@ -843,8 +820,8 @@ bool CSSSelector::matchNth(int count) const return m_data.m_rareData->matchNth(count); } -CSSSelector::RareData::RareData(PassRefPtr<StringImpl> value) - : m_value(value.leakRef()) +CSSSelector::RareData::RareData(const AtomicString& value) + : m_value(value) , m_a(0) , m_b(0) , m_attribute(anyQName()) @@ -854,8 +831,6 @@ CSSSelector::RareData::RareData(PassRefPtr<StringImpl> value) CSSSelector::RareData::~RareData() { - if (m_value) - m_value->deref(); } // a helper function for parsing nth-arguments diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSelector.h b/chromium/third_party/WebKit/Source/core/css/CSSSelector.h index b0094687fb6..254ae9c5bb7 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSelector.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSSelector.h @@ -30,7 +30,57 @@ namespace WebCore { class CSSSelectorList; - // this class represents a selector for a StyleRule + // This class represents a selector for a StyleRule. + + // CSS selector representation is somewhat complicated and subtle. A representative list of selectors is + // in CSSSelectorTest; run it in a debug build to see useful debugging output. + // + // ** tagHistory() and relation(): + // + // Selectors are represented as a linked list of simple selectors (defined more or less according to + // http://www.w3.org/TR/css3-selectors/#simple-selectors-dfn). The tagHistory() method returns the next + // simple selector in the list. The relation() method returns the relationship of the current simple selector to + // the one in tagHistory(). For example, the CSS selector .a.b #c is represented as: + // + // selectorText(): .a.b #c + // --> (relation == Descendant) + // selectorText(): .a.b + // --> (relation == SubSelector) + // selectorText(): .b + // + // Note that currently a bare selector such as ".a" has a relation() of Descendant. This is a bug - instead the relation should be + // "None". + // + // The order of tagHistory() varies depending on the situation. + // * Relations using combinators (http://www.w3.org/TR/css3-selectors/#combinators), such as descendant, sibling, etc., are parsed + // right-to-left (in the example above, this is why .c is earlier in the tagHistory() chain than .a.b). + // * SubSelector relations are parsed left-to-right in most cases (such as the .a.b example above); a counter-example is the + // ::content pseudo-element. Most (all?) other pseudo elements and pseudo classes are parsed left-to-right. + // * ShadowPseudo relations are parsed right-to-left. Example: summary::-webkit-details-marker is parsed as: + // selectorText(): summary::-webkit-details-marker + // --> (relation == ShadowPseudo) + // selectorText(): summary + // + // ** match(): + // + // The match of the current simple selector tells us the type of selector, such as class, id, tagname, or pseudo-class. + // Inline comments in the Match enum give examples of when each type would occur. + // + // ** value(), attribute(): + // + // value() tells you the value of the simple selector. For example, for class selectors, value() will tell you the class string, + // and for id selectors it will tell you the id(). See below for the special case of attribute selectors. + // + // ** Attribute selectors. + // + // Attribute selectors return the attribute name in the attribute() method. The value() method returns the value matched against + // in case of selectors like [attr="value"]. + // + // ** isCustomPseudoElement(): + // + // It appears this is used only for pseudo elements that appear in user-agent shadow DOM. They are not exposed to author-created + // shadow DOM. + class CSSSelector { WTF_MAKE_FAST_ALLOCATED; public: @@ -50,36 +100,37 @@ namespace WebCore { // tag == -1 means apply to all elements (Selector = *) + // http://www.w3.org/TR/css3-selectors/#specificity + // We use 256 as the base of the specificity number system. unsigned specificity() const; /* how the attribute value has to match.... Default is Exact */ enum Match { Unknown = 0, - Tag, - Id, - Class, - Exact, - Set, - List, - Hyphen, - PseudoClass, - PseudoElement, + Tag, // Example: div + Id, // Example: #id + Class, // example: .class + PseudoClass, // Example: :nth-child(2) + PseudoElement, // Example: ::first-line + PagePseudoClass, // ?? + Exact, // Example: E[foo="bar"] + Set, // Example: E[foo] + Hyphen, // Example: E[foo|="bar"] + List, // Example: E[foo~="bar"] Contain, // css3: E[foo*="bar"] Begin, // css3: E[foo^="bar"] End, // css3: E[foo$="bar"] - PagePseudoClass + FirstAttributeSelectorMatch = Exact, }; enum Relation { - Descendant = 0, - Child, - DirectAdjacent, - IndirectAdjacent, - SubSelector, - ShadowPseudo, - // FIXME: rename ChildTree and DescendantTree when the spec for this is written down. - ChildTree, - DescendantTree + Descendant = 0, // "Space" combinator + Child, // > combinator + DirectAdjacent, // + combinator + IndirectAdjacent, // ~ combinator + SubSelector, // "No space" combinator + ShadowPseudo, // Special case of shadow DOM pseudo elements / shadow pseudo element + ShadowDeep // /deep/ combinator }; enum PseudoType { @@ -161,11 +212,11 @@ namespace WebCore { PseudoCue, PseudoFutureCue, PseudoPastCue, - PseudoSeamlessDocument, - PseudoDistributed, PseudoUnresolved, PseudoContent, - PseudoHost + PseudoHost, + PseudoHostContext, + PseudoShadow }; enum MarginBoxType { @@ -210,9 +261,15 @@ namespace WebCore { // how you use the returned QualifiedName. // http://www.w3.org/TR/css3-selectors/#attrnmsp const QualifiedName& attribute() const; + // Returns the argument of a parameterized selector. For example, nth-child(2) would have an argument of 2. const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; } const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : 0; } +#ifndef NDEBUG + void show() const; + void show(int indent) const; +#endif + void setValue(const AtomicString&); void setAttribute(const QualifiedName&); void setArgument(const AtomicString&); @@ -228,11 +285,25 @@ namespace WebCore { bool isDirectAdjacentSelector() const { return m_relation == DirectAdjacent; } bool isSiblingSelector() const; bool isAttributeSelector() const; - bool isDistributedPseudoElement() const; bool isContentPseudoElement() const; + bool isShadowPseudoElement() const; bool isHostPseudoClass() const; + // FIXME: selectors with no tagHistory() get a relation() of Descendant (and sometimes even SubSelector). It should instead be + // None. Relation relation() const { return static_cast<Relation>(m_relation); } + void setRelation(Relation relation) + { + m_relation = relation; + ASSERT(static_cast<Relation>(m_relation) == relation); // using a bitfield. + } + + Match match() const { return static_cast<Match>(m_match); } + void setMatch(Match match) + { + m_match = match; + ASSERT(static_cast<Match>(m_match) == match); // using a bitfield. + } bool isLastInSelectorList() const { return m_isLastInSelectorList; } void setLastInSelectorList() { m_isLastInSelectorList = true; } @@ -248,11 +319,10 @@ namespace WebCore { bool relationIsAffectedByPseudoContent() const { return m_relationIsAffectedByPseudoContent; } void setRelationIsAffectedByPseudoContent() { m_relationIsAffectedByPseudoContent = true; } + private: unsigned m_relation : 3; // enum Relation mutable unsigned m_match : 4; // enum Match mutable unsigned m_pseudoType : 8; // PseudoType - - private: mutable unsigned m_parsedNth : 1; // Used for :nth-* unsigned m_isLastInSelectorList : 1; unsigned m_isLastInTagHistory : 1; @@ -269,13 +339,13 @@ namespace WebCore { CSSSelector& operator=(const CSSSelector&); struct RareData : public RefCounted<RareData> { - static PassRefPtr<RareData> create(PassRefPtr<StringImpl> value) { return adoptRef(new RareData(value)); } + static PassRefPtr<RareData> create(const AtomicString& value) { return adoptRef(new RareData(value)); } ~RareData(); bool parseNth(); bool matchNth(int count); - StringImpl* m_value; // Plain pointer to keep things uniform with the union. + AtomicString m_value; int m_a; // Used for :nth-* int m_b; // Used for :nth-* QualifiedName m_attribute; // used for attribute selector @@ -283,7 +353,7 @@ namespace WebCore { OwnPtr<CSSSelectorList> m_selectorList; // Used for :-webkit-any and :not private: - RareData(PassRefPtr<StringImpl> value); + RareData(const AtomicString& value); }; void createRareData(); @@ -321,7 +391,7 @@ inline bool CSSSelector::isCustomPseudoElement() const inline bool CSSSelector::isHostPseudoClass() const { - return m_match == PseudoClass && m_pseudoType == PseudoHost; + return m_match == PseudoClass && (m_pseudoType == PseudoHost || m_pseudoType == PseudoHostContext); } inline bool CSSSelector::isSiblingSelector() const @@ -344,23 +414,17 @@ inline bool CSSSelector::isSiblingSelector() const inline bool CSSSelector::isAttributeSelector() const { - return m_match == CSSSelector::Exact - || m_match == CSSSelector::Set - || m_match == CSSSelector::List - || m_match == CSSSelector::Hyphen - || m_match == CSSSelector::Contain - || m_match == CSSSelector::Begin - || m_match == CSSSelector::End; + return m_match >= FirstAttributeSelectorMatch; } -inline bool CSSSelector::isDistributedPseudoElement() const +inline bool CSSSelector::isContentPseudoElement() const { - return m_match == PseudoElement && pseudoType() == PseudoDistributed; + return m_match == PseudoElement && pseudoType() == PseudoContent; } -inline bool CSSSelector::isContentPseudoElement() const +inline bool CSSSelector::isShadowPseudoElement() const { - return m_match == PseudoElement && pseudoType() == PseudoContent; + return m_match == PseudoElement && pseudoType() == PseudoShadow; } inline void CSSSelector::setValue(const AtomicString& value) @@ -369,10 +433,7 @@ inline void CSSSelector::setValue(const AtomicString& value) ASSERT(m_pseudoType == PseudoNotParsed); // Need to do ref counting manually for the union. if (m_hasRareData) { - if (m_data.m_rareData->m_value) - m_data.m_rareData->m_value->deref(); - m_data.m_rareData->m_value = value.impl(); - m_data.m_rareData->m_value->ref(); + m_data.m_rareData->m_value = value; return; } if (m_data.m_value) @@ -454,12 +515,13 @@ inline const QualifiedName& CSSSelector::tagQName() const inline const AtomicString& CSSSelector::value() const { ASSERT(m_match != Tag); + if (m_hasRareData) + return m_data.m_rareData->m_value; // AtomicString is really just a StringImpl* so the cast below is safe. // FIXME: Perhaps call sites could be changed to accept StringImpl? - return *reinterpret_cast<const AtomicString*>(m_hasRareData ? &m_data.m_rareData->m_value : &m_data.m_value); + return *reinterpret_cast<const AtomicString*>(&m_data.m_value); } - } // namespace WebCore #endif // CSSSelector_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.cpp b/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.cpp index a3b8bdc7c12..2710a0f2e42 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.cpp @@ -112,7 +112,7 @@ String CSSSelectorList::selectorsText() const { StringBuilder result; - for (const CSSSelector* s = first(); s; s = next(s)) { + for (const CSSSelector* s = first(); s; s = next(*s)) { if (s != first()) result.append(", "); result.append(s->selectorText()); @@ -122,20 +122,19 @@ String CSSSelectorList::selectorsText() const } template <typename Functor> -static bool forEachTagSelector(Functor& functor, const CSSSelector* selector) +static bool forEachTagSelector(Functor& functor, const CSSSelector& selector) { - ASSERT(selector); - + const CSSSelector* current = &selector; do { - if (functor(selector)) + if (functor(*current)) return true; - if (const CSSSelectorList* selectorList = selector->selectorList()) { - for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { - if (forEachTagSelector(functor, subSelector)) + if (const CSSSelectorList* selectorList = current->selectorList()) { + for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(*subSelector)) { + if (forEachTagSelector(functor, *subSelector)) return true; } } - } while ((selector = selector->tagHistory())); + } while ((current = current->tagHistory())); return false; } @@ -143,8 +142,8 @@ static bool forEachTagSelector(Functor& functor, const CSSSelector* selector) template <typename Functor> static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorList) { - for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) { - if (forEachTagSelector(functor, selector)) + for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) { + if (forEachTagSelector(functor, *selector)) return true; } @@ -153,11 +152,11 @@ static bool forEachSelector(Functor& functor, const CSSSelectorList* selectorLis class SelectorNeedsNamespaceResolutionFunctor { public: - bool operator()(const CSSSelector* selector) + bool operator()(const CSSSelector& selector) { - if (selector->m_match == CSSSelector::Tag && selector->tagQName().prefix() != nullAtom && selector->tagQName().prefix() != starAtom) + if (selector.match() == CSSSelector::Tag && selector.tagQName().prefix() != nullAtom && selector.tagQName().prefix() != starAtom) return true; - if (selector->isAttributeSelector() && selector->attribute().prefix() != nullAtom && selector->attribute().prefix() != starAtom) + if (selector.isAttributeSelector() && selector.attribute().prefix() != nullAtom && selector.attribute().prefix() != starAtom) return true; return false; } @@ -171,9 +170,9 @@ bool CSSSelectorList::selectorsNeedNamespaceResolution() class SelectorHasShadowDistributed { public: - bool operator()(const CSSSelector* selector) + bool operator()(const CSSSelector& selector) { - return selector->relationIsAffectedByPseudoContent(); + return selector.relationIsAffectedByPseudoContent(); } }; @@ -183,17 +182,17 @@ bool CSSSelectorList::hasShadowDistributedAt(size_t index) const return forEachTagSelector(functor, selectorAt(index)); } -class SelectorHasCombinatorCrossingTreeBoundary { +class SelectorCrossesTreeScopes { public: - bool operator()(const CSSSelector* selector) + bool operator()(const CSSSelector& selector) { - return selector->relation() == CSSSelector::ChildTree || selector->relation() == CSSSelector::DescendantTree; + return selector.relation() == CSSSelector::ShadowDeep || selector.isShadowPseudoElement(); } }; -bool CSSSelectorList::hasCombinatorCrossingTreeBoundaryAt(size_t index) const +bool CSSSelectorList::selectorCrossesTreeScopes(size_t index) const { - SelectorHasCombinatorCrossingTreeBoundary functor; + SelectorCrossesTreeScopes functor; return forEachTagSelector(functor, selectorAt(index)); } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.h b/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.h index 320de3b4175..e8932fec6fc 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSSelectorList.h @@ -45,23 +45,23 @@ public: bool isValid() const { return !!m_selectorArray; } const CSSSelector* first() const { return m_selectorArray; } - static const CSSSelector* next(const CSSSelector*); - bool hasOneSelector() const { return m_selectorArray && !next(m_selectorArray); } - const CSSSelector* selectorAt(size_t index) const { return &m_selectorArray[index]; } + static const CSSSelector* next(const CSSSelector&); + bool hasOneSelector() const { return m_selectorArray && !next(*m_selectorArray); } + const CSSSelector& selectorAt(size_t index) const { return m_selectorArray[index]; } size_t indexOfNextSelectorAfter(size_t index) const { - const CSSSelector* current = selectorAt(index); - current = next(current); - if (!current) + const CSSSelector& current = selectorAt(index); + const CSSSelector* next = this->next(current); + if (!next) return kNotFound; - return current - m_selectorArray; + return next - m_selectorArray; } bool selectorsNeedNamespaceResolution(); bool hasShadowDistributedAt(size_t index) const; - bool hasCombinatorCrossingTreeBoundaryAt(size_t index) const; + bool selectorCrossesTreeScopes(size_t index) const; String selectorsText() const; @@ -77,12 +77,13 @@ private: CSSSelector* m_selectorArray; }; -inline const CSSSelector* CSSSelectorList::next(const CSSSelector* current) +inline const CSSSelector* CSSSelectorList::next(const CSSSelector& current) { // Skip subparts of compound selectors. - while (!current->isLastInTagHistory()) - current++; - return current->isLastInSelectorList() ? 0 : current + 1; + const CSSSelector* last = ¤t; + while (!last->isLastInTagHistory()) + last++; + return last->isLastInSelectorList() ? 0 : last + 1; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSelectorTest.cpp b/chromium/third_party/WebKit/Source/core/css/CSSSelectorTest.cpp new file mode 100644 index 00000000000..baf04659d65 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/CSSSelectorTest.cpp @@ -0,0 +1,58 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/CSSTestHelper.h" +#include "core/css/RuleSet.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +TEST(CSSSelector, Representations) +{ + CSSTestHelper helper; + + const char* cssRules = + "summary::-webkit-details-marker { }" + "* {}" + "div {}" + "#id {}" + ".class {}" + "[attr] {}" + "div:hover {}" + "div:nth-child(2){}" + ".class#id { }" + "#id.class { }" + "[attr]#id { }" + "div[attr]#id { }" + "div::content { }" + "div::first-line { }" + ".a.b.c { }" + "div:not(.a) { }" // without class a + "div:not(:visited) { }" // without the visited pseudo class + + "[attr=\"value\"] { }" // Exact equality + "[attr~=\"value\"] { }" // One of a space-separated list + "[attr^=\"value\"] { }" // Begins with + "[attr$=\"value\"] { }" // Ends with + "[attr*=\"value\"] { }" // Substring equal to + "[attr|=\"value\"] { }" // One of a hyphen-separated list + + ".a .b { }" // .b is a descendant of .a + ".a > .b { }" // .b is a direct descendant of .a + ".a ~ .b { }" // .a precedes .b in sibling order + ".a + .b { }" // .a element immediately precedes .b in sibling order + ".a, .b { }" // matches .a or .b + + ".a.b .c {}"; + + helper.addCSSRules(cssRules); + EXPECT_EQ(30u, helper.ruleSet().ruleCount()); // .a, .b counts as two rules. +#ifndef NDEBUG + helper.ruleSet().show(); +#endif +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSShaderValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSShaderValue.cpp deleted file mode 100644 index 1fafe3008f1..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSShaderValue.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#include "core/css/CSSShaderValue.h" - -#include "FetchInitiatorTypeNames.h" -#include "core/css/CSSParser.h" -#include "core/dom/Document.h" -#include "core/fetch/FetchRequest.h" -#include "core/fetch/ResourceFetcher.h" -#include "core/rendering/style/StyleFetchedShader.h" -#include "core/rendering/style/StylePendingShader.h" -#include "wtf/text/StringBuilder.h" - -namespace WebCore { - -CSSShaderValue::CSSShaderValue(const String& url) - : CSSValue(CSSShaderClass) - , m_url(url) - , m_accessedShader(false) -{ -} - -CSSShaderValue::~CSSShaderValue() -{ -} - -KURL CSSShaderValue::completeURL(ResourceFetcher* loader) const -{ - return loader->document()->completeURL(m_url); -} - -StyleFetchedShader* CSSShaderValue::resource(ResourceFetcher* loader) -{ - ASSERT(loader); - - if (!m_accessedShader) { - m_accessedShader = true; - - FetchRequest request(ResourceRequest(completeURL(loader)), FetchInitiatorTypeNames::css); - if (ResourcePtr<ShaderResource> resource = loader->fetchShader(request)) - m_shader = StyleFetchedShader::create(resource.get()); - } - - return (m_shader && m_shader->isShaderResource()) ? static_cast<StyleFetchedShader*>(m_shader.get()) : 0; -} - -StyleShader* CSSShaderValue::cachedOrPendingShader() -{ - if (!m_shader) - m_shader = StylePendingShader::create(this); - - return m_shader.get(); -} - -String CSSShaderValue::customCSSText() const -{ - StringBuilder result; - result.appendLiteral("url("); - result.append(quoteCSSURLIfNeeded(m_url)); - result.append(')'); - if (!m_format.isEmpty()) { - result.appendLiteral(" format('"); - result.append(m_format); - result.appendLiteral("')"); - } - return result.toString(); -} - -bool CSSShaderValue::equals(const CSSShaderValue& other) const -{ - return m_url == other.m_url; -} - -} // namespace WebCore - diff --git a/chromium/third_party/WebKit/Source/core/css/CSSShaderValue.h b/chromium/third_party/WebKit/Source/core/css/CSSShaderValue.h deleted file mode 100644 index 9c736262402..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSShaderValue.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef CSSShaderValue_h -#define CSSShaderValue_h - -#include "core/css/CSSValue.h" - -namespace WebCore { - -class ResourceFetcher; -class KURL; -class StyleFetchedShader; -class StyleShader; - -class CSSShaderValue : public CSSValue { -public: - static PassRefPtr<CSSShaderValue> create(const String& url) { return adoptRef(new CSSShaderValue(url)); } - ~CSSShaderValue(); - - const String& format() const { return m_format; } - void setFormat(const String& format) { m_format = format; } - - KURL completeURL(ResourceFetcher*) const; - StyleFetchedShader* resource(ResourceFetcher*); - StyleShader* cachedOrPendingShader(); - - String customCSSText() const; - - bool equals(const CSSShaderValue&) const; - -private: - CSSShaderValue(const String& url); - - String m_url; - String m_format; - RefPtr<StyleShader> m_shader; - bool m_accessedShader; -}; - -DEFINE_CSS_VALUE_TYPE_CASTS(CSSShaderValue, isShaderValue()); - -} // namespace WebCore - - -#endif // CSSShaderValue_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.cpp index 35ecefb8cf9..4bdecf5ec10 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.cpp @@ -27,12 +27,12 @@ namespace WebCore { // Used for text-shadow and box-shadow -CSSShadowValue::CSSShadowValue(PassRefPtr<CSSPrimitiveValue> x, - PassRefPtr<CSSPrimitiveValue> y, - PassRefPtr<CSSPrimitiveValue> blur, - PassRefPtr<CSSPrimitiveValue> spread, - PassRefPtr<CSSPrimitiveValue> style, - PassRefPtr<CSSPrimitiveValue> color) +CSSShadowValue::CSSShadowValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> x, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> y, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> blur, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> spread, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> style, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> color) : CSSValue(ShadowClass) , x(x) , y(y) @@ -88,4 +88,15 @@ bool CSSShadowValue::equals(const CSSShadowValue& other) const && compareCSSValuePtr(style, other.style); } +void CSSShadowValue::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(x); + visitor->trace(y); + visitor->trace(blur); + visitor->trace(spread); + visitor->trace(style); + visitor->trace(color); + CSSValue::traceAfterDispatch(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.h b/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.h index 79fe736c6f5..ddd32ddab2c 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSShadowValue.h @@ -32,34 +32,36 @@ class CSSPrimitiveValue; // Used for text-shadow and box-shadow class CSSShadowValue : public CSSValue { public: - static PassRefPtr<CSSShadowValue> create(PassRefPtr<CSSPrimitiveValue> x, - PassRefPtr<CSSPrimitiveValue> y, - PassRefPtr<CSSPrimitiveValue> blur, - PassRefPtr<CSSPrimitiveValue> spread, - PassRefPtr<CSSPrimitiveValue> style, - PassRefPtr<CSSPrimitiveValue> color) + static PassRefPtrWillBeRawPtr<CSSShadowValue> create(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> x, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> y, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> blur, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> spread, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> style, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> color) { - return adoptRef(new CSSShadowValue(x, y, blur, spread, style, color)); + return adoptRefWillBeNoop(new CSSShadowValue(x, y, blur, spread, style, color)); } String customCSSText() const; bool equals(const CSSShadowValue&) const; - RefPtr<CSSPrimitiveValue> x; - RefPtr<CSSPrimitiveValue> y; - RefPtr<CSSPrimitiveValue> blur; - RefPtr<CSSPrimitiveValue> spread; - RefPtr<CSSPrimitiveValue> style; - RefPtr<CSSPrimitiveValue> color; + RefPtrWillBeMember<CSSPrimitiveValue> x; + RefPtrWillBeMember<CSSPrimitiveValue> y; + RefPtrWillBeMember<CSSPrimitiveValue> blur; + RefPtrWillBeMember<CSSPrimitiveValue> spread; + RefPtrWillBeMember<CSSPrimitiveValue> style; + RefPtrWillBeMember<CSSPrimitiveValue> color; + + void traceAfterDispatch(Visitor*); private: - CSSShadowValue(PassRefPtr<CSSPrimitiveValue> x, - PassRefPtr<CSSPrimitiveValue> y, - PassRefPtr<CSSPrimitiveValue> blur, - PassRefPtr<CSSPrimitiveValue> spread, - PassRefPtr<CSSPrimitiveValue> style, - PassRefPtr<CSSPrimitiveValue> color); + CSSShadowValue(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> x, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> y, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> blur, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> spread, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> style, + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> color); }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSShadowValue, isShadowValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSShorthands.in b/chromium/third_party/WebKit/Source/core/css/CSSShorthands.in index f66d64994df..9495b43504e 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSShorthands.in +++ b/chromium/third_party/WebKit/Source/core/css/CSSShorthands.in @@ -21,6 +21,8 @@ border-width longhands=border-top-width;border-right-width;border-bottom-width;b flex longhands=flex-grow;flex-shrink;flex-basis flex-flow longhands=flex-direction;flex-wrap font longhands=font-family;font-size;font-style;font-variant;font-weight;line-height +grid longhands=grid-template;grid-auto-flow;grid-auto-columns;grid-auto-rows +grid-template longhands=grid-template-columns;grid-template-rows;grid-template-areas grid-area longhands=grid-row-start;grid-column-start;grid-row-end;grid-column-end grid-column longhands=grid-column-start;grid-column-end grid-row longhands=grid-row-start;grid-row-end diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.cpp b/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.cpp deleted file mode 100644 index 1347f99c5c0..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/css/CSSStyleDeclaration.h" - - -namespace WebCore { - -PassRefPtr<CSSVariablesMap> CSSStyleDeclaration::var() -{ - if (!m_variablesMap) - m_variablesMap = CSSVariablesMap::create(this); - return m_variablesMap; -} - -CSSStyleDeclaration::~CSSStyleDeclaration() -{ - if (m_variablesMap) - m_variablesMap->clearStyleDeclaration(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h b/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h index 5c2445af31a..3aa549510f4 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.h @@ -21,10 +21,8 @@ #ifndef CSSStyleDeclaration_h #define CSSStyleDeclaration_h -#include "CSSPropertyNames.h" #include "bindings/v8/ScriptWrappable.h" -#include "core/css/CSSVariablesIterator.h" -#include "core/css/CSSVariablesMap.h" +#include "core/CSSPropertyNames.h" #include "wtf/Forward.h" #include "wtf/Noncopyable.h" @@ -36,22 +34,23 @@ class CSSStyleSheet; class CSSValue; class ExceptionState; class MutableStylePropertySet; -class VariablesIterator; -class CSSStyleDeclaration : public ScriptWrappable { - WTF_MAKE_NONCOPYABLE(CSSStyleDeclaration); WTF_MAKE_FAST_ALLOCATED; +class CSSStyleDeclaration : public NoBaseWillBeGarbageCollectedFinalized<CSSStyleDeclaration>, public ScriptWrappable { + WTF_MAKE_NONCOPYABLE(CSSStyleDeclaration); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - virtual ~CSSStyleDeclaration(); + virtual ~CSSStyleDeclaration() { } +#if !ENABLE(OILPAN) virtual void ref() = 0; virtual void deref() = 0; +#endif virtual CSSRule* parentRule() const = 0; virtual String cssText() const = 0; virtual void setCSSText(const String&, ExceptionState&) = 0; virtual unsigned length() const = 0; virtual String item(unsigned index) const = 0; - virtual PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName) = 0; + virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(const String& propertyName) = 0; virtual String getPropertyValue(const String& propertyName) = 0; virtual String getPropertyPriority(const String& propertyName) = 0; virtual String getPropertyShorthand(const String& propertyName) = 0; @@ -59,32 +58,25 @@ public: virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState&) = 0; virtual String removeProperty(const String& propertyName, ExceptionState&) = 0; - PassRefPtr<CSSVariablesMap> var(); - virtual unsigned variableCount() const = 0; - virtual String variableValue(const AtomicString& name) const = 0; - virtual bool setVariableValue(const AtomicString& name, const String& value, ExceptionState&) = 0; // Return value indicates whether variable was added. - virtual bool removeVariable(const AtomicString& name) = 0; - virtual bool clearVariables(ExceptionState&) = 0; - virtual PassRefPtr<CSSVariablesIterator> variablesIterator() const = 0; - // CSSPropertyID versions of the CSSOM functions to support bindings and editing. // Use the non-virtual methods in the concrete subclasses when possible. // The CSSValue returned by this function should not be exposed to the web as it may be used by multiple documents at the same time. - virtual PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) = 0; + virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) = 0; virtual String getPropertyValueInternal(CSSPropertyID) = 0; virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) = 0; - virtual PassRefPtr<MutableStylePropertySet> copyProperties() const = 0; + virtual PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyProperties() const = 0; virtual bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const = 0; virtual CSSStyleSheet* parentStyleSheet() const { return 0; } + virtual void trace(Visitor*) { } + protected: CSSStyleDeclaration() { ScriptWrappable::init(this); } - RefPtr<CSSVariablesMap> m_variablesMap; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl b/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl index f552573a8eb..1fc7e9c6abf 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleDeclaration.idl @@ -20,23 +20,27 @@ // Introduced in DOM Level 2: [ - DependentLifetime + DependentLifetime, + WillBeGarbageCollected ] interface CSSStyleDeclaration { [TreatReturnedNullStringAs=Null, TreatNullAs=NullString, RaisesException=Setter] attribute DOMString cssText; [TreatReturnedNullStringAs=Null] DOMString getPropertyValue([Default=Undefined] optional DOMString propertyName); - CSSValue getPropertyCSSValue([Default=Undefined] optional DOMString propertyName); [TreatReturnedNullStringAs=Null, RaisesException] DOMString removeProperty([Default=Undefined] optional DOMString propertyName); [TreatReturnedNullStringAs=Null] DOMString getPropertyPriority([Default=Undefined] optional DOMString propertyName); [RaisesException] void setProperty([Default=Undefined] optional DOMString propertyName, [TreatNullAs=NullString,Default=Undefined] optional DOMString value, - [Default=Undefined] optional DOMString priority); + [TreatNullAs=NullString] optional DOMString priority = null); readonly attribute unsigned long length; getter DOMString item([Default=Undefined] optional unsigned long index); - [Custom, CustomEnumerateProperty] getter (DOMString or float) (DOMString name); + [Custom=PropertyGetter|PropertyEnumerator|PropertyQuery] getter (DOMString or float) (DOMString name); [Custom] setter void (DOMString propertyName, [TreatNullAs=NullString] DOMString propertyValue); readonly attribute CSSRule parentRule; - [RuntimeEnabled=CSSVariables] readonly attribute CSSVariablesMap var; + + // Deprecated as of 2003: http://lists.w3.org/Archives/Public/www-style/2003Oct/0347.html + // FIXME: This should be DeprecateAs=, but currently too many LayoutTests use + // this function and would need CONSOLE: message rebaselines! + [MeasureAs=CSSStyleDeclarationGetPropertyCSSValue] CSSValue getPropertyCSSValue([Default=Undefined] optional DOMString propertyName); }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.cpp index 1ab4c5203a4..775583f6464 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "core/css/CSSStyleRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSSelector.h" #include "core/css/CSSStyleSheet.h" #include "core/css/PropertySetCSSStyleDeclaration.h" @@ -47,9 +47,10 @@ CSSStyleRule::CSSStyleRule(StyleRule* styleRule, CSSStyleSheet* parent) CSSStyleRule::~CSSStyleRule() { +#if !ENABLE(OILPAN) if (m_propertiesCSSOMWrapper) m_propertiesCSSOMWrapper->clearParentRule(); - +#endif if (hasCachedSelectorText()) { selectorTextCache().remove(this); setHasCachedSelectorText(false); @@ -67,7 +68,7 @@ CSSStyleDeclaration* CSSStyleRule::style() const String CSSStyleRule::generateSelectorText() const { StringBuilder builder; - for (const CSSSelector* selector = m_styleRule->selectorList().first(); selector; selector = CSSSelectorList::next(selector)) { + for (const CSSSelector* selector = m_styleRule->selectorList().first(); selector; selector = CSSSelectorList::next(*selector)) { if (selector != m_styleRule->selectorList().first()) builder.append(", "); builder.append(selector->selectorText()); @@ -91,7 +92,8 @@ String CSSStyleRule::selectorText() const void CSSStyleRule::setSelectorText(const String& selectorText) { - CSSParser p(parserContext()); + CSSParserContext context(parserContext(), 0); + BisonCSSParser p(context); CSSSelectorList selectorList; p.parseSelector(selectorText, selectorList); if (!selectorList.isValid()) @@ -112,7 +114,7 @@ String CSSStyleRule::cssText() const StringBuilder result; result.append(selectorText()); result.appendLiteral(" { "); - String decls = m_styleRule->properties()->asText(); + String decls = m_styleRule->properties().asText(); result.append(decls); if (!decls.isEmpty()) result.append(' '); @@ -128,4 +130,11 @@ void CSSStyleRule::reattach(StyleRuleBase* rule) m_propertiesCSSOMWrapper->reattach(m_styleRule->mutableProperties()); } +void CSSStyleRule::trace(Visitor* visitor) +{ + visitor->trace(m_styleRule); + visitor->trace(m_propertiesCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.h b/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.h index 12b4562f039..e1258bf5bc7 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleRule.h @@ -23,6 +23,7 @@ #define CSSStyleRule_h #include "core/css/CSSRule.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -30,13 +31,16 @@ class CSSStyleDeclaration; class StyleRuleCSSStyleDeclaration; class StyleRule; -class CSSStyleRule : public CSSRule { +class CSSStyleRule FINAL : public CSSRule { public: - static PassRefPtr<CSSStyleRule> create(StyleRule* rule, CSSStyleSheet* sheet) { return adoptRef(new CSSStyleRule(rule, sheet)); } + static PassRefPtrWillBeRawPtr<CSSStyleRule> create(StyleRule* rule, CSSStyleSheet* sheet) + { + return adoptRefWillBeNoop(new CSSStyleRule(rule, sheet)); + } virtual ~CSSStyleRule(); - virtual CSSRule::Type type() const { return STYLE_RULE; } + virtual CSSRule::Type type() const OVERRIDE { return STYLE_RULE; } virtual String cssText() const OVERRIDE; virtual void reattach(StyleRuleBase*) OVERRIDE; @@ -48,13 +52,15 @@ public: // FIXME: Not CSSOM. Remove. StyleRule* styleRule() const { return m_styleRule.get(); } + virtual void trace(Visitor*) OVERRIDE; + private: CSSStyleRule(StyleRule*, CSSStyleSheet*); String generateSelectorText() const; - RefPtr<StyleRule> m_styleRule; - mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; + RefPtrWillBeMember<StyleRule> m_styleRule; + mutable RefPtrWillBeMember<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSStyleRule, STYLE_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp b/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp index e7fe16ecd27..f3b536719c0 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.cpp @@ -21,14 +21,15 @@ #include "config.h" #include "core/css/CSSStyleSheet.h" -#include "HTMLNames.h" -#include "SVGNames.h" #include "bindings/v8/ExceptionState.h" +#include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8PerIsolateData.h" +#include "core/HTMLNames.h" +#include "core/SVGNames.h" #include "core/css/CSSCharsetRule.h" #include "core/css/CSSImportRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSRuleList.h" -#include "core/css/CSSStyleRule.h" #include "core/css/MediaList.h" #include "core/css/StyleRule.h" #include "core/css/StyleSheetContents.h" @@ -36,76 +37,103 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/Node.h" #include "core/frame/UseCounter.h" +#include "core/html/HTMLStyleElement.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/svg/SVGStyleElement.h" #include "platform/weborigin/SecurityOrigin.h" #include "wtf/text/StringBuilder.h" namespace WebCore { -class StyleSheetCSSRuleList : public CSSRuleList { +class StyleSheetCSSRuleList FINAL : public CSSRuleList { public: - StyleSheetCSSRuleList(CSSStyleSheet* sheet) : m_styleSheet(sheet) { } + static PassOwnPtrWillBeRawPtr<StyleSheetCSSRuleList> create(CSSStyleSheet* sheet) + { + return adoptPtrWillBeNoop(new StyleSheetCSSRuleList(sheet)); + } + + virtual void trace(Visitor* visitor) OVERRIDE + { + visitor->trace(m_styleSheet); + CSSRuleList::trace(visitor); + } private: - virtual void ref() { m_styleSheet->ref(); } - virtual void deref() { m_styleSheet->deref(); } + StyleSheetCSSRuleList(CSSStyleSheet* sheet) : m_styleSheet(sheet) { } - virtual unsigned length() const { return m_styleSheet->length(); } - virtual CSSRule* item(unsigned index) const { return m_styleSheet->item(index); } +#if !ENABLE(OILPAN) + virtual void ref() OVERRIDE { m_styleSheet->ref(); } + virtual void deref() OVERRIDE { m_styleSheet->deref(); } +#endif - virtual CSSStyleSheet* styleSheet() const { return m_styleSheet; } + virtual unsigned length() const OVERRIDE { return m_styleSheet->length(); } + virtual CSSRule* item(unsigned index) const OVERRIDE { return m_styleSheet->item(index); } - CSSStyleSheet* m_styleSheet; + virtual CSSStyleSheet* styleSheet() const OVERRIDE { return m_styleSheet; } + + RawPtrWillBeMember<CSSStyleSheet> m_styleSheet; }; -#if !ASSERT_DISABLED +#if ASSERT_ENABLED static bool isAcceptableCSSStyleSheetParent(Node* parentNode) { - // Only these nodes can be parents of StyleSheets, and they need to call clearOwnerNode() when moved out of document. + // Only these nodes can be parents of StyleSheets, and they need to call + // clearOwnerNode() when moved out of document. + // Destruction of the style sheet counts as being "moved out of the + // document", but only in the non-oilpan version of blink. I.e. don't call + // clearOwnerNode() in the owner's destructor in oilpan. return !parentNode || parentNode->isDocumentNode() - || parentNode->hasTagName(HTMLNames::linkTag) - || parentNode->hasTagName(HTMLNames::styleTag) - || parentNode->hasTagName(SVGNames::styleTag) + || isHTMLLinkElement(*parentNode) + || isHTMLStyleElement(*parentNode) + || isSVGStyleElement(*parentNode) || parentNode->nodeType() == Node::PROCESSING_INSTRUCTION_NODE; } #endif -PassRefPtr<CSSStyleSheet> CSSStyleSheet::create(PassRefPtr<StyleSheetContents> sheet, CSSImportRule* ownerRule) +PassRefPtrWillBeRawPtr<CSSStyleSheet> CSSStyleSheet::create(PassRefPtrWillBeRawPtr<StyleSheetContents> sheet, CSSImportRule* ownerRule) { - return adoptRef(new CSSStyleSheet(sheet, ownerRule)); + return adoptRefWillBeNoop(new CSSStyleSheet(sheet, ownerRule)); } -PassRefPtr<CSSStyleSheet> CSSStyleSheet::create(PassRefPtr<StyleSheetContents> sheet, Node* ownerNode) +PassRefPtrWillBeRawPtr<CSSStyleSheet> CSSStyleSheet::create(PassRefPtrWillBeRawPtr<StyleSheetContents> sheet, Node* ownerNode) { - return adoptRef(new CSSStyleSheet(sheet, ownerNode, false, TextPosition::minimumPosition())); + return adoptRefWillBeNoop(new CSSStyleSheet(sheet, ownerNode, false, TextPosition::minimumPosition())); } -PassRefPtr<CSSStyleSheet> CSSStyleSheet::createInline(Node* ownerNode, const KURL& baseURL, const TextPosition& startPosition, const String& encoding) +PassRefPtrWillBeRawPtr<CSSStyleSheet> CSSStyleSheet::createInline(PassRefPtrWillBeRawPtr<StyleSheetContents> sheet, Node* ownerNode, const TextPosition& startPosition) { - CSSParserContext parserContext(ownerNode->document(), baseURL, encoding); - RefPtr<StyleSheetContents> sheet = StyleSheetContents::create(baseURL.string(), parserContext); - return adoptRef(new CSSStyleSheet(sheet.release(), ownerNode, true, startPosition)); + ASSERT(sheet); + return adoptRefWillBeNoop(new CSSStyleSheet(sheet, ownerNode, true, startPosition)); } -CSSStyleSheet::CSSStyleSheet(PassRefPtr<StyleSheetContents> contents, CSSImportRule* ownerRule) +PassRefPtrWillBeRawPtr<CSSStyleSheet> CSSStyleSheet::createInline(Node* ownerNode, const KURL& baseURL, const TextPosition& startPosition, const String& encoding) +{ + CSSParserContext parserContext(ownerNode->document(), 0, baseURL, encoding); + RefPtrWillBeRawPtr<StyleSheetContents> sheet = StyleSheetContents::create(baseURL.string(), parserContext); + return adoptRefWillBeNoop(new CSSStyleSheet(sheet.release(), ownerNode, true, startPosition)); +} + +CSSStyleSheet::CSSStyleSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> contents, CSSImportRule* ownerRule) : m_contents(contents) , m_isInlineStylesheet(false) , m_isDisabled(false) - , m_ownerNode(0) + , m_ownerNode(nullptr) , m_ownerRule(ownerRule) , m_startPosition(TextPosition::minimumPosition()) + , m_loadCompleted(false) { m_contents->registerClient(this); } -CSSStyleSheet::CSSStyleSheet(PassRefPtr<StyleSheetContents> contents, Node* ownerNode, bool isInlineStylesheet, const TextPosition& startPosition) +CSSStyleSheet::CSSStyleSheet(PassRefPtrWillBeRawPtr<StyleSheetContents> contents, Node* ownerNode, bool isInlineStylesheet, const TextPosition& startPosition) : m_contents(contents) , m_isInlineStylesheet(isInlineStylesheet) , m_isDisabled(false) , m_ownerNode(ownerNode) - , m_ownerRule(0) + , m_ownerRule(nullptr) , m_startPosition(startPosition) + , m_loadCompleted(false) { ASSERT(isAcceptableCSSStyleSheetParent(ownerNode)); m_contents->registerClient(this); @@ -113,6 +141,11 @@ CSSStyleSheet::CSSStyleSheet(PassRefPtr<StyleSheetContents> contents, Node* owne CSSStyleSheet::~CSSStyleSheet() { + // With oilpan the parent style sheet pointer is strong and the sheet and + // its RuleCSSOMWrappers die together and we don't need to clear them here. + // Also with oilpan the StyleSheetContents client pointers are weak and + // therefore do not need to be cleared here. +#if !ENABLE(OILPAN) // For style rules outside the document, .parentStyleSheet can become null even if the style rule // is still observable from JavaScript. This matches the behavior of .parentNode for nodes, but // it's not ideal because it makes the CSSOM's behavior depend on the timing of garbage collection. @@ -121,53 +154,28 @@ CSSStyleSheet::~CSSStyleSheet() m_childRuleCSSOMWrappers[i]->setParentStyleSheet(0); } - for (unsigned i = 0; i < m_extraChildRuleCSSOMWrappers.size(); ++i) - m_extraChildRuleCSSOMWrappers[i]->setParentStyleSheet(0); - if (m_mediaCSSOMWrapper) m_mediaCSSOMWrapper->clearParentStyleSheet(); m_contents->unregisterClient(this); -} - -void CSSStyleSheet::extraCSSOMWrapperIndices(Vector<unsigned>& indices) -{ - indices.grow(m_extraChildRuleCSSOMWrappers.size()); - - for (unsigned i = 0; i < m_extraChildRuleCSSOMWrappers.size(); ++i) { - CSSRule* cssRule = m_extraChildRuleCSSOMWrappers[i].get(); - ASSERT(cssRule->type() == CSSRule::STYLE_RULE); - StyleRule* styleRule = toCSSStyleRule(cssRule)->styleRule(); - - bool didFindIndex = false; - for (unsigned j = 0; j < m_contents->ruleCount(); ++j) { - if (m_contents->ruleAt(j) == styleRule) { - didFindIndex = true; - indices[i] = j; - break; - } - } - ASSERT(didFindIndex); - if (!didFindIndex) - indices[i] = 0; - } +#endif } void CSSStyleSheet::willMutateRules() { InspectorInstrumentation::willMutateRules(this); + // If we are the only client it is safe to mutate. - if (m_contents->hasOneClient() && !m_contents->isInMemoryCache()) { + if (m_contents->clientSize() <= 1 && !m_contents->isInMemoryCache()) { m_contents->clearRuleSet(); + if (Document* document = ownerDocument()) + m_contents->removeSheetFromCache(document); m_contents->setMutable(); return; } // Only cacheable stylesheets should have multiple clients. ASSERT(m_contents->isCacheable()); - Vector<unsigned> indices; - extraCSSOMWrapperIndices(indices); - // Copy-on-write. m_contents->unregisterClient(this); m_contents = m_contents->copy(); @@ -176,13 +184,13 @@ void CSSStyleSheet::willMutateRules() m_contents->setMutable(); // Any existing CSSOM wrappers need to be connected to the copied child rules. - reattachChildRuleCSSOMWrappers(indices); + reattachChildRuleCSSOMWrappers(); } void CSSStyleSheet::didMutateRules() { ASSERT(m_contents->isMutable()); - ASSERT(m_contents->hasOneClient()); + ASSERT(m_contents->clientSize() <= 1); InspectorInstrumentation::didMutateRules(this); didMutate(PartialRuleUpdate); @@ -197,20 +205,11 @@ void CSSStyleSheet::didMutate(StyleSheetUpdateType updateType) // Need FullStyleUpdate when insertRule or deleteRule, // because StyleSheetCollection::analyzeStyleSheetChange cannot detect partial rule update. StyleResolverUpdateMode updateMode = updateType != PartialRuleUpdate ? AnalyzedStyleUpdate : FullStyleUpdate; - owner->modifiedStyleSheet(this, RecalcStyleDeferred, updateMode); -} - -void CSSStyleSheet::registerExtraChildRuleCSSOMWrapper(PassRefPtr<CSSRule> rule) -{ - m_extraChildRuleCSSOMWrappers.append(rule); + owner->modifiedStyleSheet(this, updateMode); } -void CSSStyleSheet::reattachChildRuleCSSOMWrappers(const Vector<unsigned>& extraCSSOMWrapperIndices) +void CSSStyleSheet::reattachChildRuleCSSOMWrappers() { - ASSERT(extraCSSOMWrapperIndices.size() == m_extraChildRuleCSSOMWrappers.size()); - for (unsigned i = 0; i < extraCSSOMWrapperIndices.size(); ++i) - m_extraChildRuleCSSOMWrappers[i]->reattach(m_contents->ruleAt(extraCSSOMWrapperIndices[i])); - for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { if (!m_childRuleCSSOMWrappers[i]) continue; @@ -227,7 +226,7 @@ void CSSStyleSheet::setDisabled(bool disabled) didMutate(); } -void CSSStyleSheet::setMediaQueries(PassRefPtr<MediaQuerySet> mediaQueries) +void CSSStyleSheet::setMediaQueries(PassRefPtrWillBeRawPtr<MediaQuerySet> mediaQueries) { m_mediaQueries = mediaQueries; if (m_mediaCSSOMWrapper && m_mediaQueries) @@ -252,7 +251,7 @@ CSSRule* CSSStyleSheet::item(unsigned index) m_childRuleCSSOMWrappers.grow(ruleCount); ASSERT(m_childRuleCSSOMWrappers.size() == ruleCount); - RefPtr<CSSRule>& cssRule = m_childRuleCSSOMWrappers[index]; + RefPtrWillBeMember<CSSRule>& cssRule = m_childRuleCSSOMWrappers[index]; if (!cssRule) { if (index == 0 && m_contents->hasCharsetRule()) { ASSERT(!m_contents->ruleAt(0)); @@ -263,6 +262,14 @@ CSSRule* CSSStyleSheet::item(unsigned index) return cssRule.get(); } +void CSSStyleSheet::clearOwnerNode() +{ + didMutate(EntireStyleSheetUpdate); + if (m_ownerNode) + m_contents->unregisterClient(this); + m_ownerNode = nullptr; +} + bool CSSStyleSheet::canAccessRules() const { if (m_isInlineStylesheet) @@ -278,12 +285,12 @@ bool CSSStyleSheet::canAccessRules() const return false; } -PassRefPtr<CSSRuleList> CSSStyleSheet::rules() +PassRefPtrWillBeRawPtr<CSSRuleList> CSSStyleSheet::rules() { if (!canAccessRules()) - return 0; + return nullptr; // IE behavior. - RefPtr<StaticCSSRuleList> nonCharsetRules = StaticCSSRuleList::create(); + RefPtrWillBeRawPtr<StaticCSSRuleList> nonCharsetRules(StaticCSSRuleList::create()); unsigned ruleCount = length(); for (unsigned i = 0; i < ruleCount; ++i) { CSSRule* rule = item(i); @@ -299,32 +306,33 @@ unsigned CSSStyleSheet::insertRule(const String& ruleString, unsigned index, Exc ASSERT(m_childRuleCSSOMWrappers.isEmpty() || m_childRuleCSSOMWrappers.size() == m_contents->ruleCount()); if (index > length()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is larger than the maximum index (" + String::number(length()) + ")."); return 0; } - CSSParser p(m_contents->parserContext(), UseCounter::getFrom(this)); - RefPtr<StyleRuleBase> rule = p.parseRule(m_contents.get(), ruleString); + CSSParserContext context(m_contents->parserContext(), UseCounter::getFrom(this)); + BisonCSSParser p(context); + RefPtrWillBeRawPtr<StyleRuleBase> rule = p.parseRule(m_contents.get(), ruleString); if (!rule) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Failed to parse the rule '" + ruleString + "'."); return 0; } RuleMutationScope mutationScope(this); bool success = m_contents->wrapperInsertRule(rule, index); if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(HierarchyRequestError); + exceptionState.throwDOMException(HierarchyRequestError, "Failed to insert the rule."); return 0; } if (!m_childRuleCSSOMWrappers.isEmpty()) - m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>()); + m_childRuleCSSOMWrappers.insert(index, RefPtrWillBeMember<CSSRule>(nullptr)); return index; } unsigned CSSStyleSheet::insertRule(const String& rule, ExceptionState& exceptionState) { - UseCounter::countDeprecation(activeExecutionContext(), UseCounter::CSSStyleSheetInsertRuleOptionalArg); + UseCounter::countDeprecation(callingExecutionContext(V8PerIsolateData::mainThreadIsolate()), UseCounter::CSSStyleSheetInsertRuleOptionalArg); return insertRule(rule, 0, exceptionState); } @@ -333,7 +341,7 @@ void CSSStyleSheet::deleteRule(unsigned index, ExceptionState& exceptionState) ASSERT(m_childRuleCSSOMWrappers.isEmpty() || m_childRuleCSSOMWrappers.size() == m_contents->ruleCount()); if (index >= length()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is larger than the maximum index (" + String::number(length() - 1) + ")."); return; } RuleMutationScope mutationScope(this); @@ -368,12 +376,12 @@ int CSSStyleSheet::addRule(const String& selector, const String& style, Exceptio } -PassRefPtr<CSSRuleList> CSSStyleSheet::cssRules() +PassRefPtrWillBeRawPtr<CSSRuleList> CSSStyleSheet::cssRules() { if (!canAccessRules()) - return 0; + return nullptr; if (!m_ruleListCSSOMWrapper) - m_ruleListCSSOMWrapper = adoptPtr(new StyleSheetCSSRuleList(this)); + m_ruleListCSSOMWrapper = StyleSheetCSSRuleList::create(this); return m_ruleListCSSOMWrapper.get(); } @@ -420,4 +428,42 @@ void CSSStyleSheet::clearChildRuleCSSOMWrappers() m_childRuleCSSOMWrappers.clear(); } +bool CSSStyleSheet::sheetLoaded() +{ + ASSERT(m_ownerNode); + setLoadCompleted(m_ownerNode->sheetLoaded()); + return m_loadCompleted; +} + +void CSSStyleSheet::startLoadingDynamicSheet() +{ + setLoadCompleted(false); + m_ownerNode->startLoadingDynamicSheet(); +} + +void CSSStyleSheet::setLoadCompleted(bool completed) +{ + if (completed == m_loadCompleted) + return; + + m_loadCompleted = completed; + + if (completed) + m_contents->clientLoadCompleted(this); + else + m_contents->clientLoadStarted(this); +} + +void CSSStyleSheet::trace(Visitor* visitor) +{ + visitor->trace(m_contents); + visitor->trace(m_mediaQueries); + visitor->trace(m_ownerNode); + visitor->trace(m_ownerRule); + visitor->trace(m_mediaCSSOMWrapper); + visitor->trace(m_childRuleCSSOMWrappers); + visitor->trace(m_ruleListCSSOMWrapper); + StyleSheet::trace(visitor); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.h b/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.h index 3c02c230c9f..18d68d5716c 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.h @@ -23,6 +23,7 @@ #include "core/css/CSSRule.h" #include "core/css/StyleSheet.h" +#include "platform/heap/Handle.h" #include "wtf/Noncopyable.h" #include "wtf/text/TextPosition.h" @@ -30,7 +31,7 @@ namespace WebCore { class CSSCharsetRule; class CSSImportRule; -class CSSParser; +class BisonCSSParser; class CSSRule; class CSSRuleList; class CSSStyleSheet; @@ -46,11 +47,12 @@ enum StyleSheetUpdateType { EntireStyleSheetUpdate }; -class CSSStyleSheet : public StyleSheet { +class CSSStyleSheet FINAL : public StyleSheet { public: - static PassRefPtr<CSSStyleSheet> create(PassRefPtr<StyleSheetContents>, CSSImportRule* ownerRule = 0); - static PassRefPtr<CSSStyleSheet> create(PassRefPtr<StyleSheetContents>, Node* ownerNode); - static PassRefPtr<CSSStyleSheet> createInline(Node*, const KURL&, const TextPosition& startPosition = TextPosition::minimumPosition(), const String& encoding = String()); + static PassRefPtrWillBeRawPtr<CSSStyleSheet> create(PassRefPtrWillBeRawPtr<StyleSheetContents>, CSSImportRule* ownerRule = 0); + static PassRefPtrWillBeRawPtr<CSSStyleSheet> create(PassRefPtrWillBeRawPtr<StyleSheetContents>, Node* ownerNode); + static PassRefPtrWillBeRawPtr<CSSStyleSheet> createInline(Node*, const KURL&, const TextPosition& startPosition = TextPosition::minimumPosition(), const String& encoding = String()); + static PassRefPtrWillBeRawPtr<CSSStyleSheet> createInline(PassRefPtrWillBeRawPtr<StyleSheetContents>, Node* ownerNode, const TextPosition& startPosition = TextPosition::minimumPosition()); virtual ~CSSStyleSheet(); @@ -62,13 +64,13 @@ public: virtual bool disabled() const OVERRIDE { return m_isDisabled; } virtual void setDisabled(bool) OVERRIDE; - PassRefPtr<CSSRuleList> cssRules(); + PassRefPtrWillBeRawPtr<CSSRuleList> cssRules(); unsigned insertRule(const String& rule, unsigned index, ExceptionState&); unsigned insertRule(const String& rule, ExceptionState&); // Deprecated. void deleteRule(unsigned index, ExceptionState&); // IE Extensions - PassRefPtr<CSSRuleList> rules(); + PassRefPtrWillBeRawPtr<CSSRuleList> rules(); int addRule(const String& selector, const String& style, int index, ExceptionState&); int addRule(const String& selector, const String& style, ExceptionState&); void removeRule(unsigned index, ExceptionState& exceptionState) { deleteRule(index, exceptionState); } @@ -77,26 +79,28 @@ public: unsigned length() const; CSSRule* item(unsigned index); - virtual void clearOwnerNode() OVERRIDE { didMutate(EntireStyleSheetUpdate); m_ownerNode = 0; } + virtual void clearOwnerNode() OVERRIDE; + virtual CSSRule* ownerRule() const OVERRIDE { return m_ownerRule; } virtual KURL baseURL() const OVERRIDE; virtual bool isLoading() const OVERRIDE; - void clearOwnerRule() { m_ownerRule = 0; } + void clearOwnerRule() { m_ownerRule = nullptr; } Document* ownerDocument() const; MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); } - void setMediaQueries(PassRefPtr<MediaQuerySet>); + void setMediaQueries(PassRefPtrWillBeRawPtr<MediaQuerySet>); void setTitle(const String& title) { m_title = title; } class RuleMutationScope { WTF_MAKE_NONCOPYABLE(RuleMutationScope); + STACK_ALLOCATED(); public: - RuleMutationScope(CSSStyleSheet*); - RuleMutationScope(CSSRule*); + explicit RuleMutationScope(CSSStyleSheet*); + explicit RuleMutationScope(CSSRule*); ~RuleMutationScope(); private: - CSSStyleSheet* m_styleSheet; + RawPtrWillBeMember<CSSStyleSheet> m_styleSheet; }; void willMutateRules(); @@ -105,42 +109,44 @@ public: void clearChildRuleCSSOMWrappers(); - void registerExtraChildRuleCSSOMWrapper(PassRefPtr<CSSRule>); - StyleSheetContents* contents() const { return m_contents.get(); } bool isInline() const { return m_isInlineStylesheet; } TextPosition startPositionInSource() const { return m_startPosition; } + bool sheetLoaded(); + bool loadCompleted() const { return m_loadCompleted; } + void startLoadingDynamicSheet(); + + virtual void trace(Visitor*) OVERRIDE; + private: - CSSStyleSheet(PassRefPtr<StyleSheetContents>, CSSImportRule* ownerRule); - CSSStyleSheet(PassRefPtr<StyleSheetContents>, Node* ownerNode, bool isInlineStylesheet, const TextPosition& startPosition); + CSSStyleSheet(PassRefPtrWillBeRawPtr<StyleSheetContents>, CSSImportRule* ownerRule); + CSSStyleSheet(PassRefPtrWillBeRawPtr<StyleSheetContents>, Node* ownerNode, bool isInlineStylesheet, const TextPosition& startPosition); - virtual bool isCSSStyleSheet() const { return true; } - virtual String type() const { return "text/css"; } + virtual bool isCSSStyleSheet() const OVERRIDE { return true; } + virtual String type() const OVERRIDE { return "text/css"; } - void extraCSSOMWrapperIndices(Vector<unsigned>& indices); - void reattachChildRuleCSSOMWrappers(const Vector<unsigned>& extraCSSOMWrapperIndices); + void reattachChildRuleCSSOMWrappers(); bool canAccessRules() const; - RefPtr<StyleSheetContents> m_contents; + void setLoadCompleted(bool); + + RefPtrWillBeMember<StyleSheetContents> m_contents; bool m_isInlineStylesheet; bool m_isDisabled; String m_title; - RefPtr<MediaQuerySet> m_mediaQueries; + RefPtrWillBeMember<MediaQuerySet> m_mediaQueries; - Node* m_ownerNode; - CSSRule* m_ownerRule; + RawPtrWillBeMember<Node> m_ownerNode; + RawPtrWillBeMember<CSSRule> m_ownerRule; TextPosition m_startPosition; - - mutable RefPtr<MediaList> m_mediaCSSOMWrapper; - mutable Vector<RefPtr<CSSRule> > m_childRuleCSSOMWrappers; - // These are CSSOMWrappers that come from getMatchedCSSRules and thus don't map 1-1 to - // the StyleRules in the StyleSheetContents. - mutable Vector<RefPtr<CSSRule> > m_extraChildRuleCSSOMWrappers; - mutable OwnPtr<CSSRuleList> m_ruleListCSSOMWrapper; + bool m_loadCompleted; + mutable RefPtrWillBeMember<MediaList> m_mediaCSSOMWrapper; + mutable WillBeHeapVector<RefPtrWillBeMember<CSSRule> > m_childRuleCSSOMWrappers; + mutable OwnPtrWillBeMember<CSSRuleList> m_ruleListCSSOMWrapper; }; inline CSSStyleSheet::RuleMutationScope::RuleMutationScope(CSSStyleSheet* sheet) diff --git a/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.idl b/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.idl index a9b09007967..71619f33e45 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSStyleSheet.idl @@ -20,7 +20,7 @@ // Introduced in DOM Level 2: [ - GenerateVisitDOMWrapper=ownerNode, + SetWrapperReferenceFrom=ownerNode, ] interface CSSStyleSheet : StyleSheet { readonly attribute CSSRule ownerRule; readonly attribute CSSRuleList cssRules; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSupportsRule.h b/chromium/third_party/WebKit/Source/core/css/CSSSupportsRule.h index 4d15dd2523f..75f467553cd 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSupportsRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSSupportsRule.h @@ -36,11 +36,11 @@ namespace WebCore { class CSSRule; class StyleRuleSupports; -class CSSSupportsRule : public CSSGroupingRule { +class CSSSupportsRule FINAL : public CSSGroupingRule { public: - static PassRefPtr<CSSSupportsRule> create(StyleRuleSupports* rule, CSSStyleSheet* sheet) + static PassRefPtrWillBeRawPtr<CSSSupportsRule> create(StyleRuleSupports* rule, CSSStyleSheet* sheet) { - return adoptRef(new CSSSupportsRule(rule, sheet)); + return adoptRefWillBeNoop(new CSSSupportsRule(rule, sheet)); } virtual ~CSSSupportsRule() { } @@ -50,6 +50,8 @@ public: String conditionText() const; + virtual void trace(Visitor* visitor) OVERRIDE { CSSGroupingRule::trace(visitor); } + private: CSSSupportsRule(StyleRuleSupports*, CSSStyleSheet*); }; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTestHelper.cpp b/chromium/third_party/WebKit/Source/core/css/CSSTestHelper.cpp new file mode 100644 index 00000000000..4edca948153 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/CSSTestHelper.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, 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. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 HOLDER 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. + */ + +#include "config.h" +#include "core/css/CSSTestHelper.h" + +#include "core/css/CSSRuleList.h" +#include "core/css/CSSStyleSheet.h" +#include "core/css/RuleSet.h" +#include "core/css/StyleSheetContents.h" +#include "core/dom/Document.h" +#include "wtf/text/WTFString.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +CSSTestHelper::~CSSTestHelper() +{ +} + +CSSTestHelper::CSSTestHelper() +{ + m_document = Document::create(); + TextPosition position; + m_styleSheet = CSSStyleSheet::createInline(m_document.get(), KURL(), position, "UTF-8"); +} + +RuleSet& CSSTestHelper::ruleSet() +{ + RuleSet& ruleSet = m_styleSheet->contents()->ensureRuleSet(MediaQueryEvaluator(), RuleHasNoSpecialState); + ruleSet.compactRulesIfNeeded(); + return ruleSet; +} + +void CSSTestHelper::addCSSRules(const char* cssText) +{ + TextPosition position; + unsigned sheetLength = m_styleSheet->length(); + ASSERT_TRUE(m_styleSheet->contents()->parseStringAtPosition(cssText, position, true)); + ASSERT_TRUE(m_styleSheet->length() > sheetLength); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTestHelper.h b/chromium/third_party/WebKit/Source/core/css/CSSTestHelper.h new file mode 100644 index 00000000000..f217b77afbf --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/CSSTestHelper.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, 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. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 HOLDER 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. + */ + +#ifndef CSSTestHelper_h +#define CSSTestHelper_h + +#include "core/css/RuleSet.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +class Document; +class CSSStyleSheet; + +// A helper class for writing tests of CSS rules. Example usage: +// +// CSSTestHelper helper; +// helper.addCSSRule("body { color: red} #a { position: absolute }"); +// RuleSet& ruleSet = helper.ruleSet(); +// ... examine RuleSet to find the rule and test properties on it. + +class CSSTestHelper { +public: + CSSTestHelper(); + ~CSSTestHelper(); + + void addCSSRules(const char* ruleText); + RuleSet& ruleSet(); + +private: + RefPtrWillBePersistent<Document> m_document; + RefPtrWillBePersistent<CSSStyleSheet> m_styleSheet; +}; + +} // namespace WebCore + +#endif // CSSTestHelper_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.cpp index 49420cbb26b..b8eee452aca 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.cpp @@ -46,12 +46,28 @@ bool CSSCubicBezierTimingFunctionValue::equals(const CSSCubicBezierTimingFunctio String CSSStepsTimingFunctionValue::customCSSText() const { - return "steps(" + String::number(m_steps) + ", " + (m_stepAtStart ? "start" : "end") + ')'; + String stepAtPositionString; + switch (m_stepAtPosition) { + case StepsTimingFunction::StepAtStart: + stepAtPositionString = "start"; + break; + case StepsTimingFunction::StepAtMiddle: + stepAtPositionString = "middle"; + break; + case StepsTimingFunction::StepAtEnd: + stepAtPositionString = "end"; + break; + default: + ASSERT_NOT_REACHED(); + stepAtPositionString = "end"; + break; + } + return "steps(" + String::number(m_steps) + ", " + stepAtPositionString + ')'; } bool CSSStepsTimingFunctionValue::equals(const CSSStepsTimingFunctionValue& other) const { - return m_steps == other.m_steps && m_stepAtStart == other.m_stepAtStart; + return m_steps == other.m_steps && m_stepAtPosition == other.m_stepAtPosition; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.h b/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.h index 54f566171c2..f0daa301a3e 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSTimingFunctionValue.h @@ -27,15 +27,16 @@ #define CSSTimingFunctionValue_h #include "core/css/CSSValue.h" +#include "platform/animation/TimingFunction.h" #include "wtf/PassRefPtr.h" namespace WebCore { class CSSCubicBezierTimingFunctionValue : public CSSValue { public: - static PassRefPtr<CSSCubicBezierTimingFunctionValue> create(double x1, double y1, double x2, double y2) + static PassRefPtrWillBeRawPtr<CSSCubicBezierTimingFunctionValue> create(double x1, double y1, double x2, double y2) { - return adoptRef(new CSSCubicBezierTimingFunctionValue(x1, y1, x2, y2)); + return adoptRefWillBeNoop(new CSSCubicBezierTimingFunctionValue(x1, y1, x2, y2)); } String customCSSText() const; @@ -47,6 +48,8 @@ public: bool equals(const CSSCubicBezierTimingFunctionValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSCubicBezierTimingFunctionValue(double x1, double y1, double x2, double y2) : CSSValue(CubicBezierTimingFunctionClass) @@ -67,28 +70,30 @@ DEFINE_CSS_VALUE_TYPE_CASTS(CSSCubicBezierTimingFunctionValue, isCubicBezierTimi class CSSStepsTimingFunctionValue : public CSSValue { public: - static PassRefPtr<CSSStepsTimingFunctionValue> create(int steps, bool stepAtStart) + static PassRefPtrWillBeRawPtr<CSSStepsTimingFunctionValue> create(int steps, StepsTimingFunction::StepAtPosition stepAtPosition) { - return adoptRef(new CSSStepsTimingFunctionValue(steps, stepAtStart)); + return adoptRefWillBeNoop(new CSSStepsTimingFunctionValue(steps, stepAtPosition)); } int numberOfSteps() const { return m_steps; } - bool stepAtStart() const { return m_stepAtStart; } + StepsTimingFunction::StepAtPosition stepAtPosition() const { return m_stepAtPosition; } String customCSSText() const; bool equals(const CSSStepsTimingFunctionValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: - CSSStepsTimingFunctionValue(int steps, bool stepAtStart) + CSSStepsTimingFunctionValue(int steps, StepsTimingFunction::StepAtPosition stepAtPosition) : CSSValue(StepsTimingFunctionClass) , m_steps(steps) - , m_stepAtStart(stepAtStart) + , m_stepAtPosition(stepAtPosition) { } int m_steps; - bool m_stepAtStart; + StepsTimingFunction::StepAtPosition m_stepAtPosition; }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSStepsTimingFunctionValue, isStepsTimingFunctionValue()); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp b/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp index 6085a69892b..66583963904 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.cpp @@ -31,10 +31,45 @@ #include "config.h" #include "core/css/CSSToLengthConversionData.h" +#include "core/rendering/RenderView.h" #include "core/rendering/style/RenderStyle.h" namespace WebCore { +CSSToLengthConversionData::CSSToLengthConversionData(const RenderStyle* style, const RenderStyle* rootStyle, const RenderView* renderView, float zoom, bool computingFontSize) + : m_style(style) + , m_rootStyle(rootStyle) + , m_viewportWidth(renderView ? renderView->layoutViewportWidth() : 0) + , m_viewportHeight(renderView ? renderView->layoutViewportHeight() : 0) + , m_zoom(zoom) + , m_useEffectiveZoom(false) + , m_computingFontSize(computingFontSize) +{ + ASSERT(zoom > 0); +} + +CSSToLengthConversionData::CSSToLengthConversionData(const RenderStyle* style, const RenderStyle* rootStyle, const RenderView* renderView, bool computingFontSize) + : m_style(style) + , m_rootStyle(rootStyle) + , m_viewportWidth(renderView ? renderView->layoutViewportWidth() : 0) + , m_viewportHeight(renderView ? renderView->layoutViewportHeight() : 0) + , m_useEffectiveZoom(true) + , m_computingFontSize(computingFontSize) +{ +} + +CSSToLengthConversionData::CSSToLengthConversionData(const RenderStyle* style, const RenderStyle* rootStyle, float viewportWidth, float viewportHeight, float zoom, bool computingFontSize) + : m_style(style) + , m_rootStyle(rootStyle) + , m_viewportWidth(viewportWidth) + , m_viewportHeight(viewportHeight) + , m_zoom(zoom) + , m_useEffectiveZoom(false) + , m_computingFontSize(computingFontSize) +{ + ASSERT(zoom > 0); +} + float CSSToLengthConversionData::zoom() const { if (m_useEffectiveZoom) @@ -42,4 +77,25 @@ float CSSToLengthConversionData::zoom() const return m_zoom; } +double CSSToLengthConversionData::viewportWidthPercent() const +{ + m_style->setHasViewportUnits(); + return m_viewportWidth / 100; +} +double CSSToLengthConversionData::viewportHeightPercent() const +{ + m_style->setHasViewportUnits(); + return m_viewportHeight / 100; +} +double CSSToLengthConversionData::viewportMinPercent() const +{ + m_style->setHasViewportUnits(); + return std::min(m_viewportWidth, m_viewportHeight) / 100; +} +double CSSToLengthConversionData::viewportMaxPercent() const +{ + m_style->setHasViewportUnits(); + return std::max(m_viewportWidth, m_viewportHeight) / 100; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.h b/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.h index 975be5f2122..6b81ce993b9 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSToLengthConversionData.h @@ -37,41 +37,38 @@ namespace WebCore { class RenderStyle; +class RenderView; class CSSToLengthConversionData { public: - CSSToLengthConversionData(const RenderStyle* style, const RenderStyle* rootStyle, float zoom, bool computingFontSize = false) - : m_style(style) - , m_rootStyle(rootStyle) - , m_zoom(zoom) - , m_useEffectiveZoom(false) - , m_computingFontSize(computingFontSize) - { - ASSERT(zoom > 0); - } - CSSToLengthConversionData(const RenderStyle* style, const RenderStyle* rootStyle, bool computingFontSize = false) - : m_style(style) - , m_rootStyle(rootStyle) - , m_useEffectiveZoom(true) - , m_computingFontSize(computingFontSize) - { - } + CSSToLengthConversionData(const RenderStyle* currStyle, const RenderStyle* rootStyle, const RenderView*, float zoom, bool computingFontSize = false); + CSSToLengthConversionData(const RenderStyle* currStyle, const RenderStyle* rootStyle, const RenderView*, bool computingFontSize = false); + CSSToLengthConversionData(const RenderStyle* currStyle, const RenderStyle* rootStyle, float viewportWidth, float viewportHeight, float zoom, bool computingFontSize = false); + const RenderStyle& style() const { return *m_style; } - const RenderStyle& rootStyle() const { return *m_rootStyle; } + const RenderStyle* rootStyle() const { return m_rootStyle; } float zoom() const; bool computingFontSize() const { return m_computingFontSize; } + // Accessing these marks the style as having viewport units + double viewportWidthPercent() const; + double viewportHeightPercent() const; + double viewportMinPercent() const; + double viewportMaxPercent() const; + void setStyle(const RenderStyle* style) { m_style = style; } void setRootStyle(const RenderStyle* rootStyle) { m_rootStyle = rootStyle; } CSSToLengthConversionData copyWithAdjustedZoom(float newZoom) const { - return CSSToLengthConversionData(m_style, m_rootStyle, newZoom, m_computingFontSize); + return CSSToLengthConversionData(m_style, m_rootStyle, m_viewportWidth, m_viewportHeight, newZoom, m_computingFontSize); } private: const RenderStyle* m_style; const RenderStyle* m_rootStyle; + float m_viewportWidth; + float m_viewportHeight; float m_zoom; bool m_useEffectiveZoom; bool m_computingFontSize; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTokenizer-in.cpp b/chromium/third_party/WebKit/Source/core/css/CSSTokenizer-in.cpp index 5ee194a188c..3b8aef115ae 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSTokenizer-in.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSTokenizer-in.cpp @@ -28,7 +28,7 @@ #include "core/css/CSSTokenizer.h" #include "core/css/CSSKeyframeRule.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSParserValues.h" #include "core/css/MediaQuery.h" #include "core/css/StyleRule.h" @@ -37,7 +37,7 @@ namespace WebCore { -#include "CSSGrammar.h" +#include "core/CSSGrammar.h" enum CharacterType { // Types for the main switch. @@ -304,14 +304,17 @@ inline UChar*& CSSTokenizer::currentCharacter<UChar>() return m_currentCharacter16; } -UChar*& CSSTokenizer::currentCharacter16() +UChar* CSSTokenizer::allocateStringBuffer16(size_t len) { - if (!m_currentCharacter16) { - m_dataStart16 = adoptArrayPtr(new UChar[m_length]); - m_currentCharacter16 = m_dataStart16.get(); - } + // Allocates and returns a CSSTokenizer owned buffer for storing + // UTF-16 data. Used to get a suitable life span for UTF-16 + // strings, identifiers and URIs created by the tokenizer. + OwnPtr<UChar[]> buffer = adoptArrayPtr(new UChar[len]); - return m_currentCharacter16; + UChar* bufferPtr = buffer.get(); + + m_cssStrings16.append(buffer.release()); + return bufferPtr; } template <> @@ -350,13 +353,17 @@ inline bool CSSTokenizer::isIdentifierStart() return isIdentifierStartAfterDash((*currentCharacter<CharacterType>() != '-') ? currentCharacter<CharacterType>() : currentCharacter<CharacterType>() + 1); } +enum CheckStringValidationMode { + AbortIfInvalid, + SkipInvalid +}; + template <typename CharacterType> -static inline CharacterType* checkAndSkipString(CharacterType* currentCharacter, int quote) +static inline CharacterType* checkAndSkipString(CharacterType* currentCharacter, int quote, CheckStringValidationMode mode) { - // Returns with 0, if string check is failed. Otherwise - // it returns with the following character. This is necessary - // since we cannot revert escape sequences, thus strings - // must be validated before parsing. + // If mode is AbortIfInvalid and the string check fails it returns + // with 0. Otherwise it returns with a pointer to the first + // character after the string. while (true) { if (UNLIKELY(*currentCharacter == quote)) { // String parsing is successful. @@ -366,7 +373,7 @@ static inline CharacterType* checkAndSkipString(CharacterType* currentCharacter, // String parsing is successful up to end of input. return currentCharacter; } - if (UNLIKELY(*currentCharacter <= '\r' && (*currentCharacter == '\n' || (*currentCharacter | 0x1) == '\r'))) { + if (mode == AbortIfInvalid && UNLIKELY(*currentCharacter <= '\r' && (*currentCharacter == '\n' || (*currentCharacter | 0x1) == '\r'))) { // String parsing is failed for character '\n', '\f' or '\r'. return 0; } @@ -378,9 +385,13 @@ static inline CharacterType* checkAndSkipString(CharacterType* currentCharacter, } else if (currentCharacter[1] == '\r') { currentCharacter += currentCharacter[2] == '\n' ? 3 : 2; } else { - currentCharacter = checkAndSkipEscape(currentCharacter); - if (!currentCharacter) - return 0; + CharacterType* next = checkAndSkipEscape(currentCharacter); + if (!next) { + if (mode == AbortIfInvalid) + return 0; + next = currentCharacter + 1; + } + currentCharacter = next; } } } @@ -412,7 +423,7 @@ unsigned CSSTokenizer::parseEscape(CharacterType*& src) return unicode; } - return *currentCharacter<CharacterType>()++; + return *src++; } template <> @@ -438,6 +449,24 @@ inline void CSSTokenizer::UnicodeToChars<UChar>(UChar*& result, unsigned unicode ++result; } +template <typename SrcCharacterType> +size_t CSSTokenizer::peekMaxIdentifierLen(SrcCharacterType* src) +{ + // The decoded form of an identifier (after resolving escape + // sequences) will not contain more characters (ASCII or UTF-16 + // codepoints) than the input. This code can therefore ignore + // escape sequences completely. + SrcCharacterType* start = src; + do { + if (LIKELY(*src != '\\')) + src++; + else + parseEscape<SrcCharacterType>(src); + } while (isCSSLetter(src[0]) || (src[0] == '\\' && isCSSEscape(src[1]))); + + return src - start; +} + template <typename SrcCharacterType, typename DestCharacterType> inline bool CSSTokenizer::parseIdentifierInternal(SrcCharacterType*& src, DestCharacterType*& result, bool& hasEscape) { @@ -471,7 +500,7 @@ inline void CSSTokenizer::parseIdentifier(CharacterType*& result, CSSParserStrin if (UNLIKELY(!parseIdentifierInternal(currentCharacter<CharacterType>(), result, hasEscape))) { // Found an escape we couldn't handle with 8 bits, copy what has been recognized and continue ASSERT(is8BitSource()); - UChar*& result16 = currentCharacter16(); + UChar* result16 = allocateStringBuffer16((result - start) + peekMaxIdentifierLen(currentCharacter<CharacterType>())); UChar* start16 = result16; int i = 0; for (; i < result - start; i++) @@ -489,6 +518,18 @@ inline void CSSTokenizer::parseIdentifier(CharacterType*& result, CSSParserStrin resultString.init(start, result - start); } +template <typename SrcCharacterType> +size_t CSSTokenizer::peekMaxStringLen(SrcCharacterType* src, UChar quote) +{ + // The decoded form of a CSS string (after resolving escape + // sequences) will not contain more characters (ASCII or UTF-16 + // codepoints) than the input. This code can therefore ignore + // escape sequences completely and just return the length of the + // input string (possibly including terminating quote if any). + SrcCharacterType* end = checkAndSkipString(src, quote, SkipInvalid); + return end ? end - src : 0; +} + template <typename SrcCharacterType, typename DestCharacterType> inline bool CSSTokenizer::parseStringInternal(SrcCharacterType*& src, DestCharacterType*& result, UChar quote) { @@ -502,8 +543,6 @@ inline bool CSSTokenizer::parseStringInternal(SrcCharacterType*& src, DestCharac // String parsing is done, but don't advance pointer if at the end of input. return true; } - ASSERT(*src > '\r' || (*src < '\n' && *src) || *src == '\v'); - if (LIKELY(src[0] != '\\')) { *result++ = *src++; } else if (src[1] == '\n' || src[1] == '\f') { @@ -532,7 +571,7 @@ inline void CSSTokenizer::parseString(CharacterType*& result, CSSParserString& r if (UNLIKELY(!parseStringInternal(currentCharacter<CharacterType>(), result, quote))) { // Found an escape we couldn't handle with 8 bits, copy what has been recognized and continue ASSERT(is8BitSource()); - UChar*& result16 = currentCharacter16(); + UChar* result16 = allocateStringBuffer16((result - start) + peekMaxStringLen(currentCharacter<CharacterType>(), quote)); UChar* start16 = result16; int i = 0; for (; i < result - start; i++) @@ -556,7 +595,7 @@ inline bool CSSTokenizer::findURI(CharacterType*& start, CharacterType*& end, UC if (*start == '"' || *start == '\'') { quote = *start++; - end = checkAndSkipString(start, quote); + end = checkAndSkipString(start, quote, AbortIfInvalid); if (!end) return false; } else { @@ -580,6 +619,29 @@ inline bool CSSTokenizer::findURI(CharacterType*& start, CharacterType*& end, UC return true; } +template <typename SrcCharacterType> +inline size_t CSSTokenizer::peekMaxURILen(SrcCharacterType* src, UChar quote) +{ + // The decoded form of a URI (after resolving escape sequences) + // will not contain more characters (ASCII or UTF-16 codepoints) + // than the input. This code can therefore ignore escape sequences + // completely. + SrcCharacterType* start = src; + if (quote) { + ASSERT(quote == '"' || quote == '\''); + return peekMaxStringLen(src, quote); + } + + while (isURILetter(*src)) { + if (LIKELY(*src != '\\')) + src++; + else + parseEscape<SrcCharacterType>(src); + } + + return src - start; +} + template <typename SrcCharacterType, typename DestCharacterType> inline bool CSSTokenizer::parseURIInternal(SrcCharacterType*& src, DestCharacterType*& dest, UChar quote) { @@ -593,7 +655,7 @@ inline bool CSSTokenizer::parseURIInternal(SrcCharacterType*& src, DestCharacter *dest++ = *src++; } else { unsigned unicode = parseEscape<SrcCharacterType>(src); - if (unicode > 0xff && sizeof(SrcCharacterType) == 1) + if (unicode > 0xff && sizeof(DestCharacterType) == 1) return false; UnicodeToChars(dest, unicode); } @@ -619,11 +681,12 @@ inline void CSSTokenizer::parseURI(CSSParserString& string) // Reset the current character to the start of the URI and re-parse with // a 16-bit destination. ASSERT(is8BitSource()); - UChar* uriStart16 = currentCharacter16(); currentCharacter<CharacterType>() = uriStart; - bool result = parseURIInternal(currentCharacter<CharacterType>(), currentCharacter16(), quote); + UChar* result16 = allocateStringBuffer16(peekMaxURILen(currentCharacter<CharacterType>(), quote)); + UChar* uriStart16 = result16; + bool result = parseURIInternal(currentCharacter<CharacterType>(), result16, quote); ASSERT_UNUSED(result, result); - string.init(uriStart16, currentCharacter16() - uriStart16); + string.init(uriStart16, result16 - uriStart16); } currentCharacter<CharacterType>() = uriEnd + 1; @@ -719,12 +782,6 @@ inline bool CSSTokenizer::detectFunctionTypeToken(int length) m_token = CUEFUNCTION; return true; } - CASE("var") { - if (!RuntimeEnabledFeatures::cssVariablesEnabled()) - return false; - m_token = VARFUNCTION; - return true; - } CASE("calc") { m_token = CALCFUNCTION; return true; @@ -733,6 +790,10 @@ inline bool CSSTokenizer::detectFunctionTypeToken(int length) m_token = HOSTFUNCTION; return true; } + CASE("host-context") { + m_token = HOSTCONTEXTFUNCTION; + return true; + } CASE("nth-child") { m_parsingMode = NthChildMode; return true; @@ -881,18 +942,9 @@ inline void CSSTokenizer::detectDashToken(int length) CASE("webkit-any") { m_token = ANYFUNCTION; } - CASE("webkit-min") { - m_token = MINFUNCTION; - } - CASE("webkit-max") { - m_token = MAXFUNCTION; - } CASE("webkit-calc") { m_token = CALCFUNCTION; } - CASE("webkit-distributed") { - m_token = DISTRIBUTEDFUNCTION; - } } } @@ -1009,14 +1061,6 @@ inline void CSSTokenizer::detectAtToken(int length, bool hasEscape) if (LIKELY(!hasEscape && m_internal)) m_token = INTERNAL_RULE_SYM; } - CASE("-webkit-region") { - if (LIKELY(!hasEscape)) - m_token = WEBKIT_REGION_RULE_SYM; - } - CASE("-webkit-filter") { - if (LIKELY(!hasEscape)) - m_token = WEBKIT_FILTER_RULE_SYM; - } CASE("-internal-decls") { if (LIKELY(!hasEscape && m_internal)) m_token = INTERNAL_DECLS_SYM; @@ -1075,18 +1119,6 @@ inline void CSSTokenizer::detectSupportsToken(int length) } } -template <typename CharacterType> -inline void CSSTokenizer::detectCSSVariableDefinitionToken(int length) -{ - static const int prefixLength = static_cast<int>(sizeof("var-") - 1); - if (length <= prefixLength) - return; - CharacterType* name = tokenStart<CharacterType>(); - COMPILE_ASSERT(prefixLength > 0, CSS_variable_prefix_must_be_nonempty); - if (name[prefixLength - 1] == '-' && isIdentifierStartAfterDash(name + prefixLength) && isEqualToCSSCaseSensitiveIdentifier(name, "var")) - m_token = VAR_DEFINITION; -} - template <typename SrcCharacterType> int CSSTokenizer::realLex(void* yylvalWithoutType) { @@ -1176,8 +1208,6 @@ restartAfterComment: } } } - } else if (UNLIKELY(RuntimeEnabledFeatures::cssVariablesEnabled())) { - detectCSSVariableDefinitionToken<SrcCharacterType>(result - tokenStart<SrcCharacterType>()); } break; @@ -1338,7 +1368,7 @@ restartAfterComment: break; case CharacterQuote: - if (checkAndSkipString(currentCharacter<SrcCharacterType>(), m_token)) { + if (checkAndSkipString(currentCharacter<SrcCharacterType>(), m_token, AbortIfInvalid)) { ++result; parseString<SrcCharacterType>(result, yylval->string, m_token); m_token = STRING; @@ -1388,9 +1418,9 @@ restartAfterComment: // Ignore comments. They are not even considered as white spaces. if (*currentCharacter<SrcCharacterType>() == '*') { const CSSParserLocation startLocation = currentLocation(); - if (m_parser.m_sourceDataHandler) { + if (m_parser.m_observer) { unsigned startOffset = currentCharacter<SrcCharacterType>() - dataStart<SrcCharacterType>() - 1; // Start with a slash. - m_parser.m_sourceDataHandler->startComment(startOffset - m_parsedTextPrefixLength); + m_parser.m_observer->startComment(startOffset - m_parsedTextPrefixLength); } ++currentCharacter<SrcCharacterType>(); while (currentCharacter<SrcCharacterType>()[0] != '*' || currentCharacter<SrcCharacterType>()[1] != '/') { @@ -1399,16 +1429,16 @@ restartAfterComment: if (*currentCharacter<SrcCharacterType>() == '\0') { // Unterminated comments are simply ignored. currentCharacter<SrcCharacterType>() -= 2; - m_parser.reportError(startLocation, CSSParser::UnterminatedCommentError); + m_parser.reportError(startLocation, UnterminatedCommentCSSError); break; } ++currentCharacter<SrcCharacterType>(); } currentCharacter<SrcCharacterType>() += 2; - if (m_parser.m_sourceDataHandler) { + if (m_parser.m_observer) { unsigned endOffset = currentCharacter<SrcCharacterType>() - dataStart<SrcCharacterType>(); unsigned userTextEndOffset = static_cast<unsigned>(m_length - 1 - m_parsedTextSuffixLength); - m_parser.m_sourceDataHandler->endComment(std::min(endOffset, userTextEndOffset) - m_parsedTextPrefixLength); + m_parser.m_observer->endComment(std::min(endOffset, userTextEndOffset) - m_parsedTextPrefixLength); } goto restartAfterComment; } @@ -1451,7 +1481,9 @@ restartAfterComment: m_token = ATKEYWORD; ++result; parseIdentifier(result, resultString, hasEscape); - detectAtToken<SrcCharacterType>(result - tokenStart<SrcCharacterType>(), hasEscape); + // The standard enables unicode escapes in at-rules. In this case only the resultString will contain the + // correct identifier, hence we have to use it to determine its length instead of the usual pointer arithmetic. + detectAtToken<SrcCharacterType>(resultString.length() + 1, hasEscape); } break; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTokenizer.h b/chromium/third_party/WebKit/Source/core/css/CSSTokenizer.h index 05b319c177a..508bf71ee29 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSTokenizer.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSTokenizer.h @@ -29,7 +29,7 @@ namespace WebCore { -class CSSParser; +class BisonCSSParser; struct CSSParserLocation; struct CSSParserString; @@ -37,9 +37,9 @@ class CSSTokenizer { WTF_MAKE_NONCOPYABLE(CSSTokenizer); public: // FIXME: This should not be needed but there are still some ties between the 2 classes. - friend class CSSParser; + friend class BisonCSSParser; - CSSTokenizer(CSSParser& parser) + CSSTokenizer(BisonCSSParser& parser) : m_parser(parser) , m_parsedTextPrefixLength(0) , m_parsedTextSuffixLength(0) @@ -74,7 +74,7 @@ public: inline unsigned tokenStartOffset(); private: - UChar*& currentCharacter16(); + UChar* allocateStringBuffer16(size_t len); template <typename CharacterType> inline CharacterType*& currentCharacter(); @@ -92,29 +92,33 @@ private: inline CSSParserLocation tokenLocation(); template <typename CharacterType> - unsigned parseEscape(CharacterType*&); + static unsigned parseEscape(CharacterType*&); template <typename DestCharacterType> - inline void UnicodeToChars(DestCharacterType*&, unsigned); - template <typename SrcCharacterType, typename DestCharacterType> - inline bool parseIdentifierInternal(SrcCharacterType*&, DestCharacterType*&, bool&); + static inline void UnicodeToChars(DestCharacterType*&, unsigned); + template <typename SrcCharacterType, typename DestCharacterType> + static inline bool parseIdentifierInternal(SrcCharacterType*&, DestCharacterType*&, bool&); + template <typename SrcCharacterType> + static size_t peekMaxIdentifierLen(SrcCharacterType*); template <typename CharacterType> inline void parseIdentifier(CharacterType*&, CSSParserString&, bool&); + template <typename SrcCharacterType> + static size_t peekMaxStringLen(SrcCharacterType*, UChar quote); template <typename SrcCharacterType, typename DestCharacterType> - inline bool parseStringInternal(SrcCharacterType*&, DestCharacterType*&, UChar); - + static inline bool parseStringInternal(SrcCharacterType*&, DestCharacterType*&, UChar); template <typename CharacterType> inline void parseString(CharacterType*&, CSSParserString& resultString, UChar); template <typename CharacterType> inline bool findURI(CharacterType*& start, CharacterType*& end, UChar& quote); - + template <typename SrcCharacterType> + static size_t peekMaxURILen(SrcCharacterType*, UChar quote); template <typename SrcCharacterType, typename DestCharacterType> - inline bool parseURIInternal(SrcCharacterType*&, DestCharacterType*&, UChar quote); - + static inline bool parseURIInternal(SrcCharacterType*&, DestCharacterType*&, UChar quote); template <typename CharacterType> inline void parseURI(CSSParserString&); + template <typename CharacterType> inline bool parseUnicodeRange(); template <typename CharacterType> @@ -133,13 +137,11 @@ private: inline void detectAtToken(int, bool); template <typename CharacterType> inline void detectSupportsToken(int); - template <typename CharacterType> - inline void detectCSSVariableDefinitionToken(int); template <typename SourceCharacterType> int realLex(void* yylval); - CSSParser& m_parser; + BisonCSSParser& m_parser; size_t m_parsedTextPrefixLength; size_t m_parsedTextSuffixLength; @@ -157,6 +159,13 @@ private: OwnPtr<UChar[]> m_dataStart16; LChar* m_currentCharacter8; UChar* m_currentCharacter16; + + // During parsing of an ASCII stylesheet we might locate escape + // sequences that expand into UTF-16 code points. Strings, + // identifiers and URIs containing such escape sequences are + // stored in m_cssStrings16 so that we don't have to store the + // whole stylesheet as UTF-16. + Vector<OwnPtr<UChar[]> > m_cssStrings16; union { LChar* ptr8; UChar* ptr16; diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.cpp index de981949bd3..ebb21b931ba 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.cpp @@ -76,20 +76,15 @@ String CSSTransformValue::customCSSText() const return transformValueToCssString(m_type, CSSValueList::customCSSText()); } -String CSSTransformValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - return transformValueToCssString(m_type, CSSValueList::customSerializeResolvingVariables(variables)); -} - CSSTransformValue::CSSTransformValue(const CSSTransformValue& cloneFrom) : CSSValueList(cloneFrom) , m_type(cloneFrom.m_type) { } -PassRefPtr<CSSTransformValue> CSSTransformValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSTransformValue> CSSTransformValue::cloneForCSSOM() const { - return adoptRef(new CSSTransformValue(*this)); + return adoptRefWillBeNoop(new CSSTransformValue(*this)); } } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.h b/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.h index 1ca3bbd45f1..11cd454a0d0 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSTransformValue.h @@ -59,18 +59,19 @@ public: Matrix3DTransformOperation }; - static PassRefPtr<CSSTransformValue> create(TransformOperationType type) + static PassRefPtrWillBeRawPtr<CSSTransformValue> create(TransformOperationType type) { - return adoptRef(new CSSTransformValue(type)); + return adoptRefWillBeNoop(new CSSTransformValue(type)); } String customCSSText() const; bool equals(const CSSTransformValue& other) const { return m_type == other.m_type && CSSValueList::equals(other); } - String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const; TransformOperationType operationType() const { return m_type; } - PassRefPtr<CSSTransformValue> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSTransformValue> cloneForCSSOM() const; + + void traceAfterDispatch(Visitor* visitor) { CSSValueList::traceAfterDispatch(visitor); } private: CSSTransformValue(TransformOperationType); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSUnicodeRangeValue.h b/chromium/third_party/WebKit/Source/core/css/CSSUnicodeRangeValue.h index 3ce02a98cc6..c198a237d6e 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSUnicodeRangeValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSUnicodeRangeValue.h @@ -33,9 +33,9 @@ namespace WebCore { class CSSUnicodeRangeValue : public CSSValue { public: - static PassRefPtr<CSSUnicodeRangeValue> create(UChar32 from, UChar32 to) + static PassRefPtrWillBeRawPtr<CSSUnicodeRangeValue> create(UChar32 from, UChar32 to) { - return adoptRef(new CSSUnicodeRangeValue(from, to)); + return adoptRefWillBeNoop(new CSSUnicodeRangeValue(from, to)); } UChar32 from() const { return m_from; } @@ -45,6 +45,8 @@ public: bool equals(const CSSUnicodeRangeValue&) const; + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: CSSUnicodeRangeValue(UChar32 from, UChar32 to) : CSSValue(UnicodeRangeClass) diff --git a/chromium/third_party/WebKit/Source/core/css/CSSUnknownRule.h b/chromium/third_party/WebKit/Source/core/css/CSSUnknownRule.h index 629aaead0d3..06d1be4283a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSUnknownRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSUnknownRule.h @@ -26,7 +26,7 @@ namespace WebCore { -class CSSUnknownRule : public CSSRule { +class CSSUnknownRule FINAL : public CSSRule { public: CSSUnknownRule() : CSSRule(0) { } virtual ~CSSUnknownRule() { } @@ -34,6 +34,7 @@ public: virtual CSSRule::Type type() const OVERRIDE { return UNKNOWN_RULE; } virtual String cssText() const OVERRIDE { return String(); } virtual void reattach(StyleRuleBase*) OVERRIDE { } + virtual void trace(Visitor* visitor) OVERRIDE { CSSRule::trace(visitor); } }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValue.cpp b/chromium/third_party/WebKit/Source/core/css/CSSValue.cpp index 6d74434cc11..332638e95eb 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValue.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSValue.cpp @@ -41,29 +41,25 @@ #include "core/css/CSSFunctionValue.h" #include "core/css/CSSGradientValue.h" #include "core/css/CSSGridLineNamesValue.h" -#include "core/css/CSSGridTemplateValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" #include "core/css/CSSImageSetValue.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSInheritedValue.h" #include "core/css/CSSInitialValue.h" #include "core/css/CSSLineBoxContainValue.h" -#include "core/css/CSSMixFunctionValue.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSReflectValue.h" #include "core/css/CSSSVGDocumentValue.h" -#include "core/css/CSSShaderValue.h" #include "core/css/CSSShadowValue.h" #include "core/css/CSSTimingFunctionValue.h" #include "core/css/CSSTransformValue.h" #include "core/css/CSSUnicodeRangeValue.h" #include "core/css/CSSValueList.h" -#include "core/css/CSSVariableValue.h" -#include "core/svg/SVGColor.h" #include "core/svg/SVGPaint.h" namespace WebCore { -struct SameSizeAsCSSValue : public RefCounted<SameSizeAsCSSValue> { +struct SameSizeAsCSSValue : public RefCountedWillBeGarbageCollectedFinalized<SameSizeAsCSSValue> { uint32_t bitfields; }; @@ -71,10 +67,15 @@ COMPILE_ASSERT(sizeof(CSSValue) <= sizeof(SameSizeAsCSSValue), CSS_value_should_ class TextCloneCSSValue : public CSSValue { public: - static PassRefPtr<TextCloneCSSValue> create(ClassType classType, const String& text) { return adoptRef(new TextCloneCSSValue(classType, text)); } + static PassRefPtrWillBeRawPtr<TextCloneCSSValue> create(ClassType classType, const String& text) + { + return adoptRefWillBeNoop(new TextCloneCSSValue(classType, text)); + } String cssText() const { return m_cssText; } + void traceAfterDispatch(Visitor* visitor) { CSSValue::traceAfterDispatch(visitor); } + private: TextCloneCSSValue(ClassType classType, const String& text) : CSSValue(classType, /*isCSSOMSafe*/ true) @@ -106,21 +107,6 @@ CSSValue::Type CSSValue::cssValueType() const return CSS_CUSTOM; } -void CSSValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const -{ - // This should get called for internal instances only. - ASSERT(!isCSSOMSafe()); - - if (isPrimitiveValue()) - toCSSPrimitiveValue(this)->addSubresourceStyleURLs(urls, styleSheet); - else if (isValueList()) - toCSSValueList(this)->addSubresourceStyleURLs(urls, styleSheet); - else if (classType() == FontFaceSrcClass) - toCSSFontFaceSrcValue(this)->addSubresourceStyleURLs(urls, styleSheet); - else if (classType() == ReflectClass) - toCSSReflectValue(this)->addSubresourceStyleURLs(urls, styleSheet); -} - bool CSSValue::hasFailedOrCanceledSubresources() const { // This should get called for internal instances only. @@ -185,8 +171,8 @@ bool CSSValue::equals(const CSSValue& other) const return compareCSSValues<CSSInitialValue>(*this, other); case GridLineNamesClass: return compareCSSValues<CSSGridLineNamesValue>(*this, other); - case GridTemplateClass: - return compareCSSValues<CSSGridTemplateValue>(*this, other); + case GridTemplateAreasClass: + return compareCSSValues<CSSGridTemplateAreasValue>(*this, other); case PrimitiveClass: return compareCSSValues<CSSPrimitiveValue>(*this, other); case ReflectClass: @@ -213,14 +199,6 @@ bool CSSValue::equals(const CSSValue& other) const return compareCSSValues<CSSFilterValue>(*this, other); case CSSArrayFunctionValueClass: return compareCSSValues<CSSArrayFunctionValue>(*this, other); - case CSSMixFunctionValueClass: - return compareCSSValues<CSSMixFunctionValue>(*this, other); - case CSSShaderClass: - return compareCSSValues<CSSShaderValue>(*this, other); - case VariableClass: - return compareCSSValues<CSSVariableValue>(*this, other); - case SVGColorClass: - return compareCSSValues<SVGColor>(*this, other); case SVGPaintClass: return compareCSSValues<SVGPaint>(*this, other); case CSSSVGDocumentClass: @@ -275,8 +253,8 @@ String CSSValue::cssText() const return toCSSInitialValue(this)->customCSSText(); case GridLineNamesClass: return toCSSGridLineNamesValue(this)->customCSSText(); - case GridTemplateClass: - return toCSSGridTemplateValue(this)->customCSSText(); + case GridTemplateAreasClass: + return toCSSGridTemplateAreasValue(this)->customCSSText(); case PrimitiveClass: return toCSSPrimitiveValue(this)->customCSSText(); case ReflectClass: @@ -303,14 +281,6 @@ String CSSValue::cssText() const return toCSSFilterValue(this)->customCSSText(); case CSSArrayFunctionValueClass: return toCSSArrayFunctionValue(this)->customCSSText(); - case CSSMixFunctionValueClass: - return toCSSMixFunctionValue(this)->customCSSText(); - case CSSShaderClass: - return toCSSShaderValue(this)->customCSSText(); - case VariableClass: - return toCSSVariableValue(this)->value(); - case SVGColorClass: - return toSVGColor(this)->customCSSText(); case SVGPaintClass: return toSVGPaint(this)->customCSSText(); case CSSSVGDocumentClass: @@ -320,22 +290,6 @@ String CSSValue::cssText() const return String(); } -String CSSValue::serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - switch (classType()) { - case PrimitiveClass: - return toCSSPrimitiveValue(this)->customSerializeResolvingVariables(variables); - case ReflectClass: - return toCSSReflectValue(this)->customSerializeResolvingVariables(variables); - case ValueListClass: - return toCSSValueList(this)->customSerializeResolvingVariables(variables); - case CSSTransformClass: - return toCSSTransformValue(this)->customSerializeResolvingVariables(variables); - default: - return cssText(); - } -} - void CSSValue::destroy() { if (m_isTextClone) { @@ -391,8 +345,8 @@ void CSSValue::destroy() case GridLineNamesClass: delete toCSSGridLineNamesValue(this); return; - case GridTemplateClass: - delete toCSSGridTemplateValue(this); + case GridTemplateAreasClass: + delete toCSSGridTemplateAreasValue(this); return; case PrimitiveClass: delete toCSSPrimitiveValue(this); @@ -433,29 +387,231 @@ void CSSValue::destroy() case CSSArrayFunctionValueClass: delete toCSSArrayFunctionValue(this); return; - case CSSMixFunctionValueClass: - delete toCSSMixFunctionValue(this); + case SVGPaintClass: + delete toSVGPaint(this); + return; + case CSSSVGDocumentClass: + delete toCSSSVGDocumentValue(this); + return; + } + ASSERT_NOT_REACHED(); +} + +void CSSValue::finalizeGarbageCollectedObject() +{ + if (m_isTextClone) { + ASSERT(isCSSOMSafe()); + static_cast<TextCloneCSSValue*>(this)->~TextCloneCSSValue(); + return; + } + ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM()); + + switch (classType()) { + case AspectRatioClass: + toCSSAspectRatioValue(this)->~CSSAspectRatioValue(); + return; + case BorderImageSliceClass: + toCSSBorderImageSliceValue(this)->~CSSBorderImageSliceValue(); + return; + case CanvasClass: + toCSSCanvasValue(this)->~CSSCanvasValue(); + return; + case CursorImageClass: + toCSSCursorImageValue(this)->~CSSCursorImageValue(); + return; + case FontClass: + toCSSFontValue(this)->~CSSFontValue(); + return; + case FontFaceSrcClass: + toCSSFontFaceSrcValue(this)->~CSSFontFaceSrcValue(); + return; + case FontFeatureClass: + toCSSFontFeatureValue(this)->~CSSFontFeatureValue(); + return; + case FunctionClass: + toCSSFunctionValue(this)->~CSSFunctionValue(); + return; + case LinearGradientClass: + toCSSLinearGradientValue(this)->~CSSLinearGradientValue(); + return; + case RadialGradientClass: + toCSSRadialGradientValue(this)->~CSSRadialGradientValue(); + return; + case CrossfadeClass: + toCSSCrossfadeValue(this)->~CSSCrossfadeValue(); + return; + case ImageClass: + toCSSImageValue(this)->~CSSImageValue(); + return; + case InheritedClass: + toCSSInheritedValue(this)->~CSSInheritedValue(); + return; + case InitialClass: + toCSSInitialValue(this)->~CSSInitialValue(); + return; + case GridLineNamesClass: + toCSSGridLineNamesValue(this)->~CSSGridLineNamesValue(); + return; + case GridTemplateAreasClass: + toCSSGridTemplateAreasValue(this)->~CSSGridTemplateAreasValue(); + return; + case PrimitiveClass: + toCSSPrimitiveValue(this)->~CSSPrimitiveValue(); + return; + case ReflectClass: + toCSSReflectValue(this)->~CSSReflectValue(); + return; + case ShadowClass: + toCSSShadowValue(this)->~CSSShadowValue(); + return; + case CubicBezierTimingFunctionClass: + toCSSCubicBezierTimingFunctionValue(this)->~CSSCubicBezierTimingFunctionValue(); + return; + case StepsTimingFunctionClass: + toCSSStepsTimingFunctionValue(this)->~CSSStepsTimingFunctionValue(); + return; + case UnicodeRangeClass: + toCSSUnicodeRangeValue(this)->~CSSUnicodeRangeValue(); + return; + case ValueListClass: + toCSSValueList(this)->~CSSValueList(); + return; + case CSSTransformClass: + toCSSTransformValue(this)->~CSSTransformValue(); + return; + case LineBoxContainClass: + toCSSLineBoxContainValue(this)->~CSSLineBoxContainValue(); return; - case CSSShaderClass: - delete toCSSShaderValue(this); + case CalculationClass: + toCSSCalcValue(this)->~CSSCalcValue(); return; - case VariableClass: - delete toCSSVariableValue(this); + case ImageSetClass: + toCSSImageSetValue(this)->~CSSImageSetValue(); return; - case SVGColorClass: - delete toSVGColor(this); + case CSSFilterClass: + toCSSFilterValue(this)->~CSSFilterValue(); + return; + case CSSArrayFunctionValueClass: + toCSSArrayFunctionValue(this)->~CSSArrayFunctionValue(); return; case SVGPaintClass: - delete toSVGPaint(this); + toSVGPaint(this)->~SVGPaint(); return; case CSSSVGDocumentClass: - delete toCSSSVGDocumentValue(this); + toCSSSVGDocumentValue(this)->~CSSSVGDocumentValue(); + return; + } + ASSERT_NOT_REACHED(); +} + +void CSSValue::trace(Visitor* visitor) +{ + if (m_isTextClone) { + ASSERT(isCSSOMSafe()); + static_cast<TextCloneCSSValue*>(this)->traceAfterDispatch(visitor); + return; + } + ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM()); + + switch (classType()) { + case AspectRatioClass: + toCSSAspectRatioValue(this)->traceAfterDispatch(visitor); + return; + case BorderImageSliceClass: + toCSSBorderImageSliceValue(this)->traceAfterDispatch(visitor); + return; + case CanvasClass: + toCSSCanvasValue(this)->traceAfterDispatch(visitor); + return; + case CursorImageClass: + toCSSCursorImageValue(this)->traceAfterDispatch(visitor); + return; + case FontClass: + toCSSFontValue(this)->traceAfterDispatch(visitor); + return; + case FontFaceSrcClass: + toCSSFontFaceSrcValue(this)->traceAfterDispatch(visitor); + return; + case FontFeatureClass: + toCSSFontFeatureValue(this)->traceAfterDispatch(visitor); + return; + case FunctionClass: + toCSSFunctionValue(this)->traceAfterDispatch(visitor); + return; + case LinearGradientClass: + toCSSLinearGradientValue(this)->traceAfterDispatch(visitor); + return; + case RadialGradientClass: + toCSSRadialGradientValue(this)->traceAfterDispatch(visitor); + return; + case CrossfadeClass: + toCSSCrossfadeValue(this)->traceAfterDispatch(visitor); + return; + case ImageClass: + toCSSImageValue(this)->traceAfterDispatch(visitor); + return; + case InheritedClass: + toCSSInheritedValue(this)->traceAfterDispatch(visitor); + return; + case InitialClass: + toCSSInitialValue(this)->traceAfterDispatch(visitor); + return; + case GridLineNamesClass: + toCSSGridLineNamesValue(this)->traceAfterDispatch(visitor); + return; + case GridTemplateAreasClass: + toCSSGridTemplateAreasValue(this)->traceAfterDispatch(visitor); + return; + case PrimitiveClass: + toCSSPrimitiveValue(this)->traceAfterDispatch(visitor); + return; + case ReflectClass: + toCSSReflectValue(this)->traceAfterDispatch(visitor); + return; + case ShadowClass: + toCSSShadowValue(this)->traceAfterDispatch(visitor); + return; + case CubicBezierTimingFunctionClass: + toCSSCubicBezierTimingFunctionValue(this)->traceAfterDispatch(visitor); + return; + case StepsTimingFunctionClass: + toCSSStepsTimingFunctionValue(this)->traceAfterDispatch(visitor); + return; + case UnicodeRangeClass: + toCSSUnicodeRangeValue(this)->traceAfterDispatch(visitor); + return; + case ValueListClass: + toCSSValueList(this)->traceAfterDispatch(visitor); + return; + case CSSTransformClass: + toCSSTransformValue(this)->traceAfterDispatch(visitor); + return; + case LineBoxContainClass: + toCSSLineBoxContainValue(this)->traceAfterDispatch(visitor); + return; + case CalculationClass: + toCSSCalcValue(this)->traceAfterDispatch(visitor); + return; + case ImageSetClass: + toCSSImageSetValue(this)->traceAfterDispatch(visitor); + return; + case CSSFilterClass: + toCSSFilterValue(this)->traceAfterDispatch(visitor); + return; + case CSSArrayFunctionValueClass: + toCSSArrayFunctionValue(this)->traceAfterDispatch(visitor); + return; + case SVGPaintClass: + toSVGPaint(this)->traceAfterDispatch(visitor); + return; + case CSSSVGDocumentClass: + toCSSSVGDocumentValue(this)->traceAfterDispatch(visitor); return; } ASSERT_NOT_REACHED(); } -PassRefPtr<CSSValue> CSSValue::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSValue> CSSValue::cloneForCSSOM() const { switch (classType()) { case PrimitiveClass: @@ -469,14 +625,10 @@ PassRefPtr<CSSValue> CSSValue::cloneForCSSOM() const return toCSSFilterValue(this)->cloneForCSSOM(); case CSSArrayFunctionValueClass: return toCSSArrayFunctionValue(this)->cloneForCSSOM(); - case CSSMixFunctionValueClass: - return toCSSMixFunctionValue(this)->cloneForCSSOM(); case CSSTransformClass: return toCSSTransformValue(this)->cloneForCSSOM(); case ImageSetClass: return toCSSImageSetValue(this)->cloneForCSSOM(); - case SVGColorClass: - return toSVGColor(this)->cloneForCSSOM(); case SVGPaintClass: return toSVGPaint(this)->cloneForCSSOM(); default: diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValue.h b/chromium/third_party/WebKit/Source/core/css/CSSValue.h index e6b21b8ce2b..a883479b899 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValue.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSValue.h @@ -22,6 +22,7 @@ #define CSSValue_h #include "core/dom/ExceptionCode.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "wtf/HashMap.h" #include "wtf/ListHashSet.h" @@ -40,7 +41,7 @@ enum CSSTextFormattingFlags { QuoteCSSStringIfNeeded, AlwaysQuoteCSSString }; // They should be handled by separate wrapper classes. // Please don't expose more CSSValue types to the web. -class CSSValue : public RefCounted<CSSValue> { +class CSSValue : public RefCountedWillBeGarbageCollectedFinalized<CSSValue> { public: enum Type { CSS_INHERIT = 0, @@ -53,17 +54,20 @@ public: // Override RefCounted's deref() to ensure operator delete is called on // the appropriate subclass type. + // When oilpan is enabled the finalize method is called by the garbage + // collector and not immediately when deref reached zero. +#if !ENABLE(OILPAN) void deref() { if (derefBase()) destroy(); } +#endif // !ENABLE(OILPAN) Type cssValueType() const; String cssText() const; void setCSSText(const String&, ExceptionState&) { } // FIXME: Not implemented. - String serializeResolvingVariables(const HashMap<AtomicString, String>&) const; bool isPrimitiveValue() const { return m_classType == PrimitiveClass; } bool isValueList() const { return m_classType >= ValueListClass; } @@ -98,11 +102,7 @@ public: bool isCalcValue() const {return m_classType == CalculationClass; } bool isFilterValue() const { return m_classType == CSSFilterClass; } bool isArrayFunctionValue() const { return m_classType == CSSArrayFunctionValueClass; } - bool isMixFunctionValue() const { return m_classType == CSSMixFunctionValueClass; } - bool isShaderValue() const { return m_classType == CSSShaderClass; } - bool isVariableValue() const { return m_classType == VariableClass; } - bool isGridTemplateValue() const { return m_classType == GridTemplateClass; } - bool isSVGColor() const { return m_classType == SVGColorClass || m_classType == SVGPaintClass; } + bool isGridTemplateAreasValue() const { return m_classType == GridTemplateAreasClass; } bool isSVGPaint() const { return m_classType == SVGPaintClass; } bool isSVGDocumentValue() const { return m_classType == CSSSVGDocumentClass; } bool isUnicodeRangeValue() const { return m_classType == UnicodeRangeClass; } @@ -111,17 +111,19 @@ public: bool isCSSOMSafe() const { return m_isCSSOMSafe; } bool isSubtypeExposedToCSSOM() const { - return isPrimitiveValue() || isSVGColor() || isValueList(); + return isPrimitiveValue() || isSVGPaint() || isValueList(); } - PassRefPtr<CSSValue> cloneForCSSOM() const; - - void addSubresourceStyleURLs(ListHashSet<KURL>&, const StyleSheetContents*) const; + PassRefPtrWillBeRawPtr<CSSValue> cloneForCSSOM() const; bool hasFailedOrCanceledSubresources() const; bool equals(const CSSValue&) const; + void finalizeGarbageCollectedObject(); + void traceAfterDispatch(Visitor*) { } + void trace(Visitor*); + protected: static const size_t ClassTypeBits = 6; @@ -158,12 +160,9 @@ protected: UnicodeRangeClass, LineBoxContainClass, CalculationClass, - CSSShaderClass, - VariableClass, - GridTemplateClass, + GridTemplateAreasClass, // SVG classes. - SVGColorClass, SVGPaintClass, CSSSVGDocumentClass, @@ -172,7 +171,6 @@ protected: ImageSetClass, CSSFilterClass, CSSArrayFunctionValueClass, - CSSMixFunctionValueClass, CSSTransformClass, GridLineNamesClass, // Do not append non-list class types here. @@ -213,7 +211,7 @@ protected: // to maximize struct packing. // CSSPrimitiveValue bits: - unsigned m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes + unsigned m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitType mutable unsigned m_hasCachedCSSText : 1; unsigned m_isQuirkValue : 1; @@ -223,16 +221,16 @@ private: unsigned m_classType : ClassTypeBits; // ClassType }; -template<typename CSSValueType> -inline bool compareCSSValueVector(const Vector<RefPtr<CSSValueType> >& firstVector, const Vector<RefPtr<CSSValueType> >& secondVector) +template<typename CSSValueType, size_t inlineCapacity> +inline bool compareCSSValueVector(const WillBeHeapVector<RefPtrWillBeMember<CSSValueType>, inlineCapacity>& firstVector, const WillBeHeapVector<RefPtrWillBeMember<CSSValueType>, inlineCapacity>& secondVector) { size_t size = firstVector.size(); if (size != secondVector.size()) return false; for (size_t i = 0; i < size; i++) { - const RefPtr<CSSValueType>& firstPtr = firstVector[i]; - const RefPtr<CSSValueType>& secondPtr = secondVector[i]; + const RefPtrWillBeMember<CSSValueType>& firstPtr = firstVector[i]; + const RefPtrWillBeMember<CSSValueType>& secondPtr = secondVector[i]; if (firstPtr == secondPtr || (firstPtr && secondPtr && firstPtr->equals(*secondPtr))) continue; return false; @@ -246,6 +244,18 @@ inline bool compareCSSValuePtr(const RefPtr<CSSValueType>& first, const RefPtr<C return first ? second && first->equals(*second) : !second; } +template<typename CSSValueType> +inline bool compareCSSValuePtr(const RawPtr<CSSValueType>& first, const RawPtr<CSSValueType>& second) +{ + return first ? second && first->equals(*second) : !second; +} + +template<typename CSSValueType> +inline bool compareCSSValuePtr(const Member<CSSValueType>& first, const Member<CSSValueType>& second) +{ + return first ? second && first->equals(*second) : !second; +} + #define DEFINE_CSS_VALUE_TYPE_CASTS(thisType, predicate) \ DEFINE_TYPE_CASTS(thisType, CSSValue, value, value->predicate, value.predicate) diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValue.idl b/chromium/third_party/WebKit/Source/core/css/CSSValue.idl index dfdacd3a828..145010b29bb 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValue.idl +++ b/chromium/third_party/WebKit/Source/core/css/CSSValue.idl @@ -21,6 +21,7 @@ [ Custom=Wrap, DependentLifetime, + WillBeGarbageCollected, ] interface CSSValue { // UnitTypes diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValueKeywords.in b/chromium/third_party/WebKit/Source/core/css/CSSValueKeywords.in index c2c3a1b4765..c8512398070 100755..100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValueKeywords.in +++ b/chromium/third_party/WebKit/Source/core/css/CSSValueKeywords.in @@ -9,10 +9,11 @@ inherit initial // -// CSS_PROP_OUTLINE_STYLE -// CSS_PROP_BORDER_TOP_STYLE -// CSS_PROP_BORDER_BOTTOM_STYLE -// CSS_PROP_BORDER_LEFT_STYLE +// outline-style +// border-top-style +// border-bottom-style +// border-left-style +// border-right-style // The order here must match the order of the EBorderStyle enum in RenderStyleConstants.h. none hidden @@ -26,7 +27,7 @@ solid double // -// CSS_PROP_FONT: +// font // caption icon @@ -39,20 +40,21 @@ small-caption status-bar // -// CSS_PROP_FONT_STYLE: +// font-style // //normal italic oblique // The following is only allowed in @font-face: all + // -// CSS_PROP_FONT_VARIANT: +// font-variant // //normal small-caps -// -webkit-font-variant-ligatures: +// font-variant-ligatures: // // normal common-ligatures @@ -61,9 +63,11 @@ discretionary-ligatures no-discretionary-ligatures historical-ligatures no-historical-ligatures +contextual +no-contextual // -// CSS_PROP_FONT_WEIGHT: +// font-weigth // normal bold @@ -78,8 +82,9 @@ lighter 700 800 900 + // -// CSS_PROP_FONT_SIZE: +// font-size // xx-small x-small @@ -91,22 +96,9 @@ xx-large -webkit-xxx-large smaller larger + // -// CSS_PROP_FONT_STRETCH: -// -//normal -wider -narrower -ultra-condensed -extra-condensed -condensed -semi-condensed -semi-expanded -expanded -extra-expanded -ultra-expanded -// -// CSS_PROP_GENERIC_FONT_FAMILY: +// font-family (<generic-family> in CSS 2.1) // serif sans-serif @@ -115,9 +107,10 @@ fantasy monospace -webkit-body -webkit-pictograph + // // -// CSS_PROP_*_COLOR +// *-color // aqua black @@ -177,7 +170,7 @@ grey // colors in non strict mode -webkit-text mode=QuirksOrUASheet // -// CSS_PROP_BACKGROUND_REPEAT: +// background-repeat // repeat repeat-x @@ -186,7 +179,7 @@ no-repeat // round // space // -// CSS_PROP__WEBKIT_BACKGROUND_COMPOSITE: +// -webkit-background-composite // clear copy @@ -203,7 +196,7 @@ plus-darker // highlight plus-lighter // -// CSS_PROP_VERTICAL_ALIGN: +// vertical-align // baseline middle @@ -216,7 +209,7 @@ bottom // HTML alignment MIDDLE has no corresponding CSS alignment -webkit-baseline-middle // -// CSS_PROP_TEXT_ALIGN: +// text-align // The order here must match the order of the ETextAlign enum in RenderStyleConstants.h. // -webkit-auto @@ -229,19 +222,19 @@ justify -webkit-center -webkit-match-parent // -// CSS_PROP_TEXT_JUSTIFY: +// text-justify // //auto //none inter-word distribute // -// CSS_PROP_LIST_STYLE_POSITION: +// list-style-position // outside inside // -// CSS_PROP_LIST_STYLE_TYPE: +// list-style-type // The order here must match the order of the EListStyleType enum in RenderStyleConstants.h. // disc @@ -326,7 +319,7 @@ hiragana-iroha katakana-iroha //none // -// CSS_PROP_DISPLAY: +// display // The order here must match the order of the EDisplay enum in RenderStyleConstants.h. // inline @@ -349,12 +342,11 @@ flex inline-flex grid inline-grid -lazy-block //none -webkit-flex -webkit-inline-flex // -// CSS_PROP_CURSOR: +// cursor // The order here must match the order of the ECursor enum in RenderStyleConstants.h. // auto @@ -370,8 +362,8 @@ alias progress no-drop not-allowed --webkit-zoom-in --webkit-zoom-out +zoom-in +zoom-out e-resize ne-resize nw-resize @@ -392,21 +384,23 @@ help all-scroll -webkit-grab -webkit-grabbing +-webkit-zoom-in +-webkit-zoom-out // none // -// CSS_PROP_DIRECTION: +// direction // ltr rtl // -// CSS_PROP_TEXT_TRANSFORM: +// text-transform // capitalize uppercase lowercase //none // -// CSS_PROP_VISIBILITY: +// visibility // visible //hidden @@ -428,13 +422,10 @@ bidi-override blink both close-quote -crop -cross embed fixed hand hide -higher invert -webkit-isolate -webkit-isolate-override @@ -443,12 +434,8 @@ landscape ledger legal letter -level line-through local -loud -lower -mix no-close-quote no-open-quote nowrap @@ -472,38 +459,38 @@ wavy -webkit-nowrap // CSS3 Values -// CSS_PROP_BOX_ALIGN +// box-align stretch start end //center //baseline -// CSS_PROP_BOX_DECORATION_BREAK +// box-decoration-break clone slice -// CSS_PROP_BOX_DIRECTION +// box-direction // normal reverse -// CSS_PROP_BOX_ORIENT +// box-orient horizontal vertical inline-axis block-axis -// CSS_PROP_BOX_PACK +// box-pack // start // end // center // justify -// CSS_PROP_BOX_LINES +// box-lines single multiple -// CSS_PROP_ALIGN_CONTENT +// align-content flex-start flex-end // center @@ -511,21 +498,21 @@ space-between space-around // stretch -// CSS_PROP_ALIGN_ITEMS / CSS_PROP_ALIGN_SELF +// align-items / align-self // flex-start // flex-end // center // baseline // stretch -// CSS_PROP_JUSTIFY_CONTENT +// justify-content // flex-start // flex-end // center // space-between // space-around -// CSS_PROP_FLEX_FLOW +// flex-flow row row-reverse column @@ -534,7 +521,7 @@ column-reverse // wrap wrap-reverse -// CSS_PROP_MARQUEE_DIRECTION +// -internal-marquee-direction forwards backwards ahead @@ -545,39 +532,34 @@ up down // auto -// CSS_PROP_MARQUEE_SPEED +// -internal-marquee-speed slow // normal fast -// CSS_PROP_MARQUEE_REPETITION +// -internal-marquee-repetition infinite -// CSS_PROP_MARQUEE_STYLE +// -internal-marquee-style // none slide // scroll alternate // -// CSS_PROP__KHTML_USER_MODIFY +// -webkit-user-modify // read-only read-write read-write-plaintext-only // -// CSS_PROP__KHTML_USER_DRAG +// -webkit-user-drag // element // -// CSS_PROP__KHTML_USER_SELECT -// -ignore - -// -// CSS_PROP_WIDTH/MIN_WIDTH/MAX_WIDTH +// width/min-width/max-width // intrinsic min-intrinsic @@ -594,48 +576,48 @@ min-content max-content // -// CSS_PROP_TEXT_OVERFLOW +// text-overflow // clip ellipsis // -// CSS_PROP__KHTML_MARGIN_COLLAPSE +// -webkit-margin-collapse // // collapse // separate discard // -// CSS_PROP_TEXT_*_COLOR +// text-*-color // dot-dash dot-dot-dash wave // -// CSS_PROP_TEXT_*_MODE +// text-*-mode // continuous skip-white-space // -// CSS_PROP_WORD_BREAK +// word-break // break-all // -// CSS_PROP_WORD_WRAP +// word-wrap // break-word // -// CSS_PROP__KHTML_NBSP_MODE +// nbsp-mode // space // -// CSS_PROP__KHTML_LINE_BREAK +// -webkit-line-break // // auto loose @@ -653,7 +635,6 @@ square-button button button-bevel inner-spin-button --webkit-input-speech-button listbox listitem media-enter-fullscreen-button @@ -663,17 +644,12 @@ media-fullscreen-volume-slider-thumb media-mute-button media-play-button media-overlay-play-button -media-seek-back-button -media-seek-forward-button -media-rewind-button -media-return-to-realtime-button media-toggle-closed-captions-button media-slider media-sliderthumb media-volume-slider-container media-volume-slider media-volume-sliderthumb -media-volume-slider-mute-button media-controls-background media-controls-fullscreen-background media-current-time-display @@ -704,14 +680,14 @@ textarea caps-lock-indicator // -// CSS_PROP_BORDER_IMAGE +// border-image // // stretch // repeat round // -// CSS_PROP_BACKGROUND_CLIP/ORIGIN +// background-clip/background-origin // // border/content/padding are deprecated and ultimately will only apply to the -webkit- form of these properties. // border-box/content-box/padding-box should be used instead. @@ -723,7 +699,7 @@ content-box padding padding-box -// CSS_SHAPES +// CSS 3 SHAPES margin-box // @@ -733,50 +709,50 @@ contain cover // -// CSS_PROP__KHTML_RTL_ORDERING +// -webkit-rtl-ordering // logical visual // -// CSS_PROP__WEBKIT_BORDER_FIT +// -webkit-border-fit // lines // -// CSS_PROP__WEBKIT_ANIMATION_DIRECTION +// animation-direction // // alternate alternate-reverse // -// CSS_PROP__WEBKIT_ANIMATION_FILL_MODE +// animation-fill-mode // // forwards // backwards // both // -// CSS_PROP__WEBKIT_ANIMATION_ITERATION_COUNT +// animation-iteration-count // // infinite // -// CSS_PROP__WEBKIT_ANIMATION_PLAY_STATE +// animation-play-state // running paused // -// CSS_PROP__WEBKIT_TRANSFORM_STYLE +// transform-style // flat preserve-3d // -// CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION -// CSS_PROP__WEBKIT_ANIMATION_TIMING_FUNCTION +// transition-timing-function +// animation-timing-function // ease linear @@ -784,22 +760,23 @@ ease-in ease-out ease-in-out step-start +step-middle step-end // -// CSS_PROP_ZOOM +// zoom // document reset // -// CSS_PROP_USER_ZOOM +// user-zoom // // fixed zoom // -// CSS_PROP_POINTER_EVENTS +// pointer-events // visiblePainted visibleFill @@ -813,7 +790,7 @@ bounding-box //none // -// CSS_PROP_SPEECH +// speech // spell-out digits @@ -838,16 +815,6 @@ geometricPrecision economy exact -// (-webkit-view-mode:) media feature: -floating -fullscreen -maximized -minimized -windowed - -// -webkit-hyphenate-limit-lines -no-limit - // -webkit-writing-mode // SVG compatibility lr @@ -911,15 +878,12 @@ off optimizeQuality -webkit-optimize-contrast -// shape-inside // shape-outside nonzero evenodd -outside-shape - -// -webkit-region-fragment -// auto -break +at +// closest-side +// farthest-side // -webkit-wrap-flow // auto @@ -933,9 +897,6 @@ maximum wrap // none -// -webkit-line-align -edges - alphabetic // position @@ -946,13 +907,6 @@ sticky coarse fine -// -webkit-filter -// values for the custom() function -// border-box -// padding-box -// content-box -filter-box -detached // blend modes // normal multiply @@ -985,17 +939,20 @@ balance drag no-drag -// -webkit-grid-{start|end|before|after} +// grid-{column|row}-{start|end} span // text-indent each-line +//hanging // hanging exists in SVGCSSValueKeywords.in // (scan:) media feature progressive interlace -// CSS_PROP_PAINT_ORDER +// +// paint-order +// // normal // fill // stroke @@ -1017,3 +974,34 @@ script // touch-action pan-x pan-y +manipulation + +// justify-self +// auto +// stretch +// baseline +// center +// start +// end +self-start +self-end +// flex-start +// flex-end +// left +// right +true +safe + +// scroll-behavior +instant +smooth + +// will-change +// auto +contents +scroll-position + +// all +// initial +// inherit +unset diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValueList.cpp b/chromium/third_party/WebKit/Source/core/css/CSSValueList.cpp index e1505c2e504..9d31f6bdf5b 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValueList.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSValueList.cpp @@ -53,7 +53,7 @@ bool CSSValueList::removeAll(CSSValue* val) { bool found = false; for (size_t index = 0; index < m_values.size(); index++) { - RefPtr<CSSValue>& value = m_values.at(index); + RefPtrWillBeMember<CSSValue>& value = m_values.at(index); if (value && val && value->equals(*val)) { m_values.remove(index); found = true; @@ -66,16 +66,16 @@ bool CSSValueList::removeAll(CSSValue* val) bool CSSValueList::hasValue(CSSValue* val) const { for (size_t index = 0; index < m_values.size(); index++) { - const RefPtr<CSSValue>& value = m_values.at(index); + const RefPtrWillBeMember<CSSValue>& value = m_values.at(index); if (value && val && value->equals(*val)) return true; } return false; } -PassRefPtr<CSSValueList> CSSValueList::copy() +PassRefPtrWillBeRawPtr<CSSValueList> CSSValueList::copy() { - RefPtr<CSSValueList> newList; + RefPtrWillBeRawPtr<CSSValueList> newList = nullptr; switch (m_valueListSeparator) { case SpaceSeparator: newList = createSpaceSeparated(); @@ -127,9 +127,7 @@ String CSSValueList::customCSSText(CSSTextFormattingFlags formattingFlag) const bool CSSValueList::equals(const CSSValueList& other) const { - // FIXME: the explicit Vector conversion copies into a temporary and is - // wasteful. - return m_valueListSeparator == other.m_valueListSeparator && compareCSSValueVector<CSSValue>(Vector<RefPtr<CSSValue> >(m_values), Vector<RefPtr<CSSValue> >(other.m_values)); + return m_valueListSeparator == other.m_valueListSeparator && compareCSSValueVector(m_values, other.m_values); } bool CSSValueList::equals(const CSSValue& other) const @@ -137,45 +135,10 @@ bool CSSValueList::equals(const CSSValue& other) const if (m_values.size() != 1) return false; - const RefPtr<CSSValue>& value = m_values[0]; + const RefPtrWillBeMember<CSSValue>& value = m_values[0]; return value && value->equals(other); } -String CSSValueList::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const -{ - StringBuilder result; - String separator; - switch (m_valueListSeparator) { - case SpaceSeparator: - separator = " "; - break; - case CommaSeparator: - separator = ", "; - break; - case SlashSeparator: - separator = " / "; - break; - default: - ASSERT_NOT_REACHED(); - } - - unsigned size = m_values.size(); - for (unsigned i = 0; i < size; i++) { - if (!result.isEmpty()) - result.append(separator); - result.append(m_values[i]->serializeResolvingVariables(variables)); - } - - return result.toString(); -} - -void CSSValueList::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const -{ - size_t size = m_values.size(); - for (size_t i = 0; i < size; ++i) - m_values[i]->addSubresourceStyleURLs(urls, styleSheet); -} - bool CSSValueList::hasFailedOrCanceledSubresources() const { for (unsigned i = 0; i < m_values.size(); ++i) { @@ -194,9 +157,15 @@ CSSValueList::CSSValueList(const CSSValueList& cloneFrom) m_values[i] = cloneFrom.m_values[i]->cloneForCSSOM(); } -PassRefPtr<CSSValueList> CSSValueList::cloneForCSSOM() const +PassRefPtrWillBeRawPtr<CSSValueList> CSSValueList::cloneForCSSOM() const +{ + return adoptRefWillBeNoop(new CSSValueList(*this)); +} + +void CSSValueList::traceAfterDispatch(Visitor* visitor) { - return adoptRef(new CSSValueList(*this)); + visitor->trace(m_values); + CSSValue::traceAfterDispatch(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValueList.h b/chromium/third_party/WebKit/Source/core/css/CSSValueList.h index 2f08014f190..2d34b4f9406 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValueList.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSValueList.h @@ -31,21 +31,21 @@ class CSSParserValueList; class CSSValueList : public CSSValue { public: - static PassRefPtr<CSSValueList> createCommaSeparated() + static PassRefPtrWillBeRawPtr<CSSValueList> createCommaSeparated() { - return adoptRef(new CSSValueList(CommaSeparator)); + return adoptRefWillBeNoop(new CSSValueList(CommaSeparator)); } - static PassRefPtr<CSSValueList> createSpaceSeparated() + static PassRefPtrWillBeRawPtr<CSSValueList> createSpaceSeparated() { - return adoptRef(new CSSValueList(SpaceSeparator)); + return adoptRefWillBeNoop(new CSSValueList(SpaceSeparator)); } - static PassRefPtr<CSSValueList> createSlashSeparated() + static PassRefPtrWillBeRawPtr<CSSValueList> createSlashSeparated() { - return adoptRef(new CSSValueList(SlashSeparator)); + return adoptRefWillBeNoop(new CSSValueList(SlashSeparator)); } - static PassRefPtr<CSSValueList> createFromParserValueList(CSSParserValueList* list) + static PassRefPtrWillBeRawPtr<CSSValueList> createFromParserValueList(CSSParserValueList* list) { - return adoptRef(new CSSValueList(list)); + return adoptRefWillBeNoop(new CSSValueList(list)); } size_t length() const { return m_values.size(); } @@ -53,22 +53,21 @@ public: const CSSValue* item(size_t index) const { return index < m_values.size() ? m_values[index].get() : 0; } CSSValue* itemWithoutBoundsCheck(size_t index) { return m_values[index].get(); } - void append(PassRefPtr<CSSValue> value) { m_values.append(value); } - void prepend(PassRefPtr<CSSValue> value) { m_values.prepend(value); } + void append(PassRefPtrWillBeRawPtr<CSSValue> value) { m_values.append(value); } + void prepend(PassRefPtrWillBeRawPtr<CSSValue> value) { m_values.prepend(value); } bool removeAll(CSSValue*); bool hasValue(CSSValue*) const; - PassRefPtr<CSSValueList> copy(); + PassRefPtrWillBeRawPtr<CSSValueList> copy(); String customCSSText(CSSTextFormattingFlags = QuoteCSSStringIfNeeded) const; bool equals(const CSSValueList&) const; bool equals(const CSSValue&) const; - String customSerializeResolvingVariables(const HashMap<AtomicString, String>&) const; - - void addSubresourceStyleURLs(ListHashSet<KURL>&, const StyleSheetContents*) const; bool hasFailedOrCanceledSubresources() const; - PassRefPtr<CSSValueList> cloneForCSSOM() const; + PassRefPtrWillBeRawPtr<CSSValueList> cloneForCSSOM() const; + + void traceAfterDispatch(Visitor*); protected: CSSValueList(ClassType, ValueListSeparator); @@ -78,7 +77,7 @@ private: explicit CSSValueList(ValueListSeparator); explicit CSSValueList(CSSParserValueList*); - Vector<RefPtr<CSSValue>, 4> m_values; + WillBeHeapVector<RefPtrWillBeMember<CSSValue>, 4> m_values; }; DEFINE_CSS_VALUE_TYPE_CASTS(CSSValueList, isValueList()); @@ -86,6 +85,7 @@ DEFINE_CSS_VALUE_TYPE_CASTS(CSSValueList, isValueList()); // Objects of this class are intended to be stack-allocated and scoped to a single function. // Please take care not to pass these around as they do hold onto a raw pointer. class CSSValueListInspector { + STACK_ALLOCATED(); public: CSSValueListInspector(CSSValue* value) : m_list((value && value->isValueList()) ? toCSSValueList(value) : 0) { } CSSValue* item(size_t index) const { ASSERT_WITH_SECURITY_IMPLICATION(index < length()); return m_list->itemWithoutBoundsCheck(index); } @@ -93,13 +93,14 @@ public: CSSValue* second() const { return item(1); } size_t length() const { return m_list ? m_list->length() : 0; } private: - CSSValueList* m_list; + RawPtrWillBeMember<CSSValueList> m_list; }; // Wrapper that can be used to iterate over any CSSValue. Non-list values and 0 behave as zero-length lists. // Objects of this class are intended to be stack-allocated and scoped to a single function. // Please take care not to pass these around as they do hold onto a raw pointer. class CSSValueListIterator { + STACK_ALLOCATED(); public: CSSValueListIterator(CSSValue* value) : m_inspector(value), m_position(0) { } bool hasMore() const { return m_position < m_inspector.length(); } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValuePool.cpp b/chromium/third_party/WebKit/Source/core/css/CSSValuePool.cpp index 4550915eba4..3d914d33198 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValuePool.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSValuePool.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "core/css/CSSValuePool.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSValueList.h" #include "core/rendering/style/RenderStyle.h" @@ -34,8 +34,13 @@ namespace WebCore { CSSValuePool& cssValuePool() { +#if ENABLE(OILPAN) + DEFINE_STATIC_LOCAL(Persistent<CSSValuePool>, pool, (new CSSValuePool())); + return *pool; +#else DEFINE_STATIC_LOCAL(CSSValuePool, pool, ()); return pool; +#endif // ENABLE(OILPAN) } CSSValuePool::CSSValuePool() @@ -46,9 +51,13 @@ CSSValuePool::CSSValuePool() , m_colorWhite(CSSPrimitiveValue::createColor(Color::white)) , m_colorBlack(CSSPrimitiveValue::createColor(Color::black)) { + m_identifierValueCache.resize(numCSSValueKeywords); + m_pixelValueCache.resize(maximumCacheableIntegerValue + 1); + m_percentValueCache.resize(maximumCacheableIntegerValue + 1); + m_numberValueCache.resize(maximumCacheableIntegerValue + 1); } -PassRefPtr<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSValueID ident) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSValueID ident) { if (ident <= 0) return CSSPrimitiveValue::createIdentifier(ident); @@ -58,12 +67,12 @@ PassRefPtr<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSValueID ide return m_identifierValueCache[ident]; } -PassRefPtr<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSPropertyID ident) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSValuePool::createIdentifierValue(CSSPropertyID ident) { return CSSPrimitiveValue::createIdentifier(ident); } -PassRefPtr<CSSPrimitiveValue> CSSValuePool::createColorValue(unsigned rgbValue) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSValuePool::createColorValue(unsigned rgbValue) { // These are the empty and deleted values of the hash table. if (rgbValue == Color::transparent) @@ -79,15 +88,18 @@ PassRefPtr<CSSPrimitiveValue> CSSValuePool::createColorValue(unsigned rgbValue) if (m_colorValueCache.size() > maximumColorCacheSize) m_colorValueCache.clear(); - RefPtr<CSSPrimitiveValue> dummyValue; + RefPtrWillBeRawPtr<CSSPrimitiveValue> dummyValue = nullptr; ColorValueCache::AddResult entry = m_colorValueCache.add(rgbValue, dummyValue); if (entry.isNewEntry) - entry.iterator->value = CSSPrimitiveValue::createColor(rgbValue); - return entry.iterator->value; + entry.storedValue->value = CSSPrimitiveValue::createColor(rgbValue); + return entry.storedValue->value; } -PassRefPtr<CSSPrimitiveValue> CSSValuePool::createValue(double value, CSSPrimitiveValue::UnitTypes type) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSValuePool::createValue(double value, CSSPrimitiveValue::UnitType type) { + if (std::isinf(value)) + value = 0; + if (value < 0 || value > maximumCacheableIntegerValue) return CSSPrimitiveValue::create(value, type); @@ -95,50 +107,65 @@ PassRefPtr<CSSPrimitiveValue> CSSValuePool::createValue(double value, CSSPrimiti if (value != intValue) return CSSPrimitiveValue::create(value, type); - RefPtr<CSSPrimitiveValue>* cache; switch (type) { case CSSPrimitiveValue::CSS_PX: - cache = m_pixelValueCache; - break; + if (!m_pixelValueCache[intValue]) + m_pixelValueCache[intValue] = CSSPrimitiveValue::create(value, type); + return m_pixelValueCache[intValue]; case CSSPrimitiveValue::CSS_PERCENTAGE: - cache = m_percentValueCache; - break; + if (!m_percentValueCache[intValue]) + m_percentValueCache[intValue] = CSSPrimitiveValue::create(value, type); + return m_percentValueCache[intValue]; case CSSPrimitiveValue::CSS_NUMBER: - cache = m_numberValueCache; - break; + if (!m_numberValueCache[intValue]) + m_numberValueCache[intValue] = CSSPrimitiveValue::create(value, type); + return m_numberValueCache[intValue]; default: return CSSPrimitiveValue::create(value, type); } - - if (!cache[intValue]) - cache[intValue] = CSSPrimitiveValue::create(value, type); - return cache[intValue]; } -PassRefPtr<CSSPrimitiveValue> CSSValuePool::createValue(const Length& value, const RenderStyle& style) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSValuePool::createValue(const Length& value, const RenderStyle& style) { return CSSPrimitiveValue::create(value, style.effectiveZoom()); } -PassRefPtr<CSSPrimitiveValue> CSSValuePool::createFontFamilyValue(const String& familyName) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSValuePool::createFontFamilyValue(const String& familyName) { - RefPtr<CSSPrimitiveValue>& value = m_fontFamilyValueCache.add(familyName, 0).iterator->value; + RefPtrWillBeMember<CSSPrimitiveValue>& value = m_fontFamilyValueCache.add(familyName, nullptr).storedValue->value; if (!value) value = CSSPrimitiveValue::create(familyName, CSSPrimitiveValue::CSS_STRING); return value; } -PassRefPtr<CSSValueList> CSSValuePool::createFontFaceValue(const AtomicString& string) +PassRefPtrWillBeRawPtr<CSSValueList> CSSValuePool::createFontFaceValue(const AtomicString& string) { // Just wipe out the cache and start rebuilding if it gets too big. const unsigned maximumFontFaceCacheSize = 128; if (m_fontFaceValueCache.size() > maximumFontFaceCacheSize) m_fontFaceValueCache.clear(); - RefPtr<CSSValueList>& value = m_fontFaceValueCache.add(string, 0).iterator->value; + RefPtrWillBeMember<CSSValueList>& value = m_fontFaceValueCache.add(string, nullptr).storedValue->value; if (!value) - value = CSSParser::parseFontFaceValue(string); + value = BisonCSSParser::parseFontFaceValue(string); return value; } +void CSSValuePool::trace(Visitor* visitor) +{ + visitor->trace(m_inheritedValue); + visitor->trace(m_implicitInitialValue); + visitor->trace(m_explicitInitialValue); + visitor->trace(m_identifierValueCache); + visitor->trace(m_colorValueCache); + visitor->trace(m_colorTransparent); + visitor->trace(m_colorWhite); + visitor->trace(m_colorBlack); + visitor->trace(m_pixelValueCache); + visitor->trace(m_percentValueCache); + visitor->trace(m_numberValueCache); + visitor->trace(m_fontFaceValueCache); + visitor->trace(m_fontFamilyValueCache); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/CSSValuePool.h b/chromium/third_party/WebKit/Source/core/css/CSSValuePool.h index 75b8984a1f7..87eacf6d385 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSValuePool.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSValuePool.h @@ -26,8 +26,8 @@ #ifndef CSSValuePool_h #define CSSValuePool_h -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" #include "core/css/CSSInheritedValue.h" #include "core/css/CSSInitialValue.h" #include "core/css/CSSPrimitiveValue.h" @@ -39,48 +39,50 @@ namespace WebCore { class CSSValueList; -class CSSValuePool { - WTF_MAKE_FAST_ALLOCATED; +class CSSValuePool : public NoBaseWillBeGarbageCollected<CSSValuePool> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - PassRefPtr<CSSValueList> createFontFaceValue(const AtomicString&); - PassRefPtr<CSSPrimitiveValue> createFontFamilyValue(const String&); - PassRefPtr<CSSInheritedValue> createInheritedValue() { return m_inheritedValue; } - PassRefPtr<CSSInitialValue> createImplicitInitialValue() { return m_implicitInitialValue; } - PassRefPtr<CSSInitialValue> createExplicitInitialValue() { return m_explicitInitialValue; } - PassRefPtr<CSSPrimitiveValue> createIdentifierValue(CSSValueID identifier); - PassRefPtr<CSSPrimitiveValue> createIdentifierValue(CSSPropertyID identifier); - PassRefPtr<CSSPrimitiveValue> createColorValue(unsigned rgbValue); - PassRefPtr<CSSPrimitiveValue> createValue(double value, CSSPrimitiveValue::UnitTypes); - PassRefPtr<CSSPrimitiveValue> createValue(const String& value, CSSPrimitiveValue::UnitTypes type) { return CSSPrimitiveValue::create(value, type); } - PassRefPtr<CSSPrimitiveValue> createValue(const Length& value, const RenderStyle&); - PassRefPtr<CSSPrimitiveValue> createValue(const Length& value, float zoom) { return CSSPrimitiveValue::create(value, zoom); } - template<typename T> static PassRefPtr<CSSPrimitiveValue> createValue(T value) { return CSSPrimitiveValue::create(value); } + PassRefPtrWillBeRawPtr<CSSValueList> createFontFaceValue(const AtomicString&); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createFontFamilyValue(const String&); + PassRefPtrWillBeRawPtr<CSSInheritedValue> createInheritedValue() { return m_inheritedValue; } + PassRefPtrWillBeRawPtr<CSSInitialValue> createImplicitInitialValue() { return m_implicitInitialValue; } + PassRefPtrWillBeRawPtr<CSSInitialValue> createExplicitInitialValue() { return m_explicitInitialValue; } + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifierValue(CSSValueID identifier); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createIdentifierValue(CSSPropertyID identifier); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createColorValue(unsigned rgbValue); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createValue(double value, CSSPrimitiveValue::UnitType); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createValue(const String& value, CSSPrimitiveValue::UnitType type) { return CSSPrimitiveValue::create(value, type); } + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createValue(const Length& value, const RenderStyle&); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createValue(const Length& value, float zoom) { return CSSPrimitiveValue::create(value, zoom); } + template<typename T> static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createValue(T value) { return CSSPrimitiveValue::create(value); } + + void trace(Visitor*); private: CSSValuePool(); - RefPtr<CSSInheritedValue> m_inheritedValue; - RefPtr<CSSInitialValue> m_implicitInitialValue; - RefPtr<CSSInitialValue> m_explicitInitialValue; + RefPtrWillBeMember<CSSInheritedValue> m_inheritedValue; + RefPtrWillBeMember<CSSInitialValue> m_implicitInitialValue; + RefPtrWillBeMember<CSSInitialValue> m_explicitInitialValue; - RefPtr<CSSPrimitiveValue> m_identifierValueCache[numCSSValueKeywords]; + WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue>, numCSSValueKeywords> m_identifierValueCache; - typedef HashMap<unsigned, RefPtr<CSSPrimitiveValue> > ColorValueCache; + typedef WillBeHeapHashMap<unsigned, RefPtrWillBeMember<CSSPrimitiveValue> > ColorValueCache; ColorValueCache m_colorValueCache; - RefPtr<CSSPrimitiveValue> m_colorTransparent; - RefPtr<CSSPrimitiveValue> m_colorWhite; - RefPtr<CSSPrimitiveValue> m_colorBlack; + RefPtrWillBeMember<CSSPrimitiveValue> m_colorTransparent; + RefPtrWillBeMember<CSSPrimitiveValue> m_colorWhite; + RefPtrWillBeMember<CSSPrimitiveValue> m_colorBlack; static const int maximumCacheableIntegerValue = 255; - RefPtr<CSSPrimitiveValue> m_pixelValueCache[maximumCacheableIntegerValue + 1]; - RefPtr<CSSPrimitiveValue> m_percentValueCache[maximumCacheableIntegerValue + 1]; - RefPtr<CSSPrimitiveValue> m_numberValueCache[maximumCacheableIntegerValue + 1]; + WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_pixelValueCache; + WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_percentValueCache; + WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue>, maximumCacheableIntegerValue + 1> m_numberValueCache; - typedef HashMap<AtomicString, RefPtr<CSSValueList> > FontFaceValueCache; + typedef WillBeHeapHashMap<AtomicString, RefPtrWillBeMember<CSSValueList> > FontFaceValueCache; FontFaceValueCache m_fontFaceValueCache; - typedef HashMap<String, RefPtr<CSSPrimitiveValue> > FontFamilyValueCache; + typedef WillBeHeapHashMap<String, RefPtrWillBeMember<CSSPrimitiveValue> > FontFamilyValueCache; FontFamilyValueCache m_fontFamilyValueCache; friend CSSValuePool& cssValuePool(); diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariableValue.h b/chromium/third_party/WebKit/Source/core/css/CSSVariableValue.h deleted file mode 100644 index 525581ae19c..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariableValue.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CSSVariableValue_h -#define CSSVariableValue_h - -#include "CSSPropertyNames.h" -#include "core/css/CSSParserValues.h" -#include "core/css/CSSValue.h" - -namespace WebCore { - -class CSSVariableValue : public CSSValue { -public: - static PassRefPtr<CSSVariableValue> create(const AtomicString& name, const String& value) - { - return adoptRef(new CSSVariableValue(name, value)); - } - - const AtomicString& name() const { return m_name; } - const String& value() const { return m_value; } - - bool equals(const CSSVariableValue& other) const { return m_name == other.m_name && m_value == other.m_value; } - -private: - CSSVariableValue(const AtomicString& name, const String& value) - : CSSValue(VariableClass) - , m_name(name) - , m_value(value) - { - } - - const AtomicString m_name; - const String m_value; -}; - -DEFINE_CSS_VALUE_TYPE_CASTS(CSSVariableValue, isVariableValue()); - -} - -#endif /* CSSVariableValue_h */ diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariablesIterator.h b/chromium/third_party/WebKit/Source/core/css/CSSVariablesIterator.h deleted file mode 100644 index edfe3a7e9ed..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariablesIterator.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2013 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: - * - * * 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. - */ - -#ifndef CSSVariablesIterator_h -#define CSSVariablesIterator_h - -#include "wtf/RefCounted.h" - -namespace WebCore { - -class CSSVariablesIterator : public RefCounted<CSSVariablesIterator> { -public: - virtual ~CSSVariablesIterator() { } - virtual void advance() = 0; - virtual bool atEnd() const = 0; - virtual AtomicString name() const = 0; - virtual String value() const = 0; - virtual void addedVariable(const AtomicString& name) { } - virtual void removedVariable(const AtomicString& name) { } - virtual void clearedVariables() { } -}; - -} - -#endif // CSSVariablesIterator_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.cpp b/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.cpp deleted file mode 100644 index eb6232dd43a..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2013 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "core/css/CSSVariablesMap.h" - -#include "core/css/CSSStyleDeclaration.h" - -namespace WebCore { - -unsigned CSSVariablesMap::size() const -{ - if (m_styleDeclaration) - return m_styleDeclaration->variableCount(); - return 0; -} - -String CSSVariablesMap::get(const AtomicString& name) const -{ - if (m_styleDeclaration) - return m_styleDeclaration->variableValue(name); - return String(); -} - -bool CSSVariablesMap::has(const AtomicString& name) const -{ - if (m_styleDeclaration) - return !get(name).isEmpty(); - return false; -} - -void CSSVariablesMap::set(const AtomicString& name, const String& value, ExceptionState& exceptionState) -{ - if (!m_styleDeclaration) - return; - if (m_styleDeclaration->setVariableValue(name, value, exceptionState)) { - Iterators::iterator end = m_activeIterators.end(); - for (Iterators::iterator it = m_activeIterators.begin(); it != end; ++it) - (*it)->addedVariable(name); - } -} - -bool CSSVariablesMap::remove(const AtomicString& name) -{ - if (!m_styleDeclaration) - return false; - if (m_styleDeclaration->removeVariable(name)) { - Iterators::iterator end = m_activeIterators.end(); - for (Iterators::iterator it = m_activeIterators.begin(); it != end; ++it) - (*it)->removedVariable(name); - return true; - } - return false; -} - -void CSSVariablesMap::clear(ExceptionState& exceptionState) -{ - if (!m_styleDeclaration) - return; - if (m_styleDeclaration->clearVariables(exceptionState)) { - Iterators::iterator end = m_activeIterators.end(); - for (Iterators::iterator it = m_activeIterators.begin(); it != end; ++it) - (*it)->clearedVariables(); - } -} - -void CSSVariablesMap::forEach(PassOwnPtr<CSSVariablesMapForEachCallback> callback, ScriptValue& thisArg) const -{ - forEach(callback, &thisArg); -} - -void CSSVariablesMap::forEach(PassOwnPtr<CSSVariablesMapForEachCallback> callback) const -{ - forEach(callback, 0); -} - -void CSSVariablesMap::forEach(PassOwnPtr<CSSVariablesMapForEachCallback> callback, ScriptValue* thisArg) const -{ - if (!m_styleDeclaration) - return; - RefPtr<CSSVariablesIterator> iterator = m_styleDeclaration->variablesIterator(); - m_activeIterators.append(iterator.get()); - while (!iterator->atEnd()) { - String name = iterator->name(); - String value = iterator->value(); - if (thisArg) - callback->handleItem(*thisArg, value, name, const_cast<CSSVariablesMap*>(this)); - else - callback->handleItem(value, name, const_cast<CSSVariablesMap*>(this)); - iterator->advance(); - } - ASSERT(m_activeIterators.last() == iterator.get()); - m_activeIterators.removeLast(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.h b/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.h deleted file mode 100644 index 12b1bee2845..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2013 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: - * - * * 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. - */ - -#ifndef CSSVariablesMap_h -#define CSSVariablesMap_h - -#include "RuntimeEnabledFeatures.h" -#include "core/css/CSSVariablesMapForEachCallback.h" -#include "wtf/PassOwnPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/text/WTFString.h" - -namespace WebCore { - -class CSSStyleDeclaration; -class CSSVariablesIterator; -class ExceptionState; - -class CSSVariablesMap FINAL : public RefCounted<CSSVariablesMap> { -public: - static PassRefPtr<CSSVariablesMap> create(CSSStyleDeclaration* styleDeclaration) - { - return adoptRef(new CSSVariablesMap(styleDeclaration)); - } - - unsigned size() const; - String get(const AtomicString& name) const; - bool has(const AtomicString& name) const; - void set(const AtomicString& name, const String& value, ExceptionState&); - bool remove(const AtomicString& name); - void clear(ExceptionState&); - void forEach(PassOwnPtr<CSSVariablesMapForEachCallback>, ScriptValue& thisArg) const; - void forEach(PassOwnPtr<CSSVariablesMapForEachCallback>) const; - - void clearStyleDeclaration() { m_styleDeclaration = 0; } - -private: - explicit CSSVariablesMap(CSSStyleDeclaration* styleDeclaration) - : m_styleDeclaration(styleDeclaration) - { - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - } - - void forEach(PassOwnPtr<CSSVariablesMapForEachCallback>, ScriptValue* thisArg) const; - - CSSStyleDeclaration* m_styleDeclaration; - typedef Vector<CSSVariablesIterator*> Iterators; - mutable Iterators m_activeIterators; -}; - -} // namespace WebCore - -#endif // CSSVariablesMap_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.cpp b/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.cpp index a5d1f0e9cf9..9c56ee4a48b 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.cpp @@ -46,8 +46,10 @@ CSSViewportRule::CSSViewportRule(StyleRuleViewport* viewportRule, CSSStyleSheet* CSSViewportRule::~CSSViewportRule() { +#if !ENABLE(OILPAN) if (m_propertiesCSSOMWrapper) m_propertiesCSSOMWrapper->clearParentRule(); +#endif } CSSStyleDeclaration* CSSViewportRule::style() const @@ -63,7 +65,7 @@ String CSSViewportRule::cssText() const StringBuilder result; result.appendLiteral("@viewport { "); - String decls = m_viewportRule->properties()->asText(); + String decls = m_viewportRule->properties().asText(); result.append(decls); if (!decls.isEmpty()) result.append(' '); @@ -81,4 +83,11 @@ void CSSViewportRule::reattach(StyleRuleBase* rule) m_propertiesCSSOMWrapper->reattach(m_viewportRule->mutableProperties()); } +void CSSViewportRule::trace(Visitor* visitor) +{ + visitor->trace(m_viewportRule); + visitor->trace(m_propertiesCSSOMWrapper); + CSSRule::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.h b/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.h index 2ef8c81511f..20a84b5c73a 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.h +++ b/chromium/third_party/WebKit/Source/core/css/CSSViewportRule.h @@ -32,6 +32,7 @@ #define CSSViewportRule_h #include "core/css/CSSRule.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -39,13 +40,13 @@ class CSSStyleDeclaration; class StyleRuleViewport; class StyleRuleCSSStyleDeclaration; -class CSSViewportRule: public CSSRule { +class CSSViewportRule FINAL: public CSSRule { public: - static PassRefPtr<CSSViewportRule> create(StyleRuleViewport* viewportRule, CSSStyleSheet* sheet) + static PassRefPtrWillBeRawPtr<CSSViewportRule> create(StyleRuleViewport* viewportRule, CSSStyleSheet* sheet) { - return adoptRef(new CSSViewportRule(viewportRule, sheet)); + return adoptRefWillBeNoop(new CSSViewportRule(viewportRule, sheet)); } - ~CSSViewportRule(); + virtual ~CSSViewportRule(); virtual CSSRule::Type type() const OVERRIDE { return VIEWPORT_RULE; } virtual String cssText() const OVERRIDE; @@ -53,11 +54,13 @@ public: CSSStyleDeclaration* style() const; + virtual void trace(Visitor*) OVERRIDE; + private: CSSViewportRule(StyleRuleViewport*, CSSStyleSheet*); - RefPtr<StyleRuleViewport> m_viewportRule; - mutable RefPtr<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; + RefPtrWillBeMember<StyleRuleViewport> m_viewportRule; + mutable RefPtrWillBeMember<StyleRuleCSSStyleDeclaration> m_propertiesCSSOMWrapper; }; DEFINE_CSS_RULE_TYPE_CASTS(CSSViewportRule, VIEWPORT_RULE); diff --git a/chromium/third_party/WebKit/Source/core/css/Counter.cpp b/chromium/third_party/WebKit/Source/core/css/Counter.cpp new file mode 100644 index 00000000000..d012b1a6c24 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/Counter.cpp @@ -0,0 +1,17 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/Counter.h" + +namespace WebCore { + +void Counter::trace(Visitor* visitor) +{ + visitor->trace(m_identifier); + visitor->trace(m_listStyle); + visitor->trace(m_separator); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/css/Counter.h b/chromium/third_party/WebKit/Source/core/css/Counter.h index cb73a3dd36d..68b3a7360fb 100644 --- a/chromium/third_party/WebKit/Source/core/css/Counter.h +++ b/chromium/third_party/WebKit/Source/core/css/Counter.h @@ -26,11 +26,11 @@ namespace WebCore { -class Counter : public RefCounted<Counter> { +class Counter : public RefCountedWillBeGarbageCollected<Counter> { public: - static PassRefPtr<Counter> create(PassRefPtr<CSSPrimitiveValue> identifier, PassRefPtr<CSSPrimitiveValue> listStyle, PassRefPtr<CSSPrimitiveValue> separator) + static PassRefPtrWillBeRawPtr<Counter> create(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> identifier, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> listStyle, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> separator) { - return adoptRef(new Counter(identifier, listStyle, separator)); + return adoptRefWillBeNoop(new Counter(identifier, listStyle, separator)); } String identifier() const { return m_identifier ? m_identifier->getStringValue() : String(); } @@ -39,9 +39,9 @@ public: CSSValueID listStyleIdent() const { return m_listStyle ? m_listStyle->getValueID() : CSSValueInvalid; } - void setIdentifier(PassRefPtr<CSSPrimitiveValue> identifier) { m_identifier = identifier; } - void setListStyle(PassRefPtr<CSSPrimitiveValue> listStyle) { m_listStyle = listStyle; } - void setSeparator(PassRefPtr<CSSPrimitiveValue> separator) { m_separator = separator; } + void setIdentifier(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> identifier) { m_identifier = identifier; } + void setListStyle(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> listStyle) { m_listStyle = listStyle; } + void setSeparator(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> separator) { m_separator = separator; } bool equals(const Counter& other) const { @@ -50,24 +50,26 @@ public: && separator() == other.separator(); } - PassRefPtr<Counter> cloneForCSSOM() const + PassRefPtrWillBeRawPtr<Counter> cloneForCSSOM() const { - return create(m_identifier ? m_identifier->cloneForCSSOM() : 0 - , m_listStyle ? m_listStyle->cloneForCSSOM() : 0 - , m_separator ? m_separator->cloneForCSSOM() : 0); + return create(m_identifier ? m_identifier->cloneForCSSOM() : nullptr + , m_listStyle ? m_listStyle->cloneForCSSOM() : nullptr + , m_separator ? m_separator->cloneForCSSOM() : nullptr); } + void trace(Visitor*); + private: - Counter(PassRefPtr<CSSPrimitiveValue> identifier, PassRefPtr<CSSPrimitiveValue> listStyle, PassRefPtr<CSSPrimitiveValue> separator) + Counter(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> identifier, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> listStyle, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> separator) : m_identifier(identifier) , m_listStyle(listStyle) , m_separator(separator) { } - RefPtr<CSSPrimitiveValue> m_identifier; // string - RefPtr<CSSPrimitiveValue> m_listStyle; // ident - RefPtr<CSSPrimitiveValue> m_separator; // string + RefPtrWillBeMember<CSSPrimitiveValue> m_identifier; // string + RefPtrWillBeMember<CSSPrimitiveValue> m_listStyle; // ident + RefPtrWillBeMember<CSSPrimitiveValue> m_separator; // string }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/Counter.idl b/chromium/third_party/WebKit/Source/core/css/Counter.idl index 7006aa5001d..886436eea9d 100644 --- a/chromium/third_party/WebKit/Source/core/css/Counter.idl +++ b/chromium/third_party/WebKit/Source/core/css/Counter.idl @@ -19,6 +19,7 @@ // Introduced in DOM Level 2: [ + WillBeGarbageCollected ] interface Counter { readonly attribute DOMString identifier; readonly attribute DOMString listStyle; diff --git a/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp b/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp index 248ddcc4648..d0edccaa075 100644 --- a/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp +++ b/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.cpp @@ -30,16 +30,16 @@ #include "config.h" #include "core/css/DOMWindowCSS.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/RuntimeCSSEnabled.h" #include "core/css/StylePropertySet.h" #include "wtf/text/WTFString.h" namespace WebCore { -PassRefPtr<DOMWindowCSS> DOMWindowCSS::create() +PassRefPtrWillBeRawPtr<DOMWindowCSS> DOMWindowCSS::create() { - return adoptRef(new DOMWindowCSS()); + return adoptRefWillBeNoop(new DOMWindowCSS()); } static String valueWithoutImportant(const String& value) @@ -65,7 +65,7 @@ bool DOMWindowCSS::supports(const String& property, const String& value) const if (!RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID)) return false; - // CSSParser::parseValue() won't work correctly if !important is present, + // BisonCSSParser::parseValue() won't work correctly if !important is present, // so just get rid of it. It doesn't matter to supports() if it's actually // there or not, provided how it's specified in the value is correct. String normalizedValue = value.stripWhiteSpace().simplifyWhiteSpace(); @@ -74,14 +74,14 @@ bool DOMWindowCSS::supports(const String& property, const String& value) const if (normalizedValue.isEmpty()) return false; - RefPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create(); - return CSSParser::parseValue(dummyStyle.get(), propertyID, normalizedValue, false, HTMLStandardMode, 0); + RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create(); + return BisonCSSParser::parseValue(dummyStyle.get(), propertyID, normalizedValue, false, HTMLStandardMode, 0); } bool DOMWindowCSS::supports(const String& conditionText) const { - CSSParserContext context(HTMLStandardMode); - CSSParser parser(context); + CSSParserContext context(HTMLStandardMode, 0); + BisonCSSParser parser(context); return parser.parseSupportsCondition(conditionText); } diff --git a/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.h b/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.h index e6c6d19b2dc..25a7eb6f9e7 100644 --- a/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.h +++ b/chromium/third_party/WebKit/Source/core/css/DOMWindowCSS.h @@ -30,19 +30,22 @@ #ifndef DOMWindowCSS_h #define DOMWindowCSS_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class DOMWindowCSS : public RefCounted<DOMWindowCSS> { +class DOMWindowCSS : public RefCountedWillBeGarbageCollected<DOMWindowCSS> { public: - static PassRefPtr<DOMWindowCSS> create(); + static PassRefPtrWillBeRawPtr<DOMWindowCSS> create(); bool supports(const String& property, const String& value) const; bool supports(const String& conditionText) const; + void trace(Visitor*) { } + private: DOMWindowCSS() { diff --git a/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.cpp b/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.cpp index 408668f70fc..2df6c3e27bc 100644 --- a/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.cpp +++ b/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.cpp @@ -30,7 +30,7 @@ namespace WebCore { -PassRefPtr<FontFaceSet> DocumentFontFaceSet::fonts(Document* document) +PassRefPtrWillBeRawPtr<FontFaceSet> DocumentFontFaceSet::fonts(Document& document) { return FontFaceSet::from(document); } diff --git a/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.h b/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.h index 910d878291e..b1ecf426d14 100644 --- a/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.h +++ b/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.h @@ -26,6 +26,7 @@ #ifndef DocumentFontFaceSet_h #define DocumentFontFaceSet_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" namespace WebCore { @@ -35,7 +36,7 @@ class FontFaceSet; class DocumentFontFaceSet { public: - static PassRefPtr<FontFaceSet> fonts(Document*); + static PassRefPtrWillBeRawPtr<FontFaceSet> fonts(Document&); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.idl b/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.idl index 820fdc899e9..6ed56abb6fb 100644 --- a/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.idl +++ b/chromium/third_party/WebKit/Source/core/css/DocumentFontFaceSet.idl @@ -28,6 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -partial interface Document { - [RuntimeEnabled=FontLoadEvents] readonly attribute FontFaceSet fonts; +[ + RuntimeEnabled=FontLoadEvents, +] partial interface Document { + [MeasureAs=DocumentFonts] readonly attribute FontFaceSet fonts; }; diff --git a/chromium/third_party/WebKit/Source/core/css/DragUpdateTest.cpp b/chromium/third_party/WebKit/Source/core/css/DragUpdateTest.cpp new file mode 100644 index 00000000000..c801b6b11bc --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/DragUpdateTest.cpp @@ -0,0 +1,69 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/dom/Element.h" +#include "core/frame/FrameView.h" +#include "core/html/HTMLDocument.h" +#include "core/html/HTMLElement.h" +#include "core/testing/DummyPageHolder.h" +#include <gtest/gtest.h> + +using namespace WebCore; + +namespace { + +TEST(DragUpdateTest, AffectedByDragUpdate) +{ + // Check that when dragging the div in the document below, you only get a + // single element style recalc. + + OwnPtr<DummyPageHolder> dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); + HTMLDocument* document = toHTMLDocument(&dummyPageHolder->document()); + document->documentElement()->setInnerHTML("<style>div {width:100px;height:100px} div:-webkit-drag { background-color: green }</style>" + "<div>" + "<span></span>" + "<span></span>" + "<span></span>" + "<span></span>" + "</div>", ASSERT_NO_EXCEPTION); + + document->view()->updateLayoutAndStyleIfNeededRecursive(); + unsigned startCount = document->styleEngine()->resolverAccessCount(); + + document->documentElement()->renderer()->updateDragState(true); + document->view()->updateLayoutAndStyleIfNeededRecursive(); + + unsigned accessCount = document->styleEngine()->resolverAccessCount() - startCount; + + ASSERT_EQ(1U, accessCount); +} + +TEST(DragUpdateTest, ChildrenOrSiblingsAffectedByDragUpdate) +{ + // Check that when dragging the div in the document below, you get a + // full subtree style recalc. + + OwnPtr<DummyPageHolder> dummyPageHolder = DummyPageHolder::create(IntSize(800, 600)); + HTMLDocument* document = toHTMLDocument(&dummyPageHolder->document()); + document->documentElement()->setInnerHTML("<style>div {width:100px;height:100px} div:-webkit-drag span { background-color: green }</style>" + "<div>" + "<span></span>" + "<span></span>" + "<span></span>" + "<span></span>" + "</div>", ASSERT_NO_EXCEPTION); + + document->updateLayout(); + unsigned startCount = document->styleEngine()->resolverAccessCount(); + + document->documentElement()->renderer()->updateDragState(true); + document->updateLayout(); + + unsigned accessCount = document->styleEngine()->resolverAccessCount() - startCount; + + ASSERT_EQ(5U, accessCount); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp b/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp index 4fdd44c8eb4..79ef923b697 100644 --- a/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp +++ b/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.cpp @@ -29,31 +29,32 @@ #include "config.h" #include "core/css/ElementRuleCollector.h" +#include "core/css/CSSImportRule.h" +#include "core/css/CSSKeyframesRule.h" +#include "core/css/CSSMediaRule.h" #include "core/css/CSSRuleList.h" #include "core/css/CSSSelector.h" #include "core/css/CSSStyleRule.h" #include "core/css/CSSStyleSheet.h" -#include "core/css/SelectorCheckerFastPath.h" +#include "core/css/CSSSupportsRule.h" #include "core/css/SiblingTraversalStrategies.h" #include "core/css/StylePropertySet.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/shadow/ShadowRoot.h" -#include "core/rendering/RenderRegion.h" +#include "core/rendering/style/StyleInheritedData.h" namespace WebCore { ElementRuleCollector::ElementRuleCollector(const ElementResolveContext& context, - const SelectorFilter& filter, RenderStyle* style, ShouldIncludeStyleSheetInCSSOMWrapper includeStyleSheet) + const SelectorFilter& filter, RenderStyle* style) : m_context(context) , m_selectorFilter(filter) , m_style(style) - , m_regionForStyling(0) , m_pseudoStyleRequest(NOPSEUDO) , m_mode(SelectorChecker::ResolvingStyle) , m_canUseFastReject(m_selectorFilter.parentStackIsConsistent(context.parentNode())) , m_sameOriginOnly(false) , m_matchingUARules(false) - , m_includeStyleSheet(includeStyleSheet) { } ElementRuleCollector::~ElementRuleCollector() @@ -65,23 +66,23 @@ MatchResult& ElementRuleCollector::matchedResult() return m_result; } -PassRefPtr<StyleRuleList> ElementRuleCollector::matchedStyleRuleList() +PassRefPtrWillBeRawPtr<StyleRuleList> ElementRuleCollector::matchedStyleRuleList() { ASSERT(m_mode == SelectorChecker::CollectingStyleRules); return m_styleRuleList.release(); } -PassRefPtr<CSSRuleList> ElementRuleCollector::matchedCSSRuleList() +PassRefPtrWillBeRawPtr<CSSRuleList> ElementRuleCollector::matchedCSSRuleList() { ASSERT(m_mode == SelectorChecker::CollectingCSSRules); return m_cssRuleList.release(); } -inline void ElementRuleCollector::addMatchedRule(const RuleData* rule, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex) +inline void ElementRuleCollector::addMatchedRule(const RuleData* rule, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex, const CSSStyleSheet* parentStyleSheet) { if (!m_matchedRules) - m_matchedRules = adoptPtr(new Vector<MatchedRule, 32>); - m_matchedRules->append(MatchedRule(rule, specificity, cascadeScope, cascadeOrder, styleSheetIndex)); + m_matchedRules = adoptPtrWillBeNoop(new WillBeHeapVector<MatchedRule, 32>); + m_matchedRules->append(MatchedRule(rule, specificity, cascadeScope, cascadeOrder, styleSheetIndex, parentStyleSheet)); } void ElementRuleCollector::clearMatchedRules() @@ -129,10 +130,7 @@ static bool rulesApplicableInCurrentTreeScope(const Element* element, const Cont if (!scopingNode || treeScope == scopingNode->treeScope()) return true; // d) the rules comes from a scoped style sheet within an active shadow root whose host is the given element - if (element->isInShadowTree() && (behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost) && scopingNode == element->containingShadowRoot()->host()) - return true; - // e) the rules can cross boundaries - if ((behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) == SelectorChecker::CrossesBoundary) + if (SelectorChecker::isHostInItsShadowTree(*element, behaviorAtBoundary, scopingNode)) return true; return false; } @@ -146,7 +144,7 @@ void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest const AtomicString& pseudoId = element.shadowPseudoId(); if (!pseudoId.isEmpty()) { ASSERT(element.isStyledElement()); - collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId.impl()), behaviorAtBoundary, ignoreCascadeScope, cascadeOrder, matchRequest, ruleRange); + collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId), behaviorAtBoundary, ignoreCascadeScope, cascadeOrder, matchRequest, ruleRange); } if (element.isVTTElement()) @@ -164,65 +162,68 @@ void ElementRuleCollector::collectMatchingRules(const MatchRequest& matchRequest // We need to collect the rules for id, class, tag, and everything else into a buffer and // then sort the buffer. if (element.hasID()) - collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForStyleResolution().impl()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); + collectMatchingRulesForList(matchRequest.ruleSet->idRules(element.idForStyleResolution()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); if (element.isStyledElement() && element.hasClass()) { for (size_t i = 0; i < element.classNames().size(); ++i) - collectMatchingRulesForList(matchRequest.ruleSet->classRules(element.classNames()[i].impl()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); + collectMatchingRulesForList(matchRequest.ruleSet->classRules(element.classNames()[i]), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); } if (element.isLink()) collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); if (SelectorChecker::matchesFocusPseudoClass(element)) collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); - collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName().impl()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); + collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element.localName()), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); } -void ElementRuleCollector::collectMatchingRulesForRegion(const MatchRequest& matchRequest, RuleRange& ruleRange, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder) +CSSRuleList* ElementRuleCollector::nestedRuleList(CSSRule* rule) { - if (!m_regionForStyling) - return; - - unsigned size = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.size(); - for (unsigned i = 0; i < size; ++i) { - const CSSSelector* regionSelector = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).selector; - if (checkRegionSelector(regionSelector, toElement(m_regionForStyling->nodeForRegion()))) { - RuleSet* regionRules = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).ruleSet.get(); - ASSERT(regionRules); - collectMatchingRules(MatchRequest(regionRules, matchRequest.includeEmptyRules, matchRequest.scope), ruleRange, behaviorAtBoundary, cascadeScope, cascadeOrder); - } + switch (rule->type()) { + case CSSRule::MEDIA_RULE: + return toCSSMediaRule(rule)->cssRules(); + case CSSRule::KEYFRAMES_RULE: + return toCSSKeyframesRule(rule)->cssRules(); + case CSSRule::SUPPORTS_RULE: + return toCSSSupportsRule(rule)->cssRules(); + default: + return 0; } } - -static CSSStyleSheet* findStyleSheet(StyleEngine* styleEngine, StyleRule* rule) +template<class CSSRuleCollection> +CSSRule* ElementRuleCollector::findStyleRule(CSSRuleCollection* cssRules, StyleRule* styleRule) { - // FIXME: StyleEngine has a bunch of different accessors for StyleSheet lists, is this the only one we need to care about? - const Vector<RefPtr<CSSStyleSheet> >& stylesheets = styleEngine->activeAuthorStyleSheets(); - for (size_t i = 0; i < stylesheets.size(); ++i) { - CSSStyleSheet* sheet = stylesheets[i].get(); - for (unsigned j = 0; j < sheet->length(); ++j) { - CSSRule* cssRule = sheet->item(j); - if (cssRule->type() != CSSRule::STYLE_RULE) - continue; + if (!cssRules) + return 0; + CSSRule* result = 0; + for (unsigned i = 0; i < cssRules->length() && !result; ++i) { + CSSRule* cssRule = cssRules->item(i); + CSSRule::Type cssRuleType = cssRule->type(); + if (cssRuleType == CSSRule::STYLE_RULE) { CSSStyleRule* cssStyleRule = toCSSStyleRule(cssRule); - if (cssStyleRule->styleRule() == rule) - return sheet; + if (cssStyleRule->styleRule() == styleRule) + result = cssRule; + } else if (cssRuleType == CSSRule::IMPORT_RULE) { + CSSImportRule* cssImportRule = toCSSImportRule(cssRule); + result = findStyleRule(cssImportRule->styleSheet(), styleRule); + } else { + result = findStyleRule(nestedRuleList(cssRule), styleRule); } } - return 0; + return result; } -void ElementRuleCollector::appendCSSOMWrapperForRule(StyleRule* rule) +void ElementRuleCollector::appendCSSOMWrapperForRule(CSSStyleSheet* parentStyleSheet, StyleRule* rule) { - // FIXME: There should be no codepath that creates a CSSOMWrapper without a parent stylesheet or rule because - // then that codepath can lead to the CSSStyleSheet contents not getting correctly copied when the rule is modified - // through the wrapper (e.g. rule.selectorText="div"). Right now, the inspector uses the pointers for identity though, - // so calling CSSStyleSheet->willMutateRules breaks the inspector. - CSSStyleSheet* sheet = m_includeStyleSheet == IncludeStyleSheetInCSSOMWrapper ? findStyleSheet(m_context.element()->document().styleEngine(), rule) : 0; - RefPtr<CSSRule> cssRule = rule->createCSSOMWrapper(sheet); - if (sheet) - sheet->registerExtraChildRuleCSSOMWrapper(cssRule); + // |parentStyleSheet| is 0 if and only if the |rule| is coming from User Agent. In this case, + // it is safe to create CSSOM wrappers without parentStyleSheets as they will be used only + // by inspector which will not try to edit them. + RefPtrWillBeRawPtr<CSSRule> cssRule = nullptr; + if (parentStyleSheet) + cssRule = findStyleRule(parentStyleSheet, rule); + else + cssRule = rule->createCSSOMWrapper(); + ASSERT(!parentStyleSheet || cssRule); ensureRuleList()->rules().append(cssRule); } @@ -233,7 +234,7 @@ void ElementRuleCollector::sortAndTransferMatchedRules() sortMatchedRules(); - Vector<MatchedRule, 32>& matchedRules = *m_matchedRules; + WillBeHeapVector<MatchedRule, 32>& matchedRules = *m_matchedRules; if (m_mode == SelectorChecker::CollectingStyleRules) { for (unsigned i = 0; i < matchedRules.size(); ++i) ensureStyleRuleList()->m_list.append(matchedRules[i].ruleData()->rule()); @@ -242,7 +243,7 @@ void ElementRuleCollector::sortAndTransferMatchedRules() if (m_mode == SelectorChecker::CollectingCSSRules) { for (unsigned i = 0; i < matchedRules.size(); ++i) - appendCSSOMWrapperForRule(matchedRules[i].ruleData()->rule()); + appendCSSOMWrapperForRule(const_cast<CSSStyleSheet*>(matchedRules[i].parentStyleSheet()), matchedRules[i].ruleData()->rule()); return; } @@ -252,35 +253,12 @@ void ElementRuleCollector::sortAndTransferMatchedRules() const RuleData* ruleData = matchedRules[i].ruleData(); if (m_style && ruleData->containsUncommonAttributeSelector()) m_style->setUnique(); - m_result.addMatchedProperties(ruleData->rule()->properties(), ruleData->rule(), ruleData->linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules)); + m_result.addMatchedProperties(&ruleData->rule()->properties(), ruleData->rule(), ruleData->linkMatchType(), ruleData->propertyWhitelistType(m_matchingUARules)); } } inline bool ElementRuleCollector::ruleMatches(const RuleData& ruleData, const ContainerNode* scope, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, SelectorChecker::MatchResult* result) { - // Scoped rules can't match because the fast path uses a pool of tag/class/ids, collected from - // elements in that tree and those will never match the host, since it's in a different pool. - if (ruleData.hasFastCheckableSelector() && !scope) { - // We know this selector does not include any pseudo elements. - if (m_pseudoStyleRequest.pseudoId != NOPSEUDO) - return false; - // We know a sufficiently simple single part selector matches simply because we found it from the rule hash. - // This is limited to HTML only so we don't need to check the namespace. - ASSERT(m_context.element()); - if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_context.element()->isHTMLElement()) { - if (!ruleData.hasMultipartSelector()) - return true; - } - if (ruleData.selector()->m_match == CSSSelector::Tag && !SelectorChecker::tagMatches(*m_context.element(), ruleData.selector()->tagQName())) - return false; - SelectorCheckerFastPath selectorCheckerFastPath(ruleData.selector(), *m_context.element()); - if (!selectorCheckerFastPath.matchesRightmostAttributeSelector()) - return false; - - return selectorCheckerFastPath.matches(); - } - - // Slow path. SelectorChecker selectorChecker(m_context.element()->document(), m_mode); SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_context.element(), SelectorChecker::VisitedMatchEnabled); context.elementStyle = m_style.get(); @@ -306,8 +284,8 @@ void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, Select SelectorChecker::MatchResult result; if (ruleMatches(ruleData, matchRequest.scope, behaviorAtBoundary, &result)) { // If the rule has no properties to apply, then ignore it in the non-debug mode. - const StylePropertySet* properties = rule->properties(); - if (!properties || (properties->isEmpty() && !matchRequest.includeEmptyRules)) + const StylePropertySet& properties = rule->properties(); + if (properties.isEmpty() && !matchRequest.includeEmptyRules) return; // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed. if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin()) @@ -329,30 +307,12 @@ void ElementRuleCollector::collectRuleIfMatches(const RuleData& ruleData, Select ruleRange.firstRuleIndex = ruleRange.lastRuleIndex; // Add this rule to our list of matched rules. - addMatchedRule(&ruleData, result.specificity, cascadeScope, cascadeOrder, matchRequest.styleSheetIndex); + addMatchedRule(&ruleData, result.specificity, cascadeScope, cascadeOrder, matchRequest.styleSheetIndex, matchRequest.styleSheet); return; } } } -void ElementRuleCollector::collectMatchingRulesForList(const RuleData* rules, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange) -{ - if (!rules) - return; - while (!rules->isLastInArray()) - collectRuleIfMatches(*rules++, behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); - collectRuleIfMatches(*rules, behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); -} - -void ElementRuleCollector::collectMatchingRulesForList(const Vector<RuleData>* rules, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange) -{ - if (!rules) - return; - unsigned size = rules->size(); - for (unsigned i = 0; i < size; ++i) - collectRuleIfMatches(rules->at(i), behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); -} - static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRule& matchedRule2) { if (matchedRule1.cascadeScope() != matchedRule2.cascadeScope()) @@ -363,9 +323,6 @@ static inline bool compareRules(const MatchedRule& matchedRule1, const MatchedRu if (specificity1 != specificity2) return specificity1 < specificity2; - if (matchedRule1.styleSheetIndex() != matchedRule2.styleSheetIndex()) - return matchedRule1.styleSheetIndex() < matchedRule2.styleSheetIndex(); - return matchedRule1.position() < matchedRule2.position(); } diff --git a/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.h b/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.h index cf47567909a..2423b1f23b3 100644 --- a/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.h +++ b/chromium/third_party/WebKit/Source/core/css/ElementRuleCollector.h @@ -27,14 +27,13 @@ #include "core/css/resolver/ElementResolveContext.h" #include "core/css/resolver/MatchRequest.h" #include "core/css/resolver/MatchResult.h" -#include "core/css/resolver/StyleResolverIncludes.h" #include "wtf/RefPtr.h" #include "wtf/Vector.h" namespace WebCore { +class CSSStyleSheet; class CSSRuleList; -class RenderRegion; class RuleData; class RuleSet; class ScopedStyleResolver; @@ -48,37 +47,61 @@ const CascadeScope ignoreCascadeScope = 0; const CascadeOrder ignoreCascadeOrder = 0; class MatchedRule { - WTF_MAKE_FAST_ALLOCATED; + ALLOW_ONLY_INLINE_ALLOCATION(); public: - explicit MatchedRule(const RuleData* ruleData, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex) + MatchedRule(const RuleData* ruleData, unsigned specificity, CascadeScope cascadeScope, CascadeOrder cascadeOrder, unsigned styleSheetIndex, const CSSStyleSheet* parentStyleSheet) : m_ruleData(ruleData) , m_specificity(specificity) , m_cascadeScope(cascadeScope) - , m_styleSheetIndex(styleSheetIndex) + , m_parentStyleSheet(parentStyleSheet) { ASSERT(m_ruleData); static const unsigned BitsForPositionInRuleData = 18; - m_position = (cascadeOrder << BitsForPositionInRuleData) + m_ruleData->position(); + static const unsigned BitsForStyleSheetIndex = 32; + m_position = ((uint64_t)cascadeOrder << (BitsForStyleSheetIndex + BitsForPositionInRuleData)) + ((uint64_t)styleSheetIndex << BitsForPositionInRuleData)+ m_ruleData->position(); } const RuleData* ruleData() const { return m_ruleData; } uint32_t cascadeScope() const { return m_cascadeScope; } - uint32_t position() const { return m_position; } + uint64_t position() const { return m_position; } unsigned specificity() const { return ruleData()->specificity() + m_specificity; } - uint32_t styleSheetIndex() const { return m_styleSheetIndex; } + const CSSStyleSheet* parentStyleSheet() const { return m_parentStyleSheet; } + void trace(Visitor* visitor) + { + visitor->trace(m_parentStyleSheet); + } private: + // FIXME: Oilpan: RuleData is in the oilpan heap and this pointer + // really should be traced. However, RuleData objects are + // allocated inside larger TerminatedArray objects and we cannot + // trace a raw rule data pointer at this point. const RuleData* m_ruleData; unsigned m_specificity; CascadeScope m_cascadeScope; - uint32_t m_position; - uint32_t m_styleSheetIndex; + uint64_t m_position; + RawPtrWillBeMember<const CSSStyleSheet> m_parentStyleSheet; }; -class StyleRuleList : public RefCounted<StyleRuleList> { +} // namespace WebCore + +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::MatchedRule); + +namespace WebCore { + +// FIXME: oilpan: when transition types are gone this class can be replaced with HeapVector. +class StyleRuleList FINAL : public RefCountedWillBeGarbageCollected<StyleRuleList> { public: - static PassRefPtr<StyleRuleList> create() { return adoptRef(new StyleRuleList()); } - Vector<StyleRule*> m_list; + static PassRefPtrWillBeRawPtr<StyleRuleList> create() { return adoptRefWillBeNoop(new StyleRuleList()); } + + void trace(Visitor* visitor) + { +#if ENABLE(OILPAN) + visitor->trace(m_list); +#endif + } + + WillBeHeapVector<RawPtrWillBeMember<StyleRule> > m_list; }; // ElementRuleCollector is designed to be used as a stack object. @@ -86,25 +109,24 @@ public: // and then let it go out of scope. // FIXME: Currently it modifies the RenderStyle but should not! class ElementRuleCollector { + STACK_ALLOCATED(); WTF_MAKE_NONCOPYABLE(ElementRuleCollector); public: - ElementRuleCollector(const ElementResolveContext&, const SelectorFilter&, RenderStyle* = 0, ShouldIncludeStyleSheetInCSSOMWrapper = IncludeStyleSheetInCSSOMWrapper); + ElementRuleCollector(const ElementResolveContext&, const SelectorFilter&, RenderStyle* = 0); ~ElementRuleCollector(); void setMode(SelectorChecker::Mode mode) { m_mode = mode; } void setPseudoStyleRequest(const PseudoStyleRequest& request) { m_pseudoStyleRequest = request; } void setSameOriginOnly(bool f) { m_sameOriginOnly = f; } - void setRegionForStyling(const RenderRegion* regionForStyling) { m_regionForStyling = regionForStyling; } void setMatchingUARules(bool matchingUARules) { m_matchingUARules = matchingUARules; } bool hasAnyMatchingRules(RuleSet*); MatchResult& matchedResult(); - PassRefPtr<StyleRuleList> matchedStyleRuleList(); - PassRefPtr<CSSRuleList> matchedCSSRuleList(); + PassRefPtrWillBeRawPtr<StyleRuleList> matchedStyleRuleList(); + PassRefPtrWillBeRawPtr<CSSRuleList> matchedCSSRuleList(); void collectMatchingRules(const MatchRequest&, RuleRange&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary, CascadeScope = ignoreCascadeScope, CascadeOrder = ignoreCascadeOrder); - void collectMatchingRulesForRegion(const MatchRequest&, RuleRange&, SelectorChecker::BehaviorAtBoundary = SelectorChecker::DoesNotCrossBoundary, CascadeScope = ignoreCascadeScope, CascadeOrder = ignoreCascadeOrder); void sortAndTransferMatchedRules(); void clearMatchedRules(); void addElementStyleProperties(const StylePropertySet*, bool isCacheable = true); @@ -115,15 +137,26 @@ public: private: void collectRuleIfMatches(const RuleData&, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&); - void collectMatchingRulesForList(const Vector<RuleData>*, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&); - void collectMatchingRulesForList(const RuleData*, SelectorChecker::BehaviorAtBoundary, CascadeScope, CascadeOrder, const MatchRequest&, RuleRange&); + + template<typename RuleDataListType> + void collectMatchingRulesForList(const RuleDataListType* rules, SelectorChecker::BehaviorAtBoundary behaviorAtBoundary, CascadeScope cascadeScope, CascadeOrder cascadeOrder, const MatchRequest& matchRequest, RuleRange& ruleRange) + { + if (!rules) + return; + + for (typename RuleDataListType::const_iterator it = rules->begin(), end = rules->end(); it != end; ++it) + collectRuleIfMatches(*it, behaviorAtBoundary, cascadeScope, cascadeOrder, matchRequest, ruleRange); + } + bool ruleMatches(const RuleData&, const ContainerNode* scope, SelectorChecker::BehaviorAtBoundary, SelectorChecker::MatchResult*); - void appendCSSOMWrapperForRule(StyleRule*); + CSSRuleList* nestedRuleList(CSSRule*); + template<class CSSRuleCollection> + CSSRule* findStyleRule(CSSRuleCollection*, StyleRule*); + void appendCSSOMWrapperForRule(CSSStyleSheet*, StyleRule*); void sortMatchedRules(); - void addMatchedRule(const RuleData*, unsigned specificity, CascadeScope, CascadeOrder); - void addMatchedRule(const RuleData*, unsigned specificity, CascadeScope, CascadeOrder, unsigned styleSheetIndex); + void addMatchedRule(const RuleData*, unsigned specificity, CascadeScope, CascadeOrder, unsigned styleSheetIndex, const CSSStyleSheet* parentStyleSheet); StaticCSSRuleList* ensureRuleList(); StyleRuleList* ensureStyleRuleList(); @@ -133,19 +166,17 @@ private: const SelectorFilter& m_selectorFilter; RefPtr<RenderStyle> m_style; // FIXME: This can be mutated during matching! - const RenderRegion* m_regionForStyling; PseudoStyleRequest m_pseudoStyleRequest; SelectorChecker::Mode m_mode; bool m_canUseFastReject; bool m_sameOriginOnly; bool m_matchingUARules; - bool m_includeStyleSheet; - OwnPtr<Vector<MatchedRule, 32> > m_matchedRules; + OwnPtrWillBeMember<WillBeHeapVector<MatchedRule, 32> > m_matchedRules; // Output. - RefPtr<StaticCSSRuleList> m_cssRuleList; - RefPtr<StyleRuleList> m_styleRuleList; + RefPtrWillBeMember<StaticCSSRuleList> m_cssRuleList; + RefPtrWillBeMember<StyleRuleList> m_styleRuleList; MatchResult m_result; }; diff --git a/chromium/third_party/WebKit/Source/core/css/FontFace.cpp b/chromium/third_party/WebKit/Source/core/css/FontFace.cpp index 3b35cbca0fb..9590053c590 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontFace.cpp +++ b/chromium/third_party/WebKit/Source/core/css/FontFace.cpp @@ -31,134 +31,161 @@ #include "config.h" #include "core/css/FontFace.h" -#include "CSSValueKeywords.h" -#include "FontFamilyNames.h" #include "bindings/v8/Dictionary.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptPromiseResolver.h" -#include "bindings/v8/ScriptScope.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" #include "bindings/v8/ScriptState.h" +#include "core/CSSValueKeywords.h" +#include "core/css/BinaryDataFontFaceSource.h" #include "core/css/CSSFontFace.h" #include "core/css/CSSFontFaceSrcValue.h" -#include "core/css/CSSParser.h" +#include "core/css/CSSFontSelector.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSUnicodeRangeValue.h" #include "core/css/CSSValueList.h" +#include "core/css/LocalFontFaceSource.h" +#include "core/css/RemoteFontFaceSource.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRule.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/dom/DOMError.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/frame/Frame.h" +#include "core/dom/StyleEngine.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "core/svg/SVGFontFaceElement.h" -#include "platform/fonts/FontDescription.h" -#include "platform/fonts/FontTraitsMask.h" -#include "platform/fonts/SimpleFontData.h" +#include "core/svg/SVGFontFaceSource.h" +#include "core/svg/SVGRemoteFontFaceSource.h" +#include "platform/FontFamilyNames.h" +#include "platform/SharedBuffer.h" namespace WebCore { class FontFaceReadyPromiseResolver { public: - static PassOwnPtr<FontFaceReadyPromiseResolver> create(ScriptPromise promise, ExecutionContext* context) + static PassOwnPtr<FontFaceReadyPromiseResolver> create(ScriptState* scriptState) { - return adoptPtr(new FontFaceReadyPromiseResolver(promise, context)); + return adoptPtr(new FontFaceReadyPromiseResolver(scriptState)); } - void resolve(PassRefPtr<FontFace> fontFace) + void resolve(PassRefPtrWillBeRawPtr<FontFace> fontFace) { - ScriptScope scope(m_scriptState); switch (fontFace->loadStatus()) { case FontFace::Loaded: m_resolver->resolve(fontFace); break; case FontFace::Error: - m_resolver->reject(DOMError::create(NetworkError)); + m_resolver->reject(fontFace->error()); break; default: ASSERT_NOT_REACHED(); } } + ScriptPromise promise() { return m_resolver->promise(); } + private: - FontFaceReadyPromiseResolver(ScriptPromise promise, ExecutionContext* context) - : m_scriptState(ScriptState::current()) - , m_resolver(ScriptPromiseResolver::create(promise, context)) - { } - ScriptState* m_scriptState; - RefPtr<ScriptPromiseResolver> m_resolver; + FontFaceReadyPromiseResolver(ScriptState* scriptState) + : m_resolver(ScriptPromiseResolverWithContext::create(scriptState)) + { + } + + RefPtr<ScriptPromiseResolverWithContext> m_resolver; }; -static PassRefPtr<CSSValue> parseCSSValue(const String& s, CSSPropertyID propertyID) +static PassRefPtrWillBeRawPtr<CSSValue> parseCSSValue(const Document* document, const String& s, CSSPropertyID propertyID) { if (s.isEmpty()) - return 0; - RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::create(); - CSSParser::parseValue(parsedStyle.get(), propertyID, s, true, HTMLStandardMode, 0); + return nullptr; + RefPtrWillBeRawPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::create(); + BisonCSSParser::parseValue(parsedStyle.get(), propertyID, s, true, *document); return parsedStyle->getPropertyCSSValue(propertyID); } -PassRefPtr<FontFace> FontFace::create(const AtomicString& family, const String& source, const Dictionary& descriptors, ExceptionState& exceptionState) +static bool initFontFace(FontFace* fontFace, ExecutionContext* context, const AtomicString& family, const Dictionary& descriptors, ExceptionState& exceptionState) { - RefPtr<CSSValue> src = parseCSSValue(source, CSSPropertySrc); - if (!src || !src->isValueList()) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return 0; - } - - RefPtr<FontFace> fontFace = adoptRef<FontFace>(new FontFace(src)); - fontFace->setFamily(family, exceptionState); + fontFace->setFamily(context, family, exceptionState); if (exceptionState.hadException()) - return 0; + return false; String value; if (descriptors.get("style", value)) { - fontFace->setStyle(value, exceptionState); + fontFace->setStyle(context, value, exceptionState); if (exceptionState.hadException()) - return 0; + return false; } if (descriptors.get("weight", value)) { - fontFace->setWeight(value, exceptionState); + fontFace->setWeight(context, value, exceptionState); if (exceptionState.hadException()) - return 0; + return false; } if (descriptors.get("stretch", value)) { - fontFace->setStretch(value, exceptionState); + fontFace->setStretch(context, value, exceptionState); if (exceptionState.hadException()) - return 0; + return false; } if (descriptors.get("unicodeRange", value)) { - fontFace->setUnicodeRange(value, exceptionState); + fontFace->setUnicodeRange(context, value, exceptionState); if (exceptionState.hadException()) - return 0; + return false; } if (descriptors.get("variant", value)) { - fontFace->setVariant(value, exceptionState); + fontFace->setVariant(context, value, exceptionState); if (exceptionState.hadException()) - return 0; + return false; } if (descriptors.get("featureSettings", value)) { - fontFace->setFeatureSettings(value, exceptionState); + fontFace->setFeatureSettings(context, value, exceptionState); if (exceptionState.hadException()) - return 0; + return false; + } + return true; +} + +PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, const String& source, const Dictionary& descriptors, ExceptionState& exceptionState) +{ + RefPtrWillBeRawPtr<CSSValue> src = parseCSSValue(toDocument(context), source, CSSPropertySrc); + if (!src || !src->isValueList()) { + exceptionState.throwDOMException(SyntaxError, "The source provided ('" + source + "') could not be parsed as a value list."); + return nullptr; } - return fontFace; + RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace()); + if (initFontFace(fontFace.get(), context, family, descriptors, exceptionState)) + fontFace->initCSSFontFace(toDocument(context), src); + return fontFace.release(); } -PassRefPtr<FontFace> FontFace::create(const StyleRuleFontFace* fontFaceRule) +PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, PassRefPtr<ArrayBuffer> source, const Dictionary& descriptors, ExceptionState& exceptionState) { - const StylePropertySet* properties = fontFaceRule->properties(); + RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace()); + if (initFontFace(fontFace.get(), context, family, descriptors, exceptionState)) + fontFace->initCSSFontFace(static_cast<const unsigned char*>(source->data()), source->byteLength()); + return fontFace.release(); +} + +PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, PassRefPtr<ArrayBufferView> source, const Dictionary& descriptors, ExceptionState& exceptionState) +{ + RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace()); + if (initFontFace(fontFace.get(), context, family, descriptors, exceptionState)) + fontFace->initCSSFontFace(static_cast<const unsigned char*>(source->baseAddress()), source->byteLength()); + return fontFace.release(); +} + +PassRefPtrWillBeRawPtr<FontFace> FontFace::create(Document* document, const StyleRuleFontFace* fontFaceRule) +{ + const StylePropertySet& properties = fontFaceRule->properties(); // Obtain the font-family property and the src property. Both must be defined. - RefPtr<CSSValue> family = properties->getPropertyCSSValue(CSSPropertyFontFamily); + RefPtrWillBeRawPtr<CSSValue> family = properties.getPropertyCSSValue(CSSPropertyFontFamily); if (!family || !family->isValueList()) - return 0; - RefPtr<CSSValue> src = properties->getPropertyCSSValue(CSSPropertySrc); + return nullptr; + RefPtrWillBeRawPtr<CSSValue> src = properties.getPropertyCSSValue(CSSPropertySrc); if (!src || !src->isValueList()) - return 0; + return nullptr; - RefPtr<FontFace> fontFace = adoptRef<FontFace>(new FontFace(src)); + RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace()); if (fontFace->setFamilyValue(toCSSValueList(family.get())) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStyle) @@ -166,15 +193,17 @@ PassRefPtr<FontFace> FontFace::create(const StyleRuleFontFace* fontFaceRule) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStretch) && fontFace->setPropertyFromStyle(properties, CSSPropertyUnicodeRange) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontVariant) - && fontFace->setPropertyFromStyle(properties, CSSPropertyWebkitFontFeatureSettings)) - return fontFace; - return 0; + && fontFace->setPropertyFromStyle(properties, CSSPropertyWebkitFontFeatureSettings) + && !fontFace->family().isEmpty() + && fontFace->traits().mask()) { + fontFace->initCSSFontFace(document, src); + return fontFace.release(); + } + return nullptr; } -FontFace::FontFace(PassRefPtr<CSSValue> src) - : m_src(src) - , m_status(Unloaded) - , m_cssFontFace(0) +FontFace::FontFace() + : m_status(Unloaded) { } @@ -212,49 +241,49 @@ String FontFace::featureSettings() const return m_featureSettings ? m_featureSettings->cssText() : "normal"; } -void FontFace::setStyle(const String& s, ExceptionState& exceptionState) +void FontFace::setStyle(ExecutionContext* context, const String& s, ExceptionState& exceptionState) { - setPropertyFromString(s, CSSPropertyFontStyle, exceptionState); + setPropertyFromString(toDocument(context), s, CSSPropertyFontStyle, exceptionState); } -void FontFace::setWeight(const String& s, ExceptionState& exceptionState) +void FontFace::setWeight(ExecutionContext* context, const String& s, ExceptionState& exceptionState) { - setPropertyFromString(s, CSSPropertyFontWeight, exceptionState); + setPropertyFromString(toDocument(context), s, CSSPropertyFontWeight, exceptionState); } -void FontFace::setStretch(const String& s, ExceptionState& exceptionState) +void FontFace::setStretch(ExecutionContext* context, const String& s, ExceptionState& exceptionState) { - setPropertyFromString(s, CSSPropertyFontStretch, exceptionState); + setPropertyFromString(toDocument(context), s, CSSPropertyFontStretch, exceptionState); } -void FontFace::setUnicodeRange(const String& s, ExceptionState& exceptionState) +void FontFace::setUnicodeRange(ExecutionContext* context, const String& s, ExceptionState& exceptionState) { - setPropertyFromString(s, CSSPropertyUnicodeRange, exceptionState); + setPropertyFromString(toDocument(context), s, CSSPropertyUnicodeRange, exceptionState); } -void FontFace::setVariant(const String& s, ExceptionState& exceptionState) +void FontFace::setVariant(ExecutionContext* context, const String& s, ExceptionState& exceptionState) { - setPropertyFromString(s, CSSPropertyFontVariant, exceptionState); + setPropertyFromString(toDocument(context), s, CSSPropertyFontVariant, exceptionState); } -void FontFace::setFeatureSettings(const String& s, ExceptionState& exceptionState) +void FontFace::setFeatureSettings(ExecutionContext* context, const String& s, ExceptionState& exceptionState) { - setPropertyFromString(s, CSSPropertyWebkitFontFeatureSettings, exceptionState); + setPropertyFromString(toDocument(context), s, CSSPropertyWebkitFontFeatureSettings, exceptionState); } -void FontFace::setPropertyFromString(const String& s, CSSPropertyID propertyID, ExceptionState& exceptionState) +void FontFace::setPropertyFromString(const Document* document, const String& s, CSSPropertyID propertyID, ExceptionState& exceptionState) { - RefPtr<CSSValue> value = parseCSSValue(s, propertyID); + RefPtrWillBeRawPtr<CSSValue> value = parseCSSValue(document, s, propertyID); if (!value || !setPropertyValue(value, propertyID)) - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Failed to set '" + s + "' as a property value."); } -bool FontFace::setPropertyFromStyle(const StylePropertySet* properties, CSSPropertyID propertyID) +bool FontFace::setPropertyFromStyle(const StylePropertySet& properties, CSSPropertyID propertyID) { - return setPropertyValue(properties->getPropertyCSSValue(propertyID), propertyID); + return setPropertyValue(properties.getPropertyCSSValue(propertyID), propertyID); } -bool FontFace::setPropertyValue(PassRefPtr<CSSValue> value, CSSPropertyID propertyID) +bool FontFace::setPropertyValue(PassRefPtrWillBeRawPtr<CSSValue> value, CSSPropertyID propertyID) { switch (propertyID) { case CSSPropertyFontStyle: @@ -344,38 +373,62 @@ String FontFace::status() const void FontFace::setLoadStatus(LoadStatus status) { m_status = status; - if (m_status == Loaded || m_status == Error) + if (m_status == Error) + m_error = DOMError::create(NetworkError); + if (m_status == Loaded || m_status == Error) { resolveReadyPromises(); -} - -void FontFace::load() -{ - // FIXME: This does not load FontFace created by JavaScript, since m_cssFontFace is null. - if (m_status != Unloaded || !m_cssFontFace) - return; - - FontDescription fontDescription; - FontFamily fontFamily; - fontFamily.setFamily(m_family); - fontDescription.setFamily(fontFamily); - fontDescription.setTraitsMask(static_cast<FontTraitsMask>(traitsMask())); - RefPtr<SimpleFontData> fontData = m_cssFontFace->getFontData(fontDescription); - if (fontData && fontData->customFontData()) - fontData->customFontData()->beginLoadIfNeeded(); + WillBeHeapVector<RefPtrWillBeMember<LoadFontCallback> > callbacks; + m_callbacks.swap(callbacks); + for (size_t i = 0; i < callbacks.size(); ++i) { + if (m_status == Loaded) + callbacks[i]->notifyLoaded(this); + else + callbacks[i]->notifyError(this); + } + } } -ScriptPromise FontFace::ready(ExecutionContext* context) +ScriptPromise FontFace::fontStatusPromise(ScriptState* scriptState) { - ScriptPromise promise = ScriptPromise::createPending(context); - OwnPtr<FontFaceReadyPromiseResolver> resolver = FontFaceReadyPromiseResolver::create(promise, context); + // Since we cannot hold a ScriptPromise as a member of FontFace (that will + // cause a circular reference), this creates new Promise every time. + OwnPtr<FontFaceReadyPromiseResolver> resolver = FontFaceReadyPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); if (m_status == Loaded || m_status == Error) resolver->resolve(this); else m_readyResolvers.append(resolver.release()); + return promise; } +ScriptPromise FontFace::load(ScriptState* scriptState) +{ + loadInternal(scriptState->executionContext()); + return fontStatusPromise(scriptState); +} + +void FontFace::loadWithCallback(PassRefPtrWillBeRawPtr<LoadFontCallback> callback, ExecutionContext* context) +{ + loadInternal(context); + if (m_status == Loaded) + callback->notifyLoaded(this); + else if (m_status == Error) + callback->notifyError(this); + else + m_callbacks.append(callback); +} + +void FontFace::loadInternal(ExecutionContext* context) +{ + if (m_status != Unloaded) + return; + + m_cssFontFace->load(); + toDocument(context)->styleEngine()->fontSelector()->fontLoader()->loadPendingFonts(); +} + void FontFace::resolveReadyPromises() { for (size_t i = 0; i < m_readyResolvers.size(); i++) @@ -383,29 +436,27 @@ void FontFace::resolveReadyPromises() m_readyResolvers.clear(); } -unsigned FontFace::traitsMask() const +FontTraits FontFace::traits() const { - unsigned traitsMask = 0; - + FontStyle style = FontStyleNormal; if (m_style) { if (!m_style->isPrimitiveValue()) return 0; switch (toCSSPrimitiveValue(m_style.get())->getValueID()) { case CSSValueNormal: - traitsMask |= FontStyleNormalMask; + style = FontStyleNormal; break; case CSSValueItalic: case CSSValueOblique: - traitsMask |= FontStyleItalicMask; + style = FontStyleItalic; break; default: break; } - } else { - traitsMask |= FontStyleNormalMask; } + FontWeight weight = FontWeight400; if (m_weight) { if (!m_weight->isPrimitiveValue()) return 0; @@ -413,44 +464,45 @@ unsigned FontFace::traitsMask() const switch (toCSSPrimitiveValue(m_weight.get())->getValueID()) { case CSSValueBold: case CSSValue700: - traitsMask |= FontWeight700Mask; + weight = FontWeight700; break; case CSSValueNormal: case CSSValue400: - traitsMask |= FontWeight400Mask; + weight = FontWeight400; break; case CSSValue900: - traitsMask |= FontWeight900Mask; + weight = FontWeight900; break; case CSSValue800: - traitsMask |= FontWeight800Mask; + weight = FontWeight800; break; case CSSValue600: - traitsMask |= FontWeight600Mask; + weight = FontWeight600; break; case CSSValue500: - traitsMask |= FontWeight500Mask; + weight = FontWeight500; break; case CSSValue300: - traitsMask |= FontWeight300Mask; + weight = FontWeight300; break; case CSSValue200: - traitsMask |= FontWeight200Mask; + weight = FontWeight200; break; + case CSSValueLighter: case CSSValue100: - traitsMask |= FontWeight100Mask; + weight = FontWeight100; break; default: + ASSERT_NOT_REACHED(); break; } - } else { - traitsMask |= FontWeight400Mask; } - if (RefPtr<CSSValue> fontVariant = m_variant) { + FontVariant variant = FontVariantNormal; + if (RefPtrWillBeRawPtr<CSSValue> fontVariant = m_variant) { // font-variant descriptor can be a value list. if (fontVariant->isPrimitiveValue()) { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); list->append(fontVariant); fontVariant = list; } else if (!fontVariant->isValueList()) { @@ -465,31 +517,40 @@ unsigned FontFace::traitsMask() const for (unsigned i = 0; i < numVariants; ++i) { switch (toCSSPrimitiveValue(variantList->itemWithoutBoundsCheck(i))->getValueID()) { case CSSValueNormal: - traitsMask |= FontVariantNormalMask; + variant = FontVariantNormal; break; case CSSValueSmallCaps: - traitsMask |= FontVariantSmallCapsMask; + variant = FontVariantSmallCaps; break; default: break; } } - } else { - traitsMask |= FontVariantNormalMask; } - return traitsMask; + + return FontTraits(style, variant, weight, FontStretchNormal); } -PassRefPtr<CSSFontFace> FontFace::createCSSFontFace(Document* document) +static PassOwnPtrWillBeRawPtr<CSSFontFace> createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange) { - if (m_cssFontFace) - return m_cssFontFace; + Vector<CSSFontFace::UnicodeRange> ranges; + if (CSSValueList* rangeList = toCSSValueList(unicodeRange)) { + unsigned numRanges = rangeList->length(); + for (unsigned i = 0; i < numRanges; i++) { + CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->itemWithoutBoundsCheck(i)); + ranges.append(CSSFontFace::UnicodeRange(range->from(), range->to())); + } + } - RefPtr<CSSFontFace> cssFontFace = CSSFontFace::create(this); - m_cssFontFace = cssFontFace.get(); + return adoptPtrWillBeNoop(new CSSFontFace(fontFace, ranges)); +} + +void FontFace::initCSSFontFace(Document* document, PassRefPtrWillBeRawPtr<CSSValue> src) +{ + m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get()); // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. - CSSValueList* srcList = toCSSValueList(m_src.get()); + CSSValueList* srcList = toCSSValueList(src.get()); int srcLength = srcList->length(); bool foundSVGFont = false; @@ -497,7 +558,7 @@ PassRefPtr<CSSFontFace> FontFace::createCSSFontFace(Document* document) for (int i = 0; i < srcLength; i++) { // An item in the list either specifies a string (local font name) or a URL (remote font to download). CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->itemWithoutBoundsCheck(i)); - OwnPtr<CSSFontFaceSource> source; + OwnPtrWillBeRawPtr<CSSFontFaceSource> source = nullptr; #if ENABLE(SVG_FONTS) foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); @@ -508,33 +569,71 @@ PassRefPtr<CSSFontFace> FontFace::createCSSFontFace(Document* document) if (allowDownloading && item->isSupportedFormat() && document) { FontResource* fetched = item->fetch(document); if (fetched) { - source = adoptPtr(new CSSFontFaceSource(item->resource(), fetched)); + FontLoader* fontLoader = document->styleEngine()->fontSelector()->fontLoader(); + #if ENABLE(SVG_FONTS) - if (foundSVGFont) - source->setHasExternalSVGFont(true); + if (foundSVGFont) { + source = adoptPtrWillBeNoop(new SVGRemoteFontFaceSource(item->resource(), fetched, fontLoader)); + } else #endif + { + source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader)); + } } } } else { - source = adoptPtr(new CSSFontFaceSource(item->resource())); - } - - if (source) { #if ENABLE(SVG_FONTS) - source->setSVGFontFaceElement(item->svgFontFaceElement()); + if (item->svgFontFaceElement()) { + RefPtrWillBeRawPtr<SVGFontFaceElement> fontfaceElement = item->svgFontFaceElement(); + // SVGFontFaceSource assumes that it is the case where <font-face> element resides in the same document. + // We put a RELEASE_ASSERT here as it will cause UAF if the assumption is false. + RELEASE_ASSERT(fontfaceElement->inDocument()); + RELEASE_ASSERT(fontfaceElement->document() == document); + source = adoptPtrWillBeNoop(new SVGFontFaceSource(fontfaceElement.get())); + } else #endif - cssFontFace->addSource(source.release()); + { + source = adoptPtrWillBeNoop(new LocalFontFaceSource(item->resource())); + } } + + if (source) + m_cssFontFace->addSource(source.release()); } +} - if (CSSValueList* rangeList = toCSSValueList(m_unicodeRange.get())) { - unsigned numRanges = rangeList->length(); - for (unsigned i = 0; i < numRanges; i++) { - CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->itemWithoutBoundsCheck(i)); - cssFontFace->ranges().add(range->from(), range->to()); - } +void FontFace::initCSSFontFace(const unsigned char* data, unsigned size) +{ + m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get()); + + RefPtr<SharedBuffer> buffer = SharedBuffer::create(data, size); + OwnPtrWillBeRawPtr<BinaryDataFontFaceSource> source = adoptPtrWillBeNoop(new BinaryDataFontFaceSource(buffer.get())); + if (source->isValid()) { + m_status = Loaded; + } else { + m_status = Error; + m_error = DOMError::create(SyntaxError, "Invalid font data in ArrayBuffer."); } - return cssFontFace; + m_cssFontFace->addSource(source.release()); +} + +void FontFace::trace(Visitor* visitor) +{ + visitor->trace(m_src); + visitor->trace(m_style); + visitor->trace(m_weight); + visitor->trace(m_stretch); + visitor->trace(m_unicodeRange); + visitor->trace(m_variant); + visitor->trace(m_featureSettings); + visitor->trace(m_error); + visitor->trace(m_cssFontFace); + visitor->trace(m_callbacks); +} + +bool FontFace::hadBlankText() const +{ + return m_cssFontFace->hadBlankText(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/FontFace.h b/chromium/third_party/WebKit/Source/core/css/FontFace.h index 900d3a7c962..c42316efdfa 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontFace.h +++ b/chromium/third_party/WebKit/Source/core/css/FontFace.h @@ -31,9 +31,11 @@ #ifndef FontFace_h #define FontFace_h -#include "CSSPropertyNames.h" #include "bindings/v8/ScriptPromise.h" +#include "core/CSSPropertyNames.h" #include "core/css/CSSValue.h" +#include "core/dom/DOMError.h" +#include "platform/fonts/FontTraits.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -49,12 +51,14 @@ class FontFaceReadyPromiseResolver; class StylePropertySet; class StyleRuleFontFace; -class FontFace : public RefCounted<FontFace> { +class FontFace : public RefCountedWillBeGarbageCollectedFinalized<FontFace> { public: enum LoadStatus { Unloaded, Loading, Loaded, Error }; - static PassRefPtr<FontFace> create(const AtomicString& family, const String& source, const Dictionary&, ExceptionState&); - static PassRefPtr<FontFace> create(const StyleRuleFontFace*); + static PassRefPtrWillBeRawPtr<FontFace> create(ExecutionContext*, const AtomicString& family, PassRefPtr<ArrayBuffer> source, const Dictionary&, ExceptionState&); + static PassRefPtrWillBeRawPtr<FontFace> create(ExecutionContext*, const AtomicString& family, PassRefPtr<ArrayBufferView>, const Dictionary&, ExceptionState&); + static PassRefPtrWillBeRawPtr<FontFace> create(ExecutionContext*, const AtomicString& family, const String& source, const Dictionary&, ExceptionState&); + static PassRefPtrWillBeRawPtr<FontFace> create(Document*, const StyleRuleFontFace*); ~FontFace(); @@ -67,49 +71,68 @@ public: String featureSettings() const; // FIXME: Changing these attributes should affect font matching. - void setFamily(const AtomicString& s, ExceptionState&) { m_family = s; } - void setStyle(const String&, ExceptionState&); - void setWeight(const String&, ExceptionState&); - void setStretch(const String&, ExceptionState&); - void setUnicodeRange(const String&, ExceptionState&); - void setVariant(const String&, ExceptionState&); - void setFeatureSettings(const String&, ExceptionState&); + void setFamily(ExecutionContext*, const AtomicString& s, ExceptionState&) { m_family = s; } + void setStyle(ExecutionContext*, const String&, ExceptionState&); + void setWeight(ExecutionContext*, const String&, ExceptionState&); + void setStretch(ExecutionContext*, const String&, ExceptionState&); + void setUnicodeRange(ExecutionContext*, const String&, ExceptionState&); + void setVariant(ExecutionContext*, const String&, ExceptionState&); + void setFeatureSettings(ExecutionContext*, const String&, ExceptionState&); String status() const; + ScriptPromise loaded(ScriptState* scriptState) { return fontStatusPromise(scriptState); } - void load(); - ScriptPromise ready(ExecutionContext*); + ScriptPromise load(ScriptState*); LoadStatus loadStatus() const { return m_status; } void setLoadStatus(LoadStatus); - unsigned traitsMask() const; - PassRefPtr<CSSFontFace> createCSSFontFace(Document*); - void cssFontFaceDestroyed() { m_cssFontFace = 0; } + DOMError* error() const { return m_error.get(); } + FontTraits traits() const; + CSSFontFace* cssFontFace() { return m_cssFontFace.get(); } + + void trace(Visitor*); + + bool hadBlankText() const; + + class LoadFontCallback : public RefCountedWillBeGarbageCollectedFinalized<LoadFontCallback> { + public: + virtual ~LoadFontCallback() { } + virtual void notifyLoaded(FontFace*) = 0; + virtual void notifyError(FontFace*) = 0; + virtual void trace(Visitor*) { } + }; + void loadWithCallback(PassRefPtrWillBeRawPtr<LoadFontCallback>, ExecutionContext*); private: - FontFace(PassRefPtr<CSSValue> source); + FontFace(); - void setPropertyFromString(const String&, CSSPropertyID, ExceptionState&); - bool setPropertyFromStyle(const StylePropertySet*, CSSPropertyID); - bool setPropertyValue(PassRefPtr<CSSValue>, CSSPropertyID); + void initCSSFontFace(Document*, PassRefPtrWillBeRawPtr<CSSValue> src); + void initCSSFontFace(const unsigned char* data, unsigned size); + void setPropertyFromString(const Document*, const String&, CSSPropertyID, ExceptionState&); + bool setPropertyFromStyle(const StylePropertySet&, CSSPropertyID); + bool setPropertyValue(PassRefPtrWillBeRawPtr<CSSValue>, CSSPropertyID); bool setFamilyValue(CSSValueList*); void resolveReadyPromises(); + void loadInternal(ExecutionContext*); + ScriptPromise fontStatusPromise(ScriptState*); AtomicString m_family; - RefPtr<CSSValue> m_src; - RefPtr<CSSValue> m_style; - RefPtr<CSSValue> m_weight; - RefPtr<CSSValue> m_stretch; - RefPtr<CSSValue> m_unicodeRange; - RefPtr<CSSValue> m_variant; - RefPtr<CSSValue> m_featureSettings; + RefPtrWillBeMember<CSSValue> m_src; + RefPtrWillBeMember<CSSValue> m_style; + RefPtrWillBeMember<CSSValue> m_weight; + RefPtrWillBeMember<CSSValue> m_stretch; + RefPtrWillBeMember<CSSValue> m_unicodeRange; + RefPtrWillBeMember<CSSValue> m_variant; + RefPtrWillBeMember<CSSValue> m_featureSettings; LoadStatus m_status; + RefPtrWillBeMember<DOMError> m_error; Vector<OwnPtr<FontFaceReadyPromiseResolver> > m_readyResolvers; - CSSFontFace* m_cssFontFace; + OwnPtrWillBeMember<CSSFontFace> m_cssFontFace; + WillBeHeapVector<RefPtrWillBeMember<LoadFontCallback> > m_callbacks; }; -typedef Vector<RefPtr<FontFace> > FontFaceArray; +typedef WillBeHeapVector<RefPtrWillBeMember<FontFace> > FontFaceArray; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/FontFace.idl b/chromium/third_party/WebKit/Source/core/css/FontFace.idl index fcfef2d143b..77d12b268e7 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontFace.idl +++ b/chromium/third_party/WebKit/Source/core/css/FontFace.idl @@ -28,6 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// http://dev.w3.org/csswg/css-font-loading/#dom-fontface + enum FontFaceLoadStatus { "unloaded", "loading", @@ -36,21 +38,26 @@ enum FontFaceLoadStatus { }; [ + // FIXME: should be union type http://crbug.com/240176 + Constructor(DOMString family, DOMString source, optional Dictionary descriptors), + Constructor(DOMString family, ArrayBuffer source, optional Dictionary descriptors), + Constructor(DOMString family, ArrayBufferView source, optional Dictionary descriptors), + ConstructorCallWith=ExecutionContext, + RaisesException=Constructor, RuntimeEnabled=FontLoadEvents, - Constructor(DOMString family, DOMString source, Dictionary descriptors), - RaisesException=Constructor + WillBeGarbageCollected, ] interface FontFace { - [RaisesException=Setter] attribute DOMString family; - [RaisesException=Setter] attribute DOMString style; - [RaisesException=Setter] attribute DOMString weight; - [RaisesException=Setter] attribute DOMString stretch; - [RaisesException=Setter] attribute DOMString unicodeRange; - [RaisesException=Setter] attribute DOMString variant; - [RaisesException=Setter] attribute DOMString featureSettings; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString family; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString style; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString weight; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString stretch; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString unicodeRange; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString variant; + [RaisesException=Setter, SetterCallWith=ExecutionContext] attribute DOMString featureSettings; readonly attribute FontFaceLoadStatus status; + [CallWith=ScriptState] readonly attribute Promise loaded; - void load(); - [CallWith=ExecutionContext] Promise ready(); + [CallWith=ScriptState] Promise load(); }; diff --git a/chromium/third_party/WebKit/Source/core/css/FontFaceCache.cpp b/chromium/third_party/WebKit/Source/core/css/FontFaceCache.cpp new file mode 100644 index 00000000000..ad5dbdc8806 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceCache.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2013 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 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, + * 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 "core/css/FontFaceCache.h" + +#include "core/css/CSSFontSelector.h" +#include "core/css/CSSSegmentedFontFace.h" +#include "core/css/CSSValueList.h" +#include "core/css/FontFace.h" +#include "core/css/StyleRule.h" +#include "core/fetch/FontResource.h" +#include "core/fetch/ResourceFetcher.h" +#include "platform/FontFamilyNames.h" +#include "platform/fonts/FontDescription.h" +#include "wtf/text/AtomicString.h" + +namespace WebCore { + +FontFaceCache::FontFaceCache() + : m_version(0) +{ +} + +void FontFaceCache::add(CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule, PassRefPtrWillBeRawPtr<FontFace> prpFontFace) +{ + RefPtrWillBeRawPtr<FontFace> fontFace = prpFontFace; + if (!m_styleRuleToFontFace.add(fontFaceRule, fontFace).isNewEntry) + return; + addFontFace(cssFontSelector, fontFace, true); +} + +void FontFaceCache::addFontFace(CSSFontSelector* cssFontSelector, PassRefPtrWillBeRawPtr<FontFace> prpFontFace, bool cssConnected) +{ + RefPtrWillBeRawPtr<FontFace> fontFace = prpFontFace; + + FamilyToTraitsMap::AddResult traitsResult = m_fontFaces.add(fontFace->family(), nullptr); + if (!traitsResult.storedValue->value) + traitsResult.storedValue->value = adoptPtrWillBeNoop(new TraitsMap); + + TraitsMap::AddResult segmentedFontFaceResult = traitsResult.storedValue->value->add(fontFace->traits().mask(), nullptr); + if (!segmentedFontFaceResult.storedValue->value) + segmentedFontFaceResult.storedValue->value = CSSSegmentedFontFace::create(cssFontSelector, fontFace->traits()); + + segmentedFontFaceResult.storedValue->value->addFontFace(fontFace, cssConnected); + if (cssConnected) + m_cssConnectedFontFaces.add(fontFace); + + ++m_version; +} + +void FontFaceCache::remove(const StyleRuleFontFace* fontFaceRule) +{ + StyleRuleToFontFace::iterator it = m_styleRuleToFontFace.find(fontFaceRule); + if (it != m_styleRuleToFontFace.end()) { + removeFontFace(it->value.get(), true); + m_styleRuleToFontFace.remove(it); + } +} + +void FontFaceCache::removeFontFace(FontFace* fontFace, bool cssConnected) +{ + FamilyToTraitsMap::iterator fontFacesIter = m_fontFaces.find(fontFace->family()); + if (fontFacesIter == m_fontFaces.end()) + return; + TraitsMap* familyFontFaces = fontFacesIter->value.get(); + + TraitsMap::iterator familyFontFacesIter = familyFontFaces->find(fontFace->traits().mask()); + if (familyFontFacesIter == familyFontFaces->end()) + return; + RefPtrWillBeRawPtr<CSSSegmentedFontFace> segmentedFontFace = familyFontFacesIter->value; + + segmentedFontFace->removeFontFace(fontFace); + if (segmentedFontFace->isEmpty()) { + familyFontFaces->remove(familyFontFacesIter); + if (familyFontFaces->isEmpty()) + m_fontFaces.remove(fontFacesIter); + } + m_fonts.clear(); + if (cssConnected) + m_cssConnectedFontFaces.remove(fontFace); + + ++m_version; +} + +void FontFaceCache::clear() +{ + for (StyleRuleToFontFace::iterator it = m_styleRuleToFontFace.begin(); it != m_styleRuleToFontFace.end(); ++it) + removeFontFace(it->value.get(), true); + m_styleRuleToFontFace.clear(); +} + +static inline bool compareFontFaces(CSSSegmentedFontFace* first, CSSSegmentedFontFace* second, FontTraits desiredTraits) +{ + const FontTraits& firstTraits = first->traits(); + const FontTraits& secondTraits = second->traits(); + + bool firstHasDesiredVariant = firstTraits.variant() == desiredTraits.variant(); + bool secondHasDesiredVariant = secondTraits.variant() == desiredTraits.variant(); + + if (firstHasDesiredVariant != secondHasDesiredVariant) + return firstHasDesiredVariant; + + // We need to check font-variant css property for CSS2.1 compatibility. + if (desiredTraits.variant() == FontVariantSmallCaps) { + // Prefer a font that has indicated that it can only support small-caps to a font that claims to support + // all variants. The specialized font is more likely to be true small-caps and not require synthesis. + bool firstRequiresSmallCaps = firstTraits.variant() == FontVariantSmallCaps; + bool secondRequiresSmallCaps = secondTraits.variant() == FontVariantSmallCaps; + if (firstRequiresSmallCaps != secondRequiresSmallCaps) + return firstRequiresSmallCaps; + } + + bool firstHasDesiredStyle = firstTraits.style() == desiredTraits.style(); + bool secondHasDesiredStyle = secondTraits.style() == desiredTraits.style(); + + if (firstHasDesiredStyle != secondHasDesiredStyle) + return firstHasDesiredStyle; + + if (desiredTraits.style() == FontStyleItalic) { + // Prefer a font that has indicated that it can only support italics to a font that claims to support + // all styles. The specialized font is more likely to be the one the author wants used. + bool firstRequiresItalics = firstTraits.style() == FontStyleItalic; + bool secondRequiresItalics = secondTraits.style() == FontStyleItalic; + if (firstRequiresItalics != secondRequiresItalics) + return firstRequiresItalics; + } + if (secondTraits.weight() == desiredTraits.weight()) + return false; + + if (firstTraits.weight() == desiredTraits.weight()) + return true; + + // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says : + // - If the desired weight is less than 400, weights below the desired weight are checked in descending order followed by weights above the desired weight in ascending order until a match is found. + // - If the desired weight is greater than 500, weights above the desired weight are checked in ascending order followed by weights below the desired weight in descending order until a match is found. + // - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used. + // - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used. + static const unsigned fallbackRuleSets = 9; + static const unsigned rulesPerSet = 8; + static const FontWeight weightFallbackRuleSets[fallbackRuleSets][rulesPerSet] = { + { FontWeight200, FontWeight300, FontWeight400, FontWeight500, FontWeight600, FontWeight700, FontWeight800, FontWeight900 }, + { FontWeight100, FontWeight300, FontWeight400, FontWeight500, FontWeight600, FontWeight700, FontWeight800, FontWeight900 }, + { FontWeight200, FontWeight100, FontWeight400, FontWeight500, FontWeight600, FontWeight700, FontWeight800, FontWeight900 }, + { FontWeight500, FontWeight300, FontWeight200, FontWeight100, FontWeight600, FontWeight700, FontWeight800, FontWeight900 }, + { FontWeight400, FontWeight300, FontWeight200, FontWeight100, FontWeight600, FontWeight700, FontWeight800, FontWeight900 }, + { FontWeight700, FontWeight800, FontWeight900, FontWeight500, FontWeight400, FontWeight300, FontWeight200, FontWeight100 }, + { FontWeight800, FontWeight900, FontWeight600, FontWeight500, FontWeight400, FontWeight300, FontWeight200, FontWeight100 }, + { FontWeight900, FontWeight700, FontWeight600, FontWeight500, FontWeight400, FontWeight300, FontWeight200, FontWeight100 }, + { FontWeight800, FontWeight700, FontWeight600, FontWeight500, FontWeight400, FontWeight300, FontWeight200, FontWeight100 } + }; + + unsigned ruleSetIndex = static_cast<unsigned>(desiredTraits.weight()); + ASSERT(ruleSetIndex < fallbackRuleSets); + const FontWeight* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex]; + for (unsigned i = 0; i < rulesPerSet; ++i) { + if (secondTraits.weight() == weightFallbackRule[i]) + return false; + if (firstTraits.weight() == weightFallbackRule[i]) + return true; + } + + return false; +} + +CSSSegmentedFontFace* FontFaceCache::get(const FontDescription& fontDescription, const AtomicString& family) +{ + TraitsMap* familyFontFaces = m_fontFaces.get(family); + if (!familyFontFaces || familyFontFaces->isEmpty()) + return 0; + + FamilyToTraitsMap::AddResult traitsResult = m_fonts.add(family, nullptr); + if (!traitsResult.storedValue->value) + traitsResult.storedValue->value = adoptPtrWillBeNoop(new TraitsMap); + + FontTraits traits = fontDescription.traits(); + TraitsMap::AddResult faceResult = traitsResult.storedValue->value->add(traits.mask(), nullptr); + if (!faceResult.storedValue->value) { + for (TraitsMap::const_iterator i = familyFontFaces->begin(); i != familyFontFaces->end(); ++i) { + CSSSegmentedFontFace* candidate = i->value.get(); + FontTraits candidateTraits = candidate->traits(); + if (traits.style() == FontStyleNormal && candidateTraits.style() != FontStyleNormal) + continue; + if (traits.variant() == FontVariantNormal && candidateTraits.variant() != FontVariantNormal) + continue; + if (!faceResult.storedValue->value || compareFontFaces(candidate, faceResult.storedValue->value.get(), traits)) + faceResult.storedValue->value = candidate; + } + } + return faceResult.storedValue->value.get(); +} + +void FontFaceCache::trace(Visitor* visitor) +{ + visitor->trace(m_fontFaces); + visitor->trace(m_fonts); + visitor->trace(m_styleRuleToFontFace); + visitor->trace(m_cssConnectedFontFaces); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFaceCache.h b/chromium/third_party/WebKit/Source/core/css/FontFaceCache.h index c18220906eb..457bc3b2919 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSSegmentedFontFaceCache.h +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceCache.h @@ -24,42 +24,56 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CSSSegmentedFontFaceCache_h -#define CSSSegmentedFontFaceCache_h +#ifndef FontFaceCache_h +#define FontFaceCache_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" +#include "wtf/ListHashSet.h" #include "wtf/text/StringHash.h" namespace WebCore { -class CSSFontFace; +class FontFace; class CSSFontSelector; class CSSSegmentedFontFace; class FontDescription; class StyleRuleFontFace; -class CSSSegmentedFontFaceCache { +class FontFaceCache FINAL { + DISALLOW_ALLOCATION(); public: - CSSSegmentedFontFaceCache(); + FontFaceCache(); // FIXME: Remove CSSFontSelector as argument. Passing CSSFontSelector here is - // a result of egregious spaghettification in CSSFontFace/FontFaceSet. - void add(CSSFontSelector*, const StyleRuleFontFace*, PassRefPtr<CSSFontFace>); + // a result of egregious spaghettification in FontFace/FontFaceSet. + void add(CSSFontSelector*, const StyleRuleFontFace*, PassRefPtrWillBeRawPtr<FontFace>); void remove(const StyleRuleFontFace*); + void clear(); + void addFontFace(CSSFontSelector*, PassRefPtrWillBeRawPtr<FontFace>, bool cssConnected); + void removeFontFace(FontFace*, bool cssConnected); + // FIXME: It's sort of weird that add/remove uses StyleRuleFontFace* as key, // but this function uses FontDescription/family pair. CSSSegmentedFontFace* get(const FontDescription&, const AtomicString& family); + const ListHashSet<RefPtrWillBeMember<FontFace> >& cssConnectedFontFaces() const { return m_cssConnectedFontFaces; } + unsigned version() const { return m_version; } + void incrementVersion() { ++m_version; } + + void trace(Visitor*); private: - typedef HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > TraitsMap; - typedef HashMap<String, OwnPtr<TraitsMap>, CaseFoldingHash> FamilyToTraitsMap; - typedef HashMap<const StyleRuleFontFace*, RefPtr<CSSFontFace> > StyleRuleToFontFace; + typedef WillBeHeapHashMap<unsigned, RefPtrWillBeMember<CSSSegmentedFontFace> > TraitsMap; + typedef WillBeHeapHashMap<String, OwnPtrWillBeMember<TraitsMap>, CaseFoldingHash> FamilyToTraitsMap; + typedef WillBeHeapHashMap<const StyleRuleFontFace*, RefPtrWillBeMember<FontFace> > StyleRuleToFontFace; FamilyToTraitsMap m_fontFaces; FamilyToTraitsMap m_fonts; StyleRuleToFontFace m_styleRuleToFontFace; + // FIXME: Oilpan: Replace by HeapLinkedHashSet or HeapListHashSet. + ListHashSet<RefPtrWillBeMember<FontFace> > m_cssConnectedFontFaces; // FIXME: See if this could be ditched // Used to compare Font instances, and the usage seems suspect. diff --git a/chromium/third_party/WebKit/Source/core/css/FontFaceSet.cpp b/chromium/third_party/WebKit/Source/core/css/FontFaceSet.cpp index 38165b8a9aa..668f6efa4ca 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontFaceSet.cpp +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceSet.cpp @@ -26,21 +26,22 @@ #include "config.h" #include "core/css/FontFaceSet.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ScriptPromiseResolver.h" -#include "bindings/v8/ScriptScope.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" #include "bindings/v8/ScriptState.h" #include "core/css/CSSFontFaceLoadEvent.h" -#include "core/css/CSSFontFaceSource.h" #include "core/css/CSSFontSelector.h" -#include "core/css/CSSParser.h" #include "core/css/CSSSegmentedFontFace.h" +#include "core/css/FontFaceCache.h" #include "core/css/StylePropertySet.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/dom/StyleEngine.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/rendering/style/StyleInheritedData.h" +#include "platform/RuntimeEnabledFeatures.h" #include "public/platform/Platform.h" namespace WebCore { @@ -48,89 +49,96 @@ namespace WebCore { static const int defaultFontSize = 10; static const char defaultFontFamily[] = "sans-serif"; -class LoadFontPromiseResolver : public CSSSegmentedFontFace::LoadFontCallback { +class LoadFontPromiseResolver FINAL : public FontFace::LoadFontCallback { public: - static PassRefPtr<LoadFontPromiseResolver> create(const FontFamily& family, ScriptPromise promise, ExecutionContext* context) + static PassRefPtrWillBeRawPtr<LoadFontPromiseResolver> create(FontFaceArray faces, ScriptState* scriptState) { - int numFamilies = 0; - for (const FontFamily* f = &family; f; f = f->next()) - numFamilies++; - return adoptRef<LoadFontPromiseResolver>(new LoadFontPromiseResolver(numFamilies, promise, context)); + return adoptRefWillBeNoop(new LoadFontPromiseResolver(faces, scriptState)); } - virtual void notifyLoaded(CSSSegmentedFontFace*) OVERRIDE; - virtual void notifyError(CSSSegmentedFontFace*) OVERRIDE; - void loaded(Document*); - void error(Document*); + void loadFonts(ExecutionContext*); + ScriptPromise promise() { return m_resolver->promise(); } + + virtual void notifyLoaded(FontFace*) OVERRIDE; + virtual void notifyError(FontFace*) OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: - LoadFontPromiseResolver(int numLoading, ScriptPromise promise, ExecutionContext* context) - : m_numLoading(numLoading) + LoadFontPromiseResolver(FontFaceArray faces, ScriptState* scriptState) + : m_numLoading(faces.size()) , m_errorOccured(false) - , m_scriptState(ScriptState::current()) - , m_resolver(ScriptPromiseResolver::create(promise, context)) - { } + , m_resolver(ScriptPromiseResolverWithContext::create(scriptState)) + { + m_fontFaces.swap(faces); + } + WillBeHeapVector<RefPtrWillBeMember<FontFace> > m_fontFaces; int m_numLoading; bool m_errorOccured; - ScriptState* m_scriptState; - RefPtr<ScriptPromiseResolver> m_resolver; + RefPtr<ScriptPromiseResolverWithContext> m_resolver; }; -void LoadFontPromiseResolver::loaded(Document* document) +void LoadFontPromiseResolver::loadFonts(ExecutionContext* context) { - m_numLoading--; - if (m_numLoading || !document) + if (!m_numLoading) { + m_resolver->resolve(m_fontFaces); return; + } - ScriptScope scope(m_scriptState); - if (m_errorOccured) - m_resolver->reject(ScriptValue::createNull()); - else - m_resolver->resolve(ScriptValue::createNull()); + for (size_t i = 0; i < m_fontFaces.size(); i++) + m_fontFaces[i]->loadWithCallback(this, context); } -void LoadFontPromiseResolver::error(Document* document) +void LoadFontPromiseResolver::notifyLoaded(FontFace* fontFace) { - m_errorOccured = true; - loaded(document); + m_numLoading--; + if (m_numLoading || m_errorOccured) + return; + + m_resolver->resolve(m_fontFaces); } -void LoadFontPromiseResolver::notifyLoaded(CSSSegmentedFontFace* face) +void LoadFontPromiseResolver::notifyError(FontFace* fontFace) { - loaded(face->fontSelector()->document()); + m_numLoading--; + if (!m_errorOccured) { + m_errorOccured = true; + m_resolver->reject(fontFace->error()); + } } -void LoadFontPromiseResolver::notifyError(CSSSegmentedFontFace* face) +void LoadFontPromiseResolver::trace(Visitor* visitor) { - error(face->fontSelector()->document()); + visitor->trace(m_fontFaces); + LoadFontCallback::trace(visitor); } class FontsReadyPromiseResolver { public: - static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptPromise promise, ExecutionContext* context) + static PassOwnPtr<FontsReadyPromiseResolver> create(ScriptState* scriptState) { - return adoptPtr(new FontsReadyPromiseResolver(promise, context)); + return adoptPtr(new FontsReadyPromiseResolver(scriptState)); } - void resolve(PassRefPtr<FontFaceSet> fontFaceSet) + void resolve(PassRefPtrWillBeRawPtr<FontFaceSet> fontFaceSet) { - ScriptScope scope(m_scriptState); m_resolver->resolve(fontFaceSet); } + ScriptPromise promise() { return m_resolver->promise(); } + private: - FontsReadyPromiseResolver(ScriptPromise promise, ExecutionContext* context) - : m_scriptState(ScriptState::current()) - , m_resolver(ScriptPromiseResolver::create(promise, context)) - { } - ScriptState* m_scriptState; - RefPtr<ScriptPromiseResolver> m_resolver; + explicit FontsReadyPromiseResolver(ScriptState* scriptState) + : m_resolver(ScriptPromiseResolverWithContext::create(scriptState)) + { + } + + RefPtr<ScriptPromiseResolverWithContext> m_resolver; }; -FontFaceSet::FontFaceSet(Document* document) - : ActiveDOMObject(document) - , m_loadingCount(0) +FontFaceSet::FontFaceSet(Document& document) + : ActiveDOMObject(&document) , m_shouldFireLoadingEvent(false) , m_asyncRunner(this, &FontFaceSet::handlePendingEventsAndPromises) { @@ -146,6 +154,18 @@ Document* FontFaceSet::document() const return toDocument(executionContext()); } +bool FontFaceSet::inActiveDocumentContext() const +{ + ExecutionContext* context = executionContext(); + return context && toDocument(context)->isActive(); +} + +void FontFaceSet::addFontFacesToFontFaceCache(FontFaceCache* fontFaceCache, CSSFontSelector* fontSelector) +{ + for (ListHashSet<RefPtrWillBeMember<FontFace> >::iterator it = m_nonCSSConnectedFaces.begin(); it != m_nonCSSConnectedFaces.end(); ++it) + fontFaceCache->addFontFace(fontSelector, *it, false); +} + const AtomicString& FontFaceSet::interfaceName() const { return EventTargetNames::FontFaceSet; @@ -160,7 +180,7 @@ AtomicString FontFaceSet::status() const { DEFINE_STATIC_LOCAL(AtomicString, loading, ("loading", AtomicString::ConstructFromLiteral)); DEFINE_STATIC_LOCAL(AtomicString, loaded, ("loaded", AtomicString::ConstructFromLiteral)); - return (m_loadingCount > 0 || hasLoadedFonts()) ? loading : loaded; + return (!m_loadingFonts.isEmpty() || hasLoadedFonts()) ? loading : loaded; } void FontFaceSet::handlePendingEventsAndPromisesSoon() @@ -172,11 +192,11 @@ void FontFaceSet::handlePendingEventsAndPromisesSoon() void FontFaceSet::didLayout() { - if (document()->frame()->isMainFrame()) + if (document()->frame()->isMainFrame() && m_loadingFonts.isEmpty()) m_histogram.record(); if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) return; - if (m_loadingCount || (!hasLoadedFonts() && m_readyResolvers.isEmpty())) + if (!m_loadingFonts.isEmpty() || (!hasLoadedFonts() && m_readyResolvers.isEmpty())) return; handlePendingEventsAndPromisesSoon(); } @@ -213,55 +233,178 @@ void FontFaceSet::stop() void FontFaceSet::beginFontLoading(FontFace* fontFace) { m_histogram.incrementCount(); - if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) - return; - - if (!m_loadingCount && !hasLoadedFonts()) { - ASSERT(!m_shouldFireLoadingEvent); - m_shouldFireLoadingEvent = true; - handlePendingEventsAndPromisesSoon(); - } - ++m_loadingCount; + addToLoadingFonts(fontFace); } void FontFaceSet::fontLoaded(FontFace* fontFace) { - if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) - return; - m_loadedFonts.append(fontFace); - queueDoneEvent(fontFace); + m_histogram.updateStatus(fontFace); + if (RuntimeEnabledFeatures::fontLoadEventsEnabled()) + m_loadedFonts.append(fontFace); + removeFromLoadingFonts(fontFace); } void FontFaceSet::loadError(FontFace* fontFace) { - if (!RuntimeEnabledFeatures::fontLoadEventsEnabled()) - return; - m_failedFonts.append(fontFace); - queueDoneEvent(fontFace); + m_histogram.updateStatus(fontFace); + if (RuntimeEnabledFeatures::fontLoadEventsEnabled()) + m_failedFonts.append(fontFace); + removeFromLoadingFonts(fontFace); +} + +void FontFaceSet::addToLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFace) +{ + if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && m_loadingFonts.isEmpty() && !hasLoadedFonts()) { + m_shouldFireLoadingEvent = true; + handlePendingEventsAndPromisesSoon(); + } + m_loadingFonts.add(fontFace); } -void FontFaceSet::queueDoneEvent(FontFace* fontFace) +void FontFaceSet::removeFromLoadingFonts(PassRefPtrWillBeRawPtr<FontFace> fontFace) { - ASSERT(m_loadingCount > 0); - --m_loadingCount; - if (!m_loadingCount) + m_loadingFonts.remove(fontFace); + if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && m_loadingFonts.isEmpty()) handlePendingEventsAndPromisesSoon(); } -ScriptPromise FontFaceSet::ready() +ScriptPromise FontFaceSet::ready(ScriptState* scriptState) { - ScriptPromise promise = ScriptPromise::createPending(executionContext()); - OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::create(promise, executionContext()); + if (!inActiveDocumentContext()) + return ScriptPromise(); + OwnPtr<FontsReadyPromiseResolver> resolver = FontsReadyPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); m_readyResolvers.append(resolver.release()); handlePendingEventsAndPromisesSoon(); return promise; } +void FontFaceSet::add(FontFace* fontFace, ExceptionState& exceptionState) +{ + if (!inActiveDocumentContext()) + return; + if (!fontFace) { + exceptionState.throwTypeError("The argument is not a FontFace."); + return; + } + if (m_nonCSSConnectedFaces.contains(fontFace)) + return; + if (isCSSConnectedFontFace(fontFace)) { + exceptionState.throwDOMException(InvalidModificationError, "Cannot add a CSS-connected FontFace."); + return; + } + CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); + m_nonCSSConnectedFaces.add(fontFace); + fontSelector->fontFaceCache()->addFontFace(fontSelector, fontFace, false); + if (fontFace->loadStatus() == FontFace::Loading) + addToLoadingFonts(fontFace); + fontSelector->fontFaceInvalidated(); +} + +void FontFaceSet::clear() +{ + if (!inActiveDocumentContext() || m_nonCSSConnectedFaces.isEmpty()) + return; + CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); + FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); + for (ListHashSet<RefPtrWillBeMember<FontFace> >::iterator it = m_nonCSSConnectedFaces.begin(); it != m_nonCSSConnectedFaces.end(); ++it) { + fontFaceCache->removeFontFace(it->get(), false); + if ((*it)->loadStatus() == FontFace::Loading) + removeFromLoadingFonts(*it); + } + m_nonCSSConnectedFaces.clear(); + fontSelector->fontFaceInvalidated(); +} + +bool FontFaceSet::remove(FontFace* fontFace, ExceptionState& exceptionState) +{ + if (!inActiveDocumentContext()) + return false; + if (!fontFace) { + exceptionState.throwTypeError("The argument is not a FontFace."); + return false; + } + ListHashSet<RefPtrWillBeMember<FontFace> >::iterator it = m_nonCSSConnectedFaces.find(fontFace); + if (it != m_nonCSSConnectedFaces.end()) { + m_nonCSSConnectedFaces.remove(it); + CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); + fontSelector->fontFaceCache()->removeFontFace(fontFace, false); + if (fontFace->loadStatus() == FontFace::Loading) + removeFromLoadingFonts(fontFace); + fontSelector->fontFaceInvalidated(); + return true; + } + if (isCSSConnectedFontFace(fontFace)) + exceptionState.throwDOMException(InvalidModificationError, "Cannot delete a CSS-connected FontFace."); + return false; +} + +bool FontFaceSet::has(FontFace* fontFace, ExceptionState& exceptionState) const +{ + if (!inActiveDocumentContext()) + return false; + if (!fontFace) { + exceptionState.throwTypeError("The argument is not a FontFace."); + return false; + } + return m_nonCSSConnectedFaces.contains(fontFace) || isCSSConnectedFontFace(fontFace); +} + +const ListHashSet<RefPtrWillBeMember<FontFace> >& FontFaceSet::cssConnectedFontFaceList() const +{ + Document* d = document(); + d->ensureStyleResolver(); // Flush pending style changes. + return d->styleEngine()->fontSelector()->fontFaceCache()->cssConnectedFontFaces(); +} + +bool FontFaceSet::isCSSConnectedFontFace(FontFace* fontFace) const +{ + return cssConnectedFontFaceList().contains(fontFace); +} + +void FontFaceSet::forEach(PassOwnPtr<FontFaceSetForEachCallback> callback, ScriptValue& thisArg) const +{ + forEachInternal(callback, &thisArg); +} + +void FontFaceSet::forEach(PassOwnPtr<FontFaceSetForEachCallback> callback) const +{ + forEachInternal(callback, 0); +} + +void FontFaceSet::forEachInternal(PassOwnPtr<FontFaceSetForEachCallback> callback, ScriptValue* thisArg) const +{ + if (!inActiveDocumentContext()) + return; + const ListHashSet<RefPtrWillBeMember<FontFace> >& cssConnectedFaces = cssConnectedFontFaceList(); + WillBeHeapVector<RefPtrWillBeMember<FontFace> > fontFaces; + fontFaces.reserveInitialCapacity(cssConnectedFaces.size() + m_nonCSSConnectedFaces.size()); + for (ListHashSet<RefPtrWillBeMember<FontFace> >::const_iterator it = cssConnectedFaces.begin(); it != cssConnectedFaces.end(); ++it) + fontFaces.append(*it); + for (ListHashSet<RefPtrWillBeMember<FontFace> >::const_iterator it = m_nonCSSConnectedFaces.begin(); it != m_nonCSSConnectedFaces.end(); ++it) + fontFaces.append(*it); + + for (size_t i = 0; i < fontFaces.size(); ++i) { + FontFace* face = fontFaces[i].get(); + if (thisArg) + callback->handleItem(*thisArg, face, face, const_cast<FontFaceSet*>(this)); + else + callback->handleItem(face, face, const_cast<FontFaceSet*>(this)); + } +} + +unsigned long FontFaceSet::size() const +{ + if (!inActiveDocumentContext()) + return m_nonCSSConnectedFaces.size(); + return cssConnectedFontFaceList().size() + m_nonCSSConnectedFaces.size(); +} + void FontFaceSet::fireDoneEventIfPossible() { if (m_shouldFireLoadingEvent) return; - if (m_loadingCount || (!hasLoadedFonts() && m_readyResolvers.isEmpty())) + if (!m_loadingFonts.isEmpty() || (!hasLoadedFonts() && m_readyResolvers.isEmpty())) return; // If the layout was invalidated in between when we thought layout @@ -272,8 +415,8 @@ void FontFaceSet::fireDoneEventIfPossible() return; if (hasLoadedFonts()) { - RefPtr<CSSFontFaceLoadEvent> doneEvent; - RefPtr<CSSFontFaceLoadEvent> errorEvent; + RefPtrWillBeRawPtr<CSSFontFaceLoadEvent> doneEvent = nullptr; + RefPtrWillBeRawPtr<CSSFontFaceLoadEvent> errorEvent = nullptr; doneEvent = CSSFontFaceLoadEvent::createForFontFaces(EventTypeNames::loadingdone, m_loadedFonts); m_loadedFonts.clear(); if (!m_failedFonts.isEmpty()) { @@ -299,60 +442,63 @@ static const String& nullToSpace(const String& s) return s.isNull() ? space : s; } -Vector<RefPtr<FontFace> > FontFaceSet::match(const String& fontString, const String& text, ExceptionState& exceptionState) +ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontString, const String& text) { - Vector<RefPtr<FontFace> > matchedFonts; + if (!inActiveDocumentContext()) + return ScriptPromise(); Font font; if (!resolveFontStyle(fontString, font)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return matchedFonts; + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->reject(DOMError::create(SyntaxError, "Could not resolve '" + fontString + "' as a font.")); + return promise; } - for (const FontFamily* f = &font.family(); f; f = f->next()) { - CSSSegmentedFontFace* face = document()->styleEngine()->fontSelector()->getFontFace(font.fontDescription(), f->family()); - if (face) - matchedFonts.append(face->fontFaces(nullToSpace(text))); - } - return matchedFonts; -} - -ScriptPromise FontFaceSet::load(const String& fontString, const String& text, ExceptionState& exceptionState) -{ - Font font; - if (!resolveFontStyle(fontString, font)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); - return ScriptPromise(); + FontFaceCache* fontFaceCache = document()->styleEngine()->fontSelector()->fontFaceCache(); + FontFaceArray faces; + for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) { + CSSSegmentedFontFace* segmentedFontFace = fontFaceCache->get(font.fontDescription(), f->family()); + if (segmentedFontFace) + segmentedFontFace->match(nullToSpace(text), faces); } - Document* d = document(); - ScriptPromise promise = ScriptPromise::createPending(executionContext()); - RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(font.family(), promise, executionContext()); - for (const FontFamily* f = &font.family(); f; f = f->next()) { - CSSSegmentedFontFace* face = d->styleEngine()->fontSelector()->getFontFace(font.fontDescription(), f->family()); - if (!face) { - resolver->error(d); - continue; - } - face->loadFont(font.fontDescription(), nullToSpace(text), resolver); - } + RefPtrWillBeRawPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(faces, scriptState); + ScriptPromise promise = resolver->promise(); + resolver->loadFonts(executionContext()); // After this, resolver->promise() may return null. return promise; } bool FontFaceSet::check(const String& fontString, const String& text, ExceptionState& exceptionState) { + if (!inActiveDocumentContext()) + return false; + Font font; if (!resolveFontStyle(fontString, font)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "Could not resolve '" + fontString + "' as a font."); return false; } - for (const FontFamily* f = &font.family(); f; f = f->next()) { - CSSSegmentedFontFace* face = document()->styleEngine()->fontSelector()->getFontFace(font.fontDescription(), f->family()); - if (!face || !face->checkFont(nullToSpace(text))) - return false; + CSSFontSelector* fontSelector = document()->styleEngine()->fontSelector(); + FontFaceCache* fontFaceCache = fontSelector->fontFaceCache(); + + bool hasLoadedFaces = false; + for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) { + CSSSegmentedFontFace* face = fontFaceCache->get(font.fontDescription(), f->family()); + if (face) { + if (!face->checkFont(nullToSpace(text))) + return false; + hasLoadedFaces = true; + } } - return true; + if (hasLoadedFaces) + return true; + for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) { + if (fontSelector->isPlatformFontAvailable(font.fontDescription(), f->family())) + return true; + } + return false; } bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) @@ -361,8 +507,8 @@ bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) return false; // Interpret fontString in the same way as the 'font' attribute of CanvasRenderingContext2D. - RefPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::create(); - CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, HTMLStandardMode, 0); + RefPtrWillBeRawPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::create(); + BisonCSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, HTMLStandardMode, 0); if (parsedStyle->isEmpty()) return false; @@ -401,12 +547,26 @@ bool FontFaceSet::resolveFontStyle(const String& fontString, Font& font) return true; } -void FontFaceSet::FontLoadHistogram::record() +void FontFaceSet::FontLoadHistogram::updateStatus(FontFace* fontFace) { - if (m_recorded) + if (m_status == Reported) return; - m_recorded = true; - blink::Platform::current()->histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1, 100, 50); + if (fontFace->hadBlankText()) + m_status = HadBlankText; + else if (m_status == NoWebFonts) + m_status = DidNotHaveBlankText; +} + +void FontFaceSet::FontLoadHistogram::record() +{ + if (!m_recorded) { + m_recorded = true; + blink::Platform::current()->histogramCustomCounts("WebFont.WebFontsInPage", m_count, 1, 100, 50); + } + if (m_status == HadBlankText || m_status == DidNotHaveBlankText) { + blink::Platform::current()->histogramEnumeration("WebFont.HadBlankText", m_status == HadBlankText ? 1 : 0, 2); + m_status = Reported; + } } static const char* supplementName() @@ -414,9 +574,9 @@ static const char* supplementName() return "FontFaceSet"; } -PassRefPtr<FontFaceSet> FontFaceSet::from(Document* document) +PassRefPtrWillBeRawPtr<FontFaceSet> FontFaceSet::from(Document& document) { - RefPtr<FontFaceSet> fonts = static_cast<FontFaceSet*>(SupplementType::from(document, supplementName())); + RefPtrWillBeRawPtr<FontFaceSet> fonts = static_cast<FontFaceSet*>(SupplementType::from(document, supplementName())); if (!fonts) { fonts = FontFaceSet::create(document); SupplementType::provideTo(document, supplementName(), fonts); @@ -425,11 +585,22 @@ PassRefPtr<FontFaceSet> FontFaceSet::from(Document* document) return fonts.release(); } -void FontFaceSet::didLayout(Document* document) +void FontFaceSet::didLayout(Document& document) { if (FontFaceSet* fonts = static_cast<FontFaceSet*>(SupplementType::from(document, supplementName()))) fonts->didLayout(); } +#if ENABLE(OILPAN) +void FontFaceSet::trace(Visitor* visitor) +{ + visitor->trace(m_loadingFonts); + visitor->trace(m_loadedFonts); + visitor->trace(m_failedFonts); + visitor->trace(m_nonCSSConnectedFaces); + DocumentSupplement::trace(visitor); + EventTargetWithInlineData::trace(visitor); +} +#endif } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/FontFaceSet.h b/chromium/third_party/WebKit/Source/core/css/FontFaceSet.h index ebad1329e07..5e1f54347ea 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontFaceSet.h +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceSet.h @@ -28,10 +28,10 @@ #include "bindings/v8/ScriptPromise.h" #include "core/css/FontFace.h" +#include "core/css/FontFaceSetForEachCallback.h" #include "core/dom/ActiveDOMObject.h" #include "core/events/EventListener.h" #include "core/events/EventTarget.h" -#include "core/events/ThreadLocalEventNames.h" #include "platform/AsyncMethodRunner.h" #include "platform/RefCountedSupplement.h" #include "wtf/PassRefPtr.h" @@ -45,17 +45,27 @@ namespace WebCore { +class CSSFontFace; class CSSFontFaceSource; +class CSSFontSelector; class Dictionary; class Document; class ExceptionState; class Font; +class FontFaceCache; class FontResource; class FontsReadyPromiseResolver; class ExecutionContext; -class FontFaceSet : public RefCountedSupplement<Document, FontFaceSet>, public ActiveDOMObject, public EventTargetWithInlineData { - REFCOUNTED_EVENT_TARGET(FontFaceSet); +#if ENABLE(OILPAN) +class FontFaceSet FINAL : public GarbageCollectedFinalized<FontFaceSet>, public HeapSupplement<Document>, public ActiveDOMObject, public EventTargetWithInlineData { + USING_GARBAGE_COLLECTED_MIXIN(FontFaceSet); + typedef HeapSupplement<Document> SupplementType; +#else +class FontFaceSet FINAL : public RefCountedSupplement<Document, FontFaceSet>, public ActiveDOMObject, public EventTargetWithInlineData { + DEFINE_EVENT_TARGET_REFCOUNTING(RefCounted<FontFaceSet>); + typedef RefCountedSupplement<Document, FontFaceSet> SupplementType; +#endif public: virtual ~FontFaceSet(); @@ -63,11 +73,18 @@ public: DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingdone); DEFINE_ATTRIBUTE_EVENT_LISTENER(loadingerror); - Vector<RefPtr<FontFace> > match(const String& font, const String& text, ExceptionState&); bool check(const String& font, const String& text, ExceptionState&); - ScriptPromise load(const String& font, const String& text, ExceptionState&); - ScriptPromise ready(); + ScriptPromise load(ScriptState*, const String& font, const String& text); + ScriptPromise ready(ScriptState*); + void add(FontFace*, ExceptionState&); + void clear(); + bool remove(FontFace*, ExceptionState&); + void forEach(PassOwnPtr<FontFaceSetForEachCallback>, ScriptValue& thisArg) const; + void forEach(PassOwnPtr<FontFaceSetForEachCallback>) const; + bool has(FontFace*, ExceptionState&) const; + + unsigned long size() const; AtomicString status() const; virtual ExecutionContext* executionContext() const OVERRIDE; @@ -85,44 +102,58 @@ public: virtual void resume() OVERRIDE; virtual void stop() OVERRIDE; - static PassRefPtr<FontFaceSet> from(Document*); - static void didLayout(Document*); + static PassRefPtrWillBeRawPtr<FontFaceSet> from(Document&); + static void didLayout(Document&); -private: - typedef RefCountedSupplement<Document, FontFaceSet> SupplementType; + void addFontFacesToFontFaceCache(FontFaceCache*, CSSFontSelector*); + +#if ENABLE(OILPAN) + virtual void trace(Visitor*) OVERRIDE; +#endif - static PassRefPtr<FontFaceSet> create(Document* document) +private: + static PassRefPtrWillBeRawPtr<FontFaceSet> create(Document& document) { - return adoptRef<FontFaceSet>(new FontFaceSet(document)); + return adoptRefWillBeNoop(new FontFaceSet(document)); } class FontLoadHistogram { public: - FontLoadHistogram() : m_count(0), m_recorded(false) { } + enum Status { NoWebFonts, HadBlankText, DidNotHaveBlankText, Reported }; + FontLoadHistogram() : m_status(NoWebFonts), m_count(0), m_recorded(false) { } void incrementCount() { m_count++; } + void updateStatus(FontFace*); void record(); private: + Status m_status; int m_count; bool m_recorded; }; - FontFaceSet(Document*); + FontFaceSet(Document&); bool hasLoadedFonts() const { return !m_loadedFonts.isEmpty() || !m_failedFonts.isEmpty(); } - void queueDoneEvent(FontFace*); + bool inActiveDocumentContext() const; + void forEachInternal(PassOwnPtr<FontFaceSetForEachCallback>, ScriptValue* thisArg) const; + void addToLoadingFonts(PassRefPtrWillBeRawPtr<FontFace>); + void removeFromLoadingFonts(PassRefPtrWillBeRawPtr<FontFace>); void fireLoadingEvent(); void fireDoneEventIfPossible(); bool resolveFontStyle(const String&, Font&); void handlePendingEventsAndPromisesSoon(); void handlePendingEventsAndPromises(); + const ListHashSet<RefPtrWillBeMember<FontFace> >& cssConnectedFontFaceList() const; + bool isCSSConnectedFontFace(FontFace*) const; - unsigned m_loadingCount; + WillBeHeapHashSet<RefPtrWillBeMember<FontFace> > m_loadingFonts; bool m_shouldFireLoadingEvent; Vector<OwnPtr<FontsReadyPromiseResolver> > m_readyResolvers; FontFaceArray m_loadedFonts; FontFaceArray m_failedFonts; + // FIXME: Oilpan: replace with a HeapListHashSet or HeapLinkedHashSet. + ListHashSet<RefPtrWillBeMember<FontFace> > m_nonCSSConnectedFaces; AsyncMethodRunner<FontFaceSet> m_asyncRunner; diff --git a/chromium/third_party/WebKit/Source/core/css/FontFaceSet.idl b/chromium/third_party/WebKit/Source/core/css/FontFaceSet.idl index 643c335b562..10bc2f71838 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontFaceSet.idl +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceSet.idl @@ -32,7 +32,7 @@ enum FontFaceSetLoadStatus { "loading", "loaded" }; [ ActiveDOMObject, - GenerateVisitDOMWrapper=document, + SetWrapperReferenceFrom=document, NoInterfaceObject, RuntimeEnabled=FontLoadEvents, ] interface FontFaceSet : EventTarget { @@ -41,10 +41,16 @@ enum FontFaceSetLoadStatus { "loading", "loaded" }; attribute EventHandler onloadingdone; attribute EventHandler onloadingerror; - [RaisesException] sequence<FontFace> match(DOMString font, [Default=NullString] optional DOMString text); - [RaisesException] boolean check(DOMString font, [Default=NullString] optional DOMString text); - [RaisesException] Promise load(DOMString font, [Default=NullString] optional DOMString text); - Promise ready(); + [RaisesException] boolean check(DOMString font, optional DOMString text = null); + [CallWith=ScriptState] Promise load(DOMString font, optional DOMString text = null); + [MeasureAs=FontFaceSetReady, CallWith=ScriptState] Promise ready(); + [RaisesException] void add(FontFace fontFace); + void clear(); + [RaisesException, ImplementedAs=remove] boolean delete(FontFace fontFace); + void forEach(FontFaceSetForEachCallback callback, optional any thisArg); + [RaisesException] boolean has(FontFace fontFace); + + readonly attribute unsigned long size; readonly attribute FontFaceSetLoadStatus status; }; diff --git a/chromium/third_party/WebKit/Source/core/css/FontFaceSetForEachCallback.h b/chromium/third_party/WebKit/Source/core/css/FontFaceSetForEachCallback.h new file mode 100644 index 00000000000..8550e24bbaf --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceSetForEachCallback.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 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 FontFaceSetForEachCallback_h +#define FontFaceSetForEachCallback_h + +#include "bindings/v8/ScriptValue.h" + +namespace WebCore { + +class FontFace; +class FontFaceSet; + +class FontFaceSetForEachCallback { +public: + virtual ~FontFaceSetForEachCallback() { } + virtual bool handleItem(ScriptValue thisValue, FontFace*, FontFace*, FontFaceSet*) = 0; + virtual bool handleItem(FontFace*, FontFace*, FontFaceSet*) = 0; +}; + +} // namespace WebCore + +#endif // FontFaceSetForEachCallback_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.idl b/chromium/third_party/WebKit/Source/core/css/FontFaceSetForEachCallback.idl index 3c88025beb9..6b9fdab7731 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMap.idl +++ b/chromium/third_party/WebKit/Source/core/css/FontFaceSetForEachCallback.idl @@ -11,6 +11,9 @@ * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,12 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -interface CSSVariablesMap { - readonly attribute unsigned long size; - DOMString get(DOMString name); - boolean has(DOMString name); - [RaisesException] void set(DOMString name, DOMString value); - [ImplementedAs=remove] boolean delete(DOMString name); - [RaisesException] void clear(); - void forEach(CSSVariablesMapForEachCallback callback, optional any thisArg); +callback interface FontFaceSetForEachCallback { + [CallWith=ThisValue] boolean handleItem(FontFace fontFace, FontFace fontFaceAgain, FontFaceSet set); + boolean handleItem(FontFace fontFace, FontFace fontFaceAgain, FontFaceSet set); }; diff --git a/chromium/third_party/WebKit/Source/core/css/FontLoader.cpp b/chromium/third_party/WebKit/Source/core/css/FontLoader.cpp new file mode 100644 index 00000000000..189c37cf93c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/FontLoader.cpp @@ -0,0 +1,95 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/FontLoader.h" + +#include "core/css/CSSFontSelector.h" +#include "core/fetch/FontResource.h" +#include "core/fetch/ResourceFetcher.h" + +namespace WebCore { + +FontLoader::FontLoader(CSSFontSelector* fontSelector, ResourceFetcher* resourceFetcher) + : m_beginLoadingTimer(this, &FontLoader::beginLoadTimerFired) + , m_fontSelector(fontSelector) + , m_resourceFetcher(resourceFetcher) +{ +} + +FontLoader::~FontLoader() +{ +#if ENABLE(OILPAN) + if (!m_resourceFetcher) { + ASSERT(m_fontsToBeginLoading.isEmpty()); + return; + } + m_beginLoadingTimer.stop(); + + // When the m_fontsToBeginLoading vector is destroyed it will decrement the + // request counts on the ResourceFetcher for all the fonts that were pending + // at the time the FontLoader dies. +#endif +} + +void FontLoader::addFontToBeginLoading(FontResource* fontResource) +{ + if (!m_resourceFetcher || !fontResource->stillNeedsLoad()) + return; + + m_fontsToBeginLoading.append( + std::make_pair(fontResource, ResourceLoader::RequestCountTracker(m_resourceFetcher, fontResource))); + if (!m_beginLoadingTimer.isActive()) + m_beginLoadingTimer.startOneShot(0, FROM_HERE); +} + +void FontLoader::beginLoadTimerFired(Timer<WebCore::FontLoader>*) +{ + loadPendingFonts(); +} + +void FontLoader::loadPendingFonts() +{ + ASSERT(m_resourceFetcher); + + FontsToLoadVector fontsToBeginLoading; + fontsToBeginLoading.swap(m_fontsToBeginLoading); + for (FontsToLoadVector::iterator it = fontsToBeginLoading.begin(); it != fontsToBeginLoading.end(); ++it) { + FontResource* fontResource = it->first.get(); + fontResource->beginLoadIfNeeded(m_resourceFetcher); + } + + // When the local fontsToBeginLoading vector goes out of scope it will + // decrement the request counts on the ResourceFetcher for all the fonts + // that were just loaded. +} + +void FontLoader::fontFaceInvalidated() +{ + if (m_fontSelector) + m_fontSelector->fontFaceInvalidated(); +} + +#if !ENABLE(OILPAN) +void FontLoader::clearResourceFetcherAndFontSelector() +{ + if (!m_resourceFetcher) { + ASSERT(m_fontsToBeginLoading.isEmpty()); + return; + } + + m_beginLoadingTimer.stop(); + m_fontsToBeginLoading.clear(); + m_resourceFetcher = nullptr; + m_fontSelector = nullptr; +} +#endif + +void FontLoader::trace(Visitor* visitor) +{ + visitor->trace(m_resourceFetcher); + visitor->trace(m_fontSelector); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/FontLoader.h b/chromium/third_party/WebKit/Source/core/css/FontLoader.h new file mode 100644 index 00000000000..92f37275730 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/FontLoader.h @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FontLoader_h +#define FontLoader_h + +#include "core/fetch/ResourceLoader.h" +#include "core/fetch/ResourcePtr.h" +#include "platform/Timer.h" +#include "platform/heap/Handle.h" +#include "wtf/Vector.h" + +namespace WebCore { + +class CSSFontSelector; +class FontResource; + +class FontLoader : public RefCountedWillBeGarbageCollectedFinalized<FontLoader> { +public: + static PassRefPtrWillBeRawPtr<FontLoader> create(CSSFontSelector* fontSelector, ResourceFetcher* fetcher) + { + return adoptRefWillBeNoop(new FontLoader(fontSelector, fetcher)); + } + ~FontLoader(); + + void addFontToBeginLoading(FontResource*); + void loadPendingFonts(); + void fontFaceInvalidated(); + +#if !ENABLE(OILPAN) + void clearResourceFetcherAndFontSelector(); +#endif + + void trace(Visitor*); + +private: + FontLoader(CSSFontSelector*, ResourceFetcher*); + void beginLoadTimerFired(Timer<FontLoader>*); + + Timer<FontLoader> m_beginLoadingTimer; + + typedef Vector<std::pair<ResourcePtr<FontResource>, ResourceLoader::RequestCountTracker> > FontsToLoadVector; + FontsToLoadVector m_fontsToBeginLoading; + RawPtrWillBeMember<CSSFontSelector> m_fontSelector; + RawPtrWillBeMember<ResourceFetcher> m_resourceFetcher; +}; + +} // namespace WebCore + +#endif // FontLoader_h diff --git a/chromium/third_party/WebKit/Source/core/css/FontSize.cpp b/chromium/third_party/WebKit/Source/core/css/FontSize.cpp index 4b545c458a8..6c1b53c5282 100644 --- a/chromium/third_party/WebKit/Source/core/css/FontSize.cpp +++ b/chromium/third_party/WebKit/Source/core/css/FontSize.cpp @@ -29,7 +29,7 @@ #include "config.h" #include "core/css/FontSize.h" -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" #include "core/dom/Document.h" #include "core/frame/Settings.h" diff --git a/chromium/third_party/WebKit/Source/core/css/HashTools.h b/chromium/third_party/WebKit/Source/core/css/HashTools.h index c86f62d3343..309ab164218 100644 --- a/chromium/third_party/WebKit/Source/core/css/HashTools.h +++ b/chromium/third_party/WebKit/Source/core/css/HashTools.h @@ -32,8 +32,8 @@ struct Value { int id; }; -const Property* findProperty(register const char* str, register unsigned int len); -const Value* findValue(register const char* str, register unsigned int len); +const Property* findProperty(register const char* str, register unsigned len); +const Value* findValue(register const char* str, register unsigned len); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/InspectorCSSOMWrappers.cpp b/chromium/third_party/WebKit/Source/core/css/InspectorCSSOMWrappers.cpp deleted file mode 100644 index 5a99c072010..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/InspectorCSSOMWrappers.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) - * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. - * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> - * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * Copyright (C) Research In Motion Limited 2011. All rights reserved. - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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. - */ - -#include "config.h" -#include "core/css/InspectorCSSOMWrappers.h" - -#include "core/css/CSSDefaultStyleSheets.h" -#include "core/css/CSSImportRule.h" -#include "core/css/CSSMediaRule.h" -#include "core/css/CSSRegionRule.h" -#include "core/css/CSSRule.h" -#include "core/css/CSSStyleRule.h" -#include "core/css/CSSStyleSheet.h" -#include "core/css/CSSSupportsRule.h" -#include "core/css/StyleSheetContents.h" -#include "core/dom/StyleEngine.h" - -namespace WebCore { - -void InspectorCSSOMWrappers::collectFromStyleSheetIfNeeded(CSSStyleSheet* styleSheet) -{ - if (!m_styleRuleToCSSOMWrapperMap.isEmpty()) - collect(styleSheet); -} - -void InspectorCSSOMWrappers::reset() -{ - m_styleRuleToCSSOMWrapperMap.clear(); - m_styleSheetCSSOMWrapperSet.clear(); -} - -template <class ListType> -void InspectorCSSOMWrappers::collect(ListType* listType) -{ - if (!listType) - return; - unsigned size = listType->length(); - for (unsigned i = 0; i < size; ++i) { - CSSRule* cssRule = listType->item(i); - switch (cssRule->type()) { - case CSSRule::IMPORT_RULE: - collect(toCSSImportRule(cssRule)->styleSheet()); - break; - case CSSRule::MEDIA_RULE: - collect(toCSSMediaRule(cssRule)); - break; - case CSSRule::SUPPORTS_RULE: - collect(toCSSSupportsRule(cssRule)); - break; - case CSSRule::WEBKIT_REGION_RULE: - collect(toCSSRegionRule(cssRule)); - break; - case CSSRule::STYLE_RULE: - m_styleRuleToCSSOMWrapperMap.add(toCSSStyleRule(cssRule)->styleRule(), toCSSStyleRule(cssRule)); - break; - default: - break; - } - } -} - -void InspectorCSSOMWrappers::collectFromStyleSheetContents(HashSet<RefPtr<CSSStyleSheet> >& sheetWrapperSet, StyleSheetContents* styleSheet) -{ - if (!styleSheet) - return; - RefPtr<CSSStyleSheet> styleSheetWrapper = CSSStyleSheet::create(styleSheet); - sheetWrapperSet.add(styleSheetWrapper); - collect(styleSheetWrapper.get()); -} - -void InspectorCSSOMWrappers::collectFromStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& sheets) -{ - for (unsigned i = 0; i < sheets.size(); ++i) - collect(sheets[i].get()); -} - -void InspectorCSSOMWrappers::collectFromStyleEngine(StyleEngine* styleSheetCollection) -{ - Vector<const Vector<RefPtr<CSSStyleSheet> >*> activeAuthorStyleSheets; - styleSheetCollection->getActiveAuthorStyleSheets(activeAuthorStyleSheets); - for (size_t i = 0; i < activeAuthorStyleSheets.size(); ++i) - collectFromStyleSheets(*activeAuthorStyleSheets[i]); -} - -CSSStyleRule* InspectorCSSOMWrappers::getWrapperForRuleInSheets(StyleRule* rule, StyleEngine* styleSheetCollection) -{ - if (m_styleRuleToCSSOMWrapperMap.isEmpty()) { - collectFromStyleSheetContents(m_styleSheetCSSOMWrapperSet, CSSDefaultStyleSheets::defaultStyleSheet); - collectFromStyleSheetContents(m_styleSheetCSSOMWrapperSet, CSSDefaultStyleSheets::viewportStyleSheet); - collectFromStyleSheetContents(m_styleSheetCSSOMWrapperSet, CSSDefaultStyleSheets::quirksStyleSheet); - collectFromStyleSheetContents(m_styleSheetCSSOMWrapperSet, CSSDefaultStyleSheets::svgStyleSheet); - collectFromStyleSheetContents(m_styleSheetCSSOMWrapperSet, CSSDefaultStyleSheets::mediaControlsStyleSheet); - collectFromStyleSheetContents(m_styleSheetCSSOMWrapperSet, CSSDefaultStyleSheets::fullscreenStyleSheet); - - collectFromStyleEngine(styleSheetCollection); - } - return m_styleRuleToCSSOMWrapperMap.get(rule); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/InspectorCSSOMWrappers.h b/chromium/third_party/WebKit/Source/core/css/InspectorCSSOMWrappers.h deleted file mode 100644 index fda87899fe7..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/InspectorCSSOMWrappers.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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 InspectorCSSOMWrappers_h -#define InspectorCSSOMWrappers_h - -#include "wtf/Forward.h" -#include "wtf/HashMap.h" -#include "wtf/HashSet.h" -#include "wtf/Vector.h" - -namespace WebCore { - -class CSSStyleRule; -class CSSStyleSheet; -class StyleRule; -class StyleEngine; -class StyleSheetContents; - -class InspectorCSSOMWrappers { -public: - // WARNING. This will construct CSSOM wrappers for all style rules and cache them in a map for significant memory cost. - // It is here to support inspector. Don't use for any regular engine functions. - CSSStyleRule* getWrapperForRuleInSheets(StyleRule*, StyleEngine*); - void collectFromStyleSheetIfNeeded(CSSStyleSheet*); - void reset(); - -private: - template <class ListType> - void collect(ListType*); - - void collectFromStyleSheetContents(HashSet<RefPtr<CSSStyleSheet> >& sheetWrapperSet, StyleSheetContents*); - void collectFromStyleSheets(const Vector<RefPtr<CSSStyleSheet> >&); - void collectFromStyleEngine(StyleEngine*); - - HashMap<StyleRule*, RefPtr<CSSStyleRule> > m_styleRuleToCSSOMWrapperMap; - HashSet<RefPtr<CSSStyleSheet> > m_styleSheetCSSOMWrapperSet; -}; - -} // namespace WebCore - -#endif // InspectorCSSOMWrappers_h diff --git a/chromium/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp b/chromium/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp new file mode 100644 index 00000000000..a920bdfd0bc --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/LocalFontFaceSource.cpp @@ -0,0 +1,36 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/LocalFontFaceSource.h" + +#include "platform/fonts/FontCache.h" +#include "platform/fonts/FontDescription.h" +#include "platform/fonts/SimpleFontData.h" +#include "public/platform/Platform.h" + +namespace WebCore { + +bool LocalFontFaceSource::isLocalFontAvailable(const FontDescription& fontDescription) +{ + return FontCache::fontCache()->isPlatformFontAvailable(fontDescription, m_fontName); +} + +PassRefPtr<SimpleFontData> LocalFontFaceSource::createFontData(const FontDescription& fontDescription) +{ + // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter. + RefPtr<SimpleFontData> fontData = FontCache::fontCache()->getFontData(fontDescription, m_fontName, true); + m_histograms.record(fontData); + return fontData.release(); +} + +void LocalFontFaceSource::LocalFontHistograms::record(bool loadSuccess) +{ + if (m_reported) + return; + m_reported = true; + blink::Platform::current()->histogramEnumeration("WebFont.LocalFontUsed", loadSuccess ? 1 : 0, 2); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/LocalFontFaceSource.h b/chromium/third_party/WebKit/Source/core/css/LocalFontFaceSource.h new file mode 100644 index 00000000000..3036e4f9723 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/LocalFontFaceSource.h @@ -0,0 +1,36 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef LocalFontFaceSource_h +#define LocalFontFaceSource_h + +#include "core/css/CSSFontFaceSource.h" +#include "wtf/text/AtomicString.h" + +namespace WebCore { + +class LocalFontFaceSource : public CSSFontFaceSource { +public: + LocalFontFaceSource(const String& fontName) : m_fontName(fontName) { } + virtual bool isLocal() const { return true; } + virtual bool isLocalFontAvailable(const FontDescription&) OVERRIDE; + +private: + virtual PassRefPtr<SimpleFontData> createFontData(const FontDescription&) OVERRIDE; + + class LocalFontHistograms { + public: + LocalFontHistograms() : m_reported(false) { } + void record(bool loadSuccess); + private: + bool m_reported; + }; + + AtomicString m_fontName; + LocalFontHistograms m_histograms; +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.h b/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.h deleted file mode 100644 index b249625420a..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2005, 2013 Apple Inc. All rights reserved. - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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 MediaFeatureNames_h -#define MediaFeatureNames_h - -#include "wtf/text/AtomicString.h" - -namespace WebCore { -namespace MediaFeatureNames { - -#define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \ - macro(deprecatedTransition, "-webkit-transition") \ - macro(color, "color") \ - macro(colorIndex, "color-index") \ - macro(grid, "grid") \ - macro(monochrome, "monochrome") \ - macro(height, "height") \ - macro(hover, "hover") \ - macro(width, "width") \ - macro(orientation, "orientation") \ - macro(aspectRatio, "aspect-ratio") \ - macro(deviceAspectRatio, "device-aspect-ratio") \ - macro(devicePixelRatio, "-webkit-device-pixel-ratio") \ - macro(deviceHeight, "device-height") \ - macro(deviceWidth, "device-width") \ - macro(maxColor, "max-color") \ - macro(maxColorIndex, "max-color-index") \ - macro(maxAspectRatio, "max-aspect-ratio") \ - macro(maxDeviceAspectRatio, "max-device-aspect-ratio") \ - macro(maxDevicePixelRatio, "-webkit-max-device-pixel-ratio") \ - macro(maxDeviceHeight, "max-device-height") \ - macro(maxDeviceWidth, "max-device-width") \ - macro(maxHeight, "max-height") \ - macro(maxMonochrome, "max-monochrome") \ - macro(maxWidth, "max-width") \ - macro(maxResolution, "max-resolution") \ - macro(minColor, "min-color") \ - macro(minColorIndex, "min-color-index") \ - macro(minAspectRatio, "min-aspect-ratio") \ - macro(minDeviceAspectRatio, "min-device-aspect-ratio") \ - macro(minDevicePixelRatio, "-webkit-min-device-pixel-ratio") \ - macro(minDeviceHeight, "min-device-height") \ - macro(minDeviceWidth, "min-device-width") \ - macro(minHeight, "min-height") \ - macro(minMonochrome, "min-monochrome") \ - macro(minWidth, "min-width") \ - macro(minResolution, "min-resolution") \ - macro(pointer, "pointer") \ - macro(resolution, "resolution") \ - macro(transform2d, "-webkit-transform-2d") \ - macro(transform3d, "-webkit-transform-3d") \ - macro(scan, "scan") \ - macro(animation, "-webkit-animation") \ - macro(viewMode, "-webkit-view-mode") - -// end of macro - -#ifndef CSS_MEDIAQUERY_NAMES_HIDE_GLOBALS -#define CSS_MEDIAQUERY_NAMES_DECLARE(name, str) extern const AtomicString name##MediaFeature; -CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(CSS_MEDIAQUERY_NAMES_DECLARE) -#undef CSS_MEDIAQUERY_NAMES_DECLARE -#endif - - void init(); - -} // namespace MediaFeatureNames -} // namespace WebCore - -#endif // MediaFeatureNames_h diff --git a/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.in b/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.in new file mode 100644 index 00000000000..f94bd9bdadd --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaFeatureNames.in @@ -0,0 +1,42 @@ +namespace="MediaFeature" +export="" + +color +color-index +grid +monochrome +height +hover +width +orientation +aspect-ratio +device-aspect-ratio +-webkit-device-pixel-ratio +device-height +device-width +max-color +max-color-index +max-aspect-ratio +max-device-aspect-ratio +-webkit-max-device-pixel-ratio +max-device-height +max-device-width +max-height +max-monochrome +max-width +max-resolution +min-color +min-color-index +min-aspect-ratio +min-device-aspect-ratio +-webkit-min-device-pixel-ratio +min-device-height +min-device-width +min-height +min-monochrome +min-width +min-resolution +pointer +resolution +-webkit-transform-3d +scan diff --git a/chromium/third_party/WebKit/Source/core/css/MediaList.cpp b/chromium/third_party/WebKit/Source/core/css/MediaList.cpp index 4a4442fb83d..69fe9145188 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaList.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaList.cpp @@ -21,13 +21,14 @@ #include "core/css/MediaList.h" #include "bindings/v8/ExceptionState.h" -#include "core/css/CSSParser.h" +#include "core/MediaFeatureNames.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSStyleSheet.h" -#include "core/css/MediaFeatureNames.h" #include "core/css/MediaQuery.h" #include "core/css/MediaQueryExp.h" +#include "core/css/parser/MediaQueryParser.h" #include "core/dom/Document.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "wtf/text/StringBuilder.h" namespace WebCore { @@ -57,29 +58,37 @@ MediaQuerySet::MediaQuerySet() } MediaQuerySet::MediaQuerySet(const MediaQuerySet& o) - : RefCounted<MediaQuerySet>() - , m_queries(o.m_queries.size()) + : m_queries(o.m_queries.size()) { for (unsigned i = 0; i < m_queries.size(); ++i) m_queries[i] = o.m_queries[i]->copy(); } -MediaQuerySet::~MediaQuerySet() +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQuerySet) + +PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQuerySet::create(const String& mediaString) { + if (mediaString.isEmpty()) + return MediaQuerySet::create(); + + if (RuntimeEnabledFeatures::mediaQueryParserEnabled()) + return MediaQueryParser::parseMediaQuerySet(mediaString); + + BisonCSSParser parser(strictCSSParserContext()); + return parser.parseMediaQueryList(mediaString); } -PassRefPtr<MediaQuerySet> MediaQuerySet::create(const String& mediaString) +PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQuerySet::createOffMainThread(const String& mediaString) { if (mediaString.isEmpty()) return MediaQuerySet::create(); - CSSParser parser(HTMLStandardMode); - return parser.parseMediaQueryList(mediaString); + return MediaQueryParser::parseMediaQuerySet(mediaString); } bool MediaQuerySet::set(const String& mediaString) { - RefPtr<MediaQuerySet> result = create(mediaString); + RefPtrWillBeRawPtr<MediaQuerySet> result = create(mediaString); m_queries.swap(result->m_queries); return true; } @@ -89,13 +98,13 @@ bool MediaQuerySet::add(const String& queryString) // To "parse a media query" for a given string means to follow "the parse // a media query list" steps and return "null" if more than one media query // is returned, or else the returned media query. - RefPtr<MediaQuerySet> result = create(queryString); + RefPtrWillBeRawPtr<MediaQuerySet> result = create(queryString); // Only continue if exactly one media query is found, as described above. if (result->m_queries.size() != 1) return true; - OwnPtr<MediaQuery> newQuery = result->m_queries[0].release(); + OwnPtrWillBeRawPtr<MediaQuery> newQuery = result->m_queries[0].release(); ASSERT(newQuery); // If comparing with any of the media queries in the collection of media @@ -115,13 +124,13 @@ bool MediaQuerySet::remove(const String& queryStringToRemove) // To "parse a media query" for a given string means to follow "the parse // a media query list" steps and return "null" if more than one media query // is returned, or else the returned media query. - RefPtr<MediaQuerySet> result = create(queryStringToRemove); + RefPtrWillBeRawPtr<MediaQuerySet> result = create(queryStringToRemove); // Only continue if exactly one media query is found, as described above. if (result->m_queries.size() != 1) return true; - OwnPtr<MediaQuery> newQuery = result->m_queries[0].release(); + OwnPtrWillBeRawPtr<MediaQuery> newQuery = result->m_queries[0].release(); ASSERT(newQuery); // Remove any media query from the collection of media queries for which @@ -139,7 +148,7 @@ bool MediaQuerySet::remove(const String& queryStringToRemove) return found; } -void MediaQuerySet::addMediaQuery(PassOwnPtr<MediaQuery> mediaQuery) +void MediaQuerySet::addMediaQuery(PassOwnPtrWillBeRawPtr<MediaQuery> mediaQuery) { m_queries.append(mediaQuery); } @@ -159,16 +168,25 @@ String MediaQuerySet::mediaText() const return text.toString(); } +void MediaQuerySet::trace(Visitor* visitor) +{ + // We don't support tracing of vectors of OwnPtrs (ie. OwnPtr<Vector<OwnPtr<MediaQuery> > >). + // Since this is a transitional object we are just ifdef'ing it out when oilpan is not enabled. +#if ENABLE(OILPAN) + visitor->trace(m_queries); +#endif +} + MediaList::MediaList(MediaQuerySet* mediaQueries, CSSStyleSheet* parentSheet) : m_mediaQueries(mediaQueries) , m_parentStyleSheet(parentSheet) - , m_parentRule(0) + , m_parentRule(nullptr) { } MediaList::MediaList(MediaQuerySet* mediaQueries, CSSRule* parentRule) : m_mediaQueries(mediaQueries) - , m_parentStyleSheet(0) + , m_parentStyleSheet(nullptr) , m_parentRule(parentRule) { } @@ -189,7 +207,7 @@ void MediaList::setMediaText(const String& value) String MediaList::item(unsigned index) const { - const Vector<OwnPtr<MediaQuery> >& queries = m_mediaQueries->queryVector(); + const WillBeHeapVector<OwnPtrWillBeMember<MediaQuery> >& queries = m_mediaQueries->queryVector(); if (index < queries.size()) return queries[index]->cssText(); return String(); @@ -201,7 +219,7 @@ void MediaList::deleteMedium(const String& medium, ExceptionState& exceptionStat bool success = m_mediaQueries->remove(medium); if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(NotFoundError); + exceptionState.throwDOMException(NotFoundError, "Failed to delete '" + medium + "'."); return; } if (m_parentStyleSheet) @@ -214,7 +232,7 @@ void MediaList::appendMedium(const String& medium, ExceptionState& exceptionStat bool success = m_mediaQueries->add(medium); if (!success) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidCharacterError); + exceptionState.throwDOMException(InvalidCharacterError, "The value provided ('" + medium + "') is not a valid medium."); return; } @@ -228,31 +246,37 @@ void MediaList::reattach(MediaQuerySet* mediaQueries) m_mediaQueries = mediaQueries; } -static void addResolutionWarningMessageToConsole(Document* document, const String& serializedExpression, const CSSPrimitiveValue* value) +void MediaList::trace(Visitor* visitor) +{ + visitor->trace(m_mediaQueries); + visitor->trace(m_parentStyleSheet); + visitor->trace(m_parentRule); +} + +static void addResolutionWarningMessageToConsole(Document* document, const String& serializedExpression, CSSPrimitiveValue::UnitType type) { ASSERT(document); - ASSERT(value); - DEFINE_STATIC_LOCAL(String, mediaQueryMessage, ("Consider using 'dppx' units instead of '%replacementUnits%', as in CSS '%replacementUnits%' means dots-per-CSS-%lengthUnit%, not dots-per-physical-%lengthUnit%, so does not correspond to the actual '%replacementUnits%' of a screen. In media query expression: ")); + DEFINE_STATIC_LOCAL(String, mediaQueryMessage, ("Consider using 'dppx' units, as in CSS '%replacementUnits%' means dots-per-CSS-%lengthUnit%, not dots-per-physical-%lengthUnit%, so does not correspond to the actual '%replacementUnits%' of a screen. In media query expression: ")); DEFINE_STATIC_LOCAL(String, mediaValueDPI, ("dpi")); DEFINE_STATIC_LOCAL(String, mediaValueDPCM, ("dpcm")); DEFINE_STATIC_LOCAL(String, lengthUnitInch, ("inch")); DEFINE_STATIC_LOCAL(String, lengthUnitCentimeter, ("centimeter")); - String message; - if (value->isDotsPerInch()) - message = String(mediaQueryMessage).replace("%replacementUnits%", mediaValueDPI).replace("%lengthUnit%", lengthUnitInch); - else if (value->isDotsPerCentimeter()) - message = String(mediaQueryMessage).replace("%replacementUnits%", mediaValueDPCM).replace("%lengthUnit%", lengthUnitCentimeter); + StringBuilder message; + if (CSSPrimitiveValue::isDotsPerInch(type)) + message.append(String(mediaQueryMessage).replace("%replacementUnits%", mediaValueDPI).replace("%lengthUnit%", lengthUnitInch)); + else if (CSSPrimitiveValue::isDotsPerCentimeter(type)) + message.append(String(mediaQueryMessage).replace("%replacementUnits%", mediaValueDPCM).replace("%lengthUnit%", lengthUnitCentimeter)); else ASSERT_NOT_REACHED(); message.append(serializedExpression); - document->addConsoleMessage(CSSMessageSource, DebugMessageLevel, message); + document->addConsoleMessage(CSSMessageSource, DebugMessageLevel, message.toString()); } -static inline bool isResolutionMediaFeature(const AtomicString& mediaFeature) +static inline bool isResolutionMediaFeature(const String& mediaFeature) { return mediaFeature == MediaFeatureNames::resolutionMediaFeature || mediaFeature == MediaFeatureNames::maxResolutionMediaFeature @@ -264,30 +288,36 @@ void reportMediaQueryWarningIfNeeded(Document* document, const MediaQuerySet* me if (!mediaQuerySet || !document) return; - const Vector<OwnPtr<MediaQuery> >& mediaQueries = mediaQuerySet->queryVector(); + const WillBeHeapVector<OwnPtrWillBeMember<MediaQuery> >& mediaQueries = mediaQuerySet->queryVector(); const size_t queryCount = mediaQueries.size(); if (!queryCount) return; + CSSPrimitiveValue::UnitType suspiciousType = CSSPrimitiveValue::CSS_UNKNOWN; + bool dotsPerPixelUsed = false; for (size_t i = 0; i < queryCount; ++i) { const MediaQuery* query = mediaQueries[i].get(); if (equalIgnoringCase(query->mediaType(), "print")) continue; - const ExpressionVector& expressions = query->expressions(); + const ExpressionHeapVector& expressions = query->expressions(); for (size_t j = 0; j < expressions.size(); ++j) { const MediaQueryExp* expression = expressions.at(j).get(); if (isResolutionMediaFeature(expression->mediaFeature())) { - CSSValue* cssValue = expression->value(); - if (cssValue && cssValue->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(cssValue); - if (primitiveValue->isDotsPerInch() || primitiveValue->isDotsPerCentimeter()) - addResolutionWarningMessageToConsole(document, mediaQuerySet->mediaText(), primitiveValue); + MediaQueryExpValue expValue = expression->expValue(); + if (expValue.isValue) { + if (CSSPrimitiveValue::isDotsPerPixel(expValue.unit)) + dotsPerPixelUsed = true; + else if (CSSPrimitiveValue::isDotsPerInch(expValue.unit) || CSSPrimitiveValue::isDotsPerCentimeter(expValue.unit)) + suspiciousType = expValue.unit; } } } } + + if (suspiciousType && !dotsPerPixelUsed) + addResolutionWarningMessageToConsole(document, mediaQuerySet->mediaText(), suspiciousType); } } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaList.h b/chromium/third_party/WebKit/Source/core/css/MediaList.h index 80223b03421..1e32424fa54 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaList.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaList.h @@ -22,6 +22,7 @@ #define MediaList_h #include "core/dom/ExceptionCode.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -37,43 +38,46 @@ class ExceptionState; class MediaList; class MediaQuery; -class MediaQuerySet : public RefCounted<MediaQuerySet> { +class MediaQuerySet : public RefCountedWillBeGarbageCollected<MediaQuerySet> { + DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQuerySet); public: - static PassRefPtr<MediaQuerySet> create() + static PassRefPtrWillBeRawPtr<MediaQuerySet> create() { - return adoptRef(new MediaQuerySet()); + return adoptRefWillBeNoop(new MediaQuerySet()); } - static PassRefPtr<MediaQuerySet> create(const String& mediaString); - ~MediaQuerySet(); + static PassRefPtrWillBeRawPtr<MediaQuerySet> create(const String& mediaString); + static PassRefPtrWillBeRawPtr<MediaQuerySet> createOffMainThread(const String& mediaString); bool set(const String&); bool add(const String&); bool remove(const String&); - void addMediaQuery(PassOwnPtr<MediaQuery>); + void addMediaQuery(PassOwnPtrWillBeRawPtr<MediaQuery>); - const Vector<OwnPtr<MediaQuery> >& queryVector() const { return m_queries; } + const WillBeHeapVector<OwnPtrWillBeMember<MediaQuery> >& queryVector() const { return m_queries; } String mediaText() const; - PassRefPtr<MediaQuerySet> copy() const { return adoptRef(new MediaQuerySet(*this)); } + PassRefPtrWillBeRawPtr<MediaQuerySet> copy() const { return adoptRefWillBeNoop(new MediaQuerySet(*this)); } + + void trace(Visitor*); private: MediaQuerySet(); MediaQuerySet(const MediaQuerySet&); - Vector<OwnPtr<MediaQuery> > m_queries; + WillBeHeapVector<OwnPtrWillBeMember<MediaQuery> > m_queries; }; -class MediaList : public RefCounted<MediaList> { +class MediaList : public RefCountedWillBeGarbageCollectedFinalized<MediaList> { public: - static PassRefPtr<MediaList> create(MediaQuerySet* mediaQueries, CSSStyleSheet* parentSheet) + static PassRefPtrWillBeRawPtr<MediaList> create(MediaQuerySet* mediaQueries, CSSStyleSheet* parentSheet) { - return adoptRef(new MediaList(mediaQueries, parentSheet)); + return adoptRefWillBeNoop(new MediaList(mediaQueries, parentSheet)); } - static PassRefPtr<MediaList> create(MediaQuerySet* mediaQueries, CSSRule* parentRule) + static PassRefPtrWillBeRawPtr<MediaList> create(MediaQuerySet* mediaQueries, CSSRule* parentRule) { - return adoptRef(new MediaList(mediaQueries, parentRule)); + return adoptRefWillBeNoop(new MediaList(mediaQueries, parentRule)); } ~MediaList(); @@ -89,20 +93,28 @@ public: // Not part of CSSOM. CSSRule* parentRule() const { return m_parentRule; } CSSStyleSheet* parentStyleSheet() const { return m_parentStyleSheet; } - void clearParentStyleSheet() { ASSERT(m_parentStyleSheet); m_parentStyleSheet = 0; } - void clearParentRule() { ASSERT(m_parentRule); m_parentRule = 0; } + +#if !ENABLE(OILPAN) + void clearParentStyleSheet() { ASSERT(m_parentStyleSheet); m_parentStyleSheet = nullptr; } + void clearParentRule() { ASSERT(m_parentRule); m_parentRule = nullptr; } +#endif + const MediaQuerySet* queries() const { return m_mediaQueries.get(); } void reattach(MediaQuerySet*); + void trace(Visitor*); + private: MediaList(); MediaList(MediaQuerySet*, CSSStyleSheet* parentSheet); MediaList(MediaQuerySet*, CSSRule* parentRule); - RefPtr<MediaQuerySet> m_mediaQueries; - CSSStyleSheet* m_parentStyleSheet; - CSSRule* m_parentRule; + RefPtrWillBeMember<MediaQuerySet> m_mediaQueries; + // Cleared in ~CSSStyleSheet destructor when oilpan is not enabled. + RawPtrWillBeMember<CSSStyleSheet> m_parentStyleSheet; + // Cleared in the ~CSSMediaRule and ~CSSImportRule destructors when oilpan is not enabled. + RawPtrWillBeMember<CSSRule> m_parentRule; }; // Adds message to inspector console whenever dpi or dpcm values are used for "screen" media. diff --git a/chromium/third_party/WebKit/Source/core/css/MediaList.idl b/chromium/third_party/WebKit/Source/core/css/MediaList.idl index 20ef3ec8835..8db9886f3f5 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaList.idl +++ b/chromium/third_party/WebKit/Source/core/css/MediaList.idl @@ -25,6 +25,7 @@ // Introduced in DOM Level 2: [ + WillBeGarbageCollected ] interface MediaList { [TreatNullAs=NullString, TreatReturnedNullStringAs=Null] attribute DOMString mediaText; diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQuery.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQuery.cpp index 681ac137fa2..ab20c2145d9 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQuery.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaQuery.cpp @@ -29,7 +29,9 @@ #include "config.h" #include "core/css/MediaQuery.h" +#include "core/MediaTypeNames.h" #include "core/css/MediaQueryExp.h" +#include "core/html/parser/HTMLParserIdioms.h" #include "wtf/NonCopyingSort.h" #include "wtf/text/StringBuilder.h" @@ -55,7 +57,7 @@ String MediaQuery::serialize() const return result.toString(); } - if (m_mediaType != "all" || m_restrictor != None) { + if (m_mediaType != MediaTypeNames::all || m_restrictor != None) { result.append(m_mediaType); result.append(" and "); } @@ -68,18 +70,23 @@ String MediaQuery::serialize() const return result.toString(); } -static bool expressionCompare(const OwnPtr<MediaQueryExp>& a, const OwnPtr<MediaQueryExp>& b) +static bool expressionCompare(const OwnPtrWillBeMember<MediaQueryExp>& a, const OwnPtrWillBeMember<MediaQueryExp>& b) { return codePointCompare(a->serialize(), b->serialize()) < 0; } -MediaQuery::MediaQuery(Restrictor r, const AtomicString& mediaType, PassOwnPtr<ExpressionVector> expressions) +PassOwnPtrWillBeRawPtr<MediaQuery> MediaQuery::createNotAll() +{ + return adoptPtrWillBeNoop(new MediaQuery(MediaQuery::Not, MediaTypeNames::all, nullptr)); +} + +MediaQuery::MediaQuery(Restrictor r, const String& mediaType, PassOwnPtrWillBeRawPtr<ExpressionHeapVector> expressions) : m_restrictor(r) - , m_mediaType(mediaType.lower()) + , m_mediaType(attemptStaticStringCreation(mediaType.lower())) , m_expressions(expressions) { if (!m_expressions) { - m_expressions = adoptPtr(new ExpressionVector); + m_expressions = adoptPtrWillBeNoop(new ExpressionHeapVector); return; } @@ -100,7 +107,7 @@ MediaQuery::MediaQuery(Restrictor r, const AtomicString& mediaType, PassOwnPtr<E MediaQuery::MediaQuery(const MediaQuery& o) : m_restrictor(o.m_restrictor) , m_mediaType(o.m_mediaType) - , m_expressions(adoptPtr(new ExpressionVector(o.m_expressions->size()))) + , m_expressions(adoptPtrWillBeNoop(new ExpressionHeapVector(o.m_expressions->size()))) , m_serializationCache(o.m_serializationCache) { for (unsigned i = 0; i < m_expressions->size(); ++i) @@ -126,4 +133,13 @@ String MediaQuery::cssText() const return m_serializationCache; } +void MediaQuery::trace(Visitor* visitor) +{ + // We don't support tracing of vectors of OwnPtrs (ie. OwnPtr<Vector<OwnPtr<MediaQuery> > >). + // Since this is a transitional object we are just ifdef'ing it out when oilpan is not enabled. +#if ENABLE(OILPAN) + visitor->trace(m_expressions); +#endif +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQuery.h b/chromium/third_party/WebKit/Source/core/css/MediaQuery.h index fa5463ee7df..6a5197578a7 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQuery.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaQuery.h @@ -29,6 +29,7 @@ #ifndef MediaQuery_h #define MediaQuery_h +#include "platform/heap/Handle.h" #include "wtf/PassOwnPtr.h" #include "wtf/Vector.h" #include "wtf/text/StringHash.h" @@ -37,32 +38,36 @@ namespace WebCore { class MediaQueryExp; -typedef Vector<OwnPtr<MediaQueryExp> > ExpressionVector; +typedef WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > ExpressionHeapVector; -class MediaQuery { - WTF_MAKE_FAST_ALLOCATED; +class MediaQuery : public NoBaseWillBeGarbageCollectedFinalized<MediaQuery> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: enum Restrictor { Only, Not, None }; - MediaQuery(Restrictor, const AtomicString& mediaType, PassOwnPtr<ExpressionVector> exprs); + static PassOwnPtrWillBeRawPtr<MediaQuery> createNotAll(); + + MediaQuery(Restrictor, const String& mediaType, PassOwnPtrWillBeRawPtr<ExpressionHeapVector> exprs); ~MediaQuery(); Restrictor restrictor() const { return m_restrictor; } - const ExpressionVector& expressions() const { return *m_expressions; } - const AtomicString& mediaType() const { return m_mediaType; } + const ExpressionHeapVector& expressions() const { return *m_expressions; } + const String& mediaType() const { return m_mediaType; } bool operator==(const MediaQuery& other) const; String cssText() const; - PassOwnPtr<MediaQuery> copy() const { return adoptPtr(new MediaQuery(*this)); } + PassOwnPtrWillBeRawPtr<MediaQuery> copy() const { return adoptPtrWillBeNoop(new MediaQuery(*this)); } + + void trace(Visitor*); private: MediaQuery(const MediaQuery&); Restrictor m_restrictor; - AtomicString m_mediaType; - OwnPtr<ExpressionVector> m_expressions; + String m_mediaType; + OwnPtrWillBeMember<ExpressionHeapVector> m_expressions; String m_serializationCache; String serialize() const; diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp index 5673e6e98fc..51a48409071 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.cpp @@ -30,23 +30,26 @@ #include "config.h" #include "core/css/MediaQueryEvaluator.h" -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" +#include "core/MediaFeatureNames.h" +#include "core/MediaFeatures.h" +#include "core/MediaTypeNames.h" #include "core/css/CSSAspectRatioValue.h" #include "core/css/CSSHelper.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSToLengthConversionData.h" -#include "core/css/MediaFeatureNames.h" #include "core/css/MediaList.h" #include "core/css/MediaQuery.h" +#include "core/css/MediaValuesDynamic.h" #include "core/css/resolver/MediaQueryResult.h" #include "core/dom/NodeRenderStyle.h" -#include "core/inspector/InspectorInstrumentation.h" -#include "core/frame/Frame.h" +#include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" -#include "core/page/Page.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" -#include "core/rendering/RenderLayerCompositor.h" +#include "core/inspector/InspectorInstrumentation.h" #include "core/rendering/RenderView.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" #include "core/rendering/style/RenderStyle.h" #include "platform/PlatformScreen.h" #include "platform/geometry/FloatRect.h" @@ -58,38 +61,38 @@ using namespace MediaFeatureNames; enum MediaFeaturePrefix { MinPrefix, MaxPrefix, NoPrefix }; -typedef bool (*EvalFunc)(CSSValue*, RenderStyle*, Frame*, MediaFeaturePrefix); +typedef bool (*EvalFunc)(const MediaQueryExpValue&, MediaFeaturePrefix, const MediaValues&); typedef HashMap<StringImpl*, EvalFunc> FunctionMap; static FunctionMap* gFunctionMap; MediaQueryEvaluator::MediaQueryEvaluator(bool mediaFeatureResult) - : m_frame(0) - , m_style(0) - , m_expResult(mediaFeatureResult) + : m_expectedResult(mediaFeatureResult) { } -MediaQueryEvaluator::MediaQueryEvaluator(const AtomicString& acceptedMediaType, bool mediaFeatureResult) +MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult) : m_mediaType(acceptedMediaType) - , m_frame(0) - , m_style(0) - , m_expResult(mediaFeatureResult) + , m_expectedResult(mediaFeatureResult) { } MediaQueryEvaluator::MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult) : m_mediaType(acceptedMediaType) - , m_frame(0) - , m_style(0) - , m_expResult(mediaFeatureResult) + , m_expectedResult(mediaFeatureResult) { } -MediaQueryEvaluator::MediaQueryEvaluator(const AtomicString& acceptedMediaType, Frame* frame, RenderStyle* style) +MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, LocalFrame* frame) : m_mediaType(acceptedMediaType) - , m_frame(frame) - , m_style(style) - , m_expResult(false) // Doesn't matter when we have m_frame and m_style. + , m_expectedResult(false) // Doesn't matter when we have m_frame and m_style. + , m_mediaValues(MediaValues::createDynamicIfFrameExists(frame)) +{ +} + +MediaQueryEvaluator::MediaQueryEvaluator(const String& acceptedMediaType, const MediaValues& mediaValues) + : m_mediaType(acceptedMediaType) + , m_expectedResult(false) // Doesn't matter when we have mediaValues. + , m_mediaValues(mediaValues.copy()) { } @@ -97,10 +100,10 @@ MediaQueryEvaluator::~MediaQueryEvaluator() { } -bool MediaQueryEvaluator::mediaTypeMatch(const AtomicString& mediaTypeToMatch) const +bool MediaQueryEvaluator::mediaTypeMatch(const String& mediaTypeToMatch) const { return mediaTypeToMatch.isEmpty() - || equalIgnoringCase(mediaTypeToMatch, "all") + || equalIgnoringCase(mediaTypeToMatch, MediaTypeNames::all) || equalIgnoringCase(mediaTypeToMatch, m_mediaType); } @@ -109,7 +112,7 @@ bool MediaQueryEvaluator::mediaTypeMatchSpecific(const char* mediaTypeToMatch) c // Like mediaTypeMatch, but without the special cases for "" and "all". ASSERT(mediaTypeToMatch); ASSERT(mediaTypeToMatch[0] != '\0'); - ASSERT(!equalIgnoringCase(mediaTypeToMatch, AtomicString("all"))); + ASSERT(!equalIgnoringCase(mediaTypeToMatch, MediaTypeNames::all)); return equalIgnoringCase(mediaTypeToMatch, m_mediaType); } @@ -123,7 +126,7 @@ bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, MediaQueryResultLi if (!querySet) return true; - const Vector<OwnPtr<MediaQuery> >& queries = querySet->queryVector(); + const WillBeHeapVector<OwnPtrWillBeMember<MediaQuery> >& queries = querySet->queryVector(); if (!queries.size()) return true; // Empty query list evaluates to true. @@ -133,21 +136,22 @@ bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, MediaQueryResultLi MediaQuery* query = queries[i].get(); if (mediaTypeMatch(query->mediaType())) { - const ExpressionVector& expressions = query->expressions(); + const ExpressionHeapVector& expressions = query->expressions(); // Iterate through expressions, stop if any of them eval to false (AND semantics). size_t j = 0; for (; j < expressions.size(); ++j) { bool exprResult = eval(expressions.at(j).get()); if (viewportDependentMediaQueryResults && expressions.at(j)->isViewportDependent()) - viewportDependentMediaQueryResults->append(adoptRef(new MediaQueryResult(*expressions.at(j), exprResult))); + viewportDependentMediaQueryResults->append(adoptRefWillBeNoop(new MediaQueryResult(*expressions.at(j), exprResult))); if (!exprResult) break; } // Assume true if we are at the end of the list, otherwise assume false. result = applyRestrictor(query->restrictor(), expressions.size() == j); - } else + } else { result = applyRestrictor(query->restrictor(), false); + } } return result; @@ -167,41 +171,38 @@ bool compareValue(T a, T b, MediaFeaturePrefix op) return false; } -static bool compareAspectRatioValue(CSSValue* value, int width, int height, MediaFeaturePrefix op) +static bool compareAspectRatioValue(const MediaQueryExpValue& value, int width, int height, MediaFeaturePrefix op) { - if (value->isAspectRatioValue()) { - CSSAspectRatioValue* aspectRatio = toCSSAspectRatioValue(value); - return compareValue(width * static_cast<int>(aspectRatio->denominatorValue()), height * static_cast<int>(aspectRatio->numeratorValue()), op); - } + if (value.isRatio) + return compareValue(width * static_cast<int>(value.denominator), height * static_cast<int>(value.numerator), op); return false; } -static bool numberValue(CSSValue* value, float& result) +static bool numberValue(const MediaQueryExpValue& value, float& result) { - if (value->isPrimitiveValue() - && toCSSPrimitiveValue(value)->isNumber()) { - result = toCSSPrimitiveValue(value)->getFloatValue(CSSPrimitiveValue::CSS_NUMBER); + if (value.isValue && value.unit == CSSPrimitiveValue::CSS_NUMBER) { + result = value.value; return true; } return false; } -static bool colorMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +static bool colorMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - int bitsPerComponent = screenDepthPerComponent(frame->view()); float number; - if (value) + int bitsPerComponent = mediaValues.colorBitsPerComponent(); + if (value.isValid()) return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op); return bitsPerComponent != 0; } -static bool colorIndexMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op) +static bool colorIndexMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues&) { // FIXME: We currently assume that we do not support indexed displays, as it is unknown // how to retrieve the information if the display mode is indexed. This matches Firefox. - if (!value) + if (!value.isValid()) return false; // Acording to spec, if the device does not use a color lookup table, the value is zero. @@ -209,65 +210,55 @@ static bool colorIndexMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, Me return numberValue(value, number) && compareValue(0, static_cast<int>(number), op); } -static bool monochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +static bool monochromeMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - if (!screenIsMonochrome(frame->view())) { - if (value) { + if (!mediaValues.monochromeBitsPerComponent()) { + if (value.isValid()) { float number; return numberValue(value, number) && compareValue(0, static_cast<int>(number), op); } return false; } - return colorMediaFeatureEval(value, style, frame, op); + return colorMediaFeatureEval(value, op, mediaValues); } -static IntSize viewportSize(FrameView* view) +static bool orientationMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return view->layoutSize(ScrollableArea::IncludeScrollbars); -} + int width = mediaValues.viewportWidth(); + int height = mediaValues.viewportHeight(); -static bool orientationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix) -{ - FrameView* view = frame->view(); - int width = viewportSize(view).width(); - int height = viewportSize(view).height(); - if (value && value->isPrimitiveValue()) { - const CSSValueID id = toCSSPrimitiveValue(value)->getValueID(); + if (value.isID) { if (width > height) // Square viewport is portrait. - return CSSValueLandscape == id; - return CSSValuePortrait == id; + return CSSValueLandscape == value.id; + return CSSValuePortrait == value.id; } // Expression (orientation) evaluates to true if width and height >= 0. return height >= 0 && width >= 0; } -static bool aspectRatioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +static bool aspectRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - if (value) { - FrameView* view = frame->view(); - return compareAspectRatioValue(value, viewportSize(view).width(), viewportSize(view).height(), op); - } + if (value.isValid()) + return compareAspectRatioValue(value, mediaValues.viewportWidth(), mediaValues.viewportHeight(), op); // ({,min-,max-}aspect-ratio) // assume if we have a device, its aspect ratio is non-zero. return true; } -static bool deviceAspectRatioMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +static bool deviceAspectRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - if (value) { - FloatRect sg = screenRect(frame->view()); - return compareAspectRatioValue(value, static_cast<int>(sg.width()), static_cast<int>(sg.height()), op); - } + if (value.isValid()) + return compareAspectRatioValue(value, mediaValues.deviceWidth(), mediaValues.deviceHeight(), op); // ({,min-,max-}device-aspect-ratio) // assume if we have a device, its aspect ratio is non-zero. return true; } -static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op) +static bool evalResolution(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { // According to MQ4, only 'screen', 'print' and 'speech' may match. // FIXME: What should speech match? https://www.w3.org/Style/CSS/Tracker/issues/348 @@ -277,31 +268,31 @@ static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op) // this method only got called if this media type matches the one defined // in the query. Thus, if if the document's media type is "print", the // media type of the query will either be "print" or "all". - String mediaType = frame->view()->mediaType(); - if (equalIgnoringCase(mediaType, "screen")) - actualResolution = clampTo<float>(frame->devicePixelRatio()); - else if (equalIgnoringCase(mediaType, "print")) { + if (mediaValues.screenMediaType()) { + actualResolution = clampTo<float>(mediaValues.devicePixelRatio()); + } else if (mediaValues.printMediaType()) { // The resolution of images while printing should not depend on the DPI // of the screen. Until we support proper ways of querying this info // we use 300px which is considered minimum for current printers. actualResolution = 300 / cssPixelsPerInch; } - if (!value) + if (!value.isValid()) return !!actualResolution; - if (!value->isPrimitiveValue()) + if (!value.isValue) return false; - CSSPrimitiveValue* resolution = toCSSPrimitiveValue(value); - - if (resolution->isNumber()) - return compareValue(actualResolution, resolution->getFloatValue(), op); + if (value.unit == CSSPrimitiveValue::CSS_NUMBER) + return compareValue(actualResolution, clampTo<float>(value.value), op); - if (!resolution->isResolution()) + if (!CSSPrimitiveValue::isResolution(value.unit)) return false; - if (resolution->isDotsPerCentimeter()) { + double canonicalFactor = CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(value.unit); + double dppxFactor = CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(CSSPrimitiveValue::CSS_DPPX); + float valueInDppx = clampTo<float>(value.value * (canonicalFactor / dppxFactor)); + if (CSSPrimitiveValue::isDotsPerCentimeter(value.unit)) { // To match DPCM to DPPX values, we limit to 2 decimal points. // The http://dev.w3.org/csswg/css3-values/#absolute-lengths recommends // "that the pixel unit refer to the whole number of device pixels that best @@ -309,111 +300,88 @@ static bool evalResolution(CSSValue* value, Frame* frame, MediaFeaturePrefix op) // point precision seems appropriate. return compareValue( floorf(0.5 + 100 * actualResolution) / 100, - floorf(0.5 + 100 * resolution->getFloatValue(CSSPrimitiveValue::CSS_DPPX)) / 100, op); + floorf(0.5 + 100 * valueInDppx) / 100, op); } - return compareValue(actualResolution, resolution->getFloatValue(CSSPrimitiveValue::CSS_DPPX), op); + return compareValue(actualResolution, valueInDppx, op); } -static bool devicePixelRatioMediaFeatureEval(CSSValue *value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +static bool devicePixelRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - return (!value || toCSSPrimitiveValue(value)->isNumber()) && evalResolution(value, frame, op); + UseCounter::count(mediaValues.document(), UseCounter::PrefixedDevicePixelRatioMediaFeature); + + return (!value.isValid() || value.unit == CSSPrimitiveValue::CSS_NUMBER) && evalResolution(value, op, mediaValues); } -static bool resolutionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +static bool resolutionMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& MediaValues) { - return (!value || toCSSPrimitiveValue(value)->isResolution()) && evalResolution(value, frame, op); + return (!value.isValid() || CSSPrimitiveValue::isResolution(value.unit)) && evalResolution(value, op, MediaValues); } -static bool gridMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op) +static bool gridMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues&) { // if output device is bitmap, grid: 0 == true // assume we have bitmap device float number; - if (value && numberValue(value, number)) + if (value.isValid() && numberValue(value, number)) return compareValue(static_cast<int>(number), 0, op); return false; } -static bool computeLength(CSSValue* value, bool strict, RenderStyle* initialStyle, int& result) +static bool computeLength(const MediaQueryExpValue& value, const MediaValues& mediaValues, int& result) { - if (!value->isPrimitiveValue()) + if (!value.isValue) return false; - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - - if (primitiveValue->isNumber()) { - result = primitiveValue->getIntValue(); - return !strict || !result; - } - - if (primitiveValue->isLength()) { - // Relative (like EM) and root relative (like REM) units are always resolved against - // the initial values for media queries, hence the two initialStyle parameters. - result = primitiveValue->computeLength<int>(CSSToLengthConversionData(initialStyle, initialStyle, 1.0 /* zoom */, true /* computingFontSize */)); - return true; + if (value.unit == CSSPrimitiveValue::CSS_NUMBER) { + result = clampTo<int>(value.value); + return !mediaValues.strictMode() || !result; } + if (CSSPrimitiveValue::isLength(value.unit)) + return mediaValues.computeLength(value.value, value.unit, result); return false; } -static bool deviceHeightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +static bool deviceHeightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - if (value) { + if (value.isValid()) { int length; - if (!computeLength(value, !frame->document()->inQuirksMode(), style, length)) - return false; - int height = static_cast<int>(screenRect(frame->view()).height()); - if (frame->settings()->reportScreenSizeInPhysicalPixelsQuirk()) - height = lroundf(height * frame->page()->deviceScaleFactor()); - return compareValue(height, length, op); + return computeLength(value, mediaValues, length) && compareValue(static_cast<int>(mediaValues.deviceHeight()), length, op); } // ({,min-,max-}device-height) // assume if we have a device, assume non-zero return true; } -static bool deviceWidthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +static bool deviceWidthMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - if (value) { + if (value.isValid()) { int length; - if (!computeLength(value, !frame->document()->inQuirksMode(), style, length)) - return false; - int width = static_cast<int>(screenRect(frame->view()).width()); - if (frame->settings()->reportScreenSizeInPhysicalPixelsQuirk()) - width = lroundf(width * frame->page()->deviceScaleFactor()); - return compareValue(width, length, op); + return computeLength(value, mediaValues, length) && compareValue(static_cast<int>(mediaValues.deviceWidth()), length, op); } // ({,min-,max-}device-width) // assume if we have a device, assume non-zero return true; } -static bool heightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +static bool heightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - FrameView* view = frame->view(); - - int height = viewportSize(view).height(); - if (value) { - if (RenderView* renderView = frame->document()->renderView()) - height = adjustForAbsoluteZoom(height, renderView); + int height = mediaValues.viewportHeight(); + if (value.isValid()) { int length; - return computeLength(value, !frame->document()->inQuirksMode(), style, length) && compareValue(height, length, op); + return computeLength(value, mediaValues, length) && compareValue(height, length, op); } return height; } -static bool widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix op) +static bool widthMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - FrameView* view = frame->view(); - - int width = viewportSize(view).width(); - if (value) { - if (RenderView* renderView = frame->document()->renderView()) - width = adjustForAbsoluteZoom(width, renderView); + int width = mediaValues.viewportWidth(); + if (value.isValid()) { int length; - return computeLength(value, !frame->document()->inQuirksMode(), style, length) && compareValue(width, length, op); + return computeLength(value, mediaValues, length) && compareValue(width, length, op); } return width; @@ -421,255 +389,203 @@ static bool widthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* fr // Rest of the functions are trampolines which set the prefix according to the media feature expression used. -static bool minColorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minColorMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return colorMediaFeatureEval(value, style, frame, MinPrefix); + return colorMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxColorMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxColorMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return colorMediaFeatureEval(value, style, frame, MaxPrefix); + return colorMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minColorIndexMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minColorIndexMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return colorIndexMediaFeatureEval(value, style, frame, MinPrefix); + return colorIndexMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxColorIndexMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxColorIndexMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return colorIndexMediaFeatureEval(value, style, frame, MaxPrefix); + return colorIndexMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minMonochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minMonochromeMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return monochromeMediaFeatureEval(value, style, frame, MinPrefix); + return monochromeMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxMonochromeMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxMonochromeMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return monochromeMediaFeatureEval(value, style, frame, MaxPrefix); + return monochromeMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minAspectRatioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minAspectRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return aspectRatioMediaFeatureEval(value, style, frame, MinPrefix); + return aspectRatioMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxAspectRatioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxAspectRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return aspectRatioMediaFeatureEval(value, style, frame, MaxPrefix); + return aspectRatioMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minDeviceAspectRatioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minDeviceAspectRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return deviceAspectRatioMediaFeatureEval(value, style, frame, MinPrefix); + return deviceAspectRatioMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxDeviceAspectRatioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxDeviceAspectRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return deviceAspectRatioMediaFeatureEval(value, style, frame, MaxPrefix); + return deviceAspectRatioMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minDevicePixelRatioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minDevicePixelRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return devicePixelRatioMediaFeatureEval(value, style, frame, MinPrefix); -} + UseCounter::count(mediaValues.document(), UseCounter::PrefixedMinDevicePixelRatioMediaFeature); -static bool maxDevicePixelRatioMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) -{ - return devicePixelRatioMediaFeatureEval(value, style, frame, MaxPrefix); + return devicePixelRatioMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool minHeightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxDevicePixelRatioMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return heightMediaFeatureEval(value, style, frame, MinPrefix); -} + UseCounter::count(mediaValues.document(), UseCounter::PrefixedMaxDevicePixelRatioMediaFeature); -static bool maxHeightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) -{ - return heightMediaFeatureEval(value, style, frame, MaxPrefix); + return devicePixelRatioMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minWidthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minHeightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return widthMediaFeatureEval(value, style, frame, MinPrefix); + return heightMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxWidthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxHeightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return widthMediaFeatureEval(value, style, frame, MaxPrefix); + return heightMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minDeviceHeightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minWidthMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return deviceHeightMediaFeatureEval(value, style, frame, MinPrefix); + return widthMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxDeviceHeightMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxWidthMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return deviceHeightMediaFeatureEval(value, style, frame, MaxPrefix); + return widthMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minDeviceWidthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minDeviceHeightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return deviceWidthMediaFeatureEval(value, style, frame, MinPrefix); + return deviceHeightMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxDeviceWidthMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxDeviceHeightMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return deviceWidthMediaFeatureEval(value, style, frame, MaxPrefix); + return deviceHeightMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool minResolutionMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool minDeviceWidthMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return resolutionMediaFeatureEval(value, style, frame, MinPrefix); + return deviceWidthMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool maxResolutionMediaFeatureEval(CSSValue* value, RenderStyle* style, Frame* frame, MediaFeaturePrefix) +static bool maxDeviceWidthMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - return resolutionMediaFeatureEval(value, style, frame, MaxPrefix); + return deviceWidthMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool animationMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op) +static bool minResolutionMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - if (value) { - float number; - return numberValue(value, number) && compareValue(1, static_cast<int>(number), op); - } - return true; + return resolutionMediaFeatureEval(value, MinPrefix, mediaValues); } -static bool deprecatedTransitionMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) +static bool maxResolutionMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - UseCounter::countDeprecation(frame->document(), UseCounter::PrefixedTransitionMediaFeature); - - if (value) { - float number; - return numberValue(value, number) && compareValue(1, static_cast<int>(number), op); - } - return true; + return resolutionMediaFeatureEval(value, MaxPrefix, mediaValues); } -static bool transform2dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame*, MediaFeaturePrefix op) +static bool transform3dMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix op, const MediaValues& mediaValues) { - if (value) { - float number; - return numberValue(value, number) && compareValue(1, static_cast<int>(number), op); - } - return true; -} + UseCounter::count(mediaValues.document(), UseCounter::PrefixedTransform3dMediaFeature); -static bool transform3dMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op) -{ bool returnValueIfNoParameter; int have3dRendering; - bool threeDEnabled = false; - if (RenderView* view = frame->contentRenderer()) - threeDEnabled = view->compositor()->canRender3DTransforms(); + bool threeDEnabled = mediaValues.threeDEnabled(); returnValueIfNoParameter = threeDEnabled; have3dRendering = threeDEnabled ? 1 : 0; - if (value) { + if (value.isValid()) { float number; return numberValue(value, number) && compareValue(have3dRendering, static_cast<int>(number), op); } return returnValueIfNoParameter; } -static bool viewModeMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix) -{ - if (!value) - return true; - - return toCSSPrimitiveValue(value)->getValueID() == CSSValueWindowed; -} - -enum PointerDeviceType { TouchPointer, MousePointer, NoPointer, UnknownPointer }; - -static PointerDeviceType leastCapablePrimaryPointerDeviceType(Frame* frame) -{ - if (frame->settings()->deviceSupportsTouch()) - return TouchPointer; - - // FIXME: We should also try to determine if we know we have a mouse. - // When we do this, we'll also need to differentiate between known not to - // have mouse or touch screen (NoPointer) and unknown (UnknownPointer). - // We could also take into account other preferences like accessibility - // settings to decide which of the available pointers should be considered - // "primary". - - return UnknownPointer; -} - -static bool hoverMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix) +static bool hoverMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - PointerDeviceType pointer = leastCapablePrimaryPointerDeviceType(frame); + MediaValues::PointerDeviceType pointer = mediaValues.pointer(); // If we're on a port that hasn't explicitly opted into providing pointer device information // (or otherwise can't be confident in the pointer hardware available), then behave exactly // as if this feature feature isn't supported. - if (pointer == UnknownPointer) + if (pointer == MediaValues::UnknownPointer) return false; float number = 1; - if (value) { + if (value.isValid()) { if (!numberValue(value, number)) return false; } - return (pointer == NoPointer && !number) - || (pointer == TouchPointer && !number) - || (pointer == MousePointer && number == 1); + return (pointer == MediaValues::NoPointer && !number) + || (pointer == MediaValues::TouchPointer && !number) + || (pointer == MediaValues::MousePointer && number == 1); } -static bool pointerMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix) +static bool pointerMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - PointerDeviceType pointer = leastCapablePrimaryPointerDeviceType(frame); + MediaValues::PointerDeviceType pointer = mediaValues.pointer(); // If we're on a port that hasn't explicitly opted into providing pointer device information // (or otherwise can't be confident in the pointer hardware available), then behave exactly // as if this feature feature isn't supported. - if (pointer == UnknownPointer) + if (pointer == MediaValues::UnknownPointer) return false; - if (!value) - return pointer != NoPointer; + if (!value.isValid()) + return pointer != MediaValues::NoPointer; - if (!value->isPrimitiveValue()) + if (!value.isID) return false; - const CSSValueID id = toCSSPrimitiveValue(value)->getValueID(); - return (pointer == NoPointer && id == CSSValueNone) - || (pointer == TouchPointer && id == CSSValueCoarse) - || (pointer == MousePointer && id == CSSValueFine); + return (pointer == MediaValues::NoPointer && value.id == CSSValueNone) + || (pointer == MediaValues::TouchPointer && value.id == CSSValueCoarse) + || (pointer == MediaValues::MousePointer && value.id == CSSValueFine); } -static bool scanMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix) +static bool scanMediaFeatureEval(const MediaQueryExpValue& value, MediaFeaturePrefix, const MediaValues& mediaValues) { - // Scan only applies to 'tv' media. - if (!equalIgnoringCase(frame->view()->mediaType(), "tv")) + if (!mediaValues.scanMediaType()) return false; - if (!value) + if (!value.isValid()) return true; - if (!value->isPrimitiveValue()) + if (!value.isID) return false; // If a platform interface supplies progressive/interlace info for TVs in the // future, it needs to be handled here. For now, assume a modern TV with // progressive display. - return toCSSPrimitiveValue(value)->getValueID() == CSSValueProgressive; + return (value.id == CSSValueProgressive); } static void createFunctionMap() { // Create the table. gFunctionMap = new FunctionMap; -#define ADD_TO_FUNCTIONMAP(name, str) \ +#define ADD_TO_FUNCTIONMAP(name) \ gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval); CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP); #undef ADD_TO_FUNCTIONMAP @@ -677,8 +593,8 @@ static void createFunctionMap() bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const { - if (!m_frame || !m_style) - return m_expResult; + if (!m_mediaValues || !m_mediaValues->hasValues()) + return m_expectedResult; if (!gFunctionMap) createFunctionMap(); @@ -687,7 +603,7 @@ bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const // trampoline functions override the prefix if prefix is used. EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl()); if (func) - return func(expr->value(), m_style.get(), m_frame, NoPrefix); + return func(expr->expValue(), NoPrefix, *m_mediaValues); return false; } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h b/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h index 60bd9cd78f2..64f1894e507 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluator.h @@ -28,64 +28,67 @@ #ifndef MediaQueryEvaluator_h #define MediaQueryEvaluator_h +#include "platform/heap/Handle.h" #include "wtf/text/WTFString.h" namespace WebCore { -class Frame; +class LocalFrame; class MediaQueryExp; class MediaQueryResult; class MediaQuerySet; class RenderStyle; +class MediaValues; -typedef Vector<RefPtr<MediaQueryResult> > MediaQueryResultList; +typedef WillBeHeapVector<RefPtrWillBeMember<MediaQueryResult> > MediaQueryResultList; + +// Class that evaluates css media queries as defined in +// CSS3 Module "Media Queries" (http://www.w3.org/TR/css3-mediaqueries/) +// Special constructors are needed, if simple media queries are to be +// evaluated without knowledge of the medium features. This can happen +// for example when parsing UA stylesheets, if evaluation is done +// right after parsing. +// +// the boolean parameter is used to approximate results of evaluation, if +// the device characteristics are not known. This can be used to prune the loading +// of stylesheets to only those which are probable to match. -/** - * Class that evaluates css media queries as defined in - * CSS3 Module "Media Queries" (http://www.w3.org/TR/css3-mediaqueries/) - * Special constructors are needed, if simple media queries are to be - * evaluated without knowledge of the medium features. This can happen - * for example when parsing UA stylesheets, if evaluation is done - * right after parsing. - * - * the boolean parameter is used to approximate results of evaluation, if - * the device characteristics are not known. This can be used to prune the loading - * of stylesheets to only those which are probable to match. - */ class MediaQueryEvaluator { WTF_MAKE_NONCOPYABLE(MediaQueryEvaluator); WTF_MAKE_FAST_ALLOCATED; public: - /** Creates evaluator which evaluates only simple media queries - * Evaluator returns true for "all", and returns value of \mediaFeatureResult - * for any media features - */ + // Creates evaluator which evaluates only simple media queries + // Evaluator returns true for "all", and returns value of \mediaFeatureResult + // for any media features + explicit MediaQueryEvaluator(bool mediaFeatureResult = false); - /** Creates evaluator which evaluates only simple media queries - * Evaluator returns true for acceptedMediaType and returns value of \mediafeatureResult - * for any media features - */ - MediaQueryEvaluator(const AtomicString& acceptedMediaType, bool mediaFeatureResult = false); + // Creates evaluator which evaluates only simple media queries + // Evaluator returns true for acceptedMediaType and returns value of \mediafeatureResult + // for any media features + + MediaQueryEvaluator(const String& acceptedMediaType, bool mediaFeatureResult = false); MediaQueryEvaluator(const char* acceptedMediaType, bool mediaFeatureResult = false); - /** Creates evaluator which evaluates full media queries */ - MediaQueryEvaluator(const AtomicString& acceptedMediaType, Frame*, RenderStyle*); + // Creates evaluator which evaluates full media queries + MediaQueryEvaluator(const String& acceptedMediaType, LocalFrame*); + + // Creates evaluator which evaluates in a thread-safe manner a subset of media values + MediaQueryEvaluator(const String& acceptedMediaType, const MediaValues&); ~MediaQueryEvaluator(); - bool mediaTypeMatch(const AtomicString& mediaTypeToMatch) const; + bool mediaTypeMatch(const String& mediaTypeToMatch) const; bool mediaTypeMatchSpecific(const char* mediaTypeToMatch) const; - /** Evaluates a list of media queries */ + // Evaluates a list of media queries bool eval(const MediaQuerySet*, MediaQueryResultList* = 0) const; - /** Evaluates media query subexpression, ie "and (media-feature: value)" part */ + // Evaluates media query subexpression, ie "and (media-feature: value)" part bool eval(const MediaQueryExp*) const; private: - AtomicString m_mediaType; - Frame* m_frame; // Not owned. - RefPtr<RenderStyle> m_style; - bool m_expResult; + String m_mediaType; + bool m_expectedResult; + RefPtr<MediaValues> m_mediaValues; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp new file mode 100644 index 00000000000..668077ef683 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryEvaluatorTest.cpp @@ -0,0 +1,102 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/MediaQueryEvaluator.h" + +#include "core/css/MediaList.h" +#include "core/css/MediaValuesCached.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/text/StringBuilder.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +typedef struct { + const char* input; + const bool output; +} TestCase; + +TEST(MediaQueryEvaluatorTest, Basic) +{ + // The first string represents the input string. + // The second string represents the output string, if present. + // Otherwise, the output string is identical to the first string. + TestCase screenTestCases[] = { + {"", 1}, + {" ", 1}, + {"screen", 1}, + {"screen and (color)", 1}, + {"all and (min-width: 500px)", 1}, + {"not screen and (color)", 0}, + {"(min-width: 500px)", 1}, + {"(min-width: 501px)", 0}, + {"(max-width: 500px)", 1}, + {"(max-width: 499px)", 0}, + {"(width: 500px)", 1}, + {"(width: 501px)", 0}, + {"(min-height: 500px)", 1}, + {"(min-height: 501px)", 0}, + {"(max-height: 500px)", 1}, + {"(max-height: 499px)", 0}, + {"(height: 500px)", 1}, + {"(height: 501px)", 0}, + {"screen and (min-width: 400px) and (max-width: 700px)", 1}, + {"screen and (device-aspect-ratio: 16/9)", 0}, + {"screen and (device-aspect-ratio: 1/1)", 1}, + {"all and (min-color: 2)", 1}, + {"all and (min-color: 32)", 0}, + {"all and (min-color-index: 0)", 1}, + {"all and (min-color-index: 1)", 0}, + {"all and (monochrome)", 0}, + {"all and (min-monochrome: 0)", 1}, + {"all and (grid: 0)", 1}, + {"(resolution: 2dppx)", 1}, + {"(resolution: 1dppx)", 0}, + {"(orientation: portrait)", 1}, + {"(orientation: landscape)", 0}, + {"tv and (scan: progressive)", 0}, + {"(pointer: coarse)", 0}, + {"(pointer: fine)", 1}, + {"(hover: 1)", 1}, + {"(hover: 0)", 0}, + {0, 0} // Do not remove the terminator line. + }; + TestCase printTestCases[] = { + {"print and (min-resolution: 1dppx)", 1}, + {"print and (min-resolution: 118dpcm)", 0}, + {0, 0} // Do not remove the terminator line. + }; + + MediaValuesCached::MediaValuesCachedData data; + data.viewportWidth = 500; + data.viewportHeight = 500; + data.deviceWidth = 500; + data.deviceHeight = 500; + data.devicePixelRatio = 2.0; + data.colorBitsPerComponent = 24; + data.monochromeBitsPerComponent = 0; + data.pointer = MediaValues::MousePointer; + data.defaultFontSize = 16; + data.threeDEnabled = true; + data.scanMediaType = false; + data.screenMediaType = true; + data.printMediaType = false; + data.strictMode = true; + RefPtr<MediaValues> mediaValues = MediaValuesCached::create(data); + + for (unsigned i = 0; screenTestCases[i].input; ++i) { + RefPtrWillBeRawPtr<MediaQuerySet> querySet = MediaQuerySet::create(screenTestCases[i].input); + MediaQueryEvaluator mediaQueryEvaluator("screen", *mediaValues); + ASSERT_EQ(screenTestCases[i].output, mediaQueryEvaluator.eval(querySet.get())); + } + for (unsigned i = 0; printTestCases[i].input; ++i) { + RefPtrWillBeRawPtr<MediaQuerySet> querySet = MediaQuerySet::create(printTestCases[i].input); + MediaQueryEvaluator mediaQueryEvaluator("print", *mediaValues); + ASSERT_EQ(printTestCases[i].output, mediaQueryEvaluator.eval(querySet.get())); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.cpp index 05c0e5cffd7..14348dfeaad 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.cpp @@ -30,214 +30,211 @@ #include "config.h" #include "core/css/MediaQueryExp.h" -#include "CSSValueKeywords.h" #include "core/css/CSSAspectRatioValue.h" -#include "core/css/CSSParser.h" +#include "core/css/CSSParserValues.h" #include "core/css/CSSPrimitiveValue.h" +#include "core/html/parser/HTMLParserIdioms.h" +#include "platform/Decimal.h" +#include "wtf/text/StringBuffer.h" #include "wtf/text/StringBuilder.h" namespace WebCore { -static inline bool featureWithCSSValueID(const AtomicString& mediaFeature, const CSSParserValue* value) +using namespace MediaFeatureNames; + +static inline bool featureWithCSSValueID(const String& mediaFeature, const CSSParserValue* value) { if (!value->id) return false; - return mediaFeature == MediaFeatureNames::orientationMediaFeature - || mediaFeature == MediaFeatureNames::viewModeMediaFeature - || mediaFeature == MediaFeatureNames::pointerMediaFeature - || mediaFeature == MediaFeatureNames::scanMediaFeature; + return mediaFeature == orientationMediaFeature + || mediaFeature == pointerMediaFeature + || mediaFeature == scanMediaFeature; } -static inline bool featureWithValidIdent(const AtomicString& mediaFeature, CSSValueID ident) +static inline bool featureWithValidIdent(const String& mediaFeature, CSSValueID ident) { - if (mediaFeature == MediaFeatureNames::orientationMediaFeature) + if (mediaFeature == orientationMediaFeature) return ident == CSSValuePortrait || ident == CSSValueLandscape; - if (mediaFeature == MediaFeatureNames::viewModeMediaFeature) { - switch (ident) { - case CSSValueWindowed: - case CSSValueFloating: - case CSSValueFullscreen: - case CSSValueMaximized: - case CSSValueMinimized: - return true; - default: - return false; - } - } - - if (mediaFeature == MediaFeatureNames::pointerMediaFeature) + if (mediaFeature == pointerMediaFeature) return ident == CSSValueNone || ident == CSSValueCoarse || ident == CSSValueFine; - if (mediaFeature == MediaFeatureNames::scanMediaFeature) + if (mediaFeature == scanMediaFeature) return ident == CSSValueInterlace || ident == CSSValueProgressive; ASSERT_NOT_REACHED(); return false; } -static inline bool featureWithValidPositiveLenghtOrNumber(const AtomicString& mediaFeature, const CSSParserValue* value) +static inline bool featureWithValidPositiveLength(const String& mediaFeature, const CSSParserValue* value) { - if (!(((value->unit >= CSSPrimitiveValue::CSS_EMS && value->unit <= CSSPrimitiveValue::CSS_PC) || value->unit == CSSPrimitiveValue::CSS_REMS) || value->unit == CSSPrimitiveValue::CSS_NUMBER) || value->fValue < 0) + if (!(((value->unit >= CSSPrimitiveValue::CSS_EMS && value->unit <= CSSPrimitiveValue::CSS_PC) || value->unit == CSSPrimitiveValue::CSS_REMS) || (value->unit == CSSPrimitiveValue::CSS_NUMBER && !(value->fValue))) || value->fValue < 0) return false; - return mediaFeature == MediaFeatureNames::heightMediaFeature - || mediaFeature == MediaFeatureNames::maxHeightMediaFeature - || mediaFeature == MediaFeatureNames::minHeightMediaFeature - || mediaFeature == MediaFeatureNames::widthMediaFeature - || mediaFeature == MediaFeatureNames::maxWidthMediaFeature - || mediaFeature == MediaFeatureNames::minWidthMediaFeature - || mediaFeature == MediaFeatureNames::deviceHeightMediaFeature - || mediaFeature == MediaFeatureNames::maxDeviceHeightMediaFeature - || mediaFeature == MediaFeatureNames::minDeviceHeightMediaFeature - || mediaFeature == MediaFeatureNames::deviceWidthMediaFeature - || mediaFeature == MediaFeatureNames::maxDeviceWidthMediaFeature - || mediaFeature == MediaFeatureNames::minDeviceWidthMediaFeature; + + return mediaFeature == heightMediaFeature + || mediaFeature == maxHeightMediaFeature + || mediaFeature == minHeightMediaFeature + || mediaFeature == widthMediaFeature + || mediaFeature == maxWidthMediaFeature + || mediaFeature == minWidthMediaFeature + || mediaFeature == deviceHeightMediaFeature + || mediaFeature == maxDeviceHeightMediaFeature + || mediaFeature == minDeviceHeightMediaFeature + || mediaFeature == deviceWidthMediaFeature + || mediaFeature == minDeviceWidthMediaFeature + || mediaFeature == maxDeviceWidthMediaFeature; } -static inline bool featureWithValidDensity(const AtomicString& mediaFeature, const CSSParserValue* value) +static inline bool featureWithValidDensity(const String& mediaFeature, const CSSParserValue* value) { if ((value->unit != CSSPrimitiveValue::CSS_DPPX && value->unit != CSSPrimitiveValue::CSS_DPI && value->unit != CSSPrimitiveValue::CSS_DPCM) || value->fValue <= 0) return false; - return mediaFeature == MediaFeatureNames::resolutionMediaFeature - || mediaFeature == MediaFeatureNames::maxResolutionMediaFeature - || mediaFeature == MediaFeatureNames::minResolutionMediaFeature; + return mediaFeature == resolutionMediaFeature + || mediaFeature == minResolutionMediaFeature + || mediaFeature == maxResolutionMediaFeature; } -static inline bool featureWithPositiveInteger(const AtomicString& mediaFeature, const CSSParserValue* value) +static inline bool featureWithPositiveInteger(const String& mediaFeature, const CSSParserValue* value) { if (!value->isInt || value->fValue < 0) return false; - return mediaFeature == MediaFeatureNames::colorMediaFeature - || mediaFeature == MediaFeatureNames::maxColorMediaFeature - || mediaFeature == MediaFeatureNames::minColorMediaFeature - || mediaFeature == MediaFeatureNames::colorIndexMediaFeature - || mediaFeature == MediaFeatureNames::maxColorIndexMediaFeature - || mediaFeature == MediaFeatureNames::minColorIndexMediaFeature - || mediaFeature == MediaFeatureNames::monochromeMediaFeature - || mediaFeature == MediaFeatureNames::minMonochromeMediaFeature - || mediaFeature == MediaFeatureNames::maxMonochromeMediaFeature; + return mediaFeature == colorMediaFeature + || mediaFeature == maxColorMediaFeature + || mediaFeature == minColorMediaFeature + || mediaFeature == colorIndexMediaFeature + || mediaFeature == maxColorIndexMediaFeature + || mediaFeature == minColorIndexMediaFeature + || mediaFeature == monochromeMediaFeature + || mediaFeature == maxMonochromeMediaFeature + || mediaFeature == minMonochromeMediaFeature; } -static inline bool featureWithPositiveNumber(const AtomicString& mediaFeature, const CSSParserValue* value) +static inline bool featureWithPositiveNumber(const String& mediaFeature, const CSSParserValue* value) { if (value->unit != CSSPrimitiveValue::CSS_NUMBER || value->fValue < 0) return false; - return mediaFeature == MediaFeatureNames::transform2dMediaFeature - || mediaFeature == MediaFeatureNames::transform3dMediaFeature - || mediaFeature == MediaFeatureNames::deprecatedTransitionMediaFeature - || mediaFeature == MediaFeatureNames::animationMediaFeature - || mediaFeature == MediaFeatureNames::devicePixelRatioMediaFeature - || mediaFeature == MediaFeatureNames::maxDevicePixelRatioMediaFeature - || mediaFeature == MediaFeatureNames::minDevicePixelRatioMediaFeature; + return mediaFeature == transform3dMediaFeature + || mediaFeature == devicePixelRatioMediaFeature + || mediaFeature == maxDevicePixelRatioMediaFeature + || mediaFeature == minDevicePixelRatioMediaFeature; } -static inline bool featureWithZeroOrOne(const AtomicString& mediaFeature, const CSSParserValue* value) +static inline bool featureWithZeroOrOne(const String& mediaFeature, const CSSParserValue* value) { if (!value->isInt || !(value->fValue == 1 || !value->fValue)) return false; - return mediaFeature == MediaFeatureNames::gridMediaFeature - || mediaFeature == MediaFeatureNames::hoverMediaFeature; + return mediaFeature == gridMediaFeature + || mediaFeature == hoverMediaFeature; } -static inline bool featureWithAspectRatio(const AtomicString& mediaFeature) +static inline bool featureWithAspectRatio(const String& mediaFeature) { - return mediaFeature == MediaFeatureNames::aspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::deviceAspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::minAspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::maxAspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::minDeviceAspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::maxDeviceAspectRatioMediaFeature; + return mediaFeature == aspectRatioMediaFeature + || mediaFeature == deviceAspectRatioMediaFeature + || mediaFeature == minAspectRatioMediaFeature + || mediaFeature == maxAspectRatioMediaFeature + || mediaFeature == minDeviceAspectRatioMediaFeature + || mediaFeature == maxDeviceAspectRatioMediaFeature; } -static inline bool featureWithoutValue(const AtomicString& mediaFeature) +static inline bool featureWithoutValue(const String& mediaFeature) { // Media features that are prefixed by min/max cannot be used without a value. - return mediaFeature == MediaFeatureNames::monochromeMediaFeature - || mediaFeature == MediaFeatureNames::colorMediaFeature - || mediaFeature == MediaFeatureNames::colorIndexMediaFeature - || mediaFeature == MediaFeatureNames::gridMediaFeature - || mediaFeature == MediaFeatureNames::heightMediaFeature - || mediaFeature == MediaFeatureNames::widthMediaFeature - || mediaFeature == MediaFeatureNames::deviceHeightMediaFeature - || mediaFeature == MediaFeatureNames::deviceWidthMediaFeature - || mediaFeature == MediaFeatureNames::orientationMediaFeature - || mediaFeature == MediaFeatureNames::aspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::deviceAspectRatioMediaFeature - || mediaFeature == MediaFeatureNames::hoverMediaFeature - || mediaFeature == MediaFeatureNames::transform2dMediaFeature - || mediaFeature == MediaFeatureNames::transform3dMediaFeature - || mediaFeature == MediaFeatureNames::deprecatedTransitionMediaFeature - || mediaFeature == MediaFeatureNames::animationMediaFeature - || mediaFeature == MediaFeatureNames::viewModeMediaFeature - || mediaFeature == MediaFeatureNames::pointerMediaFeature - || mediaFeature == MediaFeatureNames::devicePixelRatioMediaFeature - || mediaFeature == MediaFeatureNames::resolutionMediaFeature - || mediaFeature == MediaFeatureNames::scanMediaFeature; + return mediaFeature == monochromeMediaFeature + || mediaFeature == colorMediaFeature + || mediaFeature == colorIndexMediaFeature + || mediaFeature == gridMediaFeature + || mediaFeature == heightMediaFeature + || mediaFeature == widthMediaFeature + || mediaFeature == deviceHeightMediaFeature + || mediaFeature == deviceWidthMediaFeature + || mediaFeature == orientationMediaFeature + || mediaFeature == aspectRatioMediaFeature + || mediaFeature == deviceAspectRatioMediaFeature + || mediaFeature == hoverMediaFeature + || mediaFeature == transform3dMediaFeature + || mediaFeature == pointerMediaFeature + || mediaFeature == devicePixelRatioMediaFeature + || mediaFeature == resolutionMediaFeature + || mediaFeature == scanMediaFeature; } bool MediaQueryExp::isViewportDependent() const { - return m_mediaFeature == MediaFeatureNames::widthMediaFeature - || m_mediaFeature == MediaFeatureNames::heightMediaFeature - || m_mediaFeature == MediaFeatureNames::minWidthMediaFeature - || m_mediaFeature == MediaFeatureNames::minHeightMediaFeature - || m_mediaFeature == MediaFeatureNames::maxWidthMediaFeature - || m_mediaFeature == MediaFeatureNames::maxHeightMediaFeature - || m_mediaFeature == MediaFeatureNames::orientationMediaFeature - || m_mediaFeature == MediaFeatureNames::aspectRatioMediaFeature - || m_mediaFeature == MediaFeatureNames::minAspectRatioMediaFeature - || m_mediaFeature == MediaFeatureNames::devicePixelRatioMediaFeature - || m_mediaFeature == MediaFeatureNames::resolutionMediaFeature - || m_mediaFeature == MediaFeatureNames::maxAspectRatioMediaFeature; + return m_mediaFeature == widthMediaFeature + || m_mediaFeature == heightMediaFeature + || m_mediaFeature == minWidthMediaFeature + || m_mediaFeature == minHeightMediaFeature + || m_mediaFeature == maxWidthMediaFeature + || m_mediaFeature == maxHeightMediaFeature + || m_mediaFeature == orientationMediaFeature + || m_mediaFeature == aspectRatioMediaFeature + || m_mediaFeature == minAspectRatioMediaFeature + || m_mediaFeature == devicePixelRatioMediaFeature + || m_mediaFeature == resolutionMediaFeature + || m_mediaFeature == maxAspectRatioMediaFeature; } -MediaQueryExp::MediaQueryExp(const AtomicString& mediaFeature, PassRefPtr<CSSValue> value) +MediaQueryExp::MediaQueryExp(const MediaQueryExp& other) + : m_mediaFeature(other.mediaFeature()) + , m_expValue(other.expValue()) +{ +} + +MediaQueryExp::MediaQueryExp(const String& mediaFeature, const MediaQueryExpValue& expValue) : m_mediaFeature(mediaFeature) - , m_value(value) + , m_expValue(expValue) { } -PassOwnPtr<MediaQueryExp> MediaQueryExp::create(const AtomicString& mediaFeature, CSSParserValueList* valueList) +PassOwnPtrWillBeRawPtr<MediaQueryExp> MediaQueryExp::createIfValid(const String& mediaFeature, CSSParserValueList* valueList) { - RefPtr<CSSValue> cssValue; + ASSERT(!mediaFeature.isNull()); + + MediaQueryExpValue expValue; bool isValid = false; + String lowerMediaFeature = attemptStaticStringCreation(mediaFeature.lower()); // Create value for media query expression that must have 1 or more values. - if (valueList) { + if (valueList && valueList->size() > 0) { if (valueList->size() == 1) { CSSParserValue* value = valueList->current(); + ASSERT(value); - if (featureWithCSSValueID(mediaFeature, value)) { + if (featureWithCSSValueID(lowerMediaFeature, value) && featureWithValidIdent(lowerMediaFeature, value->id)) { // Media features that use CSSValueIDs. - cssValue = CSSPrimitiveValue::createIdentifier(value->id); - if (!featureWithValidIdent(mediaFeature, toCSSPrimitiveValue(cssValue.get())->getValueID())) - cssValue.clear(); - } else if (featureWithValidDensity(mediaFeature, value)) { - // Media features that must have non-negative <density>, ie. dppx, dpi or dpcm. - cssValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); - } else if (featureWithValidPositiveLenghtOrNumber(mediaFeature, value)) { - // Media features that must have non-negative <lenght> or number value. - cssValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit); - } else if (featureWithPositiveInteger(mediaFeature, value)) { - // Media features that must have non-negative integer value. - cssValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER); - } else if (featureWithPositiveNumber(mediaFeature, value)) { - // Media features that must have non-negative number value. - cssValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER); - } else if (featureWithZeroOrOne(mediaFeature, value)) { - // Media features that must have (0|1) value. - cssValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_NUMBER); + expValue.id = value->id; + expValue.unit = CSSPrimitiveValue::CSS_VALUE_ID; + expValue.isID = true; + } else if (featureWithValidDensity(lowerMediaFeature, value) + || featureWithValidPositiveLength(lowerMediaFeature, value)) { + // Media features that must have non-negative <density>, ie. dppx, dpi or dpcm, + // or Media features that must have non-negative <length> or number value. + expValue.value = value->fValue; + expValue.unit = (CSSPrimitiveValue::UnitType)value->unit; + expValue.isValue = true; + expValue.isInteger = value->isInt; + } else if (featureWithPositiveInteger(lowerMediaFeature, value) + || featureWithPositiveNumber(lowerMediaFeature, value) + || featureWithZeroOrOne(lowerMediaFeature, value)) { + // Media features that must have non-negative integer value, + // or media features that must have non-negative number value, + // or media features that must have (0|1) value. + expValue.value = value->fValue; + expValue.unit = CSSPrimitiveValue::CSS_NUMBER; + expValue.isValue = true; + expValue.isInteger = value->isInt; } - isValid = cssValue; + isValid = (expValue.isID || expValue.isValue); - } else if (valueList->size() == 3 && featureWithAspectRatio(mediaFeature)) { + } else if (valueList->size() == 3 && featureWithAspectRatio(lowerMediaFeature)) { // Create list of values. // Currently accepts only <integer>/<integer>. // Applicable to device-aspect-ratio and aspec-ratio. @@ -260,35 +257,67 @@ PassOwnPtr<MediaQueryExp> MediaQueryExp::create(const AtomicString& mediaFeature } } - if (isValid) - cssValue = CSSAspectRatioValue::create(numeratorValue, denominatorValue); + if (isValid) { + expValue.numerator = (unsigned)numeratorValue; + expValue.denominator = (unsigned)denominatorValue; + expValue.isRatio = true; + } } - } else if (featureWithoutValue(mediaFeature)) { + } else if (featureWithoutValue(lowerMediaFeature)) { isValid = true; } if (!isValid) return nullptr; - return adoptPtr(new MediaQueryExp(mediaFeature, cssValue)); + return adoptPtrWillBeNoop(new MediaQueryExp(lowerMediaFeature, expValue)); } MediaQueryExp::~MediaQueryExp() { } +bool MediaQueryExp::operator==(const MediaQueryExp& other) const +{ + return (other.m_mediaFeature == m_mediaFeature) + && ((!other.m_expValue.isValid() && !m_expValue.isValid()) + || (other.m_expValue.isValid() && m_expValue.isValid() && other.m_expValue.equals(m_expValue))); +} + String MediaQueryExp::serialize() const { StringBuilder result; result.append("("); result.append(m_mediaFeature.lower()); - if (m_value) { + if (m_expValue.isValid()) { result.append(": "); - result.append(m_value->cssText()); + result.append(m_expValue.cssText()); } result.append(")"); return result.toString(); } +static inline String printNumber(double number) +{ + return Decimal::fromDouble(number).toString(); +} + +String MediaQueryExpValue::cssText() const +{ + StringBuilder output; + if (isValue) { + output.append(printNumber(value)); + output.append(CSSPrimitiveValue::unitTypeToString(unit)); + } else if (isRatio) { + output.append(printNumber(numerator)); + output.append("/"); + output.append(printNumber(denominator)); + } else if (isID) { + output.append(getValueName(id)); + } + + return output.toString(); +} + } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.h b/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.h index 0586b0a6bb3..1ca45c2fa70 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryExp.h @@ -29,43 +29,82 @@ #ifndef MediaQueryExp_h #define MediaQueryExp_h +#include "core/CSSValueKeywords.h" +#include "core/MediaFeatureNames.h" +#include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSValue.h" -#include "core/css/MediaFeatureNames.h" #include "wtf/PassOwnPtr.h" #include "wtf/RefPtr.h" -#include "wtf/text/AtomicString.h" namespace WebCore { class CSSParserValueList; -class MediaQueryExp { - WTF_MAKE_FAST_ALLOCATED; -public: - static PassOwnPtr<MediaQueryExp> create(const AtomicString& mediaFeature, CSSParserValueList*); - ~MediaQueryExp(); +struct MediaQueryExpValue { + CSSValueID id; + double value; + CSSPrimitiveValue::UnitType unit; + unsigned numerator; + unsigned denominator; - AtomicString mediaFeature() const { return m_mediaFeature; } + bool isID; + bool isValue; + bool isRatio; + bool isInteger; - CSSValue* value() const { return m_value.get(); } + MediaQueryExpValue() + : id(CSSValueInvalid) + , value(0) + , unit(CSSPrimitiveValue::CSS_UNKNOWN) + , numerator(0) + , denominator(1) + , isID(false) + , isValue(false) + , isRatio(false) + , isInteger(false) + { + } - bool operator==(const MediaQueryExp& other) const + bool isValid() const { return (isID || isValue || isRatio); } + String cssText() const; + bool equals(const MediaQueryExpValue& expValue) const { - return (other.m_mediaFeature == m_mediaFeature) - && ((!other.m_value && !m_value) - || (other.m_value && m_value && other.m_value->equals(*m_value))); + if (isID) + return (id == expValue.id); + if (isValue) + return (value == expValue.value); + if (isRatio) + return (numerator == expValue.numerator && denominator == expValue.denominator); + return !expValue.isValid(); } +}; + +class MediaQueryExp : public NoBaseWillBeGarbageCollectedFinalized<MediaQueryExp> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; +public: + static PassOwnPtrWillBeRawPtr<MediaQueryExp> createIfValid(const String& mediaFeature, CSSParserValueList*); + ~MediaQueryExp(); + + const String& mediaFeature() const { return m_mediaFeature; } + + MediaQueryExpValue expValue() const { return m_expValue; } + + bool operator==(const MediaQueryExp& other) const; bool isViewportDependent() const; String serialize() const; - PassOwnPtr<MediaQueryExp> copy() const { return adoptPtr(new MediaQueryExp(*this)); } + PassOwnPtrWillBeRawPtr<MediaQueryExp> copy() const { return adoptPtrWillBeNoop(new MediaQueryExp(*this)); } + + MediaQueryExp(const MediaQueryExp& other); + + void trace(Visitor* visitor) { } private: - MediaQueryExp(const AtomicString& mediaFeature, PassRefPtr<CSSValue>); + MediaQueryExp(const String&, const MediaQueryExpValue&); - AtomicString m_mediaFeature; - RefPtr<CSSValue> m_value; + String m_mediaFeature; + MediaQueryExpValue m_expValue; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryList.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQueryList.cpp index b55f3fb482d..d76b5bbec15 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryList.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryList.cpp @@ -27,12 +27,12 @@ namespace WebCore { -PassRefPtr<MediaQueryList> MediaQueryList::create(PassRefPtr<MediaQueryMatcher> vector, PassRefPtr<MediaQuerySet> media, bool matches) +PassRefPtrWillBeRawPtr<MediaQueryList> MediaQueryList::create(PassRefPtrWillBeRawPtr<MediaQueryMatcher> vector, PassRefPtrWillBeRawPtr<MediaQuerySet> media, bool matches) { - return adoptRef(new MediaQueryList(vector, media, matches)); + return adoptRefWillBeNoop(new MediaQueryList(vector, media, matches)); } -MediaQueryList::MediaQueryList(PassRefPtr<MediaQueryMatcher> vector, PassRefPtr<MediaQuerySet> media, bool matches) +MediaQueryList::MediaQueryList(PassRefPtrWillBeRawPtr<MediaQueryMatcher> vector, PassRefPtrWillBeRawPtr<MediaQuerySet> media, bool matches) : m_matcher(vector) , m_media(media) , m_evaluationRound(m_matcher->evaluationRound()) @@ -41,16 +41,14 @@ MediaQueryList::MediaQueryList(PassRefPtr<MediaQueryMatcher> vector, PassRefPtr< { } -MediaQueryList::~MediaQueryList() -{ -} +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryList) String MediaQueryList::media() const { return m_media->mediaText(); } -void MediaQueryList::addListener(PassRefPtr<MediaQueryListListener> listener) +void MediaQueryList::addListener(PassRefPtrWillBeRawPtr<MediaQueryListListener> listener) { if (!listener) return; @@ -58,7 +56,7 @@ void MediaQueryList::addListener(PassRefPtr<MediaQueryListListener> listener) m_matcher->addListener(listener, this); } -void MediaQueryList::removeListener(PassRefPtr<MediaQueryListListener> listener) +void MediaQueryList::removeListener(PassRefPtrWillBeRawPtr<MediaQueryListListener> listener) { if (!listener) return; @@ -66,11 +64,11 @@ void MediaQueryList::removeListener(PassRefPtr<MediaQueryListListener> listener) m_matcher->removeListener(listener.get(), this); } -void MediaQueryList::evaluate(MediaQueryEvaluator* evaluator, bool& notificationNeeded) +bool MediaQueryList::evaluate(MediaQueryEvaluator* evaluator) { if (m_evaluationRound != m_matcher->evaluationRound() && evaluator) setMatches(evaluator->eval(m_media.get())); - notificationNeeded = m_changeRound == m_matcher->evaluationRound(); + return m_changeRound == m_matcher->evaluationRound(); } void MediaQueryList::setMatches(bool newValue) @@ -91,4 +89,10 @@ bool MediaQueryList::matches() return m_matches; } +void MediaQueryList::trace(Visitor* visitor) +{ + visitor->trace(m_matcher); + visitor->trace(m_media); +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryList.h b/chromium/third_party/WebKit/Source/core/css/MediaQueryList.h index a15bc6a304f..ba04100cc72 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryList.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryList.h @@ -20,6 +20,7 @@ #ifndef MediaQueryList_h #define MediaQueryList_h +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" @@ -36,25 +37,26 @@ class MediaQuerySet; // retrieve the current value of the given media query and to add/remove listeners that // will be called whenever the value of the query changes. -class MediaQueryList : public RefCounted<MediaQueryList> { +class MediaQueryList FINAL : public RefCountedWillBeGarbageCollected<MediaQueryList> { + DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryList); public: - static PassRefPtr<MediaQueryList> create(PassRefPtr<MediaQueryMatcher>, PassRefPtr<MediaQuerySet>, bool); - ~MediaQueryList(); - + static PassRefPtrWillBeRawPtr<MediaQueryList> create(PassRefPtrWillBeRawPtr<MediaQueryMatcher>, PassRefPtrWillBeRawPtr<MediaQuerySet>, bool); String media() const; bool matches(); - void addListener(PassRefPtr<MediaQueryListListener>); - void removeListener(PassRefPtr<MediaQueryListListener>); + void addListener(PassRefPtrWillBeRawPtr<MediaQueryListListener>); + void removeListener(PassRefPtrWillBeRawPtr<MediaQueryListListener>); + + bool evaluate(MediaQueryEvaluator*); - void evaluate(MediaQueryEvaluator*, bool& notificationNeeded); + void trace(Visitor*); private: - MediaQueryList(PassRefPtr<MediaQueryMatcher>, PassRefPtr<MediaQuerySet>, bool matches); + MediaQueryList(PassRefPtrWillBeRawPtr<MediaQueryMatcher>, PassRefPtrWillBeRawPtr<MediaQuerySet>, bool matches); void setMatches(bool); - RefPtr<MediaQueryMatcher> m_matcher; - RefPtr<MediaQuerySet> m_media; + RefPtrWillBeMember<MediaQueryMatcher> m_matcher; + RefPtrWillBeMember<MediaQuerySet> m_media; unsigned m_evaluationRound; // Indicates if the query has been evaluated after the last style selector change. unsigned m_changeRound; // Used to know if the query has changed in the last style selector change. bool m_matches; diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryList.idl b/chromium/third_party/WebKit/Source/core/css/MediaQueryList.idl index 7785d8dc2c6..c60c692ac79 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryList.idl +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryList.idl @@ -17,7 +17,8 @@ * Boston, MA 02110-1301, USA. */ [ - NoInterfaceObject + NoInterfaceObject, + WillBeGarbageCollected ] interface MediaQueryList { readonly attribute DOMString media; readonly attribute boolean matches; diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.cpp index 494883e7ed8..7cda1b4dc65 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.cpp @@ -20,23 +20,26 @@ #include "config.h" #include "core/css/MediaQueryListListener.h" -#include "V8MediaQueryList.h" -#include "bindings/v8/ScriptFunctionCall.h" +#include "bindings/core/v8/V8MediaQueryList.h" +#include "bindings/v8/V8Callback.h" +#include <v8.h> namespace WebCore { -void MediaQueryListListener::queryChanged(ScriptState* state, MediaQueryList* query) +MediaQueryListListener::MediaQueryListListener(ScriptState* scriptState, const ScriptValue& function) + : m_scriptState(scriptState) + , m_function(function) { - ScriptCallback callback(state, m_value); - v8::HandleScope handleScope(state->isolate()); - - v8::Handle<v8::Context> context = state->context(); - if (context.IsEmpty()) - return; // JS may not be enabled. + ASSERT(m_function.isFunction()); +} - v8::Context::Scope scope(context); - callback.appendArgument(ScriptValue(toV8(query, v8::Handle<v8::Object>(), context->GetIsolate()), context->GetIsolate())); - callback.call(); +void MediaQueryListListener::queryChanged(MediaQueryList* query) +{ + if (m_scriptState->contextIsEmpty()) + return; + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Value> args[] = { toV8(query, m_scriptState->context()->Global(), m_scriptState->isolate()) }; + invokeCallback(m_scriptState.get(), v8::Handle<v8::Function>::Cast(m_function.v8Value()), WTF_ARRAY_LENGTH(args), args); } } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.h b/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.h index fccf99dbef1..26a921f77db 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryListListener.h @@ -22,6 +22,7 @@ #include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" namespace WebCore { @@ -30,22 +31,25 @@ class MediaQueryList; // See http://dev.w3.org/csswg/cssom-view/#the-mediaquerylist-interface -class MediaQueryListListener : public RefCounted<MediaQueryListListener> { +class MediaQueryListListener : public RefCountedWillBeGarbageCollectedFinalized<MediaQueryListListener> { public: - static PassRefPtr<MediaQueryListListener> create(const ScriptValue& value) + static PassRefPtrWillBeRawPtr<MediaQueryListListener> create(ScriptState* scriptState, const ScriptValue& value) { if (!value.isFunction()) - return 0; - return adoptRef(new MediaQueryListListener(value)); + return nullptr; + return adoptRefWillBeNoop(new MediaQueryListListener(scriptState, value)); } - void queryChanged(ScriptState*, MediaQueryList*); + void queryChanged(MediaQueryList*); - bool operator==(const MediaQueryListListener& other) const { return m_value == other.m_value; } + bool operator==(const MediaQueryListListener& other) const { return m_function == other.m_function; } + + void trace(Visitor*) { } private: - MediaQueryListListener(const ScriptValue& value) : m_value(value) { } + MediaQueryListListener(ScriptState*, const ScriptValue&); - ScriptValue m_value; + RefPtr<ScriptState> m_scriptState; + ScriptValue m_function; }; } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp index 9051099e17c..1821634634a 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.cpp @@ -26,27 +26,27 @@ #include "core/css/MediaQueryListListener.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -MediaQueryMatcher::Listener::Listener(PassRefPtr<MediaQueryListListener> listener, PassRefPtr<MediaQueryList> query) +MediaQueryMatcher::Listener::Listener(PassRefPtrWillBeRawPtr<MediaQueryListListener> listener, PassRefPtrWillBeRawPtr<MediaQueryList> query) : m_listener(listener) , m_query(query) { } -MediaQueryMatcher::Listener::~Listener() +void MediaQueryMatcher::Listener::evaluate(MediaQueryEvaluator* evaluator) { + if (m_query->evaluate(evaluator)) + m_listener->queryChanged(m_query.get()); } -void MediaQueryMatcher::Listener::evaluate(ScriptState* state, MediaQueryEvaluator* evaluator) +void MediaQueryMatcher::Listener::trace(Visitor* visitor) { - bool notify; - m_query->evaluate(evaluator, notify); - if (notify) - m_listener->queryChanged(state, m_query.get()); + visitor->trace(m_listener); + visitor->trace(m_query); } MediaQueryMatcher::MediaQueryMatcher(Document* document) @@ -56,14 +56,12 @@ MediaQueryMatcher::MediaQueryMatcher(Document* document) ASSERT(m_document); } -MediaQueryMatcher::~MediaQueryMatcher() -{ -} +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryMatcher) void MediaQueryMatcher::documentDestroyed() { m_listeners.clear(); - m_document = 0; + m_document = nullptr; } AtomicString MediaQueryMatcher::mediaType() const @@ -79,14 +77,7 @@ PassOwnPtr<MediaQueryEvaluator> MediaQueryMatcher::prepareEvaluator() const if (!m_document || !m_document->frame()) return nullptr; - Element* documentElement = m_document->documentElement(); - if (!documentElement) - return nullptr; - - StyleResolver& styleResolver = m_document->ensureStyleResolver(); - RefPtr<RenderStyle> rootStyle = styleResolver.styleForElement(documentElement, 0 /*defaultParent*/, DisallowStyleSharing, MatchOnlyUserAgentRules); - - return adoptPtr(new MediaQueryEvaluator(mediaType(), m_document->frame(), rootStyle.get())); + return adoptPtr(new MediaQueryEvaluator(mediaType(), m_document->frame())); } bool MediaQueryMatcher::evaluate(const MediaQuerySet* media) @@ -98,18 +89,18 @@ bool MediaQueryMatcher::evaluate(const MediaQuerySet* media) return evaluator && evaluator->eval(media); } -PassRefPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query) +PassRefPtrWillBeRawPtr<MediaQueryList> MediaQueryMatcher::matchMedia(const String& query) { if (!m_document) - return 0; + return nullptr; - RefPtr<MediaQuerySet> media = MediaQuerySet::create(query); + RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(query); // Add warning message to inspector whenever dpi/dpcm values are used for "screen" media. reportMediaQueryWarningIfNeeded(m_document, media.get()); return MediaQueryList::create(this, media, evaluate(media.get())); } -void MediaQueryMatcher::addListener(PassRefPtr<MediaQueryListListener> listener, PassRefPtr<MediaQueryList> query) +void MediaQueryMatcher::addListener(PassRefPtrWillBeRawPtr<MediaQueryListListener> listener, PassRefPtrWillBeRawPtr<MediaQueryList> query) { if (!m_document) return; @@ -119,7 +110,7 @@ void MediaQueryMatcher::addListener(PassRefPtr<MediaQueryListListener> listener, return; } - m_listeners.append(adoptPtr(new Listener(listener, query))); + m_listeners.append(adoptPtrWillBeNoop(new Listener(listener, query))); } void MediaQueryMatcher::removeListener(MediaQueryListListener* listener, MediaQueryList* query) @@ -140,17 +131,23 @@ void MediaQueryMatcher::styleResolverChanged() if (!m_document) return; - ScriptState* scriptState = m_document->frame() ? mainWorldScriptState(m_document->frame()) : 0; - if (!scriptState) - return; - ++m_evaluationRound; OwnPtr<MediaQueryEvaluator> evaluator = prepareEvaluator(); if (!evaluator) return; for (size_t i = 0; i < m_listeners.size(); ++i) - m_listeners[i]->evaluate(scriptState, evaluator.get()); + m_listeners[i]->evaluate(evaluator.get()); +} + +void MediaQueryMatcher::trace(Visitor* visitor) +{ + visitor->trace(m_document); + // We don't support tracing of vectors of OwnPtrs (ie. Vector<OwnPtr<Listener> >). + // Since this is a transitional object we are just ifdef'ing it out when oilpan is not enabled. +#if ENABLE(OILPAN) + visitor->trace(m_listeners); +#endif } } diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.h b/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.h index 42945b485a1..abe862883b5 100644 --- a/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.h +++ b/chromium/third_party/WebKit/Source/core/css/MediaQueryMatcher.h @@ -20,7 +20,7 @@ #ifndef MediaQueryMatcher_h #define MediaQueryMatcher_h -#include "bindings/v8/ScriptState.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" #include "wtf/Vector.h" @@ -38,43 +38,45 @@ class MediaQuerySet; // whenever it is needed and to call the listeners if the corresponding query has changed. // The listeners must be called in the very same order in which they have been added. -class MediaQueryMatcher : public RefCounted<MediaQueryMatcher> { +class MediaQueryMatcher FINAL : public RefCountedWillBeGarbageCollected<MediaQueryMatcher> { + DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(MediaQueryMatcher); public: - static PassRefPtr<MediaQueryMatcher> create(Document* document) { return adoptRef(new MediaQueryMatcher(document)); } - ~MediaQueryMatcher(); + static PassRefPtrWillBeRawPtr<MediaQueryMatcher> create(Document* document) { return adoptRefWillBeNoop(new MediaQueryMatcher(document)); } void documentDestroyed(); - void addListener(PassRefPtr<MediaQueryListListener>, PassRefPtr<MediaQueryList>); + void addListener(PassRefPtrWillBeRawPtr<MediaQueryListListener>, PassRefPtrWillBeRawPtr<MediaQueryList>); void removeListener(MediaQueryListListener*, MediaQueryList*); - PassRefPtr<MediaQueryList> matchMedia(const String&); + PassRefPtrWillBeRawPtr<MediaQueryList> matchMedia(const String&); unsigned evaluationRound() const { return m_evaluationRound; } void styleResolverChanged(); bool evaluate(const MediaQuerySet*); + void trace(Visitor*); + private: - class Listener { + class Listener FINAL : public NoBaseWillBeGarbageCollected<Listener> { public: - Listener(PassRefPtr<MediaQueryListListener>, PassRefPtr<MediaQueryList>); - ~Listener(); - - void evaluate(ScriptState*, MediaQueryEvaluator*); + Listener(PassRefPtrWillBeRawPtr<MediaQueryListListener>, PassRefPtrWillBeRawPtr<MediaQueryList>); + void evaluate(MediaQueryEvaluator*); MediaQueryListListener* listener() { return m_listener.get(); } MediaQueryList* query() { return m_query.get(); } + void trace(Visitor*); + private: - RefPtr<MediaQueryListListener> m_listener; - RefPtr<MediaQueryList> m_query; + RefPtrWillBeMember<MediaQueryListListener> m_listener; + RefPtrWillBeMember<MediaQueryList> m_query; }; MediaQueryMatcher(Document*); PassOwnPtr<MediaQueryEvaluator> prepareEvaluator() const; AtomicString mediaType() const; - Document* m_document; - Vector<OwnPtr<Listener> > m_listeners; + RawPtrWillBeMember<Document> m_document; + WillBeHeapVector<OwnPtrWillBeMember<Listener> > m_listeners; // This value is incremented at style selector changes. // It is used to avoid evaluating queries more then once and to make sure diff --git a/chromium/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp b/chromium/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp new file mode 100644 index 00000000000..834625e3ece --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaQuerySetTest.cpp @@ -0,0 +1,171 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/MediaQuery.h" + +#include "core/css/MediaList.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/text/StringBuilder.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +typedef struct { + const char* input; + const char* output; + bool shouldWorkOnOldParser; +} TestCase; + +static void testMediaQuery(TestCase test, MediaQuerySet& querySet, bool oldParser) +{ + StringBuilder output; + size_t j = 0; + while (j < querySet.queryVector().size()) { + String queryText = querySet.queryVector()[j]->cssText(); + output.append(queryText); + ++j; + if (j >= querySet.queryVector().size()) + break; + output.append(", "); + } + if (!oldParser || test.shouldWorkOnOldParser) { + if (test.output) + ASSERT_STREQ(test.output, output.toString().ascii().data()); + else + ASSERT_STREQ(test.input, output.toString().ascii().data()); + } +} + +TEST(MediaQuerySetTest, Basic) +{ + // The first string represents the input string. + // The second string represents the output string, if present. + // Otherwise, the output string is identical to the first string. + TestCase testCases[] = { + {"", 0, true}, + {" ", "", true}, + {"screen", 0, true}, + {"screen and (color)", 0, true}, + {"all and (min-width:500px)", "(min-width: 500px)", true}, + {"all and (min-width:/*bla*/500px)", "(min-width: 500px)", true}, + {"(min-width:500px)", "(min-width: 500px)", true}, + {"screen and (color), projection and (color)", 0, true}, + {"not screen and (color)", 0, true}, + {"only screen and (color)", 0, true}, + {"screen and (color), projection and (color)", 0, true}, + {"aural and (device-aspect-ratio: 16/9)", 0, true}, + {"speech and (min-device-width: 800px)", 0, true}, + {"example", 0, true}, + {"screen and (max-weight: 3kg) and (color), (monochrome)", "not all, (monochrome)", true}, + {"(min-width: -100px)", "not all", true}, + {"(example, all,), speech", "not all, speech", true}, + {"&test, screen", "not all, screen", true}, + {"print and (min-width: 25cm)", 0, true}, + {"screen and (min-width: 400px) and (max-width: 700px)", "screen and (max-width: 700px) and (min-width: 400px)", true}, + {"screen and (device-width: 800px)", 0, true}, + {"screen and (device-height: 60em)", 0, true}, + {"screen and (device-aspect-ratio: 16/9)", 0, true}, + {"(device-aspect-ratio: 16.0/9.0)", "not all", true}, + {"(device-aspect-ratio: 16/ 9)", "(device-aspect-ratio: 16/9)", true}, + {"(device-aspect-ratio: 16/\r9)", "(device-aspect-ratio: 16/9)", true}, + {"all and (color)", "(color)", true}, + {"all and (min-color: 1)", "(min-color: 1)", true}, + {"all and (min-color: 1.0)", "not all", true}, + {"all and (min-color: 2)", "(min-color: 2)", true}, + {"all and (color-index)", "(color-index)", true}, + {"all and (min-color-index: 1)", "(min-color-index: 1)", true}, + {"all and (monochrome)", "(monochrome)", true}, + {"all and (min-monochrome: 1)", "(min-monochrome: 1)", true}, + {"all and (min-monochrome: 2)", "(min-monochrome: 2)", true}, + {"print and (monochrome)", 0, true}, + {"handheld and (grid) and (max-width: 15em)", 0, true}, + {"handheld and (grid) and (max-device-height: 7em)", 0, true}, + {"screen and (max-width: 50%)", "not all", true}, + {"screen and (max-WIDTH: 500px)", "screen and (max-width: 500px)", true}, + {"screen and (max-width: 24.4em)", 0, true}, + {"screen and (max-width: 24.4EM)", "screen and (max-width: 24.4em)", true}, + {"screen and (max-width: blabla)", "not all", true}, + {"screen and (max-width: 1)", "not all", true}, + {"screen and (max-width: 0)", 0, true}, + {"screen and (max-width: 1deg)", "not all", true}, + {"handheld and (min-width: 20em), \nscreen and (min-width: 20em)", "handheld and (min-width: 20em), screen and (min-width: 20em)", true}, + {"print and (min-resolution: 300dpi)", 0, true}, + {"print and (min-resolution: 118dpcm)", 0, true}, + {"(resolution: 0.83333333333333333333dppx)", "(resolution: 0.833333333333333dppx)", true}, + {"(resolution: 2.4dppx)", 0, true}, + {"all and(color)", "not all", true}, + {"all and (", "not all", true}, + {"test;,all", "not all, all", true}, + {"(color:20example)", "not all", false}, + {"not braille", 0, true}, + {",screen", "not all, screen", true}, + {",all", "not all, all", true}, + {",,all,,", "not all, not all, all, not all, not all", true}, + {",,all,, ", "not all, not all, all, not all, not all", true}, + {",screen,,&invalid,,", "not all, screen, not all, not all, not all, not all", true}, + {",screen,,(invalid,),,", "not all, screen, not all, not all, not all, not all", true}, + {",(all,),,", "not all, not all, not all, not all", true}, + {",", "not all, not all", true}, + {" ", "", true}, + {"(color", "(color)", true}, + {"(min-color: 2", "(min-color: 2)", true}, + {"(orientation: portrait)", 0, true}, + {"tv and (scan: progressive)", 0, true}, + {"(pointer: coarse)", 0, true}, + {"(min-orientation:portrait)", "not all", true}, + {"all and (orientation:portrait)", "(orientation: portrait)", true}, + {"all and (orientation:landscape)", "(orientation: landscape)", true}, + {"NOT braille, tv AND (max-width: 200px) and (min-WIDTH: 100px) and (orientation: landscape), (color)", + "not braille, tv and (max-width: 200px) and (min-width: 100px) and (orientation: landscape), (color)", true}, + {"(m\\61x-width: 300px)", "(max-width: 300px)", true}, + {"(max-width: 400\\70\\78)", "(max-width: 400px)", false}, + {"(max-width: 500\\0070\\0078)", "(max-width: 500px)", false}, + {"(max-width: 600\\000070\\000078)", "(max-width: 600px)", false}, + {"(max-width: 700px), (max-width: 700px)", "(max-width: 700px), (max-width: 700px)", true}, + {"(max-width: 800px()), (max-width: 800px)", "not all, (max-width: 800px)", true}, + {"(max-width: 900px(()), (max-width: 900px)", "not all", true}, + {"(max-width: 600px(())))), (max-width: 600px)", "not all, (max-width: 600px)", true}, + {"(max-width: 500px(((((((((())))), (max-width: 500px)", "not all", true}, + {"(max-width: 800px[]), (max-width: 800px)", "not all, (max-width: 800px)", true}, + {"(max-width: 900px[[]), (max-width: 900px)", "not all", true}, + {"(max-width: 600px[[]]]]), (max-width: 600px)", "not all, (max-width: 600px)", true}, + {"(max-width: 500px[[[[[[[[[[]]]]), (max-width: 500px)", "not all", true}, + {"(max-width: 800px{}), (max-width: 800px)", "not all, (max-width: 800px)", true}, + {"(max-width: 900px{{}), (max-width: 900px)", "not all", true}, + {"(max-width: 600px{{}}}}), (max-width: 600px)", "not all, (max-width: 600px)", true}, + {"(max-width: 500px{{{{{{{{{{}}}}), (max-width: 500px)", "not all", true}, + {"[(), (max-width: 400px)", "not all", true}, + {"[{}, (max-width: 500px)", "not all", true}, + {"[{]}], (max-width: 900px)", "not all, (max-width: 900px)", true}, + {"[{[]{}{{{}}}}], (max-width: 900px)", "not all, (max-width: 900px)", true}, + {"[{[}], (max-width: 900px)", "not all", true}, + {"[({)}], (max-width: 900px)", "not all", true}, + {"[]((), (max-width: 900px)", "not all", true}, + {"((), (max-width: 900px)", "not all", true}, + {"(foo(), (max-width: 900px)", "not all", true}, + {"[](()), (max-width: 900px)", "not all, (max-width: 900px)", true}, + {"all an[isdfs bla())()]icalc(i)(()), (max-width: 400px)", "not all, (max-width: 400px)", true}, + {"all an[isdfs bla())(]icalc(i)(()), (max-width: 500px)", "not all", true}, + {"all an[isdfs bla())(]icalc(i)(())), (max-width: 600px)", "not all", true}, + {"all an[isdfs bla())(]icalc(i)(()))], (max-width: 800px)", "not all, (max-width: 800px)", true}, + {"(max-width: '40px')", "not all", true}, + {"('max-width': 40px)", "not all", true}, + {"'\"'\", (max-width: 900px)", "not all", true}, + {"'\"\"\"', (max-width: 900px)", "not all, (max-width: 900px)", true}, + {"\"'\"', (max-width: 900px)", "not all", true}, + {"\"'''\", (max-width: 900px)", "not all, (max-width: 900px)", true}, + {0, 0} // Do not remove the terminator line. + }; + + for (unsigned i = 0; testCases[i].input; ++i) { + RefPtrWillBeRawPtr<MediaQuerySet> oldParserQuerySet = MediaQuerySet::create(testCases[i].input); + RefPtrWillBeRawPtr<MediaQuerySet> threadSafeQuerySet = MediaQuerySet::createOffMainThread(testCases[i].input); + testMediaQuery(testCases[i], *oldParserQuerySet, true); + testMediaQuery(testCases[i], *threadSafeQuerySet, false); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaTypeNames.in b/chromium/third_party/WebKit/Source/core/css/MediaTypeNames.in new file mode 100644 index 00000000000..556996d8c61 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaTypeNames.in @@ -0,0 +1,15 @@ +namespace="MediaType" +export="" + +# http://www.w3.org/TR/CSS2/media.html#media-types + +all +braille +embossed +handheld +print +projection +screen +speech +tty +tv diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValues.cpp b/chromium/third_party/WebKit/Source/core/css/MediaValues.cpp new file mode 100644 index 00000000000..a2d5e1b63c6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValues.cpp @@ -0,0 +1,206 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/MediaValues.h" + +#include "core/css/CSSHelper.h" +#include "core/css/MediaValuesCached.h" +#include "core/css/MediaValuesDynamic.h" +#include "core/dom/Document.h" +#include "core/dom/Element.h" +#include "core/frame/FrameHost.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/page/Page.h" +#include "core/rendering/RenderObject.h" +#include "core/rendering/RenderView.h" +#include "core/rendering/compositing/RenderLayerCompositor.h" +#include "core/rendering/style/RenderStyle.h" +#include "platform/PlatformScreen.h" + +namespace WebCore { + +PassRefPtr<MediaValues> MediaValues::createDynamicIfFrameExists(LocalFrame* frame) +{ + if (frame) + return MediaValuesDynamic::create(frame); + return MediaValuesCached::create(); +} + +int MediaValues::calculateViewportWidth(LocalFrame* frame) const +{ + ASSERT(frame && frame->view() && frame->document()); + int viewportWidth = frame->view()->layoutSize(IncludeScrollbars).width(); + return adjustForAbsoluteZoom(viewportWidth, frame->document()->renderView()); +} + +int MediaValues::calculateViewportHeight(LocalFrame* frame) const +{ + ASSERT(frame && frame->view() && frame->document()); + int viewportHeight = frame->view()->layoutSize(IncludeScrollbars).height(); + return adjustForAbsoluteZoom(viewportHeight, frame->document()->renderView()); +} + +int MediaValues::calculateDeviceWidth(LocalFrame* frame) const +{ + ASSERT(frame && frame->view() && frame->settings() && frame->host()); + int deviceWidth = static_cast<int>(screenRect(frame->view()).width()); + if (frame->settings()->reportScreenSizeInPhysicalPixelsQuirk()) + deviceWidth = lroundf(deviceWidth * frame->host()->deviceScaleFactor()); + return deviceWidth; +} + +int MediaValues::calculateDeviceHeight(LocalFrame* frame) const +{ + ASSERT(frame && frame->view() && frame->settings() && frame->host()); + int deviceHeight = static_cast<int>(screenRect(frame->view()).height()); + if (frame->settings()->reportScreenSizeInPhysicalPixelsQuirk()) + deviceHeight = lroundf(deviceHeight * frame->host()->deviceScaleFactor()); + return deviceHeight; +} + +bool MediaValues::calculateStrictMode(LocalFrame* frame) const +{ + ASSERT(frame && frame->document()); + return !frame->document()->inQuirksMode(); +} + +float MediaValues::calculateDevicePixelRatio(LocalFrame* frame) const +{ + return frame->devicePixelRatio(); +} + +int MediaValues::calculateColorBitsPerComponent(LocalFrame* frame) const +{ + ASSERT(frame && frame->page() && frame->page()->mainFrame()); + if (!frame->page()->mainFrame()->isLocalFrame() + || screenIsMonochrome(frame->page()->deprecatedLocalMainFrame()->view())) + return 0; + return screenDepthPerComponent(frame->view()); +} + +int MediaValues::calculateMonochromeBitsPerComponent(LocalFrame* frame) const +{ + ASSERT(frame && frame->page() && frame->page()->mainFrame()); + if (!frame->page()->mainFrame()->isLocalFrame() + || !screenIsMonochrome(frame->page()->deprecatedLocalMainFrame()->view())) + return 0; + return screenDepthPerComponent(frame->view()); +} + +int MediaValues::calculateDefaultFontSize(LocalFrame* frame) const +{ + return frame->host()->settings().defaultFontSize(); +} + +bool MediaValues::calculateScanMediaType(LocalFrame* frame) const +{ + ASSERT(frame && frame->view()); + // Scan only applies to 'tv' media. + return equalIgnoringCase(frame->view()->mediaType(), "tv"); +} + +bool MediaValues::calculateScreenMediaType(LocalFrame* frame) const +{ + ASSERT(frame && frame->view()); + return equalIgnoringCase(frame->view()->mediaType(), "screen"); +} + +bool MediaValues::calculatePrintMediaType(LocalFrame* frame) const +{ + ASSERT(frame && frame->view()); + return equalIgnoringCase(frame->view()->mediaType(), "print"); +} + +bool MediaValues::calculateThreeDEnabled(LocalFrame* frame) const +{ + ASSERT(frame && frame->contentRenderer() && frame->contentRenderer()->compositor()); + bool threeDEnabled = false; + if (RenderView* view = frame->contentRenderer()) + threeDEnabled = view->compositor()->hasAcceleratedCompositing(); + return threeDEnabled; +} + +MediaValues::PointerDeviceType MediaValues::calculateLeastCapablePrimaryPointerDeviceType(LocalFrame* frame) const +{ + ASSERT(frame && frame->settings()); + if (frame->settings()->deviceSupportsTouch()) + return MediaValues::TouchPointer; + + // FIXME: We should also try to determine if we know we have a mouse. + // When we do this, we'll also need to differentiate between known not to + // have mouse or touch screen (NoPointer) and unknown (UnknownPointer). + // We could also take into account other preferences like accessibility + // settings to decide which of the available pointers should be considered + // "primary". + + return MediaValues::UnknownPointer; +} + +bool MediaValues::computeLengthImpl(double value, CSSPrimitiveValue::UnitType type, unsigned defaultFontSize, unsigned viewportWidth, unsigned viewportHeight, double& result) +{ + // The logic in this function is duplicated from CSSPrimitiveValue::computeLengthDouble + // because MediaValues::computeLength needs nearly identical logic, but we haven't found a way to make + // CSSPrimitiveValue::computeLengthDouble more generic (to solve both cases) without hurting performance. + + // FIXME - Unite the logic here with CSSPrimitiveValue in a performant way. + double factor = 0; + switch (type) { + case CSSPrimitiveValue::CSS_EMS: + case CSSPrimitiveValue::CSS_REMS: + factor = defaultFontSize; + break; + case CSSPrimitiveValue::CSS_PX: + factor = 1; + break; + case CSSPrimitiveValue::CSS_EXS: + // FIXME: We have a bug right now where the zoom will be applied twice to EX units. + // FIXME: We don't seem to be able to cache fontMetrics related values. + // Trying to access them is triggering some sort of microtask. Serving the spec's default instead. + factor = defaultFontSize / 2.0; + break; + case CSSPrimitiveValue::CSS_CHS: + // FIXME: We don't seem to be able to cache fontMetrics related values. + // Trying to access them is triggering some sort of microtask. Serving the (future) spec default instead. + factor = defaultFontSize / 2.0; + break; + case CSSPrimitiveValue::CSS_VW: + factor = viewportWidth / 100.0; + break; + case CSSPrimitiveValue::CSS_VH: + factor = viewportHeight / 100.0; + break; + case CSSPrimitiveValue::CSS_VMIN: + factor = std::min(viewportWidth, viewportHeight) / 100.0; + break; + case CSSPrimitiveValue::CSS_VMAX: + factor = std::max(viewportWidth, viewportHeight) / 100.0; + break; + case CSSPrimitiveValue::CSS_CM: + factor = cssPixelsPerCentimeter; + break; + case CSSPrimitiveValue::CSS_MM: + factor = cssPixelsPerMillimeter; + break; + case CSSPrimitiveValue::CSS_IN: + factor = cssPixelsPerInch; + break; + case CSSPrimitiveValue::CSS_PT: + factor = cssPixelsPerPoint; + break; + case CSSPrimitiveValue::CSS_PC: + factor = cssPixelsPerPica; + break; + default: + return false; + } + + ASSERT(factor > 0); + result = value * factor; + return true; +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValues.h b/chromium/third_party/WebKit/Source/core/css/MediaValues.h new file mode 100644 index 00000000000..eee54657b37 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValues.h @@ -0,0 +1,88 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaValues_h +#define MediaValues_h + +#include "core/css/CSSPrimitiveValue.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" + +namespace WebCore { + +class Document; +class CSSPrimitiveValue; +class LocalFrame; + +class MediaValues : public RefCounted<MediaValues> { +public: + + enum MediaValuesMode { + CachingMode, + DynamicMode + }; + + enum PointerDeviceType { + TouchPointer, + MousePointer, + NoPointer, + UnknownPointer + }; + + virtual ~MediaValues() { } + + static PassRefPtr<MediaValues> createDynamicIfFrameExists(LocalFrame*); + virtual PassRefPtr<MediaValues> copy() const = 0; + virtual bool isSafeToSendToAnotherThread() const = 0; + + static bool computeLengthImpl(double value, CSSPrimitiveValue::UnitType, unsigned defaultFontSize, unsigned viewportWidth, unsigned viewportHeight, double& result); + template<typename T> + static bool computeLength(double value, CSSPrimitiveValue::UnitType type, unsigned defaultFontSize, unsigned viewportWidth, unsigned viewportHeight, T& result) + { + double tempResult; + if (!computeLengthImpl(value, type, defaultFontSize, viewportWidth, viewportHeight, tempResult)) + return false; + result = roundForImpreciseConversion<T>(tempResult); + return true; + } + virtual bool computeLength(double value, CSSPrimitiveValue::UnitType, int& result) const = 0; + virtual bool computeLength(double value, CSSPrimitiveValue::UnitType, double& result) const = 0; + + virtual int viewportWidth() const = 0; + virtual int viewportHeight() const = 0; + virtual int deviceWidth() const = 0; + virtual int deviceHeight() const = 0; + virtual float devicePixelRatio() const = 0; + virtual int colorBitsPerComponent() const = 0; + virtual int monochromeBitsPerComponent() const = 0; + virtual PointerDeviceType pointer() const = 0; + virtual bool threeDEnabled() const = 0; + virtual bool scanMediaType() const = 0; + virtual bool screenMediaType() const = 0; + virtual bool printMediaType() const = 0; + virtual bool strictMode() const = 0; + virtual Document* document() const = 0; + virtual bool hasValues() const = 0; + +protected: + int calculateViewportWidth(LocalFrame*) const; + int calculateViewportHeight(LocalFrame*) const; + int calculateDeviceWidth(LocalFrame*) const; + int calculateDeviceHeight(LocalFrame*) const; + bool calculateStrictMode(LocalFrame*) const; + float calculateDevicePixelRatio(LocalFrame*) const; + int calculateColorBitsPerComponent(LocalFrame*) const; + int calculateMonochromeBitsPerComponent(LocalFrame*) const; + int calculateDefaultFontSize(LocalFrame*) const; + bool calculateScanMediaType(LocalFrame*) const; + bool calculateScreenMediaType(LocalFrame*) const; + bool calculatePrintMediaType(LocalFrame*) const; + bool calculateThreeDEnabled(LocalFrame*) const; + MediaValues::PointerDeviceType calculateLeastCapablePrimaryPointerDeviceType(LocalFrame*) const; + +}; + +} // namespace + +#endif // MediaValues_h diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValuesCached.cpp b/chromium/third_party/WebKit/Source/core/css/MediaValuesCached.cpp new file mode 100644 index 00000000000..570a3a51709 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValuesCached.cpp @@ -0,0 +1,169 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/MediaValuesCached.h" + +#include "core/css/CSSPrimitiveValue.h" +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" +#include "core/html/imports/HTMLImportsController.h" +#include "core/rendering/RenderObject.h" + +namespace WebCore { + +PassRefPtr<MediaValues> MediaValuesCached::create() +{ + return adoptRef(new MediaValuesCached()); +} + +PassRefPtr<MediaValues> MediaValuesCached::create(MediaValuesCachedData& data) +{ + return adoptRef(new MediaValuesCached(data)); +} + +PassRefPtr<MediaValues> MediaValuesCached::create(Document& document) +{ + Document* executingDocument = document.importsController() ? document.importsController()->master() : &document; + ASSERT(executingDocument); + return MediaValuesCached::create(executingDocument->frame()); +} + +PassRefPtr<MediaValues> MediaValuesCached::create(LocalFrame* frame) +{ + // FIXME - Added an assert here so we can better understand when a frame is present without its view(). + ASSERT(!frame || frame->view()); + // FIXME - Because of crbug.com/371084, document()->renderView() may be null here. + if (!frame || !frame->view() || !frame->document() || !frame->document()->renderView()) + return adoptRef(new MediaValuesCached()); + return adoptRef(new MediaValuesCached(frame)); +} + +MediaValuesCached::MediaValuesCached() +{ +} + +MediaValuesCached::MediaValuesCached(LocalFrame* frame) +{ + ASSERT(isMainThread()); + ASSERT(frame); + // In case that frame is missing (e.g. for images that their document does not have a frame) + // We simply leave the MediaValues object with the default MediaValuesCachedData values. + m_data.viewportWidth = calculateViewportWidth(frame); + m_data.viewportHeight = calculateViewportHeight(frame); + m_data.deviceWidth = calculateDeviceWidth(frame); + m_data.deviceHeight = calculateDeviceHeight(frame); + m_data.devicePixelRatio = calculateDevicePixelRatio(frame); + m_data.colorBitsPerComponent = calculateColorBitsPerComponent(frame); + m_data.monochromeBitsPerComponent = calculateMonochromeBitsPerComponent(frame); + m_data.pointer = calculateLeastCapablePrimaryPointerDeviceType(frame); + m_data.defaultFontSize = calculateDefaultFontSize(frame); + m_data.threeDEnabled = calculateThreeDEnabled(frame); + m_data.scanMediaType = calculateScanMediaType(frame); + m_data.screenMediaType = calculateScreenMediaType(frame); + m_data.printMediaType = calculatePrintMediaType(frame); + m_data.strictMode = calculateStrictMode(frame); +} + +MediaValuesCached::MediaValuesCached(const MediaValuesCachedData& data) + : m_data(data) +{ +} + +PassRefPtr<MediaValues> MediaValuesCached::copy() const +{ + return adoptRef(new MediaValuesCached(m_data)); +} + +bool MediaValuesCached::computeLength(double value, CSSPrimitiveValue::UnitType type, int& result) const +{ + return MediaValues::computeLength(value, type, m_data.defaultFontSize, m_data.viewportWidth, m_data.viewportHeight, result); +} + +bool MediaValuesCached::computeLength(double value, CSSPrimitiveValue::UnitType type, double& result) const +{ + return MediaValues::computeLength(value, type, m_data.defaultFontSize, m_data.viewportWidth, m_data.viewportHeight, result); +} + +bool MediaValuesCached::isSafeToSendToAnotherThread() const +{ + return hasOneRef(); +} + +int MediaValuesCached::viewportWidth() const +{ + return m_data.viewportWidth; +} + +int MediaValuesCached::viewportHeight() const +{ + return m_data.viewportHeight; +} + +int MediaValuesCached::deviceWidth() const +{ + return m_data.deviceWidth; +} + +int MediaValuesCached::deviceHeight() const +{ + return m_data.deviceHeight; +} + +float MediaValuesCached::devicePixelRatio() const +{ + return m_data.devicePixelRatio; +} + +int MediaValuesCached::colorBitsPerComponent() const +{ + return m_data.colorBitsPerComponent; +} + +int MediaValuesCached::monochromeBitsPerComponent() const +{ + return m_data.monochromeBitsPerComponent; +} + +MediaValues::PointerDeviceType MediaValuesCached::pointer() const +{ + return m_data.pointer; +} + +bool MediaValuesCached::threeDEnabled() const +{ + return m_data.threeDEnabled; +} + +bool MediaValuesCached::scanMediaType() const +{ + return m_data.scanMediaType; +} + +bool MediaValuesCached::screenMediaType() const +{ + return m_data.screenMediaType; +} + +bool MediaValuesCached::printMediaType() const +{ + return m_data.printMediaType; +} + +bool MediaValuesCached::strictMode() const +{ + return m_data.strictMode; +} + +Document* MediaValuesCached::document() const +{ + return 0; +} + +bool MediaValuesCached::hasValues() const +{ + return true; +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValuesCached.h b/chromium/third_party/WebKit/Source/core/css/MediaValuesCached.h new file mode 100644 index 00000000000..c3ff031c884 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValuesCached.h @@ -0,0 +1,85 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaValuesCached_h +#define MediaValuesCached_h + +#include "core/css/MediaValues.h" + +namespace WebCore { + +class MediaValuesCached FINAL : public MediaValues { +public: + struct MediaValuesCachedData { + // Members variables must be thread safe, since they're copied to the parser thread + int viewportWidth; + int viewportHeight; + int deviceWidth; + int deviceHeight; + float devicePixelRatio; + int colorBitsPerComponent; + int monochromeBitsPerComponent; + PointerDeviceType pointer; + int defaultFontSize; + bool threeDEnabled; + bool scanMediaType; + bool screenMediaType; + bool printMediaType; + bool strictMode; + + MediaValuesCachedData() + : viewportWidth(0) + , viewportHeight(0) + , deviceWidth(0) + , deviceHeight(0) + , devicePixelRatio(1.0) + , colorBitsPerComponent(24) + , monochromeBitsPerComponent(0) + , pointer(UnknownPointer) + , defaultFontSize(16) + , threeDEnabled(false) + , scanMediaType(false) + , screenMediaType(true) + , printMediaType(false) + , strictMode(true) + { + } + }; + + static PassRefPtr<MediaValues> create(); + static PassRefPtr<MediaValues> create(Document&); + static PassRefPtr<MediaValues> create(LocalFrame*); + static PassRefPtr<MediaValues> create(MediaValuesCachedData&); + virtual PassRefPtr<MediaValues> copy() const OVERRIDE; + virtual bool isSafeToSendToAnotherThread() const OVERRIDE; + virtual bool computeLength(double value, CSSPrimitiveValue::UnitType, int& result) const OVERRIDE; + virtual bool computeLength(double value, CSSPrimitiveValue::UnitType, double& result) const OVERRIDE; + + virtual int viewportWidth() const OVERRIDE; + virtual int viewportHeight() const OVERRIDE; + virtual int deviceWidth() const OVERRIDE; + virtual int deviceHeight() const OVERRIDE; + virtual float devicePixelRatio() const OVERRIDE; + virtual int colorBitsPerComponent() const OVERRIDE; + virtual int monochromeBitsPerComponent() const OVERRIDE; + virtual PointerDeviceType pointer() const OVERRIDE; + virtual bool threeDEnabled() const OVERRIDE; + virtual bool scanMediaType() const OVERRIDE; + virtual bool screenMediaType() const OVERRIDE; + virtual bool printMediaType() const OVERRIDE; + virtual bool strictMode() const OVERRIDE; + virtual Document* document() const OVERRIDE; + virtual bool hasValues() const OVERRIDE; + +protected: + MediaValuesCached(); + MediaValuesCached(LocalFrame*); + MediaValuesCached(const MediaValuesCachedData&); + + MediaValuesCachedData m_data; +}; + +} // namespace + +#endif // MediaValuesCached_h diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp b/chromium/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp new file mode 100644 index 00000000000..2ac823feb98 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValuesDynamic.cpp @@ -0,0 +1,132 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/MediaValuesDynamic.h" + +#include "core/css/CSSHelper.h" +#include "core/css/CSSPrimitiveValue.h" +#include "core/css/CSSToLengthConversionData.h" +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" + +namespace WebCore { + +PassRefPtr<MediaValues> MediaValuesDynamic::create(LocalFrame* frame) +{ + return adoptRef(new MediaValuesDynamic(frame)); +} + +MediaValuesDynamic::MediaValuesDynamic(LocalFrame* frame) + : m_frame(frame) +{ + ASSERT(m_frame); +} + +PassRefPtr<MediaValues> MediaValuesDynamic::copy() const +{ + return adoptRef(new MediaValuesDynamic(m_frame)); +} + +bool MediaValuesDynamic::computeLength(double value, CSSPrimitiveValue::UnitType type, int& result) const +{ + return MediaValues::computeLength(value, + type, + calculateDefaultFontSize(m_frame), + calculateViewportWidth(m_frame), + calculateViewportHeight(m_frame), + result); +} + +bool MediaValuesDynamic::computeLength(double value, CSSPrimitiveValue::UnitType type, double& result) const +{ + return MediaValues::computeLength(value, + type, + calculateDefaultFontSize(m_frame), + calculateViewportWidth(m_frame), + calculateViewportHeight(m_frame), + result); +} + +bool MediaValuesDynamic::isSafeToSendToAnotherThread() const +{ + return false; +} + +int MediaValuesDynamic::viewportWidth() const +{ + return calculateViewportWidth(m_frame); +} + +int MediaValuesDynamic::viewportHeight() const +{ + return calculateViewportHeight(m_frame); +} + +int MediaValuesDynamic::deviceWidth() const +{ + return calculateDeviceWidth(m_frame); +} + +int MediaValuesDynamic::deviceHeight() const +{ + return calculateDeviceHeight(m_frame); +} + +float MediaValuesDynamic::devicePixelRatio() const +{ + return calculateDevicePixelRatio(m_frame); +} + +int MediaValuesDynamic::colorBitsPerComponent() const +{ + return calculateColorBitsPerComponent(m_frame); +} + +int MediaValuesDynamic::monochromeBitsPerComponent() const +{ + return calculateMonochromeBitsPerComponent(m_frame); +} + +MediaValues::PointerDeviceType MediaValuesDynamic::pointer() const +{ + return calculateLeastCapablePrimaryPointerDeviceType(m_frame); +} + +bool MediaValuesDynamic::threeDEnabled() const +{ + return calculateThreeDEnabled(m_frame); +} + +bool MediaValuesDynamic::scanMediaType() const +{ + return calculateScanMediaType(m_frame); +} + +bool MediaValuesDynamic::screenMediaType() const +{ + return calculateScreenMediaType(m_frame); +} + +bool MediaValuesDynamic::printMediaType() const +{ + return calculatePrintMediaType(m_frame); +} + +bool MediaValuesDynamic::strictMode() const +{ + return calculateStrictMode(m_frame); +} + +Document* MediaValuesDynamic::document() const +{ + return m_frame->document(); +} + +bool MediaValuesDynamic::hasValues() const +{ + return m_frame; +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValuesDynamic.h b/chromium/third_party/WebKit/Source/core/css/MediaValuesDynamic.h new file mode 100644 index 00000000000..26fac877451 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValuesDynamic.h @@ -0,0 +1,49 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaValuesDynamic_h +#define MediaValuesDynamic_h + +#include "core/css/MediaValues.h" + +namespace WebCore { + +class Document; + +class MediaValuesDynamic FINAL : public MediaValues { +public: + static PassRefPtr<MediaValues> create(LocalFrame*); + virtual PassRefPtr<MediaValues> copy() const OVERRIDE; + virtual bool isSafeToSendToAnotherThread() const OVERRIDE; + virtual bool computeLength(double value, CSSPrimitiveValue::UnitType, int& result) const OVERRIDE; + virtual bool computeLength(double value, CSSPrimitiveValue::UnitType, double& result) const OVERRIDE; + + virtual int viewportWidth() const OVERRIDE; + virtual int viewportHeight() const OVERRIDE; + virtual int deviceWidth() const OVERRIDE; + virtual int deviceHeight() const OVERRIDE; + virtual float devicePixelRatio() const OVERRIDE; + virtual int colorBitsPerComponent() const OVERRIDE; + virtual int monochromeBitsPerComponent() const OVERRIDE; + virtual PointerDeviceType pointer() const OVERRIDE; + virtual bool threeDEnabled() const OVERRIDE; + virtual bool scanMediaType() const OVERRIDE; + virtual bool screenMediaType() const OVERRIDE; + virtual bool printMediaType() const OVERRIDE; + virtual bool strictMode() const OVERRIDE; + virtual Document* document() const OVERRIDE; + virtual bool hasValues() const OVERRIDE; + +protected: + MediaValuesDynamic(LocalFrame*); + + // This raw ptr is safe, as MediaValues would not outlive MediaQueryEvaluator, and + // MediaQueryEvaluator is reset on |Document::detach|. + // FIXME: Oilpan: This raw ptr should be changed to a Member when LocalFrame is migrated to the heap. + LocalFrame* m_frame; +}; + +} // namespace + +#endif // MediaValuesDynamic_h diff --git a/chromium/third_party/WebKit/Source/core/css/MediaValuesTest.cpp b/chromium/third_party/WebKit/Source/core/css/MediaValuesTest.cpp new file mode 100644 index 00000000000..f4b9c8b650a --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/MediaValuesTest.cpp @@ -0,0 +1,61 @@ +// Use of this source code is governed by a BSD-style license that can be +// Copyright 2014 The Chromium Authors. All rights reserved. +// found in the LICENSE file. + +#include "config.h" +#include "core/css/MediaValues.h" + +#include "core/css/CSSPrimitiveValue.h" +#include "wtf/text/StringBuilder.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +struct TestCase { + double value; + CSSPrimitiveValue::UnitType type; + unsigned fontSize; + unsigned viewportWidth; + unsigned viewportHeight; + bool success; + int output; +}; + +TEST(MediaValuesTest, Basic) +{ + TestCase testCases[] = { + { 40.0, CSSPrimitiveValue::CSS_PX, 16, 300, 300, true, 40 }, + { 40.0, CSSPrimitiveValue::CSS_EMS, 16, 300, 300, true, 640 }, + { 40.0, CSSPrimitiveValue::CSS_REMS, 16, 300, 300, true, 640 }, + { 40.0, CSSPrimitiveValue::CSS_EXS, 16, 300, 300, true, 320 }, + { 40.0, CSSPrimitiveValue::CSS_CHS, 16, 300, 300, true, 320 }, + { 43.0, CSSPrimitiveValue::CSS_VW, 16, 848, 976, true, 364 }, + { 43.0, CSSPrimitiveValue::CSS_VH, 16, 848, 976, true, 419 }, + { 43.0, CSSPrimitiveValue::CSS_VMIN, 16, 848, 976, true, 364 }, + { 43.0, CSSPrimitiveValue::CSS_VMAX, 16, 848, 976, true, 419 }, + { 1.3, CSSPrimitiveValue::CSS_CM, 16, 300, 300, true, 49 }, + { 1.3, CSSPrimitiveValue::CSS_MM, 16, 300, 300, true, 4 }, + { 1.3, CSSPrimitiveValue::CSS_IN, 16, 300, 300, true, 124 }, + { 13, CSSPrimitiveValue::CSS_PT, 16, 300, 300, true, 17 }, + { 1.3, CSSPrimitiveValue::CSS_PC, 16, 300, 300, true, 20 }, + { 1.3, CSSPrimitiveValue::CSS_UNKNOWN, 16, 300, 300, false, 20 }, + { 0.0, CSSPrimitiveValue::CSS_UNKNOWN, 0, 0, 0, false, 0.0 } // Do not remove the terminating line. + }; + + + for (unsigned i = 0; testCases[i].viewportWidth; ++i) { + int output = 0; + bool success = MediaValues::computeLength(testCases[i].value, + testCases[i].type, + testCases[i].fontSize, + testCases[i].viewportWidth, + testCases[i].viewportHeight, + output); + ASSERT_EQ(testCases[i].success, success); + if (success) + ASSERT_EQ(testCases[i].output, output); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.cpp b/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.cpp index e4494526d30..3e8c76f8919 100644 --- a/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.cpp +++ b/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.cpp @@ -73,7 +73,7 @@ void PageRuleCollector::matchPageRules(RuleSet* rules) return; rules->compactRulesIfNeeded(); - Vector<StyleRulePage*> matchedPageRules; + WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> > matchedPageRules; matchPageRulesForList(matchedPageRules, rules->pageRules(), m_isLeftPage, m_isFirstPage, m_pageName); if (matchedPageRules.isEmpty()) return; @@ -81,13 +81,13 @@ void PageRuleCollector::matchPageRules(RuleSet* rules) std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules); for (unsigned i = 0; i < matchedPageRules.size(); i++) - m_result.addMatchedProperties(matchedPageRules[i]->properties()); + m_result.addMatchedProperties(&matchedPageRules[i]->properties()); } static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeftPage, bool isFirstPage, const String& pageName) { for (const CSSSelector* component = selector; component; component = component->tagHistory()) { - if (component->m_match == CSSSelector::Tag) { + if (component->match() == CSSSelector::Tag) { const AtomicString& localName = component->tagQName().localName(); if (localName != starAtom && localName != pageName) return false; @@ -104,7 +104,7 @@ static bool checkPageSelectorComponents(const CSSSelector* selector, bool isLeft return true; } -void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName) +void PageRuleCollector::matchPageRulesForList(WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >& matchedRules, const WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >& rules, bool isLeftPage, bool isFirstPage, const String& pageName) { for (unsigned i = 0; i < rules.size(); ++i) { StyleRulePage* rule = rules[i]; @@ -113,8 +113,8 @@ void PageRuleCollector::matchPageRulesForList(Vector<StyleRulePage*>& matchedRul continue; // If the rule has no properties to apply, then ignore it. - const StylePropertySet* properties = rule->properties(); - if (!properties || properties->isEmpty()) + const StylePropertySet& properties = rule->properties(); + if (properties.isEmpty()) continue; // Add this rule to our list of matched rules. diff --git a/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.h b/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.h index 83251612aaf..af632809358 100644 --- a/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.h +++ b/chromium/third_party/WebKit/Source/core/css/PageRuleCollector.h @@ -31,6 +31,7 @@ class ElementResolveContext; class StyleRulePage; class PageRuleCollector { + STACK_ALLOCATED(); public: PageRuleCollector(const RenderStyle* rootElementStyle, int pageIndex); @@ -43,7 +44,7 @@ private: bool isFirstPage(int pageIndex) const; String pageName(int pageIndex) const; - void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName); + void matchPageRulesForList(WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >& matchedRules, const WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >& rules, bool isLeftPage, bool isFirstPage, const String& pageName); const bool m_isLeftPage; const bool m_isFirstPage; diff --git a/chromium/third_party/WebKit/Source/core/css/Pair.cpp b/chromium/third_party/WebKit/Source/core/css/Pair.cpp new file mode 100644 index 00000000000..5362b6b5274 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/Pair.cpp @@ -0,0 +1,16 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/Pair.h" + +namespace WebCore { + +void Pair::trace(Visitor* visitor) +{ + visitor->trace(m_first); + visitor->trace(m_second); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/css/Pair.h b/chromium/third_party/WebKit/Source/core/css/Pair.h index fc2edaa828b..5cafb532092 100644 --- a/chromium/third_party/WebKit/Source/core/css/Pair.h +++ b/chromium/third_party/WebKit/Source/core/css/Pair.h @@ -32,25 +32,22 @@ namespace WebCore { // and border-spacing (all of which are space-separated sets of two values). At the moment we are only using it for // border-radius and background-size, but (FIXME) border-spacing and background-position could be converted over to use // it (eliminating some extra -webkit- internal properties). -class Pair FINAL : public RefCounted<Pair> { +class Pair FINAL : public RefCountedWillBeGarbageCollected<Pair> { public: enum IdenticalValuesPolicy { DropIdenticalValues, KeepIdenticalValues }; - static PassRefPtr<Pair> create() + static PassRefPtrWillBeRawPtr<Pair> create(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> first, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> second, + IdenticalValuesPolicy identicalValuesPolicy) { - return adoptRef(new Pair); - } - static PassRefPtr<Pair> create(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second, IdenticalValuesPolicy identicalValuesPolicy) - { - return adoptRef(new Pair(first, second, identicalValuesPolicy)); + return adoptRefWillBeNoop(new Pair(first, second, identicalValuesPolicy)); } CSSPrimitiveValue* first() const { return m_first.get(); } CSSPrimitiveValue* second() const { return m_second.get(); } IdenticalValuesPolicy identicalValuesPolicy() const { return m_identicalValuesPolicy; } - void setFirst(PassRefPtr<CSSPrimitiveValue> first) { m_first = first; } - void setSecond(PassRefPtr<CSSPrimitiveValue> second) { m_second = second; } + void setFirst(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> first) { m_first = first; } + void setSecond(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> second) { m_second = second; } void setIdenticalValuesPolicy(IdenticalValuesPolicy identicalValuesPolicy) { m_identicalValuesPolicy = identicalValuesPolicy; } String cssText() const @@ -65,23 +62,15 @@ public: && m_identicalValuesPolicy == other.m_identicalValuesPolicy; } - String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const - { - return generateCSSString( - first()->customSerializeResolvingVariables(variables), - second()->customSerializeResolvingVariables(variables), - m_identicalValuesPolicy); - } - - bool hasVariableReference() const { return first()->hasVariableReference() || second()->hasVariableReference(); } + void trace(Visitor*); private: Pair() - : m_first(0) - , m_second(0) + : m_first(nullptr) + , m_second(nullptr) , m_identicalValuesPolicy(DropIdenticalValues) { } - Pair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second, IdenticalValuesPolicy identicalValuesPolicy) + Pair(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> first, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> second, IdenticalValuesPolicy identicalValuesPolicy) : m_first(first) , m_second(second) , m_identicalValuesPolicy(identicalValuesPolicy) { } @@ -93,8 +82,8 @@ private: return first + ' ' + second; } - RefPtr<CSSPrimitiveValue> m_first; - RefPtr<CSSPrimitiveValue> m_second; + RefPtrWillBeMember<CSSPrimitiveValue> m_first; + RefPtrWillBeMember<CSSPrimitiveValue> m_second; IdenticalValuesPolicy m_identicalValuesPolicy; }; diff --git a/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp index e30610ab3a2..b6d0f6eed1f 100644 --- a/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp +++ b/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp @@ -22,18 +22,16 @@ #include "config.h" #include "core/css/PropertySetCSSStyleDeclaration.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionState.h" -#include "core/css/CSSParser.h" +#include "core/HTMLNames.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSStyleSheet.h" #include "core/css/StylePropertySet.h" #include "core/dom/Element.h" #include "core/dom/MutationObserverInterestGroup.h" #include "core/dom/MutationRecord.h" #include "core/inspector/InspectorInstrumentation.h" - -using namespace std; +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { @@ -41,8 +39,9 @@ namespace { class StyleAttributeMutationScope { WTF_MAKE_NONCOPYABLE(StyleAttributeMutationScope); + STACK_ALLOCATED(); public: - StyleAttributeMutationScope(PropertySetCSSStyleDeclaration* decl) + StyleAttributeMutationScope(AbstractPropertySetCSSStyleDeclaration* decl) { InspectorInstrumentation::willMutateStyle(decl); ++s_scopeCount; @@ -86,7 +85,7 @@ public: s_shouldDeliver = false; // We have to clear internal state before calling Inspector's code. - PropertySetCSSStyleDeclaration* localCopyStyleDecl = s_currentDecl; + AbstractPropertySetCSSStyleDeclaration* localCopyStyleDecl = s_currentDecl; s_currentDecl = 0; InspectorInstrumentation::didMutateStyle(localCopyStyleDecl, localCopyStyleDecl->parentElement()); @@ -110,21 +109,22 @@ public: private: static unsigned s_scopeCount; - static PropertySetCSSStyleDeclaration* s_currentDecl; + static AbstractPropertySetCSSStyleDeclaration* s_currentDecl; static bool s_shouldNotifyInspector; static bool s_shouldDeliver; - OwnPtr<MutationObserverInterestGroup> m_mutationRecipients; - RefPtr<MutationRecord> m_mutation; + OwnPtrWillBeMember<MutationObserverInterestGroup> m_mutationRecipients; + RefPtrWillBeMember<MutationRecord> m_mutation; }; unsigned StyleAttributeMutationScope::s_scopeCount = 0; -PropertySetCSSStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = 0; +AbstractPropertySetCSSStyleDeclaration* StyleAttributeMutationScope::s_currentDecl = 0; bool StyleAttributeMutationScope::s_shouldNotifyInspector = false; bool StyleAttributeMutationScope::s_shouldDeliver = false; } // namespace +#if !ENABLE(OILPAN) void PropertySetCSSStyleDeclaration::ref() { m_propertySet->ref(); @@ -134,103 +134,101 @@ void PropertySetCSSStyleDeclaration::deref() { m_propertySet->deref(); } +#endif -unsigned PropertySetCSSStyleDeclaration::length() const +void PropertySetCSSStyleDeclaration::trace(Visitor* visitor) { - return m_propertySet->propertyCount(); + visitor->trace(m_propertySet); + AbstractPropertySetCSSStyleDeclaration::trace(visitor); } -String PropertySetCSSStyleDeclaration::item(unsigned i) const +unsigned AbstractPropertySetCSSStyleDeclaration::length() const { - if (i >= m_propertySet->propertyCount()) + return propertySet().propertyCount(); +} + +String AbstractPropertySetCSSStyleDeclaration::item(unsigned i) const +{ + if (i >= propertySet().propertyCount()) return ""; - return m_propertySet->propertyAt(i).cssName(); + return propertySet().propertyAt(i).cssName(); } -String PropertySetCSSStyleDeclaration::cssText() const +String AbstractPropertySetCSSStyleDeclaration::cssText() const { - return m_propertySet->asText(); + return propertySet().asText(); } -void PropertySetCSSStyleDeclaration::setCSSText(const String& text, ExceptionState& exceptionState) +void AbstractPropertySetCSSStyleDeclaration::setCSSText(const String& text, ExceptionState& exceptionState) { StyleAttributeMutationScope mutationScope(this); willMutate(); // FIXME: Detect syntax errors and set exceptionState. - m_propertySet->parseDeclaration(text, contextStyleSheet()); + propertySet().parseDeclaration(text, contextStyleSheet()); didMutate(PropertyChanged); mutationScope.enqueueMutationRecord(); } -PassRefPtr<CSSValue> PropertySetCSSStyleDeclaration::getPropertyCSSValue(const String& propertyName) +PassRefPtrWillBeRawPtr<CSSValue> AbstractPropertySetCSSStyleDeclaration::getPropertyCSSValue(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) - return 0; - return cloneAndCacheForCSSOM(m_propertySet->getPropertyCSSValue(propertyID).get()); + return nullptr; + return cloneAndCacheForCSSOM(propertySet().getPropertyCSSValue(propertyID).get()); } -String PropertySetCSSStyleDeclaration::getPropertyValue(const String &propertyName) +String AbstractPropertySetCSSStyleDeclaration::getPropertyValue(const String &propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) return String(); - return m_propertySet->getPropertyValue(propertyID); + return propertySet().getPropertyValue(propertyID); } -String PropertySetCSSStyleDeclaration::getPropertyPriority(const String& propertyName) +String AbstractPropertySetCSSStyleDeclaration::getPropertyPriority(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) return String(); - return m_propertySet->propertyIsImportant(propertyID) ? "important" : ""; + return propertySet().propertyIsImportant(propertyID) ? "important" : ""; } -String PropertySetCSSStyleDeclaration::getPropertyShorthand(const String& propertyName) +String AbstractPropertySetCSSStyleDeclaration::getPropertyShorthand(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) return String(); - CSSPropertyID shorthandID = m_propertySet->getPropertyShorthand(propertyID); + CSSPropertyID shorthandID = propertySet().getPropertyShorthand(propertyID); if (!shorthandID) return String(); return getPropertyNameString(shorthandID); } -bool PropertySetCSSStyleDeclaration::isPropertyImplicit(const String& propertyName) +bool AbstractPropertySetCSSStyleDeclaration::isPropertyImplicit(const String& propertyName) { CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) return false; - return m_propertySet->isPropertyImplicit(propertyID); + return propertySet().isPropertyImplicit(propertyID); } -void PropertySetCSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState& exceptionState) +void AbstractPropertySetCSSStyleDeclaration::setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState& exceptionState) { - StyleAttributeMutationScope mutationScope(this); CSSPropertyID propertyID = cssPropertyID(propertyName); if (!propertyID) return; - bool important = priority.find("important", 0, false) != kNotFound; - - willMutate(); - - bool changed = m_propertySet->setProperty(propertyID, value, important, contextStyleSheet()); - - didMutate(changed ? PropertyChanged : NoChanges); + bool important = equalIgnoringCase(priority, "important"); + if (!important && !priority.isEmpty()) + return; - if (changed) { - // CSS DOM requires raising SyntaxError of parsing failed, but this is too dangerous for compatibility, - // see <http://bugs.webkit.org/show_bug.cgi?id=7296>. - mutationScope.enqueueMutationRecord(); - } + setPropertyInternal(propertyID, value, important, exceptionState); } -String PropertySetCSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionState& exceptionState) +String AbstractPropertySetCSSStyleDeclaration::removeProperty(const String& propertyName, ExceptionState& exceptionState) { StyleAttributeMutationScope mutationScope(this); CSSPropertyID propertyID = cssPropertyID(propertyName); @@ -240,7 +238,7 @@ String PropertySetCSSStyleDeclaration::removeProperty(const String& propertyName willMutate(); String result; - bool changed = m_propertySet->removeProperty(propertyID, &result); + bool changed = propertySet().removeProperty(propertyID, &result); didMutate(changed ? PropertyChanged : NoChanges); @@ -249,22 +247,22 @@ String PropertySetCSSStyleDeclaration::removeProperty(const String& propertyName return result; } -PassRefPtr<CSSValue> PropertySetCSSStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID) +PassRefPtrWillBeRawPtr<CSSValue> AbstractPropertySetCSSStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID) { - return m_propertySet->getPropertyCSSValue(propertyID); + return propertySet().getPropertyCSSValue(propertyID); } -String PropertySetCSSStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID) +String AbstractPropertySetCSSStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID) { - return m_propertySet->getPropertyValue(propertyID); + return propertySet().getPropertyValue(propertyID); } -void PropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID propertyID, const String& value, bool important, ExceptionState&) +void AbstractPropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID propertyID, const String& value, bool important, ExceptionState&) { StyleAttributeMutationScope mutationScope(this); willMutate(); - bool changed = m_propertySet->setProperty(propertyID, value, important, contextStyleSheet()); + bool changed = propertySet().setProperty(propertyID, value, important, contextStyleSheet()); didMutate(changed ? PropertyChanged : NoChanges); @@ -272,60 +270,7 @@ void PropertySetCSSStyleDeclaration::setPropertyInternal(CSSPropertyID propertyI mutationScope.enqueueMutationRecord(); } -unsigned PropertySetCSSStyleDeclaration::variableCount() const -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - return m_propertySet->variableCount(); -} - -String PropertySetCSSStyleDeclaration::variableValue(const AtomicString& name) const -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - return m_propertySet->variableValue(name); -} - -bool PropertySetCSSStyleDeclaration::setVariableValue(const AtomicString& name, const String& value, ExceptionState&) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - StyleAttributeMutationScope mutationScope(this); - willMutate(); - bool changed = m_propertySet->setVariableValue(name, value); - didMutate(changed ? PropertyChanged : NoChanges); - if (changed) - mutationScope.enqueueMutationRecord(); - return changed; -} - -bool PropertySetCSSStyleDeclaration::removeVariable(const AtomicString& name) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - StyleAttributeMutationScope mutationScope(this); - willMutate(); - bool changed = m_propertySet->removeVariable(name); - didMutate(changed ? PropertyChanged : NoChanges); - if (changed) - mutationScope.enqueueMutationRecord(); - return changed; -} - -bool PropertySetCSSStyleDeclaration::clearVariables(ExceptionState&) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - StyleAttributeMutationScope mutationScope(this); - willMutate(); - bool changed = m_propertySet->clearVariables(); - didMutate(changed ? PropertyChanged : NoChanges); - if (changed) - mutationScope.enqueueMutationRecord(); - return changed; -} - -PassRefPtr<CSSVariablesIterator> PropertySetCSSStyleDeclaration::variablesIterator() const -{ - return m_propertySet->variablesIterator(); -} - -CSSValue* PropertySetCSSStyleDeclaration::cloneAndCacheForCSSOM(CSSValue* internalValue) +CSSValue* AbstractPropertySetCSSStyleDeclaration::cloneAndCacheForCSSOM(CSSValue* internalValue) { if (!internalValue) return 0; @@ -333,43 +278,58 @@ CSSValue* PropertySetCSSStyleDeclaration::cloneAndCacheForCSSOM(CSSValue* intern // The map is here to maintain the object identity of the CSSValues over multiple invocations. // FIXME: It is likely that the identity is not important for web compatibility and this code should be removed. if (!m_cssomCSSValueClones) - m_cssomCSSValueClones = adoptPtr(new HashMap<CSSValue*, RefPtr<CSSValue> >); + m_cssomCSSValueClones = adoptPtrWillBeNoop(new WillBeHeapHashMap<RawPtrWillBeMember<CSSValue>, RefPtrWillBeMember<CSSValue> >); - RefPtr<CSSValue>& clonedValue = m_cssomCSSValueClones->add(internalValue, RefPtr<CSSValue>()).iterator->value; + RefPtrWillBeMember<CSSValue>& clonedValue = m_cssomCSSValueClones->add(internalValue, RefPtrWillBeMember<CSSValue>()).storedValue->value; if (!clonedValue) clonedValue = internalValue->cloneForCSSOM(); return clonedValue.get(); } -StyleSheetContents* PropertySetCSSStyleDeclaration::contextStyleSheet() const +StyleSheetContents* AbstractPropertySetCSSStyleDeclaration::contextStyleSheet() const { CSSStyleSheet* cssStyleSheet = parentStyleSheet(); return cssStyleSheet ? cssStyleSheet->contents() : 0; } -PassRefPtr<MutableStylePropertySet> PropertySetCSSStyleDeclaration::copyProperties() const +PassRefPtrWillBeRawPtr<MutableStylePropertySet> AbstractPropertySetCSSStyleDeclaration::copyProperties() const +{ + return propertySet().mutableCopy(); +} + +bool AbstractPropertySetCSSStyleDeclaration::cssPropertyMatches(CSSPropertyID propertyID, const CSSValue* propertyValue) const { - return m_propertySet->mutableCopy(); + return propertySet().propertyMatches(propertyID, propertyValue); } -bool PropertySetCSSStyleDeclaration::cssPropertyMatches(CSSPropertyID propertyID, const CSSValue* propertyValue) const +void AbstractPropertySetCSSStyleDeclaration::trace(Visitor* visitor) { - return m_propertySet->propertyMatches(propertyID, propertyValue); +#if ENABLE(OILPAN) + visitor->trace(m_cssomCSSValueClones); +#endif + CSSStyleDeclaration::trace(visitor); } -StyleRuleCSSStyleDeclaration::StyleRuleCSSStyleDeclaration(MutableStylePropertySet* propertySet, CSSRule* parentRule) - : PropertySetCSSStyleDeclaration(propertySet) +StyleRuleCSSStyleDeclaration::StyleRuleCSSStyleDeclaration(MutableStylePropertySet& propertySetArg, CSSRule* parentRule) + : PropertySetCSSStyleDeclaration(propertySetArg) +#if !ENABLE(OILPAN) , m_refCount(1) +#endif , m_parentRule(parentRule) { +#if !ENABLE(OILPAN) m_propertySet->ref(); +#endif } StyleRuleCSSStyleDeclaration::~StyleRuleCSSStyleDeclaration() { +#if !ENABLE(OILPAN) m_propertySet->deref(); +#endif } +#if !ENABLE(OILPAN) void StyleRuleCSSStyleDeclaration::ref() { ++m_refCount; @@ -381,6 +341,7 @@ void StyleRuleCSSStyleDeclaration::deref() if (!--m_refCount) delete this; } +#endif void StyleRuleCSSStyleDeclaration::willMutate() { @@ -403,12 +364,26 @@ CSSStyleSheet* StyleRuleCSSStyleDeclaration::parentStyleSheet() const return m_parentRule ? m_parentRule->parentStyleSheet() : 0; } -void StyleRuleCSSStyleDeclaration::reattach(MutableStylePropertySet* propertySet) +void StyleRuleCSSStyleDeclaration::reattach(MutableStylePropertySet& propertySet) { - ASSERT(propertySet); +#if !ENABLE(OILPAN) m_propertySet->deref(); - m_propertySet = propertySet; +#endif + m_propertySet = &propertySet; +#if !ENABLE(OILPAN) m_propertySet->ref(); +#endif +} + +void StyleRuleCSSStyleDeclaration::trace(Visitor* visitor) +{ + visitor->trace(m_parentRule); + PropertySetCSSStyleDeclaration::trace(visitor); +} + +MutableStylePropertySet& InlineCSSStyleDeclaration::propertySet() const +{ + return m_parentElement->ensureMutableInlineStyle(); } void InlineCSSStyleDeclaration::didMutate(MutationType type) @@ -421,6 +396,7 @@ void InlineCSSStyleDeclaration::didMutate(MutationType type) if (!m_parentElement) return; + m_parentElement->clearMutableInlineStyleIfEmpty(); m_parentElement->setNeedsStyleRecalc(LocalStyleChange); m_parentElement->invalidateStyleAttribute(); StyleAttributeMutationScope(this).didInvalidateStyleAttr(); @@ -428,7 +404,25 @@ void InlineCSSStyleDeclaration::didMutate(MutationType type) CSSStyleSheet* InlineCSSStyleDeclaration::parentStyleSheet() const { - return m_parentElement ? m_parentElement->document().elementSheet() : 0; + return m_parentElement ? &m_parentElement->document().elementSheet() : 0; +} + +#if !ENABLE(OILPAN) +void InlineCSSStyleDeclaration::ref() +{ + m_parentElement->ref(); +} + +void InlineCSSStyleDeclaration::deref() +{ + m_parentElement->deref(); +} +#endif + +void InlineCSSStyleDeclaration::trace(Visitor* visitor) +{ + visitor->trace(m_parentElement); + AbstractPropertySetCSSStyleDeclaration::trace(visitor); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h b/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h index 20b36855afe..e38bd4557f7 100644 --- a/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h +++ b/chromium/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.h @@ -40,43 +40,32 @@ class ExceptionState; class MutableStylePropertySet; class StyleSheetContents; -class PropertySetCSSStyleDeclaration : public CSSStyleDeclaration { +class AbstractPropertySetCSSStyleDeclaration : public CSSStyleDeclaration { public: - PropertySetCSSStyleDeclaration(MutableStylePropertySet* propertySet) : m_propertySet(propertySet) { } - virtual Element* parentElement() const { return 0; } - virtual void clearParentElement() { ASSERT_NOT_REACHED(); } StyleSheetContents* contextStyleSheet() const; - virtual void ref() OVERRIDE; - virtual void deref() OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; private: - virtual CSSRule* parentRule() const OVERRIDE { return 0; }; - virtual unsigned length() const OVERRIDE; - virtual String item(unsigned index) const OVERRIDE; - virtual PassRefPtr<CSSValue> getPropertyCSSValue(const String& propertyName) OVERRIDE; - virtual String getPropertyValue(const String& propertyName) OVERRIDE; - virtual String getPropertyPriority(const String& propertyName) OVERRIDE; - virtual String getPropertyShorthand(const String& propertyName) OVERRIDE; - virtual bool isPropertyImplicit(const String& propertyName) OVERRIDE; - virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState&) OVERRIDE; - virtual String removeProperty(const String& propertyName, ExceptionState&) OVERRIDE; - virtual String cssText() const OVERRIDE; - virtual void setCSSText(const String&, ExceptionState&) OVERRIDE; - virtual PassRefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) OVERRIDE; - virtual String getPropertyValueInternal(CSSPropertyID) OVERRIDE; - virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) OVERRIDE; - - virtual unsigned variableCount() const OVERRIDE; - virtual String variableValue(const AtomicString& name) const OVERRIDE; - virtual bool setVariableValue(const AtomicString& name, const String& value, ExceptionState&) OVERRIDE; - virtual bool removeVariable(const AtomicString& name) OVERRIDE; - virtual bool clearVariables(ExceptionState&) OVERRIDE; - virtual PassRefPtr<CSSVariablesIterator> variablesIterator() const OVERRIDE; - - virtual bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const OVERRIDE; - virtual PassRefPtr<MutableStylePropertySet> copyProperties() const OVERRIDE; + virtual CSSRule* parentRule() const OVERRIDE { return 0; } + virtual unsigned length() const OVERRIDE FINAL; + virtual String item(unsigned index) const OVERRIDE FINAL; + virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(const String& propertyName) OVERRIDE FINAL; + virtual String getPropertyValue(const String& propertyName) OVERRIDE FINAL; + virtual String getPropertyPriority(const String& propertyName) OVERRIDE FINAL; + virtual String getPropertyShorthand(const String& propertyName) OVERRIDE FINAL; + virtual bool isPropertyImplicit(const String& propertyName) OVERRIDE FINAL; + virtual void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionState&) OVERRIDE FINAL; + virtual String removeProperty(const String& propertyName, ExceptionState&) OVERRIDE FINAL; + virtual String cssText() const OVERRIDE FINAL; + virtual void setCSSText(const String&, ExceptionState&) OVERRIDE FINAL; + virtual PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) OVERRIDE FINAL; + virtual String getPropertyValueInternal(CSSPropertyID) OVERRIDE FINAL; + virtual void setPropertyInternal(CSSPropertyID, const String& value, bool important, ExceptionState&) OVERRIDE FINAL; + + virtual bool cssPropertyMatches(CSSPropertyID, const CSSValue*) const OVERRIDE FINAL; + virtual PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyProperties() const OVERRIDE FINAL; CSSValue* cloneAndCacheForCSSOM(CSSValue*); @@ -84,28 +73,49 @@ protected: enum MutationType { NoChanges, PropertyChanged }; virtual void willMutate() { } virtual void didMutate(MutationType) { } + virtual MutableStylePropertySet& propertySet() const = 0; - MutableStylePropertySet* m_propertySet; - OwnPtr<HashMap<CSSValue*, RefPtr<CSSValue> > > m_cssomCSSValueClones; + OwnPtrWillBeMember<WillBeHeapHashMap<RawPtrWillBeMember<CSSValue>, RefPtrWillBeMember<CSSValue> > > m_cssomCSSValueClones; }; -class StyleRuleCSSStyleDeclaration : public PropertySetCSSStyleDeclaration +class PropertySetCSSStyleDeclaration : public AbstractPropertySetCSSStyleDeclaration { +public: + PropertySetCSSStyleDeclaration(MutableStylePropertySet& propertySet) : m_propertySet(&propertySet) { } + +#if !ENABLE(OILPAN) + virtual void ref() OVERRIDE; + virtual void deref() OVERRIDE; +#endif + + virtual void trace(Visitor*) OVERRIDE; + +protected: + virtual MutableStylePropertySet& propertySet() const OVERRIDE FINAL { ASSERT(m_propertySet); return *m_propertySet; } + + RawPtrWillBeMember<MutableStylePropertySet> m_propertySet; // Cannot be null +}; + +class StyleRuleCSSStyleDeclaration FINAL : public PropertySetCSSStyleDeclaration { public: - static PassRefPtr<StyleRuleCSSStyleDeclaration> create(MutableStylePropertySet* propertySet, CSSRule* parentRule) + static PassRefPtrWillBeRawPtr<StyleRuleCSSStyleDeclaration> create(MutableStylePropertySet& propertySet, CSSRule* parentRule) { - return adoptRef(new StyleRuleCSSStyleDeclaration(propertySet, parentRule)); + return adoptRefWillBeNoop(new StyleRuleCSSStyleDeclaration(propertySet, parentRule)); } - void clearParentRule() { m_parentRule = 0; } +#if !ENABLE(OILPAN) + void clearParentRule() { m_parentRule = nullptr; } virtual void ref() OVERRIDE; virtual void deref() OVERRIDE; +#endif + + void reattach(MutableStylePropertySet&); - void reattach(MutableStylePropertySet*); + virtual void trace(Visitor*) OVERRIDE; private: - StyleRuleCSSStyleDeclaration(MutableStylePropertySet*, CSSRule*); + StyleRuleCSSStyleDeclaration(MutableStylePropertySet&, CSSRule*); virtual ~StyleRuleCSSStyleDeclaration(); virtual CSSStyleSheet* parentStyleSheet() const OVERRIDE; @@ -115,27 +125,34 @@ private: virtual void willMutate() OVERRIDE; virtual void didMutate(MutationType) OVERRIDE; +#if !ENABLE(OILPAN) unsigned m_refCount; - CSSRule* m_parentRule; +#endif + RawPtrWillBeMember<CSSRule> m_parentRule; }; -class InlineCSSStyleDeclaration : public PropertySetCSSStyleDeclaration +class InlineCSSStyleDeclaration FINAL : public AbstractPropertySetCSSStyleDeclaration { public: - InlineCSSStyleDeclaration(MutableStylePropertySet* propertySet, Element* parentElement) - : PropertySetCSSStyleDeclaration(propertySet) - , m_parentElement(parentElement) + explicit InlineCSSStyleDeclaration(Element* parentElement) + : m_parentElement(parentElement) { } + virtual void trace(Visitor*) OVERRIDE; + private: + virtual MutableStylePropertySet& propertySet() const OVERRIDE; +#if !ENABLE(OILPAN) + virtual void ref() OVERRIDE; + virtual void deref() OVERRIDE; +#endif virtual CSSStyleSheet* parentStyleSheet() const OVERRIDE; virtual Element* parentElement() const OVERRIDE { return m_parentElement; } - virtual void clearParentElement() OVERRIDE { m_parentElement = 0; } virtual void didMutate(MutationType) OVERRIDE; - Element* m_parentElement; + RawPtrWillBeMember<Element> m_parentElement; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/RGBColor.cpp b/chromium/third_party/WebKit/Source/core/css/RGBColor.cpp index 6b131d04654..9994d231786 100644 --- a/chromium/third_party/WebKit/Source/core/css/RGBColor.cpp +++ b/chromium/third_party/WebKit/Source/core/css/RGBColor.cpp @@ -30,39 +30,39 @@ namespace WebCore { -PassRefPtr<RGBColor> RGBColor::create(unsigned rgbColor) +PassRefPtrWillBeRawPtr<RGBColor> RGBColor::create(unsigned rgbColor) { - return adoptRef(new RGBColor(rgbColor)); + return adoptRefWillBeNoop(new RGBColor(rgbColor)); } -PassRefPtr<CSSPrimitiveValue> RGBColor::red() +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> RGBColor::red() { unsigned value = (m_rgbColor >> 16) & 0xFF; - RefPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); result->setCSSOMSafe(); return result.release(); } -PassRefPtr<CSSPrimitiveValue> RGBColor::green() +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> RGBColor::green() { unsigned value = (m_rgbColor >> 8) & 0xFF; - RefPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); result->setCSSOMSafe(); return result.release(); } -PassRefPtr<CSSPrimitiveValue> RGBColor::blue() +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> RGBColor::blue() { unsigned value = m_rgbColor & 0xFF; - RefPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); result->setCSSOMSafe(); return result.release(); } -PassRefPtr<CSSPrimitiveValue> RGBColor::alpha() +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> RGBColor::alpha() { float value = static_cast<float>((m_rgbColor >> 24) & 0xFF) / 0xFF; - RefPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = CSSPrimitiveValue::create(value, CSSPrimitiveValue::CSS_NUMBER); result->setCSSOMSafe(); return result.release(); } diff --git a/chromium/third_party/WebKit/Source/core/css/RGBColor.h b/chromium/third_party/WebKit/Source/core/css/RGBColor.h index 5cd4697d4fb..51a98f8845a 100644 --- a/chromium/third_party/WebKit/Source/core/css/RGBColor.h +++ b/chromium/third_party/WebKit/Source/core/css/RGBColor.h @@ -28,23 +28,26 @@ #define RGBColor_h #include "platform/graphics/Color.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" namespace WebCore { class CSSPrimitiveValue; - class RGBColor : public RefCounted<RGBColor> { + class RGBColor : public RefCountedWillBeGarbageCollected<RGBColor> { public: - static PassRefPtr<RGBColor> create(unsigned rgbColor); + static PassRefPtrWillBeRawPtr<RGBColor> create(unsigned rgbColor); - PassRefPtr<CSSPrimitiveValue> red(); - PassRefPtr<CSSPrimitiveValue> green(); - PassRefPtr<CSSPrimitiveValue> blue(); - PassRefPtr<CSSPrimitiveValue> alpha(); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> red(); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> green(); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> blue(); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> alpha(); Color color() const { return Color(m_rgbColor); } + void trace(Visitor*) { } + private: RGBColor(unsigned rgbColor) : m_rgbColor(rgbColor) diff --git a/chromium/third_party/WebKit/Source/core/css/RGBColor.idl b/chromium/third_party/WebKit/Source/core/css/RGBColor.idl index 09fa76ef2ef..398fe1b5085 100644 --- a/chromium/third_party/WebKit/Source/core/css/RGBColor.idl +++ b/chromium/third_party/WebKit/Source/core/css/RGBColor.idl @@ -19,6 +19,7 @@ */ [ + WillBeGarbageCollected ] interface RGBColor { readonly attribute CSSPrimitiveValue red; readonly attribute CSSPrimitiveValue green; diff --git a/chromium/third_party/WebKit/Source/core/css/Rect.cpp b/chromium/third_party/WebKit/Source/core/css/Rect.cpp new file mode 100644 index 00000000000..13afc70a656 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/Rect.cpp @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/Rect.h" + +namespace WebCore { + +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RectBase) + +void RectBase::trace(Visitor* visitor) +{ + visitor->trace(m_top); + visitor->trace(m_right); + visitor->trace(m_bottom); + visitor->trace(m_left); +} + +} diff --git a/chromium/third_party/WebKit/Source/core/css/Rect.h b/chromium/third_party/WebKit/Source/core/css/Rect.h index 21978cd15fa..2f9e08e4a6d 100644 --- a/chromium/third_party/WebKit/Source/core/css/Rect.h +++ b/chromium/third_party/WebKit/Source/core/css/Rect.h @@ -27,17 +27,18 @@ namespace WebCore { -class RectBase { +class RectBase : public RefCountedWillBeGarbageCollected<RectBase> { + DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(RectBase); public: CSSPrimitiveValue* top() const { return m_top.get(); } CSSPrimitiveValue* right() const { return m_right.get(); } CSSPrimitiveValue* bottom() const { return m_bottom.get(); } CSSPrimitiveValue* left() const { return m_left.get(); } - void setTop(PassRefPtr<CSSPrimitiveValue> top) { m_top = top; } - void setRight(PassRefPtr<CSSPrimitiveValue> right) { m_right = right; } - void setBottom(PassRefPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; } - void setLeft(PassRefPtr<CSSPrimitiveValue> left) { m_left = left; } + void setTop(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> top) { m_top = top; } + void setRight(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> right) { m_right = right; } + void setBottom(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> bottom) { m_bottom = bottom; } + void setLeft(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> left) { m_left = left; } bool equals(const RectBase& other) const { @@ -47,83 +48,63 @@ public: && compareCSSValuePtr(m_bottom, other.m_bottom); } - bool hasVariableReference() const - { - return m_top->hasVariableReference() - || m_right->hasVariableReference() - || m_bottom->hasVariableReference() - || m_left->hasVariableReference(); - } + void trace(Visitor*); protected: RectBase() { } RectBase(const RectBase& cloneFrom) - : m_top(cloneFrom.m_top ? cloneFrom.m_top->cloneForCSSOM() : 0) - , m_right(cloneFrom.m_right ? cloneFrom.m_right->cloneForCSSOM() : 0) - , m_bottom(cloneFrom.m_bottom ? cloneFrom.m_bottom->cloneForCSSOM() : 0) - , m_left(cloneFrom.m_left ? cloneFrom.m_left->cloneForCSSOM() : 0) + : m_top(cloneFrom.m_top ? cloneFrom.m_top->cloneForCSSOM() : nullptr) + , m_right(cloneFrom.m_right ? cloneFrom.m_right->cloneForCSSOM() : nullptr) + , m_bottom(cloneFrom.m_bottom ? cloneFrom.m_bottom->cloneForCSSOM() : nullptr) + , m_left(cloneFrom.m_left ? cloneFrom.m_left->cloneForCSSOM() : nullptr) { } - ~RectBase() { } - private: - RefPtr<CSSPrimitiveValue> m_top; - RefPtr<CSSPrimitiveValue> m_right; - RefPtr<CSSPrimitiveValue> m_bottom; - RefPtr<CSSPrimitiveValue> m_left; + RefPtrWillBeMember<CSSPrimitiveValue> m_top; + RefPtrWillBeMember<CSSPrimitiveValue> m_right; + RefPtrWillBeMember<CSSPrimitiveValue> m_bottom; + RefPtrWillBeMember<CSSPrimitiveValue> m_left; }; -class Rect : public RectBase, public RefCounted<Rect> { +class Rect : public RectBase { public: - static PassRefPtr<Rect> create() { return adoptRef(new Rect); } + static PassRefPtrWillBeRawPtr<Rect> create() { return adoptRefWillBeNoop(new Rect); } - PassRefPtr<Rect> cloneForCSSOM() const { return adoptRef(new Rect(*this)); } + PassRefPtrWillBeRawPtr<Rect> cloneForCSSOM() const { return adoptRefWillBeNoop(new Rect(*this)); } String cssText() const { return generateCSSString(top()->cssText(), right()->cssText(), bottom()->cssText(), left()->cssText()); } - String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const - { - return generateCSSString(top()->customSerializeResolvingVariables(variables), - right()->customSerializeResolvingVariables(variables), - bottom()->customSerializeResolvingVariables(variables), - left()->customSerializeResolvingVariables(variables)); - } - private: Rect() { } - Rect(const Rect& cloneFrom) : RectBase(cloneFrom), RefCounted<Rect>() { } + Rect(const Rect& cloneFrom) : RectBase(cloneFrom) { } static String generateCSSString(const String& top, const String& right, const String& bottom, const String& left) { return "rect(" + top + ' ' + right + ' ' + bottom + ' ' + left + ')'; } + + // NOTE: If adding fields to this class please make the RectBase trace + // method virtual and add a trace method in this subclass tracing the new + // fields. }; -class Quad : public RectBase, public RefCounted<Quad> { +class Quad : public RectBase { public: - static PassRefPtr<Quad> create() { return adoptRef(new Quad); } + static PassRefPtrWillBeRawPtr<Quad> create() { return adoptRefWillBeNoop(new Quad); } - PassRefPtr<Quad> cloneForCSSOM() const { return adoptRef(new Quad(*this)); } + PassRefPtrWillBeRawPtr<Quad> cloneForCSSOM() const { return adoptRefWillBeNoop(new Quad(*this)); } String cssText() const { return generateCSSString(top()->cssText(), right()->cssText(), bottom()->cssText(), left()->cssText()); } - String serializeResolvingVariables(const HashMap<AtomicString, String>& variables) const - { - return generateCSSString(top()->customSerializeResolvingVariables(variables), - right()->customSerializeResolvingVariables(variables), - bottom()->customSerializeResolvingVariables(variables), - left()->customSerializeResolvingVariables(variables)); - } - private: Quad() { } - Quad(const Quad& cloneFrom) : RectBase(cloneFrom), RefCounted<Quad>() { } + Quad(const Quad& cloneFrom) : RectBase(cloneFrom) { } static String generateCSSString(const String& top, const String& right, const String& bottom, const String& left) { StringBuilder result; @@ -144,6 +125,10 @@ private: } return result.toString(); } + + // NOTE: If adding fields to this class please make the RectBase trace + // method virtual and add a trace method in this subclass tracing the new + // fields. }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/Rect.idl b/chromium/third_party/WebKit/Source/core/css/Rect.idl index 3eac82fd539..87336d5bc06 100644 --- a/chromium/third_party/WebKit/Source/core/css/Rect.idl +++ b/chromium/third_party/WebKit/Source/core/css/Rect.idl @@ -18,6 +18,7 @@ */ [ + WillBeGarbageCollected ] interface Rect { readonly attribute CSSPrimitiveValue top; readonly attribute CSSPrimitiveValue right; diff --git a/chromium/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/chromium/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp new file mode 100644 index 00000000000..5316a6ef55a --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp @@ -0,0 +1,193 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/RemoteFontFaceSource.h" + +#include "core/css/CSSCustomFontData.h" +#include "core/css/CSSFontFace.h" +#include "core/css/FontLoader.h" +#include "platform/fonts/FontCache.h" +#include "platform/fonts/FontDescription.h" +#include "platform/fonts/SimpleFontData.h" +#include "public/platform/Platform.h" +#include "wtf/CurrentTime.h" + +namespace WebCore { + +RemoteFontFaceSource::RemoteFontFaceSource(FontResource* font, PassRefPtrWillBeRawPtr<FontLoader> fontLoader) + : m_font(font) + , m_fontLoader(fontLoader) +{ + m_font->addClient(this); +} + +RemoteFontFaceSource::~RemoteFontFaceSource() +{ + m_font->removeClient(this); + pruneTable(); +} + +void RemoteFontFaceSource::pruneTable() +{ + if (m_fontDataTable.isEmpty()) + return; + + for (FontDataTable::iterator it = m_fontDataTable.begin(); it != m_fontDataTable.end(); ++it) { + SimpleFontData* fontData = it->value.get(); + if (fontData && fontData->customFontData()) + fontData->customFontData()->clearFontFaceSource(); + } + m_fontDataTable.clear(); +} + +bool RemoteFontFaceSource::isLoading() const +{ + return !m_font->stillNeedsLoad() && !m_font->isLoaded(); +} + +bool RemoteFontFaceSource::isLoaded() const +{ + return m_font->isLoaded(); +} + +bool RemoteFontFaceSource::isValid() const +{ + return !m_font->errorOccurred(); +} + +void RemoteFontFaceSource::didStartFontLoad(FontResource*) +{ + // We may send duplicated reports when multiple CSSFontFaceSource are + // registered at this FontResource. Associating the same URL to different + // font-family causes the case, but we treat them as indivisual resources. + m_histograms.loadStarted(); +} + +void RemoteFontFaceSource::fontLoaded(FontResource*) +{ + m_histograms.recordRemoteFont(m_font.get()); + + pruneTable(); + if (m_face) { + m_fontLoader->fontFaceInvalidated(); + m_face->fontLoaded(this); + } +} + +void RemoteFontFaceSource::fontLoadWaitLimitExceeded(FontResource*) +{ + pruneTable(); + if (m_face) { + m_fontLoader->fontFaceInvalidated(); + m_face->fontLoadWaitLimitExceeded(this); + } + + m_histograms.recordFallbackTime(m_font.get()); +} + +PassRefPtr<SimpleFontData> RemoteFontFaceSource::createFontData(const FontDescription& fontDescription) +{ + if (!isLoaded()) + return createLoadingFallbackFontData(fontDescription); + + // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. + if (!m_font->ensureCustomFontData()) + return nullptr; + + m_histograms.recordFallbackTime(m_font.get()); + + return SimpleFontData::create( + m_font->platformDataFromCustomData(fontDescription.effectiveFontSize(), + fontDescription.isSyntheticBold(), fontDescription.isSyntheticItalic(), + fontDescription.orientation(), fontDescription.widthVariant()), CustomFontData::create()); +} + +PassRefPtr<SimpleFontData> RemoteFontFaceSource::createLoadingFallbackFontData(const FontDescription& fontDescription) +{ + // This temporary font is not retained and should not be returned. + FontCachePurgePreventer fontCachePurgePreventer; + SimpleFontData* temporaryFont = FontCache::fontCache()->getNonRetainedLastResortFallbackFont(fontDescription); + if (!temporaryFont) { + ASSERT_NOT_REACHED(); + return nullptr; + } + RefPtr<CSSCustomFontData> cssFontData = CSSCustomFontData::create(this, m_font->exceedsFontLoadWaitLimit() ? CSSCustomFontData::VisibleFallback : CSSCustomFontData::InvisibleFallback); + return SimpleFontData::create(temporaryFont->platformData(), cssFontData); +} + +void RemoteFontFaceSource::beginLoadIfNeeded() +{ + if (m_font->stillNeedsLoad()) + m_fontLoader->addFontToBeginLoading(m_font.get()); + + if (m_face) + m_face->didBeginLoad(); +} + +bool RemoteFontFaceSource::ensureFontData() +{ + return m_font->ensureCustomFontData(); +} + +void RemoteFontFaceSource::trace(Visitor* visitor) +{ + visitor->trace(m_fontLoader); + CSSFontFaceSource::trace(visitor); +} + +void RemoteFontFaceSource::FontLoadHistograms::loadStarted() +{ + if (!m_loadStartTime) + m_loadStartTime = currentTimeMS(); +} + +void RemoteFontFaceSource::FontLoadHistograms::fallbackFontPainted() +{ + if (!m_fallbackPaintTime) + m_fallbackPaintTime = currentTimeMS(); +} + +void RemoteFontFaceSource::FontLoadHistograms::recordFallbackTime(const FontResource* font) +{ + if (m_fallbackPaintTime <= 0) + return; + int duration = static_cast<int>(currentTimeMS() - m_fallbackPaintTime); + blink::Platform::current()->histogramCustomCounts("WebFont.BlankTextShownTime", duration, 0, 10000, 50); + m_fallbackPaintTime = -1; +} + +void RemoteFontFaceSource::FontLoadHistograms::recordRemoteFont(const FontResource* font) +{ + if (m_loadStartTime > 0 && font && !font->isLoading()) { + int duration = static_cast<int>(currentTimeMS() - m_loadStartTime); + blink::Platform::current()->histogramCustomCounts(histogramName(font), duration, 0, 10000, 50); + m_loadStartTime = -1; + + enum { Miss, Hit, DataUrl, CacheHitEnumMax }; + int histogramValue = font->url().protocolIsData() ? DataUrl + : font->response().wasCached() ? Hit + : Miss; + blink::Platform::current()->histogramEnumeration("WebFont.CacheHit", histogramValue, CacheHitEnumMax); + } +} + +const char* RemoteFontFaceSource::FontLoadHistograms::histogramName(const FontResource* font) +{ + if (font->errorOccurred()) + return "WebFont.DownloadTime.LoadError"; + + unsigned size = font->encodedSize(); + if (size < 10 * 1024) + return "WebFont.DownloadTime.0.Under10KB"; + if (size < 50 * 1024) + return "WebFont.DownloadTime.1.10KBTo50KB"; + if (size < 100 * 1024) + return "WebFont.DownloadTime.2.50KBTo100KB"; + if (size < 1024 * 1024) + return "WebFont.DownloadTime.3.100KBTo1MB"; + return "WebFont.DownloadTime.4.Over1MB"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h b/chromium/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h new file mode 100644 index 00000000000..f7d84ee5a36 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/RemoteFontFaceSource.h @@ -0,0 +1,70 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RemoteFontFaceSource_h +#define RemoteFontFaceSource_h + +#include "core/css/CSSFontFaceSource.h" +#include "core/fetch/FontResource.h" +#include "core/fetch/ResourcePtr.h" + +namespace WebCore { + +class FontLoader; + +class RemoteFontFaceSource : public CSSFontFaceSource, public FontResourceClient { +public: + explicit RemoteFontFaceSource(FontResource*, PassRefPtrWillBeRawPtr<FontLoader>); + virtual ~RemoteFontFaceSource(); + + virtual FontResource* resource() OVERRIDE { return m_font.get(); } + virtual bool isLoading() const OVERRIDE; + virtual bool isLoaded() const OVERRIDE; + virtual bool isValid() const OVERRIDE; + + void beginLoadIfNeeded() OVERRIDE; + virtual bool ensureFontData(); + +#if ENABLE(SVG_FONTS) + virtual bool isSVGFontFaceSource() const { return false; } +#endif + + virtual void didStartFontLoad(FontResource*) OVERRIDE; + virtual void fontLoaded(FontResource*) OVERRIDE; + virtual void fontLoadWaitLimitExceeded(FontResource*) OVERRIDE; + + // For UMA reporting + virtual bool hadBlankText() OVERRIDE { return m_histograms.hadBlankText(); } + void paintRequested() { m_histograms.fallbackFontPainted(); } + + virtual void trace(Visitor*) OVERRIDE; + +protected: + virtual PassRefPtr<SimpleFontData> createFontData(const FontDescription&) OVERRIDE; + PassRefPtr<SimpleFontData> createLoadingFallbackFontData(const FontDescription&); + void pruneTable(); + +private: + class FontLoadHistograms { + public: + FontLoadHistograms() : m_loadStartTime(0), m_fallbackPaintTime(0) { } + void loadStarted(); + void fallbackFontPainted(); + void recordRemoteFont(const FontResource*); + void recordFallbackTime(const FontResource*); + bool hadBlankText() { return m_fallbackPaintTime; } + private: + const char* histogramName(const FontResource*); + double m_loadStartTime; + double m_fallbackPaintTime; + }; + + ResourcePtr<FontResource> m_font; + RefPtrWillBeMember<FontLoader> m_fontLoader; + FontLoadHistograms m_histograms; +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/css/RuleFeature.cpp b/chromium/third_party/WebKit/Source/core/css/RuleFeature.cpp index 7c8f160ae43..26aea450ff0 100644 --- a/chromium/third_party/WebKit/Source/core/css/RuleFeature.cpp +++ b/chromium/third_party/WebKit/Source/core/css/RuleFeature.cpp @@ -29,70 +29,501 @@ #include "config.h" #include "core/css/RuleFeature.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/css/CSSSelector.h" #include "core/css/CSSSelectorList.h" +#include "core/css/RuleSet.h" +#include "core/css/StyleRule.h" +#include "core/css/invalidation/DescendantInvalidationSet.h" +#include "core/dom/Element.h" +#include "core/dom/Node.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "wtf/BitVector.h" namespace WebCore { -void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector* selector) -{ - if (selector->m_match == CSSSelector::Id) - idsInRules.add(selector->value()); - else if (selector->m_match == CSSSelector::Class) - classesInRules.add(selector->value()); - else if (selector->isAttributeSelector()) - attrsInRules.add(selector->attribute().localName()); - switch (selector->pseudoType()) { - case CSSSelector::PseudoFirstLine: - m_usesFirstLineRules = true; - break; - break; - case CSSSelector::PseudoHost: - collectFeaturesFromSelectorList(selector->selectorList()); - break; +static bool isSkippableComponentForInvalidation(const CSSSelector& selector) +{ + if (selector.match() == CSSSelector::Tag + || selector.match() == CSSSelector::Id + || selector.isAttributeSelector()) + return true; + if (selector.match() == CSSSelector::PseudoElement) { + switch (selector.pseudoType()) { + case CSSSelector::PseudoBefore: + case CSSSelector::PseudoAfter: + case CSSSelector::PseudoBackdrop: + case CSSSelector::PseudoShadow: + return true; + default: + return selector.isCustomPseudoElement(); + } + } + if (selector.match() != CSSSelector::PseudoClass) + return false; + switch (selector.pseudoType()) { + case CSSSelector::PseudoEmpty: + case CSSSelector::PseudoFirstChild: + case CSSSelector::PseudoFirstOfType: + case CSSSelector::PseudoLastChild: + case CSSSelector::PseudoLastOfType: + case CSSSelector::PseudoOnlyChild: + case CSSSelector::PseudoOnlyOfType: + case CSSSelector::PseudoNthChild: + case CSSSelector::PseudoNthOfType: + case CSSSelector::PseudoNthLastChild: + case CSSSelector::PseudoNthLastOfType: + case CSSSelector::PseudoLink: + case CSSSelector::PseudoVisited: + case CSSSelector::PseudoAnyLink: + case CSSSelector::PseudoHover: + case CSSSelector::PseudoDrag: + case CSSSelector::PseudoFocus: + case CSSSelector::PseudoActive: + case CSSSelector::PseudoChecked: + case CSSSelector::PseudoEnabled: + case CSSSelector::PseudoDefault: + case CSSSelector::PseudoDisabled: + case CSSSelector::PseudoOptional: + case CSSSelector::PseudoRequired: + case CSSSelector::PseudoReadOnly: + case CSSSelector::PseudoReadWrite: + case CSSSelector::PseudoValid: + case CSSSelector::PseudoInvalid: + case CSSSelector::PseudoIndeterminate: + case CSSSelector::PseudoTarget: + case CSSSelector::PseudoLang: + case CSSSelector::PseudoRoot: + case CSSSelector::PseudoScope: + case CSSSelector::PseudoInRange: + case CSSSelector::PseudoOutOfRange: + case CSSSelector::PseudoUnresolved: + return true; default: - break; + return false; + } +} + +RuleFeature::RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin) + : rule(rule) + , selectorIndex(selectorIndex) + , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) +{ +} + +void RuleFeature::trace(Visitor* visitor) +{ + visitor->trace(rule); +} + +// This method is somewhat conservative in what it accepts. +RuleFeatureSet::InvalidationSetMode RuleFeatureSet::invalidationSetModeForSelector(const CSSSelector& selector) +{ + bool foundDescendantRelation = false; + bool foundIdent = false; + for (const CSSSelector* component = &selector; component; component = component->tagHistory()) { + + if (component->match() == CSSSelector::Class || component->match() == CSSSelector::Id + || (component->match() == CSSSelector::Tag && component->tagQName().localName() != starAtom) + || component->isAttributeSelector() || component->isCustomPseudoElement()) { + if (!foundDescendantRelation) + foundIdent = true; + } else if (component->pseudoType() == CSSSelector::PseudoHost || component->pseudoType() == CSSSelector::PseudoAny) { + if (const CSSSelectorList* selectorList = component->selectorList()) { + for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) { + InvalidationSetMode hostMode = invalidationSetModeForSelector(*selector); + if (hostMode == UseSubtreeStyleChange) + return foundDescendantRelation ? UseLocalStyleChange : UseSubtreeStyleChange; + if (!foundDescendantRelation && hostMode == AddFeatures) + foundIdent = true; + } + } + } else if (!isSkippableComponentForInvalidation(*component)) { + return foundDescendantRelation ? UseLocalStyleChange : UseSubtreeStyleChange; + } + switch (component->relation()) { + case CSSSelector::Descendant: + case CSSSelector::Child: + case CSSSelector::ShadowPseudo: + case CSSSelector::ShadowDeep: + foundDescendantRelation = true; + // Fall through! + case CSSSelector::SubSelector: + case CSSSelector::DirectAdjacent: + case CSSSelector::IndirectAdjacent: + continue; + default: + // All combinators should be handled above. + ASSERT_NOT_REACHED(); + return UseLocalStyleChange; + } + } + return foundIdent ? AddFeatures : UseLocalStyleChange; +} + +void RuleFeatureSet::extractInvalidationSetFeature(const CSSSelector& selector, InvalidationSetFeatures& features) +{ + if (selector.match() == CSSSelector::Tag) + features.tagName = selector.tagQName().localName(); + else if (selector.match() == CSSSelector::Id) + features.id = selector.value(); + else if (selector.match() == CSSSelector::Class) + features.classes.append(selector.value()); + else if (selector.isAttributeSelector()) + features.attributes.append(selector.attribute().localName()); + else if (selector.isCustomPseudoElement()) + features.customPseudoElement = true; +} + +RuleFeatureSet::RuleFeatureSet() + : m_targetedStyleRecalcEnabled(RuntimeEnabledFeatures::targetedStyleRecalcEnabled()) +{ +} + +RuleFeatureSet::~RuleFeatureSet() +{ +} + +DescendantInvalidationSet* RuleFeatureSet::invalidationSetForSelector(const CSSSelector& selector) +{ + if (selector.match() == CSSSelector::Class) + return &ensureClassInvalidationSet(selector.value()); + if (selector.isAttributeSelector()) + return &ensureAttributeInvalidationSet(selector.attribute().localName()); + if (selector.match() == CSSSelector::Id) + return &ensureIdInvalidationSet(selector.value()); + if (selector.match() == CSSSelector::PseudoClass) { + CSSSelector::PseudoType pseudo = selector.pseudoType(); + if (pseudo == CSSSelector::PseudoHover || pseudo == CSSSelector::PseudoActive || pseudo == CSSSelector::PseudoFocus) + return &ensurePseudoInvalidationSet(pseudo); + } + return 0; +} + +RuleFeatureSet::InvalidationSetMode RuleFeatureSet::updateInvalidationSets(const CSSSelector& selector) +{ + InvalidationSetMode mode = invalidationSetModeForSelector(selector); + if (mode != AddFeatures) + return mode; + + InvalidationSetFeatures features; + if (const CSSSelector* current = extractInvalidationSetFeatures(selector, features)) + addFeaturesToInvalidationSets(*current, features); + return AddFeatures; +} + +const CSSSelector* RuleFeatureSet::extractInvalidationSetFeatures(const CSSSelector& selector, InvalidationSetFeatures& features) +{ + for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { + extractInvalidationSetFeature(*current, features); + // Initialize the entry in the invalidation set map, if supported. + invalidationSetForSelector(*current); + if (current->pseudoType() == CSSSelector::PseudoHost || current->pseudoType() == CSSSelector::PseudoAny) { + if (const CSSSelectorList* selectorList = current->selectorList()) { + for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) + extractInvalidationSetFeatures(*selector, features); + } + } + + switch (current->relation()) { + case CSSSelector::SubSelector: + break; + case CSSSelector::ShadowPseudo: + case CSSSelector::ShadowDeep: + features.treeBoundaryCrossing = true; + return current->tagHistory(); + case CSSSelector::DirectAdjacent: + case CSSSelector::IndirectAdjacent: + features.wholeSubtree = true; + return current->tagHistory(); + case CSSSelector::Descendant: + case CSSSelector::Child: + return current->tagHistory(); + } + } + return 0; +} + +void RuleFeatureSet::addFeaturesToInvalidationSets(const CSSSelector& selector, InvalidationSetFeatures& features) +{ + for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { + if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelector(*current)) { + if (features.treeBoundaryCrossing) + invalidationSet->setTreeBoundaryCrossing(); + if (features.wholeSubtree) { + invalidationSet->setWholeSubtreeInvalid(); + } else { + if (!features.id.isEmpty()) + invalidationSet->addId(features.id); + if (!features.tagName.isEmpty()) + invalidationSet->addTagName(features.tagName); + for (Vector<AtomicString>::const_iterator it = features.classes.begin(); it != features.classes.end(); ++it) + invalidationSet->addClass(*it); + for (Vector<AtomicString>::const_iterator it = features.attributes.begin(); it != features.attributes.end(); ++it) + invalidationSet->addAttribute(*it); + if (features.customPseudoElement) + invalidationSet->setCustomPseudoInvalid(); + } + } else if (current->pseudoType() == CSSSelector::PseudoHost || current->pseudoType() == CSSSelector::PseudoAny) { + if (current->pseudoType() == CSSSelector::PseudoHost) + features.treeBoundaryCrossing = true; + if (const CSSSelectorList* selectorList = current->selectorList()) { + for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) + addFeaturesToInvalidationSets(*selector, features); + } + } + switch (current->relation()) { + case CSSSelector::SubSelector: + break; + case CSSSelector::ShadowPseudo: + case CSSSelector::ShadowDeep: + features.treeBoundaryCrossing = true; + features.wholeSubtree = false; + break; + case CSSSelector::Descendant: + case CSSSelector::Child: + features.wholeSubtree = false; + break; + case CSSSelector::DirectAdjacent: + case CSSSelector::IndirectAdjacent: + features.wholeSubtree = true; + break; + } + } +} + +void RuleFeatureSet::addContentAttr(const AtomicString& attributeName) +{ + DescendantInvalidationSet& invalidationSet = ensureAttributeInvalidationSet(attributeName); + invalidationSet.setWholeSubtreeInvalid(); +} + +void RuleFeatureSet::collectFeaturesFromRuleData(const RuleData& ruleData) +{ + FeatureMetadata metadata; + InvalidationSetMode mode = UseSubtreeStyleChange; + if (m_targetedStyleRecalcEnabled) + mode = updateInvalidationSets(ruleData.selector()); + + collectFeaturesFromSelector(ruleData.selector(), metadata, mode); + m_metadata.add(metadata); + + if (metadata.foundSiblingSelector) + siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); + if (ruleData.containsUncommonAttributeSelector()) + uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); +} + +DescendantInvalidationSet& RuleFeatureSet::ensureClassInvalidationSet(const AtomicString& className) +{ + InvalidationSetMap::AddResult addResult = m_classInvalidationSets.add(className, nullptr); + if (addResult.isNewEntry) + addResult.storedValue->value = DescendantInvalidationSet::create(); + return *addResult.storedValue->value; +} + +DescendantInvalidationSet& RuleFeatureSet::ensureAttributeInvalidationSet(const AtomicString& attributeName) +{ + InvalidationSetMap::AddResult addResult = m_attributeInvalidationSets.add(attributeName, nullptr); + if (addResult.isNewEntry) + addResult.storedValue->value = DescendantInvalidationSet::create(); + return *addResult.storedValue->value; +} + +DescendantInvalidationSet& RuleFeatureSet::ensureIdInvalidationSet(const AtomicString& id) +{ + InvalidationSetMap::AddResult addResult = m_idInvalidationSets.add(id, nullptr); + if (addResult.isNewEntry) + addResult.storedValue->value = DescendantInvalidationSet::create(); + return *addResult.storedValue->value; +} + +DescendantInvalidationSet& RuleFeatureSet::ensurePseudoInvalidationSet(CSSSelector::PseudoType pseudoType) +{ + PseudoTypeInvalidationSetMap::AddResult addResult = m_pseudoInvalidationSets.add(pseudoType, nullptr); + if (addResult.isNewEntry) + addResult.storedValue->value = DescendantInvalidationSet::create(); + return *addResult.storedValue->value; +} + +void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector) +{ + collectFeaturesFromSelector(selector, m_metadata, UseSubtreeStyleChange); +} + +void RuleFeatureSet::collectFeaturesFromSelector(const CSSSelector& selector, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) +{ + unsigned maxDirectAdjacentSelectors = 0; + + for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { + if (mode != AddFeatures) { + if (DescendantInvalidationSet* invalidationSet = invalidationSetForSelector(*current)) { + if (mode == UseSubtreeStyleChange) + invalidationSet->setWholeSubtreeInvalid(); + } + } + if (current->pseudoType() == CSSSelector::PseudoFirstLine) + metadata.usesFirstLineRules = true; + if (current->isDirectAdjacentSelector()) { + maxDirectAdjacentSelectors++; + } else if (maxDirectAdjacentSelectors) { + if (maxDirectAdjacentSelectors > metadata.maxDirectAdjacentSelectors) + metadata.maxDirectAdjacentSelectors = maxDirectAdjacentSelectors; + maxDirectAdjacentSelectors = 0; + } + if (current->isSiblingSelector()) + metadata.foundSiblingSelector = true; + + collectFeaturesFromSelectorList(current->selectorList(), metadata, mode); + + if (mode == UseLocalStyleChange && current->relation() != CSSSelector::SubSelector) + mode = UseSubtreeStyleChange; } + + ASSERT(!maxDirectAdjacentSelectors); } -void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* selectorList) +void RuleFeatureSet::collectFeaturesFromSelectorList(const CSSSelectorList* selectorList, RuleFeatureSet::FeatureMetadata& metadata, InvalidationSetMode mode) { if (!selectorList) return; - for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) { - for (const CSSSelector* subSelector = selector; subSelector; subSelector = subSelector->tagHistory()) - collectFeaturesFromSelector(subSelector); - } + for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) + collectFeaturesFromSelector(*selector, metadata, mode); +} + +void RuleFeatureSet::FeatureMetadata::add(const FeatureMetadata& other) +{ + usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; + maxDirectAdjacentSelectors = std::max(maxDirectAdjacentSelectors, other.maxDirectAdjacentSelectors); +} + +void RuleFeatureSet::FeatureMetadata::clear() +{ + usesFirstLineRules = false; + foundSiblingSelector = false; + maxDirectAdjacentSelectors = 0; } void RuleFeatureSet::add(const RuleFeatureSet& other) { - HashSet<AtomicString>::const_iterator end = other.idsInRules.end(); - for (HashSet<AtomicString>::const_iterator it = other.idsInRules.begin(); it != end; ++it) - idsInRules.add(*it); - end = other.classesInRules.end(); - for (HashSet<AtomicString>::const_iterator it = other.classesInRules.begin(); it != end; ++it) - classesInRules.add(*it); - end = other.attrsInRules.end(); - for (HashSet<AtomicString>::const_iterator it = other.attrsInRules.begin(); it != end; ++it) - attrsInRules.add(*it); - siblingRules.append(other.siblingRules); - uncommonAttributeRules.append(other.uncommonAttributeRules); - m_usesFirstLineRules = m_usesFirstLineRules || other.m_usesFirstLineRules; - m_maxDirectAdjacentSelectors = std::max(m_maxDirectAdjacentSelectors, other.maxDirectAdjacentSelectors()); + for (InvalidationSetMap::const_iterator it = other.m_classInvalidationSets.begin(); it != other.m_classInvalidationSets.end(); ++it) + ensureClassInvalidationSet(it->key).combine(*it->value); + for (InvalidationSetMap::const_iterator it = other.m_attributeInvalidationSets.begin(); it != other.m_attributeInvalidationSets.end(); ++it) + ensureAttributeInvalidationSet(it->key).combine(*it->value); + for (InvalidationSetMap::const_iterator it = other.m_idInvalidationSets.begin(); it != other.m_idInvalidationSets.end(); ++it) + ensureIdInvalidationSet(it->key).combine(*it->value); + for (PseudoTypeInvalidationSetMap::const_iterator it = other.m_pseudoInvalidationSets.begin(); it != other.m_pseudoInvalidationSets.end(); ++it) + ensurePseudoInvalidationSet(static_cast<CSSSelector::PseudoType>(it->key)).combine(*it->value); + + m_metadata.add(other.m_metadata); + + siblingRules.appendVector(other.siblingRules); + uncommonAttributeRules.appendVector(other.uncommonAttributeRules); } void RuleFeatureSet::clear() { - idsInRules.clear(); - classesInRules.clear(); - attrsInRules.clear(); siblingRules.clear(); uncommonAttributeRules.clear(); - m_usesFirstLineRules = false; - m_maxDirectAdjacentSelectors = 0; + m_metadata.clear(); + m_classInvalidationSets.clear(); + m_attributeInvalidationSets.clear(); + m_idInvalidationSets.clear(); + // We cannot clear m_styleInvalidator here, because the style invalidator might not + // have been evaluated yet. If not yet, in StyleInvalidator, there exists some element + // who has needsStyleInvlidation but does not have any invalidation list. + // This makes Blink not to recalc style correctly. crbug.com/344729. +} + +void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element& element) +{ + unsigned changedSize = changedClasses.size(); + for (unsigned i = 0; i < changedSize; ++i) { + addClassToInvalidationSet(changedClasses[i], element); + } +} + +void RuleFeatureSet::scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element& element) +{ + if (!oldClasses.size()) { + scheduleStyleInvalidationForClassChange(newClasses, element); + return; + } + + // Class vectors tend to be very short. This is faster than using a hash table. + BitVector remainingClassBits; + remainingClassBits.ensureSize(oldClasses.size()); + + for (unsigned i = 0; i < newClasses.size(); ++i) { + bool found = false; + for (unsigned j = 0; j < oldClasses.size(); ++j) { + if (newClasses[i] == oldClasses[j]) { + // Mark each class that is still in the newClasses so we can skip doing + // an n^2 search below when looking for removals. We can't break from + // this loop early since a class can appear more than once. + remainingClassBits.quickSet(j); + found = true; + } + } + // Class was added. + if (!found) + addClassToInvalidationSet(newClasses[i], element); + } + + for (unsigned i = 0; i < oldClasses.size(); ++i) { + if (remainingClassBits.quickGet(i)) + continue; + // Class was removed. + addClassToInvalidationSet(oldClasses[i], element); + } +} + +void RuleFeatureSet::scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element& element) +{ + + if (RefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet = m_attributeInvalidationSets.get(attributeName.localName())) + m_styleInvalidator.scheduleInvalidation(invalidationSet, element); +} + +void RuleFeatureSet::scheduleStyleInvalidationForIdChange(const AtomicString& oldId, const AtomicString& newId, Element& element) +{ + if (!oldId.isEmpty()) { + if (RefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet = m_idInvalidationSets.get(oldId)) + m_styleInvalidator.scheduleInvalidation(invalidationSet, element); + } + if (!newId.isEmpty()) { + if (RefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet = m_idInvalidationSets.get(newId)) + m_styleInvalidator.scheduleInvalidation(invalidationSet, element); + } +} + +void RuleFeatureSet::scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoType pseudo, Element& element) +{ + if (RefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet = m_pseudoInvalidationSets.get(pseudo)) + m_styleInvalidator.scheduleInvalidation(invalidationSet, element); +} + +void RuleFeatureSet::addClassToInvalidationSet(const AtomicString& className, Element& element) +{ + if (RefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet = m_classInvalidationSets.get(className)) + m_styleInvalidator.scheduleInvalidation(invalidationSet, element); +} + +StyleInvalidator& RuleFeatureSet::styleInvalidator() +{ + return m_styleInvalidator; +} + +void RuleFeatureSet::trace(Visitor* visitor) +{ + visitor->trace(siblingRules); + visitor->trace(uncommonAttributeRules); + visitor->trace(m_classInvalidationSets); + visitor->trace(m_attributeInvalidationSets); + visitor->trace(m_idInvalidationSets); + visitor->trace(m_pseudoInvalidationSets); + visitor->trace(m_styleInvalidator); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/RuleFeature.h b/chromium/third_party/WebKit/Source/core/css/RuleFeature.h index b51863c4289..bc098d89244 100644 --- a/chromium/third_party/WebKit/Source/core/css/RuleFeature.h +++ b/chromium/third_party/WebKit/Source/core/css/RuleFeature.h @@ -22,76 +22,172 @@ #ifndef RuleFeature_h #define RuleFeature_h +#include "core/css/CSSSelector.h" +#include "core/css/invalidation/StyleInvalidator.h" #include "wtf/Forward.h" #include "wtf/HashSet.h" #include "wtf/text/AtomicStringHash.h" namespace WebCore { -class StyleRule; -class CSSSelector; class CSSSelectorList; +class DescendantInvalidationSet; +class Document; +class Node; +class QualifiedName; +class RuleData; +class ShadowRoot; +class SpaceSplitString; +class StyleRule; struct RuleFeature { - RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin) - : rule(rule) - , selectorIndex(selectorIndex) - , hasDocumentSecurityOrigin(hasDocumentSecurityOrigin) - { - } - StyleRule* rule; + ALLOW_ONLY_INLINE_ALLOCATION(); +public: + RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin); + + void trace(Visitor*); + + RawPtrWillBeMember<StyleRule> rule; unsigned selectorIndex; bool hasDocumentSecurityOrigin; }; class RuleFeatureSet { + DISALLOW_ALLOCATION(); public: - RuleFeatureSet() - : m_usesFirstLineRules(false) - , m_maxDirectAdjacentSelectors(0) - { } + RuleFeatureSet(); + ~RuleFeatureSet(); void add(const RuleFeatureSet&); void clear(); - void collectFeaturesFromSelector(const CSSSelector*); + void collectFeaturesFromSelector(const CSSSelector&); + void collectFeaturesFromRuleData(const RuleData&); bool usesSiblingRules() const { return !siblingRules.isEmpty(); } - bool usesFirstLineRules() const { return m_usesFirstLineRules; } + bool usesFirstLineRules() const { return m_metadata.usesFirstLineRules; } - unsigned maxDirectAdjacentSelectors() const { return m_maxDirectAdjacentSelectors; } - void setMaxDirectAdjacentSelectors(unsigned value) { m_maxDirectAdjacentSelectors = std::max(value, m_maxDirectAdjacentSelectors); } + unsigned maxDirectAdjacentSelectors() const { return m_metadata.maxDirectAdjacentSelectors; } + void setMaxDirectAdjacentSelectors(unsigned value) { m_metadata.maxDirectAdjacentSelectors = std::max(value, m_metadata.maxDirectAdjacentSelectors); } inline bool hasSelectorForAttribute(const AtomicString& attributeName) const { ASSERT(!attributeName.isEmpty()); - return attrsInRules.contains(attributeName); + return m_attributeInvalidationSets.contains(attributeName); } inline bool hasSelectorForClass(const AtomicString& classValue) const { ASSERT(!classValue.isEmpty()); - return classesInRules.contains(classValue); + return m_classInvalidationSets.contains(classValue); } inline bool hasSelectorForId(const AtomicString& idValue) const { - ASSERT(!idValue.isEmpty()); - return idsInRules.contains(idValue); + return m_idInvalidationSets.contains(idValue); } - HashSet<AtomicString> idsInRules; - HashSet<AtomicString> classesInRules; - HashSet<AtomicString> attrsInRules; - Vector<RuleFeature> siblingRules; - Vector<RuleFeature> uncommonAttributeRules; -private: - void collectFeaturesFromSelectorList(const CSSSelectorList*); + void scheduleStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, Element&); + void scheduleStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Element&); + void scheduleStyleInvalidationForAttributeChange(const QualifiedName& attributeName, Element&); + void scheduleStyleInvalidationForIdChange(const AtomicString& oldId, const AtomicString& newId, Element&); + void scheduleStyleInvalidationForPseudoChange(CSSSelector::PseudoType, Element&); + + bool hasIdsInSelectors() const + { + return m_idInvalidationSets.size() > 0; + } - bool m_usesFirstLineRules; - unsigned m_maxDirectAdjacentSelectors; + // Marks the given attribute name as "appearing in a selector". Used for + // CSS properties such as content: ... attr(...) ... + // FIXME: record these internally to this class instead calls from StyleResolver to here. + void addContentAttr(const AtomicString& attributeName); + + StyleInvalidator& styleInvalidator(); + + void trace(Visitor*); + + WillBeHeapVector<RuleFeature> siblingRules; + WillBeHeapVector<RuleFeature> uncommonAttributeRules; + +private: + typedef WillBeHeapHashMap<AtomicString, RefPtrWillBeMember<DescendantInvalidationSet> > InvalidationSetMap; + typedef WillBeHeapHashMap<CSSSelector::PseudoType, RefPtrWillBeMember<DescendantInvalidationSet>, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > PseudoTypeInvalidationSetMap; + + struct FeatureMetadata { + FeatureMetadata() + : usesFirstLineRules(false) + , foundSiblingSelector(false) + , maxDirectAdjacentSelectors(0) + { } + void add(const FeatureMetadata& other); + void clear(); + + bool usesFirstLineRules; + bool foundSiblingSelector; + unsigned maxDirectAdjacentSelectors; + }; + + enum InvalidationSetMode { + AddFeatures, + UseLocalStyleChange, + UseSubtreeStyleChange + }; + + static InvalidationSetMode invalidationSetModeForSelector(const CSSSelector&); + + void collectFeaturesFromSelector(const CSSSelector&, FeatureMetadata&, InvalidationSetMode); + void collectFeaturesFromSelectorList(const CSSSelectorList*, FeatureMetadata&, InvalidationSetMode); + + DescendantInvalidationSet& ensureClassInvalidationSet(const AtomicString& className); + DescendantInvalidationSet& ensureAttributeInvalidationSet(const AtomicString& attributeName); + DescendantInvalidationSet& ensureIdInvalidationSet(const AtomicString& attributeName); + DescendantInvalidationSet& ensurePseudoInvalidationSet(CSSSelector::PseudoType); + DescendantInvalidationSet* invalidationSetForSelector(const CSSSelector&); + + InvalidationSetMode updateInvalidationSets(const CSSSelector&); + + struct InvalidationSetFeatures { + InvalidationSetFeatures() + : customPseudoElement(false) + , treeBoundaryCrossing(false) + , wholeSubtree(false) + { } + Vector<AtomicString> classes; + Vector<AtomicString> attributes; + AtomicString id; + AtomicString tagName; + bool customPseudoElement; + bool treeBoundaryCrossing; + bool wholeSubtree; + }; + + static void extractInvalidationSetFeature(const CSSSelector&, InvalidationSetFeatures&); + const CSSSelector* extractInvalidationSetFeatures(const CSSSelector&, InvalidationSetFeatures&); + void addFeaturesToInvalidationSets(const CSSSelector&, InvalidationSetFeatures&); + + void addClassToInvalidationSet(const AtomicString& className, Element&); + + FeatureMetadata m_metadata; + InvalidationSetMap m_classInvalidationSets; + InvalidationSetMap m_attributeInvalidationSets; + InvalidationSetMap m_idInvalidationSets; + PseudoTypeInvalidationSetMap m_pseudoInvalidationSets; + bool m_targetedStyleRecalcEnabled; + StyleInvalidator m_styleInvalidator; }; + } // namespace WebCore +namespace WTF { + +template <> struct VectorTraits<WebCore::RuleFeature> : VectorTraitsBase<WebCore::RuleFeature> { + static const bool needsDestruction = false; + static const bool canInitializeWithMemset = true; + static const bool canMoveWithMemcpy = true; +}; + +} // namespace WTF + #endif // RuleFeature_h diff --git a/chromium/third_party/WebKit/Source/core/css/RuleSet.cpp b/chromium/third_party/WebKit/Source/core/css/RuleSet.cpp index f7a0325f543..7e2a8f344fd 100644 --- a/chromium/third_party/WebKit/Source/core/css/RuleSet.cpp +++ b/chromium/third_party/WebKit/Source/core/css/RuleSet.cpp @@ -29,39 +29,43 @@ #include "config.h" #include "core/css/RuleSet.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" +#include "core/HTMLNames.h" #include "core/css/CSSFontSelector.h" #include "core/css/CSSSelector.h" #include "core/css/CSSSelectorList.h" #include "core/css/SelectorChecker.h" -#include "core/css/SelectorCheckerFastPath.h" #include "core/css/SelectorFilter.h" #include "core/css/StyleRuleImport.h" #include "core/css/StyleSheetContents.h" #include "core/html/track/TextTrackCue.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/TraceEvent.h" +#include "platform/heap/HeapTerminatedArrayBuilder.h" #include "platform/weborigin/SecurityOrigin.h" +#include "wtf/TerminatedArrayBuilder.h" + namespace WebCore { using namespace HTMLNames; // ----------------------------------------------------------------- -static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector) +static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector& selector) { - ASSERT(selector); - if (selector->m_match == CSSSelector::Tag) { - const AtomicString& selectorNamespace = selector->tagQName().namespaceURI(); + if (selector.match() == CSSSelector::Tag) { + const AtomicString& selectorNamespace = selector.tagQName().namespaceURI(); if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI) return false; - if (selector->relation() == CSSSelector::SubSelector) - return isSelectorMatchingHTMLBasedOnRuleHash(selector->tagHistory()); + if (selector.relation() == CSSSelector::SubSelector) { + ASSERT(selector.tagHistory()); + return isSelectorMatchingHTMLBasedOnRuleHash(*selector.tagHistory()); + } return true; } if (SelectorChecker::isCommonPseudoClassSelector(selector)) return true; - return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class; + return selector.match() == CSSSelector::Id || selector.match() == CSSSelector::Class; } static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector) @@ -69,7 +73,7 @@ static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelect const CSSSelectorList* selectorList = selector->selectorList(); if (!selectorList) return false; - for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(selector)) { + for (const CSSSelector* selector = selectorList->first(); selector; selector = CSSSelectorList::next(*selector)) { for (const CSSSelector* component = selector; component; component = component->tagHistory()) { if (component->isAttributeSelector()) return true; @@ -84,118 +88,48 @@ static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attri return attribute == typeAttr || attribute == readonlyAttr; } -static inline bool containsUncommonAttributeSelector(const CSSSelector* selector) +static inline bool containsUncommonAttributeSelector(const CSSSelector& selector) { - for (; selector; selector = selector->tagHistory()) { + const CSSSelector* current = &selector; + for (; current; current = current->tagHistory()) { // Allow certain common attributes (used in the default style) in the selectors that match the current element. - if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute())) + if (current->isAttributeSelector() && !isCommonAttributeSelectorAttribute(current->attribute())) return true; - if (selectorListContainsUncommonAttributeSelector(selector)) + if (selectorListContainsUncommonAttributeSelector(current)) return true; - if (selector->relation() != CSSSelector::SubSelector) { - selector = selector->tagHistory(); + if (current->relation() != CSSSelector::SubSelector) { + current = current->tagHistory(); break; } } - for (; selector; selector = selector->tagHistory()) { - if (selector->isAttributeSelector()) + for (; current; current = current->tagHistory()) { + if (current->isAttributeSelector()) return true; - if (selectorListContainsUncommonAttributeSelector(selector)) + if (selectorListContainsUncommonAttributeSelector(current)) return true; } return false; } -static inline PropertyWhitelistType determinePropertyWhitelistType(const AddRuleFlags addRuleFlags, const CSSSelector* selector) +static inline PropertyWhitelistType determinePropertyWhitelistType(const AddRuleFlags addRuleFlags, const CSSSelector& selector) { - if (addRuleFlags & RuleIsInRegionRule) - return PropertyWhitelistRegion; - for (const CSSSelector* component = selector; component; component = component->tagHistory()) { - if (component->pseudoType() == CSSSelector::PseudoCue || (component->m_match == CSSSelector::PseudoElement && component->value() == TextTrackCue::cueShadowPseudoId())) + for (const CSSSelector* component = &selector; component; component = component->tagHistory()) { + if (component->pseudoType() == CSSSelector::PseudoCue || (component->match() == CSSSelector::PseudoElement && component->value() == TextTrackCue::cueShadowPseudoId())) return PropertyWhitelistCue; + if (component->pseudoType() == CSSSelector::PseudoFirstLetter) + return PropertyWhitelistFirstLetter; } return PropertyWhitelistNone; } -namespace { - -// FIXME: Should we move this class to WTF? -template<typename T> -class TerminatedArrayBuilder { -public: - explicit TerminatedArrayBuilder(PassOwnPtr<T> array) - : m_array(array) - , m_count(0) - , m_capacity(0) - { - if (!m_array) - return; - for (T* item = m_array.get(); !item->isLastInArray(); ++item) - ++m_count; - ++m_count; // To count the last item itself. - m_capacity = m_count; - } - - void grow(size_t count) - { - ASSERT(count); - if (!m_array) { - ASSERT(!m_count); - ASSERT(!m_capacity); - m_capacity = count; - m_array = adoptPtr(static_cast<T*>(fastMalloc(m_capacity * sizeof(T)))); - return; - } - m_capacity += count; - m_array = adoptPtr(static_cast<T*>(fastRealloc(m_array.leakPtr(), m_capacity * sizeof(T)))); - m_array.get()[m_count - 1].setLastInArray(false); - } - - void append(const T& item) - { - RELEASE_ASSERT(m_count < m_capacity); - ASSERT(!item.isLastInArray()); - m_array.get()[m_count++] = item; - } - - PassOwnPtr<T> release() - { - RELEASE_ASSERT(m_count == m_capacity); - if (m_array) - m_array.get()[m_count - 1].setLastInArray(true); - assertValid(); - return m_array.release(); - } - -private: -#ifndef NDEBUG - void assertValid() - { - for (size_t i = 0; i < m_count; ++i) { - bool isLastInArray = (i + 1 == m_count); - ASSERT(m_array.get()[i].isLastInArray() == isLastInArray); - } - } -#else - void assertValid() { } -#endif - - OwnPtr<T> m_array; - size_t m_count; - size_t m_capacity; -}; - -} - RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, AddRuleFlags addRuleFlags) : m_rule(rule) , m_selectorIndex(selectorIndex) , m_isLastInArray(false) , m_position(position) - , m_hasFastCheckableSelector((addRuleFlags & RuleCanUseFastCheckSelector) && SelectorCheckerFastPath::canUse(selector())) - , m_specificity(selector()->specificity()) - , m_hasMultipartSelector(!!selector()->tagHistory()) + , m_specificity(selector().specificity()) + , m_hasMultipartSelector(!!selector().tagHistory()) , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector())) , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector())) , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector())) @@ -207,66 +141,78 @@ RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, A SelectorFilter::collectIdentifierHashes(selector(), m_descendantSelectorIdentifierHashes, maximumIdentifierCount); } -static void collectFeaturesFromRuleData(RuleFeatureSet& features, const RuleData& ruleData) +void RuleSet::addToRuleSet(const AtomicString& key, PendingRuleMap& map, const RuleData& ruleData) { - bool foundSiblingSelector = false; - unsigned maxDirectAdjacentSelectors = 0; - for (const CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) { - features.collectFeaturesFromSelector(selector); - - if (const CSSSelectorList* selectorList = selector->selectorList()) { - for (const CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { - // FIXME: Shouldn't this be checking subSelector->isSiblingSelector()? - if (!foundSiblingSelector && selector->isSiblingSelector()) - foundSiblingSelector = true; - if (subSelector->isDirectAdjacentSelector()) - maxDirectAdjacentSelectors++; - features.collectFeaturesFromSelector(subSelector); - } - } else { - if (!foundSiblingSelector && selector->isSiblingSelector()) - foundSiblingSelector = true; - if (selector->isDirectAdjacentSelector()) - maxDirectAdjacentSelectors++; - } - } - features.setMaxDirectAdjacentSelectors(maxDirectAdjacentSelectors); - if (foundSiblingSelector) - features.siblingRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); - if (ruleData.containsUncommonAttributeSelector()) - features.uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); + OwnPtrWillBeMember<WillBeHeapLinkedStack<RuleData> >& rules = map.add(key, nullptr).storedValue->value; + if (!rules) + rules = adoptPtrWillBeNoop(new WillBeHeapLinkedStack<RuleData>); + rules->push(ruleData); } -void RuleSet::addToRuleSet(StringImpl* key, PendingRuleMap& map, const RuleData& ruleData) +static void extractValuesforSelector(const CSSSelector* selector, AtomicString& id, AtomicString& className, AtomicString& customPseudoElementName, AtomicString& tagName) { - if (!key) - return; - OwnPtr<LinkedStack<RuleData> >& rules = map.add(key, nullptr).iterator->value; - if (!rules) - rules = adoptPtr(new LinkedStack<RuleData>); - rules->push(ruleData); + switch (selector->match()) { + case CSSSelector::Id: + id = selector->value(); + break; + case CSSSelector::Class: + className = selector->value(); + break; + case CSSSelector::Tag: + if (selector->tagQName().localName() != starAtom) + tagName = selector->tagQName().localName(); + break; + default: + break; + } + if (selector->isCustomPseudoElement()) + customPseudoElementName = selector->value(); } -bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& ruleData) +bool RuleSet::findBestRuleSetAndAdd(const CSSSelector& component, RuleData& ruleData) { - if (component->m_match == CSSSelector::Id) { - addToRuleSet(component->value().impl(), ensurePendingRules()->idRules, ruleData); + AtomicString id; + AtomicString className; + AtomicString customPseudoElementName; + AtomicString tagName; + +#ifndef NDEBUG + m_allRules.append(ruleData); +#endif + + const CSSSelector* it = &component; + for (; it && it->relation() == CSSSelector::SubSelector; it = it->tagHistory()) { + extractValuesforSelector(it, id, className, customPseudoElementName, tagName); + } + // FIXME: this null check should not be necessary. See crbug.com/358475 + if (it) + extractValuesforSelector(it, id, className, customPseudoElementName, tagName); + + // Prefer rule sets in order of most likely to apply infrequently. + if (!id.isEmpty()) { + addToRuleSet(id, ensurePendingRules()->idRules, ruleData); return true; } - if (component->m_match == CSSSelector::Class) { - addToRuleSet(component->value().impl(), ensurePendingRules()->classRules, ruleData); + if (!className.isEmpty()) { + addToRuleSet(className, ensurePendingRules()->classRules, ruleData); return true; } - if (component->isCustomPseudoElement()) { - addToRuleSet(component->value().impl(), ensurePendingRules()->shadowPseudoElementRules, ruleData); + if (!customPseudoElementName.isEmpty()) { + // Custom pseudos come before ids and classes in the order of tagHistory, and have a relation of + // ShadowPseudo between them. Therefore we should never be a situation where extractValuesforSelector + // finsd id and className in addition to custom pseudo. + ASSERT(id.isEmpty() && className.isEmpty()); + addToRuleSet(customPseudoElementName, ensurePendingRules()->shadowPseudoElementRules, ruleData); return true; } - if (component->pseudoType() == CSSSelector::PseudoCue) { + + if (component.pseudoType() == CSSSelector::PseudoCue) { m_cuePseudoRules.append(ruleData); return true; } + if (SelectorChecker::isCommonPseudoClassSelector(component)) { - switch (component->pseudoType()) { + switch (component.pseudoType()) { case CSSSelector::PseudoLink: case CSSSelector::PseudoVisited: case CSSSelector::PseudoAnyLink: @@ -281,25 +227,18 @@ bool RuleSet::findBestRuleSetAndAdd(const CSSSelector* component, RuleData& rule } } - if (component->m_match == CSSSelector::Tag) { - if (component->tagQName().localName() != starAtom) { - // If this is part of a subselector chain, recurse ahead to find a narrower set (ID/class.) - if (component->relation() == CSSSelector::SubSelector - && (component->tagHistory()->m_match == CSSSelector::Class || component->tagHistory()->m_match == CSSSelector::Id || SelectorChecker::isCommonPseudoClassSelector(component->tagHistory())) - && findBestRuleSetAndAdd(component->tagHistory(), ruleData)) - return true; - - addToRuleSet(component->tagQName().localName().impl(), ensurePendingRules()->tagRules, ruleData); - return true; - } + if (!tagName.isEmpty()) { + addToRuleSet(tagName, ensurePendingRules()->tagRules, ruleData); + return true; } + return false; } void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, AddRuleFlags addRuleFlags) { RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags); - collectFeaturesFromRuleData(m_features, ruleData); + m_features.collectFeaturesFromRuleData(ruleData); if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) { // If we didn't find a specialized map to stick it in, file under universal rules. @@ -331,32 +270,7 @@ void RuleSet::addKeyframesRule(StyleRuleKeyframes* rule) m_keyframesRules.append(rule); } -void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurityOrigin) -{ - ensurePendingRules(); // So that m_regionSelectorsAndRuleSets.shrinkToFit() gets called. - OwnPtr<RuleSet> regionRuleSet = RuleSet::create(); - // The region rule set should take into account the position inside the parent rule set. - // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from - // the stylesheet that contains the region block. - regionRuleSet->m_ruleCount = m_ruleCount; - - // Collect the region rules into a rule set - // FIXME: Should this add other types of rules? (i.e. use addChildRules() directly?) - const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules(); - AddRuleFlags addRuleFlags = hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState; - addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleIsInRegionRule | RuleCanUseFastCheckSelector); - for (unsigned i = 0; i < childRules.size(); ++i) { - StyleRuleBase* regionStylingRule = childRules[i].get(); - if (regionStylingRule->isStyleRule()) - regionRuleSet->addStyleRule(toStyleRule(regionStylingRule), addRuleFlags); - } - // Update the "global" rule count so that proper order is maintained - m_ruleCount = regionRuleSet->m_ruleCount; - - m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(regionRule->selectorList().first(), regionRuleSet.release())); -} - -void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase> >& rules, const MediaQueryEvaluator& medium, AddRuleFlags addRuleFlags) +void RuleSet::addChildRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& rules, const MediaQueryEvaluator& medium, AddRuleFlags addRuleFlags) { for (unsigned i = 0; i < rules.size(); ++i) { StyleRuleBase* rule = rules[i].get(); @@ -366,7 +280,7 @@ void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase> >& rules, const M const CSSSelectorList& selectorList = styleRule->selectorList(); for (size_t selectorIndex = 0; selectorIndex != kNotFound; selectorIndex = selectorList.indexOfNextSelectorAfter(selectorIndex)) { - if (selectorList.hasCombinatorCrossingTreeBoundaryAt(selectorIndex)) { + if (selectorList.selectorCrossesTreeScopes(selectorIndex)) { m_treeBoundaryCrossingRules.append(MinimalRuleData(styleRule, selectorIndex, addRuleFlags)); } else if (selectorList.hasShadowDistributedAt(selectorIndex)) { m_shadowDistributedRules.append(MinimalRuleData(styleRule, selectorIndex, addRuleFlags)); @@ -384,8 +298,6 @@ void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase> >& rules, const M addFontFaceRule(toStyleRuleFontFace(rule)); } else if (rule->isKeyframesRule()) { addKeyframesRule(toStyleRuleKeyframes(rule)); - } else if (rule->isRegionRule()) { - addRegionRule(toStyleRuleRegion(rule), addRuleFlags & RuleHasDocumentSecurityOrigin); } else if (rule->isViewportRule()) { addViewportRule(toStyleRuleViewport(rule)); } else if (rule->isSupportsRule() && toStyleRuleSupports(rule)->conditionIsSupported()) { @@ -396,10 +308,12 @@ void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase> >& rules, const M void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, AddRuleFlags addRuleFlags) { + TRACE_EVENT0("webkit", "RuleSet::addRulesFromSheet"); + ASSERT(sheet); addRuleFlags = static_cast<AddRuleFlags>(addRuleFlags | RuleCanUseFastCheckSelector); - const Vector<RefPtr<StyleRuleImport> >& importRules = sheet->importRules(); + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport> >& importRules = sheet->importRules(); for (unsigned i = 0; i < importRules.size(); ++i) { StyleRuleImport* importRule = importRules[i].get(); if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), &m_viewportDependentMediaQueryResults))) @@ -419,10 +333,10 @@ void RuleSet::compactPendingRules(PendingRuleMap& pendingMap, CompactRuleMap& co { PendingRuleMap::iterator end = pendingMap.end(); for (PendingRuleMap::iterator it = pendingMap.begin(); it != end; ++it) { - OwnPtr<LinkedStack<RuleData> > pendingRules = it->value.release(); - CompactRuleMap::iterator compactRules = compactMap.add(it->key, nullptr).iterator; + OwnPtrWillBeRawPtr<WillBeHeapLinkedStack<RuleData> > pendingRules = it->value.release(); + CompactRuleMap::ValueType* compactRules = compactMap.add(it->key, nullptr).storedValue; - TerminatedArrayBuilder<RuleData> builder(compactRules->value.release()); + WillBeHeapTerminatedArrayBuilder<RuleData> builder(compactRules->value.release()); builder.grow(pendingRules->size()); while (!pendingRules->isEmpty()) { builder.append(pendingRules->peek()); @@ -436,7 +350,7 @@ void RuleSet::compactPendingRules(PendingRuleMap& pendingMap, CompactRuleMap& co void RuleSet::compactRules() { ASSERT(m_pendingRules); - OwnPtr<PendingRuleMaps> pendingRules = m_pendingRules.release(); + OwnPtrWillBeRawPtr<PendingRuleMaps> pendingRules = m_pendingRules.release(); compactPendingRules(pendingRules->idRules, m_idRules); compactPendingRules(pendingRules->classRules, m_classRules); compactPendingRules(pendingRules->tagRules, m_tagRules); @@ -453,4 +367,56 @@ void RuleSet::compactRules() m_shadowDistributedRules.shrinkToFit(); } +void MinimalRuleData::trace(Visitor* visitor) +{ + visitor->trace(m_rule); +} + +void RuleData::trace(Visitor* visitor) +{ + visitor->trace(m_rule); +} + +void RuleSet::PendingRuleMaps::trace(Visitor* visitor) +{ + visitor->trace(idRules); + visitor->trace(classRules); + visitor->trace(tagRules); + visitor->trace(shadowPseudoElementRules); +} + +void RuleSet::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_idRules); + visitor->trace(m_classRules); + visitor->trace(m_tagRules); + visitor->trace(m_shadowPseudoElementRules); + visitor->trace(m_linkPseudoClassRules); + visitor->trace(m_cuePseudoRules); + visitor->trace(m_focusPseudoClassRules); + visitor->trace(m_universalRules); + visitor->trace(m_features); + visitor->trace(m_pageRules); + visitor->trace(m_viewportRules); + visitor->trace(m_fontFaceRules); + visitor->trace(m_keyframesRules); + visitor->trace(m_treeBoundaryCrossingRules); + visitor->trace(m_shadowDistributedRules); + visitor->trace(m_viewportDependentMediaQueryResults); + visitor->trace(m_pendingRules); +#ifndef NDEBUG + visitor->trace(m_allRules); +#endif +#endif +} + +#ifndef NDEBUG +void RuleSet::show() +{ + for (WillBeHeapVector<RuleData>::const_iterator it = m_allRules.begin(); it != m_allRules.end(); ++it) + it->selector().show(); +} +#endif + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/RuleSet.h b/chromium/third_party/WebKit/Source/core/css/RuleSet.h index d8249a3edb9..e7538f58100 100644 --- a/chromium/third_party/WebKit/Source/core/css/RuleSet.h +++ b/chromium/third_party/WebKit/Source/core/css/RuleSet.h @@ -27,9 +27,12 @@ #include "core/css/RuleFeature.h" #include "core/css/StyleRule.h" #include "core/css/resolver/MediaQueryResult.h" +#include "platform/heap/HeapLinkedStack.h" +#include "platform/heap/HeapTerminatedArray.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" #include "wtf/LinkedStack.h" +#include "wtf/TerminatedArray.h" namespace WebCore { @@ -37,21 +40,21 @@ enum AddRuleFlags { RuleHasNoSpecialState = 0, RuleHasDocumentSecurityOrigin = 1, RuleCanUseFastCheckSelector = 1 << 1, - RuleIsInRegionRule = 1 << 2, }; enum PropertyWhitelistType { PropertyWhitelistNone = 0, - PropertyWhitelistRegion, - PropertyWhitelistCue + PropertyWhitelistCue, + PropertyWhitelistFirstLetter, }; class CSSSelector; class MediaQueryEvaluator; -class StyleRuleRegion; class StyleSheetContents; -struct MinimalRuleData { +class MinimalRuleData { + ALLOW_ONLY_INLINE_ALLOCATION(); +public: MinimalRuleData(StyleRule* rule, unsigned selectorIndex, AddRuleFlags flags) : m_rule(rule) , m_selectorIndex(selectorIndex) @@ -59,25 +62,26 @@ struct MinimalRuleData { { } - StyleRule* m_rule; + void trace(Visitor*); + + RawPtrWillBeMember<StyleRule> m_rule; unsigned m_selectorIndex; AddRuleFlags m_flags; }; class RuleData { - WTF_MAKE_FAST_ALLOCATED; + ALLOW_ONLY_INLINE_ALLOCATION(); public: RuleData(StyleRule*, unsigned selectorIndex, unsigned position, AddRuleFlags); unsigned position() const { return m_position; } StyleRule* rule() const { return m_rule; } - const CSSSelector* selector() const { return m_rule->selectorList().selectorAt(m_selectorIndex); } + const CSSSelector& selector() const { return m_rule->selectorList().selectorAt(m_selectorIndex); } unsigned selectorIndex() const { return m_selectorIndex; } bool isLastInArray() const { return m_isLastInArray; } void setLastInArray(bool flag) { m_isLastInArray = flag; } - bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; } bool hasMultipartSelector() const { return m_hasMultipartSelector; } bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; } bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; } @@ -89,14 +93,15 @@ public: static const unsigned maximumIdentifierCount = 4; const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; } + void trace(Visitor*); + private: - StyleRule* m_rule; + RawPtrWillBeMember<StyleRule> m_rule; unsigned m_selectorIndex : 12; unsigned m_isLastInArray : 1; // We store an array of RuleData objects in a primitive array. // This number was picked fairly arbitrarily. We can probably lower it if we need to. // Some simple testing showed <100,000 RuleData's on large sites. unsigned m_position : 18; - unsigned m_hasFastCheckableSelector : 1; unsigned m_specificity : 24; unsigned m_hasMultipartSelector : 1; unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1; @@ -117,10 +122,11 @@ struct SameSizeAsRuleData { COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small); -class RuleSet { - WTF_MAKE_NONCOPYABLE(RuleSet); WTF_MAKE_FAST_ALLOCATED; +class RuleSet : public NoBaseWillBeGarbageCollectedFinalized<RuleSet> { + WTF_MAKE_NONCOPYABLE(RuleSet); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassOwnPtr<RuleSet> create() { return adoptPtr(new RuleSet); } + static PassOwnPtrWillBeRawPtr<RuleSet> create() { return adoptPtrWillBeNoop(new RuleSet); } void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, AddRuleFlags = RuleHasNoSpecialState); void addStyleRule(StyleRule*, AddRuleFlags); @@ -128,20 +134,20 @@ public: const RuleFeatureSet& features() const { return m_features; } - const RuleData* idRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_idRules.get(key); } - const RuleData* classRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_classRules.get(key); } - const RuleData* tagRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_tagRules.get(key); } - const RuleData* shadowPseudoElementRules(StringImpl* key) const { ASSERT(!m_pendingRules); return m_shadowPseudoElementRules.get(key); } - const Vector<RuleData>* linkPseudoClassRules() const { ASSERT(!m_pendingRules); return &m_linkPseudoClassRules; } - const Vector<RuleData>* cuePseudoRules() const { ASSERT(!m_pendingRules); return &m_cuePseudoRules; } - const Vector<RuleData>* focusPseudoClassRules() const { ASSERT(!m_pendingRules); return &m_focusPseudoClassRules; } - const Vector<RuleData>* universalRules() const { ASSERT(!m_pendingRules); return &m_universalRules; } - const Vector<StyleRulePage*>& pageRules() const { ASSERT(!m_pendingRules); return m_pageRules; } - const Vector<StyleRuleViewport*>& viewportRules() const { ASSERT(!m_pendingRules); return m_viewportRules; } - const Vector<StyleRuleFontFace*>& fontFaceRules() const { return m_fontFaceRules; } - const Vector<StyleRuleKeyframes*>& keyframesRules() const { return m_keyframesRules; } - const Vector<MinimalRuleData>& treeBoundaryCrossingRules() const { return m_treeBoundaryCrossingRules; } - const Vector<MinimalRuleData>& shadowDistributedRules() const { return m_shadowDistributedRules; } + const WillBeHeapTerminatedArray<RuleData>* idRules(const AtomicString& key) const { ASSERT(!m_pendingRules); return m_idRules.get(key); } + const WillBeHeapTerminatedArray<RuleData>* classRules(const AtomicString& key) const { ASSERT(!m_pendingRules); return m_classRules.get(key); } + const WillBeHeapTerminatedArray<RuleData>* tagRules(const AtomicString& key) const { ASSERT(!m_pendingRules); return m_tagRules.get(key); } + const WillBeHeapTerminatedArray<RuleData>* shadowPseudoElementRules(const AtomicString& key) const { ASSERT(!m_pendingRules); return m_shadowPseudoElementRules.get(key); } + const WillBeHeapVector<RuleData>* linkPseudoClassRules() const { ASSERT(!m_pendingRules); return &m_linkPseudoClassRules; } + const WillBeHeapVector<RuleData>* cuePseudoRules() const { ASSERT(!m_pendingRules); return &m_cuePseudoRules; } + const WillBeHeapVector<RuleData>* focusPseudoClassRules() const { ASSERT(!m_pendingRules); return &m_focusPseudoClassRules; } + const WillBeHeapVector<RuleData>* universalRules() const { ASSERT(!m_pendingRules); return &m_universalRules; } + const WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >& pageRules() const { ASSERT(!m_pendingRules); return m_pageRules; } + const WillBeHeapVector<RawPtrWillBeMember<StyleRuleViewport> >& viewportRules() const { ASSERT(!m_pendingRules); return m_viewportRules; } + const WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> >& fontFaceRules() const { return m_fontFaceRules; } + const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> >& keyframesRules() const { return m_keyframesRules; } + const WillBeHeapVector<MinimalRuleData>& treeBoundaryCrossingRules() const { return m_treeBoundaryCrossingRules; } + const WillBeHeapVector<MinimalRuleData>& shadowDistributedRules() const { return m_shadowDistributedRules; } const MediaQueryResultList& viewportDependentMediaQueryResults() const { return m_viewportDependentMediaQueryResults; } unsigned ruleCount() const { return m_ruleCount; } @@ -153,49 +159,52 @@ public: compactRules(); } - struct RuleSetSelectorPair { - RuleSetSelectorPair(const CSSSelector* selector, PassOwnPtr<RuleSet> ruleSet) : selector(selector), ruleSet(ruleSet) { } - RuleSetSelectorPair(const RuleSetSelectorPair& rs) : selector(rs.selector), ruleSet(const_cast<RuleSetSelectorPair*>(&rs)->ruleSet.release()) { } - - const CSSSelector* selector; - OwnPtr<RuleSet> ruleSet; - }; +#ifndef NDEBUG + void show(); +#endif - Vector<RuleSetSelectorPair> m_regionSelectorsAndRuleSets; + void trace(Visitor*); private: - typedef HashMap<StringImpl*, OwnPtr<LinkedStack<RuleData> > > PendingRuleMap; - typedef HashMap<StringImpl*, OwnPtr<RuleData> > CompactRuleMap; + typedef WillBeHeapHashMap<AtomicString, OwnPtrWillBeMember<WillBeHeapLinkedStack<RuleData> > > PendingRuleMap; + typedef WillBeHeapHashMap<AtomicString, OwnPtrWillBeMember<WillBeHeapTerminatedArray<RuleData> > > CompactRuleMap; RuleSet() : m_ruleCount(0) { } - void addToRuleSet(StringImpl* key, PendingRuleMap&, const RuleData&); + void addToRuleSet(const AtomicString& key, PendingRuleMap&, const RuleData&); void addPageRule(StyleRulePage*); void addViewportRule(StyleRuleViewport*); void addFontFaceRule(StyleRuleFontFace*); void addKeyframesRule(StyleRuleKeyframes*); - void addRegionRule(StyleRuleRegion*, bool hasDocumentSecurityOrigin); - void addChildRules(const Vector<RefPtr<StyleRuleBase> >&, const MediaQueryEvaluator& medium, AddRuleFlags); - bool findBestRuleSetAndAdd(const CSSSelector*, RuleData&); + void addChildRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >&, const MediaQueryEvaluator& medium, AddRuleFlags); + bool findBestRuleSetAndAdd(const CSSSelector&, RuleData&); void compactRules(); static void compactPendingRules(PendingRuleMap&, CompactRuleMap&); - struct PendingRuleMaps { + class PendingRuleMaps : public NoBaseWillBeGarbageCollected<PendingRuleMaps> { + public: + static PassOwnPtrWillBeRawPtr<PendingRuleMaps> create() { return adoptPtrWillBeNoop(new PendingRuleMaps); } + PendingRuleMap idRules; PendingRuleMap classRules; PendingRuleMap tagRules; PendingRuleMap shadowPseudoElementRules; + + void trace(Visitor*); + + private: + PendingRuleMaps() { } }; PendingRuleMaps* ensurePendingRules() { if (!m_pendingRules) - m_pendingRules = adoptPtr(new PendingRuleMaps); + m_pendingRules = PendingRuleMaps::create(); return m_pendingRules.get(); } @@ -203,24 +212,31 @@ private: CompactRuleMap m_classRules; CompactRuleMap m_tagRules; CompactRuleMap m_shadowPseudoElementRules; - Vector<RuleData> m_linkPseudoClassRules; - Vector<RuleData> m_cuePseudoRules; - Vector<RuleData> m_focusPseudoClassRules; - Vector<RuleData> m_universalRules; + WillBeHeapVector<RuleData> m_linkPseudoClassRules; + WillBeHeapVector<RuleData> m_cuePseudoRules; + WillBeHeapVector<RuleData> m_focusPseudoClassRules; + WillBeHeapVector<RuleData> m_universalRules; RuleFeatureSet m_features; - Vector<StyleRulePage*> m_pageRules; - Vector<StyleRuleViewport*> m_viewportRules; - Vector<StyleRuleFontFace*> m_fontFaceRules; - Vector<StyleRuleKeyframes*> m_keyframesRules; - Vector<MinimalRuleData> m_treeBoundaryCrossingRules; - Vector<MinimalRuleData> m_shadowDistributedRules; + WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> > m_pageRules; + WillBeHeapVector<RawPtrWillBeMember<StyleRuleViewport> > m_viewportRules; + WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> > m_fontFaceRules; + WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > m_keyframesRules; + WillBeHeapVector<MinimalRuleData> m_treeBoundaryCrossingRules; + WillBeHeapVector<MinimalRuleData> m_shadowDistributedRules; MediaQueryResultList m_viewportDependentMediaQueryResults; unsigned m_ruleCount; - OwnPtr<PendingRuleMaps> m_pendingRules; + OwnPtrWillBeMember<PendingRuleMaps> m_pendingRules; + +#ifndef NDEBUG + WillBeHeapVector<RuleData> m_allRules; +#endif }; } // namespace WebCore +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::RuleData); +WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(WebCore::MinimalRuleData); + #endif // RuleSet_h diff --git a/chromium/third_party/WebKit/Source/core/css/RuleSetTest.cpp b/chromium/third_party/WebKit/Source/core/css/RuleSetTest.cpp new file mode 100644 index 00000000000..8fd5ec63bba --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/RuleSetTest.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014, 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. + * 3. Neither the name of Opera Software ASA nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 HOLDER 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. + */ + +#include "config.h" +#include "core/css/CSSTestHelper.h" +#include "core/css/RuleSet.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +TEST(RuleSetTest, findBestRuleSetAndAdd_CustomPseudoElements) +{ + CSSTestHelper helper; + + helper.addCSSRules("summary::-webkit-details-marker { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("-webkit-details-marker"); + const TerminatedArray<RuleData>* rules = ruleSet.shadowPseudoElementRules(str); + ASSERT_EQ(1u, rules->size()); + ASSERT_EQ(str, rules->at(0).selector().value()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_Id) +{ + CSSTestHelper helper; + + helper.addCSSRules("#id { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("id"); + const TerminatedArray<RuleData>* rules = ruleSet.idRules(str); + ASSERT_EQ(1u, rules->size()); + ASSERT_EQ(str, rules->at(0).selector().value()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_NthChild) +{ + CSSTestHelper helper; + + helper.addCSSRules("div:nth-child(2) { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("div"); + const TerminatedArray<RuleData>* rules = ruleSet.tagRules(str); + ASSERT_EQ(1u, rules->size()); + ASSERT_EQ(str, rules->at(0).selector().tagQName().localName()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_ClassThenId) +{ + CSSTestHelper helper; + + helper.addCSSRules(".class#id { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("id"); + // id is prefered over class even if class preceeds it in the selector. + const TerminatedArray<RuleData>* rules = ruleSet.idRules(str); + ASSERT_EQ(1u, rules->size()); + AtomicString classStr("class"); + ASSERT_EQ(classStr, rules->at(0).selector().value()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_IdThenClass) +{ + CSSTestHelper helper; + + helper.addCSSRules("#id.class { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("id"); + const TerminatedArray<RuleData>* rules = ruleSet.idRules(str); + ASSERT_EQ(1u, rules->size()); + ASSERT_EQ(str, rules->at(0).selector().value()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_AttrThenId) +{ + CSSTestHelper helper; + + helper.addCSSRules("[attr]#id { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("id"); + const TerminatedArray<RuleData>* rules = ruleSet.idRules(str); + ASSERT_EQ(1u, rules->size()); + AtomicString attrStr("attr"); + ASSERT_EQ(attrStr, rules->at(0).selector().attribute().localName()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_TagThenAttrThenId) +{ + CSSTestHelper helper; + + helper.addCSSRules("div[attr]#id { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("id"); + const TerminatedArray<RuleData>* rules = ruleSet.idRules(str); + ASSERT_EQ(1u, rules->size()); + AtomicString tagStr("div"); + ASSERT_EQ(tagStr, rules->at(0).selector().tagQName().localName()); +} + +TEST(RuleSetTest, findBestRuleSetAndAdd_DivWithContent) +{ + CSSTestHelper helper; + + helper.addCSSRules("div::content { }"); + RuleSet& ruleSet = helper.ruleSet(); + AtomicString str("div"); + const TerminatedArray<RuleData>* rules = ruleSet.tagRules(str); + ASSERT_EQ(1u, rules->size()); + AtomicString valueStr("content"); + ASSERT_EQ(valueStr, rules->at(0).selector().value()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.cpp b/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.cpp index 7e0d728e2b8..dd9796bfc9d 100644 --- a/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.cpp +++ b/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.cpp @@ -30,12 +30,12 @@ #include "config.h" #include "core/css/RuntimeCSSEnabled.h" -#include "RuntimeEnabledFeatures.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "wtf/BitArray.h" namespace WebCore { -// FIXME: We should use a real BitVector class instead! -typedef Vector<bool> BoolVector; +typedef BitArray<numCSSProperties> CSSPropertySwitches; static void setCSSPropertiesEnabled(CSSPropertyID* properties, size_t length, bool featureFlag) { @@ -45,15 +45,6 @@ static void setCSSPropertiesEnabled(CSSPropertyID* properties, size_t length, bo static void setPropertySwitchesFromRuntimeFeatures() { - CSSPropertyID regionProperites[] = { - CSSPropertyWebkitFlowInto, - CSSPropertyWebkitFlowFrom, - CSSPropertyWebkitRegionFragment, - CSSPropertyWebkitRegionBreakAfter, - CSSPropertyWebkitRegionBreakBefore, - CSSPropertyWebkitRegionBreakInside - }; - setCSSPropertiesEnabled(regionProperites, WTF_ARRAY_LENGTH(regionProperites), RuntimeEnabledFeatures::cssRegionsEnabled()); CSSPropertyID exclusionProperties[] = { CSSPropertyWebkitWrapFlow, CSSPropertyWebkitWrapThrough, @@ -61,9 +52,7 @@ static void setPropertySwitchesFromRuntimeFeatures() setCSSPropertiesEnabled(exclusionProperties, WTF_ARRAY_LENGTH(exclusionProperties), RuntimeEnabledFeatures::cssExclusionsEnabled()); CSSPropertyID shapeProperties[] = { CSSPropertyShapeMargin, - CSSPropertyShapePadding, CSSPropertyShapeImageThreshold, - CSSPropertyShapeInside, CSSPropertyShapeOutside, }; setCSSPropertiesEnabled(shapeProperties, WTF_ARRAY_LENGTH(shapeProperties), RuntimeEnabledFeatures::cssShapesEnabled()); @@ -82,8 +71,8 @@ static void setPropertySwitchesFromRuntimeFeatures() CSSPropertyID cssGridLayoutProperties[] = { CSSPropertyGridAutoColumns, CSSPropertyGridAutoRows, - CSSPropertyGridDefinitionColumns, - CSSPropertyGridDefinitionRows, + CSSPropertyGridTemplateColumns, + CSSPropertyGridTemplateRows, CSSPropertyGridColumnStart, CSSPropertyGridColumnEnd, CSSPropertyGridRowStart, @@ -92,7 +81,10 @@ static void setPropertySwitchesFromRuntimeFeatures() CSSPropertyGridRow, CSSPropertyGridArea, CSSPropertyGridAutoFlow, - CSSPropertyGridTemplate + CSSPropertyGridTemplateAreas, + CSSPropertyGridTemplate, + CSSPropertyGrid, + CSSPropertyJustifySelf }; setCSSPropertiesEnabled(cssGridLayoutProperties, WTF_ARRAY_LENGTH(cssGridLayoutProperties), RuntimeEnabledFeatures::cssGridLayoutEnabled()); CSSPropertyID cssObjectFitPositionProperties[] = { @@ -114,26 +106,34 @@ static void setPropertySwitchesFromRuntimeFeatures() }; setCSSPropertiesEnabled(animationProperties, WTF_ARRAY_LENGTH(animationProperties), RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()); - RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyBackgroundBlendMode, RuntimeEnabledFeatures::cssCompositingEnabled()); + CSSPropertyID transformProperties[] = { + CSSPropertyBackfaceVisibility, + CSSPropertyPerspective, + CSSPropertyPerspectiveOrigin, + CSSPropertyTransform, + CSSPropertyTransformOrigin, + CSSPropertyTransformStyle + }; + setCSSPropertiesEnabled(transformProperties, WTF_ARRAY_LENGTH(transformProperties), RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); + RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyMixBlendMode, RuntimeEnabledFeatures::cssCompositingEnabled()); RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyIsolation, RuntimeEnabledFeatures::cssCompositingEnabled()); RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyTouchAction, RuntimeEnabledFeatures::cssTouchActionEnabled()); - RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyPaintOrder, RuntimeEnabledFeatures::svgPaintOrderEnabled()); - RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyVariable, RuntimeEnabledFeatures::cssVariablesEnabled()); + RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyTouchActionDelay, RuntimeEnabledFeatures::cssTouchActionDelayEnabled()); RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyMaskSourceType, RuntimeEnabledFeatures::cssMaskSourceTypeEnabled()); RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyColumnFill, RuntimeEnabledFeatures::regionBasedColumnsEnabled()); + RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyScrollBehavior, RuntimeEnabledFeatures::cssomSmoothScrollEnabled()); + RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyWillChange, RuntimeEnabledFeatures::cssWillChangeEnabled()); // InternalCallback is an implementation detail, rather than an experimental feature, and should never be exposed to the web. RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyInternalCallback, false); } -static BoolVector& propertySwitches() +static CSSPropertySwitches& propertySwitches() { - static BoolVector* switches = 0; + static CSSPropertySwitches* switches = 0; if (!switches) { - switches = new BoolVector; - // Accomodate CSSPropertyIDs that fall outside the firstCSSProperty, lastCSSProperty range (eg. CSSPropertyVariable). - switches->fill(true, lastCSSProperty + 1); + switches = new CSSPropertySwitches(true); // All bits sets to 1. setPropertySwitchesFromRuntimeFeatures(); } return *switches; @@ -141,9 +141,9 @@ static BoolVector& propertySwitches() size_t indexForProperty(CSSPropertyID propertyId) { - RELEASE_ASSERT(propertyId >= 0 && propertyId <= lastCSSProperty); - ASSERT(propertyId != CSSPropertyInvalid); - return static_cast<size_t>(propertyId); + RELEASE_ASSERT(propertyId >= firstCSSProperty && propertyId <= lastCSSProperty); + // Values all start at 0. BitArray ASSERTS will catch if we're ever wrong. + return static_cast<size_t>(propertyId - firstCSSProperty); } bool RuntimeCSSEnabled::isCSSPropertyEnabled(CSSPropertyID propertyId) @@ -153,12 +153,16 @@ bool RuntimeCSSEnabled::isCSSPropertyEnabled(CSSPropertyID propertyId) if (isInternalProperty(propertyId)) return false; - return propertySwitches()[indexForProperty(propertyId)]; + return propertySwitches().get(indexForProperty(propertyId)); } void RuntimeCSSEnabled::setCSSPropertyEnabled(CSSPropertyID propertyId, bool enable) { - propertySwitches()[indexForProperty(propertyId)] = enable; + size_t propertyIndex = indexForProperty(propertyId); + if (enable) + propertySwitches().set(propertyIndex); + else + propertySwitches().clear(propertyIndex); } void RuntimeCSSEnabled::filterEnabledCSSPropertiesIntoVector(const CSSPropertyID* properties, size_t propertyCount, Vector<CSSPropertyID>& outVector) diff --git a/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.h b/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.h index 493d3a52356..bb7900f1c21 100644 --- a/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.h +++ b/chromium/third_party/WebKit/Source/core/css/RuntimeCSSEnabled.h @@ -30,7 +30,7 @@ #ifndef RuntimeCSSEnabled_h #define RuntimeCSSEnabled_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "wtf/Vector.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/core/css/SVGCSSComputedStyleDeclaration.cpp b/chromium/third_party/WebKit/Source/core/css/SVGCSSComputedStyleDeclaration.cpp index c972f873786..584b67705a6 100644 --- a/chromium/third_party/WebKit/Source/core/css/SVGCSSComputedStyleDeclaration.cpp +++ b/chromium/third_party/WebKit/Source/core/css/SVGCSSComputedStyleDeclaration.cpp @@ -22,7 +22,7 @@ #include "core/css/CSSComputedStyleDeclaration.h" -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/dom/Document.h" #include "core/rendering/style/RenderStyle.h" @@ -30,7 +30,7 @@ namespace WebCore { -static PassRefPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphOrientation orientation) { switch (orientation) { case GO_0DEG: @@ -42,26 +42,29 @@ static PassRefPtr<CSSPrimitiveValue> glyphOrientationToCSSPrimitiveValue(EGlyphO case GO_270DEG: return CSSPrimitiveValue::create(270.0f, CSSPrimitiveValue::CSS_DEG); default: - return 0; + return nullptr; } } -static PassRefPtr<CSSValue> strokeDashArrayToCSSValueList(const Vector<SVGLength>& dashes) +static PassRefPtrWillBeRawPtr<CSSValue> strokeDashArrayToCSSValueList(PassRefPtr<SVGLengthList> passDashes) { - if (dashes.isEmpty()) + RefPtr<SVGLengthList> dashes = passDashes; + + if (dashes->isEmpty()) return CSSPrimitiveValue::createIdentifier(CSSValueNone); - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - const Vector<SVGLength>::const_iterator end = dashes.end(); - for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it) + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + SVGLengthList::ConstIterator it = dashes->begin(); + SVGLengthList::ConstIterator itEnd = dashes->end(); + for (; it != itEnd; ++it) list->append(SVGLength::toCSSPrimitiveValue(*it)); return list.release(); } -static PassRefPtr<CSSValue> paintOrderToCSSValueList(EPaintOrder paintorder) +static PassRefPtrWillBeRawPtr<CSSValue> paintOrderToCSSValueList(EPaintOrder paintorder) { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); do { EPaintOrderType paintOrderType = (EPaintOrderType)(paintorder & ((1 << kPaintOrderBitwidth) - 1)); switch (paintOrderType) { @@ -80,19 +83,24 @@ static PassRefPtr<CSSValue> paintOrderToCSSValueList(EPaintOrder paintorder) return list.release(); } -PassRefPtr<SVGPaint> CSSComputedStyleDeclaration::adjustSVGPaintForCurrentColor(PassRefPtr<SVGPaint> newPaint, RenderStyle& style) const +PassRefPtrWillBeRawPtr<SVGPaint> CSSComputedStyleDeclaration::adjustSVGPaintForCurrentColor(PassRefPtrWillBeRawPtr<SVGPaint> newPaint, RenderStyle& style) const { - RefPtr<SVGPaint> paint = newPaint; + RefPtrWillBeRawPtr<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(CSSPropertyID propertyID, EUpdateLayout updateLayout) const +static inline String serializeAsFragmentIdentifier(const AtomicString& resource) +{ + return "#" + resource; +} + +PassRefPtrWillBeRawPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const { Node* node = m_node.get(); if (!node) - return 0; + return nullptr; // Make sure our layout is up to date before we allow a query on these attributes. if (updateLayout) @@ -100,11 +108,11 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSProp RenderStyle* style = node->computedStyle(); if (!style) - return 0; + return nullptr; const SVGRenderStyle* svgStyle = style->svgStyle(); if (!svgStyle) - return 0; + return nullptr; switch (propertyID) { case CSSPropertyClipRule: @@ -143,15 +151,15 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSProp return CSSPrimitiveValue::create(svgStyle->writingMode()); case CSSPropertyClipPath: if (!svgStyle->clipperResource().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->clipperResource(), CSSPrimitiveValue::CSS_URI); + return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle->clipperResource()), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyMask: if (!svgStyle->maskerResource().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->maskerResource(), CSSPrimitiveValue::CSS_URI); + return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle->maskerResource()), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyFilter: if (!svgStyle->filterResource().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->filterResource(), CSSPrimitiveValue::CSS_URI); + return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle->filterResource()), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyFloodColor: return currentColorOrValidColor(*style, svgStyle->floodColor()); @@ -161,19 +169,17 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSProp return currentColorOrValidColor(*style, svgStyle->stopColor()); case CSSPropertyFill: return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle->fillPaintType(), svgStyle->fillPaintUri(), svgStyle->fillPaintColor()), *style); - case CSSPropertyKerning: - return SVGLength::toCSSPrimitiveValue(svgStyle->kerning()); case CSSPropertyMarkerEnd: if (!svgStyle->markerEndResource().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->markerEndResource(), CSSPrimitiveValue::CSS_URI); + return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle->markerEndResource()), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyMarkerMid: if (!svgStyle->markerMidResource().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->markerMidResource(), CSSPrimitiveValue::CSS_URI); + return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle->markerMidResource()), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyMarkerStart: if (!svgStyle->markerStartResource().isEmpty()) - return CSSPrimitiveValue::create(svgStyle->markerStartResource(), CSSPrimitiveValue::CSS_URI); + return CSSPrimitiveValue::create(serializeAsFragmentIdentifier(svgStyle->markerStartResource()), CSSPrimitiveValue::CSS_URI); return CSSPrimitiveValue::createIdentifier(CSSValueNone); case CSSPropertyStroke: return adjustSVGPaintForCurrentColor(SVGPaint::create(svgStyle->strokePaintType(), svgStyle->strokePaintUri(), svgStyle->strokePaintColor()), *style); @@ -195,20 +201,20 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSProp return SVGLength::toCSSPrimitiveValue(svgStyle->baselineShiftValue()); } ASSERT_NOT_REACHED(); - return 0; + return nullptr; } case CSSPropertyBufferedRendering: return CSSPrimitiveValue::create(svgStyle->bufferedRendering()); case CSSPropertyGlyphOrientationHorizontal: return glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationHorizontal()); case CSSPropertyGlyphOrientationVertical: { - if (RefPtr<CSSPrimitiveValue> value = glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationVertical())) + if (RefPtrWillBeRawPtr<CSSPrimitiveValue> value = glyphOrientationToCSSPrimitiveValue(svgStyle->glyphOrientationVertical())) return value.release(); if (svgStyle->glyphOrientationVertical() == GO_AUTO) return CSSPrimitiveValue::createIdentifier(CSSValueAuto); - return 0; + return nullptr; } case CSSPropertyPaintOrder: return paintOrderToCSSValueList(svgStyle->paintOrder()); @@ -218,7 +224,6 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSProp return CSSPrimitiveValue::create(svgStyle->maskType()); case CSSPropertyMarker: case CSSPropertyEnableBackground: - case CSSPropertyColorProfile: // the above properties are not yet implemented in the engine break; default: @@ -227,7 +232,7 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getSVGPropertyCSSValue(CSSProp ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propertyID); } WTF_LOG_ERROR("unimplemented propertyID: %d", propertyID); - return 0; + return nullptr; } } diff --git a/chromium/third_party/WebKit/Source/core/css/SVGCSSParser.cpp b/chromium/third_party/WebKit/Source/core/css/SVGCSSParser.cpp deleted file mode 100644 index 8c07b148933..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/SVGCSSParser.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/* - Copyright (C) 2008 Eric Seidel <eric@webkit.org> - Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> - 2004, 2005, 2007, 2010 Rob Buis <buis@kde.org> - Copyright (C) 2005, 2006 Apple Computer, Inc. - - 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. -*/ - -#include "config.h" - -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "RuntimeEnabledFeatures.h" -#include "core/css/CSSParser.h" -#include "core/css/CSSValueList.h" -#include "core/rendering/RenderTheme.h" -#include "core/svg/SVGPaint.h" - -using namespace std; - -namespace WebCore { - -static bool isSystemColor(int id) -{ - return (id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu; -} - -bool CSSParser::parseSVGValue(CSSPropertyID propId, bool important) -{ - CSSParserValue* value = m_valueList->current(); - if (!value) - return false; - - CSSValueID id = value->id; - - bool valid_primitive = false; - RefPtr<CSSValue> parsedValue; - - switch (propId) { - /* The comment to the right defines all valid value of these - * properties as defined in SVG 1.1, Appendix N. Property index */ - case CSSPropertyAlignmentBaseline: - // auto | baseline | before-edge | text-before-edge | middle | - // central | after-edge | text-after-edge | ideographic | alphabetic | - // hanging | mathematical | inherit - if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle || - (id >= CSSValueBeforeEdge && id <= CSSValueMathematical)) - valid_primitive = true; - break; - - case CSSPropertyBaselineShift: - // baseline | super | sub | <percentage> | <length> | inherit - if (id == CSSValueBaseline || id == CSSValueSub || - id >= CSSValueSuper) - valid_primitive = true; - else - valid_primitive = validUnit(value, FLength | FPercent, SVGAttributeMode); - break; - - case CSSPropertyDominantBaseline: - // auto | use-script | no-change | reset-size | ideographic | - // alphabetic | hanging | mathematical | central | middle | - // text-after-edge | text-before-edge | inherit - if (id == CSSValueAuto || id == CSSValueMiddle || - (id >= CSSValueUseScript && id <= CSSValueResetSize) || - (id >= CSSValueCentral && id <= CSSValueMathematical)) - valid_primitive = true; - break; - - case CSSPropertyEnableBackground: - // accumulate | new [x] [y] [width] [height] | inherit - if (id == CSSValueAccumulate) // TODO : new - valid_primitive = true; - break; - - case CSSPropertyMarkerStart: - case CSSPropertyMarkerMid: - case CSSPropertyMarkerEnd: - case CSSPropertyMask: - if (id == CSSValueNone) - valid_primitive = true; - else if (value->unit == CSSPrimitiveValue::CSS_URI) { - parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI); - if (parsedValue) - m_valueList->next(); - } - break; - - case CSSPropertyClipRule: // nonzero | evenodd | inherit - case CSSPropertyFillRule: - if (id == CSSValueNonzero || id == CSSValueEvenodd) - valid_primitive = true; - break; - - case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit - valid_primitive = validUnit(value, FNumber | FNonNeg, SVGAttributeMode); - break; - - case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit - if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel) - valid_primitive = true; - break; - - case CSSPropertyStrokeLinecap: // butt | round | square | inherit - if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare) - valid_primitive = true; - break; - - case CSSPropertyStrokeOpacity: // <opacity-value> | inherit - case CSSPropertyFillOpacity: - case CSSPropertyStopOpacity: - case CSSPropertyFloodOpacity: - valid_primitive = (!id && validUnit(value, FNumber | FPercent, SVGAttributeMode)); - break; - - case CSSPropertyShapeRendering: - // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit - if (id == CSSValueAuto || id == CSSValueOptimizespeed || - id == CSSValueCrispedges || id == CSSValueGeometricprecision) - valid_primitive = true; - break; - - case CSSPropertyImageRendering: // auto | optimizeSpeed | - case CSSPropertyColorRendering: // optimizeQuality | inherit - if (id == CSSValueAuto || id == CSSValueOptimizespeed || - id == CSSValueOptimizequality) - valid_primitive = true; - break; - - case CSSPropertyBufferedRendering: // auto | dynamic | static - if (id == CSSValueAuto || id == CSSValueDynamic || id == CSSValueStatic) - valid_primitive = true; - break; - - case CSSPropertyColorProfile: // auto | sRGB | <name> | <uri> inherit - if (id == CSSValueAuto || id == CSSValueSrgb) - valid_primitive = true; - break; - - case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit - case CSSPropertyColorInterpolationFilters: - if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb) - valid_primitive = true; - break; - - /* Start of supported CSS properties with validation. This is needed for parseShortHand to work - * correctly and allows optimization in applyRule(..) - */ - - case CSSPropertyTextAnchor: // start | middle | end | inherit - if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd) - valid_primitive = true; - break; - - case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit - if (id == CSSValueAuto) { - valid_primitive = true; - break; - } - /* fallthrough intentional */ - case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit - if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) { - parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_DEG); - - if (parsedValue) - m_valueList->next(); - } - break; - - case CSSPropertyFill: // <paint> | inherit - case CSSPropertyStroke: // <paint> | inherit - { - if (id == CSSValueNone) - parsedValue = SVGPaint::createNone(); - else if (id == CSSValueCurrentcolor) - parsedValue = SVGPaint::createCurrentColor(); - else if (isSystemColor(id)) - parsedValue = SVGPaint::createColor(RenderTheme::theme().systemColor(id)); - else if (value->unit == CSSPrimitiveValue::CSS_URI) { - RGBA32 c = Color::transparent; - if (m_valueList->next()) { - if (parseColorFromValue(m_valueList->current(), c)) - parsedValue = SVGPaint::createURIAndColor(value->string, c); - else if (m_valueList->current()->id == CSSValueNone) - parsedValue = SVGPaint::createURIAndNone(value->string); - } - if (!parsedValue) - parsedValue = SVGPaint::createURI(value->string); - } else - parsedValue = parseSVGPaint(); - - if (parsedValue) - m_valueList->next(); - } - break; - - case CSSPropertyStopColor: // TODO : icccolor - case CSSPropertyFloodColor: - case CSSPropertyLightingColor: - if (isSystemColor(id)) - parsedValue = SVGColor::createFromColor(RenderTheme::theme().systemColor(id)); - else if ((id >= CSSValueAqua && id <= CSSValueTransparent) || - (id >= CSSValueAliceblue && id <= CSSValueYellowgreen) || id == CSSValueGrey) - parsedValue = SVGColor::createFromString(value->string); - else if (id == CSSValueCurrentcolor) - parsedValue = SVGColor::createCurrentColor(); - else // TODO : svgcolor (iccColor) - parsedValue = parseSVGColor(); - - if (parsedValue) - m_valueList->next(); - - break; - - case CSSPropertyPaintOrder: - if (!RuntimeEnabledFeatures::svgPaintOrderEnabled()) - return false; - - if (m_valueList->size() == 1 && id == CSSValueNormal) - valid_primitive = true; - else if ((parsedValue = parsePaintOrder())) - m_valueList->next(); - break; - - case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit - if (id == CSSValueNone || id == CSSValueNonScalingStroke) - valid_primitive = true; - break; - - case CSSPropertyWritingMode: - // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit - if (id == CSSValueLrTb || id == CSSValueRlTb || id == CSSValueTbRl || id == CSSValueLr || id == CSSValueRl || id == CSSValueTb) - valid_primitive = true; - break; - - case CSSPropertyStrokeWidth: // <length> | inherit - case CSSPropertyStrokeDashoffset: - valid_primitive = validUnit(value, FLength | FPercent, SVGAttributeMode); - break; - case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit - if (id == CSSValueNone) - valid_primitive = true; - else - parsedValue = parseSVGStrokeDasharray(); - - break; - - case CSSPropertyKerning: // auto | normal | <length> | inherit - if (id == CSSValueAuto || id == CSSValueNormal) - valid_primitive = true; - else - valid_primitive = validUnit(value, FLength, SVGAttributeMode); - break; - - case CSSPropertyClipPath: // <uri> | none | inherit - case CSSPropertyFilter: - if (id == CSSValueNone) - valid_primitive = true; - else if (value->unit == CSSPrimitiveValue::CSS_URI) { - parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitTypes) value->unit); - if (parsedValue) - m_valueList->next(); - } - break; - case CSSPropertyMaskType: // luminance | alpha | inherit - if (id == CSSValueLuminance || id == CSSValueAlpha) - valid_primitive = true; - break; - - /* shorthand properties */ - case CSSPropertyMarker: - { - ShorthandScope scope(this, propId); - CSSParser::ImplicitScope implicitScope(this, PropertyImplicit); - if (!parseValue(CSSPropertyMarkerStart, important)) - return false; - if (m_valueList->current()) { - rollbackLastProperties(1); - return false; - } - CSSValue* value = m_parsedProperties.last().value(); - addProperty(CSSPropertyMarkerMid, value, important); - addProperty(CSSPropertyMarkerEnd, value, important); - return true; - } - default: - // If you crash here, it's because you added a css property and are not handling it - // in either this switch statement or the one in CSSParser::parseValue - ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); - return false; - } - - if (valid_primitive) { - if (id != 0) - parsedValue = CSSPrimitiveValue::createIdentifier(id); - else if (value->unit == CSSPrimitiveValue::CSS_STRING) - parsedValue = CSSPrimitiveValue::create(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); - else if (value->unit >= CSSParserValue::Q_EMS) - parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); - if (isCalculation(value)) { - // FIXME calc() http://webkit.org/b/16662 : actually create a CSSPrimitiveValue here, ie - // parsedValue = CSSPrimitiveValue::create(m_parsedCalculation.release()); - m_parsedCalculation.release(); - parsedValue = 0; - } - m_valueList->next(); - } - if (!parsedValue || (m_valueList->current() && !inShorthand())) - return false; - - addProperty(propId, parsedValue.release(), important); - return true; -} - -PassRefPtr<CSSValue> CSSParser::parseSVGStrokeDasharray() -{ - RefPtr<CSSValueList> ret = CSSValueList::createCommaSeparated(); - CSSParserValue* value = m_valueList->current(); - bool valid_primitive = true; - while (value) { - valid_primitive = validUnit(value, FLength | FPercent | FNonNeg, SVGAttributeMode); - if (!valid_primitive) - break; - if (value->id != 0) - ret->append(CSSPrimitiveValue::createIdentifier(value->id)); - else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) - ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit)); - value = m_valueList->next(); - if (value && value->unit == CSSParserValue::Operator && value->iValue == ',') - value = m_valueList->next(); - } - if (!valid_primitive) - return 0; - return ret.release(); -} - -PassRefPtr<CSSValue> CSSParser::parseSVGPaint() -{ - RGBA32 c = Color::transparent; - if (!parseColorFromValue(m_valueList->current(), c)) - return SVGPaint::createUnknown(); - return SVGPaint::createColor(Color(c)); -} - -PassRefPtr<CSSValue> CSSParser::parseSVGColor() -{ - RGBA32 c = Color::transparent; - if (!parseColorFromValue(m_valueList->current(), c)) - return 0; - return SVGColor::createFromColor(Color(c)); -} - -// normal | [ fill || stroke || markers ] -PassRefPtr<CSSValue> CSSParser::parsePaintOrder() const -{ - if (m_valueList->size() > 3) - return 0; - - CSSParserValue* value = m_valueList->current(); - if (!value) - return 0; - - RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); - - // The default paint-order is: Fill, Stroke, Markers. - bool seenFill = false, - seenStroke = false, - seenMarkers = false; - - do { - switch (value->id) { - case CSSValueNormal: - // normal inside [fill || stroke || markers] not valid - return 0; - case CSSValueFill: - if (seenFill) - return 0; - - seenFill = true; - break; - case CSSValueStroke: - if (seenStroke) - return 0; - - seenStroke = true; - break; - case CSSValueMarkers: - if (seenMarkers) - return 0; - - seenMarkers = true; - break; - default: - return 0; - } - - parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); - } while ((value = m_valueList->next())); - - // fill out the rest of the paint order - if (!seenFill) - parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueFill)); - if (!seenStroke) - parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke)); - if (!seenMarkers) - parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers)); - - return parsedValues.release(); -} - -} diff --git a/chromium/third_party/WebKit/Source/core/css/SVGCSSPropertyNames.in b/chromium/third_party/WebKit/Source/core/css/SVGCSSPropertyNames.in index 1cf28711f0f..98fb81438de 100644 --- a/chromium/third_party/WebKit/Source/core/css/SVGCSSPropertyNames.in +++ b/chromium/third_party/WebKit/Source/core/css/SVGCSSPropertyNames.in @@ -18,7 +18,6 @@ stop-opacity // pointer-events color-interpolation color-interpolation-filters -color-profile color-rendering fill fill-opacity @@ -45,7 +44,6 @@ baseline-shift dominant-baseline glyph-orientation-horizontal glyph-orientation-vertical -kerning text-anchor vector-effect writing-mode diff --git a/chromium/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in b/chromium/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in index ccfad3ca78f..b4260b76325 100644 --- a/chromium/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in +++ b/chromium/third_party/WebKit/Source/core/css/SVGCSSValueKeywords.in @@ -259,7 +259,6 @@ reset-size // CSS_PROP_GLYPH_ORIENTATION_HORIZONTAL // CSS_PROP_GLYPH_ORIENTATION_VERTICAL -// CSS_PROP_KERNING // CSS_PROP_TEXT_ANCHOR // start // middle diff --git a/chromium/third_party/WebKit/Source/core/css/SelectorChecker.cpp b/chromium/third_party/WebKit/Source/core/css/SelectorChecker.cpp index 15474cedd1d..3c6755a57fc 100644 --- a/chromium/third_party/WebKit/Source/core/css/SelectorChecker.cpp +++ b/chromium/third_party/WebKit/Source/core/css/SelectorChecker.cpp @@ -28,27 +28,26 @@ #include "config.h" #include "core/css/SelectorChecker.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/css/CSSSelectorList.h" #include "core/css/SiblingTraversalStrategies.h" #include "core/dom/Document.h" +#include "core/dom/ElementTraversal.h" #include "core/dom/FullscreenElementStack.h" #include "core/dom/NodeRenderStyle.h" #include "core/dom/Text.h" #include "core/dom/shadow/InsertionPoint.h" #include "core/dom/shadow/ShadowRoot.h" #include "core/editing/FrameSelection.h" -#include "core/html/HTMLAnchorElement.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLDocument.h" #include "core/html/HTMLFrameElementBase.h" #include "core/html/HTMLInputElement.h" -#include "core/html/HTMLOptGroupElement.h" #include "core/html/HTMLOptionElement.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/html/track/vtt/VTTElement.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/page/FocusController.h" -#include "core/frame/Frame.h" #include "core/rendering/RenderObject.h" #include "core/rendering/RenderScrollbar.h" #include "core/rendering/style/RenderStyle.h" @@ -66,32 +65,39 @@ SelectorChecker::SelectorChecker(Document& document, Mode mode) { } -static bool matchesCustomPseudoElement(const Element* element, const CSSSelector* selector) +static bool matchesCustomPseudoElement(const Element* element, const CSSSelector& selector) { ShadowRoot* root = element->containingShadowRoot(); - if (!root) + if (!root || root->type() != ShadowRoot::UserAgentShadowRoot) return false; - const AtomicString& pseudoId = selector->pseudoType() == CSSSelector::PseudoWebKitCustomElement ? element->shadowPseudoId() : element->pseudo(); - if (pseudoId != selector->value()) - return false; - if (selector->pseudoType() == CSSSelector::PseudoWebKitCustomElement && root->type() != ShadowRoot::UserAgentShadowRoot) + if (element->shadowPseudoId() != selector.value()) return false; + return true; } -Element* SelectorChecker::parentElement(const SelectorCheckingContext& context) const +Element* SelectorChecker::parentElement(const SelectorCheckingContext& context, bool allowToCrossBoundary) const { // CrossesBoundary means we don't care any context.scope. So we can walk up from a shadow root to its shadow host. - if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) == SelectorChecker::CrossesBoundary) + if (allowToCrossBoundary) + return context.element->parentOrShadowHostElement(); + + // If context.scope is a shadow root, we should walk up to its shadow host. + if ((context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot) && context.scope == context.element->containingShadowRoot()) return context.element->parentOrShadowHostElement(); - // If context.scope is not a shadow host, we cannot walk up from a shadow root to its shadow host. - if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost)) + if ((context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope) return context.element->parentElement(); - // If behaviorAtBoundary is StaysWithInTreeScope, we cannot walk up from a shadow root to its shadow host. - return (context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope ? context.element->parentOrShadowHostElement() : context.element->parentElement(); + // If context.scope is some element in some shadow tree and querySelector initialized the context, + // e.g. shadowRoot.querySelector(':host *'), + // (a) context.element has the same treescope as context.scope, need to walk up to its shadow host. + // (b) Otherwise, should not walk up from a shadow root to a shadow host. + if (context.scope && context.scope->treeScope() == context.element->treeScope()) + return context.element->parentOrShadowHostElement(); + + return context.element->parentElement(); } bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingContext& context) const @@ -100,25 +106,21 @@ bool SelectorChecker::scopeContainsLastMatchedElement(const SelectorCheckingCont return true; ASSERT(context.scope); - // If behaviorAtBoundary is not ScopeIsShadowHost, we can use "contains". - if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowHost)) - return context.scope->contains(context.element); - - // If a given element is scope, i.e. shadow host, matches. - if (context.element == context.scope) + if (context.scope->treeScope() == context.element->treeScope()) return true; - ShadowRoot* root = context.element->containingShadowRoot(); - if (!root) - return false; - - // If a host of the containing shadow root is scope, matches. - return root->host() == context.scope; + // Because Blink treats a shadow host's TreeScope as a separate one from its descendent shadow roots, + // if the last matched element is a shadow host, the condition above isn't met, even though it + // should be. + return context.element == context.scope->shadowHost() && (!context.previousElement || context.previousElement->isInDescendantTreeOf(context.element)); } static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheckingContext& context) { - return context.element == context.scope && (context.behaviorAtBoundary & SelectorChecker::BoundaryBehaviorMask) != SelectorChecker::StaysWithinTreeScope; + if (context.scope && context.scope->isInShadowTree()) + return context.element == context.scope->shadowHost(); + + return false; } // Recursive check of selectors and combinators @@ -135,13 +137,16 @@ SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con if (!checkOne(context, siblingTraversalStrategy, &specificity)) return SelectorFailsLocally; - if (context.selector->m_match == CSSSelector::PseudoElement) { + if (context.selector->match() == CSSSelector::PseudoElement) { if (context.selector->isCustomPseudoElement()) { - if (!matchesCustomPseudoElement(context.element, context.selector)) + if (!matchesCustomPseudoElement(context.element, *context.selector)) return SelectorFailsLocally; } else if (context.selector->isContentPseudoElement()) { if (!context.element->isInShadowTree() || !context.element->isInsertionPoint()) return SelectorFailsLocally; + } else if (context.selector->isShadowPseudoElement()) { + if (!context.element->isInShadowTree() || !context.previousElement) + return SelectorFailsCompletely; } else { if ((!context.elementStyle && m_mode == ResolvingStyle) || m_mode == QueryingRules) return SelectorFailsLocally; @@ -155,8 +160,7 @@ SelectorChecker::Match SelectorChecker::match(const SelectorCheckingContext& con } // Prepare next selector - const CSSSelector* historySelector = context.selector->tagHistory(); - if (!historySelector) { + if (context.selector->isLastInTagHistory()) { if (scopeContainsLastMatchedElement(context)) { if (result) result->specificity += specificity; @@ -199,6 +203,11 @@ static inline SelectorChecker::SelectorCheckingContext prepareNextContextForRela return nextContext; } +static inline bool isAuthorShadowRoot(const Node* node) +{ + return node && node->isShadowRoot() && toShadowRoot(node)->type() == ShadowRoot::AuthorShadowRoot; +} + template<typename SiblingTraversalStrategy> SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const { @@ -212,17 +221,31 @@ SelectorChecker::Match SelectorChecker::matchForSubSelector(const SelectorChecki nextContext.hasSelectionPseudo = dynamicPseudo == SELECTION; if ((context.elementStyle || m_mode == CollectingCSSRules || m_mode == CollectingStyleRules || m_mode == QueryingRules) && dynamicPseudo != NOPSEUDO && !nextContext.hasSelectionPseudo - && !(nextContext.hasScrollbarPseudo && nextContext.selector->m_match == CSSSelector::PseudoClass)) + && !(nextContext.hasScrollbarPseudo && nextContext.selector->match() == CSSSelector::PseudoClass)) return SelectorFailsCompletely; nextContext.isSubSelector = true; return match(nextContext, siblingTraversalStrategy, result); } +static bool selectorMatchesShadowRoot(const CSSSelector* selector) +{ + return selector && selector->isShadowPseudoElement(); +} + +template<typename SiblingTraversalStrategy> +SelectorChecker::Match SelectorChecker::matchForPseudoShadow(const ContainerNode* node, const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const +{ + if (!isAuthorShadowRoot(node)) + return SelectorFailsCompletely; + return match(context, siblingTraversalStrategy, result); +} + template<typename SiblingTraversalStrategy> SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy, MatchResult* result) const { SelectorCheckingContext nextContext = prepareNextContextForRelation(context); + nextContext.previousElement = context.element; CSSSelector::Relation relation = context.selector->relation(); @@ -243,6 +266,10 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC } nextContext.isSubSelector = false; nextContext.elementStyle = 0; + + if (selectorMatchesShadowRoot(nextContext.selector)) + return matchForPseudoShadow(context.element->containingShadowRoot(), nextContext, siblingTraversalStrategy, result); + for (nextContext.element = parentElement(context); nextContext.element; nextContext.element = parentElement(nextContext)) { Match match = this->match(nextContext, siblingTraversalStrategy, result); if (match == SelectorMatches || match == SelectorFailsCompletely) @@ -256,20 +283,27 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC if (context.selector->relationIsAffectedByPseudoContent()) return matchForShadowDistributed(context.element, siblingTraversalStrategy, nextContext, result); + nextContext.isSubSelector = false; + nextContext.elementStyle = 0; + + if (selectorMatchesShadowRoot(nextContext.selector)) + return matchForPseudoShadow(context.element->parentNode(), nextContext, siblingTraversalStrategy, result); + nextContext.element = parentElement(context); if (!nextContext.element) return SelectorFailsCompletely; - - nextContext.isSubSelector = false; - nextContext.elementStyle = 0; return match(nextContext, siblingTraversalStrategy, result); } case CSSSelector::DirectAdjacent: + // Shadow roots can't have sibling elements + if (selectorMatchesShadowRoot(nextContext.selector)) + return SelectorFailsCompletely; + if (m_mode == ResolvingStyle) { - if (Element* parent = parentElement(context)) + if (ContainerNode* parent = context.element->parentElementOrShadowRoot()) parent->setChildrenAffectedByDirectAdjacentRules(); } - nextContext.element = context.element->previousElementSibling(); + nextContext.element = ElementTraversal::previousSibling(*context.element); if (!nextContext.element) return SelectorFailsAllSiblings; nextContext.isSubSelector = false; @@ -277,14 +311,18 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC return match(nextContext, siblingTraversalStrategy, result); case CSSSelector::IndirectAdjacent: + // Shadow roots can't have sibling elements + if (selectorMatchesShadowRoot(nextContext.selector)) + return SelectorFailsCompletely; + if (m_mode == ResolvingStyle) { - if (Element* parent = parentElement(context)) - parent->setChildrenAffectedByForwardPositionalRules(); + if (ContainerNode* parent = context.element->parentElementOrShadowRoot()) + parent->setChildrenAffectedByIndirectAdjacentRules(); } - nextContext.element = context.element->previousElementSibling(); + nextContext.element = ElementTraversal::previousSibling(*context.element); nextContext.isSubSelector = false; nextContext.elementStyle = 0; - for (; nextContext.element; nextContext.element = nextContext.element->previousElementSibling()) { + for (; nextContext.element; nextContext.element = ElementTraversal::previousSibling(*nextContext.element)) { Match match = this->match(nextContext, siblingTraversalStrategy, result); if (match == SelectorMatches || match == SelectorFailsAllSiblings || match == SelectorFailsCompletely) return match; @@ -292,10 +330,9 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC return SelectorFailsAllSiblings; case CSSSelector::ShadowPseudo: - case CSSSelector::ChildTree: { // If we're in the same tree-scope as the scoping element, then following a shadow descendant combinator would escape that and thus the scope. - if (context.scope && context.scope->treeScope() == context.element->treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithinTreeScope) + if (context.scope && context.scope->shadowHost() && context.scope->shadowHost()->treeScope() == context.element->treeScope() && (context.behaviorAtBoundary & BoundaryBehaviorMask) != StaysWithinTreeScope) return SelectorFailsCompletely; Element* shadowHost = context.element->shadowHost(); @@ -307,11 +344,11 @@ SelectorChecker::Match SelectorChecker::matchForRelation(const SelectorCheckingC return this->match(nextContext, siblingTraversalStrategy, result); } - case CSSSelector::DescendantTree: + case CSSSelector::ShadowDeep: { nextContext.isSubSelector = false; nextContext.elementStyle = 0; - for (nextContext.element = parentElement(context); nextContext.element; nextContext.element = parentElement(nextContext)) { + for (nextContext.element = parentElement(context, true); nextContext.element; nextContext.element = parentElement(nextContext, true)) { Match match = this->match(nextContext, siblingTraversalStrategy, result); if (match == SelectorMatches || match == SelectorFailsCompletely) return match; @@ -333,7 +370,7 @@ template<typename SiblingTraversalStrategy> SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* element, const SiblingTraversalStrategy& siblingTraversalStrategy, SelectorCheckingContext& nextContext, MatchResult* result) const { ASSERT(element); - Vector<InsertionPoint*, 8> insertionPoints; + WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; const ContainerNode* scope = nextContext.scope; BehaviorAtBoundary behaviorAtBoundary = nextContext.behaviorAtBoundary; @@ -342,32 +379,44 @@ SelectorChecker::Match SelectorChecker::matchForShadowDistributed(const Element* for (size_t i = 0; i < insertionPoints.size(); ++i) { nextContext.element = insertionPoints[i]; - // If a given scope is a shadow host of an insertion point but behaviorAtBoundary doesn't have ScopeIsShadowHost, + // If a given scope is a shadow host of an insertion point but behaviorAtBoundary doesn't have ScopeIsShadowRoot, // we need to update behaviorAtBoundary to make selectors like ":host > ::content" work correctly. - if (scope == insertionPoints[i]->containingShadowRoot()->shadowHost() && !(behaviorAtBoundary & ScopeIsShadowHost)) - nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowHost); - else + if (m_mode == SharingRules) { + nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowRoot); + nextContext.scope = insertionPoints[i]->containingShadowRoot(); + } else if (scope == insertionPoints[i]->containingShadowRoot() && !(behaviorAtBoundary & ScopeIsShadowRoot)) { + nextContext.behaviorAtBoundary = static_cast<BehaviorAtBoundary>(behaviorAtBoundary | ScopeIsShadowRoot); + } else { nextContext.behaviorAtBoundary = behaviorAtBoundary; + } nextContext.isSubSelector = false; nextContext.elementStyle = 0; if (match(nextContext, siblingTraversalStrategy, result) == SelectorMatches) return SelectorMatches; } - return SelectorFailsCompletely; + return SelectorFailsLocally; } -static inline bool containsHTMLSpace(const AtomicString& string) +template<typename CharType> +static inline bool containsHTMLSpaceTemplate(const CharType* string, unsigned length) { - for (unsigned i = 0; i < string.length(); i++) - if (isHTMLSpace<UChar>(string[i])) + for (unsigned i = 0; i < length; ++i) + if (isHTMLSpace<CharType>(string[i])) return true; return false; } -static bool attributeValueMatches(const Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive) +static inline bool containsHTMLSpace(const AtomicString& string) +{ + if (LIKELY(string.is8Bit())) + return containsHTMLSpaceTemplate<LChar>(string.characters8(), string.length()); + return containsHTMLSpaceTemplate<UChar>(string.characters16(), string.length()); +} + +static bool attributeValueMatches(const Attribute& attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive) { - const AtomicString& value = attributeItem->value(); + const AtomicString& value = attributeItem.value(); if (value.isNull()) return false; @@ -441,18 +490,28 @@ static bool anyAttributeMatches(Element& element, CSSSelector::Match match, cons return false; const AtomicString& selectorValue = selector.value(); - // Case sensitivity for attribute matching is looser than hasAttribute or - // Element::shouldIgnoreAttributeCase() for now. Unclear if that's correct. - bool caseSensitive = !element.document().isHTMLDocument() || HTMLDocument::isCaseSensitiveAttribute(selectorAttr); - for (size_t i = 0; i < element.attributeCount(); ++i) { - const Attribute* attributeItem = element.attributeItem(i); + AttributeCollection attributes = element.attributes(); + AttributeCollection::const_iterator end = attributes.end(); + for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { + const Attribute& attributeItem = *it; - if (!attributeItem->matches(selectorAttr)) + if (!attributeItem.matches(selectorAttr)) continue; - if (attributeValueMatches(attributeItem, match, selectorValue, caseSensitive)) + if (attributeValueMatches(attributeItem, match, selectorValue, true)) return true; + + // Case sensitivity for attribute matching is looser than hasAttribute or + // Element::shouldIgnoreAttributeCase() for now. Unclear if that's correct. + bool caseSensitive = !element.document().isHTMLDocument() || HTMLDocument::isCaseSensitiveAttribute(selectorAttr); + + // If case-insensitive, re-check, and count if result differs. + // See http://code.google.com/p/chromium/issues/detail?id=327060 + if (!caseSensitive && attributeValueMatches(attributeItem, match, selectorValue, false)) { + UseCounter::count(element.document(), UseCounter::CaseInsensitiveAttrSelectorMatch); + return true; + } } return false; @@ -463,33 +522,35 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib { ASSERT(context.element); Element& element = *context.element; - const CSSSelector* const & selector = context.selector; - ASSERT(selector); + ASSERT(context.selector); + const CSSSelector& selector = *context.selector; + bool elementIsHostInItsShadowTree = isHostInItsShadowTree(element, context.behaviorAtBoundary, context.scope); - if (selector->m_match == CSSSelector::Tag) - return SelectorChecker::tagMatches(element, selector->tagQName(), elementIsHostInItsShadowTree ? MatchingHostInItsShadowTree : MatchingElement); + // Only :host and :ancestor should match the host: http://drafts.csswg.org/css-scoping/#host-element + if (elementIsHostInItsShadowTree && !selector.isHostPseudoClass() + && !(context.behaviorAtBoundary & TreatShadowHostAsNormalScope)) + return false; - if (selector->m_match == CSSSelector::Class) - return element.hasClass() && element.classNames().contains(selector->value()) && !elementIsHostInItsShadowTree; + if (selector.match() == CSSSelector::Tag) + return SelectorChecker::tagMatches(element, selector.tagQName()); - if (selector->m_match == CSSSelector::Id) - return element.hasID() && element.idForStyleResolution() == selector->value() && !elementIsHostInItsShadowTree; + if (selector.match() == CSSSelector::Class) + return element.hasClass() && element.classNames().contains(selector.value()); - if (selector->isAttributeSelector()) { - if (elementIsHostInItsShadowTree) - return false; - if (!anyAttributeMatches(element, static_cast<CSSSelector::Match>(selector->m_match), *selector)) - return false; - } + if (selector.match() == CSSSelector::Id) + return element.hasID() && element.idForStyleResolution() == selector.value(); + + if (selector.isAttributeSelector()) + return anyAttributeMatches(element, selector.match(), selector); - if (selector->m_match == CSSSelector::PseudoClass) { + if (selector.match() == CSSSelector::PseudoClass) { // Handle :not up front. - if (selector->pseudoType() == CSSSelector::PseudoNot) { + if (selector.pseudoType() == CSSSelector::PseudoNot) { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; - ASSERT(selector->selectorList()); - for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) { + ASSERT(selector.selectorList()); + for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = subContext.selector->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 @@ -497,6 +558,10 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib // We select between :visited and :link when applying. We don't know which one applied (or not) yet. if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled)) return true; + // context.scope is not available if m_mode == SharingRules. + // We cannot determine whether :host or :scope matches a given element or not. + if (m_mode == SharingRules && (subContext.selector->isHostPseudoClass() || subContext.selector->pseudoType() == CSSSelector::PseudoScope)) + return true; if (!checkOne(subContext, DOMSiblingTraversalStrategy())) return true; } @@ -505,12 +570,12 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib // (since there are no elements involved). return checkScrollbarPseudoClass(context, &element.document(), selector); } else if (context.hasSelectionPseudo) { - if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) + if (selector.pseudoType() == CSSSelector::PseudoWindowInactive) return !element.document().page()->focusController().isActive(); } // Normal element pseudo class checking. - switch (selector->pseudoType()) { + switch (selector.pseudoType()) { // Pseudo classes: case CSSSelector::PseudoNot: break; // Already handled up above. @@ -541,8 +606,8 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib } case CSSSelector::PseudoFirstChild: // first-child matches the first child that is an element - if (Element* parent = element.parentElement()) { - bool result = siblingTraversalStrategy.isFirstChild(&element); + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { + bool result = siblingTraversalStrategy.isFirstChild(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle(); parent->setChildrenAffectedByFirstChildRules(); @@ -554,8 +619,8 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib break; case CSSSelector::PseudoFirstOfType: // first-of-type matches the first element of its type - if (Element* parent = element.parentElement()) { - bool result = siblingTraversalStrategy.isFirstOfType(&element, element.tagQName()); + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { + bool result = siblingTraversalStrategy.isFirstOfType(element, element.tagQName()); if (m_mode == ResolvingStyle) parent->setChildrenAffectedByForwardPositionalRules(); return result; @@ -563,8 +628,8 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib break; case CSSSelector::PseudoLastChild: // last-child matches the last child that is an element - if (Element* parent = element.parentElement()) { - bool result = parent->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(&element); + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { + bool result = parent->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle(); parent->setChildrenAffectedByLastChildRules(); @@ -576,18 +641,18 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib break; case CSSSelector::PseudoLastOfType: // last-of-type matches the last element of its type - if (Element* parent = element.parentElement()) { + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { if (m_mode == ResolvingStyle) parent->setChildrenAffectedByBackwardPositionalRules(); if (!parent->isFinishedParsingChildren()) return false; - return siblingTraversalStrategy.isLastOfType(&element, element.tagQName()); + return siblingTraversalStrategy.isLastOfType(element, element.tagQName()); } break; case CSSSelector::PseudoOnlyChild: - if (Element* parent = element.parentElement()) { - bool firstChild = siblingTraversalStrategy.isFirstChild(&element); - bool onlyChild = firstChild && parent->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(&element); + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { + bool firstChild = siblingTraversalStrategy.isFirstChild(element); + bool onlyChild = firstChild && parent->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle(); parent->setChildrenAffectedByFirstChildRules(); @@ -602,69 +667,68 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib break; case CSSSelector::PseudoOnlyOfType: // FIXME: This selector is very slow. - if (Element* parent = element.parentElement()) { + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { if (m_mode == ResolvingStyle) { parent->setChildrenAffectedByForwardPositionalRules(); parent->setChildrenAffectedByBackwardPositionalRules(); } if (!parent->isFinishedParsingChildren()) return false; - return siblingTraversalStrategy.isFirstOfType(&element, element.tagQName()) && siblingTraversalStrategy.isLastOfType(&element, element.tagQName()); + return siblingTraversalStrategy.isFirstOfType(element, element.tagQName()) && siblingTraversalStrategy.isLastOfType(element, element.tagQName()); } break; case CSSSelector::PseudoNthChild: - if (!selector->parseNth()) + if (!selector.parseNth()) break; - if (Element* parent = element.parentElement()) { - int count = 1 + siblingTraversalStrategy.countElementsBefore(&element); + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { + int count = 1 + siblingTraversalStrategy.countElementsBefore(element); if (m_mode == ResolvingStyle) { RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element.renderStyle(); - element.setChildIndex(count); if (childStyle) childStyle->setUnique(); parent->setChildrenAffectedByForwardPositionalRules(); } - if (selector->matchNth(count)) + if (selector.matchNth(count)) return true; } break; case CSSSelector::PseudoNthOfType: - if (!selector->parseNth()) + if (!selector.parseNth()) break; - if (Element* parent = element.parentElement()) { - int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefore(&element, element.tagQName()); + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { + int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefore(element, element.tagQName()); if (m_mode == ResolvingStyle) parent->setChildrenAffectedByForwardPositionalRules(); - if (selector->matchNth(count)) + if (selector.matchNth(count)) return true; } break; case CSSSelector::PseudoNthLastChild: - if (!selector->parseNth()) + if (!selector.parseNth()) break; - if (Element* parent = element.parentElement()) { + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { if (m_mode == ResolvingStyle) parent->setChildrenAffectedByBackwardPositionalRules(); if (!parent->isFinishedParsingChildren()) return false; - int count = 1 + siblingTraversalStrategy.countElementsAfter(&element); - if (selector->matchNth(count)) + int count = 1 + siblingTraversalStrategy.countElementsAfter(element); + if (selector.matchNth(count)) return true; } break; case CSSSelector::PseudoNthLastOfType: - if (!selector->parseNth()) + if (!selector.parseNth()) break; - if (Element* parent = element.parentElement()) { + if (ContainerNode* parent = element.parentElementOrDocumentFragment()) { if (m_mode == ResolvingStyle) parent->setChildrenAffectedByBackwardPositionalRules(); if (!parent->isFinishedParsingChildren()) return false; - int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfter(&element, element.tagQName()); - if (selector->matchNth(count)) + int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfter(element, element.tagQName()); + if (selector.matchNth(count)) return true; } break; @@ -676,8 +740,8 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; - ASSERT(selector->selectorList()); - for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { + ASSERT(selector.selectorList()); + for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { if (match(subContext, siblingTraversalStrategy) == SelectorMatches) return true; } @@ -699,7 +763,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib if (context.elementStyle) context.elementStyle->setAffectedByDrag(); else - element.setChildrenAffectedByDrag(); + element.setChildrenOrSiblingsAffectedByDrag(); } if (element.renderer() && element.renderer()->isDragging()) return true; @@ -709,18 +773,18 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib if (context.elementStyle) context.elementStyle->setAffectedByFocus(); else - element.setChildrenAffectedByFocus(); + element.setChildrenOrSiblingsAffectedByFocus(); } return matchesFocusPseudoClass(element); case CSSSelector::PseudoHover: // If we're in quirks mode, then hover should never match anchors with no // href and *:hover should not match anything. This is important for sites like wsj.com. - if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !isHTMLAnchorElement(element)) || element.isLink()) { + if (m_strictParsing || context.isSubSelector || element.isLink()) { if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByHover(); else - element.setChildrenAffectedByHover(); + element.setChildrenOrSiblingsAffectedByHover(); } if (element.hovered() || InspectorInstrumentation::forcePseudoState(&element, CSSSelector::PseudoHover)) return true; @@ -729,19 +793,19 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib case CSSSelector::PseudoActive: // If we're in quirks mode, then :active should never match anchors with no // href and *:active should not match anything. - if (m_strictParsing || context.isSubSelector || (selector->m_match == CSSSelector::Tag && selector->tagQName() != anyQName() && !isHTMLAnchorElement(element)) || element.isLink()) { + if (m_strictParsing || context.isSubSelector || element.isLink()) { if (m_mode == ResolvingStyle) { if (context.elementStyle) context.elementStyle->setAffectedByActive(); else - element.setChildrenAffectedByActive(); + element.setChildrenOrSiblingsAffectedByActive(); } if (element.active() || InspectorInstrumentation::forcePseudoState(&element, CSSSelector::PseudoActive)) return true; } break; case CSSSelector::PseudoEnabled: - if (element.isFormControlElement() || element.hasTagName(optionTag) || isHTMLOptGroupElement(element)) + if (element.isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) return !element.isDisabledFormControl(); break; case CSSSelector::PseudoFullPageMedia: @@ -750,7 +814,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib case CSSSelector::PseudoDefault: return element.isDefaultButtonForForm(); case CSSSelector::PseudoDisabled: - if (element.isFormControlElement() || element.hasTagName(optionTag) || isHTMLOptGroupElement(element)) + if (element.isFormControlElement() || isHTMLOptionElement(element) || isHTMLOptGroupElement(element)) return element.isDisabledFormControl(); break; case CSSSelector::PseudoReadOnly: @@ -769,7 +833,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib return element.willValidate() && !element.isValidFormControlElement(); case CSSSelector::PseudoChecked: { - if (element.hasTagName(inputTag)) { + if (isHTMLInputElement(element)) { HTMLInputElement& inputElement = toHTMLInputElement(element); // Even though WinIE allows checked and indeterminate to // co-exist, the CSS selector spec says that you can't be @@ -778,7 +842,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib // test for matching the pseudo. if (inputElement.shouldAppearChecked() && !inputElement.shouldAppearIndeterminate()) return true; - } else if (element.hasTagName(optionTag) && toHTMLOptionElement(element).selected()) + } else if (isHTMLOptionElement(element) && toHTMLOptionElement(element).selected()) return true; break; } @@ -795,7 +859,7 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib value = toVTTElement(element).language(); else value = element.computeInheritedLanguage(); - const AtomicString& argument = selector->argument(); + const AtomicString& argument = selector.argument(); if (value.isEmpty() || !value.startsWith(argument, false)) break; if (value.length() != argument.length() && value[argument.length()] != '-') @@ -807,9 +871,9 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib // element is an element in the document, the 'full-screen' pseudoclass applies to // that element. Also, an <iframe>, <object> or <embed> element whose child browsing // context's Document is in the fullscreen state has the 'full-screen' pseudoclass applied. - if (element.isFrameElementBase() && element.containsFullScreenElement()) + if (isHTMLFrameElementBase(element) && element.containsFullScreenElement()) return true; - if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(&element.document())) { + if (FullscreenElementStack* fullscreen = FullscreenElementStack::fromIfExists(element.document())) { if (!fullscreen->webkitIsFullScreen()) return false; return element == fullscreen->webkitCurrentFullScreenElement(); @@ -820,13 +884,9 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib case CSSSelector::PseudoFullScreenDocument: // While a Document is in the fullscreen state, the 'full-screen-document' pseudoclass applies // to all elements of that Document. - if (!FullscreenElementStack::isFullScreen(&element.document())) + if (!FullscreenElementStack::isFullScreen(element.document())) return false; return true; - case CSSSelector::PseudoSeamlessDocument: - // While a document is rendered in a seamless iframe, the 'seamless-document' pseudoclass applies - // to all elements of that Document. - return element.document().shouldDisplaySeamlesslyWithParent(); case CSSSelector::PseudoInRange: element.document().setContainsValidityStyleRules(); return element.isInRange(); @@ -840,7 +900,9 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib case CSSSelector::PseudoScope: { - const Node* contextualReferenceNode = !context.scope || (context.behaviorAtBoundary & BoundaryBehaviorMask) == CrossesBoundary ? element.document().documentElement() : context.scope; + if (m_mode == SharingRules) + return true; + const Node* contextualReferenceNode = !context.scope ? element.document().documentElement() : context.scope; if (element == contextualReferenceNode) return true; break; @@ -852,14 +914,20 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib break; case CSSSelector::PseudoHost: + case CSSSelector::PseudoHostContext: { + if (m_mode == SharingRules) + return true; // :host only matches a shadow host when :host is in a shadow tree of the shadow host. - if (!context.scope || !(context.behaviorAtBoundary & ScopeIsShadowHost) || context.scope != element) + if (!context.scope) + return false; + const ContainerNode* shadowHost = context.scope->shadowHost(); + if (!shadowHost || shadowHost != element) return false; ASSERT(element.shadow()); // For empty parameter case, i.e. just :host or :host(). - if (!selector->selectorList()) // Use *'s specificity. So just 0. + if (!selector.selectorList()) // Use *'s specificity. So just 0. return true; SelectorCheckingContext subContext(context); @@ -869,22 +937,30 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib unsigned maxSpecificity = 0; // If one of simple selectors matches an element, returns SelectorMatches. Just "OR". - for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { + for (subContext.selector = selector.selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { subContext.behaviorAtBoundary = ScopeIsShadowHostInPseudoHostParameter; subContext.scope = context.scope; // Use NodeRenderingTraversal to traverse a composed ancestor list of a given element. - for (Element* nextElement = &element; nextElement; nextElement = NodeRenderingTraversal::parentElement(nextElement)) { + Element* nextElement = &element; + SelectorCheckingContext hostContext(subContext); + do { MatchResult subResult; - subContext.element = nextElement; - if (match(subContext, siblingTraversalStrategy, &subResult) == SelectorMatches) { + hostContext.element = nextElement; + if (match(hostContext, siblingTraversalStrategy, &subResult) == SelectorMatches) { matched = true; // Consider div:host(div:host(div:host(div:host...))). - maxSpecificity = std::max(maxSpecificity, subContext.selector->specificity() + subResult.specificity); + maxSpecificity = std::max(maxSpecificity, hostContext.selector->specificity() + subResult.specificity); break; } - subContext.behaviorAtBoundary = CrossesBoundary; - subContext.scope = 0; - } + hostContext.behaviorAtBoundary = DoesNotCrossBoundary; + hostContext.scope = 0; + + if (selector.pseudoType() == CSSSelector::PseudoHost) + break; + + hostContext.elementStyle = 0; + nextElement = NodeRenderingTraversal::parentElement(nextElement); + } while (nextElement); } if (matched) { if (specificity) @@ -913,14 +989,14 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib break; } return false; - } - else if (selector->m_match == CSSSelector::PseudoElement && selector->pseudoType() == CSSSelector::PseudoCue) { + } else if (selector.match() == CSSSelector::PseudoElement && selector.pseudoType() == CSSSelector::PseudoCue) { SelectorCheckingContext subContext(context); subContext.isSubSelector = true; subContext.behaviorAtBoundary = StaysWithinTreeScope; - const CSSSelector* const & selector = context.selector; - for (subContext.selector = selector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(subContext.selector)) { + const CSSSelector* contextSelector = context.selector; + ASSERT(contextSelector); + for (subContext.selector = contextSelector->selectorList()->first(); subContext.selector; subContext.selector = CSSSelectorList::next(*subContext.selector)) { if (match(subContext, siblingTraversalStrategy) == SelectorMatches) return true; } @@ -930,21 +1006,21 @@ bool SelectorChecker::checkOne(const SelectorCheckingContext& context, const Sib return true; } -bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& context, Document* document, const CSSSelector* selector) const +bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& context, Document* document, const CSSSelector& selector) const { RenderScrollbar* scrollbar = context.scrollbar; ScrollbarPart part = context.scrollbarPart; // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real // pseudo class and just apply to everything. - if (selector->pseudoType() == CSSSelector::PseudoWindowInactive) + if (selector.pseudoType() == CSSSelector::PseudoWindowInactive) return !document->page()->focusController().isActive(); if (!scrollbar) return false; - ASSERT(selector->m_match == CSSSelector::PseudoClass); - switch (selector->pseudoType()) { + ASSERT(selector.match() == CSSSelector::PseudoClass); + switch (selector.pseudoType()) { case CSSSelector::PseudoEnabled: return scrollbar->enabled(); case CSSSelector::PseudoDisabled: @@ -1011,19 +1087,19 @@ bool SelectorChecker::checkScrollbarPseudoClass(const SelectorCheckingContext& c } } -unsigned SelectorChecker::determineLinkMatchType(const CSSSelector* selector) +unsigned SelectorChecker::determineLinkMatchType(const CSSSelector& selector) { unsigned linkMatchType = MatchAll; // Statically determine if this selector will match a link in visited, unvisited or any state, or never. // :visited never matches other elements than the innermost link element. - for (; selector; selector = selector->tagHistory()) { - switch (selector->pseudoType()) { + for (const CSSSelector* current = &selector; current; current = current->tagHistory()) { + switch (current->pseudoType()) { case CSSSelector::PseudoNot: { // :not(:visited) is equivalent to :link. Parser enforces that :not can't nest. - ASSERT(selector->selectorList()); - for (const CSSSelector* subSelector = selector->selectorList()->first(); subSelector; subSelector = subSelector->tagHistory()) { + ASSERT(current->selectorList()); + for (const CSSSelector* subSelector = current->selectorList()->first(); subSelector; subSelector = subSelector->tagHistory()) { CSSSelector::PseudoType subType = subSelector->pseudoType(); if (subType == CSSSelector::PseudoVisited) linkMatchType &= ~SelectorChecker::MatchVisited; @@ -1042,7 +1118,7 @@ unsigned SelectorChecker::determineLinkMatchType(const CSSSelector* selector) // We don't support :link and :visited inside :-webkit-any. break; } - CSSSelector::Relation relation = selector->relation(); + CSSSelector::Relation relation = current->relation(); if (relation == CSSSelector::SubSelector) continue; if (relation != CSSSelector::Descendant && relation != CSSSelector::Child) diff --git a/chromium/third_party/WebKit/Source/core/css/SelectorChecker.h b/chromium/third_party/WebKit/Source/core/css/SelectorChecker.h index 13d7d7dc1fc..55fddb9b942 100644 --- a/chromium/third_party/WebKit/Source/core/css/SelectorChecker.h +++ b/chromium/third_party/WebKit/Source/core/css/SelectorChecker.h @@ -49,26 +49,22 @@ public: explicit SelectorChecker(Document&, Mode); enum BehaviorAtBoundary { DoesNotCrossBoundary = 0, - CrossesBoundary = 1, + // FIXME: refactor to remove BoundaryBehavior (i.e. DoesNotCrossBoundary and StaysWithinTreeScope). StaysWithinTreeScope = 2, BoundaryBehaviorMask = 3, // 2bit for boundary behavior ScopeContainsLastMatchedElement = 4, - ScopeIsShadowHost = 8, + ScopeIsShadowRoot = 8, TreatShadowHostAsNormalScope = 16, - ScopeIsShadowHostInPseudoHostParameter = CrossesBoundary | ScopeIsShadowHost | TreatShadowHostAsNormalScope - }; - - enum MatchingTagType { - MatchingElement = 0, - MatchingHostInItsShadowTree + ScopeIsShadowHostInPseudoHostParameter = ScopeIsShadowRoot | TreatShadowHostAsNormalScope }; struct SelectorCheckingContext { // Initial selector constructor - SelectorCheckingContext(const CSSSelector* selector, Element* element, VisitedMatchType visitedMatchType) - : selector(selector) + SelectorCheckingContext(const CSSSelector& selector, Element* element, VisitedMatchType visitedMatchType) + : selector(&selector) , element(element) + , previousElement(0) , scope(0) , visitedMatchType(visitedMatchType) , pseudoId(NOPSEUDO) @@ -83,6 +79,7 @@ public: const CSSSelector* selector; Element* element; + Element* previousElement; const ContainerNode* scope; VisitedMatchType visitedMatchType; PseudoId pseudoId; @@ -114,13 +111,13 @@ public: Mode mode() const { return m_mode; } - static bool tagMatches(const Element&, const QualifiedName&, MatchingTagType = MatchingElement); - static bool isCommonPseudoClassSelector(const CSSSelector*); + static bool tagMatches(const Element&, const QualifiedName&); + static bool isCommonPseudoClassSelector(const CSSSelector&); static bool matchesFocusPseudoClass(const Element&); static bool checkExactAttribute(const Element&, const QualifiedName& selectorAttributeName, const StringImpl* value); enum LinkMatchMask { MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited }; - static unsigned determineLinkMatchType(const CSSSelector*); + static unsigned determineLinkMatchType(const CSSSelector&); static bool isHostInItsShadowTree(const Element&, BehaviorAtBoundary, const ContainerNode* scope); @@ -131,9 +128,11 @@ private: Match matchForRelation(const SelectorCheckingContext&, const SiblingTraversalStrategy&, MatchResult*) const; template<typename SiblingTraversalStrategy> Match matchForShadowDistributed(const Element*, const SiblingTraversalStrategy&, SelectorCheckingContext& nextContext, MatchResult* = 0) const; + template<typename SiblingTraversalStrategy> + Match matchForPseudoShadow(const ContainerNode*, const SelectorCheckingContext&, const SiblingTraversalStrategy&, MatchResult*) const; - bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector*) const; - Element* parentElement(const SelectorCheckingContext&) const; + bool checkScrollbarPseudoClass(const SelectorCheckingContext&, Document*, const CSSSelector&) const; + Element* parentElement(const SelectorCheckingContext&, bool allowToCrossBoundary = false) const; bool scopeContainsLastMatchedElement(const SelectorCheckingContext&) const; static bool isFrameFocused(const Element&); @@ -143,23 +142,23 @@ private: Mode m_mode; }; -inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector* selector) +inline bool SelectorChecker::isCommonPseudoClassSelector(const CSSSelector& selector) { - if (selector->m_match != CSSSelector::PseudoClass) + if (selector.match() != CSSSelector::PseudoClass) return false; - CSSSelector::PseudoType pseudoType = selector->pseudoType(); + CSSSelector::PseudoType pseudoType = selector.pseudoType(); return pseudoType == CSSSelector::PseudoLink || pseudoType == CSSSelector::PseudoAnyLink || pseudoType == CSSSelector::PseudoVisited || pseudoType == CSSSelector::PseudoFocus; } -inline bool SelectorChecker::tagMatches(const Element& element, const QualifiedName& tagQName, MatchingTagType matchingTagType) +inline bool SelectorChecker::tagMatches(const Element& element, const QualifiedName& tagQName) { if (tagQName == anyQName()) return true; const AtomicString& localName = tagQName.localName(); - if (localName != starAtom && (localName != element.localName() || matchingTagType == MatchingHostInItsShadowTree)) + if (localName != starAtom && localName != element.localName()) return false; const AtomicString& namespaceURI = tagQName.namespaceURI(); return namespaceURI == starAtom || namespaceURI == element.namespaceURI(); @@ -169,10 +168,10 @@ inline bool SelectorChecker::checkExactAttribute(const Element& element, const Q { if (!element.hasAttributesWithoutUpdate()) return false; - unsigned size = element.attributeCount(); - for (unsigned i = 0; i < size; ++i) { - const Attribute* attribute = element.attributeItem(i); - if (attribute->matches(selectorAttributeName) && (!value || attribute->value().impl() == value)) + AttributeCollection attributes = element.attributes(); + AttributeCollection::const_iterator end = attributes.end(); + for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { + if (it->matches(selectorAttributeName) && (!value || it->value().impl() == value)) return true; } return false; @@ -180,7 +179,7 @@ inline bool SelectorChecker::checkExactAttribute(const Element& element, const Q inline bool SelectorChecker::isHostInItsShadowTree(const Element& element, BehaviorAtBoundary behaviorAtBoundary, const ContainerNode* scope) { - return (behaviorAtBoundary & (ScopeIsShadowHost | TreatShadowHostAsNormalScope)) == ScopeIsShadowHost && scope == element; + return scope && scope->isInShadowTree() && scope->shadowHost() == element; } } diff --git a/chromium/third_party/WebKit/Source/core/css/SelectorCheckerFastPath.cpp b/chromium/third_party/WebKit/Source/core/css/SelectorCheckerFastPath.cpp deleted file mode 100644 index 557f0438a56..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/SelectorCheckerFastPath.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) - * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. - * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> - * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * Copyright (C) Research In Motion Limited 2011. All rights reserved. - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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. - */ - -#include "config.h" -#include "core/css/SelectorCheckerFastPath.h" - -#include "HTMLNames.h" -#include "core/dom/Element.h" -#include "core/html/HTMLDocument.h" - -namespace WebCore { - -using namespace HTMLNames; - -namespace { - -template <bool checkValue(const Element&, const CSSSelector*)> -inline bool fastCheckSingleSelector(const CSSSelector*& selector, const Element*& element, const CSSSelector*& topChildOrSubselector, const Element*& topChildOrSubselectorMatchElement) -{ - for (; element; element = element->parentElement()) { - if (checkValue(*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; -} - -inline bool checkClassValue(const Element& element, const CSSSelector* selector) -{ - return element.hasClass() && element.classNames().contains(selector->value()); -} - -inline bool checkIDValue(const Element& element, const CSSSelector* selector) -{ - return element.hasID() && element.idForStyleResolution() == selector->value(); -} - -inline bool checkExactAttributeValue(const Element& element, const CSSSelector* selector) -{ - return SelectorChecker::checkExactAttribute(element, selector->attribute(), selector->value().impl()); -} - -inline bool checkTagValue(const Element& element, const CSSSelector* selector) -{ - return SelectorChecker::tagMatches(element, selector->tagQName()); -} - -} - -SelectorCheckerFastPath::SelectorCheckerFastPath(const CSSSelector* selector, const Element& element) - : m_selector(selector) - , m_element(element) -{ -} - -bool SelectorCheckerFastPath::matchesRightmostSelector(SelectorChecker::VisitedMatchType visitedMatchType) const -{ - ASSERT(SelectorCheckerFastPath::canUse(m_selector)); - - switch (m_selector->m_match) { - case CSSSelector::Tag: - return checkTagValue(m_element, m_selector); - case CSSSelector::Class: - return checkClassValue(m_element, m_selector); - case CSSSelector::Id: - return checkIDValue(m_element, m_selector); - case CSSSelector::Exact: - case CSSSelector::Set: - return checkExactAttributeValue(m_element, m_selector); - case CSSSelector::PseudoClass: - return commonPseudoClassSelectorMatches(visitedMatchType); - default: - ASSERT_NOT_REACHED(); - } - return false; -} - -bool SelectorCheckerFastPath::matches() const -{ - ASSERT(matchesRightmostSelector(SelectorChecker::VisitedMatchEnabled)); - const CSSSelector* selector = m_selector; - const Element* element = &m_element; - - 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(); - - // 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: - if (!fastCheckSingleSelector<checkClassValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) - return false; - break; - case CSSSelector::Id: - if (!fastCheckSingleSelector<checkIDValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) - return false; - break; - case CSSSelector::Tag: - if (!fastCheckSingleSelector<checkTagValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) - return false; - break; - case CSSSelector::Set: - case CSSSelector::Exact: - if (!fastCheckSingleSelector<checkExactAttributeValue>(selector, element, topChildOrSubselector, topChildOrSubselectorMatchElement)) - return false; - break; - default: - ASSERT_NOT_REACHED(); - } - } - return true; -} - -static inline bool isFastCheckableRelation(CSSSelector::Relation relation) -{ - return relation == CSSSelector::Descendant || relation == CSSSelector::Child || relation == CSSSelector::SubSelector; -} - -static inline bool isFastCheckableMatch(const CSSSelector* selector) -{ - if (selector->m_match == CSSSelector::Set) { - // Style attribute is generated lazily but the fast path doesn't trigger it. - // Disallow them here rather than making the fast path more branchy. - return selector->attribute() != styleAttr; - } - if (selector->m_match == CSSSelector::Exact) - return selector->attribute() != styleAttr && HTMLDocument::isCaseSensitiveAttribute(selector->attribute()); - return selector->m_match == CSSSelector::Tag || selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class; -} - -static inline bool isFastCheckableRightmostSelector(const CSSSelector* selector) -{ - if (!isFastCheckableRelation(selector->relation())) - return false; - return isFastCheckableMatch(selector) || SelectorChecker::isCommonPseudoClassSelector(selector); -} - -bool SelectorCheckerFastPath::canUse(const CSSSelector* selector) -{ - if (!isFastCheckableRightmostSelector(selector)) - return false; - for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) { - if (!isFastCheckableRelation(selector->relation())) - return false; - if (!isFastCheckableMatch(selector)) - return false; - } - return true; -} - -bool SelectorCheckerFastPath::commonPseudoClassSelectorMatches(SelectorChecker::VisitedMatchType visitedMatchType) const -{ - ASSERT(SelectorChecker::isCommonPseudoClassSelector(m_selector)); - switch (m_selector->pseudoType()) { - case CSSSelector::PseudoLink: - case CSSSelector::PseudoAnyLink: - return m_element.isLink(); - case CSSSelector::PseudoVisited: - return m_element.isLink() && visitedMatchType == SelectorChecker::VisitedMatchEnabled; - case CSSSelector::PseudoFocus: - return SelectorChecker::matchesFocusPseudoClass(m_element); - default: - ASSERT_NOT_REACHED(); - } - return true; -} - - -} diff --git a/chromium/third_party/WebKit/Source/core/css/SelectorCheckerFastPath.h b/chromium/third_party/WebKit/Source/core/css/SelectorCheckerFastPath.h deleted file mode 100644 index 1a37b9ac35a..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/SelectorCheckerFastPath.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com) - * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com) - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved. - * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> - * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org> - * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * Copyright (c) 2011, Code Aurora Forum. All rights reserved. - * Copyright (C) Research In Motion Limited 2011. All rights reserved. - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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 SelectorCheckerFastPath_h -#define SelectorCheckerFastPath_h - -#include "core/css/CSSSelector.h" -#include "core/css/SelectorChecker.h" - -namespace WebCore { - -class SelectorCheckerFastPath { -public: - SelectorCheckerFastPath(const CSSSelector*, const Element&); - - bool matches() const; - bool matchesRightmostSelector(SelectorChecker::VisitedMatchType) const; - bool matchesRightmostAttributeSelector() const; - - static bool canUse(const CSSSelector*); - -private: - bool commonPseudoClassSelectorMatches(SelectorChecker::VisitedMatchType) const; - - const CSSSelector* m_selector; - const Element& m_element; -}; - -inline bool SelectorCheckerFastPath::matchesRightmostAttributeSelector() const -{ - if (m_selector->m_match == CSSSelector::Exact || m_selector->m_match == CSSSelector::Set) - return SelectorChecker::checkExactAttribute(m_element, m_selector->attribute(), m_selector->value().impl()); - ASSERT(!m_selector->isAttributeSelector()); - return true; -} - -} - -#endif diff --git a/chromium/third_party/WebKit/Source/core/css/SelectorFilter.cpp b/chromium/third_party/WebKit/Source/core/css/SelectorFilter.cpp index 50d13de6b48..c0c6a97a16a 100644 --- a/chromium/third_party/WebKit/Source/core/css/SelectorFilter.cpp +++ b/chromium/third_party/WebKit/Source/core/css/SelectorFilter.cpp @@ -108,45 +108,44 @@ void SelectorFilter::pushParent(Element& parent) pushParentStackFrame(parent); } -static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector* selector, unsigned*& hash) +static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector& selector, unsigned*& hash) { - switch (selector->m_match) { + switch (selector.match()) { case CSSSelector::Id: - if (!selector->value().isEmpty()) - (*hash++) = selector->value().impl()->existingHash() * IdAttributeSalt; + if (!selector.value().isEmpty()) + (*hash++) = selector.value().impl()->existingHash() * IdAttributeSalt; break; case CSSSelector::Class: - if (!selector->value().isEmpty()) - (*hash++) = selector->value().impl()->existingHash() * ClassAttributeSalt; + if (!selector.value().isEmpty()) + (*hash++) = selector.value().impl()->existingHash() * ClassAttributeSalt; break; case CSSSelector::Tag: - if (selector->tagQName().localName() != starAtom) - (*hash++) = selector->tagQName().localName().impl()->existingHash() * TagNameSalt; + if (selector.tagQName().localName() != starAtom) + (*hash++) = selector.tagQName().localName().impl()->existingHash() * TagNameSalt; break; default: break; } } -void SelectorFilter::collectIdentifierHashes(const CSSSelector* selector, unsigned* identifierHashes, unsigned maximumIdentifierCount) +void SelectorFilter::collectIdentifierHashes(const CSSSelector& selector, unsigned* identifierHashes, unsigned maximumIdentifierCount) { unsigned* hash = identifierHashes; unsigned* end = identifierHashes + maximumIdentifierCount; - CSSSelector::Relation relation = selector->relation(); - bool relationIsAffectedByPseudoContent = selector->relationIsAffectedByPseudoContent(); + CSSSelector::Relation relation = selector.relation(); + bool relationIsAffectedByPseudoContent = selector.relationIsAffectedByPseudoContent(); // Skip the topmost selector. It is handled quickly by the rule hashes. bool skipOverSubselectors = true; - for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) { + for (const CSSSelector* current = selector.tagHistory(); current; current = current->tagHistory()) { // Only collect identifiers that match ancestors. switch (relation) { case CSSSelector::SubSelector: if (!skipOverSubselectors) - collectDescendantSelectorIdentifierHashes(selector, hash); + collectDescendantSelectorIdentifierHashes(*current, hash); break; case CSSSelector::DirectAdjacent: case CSSSelector::IndirectAdjacent: - case CSSSelector::ShadowPseudo: skipOverSubselectors = true; break; case CSSSelector::Descendant: @@ -157,16 +156,16 @@ void SelectorFilter::collectIdentifierHashes(const CSSSelector* selector, unsign return; } // Fall through. - case CSSSelector::ChildTree: - case CSSSelector::DescendantTree: + case CSSSelector::ShadowPseudo: + case CSSSelector::ShadowDeep: skipOverSubselectors = false; - collectDescendantSelectorIdentifierHashes(selector, hash); + collectDescendantSelectorIdentifierHashes(*current, hash); break; } if (hash == end) return; - relation = selector->relation(); - relationIsAffectedByPseudoContent = selector->relationIsAffectedByPseudoContent(); + relation = current->relation(); + relationIsAffectedByPseudoContent = current->relationIsAffectedByPseudoContent(); } *hash = 0; } diff --git a/chromium/third_party/WebKit/Source/core/css/SelectorFilter.h b/chromium/third_party/WebKit/Source/core/css/SelectorFilter.h index 905edb6dd30..8a2e85280c1 100644 --- a/chromium/third_party/WebKit/Source/core/css/SelectorFilter.h +++ b/chromium/third_party/WebKit/Source/core/css/SelectorFilter.h @@ -50,7 +50,7 @@ public: template <unsigned maximumIdentifierCount> inline bool fastRejectSelector(const unsigned* identifierHashes) const; - static void collectIdentifierHashes(const CSSSelector*, unsigned* identifierHashes, unsigned maximumIdentifierCount); + static void collectIdentifierHashes(const CSSSelector&, unsigned* identifierHashes, unsigned maximumIdentifierCount); private: struct ParentStackFrame { diff --git a/chromium/third_party/WebKit/Source/core/css/SiblingTraversalStrategies.h b/chromium/third_party/WebKit/Source/core/css/SiblingTraversalStrategies.h index b082fa6df0e..dce3c41af18 100644 --- a/chromium/third_party/WebKit/Source/core/css/SiblingTraversalStrategies.h +++ b/chromium/third_party/WebKit/Source/core/css/SiblingTraversalStrategies.h @@ -30,63 +30,64 @@ #define SiblingTraversalStrategies_h #include "core/dom/Element.h" +#include "core/dom/ElementTraversal.h" #include "core/rendering/style/RenderStyle.h" namespace WebCore { struct DOMSiblingTraversalStrategy { - bool isFirstChild(Element*) const; - bool isLastChild(Element*) const; - bool isFirstOfType(Element*, const QualifiedName&) const; - bool isLastOfType(Element*, const QualifiedName&) const; - - int countElementsBefore(Element*) const; - int countElementsAfter(Element*) const; - int countElementsOfTypeBefore(Element*, const QualifiedName&) const; - int countElementsOfTypeAfter(Element*, const QualifiedName&) const; + bool isFirstChild(Element&) const; + bool isLastChild(Element&) const; + bool isFirstOfType(Element&, const QualifiedName&) const; + bool isLastOfType(Element&, const QualifiedName&) const; + + int countElementsBefore(Element&) const; + int countElementsAfter(Element&) const; + int countElementsOfTypeBefore(Element&, const QualifiedName&) const; + int countElementsOfTypeAfter(Element&, const QualifiedName&) const; }; -inline bool DOMSiblingTraversalStrategy::isFirstChild(Element* element) const +inline bool DOMSiblingTraversalStrategy::isFirstChild(Element& element) const { - return !element->previousElementSibling(); + return !ElementTraversal::previousSibling(element); } -inline bool DOMSiblingTraversalStrategy::isLastChild(Element* element) const +inline bool DOMSiblingTraversalStrategy::isLastChild(Element& element) const { - return !element->nextElementSibling(); + return !ElementTraversal::nextSibling(element); } -inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const +inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const { - for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { + for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) { if (sibling->hasTagName(type)) return false; } return true; } -inline bool DOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const +inline bool DOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const { - for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { + for (const Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) { if (sibling->hasTagName(type)) return false; } return true; } -inline int DOMSiblingTraversalStrategy::countElementsBefore(Element* element) const +inline int DOMSiblingTraversalStrategy::countElementsBefore(Element& element) const { int count = 0; - for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) + for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) count++; return count; } -inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const +inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element& element, const QualifiedName& type) const { int count = 0; - for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) { + for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling)) { if (sibling->hasTagName(type)) ++count; } @@ -94,19 +95,19 @@ inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* eleme return count; } -inline int DOMSiblingTraversalStrategy::countElementsAfter(Element* element) const +inline int DOMSiblingTraversalStrategy::countElementsAfter(Element& element) const { int count = 0; - for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) + for (const Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) ++count; return count; } -inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const +inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element& element, const QualifiedName& type) const { int count = 0; - for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) { + for (const Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling)) { if (sibling->hasTagName(type)) ++count; } @@ -114,29 +115,31 @@ inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* elemen return count; } -struct ShadowDOMSiblingTraversalStrategy { - ShadowDOMSiblingTraversalStrategy(const Vector<Node*, 32>& siblings, int nth) +class ShadowDOMSiblingTraversalStrategy FINAL { + STACK_ALLOCATED(); +public: + ShadowDOMSiblingTraversalStrategy(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth) : m_siblings(siblings) , m_nth(nth) { } - bool isFirstChild(Element*) const; - bool isLastChild(Element*) const; - bool isFirstOfType(Element*, const QualifiedName&) const; - bool isLastOfType(Element*, const QualifiedName&) const; + bool isFirstChild(Element&) const; + bool isLastChild(Element&) const; + bool isFirstOfType(Element&, const QualifiedName&) const; + bool isLastOfType(Element&, const QualifiedName&) const; - int countElementsBefore(Element*) const; - int countElementsAfter(Element*) const; - int countElementsOfTypeBefore(Element*, const QualifiedName&) const; - int countElementsOfTypeAfter(Element*, const QualifiedName&) const; + int countElementsBefore(Element&) const; + int countElementsAfter(Element&) const; + int countElementsOfTypeBefore(Element&, const QualifiedName&) const; + int countElementsOfTypeAfter(Element&, const QualifiedName&) const; private: - const Vector<Node*, 32>& m_siblings; + const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& m_siblings; int m_nth; }; -inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element* element) const +inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element& element) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -148,7 +151,7 @@ inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element* element) co return true; } -inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element* element) const +inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element& element) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -160,7 +163,7 @@ inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element* element) con return true; } -inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const +inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -172,7 +175,7 @@ inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element* element, c return true; } -inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const +inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -184,7 +187,7 @@ inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element* element, co return true; } -inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element* element) const +inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element& element) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -197,7 +200,7 @@ inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element* eleme return count; } -inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element* element) const +inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element& element) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -210,7 +213,7 @@ inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element* elemen return count; } -inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const +inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element& element, const QualifiedName& type) const { ASSERT(element == toElement(m_siblings[m_nth])); @@ -223,7 +226,7 @@ inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* return count; } -inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const +inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element& element, const QualifiedName& type) const { ASSERT(element == toElement(m_siblings[m_nth])); diff --git a/chromium/third_party/WebKit/Source/core/css/StyleColor.h b/chromium/third_party/WebKit/Source/core/css/StyleColor.h index 1f58584f9a9..3c26609cb20 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleColor.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleColor.h @@ -32,79 +32,30 @@ #define StyleColor_h #include "platform/graphics/Color.h" -#include "wtf/FastAllocBase.h" namespace WebCore { class StyleColor { - WTF_MAKE_FAST_ALLOCATED; public: - StyleColor() - : m_color() - , m_valid(false) - , m_currentColor(false) { } - StyleColor(Color color) - : m_color(color) - , m_valid(true) - , m_currentColor(false) { } - StyleColor(RGBA32 color, bool valid = true, bool currentColor = false) - : m_color(color) - , m_valid(valid) - , m_currentColor(currentColor) { } - StyleColor(int r, int g, int b) - : m_color(Color(r, g, b)) - , m_valid(true) - , m_currentColor(false) { } - StyleColor(int r, int g, int b, int a) - : m_color(Color(r, g, b, a)) - , m_valid(true) - , m_currentColor(false) { } - StyleColor(const StyleColor& other) - : m_color(other.m_color) - , m_valid(other.m_valid) - , m_currentColor(other.m_currentColor) { } + StyleColor(Color color) : m_color(color), m_currentColor(false) { } + static StyleColor currentColor() { return StyleColor(); } - Color color() const { return m_color; } - bool isValid() const { return m_valid; } bool isCurrentColor() const { return m_currentColor; } - bool hasAlpha() const { return m_color.hasAlpha(); } + Color color() const { ASSERT(!isCurrentColor()); return m_color; } - void setRGB(int r, int g, int b) - { - m_color.setRGB(r, g, b); - m_valid = true; - m_currentColor = false; - } - - RGBA32 rgb() const { return m_color.rgb(); } // Preserve the alpha. - int red() const { return m_color.red(); } - int green() const { return m_color.green(); } - int blue() const { return m_color.blue(); } - int alpha() const { return m_color.alpha(); } - - static const StyleColor invalid() - { - return StyleColor(false, false); - } - static const StyleColor currentColor() - { - return StyleColor(true, true); - } + Color resolve(Color currentColor) const { return m_currentColor ? currentColor : m_color; } private: - StyleColor(bool invalid, bool currentColor) - : m_color() - , m_valid(invalid) - , m_currentColor(currentColor) { } - + StyleColor() : m_currentColor(true) { } Color m_color; - bool m_valid; bool m_currentColor; }; inline bool operator==(const StyleColor& a, const StyleColor& b) { - return a.rgb() == b.rgb() && a.isValid() == b.isValid() && a.isCurrentColor() == b.isCurrentColor(); + if (a.isCurrentColor() || b.isCurrentColor()) + return a.isCurrentColor() && b.isCurrentColor(); + return a.color() == b.color(); } inline bool operator!=(const StyleColor& a, const StyleColor& b) diff --git a/chromium/third_party/WebKit/Source/core/css/StyleMedia.cpp b/chromium/third_party/WebKit/Source/core/css/StyleMedia.cpp index 791ef27328f..c18d26c592c 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleMedia.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StyleMedia.cpp @@ -28,14 +28,13 @@ #include "core/css/MediaList.h" #include "core/css/MediaQueryEvaluator.h" -#include "core/css/resolver/StyleResolver.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -StyleMedia::StyleMedia(Frame* frame) +StyleMedia::StyleMedia(LocalFrame* frame) : DOMWindowProperty(frame) { } @@ -60,14 +59,11 @@ bool StyleMedia::matchMedium(const String& query) const if (!documentElement) return false; - StyleResolver& styleResolver = document->ensureStyleResolver(); - RefPtr<RenderStyle> rootStyle = styleResolver.styleForElement(documentElement, 0 /*defaultParent*/, DisallowStyleSharing, MatchOnlyUserAgentRules); - - RefPtr<MediaQuerySet> media = MediaQuerySet::create(); + RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(); if (!media->set(query)) return false; - MediaQueryEvaluator screenEval(type(), m_frame, rootStyle.get()); + MediaQueryEvaluator screenEval(type(), m_frame); return screenEval.eval(media.get()); } diff --git a/chromium/third_party/WebKit/Source/core/css/StyleMedia.h b/chromium/third_party/WebKit/Source/core/css/StyleMedia.h index e2cd69be117..c08bd104930 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleMedia.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleMedia.h @@ -28,22 +28,25 @@ #define StyleMedia_h #include "core/frame/DOMWindowProperty.h" +#include "platform/heap/Handle.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" namespace WebCore { -class Frame; +class LocalFrame; -class StyleMedia : public RefCounted<StyleMedia>, public DOMWindowProperty { +class StyleMedia : public RefCountedWillBeGarbageCollectedFinalized<StyleMedia>, public DOMWindowProperty { public: - static PassRefPtr<StyleMedia> create(Frame* frame) { return adoptRef(new StyleMedia(frame));} + static PassRefPtrWillBeRawPtr<StyleMedia> create(LocalFrame* frame) { return adoptRefWillBeNoop(new StyleMedia(frame));} AtomicString type() const; bool matchMedium(const String&) const; + void trace(Visitor*) { } + private: - explicit StyleMedia(Frame*); + explicit StyleMedia(LocalFrame*); }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/StyleMedia.idl b/chromium/third_party/WebKit/Source/core/css/StyleMedia.idl index 370eee8f913..b897eb0690b 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleMedia.idl +++ b/chromium/third_party/WebKit/Source/core/css/StyleMedia.idl @@ -25,7 +25,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + WillBeGarbageCollected ] interface StyleMedia { readonly attribute DOMString type; boolean matchMedium([Default=Undefined] optional DOMString mediaquery); diff --git a/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp index 825781430ab..4d00705a09c 100644 --- a/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp @@ -23,14 +23,12 @@ #include "config.h" #include "core/css/StylePropertySerializer.h" -#include "CSSValueKeywords.h" -#include "StylePropertyShorthand.h" +#include "core/CSSValueKeywords.h" +#include "core/StylePropertyShorthand.h" #include "core/css/RuntimeCSSEnabled.h" #include "wtf/BitArray.h" #include "wtf/text/StringBuilder.h" -using namespace std; - namespace WebCore { static bool isInitialOrInherit(const String& value) @@ -45,14 +43,23 @@ StylePropertySerializer::StylePropertySerializer(const StylePropertySet& propert { } -String StylePropertySerializer::asText() const +String StylePropertySerializer::getPropertyText(CSSPropertyID propertyID, const String& value, bool isImportant, bool isNotFirstDecl) const { StringBuilder result; + if (isNotFirstDecl) + result.append(' '); + result.append(getPropertyName(propertyID)); + result.appendLiteral(": "); + result.append(value); + if (isImportant) + result.appendLiteral(" !important"); + result.append(';'); + return result.toString(); +} - int positionXPropertyIndex = -1; - int positionYPropertyIndex = -1; - int repeatXPropertyIndex = -1; - int repeatYPropertyIndex = -1; +String StylePropertySerializer::asText() const +{ + StringBuilder result; BitArray<numCSSProperties> shorthandPropertyUsed; BitArray<numCSSProperties> shorthandPropertyAppeared; @@ -69,22 +76,17 @@ String StylePropertySerializer::asText() const String value; switch (propertyID) { - case CSSPropertyVariable: - if (numDecls++) - result.append(' '); - result.append(property.cssText()); - continue; + case CSSPropertyBackgroundAttachment: + case CSSPropertyBackgroundClip: + case CSSPropertyBackgroundColor: + case CSSPropertyBackgroundImage: + case CSSPropertyBackgroundOrigin: case CSSPropertyBackgroundPositionX: - positionXPropertyIndex = n; - continue; case CSSPropertyBackgroundPositionY: - positionYPropertyIndex = n; - continue; + case CSSPropertyBackgroundSize: case CSSPropertyBackgroundRepeatX: - repeatXPropertyIndex = n; - continue; case CSSPropertyBackgroundRepeatY: - repeatYPropertyIndex = n; + shorthandPropertyAppeared.set(CSSPropertyBackground - firstCSSProperty); continue; case CSSPropertyContent: if (property.value()->isValueList()) @@ -229,80 +231,11 @@ String StylePropertySerializer::asText() const if (value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) continue; - if (numDecls++) - result.append(' '); - result.append(getPropertyName(propertyID)); - result.appendLiteral(": "); - result.append(value); - if (property.isImportant()) - result.appendLiteral(" !important"); - result.append(';'); - } - - // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. - // It is required because background-position-x/y are non-standard properties and WebKit generated output - // would not work in Firefox (<rdar://problem/5143183>) - // It would be a better solution if background-position was CSS_PAIR. - if (positionXPropertyIndex != -1 && positionYPropertyIndex != -1 && m_propertySet.propertyAt(positionXPropertyIndex).isImportant() == m_propertySet.propertyAt(positionYPropertyIndex).isImportant()) { - StylePropertySet::PropertyReference positionXProperty = m_propertySet.propertyAt(positionXPropertyIndex); - StylePropertySet::PropertyReference positionYProperty = m_propertySet.propertyAt(positionYPropertyIndex); - - if (numDecls++) - result.append(' '); - result.appendLiteral("background-position: "); - if (positionXProperty.value()->isValueList() || positionYProperty.value()->isValueList()) - result.append(getLayeredShorthandValue(backgroundPositionShorthand())); - else { - result.append(positionXProperty.value()->cssText()); - result.append(' '); - result.append(positionYProperty.value()->cssText()); - } - if (positionXProperty.isImportant()) - result.appendLiteral(" !important"); - result.append(';'); - } else { - if (positionXPropertyIndex != -1) { - if (numDecls++) - result.append(' '); - result.append(m_propertySet.propertyAt(positionXPropertyIndex).cssText()); - } - if (positionYPropertyIndex != -1) { - if (numDecls++) - result.append(' '); - result.append(m_propertySet.propertyAt(positionYPropertyIndex).cssText()); - } + result.append(getPropertyText(propertyID, value, property.isImportant(), numDecls++)); } - // FIXME: We need to do the same for background-repeat. - if (repeatXPropertyIndex != -1 && repeatYPropertyIndex != -1 && m_propertySet.propertyAt(repeatXPropertyIndex).isImportant() == m_propertySet.propertyAt(repeatYPropertyIndex).isImportant()) { - StylePropertySet::PropertyReference repeatXProperty = m_propertySet.propertyAt(repeatXPropertyIndex); - StylePropertySet::PropertyReference repeatYProperty = m_propertySet.propertyAt(repeatYPropertyIndex); - - if (numDecls++) - result.append(' '); - result.appendLiteral("background-repeat: "); - if (repeatXProperty.value()->isValueList() || repeatYProperty.value()->isValueList()) - result.append(getLayeredShorthandValue(backgroundRepeatShorthand())); - else { - result.append(repeatXProperty.value()->cssText()); - result.append(' '); - result.append(repeatYProperty.value()->cssText()); - } - if (repeatXProperty.isImportant()) - result.appendLiteral(" !important"); - result.append(';'); - } else { - if (repeatXPropertyIndex != -1) { - if (numDecls++) - result.append(' '); - result.append(m_propertySet.propertyAt(repeatXPropertyIndex).cssText()); - } - if (repeatYPropertyIndex != -1) { - if (numDecls++) - result.append(' '); - result.append(m_propertySet.propertyAt(repeatYPropertyIndex).cssText()); - } - } + if (shorthandPropertyAppeared.get(CSSPropertyBackground - firstCSSProperty)) + appendBackgroundPropertyAsText(result, numDecls); ASSERT(!numDecls ^ !result.isEmpty()); return result.toString(); @@ -319,7 +252,7 @@ String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const case CSSPropertyBackgroundPosition: return getLayeredShorthandValue(backgroundPositionShorthand()); case CSSPropertyBackgroundRepeat: - return getLayeredShorthandValue(backgroundRepeatShorthand()); + return backgroundRepeatPropertyValue(); case CSSPropertyBackground: return getLayeredShorthandValue(backgroundShorthand()); case CSSPropertyBorder: @@ -378,6 +311,7 @@ String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const return getShorthandValue(webkitTextEmphasisShorthand()); case CSSPropertyWebkitTextStroke: return getShorthandValue(webkitTextStrokeShorthand()); + case CSSPropertyTransformOrigin: case CSSPropertyWebkitTransformOrigin: return getShorthandValue(webkitTransformOriginShorthand()); case CSSPropertyWebkitTransition: @@ -385,7 +319,7 @@ String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const case CSSPropertyWebkitAnimation: return getLayeredShorthandValue(webkitAnimationShorthand()); case CSSPropertyMarker: { - RefPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyMarkerStart); + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyMarkerStart); if (value) return value->cssText(); return String(); @@ -399,8 +333,8 @@ String StylePropertySerializer::getPropertyValue(CSSPropertyID propertyID) const String StylePropertySerializer::borderSpacingValue(const StylePropertyShorthand& shorthand) const { - RefPtr<CSSValue> horizontalValue = m_propertySet.getPropertyCSSValue(shorthand.properties()[0]); - RefPtr<CSSValue> verticalValue = m_propertySet.getPropertyCSSValue(shorthand.properties()[1]); + RefPtrWillBeRawPtr<CSSValue> horizontalValue = m_propertySet.getPropertyCSSValue(shorthand.properties()[0]); + RefPtrWillBeRawPtr<CSSValue> verticalValue = m_propertySet.getPropertyCSSValue(shorthand.properties()[1]); // While standard border-spacing property does not allow specifying border-spacing-vertical without // specifying border-spacing-horizontal <http://www.w3.org/TR/CSS21/tables.html#separated-borders>, @@ -539,7 +473,7 @@ String StylePropertySerializer::getLayeredShorthandValue(const StylePropertyShor const unsigned size = shorthand.length(); // Begin by collecting the properties into an array. - Vector< RefPtr<CSSValue> > values(size); + WillBeHeapVector<RefPtrWillBeMember<CSSValue> > values(size); size_t numLayers = 0; for (unsigned i = 0; i < size; ++i) { @@ -547,9 +481,10 @@ String StylePropertySerializer::getLayeredShorthandValue(const StylePropertyShor if (values[i]) { if (values[i]->isBaseValueList()) { CSSValueList* valueList = toCSSValueList(values[i].get()); - numLayers = max(valueList->length(), numLayers); - } else - numLayers = max<size_t>(1U, numLayers); + numLayers = std::max(valueList->length(), numLayers); + } else { + numLayers = std::max<size_t>(1U, numLayers); + } } } @@ -565,7 +500,7 @@ String StylePropertySerializer::getLayeredShorthandValue(const StylePropertyShor bool useSingleWordShorthand = false; bool foundPositionYCSSProperty = false; for (unsigned j = 0; j < size; j++) { - RefPtr<CSSValue> value; + RefPtrWillBeRawPtr<CSSValue> value = nullptr; if (values[j]) { if (values[j]->isBaseValueList()) value = toCSSValueList(values[j].get())->item(i); @@ -575,9 +510,11 @@ String StylePropertySerializer::getLayeredShorthandValue(const StylePropertyShor // Color only belongs in the last layer. if (shorthand.properties()[j] == CSSPropertyBackgroundColor) { if (i != numLayers - 1) - value = 0; - } else if (i) // Other singletons only belong in the first layer. - value = 0; + value = nullptr; + } else if (i) { + // Other singletons only belong in the first layer. + value = nullptr; + } } } @@ -590,8 +527,8 @@ String StylePropertySerializer::getLayeredShorthandValue(const StylePropertyShor // BUG 49055: make sure the value was not reset in the layer check just above. if ((j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyBackgroundRepeatY && value) || (j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyWebkitMaskRepeatY && value)) { - RefPtr<CSSValue> yValue; - RefPtr<CSSValue> nextValue = values[j + 1]; + RefPtrWillBeRawPtr<CSSValue> yValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> nextValue = values[j + 1]; if (nextValue->isValueList()) yValue = toCSSValueList(nextValue.get())->itemWithoutBoundsCheck(i); else @@ -687,7 +624,7 @@ String StylePropertySerializer::getShorthandValue(const StylePropertyShorthand& StringBuilder result; for (unsigned i = 0; i < shorthand.length(); ++i) { if (!m_propertySet.isPropertyImplicit(shorthand.properties()[i])) { - RefPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]); + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]); if (!value) return String(); String valueText = value->cssText(); @@ -716,7 +653,7 @@ String StylePropertySerializer::getCommonValue(const StylePropertyShorthand& sho String res; bool lastPropertyWasImportant = false; for (unsigned i = 0; i < shorthand.length(); ++i) { - RefPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]); + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]); // FIXME: CSSInitialValue::cssText should generate the right value. if (!value) return String(); @@ -764,4 +701,172 @@ String StylePropertySerializer::borderPropertyValue(CommonValueMode valueMode) c return result.isEmpty() ? String() : result.toString(); } +static void appendBackgroundRepeatValue(StringBuilder& builder, const CSSValue& repeatXCSSValue, const CSSValue& repeatYCSSValue) +{ + // FIXME: Ensure initial values do not appear in CSS_VALUE_LISTS. + DEFINE_STATIC_REF_WILL_BE_PERSISTENT(CSSPrimitiveValue, initialRepeatValue, (CSSPrimitiveValue::create(CSSValueRepeat))); + const CSSPrimitiveValue& repeatX = repeatXCSSValue.isInitialValue() ? *initialRepeatValue : toCSSPrimitiveValue(repeatXCSSValue); + const CSSPrimitiveValue& repeatY = repeatYCSSValue.isInitialValue() ? *initialRepeatValue : toCSSPrimitiveValue(repeatYCSSValue); + CSSValueID repeatXValueId = repeatX.getValueID(); + CSSValueID repeatYValueId = repeatY.getValueID(); + if (repeatXValueId == repeatYValueId) { + builder.append(repeatX.cssText()); + } else if (repeatXValueId == CSSValueNoRepeat && repeatYValueId == CSSValueRepeat) { + builder.append("repeat-y"); + } else if (repeatXValueId == CSSValueRepeat && repeatYValueId == CSSValueNoRepeat) { + builder.append("repeat-x"); + } else { + builder.append(repeatX.cssText()); + builder.append(" "); + builder.append(repeatY.cssText()); + } +} + +String StylePropertySerializer::backgroundRepeatPropertyValue() const +{ + RefPtrWillBeRawPtr<CSSValue> repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundRepeatX); + RefPtrWillBeRawPtr<CSSValue> repeatY = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundRepeatY); + if (!repeatX || !repeatY) + return String(); + if (m_propertySet.propertyIsImportant(CSSPropertyBackgroundRepeatX) != m_propertySet.propertyIsImportant(CSSPropertyBackgroundRepeatY)) + return String(); + if (repeatX->cssValueType() == repeatY->cssValueType() + && (repeatX->cssValueType() == CSSValue::CSS_INITIAL || repeatX->cssValueType() == CSSValue::CSS_INHERIT)) { + return repeatX->cssText(); + } + + RefPtrWillBeRawPtr<CSSValueList> repeatXList; + if (repeatX->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) { + repeatXList = CSSValueList::createCommaSeparated(); + repeatXList->append(repeatX); + } else if (repeatX->cssValueType() == CSSValue::CSS_VALUE_LIST) { + repeatXList = toCSSValueList(repeatX.get()); + } else { + return String(); + } + + RefPtrWillBeRawPtr<CSSValueList> repeatYList; + if (repeatY->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) { + repeatYList = CSSValueList::createCommaSeparated(); + repeatYList->append(repeatY); + } else if (repeatY->cssValueType() == CSSValue::CSS_VALUE_LIST) { + repeatYList = toCSSValueList(repeatY.get()); + } else { + return String(); + } + + size_t shorthandLength = lowestCommonMultiple(repeatXList->length(), repeatYList->length()); + StringBuilder builder; + for (size_t i = 0; i < shorthandLength; ++i) { + if (i) + builder.append(", "); + appendBackgroundRepeatValue(builder, + *repeatXList->item(i % repeatXList->length()), + *repeatYList->item(i % repeatYList->length())); + } + return builder.toString(); +} + +void StylePropertySerializer::appendBackgroundPropertyAsText(StringBuilder& result, unsigned& numDecls) const +{ + if (isPropertyShorthandAvailable(backgroundShorthand())) { + String backgroundValue = getPropertyValue(CSSPropertyBackground); + bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundImage); + result.append(getPropertyText(CSSPropertyBackground, backgroundValue, isImportant, numDecls++)); + return; + } + if (shorthandHasOnlyInitialOrInheritedValue(backgroundShorthand())) { + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundImage); + bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundImage); + result.append(getPropertyText(CSSPropertyBackground, value->cssText(), isImportant, numDecls++)); + return; + } + + // backgroundShorthandProperty without layered shorhand properties + const CSSPropertyID backgroundPropertyIds[] = { + CSSPropertyBackgroundImage, + CSSPropertyBackgroundAttachment, + CSSPropertyBackgroundColor, + CSSPropertyBackgroundSize, + CSSPropertyBackgroundOrigin, + CSSPropertyBackgroundClip + }; + + for (unsigned i = 0; i < WTF_ARRAY_LENGTH(backgroundPropertyIds); ++i) { + CSSPropertyID propertyID = backgroundPropertyIds[i]; + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(propertyID); + if (!value) + continue; + result.append(getPropertyText(propertyID, value->cssText(), m_propertySet.propertyIsImportant(propertyID), numDecls++)); + } + + // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output. + // It is required because background-position-x/y are non-standard properties and WebKit generated output + // would not work in Firefox (<rdar://problem/5143183>) + // It would be a better solution if background-position was CSS_PAIR. + if (shorthandHasOnlyInitialOrInheritedValue(backgroundPositionShorthand())) { + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundPositionX); + bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionX); + result.append(getPropertyText(CSSPropertyBackgroundPosition, value->cssText(), isImportant, numDecls++)); + } else if (isPropertyShorthandAvailable(backgroundPositionShorthand())) { + String positionValue = m_propertySet.getPropertyValue(CSSPropertyBackgroundPosition); + bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionX); + if (!positionValue.isNull()) + result.append(getPropertyText(CSSPropertyBackgroundPosition, positionValue, isImportant, numDecls++)); + } else { + // should check background-position-x or background-position-y. + if (RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundPositionX)) { + if (!value->isImplicitInitialValue()) { + bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionX); + result.append(getPropertyText(CSSPropertyBackgroundPositionX, value->cssText(), isImportant, numDecls++)); + } + } + if (RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundPositionY)) { + if (!value->isImplicitInitialValue()) { + bool isImportant = m_propertySet.propertyIsImportant(CSSPropertyBackgroundPositionY); + result.append(getPropertyText(CSSPropertyBackgroundPositionY, value->cssText(), isImportant, numDecls++)); + } + } + } + + String repeatValue = m_propertySet.getPropertyValue(CSSPropertyBackgroundRepeat); + if (!repeatValue.isNull()) + result.append(getPropertyText(CSSPropertyBackgroundRepeat, repeatValue, m_propertySet.propertyIsImportant(CSSPropertyBackgroundRepeatX), numDecls++)); +} + +bool StylePropertySerializer::isPropertyShorthandAvailable(const StylePropertyShorthand& shorthand) const +{ + ASSERT(shorthand.length() > 0); + + bool isImportant = m_propertySet.propertyIsImportant(shorthand.properties()[0]); + for (unsigned i = 0; i < shorthand.length(); ++i) { + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]); + if (!value || (value->isInitialValue() && !value->isImplicitInitialValue()) || value->isInheritedValue()) + return false; + if (isImportant != m_propertySet.propertyIsImportant(shorthand.properties()[i])) + return false; + } + return true; +} + +bool StylePropertySerializer::shorthandHasOnlyInitialOrInheritedValue(const StylePropertyShorthand& shorthand) const +{ + ASSERT(shorthand.length() > 0); + bool isImportant = m_propertySet.propertyIsImportant(shorthand.properties()[0]); + bool isInitialValue = true; + bool isInheritedValue = true; + for (unsigned i = 0; i < shorthand.length(); ++i) { + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet.getPropertyCSSValue(shorthand.properties()[i]); + if (!value) + return false; + if (!value->isInitialValue()) + isInitialValue = false; + if (!value->isInheritedValue()) + isInheritedValue = false; + if (isImportant != m_propertySet.propertyIsImportant(shorthand.properties()[i])) + return false; + } + return isInitialValue || isInheritedValue; +} + } diff --git a/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.h b/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.h index 55d1027b5bd..ed9bc6ab478 100644 --- a/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.h +++ b/chromium/third_party/WebKit/Source/core/css/StylePropertySerializer.h @@ -45,6 +45,11 @@ private: String getShorthandValue(const StylePropertyShorthand&) const; String fontValue() const; void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const; + String backgroundRepeatPropertyValue() const; + String getPropertyText(CSSPropertyID, const String& value, bool isImportant, bool isNotFirstDecl) const; + bool isPropertyShorthandAvailable(const StylePropertyShorthand&) const; + bool shorthandHasOnlyInitialOrInheritedValue(const StylePropertyShorthand&) const; + void appendBackgroundPropertyAsText(StringBuilder& result, unsigned& numDecls) const; const StylePropertySet& m_propertySet; }; diff --git a/chromium/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/chromium/third_party/WebKit/Source/core/css/StylePropertySet.cpp index c7e0ae63811..2581c01e911 100644 --- a/chromium/third_party/WebKit/Source/core/css/StylePropertySet.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StylePropertySet.cpp @@ -23,14 +23,14 @@ #include "config.h" #include "core/css/StylePropertySet.h" -#include "RuntimeEnabledFeatures.h" -#include "StylePropertyShorthand.h" -#include "core/css/CSSParser.h" +#include "core/StylePropertyShorthand.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSValuePool.h" -#include "core/css/CSSVariableValue.h" #include "core/css/RuntimeCSSEnabled.h" #include "core/css/StylePropertySerializer.h" #include "core/css/StyleSheetContents.h" +#include "core/frame/UseCounter.h" +#include "platform/RuntimeEnabledFeatures.h" #include "wtf/text/StringBuilder.h" #ifndef NDEBUG @@ -38,8 +38,6 @@ #include <stdio.h> #endif -using namespace std; - namespace WebCore { static size_t sizeForImmutableStylePropertySetWithPropertyCount(unsigned count) @@ -50,8 +48,12 @@ static size_t sizeForImmutableStylePropertySetWithPropertyCount(unsigned count) PassRefPtr<ImmutableStylePropertySet> ImmutableStylePropertySet::create(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode) { ASSERT(count <= MaxArraySize); +#if ENABLE(OILPAN) + void* slot = Heap::allocate<StylePropertySet>(sizeForImmutableStylePropertySetWithPropertyCount(count)); +#else void* slot = WTF::fastMalloc(sizeForImmutableStylePropertySetWithPropertyCount(count)); - return adoptRef(new (slot) ImmutableStylePropertySet(properties, count, cssParserMode)); +#endif // ENABLE(OILPAN) + return adoptRefWillBeRefCountedGarbageCollected(new (slot) ImmutableStylePropertySet(properties, count, cssParserMode)); } PassRefPtr<ImmutableStylePropertySet> StylePropertySet::immutableCopyIfNeeded() const @@ -79,19 +81,47 @@ ImmutableStylePropertySet::ImmutableStylePropertySet(const CSSProperty* properti : StylePropertySet(cssParserMode, length) { StylePropertyMetadata* metadataArray = const_cast<StylePropertyMetadata*>(this->metadataArray()); - CSSValue** valueArray = const_cast<CSSValue**>(this->valueArray()); + RawPtrWillBeMember<CSSValue>* valueArray = const_cast<RawPtrWillBeMember<CSSValue>*>(this->valueArray()); for (unsigned i = 0; i < m_arraySize; ++i) { metadataArray[i] = properties[i].metadata(); valueArray[i] = properties[i].value(); +#if !ENABLE(OILPAN) valueArray[i]->ref(); +#endif } } ImmutableStylePropertySet::~ImmutableStylePropertySet() { - CSSValue** valueArray = const_cast<CSSValue**>(this->valueArray()); +#if !ENABLE(OILPAN) + RawPtrWillBeMember<CSSValue>* valueArray = const_cast<RawPtrWillBeMember<CSSValue>*>(this->valueArray()); for (unsigned i = 0; i < m_arraySize; ++i) valueArray[i]->deref(); +#endif +} + +int ImmutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const +{ + // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid + // the compiler converting it to an int multiple times in the loop. + uint16_t id = static_cast<uint16_t>(propertyID); + for (int n = m_arraySize - 1 ; n >= 0; --n) { + if (metadataArray()[n].m_propertyID == id) { + // Only enabled or internal properties should be part of the style. + ASSERT(RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID) || isInternalProperty(propertyID)); + return n; + } + } + + return -1; +} + +void ImmutableStylePropertySet::traceAfterDispatch(Visitor* visitor) +{ + const RawPtrWillBeMember<CSSValue>* values = valueArray(); + for (unsigned i = 0; i < m_arraySize; i++) + visitor->trace(values[i]); + StylePropertySet::traceAfterDispatch(visitor); } MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other) @@ -108,40 +138,38 @@ MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other) String StylePropertySet::getPropertyValue(CSSPropertyID propertyID) const { - RefPtr<CSSValue> value = getPropertyCSSValue(propertyID); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(propertyID); if (value) return value->cssText(); return StylePropertySerializer(*this).getPropertyValue(propertyID); } -PassRefPtr<CSSValue> StylePropertySet::getPropertyCSSValue(CSSPropertyID propertyID) const +PassRefPtrWillBeRawPtr<CSSValue> StylePropertySet::getPropertyCSSValue(CSSPropertyID propertyID) const { int foundPropertyIndex = findPropertyIndex(propertyID); if (foundPropertyIndex == -1) - return 0; + return nullptr; return propertyAt(foundPropertyIndex).value(); } -unsigned StylePropertySet::variableCount() const +void StylePropertySet::trace(Visitor* visitor) { - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - unsigned count = 0; - for (unsigned i = 0; i < propertyCount(); ++i) { - if (propertyAt(i).id() == CSSPropertyVariable) - count++; - } - return count; + if (m_isMutable) + toMutableStylePropertySet(this)->traceAfterDispatch(visitor); + else + toImmutableStylePropertySet(this)->traceAfterDispatch(visitor); } -String StylePropertySet::variableValue(const AtomicString& name) const +#if ENABLE(OILPAN) +void StylePropertySet::finalizeGarbageCollectedObject() { - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - size_t index = findVariableIndex(name); - if (index == kNotFound) - return String(); - return toCSSVariableValue(propertyAt(index).value())->value(); + if (m_isMutable) + toMutableStylePropertySet(this)->~MutableStylePropertySet(); + else + toImmutableStylePropertySet(this)->~ImmutableStylePropertySet(); } +#endif bool MutableStylePropertySet::removeShorthandProperty(CSSPropertyID propertyID) { @@ -237,10 +265,10 @@ bool MutableStylePropertySet::setProperty(CSSPropertyID propertyID, const String // 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. - return CSSParser::parseValue(this, propertyID, value, important, cssParserMode(), contextStyleSheet); + return BisonCSSParser::parseValue(this, propertyID, value, important, cssParserMode(), contextStyleSheet); } -void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue> prpValue, bool important) +void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtrWillBeRawPtr<CSSValue> prpValue, bool important) { StylePropertyShorthand shorthand = shorthandForProperty(propertyID); if (!shorthand.length()) { @@ -250,7 +278,7 @@ void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtr<C removePropertiesInSet(shorthand.properties(), shorthand.length()); - RefPtr<CSSValue> value = prpValue; + RefPtrWillBeRawPtr<CSSValue> value = prpValue; for (unsigned i = 0; i < shorthand.length(); ++i) m_propertyVector.append(CSSProperty(shorthand.properties()[i], value, important)); } @@ -279,28 +307,6 @@ unsigned getIndexInShorthandVectorForPrefixingVariant(const CSSProperty& propert return indexOfShorthandForLonghand(prefixedShorthand, shorthands); } -bool MutableStylePropertySet::setVariableValue(const AtomicString& name, const String& value, bool important) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - if (value.isEmpty()) - return removeVariable(name); - - size_t index = findVariableIndex(name); - if (index != kNotFound) { - const CSSValue* cssValue = m_propertyVector.at(index).value(); - if (toCSSVariableValue(cssValue)->value() == value) - return false; - } - - CSSProperty property(CSSPropertyVariable, CSSVariableValue::create(name, value), important); - if (index == kNotFound) { - m_propertyVector.append(property); - return true; - } - m_propertyVector.at(index) = property; - return false; -} - void MutableStylePropertySet::appendPrefixingVariantProperty(const CSSProperty& property) { m_propertyVector.append(property); @@ -335,17 +341,17 @@ void MutableStylePropertySet::parseDeclaration(const String& styleDeclaration, S { m_propertyVector.clear(); - CSSParserContext context(cssParserMode()); + CSSParserContext context(cssParserMode(), UseCounter::getFrom(contextStyleSheet)); if (contextStyleSheet) { context = contextStyleSheet->parserContext(); context.setMode(cssParserMode()); } - CSSParser parser(context, UseCounter::getFrom(contextStyleSheet)); + BisonCSSParser parser(context); parser.parseDeclaration(this, styleDeclaration, 0, contextStyleSheet); } -void MutableStylePropertySet::addParsedProperties(const Vector<CSSProperty, 256>& properties) +void MutableStylePropertySet::addParsedProperties(const WillBeHeapVector<CSSProperty, 256>& properties) { m_propertyVector.reserveCapacity(m_propertyVector.size() + properties.size()); for (unsigned i = 0; i < properties.size(); ++i) @@ -364,11 +370,6 @@ String StylePropertySet::asText() const return StylePropertySerializer(*this).asText(); } -bool StylePropertySet::hasCSSOMWrapper() const -{ - return m_isMutable && toMutableStylePropertySet(this)->m_cssomWrapper; -} - void MutableStylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) { unsigned size = other->propertyCount(); @@ -382,13 +383,6 @@ void MutableStylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* } } -void StylePropertySet::addSubresourceStyleURLs(ListHashSet<KURL>& urls, StyleSheetContents* contextStyleSheet) const -{ - unsigned size = propertyCount(); - for (unsigned i = 0; i < size; ++i) - propertyAt(i).value()->addSubresourceStyleURLs(urls, contextStyleSheet); -} - bool StylePropertySet::hasFailedOrCanceledSubresources() const { unsigned size = propertyCount(); @@ -417,9 +411,6 @@ static const CSSPropertyID staticBlockProperties[] = { CSSPropertyPageBreakAfter, CSSPropertyPageBreakBefore, CSSPropertyPageBreakInside, - CSSPropertyWebkitRegionBreakAfter, - CSSPropertyWebkitRegionBreakBefore, - CSSPropertyWebkitRegionBreakInside, CSSPropertyTextAlign, CSSPropertyTextAlignLast, CSSPropertyTextIndent, @@ -440,7 +431,7 @@ void MutableStylePropertySet::clear() m_propertyVector.clear(); } -PassRefPtr<MutableStylePropertySet> StylePropertySet::copyBlockProperties() const +PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyBlockProperties() const { return copyPropertiesInSet(blockProperties()); } @@ -450,59 +441,35 @@ void MutableStylePropertySet::removeBlockProperties() removePropertiesInSet(blockProperties().data(), blockProperties().size()); } +inline bool containsId(const CSSPropertyID* set, unsigned length, CSSPropertyID id) +{ + for (unsigned i = 0; i < length; ++i) { + if (set[i] == id) + return true; + } + return false; +} + bool MutableStylePropertySet::removePropertiesInSet(const CSSPropertyID* set, unsigned length) { if (m_propertyVector.isEmpty()) return false; - // FIXME: This is always used with static sets and in that case constructing the hash repeatedly is pretty pointless. - HashSet<CSSPropertyID> toRemove; - for (unsigned i = 0; i < length; ++i) - toRemove.add(set[i]); - - Vector<CSSProperty> newProperties; + WillBeHeapVector<CSSProperty> newProperties; newProperties.reserveInitialCapacity(m_propertyVector.size()); - unsigned size = m_propertyVector.size(); - for (unsigned n = 0; n < size; ++n) { - const CSSProperty& property = m_propertyVector.at(n); + unsigned initialSize = m_propertyVector.size(); + const CSSProperty* properties = m_propertyVector.data(); + for (unsigned n = 0; n < initialSize; ++n) { + const CSSProperty& property = properties[n]; // Not quite sure if the isImportant test is needed but it matches the existing behavior. - if (!property.isImportant()) { - if (toRemove.contains(property.id())) - continue; - } + if (!property.isImportant() && containsId(set, length, property.id())) + continue; newProperties.append(property); } - bool changed = newProperties.size() != m_propertyVector.size(); m_propertyVector = newProperties; - return changed; -} - -int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const -{ - // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid - // the compiler converting it to an int multiple times in the loop. - uint16_t id = static_cast<uint16_t>(propertyID); - for (int n = propertyCount() - 1 ; n >= 0; --n) { - if (id == propertyAt(n).propertyMetadata().m_propertyID) { - // Only enabled or internal properties should be part of the style. - ASSERT(RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID) || isInternalProperty(propertyID)); - return n; - } - } - return -1; -} - -size_t StylePropertySet::findVariableIndex(const AtomicString& name) const -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - for (int i = propertyCount() - 1; i >= 0; --i) { - const PropertyReference& property = propertyAt(i); - if (property.id() == CSSPropertyVariable && toCSSVariableValue(property.value())->name() == name) - return i; - } - return kNotFound; + return initialSize != m_propertyVector.size(); } CSSProperty* MutableStylePropertySet::findCSSPropertyWithID(CSSPropertyID propertyID) @@ -549,116 +516,58 @@ void MutableStylePropertySet::removeEquivalentProperties(const CSSStyleDeclarati removeProperty(propertiesToRemove[i]); } -bool MutableStylePropertySet::removeVariable(const AtomicString& name) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - size_t index = findVariableIndex(name); - if (index == kNotFound) - return false; - m_propertyVector.remove(index); - return true; -} - -bool MutableStylePropertySet::clearVariables() -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - CSSPropertyID variablesId = CSSPropertyVariable; - return removePropertiesInSet(&variablesId, 1); -} - -PassRefPtr<MutableStylePropertySet::VariablesIterator> MutableStylePropertySet::VariablesIterator::create(MutableStylePropertySet* propertySet) -{ - ASSERT(RuntimeEnabledFeatures::cssVariablesEnabled()); - const size_t propertyCount = propertySet->propertyCount(); - size_t variableCount = 0; - Vector<AtomicString> remainingNames(propertyCount); - for (int i = propertyCount; i--; ) { - const PropertyReference& property = propertySet->propertyAt(i); - if (property.id() == CSSPropertyVariable) - remainingNames[variableCount++] = toCSSVariableValue(property.value())->name(); - } - remainingNames.shrink(variableCount); - - RefPtr<VariablesIterator> iterator = adoptRef(new VariablesIterator(propertySet)); - // FIXME: Make use of the Vector move constructor when rvalues are supported on all platforms. - iterator->takeRemainingNames(remainingNames); - return iterator.release(); -} - -void MutableStylePropertySet::VariablesIterator::addedVariable(const AtomicString& name) -{ - ASSERT(!m_remainingNames.contains(name)); - ASSERT(!m_newNames.contains(name)); - m_newNames.append(name); -} - -void MutableStylePropertySet::VariablesIterator::removedVariable(const AtomicString& name) -{ - size_t index = m_remainingNames.find(name); - if (index != kNotFound) - m_remainingNames.remove(index); - index = m_newNames.find(name); - if (index != kNotFound) - m_newNames.remove(index); -} - -void MutableStylePropertySet::VariablesIterator::clearedVariables() -{ - m_remainingNames.clear(); - m_newNames.clear(); -} - -void MutableStylePropertySet::VariablesIterator::advance() -{ - if (!atEnd()) - m_remainingNames.removeLast(); - if (!m_newNames.isEmpty()) { - m_remainingNames.appendVector(m_newNames); - m_newNames.clear(); - } -} - -PassRefPtr<MutableStylePropertySet> StylePropertySet::mutableCopy() const +PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::mutableCopy() const { - return adoptRef(new MutableStylePropertySet(*this)); + return adoptRefWillBeRefCountedGarbageCollected(new MutableStylePropertySet(*this)); } -PassRefPtr<MutableStylePropertySet> StylePropertySet::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const +PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const { - Vector<CSSProperty, 256> list; + WillBeHeapVector<CSSProperty, 256> list; list.reserveInitialCapacity(properties.size()); for (unsigned i = 0; i < properties.size(); ++i) { - RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]); + RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(properties[i]); if (value) list.append(CSSProperty(properties[i], value.release(), false)); } return MutableStylePropertySet::create(list.data(), list.size()); } -PropertySetCSSStyleDeclaration* MutableStylePropertySet::cssStyleDeclaration() -{ - return m_cssomWrapper.get(); -} - CSSStyleDeclaration* MutableStylePropertySet::ensureCSSStyleDeclaration() { + // FIXME: get rid of this weirdness of a CSSStyleDeclaration inside of a + // style property set. if (m_cssomWrapper) { ASSERT(!static_cast<CSSStyleDeclaration*>(m_cssomWrapper.get())->parentRule()); ASSERT(!m_cssomWrapper->parentElement()); return m_cssomWrapper.get(); } - m_cssomWrapper = adoptPtr(new PropertySetCSSStyleDeclaration(this)); + m_cssomWrapper = adoptPtrWillBeNoop(new PropertySetCSSStyleDeclaration(*this)); return m_cssomWrapper.get(); } -CSSStyleDeclaration* MutableStylePropertySet::ensureInlineCSSStyleDeclaration(Element* parentElement) +int MutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const { - if (m_cssomWrapper) { - ASSERT(m_cssomWrapper->parentElement() == parentElement); - return m_cssomWrapper.get(); + // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid + // the compiler converting it to an int multiple times in the loop. + uint16_t id = static_cast<uint16_t>(propertyID); + const CSSProperty* properties = m_propertyVector.data(); + for (int n = m_propertyVector.size() - 1 ; n >= 0; --n) { + if (properties[n].metadata().m_propertyID == id) { + // Only enabled or internal properties should be part of the style. + ASSERT(RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID) || isInternalProperty(propertyID)); + return n; + } } - m_cssomWrapper = adoptPtr(new InlineCSSStyleDeclaration(this, parentElement)); - return m_cssomWrapper.get(); + + return -1; +} + +void MutableStylePropertySet::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_cssomWrapper); + visitor->trace(m_propertyVector); + StylePropertySet::traceAfterDispatch(visitor); } unsigned StylePropertySet::averageSizeInBytes() @@ -668,7 +577,7 @@ unsigned StylePropertySet::averageSizeInBytes() } // See the function above if you need to update this. -struct SameSizeAsStylePropertySet : public RefCounted<SameSizeAsStylePropertySet> { +struct SameSizeAsStylePropertySet : public RefCountedWillBeRefCountedGarbageCollected<SameSizeAsStylePropertySet> { unsigned bitfield; }; COMPILE_ASSERT(sizeof(StylePropertySet) == sizeof(SameSizeAsStylePropertySet), style_property_set_should_stay_small); @@ -680,23 +589,18 @@ void StylePropertySet::showStyle() } #endif -PassRefPtr<MutableStylePropertySet> MutableStylePropertySet::create(CSSParserMode cssParserMode) +PassRefPtrWillBeRawPtr<MutableStylePropertySet> MutableStylePropertySet::create(CSSParserMode cssParserMode) { - return adoptRef(new MutableStylePropertySet(cssParserMode)); + return adoptRefWillBeRefCountedGarbageCollected(new MutableStylePropertySet(cssParserMode)); } -PassRefPtr<MutableStylePropertySet> MutableStylePropertySet::create(const CSSProperty* properties, unsigned count) +PassRefPtrWillBeRawPtr<MutableStylePropertySet> MutableStylePropertySet::create(const CSSProperty* properties, unsigned count) { - return adoptRef(new MutableStylePropertySet(properties, count)); + return adoptRefWillBeRefCountedGarbageCollected(new MutableStylePropertySet(properties, count)); } String StylePropertySet::PropertyReference::cssName() const { - if (id() == CSSPropertyVariable) { - if (!propertyValue()->isVariableValue()) - return emptyString(); // Should not happen, but if it does, avoid a bad cast. - return "var-" + toCSSVariableValue(propertyValue())->name(); - } return getPropertyNameString(id()); } diff --git a/chromium/third_party/WebKit/Source/core/css/StylePropertySet.h b/chromium/third_party/WebKit/Source/core/css/StylePropertySet.h index 1003f3b93e5..3e1a42786e0 100644 --- a/chromium/third_party/WebKit/Source/core/css/StylePropertySet.h +++ b/chromium/third_party/WebKit/Source/core/css/StylePropertySet.h @@ -21,11 +21,10 @@ #ifndef StylePropertySet_h #define StylePropertySet_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "core/css/CSSParserMode.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSProperty.h" -#include "core/css/CSSVariablesIterator.h" #include "core/css/PropertySetCSSStyleDeclaration.h" #include "wtf/ListHashSet.h" #include "wtf/Vector.h" @@ -42,12 +41,20 @@ class MutableStylePropertySet; class StylePropertyShorthand; class StyleSheetContents; -class StylePropertySet : public RefCounted<StylePropertySet> { +class StylePropertySet : public RefCountedWillBeRefCountedGarbageCollected<StylePropertySet> { friend class PropertyReference; public: + +#if ENABLE(OILPAN) + // When oilpan is enabled override the finalize method to dispatch to the subclasses' + // destructor. This can be removed once the MutableStylePropertySet's OwnPtr is moved + // to the heap. + void finalizeGarbageCollectedObject(); +#else // Override RefCounted's deref() to ensure operator delete is called on // the appropriate subclass type. void deref(); +#endif class PropertyReference { public: @@ -87,32 +94,26 @@ public: bool isEmpty() const; PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); } int findPropertyIndex(CSSPropertyID) const; - size_t findVariableIndex(const AtomicString& name) const; - PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; + PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; String getPropertyValue(CSSPropertyID) const; - unsigned variableCount() const; - String variableValue(const AtomicString& name) const; bool propertyIsImportant(CSSPropertyID) const; CSSPropertyID getPropertyShorthand(CSSPropertyID) const; bool isPropertyImplicit(CSSPropertyID) const; - PassRefPtr<MutableStylePropertySet> copyBlockProperties() const; + PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyBlockProperties() const; CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); } - void addSubresourceStyleURLs(ListHashSet<KURL>&, StyleSheetContents* contextStyleSheet) const; - - PassRefPtr<MutableStylePropertySet> mutableCopy() const; + PassRefPtrWillBeRawPtr<MutableStylePropertySet> mutableCopy() const; PassRefPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const; - PassRefPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; + PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; String asText() const; bool isMutable() const { return m_isMutable; } - bool hasCSSOMWrapper() const; bool hasFailedOrCanceledSubresources() const; @@ -124,6 +125,9 @@ public: bool propertyMatches(CSSPropertyID, const CSSValue*) const; + void trace(Visitor*); + void traceAfterDispatch(Visitor*) { } + protected: enum { MaxArraySize = (1 << 28) - 1 }; @@ -154,8 +158,16 @@ public: unsigned propertyCount() const { return m_arraySize; } - const CSSValue** valueArray() const; + const RawPtrWillBeMember<CSSValue>* valueArray() const; const StylePropertyMetadata* metadataArray() const; + int findPropertyIndex(CSSPropertyID) const; + + void traceAfterDispatch(Visitor*); + + void* operator new(std::size_t, void* location) + { + return location; + } void* m_storage; @@ -163,14 +175,14 @@ private: ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode); }; -inline const CSSValue** ImmutableStylePropertySet::valueArray() const +inline const RawPtrWillBeMember<CSSValue>* ImmutableStylePropertySet::valueArray() const { - return reinterpret_cast<const CSSValue**>(const_cast<const void**>(&(this->m_storage))); + return reinterpret_cast<const RawPtrWillBeMember<CSSValue>*>(const_cast<const void**>(&(this->m_storage))); } inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const { - return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(CSSValue*)]); + return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(RawPtrWillBeMember<CSSValue>)]); } DEFINE_TYPE_CASTS(ImmutableStylePropertySet, StylePropertySet, set, !set->isMutable(), !set.isMutable()); @@ -183,18 +195,17 @@ inline ImmutableStylePropertySet* toImmutableStylePropertySet(const RefPtr<Style class MutableStylePropertySet : public StylePropertySet { public: ~MutableStylePropertySet() { } - static PassRefPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode); - static PassRefPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count); + static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode); + static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count); unsigned propertyCount() const { return m_propertyVector.size(); } - PropertySetCSSStyleDeclaration* cssStyleDeclaration(); - void addParsedProperties(const Vector<CSSProperty, 256>&); + void addParsedProperties(const WillBeHeapVector<CSSProperty, 256>&); void addParsedProperty(const CSSProperty&); // These expand shorthand properties into multiple properties. bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); - void setProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important = false); + void setProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important = false); // These do not. FIXME: This is too messy, we can do better. bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false); @@ -202,7 +213,6 @@ public: void appendPrefixingVariantProperty(const CSSProperty&); void setPrefixingVariantProperty(const CSSProperty&); void setProperty(const CSSProperty&, CSSProperty* slot = 0); - bool setVariableValue(const AtomicString& name, const String& value, bool important = false); bool removeProperty(CSSPropertyID, String* returnText = 0); void removePrefixedOrUnprefixedProperty(CSSPropertyID); @@ -210,10 +220,6 @@ public: bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); void removeEquivalentProperties(const StylePropertySet*); void removeEquivalentProperties(const CSSStyleDeclaration*); - bool removeVariable(const AtomicString& name); - bool clearVariables(); - - PassRefPtr<CSSVariablesIterator> variablesIterator() { return VariablesIterator::create(this); } void mergeAndOverrideOnConflict(const StylePropertySet*); @@ -221,40 +227,22 @@ public: void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet); CSSStyleDeclaration* ensureCSSStyleDeclaration(); - CSSStyleDeclaration* ensureInlineCSSStyleDeclaration(Element* parentElement); + int findPropertyIndex(CSSPropertyID) const; - Vector<CSSProperty, 4> m_propertyVector; + void traceAfterDispatch(Visitor*); private: - class VariablesIterator : public CSSVariablesIterator { - public: - virtual ~VariablesIterator() { } - static PassRefPtr<VariablesIterator> create(MutableStylePropertySet*); - private: - explicit VariablesIterator(MutableStylePropertySet* propertySet) : m_propertySet(propertySet) { } - void takeRemainingNames(Vector<AtomicString>& remainingNames) { m_remainingNames.swap(remainingNames); } - virtual void advance() OVERRIDE; - virtual bool atEnd() const OVERRIDE { return m_remainingNames.isEmpty(); } - virtual AtomicString name() const OVERRIDE { return m_remainingNames.last(); } - virtual String value() const OVERRIDE { return m_propertySet->variableValue(name()); } - virtual void addedVariable(const AtomicString& name) OVERRIDE; - virtual void removedVariable(const AtomicString& name) OVERRIDE; - virtual void clearedVariables() OVERRIDE; - - RefPtr<MutableStylePropertySet> m_propertySet; - Vector<AtomicString> m_remainingNames; - Vector<AtomicString> m_newNames; - }; - explicit MutableStylePropertySet(CSSParserMode); explicit MutableStylePropertySet(const StylePropertySet&); MutableStylePropertySet(const CSSProperty* properties, unsigned count); bool removeShorthandProperty(CSSPropertyID); CSSProperty* findCSSPropertyWithID(CSSPropertyID); - OwnPtr<PropertySetCSSStyleDeclaration> m_cssomWrapper; + OwnPtrWillBeMember<PropertySetCSSStyleDeclaration> m_cssomWrapper; friend class StylePropertySet; + + WillBeHeapVector<CSSProperty, 4> m_propertyVector; }; DEFINE_TYPE_CASTS(MutableStylePropertySet, StylePropertySet, set, set->isMutable(), set.isMutable()); @@ -290,6 +278,7 @@ inline bool StylePropertySet::isEmpty() const return !propertyCount(); } +#if !ENABLE(OILPAN) inline void StylePropertySet::deref() { if (!derefBase()) @@ -300,6 +289,14 @@ inline void StylePropertySet::deref() else delete toImmutableStylePropertySet(this); } +#endif // !ENABLE(OILPAN) + +inline int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const +{ + if (m_isMutable) + return toMutableStylePropertySet(this)->findPropertyIndex(propertyID); + return toImmutableStylePropertySet(this)->findPropertyIndex(propertyID); +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/StylePropertyShorthandCustom.cpp b/chromium/third_party/WebKit/Source/core/css/StylePropertyShorthandCustom.cpp index b157746c8b9..9284ca7e8bb 100644 --- a/chromium/third_party/WebKit/Source/core/css/StylePropertyShorthandCustom.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StylePropertyShorthandCustom.cpp @@ -20,7 +20,7 @@ */ #include "config.h" -#include "StylePropertyShorthand.h" +#include "core/StylePropertyShorthand.h" namespace WebCore { @@ -86,6 +86,31 @@ const StylePropertyShorthand& webkitAnimationShorthandForParsing() return webkitAnimationLonghandsForParsing; } +// Similar to animations, we have property after timing-function and delay after duration +const StylePropertyShorthand& transitionShorthandForParsing() +{ + static const CSSPropertyID transitionProperties[] = { + CSSPropertyTransitionDuration, + CSSPropertyTransitionTimingFunction, + CSSPropertyTransitionDelay, + CSSPropertyTransitionProperty + }; + DEFINE_STATIC_LOCAL(StylePropertyShorthand, transitionLonghands, (CSSPropertyTransition, transitionProperties, WTF_ARRAY_LENGTH(transitionProperties))); + return transitionLonghands; +} + +const StylePropertyShorthand& webkitTransitionShorthandForParsing() +{ + static const CSSPropertyID webkitTransitionProperties[] = { + CSSPropertyWebkitTransitionDuration, + CSSPropertyWebkitTransitionTimingFunction, + CSSPropertyWebkitTransitionDelay, + CSSPropertyWebkitTransitionProperty + }; + DEFINE_STATIC_LOCAL(StylePropertyShorthand, webkitTransitionLonghands, (CSSPropertyWebkitTransition, webkitTransitionProperties, WTF_ARRAY_LENGTH(webkitTransitionProperties))); + return webkitTransitionLonghands; +} + // Returns an empty list if the property is not a shorthand, otherwise the list of longhands for parsing. const StylePropertyShorthand& parsingShorthandForProperty(CSSPropertyID propertyID) { @@ -96,6 +121,10 @@ const StylePropertyShorthand& parsingShorthandForProperty(CSSPropertyID property return borderShorthandForParsing(); case CSSPropertyWebkitAnimation: return webkitAnimationShorthandForParsing(); + case CSSPropertyTransition: + return transitionShorthandForParsing(); + case CSSPropertyWebkitTransition: + return webkitTransitionShorthandForParsing(); default: return shorthandForProperty(propertyID); } @@ -113,6 +142,22 @@ bool isExpandedShorthand(CSSPropertyID id) return shorthandForProperty(id).length(); } +bool isExpandedShorthandForAll(CSSPropertyID propertyId) +{ + // FIXME: isExpandedShorthand says "font" is not an expanded shorthand, + // but font is expanded to font-family, font-size, and so on. + // StylePropertySerializer::asText should not generate css text like + // "font: initial; font-family: initial;...". To avoid this, we need to + // treat "font" as an expanded shorthand. + // And while applying "all" property, we cannot apply "font" property + // directly. This causes ASSERT crash, because StyleBuilder assume that + // all given properties are not expanded shorthands. + // "marker" has the same issue. + if (propertyId == CSSPropertyMarker || propertyId == CSSPropertyFont) + return true; + return shorthandForProperty(propertyId).length(); +} + unsigned indexOfShorthandForLonghand(CSSPropertyID shorthandID, const Vector<StylePropertyShorthand, 4>& shorthands) { for (unsigned i = 0; i < shorthands.size(); ++i) { diff --git a/chromium/third_party/WebKit/Source/core/css/StyleRule.cpp b/chromium/third_party/WebKit/Source/core/css/StyleRule.cpp index 299f7a2300d..7735706796f 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleRule.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StyleRule.cpp @@ -22,14 +22,12 @@ #include "config.h" #include "core/css/StyleRule.h" -#include "RuntimeEnabledFeatures.h" #include "core/css/CSSFilterRule.h" #include "core/css/CSSFontFaceRule.h" #include "core/css/CSSImportRule.h" #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSMediaRule.h" #include "core/css/CSSPageRule.h" -#include "core/css/CSSRegionRule.h" #include "core/css/CSSStyleRule.h" #include "core/css/CSSSupportsRule.h" #include "core/css/CSSViewportRule.h" @@ -38,22 +36,100 @@ namespace WebCore { -struct SameSizeAsStyleRuleBase : public WTF::RefCountedBase { +struct SameSizeAsStyleRuleBase : public RefCountedWillBeRefCountedGarbageCollected<SameSizeAsStyleRuleBase> { unsigned bitfields; }; COMPILE_ASSERT(sizeof(StyleRuleBase) <= sizeof(SameSizeAsStyleRuleBase), StyleRuleBase_should_stay_small); -PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet) const +PassRefPtrWillBeRawPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet) const { return createCSSOMWrapper(parentSheet, 0); } -PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSRule* parentRule) const +PassRefPtrWillBeRawPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSRule* parentRule) const { return createCSSOMWrapper(0, parentRule); } +void StyleRuleBase::trace(Visitor* visitor) +{ + switch (type()) { + case Style: + toStyleRule(this)->traceAfterDispatch(visitor); + return; + case Page: + toStyleRulePage(this)->traceAfterDispatch(visitor); + return; + case FontFace: + toStyleRuleFontFace(this)->traceAfterDispatch(visitor); + return; + case Media: + toStyleRuleMedia(this)->traceAfterDispatch(visitor); + return; + case Supports: + toStyleRuleSupports(this)->traceAfterDispatch(visitor); + return; + case Import: + toStyleRuleImport(this)->traceAfterDispatch(visitor); + return; + case Keyframes: + toStyleRuleKeyframes(this)->traceAfterDispatch(visitor); + return; + case Viewport: + toStyleRuleViewport(this)->traceAfterDispatch(visitor); + return; + case Filter: + toStyleRuleFilter(this)->traceAfterDispatch(visitor); + return; + case Unknown: + case Charset: + case Keyframe: + ASSERT_NOT_REACHED(); + return; + } + ASSERT_NOT_REACHED(); +} + +void StyleRuleBase::finalizeGarbageCollectedObject() +{ + switch (type()) { + case Style: + toStyleRule(this)->~StyleRule(); + return; + case Page: + toStyleRulePage(this)->~StyleRulePage(); + return; + case FontFace: + toStyleRuleFontFace(this)->~StyleRuleFontFace(); + return; + case Media: + toStyleRuleMedia(this)->~StyleRuleMedia(); + return; + case Supports: + toStyleRuleSupports(this)->~StyleRuleSupports(); + return; + case Import: + toStyleRuleImport(this)->~StyleRuleImport(); + return; + case Keyframes: + toStyleRuleKeyframes(this)->~StyleRuleKeyframes(); + return; + case Viewport: + toStyleRuleViewport(this)->~StyleRuleViewport(); + return; + case Filter: + toStyleRuleFilter(this)->~StyleRuleFilter(); + return; + case Unknown: + case Charset: + case Keyframe: + ASSERT_NOT_REACHED(); + return; + } + ASSERT_NOT_REACHED(); +} + void StyleRuleBase::destroy() { switch (type()) { @@ -72,9 +148,6 @@ void StyleRuleBase::destroy() case Supports: delete toStyleRuleSupports(this); return; - case Region: - delete toStyleRuleRegion(this); - return; case Import: delete toStyleRuleImport(this); return; @@ -96,7 +169,7 @@ void StyleRuleBase::destroy() ASSERT_NOT_REACHED(); } -PassRefPtr<StyleRuleBase> StyleRuleBase::copy() const +PassRefPtrWillBeRawPtr<StyleRuleBase> StyleRuleBase::copy() const { switch (type()) { case Style: @@ -109,12 +182,10 @@ PassRefPtr<StyleRuleBase> StyleRuleBase::copy() const return toStyleRuleMedia(this)->copy(); case Supports: return toStyleRuleSupports(this)->copy(); - case Region: - return toStyleRuleRegion(this)->copy(); case Import: // FIXME: Copy import rules. ASSERT_NOT_REACHED(); - return 0; + return nullptr; case Keyframes: return toStyleRuleKeyframes(this)->copy(); case Viewport: @@ -125,15 +196,15 @@ PassRefPtr<StyleRuleBase> StyleRuleBase::copy() const case Charset: case Keyframe: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } ASSERT_NOT_REACHED(); - return 0; + return nullptr; } -PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const +PassRefPtrWillBeRawPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const { - RefPtr<CSSRule> rule; + RefPtrWillBeRawPtr<CSSRule> rule = nullptr; StyleRuleBase* self = const_cast<StyleRuleBase*>(this); switch (type()) { case Style: @@ -151,9 +222,6 @@ PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet case Supports: rule = CSSSupportsRule::create(toStyleRuleSupports(self), parentSheet); break; - case Region: - rule = CSSRegionRule::create(toStyleRuleRegion(self), parentSheet); - break; case Import: rule = CSSImportRule::create(toStyleRuleImport(self), parentSheet); break; @@ -170,7 +238,7 @@ PassRefPtr<CSSRule> StyleRuleBase::createCSSOMWrapper(CSSStyleSheet* parentSheet case Charset: case Keyframe: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } if (parentRule) rule->setParentRule(parentRule); @@ -198,11 +266,11 @@ StyleRule::~StyleRule() { } -MutableStylePropertySet* StyleRule::mutableProperties() +MutableStylePropertySet& StyleRule::mutableProperties() { if (!m_properties->isMutable()) m_properties = m_properties->mutableCopy(); - return toMutableStylePropertySet(m_properties); + return *toMutableStylePropertySet(m_properties); } void StyleRule::setProperties(PassRefPtr<StylePropertySet> properties) @@ -226,11 +294,11 @@ StyleRulePage::~StyleRulePage() { } -MutableStylePropertySet* StyleRulePage::mutableProperties() +MutableStylePropertySet& StyleRulePage::mutableProperties() { if (!m_properties->isMutable()) m_properties = m_properties->mutableCopy(); - return toMutableStylePropertySet(m_properties); + return *toMutableStylePropertySet(m_properties); } void StyleRulePage::setProperties(PassRefPtr<StylePropertySet> properties) @@ -253,11 +321,11 @@ StyleRuleFontFace::~StyleRuleFontFace() { } -MutableStylePropertySet* StyleRuleFontFace::mutableProperties() +MutableStylePropertySet& StyleRuleFontFace::mutableProperties() { if (!m_properties->isMutable()) m_properties = m_properties->mutableCopy(); - return toMutableStylePropertySet(m_properties); + return *toMutableStylePropertySet(m_properties); } void StyleRuleFontFace::setProperties(PassRefPtr<StylePropertySet> properties) @@ -265,7 +333,7 @@ void StyleRuleFontFace::setProperties(PassRefPtr<StylePropertySet> properties) m_properties = properties; } -StyleRuleGroup::StyleRuleGroup(Type type, Vector<RefPtr<StyleRuleBase> >& adoptRule) +StyleRuleGroup::StyleRuleGroup(Type type, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRule) : StyleRuleBase(type) { m_childRules.swap(adoptRule); @@ -279,7 +347,7 @@ StyleRuleGroup::StyleRuleGroup(const StyleRuleGroup& o) m_childRules[i] = o.m_childRules[i]->copy(); } -void StyleRuleGroup::wrapperInsertRule(unsigned index, PassRefPtr<StyleRuleBase> rule) +void StyleRuleGroup::wrapperInsertRule(unsigned index, PassRefPtrWillBeRawPtr<StyleRuleBase> rule) { m_childRules.insert(index, rule); } @@ -289,7 +357,13 @@ void StyleRuleGroup::wrapperRemoveRule(unsigned index) m_childRules.remove(index); } -StyleRuleMedia::StyleRuleMedia(PassRefPtr<MediaQuerySet> media, Vector<RefPtr<StyleRuleBase> >& adoptRules) +void StyleRuleGroup::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_childRules); + StyleRuleBase::traceAfterDispatch(visitor); +} + +StyleRuleMedia::StyleRuleMedia(PassRefPtrWillBeRawPtr<MediaQuerySet> media, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRules) : StyleRuleGroup(Media, adoptRules) , m_mediaQueries(media) { @@ -302,7 +376,13 @@ StyleRuleMedia::StyleRuleMedia(const StyleRuleMedia& o) m_mediaQueries = o.m_mediaQueries->copy(); } -StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase> >& adoptRules) +void StyleRuleMedia::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_mediaQueries); + StyleRuleGroup::traceAfterDispatch(visitor); +} + +StyleRuleSupports::StyleRuleSupports(const String& conditionText, bool conditionIsSupported, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRules) : StyleRuleGroup(Supports, adoptRules) , m_conditionText(conditionText) , m_conditionIsSupported(conditionIsSupported) @@ -316,20 +396,6 @@ StyleRuleSupports::StyleRuleSupports(const StyleRuleSupports& o) { } -StyleRuleRegion::StyleRuleRegion(Vector<OwnPtr<CSSParserSelector> >* selectors, Vector<RefPtr<StyleRuleBase> >& adoptRules) - : StyleRuleGroup(Region, adoptRules) -{ - ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled()); - m_selectorList.adoptSelectorVector(*selectors); -} - -StyleRuleRegion::StyleRuleRegion(const StyleRuleRegion& o) - : StyleRuleGroup(o) - , m_selectorList(o.m_selectorList) -{ - ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled()); -} - StyleRuleViewport::StyleRuleViewport() : StyleRuleBase(Viewport) { @@ -345,11 +411,11 @@ StyleRuleViewport::~StyleRuleViewport() { } -MutableStylePropertySet* StyleRuleViewport::mutableProperties() +MutableStylePropertySet& StyleRuleViewport::mutableProperties() { if (!m_properties->isMutable()) m_properties = m_properties->mutableCopy(); - return toMutableStylePropertySet(m_properties); + return *toMutableStylePropertySet(m_properties); } void StyleRuleViewport::setProperties(PassRefPtr<StylePropertySet> properties) @@ -374,11 +440,11 @@ StyleRuleFilter::~StyleRuleFilter() { } -MutableStylePropertySet* StyleRuleFilter::mutableProperties() +MutableStylePropertySet& StyleRuleFilter::mutableProperties() { if (!m_properties->isMutable()) m_properties = m_properties->mutableCopy(); - return toMutableStylePropertySet(m_properties); + return *toMutableStylePropertySet(m_properties); } void StyleRuleFilter::setProperties(PassRefPtr<StylePropertySet> properties) diff --git a/chromium/third_party/WebKit/Source/core/css/StyleRule.h b/chromium/third_party/WebKit/Source/core/css/StyleRule.h index e1216ebeedd..ab0853d7844 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleRule.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleRule.h @@ -24,6 +24,7 @@ #include "core/css/CSSSelectorList.h" #include "core/css/MediaList.h" +#include "platform/heap/Handle.h" #include "wtf/RefPtr.h" namespace WebCore { @@ -34,8 +35,8 @@ class CSSStyleSheet; class MutableStylePropertySet; class StylePropertySet; -class StyleRuleBase : public WTF::RefCountedBase { - WTF_MAKE_FAST_ALLOCATED; +class StyleRuleBase : public RefCountedWillBeGarbageCollectedFinalized<StyleRuleBase> { + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: enum Type { Unknown, // Not used. @@ -49,7 +50,6 @@ public: Keyframe, // Not used. These are internally non-rule StyleKeyframe objects. Supports = 12, Viewport = 15, - Region = 16, Filter = 17 }; @@ -61,213 +61,216 @@ public: bool isMediaRule() const { return type() == Media; } bool isPageRule() const { return type() == Page; } bool isStyleRule() const { return type() == Style; } - bool isRegionRule() const { return type() == Region; } bool isSupportsRule() const { return type() == Supports; } bool isViewportRule() const { return type() == Viewport; } bool isImportRule() const { return type() == Import; } bool isFilterRule() const { return type() == Filter; } - PassRefPtr<StyleRuleBase> copy() const; + PassRefPtrWillBeRawPtr<StyleRuleBase> copy() const; +#if !ENABLE(OILPAN) void deref() { if (derefBase()) destroy(); } +#endif // !ENABLE(OILPAN) // FIXME: There shouldn't be any need for the null parent version. - PassRefPtr<CSSRule> createCSSOMWrapper(CSSStyleSheet* parentSheet = 0) const; - PassRefPtr<CSSRule> createCSSOMWrapper(CSSRule* parentRule) const; + PassRefPtrWillBeRawPtr<CSSRule> createCSSOMWrapper(CSSStyleSheet* parentSheet = 0) const; + PassRefPtrWillBeRawPtr<CSSRule> createCSSOMWrapper(CSSRule* parentRule) const; + + void trace(Visitor*); + void traceAfterDispatch(Visitor*) { }; + void finalizeGarbageCollectedObject(); protected: StyleRuleBase(Type type) : m_type(type) { } - StyleRuleBase(const StyleRuleBase& o) : WTF::RefCountedBase(), m_type(o.m_type) { } + StyleRuleBase(const StyleRuleBase& o) : m_type(o.m_type) { } ~StyleRuleBase() { } private: void destroy(); - PassRefPtr<CSSRule> createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const; + PassRefPtrWillBeRawPtr<CSSRule> createCSSOMWrapper(CSSStyleSheet* parentSheet, CSSRule* parentRule) const; unsigned m_type : 5; }; class StyleRule : public StyleRuleBase { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<StyleRule> create() { return adoptRef(new StyleRule()); } + static PassRefPtrWillBeRawPtr<StyleRule> create() { return adoptRefWillBeNoop(new StyleRule()); } ~StyleRule(); const CSSSelectorList& selectorList() const { return m_selectorList; } - const StylePropertySet* properties() const { return m_properties.get(); } - MutableStylePropertySet* mutableProperties(); + const StylePropertySet& properties() const { return *m_properties; } + MutableStylePropertySet& mutableProperties(); void parserAdoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectors) { m_selectorList.adoptSelectorVector(selectors); } void wrapperAdoptSelectorList(CSSSelectorList& selectors) { m_selectorList.adopt(selectors); } void setProperties(PassRefPtr<StylePropertySet>); - PassRefPtr<StyleRule> copy() const { return adoptRef(new StyleRule(*this)); } + PassRefPtrWillBeRawPtr<StyleRule> copy() const { return adoptRefWillBeNoop(new StyleRule(*this)); } static unsigned averageSizeInBytes(); + void traceAfterDispatch(Visitor* visitor) { StyleRuleBase::traceAfterDispatch(visitor); } + private: StyleRule(); StyleRule(const StyleRule&); - RefPtr<StylePropertySet> m_properties; + RefPtr<StylePropertySet> m_properties; // Cannot be null. CSSSelectorList m_selectorList; }; class StyleRuleFontFace : public StyleRuleBase { public: - static PassRefPtr<StyleRuleFontFace> create() { return adoptRef(new StyleRuleFontFace); } + static PassRefPtrWillBeRawPtr<StyleRuleFontFace> create() { return adoptRefWillBeNoop(new StyleRuleFontFace); } ~StyleRuleFontFace(); - const StylePropertySet* properties() const { return m_properties.get(); } - MutableStylePropertySet* mutableProperties(); + const StylePropertySet& properties() const { return *m_properties; } + MutableStylePropertySet& mutableProperties(); void setProperties(PassRefPtr<StylePropertySet>); - PassRefPtr<StyleRuleFontFace> copy() const { return adoptRef(new StyleRuleFontFace(*this)); } + PassRefPtrWillBeRawPtr<StyleRuleFontFace> copy() const { return adoptRefWillBeNoop(new StyleRuleFontFace(*this)); } + + void traceAfterDispatch(Visitor* visitor) { StyleRuleBase::traceAfterDispatch(visitor); } private: StyleRuleFontFace(); StyleRuleFontFace(const StyleRuleFontFace&); - RefPtr<StylePropertySet> m_properties; + RefPtr<StylePropertySet> m_properties; // Cannot be null. }; class StyleRulePage : public StyleRuleBase { public: - static PassRefPtr<StyleRulePage> create() { return adoptRef(new StyleRulePage); } + static PassRefPtrWillBeRawPtr<StyleRulePage> create() { return adoptRefWillBeNoop(new StyleRulePage); } ~StyleRulePage(); const CSSSelector* selector() const { return m_selectorList.first(); } - const StylePropertySet* properties() const { return m_properties.get(); } - MutableStylePropertySet* mutableProperties(); + const StylePropertySet& properties() const { return *m_properties; } + MutableStylePropertySet& mutableProperties(); void parserAdoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectors) { m_selectorList.adoptSelectorVector(selectors); } void wrapperAdoptSelectorList(CSSSelectorList& selectors) { m_selectorList.adopt(selectors); } void setProperties(PassRefPtr<StylePropertySet>); - PassRefPtr<StyleRulePage> copy() const { return adoptRef(new StyleRulePage(*this)); } + PassRefPtrWillBeRawPtr<StyleRulePage> copy() const { return adoptRefWillBeNoop(new StyleRulePage(*this)); } + + void traceAfterDispatch(Visitor* visitor) { StyleRuleBase::traceAfterDispatch(visitor); } private: StyleRulePage(); StyleRulePage(const StyleRulePage&); - RefPtr<StylePropertySet> m_properties; + RefPtr<StylePropertySet> m_properties; // Cannot be null. CSSSelectorList m_selectorList; }; class StyleRuleGroup : public StyleRuleBase { public: - const Vector<RefPtr<StyleRuleBase> >& childRules() const { return m_childRules; } + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& childRules() const { return m_childRules; } - void wrapperInsertRule(unsigned, PassRefPtr<StyleRuleBase>); + void wrapperInsertRule(unsigned, PassRefPtrWillBeRawPtr<StyleRuleBase>); void wrapperRemoveRule(unsigned); + void traceAfterDispatch(Visitor*); + protected: - StyleRuleGroup(Type, Vector<RefPtr<StyleRuleBase> >& adoptRule); + StyleRuleGroup(Type, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRule); StyleRuleGroup(const StyleRuleGroup&); private: - Vector<RefPtr<StyleRuleBase> > m_childRules; + WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> > m_childRules; }; class StyleRuleMedia : public StyleRuleGroup { public: - static PassRefPtr<StyleRuleMedia> create(PassRefPtr<MediaQuerySet> media, Vector<RefPtr<StyleRuleBase> >& adoptRules) + static PassRefPtrWillBeRawPtr<StyleRuleMedia> create(PassRefPtrWillBeRawPtr<MediaQuerySet> media, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRules) { - return adoptRef(new StyleRuleMedia(media, adoptRules)); + return adoptRefWillBeNoop(new StyleRuleMedia(media, adoptRules)); } MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); } - PassRefPtr<StyleRuleMedia> copy() const { return adoptRef(new StyleRuleMedia(*this)); } + PassRefPtrWillBeRawPtr<StyleRuleMedia> copy() const { return adoptRefWillBeNoop(new StyleRuleMedia(*this)); } + + void traceAfterDispatch(Visitor*); private: - StyleRuleMedia(PassRefPtr<MediaQuerySet>, Vector<RefPtr<StyleRuleBase> >& adoptRules); + StyleRuleMedia(PassRefPtrWillBeRawPtr<MediaQuerySet>, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRules); StyleRuleMedia(const StyleRuleMedia&); - RefPtr<MediaQuerySet> m_mediaQueries; + RefPtrWillBeMember<MediaQuerySet> m_mediaQueries; }; class StyleRuleSupports : public StyleRuleGroup { public: - static PassRefPtr<StyleRuleSupports> create(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase> >& adoptRules) + static PassRefPtrWillBeRawPtr<StyleRuleSupports> create(const String& conditionText, bool conditionIsSupported, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRules) { - return adoptRef(new StyleRuleSupports(conditionText, conditionIsSupported, adoptRules)); + return adoptRefWillBeNoop(new StyleRuleSupports(conditionText, conditionIsSupported, adoptRules)); } String conditionText() const { return m_conditionText; } bool conditionIsSupported() const { return m_conditionIsSupported; } - PassRefPtr<StyleRuleSupports> copy() const { return adoptRef(new StyleRuleSupports(*this)); } + PassRefPtrWillBeRawPtr<StyleRuleSupports> copy() const { return adoptRefWillBeNoop(new StyleRuleSupports(*this)); } + + void traceAfterDispatch(Visitor* visitor) { StyleRuleGroup::traceAfterDispatch(visitor); } private: - StyleRuleSupports(const String& conditionText, bool conditionIsSupported, Vector<RefPtr<StyleRuleBase> >& adoptRules); + StyleRuleSupports(const String& conditionText, bool conditionIsSupported, WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& adoptRules); StyleRuleSupports(const StyleRuleSupports&); String m_conditionText; bool m_conditionIsSupported; }; -class StyleRuleRegion : public StyleRuleGroup { -public: - static PassRefPtr<StyleRuleRegion> create(Vector<OwnPtr<CSSParserSelector> >* selectors, Vector<RefPtr<StyleRuleBase> >& adoptRules) - { - return adoptRef(new StyleRuleRegion(selectors, adoptRules)); - } - - const CSSSelectorList& selectorList() const { return m_selectorList; } - - PassRefPtr<StyleRuleRegion> copy() const { return adoptRef(new StyleRuleRegion(*this)); } - -private: - StyleRuleRegion(Vector<OwnPtr<CSSParserSelector> >*, Vector<RefPtr<StyleRuleBase> >& adoptRules); - StyleRuleRegion(const StyleRuleRegion&); - - CSSSelectorList m_selectorList; -}; - class StyleRuleViewport : public StyleRuleBase { public: - static PassRefPtr<StyleRuleViewport> create() { return adoptRef(new StyleRuleViewport); } + static PassRefPtrWillBeRawPtr<StyleRuleViewport> create() { return adoptRefWillBeNoop(new StyleRuleViewport); } ~StyleRuleViewport(); - const StylePropertySet* properties() const { return m_properties.get(); } - MutableStylePropertySet* mutableProperties(); + const StylePropertySet& properties() const { return *m_properties; } + MutableStylePropertySet& mutableProperties(); void setProperties(PassRefPtr<StylePropertySet>); - PassRefPtr<StyleRuleViewport> copy() const { return adoptRef(new StyleRuleViewport(*this)); } + PassRefPtrWillBeRawPtr<StyleRuleViewport> copy() const { return adoptRefWillBeNoop(new StyleRuleViewport(*this)); } + + void traceAfterDispatch(Visitor* visitor) { StyleRuleBase::traceAfterDispatch(visitor); } private: StyleRuleViewport(); StyleRuleViewport(const StyleRuleViewport&); - RefPtr<StylePropertySet> m_properties; + RefPtr<StylePropertySet> m_properties; // Cannot be null }; class StyleRuleFilter : public StyleRuleBase { public: - static PassRefPtr<StyleRuleFilter> create(const String& filterName) { return adoptRef(new StyleRuleFilter(filterName)); } + static PassRefPtrWillBeRawPtr<StyleRuleFilter> create(const String& filterName) { return adoptRefWillBeNoop(new StyleRuleFilter(filterName)); } ~StyleRuleFilter(); const String& filterName() const { return m_filterName; } - const StylePropertySet* properties() const { return m_properties.get(); } - MutableStylePropertySet* mutableProperties(); + const StylePropertySet& properties() const { return *m_properties; } + MutableStylePropertySet& mutableProperties(); void setProperties(PassRefPtr<StylePropertySet>); - PassRefPtr<StyleRuleFilter> copy() const { return adoptRef(new StyleRuleFilter(*this)); } + PassRefPtrWillBeRawPtr<StyleRuleFilter> copy() const { return adoptRefWillBeNoop(new StyleRuleFilter(*this)); } + + void traceAfterDispatch(Visitor* visitor) { StyleRuleBase::traceAfterDispatch(visitor); } private: StyleRuleFilter(const String&); @@ -285,7 +288,6 @@ DEFINE_STYLE_RULE_TYPE_CASTS(FontFace); DEFINE_STYLE_RULE_TYPE_CASTS(Page); DEFINE_STYLE_RULE_TYPE_CASTS(Media); DEFINE_STYLE_RULE_TYPE_CASTS(Supports); -DEFINE_STYLE_RULE_TYPE_CASTS(Region); DEFINE_STYLE_RULE_TYPE_CASTS(Viewport); DEFINE_STYLE_RULE_TYPE_CASTS(Filter); diff --git a/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.cpp b/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.cpp index aff60cb9ecd..13fd117ca58 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.cpp @@ -22,7 +22,7 @@ #include "config.h" #include "core/css/StyleRuleImport.h" -#include "FetchInitiatorTypeNames.h" +#include "core/FetchInitiatorTypeNames.h" #include "core/css/StyleSheetContents.h" #include "core/dom/Document.h" #include "core/fetch/CSSStyleSheetResource.h" @@ -31,14 +31,14 @@ namespace WebCore { -PassRefPtr<StyleRuleImport> StyleRuleImport::create(const String& href, PassRefPtr<MediaQuerySet> media) +PassRefPtrWillBeRawPtr<StyleRuleImport> StyleRuleImport::create(const String& href, PassRefPtrWillBeRawPtr<MediaQuerySet> media) { - return adoptRef(new StyleRuleImport(href, media)); + return adoptRefWillBeNoop(new StyleRuleImport(href, media)); } -StyleRuleImport::StyleRuleImport(const String& href, PassRefPtr<MediaQuerySet> media) +StyleRuleImport::StyleRuleImport(const String& href, PassRefPtrWillBeRawPtr<MediaQuerySet> media) : StyleRuleBase(Import) - , m_parentStyleSheet(0) + , m_parentStyleSheet(nullptr) , m_styleSheetClient(this) , m_strHref(href) , m_mediaQueries(media) @@ -51,25 +51,38 @@ StyleRuleImport::StyleRuleImport(const String& href, PassRefPtr<MediaQuerySet> m StyleRuleImport::~StyleRuleImport() { +#if !ENABLE(OILPAN) if (m_styleSheet) m_styleSheet->clearOwnerRule(); +#endif if (m_resource) m_resource->removeClient(&m_styleSheetClient); } +void StyleRuleImport::traceAfterDispatch(Visitor* visitor) +{ + visitor->trace(m_parentStyleSheet); + visitor->trace(m_mediaQueries); + visitor->trace(m_styleSheet); + StyleRuleBase::traceAfterDispatch(visitor); +} + void StyleRuleImport::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* cachedStyleSheet) { if (m_styleSheet) m_styleSheet->clearOwnerRule(); - CSSParserContext context = m_parentStyleSheet ? m_parentStyleSheet->parserContext() : HTMLStandardMode; + CSSParserContext context = m_parentStyleSheet ? m_parentStyleSheet->parserContext() : strictCSSParserContext(); context.setCharset(charset); - if (!baseURL.isNull()) + Document* document = m_parentStyleSheet ? m_parentStyleSheet->singleOwnerDocument() : 0; + if (!baseURL.isNull()) { context.setBaseURL(baseURL); + if (document) + context.setReferrer(Referrer(baseURL.strippedForUseAsReferrer(), document->referrerPolicy())); + } m_styleSheet = StyleSheetContents::create(this, href, context); - Document* document = m_parentStyleSheet ? m_parentStyleSheet->singleOwnerDocument() : 0; m_styleSheet->parseAuthorStyleSheet(cachedStyleSheet, document ? document->securityOrigin() : 0); m_loading = false; diff --git a/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.h b/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.h index 8af664e2438..e67f7120a0c 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleRuleImport.h @@ -25,6 +25,7 @@ #include "core/css/StyleRule.h" #include "core/fetch/ResourcePtr.h" #include "core/fetch/StyleSheetResourceClient.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -33,15 +34,15 @@ class MediaQuerySet; class StyleSheetContents; class StyleRuleImport : public StyleRuleBase { - WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: - static PassRefPtr<StyleRuleImport> create(const String& href, PassRefPtr<MediaQuerySet>); + static PassRefPtrWillBeRawPtr<StyleRuleImport> create(const String& href, PassRefPtrWillBeRawPtr<MediaQuerySet>); ~StyleRuleImport(); StyleSheetContents* parentStyleSheet() const { return m_parentStyleSheet; } void setParentStyleSheet(StyleSheetContents* sheet) { ASSERT(sheet); m_parentStyleSheet = sheet; } - void clearParentStyleSheet() { m_parentStyleSheet = 0; } + void clearParentStyleSheet() { m_parentStyleSheet = nullptr; } String href() const { return m_strHref; } StyleSheetContents* styleSheet() const { return m_styleSheet.get(); } @@ -51,14 +52,17 @@ public: void requestStyleSheet(); + void traceAfterDispatch(Visitor*); + private: + // FIXME: inherit from StyleSheetResourceClient directly to eliminate raw back pointer, as there are no space savings in this. // NOTE: We put the StyleSheetResourceClient in a member instead of inheriting from it // to avoid adding a vptr to StyleRuleImport. - class ImportedStyleSheetClient : public StyleSheetResourceClient { + class ImportedStyleSheetClient FINAL : public StyleSheetResourceClient { public: ImportedStyleSheetClient(StyleRuleImport* ownerRule) : m_ownerRule(ownerRule) { } virtual ~ImportedStyleSheetClient() { } - virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* sheet) + virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* sheet) OVERRIDE { m_ownerRule->setCSSStyleSheet(href, baseURL, charset, sheet); } @@ -69,14 +73,14 @@ private: void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource*); friend class ImportedStyleSheetClient; - StyleRuleImport(const String& href, PassRefPtr<MediaQuerySet>); + StyleRuleImport(const String& href, PassRefPtrWillBeRawPtr<MediaQuerySet>); - StyleSheetContents* m_parentStyleSheet; + RawPtrWillBeMember<StyleSheetContents> m_parentStyleSheet; ImportedStyleSheetClient m_styleSheetClient; String m_strHref; - RefPtr<MediaQuerySet> m_mediaQueries; - RefPtr<StyleSheetContents> m_styleSheet; + RefPtrWillBeMember<MediaQuerySet> m_mediaQueries; + RefPtrWillBeMember<StyleSheetContents> m_styleSheet; ResourcePtr<CSSStyleSheetResource> m_resource; bool m_loading; }; diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheet.h b/chromium/third_party/WebKit/Source/core/css/StyleSheet.h index 2207b5a006c..136fa1d4ba9 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheet.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheet.h @@ -22,6 +22,7 @@ #define StyleSheet_h #include "core/css/CSSParserMode.h" +#include "platform/heap/Handle.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" @@ -33,7 +34,7 @@ class MediaList; class Node; class StyleSheet; -class StyleSheet : public RefCounted<StyleSheet> { +class StyleSheet : public RefCountedWillBeGarbageCollectedFinalized<StyleSheet> { public: virtual ~StyleSheet(); @@ -51,6 +52,8 @@ public: virtual KURL baseURL() const = 0; virtual bool isLoading() const = 0; virtual bool isCSSStyleSheet() const { return false; } + + virtual void trace(Visitor*) { } }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheet.idl b/chromium/third_party/WebKit/Source/core/css/StyleSheet.idl index e3e13b37b1d..ed83f144757 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheet.idl +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheet.idl @@ -21,7 +21,8 @@ // Introduced in DOM Level 2: [ Custom=Wrap, - GenerateVisitDOMWrapper=ownerNode, + SetWrapperReferenceFrom=ownerNode, + WillBeGarbageCollected ] interface StyleSheet { [TreatReturnedNullStringAs=Null] readonly attribute DOMString type; attribute boolean disabled; diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.cpp b/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.cpp index fa7b022da58..2b3da24942a 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.cpp @@ -21,16 +21,17 @@ #include "config.h" #include "core/css/StyleSheetContents.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSStyleSheet.h" #include "core/css/MediaList.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRule.h" #include "core/css/StyleRuleImport.h" -#include "core/css/resolver/StyleResolver.h" +#include "core/dom/Document.h" #include "core/dom/Node.h" #include "core/dom/StyleEngine.h" #include "core/fetch/CSSStyleSheetResource.h" +#include "core/frame/UseCounter.h" #include "platform/TraceEvent.h" #include "platform/weborigin/SecurityOrigin.h" #include "wtf/Deque.h" @@ -44,7 +45,7 @@ unsigned StyleSheetContents::estimatedSizeInBytes() const // The assumption is that nearly all of of them are atomic and would exist anyway. unsigned size = sizeof(*this); - // FIXME: This ignores the children of media and region rules. + // FIXME: This ignores the children of media rules. // Most rules are StyleRules. size += ruleCount() * StyleRule::averageSizeInBytes(); @@ -58,32 +59,33 @@ unsigned StyleSheetContents::estimatedSizeInBytes() const StyleSheetContents::StyleSheetContents(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext& context) : m_ownerRule(ownerRule) , m_originalURL(originalURL) - , m_loadCompleted(false) , m_hasSyntacticallyValidCSSHeader(true) , m_didLoadErrorOccur(false) , m_usesRemUnits(false) , m_isMutable(false) , m_isInMemoryCache(false) , m_hasFontFaceRule(false) + , m_hasMediaQueries(false) + , m_hasSingleOwnerDocument(true) , m_parserContext(context) { } StyleSheetContents::StyleSheetContents(const StyleSheetContents& o) - : RefCounted<StyleSheetContents>() - , m_ownerRule(0) + : m_ownerRule(nullptr) , m_originalURL(o.m_originalURL) , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule) , m_importRules(o.m_importRules.size()) , m_childRules(o.m_childRules.size()) , m_namespaces(o.m_namespaces) - , m_loadCompleted(true) , m_hasSyntacticallyValidCSSHeader(o.m_hasSyntacticallyValidCSSHeader) , m_didLoadErrorOccur(false) , m_usesRemUnits(o.m_usesRemUnits) , m_isMutable(false) , m_isInMemoryCache(false) , m_hasFontFaceRule(o.m_hasFontFaceRule) + , m_hasMediaQueries(o.m_hasMediaQueries) + , m_hasSingleOwnerDocument(true) , m_parserContext(o.m_parserContext) { ASSERT(o.isCacheable()); @@ -97,11 +99,25 @@ StyleSheetContents::StyleSheetContents(const StyleSheetContents& o) StyleSheetContents::~StyleSheetContents() { +#if !ENABLE(OILPAN) clearRules(); +#endif +} + +void StyleSheetContents::setHasSyntacticallyValidCSSHeader(bool isValidCss) +{ + if (!isValidCss) { + if (Document* document = clientSingleOwnerDocument()) + removeSheetFromCache(document); + } + m_hasSyntacticallyValidCSSHeader = isValidCss; } bool StyleSheetContents::isCacheable() const { + // This would require dealing with multiple clients for load callbacks. + if (!loadCompleted()) + return false; // FIXME: StyleSheets with media queries can't be cached because their RuleSet // is processed differently based off the media queries, which might resolve // differently depending on the context of the parent CSSStyleSheet (e.g. @@ -115,9 +131,6 @@ bool StyleSheetContents::isCacheable() const // FIXME: Support cached stylesheets in import rules. if (m_ownerRule) return false; - // This would require dealing with multiple clients for load callbacks. - if (!m_loadCompleted) - return false; if (m_didLoadErrorOccur) return false; // It is not the original sheet anymore. @@ -130,7 +143,7 @@ bool StyleSheetContents::isCacheable() const return true; } -void StyleSheetContents::parserAppendRule(PassRefPtr<StyleRuleBase> rule) +void StyleSheetContents::parserAppendRule(PassRefPtrWillBeRawPtr<StyleRuleBase> rule) { ASSERT(!rule->isCharsetRule()); if (rule->isImportRule()) { @@ -210,7 +223,7 @@ void StyleSheetContents::parserSetEncodingFromCharsetRule(const String& encoding m_encodingFromCharsetRule = encoding; } -bool StyleSheetContents::wrapperInsertRule(PassRefPtr<StyleRuleBase> rule, unsigned index) +bool StyleSheetContents::wrapperInsertRule(PassRefPtrWillBeRawPtr<StyleRuleBase> rule, unsigned index) { ASSERT(m_isMutable); ASSERT_WITH_SECURITY_IMPLICATION(index <= ruleCount()); @@ -251,6 +264,8 @@ bool StyleSheetContents::wrapperInsertRule(PassRefPtr<StyleRuleBase> rule, unsig childVectorIndex -= m_importRules.size(); + if (rule->isFontFaceRule()) + setHasFontFaceRule(true); m_childRules.insert(childVectorIndex, rule); return true; } @@ -270,11 +285,15 @@ void StyleSheetContents::wrapperDeleteRule(unsigned index) } if (childVectorIndex < m_importRules.size()) { m_importRules[childVectorIndex]->clearParentStyleSheet(); + if (m_importRules[childVectorIndex]->isFontFaceRule()) + notifyRemoveFontFaceRule(toStyleRuleFontFace(m_importRules[childVectorIndex].get())); m_importRules.remove(childVectorIndex); return; } childVectorIndex -= m_importRules.size(); + if (m_childRules[childVectorIndex]->isFontFaceRule()) + notifyRemoveFontFaceRule(toStyleRuleFontFace(m_childRules[childVectorIndex].get())); m_childRules.remove(childVectorIndex); } @@ -285,7 +304,7 @@ void StyleSheetContents::parserAddNamespace(const AtomicString& prefix, const At PrefixNamespaceURIMap::AddResult result = m_namespaces.add(prefix, uri); if (result.isNewEntry) return; - result.iterator->value = uri; + result.storedValue->value = uri; } const AtomicString& StyleSheetContents::determineNamespace(const AtomicString& prefix) @@ -307,7 +326,8 @@ void StyleSheetContents::parseAuthorStyleSheet(const CSSStyleSheetResource* cach bool hasValidMIMEType = false; String sheetText = cachedStyleSheet->sheetText(enforceMIMEType, &hasValidMIMEType); - CSSParser p(parserContext(), UseCounter::getFrom(this)); + CSSParserContext context(parserContext(), UseCounter::getFrom(this)); + BisonCSSParser p(context); p.parseSheet(this, sheetText, TextPosition::minimumPosition(), 0, true); // If we're loading a stylesheet cross-origin, and the MIME type is not standard, require the CSS @@ -329,7 +349,8 @@ bool StyleSheetContents::parseString(const String& sheetText) bool StyleSheetContents::parseStringAtPosition(const String& sheetText, const TextPosition& startPosition, bool createdByParser) { - CSSParser p(parserContext(), UseCounter::getFrom(this)); + CSSParserContext context(parserContext(), UseCounter::getFrom(this)); + BisonCSSParser p(context); p.parseSheet(this, sheetText, startPosition, 0, createdByParser); return true; @@ -344,6 +365,16 @@ bool StyleSheetContents::isLoading() const return false; } +bool StyleSheetContents::loadCompleted() const +{ + StyleSheetContents* parentSheet = parentStyleSheet(); + if (parentSheet) + return parentSheet->loadCompleted(); + + StyleSheetContents* root = rootStyleSheet(); + return root->m_loadingClients.isEmpty(); +} + void StyleSheetContents::checkLoaded() { if (isLoading()) @@ -352,22 +383,39 @@ void StyleSheetContents::checkLoaded() // Avoid |this| being deleted by scripts that run via // ScriptableDocumentParser::executeScriptsWaitingForResources(). // See https://bugs.webkit.org/show_bug.cgi?id=95106 - RefPtr<StyleSheetContents> protect(this); + RefPtrWillBeRawPtr<StyleSheetContents> protect(this); StyleSheetContents* parentSheet = parentStyleSheet(); if (parentSheet) { parentSheet->checkLoaded(); - m_loadCompleted = true; return; } - RefPtr<Node> ownerNode = singleOwnerNode(); - if (!ownerNode) { - m_loadCompleted = true; + + StyleSheetContents* root = rootStyleSheet(); + if (root->m_loadingClients.isEmpty()) return; + + // Avoid |CSSSStyleSheet| and |ownerNode| being deleted by scripts that run via + // ScriptableDocumentParser::executeScriptsWaitingForResources(). Also protect + // the |CSSStyleSheet| from being deleted during iteration via the |sheetLoaded| + // method. + // + // When a sheet is loaded it is moved from the set of loading clients + // to the set of completed clients. We therefore need the copy in order to + // not modify the set while iterating it. + WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> > loadingClients; + copyToVector(m_loadingClients, loadingClients); + + for (unsigned i = 0; i < loadingClients.size(); ++i) { + if (loadingClients[i]->loadCompleted()) + continue; + + // sheetLoaded might be invoked after its owner node is removed from document. + if (RefPtrWillBeRawPtr<Node> ownerNode = loadingClients[i]->ownerNode()) { + if (loadingClients[i]->sheetLoaded()) + ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur); + } } - m_loadCompleted = ownerNode->sheetLoaded(); - if (m_loadCompleted) - ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur); } void StyleSheetContents::notifyLoadedSheet(const CSSStyleSheetResource* sheet) @@ -382,8 +430,18 @@ void StyleSheetContents::notifyLoadedSheet(const CSSStyleSheetResource* sheet) void StyleSheetContents::startLoadingDynamicSheet() { - if (Node* owner = singleOwnerNode()) - owner->startLoadingDynamicSheet(); + StyleSheetContents* root = rootStyleSheet(); + for (ClientsIterator it = root->m_loadingClients.begin(); it != root->m_loadingClients.end(); ++it) + (*it)->startLoadingDynamicSheet(); + // Copy the completed clients to a vector for iteration. + // startLoadingDynamicSheet will move the style sheet from the + // completed state to the loading state which modifies the set of + // completed clients. We therefore need the copy in order to not + // modify the set of completed clients while iterating it. + WillBeHeapVector<RawPtrWillBeMember<CSSStyleSheet> > completedClients; + copyToVector(root->m_completedClients, completedClients); + for (unsigned i = 0; i < completedClients.size(); ++i) + completedClients[i]->startLoadingDynamicSheet(); } StyleSheetContents* StyleSheetContents::rootStyleSheet() const @@ -396,78 +454,48 @@ StyleSheetContents* StyleSheetContents::rootStyleSheet() const bool StyleSheetContents::hasSingleOwnerNode() const { - StyleSheetContents* root = rootStyleSheet(); - if (root->m_clients.isEmpty()) - return false; - return root->m_clients.size() == 1; + return rootStyleSheet()->hasOneClient(); } Node* StyleSheetContents::singleOwnerNode() const { StyleSheetContents* root = rootStyleSheet(); - if (root->m_clients.isEmpty()) + if (!root->hasOneClient()) return 0; - ASSERT(root->m_clients.size() == 1); - return root->m_clients[0]->ownerNode(); + if (root->m_loadingClients.size()) + return (*root->m_loadingClients.begin())->ownerNode(); + return (*root->m_completedClients.begin())->ownerNode(); } Document* StyleSheetContents::singleOwnerDocument() const { - Node* ownerNode = singleOwnerNode(); - return ownerNode ? &ownerNode->document() : 0; + StyleSheetContents* root = rootStyleSheet(); + return root->clientSingleOwnerDocument(); } KURL StyleSheetContents::completeURL(const String& url) const { - return CSSParser::completeURL(m_parserContext, url); + // FIXME: This is only OK when we have a singleOwnerNode, right? + return m_parserContext.completeURL(url); } -void StyleSheetContents::addSubresourceStyleURLs(ListHashSet<KURL>& urls) -{ - Deque<StyleSheetContents*> styleSheetQueue; - styleSheetQueue.append(this); - - while (!styleSheetQueue.isEmpty()) { - StyleSheetContents* styleSheet = styleSheetQueue.takeFirst(); - - for (unsigned i = 0; i < styleSheet->m_importRules.size(); ++i) { - StyleRuleImport* importRule = styleSheet->m_importRules[i].get(); - if (importRule->styleSheet()) { - styleSheetQueue.append(importRule->styleSheet()); - addSubresourceURL(urls, importRule->styleSheet()->baseURL()); - } - } - for (unsigned i = 0; i < styleSheet->m_childRules.size(); ++i) { - StyleRuleBase* rule = styleSheet->m_childRules[i].get(); - if (rule->isStyleRule()) - toStyleRule(rule)->properties()->addSubresourceStyleURLs(urls, this); - else if (rule->isFontFaceRule()) - toStyleRuleFontFace(rule)->properties()->addSubresourceStyleURLs(urls, this); - } - } -} - -static bool childRulesHaveFailedOrCanceledSubresources(const Vector<RefPtr<StyleRuleBase> >& rules) +static bool childRulesHaveFailedOrCanceledSubresources(const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& rules) { for (unsigned i = 0; i < rules.size(); ++i) { const StyleRuleBase* rule = rules[i].get(); switch (rule->type()) { case StyleRuleBase::Style: - if (toStyleRule(rule)->properties()->hasFailedOrCanceledSubresources()) + if (toStyleRule(rule)->properties().hasFailedOrCanceledSubresources()) return true; break; case StyleRuleBase::FontFace: - if (toStyleRuleFontFace(rule)->properties()->hasFailedOrCanceledSubresources()) + if (toStyleRuleFontFace(rule)->properties().hasFailedOrCanceledSubresources()) return true; break; case StyleRuleBase::Media: if (childRulesHaveFailedOrCanceledSubresources(toStyleRuleMedia(rule)->childRules())) return true; break; - case StyleRuleBase::Region: - if (childRulesHaveFailedOrCanceledSubresources(toStyleRuleRegion(rule)->childRules())) - return true; - break; case StyleRuleBase::Import: ASSERT_NOT_REACHED(); case StyleRuleBase::Page: @@ -490,6 +518,16 @@ bool StyleSheetContents::hasFailedOrCanceledSubresources() const return childRulesHaveFailedOrCanceledSubresources(m_childRules); } +Document* StyleSheetContents::clientSingleOwnerDocument() const +{ + if (!m_hasSingleOwnerDocument || clientSize() <= 0) + return 0; + + if (m_loadingClients.size()) + return (*m_loadingClients.begin())->ownerDocument(); + return (*m_completedClients.begin())->ownerDocument(); +} + StyleSheetContents* StyleSheetContents::parentStyleSheet() const { return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0; @@ -497,15 +535,55 @@ StyleSheetContents* StyleSheetContents::parentStyleSheet() const void StyleSheetContents::registerClient(CSSStyleSheet* sheet) { - ASSERT(!m_clients.contains(sheet)); - m_clients.append(sheet); + ASSERT(!m_loadingClients.contains(sheet) && !m_completedClients.contains(sheet)); + + // InspectorCSSAgent::buildObjectForRule creates CSSStyleSheet without any owner node. + if (!sheet->ownerDocument()) + return; + + if (Document* document = clientSingleOwnerDocument()) { + if (sheet->ownerDocument() != document) + m_hasSingleOwnerDocument = false; + } + m_loadingClients.add(sheet); } void StyleSheetContents::unregisterClient(CSSStyleSheet* sheet) { - size_t position = m_clients.find(sheet); - ASSERT(position != kNotFound); - m_clients.remove(position); + m_loadingClients.remove(sheet); + m_completedClients.remove(sheet); + + if (!sheet->ownerDocument() || !m_loadingClients.isEmpty() || !m_completedClients.isEmpty()) + return; + + if (m_hasSingleOwnerDocument) + removeSheetFromCache(sheet->ownerDocument()); + m_hasSingleOwnerDocument = true; +} + +void StyleSheetContents::clientLoadCompleted(CSSStyleSheet* sheet) +{ + ASSERT(m_loadingClients.contains(sheet) || !sheet->ownerDocument()); + m_loadingClients.remove(sheet); + // In m_ownerNode->sheetLoaded, the CSSStyleSheet might be detached. + // (i.e. clearOwnerNode was invoked.) + // In this case, we don't need to add the stylesheet to completed clients. + if (!sheet->ownerDocument()) + return; + m_completedClients.add(sheet); +} + +void StyleSheetContents::clientLoadStarted(CSSStyleSheet* sheet) +{ + ASSERT(m_completedClients.contains(sheet)); + m_completedClients.remove(sheet); + m_loadingClients.add(sheet); +} + +void StyleSheetContents::removeSheetFromCache(Document* document) +{ + ASSERT(document); + document->styleEngine()->removeSheet(this); } void StyleSheetContents::addedToMemoryCache() @@ -537,6 +615,14 @@ RuleSet& StyleSheetContents::ensureRuleSet(const MediaQueryEvaluator& medium, Ad return *m_ruleSet.get(); } +static void clearResolvers(WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >& clients) +{ + for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >::iterator it = clients.begin(); it != clients.end(); ++it) { + if (Document* document = (*it)->ownerDocument()) + document->styleEngine()->clearResolver(); + } +} + void StyleSheetContents::clearRuleSet() { if (StyleSheetContents* parentSheet = parentStyleSheet()) @@ -550,12 +636,61 @@ void StyleSheetContents::clearRuleSet() // Clearing the ruleSet means we need to recreate the styleResolver data structures. // See the StyleResolver calls in ScopedStyleResolver::addRulesFromSheet. - for (size_t i = 0; i < m_clients.size(); ++i) { - if (Document* document = m_clients[i]->ownerDocument()) - document->styleEngine()->clearResolver(); - } + clearResolvers(m_loadingClients); + clearResolvers(m_completedClients); m_ruleSet.clear(); } +static void removeFontFaceRules(WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >& clients, const StyleRuleFontFace* fontFaceRule) +{ + for (WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >::iterator it = clients.begin(); it != clients.end(); ++it) { + if (Node* ownerNode = (*it)->ownerNode()) + ownerNode->document().styleEngine()->removeFontFaceRules(WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >(1, fontFaceRule)); + } +} + +void StyleSheetContents::notifyRemoveFontFaceRule(const StyleRuleFontFace* fontFaceRule) +{ + StyleSheetContents* root = rootStyleSheet(); + removeFontFaceRules(root->m_loadingClients, fontFaceRule); + removeFontFaceRules(root->m_completedClients, fontFaceRule); +} + +static void findFontFaceRulesFromRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& rules, WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules) +{ + for (unsigned i = 0; i < rules.size(); ++i) { + StyleRuleBase* rule = rules[i].get(); + + if (rule->isFontFaceRule()) { + fontFaceRules.append(toStyleRuleFontFace(rule)); + } else if (rule->isMediaRule()) { + StyleRuleMedia* mediaRule = toStyleRuleMedia(rule); + // We cannot know whether the media rule matches or not, but + // for safety, remove @font-face in the media rule (if exists). + findFontFaceRulesFromRules(mediaRule->childRules(), fontFaceRules); + } + } +} + +void StyleSheetContents::findFontFaceRules(WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules) +{ + for (unsigned i = 0; i < m_importRules.size(); ++i) { + if (!m_importRules[i]->styleSheet()) + continue; + m_importRules[i]->styleSheet()->findFontFaceRules(fontFaceRules); + } + + findFontFaceRulesFromRules(childRules(), fontFaceRules); +} + +void StyleSheetContents::trace(Visitor* visitor) +{ + visitor->trace(m_ownerRule); + visitor->trace(m_importRules); + visitor->trace(m_childRules); + visitor->trace(m_loadingClients); + visitor->trace(m_completedClients); + visitor->trace(m_ruleSet); +} } diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.h b/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.h index 7d59d80ef93..7dca729d02b 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheetContents.h @@ -23,6 +23,7 @@ #include "core/css/CSSParserMode.h" #include "core/css/RuleSet.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" #include "wtf/HashMap.h" #include "wtf/ListHashSet.h" @@ -41,21 +42,22 @@ class Document; class Node; class SecurityOrigin; class StyleRuleBase; +class StyleRuleFontFace; class StyleRuleImport; -class StyleSheetContents : public RefCounted<StyleSheetContents> { +class StyleSheetContents : public RefCountedWillBeGarbageCollectedFinalized<StyleSheetContents> { public: - static PassRefPtr<StyleSheetContents> create(const CSSParserContext& context = CSSParserContext(HTMLStandardMode)) + static PassRefPtrWillBeRawPtr<StyleSheetContents> create(const CSSParserContext& context) { - return adoptRef(new StyleSheetContents(0, String(), context)); + return adoptRefWillBeNoop(new StyleSheetContents(0, String(), context)); } - static PassRefPtr<StyleSheetContents> create(const String& originalURL, const CSSParserContext& context) + static PassRefPtrWillBeRawPtr<StyleSheetContents> create(const String& originalURL, const CSSParserContext& context) { - return adoptRef(new StyleSheetContents(0, originalURL, context)); + return adoptRefWillBeNoop(new StyleSheetContents(0, originalURL, context)); } - static PassRefPtr<StyleSheetContents> create(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext& context) + static PassRefPtrWillBeRawPtr<StyleSheetContents> create(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext& context) { - return adoptRef(new StyleSheetContents(ownerRule, originalURL, context)); + return adoptRefWillBeNoop(new StyleSheetContents(ownerRule, originalURL, context)); } ~StyleSheetContents(); @@ -82,20 +84,20 @@ public: const String& charset() const { return m_parserContext.charset(); } - bool loadCompleted() const { return m_loadCompleted; } + bool loadCompleted() const; bool hasFailedOrCanceledSubresources() const; KURL completeURL(const String& url) const; - void addSubresourceStyleURLs(ListHashSet<KURL>&); - void setHasSyntacticallyValidCSSHeader(bool b) { m_hasSyntacticallyValidCSSHeader = b; } + void setHasSyntacticallyValidCSSHeader(bool isValidCss); bool hasSyntacticallyValidCSSHeader() const { return m_hasSyntacticallyValidCSSHeader; } void setHasFontFaceRule(bool b) { m_hasFontFaceRule = b; } bool hasFontFaceRule() const { return m_hasFontFaceRule; } + void findFontFaceRules(WillBeHeapVector<RawPtrWillBeMember<const StyleRuleFontFace> >& fontFaceRules); void parserAddNamespace(const AtomicString& prefix, const AtomicString& uri); - void parserAppendRule(PassRefPtr<StyleRuleBase>); + void parserAppendRule(PassRefPtrWillBeRawPtr<StyleRuleBase>); void parserSetEncodingFromCharsetRule(const String& encoding); void parserSetUsesRemUnits(bool b) { m_usesRemUnits = b; } @@ -104,14 +106,14 @@ public: bool hasCharsetRule() const { return !m_encodingFromCharsetRule.isNull(); } String encodingFromCharsetRule() const { return m_encodingFromCharsetRule; } // Rules other than @charset and @import. - const Vector<RefPtr<StyleRuleBase> >& childRules() const { return m_childRules; } - const Vector<RefPtr<StyleRuleImport> >& importRules() const { return m_importRules; } + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& childRules() const { return m_childRules; } + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport> >& importRules() const { return m_importRules; } void notifyLoadedSheet(const CSSStyleSheetResource*); StyleSheetContents* parentStyleSheet() const; StyleRuleImport* ownerRule() const { return m_ownerRule; } - void clearOwnerRule() { m_ownerRule = 0; } + void clearOwnerRule() { m_ownerRule = nullptr; } // Note that href is the URL that started the redirect chain that led to // this style sheet. This property probably isn't useful for much except @@ -126,47 +128,60 @@ public: unsigned estimatedSizeInBytes() const; - bool wrapperInsertRule(PassRefPtr<StyleRuleBase>, unsigned index); + bool wrapperInsertRule(PassRefPtrWillBeRawPtr<StyleRuleBase>, unsigned index); void wrapperDeleteRule(unsigned index); - PassRefPtr<StyleSheetContents> copy() const { return adoptRef(new StyleSheetContents(*this)); } + PassRefPtrWillBeRawPtr<StyleSheetContents> copy() const + { + return adoptRefWillBeNoop(new StyleSheetContents(*this)); + } void registerClient(CSSStyleSheet*); void unregisterClient(CSSStyleSheet*); - bool hasOneClient() { return m_clients.size() == 1; } + size_t clientSize() const { return m_loadingClients.size() + m_completedClients.size(); } + bool hasOneClient() { return clientSize() == 1; } + void clientLoadCompleted(CSSStyleSheet*); + void clientLoadStarted(CSSStyleSheet*); bool isMutable() const { return m_isMutable; } void setMutable() { m_isMutable = true; } + void removeSheetFromCache(Document*); + bool isInMemoryCache() const { return m_isInMemoryCache; } void addedToMemoryCache(); void removedFromMemoryCache(); void setHasMediaQueries(); - bool hasMediaQueries() { return m_hasMediaQueries; } + bool hasMediaQueries() const { return m_hasMediaQueries; } + + bool didLoadErrorOccur() const { return m_didLoadErrorOccur; } void shrinkToFit(); RuleSet& ruleSet() { ASSERT(m_ruleSet); return *m_ruleSet.get(); } RuleSet& ensureRuleSet(const MediaQueryEvaluator&, AddRuleFlags); void clearRuleSet(); + void trace(Visitor*); + private: StyleSheetContents(StyleRuleImport* ownerRule, const String& originalURL, const CSSParserContext&); StyleSheetContents(const StyleSheetContents&); + void notifyRemoveFontFaceRule(const StyleRuleFontFace*); + Document* clientSingleOwnerDocument() const; void clearCharsetRule(); - StyleRuleImport* m_ownerRule; + RawPtrWillBeMember<StyleRuleImport> m_ownerRule; String m_originalURL; String m_encodingFromCharsetRule; - Vector<RefPtr<StyleRuleImport> > m_importRules; - Vector<RefPtr<StyleRuleBase> > m_childRules; + WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport> > m_importRules; + WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> > m_childRules; typedef HashMap<AtomicString, AtomicString> PrefixNamespaceURIMap; PrefixNamespaceURIMap m_namespaces; - bool m_loadCompleted : 1; bool m_hasSyntacticallyValidCSSHeader : 1; bool m_didLoadErrorOccur : 1; bool m_usesRemUnits : 1; @@ -174,11 +189,15 @@ private: bool m_isInMemoryCache : 1; bool m_hasFontFaceRule : 1; bool m_hasMediaQueries : 1; + bool m_hasSingleOwnerDocument : 1; CSSParserContext m_parserContext; - Vector<CSSStyleSheet*> m_clients; - OwnPtr<RuleSet> m_ruleSet; + WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> > m_loadingClients; + WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> > m_completedClients; + typedef WillBeHeapHashSet<RawPtrWillBeWeakMember<CSSStyleSheet> >::iterator ClientsIterator; + + OwnPtrWillBeMember<RuleSet> m_ruleSet; }; } // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheetList.cpp b/chromium/third_party/WebKit/Source/core/css/StyleSheetList.cpp index 10f5905ba4e..80714e52a8c 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheetList.cpp +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheetList.cpp @@ -21,7 +21,7 @@ #include "config.h" #include "core/css/StyleSheetList.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/dom/Document.h" #include "core/dom/StyleEngine.h" #include "core/html/HTMLStyleElement.h" @@ -40,18 +40,22 @@ StyleSheetList::~StyleSheetList() { } -inline const Vector<RefPtr<StyleSheet> >& StyleSheetList::styleSheets() +inline const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& StyleSheetList::styleSheets() { +#if !ENABLE(OILPAN) if (!m_treeScope) return m_detachedStyleSheets; +#endif return document()->styleEngine()->styleSheetsForStyleSheetList(*m_treeScope); } +#if !ENABLE(OILPAN) void StyleSheetList::detachFromDocument() { m_detachedStyleSheets = document()->styleEngine()->styleSheetsForStyleSheetList(*m_treeScope); - m_treeScope = 0; + m_treeScope = nullptr; } +#endif unsigned StyleSheetList::length() { @@ -60,14 +64,16 @@ unsigned StyleSheetList::length() StyleSheet* StyleSheetList::item(unsigned index) { - const Vector<RefPtr<StyleSheet> >& sheets = styleSheets(); + const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& sheets = styleSheets(); return index < sheets.size() ? sheets[index].get() : 0; } HTMLStyleElement* StyleSheetList::getNamedItem(const AtomicString& name) const { +#if !ENABLE(OILPAN) if (!m_treeScope) return 0; +#endif // IE also supports retrieving a stylesheet by name, using the name/id of the <style> tag // (this is consistent with all the other collections) @@ -76,9 +82,7 @@ HTMLStyleElement* StyleSheetList::getNamedItem(const AtomicString& name) const // But unicity of stylesheet ids is good practice anyway ;) // FIXME: We should figure out if we should change this or fix the spec. Element* element = m_treeScope->getElementById(name); - if (element && element->hasTagName(styleTag)) - return toHTMLStyleElement(element); - return 0; + return isHTMLStyleElement(element) ? toHTMLStyleElement(element) : 0; } CSSStyleSheet* StyleSheetList::anonymousNamedGetter(const AtomicString& name) @@ -89,4 +93,9 @@ CSSStyleSheet* StyleSheetList::anonymousNamedGetter(const AtomicString& name) return item->sheet(); } +void StyleSheetList::trace(Visitor* visitor) +{ + visitor->trace(m_treeScope); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheetList.h b/chromium/third_party/WebKit/Source/core/css/StyleSheetList.h index c9c15404729..f842183b75d 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheetList.h +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheetList.h @@ -33,9 +33,9 @@ namespace WebCore { class HTMLStyleElement; class StyleSheet; -class StyleSheetList : public RefCounted<StyleSheetList> { +class StyleSheetList : public RefCountedWillBeGarbageCollectedFinalized<StyleSheetList> { public: - static PassRefPtr<StyleSheetList> create(TreeScope* treeScope) { return adoptRef(new StyleSheetList(treeScope)); } + static PassRefPtrWillBeRawPtr<StyleSheetList> create(TreeScope* treeScope) { return adoptRefWillBeNoop(new StyleSheetList(treeScope)); } ~StyleSheetList(); unsigned length(); @@ -43,17 +43,24 @@ public: HTMLStyleElement* getNamedItem(const AtomicString&) const; - Document* document() { return m_treeScope->documentScope(); } + Document* document() { return m_treeScope ? &m_treeScope->document() : 0; } +#if !ENABLE(OILPAN) void detachFromDocument(); +#endif + CSSStyleSheet* anonymousNamedGetter(const AtomicString&); + void trace(Visitor*); + private: StyleSheetList(TreeScope*); - const Vector<RefPtr<StyleSheet> >& styleSheets(); + const WillBeHeapVector<RefPtrWillBeMember<StyleSheet> >& styleSheets(); - TreeScope* m_treeScope; + RawPtrWillBeMember<TreeScope> m_treeScope; +#if !ENABLE(OILPAN) Vector<RefPtr<StyleSheet> > m_detachedStyleSheets; +#endif }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/StyleSheetList.idl b/chromium/third_party/WebKit/Source/core/css/StyleSheetList.idl index 7341728216d..3da2d91e544 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleSheetList.idl +++ b/chromium/third_party/WebKit/Source/core/css/StyleSheetList.idl @@ -20,10 +20,10 @@ // Introduced in DOM Level 2: [ - GenerateVisitDOMWrapper=document, + SetWrapperReferenceFrom=document, + WillBeGarbageCollected ] interface StyleSheetList { - readonly attribute unsigned long length; - getter StyleSheet item(unsigned long index); - [ImplementedAs=anonymousNamedGetter, NotEnumerable] getter CSSStyleSheet (DOMString name); + readonly attribute unsigned long length; + getter StyleSheet item(unsigned long index); + [NotEnumerable] getter CSSStyleSheet (DOMString name); }; - diff --git a/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.cpp b/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.cpp index 30a5604c412..4d3b123d3bc 100644 --- a/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.cpp +++ b/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.cpp @@ -29,20 +29,68 @@ #include "config.h" #include "core/css/TreeBoundaryCrossingRules.h" +#include "core/css/ElementRuleCollector.h" #include "core/css/RuleFeature.h" #include "core/dom/StyleEngine.h" +#include "core/dom/shadow/ShadowRoot.h" namespace WebCore { -void TreeBoundaryCrossingRules::addRule(StyleRule* rule, size_t selectorIndex, ContainerNode* scopingNode, AddRuleFlags addRuleFlags) +static void addRules(RuleSet* ruleSet, const WillBeHeapVector<MinimalRuleData>& rules) { - if (m_treeBoundaryCrossingRuleSetMap.contains(scopingNode)) { - m_treeBoundaryCrossingRuleSetMap.get(scopingNode)->addRule(rule, selectorIndex, addRuleFlags); - } else { - OwnPtr<RuleSet> ruleSetForScope = RuleSet::create(); - ruleSetForScope->addRule(rule, selectorIndex, addRuleFlags); - m_treeBoundaryCrossingRuleSetMap.add(scopingNode, ruleSetForScope.release()); - m_scopingNodes.add(scopingNode); + for (unsigned i = 0; i < rules.size(); ++i) { + const MinimalRuleData& info = rules[i]; + ruleSet->addRule(info.m_rule, info.m_selectorIndex, info.m_flags); + } +} + +void TreeBoundaryCrossingRules::addTreeBoundaryCrossingRules(const RuleSet& authorRules, ContainerNode& scopingNode, CSSStyleSheet* parentStyleSheet) +{ + if (authorRules.treeBoundaryCrossingRules().isEmpty() && (scopingNode.isDocumentNode() || authorRules.shadowDistributedRules().isEmpty())) + return; + OwnPtrWillBeRawPtr<RuleSet> ruleSetForScope = RuleSet::create(); + addRules(ruleSetForScope.get(), authorRules.treeBoundaryCrossingRules()); + if (!scopingNode.isDocumentNode()) + addRules(ruleSetForScope.get(), authorRules.shadowDistributedRules()); + + if (!m_treeBoundaryCrossingRuleSetMap.contains(&scopingNode)) { + m_treeBoundaryCrossingRuleSetMap.add(&scopingNode, adoptPtrWillBeNoop(new CSSStyleSheetRuleSubSet())); + m_scopingNodes.add(&scopingNode); + } + CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(&scopingNode); + ruleSubSet->append(std::make_pair(parentStyleSheet, ruleSetForScope.release())); +} + +void TreeBoundaryCrossingRules::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules) +{ + if (m_treeBoundaryCrossingRuleSetMap.isEmpty()) + return; + + RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); + + // When comparing rules declared in outer treescopes, outer's rules win. + CascadeOrder outerCascadeOrder = size() + size(); + // When comparing rules declared in inner treescopes, inner's rules win. + CascadeOrder innerCascadeOrder = size(); + + for (DocumentOrderedList::iterator it = m_scopingNodes.begin(); it != m_scopingNodes.end(); ++it) { + const ContainerNode* scopingNode = toContainerNode(*it); + CSSStyleSheetRuleSubSet* ruleSubSet = m_treeBoundaryCrossingRuleSetMap.get(scopingNode); + unsigned boundaryBehavior = SelectorChecker::ScopeContainsLastMatchedElement; + bool isInnerTreeScope = element->treeScope().isInclusiveAncestorOf(scopingNode->treeScope()); + + // If a given scoping node is a shadow root, we should use ScopeIsShadowRoot. + if (scopingNode && scopingNode->isShadowRoot()) + boundaryBehavior |= SelectorChecker::ScopeIsShadowRoot; + + CascadeOrder cascadeOrder = isInnerTreeScope ? innerCascadeOrder : outerCascadeOrder; + for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) { + CSSStyleSheet* parentStyleSheet = it->first; + RuleSet* ruleSet = it->second.get(); + collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode, parentStyleSheet), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder); + } + ++innerCascadeOrder; + --outerCascadeOrder; } } @@ -52,12 +100,16 @@ void TreeBoundaryCrossingRules::reset(const ContainerNode* scopingNode) m_scopingNodes.remove(scopingNode); } +void TreeBoundaryCrossingRules::collectFeaturesFromRuleSubSet(CSSStyleSheetRuleSubSet* ruleSubSet, RuleFeatureSet& features) +{ + for (CSSStyleSheetRuleSubSet::iterator it = ruleSubSet->begin(); it != ruleSubSet->end(); ++it) + features.add(it->second->features()); +} + void TreeBoundaryCrossingRules::collectFeaturesTo(RuleFeatureSet& features) { - for (TreeBoundaryCrossingRuleSetMap::iterator::Values it = m_treeBoundaryCrossingRuleSetMap.values().begin(); it != m_treeBoundaryCrossingRuleSetMap.values().end(); ++it) { - RuleSet* ruleSet = it->get(); - features.add(ruleSet->features()); - } + for (TreeBoundaryCrossingRuleSetMap::iterator::Values it = m_treeBoundaryCrossingRuleSetMap.values().begin(); it != m_treeBoundaryCrossingRuleSetMap.values().end(); ++it) + collectFeaturesFromRuleSubSet(it->get(), features); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.h b/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.h index bba30ed9dcf..64c2970e4c3 100644 --- a/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.h +++ b/chromium/third_party/WebKit/Source/core/css/TreeBoundaryCrossingRules.h @@ -32,24 +32,29 @@ namespace WebCore { +class CSSStyleSheet; class ContainerNode; +class ElementRuleCollector; class RuleFeatureSet; class TreeBoundaryCrossingRules { + DISALLOW_ALLOCATION(); public: - void addRule(StyleRule*, size_t selectorIndex, ContainerNode* scopingNode, AddRuleFlags); - void clear() { m_treeBoundaryCrossingRuleSetMap.clear(); } + void addTreeBoundaryCrossingRules(const RuleSet&, ContainerNode& scope, CSSStyleSheet*); + void reset(const ContainerNode* scopingNode); - bool isEmpty() const { return m_treeBoundaryCrossingRuleSetMap.isEmpty(); } void collectFeaturesTo(RuleFeatureSet&); + void collectTreeBoundaryCrossingRules(Element*, ElementRuleCollector&, bool includeEmptyRules); - DocumentOrderedList::iterator begin() { return m_scopingNodes.begin(); } - DocumentOrderedList::iterator end() { return m_scopingNodes.end(); } - RuleSet* ruleSetScopedBy(const ContainerNode* scopingNode) { return m_treeBoundaryCrossingRuleSetMap.get(scopingNode); } + void trace(Visitor* visitor) { visitor->trace(m_treeBoundaryCrossingRuleSetMap); } private: + size_t size() const { return m_scopingNodes.size(); } + typedef WillBeHeapVector<std::pair<CSSStyleSheet*, OwnPtrWillBeMember<RuleSet> > > CSSStyleSheetRuleSubSet; + void collectFeaturesFromRuleSubSet(CSSStyleSheetRuleSubSet*, RuleFeatureSet&); + DocumentOrderedList m_scopingNodes; - typedef HashMap<const ContainerNode*, OwnPtr<RuleSet> > TreeBoundaryCrossingRuleSetMap; + typedef WillBeHeapHashMap<const ContainerNode*, OwnPtrWillBeMember<CSSStyleSheetRuleSubSet> > TreeBoundaryCrossingRuleSetMap; TreeBoundaryCrossingRuleSetMap m_treeBoundaryCrossingRuleSetMap; }; diff --git a/chromium/third_party/WebKit/Source/core/css/WebKitCSSFilterValue.idl b/chromium/third_party/WebKit/Source/core/css/WebKitCSSFilterValue.idl index db2fb1d931d..8c346d2d612 100644 --- a/chromium/third_party/WebKit/Source/core/css/WebKitCSSFilterValue.idl +++ b/chromium/third_party/WebKit/Source/core/css/WebKitCSSFilterValue.idl @@ -25,7 +25,7 @@ [ DoNotCheckConstants, - ImplementedAs=CSSFilterValue + ImplementedAs=CSSFilterValue, ] interface WebKitCSSFilterValue : CSSValueList { // OperationTypes @@ -41,8 +41,7 @@ const unsigned short CSS_FILTER_CONTRAST = 9; const unsigned short CSS_FILTER_BLUR = 10; const unsigned short CSS_FILTER_DROP_SHADOW = 11; - const unsigned short CSS_FILTER_CUSTOM = 12; readonly attribute unsigned short operationType; - [ImplementedAs=item] getter CSSValue(unsigned long index); + [ImplementedAs=item] getter CSSValue (unsigned long index); }; diff --git a/chromium/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl b/chromium/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl index 0016fcfdc80..08ee79783c5 100644 --- a/chromium/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl +++ b/chromium/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl @@ -25,9 +25,10 @@ // Introduced in DOM Level ?: [ - Constructor([Default=NullString] optional DOMString cssValue), + Constructor(optional DOMString cssValue = null), ImplementedAs=CSSMatrix, - RaisesException=Constructor + RaisesException=Constructor, + WillBeGarbageCollected ] interface WebKitCSSMatrix { // These attributes are simple aliases for certain elements of the 4x4 matrix diff --git a/chromium/third_party/WebKit/Source/core/css/WebKitCSSMixFunctionValue.idl b/chromium/third_party/WebKit/Source/core/css/WebKitCSSMixFunctionValue.idl deleted file mode 100644 index 57f3125d6df..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/WebKitCSSMixFunctionValue.idl +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -[ - ImplementedAs=CSSMixFunctionValue -] interface WebKitCSSMixFunctionValue : CSSValueList { -}; - diff --git a/chromium/third_party/WebKit/Source/core/css/WebKitCSSRegionRule.idl b/chromium/third_party/WebKit/Source/core/css/WebKitCSSRegionRule.idl deleted file mode 100644 index 68113448048..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/WebKitCSSRegionRule.idl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -[ - RuntimeEnabled=CSSRegions, - ImplementedAs=CSSRegionRule -] interface WebKitCSSRegionRule : CSSRule { - readonly attribute CSSRuleList cssRules; -}; - diff --git a/chromium/third_party/WebKit/Source/core/css/WebKitCSSTransformValue.idl b/chromium/third_party/WebKit/Source/core/css/WebKitCSSTransformValue.idl index 836bcc6dc2d..a17e482d4c6 100644 --- a/chromium/third_party/WebKit/Source/core/css/WebKitCSSTransformValue.idl +++ b/chromium/third_party/WebKit/Source/core/css/WebKitCSSTransformValue.idl @@ -28,7 +28,7 @@ [ DoNotCheckConstants, - ImplementedAs=CSSTransformValue + ImplementedAs=CSSTransformValue, ] interface WebKitCSSTransformValue : CSSValueList { // OperationTypes @@ -56,6 +56,6 @@ const unsigned short CSS_MATRIX3D = 21; readonly attribute unsigned short operationType; - [ImplementedAs=item] getter CSSValue(unsigned long index); + [ImplementedAs=item] getter CSSValue (unsigned long index); }; diff --git a/chromium/third_party/WebKit/Source/core/css/fullscreen.css b/chromium/third_party/WebKit/Source/core/css/fullscreen.css index 7ecffc6ffa2..337265b9e42 100644 --- a/chromium/third_party/WebKit/Source/core/css/fullscreen.css +++ b/chromium/third_party/WebKit/Source/core/css/fullscreen.css @@ -31,6 +31,7 @@ video:-webkit-full-screen, audio:-webkit-full-screen { width: 100% !important; flex: 1 !important; display: block !important; + -webkit-transform: none !important; } img:-webkit-full-screen { diff --git a/chromium/third_party/WebKit/Source/core/css/html.css b/chromium/third_party/WebKit/Source/core/css/html.css index fdacec72bdf..52aa586e5c8 100644 --- a/chromium/third_party/WebKit/Source/core/css/html.css +++ b/chromium/third_party/WebKit/Source/core/css/html.css @@ -59,10 +59,6 @@ body { margin: 8px } -body:-webkit-seamless-document { - margin: 0px -} - body:-webkit-full-page-media { background-color: rgb(0, 0, 0) } @@ -394,11 +390,11 @@ button { } /* Form controls don't go vertical. */ -input, textarea, keygen, select, button, isindex, meter, progress { +input, textarea, keygen, select, button, meter, progress { -webkit-writing-mode: horizontal-tb !important; } -input, textarea, keygen, select, button, isindex { +input, textarea, keygen, select, button { margin: 0__qem; font: -webkit-small-control; color: initial; @@ -416,7 +412,7 @@ input[type="hidden"] { display: none } -input, input[type="password"], input[type="search"], isindex { +input, input[type="password"], input[type="search"] { -webkit-appearance: textfield; padding: 1px; background-color: white; @@ -577,8 +573,8 @@ input[type="datetime-local"]::-webkit-inner-spin-button, input[type="month"]::-webkit-inner-spin-button, input[type="time"]::-webkit-inner-spin-button, input[type="week"]::-webkit-inner-spin-button { - display: inline-block; - position: static; + /* FIXME: Remove height. */ + height: 1.5em; -webkit-margin-start: 2px; } @@ -589,7 +585,9 @@ input[type="month"], input[type="time"], input[type="week"] { align-items: center; - -webkit-appearance: menulist-button; + -webkit-appearance: menulist; + background-color: ButtonFace; + border: 1px solid #a9a9a9; display: -webkit-inline-flex; overflow: hidden; width: 10em; @@ -603,15 +601,10 @@ input::-webkit-date-and-time-value { input::-webkit-inner-spin-button { -webkit-appearance: inner-spin-button; - display: block; - position: relative; + display: inline-block; cursor: default; - /* This height property is ignored for input type "number" and others which - * use RenderTextControlSingleLine as renderer which sets height of spin - * button in layout(). */ - height: 1.5em; - vertical-align: top; flex: none; + align-self: stretch; -webkit-user-select: none; -webkit-user-modify: read-only !important; opacity: 0; @@ -623,18 +616,6 @@ input:enabled:read-write:-webkit-any(:focus,:hover)::-webkit-inner-spin-button { pointer-events: auto; } -#if defined(ENABLE_INPUT_SPEECH) && ENABLE_INPUT_SPEECH -input::-webkit-input-speech-button { - -webkit-appearance: -webkit-input-speech-button; - display: block; - vertical-align: top; - flex: none; - -webkit-user-modify: read-only !important; - -webkit-align-self: flex-start; - margin: auto 0; -} -#endif - keygen, select { border-radius: 5px; } @@ -664,7 +645,7 @@ textarea { pointer-events: none !important; } -input::-webkit-input-placeholder, isindex::-webkit-input-placeholder { +input::-webkit-input-placeholder { white-space: pre; word-wrap: normal; overflow: hidden; @@ -688,7 +669,7 @@ input[type="file"] { text-align: start !important; } -input:-webkit-autofill, textarea:-webkit-autofill { +input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill { background-color: #FAFFBD !important; background-image:none !important; color: #000000 !important; @@ -773,6 +754,10 @@ input[type="button"]:active:disabled, input[type="submit"]:active:disabled, inpu border-style: outset } +datalist { + display: none +} + area, param { display: none } @@ -791,6 +776,10 @@ input[type="color"] { -webkit-appearance: square-button; width: 44px; height: 23px; + background-color: ButtonFace; + /* Same as native_theme_base. */ + border: 1px #a9a9a9 solid; + padding: 1px 2px; } input[type="color"]::-webkit-color-swatch-wrapper { @@ -809,6 +798,21 @@ input[type="color"]::-webkit-color-swatch { -webkit-user-modify: read-only !important; } +input[type="color"][list] { + -webkit-appearance: menulist; + width: 88px; + height: 23px +} + +input[type="color"][list]::-webkit-color-swatch-wrapper { + padding-left: 8px; + padding-right: 24px; +} + +input[type="color"][list]::-webkit-color-swatch { + border-color: #000000; +} + input::-webkit-calendar-picker-indicator { display: inline-block; width: 0.66em; @@ -912,7 +916,7 @@ meter::-webkit-meter-inner-element { } 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)); + background: linear-gradient(to bottom, #ddd, #eee 20%, #ccc 45%, #ccc 55%, #ddd); height: 100%; width: 100%; -webkit-user-modify: read-only !important; @@ -920,21 +924,21 @@ meter::-webkit-meter-bar { } 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)); + background: linear-gradient(to bottom, #ad7, #cea 20%, #7a3 45%, #7a3 55%, #ad7); height: 100%; -webkit-user-modify: read-only !important; box-sizing: border-box; } 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)); + background: linear-gradient(to bottom, #fe7, #ffc 20%, #db3 45%, #db3 55%, #fe7); height: 100%; -webkit-user-modify: read-only !important; box-sizing: border-box; } 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)); + background: linear-gradient(to bottom, #f77, #fcc 20%, #d44 45%, #d44 55%, #f77); height: 100%; -webkit-user-modify: read-only !important; box-sizing: border-box; @@ -1046,7 +1050,7 @@ applet:focus, embed:focus, iframe:focus, object:focus { outline: none } -input:focus, textarea:focus, isindex:focus, keygen:focus, select:focus { +input:focus, textarea:focus, keygen:focus, select:focus { outline-offset: -2px } @@ -1108,14 +1112,10 @@ frameset { border-color: inherit } -iframe:not([seamless]) { +iframe { border: 2px inset } -iframe[seamless] { - display: block -} - details { display: block } @@ -1128,7 +1128,7 @@ summary::-webkit-details-marker { display: inline-block; width: 0.66em; height: 0.66em; - margin-right: 0.4em; + -webkit-margin-end: 0.4em; } template { diff --git a/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSet.cpp b/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSet.cpp new file mode 100644 index 00000000000..6f1be3b13bf --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSet.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2014 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: + * + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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. + */ + +#include "config.h" +#include "core/css/invalidation/DescendantInvalidationSet.h" + +#include "core/css/resolver/StyleResolver.h" +#include "core/dom/Element.h" + +namespace WebCore { + +DescendantInvalidationSet::DescendantInvalidationSet() + : m_allDescendantsMightBeInvalid(false) + , m_customPseudoInvalid(false) + , m_treeBoundaryCrossing(false) +{ +} + +bool DescendantInvalidationSet::invalidatesElement(Element& element) const +{ + if (m_allDescendantsMightBeInvalid) + return true; + + if (m_tagNames && m_tagNames->contains(element.tagQName().localName())) + return true; + + if (element.hasID() && m_ids && m_ids->contains(element.idForStyleResolution())) + return true; + + if (element.hasClass() && m_classes) { + const SpaceSplitString& classNames = element.classNames(); + for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_classes->begin(); it != m_classes->end(); ++it) { + if (classNames.contains(*it)) + return true; + } + } + + if (element.hasAttributes() && m_attributes) { + for (WillBeHeapHashSet<AtomicString>::const_iterator it = m_attributes->begin(); it != m_attributes->end(); ++it) { + if (element.hasAttribute(*it)) + return true; + } + } + + return false; +} + +void DescendantInvalidationSet::combine(const DescendantInvalidationSet& other) +{ + // No longer bother combining data structures, since the whole subtree is deemed invalid. + if (wholeSubtreeInvalid()) + return; + + if (other.wholeSubtreeInvalid()) { + setWholeSubtreeInvalid(); + return; + } + + if (other.customPseudoInvalid()) + setCustomPseudoInvalid(); + + if (other.treeBoundaryCrossing()) + setTreeBoundaryCrossing(); + + if (other.m_classes) { + WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_classes->end(); + for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_classes->begin(); it != end; ++it) + addClass(*it); + } + + if (other.m_ids) { + WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_ids->end(); + for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_ids->begin(); it != end; ++it) + addId(*it); + } + + if (other.m_tagNames) { + WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_tagNames->end(); + for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_tagNames->begin(); it != end; ++it) + addTagName(*it); + } + + if (other.m_attributes) { + WillBeHeapHashSet<AtomicString>::const_iterator end = other.m_attributes->end(); + for (WillBeHeapHashSet<AtomicString>::const_iterator it = other.m_attributes->begin(); it != end; ++it) + addAttribute(*it); + } +} + +WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureClassSet() +{ + if (!m_classes) + m_classes = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>); + return *m_classes; +} + +WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureIdSet() +{ + if (!m_ids) + m_ids = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>); + return *m_ids; +} + +WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureTagNameSet() +{ + if (!m_tagNames) + m_tagNames = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>); + return *m_tagNames; +} + +WillBeHeapHashSet<AtomicString>& DescendantInvalidationSet::ensureAttributeSet() +{ + if (!m_attributes) + m_attributes = adoptPtrWillBeNoop(new WillBeHeapHashSet<AtomicString>); + return *m_attributes; +} + +void DescendantInvalidationSet::addClass(const AtomicString& className) +{ + if (wholeSubtreeInvalid()) + return; + ensureClassSet().add(className); +} + +void DescendantInvalidationSet::addId(const AtomicString& id) +{ + if (wholeSubtreeInvalid()) + return; + ensureIdSet().add(id); +} + +void DescendantInvalidationSet::addTagName(const AtomicString& tagName) +{ + if (wholeSubtreeInvalid()) + return; + ensureTagNameSet().add(tagName); +} + +void DescendantInvalidationSet::addAttribute(const AtomicString& attribute) +{ + if (wholeSubtreeInvalid()) + return; + ensureAttributeSet().add(attribute); +} + +void DescendantInvalidationSet::setWholeSubtreeInvalid() +{ + if (m_allDescendantsMightBeInvalid) + return; + + m_allDescendantsMightBeInvalid = true; + m_treeBoundaryCrossing = false; + m_classes = nullptr; + m_ids = nullptr; + m_tagNames = nullptr; + m_attributes = nullptr; +} + +void DescendantInvalidationSet::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_classes); + visitor->trace(m_ids); + visitor->trace(m_tagNames); + visitor->trace(m_attributes); +#endif +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSet.h b/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSet.h new file mode 100644 index 00000000000..b86c93b03c6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSet.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2014 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: + * + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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. + */ + +#ifndef DescendantInvalidationSet_h +#define DescendantInvalidationSet_h + +#include "platform/heap/Handle.h" +#include "wtf/Forward.h" +#include "wtf/HashSet.h" +#include "wtf/RefCounted.h" +#include "wtf/RefPtr.h" +#include "wtf/text/AtomicStringHash.h" +#include "wtf/text/StringHash.h" + +namespace WebCore { + +class Element; + +// Tracks data to determine which elements of a DOM subtree need to have style +// recalculated. +class DescendantInvalidationSet FINAL : public RefCountedWillBeGarbageCollected<DescendantInvalidationSet> { +public: + static PassRefPtrWillBeRawPtr<DescendantInvalidationSet> create() + { + return adoptRefWillBeNoop(new DescendantInvalidationSet); + } + + bool invalidatesElement(Element&) const; + + void combine(const DescendantInvalidationSet& other); + + void addClass(const AtomicString& className); + void addId(const AtomicString& id); + void addTagName(const AtomicString& tagName); + void addAttribute(const AtomicString& attributeLocalName); + + void setWholeSubtreeInvalid(); + bool wholeSubtreeInvalid() const { return m_allDescendantsMightBeInvalid; } + + void setTreeBoundaryCrossing() { m_treeBoundaryCrossing = true; } + bool treeBoundaryCrossing() const { return m_treeBoundaryCrossing; } + + void setCustomPseudoInvalid() { m_customPseudoInvalid = true; } + bool customPseudoInvalid() const { return m_customPseudoInvalid; } + + bool isEmpty() const { return !m_classes && !m_ids && !m_tagNames && !m_attributes; } + + void trace(Visitor*); + +private: + DescendantInvalidationSet(); + + WillBeHeapHashSet<AtomicString>& ensureClassSet(); + WillBeHeapHashSet<AtomicString>& ensureIdSet(); + WillBeHeapHashSet<AtomicString>& ensureTagNameSet(); + WillBeHeapHashSet<AtomicString>& ensureAttributeSet(); + + // FIXME: optimize this if it becomes a memory issue. + OwnPtrWillBeMember<WillBeHeapHashSet<AtomicString> > m_classes; + OwnPtrWillBeMember<WillBeHeapHashSet<AtomicString> > m_ids; + OwnPtrWillBeMember<WillBeHeapHashSet<AtomicString> > m_tagNames; + OwnPtrWillBeMember<WillBeHeapHashSet<AtomicString> > m_attributes; + + // If true, all descendants might be invalidated, so a full subtree recalc is required. + unsigned m_allDescendantsMightBeInvalid : 1; + + // If true, all descendants which are custom pseudo elements must be invalidated. + unsigned m_customPseudoInvalid : 1; + + // If true, the invalidation must traverse into ShadowRoots with this set. + unsigned m_treeBoundaryCrossing : 1; +}; + +} // namespace WebCore + +#endif // DescendantInvalidationSet_h diff --git a/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSetTest.cpp b/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSetTest.cpp new file mode 100644 index 00000000000..3732ebf405e --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/DescendantInvalidationSetTest.cpp @@ -0,0 +1,64 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/invalidation/DescendantInvalidationSet.h" + +#include <gtest/gtest.h> + +using namespace WebCore; + +namespace { + +// Once we setWholeSubtreeInvalid, we should not keep the HashSets. +TEST(DescendantInvalidationSetTest, SubtreeInvalid_AddBefore) +{ + RefPtrWillBeRawPtr<DescendantInvalidationSet> set = DescendantInvalidationSet::create(); + set->addClass("a"); + set->setWholeSubtreeInvalid(); + + ASSERT_TRUE(set->isEmpty()); +} + +// Don't (re)create HashSets if we've already setWholeSubtreeInvalid. +TEST(DescendantInvalidationSetTest, SubtreeInvalid_AddAfter) +{ + RefPtrWillBeRawPtr<DescendantInvalidationSet> set = DescendantInvalidationSet::create(); + set->setWholeSubtreeInvalid(); + set->addTagName("a"); + + ASSERT_TRUE(set->isEmpty()); +} + +// No need to keep the HashSets when combining with a wholeSubtreeInvalid set. +TEST(DescendantInvalidationSetTest, SubtreeInvalid_Combine_1) +{ + RefPtrWillBeRawPtr<DescendantInvalidationSet> set1 = DescendantInvalidationSet::create(); + RefPtrWillBeRawPtr<DescendantInvalidationSet> set2 = DescendantInvalidationSet::create(); + + set1->addId("a"); + set2->setWholeSubtreeInvalid(); + + set1->combine(*set2); + + ASSERT_TRUE(set1->wholeSubtreeInvalid()); + ASSERT_TRUE(set1->isEmpty()); +} + +// No need to add HashSets from combining set when we already have wholeSubtreeInvalid. +TEST(DescendantInvalidationSetTest, SubtreeInvalid_Combine_2) +{ + RefPtrWillBeRawPtr<DescendantInvalidationSet> set1 = DescendantInvalidationSet::create(); + RefPtrWillBeRawPtr<DescendantInvalidationSet> set2 = DescendantInvalidationSet::create(); + + set1->setWholeSubtreeInvalid(); + set2->addAttribute("a"); + + set1->combine(*set2); + + ASSERT_TRUE(set1->wholeSubtreeInvalid()); + ASSERT_TRUE(set1->isEmpty()); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp new file mode 100644 index 00000000000..3874c2b93e6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp @@ -0,0 +1,167 @@ + +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/css/invalidation/StyleInvalidator.h" + +#include "core/css/invalidation/DescendantInvalidationSet.h" +#include "core/dom/Document.h" +#include "core/dom/Element.h" +#include "core/dom/ElementTraversal.h" +#include "core/dom/shadow/ElementShadow.h" +#include "core/dom/shadow/ShadowRoot.h" +#include "core/rendering/RenderObject.h" + +namespace WebCore { + +void StyleInvalidator::invalidate(Document& document) +{ + if (Element* documentElement = document.documentElement()) + invalidate(*documentElement); + document.clearChildNeedsStyleInvalidation(); + document.clearNeedsStyleInvalidation(); + clearPendingInvalidations(); +} + +void StyleInvalidator::scheduleInvalidation(PassRefPtrWillBeRawPtr<DescendantInvalidationSet> invalidationSet, Element& element) +{ + ASSERT(element.inActiveDocument()); + ASSERT(element.styleChangeType() < SubtreeStyleChange); + InvalidationList& list = ensurePendingInvalidationList(element); + // If we're already going to invalidate the whole subtree we don't need to store any new sets. + if (!list.isEmpty() && list.last()->wholeSubtreeInvalid()) + return; + // If this set would invalidate the whole subtree we can discard all existing sets. + if (invalidationSet->wholeSubtreeInvalid()) + list.clear(); + list.append(invalidationSet); + element.setNeedsStyleInvalidation(); +} + +StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationList(Element& element) +{ + PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(&element, nullptr); + if (addResult.isNewEntry) + addResult.storedValue->value = adoptPtrWillBeNoop(new InvalidationList); + return *addResult.storedValue->value; +} + +void StyleInvalidator::clearInvalidation(Node& node) +{ + if (node.isElementNode() && node.needsStyleInvalidation()) + m_pendingInvalidationMap.remove(toElement(&node)); +} + +void StyleInvalidator::clearPendingInvalidations() +{ + m_pendingInvalidationMap.clear(); +} + +StyleInvalidator::StyleInvalidator() +{ +} + +StyleInvalidator::~StyleInvalidator() +{ +} + +void StyleInvalidator::RecursionData::pushInvalidationSet(const DescendantInvalidationSet& invalidationSet) +{ + ASSERT(!m_wholeSubtreeInvalid); + if (invalidationSet.treeBoundaryCrossing()) + m_treeBoundaryCrossing = true; + if (invalidationSet.wholeSubtreeInvalid()) { + m_wholeSubtreeInvalid = true; + return; + } + m_invalidationSets.append(&invalidationSet); + m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid(); +} + +bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& element) +{ + ASSERT(!m_wholeSubtreeInvalid); + + if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom) + return true; + + for (InvalidationSets::iterator it = m_invalidationSets.begin(); it != m_invalidationSets.end(); ++it) { + if ((*it)->invalidatesElement(element)) + return true; + } + + return false; +} + +bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element) +{ + if (element.styleChangeType() >= SubtreeStyleChange || m_recursionData.wholeSubtreeInvalid()) { + m_recursionData.setWholeSubtreeInvalid(); + return false; + } + if (element.needsStyleInvalidation()) { + if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&element)) { + for (InvalidationList::const_iterator it = invalidationList->begin(); it != invalidationList->end(); ++it) + m_recursionData.pushInvalidationSet(**it); + // FIXME: It's really only necessary to clone the render style for this element, not full style recalc. + return true; + } + } + return m_recursionData.matchesCurrentInvalidationSets(element); +} + +bool StyleInvalidator::invalidateChildren(Element& element) +{ + bool someChildrenNeedStyleRecalc = false; + for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->olderShadowRoot()) { + if (!m_recursionData.treeBoundaryCrossing() && !root->childNeedsStyleInvalidation() && !root->needsStyleInvalidation()) + continue; + for (Element* child = ElementTraversal::firstChild(*root); child; child = ElementTraversal::nextSibling(*child)) { + bool childRecalced = invalidate(*child); + someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced; + } + root->clearChildNeedsStyleInvalidation(); + root->clearNeedsStyleInvalidation(); + } + for (Element* child = ElementTraversal::firstChild(element); child; child = ElementTraversal::nextSibling(*child)) { + bool childRecalced = invalidate(*child); + someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalced; + } + return someChildrenNeedStyleRecalc; +} + +bool StyleInvalidator::invalidate(Element& element) +{ + RecursionCheckpoint checkpoint(&m_recursionData); + + bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(element); + + bool someChildrenNeedStyleRecalc = false; + if (m_recursionData.hasInvalidationSets() || element.childNeedsStyleInvalidation()) + someChildrenNeedStyleRecalc = invalidateChildren(element); + + if (thisElementNeedsStyleRecalc) { + element.setNeedsStyleRecalc(m_recursionData.wholeSubtreeInvalid() ? SubtreeStyleChange : LocalStyleChange); + } else if (m_recursionData.hasInvalidationSets() && someChildrenNeedStyleRecalc) { + // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style. + if (RenderObject* renderer = element.renderer()) + renderer->setStyleInternal(RenderStyle::clone(renderer->style())); + else + element.setNeedsStyleRecalc(LocalStyleChange); + } + + element.clearChildNeedsStyleInvalidation(); + element.clearNeedsStyleInvalidation(); + + return thisElementNeedsStyleRecalc; +} + +void StyleInvalidator::trace(Visitor* visitor) +{ + visitor->trace(m_pendingInvalidationMap); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.h b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.h new file mode 100644 index 00000000000..275c6c8c8e6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.h @@ -0,0 +1,96 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef StyleInvalidator_h +#define StyleInvalidator_h + +#include "platform/heap/Handle.h" + +namespace WebCore { + +class DescendantInvalidationSet; +class Document; +class Element; + +class StyleInvalidator { + DISALLOW_ALLOCATION(); +public: + StyleInvalidator(); + ~StyleInvalidator(); + void invalidate(Document&); + void scheduleInvalidation(PassRefPtrWillBeRawPtr<DescendantInvalidationSet>, Element&); + + // Clears all style invalidation state for the passed node. + void clearInvalidation(Node&); + + void clearPendingInvalidations(); + + void trace(Visitor*); + +private: + bool invalidate(Element&); + bool invalidateChildren(Element&); + + bool checkInvalidationSetsAgainstElement(Element&); + + struct RecursionData { + RecursionData() + : m_invalidateCustomPseudo(false) + , m_wholeSubtreeInvalid(false) + , m_treeBoundaryCrossing(false) + { } + + void pushInvalidationSet(const DescendantInvalidationSet&); + bool matchesCurrentInvalidationSets(Element&); + bool hasInvalidationSets() const { return !wholeSubtreeInvalid() && m_invalidationSets.size(); } + + bool wholeSubtreeInvalid() const { return m_wholeSubtreeInvalid; } + void setWholeSubtreeInvalid() { m_wholeSubtreeInvalid = true; } + + bool treeBoundaryCrossing() const { return m_treeBoundaryCrossing; } + + typedef Vector<const DescendantInvalidationSet*, 16> InvalidationSets; + InvalidationSets m_invalidationSets; + bool m_invalidateCustomPseudo; + bool m_wholeSubtreeInvalid; + bool m_treeBoundaryCrossing; + }; + + class RecursionCheckpoint { + public: + RecursionCheckpoint(RecursionData* data) + : m_prevInvalidationSetsSize(data->m_invalidationSets.size()) + , m_prevInvalidateCustomPseudo(data->m_invalidateCustomPseudo) + , m_prevWholeSubtreeInvalid(data->m_wholeSubtreeInvalid) + , m_treeBoundaryCrossing(data->m_treeBoundaryCrossing) + , m_data(data) + { } + ~RecursionCheckpoint() + { + m_data->m_invalidationSets.remove(m_prevInvalidationSetsSize, m_data->m_invalidationSets.size() - m_prevInvalidationSetsSize); + m_data->m_invalidateCustomPseudo = m_prevInvalidateCustomPseudo; + m_data->m_wholeSubtreeInvalid = m_prevWholeSubtreeInvalid; + m_data->m_treeBoundaryCrossing = m_treeBoundaryCrossing; + } + + private: + int m_prevInvalidationSetsSize; + bool m_prevInvalidateCustomPseudo; + bool m_prevWholeSubtreeInvalid; + bool m_treeBoundaryCrossing; + RecursionData* m_data; + }; + + typedef WillBeHeapVector<RefPtrWillBeMember<DescendantInvalidationSet> > InvalidationList; + typedef WillBeHeapHashMap<RawPtrWillBeMember<Element>, OwnPtrWillBeMember<InvalidationList> > PendingInvalidationMap; + + InvalidationList& ensurePendingInvalidationList(Element&); + + PendingInvalidationMap m_pendingInvalidationMap; + RecursionData m_recursionData; +}; + +} // namespace WebCore + +#endif // StyleInvalidator_h diff --git a/chromium/third_party/WebKit/Source/core/css/StyleInvalidationAnalysis.cpp b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleSheetInvalidationAnalysis.cpp index 440e17fe346..bb9854b4762 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleInvalidationAnalysis.cpp +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleSheetInvalidationAnalysis.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "core/css/StyleInvalidationAnalysis.h" +#include "core/css/invalidation/StyleSheetInvalidationAnalysis.h" #include "core/css/CSSSelectorList.h" #include "core/css/StyleRuleImport.h" @@ -37,7 +37,7 @@ namespace WebCore { -StyleInvalidationAnalysis::StyleInvalidationAnalysis(const Vector<StyleSheetContents*>& sheets) +StyleSheetInvalidationAnalysis::StyleSheetInvalidationAnalysis(const WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents> >& sheets) : m_dirtiesAllStyle(false) { for (unsigned i = 0; i < sheets.size() && !m_dirtiesAllStyle; ++i) @@ -46,23 +46,27 @@ StyleInvalidationAnalysis::StyleInvalidationAnalysis(const Vector<StyleSheetCont static bool determineSelectorScopes(const CSSSelectorList& selectorList, HashSet<StringImpl*>& idScopes, HashSet<StringImpl*>& classScopes) { - for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) { + for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) { const CSSSelector* scopeSelector = 0; // This picks the widest scope, not the narrowest, to minimize the number of found scopes. for (const CSSSelector* current = selector; current; current = current->tagHistory()) { // Prefer ids over classes. - if (current->m_match == CSSSelector::Id) + if (current->match() == CSSSelector::Id) scopeSelector = current; - else if (current->m_match == CSSSelector::Class && (!scopeSelector || scopeSelector->m_match != CSSSelector::Id)) + else if (current->match() == CSSSelector::Class && (!scopeSelector || scopeSelector->match() != CSSSelector::Id)) scopeSelector = current; CSSSelector::Relation relation = current->relation(); + // FIXME: it would be better to use setNeedsStyleRecalc for all shadow hosts matching + // scopeSelector. Currently requests full style recalc. + if (relation == CSSSelector::ShadowDeep || relation == CSSSelector::ShadowPseudo) + return false; if (relation != CSSSelector::Descendant && relation != CSSSelector::Child && relation != CSSSelector::SubSelector) break; } if (!scopeSelector) return false; - ASSERT(scopeSelector->m_match == CSSSelector::Class || scopeSelector->m_match == CSSSelector::Id); - if (scopeSelector->m_match == CSSSelector::Id) + ASSERT(scopeSelector->match() == CSSSelector::Class || scopeSelector->match() == CSSSelector::Id); + if (scopeSelector->match() == CSSSelector::Id) idScopes.add(scopeSelector->value().impl()); else classScopes.add(scopeSelector->value().impl()); @@ -72,7 +76,7 @@ static bool determineSelectorScopes(const CSSSelectorList& selectorList, HashSet static bool hasDistributedRule(StyleSheetContents* styleSheetContents) { - const Vector<RefPtr<StyleRuleBase> >& rules = styleSheetContents->childRules(); + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& rules = styleSheetContents->childRules(); for (unsigned i = 0; i < rules.size(); i++) { const StyleRuleBase* rule = rules[i].get(); if (!rule->isStyleRule()) @@ -88,24 +92,19 @@ static bool hasDistributedRule(StyleSheetContents* styleSheetContents) return false; } -static Node* determineScopingNodeForStyleScoped(HTMLStyleElement* ownerElement, StyleSheetContents* styleSheetContents) +static Node* determineScopingNodeForStyleInShadow(HTMLStyleElement* ownerElement, StyleSheetContents* styleSheetContents) { - ASSERT(ownerElement && ownerElement->isRegisteredAsScoped()); - - if (ownerElement->isInShadowTree()) { - if (hasDistributedRule(styleSheetContents)) { - ContainerNode* scope = ownerElement; - do { - scope = scope->containingShadowRoot()->shadowHost(); - } while (scope->isInShadowTree()); - - return scope; - } - if (ownerElement->isRegisteredAsScoped()) - return ownerElement->containingShadowRoot()->shadowHost(); + ASSERT(ownerElement && ownerElement->isInShadowTree()); + + if (hasDistributedRule(styleSheetContents)) { + ContainerNode* scope = ownerElement; + do { + scope = scope->containingShadowRoot()->shadowHost(); + } while (scope->isInShadowTree()); + return scope; } - return ownerElement->isRegisteredInShadowRoot() ? ownerElement->containingShadowRoot()->shadowHost() : ownerElement->parentNode(); + return ownerElement->containingShadowRoot()->shadowHost(); } static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule) @@ -123,7 +122,6 @@ static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule) case StyleRule::Supports: // If we evaluated the supports-clause we could avoid recalc. case StyleRule::Viewport: // If the viewport doesn't match, we could avoid recalcing. // FIXME: Unclear if any of the rest need to cause style recalc: - case StyleRule::Region: case StyleRule::Filter: return true; @@ -138,13 +136,13 @@ static bool ruleAdditionMightRequireDocumentStyleRecalc(StyleRuleBase* rule) return true; } -void StyleInvalidationAnalysis::analyzeStyleSheet(StyleSheetContents* styleSheetContents) +void StyleSheetInvalidationAnalysis::analyzeStyleSheet(StyleSheetContents* styleSheetContents) { ASSERT(!styleSheetContents->isLoading()); // See if all rules on the sheet are scoped to some specific ids or classes. // Then test if we actually have any of those in the tree at the moment. - const Vector<RefPtr<StyleRuleImport> >& importRules = styleSheetContents->importRules(); + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleImport> >& importRules = styleSheetContents->importRules(); for (unsigned i = 0; i < importRules.size(); ++i) { if (!importRules[i]->styleSheet()) continue; @@ -154,13 +152,13 @@ void StyleInvalidationAnalysis::analyzeStyleSheet(StyleSheetContents* styleSheet } if (styleSheetContents->hasSingleOwnerNode()) { Node* ownerNode = styleSheetContents->singleOwnerNode(); - if (ownerNode && ownerNode->hasTagName(HTMLNames::styleTag) && toHTMLStyleElement(ownerNode)->isRegisteredAsScoped()) { - m_scopingNodes.append(determineScopingNodeForStyleScoped(toHTMLStyleElement(ownerNode), styleSheetContents)); + if (isHTMLStyleElement(ownerNode) && toHTMLStyleElement(*ownerNode).isInShadowTree()) { + m_scopingNodes.append(determineScopingNodeForStyleInShadow(toHTMLStyleElement(ownerNode), styleSheetContents)); return; } } - const Vector<RefPtr<StyleRuleBase> >& rules = styleSheetContents->childRules(); + const WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> >& rules = styleSheetContents->childRules(); for (unsigned i = 0; i < rules.size(); i++) { StyleRuleBase* rule = rules[i].get(); if (!rule->isStyleRule()) { @@ -192,13 +190,13 @@ static bool elementMatchesSelectorScopes(const Element* element, const HashSet<S return false; } -void StyleInvalidationAnalysis::invalidateStyle(Document& document) +void StyleSheetInvalidationAnalysis::invalidateStyle(Document& document) { ASSERT(!m_dirtiesAllStyle); if (!m_scopingNodes.isEmpty()) { for (unsigned i = 0; i < m_scopingNodes.size(); ++i) - m_scopingNodes.at(i)->setNeedsStyleRecalc(); + m_scopingNodes.at(i)->setNeedsStyleRecalc(SubtreeStyleChange); } if (m_idScopes.isEmpty() && m_classScopes.isEmpty()) @@ -206,7 +204,7 @@ void StyleInvalidationAnalysis::invalidateStyle(Document& document) Element* element = ElementTraversal::firstWithin(document); while (element) { if (elementMatchesSelectorScopes(element, m_idScopes, m_classScopes)) { - element->setNeedsStyleRecalc(); + element->setNeedsStyleRecalc(SubtreeStyleChange); // The whole subtree is now invalidated, we can skip to the next sibling. element = ElementTraversal::nextSkippingChildren(*element); continue; diff --git a/chromium/third_party/WebKit/Source/core/css/StyleInvalidationAnalysis.h b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleSheetInvalidationAnalysis.h index 79cf3d87bda..9b74a3eef53 100644 --- a/chromium/third_party/WebKit/Source/core/css/StyleInvalidationAnalysis.h +++ b/chromium/third_party/WebKit/Source/core/css/invalidation/StyleSheetInvalidationAnalysis.h @@ -23,9 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef StyleInvalidationAnalysis_h -#define StyleInvalidationAnalysis_h +#ifndef StyleSheetInvalidationAnalysis_h +#define StyleSheetInvalidationAnalysis_h +#include "platform/heap/Handle.h" #include "wtf/HashSet.h" #include "wtf/Vector.h" #include "wtf/text/StringImpl.h" @@ -36,9 +37,9 @@ class Document; class Node; class StyleSheetContents; -class StyleInvalidationAnalysis { +class StyleSheetInvalidationAnalysis { public: - StyleInvalidationAnalysis(const Vector<StyleSheetContents*>&); + StyleSheetInvalidationAnalysis(const WillBeHeapVector<RawPtrWillBeMember<StyleSheetContents> >&); bool dirtiesAllStyle() const { return m_dirtiesAllStyle; } void invalidateStyle(Document&); diff --git a/chromium/third_party/WebKit/Source/core/css/make-css-file-arrays.pl b/chromium/third_party/WebKit/Source/core/css/make-css-file-arrays.pl index 66eb7dfb0e4..d111cb30576 100755 --- a/chromium/third_party/WebKit/Source/core/css/make-css-file-arrays.pl +++ b/chromium/third_party/WebKit/Source/core/css/make-css-file-arrays.pl @@ -34,8 +34,10 @@ shift; my $out = $ARGV[0]; shift; -open HEADER, ">", $header or die; -open OUT, ">", $out or die; +$header =~ s|\\|/|g; +$out =~ s|\\|/|g; +open HEADER, ">", $header or die "$!\n"; +open OUT, ">", $out or die "$!\n"; print HEADER "namespace WebCore {\n"; print OUT "namespace WebCore {\n"; diff --git a/chromium/third_party/WebKit/Source/core/css/mathml.css b/chromium/third_party/WebKit/Source/core/css/mathml.css new file mode 100644 index 00000000000..cef10e3f7b0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/mathml.css @@ -0,0 +1,49 @@ +/* + * The default style sheet used to render MathML. + * + * Copyright (C) 2014 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 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, + * 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. + */ + +@namespace "http://www.w3.org/1998/Math/MathML"; + +/* By default, we only display the MathML formulas without any formatting other than the one specified by the display attribute. */ +math { + display: inline; +} + +math[display="block"] { + display: block; + text-align: center; +} + +/* We hide the PresentationExpression constructions that are children of a <semantics> element. + http://www.w3.org/TR/MathML/appendixa.html#parsing_PresentationExpression */ +semantics > mi, semantics > mn, semantics > mo, semantics > mtext, semantics > mspace, semantics > ms, semantics > maligngroup, semantics > malignmark, semantics > mrow, semantics > mfrac, semantics > msqrt, semantics > mroot, semantics > mstyle, semantics > merror, semantics > mpadded, semantics > mphantom, semantics > mfenced, semantics > menclose, semantics > msub, semantics > msup, semantics > msubsup, semantics > munder, semantics > mover, semantics > munderover, semantics > mmultiscripts, semantics > mtable, semantics > mstack, semantics > mlongdiv, semantics > maction { + display: none; +} + +/* However, we display all the annotations. */ +annotation, annotation-xml { + display: inline-block; +} diff --git a/chromium/third_party/WebKit/Source/core/css/mediaControls.css b/chromium/third_party/WebKit/Source/core/css/mediaControls.css index a2efc1d2bc1..d3b5536e4a4 100644 --- a/chromium/third_party/WebKit/Source/core/css/mediaControls.css +++ b/chromium/third_party/WebKit/Source/core/css/mediaControls.css @@ -115,10 +115,40 @@ audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-bu color: inherit; } -audio::-webkit-media-controls-overlay-play-button, video::-webkit-media-controls-overlay-play-button { +audio::-webkit-media-controls-overlay-enclosure { display: none; } +video::-webkit-media-controls-overlay-enclosure { + display: flex; + position: relative; + flex-direction: column; + justify-content: flex-end; + align-items: center; + flex: 1 1; + width: 100%; + max-width: 800px; + text-indent: 0; + box-sizing: border-box; + overflow: hidden; +} + +video::-webkit-media-controls-overlay-play-button { + -webkit-appearance: media-overlay-play-button; + display: flex; + position: absolute; + top: 50%; + left: 50%; + margin-left: -40px; + margin-top: -40px; + border: none; + box-sizing: border-box; + background-color: transparent; + width: 80px; + height: 80px; + padding: 0; +} + audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { -webkit-appearance: media-play-button; display: flex; @@ -231,26 +261,6 @@ input[type="range"]::-webkit-media-slider-thumb { margin-right: -7px; } -audio::-webkit-media-controls-seek-back-button, video::-webkit-media-controls-seek-back-button { - -webkit-appearance: media-seek-back-button; - display: flex; - width: 16px; - height: 16px; - background-color: initial; - border: initial; - color: inherit; -} - -audio::-webkit-media-controls-seek-forward-button, video::-webkit-media-controls-seek-forward-button { - -webkit-appearance: media-seek-forward-button; - display: flex; - width: 16px; - height: 16px; - background-color: initial; - border: initial; - color: inherit; -} - audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-fullscreen-button { -webkit-appearance: media-enter-fullscreen-button; display: flex; @@ -267,20 +277,6 @@ audio::-webkit-media-controls-fullscreen-button, video::-webkit-media-controls-f 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 { display: none; } @@ -301,14 +297,6 @@ video::-webkit-media-controls-toggle-closed-captions-button { 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; -} - audio::-webkit-media-controls-fullscreen-volume-slider, video::-webkit-media-controls-fullscreen-volume-slider { display: none; } diff --git a/chromium/third_party/WebKit/Source/core/css/mediaControlsAndroid.css b/chromium/third_party/WebKit/Source/core/css/mediaControlsAndroid.css index 35a0bb4435e..107d18106b7 100644 --- a/chromium/third_party/WebKit/Source/core/css/mediaControlsAndroid.css +++ b/chromium/third_party/WebKit/Source/core/css/mediaControlsAndroid.css @@ -38,24 +38,6 @@ video::-webkit-media-controls-enclosure { height: 40px; } -audio::-webkit-media-controls-overlay-enclosure { - display: none; -} - -video::-webkit-media-controls-overlay-enclosure { - display: flex; - position: relative; - flex-direction: column; - justify-content: flex-end; - align-items: center; - flex: 1 1; - width: 100%; - max-width: 800px; - text-indent: 0; - box-sizing: border-box; - overflow: hidden; -} - audio::-webkit-media-controls-panel, video::-webkit-media-controls-panel { height: 35px; } @@ -64,22 +46,6 @@ audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-bu display: none; } -video::-webkit-media-controls-overlay-play-button { - -webkit-appearance: media-overlay-play-button; - display: flex; - position: absolute; - top: 50%; - left: 50%; - margin-left: -40px; - margin-top: -40px; - border: none; - box-sizing: border-box; - background-color: transparent; - width: 80px; - height: 80px; - padding: 0; -} - audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button { width: 35px; height: 35px; diff --git a/chromium/third_party/WebKit/Source/core/css/navigationTransitions.css b/chromium/third_party/WebKit/Source/core/css/navigationTransitions.css new file mode 100644 index 00000000000..4ae2f81d390 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/navigationTransitions.css @@ -0,0 +1,13 @@ +/* + * Copyright 2014 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +body { + animation-duration: 300ms; + transition-duration: 300ms; + + /* Prevent user interaction. */ + pointer-events: none !important; +}
\ No newline at end of file diff --git a/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp new file mode 100644 index 00000000000..4b366c75d11 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp @@ -0,0 +1,2119 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * 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. + */ + +#include "config.h" +#include "core/css/parser/BisonCSSParser.h" + +#include "core/CSSValueKeywords.h" +#include "core/StylePropertyShorthand.h" +#include "core/css/CSSArrayFunctionValue.h" +#include "core/css/CSSAspectRatioValue.h" +#include "core/css/CSSBasicShapes.h" +#include "core/css/CSSBorderImage.h" +#include "core/css/CSSCanvasValue.h" +#include "core/css/CSSCrossfadeValue.h" +#include "core/css/CSSCursorImageValue.h" +#include "core/css/CSSFontFaceSrcValue.h" +#include "core/css/CSSFontFeatureValue.h" +#include "core/css/CSSFunctionValue.h" +#include "core/css/CSSGradientValue.h" +#include "core/css/CSSGridLineNamesValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" +#include "core/css/CSSImageSetValue.h" +#include "core/css/CSSImageValue.h" +#include "core/css/CSSInheritedValue.h" +#include "core/css/CSSInitialValue.h" +#include "core/css/CSSKeyframeRule.h" +#include "core/css/CSSKeyframesRule.h" +#include "core/css/CSSLineBoxContainValue.h" +#include "core/css/CSSPrimitiveValue.h" +#include "core/css/CSSPropertySourceData.h" +#include "core/css/CSSReflectValue.h" +#include "core/css/CSSSelector.h" +#include "core/css/CSSShadowValue.h" +#include "core/css/CSSStyleSheet.h" +#include "core/css/CSSTimingFunctionValue.h" +#include "core/css/CSSTransformValue.h" +#include "core/css/CSSUnicodeRangeValue.h" +#include "core/css/CSSValueList.h" +#include "core/css/CSSValuePool.h" +#include "core/css/Counter.h" +#include "core/css/HashTools.h" +#include "core/css/MediaList.h" +#include "core/css/MediaQueryExp.h" +#include "core/css/Pair.h" +#include "core/css/Rect.h" +#include "core/css/StylePropertySet.h" +#include "core/css/StyleRule.h" +#include "core/css/StyleRuleImport.h" +#include "core/css/StyleSheetContents.h" +#include "core/css/parser/CSSParserIdioms.h" +#include "core/dom/Document.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/Settings.h" +#include "core/html/parser/HTMLParserIdioms.h" +#include "core/inspector/InspectorInstrumentation.h" +#include "core/rendering/RenderTheme.h" +#include "platform/FloatConversion.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "wtf/BitArray.h" +#include "wtf/HexNumber.h" +#include "wtf/text/StringBuffer.h" +#include "wtf/text/StringBuilder.h" +#include "wtf/text/StringImpl.h" +#include "wtf/text/TextEncoding.h" +#include <limits.h> + +#define YYDEBUG 0 + +#if YYDEBUG > 0 +extern int cssyydebug; +#endif + +int cssyyparse(WebCore::BisonCSSParser*); + +using namespace WTF; + +namespace WebCore { + +static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; + +BisonCSSParser::BisonCSSParser(const CSSParserContext& context) + : m_context(context) + , m_important(false) + , m_id(CSSPropertyInvalid) + , m_styleSheet(nullptr) + , m_supportsCondition(false) + , m_selectorListForParseSelector(0) + , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES) + , m_hadSyntacticallyValidCSSRule(false) + , m_logErrors(false) + , m_ignoreErrors(false) + , m_defaultNamespace(starAtom) + , m_observer(0) + , m_source(0) + , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE) + , m_allowImportRules(true) + , m_allowNamespaceDeclarations(true) + , m_inViewport(false) + , m_tokenizer(*this) +{ +#if YYDEBUG > 0 + cssyydebug = 1; +#endif +} + +BisonCSSParser::~BisonCSSParser() +{ + clearProperties(); + + deleteAllValues(m_floatingSelectors); + deleteAllValues(m_floatingSelectorVectors); + deleteAllValues(m_floatingValueLists); + deleteAllValues(m_floatingFunctions); +} + +void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength) +{ + m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength); + m_ruleHasHeader = true; +} + +void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors) +{ + setStyleSheet(sheet); + m_defaultNamespace = starAtom; // Reset the default namespace. + TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer); + m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost(); + m_ignoreErrors = false; + m_tokenizer.m_lineNumber = 0; + m_startPosition = startPosition; + m_source = &string; + m_tokenizer.m_internal = false; + setupParser("", string, ""); + cssyyparse(this); + sheet->shrinkToFit(); + m_source = 0; + m_rule = nullptr; + m_lineEndings.clear(); + m_ignoreErrors = false; + m_logErrors = false; + m_tokenizer.m_internal = true; +} + +PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string) +{ + setStyleSheet(sheet); + m_allowNamespaceDeclarations = false; + setupParser("@-internal-rule ", string, ""); + cssyyparse(this); + return m_rule.release(); +} + +PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string) +{ + setStyleSheet(sheet); + setupParser("@-internal-keyframe-rule ", string, ""); + cssyyparse(this); + return m_keyframe.release(); +} + +PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string) +{ + setupParser("@-internal-keyframe-key-list ", string, ""); + cssyyparse(this); + ASSERT(m_valueList); + return StyleKeyframe::createKeyList(m_valueList.get()); +} + +bool BisonCSSParser::parseSupportsCondition(const String& string) +{ + m_supportsCondition = false; + setupParser("@-internal-supports-condition ", string, ""); + cssyyparse(this); + return m_supportsCondition; +} + +static inline bool isColorPropertyID(CSSPropertyID 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; + case CSSPropertyTextDecorationColor: + return RuntimeEnabledFeatures::css3TextDecorationsEnabled(); + default: + return false; + } +} + +static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode) +{ + ASSERT(!string.isEmpty()); + bool quirksMode = isQuirksModeBehavior(cssParserMode); + if (!isColorPropertyID(propertyId)) + return false; + CSSParserString cssString; + cssString.init(string); + CSSValueID 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 + || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) { + validPrimitive = true; + } + + if (validPrimitive) { + RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID); + declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); + return true; + } + RGBA32 color; + if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#')) + return false; + RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color); + declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); + return true; +} + +static inline bool isSimpleLengthPropertyID(CSSPropertyID 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 CSSPropertyShapeMargin: + acceptsNegativeNumbers = false; + return RuntimeEnabledFeatures::cssShapesEnabled(); + case CSSPropertyBottom: + case CSSPropertyLeft: + case CSSPropertyMarginBottom: + case CSSPropertyMarginLeft: + case CSSPropertyMarginRight: + case CSSPropertyMarginTop: + case CSSPropertyRight: + case CSSPropertyTop: + case CSSPropertyWebkitMarginAfter: + case CSSPropertyWebkitMarginBefore: + case CSSPropertyWebkitMarginEnd: + case CSSPropertyWebkitMarginStart: + acceptsNegativeNumbers = true; + return true; + default: + return false; + } +} + +template <typename CharacterType> +static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number) +{ + if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == '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; + number = charactersToDouble(characters, length, &ok); + return ok; +} + +static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode) +{ + ASSERT(!string.isEmpty()); + bool acceptsNegativeNumbers = false; + + // In @viewport, width and height are shorthands, not simple length values. + if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) + return false; + + unsigned length = string.length(); + double number; + CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER; + + if (string.is8Bit()) { + if (!parseSimpleLength(string.characters8(), length, unit, number)) + return false; + } else { + if (!parseSimpleLength(string.characters16(), length, unit, number)) + return false; + } + + if (unit == CSSPrimitiveValue::CSS_NUMBER) { + bool quirksMode = isQuirksModeBehavior(cssParserMode); + if (number && !quirksMode) + return false; + unit = CSSPrimitiveValue::CSS_PX; + } + if (number < 0 && !acceptsNegativeNumbers) + return false; + + RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit); + declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); + return true; +} + +bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, const CSSParserContext& parserContext) +{ + if (valueID == CSSValueInvalid) + return false; + + switch (propertyId) { + case CSSPropertyBackgroundRepeatX: // repeat | no-repeat + case CSSPropertyBackgroundRepeatY: // repeat | no-repeat + return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat; + case CSSPropertyBorderCollapse: // collapse | separate + return valueID == CSSValueCollapse || valueID == CSSValueSeparate; + case CSSPropertyBorderTopStyle: // <border-style> + case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed | + case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset + case CSSPropertyBorderLeftStyle: + case CSSPropertyWebkitBorderAfterStyle: + case CSSPropertyWebkitBorderBeforeStyle: + case CSSPropertyWebkitBorderEndStyle: + case CSSPropertyWebkitBorderStartStyle: + case CSSPropertyWebkitColumnRuleStyle: + return valueID >= CSSValueNone && valueID <= CSSValueDouble; + case CSSPropertyBoxSizing: + return valueID == CSSValueBorderBox || valueID == CSSValueContentBox; + case CSSPropertyCaptionSide: // top | bottom | left | right + return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom; + case CSSPropertyClear: // none | left | right | both + return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth; + case CSSPropertyDirection: // ltr | rtl + return valueID == CSSValueLtr || valueID == CSSValueRtl; + case CSSPropertyDisplay: + // inline | block | list-item | inline-block | table | + // inline-table | table-row-group | table-header-group | table-footer-group | table-row | + // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none + // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid | lazy-block + return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone + || (RuntimeEnabledFeatures::cssGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid)); + case CSSPropertyEmptyCells: // show | hide + return valueID == CSSValueShow || valueID == CSSValueHide; + case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none) + return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter; + case CSSPropertyFontStyle: // normal | italic | oblique + return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique; + case CSSPropertyImageRendering: // auto | optimizeContrast + return valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast; + case CSSPropertyIsolation: // auto | isolate + return RuntimeEnabledFeatures::cssCompositingEnabled() + && (valueID == CSSValueAuto || valueID == CSSValueIsolate); + case CSSPropertyListStylePosition: // inside | outside + return valueID == CSSValueInside || valueID == CSSValueOutside; + case CSSPropertyListStyleType: + // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in + // for the list of supported list-style-types. + return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone; + case CSSPropertyObjectFit: + return RuntimeEnabledFeatures::objectFitPositionEnabled() + && (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown); + case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto + return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble); + case CSSPropertyOverflowWrap: // normal | break-word + case CSSPropertyWordWrap: + return valueID == CSSValueNormal || valueID == CSSValueBreakWord; + case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay + return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay; + case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y + return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY; + case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right + case CSSPropertyPageBreakBefore: + case CSSPropertyWebkitColumnBreakAfter: + case CSSPropertyWebkitColumnBreakBefore: + return valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight; + case CSSPropertyPageBreakInside: // avoid | auto + case CSSPropertyWebkitColumnBreakInside: + return valueID == CSSValueAuto || valueID == CSSValueAvoid; + case CSSPropertyPointerEvents: + // none | visiblePainted | visibleFill | visibleStroke | visible | + // painted | fill | stroke | auto | all | bounding-box + return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox); + case CSSPropertyPosition: // static | relative | absolute | fixed | sticky + return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed + || (RuntimeEnabledFeatures::cssStickyPositionEnabled() && valueID == CSSValueSticky); + case CSSPropertyResize: // none | both | horizontal | vertical | auto + return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto; + case CSSPropertyScrollBehavior: // instant | smooth + return RuntimeEnabledFeatures::cssomSmoothScrollEnabled() + && (valueID == CSSValueInstant || valueID == CSSValueSmooth); + case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation + return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation; + case CSSPropertyTableLayout: // auto | fixed + return valueID == CSSValueAuto || valueID == CSSValueFixed; + case CSSPropertyTextAlignLast: + // auto | start | end | left | right | center | justify + return RuntimeEnabledFeatures::css3TextEnabled() + && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto); + case CSSPropertyTextJustify: + // auto | none | inter-word | distribute + return RuntimeEnabledFeatures::css3TextEnabled() + && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone); + case CSSPropertyTextLineThroughMode: + case CSSPropertyTextOverlineMode: + case CSSPropertyTextUnderlineMode: + return valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace; + case CSSPropertyTextLineThroughStyle: + case CSSPropertyTextOverlineStyle: + case CSSPropertyTextUnderlineStyle: + return valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave; + case CSSPropertyTextOverflow: // clip | ellipsis + return valueID == CSSValueClip || valueID == CSSValueEllipsis; + case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision + return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision; + case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none + return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone; + case CSSPropertyTouchActionDelay: // none | script + return RuntimeEnabledFeatures::cssTouchActionDelayEnabled() + && (valueID == CSSValueScript || valueID == CSSValueNone); + case CSSPropertyVisibility: // visible | hidden | collapse + return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse; + case CSSPropertyWebkitAppearance: + return (valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone; + case CSSPropertyBackfaceVisibility: + case CSSPropertyWebkitBackfaceVisibility: + return valueID == CSSValueVisible || valueID == CSSValueHidden; + case CSSPropertyMixBlendMode: + return RuntimeEnabledFeatures::cssCompositingEnabled() + && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay + || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn + || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion + || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity); + case CSSPropertyWebkitBorderFit: + return valueID == CSSValueBorder || valueID == CSSValueLines; + case CSSPropertyWebkitBoxAlign: + return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline; + case CSSPropertyWebkitBoxDecorationBreak: + return valueID == CSSValueClone || valueID == CSSValueSlice; + case CSSPropertyWebkitBoxDirection: + return valueID == CSSValueNormal || valueID == CSSValueReverse; + case CSSPropertyWebkitBoxLines: + return valueID == CSSValueSingle || valueID == CSSValueMultiple; + case CSSPropertyWebkitBoxOrient: + return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis; + case CSSPropertyWebkitBoxPack: + return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify; + case CSSPropertyInternalCallback: + // This property is only injected programmatically, not parsed from stylesheets. + return false; + case CSSPropertyColumnFill: + return RuntimeEnabledFeatures::regionBasedColumnsEnabled() + && (valueID == CSSValueAuto || valueID == CSSValueBalance); + case CSSPropertyAlignContent: + // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'. + return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch; + case CSSPropertyAlignItems: + // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code. + return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch; + case CSSPropertyAlignSelf: + // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code. + return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch; + case CSSPropertyFlexDirection: + return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse; + case CSSPropertyFlexWrap: + return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse; + case CSSPropertyJustifyContent: + // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'. + return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround; + case CSSPropertyFontKerning: + return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone; + case CSSPropertyWebkitFontSmoothing: + return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased; + case CSSPropertyGridAutoFlow: + return RuntimeEnabledFeatures::cssGridLayoutEnabled() + && (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn); + case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space + return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace; + case CSSPropertyWebkitMarginAfterCollapse: + case CSSPropertyWebkitMarginBeforeCollapse: + case CSSPropertyWebkitMarginBottomCollapse: + case CSSPropertyWebkitMarginTopCollapse: + return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard; + case CSSPropertyInternalMarqueeDirection: + return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown + || valueID == CSSValueUp || valueID == CSSValueAuto; + case CSSPropertyInternalMarqueeStyle: + return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate; + case CSSPropertyWebkitPrintColorAdjust: + return valueID == CSSValueExact || valueID == CSSValueEconomy; + case CSSPropertyWebkitRtlOrdering: + return valueID == CSSValueLogical || valueID == CSSValueVisual; + case CSSPropertyWebkitRubyPosition: + return valueID == CSSValueBefore || valueID == CSSValueAfter; + case CSSPropertyWebkitTextCombine: + return valueID == CSSValueNone || valueID == CSSValueHorizontal; + case CSSPropertyWebkitTextEmphasisPosition: + return valueID == CSSValueOver || valueID == CSSValueUnder; + case CSSPropertyWebkitTextSecurity: // disc | circle | square | none + return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone; + case CSSPropertyTransformStyle: + case CSSPropertyWebkitTransformStyle: + return valueID == CSSValueFlat || valueID == CSSValuePreserve3d; + case CSSPropertyWebkitUserDrag: // auto | none | element + return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement; + case CSSPropertyWebkitUserModify: // read-only | read-write + return valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly; + case CSSPropertyWebkitUserSelect: // auto | none | text | all + return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll; + case CSSPropertyWebkitWrapFlow: + return RuntimeEnabledFeatures::cssExclusionsEnabled() + && (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear); + case CSSPropertyWebkitWrapThrough: + return RuntimeEnabledFeatures::cssExclusionsEnabled() + && (valueID == CSSValueWrap || valueID == CSSValueNone); + case CSSPropertyWebkitWritingMode: + return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt; + case CSSPropertyWhiteSpace: // normal | pre | nowrap + return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap; + case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension) + return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord; + default: + ASSERT_NOT_REACHED(); + return false; + } + return false; +} + +bool isKeywordPropertyID(CSSPropertyID propertyId) +{ + switch (propertyId) { + case CSSPropertyMixBlendMode: + case CSSPropertyIsolation: + case CSSPropertyBackgroundRepeatX: + case CSSPropertyBackgroundRepeatY: + case CSSPropertyBorderBottomStyle: + case CSSPropertyBorderCollapse: + case CSSPropertyBorderLeftStyle: + case CSSPropertyBorderRightStyle: + case CSSPropertyBorderTopStyle: + case CSSPropertyBoxSizing: + case CSSPropertyCaptionSide: + case CSSPropertyClear: + case CSSPropertyDirection: + case CSSPropertyDisplay: + case CSSPropertyEmptyCells: + case CSSPropertyFloat: + case CSSPropertyFontStyle: + case CSSPropertyImageRendering: + case CSSPropertyListStylePosition: + case CSSPropertyListStyleType: + case CSSPropertyObjectFit: + case CSSPropertyOutlineStyle: + case CSSPropertyOverflowWrap: + case CSSPropertyOverflowX: + case CSSPropertyOverflowY: + case CSSPropertyPageBreakAfter: + case CSSPropertyPageBreakBefore: + case CSSPropertyPageBreakInside: + case CSSPropertyPointerEvents: + case CSSPropertyPosition: + case CSSPropertyResize: + case CSSPropertyScrollBehavior: + case CSSPropertySpeak: + case CSSPropertyTableLayout: + case CSSPropertyTextAlignLast: + case CSSPropertyTextJustify: + case CSSPropertyTextLineThroughMode: + case CSSPropertyTextLineThroughStyle: + case CSSPropertyTextOverflow: + case CSSPropertyTextOverlineMode: + case CSSPropertyTextOverlineStyle: + case CSSPropertyTextRendering: + case CSSPropertyTextTransform: + case CSSPropertyTextUnderlineMode: + case CSSPropertyTextUnderlineStyle: + case CSSPropertyTouchActionDelay: + case CSSPropertyVisibility: + case CSSPropertyWebkitAppearance: + case CSSPropertyBackfaceVisibility: + case CSSPropertyWebkitBackfaceVisibility: + case CSSPropertyWebkitBorderAfterStyle: + case CSSPropertyWebkitBorderBeforeStyle: + case CSSPropertyWebkitBorderEndStyle: + case CSSPropertyWebkitBorderFit: + case CSSPropertyWebkitBorderStartStyle: + case CSSPropertyWebkitBoxAlign: + case CSSPropertyWebkitBoxDecorationBreak: + case CSSPropertyWebkitBoxDirection: + case CSSPropertyWebkitBoxLines: + case CSSPropertyWebkitBoxOrient: + case CSSPropertyWebkitBoxPack: + case CSSPropertyInternalCallback: + case CSSPropertyWebkitColumnBreakAfter: + case CSSPropertyWebkitColumnBreakBefore: + case CSSPropertyWebkitColumnBreakInside: + case CSSPropertyColumnFill: + case CSSPropertyWebkitColumnRuleStyle: + case CSSPropertyAlignContent: + case CSSPropertyFlexDirection: + case CSSPropertyFlexWrap: + case CSSPropertyJustifyContent: + case CSSPropertyFontKerning: + case CSSPropertyWebkitFontSmoothing: + case CSSPropertyGridAutoFlow: + case CSSPropertyWebkitLineBreak: + case CSSPropertyWebkitMarginAfterCollapse: + case CSSPropertyWebkitMarginBeforeCollapse: + case CSSPropertyWebkitMarginBottomCollapse: + case CSSPropertyWebkitMarginTopCollapse: + case CSSPropertyInternalMarqueeDirection: + case CSSPropertyInternalMarqueeStyle: + case CSSPropertyWebkitPrintColorAdjust: + case CSSPropertyWebkitRtlOrdering: + case CSSPropertyWebkitRubyPosition: + case CSSPropertyWebkitTextCombine: + case CSSPropertyWebkitTextEmphasisPosition: + case CSSPropertyWebkitTextSecurity: + case CSSPropertyTransformStyle: + case CSSPropertyWebkitTransformStyle: + case CSSPropertyWebkitUserDrag: + case CSSPropertyWebkitUserModify: + case CSSPropertyWebkitUserSelect: + case CSSPropertyWebkitWrapFlow: + case CSSPropertyWebkitWrapThrough: + case CSSPropertyWebkitWritingMode: + case CSSPropertyWhiteSpace: + case CSSPropertyWordBreak: + case CSSPropertyWordWrap: + return true; + case CSSPropertyAlignItems: + case CSSPropertyAlignSelf: + return !RuntimeEnabledFeatures::cssGridLayoutEnabled(); + default: + return false; + } +} + +static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext) +{ + ASSERT(!string.isEmpty()); + + if (!isKeywordPropertyID(propertyId)) { + // All properties accept the values of "initial" and "inherit". + String lowerCaseString = string.lower(); + if (lowerCaseString != "initial" && lowerCaseString != "inherit") + return false; + + // Parse initial/inherit shorthands using the BisonCSSParser. + if (shorthandForProperty(propertyId).length()) + return false; + } + + CSSParserString cssString; + cssString.init(string); + CSSValueID valueID = cssValueKeywordID(cssString); + + if (!valueID) + return false; + + RefPtrWillBeRawPtr<CSSValue> value = nullptr; + if (valueID == CSSValueInherit) + value = cssValuePool().createInheritedValue(); + else if (valueID == CSSValueInitial) + value = cssValuePool().createExplicitInitialValue(); + else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext)) + value = cssValuePool().createIdentifierValue(valueID); + else + return false; + + declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); + return true; +} + +template <typename CharType> +static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue) +{ + while (expectedCount) { + size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ','); + if (delimiter == kNotFound) + return false; + unsigned argumentLength = static_cast<unsigned>(delimiter); + CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER; + double number; + if (!parseSimpleLength(pos, argumentLength, unit, number)) + return false; + if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER)) + return false; + transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX)); + pos += argumentLength + 1; + --expectedCount; + } + return true; +} + +template <typename CharType> +static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue) +{ + while (expectedCount) { + size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ','); + if (delimiter == kNotFound) + return false; + unsigned argumentLength = static_cast<unsigned>(delimiter); + bool ok; + double number = charactersToDouble(pos, argumentLength, &ok); + if (!ok) + return false; + transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER)); + pos += argumentLength + 1; + --expectedCount; + } + return true; +} + +template <typename CharType> +static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end) +{ + static const int shortestValidTransformStringLength = 12; + + if (end - pos < shortestValidTransformStringLength) + return nullptr; + + const bool isTranslate = toASCIILower(pos[0]) == 't' + && toASCIILower(pos[1]) == 'r' + && toASCIILower(pos[2]) == 'a' + && toASCIILower(pos[3]) == 'n' + && toASCIILower(pos[4]) == 's' + && toASCIILower(pos[5]) == 'l' + && toASCIILower(pos[6]) == 'a' + && toASCIILower(pos[7]) == 't' + && toASCIILower(pos[8]) == 'e'; + + if (isTranslate) { + CSSTransformValue::TransformOperationType transformType; + unsigned expectedArgumentCount = 1; + unsigned argumentStart = 11; + CharType c9 = toASCIILower(pos[9]); + if (c9 == 'x' && pos[10] == '(') { + transformType = CSSTransformValue::TranslateXTransformOperation; + } else if (c9 == 'y' && pos[10] == '(') { + transformType = CSSTransformValue::TranslateYTransformOperation; + } else if (c9 == 'z' && pos[10] == '(') { + transformType = CSSTransformValue::TranslateZTransformOperation; + } else if (c9 == '(') { + transformType = CSSTransformValue::TranslateTransformOperation; + expectedArgumentCount = 2; + argumentStart = 10; + } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') { + transformType = CSSTransformValue::Translate3DTransformOperation; + expectedArgumentCount = 3; + argumentStart = 12; + } else { + return nullptr; + } + pos += argumentStart; + RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType); + if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get())) + return nullptr; + return transformValue.release(); + } + + const bool isMatrix3d = toASCIILower(pos[0]) == 'm' + && toASCIILower(pos[1]) == 'a' + && toASCIILower(pos[2]) == 't' + && toASCIILower(pos[3]) == 'r' + && toASCIILower(pos[4]) == 'i' + && toASCIILower(pos[5]) == 'x' + && pos[6] == '3' + && toASCIILower(pos[7]) == 'd' + && pos[8] == '('; + + if (isMatrix3d) { + pos += 9; + RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation); + if (!parseTransformNumberArguments(pos, end, 16, transformValue.get())) + return nullptr; + return transformValue.release(); + } + + const bool isScale3d = toASCIILower(pos[0]) == 's' + && toASCIILower(pos[1]) == 'c' + && toASCIILower(pos[2]) == 'a' + && toASCIILower(pos[3]) == 'l' + && toASCIILower(pos[4]) == 'e' + && pos[5] == '3' + && toASCIILower(pos[6]) == 'd' + && pos[7] == '('; + + if (isScale3d) { + pos += 8; + RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation); + if (!parseTransformNumberArguments(pos, end, 3, transformValue.get())) + return nullptr; + return transformValue.release(); + } + + return nullptr; +} + +template <typename CharType> +static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end) +{ + RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr; + while (pos < end) { + while (pos < end && isCSSSpace(*pos)) + ++pos; + RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end); + if (!transformValue) + return nullptr; + if (!transformList) + transformList = CSSValueList::createSpaceSeparated(); + transformList->append(transformValue.release()); + if (pos < end) { + if (isCSSSpace(*pos)) + return nullptr; + } + } + return transformList.release(); +} + +static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important) +{ + if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform) + return false; + if (string.isEmpty()) + return false; + RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr; + if (string.is8Bit()) { + const LChar* pos = string.characters8(); + const LChar* end = pos + string.length(); + transformList = parseSimpleTransformList(pos, end); + if (!transformList) + return false; + } else { + const UChar* pos = string.characters16(); + const UChar* end = pos + string.length(); + transformList = parseSimpleTransformList(pos, end); + if (!transformList) + return false; + } + properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important)); + return true; +} + +PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string) +{ + if (string.isEmpty()) + return nullptr; + RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create(); + if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0)) + return nullptr; + + RefPtrWillBeRawPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily); + if (!fontFamily->isValueList()) + return nullptr; + + return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get()); +} + +PassRefPtrWillBeRawPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string) +{ + if (string.isEmpty()) + return nullptr; + RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create(); + if (!parseValue(style.get(), CSSPropertyTransitionTimingFunction, string, false, HTMLStandardMode, 0)) + return nullptr; + + RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(CSSPropertyTransitionTimingFunction); + if (!value || value->isInitialValue() || value->isInheritedValue()) + return nullptr; + CSSValueList* valueList = toCSSValueList(value.get()); + if (valueList->length() > 1) + return nullptr; + return valueList->item(0); +} + +bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document) +{ + ASSERT(!string.isEmpty()); + + CSSParserContext context(document, UseCounter::getFrom(&document)); + + if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode())) + return true; + if (parseColorValue(declaration, propertyID, string, important, context.mode())) + return true; + if (parseKeywordValue(declaration, propertyID, string, important, context)) + return true; + + BisonCSSParser parser(context); + return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0)); +} + +bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet) +{ + ASSERT(!string.isEmpty()); + if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode)) + return true; + if (parseColorValue(declaration, propertyID, string, important, cssParserMode)) + return true; + + CSSParserContext context(cssParserMode, 0); + if (contextStyleSheet) { + context = contextStyleSheet->parserContext(); + context.setMode(cssParserMode); + } + + if (parseKeywordValue(declaration, propertyID, string, important, context)) + return true; + if (parseSimpleTransform(declaration, propertyID, string, important)) + return true; + + BisonCSSParser parser(context); + return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet); +} + +bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet) +{ + // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty. + + if (m_context.useCounter()) + m_context.useCounter()->count(m_context, propertyID); + + setStyleSheet(contextStyleSheet); + + setupParser("@-internal-value ", string, ""); + + m_id = propertyID; + m_important = important; + + { + StyleDeclarationScope scope(this, declaration); + cssyyparse(this); + } + + m_rule = nullptr; + m_id = CSSPropertyInvalid; + + bool ok = false; + if (!m_parsedProperties.isEmpty()) { + ok = true; + declaration->addParsedProperties(m_parsedProperties); + clearProperties(); + } + + return ok; +} + +// The color will only be changed when string contains a valid CSS color, so callers +// can set it to a default color and ignore the boolean result. +bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict) +{ + // First try creating a color specified by name, rgba(), rgb() or "#" syntax. + if (CSSPropertyParser::fastParseColor(color, string, strict)) + return true; + + BisonCSSParser parser(strictCSSParserContext()); + + // In case the fast-path parser didn't understand the color, try the full parser. + if (!parser.parseColor(string)) + return false; + + CSSValue* value = parser.m_parsedProperties.first().value(); + if (!value->isPrimitiveValue()) + return false; + + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (!primitiveValue->isRGBColor()) + return false; + + color = primitiveValue->getRGBA32Value(); + return true; +} + +bool BisonCSSParser::parseColor(const String& string) +{ + setupParser("@-internal-decls color:", string, ""); + cssyyparse(this); + m_rule = nullptr; + + return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor; +} + +bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string) +{ + CSSParserString cssColor; + cssColor.init(string); + CSSValueID id = cssValueKeywordID(cssColor); + if (!CSSPropertyParser::isSystemColor(id)) + return false; + + Color parsedColor = RenderTheme::theme().systemColor(id); + color = parsedColor.rgb(); + return true; +} + +void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList) +{ + m_selectorListForParseSelector = &selectorList; + + setupParser("@-internal-selector ", string, ""); + + cssyyparse(this); + + m_selectorListForParseSelector = 0; +} + +PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element) +{ + Document& document = element->document(); + CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document)); + context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode); + return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents()); +} + +PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet) +{ + setStyleSheet(contextStyleSheet); + + setupParser("@-internal-decls ", string, ""); + cssyyparse(this); + m_rule = nullptr; + + RefPtr<ImmutableStylePropertySet> style = createStylePropertySet(); + clearProperties(); + return style.release(); +} + + +bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet) +{ + setStyleSheet(contextStyleSheet); + + TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer); + + setupParser("@-internal-decls ", string, ""); + if (m_observer) { + m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0); + m_observer->endRuleHeader(1); + m_observer->startRuleBody(0); + } + + { + StyleDeclarationScope scope(this, declaration); + cssyyparse(this); + } + + m_rule = nullptr; + + bool ok = false; + if (!m_parsedProperties.isEmpty()) { + ok = true; + declaration->addParsedProperties(m_parsedProperties); + clearProperties(); + } + + if (m_observer) + m_observer->endRuleBody(string.length(), false); + + return ok; +} + +PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string) +{ + ASSERT(!m_mediaList); + + // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token. + // instead insert one " " (which is caught by maybe_space in CSSGrammar.y) + setupParser("@-internal-medialist ", string, ""); + cssyyparse(this); + + ASSERT(m_mediaList); + return m_mediaList.release(); +} + +static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties) +{ + // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found. + for (int i = input.size() - 1; i >= 0; --i) { + const CSSProperty& property = input[i]; + if (property.isImportant() != important) + continue; + const unsigned propertyIDIndex = property.id() - firstCSSProperty; + if (seenProperties.get(propertyIDIndex)) + continue; + seenProperties.set(propertyIDIndex); + output[--unusedEntries] = property; + } +} + +PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet() +{ + BitArray<numCSSProperties> seenProperties; + size_t unusedEntries = m_parsedProperties.size(); + WillBeHeapVector<CSSProperty, 256> results(unusedEntries); + + // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found. + filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties); + filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties); + if (unusedEntries) + results.remove(0, unusedEntries); + + CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode(); + + return ImmutableStylePropertySet::create(results.data(), results.size(), mode); +} + +void BisonCSSParser::rollbackLastProperties(int num) +{ + ASSERT(num >= 0); + ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num)); + m_parsedProperties.shrink(m_parsedProperties.size() - num); +} + +void BisonCSSParser::clearProperties() +{ + m_parsedProperties.clear(); + m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; +} + +void BisonCSSParser::setCurrentProperty(CSSPropertyID propId) +{ + m_id = propId; +} + +bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important) +{ + CSSPropertyParser parser(m_valueList, m_context, m_inViewport, m_important, m_parsedProperties, m_ruleHeaderType); + return parser.parseValue(propId, important); +} + + +class TransformOperationInfo { +public: + TransformOperationInfo(const CSSParserString& name) + : m_type(CSSTransformValue::UnknownTransformOperation) + , m_argCount(1) + , m_allowSingleArgument(false) + , m_unit(CSSPropertyParser::FUnknown) + { + const UChar* characters; + unsigned nameLength = name.length(); + + const unsigned longestNameLength = 12; + UChar characterBuffer[longestNameLength]; + if (name.is8Bit()) { + unsigned length = std::min(longestNameLength, nameLength); + const LChar* characters8 = name.characters8(); + for (unsigned i = 0; i < length; ++i) + characterBuffer[i] = characters8[i]; + characters = characterBuffer; + } else + characters = name.characters16(); + + SWITCH(characters, nameLength) { + CASE("skew(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::SkewTransformOperation; + m_allowSingleArgument = true; + m_argCount = 3; + } + CASE("scale(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::ScaleTransformOperation; + m_allowSingleArgument = true; + m_argCount = 3; + } + CASE("skewx(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::SkewXTransformOperation; + } + CASE("skewy(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::SkewYTransformOperation; + } + CASE("matrix(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::MatrixTransformOperation; + m_argCount = 11; + } + CASE("rotate(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::RotateTransformOperation; + } + CASE("scalex(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::ScaleXTransformOperation; + } + CASE("scaley(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::ScaleYTransformOperation; + } + CASE("scalez(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::ScaleZTransformOperation; + } + CASE("scale3d(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::Scale3DTransformOperation; + m_argCount = 5; + } + CASE("rotatex(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::RotateXTransformOperation; + } + CASE("rotatey(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::RotateYTransformOperation; + } + CASE("rotatez(") { + m_unit = CSSPropertyParser::FAngle; + m_type = CSSTransformValue::RotateZTransformOperation; + } + CASE("matrix3d(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::Matrix3DTransformOperation; + m_argCount = 31; + } + CASE("rotate3d(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::Rotate3DTransformOperation; + m_argCount = 7; + } + CASE("translate(") { + m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent; + m_type = CSSTransformValue::TranslateTransformOperation; + m_allowSingleArgument = true; + m_argCount = 3; + } + CASE("translatex(") { + m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent; + m_type = CSSTransformValue::TranslateXTransformOperation; + } + CASE("translatey(") { + m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent; + m_type = CSSTransformValue::TranslateYTransformOperation; + } + CASE("translatez(") { + m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent; + m_type = CSSTransformValue::TranslateZTransformOperation; + } + CASE("perspective(") { + m_unit = CSSPropertyParser::FNumber; + m_type = CSSTransformValue::PerspectiveTransformOperation; + } + CASE("translate3d(") { + m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent; + m_type = CSSTransformValue::Translate3DTransformOperation; + m_argCount = 5; + } + } + } + + CSSTransformValue::TransformOperationType type() const { return m_type; } + unsigned argCount() const { return m_argCount; } + CSSPropertyParser::Units unit() const { return m_unit; } + + bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; } + bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); } + +private: + CSSTransformValue::TransformOperationType m_type; + unsigned m_argCount; + bool m_allowSingleArgument; + CSSPropertyParser::Units m_unit; +}; + +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId) +{ + if (!m_valueList) + return nullptr; + + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { + RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value); + if (!parsedTransformValue) + return nullptr; + + list->append(parsedTransformValue.release()); + } + + return list.release(); +} + +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value) +{ + if (value->unit != CSSParserValue::Function || !value->function) + return nullptr; + + // Every primitive requires at least one argument. + CSSParserValueList* args = value->function->args.get(); + if (!args) + return nullptr; + + // See if the specified primitive is one we understand. + TransformOperationInfo info(value->function->name); + if (info.unknown()) + return nullptr; + + if (!info.hasCorrectArgCount(args->size())) + return nullptr; + + // The transform is a list of functional primitives that specify transform operations. + // We collect a list of CSSTransformValues, where each value specifies a single operation. + + // Create the new CSSTransformValue for this operation and add it to our list. + RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type()); + + // Snag our values. + CSSParserValue* a = args->current(); + unsigned argNumber = 0; + while (a) { + CSSPropertyParser::Units unit = info.unit(); + + if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) { + // 4th param of rotate3d() is an angle rather than a bare number, validate it as such + if (!validUnit(a, FAngle, HTMLStandardMode)) + return nullptr; + } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) { + // 3rd param of translate3d() cannot be a percentage + if (!validUnit(a, FLength, HTMLStandardMode)) + return nullptr; + } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) { + // 1st param of translateZ() cannot be a percentage + if (!validUnit(a, FLength, HTMLStandardMode)) + return nullptr; + } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) { + // 1st param of perspective() must be a non-negative number (deprecated) or length. + if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode)) + || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode))) + return nullptr; + } else if (!validUnit(a, unit, HTMLStandardMode)) { + return nullptr; + } + + // Add the value to the current transform operation. + transformValue->append(createPrimitiveNumericValue(a)); + + a = args->next(); + if (!a) + break; + if (a->unit != CSSParserValue::Operator || a->iValue != ',') + return nullptr; + a = args->next(); + + argNumber++; + } + + return transformValue.release(); +} + +void BisonCSSParser::ensureLineEndings() +{ + if (!m_lineEndings) + m_lineEndings = lineEndings(*m_source); +} + +CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName) +{ + CSSParserSelector* selector = new CSSParserSelector(tagQName); + m_floatingSelectors.append(selector); + return selector; +} + +CSSParserSelector* BisonCSSParser::createFloatingSelector() +{ + CSSParserSelector* selector = new CSSParserSelector; + m_floatingSelectors.append(selector); + return selector; +} + +PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector) +{ + if (selector) { + size_t index = m_floatingSelectors.reverseFind(selector); + ASSERT(index != kNotFound); + m_floatingSelectors.remove(index); + } + return adoptPtr(selector); +} + +Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector() +{ + Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >; + m_floatingSelectorVectors.append(selectorVector); + return selectorVector; +} + +PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector) +{ + if (selectorVector) { + size_t index = m_floatingSelectorVectors.reverseFind(selectorVector); + ASSERT(index != kNotFound); + m_floatingSelectorVectors.remove(index); + } + return adoptPtr(selectorVector); +} + +CSSParserValueList* BisonCSSParser::createFloatingValueList() +{ + CSSParserValueList* list = new CSSParserValueList; + m_floatingValueLists.append(list); + return list; +} + +PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list) +{ + if (list) { + size_t index = m_floatingValueLists.reverseFind(list); + ASSERT(index != kNotFound); + m_floatingValueLists.remove(index); + } + return adoptPtr(list); +} + +CSSParserFunction* BisonCSSParser::createFloatingFunction() +{ + CSSParserFunction* function = new CSSParserFunction; + m_floatingFunctions.append(function); + return function; +} + +CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args) +{ + CSSParserFunction* function = createFloatingFunction(); + function->name = name; + function->args = args; + return function; +} + +PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function) +{ + if (function) { + size_t index = m_floatingFunctions.reverseFind(function); + ASSERT(index != kNotFound); + m_floatingFunctions.remove(index); + } + return adoptPtr(function); +} + +CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value) +{ + if (value.unit == CSSParserValue::Function) { + size_t index = m_floatingFunctions.reverseFind(value.function); + ASSERT(index != kNotFound); + m_floatingFunctions.remove(index); + } + return value; +} + +MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values) +{ + m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values); + return m_floatingMediaQueryExp.get(); +} + +PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression) +{ + ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp); + return m_floatingMediaQueryExp.release(); +} + +WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList() +{ + m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >); + return m_floatingMediaQueryExpList.get(); +} + +PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list) +{ + ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList); + return m_floatingMediaQueryExpList.release(); +} + +MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions) +{ + m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions)); + return m_floatingMediaQuery.get(); +} + +MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions) +{ + return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions); +} + +MediaQuery* BisonCSSParser::createFloatingNotAllQuery() +{ + return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList())); +} + +PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query) +{ + ASSERT_UNUSED(query, query == m_floatingMediaQuery); + return m_floatingMediaQuery.release(); +} + +WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector() +{ + m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >()); + return m_floatingKeyframeVector.get(); +} + +PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector) +{ + ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector); + return m_floatingKeyframeVector.release(); +} + +MediaQuerySet* BisonCSSParser::createMediaQuerySet() +{ + RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create(); + MediaQuerySet* result = queries.get(); + m_parsedMediaQuerySets.append(queries.release()); + return result; +} + +StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media) +{ + if (!media || !m_allowImportRules) + return 0; + RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media); + StyleRuleImport* result = rule.get(); + m_parsedRules.append(rule.release()); + return result; +} + +StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules) +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr; + if (rules) { + rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules); + } else { + RuleList emptyRules; + rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules); + } + StyleRuleMedia* result = rule.get(); + m_parsedRules.append(rule.release()); + return result; +} + +StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules) +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + + RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData(); + RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr; + String conditionText; + unsigned conditionOffset = data->ruleHeaderRange.start + 9; + unsigned conditionLength = data->ruleHeaderRange.length() - 9; + + if (m_tokenizer.is8BitSource()) + conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace(); + else + conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace(); + + if (rules) { + rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules); + } else { + RuleList emptyRules; + rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules); + } + + StyleRuleSupports* result = rule.get(); + m_parsedRules.append(rule.release()); + + return result; +} + +void BisonCSSParser::markSupportsRuleHeaderStart() +{ + if (!m_supportsRuleDataStack) + m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList()); + + RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE); + data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset(); + m_supportsRuleDataStack->append(data); +} + +void BisonCSSParser::markSupportsRuleHeaderEnd() +{ + ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty()); + + if (m_tokenizer.is8BitSource()) + m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get(); + else + m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get(); +} + +PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData() +{ + ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty()); + RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last(); + m_supportsRuleDataStack->removeLast(); + return data.release(); +} + +BisonCSSParser::RuleList* BisonCSSParser::createRuleList() +{ + OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList); + RuleList* listPtr = list.get(); + + m_parsedRuleLists.append(list.release()); + return listPtr; +} + +BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule) +{ + if (rule) { + if (!ruleList) + ruleList = createRuleList(); + ruleList->append(rule); + } + return ruleList; +} + +template <typename CharacterType> +ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length) +{ + // FIXME: If we need Unicode lowercasing here, then we probably want the real kind + // that can potentially change the length of the string rather than the character + // by character kind. If we don't need Unicode lowercasing, it would be good to + // simplify this function. + + if (charactersAreAllASCII(input, length)) { + // Fast case for all-ASCII. + for (unsigned i = 0; i < length; i++) + output[i] = toASCIILower(input[i]); + } else { + for (unsigned i = 0; i < length; i++) + output[i] = Unicode::toLower(input[i]); + } +} + +void BisonCSSParser::tokenToLowerCase(CSSParserString& token) +{ + // Since it's our internal token, we know that we created it out + // of our writable work buffers. Therefore the const_cast is just + // ugly and not a potential crash. + size_t length = token.length(); + if (token.is8Bit()) { + makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length); + } else { + makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length); + } +} + +void BisonCSSParser::endInvalidRuleHeader() +{ + if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE) + return; + + CSSParserLocation location; + location.lineNumber = m_tokenizer.m_lineNumber; + location.offset = m_ruleHeaderStartOffset; + if (m_tokenizer.is8BitSource()) + location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0); + else + location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0); + + reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError); + + endRuleHeader(); +} + +void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError) +{ + // FIXME: error reporting temporatily disabled. +} + +bool BisonCSSParser::isLoggingErrors() +{ + return m_logErrors && !m_ignoreErrors; +} + +void BisonCSSParser::logError(const String& message, const CSSParserLocation& location) +{ + unsigned lineNumberInStyleSheet; + unsigned columnNumber = 0; + if (InspectorInstrumentation::hasFrontends()) { + ensureLineEndings(); + TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings); + lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt(); + columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt(); + } else { + lineNumberInStyleSheet = location.lineNumber; + } + FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console(); + console.addMessage(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1); +} + +StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed) +{ + OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes; + m_allowImportRules = m_allowNamespaceDeclarations = false; + RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create(); + for (size_t i = 0; i < keyframes->size(); ++i) + rule->parserAppendKeyframe(keyframes->at(i)); + rule->setName(name); + rule->setVendorPrefixed(isPrefixed); + StyleRuleKeyframes* rulePtr = rule.get(); + m_parsedRules.append(rule.release()); + return rulePtr; +} + +static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList) +{ + if (!context.useCounter()) + return; + + for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) { + for (const CSSSelector* current = selector; current ; current = current->tagHistory()) { + UseCounter::Feature feature = UseCounter::NumberOfFeatures; + switch (current->pseudoType()) { + case CSSSelector::PseudoUnresolved: + feature = UseCounter::CSSSelectorPseudoUnresolved; + break; + case CSSSelector::PseudoShadow: + feature = UseCounter::CSSSelectorPseudoShadow; + break; + case CSSSelector::PseudoContent: + feature = UseCounter::CSSSelectorPseudoContent; + break; + case CSSSelector::PseudoHost: + feature = UseCounter::CSSSelectorPseudoHost; + break; + case CSSSelector::PseudoHostContext: + feature = UseCounter::CSSSelectorPseudoHostContext; + break; + default: + break; + } + if (feature != UseCounter::NumberOfFeatures) + context.useCounter()->count(feature); + if (current->relation() == CSSSelector::ShadowDeep) + context.useCounter()->count(UseCounter::CSSDeepCombinator); + if (current->selectorList()) + recordSelectorStats(context, *current->selectorList()); + } + } +} + +StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors) +{ + StyleRule* result = 0; + if (selectors) { + m_allowImportRules = m_allowNamespaceDeclarations = false; + RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create(); + rule->parserAdoptSelectorVector(*selectors); + rule->setProperties(createStylePropertySet()); + result = rule.get(); + m_parsedRules.append(rule.release()); + recordSelectorStats(m_context, result->selectorList()); + } + clearProperties(); + return result; +} + +StyleRuleBase* BisonCSSParser::createFontFaceRule() +{ + m_allowImportRules = m_allowNamespaceDeclarations = false; + for (unsigned i = 0; i < m_parsedProperties.size(); ++i) { + CSSProperty& property = m_parsedProperties[i]; + if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue()) + property.wrapValueInCommaSeparatedList(); + else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) { + // Unlike font-family property, font-family descriptor in @font-face rule + // has to be a value list with exactly one family name. It cannot have a + // have 'initial' value and cannot 'inherit' from parent. + // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc + clearProperties(); + return 0; + } + } + RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create(); + rule->setProperties(createStylePropertySet()); + clearProperties(); + StyleRuleFontFace* result = rule.get(); + m_parsedRules.append(rule.release()); + if (m_styleSheet) + m_styleSheet->setHasFontFaceRule(true); + return result; +} + +void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri) +{ + if (!m_styleSheet || !m_allowNamespaceDeclarations) + return; + m_allowImportRules = false; + m_styleSheet->parserAddNamespace(prefix, uri); + if (prefix.isEmpty() && !uri.isNull()) + m_defaultNamespace = uri; +} + +QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName) +{ + if (!m_styleSheet) + return QualifiedName(prefix, localName, m_defaultNamespace); + return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix)); +} + +CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers) +{ + if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes()) + return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true); + return specifiers; +} + +CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) +{ + AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace; + QualifiedName tag(namespacePrefix, elementName, determinedNamespace); + + if (specifiers->crossesTreeScopes()) + return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule); + + if (specifiers->isContentPseudoElement()) + return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule); + + // *:host never matches, so we can't discard the * otherwise we can't tell the + // difference between *:host and just :host. + if (tag == anyQName() && !specifiers->hasHostPseudoSelector()) + return specifiers; + if (specifiers->pseudoType() != CSSSelector::PseudoCue) + specifiers->prependTagSelector(tag, tagIsForNamespaceRule); + return specifiers; +} + +CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) +{ + if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement) + m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo); + + CSSParserSelector* lastShadowPseudo = specifiers; + CSSParserSelector* history = specifiers; + while (history->tagHistory()) { + history = history->tagHistory(); + if (history->crossesTreeScopes() || history->hasShadowPseudo()) + lastShadowPseudo = history; + } + + if (lastShadowPseudo->tagHistory()) { + if (tag != anyQName()) + lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule); + return specifiers; + } + + // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used. + // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). + OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag)); + lastShadowPseudo->setTagHistory(elementNameSelector.release()); + lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo); + return specifiers; +} + +CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) +{ + CSSParserSelector* last = specifiers; + CSSParserSelector* history = specifiers; + while (history->tagHistory()) { + history = history->tagHistory(); + if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent()) + last = history; + } + + if (last->tagHistory()) { + if (tag != anyQName()) + last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule); + return specifiers; + } + + // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used. + // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). + OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag)); + last->setTagHistory(elementNameSelector.release()); + last->setRelation(CSSSelector::SubSelector); + return specifiers; +} + +CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier) +{ + if (newSpecifier->crossesTreeScopes()) { + // Unknown pseudo element always goes at the top of selector chain. + newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers)); + return newSpecifier; + } + if (newSpecifier->isContentPseudoElement()) { + newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers)); + return newSpecifier; + } + if (specifiers->crossesTreeScopes()) { + // Specifiers for unknown pseudo element go right behind it in the chain. + specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo); + return specifiers; + } + if (specifiers->isContentPseudoElement()) { + specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector); + return specifiers; + } + specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier)); + return specifiers; +} + +StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector) +{ + // FIXME: Margin at-rules are ignored. + m_allowImportRules = m_allowNamespaceDeclarations = false; + StyleRulePage* pageRule = 0; + if (pageSelector) { + RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create(); + Vector<OwnPtr<CSSParserSelector> > selectorVector; + selectorVector.append(pageSelector); + rule->parserAdoptSelectorVector(selectorVector); + rule->setProperties(createStylePropertySet()); + pageRule = rule.get(); + m_parsedRules.append(rule.release()); + } + clearProperties(); + return pageRule; +} + +StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */) +{ + // FIXME: Implement margin at-rule here, using: + // - marginBox: margin box + // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule. + // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid. + + endDeclarationsForMarginBox(); + return 0; // until this method is implemented. +} + +void BisonCSSParser::startDeclarationsForMarginBox() +{ + m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size(); +} + +void BisonCSSParser::endDeclarationsForMarginBox() +{ + rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox); + m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; +} + +StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys) +{ + OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys); + if (keyVector->isEmpty()) + return 0; + + RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create(); + keyframe->setKeys(keyVector.release()); + keyframe->setProperties(createStylePropertySet()); + + clearProperties(); + + StyleKeyframe* keyframePtr = keyframe.get(); + m_parsedKeyframes.append(keyframe.release()); + return keyframePtr; +} + +void BisonCSSParser::invalidBlockHit() +{ + if (m_styleSheet && !m_hadSyntacticallyValidCSSRule) + m_styleSheet->setHasSyntacticallyValidCSSHeader(false); +} + +void BisonCSSParser::startRule() +{ + if (!m_observer) + return; + + ASSERT(m_ruleHasHeader); + m_ruleHasHeader = false; +} + +void BisonCSSParser::endRule(bool valid) +{ + if (!m_observer) + return; + + if (m_ruleHasHeader) + m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid); + m_ruleHasHeader = true; +} + +void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType) +{ + resumeErrorLogging(); + m_ruleHeaderType = ruleType; + m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset(); + m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber; + if (m_observer) { + ASSERT(!m_ruleHasHeader); + m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset); + m_ruleHasHeader = true; + } +} + +void BisonCSSParser::endRuleHeader() +{ + ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE); + m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE; + if (m_observer) { + ASSERT(m_ruleHasHeader); + m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset()); + } +} + +void BisonCSSParser::startSelector() +{ + if (m_observer) + m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset()); +} + +void BisonCSSParser::endSelector() +{ + if (m_observer) + m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset()); +} + +void BisonCSSParser::startRuleBody() +{ + if (m_observer) + m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset()); +} + +void BisonCSSParser::startProperty() +{ + resumeErrorLogging(); + if (m_observer) + m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset()); +} + +void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType) +{ + m_id = CSSPropertyInvalid; + if (m_observer) + m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType); +} + +void BisonCSSParser::startEndUnknownRule() +{ + if (m_observer) + m_observer->startEndUnknownRule(); +} + +StyleRuleBase* BisonCSSParser::createViewportRule() +{ + // Allow @viewport rules from UA stylesheets even if the feature is disabled. + if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode())) + return 0; + + m_allowImportRules = m_allowNamespaceDeclarations = false; + + RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); + + rule->setProperties(createStylePropertySet()); + clearProperties(); + + StyleRuleViewport* result = rule.get(); + m_parsedRules.append(rule.release()); + + return result; +} + +} diff --git a/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser.h b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser.h new file mode 100644 index 00000000000..e4447416394 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 BisonCSSParser_h +#define BisonCSSParser_h + +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/css/CSSCalculationValue.h" +#include "core/css/CSSFilterValue.h" +#include "core/css/CSSGradientValue.h" +#include "core/css/CSSParserMode.h" +#include "core/css/CSSParserValues.h" +#include "core/css/CSSProperty.h" +#include "core/css/CSSPropertySourceData.h" +#include "core/css/CSSSelector.h" +#include "core/css/CSSTokenizer.h" +#include "core/css/MediaQuery.h" +#include "core/css/StylePropertySet.h" +#include "core/css/parser/CSSParserObserver.h" +#include "core/css/parser/CSSPropertyParser.h" +#include "platform/graphics/Color.h" +#include "wtf/HashSet.h" +#include "wtf/OwnPtr.h" +#include "wtf/Vector.h" +#include "wtf/text/AtomicString.h" +#include "wtf/text/TextPosition.h" + +namespace WebCore { + +class AnimationParseContext; +class CSSArrayFunctionValue; +class CSSBorderImageSliceValue; +class CSSPrimitiveValue; +class CSSSelectorList; +class CSSValue; +class CSSValueList; +class CSSBasicShape; +class CSSBasicShapeInset; +class Document; +class Element; +class ImmutableStylePropertySet; +class MediaQueryExp; +class MediaQuerySet; +class MutableStylePropertySet; +class StyleKeyframe; +class StylePropertyShorthand; +class StyleRuleBase; +class StyleRuleKeyframes; +class StyleKeyframe; +class StyleSheetContents; +class UseCounter; + +// FIXME: This class is shared with CSSTokenizer so should we rename it to CSSSourceLocation? +struct CSSParserLocation { + unsigned offset; + unsigned lineNumber; + CSSParserString token; +}; + +class BisonCSSParser { + STACK_ALLOCATED(); + friend inline int cssyylex(void*, BisonCSSParser*); +public: + explicit BisonCSSParser(const CSSParserContext&); + ~BisonCSSParser(); + + void rollbackLastProperties(int num); + void setCurrentProperty(CSSPropertyID); + + void parseSheet(StyleSheetContents*, const String&, const TextPosition& startPosition = TextPosition::minimumPosition(), CSSParserObserver* = 0, bool = false); + PassRefPtrWillBeRawPtr<StyleRuleBase> parseRule(StyleSheetContents*, const String&); + PassRefPtrWillBeRawPtr<StyleKeyframe> parseKeyframeRule(StyleSheetContents*, const String&); + bool parseSupportsCondition(const String&); + static bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, CSSParserMode, StyleSheetContents*); + static bool parseColor(RGBA32& color, const String&, bool strict = false); + static bool parseSystemColor(RGBA32& color, const String&); + static PassRefPtrWillBeRawPtr<CSSValueList> parseFontFaceValue(const AtomicString&); + static PassRefPtrWillBeRawPtr<CSSValue> parseAnimationTimingFunctionValue(const String&); + bool parseDeclaration(MutableStylePropertySet*, const String&, CSSParserObserver*, StyleSheetContents* contextStyleSheet); + static PassRefPtr<ImmutableStylePropertySet> parseInlineStyleDeclaration(const String&, Element*); + PassRefPtrWillBeRawPtr<MediaQuerySet> parseMediaQueryList(const String&); + PassOwnPtr<Vector<double> > parseKeyframeKeyList(const String&); + + static bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, const Document&); + + bool parseValue(CSSPropertyID, bool important); + void parseSelector(const String&, CSSSelectorList&); + + CSSParserSelector* createFloatingSelector(); + CSSParserSelector* createFloatingSelectorWithTagName(const QualifiedName&); + PassOwnPtr<CSSParserSelector> sinkFloatingSelector(CSSParserSelector*); + + Vector<OwnPtr<CSSParserSelector> >* createFloatingSelectorVector(); + PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >*); + + CSSParserValueList* createFloatingValueList(); + PassOwnPtr<CSSParserValueList> sinkFloatingValueList(CSSParserValueList*); + + CSSParserFunction* createFloatingFunction(); + CSSParserFunction* createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args); + PassOwnPtr<CSSParserFunction> sinkFloatingFunction(CSSParserFunction*); + + CSSParserValue& sinkFloatingValue(CSSParserValue&); + + MediaQuerySet* createMediaQuerySet(); + StyleRuleBase* createImportRule(const CSSParserString&, MediaQuerySet*); + StyleKeyframe* createKeyframe(CSSParserValueList*); + StyleRuleKeyframes* createKeyframesRule(const String&, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > >, bool isPrefixed); + + typedef WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> > RuleList; + StyleRuleBase* createMediaRule(MediaQuerySet*, RuleList*); + RuleList* createRuleList(); + RuleList* appendRule(RuleList*, StyleRuleBase*); + StyleRuleBase* createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors); + StyleRuleBase* createFontFaceRule(); + StyleRuleBase* createPageRule(PassOwnPtr<CSSParserSelector> pageSelector); + StyleRuleBase* createMarginAtRule(CSSSelector::MarginBoxType); + StyleRuleBase* createSupportsRule(bool conditionIsSupported, RuleList*); + void markSupportsRuleHeaderStart(); + void markSupportsRuleHeaderEnd(); + PassRefPtrWillBeRawPtr<CSSRuleSourceData> popSupportsRuleData(); + StyleRuleBase* createHostRule(RuleList* rules); + + void startDeclarationsForMarginBox(); + void endDeclarationsForMarginBox(); + + MediaQueryExp* createFloatingMediaQueryExp(const AtomicString&, CSSParserValueList*); + PassOwnPtrWillBeRawPtr<MediaQueryExp> sinkFloatingMediaQueryExp(MediaQueryExp*); + WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* createFloatingMediaQueryExpList(); + PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >*); + MediaQuery* createFloatingMediaQuery(MediaQuery::Restrictor, const AtomicString&, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > >); + MediaQuery* createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > >); + MediaQuery* createFloatingNotAllQuery(); + PassOwnPtrWillBeRawPtr<MediaQuery> sinkFloatingMediaQuery(MediaQuery*); + + WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* createFloatingKeyframeVector(); + PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >*); + + void addNamespace(const AtomicString& prefix, const AtomicString& uri); + QualifiedName determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName); + + CSSParserSelector* rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector*, bool isNamespacePlaceholder = false); + CSSParserSelector* rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule); + CSSParserSelector* rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule); + CSSParserSelector* rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector*); + CSSParserSelector* rewriteSpecifiers(CSSParserSelector*, CSSParserSelector*); + CSSParserSelector* rewriteSpecifiersForShadowDistributed(CSSParserSelector* specifiers, CSSParserSelector* distributedPseudoElementSelector); + + void invalidBlockHit(); + + Vector<OwnPtr<CSSParserSelector> >* reusableSelectorVector() { return &m_reusableSelectorVector; } + + void clearProperties(); + + PassRefPtr<ImmutableStylePropertySet> createStylePropertySet(); + + CSSParserContext m_context; + + bool m_important; + CSSPropertyID m_id; + RawPtrWillBeMember<StyleSheetContents> m_styleSheet; + RefPtrWillBeMember<StyleRuleBase> m_rule; + RefPtrWillBeMember<StyleKeyframe> m_keyframe; + RefPtrWillBeMember<MediaQuerySet> m_mediaList; + OwnPtr<CSSParserValueList> m_valueList; + bool m_supportsCondition; + + WillBeHeapVector<CSSProperty, 256> m_parsedProperties; + CSSSelectorList* m_selectorListForParseSelector; + + unsigned m_numParsedPropertiesBeforeMarginBox; + + bool m_hadSyntacticallyValidCSSRule; + bool m_logErrors; + bool m_ignoreErrors; + + AtomicString m_defaultNamespace; + + // tokenizer methods and data + CSSParserObserver* m_observer; + + // Local functions which just call into CSSParserObserver if non-null. + void startRule(); + void endRule(bool valid); + void startRuleHeader(CSSRuleSourceData::Type); + void endRuleHeader(); + void startSelector(); + void endSelector(); + void startRuleBody(); + void startProperty(); + void endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError = NoCSSError); + void startEndUnknownRule(); + + void endInvalidRuleHeader(); + void reportError(const CSSParserLocation&, CSSParserError = GeneralCSSError); + void resumeErrorLogging() { m_ignoreErrors = false; } + void setLocationLabel(const CSSParserLocation& location) { m_locationLabel = location; } + const CSSParserLocation& lastLocationLabel() const { return m_locationLabel; } + + void tokenToLowerCase(CSSParserString& token); + + void markViewportRuleBodyStart() { m_inViewport = true; } + void markViewportRuleBodyEnd() { m_inViewport = false; } + StyleRuleBase* createViewportRule(); + + CSSParserLocation currentLocation() { return m_tokenizer.currentLocation(); } + +private: + class StyleDeclarationScope { + STACK_ALLOCATED(); + WTF_MAKE_NONCOPYABLE(StyleDeclarationScope); + public: + StyleDeclarationScope(BisonCSSParser* parser, const StylePropertySet* declaration) + : m_parser(parser) + , m_mode(declaration->cssParserMode()) + { + if (isCSSViewportParsingEnabledForMode(m_mode)) { + ASSERT(!m_parser->inViewport()); + m_parser->markViewportRuleBodyStart(); + } + } + + ~StyleDeclarationScope() + { + if (isCSSViewportParsingEnabledForMode(m_mode)) + m_parser->markViewportRuleBodyEnd(); + } + + private: + BisonCSSParser* m_parser; + CSSParserMode m_mode; + }; + + inline void ensureLineEndings(); + + void setStyleSheet(StyleSheetContents* styleSheet) { m_styleSheet = styleSheet; } + + bool inViewport() const { return m_inViewport; } + + void recheckAtKeyword(const UChar* str, int len); + + template<unsigned prefixLength, unsigned suffixLength> + inline void setupParser(const char (&prefix)[prefixLength], const String& string, const char (&suffix)[suffixLength]) + { + setupParser(prefix, prefixLength - 1, string, suffix, suffixLength - 1); + } + void setupParser(const char* prefix, unsigned prefixLength, const String&, const char* suffix, unsigned suffixLength); + + bool parseValue(MutableStylePropertySet*, CSSPropertyID, const String&, bool important, StyleSheetContents* contextStyleSheet); + PassRefPtr<ImmutableStylePropertySet> parseDeclaration(const String&, StyleSheetContents* contextStyleSheet); + + bool parseColor(const String&); + + const String* m_source; + TextPosition m_startPosition; + CSSRuleSourceData::Type m_ruleHeaderType; + unsigned m_ruleHeaderStartOffset; + int m_ruleHeaderStartLineNumber; + OwnPtr<Vector<unsigned> > m_lineEndings; + + bool m_ruleHasHeader; + + bool m_allowImportRules; + bool m_allowNamespaceDeclarations; + + bool m_inViewport; + + CSSParserLocation m_locationLabel; + + WillBeHeapVector<RefPtrWillBeMember<StyleRuleBase> > m_parsedRules; + WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > m_parsedKeyframes; + WillBeHeapVector<RefPtrWillBeMember<MediaQuerySet> > m_parsedMediaQuerySets; + WillBeHeapVector<OwnPtrWillBeMember<RuleList> > m_parsedRuleLists; + Vector<CSSParserSelector*> m_floatingSelectors; + Vector<Vector<OwnPtr<CSSParserSelector> >*> m_floatingSelectorVectors; + Vector<CSSParserValueList*> m_floatingValueLists; + Vector<CSSParserFunction*> m_floatingFunctions; + + OwnPtrWillBeMember<MediaQuery> m_floatingMediaQuery; + OwnPtrWillBeMember<MediaQueryExp> m_floatingMediaQueryExp; + OwnPtrWillBeMember<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > m_floatingMediaQueryExpList; + + OwnPtrWillBeMember<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > m_floatingKeyframeVector; + + Vector<OwnPtr<CSSParserSelector> > m_reusableSelectorVector; + + OwnPtrWillBeMember<RuleSourceDataList> m_supportsRuleDataStack; + + bool isLoggingErrors(); + void logError(const String& message, const CSSParserLocation&); + + CSSTokenizer m_tokenizer; + + friend class TransformOperationInfo; + friend class FilterOperationInfo; +}; + +inline int cssyylex(void* yylval, BisonCSSParser* parser) +{ + return parser->m_tokenizer.lex(yylval); +} + +bool isValidNthToken(const CSSParserString&); + +} // namespace WebCore + +#endif // BisonCSSParser_h diff --git a/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParserTest.cpp b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParserTest.cpp new file mode 100644 index 00000000000..f2e2f36e11f --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParserTest.cpp @@ -0,0 +1,67 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/BisonCSSParser.h" + +#include "core/css/CSSTimingFunctionValue.h" +#include "platform/animation/TimingFunction.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +TEST(BisonCSSParserTest, ParseAnimationTimingFunctionValue) +{ + RefPtrWillBeRawPtr<CSSValue> timingFunctionValue; + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("ease"); + EXPECT_EQ(CSSValueEase, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("linear"); + EXPECT_EQ(CSSValueLinear, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("ease-in"); + EXPECT_EQ(CSSValueEaseIn, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("ease-out"); + EXPECT_EQ(CSSValueEaseOut, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("ease-in-out"); + EXPECT_EQ(CSSValueEaseInOut, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("step-start"); + EXPECT_EQ(CSSValueStepStart, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("step-middle"); + EXPECT_EQ(CSSValueStepMiddle, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("step-end"); + EXPECT_EQ(CSSValueStepEnd, toCSSPrimitiveValue(timingFunctionValue.get())->getValueID()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("steps(3, start)"); + EXPECT_TRUE(CSSStepsTimingFunctionValue::create(3, StepsTimingFunction::StepAtStart)->equals(toCSSStepsTimingFunctionValue(*timingFunctionValue.get()))); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("steps(3, middle)"); + EXPECT_TRUE(CSSStepsTimingFunctionValue::create(3, StepsTimingFunction::StepAtMiddle)->equals(toCSSStepsTimingFunctionValue(*timingFunctionValue.get()))); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("steps(3, end)"); + EXPECT_TRUE(CSSStepsTimingFunctionValue::create(3, StepsTimingFunction::StepAtEnd)->equals(toCSSStepsTimingFunctionValue(*timingFunctionValue.get()))); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("steps(3, nowhere)"); + EXPECT_EQ(0, timingFunctionValue.get()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("steps(-3, end)"); + EXPECT_EQ(0, timingFunctionValue.get()); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("steps(3)"); + EXPECT_TRUE(CSSStepsTimingFunctionValue::create(3, StepsTimingFunction::StepAtEnd)->equals(toCSSStepsTimingFunctionValue(*timingFunctionValue.get()))); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("cubic-bezier(0.1, 5, 0.23, 0)"); + EXPECT_TRUE(CSSCubicBezierTimingFunctionValue::create(0.1, 5, 0.23, 0)->equals(toCSSCubicBezierTimingFunctionValue(*timingFunctionValue.get()))); + + timingFunctionValue = BisonCSSParser::parseAnimationTimingFunctionValue("cubic-bezier(0.1, 0, 4, 0.4)"); + EXPECT_EQ(0, timingFunctionValue.get()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMapForEachCallback.idl b/chromium/third_party/WebKit/Source/core/css/parser/CSSParserIdioms.h index 11a6cfcb581..4217d0a4368 100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSVariablesMapForEachCallback.idl +++ b/chromium/third_party/WebKit/Source/core/css/parser/CSSParserIdioms.h @@ -11,6 +11,9 @@ * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -25,7 +28,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -callback interface CSSVariablesMapForEachCallback { - [CallWith=ThisValue] void handleItem(DOMString value, DOMString name, CSSVariablesMap map); - void handleItem(DOMString value, DOMString name, CSSVariablesMap map); -}; +#ifndef CSSParserIdioms_h +#define CSSParserIdioms_h + +#include "wtf/unicode/Unicode.h" + +namespace WebCore { + +// Space characters as defined by the CSS specification. +// http://www.w3.org/TR/css3-syntax/#whitespace +inline bool isCSSSpace(UChar c) +{ + return c == ' ' || c == '\t' || c == '\n'; +} + +} + +#endif diff --git a/chromium/third_party/WebKit/Source/core/css/parser/CSSParserObserver.h b/chromium/third_party/WebKit/Source/core/css/parser/CSSParserObserver.h new file mode 100644 index 00000000000..c6711a4eab2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/CSSParserObserver.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 CSSParserObserver_h +#define CSSParserObserver_h + +#include "core/css/CSSPropertySourceData.h" + +namespace WebCore { + +// FIXME: Although the parser produces these, they're all ignored! +enum CSSParserError { + NoCSSError, + PropertyDeclarationCSSError, + InvalidPropertyValueCSSError, + InvalidPropertyCSSError, + InvalidSelectorCSSError, + InvalidSupportsConditionCSSError, + InvalidRuleCSSError, + InvalidMediaQueryCSSError, + InvalidKeyframeSelectorCSSError, + InvalidSelectorPseudoCSSError, + UnterminatedCommentCSSError, + GeneralCSSError +}; + +// FIXME: What are these actually used for? There is probably +// a better way for the parser to communicate this information +// to the Inspector. + +// This only implemented by StyleSheetHandler in InspectorStyleSheet.cpp. +class CSSParserObserver { + STACK_ALLOCATED(); +public: + virtual void startRuleHeader(CSSRuleSourceData::Type, unsigned offset) = 0; + virtual void endRuleHeader(unsigned offset) = 0; + virtual void startSelector(unsigned offset) = 0; + virtual void endSelector(unsigned offset) = 0; + virtual void startRuleBody(unsigned offset) = 0; + virtual void endRuleBody(unsigned offset, bool error) = 0; + virtual void startEndUnknownRule() = 0; + virtual void startProperty(unsigned offset) = 0; + virtual void endProperty(bool isImportant, bool isParsed, unsigned offset, CSSParserError) = 0; + virtual void startComment(unsigned offset) = 0; + virtual void endComment(unsigned offset) = 0; +}; + +} // namespace WebCore + +#endif // CSSParserObserver_h diff --git a/chromium/third_party/WebKit/Source/core/css/CSSParser-in.cpp b/chromium/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index 7b540fd7b14..5431a1a06c4 100755..100644 --- a/chromium/third_party/WebKit/Source/core/css/CSSParser-in.cpp +++ b/chromium/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp @@ -25,11 +25,11 @@ */ #include "config.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/CSSPropertyParser.h" -#include "CSSValueKeywords.h" -#include "RuntimeEnabledFeatures.h" -#include "StylePropertyShorthand.h" +// FIXME: Way too many! +#include "core/CSSValueKeywords.h" +#include "core/StylePropertyShorthand.h" #include "core/css/CSSArrayFunctionValue.h" #include "core/css/CSSAspectRatioValue.h" #include "core/css/CSSBasicShapes.h" @@ -42,7 +42,7 @@ #include "core/css/CSSFunctionValue.h" #include "core/css/CSSGradientValue.h" #include "core/css/CSSGridLineNamesValue.h" -#include "core/css/CSSGridTemplateValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" #include "core/css/CSSImageSetValue.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSInheritedValue.h" @@ -50,39 +50,30 @@ #include "core/css/CSSKeyframeRule.h" #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSLineBoxContainValue.h" -#include "core/css/CSSMixFunctionValue.h" +#include "core/css/CSSParserValues.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPropertySourceData.h" #include "core/css/CSSReflectValue.h" #include "core/css/CSSSVGDocumentValue.h" #include "core/css/CSSSelector.h" -#include "core/css/CSSShaderValue.h" #include "core/css/CSSShadowValue.h" -#include "core/css/CSSStyleSheet.h" #include "core/css/CSSTimingFunctionValue.h" #include "core/css/CSSTransformValue.h" #include "core/css/CSSUnicodeRangeValue.h" #include "core/css/CSSValueList.h" #include "core/css/CSSValuePool.h" -#include "core/css/CSSVariableValue.h" #include "core/css/Counter.h" #include "core/css/HashTools.h" -#include "core/css/MediaList.h" -#include "core/css/MediaQueryExp.h" #include "core/css/Pair.h" #include "core/css/Rect.h" -#include "core/css/StylePropertySet.h" -#include "core/css/StyleRule.h" -#include "core/css/StyleRuleImport.h" -#include "core/css/StyleSheetContents.h" -#include "core/dom/Document.h" +#include "core/css/RuntimeCSSEnabled.h" +#include "core/css/parser/CSSParserIdioms.h" #include "core/html/parser/HTMLParserIdioms.h" #include "core/inspector/InspectorInstrumentation.h" -#include "core/page/PageConsole.h" -#include "core/frame/Settings.h" #include "core/rendering/RenderTheme.h" -#include "core/svg/SVGParserUtilities.h" +#include "core/svg/SVGPaint.h" #include "platform/FloatConversion.h" +#include "platform/RuntimeEnabledFeatures.h" #include "wtf/BitArray.h" #include "wtf/HexNumber.h" #include "wtf/text/StringBuffer.h" @@ -91,21 +82,10 @@ #include "wtf/text/TextEncoding.h" #include <limits.h> -#define YYDEBUG 0 - -#if YYDEBUG > 0 -extern int cssyydebug; -#endif - -extern int cssyyparse(WebCore::CSSParser*); - -using namespace std; -using namespace WTF; - namespace WebCore { -static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX; static const double MAX_SCALE = 1000000; +static const unsigned minRepetitions = 10000; template <unsigned N> static bool equal(const CSSParserString& a, const char (&b)[N]) @@ -134,1186 +114,34 @@ static bool equalIgnoringCase(CSSParserValue* value, const char (&b)[N]) return equalIgnoringCase(value->string, b); } -static PassRefPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second, Pair::IdenticalValuesPolicy identicalValuesPolicy = Pair::DropIdenticalValues) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> first, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> second, Pair::IdenticalValuesPolicy identicalValuesPolicy = Pair::DropIdenticalValues) { return cssValuePool().createValue(Pair::create(first, second, identicalValuesPolicy)); } -class AnimationParseContext { -public: - AnimationParseContext() - : m_animationPropertyKeywordAllowed(true) - , m_firstAnimationCommitted(false) - , m_hasSeenAnimationPropertyKeyword(false) - { - } - - void commitFirstAnimation() - { - m_firstAnimationCommitted = true; - } - - bool hasCommittedFirstAnimation() const - { - return m_firstAnimationCommitted; - } - - void commitAnimationPropertyKeyword() - { - m_animationPropertyKeywordAllowed = false; - } - - bool animationPropertyKeywordAllowed() const - { - return m_animationPropertyKeywordAllowed; - } - - bool hasSeenAnimationPropertyKeyword() const - { - return m_hasSeenAnimationPropertyKeyword; - } - - void sawAnimationPropertyKeyword() - { - m_hasSeenAnimationPropertyKeyword = true; - } - -private: - bool m_animationPropertyKeywordAllowed; - bool m_firstAnimationCommitted; - bool m_hasSeenAnimationPropertyKeyword; -}; - -CSSParser::CSSParser(const CSSParserContext& context, UseCounter* counter) - : m_context(context) - , m_important(false) - , m_id(CSSPropertyInvalid) - , m_styleSheet(0) - , m_supportsCondition(false) - , m_selectorListForParseSelector(0) - , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES) +CSSPropertyParser::CSSPropertyParser(OwnPtr<CSSParserValueList>& valueList, + const CSSParserContext& context, bool inViewport, bool savedImportant, + WillBeHeapVector<CSSProperty, 256>& parsedProperties, + CSSRuleSourceData::Type ruleType) + : m_valueList(valueList) + , m_context(context) + , m_inViewport(inViewport) + , m_important(savedImportant) // See comment in header, should be removed. + , m_parsedProperties(parsedProperties) + , m_ruleType(ruleType) , m_inParseShorthand(0) , m_currentShorthand(CSSPropertyInvalid) , m_implicitShorthand(false) - , m_hasFontFaceOnlyValues(false) - , m_hadSyntacticallyValidCSSRule(false) - , m_logErrors(false) - , m_ignoreErrors(false) - , m_inFilterRule(false) - , m_defaultNamespace(starAtom) - , m_sourceDataHandler(0) - , m_source(0) - , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE) - , m_allowImportRules(true) - , m_allowNamespaceDeclarations(true) - , m_inViewport(false) - , m_useCounter(counter) - , m_tokenizer(*this) -{ -#if YYDEBUG > 0 - cssyydebug = 1; -#endif - CSSPropertySourceData::init(); -} - -CSSParser::~CSSParser() -{ - clearProperties(); - - deleteAllValues(m_floatingSelectors); - deleteAllValues(m_floatingSelectorVectors); - deleteAllValues(m_floatingValueLists); - deleteAllValues(m_floatingFunctions); -} - -void CSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength) -{ - m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength); - m_ruleHasHeader = true; -} - -void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, SourceDataHandler* sourceDataHandler, bool logErrors) -{ - setStyleSheet(sheet); - m_defaultNamespace = starAtom; // Reset the default namespace. - m_sourceDataHandler = sourceDataHandler; - m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->page(); - m_ignoreErrors = false; - m_tokenizer.m_lineNumber = 0; - m_startPosition = startPosition; - m_source = &string; - m_tokenizer.m_internal = false; - setupParser("", string, ""); - cssyyparse(this); - sheet->shrinkToFit(); - m_source = 0; - m_sourceDataHandler = 0; - m_rule = 0; - m_lineEndings.clear(); - m_ignoreErrors = false; - m_logErrors = false; - m_tokenizer.m_internal = true; -} - -PassRefPtr<StyleRuleBase> CSSParser::parseRule(StyleSheetContents* sheet, const String& string) -{ - setStyleSheet(sheet); - m_allowNamespaceDeclarations = false; - setupParser("@-internal-rule ", string, ""); - cssyyparse(this); - return m_rule.release(); -} - -PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string) -{ - setStyleSheet(sheet); - setupParser("@-internal-keyframe-rule ", string, ""); - cssyyparse(this); - return m_keyframe.release(); -} - -PassOwnPtr<Vector<double> > CSSParser::parseKeyframeKeyList(const String& string) -{ - setupParser("@-internal-keyframe-key-list ", string, ""); - cssyyparse(this); - ASSERT(m_valueList); - return StyleKeyframe::createKeyList(m_valueList.get()); -} - -bool CSSParser::parseSupportsCondition(const String& string) -{ - m_supportsCondition = false; - setupParser("@-internal-supports-condition ", string, ""); - cssyyparse(this); - return m_supportsCondition; -} - -static inline bool isColorPropertyID(CSSPropertyID 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; - case CSSPropertyTextDecorationColor: - return RuntimeEnabledFeatures::css3TextDecorationsEnabled(); - default: - return false; - } -} - -static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode) -{ - ASSERT(!string.isEmpty()); - bool quirksMode = isQuirksModeBehavior(cssParserMode); - if (!isColorPropertyID(propertyId)) - return false; - CSSParserString cssString; - cssString.init(string); - CSSValueID 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 - || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) { - validPrimitive = true; - } - - if (validPrimitive) { - RefPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID); - declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); - return true; - } - RGBA32 color; - if (!CSSParser::fastParseColor(color, string, !quirksMode && string[0] != '#')) - return false; - RefPtr<CSSValue> value = cssValuePool().createColorValue(color); - declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); - return true; -} - -static inline bool isSimpleLengthPropertyID(CSSPropertyID 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 CSSPropertyShapeMargin: - case CSSPropertyShapePadding: - acceptsNegativeNumbers = false; - return RuntimeEnabledFeatures::cssShapesEnabled(); - case CSSPropertyBottom: - case CSSPropertyLeft: - case CSSPropertyMarginBottom: - case CSSPropertyMarginLeft: - case CSSPropertyMarginRight: - case CSSPropertyMarginTop: - case CSSPropertyRight: - case CSSPropertyTop: - case CSSPropertyWebkitMarginAfter: - case CSSPropertyWebkitMarginBefore: - case CSSPropertyWebkitMarginEnd: - case CSSPropertyWebkitMarginStart: - acceptsNegativeNumbers = true; - return true; - default: - return false; - } -} - -template <typename CharacterType> -static inline bool parseSimpleLength(const CharacterType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number) -{ - if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == '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; - number = charactersToDouble(characters, length, &ok); - return ok; -} - -static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode) -{ - ASSERT(!string.isEmpty()); - bool acceptsNegativeNumbers; - - // In @viewport, width and height are shorthands, not simple length values. - if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers)) - return false; - - unsigned length = string.length(); - double number; - CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; - - if (string.is8Bit()) { - if (!parseSimpleLength(string.characters8(), length, unit, number)) - return false; - } else { - if (!parseSimpleLength(string.characters16(), length, unit, number)) - return false; - } - - if (unit == CSSPrimitiveValue::CSS_NUMBER) { - bool quirksMode = isQuirksModeBehavior(cssParserMode); - if (number && !quirksMode) - return false; - unit = CSSPrimitiveValue::CSS_PX; - } - if (number < 0 && !acceptsNegativeNumbers) - return false; - - RefPtr<CSSValue> value = cssValuePool().createValue(number, unit); - declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); - return true; -} - -static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext) -{ - if (!valueID) - return false; - - switch (propertyId) { - case CSSPropertyBorderCollapse: // collapse | separate | inherit - if (valueID == CSSValueCollapse || valueID == CSSValueSeparate) - return true; - break; - case CSSPropertyBorderTopStyle: // <border-style> | inherit - case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed | - case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset - case CSSPropertyBorderLeftStyle: - case CSSPropertyWebkitBorderAfterStyle: - case CSSPropertyWebkitBorderBeforeStyle: - case CSSPropertyWebkitBorderEndStyle: - case CSSPropertyWebkitBorderStartStyle: - case CSSPropertyWebkitColumnRuleStyle: - if (valueID >= CSSValueNone && valueID <= CSSValueDouble) - return true; - break; - case CSSPropertyBoxSizing: - if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox) - return true; - break; - case CSSPropertyCaptionSide: // top | bottom | left | right | inherit - if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom) - return true; - break; - case CSSPropertyClear: // none | left | right | both | inherit - if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth) - return true; - break; - case CSSPropertyDirection: // ltr | rtl | inherit - if (valueID == CSSValueLtr || valueID == CSSValueRtl) - return true; - break; - case CSSPropertyDisplay: - // inline | block | list-item | inline-block | table | - // inline-table | table-row-group | table-header-group | table-footer-group | table-row | - // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit - // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid | lazy-block - if ((valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone) - return true; - if (valueID == CSSValueGrid || valueID == CSSValueInlineGrid) - return RuntimeEnabledFeatures::cssGridLayoutEnabled(); - break; - - case CSSPropertyEmptyCells: // show | hide | inherit - if (valueID == CSSValueShow || valueID == CSSValueHide) - return true; - break; - case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none) - if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter) - return true; - break; - case CSSPropertyFontStyle: // normal | italic | oblique | inherit - if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique) - return true; - break; - case CSSPropertyImageRendering: // auto | optimizeContrast - if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast) - return true; - break; - case CSSPropertyIsolation: // auto | isolate - if (valueID == CSSValueAuto || valueID == CSSValueIsolate) - return RuntimeEnabledFeatures::cssCompositingEnabled(); - break; - case CSSPropertyListStylePosition: // inside | outside | inherit - if (valueID == CSSValueInside || valueID == CSSValueOutside) - return true; - break; - case CSSPropertyListStyleType: - // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in - // for the list of supported list-style-types. - if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone) - return true; - break; - case CSSPropertyObjectFit: - if (RuntimeEnabledFeatures::objectFitPositionEnabled()) { - if (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown) - return true; - } - break; - case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit - if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble)) - return true; - break; - case CSSPropertyOverflowWrap: // normal | break-word - case CSSPropertyWordWrap: - if (valueID == CSSValueNormal || valueID == CSSValueBreakWord) - return true; - break; - case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay | inherit - if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay) - return true; - break; - case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | inherit | -webkit-paged-x | -webkit-paged-y - if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY) - return true; - break; - case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit - case CSSPropertyPageBreakBefore: - case CSSPropertyWebkitColumnBreakAfter: - case CSSPropertyWebkitColumnBreakBefore: - if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight) - return true; - break; - case CSSPropertyPageBreakInside: // avoid | auto | inherit - case CSSPropertyWebkitColumnBreakInside: - if (valueID == CSSValueAuto || valueID == CSSValueAvoid) - return true; - break; - case CSSPropertyPointerEvents: - // none | visiblePainted | visibleFill | visibleStroke | visible | - // painted | fill | stroke | auto | all | bounding-box | inherit - if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox)) - return true; - break; - case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit - if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed - || (RuntimeEnabledFeatures::cssStickyPositionEnabled() && valueID == CSSValueSticky)) - return true; - break; - case CSSPropertyResize: // none | both | horizontal | vertical | auto - if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto) - return true; - break; - case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit - if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation) - return true; - break; - case CSSPropertyTableLayout: // auto | fixed | inherit - if (valueID == CSSValueAuto || valueID == CSSValueFixed) - return true; - break; - case CSSPropertyTextAlignLast: - // auto | start | end | left | right | center | justify - if (RuntimeEnabledFeatures::css3TextEnabled() - && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto)) - return true; - break; - case CSSPropertyTextJustify: - // auto | none | inter-word | distribute - if (RuntimeEnabledFeatures::css3TextEnabled() - && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone)) - return true; - break; - case CSSPropertyTextLineThroughMode: - case CSSPropertyTextOverlineMode: - case CSSPropertyTextUnderlineMode: - if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace) - return true; - break; - case CSSPropertyTextLineThroughStyle: - case CSSPropertyTextOverlineStyle: - case CSSPropertyTextUnderlineStyle: - if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave) - return true; - break; - case CSSPropertyTextOverflow: // clip | ellipsis - if (valueID == CSSValueClip || valueID == CSSValueEllipsis) - return true; - break; - case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision - if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision) - return true; - break; - case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit - if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone) - return true; - break; - case CSSPropertyTouchActionDelay: // none | script - if (RuntimeEnabledFeatures::cssTouchActionEnabled() && (valueID == CSSValueScript || valueID == CSSValueNone)) - return true; - break; - case CSSPropertyVisibility: // visible | hidden | collapse | inherit - if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse) - return true; - break; - case CSSPropertyWebkitAppearance: - if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone) - return true; - break; - case CSSPropertyWebkitBackfaceVisibility: - if (valueID == CSSValueVisible || valueID == CSSValueHidden) - return true; - break; - case CSSPropertyMixBlendMode: - if (RuntimeEnabledFeatures::cssCompositingEnabled() && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen - || valueID == CSSValueOverlay || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge - || valueID == CSSValueColorBurn || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference - || valueID == CSSValueExclusion || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor - || valueID == CSSValueLuminosity)) - return true; - break; - case CSSPropertyWebkitBorderFit: - if (valueID == CSSValueBorder || valueID == CSSValueLines) - return true; - break; - case CSSPropertyWebkitBoxAlign: - if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline) - return true; - break; - case CSSPropertyWebkitBoxDecorationBreak: - if (valueID == CSSValueClone || valueID == CSSValueSlice) - return true; - break; - case CSSPropertyWebkitBoxDirection: - if (valueID == CSSValueNormal || valueID == CSSValueReverse) - return true; - break; - case CSSPropertyWebkitBoxLines: - if (valueID == CSSValueSingle || valueID == CSSValueMultiple) - return true; - break; - case CSSPropertyWebkitBoxOrient: - if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis) - return true; - break; - case CSSPropertyWebkitBoxPack: - if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify) - return true; - break; - case CSSPropertyInternalCallback: - // This property is only injected programmatically, not parsed from stylesheets. - return false; - case CSSPropertyColumnFill: - if (RuntimeEnabledFeatures::regionBasedColumnsEnabled()) { - if (valueID == CSSValueAuto || valueID == CSSValueBalance) - return true; - } - break; - case CSSPropertyAlignContent: - if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch) - return true; - break; - case CSSPropertyAlignItems: - if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) - return true; - break; - case CSSPropertyAlignSelf: - if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) - return true; - break; - case CSSPropertyFlexDirection: - if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse) - return true; - break; - case CSSPropertyFlexWrap: - if (valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse) - return true; - break; - case CSSPropertyJustifyContent: - if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround) - return true; - break; - case CSSPropertyFontKerning: - if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone) - return true; - break; - case CSSPropertyWebkitFontSmoothing: - if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased) - return true; - break; - case CSSPropertyGridAutoFlow: - if (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn) - return RuntimeEnabledFeatures::cssGridLayoutEnabled(); - break; - case CSSPropertyWebkitLineAlign: - if (valueID == CSSValueNone || valueID == CSSValueEdges) - return true; - break; - case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space - if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace) - return true; - break; - case CSSPropertyWebkitLineSnap: - if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain) - return true; - break; - case CSSPropertyWebkitMarginAfterCollapse: - case CSSPropertyWebkitMarginBeforeCollapse: - case CSSPropertyWebkitMarginBottomCollapse: - case CSSPropertyWebkitMarginTopCollapse: - if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard) - return true; - break; - case CSSPropertyInternalMarqueeDirection: - if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown - || valueID == CSSValueUp || valueID == CSSValueAuto) - return true; - break; - case CSSPropertyInternalMarqueeStyle: - if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate) - return true; - break; - case CSSPropertyWebkitPrintColorAdjust: - if (valueID == CSSValueExact || valueID == CSSValueEconomy) - return true; - break; - case CSSPropertyWebkitRegionBreakAfter: - case CSSPropertyWebkitRegionBreakBefore: - if (RuntimeEnabledFeatures::cssRegionsEnabled() && (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)) - return true; - break; - case CSSPropertyWebkitRegionBreakInside: - if (RuntimeEnabledFeatures::cssRegionsEnabled() && (valueID == CSSValueAuto || valueID == CSSValueAvoid)) - return true; - break; - case CSSPropertyWebkitRegionFragment: - if (RuntimeEnabledFeatures::cssRegionsEnabled() && (valueID == CSSValueAuto || valueID == CSSValueBreak)) - return true; - break; - case CSSPropertyWebkitRtlOrdering: - if (valueID == CSSValueLogical || valueID == CSSValueVisual) - return true; - break; - - case CSSPropertyWebkitRubyPosition: - if (valueID == CSSValueBefore || valueID == CSSValueAfter) - return true; - break; - - case CSSPropertyWebkitTextCombine: - if (valueID == CSSValueNone || valueID == CSSValueHorizontal) - return true; - break; - case CSSPropertyWebkitTextEmphasisPosition: - if (valueID == CSSValueOver || valueID == CSSValueUnder) - return true; - break; - case CSSPropertyWebkitTextSecurity: - // disc | circle | square | none | inherit - if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone) - return true; - break; - case CSSPropertyWebkitTransformStyle: - if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d) - return true; - break; - case CSSPropertyWebkitUserDrag: // auto | none | element - if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement) - return true; - break; - case CSSPropertyWebkitUserModify: // read-only | read-write - if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly) - return true; - break; - case CSSPropertyWebkitUserSelect: // auto | none | text | all - if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll) - return true; - break; - case CSSPropertyWebkitWrapFlow: - if (!RuntimeEnabledFeatures::cssExclusionsEnabled()) - return false; - if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear) - return true; - break; - case CSSPropertyWebkitWrapThrough: - if (!RuntimeEnabledFeatures::cssExclusionsEnabled()) - return false; - if (valueID == CSSValueWrap || valueID == CSSValueNone) - return true; - break; - case CSSPropertyWebkitWritingMode: - if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt) - return true; - break; - case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit - if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap) - return true; - break; - case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension) - if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord) - return true; - break; - default: - ASSERT_NOT_REACHED(); - return false; - } - return false; -} - -static inline bool isKeywordPropertyID(CSSPropertyID propertyId) -{ - switch (propertyId) { - case CSSPropertyMixBlendMode: - case CSSPropertyIsolation: - case CSSPropertyBorderBottomStyle: - case CSSPropertyBorderCollapse: - case CSSPropertyBorderLeftStyle: - case CSSPropertyBorderRightStyle: - case CSSPropertyBorderTopStyle: - case CSSPropertyBoxSizing: - case CSSPropertyCaptionSide: - case CSSPropertyClear: - case CSSPropertyDirection: - case CSSPropertyDisplay: - case CSSPropertyEmptyCells: - case CSSPropertyFloat: - case CSSPropertyFontStyle: - case CSSPropertyImageRendering: - case CSSPropertyListStylePosition: - case CSSPropertyListStyleType: - case CSSPropertyObjectFit: - case CSSPropertyOutlineStyle: - case CSSPropertyOverflowWrap: - case CSSPropertyOverflowX: - case CSSPropertyOverflowY: - case CSSPropertyPageBreakAfter: - case CSSPropertyPageBreakBefore: - case CSSPropertyPageBreakInside: - case CSSPropertyPointerEvents: - case CSSPropertyPosition: - case CSSPropertyResize: - case CSSPropertySpeak: - case CSSPropertyTableLayout: - case CSSPropertyTextAlignLast: - case CSSPropertyTextJustify: - case CSSPropertyTextLineThroughMode: - case CSSPropertyTextLineThroughStyle: - case CSSPropertyTextOverflow: - case CSSPropertyTextOverlineMode: - case CSSPropertyTextOverlineStyle: - case CSSPropertyTextRendering: - case CSSPropertyTextTransform: - case CSSPropertyTextUnderlineMode: - case CSSPropertyTextUnderlineStyle: - case CSSPropertyTouchActionDelay: - case CSSPropertyVisibility: - case CSSPropertyWebkitAppearance: - case CSSPropertyWebkitBackfaceVisibility: - case CSSPropertyWebkitBorderAfterStyle: - case CSSPropertyWebkitBorderBeforeStyle: - case CSSPropertyWebkitBorderEndStyle: - case CSSPropertyWebkitBorderFit: - case CSSPropertyWebkitBorderStartStyle: - case CSSPropertyWebkitBoxAlign: - case CSSPropertyWebkitBoxDecorationBreak: - case CSSPropertyWebkitBoxDirection: - case CSSPropertyWebkitBoxLines: - case CSSPropertyWebkitBoxOrient: - case CSSPropertyWebkitBoxPack: - case CSSPropertyInternalCallback: - case CSSPropertyWebkitColumnBreakAfter: - case CSSPropertyWebkitColumnBreakBefore: - case CSSPropertyWebkitColumnBreakInside: - case CSSPropertyColumnFill: - case CSSPropertyWebkitColumnRuleStyle: - case CSSPropertyAlignContent: - case CSSPropertyAlignItems: - case CSSPropertyAlignSelf: - case CSSPropertyFlexDirection: - case CSSPropertyFlexWrap: - case CSSPropertyJustifyContent: - case CSSPropertyFontKerning: - case CSSPropertyWebkitFontSmoothing: - case CSSPropertyGridAutoFlow: - case CSSPropertyWebkitLineAlign: - case CSSPropertyWebkitLineBreak: - case CSSPropertyWebkitLineSnap: - case CSSPropertyWebkitMarginAfterCollapse: - case CSSPropertyWebkitMarginBeforeCollapse: - case CSSPropertyWebkitMarginBottomCollapse: - case CSSPropertyWebkitMarginTopCollapse: - case CSSPropertyInternalMarqueeDirection: - case CSSPropertyInternalMarqueeStyle: - case CSSPropertyWebkitPrintColorAdjust: - case CSSPropertyWebkitRegionBreakAfter: - case CSSPropertyWebkitRegionBreakBefore: - case CSSPropertyWebkitRegionBreakInside: - case CSSPropertyWebkitRegionFragment: - case CSSPropertyWebkitRtlOrdering: - case CSSPropertyWebkitRubyPosition: - case CSSPropertyWebkitTextCombine: - case CSSPropertyWebkitTextEmphasisPosition: - case CSSPropertyWebkitTextSecurity: - case CSSPropertyWebkitTransformStyle: - case CSSPropertyWebkitUserDrag: - case CSSPropertyWebkitUserModify: - case CSSPropertyWebkitUserSelect: - case CSSPropertyWebkitWrapFlow: - case CSSPropertyWebkitWrapThrough: - case CSSPropertyWebkitWritingMode: - case CSSPropertyWhiteSpace: - case CSSPropertyWordBreak: - case CSSPropertyWordWrap: - return true; - default: - return false; - } -} - -static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext) -{ - ASSERT(!string.isEmpty()); - - if (!isKeywordPropertyID(propertyId)) { - // All properties accept the values of "initial" and "inherit". - String lowerCaseString = string.lower(); - if (lowerCaseString != "initial" && lowerCaseString != "inherit") - return false; - - // Parse initial/inherit shorthands using the CSSParser. - if (shorthandForProperty(propertyId).length()) - return false; - } - - CSSParserString cssString; - cssString.init(string); - CSSValueID valueID = cssValueKeywordID(cssString); - - if (!valueID) - return false; - - RefPtr<CSSValue> value; - if (valueID == CSSValueInherit) - value = cssValuePool().createInheritedValue(); - else if (valueID == CSSValueInitial) - value = cssValuePool().createExplicitInitialValue(); - else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext)) - value = cssValuePool().createIdentifierValue(valueID); - else - return false; - - declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)); - return true; -} - -template <typename CharacterType> -static bool parseTransformTranslateArguments(CSSTransformValue* transformValue, CharacterType* characters, unsigned length, unsigned start, unsigned expectedCount) -{ - while (expectedCount) { - size_t end = WTF::find(characters, length, expectedCount == 1 ? ')' : ',', start); - if (end == kNotFound || (expectedCount == 1 && end != length - 1)) - return false; - unsigned argumentLength = end - start; - CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER; - double number; - if (!parseSimpleLength(characters + start, argumentLength, unit, number)) - return false; - if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER)) - return false; - transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX)); - start = end + 1; - --expectedCount; - } - return true; -} - -static bool parseTranslateTransformValue(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important) -{ - if (propertyID != CSSPropertyWebkitTransform) - return false; - static const unsigned shortestValidTransformStringLength = 12; - static const unsigned likelyMultipartTransformStringLengthCutoff = 32; - if (string.length() < shortestValidTransformStringLength || string.length() > likelyMultipartTransformStringLengthCutoff) - return false; - if (!string.startsWith("translate", false)) - return false; - UChar c9 = toASCIILower(string[9]); - UChar c10 = toASCIILower(string[10]); - - CSSTransformValue::TransformOperationType transformType; - unsigned expectedArgumentCount = 1; - unsigned argumentStart = 11; - if (c9 == 'x' && c10 == '(') - transformType = CSSTransformValue::TranslateXTransformOperation; - else if (c9 == 'y' && c10 == '(') - transformType = CSSTransformValue::TranslateYTransformOperation; - else if (c9 == 'z' && c10 == '(') - transformType = CSSTransformValue::TranslateZTransformOperation; - else if (c9 == '(') { - transformType = CSSTransformValue::TranslateTransformOperation; - expectedArgumentCount = 2; - argumentStart = 10; - } else if (c9 == '3' && c10 == 'd' && string[11] == '(') { - transformType = CSSTransformValue::Translate3DTransformOperation; - expectedArgumentCount = 3; - argumentStart = 12; - } else - return false; - - RefPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType); - bool success; - if (string.is8Bit()) - success = parseTransformTranslateArguments(transformValue.get(), string.characters8(), string.length(), argumentStart, expectedArgumentCount); - else - success = parseTransformTranslateArguments(transformValue.get(), string.characters16(), string.length(), argumentStart, expectedArgumentCount); - if (!success) - return false; - RefPtr<CSSValueList> result = CSSValueList::createSpaceSeparated(); - result->append(transformValue.release()); - properties->addParsedProperty(CSSProperty(CSSPropertyWebkitTransform, result.release(), important)); - return true; -} - -PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string) -{ - if (string.isEmpty()) - return 0; - RefPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create(); - if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0)) - return 0; - - RefPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily); - if (!fontFamily->isValueList()) - return 0; - - return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get()); -} - -bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document) -{ - ASSERT(!string.isEmpty()); - - CSSParserContext context(document); - - if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode())) - return true; - if (parseColorValue(declaration, propertyID, string, important, context.mode())) - return true; - if (parseKeywordValue(declaration, propertyID, string, important, context)) - return true; - - CSSParser parser(context, UseCounter::getFrom(&document)); - return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0)); -} - -bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet) -{ - ASSERT(!string.isEmpty()); - if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode)) - return true; - if (parseColorValue(declaration, propertyID, string, important, cssParserMode)) - return true; - - CSSParserContext context(cssParserMode); - if (contextStyleSheet) { - context = contextStyleSheet->parserContext(); - context.setMode(cssParserMode); - } - - if (parseKeywordValue(declaration, propertyID, string, important, context)) - return true; - if (parseTranslateTransformValue(declaration, propertyID, string, important)) - return true; - - CSSParser parser(context); - return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet); -} - -bool CSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet) -{ - // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty. - - if (m_useCounter) - m_useCounter->count(m_context, propertyID); - - setStyleSheet(contextStyleSheet); - - setupParser("@-internal-value ", string, ""); - - m_id = propertyID; - m_important = important; - - { - StyleDeclarationScope scope(this, declaration); - cssyyparse(this); - } - - m_rule = 0; - m_id = CSSPropertyInvalid; - - bool ok = false; - if (m_hasFontFaceOnlyValues) - deleteFontFaceOnlyValues(); - if (!m_parsedProperties.isEmpty()) { - ok = true; - declaration->addParsedProperties(m_parsedProperties); - clearProperties(); - } - - return ok; -} - -// The color will only be changed when string contains a valid CSS color, so callers -// can set it to a default color and ignore the boolean result. -bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict) -{ - // First try creating a color specified by name, rgba(), rgb() or "#" syntax. - if (fastParseColor(color, string, strict)) - return true; - - CSSParser parser(HTMLStandardMode); - - // In case the fast-path parser didn't understand the color, try the full parser. - if (!parser.parseColor(string)) - return false; - - CSSValue* value = parser.m_parsedProperties.first().value(); - if (!value->isPrimitiveValue()) - return false; - - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (!primitiveValue->isRGBColor()) - return false; - - color = primitiveValue->getRGBA32Value(); - return true; -} - -bool CSSParser::parseColor(const String& string) -{ - setupParser("@-internal-decls color:", string, ""); - cssyyparse(this); - m_rule = 0; - - return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor; -} - -bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document) -{ - if (!document || !document->page()) - return false; - - CSSParserString cssColor; - cssColor.init(string); - CSSValueID id = cssValueKeywordID(cssColor); - if (id <= 0) - return false; - - color = RenderTheme::theme().systemColor(id).rgb(); - return true; -} - -void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList) -{ - m_selectorListForParseSelector = &selectorList; - - setupParser("@-internal-selector ", string, ""); - - cssyyparse(this); - - m_selectorListForParseSelector = 0; -} - -PassRefPtr<ImmutableStylePropertySet> CSSParser::parseInlineStyleDeclaration(const String& string, Element* element) -{ - Document& document = element->document(); - CSSParserContext context = document.elementSheet()->contents()->parserContext(); - context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode); - return CSSParser(context, UseCounter::getFrom(&document)).parseDeclaration(string, document.elementSheet()->contents()); -} - -PassRefPtr<ImmutableStylePropertySet> CSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet) -{ - setStyleSheet(contextStyleSheet); - - setupParser("@-internal-decls ", string, ""); - cssyyparse(this); - m_rule = 0; - - if (m_hasFontFaceOnlyValues) - deleteFontFaceOnlyValues(); - - RefPtr<ImmutableStylePropertySet> style = createStylePropertySet(); - clearProperties(); - return style.release(); -} - - -bool CSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, SourceDataHandler* sourceDataHandler, StyleSheetContents* contextStyleSheet) -{ - setStyleSheet(contextStyleSheet); - - m_sourceDataHandler = sourceDataHandler; - - setupParser("@-internal-decls ", string, ""); - if (m_sourceDataHandler) { - m_sourceDataHandler->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0); - m_sourceDataHandler->endRuleHeader(1); - m_sourceDataHandler->startRuleBody(0); - } - - { - StyleDeclarationScope scope(this, declaration); - cssyyparse(this); - } - - m_rule = 0; - - bool ok = false; - if (m_hasFontFaceOnlyValues) - deleteFontFaceOnlyValues(); - if (!m_parsedProperties.isEmpty()) { - ok = true; - declaration->addParsedProperties(m_parsedProperties); - clearProperties(); - } - - if (m_sourceDataHandler) - m_sourceDataHandler->endRuleBody(string.length(), false); - m_sourceDataHandler = 0; - - return ok; -} - -PassRefPtr<MediaQuerySet> CSSParser::parseMediaQueryList(const String& string) { - ASSERT(!m_mediaList); - - // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token. - // instead insert one " " (which is caught by maybe_space in CSSGrammar.y) - setupParser("@-internal-medialist ", string, ""); - cssyyparse(this); - - ASSERT(m_mediaList); - return m_mediaList.release(); } -static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties, HashSet<AtomicString>& seenVariables) +CSSPropertyParser::~CSSPropertyParser() { - // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found. - for (int i = input.size() - 1; i >= 0; --i) { - const CSSProperty& property = input[i]; - if (property.isImportant() != important) - continue; - if (property.id() == CSSPropertyVariable) { - const AtomicString& name = toCSSVariableValue(property.value())->name(); - if (!seenVariables.add(name).isNewEntry) - continue; - output[--unusedEntries] = property; - continue; - } - const unsigned propertyIDIndex = property.id() - firstCSSProperty; - if (seenProperties.get(propertyIDIndex)) - continue; - seenProperties.set(propertyIDIndex); - output[--unusedEntries] = property; - } } -PassRefPtr<ImmutableStylePropertySet> CSSParser::createStylePropertySet() +void CSSPropertyParser::addPropertyWithPrefixingVariant(CSSPropertyID propId, PassRefPtrWillBeRawPtr<CSSValue> value, bool important, bool implicit) { - BitArray<numCSSProperties> seenProperties; - size_t unusedEntries = m_parsedProperties.size(); - Vector<CSSProperty, 256> results(unusedEntries); - - // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found. - HashSet<AtomicString> seenVariables; - filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables); - filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables); - if (unusedEntries) - results.remove(0, unusedEntries); - - CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode(); - - return ImmutableStylePropertySet::create(results.data(), results.size(), mode); -} - -void CSSParser::addPropertyWithPrefixingVariant(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit) -{ - RefPtr<CSSValue> val = value.get(); + RefPtrWillBeRawPtr<CSSValue> val = value.get(); addProperty(propId, value, important, implicit); CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(propId); @@ -1330,11 +158,10 @@ void CSSParser::addPropertyWithPrefixingVariant(CSSPropertyID propId, PassRefPtr } } -void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit) +void CSSPropertyParser::addProperty(CSSPropertyID propId, PassRefPtrWillBeRawPtr<CSSValue> value, bool important, bool implicit) { - CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value.get()) : 0; - // This property doesn't belong to a shorthand or is a CSS variable (which will be resolved later). - if (!m_currentShorthand || (primitiveValue && primitiveValue->isVariableName())) { + // This property doesn't belong to a shorthand. + if (!m_currentShorthand) { m_parsedProperties.append(CSSProperty(propId, value, important, false, CSSPropertyInvalid, m_implicitShorthand || implicit)); return; } @@ -1348,36 +175,19 @@ void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bo m_parsedProperties.append(CSSProperty(propId, value, important, true, indexOfShorthandForLonghand(m_currentShorthand, shorthands), m_implicitShorthand || implicit)); } -void CSSParser::rollbackLastProperties(int num) +void CSSPropertyParser::rollbackLastProperties(int num) { ASSERT(num >= 0); ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num)); m_parsedProperties.shrink(m_parsedProperties.size() - num); } -void CSSParser::clearProperties() -{ - m_parsedProperties.clear(); - m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; - m_hasFontFaceOnlyValues = false; -} - -// FIXME: Move to CSSParserContext? -KURL CSSParser::completeURL(const CSSParserContext& context, const String& url) -{ - if (url.isNull()) - return KURL(); - if (context.charset().isEmpty()) - return KURL(context.baseURL(), url); - return KURL(context.baseURL(), url, context.charset()); -} - -KURL CSSParser::completeURL(const String& url) const +KURL CSSPropertyParser::completeURL(const String& url) const { - return completeURL(m_context, url); + return m_context.completeURL(url); } -bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags, ReleaseParsedCalcValueCondition releaseCalc) +bool CSSPropertyParser::validCalculationUnit(CSSParserValue* value, Units unitflags, ReleaseParsedCalcValueCondition releaseCalc) { bool mustBeNonNegative = unitflags & FNonNeg; @@ -1407,9 +217,6 @@ bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags, Rel case CalcPercentNumber: b = (unitflags & FPercent) && (unitflags & FNumber); break; - case CalcVariable: - b = true; - break; case CalcOther: break; } @@ -1418,23 +225,19 @@ bool CSSParser::validCalculationUnit(CSSParserValue* value, Units unitflags, Rel return b; } -inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode) +inline bool CSSPropertyParser::shouldAcceptUnitLessValues(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode) { // Quirks mode and presentation attributes accept unit less values. return (unitflags & (FLength | FAngle | FTime)) && (!value->fValue || isUnitLessLengthParsingEnabledForMode(cssParserMode)); } -bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode, ReleaseParsedCalcValueCondition releaseCalc) +bool CSSPropertyParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode cssParserMode, ReleaseParsedCalcValueCondition releaseCalc) { if (isCalculation(value)) return validCalculationUnit(value, unitflags, releaseCalc); bool b = false; switch (value->unit) { - case CSSPrimitiveValue::CSS_VARIABLE_NAME: - // Variables are checked at the point they are dereferenced because unit type is not available here. - b = true; - break; case CSSPrimitiveValue::CSS_NUMBER: b = (unitflags & FNumber); if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) { @@ -1493,11 +296,8 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode return b; } -inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::createPrimitiveNumericValue(CSSParserValue* value) { - if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME) - return createPrimitiveVariableNameValue(value); - if (m_parsedCalculation) { ASSERT(isCalculation(value)); return CSSPrimitiveValue::create(m_parsedCalculation.release()); @@ -1507,19 +307,20 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSP || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_CHS) || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMAX) || (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM)); - return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); + return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitType>(value->unit)); } -inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue* value) +inline PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::createPrimitiveStringValue(CSSParserValue* value) { ASSERT(value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT); return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING); } -inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveVariableNameValue(CSSParserValue* value) +inline PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::createCSSImageValueWithReferrer(const String& rawValue, const KURL& url) { - ASSERT(value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME); - return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME); + RefPtrWillBeRawPtr<CSSValue> imageValue = CSSImageValue::create(rawValue, url); + toCSSImageValue(imageValue.get())->setReferrer(m_context.referrer()); + return imageValue; } static inline bool isComma(CSSParserValue* value) @@ -1551,7 +352,7 @@ static bool isGeneratedImageValue(CSSParserValue* val) || equalIgnoringCase(val->function->name, "-webkit-cross-fade("); } -bool CSSParser::validWidthOrHeight(CSSParserValue* value) +bool CSSPropertyParser::validWidthOrHeight(CSSParserValue* value) { int id = value->id; if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic || id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent || id == CSSValueWebkitFillAvailable || id == CSSValueWebkitFitContent) @@ -1559,7 +360,7 @@ bool CSSParser::validWidthOrHeight(CSSParserValue* value) return !id && validUnit(value, FLength | FPercent | FNonNeg); } -inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(CSSValueID identifier, CSSParserValue* value) +inline PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseValidPrimitive(CSSValueID identifier, CSSParserValue* value) { if (identifier) return cssValuePool().createIdentifierValue(identifier); @@ -1573,45 +374,38 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(CSSValueID i return createPrimitiveNumericValue(value); if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM) return createPrimitiveNumericValue(value); - if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME) - return createPrimitiveVariableNameValue(value); if (value->unit >= CSSParserValue::Q_EMS) return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); if (isCalculation(value)) return CSSPrimitiveValue::create(m_parsedCalculation.release()); - return 0; + return nullptr; } -void CSSParser::addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtr<CSSValue> prpValue, bool important) +void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtrWillBeRawPtr<CSSValue> prpValue, bool important) { const StylePropertyShorthand& shorthand = shorthandForProperty(propId); unsigned shorthandLength = shorthand.length(); if (!shorthandLength) { - addProperty(propId, prpValue, important); + addPropertyWithPrefixingVariant(propId, prpValue, important); return; } - RefPtr<CSSValue> value = prpValue; + RefPtrWillBeRawPtr<CSSValue> value = prpValue; ShorthandScope scope(this, propId); const CSSPropertyID* longhands = shorthand.properties(); for (unsigned i = 0; i < shorthandLength; ++i) - addProperty(longhands[i], value, important); -} - -void CSSParser::setCurrentProperty(CSSPropertyID propId) -{ - m_id = propId; + addPropertyWithPrefixingVariant(longhands[i], value, important); } -bool CSSParser::parseValue(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseValue(CSSPropertyID propId, bool important) { if (!isInternalPropertyAndValueParsingEnabledForMode(m_context.mode()) && isInternalProperty(propId)) return false; // We don't count the UA style sheet in our statistics. - if (m_useCounter) - m_useCounter->count(m_context, propId); + if (m_context.useCounter()) + m_context.useCounter()->count(m_context, propId); if (!m_valueList) return false; @@ -1650,13 +444,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return true; } - if (!id && value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME && num == 1) { - addProperty(propId, createPrimitiveVariableNameValue(value), important); - m_valueList->next(); - return true; - } - ASSERT(propId != CSSPropertyVariable); - if (isKeywordPropertyID(propId)) { if (!isValidKeywordPropertyAndValue(propId, id, m_context)) return false; @@ -1667,7 +454,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) } bool validPrimitive = false; - RefPtr<CSSValue> parsedValue; + RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; switch (propId) { case CSSPropertySize: // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ] @@ -1708,7 +495,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) if (num != 1 || !parseValue(CSSPropertyOverflowY, important)) return false; - RefPtr<CSSValue> overflowXValue; + RefPtrWillBeRawPtr<CSSValue> overflowXValue = nullptr; // FIXME: -webkit-paged-x or -webkit-paged-y only apply to overflow-y. If this value has been // set using the shorthand, then for now overflow-x will default to auto, but once we implement @@ -1801,15 +588,15 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) // [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize | // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize | // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help | - // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | -webkit-zoom-in - // -webkit-zoom-out | all-scroll | -webkit-grab | -webkit-grabbing ] ] | inherit - RefPtr<CSSValueList> list; + // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed | all-scroll | + // zoom-in | zoom-out | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out ] ] | inherit + RefPtrWillBeRawPtr<CSSValueList> list = nullptr; while (value) { - RefPtr<CSSValue> image = 0; + RefPtrWillBeRawPtr<CSSValue> image = nullptr; if (value->unit == CSSPrimitiveValue::CSS_URI) { String uri = value->string; if (!uri.isNull()) - image = CSSImageValue::create(completeURL(uri)); + image = createCSSImageValueWithReferrer(uri, completeURL(uri)); } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) { image = parseImageSet(m_valueList.get()); if (!image) @@ -1843,12 +630,18 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return false; value = m_valueList->next(); // comma } + if (value && m_context.useCounter()) { + if (value->id == CSSValueWebkitZoomIn) + m_context.useCounter()->count(UseCounter::PrefixedCursorZoomIn); + else if (value->id == CSSValueWebkitZoomOut) + m_context.useCounter()->count(UseCounter::PrefixedCursorZoomOut); + } if (list) { if (!value) return false; if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/ list->append(cssValuePool().createIdentifierValue(CSSValuePointer)); - else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone) + else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitZoomOut) || value->id == CSSValueCopy || value->id == CSSValueNone) list->append(cssValuePool().createIdentifierValue(value->id)); m_valueList->next(); parsedValue = list.release(); @@ -1858,7 +651,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) if (inQuirksMode() && value->id == CSSValueHand) { // MSIE 5 compatibility :/ id = CSSValuePointer; validPrimitive = true; - } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitGrabbing) || value->id == CSSValueCopy || value->id == CSSValueNone) + } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitZoomOut) || value->id == CSSValueCopy || value->id == CSSValueNone) validPrimitive = true; } else { ASSERT_NOT_REACHED(); @@ -1896,21 +689,24 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitMaskRepeatX: case CSSPropertyWebkitMaskRepeatY: { - RefPtr<CSSValue> val1; - RefPtr<CSSValue> val2; + RefPtrWillBeRawPtr<CSSValue> val1 = nullptr; + RefPtrWillBeRawPtr<CSSValue> val2 = nullptr; CSSPropertyID propId1, propId2; bool result = false; if (parseFillProperty(propId, propId1, propId2, val1, val2)) { - OwnPtr<ShorthandScope> shorthandScope; if (propId == CSSPropertyBackgroundPosition || propId == CSSPropertyBackgroundRepeat || propId == CSSPropertyWebkitMaskPosition || propId == CSSPropertyWebkitMaskRepeat) { - shorthandScope = adoptPtr(new ShorthandScope(this, propId)); + ShorthandScope scope(this, propId); + addProperty(propId1, val1.release(), important); + if (val2) + addProperty(propId2, val2.release(), important); + } else { + addProperty(propId1, val1.release(), important); + if (val2) + addProperty(propId2, val2.release(), important); } - addProperty(propId1, val1.release(), important); - if (val2) - addProperty(propId2, val2.release(), important); result = true; } m_implicitShorthand = false; @@ -1925,7 +721,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) parsedValue = cssValuePool().createIdentifierValue(CSSValueNone); m_valueList->next(); } else if (value->unit == CSSPrimitiveValue::CSS_URI) { - parsedValue = CSSImageValue::create(completeURL(value->string)); + parsedValue = createCSSImageValueWithReferrer(value->string, completeURL(value->string)); m_valueList->next(); } else if (isGeneratedImageValue(value)) { if (parseGeneratedImage(m_valueList.get(), parsedValue)) @@ -2036,17 +832,18 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) validPrimitive = (!id && validUnit(value, FLength | FPercent)); break; - case CSSPropertyZIndex: // auto | <integer> | inherit - if (id == CSSValueAuto) { - validPrimitive = true; - break; - } - /* nobreak */ case CSSPropertyOrphans: // <integer> | inherit | auto (We've added support for auto for backwards compatibility) case CSSPropertyWidows: // <integer> | inherit | auto (Ditto) if (id == CSSValueAuto) validPrimitive = true; else + validPrimitive = (!id && validUnit(value, FPositiveInteger, HTMLQuirksMode)); + break; + + case CSSPropertyZIndex: // auto | <integer> | inherit + if (id == CSSValueAuto) + validPrimitive = true; + else validPrimitive = (!id && validUnit(value, FInteger, HTMLQuirksMode)); break; @@ -2102,8 +899,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) break; case CSSPropertySrc: // Only used within @font-face and @-webkit-filter, so cannot use inherit | initial or be !important. This is a list of urls or local references. - if (m_inFilterRule) - return parseFilterRuleSrc(); return parseFontFaceSrc(); case CSSPropertyUnicodeRange: @@ -2115,7 +910,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitMaskBoxImage: return parseBorderImageShorthand(propId, important); case CSSPropertyWebkitBorderImage: { - if (RefPtr<CSSValue> result = parseBorderImage(propId)) { + if (RefPtrWillBeRawPtr<CSSValue> result = parseBorderImage(propId)) { addProperty(propId, result, important); return true; } @@ -2124,7 +919,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyBorderImageOutset: case CSSPropertyWebkitMaskBoxImageOutset: { - RefPtr<CSSPrimitiveValue> result; + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = nullptr; if (parseBorderImageOutset(result)) { addProperty(propId, result, important); return true; @@ -2133,7 +928,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) } case CSSPropertyBorderImageRepeat: case CSSPropertyWebkitMaskBoxImageRepeat: { - RefPtr<CSSValue> result; + RefPtrWillBeRawPtr<CSSValue> result = nullptr; if (parseBorderImageRepeat(result)) { addProperty(propId, result, important); return true; @@ -2142,7 +937,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) } case CSSPropertyBorderImageSlice: case CSSPropertyWebkitMaskBoxImageSlice: { - RefPtr<CSSBorderImageSliceValue> result; + RefPtrWillBeRawPtr<CSSBorderImageSliceValue> result = nullptr; if (parseBorderImageSlice(propId, result)) { addProperty(propId, result, important); return true; @@ -2151,7 +946,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) } case CSSPropertyBorderImageWidth: case CSSPropertyWebkitMaskBoxImageWidth: { - RefPtr<CSSPrimitiveValue> result; + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = nullptr; if (parseBorderImageWidth(result)) { addProperty(propId, result, important); return true; @@ -2167,8 +962,8 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) validPrimitive = validUnit(value, FLength | FPercent | FNonNeg); if (!validPrimitive) return false; - RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value); - RefPtr<CSSPrimitiveValue> parsedValue2; + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(value); + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2 = nullptr; if (num == 2) { value = m_valueList->next(); validPrimitive = validUnit(value, FLength | FPercent | FNonNeg); @@ -2198,7 +993,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) if (id == CSSValueNone) validPrimitive = true; else { - RefPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId); + RefPtrWillBeRawPtr<CSSValueList> shadowValueList = parseShadow(m_valueList.get(), propId); if (shadowValueList) { addProperty(propId, shadowValueList.release(), important); m_valueList->next(); @@ -2229,7 +1024,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) if (id == CSSValueNone) validPrimitive = true; else { - RefPtr<CSSValue> val = parseFilter(); + RefPtrWillBeRawPtr<CSSValue> val = parseFilter(); if (val) { addProperty(propId, val, important); return true; @@ -2259,16 +1054,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) validPrimitive = validUnit(value, FNumber | FNonNeg); break; case CSSPropertyOrder: - if (validUnit(value, FInteger, HTMLStandardMode)) { - if (value->unit != CSSPrimitiveValue::CSS_VARIABLE_NAME) { - // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set. - parsedValue = cssValuePool().createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue), - static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); - m_valueList->next(); - } else { - validPrimitive = true; - } - } + validPrimitive = validUnit(value, FInteger, HTMLStandardMode); break; case CSSPropertyInternalMarqueeIncrement: if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium) @@ -2288,19 +1074,12 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) else validPrimitive = validUnit(value, FTime | FInteger | FNonNeg); break; - case CSSPropertyWebkitFlowInto: - if (!RuntimeEnabledFeatures::cssRegionsEnabled()) - return false; - return parseFlowThread(propId, important); - case CSSPropertyWebkitFlowFrom: - if (!RuntimeEnabledFeatures::cssRegionsEnabled()) - return false; - return parseRegionThread(propId, important); + case CSSPropertyTransform: case CSSPropertyWebkitTransform: if (id == CSSValueNone) validPrimitive = true; else { - RefPtr<CSSValue> transformValue = parseTransform(); + RefPtrWillBeRawPtr<CSSValue> transformValue = parseTransform(propId); if (transformValue) { addProperty(propId, transformValue.release(), important); return true; @@ -2308,15 +1087,27 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return false; } break; + case CSSPropertyTransformOrigin: { + RefPtrWillBeRawPtr<CSSValueList> list = parseTransformOrigin(); + if (!list) + return false; + // These values are added to match gecko serialization. + if (list->length() == 1) + list->append(cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE)); + if (list->length() == 2) + list->append(cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX)); + addProperty(propId, list.release(), important); + return true; + } case CSSPropertyWebkitTransformOrigin: case CSSPropertyWebkitTransformOriginX: case CSSPropertyWebkitTransformOriginY: case CSSPropertyWebkitTransformOriginZ: { - RefPtr<CSSValue> val1; - RefPtr<CSSValue> val2; - RefPtr<CSSValue> val3; + RefPtrWillBeRawPtr<CSSValue> val1 = nullptr; + RefPtrWillBeRawPtr<CSSValue> val2 = nullptr; + RefPtrWillBeRawPtr<CSSValue> val3 = nullptr; CSSPropertyID propId1, propId2, propId3; - if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) { + if (parseWebkitTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) { addProperty(propId1, val1.release(), important); if (val2) addProperty(propId2, val2.release(), important); @@ -2326,28 +1117,40 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) } return false; } + case CSSPropertyPerspective: + if (id == CSSValueNone) { + validPrimitive = true; + } else if (validUnit(value, FLength | FNonNeg)) { + addProperty(propId, createPrimitiveNumericValue(value), important); + return true; + } + break; case CSSPropertyWebkitPerspective: - if (id == CSSValueNone) + if (id == CSSValueNone) { validPrimitive = true; - else { + } else if (validUnit(value, FNumber | FLength | FNonNeg)) { // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property. - if (validUnit(value, FNumber | FLength | FNonNeg)) { - RefPtr<CSSValue> val = createPrimitiveNumericValue(value); - if (val) { - addProperty(propId, val.release(), important); - return true; - } - return false; - } + addProperty(propId, createPrimitiveNumericValue(value), important); + return true; } break; + case CSSPropertyPerspectiveOrigin: { + RefPtrWillBeRawPtr<CSSValueList> list = parseTransformOrigin(); + if (!list || list->length() == 3) + return false; + // This values are added to match gecko serialization. + if (list->length() == 1) + list->append(cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE)); + addProperty(propId, list.release(), important); + return true; + } case CSSPropertyWebkitPerspectiveOrigin: case CSSPropertyWebkitPerspectiveOriginX: case CSSPropertyWebkitPerspectiveOriginY: { - RefPtr<CSSValue> val1; - RefPtr<CSSValue> val2; + RefPtrWillBeRawPtr<CSSValue> val1 = nullptr; + RefPtrWillBeRawPtr<CSSValue> val2 = nullptr; CSSPropertyID propId1, propId2; - if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) { + if (parseWebkitPerspectiveOrigin(propId, propId1, propId2, val1, val2)) { addProperty(propId1, val1.release(), important); if (val2) addProperty(propId2, val2.release(), important); @@ -2381,15 +1184,18 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitTransitionDuration: case CSSPropertyWebkitTransitionTimingFunction: case CSSPropertyWebkitTransitionProperty: { - RefPtr<CSSValue> val; - AnimationParseContext context; - if (parseAnimationProperty(propId, val, context)) { + if (RefPtrWillBeRawPtr<CSSValueList> val = parseAnimationPropertyList(propId)) { addPropertyWithPrefixingVariant(propId, val.release(), important); return true; } return false; } + case CSSPropertyJustifySelf: + if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) + return false; + + return parseItemPositionOverflowPosition(propId, important); case CSSPropertyGridAutoColumns: case CSSPropertyGridAutoRows: if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) @@ -2397,11 +1203,12 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) parsedValue = parseGridTrackSize(*m_valueList); break; - case CSSPropertyGridDefinitionColumns: - case CSSPropertyGridDefinitionRows: + case CSSPropertyGridTemplateColumns: + case CSSPropertyGridTemplateRows: if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) return false; - return parseGridTrackList(propId, important); + parsedValue = parseGridTrackList(important); + break; case CSSPropertyGridColumnEnd: case CSSPropertyGridColumnStart: @@ -2423,12 +1230,22 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return false; return parseGridAreaShorthand(important); - case CSSPropertyGridTemplate: + case CSSPropertyGridTemplateAreas: if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) return false; - parsedValue = parseGridTemplate(); + parsedValue = parseGridTemplateAreas(); break; + case CSSPropertyGridTemplate: + if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) + return false; + return parseGridTemplateShorthand(important); + + case CSSPropertyGrid: + if (!RuntimeEnabledFeatures::cssGridLayoutEnabled()) + return false; + return parseGridShorthand(important); + case CSSPropertyWebkitMarginCollapse: { if (num == 1) { ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse); @@ -2464,14 +1281,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) else validPrimitive = validUnit(value, FLength | FNonNeg); break; - case CSSPropertyWebkitColumnAxis: - if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto) - validPrimitive = true; - break; - case CSSPropertyWebkitColumnProgression: - if (id == CSSValueNormal || id == CSSValueReverse) - validPrimitive = true; - break; case CSSPropertyWebkitColumnSpan: // none | all | 1 (will be dropped in the unprefixed property) if (id == CSSValueAll || id == CSSValueNone) validPrimitive = true; @@ -2481,6 +1290,10 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitColumnWidth: // auto | <length> parsedValue = parseColumnWidth(); break; + case CSSPropertyWillChange: + if (!RuntimeEnabledFeatures::cssWillChangeEnabled()) + return false; + return parseWillChange(important); // End of CSS3 properties // Apple specific properties. These will never be standardized and are purely to @@ -2505,17 +1318,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) validPrimitive = true; break; - case CSSPropertyWebkitLineGrid: - if (id == CSSValueNone) - validPrimitive = true; - else if (value->unit == CSSPrimitiveValue::CSS_IDENT) { - String lineGridValue = String(value->string); - if (!lineGridValue.isEmpty()) { - addProperty(propId, cssValuePool().createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important); - return true; - } - } - break; case CSSPropertyWebkitLocale: if (id == CSSValueAuto || value->unit == CSSPrimitiveValue::CSS_STRING) validPrimitive = true; @@ -2660,7 +1462,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return parseFontFeatureSettings(important); break; - case CSSPropertyWebkitFontVariantLigatures: + case CSSPropertyFontVariantLigatures: if (id == CSSValueNormal) validPrimitive = true; else @@ -2670,42 +1472,35 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) if (id == CSSValueNone) { validPrimitive = true; } else if (value->unit == CSSParserValue::Function) { - return parseBasicShape(propId, important); + parsedValue = parseBasicShape(); } else if (value->unit == CSSPrimitiveValue::CSS_URI) { parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI); addProperty(propId, parsedValue.release(), important); return true; } break; - case CSSPropertyShapeInside: case CSSPropertyShapeOutside: - if (!RuntimeEnabledFeatures::cssShapesEnabled()) - return false; - if (id == CSSValueAuto) - validPrimitive = true; - else if (id == CSSValueContentBox || id == CSSValuePaddingBox || id == CSSValueBorderBox || id == CSSValueMarginBox) - validPrimitive = true; - else if (propId == CSSPropertyShapeInside && id == CSSValueOutsideShape) - validPrimitive = true; - else if (value->unit == CSSParserValue::Function) - return parseBasicShape(propId, important); - else if (value->unit == CSSPrimitiveValue::CSS_URI) { - parsedValue = CSSImageValue::create(completeURL(value->string)); - m_valueList->next(); - } + parsedValue = parseShapeProperty(propId); break; case CSSPropertyShapeMargin: - case CSSPropertyShapePadding: - validPrimitive = (RuntimeEnabledFeatures::cssShapesEnabled() && !id && validUnit(value, FLength | FNonNeg)); + validPrimitive = (RuntimeEnabledFeatures::cssShapesEnabled() && !id && validUnit(value, FLength | FPercent | FNonNeg)); break; case CSSPropertyShapeImageThreshold: validPrimitive = (RuntimeEnabledFeatures::cssShapesEnabled() && !id && validUnit(value, FNumber)); break; case CSSPropertyTouchAction: - // auto | none | [pan-x || pan-y] + // auto | none | [pan-x || pan-y] | manipulation return parseTouchAction(important); + case CSSPropertyAlignSelf: + ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); + return parseItemPositionOverflowPosition(propId, important); + + case CSSPropertyAlignItems: + ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); + return parseItemPositionOverflowPosition(propId, important); + case CSSPropertyBorderBottomStyle: case CSSPropertyBorderCollapse: case CSSPropertyBorderLeftStyle: @@ -2747,9 +1542,9 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyTextUnderlineMode: case CSSPropertyTextUnderlineStyle: case CSSPropertyTouchActionDelay: - case CSSPropertyVariable: case CSSPropertyVisibility: case CSSPropertyWebkitAppearance: + case CSSPropertyBackfaceVisibility: case CSSPropertyWebkitBackfaceVisibility: case CSSPropertyWebkitBorderAfterStyle: case CSSPropertyWebkitBorderBeforeStyle: @@ -2769,17 +1564,13 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyColumnFill: case CSSPropertyWebkitColumnRuleStyle: case CSSPropertyAlignContent: - case CSSPropertyAlignItems: - case CSSPropertyAlignSelf: case CSSPropertyFlexDirection: case CSSPropertyFlexWrap: case CSSPropertyJustifyContent: case CSSPropertyFontKerning: case CSSPropertyWebkitFontSmoothing: case CSSPropertyGridAutoFlow: - case CSSPropertyWebkitLineAlign: case CSSPropertyWebkitLineBreak: - case CSSPropertyWebkitLineSnap: case CSSPropertyWebkitMarginAfterCollapse: case CSSPropertyWebkitMarginBeforeCollapse: case CSSPropertyWebkitMarginBottomCollapse: @@ -2787,15 +1578,12 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyInternalMarqueeDirection: case CSSPropertyInternalMarqueeStyle: case CSSPropertyWebkitPrintColorAdjust: - case CSSPropertyWebkitRegionBreakAfter: - case CSSPropertyWebkitRegionBreakBefore: - case CSSPropertyWebkitRegionBreakInside: - case CSSPropertyWebkitRegionFragment: case CSSPropertyWebkitRtlOrdering: case CSSPropertyWebkitRubyPosition: case CSSPropertyWebkitTextCombine: case CSSPropertyWebkitTextEmphasisPosition: case CSSPropertyWebkitTextSecurity: + case CSSPropertyTransformStyle: case CSSPropertyWebkitTransformStyle: case CSSPropertyWebkitUserDrag: case CSSPropertyWebkitUserModify: @@ -2820,6 +1608,14 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyUserZoom: validPrimitive = false; break; + + case CSSPropertyAll: + if (id == CSSValueInitial || id == CSSValueInherit || id == CSSValueUnset) { + validPrimitive = true; + break; + } + return false; + default: return parseSVGValue(propId, important); } @@ -2838,14 +1634,14 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return false; } -void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) +void CSSPropertyParser::addFillValue(RefPtrWillBeRawPtr<CSSValue>& lval, PassRefPtrWillBeRawPtr<CSSValue> rval) { if (lval) { if (lval->isBaseValueList()) toCSSValueList(lval.get())->append(rval); else { - PassRefPtr<CSSValue> oldlVal(lval.release()); - PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + PassRefPtrWillBeRawPtr<CSSValue> oldlVal(lval.release()); + PassRefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); list->append(oldlVal); list->append(rval); lval = list; @@ -2855,7 +1651,7 @@ void CSSParser::addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) lval = rval; } -static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& cssValue) +static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtrWillBeRawPtr<CSSValue>& cssValue) { if (parserValue->id == CSSValueBorderBox || parserValue->id == CSSValuePaddingBox || parserValue->id == CSSValueContentBox || parserValue->id == CSSValueWebkitText) { @@ -2865,14 +1661,9 @@ static bool parseBackgroundClip(CSSParserValue* parserValue, RefPtr<CSSValue>& c return false; } -bool CSSParser::useLegacyBackgroundSizeShorthandBehavior() const -{ - return m_context.useLegacyBackgroundSizeShorthandBehavior(); -} - const int cMaxFillProperties = 9; -bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important) +bool CSSPropertyParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important) { ASSERT(numProperties <= cMaxFillProperties); if (numProperties > cMaxFillProperties) @@ -2881,10 +1672,14 @@ bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* pr ShorthandScope scope(this, propId); bool parsedProperty[cMaxFillProperties] = { false }; - RefPtr<CSSValue> values[cMaxFillProperties]; - RefPtr<CSSValue> clipValue; - RefPtr<CSSValue> positionYValue; - RefPtr<CSSValue> repeatYValue; + RefPtrWillBeRawPtr<CSSValue> values[cMaxFillProperties]; +#if ENABLE(OILPAN) + // Zero initialize the array of raw pointers. + memset(&values, 0, sizeof(values)); +#endif + RefPtrWillBeRawPtr<CSSValue> clipValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> positionYValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> repeatYValue = nullptr; bool foundClip = false; int i; bool foundPositionCSSProperty = false; @@ -2933,8 +1728,8 @@ bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* pr continue; if (!parsedProperty[i]) { - RefPtr<CSSValue> val1; - RefPtr<CSSValue> val2; + RefPtrWillBeRawPtr<CSSValue> val1 = nullptr; + RefPtrWillBeRawPtr<CSSValue> val2 = nullptr; CSSPropertyID propId1, propId2; CSSParserValue* parserValue = m_valueList->current(); // parseFillProperty() may modify m_implicitShorthand, so we MUST reset it @@ -3005,7 +1800,7 @@ bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* pr } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip) // Value is already set while updating origin continue; - else if (properties[i] == CSSPropertyBackgroundSize && !parsedProperty[i] && useLegacyBackgroundSizeShorthandBehavior()) + else if (properties[i] == CSSPropertyBackgroundSize && !parsedProperty[i] && m_context.useLegacyBackgroundSizeShorthandBehavior()) continue; else addProperty(properties[i], values[i].release(), important); @@ -3021,48 +1816,22 @@ bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* pr return true; } -void CSSParser::storeVariableDeclaration(const CSSParserString& name, PassOwnPtr<CSSParserValueList> value, bool important) -{ - // When CSSGrammar.y encounters an invalid declaration it passes null for the CSSParserValueList, just bail. - if (!value) - return; - - static const unsigned prefixLength = sizeof("var-") - 1; - - ASSERT(name.length() > prefixLength); - AtomicString variableName = name.atomicSubstring(prefixLength, name.length() - prefixLength); - - StringBuilder builder; - for (unsigned i = 0, size = value->size(); i < size; i++) { - if (i) - builder.append(' '); - RefPtr<CSSValue> cssValue = value->valueAt(i)->createCSSValue(); - if (!cssValue) - return; - builder.append(cssValue->cssText()); - } - - addProperty(CSSPropertyVariable, CSSVariableValue::create(variableName, builder.toString()), important, false); -} - -void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) +static bool isValidTransitionPropertyList(CSSValueList* value) { - if (lval) { - if (lval->isValueList()) - toCSSValueList(lval.get())->append(rval); - else { - PassRefPtr<CSSValue> oldVal(lval.release()); - PassRefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - list->append(oldVal); - list->append(rval); - lval = list; - } + if (value->length() < 2) + return true; + for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { + // FIXME: Shorthand parsing shouldn't add initial to the list since it won't round-trip + if (i.value()->isInitialValue()) + continue; + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); + if (primitiveValue->isValueID() && primitiveValue->getValueID() == CSSValueNone) + return false; } - else - lval = rval; + return true; } -bool CSSParser::parseAnimationShorthand(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseAnimationShorthand(CSSPropertyID propId, bool important) { const StylePropertyShorthand& animationProperties = parsingShorthandForProperty(propId); const unsigned numProperties = 8; @@ -3076,34 +1845,32 @@ bool CSSParser::parseAnimationShorthand(CSSPropertyID propId, bool important) ShorthandScope scope(this, propId); bool parsedProperty[numProperties] = { false }; - AnimationParseContext context; - RefPtr<CSSValue> values[numProperties]; + RefPtrWillBeRawPtr<CSSValueList> values[numProperties]; + for (size_t i = 0; i < numProperties; ++i) + values[i] = CSSValueList::createCommaSeparated(); - unsigned i; while (m_valueList->current()) { CSSParserValue* val = m_valueList->current(); if (val->unit == CSSParserValue::Operator && val->iValue == ',') { - // We hit the end. Fill in all remaining values with the initial value. + // We hit the end. Fill in all remaining values with the initial value. m_valueList->next(); - for (i = 0; i < numProperties; ++i) { + for (size_t i = 0; i < numProperties; ++i) { if (!parsedProperty[i]) - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue()); + values[i]->append(cssValuePool().createImplicitInitialValue()); parsedProperty[i] = false; } if (!m_valueList->current()) break; - context.commitFirstAnimation(); } bool found = false; - for (i = 0; i < numProperties; ++i) { - if (!parsedProperty[i]) { - RefPtr<CSSValue> val; - if (parseAnimationProperty(animationProperties.properties()[i], val, context)) { - parsedProperty[i] = found = true; - addAnimationValue(values[i], val.release()); - break; - } + for (size_t i = 0; i < numProperties; ++i) { + if (parsedProperty[i]) + continue; + if (RefPtrWillBeRawPtr<CSSValue> val = parseAnimationProperty(animationProperties.properties()[i])) { + parsedProperty[i] = found = true; + values[i]->append(val.release()); + break; } } @@ -3113,57 +1880,55 @@ bool CSSParser::parseAnimationShorthand(CSSPropertyID propId, bool important) return false; } - for (i = 0; i < numProperties; ++i) { + for (size_t i = 0; i < numProperties; ++i) { // If we didn't find the property, set an intial value. if (!parsedProperty[i]) - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue()); + values[i]->append(cssValuePool().createImplicitInitialValue()); - addProperty(animationProperties.properties()[i], values[i].release(), important); + if (RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled()) + addPropertyWithPrefixingVariant(animationProperties.properties()[i], values[i].release(), important); + else + addProperty(animationProperties.properties()[i], values[i].release(), important); } return true; } -bool CSSParser::parseTransitionShorthand(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseTransitionShorthand(CSSPropertyID propId, bool important) { const unsigned numProperties = 4; - const StylePropertyShorthand& shorthand = shorthandForProperty(propId); + const StylePropertyShorthand& shorthand = parsingShorthandForProperty(propId); ASSERT(numProperties == shorthand.length()); ShorthandScope scope(this, propId); bool parsedProperty[numProperties] = { false }; - AnimationParseContext context; - RefPtr<CSSValue> values[numProperties]; + RefPtrWillBeRawPtr<CSSValueList> values[numProperties]; + for (size_t i = 0; i < numProperties; ++i) + values[i] = CSSValueList::createCommaSeparated(); - unsigned i; while (m_valueList->current()) { CSSParserValue* val = m_valueList->current(); if (val->unit == CSSParserValue::Operator && val->iValue == ',') { // We hit the end. Fill in all remaining values with the initial value. m_valueList->next(); - for (i = 0; i < numProperties; ++i) { + for (size_t i = 0; i < numProperties; ++i) { if (!parsedProperty[i]) - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue()); + values[i]->append(cssValuePool().createImplicitInitialValue()); parsedProperty[i] = false; } if (!m_valueList->current()) break; - context.commitFirstAnimation(); } bool found = false; - for (i = 0; !found && i < numProperties; ++i) { - if (!parsedProperty[i]) { - RefPtr<CSSValue> val; - if (parseAnimationProperty(shorthand.properties()[i], val, context)) { - parsedProperty[i] = found = true; - addAnimationValue(values[i], val.release()); - } - - // There are more values to process but 'none' or 'all' were already defined as the animation property, the declaration becomes invalid. - if (!context.animationPropertyKeywordAllowed() && context.hasCommittedFirstAnimation()) - return false; + for (size_t i = 0; i < numProperties; ++i) { + if (parsedProperty[i]) + continue; + if (RefPtrWillBeRawPtr<CSSValue> val = parseAnimationProperty(shorthand.properties()[i])) { + parsedProperty[i] = found = true; + values[i]->append(val.release()); + break; } } @@ -3173,49 +1938,50 @@ bool CSSParser::parseTransitionShorthand(CSSPropertyID propId, bool important) return false; } - // Fill in any remaining properties with the initial value. - for (i = 0; i < numProperties; ++i) { - if (!parsedProperty[i]) - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue()); - } + ASSERT(shorthand.properties()[3] == CSSPropertyTransitionProperty || shorthand.properties()[3] == CSSPropertyWebkitTransitionProperty); + if (!isValidTransitionPropertyList(values[3].get())) + return false; - // Now add all of the properties we found. - for (i = 0; i < numProperties; i++) + // Fill in any remaining properties with the initial value and add + for (size_t i = 0; i < numProperties; ++i) { + if (!parsedProperty[i]) + values[i]->append(cssValuePool().createImplicitInitialValue()); addPropertyWithPrefixingVariant(shorthand.properties()[i], values[i].release(), important); + } return true; } -PassRefPtr<CSSValue> CSSParser::parseColumnWidth() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseColumnWidth() { CSSParserValue* value = m_valueList->current(); // Always parse lengths in strict mode here, since it would be ambiguous otherwise when used in // the 'columns' shorthand property. if (value->id == CSSValueAuto || (validUnit(value, FLength | FNonNeg, HTMLStandardMode) && value->fValue)) { - RefPtr<CSSValue> parsedValue = parseValidPrimitive(value->id, value); + RefPtrWillBeRawPtr<CSSValue> parsedValue = parseValidPrimitive(value->id, value); m_valueList->next(); return parsedValue; } - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseColumnCount() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseColumnCount() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueAuto || (!value->id && validUnit(value, FPositiveInteger, HTMLQuirksMode))) { - RefPtr<CSSValue> parsedValue = parseValidPrimitive(value->id, value); + RefPtrWillBeRawPtr<CSSValue> parsedValue = parseValidPrimitive(value->id, value); m_valueList->next(); return parsedValue; } - return 0; + return nullptr; } -bool CSSParser::parseColumnsShorthand(bool important) +bool CSSPropertyParser::parseColumnsShorthand(bool important) { - RefPtr <CSSValue> columnWidth; - RefPtr <CSSValue> columnCount; + RefPtrWillBeRawPtr<CSSValue> columnWidth = nullptr; + RefPtrWillBeRawPtr<CSSValue> columnCount = nullptr; bool hasPendingExplicitAuto = false; for (unsigned propertiesParsed = 0; CSSParserValue* value = m_valueList->current(); propertiesParsed++) { @@ -3267,7 +2033,7 @@ bool CSSParser::parseColumnsShorthand(bool important) return true; } -bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important) +bool CSSPropertyParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important) { // We try to match as many properties as possible // We set up an array of booleans to mark which property has been found, @@ -3276,14 +2042,14 @@ bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthan bool found = false; unsigned propertiesParsed = 0; - bool propertyFound[6]= { false, false, false, false, false, false }; // 6 is enough size. + bool propertyFound[6] = { false, false, false, false, false, false }; // 6 is enough size. while (m_valueList->current()) { found = false; for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) { if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) { - propertyFound[propIndex] = found = true; - propertiesParsed++; + propertyFound[propIndex] = found = true; + propertiesParsed++; } } @@ -3314,7 +2080,7 @@ bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthan return true; } -bool CSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties, bool important) +bool CSSPropertyParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties, bool important) { /* From the CSS 2 specs, 8.3 * If there is only one value, it applies to all sides. If there are two values, the top and @@ -3373,7 +2139,7 @@ bool CSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properti } // auto | <identifier> -bool CSSParser::parsePage(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parsePage(CSSPropertyID propId, bool important) { ASSERT(propId == CSSPropertyPage); @@ -3395,7 +2161,7 @@ bool CSSParser::parsePage(CSSPropertyID propId, bool important) } // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ] -bool CSSParser::parseSize(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseSize(CSSPropertyID propId, bool important) { ASSERT(propId == CSSPropertySize); @@ -3406,7 +2172,7 @@ bool CSSParser::parseSize(CSSPropertyID propId, bool important) if (!value) return false; - RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); // First parameter. SizeParameterType paramType = parseSizeParameter(parsedValues.get(), value, None); @@ -3425,7 +2191,7 @@ bool CSSParser::parseSize(CSSPropertyID propId, bool important) return true; } -CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType) +CSSPropertyParser::SizeParameterType CSSPropertyParser::parseSizeParameter(CSSValueList* parsedValues, CSSParserValue* value, SizeParameterType prevParamType) { switch (value->id) { case CSSValueAuto: @@ -3469,11 +2235,11 @@ CSSParser::SizeParameterType CSSParser::parseSizeParameter(CSSValueList* parsedV // [ <string> <string> ]+ | inherit | none // inherit and none are handled in parseValue. -bool CSSParser::parseQuotes(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseQuotes(CSSPropertyID propId, bool important) { - RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); while (CSSParserValue* val = m_valueList->current()) { - RefPtr<CSSValue> parsedValue; + RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; if (val->unit == CSSPrimitiveValue::CSS_STRING) parsedValue = CSSPrimitiveValue::create(val->string, CSSPrimitiveValue::CSS_STRING); else @@ -3492,15 +2258,15 @@ bool CSSParser::parseQuotes(CSSPropertyID propId, bool important) // [ <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 -bool CSSParser::parseContent(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseContent(CSSPropertyID propId, bool important) { - RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); while (CSSParserValue* val = m_valueList->current()) { - RefPtr<CSSValue> parsedValue; + RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; if (val->unit == CSSPrimitiveValue::CSS_URI) { // url - parsedValue = CSSImageValue::create(completeURL(val->string)); + parsedValue = createCSSImageValueWithReferrer(val->string, completeURL(val->string)); } else if (val->unit == CSSParserValue::Function) { // attr(X) | counter(X [,Y]) | counters(X, Y, [,Z]) | -webkit-gradient(...) CSSParserValueList* args = val->function->args.get(); @@ -3565,22 +2331,22 @@ bool CSSParser::parseContent(CSSPropertyID propId, bool important) return false; } -PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAttr(CSSParserValueList* args) { if (args->size() != 1) - return 0; + return nullptr; CSSParserValue* a = args->current(); if (a->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; + return nullptr; String attrName = a->string; // CSS allows identifiers with "-" at the start, like "-webkit-mask-image". // But HTML attribute names can't have those characters, and we should not // even parse them inside attr(). if (attrName[0] == '-') - return 0; + return nullptr; if (m_context.isHTMLDocument()) attrName = attrName.lower(); @@ -3588,7 +2354,7 @@ PassRefPtr<CSSValue> CSSParser::parseAttr(CSSParserValueList* args) return cssValuePool().createValue(attrName, CSSPrimitiveValue::CSS_ATTR); } -PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseBackgroundColor() { CSSValueID id = m_valueList->current()->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor || @@ -3597,14 +2363,14 @@ PassRefPtr<CSSValue> CSSParser::parseBackgroundColor() return parseColor(); } -bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value) +bool CSSPropertyParser::parseFillImage(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& value) { if (valueList->current()->id == CSSValueNone) { value = cssValuePool().createIdentifierValue(CSSValueNone); return true; } if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) { - value = CSSImageValue::create(completeURL(valueList->current()->string)); + value = createCSSImageValueWithReferrer(valueList->current()->string, completeURL(valueList->current()->string)); return true; } @@ -3620,7 +2386,7 @@ bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>& return false; } -PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseFillPositionX(CSSParserValueList* valueList) { int id = valueList->current()->id; if (id == CSSValueLeft || id == CSSValueRight || id == CSSValueCenter) { @@ -3633,10 +2399,10 @@ PassRefPtr<CSSValue> CSSParser::parseFillPositionX(CSSParserValueList* valueList } if (validUnit(valueList->current(), FPercent | FLength)) return createPrimitiveNumericValue(valueList->current()); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseFillPositionY(CSSParserValueList* valueList) { int id = valueList->current()->id; if (id == CSSValueTop || id == CSSValueBottom || id == CSSValueCenter) { @@ -3649,17 +2415,17 @@ PassRefPtr<CSSValue> CSSParser::parseFillPositionY(CSSParserValueList* valueList } if (validUnit(valueList->current(), FPercent | FLength)) return createPrimitiveNumericValue(valueList->current()); - return 0; + return nullptr; } -PassRefPtr<CSSPrimitiveValue> CSSParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag, FillPositionParsingMode parsingMode) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseFillPositionComponent(CSSParserValueList* valueList, unsigned& cumulativeFlags, FillPositionFlag& individualFlag, FillPositionParsingMode parsingMode) { CSSValueID id = valueList->current()->id; if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) { int percent = 0; if (id == CSSValueLeft || id == CSSValueRight) { if (cumulativeFlags & XFillPosition) - return 0; + return nullptr; cumulativeFlags |= XFillPosition; individualFlag = XFillPosition; if (id == CSSValueRight) @@ -3667,7 +2433,7 @@ PassRefPtr<CSSPrimitiveValue> CSSParser::parseFillPositionComponent(CSSParserVal } else if (id == CSSValueTop || id == CSSValueBottom) { if (cumulativeFlags & YFillPosition) - return 0; + return nullptr; cumulativeFlags |= YFillPosition; individualFlag = YFillPosition; if (id == CSSValueBottom) @@ -3694,11 +2460,11 @@ PassRefPtr<CSSPrimitiveValue> CSSParser::parseFillPositionComponent(CSSParserVal } else { if (m_parsedCalculation) m_parsedCalculation.release(); - return 0; + return nullptr; } return createPrimitiveNumericValue(valueList->current()); } - return 0; + return nullptr; } static bool isValueConflictingWithCurrentEdge(int value1, int value2) @@ -3717,7 +2483,7 @@ static bool isFillPositionKeyword(CSSValueID value) return value == CSSValueLeft || value == CSSValueTop || value == CSSValueBottom || value == CSSValueRight || value == CSSValueCenter; } -void CSSParser::parse4ValuesFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, PassRefPtr<CSSPrimitiveValue> parsedValue1, PassRefPtr<CSSPrimitiveValue> parsedValue2) +void CSSPropertyParser::parse4ValuesFillPosition(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2) { // [ left | right ] [ <percentage] | <length> ] && [ top | bottom ] [ <percentage> | <length> ] // In the case of 4 values <position> requires the second value to be a length or a percentage. @@ -3726,7 +2492,7 @@ void CSSParser::parse4ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C unsigned cumulativeFlags = 0; FillPositionFlag value3Flag = InvalidFillPosition; - RefPtr<CSSPrimitiveValue> value3 = parseFillPositionComponent(valueList, cumulativeFlags, value3Flag, ResolveValuesAsKeyword); + RefPtrWillBeRawPtr<CSSPrimitiveValue> value3 = parseFillPositionComponent(valueList, cumulativeFlags, value3Flag, ResolveValuesAsKeyword); if (!value3) return; @@ -3749,7 +2515,7 @@ void CSSParser::parse4ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C cumulativeFlags = 0; FillPositionFlag value4Flag = InvalidFillPosition; - RefPtr<CSSPrimitiveValue> value4 = parseFillPositionComponent(valueList, cumulativeFlags, value4Flag, ResolveValuesAsKeyword); + RefPtrWillBeRawPtr<CSSPrimitiveValue> value4 = parseFillPositionComponent(valueList, cumulativeFlags, value4Flag, ResolveValuesAsKeyword); if (!value4) return; @@ -3765,11 +2531,11 @@ void CSSParser::parse4ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C valueList->next(); } -void CSSParser::parse3ValuesFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, PassRefPtr<CSSPrimitiveValue> parsedValue1, PassRefPtr<CSSPrimitiveValue> parsedValue2) +void CSSPropertyParser::parse3ValuesFillPosition(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1, PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2) { unsigned cumulativeFlags = 0; FillPositionFlag value3Flag = InvalidFillPosition; - RefPtr<CSSPrimitiveValue> value3 = parseFillPositionComponent(valueList, cumulativeFlags, value3Flag, ResolveValuesAsKeyword); + RefPtrWillBeRawPtr<CSSPrimitiveValue> value3 = parseFillPositionComponent(valueList, cumulativeFlags, value3Flag, ResolveValuesAsKeyword); // value3 is not an expected value, we return. if (!value3) @@ -3813,8 +2579,8 @@ void CSSParser::parse3ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C value1 = createPrimitiveValuePair(parsedValue1, parsedValue2); value2 = createPrimitiveValuePair(cssValuePool().createIdentifierValue(secondPositionKeyword), cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE)); } else { - RefPtr<CSSPrimitiveValue> firstPositionValue; - RefPtr<CSSPrimitiveValue> secondPositionValue; + RefPtrWillBeRawPtr<CSSPrimitiveValue> firstPositionValue = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> secondPositionValue = nullptr; if (isFillPositionKeyword(ident2)) { // To match CSS grammar, we should only accept: [ center | left | right | bottom | top ] [ left | right | top | bottom ] [ <percentage> | <length> ]. @@ -3856,12 +2622,12 @@ void CSSParser::parse3ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C #endif } -inline bool CSSParser::isPotentialPositionValue(CSSParserValue* value) +inline bool CSSPropertyParser::isPotentialPositionValue(CSSParserValue* value) { return isFillPositionKeyword(value->id) || validUnit(value, FPercent | FLength, ReleaseParsedCalcValue); } -void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2) +void CSSPropertyParser::parseFillPosition(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2) { unsigned numberOfValues = 0; for (unsigned i = valueList->currentIndex(); i < valueList->size(); ++i, ++numberOfValues) { @@ -3895,7 +2661,7 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue if (!value1) return; - value = valueList->next(); + valueList->next(); // In case we are parsing more than two values, relax the check inside of parseFillPositionComponent. top 20px is // a valid start for <position>. @@ -3908,8 +2674,8 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue return; } - RefPtr<CSSPrimitiveValue> parsedValue1 = toCSSPrimitiveValue(value1.get()); - RefPtr<CSSPrimitiveValue> parsedValue2 = toCSSPrimitiveValue(value2.get()); + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1 = toCSSPrimitiveValue(value1.get()); + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2 = toCSSPrimitiveValue(value2.get()); value1.clear(); value2.clear(); @@ -3924,10 +2690,8 @@ void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue parse4ValuesFillPosition(valueList, value1, value2, parsedValue1.release(), parsedValue2.release()); } -void CSSParser::parse2ValuesFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2) +void CSSPropertyParser::parse2ValuesFillPosition(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2) { - 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. unsigned cumulativeFlags = 0; FillPositionFlag value1Flag = InvalidFillPosition; @@ -3939,7 +2703,7 @@ void CSSParser::parse2ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the // value was explicitly specified for our property. - value = valueList->next(); + CSSParserValue* value = valueList->next(); // First check for the comma. If so, we are finished parsing this value or value pair. if (isComma(value)) @@ -3968,7 +2732,7 @@ void CSSParser::parse2ValuesFillPosition(CSSParserValueList* valueList, RefPtr<C value1.swap(value2); } -void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2) +void CSSPropertyParser::parseFillRepeat(RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2) { CSSValueID id = m_valueList->current()->id; if (id == CSSValueRepeatX) { @@ -3988,7 +2752,7 @@ void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& valu if (id == CSSValueRepeat || id == CSSValueNoRepeat || id == CSSValueRound || id == CSSValueSpace) value1 = cssValuePool().createIdentifierValue(id); else { - value1 = 0; + value1 = nullptr; return; } @@ -4009,7 +2773,7 @@ void CSSParser::parseFillRepeat(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& valu value2 = cssValuePool().createIdentifierValue(toCSSPrimitiveValue(value1.get())->getValueID()); } -PassRefPtr<CSSValue> CSSParser::parseFillSize(CSSPropertyID propId, bool& allowComma) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseFillSize(CSSPropertyID propId, bool& allowComma) { allowComma = true; CSSParserValue* value = m_valueList->current(); @@ -4017,24 +2781,24 @@ PassRefPtr<CSSValue> CSSParser::parseFillSize(CSSPropertyID propId, bool& allowC if (value->id == CSSValueContain || value->id == CSSValueCover) return cssValuePool().createIdentifierValue(value->id); - RefPtr<CSSPrimitiveValue> parsedValue1; + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue1 = nullptr; if (value->id == CSSValueAuto) parsedValue1 = cssValuePool().createIdentifierValue(CSSValueAuto); else { if (!validUnit(value, FLength | FPercent)) - return 0; + return nullptr; parsedValue1 = createPrimitiveNumericValue(value); } - RefPtr<CSSPrimitiveValue> parsedValue2; + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue2 = nullptr; if ((value = m_valueList->next())) { if (value->unit == CSSParserValue::Operator && value->iValue == ',') allowComma = false; else if (value->id != CSSValueAuto) { if (!validUnit(value, FLength | FPercent)) { if (!inShorthand()) - return 0; + return nullptr; // We need to rewind the value list, so that when it is advanced we'll end up back at this value. m_valueList->previous(); } else @@ -4049,21 +2813,25 @@ PassRefPtr<CSSValue> CSSParser::parseFillSize(CSSPropertyID propId, bool& allowC if (!parsedValue2) return parsedValue1; - return createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release()); + + Pair::IdenticalValuesPolicy policy = propId == CSSPropertyWebkitBackgroundSize ? + Pair::DropIdenticalValues : Pair::KeepIdenticalValues; + + return createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release(), policy); } -bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, - RefPtr<CSSValue>& retValue1, RefPtr<CSSValue>& retValue2) +bool CSSPropertyParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, + RefPtrWillBeRawPtr<CSSValue>& retValue1, RefPtrWillBeRawPtr<CSSValue>& retValue2) { - RefPtr<CSSValueList> values; - RefPtr<CSSValueList> values2; + RefPtrWillBeRawPtr<CSSValueList> values = nullptr; + RefPtrWillBeRawPtr<CSSValueList> values2 = nullptr; CSSParserValue* val; - RefPtr<CSSValue> value; - RefPtr<CSSValue> value2; + RefPtrWillBeRawPtr<CSSValue> value = nullptr; + RefPtrWillBeRawPtr<CSSValue> value2 = nullptr; bool allowComma = false; - retValue1 = retValue2 = 0; + retValue1 = retValue2 = nullptr; propId1 = propId; propId2 = propId; if (propId == CSSPropertyBackgroundPosition) { @@ -4081,8 +2849,8 @@ bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, } while ((val = m_valueList->current())) { - RefPtr<CSSValue> currValue; - RefPtr<CSSValue> currValue2; + RefPtrWillBeRawPtr<CSSValue> currValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> currValue2 = nullptr; if (allowComma) { if (!isComma(val)) @@ -4159,12 +2927,12 @@ bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, } break; case CSSPropertyBackgroundBlendMode: - if (RuntimeEnabledFeatures::cssCompositingEnabled() && (val->id == CSSValueNormal || val->id == CSSValueMultiply + if (val->id == CSSValueNormal || val->id == CSSValueMultiply || val->id == CSSValueScreen || val->id == CSSValueOverlay || val->id == CSSValueDarken || val->id == CSSValueLighten || val->id == CSSValueColorDodge || val->id == CSSValueColorBurn || val->id == CSSValueHardLight || val->id == CSSValueSoftLight || val->id == CSSValueDifference || val->id == CSSValueExclusion || val->id == CSSValueHue || val->id == CSSValueSaturation - || val->id == CSSValueColor || val->id == CSSValueLuminosity)) { + || val->id == CSSValueColor || val->id == CSSValueLuminosity) { currValue = cssValuePool().createIdentifierValue(val->id); m_valueList->next(); } @@ -4188,7 +2956,7 @@ bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, currValue = cssValuePool().createIdentifierValue(val->id); m_valueList->next(); } else { - currValue = 0; + currValue = nullptr; } } break; @@ -4241,49 +3009,49 @@ bool CSSParser::parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, return false; } -PassRefPtr<CSSValue> CSSParser::parseAnimationDelay() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationDelay() { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FTime)) return createPrimitiveNumericValue(value); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationDirection() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationDirection() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNormal || value->id == CSSValueAlternate || value->id == CSSValueReverse || value->id == CSSValueAlternateReverse) return cssValuePool().createIdentifierValue(value->id); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationDuration() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationDuration() { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FTime | FNonNeg)) return createPrimitiveNumericValue(value); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationFillMode() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationFillMode() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNone || value->id == CSSValueForwards || value->id == CSSValueBackwards || value->id == CSSValueBoth) return cssValuePool().createIdentifierValue(value->id); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationIterationCount() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationIterationCount() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueInfinite) return cssValuePool().createIdentifierValue(value->id); if (validUnit(value, FNumber | FNonNeg)) return createPrimitiveNumericValue(value); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationName() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationName() { CSSParserValue* value = m_valueList->current(); if (value->unit == CSSPrimitiveValue::CSS_STRING || value->unit == CSSPrimitiveValue::CSS_IDENT) { @@ -4293,38 +3061,38 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationName() return createPrimitiveStringValue(value); } } - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationPlayState() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationPlayState() { CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueRunning || value->id == CSSValuePaused) return cssValuePool().createIdentifierValue(value->id); - return 0; + return nullptr; } -PassRefPtr<CSSValue> CSSParser::parseAnimationProperty(AnimationParseContext& context) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationProperty() { CSSParserValue* value = m_valueList->current(); if (value->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; + return nullptr; + // Since all is valid css property keyword, cssPropertyID for all + // returns non-null value. We need to check "all" before + // cssPropertyID check. + if (equalIgnoringCase(value, "all")) + return cssValuePool().createIdentifierValue(CSSValueAll); CSSPropertyID result = cssPropertyID(value->string); - if (result) + if (result && RuntimeCSSEnabled::isCSSPropertyEnabled(result)) return cssValuePool().createIdentifierValue(result); - if (equalIgnoringCase(value, "all")) { - context.sawAnimationPropertyKeyword(); - return cssValuePool().createIdentifierValue(CSSValueAll); - } - if (equalIgnoringCase(value, "none")) { - context.commitAnimationPropertyKeyword(); - context.sawAnimationPropertyKeyword(); + if (equalIgnoringCase(value, "none")) return cssValuePool().createIdentifierValue(CSSValueNone); - } - return 0; + if (equalIgnoringCase(value, "inherit") || equalIgnoringCase(value, "initial")) + return nullptr; + return createPrimitiveStringValue(value); } -bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3) +bool CSSPropertyParser::parseWebkitTransformOriginShorthand(RefPtrWillBeRawPtr<CSSValue>& value1, RefPtrWillBeRawPtr<CSSValue>& value2, RefPtrWillBeRawPtr<CSSValue>& value3) { parse2ValuesFillPosition(m_valueList.get(), value1, value2); @@ -4341,7 +3109,7 @@ bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<C return true; } -bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result) +bool CSSPropertyParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result) { CSSParserValue* v = args->current(); if (!validUnit(v, FNumber)) @@ -4357,210 +3125,192 @@ bool CSSParser::parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, d return true; } -PassRefPtr<CSSValue> CSSParser::parseAnimationTimingFunction() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::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) + || value->id == CSSValueEaseInOut || value->id == CSSValueStepStart || value->id == CSSValueStepEnd + || (value->id == CSSValueStepMiddle && RuntimeEnabledFeatures::webAnimationsElementAnimateEnabled())) return cssValuePool().createIdentifierValue(value->id); // We must be a function. if (value->unit != CSSParserValue::Function) - return 0; + return nullptr; CSSParserValueList* args = value->function->args.get(); if (equalIgnoringCase(value->function->name, "steps(")) { // For steps, 1 or 2 params must be specified (comma-separated) if (!args || (args->size() != 1 && args->size() != 3)) - return 0; + return nullptr; // There are two values. int numSteps; - bool stepAtStart = false; + StepsTimingFunction::StepAtPosition stepAtPosition = StepsTimingFunction::StepAtEnd; CSSParserValue* v = args->current(); if (!validUnit(v, FInteger)) - return 0; + return nullptr; numSteps = clampToInteger(v->fValue); if (numSteps < 1) - return 0; + return nullptr; v = args->next(); if (v) { // There is a comma so we need to parse the second value if (!isComma(v)) - return 0; + return nullptr; v = args->next(); - if (v->id != CSSValueStart && v->id != CSSValueEnd) - return 0; - stepAtStart = v->id == CSSValueStart; + switch (v->id) { + case CSSValueMiddle: + if (!RuntimeEnabledFeatures::webAnimationsAPIEnabled()) + return nullptr; + stepAtPosition = StepsTimingFunction::StepAtMiddle; + break; + case CSSValueStart: + stepAtPosition = StepsTimingFunction::StepAtStart; + break; + case CSSValueEnd: + stepAtPosition = StepsTimingFunction::StepAtEnd; + break; + default: + return nullptr; + } } - return CSSStepsTimingFunctionValue::create(numSteps, stepAtStart); + return CSSStepsTimingFunctionValue::create(numSteps, stepAtPosition); } if (equalIgnoringCase(value->function->name, "cubic-bezier(")) { // For cubic bezier, 4 values must be specified. if (!args || args->size() != 7) - return 0; + return nullptr; // There are two points specified. The x values must be between 0 and 1 but the y values can exceed this range. double x1, y1, x2, y2; if (!parseCubicBezierTimingFunctionValue(args, x1)) - return 0; + return nullptr; if (x1 < 0 || x1 > 1) - return 0; + return nullptr; if (!parseCubicBezierTimingFunctionValue(args, y1)) - return 0; + return nullptr; if (!parseCubicBezierTimingFunctionValue(args, x2)) - return 0; + return nullptr; if (x2 < 0 || x2 > 1) - return 0; + return nullptr; if (!parseCubicBezierTimingFunctionValue(args, y2)) - return 0; + return nullptr; return CSSCubicBezierTimingFunctionValue::create(x1, y1, x2, y2); } - return 0; + return nullptr; } -bool CSSParser::parseAnimationProperty(CSSPropertyID propId, RefPtr<CSSValue>& result, AnimationParseContext& context) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationProperty(CSSPropertyID propId) { - RefPtr<CSSValueList> values; - CSSParserValue* val; - RefPtr<CSSValue> value; - bool allowComma = false; + RefPtrWillBeRawPtr<CSSValue> value = nullptr; + switch (propId) { + case CSSPropertyAnimationDelay: + case CSSPropertyWebkitAnimationDelay: + case CSSPropertyTransitionDelay: + case CSSPropertyWebkitTransitionDelay: + value = parseAnimationDelay(); + break; + case CSSPropertyAnimationDirection: + case CSSPropertyWebkitAnimationDirection: + value = parseAnimationDirection(); + break; + case CSSPropertyAnimationDuration: + case CSSPropertyWebkitAnimationDuration: + case CSSPropertyTransitionDuration: + case CSSPropertyWebkitTransitionDuration: + value = parseAnimationDuration(); + break; + case CSSPropertyAnimationFillMode: + case CSSPropertyWebkitAnimationFillMode: + value = parseAnimationFillMode(); + break; + case CSSPropertyAnimationIterationCount: + case CSSPropertyWebkitAnimationIterationCount: + value = parseAnimationIterationCount(); + break; + case CSSPropertyAnimationName: + case CSSPropertyWebkitAnimationName: + value = parseAnimationName(); + break; + case CSSPropertyAnimationPlayState: + case CSSPropertyWebkitAnimationPlayState: + value = parseAnimationPlayState(); + break; + case CSSPropertyTransitionProperty: + case CSSPropertyWebkitTransitionProperty: + value = parseAnimationProperty(); + break; + case CSSPropertyAnimationTimingFunction: + case CSSPropertyWebkitAnimationTimingFunction: + case CSSPropertyTransitionTimingFunction: + case CSSPropertyWebkitTransitionTimingFunction: + value = parseAnimationTimingFunction(); + break; + default: + ASSERT_NOT_REACHED(); + return nullptr; + } - result = 0; + if (value) + m_valueList->next(); + return value.release(); +} - while ((val = m_valueList->current())) { - RefPtr<CSSValue> currValue; - if (allowComma) { - if (!isComma(val)) - return false; +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseAnimationPropertyList(CSSPropertyID propId) +{ + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + while (m_valueList->current()) { + RefPtrWillBeRawPtr<CSSValue> value = parseAnimationProperty(propId); + if (!value) + return nullptr; + list->append(value.release()); + if (CSSParserValue* parserValue = m_valueList->current()) { + if (!isComma(parserValue)) + return nullptr; m_valueList->next(); - allowComma = false; - } - else { - switch (propId) { - case CSSPropertyAnimationDelay: - case CSSPropertyWebkitAnimationDelay: - case CSSPropertyTransitionDelay: - case CSSPropertyWebkitTransitionDelay: - currValue = parseAnimationDelay(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationDirection: - case CSSPropertyWebkitAnimationDirection: - currValue = parseAnimationDirection(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationDuration: - case CSSPropertyWebkitAnimationDuration: - case CSSPropertyTransitionDuration: - case CSSPropertyWebkitTransitionDuration: - currValue = parseAnimationDuration(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationFillMode: - case CSSPropertyWebkitAnimationFillMode: - currValue = parseAnimationFillMode(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationIterationCount: - case CSSPropertyWebkitAnimationIterationCount: - currValue = parseAnimationIterationCount(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationName: - case CSSPropertyWebkitAnimationName: - currValue = parseAnimationName(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationPlayState: - case CSSPropertyWebkitAnimationPlayState: - currValue = parseAnimationPlayState(); - if (currValue) - m_valueList->next(); - break; - case CSSPropertyTransitionProperty: - case CSSPropertyWebkitTransitionProperty: - currValue = parseAnimationProperty(context); - if (value && !context.animationPropertyKeywordAllowed()) - return false; - if (currValue) - m_valueList->next(); - break; - case CSSPropertyAnimationTimingFunction: - case CSSPropertyWebkitAnimationTimingFunction: - case CSSPropertyTransitionTimingFunction: - case CSSPropertyWebkitTransitionTimingFunction: - currValue = parseAnimationTimingFunction(); - if (currValue) - m_valueList->next(); - break; - default: - ASSERT_NOT_REACHED(); - return false; - } - - if (!currValue) - return false; - - if (value && !values) { - values = CSSValueList::createCommaSeparated(); - values->append(value.release()); - } - - if (values) - values->append(currValue.release()); - else - value = currValue.release(); - - allowComma = true; + ASSERT(m_valueList->current()); } - - // When parsing the 'transition' shorthand property, we let it handle building up the lists for all - // properties. - if (inShorthand()) - break; } + if ((propId == CSSPropertyTransitionProperty || propId == CSSPropertyWebkitTransitionProperty) && !isValidTransitionPropertyList(list.get())) + return nullptr; + ASSERT(list->length()); + return list.release(); +} - if (values && values->length()) { - result = values.release(); - return true; - } - if (value) { - result = value.release(); - return true; - } - return false; +static inline bool isCSSWideKeyword(CSSParserValue& value) +{ + return value.id == CSSValueInitial || value.id == CSSValueInherit || value.id == CSSValueDefault; +} + +static inline bool isValidCustomIdentForGridPositions(CSSParserValue& value) +{ + // FIXME: we need a more general solution for <custom-ident> in all properties. + return value.unit == CSSPrimitiveValue::CSS_IDENT && value.id != CSSValueSpan && value.id != CSSValueAuto && !isCSSWideKeyword(value); } -// The function parses [ <integer> || <string> ] in <grid-line> (which can be stand alone or with 'span'). -bool CSSParser::parseIntegerOrStringFromGridPosition(RefPtr<CSSPrimitiveValue>& numericValue, RefPtr<CSSPrimitiveValue>& gridLineName) +// The function parses [ <integer> || <custom-ident> ] in <grid-line> (which can be stand alone or with 'span'). +bool CSSPropertyParser::parseIntegerOrCustomIdentFromGridPosition(RefPtrWillBeRawPtr<CSSPrimitiveValue>& numericValue, RefPtrWillBeRawPtr<CSSPrimitiveValue>& gridLineName) { CSSParserValue* value = m_valueList->current(); if (validUnit(value, FInteger) && value->fValue) { numericValue = createPrimitiveNumericValue(value); value = m_valueList->next(); - if (value && value->unit == CSSPrimitiveValue::CSS_STRING) { + if (value && isValidCustomIdentForGridPositions(*value)) { gridLineName = createPrimitiveStringValue(m_valueList->current()); m_valueList->next(); } return true; } - if (value->unit == CSSPrimitiveValue::CSS_STRING) { + if (isValidCustomIdentForGridPositions(*value)) { gridLineName = createPrimitiveStringValue(m_valueList->current()); value = m_valueList->next(); if (value && validUnit(value, FInteger) && value->fValue) { @@ -4573,7 +3323,7 @@ bool CSSParser::parseIntegerOrStringFromGridPosition(RefPtr<CSSPrimitiveValue>& return false; } -PassRefPtr<CSSValue> CSSParser::parseGridPosition() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridPosition() { ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); @@ -4583,16 +3333,11 @@ PassRefPtr<CSSValue> CSSParser::parseGridPosition() return cssValuePool().createIdentifierValue(CSSValueAuto); } - if (value->id != CSSValueSpan && value->unit == CSSPrimitiveValue::CSS_IDENT) { - m_valueList->next(); - return cssValuePool().createValue(value->string, CSSPrimitiveValue::CSS_STRING); - } - - RefPtr<CSSPrimitiveValue> numericValue; - RefPtr<CSSPrimitiveValue> gridLineName; + RefPtrWillBeRawPtr<CSSPrimitiveValue> numericValue = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> gridLineName = nullptr; bool hasSeenSpanKeyword = false; - if (parseIntegerOrStringFromGridPosition(numericValue, gridLineName)) { + if (parseIntegerOrCustomIdentFromGridPosition(numericValue, gridLineName)) { value = m_valueList->current(); if (value && value->id == CSSValueSpan) { hasSeenSpanKeyword = true; @@ -4600,24 +3345,30 @@ PassRefPtr<CSSValue> CSSParser::parseGridPosition() } } else if (value->id == CSSValueSpan) { hasSeenSpanKeyword = true; - if (m_valueList->next()) - parseIntegerOrStringFromGridPosition(numericValue, gridLineName); + if (CSSParserValue* nextValue = m_valueList->next()) { + if (!isForwardSlashOperator(nextValue) && !parseIntegerOrCustomIdentFromGridPosition(numericValue, gridLineName)) + return nullptr; + } } // Check that we have consumed all the value list. For shorthands, the parser will pass // the whole value list (including the opposite position). if (m_valueList->current() && !isForwardSlashOperator(m_valueList->current())) - return 0; + return nullptr; // If we didn't parse anything, this is not a valid grid position. if (!hasSeenSpanKeyword && !gridLineName && !numericValue) - return 0; + return nullptr; // Negative numbers are not allowed for span (but are for <integer>). if (hasSeenSpanKeyword && numericValue && numericValue->getIntValue() < 0) - return 0; + return nullptr; - RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); + // For the <custom-ident> case. + if (gridLineName && !numericValue && !hasSeenSpanKeyword) + return cssValuePool().createValue(gridLineName->getStringValue(), CSSPrimitiveValue::CSS_STRING); + + RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); if (hasSeenSpanKeyword) values->append(cssValuePool().createIdentifierValue(CSSValueSpan)); if (numericValue) @@ -4628,7 +3379,7 @@ PassRefPtr<CSSValue> CSSParser::parseGridPosition() return values.release(); } -static PassRefPtr<CSSValue> gridMissingGridPositionValue(CSSValue* value) +static PassRefPtrWillBeRawPtr<CSSValue> gridMissingGridPositionValue(CSSValue* value) { if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->isString()) return value; @@ -4636,17 +3387,17 @@ static PassRefPtr<CSSValue> gridMissingGridPositionValue(CSSValue* value) return cssValuePool().createIdentifierValue(CSSValueAuto); } -bool CSSParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool important) +bool CSSPropertyParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool important) { ShorthandScope scope(this, shorthandId); const StylePropertyShorthand& shorthand = shorthandForProperty(shorthandId); ASSERT(shorthand.length() == 2); - RefPtr<CSSValue> startValue = parseGridPosition(); + RefPtrWillBeRawPtr<CSSValue> startValue = parseGridPosition(); if (!startValue) return false; - RefPtr<CSSValue> endValue; + RefPtrWillBeRawPtr<CSSValue> endValue = nullptr; if (m_valueList->current()) { if (!isForwardSlashOperator(m_valueList->current())) return false; @@ -4666,7 +3417,186 @@ bool CSSParser::parseGridItemPositionShorthand(CSSPropertyID shorthandId, bool i return true; } -bool CSSParser::parseGridAreaShorthand(bool important) +bool CSSPropertyParser::parseGridTemplateRowsAndAreas(PassRefPtrWillBeRawPtr<CSSValue> templateColumns, bool important) +{ + NamedGridAreaMap gridAreaMap; + size_t rowCount = 0; + size_t columnCount = 0; + bool trailingIdentWasAdded = false; + RefPtrWillBeRawPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated(); + + // At least template-areas strings must be defined. + if (!m_valueList->current()) + return false; + + while (m_valueList->current()) { + // Handle leading <custom-ident>*. + if (m_valueList->current()->unit == CSSParserValue::ValueList) { + if (trailingIdentWasAdded) { + // A row's trailing ident must be concatenated with the next row's leading one. + parseGridLineNames(*m_valueList, *templateRows, static_cast<CSSGridLineNamesValue*>(templateRows->item(templateRows->length() - 1))); + } else { + parseGridLineNames(*m_valueList, *templateRows); + } + } + + // Handle a template-area's row. + if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount)) + return false; + ++rowCount; + + // Handle template-rows's track-size. + if (m_valueList->current() && m_valueList->current()->unit != CSSParserValue::ValueList && m_valueList->current()->unit != CSSPrimitiveValue::CSS_STRING) { + RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList); + if (!value) + return false; + templateRows->append(value); + } else { + templateRows->append(cssValuePool().createIdentifierValue(CSSValueAuto)); + } + + // This will handle the trailing/leading <custom-ident>* in the grammar. + trailingIdentWasAdded = false; + if (m_valueList->current() && m_valueList->current()->unit == CSSParserValue::ValueList) { + parseGridLineNames(*m_valueList, *templateRows); + trailingIdentWasAdded = true; + } + } + + // [<track-list> /]? + if (templateColumns) + addProperty(CSSPropertyGridTemplateColumns, templateColumns, important); + else + addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important); + + // [<line-names>? <string> [<track-size> <line-names>]? ]+ + RefPtrWillBeRawPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount); + addProperty(CSSPropertyGridTemplateAreas, templateAreas.release(), important); + addProperty(CSSPropertyGridTemplateRows, templateRows.release(), important); + + + return true; +} + + +bool CSSPropertyParser::parseGridTemplateShorthand(bool important) +{ + ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); + + ShorthandScope scope(this, CSSPropertyGridTemplate); + ASSERT(gridTemplateShorthand().length() == 3); + + // At least "none" must be defined. + if (!m_valueList->current()) + return false; + + bool firstValueIsNone = m_valueList->current()->id == CSSValueNone; + + // 1- 'none' case. + if (firstValueIsNone && !m_valueList->next()) { + addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentifierValue(CSSValueNone), important); + addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifierValue(CSSValueNone), important); + addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important); + return true; + } + + unsigned index = 0; + RefPtrWillBeRawPtr<CSSValue> columnsValue = nullptr; + if (firstValueIsNone) { + columnsValue = cssValuePool().createIdentifierValue(CSSValueNone); + } else { + columnsValue = parseGridTrackList(important); + } + + // 2- <grid-template-columns> / <grid-template-columns> syntax. + if (columnsValue) { + if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current()) && m_valueList->next())) + return false; + index = m_valueList->currentIndex(); + if (RefPtrWillBeRawPtr<CSSValue> rowsValue = parseGridTrackList(important)) { + if (m_valueList->current()) + return false; + addProperty(CSSPropertyGridTemplateColumns, columnsValue, important); + addProperty(CSSPropertyGridTemplateRows, rowsValue, important); + addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifierValue(CSSValueNone), important); + return true; + } + } + + + // 3- [<track-list> /]? [<line-names>? <string> [<track-size> <line-names>]? ]+ syntax. + // The template-columns <track-list> can't be 'none'. + if (firstValueIsNone) + return false; + // It requires to rewind parsing due to previous syntax failures. + m_valueList->setCurrentIndex(index); + return parseGridTemplateRowsAndAreas(columnsValue, important); +} + +bool CSSPropertyParser::parseGridShorthand(bool important) +{ + ShorthandScope scope(this, CSSPropertyGrid); + ASSERT(shorthandForProperty(CSSPropertyGrid).length() == 4); + + // 1- <grid-template> + if (parseGridTemplateShorthand(important)) { + // It can only be specified the explicit or the implicit grid properties in a single grid declaration. + // The sub-properties not specified are set to their initial value, as normal for shorthands. + addProperty(CSSPropertyGridAutoFlow, cssValuePool().createImplicitInitialValue(), important); + addProperty(CSSPropertyGridAutoColumns, cssValuePool().createImplicitInitialValue(), important); + addProperty(CSSPropertyGridAutoRows, cssValuePool().createImplicitInitialValue(), important); + return true; + } + + // Need to rewind parsing to explore the alternative syntax of this shorthand. + m_valueList->setCurrentIndex(0); + + // 2- <grid-auto-flow> [ <grid-auto-columns> [ / <grid-auto-rows> ]? ] + CSSValueID id = m_valueList->current()->id; + if (id != CSSValueRow && id != CSSValueColumn && id != CSSValueNone) + return false; + + RefPtrWillBeRawPtr<CSSValue> autoFlowValue = cssValuePool().createIdentifierValue(id); + RefPtrWillBeRawPtr<CSSValue> autoColumnsValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> autoRowsValue = nullptr; + + if (m_valueList->next()) { + autoColumnsValue = parseGridTrackSize(*m_valueList); + if (!autoColumnsValue) + return false; + if (m_valueList->current()) { + if (!isForwardSlashOperator(m_valueList->current()) || !m_valueList->next()) + return false; + autoRowsValue = parseGridTrackSize(*m_valueList); + if (!autoRowsValue) + return false; + } + if (m_valueList->current()) + return false; + } else { + // Other omitted values are set to their initial values. + autoColumnsValue = cssValuePool().createImplicitInitialValue(); + autoRowsValue = cssValuePool().createImplicitInitialValue(); + } + + // if <grid-auto-rows> value is omitted, it is set to the value specified for grid-auto-columns. + if (!autoRowsValue) + autoRowsValue = autoColumnsValue; + + addProperty(CSSPropertyGridAutoFlow, autoFlowValue, important); + addProperty(CSSPropertyGridAutoColumns, autoColumnsValue, important); + addProperty(CSSPropertyGridAutoRows, autoRowsValue, important); + + // It can only be specified the explicit or the implicit grid properties in a single grid declaration. + // The sub-properties not specified are set to their initial value, as normal for shorthands. + addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createImplicitInitialValue(), important); + addProperty(CSSPropertyGridTemplateRows, cssValuePool().createImplicitInitialValue(), important); + addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createImplicitInitialValue(), important); + + return true; +} + +bool CSSPropertyParser::parseGridAreaShorthand(bool important) { ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); @@ -4674,19 +3604,19 @@ bool CSSParser::parseGridAreaShorthand(bool important) const StylePropertyShorthand& shorthand = gridAreaShorthand(); ASSERT_UNUSED(shorthand, shorthand.length() == 4); - RefPtr<CSSValue> rowStartValue = parseGridPosition(); + RefPtrWillBeRawPtr<CSSValue> rowStartValue = parseGridPosition(); if (!rowStartValue) return false; - RefPtr<CSSValue> columnStartValue; + RefPtrWillBeRawPtr<CSSValue> columnStartValue = nullptr; if (!parseSingleGridAreaLonghand(columnStartValue)) return false; - RefPtr<CSSValue> rowEndValue; + RefPtrWillBeRawPtr<CSSValue> rowEndValue = nullptr; if (!parseSingleGridAreaLonghand(rowEndValue)) return false; - RefPtr<CSSValue> columnEndValue; + RefPtrWillBeRawPtr<CSSValue> columnEndValue = nullptr; if (!parseSingleGridAreaLonghand(columnEndValue)) return false; @@ -4706,7 +3636,7 @@ bool CSSParser::parseGridAreaShorthand(bool important) return true; } -bool CSSParser::parseSingleGridAreaLonghand(RefPtr<CSSValue>& property) +bool CSSPropertyParser::parseSingleGridAreaLonghand(RefPtrWillBeRawPtr<CSSValue>& property) { if (!m_valueList->current()) return true; @@ -4721,75 +3651,79 @@ bool CSSParser::parseSingleGridAreaLonghand(RefPtr<CSSValue>& property) return true; } -void CSSParser::parseGridLineNames(CSSParserValueList* parserValueList, CSSValueList& valueList) +void CSSPropertyParser::parseGridLineNames(CSSParserValueList& inputList, CSSValueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames) { - ASSERT(parserValueList->current() && parserValueList->current()->unit == CSSParserValue::ValueList); + ASSERT(inputList.current() && inputList.current()->unit == CSSParserValue::ValueList); - CSSParserValueList* identList = parserValueList->current()->valueList; + CSSParserValueList* identList = inputList.current()->valueList; if (!identList->size()) { - parserValueList->next(); + inputList.next(); return; } - RefPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create(); + // Need to ensure the identList is at the heading index, since the parserList might have been rewound. + identList->setCurrentIndex(0); + + RefPtrWillBeRawPtr<CSSGridLineNamesValue> lineNames = previousNamedAreaTrailingLineNames; + if (!lineNames) + lineNames = CSSGridLineNamesValue::create(); while (CSSParserValue* identValue = identList->current()) { ASSERT(identValue->unit == CSSPrimitiveValue::CSS_IDENT); - RefPtr<CSSPrimitiveValue> lineName = createPrimitiveStringValue(identValue); + RefPtrWillBeRawPtr<CSSPrimitiveValue> lineName = createPrimitiveStringValue(identValue); lineNames->append(lineName.release()); identList->next(); } - valueList.append(lineNames.release()); + if (!previousNamedAreaTrailingLineNames) + valueList.append(lineNames.release()); - parserValueList->next(); + inputList.next(); } -bool CSSParser::parseGridTrackList(CSSPropertyID propId, bool important) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackList(bool important) { ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); CSSParserValue* value = m_valueList->current(); if (value->id == CSSValueNone) { - if (m_valueList->next()) - return false; - - addProperty(propId, cssValuePool().createIdentifierValue(value->id), important); - return true; + m_valueList->next(); + return cssValuePool().createIdentifierValue(CSSValueNone); } - RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); // Handle leading <ident>*. value = m_valueList->current(); if (value && value->unit == CSSParserValue::ValueList) - parseGridLineNames(m_valueList.get(), *values); + parseGridLineNames(*m_valueList, *values); bool seenTrackSizeOrRepeatFunction = false; while (CSSParserValue* currentValue = m_valueList->current()) { + if (isForwardSlashOperator(currentValue)) + break; if (currentValue->unit == CSSParserValue::Function && equalIgnoringCase(currentValue->function->name, "repeat(")) { if (!parseGridTrackRepeatFunction(*values)) - return false; + return nullptr; seenTrackSizeOrRepeatFunction = true; } else { - RefPtr<CSSValue> value = parseGridTrackSize(*m_valueList); + RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList); if (!value) - return false; + return nullptr; values->append(value); seenTrackSizeOrRepeatFunction = true; } // This will handle the trailing <ident>* in the grammar. value = m_valueList->current(); if (value && value->unit == CSSParserValue::ValueList) - parseGridLineNames(m_valueList.get(), *values); + parseGridLineNames(*m_valueList, *values); } // We should have found a <track-size> or else it is not a valid <track-list> if (!seenTrackSizeOrRepeatFunction) - return false; + return nullptr; - addProperty(propId, values.release(), important); - return true; + return values; } -bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list) +bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list) { CSSParserValueList* arguments = m_valueList->current()->function->args.get(); if (!arguments || arguments->size() < 3 || !validUnit(arguments->valueAt(0), FPositiveInteger) || !isComma(arguments->valueAt(1))) @@ -4797,17 +3731,21 @@ bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list) ASSERT_WITH_SECURITY_IMPLICATION(arguments->valueAt(0)->fValue > 0); size_t repetitions = arguments->valueAt(0)->fValue; - RefPtr<CSSValueList> repeatedValues = CSSValueList::createSpaceSeparated(); + // Clamp repetitions at minRepetitions. + // http://www.w3.org/TR/css-grid-1/#repeat-notation + if (repetitions > minRepetitions) + repetitions = minRepetitions; + RefPtrWillBeRawPtr<CSSValueList> repeatedValues = CSSValueList::createSpaceSeparated(); arguments->next(); // Skip the repetition count. arguments->next(); // Skip the comma. // Handle leading <ident>*. CSSParserValue* currentValue = arguments->current(); if (currentValue && currentValue->unit == CSSParserValue::ValueList) - parseGridLineNames(arguments, *repeatedValues); + parseGridLineNames(*arguments, *repeatedValues); while (arguments->current()) { - RefPtr<CSSValue> trackSize = parseGridTrackSize(*arguments); + RefPtrWillBeRawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments); if (!trackSize) return false; @@ -4816,7 +3754,7 @@ bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list) // This takes care of any trailing <ident>* in the grammar. currentValue = arguments->current(); if (currentValue && currentValue->unit == CSSParserValue::ValueList) - parseGridLineNames(arguments, *repeatedValues); + parseGridLineNames(*arguments, *repeatedValues); } for (size_t i = 0; i < repetitions; ++i) { @@ -4829,7 +3767,8 @@ bool CSSParser::parseGridTrackRepeatFunction(CSSValueList& list) return true; } -PassRefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList) + +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParserValueList& inputList) { ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); @@ -4843,17 +3782,17 @@ PassRefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList // The spec defines the following grammar: minmax( <track-breadth> , <track-breadth> ) CSSParserValueList* arguments = currentValue->function->args.get(); if (!arguments || arguments->size() != 3 || !isComma(arguments->valueAt(1))) - return 0; + return nullptr; - RefPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(arguments->valueAt(0)); + RefPtrWillBeRawPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(arguments->valueAt(0)); if (!minTrackBreadth) - return 0; + return nullptr; - RefPtr<CSSPrimitiveValue> maxTrackBreadth = parseGridBreadth(arguments->valueAt(2)); + RefPtrWillBeRawPtr<CSSPrimitiveValue> maxTrackBreadth = parseGridBreadth(arguments->valueAt(2)); if (!maxTrackBreadth) - return 0; + return nullptr; - RefPtr<CSSValueList> parsedArguments = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> parsedArguments = CSSValueList::createCommaSeparated(); parsedArguments->append(minTrackBreadth); parsedArguments->append(maxTrackBreadth); return CSSFunctionValue::create("minmax(", parsedArguments); @@ -4862,7 +3801,7 @@ PassRefPtr<CSSValue> CSSParser::parseGridTrackSize(CSSParserValueList& inputList return parseGridBreadth(currentValue); } -PassRefPtr<CSSPrimitiveValue> CSSParser::parseGridBreadth(CSSParserValue* currentValue) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseGridBreadth(CSSParserValue* currentValue) { if (currentValue->id == CSSValueMinContent || currentValue->id == CSSValueMaxContent) return cssValuePool().createIdentifierValue(currentValue->id); @@ -4872,135 +3811,143 @@ PassRefPtr<CSSPrimitiveValue> CSSParser::parseGridBreadth(CSSParserValue* curren // Fractional unit is a non-negative dimension. if (flexValue <= 0) - return 0; + return nullptr; return cssValuePool().createValue(flexValue, CSSPrimitiveValue::CSS_FR); } if (!validUnit(currentValue, FNonNeg | FLength | FPercent)) - return 0; + return nullptr; return createPrimitiveNumericValue(currentValue); } -PassRefPtr<CSSValue> CSSParser::parseGridTemplate() +bool CSSPropertyParser::parseGridTemplateAreasRow(NamedGridAreaMap& gridAreaMap, const size_t rowCount, size_t& columnCount) { - NamedGridAreaMap gridAreaMap; - size_t rowCount = 0; - size_t columnCount = 0; - - while (CSSParserValue* currentValue = m_valueList->current()) { - if (currentValue->unit != CSSPrimitiveValue::CSS_STRING) - return 0; + CSSParserValue* currentValue = m_valueList->current(); + if (!currentValue || currentValue->unit != CSSPrimitiveValue::CSS_STRING) + return false; - String gridRowNames = currentValue->string; - if (!gridRowNames.length()) - return 0; + String gridRowNames = currentValue->string; + if (!gridRowNames.length()) + return false; - Vector<String> columnNames; - gridRowNames.split(' ', columnNames); + Vector<String> columnNames; + gridRowNames.split(' ', columnNames); - if (!columnCount) { - columnCount = columnNames.size(); - ASSERT(columnCount); - } else if (columnCount != columnNames.size()) { - // The declaration is invalid is all the rows don't have the number of columns. - return 0; - } + if (!columnCount) { + columnCount = columnNames.size(); + ASSERT(columnCount); + } else if (columnCount != columnNames.size()) { + // The declaration is invalid is all the rows don't have the number of columns. + return false; + } - for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) { - const String& gridAreaName = columnNames[currentCol]; + for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) { + const String& gridAreaName = columnNames[currentCol]; - // Unamed areas are always valid (we consider them to be 1x1). - if (gridAreaName == ".") - continue; + // Unamed areas are always valid (we consider them to be 1x1). + if (gridAreaName == ".") + continue; - // We handle several grid areas with the same name at once to simplify the validation code. - size_t lookAheadCol; - for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) { - if (columnNames[lookAheadCol + 1] != gridAreaName) - break; - } + // We handle several grid areas with the same name at once to simplify the validation code. + size_t lookAheadCol; + for (lookAheadCol = currentCol; lookAheadCol < (columnCount - 1); ++lookAheadCol) { + if (columnNames[lookAheadCol + 1] != gridAreaName) + break; + } - NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName); - if (gridAreaIt == gridAreaMap.end()) { - gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol))); - } else { - GridCoordinate& gridCoordinate = gridAreaIt->value; + NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName); + if (gridAreaIt == gridAreaMap.end()) { + gridAreaMap.add(gridAreaName, GridCoordinate(GridSpan(rowCount, rowCount), GridSpan(currentCol, lookAheadCol))); + } else { + GridCoordinate& gridCoordinate = gridAreaIt->value; - // The following checks test that the grid area is a single filled-in rectangle. - // 1. The new row is adjacent to the previously parsed row. - if (rowCount != gridCoordinate.rows.initialPositionIndex + 1) - return 0; + // The following checks test that the grid area is a single filled-in rectangle. + // 1. The new row is adjacent to the previously parsed row. + if (rowCount != gridCoordinate.rows.resolvedFinalPosition.next().toInt()) + return false; - // 2. The new area starts at the same position as the previously parsed area. - if (currentCol != gridCoordinate.columns.initialPositionIndex) - return 0; + // 2. The new area starts at the same position as the previously parsed area. + if (currentCol != gridCoordinate.columns.resolvedInitialPosition.toInt()) + return false; - // 3. The new area ends at the same position as the previously parsed area. - if (lookAheadCol != gridCoordinate.columns.finalPositionIndex) - return 0; + // 3. The new area ends at the same position as the previously parsed area. + if (lookAheadCol != gridCoordinate.columns.resolvedFinalPosition.toInt()) + return false; - ++gridCoordinate.rows.finalPositionIndex; - } - currentCol = lookAheadCol; + ++gridCoordinate.rows.resolvedFinalPosition; } + currentCol = lookAheadCol; + } + + m_valueList->next(); + return true; +} +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTemplateAreas() +{ + NamedGridAreaMap gridAreaMap; + size_t rowCount = 0; + size_t columnCount = 0; + + while (m_valueList->current()) { + if (!parseGridTemplateAreasRow(gridAreaMap, rowCount, columnCount)) + return nullptr; ++rowCount; - m_valueList->next(); } if (!rowCount || !columnCount) - return 0; + return nullptr; - return CSSGridTemplateValue::create(gridAreaMap, rowCount, columnCount); + return CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount); } -PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bool counters) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseCounterContent(CSSParserValueList* args, bool counters) { unsigned numArgs = args->size(); if (counters && numArgs != 3 && numArgs != 5) - return 0; + return nullptr; if (!counters && numArgs != 1 && numArgs != 3) - return 0; + return nullptr; CSSParserValue* i = args->current(); if (i->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; - RefPtr<CSSPrimitiveValue> identifier = createPrimitiveStringValue(i); + return nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> identifier = createPrimitiveStringValue(i); - RefPtr<CSSPrimitiveValue> separator; + RefPtrWillBeRawPtr<CSSPrimitiveValue> separator = nullptr; if (!counters) separator = cssValuePool().createValue(String(), CSSPrimitiveValue::CSS_STRING); else { i = args->next(); if (i->unit != CSSParserValue::Operator || i->iValue != ',') - return 0; + return nullptr; i = args->next(); if (i->unit != CSSPrimitiveValue::CSS_STRING) - return 0; + return nullptr; separator = createPrimitiveStringValue(i); } - RefPtr<CSSPrimitiveValue> listStyle; + RefPtrWillBeRawPtr<CSSPrimitiveValue> listStyle = nullptr; i = args->next(); if (!i) // Make the list style default decimal listStyle = cssValuePool().createIdentifierValue(CSSValueDecimal); else { if (i->unit != CSSParserValue::Operator || i->iValue != ',') - return 0; + return nullptr; i = args->next(); if (i->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; + return nullptr; CSSValueID listStyleID = CSSValueInvalid; if (i->id == CSSValueNone || (i->id >= CSSValueDisc && i->id <= CSSValueKatakanaIroha)) listStyleID = i->id; else - return 0; + return nullptr; listStyle = cssValuePool().createIdentifierValue(listStyleID); } @@ -5008,7 +3955,7 @@ PassRefPtr<CSSValue> CSSParser::parseCounterContent(CSSParserValueList* args, bo return cssValuePool().createValue(Counter::create(identifier.release(), listStyle.release(), separator.release())); } -bool CSSParser::parseClipShape(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseClipShape(CSSPropertyID propId, bool important) { CSSParserValue* value = m_valueList->current(); CSSParserValueList* args = value->function->args.get(); @@ -5019,7 +3966,7 @@ bool CSSParser::parseClipShape(CSSPropertyID propId, bool important) // rect(t, r, b, l) || rect(t r b l) if (args->size() != 4 && args->size() != 7) return false; - RefPtr<Rect> rect = Rect::create(); + RefPtrWillBeRawPtr<Rect> rect = Rect::create(); bool valid = true; int i = 0; CSSParserValue* a = args->current(); @@ -5027,7 +3974,7 @@ bool CSSParser::parseClipShape(CSSPropertyID propId, bool important) valid = a->id == CSSValueAuto || validUnit(a, FLength); if (!valid) break; - RefPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ? + RefPtrWillBeRawPtr<CSSPrimitiveValue> length = a->id == CSSValueAuto ? cssValuePool().createIdentifierValue(CSSValueAuto) : createPrimitiveNumericValue(a); if (i == 0) @@ -5057,235 +4004,316 @@ bool CSSParser::parseClipShape(CSSPropertyID propId, bool important) return false; } -PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeRectangle(CSSParserValueList* args) +static void completeBorderRadii(RefPtrWillBeRawPtr<CSSPrimitiveValue> radii[4]) { - ASSERT(args); + if (radii[3]) + return; + if (!radii[2]) { + if (!radii[1]) + radii[1] = radii[0]; + radii[2] = radii[0]; + } + radii[3] = radii[1]; +} - // rect(x, y, width, height, [[rx], ry]) - if (args->size() != 7 && args->size() != 9 && args->size() != 11) - return 0; +// FIXME: This should be refactored with CSSParser::parseBorderRadius. +// CSSParser::parseBorderRadius contains support for some legacy radius construction. +PassRefPtrWillBeRawPtr<CSSBasicShape> CSSPropertyParser::parseInsetRoundedCorners(PassRefPtrWillBeRawPtr<CSSBasicShapeInset> shape, CSSParserValueList* args) +{ + CSSParserValue* argument = args->next(); - RefPtr<CSSBasicShapeRectangle> shape = CSSBasicShapeRectangle::create(); + if (!argument) + return nullptr; - unsigned argumentNumber = 0; - CSSParserValue* argument = args->current(); + Vector<CSSParserValue*> radiusArguments; while (argument) { - Units unitFlags = FLength | FPercent; - if (argumentNumber > 1) { - // Arguments width, height, rx, and ry cannot be negative. - unitFlags = unitFlags | FNonNeg; - } - if (!validUnit(argument, unitFlags)) - return 0; - - RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument); - ASSERT(argumentNumber < 6); - switch (argumentNumber) { - case 0: - shape->setX(length); - break; - case 1: - shape->setY(length); - break; - case 2: - shape->setWidth(length); - break; - case 3: - shape->setHeight(length); - break; - case 4: - shape->setRadiusX(length); - break; - case 5: - shape->setRadiusY(length); - break; - } + radiusArguments.append(argument); argument = args->next(); - if (argument) { - if (!isComma(argument)) - return 0; + } - argument = args->next(); + unsigned num = radiusArguments.size(); + if (!num || num > 9) + return nullptr; + + // FIXME: Refactor completeBorderRadii and the array + RefPtrWillBeRawPtr<CSSPrimitiveValue> radii[2][4]; +#if ENABLE(OILPAN) + // Zero initialize the array of raw pointers. + memset(&radii, 0, sizeof(radii)); +#endif + + unsigned indexAfterSlash = 0; + for (unsigned i = 0; i < num; ++i) { + CSSParserValue* value = radiusArguments.at(i); + if (value->unit == CSSParserValue::Operator) { + if (value->iValue != '/') + return nullptr; + + if (!i || indexAfterSlash || i + 1 == num) + return nullptr; + + indexAfterSlash = i + 1; + completeBorderRadii(radii[0]); + continue; } - argumentNumber++; + + if (i - indexAfterSlash >= 4) + return nullptr; + + if (!validUnit(value, FLength | FPercent | FNonNeg)) + return nullptr; + + RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value); + + if (!indexAfterSlash) + radii[0][i] = radius; + else + radii[1][i - indexAfterSlash] = radius.release(); } - if (argumentNumber < 4) - return 0; + if (!indexAfterSlash) { + completeBorderRadii(radii[0]); + for (unsigned i = 0; i < 4; ++i) + radii[1][i] = radii[0][i]; + } else { + completeBorderRadii(radii[1]); + } + shape->setTopLeftRadius(createPrimitiveValuePair(radii[0][0].release(), radii[1][0].release())); + shape->setTopRightRadius(createPrimitiveValuePair(radii[0][1].release(), radii[1][1].release())); + shape->setBottomRightRadius(createPrimitiveValuePair(radii[0][2].release(), radii[1][2].release())); + shape->setBottomLeftRadius(createPrimitiveValuePair(radii[0][3].release(), radii[1][3].release())); + return shape; } -PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeInsetRectangle(CSSParserValueList* args) +PassRefPtrWillBeRawPtr<CSSBasicShape> CSSPropertyParser::parseBasicShapeInset(CSSParserValueList* args) { ASSERT(args); - // inset-rectangle(top, right, bottom, left, [[rx], ry]) - if (args->size() != 7 && args->size() != 9 && args->size() != 11) - return 0; - - RefPtr<CSSBasicShapeInsetRectangle> shape = CSSBasicShapeInsetRectangle::create(); + RefPtrWillBeRawPtr<CSSBasicShapeInset> shape = CSSBasicShapeInset::create(); - unsigned argumentNumber = 0; CSSParserValue* argument = args->current(); + WillBeHeapVector<RefPtrWillBeMember<CSSPrimitiveValue> > widthArguments; + bool hasRoundedInset = false; + while (argument) { - Units unitFlags = FLength | FPercent | FNonNeg; - if (!validUnit(argument, unitFlags)) - return 0; - - RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument); - ASSERT(argumentNumber < 6); - switch (argumentNumber) { - case 0: - shape->setTop(length); - break; - case 1: - shape->setRight(length); - break; - case 2: - shape->setBottom(length); - break; - case 3: - shape->setLeft(length); - break; - case 4: - shape->setRadiusX(length); - break; - case 5: - shape->setRadiusY(length); + if (argument->unit == CSSPrimitiveValue::CSS_IDENT && equalIgnoringCase(argument->string, "round")) { + hasRoundedInset = true; break; } + + Units unitFlags = FLength | FPercent; + if (!validUnit(argument, unitFlags) || widthArguments.size() > 4) + return nullptr; + + widthArguments.append(createPrimitiveNumericValue(argument)); argument = args->next(); - if (argument) { - if (!isComma(argument)) - return 0; + } - argument = args->next(); + switch (widthArguments.size()) { + case 1: { + shape->updateShapeSize1Value(widthArguments[0].get()); + break; + } + case 2: { + shape->updateShapeSize2Values(widthArguments[0].get(), widthArguments[1].get()); + break; } - argumentNumber++; + case 3: { + shape->updateShapeSize3Values(widthArguments[0].get(), widthArguments[1].get(), widthArguments[2].get()); + break; + } + case 4: { + shape->updateShapeSize4Values(widthArguments[0].get(), widthArguments[1].get(), widthArguments[2].get(), widthArguments[3].get()); + break; + } + default: + return nullptr; } - if (argumentNumber < 4) - return 0; + if (hasRoundedInset) + return parseInsetRoundedCorners(shape, args); return shape; } -PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeCircle(CSSParserValueList* args) +static bool isItemPositionKeyword(CSSValueID id) { - ASSERT(args); + return id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter + || id == CSSValueSelfStart || id == CSSValueSelfEnd || id == CSSValueFlexStart + || id == CSSValueFlexEnd || id == CSSValueLeft || id == CSSValueRight; +} - // circle(centerX, centerY, radius) - if (args->size() != 5) - return 0; +bool CSSPropertyParser::parseItemPositionOverflowPosition(CSSPropertyID propId, bool important) +{ + // auto | baseline | stretch | [<item-position> && <overflow-position>? ] + // <item-position> = center | start | end | self-start | self-end | flex-start | flex-end | left | right; + // <overflow-position> = true | safe - RefPtr<CSSBasicShapeCircle> shape = CSSBasicShapeCircle::create(); + CSSParserValue* value = m_valueList->current(); - unsigned argumentNumber = 0; - CSSParserValue* argument = args->current(); - while (argument) { - Units unitFlags = FLength | FPercent; - if (argumentNumber == 2) { - // Argument radius cannot be negative. - unitFlags = unitFlags | FNonNeg; + if (value->id == CSSValueAuto || value->id == CSSValueBaseline || value->id == CSSValueStretch) { + if (m_valueList->next()) + return false; + + addProperty(propId, cssValuePool().createIdentifierValue(value->id), important); + return true; + } + + RefPtrWillBeRawPtr<CSSPrimitiveValue> position = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> overflowAlignmentKeyword = nullptr; + if (isItemPositionKeyword(value->id)) { + position = cssValuePool().createIdentifierValue(value->id); + value = m_valueList->next(); + if (value) { + if (value->id == CSSValueTrue || value->id == CSSValueSafe) + overflowAlignmentKeyword = cssValuePool().createIdentifierValue(value->id); + else + return false; } + } else if (value->id == CSSValueTrue || value->id == CSSValueSafe) { + overflowAlignmentKeyword = cssValuePool().createIdentifierValue(value->id); + value = m_valueList->next(); + if (value && isItemPositionKeyword(value->id)) + position = cssValuePool().createIdentifierValue(value->id); + else + return false; + } else { + return false; + } - if (!validUnit(argument, unitFlags)) - return 0; + if (m_valueList->next()) + return false; - RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument); - ASSERT(argumentNumber < 3); - switch (argumentNumber) { - case 0: - shape->setCenterX(length); - break; - case 1: - shape->setCenterY(length); - break; - case 2: - shape->setRadius(length); - break; + ASSERT(position); + if (overflowAlignmentKeyword) + addProperty(propId, createPrimitiveValuePair(position, overflowAlignmentKeyword), important); + else + addProperty(propId, position.release(), important); + + return true; +} + +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseShapeRadius(CSSParserValue* value) +{ + if (value->id == CSSValueClosestSide || value->id == CSSValueFarthestSide) + return cssValuePool().createIdentifierValue(value->id); + + if (!validUnit(value, FLength | FPercent | FNonNeg)) + return nullptr; + + return createPrimitiveNumericValue(value); +} + +PassRefPtrWillBeRawPtr<CSSBasicShape> CSSPropertyParser::parseBasicShapeCircle(CSSParserValueList* args) +{ + ASSERT(args); + + // circle(radius) + // circle(radius at <position>) + // circle(at <position>) + // where position defines centerX and centerY using a CSS <position> data type. + RefPtrWillBeRawPtr<CSSBasicShapeCircle> shape = CSSBasicShapeCircle::create(); + + for (CSSParserValue* argument = args->current(); argument; argument = args->next()) { + // The call to parseFillPosition below should consume all of the + // arguments except the first two. Thus, and index greater than one + // indicates an invalid production. + if (args->currentIndex() > 1) + return nullptr; + + if (!args->currentIndex() && argument->id != CSSValueAt) { + if (RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = parseShapeRadius(argument)) { + shape->setRadius(radius); + continue; + } + + return nullptr; } - argument = args->next(); - if (argument) { - if (!isComma(argument)) - return 0; - argument = args->next(); + if (argument->id == CSSValueAt && args->next()) { + RefPtrWillBeRawPtr<CSSValue> centerX = nullptr; + RefPtrWillBeRawPtr<CSSValue> centerY = nullptr; + parseFillPosition(args, centerX, centerY); + if (centerX && centerY && !args->current()) { + ASSERT(centerX->isPrimitiveValue()); + ASSERT(centerY->isPrimitiveValue()); + shape->setCenterX(toCSSPrimitiveValue(centerX.get())); + shape->setCenterY(toCSSPrimitiveValue(centerY.get())); + } else { + return nullptr; + } + } else { + return nullptr; } - argumentNumber++; } - if (argumentNumber < 3) - return 0; return shape; } -PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapeEllipse(CSSParserValueList* args) +PassRefPtrWillBeRawPtr<CSSBasicShape> CSSPropertyParser::parseBasicShapeEllipse(CSSParserValueList* args) { ASSERT(args); - // ellipse(centerX, centerY, radiusX, radiusY) - if (args->size() != 7) - return 0; + // ellipse(radiusX) + // ellipse(radiusX at <position>) + // ellipse(radiusX radiusY) + // ellipse(radiusX radiusY at <position>) + // ellipse(at <position>) + // where position defines centerX and centerY using a CSS <position> data type. + RefPtrWillBeRawPtr<CSSBasicShapeEllipse> shape = CSSBasicShapeEllipse::create(); + + for (CSSParserValue* argument = args->current(); argument; argument = args->next()) { + // The call to parseFillPosition below should consume all of the + // arguments except the first three. Thus, an index greater than two + // indicates an invalid production. + if (args->currentIndex() > 2) + return nullptr; + + if (args->currentIndex() < 2 && argument->id != CSSValueAt) { + if (RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = parseShapeRadius(argument)) { + if (!shape->radiusX()) + shape->setRadiusX(radius); + else + shape->setRadiusY(radius); + continue; + } - RefPtr<CSSBasicShapeEllipse> shape = CSSBasicShapeEllipse::create(); - unsigned argumentNumber = 0; - CSSParserValue* argument = args->current(); - while (argument) { - Units unitFlags = FLength | FPercent; - if (argumentNumber > 1) { - // Arguments radiusX and radiusY cannot be negative. - unitFlags = unitFlags | FNonNeg; - } - if (!validUnit(argument, unitFlags)) - return 0; - - RefPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(argument); - ASSERT(argumentNumber < 4); - switch (argumentNumber) { - case 0: - shape->setCenterX(length); - break; - case 1: - shape->setCenterY(length); - break; - case 2: - shape->setRadiusX(length); - break; - case 3: - shape->setRadiusY(length); - break; + return nullptr; } - argument = args->next(); - if (argument) { - if (!isComma(argument)) - return 0; - argument = args->next(); - } - argumentNumber++; + if (argument->id != CSSValueAt || !args->next()) // expecting ellipse(.. at <position>) + return nullptr; + RefPtrWillBeRawPtr<CSSValue> centerX = nullptr; + RefPtrWillBeRawPtr<CSSValue> centerY = nullptr; + parseFillPosition(args, centerX, centerY); + if (!centerX || !centerY || args->current()) + return nullptr; + + ASSERT(centerX->isPrimitiveValue()); + ASSERT(centerY->isPrimitiveValue()); + shape->setCenterX(toCSSPrimitiveValue(centerX.get())); + shape->setCenterY(toCSSPrimitiveValue(centerY.get())); } - if (argumentNumber < 4) - return 0; return shape; } -PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapePolygon(CSSParserValueList* args) +PassRefPtrWillBeRawPtr<CSSBasicShape> CSSPropertyParser::parseBasicShapePolygon(CSSParserValueList* args) { ASSERT(args); unsigned size = args->size(); if (!size) - return 0; + return nullptr; - RefPtr<CSSBasicShapePolygon> shape = CSSBasicShapePolygon::create(); + RefPtrWillBeRawPtr<CSSBasicShapePolygon> shape = CSSBasicShapePolygon::create(); CSSParserValue* argument = args->current(); if (argument->id == CSSValueEvenodd || argument->id == CSSValueNonzero) { shape->setWindRule(argument->id == CSSValueEvenodd ? RULE_EVENODD : RULE_NONZERO); if (!isComma(args->next())) - return 0; + return nullptr; argument = args->next(); size -= 2; @@ -5293,19 +4321,20 @@ PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapePolygon(CSSParserValueList* // <length> <length>, ... <length> <length> -> each pair has 3 elements except the last one if (!size || (size % 3) - 2) - return 0; + return nullptr; CSSParserValue* argumentX = argument; while (argumentX) { + if (!validUnit(argumentX, FLength | FPercent)) - return 0; + return nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> xLength = createPrimitiveNumericValue(argumentX); CSSParserValue* argumentY = args->next(); if (!argumentY || !validUnit(argumentY, FLength | FPercent)) - return 0; + return nullptr; - RefPtr<CSSPrimitiveValue> xLength = createPrimitiveNumericValue(argumentX); - RefPtr<CSSPrimitiveValue> yLength = createPrimitiveNumericValue(argumentY); + RefPtrWillBeRawPtr<CSSPrimitiveValue> yLength = createPrimitiveNumericValue(argumentY); shape->appendPoint(xLength.release(), yLength.release()); @@ -5313,7 +4342,7 @@ PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapePolygon(CSSParserValueList* if (!commaOrNull) argumentX = 0; else if (!isComma(commaOrNull)) - return 0; + return nullptr; else argumentX = args->next(); } @@ -5321,37 +4350,109 @@ PassRefPtr<CSSBasicShape> CSSParser::parseBasicShapePolygon(CSSParserValueList* return shape; } -bool CSSParser::parseBasicShape(CSSPropertyID propId, bool important) +static bool isBoxValue(CSSValueID valueId) +{ + switch (valueId) { + case CSSValueContentBox: + case CSSValuePaddingBox: + case CSSValueBorderBox: + case CSSValueMarginBox: + return true; + default: + break; + } + + return false; +} + +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseShapeProperty(CSSPropertyID propId) +{ + if (!RuntimeEnabledFeatures::cssShapesEnabled()) + return nullptr; + + CSSParserValue* value = m_valueList->current(); + CSSValueID valueId = value->id; + + if (valueId == CSSValueNone) { + RefPtrWillBeRawPtr<CSSPrimitiveValue> keywordValue = parseValidPrimitive(valueId, value); + m_valueList->next(); + return keywordValue.release(); + } + + RefPtrWillBeRawPtr<CSSValue> imageValue = nullptr; + if (valueId != CSSValueNone && parseFillImage(m_valueList.get(), imageValue)) { + m_valueList->next(); + return imageValue.release(); + } + + return parseBasicShapeAndOrBox(); +} + +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseBasicShapeAndOrBox() +{ + CSSParserValue* value = m_valueList->current(); + + bool shapeFound = false; + bool boxFound = false; + CSSValueID valueId; + + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + for (unsigned i = 0; i < 2; ++i) { + if (!value) + break; + valueId = value->id; + if (value->unit == CSSParserValue::Function && !shapeFound) { + // parseBasicShape already asks for the next value list item. + RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue = parseBasicShape(); + if (!shapeValue) + return nullptr; + list->append(shapeValue.release()); + shapeFound = true; + } else if (isBoxValue(valueId) && !boxFound) { + list->append(parseValidPrimitive(valueId, value)); + boxFound = true; + m_valueList->next(); + } else { + return nullptr; + } + + value = m_valueList->current(); + } + + if (m_valueList->current()) + return nullptr; + return list.release(); +} + +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseBasicShape() { CSSParserValue* value = m_valueList->current(); ASSERT(value->unit == CSSParserValue::Function); CSSParserValueList* args = value->function->args.get(); if (!args) - return false; + return nullptr; - RefPtr<CSSBasicShape> shape; - if (equalIgnoringCase(value->function->name, "rectangle(")) - shape = parseBasicShapeRectangle(args); - else if (equalIgnoringCase(value->function->name, "circle(")) + RefPtrWillBeRawPtr<CSSBasicShape> shape = nullptr; + if (equalIgnoringCase(value->function->name, "circle(")) shape = parseBasicShapeCircle(args); else if (equalIgnoringCase(value->function->name, "ellipse(")) shape = parseBasicShapeEllipse(args); else if (equalIgnoringCase(value->function->name, "polygon(")) shape = parseBasicShapePolygon(args); - else if (equalIgnoringCase(value->function->name, "inset-rectangle(")) - shape = parseBasicShapeInsetRectangle(args); + else if (equalIgnoringCase(value->function->name, "inset(")) + shape = parseBasicShapeInset(args); if (!shape) - return false; + return nullptr; - addProperty(propId, cssValuePool().createValue(shape.release()), important); m_valueList->next(); - return true; + + return cssValuePool().createValue(shape.release()); } // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family' -bool CSSParser::parseFont(bool important) +bool CSSPropertyParser::parseFont(bool important) { // Let's check if there is an inherit or initial somewhere in the shorthand. for (unsigned i = 0; i < m_valueList->size(); ++i) { @@ -5410,7 +4511,7 @@ bool CSSParser::parseFont(bool important) addProperty(CSSPropertyLineHeight, cssValuePool().createIdentifierValue(CSSValueNormal), important, true); // Font family must come now. - RefPtr<CSSValue> parsedFamilyValue = parseFontFamily(); + RefPtrWillBeRawPtr<CSSValue> parsedFamilyValue = parseFontFamily(); if (!parsedFamilyValue) return false; @@ -5426,6 +4527,7 @@ bool CSSParser::parseFont(bool important) } class FontFamilyValueBuilder { + DISALLOW_ALLOCATION(); public: FontFamilyValueBuilder(CSSValueList* list) : m_list(list) @@ -5458,9 +4560,9 @@ private: CSSValueList* m_list; }; -PassRefPtr<CSSValueList> CSSParser::parseFontFamily() +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseFontFamily() { - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); CSSParserValue* value = m_valueList->current(); FontFamilyValueBuilder familyBuilder(list.get()); @@ -5474,8 +4576,7 @@ PassRefPtr<CSSValueList> CSSParser::parseFontFamily() ((nextValue->id >= CSSValueSerif && nextValue->id <= CSSValueWebkitBody) || (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT)); - bool valueIsKeyword = value->id == CSSValueInitial || value->id == CSSValueInherit || value->id == CSSValueDefault; - if (valueIsKeyword && !inFamily) { + if (isCSSWideKeyword(*value) && !inFamily) { if (nextValBreaksFont) value = m_valueList->next(); else if (nextValIsFontName) @@ -5528,11 +4629,11 @@ PassRefPtr<CSSValueList> CSSParser::parseFontFamily() familyBuilder.commit(); if (!list->length()) - list = 0; + list = nullptr; return list.release(); } -bool CSSParser::parseLineHeight(bool important) +bool CSSPropertyParser::parseLineHeight(bool important) { CSSParserValue* value = m_valueList->current(); CSSValueID id = value->id; @@ -5547,7 +4648,7 @@ bool CSSParser::parseLineHeight(bool important) return validPrimitive; } -bool CSSParser::parseFontSize(bool important) +bool CSSPropertyParser::parseFontSize(bool important) { CSSParserValue* value = m_valueList->current(); CSSValueID id = value->id; @@ -5562,20 +4663,23 @@ bool CSSParser::parseFontSize(bool important) return validPrimitive; } -bool CSSParser::parseFontVariant(bool important) +bool CSSPropertyParser::parseFontVariant(bool important) { - RefPtr<CSSValueList> values; + RefPtrWillBeRawPtr<CSSValueList> values = nullptr; if (m_valueList->size() > 1) values = CSSValueList::createCommaSeparated(); CSSParserValue* val; bool expectComma = false; while ((val = m_valueList->current())) { - RefPtr<CSSPrimitiveValue> parsedValue; + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedValue = nullptr; if (!expectComma) { expectComma = true; if (val->id == CSSValueNormal || val->id == CSSValueSmallCaps) parsedValue = cssValuePool().createIdentifierValue(val->id); else if (val->id == CSSValueAll && !values) { + // FIXME: CSSPropertyParser::parseFontVariant() implements + // the old css3 draft: + // http://www.w3.org/TR/2002/WD-css3-webfonts-20020802/#font-variant // '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(); @@ -5601,7 +4705,8 @@ bool CSSParser::parseFontVariant(bool important) } if (values && values->length()) { - m_hasFontFaceOnlyValues = true; + if (m_ruleType != CSSRuleSourceData::FONT_FACE_RULE) + return false; addProperty(CSSPropertyFontVariant, values.release(), important); return true; } @@ -5609,7 +4714,7 @@ bool CSSParser::parseFontVariant(bool important) return false; } -bool CSSParser::parseFontWeight(bool important) +bool CSSPropertyParser::parseFontWeight(bool important) { CSSParserValue* value = m_valueList->current(); if ((value->id >= CSSValueNormal) && (value->id <= CSSValue900)) { @@ -5626,9 +4731,10 @@ bool CSSParser::parseFontWeight(bool important) return false; } -bool CSSParser::parseFontFaceSrcURI(CSSValueList* valueList) +bool CSSPropertyParser::parseFontFaceSrcURI(CSSValueList* valueList) { - RefPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(completeURL(m_valueList->current()->string))); + RefPtrWillBeRawPtr<CSSFontFaceSrcValue> uriValue(CSSFontFaceSrcValue::create(completeURL(m_valueList->current()->string))); + uriValue->setReferrer(m_context.referrer()); CSSParserValue* value = m_valueList->next(); if (!value) { @@ -5657,7 +4763,7 @@ bool CSSParser::parseFontFaceSrcURI(CSSValueList* valueList) return true; } -bool CSSParser::parseFontFaceSrcLocal(CSSValueList* valueList) +bool CSSPropertyParser::parseFontFaceSrcLocal(CSSValueList* valueList) { CSSParserValueList* args = m_valueList->current()->function->args.get(); if (!args || !args->size()) @@ -5685,9 +4791,9 @@ bool CSSParser::parseFontFaceSrcLocal(CSSValueList* valueList) return true; } -bool CSSParser::parseFontFaceSrc() +bool CSSPropertyParser::parseFontFaceSrc() { - RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated()); + RefPtrWillBeRawPtr<CSSValueList> values(CSSValueList::createCommaSeparated()); while (CSSParserValue* value = m_valueList->current()) { if (value->unit == CSSPrimitiveValue::CSS_URI) { @@ -5707,9 +4813,9 @@ bool CSSParser::parseFontFaceSrc() return true; } -bool CSSParser::parseFontFaceUnicodeRange() +bool CSSPropertyParser::parseFontFaceUnicodeRange() { - RefPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); bool failed = false; bool operatorExpected = false; for (; m_valueList->current(); m_valueList->next(), operatorExpected = !operatorExpected) { @@ -5869,7 +4975,7 @@ static int parseDouble(const CharacterType* string, const CharacterType* end, co } template <typename CharacterType> -static bool parseColorIntOrPercentage(const CharacterType*& string, const CharacterType* end, const char terminator, CSSPrimitiveValue::UnitTypes& expect, int& value) +static bool parseColorIntOrPercentage(const CharacterType*& string, const CharacterType* end, const char terminator, CSSPrimitiveValue::UnitType& expect, int& value) { const CharacterType* current = string; double localValue = 0; @@ -6028,16 +5134,14 @@ static inline bool mightBeRGB(const CharacterType* characters, unsigned length) template <typename CharacterType> static inline bool fastParseColorInternal(RGBA32& rgb, const CharacterType* characters, unsigned length , bool strict) { - CSSPrimitiveValue::UnitTypes expect = CSSPrimitiveValue::CSS_UNKNOWN; + CSSPrimitiveValue::UnitType expect = CSSPrimitiveValue::CSS_UNKNOWN; + + if (length >= 4 && characters[0] == '#') + return Color::parseHexColor(characters + 1, length - 1, rgb); if (!strict && length >= 3) { - if (characters[0] == '#') { - if (Color::parseHexColor(characters + 1, length - 1, rgb)) - return true; - } else { - if (Color::parseHexColor(characters, length, rgb)) - return true; - } + if (Color::parseHexColor(characters, length, rgb)) + return true; } // Try rgba() syntax. @@ -6086,7 +5190,7 @@ static inline bool fastParseColorInternal(RGBA32& rgb, const CharacterType* char } template<typename StringType> -bool CSSParser::fastParseColor(RGBA32& rgb, const StringType& name, bool strict) +bool CSSPropertyParser::fastParseColor(RGBA32& rgb, const StringType& name, bool strict) { unsigned length = name.length(); bool parseResult; @@ -6104,15 +5208,15 @@ bool CSSParser::fastParseColor(RGBA32& rgb, const StringType& name, bool strict) // Try named colors. Color tc; - tc.setNamedColor(name); - if (tc.isValid()) { - rgb = tc.rgb(); - return true; - } - return false; + if (!tc.setNamedColor(name)) + return false; + rgb = tc.rgb(); + return true; } -inline double CSSParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueCondition releaseCalc) +template bool CSSPropertyParser::fastParseColor(RGBA32&, const String&, bool strict); + +inline double CSSPropertyParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueCondition releaseCalc) { const double result = m_parsedCalculation ? m_parsedCalculation->doubleValue() : v->fValue; if (releaseCalc == ReleaseParsedCalcValue) @@ -6120,7 +5224,7 @@ inline double CSSParser::parsedDouble(CSSParserValue *v, ReleaseParsedCalcValueC return result; } -bool CSSParser::isCalculation(CSSParserValue* value) +bool CSSPropertyParser::isCalculation(CSSParserValue* value) { return (value->unit == CSSParserValue::Function) && (equalIgnoringCase(value->function->name, "calc(") @@ -6129,7 +5233,7 @@ bool CSSParser::isCalculation(CSSParserValue* value) || equalIgnoringCase(value->function->name, "-webkit-max(")); } -inline int CSSParser::colorIntFromValue(CSSParserValue* v) +inline int CSSPropertyParser::colorIntFromValue(CSSParserValue* v) { bool isPercent; @@ -6155,7 +5259,7 @@ inline int CSSParser::colorIntFromValue(CSSParserValue* v) return static_cast<int>(value); } -bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha) +bool CSSPropertyParser::parseColorParameters(CSSParserValue* value, int* colorArray, bool parseAlpha) { CSSParserValueList* args = value->function->args.get(); CSSParserValue* v = args->current(); @@ -6188,7 +5292,7 @@ bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, boo const double value = parsedDouble(v, ReleaseParsedCalcValue); // Convert the floating pointer number of alpha to an integer in the range [0, 256), // with an equal distribution across all 256 values. - colorArray[3] = static_cast<int>(max(0.0, min(1.0, value)) * nextafter(256.0, 0.0)); + colorArray[3] = static_cast<int>(std::max(0.0, std::min(1.0, value)) * nextafter(256.0, 0.0)); } return true; } @@ -6198,7 +5302,7 @@ bool CSSParser::parseColorParameters(CSSParserValue* value, int* colorArray, boo // and with alpha, the format is // hsla(<number>, <percent>, <percent>, <number>) // The first value, HUE, is in an angle with a value between 0 and 360 -bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha) +bool CSSPropertyParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bool parseAlpha) { CSSParserValueList* args = value->function->args.get(); CSSParserValue* v = args->current(); @@ -6214,7 +5318,7 @@ bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bo v = args->next(); if (!validUnit(v, FPercent, HTMLStandardMode)) return false; - colorArray[i] = max(0.0, min(100.0, parsedDouble(v, ReleaseParsedCalcValue))) / 100.0; // needs to be value between 0 and 1.0 + colorArray[i] = std::max(0.0, std::min(100.0, parsedDouble(v, ReleaseParsedCalcValue))) / 100.0; // needs to be value between 0 and 1.0 } if (parseAlpha) { v = args->next(); @@ -6223,20 +5327,20 @@ bool CSSParser::parseHSLParameters(CSSParserValue* value, double* colorArray, bo v = args->next(); if (!validUnit(v, FNumber, HTMLStandardMode)) return false; - colorArray[3] = max(0.0, min(1.0, parsedDouble(v, ReleaseParsedCalcValue))); + colorArray[3] = std::max(0.0, std::min(1.0, parsedDouble(v, ReleaseParsedCalcValue))); } return true; } -PassRefPtr<CSSPrimitiveValue> CSSParser::parseColor(CSSParserValue* value) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseColor(CSSParserValue* value) { RGBA32 c = Color::transparent; if (!parseColorFromValue(value ? value : m_valueList->current(), c)) - return 0; + return nullptr; return cssValuePool().createColorValue(c); } -bool CSSParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) +bool CSSPropertyParser::parseColorFromValue(CSSParserValue* value, RGBA32& c) { if (inQuirksMode() && value->unit == CSSPrimitiveValue::CSS_NUMBER && value->fValue >= 0. && value->fValue < 1000000.) { @@ -6291,8 +5395,10 @@ 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, CSSParser* parser) +class ShadowParseContext { + STACK_ALLOCATED(); +public: + ShadowParseContext(CSSPropertyID prop, CSSPropertyParser* parser) : property(prop) , m_parser(parser) , allowX(true) @@ -6319,12 +5425,12 @@ struct ShadowParseContext { } // Now reset for the next shadow value. - x = 0; - y = 0; - blur = 0; - spread = 0; - style = 0; - color = 0; + x = nullptr; + y = nullptr; + blur = nullptr; + spread = nullptr; + style = nullptr; + color = nullptr; allowX = true; allowColor = true; @@ -6337,7 +5443,7 @@ struct ShadowParseContext { void commitLength(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v); + RefPtrWillBeRawPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v); if (allowX) { x = val.release(); @@ -6363,7 +5469,7 @@ struct ShadowParseContext { } } - void commitColor(PassRefPtr<CSSPrimitiveValue> val) + void commitColor(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { color = val; allowColor = false; @@ -6391,15 +5497,15 @@ struct ShadowParseContext { } CSSPropertyID property; - CSSParser* m_parser; + CSSPropertyParser* m_parser; - RefPtr<CSSValueList> values; - RefPtr<CSSPrimitiveValue> x; - RefPtr<CSSPrimitiveValue> y; - RefPtr<CSSPrimitiveValue> blur; - RefPtr<CSSPrimitiveValue> spread; - RefPtr<CSSPrimitiveValue> style; - RefPtr<CSSPrimitiveValue> color; + RefPtrWillBeMember<CSSValueList> values; + RefPtrWillBeMember<CSSPrimitiveValue> x; + RefPtrWillBeMember<CSSPrimitiveValue> y; + RefPtrWillBeMember<CSSPrimitiveValue> blur; + RefPtrWillBeMember<CSSPrimitiveValue> spread; + RefPtrWillBeMember<CSSPrimitiveValue> style; + RefPtrWillBeMember<CSSPrimitiveValue> color; bool allowX; bool allowY; @@ -6410,44 +5516,45 @@ struct ShadowParseContext { bool allowBreak; }; -PassRefPtr<CSSValueList> CSSParser::parseShadow(CSSParserValueList* valueList, CSSPropertyID propId) +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseShadow(CSSParserValueList* valueList, CSSPropertyID propId) { ShadowParseContext context(propId, this); CSSParserValue* val; while ((val = valueList->current())) { // Check for a comma break first. if (val->unit == CSSParserValue::Operator) { - if (val->iValue != ',' || !context.allowBreak) + if (val->iValue != ',' || !context.allowBreak) { // Other operators aren't legal or we aren't done with the current shadow // value. Treat as invalid. - return 0; + return nullptr; + } // The value is good. Commit it. context.commitValue(); } else if (validUnit(val, FLength, HTMLStandardMode)) { // We required a length and didn't get one. Invalid. if (!context.allowLength()) - return 0; + return nullptr; // Blur radius must be non-negative. if (context.allowBlur && !validUnit(val, FLength | FNonNeg, HTMLStandardMode)) - return 0; + return nullptr; // A length is allowed here. Construct the value and add it. context.commitLength(val); } else if (val->id == CSSValueInset) { if (!context.allowStyle) - return 0; + return nullptr; context.commitStyle(val); } else { // The only other type of value that's ok is a color value. - RefPtr<CSSPrimitiveValue> parsedColor; + RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedColor = nullptr; bool isColor = ((val->id >= CSSValueAqua && val->id <= CSSValueWindowtext) || val->id == CSSValueMenu || (val->id >= CSSValueWebkitFocusRingColor && val->id <= CSSValueWebkitText && inQuirksMode()) || val->id == CSSValueCurrentcolor); if (isColor) { if (!context.allowColor) - return 0; + return nullptr; parsedColor = cssValuePool().createIdentifierValue(val->id); } @@ -6456,7 +5563,7 @@ PassRefPtr<CSSValueList> CSSParser::parseShadow(CSSParserValueList* valueList, C parsedColor = parseColor(val); if (!parsedColor || !context.allowColor) - return 0; // This value is not a color or length and is invalid or + return nullptr; // This value is not a color or length and is invalid or // it is a color, but a color isn't allowed at this point. context.commitColor(parsedColor.release()); @@ -6471,33 +5578,30 @@ PassRefPtr<CSSValueList> CSSParser::parseShadow(CSSParserValueList* valueList, C return context.values.release(); } - return 0; + return nullptr; } -bool CSSParser::parseReflect(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseReflect(CSSPropertyID propId, bool important) { // box-reflect: <direction> <offset> <mask> // Direction comes first. CSSParserValue* val = m_valueList->current(); - RefPtr<CSSPrimitiveValue> direction; - if (val->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME) - direction = createPrimitiveVariableNameValue(val); - else + RefPtrWillBeRawPtr<CSSPrimitiveValue> direction = nullptr; switch (val->id) { - case CSSValueAbove: - case CSSValueBelow: - case CSSValueLeft: - case CSSValueRight: - direction = cssValuePool().createIdentifierValue(val->id); - break; - default: - return false; + case CSSValueAbove: + case CSSValueBelow: + case CSSValueLeft: + case CSSValueRight: + direction = cssValuePool().createIdentifierValue(val->id); + break; + default: + return false; } // The offset comes next. val = m_valueList->next(); - RefPtr<CSSPrimitiveValue> offset; + RefPtrWillBeRawPtr<CSSPrimitiveValue> offset = nullptr; if (!val) offset = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX); else { @@ -6507,7 +5611,7 @@ bool CSSParser::parseReflect(CSSPropertyID propId, bool important) } // Now for the mask. - RefPtr<CSSValue> mask; + RefPtrWillBeRawPtr<CSSValue> mask = nullptr; val = m_valueList->next(); if (val) { mask = parseBorderImage(propId); @@ -6515,20 +5619,20 @@ bool CSSParser::parseReflect(CSSPropertyID propId, bool important) return false; } - RefPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction.release(), offset.release(), mask.release()); + RefPtrWillBeRawPtr<CSSReflectValue> reflectValue = CSSReflectValue::create(direction.release(), offset.release(), mask.release()); addProperty(propId, reflectValue.release(), important); m_valueList->next(); return true; } -bool CSSParser::parseFlex(CSSParserValueList* args, bool important) +bool CSSPropertyParser::parseFlex(CSSParserValueList* args, bool important) { if (!args || !args->size() || args->size() > 3) return false; static const double unsetValue = -1; double flexGrow = unsetValue; double flexShrink = unsetValue; - RefPtr<CSSPrimitiveValue> flexBasis; + RefPtrWillBeRawPtr<CSSPrimitiveValue> flexBasis = nullptr; while (CSSParserValue* arg = args->current()) { if (validUnit(arg, FNumber | FNonNeg)) { @@ -6565,10 +5669,10 @@ bool CSSParser::parseFlex(CSSParserValueList* args, bool important) return true; } -bool CSSParser::parseObjectPosition(bool important) +bool CSSPropertyParser::parseObjectPosition(bool important) { - RefPtr<CSSValue> xValue; - RefPtr<CSSValue> yValue; + RefPtrWillBeRawPtr<CSSValue> xValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> yValue = nullptr; parseFillPosition(m_valueList.get(), xValue, yValue); if (!xValue || !yValue) return false; @@ -6579,7 +5683,9 @@ bool CSSParser::parseObjectPosition(bool important) return true; } -struct BorderImageParseContext { +class BorderImageParseContext { + STACK_ALLOCATED(); +public: BorderImageParseContext() : m_canAdvance(false) , m_allowCommit(true) @@ -6603,7 +5709,7 @@ struct BorderImageParseContext { bool requireWidth() const { return m_requireWidth; } bool requireOutset() const { return m_requireOutset; } - void commitImage(PassRefPtr<CSSValue> image) + void commitImage(PassRefPtrWillBeRawPtr<CSSValue> image) { m_image = image; m_canAdvance = true; @@ -6612,7 +5718,7 @@ struct BorderImageParseContext { m_allowImageSlice = !m_imageSlice; m_allowRepeat = !m_repeat; } - void commitImageSlice(PassRefPtr<CSSBorderImageSliceValue> slice) + void commitImageSlice(PassRefPtrWillBeRawPtr<CSSBorderImageSliceValue> slice) { m_imageSlice = slice; m_canAdvance = true; @@ -6633,7 +5739,7 @@ struct BorderImageParseContext { m_requireWidth = false; } } - void commitBorderWidth(PassRefPtr<CSSPrimitiveValue> slice) + void commitBorderWidth(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> slice) { m_borderSlice = slice; m_canAdvance = true; @@ -6642,7 +5748,7 @@ struct BorderImageParseContext { m_allowImage = !m_image; m_allowRepeat = !m_repeat; } - void commitBorderOutset(PassRefPtr<CSSPrimitiveValue> outset) + void commitBorderOutset(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> outset) { m_outset = outset; m_canAdvance = true; @@ -6651,7 +5757,7 @@ struct BorderImageParseContext { m_allowImage = !m_image; m_allowRepeat = !m_repeat; } - void commitRepeat(PassRefPtr<CSSValue> repeat) + void commitRepeat(PassRefPtrWillBeRawPtr<CSSValue> repeat) { m_repeat = repeat; m_canAdvance = true; @@ -6661,30 +5767,30 @@ struct BorderImageParseContext { m_allowImage = !m_image; } - PassRefPtr<CSSValue> commitCSSValue() + PassRefPtrWillBeRawPtr<CSSValue> commitCSSValue() { - return createBorderImageValue(m_image, m_imageSlice, m_borderSlice, m_outset, m_repeat); + return createBorderImageValue(m_image, m_imageSlice.get(), m_borderSlice.get(), m_outset.get(), m_repeat.get()); } - void commitMaskBoxImage(CSSParser* parser, bool important) + void commitMaskBoxImage(CSSPropertyParser* parser, bool important) { commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageSource, parser, m_image, important); - commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageSlice, parser, m_imageSlice, important); - commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageWidth, parser, m_borderSlice, important); - commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageOutset, parser, m_outset, important); - commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageRepeat, parser, m_repeat, important); + commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageSlice, parser, m_imageSlice.get(), important); + commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageWidth, parser, m_borderSlice.get(), important); + commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageOutset, parser, m_outset.get(), important); + commitBorderImageProperty(CSSPropertyWebkitMaskBoxImageRepeat, parser, m_repeat.get(), important); } - void commitBorderImage(CSSParser* parser, bool important) + void commitBorderImage(CSSPropertyParser* parser, bool important) { commitBorderImageProperty(CSSPropertyBorderImageSource, parser, m_image, important); - commitBorderImageProperty(CSSPropertyBorderImageSlice, parser, m_imageSlice, important); - commitBorderImageProperty(CSSPropertyBorderImageWidth, parser, m_borderSlice, important); - commitBorderImageProperty(CSSPropertyBorderImageOutset, parser, m_outset, important); + commitBorderImageProperty(CSSPropertyBorderImageSlice, parser, m_imageSlice.get(), important); + commitBorderImageProperty(CSSPropertyBorderImageWidth, parser, m_borderSlice.get(), important); + commitBorderImageProperty(CSSPropertyBorderImageOutset, parser, m_outset.get(), important); commitBorderImageProperty(CSSPropertyBorderImageRepeat, parser, m_repeat, important); } - void commitBorderImageProperty(CSSPropertyID propId, CSSParser* parser, PassRefPtr<CSSValue> value, bool important) + void commitBorderImageProperty(CSSPropertyID propId, CSSPropertyParser* parser, PassRefPtrWillBeRawPtr<CSSValue> value, bool important) { if (value) parser->addProperty(propId, value, important); @@ -6692,6 +5798,8 @@ struct BorderImageParseContext { parser->addProperty(propId, cssValuePool().createImplicitInitialValue(), important, true); } + static bool buildFromParser(CSSPropertyParser&, CSSPropertyID, BorderImageParseContext&); + bool m_canAdvance; bool m_allowCommit; @@ -6703,17 +5811,17 @@ struct BorderImageParseContext { bool m_requireWidth; bool m_requireOutset; - RefPtr<CSSValue> m_image; - RefPtr<CSSBorderImageSliceValue> m_imageSlice; - RefPtr<CSSPrimitiveValue> m_borderSlice; - RefPtr<CSSPrimitiveValue> m_outset; + RefPtrWillBeMember<CSSValue> m_image; + RefPtrWillBeMember<CSSBorderImageSliceValue> m_imageSlice; + RefPtrWillBeMember<CSSPrimitiveValue> m_borderSlice; + RefPtrWillBeMember<CSSPrimitiveValue> m_outset; - RefPtr<CSSValue> m_repeat; + RefPtrWillBeMember<CSSValue> m_repeat; }; -static bool buildBorderImageParseContext(CSSParser& parser, CSSPropertyID propId, BorderImageParseContext& context) +bool BorderImageParseContext::buildFromParser(CSSPropertyParser& parser, CSSPropertyID propId, BorderImageParseContext& context) { - ShorthandScope scope(&parser, propId); + CSSPropertyParser::ShorthandScope scope(&parser, propId); while (CSSParserValue* val = parser.m_valueList->current()) { context.setCanAdvance(false); @@ -6722,15 +5830,15 @@ static bool buildBorderImageParseContext(CSSParser& parser, CSSPropertyID propId if (!context.canAdvance() && context.allowImage()) { if (val->unit == CSSPrimitiveValue::CSS_URI) { - context.commitImage(CSSImageValue::create(parser.completeURL(parser.m_context, val->string))); + context.commitImage(parser.createCSSImageValueWithReferrer(val->string, parser.m_context.completeURL(val->string))); } else if (isGeneratedImageValue(val)) { - RefPtr<CSSValue> value; + RefPtrWillBeRawPtr<CSSValue> value = nullptr; if (parser.parseGeneratedImage(parser.m_valueList.get(), value)) context.commitImage(value.release()); else return false; } else if (val->unit == CSSParserValue::Function && equalIgnoringCase(val->function->name, "-webkit-image-set(")) { - RefPtr<CSSValue> value = parser.parseImageSet(parser.m_valueList.get()); + RefPtrWillBeRawPtr<CSSValue> value = parser.parseImageSet(parser.m_valueList.get()); if (value) context.commitImage(value.release()); else @@ -6740,25 +5848,25 @@ static bool buildBorderImageParseContext(CSSParser& parser, CSSPropertyID propId } if (!context.canAdvance() && context.allowImageSlice()) { - RefPtr<CSSBorderImageSliceValue> imageSlice; + RefPtrWillBeRawPtr<CSSBorderImageSliceValue> imageSlice = nullptr; if (parser.parseBorderImageSlice(propId, imageSlice)) context.commitImageSlice(imageSlice.release()); } if (!context.canAdvance() && context.allowRepeat()) { - RefPtr<CSSValue> repeat; + RefPtrWillBeRawPtr<CSSValue> repeat = nullptr; if (parser.parseBorderImageRepeat(repeat)) context.commitRepeat(repeat.release()); } if (!context.canAdvance() && context.requireWidth()) { - RefPtr<CSSPrimitiveValue> borderSlice; + RefPtrWillBeRawPtr<CSSPrimitiveValue> borderSlice = nullptr; if (parser.parseBorderImageWidth(borderSlice)) context.commitBorderWidth(borderSlice.release()); } if (!context.canAdvance() && context.requireOutset()) { - RefPtr<CSSPrimitiveValue> borderOutset; + RefPtrWillBeRawPtr<CSSPrimitiveValue> borderOutset = nullptr; if (parser.parseBorderImageOutset(borderOutset)) context.commitBorderOutset(borderOutset.release()); } @@ -6772,10 +5880,10 @@ static bool buildBorderImageParseContext(CSSParser& parser, CSSPropertyID propId return context.allowCommit(); } -bool CSSParser::parseBorderImageShorthand(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseBorderImageShorthand(CSSPropertyID propId, bool important) { BorderImageParseContext context; - if (buildBorderImageParseContext(*this, propId, context)) { + if (BorderImageParseContext::buildFromParser(*this, propId, context)) { switch (propId) { case CSSPropertyWebkitMaskBoxImage: context.commitMaskBoxImage(this, important); @@ -6791,13 +5899,13 @@ bool CSSParser::parseBorderImageShorthand(CSSPropertyID propId, bool important) return false; } -PassRefPtr<CSSValue> CSSParser::parseBorderImage(CSSPropertyID propId) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseBorderImage(CSSPropertyID propId) { BorderImageParseContext context; - if (buildBorderImageParseContext(*this, propId, context)) { + if (BorderImageParseContext::buildFromParser(*this, propId, context)) { return context.commitCSSValue(); } - return 0; + return nullptr; } static bool isBorderImageRepeatKeyword(int id) @@ -6805,10 +5913,10 @@ static bool isBorderImageRepeatKeyword(int id) return id == CSSValueStretch || id == CSSValueRepeat || id == CSSValueSpace || id == CSSValueRound; } -bool CSSParser::parseBorderImageRepeat(RefPtr<CSSValue>& result) +bool CSSPropertyParser::parseBorderImageRepeat(RefPtrWillBeRawPtr<CSSValue>& result) { - RefPtr<CSSPrimitiveValue> firstValue; - RefPtr<CSSPrimitiveValue> secondValue; + RefPtrWillBeRawPtr<CSSPrimitiveValue> firstValue = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> secondValue = nullptr; CSSParserValue* val = m_valueList->current(); if (!val) return false; @@ -6838,8 +5946,9 @@ bool CSSParser::parseBorderImageRepeat(RefPtr<CSSValue>& result) } class BorderImageSliceParseContext { + STACK_ALLOCATED(); public: - BorderImageSliceParseContext(CSSParser* parser) + BorderImageSliceParseContext(CSSPropertyParser* parser) : m_parser(parser) , m_allowNumber(true) , m_allowFill(true) @@ -6854,7 +5963,7 @@ public: void commitNumber(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v); + RefPtrWillBeRawPtr<CSSPrimitiveValue> val = m_parser->createPrimitiveNumericValue(v); if (!m_top) m_top = val; else if (!m_right) @@ -6872,7 +5981,7 @@ public: void commitFill() { m_fill = true; m_allowFill = false; m_allowNumber = !m_top; } - PassRefPtr<CSSBorderImageSliceValue> commitBorderImageSlice() + PassRefPtrWillBeRawPtr<CSSBorderImageSliceValue> commitBorderImageSlice() { // We need to clone and repeat values for any omissions. ASSERT(m_top); @@ -6889,7 +5998,7 @@ public: m_left = m_right; // Now build a rect value to hold all four of our primitive values. - RefPtr<Quad> quad = Quad::create(); + RefPtrWillBeRawPtr<Quad> quad = Quad::create(); quad->setTop(m_top); quad->setRight(m_right); quad->setBottom(m_bottom); @@ -6900,21 +6009,21 @@ public: } private: - CSSParser* m_parser; + CSSPropertyParser* m_parser; bool m_allowNumber; bool m_allowFill; bool m_allowFinalCommit; - RefPtr<CSSPrimitiveValue> m_top; - RefPtr<CSSPrimitiveValue> m_right; - RefPtr<CSSPrimitiveValue> m_bottom; - RefPtr<CSSPrimitiveValue> m_left; + RefPtrWillBeMember<CSSPrimitiveValue> m_top; + RefPtrWillBeMember<CSSPrimitiveValue> m_right; + RefPtrWillBeMember<CSSPrimitiveValue> m_bottom; + RefPtrWillBeMember<CSSPrimitiveValue> m_left; bool m_fill; }; -bool CSSParser::parseBorderImageSlice(CSSPropertyID propId, RefPtr<CSSBorderImageSliceValue>& result) +bool CSSPropertyParser::parseBorderImageSlice(CSSPropertyID propId, RefPtrWillBeRawPtr<CSSBorderImageSliceValue>& result) { BorderImageSliceParseContext context(this); CSSParserValue* val; @@ -6952,8 +6061,9 @@ bool CSSParser::parseBorderImageSlice(CSSPropertyID propId, RefPtr<CSSBorderImag } class BorderImageQuadParseContext { + STACK_ALLOCATED(); public: - BorderImageQuadParseContext(CSSParser* parser) + BorderImageQuadParseContext(CSSPropertyParser* parser) : m_parser(parser) , m_allowNumber(true) , m_allowFinalCommit(false) @@ -6965,7 +6075,7 @@ public: void commitNumber(CSSParserValue* v) { - RefPtr<CSSPrimitiveValue> val; + RefPtrWillBeRawPtr<CSSPrimitiveValue> val = nullptr; if (v->id == CSSValueAuto) val = cssValuePool().createIdentifierValue(v->id); else @@ -6986,10 +6096,9 @@ public: m_allowFinalCommit = true; } - void setAllowFinalCommit() { m_allowFinalCommit = true; } - void setTop(PassRefPtr<CSSPrimitiveValue> val) { m_top = val; } + void setTop(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) { m_top = val; } - PassRefPtr<CSSPrimitiveValue> commitBorderImageQuad() + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> commitBorderImageQuad() { // We need to clone and repeat values for any omissions. ASSERT(m_top); @@ -7006,7 +6115,7 @@ public: m_left = m_right; // Now build a quad value to hold all four of our primitive values. - RefPtr<Quad> quad = Quad::create(); + RefPtrWillBeRawPtr<Quad> quad = Quad::create(); quad->setTop(m_top); quad->setRight(m_right); quad->setBottom(m_bottom); @@ -7017,18 +6126,18 @@ public: } private: - CSSParser* m_parser; + CSSPropertyParser* m_parser; bool m_allowNumber; bool m_allowFinalCommit; - RefPtr<CSSPrimitiveValue> m_top; - RefPtr<CSSPrimitiveValue> m_right; - RefPtr<CSSPrimitiveValue> m_bottom; - RefPtr<CSSPrimitiveValue> m_left; + RefPtrWillBeMember<CSSPrimitiveValue> m_top; + RefPtrWillBeMember<CSSPrimitiveValue> m_right; + RefPtrWillBeMember<CSSPrimitiveValue> m_bottom; + RefPtrWillBeMember<CSSPrimitiveValue> m_left; }; -bool CSSParser::parseBorderImageQuad(Units validUnits, RefPtr<CSSPrimitiveValue>& result) +bool CSSPropertyParser::parseBorderImageQuad(Units validUnits, RefPtrWillBeRawPtr<CSSPrimitiveValue>& result) { BorderImageQuadParseContext context(this); CSSParserValue* val; @@ -7054,36 +6163,28 @@ bool CSSParser::parseBorderImageQuad(Units validUnits, RefPtr<CSSPrimitiveValue> return false; } -bool CSSParser::parseBorderImageWidth(RefPtr<CSSPrimitiveValue>& result) +bool CSSPropertyParser::parseBorderImageWidth(RefPtrWillBeRawPtr<CSSPrimitiveValue>& result) { return parseBorderImageQuad(FLength | FNumber | FNonNeg | FPercent, result); } -bool CSSParser::parseBorderImageOutset(RefPtr<CSSPrimitiveValue>& result) +bool CSSPropertyParser::parseBorderImageOutset(RefPtrWillBeRawPtr<CSSPrimitiveValue>& result) { return parseBorderImageQuad(FLength | FNumber | FNonNeg, result); } -static void completeBorderRadii(RefPtr<CSSPrimitiveValue> radii[4]) -{ - if (radii[3]) - return; - if (!radii[2]) { - if (!radii[1]) - radii[1] = radii[0]; - radii[2] = radii[0]; - } - radii[3] = radii[1]; -} - -bool CSSParser::parseBorderRadius(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseBorderRadius(CSSPropertyID propId, bool important) { unsigned num = m_valueList->size(); if (num > 9) return false; ShorthandScope scope(this, propId); - RefPtr<CSSPrimitiveValue> radii[2][4]; + RefPtrWillBeRawPtr<CSSPrimitiveValue> radii[2][4]; +#if ENABLE(OILPAN) + // Zero initialize the array of raw pointers. + memset(&radii, 0, sizeof(radii)); +#endif unsigned indexAfterSlash = 0; for (unsigned i = 0; i < num; ++i) { @@ -7106,7 +6207,7 @@ bool CSSParser::parseBorderRadius(CSSPropertyID propId, bool important) if (!validUnit(value, FLength | FPercent | FNonNeg)) return false; - RefPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value); + RefPtrWillBeRawPtr<CSSPrimitiveValue> radius = createPrimitiveNumericValue(value); if (!indexAfterSlash) { radii[0][i] = radius; @@ -7135,7 +6236,7 @@ bool CSSParser::parseBorderRadius(CSSPropertyID propId, bool important) return true; } -bool CSSParser::parseAspectRatio(bool important) +bool CSSPropertyParser::parseAspectRatio(bool important) { unsigned num = m_valueList->size(); if (num == 1 && m_valueList->valueAt(0)->id == CSSValueNone) { @@ -7164,12 +6265,12 @@ bool CSSParser::parseAspectRatio(bool important) return true; } -bool CSSParser::parseCounter(CSSPropertyID propId, int defaultValue, bool important) +bool CSSPropertyParser::parseCounter(CSSPropertyID propId, int defaultValue, bool important) { enum { ID, VAL } state = ID; - RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); - RefPtr<CSSPrimitiveValue> counterName; + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSPrimitiveValue> counterName = nullptr; while (true) { CSSParserValue* val = m_valueList->current(); @@ -7207,9 +6308,9 @@ bool CSSParser::parseCounter(CSSPropertyID propId, int defaultValue, bool import } // This should go away once we drop support for -webkit-gradient -static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal) { - RefPtr<CSSPrimitiveValue> result; + RefPtrWillBeRawPtr<CSSPrimitiveValue> result = nullptr; if (a->unit == CSSPrimitiveValue::CSS_IDENT) { if ((equalIgnoringCase(a, "left") && horizontal) || (equalIgnoringCase(a, "top") && !horizontal)) @@ -7219,12 +6320,13 @@ static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue result = cssValuePool().createValue(100., CSSPrimitiveValue::CSS_PERCENTAGE); else if (equalIgnoringCase(a, "center")) result = cssValuePool().createValue(50., CSSPrimitiveValue::CSS_PERCENTAGE); - } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE) - result = cssValuePool().createValue(a->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(a->unit)); + } else if (a->unit == CSSPrimitiveValue::CSS_NUMBER || a->unit == CSSPrimitiveValue::CSS_PERCENTAGE) { + result = cssValuePool().createValue(a->fValue, static_cast<CSSPrimitiveValue::UnitType>(a->unit)); + } return result; } -static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop) +bool parseDeprecatedGradientColorStop(CSSPropertyParser* p, CSSParserValue* a, CSSGradientColorStop& stop) { if (a->unit != CSSParserValue::Function) return false; @@ -7288,7 +6390,7 @@ static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CS return true; } -bool CSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient) +bool CSSPropertyParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& gradient) { // Walk the arguments. CSSParserValueList* args = valueList->current()->function->args.get(); @@ -7307,7 +6409,7 @@ bool CSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CS else return false; - RefPtr<CSSGradientValue> result; + RefPtrWillBeRawPtr<CSSGradientValue> result = nullptr; switch (gradientType) { case CSSDeprecatedLinearGradient: result = CSSLinearGradientValue::create(NonRepeating, gradientType); @@ -7331,7 +6433,7 @@ bool CSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CS a = args->next(); if (!a) return false; - RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true); + RefPtrWillBeRawPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true); if (!point) return false; result->setFirstX(point.release()); @@ -7421,10 +6523,10 @@ bool CSSParser::parseDeprecatedGradient(CSSParserValueList* valueList, RefPtr<CS return true; } -static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal) +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal) { if (a->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; + return nullptr; switch (a->id) { case CSSValueLeft: @@ -7436,12 +6538,12 @@ static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, boo isHorizontal = false; break; default: - return 0; + return nullptr; } return cssValuePool().createIdentifierValue(a->id); } -static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value) +PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSPropertyParser* p, CSSParserValue* value) { CSSValueID id = value->id; if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu || id == CSSValueCurrentcolor) @@ -7450,9 +6552,9 @@ static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, C return p->parseColor(value); } -bool CSSParser::parseDeprecatedLinearGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating) +bool CSSPropertyParser::parseDeprecatedLinearGradient(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& gradient, CSSGradientRepeat repeating) { - RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, CSSPrefixedLinearGradient); + RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, CSSPrefixedLinearGradient); // Walk the arguments. CSSParserValueList* args = valueList->current()->function->args.get(); @@ -7472,9 +6574,10 @@ bool CSSParser::parseDeprecatedLinearGradient(CSSParserValueList* valueList, Ref expectComma = true; } else { // Look one or two optional keywords that indicate a side or corner. - RefPtr<CSSPrimitiveValue> startX, startY; + RefPtrWillBeRawPtr<CSSPrimitiveValue> startX = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> startY = nullptr; - RefPtr<CSSPrimitiveValue> location; + RefPtrWillBeRawPtr<CSSPrimitiveValue> location = nullptr; bool isHorizontal = false; if ((location = valueFromSideKeyword(a, isHorizontal))) { if (isHorizontal) @@ -7518,9 +6621,9 @@ bool CSSParser::parseDeprecatedLinearGradient(CSSParserValueList* valueList, Ref return true; } -bool CSSParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating) +bool CSSPropertyParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& gradient, CSSGradientRepeat repeating) { - RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSPrefixedRadialGradient); + RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSPrefixedRadialGradient); // Walk the arguments. CSSParserValueList* args = valueList->current()->function->args.get(); @@ -7534,8 +6637,8 @@ bool CSSParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, Ref bool expectComma = false; // Optional background-position - RefPtr<CSSValue> centerX; - RefPtr<CSSValue> centerY; + RefPtrWillBeRawPtr<CSSValue> centerX = nullptr; + RefPtrWillBeRawPtr<CSSValue> centerY = nullptr; // parse2ValuesFillPosition advances the args next pointer. parse2ValuesFillPosition(args, centerX, centerY); a = args->current(); @@ -7558,8 +6661,8 @@ bool CSSParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, Ref result->setFirstY(toCSSPrimitiveValue(centerY.get())); result->setSecondY(toCSSPrimitiveValue(centerY.get())); - RefPtr<CSSPrimitiveValue> shapeValue; - RefPtr<CSSPrimitiveValue> sizeValue; + RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeValue = nullptr; // Optional shape and/or size in any order. for (int i = 0; i < 2; ++i) { @@ -7599,8 +6702,8 @@ bool CSSParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, Ref result->setSizingBehavior(sizeValue); // Or, two lengths or percentages - RefPtr<CSSPrimitiveValue> horizontalSize; - RefPtr<CSSPrimitiveValue> verticalSize; + RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr; if (!shapeValue && !sizeValue) { if (validUnit(a, FLength | FPercent)) { @@ -7636,9 +6739,9 @@ bool CSSParser::parseDeprecatedRadialGradient(CSSParserValueList* valueList, Ref return true; } -bool CSSParser::parseLinearGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating) +bool CSSPropertyParser::parseLinearGradient(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& gradient, CSSGradientRepeat repeating) { - RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, CSSLinearGradient); + RefPtrWillBeRawPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create(repeating, CSSLinearGradient); CSSParserValueList* args = valueList->current()->function->args.get(); if (!args || !args->size()) @@ -7661,8 +6764,9 @@ bool CSSParser::parseLinearGradient(CSSParserValueList* valueList, RefPtr<CSSVal if (!a) return false; - RefPtr<CSSPrimitiveValue> endX, endY; - RefPtr<CSSPrimitiveValue> location; + RefPtrWillBeRawPtr<CSSPrimitiveValue> endX = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> endY = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> location = nullptr; bool isHorizontal = false; location = valueFromSideKeyword(a, isHorizontal); @@ -7708,9 +6812,9 @@ bool CSSParser::parseLinearGradient(CSSParserValueList* valueList, RefPtr<CSSVal return true; } -bool CSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSValue>& gradient, CSSGradientRepeat repeating) +bool CSSPropertyParser::parseRadialGradient(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& gradient, CSSGradientRepeat repeating) { - RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSRadialGradient); + RefPtrWillBeRawPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::create(repeating, CSSRadialGradient); CSSParserValueList* args = valueList->current()->function->args.get(); if (!args || !args->size()) @@ -7722,10 +6826,10 @@ bool CSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSVal bool expectComma = false; - RefPtr<CSSPrimitiveValue> shapeValue; - RefPtr<CSSPrimitiveValue> sizeValue; - RefPtr<CSSPrimitiveValue> horizontalSize; - RefPtr<CSSPrimitiveValue> verticalSize; + RefPtrWillBeRawPtr<CSSPrimitiveValue> shapeValue = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> sizeValue = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> horizontalSize = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> verticalSize = nullptr; // First part of grammar, the size/shape clause: // [ circle || <length> ] | @@ -7800,8 +6904,8 @@ bool CSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSVal // Second part of grammar, the center-position clause: // at <position> - RefPtr<CSSValue> centerX; - RefPtr<CSSValue> centerY; + RefPtrWillBeRawPtr<CSSValue> centerX = nullptr; + RefPtrWillBeRawPtr<CSSValue> centerY = nullptr; if (a->unit == CSSPrimitiveValue::CSS_IDENT && equalIgnoringCase(a, "at")) { a = args->next(); if (!a) @@ -7831,7 +6935,7 @@ bool CSSParser::parseRadialGradient(CSSParserValueList* valueList, RefPtr<CSSVal return true; } -bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradientValue* gradient, bool expectComma) +bool CSSPropertyParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradientValue* gradient, bool expectComma) { CSSParserValue* a = valueList->current(); @@ -7869,36 +6973,55 @@ bool CSSParser::parseGradientColorStops(CSSParserValueList* valueList, CSSGradie return gradient->stopCount() >= 2; } -bool CSSParser::parseGeneratedImage(CSSParserValueList* valueList, RefPtr<CSSValue>& value) +bool CSSPropertyParser::parseGeneratedImage(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& value) { CSSParserValue* val = valueList->current(); if (val->unit != CSSParserValue::Function) return false; - if (equalIgnoringCase(val->function->name, "-webkit-gradient(")) + if (equalIgnoringCase(val->function->name, "-webkit-gradient(")) { + // FIXME: This should send a deprecation message. + if (m_context.useCounter()) + m_context.useCounter()->count(UseCounter::DeprecatedWebKitGradient); return parseDeprecatedGradient(valueList, value); + } - if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")) + if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")) { + // FIXME: This should send a deprecation message. + if (m_context.useCounter()) + m_context.useCounter()->count(UseCounter::DeprecatedWebKitLinearGradient); return parseDeprecatedLinearGradient(valueList, value, NonRepeating); + } if (equalIgnoringCase(val->function->name, "linear-gradient(")) return parseLinearGradient(valueList, value, NonRepeating); - if (equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")) + if (equalIgnoringCase(val->function->name, "-webkit-repeating-linear-gradient(")) { + // FIXME: This should send a deprecation message. + if (m_context.useCounter()) + m_context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingLinearGradient); return parseDeprecatedLinearGradient(valueList, value, Repeating); + } if (equalIgnoringCase(val->function->name, "repeating-linear-gradient(")) return parseLinearGradient(valueList, value, Repeating); - if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")) + if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")) { + // FIXME: This should send a deprecation message. + if (m_context.useCounter()) + m_context.useCounter()->count(UseCounter::DeprecatedWebKitRadialGradient); return parseDeprecatedRadialGradient(valueList, value, NonRepeating); + } if (equalIgnoringCase(val->function->name, "radial-gradient(")) return parseRadialGradient(valueList, value, NonRepeating); - if (equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")) + if (equalIgnoringCase(val->function->name, "-webkit-repeating-radial-gradient(")) { + if (m_context.useCounter()) + m_context.useCounter()->count(UseCounter::DeprecatedWebKitRepeatingRadialGradient); return parseDeprecatedRadialGradient(valueList, value, Repeating); + } if (equalIgnoringCase(val->function->name, "repeating-radial-gradient(")) return parseRadialGradient(valueList, value, Repeating); @@ -7912,17 +7035,15 @@ bool CSSParser::parseGeneratedImage(CSSParserValueList* valueList, RefPtr<CSSVal return false; } -bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& crossfade) +bool CSSPropertyParser::parseCrossfade(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& crossfade) { - RefPtr<CSSCrossfadeValue> result; - // Walk the arguments. CSSParserValueList* args = valueList->current()->function->args.get(); if (!args || args->size() != 5) return false; CSSParserValue* a = args->current(); - RefPtr<CSSValue> fromImageValue; - RefPtr<CSSValue> toImageValue; + RefPtrWillBeRawPtr<CSSValue> fromImageValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> toImageValue = nullptr; // The first argument is the "from" image. It is a fill image. if (!a || !parseFillImage(args, fromImageValue)) @@ -7945,7 +7066,7 @@ bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& a = args->next(); // The third argument is the crossfade value. It is a percentage or a fractional number. - RefPtr<CSSPrimitiveValue> percentage; + RefPtrWillBeRawPtr<CSSPrimitiveValue> percentage = nullptr; if (!a) return false; @@ -7956,7 +7077,7 @@ bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& else return false; - result = CSSCrossfadeValue::create(fromImageValue, toImageValue); + RefPtrWillBeRawPtr<CSSCrossfadeValue> result = CSSCrossfadeValue::create(fromImageValue, toImageValue); result->setPercentage(percentage); crossfade = result; @@ -7964,7 +7085,7 @@ bool CSSParser::parseCrossfade(CSSParserValueList* valueList, RefPtr<CSSValue>& return true; } -bool CSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& canvas) +bool CSSPropertyParser::parseCanvas(CSSParserValueList* valueList, RefPtrWillBeRawPtr<CSSValue>& canvas) { // Walk the arguments. CSSParserValueList* args = valueList->current()->function->args.get(); @@ -7980,36 +7101,36 @@ bool CSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& can return true; } -PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseImageSet(CSSParserValueList* valueList) { CSSParserValue* function = valueList->current(); if (function->unit != CSSParserValue::Function) - return 0; + return nullptr; CSSParserValueList* functionArgs = valueList->current()->function->args.get(); if (!functionArgs || !functionArgs->size() || !functionArgs->current()) - return 0; + return nullptr; - RefPtr<CSSImageSetValue> imageSet = CSSImageSetValue::create(); + RefPtrWillBeRawPtr<CSSImageSetValue> imageSet = CSSImageSetValue::create(); CSSParserValue* arg = functionArgs->current(); while (arg) { if (arg->unit != CSSPrimitiveValue::CSS_URI) - return 0; + return nullptr; - RefPtr<CSSImageValue> image = CSSImageValue::create(completeURL(arg->string)); + RefPtrWillBeRawPtr<CSSValue> image = createCSSImageValueWithReferrer(arg->string, completeURL(arg->string)); imageSet->append(image); arg = functionArgs->next(); if (!arg || arg->unit != CSSPrimitiveValue::CSS_DIMENSION) - return 0; + return nullptr; double imageScaleFactor = 0; const String& string = arg->string; unsigned length = string.length(); if (!length) - return 0; + return nullptr; if (string.is8Bit()) { const LChar* start = string.characters8(); parseDouble(start, start + length, 'x', imageScaleFactor); @@ -8018,7 +7139,7 @@ PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList) parseDouble(start, start + length, 'x', imageScaleFactor); } if (imageScaleFactor <= 0) - return 0; + return nullptr; imageSet->append(cssValuePool().createValue(imageScaleFactor, CSSPrimitiveValue::CSS_NUMBER)); // If there are no more arguments, we're done. @@ -8028,7 +7149,7 @@ PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList) // If there are more arguments, they should be after a comma. if (!isComma(arg)) - return 0; + return nullptr; // Skip the comma and move on to the next argument. arg = functionArgs->next(); @@ -8037,234 +7158,63 @@ PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList) return imageSet.release(); } -class TransformOperationInfo { -public: - TransformOperationInfo(const CSSParserString& name) - : m_type(CSSTransformValue::UnknownTransformOperation) - , m_argCount(1) - , m_allowSingleArgument(false) - , m_unit(CSSParser::FUnknown) - { - const UChar* characters; - unsigned nameLength = name.length(); - - const unsigned longestNameLength = 12; - UChar characterBuffer[longestNameLength]; - if (name.is8Bit()) { - unsigned length = std::min(longestNameLength, nameLength); - const LChar* characters8 = name.characters8(); - for (unsigned i = 0; i < length; ++i) - characterBuffer[i] = characters8[i]; - characters = characterBuffer; - } else - characters = name.characters16(); - - SWITCH(characters, nameLength) { - CASE("skew(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::SkewTransformOperation; - m_allowSingleArgument = true; - m_argCount = 3; - } - CASE("scale(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::ScaleTransformOperation; - m_allowSingleArgument = true; - m_argCount = 3; - } - CASE("skewx(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::SkewXTransformOperation; - } - CASE("skewy(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::SkewYTransformOperation; - } - CASE("matrix(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::MatrixTransformOperation; - m_argCount = 11; - } - CASE("rotate(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::RotateTransformOperation; - } - CASE("scalex(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::ScaleXTransformOperation; - } - CASE("scaley(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::ScaleYTransformOperation; - } - CASE("scalez(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::ScaleZTransformOperation; - } - CASE("scale3d(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::Scale3DTransformOperation; - m_argCount = 5; - } - CASE("rotatex(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::RotateXTransformOperation; - } - CASE("rotatey(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::RotateYTransformOperation; - } - CASE("rotatez(") { - m_unit = CSSParser::FAngle; - m_type = CSSTransformValue::RotateZTransformOperation; - } - CASE("matrix3d(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::Matrix3DTransformOperation; - m_argCount = 31; - } - CASE("rotate3d(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::Rotate3DTransformOperation; - m_argCount = 7; - } - CASE("translate(") { - m_unit = CSSParser::FLength | CSSParser::FPercent; - m_type = CSSTransformValue::TranslateTransformOperation; - m_allowSingleArgument = true; - m_argCount = 3; - } - CASE("translatex(") { - m_unit = CSSParser::FLength | CSSParser::FPercent; - m_type = CSSTransformValue::TranslateXTransformOperation; - } - CASE("translatey(") { - m_unit = CSSParser::FLength | CSSParser::FPercent; - m_type = CSSTransformValue::TranslateYTransformOperation; - } - CASE("translatez(") { - m_unit = CSSParser::FLength | CSSParser::FPercent; - m_type = CSSTransformValue::TranslateZTransformOperation; - } - CASE("perspective(") { - m_unit = CSSParser::FNumber; - m_type = CSSTransformValue::PerspectiveTransformOperation; - } - CASE("translate3d(") { - m_unit = CSSParser::FLength | CSSParser::FPercent; - m_type = CSSTransformValue::Translate3DTransformOperation; - m_argCount = 5; - } - } - } - - CSSTransformValue::TransformOperationType type() const { return m_type; } - unsigned argCount() const { return m_argCount; } - CSSParser::Units unit() const { return m_unit; } - - bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; } - bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); } - -private: - CSSTransformValue::TransformOperationType m_type; - unsigned m_argCount; - bool m_allowSingleArgument; - CSSParser::Units m_unit; -}; - -PassRefPtr<CSSValueList> CSSParser::parseTransform() +bool CSSPropertyParser::parseWillChange(bool important) { - if (!m_valueList) - return 0; + ASSERT(RuntimeEnabledFeatures::cssWillChangeEnabled()); - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { - RefPtr<CSSValue> parsedTransformValue = parseTransformValue(value); - if (!parsedTransformValue) - return 0; - - list->append(parsedTransformValue.release()); + RefPtrWillBeRawPtr<CSSValueList> values = CSSValueList::createCommaSeparated(); + if (m_valueList->current()->id == CSSValueAuto) { + if (m_valueList->next()) + return false; } - return list.release(); -} - -PassRefPtr<CSSValue> CSSParser::parseTransformValue(CSSParserValue *value) -{ - if (value->unit != CSSParserValue::Function || !value->function) - return 0; - - // Every primitive requires at least one argument. - CSSParserValueList* args = value->function->args.get(); - if (!args) - return 0; - - // See if the specified primitive is one we understand. - TransformOperationInfo info(value->function->name); - if (info.unknown()) - return 0; - - if (!info.hasCorrectArgCount(args->size())) - return 0; - - // The transform is a list of functional primitives that specify transform operations. - // We collect a list of CSSTransformValues, where each value specifies a single operation. - - // Create the new CSSTransformValue for this operation and add it to our list. - RefPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type()); - - // Snag our values. - CSSParserValue* a = args->current(); - unsigned argNumber = 0; - while (a) { - CSSParser::Units unit = info.unit(); - - if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) { - // 4th param of rotate3d() is an angle rather than a bare number, validate it as such - if (!validUnit(a, FAngle, HTMLStandardMode)) - return 0; - } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) { - // 3rd param of translate3d() cannot be a percentage - if (!validUnit(a, FLength, HTMLStandardMode)) - return 0; - } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) { - // 1st param of translateZ() cannot be a percentage - if (!validUnit(a, FLength, HTMLStandardMode)) - return 0; - } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) { - // 1st param of perspective() must be a non-negative number (deprecated) or length. - if (!validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode)) - return 0; - } else if (!validUnit(a, unit, HTMLStandardMode)) - return 0; + CSSParserValue* currentValue; + bool expectComma = false; - // Add the value to the current transform operation. - transformValue->append(createPrimitiveNumericValue(a)); + // Every comma-separated list of CSS_IDENTs is a valid will-change value, + // unless the list includes an explicitly disallowed CSS_IDENT. + while ((currentValue = m_valueList->current())) { + if (expectComma) { + if (!isComma(currentValue)) + return false; + expectComma = false; + m_valueList->next(); + continue; + } - a = args->next(); - if (!a) - break; - if (a->unit != CSSParserValue::Operator || a->iValue != ',') - return 0; - a = args->next(); + if (currentValue->unit != CSSPrimitiveValue::CSS_IDENT) + return false; - argNumber++; + CSSPropertyID property = cssPropertyID(currentValue->string); + if (property && RuntimeCSSEnabled::isCSSPropertyEnabled(property)) { + // Now "all" is used by both CSSValue and CSSPropertyValue. + // Need to return false when currentValue is CSSPropertyAll. + if (property == CSSPropertyWillChange || property == CSSPropertyAll) + return false; + values->append(cssValuePool().createIdentifierValue(property)); + } else { + switch (currentValue->id) { + case CSSValueNone: + case CSSValueAll: + case CSSValueAuto: + case CSSValueDefault: + case CSSValueInitial: + case CSSValueInherit: + return false; + case CSSValueContents: + case CSSValueScrollPosition: + values->append(cssValuePool().createIdentifierValue(currentValue->id)); + break; + default: + break; + } + } + expectComma = true; + m_valueList->next(); } - return transformValue.release(); -} - -bool CSSParser::isBlendMode(CSSValueID valueID) -{ - return (valueID >= CSSValueMultiply && valueID <= CSSValueLuminosity) - || valueID == CSSValueNormal - || valueID == CSSValueOverlay; -} - -bool CSSParser::isCompositeOperator(CSSValueID valueID) -{ - // FIXME: Add CSSValueDestination and CSSValueLighter when the Compositing spec updates. - return valueID >= CSSValueClear && valueID <= CSSValueXor; + addProperty(CSSPropertyWillChange, values.release(), important); + return true; } static void filterInfoForName(const CSSParserString& name, CSSFilterValue::FilterOperationType& filterType, unsigned& maximumArgumentCount) @@ -8291,425 +7241,11 @@ static void filterInfoForName(const CSSParserString& name, CSSFilterValue::Filte filterType = CSSFilterValue::DropShadowFilterOperation; maximumArgumentCount = 4; // x-offset, y-offset, blur-radius, color -- spread and inset style not allowed. } - else if (equalIgnoringCase(name, "custom(")) - filterType = CSSFilterValue::CustomFilterOperation; -} - -static bool acceptCommaOperator(CSSParserValueList* argsList) -{ - if (CSSParserValue* arg = argsList->current()) { - if (!isComma(arg)) - return false; - argsList->next(); - } - return true; -} - -PassRefPtr<CSSArrayFunctionValue> CSSParser::parseCustomFilterArrayFunction(CSSParserValue* value) -{ - ASSERT(value->unit == CSSParserValue::Function && value->function); - - if (!equalIgnoringCase(value->function->name, "array(")) - return 0; - - CSSParserValueList* arrayArgsParserValueList = value->function->args.get(); - if (!arrayArgsParserValueList || !arrayArgsParserValueList->size()) - return 0; - - // array() values are comma separated. - RefPtr<CSSArrayFunctionValue> arrayFunction = CSSArrayFunctionValue::create(); - while (true) { - // We parse pairs <Value, Comma> at each step. - CSSParserValue* currentParserValue = arrayArgsParserValueList->current(); - if (!currentParserValue || !validUnit(currentParserValue, FNumber, HTMLStandardMode)) - return 0; - - RefPtr<CSSValue> arrayValue = cssValuePool().createValue(currentParserValue->fValue, CSSPrimitiveValue::CSS_NUMBER); - arrayFunction->append(arrayValue.release()); - - CSSParserValue* nextParserValue = arrayArgsParserValueList->next(); - if (!nextParserValue) - break; - - if (!isComma(nextParserValue)) - return 0; - - arrayArgsParserValueList->next(); - } - - return arrayFunction; -} - -PassRefPtr<CSSMixFunctionValue> CSSParser::parseMixFunction(CSSParserValue* value) -{ - ASSERT(value->unit == CSSParserValue::Function && value->function); - - if (!equalIgnoringCase(value->function->name, "mix(")) - return 0; - - CSSParserValueList* argsList = value->function->args.get(); - if (!argsList) - return 0; - - unsigned numArgs = argsList->size(); - if (numArgs < 1 || numArgs > 3) - return 0; - - RefPtr<CSSMixFunctionValue> mixFunction = CSSMixFunctionValue::create(); - - bool hasBlendMode = false; - bool hasAlphaCompositing = false; - - for (CSSParserValue* arg = argsList->current(); arg; arg = argsList->next()) { - RefPtr<CSSValue> value; - - unsigned argNumber = argsList->currentIndex(); - if (!argNumber) { - if (arg->unit == CSSPrimitiveValue::CSS_URI) { - KURL shaderURL = completeURL(arg->string); - value = CSSShaderValue::create(shaderURL.string()); - } - } else if (argNumber == 1 || argNumber == 2) { - if (!hasBlendMode && isBlendMode(arg->id)) { - hasBlendMode = true; - value = cssValuePool().createIdentifierValue(arg->id); - } else if (!hasAlphaCompositing && isCompositeOperator(arg->id)) { - hasAlphaCompositing = true; - value = cssValuePool().createIdentifierValue(arg->id); - } - } - - if (!value) - return 0; - - mixFunction->append(value.release()); - } - - return mixFunction; -} - -PassRefPtr<CSSValueList> CSSParser::parseCustomFilterParameters(CSSParserValueList* argsList) -{ - // - // params: [<param-def>[,<param-def>*]] - // param-def: <param-name>wsp<param-value> - // param-name: <ident> - // param-value: true|false[wsp+true|false]{0-3} | - // <number>[wsp+<number>]{0-3} | - // <array> | - // <transform> | - // <texture(<uri>)> - // array: 'array('<number>[wsp<number>]*')' - // css-3d-transform: <transform-function>;[<transform-function>]* - // transform: <css-3d-transform> | <mat> - // mat: 'mat2('<number>(,<number>){3}')' | - // 'mat3('<number>(,<number>){8}')' | - // 'mat4('<number>(,<number>){15}')' ) - // - - RefPtr<CSSValueList> paramList = CSSValueList::createCommaSeparated(); - - while (CSSParserValue* arg = argsList->current()) { - if (arg->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; - - RefPtr<CSSValueList> parameter = CSSValueList::createSpaceSeparated(); - parameter->append(createPrimitiveStringValue(arg)); - - arg = argsList->next(); - if (!arg) - return 0; - - RefPtr<CSSValue> parameterValue; - - if (arg->unit == CSSParserValue::Function && arg->function) { - // FIXME: Implement parsing for the other parameter types. - // textures: https://bugs.webkit.org/show_bug.cgi?id=71442 - // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444 - if (equalIgnoringCase(arg->function->name, "array(")) { - parameterValue = parseCustomFilterArrayFunction(arg); - // This parsing step only consumes function arguments, - // argsList is therefore moved forward explicitely. - argsList->next(); - } else - parameterValue = parseCustomFilterTransform(argsList); - } else { - RefPtr<CSSValueList> paramValueList = CSSValueList::createSpaceSeparated(); - arg = argsList->current(); - while (arg) { - // If we hit a comma, it means that we finished this parameter's values. - if (isComma(arg)) - break; - if (!validUnit(arg, FNumber, HTMLStandardMode)) - return 0; - paramValueList->append(cssValuePool().createValue(arg->fValue, CSSPrimitiveValue::CSS_NUMBER)); - arg = argsList->next(); - } - if (!paramValueList->length() || paramValueList->length() > 4) - return 0; - parameterValue = paramValueList.release(); - } - - if (!parameterValue || !acceptCommaOperator(argsList)) - return 0; - - parameter->append(parameterValue.release()); - paramList->append(parameter.release()); - } - - return paramList; -} - -PassRefPtr<CSSFilterValue> CSSParser::parseCustomFilterFunctionWithAtRuleReferenceSyntax(CSSParserValue* value) -{ - // - // Custom filter function "at-rule reference" syntax: - // - // custom(<filter-name>wsp[,wsp<params>]) - // - // filter-name: <filter-name> - // params: See the comment in CSSParser::parseCustomFilterParameters. - // - - ASSERT(value->function); - - CSSParserValueList* argsList = value->function->args.get(); - if (!argsList || !argsList->size()) - return 0; - - // 1. Parse the filter name. - CSSParserValue* arg = argsList->current(); - if (arg->unit != CSSPrimitiveValue::CSS_IDENT) - return 0; - - RefPtr<CSSFilterValue> filterValue = CSSFilterValue::create(CSSFilterValue::CustomFilterOperation); - - RefPtr<CSSValue> filterName = createPrimitiveStringValue(arg); - filterValue->append(filterName); - argsList->next(); - - if (!acceptCommaOperator(argsList)) - return 0; - - // 2. Parse the parameters. - RefPtr<CSSValueList> paramList = parseCustomFilterParameters(argsList); - if (!paramList) - return 0; - - if (paramList->length()) - filterValue->append(paramList.release()); - - return filterValue; -} - -// FIXME: The custom filters "inline" syntax is deprecated. We will remove it eventually. -PassRefPtr<CSSFilterValue> CSSParser::parseCustomFilterFunctionWithInlineSyntax(CSSParserValue* value) -{ - // - // Custom filter function "inline" syntax: - // - // custom(<vertex-shader>[wsp<fragment-shader>][,<vertex-mesh>][,<params>]) - // - // vertexShader: <uri> | none - // fragmentShader: <uri> | none | mix(<uri> [ <blend-mode> || <alpha-compositing> ]?) - // - // blend-mode: normal | multiply | screen | overlay | darken | lighten | color-dodge | - // color-burn | hard-light | soft-light | difference | exclusion | hue | - // saturation | color | luminosity - // alpha-compositing: clear | src | dst | src-over | dst-over | src-in | dst-in | - // src-out | dst-out | src-atop | dst-atop | xor | plus - // - // vertexMesh: +<integer>{1,2}[wsp<box>][wsp'detached'] - // box: filter-box | border-box | padding-box | content-box - // - // params: See the comment in CSSParser::parseCustomFilterParameters. - // - - ASSERT(value->function); - - CSSParserValueList* argsList = value->function->args.get(); - if (!argsList) - return 0; - - RefPtr<CSSFilterValue> filterValue = CSSFilterValue::create(CSSFilterValue::CustomFilterOperation); - - // 1. Parse the shader URLs: <vertex-shader>[wsp<fragment-shader>] - RefPtr<CSSValueList> shadersList = CSSValueList::createSpaceSeparated(); - bool hadAtLeastOneCustomShader = false; - CSSParserValue* arg; - for (arg = argsList->current(); arg; arg = argsList->next()) { - RefPtr<CSSValue> value; - if (arg->id == CSSValueNone) - value = cssValuePool().createIdentifierValue(CSSValueNone); - else if (arg->unit == CSSPrimitiveValue::CSS_URI) { - KURL shaderURL = completeURL(arg->string); - value = CSSShaderValue::create(shaderURL.string()); - hadAtLeastOneCustomShader = true; - } else if (argsList->currentIndex() == 1 && arg->unit == CSSParserValue::Function) { - if (!(value = parseMixFunction(arg))) - return 0; - hadAtLeastOneCustomShader = true; - } - - if (!value) - break; - shadersList->append(value.release()); - } - - if (!shadersList->length() || !hadAtLeastOneCustomShader || shadersList->length() > 2 || !acceptCommaOperator(argsList)) - return 0; - - filterValue->append(shadersList.release()); - - // 2. Parse the mesh size <vertex-mesh> - RefPtr<CSSValueList> meshSizeList = CSSValueList::createSpaceSeparated(); - - for (arg = argsList->current(); arg; arg = argsList->next()) { - if (!validUnit(arg, FInteger | FNonNeg, HTMLStandardMode)) - break; - int integerValue = clampToInteger(arg->fValue); - // According to the specification we can only accept positive non-zero values. - if (integerValue < 1) - return 0; - meshSizeList->append(cssValuePool().createValue(integerValue, CSSPrimitiveValue::CSS_NUMBER)); - } - - if (meshSizeList->length() > 2) - return 0; - - // FIXME: For legacy content, we accept the mesh box types. We don't do anything else with them. - // Eventually, we'll remove them completely. - // https://bugs.webkit.org/show_bug.cgi?id=103778 - if ((arg = argsList->current()) && (arg->id == CSSValueBorderBox || arg->id == CSSValuePaddingBox - || arg->id == CSSValueContentBox || arg->id == CSSValueFilterBox)) - argsList->next(); - - if ((arg = argsList->current()) && arg->id == CSSValueDetached) { - meshSizeList->append(cssValuePool().createIdentifierValue(arg->id)); - argsList->next(); - } - - if (meshSizeList->length()) { - if (!acceptCommaOperator(argsList)) - return 0; - filterValue->append(meshSizeList.release()); - } - - // 3. Parse the parameters. - RefPtr<CSSValueList> paramList = parseCustomFilterParameters(argsList); - if (!paramList) - return 0; - - if (paramList->length()) - filterValue->append(paramList.release()); - - return filterValue; -} - -PassRefPtr<CSSFilterValue> CSSParser::parseCustomFilterFunction(CSSParserValue* value) -{ - ASSERT(value->function); - - // Look ahead to determine which syntax the custom function is using. - // Both the at-rule reference syntax and the inline syntax require at least one argument. - CSSParserValueList* argsList = value->function->args.get(); - if (!argsList || !argsList->size()) - return 0; - - // The at-rule reference syntax expects a single ident or an ident followed by a comma. - // e.g. custom(my-filter) or custom(my-filter, ...) - // In contrast, when the inline syntax starts with an ident like "none", it expects a uri or a mix function next. - // e.g. custom(none url(...)) or custom(none mix(...) - bool isAtRuleReferenceSyntax = argsList->valueAt(0)->unit == CSSPrimitiveValue::CSS_IDENT - && (argsList->size() == 1 || isComma(argsList->valueAt(1))); - return isAtRuleReferenceSyntax ? parseCustomFilterFunctionWithAtRuleReferenceSyntax(value) : parseCustomFilterFunctionWithInlineSyntax(value); -} - -PassRefPtr<CSSValueList> CSSParser::parseCustomFilterTransform(CSSParserValueList* valueList) -{ - if (!valueList) - return 0; - - // CSS Shaders' custom() transforms are space separated and comma terminated. - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - for (CSSParserValue* value = valueList->current(); value; value = valueList->next()) { - if (isComma(value)) - break; - - RefPtr<CSSValue> parsedTransformValue = parseTransformValue(value); - if (!parsedTransformValue) - return 0; - - list->append(parsedTransformValue.release()); - } - - return list.release(); -} - -PassRefPtr<CSSShaderValue> CSSParser::parseFilterRuleSrcUriAndFormat(CSSParserValueList* valueList) -{ - CSSParserValue* value = valueList->current(); - ASSERT(value && value->unit == CSSPrimitiveValue::CSS_URI); - RefPtr<CSSShaderValue> shaderValue = CSSShaderValue::create(completeURL(value->string)); - - value = valueList->next(); - if (value && value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "format(")) { - CSSParserValueList* args = value->function->args.get(); - if (!args || args->size() != 1) - return 0; - - CSSParserValue* arg = args->current(); - if (arg->unit != CSSPrimitiveValue::CSS_STRING) - return 0; - - shaderValue->setFormat(arg->string); - valueList->next(); - } - - return shaderValue.release(); -} - -bool CSSParser::parseFilterRuleSrc() -{ - RefPtr<CSSValueList> srcList = CSSValueList::createCommaSeparated(); - - CSSParserValue* value = m_valueList->current(); - while (value) { - if (value->unit != CSSPrimitiveValue::CSS_URI) - return false; - - RefPtr<CSSShaderValue> shaderValue = parseFilterRuleSrcUriAndFormat(m_valueList.get()); - if (!shaderValue) - return false; - srcList->append(shaderValue.release()); - - if (!acceptCommaOperator(m_valueList.get())) - return false; - - value = m_valueList->current(); - } - - if (!srcList->length()) - return false; - - addProperty(CSSPropertySrc, srcList.release(), m_important); - return true; -} - -StyleRuleBase* CSSParser::createFilterRule(const CSSParserString& filterName) -{ - RefPtr<StyleRuleFilter> rule = StyleRuleFilter::create(filterName); - rule->setProperties(createStylePropertySet()); - clearProperties(); - StyleRuleFilter* result = rule.get(); - m_parsedRules.append(rule.release()); - return result; } - -PassRefPtr<CSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValueList* args, CSSFilterValue::FilterOperationType filterType) +PassRefPtrWillBeRawPtr<CSSFilterValue> CSSPropertyParser::parseBuiltinFilterArguments(CSSParserValueList* args, CSSFilterValue::FilterOperationType filterType) { - RefPtr<CSSFilterValue> filterValue = CSSFilterValue::create(filterType); + RefPtrWillBeRawPtr<CSSFilterValue> filterValue = CSSFilterValue::create(filterType); ASSERT(args); switch (filterType) { @@ -8721,12 +7257,12 @@ PassRefPtr<CSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValue case CSSFilterValue::ContrastFilterOperation: { // One optional argument, 0-1 or 0%-100%, if missing use 100%. if (args->size() > 1) - return 0; + return nullptr; if (args->size()) { CSSParserValue* value = args->current(); if (!validUnit(value, FNumber | FPercent | FNonNeg, HTMLStandardMode)) - return 0; + return nullptr; double amount = value->fValue; @@ -8735,36 +7271,36 @@ PassRefPtr<CSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValue && filterType != CSSFilterValue::ContrastFilterOperation) { double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0; if (amount > maxAllowed) - return 0; + return nullptr; } - filterValue->append(cssValuePool().createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); + filterValue->append(cssValuePool().createValue(amount, static_cast<CSSPrimitiveValue::UnitType>(value->unit))); } break; } case CSSFilterValue::BrightnessFilterOperation: { // One optional argument, if missing use 100%. if (args->size() > 1) - return 0; + return nullptr; if (args->size()) { CSSParserValue* value = args->current(); if (!validUnit(value, FNumber | FPercent, HTMLStandardMode)) - return 0; + return nullptr; - filterValue->append(cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit))); + filterValue->append(cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitType>(value->unit))); } break; } case CSSFilterValue::HueRotateFilterOperation: { // hue-rotate() takes one optional angle. if (args->size() > 1) - return 0; + return nullptr; if (args->size()) { CSSParserValue* argument = args->current(); if (!validUnit(argument, FAngle, HTMLStandardMode)) - return 0; + return nullptr; filterValue->append(createPrimitiveNumericValue(argument)); } @@ -8773,12 +7309,12 @@ PassRefPtr<CSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValue case CSSFilterValue::BlurFilterOperation: { // Blur takes a single length. Zero parameters are allowed. if (args->size() > 1) - return 0; + return nullptr; if (args->size()) { CSSParserValue* argument = args->current(); if (!validUnit(argument, FLength | FNonNeg, HTMLStandardMode)) - return 0; + return nullptr; filterValue->append(createPrimitiveNumericValue(argument)); } @@ -8786,9 +7322,9 @@ PassRefPtr<CSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValue } case CSSFilterValue::DropShadowFilterOperation: { // drop-shadow() takes a single shadow. - RefPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter); + RefPtrWillBeRawPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter); if (!shadowValueList || shadowValueList->length() != 1) - return 0; + return nullptr; filterValue->append((shadowValueList.release())->itemWithoutBoundsCheck(0)); break; @@ -8799,22 +7335,22 @@ PassRefPtr<CSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValue return filterValue.release(); } -PassRefPtr<CSSValueList> CSSParser::parseFilter() +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseFilter() { if (!m_valueList) - return 0; + return nullptr; // The filter is a list of functional primitives that specify individual operations. - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { if (value->unit != CSSPrimitiveValue::CSS_URI && (value->unit != CSSParserValue::Function || !value->function)) - return 0; + return nullptr; CSSFilterValue::FilterOperationType filterType = CSSFilterValue::UnknownFilterOperation; // See if the specified primitive is one we understand. if (value->unit == CSSPrimitiveValue::CSS_URI) { - RefPtr<CSSFilterValue> referenceFilterValue = CSSFilterValue::create(CSSFilterValue::ReferenceFilterOperation); + RefPtrWillBeRawPtr<CSSFilterValue> referenceFilterValue = CSSFilterValue::create(CSSFilterValue::ReferenceFilterOperation); list->append(referenceFilterValue); referenceFilterValue->append(CSSSVGDocumentValue::create(value->string)); } else { @@ -8824,26 +7360,15 @@ PassRefPtr<CSSValueList> CSSParser::parseFilter() filterInfoForName(name, filterType, maximumArgumentCount); if (filterType == CSSFilterValue::UnknownFilterOperation) - return 0; + return nullptr; - if (filterType == CSSFilterValue::CustomFilterOperation) { - // Make sure parsing fails if custom filters are disabled. - if (!RuntimeEnabledFeatures::cssCustomFilterEnabled()) - return 0; - - RefPtr<CSSFilterValue> filterValue = parseCustomFilterFunction(value); - if (!filterValue) - return 0; - list->append(filterValue.release()); - continue; - } CSSParserValueList* args = value->function->args.get(); if (!args) - return 0; + return nullptr; - RefPtr<CSSFilterValue> filterValue = parseBuiltinFilterArguments(args, filterType); + RefPtrWillBeRawPtr<CSSFilterValue> filterValue = parseBuiltinFilterArguments(args, filterType); if (!filterValue) - return 0; + return nullptr; list->append(filterValue); } @@ -8851,90 +7376,71 @@ PassRefPtr<CSSValueList> CSSParser::parseFilter() return list.release(); } - -static bool validFlowName(const String& flowName) -{ - return !(equalIgnoringCase(flowName, "auto") - || equalIgnoringCase(flowName, "default") - || equalIgnoringCase(flowName, "inherit") - || equalIgnoringCase(flowName, "initial") - || equalIgnoringCase(flowName, "none")); -} - -bool CSSParser::parseFlowThread(const String& flowName) -{ - setupParser("@-internal-decls -webkit-flow-into:", flowName, ""); - cssyyparse(this); - - m_rule = 0; - - return ((m_parsedProperties.size() == 1) && (m_parsedProperties.first().id() == CSSPropertyWebkitFlowInto)); -} - -// none | <ident> -bool CSSParser::parseFlowThread(CSSPropertyID propId, bool important) +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransformOrigin() { - ASSERT(propId == CSSPropertyWebkitFlowInto); - ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled()); - - if (m_valueList->size() != 1) - return false; - CSSParserValue* value = m_valueList->current(); - if (!value) - return false; - - if (value->unit != CSSPrimitiveValue::CSS_IDENT) - return false; - - if (value->id == CSSValueNone) { - addProperty(propId, cssValuePool().createIdentifierValue(value->id), important); - return true; + CSSValueID id = value->id; + RefPtrWillBeRawPtr<CSSValue> xValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> yValue = nullptr; + RefPtrWillBeRawPtr<CSSValue> zValue = nullptr; + if (id == CSSValueLeft || id == CSSValueRight) { + xValue = cssValuePool().createIdentifierValue(id); + } else if (id == CSSValueTop || id == CSSValueBottom) { + yValue = cssValuePool().createIdentifierValue(id); + } else if (id == CSSValueCenter) { + // Unresolved as to whether this is X or Y. + } else if (validUnit(value, FPercent | FLength)) { + xValue = createPrimitiveNumericValue(value); + } else { + return nullptr; } - String inputProperty = String(value->string); - if (!inputProperty.isEmpty()) { - if (!validFlowName(inputProperty)) - return false; - addProperty(propId, cssValuePool().createValue(inputProperty, CSSPrimitiveValue::CSS_STRING), important); - } else - addProperty(propId, cssValuePool().createIdentifierValue(CSSValueNone), important); - - return true; -} - -// -webkit-flow-from: none | <ident> -bool CSSParser::parseRegionThread(CSSPropertyID propId, bool important) -{ - ASSERT(propId == CSSPropertyWebkitFlowFrom); - ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled()); - - if (m_valueList->size() != 1) - return false; + if ((value = m_valueList->next())) { + id = value->id; + if (!xValue && (id == CSSValueLeft || id == CSSValueRight)) { + xValue = cssValuePool().createIdentifierValue(id); + } else if (!yValue && (id == CSSValueTop || id == CSSValueBottom)) { + yValue = cssValuePool().createIdentifierValue(id); + } else if (id == CSSValueCenter) { + // Resolved below. + } else if (!yValue && validUnit(value, FPercent | FLength)) { + yValue = createPrimitiveNumericValue(value); + } else { + return nullptr; + } - CSSParserValue* value = m_valueList->current(); - if (!value) - return false; + // If X or Y have not been resolved, they must be center. + if (!xValue) + xValue = cssValuePool().createIdentifierValue(CSSValueCenter); + if (!yValue) + yValue = cssValuePool().createIdentifierValue(CSSValueCenter); - if (value->unit != CSSPrimitiveValue::CSS_IDENT) - return false; + if ((value = m_valueList->next())) { + if (!validUnit(value, FLength)) + return nullptr; + zValue = createPrimitiveNumericValue(value); - if (value->id == CSSValueNone) - addProperty(propId, cssValuePool().createIdentifierValue(value->id), important); - else { - String inputProperty = String(value->string); - if (!inputProperty.isEmpty()) { - if (!validFlowName(inputProperty)) - return false; - addProperty(propId, cssValuePool().createValue(inputProperty, CSSPrimitiveValue::CSS_STRING), important); - } else - addProperty(propId, cssValuePool().createIdentifierValue(CSSValueNone), important); + if ((value = m_valueList->next())) + return nullptr; + } + } else if (!xValue) { + if (yValue) { + xValue = cssValuePool().createValue(50, CSSPrimitiveValue::CSS_PERCENTAGE); + } else { + xValue = cssValuePool().createIdentifierValue(CSSValueCenter); + } } - return true; + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + list->append(xValue.release()); + if (yValue) + list->append(yValue.release()); + if (zValue) + list->append(zValue.release()); + return list.release(); } -bool CSSParser::parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3) +bool CSSPropertyParser::parseWebkitTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtrWillBeRawPtr<CSSValue>& value, RefPtrWillBeRawPtr<CSSValue>& value2, RefPtrWillBeRawPtr<CSSValue>& value3) { propId1 = propId; propId2 = propId; @@ -8947,9 +7453,9 @@ bool CSSParser::parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId switch (propId) { case CSSPropertyWebkitTransformOrigin: - if (!parseTransformOriginShorthand(value, value2, value3)) + if (!parseWebkitTransformOriginShorthand(value, value2, value3)) return false; - // parseTransformOriginShorthand advances the m_valueList pointer + // parseWebkitTransformOriginShorthand advances the m_valueList pointer break; case CSSPropertyWebkitTransformOriginX: { value = parseFillPositionX(m_valueList.get()); @@ -8978,7 +7484,7 @@ bool CSSParser::parseTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId return value; } -bool CSSParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtr<CSSValue>& value, RefPtr<CSSValue>& value2) +bool CSSPropertyParser::parseWebkitPerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtrWillBeRawPtr<CSSValue>& value, RefPtrWillBeRawPtr<CSSValue>& value2) { propId1 = propId; propId2 = propId; @@ -9013,14 +7519,14 @@ bool CSSParser::parsePerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& prop return value; } -bool CSSParser::parseTouchAction(bool important) +bool CSSPropertyParser::parseTouchAction(bool important) { if (!RuntimeEnabledFeatures::cssTouchActionEnabled()) return false; CSSParserValue* value = m_valueList->current(); - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - if (m_valueList->size() == 1 && value && (value->id == CSSValueAuto || value->id == CSSValueNone)) { + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + if (m_valueList->size() == 1 && value && (value->id == CSSValueAuto || value->id == CSSValueNone || value->id == CSSValueManipulation)) { list->append(cssValuePool().createIdentifierValue(value->id)); addProperty(CSSPropertyTouchAction, list.release(), important); m_valueList->next(); @@ -9032,7 +7538,7 @@ bool CSSParser::parseTouchAction(bool important) switch (value->id) { case CSSValuePanX: case CSSValuePanY: { - RefPtr<CSSValue> panValue = cssValuePool().createIdentifierValue(value->id); + RefPtrWillBeRawPtr<CSSValue> panValue = cssValuePool().createIdentifierValue(value->id); if (list->hasValue(panValue.get())) { isValid = false; break; @@ -9056,7 +7562,7 @@ bool CSSParser::parseTouchAction(bool important) return false; } -void CSSParser::addTextDecorationProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important) +void CSSPropertyParser::addTextDecorationProperty(CSSPropertyID propId, PassRefPtrWillBeRawPtr<CSSValue> value, bool important) { // The text-decoration-line property takes priority over text-decoration, unless the latter has important priority set. if (propId == CSSPropertyTextDecoration && !important && !inShorthand()) { @@ -9068,7 +7574,7 @@ void CSSParser::addTextDecorationProperty(CSSPropertyID propId, PassRefPtr<CSSVa addProperty(propId, value, important); } -bool CSSParser::parseTextDecoration(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseTextDecoration(CSSPropertyID propId, bool important) { if (propId == CSSPropertyTextDecorationLine && !RuntimeEnabledFeatures::css3TextDecorationsEnabled()) @@ -9081,7 +7587,7 @@ bool CSSParser::parseTextDecoration(CSSPropertyID propId, bool important) return true; } - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); bool isValid = true; while (isValid && value) { switch (value->id) { @@ -9108,7 +7614,7 @@ bool CSSParser::parseTextDecoration(CSSPropertyID propId, bool important) return false; } -bool CSSParser::parseTextUnderlinePosition(bool important) +bool CSSPropertyParser::parseTextUnderlinePosition(bool important) { // The text-underline-position property has syntax "auto | [ under || [ left | right ] ]". // However, values 'left' and 'right' are not implemented yet, so we will parse syntax @@ -9126,12 +7632,12 @@ bool CSSParser::parseTextUnderlinePosition(bool important) } } -bool CSSParser::parseTextEmphasisStyle(bool important) +bool CSSPropertyParser::parseTextEmphasisStyle(bool important) { unsigned valueListSize = m_valueList->size(); - RefPtr<CSSPrimitiveValue> fill; - RefPtr<CSSPrimitiveValue> shape; + RefPtrWillBeRawPtr<CSSPrimitiveValue> fill = nullptr; + RefPtrWillBeRawPtr<CSSPrimitiveValue> shape = nullptr; for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { if (value->unit == CSSPrimitiveValue::CSS_STRING) { @@ -9165,7 +7671,7 @@ bool CSSParser::parseTextEmphasisStyle(bool important) } if (fill && shape) { - RefPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); parsedValues->append(fill.release()); parsedValues->append(shape.release()); addProperty(CSSPropertyWebkitTextEmphasisStyle, parsedValues.release(), important); @@ -9183,52 +7689,46 @@ bool CSSParser::parseTextEmphasisStyle(bool important) return false; } -PassRefPtr<CSSValue> CSSParser::parseTextIndent() +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTextIndent() { - RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); - // <length> | <percentage> | inherit - if (m_valueList->size() == 1) { - CSSParserValue* value = m_valueList->current(); - if (!value->id && validUnit(value, FLength | FPercent)) { + bool hasLengthOrPercentage = false; + bool hasEachLine = false; + bool hasHanging = false; + + for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { + // <length> | <percentage> | inherit when RuntimeEnabledFeatures::css3TextEnabled() returns false + if (!hasLengthOrPercentage && validUnit(value, FLength | FPercent)) { list->append(createPrimitiveNumericValue(value)); - m_valueList->next(); - return list.release(); + hasLengthOrPercentage = true; + continue; } - } - - if (!RuntimeEnabledFeatures::css3TextEnabled()) - return 0; - - // The case where text-indent has only <length>(or <percentage>) value - // is handled above if statement even though css3TextEnabled() returns true. - - // [ [ <length> | <percentage> ] && each-line ] | inherit - if (m_valueList->size() != 2) - return 0; - CSSParserValue* firstValue = m_valueList->current(); - CSSParserValue* secondValue = m_valueList->next(); - CSSParserValue* lengthOrPercentageValue = 0; - - // [ <length> | <percentage> ] each-line - if (validUnit(firstValue, FLength | FPercent) && secondValue->id == CSSValueEachLine) - lengthOrPercentageValue = firstValue; - // each-line [ <length> | <percentage> ] - else if (firstValue->id == CSSValueEachLine && validUnit(secondValue, FLength | FPercent)) - lengthOrPercentageValue = secondValue; - - if (lengthOrPercentageValue) { - list->append(createPrimitiveNumericValue(lengthOrPercentageValue)); - list->append(cssValuePool().createIdentifierValue(CSSValueEachLine)); - m_valueList->next(); - return list.release(); + // [ <length> | <percentage> ] && hanging? && each-line? | inherit + // when RuntimeEnabledFeatures::css3TextEnabled() returns true + if (RuntimeEnabledFeatures::css3TextEnabled()) { + if (!hasEachLine && value->id == CSSValueEachLine) { + list->append(cssValuePool().createIdentifierValue(CSSValueEachLine)); + hasEachLine = true; + continue; + } + if (!hasHanging && value->id == CSSValueHanging) { + list->append(cssValuePool().createIdentifierValue(CSSValueHanging)); + hasHanging = true; + continue; + } + } + return nullptr; } - return 0; + if (!hasLengthOrPercentage) + return nullptr; + + return list.release(); } -bool CSSParser::parseLineBoxContain(bool important) +bool CSSPropertyParser::parseLineBoxContain(bool important) { LineBoxContain lineBoxContain = LineBoxContainNone; @@ -9268,7 +7768,7 @@ bool CSSParser::parseLineBoxContain(bool important) return true; } -bool CSSParser::parseFontFeatureTag(CSSValueList* settings) +bool CSSPropertyParser::parseFontFeatureTag(CSSValueList* settings) { // Feature tag name consists of 4-letter characters. static const unsigned tagNameLength = 4; @@ -9305,16 +7805,16 @@ bool CSSParser::parseFontFeatureTag(CSSValueList* settings) return true; } -bool CSSParser::parseFontFeatureSettings(bool important) +bool CSSPropertyParser::parseFontFeatureSettings(bool important) { if (m_valueList->size() == 1 && m_valueList->current()->id == CSSValueNormal) { - RefPtr<CSSPrimitiveValue> normalValue = cssValuePool().createIdentifierValue(CSSValueNormal); + RefPtrWillBeRawPtr<CSSPrimitiveValue> normalValue = cssValuePool().createIdentifierValue(CSSValueNormal); m_valueList->next(); addProperty(CSSPropertyWebkitFontFeatureSettings, normalValue.release(), important); return true; } - RefPtr<CSSValueList> settings = CSSValueList::createCommaSeparated(); + RefPtrWillBeRawPtr<CSSValueList> settings = CSSValueList::createCommaSeparated(); for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { if (!parseFontFeatureTag(settings.get())) return false; @@ -9331,12 +7831,13 @@ bool CSSParser::parseFontFeatureSettings(bool important) return false; } -bool CSSParser::parseFontVariantLigatures(bool important) +bool CSSPropertyParser::parseFontVariantLigatures(bool important) { - RefPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated(); + RefPtrWillBeRawPtr<CSSValueList> ligatureValues = CSSValueList::createSpaceSeparated(); bool sawCommonLigaturesValue = false; bool sawDiscretionaryLigaturesValue = false; bool sawHistoricalLigaturesValue = false; + bool sawContextualLigaturesValue = false; for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { if (value->unit != CSSPrimitiveValue::CSS_IDENT) @@ -9364,6 +7865,13 @@ bool CSSParser::parseFontVariantLigatures(bool important) sawHistoricalLigaturesValue = true; ligatureValues->append(cssValuePool().createIdentifierValue(value->id)); break; + case CSSValueNoContextual: + case CSSValueContextual: + if (sawContextualLigaturesValue) + return false; + sawContextualLigaturesValue = true; + ligatureValues->append(cssValuePool().createIdentifierValue(value->id)); + break; default: return false; } @@ -9372,11 +7880,11 @@ bool CSSParser::parseFontVariantLigatures(bool important) if (!ligatureValues->length()) return false; - addProperty(CSSPropertyWebkitFontVariantLigatures, ligatureValues.release(), important); + addProperty(CSSPropertyFontVariantLigatures, ligatureValues.release(), important); return true; } -bool CSSParser::parseCalculation(CSSParserValue* value, ValueRange range) +bool CSSPropertyParser::parseCalculation(CSSParserValue* value, ValueRange range) { ASSERT(isCalculation(value)); @@ -9393,760 +7901,7 @@ bool CSSParser::parseCalculation(CSSParserValue* value, ValueRange range) return true; } -#define END_TOKEN 0 - -void CSSParser::ensureLineEndings() -{ - if (!m_lineEndings) - m_lineEndings = lineEndings(*m_source); -} - -CSSParserSelector* CSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName) -{ - CSSParserSelector* selector = new CSSParserSelector(tagQName); - m_floatingSelectors.append(selector); - return selector; -} - -CSSParserSelector* CSSParser::createFloatingSelector() -{ - CSSParserSelector* selector = new CSSParserSelector; - m_floatingSelectors.append(selector); - return selector; -} - -PassOwnPtr<CSSParserSelector> CSSParser::sinkFloatingSelector(CSSParserSelector* selector) -{ - if (selector) { - size_t index = m_floatingSelectors.reverseFind(selector); - ASSERT(index != kNotFound); - m_floatingSelectors.remove(index); - } - return adoptPtr(selector); -} - -Vector<OwnPtr<CSSParserSelector> >* CSSParser::createFloatingSelectorVector() -{ - Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >; - m_floatingSelectorVectors.append(selectorVector); - return selectorVector; -} - -PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > CSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector) -{ - if (selectorVector) { - size_t index = m_floatingSelectorVectors.reverseFind(selectorVector); - ASSERT(index != kNotFound); - m_floatingSelectorVectors.remove(index); - } - return adoptPtr(selectorVector); -} - -CSSParserValueList* CSSParser::createFloatingValueList() -{ - CSSParserValueList* list = new CSSParserValueList; - m_floatingValueLists.append(list); - return list; -} - -PassOwnPtr<CSSParserValueList> CSSParser::sinkFloatingValueList(CSSParserValueList* list) -{ - if (list) { - size_t index = m_floatingValueLists.reverseFind(list); - ASSERT(index != kNotFound); - m_floatingValueLists.remove(index); - } - return adoptPtr(list); -} - -CSSParserFunction* CSSParser::createFloatingFunction() -{ - CSSParserFunction* function = new CSSParserFunction; - m_floatingFunctions.append(function); - return function; -} - -CSSParserFunction* CSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args) -{ - CSSParserFunction* function = createFloatingFunction(); - function->name = name; - function->args = args; - return function; -} - -PassOwnPtr<CSSParserFunction> CSSParser::sinkFloatingFunction(CSSParserFunction* function) -{ - if (function) { - size_t index = m_floatingFunctions.reverseFind(function); - ASSERT(index != kNotFound); - m_floatingFunctions.remove(index); - } - return adoptPtr(function); -} - -CSSParserValue& CSSParser::sinkFloatingValue(CSSParserValue& value) -{ - if (value.unit == CSSParserValue::Function) { - size_t index = m_floatingFunctions.reverseFind(value.function); - ASSERT(index != kNotFound); - m_floatingFunctions.remove(index); - } - return value; -} - -MediaQueryExp* CSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values) -{ - m_floatingMediaQueryExp = MediaQueryExp::create(mediaFeature, values); - return m_floatingMediaQueryExp.get(); -} - -PassOwnPtr<MediaQueryExp> CSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression) -{ - ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp); - return m_floatingMediaQueryExp.release(); -} - -Vector<OwnPtr<MediaQueryExp> >* CSSParser::createFloatingMediaQueryExpList() -{ - m_floatingMediaQueryExpList = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >); - return m_floatingMediaQueryExpList.get(); -} - -PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > CSSParser::sinkFloatingMediaQueryExpList(Vector<OwnPtr<MediaQueryExp> >* list) -{ - ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList); - return m_floatingMediaQueryExpList.release(); -} - -MediaQuery* CSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions) -{ - m_floatingMediaQuery = adoptPtr(new MediaQuery(restrictor, mediaType, expressions)); - return m_floatingMediaQuery.get(); -} - -MediaQuery* CSSParser::createFloatingMediaQuery(PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > expressions) -{ - return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions); -} - -MediaQuery* CSSParser::createFloatingNotAllQuery() -{ - return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList())); -} - -PassOwnPtr<MediaQuery> CSSParser::sinkFloatingMediaQuery(MediaQuery* query) -{ - ASSERT_UNUSED(query, query == m_floatingMediaQuery); - return m_floatingMediaQuery.release(); -} - -Vector<RefPtr<StyleKeyframe> >* CSSParser::createFloatingKeyframeVector() -{ - m_floatingKeyframeVector = adoptPtr(new Vector<RefPtr<StyleKeyframe> >()); - return m_floatingKeyframeVector.get(); -} - -PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > CSSParser::sinkFloatingKeyframeVector(Vector<RefPtr<StyleKeyframe> >* keyframeVector) -{ - ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector); - return m_floatingKeyframeVector.release(); -} - -MediaQuerySet* CSSParser::createMediaQuerySet() -{ - RefPtr<MediaQuerySet> queries = MediaQuerySet::create(); - MediaQuerySet* result = queries.get(); - m_parsedMediaQuerySets.append(queries.release()); - return result; -} - -StyleRuleBase* CSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media) -{ - if (!media || !m_allowImportRules) - return 0; - RefPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media); - StyleRuleImport* result = rule.get(); - m_parsedRules.append(rule.release()); - return result; -} - -StyleRuleBase* CSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules) -{ - m_allowImportRules = m_allowNamespaceDeclarations = false; - RefPtr<StyleRuleMedia> rule; - if (rules) { - rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create(), *rules); - } else { - RuleList emptyRules; - rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create(), emptyRules); - } - StyleRuleMedia* result = rule.get(); - m_parsedRules.append(rule.release()); - return result; -} - -StyleRuleBase* CSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules) -{ - m_allowImportRules = m_allowNamespaceDeclarations = false; - - RefPtr<CSSRuleSourceData> data = popSupportsRuleData(); - RefPtr<StyleRuleSupports> rule; - String conditionText; - unsigned conditionOffset = data->ruleHeaderRange.start + 9; - unsigned conditionLength = data->ruleHeaderRange.length() - 9; - - if (m_tokenizer.is8BitSource()) - conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace(); - else - conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace(); - - if (rules) { - rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules); - } else { - RuleList emptyRules; - rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules); - } - - StyleRuleSupports* result = rule.get(); - m_parsedRules.append(rule.release()); - - return result; -} - -void CSSParser::markSupportsRuleHeaderStart() -{ - if (!m_supportsRuleDataStack) - m_supportsRuleDataStack = adoptPtr(new RuleSourceDataList()); - - RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE); - data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset(); - m_supportsRuleDataStack->append(data); -} - -void CSSParser::markSupportsRuleHeaderEnd() -{ - ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty()); - - if (m_tokenizer.is8BitSource()) - m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get(); - else - m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get(); -} - -PassRefPtr<CSSRuleSourceData> CSSParser::popSupportsRuleData() -{ - ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty()); - RefPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last(); - m_supportsRuleDataStack->removeLast(); - return data.release(); -} - -CSSParser::RuleList* CSSParser::createRuleList() -{ - OwnPtr<RuleList> list = adoptPtr(new RuleList); - RuleList* listPtr = list.get(); - - m_parsedRuleLists.append(list.release()); - return listPtr; -} - -CSSParser::RuleList* CSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule) -{ - if (rule) { - if (!ruleList) - ruleList = createRuleList(); - ruleList->append(rule); - } - return ruleList; -} - -template <typename CharacterType> -ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length) -{ - // FIXME: If we need Unicode lowercasing here, then we probably want the real kind - // that can potentially change the length of the string rather than the character - // by character kind. If we don't need Unicode lowercasing, it would be good to - // simplify this function. - - if (charactersAreAllASCII(input, length)) { - // Fast case for all-ASCII. - for (unsigned i = 0; i < length; i++) - output[i] = toASCIILower(input[i]); - } else { - for (unsigned i = 0; i < length; i++) - output[i] = Unicode::toLower(input[i]); - } -} - -void CSSParser::tokenToLowerCase(const CSSParserString& token) -{ - size_t length = token.length(); - if (m_tokenizer.is8BitSource()) { - size_t offset = token.characters8() - m_tokenizer.m_dataStart8.get(); - makeLower(token.characters8(), m_tokenizer.m_dataStart8.get() + offset, length); - } else { - size_t offset = token.characters16() - m_tokenizer.m_dataStart16.get(); - makeLower(token.characters16(), m_tokenizer.m_dataStart16.get() + offset, length); - } -} - -void CSSParser::endInvalidRuleHeader() -{ - if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE) - return; - - CSSParserLocation location; - location.lineNumber = m_tokenizer.m_lineNumber; - location.offset = m_ruleHeaderStartOffset; - if (m_tokenizer.is8BitSource()) - location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0); - else - location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0); - - reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorError : InvalidRuleError); - - endRuleHeader(); -} - -void CSSParser::reportError(const CSSParserLocation&, ErrorType) -{ - // FIXME: error reporting temporatily disabled. -} - -bool CSSParser::isLoggingErrors() -{ - return m_logErrors && !m_ignoreErrors; -} - -void CSSParser::logError(const String& message, const CSSParserLocation& location) -{ - unsigned lineNumberInStyleSheet; - unsigned columnNumber = 0; - PageConsole& console = m_styleSheet->singleOwnerDocument()->page()->console(); - if (InspectorInstrumentation::hasFrontends()) { - ensureLineEndings(); - TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings); - lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt(); - columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt(); - } else { - lineNumberInStyleSheet = location.lineNumber; - } - console.addMessage(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1); -} - -StyleRuleKeyframes* CSSParser::createKeyframesRule(const String& name, PassOwnPtr<Vector<RefPtr<StyleKeyframe> > > popKeyframes, bool isPrefixed) -{ - OwnPtr<Vector<RefPtr<StyleKeyframe> > > keyframes = popKeyframes; - m_allowImportRules = m_allowNamespaceDeclarations = false; - RefPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create(); - for (size_t i = 0; i < keyframes->size(); ++i) - rule->parserAppendKeyframe(keyframes->at(i)); - rule->setName(name); - rule->setVendorPrefixed(isPrefixed); - StyleRuleKeyframes* rulePtr = rule.get(); - m_parsedRules.append(rule.release()); - return rulePtr; -} - -StyleRuleBase* CSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors) -{ - StyleRule* result = 0; - if (selectors) { - m_allowImportRules = m_allowNamespaceDeclarations = false; - RefPtr<StyleRule> rule = StyleRule::create(); - rule->parserAdoptSelectorVector(*selectors); - if (m_hasFontFaceOnlyValues) - deleteFontFaceOnlyValues(); - rule->setProperties(createStylePropertySet()); - result = rule.get(); - m_parsedRules.append(rule.release()); - } - clearProperties(); - return result; -} - -StyleRuleBase* CSSParser::createFontFaceRule() -{ - m_allowImportRules = m_allowNamespaceDeclarations = false; - for (unsigned i = 0; i < m_parsedProperties.size(); ++i) { - CSSProperty& property = m_parsedProperties[i]; - if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue()) - property.wrapValueInCommaSeparatedList(); - else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) { - // Unlike font-family property, font-family descriptor in @font-face rule - // has to be a value list with exactly one family name. It cannot have a - // have 'initial' value and cannot 'inherit' from parent. - // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc - clearProperties(); - return 0; - } - } - RefPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create(); - rule->setProperties(createStylePropertySet()); - clearProperties(); - StyleRuleFontFace* result = rule.get(); - m_parsedRules.append(rule.release()); - if (m_styleSheet) - m_styleSheet->setHasFontFaceRule(true); - return result; -} - -void CSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri) -{ - if (!m_styleSheet || !m_allowNamespaceDeclarations) - return; - m_allowImportRules = false; - m_styleSheet->parserAddNamespace(prefix, uri); - if (prefix.isEmpty() && !uri.isNull()) - m_defaultNamespace = uri; -} - -QualifiedName CSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName) -{ - if (!m_styleSheet) - return QualifiedName(prefix, localName, m_defaultNamespace); - return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix)); -} - -CSSParserSelector* CSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers) -{ - if (m_defaultNamespace != starAtom || specifiers->needsCrossingTreeScopeBoundary()) - return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true); - if (CSSParserSelector* distributedPseudoElementSelector = specifiers->findDistributedPseudoElementSelector()) { - specifiers->prependTagSelector(QualifiedName(nullAtom, starAtom, m_defaultNamespace), /*tagIsForNamespaceRule*/true); - return rewriteSpecifiersForShadowDistributed(specifiers, distributedPseudoElementSelector); - } - return specifiers; -} - -CSSParserSelector* CSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) -{ - AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace; - QualifiedName tag(namespacePrefix, elementName, determinedNamespace); - - if (CSSParserSelector* distributedPseudoElementSelector = specifiers->findDistributedPseudoElementSelector()) { - specifiers->prependTagSelector(tag, tagIsForNamespaceRule); - return rewriteSpecifiersForShadowDistributed(specifiers, distributedPseudoElementSelector); - } - - if (specifiers->needsCrossingTreeScopeBoundary()) - return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule); - - if (specifiers->isContentPseudoElement()) - return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule); - - if (tag == anyQName()) - return specifiers; - if (!(specifiers->pseudoType() == CSSSelector::PseudoCue)) - specifiers->prependTagSelector(tag, tagIsForNamespaceRule); - return specifiers; -} - -CSSParserSelector* CSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) -{ - if (m_useCounter && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement) - m_useCounter->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo); - - CSSParserSelector* lastShadowPseudo = specifiers; - CSSParserSelector* history = specifiers; - while (history->tagHistory()) { - history = history->tagHistory(); - if (history->needsCrossingTreeScopeBoundary() || history->hasShadowPseudo()) - lastShadowPseudo = history; - } - - if (lastShadowPseudo->tagHistory()) { - if (tag != anyQName()) - lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule); - return specifiers; - } - - // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used. - // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). - OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag)); - lastShadowPseudo->setTagHistory(elementNameSelector.release()); - lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo); - return specifiers; -} - -CSSParserSelector* CSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule) -{ - CSSParserSelector* last = specifiers; - CSSParserSelector* history = specifiers; - while (history->tagHistory()) { - history = history->tagHistory(); - if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent()) - last = history; - } - - if (last->tagHistory()) { - if (tag != anyQName()) - last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule); - return specifiers; - } - - // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used. - // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). - OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag)); - last->setTagHistory(elementNameSelector.release()); - last->setRelation(CSSSelector::SubSelector); - return specifiers; -} - -CSSParserSelector* CSSParser::rewriteSpecifiersForShadowDistributed(CSSParserSelector* specifiers, CSSParserSelector* distributedPseudoElementSelector) -{ - if (m_useCounter) - m_useCounter->count(UseCounter::CSSPseudoElementPrefixedDistributed); - CSSParserSelector* argumentSelector = distributedPseudoElementSelector->functionArgumentSelector(); - ASSERT(argumentSelector); - ASSERT(!specifiers->isDistributedPseudoElement()); - for (CSSParserSelector* end = specifiers; end->tagHistory(); end = end->tagHistory()) { - if (end->tagHistory()->isDistributedPseudoElement()) { - end->clearTagHistory(); - break; - } - } - CSSParserSelector* end = argumentSelector; - while (end->tagHistory()) - end = end->tagHistory(); - - switch (end->relation()) { - case CSSSelector::Child: - case CSSSelector::Descendant: - end->setTagHistory(sinkFloatingSelector(specifiers)); - end->setRelationIsAffectedByPseudoContent(); - return argumentSelector; - default: - return 0; - } -} - -CSSParserSelector* CSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier) -{ - if (newSpecifier->needsCrossingTreeScopeBoundary()) { - // Unknown pseudo element always goes at the top of selector chain. - newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers)); - return newSpecifier; - } - if (newSpecifier->isContentPseudoElement()) { - newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers)); - return newSpecifier; - } - if (specifiers->needsCrossingTreeScopeBoundary()) { - // Specifiers for unknown pseudo element go right behind it in the chain. - specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo); - return specifiers; - } - if (specifiers->isContentPseudoElement()) { - specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector); - return specifiers; - } - specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier)); - return specifiers; -} - -StyleRuleBase* CSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector) -{ - // FIXME: Margin at-rules are ignored. - m_allowImportRules = m_allowNamespaceDeclarations = false; - StyleRulePage* pageRule = 0; - if (pageSelector) { - RefPtr<StyleRulePage> rule = StyleRulePage::create(); - Vector<OwnPtr<CSSParserSelector> > selectorVector; - selectorVector.append(pageSelector); - rule->parserAdoptSelectorVector(selectorVector); - rule->setProperties(createStylePropertySet()); - pageRule = rule.get(); - m_parsedRules.append(rule.release()); - } - clearProperties(); - return pageRule; -} - -void CSSParser::setReusableRegionSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectors) -{ - if (selectors) - m_reusableRegionSelectorVector.swap(*selectors); -} - -StyleRuleBase* CSSParser::createRegionRule(Vector<OwnPtr<CSSParserSelector> >* regionSelector, RuleList* rules) -{ - if (m_useCounter) - m_useCounter->count(UseCounter::CSSWebkitRegionAtRule); - - if (!RuntimeEnabledFeatures::cssRegionsEnabled() || !regionSelector || !rules) - return 0; - - m_allowImportRules = m_allowNamespaceDeclarations = false; - - RefPtr<StyleRuleRegion> regionRule = StyleRuleRegion::create(regionSelector, *rules); - - StyleRuleRegion* result = regionRule.get(); - m_parsedRules.append(regionRule.release()); - if (m_sourceDataHandler) - m_sourceDataHandler->startEndUnknownRule(); - - return result; -} - -StyleRuleBase* CSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */) -{ - // FIXME: Implement margin at-rule here, using: - // - marginBox: margin box - // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule. - // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid. - - endDeclarationsForMarginBox(); - return 0; // until this method is implemented. -} - -void CSSParser::startDeclarationsForMarginBox() -{ - m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size(); -} - -void CSSParser::endDeclarationsForMarginBox() -{ - rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox); - m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES; -} - -void CSSParser::deleteFontFaceOnlyValues() -{ - ASSERT(m_hasFontFaceOnlyValues); - for (unsigned i = 0; i < m_parsedProperties.size();) { - CSSProperty& property = m_parsedProperties[i]; - if (property.id() == CSSPropertyFontVariant && property.value()->isValueList()) { - m_parsedProperties.remove(i); - continue; - } - ++i; - } -} - -StyleKeyframe* CSSParser::createKeyframe(CSSParserValueList* keys) -{ - OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys); - if (keyVector->isEmpty()) - return 0; - - RefPtr<StyleKeyframe> keyframe = StyleKeyframe::create(); - keyframe->setKeys(keyVector.release()); - keyframe->setProperties(createStylePropertySet()); - - clearProperties(); - - StyleKeyframe* keyframePtr = keyframe.get(); - m_parsedKeyframes.append(keyframe.release()); - return keyframePtr; -} - -void CSSParser::invalidBlockHit() -{ - if (m_styleSheet && !m_hadSyntacticallyValidCSSRule) - m_styleSheet->setHasSyntacticallyValidCSSHeader(false); -} - -void CSSParser::startRule() -{ - if (!m_sourceDataHandler) - return; - - ASSERT(m_ruleHasHeader); - m_ruleHasHeader = false; -} - -void CSSParser::endRule(bool valid) -{ - if (!m_sourceDataHandler) - return; - - if (m_ruleHasHeader) - m_sourceDataHandler->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid); - m_ruleHasHeader = true; -} - -void CSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType) -{ - resumeErrorLogging(); - m_ruleHeaderType = ruleType; - m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset(); - m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber; - if (m_sourceDataHandler) { - ASSERT(!m_ruleHasHeader); - m_sourceDataHandler->startRuleHeader(ruleType, m_ruleHeaderStartOffset); - m_ruleHasHeader = true; - } -} - -void CSSParser::endRuleHeader() -{ - ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE); - m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE; - if (m_sourceDataHandler) { - ASSERT(m_ruleHasHeader); - m_sourceDataHandler->endRuleHeader(m_tokenizer.safeUserStringTokenOffset()); - } -} - -void CSSParser::startSelector() -{ - if (m_sourceDataHandler) - m_sourceDataHandler->startSelector(m_tokenizer.safeUserStringTokenOffset()); -} - -void CSSParser::endSelector() -{ - if (m_sourceDataHandler) - m_sourceDataHandler->endSelector(m_tokenizer.safeUserStringTokenOffset()); -} - -void CSSParser::startRuleBody() -{ - if (m_sourceDataHandler) - m_sourceDataHandler->startRuleBody(m_tokenizer.safeUserStringTokenOffset()); -} - -void CSSParser::startProperty() -{ - resumeErrorLogging(); - if (m_sourceDataHandler) - m_sourceDataHandler->startProperty(m_tokenizer.safeUserStringTokenOffset()); -} - -void CSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, ErrorType errorType) -{ - m_id = CSSPropertyInvalid; - if (m_sourceDataHandler) - m_sourceDataHandler->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType); -} - -void CSSParser::startEndUnknownRule() -{ - if (m_sourceDataHandler) - m_sourceDataHandler->startEndUnknownRule(); -} - -StyleRuleBase* CSSParser::createViewportRule() -{ - // Allow @viewport rules from UA stylesheets even if the feature is disabled. - if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode())) - return 0; - - m_allowImportRules = m_allowNamespaceDeclarations = false; - - RefPtr<StyleRuleViewport> rule = StyleRuleViewport::create(); - - rule->setProperties(createStylePropertySet()); - clearProperties(); - - StyleRuleViewport* result = rule.get(); - m_parsedRules.append(rule.release()); - - return result; -} - -bool CSSParser::parseViewportProperty(CSSPropertyID propId, bool important) +bool CSSPropertyParser::parseViewportProperty(CSSPropertyID propId, bool important) { ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode())); @@ -10190,7 +7945,7 @@ bool CSSParser::parseViewportProperty(CSSPropertyID propId, bool important) break; } - RefPtr<CSSValue> parsedValue; + RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; if (validPrimitive) { parsedValue = parseValidPrimitive(id, value); m_valueList->next(); @@ -10206,7 +7961,7 @@ bool CSSParser::parseViewportProperty(CSSPropertyID propId, bool important) return false; } -bool CSSParser::parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important) +bool CSSPropertyParser::parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important) { ASSERT(RuntimeEnabledFeatures::cssViewportEnabled() || isUASheetBehavior(m_context.mode())); unsigned numValues = m_valueList->size(); @@ -10297,169 +8052,384 @@ CSSValueID cssValueKeywordID(const CSSParserString& string) return string.is8Bit() ? cssValueKeywordID(string.characters8(), length) : cssValueKeywordID(string.characters16(), length); } -template <typename CharacterType> -static inline bool isCSSTokenizerIdentifier(const CharacterType* characters, unsigned length) +bool isValidNthToken(const CSSParserString& token) { - const CharacterType* end = characters + length; + // The tokenizer checks for the construct of an+b. + // However, since the {ident} rule precedes the {nth} rule, some of those + // tokens are identified as string literal. Furthermore we need to accept + // "odd" and "even" which does not match to an+b. + return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even") + || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n"); +} - // -? - if (characters != end && characters[0] == '-') - ++characters; +bool CSSPropertyParser::isSystemColor(int id) +{ + return (id >= CSSValueActiveborder && id <= CSSValueWindowtext) || id == CSSValueMenu; +} - // {nmstart} - if (characters == end || !(characters[0] == '_' || characters[0] >= 128 || isASCIIAlpha(characters[0]))) +bool CSSPropertyParser::parseSVGValue(CSSPropertyID propId, bool important) +{ + CSSParserValue* value = m_valueList->current(); + if (!value) return false; - ++characters; - // {nmchar}* - for (; characters != end; ++characters) { - if (!(characters[0] == '_' || characters[0] == '-' || characters[0] >= 128 || isASCIIAlphanumeric(characters[0]))) - return false; - } + CSSValueID id = value->id; - return true; -} + bool validPrimitive = false; + RefPtrWillBeRawPtr<CSSValue> parsedValue = nullptr; -// "ident" from the CSS tokenizer, minus backslash-escape sequences -static bool isCSSTokenizerIdentifier(const String& string) -{ - unsigned length = string.length(); + switch (propId) { + /* The comment to the right defines all valid value of these + * properties as defined in SVG 1.1, Appendix N. Property index */ + case CSSPropertyAlignmentBaseline: + // auto | baseline | before-edge | text-before-edge | middle | + // central | after-edge | text-after-edge | ideographic | alphabetic | + // hanging | mathematical | inherit + if (id == CSSValueAuto || id == CSSValueBaseline || id == CSSValueMiddle + || (id >= CSSValueBeforeEdge && id <= CSSValueMathematical)) + validPrimitive = true; + break; - if (!length) - return false; + case CSSPropertyBaselineShift: + // baseline | super | sub | <percentage> | <length> | inherit + if (id == CSSValueBaseline || id == CSSValueSub + || id >= CSSValueSuper) + validPrimitive = true; + else + validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMode); + break; - if (string.is8Bit()) - return isCSSTokenizerIdentifier(string.characters8(), length); - return isCSSTokenizerIdentifier(string.characters16(), length); -} + case CSSPropertyDominantBaseline: + // auto | use-script | no-change | reset-size | ideographic | + // alphabetic | hanging | mathematical | central | middle | + // text-after-edge | text-before-edge | inherit + if (id == CSSValueAuto || id == CSSValueMiddle + || (id >= CSSValueUseScript && id <= CSSValueResetSize) + || (id >= CSSValueCentral && id <= CSSValueMathematical)) + validPrimitive = true; + break; -template <typename CharacterType> -static inline bool isCSSTokenizerURL(const CharacterType* characters, unsigned length) -{ - const CharacterType* end = characters + length; - - for (; characters != end; ++characters) { - CharacterType c = characters[0]; - switch (c) { - case '!': - case '#': - case '$': - case '%': - case '&': - break; - default: - if (c < '*') - return false; - if (c <= '~') - break; - if (c < 128) - return false; + case CSSPropertyEnableBackground: + // accumulate | new [x] [y] [width] [height] | inherit + if (id == CSSValueAccumulate) // TODO : new + validPrimitive = true; + break; + + case CSSPropertyMarkerStart: + case CSSPropertyMarkerMid: + case CSSPropertyMarkerEnd: + case CSSPropertyMask: + if (id == CSSValueNone) { + validPrimitive = true; + } else if (value->unit == CSSPrimitiveValue::CSS_URI) { + parsedValue = CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_URI); + if (parsedValue) + m_valueList->next(); } - } + break; - return true; -} + case CSSPropertyClipRule: // nonzero | evenodd | inherit + case CSSPropertyFillRule: + if (id == CSSValueNonzero || id == CSSValueEvenodd) + validPrimitive = true; + break; -// "url" from the CSS tokenizer, minus backslash-escape sequences -static bool isCSSTokenizerURL(const String& string) -{ - unsigned length = string.length(); + case CSSPropertyStrokeMiterlimit: // <miterlimit> | inherit + validPrimitive = validUnit(value, FNumber | FNonNeg, SVGAttributeMode); + break; - if (!length) - return true; + case CSSPropertyStrokeLinejoin: // miter | round | bevel | inherit + if (id == CSSValueMiter || id == CSSValueRound || id == CSSValueBevel) + validPrimitive = true; + break; - if (string.is8Bit()) - return isCSSTokenizerURL(string.characters8(), length); - return isCSSTokenizerURL(string.characters16(), length); -} + case CSSPropertyStrokeLinecap: // butt | round | square | inherit + if (id == CSSValueButt || id == CSSValueRound || id == CSSValueSquare) + validPrimitive = true; + break; + case CSSPropertyStrokeOpacity: // <opacity-value> | inherit + case CSSPropertyFillOpacity: + case CSSPropertyStopOpacity: + case CSSPropertyFloodOpacity: + validPrimitive = (!id && validUnit(value, FNumber | FPercent, SVGAttributeMode)); + break; -template <typename CharacterType> -static inline String quoteCSSStringInternal(const CharacterType* characters, unsigned length) -{ - // For efficiency, we first pre-calculate the length of the quoted string, then we build the actual one. - // Please see below for the actual logic. - unsigned quotedStringSize = 2; // Two quotes surrounding the entire string. - bool afterEscape = false; - for (unsigned i = 0; i < length; ++i) { - CharacterType ch = characters[i]; - if (ch == '\\' || ch == '\'') { - quotedStringSize += 2; - afterEscape = false; - } else if (ch < 0x20 || ch == 0x7F) { - quotedStringSize += 2 + (ch >= 0x10); - afterEscape = true; - } else { - quotedStringSize += 1 + (afterEscape && (isASCIIHexDigit(ch) || ch == ' ')); - afterEscape = false; + case CSSPropertyShapeRendering: + // auto | optimizeSpeed | crispEdges | geometricPrecision | inherit + if (id == CSSValueAuto || id == CSSValueOptimizespeed + || id == CSSValueCrispedges || id == CSSValueGeometricprecision) + validPrimitive = true; + break; + + case CSSPropertyImageRendering: // auto | optimizeSpeed | + case CSSPropertyColorRendering: // optimizeQuality | inherit + if (id == CSSValueAuto || id == CSSValueOptimizespeed + || id == CSSValueOptimizequality) + validPrimitive = true; + break; + + case CSSPropertyBufferedRendering: // auto | dynamic | static + if (id == CSSValueAuto || id == CSSValueDynamic || id == CSSValueStatic) + validPrimitive = true; + break; + + case CSSPropertyColorInterpolation: // auto | sRGB | linearRGB | inherit + case CSSPropertyColorInterpolationFilters: + if (id == CSSValueAuto || id == CSSValueSrgb || id == CSSValueLinearrgb) + validPrimitive = true; + break; + + /* Start of supported CSS properties with validation. This is needed for parseShortHand to work + * correctly and allows optimization in applyRule(..) + */ + + case CSSPropertyTextAnchor: // start | middle | end | inherit + if (id == CSSValueStart || id == CSSValueMiddle || id == CSSValueEnd) + validPrimitive = true; + break; + + case CSSPropertyGlyphOrientationVertical: // auto | <angle> | inherit + if (id == CSSValueAuto) { + validPrimitive = true; + break; } - } + /* fallthrough intentional */ + case CSSPropertyGlyphOrientationHorizontal: // <angle> (restricted to _deg_ per SVG 1.1 spec) | inherit + if (value->unit == CSSPrimitiveValue::CSS_DEG || value->unit == CSSPrimitiveValue::CSS_NUMBER) { + parsedValue = CSSPrimitiveValue::create(value->fValue, CSSPrimitiveValue::CSS_DEG); - StringBuffer<CharacterType> buffer(quotedStringSize); - unsigned index = 0; - buffer[index++] = '\''; - afterEscape = false; - for (unsigned i = 0; i < length; ++i) { - CharacterType ch = characters[i]; - if (ch == '\\' || ch == '\'') { - buffer[index++] = '\\'; - buffer[index++] = ch; - afterEscape = false; - } else if (ch < 0x20 || ch == 0x7F) { // Control characters. - buffer[index++] = '\\'; - placeByteAsHexCompressIfPossible(ch, buffer, index, Lowercase); - afterEscape = true; - } else { - // Space character may be required to separate backslash-escape sequence and normal characters. - if (afterEscape && (isASCIIHexDigit(ch) || ch == ' ')) - buffer[index++] = ' '; - buffer[index++] = ch; - afterEscape = false; + if (parsedValue) + m_valueList->next(); } - } - buffer[index++] = '\''; + break; - ASSERT(quotedStringSize == index); - return String::adopt(buffer); -} + case CSSPropertyFill: // <paint> | inherit + case CSSPropertyStroke: // <paint> | inherit + { + if (id == CSSValueNone) { + parsedValue = SVGPaint::createNone(); + } else if (id == CSSValueCurrentcolor) { + parsedValue = SVGPaint::createCurrentColor(); + } else if (isSystemColor(id)) { + parsedValue = SVGPaint::createColor(RenderTheme::theme().systemColor(id)); + } else if (value->unit == CSSPrimitiveValue::CSS_URI) { + RGBA32 c = Color::transparent; + if (m_valueList->next()) { + if (parseColorFromValue(m_valueList->current(), c)) + parsedValue = SVGPaint::createURIAndColor(value->string, c); + else if (m_valueList->current()->id == CSSValueNone) + parsedValue = SVGPaint::createURIAndNone(value->string); + else if (m_valueList->current()->id == CSSValueCurrentcolor) + parsedValue = SVGPaint::createURIAndCurrentColor(value->string); + } + if (!parsedValue) + parsedValue = SVGPaint::createURI(value->string); + } else { + parsedValue = parseSVGPaint(); + } -// We use single quotes for now because markup.cpp uses double quotes. -String quoteCSSString(const String& string) -{ - // This function expands each character to at most 3 characters ('\u0010' -> '\' '1' '0') as well as adds - // 2 quote characters (before and after). Make sure the resulting size (3 * length + 2) will not overflow unsigned. + if (parsedValue) + m_valueList->next(); + } + break; - unsigned length = string.length(); + case CSSPropertyStopColor: // TODO : icccolor + case CSSPropertyFloodColor: + case CSSPropertyLightingColor: + if (isSystemColor(id)) { + parsedValue = cssValuePool().createColorValue(RenderTheme::theme().systemColor(id).rgb()); + } else if ((id >= CSSValueAqua && id <= CSSValueTransparent) + || (id >= CSSValueAliceblue && id <= CSSValueYellowgreen) || id == CSSValueGrey) { + StyleColor styleColor = SVGPaint::colorFromRGBColorString(value->string); + ASSERT(!styleColor.isCurrentColor()); + parsedValue = cssValuePool().createColorValue(styleColor.color().rgb()); + } else if (id == CSSValueCurrentcolor) { + parsedValue = cssValuePool().createIdentifierValue(id); + } else { // TODO : svgcolor (iccColor) + parsedValue = parseColor(); + } - if (!length) - return String("\'\'"); + if (parsedValue) + m_valueList->next(); + + break; + + case CSSPropertyPaintOrder: + if (m_valueList->size() == 1 && id == CSSValueNormal) + validPrimitive = true; + else if ((parsedValue = parsePaintOrder())) + m_valueList->next(); + break; + + case CSSPropertyVectorEffect: // none | non-scaling-stroke | inherit + if (id == CSSValueNone || id == CSSValueNonScalingStroke) + validPrimitive = true; + break; + + case CSSPropertyWritingMode: + // lr-tb | rl_tb | tb-rl | lr | rl | tb | inherit + if (id == CSSValueLrTb || id == CSSValueRlTb || id == CSSValueTbRl || id == CSSValueLr || id == CSSValueRl || id == CSSValueTb) + validPrimitive = true; + break; + + case CSSPropertyStrokeWidth: // <length> | inherit + case CSSPropertyStrokeDashoffset: + validPrimitive = validUnit(value, FLength | FPercent, SVGAttributeMode); + break; + case CSSPropertyStrokeDasharray: // none | <dasharray> | inherit + if (id == CSSValueNone) + validPrimitive = true; + else + parsedValue = parseSVGStrokeDasharray(); - if (length > std::numeric_limits<unsigned>::max() / 3 - 2) - return emptyString(); + break; - if (string.is8Bit()) - return quoteCSSStringInternal(string.characters8(), length); - return quoteCSSStringInternal(string.characters16(), length); + case CSSPropertyClipPath: // <uri> | none | inherit + case CSSPropertyFilter: + if (id == CSSValueNone) { + validPrimitive = true; + } else if (value->unit == CSSPrimitiveValue::CSS_URI) { + parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitType) value->unit); + if (parsedValue) + m_valueList->next(); + } + break; + case CSSPropertyMaskType: // luminance | alpha | inherit + if (id == CSSValueLuminance || id == CSSValueAlpha) + validPrimitive = true; + break; + + /* shorthand properties */ + case CSSPropertyMarker: { + ShorthandScope scope(this, propId); + CSSPropertyParser::ImplicitScope implicitScope(this, PropertyImplicit); + if (!parseValue(CSSPropertyMarkerStart, important)) + return false; + if (m_valueList->current()) { + rollbackLastProperties(1); + return false; + } + CSSValue* value = m_parsedProperties.last().value(); + addProperty(CSSPropertyMarkerMid, value, important); + addProperty(CSSPropertyMarkerEnd, value, important); + return true; + } + default: + // If you crash here, it's because you added a css property and are not handling it + // in either this switch statement or the one in CSSPropertyParser::parseValue + ASSERT_WITH_MESSAGE(0, "unimplemented propertyID: %d", propId); + return false; + } + + if (validPrimitive) { + if (id) + parsedValue = CSSPrimitiveValue::createIdentifier(id); + else if (value->unit == CSSPrimitiveValue::CSS_STRING) + parsedValue = CSSPrimitiveValue::create(value->string, (CSSPrimitiveValue::UnitType) value->unit); + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) + parsedValue = CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitType) value->unit); + else if (value->unit >= CSSParserValue::Q_EMS) + parsedValue = CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); + if (isCalculation(value)) { + // FIXME calc() http://webkit.org/b/16662 : actually create a CSSPrimitiveValue here, ie + // parsedValue = CSSPrimitiveValue::create(m_parsedCalculation.release()); + m_parsedCalculation.release(); + parsedValue = nullptr; + } + m_valueList->next(); + } + if (!parsedValue || (m_valueList->current() && !inShorthand())) + return false; + + addProperty(propId, parsedValue.release(), important); + return true; } -String quoteCSSStringIfNeeded(const String& string) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGStrokeDasharray() { - return isCSSTokenizerIdentifier(string) ? string : quoteCSSString(string); + RefPtrWillBeRawPtr<CSSValueList> ret = CSSValueList::createCommaSeparated(); + CSSParserValue* value = m_valueList->current(); + bool validPrimitive = true; + while (value) { + validPrimitive = validUnit(value, FLength | FPercent | FNonNeg, SVGAttributeMode); + if (!validPrimitive) + break; + if (value->id) + ret->append(CSSPrimitiveValue::createIdentifier(value->id)); + else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) + ret->append(CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitType) value->unit)); + value = m_valueList->next(); + if (value && value->unit == CSSParserValue::Operator && value->iValue == ',') + value = m_valueList->next(); + } + if (!validPrimitive) + return nullptr; + return ret.release(); } -String quoteCSSURLIfNeeded(const String& string) +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSVGPaint() { - return isCSSTokenizerURL(string) ? string : quoteCSSString(string); + RGBA32 c = Color::transparent; + if (!parseColorFromValue(m_valueList->current(), c)) + return SVGPaint::createUnknown(); + return SVGPaint::createColor(Color(c)); } -bool isValidNthToken(const CSSParserString& token) +// normal | [ fill || stroke || markers ] +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parsePaintOrder() const { - // The tokenizer checks for the construct of an+b. - // However, since the {ident} rule precedes the {nth} rule, some of those - // tokens are identified as string literal. Furthermore we need to accept - // "odd" and "even" which does not match to an+b. - return equalIgnoringCase(token, "odd") || equalIgnoringCase(token, "even") - || equalIgnoringCase(token, "n") || equalIgnoringCase(token, "-n"); -} + if (m_valueList->size() > 3) + return nullptr; + CSSParserValue* value = m_valueList->current(); + if (!value) + return nullptr; + + RefPtrWillBeRawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); + + // The default paint-order is: Fill, Stroke, Markers. + bool seenFill = false, seenStroke = false, seenMarkers = false; + + do { + switch (value->id) { + case CSSValueNormal: + // normal inside [fill || stroke || markers] not valid + return nullptr; + case CSSValueFill: + if (seenFill) + return nullptr; + + seenFill = true; + break; + case CSSValueStroke: + if (seenStroke) + return nullptr; + + seenStroke = true; + break; + case CSSValueMarkers: + if (seenMarkers) + return nullptr; + + seenMarkers = true; + break; + default: + return nullptr; + } + + parsedValues->append(CSSPrimitiveValue::createIdentifier(value->id)); + } while ((value = m_valueList->next())); + + // fill out the rest of the paint order + if (!seenFill) + parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueFill)); + if (!seenStroke) + parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke)); + if (!seenMarkers) + parsedValues->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers)); + + return parsedValues.release(); } + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/chromium/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h new file mode 100644 index 00000000000..1fc76568cee --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h @@ -0,0 +1,410 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Eric Seidel <eric@webkit.org> + * Copyright (C) 2009 - 2010 Torch Mobile (Beijing) Co. Ltd. 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 CSSPropertyParser_h +#define CSSPropertyParser_h + +// FIXME: Way too many. +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/css/CSSCalculationValue.h" +#include "core/css/CSSFilterValue.h" +#include "core/css/CSSGradientValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" +#include "core/css/CSSParserMode.h" +#include "core/css/CSSParserValues.h" +#include "core/css/CSSProperty.h" +#include "core/css/CSSPropertySourceData.h" +#include "core/css/CSSSelector.h" +#include "platform/graphics/Color.h" +#include "wtf/OwnPtr.h" +#include "wtf/Vector.h" + +namespace WebCore { + +// FIXME: Many of these may not be used. +class CSSArrayFunctionValue; +class CSSBorderImageSliceValue; +class CSSPrimitiveValue; +class CSSSelectorList; +class CSSValue; +class CSSValueList; +class CSSBasicShape; +class CSSBasicShapeInset; +class CSSGridLineNamesValue; +class Document; +class Element; +class ImmutableStylePropertySet; +class StyleKeyframe; +class StylePropertyShorthand; +class StyleKeyframe; +class UseCounter; + +// Inputs: PropertyID, isImportant bool, CSSParserValueList. +// Outputs: Vector of CSSProperties + +class CSSPropertyParser { + STACK_ALLOCATED(); +public: + CSSPropertyParser(OwnPtr<CSSParserValueList>&, + const CSSParserContext&, bool inViewport, bool savedImportant, + WillBeHeapVector<CSSProperty, 256>&, CSSRuleSourceData::Type); + ~CSSPropertyParser(); + + // FIXME: Should this be on a separate ColorParser object? + template<typename StringType> + static bool fastParseColor(RGBA32&, const StringType&, bool strict); + + bool parseValue(CSSPropertyID, bool important); + + static bool isSystemColor(int id); + +private: + bool inShorthand() const { return m_inParseShorthand; } + bool inQuirksMode() const { return isQuirksModeBehavior(m_context.mode()); } + + bool inViewport() const { return m_inViewport; } + bool parseViewportProperty(CSSPropertyID propId, bool important); + bool parseViewportShorthand(CSSPropertyID propId, CSSPropertyID first, CSSPropertyID second, bool important); + + KURL completeURL(const String& url) const; + + void addPropertyWithPrefixingVariant(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important, bool implicit = false); + void addProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important, bool implicit = false); + void rollbackLastProperties(int num); + bool hasProperties() const { return !m_parsedProperties.isEmpty(); } + void addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtrWillBeRawPtr<CSSValue>, bool); + + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseValidPrimitive(CSSValueID ident, CSSParserValue*); + + bool parseShorthand(CSSPropertyID, const StylePropertyShorthand&, bool important); + bool parse4Values(CSSPropertyID, const CSSPropertyID* properties, bool important); + bool parseContent(CSSPropertyID, bool important); + bool parseQuotes(CSSPropertyID, bool important); + + PassRefPtrWillBeRawPtr<CSSValue> parseAttr(CSSParserValueList* args); + + PassRefPtrWillBeRawPtr<CSSValue> parseBackgroundColor(); + + bool parseFillImage(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&); + + enum FillPositionFlag { InvalidFillPosition = 0, AmbiguousFillPosition = 1, XFillPosition = 2, YFillPosition = 4 }; + enum FillPositionParsingMode { ResolveValuesAsPercent = 0, ResolveValuesAsKeyword = 1 }; + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseFillPositionComponent(CSSParserValueList*, unsigned& cumulativeFlags, FillPositionFlag& individualFlag, FillPositionParsingMode = ResolveValuesAsPercent); + PassRefPtrWillBeRawPtr<CSSValue> parseFillPositionX(CSSParserValueList*); + PassRefPtrWillBeRawPtr<CSSValue> parseFillPositionY(CSSParserValueList*); + void parse2ValuesFillPosition(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + bool isPotentialPositionValue(CSSParserValue*); + void parseFillPosition(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + void parse3ValuesFillPosition(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, PassRefPtrWillBeRawPtr<CSSPrimitiveValue>, PassRefPtrWillBeRawPtr<CSSPrimitiveValue>); + void parse4ValuesFillPosition(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, PassRefPtrWillBeRawPtr<CSSPrimitiveValue>, PassRefPtrWillBeRawPtr<CSSPrimitiveValue>); + + void parseFillRepeat(RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + PassRefPtrWillBeRawPtr<CSSValue> parseFillSize(CSSPropertyID, bool &allowComma); + + bool parseFillProperty(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + bool parseFillShorthand(CSSPropertyID, const CSSPropertyID* properties, int numProperties, bool important); + + void addFillValue(RefPtrWillBeRawPtr<CSSValue>& lval, PassRefPtrWillBeRawPtr<CSSValue> rval); + + void addAnimationValue(RefPtrWillBeRawPtr<CSSValue>& lval, PassRefPtrWillBeRawPtr<CSSValue> rval); + + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationDelay(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationDirection(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationDuration(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationFillMode(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationIterationCount(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationName(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationPlayState(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationProperty(); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationTimingFunction(); + + bool parseWebkitTransformOriginShorthand(RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + bool parseCubicBezierTimingFunctionValue(CSSParserValueList*& args, double& result); + PassRefPtrWillBeRawPtr<CSSValue> parseAnimationProperty(CSSPropertyID); + PassRefPtrWillBeRawPtr<CSSValueList> parseAnimationPropertyList(CSSPropertyID); + bool parseTransitionShorthand(CSSPropertyID, bool important); + bool parseAnimationShorthand(CSSPropertyID, bool important); + + PassRefPtrWillBeRawPtr<CSSValue> parseColumnWidth(); + PassRefPtrWillBeRawPtr<CSSValue> parseColumnCount(); + bool parseColumnsShorthand(bool important); + + PassRefPtrWillBeRawPtr<CSSValue> parseGridPosition(); + bool parseIntegerOrCustomIdentFromGridPosition(RefPtrWillBeRawPtr<CSSPrimitiveValue>& numericValue, RefPtrWillBeRawPtr<CSSPrimitiveValue>& gridLineName); + bool parseGridItemPositionShorthand(CSSPropertyID, bool important); + bool parseGridTemplateRowsAndAreas(PassRefPtrWillBeRawPtr<CSSValue>, bool important); + bool parseGridTemplateShorthand(bool important); + bool parseGridShorthand(bool important); + bool parseGridAreaShorthand(bool important); + bool parseSingleGridAreaLonghand(RefPtrWillBeRawPtr<CSSValue>&); + PassRefPtrWillBeRawPtr<CSSValue> parseGridTrackList(bool important); + bool parseGridTrackRepeatFunction(CSSValueList&); + PassRefPtrWillBeRawPtr<CSSValue> parseGridTrackSize(CSSParserValueList& inputList); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseGridBreadth(CSSParserValue*); + bool parseGridTemplateAreasRow(NamedGridAreaMap&, const size_t, size_t&); + PassRefPtrWillBeRawPtr<CSSValue> parseGridTemplateAreas(); + void parseGridLineNames(CSSParserValueList&, CSSValueList&, CSSGridLineNamesValue* = 0); + + bool parseClipShape(CSSPropertyID, bool important); + + bool parseItemPositionOverflowPosition(CSSPropertyID, bool important); + + PassRefPtrWillBeRawPtr<CSSValue> parseShapeProperty(CSSPropertyID propId); + PassRefPtrWillBeRawPtr<CSSValue> parseBasicShapeAndOrBox(); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseBasicShape(); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseShapeRadius(CSSParserValue*); + + PassRefPtrWillBeRawPtr<CSSBasicShape> parseBasicShapeCircle(CSSParserValueList* args); + PassRefPtrWillBeRawPtr<CSSBasicShape> parseBasicShapeEllipse(CSSParserValueList* args); + PassRefPtrWillBeRawPtr<CSSBasicShape> parseBasicShapePolygon(CSSParserValueList* args); + PassRefPtrWillBeRawPtr<CSSBasicShape> parseBasicShapeInset(CSSParserValueList* args); + + bool parseFont(bool important); + PassRefPtrWillBeRawPtr<CSSValueList> parseFontFamily(); + + bool parseCounter(CSSPropertyID, int defaultValue, bool important); + PassRefPtrWillBeRawPtr<CSSValue> parseCounterContent(CSSParserValueList* args, bool counters); + + bool parseColorParameters(CSSParserValue*, int* colorValues, bool parseAlpha); + bool parseHSLParameters(CSSParserValue*, double* colorValues, bool parseAlpha); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseColor(CSSParserValue* = 0); + bool parseColorFromValue(CSSParserValue*, RGBA32&); + + bool parseLineHeight(bool important); + bool parseFontSize(bool important); + bool parseFontVariant(bool important); + bool parseFontWeight(bool important); + bool parseFontFaceSrc(); + bool parseFontFaceUnicodeRange(); + + bool parseSVGValue(CSSPropertyID propId, bool important); + PassRefPtrWillBeRawPtr<CSSValue> parseSVGPaint(); + PassRefPtrWillBeRawPtr<CSSValue> parseSVGStrokeDasharray(); + + PassRefPtrWillBeRawPtr<CSSValue> parsePaintOrder() const; + + // CSS3 Parsing Routines (for properties specific to CSS3) + PassRefPtrWillBeRawPtr<CSSValueList> parseShadow(CSSParserValueList*, CSSPropertyID); + bool parseBorderImageShorthand(CSSPropertyID, bool important); + PassRefPtrWillBeRawPtr<CSSValue> parseBorderImage(CSSPropertyID); + bool parseBorderImageRepeat(RefPtrWillBeRawPtr<CSSValue>&); + bool parseBorderImageSlice(CSSPropertyID, RefPtrWillBeRawPtr<CSSBorderImageSliceValue>&); + bool parseBorderImageWidth(RefPtrWillBeRawPtr<CSSPrimitiveValue>&); + bool parseBorderImageOutset(RefPtrWillBeRawPtr<CSSPrimitiveValue>&); + bool parseBorderRadius(CSSPropertyID, bool important); + + bool parseAspectRatio(bool important); + + bool parseReflect(CSSPropertyID, bool important); + + bool parseFlex(CSSParserValueList* args, bool important); + + bool parseObjectPosition(bool important); + + // Image generators + bool parseCanvas(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&); + + bool parseDeprecatedGradient(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&); + bool parseDeprecatedLinearGradient(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, CSSGradientRepeat repeating); + bool parseDeprecatedRadialGradient(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, CSSGradientRepeat repeating); + bool parseLinearGradient(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, CSSGradientRepeat repeating); + bool parseRadialGradient(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&, CSSGradientRepeat repeating); + bool parseGradientColorStops(CSSParserValueList*, CSSGradientValue*, bool expectComma); + + bool parseCrossfade(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&); + + PassRefPtrWillBeRawPtr<CSSValue> parseImageSet(CSSParserValueList*); + + bool parseWillChange(bool important); + + PassRefPtrWillBeRawPtr<CSSValueList> parseFilter(); + PassRefPtrWillBeRawPtr<CSSFilterValue> parseBuiltinFilterArguments(CSSParserValueList*, CSSFilterValue::FilterOperationType); + + PassRefPtrWillBeRawPtr<CSSValueList> parseTransformOrigin(); + PassRefPtrWillBeRawPtr<CSSValueList> parseTransform(CSSPropertyID); + PassRefPtrWillBeRawPtr<CSSValue> parseTransformValue(CSSPropertyID, CSSParserValue*); + bool parseWebkitTransformOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, CSSPropertyID& propId3, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + bool parseWebkitPerspectiveOrigin(CSSPropertyID propId, CSSPropertyID& propId1, CSSPropertyID& propId2, RefPtrWillBeRawPtr<CSSValue>&, RefPtrWillBeRawPtr<CSSValue>&); + + bool parseTextEmphasisStyle(bool important); + + bool parseTouchAction(bool important); + + void addTextDecorationProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important); + bool parseTextDecoration(CSSPropertyID propId, bool important); + bool parseTextUnderlinePosition(bool important); + + PassRefPtrWillBeRawPtr<CSSValue> parseTextIndent(); + + bool parseLineBoxContain(bool important); + bool parseCalculation(CSSParserValue*, ValueRange); + + bool parseFontFeatureTag(CSSValueList*); + bool parseFontFeatureSettings(bool important); + + bool parseFontVariantLigatures(bool important); + + bool parseGeneratedImage(CSSParserValueList*, RefPtrWillBeRawPtr<CSSValue>&); + + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createPrimitiveNumericValue(CSSParserValue*); + PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createPrimitiveStringValue(CSSParserValue*); + + PassRefPtrWillBeRawPtr<CSSValue> createCSSImageValueWithReferrer(const String& rawValue, const KURL&); + + bool validWidthOrHeight(CSSParserValue*); + + PassRefPtrWillBeRawPtr<CSSBasicShape> parseInsetRoundedCorners(PassRefPtrWillBeRawPtr<CSSBasicShapeInset>, CSSParserValueList*); + + enum SizeParameterType { + None, + Auto, + Length, + PageSize, + Orientation, + }; + + bool parsePage(CSSPropertyID propId, bool important); + bool parseSize(CSSPropertyID propId, bool important); + SizeParameterType parseSizeParameter(CSSValueList* parsedValues, CSSParserValue*, SizeParameterType prevParamType); + + bool parseFontFaceSrcURI(CSSValueList*); + bool parseFontFaceSrcLocal(CSSValueList*); + + enum PropertyType { + PropertyExplicit, + PropertyImplicit + }; + + class ImplicitScope { + STACK_ALLOCATED(); + WTF_MAKE_NONCOPYABLE(ImplicitScope); + public: + ImplicitScope(CSSPropertyParser* parser, PropertyType propertyType) + : m_parser(parser) + { + m_parser->m_implicitShorthand = propertyType == CSSPropertyParser::PropertyImplicit; + } + + ~ImplicitScope() + { + m_parser->m_implicitShorthand = false; + } + + private: + CSSPropertyParser* m_parser; + }; + + class ShorthandScope { + STACK_ALLOCATED(); + public: + ShorthandScope(CSSPropertyParser* parser, CSSPropertyID propId) : m_parser(parser) + { + if (!(m_parser->m_inParseShorthand++)) + m_parser->m_currentShorthand = propId; + } + ~ShorthandScope() + { + if (!(--m_parser->m_inParseShorthand)) + m_parser->m_currentShorthand = CSSPropertyInvalid; + } + + private: + CSSPropertyParser* m_parser; + }; + + enum ReleaseParsedCalcValueCondition { + ReleaseParsedCalcValue, + DoNotReleaseParsedCalcValue + }; + + enum Units { + FUnknown = 0x0000, + FInteger = 0x0001, + FNumber = 0x0002, // Real Numbers + FPercent = 0x0004, + FLength = 0x0008, + FAngle = 0x0010, + FTime = 0x0020, + FFrequency = 0x0040, + FPositiveInteger = 0x0080, + FRelative = 0x0100, + FResolution = 0x0200, + FNonNeg = 0x0400 + }; + + friend inline Units operator|(Units a, Units b) + { + return static_cast<Units>(static_cast<unsigned>(a) | static_cast<unsigned>(b)); + } + + bool validCalculationUnit(CSSParserValue*, Units, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); + + bool shouldAcceptUnitLessValues(CSSParserValue*, Units, CSSParserMode); + + inline bool validUnit(CSSParserValue* value, Units unitflags, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue) { return validUnit(value, unitflags, m_context.mode(), releaseCalc); } + bool validUnit(CSSParserValue*, Units, CSSParserMode, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); + + bool parseBorderImageQuad(Units, RefPtrWillBeRawPtr<CSSPrimitiveValue>&); + int colorIntFromValue(CSSParserValue*); + double parsedDouble(CSSParserValue*, ReleaseParsedCalcValueCondition releaseCalc = DoNotReleaseParsedCalcValue); + bool isCalculation(CSSParserValue*); + +private: + // Inputs: + // FIXME: This should not be an OwnPtr&, many callers will need to be changed. + const OwnPtr<CSSParserValueList>& m_valueList; + const CSSParserContext& m_context; + const bool m_inViewport; + const bool m_important; // FIXME: This is only used by font-face-src and unicode-range and undoubtably wrong! + + // Outputs: + WillBeHeapVector<CSSProperty, 256>& m_parsedProperties; + CSSRuleSourceData::Type m_ruleType; + + // Locals during parsing: + int m_inParseShorthand; + CSSPropertyID m_currentShorthand; + bool m_implicitShorthand; + RefPtrWillBeMember<CSSCalcValue> m_parsedCalculation; + + // FIXME: There is probably a small set of APIs we could expose for these + // classes w/o needing to make them friends. + friend class ShadowParseContext; + friend class BorderImageParseContext; + friend class BorderImageSliceParseContext; + friend class BorderImageQuadParseContext; + friend class TransformOperationInfo; + friend bool parseDeprecatedGradientColorStop(CSSPropertyParser*, CSSParserValue*, CSSGradientColorStop&); + friend PassRefPtrWillBeRawPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSPropertyParser*, CSSParserValue*); +}; + +CSSPropertyID cssPropertyID(const CSSParserString&); +CSSPropertyID cssPropertyID(const String&); +CSSValueID cssValueKeywordID(const CSSParserString&); + +bool isKeywordPropertyID(CSSPropertyID); +bool isValidKeywordPropertyAndValue(CSSPropertyID, CSSValueID, const CSSParserContext&); + +} // namespace WebCore + +#endif // CSSPropertyParser_h diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp new file mode 100644 index 00000000000..46985d38ad2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaConditionTest.cpp @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/css/MediaList.h" +#include "core/css/MediaQuery.h" +#include "core/css/parser/MediaQueryParser.h" +#include "core/css/parser/MediaQueryTokenizer.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/text/StringBuilder.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +typedef struct { + const char* input; + const char* output; +} TestCase; + +TEST(MediaConditionParserTest, Basic) +{ + // The first string represents the input string. + // The second string represents the output string, if present. + // Otherwise, the output string is identical to the first string. + TestCase testCases[] = { + {"screen", "not all"}, + {"screen and (color)", "not all"}, + {"all and (min-width:500px)", "not all"}, + {"(min-width:500px)", "(min-width: 500px)"}, + {"screen and (color), projection and (color)", "not all"}, + {"(min-width: -100px)", "not all"}, + {"(min-width: 100px) and print", "not all"}, + {"(min-width: 100px) and (max-width: 900px)", "(max-width: 900px) and (min-width: 100px)"}, + {"(min-width: [100px) and (max-width: 900px)", "not all"}, + {0, 0} // Do not remove the terminator line. + }; + + for (unsigned i = 0; testCases[i].input; ++i) { + Vector<MediaQueryToken> tokens; + MediaQueryTokenizer::tokenize(testCases[i].input, tokens); + MediaQueryTokenIterator endToken; + // Stop the input once we hit a comma token + for (endToken = tokens.begin(); endToken != tokens.end() && endToken->type() != CommaToken; ++endToken) { } + RefPtrWillBeRawPtr<MediaQuerySet> mediaConditionQuerySet = MediaQueryParser::parseMediaCondition(tokens.begin(), endToken); + ASSERT_EQ(mediaConditionQuerySet->queryVector().size(), (unsigned)1); + String queryText = mediaConditionQuerySet->queryVector()[0]->cssText(); + ASSERT_STREQ(testCases[i].output, queryText.ascii().data()); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryBlockWatcher.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryBlockWatcher.cpp new file mode 100644 index 00000000000..fdceea230d0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryBlockWatcher.cpp @@ -0,0 +1,28 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/MediaQueryBlockWatcher.h" + +#include "core/css/parser/MediaQueryToken.h" + +namespace WebCore { + +MediaQueryBlockWatcher::MediaQueryBlockWatcher() + : m_blockLevel(0) +{ +} + +void MediaQueryBlockWatcher::handleToken(const MediaQueryToken& token) +{ + if (token.blockType() == MediaQueryToken::BlockStart) { + ++m_blockLevel; + } else if (token.blockType() == MediaQueryToken::BlockEnd) { + ASSERT(m_blockLevel); + --m_blockLevel; + } +} + +} // namespace + diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryBlockWatcher.h b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryBlockWatcher.h new file mode 100644 index 00000000000..73937c06653 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryBlockWatcher.h @@ -0,0 +1,25 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaQueryBlockWatcher_h +#define MediaQueryBlockWatcher_h + +namespace WebCore { + +class MediaQueryToken; + +class MediaQueryBlockWatcher { +public: + + MediaQueryBlockWatcher(); + void handleToken(const MediaQueryToken&); + unsigned blockLevel() const { return m_blockLevel; } + +private: + unsigned m_blockLevel; +}; + +} // namespace + +#endif // MediaQueryBlockWatcher_h diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryInputStream.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryInputStream.cpp new file mode 100644 index 00000000000..a5adeb551a4 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryInputStream.cpp @@ -0,0 +1,66 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/MediaQueryInputStream.h" + +#include "core/html/parser/InputStreamPreprocessor.h" + +namespace WebCore { + +MediaQueryInputStream::MediaQueryInputStream(String input) + : m_offset(0) + , m_string(input) +{ +} + +UChar MediaQueryInputStream::peek(unsigned lookaheadOffset) +{ + ASSERT((m_offset + lookaheadOffset) <= maxLength()); + if ((m_offset + lookaheadOffset) >= m_string.length()) + return kEndOfFileMarker; + return m_string[m_offset + lookaheadOffset]; +} + +void MediaQueryInputStream::advance(unsigned offset) +{ + ASSERT(m_offset + offset <= maxLength()); + m_offset += offset; +} + +void MediaQueryInputStream::pushBack(UChar cc) +{ + --m_offset; + ASSERT(nextInputChar() == cc); +} + +unsigned long long MediaQueryInputStream::getUInt(unsigned start, unsigned end) +{ + ASSERT(start <= end && ((m_offset + end) <= m_string.length())); + bool isResultOK = false; + unsigned long long result = 0; + if (start < end) { + if (m_string.is8Bit()) + result = charactersToUInt64Strict(m_string.characters8() + m_offset + start, end - start, &isResultOK); + else + result = charactersToUInt64Strict(m_string.characters16() + m_offset + start, end - start, &isResultOK); + } + return isResultOK ? result : 0; +} + +double MediaQueryInputStream::getDouble(unsigned start, unsigned end) +{ + ASSERT(start <= end && ((m_offset + end) <= m_string.length())); + bool isResultOK = false; + double result = 0.0; + if (start < end) { + if (m_string.is8Bit()) + result = charactersToDouble(m_string.characters8() + m_offset + start, end - start, &isResultOK); + else + result = charactersToDouble(m_string.characters16() + m_offset + start, end - start, &isResultOK); + } + return isResultOK ? result : 0.0; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryInputStream.h b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryInputStream.h new file mode 100644 index 00000000000..24018d095bd --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryInputStream.h @@ -0,0 +1,57 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaQueryInputStream_h +#define MediaQueryInputStream_h + +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class MediaQueryInputStream { + WTF_MAKE_NONCOPYABLE(MediaQueryInputStream); + WTF_MAKE_FAST_ALLOCATED; +public: + MediaQueryInputStream(String input); + + UChar peek(unsigned); + inline UChar nextInputChar() + { + return peek(0); + } + + void advance(unsigned = 1); + void pushBack(UChar); + + inline size_t maxLength() + { + return m_string.length() + 1; + } + + inline size_t leftChars() + { + return m_string.length() - m_offset; + + } + + unsigned long long getUInt(unsigned start, unsigned end); + double getDouble(unsigned start, unsigned end); + + template<bool characterPredicate(UChar)> + unsigned skipWhilePredicate(unsigned offset) + { + while ((m_offset + offset) < m_string.length() && characterPredicate(m_string[m_offset + offset])) + ++offset; + return offset; + } + +private: + size_t m_offset; + String m_string; +}; + +} // namespace WebCore + +#endif // MediaQueryInputStream_h + diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp new file mode 100644 index 00000000000..63b720cfe4b --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryParser.cpp @@ -0,0 +1,265 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/MediaQueryParser.h" + +#include "core/MediaTypeNames.h" +#include "core/css/parser/CSSPropertyParser.h" +#include "core/css/parser/MediaQueryTokenizer.h" + +namespace WebCore { + +PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseMediaQuerySet(const String& queryString) +{ + // FIXME: Replace the MediaQueryTokenizer with a generic CSSTokenizer, once there is one, + // or better yet, replace the MediaQueryParser with a generic thread-safe CSS parser. + Vector<MediaQueryToken> tokens; + MediaQueryTokenizer::tokenize(queryString, tokens); + return MediaQueryParser(MediaQuerySetParser).parseImpl(tokens.begin(), tokens.end()); +} + +PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseMediaCondition(MediaQueryTokenIterator token, MediaQueryTokenIterator endToken) +{ + return MediaQueryParser(MediaConditionParser).parseImpl(token, endToken); +} + +const MediaQueryParser::State MediaQueryParser::ReadRestrictor = &MediaQueryParser::readRestrictor; +const MediaQueryParser::State MediaQueryParser::ReadMediaType = &MediaQueryParser::readMediaType; +const MediaQueryParser::State MediaQueryParser::ReadAnd = &MediaQueryParser::readAnd; +const MediaQueryParser::State MediaQueryParser::ReadFeatureStart = &MediaQueryParser::readFeatureStart; +const MediaQueryParser::State MediaQueryParser::ReadFeature = &MediaQueryParser::readFeature; +const MediaQueryParser::State MediaQueryParser::ReadFeatureColon = &MediaQueryParser::readFeatureColon; +const MediaQueryParser::State MediaQueryParser::ReadFeatureValue = &MediaQueryParser::readFeatureValue; +const MediaQueryParser::State MediaQueryParser::ReadFeatureEnd = &MediaQueryParser::readFeatureEnd; +const MediaQueryParser::State MediaQueryParser::SkipUntilComma = &MediaQueryParser::skipUntilComma; +const MediaQueryParser::State MediaQueryParser::SkipUntilBlockEnd = &MediaQueryParser::skipUntilBlockEnd; +const MediaQueryParser::State MediaQueryParser::Done = &MediaQueryParser::done; + +MediaQueryParser::MediaQueryParser(ParserType parserType) + : m_parserType(parserType) + , m_querySet(MediaQuerySet::create()) +{ + if (parserType == MediaQuerySetParser) + m_state = &MediaQueryParser::readRestrictor; + else // MediaConditionParser + m_state = &MediaQueryParser::readFeatureStart; +} + +MediaQueryParser::~MediaQueryParser() { }; + +void MediaQueryParser::setStateAndRestrict(State state, MediaQuery::Restrictor restrictor) +{ + m_mediaQueryData.setRestrictor(restrictor); + m_state = state; +} + +// State machine member functions start here +void MediaQueryParser::readRestrictor(MediaQueryTokenType type, const MediaQueryToken& token) +{ + readMediaType(type, token); +} + +void MediaQueryParser::readMediaType(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == LeftParenthesisToken) { + m_state = ReadFeature; + } else if (type == IdentToken) { + if (m_state == ReadRestrictor && equalIgnoringCase(token.value(), "not")) { + setStateAndRestrict(ReadMediaType, MediaQuery::Not); + } else if (m_state == ReadRestrictor && equalIgnoringCase(token.value(), "only")) { + setStateAndRestrict(ReadMediaType, MediaQuery::Only); + } else { + m_mediaQueryData.setMediaType(token.value()); + m_state = ReadAnd; + } + } else if (type == EOFToken && (!m_querySet->queryVector().size() || m_state != ReadRestrictor)) { + m_state = Done; + } else { + m_state = SkipUntilComma; + if (type == CommaToken) + skipUntilComma(type, token); + } +} + +void MediaQueryParser::readAnd(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == IdentToken && equalIgnoringCase(token.value(), "and")) { + m_state = ReadFeatureStart; + } else if (type == CommaToken && m_parserType != MediaConditionParser) { + m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); + m_state = ReadRestrictor; + } else if (type == EOFToken) { + m_state = Done; + } else { + m_state = SkipUntilComma; + } +} + +void MediaQueryParser::readFeatureStart(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == LeftParenthesisToken) + m_state = ReadFeature; + else + m_state = SkipUntilComma; +} + +void MediaQueryParser::readFeature(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == IdentToken) { + m_mediaQueryData.setMediaFeature(token.value()); + m_state = ReadFeatureColon; + } else { + m_state = SkipUntilComma; + } +} + +void MediaQueryParser::readFeatureColon(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == ColonToken) + m_state = ReadFeatureValue; + else if (type == RightParenthesisToken || type == EOFToken) + readFeatureEnd(type, token); + else + m_state = SkipUntilBlockEnd; +} + +void MediaQueryParser::readFeatureValue(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == DimensionToken && token.unitType() == CSSPrimitiveValue::CSS_UNKNOWN) { + m_state = SkipUntilComma; + } else { + m_mediaQueryData.addParserValue(type, token); + m_state = ReadFeatureEnd; + } +} + +void MediaQueryParser::readFeatureEnd(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (type == RightParenthesisToken || type == EOFToken) { + if (m_mediaQueryData.addExpression()) + m_state = ReadAnd; + else + m_state = SkipUntilComma; + } else if (type == DelimiterToken && token.delimiter() == '/') { + m_mediaQueryData.addParserValue(type, token); + m_state = ReadFeatureValue; + } else { + m_state = SkipUntilBlockEnd; + } +} + +void MediaQueryParser::skipUntilComma(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if ((type == CommaToken && !m_blockWatcher.blockLevel()) || type == EOFToken) { + m_state = ReadRestrictor; + m_mediaQueryData.clear(); + m_querySet->addMediaQuery(MediaQuery::createNotAll()); + } +} + +void MediaQueryParser::skipUntilBlockEnd(MediaQueryTokenType type, const MediaQueryToken& token) +{ + if (token.blockType() == MediaQueryToken::BlockEnd && !m_blockWatcher.blockLevel()) + m_state = SkipUntilComma; +} + +void MediaQueryParser::done(MediaQueryTokenType type, const MediaQueryToken& token) { } + +void MediaQueryParser::handleBlocks(const MediaQueryToken& token) +{ + if (token.blockType() == MediaQueryToken::BlockStart + && (token.type() != LeftParenthesisToken || m_blockWatcher.blockLevel())) + m_state = SkipUntilBlockEnd; +} + +void MediaQueryParser::processToken(const MediaQueryToken& token) +{ + MediaQueryTokenType type = token.type(); + + handleBlocks(token); + m_blockWatcher.handleToken(token); + + // Call the function that handles current state + if (type != WhitespaceToken && type != CommentToken) + ((this)->*(m_state))(type, token); +} + +// The state machine loop +PassRefPtrWillBeRawPtr<MediaQuerySet> MediaQueryParser::parseImpl(MediaQueryTokenIterator token, MediaQueryTokenIterator endToken) +{ + for (; token != endToken; ++token) + processToken(*token); + + if (m_state != ReadAnd && m_state != ReadRestrictor && m_state != Done && (m_parserType != MediaConditionParser || m_state != ReadFeatureStart)) + m_querySet->addMediaQuery(MediaQuery::createNotAll()); + else if (m_mediaQueryData.currentMediaQueryChanged()) + m_querySet->addMediaQuery(m_mediaQueryData.takeMediaQuery()); + + return m_querySet; +} + +MediaQueryData::MediaQueryData() + : m_restrictor(MediaQuery::None) + , m_mediaType(MediaTypeNames::all) + , m_expressions(adoptPtrWillBeNoop(new ExpressionHeapVector)) + , m_mediaTypeSet(false) +{ +} + +void MediaQueryData::clear() +{ + m_restrictor = MediaQuery::None; + m_mediaType = MediaTypeNames::all; + m_mediaTypeSet = false; + m_mediaFeature = String(); + m_valueList.destroyAndClear(); + m_expressions = adoptPtrWillBeNoop(new ExpressionHeapVector); +} + +PassOwnPtrWillBeRawPtr<MediaQuery> MediaQueryData::takeMediaQuery() +{ + OwnPtrWillBeRawPtr<MediaQuery> mediaQuery = adoptPtrWillBeNoop(new MediaQuery(m_restrictor, m_mediaType, m_expressions.release())); + clear(); + return mediaQuery.release(); +} + +bool MediaQueryData::addExpression() +{ + OwnPtrWillBeRawPtr<MediaQueryExp> expression = MediaQueryExp::createIfValid(m_mediaFeature, &m_valueList); + bool isValid = !!expression; + m_expressions->append(expression.release()); + m_valueList.destroyAndClear(); + return isValid; +} + +void MediaQueryData::addParserValue(MediaQueryTokenType type, const MediaQueryToken& token) +{ + CSSParserValue value; + if (type == NumberToken || type == PercentageToken || type == DimensionToken) { + value.setFromNumber(token.numericValue(), token.unitType()); + value.isInt = (token.numericValueType() == IntegerValueType); + } else if (type == DelimiterToken) { + value.unit = CSSParserValue::Operator; + value.iValue = token.delimiter(); + value.id = CSSValueInvalid; + value.isInt = false; + } else { + CSSParserFunction* function = new CSSParserFunction; + function->name.init(token.value()); + value.setFromFunction(function); + CSSParserString tokenValue; + tokenValue.init(token.value()); + value.id = cssValueKeywordID(tokenValue); + } + m_valueList.addValue(value); +} + +void MediaQueryData::setMediaType(const String& mediaType) +{ + m_mediaType = mediaType; + m_mediaTypeSet = true; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h new file mode 100644 index 00000000000..84609982f3c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryParser.h @@ -0,0 +1,107 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaQueryParser_h +#define MediaQueryParser_h + +#include "core/css/CSSParserValues.h" +#include "core/css/MediaList.h" +#include "core/css/MediaQuery.h" +#include "core/css/MediaQueryExp.h" +#include "core/css/parser/MediaQueryBlockWatcher.h" +#include "core/css/parser/MediaQueryToken.h" +#include "wtf/Vector.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class MediaQuerySet; + +class MediaQueryData { + STACK_ALLOCATED(); +private: + MediaQuery::Restrictor m_restrictor; + String m_mediaType; + OwnPtrWillBeMember<ExpressionHeapVector> m_expressions; + String m_mediaFeature; + CSSParserValueList m_valueList; + bool m_mediaTypeSet; + +public: + MediaQueryData(); + void clear(); + bool addExpression(); + void addParserValue(MediaQueryTokenType, const MediaQueryToken&); + void setMediaType(const String&); + PassOwnPtrWillBeRawPtr<MediaQuery> takeMediaQuery(); + + inline bool currentMediaQueryChanged() const + { + return (m_restrictor != MediaQuery::None || m_mediaTypeSet || m_expressions->size() > 0); + } + + inline void setRestrictor(MediaQuery::Restrictor restrictor) { m_restrictor = restrictor; } + + inline void setMediaFeature(const String& str) { m_mediaFeature = str; } +}; + +class MediaQueryParser { + STACK_ALLOCATED(); +public: + static PassRefPtrWillBeRawPtr<MediaQuerySet> parseMediaQuerySet(const String&); + static PassRefPtrWillBeRawPtr<MediaQuerySet> parseMediaCondition(MediaQueryTokenIterator, MediaQueryTokenIterator endToken); + +private: + enum ParserType { + MediaQuerySetParser, + MediaConditionParser, + }; + + MediaQueryParser(ParserType); + virtual ~MediaQueryParser(); + + PassRefPtrWillBeRawPtr<MediaQuerySet> parseImpl(MediaQueryTokenIterator, MediaQueryTokenIterator endToken); + + void processToken(const MediaQueryToken&); + + void readRestrictor(MediaQueryTokenType, const MediaQueryToken&); + void readMediaType(MediaQueryTokenType, const MediaQueryToken&); + void readAnd(MediaQueryTokenType, const MediaQueryToken&); + void readFeatureStart(MediaQueryTokenType, const MediaQueryToken&); + void readFeature(MediaQueryTokenType, const MediaQueryToken&); + void readFeatureColon(MediaQueryTokenType, const MediaQueryToken&); + void readFeatureValue(MediaQueryTokenType, const MediaQueryToken&); + void readFeatureEnd(MediaQueryTokenType, const MediaQueryToken&); + void skipUntilComma(MediaQueryTokenType, const MediaQueryToken&); + void skipUntilBlockEnd(MediaQueryTokenType, const MediaQueryToken&); + void done(MediaQueryTokenType, const MediaQueryToken&); + + typedef void (MediaQueryParser::*State)(MediaQueryTokenType, const MediaQueryToken&); + + void setStateAndRestrict(State, MediaQuery::Restrictor); + void handleBlocks(const MediaQueryToken&); + + State m_state; + ParserType m_parserType; + MediaQueryData m_mediaQueryData; + RefPtrWillBeMember<MediaQuerySet> m_querySet; + MediaQueryBlockWatcher m_blockWatcher; + + const static State ReadRestrictor; + const static State ReadMediaType; + const static State ReadAnd; + const static State ReadFeatureStart; + const static State ReadFeature; + const static State ReadFeatureColon; + const static State ReadFeatureValue; + const static State ReadFeatureEnd; + const static State SkipUntilComma; + const static State SkipUntilBlockEnd; + const static State Done; + +}; + +} // namespace WebCore + +#endif // MediaQueryParser_h diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryToken.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryToken.cpp new file mode 100644 index 00000000000..fb6bcb39d05 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryToken.cpp @@ -0,0 +1,129 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/MediaQueryToken.h" + +#include "wtf/HashMap.h" +#include "wtf/text/StringHash.h" +#include <limits.h> + +namespace WebCore { + + +MediaQueryToken::MediaQueryToken(MediaQueryTokenType type, BlockType blockType) + : m_type(type) + , m_delimiter(0) + , m_numericValue(0) + , m_unit(CSSPrimitiveValue::CSS_UNKNOWN) + , m_blockType(blockType) +{ +} + +// Just a helper used for Delimiter tokens. +MediaQueryToken::MediaQueryToken(MediaQueryTokenType type, UChar c) + : m_type(type) + , m_delimiter(c) + , m_numericValue(0) + , m_unit(CSSPrimitiveValue::CSS_UNKNOWN) + , m_blockType(NotBlock) +{ + ASSERT(m_type == DelimiterToken); +} + +MediaQueryToken::MediaQueryToken(MediaQueryTokenType type, String value, BlockType blockType) + : m_type(type) + , m_value(value) + , m_delimiter(0) + , m_numericValue(0) + , m_unit(CSSPrimitiveValue::CSS_UNKNOWN) + , m_blockType(blockType) +{ +} + +MediaQueryToken::MediaQueryToken(MediaQueryTokenType type, double numericValue, NumericValueType numericValueType) + : m_type(type) + , m_delimiter(0) + , m_numericValueType(numericValueType) + , m_numericValue(numericValue) + , m_unit(CSSPrimitiveValue::CSS_NUMBER) + , m_blockType(NotBlock) +{ + ASSERT(type == NumberToken); +} + +void MediaQueryToken::convertToDimensionWithUnit(String unit) +{ + ASSERT(m_type == NumberToken); + m_type = DimensionToken; + m_unit = CSSPrimitiveValue::fromName(unit); +} + +void MediaQueryToken::convertToPercentage() +{ + ASSERT(m_type == NumberToken); + m_type = PercentageToken; + m_unit = CSSPrimitiveValue::CSS_PERCENTAGE; +} + +// This function is used only for testing +// FIXME - This doesn't cover all possible Token types, but it's enough for current testing. +String MediaQueryToken::textForUnitTests() const +{ + char buffer[std::numeric_limits<float>::digits]; + if (!m_value.isNull()) + return m_value; + if (m_type == LeftParenthesisToken) + return String("("); + if (m_type == RightParenthesisToken) + return String(")"); + if (m_type == ColonToken) + return String(":"); + if (m_type == WhitespaceToken) + return String(" "); + + if (m_delimiter) { + sprintf(buffer, "'%c'", m_delimiter); + return String(buffer, strlen(buffer)); + } + if (m_numericValue) { + static const unsigned maxUnitBufferLength = 6; + char unitBuffer[maxUnitBufferLength] = {0}; + if (m_unit == CSSPrimitiveValue::CSS_PERCENTAGE) + sprintf(unitBuffer, "%s", "%"); + else if (m_unit == CSSPrimitiveValue::CSS_PX) + sprintf(unitBuffer, "%s", "px"); + else if (m_unit == CSSPrimitiveValue::CSS_EMS) + sprintf(unitBuffer, "%s", "em"); + else if (m_unit != CSSPrimitiveValue::CSS_NUMBER) + sprintf(unitBuffer, "%s", "other"); + if (m_numericValueType == IntegerValueType) + sprintf(buffer, "%d%s", static_cast<int>(m_numericValue), unitBuffer); + else + sprintf(buffer, "%f%s", m_numericValue, unitBuffer); + + return String(buffer, strlen(buffer)); + } + return String(); +} + +UChar MediaQueryToken::delimiter() const +{ + ASSERT(m_type == DelimiterToken); + return m_delimiter; +} + +NumericValueType MediaQueryToken::numericValueType() const +{ + ASSERT(m_type == NumberToken || m_type == PercentageToken || m_type == DimensionToken); + return m_numericValueType; +} + +double MediaQueryToken::numericValue() const +{ + ASSERT(m_type == NumberToken || m_type == PercentageToken || m_type == DimensionToken); + return m_numericValue; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryToken.h b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryToken.h new file mode 100644 index 00000000000..5e602e8cbf6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryToken.h @@ -0,0 +1,88 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaQueryToken_h +#define MediaQueryToken_h + +#include "core/css/CSSPrimitiveValue.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +enum MediaQueryTokenType { + IdentToken = 0, + FunctionToken, + DelimiterToken, + NumberToken, + PercentageToken, + DimensionToken, + WhitespaceToken, + ColonToken, + SemicolonToken, + CommaToken, + LeftParenthesisToken, + RightParenthesisToken, + LeftBracketToken, + RightBracketToken, + LeftBraceToken, + RightBraceToken, + StringToken, + BadStringToken, + EOFToken, + CommentToken, +}; + +enum NumericValueType { + IntegerValueType, + NumberValueType, +}; + +class MediaQueryToken { +public: + enum BlockType { + NotBlock, + BlockStart, + BlockEnd, + }; + + MediaQueryToken(MediaQueryTokenType, BlockType = NotBlock); + MediaQueryToken(MediaQueryTokenType, String value, BlockType = NotBlock); + + MediaQueryToken(MediaQueryTokenType, UChar); // for DelimiterToken + MediaQueryToken(MediaQueryTokenType, double, NumericValueType); // for NumberToken + + // Converts NumberToken to DimensionToken. + void convertToDimensionWithUnit(String); + + // Converts NumberToken to PercentageToken. + void convertToPercentage(); + + MediaQueryTokenType type() const { return m_type; } + String value() const { return m_value; } + String textForUnitTests() const; + + UChar delimiter() const; + NumericValueType numericValueType() const; + double numericValue() const; + BlockType blockType() const { return m_blockType; } + CSSPrimitiveValue::UnitType unitType() const { return m_unit; } + +private: + MediaQueryTokenType m_type; + String m_value; + + UChar m_delimiter; // Could be rolled into m_value? + + NumericValueType m_numericValueType; + double m_numericValue; + CSSPrimitiveValue::UnitType m_unit; + + BlockType m_blockType; +}; + +typedef Vector<MediaQueryToken>::iterator MediaQueryTokenIterator; + +} // namespace + +#endif // MediaQueryToken_h diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizer.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizer.cpp new file mode 100644 index 00000000000..1e0b467f4f9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizer.cpp @@ -0,0 +1,527 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/MediaQueryTokenizer.h" + +namespace WebCore { +#include "core/MediaQueryTokenizerCodepoints.cpp" +} + +#include "core/css/parser/MediaQueryInputStream.h" +#include "core/html/parser/HTMLParserIdioms.h" +#include "wtf/unicode/CharacterNames.h" + +namespace WebCore { + +// http://dev.w3.org/csswg/css-syntax/#name-start-code-point +static bool isNameStart(UChar c) +{ + if (isASCIIAlpha(c)) + return true; + if (c == '_') + return true; + return !isASCII(c); +} + +// http://dev.w3.org/csswg/css-syntax/#name-code-point +static bool isNameChar(UChar c) +{ + return isNameStart(c) || isASCIIDigit(c) || c == '-'; +} + +// http://dev.w3.org/csswg/css-syntax/#check-if-two-code-points-are-a-valid-escape +static bool twoCharsAreValidEscape(UChar first, UChar second) +{ + return ((first == '\\') && (second != '\n') && (second != kEndOfFileMarker)); +} + +MediaQueryTokenizer::MediaQueryTokenizer(MediaQueryInputStream& inputStream) + : m_input(inputStream) +{ +} + +void MediaQueryTokenizer::reconsume(UChar c) +{ + m_input.pushBack(c); +} + +UChar MediaQueryTokenizer::consume() +{ + UChar current = m_input.nextInputChar(); + m_input.advance(); + return current; +} + +void MediaQueryTokenizer::consume(unsigned offset) +{ + m_input.advance(offset); +} + +MediaQueryToken MediaQueryTokenizer::whiteSpace(UChar cc) +{ + // CSS Tokenization is currently lossy, but we could record + // the exact whitespace instead of discarding it here. + consumeUntilNonWhitespace(); + return MediaQueryToken(WhitespaceToken); +} + +static bool popIfBlockMatches(Vector<MediaQueryTokenType>& blockStack, MediaQueryTokenType type) +{ + if (!blockStack.isEmpty() && blockStack.last() == type) { + blockStack.removeLast(); + return true; + } + return false; +} + +MediaQueryToken MediaQueryTokenizer::blockStart(MediaQueryTokenType type) +{ + m_blockStack.append(type); + return MediaQueryToken(type, MediaQueryToken::BlockStart); +} + +MediaQueryToken MediaQueryTokenizer::blockStart(MediaQueryTokenType blockType, MediaQueryTokenType type, String name) +{ + m_blockStack.append(blockType); + return MediaQueryToken(type, name, MediaQueryToken::BlockStart); +} + +MediaQueryToken MediaQueryTokenizer::blockEnd(MediaQueryTokenType type, MediaQueryTokenType startType) +{ + if (popIfBlockMatches(m_blockStack, startType)) + return MediaQueryToken(type, MediaQueryToken::BlockEnd); + return MediaQueryToken(type); +} + +MediaQueryToken MediaQueryTokenizer::leftParenthesis(UChar cc) +{ + return blockStart(LeftParenthesisToken); +} + +MediaQueryToken MediaQueryTokenizer::rightParenthesis(UChar cc) +{ + return blockEnd(RightParenthesisToken, LeftParenthesisToken); +} + +MediaQueryToken MediaQueryTokenizer::leftBracket(UChar cc) +{ + return blockStart(LeftBracketToken); +} + +MediaQueryToken MediaQueryTokenizer::rightBracket(UChar cc) +{ + return blockEnd(RightBracketToken, LeftBracketToken); +} + +MediaQueryToken MediaQueryTokenizer::leftBrace(UChar cc) +{ + return blockStart(LeftBraceToken); +} + +MediaQueryToken MediaQueryTokenizer::rightBrace(UChar cc) +{ + return blockEnd(RightBraceToken, LeftBraceToken); +} + +MediaQueryToken MediaQueryTokenizer::plusOrFullStop(UChar cc) +{ + if (nextCharsAreNumber(cc)) { + reconsume(cc); + return consumeNumericToken(); + } + return MediaQueryToken(DelimiterToken, cc); +} + +MediaQueryToken MediaQueryTokenizer::asterisk(UChar cc) +{ + return MediaQueryToken(DelimiterToken, cc); +} + +MediaQueryToken MediaQueryTokenizer::comma(UChar cc) +{ + return MediaQueryToken(CommaToken); +} + +MediaQueryToken MediaQueryTokenizer::hyphenMinus(UChar cc) +{ + if (nextCharsAreNumber(cc)) { + reconsume(cc); + return consumeNumericToken(); + } + if (nextCharsAreIdentifier(cc)) { + reconsume(cc); + return consumeIdentLikeToken(); + } + return MediaQueryToken(DelimiterToken, cc); +} + +MediaQueryToken MediaQueryTokenizer::solidus(UChar cc) +{ + if (consumeIfNext('*')) { + // We're intentionally deviating from the spec here, by creating tokens for CSS comments. + return consumeUntilCommentEndFound()? MediaQueryToken(CommentToken): MediaQueryToken(EOFToken); + } + + return MediaQueryToken(DelimiterToken, cc); +} + +MediaQueryToken MediaQueryTokenizer::colon(UChar cc) +{ + return MediaQueryToken(ColonToken); +} + +MediaQueryToken MediaQueryTokenizer::semiColon(UChar cc) +{ + return MediaQueryToken(SemicolonToken); +} + +MediaQueryToken MediaQueryTokenizer::reverseSolidus(UChar cc) +{ + if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { + reconsume(cc); + return consumeIdentLikeToken(); + } + return MediaQueryToken(DelimiterToken, cc); +} + +MediaQueryToken MediaQueryTokenizer::asciiDigit(UChar cc) +{ + reconsume(cc); + return consumeNumericToken(); +} + +MediaQueryToken MediaQueryTokenizer::nameStart(UChar cc) +{ + reconsume(cc); + return consumeIdentLikeToken(); +} + +MediaQueryToken MediaQueryTokenizer::stringStart(UChar cc) +{ + return consumeStringTokenUntil(cc); +} + +MediaQueryToken MediaQueryTokenizer::endOfFile(UChar cc) +{ + return MediaQueryToken(EOFToken); +} + +void MediaQueryTokenizer::tokenize(String string, Vector<MediaQueryToken>& outTokens) +{ + // According to the spec, we should perform preprocessing here. + // See: http://dev.w3.org/csswg/css-syntax/#input-preprocessing + // + // However, we can skip this step since: + // * We're using HTML spaces (which accept \r and \f as a valid white space) + // * Do not count white spaces + // * consumeEscape replaces NULLs for replacement characters + + if (string.isEmpty()) + return; + + MediaQueryInputStream input(string); + MediaQueryTokenizer tokenizer(input); + while (true) { + MediaQueryToken token = tokenizer.nextToken(); + outTokens.append(token); + if (token.type() == EOFToken) + return; + } +} + +MediaQueryToken MediaQueryTokenizer::nextToken() +{ + // Unlike the HTMLTokenizer, the CSS Syntax spec is written + // as a stateless, (fixed-size) look-ahead tokenizer. + // We could move to the stateful model and instead create + // states for all the "next 3 codepoints are X" cases. + // State-machine tokenizers are easier to write to handle + // incremental tokenization of partial sources. + // However, for now we follow the spec exactly. + UChar cc = consume(); + CodePoint codePointFunc = 0; + + if (isASCII(cc)) { + ASSERT_WITH_SECURITY_IMPLICATION(cc < codePointsNumber); + codePointFunc = codePoints[cc]; + } else { + codePointFunc = &MediaQueryTokenizer::nameStart; + } + + if (codePointFunc) + return ((this)->*(codePointFunc))(cc); + return MediaQueryToken(DelimiterToken, cc); +} + +static int getSign(MediaQueryInputStream& input, unsigned& offset) +{ + int sign = 1; + if (input.nextInputChar() == '+') { + ++offset; + } else if (input.peek(offset) == '-') { + sign = -1; + ++offset; + } + return sign; +} + +static unsigned long long getInteger(MediaQueryInputStream& input, unsigned& offset) +{ + unsigned intStartPos = offset; + offset = input.skipWhilePredicate<isASCIIDigit>(offset); + unsigned intEndPos = offset; + return input.getUInt(intStartPos, intEndPos); +} + +static double getFraction(MediaQueryInputStream& input, unsigned& offset, unsigned& digitsNumber) +{ + unsigned fractionStartPos = 0; + unsigned fractionEndPos = 0; + if (input.peek(offset) == '.' && isASCIIDigit(input.peek(++offset))) { + fractionStartPos = offset - 1; + offset = input.skipWhilePredicate<isASCIIDigit>(offset); + fractionEndPos = offset; + } + digitsNumber = fractionEndPos- fractionStartPos; + return input.getDouble(fractionStartPos, fractionEndPos); +} + +static unsigned long long getExponent(MediaQueryInputStream& input, unsigned& offset, int& sign) +{ + unsigned exponentStartPos = 0; + unsigned exponentEndPos = 0; + if ((input.peek(offset) == 'E' || input.peek(offset) == 'e')) { + int offsetBeforeExponent = offset; + ++offset; + if (input.peek(offset) == '+') { + ++offset; + } else if (input.peek(offset) =='-') { + sign = -1; + ++offset; + } + exponentStartPos = offset; + offset = input.skipWhilePredicate<isASCIIDigit>(offset); + exponentEndPos = offset; + if (exponentEndPos == exponentStartPos) + offset = offsetBeforeExponent; + } + return input.getUInt(exponentStartPos, exponentEndPos); +} + +// This method merges the following spec sections for efficiency +// http://www.w3.org/TR/css3-syntax/#consume-a-number +// http://www.w3.org/TR/css3-syntax/#convert-a-string-to-a-number +MediaQueryToken MediaQueryTokenizer::consumeNumber() +{ + ASSERT(nextCharsAreNumber()); + NumericValueType type = IntegerValueType; + double value = 0; + unsigned offset = 0; + int exponentSign = 1; + unsigned fractionDigits; + int sign = getSign(m_input, offset); + unsigned long long integerPart = getInteger(m_input, offset); + double fractionPart = getFraction(m_input, offset, fractionDigits); + unsigned long long exponentPart = getExponent(m_input, offset, exponentSign); + double exponent = pow(10, (float)exponentSign * (double)exponentPart); + value = (double)sign * ((double)integerPart + fractionPart) * exponent; + + m_input.advance(offset); + if (fractionDigits > 0) + type = NumberValueType; + + return MediaQueryToken(NumberToken, value, type); +} + +// http://www.w3.org/TR/css3-syntax/#consume-a-numeric-token +MediaQueryToken MediaQueryTokenizer::consumeNumericToken() +{ + MediaQueryToken token = consumeNumber(); + if (nextCharsAreIdentifier()) + token.convertToDimensionWithUnit(consumeName()); + else if (consumeIfNext('%')) + token.convertToPercentage(); + return token; +} + +// http://www.w3.org/TR/css3-syntax/#consume-an-ident-like-token +MediaQueryToken MediaQueryTokenizer::consumeIdentLikeToken() +{ + String name = consumeName(); + if (consumeIfNext('(')) { + return blockStart(LeftParenthesisToken, FunctionToken, name); + } + return MediaQueryToken(IdentToken, name); +} + +static bool isNewLine(UChar cc) +{ + // We check \r and \f here, since we have no preprocessing stage + return (cc == '\r' || cc == '\n' || cc == '\f'); +} + +// http://dev.w3.org/csswg/css-syntax/#consume-a-string-token +MediaQueryToken MediaQueryTokenizer::consumeStringTokenUntil(UChar endingCodePoint) +{ + StringBuilder output; + while (true) { + UChar cc = consume(); + if (cc == endingCodePoint || cc == kEndOfFileMarker) { + // The "reconsume" here deviates from the spec, but is required to avoid consuming past the EOF + if (cc == kEndOfFileMarker) + reconsume(cc); + return MediaQueryToken(StringToken, output.toString()); + } + if (isNewLine(cc)) { + reconsume(cc); + return MediaQueryToken(BadStringToken); + } + if (cc == '\\') { + if (m_input.nextInputChar() == kEndOfFileMarker) + continue; + if (isNewLine(m_input.nextInputChar())) + consume(); + else + output.append(consumeEscape()); + } else { + output.append(cc); + } + } +} + +void MediaQueryTokenizer::consumeUntilNonWhitespace() +{ + // Using HTML space here rather than CSS space since we don't do preprocessing + while (isHTMLSpace<UChar>(m_input.nextInputChar())) + consume(); +} + +bool MediaQueryTokenizer::consumeUntilCommentEndFound() +{ + UChar c = consume(); + while (true) { + if (c == kEndOfFileMarker) + return false; + if (c != '*') { + c = consume(); + continue; + } + c = consume(); + if (c == '/') + break; + } + return true; +} + +bool MediaQueryTokenizer::consumeIfNext(UChar character) +{ + if (m_input.nextInputChar() == character) { + consume(); + return true; + } + return false; +} + +// http://www.w3.org/TR/css3-syntax/#consume-a-name +String MediaQueryTokenizer::consumeName() +{ + // FIXME: Is this as efficient as it can be? + // The possibility of escape chars mandates a copy AFAICT. + StringBuilder result; + while (true) { + UChar cc = consume(); + if (isNameChar(cc)) { + result.append(cc); + continue; + } + if (twoCharsAreValidEscape(cc, m_input.nextInputChar())) { + result.append(consumeEscape()); + continue; + } + reconsume(cc); + return result.toString(); + } +} + +// http://dev.w3.org/csswg/css-syntax/#consume-an-escaped-code-point +UChar MediaQueryTokenizer::consumeEscape() +{ + UChar cc = consume(); + ASSERT(cc != '\n'); + if (isASCIIHexDigit(cc)) { + unsigned consumedHexDigits = 1; + StringBuilder hexChars; + hexChars.append(cc); + while (consumedHexDigits < 6 && isASCIIHexDigit(m_input.nextInputChar())) { + cc = consume(); + hexChars.append(cc); + consumedHexDigits++; + }; + bool ok = false; + UChar codePoint = hexChars.toString().toUIntStrict(&ok, 16); + if (!ok) + return WTF::Unicode::replacementCharacter; + return codePoint; + } + + // Replaces NULLs with replacement characters, since we do not perform preprocessing + if (cc == kEndOfFileMarker) + return WTF::Unicode::replacementCharacter; + return cc; +} + +bool MediaQueryTokenizer::nextTwoCharsAreValidEscape() +{ + if (m_input.leftChars() < 1) + return false; + return twoCharsAreValidEscape(m_input.nextInputChar(), m_input.peek(1)); +} + +// http://www.w3.org/TR/css3-syntax/#starts-with-a-number +bool MediaQueryTokenizer::nextCharsAreNumber(UChar first) +{ + UChar second = m_input.nextInputChar(); + if (isASCIIDigit(first)) + return true; + if (first == '+' || first == '-') + return ((isASCIIDigit(second)) || (second == '.' && isASCIIDigit(m_input.peek(1)))); + if (first =='.') + return (isASCIIDigit(second)); + return false; +} + +bool MediaQueryTokenizer::nextCharsAreNumber() +{ + UChar first = consume(); + bool areNumber = nextCharsAreNumber(first); + reconsume(first); + return areNumber; +} + +// http://www.w3.org/TR/css3-syntax/#would-start-an-identifier +bool MediaQueryTokenizer::nextCharsAreIdentifier(UChar first) +{ + UChar second = m_input.nextInputChar(); + if (isNameStart(first) || twoCharsAreValidEscape(first, second)) + return true; + + if (first == '-') { + if (isNameStart(m_input.nextInputChar())) + return true; + return nextTwoCharsAreValidEscape(); + } + + return false; +} + +bool MediaQueryTokenizer::nextCharsAreIdentifier() +{ + UChar first = consume(); + bool areIdentifier = nextCharsAreIdentifier(first); + reconsume(first); + return areIdentifier; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizer.h b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizer.h new file mode 100644 index 00000000000..c59a96d299a --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizer.h @@ -0,0 +1,85 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MediaQueryTokenizer_h +#define MediaQueryTokenizer_h + +#include "core/css/parser/MediaQueryToken.h" +#include "core/html/parser/InputStreamPreprocessor.h" +#include "wtf/text/WTFString.h" + +#include <climits> + +namespace WebCore { + +class MediaQueryInputStream; + +class MediaQueryTokenizer { + WTF_MAKE_NONCOPYABLE(MediaQueryTokenizer); + WTF_MAKE_FAST_ALLOCATED; +public: + static void tokenize(String, Vector<MediaQueryToken>&); +private: + MediaQueryTokenizer(MediaQueryInputStream&); + + MediaQueryToken nextToken(); + + UChar consume(); + void consume(unsigned); + void reconsume(UChar); + + MediaQueryToken consumeNumericToken(); + MediaQueryToken consumeIdentLikeToken(); + MediaQueryToken consumeNumber(); + MediaQueryToken consumeStringTokenUntil(UChar); + + void consumeUntilNonWhitespace(); + bool consumeUntilCommentEndFound(); + + bool consumeIfNext(UChar); + String consumeName(); + UChar consumeEscape(); + + bool nextTwoCharsAreValidEscape(); + bool nextCharsAreNumber(UChar); + bool nextCharsAreNumber(); + bool nextCharsAreIdentifier(UChar); + bool nextCharsAreIdentifier(); + MediaQueryToken blockStart(MediaQueryTokenType); + MediaQueryToken blockStart(MediaQueryTokenType blockType, MediaQueryTokenType, String); + MediaQueryToken blockEnd(MediaQueryTokenType, MediaQueryTokenType startType); + + typedef MediaQueryToken (MediaQueryTokenizer::*CodePoint)(UChar); + + static const CodePoint codePoints[]; + Vector<MediaQueryTokenType> m_blockStack; + + MediaQueryToken whiteSpace(UChar); + MediaQueryToken leftParenthesis(UChar); + MediaQueryToken rightParenthesis(UChar); + MediaQueryToken leftBracket(UChar); + MediaQueryToken rightBracket(UChar); + MediaQueryToken leftBrace(UChar); + MediaQueryToken rightBrace(UChar); + MediaQueryToken plusOrFullStop(UChar); + MediaQueryToken comma(UChar); + MediaQueryToken hyphenMinus(UChar); + MediaQueryToken asterisk(UChar); + MediaQueryToken solidus(UChar); + MediaQueryToken colon(UChar); + MediaQueryToken semiColon(UChar); + MediaQueryToken reverseSolidus(UChar); + MediaQueryToken asciiDigit(UChar); + MediaQueryToken nameStart(UChar); + MediaQueryToken stringStart(UChar); + MediaQueryToken endOfFile(UChar); + + MediaQueryInputStream& m_input; +}; + + + +} // namespace WebCore + +#endif // MediaQueryTokenizer_h diff --git a/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizerTest.cpp b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizerTest.cpp new file mode 100644 index 00000000000..c611dc435c2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/MediaQueryTokenizerTest.cpp @@ -0,0 +1,173 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/MediaQueryTokenizer.h" + +#include "core/css/parser/MediaQueryBlockWatcher.h" +#include "wtf/PassOwnPtr.h" +#include <gtest/gtest.h> + +namespace WebCore { + +typedef struct { + const char* input; + const char* output; +} TestCase; + +typedef struct { + const char* input; + const unsigned maxLevel; + const unsigned finalLevel; +} BlockTestCase; + +TEST(MediaQueryTokenizerTest, Basic) +{ + TestCase testCases[] = { + { "(max-width: 50px)", "(max-width: 50px)" }, + { "(max-width: 1e+2px)", "(max-width: 100px)" }, + { "(max-width: 1e2px)", "(max-width: 100px)" }, + { "(max-width: 1000e-1px)", "(max-width: 100px)" }, + { "(max-width: 50\\70\\78)", "(max-width: 50px)" }, + { "(max-width: /* comment */50px)", "(max-width: 50px)" }, + { "(max-width: /** *commen*t */60px)", "(max-width: 60px)" }, + { "(max-width: /** *commen*t **/70px)", "(max-width: 70px)" }, + { "(max-width: /** *commen*t **//**/80px)", "(max-width: 80px)" }, + { "(max-width: /*/ **/90px)", "(max-width: 90px)" }, + { "(max-width: /*/ **/*100px)", "(max-width: '*'100px)" }, + { "(max-width: 110px/*)", "(max-width: 110px" }, + { "(max-width: 120px)/*", "(max-width: 120px)" }, + { "(max-width: 130px)/**", "(max-width: 130px)" }, + { "(max-width: /***/140px)/**/", "(max-width: 140px)" }, + { "(max-width: '40px')", "(max-width: 40px)" }, + { "(max-width: '40px", "(max-width: 40px" }, + { "(max-width: '40px\n", "(max-width: " }, + { "(max-width: '40px\\", "(max-width: 40px" }, + { "(max-width: '40px\\\n", "(max-width: 40px" }, + { "(max-width: '40px\\\n')", "(max-width: 40px)" }, + { "(max-width: '40\\70\\78')", "(max-width: 40px)" }, + { "(max-width: '40\\\npx')", "(max-width: 40px)" }, + { "(max-aspect-ratio: 5)", "(max-aspect-ratio: 5)" }, + { "(max-aspect-ratio: +5)", "(max-aspect-ratio: 5)" }, + { "(max-aspect-ratio: -5)", "(max-aspect-ratio: -5)" }, + { "(max-aspect-ratio: -+5)", "(max-aspect-ratio: '-'5)" }, + { "(max-aspect-ratio: +-5)", "(max-aspect-ratio: '+'-5)" }, + { "(max-aspect-ratio: +bla5)", "(max-aspect-ratio: '+'bla5)" }, + { "(max-aspect-ratio: +5bla)", "(max-aspect-ratio: 5other)" }, + { "(max-aspect-ratio: -bla)", "(max-aspect-ratio: -bla)" }, + { "(max-aspect-ratio: --bla)", "(max-aspect-ratio: '-'-bla)" }, + { 0, 0 } // Do not remove the terminator line. + }; + + for (int i = 0; testCases[i].input; ++i) { + Vector<MediaQueryToken> tokens; + MediaQueryTokenizer::tokenize(testCases[i].input, tokens); + StringBuilder output; + for (size_t j = 0; j < tokens.size(); ++j) + output.append(tokens[j].textForUnitTests()); + ASSERT_STREQ(testCases[i].output, output.toString().ascii().data()); + } +} + +TEST(MediaQueryTokenizerBlockTest, Basic) +{ + BlockTestCase testCases[] = { + {"(max-width: 800px()), (max-width: 800px)", 2, 0}, + {"(max-width: 900px(()), (max-width: 900px)", 3, 1}, + {"(max-width: 600px(())))), (max-width: 600px)", 3, 0}, + {"(max-width: 500px(((((((((())))), (max-width: 500px)", 11, 6}, + {"(max-width: 800px[]), (max-width: 800px)", 2, 0}, + {"(max-width: 900px[[]), (max-width: 900px)", 3, 2}, + {"(max-width: 600px[[]]]]), (max-width: 600px)", 3, 0}, + {"(max-width: 500px[[[[[[[[[[]]]]), (max-width: 500px)", 11, 7}, + {"(max-width: 800px{}), (max-width: 800px)", 2, 0}, + {"(max-width: 900px{{}), (max-width: 900px)", 3, 2}, + {"(max-width: 600px{{}}}}), (max-width: 600px)", 3, 0}, + {"(max-width: 500px{{{{{{{{{{}}}}), (max-width: 500px)", 11, 7}, + {"[(), (max-width: 400px)", 2, 1}, + {"[{}, (max-width: 500px)", 2, 1}, + {"[{]}], (max-width: 900px)", 2, 0}, + {"[{[]{}{{{}}}}], (max-width: 900px)", 5, 0}, + {"[{[}], (max-width: 900px)", 3, 2}, + {"[({)}], (max-width: 900px)", 3, 2}, + {"[]((), (max-width: 900px)", 2, 1}, + {"((), (max-width: 900px)", 2, 1}, + {"(foo(), (max-width: 900px)", 2, 1}, + {"[](()), (max-width: 900px)", 2, 0}, + {"all an[isdfs bla())(i())]icalc(i)(()), (max-width: 400px)", 3, 0}, + {"all an[isdfs bla())(]icalc(i)(()), (max-width: 500px)", 4, 2}, + {"all an[isdfs bla())(]icalc(i)(())), (max-width: 600px)", 4, 1}, + {"all an[isdfs bla())(]icalc(i)(()))], (max-width: 800px)", 4, 0}, + {0, 0, 0} // Do not remove the terminator line. + }; + for (int i = 0; testCases[i].input; ++i) { + Vector<MediaQueryToken> tokens; + MediaQueryTokenizer::tokenize(testCases[i].input, tokens); + MediaQueryBlockWatcher blockWatcher; + + unsigned maxLevel = 0; + unsigned level = 0; + for (size_t j = 0; j < tokens.size(); ++j) { + blockWatcher.handleToken(tokens[j]); + level = blockWatcher.blockLevel(); + maxLevel = std::max(level, maxLevel); + } + ASSERT_EQ(testCases[i].maxLevel, maxLevel); + ASSERT_EQ(testCases[i].finalLevel, level); + } +} + +void testToken(UChar c, MediaQueryTokenType tokenType) +{ + Vector<MediaQueryToken> tokens; + StringBuilder input; + input.append(c); + MediaQueryTokenizer::tokenize(input.toString(), tokens); + ASSERT_EQ(tokens[0].type(), tokenType); +} + +TEST(MediaQueryTokenizerCodepointsTest, Basic) +{ + for (UChar c = 0; c <= 1000; ++c) { + if (isASCIIDigit(c)) + testToken(c, NumberToken); + else if (isASCIIAlpha(c)) + testToken(c, IdentToken); + else if (c == '_') + testToken(c, IdentToken); + else if (c == '\r' || c == ' ' || c == '\n' || c == '\t' || c == '\f') + testToken(c, WhitespaceToken); + else if (c == '(') + testToken(c, LeftParenthesisToken); + else if (c == ')') + testToken(c, RightParenthesisToken); + else if (c == '[') + testToken(c, LeftBracketToken); + else if (c == ']') + testToken(c, RightBracketToken); + else if (c == '{') + testToken(c, LeftBraceToken); + else if (c == '}') + testToken(c, RightBraceToken); + else if (c == '.' || c == '+' || c == '-' || c == '/' || c == '\\') + testToken(c, DelimiterToken); + else if (c == '\'' || c == '"') + testToken(c, StringToken); + else if (c == ',') + testToken(c, CommaToken); + else if (c == ':') + testToken(c, ColonToken); + else if (c == ';') + testToken(c, SemicolonToken); + else if (!c) + testToken(c, EOFToken); + else if (c > SCHAR_MAX) + testToken(c, IdentToken); + else + testToken(c, DelimiterToken); + } + testToken(USHRT_MAX, IdentToken); +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp b/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp new file mode 100644 index 00000000000..15f5590fa19 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.cpp @@ -0,0 +1,141 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/SizesAttributeParser.h" + +#include "core/MediaTypeNames.h" +#include "core/css/MediaQueryEvaluator.h" +#include "core/css/parser/MediaQueryTokenizer.h" +#include "core/css/parser/SizesCalcParser.h" + +namespace WebCore { + +unsigned SizesAttributeParser::findEffectiveSize(const String& attribute, PassRefPtr<MediaValues> mediaValues) +{ + Vector<MediaQueryToken> tokens; + SizesAttributeParser parser(mediaValues); + + MediaQueryTokenizer::tokenize(attribute, tokens); + if (!parser.parse(tokens)) + return parser.effectiveSizeDefaultValue(); + return parser.effectiveSize(); +} + +bool SizesAttributeParser::calculateLengthInPixels(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken, unsigned& result) +{ + if (startToken == endToken) + return false; + MediaQueryTokenType type = startToken->type(); + if (type == DimensionToken) { + int length; + if (!CSSPrimitiveValue::isLength(startToken->unitType())) + return false; + if ((m_mediaValues->computeLength(startToken->numericValue(), startToken->unitType(), length)) && (length > 0)) { + result = (unsigned)length; + return true; + } + } else if (type == FunctionToken) { + return SizesCalcParser::parse(startToken, endToken, m_mediaValues, result); + } else if (type == NumberToken && !startToken->numericValue()) { + result = 0; + return true; + } + + return false; +} + +static void reverseSkipIrrelevantTokens(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken) +{ + MediaQueryTokenIterator endToken = token; + while (token != startToken && (token->type() == WhitespaceToken || token->type() == CommentToken || token->type() == EOFToken)) + --token; + if (token != endToken) + ++token; +} + +static void reverseSkipUntilComponentStart(MediaQueryTokenIterator& token, MediaQueryTokenIterator startToken) +{ + if (token == startToken) + return; + --token; + if (token->blockType() != MediaQueryToken::BlockEnd) + return; + unsigned blockLevel = 0; + while (token != startToken) { + if (token->blockType() == MediaQueryToken::BlockEnd) { + ++blockLevel; + } else if (token->blockType() == MediaQueryToken::BlockStart) { + --blockLevel; + if (!blockLevel) + break; + } + + --token; + } +} + +bool SizesAttributeParser::mediaConditionMatches(PassRefPtrWillBeRawPtr<MediaQuerySet> mediaCondition) +{ + // A Media Condition cannot have a media type other then screen. + MediaQueryEvaluator mediaQueryEvaluator(MediaTypeNames::screen, *m_mediaValues); + return mediaQueryEvaluator.eval(mediaCondition.get()); +} + +bool SizesAttributeParser::parseMediaConditionAndLength(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken) +{ + MediaQueryTokenIterator lengthTokenStart; + MediaQueryTokenIterator lengthTokenEnd; + + reverseSkipIrrelevantTokens(endToken, startToken); + lengthTokenEnd = endToken; + reverseSkipUntilComponentStart(endToken, startToken); + lengthTokenStart = endToken; + unsigned length; + if (!calculateLengthInPixels(lengthTokenStart, lengthTokenEnd, length)) + return false; + RefPtrWillBeRawPtr<MediaQuerySet> mediaCondition = MediaQueryParser::parseMediaCondition(startToken, endToken); + if (mediaCondition && mediaConditionMatches(mediaCondition)) { + m_length = length; + m_lengthWasSet = true; + return true; + } + return false; +} + +bool SizesAttributeParser::parse(Vector<MediaQueryToken>& tokens) +{ + if (tokens.isEmpty()) + return false; + MediaQueryTokenIterator startToken = tokens.begin(); + MediaQueryTokenIterator endToken; + // Split on a comma token, and send the result tokens to be parsed as (media-condition, length) pairs + for (MediaQueryTokenIterator token = tokens.begin(); token != tokens.end(); ++token) { + if (token->type() == CommaToken) { + endToken = token; + if (parseMediaConditionAndLength(startToken, endToken)) + return true; + startToken = token; + ++startToken; + } + } + endToken = tokens.end(); + return parseMediaConditionAndLength(startToken, --endToken); +} + +unsigned SizesAttributeParser::effectiveSize() +{ + if (m_lengthWasSet) + return m_length; + return effectiveSizeDefaultValue(); +} + +unsigned SizesAttributeParser::effectiveSizeDefaultValue() +{ + // Returning the equivalent of "100%" + return m_mediaValues->viewportWidth(); +} + +} // namespace + diff --git a/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h b/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h new file mode 100644 index 00000000000..3c7bc4ee260 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParser.h @@ -0,0 +1,44 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SizesAttributeParser_h +#define SizesAttributeParser_h + +#include "core/css/MediaValues.h" +#include "core/css/parser/MediaQueryParser.h" +#include "platform/heap/Handle.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +class SizesAttributeParser { + STACK_ALLOCATED(); +public: + static unsigned findEffectiveSize(const String& attribute, PassRefPtr<MediaValues>); + +private: + SizesAttributeParser(PassRefPtr<MediaValues> mediaValues) + : m_mediaValues(mediaValues) + , m_length(0) + , m_lengthWasSet(false) + { + } + + bool parse(Vector<MediaQueryToken>& tokens); + bool parseMediaConditionAndLength(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken); + unsigned effectiveSize(); + bool calculateLengthInPixels(MediaQueryTokenIterator startToken, MediaQueryTokenIterator endToken, unsigned& result); + bool mediaConditionMatches(PassRefPtrWillBeRawPtr<MediaQuerySet> mediaCondition); + unsigned effectiveSizeDefaultValue(); + + RefPtrWillBeMember<MediaQuerySet> m_mediaCondition; + RefPtr<MediaValues> m_mediaValues; + unsigned m_length; + bool m_lengthWasSet; +}; + +} // namespace + +#endif + diff --git a/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParserTest.cpp b/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParserTest.cpp new file mode 100644 index 00000000000..0cc866c2acf --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/SizesAttributeParserTest.cpp @@ -0,0 +1,82 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/SizesAttributeParser.h" + +#include "core/css/MediaValuesCached.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +typedef struct { + const char* input; + const int output; +} TestCase; + +TEST(SizesAttributeParserTest, Basic) +{ + TestCase testCases[] = { + {"screen", 500}, + {"(min-width:500px)", 500}, + {"(min-width:500px) 200px", 200}, + {"(min-width:500px) 50vw", 250}, + {"(min-width:500px) 200px, 400px", 200}, + {"400px, (min-width:500px) 200px", 400}, + {"(min-width:5000px) 200px, 400px", 400}, + {"(blalbadfsdf) 200px, 400px", 400}, + {"0", 0}, + {"-0", 0}, + {"1", 500}, + {"300px, 400px", 300}, + {"(min-width:5000px) 200px, (min-width:500px) 400px", 400}, + {"", 500}, + {" ", 500}, + {" /**/ ", 500}, + {" /**/ 300px", 300}, + {"300px /**/ ", 300}, + {" /**/ (min-width:500px) /**/ 300px", 300}, + {"-100px, 200px", 200}, + {"-50vw, 20vw", 100}, + {"50asdf, 200px", 200}, + {"asdf, 200px", 200}, + {"(max-width: 3000px) 200w, 400w", 500}, + {",, , /**/ ,200px", 200}, + {"50vw", 250}, + {"calc(40vw*2)", 400}, + {"(min-width:5000px) calc(5000px/10), (min-width:500px) calc(1200px/3)", 400}, + {"(min-width:500px) calc(1200/3)", 500}, + {"(min-width:500px) calc(1200px/(0px*14))", 500}, + {"(max-width: 3000px) 200px, 400px", 200}, + {"(max-width: 3000px) 20em, 40em", 320}, + {"(max-width: 3000px) 0, 40em", 0}, + {"(max-width: 3000px) 50vw, 40em", 250}, + {0, 0} // Do not remove the terminator line. + }; + + MediaValuesCached::MediaValuesCachedData data; + data.viewportWidth = 500; + data.viewportHeight = 500; + data.deviceWidth = 500; + data.deviceHeight = 500; + data.devicePixelRatio = 2.0; + data.colorBitsPerComponent = 24; + data.monochromeBitsPerComponent = 0; + data.pointer = MediaValues::MousePointer; + data.defaultFontSize = 16; + data.threeDEnabled = true; + data.scanMediaType = false; + data.screenMediaType = true; + data.printMediaType = false; + data.strictMode = true; + RefPtr<MediaValues> mediaValues = MediaValuesCached::create(data); + + for (unsigned i = 0; testCases[i].input; ++i) { + int effectiveSize = SizesAttributeParser::findEffectiveSize(testCases[i].input, mediaValues); + ASSERT_EQ(testCases[i].output, effectiveSize); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParser.cpp b/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParser.cpp new file mode 100644 index 00000000000..f99688bb609 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParser.cpp @@ -0,0 +1,214 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/SizesCalcParser.h" + +#include "core/css/MediaValues.h" +#include "core/css/parser/MediaQueryToken.h" + +namespace WebCore { + +bool SizesCalcParser::parse(MediaQueryTokenIterator start, MediaQueryTokenIterator end, PassRefPtr<MediaValues> mediaValues, unsigned& result) +{ + SizesCalcParser parser(mediaValues); + if (!parser.calcToReversePolishNotation(start, end)) + return false; + return parser.calculate(result); +} + +static bool operatorPriority(UChar cc, bool& highPriority) +{ + if (cc == '+' || cc == '-') + highPriority = false; + else if (cc == '*' || cc == '/') + highPriority = true; + else + return false; + return true; +} + +bool SizesCalcParser::handleOperator(Vector<MediaQueryToken>& stack, const MediaQueryToken& token) +{ + // If the token is an operator, o1, then: + // while there is an operator token, o2, at the top of the stack, and + // either o1 is left-associative and its precedence is equal to that of o2, + // or o1 has precedence less than that of o2, + // pop o2 off the stack, onto the output queue; + // push o1 onto the stack. + bool stackOperatorPriority; + bool incomingOperatorPriority; + + if (!operatorPriority(token.delimiter(), incomingOperatorPriority)) + return false; + if (!stack.isEmpty() && stack.last().type() == DelimiterToken) { + if (!operatorPriority(stack.last().delimiter(), stackOperatorPriority)) + return false; + if (!incomingOperatorPriority || stackOperatorPriority) { + appendOperator(stack.last()); + stack.removeLast(); + } + } + stack.append(token); + return true; +} + +void SizesCalcParser::appendNumber(const MediaQueryToken& token) +{ + SizesCalcValue value; + value.value = token.numericValue(); + m_valueList.append(value); +} + +bool SizesCalcParser::appendLength(const MediaQueryToken& token) +{ + SizesCalcValue value; + double result = 0; + if (!m_mediaValues->computeLength(token.numericValue(), token.unitType(), result)) + return false; + value.value = result; + value.isLength = true; + m_valueList.append(value); + return true; +} + +void SizesCalcParser::appendOperator(const MediaQueryToken& token) +{ + SizesCalcValue value; + value.operation = token.delimiter(); + m_valueList.append(value); +} + +bool SizesCalcParser::calcToReversePolishNotation(MediaQueryTokenIterator start, MediaQueryTokenIterator end) +{ + // This method implements the shunting yard algorithm, to turn the calc syntax into a reverse polish notation. + // http://en.wikipedia.org/wiki/Shunting-yard_algorithm + + Vector<MediaQueryToken> stack; + for (MediaQueryTokenIterator it = start; it != end; ++it) { + MediaQueryTokenType type = it->type(); + switch (type) { + case NumberToken: + appendNumber(*it); + break; + case DimensionToken: + if (!CSSPrimitiveValue::isLength(it->unitType()) || !appendLength(*it)) + return false; + break; + case DelimiterToken: + if (!handleOperator(stack, *it)) + return false; + break; + case FunctionToken: + if (it->value() != "calc") + return false; + // "calc(" is the same as "(" + case LeftParenthesisToken: + // If the token is a left parenthesis, then push it onto the stack. + stack.append(*it); + break; + case RightParenthesisToken: + // If the token is a right parenthesis: + // Until the token at the top of the stack is a left parenthesis, pop operators off the stack onto the output queue. + while (!stack.isEmpty() && stack.last().type() != LeftParenthesisToken && stack.last().type() != FunctionToken) { + appendOperator(stack.last()); + stack.removeLast(); + } + // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. + if (stack.isEmpty()) + return false; + // Pop the left parenthesis from the stack, but not onto the output queue. + stack.removeLast(); + break; + case CommentToken: + case WhitespaceToken: + case EOFToken: + break; + case PercentageToken: + case IdentToken: + case CommaToken: + case ColonToken: + case SemicolonToken: + case LeftBraceToken: + case LeftBracketToken: + case RightBraceToken: + case RightBracketToken: + case StringToken: + case BadStringToken: + return false; + } + } + + // When there are no more tokens to read: + // While there are still operator tokens in the stack: + while (!stack.isEmpty()) { + // If the operator token on the top of the stack is a parenthesis, then there are mismatched parentheses. + MediaQueryTokenType type = stack.last().type(); + if (type == LeftParenthesisToken || type == FunctionToken) + return false; + // Pop the operator onto the output queue. + appendOperator(stack.last()); + stack.removeLast(); + } + return true; +} + +static bool operateOnStack(Vector<SizesCalcValue>& stack, UChar operation) +{ + if (stack.size() < 2) + return false; + SizesCalcValue rightOperand = stack.last(); + stack.removeLast(); + SizesCalcValue leftOperand = stack.last(); + stack.removeLast(); + bool isLength; + switch (operation) { + case '+': + if (rightOperand.isLength != leftOperand.isLength) + return false; + isLength = (rightOperand.isLength && leftOperand.isLength); + stack.append(SizesCalcValue(leftOperand.value + rightOperand.value, isLength)); + break; + case '-': + if (rightOperand.isLength != leftOperand.isLength) + return false; + isLength = (rightOperand.isLength && leftOperand.isLength); + stack.append(SizesCalcValue(leftOperand.value - rightOperand.value, isLength)); + break; + case '*': + if (rightOperand.isLength && leftOperand.isLength) + return false; + isLength = (rightOperand.isLength || leftOperand.isLength); + stack.append(SizesCalcValue(leftOperand.value * rightOperand.value, isLength)); + break; + case '/': + if (rightOperand.isLength || rightOperand.value == 0) + return false; + stack.append(SizesCalcValue(leftOperand.value / rightOperand.value, leftOperand.isLength)); + break; + default: + return false; + } + return true; +} + +bool SizesCalcParser::calculate(unsigned& result) +{ + Vector<SizesCalcValue> stack; + for (Vector<SizesCalcValue>::iterator it = m_valueList.begin(); it != m_valueList.end(); ++it) { + if (it->operation == 0) { + stack.append(*it); + } else { + if (!operateOnStack(stack, it->operation)) + return false; + } + } + if (stack.size() == 1 && stack.last().isLength) { + result = clampTo<unsigned>(stack.last().value); + return true; + } + return false; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParser.h b/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParser.h new file mode 100644 index 00000000000..4e040c6cee6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParser.h @@ -0,0 +1,59 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SizesCalcParser_h +#define SizesCalcParser_h + +#include "core/css/MediaValues.h" +#include "core/css/parser/MediaQueryToken.h" +#include "wtf/text/WTFString.h" + +namespace WebCore { + +struct SizesCalcValue { + double value; + bool isLength; + UChar operation; + + SizesCalcValue() + : value(0) + , isLength(false) + , operation(0) + { + } + + SizesCalcValue(double numericValue, bool length) + : value(numericValue) + , isLength(length) + , operation(0) + { + } +}; + +class SizesCalcParser { + +public: + static bool parse(MediaQueryTokenIterator start, MediaQueryTokenIterator end, PassRefPtr<MediaValues>, unsigned& result); + +private: + SizesCalcParser(PassRefPtr<MediaValues> mediaValues) + : m_mediaValues(mediaValues) + { + } + + bool calcToReversePolishNotation(MediaQueryTokenIterator start, MediaQueryTokenIterator end); + bool calculate(unsigned& result); + void appendNumber(const MediaQueryToken&); + bool appendLength(const MediaQueryToken&); + bool handleOperator(Vector<MediaQueryToken>& stack, const MediaQueryToken&); + void appendOperator(const MediaQueryToken&); + + Vector<SizesCalcValue> m_valueList; + RefPtr<MediaValues> m_mediaValues; +}; + +} // namespace WebCore + +#endif // SizesCalcParser_h + diff --git a/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp b/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp new file mode 100644 index 00000000000..67a6f4d92c2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/parser/SizesCalcParserTest.cpp @@ -0,0 +1,136 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/parser/SizesCalcParser.h" + +#include "core/css/CSSPrimitiveValue.h" +#include "core/css/MediaValuesCached.h" +#include "core/css/StylePropertySet.h" +#include "core/css/parser/MediaQueryTokenizer.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +struct TestCase { + const char* input; + const unsigned output; + const bool valid; + const bool dontRunInCSSCalc; +}; + +static void initLengthArray(CSSLengthArray& lengthArray) +{ + lengthArray.resize(CSSPrimitiveValue::LengthUnitTypeCount); + for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i) + lengthArray.at(i) = 0; +} + +static void verifyCSSCalc(String text, double value, bool valid, unsigned fontSize, unsigned viewportWidth, unsigned viewportHeight) +{ + CSSLengthArray lengthArray; + initLengthArray(lengthArray); + RefPtr<MutableStylePropertySet> propertySet = MutableStylePropertySet::create(); + propertySet->setProperty(CSSPropertyLeft, text); + RefPtrWillBeRawPtr<CSSValue> cssValue = propertySet->getPropertyCSSValue(CSSPropertyLeft); + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(cssValue.get()); + if (primitiveValue) + primitiveValue->accumulateLengthArray(lengthArray); + else + ASSERT_EQ(valid, false); + int length = lengthArray.at(CSSPrimitiveValue::UnitTypePixels); + length += lengthArray.at(CSSPrimitiveValue::UnitTypeFontSize) * fontSize; + length += lengthArray.at(CSSPrimitiveValue::UnitTypeViewportWidth) * viewportWidth / 100.0; + length += lengthArray.at(CSSPrimitiveValue::UnitTypeViewportHeight) * viewportHeight / 100.0; + ASSERT_EQ(value, length); +} + + +TEST(SizesCalcParserTest, Basic) +{ + TestCase testCases[] = { + {"calc(500px + 10em)", 660, true, false}, + {"calc(500px + 2 * 10em)", 820, true, false}, + {"calc(500px + 2*10em)", 820, true, false}, + {"calc(500px + 0.5*10em)", 580, true, false}, + {"calc(500px + (0.5*10em + 13px))", 593, true, false}, + {"calc(100vw + (0.5*10em + 13px))", 593, true, false}, + {"calc(100vh + (0.5*10em + 13px))", 736, true, false}, + {"calc(100vh + calc(0.5*10em + 13px))", 736, true, true}, // CSSCalculationValue does not parse internal "calc(". + {"calc(100vh + (50%*10em + 13px))", 0, false, false}, + {"calc(50em+13px)", 0, false, false}, + {"calc(50em-13px)", 0, false, false}, + {"calc(500px + 10)", 0, false, false}, + {"calc(500 + 10)", 0, false, false}, + {"calc(500px + 10s)", 0, false, true}, // This test ASSERTs in CSSCalculationValue. + {"calc(500px + 1cm)", 537, true, false}, + {"calc(500px - 10s)", 0, false, true}, // This test ASSERTs in CSSCalculationValue. + {"calc(500px - 1cm)", 462, true, false}, + {"calc(50px*10)", 500, true, false}, + {"calc(50px*10px)", 0, false, false}, + {"calc(50px/10px)", 0, false, false}, + {"calc(500px/10)", 50, true, false}, + {"calc(500/10)", 0, false, false}, + {"calc(500px/0.5)", 1000, true, false}, + {"calc(500px/.5)", 1000, true, false}, + {"calc(500/0)", 0, false, false}, + {"calc(500px/0)", 0, false, false}, + {"calc(-500px/10)", 0, true, true}, // CSSCalculationValue does not clamp negative values to 0. + {"calc(((4) * ((10px))))", 40, true, false}, + {"calc(50px / 0)", 0, false, false}, + {"calc(50px / (10 + 10))", 2, true, false}, + {"calc(50px / (10 - 10))", 0, false, false}, + {"calc(50px / (10 * 10))", 0, true, false}, + {"calc(50px / (10 / 10))", 50, true, false}, + {"calc(200px*)", 0, false, false}, + {"calc(+ +200px)", 0, false, false}, + {"calc()", 0, false, false}, + {"calc(100px + + +100px)", 0, false, false}, + {"calc(200px 200px)", 0, false, false}, + {"calc(100px * * 2)", 0, false, false}, + {"calc(100px @ 2)", 0, false, false}, + {"calc(1 flim 2)", 0, false, false}, + {"calc(100px @ 2)", 0, false, false}, + {"calc(1 flim 2)", 0, false, false}, + {"calc(1 flim (2))", 0, false, false}, + {0, 0, true, false} // Do not remove the terminator line. + }; + + + MediaValuesCached::MediaValuesCachedData data; + data.viewportWidth = 500; + data.viewportHeight = 643; + data.deviceWidth = 500; + data.deviceHeight = 643; + data.devicePixelRatio = 2.0; + data.colorBitsPerComponent = 24; + data.monochromeBitsPerComponent = 0; + data.pointer = MediaValues::MousePointer; + data.defaultFontSize = 16; + data.threeDEnabled = true; + data.scanMediaType = false; + data.screenMediaType = true; + data.printMediaType = false; + data.strictMode = true; + RefPtr<MediaValues> mediaValues = MediaValuesCached::create(data); + + for (unsigned i = 0; testCases[i].input; ++i) { + Vector<MediaQueryToken> tokens; + MediaQueryTokenizer::tokenize(testCases[i].input, tokens); + unsigned output; + bool valid = SizesCalcParser::parse(tokens.begin(), tokens.end(), mediaValues, output); + ASSERT_EQ(testCases[i].valid, valid); + if (valid) + ASSERT_EQ(testCases[i].output, output); + } + + for (unsigned i = 0; testCases[i].input; ++i) { + if (testCases[i].dontRunInCSSCalc) + continue; + verifyCSSCalc(testCases[i].input, testCases[i].output, testCases[i].valid, data.defaultFontSize, data.viewportWidth, data.viewportHeight); + } +} + +} // namespace diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp index dbfd63b8bb6..89d6cc3d0bd 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.cpp @@ -40,6 +40,7 @@ #include "core/animation/AnimatableLengthBox.h" #include "core/animation/AnimatableLengthBoxAndBool.h" #include "core/animation/AnimatableLengthPoint.h" +#include "core/animation/AnimatableLengthPoint3D.h" #include "core/animation/AnimatableLengthSize.h" #include "core/animation/AnimatableRepeatable.h" #include "core/animation/AnimatableSVGLength.h" @@ -63,11 +64,11 @@ namespace WebCore { namespace { -Length animatableValueToLength(const AnimatableValue* value, const StyleResolverState& state, NumberRange range = AllValues) +Length animatableValueToLength(const AnimatableValue* value, const StyleResolverState& state, ValueRange range = ValueRangeAll) { if (value->isLength()) - return toAnimatableLength(value)->toLength(state.cssToLengthConversionData(), range); - RefPtr<CSSValue> cssValue = toAnimatableUnknown(value)->toCSSValue(); + return toAnimatableLength(value)->length(state.style()->effectiveZoom(), range); + RefPtrWillBeRawPtr<CSSValue> cssValue = toAnimatableUnknown(value)->toCSSValue(); CSSPrimitiveValue* cssPrimitiveValue = toCSSPrimitiveValue(cssValue.get()); return cssPrimitiveValue->convertToLength<AnyConversion>(state.cssToLengthConversionData()); } @@ -75,10 +76,10 @@ Length animatableValueToLength(const AnimatableValue* value, const StyleResolver BorderImageLength animatableValueToBorderImageLength(const AnimatableValue* value, const StyleResolverState& state) { if (value->isLength()) - return BorderImageLength(toAnimatableLength(value)->toLength(state.cssToLengthConversionData(), NonNegativeValues)); + return BorderImageLength(toAnimatableLength(value)->length(state.style()->effectiveZoom(), ValueRangeNonNegative)); if (value->isDouble()) return BorderImageLength(clampTo<double>(toAnimatableDouble(value)->toDouble(), 0)); - RefPtr<CSSValue> cssValue = toAnimatableUnknown(value)->toCSSValue(); + RefPtrWillBeRawPtr<CSSValue> cssValue = toAnimatableUnknown(value)->toCSSValue(); CSSPrimitiveValue* cssPrimitiveValue = toCSSPrimitiveValue(cssValue.get()); return BorderImageLength(cssPrimitiveValue->convertToLength<AnyConversion>(state.cssToLengthConversionData())); } @@ -89,7 +90,7 @@ template<typename T> T animatableValueRoundClampTo(const AnimatableValue* value, return clampTo<T>(round(toAnimatableDouble(value)->toDouble()), min, max); } -LengthBox animatableValueToLengthBox(const AnimatableValue* value, const StyleResolverState& state, NumberRange range = AllValues) +LengthBox animatableValueToLengthBox(const AnimatableValue* value, const StyleResolverState& state, ValueRange range = ValueRangeAll) { const AnimatableLengthBox* animatableLengthBox = toAnimatableLengthBox(value); return LengthBox( @@ -109,7 +110,7 @@ BorderImageLengthBox animatableValueToBorderImageLengthBox(const AnimatableValue animatableValueToBorderImageLength(animatableLengthBox->left(), state)); } -LengthPoint animatableValueToLengthPoint(const AnimatableValue* value, const StyleResolverState& state, NumberRange range = AllValues) +LengthPoint animatableValueToLengthPoint(const AnimatableValue* value, const StyleResolverState& state, ValueRange range = ValueRangeAll) { const AnimatableLengthPoint* animatableLengthPoint = toAnimatableLengthPoint(value); return LengthPoint( @@ -117,7 +118,7 @@ LengthPoint animatableValueToLengthPoint(const AnimatableValue* value, const Sty animatableValueToLength(animatableLengthPoint->y(), state, range)); } -LengthSize animatableValueToLengthSize(const AnimatableValue* value, const StyleResolverState& state, NumberRange range) +LengthSize animatableValueToLengthSize(const AnimatableValue* value, const StyleResolverState& state, ValueRange range) { const AnimatableLengthSize* animatableLengthSize = toAnimatableLengthSize(value); return LengthSize( @@ -129,23 +130,23 @@ template <CSSPropertyID property> void setFillSize(FillLayer* fillLayer, const AnimatableValue* value, const StyleResolverState& state) { if (value->isLengthSize()) - fillLayer->setSize(FillSize(SizeLength, animatableValueToLengthSize(value, state, NonNegativeValues))); + fillLayer->setSize(FillSize(SizeLength, animatableValueToLengthSize(value, state, ValueRangeNonNegative))); else state.styleMap().mapFillSize(property, fillLayer, toAnimatableUnknown(value)->toCSSValue().get()); } -SVGLength animatableValueToNonNegativeSVGLength(const AnimatableValue* value) +PassRefPtr<SVGLength> animatableValueToNonNegativeSVGLength(const AnimatableValue* value) { - SVGLength length = toAnimatableSVGLength(value)->toSVGLength(); - if (length.valueInSpecifiedUnits() < 0) - length.setValueInSpecifiedUnits(0); - return length; + RefPtr<SVGLength> length = toAnimatableSVGLength(value)->toSVGLength(); + if (length->valueInSpecifiedUnits() < 0) + length->setValueInSpecifiedUnits(0); + return length.release(); } template <CSSPropertyID property> void setOnFillLayers(FillLayer* fillLayer, const AnimatableValue* value, StyleResolverState& state) { - const Vector<RefPtr<AnimatableValue> >& values = toAnimatableRepeatable(value)->values(); + const WillBeHeapVector<RefPtrWillBeMember<AnimatableValue> >& values = toAnimatableRepeatable(value)->values(); ASSERT(!values.isEmpty()); FillLayer* prev = 0; for (size_t i = 0; i < values.size(); ++i) { @@ -174,10 +175,10 @@ void setOnFillLayers(FillLayer* fillLayer, const AnimatableValue* value, StyleRe case CSSPropertyBackgroundImage: case CSSPropertyWebkitMaskImage: if (layerValue->isImage()) { - fillLayer->setImage(toAnimatableImage(layerValue)->toStyleImage()); + fillLayer->setImage(state.styleImage(property, toAnimatableImage(layerValue)->toCSSValue())); } else { ASSERT(toAnimatableUnknown(layerValue)->toCSSValueID() == CSSValueNone); - fillLayer->setImage(0); + fillLayer->setImage(nullptr); } break; case CSSPropertyBackgroundPositionX: @@ -225,11 +226,33 @@ void setOnFillLayers(FillLayer* fillLayer, const AnimatableValue* value, StyleRe } } +FontWeight animatableValueToFontWeight(const AnimatableValue* value) +{ + int index = round(toAnimatableDouble(value)->toDouble() / 100) - 1; + + static const FontWeight weights[] = { + FontWeight100, + FontWeight200, + FontWeight300, + FontWeight400, + FontWeight500, + FontWeight600, + FontWeight700, + FontWeight800, + FontWeight900 + }; + + index = clampTo<int>(index, 0, WTF_ARRAY_LENGTH(weights) - 1); + + return weights[index]; +} + } // namespace // FIXME: Generate this function. void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverState& state, const AnimatableValue* value) { + ASSERT(CSSAnimations::isAnimatableProperty(property)); if (value->isUnknown()) { StyleBuilder::applyProperty(property, state, toAnimatableUnknown(value)->toCSSValue().get()); return; @@ -260,10 +283,10 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setVisitedLinkBorderBottomColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderBottomLeftRadius: - style->setBorderBottomLeftRadius(animatableValueToLengthSize(value, state, NonNegativeValues)); + style->setBorderBottomLeftRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderBottomRightRadius: - style->setBorderBottomRightRadius(animatableValueToLengthSize(value, state, NonNegativeValues)); + style->setBorderBottomRightRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderBottomWidth: style->setBorderBottomWidth(animatableValueRoundClampTo<unsigned>(value)); @@ -272,10 +295,10 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setBorderImageOutset(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyBorderImageSlice: - style->setBorderImageSlices(animatableValueToLengthBox(value, state, NonNegativeValues)); + style->setBorderImageSlices(animatableValueToLengthBox(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderImageSource: - style->setBorderImageSource(toAnimatableImage(value)->toStyleImage()); + style->setBorderImageSource(state.styleImage(property, toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyBorderImageWidth: style->setBorderImageWidth(animatableValueToBorderImageLengthBox(value, state)); @@ -299,10 +322,10 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setVisitedLinkBorderTopColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyBorderTopLeftRadius: - style->setBorderTopLeftRadius(animatableValueToLengthSize(value, state, NonNegativeValues)); + style->setBorderTopLeftRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderTopRightRadius: - style->setBorderTopRightRadius(animatableValueToLengthSize(value, state, NonNegativeValues)); + style->setBorderTopRightRadius(animatableValueToLengthSize(value, state, ValueRangeNonNegative)); return; case CSSPropertyBorderTopWidth: style->setBorderTopWidth(animatableValueRoundClampTo<unsigned>(value)); @@ -323,13 +346,13 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setVisitedLinkColor(toAnimatableColor(value)->visitedLinkColor()); return; case CSSPropertyFillOpacity: - // Avoiding a value of 1 forces a layer to be created. - style->setFillOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, nextafterf(1, 0))); + style->setFillOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyFill: { const AnimatableSVGPaint* svgPaint = toAnimatableSVGPaint(value); - style->accessSVGStyle()->setFillPaint(svgPaint->paintType(), svgPaint->color(), svgPaint->uri()); + style->accessSVGStyle()->setFillPaint(svgPaint->paintType(), svgPaint->color(), svgPaint->uri(), true, false); + style->accessSVGStyle()->setFillPaint(svgPaint->visitedLinkPaintType(), svgPaint->visitedLinkColor(), svgPaint->visitedLinkURI(), false, true); } return; case CSSPropertyFlexGrow: @@ -339,7 +362,7 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setFlexShrink(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; case CSSPropertyFlexBasis: - style->setFlexBasis(animatableValueToLength(value, state, NonNegativeValues)); + style->setFlexBasis(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyFloodColor: style->setFloodColor(toAnimatableColor(value)->color()); @@ -350,11 +373,11 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt case CSSPropertyFontSize: style->setFontSize(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0)); return; - case CSSPropertyHeight: - style->setHeight(animatableValueToLength(value, state, NonNegativeValues)); + case CSSPropertyFontWeight: + style->setFontWeight(animatableValueToFontWeight(value)); return; - case CSSPropertyKerning: - style->setKerning(toAnimatableSVGLength(value)->toSVGLength()); + case CSSPropertyHeight: + style->setHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyLeft: style->setLeft(animatableValueToLength(value, state)); @@ -364,12 +387,12 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt return; case CSSPropertyLineHeight: if (value->isLength()) - style->setLineHeight(animatableValueToLength(value, state, NonNegativeValues)); + style->setLineHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); else style->setLineHeight(Length(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0), Percent)); return; case CSSPropertyListStyleImage: - style->setListStyleImage(toAnimatableImage(value)->toStyleImage()); + style->setListStyleImage(state.styleImage(property, toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyLetterSpacing: style->setLetterSpacing(clampTo<float>(toAnimatableDouble(value)->toDouble())); @@ -387,16 +410,16 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setMarginTop(animatableValueToLength(value, state)); return; case CSSPropertyMaxHeight: - style->setMaxHeight(animatableValueToLength(value, state, NonNegativeValues)); + style->setMaxHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMaxWidth: - style->setMaxWidth(animatableValueToLength(value, state, NonNegativeValues)); + style->setMaxWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMinHeight: - style->setMinHeight(animatableValueToLength(value, state, NonNegativeValues)); + style->setMinHeight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyMinWidth: - style->setMinWidth(animatableValueToLength(value, state, NonNegativeValues)); + style->setMinWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyObjectPosition: style->setObjectPosition(animatableValueToLengthPoint(value, state)); @@ -419,16 +442,16 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setOutlineWidth(animatableValueRoundClampTo<unsigned short>(value)); return; case CSSPropertyPaddingBottom: - style->setPaddingBottom(animatableValueToLength(value, state, NonNegativeValues)); + style->setPaddingBottom(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingLeft: - style->setPaddingLeft(animatableValueToLength(value, state, NonNegativeValues)); + style->setPaddingLeft(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingRight: - style->setPaddingRight(animatableValueToLength(value, state, NonNegativeValues)); + style->setPaddingRight(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyPaddingTop: - style->setPaddingTop(animatableValueToLength(value, state, NonNegativeValues)); + style->setPaddingTop(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyRight: style->setRight(animatableValueToLength(value, state)); @@ -443,7 +466,7 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setStopOpacity(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); return; case CSSPropertyStrokeDasharray: - style->setStrokeDashArray(toAnimatableStrokeDasharrayList(value)->toSVGLengthVector()); + style->setStrokeDashArray(toAnimatableStrokeDasharrayList(value)->toSVGLengthList()); return; case CSSPropertyStrokeDashoffset: style->setStrokeDashOffset(toAnimatableSVGLength(value)->toSVGLength()); @@ -457,7 +480,8 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt case CSSPropertyStroke: { const AnimatableSVGPaint* svgPaint = toAnimatableSVGPaint(value); - style->accessSVGStyle()->setStrokePaint(svgPaint->paintType(), svgPaint->color(), svgPaint->uri()); + style->accessSVGStyle()->setStrokePaint(svgPaint->paintType(), svgPaint->color(), svgPaint->uri(), true, false); + style->accessSVGStyle()->setStrokePaint(svgPaint->visitedLinkPaintType(), svgPaint->visitedLinkColor(), svgPaint->visitedLinkURI(), false, true); } return; case CSSPropertyTextDecorationColor: @@ -508,11 +532,11 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setMaskBoxImageOutset(animatableValueToBorderImageLengthBox(value, state)); return; case CSSPropertyWebkitMaskBoxImageSlice: - style->setMaskBoxImageSlices(animatableValueToLengthBox(toAnimatableLengthBoxAndBool(value)->box(), state, NonNegativeValues)); + style->setMaskBoxImageSlices(animatableValueToLengthBox(toAnimatableLengthBoxAndBool(value)->box(), state, ValueRangeNonNegative)); style->setMaskBoxImageSlicesFill(toAnimatableLengthBoxAndBool(value)->flag()); return; case CSSPropertyWebkitMaskBoxImageSource: - style->setMaskBoxImageSource(toAnimatableImage(value)->toStyleImage()); + style->setMaskBoxImageSource(state.styleImage(property, toAnimatableImage(value)->toCSSValue())); return; case CSSPropertyWebkitMaskBoxImageWidth: style->setMaskBoxImageWidth(animatableValueToBorderImageLengthBox(value, state)); @@ -529,23 +553,29 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt case CSSPropertyWebkitMaskSize: setOnFillLayers<CSSPropertyWebkitMaskSize>(style->accessMaskLayers(), value, state); return; - case CSSPropertyWebkitPerspective: + case CSSPropertyPerspective: style->setPerspective(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; + case CSSPropertyPerspectiveOrigin: { + ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); + const AnimatableLengthPoint* animatableLengthPoint = toAnimatableLengthPoint(value); + style->setPerspectiveOriginX(animatableValueToLength(animatableLengthPoint->x(), state)); + style->setPerspectiveOriginY(animatableValueToLength(animatableLengthPoint->y(), state)); + return; + } case CSSPropertyWebkitPerspectiveOriginX: + ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setPerspectiveOriginX(animatableValueToLength(value, state)); return; case CSSPropertyWebkitPerspectiveOriginY: + ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setPerspectiveOriginY(animatableValueToLength(value, state)); return; - case CSSPropertyShapeInside: - style->setShapeInside(toAnimatableShapeValue(value)->shapeValue()); - return; case CSSPropertyShapeOutside: style->setShapeOutside(toAnimatableShapeValue(value)->shapeValue()); return; case CSSPropertyShapeMargin: - style->setShapeMargin(animatableValueToLength(value, state, NonNegativeValues)); + style->setShapeMargin(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyShapeImageThreshold: style->setShapeImageThreshold(clampTo<float>(toAnimatableDouble(value)->toDouble(), 0, 1)); @@ -554,31 +584,44 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setTextStrokeColor(toAnimatableColor(value)->color()); style->setVisitedLinkTextStrokeColor(toAnimatableColor(value)->visitedLinkColor()); return; - case CSSPropertyWebkitTransform: { + case CSSPropertyTransform: { const TransformOperations& operations = toAnimatableTransform(value)->transformOperations(); - // FIXME: Using identity matrix here when the transform list is empty - // forces a layer to be created in the presence of a transform animation. + // FIXME: This normalization (handling of 'none') should be performed at input in AnimatableValueFactory. style->setTransform(operations.size() ? operations : TransformOperations(true)); return; } + case CSSPropertyTransformOrigin: { + ASSERT(RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); + const AnimatableLengthPoint3D* animatableLengthPoint3D = toAnimatableLengthPoint3D(value); + style->setTransformOriginX(animatableValueToLength(animatableLengthPoint3D->x(), state)); + style->setTransformOriginY(animatableValueToLength(animatableLengthPoint3D->y(), state)); + style->setTransformOriginZ(clampTo<float>(toAnimatableDouble(animatableLengthPoint3D->z())->toDouble())); + return; + } case CSSPropertyWebkitTransformOriginX: + ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setTransformOriginX(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginY: + ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setTransformOriginY(animatableValueToLength(value, state)); return; case CSSPropertyWebkitTransformOriginZ: + ASSERT(!RuntimeEnabledFeatures::cssTransformsUnprefixedEnabled()); style->setTransformOriginZ(toAnimatableDouble(value)->toDouble()); return; case CSSPropertyWidows: style->setWidows(animatableValueRoundClampTo<unsigned short>(value, 1)); return; case CSSPropertyWidth: - style->setWidth(animatableValueToLength(value, state, NonNegativeValues)); + style->setWidth(animatableValueToLength(value, state, ValueRangeNonNegative)); return; case CSSPropertyWordSpacing: style->setWordSpacing(clampTo<float>(toAnimatableDouble(value)->toDouble())); return; + case CSSPropertyVerticalAlign: + style->setVerticalAlignLength(animatableValueToLength(value, state)); + return; case CSSPropertyVisibility: style->setVisibility(toAnimatableVisibility(value)->visibility()); return; @@ -589,7 +632,6 @@ void AnimatedStyleBuilder::applyProperty(CSSPropertyID property, StyleResolverSt style->setZoom(clampTo<float>(toAnimatableDouble(value)->toDouble(), std::numeric_limits<float>::denorm_min())); return; default: - ASSERT_WITH_MESSAGE(!CSSAnimations::isAnimatableProperty(property), "Web Animations not yet implemented: Unable to apply AnimatableValue to RenderStyle: %s", getPropertyNameString(property).utf8().data()); ASSERT_NOT_REACHED(); } } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.h b/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.h index 3f91a145a4c..1139c524326 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/AnimatedStyleBuilder.h @@ -31,7 +31,7 @@ #ifndef AnimatedStyleBuilder_h #define AnimatedStyleBuilder_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp index 9eeec75b2c7..465a89e1bbf 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.cpp @@ -28,7 +28,8 @@ #include "config.h" #include "core/css/resolver/CSSToStyleMap.h" -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" +#include "core/animation/css/CSSAnimationData.h" #include "core/css/CSSBorderImageSliceValue.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPrimitiveValueMappings.h" @@ -36,7 +37,6 @@ #include "core/css/Pair.h" #include "core/css/Rect.h" #include "core/css/resolver/StyleResolverState.h" -#include "core/platform/animation/CSSAnimationData.h" #include "core/rendering/style/BorderImageLengthBox.h" #include "core/rendering/style/FillLayer.h" @@ -47,14 +47,9 @@ const CSSToLengthConversionData& CSSToStyleMap::cssToLengthConversionData() cons return m_state.cssToLengthConversionData(); } -bool CSSToStyleMap::useSVGZoomRules() const -{ - return m_state.useSVGZoomRules(); -} - PassRefPtr<StyleImage> CSSToStyleMap::styleImage(CSSPropertyID propertyId, CSSValue* value) { - return m_elementStyleResources.styleImage(m_state.document().textLinkColors(), m_state.style()->color(), propertyId, value); + return m_elementStyleResources.styleImage(m_state.document(), m_state.document().textLinkColors(), m_state.style()->color(), propertyId, value); } void CSSToStyleMap::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value) const @@ -215,9 +210,6 @@ void CSSToStyleMap::mapFillSize(CSSPropertyID, FillLayer* layer, CSSValue* value secondLength = Length(); } - if (firstLength.isUndefined() || secondLength.isUndefined()) - return; - b.setWidth(firstLength); b.setHeight(secondLength); layer->setSizeLength(b); @@ -241,7 +233,6 @@ void CSSToStyleMap::mapFillXPosition(CSSPropertyID propertyID, FillLayer* layer, } Length length = primitiveValue->convertToLength<FixedConversion | PercentConversion>(cssToLengthConversionData()); - ASSERT(!length.isUndefined()); layer->setXPosition(length); if (pair) @@ -266,7 +257,6 @@ void CSSToStyleMap::mapFillYPosition(CSSPropertyID propertyID, FillLayer* layer, } Length length = primitiveValue->convertToLength<FixedConversion | PercentConversion>(cssToLengthConversionData()); - ASSERT(!length.isUndefined()); layer->setYPosition(length); if (pair) @@ -300,207 +290,150 @@ void CSSToStyleMap::mapFillMaskSourceType(CSSPropertyID, FillLayer* layer, CSSVa layer->setMaskSourceType(type); } -void CSSToStyleMap::mapAnimationDelay(CSSAnimationData* animation, CSSValue* value) const +double CSSToStyleMap::mapAnimationDelay(CSSValue* value) { - if (value->isInitialValue()) { - animation->setDelay(CSSAnimationData::initialAnimationDelay()); - return; - } - - if (!value->isPrimitiveValue()) - return; - - animation->setDelay(toCSSPrimitiveValue(value)->computeTime<double, CSSPrimitiveValue::Seconds>()); + if (value->isInitialValue()) + return CSSTimingData::initialDelay(); + return toCSSPrimitiveValue(value)->computeTime<double, CSSPrimitiveValue::Seconds>(); } -void CSSToStyleMap::mapAnimationDirection(CSSAnimationData* layer, CSSValue* value) const +Timing::PlaybackDirection CSSToStyleMap::mapAnimationDirection(CSSValue* value) { - if (value->isInitialValue()) { - layer->setDirection(CSSAnimationData::initialAnimationDirection()); - return; - } - - if (!value->isPrimitiveValue()) - return; + if (value->isInitialValue()) + return CSSAnimationData::initialDirection(); switch (toCSSPrimitiveValue(value)->getValueID()) { case CSSValueNormal: - layer->setDirection(CSSAnimationData::AnimationDirectionNormal); - break; + return Timing::PlaybackDirectionNormal; case CSSValueAlternate: - layer->setDirection(CSSAnimationData::AnimationDirectionAlternate); - break; + return Timing::PlaybackDirectionAlternate; case CSSValueReverse: - layer->setDirection(CSSAnimationData::AnimationDirectionReverse); - break; + return Timing::PlaybackDirectionReverse; case CSSValueAlternateReverse: - layer->setDirection(CSSAnimationData::AnimationDirectionAlternateReverse); - break; + return Timing::PlaybackDirectionAlternateReverse; default: - break; + ASSERT_NOT_REACHED(); + return CSSAnimationData::initialDirection(); } } -void CSSToStyleMap::mapAnimationDuration(CSSAnimationData* animation, CSSValue* value) const +double CSSToStyleMap::mapAnimationDuration(CSSValue* value) { - if (value->isInitialValue()) { - animation->setDuration(CSSAnimationData::initialAnimationDuration()); - return; - } - - if (!value->isPrimitiveValue()) - return; - - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - animation->setDuration(primitiveValue->computeTime<double, CSSPrimitiveValue::Seconds>()); + if (value->isInitialValue()) + return CSSTimingData::initialDuration(); + return toCSSPrimitiveValue(value)->computeTime<double, CSSPrimitiveValue::Seconds>(); } -void CSSToStyleMap::mapAnimationFillMode(CSSAnimationData* layer, CSSValue* value) const +Timing::FillMode CSSToStyleMap::mapAnimationFillMode(CSSValue* value) { - if (value->isInitialValue()) { - layer->setFillMode(CSSAnimationData::initialAnimationFillMode()); - return; - } - - if (!value->isPrimitiveValue()) - return; + if (value->isInitialValue()) + return CSSAnimationData::initialFillMode(); - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - switch (primitiveValue->getValueID()) { + switch (toCSSPrimitiveValue(value)->getValueID()) { case CSSValueNone: - layer->setFillMode(AnimationFillModeNone); - break; + return Timing::FillModeNone; case CSSValueForwards: - layer->setFillMode(AnimationFillModeForwards); - break; + return Timing::FillModeForwards; case CSSValueBackwards: - layer->setFillMode(AnimationFillModeBackwards); - break; + return Timing::FillModeBackwards; case CSSValueBoth: - layer->setFillMode(AnimationFillModeBoth); - break; + return Timing::FillModeBoth; default: - break; + ASSERT_NOT_REACHED(); + return CSSAnimationData::initialFillMode(); } } -void CSSToStyleMap::mapAnimationIterationCount(CSSAnimationData* animation, CSSValue* value) const +double CSSToStyleMap::mapAnimationIterationCount(CSSValue* value) { - if (value->isInitialValue()) { - animation->setIterationCount(CSSAnimationData::initialAnimationIterationCount()); - return; - } - - if (!value->isPrimitiveValue()) - return; - + if (value->isInitialValue()) + return CSSAnimationData::initialIterationCount(); CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueInfinite) - animation->setIterationCount(CSSAnimationData::IterationCountInfinite); - else - animation->setIterationCount(primitiveValue->getFloatValue()); + return std::numeric_limits<double>::infinity(); + return primitiveValue->getFloatValue(); } -void CSSToStyleMap::mapAnimationName(CSSAnimationData* layer, CSSValue* value) const +AtomicString CSSToStyleMap::mapAnimationName(CSSValue* value) { - if (value->isInitialValue()) { - layer->setName(CSSAnimationData::initialAnimationName()); - return; - } - - if (!value->isPrimitiveValue()) - return; - + if (value->isInitialValue()) + return CSSAnimationData::initialName(); CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueNone) - layer->setIsNoneAnimation(true); - else - layer->setName(AtomicString(primitiveValue->getStringValue())); + return CSSAnimationData::initialName(); + return AtomicString(primitiveValue->getStringValue()); } -void CSSToStyleMap::mapAnimationPlayState(CSSAnimationData* layer, CSSValue* value) const +EAnimPlayState CSSToStyleMap::mapAnimationPlayState(CSSValue* value) { - if (value->isInitialValue()) { - layer->setPlayState(CSSAnimationData::initialAnimationPlayState()); - return; - } - - if (!value->isPrimitiveValue()) - return; - - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - EAnimPlayState playState = (primitiveValue->getValueID() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying; - layer->setPlayState(playState); + if (value->isInitialValue()) + return CSSAnimationData::initialPlayState(); + if (toCSSPrimitiveValue(value)->getValueID() == CSSValuePaused) + return AnimPlayStatePaused; + ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueRunning); + return AnimPlayStatePlaying; } -void CSSToStyleMap::mapAnimationProperty(CSSAnimationData* animation, CSSValue* value) const +CSSTransitionData::TransitionProperty CSSToStyleMap::mapAnimationProperty(CSSValue* value) { - if (value->isInitialValue()) { - animation->setAnimationMode(CSSAnimationData::AnimateAll); - animation->setProperty(CSSPropertyInvalid); - return; - } - - if (!value->isPrimitiveValue()) - return; - + if (value->isInitialValue()) + return CSSTransitionData::initialProperty(); CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (primitiveValue->getValueID() == CSSValueAll) { - animation->setAnimationMode(CSSAnimationData::AnimateAll); - animation->setProperty(CSSPropertyInvalid); - } else if (primitiveValue->getValueID() == CSSValueNone) { - animation->setAnimationMode(CSSAnimationData::AnimateNone); - animation->setProperty(CSSPropertyInvalid); - } else { - animation->setAnimationMode(CSSAnimationData::AnimateSingleProperty); - animation->setProperty(primitiveValue->getPropertyID()); - } + if (primitiveValue->isString()) + return CSSTransitionData::TransitionProperty(primitiveValue->getStringValue()); + if (primitiveValue->getValueID() == CSSValueAll) + return CSSTransitionData::TransitionProperty(CSSTransitionData::TransitionAll); + if (primitiveValue->getValueID() == CSSValueNone) + return CSSTransitionData::TransitionProperty(CSSTransitionData::TransitionNone); + return CSSTransitionData::TransitionProperty(primitiveValue->getPropertyID()); } -void CSSToStyleMap::mapAnimationTimingFunction(CSSAnimationData* animation, CSSValue* value) const +PassRefPtr<TimingFunction> CSSToStyleMap::mapAnimationTimingFunction(CSSValue* value, bool allowStepMiddle) { - if (value->isInitialValue()) { - animation->setTimingFunction(CSSAnimationData::initialAnimationTimingFunction()); - return; - } + // FIXME: We should probably only call into this function with a valid + // single timing function value which isn't initial or inherit. We can + // currently get into here with initial since the parser expands unset + // properties in shorthands to initial. if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); switch (primitiveValue->getValueID()) { case CSSValueLinear: - animation->setTimingFunction(LinearTimingFunction::create()); - break; + return LinearTimingFunction::shared(); case CSSValueEase: - animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease)); - break; + return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease); case CSSValueEaseIn: - animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn)); - break; + return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseIn); case CSSValueEaseOut: - animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut)); - break; + return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseOut); case CSSValueEaseInOut: - animation->setTimingFunction(CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut)); - break; + return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::EaseInOut); case CSSValueStepStart: - animation->setTimingFunction(StepsTimingFunction::preset(StepsTimingFunction::Start)); - break; + return StepsTimingFunction::preset(StepsTimingFunction::Start); + case CSSValueStepMiddle: + if (allowStepMiddle) + return StepsTimingFunction::preset(StepsTimingFunction::Middle); + return CSSTimingData::initialTimingFunction(); case CSSValueStepEnd: - animation->setTimingFunction(StepsTimingFunction::preset(StepsTimingFunction::End)); - break; + return StepsTimingFunction::preset(StepsTimingFunction::End); default: - break; + ASSERT_NOT_REACHED(); + return CSSTimingData::initialTimingFunction(); } - return; } if (value->isCubicBezierTimingFunctionValue()) { CSSCubicBezierTimingFunctionValue* cubicTimingFunction = toCSSCubicBezierTimingFunctionValue(value); - animation->setTimingFunction(CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2())); - } else if (value->isStepsTimingFunctionValue()) { - CSSStepsTimingFunctionValue* stepsTimingFunction = toCSSStepsTimingFunctionValue(value); - animation->setTimingFunction(StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtStart())); + return CubicBezierTimingFunction::create(cubicTimingFunction->x1(), cubicTimingFunction->y1(), cubicTimingFunction->x2(), cubicTimingFunction->y2()); } + + if (value->isInitialValue()) + return CSSTimingData::initialTimingFunction(); + + CSSStepsTimingFunctionValue* stepsTimingFunction = toCSSStepsTimingFunctionValue(value); + if (stepsTimingFunction->stepAtPosition() == StepsTimingFunction::StepAtMiddle && !allowStepMiddle) + return CSSTimingData::initialTimingFunction(); + return StepsTimingFunction::create(stepsTimingFunction->numberOfSteps(), stepsTimingFunction->stepAtPosition()); } void CSSToStyleMap::mapNinePieceImage(RenderStyle* mutableStyle, CSSPropertyID property, CSSValue* value, NinePieceImage& image) @@ -611,16 +544,14 @@ BorderImageLengthBox CSSToStyleMap::mapNinePieceImageQuad(CSSValue* value) const if (!value || !value->isPrimitiveValue()) return BorderImageLengthBox(Length(Auto)); - float zoom = useSVGZoomRules() ? 1.0f : cssToLengthConversionData().zoom(); Quad* slices = toCSSPrimitiveValue(value)->getQuadValue(); // Set up a border image length box to represent our image slices. - const CSSToLengthConversionData& conversionData = cssToLengthConversionData().copyWithAdjustedZoom(zoom); return BorderImageLengthBox( - toBorderImageLength(*slices->top(), conversionData), - toBorderImageLength(*slices->right(), conversionData), - toBorderImageLength(*slices->bottom(), conversionData), - toBorderImageLength(*slices->left(), conversionData)); + toBorderImageLength(*slices->top(), cssToLengthConversionData()), + toBorderImageLength(*slices->right(), cssToLengthConversionData()), + toBorderImageLength(*slices->bottom(), cssToLengthConversionData()), + toBorderImageLength(*slices->left(), cssToLengthConversionData())); } void CSSToStyleMap::mapNinePieceImageRepeat(CSSValue* value, NinePieceImage& image) const diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.h b/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.h index b994b6f0a78..e539064f8ba 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/CSSToStyleMap.h @@ -22,14 +22,17 @@ #ifndef CSSToStyleMap_h #define CSSToStyleMap_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" +#include "core/animation/Timing.h" +#include "core/animation/css/CSSTransitionData.h" #include "core/css/resolver/ElementStyleResources.h" +#include "core/rendering/style/RenderStyleConstants.h" +#include "platform/animation/TimingFunction.h" #include "wtf/Noncopyable.h" namespace WebCore { class FillLayer; -class CSSAnimationData; class CSSToLengthConversionData; class CSSValue; class RenderStyle; @@ -43,10 +46,10 @@ class BorderImageLengthBox; // CSSValue objects into their RenderStyle equivalents. class CSSToStyleMap { + STACK_ALLOCATED(); WTF_MAKE_NONCOPYABLE(CSSToStyleMap); public: CSSToStyleMap(const StyleResolverState& state, ElementStyleResources& elementStyleResources) : m_state(state), m_elementStyleResources(elementStyleResources) { } - void mapFillAttachment(CSSPropertyID, FillLayer*, CSSValue*) const; void mapFillClip(CSSPropertyID, FillLayer*, CSSValue*) const; void mapFillComposite(CSSPropertyID, FillLayer*, CSSValue*) const; @@ -60,15 +63,15 @@ public: void mapFillYPosition(CSSPropertyID, FillLayer*, CSSValue*) const; void mapFillMaskSourceType(CSSPropertyID, FillLayer*, CSSValue*); - void mapAnimationDelay(CSSAnimationData*, CSSValue*) const; - void mapAnimationDirection(CSSAnimationData*, CSSValue*) const; - void mapAnimationDuration(CSSAnimationData*, CSSValue*) const; - void mapAnimationFillMode(CSSAnimationData*, CSSValue*) const; - void mapAnimationIterationCount(CSSAnimationData*, CSSValue*) const; - void mapAnimationName(CSSAnimationData*, CSSValue*) const; - void mapAnimationPlayState(CSSAnimationData*, CSSValue*) const; - void mapAnimationProperty(CSSAnimationData*, CSSValue*) const; - void mapAnimationTimingFunction(CSSAnimationData*, CSSValue*) const; + static double mapAnimationDelay(CSSValue*); + static Timing::PlaybackDirection mapAnimationDirection(CSSValue*); + static double mapAnimationDuration(CSSValue*); + static Timing::FillMode mapAnimationFillMode(CSSValue*); + static double mapAnimationIterationCount(CSSValue*); + static AtomicString mapAnimationName(CSSValue*); + static EAnimPlayState mapAnimationPlayState(CSSValue*); + static CSSTransitionData::TransitionProperty mapAnimationProperty(CSSValue*); + static PassRefPtr<TimingFunction> mapAnimationTimingFunction(CSSValue*, bool allowStepMiddle = false); void mapNinePieceImage(RenderStyle* mutableStyle, CSSPropertyID, CSSValue*, NinePieceImage&); void mapNinePieceImageSlice(CSSValue*, NinePieceImage&) const; @@ -77,7 +80,6 @@ public: private: const CSSToLengthConversionData& cssToLengthConversionData() const; - bool useSVGZoomRules() const; PassRefPtr<StyleImage> styleImage(CSSPropertyID, CSSValue*); diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp index 75a1ab10f17..9d952b4363e 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.cpp @@ -33,12 +33,10 @@ ElementResolveContext::ElementResolveContext(Element& element) : m_element(&element) , m_elementLinkState(element.document().visitedLinkState().determineLinkState(element)) , m_distributedToInsertionPoint(false) - , m_resetStyleInheritance(false) { NodeRenderingTraversal::ParentDetails parentDetails; m_parentNode = NodeRenderingTraversal::parent(&element, &parentDetails); m_distributedToInsertionPoint = parentDetails.insertionPoint(); - m_resetStyleInheritance = parentDetails.resetStyleInheritance(); const Document& document = element.document(); Node* documentElement = document.documentElement(); diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.h b/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.h index f255e897425..f6c77bdbfc9 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ElementResolveContext.h @@ -34,14 +34,14 @@ class RenderStyle; // ElementResolveContext is immutable and serves as an input to the style resolve process. class ElementResolveContext { + STACK_ALLOCATED(); public: ElementResolveContext() - : m_element(0) - , m_parentNode(0) + : m_element(nullptr) + , m_parentNode(nullptr) , m_rootElementStyle(0) , m_elementLinkState(NotInsideLink) , m_distributedToInsertionPoint(false) - , m_resetStyleInheritance(false) { } @@ -52,15 +52,13 @@ public: const RenderStyle* rootElementStyle() const { return m_rootElementStyle; } EInsideLink elementLinkState() const { return m_elementLinkState; } bool distributedToInsertionPoint() const { return m_distributedToInsertionPoint; } - bool resetStyleInheritance() const { return m_resetStyleInheritance; } private: - Element* m_element; - ContainerNode* m_parentNode; + RawPtrWillBeMember<Element> m_element; + RawPtrWillBeMember<ContainerNode> m_parentNode; RenderStyle* m_rootElementStyle; EInsideLink m_elementLinkState; bool m_distributedToInsertionPoint; - bool m_resetStyleInheritance; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp index d8b081743c9..60643ae2a8e 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.cpp @@ -33,15 +33,14 @@ namespace WebCore { ElementStyleResources::ElementStyleResources() - : m_hasNewCustomFilterProgram(false) - , m_deviceScaleFactor(1) + : m_deviceScaleFactor(1) { } -PassRefPtr<StyleImage> ElementStyleResources::styleImage(const TextLinkColors& textLinkColors, Color currentColor, CSSPropertyID property, CSSValue* value) +PassRefPtr<StyleImage> ElementStyleResources::styleImage(Document& document, const TextLinkColors& textLinkColors, Color currentColor, CSSPropertyID property, CSSValue* value) { if (value->isImageValue()) - return cachedOrPendingFromValue(property, toCSSImageValue(value)); + return cachedOrPendingFromValue(document, property, toCSSImageValue(value)); if (value->isImageGeneratorValue()) { if (value->isGradientValue()) @@ -55,7 +54,7 @@ PassRefPtr<StyleImage> ElementStyleResources::styleImage(const TextLinkColors& t if (value->isCursorImageValue()) return cursorOrPendingFromValue(property, toCSSCursorImageValue(value)); - return 0; + return nullptr; } PassRefPtr<StyleImage> ElementStyleResources::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue* value) @@ -75,11 +74,15 @@ PassRefPtr<StyleImage> ElementStyleResources::setOrPendingFromValue(CSSPropertyI return image.release(); } -PassRefPtr<StyleImage> ElementStyleResources::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value) +PassRefPtr<StyleImage> ElementStyleResources::cachedOrPendingFromValue(Document& document, CSSPropertyID property, CSSImageValue* value) { RefPtr<StyleImage> image = value->cachedOrPendingImage(); - if (image && image->isPendingImage()) - m_pendingImageProperties.set(property, value); + if (image) { + if (image->isPendingImage()) + m_pendingImageProperties.set(property, value); + else + value->restoreCachedResourceIfNeeded(document); + } return image.release(); } @@ -91,6 +94,16 @@ PassRefPtr<StyleImage> ElementStyleResources::cursorOrPendingFromValue(CSSProper return image.release(); } +void ElementStyleResources::clearPendingImageProperties() +{ + m_pendingImageProperties.clear(); +} + +void ElementStyleResources::clearPendingSVGDocuments() +{ + m_pendingSVGDocuments.clear(); +} + void ElementStyleResources::addPendingSVGDocument(FilterOperation* filterOperation, CSSSVGDocumentValue* cssSVGDocumentValue) { m_pendingSVGDocuments.set(filterOperation, cssSVGDocumentValue); diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h b/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h index 354b022fe28..5d86c7d50f8 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ElementStyleResources.h @@ -23,8 +23,9 @@ #ifndef ElementStyleResources_h #define ElementStyleResources_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "platform/graphics/Color.h" +#include "platform/heap/Handle.h" #include "wtf/HashMap.h" #include "wtf/Noncopyable.h" @@ -40,28 +41,29 @@ class FilterOperation; class StyleImage; class TextLinkColors; -typedef HashMap<FilterOperation*, RefPtr<CSSSVGDocumentValue> > PendingSVGDocumentMap; -typedef HashMap<CSSPropertyID, RefPtr<CSSValue> > PendingImagePropertyMap; +typedef WillBeHeapHashMap<FilterOperation*, RefPtrWillBeMember<CSSSVGDocumentValue> > PendingSVGDocumentMap; +typedef WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<CSSValue> > PendingImagePropertyMap; // Holds information about resources, requested by stylesheets. // Lifetime: per-element style resolve. class ElementStyleResources { +STACK_ALLOCATED(); WTF_MAKE_NONCOPYABLE(ElementStyleResources); public: ElementStyleResources(); - PassRefPtr<StyleImage> styleImage(const TextLinkColors&, Color currentColor, CSSPropertyID, CSSValue*); + PassRefPtr<StyleImage> styleImage(Document&, const TextLinkColors&, Color currentColor, CSSPropertyID, CSSValue*); PassRefPtr<StyleImage> generatedOrPendingFromValue(CSSPropertyID, CSSImageGeneratorValue*); - PassRefPtr<StyleImage> cachedOrPendingFromValue(CSSPropertyID, CSSImageValue*); + PassRefPtr<StyleImage> cachedOrPendingFromValue(Document&, CSSPropertyID, CSSImageValue*); PassRefPtr<StyleImage> setOrPendingFromValue(CSSPropertyID, CSSImageSetValue*); PassRefPtr<StyleImage> cursorOrPendingFromValue(CSSPropertyID, CSSCursorImageValue*); const PendingImagePropertyMap& pendingImageProperties() const { return m_pendingImageProperties; } const PendingSVGDocumentMap& pendingSVGDocuments() const { return m_pendingSVGDocuments; } - void setHasNewCustomFilterProgram(bool hasNewCustomFilterProgram) { m_hasNewCustomFilterProgram = hasNewCustomFilterProgram; } - bool hasNewCustomFilterProgram() const { return m_hasNewCustomFilterProgram; } + void clearPendingImageProperties(); + void clearPendingSVGDocuments(); float deviceScaleFactor() const { return m_deviceScaleFactor; } void setDeviceScaleFactor(float deviceScaleFactor) { m_deviceScaleFactor = deviceScaleFactor; } @@ -71,7 +73,6 @@ public: private: PendingImagePropertyMap m_pendingImageProperties; PendingSVGDocumentMap m_pendingSVGDocuments; - bool m_hasNewCustomFilterProgram; float m_deviceScaleFactor; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp index 37706e6818d..fdb2e957ab4 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.cpp @@ -30,23 +30,12 @@ #include "core/css/resolver/FilterOperationResolver.h" #include "core/css/CSSFilterValue.h" -#include "core/css/CSSMixFunctionValue.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSPrimitiveValueMappings.h" -#include "core/css/CSSShaderValue.h" #include "core/css/CSSShadowValue.h" #include "core/css/resolver/TransformBuilder.h" -#include "core/rendering/style/StyleCustomFilterProgram.h" -#include "core/rendering/style/StyleShader.h" #include "core/rendering/svg/ReferenceFilterBuilder.h" #include "core/svg/SVGURIReference.h" -#include "platform/graphics/filters/custom/CustomFilterArrayParameter.h" -#include "platform/graphics/filters/custom/CustomFilterConstants.h" -#include "platform/graphics/filters/custom/CustomFilterNumberParameter.h" -#include "platform/graphics/filters/custom/CustomFilterOperation.h" -#include "platform/graphics/filters/custom/CustomFilterParameter.h" -#include "platform/graphics/filters/custom/CustomFilterProgramInfo.h" -#include "platform/graphics/filters/custom/CustomFilterTransformParameter.h" namespace WebCore { @@ -75,277 +64,12 @@ static FilterOperation::OperationType filterOperationForType(CSSFilterValue::Fil return FilterOperation::BLUR; case CSSFilterValue::DropShadowFilterOperation: return FilterOperation::DROP_SHADOW; - case CSSFilterValue::CustomFilterOperation: - return FilterOperation::CUSTOM; case CSSFilterValue::UnknownFilterOperation: return FilterOperation::NONE; } return FilterOperation::NONE; } -static StyleShader* styleShader(CSSValue* value) -{ - if (value->isShaderValue()) - return toCSSShaderValue(value)->cachedOrPendingShader(); - return 0; -} - -static PassRefPtr<CustomFilterParameter> parseCustomFilterArrayParameter(const String& name, CSSValueList* values) -{ - RefPtr<CustomFilterArrayParameter> arrayParameter = CustomFilterArrayParameter::create(name); - for (unsigned i = 0, length = values->length(); i < length; ++i) { - CSSValue* value = values->itemWithoutBoundsCheck(i); - if (!value->isPrimitiveValue()) - return 0; - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) - return 0; - arrayParameter->addValue(primitiveValue->getDoubleValue()); - } - return arrayParameter.release(); -} - -static PassRefPtr<CustomFilterParameter> parseCustomFilterNumberParameter(const String& name, CSSValueList* values) -{ - RefPtr<CustomFilterNumberParameter> numberParameter = CustomFilterNumberParameter::create(name); - for (unsigned i = 0; i < values->length(); ++i) { - CSSValue* value = values->itemWithoutBoundsCheck(i); - if (!value->isPrimitiveValue()) - return 0; - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) - return 0; - numberParameter->addValue(primitiveValue->getDoubleValue()); - } - return numberParameter.release(); -} - -static PassRefPtr<CustomFilterParameter> parseCustomFilterTransformParameter(const String& name, CSSValueList* values, StyleResolverState& state) -{ - RefPtr<CustomFilterTransformParameter> transformParameter = CustomFilterTransformParameter::create(name); - TransformOperations operations; - TransformBuilder::createTransformOperations(values, state.cssToLengthConversionData(), operations); - transformParameter->setOperations(operations); - return transformParameter.release(); -} - -static PassRefPtr<CustomFilterParameter> parseCustomFilterParameter(const String& name, CSSValue* parameterValue, StyleResolverState& state) -{ - // FIXME: Implement other parameters types parsing. - // booleans: https://bugs.webkit.org/show_bug.cgi?id=76438 - // textures: https://bugs.webkit.org/show_bug.cgi?id=71442 - // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444 - // Number parameters are wrapped inside a CSSValueList and all - // the other functions values inherit from CSSValueList. - if (!parameterValue->isValueList()) - return 0; - - CSSValueList* values = toCSSValueList(parameterValue); - if (!values->length()) - return 0; - - if (parameterValue->isArrayFunctionValue()) - return parseCustomFilterArrayParameter(name, values); - - // If the first value of the list is a transform function, - // then we could safely assume that all the remaining items - // are transforms. parseCustomFilterTransformParameter will - // return 0 if that assumption is incorrect. - if (values->itemWithoutBoundsCheck(0)->isTransformValue()) - return parseCustomFilterTransformParameter(name, values, state); - - // We can have only arrays of booleans or numbers, so use the first value to choose between those two. - // We need up to 4 values (all booleans or all numbers). - if (!values->itemWithoutBoundsCheck(0)->isPrimitiveValue() || values->length() > 4) - return 0; - - CSSPrimitiveValue* firstPrimitiveValue = toCSSPrimitiveValue(values->itemWithoutBoundsCheck(0)); - if (firstPrimitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) - return parseCustomFilterNumberParameter(name, values); - - // FIXME: Implement the boolean array parameter here. - // https://bugs.webkit.org/show_bug.cgi?id=76438 - - return 0; -} - -static bool parseCustomFilterParameterList(CSSValue* parametersValue, CustomFilterParameterList& parameterList, StyleResolverState& state) -{ - HashSet<String> knownParameterNames; - CSSValueListIterator parameterIterator(parametersValue); - for (; parameterIterator.hasMore(); parameterIterator.advance()) { - if (!parameterIterator.value()->isValueList()) - return false; - CSSValueListIterator iterator(parameterIterator.value()); - if (!iterator.isPrimitiveValue()) - return false; - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value()); - if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_STRING) - return false; - - String name = primitiveValue->getStringValue(); - // Do not allow duplicate parameter names. - if (!knownParameterNames.add(name).isNewEntry) - return false; - - iterator.advance(); - - if (!iterator.hasMore()) - return false; - - RefPtr<CustomFilterParameter> parameter = parseCustomFilterParameter(name, iterator.value(), state); - if (!parameter) - return false; - parameterList.append(parameter.release()); - } - - // Make sure we sort the parameters before passing them down to the CustomFilterOperation. - parameterList.sortParametersByName(); - - return true; -} - -static PassRefPtr<CustomFilterOperation> createCustomFilterOperationWithAtRuleReferenceSyntax(CSSFilterValue*) -{ - // FIXME: Implement style resolution for the custom filter at-rule reference syntax. - return 0; -} - -static PassRefPtr<CustomFilterProgram> createCustomFilterProgram(CSSShaderValue* vertexShader, CSSShaderValue* fragmentShader, - CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType, - StyleResolverState& state) -{ - ResourceFetcher* fetcher = state.document().fetcher(); - KURL vertexShaderURL = vertexShader ? vertexShader->completeURL(fetcher) : KURL(); - KURL fragmentShaderURL = fragmentShader ? fragmentShader->completeURL(fetcher) : KURL(); - // We re-resolve the custom filter style after the shaders are loaded. - // We always create a StyleCustomFilterProgram here, and later replace it with a program from the StyleCustomFilterProgramCache, if available. - StyleShader* styleVertexShader = vertexShader ? styleShader(vertexShader) : 0; - StyleShader* styleFragmentShader = fragmentShader ? styleShader(fragmentShader) : 0; - RefPtr<StyleCustomFilterProgram> program = StyleCustomFilterProgram::create(vertexShaderURL, styleVertexShader, - fragmentShaderURL, styleFragmentShader, programType, mixSettings, meshType); - state.elementStyleResources().setHasNewCustomFilterProgram(true); - return program.release(); -} - -static PassRefPtr<CustomFilterOperation> createCustomFilterOperationWithInlineSyntax(CSSFilterValue* filterValue, StyleResolverState& state) -{ - CSSValue* shadersValue = filterValue->itemWithoutBoundsCheck(0); - ASSERT_WITH_SECURITY_IMPLICATION(shadersValue->isValueList()); - CSSValueList* shadersList = toCSSValueList(shadersValue); - - unsigned shadersListLength = shadersList->length(); - ASSERT(shadersListLength); - - CSSShaderValue* vertexShader = 0; - CSSShaderValue* fragmentShader = 0; - - if (shadersList->itemWithoutBoundsCheck(0)->isShaderValue()) - vertexShader = toCSSShaderValue(shadersList->itemWithoutBoundsCheck(0)); - - CustomFilterProgramType programType = ProgramTypeBlendsElementTexture; - CustomFilterProgramMixSettings mixSettings; - - if (shadersListLength > 1) { - CSSValue* fragmentShaderOrMixFunction = shadersList->itemWithoutBoundsCheck(1); - if (fragmentShaderOrMixFunction->isMixFunctionValue()) { - CSSMixFunctionValue* mixFunction = toCSSMixFunctionValue(fragmentShaderOrMixFunction); - CSSValueListIterator iterator(mixFunction); - - ASSERT(mixFunction->length()); - if (iterator.value()->isShaderValue()) - fragmentShader = toCSSShaderValue(iterator.value()); - - iterator.advance(); - - ASSERT(mixFunction->length() <= 3); - while (iterator.hasMore()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value()); - if (CSSParser::isBlendMode(primitiveValue->getValueID())) - mixSettings.blendMode = *primitiveValue; - else if (CSSParser::isCompositeOperator(primitiveValue->getValueID())) - mixSettings.compositeOperator = *primitiveValue; - else - ASSERT_NOT_REACHED(); - iterator.advance(); - } - } else { - programType = ProgramTypeNoElementTexture; - if (fragmentShaderOrMixFunction->isShaderValue()) - fragmentShader = toCSSShaderValue(fragmentShaderOrMixFunction); - } - } - - if (!vertexShader && !fragmentShader) - return 0; - - unsigned meshRows = 1; - unsigned meshColumns = 1; - CustomFilterMeshType meshType = MeshTypeAttached; - - CSSValue* parametersValue = 0; - - if (filterValue->length() > 1) { - CSSValueListIterator iterator(filterValue->itemWithoutBoundsCheck(1)); - - // The second value might be the mesh box or the list of parameters: - // If it starts with a number or any of the mesh-box identifiers it is - // the mesh-box list, if not it means it is the parameters list. - - if (iterator.hasMore() && iterator.isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value()); - if (primitiveValue->isNumber()) { - // If only one integer value is specified, it will set both - // the rows and the columns. - meshColumns = meshRows = primitiveValue->getIntValue(); - iterator.advance(); - - // Try to match another number for the rows. - if (iterator.hasMore() && iterator.isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value()); - if (primitiveValue->isNumber()) { - meshRows = primitiveValue->getIntValue(); - iterator.advance(); - } - } - } - } - - if (iterator.hasMore() && iterator.isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value()); - if (primitiveValue->getValueID() == CSSValueDetached) { - meshType = MeshTypeDetached; - iterator.advance(); - } - } - - if (!iterator.index()) { - // If no value was consumed from the mesh value, then it is just a parameter list, meaning that we end up - // having just two CSSListValues: list of shaders and list of parameters. - ASSERT(filterValue->length() == 2); - parametersValue = filterValue->itemWithoutBoundsCheck(1); - } - } - - if (filterValue->length() > 2 && !parametersValue) - parametersValue = filterValue->itemWithoutBoundsCheck(2); - - CustomFilterParameterList parameterList; - if (parametersValue && !parseCustomFilterParameterList(parametersValue, parameterList, state)) - return 0; - - RefPtr<CustomFilterProgram> program = createCustomFilterProgram(vertexShader, fragmentShader, programType, mixSettings, meshType, state); - return CustomFilterOperation::create(program.release(), parameterList, meshRows, meshColumns, meshType); -} - -static PassRefPtr<CustomFilterOperation> createCustomFilterOperation(CSSFilterValue* filterValue, StyleResolverState& state) -{ - ASSERT(filterValue->length()); - bool isAtRuleReferenceSyntax = filterValue->itemWithoutBoundsCheck(0)->isPrimitiveValue(); - return isAtRuleReferenceSyntax ? createCustomFilterOperationWithAtRuleReferenceSyntax(filterValue) : createCustomFilterOperationWithInlineSyntax(filterValue, state); -} - - bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CSSToLengthConversionData& unadjustedConversionData, FilterOperations& outOperations, StyleResolverState& state) { ASSERT(outOperations.isEmpty()); @@ -362,7 +86,11 @@ bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CS if (!inValue->isValueList()) return false; +#ifdef BLINK_SCALE_FILTERS_AT_RECORD_TIME float zoomFactor = unadjustedConversionData.zoom() * state.elementStyleResources().deviceScaleFactor(); +#else + float zoomFactor = unadjustedConversionData.zoom(); +#endif const CSSToLengthConversionData& conversionData = unadjustedConversionData.copyWithAdjustedZoom(zoomFactor); FilterOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { @@ -373,19 +101,6 @@ bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CS CSSFilterValue* filterValue = toCSSFilterValue(i.value()); FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType()); - if (operationType == FilterOperation::VALIDATED_CUSTOM) { - // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle. - ASSERT_NOT_REACHED(); - continue; - } - if (operationType == FilterOperation::CUSTOM) { - RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue, state); - if (!operation) - return false; - - operations.operations().append(operation); - continue; - } if (operationType == FilterOperation::REFERENCE) { if (filterValue->length() != 1) continue; @@ -397,7 +112,7 @@ bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CS CSSSVGDocumentValue* svgDocumentValue = toCSSSVGDocumentValue(argument); KURL url = state.document().completeURL(svgDocumentValue->url()); - RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), url.fragmentIdentifier()); + RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), AtomicString(url.fragmentIdentifier())); if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), state.document())) { if (!svgDocumentValue->loadRequested()) state.elementStyleResources().addPendingSVGDocument(operation.get(), svgDocumentValue); @@ -463,9 +178,6 @@ bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CS Length stdDeviation = Length(0, Fixed); if (filterValue->length() >= 1) stdDeviation = firstValue->convertToLength<FixedConversion | PercentConversion>(conversionData); - if (stdDeviation.isUndefined()) - return false; - operations.operations().append(BlurFilterOperation::create(stdDeviation)); break; } @@ -480,11 +192,11 @@ bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CS CSSShadowValue* item = toCSSShadowValue(cssValue); IntPoint location(item->x->computeLength<int>(conversionData), item->y->computeLength<int>(conversionData)); int blur = item->blur ? item->blur->computeLength<int>(conversionData) : 0; - Color shadowColor; + Color shadowColor = Color::transparent; if (item->color) shadowColor = state.document().textLinkColors().colorFromPrimitiveValue(item->color.get(), state.style()->color()); - operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor.isValid() ? shadowColor : Color::transparent)); + operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor)); break; } case CSSFilterValue::UnknownFilterOperation: diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.h b/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.h index 4475ce31d63..494e0d98612 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/FilterOperationResolver.h @@ -24,6 +24,7 @@ #include "core/css/resolver/StyleResolverState.h" #include "platform/graphics/filters/FilterOperations.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -31,8 +32,7 @@ class CSSToLengthConversionData; class CSSValue; class FilterOperationResolver { -private: - FilterOperationResolver(); + STATIC_ONLY(FilterOperationResolver); public: static bool createFilterOperations(CSSValue* inValue, const CSSToLengthConversionData&, FilterOperations& outOperations, StyleResolverState&); }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp index 57eba497510..9de7131f88c 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.cpp @@ -27,10 +27,11 @@ #include "core/css/CSSFontFeatureValue.h" #include "core/css/CSSToLengthConversionData.h" #include "core/css/FontSize.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "core/rendering/RenderTheme.h" #include "core/rendering/RenderView.h" +#include "platform/fonts/FontDescription.h" #include "platform/text/LocaleToScriptMapping.h" namespace WebCore { @@ -61,23 +62,35 @@ private: FontBuilder::FontBuilder() : m_document(0) - , m_useSVGZoomRules(false) + , m_fontSizehasViewportUnits(false) + , m_style(0) , m_fontDirty(false) { } -void FontBuilder::initForStyleResolve(const Document& document, RenderStyle* style, bool useSVGZoomRules) +void FontBuilder::initForStyleResolve(const Document& document, RenderStyle* style) { - // All documents need to be in a frame (and thus have access to Settings) - // for style-resolution to make sense. - // Unfortunately SVG Animations currently violate this: crbug.com/260966 - // ASSERT(m_document->frame()); + ASSERT(document.frame()); m_document = &document; - m_useSVGZoomRules = useSVGZoomRules; m_style = style; m_fontDirty = false; } +inline static void setFontFamilyToStandard(FontDescription& fontDescription, const Document* document) +{ + if (!document || !document->settings()) + return; + + fontDescription.setGenericFamily(FontDescription::StandardFamily); + const AtomicString& standardFontFamily = document->settings()->genericFontFamilySettings().standard(); + if (standardFontFamily.isEmpty()) + return; + + fontDescription.firstFamily().setFamily(standardFontFamily); + // FIXME: Why is this needed here? + fontDescription.firstFamily().appendFamily(nullptr); +} + void FontBuilder::setInitial(float effectiveZoom) { ASSERT(m_document && m_document->settings()); @@ -87,13 +100,7 @@ void FontBuilder::setInitial(float effectiveZoom) FontDescriptionChangeScope scope(this); scope.reset(); - scope.fontDescription().setGenericFamily(FontDescription::StandardFamily); - scope.fontDescription().setUsePrinterFont(m_document->printing()); - const AtomicString& standardFontFamily = m_document->settings()->genericFontFamilySettings().standard(); - if (!standardFontFamily.isEmpty()) { - scope.fontDescription().firstFamily().setFamily(standardFontFamily); - scope.fontDescription().firstFamily().appendFamily(0); - } + setFontFamilyToStandard(scope.fontDescription(), m_document); scope.fontDescription().setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); setSize(scope.fontDescription(), effectiveZoom, FontSize::fontSizeForKeyword(m_document, CSSValueMedium, false)); } @@ -126,25 +133,17 @@ void FontBuilder::fromSystemFont(CSSValueID valueId, float effectiveZoom) ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings if (!settings) return; - fontDescription.setUsePrinterFont(m_document->printing()); // Handle the zoom factor. fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, effectiveZoom, fontDescription.specifiedSize())); scope.set(fontDescription); } -void FontBuilder::setFontFamilyInitial(float effectiveZoom) +void FontBuilder::setFontFamilyInitial() { FontDescriptionChangeScope scope(this); - FontDescription initialDesc = FontDescription(); - - // We need to adjust the size to account for the generic family change from monospace to non-monospace. - if (scope.fontDescription().keywordSize() && scope.fontDescription().useFixedDefaultSize()) - setSize(scope.fontDescription(), effectiveZoom, FontSize::fontSizeForKeyword(m_document, CSSValueXxSmall + scope.fontDescription().keywordSize() - 1, false)); - scope.fontDescription().setGenericFamily(initialDesc.genericFamily()); - if (!initialDesc.firstFamily().familyIsEmpty()) - scope.fontDescription().setFamily(initialDesc.firstFamily()); + setFontFamilyToStandard(scope.fontDescription(), m_document); } void FontBuilder::setFontFamilyInherit(const FontDescription& parentFontDescription) @@ -153,11 +152,10 @@ void FontBuilder::setFontFamilyInherit(const FontDescription& parentFontDescript scope.fontDescription().setGenericFamily(parentFontDescription.genericFamily()); scope.fontDescription().setFamily(parentFontDescription.family()); - scope.fontDescription().setIsSpecifiedFont(parentFontDescription.isSpecifiedFont()); } // FIXME: I am not convinced FontBuilder needs to know anything about CSSValues. -void FontBuilder::setFontFamilyValue(CSSValue* value, float effectiveZoom) +void FontBuilder::setFontFamilyValue(CSSValue* value) { FontDescriptionChangeScope scope(this); @@ -218,9 +216,8 @@ void FontBuilder::setFontFamilyValue(CSSValue* value, float effectiveZoom) if (!currFamily) { // Filling in the first family. firstFamily.setFamily(face); - firstFamily.appendFamily(0); // Remove any inherited family-fallback list. + firstFamily.appendFamily(nullptr); // Remove any inherited family-fallback list. currFamily = &firstFamily; - scope.fontDescription().setIsSpecifiedFont(scope.fontDescription().genericFamily() == FontDescription::NoFamily); } else { RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create(); newFamily->setFamily(face); @@ -236,10 +233,10 @@ void FontBuilder::setFontFamilyValue(CSSValue* value, float effectiveZoom) return; if (scope.fontDescription().keywordSize() && scope.fontDescription().useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize) - setSize(scope.fontDescription(), effectiveZoom, FontSize::fontSizeForKeyword(m_document, CSSValueXxSmall + scope.fontDescription().keywordSize() - 1, !oldFamilyUsedFixedDefaultSize)); + scope.fontDescription().setSpecifiedSize(FontSize::fontSizeForKeyword(m_document, CSSValueXxSmall + scope.fontDescription().keywordSize() - 1, !oldFamilyUsedFixedDefaultSize)); } -void FontBuilder::setFontSizeInitial(float effectiveZoom) +void FontBuilder::setFontSizeInitial() { FontDescriptionChangeScope scope(this); @@ -249,10 +246,10 @@ void FontBuilder::setFontSizeInitial(float effectiveZoom) return; scope.fontDescription().setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); - setSize(scope.fontDescription(), effectiveZoom, size); + scope.fontDescription().setSpecifiedSize(size); } -void FontBuilder::setFontSizeInherit(const FontDescription& parentFontDescription, float effectiveZoom) +void FontBuilder::setFontSizeInherit(const FontDescription& parentFontDescription) { FontDescriptionChangeScope scope(this); @@ -262,7 +259,7 @@ void FontBuilder::setFontSizeInherit(const FontDescription& parentFontDescriptio return; scope.fontDescription().setKeywordSize(parentFontDescription.keywordSize()); - setSize(scope.fontDescription(), effectiveZoom, size); + scope.fontDescription().setSpecifiedSize(size); } // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) @@ -278,7 +275,7 @@ static float smallerFontSize(float size) } // FIXME: Have to pass RenderStyles here for calc/computed values. This shouldn't be neecessary. -void FontBuilder::setFontSizeValue(CSSValue* value, RenderStyle* parentStyle, const RenderStyle* rootElementStyle, float effectiveZoom) +void FontBuilder::setFontSizeValue(CSSValue* value, RenderStyle* parentStyle, const RenderStyle* rootElementStyle) { if (!value->isPrimitiveValue()) return; @@ -324,16 +321,22 @@ void FontBuilder::setFontSizeValue(CSSValue* value, RenderStyle* parentStyle, co scope.fontDescription().setIsAbsoluteSize(parentIsAbsoluteSize && (valueID == CSSValueLarger || valueID == CSSValueSmaller)); } else { scope.fontDescription().setIsAbsoluteSize(parentIsAbsoluteSize || !(primitiveValue->isPercentage() || primitiveValue->isFontRelativeLength())); - if (primitiveValue->isLength()) - size = primitiveValue->computeLength<float>(CSSToLengthConversionData(parentStyle, rootElementStyle, 1.0, true)); - else if (primitiveValue->isPercentage()) + if (primitiveValue->isPercentage()) { size = (primitiveValue->getFloatValue() * parentSize) / 100.0f; - else if (primitiveValue->isCalculatedPercentageWithLength()) - size = primitiveValue->cssCalcValue()->toCalcValue(CSSToLengthConversionData(parentStyle, rootElementStyle, 1.0f))->evaluate(parentSize); - else if (primitiveValue->isViewportPercentageLength()) - size = valueForLength(primitiveValue->viewportPercentageLength(), 0, m_document->renderView()); - else - return; + } else { + // If we have viewport units the conversion will mark the parent style as having viewport units. + bool parentHasViewportUnits = parentStyle->hasViewportUnits(); + parentStyle->setHasViewportUnits(false); + CSSToLengthConversionData conversionData(parentStyle, rootElementStyle, m_document->renderView(), 1.0f, true); + if (primitiveValue->isLength()) + size = primitiveValue->computeLength<float>(conversionData); + else if (primitiveValue->isCalculatedPercentageWithLength()) + size = primitiveValue->cssCalcValue()->toCalcValue(conversionData)->evaluate(parentSize); + else + ASSERT_NOT_REACHED(); + m_fontSizehasViewportUnits = parentStyle->hasViewportUnits(); + parentStyle->setHasViewportUnits(parentHasViewportUnits); + } } if (size < 0) @@ -343,7 +346,8 @@ void FontBuilder::setFontSizeValue(CSSValue* value, RenderStyle* parentStyle, co // Cap font size here to make sure that doesn't happen. size = std::min(maximumAllowedFontSize, size); - setSize(scope.fontDescription(), effectiveZoom, size); + + scope.fontDescription().setSpecifiedSize(size); } void FontBuilder::setWeight(FontWeight fontWeight) @@ -374,6 +378,7 @@ void FontBuilder::setFontVariantLigaturesInitial() scope.fontDescription().setCommonLigaturesState(FontDescription::NormalLigaturesState); scope.fontDescription().setDiscretionaryLigaturesState(FontDescription::NormalLigaturesState); scope.fontDescription().setHistoricalLigaturesState(FontDescription::NormalLigaturesState); + scope.fontDescription().setContextualLigaturesState(FontDescription::NormalLigaturesState); } void FontBuilder::setFontVariantLigaturesInherit(const FontDescription& parentFontDescription) @@ -383,6 +388,7 @@ void FontBuilder::setFontVariantLigaturesInherit(const FontDescription& parentFo scope.fontDescription().setCommonLigaturesState(parentFontDescription.commonLigaturesState()); scope.fontDescription().setDiscretionaryLigaturesState(parentFontDescription.discretionaryLigaturesState()); scope.fontDescription().setHistoricalLigaturesState(parentFontDescription.historicalLigaturesState()); + scope.fontDescription().setContextualLigaturesState(parentFontDescription.historicalLigaturesState()); } void FontBuilder::setFontVariantLigaturesValue(CSSValue* value) @@ -392,6 +398,7 @@ void FontBuilder::setFontVariantLigaturesValue(CSSValue* value) FontDescription::LigaturesState commonLigaturesState = FontDescription::NormalLigaturesState; FontDescription::LigaturesState discretionaryLigaturesState = FontDescription::NormalLigaturesState; FontDescription::LigaturesState historicalLigaturesState = FontDescription::NormalLigaturesState; + FontDescription::LigaturesState contextualLigaturesState = FontDescription::NormalLigaturesState; if (value->isValueList()) { CSSValueList* valueList = toCSSValueList(value); @@ -419,6 +426,12 @@ void FontBuilder::setFontVariantLigaturesValue(CSSValue* value) case CSSValueHistoricalLigatures: historicalLigaturesState = FontDescription::EnabledLigaturesState; break; + case CSSValueNoContextual: + contextualLigaturesState = FontDescription::DisabledLigaturesState; + break; + case CSSValueContextual: + contextualLigaturesState = FontDescription::EnabledLigaturesState; + break; default: ASSERT_NOT_REACHED(); break; @@ -426,7 +439,7 @@ void FontBuilder::setFontVariantLigaturesValue(CSSValue* value) } } } -#if !ASSERT_DISABLED +#if ASSERT_ENABLED else { ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue()); ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal); @@ -436,34 +449,36 @@ void FontBuilder::setFontVariantLigaturesValue(CSSValue* value) scope.fontDescription().setCommonLigaturesState(commonLigaturesState); scope.fontDescription().setDiscretionaryLigaturesState(discretionaryLigaturesState); scope.fontDescription().setHistoricalLigaturesState(historicalLigaturesState); + scope.fontDescription().setContextualLigaturesState(contextualLigaturesState); } void FontBuilder::setScript(const String& locale) { FontDescriptionChangeScope scope(this); + scope.fontDescription().setLocale(locale); scope.fontDescription().setScript(localeToScriptCodeForFontSelection(locale)); } -void FontBuilder::setItalic(FontItalic italic) +void FontBuilder::setStyle(FontStyle italic) { FontDescriptionChangeScope scope(this); - scope.fontDescription().setItalic(italic); + scope.fontDescription().setStyle(italic); } -void FontBuilder::setSmallCaps(FontSmallCaps smallCaps) +void FontBuilder::setVariant(FontVariant smallCaps) { FontDescriptionChangeScope scope(this); - scope.fontDescription().setSmallCaps(smallCaps); + scope.fontDescription().setVariant(smallCaps); } -void FontBuilder::setTextRenderingMode(TextRenderingMode textRenderingMode) +void FontBuilder::setTextRendering(TextRenderingMode textRenderingMode) { FontDescriptionChangeScope scope(this); - scope.fontDescription().setTextRenderingMode(textRenderingMode); + scope.fontDescription().setTextRendering(textRenderingMode); } void FontBuilder::setKerning(FontDescription::Kerning kerning) @@ -513,13 +528,10 @@ void FontBuilder::setSize(FontDescription& fontDescription, float effectiveZoom, float FontBuilder::getComputedSizeFromSpecifiedSize(FontDescription& fontDescription, float effectiveZoom, float specifiedSize) { - float zoomFactor = 1.0f; - if (!m_useSVGZoomRules) { - zoomFactor = effectiveZoom; - // FIXME: Why is this here!!!!?! - if (Frame* frame = m_document->frame()) - zoomFactor *= frame->textZoomFactor(); - } + float zoomFactor = effectiveZoom; + // FIXME: Why is this here!!!!?! + if (LocalFrame* frame = m_document->frame()) + zoomFactor *= frame->textZoomFactor(); return FontSize::getComputedSizeFromSpecifiedSize(m_document, zoomFactor, fontDescription.isAbsoluteSize(), specifiedSize); } @@ -614,48 +626,36 @@ void FontBuilder::checkForGenericFamilyChange(RenderStyle* style, const RenderSt setSize(scope.fontDescription(), style->effectiveZoom(), size); } -void FontBuilder::checkForZoomChange(RenderStyle* style, const RenderStyle* parentStyle) +void FontBuilder::updateComputedSize(RenderStyle* style, const RenderStyle* parentStyle) { FontDescriptionChangeScope scope(this); - if (style->effectiveZoom() == parentStyle->effectiveZoom()) - return; - - setSize(scope.fontDescription(), style->effectiveZoom(), scope.fontDescription().specifiedSize()); + scope.fontDescription().setComputedSize(getComputedSizeFromSpecifiedSize(scope.fontDescription(), style->effectiveZoom(), scope.fontDescription().specifiedSize())); } // FIXME: style param should come first -void FontBuilder::createFont(PassRefPtr<FontSelector> fontSelector, const RenderStyle* parentStyle, RenderStyle* style) +void FontBuilder::createFont(PassRefPtrWillBeRawPtr<FontSelector> fontSelector, const RenderStyle* parentStyle, RenderStyle* style) { if (!m_fontDirty) return; + updateComputedSize(style, parentStyle); checkForGenericFamilyChange(style, parentStyle); - checkForZoomChange(style, parentStyle); checkForOrientationChange(style); style->font().update(fontSelector); m_fontDirty = false; } -void FontBuilder::createFontForDocument(PassRefPtr<FontSelector> fontSelector, RenderStyle* documentStyle) +void FontBuilder::createFontForDocument(PassRefPtrWillBeRawPtr<FontSelector> fontSelector, RenderStyle* documentStyle) { FontDescription fontDescription = FontDescription(); fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale())); - if (Settings* settings = m_document->settings()) { - fontDescription.setUsePrinterFont(m_document->printing()); - const AtomicString& standardFont = settings->genericFontFamilySettings().standard(fontDescription.script()); - if (!standardFont.isEmpty()) { - fontDescription.setGenericFamily(FontDescription::StandardFamily); - fontDescription.firstFamily().setFamily(standardFont); - fontDescription.firstFamily().appendFamily(0); - } - fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); - int size = FontSize::fontSizeForKeyword(m_document, CSSValueMedium, false); - fontDescription.setSpecifiedSize(size); - fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, documentStyle->effectiveZoom(), size)); - } else { - fontDescription.setUsePrinterFont(m_document->printing()); - } + + setFontFamilyToStandard(fontDescription, m_document); + fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1); + int size = FontSize::fontSizeForKeyword(m_document, CSSValueMedium, false); + fontDescription.setSpecifiedSize(size); + fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(fontDescription, documentStyle->effectiveZoom(), size)); FontOrientation fontOrientation; NonCJKGlyphOrientation glyphOrientation; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.h b/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.h index b573b5159fd..2a611a01b1c 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilder.h @@ -23,9 +23,10 @@ #ifndef FontBuilder_h #define FontBuilder_h -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" #include "platform/fonts/FontDescription.h" +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" namespace WebCore { @@ -42,7 +43,7 @@ public: FontBuilder(); // FIXME: The name is probably wrong, but matches StyleResolverState callsite for consistency. - void initForStyleResolve(const Document&, RenderStyle*, bool useSVGZoomRules); + void initForStyleResolve(const Document&, RenderStyle*); void setInitial(float effectiveZoom); @@ -51,13 +52,13 @@ public: void inheritFrom(const FontDescription&); void fromSystemFont(CSSValueID, float effectiveZoom); - void setFontFamilyInitial(float effectiveZoom); + void setFontFamilyInitial(); void setFontFamilyInherit(const FontDescription&); - void setFontFamilyValue(CSSValue*, float effectiveZoom); + void setFontFamilyValue(CSSValue*); - void setFontSizeInitial(float effectiveZoom); - void setFontSizeInherit(const FontDescription&, float effectiveZoom); - void setFontSizeValue(CSSValue*, RenderStyle* parentStyle, const RenderStyle* rootElementStyle, float effectiveZoom); + void setFontSizeInitial(); + void setFontSizeInherit(const FontDescription&); + void setFontSizeValue(CSSValue*, RenderStyle* parentStyle, const RenderStyle* rootElementStyle); void setWeight(FontWeight); void setWeightBolder(); @@ -71,24 +72,34 @@ public: void setFeatureSettingsValue(CSSValue*); void setScript(const String& locale); - void setItalic(FontItalic); - void setSmallCaps(FontSmallCaps); - void setTextRenderingMode(TextRenderingMode); + void setStyle(FontStyle); + void setVariant(FontVariant); + void setTextRendering(TextRenderingMode); void setKerning(FontDescription::Kerning); void setFontSmoothing(FontSmoothingMode); // FIXME: These need to just vend a Font object eventually. - void createFont(PassRefPtr<FontSelector>, const RenderStyle* parentStyle, RenderStyle*); + void createFont(PassRefPtrWillBeRawPtr<FontSelector>, const RenderStyle* parentStyle, RenderStyle*); // FIXME: This is nearly static, should either made fully static or decomposed into // FontBuilder calls at the callsite. - void createFontForDocument(PassRefPtr<FontSelector>, RenderStyle*); + void createFontForDocument(PassRefPtrWillBeRawPtr<FontSelector>, RenderStyle*); + + bool fontSizeHasViewportUnits() { return m_fontSizehasViewportUnits; } // FIXME: These should not be necessary eventually. void setFontDirty(bool fontDirty) { m_fontDirty = fontDirty; } // FIXME: This is only used by an ASSERT in StyleResolver. Remove? bool fontDirty() const { return m_fontDirty; } + static FontDescription::GenericFamilyType initialGenericFamily() { return FontDescription::NoFamily; } + static TextRenderingMode initialTextRendering() { return AutoTextRendering; } + static FontVariant initialVariant() { return FontVariantNormal; } + static FontStyle initialStyle() { return FontStyleNormal; } + static FontDescription::Kerning initialKerning() { return FontDescription::AutoKerning; } + static FontSmoothingMode initialFontSmoothing() { return AutoSmoothing; } + friend class FontDescriptionChangeScope; + private: // FIXME: "size" arg should be first for consistency with other similar functions. @@ -96,12 +107,12 @@ private: void checkForOrientationChange(RenderStyle*); // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh void checkForGenericFamilyChange(RenderStyle*, const RenderStyle* parentStyle); - void checkForZoomChange(RenderStyle*, const RenderStyle* parentStyle); + void updateComputedSize(RenderStyle*, const RenderStyle* parentStyle); float getComputedSizeFromSpecifiedSize(FontDescription&, float effectiveZoom, float specifiedSize); const Document* m_document; - bool m_useSVGZoomRules; + bool m_fontSizehasViewportUnits; // FIXME: This member is here on a short-term lease. The plan is to remove // any notion of RenderStyle from here, allowing FontBuilder to build Font objects // directly, rather than as a byproduct of calling RenderStyle::setFontDescription. @@ -115,6 +126,8 @@ private: // is changed, FontBuilder tracks the need to update // style->font() with this bool. bool m_fontDirty; + + friend class FontBuilderTest; }; } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp new file mode 100644 index 00000000000..231dc93627a --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/resolver/FontBuilderTest.cpp @@ -0,0 +1,26 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "core/css/resolver/FontBuilder.h" + +#include <gtest/gtest.h> + +namespace WebCore { + +class FontBuilderTest : public ::testing::Test { +protected: + RenderStyle* getStyle(const FontBuilder& builder) + { + return builder.m_style; + } +}; + +TEST_F(FontBuilderTest, StylePointerInitialisation) +{ + FontBuilder builder; + EXPECT_EQ(0, getStyle(builder)); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/MatchRequest.h b/chromium/third_party/WebKit/Source/core/css/resolver/MatchRequest.h index df0207f4038..04c587eb623 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/MatchRequest.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/MatchRequest.h @@ -23,6 +23,7 @@ #ifndef MatchRequest_h #define MatchRequest_h +#include "core/css/CSSStyleSheet.h" #include "core/css/RuleSet.h" namespace WebCore { @@ -30,11 +31,13 @@ namespace WebCore { class ContainerNode; class MatchRequest { + STACK_ALLOCATED(); public: - MatchRequest(RuleSet* ruleSet, bool includeEmptyRules = false, const ContainerNode* scope = 0, bool elementApplyAuthorStyles = true, unsigned styleSheetIndex = 0) + MatchRequest(RuleSet* ruleSet, bool includeEmptyRules = false, const ContainerNode* scope = 0, const CSSStyleSheet* cssSheet = 0, bool elementApplyAuthorStyles = true, unsigned styleSheetIndex = 0) : ruleSet(ruleSet) , includeEmptyRules(includeEmptyRules) , scope(scope) + , styleSheet(cssSheet) , elementApplyAuthorStyles(elementApplyAuthorStyles) , styleSheetIndex(styleSheetIndex) { @@ -43,9 +46,10 @@ public: ruleSet->compactRulesIfNeeded(); } - const RuleSet* ruleSet; + RawPtrWillBeMember<const RuleSet> ruleSet; const bool includeEmptyRules; - const ContainerNode* scope; + RawPtrWillBeMember<const ContainerNode> scope; + RawPtrWillBeMember<const CSSStyleSheet> styleSheet; const bool elementApplyAuthorStyles; const unsigned styleSheetIndex; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/MatchResult.h b/chromium/third_party/WebKit/Source/core/css/resolver/MatchResult.h index bbcae30bdb5..25d9b91900a 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/MatchResult.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/MatchResult.h @@ -67,10 +67,12 @@ struct MatchedProperties { }; }; -struct MatchResult { +class MatchResult { + STACK_ALLOCATED(); +public: MatchResult() : isCacheable(true) { } Vector<MatchedProperties, 64> matchedProperties; - Vector<StyleRule*, 64> matchedRules; + WillBeHeapVector<RawPtrWillBeMember<StyleRule>, 64> matchedRules; MatchRanges ranges; bool isCacheable; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp index d3c222a1f1e..469fa3c9c2f 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.cpp @@ -37,7 +37,7 @@ namespace WebCore { void CachedMatchedProperties::set(const RenderStyle* style, const RenderStyle* parentStyle, const MatchResult& matchResult) { - matchedProperties.append(matchResult.matchedProperties); + matchedProperties.appendVector(matchResult.matchedProperties); ranges = matchResult.ranges; // Note that we don't cache the original RenderStyle instance. It may be further modified. @@ -49,8 +49,8 @@ void CachedMatchedProperties::set(const RenderStyle* style, const RenderStyle* p void CachedMatchedProperties::clear() { matchedProperties.clear(); - renderStyle = 0; - parentRenderStyle = 0; + renderStyle = nullptr; + parentRenderStyle = nullptr; } MatchedPropertiesCache::MatchedPropertiesCache() @@ -89,15 +89,15 @@ void MatchedPropertiesCache::add(const RenderStyle* style, const RenderStyle* pa if (++m_additionsSinceLastSweep >= maxAdditionsBetweenSweeps && !m_sweepTimer.isActive()) { static const unsigned sweepTimeInSeconds = 60; - m_sweepTimer.startOneShot(sweepTimeInSeconds); + m_sweepTimer.startOneShot(sweepTimeInSeconds, FROM_HERE); } ASSERT(hash); Cache::AddResult addResult = m_cache.add(hash, nullptr); if (addResult.isNewEntry) - addResult.iterator->value = adoptPtr(new CachedMatchedProperties); + addResult.storedValue->value = adoptPtr(new CachedMatchedProperties); - CachedMatchedProperties* cacheItem = addResult.iterator->value.get(); + CachedMatchedProperties* cacheItem = addResult.storedValue->value.get(); if (!addResult.isNewEntry) cacheItem->clear(); @@ -109,6 +109,17 @@ void MatchedPropertiesCache::clear() m_cache.clear(); } +void MatchedPropertiesCache::clearViewportDependent() +{ + Vector<unsigned, 16> toRemove; + for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it) { + CachedMatchedProperties* cacheItem = it->value.get(); + if (cacheItem->renderStyle->hasViewportUnits()) + toRemove.append(it->key); + } + m_cache.removeAll(toRemove); +} + void MatchedPropertiesCache::sweep(Timer<MatchedPropertiesCache>*) { // Look for cache entries containing a style declaration with a single ref and remove them. @@ -127,9 +138,7 @@ void MatchedPropertiesCache::sweep(Timer<MatchedPropertiesCache>*) } } } - for (size_t i = 0; i < toRemove.size(); ++i) - m_cache.remove(toRemove[i]); - + m_cache.removeAll(toRemove); m_additionsSinceLastSweep = 0; } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h b/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h index 2e5297d5acd..d86bf01f856 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/MatchedPropertiesCache.h @@ -54,6 +54,7 @@ public: void add(const RenderStyle*, const RenderStyle* parentStyle, unsigned hash, const MatchResult&); void clear(); + void clearViewportDependent(); static bool isCacheable(const Element*, const RenderStyle*, const RenderStyle* parentStyle); diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h b/chromium/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h index 1dc00f42dc3..86adebd50d4 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/MediaQueryResult.h @@ -29,16 +29,38 @@ namespace WebCore { -class MediaQueryResult : public RefCounted<MediaQueryResult> { - WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED; +class MediaQueryResult : public RefCountedWillBeGarbageCollectedFinalized<MediaQueryResult> { + WTF_MAKE_NONCOPYABLE(MediaQueryResult); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: MediaQueryResult(const MediaQueryExp& expr, bool result) +#if ENABLE(OILPAN) + : m_expression(&expr) +#else : m_expression(expr) +#endif , m_result(result) { } + void trace(Visitor* visitor) { visitor->trace(m_expression); } + + const MediaQueryExp* expression() const + { +#if ENABLE(OILPAN) + return m_expression; +#else + return &m_expression; +#endif + } + + bool result() const { return m_result; } + +private: +#if ENABLE(OILPAN) + Member<const MediaQueryExp> m_expression; +#else MediaQueryExp m_expression; +#endif bool m_result; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp index 706f5d827ab..7aea947d29f 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "core/css/resolver/ScopedStyleResolver.h" -#include "HTMLNames.h" +#include "core/HTMLNames.h" #include "core/css/CSSStyleSheet.h" #include "core/css/PageRuleCollector.h" #include "core/css/RuleFeature.h" @@ -49,38 +49,35 @@ ContainerNode* ScopedStyleResolver::scopingNodeFor(Document& document, const CSS Document* sheetDocument = sheet->ownerDocument(); if (!sheetDocument) return 0; - Node* ownerNode = sheet->ownerNode(); - if (!ownerNode || !isHTMLStyleElement(ownerNode)) - return &document; - HTMLStyleElement* styleElement = toHTMLStyleElement(ownerNode); - if (!styleElement->scoped()) { - if (styleElement->isInShadowTree()) - return styleElement->containingShadowRoot(); + Node* ownerNode = sheet->ownerNode(); + if (!isHTMLStyleElement(ownerNode)) return &document; - } - ContainerNode* parent = styleElement->parentNode(); - if (!parent) - return 0; - - return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0; + HTMLStyleElement& styleElement = toHTMLStyleElement(*ownerNode); + if (styleElement.isInShadowTree()) + return styleElement.containingShadowRoot(); + return &document; } -void ScopedStyleResolver::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver) +void ScopedStyleResolver::addRulesFromSheet(CSSStyleSheet* cssSheet, const MediaQueryEvaluator& medium, StyleResolver* resolver) { - m_authorStyleSheets.append(sheet); + m_authorStyleSheets.append(cssSheet); + StyleSheetContents* sheet = cssSheet->contents(); AddRuleFlags addRuleFlags = resolver->document().securityOrigin()->canRequest(sheet->baseURL()) ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState; const RuleSet& ruleSet = sheet->ensureRuleSet(medium, addRuleFlags); resolver->addMediaQueryResults(ruleSet.viewportDependentMediaQueryResults()); - resolver->processScopedRules(ruleSet, sheet->baseURL(), &m_scopingNode); + resolver->processScopedRules(ruleSet, cssSheet, m_scopingNode); } -void ScopedStyleResolver::collectFeaturesTo(RuleFeatureSet& features) +void ScopedStyleResolver::collectFeaturesTo(RuleFeatureSet& features, HashSet<const StyleSheetContents*>& visitedSharedStyleSheetContents) { - for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) - features.add(m_authorStyleSheets[i]->ruleSet().features()); + for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) { + StyleSheetContents* contents = m_authorStyleSheets[i]->contents(); + if (contents->hasOneClient() || visitedSharedStyleSheetContents.add(contents).isNewEntry) + features.add(contents->ruleSet().features()); + } } void ScopedStyleResolver::resetAuthorStyle() @@ -89,19 +86,6 @@ void ScopedStyleResolver::resetAuthorStyle() m_keyframesRuleMap.clear(); } -bool ScopedStyleResolver::checkRegionStyle(Element* regionElement) -{ - for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) { - const RuleSet& ruleSet = m_authorStyleSheets[i]->ruleSet(); - for (unsigned i = 0; i < ruleSet.m_regionSelectorsAndRuleSets.size(); ++i) { - ASSERT(ruleSet.m_regionSelectorsAndRuleSets.at(i).ruleSet.get()); - if (checkRegionSelector(ruleSet.m_regionSelectorsAndRuleSets.at(i).selector, regionElement)) - return true; - } - } - return false; -} - const StyleRuleKeyframes* ScopedStyleResolver::keyframeStylesForAnimation(const StringImpl* animationName) { if (m_keyframesRuleMap.isEmpty()) @@ -114,7 +98,7 @@ const StyleRuleKeyframes* ScopedStyleResolver::keyframeStylesForAnimation(const return it->value.get(); } -void ScopedStyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule) +void ScopedStyleResolver::addKeyframeStyle(PassRefPtrWillBeRawPtr<StyleRuleKeyframes> rule) { AtomicString s(rule->name()); if (rule->isVendorPrefixed()) { @@ -136,16 +120,13 @@ void ScopedStyleResolver::collectMatchingAuthorRules(ElementRuleCollector& colle if (!applyAuthorStyles) behaviorAtBoundary |= SelectorChecker::ScopeContainsLastMatchedElement; - if (m_scopingNode.isShadowRoot()) { - scopingNode = toShadowRoot(m_scopingNode).host(); - behaviorAtBoundary |= SelectorChecker::ScopeIsShadowHost; - } + if (m_scopingNode.isShadowRoot()) + behaviorAtBoundary |= SelectorChecker::ScopeIsShadowRoot; RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) { - MatchRequest matchRequest(&m_authorStyleSheets[i]->ruleSet(), includeEmptyRules, scopingNode, applyAuthorStyles, i); + MatchRequest matchRequest(&m_authorStyleSheets[i]->contents()->ruleSet(), includeEmptyRules, scopingNode, m_authorStyleSheets[i], applyAuthorStyles, i); collector.collectMatchingRules(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder); - collector.collectMatchingRulesForRegion(matchRequest, ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(behaviorAtBoundary), cascadeScope, cascadeOrder); } } @@ -154,7 +135,7 @@ void ScopedStyleResolver::matchPageRules(PageRuleCollector& collector) // Only consider the global author RuleSet for @page rules, as per the HTML5 spec. ASSERT(m_scopingNode.isDocumentNode()); for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) - collector.matchPageRules(&m_authorStyleSheets[i]->ruleSet()); + collector.matchPageRules(&m_authorStyleSheets[i]->contents()->ruleSet()); } void ScopedStyleResolver::collectViewportRulesTo(StyleResolver* resolver) const @@ -162,7 +143,7 @@ void ScopedStyleResolver::collectViewportRulesTo(StyleResolver* resolver) const if (!m_scopingNode.isDocumentNode()) return; for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) - resolver->viewportStyleResolver()->collectViewportRules(&m_authorStyleSheets[i]->ruleSet(), ViewportStyleResolver::AuthorOrigin); + resolver->viewportStyleResolver()->collectViewportRules(&m_authorStyleSheets[i]->contents()->ruleSet(), ViewportStyleResolver::AuthorOrigin); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h b/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h index 7aa1a1a18dd..64e7b7df54a 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleResolver.h @@ -31,6 +31,7 @@ #include "core/css/RuleSet.h" #include "core/dom/ContainerNode.h" #include "wtf/HashMap.h" +#include "wtf/HashSet.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" @@ -38,7 +39,6 @@ namespace WebCore { class MediaQueryEvaluator; class PageRuleCollector; -class ShadowRoot; class StyleSheetContents; // This class selects a RenderStyle for a given element based on a collection of stylesheets. @@ -55,28 +55,25 @@ public: ScopedStyleResolver* parent() { return m_parent; } public: - bool checkRegionStyle(Element*); const StyleRuleKeyframes* keyframeStylesForAnimation(const StringImpl* animationName); - void addKeyframeStyle(PassRefPtr<StyleRuleKeyframes>); + void addKeyframeStyle(PassRefPtrWillBeRawPtr<StyleRuleKeyframes>); void collectMatchingAuthorRules(ElementRuleCollector&, bool includeEmptyRules, bool applyAuthorStyles, CascadeScope, CascadeOrder = ignoreCascadeOrder); void matchPageRules(PageRuleCollector&); - void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, StyleResolver*); - void collectFeaturesTo(RuleFeatureSet&); + void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, StyleResolver*); + void collectFeaturesTo(RuleFeatureSet&, HashSet<const StyleSheetContents*>& visitedSharedStyleSheetContents); void resetAuthorStyle(); void collectViewportRulesTo(StyleResolver*) const; private: explicit ScopedStyleResolver(ContainerNode& scopingNode) : m_scopingNode(scopingNode), m_parent(0) { } - RuleSet* ensureAuthorStyle(); - ContainerNode& m_scopingNode; ScopedStyleResolver* m_parent; - Vector<StyleSheetContents*> m_authorStyleSheets; + WillBePersistentHeapVector<RawPtrWillBeMember<CSSStyleSheet> > m_authorStyleSheets; - typedef HashMap<const StringImpl*, RefPtr<StyleRuleKeyframes> > KeyframesRuleMap; + typedef WillBePersistentHeapHashMap<const StringImpl*, RefPtrWillBeMember<StyleRuleKeyframes> > KeyframesRuleMap; KeyframesRuleMap m_keyframesRuleMap; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleTree.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleTree.cpp index 729faf15e8f..3b27951217e 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleTree.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ScopedStyleTree.cpp @@ -34,6 +34,8 @@ namespace WebCore { +class StyleSheetContents; + ScopedStyleResolver* ScopedStyleTree::ensureScopedStyleResolver(ContainerNode& scopingNode) { bool isNewEntry; @@ -45,8 +47,7 @@ ScopedStyleResolver* ScopedStyleTree::ensureScopedStyleResolver(ContainerNode& s ScopedStyleResolver* ScopedStyleTree::scopedStyleResolverFor(const ContainerNode& scopingNode) { - if (!scopingNode.hasScopedHTMLStyleChild() - && !isShadowHost(&scopingNode) + if (!isShadowHost(&scopingNode) && !scopingNode.isDocumentNode() && !scopingNode.isShadowRoot()) return 0; @@ -58,12 +59,12 @@ ScopedStyleResolver* ScopedStyleTree::addScopedStyleResolver(ContainerNode& scop HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::AddResult addResult = m_authorStyles.add(&scopingNode, nullptr); if (addResult.isNewEntry) { - addResult.iterator->value = ScopedStyleResolver::create(scopingNode); + addResult.storedValue->value = ScopedStyleResolver::create(scopingNode); if (scopingNode.isDocumentNode()) - m_scopedResolverForDocument = addResult.iterator->value.get(); + m_scopedResolverForDocument = addResult.storedValue->value.get(); } isNewEntry = addResult.isNewEntry; - return addResult.iterator->value.get(); + return addResult.storedValue->value.get(); } void ScopedStyleTree::setupScopedStylesTree(ScopedStyleResolver* target) @@ -123,12 +124,10 @@ void ScopedStyleTree::collectScopedResolversForHostedShadowTrees(const Element* // Adding scoped resolver for active shadow roots for shadow host styling. for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { - if (shadowRoot->hasScopedHTMLStyleChild()) { + if (shadowRoot->numberOfStyles() > 0) { if (ScopedStyleResolver* resolver = scopedStyleResolverFor(*shadowRoot)) resolvers.append(resolver); } - if (!shadowRoot->containsShadowElements()) - break; } } @@ -138,6 +137,10 @@ void ScopedStyleTree::resolveScopedKeyframesRules(const Element* element, Vector TreeScope& treeScope = element->treeScope(); bool applyAuthorStyles = treeScope.applyAuthorStyles(); + // Add resolvers for shadow roots hosted by the given element. + collectScopedResolversForHostedShadowTrees(element, resolvers); + + // Add resolvers while walking up DOM tree from the given element. for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scopedResolver; scopedResolver = scopedResolver->parent()) { if (scopedResolver->treeScope() == treeScope || (applyAuthorStyles && scopedResolver->treeScope() == document)) resolvers.append(scopedResolver); @@ -187,8 +190,9 @@ void ScopedStyleTree::popStyleCache(const ContainerNode& scopingNode) void ScopedStyleTree::collectFeaturesTo(RuleFeatureSet& features) { + HashSet<const StyleSheetContents*> visitedSharedStyleSheetContents; for (HashMap<const ContainerNode*, OwnPtr<ScopedStyleResolver> >::iterator it = m_authorStyles.begin(); it != m_authorStyles.end(); ++it) - it->value->collectFeaturesTo(features); + it->value->collectFeaturesTo(features, visitedSharedStyleSheetContents); } inline void ScopedStyleTree::reparentNodes(const ScopedStyleResolver* oldParent, ScopedStyleResolver* newParent) diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.cpp index 92890d6c3af..4589e71bf6f 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.cpp @@ -29,8 +29,8 @@ #include "config.h" #include "core/css/resolver/SharedStyleFinder.h" -#include "HTMLNames.h" -#include "XMLNames.h" +#include "core/HTMLNames.h" +#include "core/XMLNames.h" #include "core/css/resolver/StyleResolver.h" #include "core/css/resolver/StyleResolverStats.h" #include "core/dom/ContainerNode.h" @@ -42,9 +42,11 @@ #include "core/dom/QualifiedName.h" #include "core/dom/SpaceSplitString.h" #include "core/dom/shadow/ElementShadow.h" +#include "core/dom/shadow/InsertionPoint.h" #include "core/html/HTMLElement.h" #include "core/html/HTMLInputElement.h" #include "core/html/HTMLOptGroupElement.h" +#include "core/html/HTMLOptionElement.h" #include "core/rendering/style/RenderStyle.h" #include "core/svg/SVGElement.h" #include "wtf/HashSet.h" @@ -56,7 +58,7 @@ using namespace HTMLNames; bool SharedStyleFinder::canShareStyleWithControl(Element& candidate) const { - if (!candidate.hasTagName(inputTag) || !element().hasTagName(inputTag)) + if (!isHTMLInputElement(candidate) || !isHTMLInputElement(element())) return false; HTMLInputElement& candidateInput = toHTMLInputElement(candidate); @@ -100,7 +102,7 @@ bool SharedStyleFinder::classNamesAffectedByRules(const SpaceSplitString& classN { unsigned count = classNames.size(); for (unsigned i = 0; i < count; ++i) { - if (m_features.classesInRules.contains(classNames[i])) + if (m_features.hasSelectorForClass(classNames[i])) return true; } return false; @@ -121,7 +123,7 @@ bool SharedStyleFinder::sharingCandidateHasIdenticalStyleAffectingAttributes(Ele if (element().fastGetAttribute(langAttr) != candidate.fastGetAttribute(langAttr)) return false; - // These two checks must be here since RuleSet has a specail case to allow style sharing between elements + // These two checks must be here since RuleSet has a special case to allow style sharing between elements // with type and readonly attributes whereas other attribute selectors prevent sharing. if (typeAttributeValue(element()) != typeAttributeValue(candidate)) return false; @@ -149,11 +151,46 @@ bool SharedStyleFinder::sharingCandidateHasIdenticalStyleAffectingAttributes(Ele // FIXME: Consider removing this, it's unlikely we'll have so many progress elements // that sharing the style makes sense. Instead we should just not support style sharing // for them. - if (element().hasTagName(progressTag)) { + if (isHTMLProgressElement(element())) { if (element().shouldAppearIndeterminate() != candidate.shouldAppearIndeterminate()) return false; } + if (isHTMLOptGroupElement(element()) || isHTMLOptionElement(element())) { + if (element().isDisabledFormControl() != candidate.isDisabledFormControl()) + return false; + if (isHTMLOptionElement(element()) && toHTMLOptionElement(element()).selected() != toHTMLOptionElement(candidate).selected()) + return false; + } + + return true; +} + +bool SharedStyleFinder::sharingCandidateCanShareHostStyles(Element& candidate) const +{ + const ElementShadow* elementShadow = element().shadow(); + const ElementShadow* candidateShadow = candidate.shadow(); + + if (!elementShadow && !candidateShadow) + return true; + + if (static_cast<bool>(elementShadow) != static_cast<bool>(candidateShadow)) + return false; + + return elementShadow->hasSameStyles(candidateShadow); +} + +bool SharedStyleFinder::sharingCandidateDistributedToSameInsertionPoint(Element& candidate) const +{ + WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints, candidateInsertionPoints; + collectDestinationInsertionPoints(element(), insertionPoints); + collectDestinationInsertionPoints(candidate, candidateInsertionPoints); + if (insertionPoints.size() != candidateInsertionPoints.size()) + return false; + for (size_t i = 0; i < insertionPoints.size(); ++i) { + if (insertionPoints[i] != candidateInsertionPoints[i]) + return false; + } return true; } @@ -161,7 +198,7 @@ bool SharedStyleFinder::canShareStyleWithElement(Element& candidate) const { if (element() == candidate) return false; - Element* parent = candidate.parentElement(); + Element* parent = candidate.parentOrShadowHostElement(); RenderStyle* style = candidate.renderStyle(); if (!style) return false; @@ -169,7 +206,7 @@ bool SharedStyleFinder::canShareStyleWithElement(Element& candidate) const return false; if (!parent) return false; - if (element().parentElement()->renderStyle() != parent->renderStyle()) + if (element().parentOrShadowHostElement()->renderStyle() != parent->renderStyle()) return false; if (candidate.tagQName() != element().tagQName()) return false; @@ -181,26 +218,20 @@ bool SharedStyleFinder::canShareStyleWithElement(Element& candidate) const return false; if (candidate.isLink() != element().isLink()) return false; - if (candidate.hovered() != element().hovered()) - return false; - if (candidate.active() != element().active()) - return false; - if (candidate.focused() != element().focused()) - return false; if (candidate.shadowPseudoId() != element().shadowPseudoId()) return false; - if (candidate == document().cssTarget()) - return false; if (!sharingCandidateHasIdenticalStyleAffectingAttributes(candidate)) return false; if (candidate.additionalPresentationAttributeStyle() != element().additionalPresentationAttributeStyle()) return false; - if (candidate.hasID() && m_features.idsInRules.contains(candidate.idForStyleResolution())) + if (candidate.hasID() && m_features.hasSelectorForId(candidate.idForStyleResolution())) return false; - if (candidate.hasScopedHTMLStyleChild()) + if (!sharingCandidateCanShareHostStyles(candidate)) + return false; + if (!sharingCandidateDistributedToSameInsertionPoint(candidate)) + return false; + if (candidate.isInTopLayer() != element().isInTopLayer()) return false; - if (candidate.shadow() && candidate.shadow()->containsActiveStyles()) - return 0; bool isControl = candidate.isFormControlElement(); @@ -220,16 +251,14 @@ bool SharedStyleFinder::canShareStyleWithElement(Element& candidate) const if (candidate.isUnresolvedCustomElement() != element().isUnresolvedCustomElement()) return false; - if (element().parentElement() != parent) { + if (element().parentOrShadowHostElement() != parent) { if (!parent->isStyledElement()) return false; - if (parent->hasScopedHTMLStyleChild()) - return false; if (parent->inlineStyle()) return false; if (parent->isSVGElement() && toSVGElement(parent)->animatedSMILStyleProperties()) return false; - if (parent->hasID() && m_features.idsInRules.contains(parent->idForStyleResolution())) + if (parent->hasID() && m_features.hasSelectorForId(parent->idForStyleResolution())) return false; if (!parent->childrenSupportStyleSharing()) return false; @@ -304,7 +333,7 @@ RenderStyle* SharedStyleFinder::findSharedStyle() } // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. - if (!element().parentElement()->childrenSupportStyleSharing()) { + if (!element().parentElementOrShadowRoot()->childrenSupportStyleSharing()) { INCREMENT_STYLE_STATS_COUNTER(m_styleResolver, sharedStyleRejectedByParent); return 0; } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.h b/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.h index e65c5c07cd0..5af9a95711f 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/SharedStyleFinder.h @@ -36,6 +36,7 @@ class SpaceSplitString; class StyleResolver; class SharedStyleFinder { + STACK_ALLOCATED(); public: // RuleSets are passed non-const as the act of matching against them can cause them // to be compacted. :( @@ -63,6 +64,8 @@ private: bool canShareStyleWithElement(Element& candidate) const; bool canShareStyleWithControl(Element& candidate) const; bool sharingCandidateHasIdenticalStyleAffectingAttributes(Element& candidate) const; + bool sharingCandidateCanShareHostStyles(Element& candidate) const; + bool sharingCandidateDistributedToSameInsertionPoint(Element& candidate) const; bool matchesRuleSet(RuleSet*); Element& element() const { return *m_context.element(); } @@ -70,8 +73,8 @@ private: bool m_elementAffectedByClassRules; const RuleFeatureSet& m_features; - RuleSet* m_siblingRuleSet; - RuleSet* m_uncommonAttributeRuleSet; + RawPtrWillBeMember<RuleSet> m_siblingRuleSet; + RawPtrWillBeMember<RuleSet> m_uncommonAttributeRuleSet; StyleResolver& m_styleResolver; const ElementResolveContext& m_context; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp index 4b1fe76c082..060f53f8eb0 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.cpp @@ -29,24 +29,26 @@ #include "config.h" #include "core/css/resolver/StyleAdjuster.h" -#include "HTMLNames.h" -#include "SVGNames.h" +#include "core/HTMLNames.h" +#include "core/SVGNames.h" #include "core/dom/ContainerNode.h" #include "core/dom/Document.h" #include "core/dom/Element.h" -#include "core/html/HTMLHtmlElement.h" +#include "core/dom/NodeRenderStyle.h" #include "core/html/HTMLIFrameElement.h" #include "core/html/HTMLInputElement.h" -#include "core/html/HTMLTableElement.h" +#include "core/html/HTMLPlugInElement.h" +#include "core/html/HTMLTableCellElement.h" #include "core/html/HTMLTextAreaElement.h" #include "core/frame/FrameView.h" #include "core/frame/Settings.h" -#include "core/rendering/Pagination.h" #include "core/rendering/RenderTheme.h" #include "core/rendering/style/GridPosition.h" #include "core/rendering/style/RenderStyle.h" #include "core/rendering/style/RenderStyleConstants.h" +#include "core/svg/SVGSVGElement.h" #include "platform/Length.h" +#include "platform/transforms/TransformOperations.h" #include "wtf/Assertions.h" namespace WebCore { @@ -161,63 +163,44 @@ static bool parentStyleForcesZIndexToCreateStackingContext(const RenderStyle* pa return isDisplayFlexibleBox(parentStyle->display()) || isDisplayGridBox(parentStyle->display()); } -void StyleAdjuster::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e) +static bool hasWillChangeThatCreatesStackingContext(const RenderStyle* style) { - ASSERT(parentStyle); - - // Cache our original display. - style->setOriginalDisplay(style->display()); - - if (style->display() != NONE) { - // If we have a <td> that specifies a float property, in quirks mode we just drop the float - // property. - // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force - // these tags to retain their display types. - if (m_useQuirksModeStyles && e) { - if (e->hasTagName(tdTag)) { - style->setDisplay(TABLE_CELL); - style->setFloating(NoFloat); - } else if (isHTMLTableElement(e)) { - style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); - } - } - - if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) { - if (style->whiteSpace() == KHTML_NOWRAP) { - // Figure out if we are really nowrapping or if we should just - // use normal instead. If the width of the cell is fixed, then - // we don't actually use NOWRAP. - if (style->width().isFixed()) - style->setWhiteSpace(NORMAL); - else - style->setWhiteSpace(NOWRAP); - } - } - - // Tables never support the -webkit-* values for text-align and will reset back to the default. - if (e && isHTMLTableElement(e) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT)) - style->setTextAlign(TASTART); - - // Frames and framesets never honor position:relative or position:absolute. This is necessary to - // fix a crash where a site tries to position these objects. They also never honor display. - if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) { - style->setPosition(StaticPosition); - style->setDisplay(BLOCK); - } - - // Ruby text does not support float or position. This might change with evolution of the specification. - if (e && e->hasTagName(rtTag)) { - style->setPosition(StaticPosition); - style->setFloating(NoFloat); + for (size_t i = 0; i < style->willChangeProperties().size(); ++i) { + switch (style->willChangeProperties()[i]) { + case CSSPropertyOpacity: + case CSSPropertyTransform: + case CSSPropertyWebkitTransform: + case CSSPropertyTransformStyle: + case CSSPropertyWebkitTransformStyle: + case CSSPropertyPerspective: + case CSSPropertyWebkitPerspective: + case CSSPropertyWebkitMask: + case CSSPropertyWebkitMaskBoxImage: + case CSSPropertyWebkitClipPath: + case CSSPropertyWebkitBoxReflect: + case CSSPropertyWebkitFilter: + case CSSPropertyZIndex: + case CSSPropertyPosition: + return true; + case CSSPropertyMixBlendMode: + case CSSPropertyIsolation: + if (RuntimeEnabledFeatures::cssCompositingEnabled()) + return true; + break; + default: + break; } + } + return false; +} - // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead. - // Table headers with a text-align of -webkit-auto will change the text-align to center. - if (e && e->hasTagName(thTag) && style->textAlign() == TASTART) - style->setTextAlign(CENTER); +void StyleAdjuster::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e, const CachedUAStyle* cachedUAStyle) +{ + ASSERT(parentStyle); - if (e && e->hasTagName(legendTag)) - style->setDisplay(BLOCK); + if (style->display() != NONE) { + if (e) + adjustStyleForTagName(style, parentStyle, *e); // Per the spec, position 'static' and 'relative' in the top layer compute to 'absolute'. if (isInTopLayer(e, style) && (style->position() == StaticPosition || style->position() == RelativePosition)) @@ -227,36 +210,7 @@ void StyleAdjuster::adjustRenderStyle(RenderStyle* style, RenderStyle* parentSty if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document().documentElement() == e)) style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !m_useQuirksModeStyles)); - // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely - // clear how that should work. - if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode()) - style->setDisplay(INLINE_BLOCK); - - // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on - // table rows or cells. This has been established for position:relative 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->hasInFlowPosition()) - style->setPosition(StaticPosition); - - // writing-mode does not apply to table row groups, table column groups, table rows, and table columns. - // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though. - if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP - || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP - || style->display() == TABLE_CELL) - style->setWritingMode(parentStyle->writingMode()); - - // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting - // of block-flow to anything other than TopToBottomWritingMode. - // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support. - if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX)) - style->setWritingMode(TopToBottomWritingMode); - - if (isDisplayFlexibleBox(parentStyle->display()) || isDisplayGridBox(parentStyle->display())) { - style->setFloating(NoFloat); - style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !m_useQuirksModeStyles)); - } + adjustStyleForDisplay(style, parentStyle); } // Make sure our z-index value is only applied if the object is positioned. @@ -276,80 +230,36 @@ void StyleAdjuster::adjustRenderStyle(RenderStyle* style, RenderStyle* parentSty || style->hasBlendMode() || style->hasIsolation() || style->position() == StickyPosition - || (style->position() == FixedPosition && e && e->document().settings() && e->document().settings()->fixedPositionCreatesStackingContext()) + || style->position() == FixedPosition || isInTopLayer(e, style) - || style->hasFlowFrom() - )) + || hasWillChangeThatCreatesStackingContext(style))) style->setZIndex(0); - // Textarea considers overflow visible as auto. - if (e && isHTMLTextAreaElement(e)) { - style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX()); - style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY()); - } - - // For now, <marquee> requires an overflow clip to work properly. - if (e && e->hasTagName(marqueeTag)) { - style->setOverflowX(OHIDDEN); - style->setOverflowY(OHIDDEN); + // will-change:transform should result in the same rendering behavior as having a transform, + // including the creation of a containing block for fixed position descendants. + if (!style->hasTransform() && (style->willChangeProperties().contains(CSSPropertyWebkitTransform) || style->willChangeProperties().contains(CSSPropertyTransform))) { + bool makeIdentity = true; + style->setTransform(TransformOperations(makeIdentity)); } if (doesNotInheritTextDecoration(style, e)) - style->setTextDecorationsInEffect(style->textDecoration()); - else - style->addToTextDecorationsInEffect(style->textDecoration()); + style->clearAppliedTextDecorations(); - // If either overflow value is not visible, change to auto. - if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) { - // FIXME: Once we implement pagination controls, overflow-x should default to hidden - // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it - // default to auto so we can at least scroll through the pages. - style->setOverflowX(OAUTO); - } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) { - style->setOverflowY(OAUTO); - } + style->applyTextDecorations(); - // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these - // styles are specified on a root element, then they will be incorporated in - // StyleAdjuster::styleForDocument(). - if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e && (isHTMLHtmlElement(e) || e->hasTagName(bodyTag)))) - Pagination::setStylesForPaginationMode(WebCore::paginationModeForRenderStyle(style), style); - - // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. - // FIXME: Eventually table sections will support auto and scroll. - if (style->display() == TABLE || style->display() == INLINE_TABLE - || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { - if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) - style->setOverflowX(OVISIBLE); - if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) - style->setOverflowY(OVISIBLE); - } - - // Menulists should have visible overflow - if (style->appearance() == MenulistPart) { - style->setOverflowX(OVISIBLE); - style->setOverflowY(OVISIBLE); - } + if (style->overflowX() != OVISIBLE || style->overflowY() != OVISIBLE) + adjustOverflow(style); // Cull out any useless layers and also repeat patterns into additional layers. style->adjustBackgroundLayers(); style->adjustMaskLayers(); - // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will - // alter fonts and heights/widths. - if (e && e->isFormControlElement() && style->fontSize() >= 11) { - // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, - // so we have to treat all image buttons as though they were explicitly sized. - if (!e->hasTagName(inputTag) || !toHTMLInputElement(e)->isImageButton()) - addIntrinsicMargins(style); - } - // Let the theme also have a crack at adjusting the style. if (style->hasAppearance()) - RenderTheme::theme().adjustStyle(style, e, m_cachedUAStyle); + RenderTheme::theme().adjustStyle(style, e, cachedUAStyle); - // If we have first-letter pseudo style, do not share this style. - if (style->hasPseudoStyle(FIRST_LETTER)) + // If we have first-letter pseudo style, transitions, or animations, do not share this style. + if (style->hasPseudoStyle(FIRST_LETTER) || style->transitions() || style->animations()) style->setUnique(); // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening. @@ -358,68 +268,186 @@ void StyleAdjuster::adjustRenderStyle(RenderStyle* style, RenderStyle* parentSty || style->hasFilter())) style->setTransformStyle3D(TransformStyle3DFlat); - // Seamless iframes behave like blocks. Map their display to inline-block when marked inline. - if (e && e->hasTagName(iframeTag) && style->display() == INLINE && toHTMLIFrameElement(e)->shouldDisplaySeamlessly()) - style->setDisplay(INLINE_BLOCK); - - adjustGridItemPosition(style, parentStyle); - if (e && e->isSVGElement()) { - // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty - if (style->overflowY() == OSCROLL) - style->setOverflowY(OHIDDEN); - else if (style->overflowY() == OAUTO) - style->setOverflowY(OVISIBLE); - - if (style->overflowX() == OSCROLL) - style->setOverflowX(OHIDDEN); - else if (style->overflowX() == OAUTO) - style->setOverflowX(OVISIBLE); - // Only the root <svg> element in an SVG document fragment tree honors css position - if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement())) + if (!(isSVGSVGElement(*e) && e->parentNode() && !e->parentNode()->isSVGElement())) style->setPosition(RenderStyle::initialPosition()); - // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should - // not be scaled again. - if (e->hasTagName(SVGNames::foreignObjectTag)) - style->setEffectiveZoom(RenderStyle::initialZoom()); - // SVG text layout code expects us to be a block-level style element. - if ((e->hasTagName(SVGNames::foreignObjectTag) || e->hasTagName(SVGNames::textTag)) && style->isDisplayInlineType()) + if ((isSVGForeignObjectElement(*e) || isSVGTextElement(*e)) && style->isDisplayInlineType()) style->setDisplay(BLOCK); } + + if (e && e->renderStyle() && e->renderStyle()->textAutosizingMultiplier() != 1) { + // Preserve the text autosizing multiplier on style recalc. + // (The autosizer will update it during layout if it needs to be changed.) + style->setTextAutosizingMultiplier(e->renderStyle()->textAutosizingMultiplier()); + style->setUnique(); + } +} + +void StyleAdjuster::adjustStyleForTagName(RenderStyle* style, RenderStyle* parentStyle, Element& element) +{ + // <div> and <span> are the most common elements on the web, we skip all the work for them. + if (isHTMLDivElement(element) || isHTMLSpanElement(element)) + return; + + if (isHTMLTableCellElement(element)) { + // If we have a <td> that specifies a float property, in quirks mode we just drop the float property. + // FIXME: Why is this only <td> and not <th>? + if (element.hasTagName(tdTag) && m_useQuirksModeStyles) { + style->setDisplay(TABLE_CELL); + style->setFloating(NoFloat); + } + // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead. + // Table headers with a text-align of -webkit-auto will change the text-align to center. + if (element.hasTagName(thTag) && style->textAlign() == TASTART) + style->setTextAlign(CENTER); + if (style->whiteSpace() == KHTML_NOWRAP) { + // Figure out if we are really nowrapping or if we should just + // use normal instead. If the width of the cell is fixed, then + // we don't actually use NOWRAP. + if (style->width().isFixed()) + style->setWhiteSpace(NORMAL); + else + style->setWhiteSpace(NOWRAP); + } + return; + } + + if (isHTMLTableElement(element)) { + // Sites commonly use display:inline/block on <td>s and <table>s. In quirks mode we force + // these tags to retain their display types. + if (m_useQuirksModeStyles) + style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); + // Tables never support the -webkit-* values for text-align and will reset back to the default. + if (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT) + style->setTextAlign(TASTART); + return; + } + + if (isHTMLFrameElement(element) || isHTMLFrameSetElement(element)) { + // Frames and framesets never honor position:relative or position:absolute. This is necessary to + // fix a crash where a site tries to position these objects. They also never honor display. + style->setPosition(StaticPosition); + style->setDisplay(BLOCK); + return; + } + + if (isHTMLRTElement(element)) { + // Ruby text does not support float or position. This might change with evolution of the specification. + style->setPosition(StaticPosition); + style->setFloating(NoFloat); + return; + } + + if (isHTMLLegendElement(element)) { + style->setDisplay(BLOCK); + return; + } + + if (isHTMLMarqueeElement(element)) { + // For now, <marquee> requires an overflow clip to work properly. + style->setOverflowX(OHIDDEN); + style->setOverflowY(OHIDDEN); + return; + } + + if (element.isFormControlElement()) { + if (isHTMLTextAreaElement(element)) { + // Textarea considers overflow visible as auto. + style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX()); + style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY()); + } + + // Important: Intrinsic margins get added to controls before the theme has adjusted the style, + // since the theme will alter fonts and heights/widths. + // + // Don't apply intrinsic margins to image buttons. The designer knows how big the images are, + // so we have to treat all image buttons as though they were explicitly sized. + if (style->fontSize() >= 11 && (!isHTMLInputElement(element) || !toHTMLInputElement(element).isImageButton())) + addIntrinsicMargins(style); + return; + } + + if (isHTMLPlugInElement(element)) { + style->setRequiresAcceleratedCompositingForExternalReasons(toHTMLPlugInElement(element).shouldAccelerate()); + return; + } } -void StyleAdjuster::adjustGridItemPosition(RenderStyle* style, RenderStyle* parentStyle) const +void StyleAdjuster::adjustOverflow(RenderStyle* style) { - const GridPosition& columnStartPosition = style->gridColumnStart(); - const GridPosition& columnEndPosition = style->gridColumnEnd(); - const GridPosition& rowStartPosition = style->gridRowStart(); - const GridPosition& rowEndPosition = style->gridRowEnd(); - - // If opposing grid-placement properties both specify a grid span, they both compute to ‘auto’. - if (columnStartPosition.isSpan() && columnEndPosition.isSpan()) { - style->setGridColumnStart(GridPosition()); - style->setGridColumnEnd(GridPosition()); + ASSERT(style->overflowX() != OVISIBLE || style->overflowY() != OVISIBLE); + + // If either overflow value is not visible, change to auto. + if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) { + // FIXME: Once we implement pagination controls, overflow-x should default to hidden + // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it + // default to auto so we can at least scroll through the pages. + style->setOverflowX(OAUTO); + } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) { + style->setOverflowY(OAUTO); } - if (rowStartPosition.isSpan() && rowEndPosition.isSpan()) { - style->setGridRowStart(GridPosition()); - style->setGridRowEnd(GridPosition()); + // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. + // FIXME: Eventually table sections will support auto and scroll. + if (style->display() == TABLE || style->display() == INLINE_TABLE + || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { + if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) + style->setOverflowX(OVISIBLE); + if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) + style->setOverflowY(OVISIBLE); } - // Unknown named grid area compute to 'auto'. - const NamedGridAreaMap& map = parentStyle->namedGridArea(); + // Menulists should have visible overflow + if (style->appearance() == MenulistPart) { + style->setOverflowX(OVISIBLE); + style->setOverflowY(OVISIBLE); + } +} -#define CLEAR_UNKNOWN_NAMED_AREA(prop, Prop) \ - if (prop.isNamedGridArea() && !map.contains(prop.namedGridLine())) \ - style->setGrid##Prop(GridPosition()); +void StyleAdjuster::adjustStyleForDisplay(RenderStyle* style, RenderStyle* parentStyle) +{ + if (style->display() == BLOCK && !style->isFloating()) + return; + + // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely + // clear how that should work. + if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode()) + style->setDisplay(INLINE_BLOCK); - CLEAR_UNKNOWN_NAMED_AREA(columnStartPosition, ColumnStart); - CLEAR_UNKNOWN_NAMED_AREA(columnEndPosition, ColumnEnd); - CLEAR_UNKNOWN_NAMED_AREA(rowStartPosition, RowStart); - CLEAR_UNKNOWN_NAMED_AREA(rowEndPosition, RowEnd); + // After performing the display mutation, check table rows. We do not honor position: relative table rows or cells. + // This has been established for position: relative 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->position() == RelativePosition) + style->setPosition(StaticPosition); + + // Cannot support position: sticky for table columns and column groups because current code is only doing + // background painting through columns / column groups + if ((style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN) + && style->position() == StickyPosition) + style->setPosition(StaticPosition); + + // writing-mode does not apply to table row groups, table column groups, table rows, and table columns. + // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though. + if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP + || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP + || style->display() == TABLE_CELL) + style->setWritingMode(parentStyle->writingMode()); + + // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting + // of block-flow to anything other than TopToBottomWritingMode. + // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support. + if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX)) + style->setWritingMode(TopToBottomWritingMode); + + if (isDisplayFlexibleBox(parentStyle->display()) || isDisplayGridBox(parentStyle->display())) { + style->setFloating(NoFloat); + style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !m_useQuirksModeStyles)); + } } } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h index 96e5927bc37..b83ff9b0648 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleAdjuster.h @@ -22,6 +22,8 @@ #ifndef StyleAdjuster_h #define StyleAdjuster_h +#include "platform/heap/Handle.h" + namespace WebCore { class CachedUAStyle; @@ -32,18 +34,19 @@ class RenderStyle; // and the web expects that we expose "adjusted" values when // for those property/element pairs. class StyleAdjuster { + STACK_ALLOCATED(); public: - StyleAdjuster(const CachedUAStyle& cachedUAStyle, bool useQuirksModeStyles) - : m_cachedUAStyle(cachedUAStyle) - , m_useQuirksModeStyles(useQuirksModeStyles) + StyleAdjuster(bool useQuirksModeStyles) + : m_useQuirksModeStyles(useQuirksModeStyles) { } - void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*); + void adjustRenderStyle(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element*, const CachedUAStyle*); private: - void adjustGridItemPosition(RenderStyle*, RenderStyle*) const; + void adjustStyleForDisplay(RenderStyle* styleToAdjust, RenderStyle* parentStyle); + void adjustStyleForTagName(RenderStyle* styleToAdjust, RenderStyle* parentStyle, Element&); + void adjustOverflow(RenderStyle* styleToAdjust); - const CachedUAStyle& m_cachedUAStyle; bool m_useQuirksModeStyles; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilder.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilder.h index 82214e7980b..f3557a2044c 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilder.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilder.h @@ -31,7 +31,8 @@ #ifndef StyleBuilder_h #define StyleBuilder_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" +#include "platform/heap/Handle.h" namespace WebCore { @@ -41,16 +42,12 @@ class RenderStyle; class StyleResolverState; class StyleBuilder { + STATIC_ONLY(StyleBuilder); public: static void applyProperty(CSSPropertyID, StyleResolverState&, CSSValue*); - // This function contains the gigantic old switch-statement of properties inherited from - // StyleResolver. Each property should be migrated over to a new StyleBuilder templated - // function and removed from this code. Once they're all moved, this function can die. - static void oldApplyProperty(CSSPropertyID, StyleResolverState&, CSSValue*, bool isInitial, bool isInherit); - private: - static bool applyProperty(CSSPropertyID, StyleResolverState&, CSSValue*, bool isInitial, bool isInherit); + static void applyProperty(CSSPropertyID, StyleResolverState&, CSSValue*, bool isInitial, bool isInherit); }; } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp index d3ffb158dce..fe94e10930e 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp @@ -27,26 +27,210 @@ #include "config.h" #include "core/css/resolver/StyleBuilderConverter.h" +#include "core/css/CSSFunctionValue.h" +#include "core/css/CSSGridLineNamesValue.h" #include "core/css/CSSPrimitiveValueMappings.h" +#include "core/css/CSSReflectValue.h" #include "core/css/CSSShadowValue.h" #include "core/css/Pair.h" #include "core/svg/SVGURIReference.h" namespace WebCore { -String StyleBuilderConverter::convertFragmentIdentifier(StyleResolverState& state, CSSValue* value) +namespace { + +static GridLength convertGridTrackBreadth(const StyleResolverState& state, CSSPrimitiveValue* primitiveValue) +{ + if (primitiveValue->getValueID() == CSSValueMinContent) + return Length(MinContent); + + if (primitiveValue->getValueID() == CSSValueMaxContent) + return Length(MaxContent); + + // Fractional unit. + if (primitiveValue->isFlex()) + return GridLength(primitiveValue->getDoubleValue()); + + return primitiveValue->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData()); +} + +} // namespace + +PassRefPtr<StyleReflection> StyleBuilderConverter::convertBoxReflect(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue()) { + ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); + return RenderStyle::initialBoxReflect(); + } + + CSSReflectValue* reflectValue = toCSSReflectValue(value); + RefPtr<StyleReflection> reflection = StyleReflection::create(); + reflection->setDirection(*reflectValue->direction()); + if (reflectValue->offset()) + reflection->setOffset(reflectValue->offset()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData())); + NinePieceImage mask; + mask.setMaskDefaults(); + state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBoxReflect, reflectValue->mask(), mask); + reflection->setMask(mask); + + return reflection.release(); +} + +AtomicString StyleBuilderConverter::convertFragmentIdentifier(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->isURI()) - return SVGURIReference::fragmentIdentifierFromIRIString(primitiveValue->getStringValue(), state.document()); - return String(); + return SVGURIReference::fragmentIdentifierFromIRIString(primitiveValue->getStringValue(), state.element()->treeScope()); + return nullAtom; +} + +EGlyphOrientation StyleBuilderConverter::convertGlyphOrientation(StyleResolverState&, CSSValue* value) +{ + if (!value->isPrimitiveValue()) + return GO_0DEG; + + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_DEG) + return GO_0DEG; + + float angle = fabsf(fmodf(primitiveValue->getFloatValue(), 360.0f)); + + if (angle <= 45.0f || angle > 315.0f) + return GO_0DEG; + if (angle > 45.0f && angle <= 135.0f) + return GO_90DEG; + if (angle > 135.0f && angle <= 225.0f) + return GO_180DEG; + return GO_270DEG; +} + +GridPosition StyleBuilderConverter::convertGridPosition(StyleResolverState&, CSSValue* value) +{ + // We accept the specification's grammar: + // 'auto' | [ <integer> || <custom-ident> ] | [ span && [ <integer> || <custom-ident> ] ] | <custom-ident> + + GridPosition position; + + if (value->isPrimitiveValue()) { + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + // We translate <custom-ident> to <string> during parsing as it + // makes handling it more simple. + if (primitiveValue->isString()) { + position.setNamedGridArea(primitiveValue->getStringValue()); + return position; + } + + ASSERT(primitiveValue->getValueID() == CSSValueAuto); + return position; + } + + CSSValueList* values = toCSSValueList(value); + ASSERT(values->length()); + + bool isSpanPosition = false; + // The specification makes the <integer> optional, in which case it default to '1'. + int gridLineNumber = 1; + String gridLineName; + + CSSValueListIterator it = values; + CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value()); + if (currentValue->getValueID() == CSSValueSpan) { + isSpanPosition = true; + it.advance(); + currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; + } + + if (currentValue && currentValue->isNumber()) { + gridLineNumber = currentValue->getIntValue(); + it.advance(); + currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; + } + + if (currentValue && currentValue->isString()) { + gridLineName = currentValue->getStringValue(); + it.advance(); + } + + ASSERT(!it.hasMore()); + if (isSpanPosition) + position.setSpanPosition(gridLineNumber, gridLineName); + else + position.setExplicitPosition(gridLineNumber, gridLineName); + + return position; +} + +GridTrackSize StyleBuilderConverter::convertGridTrackSize(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue()) + return GridTrackSize(convertGridTrackBreadth(state, toCSSPrimitiveValue(value))); + + CSSFunctionValue* minmaxFunction = toCSSFunctionValue(value); + CSSValueList* arguments = minmaxFunction->arguments(); + ASSERT_WITH_SECURITY_IMPLICATION(arguments->length() == 2); + GridLength minTrackBreadth(convertGridTrackBreadth(state, toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(0)))); + GridLength maxTrackBreadth(convertGridTrackBreadth(state, toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(1)))); + return GridTrackSize(minTrackBreadth, maxTrackBreadth); +} + +bool StyleBuilderConverter::convertGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, OrderedNamedGridLines& orderedNamedGridLines, StyleResolverState& state) +{ + // Handle 'none'. + if (value->isPrimitiveValue()) { + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + return primitiveValue->getValueID() == CSSValueNone; + } + + if (!value->isValueList()) + return false; + + size_t currentNamedGridLine = 0; + for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { + CSSValue* currValue = i.value(); + if (currValue->isGridLineNamesValue()) { + CSSGridLineNamesValue* lineNamesValue = toCSSGridLineNamesValue(currValue); + for (CSSValueListIterator j = lineNamesValue; j.hasMore(); j.advance()) { + String namedGridLine = toCSSPrimitiveValue(j.value())->getStringValue(); + NamedGridLinesMap::AddResult result = namedGridLines.add(namedGridLine, Vector<size_t>()); + result.storedValue->value.append(currentNamedGridLine); + OrderedNamedGridLines::AddResult orderedInsertionResult = orderedNamedGridLines.add(currentNamedGridLine, Vector<String>()); + orderedInsertionResult.storedValue->value.append(namedGridLine); + } + continue; + } + + ++currentNamedGridLine; + trackSizes.append(convertGridTrackSize(state, currValue)); + } + + // The parser should have rejected any <track-list> without any <track-size> as + // this is not conformant to the syntax. + ASSERT(!trackSizes.isEmpty()); + return true; +} + +void StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap& namedGridAreas, NamedGridLinesMap& namedGridLines, GridTrackSizingDirection direction) +{ + NamedGridAreaMap::const_iterator end = namedGridAreas.end(); + for (NamedGridAreaMap::const_iterator it = namedGridAreas.begin(); it != end; ++it) { + GridSpan areaSpan = direction == ForRows ? it->value.rows : it->value.columns; + { + NamedGridLinesMap::AddResult startResult = namedGridLines.add(it->key + "-start", Vector<size_t>()); + startResult.storedValue->value.append(areaSpan.resolvedInitialPosition.toInt()); + std::sort(startResult.storedValue->value.begin(), startResult.storedValue->value.end()); + } + { + NamedGridLinesMap::AddResult endResult = namedGridLines.add(it->key + "-end", Vector<size_t>()); + endResult.storedValue->value.append(areaSpan.resolvedFinalPosition.toInt() + 1); + std::sort(endResult.storedValue->value.begin(), endResult.storedValue->value.end()); + } + } } Length StyleBuilderConverter::convertLength(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); Length result = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); - ASSERT(!result.isUndefined()); result.setQuirk(primitiveValue->isQuirkValue()); return result; } @@ -55,7 +239,6 @@ Length StyleBuilderConverter::convertLengthOrAuto(StyleResolverState& state, CSS { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); Length result = primitiveValue->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData()); - ASSERT(!result.isUndefined()); result.setQuirk(primitiveValue->isQuirkValue()); return result; } @@ -103,6 +286,16 @@ LengthPoint StyleBuilderConverter::convertLengthPoint(StyleResolverState& state, return LengthPoint(x, y); } +LineBoxContain StyleBuilderConverter::convertLineBoxContain(StyleResolverState&, CSSValue* value) +{ + if (value->isPrimitiveValue()) { + ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); + return LineBoxContainNone; + } + + return toCSSLineBoxContainValue(value)->value(); +} + float StyleBuilderConverter::convertNumberOrPercentage(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); @@ -112,6 +305,59 @@ float StyleBuilderConverter::convertNumberOrPercentage(StyleResolverState& state return primitiveValue->getFloatValue() / 100.0f; } +EPaintOrder StyleBuilderConverter::convertPaintOrder(StyleResolverState&, CSSValue* cssPaintOrder) +{ + if (cssPaintOrder->isValueList()) { + int paintOrder = 0; + CSSValueListInspector iter(cssPaintOrder); + for (size_t i = 0; i < iter.length(); i++) { + CSSPrimitiveValue* value = toCSSPrimitiveValue(iter.item(i)); + + EPaintOrderType paintOrderType = PT_NONE; + switch (value->getValueID()) { + case CSSValueFill: + paintOrderType = PT_FILL; + break; + case CSSValueStroke: + paintOrderType = PT_STROKE; + break; + case CSSValueMarkers: + paintOrderType = PT_MARKERS; + break; + default: + ASSERT_NOT_REACHED(); + break; + } + + paintOrder |= (paintOrderType << kPaintOrderBitwidth*i); + } + return (EPaintOrder)paintOrder; + } + + return PO_NORMAL; +} + +PassRefPtr<QuotesData> StyleBuilderConverter::convertQuotes(StyleResolverState&, CSSValue* value) +{ + if (value->isValueList()) { + CSSValueList* list = toCSSValueList(value); + RefPtr<QuotesData> quotes = QuotesData::create(); + for (size_t i = 0; i < list->length(); i += 2) { + CSSValue* first = list->itemWithoutBoundsCheck(i); + // item() returns null if out of bounds so this is safe. + CSSValue* second = list->item(i + 1); + if (!second) + continue; + String startQuote = toCSSPrimitiveValue(first)->getStringValue(); + String endQuote = toCSSPrimitiveValue(second)->getStringValue(); + quotes->addPair(std::make_pair(startQuote, endQuote)); + } + return quotes.release(); + } + // FIXME: We should assert we're a primitive value with valueID = CSSValueNone + return QuotesData::create(); +} + LengthSize StyleBuilderConverter::convertRadius(StyleResolverState& state, CSSValue* value) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); @@ -138,20 +384,17 @@ PassRefPtr<ShadowList> StyleBuilderConverter::convertShadow(StyleResolverState& ShadowDataVector shadows; for (size_t i = 0; i < shadowCount; ++i) { const CSSShadowValue* item = toCSSShadowValue(valueList->item(i)); - int x = item->x->computeLength<int>(state.cssToLengthConversionData()); - int y = item->y->computeLength<int>(state.cssToLengthConversionData()); - int blur = item->blur ? item->blur->computeLength<int>(state.cssToLengthConversionData()) : 0; - int spread = item->spread ? item->spread->computeLength<int>(state.cssToLengthConversionData()) : 0; + float x = item->x->computeLength<float>(state.cssToLengthConversionData()); + float y = item->y->computeLength<float>(state.cssToLengthConversionData()); + float blur = item->blur ? item->blur->computeLength<float>(state.cssToLengthConversionData()) : 0; + float spread = item->spread ? item->spread->computeLength<float>(state.cssToLengthConversionData()) : 0; ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal; Color color; if (item->color) color = state.document().textLinkColors().colorFromPrimitiveValue(item->color.get(), state.style()->color()); else color = state.style()->color(); - - if (!color.isValid()) - color = Color::transparent; - shadows.append(ShadowData(IntPoint(x, y), blur, spread, shadowStyle, color)); + shadows.append(ShadowData(FloatPoint(x, y), blur, spread, shadowStyle, color)); } return ShadowList::adopt(shadows); } @@ -161,14 +404,53 @@ float StyleBuilderConverter::convertSpacing(StyleResolverState& state, CSSValue* CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueNormal) return 0; - if (state.useSVGZoomRules()) - return primitiveValue->computeLength<float>(state.cssToLengthConversionData().copyWithAdjustedZoom(1)); return primitiveValue->computeLength<float>(state.cssToLengthConversionData()); } -SVGLength StyleBuilderConverter::convertSVGLength(StyleResolverState&, CSSValue* value) +PassRefPtr<SVGLengthList> StyleBuilderConverter::convertStrokeDasharray(StyleResolverState&, CSSValue* value) +{ + if (!value->isValueList()) { + return SVGRenderStyle::initialStrokeDashArray(); + } + + CSSValueList* dashes = toCSSValueList(value); + + RefPtr<SVGLengthList> array = SVGLengthList::create(); + size_t length = dashes->length(); + for (size_t i = 0; i < length; ++i) { + CSSValue* currValue = dashes->itemWithoutBoundsCheck(i); + if (!currValue->isPrimitiveValue()) + continue; + + CSSPrimitiveValue* dash = toCSSPrimitiveValue(dashes->itemWithoutBoundsCheck(i)); + array->append(SVGLength::fromCSSPrimitiveValue(dash)); + } + + return array.release(); +} + +Color StyleBuilderConverter::convertSVGColor(StyleResolverState& state, CSSValue* value) +{ + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->isRGBColor()) + return primitiveValue->getRGBA32Value(); + ASSERT(primitiveValue->getValueID() == CSSValueCurrentcolor); + return state.style()->color(); +} + +PassRefPtr<SVGLength> StyleBuilderConverter::convertSVGLength(StyleResolverState&, CSSValue* value) { return SVGLength::fromCSSPrimitiveValue(toCSSPrimitiveValue(value)); } +float StyleBuilderConverter::convertTextStrokeWidth(StyleResolverState& state, CSSValue* value) +{ + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->getValueID()) { + float multiplier = convertLineWidth<float>(state, value); + return CSSPrimitiveValue::create(multiplier / 48, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(state.cssToLengthConversionData()); + } + return primitiveValue->computeLength<float>(state.cssToLengthConversionData()); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h index 12f03ecfdcc..e2f92ccea97 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.h @@ -30,7 +30,9 @@ #include "core/css/CSSValue.h" #include "core/css/resolver/StyleResolverState.h" #include "core/rendering/RenderView.h" +#include "core/rendering/style/QuotesData.h" #include "core/rendering/style/ShadowList.h" +#include "core/rendering/style/StyleReflection.h" #include "core/svg/SVGLength.h" #include "platform/LengthSize.h" @@ -40,20 +42,33 @@ namespace WebCore { class StyleBuilderConverter { public: - static String convertFragmentIdentifier(StyleResolverState&, CSSValue*); + static PassRefPtr<StyleReflection> convertBoxReflect(StyleResolverState&, CSSValue*); + static AtomicString convertFragmentIdentifier(StyleResolverState&, CSSValue*); template <typename T> static T convertComputedLength(StyleResolverState&, CSSValue*); + static EGlyphOrientation convertGlyphOrientation(StyleResolverState&, CSSValue*); + static GridPosition convertGridPosition(StyleResolverState&, CSSValue*); + static GridTrackSize convertGridTrackSize(StyleResolverState&, CSSValue*); template <typename T> static T convertLineWidth(StyleResolverState&, CSSValue*); static Length convertLength(StyleResolverState&, CSSValue*); static Length convertLengthOrAuto(StyleResolverState&, CSSValue*); static Length convertLengthSizing(StyleResolverState&, CSSValue*); static Length convertLengthMaxSizing(StyleResolverState&, CSSValue*); static LengthPoint convertLengthPoint(StyleResolverState&, CSSValue*); + static LineBoxContain convertLineBoxContain(StyleResolverState&, CSSValue*); static float convertNumberOrPercentage(StyleResolverState&, CSSValue*); + static PassRefPtr<QuotesData> convertQuotes(StyleResolverState&, CSSValue*); static LengthSize convertRadius(StyleResolverState&, CSSValue*); + static EPaintOrder convertPaintOrder(StyleResolverState&, CSSValue*); static PassRefPtr<ShadowList> convertShadow(StyleResolverState&, CSSValue*); static float convertSpacing(StyleResolverState&, CSSValue*); template <CSSValueID IdForNone> static AtomicString convertString(StyleResolverState&, CSSValue*); - static SVGLength convertSVGLength(StyleResolverState&, CSSValue*); + static PassRefPtr<SVGLengthList> convertStrokeDasharray(StyleResolverState&, CSSValue*); + static Color convertSVGColor(StyleResolverState&, CSSValue*); + static PassRefPtr<SVGLength> convertSVGLength(StyleResolverState&, CSSValue*); + static float convertTextStrokeWidth(StyleResolverState&, CSSValue*); + + static bool convertGridTrackList(CSSValue*, Vector<GridTrackSize>&, NamedGridLinesMap&, OrderedNamedGridLines&, StyleResolverState&); + static void createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap&, NamedGridLinesMap&, GridTrackSizingDirection); }; template <typename T> @@ -73,8 +88,6 @@ T StyleBuilderConverter::convertLineWidth(StyleResolverState& state, CSSValue* v return 3; if (valueID == CSSValueThick) return 5; - if (primitiveValue->isViewportPercentageLength()) - return intValueForLength(primitiveValue->viewportPercentageLength(), 0, state.document().renderView()); if (valueID == CSSValueInvalid) { // Any original result that was >= 1 should not be allowed to fall below 1. // This keeps border lines from vanishing. @@ -96,7 +109,7 @@ AtomicString StyleBuilderConverter::convertString(StyleResolverState&, CSSValue* CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == IdForNone) return nullAtom; - return primitiveValue->getStringValue(); + return AtomicString(primitiveValue->getStringValue()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp index 8f239d8cb64..c9e9af60fb0 100755..100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp @@ -37,28 +37,25 @@ */ #include "config.h" -#include "StyleBuilderFunctions.h" -#include "CSSPropertyNames.h" -#include "CSSValueKeywords.h" -#include "StylePropertyShorthand.h" +#include "core/CSSPropertyNames.h" +#include "core/CSSValueKeywords.h" +#include "core/StyleBuilderFunctions.h" +#include "core/StylePropertyShorthand.h" #include "core/css/BasicShapeFunctions.h" #include "core/css/CSSAspectRatioValue.h" #include "core/css/CSSCursorImageValue.h" #include "core/css/CSSFontValue.h" -#include "core/css/CSSFunctionValue.h" #include "core/css/CSSGradientValue.h" -#include "core/css/CSSGridLineNamesValue.h" -#include "core/css/CSSGridTemplateValue.h" +#include "core/css/CSSGridTemplateAreasValue.h" #include "core/css/CSSHelper.h" #include "core/css/CSSImageSetValue.h" #include "core/css/CSSLineBoxContainValue.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSProperty.h" -#include "core/css/CSSReflectValue.h" -#include "core/css/CSSVariableValue.h" #include "core/css/Counter.h" +#include "core/css/Pair.h" #include "core/css/Rect.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRule.h" @@ -67,18 +64,14 @@ #include "core/css/resolver/FontBuilder.h" #include "core/css/resolver/StyleBuilder.h" #include "core/css/resolver/TransformBuilder.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "core/rendering/style/CounterContent.h" -#include "core/rendering/style/CursorList.h" #include "core/rendering/style/QuotesData.h" #include "core/rendering/style/RenderStyle.h" #include "core/rendering/style/RenderStyleConstants.h" #include "core/rendering/style/SVGRenderStyle.h" -#include "core/rendering/style/SVGRenderStyleDefs.h" #include "core/rendering/style/StyleGeneratedImage.h" -#include "core/svg/SVGColor.h" -#include "core/svg/SVGPaint.h" #include "platform/fonts/FontDescription.h" #include "wtf/MathExtras.h" #include "wtf/StdLibExtras.h" @@ -86,6 +79,58 @@ namespace WebCore { +namespace { + +static inline bool isValidVisitedLinkProperty(CSSPropertyID id) +{ + switch (id) { + case CSSPropertyBackgroundColor: + case CSSPropertyBorderLeftColor: + case CSSPropertyBorderRightColor: + case CSSPropertyBorderTopColor: + case CSSPropertyBorderBottomColor: + case CSSPropertyColor: + case CSSPropertyFill: + case CSSPropertyOutlineColor: + case CSSPropertyStroke: + case CSSPropertyTextDecorationColor: + case CSSPropertyWebkitColumnRuleColor: + case CSSPropertyWebkitTextEmphasisColor: + case CSSPropertyWebkitTextFillColor: + case CSSPropertyWebkitTextStrokeColor: + return true; + default: + return false; + } +} + +} // namespace + +void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value) +{ + ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id); + + bool isInherit = state.parentNode() && value->isInheritedValue(); + bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue()); + + ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit + ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle()) + + if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) { + // Limit the properties that can be applied to only the ones honored by :visited. + return; + } + + CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0; + if (primitiveValue && primitiveValue->getValueID() == CSSValueCurrentcolor) + state.style()->setHasCurrentColor(); + + if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id)) + state.parentStyle()->setHasExplicitlyInheritedProperties(); + + StyleBuilder::applyProperty(id, state, value, isInitial, isInherit); +} + static Length clipConvertToLength(StyleResolverState& state, CSSPrimitiveValue* value) { return value->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData()); @@ -108,22 +153,54 @@ void StyleBuilderFunctions::applyInheritCSSPropertyClip(StyleResolverState& stat void StyleBuilderFunctions::applyValueCSSPropertyClip(StyleResolverState& state, CSSValue* value) { - if (!value->isPrimitiveValue()) - return; - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (Rect* rect = primitiveValue->getRectValue()) { - Length top = clipConvertToLength(state, rect->top()); - Length right = clipConvertToLength(state, rect->right()); - Length bottom = clipConvertToLength(state, rect->bottom()); - Length left = clipConvertToLength(state, rect->left()); - state.style()->setClip(top, right, bottom, left); - state.style()->setHasClip(true); - } else if (primitiveValue->getValueID() == CSSValueAuto) { + if (primitiveValue->getValueID() == CSSValueAuto) { state.style()->setClip(Length(), Length(), Length(), Length()); state.style()->setHasClip(false); + return; + } + + Rect* rect = primitiveValue->getRectValue(); + Length top = clipConvertToLength(state, rect->top()); + Length right = clipConvertToLength(state, rect->right()); + Length bottom = clipConvertToLength(state, rect->bottom()); + Length left = clipConvertToLength(state, rect->left()); + state.style()->setClip(top, right, bottom, left); + state.style()->setHasClip(true); +} + +void StyleBuilderFunctions::applyInitialCSSPropertyColor(StyleResolverState& state) +{ + Color color = RenderStyle::initialColor(); + if (state.applyPropertyToRegularStyle()) + state.style()->setColor(color); + if (state.applyPropertyToVisitedLinkStyle()) + state.style()->setVisitedLinkColor(color); +} + +void StyleBuilderFunctions::applyInheritCSSPropertyColor(StyleResolverState& state) +{ + Color color = state.parentStyle()->color(); + if (state.applyPropertyToRegularStyle()) + state.style()->setColor(color); + if (state.applyPropertyToVisitedLinkStyle()) + state.style()->setVisitedLinkColor(color); +} + +void StyleBuilderFunctions::applyValueCSSPropertyColor(StyleResolverState& state, CSSValue* value) +{ + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + // As per the spec, 'color: currentColor' is treated as 'color: inherit' + if (primitiveValue->getValueID() == CSSValueCurrentcolor) { + applyInheritCSSPropertyColor(state); + return; } + + if (state.applyPropertyToRegularStyle()) + state.style()->setColor(state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color())); + if (state.applyPropertyToVisitedLinkStyle()) + state.style()->setVisitedLinkColor(state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color(), true)); } void StyleBuilderFunctions::applyInitialCSSPropertyCursor(StyleResolverState& state) @@ -152,16 +229,12 @@ void StyleBuilderFunctions::applyValueCSSPropertyCursor(StyleResolverState& stat if (image->updateIfSVGCursorIsUsed(state.element())) // Elements with SVG cursors are not allowed to share style. state.style()->setUnique(); state.style()->addCursor(state.styleImage(CSSPropertyCursor, image), image->hotSpot()); - } else if (item->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(item); - if (primitiveValue->isValueID()) - state.style()->setCursor(*primitiveValue); + } else { + state.style()->setCursor(*toCSSPrimitiveValue(item)); } } - } else if (value->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (primitiveValue->isValueID() && state.style()->cursor() != ECursor(*primitiveValue)) - state.style()->setCursor(*primitiveValue); + } else { + state.style()->setCursor(*toCSSPrimitiveValue(value)); } } @@ -190,20 +263,15 @@ void StyleBuilderFunctions::applyInheritCSSPropertyDisplay(StyleResolverState& s void StyleBuilderFunctions::applyValueCSSPropertyDisplay(StyleResolverState& state, CSSValue* value) { - if (!value->isPrimitiveValue()) - return; - EDisplay display = *toCSSPrimitiveValue(value); - if (!isValidDisplayValue(state, display)) return; - state.style()->setDisplay(display); } void StyleBuilderFunctions::applyInitialCSSPropertyFontFamily(StyleResolverState& state) { - state.fontBuilder().setFontFamilyInitial(state.style()->effectiveZoom()); + state.fontBuilder().setFontFamilyInitial(); } void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState& state) @@ -213,22 +281,22 @@ void StyleBuilderFunctions::applyInheritCSSPropertyFontFamily(StyleResolverState void StyleBuilderFunctions::applyValueCSSPropertyFontFamily(StyleResolverState& state, CSSValue* value) { - state.fontBuilder().setFontFamilyValue(value, state.style()->effectiveZoom()); + state.fontBuilder().setFontFamilyValue(value); } void StyleBuilderFunctions::applyInitialCSSPropertyFontSize(StyleResolverState& state) { - state.fontBuilder().setFontSizeInitial(state.style()->effectiveZoom()); + state.fontBuilder().setFontSizeInitial(); } void StyleBuilderFunctions::applyInheritCSSPropertyFontSize(StyleResolverState& state) { - state.fontBuilder().setFontSizeInherit(state.parentFontDescription(), state.style()->effectiveZoom()); + state.fontBuilder().setFontSizeInherit(state.parentFontDescription()); } void StyleBuilderFunctions::applyValueCSSPropertyFontSize(StyleResolverState& state, CSSValue* value) { - state.fontBuilder().setFontSizeValue(value, state.parentStyle(), state.rootElementStyle(), state.style()->effectiveZoom()); + state.fontBuilder().setFontSizeValue(value, state.parentStyle(), state.rootElementStyle()); } void StyleBuilderFunctions::applyInitialCSSPropertyFontWeight(StyleResolverState& state) @@ -243,17 +311,17 @@ void StyleBuilderFunctions::applyInheritCSSPropertyFontWeight(StyleResolverState void StyleBuilderFunctions::applyValueCSSPropertyFontWeight(StyleResolverState& state, CSSValue* value) { - if (!value->isPrimitiveValue()) - return; CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); switch (primitiveValue->getValueID()) { case CSSValueInvalid: ASSERT_NOT_REACHED(); break; case CSSValueBolder: + state.fontBuilder().setWeight(state.parentStyle()->fontDescription().weight()); state.fontBuilder().setWeightBolder(); break; case CSSValueLighter: + state.fontBuilder().setWeight(state.parentStyle()->fontDescription().weight()); state.fontBuilder().setWeightLighter(); break; default: @@ -261,11 +329,53 @@ void StyleBuilderFunctions::applyValueCSSPropertyFontWeight(StyleResolverState& } } -void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value) +void StyleBuilderFunctions::applyValueCSSPropertyGlyphOrientationVertical(StyleResolverState& state, CSSValue* value) { - if (!value->isPrimitiveValue()) + if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueAuto) + state.style()->accessSVGStyle()->setGlyphOrientationVertical(GO_AUTO); + else + state.style()->accessSVGStyle()->setGlyphOrientationVertical(StyleBuilderConverter::convertGlyphOrientation(state, value)); +} + +void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(StyleResolverState& state) +{ + state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea()); + state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount()); + state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount()); +} + +void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(StyleResolverState& state) +{ + state.style()->setNamedGridArea(state.parentStyle()->namedGridArea()); + state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount()); + state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount()); +} + +void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue()) { + // FIXME: Shouldn't we clear the grid-area values + ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); return; + } + CSSGridTemplateAreasValue* gridTemplateAreasValue = toCSSGridTemplateAreasValue(value); + const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue->gridAreaMap(); + + NamedGridLinesMap namedGridColumnLines = state.style()->namedGridColumnLines(); + NamedGridLinesMap namedGridRowLines = state.style()->namedGridRowLines(); + StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns); + StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows); + state.style()->setNamedGridColumnLines(namedGridColumnLines); + state.style()->setNamedGridRowLines(namedGridRowLines); + + state.style()->setNamedGridArea(newNamedGridAreas); + state.style()->setNamedGridAreaRowCount(gridTemplateAreasValue->rowCount()); + state.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue->columnCount()); +} + +void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& state, CSSValue* value) +{ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); Length lineHeight; @@ -273,18 +383,16 @@ void StyleBuilderFunctions::applyValueCSSPropertyLineHeight(StyleResolverState& lineHeight = RenderStyle::initialLineHeight(); } else if (primitiveValue->isLength()) { float multiplier = state.style()->effectiveZoom(); - if (Frame* frame = state.document().frame()) + if (LocalFrame* frame = state.document().frame()) multiplier *= frame->textZoomFactor(); lineHeight = primitiveValue->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier)); } else if (primitiveValue->isPercentage()) { lineHeight = Length((state.style()->computedFontSize() * primitiveValue->getIntValue()) / 100.0, Fixed); } else if (primitiveValue->isNumber()) { lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent); - } else if (primitiveValue->isViewportPercentageLength()) { - lineHeight = primitiveValue->viewportPercentageLength(); } else if (primitiveValue->isCalculated()) { double multiplier = state.style()->effectiveZoom(); - if (Frame* frame = state.document().frame()) + if (LocalFrame* frame = state.document().frame()) multiplier *= frame->textZoomFactor(); Length zoomedLength = Length(primitiveValue->cssCalcValue()->toCalcValue(state.cssToLengthConversionData().copyWithAdjustedZoom(multiplier))); lineHeight = Length(valueForLength(zoomedLength, state.style()->fontSize()), Fixed); @@ -320,20 +428,13 @@ void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(StyleResolverState void StyleBuilderFunctions::applyValueCSSPropertyResize(StyleResolverState& state, CSSValue* value) { - if (!value->isPrimitiveValue()) - return; - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); EResize r = RESIZE_NONE; - switch (primitiveValue->getValueID()) { - case 0: - return; - case CSSValueAuto: + if (primitiveValue->getValueID() == CSSValueAuto) { if (Settings* settings = state.document().settings()) r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE; - break; - default: + } else { r = *primitiveValue; } state.style()->setResize(r); @@ -439,7 +540,7 @@ void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, height = second->computeLength<Length>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); } else { // <page-size> <orientation> - // The value order is guaranteed. See CSSParser::parseSizeParameter. + // The value order is guaranteed. See BisonCSSParser::parseSizeParameter. if (!getPageSizeFromName(first, second, width, height)) return; } @@ -519,12 +620,14 @@ void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(StyleResolverState { state.style()->setTextIndent(state.parentStyle()->textIndent()); state.style()->setTextIndentLine(state.parentStyle()->textIndentLine()); + state.style()->setTextIndentType(state.parentStyle()->textIndentType()); } void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(StyleResolverState& state) { state.style()->setTextIndent(RenderStyle::initialTextIndent()); state.style()->setTextIndentLine(RenderStyle::initialTextIndentLine()); + state.style()->setTextIndentType(RenderStyle::initialTextIndentType()); } void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& state, CSSValue* value) @@ -532,23 +635,155 @@ void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(StyleResolverState& if (!value->isValueList()) return; - // [ <length> | <percentage> ] each-line - // The order is guaranteed. See CSSParser::parseTextIndent. - // The second value, each-line is handled only when css3TextEnabled() returns true. + Length lengthOrPercentageValue; + TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine(); + TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType(); + + for (CSSValueListIterator i(value); i.hasMore(); i.advance()) { + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); + if (!primitiveValue->getValueID()) + lengthOrPercentageValue = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); + else if (primitiveValue->getValueID() == CSSValueEachLine) + textIndentLineValue = TextIndentEachLine; + else if (primitiveValue->getValueID() == CSSValueHanging) + textIndentTypeValue = TextIndentHanging; + else + ASSERT_NOT_REACHED(); + } - CSSValueList* valueList = toCSSValueList(value); - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(valueList->itemWithoutBoundsCheck(0)); - Length lengthOrPercentageValue = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); - ASSERT(!lengthOrPercentageValue.isUndefined()); state.style()->setTextIndent(lengthOrPercentageValue); + state.style()->setTextIndentLine(textIndentLineValue); + state.style()->setTextIndentType(textIndentTypeValue); +} + +void StyleBuilderFunctions::applyValueCSSPropertyTransform(StyleResolverState& state, CSSValue* value) +{ + TransformOperations operations; + TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations); + state.style()->setTransform(operations); +} + +void StyleBuilderFunctions::applyInitialCSSPropertyTransformOrigin(StyleResolverState& state) +{ + applyInitialCSSPropertyWebkitTransformOriginX(state); + applyInitialCSSPropertyWebkitTransformOriginY(state); + applyInitialCSSPropertyWebkitTransformOriginZ(state); +} + +void StyleBuilderFunctions::applyInheritCSSPropertyTransformOrigin(StyleResolverState& state) +{ + applyInheritCSSPropertyWebkitTransformOriginX(state); + applyInheritCSSPropertyWebkitTransformOriginY(state); + applyInheritCSSPropertyWebkitTransformOriginZ(state); +} + +void StyleBuilderFunctions::applyValueCSSPropertyTransformOrigin(StyleResolverState& state, CSSValue* value) +{ + CSSValueList* list = toCSSValueList(value); + ASSERT(list->length() == 3); + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); + if (primitiveValue->isValueID()) { + switch (primitiveValue->getValueID()) { + case CSSValueLeft: + state.style()->setTransformOriginX(Length(0, Percent)); + break; + case CSSValueRight: + state.style()->setTransformOriginX(Length(100, Percent)); + break; + case CSSValueCenter: + state.style()->setTransformOriginX(Length(50, Percent)); + break; + default: + ASSERT_NOT_REACHED(); + } + } else { + state.style()->setTransformOriginX(StyleBuilderConverter::convertLength(state, primitiveValue)); + } + + primitiveValue = toCSSPrimitiveValue(list->item(1)); + if (primitiveValue->isValueID()) { + switch (primitiveValue->getValueID()) { + case CSSValueTop: + state.style()->setTransformOriginY(Length(0, Percent)); + break; + case CSSValueBottom: + state.style()->setTransformOriginY(Length(100, Percent)); + break; + case CSSValueCenter: + state.style()->setTransformOriginY(Length(50, Percent)); + break; + default: + ASSERT_NOT_REACHED(); + } + } else { + state.style()->setTransformOriginY(StyleBuilderConverter::convertLength(state, primitiveValue)); + } + + primitiveValue = toCSSPrimitiveValue(list->item(2)); + state.style()->setTransformOriginZ(StyleBuilderConverter::convertComputedLength<float>(state, primitiveValue)); +} + +void StyleBuilderFunctions::applyInitialCSSPropertyPerspectiveOrigin(StyleResolverState& state) +{ + applyInitialCSSPropertyWebkitPerspectiveOriginX(state); + applyInitialCSSPropertyWebkitPerspectiveOriginY(state); +} - ASSERT(valueList->length() <= 2); - CSSPrimitiveValue* eachLineValue = toCSSPrimitiveValue(valueList->item(1)); - if (eachLineValue) { - ASSERT(eachLineValue->getValueID() == CSSValueEachLine); - state.style()->setTextIndentLine(TextIndentEachLine); - } else - state.style()->setTextIndentLine(TextIndentFirstLine); +void StyleBuilderFunctions::applyInheritCSSPropertyPerspectiveOrigin(StyleResolverState& state) +{ + applyInheritCSSPropertyWebkitPerspectiveOriginX(state); + applyInheritCSSPropertyWebkitPerspectiveOriginY(state); +} + +void StyleBuilderFunctions::applyValueCSSPropertyPerspectiveOrigin(StyleResolverState& state, CSSValue* value) +{ + CSSValueList* list = toCSSValueList(value); + ASSERT(list->length() == 2); + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); + if (primitiveValue->isValueID()) { + switch (primitiveValue->getValueID()) { + case CSSValueLeft: + state.style()->setPerspectiveOriginX(Length(0, Percent)); + break; + case CSSValueRight: + state.style()->setPerspectiveOriginX(Length(100, Percent)); + break; + case CSSValueCenter: + state.style()->setPerspectiveOriginX(Length(50, Percent)); + break; + default: + ASSERT_NOT_REACHED(); + } + } else { + state.style()->setPerspectiveOriginX(StyleBuilderConverter::convertLength(state, primitiveValue)); + } + + primitiveValue = toCSSPrimitiveValue(list->item(1)); + if (primitiveValue->isValueID()) { + switch (primitiveValue->getValueID()) { + case CSSValueTop: + state.style()->setPerspectiveOriginY(Length(0, Percent)); + break; + case CSSValueBottom: + state.style()->setPerspectiveOriginY(Length(100, Percent)); + break; + case CSSValueCenter: + state.style()->setPerspectiveOriginY(Length(50, Percent)); + break; + default: + ASSERT_NOT_REACHED(); + } + } else { + state.style()->setPerspectiveOriginY(StyleBuilderConverter::convertLength(state, primitiveValue)); + } +} + +void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(StyleResolverState& state) +{ + EVerticalAlign verticalAlign = state.parentStyle()->verticalAlign(); + state.style()->setVerticalAlign(verticalAlign); + if (verticalAlign == LENGTH) + state.style()->setVerticalAlignLength(state.parentStyle()->verticalAlignLength()); } void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverState& state, CSSValue* value) @@ -558,8 +793,10 @@ void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(StyleResolverStat CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - if (primitiveValue->getValueID()) - return state.style()->setVerticalAlign(*primitiveValue); + if (primitiveValue->getValueID()) { + state.style()->setVerticalAlign(*primitiveValue); + return; + } state.style()->setVerticalAlignLength(primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData())); } @@ -657,29 +894,36 @@ void StyleBuilderFunctions::applyValueCSSPropertyWebkitClipPath(StyleResolverSta if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->getValueID() == CSSValueNone) { - state.style()->setClipPath(0); + state.style()->setClipPath(nullptr); } else if (primitiveValue->isShape()) { state.style()->setClipPath(ShapeClipPathOperation::create(basicShapeForValue(state, primitiveValue->getShapeValue()))); } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_URI) { String cssURLValue = primitiveValue->getStringValue(); KURL url = state.document().completeURL(cssURLValue); // FIXME: It doesn't work with forward or external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=90405) - state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, url.fragmentIdentifier())); + state.style()->setClipPath(ReferenceClipPathOperation::create(cssURLValue, AtomicString(url.fragmentIdentifier()))); } } } -void StyleBuilderFunctions::applyInitialCSSPropertyWebkitFontVariantLigatures(StyleResolverState& state) +void StyleBuilderFunctions::applyValueCSSPropertyWebkitFilter(StyleResolverState& state, CSSValue* value) +{ + FilterOperations operations; + if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state)) + state.style()->setFilter(operations); +} + +void StyleBuilderFunctions::applyInitialCSSPropertyFontVariantLigatures(StyleResolverState& state) { state.fontBuilder().setFontVariantLigaturesInitial(); } -void StyleBuilderFunctions::applyInheritCSSPropertyWebkitFontVariantLigatures(StyleResolverState& state) +void StyleBuilderFunctions::applyInheritCSSPropertyFontVariantLigatures(StyleResolverState& state) { state.fontBuilder().setFontVariantLigaturesInherit(state.parentFontDescription()); } -void StyleBuilderFunctions::applyValueCSSPropertyWebkitFontVariantLigatures(StyleResolverState& state, CSSValue* value) +void StyleBuilderFunctions::applyValueCSSPropertyFontVariantLigatures(StyleResolverState& state, CSSValue* value) { state.fontBuilder().setFontVariantLigaturesValue(value); } @@ -705,9 +949,8 @@ void StyleBuilderFunctions::applyValueCSSPropertyInternalMarqueeIncrement(StyleR break; } } else { - Length marqueeLength = primitiveValue ? primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()) : Length(Undefined); - if (!marqueeLength.isUndefined()) - state.style()->setMarqueeIncrement(marqueeLength); + Length marqueeLength = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()); + state.style()->setMarqueeIncrement(marqueeLength); } } @@ -757,6 +1000,14 @@ void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspectiveOrigin(StyleRe ASSERT_NOT_REACHED(); } +void StyleBuilderFunctions::applyValueCSSPropertyWebkitTapHighlightColor(StyleResolverState& state, CSSValue* value) +{ + if (!value->isPrimitiveValue()) + return; + Color color = state.document().textLinkColors().colorFromPrimitiveValue(toCSSPrimitiveValue(value), state.style()->color()); + state.style()->setTapHighlightColor(color); +} + void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state) { state.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill()); @@ -833,1355 +1084,310 @@ void StyleBuilderFunctions::applyValueCSSPropertyTextUnderlinePosition(StyleReso state.style()->setTextUnderlinePosition(static_cast<TextUnderlinePosition>(t)); } -// Everything below this line is from the old StyleResolver::applyProperty -// and eventually needs to move into new StyleBuilderFunctions calls intead. - -#define HANDLE_INHERIT(prop, Prop) \ -if (isInherit) { \ - state.style()->set##Prop(state.parentStyle()->prop()); \ - return; \ -} - -#define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \ -HANDLE_INHERIT(prop, Prop) \ -if (isInitial) { \ - state.style()->set##Prop(RenderStyle::initial##Prop()); \ - return; \ -} - -#define HANDLE_SVG_INHERIT(prop, Prop) \ -if (isInherit) { \ - state.style()->accessSVGStyle()->set##Prop(state.parentStyle()->svgStyle()->prop()); \ - return; \ +void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(StyleResolverState& state) +{ + state.style()->setWillChangeContents(false); + state.style()->setWillChangeScrollPosition(false); + state.style()->setWillChangeProperties(Vector<CSSPropertyID>()); + state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents()); } -#define HANDLE_SVG_INHERIT_AND_INITIAL(prop, Prop) \ -HANDLE_SVG_INHERIT(prop, Prop) \ -if (isInitial) { \ - state.style()->accessSVGStyle()->set##Prop(SVGRenderStyle::initial##Prop()); \ - return; \ +void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(StyleResolverState& state) +{ + state.style()->setWillChangeContents(state.parentStyle()->willChangeContents()); + state.style()->setWillChangeScrollPosition(state.parentStyle()->willChangeScrollPosition()); + state.style()->setWillChangeProperties(state.parentStyle()->willChangeProperties()); + state.style()->setSubtreeWillChangeContents(state.parentStyle()->subtreeWillChangeContents()); } -static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolverState& state, GridLength& workingLength) +void StyleBuilderFunctions::applyValueCSSPropertyWillChange(StyleResolverState& state, CSSValue* value) { - if (primitiveValue->getValueID() == CSSValueMinContent) { - workingLength = Length(MinContent); - return true; - } + ASSERT(value->isValueList()); + bool willChangeContents = false; + bool willChangeScrollPosition = false; + Vector<CSSPropertyID> willChangeProperties; - if (primitiveValue->getValueID() == CSSValueMaxContent) { - workingLength = Length(MaxContent); - return true; - } - - if (primitiveValue->isFlex()) { - // Fractional unit. - workingLength.setFlex(primitiveValue->getDoubleValue()); - return true; + for (CSSValueListIterator i(value); i.hasMore(); i.advance()) { + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value()); + if (CSSPropertyID propertyID = primitiveValue->getPropertyID()) + willChangeProperties.append(propertyID); + else if (primitiveValue->getValueID() == CSSValueContents) + willChangeContents = true; + else if (primitiveValue->getValueID() == CSSValueScrollPosition) + willChangeScrollPosition = true; + else + ASSERT_NOT_REACHED(); } - - workingLength = primitiveValue->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData()); - if (workingLength.length().isUndefined()) - return false; - - if (primitiveValue->isLength()) - workingLength.length().setQuirk(primitiveValue->isQuirkValue()); - - return true; + state.style()->setWillChangeContents(willChangeContents); + state.style()->setWillChangeScrollPosition(willChangeScrollPosition); + state.style()->setWillChangeProperties(willChangeProperties); + state.style()->setSubtreeWillChangeContents(willChangeContents || state.parentStyle()->subtreeWillChangeContents()); } -static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const StyleResolverState& state) +void StyleBuilderFunctions::applyInitialCSSPropertyContent(StyleResolverState& state) { - if (value->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - GridLength workingLength; - if (!createGridTrackBreadth(primitiveValue, state, workingLength)) - return false; - - trackSize.setLength(workingLength); - return true; - } - - CSSFunctionValue* minmaxFunction = toCSSFunctionValue(value); - CSSValueList* arguments = minmaxFunction->arguments(); - ASSERT_WITH_SECURITY_IMPLICATION(arguments->length() == 2); - GridLength minTrackBreadth; - GridLength maxTrackBreadth; - if (!createGridTrackBreadth(toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(0)), state, minTrackBreadth) || !createGridTrackBreadth(toCSSPrimitiveValue(arguments->itemWithoutBoundsCheck(1)), state, maxTrackBreadth)) - return false; + state.style()->clearContent(); +} - trackSize.setMinMax(minTrackBreadth, maxTrackBreadth); - return true; +void StyleBuilderFunctions::applyInheritCSSPropertyContent(StyleResolverState&) +{ + // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This + // note is a reminder that eventually "inherit" needs to be supported. } -static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, OrderedNamedGridLines& orderedNamedGridLines, const StyleResolverState& state) +void StyleBuilderFunctions::applyValueCSSPropertyContent(StyleResolverState& state, CSSValue* value) { - // Handle 'none'. - if (value->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - return primitiveValue->getValueID() == CSSValueNone; - } + // list of string, uri, counter, attr, i if (!value->isValueList()) - return false; + return; - size_t currentNamedGridLine = 0; + bool didSet = false; for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { - CSSValue* currValue = i.value(); - if (currValue->isGridLineNamesValue()) { - CSSGridLineNamesValue* lineNamesValue = toCSSGridLineNamesValue(currValue); - for (CSSValueListIterator j = lineNamesValue; j.hasMore(); j.advance()) { - String namedGridLine = toCSSPrimitiveValue(j.value())->getStringValue(); - NamedGridLinesMap::AddResult result = namedGridLines.add(namedGridLine, Vector<size_t>()); - result.iterator->value.append(currentNamedGridLine); - OrderedNamedGridLines::AddResult orderedInsertionResult = orderedNamedGridLines.add(currentNamedGridLine, Vector<String>()); - orderedInsertionResult.iterator->value.append(namedGridLine); - } - continue; + CSSValue* item = i.value(); + if (item->isImageGeneratorValue()) { + if (item->isGradientValue()) + state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet); + else + state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet); + didSet = true; + } else if (item->isImageSetValue()) { + state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet); + didSet = true; } - ++currentNamedGridLine; - GridTrackSize trackSize; - if (!createGridTrackSize(currValue, trackSize, state)) - return false; - - trackSizes.append(trackSize); - } - - // The parser should have rejected any <track-list> without any <track-size> as - // this is not conformant to the syntax. - ASSERT(!trackSizes.isEmpty()); - return true; -} - -static bool createGridPosition(CSSValue* value, GridPosition& position) -{ - // We accept the specification's grammar: - // 'auto' | [ <integer> || <string> ] | [ span && [ <integer> || string ] ] | <ident> - - if (value->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - // We translate <ident> to <string> during parsing as it - // makes handling it more simple. - if (primitiveValue->isString()) { - position.setNamedGridArea(primitiveValue->getStringValue()); - return true; + if (item->isImageValue()) { + state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(state.document(), CSSPropertyContent, toCSSImageValue(item)), didSet); + didSet = true; + continue; } - ASSERT(primitiveValue->getValueID() == CSSValueAuto); - return true; - } - - CSSValueList* values = toCSSValueList(value); - ASSERT(values->length()); - - bool isSpanPosition = false; - // The specification makes the <integer> optional, in which case it default to '1'. - int gridLineNumber = 1; - String gridLineName; - - CSSValueListIterator it = values; - CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value()); - if (currentValue->getValueID() == CSSValueSpan) { - isSpanPosition = true; - it.advance(); - currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; - } - - if (currentValue && currentValue->isNumber()) { - gridLineNumber = currentValue->getIntValue(); - it.advance(); - currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; - } - - if (currentValue && currentValue->isString()) { - gridLineName = currentValue->getStringValue(); - it.advance(); - } - - ASSERT(!it.hasMore()); - if (isSpanPosition) - position.setSpanPosition(gridLineNumber, gridLineName); - else - position.setExplicitPosition(gridLineNumber, gridLineName); - - return true; -} - -static bool degreeToGlyphOrientation(CSSPrimitiveValue* primitiveValue, EGlyphOrientation& orientation) -{ - if (!primitiveValue) - return false; - - if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_DEG) - return false; - - float angle = fabsf(fmodf(primitiveValue->getFloatValue(), 360.0f)); - - if (angle <= 45.0f || angle > 315.0f) { - orientation = GO_0DEG; - return true; - } - if (angle > 45.0f && angle <= 135.0f) { - orientation = GO_90DEG; - return true; - } - if (angle > 135.0f && angle <= 225.0f) { - orientation = GO_180DEG; - return true; - } - orientation = GO_270DEG; - return true; -} - -static Color colorFromSVGColorCSSValue(SVGColor* svgColor, const Color& fgColor) -{ - Color color; - if (svgColor->colorType() == SVGColor::SVG_COLORTYPE_CURRENTCOLOR) - color = fgColor; - else - color = svgColor->color(); - return color; -} + if (!item->isPrimitiveValue()) + continue; -static EPaintOrder paintOrderFlattened(CSSValue* cssPaintOrder) -{ - if (cssPaintOrder->isValueList()) { - int paintOrder = 0; - CSSValueListInspector iter(cssPaintOrder); - for (size_t i = 0; i < iter.length(); i++) { - CSSPrimitiveValue* value = toCSSPrimitiveValue(iter.item(i)); + CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item); - EPaintOrderType paintOrderType = PT_NONE; - switch (value->getValueID()) { - case CSSValueFill: - paintOrderType = PT_FILL; + if (contentValue->isString()) { + state.style()->setContent(contentValue->getStringValue().impl(), didSet); + didSet = true; + } else if (contentValue->isAttr()) { + // FIXME: Can a namespace be specified for an attr(foo)? + if (state.style()->styleType() == NOPSEUDO) + state.style()->setUnique(); + else + state.parentStyle()->setUnique(); + QualifiedName attr(nullAtom, AtomicString(contentValue->getStringValue()), nullAtom); + const AtomicString& value = state.element()->getAttribute(attr); + state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet); + didSet = true; + // register the fact that the attribute value affects the style + state.contentAttrValues().append(attr.localName()); + } else if (contentValue->isCounter()) { + Counter* counterValue = contentValue->getCounterValue(); + EListStyleType listStyleType = NoneListStyle; + CSSValueID listStyleIdent = counterValue->listStyleIdent(); + if (listStyleIdent != CSSValueNone) + listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); + OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator()))); + state.style()->setContent(counter.release(), didSet); + didSet = true; + } else { + switch (contentValue->getValueID()) { + case CSSValueOpenQuote: + state.style()->setContent(OPEN_QUOTE, didSet); + didSet = true; break; - case CSSValueStroke: - paintOrderType = PT_STROKE; + case CSSValueCloseQuote: + state.style()->setContent(CLOSE_QUOTE, didSet); + didSet = true; break; - case CSSValueMarkers: - paintOrderType = PT_MARKERS; + case CSSValueNoOpenQuote: + state.style()->setContent(NO_OPEN_QUOTE, didSet); + didSet = true; break; - default: - ASSERT_NOT_REACHED(); + case CSSValueNoCloseQuote: + state.style()->setContent(NO_CLOSE_QUOTE, didSet); + didSet = true; break; + default: + // normal and none do not have any effect. + { } } - - paintOrder |= (paintOrderType << kPaintOrderBitwidth*i); } - return (EPaintOrder)paintOrder; } - - return PO_NORMAL; + if (!didSet) + state.style()->clearContent(); } -static inline bool isValidVisitedLinkProperty(CSSPropertyID id) +void StyleBuilderFunctions::applyInitialCSSPropertyFont(StyleResolverState&) { - switch (id) { - case CSSPropertyBackgroundColor: - case CSSPropertyBorderLeftColor: - case CSSPropertyBorderRightColor: - case CSSPropertyBorderTopColor: - case CSSPropertyBorderBottomColor: - case CSSPropertyColor: - case CSSPropertyFill: - case CSSPropertyOutlineColor: - case CSSPropertyStroke: - case CSSPropertyTextDecorationColor: - case CSSPropertyWebkitColumnRuleColor: - case CSSPropertyWebkitTextEmphasisColor: - case CSSPropertyWebkitTextFillColor: - case CSSPropertyWebkitTextStrokeColor: - return true; - default: - break; - } - - return false; + ASSERT_NOT_REACHED(); } -static bool hasVariableReference(CSSValue* value) +void StyleBuilderFunctions::applyInheritCSSPropertyFont(StyleResolverState&) { - if (value->isPrimitiveValue()) { - CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); - return primitiveValue->hasVariableReference(); - } - - if (value->isCalcValue()) - return toCSSCalcValue(value)->hasVariableReference(); - - if (value->isReflectValue()) { - CSSReflectValue* reflectValue = toCSSReflectValue(value); - CSSPrimitiveValue* direction = reflectValue->direction(); - CSSPrimitiveValue* offset = reflectValue->offset(); - CSSValue* mask = reflectValue->mask(); - return (direction && hasVariableReference(direction)) || (offset && hasVariableReference(offset)) || (mask && hasVariableReference(mask)); - } - - for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { - if (hasVariableReference(i.value())) - return true; - } - - return false; + ASSERT_NOT_REACHED(); } -// FIXME: Resolving variables should be factored better. Maybe a resover-style class? -static void resolveVariables(StyleResolverState& state, CSSPropertyID id, CSSValue* value, Vector<std::pair<CSSPropertyID, String> >& knownExpressions) +void StyleBuilderFunctions::applyValueCSSPropertyFont(StyleResolverState& state, CSSValue* value) { - std::pair<CSSPropertyID, String> expression(id, value->serializeResolvingVariables(*state.style()->variables())); - - if (knownExpressions.contains(expression)) - return; // cycle detected. - - knownExpressions.append(expression); - - // FIXME: It would be faster not to re-parse from strings, but for now CSS property validation lives inside the parser so we do it there. - RefPtr<MutableStylePropertySet> resultSet = MutableStylePropertySet::create(); - if (!CSSParser::parseValue(resultSet.get(), id, expression.second, false, state.document())) - return; // expression failed to parse. - - for (unsigned i = 0; i < resultSet->propertyCount(); i++) { - StylePropertySet::PropertyReference property = resultSet->propertyAt(i); - if (property.id() != CSSPropertyVariable && hasVariableReference(property.value())) { - resolveVariables(state, property.id(), property.value(), knownExpressions); - } else { - StyleBuilder::applyProperty(property.id(), state, property.value()); - // All properties become dependent on their parent style when they use variables. - state.style()->setHasExplicitlyInheritedProperties(); - } - } + // Only System Font identifiers should come through this method + // all other values should have been handled when the shorthand + // was expanded by the parser. + // FIXME: System Font identifiers should not hijack this + // short-hand CSSProperty like this (crbug.com/353932) + state.style()->setLineHeight(RenderStyle::initialLineHeight()); + state.setLineHeightValue(0); + state.fontBuilder().fromSystemFont(toCSSPrimitiveValue(value)->getValueID(), state.style()->effectiveZoom()); } -void StyleBuilder::applyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value) +void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(StyleResolverState& state, CSSValue* value) { - if (RuntimeEnabledFeatures::cssVariablesEnabled() && id != CSSPropertyVariable && hasVariableReference(value)) { - Vector<std::pair<CSSPropertyID, String> > knownExpressions; - resolveVariables(state, id, value, knownExpressions); - return; - } - - // CSS variables don't resolve shorthands at parsing time, so this should be *after* handling variables. - ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id); - - bool isInherit = state.parentNode() && value->isInheritedValue(); - bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue()); - - ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit - ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle()) - - if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) { - // Limit the properties that can be applied to only the ones honored by :visited. - return; - } - - CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0; - if (primitiveValue && primitiveValue->getValueID() == CSSValueCurrentcolor) - state.style()->setHasCurrentColor(); - - if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id)) - state.parentStyle()->setHasExplicitlyInheritedProperties(); - - if (id == CSSPropertyVariable) { - ASSERT_WITH_SECURITY_IMPLICATION(value->isVariableValue()); - CSSVariableValue* variable = toCSSVariableValue(value); - ASSERT(!variable->name().isEmpty()); - ASSERT(!variable->value().isEmpty()); - state.style()->setVariable(variable->name(), variable->value()); - return; - } - - if (StyleBuilder::applyProperty(id, state, value, isInitial, isInherit)) + if (!value->isPrimitiveValue()) return; - - // Fall back to the old switch statement, which is now in StyleBuilderCustom.cpp - StyleBuilder::oldApplyProperty(id, state, value, isInitial, isInherit); + const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->getValueID() == CSSValueAuto) + state.style()->setLocale(nullAtom); + else + state.style()->setLocale(AtomicString(primitiveValue->getStringValue())); + state.fontBuilder().setScript(state.style()->locale()); } - -void StyleBuilder::oldApplyProperty(CSSPropertyID id, StyleResolverState& state, CSSValue* value, bool isInitial, bool isInherit) +void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(StyleResolverState&) { - CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0; - - // What follows is a list that maps the CSS properties into their corresponding front-end - // RenderStyle values. - switch (id) { - case CSSPropertyContent: - // list of string, uri, counter, attr, i - { - // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This - // note is a reminder that eventually "inherit" needs to be supported. - - if (isInitial) { - state.style()->clearContent(); - return; - } +} - if (!value->isValueList()) - return; +void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(StyleResolverState&) +{ +} - bool didSet = false; - for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { - CSSValue* item = i.value(); - if (item->isImageGeneratorValue()) { - if (item->isGradientValue()) - state.style()->setContent(StyleGeneratedImage::create(toCSSGradientValue(item)->gradientWithStylesResolved(state.document().textLinkColors(), state.style()->color()).get()), didSet); - else - state.style()->setContent(StyleGeneratedImage::create(toCSSImageGeneratorValue(item)), didSet); - didSet = true; - } else if (item->isImageSetValue()) { - state.style()->setContent(state.elementStyleResources().setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet); - didSet = true; - } - - if (item->isImageValue()) { - state.style()->setContent(state.elementStyleResources().cachedOrPendingFromValue(CSSPropertyContent, toCSSImageValue(item)), didSet); - didSet = true; - continue; - } - - if (!item->isPrimitiveValue()) - continue; - - CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item); - - if (contentValue->isString()) { - state.style()->setContent(contentValue->getStringValue().impl(), didSet); - didSet = true; - } else if (contentValue->isAttr()) { - // FIXME: Can a namespace be specified for an attr(foo)? - if (state.style()->styleType() == NOPSEUDO) - state.style()->setUnique(); - else - state.parentStyle()->setUnique(); - QualifiedName attr(nullAtom, AtomicString(contentValue->getStringValue()), nullAtom); - const AtomicString& value = state.element()->getAttribute(attr); - state.style()->setContent(value.isNull() ? emptyString() : value.string(), didSet); - didSet = true; - // register the fact that the attribute value affects the style - state.contentAttrValues().append(attr.localName()); - } else if (contentValue->isCounter()) { - Counter* counterValue = contentValue->getCounterValue(); - EListStyleType listStyleType = NoneListStyle; - CSSValueID listStyleIdent = counterValue->listStyleIdent(); - if (listStyleIdent != CSSValueNone) - listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc); - OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(AtomicString(counterValue->identifier()), listStyleType, AtomicString(counterValue->separator()))); - state.style()->setContent(counter.release(), didSet); - didSet = true; - } else { - switch (contentValue->getValueID()) { - case CSSValueOpenQuote: - state.style()->setContent(OPEN_QUOTE, didSet); - didSet = true; - break; - case CSSValueCloseQuote: - state.style()->setContent(CLOSE_QUOTE, didSet); - didSet = true; - break; - case CSSValueNoOpenQuote: - state.style()->setContent(NO_OPEN_QUOTE, didSet); - didSet = true; - break; - case CSSValueNoCloseQuote: - state.style()->setContent(NO_CLOSE_QUOTE, didSet); - didSet = true; - break; - default: - // normal and none do not have any effect. - { } - } - } - } - if (!didSet) - state.style()->clearContent(); - return; - } - case CSSPropertyQuotes: - HANDLE_INHERIT_AND_INITIAL(quotes, Quotes); - if (value->isValueList()) { - CSSValueList* list = toCSSValueList(value); - RefPtr<QuotesData> quotes = QuotesData::create(); - for (size_t i = 0; i < list->length(); i += 2) { - CSSValue* first = list->itemWithoutBoundsCheck(i); - // item() returns null if out of bounds so this is safe. - CSSValue* second = list->item(i + 1); - if (!second) - continue; - String startQuote = toCSSPrimitiveValue(first)->getStringValue(); - String endQuote = toCSSPrimitiveValue(second)->getStringValue(); - quotes->addPair(std::make_pair(startQuote, endQuote)); - } - state.style()->setQuotes(quotes); - return; - } - if (primitiveValue) { - if (primitiveValue->getValueID() == CSSValueNone) - state.style()->setQuotes(QuotesData::create()); - } +void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(StyleResolverState& state, CSSValue* value) +{ + if (!value->isPrimitiveValue()) return; - // Shorthand properties. - case CSSPropertyFont: - // Only System Font identifiers should come through this method - // all other values should have been handled when the shorthand - // was expanded by the parser. - // FIXME: System Font identifiers should not hijack this - // short-hand CSSProperty like this. - ASSERT(!isInitial); - ASSERT(!isInherit); - ASSERT(primitiveValue); - state.style()->setLineHeight(RenderStyle::initialLineHeight()); - state.setLineHeightValue(0); - state.fontBuilder().fromSystemFont(primitiveValue->getValueID(), state.style()->effectiveZoom()); + const CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (!primitiveValue->getValueID()) return; - case CSSPropertyAnimation: - case CSSPropertyBackground: - case CSSPropertyBackgroundPosition: - case CSSPropertyBackgroundRepeat: - case CSSPropertyBorder: - case CSSPropertyBorderBottom: - case CSSPropertyBorderColor: - case CSSPropertyBorderImage: - case CSSPropertyBorderLeft: - case CSSPropertyBorderRadius: - case CSSPropertyBorderRight: - case CSSPropertyBorderSpacing: - case CSSPropertyBorderStyle: - case CSSPropertyBorderTop: - case CSSPropertyBorderWidth: - case CSSPropertyListStyle: - case CSSPropertyMargin: - case CSSPropertyObjectPosition: - case CSSPropertyOutline: - case CSSPropertyOverflow: - case CSSPropertyPadding: - case CSSPropertyTransition: - case CSSPropertyWebkitAnimation: - case CSSPropertyWebkitBorderAfter: - case CSSPropertyWebkitBorderBefore: - case CSSPropertyWebkitBorderEnd: - case CSSPropertyWebkitBorderStart: - case CSSPropertyWebkitBorderRadius: - case CSSPropertyWebkitColumns: - case CSSPropertyWebkitColumnRule: - case CSSPropertyFlex: - case CSSPropertyFlexFlow: - case CSSPropertyGridColumn: - case CSSPropertyGridRow: - case CSSPropertyGridArea: - case CSSPropertyWebkitMarginCollapse: - case CSSPropertyWebkitMask: - case CSSPropertyWebkitMaskPosition: - case CSSPropertyWebkitMaskRepeat: - case CSSPropertyWebkitTextEmphasis: - case CSSPropertyWebkitTextStroke: - case CSSPropertyWebkitTransition: - case CSSPropertyWebkitTransformOrigin: - ASSERT(isExpandedShorthand(id)); - ASSERT_NOT_REACHED(); - break; + state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag); + state.document().setHasAnnotatedRegions(true); +} - // CSS3 Properties - case CSSPropertyWebkitBoxReflect: { - HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect) - if (primitiveValue) { - state.style()->setBoxReflect(RenderStyle::initialBoxReflect()); - return; - } +void StyleBuilderFunctions::applyInitialCSSPropertyWebkitPerspective(StyleResolverState& state) +{ + applyInitialCSSPropertyPerspective(state); +} - if (!value->isReflectValue()) - return; +void StyleBuilderFunctions::applyInheritCSSPropertyWebkitPerspective(StyleResolverState& state) +{ + applyInheritCSSPropertyPerspective(state); +} - CSSReflectValue* reflectValue = toCSSReflectValue(value); - RefPtr<StyleReflection> reflection = StyleReflection::create(); - reflection->setDirection(*reflectValue->direction()); - if (reflectValue->offset()) - reflection->setOffset(reflectValue->offset()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData())); - NinePieceImage mask; - mask.setMaskDefaults(); - state.styleMap().mapNinePieceImage(state.style(), id, reflectValue->mask(), mask); - reflection->setMask(mask); - - state.style()->setBoxReflect(reflection.release()); - return; - } - case CSSPropertySrc: // Only used in @font-face rules. - return; - case CSSPropertyUnicodeRange: // Only used in @font-face rules. - return; - case CSSPropertyWebkitLocale: { - HANDLE_INHERIT_AND_INITIAL(locale, Locale); - if (!primitiveValue) - return; - if (primitiveValue->getValueID() == CSSValueAuto) - state.style()->setLocale(nullAtom); - else - state.style()->setLocale(AtomicString(primitiveValue->getStringValue())); - state.fontBuilder().setScript(state.style()->locale()); - return; - } - case CSSPropertyWebkitAppRegion: { - if (!primitiveValue || !primitiveValue->getValueID()) - return; - state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag); - state.document().setHasAnnotatedRegions(true); - return; - } - case CSSPropertyWebkitTextStrokeWidth: { - HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth) - float width = 0; - switch (primitiveValue->getValueID()) { - case CSSValueThin: - case CSSValueMedium: - case CSSValueThick: { - double result = 1.0 / 48; - if (primitiveValue->getValueID() == CSSValueMedium) - result *= 3; - else if (primitiveValue->getValueID() == CSSValueThick) - result *= 5; - width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(state.cssToLengthConversionData()); - break; - } - default: - width = primitiveValue->computeLength<float>(state.cssToLengthConversionData()); - break; - } - state.style()->setTextStrokeWidth(width); - return; - } - case CSSPropertyWebkitTransform: { - HANDLE_INHERIT_AND_INITIAL(transform, Transform); - TransformOperations operations; - TransformBuilder::createTransformOperations(value, state.cssToLengthConversionData(), operations); - state.style()->setTransform(operations); +void StyleBuilderFunctions::applyValueCSSPropertyWebkitPerspective(StyleResolverState& state, CSSValue* value) +{ + if (!value->isPrimitiveValue()) return; - } - case CSSPropertyWebkitPerspective: { - HANDLE_INHERIT_AND_INITIAL(perspective, Perspective) - - if (!primitiveValue) - return; - - if (primitiveValue->getValueID() == CSSValueNone) { - state.style()->setPerspective(0); - return; - } - - float perspectiveValue; - if (primitiveValue->isLength()) { - perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData()); - } else if (primitiveValue->isNumber()) { - // For backward compatibility, treat valueless numbers as px. - perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData()); - } else { - return; - } - + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->isNumber()) { + float perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(state.cssToLengthConversionData()); if (perspectiveValue >= 0.0f) state.style()->setPerspective(perspectiveValue); - return; + } else { + applyValueCSSPropertyPerspective(state, value); } - case CSSPropertyWebkitTapHighlightColor: { - HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor); - if (!primitiveValue) - break; +} - Color col = state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color()); - state.style()->setTapHighlightColor(col); - return; - } - case CSSPropertyInternalCallback: { - if (isInherit || isInitial) - return; - if (primitiveValue && primitiveValue->getValueID() == CSSValueInternalPresence) { - state.style()->addCallbackSelector(state.currentRule()->selectorList().selectorsText()); - return; - } - break; - } - case CSSPropertyInvalid: - return; - // Directional properties are resolved by resolveDirectionAwareProperty() before the switch. - case CSSPropertyWebkitBorderEndColor: - case CSSPropertyWebkitBorderEndStyle: - case CSSPropertyWebkitBorderEndWidth: - case CSSPropertyWebkitBorderStartColor: - case CSSPropertyWebkitBorderStartStyle: - case CSSPropertyWebkitBorderStartWidth: - case CSSPropertyWebkitBorderBeforeColor: - case CSSPropertyWebkitBorderBeforeStyle: - case CSSPropertyWebkitBorderBeforeWidth: - case CSSPropertyWebkitBorderAfterColor: - case CSSPropertyWebkitBorderAfterStyle: - case CSSPropertyWebkitBorderAfterWidth: - case CSSPropertyWebkitMarginEnd: - case CSSPropertyWebkitMarginStart: - case CSSPropertyWebkitMarginBefore: - case CSSPropertyWebkitMarginAfter: - case CSSPropertyWebkitMarginBeforeCollapse: - case CSSPropertyWebkitMarginTopCollapse: - case CSSPropertyWebkitMarginAfterCollapse: - case CSSPropertyWebkitMarginBottomCollapse: - case CSSPropertyWebkitPaddingEnd: - case CSSPropertyWebkitPaddingStart: - case CSSPropertyWebkitPaddingBefore: - case CSSPropertyWebkitPaddingAfter: - case CSSPropertyWebkitLogicalWidth: - case CSSPropertyWebkitLogicalHeight: - case CSSPropertyWebkitMinLogicalWidth: - case CSSPropertyWebkitMinLogicalHeight: - case CSSPropertyWebkitMaxLogicalWidth: - case CSSPropertyWebkitMaxLogicalHeight: - { - CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode()); - ASSERT(newId != id); - return applyProperty(newId, state, value); - } - case CSSPropertyFontStretch: - case CSSPropertyPage: - case CSSPropertyTextLineThroughColor: - case CSSPropertyTextLineThroughMode: - case CSSPropertyTextLineThroughStyle: - case CSSPropertyTextLineThroughWidth: - case CSSPropertyTextOverlineColor: - case CSSPropertyTextOverlineMode: - case CSSPropertyTextOverlineStyle: - case CSSPropertyTextOverlineWidth: - case CSSPropertyTextUnderlineColor: - case CSSPropertyTextUnderlineMode: - case CSSPropertyTextUnderlineStyle: - case CSSPropertyTextUnderlineWidth: - case CSSPropertyWebkitFontSizeDelta: - case CSSPropertyWebkitTextDecorationsInEffect: +void StyleBuilderFunctions::applyValueCSSPropertyPerspective(StyleResolverState& state, CSSValue* value) +{ + if (!value->isPrimitiveValue()) return; - - // CSS Text Layout Module Level 3: Vertical writing support - case CSSPropertyWebkitWritingMode: { - HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode); - - if (primitiveValue) - state.setWritingMode(*primitiveValue); - - // FIXME: It is not ok to modify document state while applying style. - if (state.element() && state.element() == state.document().documentElement()) - state.document().setWritingModeSetOnDocumentElement(true); + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->getValueID() == CSSValueNone) { + state.style()->setPerspective(0); return; } - case CSSPropertyWebkitTextOrientation: { - HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation); - - if (primitiveValue) - state.setTextOrientation(*primitiveValue); - + if (!primitiveValue->isLength()) return; - } - - case CSSPropertyWebkitLineBoxContain: { - HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain) - if (primitiveValue && primitiveValue->getValueID() == CSSValueNone) { - state.style()->setLineBoxContain(LineBoxContainNone); - return; - } - - if (!value->isLineBoxContainValue()) - return; + float perspectiveValue = primitiveValue->computeLength<float>(state.cssToLengthConversionData()); + if (perspectiveValue >= 0.0f) + state.style()->setPerspective(perspectiveValue); +} - state.style()->setLineBoxContain(toCSSLineBoxContainValue(value)->value()); - return; - } +void StyleBuilderFunctions::applyInitialCSSPropertyInternalCallback(StyleResolverState& state) +{ +} - // CSS Fonts Module Level 3 - case CSSPropertyWebkitFontFeatureSettings: { - if (primitiveValue && primitiveValue->getValueID() == CSSValueNormal) { - state.fontBuilder().setFeatureSettingsNormal(); - return; - } +void StyleBuilderFunctions::applyInheritCSSPropertyInternalCallback(StyleResolverState& state) +{ +} - if (!value->isValueList()) - return; +void StyleBuilderFunctions::applyValueCSSPropertyInternalCallback(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueInternalPresence) + state.style()->addCallbackSelector(state.currentRule()->selectorList().selectorsText()); +} - state.fontBuilder().setFeatureSettingsValue(value); - return; - } +void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue()) + state.setWritingMode(*toCSSPrimitiveValue(value)); - case CSSPropertyWebkitFilter: { - HANDLE_INHERIT_AND_INITIAL(filter, Filter); - FilterOperations operations; - if (FilterOperationResolver::createFilterOperations(value, state.cssToLengthConversionData(), operations, state)) - state.style()->setFilter(operations); - return; - } - case CSSPropertyGridAutoColumns: { - HANDLE_INHERIT_AND_INITIAL(gridAutoColumns, GridAutoColumns); - GridTrackSize trackSize; - if (!createGridTrackSize(value, trackSize, state)) - return; - state.style()->setGridAutoColumns(trackSize); - return; - } - case CSSPropertyGridAutoRows: { - HANDLE_INHERIT_AND_INITIAL(gridAutoRows, GridAutoRows); - GridTrackSize trackSize; - if (!createGridTrackSize(value, trackSize, state)) - return; - state.style()->setGridAutoRows(trackSize); - return; - } - case CSSPropertyGridDefinitionColumns: { - if (isInherit) { - state.style()->setGridDefinitionColumns(state.parentStyle()->gridDefinitionColumns()); - state.style()->setNamedGridColumnLines(state.parentStyle()->namedGridColumnLines()); - state.style()->setOrderedNamedGridColumnLines(state.parentStyle()->orderedNamedGridColumnLines()); - return; - } - if (isInitial) { - state.style()->setGridDefinitionColumns(RenderStyle::initialGridDefinitionColumns()); - state.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines()); - state.style()->setOrderedNamedGridColumnLines(RenderStyle::initialOrderedNamedGridColumnLines()); - return; - } + // FIXME: It is not ok to modify document state while applying style. + if (state.element() && state.element() == state.document().documentElement()) + state.document().setWritingModeSetOnDocumentElement(true); +} - Vector<GridTrackSize> trackSizes; - NamedGridLinesMap namedGridLines; - OrderedNamedGridLines orderedNamedGridLines; - if (!createGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, state)) - return; - state.style()->setGridDefinitionColumns(trackSizes); - state.style()->setNamedGridColumnLines(namedGridLines); - state.style()->setOrderedNamedGridColumnLines(orderedNamedGridLines); - return; - } - case CSSPropertyGridDefinitionRows: { - if (isInherit) { - state.style()->setGridDefinitionRows(state.parentStyle()->gridDefinitionRows()); - state.style()->setNamedGridRowLines(state.parentStyle()->namedGridRowLines()); - state.style()->setOrderedNamedGridRowLines(state.parentStyle()->orderedNamedGridRowLines()); - return; - } - if (isInitial) { - state.style()->setGridDefinitionRows(RenderStyle::initialGridDefinitionRows()); - state.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines()); - state.style()->setOrderedNamedGridRowLines(RenderStyle::initialOrderedNamedGridRowLines()); - return; - } +void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue()) + state.setTextOrientation(*toCSSPrimitiveValue(value)); +} - Vector<GridTrackSize> trackSizes; - NamedGridLinesMap namedGridLines; - OrderedNamedGridLines orderedNamedGridLines; - if (!createGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, state)) - return; - state.style()->setGridDefinitionRows(trackSizes); - state.style()->setNamedGridRowLines(namedGridLines); - state.style()->setOrderedNamedGridRowLines(orderedNamedGridLines); - return; - } +// FIXME: We should handle initial and inherit for font-feature-settings +void StyleBuilderFunctions::applyInitialCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state) +{ +} - case CSSPropertyGridColumnStart: { - HANDLE_INHERIT_AND_INITIAL(gridColumnStart, GridColumnStart); - GridPosition startPosition; - if (!createGridPosition(value, startPosition)) - return; - state.style()->setGridColumnStart(startPosition); - return; - } - case CSSPropertyGridColumnEnd: { - HANDLE_INHERIT_AND_INITIAL(gridColumnEnd, GridColumnEnd); - GridPosition endPosition; - if (!createGridPosition(value, endPosition)) - return; - state.style()->setGridColumnEnd(endPosition); - return; - } +void StyleBuilderFunctions::applyInheritCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state) +{ +} - case CSSPropertyGridRowStart: { - HANDLE_INHERIT_AND_INITIAL(gridRowStart, GridRowStart); - GridPosition beforePosition; - if (!createGridPosition(value, beforePosition)) - return; - state.style()->setGridRowStart(beforePosition); - return; - } - case CSSPropertyGridRowEnd: { - HANDLE_INHERIT_AND_INITIAL(gridRowEnd, GridRowEnd); - GridPosition afterPosition; - if (!createGridPosition(value, afterPosition)) - return; - state.style()->setGridRowEnd(afterPosition); +void StyleBuilderFunctions::applyValueCSSPropertyWebkitFontFeatureSettings(StyleResolverState& state, CSSValue* value) +{ + if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal) { + state.fontBuilder().setFeatureSettingsNormal(); return; } - case CSSPropertyGridTemplate: { - if (isInherit) { - state.style()->setNamedGridArea(state.parentStyle()->namedGridArea()); - state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount()); - state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount()); - return; - } - if (isInitial) { - state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea()); - state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount()); - state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount()); - return; - } - - if (value->isPrimitiveValue()) { - ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); - return; - } + if (value->isValueList()) + state.fontBuilder().setFeatureSettingsValue(value); +} - CSSGridTemplateValue* gridTemplateValue = toCSSGridTemplateValue(value); - state.style()->setNamedGridArea(gridTemplateValue->gridAreaMap()); - state.style()->setNamedGridAreaRowCount(gridTemplateValue->rowCount()); - state.style()->setNamedGridAreaColumnCount(gridTemplateValue->columnCount()); - return; - } - // These properties are aliased and we already applied the property on the prefixed version. - case CSSPropertyAnimationDelay: - case CSSPropertyAnimationDirection: - case CSSPropertyAnimationDuration: - case CSSPropertyAnimationFillMode: - case CSSPropertyAnimationIterationCount: - case CSSPropertyAnimationName: - case CSSPropertyAnimationPlayState: - case CSSPropertyAnimationTimingFunction: - case CSSPropertyTransitionDelay: - case CSSPropertyTransitionDuration: - case CSSPropertyTransitionProperty: - case CSSPropertyTransitionTimingFunction: - return; - // These properties are implemented in StyleBuilder::applyProperty. - case CSSPropertyBackgroundAttachment: - case CSSPropertyBackgroundBlendMode: - case CSSPropertyBackgroundClip: - case CSSPropertyBackgroundColor: - case CSSPropertyBackgroundImage: - case CSSPropertyBackgroundOrigin: - case CSSPropertyBackgroundPositionX: - case CSSPropertyBackgroundPositionY: - case CSSPropertyBackgroundRepeatX: - case CSSPropertyBackgroundRepeatY: - case CSSPropertyBackgroundSize: - case CSSPropertyBorderBottomColor: - case CSSPropertyBorderBottomLeftRadius: - case CSSPropertyBorderBottomRightRadius: - case CSSPropertyBorderBottomStyle: - case CSSPropertyBorderBottomWidth: - case CSSPropertyBorderCollapse: - case CSSPropertyBorderImageOutset: - case CSSPropertyBorderImageRepeat: - case CSSPropertyBorderImageSlice: - case CSSPropertyBorderImageSource: - case CSSPropertyBorderImageWidth: - case CSSPropertyBorderLeftColor: - case CSSPropertyBorderLeftStyle: - case CSSPropertyBorderLeftWidth: - case CSSPropertyBorderRightColor: - case CSSPropertyBorderRightStyle: - case CSSPropertyBorderRightWidth: - case CSSPropertyBorderTopColor: - case CSSPropertyBorderTopLeftRadius: - case CSSPropertyBorderTopRightRadius: - case CSSPropertyBorderTopStyle: - case CSSPropertyBorderTopWidth: - case CSSPropertyBottom: - case CSSPropertyBoxShadow: - case CSSPropertyBoxSizing: - case CSSPropertyCaptionSide: - case CSSPropertyClear: - case CSSPropertyClip: - case CSSPropertyColor: - case CSSPropertyCounterIncrement: - case CSSPropertyCounterReset: - case CSSPropertyCursor: - case CSSPropertyDirection: - case CSSPropertyDisplay: - case CSSPropertyEmptyCells: - case CSSPropertyFloat: - case CSSPropertyFontKerning: - case CSSPropertyFontSize: - case CSSPropertyFontStyle: - case CSSPropertyFontVariant: - case CSSPropertyFontWeight: - case CSSPropertyHeight: - case CSSPropertyImageRendering: - case CSSPropertyIsolation: - case CSSPropertyLeft: - case CSSPropertyLetterSpacing: - case CSSPropertyLineHeight: - case CSSPropertyListStyleImage: - case CSSPropertyListStylePosition: - case CSSPropertyListStyleType: - case CSSPropertyMarginBottom: - case CSSPropertyMarginLeft: - case CSSPropertyMarginRight: - case CSSPropertyMarginTop: - case CSSPropertyMaxHeight: - case CSSPropertyMaxWidth: - case CSSPropertyMinHeight: - case CSSPropertyMixBlendMode: - case CSSPropertyMinWidth: - case CSSPropertyObjectFit: - case CSSPropertyOpacity: - case CSSPropertyOrphans: - case CSSPropertyOutlineColor: - case CSSPropertyOutlineOffset: - case CSSPropertyOutlineStyle: - case CSSPropertyOutlineWidth: - case CSSPropertyOverflowWrap: - case CSSPropertyOverflowX: - case CSSPropertyOverflowY: - case CSSPropertyPaddingBottom: - case CSSPropertyPaddingLeft: - case CSSPropertyPaddingRight: - case CSSPropertyPaddingTop: - case CSSPropertyPageBreakAfter: - case CSSPropertyPageBreakBefore: - case CSSPropertyPageBreakInside: - case CSSPropertyPointerEvents: - case CSSPropertyPosition: - case CSSPropertyResize: - case CSSPropertyRight: - case CSSPropertySize: - case CSSPropertySpeak: - case CSSPropertyTabSize: - case CSSPropertyTableLayout: - case CSSPropertyTextAlign: - case CSSPropertyTextAlignLast: - case CSSPropertyTextDecoration: - case CSSPropertyTextDecorationLine: - case CSSPropertyTextDecorationStyle: - case CSSPropertyTextDecorationColor: - case CSSPropertyTextIndent: - case CSSPropertyTextJustify: - case CSSPropertyTextOverflow: - case CSSPropertyTextRendering: - case CSSPropertyTextShadow: - case CSSPropertyTextTransform: - case CSSPropertyTop: - case CSSPropertyTouchAction: - case CSSPropertyTouchActionDelay: - case CSSPropertyUnicodeBidi: - case CSSPropertyVariable: - case CSSPropertyVerticalAlign: - case CSSPropertyVisibility: - case CSSPropertyWebkitAnimationDelay: - case CSSPropertyWebkitAnimationDirection: - case CSSPropertyWebkitAnimationDuration: - case CSSPropertyWebkitAnimationFillMode: - case CSSPropertyWebkitAnimationIterationCount: - case CSSPropertyWebkitAnimationName: - case CSSPropertyWebkitAnimationPlayState: - case CSSPropertyWebkitAnimationTimingFunction: - case CSSPropertyWebkitAppearance: - case CSSPropertyWebkitAspectRatio: - case CSSPropertyWebkitBackfaceVisibility: - case CSSPropertyWebkitBackgroundClip: - case CSSPropertyWebkitBackgroundComposite: - case CSSPropertyWebkitBackgroundOrigin: - case CSSPropertyWebkitBackgroundSize: - case CSSPropertyWebkitBorderFit: - case CSSPropertyWebkitBorderHorizontalSpacing: - case CSSPropertyWebkitBorderImage: - case CSSPropertyWebkitBorderVerticalSpacing: - case CSSPropertyWebkitBoxAlign: - case CSSPropertyWebkitBoxDecorationBreak: - case CSSPropertyWebkitBoxDirection: - case CSSPropertyWebkitBoxFlex: - case CSSPropertyWebkitBoxFlexGroup: - case CSSPropertyWebkitBoxLines: - case CSSPropertyWebkitBoxOrdinalGroup: - case CSSPropertyWebkitBoxOrient: - case CSSPropertyWebkitBoxPack: - case CSSPropertyWebkitBoxShadow: - case CSSPropertyWebkitColumnAxis: - case CSSPropertyWebkitColumnBreakAfter: - case CSSPropertyWebkitColumnBreakBefore: - case CSSPropertyWebkitColumnBreakInside: - case CSSPropertyWebkitColumnCount: - case CSSPropertyColumnFill: - case CSSPropertyWebkitColumnGap: - case CSSPropertyWebkitColumnProgression: - case CSSPropertyWebkitColumnRuleColor: - case CSSPropertyWebkitColumnRuleStyle: - case CSSPropertyWebkitColumnRuleWidth: - case CSSPropertyWebkitColumnSpan: - case CSSPropertyWebkitColumnWidth: - case CSSPropertyAlignContent: - case CSSPropertyAlignItems: - case CSSPropertyAlignSelf: - case CSSPropertyFlexBasis: - case CSSPropertyFlexDirection: - case CSSPropertyFlexGrow: - case CSSPropertyFlexShrink: - case CSSPropertyFlexWrap: - case CSSPropertyJustifyContent: - case CSSPropertyOrder: - case CSSPropertyWebkitFlowFrom: - case CSSPropertyWebkitFlowInto: - case CSSPropertyWebkitFontSmoothing: - case CSSPropertyWebkitFontVariantLigatures: - case CSSPropertyWebkitHighlight: - case CSSPropertyWebkitHyphenateCharacter: - case CSSPropertyWebkitLineAlign: - case CSSPropertyWebkitLineBreak: - case CSSPropertyWebkitLineClamp: - case CSSPropertyWebkitLineGrid: - case CSSPropertyWebkitLineSnap: - case CSSPropertyInternalMarqueeDirection: - case CSSPropertyInternalMarqueeIncrement: - case CSSPropertyInternalMarqueeRepetition: - case CSSPropertyInternalMarqueeSpeed: - case CSSPropertyInternalMarqueeStyle: - case CSSPropertyWebkitMaskBoxImage: - case CSSPropertyWebkitMaskBoxImageOutset: - case CSSPropertyWebkitMaskBoxImageRepeat: - case CSSPropertyWebkitMaskBoxImageSlice: - case CSSPropertyWebkitMaskBoxImageSource: - case CSSPropertyWebkitMaskBoxImageWidth: - case CSSPropertyWebkitMaskClip: - case CSSPropertyWebkitMaskComposite: - case CSSPropertyWebkitMaskImage: - case CSSPropertyWebkitMaskOrigin: - case CSSPropertyWebkitMaskPositionX: - case CSSPropertyWebkitMaskPositionY: - case CSSPropertyWebkitMaskRepeatX: - case CSSPropertyWebkitMaskRepeatY: - case CSSPropertyWebkitMaskSize: - case CSSPropertyWebkitPerspectiveOrigin: - case CSSPropertyWebkitPerspectiveOriginX: - case CSSPropertyWebkitPerspectiveOriginY: - case CSSPropertyWebkitPrintColorAdjust: - case CSSPropertyWebkitRegionBreakAfter: - case CSSPropertyWebkitRegionBreakBefore: - case CSSPropertyWebkitRegionBreakInside: - case CSSPropertyWebkitRegionFragment: - case CSSPropertyWebkitRtlOrdering: - case CSSPropertyWebkitRubyPosition: - case CSSPropertyWebkitTextCombine: - case CSSPropertyTextUnderlinePosition: - case CSSPropertyWebkitTextEmphasisColor: - case CSSPropertyWebkitTextEmphasisPosition: - case CSSPropertyWebkitTextEmphasisStyle: - case CSSPropertyWebkitTextFillColor: - case CSSPropertyWebkitTextSecurity: - case CSSPropertyWebkitTextStrokeColor: - case CSSPropertyWebkitTransformOriginX: - case CSSPropertyWebkitTransformOriginY: - case CSSPropertyWebkitTransformOriginZ: - case CSSPropertyWebkitTransformStyle: - case CSSPropertyWebkitTransitionDelay: - case CSSPropertyWebkitTransitionDuration: - case CSSPropertyWebkitTransitionProperty: - case CSSPropertyWebkitTransitionTimingFunction: - case CSSPropertyWebkitUserDrag: - case CSSPropertyWebkitUserModify: - case CSSPropertyWebkitUserSelect: - case CSSPropertyWebkitClipPath: - case CSSPropertyWebkitWrapFlow: - case CSSPropertyShapeMargin: - case CSSPropertyShapePadding: - case CSSPropertyShapeImageThreshold: - case CSSPropertyWebkitWrapThrough: - case CSSPropertyShapeInside: - case CSSPropertyShapeOutside: - case CSSPropertyWhiteSpace: - case CSSPropertyWidows: - case CSSPropertyWidth: - case CSSPropertyWordBreak: - case CSSPropertyWordSpacing: - case CSSPropertyWordWrap: - case CSSPropertyZIndex: - case CSSPropertyZoom: - case CSSPropertyFontFamily: - case CSSPropertyGridAutoFlow: - case CSSPropertyMarker: - case CSSPropertyAlignmentBaseline: - case CSSPropertyBufferedRendering: - case CSSPropertyClipRule: - case CSSPropertyColorInterpolation: - case CSSPropertyColorInterpolationFilters: - case CSSPropertyColorRendering: - case CSSPropertyDominantBaseline: - case CSSPropertyFillRule: - case CSSPropertyMaskSourceType: - case CSSPropertyMaskType: - case CSSPropertyShapeRendering: - case CSSPropertyStrokeLinecap: - case CSSPropertyStrokeLinejoin: - case CSSPropertyTextAnchor: - case CSSPropertyVectorEffect: - case CSSPropertyWritingMode: - case CSSPropertyClipPath: - case CSSPropertyFillOpacity: - case CSSPropertyFilter: - case CSSPropertyFloodOpacity: - case CSSPropertyKerning: - case CSSPropertyMarkerEnd: - case CSSPropertyMarkerMid: - case CSSPropertyMarkerStart: - case CSSPropertyMask: - case CSSPropertyStopOpacity: - case CSSPropertyStrokeDashoffset: - case CSSPropertyStrokeMiterlimit: - case CSSPropertyStrokeOpacity: - case CSSPropertyStrokeWidth: - ASSERT_NOT_REACHED(); - return; - // Only used in @viewport rules - case CSSPropertyMaxZoom: - case CSSPropertyMinZoom: - case CSSPropertyOrientation: - case CSSPropertyUserZoom: +void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(StyleResolverState& state, CSSValue* value) +{ + if (!value->isPrimitiveValue()) return; - case CSSPropertyBaselineShift: - { - HANDLE_SVG_INHERIT_AND_INITIAL(baselineShift, BaselineShift); - if (!primitiveValue) + SVGRenderStyle* svgStyle = state.style()->accessSVGStyle(); + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); + if (primitiveValue->getValueID()) { + switch (primitiveValue->getValueID()) { + case CSSValueBaseline: + svgStyle->setBaselineShift(BS_BASELINE); break; - - SVGRenderStyle* svgStyle = state.style()->accessSVGStyle(); - if (primitiveValue->getValueID()) { - switch (primitiveValue->getValueID()) { - case CSSValueBaseline: - svgStyle->setBaselineShift(BS_BASELINE); - break; - case CSSValueSub: - svgStyle->setBaselineShift(BS_SUB); - break; - case CSSValueSuper: - svgStyle->setBaselineShift(BS_SUPER); - break; - default: - break; - } - } else { - svgStyle->setBaselineShift(BS_LENGTH); - svgStyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue)); - } - - break; - } - case CSSPropertyColorProfile: - { - // Not implemented. - break; - } - // end of ident only properties - case CSSPropertyFill: - { - SVGRenderStyle* svgStyle = state.style()->accessSVGStyle(); - if (isInherit) { - const SVGRenderStyle* svgParentStyle = state.parentStyle()->svgStyle(); - svgStyle->setFillPaint(svgParentStyle->fillPaintType(), svgParentStyle->fillPaintColor(), svgParentStyle->fillPaintUri(), state.applyPropertyToRegularStyle(), state.applyPropertyToVisitedLinkStyle()); - return; - } - if (isInitial) { - svgStyle->setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRenderStyle::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri(), state.applyPropertyToRegularStyle(), state.applyPropertyToVisitedLinkStyle()); - return; - } - if (value->isSVGPaint()) { - SVGPaint* svgPaint = toSVGPaint(value); - svgStyle->setFillPaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, state.style()->color()), svgPaint->uri(), state.applyPropertyToRegularStyle(), state.applyPropertyToVisitedLinkStyle()); - } - break; - } - case CSSPropertyStroke: - { - SVGRenderStyle* svgStyle = state.style()->accessSVGStyle(); - if (isInherit) { - const SVGRenderStyle* svgParentStyle = state.parentStyle()->svgStyle(); - svgStyle->setStrokePaint(svgParentStyle->strokePaintType(), svgParentStyle->strokePaintColor(), svgParentStyle->strokePaintUri(), state.applyPropertyToRegularStyle(), state.applyPropertyToVisitedLinkStyle()); - return; - } - if (isInitial) { - svgStyle->setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRenderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri(), state.applyPropertyToRegularStyle(), state.applyPropertyToVisitedLinkStyle()); - return; - } - if (value->isSVGPaint()) { - SVGPaint* svgPaint = toSVGPaint(value); - svgStyle->setStrokePaint(svgPaint->paintType(), colorFromSVGColorCSSValue(svgPaint, state.style()->color()), svgPaint->uri(), state.applyPropertyToRegularStyle(), state.applyPropertyToVisitedLinkStyle()); - } - break; - } - case CSSPropertyStrokeDasharray: - { - HANDLE_SVG_INHERIT_AND_INITIAL(strokeDashArray, StrokeDashArray) - if (!value->isValueList()) { - state.style()->accessSVGStyle()->setStrokeDashArray(SVGRenderStyle::initialStrokeDashArray()); + case CSSValueSub: + svgStyle->setBaselineShift(BS_SUB); break; - } - - CSSValueList* dashes = toCSSValueList(value); - - Vector<SVGLength> array; - size_t length = dashes->length(); - for (size_t i = 0; i < length; ++i) { - CSSValue* currValue = dashes->itemWithoutBoundsCheck(i); - if (!currValue->isPrimitiveValue()) - continue; - - CSSPrimitiveValue* dash = toCSSPrimitiveValue(dashes->itemWithoutBoundsCheck(i)); - array.append(SVGLength::fromCSSPrimitiveValue(dash)); - } - - state.style()->accessSVGStyle()->setStrokeDashArray(array); - break; - } - case CSSPropertyStopColor: - { - HANDLE_SVG_INHERIT_AND_INITIAL(stopColor, StopColor); - if (value->isSVGColor()) - state.style()->accessSVGStyle()->setStopColor(colorFromSVGColorCSSValue(toSVGColor(value), state.style()->color())); - break; - } - case CSSPropertyLightingColor: - { - HANDLE_SVG_INHERIT_AND_INITIAL(lightingColor, LightingColor); - if (value->isSVGColor()) - state.style()->accessSVGStyle()->setLightingColor(colorFromSVGColorCSSValue(toSVGColor(value), state.style()->color())); - break; - } - case CSSPropertyFloodColor: - { - HANDLE_SVG_INHERIT_AND_INITIAL(floodColor, FloodColor); - if (value->isSVGColor()) - state.style()->accessSVGStyle()->setFloodColor(colorFromSVGColorCSSValue(toSVGColor(value), state.style()->color())); - break; - } - case CSSPropertyGlyphOrientationHorizontal: - { - HANDLE_SVG_INHERIT_AND_INITIAL(glyphOrientationHorizontal, GlyphOrientationHorizontal) - EGlyphOrientation orientation; - if (degreeToGlyphOrientation(primitiveValue, orientation)) - state.style()->accessSVGStyle()->setGlyphOrientationHorizontal(orientation); - break; - } - case CSSPropertyPaintOrder: { - HANDLE_SVG_INHERIT_AND_INITIAL(paintOrder, PaintOrder) - if (value->isValueList()) - state.style()->accessSVGStyle()->setPaintOrder(paintOrderFlattened(value)); - break; - } - case CSSPropertyGlyphOrientationVertical: - { - HANDLE_SVG_INHERIT_AND_INITIAL(glyphOrientationVertical, GlyphOrientationVertical) - if (primitiveValue->getValueID() == CSSValueAuto) { - state.style()->accessSVGStyle()->setGlyphOrientationVertical(GO_AUTO); + case CSSValueSuper: + svgStyle->setBaselineShift(BS_SUPER); + break; + default: break; } - EGlyphOrientation orientation; - if (degreeToGlyphOrientation(primitiveValue, orientation)) - state.style()->accessSVGStyle()->setGlyphOrientationVertical(orientation); - break; - } - case CSSPropertyEnableBackground: - // Silently ignoring this property for now - // http://bugs.webkit.org/show_bug.cgi?id=6022 - break; + } else { + svgStyle->setBaselineShift(BS_LENGTH); + svgStyle->setBaselineShiftValue(SVGLength::fromCSSPrimitiveValue(primitiveValue)); } } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp index bc5cbdab5db..28b0cc9254b 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp @@ -29,41 +29,42 @@ #include "config.h" #include "core/css/resolver/StyleResolver.h" -#include "CSSPropertyNames.h" -#include "HTMLNames.h" -#include "RuntimeEnabledFeatures.h" -#include "StylePropertyShorthand.h" +#include "core/CSSPropertyNames.h" +#include "core/HTMLNames.h" +#include "core/StylePropertyShorthand.h" #include "core/animation/ActiveAnimations.h" -#include "core/animation/AnimatableLength.h" #include "core/animation/AnimatableValue.h" #include "core/animation/Animation.h" -#include "core/animation/DocumentTimeline.h" +#include "core/animation/AnimationTimeline.h" #include "core/animation/css/CSSAnimatableValueFactory.h" #include "core/animation/css/CSSAnimations.h" +#include "core/animation/interpolation/StyleInterpolation.h" #include "core/css/CSSCalculationValue.h" #include "core/css/CSSDefaultStyleSheets.h" -#include "core/css/CSSFontFace.h" #include "core/css/CSSFontSelector.h" #include "core/css/CSSKeyframeRule.h" #include "core/css/CSSKeyframesRule.h" -#include "core/css/CSSParser.h" #include "core/css/CSSReflectValue.h" #include "core/css/CSSRuleList.h" #include "core/css/CSSSelector.h" #include "core/css/CSSStyleRule.h" #include "core/css/CSSValueList.h" -#include "core/css/CSSVariableValue.h" +#include "core/css/CSSValuePool.h" #include "core/css/ElementRuleCollector.h" +#include "core/css/FontFace.h" #include "core/css/MediaQueryEvaluator.h" #include "core/css/PageRuleCollector.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRuleImport.h" #include "core/css/StyleSheetContents.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/resolver/AnimatedStyleBuilder.h" #include "core/css/resolver/MatchResult.h" #include "core/css/resolver/MediaQueryResult.h" #include "core/css/resolver/SharedStyleFinder.h" #include "core/css/resolver/StyleAdjuster.h" +#include "core/css/resolver/StyleResolverParentScope.h" +#include "core/css/resolver/StyleResolverState.h" #include "core/css/resolver/StyleResolverStats.h" #include "core/css/resolver/ViewportStyleResolver.h" #include "core/dom/CSSSelectorWatch.h" @@ -72,20 +73,18 @@ #include "core/dom/Text.h" #include "core/dom/shadow/ElementShadow.h" #include "core/dom/shadow/ShadowRoot.h" +#include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLIFrameElement.h" #include "core/inspector/InspectorInstrumentation.h" -#include "core/frame/Frame.h" -#include "core/frame/FrameView.h" #include "core/rendering/RenderView.h" #include "core/rendering/style/KeyframeList.h" -#include "core/rendering/style/StyleCustomFilterProgramCache.h" #include "core/svg/SVGDocumentExtensions.h" #include "core/svg/SVGElement.h" #include "core/svg/SVGFontFaceElement.h" +#include "platform/RuntimeEnabledFeatures.h" #include "wtf/StdLibExtras.h" -using namespace std; - namespace { using namespace WebCore; @@ -94,8 +93,8 @@ void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element) { // If any changes to CSS Animations were detected, stash the update away for application after the // render object is updated if we're in the appropriate scope. - if (RuntimeEnabledFeatures::webAnimationsCSSEnabled() && state.animationUpdate()) - element.ensureActiveAnimations()->cssAnimations().setPendingUpdate(state.takeAnimationUpdate()); + if (state.animationUpdate()) + element.ensureActiveAnimations().cssAnimations().setPendingUpdate(state.takeAnimationUpdate()); } } // namespace @@ -124,9 +123,9 @@ static StylePropertySet* rightToLeftDeclaration() static void addFontFaceRule(Document* document, CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule) { - RefPtr<CSSFontFace> cssFontFace = CSSFontFace::createFromStyleRule(document, fontFaceRule); - if (cssFontFace) - cssFontSelector->addFontFaceRule(fontFaceRule, cssFontFace); + RefPtrWillBeRawPtr<FontFace> fontFace = FontFace::create(document, fontFaceRule); + if (fontFace) + cssFontSelector->fontFaceCache()->add(cssFontSelector, fontFaceRule, fontFace); } StyleResolver::StyleResolver(Document& document) @@ -134,46 +133,31 @@ StyleResolver::StyleResolver(Document& document) , m_viewportStyleResolver(ViewportStyleResolver::create(&document)) , m_needCollectFeatures(false) , m_styleResourceLoader(document.fetcher()) + , m_styleSharingDepth(0) , m_styleResolverStatsSequence(0) , m_accessCount(0) { - // FIXME: Why do this here instead of as part of resolving style on the root? - CSSDefaultStyleSheets::loadDefaultStylesheetIfNecessary(); - - // Construct document root element default style. This is needed - // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)" - // This is here instead of constructor because when constructor is run, - // Document doesn't have documentElement. - // NOTE: This assumes that element that gets passed to the styleForElement call - // is always from the document that owns the StyleResolver. FrameView* view = document.view(); if (view) - m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType())); + m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), &view->frame())); else m_medium = adoptPtr(new MediaQueryEvaluator("all")); - Element* root = document.documentElement(); - if (root) - m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules); - - if (m_rootDefaultStyle && view) - m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), &view->frame(), m_rootDefaultStyle.get())); - m_styleTree.clear(); initWatchedSelectorRules(CSSSelectorWatch::from(document).watchedCallbackSelectors()); #if ENABLE(SVG_FONTS) if (document.svgExtensions()) { - const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements(); - HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end(); - for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it) + const WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements(); + WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator end = svgFontFaceElements.end(); + for (WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator it = svgFontFaceElements.begin(); it != end; ++it) addFontFaceRule(&document, document.styleEngine()->fontSelector(), (*it)->fontFaceRule()); } #endif } -void StyleResolver::initWatchedSelectorRules(const Vector<RefPtr<StyleRule> >& watchedSelectors) +void StyleResolver::initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedSelectors) { if (!watchedSelectors.size()) return; @@ -182,14 +166,14 @@ void StyleResolver::initWatchedSelectorRules(const Vector<RefPtr<StyleRule> >& w m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(), RuleHasNoSpecialState); } -void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets) +void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets) { unsigned size = styleSheets.size(); for (unsigned i = firstNew; i < size; ++i) m_pendingStyleSheets.add(styleSheets[i].get()); } -void StyleResolver::removePendingAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& styleSheets) +void StyleResolver::removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets) { for (unsigned i = 0; i < styleSheets.size(); ++i) m_pendingStyleSheets.remove(styleSheets[i].get()); @@ -202,33 +186,31 @@ void StyleResolver::appendCSSStyleSheet(CSSStyleSheet* cssSheet) if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults)) return; - StyleSheetContents* sheet = cssSheet->contents(); ContainerNode* scopingNode = ScopedStyleResolver::scopingNodeFor(document(), cssSheet); if (!scopingNode) return; ScopedStyleResolver* resolver = ensureScopedStyleResolver(scopingNode); ASSERT(resolver); - resolver->addRulesFromSheet(sheet, *m_medium, this); - m_inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet); + resolver->addRulesFromSheet(cssSheet, *m_medium, this); } void StyleResolver::appendPendingAuthorStyleSheets() { setBuildScopedStyleTreeInDocumentOrder(false); - for (ListHashSet<CSSStyleSheet*, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it) + for (WillBeHeapListHashSet<RawPtrWillBeMember<CSSStyleSheet>, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it) appendCSSStyleSheet(*it); m_pendingStyleSheets.clear(); finishAppendAuthorStyleSheets(); } -void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets) +void StyleResolver::appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets) { // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated. unsigned size = styleSheets.size(); - for (unsigned i = firstNew; i < size; ++i) + for (unsigned i = 0; i < size; ++i) appendCSSStyleSheet(styleSheets[i].get()); } @@ -236,8 +218,8 @@ void StyleResolver::finishAppendAuthorStyleSheets() { collectFeatures(); - if (document().renderer() && document().renderer()->style()) - document().renderer()->style()->font().update(document().styleEngine()->fontSelector()); + if (document().renderView() && document().renderView()->style()) + document().renderView()->style()->font().update(document().styleEngine()->fontSelector()); collectViewportRules(); @@ -253,43 +235,31 @@ void StyleResolver::resetRuleFeatures() m_needCollectFeatures = true; } -void StyleResolver::addTreeBoundaryCrossingRules(const Vector<MinimalRuleData>& rules, ContainerNode* scope) +void StyleResolver::processScopedRules(const RuleSet& authorRules, CSSStyleSheet* parentStyleSheet, ContainerNode& scope) { - for (unsigned i = 0; i < rules.size(); ++i) { - const MinimalRuleData& info = rules[i]; - m_treeBoundaryCrossingRules.addRule(info.m_rule, info.m_selectorIndex, scope, info.m_flags); - } -} - -void StyleResolver::processScopedRules(const RuleSet& authorRules, const KURL& sheetBaseURL, ContainerNode* scope) -{ - const Vector<StyleRuleKeyframes*> keyframesRules = authorRules.keyframesRules(); + const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > keyframesRules = authorRules.keyframesRules(); for (unsigned i = 0; i < keyframesRules.size(); ++i) - ensureScopedStyleResolver(scope)->addKeyframeStyle(keyframesRules[i]); + ensureScopedStyleResolver(&scope)->addKeyframeStyle(keyframesRules[i]); - addTreeBoundaryCrossingRules(authorRules.treeBoundaryCrossingRules(), scope); + m_treeBoundaryCrossingRules.addTreeBoundaryCrossingRules(authorRules, scope, parentStyleSheet); // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment. - if (!scope || scope->isDocumentNode()) { - const Vector<StyleRuleFontFace*> fontFaceRules = authorRules.fontFaceRules(); + if (scope.isDocumentNode()) { + const WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> > fontFaceRules = authorRules.fontFaceRules(); for (unsigned i = 0; i < fontFaceRules.size(); ++i) addFontFaceRule(&m_document, document().styleEngine()->fontSelector(), fontFaceRules[i]); if (fontFaceRules.size()) invalidateMatchedPropertiesCache(); - } else { - addTreeBoundaryCrossingRules(authorRules.shadowDistributedRules(), scope); } } void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode) { - // FIXME: When chanking scoped attribute, scopingNode's hasScopedHTMLStyleChild has been already modified. - // So we cannot use hasScopedHTMLStyleChild flag here. ScopedStyleResolver* resolver = scopingNode ? m_styleTree.lookupScopedStyleResolverFor(scopingNode) : m_styleTree.scopedStyleResolverForDocument(); if (!resolver) return; - treeBoundaryCrossingRules().reset(scopingNode); + m_treeBoundaryCrossingRules.reset(scopingNode); resolver->resetAuthorStyle(); resetRuleFeatures(); @@ -299,12 +269,12 @@ void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode) m_styleTree.remove(scopingNode); } -static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules) +static PassOwnPtrWillBeRawPtr<RuleSet> makeRuleSet(const WillBeHeapVector<RuleFeature>& rules) { size_t size = rules.size(); if (!size) return nullptr; - OwnPtr<RuleSet> ruleSet = RuleSet::create(); + OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create(); for (size_t i = 0; i < size; ++i) ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState); return ruleSet.release(); @@ -316,11 +286,15 @@ void StyleResolver::collectFeatures() // Collect all ids and rules using sibling selectors (:first-child and similar) // in the current set of stylesheets. Style sharing code uses this information to reject // sharing candidates. - if (CSSDefaultStyleSheets::defaultStyle) - m_features.add(CSSDefaultStyleSheets::defaultStyle->features()); + CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance(); + if (defaultStyleSheets.defaultStyle()) + m_features.add(defaultStyleSheets.defaultStyle()->features()); if (document().isViewSource()) - m_features.add(CSSDefaultStyleSheets::viewSourceStyle()->features()); + m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features()); + + if (document().isTransitionDocument()) + m_features.add(defaultStyleSheets.defaultTransitionStyle()->features()); if (m_watchedSelectorsRules) m_features.add(m_watchedSelectorsRules->features()); @@ -336,7 +310,7 @@ void StyleResolver::collectFeatures() bool StyleResolver::hasRulesForId(const AtomicString& id) const { - return m_features.idsInRules.contains(id); + return m_features.hasSelectorForId(id); } void StyleResolver::addToStyleSharingList(Element& element) @@ -346,20 +320,29 @@ void StyleResolver::addToStyleSharingList(Element& element) if (!document().inStyleRecalc()) return; INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates); - if (m_styleSharingList.size() >= styleSharingListSize) - m_styleSharingList.remove(--m_styleSharingList.end()); - m_styleSharingList.prepend(&element); + StyleSharingList& list = styleSharingList(); + if (list.size() >= styleSharingListSize) + list.remove(--list.end()); + list.prepend(&element); } -void StyleResolver::clearStyleSharingList() +StyleSharingList& StyleResolver::styleSharingList() { - m_styleSharingList.clear(); + m_styleSharingLists.resize(styleSharingMaxDepth); + + // We never put things at depth 0 into the list since that's only the <html> element + // and it has no siblings or cousins to share with. + unsigned depth = std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u; + ASSERT(depth >= 0); + + if (!m_styleSharingLists[depth]) + m_styleSharingLists[depth] = adoptPtr(new StyleSharingList); + return *m_styleSharingLists[depth]; } -void StyleResolver::fontsNeedUpdate(FontSelector* fontSelector) +void StyleResolver::clearStyleSharingList() { - invalidateMatchedPropertiesCache(); - m_document.setNeedsStyleRecalc(); + m_styleSharingLists.resize(0); } void StyleResolver::pushParentElement(Element& parent) @@ -403,39 +386,11 @@ void StyleResolver::popParentShadowRoot(const ShadowRoot& shadowRoot) StyleResolver::~StyleResolver() { - m_viewportStyleResolver->clearDocument(); -} - -inline void StyleResolver::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules) -{ - if (m_treeBoundaryCrossingRules.isEmpty()) - return; - - RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange(); - - CascadeOrder cascadeOrder = 0; - - DocumentOrderedList::iterator it = m_treeBoundaryCrossingRules.end(); - while (it != m_treeBoundaryCrossingRules.begin()) { - --it; - const ContainerNode* scopingNode = toContainerNode(*it); - RuleSet* ruleSet = m_treeBoundaryCrossingRules.ruleSetScopedBy(scopingNode); - unsigned boundaryBehavior = SelectorChecker::CrossesBoundary | SelectorChecker::ScopeContainsLastMatchedElement; - - // If a given scoping node is a shadow root and a given element is in a descendant tree of tree hosted by - // the scoping node's shadow host, we should use ScopeIsShadowHost. - if (scopingNode && scopingNode->isShadowRoot()) { - if (element->isInDescendantTreeOf(toShadowRoot(scopingNode)->host())) - boundaryBehavior |= SelectorChecker::ScopeIsShadowHost; - scopingNode = toShadowRoot(scopingNode)->host(); - } - collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder++); - } } static inline bool applyAuthorStylesOf(const Element* element) { - return element->treeScope().applyAuthorStyles() || (element->shadow() && element->shadow()->applyAuthorStyles()); + return element->treeScope().applyAuthorStyles(); } void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleCollector& collector, bool includeEmptyRules, Vector<ScopedStyleResolver*, 8>& resolvers, Vector<ScopedStyleResolver*, 8>& resolversInShadowTree) @@ -456,7 +411,7 @@ void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleC for (unsigned i = 0; i < resolvers.size(); ++i) resolvers.at(i)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, --cascadeOrder); - collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); + m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); collector.sortAndTransferMatchedRules(); } @@ -468,7 +423,7 @@ void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& col bool applyAuthorStyles = applyAuthorStylesOf(element); if (m_styleTree.hasOnlyScopedResolverForDocument()) { m_styleTree.scopedStyleResolverForDocument()->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, ignoreCascadeScope); - collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); + m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); collector.sortAndTransferMatchedRules(); return; } @@ -494,7 +449,7 @@ void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& col resolver->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->scopingNode().isShadowRoot() ? 0 : cascadeOrder); } - collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); + m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules); collector.sortAndTransferMatchedRules(); } @@ -509,7 +464,6 @@ void StyleResolver::matchWatchSelectorRules(ElementRuleCollector& collector) MatchRequest matchRequest(m_watchedSelectorsRules.get()); RuleRange ruleRange = collector.matchedResult().ranges.userRuleRange(); collector.collectMatchingRules(matchRequest, ruleRange); - collector.collectMatchingRulesForRegion(matchRequest, ruleRange); collector.sortAndTransferMatchedRules(); } @@ -518,17 +472,21 @@ void StyleResolver::matchUARules(ElementRuleCollector& collector) { collector.setMatchingUARules(true); + CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance(); RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print") - ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle; + ? defaultStyleSheets.defaultPrintStyle() : defaultStyleSheets.defaultStyle(); matchUARules(collector, userAgentStyleSheet); // In quirks mode, we match rules from the quirks user agent sheet. if (document().inQuirksMode()) - matchUARules(collector, CSSDefaultStyleSheets::defaultQuirksStyle); + matchUARules(collector, defaultStyleSheets.defaultQuirksStyle()); // 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 (document().isViewSource()) - matchUARules(collector, CSSDefaultStyleSheets::viewSourceStyle()); + matchUARules(collector, defaultStyleSheets.defaultViewSourceStyle()); + + if (document().isTransitionDocument()) + matchUARules(collector, defaultStyleSheets.defaultTransitionStyle()); collector.setMatchingUARules(false); @@ -582,33 +540,20 @@ void StyleResolver::matchAllRules(StyleResolverState& state, ElementRuleCollecto } } -PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document, CSSFontSelector* fontSelector) +PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document) { - const Frame* frame = document.frame(); + const LocalFrame* frame = document.frame(); - // HTML5 states that seamless iframes should replace default CSS values - // with values inherited from the containing iframe element. However, - // some values (such as the case of designMode = "on") still need to - // be set by this "document style". RefPtr<RenderStyle> documentStyle = RenderStyle::create(); - bool seamlessWithParent = document.shouldDisplaySeamlesslyWithParent(); - if (seamlessWithParent) { - RenderStyle* iframeStyle = document.seamlessParentIFrame()->renderStyle(); - if (iframeStyle) - documentStyle->inheritFrom(iframeStyle); - } - - // FIXME: It's not clear which values below we want to override in the seamless case! documentStyle->setDisplay(BLOCK); - if (!seamlessWithParent) { - documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder); - documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1); - documentStyle->setLocale(document.contentLanguage()); - } - // This overrides any -webkit-user-modify inherited from the parent iframe. + documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder); + documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1); + documentStyle->setLocale(document.contentLanguage()); + documentStyle->setZIndex(0); documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE : READ_ONLY); - document.setStyleDependentState(documentStyle.get()); + document.setupFontBuilder(documentStyle.get()); + return documentStyle.release(); } @@ -631,11 +576,24 @@ static inline void resetDirectionAndWritingModeOnDocument(Document& document) static void addContentAttrValuesToFeatures(const Vector<AtomicString>& contentAttrValues, RuleFeatureSet& features) { for (size_t i = 0; i < contentAttrValues.size(); ++i) - features.attrsInRules.add(contentAttrValues[i]); + features.addContentAttr(contentAttrValues[i]); +} + +void StyleResolver::adjustRenderStyle(StyleResolverState& state, Element* element) +{ + StyleAdjuster adjuster(m_document.inQuirksMode()); + adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element, state.cachedUAStyle()); +} + +// Start loading resources referenced by this style. +void StyleResolver::loadPendingResources(StyleResolverState& state) +{ + m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources()); + document().styleEngine()->fontSelector()->fontLoader()->loadPendingFonts(); } PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, StyleSharingBehavior sharingBehavior, - RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling) + RuleMatchingBehavior matchingBehavior) { ASSERT(document().frame()); ASSERT(documentSettings()); @@ -644,23 +602,26 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer // will vanish if a style recalc happens during loading. - if (sharingBehavior == AllowStyleSharing && !element->document().haveStylesheetsLoaded() && !element->renderer()) { + if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() && !element->renderer()) { if (!s_styleNotYetAvailable) { s_styleNotYetAvailable = RenderStyle::create().leakRef(); s_styleNotYetAvailable->setDisplay(NONE); s_styleNotYetAvailable->font().update(document().styleEngine()->fontSelector()); } - element->document().setHasNodesWithPlaceholderStyle(); + + document().setHasNodesWithPlaceholderStyle(); return s_styleNotYetAvailable; } didAccess(); + StyleResolverParentScope::ensureParentStackIsPushed(); + if (element == document().documentElement()) resetDirectionAndWritingModeOnDocument(document()); - StyleResolverState state(document(), element, defaultParent, regionForStyling); + StyleResolverState state(document(), element, defaultParent); - if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoint() && state.parentStyle()) { + if (sharingBehavior == AllowStyleSharing && state.parentStyle()) { SharedStyleFinder styleFinder(state.elementContext(), m_features, m_siblingRuleSet.get(), m_uncommonAttributeRuleSet.get(), *this); if (RefPtr<RenderStyle> sharedStyle = styleFinder.findSharedStyle()) return sharedStyle.release(); @@ -682,7 +643,7 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS } } - state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules()); + state.fontBuilder().initForStyleResolve(state.document(), state.style()); if (element->isLink()) { state.style()->setIsLink(true); @@ -696,41 +657,40 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS } bool needsCollection = false; - CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection); - if (needsCollection) { + CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(element, needsCollection); + if (needsCollection) collectFeatures(); - m_inspectorCSSOMWrappers.reset(); - } { ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); - collector.setRegionForStyling(regionForStyling); - if (matchingBehavior == MatchOnlyUserAgentRules) - matchUARules(collector); - else - matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL); + matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL); applyMatchedProperties(state, collector.matchedResult()); addContentAttrValuesToFeatures(state.contentAttrValues(), m_features); } - { - StyleAdjuster adjuster(state.cachedUAStyle(), m_document.inQuirksMode()); - adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element); - } + + // Cache our original display. + state.style()->setOriginalDisplay(state.style()->display()); + + adjustRenderStyle(state, element); // FIXME: The CSSWG wants to specify that the effects of animations are applied before // important rules, but this currently happens here as we require adjustment to have happened // before deciding which properties to transition. - applyAnimatedProperties(state, element); + if (applyAnimatedProperties(state, element)) + adjustRenderStyle(state, element); // FIXME: Shouldn't this be on RenderBody::styleDidChange? - if (element->hasTagName(bodyTag)) + if (isHTMLBodyElement(*element)) document().textLinkColors().setTextColor(state.style()->color()); setAnimationUpdateIfNeeded(state, *element); + if (state.style()->hasViewportUnits()) + document().setHasViewportUnits(); + // Now return the style. return state.takeStyle(); } @@ -746,8 +706,7 @@ PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* element, const StyleResolverState state(document(), element, parentStyle); MatchResult result; - if (keyframe->properties()) - result.addMatchedProperties(keyframe->properties()); + result.addMatchedProperties(&keyframe->properties()); ASSERT(!state.style()); @@ -755,28 +714,15 @@ PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* element, const state.setStyle(RenderStyle::clone(&elementStyle)); state.setLineHeightValue(0); - // Make sure that the CSSAnimationData for the animation to which this - // keyframe belongs is first in the list. This makes sure that if the - // animation-timing-function property is set for this keyframe, it will be - // applied to the correct CSSAnimationData object. Note that objects other - // than the first in the list are ignored when reading the timing function - // value. See KeyframeValue::timingFunction(). - CSSAnimationDataList* animations = state.style()->accessAnimations(); - ASSERT(animations && !animations->isEmpty()); - while (animations->animation(0)->name() != animationName) - animations->remove(0); - ASSERT(!animations->isEmpty() && animations->animation(0)->name() == animationName); - - state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules()); + state.fontBuilder().initForStyleResolve(state.document(), state.style()); // We don't need to bother with !important. Since there is only ever one // decl, there's nothing to override. So just add the first properties. + // We also don't need to bother with animation properties since the only + // relevant one is animation-timing-function and we special-case that in + // CSSAnimations.cpp bool inheritedOnly = false; - if (keyframe->properties()) { - // FIXME: Can't keyframes contain variables? - applyMatchedProperties<AnimationProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); - applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); - } + applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); // If our font got dirtied, go ahead and update it now. updateFont(state); @@ -786,124 +732,73 @@ PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* element, const StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue()); // Now do rest of the properties. - if (keyframe->properties()) - applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); + applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); // If our font got dirtied by one of the non-essential font props, // go ahead and update it a second time. updateFont(state); - // Start loading resources referenced by this style. - m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources()); - document().styleEngine()->fontSelector()->loadPendingFonts(); + loadPendingResources(state); didAccess(); return state.takeStyle(); } -void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle& elementStyle, KeyframeList& list) -{ - ASSERT(!RuntimeEnabledFeatures::webAnimationsCSSEnabled()); - list.clear(); - - // Get the keyframesRule for this name - if (!e || list.animationName().isEmpty()) - return; - - ASSERT(!hasPendingAuthorStyleSheets()); - const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScopedKeyframesRule(this, e, list.animationName().impl()); - if (!keyframesRule) - return; - - // Construct and populate the style for each keyframe - const AtomicString& name = list.animationName(); - const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes(); - for (unsigned i = 0; i < keyframes.size(); ++i) { - // Apply the declaration to the style. This is a simplified version of the logic in styleForElement - const StyleKeyframe* keyframe = keyframes[i].get(); - - KeyframeValue keyframeValue(0, 0); - keyframeValue.setStyle(styleForKeyframe(e, elementStyle, 0, keyframe, name)); - keyframeValue.addProperties(keyframe->properties()); - - // Add this keyframe style to all the indicated key times - const Vector<double>& keys = keyframe->keys(); - for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) { - keyframeValue.setKey(keys[keyIndex]); - list.insert(keyframeValue); - } - } - - // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe) - int initialListSize = list.size(); - if (initialListSize > 0 && list[0].key()) { - static StyleKeyframe* zeroPercentKeyframe; - if (!zeroPercentKeyframe) { - zeroPercentKeyframe = StyleKeyframe::create().leakRef(); - zeroPercentKeyframe->setKeyText("0%"); - } - KeyframeValue keyframeValue(0, 0); - keyframeValue.setStyle(styleForKeyframe(e, elementStyle, 0, zeroPercentKeyframe, name)); - keyframeValue.addProperties(zeroPercentKeyframe->properties()); - list.insert(keyframeValue); - } - - // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe) - if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) { - static StyleKeyframe* hundredPercentKeyframe; - if (!hundredPercentKeyframe) { - hundredPercentKeyframe = StyleKeyframe::create().leakRef(); - hundredPercentKeyframe->setKeyText("100%"); - } - KeyframeValue keyframeValue(1, 0); - keyframeValue.setStyle(styleForKeyframe(e, elementStyle, 0, hundredPercentKeyframe, name)); - keyframeValue.addProperties(hundredPercentKeyframe->properties()); - list.insert(keyframeValue); - } -} - // This function is used by the WebAnimations JavaScript API method animate(). // FIXME: Remove this when animate() switches away from resolution-dependent parsing. -PassRefPtr<KeyframeAnimationEffect> StyleResolver::createKeyframeAnimationEffect(Element& element, const Vector<RefPtr<MutableStylePropertySet> >& propertySetVector, KeyframeAnimationEffect::KeyframeVector& keyframes) +PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(Element& element, CSSPropertyID property, CSSValue& value) { - ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled()); - ASSERT(propertySetVector.size() == keyframes.size()); - + RefPtr<RenderStyle> style; + if (element.renderStyle()) + style = RenderStyle::clone(element.renderStyle()); + else + style = RenderStyle::create(); StyleResolverState state(element.document(), &element); - state.setStyle(RenderStyle::create()); + state.setStyle(style); + state.fontBuilder().initForStyleResolve(state.document(), state.style()); + return createAnimatableValueSnapshot(state, property, value); +} - for (unsigned i = 0; i < propertySetVector.size(); ++i) { - for (unsigned j = 0; j < propertySetVector[i]->propertyCount(); ++j) { - CSSPropertyID id = propertySetVector[i]->propertyAt(j).id(); - StyleBuilder::applyProperty(id, state, propertySetVector[i]->getPropertyCSSValue(id).get()); - keyframes[i]->setPropertyValue(id, CSSAnimatableValueFactory::create(id, *state.style()).get()); - } - } - return KeyframeAnimationEffect::create(keyframes); +PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(StyleResolverState& state, CSSPropertyID property, CSSValue& value) +{ + StyleBuilder::applyProperty(property, state, &value); + return CSSAnimatableValueFactory::create(property, *state.style()); } -PassRefPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& element, PseudoId pseudoId) +PassRefPtrWillBeRawPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& parent, PseudoId pseudoId) { - RenderObject* renderer = element.renderer(); - if (!renderer) - return 0; + RenderObject* parentRenderer = parent.renderer(); + if (!parentRenderer) + return nullptr; + + if (pseudoId < FIRST_INTERNAL_PSEUDOID && !parentRenderer->style()->hasPseudoStyle(pseudoId)) + return nullptr; - if (pseudoId < FIRST_INTERNAL_PSEUDOID && !renderer->style()->hasPseudoStyle(pseudoId)) - return 0; + if (pseudoId == BACKDROP && !parent.isInTopLayer()) + return nullptr; + + if (!parentRenderer->canHaveGeneratedChildren()) + return nullptr; - RenderStyle* parentStyle = renderer->style(); - StyleResolverState state(document(), &element, parentStyle); - if (!pseudoStyleForElementInternal(element, pseudoId, parentStyle, state)) - return 0; + RenderStyle* parentStyle = parentRenderer->style(); + if (RenderStyle* cachedStyle = parentStyle->getCachedPseudoStyle(pseudoId)) { + if (!pseudoElementRendererIsNeeded(cachedStyle)) + return nullptr; + return PseudoElement::create(&parent, pseudoId); + } + + StyleResolverState state(document(), &parent, parentStyle); + if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state)) + return nullptr; RefPtr<RenderStyle> style = state.takeStyle(); ASSERT(style); + parentStyle->addCachedPseudoStyle(style); - if (!element.needsPseudoElement(pseudoId, *style)) - return 0; + if (!pseudoElementRendererIsNeeded(style.get())) + return nullptr; - renderer->style()->addCachedPseudoStyle(style.release()); - RefPtr<PseudoElement> pseudo = PseudoElement::create(&element, pseudoId); + RefPtrWillBeRawPtr<PseudoElement> pseudo = PseudoElement::create(&parent, pseudoId); setAnimationUpdateIfNeeded(state, *pseudo); if (ActiveAnimations* activeAnimations = pseudo->activeAnimations()) @@ -917,6 +812,8 @@ bool StyleResolver::pseudoStyleForElementInternal(Element& element, const Pseudo ASSERT(documentSettings()); ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED); + StyleResolverParentScope::ensureParentStackIsPushed(); + if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) { state.setStyle(RenderStyle::create()); state.style()->inheritFrom(state.parentStyle()); @@ -925,7 +822,7 @@ bool StyleResolver::pseudoStyleForElementInternal(Element& element, const Pseudo state.setParentStyle(RenderStyle::clone(state.style())); } - state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules()); + state.fontBuilder().initForStyleResolve(state.document(), state.style()); // Since we don't use pseudo-elements in any of our quirk/print // user agent rules, don't waste time walking those rules. @@ -947,20 +844,25 @@ bool StyleResolver::pseudoStyleForElementInternal(Element& element, const Pseudo addContentAttrValuesToFeatures(state.contentAttrValues(), m_features); } - { - StyleAdjuster adjuster(state.cachedUAStyle(), m_document.inQuirksMode()); - // FIXME: Passing 0 as the Element* introduces a lot of complexity - // in the adjustRenderStyle code. - adjuster.adjustRenderStyle(state.style(), state.parentStyle(), 0); - } + + // Cache our original display. + state.style()->setOriginalDisplay(state.style()->display()); + + // FIXME: Passing 0 as the Element* introduces a lot of complexity + // in the adjustRenderStyle code. + adjustRenderStyle(state, 0); // FIXME: The CSSWG wants to specify that the effects of animations are applied before // important rules, but this currently happens here as we require adjustment to have happened // before deciding which properties to transition. - applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId)); + if (applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId))) + adjustRenderStyle(state, 0); didAccess(); + if (state.style()->hasViewportUnits()) + document().setHasViewportUnits(); + return true; } @@ -968,11 +870,11 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, c { ASSERT(parentStyle); if (!element) - return 0; + return nullptr; StyleResolverState state(document(), element, parentStyle); if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state)) - return 0; + return nullptr; if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId)) setAnimationUpdateIfNeeded(state, *pseudoElement); @@ -992,11 +894,11 @@ PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) ASSERT(rootElementStyle); state.style()->inheritFrom(rootElementStyle); - state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules()); + state.fontBuilder().initForStyleResolve(state.document(), state.style()); PageRuleCollector collector(rootElementStyle, pageIndex); - collector.matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle); + collector.matchPageRules(CSSDefaultStyleSheets::instance().defaultPrintStyle()); if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument()) scopedResolver->matchPageRules(collector); @@ -1005,7 +907,6 @@ PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) bool inheritedOnly = false; MatchResult& result = collector.matchedResult(); - applyMatchedProperties<VariableDefinitions>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly); // If our font got dirtied, go ahead and update it now. @@ -1019,9 +920,7 @@ PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) addContentAttrValuesToFeatures(state.contentAttrValues(), m_features); - // Start loading resources referenced by this style. - m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources()); - document().styleEngine()->fontSelector()->loadPendingFonts(); + loadPendingResources(state); didAccess(); @@ -1031,13 +930,14 @@ PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) void StyleResolver::collectViewportRules() { - viewportStyleResolver()->collectViewportRules(CSSDefaultStyleSheets::defaultStyle, ViewportStyleResolver::UserAgentOrigin); + CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance(); + viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultStyle(), ViewportStyleResolver::UserAgentOrigin); if (!InspectorInstrumentation::applyViewportStyleOverride(&document(), this)) - viewportStyleResolver()->collectViewportRules(CSSDefaultStyleSheets::defaultViewportStyle, ViewportStyleResolver::UserAgentOrigin); + viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultViewportStyle(), ViewportStyleResolver::UserAgentOrigin); if (document().isMobileDocument()) - viewportStyleResolver()->collectViewportRules(CSSDefaultStyleSheets::xhtmlMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin); + viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultXHTMLMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin); if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument()) scopedResolver->collectViewportRulesTo(this); @@ -1049,7 +949,7 @@ PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement() { StyleResolverState state(document(), 0); state.setStyle(RenderStyle::create()); - state.fontBuilder().initForStyleResolve(document(), state.style(), state.useSVGZoomRules()); + state.fontBuilder().initForStyleResolve(document(), state.style()); state.style()->setLineHeight(RenderStyle::initialLineHeight()); state.setLineHeightValue(0); state.fontBuilder().setInitial(state.style()->effectiveZoom()); @@ -1063,28 +963,19 @@ PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode) NodeRenderingTraversal::ParentDetails parentDetails; Node* parentNode = NodeRenderingTraversal::parent(textNode, &parentDetails); - if (!parentNode || !parentNode->renderStyle() || parentDetails.resetStyleInheritance()) + if (!parentNode || !parentNode->renderStyle()) return defaultStyleForElement(); return parentNode->renderStyle(); } -bool StyleResolver::checkRegionStyle(Element* regionElement) -{ - // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment, - // so all region rules are global by default. Verify whether that can stand or needs changing. - if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument()) { - if (scopedResolver->checkRegionStyle(regionElement)) - return true; - } - return false; -} - void StyleResolver::updateFont(StyleResolverState& state) { state.fontBuilder().createFont(document().styleEngine()->fontSelector(), state.parentStyle(), state.style()); + if (state.fontBuilder().fontSizeHasViewportUnits()) + state.style()->setHasViewportUnits(); } -PassRefPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude) +PassRefPtrWillBeRawPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude) { ASSERT(element); StyleResolverState state(document(), element); @@ -1094,19 +985,19 @@ PassRefPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, return collector.matchedStyleRuleList(); } -PassRefPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude, ShouldIncludeStyleSheetInCSSOMWrapper includeDocument) +PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude) { ASSERT(element); StyleResolverState state(document(), element); - ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style(), includeDocument); + ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style()); collector.setMode(SelectorChecker::CollectingCSSRules); collectPseudoRulesForElement(element, collector, pseudoId, rulesToInclude); return collector.matchedCSSRuleList(); } -PassRefPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude, ShouldIncludeStyleSheetInCSSOMWrapper includeDocument) +PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude) { - return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude, includeDocument); + return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude); } void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCollector& collector, PseudoId pseudoId, unsigned rulesToInclude) @@ -1125,11 +1016,8 @@ void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCo // ------------------------------------------------------------------------------------- // this is mostly boring stuff on how to apply a certain rule to the renderstyle... -void StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* animatingElement) +bool StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* animatingElement) { - if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) - return; - const Element* element = state.element(); ASSERT(element); @@ -1139,61 +1027,45 @@ void StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element); if (!(animatingElement && animatingElement->hasActiveAnimations()) - && !(state.style()->transitions() && !state.style()->transitions()->isEmpty()) - && !(state.style()->animations() && !state.style()->animations()->isEmpty())) - return; + && !state.style()->transitions() && !state.style()->animations()) + return false; state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this)); if (!state.animationUpdate()) - return; + return false; + + const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations = state.animationUpdate()->activeInterpolationsForAnimations(); + const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions = state.animationUpdate()->activeInterpolationsForTransitions(); + applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForAnimations); + applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForTransitions); + + updateFont(state); + + applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForAnimations); + applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForTransitions); + + // Start loading resources used by animations. + loadPendingResources(state); - const AnimationEffect::CompositableValueMap& compositableValuesForAnimations = state.animationUpdate()->compositableValuesForAnimations(); - const AnimationEffect::CompositableValueMap& compositableValuesForTransitions = state.animationUpdate()->compositableValuesForTransitions(); - applyAnimatedProperties<HighPriorityProperties>(state, compositableValuesForAnimations); - applyAnimatedProperties<HighPriorityProperties>(state, compositableValuesForTransitions); - applyAnimatedProperties<LowPriorityProperties>(state, compositableValuesForAnimations); - applyAnimatedProperties<LowPriorityProperties>(state, compositableValuesForTransitions); + ASSERT(!state.fontBuilder().fontDirty()); - // If the animations/transitions change opacity or transform, we need to update - // the style to impose the stacking rules. Note that this is also - // done in StyleResolver::adjustRenderStyle(). - RenderStyle* style = state.style(); - if (style->hasAutoZIndex() && (style->opacity() < 1.0f || style->hasTransform())) - style->setZIndex(0); + return true; } template <StyleResolver::StyleApplicationPass pass> -void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const AnimationEffect::CompositableValueMap& compositableValues) +void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolations) { - ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled()); - ASSERT(pass != VariableDefinitions); ASSERT(pass != AnimationProperties); - for (AnimationEffect::CompositableValueMap::const_iterator iter = compositableValues.begin(); iter != compositableValues.end(); ++iter) { + for (WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >::const_iterator iter = activeInterpolations.begin(); iter != activeInterpolations.end(); ++iter) { CSSPropertyID property = iter->key; if (!isPropertyForPass<pass>(property)) continue; - ASSERT_WITH_MESSAGE(!iter->value->dependsOnUnderlyingValue(), "Web Animations not yet implemented: An interface for compositing onto the underlying value."); - RefPtr<AnimatableValue> animatableValue = iter->value->compositeOnto(0); - AnimatedStyleBuilder::applyProperty(property, state, animatableValue.get()); + const StyleInterpolation* interpolation = toStyleInterpolation(iter->value.get()); + interpolation->apply(state); } } -// http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule -// FIXME: add incremental support for other region styling properties. -static inline bool isValidRegionStyleProperty(CSSPropertyID id) -{ - switch (id) { - case CSSPropertyBackgroundColor: - case CSSPropertyColor: - return true; - default: - break; - } - - return false; -} - static inline bool isValidCueStyleProperty(CSSPropertyID id) { switch (id) { @@ -1242,36 +1114,237 @@ static inline bool isValidCueStyleProperty(CSSPropertyID id) return false; } +static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id) +{ + switch (id) { + // Valid ::first-letter properties listed in spec: + // http://www.w3.org/TR/css3-selectors/#application-in-css + case CSSPropertyBackgroundAttachment: + case CSSPropertyBackgroundBlendMode: + case CSSPropertyBackgroundClip: + case CSSPropertyBackgroundColor: + case CSSPropertyBackgroundImage: + case CSSPropertyBackgroundOrigin: + case CSSPropertyBackgroundPosition: + case CSSPropertyBackgroundPositionX: + case CSSPropertyBackgroundPositionY: + case CSSPropertyBackgroundRepeat: + case CSSPropertyBackgroundRepeatX: + case CSSPropertyBackgroundRepeatY: + case CSSPropertyBackgroundSize: + case CSSPropertyBorderBottomColor: + case CSSPropertyBorderBottomLeftRadius: + case CSSPropertyBorderBottomRightRadius: + case CSSPropertyBorderBottomStyle: + case CSSPropertyBorderBottomWidth: + case CSSPropertyBorderImageOutset: + case CSSPropertyBorderImageRepeat: + case CSSPropertyBorderImageSlice: + case CSSPropertyBorderImageSource: + case CSSPropertyBorderImageWidth: + case CSSPropertyBorderLeftColor: + case CSSPropertyBorderLeftStyle: + case CSSPropertyBorderLeftWidth: + case CSSPropertyBorderRightColor: + case CSSPropertyBorderRightStyle: + case CSSPropertyBorderRightWidth: + case CSSPropertyBorderTopColor: + case CSSPropertyBorderTopLeftRadius: + case CSSPropertyBorderTopRightRadius: + case CSSPropertyBorderTopStyle: + case CSSPropertyBorderTopWidth: + case CSSPropertyColor: + case CSSPropertyFloat: + case CSSPropertyFont: + case CSSPropertyFontFamily: + case CSSPropertyFontKerning: + case CSSPropertyFontSize: + case CSSPropertyFontStretch: + case CSSPropertyFontStyle: + case CSSPropertyFontVariant: + case CSSPropertyFontVariantLigatures: + case CSSPropertyFontWeight: + case CSSPropertyLetterSpacing: + case CSSPropertyLineHeight: + case CSSPropertyMarginBottom: + case CSSPropertyMarginLeft: + case CSSPropertyMarginRight: + case CSSPropertyMarginTop: + case CSSPropertyPaddingBottom: + case CSSPropertyPaddingLeft: + case CSSPropertyPaddingRight: + case CSSPropertyPaddingTop: + case CSSPropertyTextTransform: + case CSSPropertyVerticalAlign: + case CSSPropertyWebkitBackgroundClip: + case CSSPropertyWebkitBackgroundComposite: + case CSSPropertyWebkitBackgroundOrigin: + case CSSPropertyWebkitBackgroundSize: + case CSSPropertyWebkitBorderAfter: + case CSSPropertyWebkitBorderAfterColor: + case CSSPropertyWebkitBorderAfterStyle: + case CSSPropertyWebkitBorderAfterWidth: + case CSSPropertyWebkitBorderBefore: + case CSSPropertyWebkitBorderBeforeColor: + case CSSPropertyWebkitBorderBeforeStyle: + case CSSPropertyWebkitBorderBeforeWidth: + case CSSPropertyWebkitBorderEnd: + case CSSPropertyWebkitBorderEndColor: + case CSSPropertyWebkitBorderEndStyle: + case CSSPropertyWebkitBorderEndWidth: + case CSSPropertyWebkitBorderFit: + case CSSPropertyWebkitBorderHorizontalSpacing: + case CSSPropertyWebkitBorderImage: + case CSSPropertyWebkitBorderRadius: + case CSSPropertyWebkitBorderStart: + case CSSPropertyWebkitBorderStartColor: + case CSSPropertyWebkitBorderStartStyle: + case CSSPropertyWebkitBorderStartWidth: + case CSSPropertyWebkitBorderVerticalSpacing: + case CSSPropertyWebkitFontSmoothing: + case CSSPropertyWebkitMarginAfter: + case CSSPropertyWebkitMarginAfterCollapse: + case CSSPropertyWebkitMarginBefore: + case CSSPropertyWebkitMarginBeforeCollapse: + case CSSPropertyWebkitMarginBottomCollapse: + case CSSPropertyWebkitMarginCollapse: + case CSSPropertyWebkitMarginEnd: + case CSSPropertyWebkitMarginStart: + case CSSPropertyWebkitMarginTopCollapse: + case CSSPropertyWordSpacing: + return true; + case CSSPropertyTextDecorationColor: + case CSSPropertyTextDecorationLine: + case CSSPropertyTextDecorationStyle: + return RuntimeEnabledFeatures::css3TextDecorationsEnabled(); + + // text-shadow added in text decoration spec: + // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property + case CSSPropertyTextShadow: + // box-shadox added in CSS3 backgrounds spec: + // http://www.w3.org/TR/css3-background/#placement + case CSSPropertyBoxShadow: + case CSSPropertyWebkitBoxShadow: + // Properties that we currently support outside of spec. + case CSSPropertyWebkitLineBoxContain: + case CSSPropertyVisibility: + return true; + + default: + return false; + } +} + +// FIXME: Consider refactoring to create a new class which owns the following +// first/last/range properties. +// This method returns the first CSSPropertyId of properties which generate +// animations. All animation properties are obtained by using +// firstCSSPropertyId<AnimationProperties> and +// lastCSSPropertyId<AnimationProperties>. +// c.f. //src/third_party/WebKit/Source/core/css/CSSPropertyNames.in. +template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::AnimationProperties>() +{ + COMPILE_ASSERT(firstCSSProperty == CSSPropertyDisplay, CSS_first_animation_property_should_be_first_property); + return CSSPropertyDisplay; +} + +// This method returns the first CSSPropertyId of properties which generate +// animations. +template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::AnimationProperties>() +{ + COMPILE_ASSERT(CSSPropertyTransitionTimingFunction == CSSPropertyColor - 1, CSS_transition_timing_is_last_animation_property); + return CSSPropertyTransitionTimingFunction; +} + +// This method returns the first CSSPropertyId of high priority properties. +// Other properties can depend on high priority properties. For example, +// border-color property with currentColor value depends on color property. +// All high priority properties are obtained by using +// firstCSSPropertyId<HighPriorityProperties> and +// lastCSSPropertyId<HighPriorityProperties>. +template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::HighPriorityProperties>() +{ + COMPILE_ASSERT(CSSPropertyTransitionTimingFunction + 1 == CSSPropertyColor, CSS_color_is_first_high_priority_property); + return CSSPropertyColor; +} + +// This method returns the last CSSPropertyId of high priority properties. +template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::HighPriorityProperties>() +{ + COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyColor + 17, CSS_line_height_is_end_of_high_prioity_property_range); + COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyLineHeight - 1, CSS_zoom_is_before_line_height); + return CSSPropertyLineHeight; +} + +// This method returns the first CSSPropertyId of remaining properties, +// i.e. low priority properties. No properties depend on low priority +// properties. So we don't need to resolve such properties quickly. +// All low priority properties are obtained by using +// firstCSSPropertyId<LowPriorityProperties> and +// lastCSSPropertyId<LowPriorityProperties>. +template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::LowPriorityProperties>() +{ + COMPILE_ASSERT(CSSPropertyBackground == CSSPropertyLineHeight + 1, CSS_background_is_first_low_priority_property); + return CSSPropertyBackground; +} + +// This method returns the last CSSPropertyId of low priority properties. +template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::LowPriorityProperties>() +{ + return static_cast<CSSPropertyID>(lastCSSProperty); +} + template <StyleResolver::StyleApplicationPass pass> bool StyleResolver::isPropertyForPass(CSSPropertyID property) { - COMPILE_ASSERT(CSSPropertyVariable < firstCSSProperty, CSS_variable_is_before_first_property); - const CSSPropertyID firstAnimationProperty = CSSPropertyDisplay; - const CSSPropertyID lastAnimationProperty = CSSPropertyTransitionTimingFunction; - COMPILE_ASSERT(firstCSSProperty == firstAnimationProperty, CSS_first_animation_property_should_be_first_property); - const CSSPropertyID firstHighPriorityProperty = CSSPropertyColor; - const CSSPropertyID lastHighPriorityProperty = CSSPropertyLineHeight; - COMPILE_ASSERT(lastAnimationProperty + 1 == firstHighPriorityProperty, CSS_color_is_first_high_priority_property); - COMPILE_ASSERT(CSSPropertyLineHeight == firstHighPriorityProperty + 17, CSS_line_height_is_end_of_high_prioity_property_range); - COMPILE_ASSERT(CSSPropertyZoom == lastHighPriorityProperty - 1, CSS_zoom_is_before_line_height); - switch (pass) { - case VariableDefinitions: - return property == CSSPropertyVariable; - case AnimationProperties: - return property >= firstAnimationProperty && property <= lastAnimationProperty; - case HighPriorityProperties: - return property >= firstHighPriorityProperty && property <= lastHighPriorityProperty; - case LowPriorityProperties: - return property > lastHighPriorityProperty; + return firstCSSPropertyId<pass>() <= property && property <= lastCSSPropertyId<pass>(); +} + +// This method expands all shorthand property to longhand properties +// considering StyleApplicationPass, and apply each expanded longhand property. +// For example, if StyleApplicationPass is AnimationProperties, all shorthand +// is expaneded to display, -webkit-animation, -webkit-animation-delay, ..., +// transition-timing-function. So each property's value will be applied +// according to all's value (initial, inherit or unset). +template <StyleResolver::StyleApplicationPass pass> +void StyleResolver::applyAllProperty(StyleResolverState& state, CSSValue* allValue) +{ + bool isUnsetValue = !allValue->isInitialValue() && !allValue->isInheritedValue(); + unsigned startCSSProperty = firstCSSPropertyId<pass>(); + unsigned endCSSProperty = lastCSSPropertyId<pass>(); + + for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) { + CSSPropertyID propertyId = static_cast<CSSPropertyID>(i); + + // StyleBuilder does not allow any expanded shorthands. + if (isExpandedShorthandForAll(propertyId)) + continue; + + // all shorthand spec says: + // The all property is a shorthand that resets all CSS properties + // except direction and unicode-bidi. + // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand + // We skip applyProperty when a given property is unicode-bidi or + // direction. + if (!CSSProperty::isAffectedByAllProperty(propertyId)) + continue; + + CSSValue* value; + if (!isUnsetValue) { + value = allValue; + } else { + if (CSSProperty::isInheritedProperty(propertyId)) + value = cssValuePool().createInheritedValue().get(); + else + value = cssValuePool().createExplicitInitialValue().get(); + } + StyleBuilder::applyProperty(propertyId, state, value); } - ASSERT_NOT_REACHED(); - return false; } template <StyleResolver::StyleApplicationPass pass> void StyleResolver::applyProperties(StyleResolverState& state, const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType) { - ASSERT((propertyWhitelistType != PropertyWhitelistRegion) || state.regionForStyling()); state.setCurrentRule(rule); unsigned propertyCount = properties->propertyCount(); @@ -1279,6 +1352,13 @@ void StyleResolver::applyProperties(StyleResolverState& state, const StyleProper StylePropertySet::PropertyReference current = properties->propertyAt(i); if (isImportant != current.isImportant()) continue; + + CSSPropertyID property = current.id(); + if (property == CSSPropertyAll) { + applyAllProperty<pass>(state, current.value()); + continue; + } + if (inheritedOnly && !current.isInherited()) { // If the property value is explicitly inherited, we need to apply further non-inherited properties // as they might override the value inherited here. For this reason we don't allow declarations with @@ -1286,12 +1366,11 @@ void StyleResolver::applyProperties(StyleResolverState& state, const StyleProper ASSERT(!current.value()->isInheritedValue()); continue; } - CSSPropertyID property = current.id(); - if (propertyWhitelistType == PropertyWhitelistRegion && !isValidRegionStyleProperty(property)) - continue; if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(property)) continue; + if (propertyWhitelistType == PropertyWhitelistFirstLetter && !isValidFirstLetterStyleProperty(property)) + continue; if (!isPropertyForPass<pass>(property)) continue; if (pass == HighPriorityProperties && property == CSSPropertyLineHeight) @@ -1337,6 +1416,12 @@ void StyleResolver::invalidateMatchedPropertiesCache() m_matchedPropertiesCache.clear(); } +void StyleResolver::notifyResizeForViewportUnits() +{ + collectViewportRules(); + m_matchedPropertiesCache.clearViewportDependent(); +} + void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult) { const Element* element = state.element(); @@ -1355,7 +1440,8 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state, const Matc // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the // element context. This is fast and saves memory by reusing the style data structures. state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get()); - if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element)) { + if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element) + && (!state.distributedToInsertionPoint() || state.style()->userModify() == READ_ONLY)) { INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit); EInsideLink linkStatus = state.style()->insideLink(); @@ -1370,24 +1456,12 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state, const Matc applyInheritedOnly = true; } - // First apply all variable definitions, as they may be used during application of later properties. - applyMatchedProperties<VariableDefinitions>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly); - applyMatchedProperties<VariableDefinitions>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); - applyMatchedProperties<VariableDefinitions>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); - applyMatchedProperties<VariableDefinitions>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); - // Apply animation properties in order to apply animation results and trigger transitions below. applyMatchedProperties<AnimationProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly); applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly); applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); - // Match transition-property / animation-name length by trimming and - // lengthening other transition / animation property lists - // FIXME: This is wrong because we shouldn't affect the computed values - state.style()->adjustAnimations(); - state.style()->adjustTransitions(); - // Now we have all of the matched rules in the appropriate order. Walk the rules and apply // high-priority properties first, i.e., those properties that other properties depend on. // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important @@ -1398,6 +1472,17 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state, const Matc applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); + if (UNLIKELY(isSVGForeignObjectElement(element))) { + // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should not be scaled again. + // + // FIXME: The following hijacks the zoom property for foreignObject so that children of foreignObject get the + // correct font-size in case of zooming. 'zoom' is part of HighPriorityProperties, along with other font-related + // properties used as input to the FontBuilder, so resetting it here may cause the FontBuilder to recompute the + // font used as inheritable font for foreignObject content. If we want to support zoom on foreignObject we'll + // need to find another way of handling the SVG zoom model. + state.setEffectiveZoom(RenderStyle::initialZoom()); + } + if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) { state.fontBuilder().setFontDirty(true); applyInheritedOnly = false; @@ -1426,9 +1511,7 @@ void StyleResolver::applyMatchedProperties(StyleResolverState& state, const Matc applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly); applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly); - // Start loading resources referenced by this style. - m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources()); - document().styleEngine()->fontSelector()->loadPendingFonts(); + loadPendingResources(state); if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) { INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded); @@ -1476,7 +1559,7 @@ void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, s StyleResolverState state(document(), document().documentElement(), style); state.setStyle(style); - state.fontBuilder().initForStyleResolve(document(), style, state.useSVGZoomRules()); + state.fontBuilder().initForStyleResolve(document(), style); for (size_t i = 0; i < count; ++i) { if (properties[i].value) { @@ -1502,13 +1585,26 @@ void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list) m_viewportDependentMediaQueryResults.append(list[i]); } -bool StyleResolver::affectedByViewportChange() const +bool StyleResolver::mediaQueryAffectedByViewportChange() const { for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) { - if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result) + if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) != m_viewportDependentMediaQueryResults[i]->result()) return true; } return false; } +void StyleResolver::trace(Visitor* visitor) +{ + visitor->trace(m_keyframesRuleMap); + visitor->trace(m_viewportDependentMediaQueryResults); + visitor->trace(m_viewportStyleResolver); + visitor->trace(m_features); + visitor->trace(m_siblingRuleSet); + visitor->trace(m_uncommonAttributeRuleSet); + visitor->trace(m_watchedSelectorsRules); + visitor->trace(m_treeBoundaryCrossingRules); + visitor->trace(m_pendingStyleSheets); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.h index f1dae0b2381..1ab53b349d0 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolver.h @@ -22,8 +22,6 @@ #ifndef StyleResolver_h #define StyleResolver_h -#include "core/animation/KeyframeAnimationEffect.h" -#include "core/css/InspectorCSSOMWrappers.h" #include "core/css/PseudoStyleRequest.h" #include "core/css/RuleFeature.h" #include "core/css/RuleSet.h" @@ -35,9 +33,8 @@ #include "core/css/resolver/ScopedStyleResolver.h" #include "core/css/resolver/ScopedStyleTree.h" #include "core/css/resolver/StyleBuilder.h" -#include "core/css/resolver/StyleResolverIncludes.h" -#include "core/css/resolver/StyleResolverState.h" #include "core/css/resolver/StyleResourceLoader.h" +#include "platform/heap/Handle.h" #include "wtf/Deque.h" #include "wtf/HashMap.h" #include "wtf/HashSet.h" @@ -47,6 +44,8 @@ namespace WebCore { +class AnimatableValue; +class AnimationTimeline; class CSSAnimationUpdate; class CSSFontSelector; class CSSRuleList; @@ -55,14 +54,13 @@ class CSSStyleSheet; class CSSValue; class ContainerNode; class Document; -class DocumentTimeline; class Element; class ElementRuleCollector; +class Interpolation; class KeyframeList; class KeyframeValue; class MediaQueryEvaluator; class MediaQueryResult; -class RenderRegion; class RuleData; class Settings; class StyleKeyframe; @@ -73,40 +71,39 @@ class StyleRuleKeyframes; class StyleRulePage; class ViewportStyleResolver; -struct MatchResult; +class MatchResult; enum StyleSharingBehavior { AllowStyleSharing, DisallowStyleSharing, }; -// MatchOnlyUserAgentRules is used in media queries, where relative units -// are interpreted according to the document root element style, and styled only -// from the User Agent Stylesheet rules. enum RuleMatchingBehavior { MatchAllRules, - MatchAllRulesExcludingSMIL, - MatchOnlyUserAgentRules, + MatchAllRulesExcludingSMIL }; -const unsigned styleSharingListSize = 40; +const unsigned styleSharingListSize = 15; +const unsigned styleSharingMaxDepth = 32; typedef WTF::Deque<Element*, styleSharingListSize> StyleSharingList; struct CSSPropertyValue { + STACK_ALLOCATED(); +public: CSSPropertyValue(CSSPropertyID property, CSSValue* value) : property(property), value(value) { } // Stores value=propertySet.getPropertyCSSValue(id).get(). CSSPropertyValue(CSSPropertyID, const StylePropertySet&); CSSPropertyID property; - CSSValue* value; + RawPtrWillBeMember<CSSValue> value; }; // This class selects a RenderStyle for a given element based on a collection of stylesheets. -class StyleResolver : public FontSelectorClient { - WTF_MAKE_NONCOPYABLE(StyleResolver); WTF_MAKE_FAST_ALLOCATED; +class StyleResolver FINAL : public NoBaseWillBeGarbageCollectedFinalized<StyleResolver> { + WTF_MAKE_NONCOPYABLE(StyleResolver); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: explicit StyleResolver(Document&); - ~StyleResolver(); + virtual ~StyleResolver(); // FIXME: StyleResolver should not be keeping tree-walk state. // These should move to some global tree-walk state, or should be contained in a @@ -118,13 +115,11 @@ public: void popParentShadowRoot(const ShadowRoot&); PassRefPtr<RenderStyle> styleForElement(Element*, RenderStyle* parentStyle = 0, StyleSharingBehavior = AllowStyleSharing, - RuleMatchingBehavior = MatchAllRules, RenderRegion* regionForStyling = 0); + RuleMatchingBehavior = MatchAllRules); - // FIXME: keyframeStylesForAnimation is only used in the legacy animations implementation - // and should be removed when that is replaced by Web Animations. - void keyframeStylesForAnimation(Element*, const RenderStyle&, KeyframeList&); PassRefPtr<RenderStyle> styleForKeyframe(Element*, const RenderStyle&, RenderStyle* parentStyle, const StyleKeyframe*, const AtomicString& animationName); - static PassRefPtr<KeyframeAnimationEffect> createKeyframeAnimationEffect(Element&, const Vector<RefPtr<MutableStylePropertySet> >&, KeyframeAnimationEffect::KeyframeVector&); + static PassRefPtrWillBeRawPtr<AnimatableValue> createAnimatableValueSnapshot(Element&, CSSPropertyID, CSSValue&); + static PassRefPtrWillBeRawPtr<AnimatableValue> createAnimatableValueSnapshot(StyleResolverState&, CSSPropertyID, CSSValue&); PassRefPtr<RenderStyle> pseudoStyleForElement(Element*, const PseudoStyleRequest&, RenderStyle* parentStyle); @@ -132,7 +127,7 @@ public: PassRefPtr<RenderStyle> defaultStyleForElement(); PassRefPtr<RenderStyle> styleForText(Text*); - static PassRefPtr<RenderStyle> styleForDocument(Document&, CSSFontSelector* = 0); + static PassRefPtr<RenderStyle> styleForDocument(Document&); // FIXME: This only has 5 callers and should be removed. Callers should be explicit about // their dependency on Document* instead of grabbing one through StyleResolver. @@ -140,15 +135,14 @@ public: // FIXME: It could be better to call appendAuthorStyleSheets() directly after we factor StyleResolver further. // https://bugs.webkit.org/show_bug.cgi?id=108890 - void appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >&); + void appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >&); void resetAuthorStyle(const ContainerNode*); void finishAppendAuthorStyleSheets(); - TreeBoundaryCrossingRules& treeBoundaryCrossingRules() { return m_treeBoundaryCrossingRules; } - void processScopedRules(const RuleSet& authorRules, const KURL&, ContainerNode* scope = 0); + void processScopedRules(const RuleSet& authorRules, CSSStyleSheet*, ContainerNode& scope); - void lazyAppendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >&); - void removePendingAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet> >&); + void lazyAppendAuthorStyleSheets(unsigned firstNew, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >&); + void removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >&); void appendPendingAuthorStyleSheets(); bool hasPendingAuthorStyleSheets() const { return m_pendingStyleSheets.size() > 0 || m_needCollectFeatures; } @@ -179,9 +173,9 @@ public: AllButEmptyCSSRules = UAAndUserCSSRules | AuthorCSSRules | CrossOriginCSSRules, AllCSSRules = AllButEmptyCSSRules | EmptyCSSRules, }; - PassRefPtr<CSSRuleList> cssRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules, ShouldIncludeStyleSheetInCSSOMWrapper = IncludeStyleSheetInCSSOMWrapper); - PassRefPtr<CSSRuleList> pseudoCSSRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules, ShouldIncludeStyleSheetInCSSOMWrapper = IncludeStyleSheetInCSSOMWrapper); - PassRefPtr<StyleRuleList> styleRulesForElement(Element*, unsigned rulesToInclude); + PassRefPtrWillBeRawPtr<CSSRuleList> cssRulesForElement(Element*, unsigned rulesToInclude = AllButEmptyCSSRules); + PassRefPtrWillBeRawPtr<CSSRuleList> pseudoCSSRulesForElement(Element*, PseudoId, unsigned rulesToInclude = AllButEmptyCSSRules); + PassRefPtrWillBeRawPtr<StyleRuleList> styleRulesForElement(Element*, unsigned rulesToInclude); // |properties| is an array with |count| elements. void applyPropertiesToStyle(const CSSPropertyValue* properties, size_t count, RenderStyle*); @@ -191,28 +185,29 @@ public: void addMediaQueryResults(const MediaQueryResultList&); MediaQueryResultList* viewportDependentMediaQueryResults() { return &m_viewportDependentMediaQueryResults; } bool hasViewportDependentMediaQueries() const { return !m_viewportDependentMediaQueryResults.isEmpty(); } - bool affectedByViewportChange() const; - - // FIXME: Regions should not require special logic in StyleResolver. - bool checkRegionStyle(Element* regionElement); + bool mediaQueryAffectedByViewportChange() const; // FIXME: Rename to reflect the purpose, like didChangeFontSize or something. void invalidateMatchedPropertiesCache(); + void notifyResizeForViewportUnits(); + // Exposed for RenderStyle::isStyleAvilable(). static RenderStyle* styleNotYetAvailable() { return s_styleNotYetAvailable; } - // FIXME: StyleResolver should not have this member or method. - InspectorCSSOMWrappers& inspectorCSSOMWrappers() { return m_inspectorCSSOMWrappers; } - - const RuleFeatureSet& ensureRuleFeatureSet() + RuleFeatureSet& ensureUpdatedRuleFeatureSet() { if (hasPendingAuthorStyleSheets()) appendPendingAuthorStyleSheets(); return m_features; } - StyleSharingList& styleSharingList() { return m_styleSharingList; } + RuleFeatureSet& ruleFeatureSet() + { + return m_features; + } + + StyleSharingList& styleSharingList(); bool hasRulesForId(const AtomicString&) const; @@ -229,20 +224,22 @@ public: unsigned accessCount() const { return m_accessCount; } void didAccess() { ++m_accessCount; } - PassRefPtr<PseudoElement> createPseudoElementIfNeeded(Element&, PseudoId); + void increaseStyleSharingDepth() { ++m_styleSharingDepth; } + void decreaseStyleSharingDepth() { --m_styleSharingDepth; } -private: - // FontSelectorClient implementation. - virtual void fontsNeedUpdate(FontSelector*); + PassRefPtrWillBeRawPtr<PseudoElement> createPseudoElementIfNeeded(Element& parent, PseudoId); -private: - void initWatchedSelectorRules(const Vector<RefPtr<StyleRule> >& watchedSelectors); + void trace(Visitor*); - void addTreeBoundaryCrossingRules(const Vector<MinimalRuleData>&, ContainerNode* scope); +private: + void initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedSelectors); // FIXME: This should probably go away, folded into FontBuilder. void updateFont(StyleResolverState&); + void loadPendingResources(StyleResolverState&); + void adjustRenderStyle(StyleResolverState&, Element*); + void appendCSSStyleSheet(CSSStyleSheet*); void collectPseudoRulesForElement(Element*, ElementRuleCollector&, PseudoId, unsigned rulesToInclude); @@ -254,30 +251,35 @@ private: // FIXME: watched selectors should be implemented using injected author stylesheets: http://crbug.com/316960 void matchWatchSelectorRules(ElementRuleCollector&); void collectFeatures(); - void collectTreeBoundaryCrossingRules(Element*, ElementRuleCollector&, bool includeEmptyRules); void resetRuleFeatures(); bool fastRejectSelector(const RuleData&) const; void applyMatchedProperties(StyleResolverState&, const MatchResult&); - void applyAnimatedProperties(StyleResolverState&, Element* animatingElement); + bool applyAnimatedProperties(StyleResolverState&, Element* animatingElement); enum StyleApplicationPass { - VariableDefinitions, AnimationProperties, HighPriorityProperties, LowPriorityProperties }; template <StyleResolver::StyleApplicationPass pass> + static inline CSSPropertyID firstCSSPropertyId(); + template <StyleResolver::StyleApplicationPass pass> + static inline CSSPropertyID lastCSSPropertyId(); + template <StyleResolver::StyleApplicationPass pass> static inline bool isPropertyForPass(CSSPropertyID); template <StyleApplicationPass pass> void applyMatchedProperties(StyleResolverState&, const MatchResult&, bool important, int startIndex, int endIndex, bool inheritedOnly); template <StyleApplicationPass pass> void applyProperties(StyleResolverState&, const StylePropertySet* properties, StyleRule*, bool isImportant, bool inheritedOnly, PropertyWhitelistType = PropertyWhitelistNone); template <StyleApplicationPass pass> - void applyAnimatedProperties(StyleResolverState&, const AnimationEffect::CompositableValueMap&); + void applyAnimatedProperties(StyleResolverState&, const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >&); + template <StyleResolver::StyleApplicationPass pass> + void applyAllProperty(StyleResolverState&, CSSValue*); + void matchPageRules(MatchResult&, RuleSet*, bool isLeftPage, bool isFirstPage, const String& pageName); - void matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>&, bool isLeftPage, bool isFirstPage, const String& pageName); + void matchPageRulesForList(WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >& matchedRules, const WillBeHeapVector<RawPtrWillBeMember<StyleRulePage> >&, bool isLeftPage, bool isFirstPage, const String& pageName); void collectViewportRules(); Settings* documentSettings() { return m_document.settings(); } @@ -289,7 +291,7 @@ private: bool pseudoStyleForElementInternal(Element&, const PseudoStyleRequest&, RenderStyle* parentStyle, StyleResolverState&); // FIXME: This likely belongs on RuleSet. - typedef HashMap<StringImpl*, RefPtr<StyleRuleKeyframes> > KeyframesRuleMap; + typedef WillBeHeapHashMap<StringImpl*, RefPtrWillBeMember<StyleRuleKeyframes> > KeyframesRuleMap; KeyframesRuleMap m_keyframesRuleMap; static RenderStyle* s_styleNotYetAvailable; @@ -301,56 +303,40 @@ private: OwnPtr<MediaQueryEvaluator> m_medium; MediaQueryResultList m_viewportDependentMediaQueryResults; - RefPtr<RenderStyle> m_rootDefaultStyle; - Document& m_document; SelectorFilter m_selectorFilter; - RefPtr<ViewportStyleResolver> m_viewportStyleResolver; + OwnPtrWillBeMember<ViewportStyleResolver> m_viewportStyleResolver; - ListHashSet<CSSStyleSheet*, 16> m_pendingStyleSheets; + WillBeHeapListHashSet<RawPtrWillBeMember<CSSStyleSheet>, 16> m_pendingStyleSheets; ScopedStyleTree m_styleTree; - // FIXME: The entire logic of collecting features on StyleResolver, as well astransferring them + // FIXME: The entire logic of collecting features on StyleResolver, as well as transferring them // between various parts of machinery smells wrong. This needs to be better somehow. RuleFeatureSet m_features; - OwnPtr<RuleSet> m_siblingRuleSet; - OwnPtr<RuleSet> m_uncommonAttributeRuleSet; + OwnPtrWillBeMember<RuleSet> m_siblingRuleSet; + OwnPtrWillBeMember<RuleSet> m_uncommonAttributeRuleSet; // FIXME: watched selectors should be implemented using injected author stylesheets: http://crbug.com/316960 - OwnPtr<RuleSet> m_watchedSelectorsRules; + OwnPtrWillBeMember<RuleSet> m_watchedSelectorsRules; TreeBoundaryCrossingRules m_treeBoundaryCrossingRules; bool m_needCollectFeatures; - InspectorCSSOMWrappers m_inspectorCSSOMWrappers; - StyleResourceLoader m_styleResourceLoader; - StyleSharingList m_styleSharingList; + unsigned m_styleSharingDepth; + Vector<OwnPtr<StyleSharingList>, styleSharingMaxDepth> m_styleSharingLists; OwnPtr<StyleResolverStats> m_styleResolverStats; OwnPtr<StyleResolverStats> m_styleResolverStatsTotals; unsigned m_styleResolverStatsSequence; + // Use only for Internals::updateStyleAndReturnAffectedElementCount. unsigned m_accessCount; }; -inline bool checkRegionSelector(const CSSSelector* regionSelector, Element* regionElement) -{ - if (!regionSelector || !regionElement) - return false; - - SelectorChecker selectorChecker(regionElement->document(), SelectorChecker::QueryingRules); - for (const CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s)) { - SelectorChecker::SelectorCheckingContext selectorCheckingContext(s, regionElement, SelectorChecker::VisitedMatchDisabled); - if (selectorChecker.match(selectorCheckingContext, DOMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches) - return true; - } - return false; -} - } // namespace WebCore #endif // StyleResolver_h diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverIncludes.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverIncludes.h deleted file mode 100644 index 380c1eb1d57..00000000000 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverIncludes.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef StyleResolverIncludes_h -#define StyleResolverIncludes_h - -namespace WebCore { - -enum ShouldIncludeStyleSheetInCSSOMWrapper { - IncludeStyleSheetInCSSOMWrapper, - DoNotIncludeStyleSheetInCSSOMWrapper, -}; - -} - -#endif // StyleResolverIncludes_h diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverParentScope.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverParentScope.cpp new file mode 100644 index 00000000000..bde3a362aed --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverParentScope.cpp @@ -0,0 +1,13 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/css/resolver/StyleResolverParentScope.h" + +namespace WebCore { + +StyleResolverParentScope* StyleResolverParentScope::s_currentScope = 0; + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverParentScope.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverParentScope.h new file mode 100644 index 00000000000..87ca21cee91 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverParentScope.h @@ -0,0 +1,78 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef StyleResolverParentScope_h +#define StyleResolverParentScope_h + +#include "core/css/resolver/StyleResolver.h" +#include "core/dom/Element.h" +#include "core/dom/shadow/ShadowRoot.h" + +namespace WebCore { + +// Maintains the parent element stack (and bloom filter) inside recalcStyle. +class StyleResolverParentScope FINAL { +public: + explicit StyleResolverParentScope(Node& parent); + ~StyleResolverParentScope(); + + static void ensureParentStackIsPushed(); + +private: + void pushParentIfNeeded(); + + Node& m_parent; + bool m_pushed; + StyleResolverParentScope* m_previous; + StyleResolver& m_resolver; + + static StyleResolverParentScope* s_currentScope; +}; + +inline StyleResolverParentScope::StyleResolverParentScope(Node& parent) + : m_parent(parent) + , m_pushed(false) + , m_previous(s_currentScope) + , m_resolver(*m_parent.document().styleResolver()) +{ + ASSERT(m_parent.document().inStyleRecalc()); + ASSERT(parent.isElementNode() || parent.isShadowRoot()); + s_currentScope = this; + m_resolver.increaseStyleSharingDepth(); +} + +inline StyleResolverParentScope::~StyleResolverParentScope() +{ + s_currentScope = m_previous; + m_resolver.decreaseStyleSharingDepth(); + if (!m_pushed) + return; + if (m_parent.isElementNode()) + m_resolver.popParentElement(toElement(m_parent)); + else + m_resolver.popParentShadowRoot(toShadowRoot(m_parent)); +} + +inline void StyleResolverParentScope::ensureParentStackIsPushed() +{ + if (s_currentScope) + s_currentScope->pushParentIfNeeded(); +} + +inline void StyleResolverParentScope::pushParentIfNeeded() +{ + if (m_pushed) + return; + if (m_previous) + m_previous->pushParentIfNeeded(); + if (m_parent.isElementNode()) + m_resolver.pushParentElement(toElement(m_parent)); + else + m_resolver.pushParentShadowRoot(toShadowRoot(m_parent)); + m_pushed = true; +} + +} // namespace WebCore + +#endif // StyleResolverParentScope_h diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp index 6df80021ba5..f0efa4a7d8a 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.cpp @@ -22,33 +22,48 @@ #include "config.h" #include "core/css/resolver/StyleResolverState.h" +#include "core/animation/css/CSSAnimations.h" #include "core/dom/Node.h" #include "core/dom/NodeRenderStyle.h" -#include "core/page/Page.h" +#include "core/frame/FrameHost.h" namespace WebCore { -StyleResolverState::StyleResolverState(Document& document, Element* element, RenderStyle* parentStyle, RenderRegion* regionForStyling) +StyleResolverState::StyleResolverState(Document& document, Element* element, RenderStyle* parentStyle) : m_elementContext(element ? ElementResolveContext(*element) : ElementResolveContext()) , m_document(document) - , m_style(0) - , m_cssToLengthConversionData(0, rootElementStyle()) + , m_style(nullptr) + , m_cssToLengthConversionData(0, rootElementStyle(), document.renderView()) , m_parentStyle(parentStyle) - , m_regionForStyling(regionForStyling) , m_applyPropertyToRegularStyle(true) , m_applyPropertyToVisitedLinkStyle(false) - , m_lineHeightValue(0) + , m_lineHeightValue(nullptr) , m_styleMap(*this, m_elementStyleResources) - , m_currentRule(0) + , m_currentRule(nullptr) { - if (m_elementContext.resetStyleInheritance()) - m_parentStyle = 0; - else if (!parentStyle && m_elementContext.parentNode()) + if (!parentStyle && m_elementContext.parentNode()) m_parentStyle = m_elementContext.parentNode()->renderStyle(); - // FIXME: How can we not have a page here? - if (Page* page = document.page()) - m_elementStyleResources.setDeviceScaleFactor(page->deviceScaleFactor()); + // FIXME: Animation unitests will start animations on non-active documents! + // http://crbug.com/330095 + // ASSERT(document.isActive()); + if (!document.isActive()) + return; + m_elementStyleResources.setDeviceScaleFactor(document.frameHost()->deviceScaleFactor()); +} + +StyleResolverState::~StyleResolverState() +{ +} + +void StyleResolverState::setAnimationUpdate(PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> update) +{ + m_animationUpdate = update; +} + +PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> StyleResolverState::takeAnimationUpdate() +{ + return m_animationUpdate.release(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h index 18095bd28dd..2a723ba471b 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h @@ -22,9 +22,8 @@ #ifndef StyleResolverState_h #define StyleResolverState_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" -#include "core/animation/css/CSSAnimations.h" #include "core/css/CSSSVGDocumentValue.h" #include "core/css/CSSToLengthConversionData.h" #include "core/css/resolver/CSSToStyleMap.h" @@ -38,14 +37,16 @@ namespace WebCore { +class CSSAnimationUpdate; class FontDescription; -class RenderRegion; class StyleRule; class StyleResolverState { -WTF_MAKE_NONCOPYABLE(StyleResolverState); + STACK_ALLOCATED(); + WTF_MAKE_NONCOPYABLE(StyleResolverState); public: - StyleResolverState(Document&, Element*, RenderStyle* parentStyle = 0, RenderRegion* regionForStyling = 0); + StyleResolverState(Document&, Element*, RenderStyle* parentStyle = 0); + ~StyleResolverState(); // In FontFaceSet and CanvasRenderingContext2D, we don't have an element to grab the document from. // This is why we have to store the document separately. @@ -66,16 +67,14 @@ public: const CSSToLengthConversionData& cssToLengthConversionData() const { return m_cssToLengthConversionData; } - void setAnimationUpdate(PassOwnPtr<CSSAnimationUpdate> update) { m_animationUpdate = update; } + void setAnimationUpdate(PassOwnPtrWillBeRawPtr<CSSAnimationUpdate>); const CSSAnimationUpdate* animationUpdate() { return m_animationUpdate.get(); } - PassOwnPtr<CSSAnimationUpdate> takeAnimationUpdate() { return m_animationUpdate.release(); } + PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> takeAnimationUpdate(); void setParentStyle(PassRefPtr<RenderStyle> parentStyle) { m_parentStyle = parentStyle; } const RenderStyle* parentStyle() const { return m_parentStyle.get(); } RenderStyle* parentStyle() { return m_parentStyle.get(); } - const RenderRegion* regionForStyling() const { return m_regionForStyling; } - void setCurrentRule(StyleRule* currentRule) { m_currentRule = currentRule; } const StyleRule* currentRule() const { return m_currentRule; } @@ -95,8 +94,20 @@ public: void setLineHeightValue(CSSValue* value) { m_lineHeightValue = value; } CSSValue* lineHeightValue() { return m_lineHeightValue; } - void cacheUserAgentBorderAndBackground() { m_cachedUAStyle = CachedUAStyle(style()); } - const CachedUAStyle& cachedUAStyle() const { return m_cachedUAStyle; } + void cacheUserAgentBorderAndBackground() + { + // RenderTheme only needs the cached style if it has an appearance, + // and constructing it is expensive so we avoid it if possible. + if (!style()->hasAppearance()) + return; + + m_cachedUAStyle = CachedUAStyle::create(style()); + } + + const CachedUAStyle* cachedUAStyle() const + { + return m_cachedUAStyle.get(); + } ElementStyleResources& elementStyleResources() { return m_elementStyleResources; } const CSSToStyleMap& styleMap() const { return m_styleMap; } @@ -107,7 +118,7 @@ public: // sites are extremely verbose. PassRefPtr<StyleImage> styleImage(CSSPropertyID propertyId, CSSValue* value) { - return m_elementStyleResources.styleImage(document().textLinkColors(), style()->color(), propertyId, value); + return m_elementStyleResources.styleImage(document(), document().textLinkColors(), style()->color(), propertyId, value); } FontBuilder& fontBuilder() { return m_fontBuilder; } @@ -122,19 +133,7 @@ public: void setWritingMode(WritingMode writingMode) { m_fontBuilder.didChangeFontParameters(m_style->setWritingMode(writingMode)); } void setTextOrientation(TextOrientation textOrientation) { m_fontBuilder.didChangeFontParameters(m_style->setTextOrientation(textOrientation)); } - // 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() const { return element() && element()->isSVGElement(); } - private: - friend class StyleResolveScope; - ElementResolveContext m_elementContext; Document& m_document; @@ -147,21 +146,16 @@ private: // so we keep it separate from m_elementContext. RefPtr<RenderStyle> m_parentStyle; - OwnPtr<CSSAnimationUpdate> m_animationUpdate; - - // Required to ASSERT in applyProperties. - // FIXME: Regions should not need special state on StyleResolverState - // no other @rule does. - RenderRegion* m_regionForStyling; + OwnPtrWillBeMember<CSSAnimationUpdate> m_animationUpdate; bool m_applyPropertyToRegularStyle; bool m_applyPropertyToVisitedLinkStyle; - CSSValue* m_lineHeightValue; + RawPtrWillBeMember<CSSValue> m_lineHeightValue; FontBuilder m_fontBuilder; - CachedUAStyle m_cachedUAStyle; + OwnPtr<CachedUAStyle> m_cachedUAStyle; ElementStyleResources m_elementStyleResources; // CSSToStyleMap is a pure-logic class and only contains @@ -169,7 +163,7 @@ private: CSSToStyleMap m_styleMap; Vector<AtomicString> m_contentAttrValues; - StyleRule* m_currentRule; + RawPtrWillBeMember<StyleRule> m_currentRule; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.cpp index 04405c340a7..9025bf04f78 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.cpp @@ -23,37 +23,29 @@ #include "config.h" #include "core/css/resolver/StyleResourceLoader.h" -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "core/css/CSSCursorImageValue.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSSVGDocumentValue.h" -#include "core/css/CSSShaderValue.h" #include "core/css/resolver/ElementStyleResources.h" #include "core/fetch/ResourceFetcher.h" #include "core/rendering/style/ContentData.h" -#include "core/rendering/style/CursorList.h" #include "core/rendering/style/FillLayer.h" #include "core/rendering/style/RenderStyle.h" -#include "core/rendering/style/StyleCustomFilterProgram.h" -#include "core/rendering/style/StyleCustomFilterProgramCache.h" #include "core/rendering/style/StyleFetchedImage.h" #include "core/rendering/style/StyleFetchedImageSet.h" -#include "core/rendering/style/StyleFetchedShader.h" #include "core/rendering/style/StyleGeneratedImage.h" #include "core/rendering/style/StylePendingImage.h" -#include "core/rendering/style/StylePendingShader.h" #include "core/rendering/svg/ReferenceFilterBuilder.h" -#include "platform/graphics/filters/custom/CustomFilterOperation.h" namespace WebCore { StyleResourceLoader::StyleResourceLoader(ResourceFetcher* fetcher) - : m_customFilterProgramCache(StyleCustomFilterProgramCache::create()) - , m_fetcher(fetcher) + : m_fetcher(fetcher) { } -void StyleResourceLoader::loadPendingSVGDocuments(RenderStyle* renderStyle, const ElementStyleResources& elementStyleResources) +void StyleResourceLoader::loadPendingSVGDocuments(RenderStyle* renderStyle, ElementStyleResources& elementStyleResources) { if (!renderStyle->hasFilter() || elementStyleResources.pendingSVGDocuments().isEmpty()) return; @@ -75,35 +67,37 @@ void StyleResourceLoader::loadPendingSVGDocuments(RenderStyle* renderStyle, cons ReferenceFilterBuilder::setDocumentResourceReference(referenceFilter, adoptPtr(new DocumentResourceReference(resource))); } } + + elementStyleResources.clearPendingSVGDocuments(); } -PassRefPtr<StyleImage> StyleResourceLoader::loadPendingImage(StylePendingImage* pendingImage, float deviceScaleFactor) +static PassRefPtr<StyleImage> doLoadPendingImage(ResourceFetcher* fetcher, StylePendingImage* pendingImage, float deviceScaleFactor, const ResourceLoaderOptions& options) { - if (pendingImage->cssImageValue()) { - CSSImageValue* imageValue = pendingImage->cssImageValue(); - return imageValue->cachedImage(m_fetcher); - } + if (CSSImageValue* imageValue = pendingImage->cssImageValue()) + return imageValue->cachedImage(fetcher, options); - if (pendingImage->cssImageGeneratorValue()) { - CSSImageGeneratorValue* imageGeneratorValue = pendingImage->cssImageGeneratorValue(); - imageGeneratorValue->loadSubimages(m_fetcher); + if (CSSImageGeneratorValue* imageGeneratorValue + = pendingImage->cssImageGeneratorValue()) { + imageGeneratorValue->loadSubimages(fetcher); return StyleGeneratedImage::create(imageGeneratorValue); } - if (pendingImage->cssCursorImageValue()) { - CSSCursorImageValue* cursorImageValue = pendingImage->cssCursorImageValue(); - return cursorImageValue->cachedImage(m_fetcher, deviceScaleFactor); - } + if (CSSCursorImageValue* cursorImageValue + = pendingImage->cssCursorImageValue()) + return cursorImageValue->cachedImage(fetcher, deviceScaleFactor); - if (pendingImage->cssImageSetValue()) { - CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue(); - return imageSetValue->cachedImageSet(m_fetcher, deviceScaleFactor); - } + if (CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue()) + return imageSetValue->cachedImageSet(fetcher, deviceScaleFactor, options); + + return nullptr; +} - return 0; +PassRefPtr<StyleImage> StyleResourceLoader::loadPendingImage(StylePendingImage* pendingImage, float deviceScaleFactor) +{ + return doLoadPendingImage(m_fetcher, pendingImage, deviceScaleFactor, ResourceFetcher::defaultResourceOptions()); } -void StyleResourceLoader::loadPendingShapeImage(RenderStyle* renderStyle, ShapeValue* shapeValue) +void StyleResourceLoader::loadPendingShapeImage(RenderStyle* renderStyle, ShapeValue* shapeValue, float deviceScaleFactor) { if (!shapeValue) return; @@ -112,16 +106,15 @@ void StyleResourceLoader::loadPendingShapeImage(RenderStyle* renderStyle, ShapeV if (!image || !image->isPendingImage()) return; - StylePendingImage* pendingImage = toStylePendingImage(image); - CSSImageValue* cssImageValue = pendingImage->cssImageValue(); - ResourceLoaderOptions options = ResourceFetcher::defaultResourceOptions(); options.allowCredentials = DoNotAllowStoredCredentials; + options.credentialsRequested = ClientDidNotRequestCredentials; + options.corsEnabled = IsCORSEnabled; - shapeValue->setImage(cssImageValue->cachedImage(m_fetcher, options, PotentiallyCORSEnabled)); + shapeValue->setImage(doLoadPendingImage(m_fetcher, toStylePendingImage(image), deviceScaleFactor, options)); } -void StyleResourceLoader::loadPendingImages(RenderStyle* style, const ElementStyleResources& elementStyleResources) +void StyleResourceLoader::loadPendingImages(RenderStyle* style, ElementStyleResources& elementStyleResources) { if (elementStyleResources.pendingImageProperties().isEmpty()) return; @@ -195,51 +188,15 @@ void StyleResourceLoader::loadPendingImages(RenderStyle* style, const ElementSty } break; } - case CSSPropertyShapeInside: - loadPendingShapeImage(style, style->shapeInside()); - break; case CSSPropertyShapeOutside: - loadPendingShapeImage(style, style->shapeOutside()); + loadPendingShapeImage(style, style->shapeOutside(), elementStyleResources.deviceScaleFactor()); break; default: ASSERT_NOT_REACHED(); } } -} -void StyleResourceLoader::loadPendingShaders(RenderStyle* style, const ElementStyleResources& elementStyleResources) -{ - if (!style->hasFilter() || !elementStyleResources.hasNewCustomFilterProgram()) - return; - - Vector<RefPtr<FilterOperation> >& filterOperations = style->mutableFilter().operations(); - for (unsigned i = 0; i < filterOperations.size(); ++i) { - RefPtr<FilterOperation> filterOperation = filterOperations.at(i); - if (filterOperation->type() == FilterOperation::CUSTOM) { - CustomFilterOperation* customFilter = toCustomFilterOperation(filterOperation.get()); - ASSERT(customFilter->program()); - StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customFilter->program()); - // Note that the StylePendingShaders could be already resolved to StyleFetchedShaders. That's because the rule was matched before. - // However, the StyleCustomFilterProgram that was initially created could have been removed from the cache in the meanwhile, - // meaning that we get a new StyleCustomFilterProgram here that is not yet in the cache, but already has loaded StyleShaders. - if (!program->hasPendingShaders() && program->inCache()) - continue; - RefPtr<StyleCustomFilterProgram> styleProgram = m_customFilterProgramCache->lookup(program); - if (styleProgram.get()) { - customFilter->setProgram(styleProgram.release()); - } else { - if (program->vertexShader() && program->vertexShader()->isPendingShader()) { - CSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->vertexShader())->cssShaderValue(); - program->setVertexShader(shaderValue->resource(m_fetcher)); - } - if (program->fragmentShader() && program->fragmentShader()->isPendingShader()) { - CSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->fragmentShader())->cssShaderValue(); - program->setFragmentShader(shaderValue->resource(m_fetcher)); - } - m_customFilterProgramCache->add(program); - } - } - } + elementStyleResources.clearPendingImageProperties(); } void StyleResourceLoader::loadPendingResources(RenderStyle* renderStyle, ElementStyleResources& elementStyleResources) @@ -247,9 +204,6 @@ void StyleResourceLoader::loadPendingResources(RenderStyle* renderStyle, Element // Start loading images referenced by this style. loadPendingImages(renderStyle, elementStyleResources); - // Start loading the shaders referenced by this style. - loadPendingShaders(renderStyle, elementStyleResources); - // Start loading the SVG Documents referenced by this style. loadPendingSVGDocuments(renderStyle, elementStyleResources); } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.h b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.h index 4b33efeea47..8d3eff19ec0 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/StyleResourceLoader.h @@ -29,34 +29,29 @@ namespace WebCore { class ElementStyleResources; -class ResourceFetcher; class RenderStyle; +class ResourceFetcher; class ShapeValue; class StyleImage; class StylePendingImage; -class StyleCustomFilterProgramCache; // Manages loading of resources, requested by the stylesheets. -// Expects the same lifetime as StyleResolver, because: -// 1) it expects ResourceFetcher to never change, and -// 2) it also holds the StyleCustomFilterProgramCache. +// Expects the same lifetime as StyleResolver, because +// it expects ResourceFetcher to never change. class StyleResourceLoader { WTF_MAKE_NONCOPYABLE(StyleResourceLoader); public: explicit StyleResourceLoader(ResourceFetcher*); void loadPendingResources(RenderStyle*, ElementStyleResources&); - StyleCustomFilterProgramCache* customFilterProgramCache() const { return m_customFilterProgramCache.get(); } private: - void loadPendingSVGDocuments(RenderStyle*, const ElementStyleResources&); - void loadPendingShaders(RenderStyle*, const ElementStyleResources&); + void loadPendingSVGDocuments(RenderStyle*, ElementStyleResources&); PassRefPtr<StyleImage> loadPendingImage(StylePendingImage*, float deviceScaleFactor); - void loadPendingImages(RenderStyle*, const ElementStyleResources&); - void loadPendingShapeImage(RenderStyle*, ShapeValue*); + void loadPendingImages(RenderStyle*, ElementStyleResources&); + void loadPendingShapeImage(RenderStyle*, ShapeValue*, float deviceScaleFactor); - OwnPtr<StyleCustomFilterProgramCache> m_customFilterProgramCache; ResourceFetcher* m_fetcher; }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.cpp index 3779a01f6a5..b111c0b7844 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.cpp @@ -32,6 +32,7 @@ #include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSTransformValue.h" #include "core/rendering/style/RenderStyle.h" +#include "platform/heap/Handle.h" #include "platform/transforms/Matrix3DTransformOperation.h" #include "platform/transforms/MatrixTransformOperation.h" #include "platform/transforms/PerspectiveTransformOperation.h" @@ -43,17 +44,10 @@ namespace WebCore { -TransformBuilder::TransformBuilder() -{ -} - -TransformBuilder::~TransformBuilder() -{ -} - static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, const CSSToLengthConversionData& conversionData) { - return primitiveValue ? primitiveValue->convertToLength<FixedConversion | PercentConversion>(conversionData) : Length(Undefined); + ASSERT(primitiveValue); + return primitiveValue->convertToLength<FixedConversion | PercentConversion>(conversionData); } static TransformOperation::OperationType getTransformOperationType(CSSTransformValue::TransformOperationType type) @@ -180,19 +174,16 @@ bool TransformBuilder::createTransformOperations(CSSValue* inValue, const CSSToL } } - if (tx.isUndefined() || ty.isUndefined()) - return false; - - operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType()))); + operations.operations().append(TranslateTransformOperation::create(tx, ty, 0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateZTransformOperation: case CSSTransformValue::Translate3DTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); - Length tz = Length(0, Fixed); + double tz = 0; if (transformValue->operationType() == CSSTransformValue::TranslateZTransformOperation) - tz = convertToFloatLength(firstValue, conversionData); + tz = firstValue->computeLength<double>(conversionData); else if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, conversionData); else { @@ -200,7 +191,7 @@ bool TransformBuilder::createTransformOperations(CSSValue* inValue, const CSSToL if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); - tz = convertToFloatLength(thirdValue, conversionData); + tz = thirdValue->computeLength<double>(conversionData); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); @@ -209,9 +200,6 @@ bool TransformBuilder::createTransformOperations(CSSValue* inValue, const CSSToL } } - if (tx.isUndefined() || ty.isUndefined() || tz.isUndefined()) - return false; - operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType()))); break; } @@ -305,18 +293,17 @@ bool TransformBuilder::createTransformOperations(CSSValue* inValue, const CSSToL break; } case CSSTransformValue::PerspectiveTransformOperation: { - Length p = Length(0, Fixed); + double p; if (firstValue->isLength()) - p = convertToFloatLength(firstValue, conversionData); + p = firstValue->computeLength<double>(conversionData); else { // This is a quirk that should go away when 3d transforms are finalized. double val = firstValue->getDoubleValue(); - p = val >= 0 ? Length(clampToPositiveInteger(val), Fixed) : Length(Undefined); + if (val < 0) + return false; + p = clampToPositiveInteger(val); } - if (p.isUndefined()) - return false; - operations.operations().append(PerspectiveTransformOperation::create(p)); break; } diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.h b/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.h index a3ac2e0b0f5..94fc5a5b946 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/TransformBuilder.h @@ -31,6 +31,7 @@ #ifndef TransformBuilder_h #define TransformBuilder_h +#include "platform/heap/Handle.h" #include "platform/transforms/TransformOperations.h" #include "wtf/Noncopyable.h" @@ -40,11 +41,8 @@ class CSSToLengthConversionData; class CSSValue; class TransformBuilder { - WTF_MAKE_NONCOPYABLE(TransformBuilder); WTF_MAKE_FAST_ALLOCATED; + STATIC_ONLY(TransformBuilder); public: - TransformBuilder(); - ~TransformBuilder(); - static bool createTransformOperations(CSSValue* inValue, const CSSToLengthConversionData&, TransformOperations& outOperations); }; diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp b/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp index 61894a2458a..a8c3be72ed1 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp @@ -30,41 +30,41 @@ #include "config.h" #include "core/css/resolver/ViewportStyleResolver.h" -#include "CSSValueKeywords.h" +#include "core/CSSValueKeywords.h" +#include "core/css/CSSPrimitiveValueMappings.h" #include "core/css/CSSToLengthConversionData.h" #include "core/css/StylePropertySet.h" #include "core/css/StyleRule.h" #include "core/dom/Document.h" #include "core/dom/NodeRenderStyle.h" #include "core/dom/ViewportDescription.h" +#include "core/frame/FrameView.h" namespace WebCore { +DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ViewportStyleResolver); + ViewportStyleResolver::ViewportStyleResolver(Document* document) - : m_document(document), - m_hasAuthorStyle(false) + : m_document(document) + , m_hasAuthorStyle(false) { ASSERT(m_document); } -ViewportStyleResolver::~ViewportStyleResolver() -{ -} - void ViewportStyleResolver::collectViewportRules(RuleSet* rules, Origin origin) { rules->compactRulesIfNeeded(); - const Vector<StyleRuleViewport*>& viewportRules = rules->viewportRules(); + const WillBeHeapVector<RawPtrWillBeMember<StyleRuleViewport> >& viewportRules = rules->viewportRules(); for (size_t i = 0; i < viewportRules.size(); ++i) addViewportRule(viewportRules[i], origin); } void ViewportStyleResolver::addViewportRule(StyleRuleViewport* viewportRule, Origin origin) { - StylePropertySet* propertySet = viewportRule->mutableProperties(); + StylePropertySet& propertySet = viewportRule->mutableProperties(); - unsigned propertyCount = propertySet->propertyCount(); + unsigned propertyCount = propertySet.propertyCount(); if (!propertyCount) return; @@ -72,19 +72,14 @@ void ViewportStyleResolver::addViewportRule(StyleRuleViewport* viewportRule, Ori m_hasAuthorStyle = true; if (!m_propertySet) { - m_propertySet = propertySet->mutableCopy(); + m_propertySet = propertySet.mutableCopy(); return; } // We cannot use mergeAndOverrideOnConflict() here because it doesn't // respect the !important declaration (but addParsedProperty() does). for (unsigned i = 0; i < propertyCount; ++i) - m_propertySet->addParsedProperty(propertySet->propertyAt(i).toCSSProperty()); -} - -void ViewportStyleResolver::clearDocument() -{ - m_document = 0; + m_propertySet->addParsedProperty(propertySet.propertyAt(i).toCSSProperty()); } void ViewportStyleResolver::resolve() @@ -92,10 +87,8 @@ void ViewportStyleResolver::resolve() if (!m_document) return; - if (!m_propertySet || (!m_hasAuthorStyle && m_document->hasLegacyViewportTag())) { - ASSERT(!m_hasAuthorStyle); - m_propertySet = 0; - m_document->setViewportDescription(ViewportDescription()); + if (!m_propertySet) { + m_document->setViewportDescription(ViewportDescription(ViewportDescription::UserAgentStyleSheet)); return; } @@ -113,7 +106,7 @@ void ViewportStyleResolver::resolve() m_document->setViewportDescription(description); - m_propertySet = 0; + m_propertySet = nullptr; m_hasAuthorStyle = false; } @@ -127,7 +120,7 @@ float ViewportStyleResolver::viewportArgumentValue(CSSPropertyID id) const if (id == CSSPropertyUserZoom) defaultValue = 1; - RefPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id); + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id); if (!value || !value->isPrimitiveValue()) return defaultValue; @@ -177,31 +170,36 @@ Length ViewportStyleResolver::viewportLengthValue(CSSPropertyID id) const || id == CSSPropertyMaxWidth || id == CSSPropertyMinWidth); - RefPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id); + RefPtrWillBeRawPtr<CSSValue> value = m_propertySet->getPropertyCSSValue(id); if (!value || !value->isPrimitiveValue()) return Length(); // auto CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value.get()); - if (primitiveValue->isLength()) - return primitiveValue->computeLength<Length>(CSSToLengthConversionData(m_document->renderStyle(), m_document->renderStyle(), 1.0f)); + if (primitiveValue->getValueID() == CSSValueInternalExtendToZoom) + return Length(ExtendToZoom); - if (primitiveValue->isViewportPercentageLength()) - return primitiveValue->viewportPercentageLength(); + RenderStyle* documentStyle = m_document->renderStyle(); - if (primitiveValue->isPercentage()) - return Length(primitiveValue->getFloatValue(), Percent); + // If we have viewport units the conversion will mark the document style as having viewport units. + bool documentStyleHasViewportUnits = documentStyle->hasViewportUnits(); + documentStyle->setHasViewportUnits(false); - switch (primitiveValue->getValueID()) { - case CSSValueInternalExtendToZoom: - return Length(ExtendToZoom); - case CSSValueAuto: - return Length(); - default: - // Unrecognized keyword. - ASSERT_NOT_REACHED(); - return Length(0, Fixed); - } + FrameView* view = m_document->view(); + float width = view ? view->width() : 0; + float height = view ? view->height() : 0; + + Length result = primitiveValue->convertToLength<AnyConversion>(CSSToLengthConversionData(documentStyle, documentStyle, width, height, 1.0f)); + if (documentStyle->hasViewportUnits()) + m_document->setHasViewportUnits(); + documentStyle->setHasViewportUnits(documentStyleHasViewportUnits); + + return result; +} + +void ViewportStyleResolver::trace(Visitor* visitor) +{ + visitor->trace(m_propertySet); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h b/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h index 30b663f2b18..604a9890b97 100644 --- a/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h +++ b/chromium/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.h @@ -30,7 +30,7 @@ #ifndef ViewportStyleResolver_h #define ViewportStyleResolver_h -#include "CSSPropertyNames.h" +#include "core/CSSPropertyNames.h" #include "core/css/RuleSet.h" #include "platform/Length.h" #include "wtf/RefCounted.h" @@ -42,22 +42,22 @@ class Document; class MutableStylePropertySet; class StyleRuleViewport; -class ViewportStyleResolver : public RefCounted<ViewportStyleResolver> { +class ViewportStyleResolver : public NoBaseWillBeGarbageCollected<ViewportStyleResolver> { + DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(ViewportStyleResolver); public: - static PassRefPtr<ViewportStyleResolver> create(Document* document) + static PassOwnPtrWillBeRawPtr<ViewportStyleResolver> create(Document* document) { - return adoptRef(new ViewportStyleResolver(document)); + return adoptPtrWillBeNoop(new ViewportStyleResolver(document)); } - ~ViewportStyleResolver(); - enum Origin { UserAgentOrigin, AuthorOrigin }; void collectViewportRules(RuleSet*, Origin); - void clearDocument(); void resolve(); + void trace(Visitor*); + private: explicit ViewportStyleResolver(Document*); @@ -67,7 +67,7 @@ private: Length viewportLengthValue(CSSPropertyID) const; Document* m_document; - RefPtr<MutableStylePropertySet> m_propertySet; + RefPtrWillBeMember<MutableStylePropertySet> m_propertySet; bool m_hasAuthorStyle; }; diff --git a/chromium/third_party/WebKit/Source/core/css/svg.css b/chromium/third_party/WebKit/Source/core/css/svg.css index 3975ab42872..6151d17c5d2 100644 --- a/chromium/third_party/WebKit/Source/core/css/svg.css +++ b/chromium/third_party/WebKit/Source/core/css/svg.css @@ -47,14 +47,23 @@ svg:not(:root), symbol, image, marker, pattern, foreignObject { overflow: hidden } +svg:root { + width: 100%; + height: 100% +} + text, foreignObject { display: block } -text, tspan, textPath { +text { white-space: nowrap } +tspan, textPath { + white-space: inherit +} + /* states */ :focus { diff --git a/chromium/third_party/WebKit/Source/core/css/themeChromium.css b/chromium/third_party/WebKit/Source/core/css/themeChromium.css index 0a413e1efde..6094c1dd04e 100644 --- a/chromium/third_party/WebKit/Source/core/css/themeChromium.css +++ b/chromium/third_party/WebKit/Source/core/css/themeChromium.css @@ -30,7 +30,7 @@ /* These styles override other user-agent styles for Chromium. */ -input:disabled, isindex:disabled, textarea:disabled { +input:disabled, textarea:disabled { color: #545454; /* Color::light() for #000000. See RenderTextControl.cpp:disabledTextColor */ } diff --git a/chromium/third_party/WebKit/Source/core/css/themeChromiumAndroid.css b/chromium/third_party/WebKit/Source/core/css/themeChromiumAndroid.css index be5488fc854..3ff3183058b 100644 --- a/chromium/third_party/WebKit/Source/core/css/themeChromiumAndroid.css +++ b/chromium/third_party/WebKit/Source/core/css/themeChromiumAndroid.css @@ -35,7 +35,22 @@ select[multiple], select[size][multiple] { -webkit-appearance: menulist; align-items: center; - border: 1px solid; + background-color: ButtonFace; + border: 1px solid #a9a9a9; border-radius: initial; white-space: pre; } + +input[type="date"]:disabled, +input[type="datetime-local"]:disabled, +input[type="month"]:disabled, +input[type="time"]:disabled, +input[type="week"]:disabled, +input[type="date"]:read-only, +input[type="datetime-local"]:read-only, +input[type="month"]:read-only, +input[type="time"]:read-only, +input[type="week"]:read-only { + background-color: ButtonFace; + color: GrayText; +}
\ No newline at end of file diff --git a/chromium/third_party/WebKit/Source/core/css/themeMac.css b/chromium/third_party/WebKit/Source/core/css/themeMac.css new file mode 100644 index 00000000000..64950d72c65 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/css/themeMac.css @@ -0,0 +1,20 @@ +/* Copyright 2014 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +select, input[type="color"][list] { + background-color: #f8f8f8; + border: 1px solid #a6a6a6; +} + +select[size], +select[multiple], +select[size][multiple] { + background: white; + border: 1px inset gray; +} + +input::-webkit-inner-spin-button { + align-self: center; +} diff --git a/chromium/third_party/WebKit/Source/core/css/themeWin.css b/chromium/third_party/WebKit/Source/core/css/themeWin.css index 3c727d33b66..09b348a35a7 100644 --- a/chromium/third_party/WebKit/Source/core/css/themeWin.css +++ b/chromium/third_party/WebKit/Source/core/css/themeWin.css @@ -33,7 +33,6 @@ making our form elements match Firefox's. */ input:not([type]), -input[type="color"], input[type="email"], input[type="number"], input[type="password"], diff --git a/chromium/third_party/WebKit/Source/core/css/view-source.css b/chromium/third_party/WebKit/Source/core/css/view-source.css index daebdbf4f67..6c2077c647c 100644 --- a/chromium/third_party/WebKit/Source/core/css/view-source.css +++ b/chromium/third_party/WebKit/Source/core/css/view-source.css @@ -82,6 +82,11 @@ tbody:last-child .webkit-line-content:empty:before { padding: 0 5px !important; } +.webkit-highlight { + background-color: rgb(100%, 42%, 42%); + border: 2px solid rgb(100%, 31%, 31%); +} + .webkit-html-tag { /* Keep this in sync with inspector.css (.webkit-html-tag) */ color: rgb(136, 18, 128); |