らんだむな記憶

blogというものを体験してみようか!的なー

Rust 版 fontTools (3)

Rustでパッケージ(クレート)インストールから使用するまでの軌跡 - Qiita を参考に fonttools-rs を使ってみたい。

$ cargo new ft_sample
     Created binary (application) `ft_sample` package

でサンプルプロジェクトを作成。Cargo.toml を編集して

...
[dependencies]
fonttools = "0.1.0"

とする。*1

src/main.rs を fonttools - Rust のサンプルを元に、入力ファイルだけ指定できるようにして、

use std::env;
use fonttools::font::{self, Table};
use fonttools::name::{NameRecord, NameRecordID};

fn main() {
    let args: Vec<String> = env::args().collect();

    let font_path = &args[1];

    // Load a font (tables are lazy-loaded)
    let fontfile = File::open(font_path).unwrap();
    use std::fs::File;
    let mut myfont = font::load(fontfile).expect("Could not load font");

    // Access an existing table
    if let Table::Name(name_table) = myfont.get_table(b"name")
            .expect("Error reading name table")
            .expect("There was no name table") {
        // Manipulate the table (table-specific)
        name_table.records.push(NameRecord::windows_unicode(
            NameRecordID::LicenseURL,
            "http://opensource.org/licenses/OFL-1.1"
        ));
    }
    let mut outfile = File::create("Test-with-OFL.otf").expect("Could not create file");
    myfont.save(&mut outfile);
}

として

cargo build

でビルドできた。target の下に色々と依存クレートをビルドして配置するので結構時間がかかる。300MB くらいのプロジェクトになった・・・。なお、リビルドの際には

$ cargo build
   Compiling ft_sample v0.1.0 (/home/xxx/ft_sample)
    Finished dev [unoptimized + debuginfo] target(s) in 1.16s

みたいな感じですぐに終わる。

動作を検証してみよう。

$ curl -L https://github.com/adobe-fonts/source-sans/raw/release/OTF/SourceSans3-Regular.otf -o SourceSans3-Regular.otf

SSP をダウンロードしてくる。

$ target/debug/ft_sample SourceSans3-Regular.otf 
Warning: no glyf table

して

$ ttx -t name SourceSans3-Regular.otf
$ ttx -t name Test-with-OFL.otf

でそれぞれの name テーブルを dump する。

$ diff -u SourceSans3-Regular.ttx Test-with-OFL.ttx
--- SourceSans3-Regular.ttx	2022-01-03 12:20:57.038408465 +0000
+++ Test-with-OFL.ttx	2022-01-03 12:23:54.832466500 +0000
@@ -389,6 +389,9 @@
     <namerecord nameID="284" platformID="3" platEncID="1" langID="0x809">
       Dotted zero [ 0 ]
     </namerecord>
+    <namerecord nameID="14" platformID="3" platEncID="1" langID="0x409">
+      http://opensource.org/licenses/OFL-1.1
+    </namerecord>
   </name>

となるので、確かに書き加えられたことが確認できた。

コンパイルしないとならないぶん、オリジナルの Python 版に比べて手間がかかるが、重い処理をする場合に pybind11 で C に逃がすとかしなくても良さそうなので、便利なこともあるかもしれない。

*1:バージョンの指定もしないと cargo build で怒られた・・・。