[tech] JavaScript の必要ないソーシャルボタン | Fri, Apr 15. 2016 - 氾濫原 これを作るとき、最初のうちは全てSVGにするぞと意気込んでいて、Ligature Symbols に含まれるものをSVGに変換したらいいのではないかと、いろいろ試していました。

結局その方法はやめたのですが、SVG フォントから、個別の SVG ファイルに変換するスクリプトを雑に書いたので残しておきます。SVG フォント全体だとファイルサイズが大きすぎるので、必要なファイルだけ普通の SVG 画像として抽出するということです。

以下のように perl + XML::LibXML で書きました。グリフ名を引数に与えると、該当するグリフを個別の .svg に書き出します。LigatureSymbols でしか試していませんが、SVG フォントなら他のでもいけるかもしれません。

#!/usr/bin/env perl

use utf8;
use strict;
use warnings;
use v5.10.0;
use lib lib => glob 'modules/*/lib';

use XML::LibXML;

open(my $fh, "<", "LigatureSymbols-2.11.svg") or die "cannot open < input.txt: $!";
my $font = do { local $/; scalar <$fh> };
close $fh;

my $doc = XML::LibXML->load_xml( string => $font, load_ext_dtd => 0 );
my $xpc = XML::LibXML::XPathContext->new($doc);

# get copyright metadata
my $original_metadata = $xpc->findvalue('/svg/metadata');
my $units_per_em = $xpc->findvalue('/svg/defs/font/font-face/@units-per-em');
my $ascent = $xpc->findvalue('/svg/defs/font/font-face/@ascent');
my $bbox = $xpc->findvalue('/svg/defs/font/font-face/@bbox');

for my $glyph_name (@ARGV) {
	my $glyph = $xpc->findnodes(sprintf('/svg/defs/font/glyph[@glyph-name="%s"]', $glyph_name))->[0];
	my $horiz_adv_x = $xpc->findvalue('./@horiz-adv-x', $glyph);

	my $document = XML::LibXML::Document->new('1.0', 'UTF-8');
	my $svg = $document->createElement('svg');
	$svg->setAttribute('width',  $horiz_adv_x);
	$svg->setAttribute('height', $units_per_em);
	# $svg->setAttribute('viewBox', $bbox);
	$svg->setAttribute('xmlns', 'http://www.w3.org/2000/svg');
	$document->setDocumentElement($svg);

	my $metadata = $document->createElement('metadata');
	$metadata->appendChild($document->createTextNode($original_metadata));
	$svg->appendChild($metadata);

	my $path = $document->createElement('path');
	$path->setAttribute('transform', sprintf("scale(1, -1) translate(0,%s)", -$ascent));
	$path->setAttribute('fill', '#fff');
	$path->setAttribute('d', $xpc->findvalue('./@d', $glyph));
	$svg->appendChild($path);

	warn "write to $glyph_name.svg";
	say $document->toString(1) ;

	open(my $fh, ">", "$glyph_name.svg");
	print $fh $document->toString;
	close $fh;
}
  1. トップ
  2. tech
  3. SVGフォントのグリフを個別のSVG画像に変換する
▲ この日のエントリ