The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Use other types of graphical objects

These changes was commited to the Birdfont repository Mon, 28 Dec 2015 10:29:21 +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>
Mon, 28 Dec 2015 10:29:21 +0000 (11:29 +0100)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Mon, 28 Dec 2015 14:34:18 +0000 (15:34 +0100)
commit 30e31d8a41f758f1d2e1a9bff59aed76f89b9231
tree f0d00c694083bd75a426e12df1c3d651db5514cf
parent d004468de20a0a01226b57f9b5ea5b195b1b1256
Use other types of graphical objects

The previous version uses only simple paths this commit makes it possible to
add other objects like circles, rectangles and text. The refactoring
is the first part of the full SVG implementation.

29 files changed:
dodo.py
libbirdfont/ClipTool.vala
libbirdfont/DrawingTools.vala
libbirdfont/ExportTool.vala
libbirdfont/FastPath.vala [new ]
libbirdfont/Glyph.vala
libbirdfont/Layer.vala
libbirdfont/MenuTab.vala
libbirdfont/MoveTool.vala
libbirdfont/Object.vala [new ]
libbirdfont/ObjectGroup.vala [new ]
libbirdfont/OpenFontFormat/FontData.vala
libbirdfont/OpenFontFormat/GlyfData.vala
libbirdfont/OpenFontFormat/GlyfTable.vala
libbirdfont/OpenFontFormat/OpenFontFormatReader.vala
libbirdfont/OpenFontFormat/OpenFontFormatWriter.vala
libbirdfont/OpenFontFormat/OtfInputStream.vala
libbirdfont/OpenFontFormat/OtfTable.vala
libbirdfont/OrientationTool.vala
libbirdfont/OtfFeatureTable.vala
libbirdfont/Path.vala
libbirdfont/PenTool.vala
libbirdfont/ResizeTool.vala
libbirdfont/StrokeTool.vala
libbirdfont/SvgFontFormatWriter.vala
libbirdfont/SvgParser.vala
libbirdfont/Test.vala
libbirdfont/TrackTool.vala
diff --git a/dodo.py b/dodo.py
--- a/dodo.py +++ b/dodo.py @@ -301,7 +301,7 @@ -H build/libbirdfont/birdfont.h \ libbirdfont/*.vala \ libbirdfont/OpenFontFormat/*.vala \ - libbirdfont/Renderer/*.vala \ + libbirdfont/TextRendering/*.vala \ --pkg """ + config.GEE + """ \ --pkg gio-2.0 \ --pkg cairo \
--- a/libbirdfont/ClipTool.vala +++ b/libbirdfont/ClipTool.vala @@ -95,7 +95,7 @@ dx = g.motion_x - x - w / 2.0; dy = g.motion_y - y + h / 2.0; - foreach (Path path in g.active_paths) { + foreach (Object path in g.active_paths) { path.move (dx, dy); } } else if (fd is KerningDisplay) { @@ -260,7 +260,7 @@ } } } else if (glyph.get_visible_paths ().size > 0) { - foreach (Path path in glyph.active_paths) { + foreach (Path path in glyph.get_active_paths ()) { // FIXME: other objects s.append ("BF path: "); s.append (BirdFontFile.get_point_data (path)); s.append ("\n"); @@ -447,13 +447,13 @@ if (path.points.size > 0) { PenTool.clear_directions (); glyph.add_path (path); - glyph.active_paths.add (path); + glyph.add_active_path (null, path); path.update_region_boundaries (); } PenTool.remove_all_selected_points (); - foreach (Path p in glyph.active_paths) { + foreach (Path p in glyph.get_active_paths ()) { if (p.is_open ()) { foreach (EditPoint e in p.points) { e.set_selected (true);
--- a/libbirdfont/DrawingTools.vala +++ b/libbirdfont/DrawingTools.vala @@ -292,7 +292,7 @@ glyph.selection_boundaries (out x, out y, out w, out h); delta = x_coordinate.get_value () - x + glyph.left_limit; - foreach (Path path in glyph.active_paths) { + foreach (Object path in glyph.active_paths) { path.move (delta, 0); } @@ -335,7 +335,7 @@ glyph.selection_boundaries (out x, out y, out w, out h); - foreach (Path path in glyph.active_paths) { + foreach (Path path in glyph.get_active_paths ()) { path.move (0, y_coordinate.get_value () - (y - h) - font.base_line); } @@ -375,7 +375,7 @@ double x, y, w, h; Glyph glyph = MainWindow.get_current_glyph (); double angle = (self.get_value () / 360) * 2 * PI; - Path last_path; + Object last_path; glyph.selection_boundaries (out x, out y, out w, out h); x += w / 2; @@ -480,7 +480,7 @@ tie = !p.tie_handles; // don't tie end points - foreach (Path path in MainWindow.get_current_glyph ().active_paths) { + foreach (Path path in MainWindow.get_current_glyph ().get_active_paths ()) { if (path.is_open ()) { if (p == path.get_first_point () || p == path.get_last_point ()) { tie = false; @@ -598,9 +598,9 @@ Glyph g = MainWindow.get_current_glyph (); Layer layer = g.get_current_layer (); - foreach (Path p in g.active_paths) { - layer.paths.remove (p); - layer.paths.paths.insert (0, p); + foreach (Object p in g.active_paths) { + layer.remove (p); + layer.objects.objects.insert (0, p); } GlyphCanvas.redraw (); @@ -798,12 +798,12 @@ g.store_undo_state (); if (StrokeTool.add_stroke) { - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { p.stroke = StrokeTool.stroke_width; p.line_cap = StrokeTool.line_cap; } } else { - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { p.stroke = 0; } } @@ -838,9 +838,13 @@ StrokeTool.stroke_width = object_stroke.get_value (); if (tool && StrokeTool.add_stroke) { - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { p.stroke = StrokeTool.stroke_width; - p.reset_stroke (); + + if (p is FastPath) { + Path path = ((FastPath) p).get_path (); + path.reset_stroke (); + } } } @@ -876,9 +880,12 @@ g = MainWindow.get_current_glyph (); g.store_undo_state (); - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { p.line_cap = LineCap.BUTT; - p.reset_stroke (); + + if (p is FastPath) { + ((FastPath) p).get_path ().reset_stroke (); + } } StrokeTool.line_cap = LineCap.BUTT; @@ -900,9 +907,12 @@ g = MainWindow.get_current_glyph (); g.store_undo_state (); - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { p.line_cap = LineCap.ROUND; - p.reset_stroke (); + + if (p is FastPath) { + ((FastPath) p).get_path ().reset_stroke (); + } } StrokeTool.line_cap = LineCap.ROUND; @@ -925,9 +935,12 @@ g = MainWindow.get_current_glyph (); g.store_undo_state (); - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { p.line_cap = LineCap.SQUARE; - p.reset_stroke (); + + if (p is FastPath) { + ((FastPath) p).get_path ().reset_stroke (); + } } StrokeTool.line_cap = LineCap.SQUARE; @@ -1249,7 +1262,7 @@ bool stroke = false; Glyph g = MainWindow.get_current_glyph (); - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { if (p.stroke > 0) { stroke = true; }
--- a/libbirdfont/ExportTool.vala +++ b/libbirdfont/ExportTool.vala @@ -95,37 +95,50 @@ name = glyph.get_name (); - Gee.ArrayList<Path> pl; + Gee.ArrayList<Object> pl; s = new StringBuilder (); glyph_svg = ""; - pl = only_selected_paths ? glyph.active_paths : glyph.get_visible_paths (); - foreach (Path p in pl) { - if (p.stroke > 0) { - s.append (@"<path "); - s.append (@"style=\""); - s.append (@"fill:none;"); - s.append (@"stroke:#000000;"); - s.append (@"stroke-width:$(p.stroke)px;"); - - if (p.line_cap == LineCap.ROUND) { - s.append (@"stroke-linecap:round;"); - } else if (p.line_cap == LineCap.SQUARE) { - s.append (@"stroke-linecap:square;"); + pl = only_selected_paths ? glyph.active_paths : glyph.get_visible_objects (); + + foreach (Object o in pl) { + + if (o is FastPath) { + Path p = ((FastPath) o).get_path (); + + if (p.stroke > 0) { + s.append (@"<path "); + s.append (@"style=\""); + s.append (@"fill:none;"); + s.append (@"stroke:#000000;"); + s.append (@"stroke-width:$(p.stroke)px;"); + + if (p.line_cap == LineCap.ROUND) { + s.append (@"stroke-linecap:round;"); + } else if (p.line_cap == LineCap.SQUARE) { + s.append (@"stroke-linecap:square;"); + } + + s.append (@"\" "); + + s.append (@"d=\"$(Svg.to_svg_path (p, glyph))\" id=\"path_$(name)_$(id)\" />\n"); + id++; } - - s.append (@"\" "); - - s.append (@"d=\"$(Svg.to_svg_path (p, glyph))\" id=\"path_$(name)_$(id)\" />\n"); - id++; + } else { + warning ("Copy and paste for other objects not implemented."); } } if (only_selected_paths) { - foreach (Path p in glyph.active_paths) { - if (p.stroke == 0) { - glyph_svg += Svg.to_svg_path (p, glyph); + foreach (Object p in glyph.active_paths) { + if (p is FastPath) { + Path path = ((FastPath) p).get_path (); + if (path.stroke == 0) { + glyph_svg += Svg.to_svg_path (path, glyph); + } + } else { + warning ("Not implemented"); } } } else {
diff --git libbirdfont/FastPath.vala(new)
--- /dev/null +++ b/libbirdfont/FastPath.vala @@ -1,1 +1,82 @@ + /* + 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 Cairo; + + namespace BirdFont { + + public class FastPath : Object { + + Path path; + + public FastPath () { + path = new Path (); + update_region_boundaries (); + } + + public FastPath.create_copy (FastPath p) { + base.create_copy (p); + path = p.path.copy (); + } + + public FastPath.for_path (Path path) { + this.path = path; + } + + public override bool is_over (double x, double y) { + return path.is_over (x, y); + } + + public override void draw (Context cr) { + } + + public override void move (double dx, double dy) { + path.move (dx, dy); + path.reset_stroke (); + } + + public Path get_path () { + return path; + } + + public override void update_region_boundaries () { + path.update_region_boundaries (); + xmax = path.xmax; + xmin = path.xmin; + ymax = path.ymax; + ymin = path.ymin; + } + + public override void rotate (double theta, double xc, double yc) { + path.rotate (theta, xc, yc); + rotation += theta; + rotation %= 2 * Math.PI; + } + + public override bool is_empty () { + return path.points.size == 0; + } + + public override void resize (double ratio_x, double ratio_y) { + path.resize (ratio_x, ratio_y); + path.reset_stroke (); + } + + public override Object copy () { + return new FastPath.create_copy (this); + } + } + + }
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -132,7 +132,7 @@ public Layer layers = new Layer (); public int current_layer = 0; - public Gee.ArrayList<Path> active_paths = new Gee.ArrayList<Path> (); + public Gee.ArrayList<Object> active_paths = new Gee.ArrayList<Object> (); public Gee.ArrayList<Layer> selected_groups = new Gee.ArrayList<Layer> (); // used if this glyph originates from a fallback font @@ -189,14 +189,14 @@ public Glyph.no_lines (string name, unichar unichar_code = 0) { this.name = name; this.unichar_code = unichar_code; - } - - public Gee.ArrayList<Path> get_active_paths () { - return active_paths; } public Layer get_current_layer () { - return_val_if_fail (0 <= current_layer < layers.subgroups.size, new Layer ()); + if (unlikely (!(0 <= current_layer < layers.subgroups.size))) { + warning ("Layer index out of bounds."); + return new Layer (); + } + return layers.subgroups.get (current_layer); } @@ -211,6 +211,10 @@ } warning ("Layer is not added to glyph."); + } + + public Gee.ArrayList<Object> get_visible_objects () { + return layers.get_visible_objects ().objects; } public Gee.ArrayList<Path> get_visible_paths () { @@ -219,6 +223,10 @@ public PathList get_visible_path_list () { return layers.get_visible_paths (); + } + + public Gee.ArrayList<Object> get_objects_in_current_layer () { + return get_current_layer ().get_all_objects ().objects; } public Gee.ArrayList<Path> get_paths_in_current_layer () { @@ -289,22 +297,35 @@ } public void add_active_path (Layer? group, Path? p) { - Path path; + if (p != null) { + FastPath path = new FastPath.for_path ((!) p); + add_active_object (group, path); + } else { + add_active_object (group, null); + } + } + + public void add_active_object (Layer? group, Object? o) { + Object object; Layer g; - if (p != null) { - path = (!) p; + if (o != null) { + object = (!) o; - if (Toolbox.get_move_tool ().is_selected ()) { - if (path.stroke > 0) { - Toolbox.set_object_stroke (path.stroke); - } + if (!active_paths.contains (object)) { + active_paths.add (object); } - - if (!active_paths.contains (path)) { - active_paths.add (path); + + if (object is FastPath) { + FastPath path = (FastPath) object; + if (Toolbox.get_move_tool ().is_selected ()) { + if (path.get_path ().stroke > 0) { + Toolbox.set_object_stroke (path.get_path ().stroke); + } + } + + PenTool.active_path = path.get_path (); } - PenTool.active_path = path; } if (group != null) { @@ -319,11 +340,6 @@ store_undo_state (); background_image = null; GlyphCanvas.redraw (); - } - - public Path? get_active_path () { - return_val_if_fail (active_paths.size > 0, null); - return active_paths.get (active_paths.size - 1); } public bool boundaries (out double x1, out double y1, out double x2, out double y2) { @@ -375,7 +391,7 @@ px2 = -10000; py2 = -10000; - foreach (Path p in active_paths) { + foreach (Object p in active_paths) { if (p.xmin < px) { px = p.xmin; } @@ -485,6 +501,14 @@ } get_current_layer ().add_path (p); + } + + public void add_object (Object object) { + if (layers.subgroups.size == 0) { + layers.add_layer (new Layer ()); + } + + get_current_layer ().add_object (object); } public override void selected_canvas () { @@ -926,8 +950,9 @@ add_path (path); path.reopen (); path.create_list (); - - add_active_path (null, path); + + FastPath object = new FastPath.for_path (path); + add_active_object (null, object); } if (remaining_points.paths.size > 0) { @@ -1040,7 +1065,7 @@ public void set_active_path (Path p) { p.reopen (); clear_active_paths (); - add_active_path (null, p); + add_active_object (null, new FastPath.for_path (p)); } /** Move view port centrum to this coordinate. */ @@ -1189,8 +1214,8 @@ bool found = false; foreach (Layer layer in get_current_layer ().subgroups) { - foreach (Path pt in layer.paths.paths) { - if (pt.is_over (x, y)) { + foreach (Object o in layer.objects) { + if (o.is_over (x, y)) { found = true; group = layer; } @@ -1233,8 +1258,8 @@ } public bool is_over_selected_path (double x, double y) { - foreach (Path pt in active_paths) { - if (pt.is_over (x, y)) { + foreach (Object p in active_paths) { + if (p.is_over (x, y)) { return true; } } @@ -1349,8 +1374,9 @@ return; } - foreach (Path path in active_paths) { + foreach (Object object in active_paths) { EditPoint p; + Path path = ((FastPath) object).get_path (); EditPoint pl = path.get_last_point (); if (pl.prev != null) { @@ -1364,7 +1390,6 @@ if (px > x) px -= tw + 60; if (py > y) py -= th + 60; - } else { px = x - 60; py = y - 60; @@ -1678,7 +1703,7 @@ p.recalculate_linear_handles (); } - p.draw_path (cr, this, color); + p.draw_path (cr, color); if (open) { p.reopen (); @@ -1718,11 +1743,14 @@ && !(MainWindow.get_toolbox ().get_current_tool () is BezierTool)) { cr.save (); cr.new_path (); - foreach (Path p in active_paths) { - if (p.stroke > 0) { - stroke = p.get_stroke_fast (); - color = Theme.get_color ("Selected Objects"); - draw_path_list (stroke, cr, color); + foreach (Object o in active_paths) { + if (o is FastPath) { + Path p = ((FastPath) o).get_path (); + if (p.stroke > 0) { + stroke = p.get_stroke_fast (); + color = Theme.get_color ("Selected Objects"); + draw_path_list (stroke, cr, color); + } } } cr.fill (); @@ -1735,7 +1763,7 @@ foreach (Path p in get_visible_paths ()) { if (p.stroke == 0) { color = p.color == null ? get_path_fill_color () : (!) p.color; - p.draw_path (cr, this, color); + p.draw_path (cr, color); } } cr.fill (); @@ -1761,22 +1789,25 @@ foreach (Path p in get_visible_paths ()) { if (p.stroke == 0) { color = p.color == null ? Color.black () : (!) p.color; - p.draw_path (cr, this, color); + p.draw_path (cr, color); } } cr.close_path (); cr.fill (); cr.restore (); - foreach (Path p in active_paths) { - cr.save (); - cr.new_path (); - if (p.stroke == 0) { - p.draw_path (cr, this); + foreach (Object o in active_paths) { + if (o is FastPath) { + Path p = ((FastPath) o).get_path (); + cr.save (); + cr.new_path (); + if (p.stroke == 0) { + p.draw_path (cr); + } + cr.close_path (); + cr.fill (); + cr.restore (); } - cr.close_path (); - cr.fill (); - cr.restore (); } } @@ -1800,7 +1831,7 @@ public void draw_path_list (PathList pl, Context cr, Color? c = null) { foreach (Path p in pl.paths) { - p.draw_path (cr, this, c); + p.draw_path (cr, c); } } @@ -1961,8 +1992,8 @@ g.layers = layers.copy (); - foreach (Path p in active_paths) { - g.active_paths.add (p); + foreach (Object o in active_paths) { + g.active_paths.add (o); } if (background_image != null) { @@ -2049,8 +2080,8 @@ } clear_active_paths (); - foreach (Path p in g.active_paths) { - add_active_path (null, p); + foreach (Object p in g.active_paths) { + add_active_object (null, p); } redraw_area (0, 0, allocation.width, allocation.height); @@ -2543,7 +2574,21 @@ return g2; } + + // FIXME: convert everything to the new Object code + public Gee.ArrayList<Path> get_active_paths () { + Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> (); + + foreach (Object object in active_paths) { + if (object is FastPath) { + paths.add (((FastPath) object).get_path ()); + } + } + + return paths; + } + } }
--- a/libbirdfont/Layer.vala +++ b/libbirdfont/Layer.vala @@ -15,7 +15,8 @@ namespace BirdFont { public class Layer : GLib.Object { - public PathList paths; + public ObjectGroup objects; + public Gee.ArrayList<Layer> subgroups; public bool visible = true; public string name = "Layer"; @@ -25,40 +26,80 @@ public bool single_path = false; public Layer () { - paths = new PathList (); + objects = new ObjectGroup (); subgroups = new Gee.ArrayList<Layer> (); } public int index_of (Layer sublayer) { return subgroups.index_of (sublayer); } - + + public ObjectGroup get_all_objects () { + ObjectGroup o = new ObjectGroup (); + + o.append (objects); + + foreach (Layer sublayer in subgroups) { + o.append (sublayer.get_all_objects ()); + } + + return o; + } + public PathList get_all_paths () { - PathList p = new PathList (); + PathList paths = new PathList (); - p.append (paths); + foreach (Object o in objects) { + if (o is FastPath) { + FastPath p = (FastPath) o; + paths.add (p.get_path ()); + } + } foreach (Layer sublayer in subgroups) { - p.append (sublayer.get_all_paths ()); + paths.append (sublayer.get_all_paths ()); } - return p; + return paths; + } + + public ObjectGroup get_visible_objects () { + ObjectGroup paths = new ObjectGroup (); + + if (visible) { + foreach (Object o in objects) { + paths.add (o); + } + } + + foreach (Layer sublayer in subgroups) { + if (sublayer.visible) { + paths.append (sublayer.get_visible_objects ()); + } + } + + return paths; } public PathList get_visible_paths () { - PathList p = new PathList (); + PathList paths = new PathList (); if (visible) { - p.append (paths); + foreach (Object o in objects) { + if (o is FastPath) { + FastPath p = (FastPath) o; + paths.add (p.get_path ()); + } + } } foreach (Layer sublayer in subgroups) { if (sublayer.visible) { - p.append (sublayer.get_all_paths ()); + paths.append (sublayer.get_visible_paths ()); } } - return p; + return paths; } public void add_layer (Layer layer) { @@ -66,18 +107,52 @@ } public void add_path (Path path) { - paths.add (path); + FastPath p = new FastPath.for_path (path); + objects.add (p); } + public void add_object (Object object) { + objects.add (object); + } + + public void append_paths (PathList path_list) { + foreach (Path p in path_list.paths) { + add_path (p); + } + } + + private FastPath? get_fast_path (Path path) { + foreach (Object o in objects) { + if (o is FastPath) { + FastPath p = (FastPath) o; + if (p.get_path () == path) { + return p; + } + } + } + + return null; + } + public void remove_path (Path path) { - paths.remove (path); + FastPath? p = get_fast_path (path); + + if (p != null) { + objects.remove ((!) p); + } + foreach (Layer sublayer in subgroups) { sublayer.remove_path (path); } } + public void remove (Object o) { + objects.remove (o); + } + public void remove_layer (Layer layer) { subgroups.remove (layer); + foreach (Layer sublayer in subgroups) { sublayer.remove_layer (layer); } @@ -87,7 +162,7 @@ Layer layer = new Layer (); layer.name = name; - layer.paths = paths.copy (); + layer.objects = objects.copy (); layer.visible = visible; foreach (Layer l in subgroups) { @@ -111,7 +186,7 @@ px2 = Glyph.CANVAS_MIN; py2 = Glyph.CANVAS_MIN; - foreach (Path p in get_all_paths ().paths) { + foreach (Object p in get_all_objects ().objects) { if (px > p.xmin) { px = p.xmin; } @@ -136,14 +211,14 @@ } public void print (int indent = 0) { - foreach (Path p in paths.paths) { + foreach (Object o in objects) { for (int i = 0; i < indent; i++) { stdout.printf ("\t"); } - stdout.printf (@"Path open: $(p.is_open ())"); + stdout.printf (@"Path open: $(o.is_open ())"); - if (p.color != null) { - stdout.printf (" %s", ((!) p.color).to_rgb_hex ()); + if (o.color != null) { + stdout.printf (" %s", ((!) o.color).to_rgb_hex ()); } stdout.printf ("\n");
--- a/libbirdfont/MenuTab.vala +++ b/libbirdfont/MenuTab.vala @@ -645,28 +645,28 @@ Gee.ArrayList<Path> paths = new Gee.ArrayList<Path> (); // selected objects - foreach (Path p in g.active_paths) { + foreach (Path p in g.get_active_paths ()) { paths.add (PenTool.simplify (p, false, PenTool.simplification_threshold)); } // selected segments if (paths.size == 0) { - foreach (Path p in g.get_all_paths ()) { + foreach (Path p in g.get_active_paths ()) { g.add_active_path (null, p); } - foreach (Path p in g.active_paths) { + foreach (Path p in g.get_active_paths ()) { paths.add (PenTool.simplify (p, true, PenTool.simplification_threshold)); } } g.store_undo_state (); - foreach (Path p in g.active_paths) { - g.layers.remove_path (p); + foreach (Object o in g.active_paths) { + g.layers.remove (o); } - foreach (Path p in g.active_paths) { + foreach (Path p in g.get_active_paths ()) { g.layers.remove_path (p); }
--- a/libbirdfont/MoveTool.vala +++ b/libbirdfont/MoveTool.vala @@ -94,8 +94,8 @@ g.store_undo_state (); } - foreach (Path p in g.active_paths) { - g.layers.remove_path (p); + foreach (Object p in g.active_paths) { + g.layers.remove (p); g.update_view (); } @@ -138,7 +138,7 @@ } } - foreach (Path path in glyph.active_paths) { + foreach (Object path in glyph.active_paths) { path.move (delta_x, delta_y); } } @@ -167,7 +167,7 @@ if (GridTool.is_visible () && moved) { tie_paths_to_grid (glyph); } else if (GridTool.has_ttf_grid ()) { - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { tie_path_to_ttf_grid (p); } } @@ -184,8 +184,11 @@ objects_moved (); DrawingTools.resize_tool.signal_objects_rotated (); - foreach (Path p in glyph.active_paths) { - p.create_full_stroke (); + foreach (Object o in glyph.active_paths) { + if (o is FastPath) { + FastPath path = (FastPath) o; + path.get_path ().create_full_stroke (); + } } } else { objects_deselected (); @@ -194,7 +197,7 @@ public void press (int b, int x, int y) { Glyph glyph = MainWindow.get_current_glyph (); - Path p; + Object object; bool selected = false; Layer? group; Layer g; @@ -207,20 +210,20 @@ 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); + return_if_fail (g.objects.objects.size > 0); + object = g.objects.objects.get (0); + selected = glyph.active_paths.contains (object); if (!selected && !KeyBindings.has_shift ()) { glyph.clear_active_paths (); } - foreach (Path lp in g.paths.paths) { + foreach (Object lp in g.objects) { if (selected && KeyBindings.has_shift ()) { glyph.selected_groups.remove ((!) group); glyph.active_paths.remove (lp); } else { - glyph.add_active_path ((!) group, lp); + glyph.add_active_object ((!) group, lp); } } } else if (!KeyBindings.has_shift ()) { @@ -256,10 +259,10 @@ glyph.clear_active_paths (); - foreach (Path p in glyph.get_paths_in_current_layer ()) { + foreach (Object p in glyph.get_objects_in_current_layer ()) { if (p.xmin > x1 && p.xmax < x2 && p.ymin < y1 && p.ymax > y2) { - if (p.points.size > 0) { - glyph.add_active_path (null, p); + if (!p.is_empty ()) { + glyph.add_active_object (null, p); } } } @@ -280,7 +283,7 @@ get_selection_box_boundaries (out x, out y, out w, out h); - foreach (Path path in glyph.active_paths) { + foreach (Object path in glyph.active_paths) { path.move (glyph.left_limit - x + w / 2, font.base_line - y + h / 2); } @@ -317,23 +320,26 @@ px2 = -10000; py2 = -10000; - foreach (Path p in glyph.active_paths) { - p.update_region_boundaries (); - - if (px > p.xmin) { - px = p.xmin; - } + foreach (Object o in glyph.active_paths) { + if (o is FastPath) { + Path p = ((FastPath) o).get_path (); + p.update_region_boundaries (); + + if (px > p.xmin) { + px = p.xmin; + } - if (py > p.ymin) { - py = p.ymin; - } + if (py > p.ymin) { + py = p.ymin; + } - if (px2 < p.xmax) { - px2 = p.xmax; - } - - if (py2 < p.ymax) { - py2 = p.ymax; + if (px2 < p.xmax) { + px2 = p.xmax; + } + + if (py2 < p.ymax) { + py2 = p.ymax; + } } } @@ -367,7 +373,7 @@ break; } - foreach (Path path in glyph.active_paths) { + foreach (Object path in glyph.active_paths) { path.move (x * Glyph.ivz (), y * Glyph.ivz ()); } @@ -378,7 +384,7 @@ glyph.redraw_area (0, 0, glyph.allocation.width, glyph.allocation.height); } - static void tie_path_to_ttf_grid (Path p) { + static void tie_path_to_ttf_grid (Object p) { double sx, sy, qx, qy; sx = p.xmax; @@ -428,7 +434,7 @@ dx_min = Math.fabs (qx - minx); dx_max = Math.fabs (sx - maxx); - foreach (Path p in g.active_paths) { + foreach (Object p in g.active_paths) { if (dy_min < dy_max) { p.move (0, qy - miny); } else { @@ -447,8 +453,10 @@ public static void update_boundaries_for_selection () { Glyph glyph = MainWindow.get_current_glyph (); - foreach (Path p in glyph.active_paths) { - p.update_region_boundaries (); + foreach (Object o in glyph.active_paths) { + if (o is FastPath) { + ((FastPath)o).get_path ().update_region_boundaries (); + } } } @@ -470,14 +478,19 @@ xc = selection_box_center_x; yc = selection_box_center_y; - foreach (Path p in glyph.active_paths) { - if (vertical) { - p.flip_vertical (); - } else { - p.flip_horizontal (); + foreach (Object p in glyph.active_paths) { + if (p is FastPath) { + Path path = ((FastPath) p).get_path (); + + // FIXME: move to object + if (vertical) { + path.flip_vertical (); + } else { + path.flip_horizontal (); + } + + path.reverse (); } - - p.reverse (); } get_selection_box_boundaries (out xc2, out yc2, out w, out h); @@ -485,7 +498,7 @@ dx = -(xc2 - xc); dy = -(yc2 - yc); - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { p.move (dx, dy); } @@ -499,9 +512,9 @@ Glyph g = MainWindow.get_current_glyph (); g.clear_active_paths (); - foreach (Path p in g.get_paths_in_current_layer ()) { - if (p.points.size > 0) { - g.add_active_path (null, p); + foreach (Object p in g.get_objects_in_current_layer ()) { + if (!p.is_empty ()) { + g.add_active_object (null, p); } }
diff --git libbirdfont/Object.vala(new)
--- /dev/null +++ b/libbirdfont/Object.vala @@ -1,1 +1,89 @@ + /* + 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 Cairo; + using Math; + + namespace BirdFont { + + public abstract class Object : GLib.Object { + bool open = false; + + public Color? color = null; + public Color? stroke_color = null; + public Gradient? gradient = null; + + /** Path boundaries */ + public double xmax = Glyph.CANVAS_MIN; + public double xmin = Glyph.CANVAS_MAX; + public double ymax = Glyph.CANVAS_MIN; + public double ymin = Glyph.CANVAS_MAX; + + public double rotation = 0; + public double stroke = 0; + public LineCap line_cap = LineCap.BUTT; + + public Object () { + } + + public Object.create_copy (Object o) { + open = o.open; + + if (color != null) { + color = ((!) color).copy (); + } else { + color = null; + } + + if (stroke_color != null) { + stroke_color = ((!) stroke_color).copy (); + } else { + stroke_color = null; + } + + if (gradient != null) { + gradient = ((!) gradient).copy (); + } else { + gradient = null; + } + + xmax = o.xmax; + xmin = o.xmin; + ymax = o.ymax; + ymin = o.ymin; + + rotation = o.rotation; + stroke = o.stroke; + } + + public void set_open (bool open) { + this.open = open; + } + + public bool is_open () { + return open; + } + + public abstract void update_region_boundaries (); + public abstract bool is_over (double x, double y); + public abstract void draw (Context cr); + public abstract Object copy (); + public abstract void move (double dx, double dy); + public abstract void rotate (double theta, double xc, double yc); + public abstract bool is_empty (); + public abstract void resize (double ratio_x, double ratio_y); + } + + }
--- /dev/null +++ b/libbirdfont/ObjectGroup.vala @@ -1,1 +1,58 @@ + /* + 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 ObjectGroup : GLib.Object { + public Gee.ArrayList<Object> objects; + + public ObjectGroup () { + objects = new Gee.ArrayList<Object> (); + } + + public Gee.Iterator<Object> iterator () { + return objects.iterator (); + } + + public void remove (Object p) { + objects.remove (p); + } + + public void add (Object p) { + objects.add (p); + } + + public void clear () { + objects.clear (); + } + + public void append (ObjectGroup group) { + foreach (Object o in group.objects) { + objects.add (o); + } + } + + public ObjectGroup copy () { + ObjectGroup objects_copy = new ObjectGroup (); + + foreach (Object o in objects) { + objects_copy.add (o.copy ()); + } + + return objects_copy; + } + } + + }
--- a/libbirdfont/OpenFontFormat/FontData.vala +++ b/libbirdfont/OpenFontFormat/FontData.vala @@ -14,7 +14,7 @@ namespace BirdFont { - public class FontData : Object { + public class FontData : GLib.Object { // Read pointer uint rp = 0;
--- a/libbirdfont/OpenFontFormat/GlyfData.vala +++ b/libbirdfont/OpenFontFormat/GlyfData.vala @@ -16,7 +16,7 @@ namespace BirdFont { - public class CoordinateFlags { + public class CoordinateFlags : GLib.Object { /** TTF coordinate flags. */ public static const uint8 NONE = 0;
--- a/libbirdfont/OpenFontFormat/GlyfTable.vala +++ b/libbirdfont/OpenFontFormat/GlyfTable.vala @@ -1,5 +1,5 @@ /* - Copyright (C) 2012, 2013, 2014 Johan Mattsson + Copyright (C) 2012 2013 2014 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 @@ -478,7 +478,7 @@ end_points = new uint16[ncontours + 1]; for (int i = 0; i < ncontours; i++) { - end_points[i] = dis.read_ushort (); // FIXA: mind shot vector is negative + end_points[i] = dis.read_ushort (); // FIXME: mind shot vector is negative if (i > 0 && end_points[i] < end_points[i -1]) { warning (@"Next endpoint has bad value in $(name.str). (end_points[i] > end_points[i -1]) ($(end_points[i]) > $(end_points[i -1])) i: $i ncontours: $ncontours");
--- a/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala +++ b/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala @@ -58,7 +58,7 @@ PARSE } - public class OpenFontFormatReader : Object { + public class OpenFontFormatReader : GLib.Object { public DirectoryTable directory_table; public FontData font_data = new FontData ();
--- a/libbirdfont/OpenFontFormat/OpenFontFormatWriter.vala +++ b/libbirdfont/OpenFontFormat/OpenFontFormatWriter.vala @@ -14,7 +14,7 @@ namespace BirdFont { - public class OpenFontFormatWriter : Object { + public class OpenFontFormatWriter : GLib.Object { DataOutputStream os; DataOutputStream os_mac;
--- a/libbirdfont/OpenFontFormat/OtfInputStream.vala +++ b/libbirdfont/OpenFontFormat/OtfInputStream.vala @@ -15,7 +15,7 @@ namespace BirdFont { /** Reader for otf data types. */ - public class OtfInputStream : Object { + public class OtfInputStream : GLib.Object { public FileInputStream fin; public DataInputStream din;
--- a/libbirdfont/OpenFontFormat/OtfTable.vala +++ b/libbirdfont/OpenFontFormat/OtfTable.vala @@ -14,7 +14,7 @@ namespace BirdFont { - public class OtfTable : Object { + public class OtfTable : GLib.Object { public string id = "NO_ID";
--- a/libbirdfont/OrientationTool.vala +++ b/libbirdfont/OrientationTool.vala @@ -30,8 +30,11 @@ select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); - foreach (Path p in g.active_paths) { - p.reverse (); + foreach (Object o in g.active_paths) { + if (o is FastPath) { + FastPath p = (FastPath) o; + p.get_path ().reverse (); + } } count_down = true; @@ -54,13 +57,17 @@ bool has_clockwise_paths = false; bool has_counter_clockwise_paths = false; - foreach (Path p in glyph.active_paths) { - if (p.is_clockwise ()) { - has_clockwise_paths = true; - } - - if (!p.is_clockwise ()) { - has_counter_clockwise_paths = true; + foreach (Object o in glyph.active_paths) { + if (o is FastPath) { + Path p = ((FastPath) o).get_path (); + + if (p.is_clockwise ()) { + has_clockwise_paths = true; + } + + if (!p.is_clockwise ()) { + has_counter_clockwise_paths = true; + } } }
--- a/libbirdfont/OtfFeatureTable.vala +++ b/libbirdfont/OtfFeatureTable.vala @@ -45,7 +45,7 @@ public override void selected_row (Row row, int column, bool delete_button) { int row_index = row.get_index (); - Object o; + GLib.Object o; String s; AlternateItem a;
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -99,13 +99,12 @@ public bool highlight_last_segment = false; public string point_data = ""; + + private static Text? arrow = null; public Color? color = null; public Color? stroke_color = null; - public Gradient? gradient = null; - - private static Text? arrow = null; public Path () { string width; @@ -262,7 +261,7 @@ * Call Context.new_path (); before this method and Context.fill () * to show the path. */ - public void draw_path (Context cr, Glyph glyph, Color? color = null) { + public void draw_path (Context cr, Color? color = null) { unowned EditPoint? n = null; unowned EditPoint en; unowned EditPoint em; @@ -274,8 +273,8 @@ return; } - center_x = glyph.allocation.width / 2.0; - center_y = glyph.allocation.height / 2.0; + center_x = Glyph.xc (); + center_y = Glyph.yc (); ex = center_x + points.get (0).x; ey = center_y - points.get (0).y; @@ -2265,12 +2264,6 @@ PathList lines = new PathList (); lines = pl; - - /** // FIXME: Check automatic orientation. - foreach (Path p in pl.paths) { - lines.add (SvgParser.get_lines (p)); - } - */ foreach (Path p in lines.paths) { if (p.points.size > 1 && p != path
--- a/libbirdfont/PenTool.vala +++ b/libbirdfont/PenTool.vala @@ -765,8 +765,11 @@ p.path.reset_stroke (); } - foreach (Path path in g.active_paths) { - path.reset_stroke (); + foreach (Object path in g.active_paths) { + if (path is FastPath) { + FastPath p = (FastPath) path; + p.get_path ().reset_stroke (); + } } } @@ -1055,10 +1058,11 @@ // don't use set point to reflective to on open ends reflective = true; - foreach (Path path in MainWindow.get_current_glyph ().active_paths) { - if (path.is_open () && path.points.size > 0) { - if (selected_handle.parent == path.get_first_point () - || selected_handle.parent == path.get_last_point ()) { + foreach (Object path in MainWindow.get_current_glyph ().active_paths) { + if (path.is_open () && !path.is_empty () && path is FastPath) { + Path p = ((FastPath) path).get_path (); + if (selected_handle.parent == p.get_first_point () + || selected_handle.parent == p.get_last_point ()) { reflective = false; } } @@ -1229,7 +1233,10 @@ if (active_edit_point != null) { glyph.clear_active_paths (); - glyph.add_active_path (null, active_path); + + FastPath path = new FastPath.for_path (active_path); + glyph.add_active_object (null, path); + DrawingTools.update_stroke_settings (); if (KeyBindings.modifier != SHIFT) { @@ -1408,8 +1415,10 @@ foreach (Path merge in paths) { if (merge.points.size > 0) { - if (is_close_to_point (merge.points.get (merge.points.size - 1), px, py)) { - glyph.add_active_path (null, merge); + FastPath merged_path = new FastPath.for_path (merge); + + if (is_close_to_point (merge.points.get (merge.points.size - 1), px, py)) { + glyph.add_active_object (null, merged_path); active_path = merge; merge.reopen (); glyph.open_path (); @@ -1417,7 +1426,7 @@ } if (is_close_to_point (merge.points.get (0), px, py)) { - glyph.add_active_path (null, merge); + glyph.add_active_object (null, merged_path); active_path = merge; clear_directions (); merge.reopen (); @@ -1453,7 +1462,9 @@ force_direction (); glyph.clear_active_paths (); - glyph.add_active_path (null, path); + + FastPath closed_path = new FastPath.for_path (path); + glyph.add_active_object (null, closed_path); if (direction_changed) { path.reverse (); @@ -1492,11 +1503,12 @@ } else { union = merge_open_paths (path, merge); + FastPath union_path = new FastPath.for_path (union); glyph.add_path (union); glyph.delete_path (path); glyph.delete_path (merge); glyph.clear_active_paths (); - glyph.add_active_path (null, union); + glyph.add_active_object (null, union_path); union.reopen (); union.create_list (); @@ -1777,13 +1789,19 @@ active_edit_point = new_point.point; return_val_if_fail (glyph.active_paths.size > 0, new PointSelection.empty ()); - add_selected_point (selected_point, glyph.active_paths.get (glyph.active_paths.size - 1)); + Object object = glyph.active_paths.get (glyph.active_paths.size - 1); + + if (object is FastPath) { + Path path = ((FastPath) object).get_path (); + + add_selected_point (selected_point, path); - active_path = new_point.path; - glyph.clear_active_paths (); - glyph.add_active_path (null, new_point.path); - - move_selected = true; + active_path = new_point.path; + glyph.clear_active_paths (); + glyph.add_active_object (null, object); + + move_selected = true; + } return new_point; } @@ -1819,6 +1837,7 @@ EditPoint inserted; bool stroke = StrokeTool.add_stroke; Glyph g = MainWindow.get_current_glyph (); + FastPath path; if (g.active_paths.size == 0) { np = new Path (); @@ -1826,7 +1845,8 @@ np.stroke = stroke ? StrokeTool.stroke_width : 0; np.line_cap = StrokeTool.line_cap; - g.add_active_path (null, np); + path = new FastPath.for_path (np); + g.add_active_object (null, path); active_path = np; selected_path = np; @@ -1852,7 +1872,8 @@ } g.clear_active_paths (); - g.add_active_path (null, np); + path = new FastPath.for_path (np); + g.add_active_object (null, path); active_path = np; selected_path = np; @@ -2062,7 +2083,8 @@ selected_handle.selected = true; active_path = p.path; - g.add_active_path (null, active_path); + FastPath path = new FastPath.for_path (active_path); + g.add_active_object (null, path); } public static void add_selected_point (EditPoint p, Path path) {
--- a/libbirdfont/ResizeTool.vala +++ b/libbirdfont/ResizeTool.vala @@ -21,7 +21,7 @@ bool resize_path_proportional = false; bool resize_width = false; - Path? resized_path = null; + Object? resized_path = null; double last_resize_y; double last_resize_x; @@ -63,13 +63,13 @@ }); press_action.connect((self, b, x, y) => { - Path last_path; + Object last_path; Glyph glyph; glyph = MainWindow.get_current_glyph (); glyph.store_undo_state (); - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { if (is_over_resize_handle (p, x, y)) { resize_path_proportional = true; resized_path = p; @@ -87,7 +87,7 @@ } } - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { if (is_over_rotate_handle (p, x, y)) { rotate_path = true; return; @@ -121,8 +121,11 @@ update_selection_box (); GlyphCanvas.redraw (); - foreach (Path p in MainWindow.get_current_glyph ().active_paths) { - p.create_full_stroke (); + foreach (Object p in MainWindow.get_current_glyph ().active_paths) { + if (p is FastPath) { + FastPath path = (FastPath) p; + path.get_path ().create_full_stroke (); + } } }); @@ -150,10 +153,6 @@ || resize_width) { glyph = MainWindow.get_current_glyph (); - - foreach (Path selected_path in glyph.active_paths) { - selected_path.reset_stroke (); - } GlyphCanvas.redraw (); } @@ -234,9 +233,9 @@ public void rotate_selected_paths (double angle, double cx, double cy) { Glyph glyph = MainWindow.get_current_glyph (); double dx, dy, xc2, yc2, w, h; - Path last_path; + Object last_path; - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { p.rotate (angle, cx, cy); } @@ -245,7 +244,7 @@ dx = -(xc2 - cx); dy = -(yc2 - cy); - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { p.move (dx, dy); } @@ -287,7 +286,7 @@ rotate_selected_paths (rotation - last_rotate, selection_box_center_x, selection_box_center_y); } - static bool is_over_rotate_handle (Path p, double x, double y) { + static bool is_over_rotate_handle (Object p, double x, double y) { double cx, cy, hx, hy; double size = 10; bool inx, iny; @@ -364,17 +363,16 @@ if (!selected) { glyph.clear_active_paths (); - foreach (Path path in glyph.get_visible_paths ()) { - glyph.add_active_path (null, path); + foreach (Object path in glyph.get_visible_objects ()) { + glyph.add_active_object (null, path); } } get_selection_min (out resize_pos_x, out resize_pos_y); // resize paths - foreach (Path selected_path in glyph.active_paths) { + foreach (Object selected_path in glyph.active_paths) { selected_path.resize (ratio_x, ratio_y); - selected_path.reset_stroke (); } // move paths relative to the updated xmin and xmax @@ -382,7 +380,7 @@ dx = resize_pos_x - selection_minx; dy = resize_pos_y - selection_miny; - foreach (Path selected_path in glyph.active_paths) { + foreach (Object selected_path in glyph.active_paths) { selected_path.move (dx, dy); } @@ -470,7 +468,7 @@ DrawingTools.move_tool.move_to_baseline (); - foreach (Path path in glyph.active_paths) { + foreach (Object path in glyph.active_paths) { path.move (0, -descender * scale); } @@ -481,7 +479,7 @@ Glyph glyph = MainWindow.get_current_glyph (); x = double.MAX; y = double.MAX; - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { if (p.xmin < x) { x = p.xmin; } @@ -497,11 +495,11 @@ double h, w; double ratio = get_resize_ratio (x, y); - foreach (Path selected_path in glyph.active_paths) { + foreach (Object selected_path in glyph.active_paths) { h = selected_path.ymax - selected_path.ymin; w = selected_path.xmax - selected_path.xmin; - if (selected_path.points.size <= 1) { + if (selected_path.is_empty ()) { // FIXME: test with one point continue; } @@ -513,13 +511,13 @@ return true; } - bool is_over_resize_handle (Path p, double x, double y) { + bool is_over_resize_handle (Object p, double x, double y) { double handle_x, handle_y; get_resize_handle_position (out handle_x, out handle_y); return Path.distance (handle_x, x, handle_y, y) < 12 * MainWindow.units; } - bool is_over_horizontal_resize_handle (Path p, double x, double y) { + bool is_over_horizontal_resize_handle (Object p, double x, double y) { double handle_x, handle_y; get_horizontal_reseize_handle_position (out handle_x, out handle_y); return Path.distance (handle_x, x, handle_y, y) < 12 * MainWindow.units; @@ -540,26 +538,28 @@ if (!selected_paths) { glyph.clear_active_paths (); - foreach (Path path in glyph.get_visible_paths ()) { - glyph.add_active_path (null, path); + foreach (Object path in glyph.get_visible_objects ()) { + glyph.add_active_object (null, path); } } glyph.selection_boundaries (out x, out y, out w, out h); - foreach (Path path in glyph.active_paths) { - SvgParser.apply_matrix (path, 1, 0, s, 1, 0, 0); - path.skew = skew; - path.update_region_boundaries (); + foreach (Object path in glyph.active_paths) { + if (path is FastPath) { // FIXME: other objects + Path p = ((FastPath) path).get_path (); + SvgParser.apply_matrix (p, 1, 0, s, 1, 0, 0); + p.skew = skew; + path.update_region_boundaries (); + } } glyph.selection_boundaries (out nx, out y, out nw, out h); dx = -(nx - x); - foreach (Path p in glyph.active_paths) { + foreach (Object p in glyph.active_paths) { p.move (dx, 0); - p.reset_stroke (); } dw = (nw - w);
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -51,22 +51,27 @@ convert_stroke = true; g.store_undo_state (); - foreach (Path p in g.active_paths) { - if (p.stroke > 0) { - paths.append (p.get_completed_stroke ()); + foreach (Object o in g.active_paths) { + if (o is FastPath) { + FastPath path = (FastPath) o; + Path p = path.get_path (); + + if (p.stroke > 0) { + paths.append (p.get_completed_stroke ()); + } } } if (paths.paths.size > 0) { - foreach (Path p in g.active_paths) { - g.layers.remove_path (p); + foreach (Object o in g.active_paths) { + g.layers.remove (o); } g.active_paths.clear (); foreach (Path np in paths.paths) { g.add_path (np); - g.active_paths.add (np); + g.active_paths.add (new FastPath.for_path (np)); } PenTool.update_orientation (); @@ -134,11 +139,15 @@ g.store_undo_state (); - foreach (Path p in g.active_paths) { - if (p.stroke == 0) { - o.add (p); - } else { - o.append (p.get_completed_stroke ()); + foreach (Object object in g.active_paths) { + if (object is FastPath) { + Path p = ((FastPath) object).get_path (); + + if (p.stroke == 0) { + o.add (p); + } else { + o.append (p.get_completed_stroke ()); + } } } @@ -217,8 +226,8 @@ return; } - foreach (Path p in g.active_paths) { - g.delete_path (p); + foreach (Object object in g.active_paths) { + g.layers.remove (object); } g.clear_active_paths (); @@ -226,8 +235,9 @@ remove_merged_curve_parts (new_paths); foreach (Path p in new_paths.paths) { - g.add_path (p); - g.add_active_path (null, p); + FastPath path = new FastPath.for_path (p); + g.add_object (path); + g.add_active_object (null, path); } PenTool.update_orientation ();
--- a/libbirdfont/SvgFontFormatWriter.vala +++ b/libbirdfont/SvgFontFormatWriter.vala @@ -14,7 +14,7 @@ namespace BirdFont { - class SvgFontFormatWriter : Object { + class SvgFontFormatWriter : GLib.Object { DataOutputStream os;
--- a/libbirdfont/SvgParser.vala +++ b/libbirdfont/SvgParser.vala @@ -160,12 +160,10 @@ glyph = MainWindow.get_current_glyph (); foreach (Path p in path_list.paths) { - glyph.add_path (p); - } - - foreach (Path p in path_list.paths) { - glyph.add_active_path (null, p); // FIXME: groups - p.update_region_boundaries (); + FastPath path = new FastPath.for_path (p); + glyph.add_object (path); + glyph.add_active_object (null, path); // FIXME: groups + path.update_region_boundaries (); } glyph.close_path (); @@ -302,7 +300,15 @@ } private void transform (string transform_functions, Layer layer) { - transform_paths (transform_functions, layer.paths); + PathList path_list = new PathList (); + + foreach (Object o in layer.objects) { + if (o is FastPath) { + path_list.add (((FastPath) o).get_path ()); + } + } + + transform_paths (transform_functions, path_list); transform_subgroups (transform_functions, layer); } @@ -315,7 +321,7 @@ private void transform_paths (string transform_functions, PathList pl) { string data = transform_functions.dup (); string[] functions; - + // use only a single space as separator while (data.index_of (" ") > -1) { data = data.replace (" ", " "); @@ -538,7 +544,7 @@ } style.apply (npl); - pl.paths.append (npl); + pl.append_paths (npl); } private void parse_ellipse (Tag tag, Layer pl) { @@ -606,7 +612,7 @@ } style.apply (npl); - pl.paths.append (npl); + pl.append_paths (npl); } private void parse_line (Tag tag, Layer pl) { @@ -683,10 +689,10 @@ } style.apply (npl); - pl.paths.append (npl); + pl.append_paths (npl); } - private void parse_rect (Tag tag, Layer pl) { + private void parse_rect (Tag tag, Layer layer) { Path p; double x, y, x2, y2; BezierPoints[] bezier_points; @@ -784,22 +790,22 @@ } style.apply (npl); - pl.paths.append (npl); + layer.append_paths (npl); } - private void parse_polygon (Tag tag, Layer pl) { + private void parse_polygon (Tag tag, Layer layer) { PathList path_list = get_polyline (tag); foreach (Path p in path_list.paths) { p.close (); } - pl.paths.append (path_list); + layer.append_paths (path_list); } - private void parse_polyline (Tag tag, Layer pl) { - pl.paths.append (get_polyline (tag)); + private void parse_polyline (Tag tag, Layer layer) { + layer.append_paths (get_polyline (tag)); } private PathList get_polyline (Tag tag) { @@ -836,7 +842,7 @@ return path_list; } - private void parse_path (Tag tag, Layer pl) { + private void parse_path (Tag tag, Layer layer) { Glyph glyph = MainWindow.get_current_glyph (); PathList path_list = new PathList (); SvgStyle style = new SvgStyle (); @@ -863,37 +869,47 @@ if (hidden) { return; } - - pl.paths.append (path_list); + + foreach (Path path in path_list.paths) { + layer.add_path (path); + } + style.apply (path_list); // assume the even odd rule is applied and convert the path // to a path using the non-zero rule int inside_count; bool inside; - foreach (Path p1 in pl.paths.paths) { - inside_count = 0; - - foreach (Path p2 in pl.paths.paths) { - if (p1 != p2) { - inside = true; + foreach (Object o1 in layer.objects) { + if (o1 is FastPath) { + Path p1 = ((FastPath) o1).get_path (); + inside_count = 0; + + foreach (Object o2 in layer.objects) { + if (o2 is FastPath) { + Path p2 = ((FastPath) o2).get_path (); - foreach (EditPoint ep in p1.points) { - if (!is_inside (ep, p2)) { - inside = false; + if (p1 != p2) { + inside = true; + + foreach (EditPoint ep in p1.points) { + if (!is_inside (ep, p2)) { + inside = false; + } + } + + if (inside) { + inside_count++; + } } - } - - if (inside) { - inside_count++; } } - } - - if (inside_count % 2 == 0) { - p1.force_direction (Direction.CLOCKWISE); - } else { - p1.force_direction (Direction.COUNTER_CLOCKWISE); + + if (inside_count % 2 == 0) { + p1.force_direction (Direction.CLOCKWISE); + } else { + p1.force_direction (Direction.COUNTER_CLOCKWISE); + } } }
--- a/libbirdfont/Test.vala +++ b/libbirdfont/Test.vala @@ -14,7 +14,7 @@ namespace BirdFont { - public class Test : Object { + public class Test : GLib.Object { public Callback callback; public string name; double time_stamp;
--- a/libbirdfont/TrackTool.vala +++ b/libbirdfont/TrackTool.vala @@ -121,8 +121,11 @@ start_update_timer (); drawing = true; - foreach (Path path in glyph.active_paths) { - path.create_full_stroke (); // cache merged stroke parts + foreach (Object path in glyph.active_paths) { + if (path is FastPath) { + // cache merged stroke parts + ((FastPath) path).get_path ().create_full_stroke (); + } } } }); @@ -146,8 +149,9 @@ g = MainWindow.get_current_glyph (); if (g.active_paths.size > 0) { // set type for last point - p = g.active_paths.get (g.active_paths.size - 1); - + Object o = g.active_paths.get (g.active_paths.size - 1); + p = ((FastPath) o).get_path (); + if (p.points.size > 1) { previous = p.points.get (p.points.size - 1); previous.type = DrawingTools.point_type; @@ -164,8 +168,10 @@ add_endpoint_and_merge (x, y); } - foreach (Path path in g.active_paths) { - convert_hidden_points (path); + foreach (Object path in g.active_paths) { + if (path is FastPath) { + convert_hidden_points (((FastPath) path).get_path ()); + } } g.clear_active_paths (); @@ -403,7 +409,14 @@ return; } - p = glyph.active_paths.get (glyph.active_paths.size - 1); + Object o = glyph.active_paths.get (glyph.active_paths.size - 1); + + if (o is FastPath) { + warning ("Object is not a path"); + return; + } + + p = ((FastPath) o).get_path (); p.reopen (); px = Glyph.path_coordinate_x (x); py = Glyph.path_coordinate_y (y); @@ -488,7 +501,15 @@ return new Path (); } - return glyph.active_paths.get (glyph.active_paths.size - 1); + Object o = glyph.active_paths.get (glyph.active_paths.size - 1); + + if (likely (o is FastPath)) { + return ((FastPath) o).get_path (); + } + + warning ("Active object is a path."); + + return new Path (); } /** Delete all points close to the pixel at x,y. */