読者です 読者をやめる 読者になる 読者になる

しろもじメモランダム

文字についてあれこれと。

即席でフォントを作ってみた@サマースクール

書体 手書き

何か発表しないといけないらしい

サマースクールに参加しようと問い合わせをしたのは開催当日2日前、8月18日になってからのこと。返信のメールによると幸いにもまだ一人分空きがあったのだが、

その後の勉強会では
参加者のみなさん一人ずつにお話をしていただきます。
持ち時間は30分です。
テーマは自由ですが、しいてつければ「私の仕事」
30分、しゃべってもらってもいいですし、
参加者に質問を投げかけて応えてもらいながら進めるとか
進行は自由に考えてください。

なんと。発表が必須らしい。おいおいおい初耳だよやっべどうしよと焦る焦る。

文字や印刷関係の仕事をしているわけでもないし、かといって30分話せるようなネタを持ち合わせているわけでもない。ネタがあったらどんどんこのブログに書いてしまう性質なので、ストックなんてものは基本的にない。悩みに悩んだ挙句、最終的に「即席でフォントを作ってみよう」というテーマにした。

元ネタは、以前動画を作ってわりと好評だったこの記事*1

発表の場で作ってみた


今回は時間もなかったので、A4の用紙に一人10文字ずつ書いていただき、それを10人分、計100文字からなるひらがなフォントを作成することにした。

これをスキャンできれば楽なのだが、残念ながら今回はスキャナーがない。そこでスマートフォンのカメラで用紙を撮影し、手作業で画像を修整した。これに一番時間がかかった(笑)


 ↓↓↓


その後は画像を1文字ずつ切り出し。PerlMagick を利用した。ここからの流れは前回とほとんど同じなので、以前の記事や動画を参考にしてほしい。

#!/usr/bin/perl
# sheet_img/ 内の画像(ka.png など)をグリフごとに分割し、out/pgm/uxxxx.pgm として保存
# usage: perl split.pl

use strict;
use warnings;
use utf8;
binmode(STDOUT, ":utf8");

use File::Basename;
use Image::Magick;

my @files = glob "sheet_img/*";

# 手書きシートの画像を開く
foreach my $file (@files) {
  my $img = Image::Magick->new;
  $img->Read($file);
  splitGlyphs($img, getCodepoints($file));
  undef $img;
}

exit;

sub getCodepoints {
  my $file = shift;
  my %table = (
     a => "あいうえおがぎぐげご",
    ka => "かきくけこざじずぜぞ",
    sa => "さしすせそだぢづでど",
    ta => "たちつてとばびぶべぼ",
    na => "なにぬねのぱぴぷぺぽ",
    ha => "はひふへほぁぃぅぇぉ",
    ma => "まみむめもゃ、ゅ。ょ",
    ya => "やっゆーよ?!・「」",
    ra => "らりるれろ12345",
    wa => "わゐんゑを67890",
  );
  
  my $basename = basename($file, ".png");
  print "$file  $table{$basename}\n";
  
  my @codepoints = unpack "U*", $table{$basename};
  return \@codepoints;
}

# セルに切り分けpgmで保存
sub splitGlyphs {
  my ($img, $codepoints) = @_;

  my ($imgWidth, $imgHeight) = $img->Get('width', 'height');
  my $cellWidth  = $imgWidth  * (4 / 24);
  my $cellHeight = $imgHeight * (4 / 11); 
  my $marginX    = $imgWidth  * (1 / 24);
  my $marginY    = $imgHeight * (3 / 11); 
  my $paddingX   = $cellWidth  * 0.05;
  my $paddingY   = $cellHeight * 0.05;

  foreach my $row (0..1) {
    my $offsetY = $row * ($cellHeight + $marginY);
    foreach my $col (0..4) {
      my $offsetX = $col * ($cellWidth + $marginX);
      my $cellImg = $img->Clone();
      $cellImg->Crop(
        width  => $cellWidth  - 2 * $paddingX,
        height => $cellHeight - 2 * $paddingY,
        x => $offsetX + $paddingX,
        y => $offsetY + $paddingY,
      );
      my $cellCodeStr = sprintf "u%x", (shift @$codepoints);
      $cellImg->Write(type => "Grayscale", filename => "out/pgm/$cellCodeStr.pgm");
    }
  }
}

これで1文字ずつのビットマップ画像に切り分けられたので、Potraceベクターに変換。

#!/bin/bash
# グリフ画像(out/pgm/uxxxx.pgm)を、potraceですべてSVG(out/svg/uxxxx.svg)に変換
# usage: ./pgm2svg.sh

pushd out
  for i in pgm/*.pgm ; do 
    echo $i
    potrace -s $i -W 10cm -H 10cm -o svg/`basename $i .pgm`.svg
  done
popd

あとはお馴染み FontForge を利用して、OpenType フォントに纏め上げる。

#!/usr/bin/fontforge -script

_fontname = "out/sokuseki.otf"
_importfile = "out/svg/u*.svg"

New()

# .notdef作成
Select(0x0000)
SetWidth(1000)
SetGlyphName(".notdef")

# エンコードにUnicodeを指定
Reencode("unicode")

# SVGをすべてインポート
Print("import...")
Import(_importfile, 0)

# 自動ヒントづけOFF
SelectAll()
DontAutoHint()

# 整数値に丸める
RoundToInt()

# 半角スペース作成
Select(0u0020)
SetWidth(500)

# 全角スペース作成
Select(0u3000)
SetWidth(1000)

# フォント情報設定
SetFontNames("SokusekideTsukuttaFont",\
             "Sokusekide Tsukutta Font",\
             "Sokusekide Tsukutta Font",\
             "Medium",\
             "2011.8.21 Osaka DTP no Benkyo-beya Summer School",\
             "1.00") 
SetTTFName(0x411, 1, "即席で作ったフォント")
SetTTFName(0x411, 4, "即席で作ったフォント")
SetOS2Value("WinAscent", 200)
SetOS2Value("WinDescent", 200)
SetOS2Value("HHeadAscent", 200)
SetOS2Value("HHeadDescent", -200)

# OTF生成
Generate(_fontname, "", 0x94)
Print("generated: "+ _fontname)

Close()
Quit()

これで完成。できあがりはこんな感じ。


というわけで

なんとか無事にフォントが完成した。技術的には3年前から何も進歩していないし、そもそもが特に難しいことをやっているわけでもない(ツールさまさまです)ので、いずれはもうちょいスゴいことをやってみたいと思う所存。

*1:いま見返してみるといろいろとツッコミどころが……(笑)