1#![allow(dead_code)]
3
4use crate::kernel::draw::{Color, Screen};
5use crate::kernel::window_mgr::App;
6use alloc::collections::BTreeMap;
7use alloc::collections::VecDeque;
8use alloc::string::String;
9use alloc::vec::Vec;
10use spin::Mutex;
11
12#[derive(Debug, Clone)]
13pub enum DrawCommand {
14 BoxFill {
15 x0: u32,
16 y0: u32,
17 x1: u32,
18 y1: u32,
19 color: u32,
20 },
21 DrawString {
22 x: u32,
23 y: u32,
24 text: String,
25 color: u32,
26 size: u32,
27 },
28 ClearScreen {
29 color: u32,
30 },
31}
32
33pub static CANVAS_QUEUES: Mutex<BTreeMap<String, VecDeque<DrawCommand>>> =
34 Mutex::new(BTreeMap::new());
35pub static CANVAS_ID_COUNTER: Mutex<u32> = Mutex::new(0);
36
37pub struct CanvasApp {
38 pub id: String,
39 pub title: String,
40 pub buffer: Vec<u32>,
41 pub width: u32,
42 pub height: u32,
43}
44
45impl CanvasApp {
46 pub fn new(id: String, title: String, width: u32, height: u32) -> Self {
47 Self {
48 id,
49 title,
50 buffer: alloc::vec![0xFFFFFFFF; (width * height) as usize], width,
52 height,
53 }
54 }
55}
56
57impl App for CanvasApp {
58 fn name(&self) -> &str {
59 &self.title
60 }
61
62 fn draw(&mut self, screen: &Screen, win_x: u32, win_y: u32, win_w: u32, win_h: u32) {
63 if win_w != self.width || win_h != self.height {
65 let mut new_buf = alloc::vec![0xFFFFFFFF; (win_w * win_h) as usize];
66 let min_w = self.width.min(win_w);
67 let min_h = self.height.min(win_h);
68 for y in 0..min_h {
69 let src_offset = (y * self.width) as usize;
70 let dst_offset = (y * win_w) as usize;
71 new_buf[dst_offset..dst_offset + min_w as usize]
72 .copy_from_slice(&self.buffer[src_offset..src_offset + min_w as usize]);
73 }
74 self.buffer = new_buf;
75 self.width = win_w;
76 self.height = win_h;
77 }
78
79 let mut cmds = VecDeque::new();
81 if let Some(q) = CANVAS_QUEUES.lock().get_mut(&self.id) {
82 cmds = core::mem::take(q);
83 }
84
85 if !cmds.is_empty() {
87 let temp_screen = Screen::new(
88 self.buffer.as_mut_ptr(),
89 self.width,
90 self.height,
91 self.width * 4,
92 );
93 for cmd in cmds {
94 match cmd {
95 DrawCommand::BoxFill {
96 x0,
97 y0,
98 x1,
99 y1,
100 color,
101 } => {
102 temp_screen.boxfill(x0, y0, x1, y1, Color(color));
103 }
104 DrawCommand::DrawString {
105 x,
106 y,
107 text,
108 color,
109 size,
110 } => {
111 temp_screen.draw_string_vector(x, y, &text, Color(color), size);
112 }
113 DrawCommand::ClearScreen { color } => {
114 temp_screen.boxfill(
115 0,
116 0,
117 self.width.saturating_sub(1),
118 self.height.saturating_sub(1),
119 Color(color),
120 );
121 }
122 }
123 }
124 }
125
126 let (target_ptr, dw, dh) = screen.resolve_target();
128 let stride = screen.resolve_stride();
129
130 let (cx0, cy0, cx1, cy1) = screen.clip.get().unwrap_or((0, 0, dw, dh));
131
132 let x0 = win_x.max(cx0).min(dw);
133 let y0 = win_y.max(cy0).min(dh);
134 let x1 = (win_x + win_w).min(cx1).min(dw);
135 let y1 = (win_y + win_h).min(cy1).min(dh);
136
137 if x1 > x0 && y1 > y0 {
138 let copy_w = x1 - x0;
139 for y in y0..y1 {
140 let src_y = y - win_y;
141 let src_x = x0 - win_x;
142 unsafe {
143 let src_ptr = self.buffer.as_ptr().add((src_y * win_w + src_x) as usize);
144 let dst_ptr = target_ptr.add((y * stride + x0) as usize);
145 core::ptr::copy_nonoverlapping(src_ptr, dst_ptr, copy_w as usize);
146 }
147 }
148 }
149 }
150
151 fn on_mouse(
152 &mut self,
153 _local_x: i32,
154 _local_y: i32,
155 _btn_left: bool,
156 _btn_right: bool,
157 _wheel: i32,
158 ) {
159 }
160
161 fn on_key(&mut self, _keycode: u8, _pressed: bool, _ascii: Option<char>) {}
162}