1#![allow(clippy::cast_lossless)]
17
18extern crate cairo;
19#[macro_use]
20extern crate clap;
21extern crate core;
22
23use cairo::{Context, Format, ImageSurface, Operator, Rectangle};
24use std::f64::consts::FRAC_PI_2;
25use std::fs::File;
26use std::{io, mem};
27
28use core::deck::cards;
29use core::graphics::*;
30use core::utils::clamp;
31
32const VERSION: &str = env!("CARGO_PKG_VERSION");
33const CARD_ASPECT_RATIO: f64 = 3.5 / 2.25;
34
35fn generate_card_images(path: &str, card_width: i32, border: i32,
36 vertical: bool, scheme: ColorScheme) -> io::Result<()>
37{
38 let card_height = (card_width as f64 / CARD_ASPECT_RATIO).ceil() as i32;
39 let card_rect = Rectangle {
40 x: border as f64,
42 y: border as f64,
43 width: card_width as f64,
44 height: card_height as f64,
45 };
46
47 let mut ctx_width = card_width + border * 2;
49 let mut ctx_height = card_height + border * 2;
50 if vertical {
51 mem::swap(&mut ctx_width, &mut ctx_height);
52 }
53
54 let surface = ImageSurface::create(Format::ARgb32, ctx_width, ctx_height)
56 .expect("Could not create surface.");
57 let ctx = Context::new(&surface);
58 if vertical {
59 ctx.rotate(FRAC_PI_2);
61 ctx.translate(0.0, -ctx_width as f64);
62 }
63
64 for card in cards() {
65 ctx.save();
69 ctx.set_operator(Operator::Clear);
70 ctx.paint();
71 ctx.restore();
72
73 if border > 0 {
74 ctx.rounded_rect(card_rect, card_corner_radius(card_rect));
75 ctx.set_source_gray(0.0);
76 ctx.set_line_width(border as f64 * 2.);
78 ctx.stroke();
79 }
80
81 ctx.draw_card(card, card_rect, None, scheme);
82
83 let filename = format!("{}/{}.png", path, card.index());
84 let mut image = File::create(&filename)?;
85
86 surface.write_to_png(&mut image)
87 .unwrap_or_else(|_| println!("Error writing {}", filename));
88 }
89
90 Ok(())
91}
92
93fn main() {
94 let matches = clap_app!(genpng =>
95 (version: VERSION)
96 (about: "Generate an image for each Marmoset card.")
97 (@arg DIRECTORY: +required "Sets the directory in which to place the images")
98 (@arg VERTICAL: -v --("render-vertically") "Orients cards vertically")
99 (@arg CLASSIC: -c --("classic-colors") "Uses classic SET colors")
100 (@arg BORDER: -b --border +takes_value "Sets the border width in pixels")
101 (@arg WIDTH: -w --width +takes_value "Sets the card width in pixels")
102 ).get_matches();
103
104 let path = matches.value_of("DIRECTORY").unwrap();
105 let width = value_t!(matches, "WIDTH", i32).unwrap_or(350);
106 let border = value_t!(matches, "BORDER", i32).unwrap_or(0);
107 let render_vertically = matches.is_present("VERTICAL");
108 let classic_colors = matches.is_present("CLASSIC");
109
110 let width = clamp(width, (64, 6400));
112 let border = clamp(border, (0, 64));
113 let scheme = if classic_colors { ColorScheme::Classic } else { ColorScheme::CMYK };
114
115 generate_card_images(&path, width, border, render_vertically, scheme)
116 .unwrap_or_else(|e| println!("{}", e));
117}