⎇ bce89b1006f36ce35abfaf1f1c2b3dd95f3dffd3
bindings/swift/StretchCore/src/lib.rs
History
Who touched what
raw
Implement new rust API for bindings and release v0.3
1use std::f32;
2use std::os::raw::*;
3use stretch::geometry::*;
4use stretch::node::*;
5use stretch::number::*;
6use stretch::style::*;
7
8#[repr(C)]
9pub struct StretchSize {
10 width: f32,
11 height: f32,
12}
13
14#[repr(C)]
15pub struct StretchStyleDimension {
16 dimen_type: i32,
17 dimen_value: f32,
18}
19
20impl Into<Dimension> for StretchStyleDimension {
21 fn into(self) -> Dimension {
22 match self.dimen_type {
23 0 => Dimension::Points(self.dimen_value),
24 1 => Dimension::Percent(self.dimen_value),
25 2 => Dimension::Auto,
26 3 => Dimension::Undefined,
27 _ => panic!(),
28 }
29 }
30}
31
32#[repr(C)]
33pub struct StretchStyleRect {
34 start: StretchStyleDimension,
35 end: StretchStyleDimension,
36 top: StretchStyleDimension,
37 bottom: StretchStyleDimension,
38}
39
40#[repr(C)]
41pub struct StretchStyleSize {
42 width: StretchStyleDimension,
43 height: StretchStyleDimension,
44}
45
46#[no_mangle]
47pub unsafe extern "C" fn stretch_style_create(
48 display: i32,
49 position_type: i32,
50 direction: i32,
51 flex_direction: i32,
52 flex_wrap: i32,
53 overflow: i32,
54 align_items: i32,
55 align_self: i32,
56 align_content: i32,
57 justify_content: i32,
58
59 position: StretchStyleRect,
60 margin: StretchStyleRect,
61 padding: StretchStyleRect,
62 border: StretchStyleRect,
63
64 flex_grow: f32,
65 flex_shrink: f32,
66
67 flex_basis: StretchStyleDimension,
68
69 size: StretchStyleSize,
70 min_size: StretchStyleSize,
71 max_size: StretchStyleSize,
72
73 aspect_ratio: f32,
74) -> *mut c_void {
75 Box::into_raw(Box::new(Style {
76 display: match display {
77 0 => Display::Flex,
78 1 => Display::None,
79 _ => panic!(),
80 },
81
82 position_type: match position_type {
83 0 => PositionType::Relative,
84 1 => PositionType::Absolute,
85 _ => panic!(),
86 },
87
88 direction: match direction {
89 0 => Direction::Inherit,
90 1 => Direction::LTR,
91 2 => Direction::RTL,
92 _ => panic!(),
93 },
94
95 flex_direction: match flex_direction {
96 0 => FlexDirection::Row,
97 1 => FlexDirection::Column,
98 2 => FlexDirection::RowReverse,
99 3 => FlexDirection::ColumnReverse,
100 _ => panic!(),
101 },
102
103 flex_wrap: match flex_wrap {
104 0 => FlexWrap::NoWrap,
105 1 => FlexWrap::Wrap,
106 2 => FlexWrap::WrapReverse,
107 _ => panic!(),
108 },
109
110 overflow: match overflow {
111 0 => Overflow::Visible,
112 1 => Overflow::Hidden,
113 2 => Overflow::Scroll,
114 _ => panic!(),
115 },
116
117 align_items: match align_items {
118 0 => AlignItems::FlexStart,
119 1 => AlignItems::FlexEnd,
120 2 => AlignItems::Center,
121 3 => AlignItems::Baseline,
122 4 => AlignItems::Stretch,
123 _ => panic!(),
124 },
125
126 align_self: match align_self {
127 0 => AlignSelf::Auto,
128 1 => AlignSelf::FlexStart,
129 2 => AlignSelf::FlexEnd,
130 3 => AlignSelf::Center,
131 4 => AlignSelf::Baseline,
132 5 => AlignSelf::Stretch,
133 _ => panic!(),
134 },
135
136 align_content: match align_content {
137 0 => AlignContent::FlexStart,
138 1 => AlignContent::FlexEnd,
139 2 => AlignContent::Center,
140 3 => AlignContent::Stretch,
141 4 => AlignContent::SpaceBetween,
142 5 => AlignContent::SpaceAround,
143 _ => panic!(),
144 },
145
146 justify_content: match justify_content {
147 0 => JustifyContent::FlexStart,
148 1 => JustifyContent::FlexEnd,
149 2 => JustifyContent::Center,
150 3 => JustifyContent::SpaceBetween,
151 4 => JustifyContent::SpaceAround,
152 5 => JustifyContent::SpaceEvenly,
153 _ => panic!(),
154 },
155
156 position: Rect {
157 start: position.start.into(),
158 end: position.end.into(),
159 top: position.top.into(),
160 bottom: position.bottom.into(),
161 },
162
163 margin: Rect {
164 start: margin.start.into(),
165 end: margin.end.into(),
166 top: margin.top.into(),
167 bottom: margin.bottom.into(),
168 },
169
170 padding: Rect {
171 start: padding.start.into(),
172 end: padding.end.into(),
173 top: padding.top.into(),
174 bottom: padding.bottom.into(),
175 },
176
177 border: Rect {
178 start: border.start.into(),
179 end: border.end.into(),
180 top: border.top.into(),
181 bottom: border.bottom.into(),
182 },
183
184 flex_grow,
185 flex_shrink,
186
187 flex_basis: flex_basis.into(),
188
189 size: Size { width: size.width.into(), height: size.height.into() },
190 min_size: Size { width: min_size.width.into(), height: min_size.height.into() },
191 max_size: Size { width: max_size.width.into(), height: max_size.height.into() },
192
193 aspect_ratio: if f32::is_nan(aspect_ratio) { Number::Undefined } else { Number::Defined(aspect_ratio) },
194 })) as *mut c_void
195}
196
197#[no_mangle]
198pub unsafe extern "C" fn stretch_style_free(style: *mut c_void) {
199 let _style = Box::from_raw(style as *mut Style);
200}
201
202#[no_mangle]
203pub unsafe extern "C" fn stretch_init() -> *mut c_void {
204 let stretch = stretch::node::Stretch::new();
205 Box::into_raw(Box::new(stretch)) as *mut c_void
206}
207
208#[no_mangle]
209pub unsafe extern "C" fn stretch_free(stretch: *mut c_void) {
210 let _stretch = Box::from_raw(stretch as *mut Stretch);
211}
212
213#[no_mangle]
214pub unsafe extern "C" fn stretch_node_create(stretch: *mut c_void, style: *mut c_void) -> *mut c_void {
215 let mut stretch = Box::from_raw(stretch as *mut Stretch);
216 let style = Box::from_raw(style as *mut Style);
217 let node = stretch.new_node(*style, vec![]).unwrap();
218
219 Box::leak(style);
220 Box::leak(stretch);
221
222 Box::into_raw(Box::new(node)) as *mut c_void
223}
224
225#[no_mangle]
226pub unsafe extern "C" fn stretch_node_free(stretch: *mut c_void, node: *mut c_void) {
227 let mut stretch = Box::from_raw(stretch as *mut Stretch);
228 let node = Box::from_raw(node as *mut Node);
229
230 stretch.remove(*node);
231
232 Box::leak(stretch);
233}
234
235#[no_mangle]
236pub unsafe extern "C" fn stretch_node_set_measure(
237 stretch: *mut c_void,
238 node: *mut c_void,
239 swift_ptr: *mut c_void,
240 measure: fn(*const c_void, f32, f32) -> StretchSize,
241) {
242 let mut stretch = Box::from_raw(stretch as *mut Stretch);
243 let node = Box::from_raw(node as *mut Node);
244
245 stretch
246 .set_measure(
247 *node,
248 Some(Box::new(move |constraint| {
249 let size = measure(swift_ptr, constraint.width.or_else(f32::NAN), constraint.height.or_else(f32::NAN));
250 Ok(Size { width: size.width, height: size.height })
251 })),
252 )
253 .unwrap();
254
255 Box::leak(stretch);
256 Box::leak(node);
257}
258
259#[no_mangle]
260pub unsafe extern "C" fn stretch_node_set_style(stretch: *mut c_void, node: *mut c_void, style: *mut c_void) {
261 let mut stretch = Box::from_raw(stretch as *mut Stretch);
262 let node = Box::from_raw(node as *mut Node);
263 let style = Box::from_raw(style as *mut Style);
264
265 stretch.set_style(*node, *style).unwrap();
266
267 Box::leak(stretch);
268 Box::leak(node);
269 Box::leak(style);
270}
271
272#[no_mangle]
273pub unsafe extern "C" fn stretch_node_dirty(stretch: *mut c_void, node: *mut c_void) -> bool {
274 let stretch = Box::from_raw(stretch as *mut Stretch);
275 let node = Box::from_raw(node as *mut Node);
276 let dirty = stretch.dirty(*node).unwrap();
277
278 Box::leak(stretch);
279 Box::leak(node);
280
281 dirty
282}
283
284#[no_mangle]
285pub unsafe extern "C" fn stretch_node_mark_dirty(stretch: *mut c_void, node: *mut c_void) {
286 let mut stretch = Box::from_raw(stretch as *mut Stretch);
287 let node = Box::from_raw(node as *mut Node);
288
289 stretch.mark_dirty(*node).unwrap();
290
291 Box::leak(stretch);
292 Box::leak(node);
293}
294
295#[no_mangle]
296pub unsafe extern "C" fn stretch_node_add_child(stretch: *mut c_void, node: *mut c_void, child: *mut c_void) {
297 let mut stretch = Box::from_raw(stretch as *mut Stretch);
298 let node = Box::from_raw(node as *mut Node);
299 let child = Box::from_raw(child as *mut Node);
300
301 stretch.add_child(*node, *child).unwrap();
302
303 Box::leak(stretch);
304 Box::leak(node);
305 Box::leak(child);
306}
307
308#[no_mangle]
309pub unsafe extern "C" fn stretch_node_replace_child_at_index(
310 stretch: *mut c_void,
311 node: *mut c_void,
312 index: usize,
313 child: *mut c_void,
314) {
315 let mut stretch = Box::from_raw(stretch as *mut Stretch);
316 let node = Box::from_raw(node as *mut Node);
317 let child = Box::from_raw(child as *mut Node);
318
319 stretch.replace_child_at_index(*node, index, *child).unwrap();
320
321 Box::leak(stretch);
322 Box::leak(node);
323 Box::leak(child);
324}
325
326#[no_mangle]
327pub unsafe extern "C" fn stretch_node_remove_child(stretch: *mut c_void, node: *mut c_void, child: *mut c_void) {
328 let mut stretch = Box::from_raw(stretch as *mut Stretch);
329 let node = Box::from_raw(node as *mut Node);
330 let child = Box::from_raw(child as *mut Node);
331
332 stretch.remove_child(*node, *child).unwrap();
333
334 Box::leak(stretch);
335 Box::leak(node);
336 Box::leak(child);
337}
338
339#[no_mangle]
340pub unsafe extern "C" fn stretch_node_remove_child_at_index(stretch: *mut c_void, node: *mut c_void, index: usize) {
341 let mut stretch = Box::from_raw(stretch as *mut Stretch);
342 let node = Box::from_raw(node as *mut Node);
343
344 stretch.remove_child_at_index(*node, index).unwrap();
345
346 Box::leak(stretch);
347 Box::leak(node);
348}
349
350#[no_mangle]
351pub unsafe extern "C" fn stretch_node_compute_layout(
352 stretch: *mut c_void,
353 node: *mut c_void,
354 width: f32,
355 height: f32,
356 create_layout: fn(*const f32) -> *mut c_void,
357) -> *mut c_void {
358 let mut stretch = Box::from_raw(stretch as *mut Stretch);
359 let node = Box::from_raw(node as *mut Node);
360
361 stretch
362 .compute_layout(
363 *node,
364 Size {
365 width: if f32::is_nan(width) { Number::Undefined } else { Number::Defined(width) },
366 height: if f32::is_nan(height) { Number::Undefined } else { Number::Defined(height) },
367 },
368 )
369 .unwrap();
370
371 let mut output = vec![];
372 copy_output(&stretch, *node, &mut output);
373
374 Box::leak(stretch);
375 Box::leak(node);
376
377 create_layout(output.as_ptr())
378}
379
380fn copy_output(stretch: &Stretch, node: Node, output: &mut Vec<f32>) {
381 let layout = stretch.layout(node).unwrap();
382 let children = stretch.children(node).unwrap();
383
384 output.push(layout.location.x);
385 output.push(layout.location.y);
386 output.push(layout.size.width);
387 output.push(layout.size.height);
388 output.push(children.len() as f32);
389
390 for child in &children {
391 copy_output(stretch, *child, output);
392 }
393}