tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1118HTML 1044Markdown 12TOML 94787 Definitions

⎇ bce89b1006f36ce35abfaf1f1c2b3dd95f3dffd3 bindings/swift/StretchCore/src/lib.rs Rust · 393 lines · 10.7 KB History Who touched what raw

Implement new rust API for bindings and release v0.3 bce89b100 · Emil Sjölander ·

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}