From ef4f3aedc1aa5181ab02f572a0c4727e3e1bc3c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= <ondra@ondrovo.com>
Date: Mon, 20 Apr 2020 23:28:34 +0200
Subject: [PATCH] image nonsense

---
 Cargo.lock             |  38 +---
 Cargo.toml             |   4 +-
 out.png                | Bin 0 -> 2752 bytes
 src/DOSVGA.ttf         | Bin 0 -> 78252 bytes
 src/DejaVuSans.ttf     | Bin 0 -> 741536 bytes
 src/coders_crux.ttf    | Bin 0 -> 26300 bytes
 src/fixedsys.ttf       | Bin 0 -> 27216 bytes
 src/lilliput steps.ttf | Bin 0 -> 15548 bytes
 src/main.rs            | 453 +++++++++++++++++++++++++----------------
 9 files changed, 282 insertions(+), 213 deletions(-)
 create mode 100644 out.png
 create mode 100644 src/DOSVGA.ttf
 create mode 100644 src/DejaVuSans.ttf
 create mode 100644 src/coders_crux.ttf
 create mode 100644 src/fixedsys.ttf
 create mode 100644 src/lilliput steps.ttf

diff --git a/Cargo.lock b/Cargo.lock
index c087558..cc4dfc8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,11 +1,5 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-[[package]]
-name = "ab_glyph_rasterizer"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19eabfa36efffae27d62d530e30eb951e3d9a999d23c0d58cb010a27e3916744"
-
 [[package]]
 name = "adler32"
 version = "1.0.4"
@@ -150,7 +144,7 @@ version = "0.1.0"
 dependencies = [
  "image",
  "imageproc",
- "rusttype 0.9.0",
+ "rusttype",
 ]
 
 [[package]]
@@ -215,7 +209,7 @@ dependencies = [
  "rand_distr",
  "rayon",
  "rulinalg",
- "rusttype 0.8.3",
+ "rusttype",
 ]
 
 [[package]]
@@ -258,15 +252,6 @@ version = "0.2.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
 
-[[package]]
-name = "log"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
-dependencies = [
- "cfg-if",
-]
-
 [[package]]
 name = "lzw"
 version = "0.10.0"
@@ -532,16 +517,6 @@ dependencies = [
  "stb_truetype",
 ]
 
-[[package]]
-name = "rusttype"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40cbe3f2bab536ff4784f14f2a73f1e37550ceb36a074c47a8f4150f57182049"
-dependencies = [
- "ab_glyph_rasterizer",
- "ttf-parser",
-]
-
 [[package]]
 name = "scoped_threadpool"
 version = "0.1.9"
@@ -574,15 +549,6 @@ dependencies = [
  "miniz_oxide",
 ]
 
-[[package]]
-name = "ttf-parser"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afa7e68b11bcf63b8a990bd7fe894dece47a629dbbba0fce4dbecb4dbac3ef8d"
-dependencies = [
- "log",
-]
-
 [[package]]
 name = "wasi"
 version = "0.9.0+wasi-snapshot-preview1"
diff --git a/Cargo.toml b/Cargo.toml
index 116d809..7fed6b0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,6 @@ edition = "2018"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-image = "0.23.4"
+image = "0.23.0"
 imageproc = "0.20.0"
-rusttype = "0.9.0"
+rusttype = "0.8.2"
diff --git a/out.png b/out.png
new file mode 100644
index 0000000000000000000000000000000000000000..77bc7f1f1461a6b6b2da8212504c644b29292825
GIT binary patch
diff --git a/src/DOSVGA.ttf b/src/DOSVGA.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..bf7011283fc2b1f1326203a66306271b77041b31
GIT binary patch
diff --git a/src/DejaVuSans.ttf b/src/DejaVuSans.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..9d40c325694b3bfb8cdd4c0146ad44379d5c4ade
GIT binary patch
diff --git a/src/coders_crux.ttf b/src/coders_crux.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..01b5ea3f36081715ec12310c0b0dab04c0500518
GIT binary patch
diff --git a/src/fixedsys.ttf b/src/fixedsys.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..7d6946d64500f56550612c01d63b6d145a9dea0a
GIT binary patch
diff --git a/src/lilliput steps.ttf b/src/lilliput steps.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..7c2317da1db781c750b66440a0be6225f098e249
GIT binary patch
diff --git a/src/main.rs b/src/main.rs
index 370d1b2..1e7625b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,198 +1,301 @@
 use std::default::Default;
