use crate::cast::As;
use crate::types::Color;
use std::cmp::max;
pub mod image;
pub mod pic;
pub mod string;
pub mod svg;
pub mod unicode;
pub trait Pixel: Copy + Sized {
type Image: Sized + 'static;
type Canvas: Canvas<Pixel = Self, Image = Self::Image>;
fn default_unit_size() -> (u32, u32) {
(8, 8)
}
fn default_color(color: Color) -> Self;
}
pub trait Canvas: Sized {
type Pixel: Sized;
type Image: Sized;
fn new(width: u32, height: u32, dark_pixel: Self::Pixel, light_pixel: Self::Pixel) -> Self;
fn draw_dark_pixel(&mut self, x: u32, y: u32);
fn draw_dark_rect(&mut self, left: u32, top: u32, width: u32, height: u32) {
for y in top..(top + height) {
for x in left..(left + width) {
self.draw_dark_pixel(x, y);
}
}
}
fn into_image(self) -> Self::Image;
}
pub struct Renderer<'a, P: Pixel> {
content: &'a [Color],
modules_count: u32, quiet_zone: u32,
module_size: (u32, u32),
dark_color: P,
light_color: P,
has_quiet_zone: bool,
}
impl<'a, P: Pixel> Renderer<'a, P> {
pub fn new(content: &'a [Color], modules_count: usize, quiet_zone: u32) -> Renderer<'a, P> {
assert!(modules_count * modules_count == content.len());
Renderer {
content,
modules_count: modules_count.as_u32(),
quiet_zone,
module_size: P::default_unit_size(),
dark_color: P::default_color(Color::Dark),
light_color: P::default_color(Color::Light),
has_quiet_zone: true,
}
}
pub fn dark_color(&mut self, color: P) -> &mut Self {
self.dark_color = color;
self
}
pub fn light_color(&mut self, color: P) -> &mut Self {
self.light_color = color;
self
}
pub fn quiet_zone(&mut self, has_quiet_zone: bool) -> &mut Self {
self.has_quiet_zone = has_quiet_zone;
self
}
#[deprecated(since = "0.4.0", note = "use `.module_dimensions(width, width)` instead")]
pub fn module_size(&mut self, width: u32) -> &mut Self {
self.module_dimensions(width, width)
}
pub fn module_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
self.module_size = (max(width, 1), max(height, 1));
self
}
#[deprecated(since = "0.4.0", note = "use `.min_dimensions(width, width)` instead")]
pub fn min_width(&mut self, width: u32) -> &mut Self {
self.min_dimensions(width, width)
}
pub fn min_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
let width_in_modules = self.modules_count + quiet_zone;
let unit_width = (width + width_in_modules - 1) / width_in_modules;
let unit_height = (height + width_in_modules - 1) / width_in_modules;
self.module_dimensions(unit_width, unit_height)
}
pub fn max_dimensions(&mut self, width: u32, height: u32) -> &mut Self {
let quiet_zone = if self.has_quiet_zone { 2 } else { 0 } * self.quiet_zone;
let width_in_modules = self.modules_count + quiet_zone;
let unit_width = width / width_in_modules;
let unit_height = height / width_in_modules;
self.module_dimensions(unit_width, unit_height)
}
#[deprecated(since = "0.4.0", note = "renamed to `.build()` to de-emphasize the image connection")]
pub fn to_image(&self) -> P::Image {
self.build()
}
pub fn build(&self) -> P::Image {
let w = self.modules_count;
let qz = if self.has_quiet_zone { self.quiet_zone } else { 0 };
let width = w + 2 * qz;
let (mw, mh) = self.module_size;
let real_width = width * mw;
let real_height = width * mh;
let mut canvas = P::Canvas::new(real_width, real_height, self.dark_color, self.light_color);
let mut i = 0;
for y in 0..width {
for x in 0..width {
if qz <= x && x < w + qz && qz <= y && y < w + qz {
if self.content[i] != Color::Light {
canvas.draw_dark_rect(x * mw, y * mh, mw, mh);
}
i += 1;
}
}
}
canvas.into_image()
}
}