diff options
Diffstat (limited to 'vendor/plotters/examples/console.rs')
-rw-r--r-- | vendor/plotters/examples/console.rs | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/vendor/plotters/examples/console.rs b/vendor/plotters/examples/console.rs new file mode 100644 index 000000000..feba0956b --- /dev/null +++ b/vendor/plotters/examples/console.rs @@ -0,0 +1,200 @@ +use plotters::prelude::*; +use plotters::style::text_anchor::{HPos, VPos}; +use plotters_backend::{ + BackendColor, BackendStyle, BackendTextStyle, DrawingBackend, DrawingErrorKind, +}; +use std::error::Error; + +#[derive(Copy, Clone)] +enum PixelState { + Empty, + HLine, + VLine, + Cross, + Pixel, + Text(char), + Circle(bool), +} + +impl PixelState { + fn to_char(self) -> char { + match self { + Self::Empty => ' ', + Self::HLine => '-', + Self::VLine => '|', + Self::Cross => '+', + Self::Pixel => '.', + Self::Text(c) => c, + Self::Circle(filled) => { + if filled { + '@' + } else { + 'O' + } + } + } + } + + fn update(&mut self, new_state: PixelState) { + let next_state = match (*self, new_state) { + (Self::HLine, Self::VLine) => Self::Cross, + (Self::VLine, Self::HLine) => Self::Cross, + (_, Self::Circle(what)) => Self::Circle(what), + (Self::Circle(what), _) => Self::Circle(what), + (_, Self::Pixel) => Self::Pixel, + (Self::Pixel, _) => Self::Pixel, + (_, new) => new, + }; + + *self = next_state; + } +} + +pub struct TextDrawingBackend(Vec<PixelState>); + +impl DrawingBackend for TextDrawingBackend { + type ErrorType = std::io::Error; + + fn get_size(&self) -> (u32, u32) { + (100, 30) + } + + fn ensure_prepared(&mut self) -> Result<(), DrawingErrorKind<std::io::Error>> { + Ok(()) + } + + fn present(&mut self) -> Result<(), DrawingErrorKind<std::io::Error>> { + for r in 0..30 { + let mut buf = String::new(); + for c in 0..100 { + buf.push(self.0[r * 100 + c].to_char()); + } + println!("{}", buf); + } + + Ok(()) + } + + fn draw_pixel( + &mut self, + pos: (i32, i32), + color: BackendColor, + ) -> Result<(), DrawingErrorKind<std::io::Error>> { + if color.alpha > 0.3 { + self.0[(pos.1 * 100 + pos.0) as usize].update(PixelState::Pixel); + } + Ok(()) + } + + fn draw_line<S: BackendStyle>( + &mut self, + from: (i32, i32), + to: (i32, i32), + style: &S, + ) -> Result<(), DrawingErrorKind<Self::ErrorType>> { + if from.0 == to.0 { + let x = from.0; + let y0 = from.1.min(to.1); + let y1 = from.1.max(to.1); + for y in y0..y1 { + self.0[(y * 100 + x) as usize].update(PixelState::VLine); + } + return Ok(()); + } + + if from.1 == to.1 { + let y = from.1; + let x0 = from.0.min(to.0); + let x1 = from.0.max(to.0); + for x in x0..x1 { + self.0[(y * 100 + x) as usize].update(PixelState::HLine); + } + return Ok(()); + } + + plotters_backend::rasterizer::draw_line(self, from, to, style) + } + + fn estimate_text_size<S: BackendTextStyle>( + &self, + text: &str, + _: &S, + ) -> Result<(u32, u32), DrawingErrorKind<Self::ErrorType>> { + Ok((text.len() as u32, 1)) + } + + fn draw_text<S: BackendTextStyle>( + &mut self, + text: &str, + style: &S, + pos: (i32, i32), + ) -> Result<(), DrawingErrorKind<Self::ErrorType>> { + let (width, height) = self.estimate_text_size(text, style)?; + let (width, height) = (width as i32, height as i32); + let dx = match style.anchor().h_pos { + HPos::Left => 0, + HPos::Right => -width, + HPos::Center => -width / 2, + }; + let dy = match style.anchor().v_pos { + VPos::Top => 0, + VPos::Center => -height / 2, + VPos::Bottom => -height, + }; + let offset = (pos.1 + dy).max(0) * 100 + (pos.0 + dx).max(0); + for (idx, chr) in (offset..).zip(text.chars()) { + self.0[idx as usize].update(PixelState::Text(chr)); + } + Ok(()) + } +} + +fn draw_chart<DB: DrawingBackend>( + b: DrawingArea<DB, plotters::coord::Shift>, +) -> Result<(), Box<dyn Error>> +where + DB::ErrorType: 'static, +{ + let mut chart = ChartBuilder::on(&b) + .margin(1) + .caption("Sine and Cosine", ("sans-serif", (10).percent_height())) + .set_label_area_size(LabelAreaPosition::Left, (5i32).percent_width()) + .set_label_area_size(LabelAreaPosition::Bottom, (10i32).percent_height()) + .build_cartesian_2d(-std::f64::consts::PI..std::f64::consts::PI, -1.2..1.2)?; + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .draw()?; + + chart.draw_series(LineSeries::new( + (-314..314).map(|x| x as f64 / 100.0).map(|x| (x, x.sin())), + &RED, + ))?; + + chart.draw_series(LineSeries::new( + (-314..314).map(|x| x as f64 / 100.0).map(|x| (x, x.cos())), + &RED, + ))?; + + b.present()?; + + Ok(()) +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/console-example.png"; +fn main() -> Result<(), Box<dyn Error>> { + draw_chart(TextDrawingBackend(vec![PixelState::Empty; 5000]).into_drawing_area())?; + let b = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + b.fill(&WHITE)?; + draw_chart(b)?; + + println!("Image result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} |