• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
~BasicShape()49     virtual ~BasicShape() { }
50 
51     enum Type {
52         BasicShapeEllipseType,
53         BasicShapePolygonType,
54         BasicShapeCircleType,
55         BasicShapeInsetType
56     };
57 
58     bool canBlend(const BasicShape*) const;
isSameType(const BasicShape & other)59     bool isSameType(const BasicShape& other) const { return type() == other.type(); }
60 
61     virtual void path(Path&, const FloatRect&) = 0;
windRule()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:
BasicShape()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     };
BasicShapeCenterCoordinate()84     BasicShapeCenterCoordinate()
85         : m_direction(TopLeft)
86         , m_length(Undefined)
87     {
88         updateComputedLength();
89     }
90 
BasicShapeCenterCoordinate(Direction direction,const Length & length)91     BasicShapeCenterCoordinate(Direction direction, const Length& length)
92         : m_direction(direction)
93         , m_length(length)
94     {
95         updateComputedLength();
96     }
97 
BasicShapeCenterCoordinate(const BasicShapeCenterCoordinate & other)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 
direction()107     Direction direction() const { return m_direction; }
length()108     const Length& length() const { return m_length; }
computedLength()109     const Length& computedLength() const { return m_computedLength; }
110 
blend(const BasicShapeCenterCoordinate & other,double progress)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     };
BasicShapeRadius()131     BasicShapeRadius() : m_value(Undefined), m_type(ClosestSide) { }
BasicShapeRadius(const Length & v)132     explicit BasicShapeRadius(const Length& v) : m_value(v), m_type(Value) { }
BasicShapeRadius(Type t)133     explicit BasicShapeRadius(Type t) : m_value(Undefined), m_type(t) { }
BasicShapeRadius(const BasicShapeRadius & other)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 
value()137     const Length& value() const { return m_value; }
type()138     Type type() const { return m_type; }
139 
canBlend(const BasicShapeRadius & other)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 
blend(const BasicShapeRadius & other,double progress)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:
create()162     static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); }
163 
centerX()164     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
centerY()165     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
radius()166     const BasicShapeRadius& radius() const { return m_radius; }
167 
168     float floatValueForRadiusInBox(FloatSize) const;
setCenterX(BasicShapeCenterCoordinate centerX)169     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
setCenterY(BasicShapeCenterCoordinate centerY)170     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
setRadius(BasicShapeRadius radius)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 
type()177     virtual Type type() const OVERRIDE { return BasicShapeCircleType; }
178 private:
BasicShapeCircle()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:
create()190     static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); }
191 
centerX()192     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
centerY()193     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
radiusX()194     const BasicShapeRadius& radiusX() const { return m_radiusX; }
radiusY()195     const BasicShapeRadius& radiusY() const { return m_radiusY; }
196     float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const;
197 
setCenterX(BasicShapeCenterCoordinate centerX)198     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = centerX; }
setCenterY(BasicShapeCenterCoordinate centerY)199     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = centerY; }
setRadiusX(BasicShapeRadius radiusX)200     void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = radiusX; }
setRadiusY(BasicShapeRadius radiusY)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 
type()207     virtual Type type() const OVERRIDE { return BasicShapeEllipseType; }
208 private:
BasicShapeEllipse()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:
create()221     static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); }
222 
values()223     const Vector<Length>& values() const { return m_values; }
getXAt(unsigned i)224     Length getXAt(unsigned i) const { return m_values.at(2 * i); }
getYAt(unsigned i)225     Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); }
226 
setWindRule(WindRule windRule)227     void setWindRule(WindRule windRule) { m_windRule = windRule; }
appendPoint(const Length & x,const Length & y)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 
windRule()234     virtual WindRule windRule() const OVERRIDE { return m_windRule; }
235 
type()236     virtual Type type() const OVERRIDE { return BasicShapePolygonType; }
237 private:
BasicShapePolygon()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:
create()250     static PassRefPtr<BasicShapeInset> create() { return adoptRef(new BasicShapeInset); }
251 
top()252     const Length& top() const { return m_top; }
right()253     const Length& right() const { return m_right; }
bottom()254     const Length& bottom() const { return m_bottom; }
left()255     const Length& left() const { return m_left; }
256 
topLeftRadius()257     const LengthSize& topLeftRadius() const { return m_topLeftRadius; }
topRightRadius()258     const LengthSize& topRightRadius() const { return m_topRightRadius; }
bottomRightRadius()259     const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; }
bottomLeftRadius()260     const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; }
261 
setTop(const Length & top)262     void setTop(const Length& top) { m_top = top; }
setRight(const Length & right)263     void setRight(const Length& right) { m_right = right; }
setBottom(const Length & bottom)264     void setBottom(const Length& bottom) { m_bottom = bottom; }
setLeft(const Length & left)265     void setLeft(const Length& left) { m_left = left; }
266 
setTopLeftRadius(const LengthSize & radius)267     void setTopLeftRadius(const LengthSize& radius) { m_topLeftRadius = radius; }
setTopRightRadius(const LengthSize & radius)268     void setTopRightRadius(const LengthSize& radius) { m_topRightRadius = radius; }
setBottomRightRadius(const LengthSize & radius)269     void setBottomRightRadius(const LengthSize& radius) { m_bottomRightRadius = radius; }
setBottomLeftRadius(const LengthSize & 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 
type()276     virtual Type type() const OVERRIDE { return BasicShapeInsetType; }
277 private:
BasicShapeInset()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