[Conic Gradients] Add support for parsing conic gradients
[WebKit-https.git] / Source / WebCore / css / CSSGradientValue.h
index 413dd2e..9f66aec 100644 (file)
  *    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
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE 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. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef CSSGradientValue_h
-#define CSSGradientValue_h
+#pragma once
 
 #include "CSSImageGeneratorValue.h"
 #include "CSSPrimitiveValue.h"
-#include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
 
 class FloatPoint;
 class Gradient;
-
-enum CSSGradientType { CSSLinearGradient, CSSRadialGradient };
+class StyleResolver;
+
+enum CSSGradientType {
+    CSSDeprecatedLinearGradient,
+    CSSDeprecatedRadialGradient,
+    CSSPrefixedLinearGradient,
+    CSSPrefixedRadialGradient,
+    CSSLinearGradient,
+    CSSRadialGradient,
+    CSSConicGradient
+};
 enum CSSGradientRepeat { NonRepeating, Repeating };
 
 struct CSSGradientColorStop {
     RefPtr<CSSPrimitiveValue> m_position; // percentage or length
     RefPtr<CSSPrimitiveValue> m_color;
+    Color m_resolvedColor;
+    bool m_colorIsDerivedFromElement = false;
+    bool isMidpoint = false;
+    bool operator==(const CSSGradientColorStop& other) const
+    {
+        return compareCSSValuePtr(m_color, other.m_color)
+            && compareCSSValuePtr(m_position, other.m_position);
+    }
 };
 
 class CSSGradientValue : public CSSImageGeneratorValue {
 public:
-    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&);
+    RefPtr<Image> image(RenderElement&, const FloatSize&);
+
+    void setFirstX(RefPtr<CSSPrimitiveValue>&& val) { m_firstX = WTFMove(val); }
+    void setFirstY(RefPtr<CSSPrimitiveValue>&& val) { m_firstY = WTFMove(val); }
+    void setSecondX(RefPtr<CSSPrimitiveValue>&& val) { m_secondX = WTFMove(val); }
+    void setSecondY(RefPtr<CSSPrimitiveValue>&& val) { m_secondY = WTFMove(val); }
 
-    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 addStop(const CSSGradientColorStop& stop) { m_stops.append(stop); }
 
-    Vector<CSSGradientColorStop>& stops() { return m_stops; }
+    unsigned stopCount() const { return m_stops.size(); }
 
     void sortStopsIfNeeded();
-    
-    virtual bool isLinearGradient() const { return false; }
-    virtual bool isRadialGradient() const { return false; }
-    
+
     bool isRepeating() const { return m_repeating; }
 
-    bool deprecatedType() const { return m_deprecatedType; } // came from -webkit-gradient
+    CSSGradientType gradientType() const { return m_gradientType; }
+
+    bool isFixedSize() const { return false; }
+    FloatSize fixedSize(const RenderElement&) const { return FloatSize(); }
+
+    bool isPending() const { return false; }
+    bool knownToBeOpaque() const;
+
+    void loadSubimages(CachedResourceLoader&, const ResourceLoaderOptions&) { }
+    Ref<CSSGradientValue> gradientWithStylesResolved(const StyleResolver&);
 
 protected:
-    CSSGradientValue(CSSGradientRepeat repeat, bool deprecatedType = false)
-        : m_stopsSorted(false)
-        , m_deprecatedType(deprecatedType)
+    CSSGradientValue(ClassType classType, CSSGradientRepeat repeat, CSSGradientType gradientType)
+        : CSSImageGeneratorValue(classType)
+        , m_stopsSorted(false)
+        , m_gradientType(gradientType)
         , m_repeating(repeat == Repeating)
     {
     }
-    
-    void addStops(Gradient*, RenderObject*, RenderStyle* rootStyle, float maxLengthForRepeat = 0);
 
-    // Create the gradient for a given size.
-    virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&) = 0;
+    CSSGradientValue(const CSSGradientValue& other, ClassType classType, CSSGradientType gradientType)
+        : CSSImageGeneratorValue(classType)
+        , m_firstX(other.m_firstX)
+        , m_firstY(other.m_firstY)
+        , m_secondX(other.m_secondX)
+        , m_secondY(other.m_secondY)
+        , m_stops(other.m_stops)
+        , m_stopsSorted(other.m_stopsSorted)
+        , m_gradientType(gradientType)
+        , m_repeating(other.isRepeating() ? Repeating : NonRepeating)
+    {
+    }
+
+    void addStops(Gradient&, const CSSToLengthConversionData&, float maxLengthForRepeat = 0);
 
     // Resolve points/radii to front end values.
