1// [Blend2D]
2// 2D Vector Graphics Powered by a JIT Compiler.
3//
4// [License]
5// Zlib - See LICENSE.md file in the package.
6
7#ifndef BLEND2D_BLPATH_H
8#define BLEND2D_BLPATH_H
9
10#include "./blarray.h"
11#include "./blgeometry.h"
12#include "./blvariant.h"
13
14//! \addtogroup blend2d_api_geometry
15//! \{
16
17// ============================================================================
18// [Constants]
19// ============================================================================
20
21//! Path command.
22BL_DEFINE_ENUM(BLPathCmd) {
23 //! Move-to command (starts a new figure).
24 BL_PATH_CMD_MOVE = 0,
25 //! On-path command (interpreted as line-to or the end of a curve).
26 BL_PATH_CMD_ON = 1,
27 //! Quad-to control point.
28 BL_PATH_CMD_QUAD = 2,
29 //! Cubic-to control point (always used as a pair of commands).
30 BL_PATH_CMD_CUBIC = 3,
31 //! Close path.
32 BL_PATH_CMD_CLOSE = 4,
33
34 //! Count of path commands.
35 BL_PATH_CMD_COUNT = 5
36};
37
38//! Path command (never stored in path).
39BL_DEFINE_ENUM(BLPathCmdExtra) {
40 //! Used by `BLPath::setVertexAt` to preserve the current command value.
41 BL_PATH_CMD_PRESERVE = 0xFFFFFFFFu
42};
43
44//! Path flags.
45BL_DEFINE_ENUM(BLPathFlags) {
46 //! Path is empty (no commands or close commands only).
47 BL_PATH_FLAG_EMPTY = 0x00000001u,
48 //! Path contains multiple figures.
49 BL_PATH_FLAG_MULTIPLE = 0x00000002u,
50 //! Path contains quad curves (at least one).
51 BL_PATH_FLAG_QUADS = 0x00000004u,
52 //! Path contains cubic curves (at least one).
53 BL_PATH_FLAG_CUBICS = 0x00000008u,
54 //! Path is invalid.
55 BL_PATH_FLAG_INVALID = 0x40000000u,
56 //! Flags are dirty (not reflecting the current status).
57 BL_PATH_FLAG_DIRTY = 0x80000000u
58};
59
60//! Path reversal mode.
61BL_DEFINE_ENUM(BLPathReverseMode) {
62 //! Reverse each figure and their order as well (default).
63 BL_PATH_REVERSE_MODE_COMPLETE = 0,
64 //! Reverse each figure separately (keeps their order).
65 BL_PATH_REVERSE_MODE_SEPARATE = 1,
66
67 //! Count of path-reversal modes
68 BL_PATH_REVERSE_MODE_COUNT = 2
69};
70
71//! Stroke join type.
72BL_DEFINE_ENUM(BLStrokeJoin) {
73 //! Miter-join possibly clipped at `miterLimit` [default].
74 BL_STROKE_JOIN_MITER_CLIP = 0,
75 //! Miter-join or bevel-join depending on miterLimit condition.
76 BL_STROKE_JOIN_MITER_BEVEL = 1,
77 //! Miter-join or round-join depending on miterLimit condition.
78 BL_STROKE_JOIN_MITER_ROUND = 2,
79 //! Bevel-join.
80 BL_STROKE_JOIN_BEVEL = 3,
81 //! Round-join.
82 BL_STROKE_JOIN_ROUND = 4,
83
84 //! Count of stroke join types.
85 BL_STROKE_JOIN_COUNT = 5
86};
87
88//! Position of a stroke-cap.
89BL_DEFINE_ENUM(BLStrokeCapPosition) {
90 //! Start of the path.
91 BL_STROKE_CAP_POSITION_START = 0,
92 //! End of the path.
93 BL_STROKE_CAP_POSITION_END = 1,
94
95 //! Count of stroke position options.
96 BL_STROKE_CAP_POSITION_COUNT = 2
97};
98
99//! A presentation attribute defining the shape to be used at the end of open subpaths.
100BL_DEFINE_ENUM(BLStrokeCap) {
101 //! Butt cap [default].
102 BL_STROKE_CAP_BUTT = 0,
103 //! Square cap.
104 BL_STROKE_CAP_SQUARE = 1,
105 //! Round cap.
106 BL_STROKE_CAP_ROUND = 2,
107 //! Round cap reversed.
108 BL_STROKE_CAP_ROUND_REV = 3,
109 //! Triangle cap.
110 BL_STROKE_CAP_TRIANGLE = 4,
111 //! Triangle cap reversed.
112 BL_STROKE_CAP_TRIANGLE_REV = 5,
113
114 //! Used to catch invalid arguments.
115 BL_STROKE_CAP_COUNT = 6
116};
117
118//! Stroke transform order.
119BL_DEFINE_ENUM(BLStrokeTransformOrder) {
120 //! Transform after stroke => `Transform(Stroke(Input))` [default].
121 BL_STROKE_TRANSFORM_ORDER_AFTER = 0,
122 //! Transform before stroke => `Stroke(Transform(Input))`.
123 BL_STROKE_TRANSFORM_ORDER_BEFORE = 1,
124
125 //! Count of transform order types.
126 BL_STROKE_TRANSFORM_ORDER_COUNT = 2
127};
128
129//! Mode that specifies how curves are approximated to line segments.
130BL_DEFINE_ENUM(BLFlattenMode) {
131 //! Use default mode (decided by Blend2D).
132 BL_FLATTEN_MODE_DEFAULT = 0,
133 //! Recursive subdivision flattening.
134 BL_FLATTEN_MODE_RECURSIVE = 1,
135
136 //! Count of flatten modes.
137 BL_FLATTEN_MODE_COUNT = 2
138};
139
140//! Mode that specifies how to construct offset curves.
141BL_DEFINE_ENUM(BLOffsetMode) {
142 //! Use default mode (decided by Blend2D).
143 BL_OFFSET_MODE_DEFAULT = 0,
144 //! Iterative offset construction.
145 BL_OFFSET_MODE_ITERATIVE = 1,
146
147 //! Count of offset modes.
148 BL_OFFSET_MODE_COUNT = 2
149};
150
151// ============================================================================
152// [BLApproximationOptions]
153// ============================================================================
154
155//! Options used to describe how geometry is approximated.
156//!
157//! This struct cannot be simply zeroed and then passed to functions that accept
158//! approximation options. Use `blDefaultApproximationOptions` to setup defaults
159//! and then alter values you want to change.
160//!
161//! Example of using `BLApproximationOptions`:
162//!
163//! ```
164//! // Initialize with defaults first.
165//! BLApproximationOptions approx = blDefaultApproximationOptions;
166//!
167//! // Override values you want to change.
168//! approx.simplifyTolerance = 0.02;
169//!
170//! // ... now safely use approximation options in your code ...
171//! ```
172struct BLApproximationOptions {
173 //! Specifies how curves are flattened, see `BLFlattenMode`.
174 uint8_t flattenMode;
175 //! Specifies how curves are offsetted (used by stroking), see `BLOffsetMode`.
176 uint8_t offsetMode;
177 //! Reserved for future use, must be zero.
178 uint8_t reservedFlags[6];
179
180 //! Tolerance used to flatten curves.
181 double flattenTolerance;
182 //! Tolerance used to approximatecubic curves qith quadratic curves.
183 double simplifyTolerance;
184 //! Curve offsetting parameter, exact meaning depends on `offsetMode`.
185 double offsetParameter;
186};
187
188#ifdef __cplusplus
189extern "C" {
190#endif
191
192//! Default approximation options used by Blend2D.
193extern BL_API const BLApproximationOptions blDefaultApproximationOptions;
194
195#ifdef __cplusplus
196} // {Extern:C}
197#endif
198
199// ============================================================================
200// [BLStrokeOptions - Core]
201// ============================================================================
202
203//! Stroke options [C Interface - Core].
204//!
205//! This structure may use dynamically allocated memory so it's required to use
206//! proper initializers to initialize it and reset it.
207struct BLStrokeOptionsCore {
208 union {
209 struct {
210 uint8_t startCap;
211 uint8_t endCap;
212 uint8_t join;
213 uint8_t transformOrder;
214 uint8_t reserved[4];
215 };
216 uint8_t caps[BL_STROKE_CAP_POSITION_COUNT];
217 uint64_t hints;
218 };
219
220 double width;
221 double miterLimit;
222 double dashOffset;
223 BL_TYPED_MEMBER(BLArrayCore, BLArray<double>, dashArray);
224
225 BL_HAS_TYPED_MEMBERS(BLStrokeOptionsCore)
226};
227
228// ============================================================================
229// [BLStrokeOptions - C++]
230// ============================================================================
231
232#ifdef __cplusplus
233// Prevents the following:
234// Base class XXX should be explicitly initialized in the copy constructor [-Wextra]
235BL_DIAGNOSTIC_PUSH(BL_DIAGNOSTIC_NO_EXTRA_WARNINGS)
236
237//! Stroke options [C++ API].
238//!
239//! You should use this as a structure and use members of `BLStrokeOptionsCore`
240//! directly.
241class BLStrokeOptions : public BLStrokeOptionsCore {
242public:
243 BL_INLINE BLStrokeOptions() noexcept { blStrokeOptionsInit(this); }
244 BL_INLINE BLStrokeOptions(BLStrokeOptions&& other) noexcept { blStrokeOptionsInitMove(this, &other); }
245 BL_INLINE BLStrokeOptions(const BLStrokeOptions& other) noexcept { blStrokeOptionsInitWeak(this, &other); }
246 BL_INLINE ~BLStrokeOptions() noexcept { blStrokeOptionsReset(this); }
247
248 BL_INLINE BLStrokeOptions& operator=(BLStrokeOptions&& other) noexcept { blStrokeOptionsAssignMove(this, &other); return *this; }
249 BL_INLINE BLStrokeOptions& operator=(const BLStrokeOptions& other) noexcept { blStrokeOptionsAssignWeak(this, &other); return *this; }
250
251 BL_INLINE void setCaps(uint32_t strokeCap) noexcept {
252 startCap = uint8_t(strokeCap);
253 endCap = uint8_t(strokeCap);
254 }
255};
256
257BL_DIAGNOSTIC_POP
258#endif
259
260// ============================================================================
261// [BLPath - View]
262// ============================================================================
263
264//! 2D path view provides pointers to vertex and command data along with their
265//! size.
266struct BLPathView {
267 const uint8_t* commandData;
268 const BLPoint* vertexData;
269 size_t size;
270
271 // --------------------------------------------------------------------------
272 #ifdef __cplusplus
273 BL_DIAGNOSTIC_PUSH(BL_DIAGNOSTIC_NO_SHADOW)
274
275 BL_INLINE void reset() noexcept {
276 this->commandData = nullptr;
277 this->vertexData = nullptr;
278 this->size = 0;
279 }
280
281 BL_INLINE void reset(const uint8_t* commandData, const BLPoint* vertexData, size_t size) noexcept {
282 this->commandData = commandData;
283 this->vertexData = vertexData;
284 this->size = size;
285 }
286
287 BL_DIAGNOSTIC_POP
288 #endif
289 // --------------------------------------------------------------------------
290};
291
292// ============================================================================
293// [BLPath - Core]
294// ============================================================================
295
296//! 2D vector path [C Interface - Impl].
297struct BLPathImpl {
298 //! Union of either raw path-data or their `view`.
299 union {
300 struct {
301 //! Command data
302 uint8_t* commandData;
303 //! Vertex data.
304 BLPoint* vertexData;
305 //! Vertex/command count.
306 size_t size;
307 };
308 //! Path data as view.
309 BLPathView view;
310 };
311
312 //! Reference count.
313 volatile size_t refCount;
314 //! Impl type.
315 uint8_t implType;
316 //! Impl traits.
317 uint8_t implTraits;
318 //! Memory pool data.
319 uint16_t memPoolData;
320
321 //! Path flags related to caching.
322 volatile uint32_t flags;
323 //! Path vertex/command capacity.
324 size_t capacity;
325};
326
327//! 2D vector path [C Interface - Core].
328struct BLPathCore {
329 BLPathImpl* impl;
330};
331
332// ============================================================================
333// [BLPath - C++]
334// ============================================================================
335
336#ifdef __cplusplus
337//! 2D vector path [C++ API].
338class BLPath : public BLPathCore {
339public:
340 //! \cond INTERNAL
341 static constexpr const uint32_t kImplType = BL_IMPL_TYPE_PATH;
342 //! \endcond
343
344 //! \name Construction & Destruction
345 //! \{
346
347 BL_INLINE BLPath() noexcept { this->impl = none().impl; }
348 BL_INLINE BLPath(BLPath&& other) noexcept { blVariantInitMove(this, &other); }
349 BL_INLINE BLPath(const BLPath& other) noexcept { blVariantInitWeak(this, &other); }
350 BL_INLINE explicit BLPath(BLPathImpl* impl) noexcept { this->impl = impl; }
351
352 BL_INLINE ~BLPath() noexcept { blPathReset(this); }
353
354 //! \}
355
356 //! \name Overloaded Operators
357 //! \{
358
359 BL_INLINE explicit operator bool() const noexcept { return impl->size != 0; }
360
361 BL_INLINE BLPath& operator=(BLPath&& other) noexcept { blPathAssignMove(this, &other); return *this; }
362 BL_INLINE BLPath& operator=(const BLPath& other) noexcept { blPathAssignWeak(this, &other); return *this; }
363
364 BL_INLINE bool operator==(const BLPath& other) const noexcept { return equals(other); }
365 BL_INLINE bool operator!=(const BLPath& other) const noexcept { return !equals(other); }
366
367 //! \}
368
369 //! \name Common Functionality
370 //! \{
371
372 BL_INLINE BLResult reset() noexcept { return blPathReset(this); }
373 BL_INLINE void swap(BLPath& other) noexcept { std::swap(this->impl, other.impl); }
374
375 BL_INLINE BLResult assign(BLPath&& other) noexcept { return blPathAssignMove(this, &other); }
376 BL_INLINE BLResult assign(const BLPath& other) noexcept { return blPathAssignWeak(this, &other); }
377 BL_INLINE BLResult assignDeep(const BLPath& other) noexcept { return blPathAssignDeep(this, &other); }
378
379 //! Tests whether the 2D path is a built-in null instance.
380 BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; }
381 //! Tests whether the path is empty (its size equals zero).
382 BL_INLINE bool empty() const noexcept { return impl->size == 0; }
383
384 //! Tests whether this path and the `other` path are equal.
385 //!
386 //! The equality check is deep. The data of both paths is examined and binary
387 //! compared (thus a slight difference like -0 and +0 would make the equality
388 //! check to fail).
389 BL_INLINE bool equals(const BLPath& other) const noexcept { return blPathEquals(this, &other); }
390
391 //! \}
392
393 //! \name Path Content
394 //! \{
395
396 //! Returns path size (count of vertices used).
397 BL_INLINE size_t size() const noexcept { return impl->size; }
398 //! Returns path capacity (count of allocated vertices).
399 BL_INLINE size_t capacity() const noexcept { return impl->capacity; }
400
401 //! Returns path's vertex data (read-only).
402 BL_INLINE const BLPoint* vertexData() const noexcept { return impl->vertexData; }
403 //! Returns the end of path's vertex data (read-only).
404 BL_INLINE const BLPoint* vertexDataEnd() const noexcept { return impl->vertexData + impl->size; }
405
406 //! Returns path's command data (read-only).
407 BL_INLINE const uint8_t* commandData() const noexcept { return impl->commandData; }
408 //! Returns the end of path's command data (read-only).
409 BL_INLINE const uint8_t* commandDataEnd() const noexcept { return impl->commandData + impl->size; }
410
411 //! Returns the path data as a read-only `BLPathView`.
412 BL_INLINE const BLPathView& view() const noexcept { return impl->view; }
413
414 //! \}
415
416 //! \name Path Construction
417 //! \{
418
419 //! Clears the content of the path.
420 BL_INLINE BLResult clear() noexcept {
421 return blPathClear(this);
422 }
423
424 //! Shrinks the capacity of the path to fit the current usage.
425 BL_INLINE BLResult shrink() noexcept {
426 return blPathShrink(this);
427 }
428
429 //! Reserves the capacity of the path for at least `n` vertices and commands.
430 BL_INLINE BLResult reserve(size_t n) noexcept {
431 return blPathReserve(this, n);
432 }
433
434 BL_INLINE BLResult modifyOp(uint32_t op, size_t n, uint8_t** cmdDataOut, BLPoint** vtxDataOut) noexcept {
435 return blPathModifyOp(this, op, n, cmdDataOut, vtxDataOut);
436 }
437
438 //! Sets vertex at `index` to `cmd` and `pt`.
439 //!
440 //! Pass `BL_PATH_CMD_PRESERVE` in `cmd` to preserve the current command.
441 BL_INLINE BLResult setVertexAt(size_t index, uint32_t cmd, const BLPoint& pt) noexcept {
442 return blPathSetVertexAt(this, index, cmd, pt.x, pt.y);
443 }
444
445 //! Sets vertex at `index` to `cmd` and `[x, y]`.
446 //!
447 //! Pass `BL_PATH_CMD_PRESERVE` in `cmd` to preserve the current command.
448 BL_INLINE BLResult setVertexAt(size_t index, uint32_t cmd, double x, double y) noexcept {
449 return blPathSetVertexAt(this, index, cmd, x, y);
450 }
451
452 //! Moves to `p0`.
453 //!
454 //! Appends `BL_PATH_CMD_MOVE[p0]` command to the path.
455 BL_INLINE BLResult moveTo(const BLPoint& p0) noexcept {
456 return blPathMoveTo(this, p0.x, p0.y);
457 }
458
459 //! Moves to `[x0, y0]`.
460 //!
461 //! Appends `BL_PATH_CMD_MOVE[x0, y0]` command to the path.
462 BL_INLINE BLResult moveTo(double x0, double y0) noexcept {
463 return blPathMoveTo(this, x0, y0);
464 }
465
466 //! Adds line to `p1`.
467 //!
468 //! Appends `BL_PATH_CMD_ON[p1]` command to the path.
469 BL_INLINE BLResult lineTo(const BLPoint& p1) noexcept {
470 return blPathLineTo(this, p1.x, p1.y);
471 }
472
473 //! Adds line to `[x1, y1]`.
474 //!
475 //! Appends `BL_PATH_CMD_ON[x1, y1]` command to the path.
476 BL_INLINE BLResult lineTo(double x1, double y1) noexcept {
477 return blPathLineTo(this, x1, y1);
478 }
479
480 //! Adds a polyline (LineTo) of the given `poly` array of size `count`.
481 //!
482 //! Appends multiple `BL_PATH_CMD_ON[x[i], y[i]]` commands to the path depending on `count` parameter.
483 BL_INLINE BLResult polyTo(const BLPoint* poly, size_t count) noexcept {
484 return blPathPolyTo(this, poly, count);
485 }
486
487 //! Adds a quadratic curve to `p1` and `p2`.
488 //!
489 //! Appends the following commands to the path:
490 //! - `BL_PATH_CMD_QUAD[p1]`
491 //! - `BL_PATH_CMD_ON[p2]`
492 //!
493 //! Matches SVG 'Q' path command:
494 //! - https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands
495 BL_INLINE BLResult quadTo(const BLPoint& p1, const BLPoint& p2) noexcept {
496 return blPathQuadTo(this, p1.x, p1.y, p2.x, p2.y);
497 }
498
499 //! Adds a quadratic curve to `[x1, y1]` and `[x2, y2]`.
500 //!
501 //! Appends the following commands to the path:
502 //! - `BL_PATH_CMD_QUAD[x1, y1]`
503 //! - `BL_PATH_CMD_ON[x2, y2]`
504 //!
505 //! Matches SVG 'Q' path command:
506 //! - https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands
507 BL_INLINE BLResult quadTo(double x1, double y1, double x2, double y2) noexcept {
508 return blPathQuadTo(this, x1, y1, x2, y2);
509 }
510
511 //! Adds a cubic curve to `p1`, `p2`, `p3`.
512 //!
513 //! Appends the following commands to the path:
514 //! - `BL_PATH_CMD_CUBIC[p1]`
515 //! - `BL_PATH_CMD_CUBIC[p2]`
516 //! - `BL_PATH_CMD_ON[p3]`
517 //!
518 //! Matches SVG 'C' path command:
519 //! - https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
520 BL_INLINE BLResult cubicTo(const BLPoint& p1, const BLPoint& p2, const BLPoint& p3) noexcept {
521 return blPathCubicTo(this, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
522 }
523
524 //! Adds a cubic curve to `[x1, y1]`, `[x2, y2]`, and `[x3, y3]`.
525 //!
526 //! Appends the following commands to the path:
527 //! - `BL_PATH_CMD_CUBIC[x1, y1]`
528 //! - `BL_PATH_CMD_CUBIC[x2, y2]`
529 //! - `BL_PATH_CMD_ON[x3, y3]`
530 //!
531 //! Matches SVG 'C' path command:
532 //! - https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
533 BL_INLINE BLResult cubicTo(double x1, double y1, double x2, double y2, double x3, double y3) noexcept {
534 return blPathCubicTo(this, x1, y1, x2, y2, x3, y3);
535 }
536
537 //! Adds a smooth quadratic curve to `p2`, calculating `p1` from last points.
538 //!
539 //! Appends the following commands to the path:
540 //! - `BL_PATH_CMD_QUAD[calculated]`
541 //! - `BL_PATH_CMD_ON[p2]`
542 //!
543 //! Matches SVG 'T' path command:
544 //! - https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands
545 BL_INLINE BLResult smoothQuadTo(const BLPoint& p2) noexcept {
546 return blPathSmoothQuadTo(this, p2.x, p2.y);
547 }
548
549 //! Adds a smooth quadratic curve to `[x2, y2]`, calculating `[x1, y1]` from last points.
550 //!
551 //! Appends the following commands to the path:
552 //! - `BL_PATH_CMD_QUAD[calculated]`
553 //! - `BL_PATH_CMD_ON[x2, y2]`
554 //!
555 //! Matches SVG 'T' path command:
556 //! - https://www.w3.org/TR/SVG/paths.html#PathDataQuadraticBezierCommands
557 BL_INLINE BLResult smoothQuadTo(double x2, double y2) noexcept {
558 return blPathSmoothQuadTo(this, x2, y2);
559 }
560
561 //! Adds a smooth cubic curve to `p2` and `p3`, calculating `p1` from last points.
562 //!
563 //! Appends the following commands to the path:
564 //! - `BL_PATH_CMD_CUBIC[calculated]`
565 //! - `BL_PATH_CMD_CUBIC[p2]`
566 //! - `BL_PATH_CMD_ON[p3]`
567 //!
568 //! Matches SVG 'S' path command:
569 //! - https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
570 BL_INLINE BLResult smoothCubicTo(const BLPoint& p2, const BLPoint& p3) noexcept {
571 return blPathSmoothCubicTo(this, p2.x, p2.y, p3.x, p3.y);
572 }
573
574 //! Adds a smooth cubic curve to `[x2, y2]` and `[x3, y3]`, calculating `[x1, y1]` from last points.
575 //!
576 //! Appends the following commands to the path:
577 //! - `BL_PATH_CMD_CUBIC[calculated]`
578 //! - `BL_PATH_CMD_CUBIC[x2, y2]`
579 //! - `BL_PATH_CMD_ON[x3, y3]`
580 //!
581 //! Matches SVG 'S' path command:
582 //! - https://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands
583 BL_INLINE BLResult smoothCubicTo(double x2, double y2, double x3, double y3) noexcept {
584 return blPathSmoothCubicTo(this, x2, y2, x3, y3);
585 }
586
587 //! Adds an arc to the path.
588 //!
589 //! The center of the arc is specified by `c` and radius by `r`. Both `start`
590 //! and `sweep` angles are in radians. If the last vertex doesn't match the
591 //! start of the arc then a `lineTo()` would be emitted before adding the arc.
592 //! Pass `true` in `forceMoveTo` to always emit `moveTo()` at the beginning of
593 //! the arc, which starts a new figure.
594 BL_INLINE BLResult arcTo(const BLPoint& c, const BLPoint& r, double start, double sweep, bool forceMoveTo = false) noexcept {
595 return blPathArcTo(this, c.x, c.y, r.x, r.y, start, sweep, forceMoveTo);
596 }
597
598 //! \overload
599 BL_INLINE BLResult arcTo(double cx, double cy, double rx, double ry, double start, double sweep, bool forceMoveTo = false) noexcept {
600 return blPathArcTo(this, cx, cy, rx, ry, start, sweep, forceMoveTo);
601 }
602
603 //! Adds an arc quadrant (90deg) to the path. The first point `p1` specifies
604 //! the quadrant corner and the last point `p2` specifies the end point.
605 BL_INLINE BLResult arcQuadrantTo(const BLPoint& p1, const BLPoint& p2) noexcept {
606 return blPathArcQuadrantTo(this, p1.x, p1.y, p2.x, p2.y);
607 }
608
609 //! \overload
610 BL_INLINE BLResult arcQuadrantTo(double x1, double y1, double x2, double y2) noexcept {
611 return blPathArcQuadrantTo(this, x1, y1, x2, y2);
612 }
613
614 //! Adds an elliptic arc to the path that follows the SVG specification.
615 //!
616 //! Matches SVG 'A' path command:
617 //! - https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands
618 BL_INLINE BLResult ellipticArcTo(const BLPoint& rp, double xAxisRotation, bool largeArcFlag, bool sweepFlag, const BLPoint& p1) noexcept {
619 return blPathEllipticArcTo(this, rp.x, rp.y, xAxisRotation, largeArcFlag, sweepFlag, p1.x, p1.y);
620 }
621
622 //! \overload
623 BL_INLINE BLResult ellipticArcTo(double rx, double ry, double xAxisRotation, bool largeArcFlag, bool sweepFlag, double x1, double y1) noexcept {
624 return blPathEllipticArcTo(this, rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x1, y1);
625 }
626
627 //! Closes the current figure.
628 //!
629 //! Appends `BL_PATH_CMD_CLOSE` to the path.
630 //!
631 //! Matches SVG 'Z' path command:
632 //! - https://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand
633 BL_INLINE BLResult close() noexcept { return blPathClose(this); }
634
635 //! \}
636
637 //! \name Adding Figures
638 //! \{
639
640 //! Adds a closed rectangle to the path specified by `box`.
641 BL_INLINE BLResult addBox(const BLBoxI& box, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
642 return blPathAddBoxI(this, &box, dir);
643 }
644
645 //! Adds a closed rectangle to the path specified by `box`.
646 BL_INLINE BLResult addBox(const BLBox& box, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
647 return blPathAddBoxD(this, &box, dir);
648 }
649
650 //! Adds a closed rectangle to the path specified by `[x0, y0, x1, y1]`.
651 BL_INLINE BLResult addBox(double x0, double y0, double x1, double y1, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
652 return addBox(BLBox(x0, y0, x1, y1), dir);
653 }
654
655 //! Adds a closed rectangle to the path specified by `rect`.
656 BL_INLINE BLResult addRect(const BLRectI& rect, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
657 return blPathAddRectI(this, &rect, dir);
658 }
659
660 //! Adds a closed rectangle to the path specified by `rect`.
661 BL_INLINE BLResult addRect(const BLRect& rect, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
662 return blPathAddRectD(this, &rect, dir);
663 }
664
665 //! Adds a closed rectangle to the path specified by `[x, y, w, h]`.
666 BL_INLINE BLResult addRect(double x, double y, double w, double h, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
667 return addRect(BLRect(x, y, w, h), dir);
668 }
669
670 //! Adds a geometry to the path.
671 BL_INLINE BLResult addGeometry(uint32_t geometryType, const void* geometryData, const BLMatrix2D* m = nullptr, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
672 return blPathAddGeometry(this, geometryType, geometryData, m, dir);
673 }
674
675 //! Adds a closed circle to the path.
676 BL_INLINE BLResult addCircle(const BLCircle& circle, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
677 return addGeometry(BL_GEOMETRY_TYPE_CIRCLE, &circle, nullptr, dir);
678 }
679
680 //! \overload
681 BL_INLINE BLResult addCircle(const BLCircle& circle, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
682 return addGeometry(BL_GEOMETRY_TYPE_CIRCLE, &circle, &m, dir);
683 }
684
685 //! Adds a closed ellipse to the path.
686 BL_INLINE BLResult addEllipse(const BLEllipse& ellipse, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
687 return addGeometry(BL_GEOMETRY_TYPE_ELLIPSE, &ellipse, nullptr, dir);
688 }
689
690 //! \overload
691 BL_INLINE BLResult addEllipse(const BLEllipse& ellipse, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
692 return addGeometry(BL_GEOMETRY_TYPE_ELLIPSE, &ellipse, &m, dir);
693 }
694
695 //! Adds a closed rounded ractangle to the path.
696 BL_INLINE BLResult addRoundRect(const BLRoundRect& rr, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
697 return addGeometry(BL_GEOMETRY_TYPE_ROUND_RECT, &rr, nullptr, dir);
698 }
699
700 //! \overload
701 BL_INLINE BLResult addRoundRect(const BLRoundRect& rr, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
702 return addGeometry(BL_GEOMETRY_TYPE_ROUND_RECT, &rr, &m, dir);
703 }
704
705 //! Adds an unclosed arc to the path.
706 BL_INLINE BLResult addArc(const BLArc& arc, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
707 return addGeometry(BL_GEOMETRY_TYPE_ARC, &arc, nullptr, dir);
708 }
709
710 //! \overload
711 BL_INLINE BLResult addArc(const BLArc& arc, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
712 return addGeometry(BL_GEOMETRY_TYPE_ARC, &arc, &m, dir);
713 }
714
715 //! Adds a closed chord to the path.
716 BL_INLINE BLResult addChord(const BLArc& chord, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
717 return addGeometry(BL_GEOMETRY_TYPE_CHORD, &chord, nullptr, dir);
718 }
719
720 //! \overload
721 BL_INLINE BLResult addChord(const BLArc& chord, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
722 return addGeometry(BL_GEOMETRY_TYPE_CHORD, &chord, &m, dir);
723 }
724
725 //! Adds a closed pie to the path.
726 BL_INLINE BLResult addPie(const BLArc& pie, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
727 return addGeometry(BL_GEOMETRY_TYPE_PIE, &pie, nullptr, dir);
728 }
729
730 //! \overload
731 BL_INLINE BLResult addPie(const BLArc& pie, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
732 return addGeometry(BL_GEOMETRY_TYPE_PIE, &pie, &m, dir);
733 }
734
735 //! Adds an unclosed line to the path.
736 BL_INLINE BLResult addLine(const BLLine& line, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
737 return addGeometry(BL_GEOMETRY_TYPE_LINE, &line, nullptr, dir);
738 }
739
740 //! \overload
741 BL_INLINE BLResult addLine(const BLLine& line, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
742 return addGeometry(BL_GEOMETRY_TYPE_LINE, &line, &m, dir);
743 }
744
745 //! Adds a closed triangle.
746 BL_INLINE BLResult addTriangle(const BLTriangle& triangle, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
747 return addGeometry(BL_GEOMETRY_TYPE_TRIANGLE, &triangle, nullptr, dir);
748 }
749
750 //! \overload
751 BL_INLINE BLResult addTriangle(const BLTriangle& triangle, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
752 return addGeometry(BL_GEOMETRY_TYPE_TRIANGLE, &triangle, &m, dir);
753 }
754
755 //! Adds a polyline.
756 BL_INLINE BLResult addPolyline(const BLArrayView<BLPointI>& poly, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
757 return addGeometry(BL_GEOMETRY_TYPE_POLYLINEI, &poly, nullptr, dir);
758 }
759
760 //! \overload
761 BL_INLINE BLResult addPolyline(const BLArrayView<BLPointI>& poly, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
762 return addGeometry(BL_GEOMETRY_TYPE_POLYLINEI, &poly, &m, dir);
763 }
764
765 //! \overload
766 BL_INLINE BLResult addPolyline(const BLPointI* poly, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
767 return addPolyline(BLArrayView<BLPointI>{poly, n}, dir);
768 }
769
770 //! \overload
771 BL_INLINE BLResult addPolyline(const BLPointI* poly, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
772 return addPolyline(BLArrayView<BLPointI>{poly, n}, m, dir);
773 }
774
775 //! Adds a polyline.
776 BL_INLINE BLResult addPolyline(const BLArrayView<BLPoint>& poly, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
777 return addGeometry(BL_GEOMETRY_TYPE_POLYLINED, &poly, nullptr, dir);
778 }
779
780 //! \overload
781 BL_INLINE BLResult addPolyline(const BLArrayView<BLPoint>& poly, const BLMatrix2D& m, uint32_t dir) {
782 return addGeometry(BL_GEOMETRY_TYPE_POLYLINED, &poly, &m, dir);
783 }
784
785 //! \overload
786 BL_INLINE BLResult addPolyline(const BLPoint* poly, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
787 return addPolyline(BLArrayView<BLPoint>{poly, n}, dir);
788 }
789
790 //! \overload
791 BL_INLINE BLResult addPolyline(const BLPoint* poly, size_t n, const BLMatrix2D& m, uint32_t dir) {
792 return addPolyline(BLArrayView<BLPoint>{poly, n}, m, dir);
793 }
794
795 //! Adds a polygon.
796 BL_INLINE BLResult addPolygon(const BLArrayView<BLPointI>& poly, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
797 return addGeometry(BL_GEOMETRY_TYPE_POLYGONI, &poly, nullptr, dir);
798 }
799
800 //! \overload
801 BL_INLINE BLResult addPolygon(const BLArrayView<BLPointI>& poly, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
802 return addGeometry(BL_GEOMETRY_TYPE_POLYGONI, &poly, &m, dir);
803 }
804
805 //! \overload
806 BL_INLINE BLResult addPolygon(const BLPointI* poly, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
807 return addPolygon(BLArrayView<BLPointI>{poly, n}, dir);
808 }
809
810 //! \overload
811 BL_INLINE BLResult addPolygon(const BLPointI* poly, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
812 return addPolygon(BLArrayView<BLPointI>{poly, n}, m, dir);
813 }
814
815 //! Adds a polygon.
816 BL_INLINE BLResult addPolygon(const BLArrayView<BLPoint>& poly, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
817 return addGeometry(BL_GEOMETRY_TYPE_POLYGOND, &poly, nullptr, dir);
818 }
819
820 //! \overload
821 BL_INLINE BLResult addPolygon(const BLArrayView<BLPoint>& poly, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
822 return addGeometry(BL_GEOMETRY_TYPE_POLYGOND, &poly, &m, dir);
823 }
824
825 //! \overload
826 BL_INLINE BLResult addPolygon(const BLPoint* poly, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
827 return addPolygon(BLArrayView<BLPoint>{poly, n}, dir);
828 }
829
830 //! \overload
831 BL_INLINE BLResult addPolygon(const BLPoint* poly, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
832 return addPolygon(BLArrayView<BLPoint>{poly, n}, m, dir);
833 }
834
835 //! Adds an array of closed boxes.
836 BL_INLINE BLResult addBoxArray(const BLArrayView<BLBoxI>& array, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
837 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXI, &array, nullptr, dir);
838 }
839
840 //! \overload
841 BL_INLINE BLResult addBoxArray(const BLArrayView<BLBoxI>& array, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
842 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXI, &array, &m, dir);
843 }
844
845 //! \overload
846 BL_INLINE BLResult addBoxArray(const BLBoxI* data, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
847 return addBoxArray(BLArrayView<BLBoxI>{data, n}, dir);
848 }
849
850 //! \overload
851 BL_INLINE BLResult addBoxArray(const BLBoxI* data, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
852 return addBoxArray(BLArrayView<BLBoxI>{data, n}, m, dir);
853 }
854
855 //! Adds an array of closed boxes.
856 BL_INLINE BLResult addBoxArray(const BLArrayView<BLBox>& array, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
857 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXD, &array, nullptr, dir);
858 }
859
860 //! \overload
861 BL_INLINE BLResult addBoxArray(const BLArrayView<BLBox>& array, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
862 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_BOXD, &array, &m, dir);
863 }
864
865 //! \overload
866 BL_INLINE BLResult addBoxArray(const BLBox* data, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
867 return addBoxArray(BLArrayView<BLBox>{data, n}, dir);
868 }
869
870 //! \overload
871 BL_INLINE BLResult addBoxArray(const BLBox* data, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
872 return addBoxArray(BLArrayView<BLBox>{data, n}, m, dir);
873 }
874
875 //! Adds an array of closed rectangles.
876 BL_INLINE BLResult addRectArray(const BLArrayView<BLRectI>& array, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
877 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTI, &array, nullptr, dir);
878 }
879
880 //! \overload
881 BL_INLINE BLResult addRectArray(const BLArrayView<BLRectI>& array, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
882 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTI, &array, &m, dir);
883 }
884
885 //! \overload
886 BL_INLINE BLResult addRectArray(const BLRectI* data, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
887 return addRectArray(BLArrayView<BLRectI>{data, n}, dir);
888 }
889
890 //! \overload
891 BL_INLINE BLResult addRectArray(const BLRectI* data, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
892 return addRectArray(BLArrayView<BLRectI>{data, n}, m, dir);
893 }
894
895 //! Adds an array of closed rectangles.
896 BL_INLINE BLResult addRectArray(const BLArrayView<BLRect>& array, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
897 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTD, &array, nullptr, dir);
898 }
899
900 //! \overload
901 BL_INLINE BLResult addRectArray(const BLArrayView<BLRect>& array, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
902 return addGeometry(BL_GEOMETRY_TYPE_ARRAY_VIEW_RECTD, &array, &m, dir);
903 }
904
905 //! \overload
906 BL_INLINE BLResult addRectArray(const BLRect* data, size_t n, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
907 return addRectArray(BLArrayView<BLRect>{data, n}, dir);
908 }
909
910 //! \overload
911 BL_INLINE BLResult addRectArray(const BLRect* data, size_t n, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
912 return addRectArray(BLArrayView<BLRect>{data, n}, m, dir);
913 }
914
915 //! Adds a closed region (converted to set of rectangles).
916 BL_INLINE BLResult addRegion(const BLRegion& region, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
917 return addGeometry(BL_GEOMETRY_TYPE_REGION, &region, nullptr, dir);
918 }
919
920 //! Adds a closed region (converted to set of rectangles).
921 BL_INLINE BLResult addRegion(const BLRegion& region, const BLMatrix2D& m, uint32_t dir = BL_GEOMETRY_DIRECTION_CW) noexcept {
922 return addGeometry(BL_GEOMETRY_TYPE_REGION, &region, &m, dir);
923 }
924
925 //! \}
926
927 //! \name Adding Paths
928 //! \{
929
930 //! Adds other `path` to this path.
931 BL_INLINE BLResult addPath(const BLPath& path) noexcept {
932 return blPathAddPath(this, &path, nullptr);
933 }
934
935 //! Adds other `path` sliced by the given `range` to this path.
936 BL_INLINE BLResult addPath(const BLPath& path, const BLRange& range) noexcept {
937 return blPathAddPath(this, &path, &range);
938 }
939
940 //! Adds other `path` translated by `p` to this path.
941 BL_INLINE BLResult addPath(const BLPath& path, const BLPoint& p) noexcept {
942 return blPathAddTranslatedPath(this, &path, nullptr, &p);
943 }
944
945 //! Adds other `path` translated by `p` and sliced by the given `range` to this path.
946 BL_INLINE BLResult addPath(const BLPath& path, const BLRange& range, const BLPoint& p) noexcept {
947 return blPathAddTranslatedPath(this, &path, &range, &p);
948 }
949
950 //! Adds other `path` transformed by `m` to this path.
951 BL_INLINE BLResult addPath(const BLPath& path, const BLMatrix2D& m) noexcept {
952 return blPathAddTransformedPath(this, &path, nullptr, &m);
953 }
954
955 //! Adds other `path` transformed by `m` and sliced by the given `range` to this path.
956 BL_INLINE BLResult addPath(const BLPath& path, const BLRange& range, const BLMatrix2D& m) noexcept {
957 return blPathAddTransformedPath(this, &path, &range, &m);
958 }
959
960 //! Adds other `path`, but reversed.
961 BL_INLINE BLResult addReversedPath(const BLPath& path, uint32_t reverseMode) noexcept {
962 return blPathAddReversedPath(this, &path, nullptr, reverseMode);
963 }
964
965 //! Adds other `path`, but reversed.
966 BL_INLINE BLResult addReversedPath(const BLPath& path, const BLRange& range, uint32_t reverseMode) noexcept {
967 return blPathAddReversedPath(this, &path, &range, reverseMode);
968 }
969
970 //! Adds a stroke of `path` to this path.
971 BL_INLINE BLResult addStrokedPath(const BLPath& path, const BLRange& range, const BLStrokeOptions& strokeOptions, const BLApproximationOptions& approximationOptions) noexcept {
972 return blPathAddStrokedPath(this, &path, &range, &strokeOptions, &approximationOptions);
973 }
974 //! \overload
975 BL_INLINE BLResult addStrokedPath(const BLPath& path, const BLStrokeOptions& strokeOptions, const BLApproximationOptions& approximationOptions) noexcept {
976 return blPathAddStrokedPath(this, &path, nullptr, &strokeOptions, &approximationOptions);
977 }
978
979 //! \}
980
981 //! \name Transformations
982 //! \{
983
984 //! Translates the whole path by `p`.
985 BL_INLINE BLResult translate(const BLPoint& p) noexcept {
986 return blPathTranslate(this, nullptr, &p);
987 }
988
989 //! Translates a part of the path specified by the given `range` by `p`.
990 BL_INLINE BLResult translate(const BLRange& range, const BLPoint& p) noexcept {
991 return blPathTranslate(this, &range, &p);
992 }
993
994 //! Transforms the whole path by matrix `m`.
995 BL_INLINE BLResult transform(const BLMatrix2D& m) noexcept {
996 return blPathTransform(this, nullptr, &m);
997 }
998
999 //! Transforms a part of the path specified by the given `range` by matrix `m`.
1000 BL_INLINE BLResult transform(const BLRange& range, const BLMatrix2D& m) noexcept {
1001 return blPathTransform(this, &range, &m);
1002 }
1003
1004 //! Fits the whole path into the given `rect` by taking into account fit flags passed by `fitFlags`.
1005 BL_INLINE BLResult fitTo(const BLRect& rect, uint32_t fitFlags) noexcept {
1006 return blPathFitTo(this, nullptr, &rect, fitFlags);
1007 }
1008
1009 //! Fits a parh of the path specified by the given `range` into the given `rect` by taking into account fit flags passed by `fitFlags`.
1010 BL_INLINE BLResult fitTo(const BLRange& range, const BLRect& rect, uint32_t fitFlags) noexcept {
1011 return blPathFitTo(this, &range, &rect, fitFlags);
1012 }
1013
1014 //! \}
1015
1016 //! \name Path Information
1017 //! \{
1018
1019 //! Update a path information if necessary.
1020 BL_INLINE BLResult getInfoFlags(uint32_t* flagsOut) const noexcept {
1021 return blPathGetInfoFlags(this, flagsOut);
1022 }
1023
1024 //! Stores a bounding box of all vertices and control points to `boxOut`.
1025 //!
1026 //! Control box is simply bounds of all vertices the path has without further
1027 //! processing. It contains both on-path and off-path points. Consider using
1028 //! `getBoundingBox()` if you need a visual bounding box.
1029 BL_INLINE BLResult getControlBox(BLBox* boxOut) const noexcept {
1030 return blPathGetControlBox(this, boxOut);
1031 }
1032
1033 //! Stores a bounding box of all on-path vertices and curve extremas to `boxOut`.
1034 //!
1035 //! The bounding box stored to `boxOut` could be smaller than a bounding box
1036 //! obtained by `getControlBox()` as it's calculated by merging only start/end
1037 //! points and curves at their extremas (not control points). The resulting
1038 //! bounding box represents a visual bounds of the path.
1039 BL_INLINE BLResult getBoundingBox(BLBox* boxOut) const noexcept {
1040 return blPathGetBoundingBox(this, boxOut);
1041 }
1042
1043 //! Returns the range describing a figure at the given `index`.
1044 BL_INLINE BLResult getFigureRange(size_t index, BLRange* rangeOut) const noexcept {
1045 return blPathGetFigureRange(this, index, rangeOut);
1046 }
1047
1048 //! Returns the last vertex of the path and stores it to `vtxOut`. If the very
1049 //! last command of the path is `BL_PATH_CMD_CLOSE` then the path will be
1050 //! iterated in reverse order to match the initial vertex of the last figure.
1051 BL_INLINE BLResult getLastVertex(BLPoint* vtxOut) noexcept {
1052 return blPathGetLastVertex(this, vtxOut);
1053 }
1054
1055 BL_INLINE BLResult getClosestVertex(const BLPoint& p, double maxDistance, size_t* indexOut) const noexcept {
1056 double distanceOut;
1057 return blPathGetClosestVertex(this, &p, maxDistance, indexOut, &distanceOut);
1058 }
1059
1060 BL_INLINE BLResult getClosestVertex(const BLPoint& p, double maxDistance, size_t* indexOut, double* distanceOut) const noexcept {
1061 return blPathGetClosestVertex(this, &p, maxDistance, indexOut, distanceOut);
1062 }
1063
1064 //! \}
1065
1066 //! \name Hit Testing
1067 //! \{
1068
1069 //! Hit tests the given point `p` by respecting the given `fillRule`.
1070 BL_INLINE uint32_t hitTest(const BLPoint& p, uint32_t fillRule) const noexcept {
1071 return blPathHitTest(this, &p, fillRule);
1072 }
1073
1074 //! \}
1075
1076 static BL_INLINE const BLPath& none() noexcept { return reinterpret_cast<const BLPath*>(blNone)[kImplType]; }
1077};
1078#endif
1079
1080//! \}
1081
1082#endif // BLEND2D_BLPATH_H
1083