Skip to content

Commit

Permalink
More progress on HTML templates
Browse files Browse the repository at this point in the history
  • Loading branch information
simoncozens committed May 17, 2024
1 parent 05362ca commit 822c2f4
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 57 deletions.
31 changes: 24 additions & 7 deletions src/bin/diffenator3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use clap::{builder::ArgAction, Parser};
use colored::Colorize;
use diffenator3::{
dfont::DFont,
html::{render_output, CSSFontFace},
html::{render_output, CSSFontFace, CSSFontStyle},
render::{test_font_glyphs, test_font_words},
ttj::{jsondiff::Substantial, table_diff},
};
use serde_json::Map;
use std::path::PathBuf;
use std::{error::Error, path::PathBuf};

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
Expand Down Expand Up @@ -63,6 +63,18 @@ struct Cli {
font2: PathBuf,
}

fn die(doing: &str, err: impl Error) -> ! {
eprintln!("Error {}: {}", doing, err);
eprintln!();
eprintln!("Caused by:");
if let Some(cause) = err.source() {
for (i, e) in std::iter::successors(Some(cause), |e| (*e).source()).enumerate() {
eprintln!(" {}: {}", i, e);
}
}
std::process::exit(1);
}

fn show_map_diff(fields: &Map<String, serde_json::Value>, indent: usize, succinct: bool) {
for (field, diff) in fields.iter() {
print!("{}", " ".repeat(indent * 2));
Expand Down Expand Up @@ -127,19 +139,24 @@ fn main() {
}
if cli.words {
let word_diff = test_font_words(&font_a, &font_b);
if word_diff.is_something() {
diff.insert("words".into(), word_diff);
}
diff.insert("words".into(), word_diff);
}
if cli.html {
let font_face_old = CSSFontFace::new(cli.font1.to_str().unwrap(), "old", &font_a);
let font_face_new = CSSFontFace::new(cli.font2.to_str().unwrap(), "new", &font_b);
let font_style_old = CSSFontStyle::new(&font_a, Some("old"));
let font_style_new = CSSFontStyle::new(&font_b, Some("new"));
let value = serde_json::to_value(&diff).unwrap_or_else(|e| {
die("serializing diff", e);
});
let html = render_output(
&serde_json::to_value(&diff).expect("foo"),
&value,
font_face_old,
font_face_new,
font_style_old,
font_style_new,
)
.expect("foo");
.unwrap_or_else(|err| die("rendering HTML", err));
println!("{}", html);
std::process::exit(0);
}
Expand Down
41 changes: 29 additions & 12 deletions src/dfont.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use ucd::Codepoint;

pub struct DFont {
pub backing: Vec<u8>,
pub location: Location,
pub location: Vec<VariationSetting>,
pub normalized_location: Location,
pub codepoints: HashSet<u32>,
}

Expand All @@ -20,7 +21,8 @@ impl DFont {
let mut fnt = DFont {
backing,
codepoints: HashSet::new(),
location: Location::default(),
normalized_location: Location::default(),
location: vec![],
};
let cmap = fnt.fontref().charmap();
fnt.codepoints = cmap.mappings().map(|(cp, _)| cp).collect();
Expand All @@ -29,23 +31,31 @@ impl DFont {

pub fn set_location(&mut self, variations: &str) -> Result<(), String> {
self.location = self.parse_location(variations)?;
self.normalized_location = self.fontref().axes().location(&self.location);
Ok(())
}

pub fn set_instance(&mut self, instance: &str) -> Result<(), String> {
let font = self.fontref();
let location = font
let instance = self
.fontref()
.named_instances()
.iter()
.find(|ni| {
font.localized_strings(ni.subfamily_name_id())
self.fontref()
.localized_strings(ni.subfamily_name_id())
.any(|s| instance == s.chars().collect::<Cow<str>>())
})
.map_or_else(
|| Err(format!("No instance named {}", instance)),
|ni| Ok(ni.location()),
);
self.location = location?;
.ok_or_else(|| format!("No instance named {}", instance))?;
let user_coords = instance.user_coords();
let location = instance.location();
self.location = self
.fontref()
.axes()
.iter()
.zip(user_coords)
.map(|(a, v)| (a.tag(), v).into())
.collect();
self.normalized_location = location;
Ok(())
}

Expand All @@ -59,6 +69,13 @@ impl DFont {
.map_or_else(|| "Unknown".to_string(), |s| s.chars().collect())
}

pub fn style_name(&self) -> String {
self.fontref()
.localized_strings(NameId::SUBFAMILY_NAME)
.english_or_first()
.map_or_else(|| "Regular".to_string(), |s| s.chars().collect())
}

pub fn is_color(&self) -> bool {
self.fontref()
.table_directory
Expand Down Expand Up @@ -91,7 +108,7 @@ impl DFont {
.collect()
}

fn parse_location(&self, variations: &str) -> Result<Location, String> {
fn parse_location(&self, variations: &str) -> Result<Vec<VariationSetting>, String> {
let mut settings: Vec<VariationSetting> = vec![];
for variation in variations.split(',') {
let mut parts = variation.split('=');
Expand All @@ -102,7 +119,7 @@ impl DFont {
.map_err(|_| "Couldn't parse value".to_string())?;
settings.push((axis, value).into());
}
Ok(self.fontref().axes().location(&settings))
Ok(settings)
}

pub fn supported_scripts(&self) -> HashSet<String> {
Expand Down
66 changes: 61 additions & 5 deletions src/html.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use lazy_static::lazy_static;
use serde::Serialize;
use serde_json::json;
Expand All @@ -20,8 +22,8 @@ pub struct CSSFontFace {
impl CSSFontFace {
pub fn new(filename: &str, suffix: &str, dfont: &DFont) -> Self {
let familyname = suffix.to_string() + " " + &dfont.family_name();
let cssfamilyname = familyname.replace(' ', "-");
let class_name = cssfamilyname.clone();
let cssfamilyname = familyname.clone();
let class_name = cssfamilyname.replace(' ', "-");
let font_weight = "normal".to_string();
let font_width = "normal".to_string();
let font_style = "normal".to_string();
Expand All @@ -39,6 +41,53 @@ impl CSSFontFace {
}
}

#[derive(Debug, Serialize)]
pub struct CSSFontStyle {
suffix: String,
coords: HashMap<String, f32>,
familyname: String,
style_name: String,
cssfamilyname: String,
class_name: String,
font_variation_settings: String,
}

impl CSSFontStyle {
pub fn new(dfont: &DFont, suffix: Option<&str>) -> Self {
let familyname = dfont.family_name();
let stylename = dfont.style_name();
let coords = dfont
.location
.iter()
.map(|setting| (setting.selector.clone().to_string(), setting.value))
.collect();
let font_variation_settings = dfont
.location
.iter()
.map(|setting| format!("'{}' {}", setting.selector, setting.value))
.collect::<Vec<String>>()
.join(", ");
let (cssfamilyname, class_name) = if let Some(suffix) = suffix {
(
format!("{} {}", suffix, familyname),
format!("{}-{}", suffix, stylename).replace(' ', "-"),
)
} else {
(familyname.to_string(), stylename.replace(' ', "-"))
};

CSSFontStyle {
suffix: stylename.to_string(),
familyname: familyname.to_string(),
style_name: stylename.to_string(),
cssfamilyname,
class_name,
coords,
font_variation_settings,
}
}
}

lazy_static! {
pub static ref TEMPLATES: Tera = {
match Tera::new("templates/*") {
Expand All @@ -55,18 +104,25 @@ pub fn render_output(
value: &serde_json::Value,
font_face_old: CSSFontFace,
font_face_new: CSSFontFace,
font_style_old: CSSFontStyle,
font_style_new: CSSFontStyle,
) -> Result<String, tera::Error> {
TEMPLATES.render(
"diffenator.html",
&Context::from_serialize(json!({
"diff": value,
"diff": {
"tables": value.get("tables").unwrap_or(&json!({})),
"glyphs": value.get("glyphs").unwrap_or(&serde_json::Value::Null),
"words": value.get("words").unwrap_or(&serde_json::Value::Null),
},
"font_faces_old": [font_face_old],
"font_faces_new": [font_face_new],
"font_faces": [],
"font_styles_old": [],
"font_styles_new": [],
"font_styles_old": [font_style_old],
"font_styles_new": [font_style_new],
"font_styles": [],
"pt_size": 20,
"include_ui": true,
}))?,
)
}
2 changes: 1 addition & 1 deletion src/render/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<'a> Renderer<'a> {
font,
plan,
scale: font_size,
location: (&dfont.location).into(),
location: (&dfont.normalized_location).into(),
outlines,
}
}
Expand Down
10 changes: 5 additions & 5 deletions templates/CSSFontFace.partial.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@font-face{
src: url("{{ filename }}");
font-family: "{{ cssfamilyname }}";
font-weight: {{ font_weight }};
{% if font_stretch %}font-stretch: {{ font_stretch }};{% endif %}
font-style: {{ font_style }};
src: url("{{ font_face.filename }}");
font-family: "{{ font_face.cssfamilyname }}";
font-weight: {{ font_face.font_weight }};
{% if font_face.font_stretch %}font-stretch: {{ font_face.font_stretch }};{% endif %}
font-style: {{ font_face.font_style }};
}
12 changes: 6 additions & 6 deletions templates/CSSFontStyle.partial.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.{{class_name}}{
font-family: "{{ cssfamilyname }}", "Adobe NotDef";
{% if "wght" in coords %}font-weight: {{coords['wght']}};{% endif %}
{% if "wdth" in coords %}font-stretch: {{coords['wdth']}}%;{% endif %}
{% if "Italic" in stylename %}font-style: italic;{% else %}font-style: normal;{% endif %}
font-variation-settings: {{ font_variation_settings }};
.{{font_class.class_name}}{
font-family: "{{font_class.cssfamilyname }}", "Adobe NotDef";
{% if "wght" in font_class.coords %}font-weight: {{font_class.coords['wght']}};{% endif %}
{% if "wdth" in font_class.coords %}font-stretch: {{font_class.coords['wdth']}}%;{% endif %}
{% if "Italic" in font_class.style_name %}font-style: italic;{% else %}font-style: normal;{% endif %}
{% if font_class.font_variation_settings %} font-variation-settings: {{font_class.font_variation_settings }}; {%endif%}
}
6 changes: 3 additions & 3 deletions templates/Glyph.partial.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div class="cell-word">
<div class="tooltip">
{{ string }}<br>
{{ glyph.string }}<br>
<span class="tooltiptext">
name: {{ name }}<br>
unicode: {{ unicode }}
name: {{ glyph.name }}<br>
unicode: {{ glyph.unicode }}
</span>
</div>
</div>
16 changes: 9 additions & 7 deletions templates/_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,27 +140,27 @@
}

{% for font_face in font_faces_old %}
{{ font_face }}
{% include "CSSFontFace.partial.html" %}
{% endfor %}

{% for font_face in font_faces_new %}
{{ font_face }}
{% include "CSSFontFace.partial.html" %}
{% endfor %}

{% for font_face in font_faces %}
{{ font_face }}
{% include "CSSFontFace.partial.html" %}
{% endfor %}

{% for font_class in font_styles_old %}
{{ font_class }}
{% include "CSSFontStyle.partial.html" %}
{% endfor %}

{% for font_class in font_styles_new %}
{{ font_class }}
{% include "CSSFontStyle.partial.html" %}
{% endfor %}

{% for font_class in font_styles %}
{{ font_class }}
{% include "CSSFontStyle.partial.html" %}
{% endfor %}
{% endblock %}

Expand Down Expand Up @@ -188,7 +188,7 @@ <h2>{% block content_name %}{% endblock %}</h2>
{% block content %}
{% endblock %}
</div>
</body>

<script>

POSITION = "old"
Expand Down Expand Up @@ -301,5 +301,7 @@ <h2>{% block content_name %}{% endblock %}</h2>
{% endblock %}

</script>
</body>

</html>

Loading

0 comments on commit 822c2f4

Please sign in to comment.