diff --git a/Cargo.toml b/Cargo.toml index fe23fa1..26bc895 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,12 +13,18 @@ version = "2.3.0" [dependencies] crossterm = "0.23" +drawille = {version = "0.3", optional = true} unicode-width = "0.1.8" [dev-dependencies] console_engine = {path = ".", features = ["event"]} rand = "0.8" +[package.metadata.docs.rs] +all-features = true + [features] +compatibility = [] +compatibility-drawille = ["compatibility", "drawille"] default = [] event = [] diff --git a/src/compatibility/drawille.rs b/src/compatibility/drawille.rs new file mode 100644 index 0000000..582f5ac --- /dev/null +++ b/src/compatibility/drawille.rs @@ -0,0 +1,74 @@ +#![cfg(feature = "compatibility-drawille")] + +extern crate drawille; + +use drawille::{Canvas, PixelColor}; + +use crate::{pixel, screen::Screen, Color}; + +use super::AsScreen; + +impl AsScreen for Canvas { + fn as_screen(&self) -> Option { + let mut screen = Screen::new(self.width() as u32, self.height() as u32); + + let mut maxrow = self.width(); + let mut maxcol = self.height(); + for &(x, y) in self.chars().keys() { + if x > maxrow { + maxrow = x; + } + if y > maxcol { + maxcol = y; + } + } + + let mut result = Vec::with_capacity(maxcol as usize + 1); + for y in 0..=maxcol { + let mut row = Vec::with_capacity(maxrow as usize + 1); + for x in 0..=maxrow { + let cell = self.chars().get(&(x, y)).cloned().unwrap_or(( + 0, + ' ', + false, + PixelColor::White, + )); + match cell { + (0, _, _, _) => screen.set_pxl(x, y, pixel::pxl(cell.1)), + (_, _, false, _) => screen.set_pxl( + x, + y, + pixel::pxl(char::from_u32(0x2800 + cell.0 as u32).unwrap()), + ), + (_, _, true, _) => screen.set_pxl( + x, + y, + pixel::pxl_fg( + char::from_u32(0x2800 + cell.0 as u32).unwrap(), + match cell.3 { + PixelColor::Black => Color::Black, + PixelColor::Red => Color::DarkRed, + PixelColor::Green => Color::DarkGreen, + PixelColor::Yellow => Color::DarkYellow, + PixelColor::Blue => Color::DarkBlue, + PixelColor::Magenta => Color::DarkMagenta, + PixelColor::Cyan => Color::DarkCyan, + PixelColor::White => Color::Grey, + PixelColor::BrightBlack => Color::DarkGrey, + PixelColor::BrightRed => Color::Red, + PixelColor::BrightGreen => Color::Green, + PixelColor::BrightYellow => Color::Yellow, + PixelColor::BrightBlue => Color::Blue, + PixelColor::BrightMagenta => Color::Magenta, + PixelColor::BrightCyan => Color::Cyan, + PixelColor::BrightWhite => Color::White, + PixelColor::TrueColor { r, g, b } => Color::Rgb { r, g, b }, + }, + ), + ), + }; + } + } + Some(screen) + } +} diff --git a/src/compatibility/mod.rs b/src/compatibility/mod.rs new file mode 100644 index 0000000..814c8ad --- /dev/null +++ b/src/compatibility/mod.rs @@ -0,0 +1,10 @@ +#![cfg(feature = "compatibility")] + +use crate::screen::Screen; + +#[cfg(feature = "compatibility-drawille")] +pub mod drawille; + +pub trait AsScreen { + fn as_screen(&self) -> Option; +} diff --git a/src/lib.rs b/src/lib.rs index 200009d..dae2c56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ pub extern crate crossterm; +#[cfg(feature = "compatibility")] +pub mod compatibility; pub mod pixel; pub mod rect_style; pub mod screen; @@ -273,6 +275,13 @@ impl ConsoleEngine { self.screen.print_screen(x, y, source) } + /// Prints a screen from a compatible Struct + /// See [print_screen](#method.print_screen) + #[cfg(feature = "compatibility")] + pub fn print_with(&mut self, x: i32, y: i32, source: &impl crate::compatibility::AsScreen) { + self.screen.print_with(x, y, source) + } + /// Prints another screen on specified coordinates, ignoring a specific character while printing /// Ignoring a character will behave like transparency /// @@ -282,6 +291,19 @@ impl ConsoleEngine { .print_screen_alpha(x, y, source, alpha_character) } + /// Prints a screen from a compatible Struct, ignoring a specific character while printing for a transparency effect + /// See [print_screen_alpha](#method.print_screen_alpha) + #[cfg(feature = "compatibility")] + pub fn print_alpha_with( + &mut self, + x: i32, + y: i32, + source: &impl crate::compatibility::AsScreen, + alpha_character: char, + ) { + self.screen.print_alpha_with(x, y, source, alpha_character) + } + /// draws a line of the provided character between two sets of coordinates /// see: [Bresenham's line algorithm](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm) /// diff --git a/src/screen.rs b/src/screen.rs index 9470500..3abae8d 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -238,6 +238,15 @@ impl Screen { } } + /// Prints a screen from a compatible Struct + /// See [print_screen](#method.print_screen) + #[cfg(feature = "compatibility")] + pub fn print_with(&mut self, x: i32, y: i32, source: &impl crate::compatibility::AsScreen) { + if let Some(screen) = source.as_screen() { + self.print_screen(x, y, &screen) + } + } + /// Prints another screen on specified coordinates, ignoring a specific character while printing /// Ignoring a character will behave like transparency /// @@ -254,6 +263,21 @@ impl Screen { } } + /// Prints a screen from a compatible Struct, ignoring a specific character while printing for a transparency effect + /// See [print_screen_alpha](#method.print_screen_alpha) + #[cfg(feature = "compatibility")] + pub fn print_alpha_with( + &mut self, + x: i32, + y: i32, + source: &impl crate::compatibility::AsScreen, + alpha_character: char, + ) { + if let Some(screen) = source.as_screen() { + self.print_screen_alpha(x, y, &screen, alpha_character) + } + } + /// Optimized horizontal line drawing /// Automatically called by [line](#method.line) if needed pub fn h_line(&mut self, start_x: i32, start_y: i32, end_x: i32, character: Pixel) {