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
1113
1214namespace ORB {
1315namespace Path {
14- atomic_long Storage::_last_identifier;
16+ atomic_uint Storage::_last_identifier;
1517
1618Storage::Storage (uint32_t capacity) {
1719 _unknown = nullptr ;
@@ -59,9 +61,21 @@ Storage::Storage(uint32_t capacity, const Storage &storage): Storage(capacity) {
5961
6062Storage::~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
6781bool 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 */
0 commit comments