Skip to content

Commit 23af17b

Browse files
authored
Add ORBPath native implementations (#13)
1 parent 2bc51e1 commit 23af17b

File tree

11 files changed

+195
-55
lines changed

11 files changed

+195
-55
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ DerivedData/
88
.netrc
99
.claude/
1010
.rb_template/
11+
.augment/

Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/OpenRenderBox/Path/ORBPath.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include <OpenRenderBox/ORBPath.h>
99
#include <OpenRenderBox/ORBPathCallbacks.h>
10+
#include <OpenRenderBoxCxx/Path/PathStorage.hpp>
11+
#include <OpenRenderBoxCxx/Util/assert.hpp>
1012

1113
// Empty path callbacks (all null) - C++ internal linkage
1214
static const ORBPathCallbacks empty_path_callbacks = {
@@ -53,6 +55,21 @@ void ORBPathRelease(ORBPath path) {
5355

5456
// MARK: - Path Creation
5557

58+
namespace {
59+
ORBPath make_rect(CGRect rect, const CGAffineTransform *transform, ORBPathElement element) {
60+
if (CGRectIsNull(rect)) {
61+
return ORBPathNull;
62+
}
63+
if (transform == nullptr || CGAffineTransformIsIdentity(*transform)) {
64+
// TODO
65+
return ORBPathNull;
66+
} else {
67+
// TODO
68+
return ORBPathNull;
69+
}
70+
}
71+
} /* anonymous namespace */
72+
5673
// TODO: TO be implemented natively
5774

5875
ORBPath ORBPathMakeWithCGPath(CGPathRef cgPath) {
@@ -67,12 +84,7 @@ ORBPath ORBPathMakeWithCGPath(CGPathRef cgPath) {
6784
}
6885

6986
ORBPath ORBPathMakeRect(CGRect rect, const CGAffineTransform *transform) {
70-
CGPathRef cgPath = CGPathCreateWithRect(rect, transform);
71-
ORBPath path = {
72-
reinterpret_cast<ORBPathStorage *>(const_cast<CGPath *>(cgPath)),
73-
&ORBPathCGPathCallbacks,
74-
};
75-
return path;
87+
return make_rect(rect, transform, ORBPathElementRect);
7688
}
7789

7890
ORBPath ORBPathMakeEllipse(CGRect rect, const CGAffineTransform *transform) {
@@ -146,3 +158,19 @@ bool ORBPathContainsPoints(ORBPath path, uint64_t count, const CGPoint *points,
146158
}
147159

148160
#endif /* ORB_TARGET_OS_DARWIN */
161+
162+
bool ORBPathApplyElements(ORBPath path, void *info, ORBPathApplyCallback callback) {
163+
auto apply = path.callbacks->apply;
164+
bool flag = false; // TODO: calllbacks's flag to indicate whether it supports extra features
165+
if (flag) {
166+
if (callback == nullptr) {
167+
return true;
168+
}
169+
return apply(path.storage, info, callback/*, path.callbacks*/);
170+
} else {
171+
if (callback == nullptr) {
172+
return true;
173+
}
174+
return apply(path.storage, info, callback);
175+
}
176+
}

Sources/OpenRenderBox/Path/ORBPathStorage.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@
88

99
using namespace ORB;
1010

11+
namespace ORB {
12+
namespace Path {
13+
namespace {
14+
bool append_element_callback(void * info, ORBPathElement element, const CGFloat *points, const void * _Nullable userInfo) {
15+
reinterpret_cast<Storage *>(info)->append_element(element, points, userInfo);
16+
return true;
17+
}
18+
} /* anonymous namespace */
19+
} /* Path */
20+
} /* ORB */
21+
1122
void ORBPathStorageInit(ORBPathStorageRef dst, uint32_t capacity, ORBPathStorageRef source) {
1223
if (source != nullptr) {
1324
dst->storage = ORB::Path::Storage(capacity, source->storage);
@@ -24,16 +35,16 @@ void ORBPathStorageClear(ORBPathStorageRef storage) {
2435
storage->storage.clear();
2536
}
2637

27-
bool ORBPathStorageAppendElement(ORBPathStorageRef storage, ORBPathElement element, double const * points, const void * userInfo) {
28-
precondition_failure("TODO");
38+
bool ORBPathStorageAppendElement(ORBPathStorageRef storage, ORBPathElement element, const CGFloat * points, const void * userInfo) {
39+
return storage->storage.append_element(element, points, userInfo);
2940
}
3041

31-
void ORBPathStorageAppendPath(ORBPathStorageRef storage, ORBPath path) {
32-
precondition_failure("TODO");
42+
bool ORBPathStorageAppendPath(ORBPathStorageRef storage, ORBPath path) {
43+
return ORBPathApplyElements(path, storage, ORB::Path::append_element_callback);
3344
}
3445

35-
bool ORBPathStorageApplyElements(ORBPathStorageRef, void *info, ORBPathApplyCallback callback) {
36-
precondition_failure("TODO");
46+
bool ORBPathStorageApplyElements(ORBPathStorageRef storage, void *info, ORBPathApplyCallback callback) {
47+
return storage->storage.apply_elements(info, callback);
3748
}
3849

3950
bool ORBPathStorageIsEmpty(ORBPathStorageRef storage) {
@@ -59,6 +70,7 @@ CGRect ORBPathStorageGetBoundingRect(ORBPathStorageRef storage) {
5970
}
6071

6172
CGPathRef ORBPathStorageGetCGPath(ORBPathStorageRef storage) {
62-
precondition_failure("TODO");
73+
// FIXME
74+
return storage->storage.cgpath();
6375
}
6476
#endif

Sources/OpenRenderBox/Path/PathStorage.cpp

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// PathStorage.cpp
33
// OpenRenderBox
44

5+
#include <OpenRenderBox/ORBPath.h>
6+
#include <OpenRenderBox/ORBPathCallbacks.h>
57
#include <OpenRenderBoxCxx/Path/PathStorage.hpp>
68
#include <OpenRenderBoxCxx/Util/assert.hpp>
79

@@ -11,7 +13,7 @@
1113

1214
namespace ORB {
1315
namespace Path {
14-
atomic_long Storage::_last_identifier;
16+
atomic_uint Storage::_last_identifier;
1517

1618
Storage::Storage(uint32_t capacity) {
1719
_unknown = nullptr;
@@ -59,9 +61,21 @@ Storage::Storage(uint32_t capacity, const Storage &storage): Storage(capacity) {
5961

6062
Storage::~Storage() {
6163
if (_unknown != nullptr) {
64+
auto oldValue = _unknown;
6265
_unknown = nullptr;
6366
// TODO
6467
}
68+
// TODO: MapCache
69+
if (flags().isExternal()) {
70+
#if ORB_TARGET_OS_DARWIN
71+
if (cachedCGPath() != nullptr) {
72+
auto oldCache = cachedCGPath();
73+
_cached_cgPath = nullptr;
74+
CFRelease(oldCache);
75+
}
76+
#endif
77+
free((void *)external_storage());
78+
}
6579
}
6680

6781
bool Storage::operator==(const Storage &other) const ORB_NOEXCEPT {
@@ -73,16 +87,68 @@ void Storage::clear() {
7387
// TODO
7488
}
7589

76-
void * Storage::cgpath() const ORB_NOEXCEPT {
77-
if (_flags.isInline()) {
90+
bool Storage::append_element(ORBPathElement element, const CGFloat *points, const void *info) {
91+
if (element >= ORBPathElementInvalid) {
92+
precondition_failure("invalid path element: %d", element);
93+
}
94+
// TODO: Implement element appending
95+
precondition_failure("TODO");
96+
}
97+
98+
bool Storage::apply_elements(void *info, ORBPathApplyCallback callback) const ORB_NOEXCEPT {
99+
// TODO: Add fast-path checks for special callbacks:
100+
// - append_element_callback → append_storage(info, this)
101+
// - NestedCallbacks::apply_elements_callback → apply_elements_fast
102+
// - NestedCallbacks::single_element_callback → single_element_fast
103+
// - Mapper::apply_callback with flags check → MapCache::apply
104+
return apply_elements_(info, callback);
105+
}
106+
107+
bool Storage::apply_elements_(void *info, ORBPathApplyCallback callback) const ORB_NOEXCEPT {
108+
// TODO: Implement actual element iteration over storage
109+
return true;
110+
}
111+
112+
#if ORB_TARGET_OS_DARWIN
113+
CGPathRef Storage::cgpath() const ORB_NOEXCEPT {
114+
if (flags().isInline()) {
78115
return nullptr;
79116
}
80-
if (_cached_cgPath != nullptr) {
81-
return _cached_cgPath;
117+
CGPathRef cached = __atomic_load_n(&_cached_cgPath, __ATOMIC_SEQ_CST);
118+
if (cached != nullptr) {
119+
return cached;
120+
}
121+
static const ORBPathCallbacks callbacks = {
122+
nullptr,
123+
nullptr,
124+
nullptr,
125+
+[](const void *object, void *info, ORBPathApplyCallback callback) -> bool {
126+
auto storage = reinterpret_cast<const ORB::Path::Storage *>(object);
127+
return storage->apply_elements(info, callback);
128+
},
129+
nullptr,
130+
nullptr,
131+
nullptr,
132+
nullptr,
133+
nullptr,
134+
nullptr,
135+
nullptr,
136+
};
137+
ORBPath path = {
138+
const_cast<ORBPathStorage *>(reinterpret_cast<const ORBPathStorage *>(this)),
139+
&callbacks
140+
};
141+
CGPathRef new_path = ORBPathCopyCGPath(path);
142+
CGPathRef expected = nullptr;
143+
if (__atomic_compare_exchange_n(&_cached_cgPath, &expected, new_path,
144+
false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
145+
return new_path;
146+
} else {
147+
CGPathRelease(new_path);
148+
return expected;
82149
}
83-
// TODO: Create CGPath via RBPathCopyCGPath
84-
return nullptr;
85150
}
151+
#endif
86152

87153
} /* Path */
88154
} /* ORB */

Sources/OpenRenderBox/include/OpenRenderBox/ORBBase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,4 @@
6868

6969
#if !ORB_TRRET_OS_DARWIN
7070
#include "CFCGTypes.h"
71-
#endif
71+
#endif

Sources/OpenRenderBox/include/OpenRenderBox/ORBPath.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ typedef ORB_ENUM(int32_t, ORBPathElement) {
2020
ORBPathElementAddQuadCurveToPoint = 2,
2121
ORBPathElementAddCurveToPoint = 3,
2222
ORBPathElementCloseSubpath = 4,
23-
23+
ORBPathElementRect = 5,
24+
ORBPathElementRoundedRect = 6,
2425
ORBPathElementFixedRoundedRectCircular = 8,
2526
ORBPathElementFixedRoundedRectContinuous = 9,
26-
};
27+
28+
ORBPathElementInvalid = 25,
29+
} ORB_SWIFT_NAME(ORBPath.Element);
2730

2831
/// Defines the shape of a rounded rectangle's corners.
2932
typedef ORB_ENUM(int32_t, ORBPathRoundedCornerStyle) {
@@ -37,7 +40,7 @@ typedef ORB_ENUM(int32_t, ORBPathRoundedCornerStyle) {
3740
/// Returns true to stop enumeration, false to continue
3841
typedef bool (*ORBPathApplyCallback)(void * info, ORBPathElement element, const CGFloat *points, const void * _Nullable userInfo);
3942

40-
typedef struct ORBPathCallbacks ORBPathCallbacks;
43+
typedef struct ORBPathCallbacks ORBPathCallbacks ORB_SWIFT_NAME(ORBPath.ApplyCallback);
4144

4245
typedef struct ORBPathStorage * ORBPathStorageRef ORB_SWIFT_STRUCT ORB_SWIFT_NAME(ORBPath.Storage);
4346

@@ -55,11 +58,9 @@ ORB_EXPORT
5558
const ORBPath ORBPathNull ORB_SWIFT_NAME(ORBPath.null);
5659

5760
ORB_EXPORT
58-
ORB_REFINED_FOR_SWIFT
5961
void ORBPathRetain(ORBPath path) ORB_SWIFT_NAME(ORBPath.retain(self:));
6062

6163
ORB_EXPORT
62-
ORB_REFINED_FOR_SWIFT
6364
void ORBPathRelease(ORBPath path) ORB_SWIFT_NAME(ORBPath.release(self:));
6465

6566
#if ORB_TARGET_OS_DARWIN
@@ -95,6 +96,11 @@ ORB_EXPORT
9596
bool ORBPathContainsPoints(ORBPath path, uint64_t count, const CGPoint *points, bool eoFill, const CGAffineTransform * _Nullable transform) ORB_SWIFT_NAME(ORBPath.containsPoints(self:count:points:eoFill:transform:));
9697
#endif
9798

99+
// MARK: - Apply Callback
100+
101+
ORB_EXPORT
102+
bool ORBPathApplyElements(ORBPath path, void * info, _Nullable ORBPathApplyCallback callback) ORB_SWIFT_NAME(ORBPath.apply(self:info:callback:));
103+
98104
ORB_EXTERN_C_END
99105

100106
ORB_ASSUME_NONNULL_END

Sources/OpenRenderBox/include/OpenRenderBox/ORBPathStorage.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,53 +18,42 @@ ORB_ASSUME_NONNULL_BEGIN
1818
ORB_EXTERN_C_BEGIN
1919

2020
ORB_EXPORT
21-
ORB_REFINED_FOR_SWIFT
2221
void ORBPathStorageInit(ORBPathStorageRef dst, uint32_t capacity, ORBPathStorageRef _Nullable source) ORB_SWIFT_NAME(ORBPathStorageRef.initialize(self:capacity:source:));
2322

2423
ORB_EXPORT
25-
ORB_REFINED_FOR_SWIFT
2624
void ORBPathStorageDestroy(ORBPathStorageRef storage) ORB_SWIFT_NAME(ORBPathStorageRef.destroy(self:));
2725

2826
ORB_EXPORT
29-
ORB_REFINED_FOR_SWIFT
3027
void ORBPathStorageClear(ORBPathStorageRef storage) ORB_SWIFT_NAME(ORBPathStorageRef.clear(self:));
3128

3229
ORB_EXPORT
33-
ORB_REFINED_FOR_SWIFT
3430
bool ORBPathStorageAppendElement(ORBPathStorageRef storage, ORBPathElement element, CGFloat const * points, const void * _Nullable userInfo) ORB_SWIFT_NAME(ORBPathStorageRef.append(self:element:points:userInfo:));
3531

3632
ORB_EXPORT
37-
ORB_REFINED_FOR_SWIFT
38-
void ORBPathStorageAppendPath(ORBPathStorageRef, ORBPath) ORB_SWIFT_NAME(ORBPathStorageRef.append(self:path:));
33+
bool ORBPathStorageAppendPath(ORBPathStorageRef, ORBPath) ORB_SWIFT_NAME(ORBPathStorageRef.append(self:path:));
3934

4035
ORB_EXPORT
41-
ORB_REFINED_FOR_SWIFT
4236
bool ORBPathStorageApplyElements(ORBPathStorageRef, void *info, ORBPathApplyCallback _Nullable callback) ORB_SWIFT_NAME(ORBPathStorageRef.apply(self:info:callback:));
4337

4438
ORB_EXPORT
45-
ORB_REFINED_FOR_SWIFT
4639
bool ORBPathStorageIsEmpty(ORBPathStorageRef storage) ORB_SWIFT_NAME(getter:ORBPathStorageRef.isEmpty(self:));
4740

4841
ORB_EXPORT
49-
ORB_REFINED_FOR_SWIFT
5042
bool ORBPathStorageEqualToStorage(ORBPathStorageRef lhs, ORBPathStorageRef rhs) ORB_SWIFT_NAME(ORBPathStorageRef.isEqual(self:to:));
5143

5244
ORB_EXPORT
53-
ORB_REFINED_FOR_SWIFT
5445
bool ORBPathStorageIsSingleElement(ORBPathStorageRef storage) ORB_SWIFT_NAME(getter:ORBPathStorageRef.isSingleElement(self:));
5546

5647
ORB_EXPORT
57-
ORB_REFINED_FOR_SWIFT
5848
uint32_t ORBPathStorageGetBezierOrder(ORBPathStorageRef storage) ORB_SWIFT_NAME(getter:ORBPathStorageRef.bezierOrder(self:));
5949

6050
#if ORB_TARGET_OS_DARWIN
6151
ORB_EXPORT
62-
ORB_REFINED_FOR_SWIFT
6352
CGRect ORBPathStorageGetBoundingRect(ORBPathStorageRef storage) ORB_SWIFT_NAME(getter:ORBPathStorageRef.boundingRect(self:));
6453

6554
ORB_EXPORT
66-
ORB_REFINED_FOR_SWIFT
67-
CGPathRef RBPathStorageGetCGPath(ORBPathStorageRef storage) ORB_SWIFT_NAME(getter:ORBPathStorageRef.cgPath(self:));
55+
CF_RETURNS_NOT_RETAINED
56+
__nullable CGPathRef ORBPathStorageGetCGPath(ORBPathStorageRef storage) ORB_SWIFT_NAME(getter:ORBPathStorageRef.cgPath(self:));
6857
#endif
6958

7059
ORB_EXTERN_C_END

Sources/OpenRenderBox/include/OpenRenderBox/ORBUUID.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ ORB_EXTERN_C_BEGIN
1818

1919
#if ORB_TARGET_OS_DARWIN && __OBJC__
2020
ORB_EXPORT
21-
ORB_REFINED_FOR_SWIFT
2221
ORBUUID ORBUUIDInitFromNSUUID(NSUUID *uuid) ORB_SWIFT_NAME(ORBUUID.init(uuid:));
2322
#endif
2423

2524
ORB_EXPORT
26-
ORB_REFINED_FOR_SWIFT
2725
ORBUUID ORBUUIDInitFromHash(uint64_t words0, uint64_t words1, uint32_t words2) ORB_SWIFT_NAME(ORBUUID.init(_:_:_:));
2826

2927
ORB_EXTERN_C_END

0 commit comments

Comments
 (0)