Getty Ritter 2 лет назад
Родитель
Сommit
2bc6f9f65f
4 измененных файлов с 149 добавлено и 122 удалено
  1. 53 0
      src/data.rs
  2. 56 0
      src/draw.rs
  3. 16 122
      src/main.rs
  4. 24 0
      src/opts.rs

+ 53 - 0
src/data.rs

@@ -0,0 +1,53 @@
+use serde::Deserialize;
+
+use crate::image::Pixel;
+
+#[derive(Deserialize, Debug)]
+struct ColorEntry {
+    color: Pixel,
+    symbol: String,
+}
+
+#[derive(Deserialize, Debug)]
+pub struct Mapping(Vec<ColorEntry>);
+
+impl Mapping {
+    pub fn load(path: impl AsRef<std::path::Path>) -> Result<Mapping, Box<dyn std::error::Error>> {
+        Ok(serde_yaml::from_reader(std::fs::File::open(path)?)?)
+    }
+
+    pub fn lookup(&self, color: Pixel) -> &str {
+        let found = self.0.iter().find(|entry| entry.color == color);
+        match found {
+            Some(entry) => &entry.symbol,
+            None => panic!("Unable to find entry for {:?}", color),
+        }
+    }
+}
+
+#[derive(Deserialize)]
+pub struct Config {
+    pub grid_every: u32,
+    pub line_weight: f64,
+    pub major_line_weight: f64,
+    pub grid_size: f64,
+    pub font: String,
+}
+
+impl Config {
+    pub fn scale(&self, n: u32) -> f64 {
+        n as f64 * self.grid_size
+    }
+}
+
+impl Default for Config {
+    fn default() -> Config {
+        Config {
+            grid_every: 10,
+            line_weight: 1.0,
+            major_line_weight: 3.0,
+            grid_size: 24.0,
+            font: "Fira Sans 12".to_string(),
+        }
+    }
+}

+ 56 - 0
src/draw.rs

@@ -0,0 +1,56 @@
+use crate::data::{Config, Mapping};
+use crate::image::Image;
+
+pub struct Pattern {
+    pub image: Image,
+    pub config: Config,
+    pub mapping: Mapping,
+}
+
+impl Pattern {
+    pub fn draw(&self, ctx: cairo::Context) -> Result<(), Box<dyn std::error::Error>> {
+        ctx.set_source_rgb(1.0, 1.0, 1.0);
+        ctx.paint()?;
+
+        let layout = pangocairo::functions::create_layout(&ctx).unwrap();
+        let font = pango::FontDescription::from_string(&self.config.font);
+        layout.set_width(2880);
+        layout.set_font_description(Some(&font));
+
+        ctx.set_source_rgb(0.0, 0.0, 0.0);
+        for i in 0..=self.image.width {
+            ctx.move_to(self.config.scale(i), 0.0);
+            ctx.line_to(self.config.scale(i), self.config.scale(self.image.height));
+            ctx.set_line_width(if i % self.config.grid_every == 0 {
+                self.config.major_line_weight
+            } else {
+                self.config.line_weight
+            });
+            ctx.stroke()?;
+        }
+        for j in 0..=self.image.height {
+            ctx.move_to(0.0, self.config.scale(j));
+            ctx.line_to(self.config.scale(self.image.width), self.config.scale(j));
+            ctx.set_line_width(if j % self.config.grid_every == 0 {
+                self.config.major_line_weight
+            } else {
+                self.config.line_weight
+            });
+            ctx.stroke()?;
+        }
+
+        ctx.set_source_rgb(0.0, 0.0, 0.0);
+
+        for ((x, y), pixel) in self.image.iter() {
+            let l = self.mapping.lookup(pixel);
+
+            if !l.is_empty() {
+                ctx.move_to(self.config.scale(x) + 5.0, self.config.scale(y) + 3.0);
+                layout.set_text(l);
+                pangocairo::functions::show_layout(&ctx, &layout);
+            }
+        }
+
+        Ok(())
+    }
+}

+ 16 - 122
src/main.rs

@@ -1,89 +1,19 @@
-use std::fs::File;
-
-use clap::Parser;
-use serde::Deserialize;
-
+mod data;
+mod draw;
 mod image;
+mod opts;
 
