Support <box> values computed style for 'clip-path' property
authorkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Jan 2014 18:11:51 +0000 (18:11 +0000)
committerkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Jan 2014 18:11:51 +0000 (18:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=126148

Reviewed by Simon Fraser.

Source/WebCore:

Calculate computed style for 'clip-path' property.

Updated tests to check for computed style.

* css/BasicShapeFunctions.cpp: Add box value bounding-box.
(WebCore::valueForBox):
(WebCore::boxForValue):
* css/CSSComputedStyleDeclaration.cpp: Return the computed style
    for 'clip-path'.
(WebCore::ComputedStyleExtractor::propertyValue):
* css/DeprecatedStyleBuilder.cpp: Create CSSValueLists for 'clip-th'.
(WebCore::ApplyPropertyClipPath::applyValue):
* rendering/ClipPathOperation.h: Add bounding-box value.
(WebCore::ShapeClipPathOperation::pathForReferenceRect):
(WebCore::ShapeClipPathOperation::setReferenceBox):
(WebCore::ShapeClipPathOperation::referenceBox):
(WebCore::BoxClipPathOperation::create):
(WebCore::BoxClipPathOperation::pathForReferenceRect):
(WebCore::BoxClipPathOperation::referenceBox):
(WebCore::BoxClipPathOperation::BoxClipPathOperation):
* rendering/shapes/ShapeInfo.h: Add bounding-box value.
(WebCore::ShapeInfo::setShapeSize):
(WebCore::ShapeInfo::logicalTopOffset):
(WebCore::ShapeInfo::logicalLeftOffset):
* rendering/style/BasicShapes.cpp: Add bounding-box value.
(WebCore::BasicShape::referenceBoxSize):
* rendering/style/BasicShapes.h:

LayoutTests:

Test computed style of 'clip-path' property.

* fast/masking/parsing-clip-path-shape.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@161209 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/masking/parsing-clip-path-shape-expected.txt
LayoutTests/fast/masking/parsing-clip-path-shape.html
Source/WebCore/ChangeLog
Source/WebCore/css/BasicShapeFunctions.cpp
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/DeprecatedStyleBuilder.cpp
Source/WebCore/page/animation/CSSPropertyAnimation.cpp
Source/WebCore/rendering/ClipPathOperation.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/shapes/ShapeInfo.h
Source/WebCore/rendering/style/BasicShapes.cpp
Source/WebCore/rendering/style/BasicShapes.h
Source/WebCore/rendering/svg/SVGRenderingContext.cpp

index b6bfd50..ce94d7a 100644 (file)
@@ -1,3 +1,14 @@
+2014-01-02  Dirk Schulze  <krit@webkit.org>
+
+        Support <box> values computed style for 'clip-path' property
+        https://bugs.webkit.org/show_bug.cgi?id=126148
+
+        Reviewed by Simon Fraser.
+
+        Test computed style of 'clip-path' property.
+
+        * fast/masking/parsing-clip-path-shape.html:
+
 2014-01-01  Antti Koivisto  <antti@apple.com>
 
         Do less synchronous render tree construction
index 4a61f6d..32f5783 100644 (file)
@@ -58,6 +58,16 @@ PASS innerStyle("-webkit-clip-path", "circle(50% at 50% 50%) padding-box") is "c
 PASS innerStyle("-webkit-clip-path", "margin-box circle(50% at 50% 50%)") is "margin-box circle(50% at 50% 50%)"
 PASS innerStyle("-webkit-clip-path", "border-box circle(50% at 50% 50%)") is "border-box circle(50% at 50% 50%)"
 PASS innerStyle("-webkit-clip-path", "circle(50% at 50% 50%) bounding-box") is "circle(50% at 50% 50%) bounding-box"
+PASS computedStyle("-webkit-clip-path", "content-box") is "content-box"
+PASS computedStyle("-webkit-clip-path", "padding-box") is "padding-box"
+PASS computedStyle("-webkit-clip-path", "border-box") is "border-box"
+PASS computedStyle("-webkit-clip-path", "margin-box") is "margin-box"
+PASS computedStyle("-webkit-clip-path", "bounding-box") is "bounding-box"
+PASS computedStyle("-webkit-clip-path", "circle(50% at 50% 50%) content-box") is "circle(50% at 50% 50%) content-box"
+PASS computedStyle("-webkit-clip-path", "circle(50% at 50% 50%) padding-box") is "circle(50% at 50% 50%) padding-box"
+PASS computedStyle("-webkit-clip-path", "margin-box circle(50% at 50% 50%)") is "circle(50% at 50% 50%) margin-box"
+PASS computedStyle("-webkit-clip-path", "border-box circle(50% at 50% 50%)") is "circle(50% at 50% 50%) border-box"
+PASS computedStyle("-webkit-clip-path", "circle(50% at 50% 50%) bounding-box") is "circle(50% at 50% 50%) bounding-box"
 PASS innerStyle("-webkit-clip-path", "circle(1px, 1px, 1)") is null
 PASS computedStyle("-webkit-clip-path", "circle(1px, 1px, 1)") is "none"
 PASS innerStyle("-webkit-clip-path", "circle(1px, 1px, px)") is null
index 1d4929e..6c6cbb4 100644 (file)
@@ -118,6 +118,17 @@ testInner("-webkit-clip-path", "margin-box circle(50% at 50% 50%)", "margin-box
 testInner("-webkit-clip-path", "border-box circle(50% at 50% 50%)", "border-box circle(50% at 50% 50%)");
 testInner("-webkit-clip-path", "circle(50% at 50% 50%) bounding-box", "circle(50% at 50% 50%) bounding-box");
 
+testComputed("-webkit-clip-path", "content-box", "content-box");
+testComputed("-webkit-clip-path", "padding-box", "padding-box");
+testComputed("-webkit-clip-path", "border-box", "border-box");
+testComputed("-webkit-clip-path", "margin-box", "margin-box");
+testComputed("-webkit-clip-path", "bounding-box", "bounding-box");
+testComputed("-webkit-clip-path", "circle(50% at 50% 50%) content-box", "circle(50% at 50% 50%) content-box");
+testComputed("-webkit-clip-path", "circle(50% at 50% 50%) padding-box", "circle(50% at 50% 50%) padding-box");
+testComputed("-webkit-clip-path", "margin-box circle(50% at 50% 50%)", "circle(50% at 50% 50%) margin-box");
+testComputed("-webkit-clip-path", "border-box circle(50% at 50% 50%)", "circle(50% at 50% 50%) border-box");
+testComputed("-webkit-clip-path", "circle(50% at 50% 50%) bounding-box", "circle(50% at 50% 50%) bounding-box");
+
 // reject non-lengths
 negativeTest("-webkit-clip-path", "circle(1px, 1px, 1)");
 negativeTest("-webkit-clip-path", "circle(1px, 1px, px)");
index 7e1f237..391f8aa 100644 (file)
@@ -1,3 +1,38 @@
+2014-01-02  Dirk Schulze  <krit@webkit.org>
+
+        Support <box> values computed style for 'clip-path' property
+        https://bugs.webkit.org/show_bug.cgi?id=126148
+
+        Reviewed by Simon Fraser.
+
+        Calculate computed style for 'clip-path' property.
+
+        Updated tests to check for computed style.
+
+        * css/BasicShapeFunctions.cpp: Add box value bounding-box.
+        (WebCore::valueForBox):
+        (WebCore::boxForValue):
+        * css/CSSComputedStyleDeclaration.cpp: Return the computed style
+            for 'clip-path'.
+        (WebCore::ComputedStyleExtractor::propertyValue):
+        * css/DeprecatedStyleBuilder.cpp: Create CSSValueLists for 'clip-th'.
+        (WebCore::ApplyPropertyClipPath::applyValue):
+        * rendering/ClipPathOperation.h: Add bounding-box value.
+        (WebCore::ShapeClipPathOperation::pathForReferenceRect):
+        (WebCore::ShapeClipPathOperation::setReferenceBox):
+        (WebCore::ShapeClipPathOperation::referenceBox):
+        (WebCore::BoxClipPathOperation::create):
+        (WebCore::BoxClipPathOperation::pathForReferenceRect):
+        (WebCore::BoxClipPathOperation::referenceBox):
+        (WebCore::BoxClipPathOperation::BoxClipPathOperation):
+        * rendering/shapes/ShapeInfo.h: Add bounding-box value.
+        (WebCore::ShapeInfo::setShapeSize):
+        (WebCore::ShapeInfo::logicalTopOffset):
+        (WebCore::ShapeInfo::logicalLeftOffset):
+        * rendering/style/BasicShapes.cpp: Add bounding-box value.
+        (WebCore::BasicShape::referenceBoxSize):
+        * rendering/style/BasicShapes.h:
+
 2014-01-02  Antti Koivisto  <antti@apple.com>
 
         Always resolve style from root
index 4def700..d884dc6 100644 (file)
@@ -50,6 +50,8 @@ PassRefPtr<CSSPrimitiveValue> valueForBox(BasicShape::ReferenceBox box)
         return cssValuePool().createIdentifierValue(CSSValueBorderBox);
     case BasicShape::MarginBox:
         return cssValuePool().createIdentifierValue(CSSValueMarginBox);
+    case BasicShape::BoundingBox:
+        return cssValuePool().createIdentifierValue(CSSValueBoundingBox);
     case BasicShape::None:
         return nullptr;
     }
@@ -71,6 +73,8 @@ BasicShape::ReferenceBox boxForValue(const CSSPrimitiveValue* value)
         return BasicShape::BorderBox;
     case CSSValueMarginBox:
         return BasicShape::MarginBox;
+    case CSSValueBoundingBox:
+        return BasicShape::BoundingBox;
     default:
         ASSERT_NOT_REACHED();
         return BasicShape::None;
index aadb76b..608ef5d 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
  * Copyright (C) 2011 Sencha, Inc. All rights reserved.
+ * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -2859,18 +2860,29 @@ PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propert
             return counterToCSSValue(style.get(), propertyID);
         case CSSPropertyCounterReset:
             return counterToCSSValue(style.get(), propertyID);
-        case CSSPropertyWebkitClipPath:
-            if (ClipPathOperation* operation = style->clipPath()) {
-                if (operation->type() == ClipPathOperation::SHAPE)
-                    return valueForBasicShape(style.get(), static_cast<ShapeClipPathOperation*>(operation)->basicShape());
+        case CSSPropertyWebkitClipPath: {
+            ClipPathOperation* operation = style->clipPath();
+            if (!operation)
+                return cssValuePool().createIdentifierValue(CSSValueNone);
 #if ENABLE(SVG)
-                if (operation->type() == ClipPathOperation::REFERENCE) {
-                    ReferenceClipPathOperation* referenceOperation = static_cast<ReferenceClipPathOperation*>(operation);
-                    return CSSPrimitiveValue::create(referenceOperation->url(), CSSPrimitiveValue::CSS_URI);
-                }
+            if (operation->type() == ClipPathOperation::Reference) {
+                ReferenceClipPathOperation& referenceOperation = toReferenceClipPathOperation(*operation);
+                return CSSPrimitiveValue::create(referenceOperation.url(), CSSPrimitiveValue::CSS_URI);
+            }
 #endif
+            RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+            if (operation->type() == ClipPathOperation::Shape) {
+                ShapeClipPathOperation& shapeOperation = toShapeClipPathOperation(*operation);
+                list->append(valueForBasicShape(style.get(), shapeOperation.basicShape()));
+                if (shapeOperation.referenceBox() != BasicShape::ReferenceBox::None)
+                    list->append(valueForBox(shapeOperation.referenceBox()));
             }
-            return cssValuePool().createIdentifierValue(CSSValueNone);
+            if (operation->type() == ClipPathOperation::Box) {
+                BoxClipPathOperation& boxOperation = toBoxClipPathOperation(*operation);
+                list->append(valueForBox(boxOperation.referenceBox()));
+            }
+            return list.release();
+        }
 #if ENABLE(CSS_REGIONS)
         case CSSPropertyWebkitFlowInto:
             if (style->flowThread().isNull())
index 8611fad..4fb0516 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2011 Google Inc. All rights reserved.
  * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 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
@@ -2062,16 +2063,30 @@ public:
         }
         if (!value->isValueList())
             return;
+        BasicShape::ReferenceBox referenceBox = BasicShape::ReferenceBox::None;
+        RefPtr<ClipPathOperation> operation;
         auto& valueList = toCSSValueList(*value);
         for (unsigned i = 0; i < valueList.length(); ++i) {
-            // FIXME: <box> values are not supported yet.
-            // https://bugs.webkit.org/show_bug.cgi?id=126148
             auto& primitiveValue = toCSSPrimitiveValue(*valueList.itemWithoutBoundsCheck(i));
-            if (!primitiveValue.isShape())
-                continue;
-            setValue(styleResolver->style(), ShapeClipPathOperation::create(basicShapeForValue(styleResolver->style(), styleResolver->rootElementStyle(), primitiveValue.getShapeValue())));
-            break;
+            if (primitiveValue.isShape() && !operation)
+                operation = ShapeClipPathOperation::create(basicShapeForValue(styleResolver->style(), styleResolver->rootElementStyle(), primitiveValue.getShapeValue()));
+            else if ((primitiveValue.getValueID() == CSSValueContentBox
+                || primitiveValue.getValueID() == CSSValueBorderBox
+                || primitiveValue.getValueID() == CSSValuePaddingBox
+                || primitiveValue.getValueID() == CSSValueMarginBox
+                || primitiveValue.getValueID() == CSSValueBoundingBox)
+                && referenceBox == BasicShape::ReferenceBox::None)
+                referenceBox = boxForValue(&primitiveValue);
+            else
+                return;
         }
+        if (!operation) {
+            if (referenceBox == BasicShape::ReferenceBox::None)
+                return;
+            operation = BoxClipPathOperation::create(referenceBox);
+        } else
+            toShapeClipPathOperation(operation.get())->setReferenceBox(referenceBox);
+        setValue(styleResolver->style(), operation.release());
     }
     static PropertyHandler createHandler()
     {
index c28c134..bb3e3e8 100644 (file)
@@ -131,7 +131,7 @@ static inline PassRefPtr<ClipPathOperation> blendFunc(const AnimationBase* anim,
         return to;
 
     // Other clip-path operations than BasicShapes can not be animated.
-    if (from->type() != ClipPathOperation::SHAPE || to->type() != ClipPathOperation::SHAPE)
+    if (from->type() != ClipPathOperation::Shape || to->type() != ClipPathOperation::Shape)
         return to;
 
     const BasicShape* fromShape = static_cast<ShapeClipPathOperation*>(from)->basicShape();
index 6ab8852..0a28ac0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ * Copyright (C) 2012, 2013 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
@@ -42,8 +42,9 @@ namespace WebCore {
 class ClipPathOperation : public RefCounted<ClipPathOperation> {
 public:
     enum OperationType {
-        REFERENCE,
-        SHAPE
+        Reference,
+        Shape,
+        Box
     };
 
     virtual ~ClipPathOperation() { }
@@ -83,7 +84,7 @@ private:
     }
 
     ReferenceClipPathOperation(const String& url, const String& fragment)
-        : ClipPathOperation(REFERENCE)
+        : ClipPathOperation(Reference)
         , m_url(url)
         , m_fragment(fragment)
     {
@@ -102,15 +103,19 @@ public:
 
     const BasicShape* basicShape() const { return m_shape.get(); }
     WindRule windRule() const { return m_shape->windRule(); }
-    const Path& path(const FloatRect& boundingRect)
+    const Path pathForReferenceRect(const FloatRect& boundingRect) const
     {
         ASSERT(m_shape);
-        m_path.clear();
-        m_path = adoptPtr(new Path);
-        m_shape->path(*m_path, boundingRect);
-        return *m_path;
+        // FIXME: Make clipping path from basic-shapes relative to <box> value.
+        // https://bugs.webkit.org/show_bug.cgi?id=126206
+        Path path;
+        m_shape->path(path, boundingRect);
+        return path;
     }
 
+    void setReferenceBox(BasicShape::ReferenceBox referenceBox) { m_referenceBox = referenceBox; }
+    BasicShape::ReferenceBox referenceBox() const { return m_referenceBox; }
+
 private:
     virtual bool operator==(const ClipPathOperation& o) const OVERRIDE
     {
@@ -121,14 +126,57 @@ private:
     }
 
     explicit ShapeClipPathOperation(PassRefPtr<BasicShape> shape)
-        : ClipPathOperation(SHAPE)
+        : ClipPathOperation(Shape)
         , m_shape(shape)
+        , m_referenceBox(BasicShape::ReferenceBox::None)
     {
     }
 
     RefPtr<BasicShape> m_shape;
-    OwnPtr<Path> m_path;
+    BasicShape::ReferenceBox m_referenceBox;
 };
-}
+
+class BoxClipPathOperation : public ClipPathOperation {
+public:
+    static PassRefPtr<BoxClipPathOperation> create(BasicShape::ReferenceBox referenceBox)
+    {
+        return adoptRef(new BoxClipPathOperation(referenceBox));
+    }
+
+    const Path pathForReferenceRect(const FloatRect&) const
+    {
+        Path path;
+        // FIXME: Create clipping path from <box>.
+        // https://bugs.webkit.org/show_bug.cgi?id=126205
+        return path;
+    }
+    BasicShape::ReferenceBox referenceBox() const { return m_referenceBox; }
+
+private:
+    virtual bool operator==(const ClipPathOperation& o) const OVERRIDE
+    {
+        if (!isSameType(o))
+            return false;
+        const BoxClipPathOperation* other = static_cast<const BoxClipPathOperation*>(&o);
+        return m_referenceBox == other->m_referenceBox;
+    }
+
+    explicit BoxClipPathOperation(BasicShape::ReferenceBox referenceBox)
+        : ClipPathOperation(Box)
+        , m_referenceBox(referenceBox)
+    {
+    }
+
+    BasicShape::ReferenceBox m_referenceBox;
+};
+
+#define CLIP_PATH_OPERATION_CASTS(ToValueTypeName, predicate) \
+    TYPE_CASTS_BASE(ToValueTypeName, ClipPathOperation, operation, operation->type() == ClipPathOperation::predicate, operation.type() == ClipPathOperation::predicate)
+
+CLIP_PATH_OPERATION_CASTS(ReferenceClipPathOperation, Reference)
+CLIP_PATH_OPERATION_CASTS(ShapeClipPathOperation, Shape)
+CLIP_PATH_OPERATION_CASTS(BoxClipPathOperation, Box)
+
+} // namespace WebCore
 
 #endif // ClipPathOperation_h
index b32bb52..b89917d 100644 (file)
@@ -3916,7 +3916,7 @@ bool RenderLayer::setupClipPath(GraphicsContext* context, const LayerPaintingInf
     RenderStyle& style = renderer().style();
 
     ASSERT(style.clipPath());
-    if (style.clipPath()->type() == ClipPathOperation::SHAPE) {
+    if (style.clipPath()->type() == ClipPathOperation::Shape) {
         ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(style.clipPath());
 
         if (!rootRelativeBoundsComputed) {
@@ -3925,12 +3925,12 @@ bool RenderLayer::setupClipPath(GraphicsContext* context, const LayerPaintingInf
         }
 
         context->save();
-        context->clipPath(clipPath->path(rootRelativeBounds), clipPath->windRule());
+        context->clipPath(clipPath->pathForReferenceRect(rootRelativeBounds), clipPath->windRule());
         return true;
     }
 
 #if ENABLE(SVG)
-    if (style.clipPath()->type() == ClipPathOperation::REFERENCE) {
+    if (style.clipPath()->type() == ClipPathOperation::Reference) {
         ReferenceClipPathOperation* referenceClipPathOperation = static_cast<ReferenceClipPathOperation*>(style.clipPath());
         Element* element = renderer().document().getElementById(referenceClipPathOperation->fragment());
         if (element && element->hasTagName(SVGNames::clipPathTag) && element->renderer()) {
index 478a876..3e27dc3 100644 (file)
@@ -89,6 +89,7 @@ public:
             logicalHeight -= m_renderer.borderAndPaddingLogicalHeight();
             logicalWidth -= m_renderer.borderAndPaddingLogicalWidth();
             break;
+        case BasicShape::BoundingBox:
         case BasicShape::None:
             ASSERT_NOT_REACHED();
             break;
@@ -175,6 +176,7 @@ protected:
         case BasicShape::BorderBox: return LayoutUnit();
         case BasicShape::PaddingBox: return m_renderer.borderBefore();
         case BasicShape::ContentBox: return m_renderer.borderAndPaddingBefore();
+        case BasicShape::BoundingBox: break;
         case BasicShape::None: break;
         }
         ASSERT_NOT_REACHED();
@@ -191,6 +193,7 @@ protected:
         case BasicShape::BorderBox: return LayoutUnit();
         case BasicShape::PaddingBox: return m_renderer.borderStart();
         case BasicShape::ContentBox: return m_renderer.borderAndPaddingStart();
+        case BasicShape::BoundingBox: break;
         case BasicShape::None: break;
         }
         ASSERT_NOT_REACHED();
index 8850b5a..8b8dd44 100644 (file)
@@ -86,6 +86,8 @@ FloatSize BasicShape::referenceBoxSize(const RenderBox& renderer) const
     case MarginBox:
         return FloatSize(renderer.marginLeft() + renderer.width() + renderer.marginRight(),
             renderer.marginTop() + renderer.height() + renderer.marginBottom());
+    case BoundingBox:
+        break;
     }
 
     ASSERT_NOT_REACHED();
index f9ddf16..dcf93fd 100644 (file)
@@ -63,7 +63,8 @@ public:
         ContentBox,
         PaddingBox,
         BorderBox,
-        MarginBox
+        MarginBox,
+        BoundingBox
     };
 
     bool canBlend(const BasicShape*) const;
index 72e363d..36d95c1 100644 (file)
@@ -123,9 +123,9 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai
     }
 
     ClipPathOperation* clipPathOperation = style.clipPath();
-    if (clipPathOperation && clipPathOperation->type() == ClipPathOperation::SHAPE) {
+    if (clipPathOperation && clipPathOperation->type() == ClipPathOperation::Shape) {
         ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(clipPathOperation);
-        m_paintInfo->context->clipPath(clipPath->path(renderer.objectBoundingBox()), clipPath->windRule());
+        m_paintInfo->context->clipPath(clipPath->pathForReferenceRect(renderer.objectBoundingBox()), clipPath->windRule());
     }
 
     SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(*m_renderer);