1/*
2 * Copyright (C) 2003, 2006, 2009, 2016 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Rob Buis <buis@kde.org>
4 * Copyright (C) 2007-2008 Torch Mobile, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef Path_h
29#define Path_h
30
31#include "FloatRect.h"
32#include "WindRule.h"
33#include <wtf/FastMalloc.h>
34#include <wtf/Function.h>
35#include <wtf/Forward.h>
36
37#if USE(CG)
38
39#include <wtf/RetainPtr.h>
40#include <CoreGraphics/CGPath.h>
41typedef struct CGPath PlatformPath;
42
43#elif USE(DIRECT2D)
44#include "COMPtr.h"
45
46interface ID2D1Geometry;
47interface ID2D1GeometryGroup;
48interface ID2D1PathGeometry;
49interface ID2D1GeometrySink;
50
51typedef ID2D1GeometryGroup PlatformPath;
52
53#elif USE(CAIRO)
54
55namespace WebCore {
56class CairoPath;
57}
58typedef WebCore::CairoPath PlatformPath;
59
60#elif USE(WINGDI)
61
62namespace WebCore {
63class PlatformPath;
64}
65typedef WebCore::PlatformPath PlatformPath;
66
67#else
68
69typedef void PlatformPath;
70
71#endif
72
73typedef PlatformPath* PlatformPathPtr;
74
75namespace WTF {
76class TextStream;
77}
78
79namespace WebCore {
80
81 class AffineTransform;
82 class FloatPoint;
83 class FloatRoundedRect;
84 class FloatSize;
85 class GraphicsContext;
86 class PathTraversalState;
87 class RoundedRect;
88 class StrokeStyleApplier;
89
90 enum PathElementType {
91 PathElementMoveToPoint, // The points member will contain 1 value.
92 PathElementAddLineToPoint, // The points member will contain 1 value.
93 PathElementAddQuadCurveToPoint, // The points member will contain 2 values.
94 PathElementAddCurveToPoint, // The points member will contain 3 values.
95 PathElementCloseSubpath // The points member will contain no values.
96 };
97
98 // The points in the structure are the same as those that would be used with the
99 // add... method. For example, a line returns the endpoint, while a cubic returns
100 // two tangent points and the endpoint.
101 struct PathElement {
102 PathElementType type;
103 FloatPoint* points;
104 };
105
106 using PathApplierFunction = WTF::Function<void (const PathElement&)>;
107
108 class Path {
109 WTF_MAKE_FAST_ALLOCATED;
110 public:
111 WEBCORE_EXPORT Path();
112#if USE(CG)
113 Path(RetainPtr<CGMutablePathRef>);
114#endif
115 WEBCORE_EXPORT ~Path();
116
117 WEBCORE_EXPORT Path(const Path&);
118 WEBCORE_EXPORT Path(Path&&);
119 WEBCORE_EXPORT Path& operator=(const Path&);
120 WEBCORE_EXPORT Path& operator=(Path&&);
121
122 static Path polygonPathFromPoints(const Vector<FloatPoint>&);
123
124 bool contains(const FloatPoint&, WindRule = WindRule::NonZero) const;
125 bool strokeContains(StrokeStyleApplier*, const FloatPoint&) const;
126 // fastBoundingRect() should equal or contain boundingRect(); boundingRect()
127 // should perfectly bound the points within the path.
128 FloatRect boundingRect() const;
129 WEBCORE_EXPORT FloatRect fastBoundingRect() const;
130 FloatRect strokeBoundingRect(StrokeStyleApplier* = 0) const;
131
132 float length() const;
133 PathTraversalState traversalStateAtLength(float length, bool& success) const;
134 FloatPoint pointAtLength(float length, bool& success) const;
135 float normalAngleAtLength(float length, bool& success) const;
136
137 WEBCORE_EXPORT void clear();
138 bool isNull() const { return !m_path; }
139 bool isEmpty() const;
140 // Gets the current point of the current path, which is conceptually the final point reached by the path so far.
141 // Note the Path can be empty (isEmpty() == true) and still have a current point.
142 bool hasCurrentPoint() const;
143 FloatPoint currentPoint() const;
144
145 WEBCORE_EXPORT void moveTo(const FloatPoint&);
146 WEBCORE_EXPORT void addLineTo(const FloatPoint&);
147 WEBCORE_EXPORT void addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint);
148 WEBCORE_EXPORT void addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint);
149 void addArcTo(const FloatPoint&, const FloatPoint&, float radius);
150 WEBCORE_EXPORT void closeSubpath();
151
152 void addArc(const FloatPoint&, float radius, float startAngle, float endAngle, bool anticlockwise);
153 void addRect(const FloatRect&);
154 void addEllipse(FloatPoint, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise);
155 void addEllipse(const FloatRect&);
156
157 enum RoundedRectStrategy {
158 PreferNativeRoundedRect,
159 PreferBezierRoundedRect
160 };
161
162 WEBCORE_EXPORT void addRoundedRect(const FloatRect&, const FloatSize& roundingRadii, RoundedRectStrategy = PreferNativeRoundedRect);
163 WEBCORE_EXPORT void addRoundedRect(const FloatRoundedRect&, RoundedRectStrategy = PreferNativeRoundedRect);
164 void addRoundedRect(const RoundedRect&);
165
166 void addPath(const Path&, const AffineTransform&);
167
168 void translate(const FloatSize&);
169
170 // To keep Path() cheap, it does not allocate a PlatformPath immediately
171 // meaning Path::platformPath() can return null.
172#if USE(DIRECT2D)
173 PlatformPathPtr platformPath() const { return m_path.get(); }
174#else
175 PlatformPathPtr platformPath() const { return m_path; }
176#endif
177 // ensurePlatformPath() will allocate a PlatformPath if it has not yet been and will never return null.
178 WEBCORE_EXPORT PlatformPathPtr ensurePlatformPath();
179
180 WEBCORE_EXPORT void apply(const PathApplierFunction&) const;
181 void transform(const AffineTransform&);
182
183 static float circleControlPoint()
184 {
185 // Approximation of control point positions on a bezier to simulate a quarter of a circle.
186 // This is 1-kappa, where kappa = 4 * (sqrt(2) - 1) / 3
187 return 0.447715;
188 }
189
190 void addBeziersForRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
191
192#if USE(CG) || USE(DIRECT2D)
193 void platformAddPathForRoundedRect(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius);
194#endif
195
196#if USE(DIRECT2D)
197 ID2D1GeometrySink* activePath() const { return m_activePath.get(); }
198 void appendGeometry(ID2D1Geometry*);
199 void createGeometryWithFillMode(WindRule, COMPtr<ID2D1GeometryGroup>&) const;
200 void drawDidComplete();
201
202 HRESULT initializePathState();
203 void openFigureAtCurrentPointIfNecessary();
204 void closeAnyOpenGeometries();
205#endif
206
207#ifndef NDEBUG
208 void dump() const;
209#endif
210
211 private:
212#if USE(DIRECT2D)
213 COMPtr<ID2D1GeometryGroup> m_path;
214 COMPtr<ID2D1PathGeometry> m_activePathGeometry;
215 COMPtr<ID2D1GeometrySink> m_activePath;
216 size_t m_openFigureCount { 0 };
217#else
218 PlatformPathPtr m_path { nullptr };
219#endif
220 };
221
222WTF::TextStream& operator<<(WTF::TextStream&, const Path&);
223
224}
225
226#endif
227