-use crate::image::{Image, Pixel};
-
-#[derive(Deserialize, Debug)]
-struct ColorEntry {
-    color: Pixel,
-    symbol: String,
-}
-
-#[derive(Deserialize, Debug)]
-struct Mapping(Vec<ColorEntry>);
-
-impl Mapping {
-    fn load(path: impl AsRef<std::path::Path>) -> Result<Mapping, Box<dyn std::error::Error>> {
-        Ok(serde_yaml::from_reader(File::open(path)?)?)
-    }
-
-    fn lookup(&self, color: Pixel) -> &str {
-        let found = self.0.iter().find(|entry| entry.color == color);
-        match found {
-            Some(entry) => &entry.symbol,
-            None => panic!("Unable to find entry for {:?}", color),
-        }
-    }
-}
-
-#[derive(Deserialize)]
-struct Config {
-    grid_every: u32,
-    line_weight: f64,
-    major_line_weight: f64,
-    grid_size: f64,
-    font: String,
-}
-
-impl Config {
-    fn scale(&self, n: u32) -> f64 {
-        n as f64 * self.grid_size
-    }
-}
-
-impl Default for Config {
-    fn default() -> Config {
-        Config {
-            grid_every: 10,
-            line_weight: 1.0,
-            major_line_weight: 3.0,
-            grid_size: 24.0,
-            font: "Fira Sans 12".to_string(),
-        }
-    }
-}
-
-#[derive(Parser, Debug)]
-#[clap(author, version, about, long_about = None)]
-struct Options {
-    image: String,
-    mapping: String,
-    output: Option<String>,
-
-    #[clap(long, default_value_t = 10)]
-    grid: u32,
-
-    #[clap(long, default_value_t = 1.0)]
-    line_weight: f64,
-
-    #[clap(long, default_value_t = 3.0)]
-    major_line_weight: f64,
-
-    #[clap(long, default_value_t = 24.0)]
-    size: f64,
+use clap::Parser;
 
-    #[clap(long, default_value_t = String::from("Fira Sans 12"))]
-    font: String,
-}
+use crate::data::{Config, Mapping};
+use crate::draw::Pattern;
+use crate::image::Image;
+use crate::opts::Options;
 
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     let opts = Options::parse();
 
-    let img = Image::load(opts.image)?;
+    let image = Image::load(opts.image)?;
     let mapping = Mapping::load(opts.mapping)?;
 
     let config = Config {
@@ -95,53 +25,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
     };
 
     let surf = cairo::SvgSurface::new(
-        config.scale(img.width),
-        config.scale(img.height),
+        config.scale(image.width),
+        config.scale(image.height),
         Some(opts.output.unwrap_or_else(|| "output.svg".to_string())),
     )?;
 
-    let ctx = cairo::Context::new(&surf)?;
-    ctx.set_source_rgb(1.0, 1.0, 1.0);
-    ctx.paint()?;
-
-    let layout = pangocairo::functions::create_layout(&ctx).unwrap();
-    let font = pango::FontDescription::from_string(&config.font);
-    layout.set_width(2880);
-    layout.set_font_description(Some(&font));
-
-    ctx.set_source_rgb(0.0, 0.0, 0.0);
-    for i in 0..=img.width {
-        ctx.move_to(config.scale(i), 0.0);
-        ctx.line_to(config.scale(i), config.scale(img.height));
-        ctx.set_line_width(if i % config.grid_every == 0 {
-            config.major_line_weight
-        } else {
-            config.line_weight
-        });
-        ctx.stroke()?;
-    }
-    for j in 0..=img.height {
-        ctx.move_to(0.0, config.scale(j));
-        ctx.line_to(config.scale(img.width), config.scale(j));
-        ctx.set_line_width(if j % config.grid_every == 0 {
-            config.major_line_weight
-        } else {
-            config.line_weight
-        });
-        ctx.stroke()?;
-    }
-
-    ctx.set_source_rgb(0.0, 0.0, 0.0);
-
-    for ((x, y), pixel) in img.iter() {
-        let l = mapping.lookup(pixel);
-
-        if !l.is_empty() {
-            ctx.move_to(config.scale(x) + 5.0, config.scale(y) + 3.0);
-            layout.set_text(l);
-            pangocairo::functions::show_layout(&ctx, &layout);
-        }
+    Pattern {
+        image,
+        config,
+        mapping,
     }
+    .draw(cairo::Context::new(&surf)?)?;
 
     surf.finish();
 

+ 24 - 0
src/opts.rs

@@ -0,0 +1,24 @@
+use clap::Parser;
+
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+pub struct Options {
+    pub image: String,
+    pub mapping: String,
+    pub output: Option<String>,
+
+    #[clap(long, default_value_t = 10)]
+    pub grid: u32,
+
+    #[clap(long, default_value_t = 1.0)]
+    pub line_weight: f64,
+
+    #[clap(long, default_value_t = 3.0)]
+    pub major_line_weight: f64,
+
+    #[clap(long, default_value_t = 24.0)]
+    pub size: f64,
+
+    #[clap(long, default_value_t = String::from("Fira Sans 12"))]
+    pub font: String,
+}