From 567a5484176e7dbfb3dfc2738acca074566d8000 Mon Sep 17 00:00:00 2001 From: Ryan Kennedy Date: Thu, 16 Apr 2020 23:32:20 -0500 Subject: [PATCH] Some rectangle stuff --- src/devices/bochs.rs | 45 +++++++++++++++-------------- src/drawing/mod.rs | 26 +++++++++++------ src/writers/graphics_320x200x256.rs | 26 ++++++++++++++++- src/writers/graphics_320x240x256.rs | 26 ++++++++++++++++- src/writers/graphics_640x480x16.rs | 22 +++++++++++++- src/writers/mod.rs | 6 +++- 6 files changed, 117 insertions(+), 34 deletions(-) diff --git a/src/devices/bochs.rs b/src/devices/bochs.rs index c86931a..b7ae390 100644 --- a/src/devices/bochs.rs +++ b/src/devices/bochs.rs @@ -105,27 +105,6 @@ impl BochsDevice { } } - /// Draws a rectangle using the given `rectangle` and `color`. - pub fn draw_rectangle(&self, rectangle: &Rectangle, color: u32) { - let p1 = (rectangle.left as isize, rectangle.top as isize); - let p2 = (rectangle.left as isize, rectangle.bottom as isize); - let p3 = (rectangle.right as isize, rectangle.bottom as isize); - let p4 = (rectangle.right as isize, rectangle.top as isize); - self.draw_line(p1, p2, color); - self.draw_line(p2, p3, color); - self.draw_line(p3, p4, color); - self.draw_line(p4, p1, color); - } - - /// Draws a filled rectangle using the given `rectangle` and `color`. - pub fn fill_rectangle(&self, rectangle: &Rectangle, color: u32) { - for y in rectangle.top..rectangle.bottom { - for x in rectangle.left..rectangle.right { - self.set_pixel(x as usize, y as usize, color); - } - } - } - fn disable_display(&mut self) { unsafe { self.index_port.write(VBE_DISPI_INDEX_ENABLE); @@ -199,6 +178,7 @@ impl GraphicsWriter for BochsDevice { } } } + fn draw_character(&self, x: usize, y: usize, character: char, color: u32) { let character = match font8x8::BASIC_FONTS.get(character) { Some(character) => character, @@ -215,11 +195,32 @@ impl GraphicsWriter for BochsDevice { } } } + + fn draw_rectangle(&self, rectangle: &Rectangle, color: u32) { + let p1 = (rectangle.x as isize, rectangle.y as isize); + let p2 = (rectangle.x as isize, rectangle.bottom() as isize); + let p3 = (rectangle.right() as isize, rectangle.bottom() as isize); + let p4 = (rectangle.right() as isize, rectangle.y as isize); + self.draw_line(p1, p2, color); + self.draw_line(p2, p3, color); + self.draw_line(p3, p4, color); + self.draw_line(p4, p1, color); + } + + fn draw_filled_rectangle(&self, rectangle: &Rectangle, color: u32) { + for y in rectangle.y..rectangle.bottom() { + for x in rectangle.x..rectangle.right() { + self.set_pixel(x as usize, y as usize, color); + } + } + } + fn draw_line(&self, start: Point, end: Point, color: u32) { for (x, y) in Bresenham::new(start, end) { self.set_pixel(x as usize, y as usize, color); } } + fn set_pixel(&self, x: usize, y: usize, color: u32) { let offset = (y * self.resolution.width) + x; unsafe { @@ -229,9 +230,11 @@ impl GraphicsWriter for BochsDevice { .write_volatile(color); } } + fn get_frame_buffer(&self) -> *mut u32 { self.virtual_address.as_mut_ptr() } + fn set_mode(&mut self) { self.disable_display(); self.set_width(self.resolution.width); diff --git a/src/drawing/mod.rs b/src/drawing/mod.rs index 5c36d16..96b19df 100644 --- a/src/drawing/mod.rs +++ b/src/drawing/mod.rs @@ -13,21 +13,29 @@ pub type Point = (T, T); #[derive(Debug, Copy, Clone)] pub struct Rectangle { - pub left: usize, - pub top: usize, - pub right: usize, - pub bottom: usize, + pub x: usize, + pub y: usize, + pub width: usize, + pub height: usize, } impl Rectangle { - pub fn new(left: usize, top: usize, right: usize, bottom: usize) -> Rectangle { + pub fn new(x: usize, y: usize, width: usize, height: usize) -> Rectangle { Rectangle { - left, - top, - right, - bottom, + x, + y, + width, + height, } } + + pub fn bottom(&self) -> usize { + self.y + self.height + } + + pub fn right(&self) -> usize { + self.x + self.width + } } pub(crate) trait SignedNum: Signed + Ord + Copy + NumCast + NumAssignOps { diff --git a/src/writers/graphics_320x200x256.rs b/src/writers/graphics_320x200x256.rs index 8d239a4..012c28f 100644 --- a/src/writers/graphics_320x200x256.rs +++ b/src/writers/graphics_320x200x256.rs @@ -1,7 +1,7 @@ use super::{GraphicsWriter, Screen}; use crate::{ colors::DEFAULT_PALETTE, - drawing::{Bresenham, Point}, + drawing::{Bresenham, Point, Rectangle}, vga::{VideoMode, VGA}, }; use font8x8::UnicodeFonts; @@ -47,17 +47,20 @@ impl GraphicsWriter for Graphics320x200x256 { self.get_frame_buffer().write_bytes(color, Self::SIZE); } } + fn draw_line(&self, start: Point, end: Point, color: u8) { for (x, y) in Bresenham::new(start, end) { self.set_pixel(x as usize, y as usize, color); } } + fn set_pixel(&self, x: usize, y: usize, color: u8) { let offset = (y * WIDTH) + x; unsafe { self.get_frame_buffer().add(offset).write_volatile(color); } } + fn draw_character(&self, x: usize, y: usize, character: char, color: u8) { let character = match font8x8::BASIC_FONTS.get(character) { Some(character) => character, @@ -74,9 +77,30 @@ impl GraphicsWriter for Graphics320x200x256 { } } } + + fn draw_rectangle(&self, rectangle: &Rectangle, color: u8) { + let p1 = (rectangle.x as isize, rectangle.y as isize); + let p2 = (rectangle.x as isize, rectangle.bottom() as isize); + let p3 = (rectangle.right() as isize, rectangle.bottom() as isize); + let p4 = (rectangle.right() as isize, rectangle.y as isize); + self.draw_line(p1, p2, color); + self.draw_line(p2, p3, color); + self.draw_line(p3, p4, color); + self.draw_line(p4, p1, color); + } + + fn draw_filled_rectangle(&self, rectangle: &Rectangle, color: u8) { + for y in rectangle.y..rectangle.bottom() { + for x in rectangle.x..rectangle.right() { + self.set_pixel(x as usize, y as usize, color); + } + } + } + fn get_frame_buffer(&self) -> *mut u8 { u32::from(VGA.lock().get_frame_buffer()) as *mut u8 } + fn set_mode(&mut self) { let mut vga = VGA.lock(); vga.set_video_mode(VideoMode::Mode320x200x256); diff --git a/src/writers/graphics_320x240x256.rs b/src/writers/graphics_320x240x256.rs index 8669845..9f0baa8 100644 --- a/src/writers/graphics_320x240x256.rs +++ b/src/writers/graphics_320x240x256.rs @@ -1,7 +1,7 @@ use super::{GraphicsWriter, Screen}; use crate::{ colors::DEFAULT_PALETTE, - drawing::{Bresenham, Point}, + drawing::{Bresenham, Point, Rectangle}, registers::PlaneMask, vga::{VideoMode, VGA}, }; @@ -52,11 +52,13 @@ impl GraphicsWriter for Graphics320x240x256 { frame_buffer.write_bytes(color, Self::SIZE); } } + fn draw_line(&self, start: Point, end: Point, color: u8) { for (x, y) in Bresenham::new(start, end) { self.set_pixel(x as usize, y as usize, color); } } + fn set_pixel(&self, x: usize, y: usize, color: u8) { let frame_buffer = self.get_frame_buffer(); unsafe { @@ -68,6 +70,7 @@ impl GraphicsWriter for Graphics320x240x256 { frame_buffer.add(offset).write_volatile(color); } } + fn draw_character(&self, x: usize, y: usize, character: char, color: u8) { let character = match font8x8::BASIC_FONTS.get(character) { Some(character) => character, @@ -84,9 +87,30 @@ impl GraphicsWriter for Graphics320x240x256 { } } } + + fn draw_rectangle(&self, rectangle: &Rectangle, color: u8) { + let p1 = (rectangle.x as isize, rectangle.y as isize); + let p2 = (rectangle.x as isize, rectangle.bottom() as isize); + let p3 = (rectangle.right() as isize, rectangle.bottom() as isize); + let p4 = (rectangle.right() as isize, rectangle.y as isize); + self.draw_line(p1, p2, color); + self.draw_line(p2, p3, color); + self.draw_line(p3, p4, color); + self.draw_line(p4, p1, color); + } + + fn draw_filled_rectangle(&self, rectangle: &Rectangle, color: u8) { + for y in rectangle.y..rectangle.bottom() { + for x in rectangle.x..rectangle.right() { + self.set_pixel(x as usize, y as usize, color); + } + } + } + fn get_frame_buffer(&self) -> *mut u8 { u32::from(VGA.lock().get_frame_buffer()) as *mut u8 } + fn set_mode(&mut self) { let mut vga = VGA.lock(); vga.set_video_mode(VideoMode::Mode320x240x256); diff --git a/src/writers/graphics_640x480x16.rs b/src/writers/graphics_640x480x16.rs index 3b558c7..4d5e74a 100644 --- a/src/writers/graphics_640x480x16.rs +++ b/src/writers/graphics_640x480x16.rs @@ -1,7 +1,7 @@ use super::{GraphicsWriter, Screen}; use crate::{ colors::{Color16, DEFAULT_PALETTE}, - drawing::{Bresenham, Point}, + drawing::{Bresenham, Point, Rectangle}, registers::{PlaneMask, WriteMode}, vga::{VideoMode, VGA}, }; @@ -77,6 +77,25 @@ impl GraphicsWriter for Graphics640x480x16 { } } + fn draw_rectangle(&self, rectangle: &Rectangle, color: Color16) { + let p1 = (rectangle.x as isize, rectangle.y as isize); + let p2 = (rectangle.x as isize, rectangle.bottom() as isize); + let p3 = (rectangle.right() as isize, rectangle.bottom() as isize); + let p4 = (rectangle.right() as isize, rectangle.y as isize); + self.draw_line(p1, p2, color); + self.draw_line(p2, p3, color); + self.draw_line(p3, p4, color); + self.draw_line(p4, p1, color); + } + + fn draw_filled_rectangle(&self, rectangle: &Rectangle, color: Color16) { + for y in rectangle.y..rectangle.bottom() { + for x in rectangle.x..rectangle.right() { + self.set_pixel(x as usize, y as usize, color); + } + } + } + /// **Note:** This method is provided for convenience, but has terrible /// performance since it needs to ensure the correct `WriteMode` per pixel /// drawn. If you need to draw more then one pixel, consider using a method @@ -89,6 +108,7 @@ impl GraphicsWriter for Graphics640x480x16 { fn get_frame_buffer(&self) -> *mut Color16 { u32::from(VGA.lock().get_frame_buffer()) as *mut Color16 } + fn set_mode(&mut self) { let mut vga = VGA.lock(); vga.set_video_mode(VideoMode::Mode640x480x16); diff --git a/src/writers/mod.rs b/src/writers/mod.rs index d4608da..ecaceef 100644 --- a/src/writers/mod.rs +++ b/src/writers/mod.rs @@ -8,7 +8,7 @@ mod text_80x25; use super::{ colors::{Color16, TextModeColor}, - drawing::Point, + drawing::{Point, Rectangle}, registers::CrtcControllerIndex, vga::{Vga, VGA}, }; @@ -195,6 +195,10 @@ pub trait GraphicsWriter { fn draw_line(&self, start: Point, end: Point, color: Color); /// Draws a character at the given `(x, y)` coordinant to the specified `color`. fn draw_character(&self, x: usize, y: usize, character: char, color: Color); + /// Draws a rectangle using the given `rectangle` and `color`. + fn draw_rectangle(&self, rectangle: &Rectangle, color: Color); + /// Draws a filled rectangle using the given `rectangle` and `color`. + fn draw_filled_rectangle(&self, rectangle: &Rectangle, color: Color); /// Sets the given pixel at `(x, y)` to the given `color`. fn set_pixel(&self, x: usize, y: usize, color: Color); /// Returns the frame buffer for this vga mode.