-    FloatPoint computeEndPoint(CSSPrimitiveValue*, CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, const IntSize&);
+    FloatPoint computeEndPoint(CSSPrimitiveValue*, CSSPrimitiveValue*, const CSSToLengthConversionData&, const FloatSize&);
+
+    bool isCacheable() const;
 
-    // Points. Some of these may be null for linear gradients.
+    // Points. Some of these may be null.
     RefPtr<CSSPrimitiveValue> m_firstX;
     RefPtr<CSSPrimitiveValue> m_firstY;
-    
+
     RefPtr<CSSPrimitiveValue> m_secondX;
     RefPtr<CSSPrimitiveValue> m_secondY;
-    
+
     // Stops
-    Vector<CSSGradientColorStop> m_stops;
+    Vector<CSSGradientColorStop, 2> m_stops;
     bool m_stopsSorted;
-    bool m_deprecatedType; // -webkit-gradient()
+    CSSGradientType m_gradientType;
     bool m_repeating;
 };
 
-
-class CSSLinearGradientValue : public CSSGradientValue {
+class CSSLinearGradientValue final : public CSSGradientValue {
 public:
-    static PassRefPtr<CSSLinearGradientValue> create(CSSGradientRepeat repeat, bool deprecatedType = false)
+    static Ref<CSSLinearGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient)
     {
-        return adoptRef(new CSSLinearGradientValue(repeat, deprecatedType));
+        return adoptRef(*new CSSLinearGradientValue(repeat, gradientType));
     }
 
-    void setAngle(PassRefPtr<CSSPrimitiveValue> val) { m_angle = val; }
+    void setAngle(Ref<CSSPrimitiveValue>&& val) { m_angle = WTFMove(val); }
 
-    virtual String cssText() const;
+    String customCSSText() const;
 
-private:
-    CSSLinearGradientValue(CSSGradientRepeat repeat, bool deprecatedType = false)
-        : CSSGradientValue(repeat, deprecatedType)
+    // Create the gradient for a given size.
+    Ref<Gradient> createGradient(RenderElement&, const FloatSize&);
+
+    Ref<CSSLinearGradientValue> clone() const
     {
+        return adoptRef(*new CSSLinearGradientValue(*this));
     }
 
-    virtual bool isLinearGradient() const { return true; }
+    bool equals(const CSSLinearGradientValue&) const;
 
-    // Create the gradient for a given size.
-    virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
+private:
+    CSSLinearGradientValue(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSLinearGradient)
+        : CSSGradientValue(LinearGradientClass, repeat, gradientType)
+    {
+    }
+
+    CSSLinearGradientValue(const CSSLinearGradientValue& other)
+        : CSSGradientValue(other, LinearGradientClass, other.gradientType())
+        , m_angle(other.m_angle)
+    {
+    }
 
     RefPtr<CSSPrimitiveValue> m_angle; // may be null.
 };
 
-class CSSRadialGradientValue : public CSSGradientValue {
+class CSSRadialGradientValue final : public CSSGradientValue {
 public:
-    static PassRefPtr<CSSRadialGradientValue> create(CSSGradientRepeat repeat, bool deprecatedType = false)
+    static Ref<CSSRadialGradientValue> create(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient)
+    {
+        return adoptRef(*new CSSRadialGradientValue(repeat, gradientType));
+    }
+
+    Ref<CSSRadialGradientValue> clone() const
     {
-        return adoptRef(new CSSRadialGradientValue(repeat, deprecatedType));
+        return adoptRef(*new CSSRadialGradientValue(*this));
     }
 
-    virtual String cssText() const;
+    String customCSSText() const;
 
-    void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; }
-    void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; }
+    void setFirstRadius(RefPtr<CSSPrimitiveValue>&& val) { m_firstRadius = WTFMove(val); }
+    void setSecondRadius(RefPtr<CSSPrimitiveValue>&& val) { m_secondRadius = WTFMove(val); }
 
