2 # -*- coding: utf-8 -*-
4 # Copyright (C) 2009, mshio <mshio@users.sourceforge.jp>
6 # This program is free software: you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import xml.parsers.expat
25 COPYRIGHT = 'Copyright: (c) 2008-2009 mshio <mshio@users.sourceforge.jp>'
29 FontForge が書き出した SVG ファイルの内容を書き換え、
30 ウェブブラウザで表示できるようにするためのクラスです。
32 インスタンスを生成した後、execute メソッドを呼び出してください。
34 This class is for converting SVG files that are generated by FontForge
35 to ones that can be displayed by a web browser.
37 After getting an instance, call its execute method.
40 def __init__(self, fill_color, comment):
45 fill_color -- SVG のパスを塗りつぶすための色。文字列
46 comment -- コピーライトコメントを付けるかどうか。True/False
51 fill_color -- color name for filling svg pathes.
52 comment -- True if adding copyright comment.
54 self.fill_color = fill_color
55 self.with_comment = comment
57 def execute(self, glyph, file):
59 FontForge が書き出した SVG ファイルを解析し、目的の形式に書き換えます。
62 glyph -- FontForge のもつグリフオブジェクト
63 file -- FontForge の書き出した SVG ファイルのファイル名。文字列
65 Parses the SVG file that is output by FontForge, and outputs a new
66 SVG file that can be displayed by a web browser.
74 c = self.get_contents(file)
75 self.out = open(file, 'w')
76 self.parser.Parse(c, 1)
78 print sys.exc_info()[0]
81 def setup(self, glyph):
82 '''内部にもつ XML パーサーのセットアップを行います。'''
84 self.parser = xml.parsers.expat.ParserCreate()
85 self.parser.XmlDeclHandler = self.start_xml_declaration
86 self.parser.StartDoctypeDeclHandler = self.start_doctype_declaration
87 self.parser.StartElementHandler = self.start_element
88 self.parser.EndElementHandler = self.end_element
90 def get_contents(self, file):
91 '''指定したファイルの内容を読み込んで返します。'''
97 def start_xml_declaration(self, version, encoding, standalone):
98 '''XML 宣言部分のパースと書き出しを行います。'''
99 self.out.write('<?xml')
101 self.out.write(' version="%s"' % version)
103 self.out.write(' encoding="%s"' % encoding)
105 val = 'yes' if standalone == 1 else 'no'
106 self.out.write(' standalone="%s"' % val)
109 def start_doctype_declaration(self, doctype, sys_id, pub_id, has_subset):
110 '''DOCTYPE 部分のパースと書き出しを行います。'''
111 self.out.write('<!DOCTYPE %s' % doctype)
113 self.out.write(' PUBLIC "%s"' % pub_id)
115 self.out.write(' "%s"' % sys_id)
118 def start_element(self, name, attrs):
120 各要素の開始部分を読み込み、その部分の書き出しを行います。
121 要素名が 'svg' の場合、xmlns 属性を付加し、さらに viewBox の値を変更し、
122 またさらにコピーライトの出力が指示されている場合は、svg 要素の後に
123 metadata 要素を追加し、そこにコピーライトを出力します。
124 要素名が 'path' の場合は、fill 属性の有無をチェックし、
127 self.out.write('<%s' % name)
128 is_svg = name == 'svg'
129 is_path = name == 'path'
131 self.out.write(' xmlns="http://www.w3.org/2000/svg"')
132 for k in attrs.keys():
133 if is_svg and k == 'viewBox':
134 org = attrs[k].split()
135 w = self.glyph.width - int(org[0])
136 # here, using magic numbers at the values of top and height.
137 # if using this script for some other fonts,
138 # you might have to change these values.
139 val = '%s -100 %d 1200' % (org[0], w)
140 self.out.write(' %s="%s"' % (k, val))
141 elif is_path and k == 'fill':
142 self.out.write(' %s="%s"' % (k, self.fill_color))
144 self.out.write(' %s="%s"' % (k, attrs[k]))
146 # output copyright string
147 if is_svg and self.with_comment:
148 self.out.write('<metadata><![CDATA[ %s ]]></metadata>' % COPYRIGHT)
150 def end_element(self, name):
151 '''各要素の終了部分を読み込み、その部分の書き出しを行います。'''
152 self.out.write('</%s>' % name)
157 def make_svg(customizer, glyph, output_dir):
159 SVG ファイルの生成と書き換えを行います。
161 まず FontForge の export 機能で SVG ファイルを生成し、
162 次いで SvgCustomizer でその内容を書き換えます。
165 customizer -- SvgCustomizer のインスタンス
166 glyph -- 書き出す対象のグリフオブジェクト
167 output_dir -- 出力先のディレクトリ
169 Exports a SVG file from the specified glyph, and
170 outputs new one that can be displayed with a web browser.
173 customizer -- an instance of SvgCustomizer
174 glyph -- target glyph object
175 output_dir -- directory for SVG files that will be outputed by this script
177 path = '%s/%04x.svg' % (output_dir, glyph.unicode)
179 glyph.export(path, 1)
180 customizer.execute(glyph, path)
183 if __name__ == '__main__':
185 class InvalidArgumentError(Exception):
186 '''コマンドライン引数が正しくない場合に生成される例外です。'''
187 def __init__(self, value):
193 第一引数はフォントファイル、第二引数は保存先のディレクトリです。
197 SVG のパスを塗りつぶす色を指定します。
198 省略すると、black が指定されたことになります。
200 コピーライト(内容は固定)を含める場合に指定します。
201 コピーライトは、metadata のデータとして挿入されます。
203 フォントが持つ全グリフではなく、特定の文字のみの
204 SVG ファイルを出力したい場合に指定します。
205 指定は、16 進数の文字コード(Unicode)で行います。
207 Processes the arguments of command line.
208 The first of them is font file path, and the second of them is path of
209 directory in which the svg files will be stored.
210 The options are like this:
213 The color name with which fill the svg pathes.
216 When this option is specified, the copyright is written as
217 'metadata' in each svg files.
219 Character code (hex). When this option is specified,
220 this script will output only a SVG file of the specified character.
221 When not, it will output ones of all glyphs.
223 usage = 'usage: %prog [-f color] [-c] fontfile directory'
224 p = optparse.OptionParser(usage=usage)
225 p.add_option('-f', '--fill', dest='color', default='black',
226 help='name of color that is used when filling the svg pathes')
227 p.add_option('-c', '--copyright', dest='copyright',
228 action='store_true', default=False,
229 help="write mshio's copyright in each output files")
230 p.add_option('-g', '--glyph', dest='code', default=None,
231 help='char code that wants to be output')
232 (opt, args) = p.parse_args()
235 p.error('incorrect number of arguments')
236 raise InvalidArgumentError
238 return (args[0], args[1], opt.color, opt.copyright, opt.code)
242 (font_path, output_dir, color_name, comment, code) = parse_args()
243 except InvalidArgumentError:
246 char_code = int(code, 16) if code else None
248 customizer = SvgCustomizer(color_name, comment)
249 font = fontforge.open(font_path)
251 make_svg(customizer, font[char_code], output_dir)
256 if glyph.unicode > 0:
257 make_svg(customizer, glyph, output_dir)