Commit 6788c5e
utility for exporting fonts from command line
Changed files (8)
addedsrc/BirdfontExport.valamodifiedsrc/ExportTool.valamodifiedsrc/Font.valamodifiedsrc/Glyph.valaaddedsrc/Main.valamodifiedsrc/OpenFontFormatWriter.valamodifiedsrc/Supplement.valamodifiedsrc/wscript
Diff
new file mode 100644@@ -0,0 +1,68 @@+/*+ Copyright (C) 2012 Johan Mattsson++ This program is free software: you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation, either version 3 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program. If not, see <http://www.gnu.org/licenses/>.+*/++namespace Supplement {++/** Stand alone command line utility for exporting fonts. */+class BirdfontExport {+ + public BirdfontExport () {+ }+ + static void print_help (string[] arg) {+ stdout.printf ("Usage: ");+ stdout.printf (arg[0]);+ stdout.printf (" [INPUT FILE]\n");+ }+ + public static int main(string[] arg) {+ ExportTool export;++ LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;+ Log.set_handler (null, levels, Supplement.fatal_warning);+ + if (arg.length != 2) {+ print_help (arg);+ return 1;+ }++ Preferences preferences = new Preferences ();+ preferences.load ();+ + Supplement.args = new Argument ("");+ Supplement.current_font = new Font ();++ // TODO: refactor and remove all gtk stuff from this program+ Gtk.init (ref arg);+ MainWindow window = new MainWindow ("Birdfont");+ window.show_all ();+ + if (!Supplement.get_current_font ().load (arg[1])) {+ stderr.printf (@"Failed to load font $(arg[1]).\n");+ }++ ExportTool.export_svg_font_path (File.new_for_path ("."));+ ExportTool.export_ttf_font_path (File.new_for_path ("."), false);+ + print ("Done\n");+ + return 0;+ }+ +}++}@@ -39,16 +39,29 @@ class ExportTool : Tool { }); } - public static void export_all () {+ public static bool export_all () { Font font = Supplement.get_current_font ();+ bool f; if (font.get_ttf_export ()) {- export_ttf_font ();+ f = export_ttf_font ();+ + if (!f) {+ warning ("Failed to export font");+ return false;+ } } if (font.get_svg_export ()) {- export_svg_font ();+ f = export_svg_font ();++ if (!f) {+ warning ("Failed to export font");+ return false;+ } }+ + return true; } public void export_glyph_to_svg () {@@ -74,8 +87,6 @@ class ExportTool : Tool { return; } - print (@"Writing file $((!)file.get_path ())\n");- try { if (file.query_exists ()) {@@ -328,21 +339,48 @@ os.put_string (""" } public static bool export_ttf_font () {+ Font font = Supplement.get_current_font ();+ File file = font.get_folder ();+ return export_ttf_font_path (file);+ }+ + public static bool export_ttf_font_path (File folder, bool async = true) + requires (Supplement.get_current_font ().font_file != null) {+ Font current_font = Supplement.get_current_font ();+ string path;+ OpenFontFormatWriter fo;+ Font temp_font = new Font ();+ ExportThread th;+ unowned Thread<void*> export_thread;+ File file;+ string temp_file;+ try {- Font font = Supplement.get_current_font ();- File file = font.get_folder ();- file = file.get_child (font.get_name () + ".ttf");- OpenFontFormatWriter fo;- + // create a copy of current font and use it in a separate + // export thread+ temp_file = current_font.save_backup ();+ file = folder.get_child (temp_font.get_name () + ".ttf");+ if (file.query_exists ()) { file.delete (); }++ path = (!) file.get_path ();++ th = new ExportThread (temp_file, path); - fo = new OpenFontFormatWriter ();- fo.open (file);- fo.write_ttf_font (font);- fo.close ();- + if (async) {+ try {+ export_thread = Thread.create<void*> (th.run, true);+ export_thread.join ();+ } catch (ThreadError e) {+ stderr.printf ("%s\n", e.message);+ return false;+ }+ } else {+ th.run ();+ }+ } catch (Error e) { critical (@"$(e.message)"); return false;@@ -350,8 +388,13 @@ os.put_string (""" return true; }- + public static bool export_svg_font () {+ Font font = Supplement.get_current_font ();+ return export_svg_font_path (font.get_folder ());+ }+ + public static bool export_svg_font_path (File folder) { TooltipArea ta = MainWindow.get_tool_tip (); Font font = Supplement.get_current_font (); string file_name = @"$(font.get_name ()).svg";@@ -359,11 +402,9 @@ os.put_string (""" SvgFontFormatWriter fo; try {- file = font.get_folder ();- file = file.get_child (file_name);+ file = folder.get_child (file_name); if (file.query_exists ()) {- stderr.printf (@"ExportTool: Output file (\"$((!) file.get_path ())\") exists. Deleting it.\n"); file.delete (); } @@ -380,6 +421,39 @@ os.put_string (""" ta.show_text (@"Wrote $file_name"); return true; }+++ class ExportThread {++ private string from;+ private string to;++ public ExportThread (string from, string to) {+ this.from = from;+ this.to = to;+ }++ public void* run () {+ OpenFontFormatWriter fo = new OpenFontFormatWriter ();+ Font f = new Font ();+ + try {+ if (!f.load (from)) {+ warning (@"Can't read $from");+ return null;+ }+ + fo.open ((!) File.new_for_path (to));+ fo.write_ttf_font (f);+ fo.close ();+ } catch (Error e) {+ critical (@"$(e.message)");+ return null;+ } + + return null;+ }+ } } }@@ -54,6 +54,7 @@ class Font : GLib.Object { public string? backup_file = null; public string? font_file = null;+ public string? export_dir = null; bool modified = false; @@ -80,6 +81,16 @@ class Font : GLib.Object { modified = true; } + public string get_export_dir () + requires (font_file != null) + {+ if (export_dir == null) {+ return ((!) font_file).substring (0, ((!) font_file).last_index_of ("/") - 1);+ }+ + return (!) export_dir;+ }+ public bool get_ttf_export () { return ttf_export; }@@ -483,23 +494,27 @@ class Font : GLib.Object { g.add_kerning (b, val); } - public void save_backup () {+ /** Returns path to backup file. */+ public string save_backup () { File dir = Supplement.get_backup_directory ();- File temp_file;+ File? temp_file = null; int i = 0; if (backup_file == null) {- temp_file = dir.get_child (@"current_font_$i.ffs");+ temp_file = dir.get_child (@"current_font_$i.ffi"); - while (temp_file.query_exists ()) {+ while (((!) temp_file).query_exists ()) { i++;- temp_file = dir.get_child (@"current_font_$i.ffs");+ temp_file = dir.get_child (@"current_font_$i.ffi"); } - backup_file = temp_file.get_path ();+ backup_file = ((!) temp_file).get_path (); }- ++ assert (backup_file != null); write_font_file ((!) backup_file);+ + return (!) backup_file; } public bool save (string path) {@@ -301,6 +301,8 @@ class Glyph : FontDisplay { public void add_help_lines () { remove_lines (); + assert (!is_null (Supplement.get_current_font ()));+ double bgt = Supplement.get_current_font ().top_limit; Line top_margin_line = new Line ("top margin", bgt, false); top_margin_line.set_color (0.7, 0, 0, 0.5);new file mode 100644@@ -0,0 +1,96 @@+/*+ Copyright (C) 2012 Johan Mattsson++ This program is free software: you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation, either version 3 of the License, or+ (at your option) any later version.++ This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License for more details.++ You should have received a copy of the GNU General Public License+ along with this program. If not, see <http://www.gnu.org/licenses/>.+*/++using Gtk;++namespace Supplement {+ +public static int main(string[] arg) {+ int err_arg;+ File font_file;+ Argument args;+ IdleSource idle;++ Supplement.args = new Argument.command_line (arg);+ args = Supplement.args;+ + if (Supplement.args.has_argument ("--help")) {+ args.print_help ();+ Process.exit (0);+ }++ err_arg = args.validate ();+ if (err_arg != 0) {+ stdout.printf (@"Unknown parameter $(arg [err_arg])\n\n");+ args.print_help ();+ Process.exit (0);+ }++ stdout.printf ("birdfont version %s\n", VERSION); ++ Supplement.current_font = new Font ();++ Supplement.experimental = args.has_argument ("--test");+ Supplement.show_coordinates = args.has_argument ("--show-coordinates");+ Supplement.fatal_wanings = args.has_argument ("--fatal-warning");+ Supplement.win32 = (arg[0].index_of (".exe") > -1);++ Preferences preferences = new Preferences ();+ preferences.load ();+ + if (args.get_file () != "") {+ font_file = File.new_for_path (args.get_file ());+ + if (!font_file.query_exists ()) {+ stderr.printf (@"File $(args.get_file ()) not found.");+ return -1;+ }+ }+ + Gtk.init (ref arg);+ MainWindow window = new MainWindow ("Birdfont");+ window.show_all ();++ if (Supplement.fatal_wanings) {+ LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;+ Log.set_handler (null, levels, Supplement.fatal_warning);+ }+ + idle = new IdleSource ();+ idle.set_callback(() => {+ preferences.load ();+ + if (args.get_file () != "") {+ Supplement.get_current_font ().load (args.get_file ());+ MainWindow.get_toolbox ().select_tool_by_name ("available_characters");+ } else {+ MainWindow.get_tab_bar ().select_tab_name ("Menu");+ }+ + return false;+ });+ + idle.attach (null);+ + Gtk.main ();+ + preferences.set_last_file (Supplement.get_current_font ().get_path ());+ + return 0;+}++}@@ -26,16 +26,25 @@ class OpenFontFormatWriter : Object { DataOutputStream os; DirectoryTable directory_table; + public static Font font; + public OpenFontFormatWriter () { directory_table = new DirectoryTable (); } + public static Font get_current_font () { + return font; + } + public void open (File file) throws Error { + assert (!is_null (file)); + if (file.query_exists ()) { + warning ("File exists in export."); throw new FileError.EXIST("OpenFontFormatWriter: file exists."); } - os = new DataOutputStream(file.create(FileCreateFlags.REPLACE_DESTINATION)); + os = new DataOutputStream(file.create (FileCreateFlags.REPLACE_DESTINATION)); } public void write_ttf_font (Font font) throws Error { @@ -48,7 +57,9 @@ class OpenFontFormatWriter : Object { unichar indice = 0; FontData fd; uint l; - + + this.font = font; + directory_table.process (); tables = directory_table.get_tables (); @@ -628,7 +639,7 @@ class LocaTable : Table { public void process (GlyfTable glyf_table, HeadTable head_table) { FontData fd = new FontData (); - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); uint32 last = 0; uint32 prev = 0; int i = 0; @@ -737,7 +748,7 @@ class GlyfTable : Table { public double get_capheight () { double x1, x2, y1, y2; - Font f = Supplement.get_current_font (); + Font f = OpenFontFormatWriter.get_current_font (); double max = double.MIN; foreach (Glyph g in glyphs) { @@ -1342,7 +1353,7 @@ class GlyfTable : Table { double x, y; - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); int glyph_offset; uint len; @@ -1448,7 +1459,7 @@ class GlyfTable : Table { foreach (Path p in g.path_list) { p = p.get_quadratic_points (); - print (@"\n"); + foreach (EditPoint e in p.points) { x = e.x * UNITS - prev - g.left_limit * UNITS; @@ -1581,7 +1592,7 @@ class GlyfTable : Table { public void create_glyph_table () { Glyph? gl; Glyph g; - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); uint32 indice; // add notdef. character at index zero + other special chars first @@ -1845,7 +1856,7 @@ class CmapSubtableWindowsUnicode : CmapSubtable { s.append_unichar (start_char); e.append_unichar (end_char); - // print (@"New range $(s.str) - $(e.str) delta: $delta_offset, range: $range_offset\n"); + print (@"New range $(s.str) - $(e.str) delta: $delta_offset, range: $range_offset\n"); } public void process (FontData fd, GlyfTable glyf_table) { @@ -2351,7 +2362,7 @@ class HheaTable : Table { } public void process () { - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); FontData fd = new FontData (); Fixed version = 1 << 16; @@ -2489,7 +2500,7 @@ class HmtxTable : Table { public void process () { FontData fd = new FontData (); - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); int16 advance; int16 extent; @@ -2762,7 +2773,7 @@ class NameTable : Table { public void process () { FontData fd = new FontData (); - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); uint16 len = 0; string t; uint16 p; @@ -2865,7 +2876,7 @@ class Os2Table : Table { public void process (GlyfTable glyf_table) { FontData fd = new FontData (); - Font font = Supplement.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); int16 ascender; int16 descender; @@ -3065,9 +3076,7 @@ class PostTable : Table { for (int j = 0; j < len; j++) { name.append_c (dis.read_char ()); } - - // print (@"Name gid: $gid len: $len: $(name.str)\n"); - + names.append (name.str); } @@ -4880,16 +4889,7 @@ class DirectoryTable : Table { kern_table.length = length; } } - - // FIXA: delete - /* - FontData fd = new FontData (); - fd.write_table (dis, post_table.offset, post_table.length); - fd.print (); - */ - - printd (@"fd.write_table (dis, post_table.offset, post_table.length) $(post_table.offset) $(post_table.length)\n"); - + head_table.parse (dis); if (!validate_tables (dis, file)) { @@ -21,12 +21,12 @@ namespace Supplement { class Supplement { public static Argument args; - public static bool experimental; - public static bool show_coordinates; - public static bool fatal_wanings; - public static bool win32; + public static bool experimental = false; + public static bool show_coordinates = false; + public static bool fatal_wanings = false; + public static bool win32 = false; - static Font current_font; + public static Font current_font; public static Font get_current_font () { return current_font; @@ -85,79 +85,7 @@ class Supplement { public static string? get_argument (string param) { return args.get_argument (param); - } - - public static int main(string[] arg) { - int err_arg; - File font_file; - - args = new Argument.command_line (arg); - - if (args.has_argument ("--help")) { - args.print_help (); - Process.exit (0); - } - - err_arg = args.validate (); - if (err_arg != 0) { - stdout.printf (@"Unknown parameter $(arg [err_arg])\n\n"); - args.print_help (); - Process.exit (0); - } - - stdout.printf ("birdfont version %s\n", VERSION); - - experimental = args.has_argument ("--test"); - show_coordinates = args.has_argument ("--show-coordinates"); - fatal_wanings = has_argument ("--fatal-warning"); - win32 = (arg[0].index_of (".exe") > -1); - - Preferences preferences = new Preferences (); - preferences.load (); - - current_font = new Font (); - - if (args.get_file () != "") { - font_file = File.new_for_path (args.get_file ()); - - if (!font_file.query_exists ()) { - stderr.printf (@"File $(args.get_file ()) not found."); - return -1; - } - } - - Gtk.init (ref arg); - MainWindow window = new MainWindow ("Birdfont"); - window.show_all (); - - if (fatal_wanings) { - LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING; - Log.set_handler (null, levels, fatal_warning); - } - - IdleSource idle = new IdleSource (); - idle.set_callback(() => { - preferences.load (); - - if (args.get_file () != "") { - current_font.load (args.get_file ()); - MainWindow.get_toolbox ().select_tool_by_name ("available_characters"); - } else { - MainWindow.get_tab_bar ().select_tab_name ("Menu"); - } - - return false; - }); - - idle.attach (null); - - Gtk.main (); - - preferences.set_last_file (get_current_font ().get_path ()); - - return 0; - } - + } } internal bool is_null (void* n) { @@ -1,4 +1,4 @@-SUPPLEMENT_MAIN = [ +BIRDFONT = [ 'Argument.vala', 'Font.vala', 'BackgroundTool.vala', @@ -59,16 +59,35 @@ SUPPLEMENT_MAIN = [ 'ZoomTool.vala' ] -TEST = [ - 'TestSupplement.vala' +BIRDFONT_MAIN = [ + 'Main.vala' +] + +BIRDFONT_EXPORT = [ + 'BirdfontExport.vala' +] + +PARAM = [ + '--thread', + '--disable-warnings', + '--enable-experimental', + '--enable-experimental-non-null', + '--vapidir=../../' ] def build (bld): bld.program ( target = 'birdfont', - param = ['--disable-warnings', '--enable-experimental', '--enable-experimental-non-null', '--vapidir=../../'], + param = PARAM, packages = 'gtk+-2.0 libxml-2.0', uselib = 'GTK GLIB GIO XML WEB', - source = SUPPLEMENT_MAIN + source = BIRDFONT + BIRDFONT_MAIN ) + bld.program ( + target = 'birdfont-export', + param = PARAM, + packages = 'gtk+-2.0 libxml-2.0', + uselib = 'GTK GLIB GIO XML WEB', + source = BIRDFONT + BIRDFONT_EXPORT + )