The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Use libsvgbird for drawing in libbirdfont

These changes was commited to the Birdfont repository Sun, 17 Jan 2016 20:20:06 +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>
Sun, 17 Jan 2016 20:20:06 +0000 (21:20 +0100)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Sun, 17 Jan 2016 20:20:06 +0000 (21:20 +0100)
commit 26e337be389f1befdddf0dcc0cf56cb818a52013
tree e68c3176c71eb3c385de3469657efb0cbd623b83
parent f17b819e135e82e966550170f00a7e4bbedbf9b2
Use libsvgbird for drawing in libbirdfont

16 files changed:
libbirdfont/BirdFont.vala
libbirdfont/BirdFontFile.vala
libbirdfont/CanvasSettings.vala [new ]
libbirdfont/EmbeddedSvg.vala
libbirdfont/Glyph.vala
libbirdfont/KerningDisplay.vala
libbirdfont/LayerUtils.vala
libbirdfont/OverViewItem.vala
libbirdfont/Path.vala
libbirdfont/PathObject.vala
libbirdfont/PenTool.vala
libbirdfont/SettingsTab.vala
libbirdfont/TrackTool.vala
libsvgbird/Layer.vala
libsvgbird/SvgStyle.vala
--- a/libbirdfont/BirdFont.vala +++ b/libbirdfont/BirdFont.vala @@ -90,7 +90,6 @@ public static Font current_font; public static GlyphCollection current_glyph_collection; - public static Drawing? drawing = null; public static string? settings_subdirectory = null; @@ -166,6 +165,8 @@ Process.exit (0); } #endif + + CanvasSettings.init (); Preferences.load (); // always load default theme when names in theme does change
--- a/libbirdfont/BirdFontFile.vala +++ b/libbirdfont/BirdFontFile.vala @@ -506,7 +506,7 @@ void write_layer (Layer layer, DataOutputStream os) throws GLib.Error { os.put_string (@"\t\t<layer name= \"$(layer.name)\" visible=\"$(layer.visible)\">\n"); - foreach (SvgBird.Object o in layer.get_all_objects ().objects) { + foreach (SvgBird.Object o in layer.objects.objects) { if (o is EmbeddedSvg) { write_embedded_svg ((EmbeddedSvg) o, os);
--- /dev/null +++ b/libbirdfont/CanvasSettings.vala @@ -1,1 +1,93 @@ + /* + Copyright (C) 2016 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; + using Cairo; + + namespace BirdFont { + + public class CanvasSettings { + + public static double stroke_width { + get { + settings_mutex.lock (); + double r = stroke_width_setting; + + if (unlikely (stroke_width_setting < 1)) { + string width = Preferences.get ("stroke_width"); + if (width != "") { + stroke_width_setting = double.parse (width); + } + } + + if (stroke_width_setting < 1) { + stroke_width_setting = 1; + } + + settings_mutex.unlock (); + return r; + } + + set { + settings_mutex.lock (); + stroke_width_setting = value; + settings_mutex.unlock (); + } + } + + public static bool show_all_line_handles { + get { + settings_mutex.lock (); + bool r = show_all_line_handles_setting; + settings_mutex.unlock (); + return r; + } + + set { + settings_mutex.lock (); + show_all_line_handles_setting = value; + settings_mutex.unlock (); + } + } + + public static bool fill_open_path { + get { + settings_mutex.lock (); + bool r = fill_open_path_setting; + settings_mutex.unlock (); + return r; + } + + set { + settings_mutex.lock (); + fill_open_path_setting = value; + settings_mutex.unlock (); + } + } + + static Mutex settings_mutex; + + /** The stroke of an outline when the path is not filled. */ + static double stroke_width_setting = 0; + static bool show_all_line_handles_setting = true; + static bool fill_open_path_setting = false; + + public static void init () { + settings_mutex = new Mutex (); + } + + } + + }
--- a/libbirdfont/EmbeddedSvg.vala +++ b/libbirdfont/EmbeddedSvg.vala @@ -76,11 +76,14 @@ && (this.y - drawing.height <= y <= this.y); } - public override void draw_outline (Context cr) { + public void draw_embedded_svg (Context cr) { cr.save (); cr.translate (Glyph.xc () + x, Glyph.yc () - y); drawing.draw (cr); cr.restore (); + } + + public override void draw_outline (Context cr) { } public override SvgBird.Object copy () {
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -180,7 +180,7 @@ } public Gee.ArrayList<SvgBird.Object> get_visible_objects () { - return layers.get_visible_objects ().objects; + return LayerUtils.get_visible_objects (layers); } public Gee.ArrayList<Path> get_visible_paths () { @@ -192,7 +192,7 @@ } public Gee.ArrayList<SvgBird.Object> get_objects_in_current_layer () { - return get_current_layer ().get_all_objects ().objects; + return get_current_layer ().objects.objects; } public Gee.ArrayList<Path> get_paths_in_current_layer () { @@ -252,6 +252,10 @@ public override void close () { undo_list.clear (); redo_list.clear (); + + foreach (Path path in get_all_paths ()) { + path.set_editable (false); + } } public void set_empty_ttf (bool e) { @@ -1331,7 +1335,7 @@ } public void open_path () { - foreach (Path p in get_visible_paths ()) { + foreach (Path p in get_all_paths ()) { p.set_editable (true); p.recalculate_linear_handles (); @@ -1576,17 +1580,74 @@ cr.stroke (); } - /** Draw filled paths. */ - public void draw_paths (Context cr, Color? c = null) { - layers.draw (cr); + public void draw_layers (Context cr) { + foreach (SvgBird.Object object in layers.objects) { + if (object is Layer) { + draw_layer (cr, (Layer) object); + } + } + + draw_bird_font_paths (cr); } - public void draw_path (Context cr) { - layers.draw (cr); + public void draw_layer (Context cr, Layer sublayers) { + foreach (SvgBird.Object object in sublayers.objects) { + if (object is EmbeddedSvg) { + EmbeddedSvg svg = (EmbeddedSvg) object; + svg.draw_embedded_svg (cr); + } + } } + + public void draw_bird_font_paths (Context cr) { + Tool selected_tool = MainWindow.get_toolbox ().get_current_tool (); + + bool draw_control_points = (selected_tool is PenTool) + || (selected_tool is PointTool) + || (selected_tool is TrackTool) + || (selected_tool is BezierTool); - private Color get_path_fill_color () { - return Theme.get_color ("Fill Color"); + bool has_path = false; + foreach (SvgBird.Object object in get_visible_objects ()) { + if (object is PathObject && object.stroke > 0) { + has_path = true; + PathObject object_path = (PathObject) object; + object_path.draw_path (cr); + } + } + + if (has_path) { + cr.set_fill_rule (FillRule.WINDING); + cr.set_source_rgba (0, 0, 0, 1); + cr.fill (); + } + + has_path = false; + foreach (SvgBird.Object object in get_visible_objects ()) { + if (object is PathObject && object.stroke == 0) { + has_path = true; + PathObject object_path = (PathObject) object; + object_path.draw_path (cr); + } + } + + if (has_path) { + cr.set_fill_rule (FillRule.EVEN_ODD); + cr.set_source_rgba (0, 0, 0, 1); + cr.fill (); + } + + if (draw_control_points) { + foreach (SvgBird.Object object in get_visible_objects ()) { + if (object is PathObject) { + PathObject object_path = (PathObject) object; + Glyph g = MainWindow.get_current_glyph (); + cr.set_line_width (CanvasSettings.stroke_width / g.view_zoom); + object_path.path.draw_outline (cr); + object_path.path.draw_control_points (cr); + } + } + } } public void draw_background_color (Context cr, double opacity) { @@ -1647,7 +1708,7 @@ cmp.save (); cmp.scale (view_zoom, view_zoom); cmp.translate (-view_offset_x, -view_offset_y); - draw_path (cmp); + draw_layers (cmp); cmp.restore (); cmp.save ();
--- a/libbirdfont/KerningDisplay.vala +++ b/libbirdfont/KerningDisplay.vala @@ -193,7 +193,7 @@ cr.save (); glyph.add_help_lines (); cr.translate (kern + x - glyph.get_lsb () - Glyph.xc (), glyph.get_baseline () + y - Glyph.yc ()); - glyph.draw_paths (cr); + glyph.draw_layers (cr); cr.restore (); w = glyph.get_width ();
--- a/libbirdfont/LayerUtils.vala +++ b/libbirdfont/LayerUtils.vala @@ -17,9 +17,31 @@ namespace BirdFont { public class LayerUtils { + + public static Gee.ArrayList<SvgBird.Object> get_visible_objects (Layer layer) { + ObjectGroup group = new ObjectGroup (); + add_visible_objects (layer, group); + return group.objects; + } + + public static void add_visible_objects (Layer layer, ObjectGroup objects) { + foreach (SvgBird.Object o in layer.objects) { + if (o is Layer) { + Layer sublayer = (Layer) o; + + if (sublayer.visible) { + add_visible_objects (sublayer, objects); + } + } else { + if (o.visible) { + objects.add (o); + } + } + } + } public static PathList get_all_paths (Layer layer) { - ObjectGroup objects = layer.get_all_objects (); + ObjectGroup objects = layer.objects; PathList paths = new PathList (); foreach (SvgBird.Object o in objects) { @@ -33,19 +55,22 @@ } public static PathList get_visible_paths (Layer layer) { - ObjectGroup objects = layer.get_visible_objects (); PathList paths = new PathList (); - - foreach (SvgBird.Object o in objects) { + add_visible_paths_to_group (layer, paths); + return paths; + } + + public static void add_visible_paths_to_group (Layer layer, PathList paths) { + foreach (SvgBird.Object o in layer.objects) { if (o is PathObject) { PathObject p = (PathObject) o; paths.add (p.get_path ()); + } else if (o is Layer) { + add_visible_paths_to_group ((Layer) o, paths); } } - - return paths; } - + public static void add_path (Layer layer, Path path) { PathObject p = new PathObject.for_path (path); layer.add_object (p);
--- a/libbirdfont/OverViewItem.vala +++ b/libbirdfont/OverViewItem.vala @@ -106,7 +106,6 @@ double glyph_width, glyph_height; Surface s; Context c; - Color color = Color.black (); g = ((!) glyphs).get_current (); @@ -137,7 +136,7 @@ gx = ((w / glyph_scale) - glyph_width) / 2 - g.get_left_side_bearing (); gy = (h / glyph_scale) - 25 / glyph_scale; c.translate (gx - Glyph.xc () - g.get_lsb (), g.get_baseline () + gy - Glyph.yc ()); - g.draw_paths (c, color); + g.draw_layers (c); c.restore ();
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 2013 2014 2015 Johan Mattsson + Copyright (C) 2012 - 2016 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 @@ -84,14 +84,8 @@ bool clockwise_direction = true; // Iterate over each pixel in a path - public delegate bool RasterIterator (double x, double y, double step); - + public delegate bool RasterIterator (double x, double y, double step); public delegate bool SegmentIterator (EditPoint start, EditPoint stop); - - /** The stroke of an outline when the path is not filled. */ - public static double stroke_width = 0; - public static bool show_all_line_handles = true; - public static bool fill_open_path { get; set; } public double rotation = 0; public double skew = 0; @@ -108,18 +102,6 @@ public Gradient? gradient = null; public Path () { - string width; - - if (unlikely (stroke_width < 1)) { - width = Preferences.get ("stroke_width"); - if (width != "") { - stroke_width = double.parse (width); - } - } - - if (stroke_width < 1) { - stroke_width = 1; - } } public bool is_filled () { @@ -201,7 +183,7 @@ i++; } - // close path + // closed path if (!is_open () && n != null) { if (highlight_last_segment) { cr.stroke (); @@ -226,19 +208,20 @@ } } - public void draw_edit_points (Context cr) { - if (is_editable ()) { - // control points for curvature - foreach (EditPoint e in points) { - if (show_all_line_handles || e.selected_point || e.selected_handle > 0) { - draw_edit_point_handles (e, cr); - } - } - - // control points - foreach (EditPoint e in points) { - draw_edit_point (e, cr); + public void draw_control_points (Context cr) { + // control points for curvature + foreach (EditPoint e in points) { + if (CanvasSettings.show_all_line_handles + || e.selected_point + || e.selected_handle > 0) { + + draw_edit_point_handles (e, cr); } + } + + // on curve control points + foreach (EditPoint e in points) { + draw_edit_point (e, cr); } } @@ -334,12 +317,9 @@ cr.translate (x, y); double inverted_zoom = Glyph.ivz (); cr.rotate (-angle); - cr.translate (-x, -y); - + cr.translate (-x, -y); cr.scale (inverted_zoom, inverted_zoom); - arrow_icon.draw_at_baseline (cr, x, y); - cr.restore (); } } @@ -373,7 +353,6 @@ } private static void draw_curve (EditPoint e, EditPoint en, Context cr, bool highlighted = false, double alpha = 1) { - Glyph g = MainWindow.get_current_glyph (); double xa, ya, xb, yb, xc, yc, xd, yd; PointType t = e.get_right_handle ().type; PointType u = en.get_left_handle ().type; @@ -385,8 +364,6 @@ } else { Theme.color (cr, "Highlighted Guide"); } - - cr.set_line_width (stroke_width / g.view_zoom); cr.line_to (xa, ya); // this point makes sense only if it is in the first or last position @@ -453,7 +430,7 @@ get_line_points (e, en, out ax, out ay, out bx, out by); Theme.color (cr, "Handle Color"); - cr.set_line_width (1.7 * (stroke_width / g.view_zoom)); + cr.set_line_width (1.7 * (CanvasSettings.stroke_width / g.view_zoom)); cr.line_to (ax, ay); cr.line_to (bx, by); @@ -583,7 +560,7 @@ public static void draw_control_point (Context cr, double x, double y, Color color, double size = 3.5) { Glyph g = MainWindow.get_current_glyph (); double ivz = 1 / g.view_zoom; - double width = size * Math.sqrt (stroke_width) * ivz; + double width = size * Math.sqrt (CanvasSettings.stroke_width) * ivz; double xc = g.allocation.width / 2.0; double yc = g.allocation.height / 2.0;
--- a/libbirdfont/PathObject.vala +++ b/libbirdfont/PathObject.vala @@ -1,5 +1,5 @@ /* - Copyright (C) 2015 Johan Mattsson + Copyright (C) 2015 2016 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 @@ -19,7 +19,18 @@ public class PathObject : SvgBird.Object { - Path path; + public Path path; + + public override double stroke { + get { + return path.stroke; + } + + set { + path.stroke = value; + } + } + // FIXME: flip y axis public override double xmin { @@ -69,8 +80,9 @@ default = Glyph.CANVAS_MIN; } - + public PathObject () { + base (); path = new Path (); update_region_boundaries (); } @@ -81,36 +93,33 @@ } public PathObject.for_path (Path path) { + base (); this.path = path; } public override bool is_over (double x, double y) { return path.is_over_coordinate (x, y); } - + public override void draw_outline (Context cr) { draw_path (cr); } - - public void draw_path (Context cr, Color? c = null) { + + private SvgBird.Color get_path_fill_color () { + Color c = Theme.get_color ("Fill Color"); + return new SvgBird.Color (c.r, c.g, c.b, c.a); + } + + public void draw_path (Context cr) { // FIXME: delete PathList path_stroke; - Color path_color; bool open; - cr.save (); - - if (c != null) { - path_color = (!) c; - } else if (color != null) { - path_color = new Color.create_copy ((!) color); - } else { - path_color = Color.black (); - } - if (path.stroke > 0) { + cr.set_fill_rule (FillRule.WINDING); path_stroke = path.get_stroke_fast (); - draw_path_list (path_stroke, cr, path_color); + draw_path_list (path_stroke, cr); } else { + cr.set_fill_rule (FillRule.EVEN_ODD); open = path.is_open (); if (open) { @@ -118,19 +127,17 @@ path.recalculate_linear_handles (); } - path.draw_path (cr, path_color); + path.draw_path (cr); if (open) { path.reopen (); } } - - cr.restore (); } - public static void draw_path_list (PathList pl, Context cr, Color? c = null) { + public static void draw_path_list (PathList pl, Context cr) { foreach (Path p in pl.paths) { - p.draw_path (cr, c); + p.draw_path (cr); } }
--- a/libbirdfont/PenTool.vala +++ b/libbirdfont/PenTool.vala @@ -1924,7 +1924,7 @@ Glyph g = MainWindow.get_current_glyph (); double distance_to_edit_point = g.view_zoom * get_distance_to_closest_edit_point (event_x, event_y); - if (!Path.show_all_line_handles) { + if (!CanvasSettings.show_all_line_handles) { foreach (PointSelection selected_corner in selected_points) { if (is_close_to_handle (selected_corner.point, event_x, event_y, distance_to_edit_point)) { return true; @@ -1994,7 +1994,7 @@ foreach (Path p in g.get_paths_in_current_layer ()) { foreach (EditPoint ep in p.points) { - if (ep.is_selected () || Path.show_all_line_handles) { + if (ep.is_selected () || CanvasSettings.show_all_line_handles) { left = ep.get_left_handle (); right = ep.get_right_handle ();
--- a/libbirdfont/SettingsTab.vala +++ b/libbirdfont/SettingsTab.vala @@ -43,13 +43,13 @@ stroke_width.new_value_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); - Path.stroke_width = stroke_width.get_value (); + CanvasSettings.stroke_width = stroke_width.get_value (); g.redraw_area (0, 0, g.allocation.width, g.allocation.height); Preferences.set ("stroke_width_for_open_paths", stroke_width.get_display_value ()); MainWindow.get_toolbox ().redraw ((int) stroke_width.x, (int) stroke_width.y, 70, 70); }); - Path.stroke_width = stroke_width.get_value (); + CanvasSettings.stroke_width = stroke_width.get_value (); // adjust precision string precision_value = Preferences.get ("precision"); @@ -81,7 +81,7 @@ Tool show_all_line_handles = new Tool ("show_all_line_handles"); show_all_line_handles.select_action.connect((self) => { - Path.show_all_line_handles = !Path.show_all_line_handles; + CanvasSettings.show_all_line_handles = !CanvasSettings.show_all_line_handles; Glyph g = MainWindow.get_current_glyph (); g.redraw_area (0, 0, g.allocation.width, g.allocation.height); }); @@ -89,11 +89,11 @@ Tool fill_open_path = new Tool ("fill_open_path"); fill_open_path.select_action.connect((self) => { - Path.fill_open_path = true; + CanvasSettings.fill_open_path = true; }); fill_open_path.deselect_action.connect((self) => { - Path.fill_open_path = false; + CanvasSettings.fill_open_path = false; }); tools.add (new SettingsItem (fill_open_path, t_("Fill open paths.")));
--- a/libbirdfont/TrackTool.vala +++ b/libbirdfont/TrackTool.vala @@ -232,12 +232,17 @@ } } } - - // FIXME: double check + void set_tie () { Glyph glyph = MainWindow.get_current_glyph (); var paths = glyph.get_visible_paths (); - Path p = paths.get (paths.size - 1); + Path p; + + if (paths.size == 0) { + return; + } + + p = paths.get (paths.size - 1); foreach (EditPoint ep in p.points) { if (ep.get_right_handle ().is_line () || ep.get_left_handle ().is_line ()) {
--- a/libsvgbird/Layer.vala +++ b/libsvgbird/Layer.vala @@ -42,9 +42,14 @@ ClipPath clipping = (!) object.clip_path; clipping.apply (cr); } - - object.draw_outline (cr); - object.paint (cr); + + if (object is Layer) { + Layer sublayer = (Layer) object; + sublayer.draw (cr); + } else { + object.draw_outline (cr); + object.paint (cr); + } cr.restore (); } @@ -52,7 +57,6 @@ } public override void draw_outline (Context cr) { - cr.save (); apply_transform (cr); foreach (Object object in objects) { @@ -67,14 +71,6 @@ public int index_of (Layer sublayer) { return objects.index_of (sublayer); - } - - public ObjectGroup get_all_objects () { - return objects; - } - - public ObjectGroup get_visible_objects () { - return objects; // FIXME: remove this } public void add_layer (Layer layer) { @@ -111,39 +107,7 @@ Object.copy_attributes (this, layer); return layer; } - - public void get_boundaries (out double x, out double y, out double w, out double h) { - double px, py, px2, py2; - - px = double.MAX; - py = double.MAX; - px2 = -double.MAX; - py2 = -double.MAX; - - foreach (Object p in get_all_objects ().objects) { - if (px > p.xmin) { - px = p.xmin; - } - - if (py > p.ymin) { - py = p.ymin; - } - - if (px2 < p.xmax) { - px2 = p.xmax; - } - - if (py2 < p.ymax) { - py2 = p.ymax; - } - } - - w = px2 - px; - h = py2 - py; - x = px; - y = py2; - } - + public Gee.ArrayList<Layer> get_sublayers () { Gee.ArrayList<Layer> sublayers = new Gee.ArrayList<Layer> ();
--- a/libsvgbird/SvgStyle.vala +++ b/libsvgbird/SvgStyle.vala @@ -31,8 +31,17 @@ private static Mutex inheritance_mutex = new Mutex (); public SvgStyle () { + } + + public SvgStyle.for_properties (Defs? defs, string style) { + parse_key_value_pairs (style); + set_style_properties (defs, this); } + public void set_style (string property, string style) { + this.style.set (property, style); + } + public bool property_equals (string property, string value) { string? p = get_css_property (property); @@ -87,11 +96,6 @@ string inherit_property = inherit ? "yes" : "no"; inheritance.set (property, inherit_property); inheritance_mutex.unlock (); - } - - public SvgStyle.for_properties (Defs? defs, string style) { - parse_key_value_pairs (style); - set_style_properties (defs, this); } public SvgStyle copy () {