Commit 0f40cc1
Import SVG files from Illustrator
Changed files (6)
modifiedlibbirdfont/MoveTool.valamodifiedlibbirdfont/SvgFont.valamodifiedlibbirdfont/SvgParser.valamodifiedlibbirdfont/TestCases.valamodifiedlibsvgbird/Doubles.valamodifiedlibsvgbird/SvgFile.vala
Diff
@@ -551,7 +551,8 @@ public class MoveTool : Tool { 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) {@@ -13,6 +13,7 @@ */ using B;+using SvgBird; namespace BirdFont { @@ -18,19 +18,12 @@ using SvgBird; namespace BirdFont { -public enum SvgFormat {- NONE,- INKSCAPE,- ILLUSTRATOR-}- public enum SvgType { COLOR, REGULAR } public class SvgParser {- SvgFormat format = SvgFormat.ILLUSTRATOR; public SvgParser () {@@ -142,12 +135,13 @@ public class SvgParser { 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 @@ public class SvgParser { 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 @@ public class SvgParser { 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 @@ public class SvgParser { 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,21 +1237,13 @@ public class SvgParser { 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) { Font font = BirdFont.get_current_font (); @@ -1736,12 +1729,9 @@ public class SvgParser { } 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;@@ -13,7 +13,7 @@ */ using B;-+using SvgBird; namespace BirdFont { /** All the things we want to test listed is here. */@@ -25,14 +25,26 @@ public class Doubles : GLib.Object { 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 @@ public class Doubles : GLib.Object { 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)); }@@ -18,20 +18,35 @@ 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 @@ public class SvgFile : GLib.Object { } 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 @@ public class SvgFile : GLib.Object { } if (name == "svg") {- SvgDrawing embedded = parse_svg_file (tag);+ SvgDrawing embedded = parse_svg_file (tag, format); layer.add_object (embedded); } @@ -765,7 +780,7 @@ public class SvgFile : GLib.Object { 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,18 +788,18 @@ public class SvgFile : GLib.Object { 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 if (bezier_points[i].type == 'M') {@@ -853,6 +868,61 @@ public class SvgFile : GLib.Object { 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; }