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/GraphicsTypes.h"
     37 #include "wtf/RefCounted.h"
     38 #include "wtf/RefPtr.h"
     39 #include "wtf/Vector.h"
     40 
     41 namespace blink {
     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 
     85     BasicShapeCenterCoordinate(Direction direction = TopLeft, const Length& length = Length(0, Fixed))
     86         : m_direction(direction)
     87         , m_length(length)
     88         , m_computedLength(direction == TopLeft ? length : length.subtractFromOneHundredPercent())
     89     {
     90     }
     91 
     92     BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate& other)
     93         : m_direction(other.direction())
     94         , m_length(other.length())
     95         , m_computedLength(other.m_computedLength)
     96     {
     97     }
     98 
     99     bool operator==(const BasicShapeCenterCoordinate& other) const { return m_direction == other.m_direction && m_length == other.m_length && m_computedLength == other.m_computedLength; }
    100 
    101     Direction direction() const { return m_direction; }
    102     const Length& length() const { return m_length; }
    103     const Length& computedLength() const { return m_computedLength; }
    104 
    105     BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& other, double progress) const
    106     {
    107         return BasicShapeCenterCoordinate(TopLeft, m_computedLength.blend(other.m_computedLength, progress, ValueRangeAll));
    108     }
    109 
    110 private:
    111     Direction m_direction;
    112     Length m_length;
    113     Length m_computedLength;
    114 };
    115 
    116 class BasicShapeRadius {
    117 public:
    118     enum Type {
    119         Value,
    120         ClosestSide,
    121         FarthestSide
    122     };
    123     BasicShapeRadius() : m_type(ClosestSide) { }
    124     explicit BasicShapeRadius(const Length& v) : m_value(v), m_type(Value) { }
    125     explicit BasicShapeRadius(Type t) : m_type(t) { }
    126     BasicShapeRadius(const BasicShapeRadius& other) : m_value(other.value()), m_type(other.type()) { }
    127     bool operator==(const BasicShapeRadius& other) const { return m_type == other.m_type && m_value == other.m_value; }
    128 
    129     const Length& value() const { return m_value; }
    130     Type type() const { return m_type; }
    131 
    132     bool canBlend(const BasicShapeRadius& other) const
    133     {
    134         // FIXME determine how to interpolate between keywords. See issue 330248.
    135         return m_type == Value && other.type() == Value;
    136     }
    137 
    138     BasicShapeRadius blend(const BasicShapeRadius& other, double progress) const
    139     {
    140         if (m_type != Value || other.type() != Value)
    141             return BasicShapeRadius(other);
    142 
    143         return BasicShapeRadius(m_value.blend(other.value(), progress, ValueRangeNonNegative));
    144     }
    145 
    146 private:
    147     Length m_value;
    148     Type m_type;
    149 
    150 };
    151 
    152 class BasicShapeCircle FINAL : public BasicShape {
    153 public:
    154     static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); }
    155 
    156     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
    157     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
    158     const BasicShapeRadius& radius() const { return m_radius; }
    159 
    160     float floatValueForRadiusInBox(FloatSize) const;
    161     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
    162     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
    163     void setRadius(BasicShapeRadius radius) { m_radius = radius; }
    164 
    165     virtual void path(Path&, const FloatRect&) OVERRIDE;
    166     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    167     virtual bool operator==(const BasicShape&) const OVERRIDE;
    168 
    169     virtual Type type() const OVERRIDE { return BasicShapeCircleType; }
    170 private:
    171     BasicShapeCircle() { }
    172 
    173     BasicShapeCenterCoordinate m_centerX;
    174     BasicShapeCenterCoordinate m_centerY;
    175     BasicShapeRadius m_radius;
    176 };
    177 
    178 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeCircle);
    179 
    180 class BasicShapeEllipse FINAL : public BasicShape {
    181 public:
    182     static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); }
    183 
    184     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
    185     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
    186     const BasicShapeRadius& radiusX() const { return m_radiusX; }
    187     const BasicShapeRadius& radiusY() const { return m_radiusY; }
    188     float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const;
    189 
    190     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
    191     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
    192     void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = radiusX; }
    193     void setRadiusY(BasicShapeRadius radiusY) { m_radiusY = radiusY; }
    194 
    195     virtual void path(Path&, const FloatRect&) OVERRIDE;
    196     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    197     virtual bool operator==(const BasicShape&) const OVERRIDE;
    198 
    199     virtual Type type() const OVERRIDE { return BasicShapeEllipseType; }
    200 private:
    201     BasicShapeEllipse() { }
    202 
    203     BasicShapeCenterCoordinate m_centerX;
    204     BasicShapeCenterCoordinate m_centerY;
    205     BasicShapeRadius m_radiusX;
    206     BasicShapeRadius m_radiusY;
    207 };
    208 
    209 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeEllipse);
    210 
    211 class BasicShapePolygon FINAL : public BasicShape {
    212 public:
    213     static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); }
    214 
    215     const Vector<Length>& values() const { return m_values; }
    216     Length getXAt(unsigned i) const { return m_values.at(2 * i); }
    217     Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); }
    218 
    219     void setWindRule(WindRule windRule) { m_windRule = windRule; }
    220     void appendPoint(const Length& x, const Length& y) { m_values.append(x); m_values.append(y); }
    221 
    222     virtual void path(Path&, const FloatRect&) OVERRIDE;
    223     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    224     virtual bool operator==(const BasicShape&) const OVERRIDE;
    225 
    226     virtual WindRule windRule() const OVERRIDE { return m_windRule; }
    227 
    228     virtual Type type() const OVERRIDE { return BasicShapePolygonType; }
    229 private:
    230     BasicShapePolygon()
    231         : m_windRule(RULE_NONZERO)
    232     { }
    233 
    234     WindRule m_windRule;
    235     Vector<Length> m_values;
    236 };
    237 
    238 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapePolygon);
    239 
    240 class BasicShapeInset : public BasicShape {
    241 public:
    242     static PassRefPtr<BasicShapeInset> create() { return adoptRef(new BasicShapeInset); }
    243 
    244     const Length& top() const { return m_top; }
    245     const Length& right() const { return m_right; }
    246     const Length& bottom() const { return m_bottom; }
    247     const Length& left() const { return m_left; }
    248 
    249     const LengthSize& topLeftRadius() const { return m_topLeftRadius; }
    250     const LengthSize& topRightRadius() const { return m_topRightRadius; }
    251     const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; }
    252     const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; }
    253 
    254     void setTop(const Length& top) { m_top = top; }
    255     void setRight(const Length& right) { m_right = right; }
    256     void setBottom(const Length& bottom) { m_bottom = bottom; }
    257     void setLeft(const Length& left) { m_left = left; }
    258 
    259     void setTopLeftRadius(const LengthSize& radius) { m_topLeftRadius = radius; }
    260     void setTopRightRadius(const LengthSize& radius) { m_topRightRadius = radius; }
    261     void setBottomRightRadius(const LengthSize& radius) { m_bottomRightRadius = radius; }
    262     void setBottomLeftRadius(const LengthSize& radius) { m_bottomLeftRadius = radius; }
    263 
    264     virtual void path(Path&, const FloatRect&) OVERRIDE;
    265     virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
    266     virtual bool operator==(const BasicShape&) const OVERRIDE;
    267 
    268     virtual Type type() const OVERRIDE { return BasicShapeInsetType; }
    269 private:
    270     BasicShapeInset() { }
    271 
    272     Length m_right;
    273     Length m_top;
    274     Length m_bottom;
    275     Length m_left;
    276 
    277     LengthSize m_topLeftRadius;
    278     LengthSize m_topRightRadius;
    279     LengthSize m_bottomRightRadius;
    280     LengthSize m_bottomLeftRadius;
    281 };
    282 
    283 DEFINE_BASICSHAPE_TYPE_CASTS(BasicShapeInset);
    284 
    285 }
    286 #endif
    287