|
| 1 | +//! Graphics demonstration module. |
| 2 | +//! |
| 3 | +//! Provides a visual demo of the graphics stack capabilities |
| 4 | +//! that runs during kernel boot. |
| 5 | +
|
| 6 | +use super::font::Font; |
| 7 | +use super::primitives::{ |
| 8 | + draw_circle, draw_line, draw_rect, draw_text, fill_circle, fill_rect, Canvas, Color, Rect, |
| 9 | + TextStyle, |
| 10 | +}; |
| 11 | + |
| 12 | +/// Run a graphics demonstration on the given canvas. |
| 13 | +/// |
| 14 | +/// This draws various shapes and text to showcase the graphics stack. |
| 15 | +pub fn run_demo(canvas: &mut impl Canvas) { |
| 16 | + let width = canvas.width() as i32; |
| 17 | + let height = canvas.height() as i32; |
| 18 | + |
| 19 | + // Clear to a dark blue background |
| 20 | + fill_rect( |
| 21 | + canvas, |
| 22 | + Rect { |
| 23 | + x: 0, |
| 24 | + y: 0, |
| 25 | + width: width as u32, |
| 26 | + height: height as u32, |
| 27 | + }, |
| 28 | + Color::rgb(20, 30, 50), |
| 29 | + ); |
| 30 | + |
| 31 | + // Draw a header banner |
| 32 | + fill_rect( |
| 33 | + canvas, |
| 34 | + Rect { |
| 35 | + x: 0, |
| 36 | + y: 0, |
| 37 | + width: width as u32, |
| 38 | + height: 60, |
| 39 | + }, |
| 40 | + Color::rgb(40, 80, 120), |
| 41 | + ); |
| 42 | + |
| 43 | + // Title text |
| 44 | + let title_style = TextStyle::new() |
| 45 | + .with_color(Color::WHITE) |
| 46 | + .with_font(Font::default_font()); |
| 47 | + |
| 48 | + draw_text(canvas, 20, 20, "Breenix Graphics Stack Demo", &title_style); |
| 49 | + |
| 50 | + // Draw colorful rectangles |
| 51 | + let colors = [ |
| 52 | + Color::RED, |
| 53 | + Color::GREEN, |
| 54 | + Color::BLUE, |
| 55 | + Color::rgb(255, 255, 0), // Yellow |
| 56 | + Color::rgb(255, 0, 255), // Magenta |
| 57 | + Color::rgb(0, 255, 255), // Cyan |
| 58 | + ]; |
| 59 | + |
| 60 | + let box_width = 80; |
| 61 | + let box_height = 60; |
| 62 | + let start_x = 50; |
| 63 | + let start_y = 100; |
| 64 | + |
| 65 | + for (i, &color) in colors.iter().enumerate() { |
| 66 | + let x = start_x + (i as i32 % 3) * (box_width + 20); |
| 67 | + let y = start_y + (i as i32 / 3) * (box_height + 20); |
| 68 | + |
| 69 | + // Filled rectangle |
| 70 | + fill_rect( |
| 71 | + canvas, |
| 72 | + Rect { |
| 73 | + x, |
| 74 | + y, |
| 75 | + width: box_width as u32, |
| 76 | + height: box_height as u32, |
| 77 | + }, |
| 78 | + color, |
| 79 | + ); |
| 80 | + |
| 81 | + // White border |
| 82 | + draw_rect( |
| 83 | + canvas, |
| 84 | + Rect { |
| 85 | + x: x - 2, |
| 86 | + y: y - 2, |
| 87 | + width: (box_width + 4) as u32, |
| 88 | + height: (box_height + 4) as u32, |
| 89 | + }, |
| 90 | + Color::WHITE, |
| 91 | + ); |
| 92 | + } |
| 93 | + |
| 94 | + // Draw circles section |
| 95 | + let circle_y = start_y + 180; |
| 96 | + let circle_text_style = TextStyle::new().with_color(Color::rgb(200, 200, 200)); |
| 97 | + |
| 98 | + draw_text(canvas, 50, circle_y, "Circles:", &circle_text_style); |
| 99 | + |
| 100 | + // Filled circles |
| 101 | + fill_circle(canvas, 100, circle_y + 60, 30, Color::rgb(255, 100, 100)); |
| 102 | + fill_circle(canvas, 180, circle_y + 60, 25, Color::rgb(100, 255, 100)); |
| 103 | + fill_circle(canvas, 250, circle_y + 60, 20, Color::rgb(100, 100, 255)); |
| 104 | + |
| 105 | + // Circle outlines |
| 106 | + draw_circle(canvas, 340, circle_y + 60, 35, Color::WHITE); |
| 107 | + draw_circle(canvas, 340, circle_y + 60, 25, Color::rgb(255, 200, 0)); |
| 108 | + draw_circle(canvas, 340, circle_y + 60, 15, Color::rgb(255, 100, 0)); |
| 109 | + |
| 110 | + // Draw lines section |
| 111 | + let lines_y = circle_y + 130; |
| 112 | + draw_text(canvas, 50, lines_y, "Lines:", &circle_text_style); |
| 113 | + |
| 114 | + // Draw radiating lines (pre-computed approximate directions) |
| 115 | + // Using 12 directions at 30-degree increments |
| 116 | + let center_x = 150; |
| 117 | + let center_y = lines_y + 60; |
| 118 | + let radius = 50i32; |
| 119 | + |
| 120 | + // Pre-computed (cos, sin) * 100 for angles 0, 30, 60, ..., 330 degrees |
| 121 | + let directions: [(i32, i32); 12] = [ |
| 122 | + (100, 0), // 0° |
| 123 | + (87, 50), // 30° |
| 124 | + (50, 87), // 60° |
| 125 | + (0, 100), // 90° |
| 126 | + (-50, 87), // 120° |
| 127 | + (-87, 50), // 150° |
| 128 | + (-100, 0), // 180° |
| 129 | + (-87, -50), // 210° |
| 130 | + (-50, -87), // 240° |
| 131 | + (0, -100), // 270° |
| 132 | + (50, -87), // 300° |
| 133 | + (87, -50), // 330° |
| 134 | + ]; |
| 135 | + |
| 136 | + for (i, (dx, dy)) in directions.iter().enumerate() { |
| 137 | + let end_x = center_x + (radius * dx) / 100; |
| 138 | + let end_y = center_y + (radius * dy) / 100; |
| 139 | + let intensity = ((i as u32 * 255) / 12) as u8; |
| 140 | + let color = Color::rgb(255, intensity, 255 - intensity); |
| 141 | + draw_line(canvas, center_x, center_y, end_x, end_y, color); |
| 142 | + } |
| 143 | + |
| 144 | + // Draw diagonal lines |
| 145 | + for i in 0..10 { |
| 146 | + let x1 = 280 + i * 8; |
| 147 | + let color = Color::rgb(50 + i as u8 * 20, 100 + i as u8 * 15, 200); |
| 148 | + draw_line(canvas, x1, lines_y + 20, x1 + 60, lines_y + 100, color); |
| 149 | + } |
| 150 | + |
| 151 | + // Text rendering showcase |
| 152 | + let text_y = lines_y + 140; |
| 153 | + draw_text(canvas, 50, text_y, "Text Rendering:", &circle_text_style); |
| 154 | + |
| 155 | + // Different colored text |
| 156 | + let red_style = TextStyle::new().with_color(Color::RED); |
| 157 | + let green_style = TextStyle::new().with_color(Color::GREEN); |
| 158 | + let blue_style = TextStyle::new().with_color(Color::BLUE); |
| 159 | + let yellow_style = TextStyle::new().with_color(Color::rgb(255, 255, 0)); |
| 160 | + |
| 161 | + draw_text(canvas, 50, text_y + 30, "Red Text", &red_style); |
| 162 | + draw_text(canvas, 150, text_y + 30, "Green Text", &green_style); |
| 163 | + draw_text(canvas, 270, text_y + 30, "Blue Text", &blue_style); |
| 164 | + |
| 165 | + // Text with background |
| 166 | + let bg_style = TextStyle::new() |
| 167 | + .with_color(Color::BLACK) |
| 168 | + .with_background(Color::rgb(255, 255, 0)); |
| 169 | + |
| 170 | + draw_text(canvas, 50, text_y + 60, " Highlighted Text ", &bg_style); |
| 171 | + |
| 172 | + // Multi-line text |
| 173 | + let multiline_style = TextStyle::new().with_color(Color::rgb(180, 180, 255)); |
| 174 | + draw_text( |
| 175 | + canvas, |
| 176 | + 50, |
| 177 | + text_y + 95, |
| 178 | + "Multi-line text:\n Line 1\n Line 2\n Line 3", |
| 179 | + &multiline_style, |
| 180 | + ); |
| 181 | + |
| 182 | + // Footer |
| 183 | + let footer_style = TextStyle::new().with_color(Color::rgb(100, 100, 100)); |
| 184 | + draw_text( |
| 185 | + canvas, |
| 186 | + 50, |
| 187 | + height - 40, |
| 188 | + "Phase 4: Text Rendering Complete!", |
| 189 | + &footer_style, |
| 190 | + ); |
| 191 | + |
| 192 | + // Draw a decorative border |
| 193 | + draw_rect( |
| 194 | + canvas, |
| 195 | + Rect { |
| 196 | + x: 10, |
| 197 | + y: 70, |
| 198 | + width: (width - 20) as u32, |
| 199 | + height: (height - 120) as u32, |
| 200 | + }, |
| 201 | + Color::rgb(60, 100, 140), |
| 202 | + ); |
| 203 | +} |
0 commit comments