Some rectangle stuff

This commit is contained in:
Ryan Kennedy 2020-04-16 23:32:20 -05:00
parent fb578e73e1
commit 567a548417
6 changed files with 117 additions and 34 deletions

View file

@ -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<u32> 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<u32> 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<isize>, end: Point<isize>, 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<u32> 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);

View file

@ -13,21 +13,29 @@ pub type Point<T> = (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 {

View file

@ -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<u8> for Graphics320x200x256 {
self.get_frame_buffer().write_bytes(color, Self::SIZE);
}
}
fn draw_line(&self, start: Point<isize>, end: Point<isize>, 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<u8> 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);

View file

@ -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<u8> for Graphics320x240x256 {
frame_buffer.write_bytes(color, Self::SIZE);
}
}
fn draw_line(&self, start: Point<isize>, end: Point<isize>, 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<u8> 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<u8> 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);

View file

@ -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<Color16> 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<Color16> 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);

View file

@ -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<Color> {
fn draw_line(&self, start: Point<isize>, end: Point<isize>, 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.