Commit 78295da
Create SVG table in OpenType fonts
Changed files (8)
modifiedREADME.mdmodifieddodo.pymodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/OpenFontFormat/DirectoryTable.valamodifiedlibbirdfont/OpenFontFormat/Os2Table.valamodifiedlibbirdfont/OpenFontFormat/PostTable.valaaddedlibbirdfont/OpenFontFormat/SvgTable.valaaddedlibbirdfont/OpenFontFormat/SvgTableEntry.vala
Diff
@@ -19,15 +19,16 @@ Install vala and all required libraries, they are most likely in packages with a -dev or -devel affix: valac- python3-doit font-roboto- libxmlbird-dev+ python3-doit libgee-dev libglib2.0-dev libgtk-3-dev libwebkitgtk-3.0-dev libnotify-dev libsqlite3-dev+ librsvg2-dev+ libxmlbird-dev XML Bird is available from [birdfont.org][xmlbird]. @@ -78,6 +78,7 @@ def make_birdfont(target_binary, deps): --pkg webkitgtk-3.0 \ --pkg libnotify \ --pkg xmlbird \+ --pkg librsvg-2.0 \ --pkg libbirdfont """ @@ -93,6 +94,7 @@ def make_birdfont(target_binary, deps): $(pkg-config --cflags gdk-pixbuf-2.0) \ $(pkg-config --cflags webkitgtk-3.0) \ $(pkg-config --cflags libnotify) \+ $(pkg-config --cflags librsvg-2.0) \ -o OBJECT_FILE""" linker_command = config.CC + " " + config.LDFLAGS.get("birdfont", "") + """ \@@ -107,6 +109,7 @@ def make_birdfont(target_binary, deps): $(pkg-config --libs webkitgtk-3.0) \ $(pkg-config --libs xmlbird) \ $(pkg-config --libs libnotify) \+ $(pkg-config --libs librsvg-2.0) \ -L./build -L./build/bin -l birdgems\ -o build/bin/""" + target_binary @@ -160,6 +163,7 @@ def make_birdfont_export(target_binary, deps): $(pkg-config --libs cairo) \ $(pkg-config --libs glib-2.0) \ $(pkg-config --libs xmlbird) \+ $(pkg-config --libs librsvg-2.0) \ -L./build -L./build/bin -l birdgems\ -o ./build/bin/""" + target_binary @@ -189,7 +193,7 @@ def make_birdfont_import(target_binary, deps): --pkg gio-2.0 \ --pkg cairo \ --pkg xmlbird \- --pkg libbirdfont+ --pkg libbirdfont \ """ cc_command = config.CC + " " + config.CFLAGS.get("birdfont-import", "") + """ \@@ -213,6 +217,7 @@ def make_birdfont_import(target_binary, deps): $(pkg-config --libs cairo) \ $(pkg-config --libs glib-2.0) \ $(pkg-config --libs xmlbird) \+ $(pkg-config --libs librsvg-2.0) \ -L./build -L./build/bin -l birdgems\ -o ./build/bin/""" + target_binary @@ -267,6 +272,7 @@ def make_birdfont_autotrace(target_binary, deps): $(pkg-config --libs cairo) \ $(pkg-config --libs glib-2.0) \ $(pkg-config --libs xmlbird) \+ $(pkg-config --libs librsvg-2.0) \ -L./build -L./build/bin -l birdgems\ -o ./build/bin/""" + target_binary @@ -302,6 +308,8 @@ def make_libbirdfont(target_binary, deps): --pkg xmlbird \ --pkg libbirdgems \ --pkg sqlite3 \+ --pkg gdk-pixbuf-2.0 \+ --pkg librsvg-2.0 \ """ cc_command = config.CC + " " + config.CFLAGS.get("libbirdfont", "") + """ \@@ -317,6 +325,7 @@ def make_libbirdfont(target_binary, deps): $(pkg-config --cflags cairo) \ $(pkg-config --cflags glib-2.0) \ $(pkg-config --cflags xmlbird) \+ $(pkg-config --cflags librsvg-2.0) \ -o OBJECT_FILE""" linker_command = config.CC + " " + config.LDFLAGS.get("libbirdfont", "") + """ \@@ -440,7 +449,7 @@ def make_birdfont_test(target_binary, deps): --pkg gio-2.0 \ --pkg cairo \ --pkg xmlbird \- --pkg libbirdfont+ --pkg libbirdfont \ """ cc_command = config.CC + " " + config.CFLAGS.get("birdfont-test", "") + """ \@@ -463,6 +472,7 @@ def make_birdfont_test(target_binary, deps): $(pkg-config --libs cairo) \ $(pkg-config --libs glib-2.0) \ $(pkg-config --libs xmlbird) \+ $(pkg-config --libs librsvg-2.0) \ -L./build -L./build/bin -l birdgems\ -o build/bin/""" + target_binary @@ -134,17 +134,33 @@ public class Glyph : FontDisplay { public Gee.ArrayList<Path> active_paths = new Gee.ArrayList<Path> (); public Gee.ArrayList<Layer> selected_groups = new Gee.ArrayList<Layer> (); - // used if this glyph is fetched from a fallback font+ // used if this glyph originates from a fallback font public double top_limit = 0; public double baseline = 0; public double bottom_limit = 0; public Surface? overview_thumbnail = null;+ Rsvg.Handle? svg_drawing = null;+ public string? 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 (); left_limit = -28;@@ -1811,7 +1827,10 @@ public class Glyph : FontDisplay { } draw_background_glyph (allocation, cmp);- juxtapose (allocation, cmp);+ + if (svg_drawing != null) {+ juxtapose (allocation, cmp);+ } if (BirdFont.show_coordinates) { draw_coordinate (cmp);@@ -1823,14 +1842,19 @@ public class Glyph : FontDisplay { cmp.restore (); } - if (!is_empty ()) {- cmp.save ();- cmp.scale (view_zoom, view_zoom);- cmp.translate (-view_offset_x, -view_offset_y);+ cmp.save ();+ cmp.scale (view_zoom, view_zoom);+ cmp.translate (-view_offset_x, -view_offset_y);+ + if (svg_drawing != null) {+ Rsvg.Handle svg_handle = (!) svg_drawing;+ svg_handle.render_cairo (cmp);+ } else if (!is_empty ()) { draw_path (cmp);- cmp.restore (); }-+ + cmp.restore ();+ cmp.save (); tool = MainWindow.get_toolbox ().get_current_tool (); tool.draw_action (tool, cmp, this);@@ -33,6 +33,7 @@ public class DirectoryTable : OtfTable { public Os2Table os_2_table; public PostTable post_table; public LocaTable loca_table;+ public SvgTable svg_table; public OffsetTable offset_table; @@ -57,6 +58,7 @@ public class DirectoryTable : OtfTable { name_table = new NameTable (); os_2_table = new Os2Table (glyf_table, hmtx_table, hhea_table); post_table = new PostTable (glyf_table);+ svg_table = new SvgTable (); id = "Directory table"; @@ -81,6 +83,7 @@ public class DirectoryTable : OtfTable { post_table.process (); kern_table.process (); gpos_table.process (glyf_table);+ svg_table.process (glyf_table); offset_table.process (); process_directory (); // this table@@ -102,6 +105,10 @@ public class DirectoryTable : OtfTable { tables.add (os_2_table); + if (svg_table.has_glyphs ()) {+ tables.add (svg_table);+ }+ // tables.append (gdef_table); // invalid table tables.add (cmap_table);@@ -104,7 +104,6 @@ public class Os2Table : OtfTable { fd.add_u32 (0); // ulUnicodeRange3 Bits 64-95 fd.add_u32 (0); // ulUnicodeRange4 Bits 96-127 } else {- warning(@"unicodeRange1: $unicodeRange1 unicodeRange2: $unicodeRange2 unicodeRange3 $unicodeRange3 unicodeRange4: $unicodeRange4"); fd.add_u32 (unicodeRange1); // ulUnicodeRange1 Bits 0-31 fd.add_u32 (unicodeRange2); // ulUnicodeRange2 Bits 32-63 fd.add_u32 (unicodeRange3); // ulUnicodeRange3 Bits 64-95@@ -1102,8 +1102,6 @@ public class PostTable : OtfTable { assert (names.size == 0); add_standard_names (); - print ("Adding post names\n");- for (int i = 1; i < glyf_table.glyphs.size; i++) { gc = glyf_table.glyphs.get (i); g = gc.get_current ();new file mode 100644@@ -0,0 +1,207 @@+/*+ Copyright (C) 2015 Johan Mattsson++ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version.++ This library 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 + Lesser General Public License for more details.+*/++using B;++namespace BirdFont {++public class SvgTable : OtfTable {+ + int glyphs_in_table = 0;+ Gee.ArrayList<SvgTableEntry> entries;++ public SvgTable () {+ id = "SVG ";+ entries = new Gee.ArrayList<SvgTableEntry> ();+ }+ + public bool has_glyphs () {+ return glyphs_in_table > 0;+ }++ public void process (GlyfTable glyf_table) throws GLib.Error {+ Font font = OpenFontFormatWriter.get_current_font ();+ GlyphCollection? glyph_collection;+ GlyphCollection glyphs;+ string? svg_data;+ int gid;+ + for (int index = 0; index < font.length (); index++) { + glyph_collection = font.get_glyph_collection_index (index);+ + if (glyph_collection != null) {+ glyphs = (!) glyph_collection;+ svg_data = glyphs.get_current ().svg_data;+ + if (svg_data != null) {+ gid = glyf_table.get_gid (glyphs.get_name ());+ add_svg_glyph ((!) svg_data, gid);+ glyphs_in_table++;+ }+ }+ }++ process_svg_data ();+ }+ + void add_svg_glyph (string svg_data, int glyph_id) {+ SvgTableEntry entry;+ Gee.ArrayList<Tag> layer_content;+ Gee.ArrayList<Tag> svg_tags;+ Gee.ArrayList<Tag> meta;+ XmlParser xml;+ Tag svg_root_tag;+ + layer_content = new Gee.ArrayList<Tag> ();+ svg_tags = new Gee.ArrayList<Tag> ();+ meta = new Gee.ArrayList<Tag> ();+ xml = new XmlParser (svg_data);+ svg_root_tag = xml.get_root_tag ();+ + if (!xml.validate ()) {+ warning("Invalid SVG data in TTF table.");+ return;+ }+ + foreach (Tag tag in svg_root_tag) {+ string name = tag.get_name();++ if (name == "defs") {+ svg_tags.add (tag);+ } else if (name == "style") {+ svg_tags.add (tag);+ } else if (name == "metadata") {+ meta.add (tag);+ } else if (name == "sodipodi") {+ meta.add (tag);+ } else {+ layer_content.add (tag);+ }+ }+ + StringBuilder svg = new StringBuilder ();+ svg.append ("<");+ svg.append (svg_root_tag.get_name ());+ svg.append (" ");+ append_tag_attributes (svg, svg_root_tag);+ svg.append (">");++ foreach (Tag tag in svg_tags) {+ append_tag (svg, tag);+ }++ svg.append ("\n\n");+ svg.append ("<g id=");+ svg.append ("\"");+ svg.append ("glyph");+ svg.append (@"$glyph_id");+ svg.append ("\"");+ svg.append (">");+ svg.append ("\n\n");+ + foreach (Tag tag in layer_content) {+ append_tag (svg, tag);+ }+ + svg.append ("\n\n");+ svg.append ("</g>");+ svg.append ("\n\n");+ + svg.append ("</");+ svg.append (svg_root_tag.get_name ());+ svg.append (">\n");+ + entry = new SvgTableEntry ((uint16) glyph_id, svg.str);+ entries.add (entry);+ }++ public void append_tag (StringBuilder svg, Tag tag) {+ string content = tag.get_content ();+ + svg.append ("<");+ svg.append (tag.get_name ());+ + if (content == "") {+ svg.append ("/");+ }+ + svg.append (">");+ + if (content != "") {+ svg.append (content);+ svg.append ("</");+ svg.append (tag.get_name ());+ svg.append (">");+ }+ }+ + public void append_tag_attributes (StringBuilder svg, Tag tag) {+ bool first = true;+ + foreach (Attribute attribute in tag.get_attributes ()) {+ string ns = attribute.get_namespace ();+ + if (!first) {+ svg.append (" ");+ }+ + if (ns != "") {+ svg.append (ns);+ svg.append (":");+ }+ + svg.append (attribute.get_name ());+ svg.append ("=");+ svg.append ("\"");+ svg.append (attribute.get_content ());+ svg.append ("\"");+ + first = false;+ }+ }+ + public void process_svg_data () throws GLib.Error {+ FontData fd = new FontData ();+ + int32 svg_index_offset = 10;+ + fd.add_ushort (0); // version+ fd.add_ulong (svg_index_offset);+ fd.add_ulong (0); // reserved+ + uint32 document_offset = 2 + 12 * entries.size;+ + // SVG Documents Index+ fd.add_ushort ((uint16) entries.size);+ + foreach (SvgTableEntry entry in entries) {+ fd.add_ushort (entry.glyph_id); // start+ fd.add_ushort (entry.glyph_id); // end+ fd.add_ulong (document_offset); // offset+ fd.add_ulong (entry.data.length_with_padding ()); // length++ document_offset += entry.data.length_with_padding ();+ }++ foreach (SvgTableEntry entry in entries) {+ fd.append (entry.data);+ }+ + fd.pad ();+ + this.font_data = fd;+ }+}++}new file mode 100644@@ -0,0 +1,29 @@+/*+ Copyright (C) 2015 Johan Mattsson++ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version.++ This library 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 + Lesser General Public License for more details.+*/++namespace BirdFont {++public class SvgTableEntry : GLib.Object {+ public FontData data;+ public uint16 glyph_id;+ + public SvgTableEntry (uint16 gid, string svg) {+ print (svg);+ glyph_id = gid;+ data = new FontData ();+ data.add_str (svg);+ }+}++}