Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions gftools-builder/src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};
use serde_json::{Value, json};

pub mod addsubset;
pub mod applyhinting;
pub mod autohint;
pub mod buildstat;
pub mod compress;
Expand Down Expand Up @@ -45,6 +46,8 @@ pub(crate) enum OpStep {
Subspace,
#[serde(rename = "autohint")]
Autohint,
#[serde(rename = "applyHinting")]
ApplyHinting,
#[serde(rename = "instantiateSource")]
InstantiateSource,
#[serde(rename = "removeOverlaps")]
Expand All @@ -65,6 +68,7 @@ impl OpStep {
OpStep::AddSubset => Box::new(addsubset::AddSubset::new()),
OpStep::Subspace => Box::new(subspace::Subspace::new()),
OpStep::Autohint => Box::new(autohint::Autohint::new()),
OpStep::ApplyHinting => Box::new(applyhinting::ApplyHinting::new()),
OpStep::InstantiateSource => Box::new(instantiate_source::InstantiateSource::new()),
OpStep::RemoveOverlaps => Box::new(removeoverlaps::RemoveOverlaps),
OpStep::Fontsetter => Box::new(fontsetter::FontSetter::default()),
Expand Down Expand Up @@ -203,6 +207,17 @@ impl ConfigOperationBuilder {
self
}

pub fn apply_hinting(mut self, hinting_file: &str) -> Self {
self.steps.push(Step::OperationStep {
operation: OpStep::ApplyHinting,
extra: HashMap::new(),
args: Some(hinting_file.to_string()),
input_file: None,
needs: vec![],
});
self
}

pub fn instantiate_source(mut self, location: &DesignLocation) -> Self {
self.steps.push(Step::OperationStep {
operation: OpStep::InstantiateSource,
Expand Down
71 changes: 71 additions & 0 deletions gftools-builder/src/operations/applyhinting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::process::Output;

use crate::{
buildsystem::{DataKind, Operation, OperationOutput},
error::ApplicationError,
};
use gftools::{HintingFile, apply_hinting};

/// Give a compiled TrueType font the hinting of its hinting file (the args).
#[derive(PartialEq, Debug, Default)]
pub(crate) struct ApplyHinting {
args: Option<String>,
}

impl ApplyHinting {
pub fn new() -> Self {
ApplyHinting { args: None }
}
}

impl Operation for ApplyHinting {
fn shortname(&self) -> &str {
"ApplyHinting"
}

fn set_args(&mut self, args: Option<String>) {
self.args = args;
}

fn input_kinds(&self) -> Vec<DataKind> {
vec![DataKind::Bytes]
}

fn output_kinds(&self) -> Vec<DataKind> {
vec![DataKind::Bytes]
}

fn execute(
&self,
inputs: &[OperationOutput],
outputs: &[OperationOutput],
) -> Result<Output, ApplicationError> {
let path = self
.args
.as_deref()
.ok_or_else(|| ApplicationError::Other("applyHinting needs a hinting file".into()))?;
let text = std::fs::read_to_string(path)?;
let file = HintingFile::from_json(&text)
.map_err(|e| ApplicationError::Other(format!("{path}: {e}")))?;
let font = inputs[0].to_bytes()?;
let hinted = apply_hinting(&font, &file)
.map_err(|e| ApplicationError::Other(format!("{path}: {e}")))?;
outputs[0].set_contents(hinted)?;
Ok(Output {
status: std::process::ExitStatus::default(),
stdout: vec![],
stderr: vec![],
})
}

fn description(&self) -> String {
format!(
"Apply the hinting file {}",
self.args.as_deref().unwrap_or("")
)
}

fn identifier(&self) -> String {
format!("ApplyHinting-{}", self.args.as_deref().unwrap_or(""))
}
}
26 changes: 22 additions & 4 deletions gftools-builder/src/recipe_providers/googlefonts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ pub struct GoogleFontsOptions {
#[serde(default)]
pub filename_suffix: Option<String>,

/// A static TTF's own TrueType hinting: output file name -> hinting file
#[serde(default, rename = "hintingFiles")]
pub hinting_files: HashMap<String, String>,

// Options about what we build
#[serde_inline_default(true)]
#[serde(rename = "buildVariable")]
Expand Down Expand Up @@ -202,6 +206,12 @@ impl GoogleFontsOptions {
}

#[allow(dead_code)]
/// The hinting file of a static target, if the config names one
pub fn hinting_file(&self, target: &str) -> Option<&str> {
let name = std::path::Path::new(target).file_name()?.to_str()?;
self.hinting_files.get(name).map(String::as_str)
}

pub fn static_filename(
&self,
instancebase: &str,
Expand Down Expand Up @@ -430,10 +440,15 @@ impl GoogleFontsProvider {
let user_loc = instance_user_location(source, instance)?;
builder = builder.instance(&user_loc);
}
// Remove overlap
builder = builder.remove_overlaps();
// Autohint steps
builder = builder.autohint(None);
if let Some(hinting) = self.options.hinting_file(&target) {
// the font carries its own hinting, which needs its points
builder = builder.apply_hinting(hinting);
} else {
// Remove overlap
builder = builder.remove_overlaps();
// Autohint steps
builder = builder.autohint(None);
}
// VTT steps
builder = builder.fix(&self.options.fix_config);

Expand Down Expand Up @@ -562,6 +577,9 @@ impl GoogleFontsProvider {
}
builder = builder.compile(&self.options.fontc_config);
// Any post-compile steps
if let Some(hinting) = self.options.hinting_file(&target) {
builder = builder.apply_hinting(hinting);
}
// Any VTT steps
// If italic, subspace the axes according to style

Expand Down
1 change: 1 addition & 0 deletions gftools-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ skrifa = { workspace = true }
reqwest = { workspace = true, features = ["blocking", "json"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sha2 = "0.10"
thiserror = { workspace = true }
log = { workspace = true }
toml = { workspace = true }
Expand Down
Loading
Loading