1#![allow(non_camel_case_types)]
16#![allow(non_snake_case)]
17#![allow(dead_code)]
18
19use libc::{c_char, c_double, c_float, c_uchar, c_uint, c_void, size_t};
20
21#[repr(C)]
23pub struct MLNMap {
24 _private: [u8; 0],
25}
26
27#[repr(C)]
29pub struct MLNHeadlessFrontend {
30 _private: [u8; 0],
31}
32
33#[repr(C)]
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum MLNErrorCode {
37 MLN_OK = 0,
38 MLN_ERROR_INVALID_ARGUMENT = 1,
39 MLN_ERROR_STYLE_PARSE = 2,
40 MLN_ERROR_RENDER_FAILED = 3,
41 MLN_ERROR_NOT_LOADED = 4,
42 MLN_ERROR_TIMEOUT = 5,
43 MLN_ERROR_UNKNOWN = 99,
44}
45
46#[repr(C)]
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49pub enum MLNMapMode {
50 MLN_MAP_MODE_STATIC = 0,
51 MLN_MAP_MODE_TILE = 1,
52}
53
54#[repr(C)]
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub enum MLNDebugOptions {
58 MLN_DEBUG_NONE = 0,
59 MLN_DEBUG_TILE_BORDERS = 1,
60 MLN_DEBUG_PARSE_STATUS = 2,
61 MLN_DEBUG_TIMESTAMPS = 4,
62 MLN_DEBUG_COLLISION = 8,
63 MLN_DEBUG_OVERDRAW = 16,
64}
65
66#[repr(C)]
68#[derive(Debug, Clone, Copy, Default)]
69pub struct MLNSize {
70 pub width: c_uint,
71 pub height: c_uint,
72}
73
74impl MLNSize {
75 pub fn new(width: u32, height: u32) -> Self {
76 Self { width, height }
77 }
78}
79
80#[repr(C)]
82#[derive(Debug, Clone, Copy, Default)]
83pub struct MLNCameraOptions {
84 pub latitude: c_double,
85 pub longitude: c_double,
86 pub zoom: c_double,
87 pub bearing: c_double,
88 pub pitch: c_double,
89}
90
91impl MLNCameraOptions {
92 pub fn new(latitude: f64, longitude: f64, zoom: f64) -> Self {
93 Self {
94 latitude,
95 longitude,
96 zoom,
97 bearing: 0.0,
98 pitch: 0.0,
99 }
100 }
101
102 pub fn with_bearing(mut self, bearing: f64) -> Self {
103 self.bearing = bearing;
104 self
105 }
106
107 pub fn with_pitch(mut self, pitch: f64) -> Self {
108 self.pitch = pitch;
109 self
110 }
111}
112
113#[repr(C)]
115#[derive(Debug, Clone, Copy)]
116pub struct MLNRenderOptions {
117 pub size: MLNSize,
118 pub pixel_ratio: c_float,
119 pub camera: MLNCameraOptions,
120 pub mode: MLNMapMode,
121 pub debug: MLNDebugOptions,
122}
123
124impl Default for MLNRenderOptions {
125 fn default() -> Self {
126 Self {
127 size: MLNSize::new(512, 512),
128 pixel_ratio: 1.0,
129 camera: MLNCameraOptions::default(),
130 mode: MLNMapMode::MLN_MAP_MODE_TILE,
131 debug: MLNDebugOptions::MLN_DEBUG_NONE,
132 }
133 }
134}
135
136#[repr(C)]
138#[derive(Debug)]
139pub struct MLNImageData {
140 pub data: *mut c_uchar,
142 pub data_len: size_t,
144 pub width: c_uint,
146 pub height: c_uint,
148}
149
150impl Default for MLNImageData {
151 fn default() -> Self {
152 Self {
153 data: std::ptr::null_mut(),
154 data_len: 0,
155 width: 0,
156 height: 0,
157 }
158 }
159}
160
161#[repr(C)]
163#[derive(Debug)]
164pub struct MLNResourceRequest {
165 pub url: *const c_char,
166 pub kind: c_uchar,
168}
169
170#[repr(C)]
172#[derive(Debug)]
173pub struct MLNResourceResponse {
174 pub data: *const c_uchar,
175 pub data_len: size_t,
176 pub error: *const c_char,
178 pub not_found: bool,
180}
181
182impl Default for MLNResourceResponse {
183 fn default() -> Self {
184 Self {
185 data: std::ptr::null(),
186 data_len: 0,
187 error: std::ptr::null(),
188 not_found: false,
189 }
190 }
191}
192
193pub type MLNRenderCallback = Option<
195 unsafe extern "C" fn(error: MLNErrorCode, image: *mut MLNImageData, user_data: *mut c_void),
196>;
197
198pub type MLNResourceCallback = Option<
200 unsafe extern "C" fn(
201 request: *const MLNResourceRequest,
202 response: *mut MLNResourceResponse,
203 user_data: *mut c_void,
204 ),
205>;
206
207unsafe extern "C" {
211 pub fn mln_init() -> MLNErrorCode;
213
214 pub fn mln_cleanup();
216
217 pub fn mln_headless_frontend_create(
219 size: MLNSize,
220 pixel_ratio: c_float,
221 ) -> *mut MLNHeadlessFrontend;
222
223 pub fn mln_headless_frontend_destroy(frontend: *mut MLNHeadlessFrontend);
225
226 pub fn mln_headless_frontend_set_size(frontend: *mut MLNHeadlessFrontend, size: MLNSize);
228
229 pub fn mln_headless_frontend_get_size(frontend: *mut MLNHeadlessFrontend) -> MLNSize;
231
232 pub fn mln_map_create(
234 frontend: *mut MLNHeadlessFrontend,
235 pixel_ratio: c_float,
236 mode: MLNMapMode,
237 ) -> *mut MLNMap;
238
239 pub fn mln_map_create_with_loader(
241 frontend: *mut MLNHeadlessFrontend,
242 pixel_ratio: c_float,
243 mode: MLNMapMode,
244 request_callback: MLNResourceCallback,
245 user_data: *mut c_void,
246 ) -> *mut MLNMap;
247
248 pub fn mln_map_destroy(map: *mut MLNMap);
250
251 pub fn mln_map_load_style(map: *mut MLNMap, style_json: *const c_char) -> MLNErrorCode;
253
254 pub fn mln_map_load_style_url(map: *mut MLNMap, url: *const c_char) -> MLNErrorCode;
256
257 pub fn mln_map_is_fully_loaded(map: *mut MLNMap) -> bool;
259
260 pub fn mln_map_set_camera(map: *mut MLNMap, camera: *const MLNCameraOptions);
262
263 pub fn mln_map_get_camera(map: *mut MLNMap) -> MLNCameraOptions;
265
266 pub fn mln_map_set_size(map: *mut MLNMap, size: MLNSize);
268
269 pub fn mln_map_set_debug(map: *mut MLNMap, options: MLNDebugOptions);
271
272 pub fn mln_map_render_still(
274 map: *mut MLNMap,
275 options: *const MLNRenderOptions,
276 image: *mut MLNImageData,
277 ) -> MLNErrorCode;
278
279 pub fn mln_map_render_still_async(
281 map: *mut MLNMap,
282 options: *const MLNRenderOptions,
283 callback: MLNRenderCallback,
284 user_data: *mut c_void,
285 );
286
287 pub fn mln_image_free(image: *mut MLNImageData);
289
290 pub fn mln_get_last_error() -> *const c_char;
292
293 pub fn mln_map_add_image(
295 map: *mut MLNMap,
296 id: *const c_char,
297 data: *const c_uchar,
298 width: c_uint,
299 height: c_uint,
300 pixel_ratio: c_float,
301 sdf: bool,
302 ) -> MLNErrorCode;
303
304 pub fn mln_map_remove_image(map: *mut MLNMap, id: *const c_char) -> MLNErrorCode;
306
307 pub fn mln_set_base_path(path: *const c_char);
309
310 pub fn mln_set_api_key(key: *const c_char);
312}
313
314pub mod resource_kind {
316 pub const UNKNOWN: u8 = 0;
317 pub const STYLE: u8 = 1;
318 pub const SOURCE: u8 = 2;
319 pub const TILE: u8 = 3;
320 pub const GLYPHS: u8 = 4;
321 pub const SPRITE_IMAGE: u8 = 5;
322 pub const SPRITE_JSON: u8 = 6;
323}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328
329 #[test]
330 fn test_size_layout() {
331 assert_eq!(std::mem::size_of::<MLNSize>(), 8);
332 }
333
334 #[test]
335 fn test_camera_options() {
336 let camera = MLNCameraOptions::new(37.8, -122.4, 12.0)
337 .with_bearing(45.0)
338 .with_pitch(30.0);
339
340 assert_eq!(camera.latitude, 37.8);
341 assert_eq!(camera.longitude, -122.4);
342 assert_eq!(camera.zoom, 12.0);
343 assert_eq!(camera.bearing, 45.0);
344 assert_eq!(camera.pitch, 30.0);
345 }
346}