+use rusttype::{Scale, FontCollection, Font};
+use imageproc::drawing;
+use image::{GrayImage, RgbImage, Rgb, Luma};
+use std::path::Path;
+use imageproc::rect::Rect;
 
-mod bgm {
-    use std::fmt;
-    use std::default::Default;
-    use std::fmt::Display;
+use std::fmt;
+use std::fmt::Display;
 
-    use image::{Rgb, RgbImage};
-    use imageproc::drawing::draw_text_mut;
-    use rusttype::{FontCollection, Scale};
+#[derive(Debug,Clone,Copy,Eq,PartialEq)]
+pub enum PlayerSide {
+    Black = 0,
+    White = 1,
+}
+
+#[derive(Debug,Clone,Copy)]
+pub enum Phase {
+    PickSides,
+    Turn(PlayerSide),
+}
+
+#[derive(Debug,Clone,Default)]
+pub struct Player {
+    pub born_off: u32,
+    pub on_bar: u32,
+}
 
-    #[derive(Debug,Clone,Copy,Eq,PartialEq)]
-    pub enum Color {
-        Black = 0,
-        White = 1,
+#[derive(Debug,Clone,Copy)]
+pub enum Bin {
+    Free,
+    Black(u32),
+    White(u32),
+}
+
+#[derive(Debug)]
+pub struct Game {
+    pub phase : Phase,
+    pub multiplier : u32,
+    pub roll : [u8; 2],
+    pub players : [Player; 2],
+    pub bins : [Bin; 24],
+}
+
+impl Default for Game {
+    fn default() -> Self {
+        Game {
+            phase: Phase::PickSides,
+            multiplier: 1,
+            roll: [0; 2],
+            players: [
+                Player::default(),
+                Player::default(),
+            ],
+            bins: [Bin::Free; 24],
+        }
     }
-    
-    #[derive(Debug,Clone,Copy)]
-    pub enum Phase {
-        PickSides,
-        Turn(Color),
+}
+
+impl Display for Game {
+    fn fmt(&self, f : &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "  ")?;
+        for n in (13..=24).rev() { write!(f, "{:2}. ", n)?; }
+        write!(f, "\n╭ ")?;
+
+        for b in &self.bins[12..=23] {
+            match *b {
+                Bin::Free => write!(f, "┈┈┈ ")?,
+                Bin::Black(n) => write!(f, "{:2}█ ", n)?,
+                Bin::White(n) => write!(f, "{:2}░ ", n)?
+            }
+        }
+        write!(f, "╴\n╰ ")?;
+
+        for b in (&self.bins[0..=11]).iter().rev() {
+            match *b {
+                Bin::Free => write!(f, "┈┈┈ ")?,
+                Bin::Black(n) => write!(f, "{:2}█ ", n)?,
+                Bin::White(n) => write!(f, "{:2}░ ", n)?
+            }
+        }
+
+        write!(f, "╴\n  ")?;
+        for n in (1..=12).rev() { write!(f, "{:2}. ", n)?; }
+        write!(f, "\n")?;
+
+        Ok(())
     }
+}
+
+fn main() {
+    let mut board = Game::default();
     
-    #[derive(Debug,Clone,Default)]
-    pub struct Player {
-        pub born_off: u32,
-        pub on_bar: u32,
-    }
+    board.bins[4] = Bin::Black(5);
+    board.bins[5] = Bin::Black(2);
+    board.bins[6] = Bin::Black(7);
     
-    #[derive(Debug,Clone,Copy)]
-    pub enum Bin {
-        Free,
-        Black(u32),
-        White(u32),
+    board.bins[14] = Bin::White(9);
+    board.bins[15] = Bin::White(10);
+    board.bins[16] = Bin::White(11);
+    board.bins[2] = Bin::White(2);
+
+
+    // // let mut image = RgbImage::new(200, 200);
+    // let mut image : RgbImage = RgbImage::new(200, 200);
+    //
+    // let font = Vec::from(include_bytes!("DejaVuSans.ttf") as &[u8]);
+    // let font = FontCollection::from_bytes(font)
+    //     .unwrap()
+    //     .into_font()
+    //     .unwrap();
+    //
+    // let height = 12.0;
+    // let scale = Scale {
+    //     x: height,
+    //     y: height,
+    // };
+    //
+    // let white = Rgb([255u8, 255u8, 255u8]);
+    //
+    // draw_text_mut(
+    //     &mut image,
+    //     white,
+    //     0,
+    //     0,
+    //     scale,
+    //     &font,
+    //     "Hello, world!",
+    // );
+    //
+    // imageproc::drawing::draw_line_segment_mut(&mut image, (0.0, 0.0), (200.0,200.0), white);
+    //
+    // let _ = image.save("out.gif").unwrap();
+
+    let mut image = CrispImage::new(250, 60);
+
+    image.fill(BG);
+
+    fn draw_disc(image : &mut CrispImage, pos: (i32, i32), bin : Bin) {
+        match bin {
+            Bin::Free => {
+                image.circle_filled(GRAY, pos, 7);
+            },
+            Bin::Black(n) => {
+                let s = n.to_string();
+                // image.circle_filled(BLACK, pos, 7);
+                image.circle(WHITE, pos, 7);
+                image.text(WHITE, (pos.0 - (s.len() as i32 * 5)/2, pos.1 - 3), &s);
+            },
+            Bin::White(n) => {
+                let s = n.to_string();
+                image.circle_filled(WHITE, pos, 7);
+                image.circle(WHITE, pos, 7);
+                image.text(BLACK, (pos.0 - (s.len() as i32 * 5)/2, pos.1 - 3), &s);
+            },
+        }
     }
-    
-    #[derive(Debug)]
-    pub struct Game {
-        pub phase : Phase,
-        pub multiplier : u32,
-        pub roll : [u8; 2],
-        pub players : [Player; 2],
-        pub bins : [Bin; 24],
+
+    for (i, n) in (13..=24).enumerate() {
+        let s = n.to_string();
+        image.text(YELLOW, (10 + 20 * i as i32 - (s.len() as i32 * 5)/2, 2), &s);
     }
-    
-    impl Default for Game {
-        fn default() -> Self {
-            Game {
-                phase: Phase::PickSides,
-                multiplier: 1,
-                roll: [0; 2],
-                players: [
-                    Player::default(),
-                    Player::default(),
-                ],
-                bins: [Bin::Free; 24],
-            }
-        }
+
+    for (i, n) in (1..=12).rev().enumerate() {
+        let s = n.to_string();
+        image.text(YELLOW, (10 + 20 * i as i32 - (s.len() as i32 * 5)/2, 51), &s);
     }
-    
-    impl Display for Game {
-        fn fmt(&self, f : &mut fmt::Formatter<'_>) -> fmt::Result {
-            /*
-
-            const BLACK_DIGITS : [char; 20] = [
-                '❶', '❷', '❸', '❹', '❺', '❻', '❼', '❽', '❾', '❿',
-                '⓫', '⓬', '⓭', '⓮', '⓯', '⓰', '⓱', '⓲', '⓳', '⓴',
-            ];
-
-            const WHITE_DIGITS : [char; 20] = [
-                '➀', '➁', '➂', '➃', '➄', '➅', '➆', '➇', '➈', '➉',
-                '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳',
-            ];
-
-            write!(f, "13 14 15 16 17 18 19 20 21 22 23 24\n")?;
-            for b in &self.bins[12..=23] {
-                match *b {
-                    Bin::Free => write!(f, "-- ")?,
-                    Bin::Black(n) => {
-                        if n > 0 && n <= BLACK_DIGITS.len() as u32 {
-                            write!(f, "{}  ", BLACK_DIGITS[(n-1) as usize])?;
-                        } else {
-                            write!(f, "{} ", n)?;
-                        }
-                    }
-                    Bin::White(n) => {
-                        if n > 0 && n <= WHITE_DIGITS.len() as u32 {
-                            write!(f, "{}  ", WHITE_DIGITS[(n-1) as usize])?;
-                        } else {
-                            write!(f, "{} ", n)?;
-                        }
-                    }
-                }
-                
-            }
-            write!(f, "\n")?;
-            
-            for b in (&self.bins[0..=11]).iter().rev() {
-                match *b {
-                    Bin::Free => write!(f, "-- ")?,
-                    Bin::Black(n) => {
-                        if n > 0 && n <= BLACK_DIGITS.len() as u32 {
-                            write!(f, "{}  ", BLACK_DIGITS[(n-1) as usize])?;
-                        } else {
-                            write!(f, "{} ", n)?;
-                        }
-                    }
-                    Bin::White(n) => {
-                        if n > 0 && n <= WHITE_DIGITS.len() as u32 {
-                            write!(f, "{}  ", WHITE_DIGITS[(n-1) as usize])?;
-                        } else {
-                            write!(f, "{} ", n)?;
-                        }
-                    }
-                }
-            }
-            
-            write!(f, "\n")?;            
-            write!(f, "12 11 10  9  8  7  6  5  4  3  2  1\n")?;
-
-            */
-
-            //*
-            write!(f, "  ")?;
-            for n in (13..=24).rev() { write!(f, "{:2}. ", n)?; }
-            write!(f, "\n╭ ")?;
-
-            for b in &self.bins[12..=23] {
-                match *b {
-                    Bin::Free => write!(f, "┈┈┈ ")?,
-                    Bin::Black(n) => write!(f, "{:2}█ ", n)?,
-                    Bin::White(n) => write!(f, "{:2}░ ", n)?
-                }
-            }
-            write!(f, "╴\n╰ ")?;
-
-            for b in (&self.bins[0..=11]).iter().rev() {
-                match *b {
-                    Bin::Free => write!(f, "┈┈┈ ")?,
-                    Bin::Black(n) => write!(f, "{:2}█ ", n)?,
-                    Bin::White(n) => write!(f, "{:2}░ ", n)?
-                }
-            }
 
-            write!(f, "╴\n  ")?;
-            for n in (1..=12).rev() { write!(f, "{:2}. ", n)?; }
-            write!(f, "\n")?;
-            //*/
+    //
+    // let s = "1";
+    // image.text(YELLOW, (10 - (s.len() as i32 * 5)/2, 2), &s);
+    //
+    // let s = "13";
+    // image.text(YELLOW, (30 - (s.len() as i32 * 5)/2, 2), &s);
+
+    draw_disc(&mut image, (10, 20), Bin::Black(7));
+    draw_disc(&mut image, (30, 20), Bin::Black(13));
+    draw_disc(&mut image, (50, 20), Bin::Free);
+    draw_disc(&mut image, (70, 20), Bin::White(69));
+    draw_disc(&mut image, (90, 20), Bin::White(9));
+    for n in 1..=7 {
+        draw_disc(&mut image, (90+n*20, 20), Bin::Free);
+    }
 
-            /*
-            const DIGITS : &[u8; 36] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    for n in 0..=11 {
+        draw_disc(&mut image, (10 + n*20, 40), Bin::Free);
+    }
 
-            write!(f, "   14  16  18  20  22  24\n")?;
-            write!(f, " 13╲╱15╲╱17╲╱19╲╱21╲╱23╲╱\n")?;
-            write!(f, "╭")?;
+    image.render("out.png");
 
-            for b in &self.bins[12..=23] {
-                match *b {
-                    Bin::Free => write!(f, "──")?,
-                    Bin::Black(n) => write!(f, "{}█", DIGITS[n as usize] as char)?,
-                    Bin::White(n) => write!(f, "{}░", DIGITS[n as usize] as char)?
-                }
-            }
-            write!(f, "─┘\n╰")?;
-
-            for b in (&self.bins[0..=11]).iter().rev() {
-                match *b {
-                    Bin::Free => write!(f, "──")?,
-                    Bin::Black(n) => write!(f, "{}█", DIGITS[n as usize] as char)?,
-                    Bin::White(n) => write!(f, "{}░", DIGITS[n as usize] as char)?
-                }
-            }
+    println!("{}", board);
+}
 
-            write!(f, "─┐\n")?;
-            write!(f, " 12╱╲10╱╲8.╱╲6.╱╲4.╱╲2.╱╲\n")?;
-            write!(f, "   11  9.  7.  5.  3.  1.\n")?;
-            */
+type Color = Rgb<u8>;
 
-            Ok(())
+struct CrispImage<'a> {
+    image : RgbImage,
+    font: Font<'a>,
+    width: u32,
+    height: u32,
+    font_scale: Scale,
+}
+
+const BG : Color = Rgb([18, 26, 36]);
+
+const BLACK : Color = Rgb([0, 0, 0]);
+const GRAY : Color = Rgb([67, 83, 104]);
+const WHITE : Color = Rgb([255, 255, 255]);
+const RED : Color = Rgb([255, 0, 0]);
+const YELLOW : Color = Rgb([255, 255, 0]);
+const GREEN : Color = Rgb([0, 255, 0]);
+const BLUE : Color = Rgb([0, 0, 255]);
+const CYAN : Color = Rgb([0, 255, 255]);
+const MAGENTA : Color = Rgb([255, 0, 255]);
+
+impl<'a> CrispImage<'a> {
+    fn new(width: u32, height: u32) -> Self {
+        let mut image : RgbImage = RgbImage::new(width, height);
+
+        // let font_bytes = include_bytes!("DejaVuSans.ttf");
+        // let font_bytes = include_bytes!("lilliput steps.ttf");
+        // let font_bytes = include_bytes!("fixedsys.ttf"); // 16.2
+        // let font_bytes = include_bytes!("DOSVGA.ttf"); // 16
+        let font_bytes = include_bytes!("coders_crux.ttf"); // 8.86
+
+        let font = Vec::from(font_bytes as &[u8]);
+
+        let font = FontCollection::from_bytes(font)
+            .unwrap()
+            .into_font()
+            .unwrap();
+
+        Self {
+            image,
+            font,
+            width,
+            height,
+            font_scale: Scale {
+               /* x: 16.,
+                y: 16.,*/
+                x: 8.86,
+                y: 8.86,
+            },
         }
     }
-}
 
-fn main() {
-    let mut board = bgm::Game::default();
-    
-    board.bins[4] = bgm::Bin::Black(5);
-    board.bins[5] = bgm::Bin::Black(2);
-    board.bins[6] = bgm::Bin::Black(7);    
-    
-    board.bins[14] = bgm::Bin::White(9);
-    board.bins[15] = bgm::Bin::White(10);
-    board.bins[16] = bgm::Bin::White(11);
-    board.bins[2] = bgm::Bin::White(2);
+    fn fill(&mut self, color: Color) {
+        self.rect_filled(color, (0,0), (self.width, self.height));
+    }
 
+    fn render(&self, path : impl AsRef<Path>) {
+        let _ = self.image.save(path).unwrap();
+    }
 
-    println!("{}", board);
+    fn font_scale(&mut self, f : f32) {
+        self.font_scale.x = f;
+        self.font_scale.y = f;
+    }
+
+    fn text(&mut self, color: Color, pos : (i32, i32), text: &str) {
+        assert!(pos.0 >= 0);
+        assert!(pos.1 >= 0);
+
+        drawing::draw_text_mut(
+            &mut self.image,
+            color,
+            pos.0 as u32,
+            pos.1 as u32,
+            self.font_scale,
+            &self.font,
+            text,
+        );
+    }
+
+    fn circle(&mut self, color: Color, center: (i32, i32), radius: i32) {
+        drawing::draw_hollow_circle_mut(&mut self.image, center, radius, color);
+    }
+
+    fn circle_filled(&mut self, color: Color, center: (i32, i32), radius: i32) {
+        drawing::draw_filled_circle_mut(&mut self.image, center, radius, color);
+    }
+
+    fn line(&mut self, color: Color, from: (i32, i32), to: (i32, i32)) {
+        drawing::draw_line_segment_mut(&mut self.image,
+                                   (from.0 as f32, from.1 as f32),
+                                   (to.0 as f32, to.1 as f32),
+                                   color);
+    }
+
+    fn rect(&mut self, color: Color, tl: (i32, i32), size: (u32, u32)) {
+        drawing::draw_hollow_rect_mut(&mut self.image,
+                                  Rect::at(tl.0, tl.1).of_size(size.0, size.1),
+                                  color);
+    }
+
+    fn rect_filled(&mut self, color: Color, tl: (i32, i32), size: (u32, u32)) {
+        drawing::draw_filled_rect_mut(&mut self.image,
+                                  Rect::at(tl.0, tl.1).of_size(size.0, size.1),
+                                  color);
+    }
 }
