The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

SvgTable.vala in libbirdfont/OpenFontFormat

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/OpenFontFormat/SvgTable.vala.
Validate XML when importing SVG file
1 /* 2 Copyright (C) 2015 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using B; 16 17 namespace BirdFont { 18 19 public class SvgTable : OtfTable { 20 21 int glyphs_in_table = 0; 22 Gee.ArrayList<SvgTableEntry> entries; 23 24 public SvgTable () { 25 id = "SVG "; 26 entries = new Gee.ArrayList<SvgTableEntry> (); 27 } 28 29 public bool has_glyphs () { 30 return glyphs_in_table > 0; 31 } 32 33 public void process (GlyfTable glyf_table) throws GLib.Error { 34 Font font = OpenFontFormatWriter.get_current_font (); 35 GlyphCollection? glyph_collection; 36 GlyphCollection glyphs; 37 string? svg_data; 38 int gid; 39 40 for (int index = 0; index < font.length (); index++) { 41 glyph_collection = font.get_glyph_collection_index (index); 42 43 if (glyph_collection != null) { 44 glyphs = (!) glyph_collection; 45 svg_data = glyphs.get_current ().color_svg_data; 46 47 if (svg_data != null) { 48 gid = glyf_table.get_gid (glyphs.get_name ()); 49 add_svg_glyph ((!) svg_data, gid, glyphs); 50 glyphs_in_table++; 51 } 52 } 53 } 54 55 process_svg_data (); 56 } 57 58 void add_svg_glyph (string svg_data, int glyph_id, GlyphCollection glyphs) { 59 SvgTableEntry entry; 60 Gee.ArrayList<Tag> layer_content; 61 Gee.ArrayList<Tag> svg_tags; 62 Gee.ArrayList<Tag> meta; 63 XmlParser xml; 64 Tag svg_root_tag; 65 Font font; 66 67 font = OpenFontFormatWriter.get_current_font (); 68 69 layer_content = new Gee.ArrayList<Tag> (); 70 svg_tags = new Gee.ArrayList<Tag> (); 71 meta = new Gee.ArrayList<Tag> (); 72 xml = new XmlParser (svg_data); 73 74 if (!xml.validate ()) { 75 warning("Invalid SVG data in TTF table."); 76 return; 77 } 78 79 svg_root_tag = xml.get_root_tag (); 80 81 foreach (Tag tag in svg_root_tag) { 82 string name = tag.get_name(); 83 84 if (name == "defs") { 85 svg_tags.add (tag); 86 } else if (name == "style") { 87 svg_tags.add (tag); 88 } else if (name == "metadata") { 89 meta.add (tag); 90 } else if (name == "sodipodi") { 91 meta.add (tag); 92 } else { 93 layer_content.add (tag); 94 } 95 } 96 97 StringBuilder svg = new StringBuilder (); 98 svg.append ("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"); 99 svg.append ("<"); 100 svg.append (svg_root_tag.get_name ()); 101 svg.append (" "); 102 append_tag_attributes (svg, svg_root_tag); 103 svg.append (">"); 104 105 foreach (Tag tag in svg_tags) { 106 append_tag (svg, tag); 107 } 108 109 svg.append ("\n\n"); 110 svg.append ("<g id="); 111 svg.append ("\""); 112 svg.append ("glyph"); 113 svg.append (@"$glyph_id"); 114 svg.append ("\" "); 115 116 // scale the internal coordinates from 100 units per em to the 117 // number of units per em in this font and move the glyph 118 // in to the em box 119 Glyph glyph = glyphs.get_current (); 120 //FIXME: DELETE double height = font.top_position - font.base_line; 121 double scale = HeadTable.UNITS; 122 double x = glyph.svg_x - glyph.left_limit; 123 double y = -glyph.svg_y; 124 svg.append (@"transform=\"scale($scale) translate($x, $y)\""); 125 126 svg.append (">"); 127 svg.append ("\n\n"); 128 129 foreach (Tag tag in layer_content) { 130 append_tag (svg, tag); 131 } 132 133 svg.append ("\n\n"); 134 svg.append ("</g>"); 135 svg.append ("\n\n"); 136 137 svg.append ("</"); 138 svg.append (svg_root_tag.get_name ()); 139 svg.append (">\n"); 140 141 entry = new SvgTableEntry ((uint16) glyph_id, svg.str); 142 entries.add (entry); 143 } 144 145 public void append_tag (StringBuilder svg, Tag tag) { 146 string content = tag.get_content (); 147 148 svg.append ("<"); 149 svg.append (tag.get_name ()); 150 151 svg.append (" "); 152 append_tag_attributes (svg, tag); 153 154 if (content == "") { 155 svg.append (" /"); 156 } 157 158 svg.append (">"); 159 160 if (content != "") { 161 svg.append (content); 162 svg.append ("</"); 163 svg.append (tag.get_name ()); 164 svg.append (">"); 165 } 166 } 167 168 public void append_tag_attributes (StringBuilder svg, Tag tag) { 169 bool first = true; 170 171 foreach (Attribute attribute in tag.get_attributes ()) { 172 string ns = attribute.get_namespace (); 173 174 if (!first) { 175 svg.append (" "); 176 } 177 178 if (ns != "") { 179 svg.append (ns); 180 svg.append (":"); 181 } 182 183 svg.append (attribute.get_name ()); 184 svg.append ("="); 185 svg.append ("\""); 186 svg.append (attribute.get_content ()); 187 svg.append ("\""); 188 189 first = false; 190 } 191 } 192 193 public void process_svg_data () throws GLib.Error { 194 FontData fd = new FontData (); 195 196 int32 svg_index_offset = 10; 197 198 fd.add_ushort (0); // version 199 fd.add_ulong (svg_index_offset); 200 fd.add_ulong (0); // reserved 201 202 uint32 document_offset = 2 + 12 * entries.size; 203 204 // SVG Documents Index 205 fd.add_ushort ((uint16) entries.size); 206 207 foreach (SvgTableEntry entry in entries) { 208 fd.add_ushort (entry.glyph_id); // start 209 fd.add_ushort (entry.glyph_id); // end 210 fd.add_ulong (document_offset); // offset 211 fd.add_ulong (entry.data.length_with_padding ()); // length 212 213 document_offset += entry.data.length_with_padding (); 214 } 215 216 foreach (SvgTableEntry entry in entries) { 217 fd.append (entry.data); 218 } 219 220 fd.pad (); 221 222 this.font_data = fd; 223 } 224 } 225 226 } 227