Skip to content

Commit

Permalink
Remove in source geometry types in favour of Kurbo
Browse files Browse the repository at this point in the history
  • Loading branch information
staticintlucas committed Jul 27, 2023
1 parent a97f307 commit fac7ce6
Show file tree
Hide file tree
Showing 18 changed files with 661 additions and 3,177 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ categories = ["command-line-utilities", "graphics", "multimedia::images", "rende
interp = { version = "1.0", features = ["interp_array"] }
itertools = "0.10"
kle-serial = "0.2"
kurbo = "0.9"
log = "0.4"
rgb = { version = "0.8", default-features = false }
serde = { version = "1.0", default-features = false, features = ["derive"] }
Expand Down
31 changes: 16 additions & 15 deletions src/drawing/svg/font.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use itertools::Itertools;
use kurbo::{Affine, BezPath, Shape, Vec2};
use svg::node::element::Path as SvgPath;

use crate::font::Font;
use crate::key::Key;
use crate::profile::Profile;
use crate::utils::{Path, Vec2};

pub trait Draw {
fn draw_legends(&self, profile: &Profile, key: &Key) -> Vec<SvgPath>;
Expand All @@ -21,18 +21,20 @@ impl Draw for Font {
let mut path = self.text_path(&legend.text);

let scale = profile.text_height.get(legend.size) / self.cap_height;
path.scale(Vec2::from(scale));
path.apply_affine(Affine::scale(scale));

let align = Vec2::new(
(j as f64) / ((key.legends.len() - 1) as f64),
(i as f64) / ((key.legends[0].len() - 1) as f64),
);
let margin = profile.text_margin.get(legend.size);
let point = margin.position() + (margin.size() - path.bounds.size()) * align;
path.translate(point - path.bounds.position());
let bounds = path.bounding_box();
let size = margin.size() - bounds.size();
let point = margin.origin() + (align.x * size.width, align.y * size.height);
path.apply_affine(Affine::translate(point - bounds.origin()));

let svg_path = SvgPath::new()
.set("d", path)
.set("d", path.to_svg())
.set("fill", legend.color.to_string())
.set("stroke", "none");

Expand All @@ -45,16 +47,16 @@ impl Draw for Font {
}

impl Font {
fn text_path(&self, text: &str) -> Path {
let mut path = Path::new();
fn text_path(&self, text: &str) -> BezPath {
let mut path = BezPath::new();

let first = if let Some(first) = text.chars().next() {
self.glyphs.get(&first).unwrap_or(&self.notdef)
} else {
return path;
};

path.append(first.path.clone());
path.extend(first.path.clone());
text.chars()
.map(|char| self.glyphs.get(&char).unwrap_or(&self.notdef))
.tuple_windows()
Expand All @@ -68,16 +70,16 @@ impl Font {
})
.for_each(|(pos, glyph)| {
let mut glyph = glyph.path.clone();
glyph.translate(Vec2::new(pos, 0.));
path.append(glyph);
glyph.apply_affine(Affine::translate((pos, 0.)));
path.extend(glyph);
});
path
}
}

#[cfg(test)]
mod tests {
use crate::utils::PathSegment;
use kurbo::PathEl;

use super::*;

Expand All @@ -98,14 +100,13 @@ mod tests {
let font = Font::from_ttf(&std::fs::read("tests/fonts/demo.ttf").unwrap()).unwrap();
let path = font.text_path("AV");
assert_eq!(
path.data
.into_iter()
.filter(|seg| matches!(seg, PathSegment::Move(..)))
path.into_iter()
.filter(|seg| matches!(seg, PathEl::MoveTo(..)))
.count(),
3
);

let path = font.text_path("");
assert!(path.data.is_empty());
assert_eq!(path.into_iter().count(), 0);
}
}
40 changes: 25 additions & 15 deletions src/drawing/svg/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
mod font;
mod path;
mod profile;

use kurbo::{Affine, Point, Rect, Size};
use svg::node::element::Group;
use svg::Document;

use crate::drawing::Drawing;
use crate::key::Key;
use crate::utils::Vec2;

use font::Draw as _;
use profile::Draw as _;
Expand All @@ -19,23 +18,34 @@ pub trait ToSvg {
impl ToSvg for Drawing {
#[must_use]
fn to_svg(&self) -> String {
let key_size = self
let bounds = self
.keys
.iter()
.map(|k| k.position + k.shape.size())
.fold(Vec2::from(1.), Vec2::max);

// scale from keyboard units to drawing units (milliunits)
let scale = Vec2::from(1e3);
let size = key_size * scale;
.map(|k| k.position + k.shape.size().to_vec2())
.fold(
Rect::from_origin_size(Point::ORIGIN, Size::new(1., 1.)),
|r, p| r.union_pt(p),
);

// w and h are in dpi units, the 0.75 is keyboard units per inch
let Vec2 { x, y } = key_size * self.options.dpi * 0.75;
let Size { width, height } = bounds.size() * self.options.dpi * 0.75;

// scale from keyboard units to drawing units (milliunits)
let bounds = bounds.scale_from_origin(1e3);

let document = Document::new()
.set("width", format!("{}", (1e5 * x).floor() / 1e5))
.set("height", format!("{}", (1e5 * y).floor() / 1e5))
.set("viewBox", format!("0 0 {:.0} {:.0}", size.x, size.y));
.set("width", format!("{}", (1e5 * width).floor() / 1e5))
.set("height", format!("{}", (1e5 * height).floor() / 1e5))
.set(
"viewBox",
format!(
"{:.0} {:.0} {:.0} {:.0}",
bounds.origin().x,
bounds.origin().y,
bounds.size().width,
bounds.size().height
),
);

let document = self
.keys
Expand All @@ -49,8 +59,8 @@ impl ToSvg for Drawing {

impl Drawing {
fn draw_key(&self, key: &Key) -> Group {
let scale = Vec2::from(1e3);
let pos = key.position * scale;
// scale from keyboard units to drawing units (milliunits)
let pos = Affine::scale(1e3) * key.position;

let result = Group::new().set("transform", format!("translate({}, {})", pos.x, pos.y));

Expand Down
Loading

0 comments on commit fac7ce6

Please sign in to comment.