The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Import SVG files from Illustrator

These changes was commited to the Birdfont repository Wed, 06 Jul 2016 21:18:29 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Wed, 06 Jul 2016 21:18:29 +0000 (23:18 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Wed, 06 Jul 2016 21:18:29 +0000 (23:18 +0200)
commit 0f40cc1ec04c1b63443f886c9ba2324dae3f2b6e
tree 3ab225c3671b08af710c696d8e40826f5915cac0
parent e59856b085576fd9d7ca9229a51b5927c05ee93a
Import SVG files from Illustrator

libbirdfont/MoveTool.vala
libbirdfont/SvgFont.vala
libbirdfont/SvgParser.vala
libbirdfont/TestCases.vala
libsvgbird/Doubles.vala
libsvgbird/SvgFile.vala
--- a/libbirdfont/MoveTool.vala +++ b/libbirdfont/MoveTool.vala @@ -551,7 +551,8 @@ EmbeddedSvg svg = (EmbeddedSvg) object; glyph.clear_active_paths (); string transformed_svg_data = svg.get_transformed_svg_data (); - PathList path_list = SvgParser.import_svg_data_in_glyph (transformed_svg_data, glyph); + SvgParser svg_parser = new SvgParser (); + PathList path_list = svg_parser.import_svg_data_in_glyph (transformed_svg_data, glyph); glyph.delete_object (svg); foreach (Path path in path_list.paths) {
--- a/libbirdfont/SvgFont.vala +++ b/libbirdfont/SvgFont.vala @@ -13,6 +13,7 @@ */ using B; + using SvgBird; namespace BirdFont {
--- a/libbirdfont/SvgParser.vala +++ b/libbirdfont/SvgParser.vala @@ -17,12 +17,6 @@ using SvgBird; namespace BirdFont { - - public enum SvgFormat { - NONE, - INKSCAPE, - ILLUSTRATOR - } public enum SvgType { COLOR, @@ -30,7 +24,6 @@ } public class SvgParser { - SvgFormat format = SvgFormat.ILLUSTRATOR; public SvgParser () { @@ -142,12 +135,13 @@ MainWindow.file_chooser (t_("Import"), fc, FileChooser.LOAD | FileChooser.DIRECTORY); } - public static PathList import_svg_data (string xml_data, SvgFormat format = SvgFormat.NONE) { + public static PathList import_svg_data (string xml_data) { Glyph glyph = MainWindow.get_current_glyph (); - return import_svg_data_in_glyph (xml_data, glyph, format); + SvgParser parser = new SvgParser (); + return parser.import_svg_data_in_glyph (xml_data, glyph); } - public static PathList import_svg_data_in_glyph (string xml_data, Glyph glyph, SvgFormat format = SvgFormat.NONE) { + public PathList import_svg_data_in_glyph (string xml_data, Glyph glyph) { PathList path_list = new PathList (); string[] lines = xml_data.split ("\n"); bool has_format = false; @@ -1145,18 +1139,22 @@ move_and_resize (bezier_points, points, svg_glyph, units, glyph); + /* if (format == SvgFormat.ILLUSTRATOR) { path_list = create_paths_illustrator (bezier_points, points); } else { - path_list = create_svg_paths_inkscape (d); + } + */ + + path_list = create_svg_paths (d, format); // TODO: Find out if it is possible to tie handles. return path_list; } - public PathList create_svg_paths_inkscape (string path_data) { - Gee.ArrayList<Points> points_set = SvgFile.parse_points (path_data); + public PathList create_svg_paths (string path_data, SvgFormat format) { + Gee.ArrayList<Points> points_set = SvgFile.parse_points (path_data, format); PathList path_list = new PathList (); foreach (Points p in points_set) { @@ -1166,6 +1164,11 @@ EditPoint next = new EditPoint (p.x, -p.y, PointType.CUBIC); EditPointHandle handle; + if (p.size == 0) { + warning ("No points in path."); + return path_list; + } + if (p.size % 8 != 0) { warning ("Points not padded."); return path_list; @@ -1220,8 +1223,6 @@ if (p.closed) { path.close (); - path.get_first_point ().color = Color.blue (); - path.get_last_point ().color = Color.green (); } Font font = BirdFont.get_current_font (); @@ -1236,19 +1237,11 @@ e.get_left_handle ().independent_y += font.top_limit; } + path.recalculate_linear_handles (); path_list.add (path); } return path_list; - } - - void to_svg_coordinate (ref double x, ref double y) { - Font font = BirdFont.get_current_font (); - Glyph glyph = MainWindow.get_current_glyph (); - x -= glyph.left_limit; - y -= font.base_line; - x -= glyph.left_limit; - y -= font.top_limit; } void move_and_resize (BezierPoints[] b, int num_b, bool svg_glyph, double units, Glyph glyph) { @@ -1736,12 +1729,9 @@ } public static EmbeddedSvg parse_embedded_svg_data (string xml_data) { - XmlTree tree = new XmlTree (xml_data); SvgDrawing drawing = new SvgDrawing (); SvgFile svg_file = new SvgFile (); - - XmlElement root = tree.get_root (); - drawing = svg_file.parse_svg_file (root); + drawing = svg_file.parse_svg_data (xml_data); EmbeddedSvg svg = new EmbeddedSvg (drawing); svg.svg_data = xml_data; return svg;
--- a/libbirdfont/TestCases.vala +++ b/libbirdfont/TestCases.vala @@ -13,7 +13,7 @@ */ using B; - + using SvgBird; namespace BirdFont { /** All the things we want to test listed is here. */
--- a/libsvgbird/Doubles.vala +++ b/libsvgbird/Doubles.vala @@ -25,14 +25,26 @@ data = new PointValue[capacity]; } + public Doubles.for_capacity (int capacity) { + data = new PointValue[capacity]; + this.capacity = capacity; + } + ~Doubles () { delete data; data = null; } - public Doubles.for_capacity (int capacity) { - data = new PointValue[capacity]; - this.capacity = capacity; + public void remove_first (int n) { + if (size < n) { + return; + } + + size -= n; + + for (int i = 0; i < size; i++) { + data[i] = data[i + n]; + } } void increase_capacity () { @@ -86,6 +98,20 @@ return data[index].value; } + public uchar get_point_type (int index) { + if (unlikely (index < 0)) { + warning ("index < 0"); + return 0; + } + + if (unlikely (index >= size)) { + warning ("index >= size"); + return 0; + } + + return data[index].type; + } + public string get_string (int i) { return round (get_double (i)); }
--- a/libsvgbird/SvgFile.vala +++ b/libsvgbird/SvgFile.vala @@ -17,21 +17,36 @@ using Math; namespace SvgBird { + + public enum SvgFormat { + NONE, + INKSCAPE, + ILLUSTRATOR + } public class SvgFile : GLib.Object { SvgDrawing drawing; + SvgFormat format = SvgFormat.ILLUSTRATOR; public SvgFile () { } public SvgDrawing parse_svg_data (string xml_data) { XmlTree tree = new XmlTree (xml_data); - return parse_svg_file (tree.get_root ()); + + if (xml_data.index_of ("Illustrator") > -1 || xml_data.index_of ("illustrator") > -1) { + format = SvgFormat.ILLUSTRATOR; + } else if (xml_data.index_of ("Inkscape") > -1 || xml_data.index_of ("inkscape") > -1) { + format = SvgFormat.INKSCAPE; + } + + return parse_svg_file (tree.get_root (), format); } - public SvgDrawing parse_svg_file (XmlElement svg_tag) { + public SvgDrawing parse_svg_file (XmlElement svg_tag, SvgFormat format) { drawing = new SvgDrawing (); + this.format = format; SvgStyle style = new SvgStyle (); SvgStyle.parse (drawing.defs, style, svg_tag, null); @@ -58,7 +73,7 @@ } if (name == "svg") { - SvgDrawing embedded = parse_svg_file (t); + SvgDrawing embedded = parse_svg_file (t, format); drawing.root_layer.add_object (embedded); } @@ -396,7 +411,7 @@ } if (name == "svg") { - SvgDrawing embedded = parse_svg_file (tag); + SvgDrawing embedded = parse_svg_file (tag, format); layer.add_object (embedded); } @@ -765,7 +780,7 @@ foreach (Attribute attr in tag.get_attributes ()) { if (attr.get_name () == "d") { - path.points = parse_points (attr.get_content ()); + path.points = parse_points (attr.get_content (), format); } } @@ -773,17 +788,17 @@ layer.add_object (path); } - public static Gee.ArrayList<Points> parse_points (string data) { + public static Gee.ArrayList<Points> parse_points (string data, SvgFormat format) { Gee.ArrayList<Points> path_data = new Gee.ArrayList<Points> (); Points points = new Points (); BezierPoints[] bezier_points; int points_size; - + get_bezier_points (data, out bezier_points, out points_size, true); + print (@"format $format\n"); + // all instructions are padded - - // FIXME: Inscape and Illustrator discrepancies for (int i = 0; i < points_size; i++) { // FIXME: add more types @@ -852,6 +867,61 @@ if (points.size > 0) { path_data.add (points); + } + + if (format == SvgFormat.ILLUSTRATOR) { + print ("Remove first"); + + Gee.ArrayList<Points> illustrator_path_data = new Gee.ArrayList<Points> (); + + foreach (Points p in path_data) { + return_val_if_fail (p.point_data.size % 8 == 0, path_data); + + if (p.point_data.size > 16) { + Points illustrator_points = new Points (); + + illustrator_points.x = p.point_data.get_double (p.point_data.size - 3); + illustrator_points.y = p.point_data.get_double (p.point_data.size - 2); + + int start = p.point_data.get_point_type (0) == POINT_CUBIC ? 8 : 0; + + for (int i = start; i < p.point_data.size; i += 1) { + illustrator_points.point_data.add (p.point_data.get_double (i)); + } + + illustrator_points.closed = p.closed; + illustrator_path_data.add (illustrator_points); + } + } + + return illustrator_path_data; + + /* + foreach (Points p in path_data) { + //p.point_data.remove_first (8); + p.point_data.size -= 8; + p.point_data.get_double (0) + p.point_data.get_double (1) + } + */ + + + + /*EditPoint first = path.delete_first_point (); + EditPoint last = path.get_last_point (); + handle = last.get_right_handle (); + + last.get_right_handle ().independent_x = first.get_left_handle ().x; + last.get_right_handle ().independent_y = first.get_left_handle ().y; + + if (points[0].type == POINT_CUBIC && !handle.is_line ()) { + handle.set_point_type (PointType.CUBIC); + handle.move_to_coordinate (points[0].value, points[1].value); + } else { + handle.set_point_type (PointType.LINE_CUBIC); + path.recalculate_linear_handles_for_point (last); + } + */ } return path_data;