1extern crate blockish;
2extern crate crossterm;
3extern crate redhook;
4use blockish::ThreadedEngine;
5use gag::Gag;
6use std::env;
7use std::slice;
8
9#[repr(C)]
10#[derive(Debug, Copy, Clone)]
11pub struct caca_display {
12 _unused: [u8; 0],
13}
14#[doc = " \\e libcaca display context"]
15pub type CacaDisplayT = caca_display;
16#[repr(C)]
17#[derive(Debug, Copy, Clone)]
18pub struct caca_canvas {
19 _unused: [u8; 0],
20}
21#[doc = " \\e libcaca canvas"]
22pub type CacaCanvasT = caca_canvas;
23#[repr(C)]
24#[derive(Debug, Copy, Clone)]
25pub struct caca_dither {
26 _unused: [u8; 0],
27}
28#[doc = " dither structure"]
29pub type CacaDitherT = caca_dither;
30
31static mut WIDTH: i32 = 0;
32static mut HEIGHT: i32 = 0;
33static mut BYTES_PER_PIXEL: u32 = 0;
34static mut TERMINAL_WIDTH: i32 = 0;
35static mut TERMINAL_HEIGHT: i32 = 0;
36static mut TERMINAL_SIZE_CHANGED: bool = false;
37
38static mut ENGINE: Option<blockish::ThreadedEngine> = None;
39
40redhook::hook! {
41 unsafe fn caca_dither_bitmap(
42 _arg1: *mut CacaCanvasT,
43 _arg2: ::std::os::raw::c_int,
44 _arg3: ::std::os::raw::c_int,
45 _width: ::std::os::raw::c_int,
46 _height: ::std::os::raw::c_int,
47 _arg6: *const CacaDitherT,
48 data: *const ::std::os::raw::c_uchar
49 ) -> ::std::os::raw::c_int => my_caca_dither_bitmap {
50 let mut bwidth = 80;
51 let mut bheight = 20;
52 if let Ok(columns_string) = env::var("COLUNMS") {
53 if let Ok(columns) = columns_string.parse() {
54 bwidth = columns;
55 if TERMINAL_WIDTH != columns {
56 TERMINAL_WIDTH = columns;
57 TERMINAL_SIZE_CHANGED = true;
58 }
59 }
60 }
61 if let Ok(lines_string) = env::var("LINES") {
62 if let Ok(lines) = lines_string.parse() {
63 bheight = lines;
64 if TERMINAL_HEIGHT != lines {
65 TERMINAL_HEIGHT = lines;
66 TERMINAL_SIZE_CHANGED = true;
67 }
68 }
69 }
70 match crossterm::terminal::size() {
71 Ok(res) => {
72 bwidth = res.0 as i32;
73 bheight = res.1 as i32;
74 if bwidth != TERMINAL_WIDTH || bheight != TERMINAL_HEIGHT {
75 TERMINAL_SIZE_CHANGED = true;
76 }
77 TERMINAL_WIDTH = bwidth;
78 TERMINAL_HEIGHT = bheight;
79 }
80 Err(_) => {
81 }
82 }
83 let width = bwidth as u32 * 8;
84 let height = bheight as u32 * 16 - 1;
85 if TERMINAL_SIZE_CHANGED {
86 ENGINE = Some(ThreadedEngine::new(width as u32, height as u32, true));
87 }
88 let original_width : u32 = WIDTH as u32;
89 let original_height : u32 = HEIGHT as u32;
90 print!("\x1b[{};0f", 1);
91 let raw_slice = slice::from_raw_parts(data, (original_width * original_height * BYTES_PER_PIXEL) as usize);
92 match &mut ENGINE {
93 Some(engine) => {
94 engine.render(&|x, y| {
95 let start = (( ((y * original_height / height) * original_width as u32 + (x * original_width / width) ) * BYTES_PER_PIXEL)) as usize;
96 let b = (raw_slice[start]) as u8;
97 let g = (raw_slice[start + 1]) as u8;
98 let r = (raw_slice[start + 2]) as u8;
99 (r, g, b, 0)
100 });
101 }
102 None => {}
103 };
104 0
105 }
106}
107
108redhook::hook! {
109unsafe fn caca_refresh_display(arg1: *mut CacaDisplayT) -> ::std::os::raw::c_int => my_caca_refresh_display {
110 {
111 let _print_gag = Gag::stdout().unwrap();
112 redhook::real!(caca_refresh_display)(arg1)
113 }
114 }
115}
116
117redhook::hook! {
118 unsafe fn caca_create_dither(
119 _arg1: ::std::os::raw::c_int,
120 _arg2: ::std::os::raw::c_int,
121 _arg3: ::std::os::raw::c_int,
122 _arg4: ::std::os::raw::c_int,
123 _arg5: u32,
124 _arg6: u32,
125 _arg7: u32,
126 _arg8: u32
127 ) -> *mut CacaDitherT => my_caca_create_dither {
128 let res = redhook::real!(caca_create_dither)(_arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8);
129 WIDTH=_arg2;
130 HEIGHT=_arg3;
131 BYTES_PER_PIXEL=_arg1 as u32 / 8;
132 res
133 }
134}