Implement CSS `display: flow-root` (modern clearfix)
[WebKit-https.git] / Source / WebCore / rendering / style / BasicShapes.h
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 #pragma once
31
32 #include "Length.h"
33 #include "LengthSize.h"
34 #include "WindRule.h"
35 #include <wtf/RefCounted.h>
36 #include <wtf/RefPtr.h>
37 #include <wtf/TypeCasts.h>
38 #include <wtf/Vector.h>
39
40 namespace WebCore {
41
42 class FloatRect;
43 class Path;
44 class RenderBox;
45 class SVGPathByteStream;
46
47 class BasicShape : public RefCounted<BasicShape> {
48 public:
49     virtual ~BasicShape() = default;
50
51     enum Type {
52         BasicShapePolygonType,
53         BasicShapePathType,
54         BasicShapeCircleType,
55         BasicShapeEllipseType,
56         BasicShapeInsetType
57     };
58
59     virtual Type type() const = 0;
60
61     virtual const Path& path(const FloatRect&) = 0;
62     virtual WindRule windRule() const { return WindRule::NonZero; }
63
64     virtual bool canBlend(const BasicShape&) const = 0;
65     virtual Ref<BasicShape> blend(const BasicShape& from, double) const = 0;
66
67     virtual bool operator==(const BasicShape&) const = 0;
68 };
69
70 class BasicShapeCenterCoordinate {
71 public:
72     enum Direction {
73         TopLeft,
74         BottomRight
75     };
76
77     BasicShapeCenterCoordinate()
78         : m_direction(TopLeft)
79         , m_length(Undefined)
80     {
81         updateComputedLength();
82     }
83
84     BasicShapeCenterCoordinate(Direction direction, Length length)
85         : m_direction(direction)
86         , m_length(length)
87     {
88         updateComputedLength();
89     }
90
91     Direction direction() const { return m_direction; }
92     const Length& length() const { return m_length; }
93     const Length& computedLength() const { return m_computedLength; }
94
95     BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& from, double progress) const
96     {
97         return BasicShapeCenterCoordinate(TopLeft, WebCore::blend(from.m_computedLength, m_computedLength, progress));
98     }
99     
100     bool operator==(const BasicShapeCenterCoordinate& other) const
101     {
102         return m_direction == other.m_direction
103             && m_length == other.m_length
104             && m_computedLength == other.m_computedLength;
105     }
106
107 private:
108     void updateComputedLength();
109
110     Direction m_direction;
111     Length m_length;
112     Length m_computedLength;
113 };
114
115 class BasicShapeRadius {
116 public:
117     enum Type {
118         Value,
119         ClosestSide,
120         FarthestSide
121     };
122     BasicShapeRadius()
123         : m_value(Undefined),
124         m_type(ClosestSide)
125     { }
126
127     explicit BasicShapeRadius(Length v)
128         : m_value(v)
129         , m_type(Value)
130     { }
131     explicit BasicShapeRadius(Type t)
132         : m_value(Undefined)
133         , m_type(t)
134     { }
135
136     const Length& value() const { return m_value; }
137     Type type() const { return m_type; }
138
139     bool canBlend(const BasicShapeRadius& other) const
140     {
141         // FIXME determine how to interpolate between keywords. See bug 125108.
142         return m_type == Value && other.type() == Value;
143     }
144
145     BasicShapeRadius blend(const BasicShapeRadius& from, double progress) const
146     {
147         if (m_type != Value || from.type() != Value)
148             return BasicShapeRadius(from);
149
150         return BasicShapeRadius(WebCore::blend(from.value(), value(), progress));
151     }
152     
153     bool operator==(const BasicShapeRadius& other) const
154     {
155         return m_value == other.m_value && m_type == other.m_type;
156     }
157
158 private:
159     Length m_value;
160     Type m_type;
161
162 };
163
164 class BasicShapeCircle final : public BasicShape {
165 public:
166     static Ref<BasicShapeCircle> create() { return adoptRef(*new BasicShapeCircle); }
167
168     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
169     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
170     const BasicShapeRadius& radius() const { return m_radius; }
171     float floatValueForRadiusInBox(float boxWidth, float boxHeight) const;
172
173     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = WTFMove(centerX); }
174     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = WTFMove(centerY); }
175     void setRadius(BasicShapeRadius radius) { m_radius = WTFMove(radius); }
176
177 private:
178     BasicShapeCircle() = default;
179
180     Type type() const override { return BasicShapeCircleType; }
181
182     const Path& path(const FloatRect&) override;
183
184     bool canBlend(const BasicShape&) const override;
185     Ref<BasicShape> blend(const BasicShape& from, double) const override;
186
187     bool operator==(const BasicShape&) const override;
188
189     BasicShapeCenterCoordinate m_centerX;
190     BasicShapeCenterCoordinate m_centerY;
191     BasicShapeRadius m_radius;
192 };
193
194 class BasicShapeEllipse final : public BasicShape {
195 public:
196     static Ref<BasicShapeEllipse> create() { return adoptRef(*new BasicShapeEllipse); }
197
198     const BasicShapeCenterCoordinate& centerX() const { return m_centerX; }
199     const BasicShapeCenterCoordinate& centerY() const { return m_centerY; }
200     const BasicShapeRadius& radiusX() const { return m_radiusX; }
201     const BasicShapeRadius& radiusY() const { return m_radiusY; }
202     float floatValueForRadiusInBox(const BasicShapeRadius&, float center, float boxWidthOrHeight) const;
203
204     void setCenterX(BasicShapeCenterCoordinate centerX) { m_centerX = WTFMove(centerX); }
205     void setCenterY(BasicShapeCenterCoordinate centerY) { m_centerY = WTFMove(centerY); }
206     void setRadiusX(BasicShapeRadius radiusX) { m_radiusX = WTFMove(radiusX); }
207     void setRadiusY(BasicShapeRadius radiusY) { m_radiusY = WTFMove(radiusY); }
208
209 private:
210     BasicShapeEllipse() = default;
211
212     Type type() const override { return BasicShapeEllipseType; }
213
214     const Path& path(const FloatRect&) override;
215
216     bool canBlend(const BasicShape&) const override;
217     Ref<BasicShape> blend(const BasicShape& from, double) const override;
218
219     bool operator==(const BasicShape&) const override;
220
221     BasicShapeCenterCoordinate m_centerX;
222     BasicShapeCenterCoordinate m_centerY;
223     BasicShapeRadius m_radiusX;
224     BasicShapeRadius m_radiusY;
225 };
226
227 class BasicShapePolygon final : public BasicShape {
228 public:
229     static Ref<BasicShapePolygon> create() { return adoptRef(*new BasicShapePolygon); }
230
231     const Vector<Length>& values() const { return m_values; }
232     const Length& getXAt(unsigned i) const { return m_values[2 * i]; }
233     const Length& getYAt(unsigned i) const { return m_values[2 * i + 1]; }
234
235     void setWindRule(WindRule windRule) { m_windRule = windRule; }
236     void appendPoint(Length x, Length y) { m_values.append(WTFMove(x)); m_values.append(WTFMove(y)); }
237
238     WindRule windRule() const override { return m_windRule; }
239
240 private:
241     BasicShapePolygon() = default;
242
243     Type type() const override { return BasicShapePolygonType; }
244
245     const Path& path(const FloatRect&) override;
246
247     bool canBlend(const BasicShape&) const override;
248     Ref<BasicShape> blend(const BasicShape& from, double) const override;
249
250     bool operator==(const BasicShape&) const override;
251
252     WindRule m_windRule { WindRule::NonZero };
253     Vector<Length> m_values;
254 };
255
256 class BasicShapePath final : public BasicShape {
257 public:
258     static Ref<BasicShapePath> create(std::unique_ptr<SVGPathByteStream>&& byteStream)
259     {
260         return adoptRef(*new BasicShapePath(WTFMove(byteStream)));
261     }
262
263     void setWindRule(WindRule windRule) { m_windRule = windRule; }
264     WindRule windRule() const override { return m_windRule; }
265
266     const SVGPathByteStream* pathData() const { return m_byteStream.get(); }
267
268 private:
269     BasicShapePath(std::unique_ptr<SVGPathByteStream>&&);
270
271     Type type() const override { return BasicShapePathType; }
272
273     const Path& path(const FloatRect&) override;
274
275     bool canBlend(const BasicShape&) const override;
276     Ref<BasicShape> blend(const BasicShape& from, double) const override;
277
278     bool operator==(const BasicShape&) const override;
279
280     std::unique_ptr<SVGPathByteStream> m_byteStream;
281     WindRule m_windRule { WindRule::NonZero };
282 };
283
284 class BasicShapeInset final : public BasicShape {
285 public:
286     static Ref<BasicShapeInset> create() { return adoptRef(*new BasicShapeInset); }
287
288     const Length& top() const { return m_top; }
289     const Length& right() const { return m_right; }
290     const Length& bottom() const { return m_bottom; }
291     const Length& left() const { return m_left; }
292
293     const LengthSize& topLeftRadius() const { return m_topLeftRadius; }
294     const LengthSize& topRightRadius() const { return m_topRightRadius; }
295     const LengthSize& bottomRightRadius() const { return m_bottomRightRadius; }
296     const LengthSize& bottomLeftRadius() const { return m_bottomLeftRadius; }
297
298     void setTop(Length top) { m_top = WTFMove(top); }
299     void setRight(Length right) { m_right = WTFMove(right); }
300     void setBottom(Length bottom) { m_bottom = WTFMove(bottom); }
301     void setLeft(Length left) { m_left = WTFMove(left); }
302
303     void setTopLeftRadius(LengthSize radius) { m_topLeftRadius = WTFMove(radius); }
304     void setTopRightRadius(LengthSize radius) { m_topRightRadius = WTFMove(radius); }
305     void setBottomRightRadius(LengthSize radius) { m_bottomRightRadius = WTFMove(radius); }
306     void setBottomLeftRadius(LengthSize radius) { m_bottomLeftRadius = WTFMove(radius); }
307
308 private:
309     BasicShapeInset() = default;
310
311     Type type() const override { return BasicShapeInsetType; }
312
313     const Path& path(const FloatRect&) override;
314
315     bool canBlend(const BasicShape&) const override;
316     Ref<BasicShape> blend(const BasicShape& from, double) const override;
317
318     bool operator==(const BasicShape&) const override;
319
320     Length m_right;
321     Length m_top;
322     Length m_bottom;
323     Length m_left;
324
325     LengthSize m_topLeftRadius;
326     LengthSize m_topRightRadius;
327     LengthSize m_bottomRightRadius;
328     LengthSize m_bottomLeftRadius;
329 };
330
331 } // namespace WebCore
332
333 #define SPECIALIZE_TYPE_TRAITS_BASIC_SHAPE(ToValueTypeName, predicate) \
334 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
335     static bool isType(const WebCore::BasicShape& basicShape) { return basicShape.type() == WebCore::predicate; } \
336 SPECIALIZE_TYPE_TRAITS_END()
337
338 SPECIALIZE_TYPE_TRAITS_BASIC_SHAPE(BasicShapeCircle, BasicShape::BasicShapeCircleType)
339 SPECIALIZE_TYPE_TRAITS_BASIC_SHAPE(BasicShapeEllipse, BasicShape::BasicShapeEllipseType)
340 SPECIALIZE_TYPE_TRAITS_BASIC_SHAPE(BasicShapePolygon, BasicShape::BasicShapePolygonType)
341 SPECIALIZE_TYPE_TRAITS_BASIC_SHAPE(BasicShapePath, BasicShape::BasicShapePathType)
342 SPECIALIZE_TYPE_TRAITS_BASIC_SHAPE(BasicShapeInset, BasicShape::BasicShapeInsetType)