-    void setShape(PassRefPtr<CSSPrimitiveValue> val) { m_shape = val; }
-    void setSizingBehavior(PassRefPtr<CSSPrimitiveValue> val) { m_sizingBehavior = val; }
+    void setShape(RefPtr<CSSPrimitiveValue>&& val) { m_shape = WTFMove(val); }
+    void setSizingBehavior(RefPtr<CSSPrimitiveValue>&& val) { m_sizingBehavior = WTFMove(val); }
 
-    void setEndHorizontalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endHorizontalSize = val; }
-    void setEndVerticalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endVerticalSize = val; }
+    void setEndHorizontalSize(RefPtr<CSSPrimitiveValue>&& val) { m_endHorizontalSize = WTFMove(val); }
+    void setEndVerticalSize(RefPtr<CSSPrimitiveValue>&& val) { m_endVerticalSize = WTFMove(val); }
+
+    // Create the gradient for a given size.
+    Ref<Gradient> createGradient(RenderElement&, const FloatSize&);
+
+    bool equals(const CSSRadialGradientValue&) const;
 
 private:
-    CSSRadialGradientValue(CSSGradientRepeat repeat, bool deprecatedType = false)
-        : CSSGradientValue(repeat, deprecatedType)
+    CSSRadialGradientValue(CSSGradientRepeat repeat, CSSGradientType gradientType = CSSRadialGradient)
+        : CSSGradientValue(RadialGradientClass, repeat, gradientType)
     {
     }
 
-    virtual bool isRadialGradient() const { return true; }
+    CSSRadialGradientValue(const CSSRadialGradientValue& other)
+        : CSSGradientValue(other, RadialGradientClass, other.gradientType())
+        , m_firstRadius(other.m_firstRadius)
+        , m_secondRadius(other.m_secondRadius)
+        , m_shape(other.m_shape)
+        , m_sizingBehavior(other.m_sizingBehavior)
+        , m_endHorizontalSize(other.m_endHorizontalSize)
+        , m_endVerticalSize(other.m_endVerticalSize)
+    {
+    }
 
-    // Create the gradient for a given size.
-    virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
-    
     // Resolve points/radii to front end values.
-    float resolveRadius(CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, float* widthOrHeight = 0);
-    
+    float resolveRadius(CSSPrimitiveValue&, const CSSToLengthConversionData&, float* widthOrHeight = 0);
+
     // These may be null for non-deprecated gradients.
     RefPtr<CSSPrimitiveValue> m_firstRadius;
     RefPtr<CSSPrimitiveValue> m_secondRadius;
 
-    // The below are only used for non-deprecated gradients.
+    // The below are only used for non-deprecated gradients. Any of them may be null.
     RefPtr<CSSPrimitiveValue> m_shape;
     RefPtr<CSSPrimitiveValue> m_sizingBehavior;
 
@@ -166,6 +226,45 @@ private:
     RefPtr<CSSPrimitiveValue> m_endVerticalSize;
 };
 
+class CSSConicGradientValue final : public CSSGradientValue {
+public:
+    static Ref<CSSConicGradientValue> create(CSSGradientRepeat repeat)
+    {
+        return adoptRef(*new CSSConicGradientValue(repeat));
+    }
+
+    Ref<CSSConicGradientValue> clone() const
+    {
+        return adoptRef(*new CSSConicGradientValue(*this));
+    }
+
+    String customCSSText() const;
+
+    void setAngle(RefPtr<CSSPrimitiveValue>&& val) { m_angle = WTFMove(val); }
+
+    // Create the gradient for a given size.
+    Ref<Gradient> createGradient(RenderElement&, const FloatSize&);
+
+    bool equals(const CSSConicGradientValue&) const;
+
+private:
+    CSSConicGradientValue(CSSGradientRepeat repeat)
+        : CSSGradientValue(ConicGradientClass, repeat, CSSConicGradient)
+    {
+    }
+
+    CSSConicGradientValue(const CSSConicGradientValue& other)
+        : CSSGradientValue(other, ConicGradientClass, other.gradientType())
+        , m_angle(other.m_angle)
+    {
+    }
+
+    RefPtr<CSSPrimitiveValue> m_angle; // may be null.
+};
+
 } // namespace WebCore
 
-#endif // CSSGradientValue_h
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSGradientValue, isGradientValue())
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSLinearGradientValue, isLinearGradientValue())
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSRadialGradientValue, isRadialGradientValue())
+SPECIALIZE_TYPE_TRAITS_CSS_VALUE(CSSConicGradientValue, isConicGradientValue())