Home | History | Annotate | Download | only in style
      1 /*
      2  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1. Redistributions of source code must retain the above
      9  *    copyright notice, this list of conditions and the following
     10  *    disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above
     12  *    copyright notice, this list of conditions and the following
     13  *    disclaimer in the documentation and/or other materials
     14  *    provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
     17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
     20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
     21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
     26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #ifndef BasicShapes_h
     31 #define BasicShapes_h
     32 
     33 #include "core/rendering/style/RenderStyleConstants.h"
     34 #include "platform/Length.h"
     35 #include "platform/LengthSize.h"
     36 #include "platform/graphics/WindRule.h"
     37 #include "wtf/RefCounted.h"
     38 #include "wtf/RefPtr.h"
     39 #include "wtf/Vector.h"
     40 
     41 namespace WebCore {
     42 
     43 class FloatRect;
     44 class FloatSize;
     45 class Path;
     46 
     47 class BasicShape : public RefCounted<BasicShape> {
     48 public:
     49     virtual ~BasicShape() { }
     50 
     51     enum Type {
     52         BasicShapeEllipseType,
     53         BasicShapePolygonType,
     54         BasicShapeCircleType,
     55         BasicShapeInsetType
     56     };
     57 
     58     bool canBlend(const BasicShape*) const;
     59     bool isSameType(const BasicShape& other) const { return type() == other.type(); }
     60 
     61     virtual void path(Path&, const FloatRect&) = 0;
     62     virtual WindRule windRule() const { return RULE_NONZERO; }
     63     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const = 0;
     64     virtual bool operator==(const BasicShape&) const = 0;
     65 
     66     virtual Type type() const = 0;
     67 
     68 protected:
     69     BasicShape()
     70     {
     71     }
     72 
     73 };
     74 
     75 #define DEFINE_BASICSHAPE_TYPE_CASTS(thisType) \
     76     DEFINE_TYPE_CASTS(thisType, BasicShape, value, value->type() == BasicShape::thisType##Type, value.type() == BasicShape::thisType##Type)
     77 
     78 class BasicShapeCenterCoordinate {
     79 public:
     80     enum Direction {
     81         TopLeft,
     82         BottomRight
     83     };
     84     BasicShapeCenterCoordinate()
     85         : m_direction(TopLeft)
     86         , m_length(Undefined)
     87     {
     88         updateComputedLength();
     89     }
     90 
     91     BasicShapeCenterCoordinate(Direction direction, const Length& length)
     92         : m_direction(direction)
     93         , m_length(length)
     94     {
     95         updateComputedLength();
     96     }
     97 
     98     BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate& other)
     99         : m_direction(other.direction())
    100         , m_length(other.length())
    101         , m_computedLength(other.m_computedLength)
    102     {
    103     }
    104 
    105     bool operator==(const BasicShapeCenterCoordinate& other) const { return m_direction == other.m_direction && m_length == other.m_length && m_computedLength == other.m_computedLength; }
    106 
    107     Direction direction() const { return m_direction; }
    108     const Length& length() const { return m_length; }
    109     const Length& computedLength() const { return m_computedLength; }
    110 
    111     BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& other, double progress) const
    112     {
    113         return BasicShapeCenterCoordinate(TopLeft, m_computedLength.blend(other.m_computedLength, progress, ValueRangeAll));
    114     }
    115 
    116 private:
    117     Direction m_direction;
    118     Length m_length;
    119     Length m_computedLength;
    120 
    121     void updateComputedLength();
    122 };
    123 
    124 class BasicShapeRadius {
    125 public:
    126     enum Type {
    127         Value,
    128         ClosestSide,
    129         FarthestSide
    130     };
    131     BasicShapeRadius() : m_value(Undefined), m_type(ClosestSide) { }
    132     explicit BasicShapeRadius(const Length& v) : m_value(v), m_type(Value) { }
    133     explicit BasicShapeRadius(Type t) : m_value(Undefined), m_type(t) { }
    134     BasicShapeRadius(const BasicShapeRadius& other) : m_value(other.value()), m_type(other.type()) { }
    135     bool operator==(const BasicShapeRadius& other) const { return m_type == other.m_type && m_value == other.m_value; }
    136 
    137     const Length& value() const { return m_value; }
    138     Type type() const { return m_type; }
    139 
    140     bool canBlend(const BasicShapeRadius& other) const
    141     {
    142         // FIXME determine how to interpolate between keywords. See issue 330248.
    143         return m_type == Value && other.type() == Value;
    144     }
    145 
    146     BasicShapeRadius blend(const BasicShapeRadius& other, double progress) const
    147     {
    148         if (m_type != Value || other.type() != Value)
    149             return BasicShapeRadius(other);
    150 
    151         return BasicShapeRadius(m_value.blend(other.value(), progress, ValueRangeNonNegative));
    152     }
    153 
    154 private:
    155     Length m_value;
    156     Type m_type;
    157 
    158 };
    159 
    160 class BasicShapeCircle FINAL : public BasicShape {
    161 public:
    162     static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); }
    163 
    164     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
    165     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
    166     const BasicShapeRadius& radius() const { return m_radius; }
    167 
    168     float floatValueForRadiusInBox(FloatSize) const;
    169     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
    170     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
    171     void setRadius(BasicShapeRadius radius) { m_radius = radius; }
    172 
    173     virtual void path(Path&, const FloatRect&) OVERRIDE;
    174     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    175     virtual bool operator==(const BasicShape&) const OVERRIDE;
    176 
    177     virtual Type type() const OVERRIDE { return BasicShapeCircleType; }
    178 private:
    179     BasicShapeCircle() { }
    180 
    181     BasicShapeCenterCoordinate m_centerX;
    182     BasicShapeCenterCoordinate m_centerY;
    183     BasicShapeRadius m_radius;
    184 };
    185 
    186 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeCircle);
    187 
    188 class BasicShapeEllipse FINAL : public BasicShape {
    189 public:
    190     static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); }
    191 
    192     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
    193     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
    194     const BasicShapeRadius& radiusX() const { return m_radiusX; }
    195     const BasicShapeRadius& radiusY() const { return m_radiusY; }
    196     float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const;
    197 
    198     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
    199     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
    200     void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = radiusX; }
    201     void setRadiusY(BasicShapeRadius radiusY) { m_radiusY = radiusY; }
    202 
    203     virtual void path(Path&, const FloatRect&) OVERRIDE;
    204     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    205     virtual bool operator==(const BasicShape&) const OVERRIDE;
    206 
    207     virtual Type type() const OVERRIDE { return BasicShapeEllipseType; }
    208 private:
    209     BasicShapeEllipse() { }
    210 
    211     BasicShapeCenterCoordinate m_centerX;
    212     BasicShapeCenterCoordinate m_centerY;
    213     BasicShapeRadius m_radiusX;
    214     BasicShapeRadius m_radiusY;
    215 };
    216 
    217 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeEllipse);
    218 
    219 class BasicShapePolygon FINAL : public BasicShape {
    220 public:
    221     static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); }
    222 
    223     const Vector<Length>& values() const { return m_values; }
    224     Length getXAt(unsigned i) const { return m_values.at(2 * i); }
    225     Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); }
    226 
    227     void setWindRule(WindRule windRule) { m_windRule = windRule; }
    228     void appendPoint(const Length& x, const Length& y) { m_values.append(x); m_values.append(y); }
    229 
    230     virtual void path(Path&, const FloatRect&) OVERRIDE;
    231     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    232     virtual bool operator==(const BasicShape&) const OVERRIDE;
    233 
    234     virtual WindRule windRule() const OVERRIDE { return m_windRule; }
    235 
    236     virtual Type type() const OVERRIDE { return BasicShapePolygonType; }
    237 private:
    238     BasicShapePolygon()
    239         : m_windRule(RULE_NONZERO)
    240     { }
    241 
    242     WindRule m_windRule;
    243     Vector<Length> m_values;
    244 };
    245 
    246 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapePolygon);
    247 
    248 class BasicShapeInset : public BasicShape {
    249 public:
    250     static PassRefPtr<BasicShapeInset> create() { return adoptRef(new BasicShapeInset); }
    251 
    252     const Length& top() const { return m_top; }
    253     const Length& right() const { return m_right; }
    254     const Length& bottom() const { return m_bottom; }
    255     const Length& left() const { return m_left; }
    256 
    257     const LengthSize& topLeftRadius() const { return m_topLeftRadius; }
    258     const LengthSize& topRightRadius() const { return m_topRightRadius; }
    259     const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; }
    260     const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; }
    261 
    262     void setTop(const Length& top) { m_top = top; }
    263     void setRight(const Length& right) { m_right = right; }
    264     void setBottom(const Length& bottom) { m_bottom = bottom; }
    265     void setLeft(const Length& left) { m_left = left; }
    266 
    267     void setTopLeftRadius(const LengthSize& radius) { m_topLeftRadius = radius; }
    268     void setTopRightRadius(const LengthSize& radius) { m_topRightRadius = radius; }
    269     void setBottomRightRadius(const LengthSize& radius) { m_bottomRightRadius = radius; }
    270     void setBottomLeftRadius(const LengthSize& radius) { m_bottomLeftRadius = radius; }
    271 
    272     virtual void path(Path&, const FloatRect&) OVERRIDE;
    273     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    274     virtual bool operator==(const BasicShape&) const OVERRIDE;
    275 
    276     virtual Type type() const OVERRIDE { return BasicShapeInsetType; }
    277 private:
    278     BasicShapeInset() { }
    279 
    280     Length m_right;
    281     Length m_top;
    282     Length m_bottom;
    283     Length m_left;
    284 
    285     LengthSize m_topLeftRadius;
    286     LengthSize m_topRightRadius;
    287     LengthSize m_bottomRightRadius;
    288     LengthSize m_bottomLeftRadius;
    289 };
    290 
    291 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeInset);
    292 
    293 }
    294 #endif
    295