JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_PathIterator.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29#if JUCE_MSVC && JUCE_DEBUG
30 #pragma optimize ("t", on)
31#endif
32
33//==============================================================================
35 const AffineTransform& t,
36 float tolerance)
37 : x2 (0),
38 y2 (0),
39 closesSubPath (false),
40 subPathIndex (-1),
41 path (pathToUse),
42 transform (t),
43 source (path.data.begin()),
44 toleranceSquared (tolerance * tolerance),
45 isIdentityTransform (t.isIdentity())
46{
47 stackPos = stackBase;
48}
49
53
55{
56 return stackPos == stackBase.get()
57 && (source == path.data.end() || isMarker (*source, Path::moveMarker));
58}
59
61{
62 x1 = x2;
63 y1 = y2;
64
65 float x3 = 0;
66 float y3 = 0;
67 float x4 = 0;
68 float y4 = 0;
69
70 for (;;)
71 {
72 float type;
73
74 if (stackPos == stackBase.get())
75 {
76 if (source == path.data.end())
77 return false;
78
79 type = *source++;
80
81 if (! isMarker (type, Path::closeSubPathMarker))
82 {
83 x2 = *source++;
84 y2 = *source++;
85
86 if (isMarker (type, Path::quadMarker))
87 {
88 x3 = *source++;
89 y3 = *source++;
90
91 if (! isIdentityTransform)
92 transform.transformPoints (x2, y2, x3, y3);
93 }
94 else if (isMarker (type, Path::cubicMarker))
95 {
96 x3 = *source++;
97 y3 = *source++;
98 x4 = *source++;
99 y4 = *source++;
100
101 if (! isIdentityTransform)
102 transform.transformPoints (x2, y2, x3, y3, x4, y4);
103 }
104 else
105 {
106 if (! isIdentityTransform)
107 transform.transformPoint (x2, y2);
108 }
109 }
110 }
111 else
112 {
113 type = *--stackPos;
114
115 if (! isMarker (type, Path::closeSubPathMarker))
116 {
117 x2 = *--stackPos;
118 y2 = *--stackPos;
119
120 if (isMarker (type, Path::quadMarker))
121 {
122 x3 = *--stackPos;
123 y3 = *--stackPos;
124 }
125 else if (isMarker (type, Path::cubicMarker))
126 {
127 x3 = *--stackPos;
128 y3 = *--stackPos;
129 x4 = *--stackPos;
130 y4 = *--stackPos;
131 }
132 }
133 }
134
135 if (isMarker (type, Path::lineMarker))
136 {
137 ++subPathIndex;
138
139 closesSubPath = stackPos == stackBase.get()
140 && source != path.data.end()
141 && isMarker (*source, Path::closeSubPathMarker)
142 && approximatelyEqual (x2, subPathCloseX)
143 && approximatelyEqual (y2, subPathCloseY);
144
145 return true;
146 }
147
148 if (isMarker (type, Path::quadMarker))
149 {
150 const size_t offset = (size_t) (stackPos - stackBase);
151
152 if (offset >= stackSize - 10)
153 {
154 stackSize <<= 1;
155 stackBase.realloc (stackSize);
156 stackPos = stackBase + offset;
157 }
158
159 auto m1x = (x1 + x2) * 0.5f;
160 auto m1y = (y1 + y2) * 0.5f;
161 auto m2x = (x2 + x3) * 0.5f;
162 auto m2y = (y2 + y3) * 0.5f;
163 auto m3x = (m1x + m2x) * 0.5f;
164 auto m3y = (m1y + m2y) * 0.5f;
165
166 auto errorX = m3x - x2;
167 auto errorY = m3y - y2;
168
169 auto outsideTolerance = errorX * errorX + errorY * errorY > toleranceSquared;
172
174 {
175 *stackPos++ = y3;
176 *stackPos++ = x3;
177 *stackPos++ = m2y;
178 *stackPos++ = m2x;
179 *stackPos++ = Path::quadMarker;
180
181 *stackPos++ = m3y;
182 *stackPos++ = m3x;
183 *stackPos++ = m1y;
184 *stackPos++ = m1x;
185 *stackPos++ = Path::quadMarker;
186 }
187 else
188 {
189 *stackPos++ = y3;
190 *stackPos++ = x3;
191 *stackPos++ = Path::lineMarker;
192
193 *stackPos++ = m3y;
194 *stackPos++ = m3x;
195 *stackPos++ = Path::lineMarker;
196 }
197
198 jassert (stackPos < stackBase + stackSize);
199 }
200 else if (isMarker (type, Path::cubicMarker))
201 {
202 const size_t offset = (size_t) (stackPos - stackBase);
203
204 if (offset >= stackSize - 16)
205 {
206 stackSize <<= 1;
207 stackBase.realloc (stackSize);
208 stackPos = stackBase + offset;
209 }
210
211 auto m1x = (x1 + x2) * 0.5f;
212 auto m1y = (y1 + y2) * 0.5f;
213 auto m2x = (x3 + x2) * 0.5f;
214 auto m2y = (y3 + y2) * 0.5f;
215 auto m3x = (x3 + x4) * 0.5f;
216 auto m3y = (y3 + y4) * 0.5f;
217 auto m4x = (m1x + m2x) * 0.5f;
218 auto m4y = (m1y + m2y) * 0.5f;
219 auto m5x = (m3x + m2x) * 0.5f;
220 auto m5y = (m3y + m2y) * 0.5f;
221
222 auto error1X = m4x - x2;
223 auto error1Y = m4y - y2;
224 auto error2X = m5x - x3;
225 auto error2Y = m5y - y3;
226
227 auto outsideTolerance = error1X * error1X + error1Y * error1Y > toleranceSquared
228 || error2X * error2X + error2Y * error2Y > toleranceSquared;
233
235 {
236 *stackPos++ = y4;
237 *stackPos++ = x4;
238 *stackPos++ = m3y;
239 *stackPos++ = m3x;
240 *stackPos++ = m5y;
241 *stackPos++ = m5x;
242 *stackPos++ = Path::cubicMarker;
243
244 *stackPos++ = (m4y + m5y) * 0.5f;
245 *stackPos++ = (m4x + m5x) * 0.5f;
246 *stackPos++ = m4y;
247 *stackPos++ = m4x;
248 *stackPos++ = m1y;
249 *stackPos++ = m1x;
250 *stackPos++ = Path::cubicMarker;
251 }
252 else
253 {
254 *stackPos++ = y4;
255 *stackPos++ = x4;
256 *stackPos++ = Path::lineMarker;
257
258 *stackPos++ = m5y;
259 *stackPos++ = m5x;
260 *stackPos++ = Path::lineMarker;
261
262 *stackPos++ = m4y;
263 *stackPos++ = m4x;
264 *stackPos++ = Path::lineMarker;
265 }
266 }
267 else if (isMarker (type, Path::closeSubPathMarker))
268 {
269 if (! approximatelyEqual (x2, subPathCloseX) || ! approximatelyEqual (y2, subPathCloseY))
270 {
271 x1 = x2;
272 y1 = y2;
273 x2 = subPathCloseX;
274 y2 = subPathCloseY;
275 closesSubPath = true;
276
277 return true;
278 }
279 }
280 else
281 {
282 jassert (isMarker (type, Path::moveMarker));
283
284 subPathIndex = -1;
285 subPathCloseX = x1 = x2;
286 subPathCloseY = y1 = y2;
287 }
288 }
289}
290
291#if JUCE_MSVC && JUCE_DEBUG
292 #pragma optimize ("", on) // resets optimisations to the project defaults
293#endif
294
295} // namespace juce
Represents a 2D affine-transformation matrix.
void transformPoint(ValueType &x, ValueType &y) const noexcept
Transforms a 2D coordinate using this matrix.
void transformPoints(ValueType &x1, ValueType &y1, ValueType &x2, ValueType &y2) const noexcept
Transforms two 2D coordinates using this matrix.
ElementType * end() noexcept
Returns a pointer to the element which follows the last element in the array.
Definition juce_Array.h:344
ElementType * get() const noexcept
Returns a raw pointer to the allocated data.
void realloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Re-allocates a specified amount of memory.
bool closesSubPath
Indicates whether the current line segment is closing a sub-path.
bool next()
Fetches the next line segment from the path.
float y2
The y position of the end of the current line segment.
float x2
The x position of the end of the current line segment.
float y1
The y position of the start of the current line segment.
PathFlatteningIterator(const Path &path, const AffineTransform &transform=AffineTransform(), float tolerance=Path::defaultToleranceForMeasurement)
Creates a PathFlatteningIterator.
float x1
The x position of the start of the current line segment.
int subPathIndex
The index of the current line within the current sub-path.
bool isLastInSubpath() const noexcept
Returns true if the current segment is the last in the current sub-path.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
Definition juce_Path.h:65
#define jassert(expression)
Platform-independent assertion macro.
JUCE Namespace.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Returns the iterator that was passed in.
typedef size_t