inkview_sys/
lib.rs

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}
142/// Put Event::EXIT into applications event queue and closes the application.
143pub fn exit() {
144    unsafe {
145        c_api::CloseApp();
146    }
147}
148
149/// Put Event::SHOW into applications event queue.
150pub fn repaint() {
151    unsafe {
152        c_api::CloseApp();
153    }
154}
155
156////////////////////////////////////////////////////////////////////////////////
157// Graphic functions
158
159pub 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
292// Выделение текста
293pub 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
335// Text functions
336pub 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
364////////////////////////////////////////////////////////////////////////////////
365// Screen update
366
367pub 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
385////////////////////////////////////////////////////////////////////////////////
386// UI functions
387
388//pub type Icon = c_api::Icon;                /// Dialog icons
389//pub type Button = c_api::Button;            /// Dialog buttons
390pub type PanelType = c_api::PanelType;
391/// InkView header panel control flags
392
393pub 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