1#![allow(non_upper_case_globals)]
2#![allow(non_camel_case_types)]
3#![allow(non_snake_case)]
4
5extern crate num;
6#[macro_use]
7extern crate num_derive;
8
9extern crate num_traits;
10
11use std::{
12 alloc::{self, Layout},
13 cmp,
14 ffi::CString,
15 io::Cursor,
16 mem,
17 sync::{Arc, Mutex},
18};
19use std::{
20 convert::{TryFrom, TryInto},
21 ffi::CStr,
22 panic,
23 time::Duration,
24};
25use tinybmp::{Bmp, FileType, Header, Pixel};
26pub mod c_api;
27use c_api::{ibitmap, ifont};
28
29#[derive(Debug, Copy, Clone)]
30pub struct Color(pub i32);
31
32impl Color {
33 pub const fn rgb(red: u8, green: u8, blue: u8) -> Self {
34 Self(((blue as i32) << 16) + ((green as i32) << 8) + red as i32)
35 }
36
37 pub const fn gs(intensity: u8) -> Self {
38 Self(intensity as i32 * 0x010101)
39 }
40
41 pub const WHITE: Self = Self(c_api::WHITE);
42 pub const LGRAY: Self = Self(c_api::LGRAY);
43 pub const DGRAY: Self = Self(c_api::DGRAY);
44 pub const BLACK: Self = Self(c_api::BLACK);
45}
46
47
48pub struct PbBmp(pub *mut ibitmap);
49
50impl PbBmp {
51 pub fn get_pointer(&self) -> *mut ibitmap{
52 self.0
53 }
54}
55
56impl From<Bmp<'_>> for PbBmp {
57 fn from(bmp: Bmp<'_>) -> Self {
58 let bmp_width = bmp.header.image_width;
59 let bmp_height = bmp.header.image_height;
60 let pixels = bmp.image_data();
61
62 let layout = Layout::from_size_align(
63 mem::size_of::<ibitmap>() + pixels.len() * mem::size_of::<u8>(),
64 cmp::max(mem::align_of::<u8>(), mem::align_of::<ibitmap>()),
65 )
66 .unwrap();
67
68 let bmp_struct = unsafe { alloc::alloc(layout) } as *mut ibitmap;
69 unsafe {
70 (*bmp_struct).width = bmp_width as u16;
71 (*bmp_struct).height = bmp_height as u16;
72 (*bmp_struct).depth = bmp.header.bpp;
73 (*bmp_struct).scanline = bmp.header.image_data_len as u16 / bmp_width as u16;
74 (*bmp_struct)
75 .data
76 .as_mut_ptr()
77 .copy_from_nonoverlapping(pixels.as_ptr(), pixels.len());
78 }
79 PbBmp(bmp_struct)
80 }
81}
82
83
84#[macro_export]
85macro_rules! include_bmp {
86 ($expression:expr) => {{
87 Bmp::from_slice(include_bytes!($expression)).expect("Failed to parse BMP image")
88
89 }};
90}
91
92pub fn scale_bitmap_to(bmp: *mut ibitmap, w: i32, h: i32) -> *mut ibitmap {
93 unsafe { c_api::BitmapStretchCopy(bmp, 0, 0, (*bmp).width as i32, (*bmp).height as i32, w, h) }
94}
95
96
97pub fn mirror_bitmap(bmp: *mut ibitmap, mirror_flags: i32) {
98 unsafe { c_api::MirrorBitmap(bmp, mirror_flags) }
99}
100
101pub trait EventHandler {
102 fn handle_event(&mut self, event: c_api::Event, par1: i32, par2: i32) -> i32;
103}
104
105static mut iv_event_handler: Option<Arc<Mutex<dyn EventHandler>>> = None;
106extern "C" fn iv_event_handler_wrapper(event: i32, par1: i32, par2: i32) -> i32 {
107 unsafe {
108 match iv_event_handler {
109 Some(ref mut event_handler) => {
110 if let Some(event) = num::FromPrimitive::from_i32(event) {
111 let result = panic::catch_unwind(|| {
112 event_handler
113 .lock()
114 .expect("Event handler is locked")
115 .handle_event(event, par1, par2)
116 });
117
118 match result {
119 Ok(v) => v,
120 Err(err) => {
121 message(c_api::Icon::ERROR, "Panic", &format!("{:?}", err), 10000);
122
123 std::thread::sleep(Duration::from_secs(10));
124 -2
125 }
126 }
127 } else {
128 -1
129 }
130 }
131 None => -2,
132 }
133 }
134}
135
136pub fn main(event_handler: &Arc<Mutex<dyn EventHandler>>) {
137 unsafe {
138 iv_event_handler = Some(Arc::clone(event_handler));
139 c_api::InkViewMain(Some(iv_event_handler_wrapper));
140 }
141}
142pub fn exit() {
144 unsafe {
145 c_api::CloseApp();
146 }
147}
148
149pub fn repaint() {
151 unsafe {
152 c_api::CloseApp();
153 }
154}
155
156pub type Dither = c_api::Dither;
160
161pub fn screen_width() -> i32 {
162 unsafe { c_api::ScreenWidth() }
163}
164
165pub fn screen_height() -> i32 {
166 unsafe { c_api::ScreenHeight() }
167}
168
169#[repr(i32)]
170pub enum Orientation{
171 Portrait = 0,
172 Landscape90 = 1,
173 Landscape270 = 2,
174 Portrait180 = 3,
175 Auto = -1
176}
177
178pub fn set_orientation(orientation: Orientation){
179 unsafe{
180 c_api::SetOrientation(orientation as i32)
181 }
182}
183
184pub fn get_orientation() -> Orientation{
185 let orientation = unsafe{
186 c_api::GetOrientation()
187 };
188
189 todo!()
190}
191
192
193pub fn panel_height() -> i32 {
194 unsafe { c_api::PanelHeight() }
195}
196
197pub fn clear_screen() {
198 unsafe {
199 c_api::ClearScreen();
200 }
201}
202
203pub fn set_clip(x: i32, y: i32, w: i32, h: i32) {
204 unsafe {
205 c_api::SetClip(x, y, w, h);
206 }
207}
208
209pub fn draw_pixel(x: i32, y: i32, color: Color) {
210 unsafe {
211 c_api::DrawPixel(x, y, color.0);
212 }
213}
214
215pub fn draw_line(x1: i32, y1: i32, x2: i32, y2: i32, color: Color) {
216 unsafe {
217 c_api::DrawLine(x1, y1, x2, y2, color.0);
218 }
219}
220
221pub fn draw_dot_line(x1: i32, y1: i32, x2: i32, y2: i32, color: Color, step: i32) {
222 unsafe {
223 c_api::DrawLineEx(x1, y1, x2, y2, color.0, step);
224 }
225}
226
227#[cfg(feature = "sdk_v6")]
228pub fn draw_dash_line(x1: i32, y1: i32, x2: i32, y2: i32, color: Color, fill: u32, space: u32) {
229 unsafe {
230 c_api::DrawDashLine(x1, y1, x2, y2, color.0, fill, space);
231 }
232}
233
234pub fn draw_rect(x: i32, y: i32, w: i32, h: i32, color: Color) {
235 unsafe {
236 c_api::DrawRect(x, y, w, h, color.0);
237 }
238}
239
240pub fn draw_rect_round(x: i32, y: i32, w: i32, h: i32, color: Color, radius: i32) {
241 unsafe {
242 c_api::DrawRectRound(x, y, w, h, color.0, radius);
243 }
244}
245
246pub fn fill_area(x: i32, y: i32, w: i32, h: i32, color: Color) {
247 unsafe {
248 c_api::FillArea(x, y, w, h, color.0);
249 }
250}
251
252pub fn invert_area(x: i32, y: i32, w: i32, h: i32) {
253 unsafe {
254 c_api::InvertArea(x, y, w, h);
255 }
256}
257
258pub fn invert_area_bw(x: i32, y: i32, w: i32, h: i32) {
259 unsafe {
260 c_api::InvertAreaBW(x, y, w, h);
261 }
262}
263
264pub fn dim_area(x: i32, y: i32, w: i32, h: i32, color: Color) {
265 unsafe {
266 c_api::DimArea(x, y, w, h, color.0);
267 }
268}
269
270pub fn draw_selection(x: i32, y: i32, w: i32, h: i32, color: Color) {
271 unsafe {
272 c_api::DrawSelection(x, y, w, h, color.0);
273 }
274}
275
276pub fn draw_circle(x: i32, y: i32, radius: i32, color: Color) {
277 unsafe {
278 c_api::DrawCircle(x, y, radius, color.0);
279 }
280}
281
282pub fn draw_bitmap(x: i32, y: i32, bmp: *mut ibitmap) {
283 unsafe {
284 c_api::DrawBitmap(
285 x,
286 y,
287 bmp,
288 );
289 }
290}
291
292pub fn draw_pick_out(x: i32, y: i32, w: i32, h: i32, key: &str) {
294 let c_key = CString::new(key).expect("CString::new failed").into_raw();
295 unsafe {
296 c_api::DrawPickOut(x, y, w, h, c_key);
297 }
298}
299
300pub fn dither_area(x: i32, y: i32, w: i32, h: i32, levels: i32, method: Dither) {
301 unsafe {
302 c_api::DitherArea(x, y, w, h, levels, method as i32);
303 }
304}
305
306pub fn dither_area_quick_2level(x: i32, y: i32, w: i32, h: i32) {
307 unsafe {
308 c_api::DitherAreaQuick2Level(x, y, w, h);
309 }
310}
311
312#[cfg(feature = "sdk_v6")]
313pub fn dither_area_pattern_2level(x: i32, y: i32, w: i32, h: i32) {
314 unsafe {
315 c_api::DitherAreaPattern2Level(x, y, w, h);
316 }
317}
318
319pub fn draw_diagonal_hatch(x: i32, y: i32, w: i32, h: i32, step: i32, color: Color) {
320 unsafe {
321 c_api::DrawDiagonalHatch(x, y, w, h, step, color.0);
322 }
323}
324
325pub fn transparent(x: i32, y: i32, w: i32, h: i32, percent: i32) {
326 unsafe {
327 c_api::Transparent(x, y, w, h, percent);
328 }
329}
330
331
332#[derive(Clone, Copy)]
333pub struct Font(pub *mut ifont);
334
335pub fn open_font(name: &str, size: i32, aa: i32) -> Font {
337 Font(unsafe { c_api::OpenFont(CString::new(name).unwrap().into_raw(), size, aa) })
338}
339
340pub fn set_font(font: Font, color: Color) {
341 unsafe { c_api::SetFont(font.0, color.0.into()) }
342}
343
344pub fn text_rect_height(width: i32, string: &str, flags: i32) -> i32{
345 return unsafe { c_api::TextRectHeight(width, CString::new(string).unwrap().into_raw(), flags) }
346}
347
348
349pub fn draw_text_rect(x: i32, y: i32, w: i32, h: i32, s: &str, flags: i32) -> String {
350 unsafe {
351 CStr::from_ptr(c_api::DrawTextRect(
352 x,
353 y,
354 w,
355 h,
356 CString::new(s).unwrap().into_raw(),
357 flags,
358 ))
359 .to_string_lossy()
360 .into()
361 }
362}
363
364pub fn full_update() {
368 unsafe {
369 c_api::FullUpdate();
370 }
371}
372
373pub fn soft_update() {
374 unsafe {
375 c_api::FullUpdate();
376 }
377}
378
379pub fn partial_update(x: i32, y: i32, w: i32, h: i32) {
380 unsafe {
381 c_api::PartialUpdate(x, y, w, h);
382 }
383}
384
385pub type PanelType = c_api::PanelType;
391pub fn panel_type() -> PanelType {
394 unsafe {
395 {
396 c_api::GetPanelType().try_into().unwrap()
397 }
398 }
399}
400
401pub fn set_panel_type(panel_type: PanelType) {
402 unsafe {
403 c_api::SetPanelType(panel_type.0 as i32);
404 }
405}
406
407pub fn message(icon: c_api::Icon, title: &str, text: &str, timeout: i32) {
408 unsafe {
409 c_api::Message(
410 icon as i32,
411 CString::new(title).unwrap().into_raw(),
412 CString::new(text).unwrap().into_raw(),
413 timeout,
414 )
415 }
416}
417
418
419#[repr(i32)]
420#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
421pub enum TextAlignFlag{
422 ALIGN_LEFT = c_api::ALIGN_LEFT,
423 ALIGN_CENTER = c_api::ALIGN_CENTER,
424 ALIGN_RIGHT = c_api::ALIGN_RIGHT,
425 ALIGN_FIT = c_api::ALIGN_FIT,
426 VALIGN_TOP = c_api::VALIGN_TOP,
427 VALIGN_MIDDLE = c_api::VALIGN_MIDDLE,
428 VALIGN_BOTTOM = c_api::VALIGN_BOTTOM
429}
430#[repr(i32)]
431#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
432pub enum MirrorFlag{
433 X_MIRROR = c_api::XMIRROR,
434 Y_MIRROR = c_api::YMIRROR
435}
436