Commit 03b1778
Import SVG files for color fonts
Changed files (9)
modifiedbirdfont-test/TestRunner.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/ImportUtils.valamodifiedlibbirdfont/Menu.valamodifiedlibbirdfont/MoveTool.valamodifiedlibbirdfont/OpenFontFormat/SvgTable.valamodifiedlibbirdfont/SvgFont.valamodifiedlibbirdfont/SvgParser.valamodifiedresources/linux/birdfont-import.1
Diff
@@ -37,7 +37,7 @@ public class TestRunner : NativeWindow, GLib.Object { if (type == "SVG") { File f = File.new_for_path (file); Font font = new Font ();- import_svg_file (font, f);+ import_svg_file (font, f, SvgType.REGULAR); } else if (type == "BF") { Font font = new Font (); font.set_font_file (file);@@ -140,26 +140,37 @@ public class Glyph : FontDisplay { public double bottom_limit = 0; public Surface? overview_thumbnail = null;- Rsvg.Handle? svg_drawing = null;- public string? svg_data = null;+ + public double svg_x = 0;+ public double svg_y = 0;+ private Rsvg.Handle? svg_drawing = null;++ public string? color_svg_data {+ get {+ return _color_svg_data;+ }+ + set {+ try {+ if (value != null) {+ uint8[] svg_array = ((!) value).data;+ svg_drawing = new Rsvg.Handle.from_data (svg_array);+ } else {+ svg_drawing = null;+ }+ + _color_svg_data = value; + } catch (GLib.Error e) {+ warning (e.message);+ }+ }+ }++ private string? _color_svg_data = null; public Glyph (string name, unichar unichar_code = 0) { this.name = name; this.unichar_code = unichar_code;-- try {- string data;- FileUtils.get_contents ("/home/johan/birdfont/attic/test.svg", out data);- svg_data = data;-- if (svg_data != null) {- uint8[] svg_array = ((!) svg_data).data;- svg_drawing = new Rsvg.Handle.from_data (svg_array);- // FIXME: DELETE svg_drawing = new Rsvg.Handle.from_file ("/home/johan/birdfont/attic/test.svg");- }- } catch (GLib.Error e) {- warning (e.message);- } add_help_lines (); @@ -1842,19 +1853,21 @@ public class Glyph : FontDisplay { cmp.restore (); } - cmp.save ();- cmp.scale (view_zoom, view_zoom);- cmp.translate (-view_offset_x, -view_offset_y);- if (svg_drawing != null) {+ cmp.save ();+ cmp.scale (view_zoom, view_zoom);+ cmp.translate (xc () + svg_x - view_offset_x, yc () - svg_y - view_offset_y); Rsvg.Handle svg_handle = (!) svg_drawing; svg_handle.render_cairo (cmp);- } else if (!is_empty ()) {- draw_path (cmp);+ cmp.restore ();+ } else {+ cmp.save ();+ cmp.scale (view_zoom, view_zoom);+ cmp.translate (-view_offset_x, -view_offset_y);+ draw_path (cmp); + cmp.restore (); }- - cmp.restore ();- + cmp.save (); tool = MainWindow.get_toolbox ().get_current_tool (); tool.draw_action (tool, cmp, this);@@ -34,6 +34,7 @@ public static int run_import (string[] arg) { BirdFont.current_font = new Font (); BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', ""); MainWindow.init ();+ SvgType type = SvgType.REGULAR; if (arg.length < 3) { print_import_help (arg);@@ -43,7 +44,11 @@ public static int run_import (string[] arg) { bf_file = build_absoulute_path (arg[1]); for (int i = 2; i < arg.length; i++) {- svg_files.add (arg[i]);+ if (arg[i] == "--color") {+ type = SvgType.COLOR;+ } else {+ svg_files.add (arg[i]);+ } } bf = File.new_for_path (bf_file);@@ -79,7 +84,7 @@ public static int run_import (string[] arg) { foreach (string f in svg_files) { svg = File.new_for_path (f);- imported = import_svg_file (font, svg);+ imported = import_svg_file (font, svg, type); if (!imported) { stdout.printf (t_("Failed to import") + " " + f + "\n");@@ -93,7 +98,7 @@ public static int run_import (string[] arg) { return 0; } -public static bool import_svg_file (Font font, File svg_file) {+public static bool import_svg_file (Font font, File svg_file, SvgType type) { string file_name = (!) svg_file.get_basename (); string glyph_name; StringBuilder n;@@ -158,7 +163,11 @@ public static bool import_svg_file (Font font, File svg_file) { stdout.printf (@"$(glyph.version_id)"); stdout.printf ("\n"); - SvgParser.import_svg ((!) svg_file.get_path ());+ if (type == SvgType.COLOR) {+ SvgParser.import_color_svg (glyph, (!) svg_file.get_path ());+ } else {+ SvgParser.import_svg ((!) svg_file.get_path ());+ } return true; }@@ -287,17 +287,35 @@ public class Menu : AbstractMenu { MenuItem import_svg = add_menu_item (t_("Import SVG file"), "import svg file", "Glyph"); import_svg.action.connect (() => {- SvgParser.import ();+ SvgParser.import (SvgType.REGULAR); show_menu = false; }); export_menu.items.add (import_svg);- + MenuItem import_svg_folder = add_menu_item (t_("Import SVG folder"), "import svg folder", ""); import_svg_folder.action.connect (() => {- SvgParser.import_folder ();+ SvgParser.import_folder (SvgType.REGULAR); show_menu = false; }); export_menu.items.add (import_svg_folder);++ MenuItem import_color_svg;+ import_color_svg = add_menu_item (t_("Import SVG file") + ", " + t_("color"),+ "import svg file color", "Glyph");+ import_color_svg.action.connect (() => {+ SvgParser.import (SvgType.COLOR);+ show_menu = false;+ });+ export_menu.items.add (import_color_svg);++ MenuItem import_svg_color_folder;+ import_svg_color_folder = add_menu_item (t_("Import SVG folder") + ", " + t_("color"), + "import svg folder color", "");+ import_svg_color_folder.action.connect (() => {+ SvgParser.import_folder (SvgType.COLOR);+ show_menu = false;+ });+ export_menu.items.add (import_svg_color_folder); MenuItem import_background_image = add_menu_item (t_("Import Background Image"), "import background image"); import_background_image.action.connect (() => {@@ -123,19 +123,24 @@ public class MoveTool : Tool { delta_x = Glyph.ivz () * -dx * p; delta_y = Glyph.ivz () * dy * p;- - foreach (Layer group in glyph.selected_groups) {- if (group.gradient != null) {- Gradient g = (!) group.gradient;- g.x1 += delta_x;- g.x2 += delta_x;- g.y1 += delta_y;- g.y2 += delta_y;- }- } - foreach (Path path in glyph.active_paths) {- path.move (delta_x, delta_y);+ if (glyph.color_svg_data != null) {+ glyph.svg_x += delta_x;+ glyph.svg_y += delta_y;+ } else { + foreach (Layer group in glyph.selected_groups) {+ if (group.gradient != null) {+ Gradient g = (!) group.gradient;+ g.x1 += delta_x;+ g.x2 += delta_x;+ g.y1 += delta_y;+ g.y2 += delta_y;+ }+ }+ + foreach (Path path in glyph.active_paths) {+ path.move (delta_x, delta_y);+ } } } @@ -197,34 +202,36 @@ public class MoveTool : Tool { glyph.store_undo_state (); group_selection = false; - group = glyph.get_path_at (x, y);- - if (group != null) {- g = (!) group;- return_if_fail (g.paths.paths.size > 0);- p = g.paths.paths.get (0);- selected = glyph.active_paths.contains (p);+ if (glyph.color_svg_data == null) {+ group = glyph.get_path_at (x, y); - if (!selected && !KeyBindings.has_shift ()) {- glyph.clear_active_paths ();- } - - foreach (Path lp in g.paths.paths) {- if (selected && KeyBindings.has_shift ()) {- glyph.selected_groups.remove ((!) group);- glyph.active_paths.remove (lp);- } else {- glyph.add_active_path ((!) group, lp);+ if (group != null) {+ g = (!) group;+ return_if_fail (g.paths.paths.size > 0);+ p = g.paths.paths.get (0);+ selected = glyph.active_paths.contains (p);+ + if (!selected && !KeyBindings.has_shift ()) {+ glyph.clear_active_paths ();+ } + + foreach (Path lp in g.paths.paths) {+ if (selected && KeyBindings.has_shift ()) {+ glyph.selected_groups.remove ((!) group);+ glyph.active_paths.remove (lp);+ } else {+ glyph.add_active_path ((!) group, lp);+ } }+ } else if (!KeyBindings.has_shift ()) {+ glyph.clear_active_paths (); }- } else if (!KeyBindings.has_shift ()) {- glyph.clear_active_paths ();+ + update_selection_boundaries (); } move_path = true;-- update_selection_boundaries ();- + last_x = x; last_y = y; @@ -289,14 +296,16 @@ public class MoveTool : Tool { double w = Math.fabs (selection_x - last_x); double h = Math.fabs (selection_y - last_y); - cr.save ();- - Theme.color (cr, "Foreground 1");- cr.set_line_width (2);- cr.rectangle (x, y, w, h);- cr.stroke ();+ Glyph glyph = MainWindow.get_current_glyph (); - cr.restore ();+ if (glyph.color_svg_data == null) {+ cr.save (); + Theme.color (cr, "Foreground 1");+ cr.set_line_width (2);+ cr.rectangle (x, y, w, h);+ cr.stroke ();+ cr.restore ();+ } } public static void get_selection_box_boundaries (out double x, out double y, out double w, out double h) {@@ -42,11 +42,11 @@ public class SvgTable : OtfTable { if (glyph_collection != null) { glyphs = (!) glyph_collection;- svg_data = glyphs.get_current ().svg_data;+ svg_data = glyphs.get_current ().color_svg_data; if (svg_data != null) { gid = glyf_table.get_gid (glyphs.get_name ());- add_svg_glyph ((!) svg_data, gid);+ add_svg_glyph ((!) svg_data, gid, glyphs); glyphs_in_table++; } }@@ -55,7 +55,7 @@ public class SvgTable : OtfTable { process_svg_data (); } - void add_svg_glyph (string svg_data, int glyph_id) {+ void add_svg_glyph (string svg_data, int glyph_id, GlyphCollection glyphs) { SvgTableEntry entry; Gee.ArrayList<Tag> layer_content; Gee.ArrayList<Tag> svg_tags;@@ -94,6 +94,7 @@ public class SvgTable : OtfTable { } StringBuilder svg = new StringBuilder ();+ svg.append ("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"); svg.append ("<"); svg.append (svg_root_tag.get_name ()); svg.append (" ");@@ -114,9 +115,12 @@ public class SvgTable : OtfTable { // scale the internal coordinates from 100 units per em to the // number of units per em in this font and move the glyph // in to the em box- double height = -1 * (font.top_position - font.base_line);+ Glyph glyph = glyphs.get_current ();+ //FIXME: DELETE double height = font.top_position - font.base_line; double scale = HeadTable.UNITS;- svg.append (@"transform=\"scale($scale) translate(0, $height)\"");+ double x = glyph.svg_x - glyph.left_limit;+ double y = -glyph.svg_y;+ svg.append (@"transform=\"scale($scale) translate($x, $y)\""); svg.append (">"); svg.append ("\n\n");@@ -253,11 +253,6 @@ class SvgFont : GLib.Object { glyph.right_limit = glyph.left_limit + advance * units; // FIXME: add svg font ligatures- /*- if (ligature != "") {- glyph.set_ligature_substitution (ligature);- }- */ glyph_collection = new GlyphCollection (unicode_value, glyph_name); glyph_collection.insert_glyph (glyph, true);@@ -23,6 +23,11 @@ public enum SvgFormat { ILLUSTRATOR } +public enum SvgType {+ COLOR,+ REGULAR+}+ public class SvgParser { SvgFormat format = SvgFormat.ILLUSTRATOR;@@ -34,7 +39,7 @@ public class SvgParser { format = f; } - public static void import () {+ public static void import (SvgType type) { FileChooser fc = new FileChooser (); fc.file_selected.connect ((p) => { string path;@@ -44,14 +49,35 @@ public class SvgParser { } path = (!) p;- import_svg (path);+ + if (type == SvgType.REGULAR) {+ import_svg (path);+ } else if (type == SvgType.COLOR) {+ Glyph glyph = MainWindow.get_current_glyph ();+ import_color_svg (glyph, path);+ } }); fc.add_extension ("svg"); MainWindow.file_chooser (t_("Import"), fc, FileChooser.LOAD); }+ + public static void import_color_svg (Glyph glyph, string path) {+ try {+ string data;+ FileUtils.get_contents (path, out data);+ glyph.color_svg_data = data;++ if (glyph.color_svg_data != null) {+ glyph.svg_x = glyph.left_limit;+ glyph.svg_y = BirdFont.get_current_font ().top_position;+ }+ } catch (GLib.Error e) {+ warning (e.message);+ }+ } - public static void import_folder () {+ public static void import_folder (SvgType type) { FileChooser fc = new FileChooser (); fc.file_selected.connect ((p) => { string path;@@ -78,7 +104,7 @@ public class SvgParser { if (file_name.has_suffix (".svg")) { svg = get_child (svg_folder, file_name);- imported = import_svg_file (font, svg);+ imported = import_svg_file (font, svg, type); if (!imported) { warning ("Can't import %s.", (!) svg.get_path ());@@ -20,5 +20,10 @@ birdfont-import typeface.bf U+62.svg See also birdfont-export for creating SVG, EOT and TTF fonts from the birdfont file. +.SH OPTIONS+.TP 5+\--color+Preserve colors and create OpenType SVG table instead of using TrueType.+ .SH AUTHOR Johan Mattsson