Commit 9597194
Zoom with trackpad and other fixes for Mac
Changed files (6)
modifiedinstall.pymodifiedlibbirdfont/BirdFont.valamodifiedlibbirdfont/FontDisplay.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/Preview.valamodifiedlibbirdfont/TabContent.vala
Diff
@@ -123,7 +123,9 @@ if not options.nocli: install ('build/bin/birdfont-import', '/bin', 755) #library-if not options.libdir:+if sys.platform == 'darwin':+ libdir = '/lib'+elif not options.libdir: if platform.dist()[0] == 'Ubuntu' or platform.dist()[0] == 'Debian': process = subprocess.Popen(['dpkg-architecture', '-qDEB_HOST_MULTIARCH'], stdout=subprocess.PIPE)@@ -1,19 +1,19 @@ /* Copyright (C) 2012 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 - published by the Free Software Foundation; either version 3 of the + 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 + 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 BirdFont; -public const string GETTEXT_PACKAGE = "birdfont"; +public const string GETTEXT_PACKAGE = "birdfont"; namespace BirdFont { @@ -39,26 +39,26 @@ public static string wine_to_unix_path (string exec_path) { p = exec_path; p = p.replace ("\\", "/");- + drive_c = exec_path.index_of ("C:") == 0; drive_z = exec_path.index_of ("Z:") == 0;- + i = p.index_of (":");- + if (i != -1) { p = p.substring (i + 2); } if (drive_c) { q = @"/home/$(Environment.get_user_name ())/.wine/drive_c/" + p;- + if (File.new_for_path (q).query_exists ()) { return q; } else { return p; } }- + if (drive_z) { return ("/" + p).dup (); }@@ -90,28 +90,27 @@ public class BirdFont { public static Font current_font; public static GlyphCollection current_glyph_collection;- + public static Drawing? drawing = null;- + public static string? settings_subdirectory = null;- + public BirdFont () { set_defaul_drawing_callbacks (); }- + void set_defaul_drawing_callbacks () { if (drawing == null) { drawing = new Drawing (); }- } - + }+ /** * @param arg command line arguments * @param program path * @param setting subdirectory */ public void init (string[] arg, string? program_path, string? settings_subdir) {- int err_arg; int i; File font_file; string exec_path;@@ -120,7 +119,7 @@ public class BirdFont { string theme_version; CharDatabaseParser parser; CodePageBits codepage_bits;- + set_settings_subdir (settings_subdir); args = new Argument.command_line (arg);@@ -128,17 +127,17 @@ public class BirdFont { #if ANDROID BirdFont.logging = true;- + __android_log_print (ANDROID_LOG_WARN, "BirdFont", @"libbirdfont version $VERSION"); LogLevelFlags log_levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING; Log.set_handler (null, log_levels, android_warning);- + android = true; #else stdout.printf ("birdfont version %s\n", VERSION);- + android = args.has_argument ("--android");- + if (!BirdFont.logging) { BirdFont.logging = args.has_argument ("--log"); }@@ -147,7 +146,7 @@ public class BirdFont { if (BirdFont.logging) { init_logfile (); }- + if (!args.has_argument ("--no-translation")) { init_gettext (); }@@ -157,24 +156,25 @@ public class BirdFont { Process.exit (0); } - err_arg = args.validate ();+#if !MAC+ int err_arg = args.validate (); if (err_arg != 0) { stdout.printf (@"Unknown parameter $(arg [err_arg])\n\n"); args.print_help (); Process.exit (0); }-+#endif Preferences.load ();- + // always load default theme when names in theme does change default_theme_version = 1; theme = Preferences.get ("theme"); theme_version = Preferences.get ("theme_version"); Theme.set_default_colors ();- + if (theme_version == "" || int.parse (theme_version) < default_theme_version) {- + Theme.load_theme ("dark.theme"); Preferences.set ("theme", "dark.theme"); } else {@@ -186,16 +186,16 @@ public class BirdFont { } Preferences.set ("theme_version", @"$default_theme_version");- + current_font = new Font (); current_font.set_name (""); current_font.initialised = false; current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");- + experimental = args.has_argument ("--test"); show_coordinates = args.has_argument ("--show-coordinates") || experimental; fatal_wanings = args.has_argument ("--fatal-warning");- win32 = (arg[0].index_of (".exe") > -1) + win32 = (arg[0].index_of (".exe") > -1) || arg[0] == "wine" || args.has_argument ("--windows"); @@ -204,18 +204,18 @@ public class BirdFont { #else mac = args.has_argument ("--mac"); #endif- + if (program_path == null) { exec_path = ""; if (win32) { // wine hack to get "." folder in win32 environment i = arg[0].last_index_of ("\\");- - if (i != -1) { ++ if (i != -1) { exec_path = arg[0]; exec_path = exec_path.substring (0, i);- exec_path = wine_to_unix_path (exec_path); + exec_path = wine_to_unix_path (exec_path); } } else { exec_path = "./";@@ -223,10 +223,10 @@ public class BirdFont { } else { exec_path = (!) program_path; }- + if (args.get_file () != "") { font_file = File.new_for_path (args.get_file ());- + if (!font_file.query_exists ()) { stderr.printf (@"The file \"$(args.get_file ())\" was not found.\n"); Process.exit (-1);@@ -237,7 +237,7 @@ public class BirdFont { LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING; Log.set_handler (null, levels, fatal_warning); }- + Preferences.set_last_file (get_current_font ().get_path ()); DefaultCharacterSet.create_default_character_sets ();@@ -248,7 +248,7 @@ public class BirdFont { if (TestBirdFont.get_singleton ().test_cases_to_run != "All") { TestBirdFont.run_tests (); }- + if (has_argument ("--parse-ucd")) { parser = new CharDatabaseParser (); parser.regenerate_database ();@@ -262,20 +262,20 @@ public class BirdFont { public static bool has_logging () { bool log;- + lock (BirdFont.logging) { log = BirdFont.logging; }- + return log; }- + public static Argument get_arguments () { return args; } public static void set_bundle_path (string path) {- bundle_path = path; + bundle_path = path; } public static void init_gettext () {@@ -287,25 +287,25 @@ public class BirdFont { Intl.bindtextdomain (GETTEXT_PACKAGE, locale_directory); #endif }- + public static void load_font_from_command_line () { string file = args.get_file (); if (file != "") { RecentFiles.load_font (file);- } + } }- + public static Font get_current_font () { return current_font; } - internal static void fatal_warning (string? log_domain, LogLevelFlags log_levels, string message) { + internal static void fatal_warning (string? log_domain, LogLevelFlags log_levels, string message) { bool fatal = true;- + if (log_domain != null) { stderr.printf ("%s: \n", (!) log_domain); }- + stderr.printf ("\n%s\n\n", message); assert (!fatal); }@@ -315,38 +315,38 @@ public class BirdFont { __android_log_print (ANDROID_LOG_WARN, "BirdFont", message); } #endif- + public static Font new_font () { current_font = new Font ();- + if (!is_null (MainWindow.tools)) { MainWindow.get_drawing_tools ().remove_all_grid_buttons (); DrawingTools.add_new_grid (1, false); DrawingTools.add_new_grid (2, false); DrawingTools.add_new_grid (4, false); }- + if (!is_null (Toolbox.background_tools)) { Toolbox.background_tools.remove_images (); }- + KerningTools.update_kerning_classes ();- + return current_font; } public static void set_settings_directory (string directory) { settings_subdirectory = directory; }- + public static File get_preview_directory () { File settings = get_settings_directory (); File backup = get_child(settings, "preview");- + if (!backup.query_exists ()) { DirUtils.create ((!) backup.get_path (), 0755); }- + return backup; } @@ -367,15 +367,15 @@ public class BirdFont { printd ("Create settings directory."); DirUtils.create ((!) home.get_path (),0755); }-#else - home_path = (settings_directory != null) +#else+ home_path = (settings_directory != null) ? (!) settings_directory : Environment.get_user_config_dir ();- + if (is_null (home_path)) { warning ("No home directory set."); home_path = "."; }- + home = File.new_for_path (home_path); #endif @@ -384,22 +384,22 @@ public class BirdFont { } else { settings = get_child(home, "birdfont"); }- + if (!settings.query_exists ()) { DirUtils.create ((!) settings.get_path (), 0755); }- + return settings; } internal static File get_backup_directory () { File settings = get_settings_directory (); File backup = get_child (settings, "backup");- + if (!backup.query_exists ()) { DirUtils.create ((!) backup.get_path (), 0755); }- + return backup; } @@ -407,14 +407,14 @@ public class BirdFont { if (is_null (args)) { return false; }- + return args.has_argument (param); }- + internal static string? get_argument (string param) { return args.get_argument (param); }- + public static void debug_message (string s) { if (unlikely (has_logging ())) { try {@@ -424,7 +424,7 @@ public class BirdFont { } else { warning ("No logstream."); }- + stderr.printf (s); } catch (GLib.Error e) { warning (e.message);@@ -438,26 +438,26 @@ void init_logfile () { File settings; string s; File log;- + try { t = new DateTime.now_local (); settings = BirdFont.get_settings_directory (); s = t.to_string ().replace (":", "_"); log = get_child (settings, @"birdfont_$s.log");- + BirdFont.logstream = new DataOutputStream (log.create (FileCreateFlags.REPLACE_DESTINATION)); ((!)BirdFont.logstream).put_string ((!) log.get_path ()); ((!)BirdFont.logstream).put_string ("\n");- - warning ("Logging to " + (!) log.get_path ()); ++ warning ("Logging to " + (!) log.get_path ()); } catch (GLib.Error e) { warning (e.message); warning ((!) log.get_path ()); } LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING | LogLevelFlags.LEVEL_DEBUG;- Log.set_handler (null, levels, log_warning); - + Log.set_handler (null, levels, log_warning);+ BirdFont.logging = true; printd (@"Program version: $(VERSION)\n");@@ -467,7 +467,7 @@ internal static void log_warning (string? log_domain, LogLevelFlags log_levels, if (log_domain != null) { printd ((!) log_domain); }- + printd ("\n"); printd (message); printd ("\n");@@ -487,7 +487,7 @@ public static void printd (string s) { public string t_ (string t) { #if ANDROID return t;-#else +#else return _(t); #endif }@@ -505,7 +505,7 @@ public static void warn_if_test (string message) { } } -/** Obtain a handle to a file in a folder. */ +/** Obtain a handle to a file in a folder. */ public static File get_child (File folder, string file_name) { string f; string s;@@ -516,11 +516,11 @@ public static File get_child (File folder, string file_name) { f = (!) folder.get_path (); #if LINUX- s = "/"; + s = "/"; #else- s = (BirdFont.win32) ? "\\" : "/"; + s = (BirdFont.win32) ? "\\" : "/"; #endif- + n = file_name; if (unlikely (BirdFont.win32 && file_name.index_of ("\\") != -1)) { warning (@"File name contains path separator: $file_name, Directory: $f");@@ -530,9 +530,9 @@ public static File get_child (File folder, string file_name) { if (!f.has_suffix (s)) { f += s; }- + printd (@"File in Directory: $f Name: $n\n");- + return File.new_for_path (f + n); } @@ -1,14 +1,14 @@ /* Copyright (C) 2012 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 + 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 + 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. */ @@ -18,7 +18,7 @@ using Math; namespace BirdFont { public abstract class FontDisplay : GLib.Object {- + private static double last_tap_y = -1; private static double last_tap_time = 0; @@ -26,7 +26,7 @@ public abstract class FontDisplay : GLib.Object { /** Queue redraw area */ public signal void redraw_area (double x, double y, double w, double h);- + public virtual string get_name () { warning ("No name."); return "";@@ -36,43 +36,46 @@ public abstract class FontDisplay : GLib.Object { warning ("No label."); return ""; }- + public virtual void close () { }- + public virtual bool has_scrollbar () { return false; }- + public virtual void update_scrollbar () { }- + public virtual void scroll_to (double percent) { }- + public virtual void draw (WidgetAllocation allocation, Context cr) { }- + public virtual void selected_canvas () { }- + public virtual void key_press (uint keyval) { }- + public virtual void key_release (uint keyval) { }- + public virtual void motion_notify (double x, double y) { }- + public virtual void button_release (int button, double x, double y) { }- + public virtual void button_press (uint button, double x, double y) { } public virtual void double_click (uint button, double ex, double ey) {- } + }++ public virtual void magnify (double magnification) {+ } public virtual void tap_down (int finger, int x, int y) { if (finger == 0) {@@ -81,27 +84,27 @@ public abstract class FontDisplay : GLib.Object { } else { button_press (1, x, y); }- - last_tap_time = GLib.get_real_time (); ++ last_tap_time = GLib.get_real_time (); }- + last_tap_y = -1; }- + public virtual void tap_up (int finger, int x, int y) { if (finger == 0) { button_release (1, x, y); }- + last_tap_y = -1; }- + public virtual void tap_move (int finger, int x, int y) { double d; if (finger == 0) { motion_notify (x, y);- - d = y - last_tap_y; ++ d = y - last_tap_y; if (last_tap_y > -1 && fabs (d) > 15) { // FIXME: pixels, other units are better if (d > 0) { scroll_wheel (x, y, 15, 0);@@ -109,50 +112,50 @@ public abstract class FontDisplay : GLib.Object { scroll_wheel (x, y, 15, 0); } }- + last_tap_y = y; } } public virtual void zoom_in () { }- + public virtual void zoom_out () { }- + public virtual void zoom_max () { }- + public virtual void zoom_min () { }- + public virtual void move_view (double x, double y) { }- + public virtual void reset_zoom () { }- + public virtual void store_current_view () { }- + public virtual void restore_last_view () { } public virtual void next_view () { }- + public virtual void scroll_wheel (double x, double y, double pixeldelta_x, double pixeldelta_y) { }- + public virtual void undo () { } public virtual void redo () { }- + public static File find_file (string? dir, string name) {- return SearchPaths.find_file (dir, name); + return SearchPaths.find_file (dir, name); } /** returns false if bindings to a single key works in the display. */@@ -1,14 +1,14 @@ /* Copyright (C) 2012 2013 2014 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 + 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 + 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. */ @@ -19,20 +19,20 @@ using Gee; namespace BirdFont { public class Glyph : FontDisplay {- + // Background image BackgroundImage? background_image = null; bool background_image_visible = true;- + // Glyph zoom level public double view_zoom = 0.1;- + public double view_offset_x = 0; public double view_offset_y = 0; Gee.ArrayList<ZoomView> zoom_list = new Gee.ArrayList<ZoomView> (); int zoom_list_index = 0;- - // The point where edit event begun ++ // The point where edit event begun double pointer_begin_x = 0; double pointer_begin_y = 0; @@ -42,21 +42,21 @@ public class Glyph : FontDisplay { int last_tap1_y = 0; int last_tap1_x = 0; double zoom_distance = 0;- bool change_view; + bool change_view; bool ignore_input = false;- + // Current pointer position public double motion_x = 0; public double motion_y = 0;- + // Zoom area public double zoom_x1 = 0; public double zoom_y1 = 0; public double zoom_x2 = 0; public double zoom_y2 = 0; public bool zoom_area_is_visible = false;- + bool view_is_moving = false; public double move_offset_x = 0; public double move_offset_y = 0;@@ -64,34 +64,34 @@ public class Glyph : FontDisplay { public WidgetAllocation allocation = new WidgetAllocation (); - public unichar unichar_code = 0; // FIXME: name and unichar should be moved to to glyph collection + public unichar unichar_code = 0; // FIXME: name and unichar should be moved to to glyph collection public string name; public double left_limit { get { return _left_limit; }- + set { ttf_data = null; _left_limit = value; } }- + public double right_limit { get { return _right_limit; }- + set { ttf_data = null; _right_limit = value; } }- + private double _right_limit = 0; private double _left_limit = 0;- + // x-height, lsb, etc. public Gee.ArrayList<Line> vertical_help_lines = new Gee.ArrayList<Line> (); public Gee.ArrayList<Line> horizontal_help_lines = new Gee.ArrayList<Line> ();@@ -99,26 +99,26 @@ public class Glyph : FontDisplay { bool xheight_lines_visible = false; bool margin_boundaries_visible = false; string new_guide_name = "";- + Gee.ArrayList<Glyph> undo_list = new Gee.ArrayList<Glyph> (); Gee.ArrayList<Glyph> redo_list = new Gee.ArrayList<Glyph> (); string glyph_sequence = ""; bool open = true;- + public static Glyph? background_glyph = null;- + bool empty = false;- + /** Id in the version list. */ public int version_id = 0;- + /** Cache quadratic form on export. */ GlyfData? ttf_data = null;- + Line left_line; Line right_line;- + /** Cache for Cairo rendering */ HashMap<string, Surface> glyph_cache = new HashMap<string, Surface> (); @@ -127,7 +127,7 @@ public class Glyph : FontDisplay { public static bool show_orientation_arrow = false; public static double orientation_arrow_opacity = 1;- + public Layer layers = new Layer (); public int current_layer = 0; public Gee.ArrayList<Path> active_paths = new Gee.ArrayList<Path> ();@@ -143,7 +143,7 @@ public class Glyph : FontDisplay { this.unichar_code = unichar_code; add_help_lines ();- + left_limit = -28; right_limit = 28; }@@ -156,7 +156,7 @@ public class Glyph : FontDisplay { 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 ()); return layers.subgroups.get (current_layer);@@ -171,10 +171,10 @@ public class Glyph : FontDisplay { } i++; }- + warning ("Layer is not added to glyph."); }- + public Gee.ArrayList<Path> get_visible_paths () { return layers.get_visible_paths ().paths; }@@ -182,36 +182,36 @@ public class Glyph : FontDisplay { public PathList get_visible_path_list () { return layers.get_visible_paths (); }- + public Gee.ArrayList<Path> get_paths_in_current_layer () { return get_current_layer ().get_all_paths ().paths; }- + public Gee.ArrayList<Path> get_all_paths () { return layers.get_all_paths ().paths; }- + public void add_new_layer () { layers.add_layer (new Layer ()); current_layer = layers.subgroups.size - 1; }- + public GlyfData get_ttf_data () { if (ttf_data == null) {- + ttf_data = new GlyfData (this); }- + return (!) ttf_data; }- + public PathList get_quadratic_paths () { PointConverter pc; PathList pl; PathList stroke; pl = new PathList ();- + foreach (Path p in get_visible_paths ()) { if (p.stroke > 0) { stroke = p.get_stroke ();@@ -232,7 +232,7 @@ public class Glyph : FontDisplay { undo_list.clear (); redo_list.clear (); }- + public void set_empty_ttf (bool e) { empty = e; }@@ -241,24 +241,24 @@ public class Glyph : FontDisplay { return empty; } - public void clear_active_paths () { + public void clear_active_paths () { selected_groups.clear (); active_paths.clear (); }- + public void add_active_path (Layer? group, Path? p) { Path path; Layer g;- + if (p != null) { path = (!) p;- + if (Toolbox.get_move_tool ().is_selected ()) { if (path.stroke > 0) { Toolbox.set_object_stroke (path.stroke); } }- + if (!active_paths.contains (path)) { active_paths.add (path); }@@ -272,21 +272,21 @@ public class Glyph : FontDisplay { } } }- + public void delete_background () { 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) { var paths = get_all_paths ();- + if (paths.size == 0) { x1 = 0; y1 = 0;@@ -299,7 +299,7 @@ public class Glyph : FontDisplay { x2 = CANVAS_MIN; y1 = CANVAS_MAX; y2 = CANVAS_MIN;- + foreach (Path p in paths) { p.update_region_boundaries (); @@ -307,36 +307,36 @@ public class Glyph : FontDisplay { if (p.xmin < x1) { x1 = p.xmin; }- + if (p.xmax > x2) { x2 = p.xmax; }- + if (p.ymin < y1) { y1 = p.ymin; }- + if (p.ymax > y2) { y2 = p.ymax; } } }- + return x1 != double.MAX; }- + public void selection_boundaries (out double x, out double y, out double w, out double h) { double px, py, px2, py2;- + px = 10000; py = 10000; px2 = -10000; py2 = -10000;- + foreach (Path p in active_paths) { if (p.xmin < px) { px = p.xmin;- } + } if (p.ymin < py) { py = p.ymin;@@ -345,12 +345,12 @@ public class Glyph : FontDisplay { if (p.xmax > px2) { px2 = p.xmax; }- + if (p.ymax > py2) { py2 = p.ymax; } }- + if (px2 == -10000 || px == 10000) { warning (@"No box for selected paths. ($(active_paths.size))"); px = 0;@@ -360,15 +360,15 @@ public class Glyph : FontDisplay { } x = px;- y = py2; + y = py2; w = px2 - px; h = py2 - py; }- + /** @return centrum pixel for x coordinates. */ public static double xc () { double c = MainWindow.get_current_glyph ().allocation.width / 2.0;- return c; + return c; } /** @return centrum pixel for y coordinates. */@@ -387,7 +387,7 @@ public class Glyph : FontDisplay { a = Glyph.path_coordinate_x (0); b = Glyph.path_coordinate_y (0);- + this.allocation = alloc; c = Glyph.path_coordinate_x (0);@@ -399,24 +399,24 @@ public class Glyph : FontDisplay { public void set_background_image (BackgroundImage? b) { BackgroundImage bg;- + if (b == null) { background_image = null;- } else { + } else { bg = (!) b; background_image = bg; }- + BirdFont.get_current_font ().touch (); }- + public BackgroundImage? get_background_image () { return background_image; }- - public override void scroll_wheel (double x, double y, ++ public override void scroll_wheel (double x, double y, double pixeldelta_x, double pixeldelta_y) {- + if (KeyBindings.has_alt () || KeyBindings.has_ctrl ()) { if (pixeldelta_y > 0) { zoom_in_at_point (x, y, pixeldelta_y);@@ -433,23 +433,23 @@ public class Glyph : FontDisplay { view_offset_y -= pixeldelta_x / view_zoom; } }- + redraw_area (0, 0, allocation.width, allocation.height); }- + public virtual void add_path (Path p) { if (layers.subgroups.size == 0) { layers.add_layer (new Layer ()); }- + get_current_layer ().add_path (p); }- + public override void selected_canvas () { TimeoutSource input_delay;- + ttf_data = null; // recreate quatradic path on export- + ignore_input = true; // make sure that tripple clicks in overview are ignored input_delay = new TimeoutSource (250);@@ -458,58 +458,58 @@ public class Glyph : FontDisplay { return false; }); input_delay.attach (null);- + add_help_lines (); KeyBindings.set_require_modifier (false); glyph_sequence = Preferences.get ("glyph_sequence");- + GridTool.update_lines ();- + if (!is_null (MainWindow.native_window)) { MainWindow.native_window.set_scrollbar_size (0); }- + update_zoom_bar (); DrawingTools.update_layers (); MainWindow.get_toolbox ().update_expanders (); }- + void update_zoom_bar () { if (!is_null (Toolbox.drawing_tools) && !is_null (Toolbox.drawing_tools.zoom_bar)) { Toolbox.drawing_tools.zoom_bar.set_zoom ((view_zoom - 1) / 20); } }- + public void remove_lines () { vertical_help_lines.clear ();- horizontal_help_lines.clear (); + horizontal_help_lines.clear (); }- + public void add_help_lines () { remove_lines ();- + return_if_fail (!is_null (BirdFont.get_current_font ()));- + double bgt = BirdFont.get_current_font ().top_limit; Line top_margin_line = new Line ("top margin", bgt, false); top_margin_line.set_color_theme ("Guide 2"); top_margin_line.position_updated.connect ((pos) => { BirdFont.get_current_font ().top_limit = pos; });- + double thp = BirdFont.get_current_font ().top_position; Line top_line = new Line ("top", thp, false); top_line.position_updated.connect ((pos) => { Font f = BirdFont.get_current_font (); f.top_position = pos; });- + double xhp = BirdFont.get_current_font ().xheight_position; Line xheight_line = new Line ("x-height", xhp, false); xheight_line.set_color_theme ("Guide 3"); xheight_line.dashed = true;- xheight_line.position_updated.connect ((pos) => { + xheight_line.position_updated.connect ((pos) => { Font f = BirdFont.get_current_font (); f.xheight_position = pos; });@@ -520,7 +520,7 @@ public class Glyph : FontDisplay { Font f = BirdFont.get_current_font (); f.base_line = pos; });- + double bp = BirdFont.get_current_font ().bottom_position; Line bottom_line = new Line ("bottom", bp, false); bottom_line.position_updated.connect ((pos) => {@@ -533,7 +533,7 @@ public class Glyph : FontDisplay { bottom_margin_line.position_updated.connect ((pos) => { BirdFont.get_current_font ().bottom_limit = pos; });- + left_line = new Line ("left", left_limit, true); left_line.lsb = true; left_line.position_updated.connect ((pos) => {@@ -542,7 +542,7 @@ public class Glyph : FontDisplay { left_line.set_metrics (get_left_side_bearing ()); }); left_line.set_metrics (get_left_side_bearing ());- + right_line = new Line ("right", right_limit, true); right_line.rsb = true; right_line.position_updated.connect ((pos) => {@@ -551,10 +551,10 @@ public class Glyph : FontDisplay { right_line.set_metrics (get_right_side_bearing ()); }); right_line.set_metrics (get_right_side_bearing ());- - // lists of lines are sorted and lines are added only if ++ // lists of lines are sorted and lines are added only if // they are relevant for a particular glyph.- + // left to right add_line (left_line); add_line (right_line);@@ -564,29 +564,29 @@ public class Glyph : FontDisplay { // top to bottom add_line (top_margin_line); top_margin_line.set_visible (margin_boundaries_visible);- + add_line (top_line); top_line.set_visible (glyph_has_top || xheight_lines_visible);- + add_line (xheight_line); xheight_line.set_visible (!glyph_has_top || xheight_lines_visible);- + add_line (base_line);- + add_line (bottom_line); bottom_line.set_visible (CharDatabase.has_descender (unichar_code) || xheight_lines_visible);- + add_line (bottom_margin_line); bottom_margin_line.set_visible (margin_boundaries_visible);- + foreach (Line guide in BirdFont.get_current_font ().custom_guides) { add_line (guide); } }- + public double get_left_side_bearing () { double x1, y1, x2, y2;- + if (get_boundaries (out x1, out y1, out x2, out y2)) { return x1 - left_limit; } else {@@ -596,21 +596,21 @@ public class Glyph : FontDisplay { public double get_right_side_bearing () { double x1, y1, x2, y2;- + if (get_boundaries (out x1, out y1, out x2, out y2)) { return right_limit - x2; } else { return right_limit - left_limit; } }- + public bool get_boundaries (out double x1, out double y1, out double x2, out double y2) {- + double max_x, min_x, max_y, min_y; PathList pl; var paths = get_all_paths ();- + if (paths.size == 0) { x1 = 0; y1 = 0;@@ -618,18 +618,18 @@ public class Glyph : FontDisplay { y2 = 0; return false; }- + max_x = CANVAS_MIN; min_x = CANVAS_MAX; max_y = CANVAS_MIN; min_y = CANVAS_MAX;- + // FIXME: optimize foreach (Path p in paths) {- + if (p.stroke > 0) { pl = p.get_stroke_fast ();- + foreach (Path part in pl.paths) { boundaries_for_path (part, ref min_x, ref max_x, ref min_y, ref max_y); }@@ -642,20 +642,20 @@ public class Glyph : FontDisplay { y1 = max_y; x2 = max_x; y2 = min_y;- + return max_x != CANVAS_MIN; }- + void boundaries_for_path (Path p, ref double min_x, ref double max_x, ref double min_y, ref double max_y) {- + double max_x2, max_y2, min_x2, min_y2; max_x2 = max_x; min_x2 = min_x; max_y2 = max_y; min_y2 = min_y;- + p.all_of_path ((x, y, t) => { if (x > max_x2) { max_x2 = x;@@ -668,20 +668,20 @@ public class Glyph : FontDisplay { if (x < min_x2) { min_x2 = x; }- + if (y < min_y2) { min_y2 = y; }- + return true;- }); - + });+ max_x = max_x2; min_x = min_x2; max_y = max_y2; min_y = min_y2; }- + bool has_top_line () { return !unichar_code.islower () || CharDatabase.has_ascender (unichar_code); }@@ -689,7 +689,7 @@ public class Glyph : FontDisplay { public bool get_show_help_lines () { return show_help_lines; }- + /** Show both x-height and top lines. */ public bool get_xheight_lines_visible () { return xheight_lines_visible;@@ -700,16 +700,16 @@ public class Glyph : FontDisplay { xheight_lines_visible = x; add_help_lines (); }- + public void set_margin_lines_visible (bool m) { margin_boundaries_visible = m; add_help_lines (); }- + public bool get_margin_lines_visible () { return margin_boundaries_visible; }- + public void remove_empty_paths () { foreach (Path p in get_all_paths ()) { if (p.points.size < 2) {@@ -719,20 +719,20 @@ public class Glyph : FontDisplay { } } }- + public void delete_path (Path p) { layers.remove_path(p); }- + public string get_svg_data () { return Svg.to_svg_glyph (this); }- + public int get_height () { Font f = BirdFont.get_current_font ();- return (int) Math.fabs (f.top_limit - f.bottom_limit); + return (int) Math.fabs (f.top_limit - f.bottom_limit); }- + public double get_width () { return Math.fabs (right_limit - left_limit); }@@ -743,23 +743,23 @@ public class Glyph : FontDisplay { public string get_unichar_string () { string? s = (!)get_unichar ().to_string ();- + if (unlikely (s == null)) { warning ("Invalid character."); return "".dup (); }- + return (!) s; }- + public void redraw_help_lines () { redraw_area (0, 0, allocation.width, allocation.height); }- + public void set_show_help_lines (bool hl) { show_help_lines = hl; }- + private void add_line (Line line) { if (line.is_vertical ()) { vertical_help_lines.add (line);@@ -768,12 +768,12 @@ public class Glyph : FontDisplay { } sort_help_lines ();- + line.queue_draw_area.connect ((x, y, w, h) => { this.redraw_area (x, y, w, h); }); }- + public void sort_help_lines () { vertical_help_lines.sort ((a, b) => { Line first, next;@@ -781,7 +781,7 @@ public class Glyph : FontDisplay { next = (Line) b; return (int) (first.get_pos () - next.get_pos ()); });- + horizontal_help_lines.sort ((a, b) => { Line first, next; first = (Line) a;@@ -789,7 +789,7 @@ public class Glyph : FontDisplay { return (int) (first.get_pos () - next.get_pos ()); }); }- + public override string get_name () { return name; }@@ -797,10 +797,10 @@ public class Glyph : FontDisplay { public override string get_label () { return name; }- + private void help_line_event (int x, int y) { bool m = false;- + foreach (Line line in vertical_help_lines) { if (!m && line.event_move_to (x, y, allocation)) { m = true;@@ -814,7 +814,7 @@ public class Glyph : FontDisplay { } } - public override void key_release (uint keyval) { + public override void key_release (uint keyval) { Tool t; t = MainWindow.get_toolbox ().get_current_tool (); t.key_release_action (t, keyval);@@ -824,10 +824,10 @@ public class Glyph : FontDisplay { } } - public override void key_press (uint keyval) { + public override void key_press (uint keyval) { Tool t = MainWindow.get_toolbox ().get_current_tool (); t.key_press_action (t, keyval);- + if (keyval == (uint)' ') { move_canvas = true; }@@ -843,7 +843,7 @@ public class Glyph : FontDisplay { } /** Delete edit point from path.- * @return false if no points was deleted + * @return false if no points was deleted */ public bool process_deleted () { Gee.ArrayList<Path> deleted_paths = new Gee.ArrayList<Path> ();@@ -856,14 +856,14 @@ public class Glyph : FontDisplay { deleted_paths.add (p); } }- + foreach (Path p in deleted_paths) { delete_path (p); }- + return false; }- + private bool process_deleted_points_in_path (Path p) { PathList remaining_points; remaining_points = p.process_deleted_points ();@@ -871,37 +871,37 @@ public class Glyph : FontDisplay { add_path (path); path.reopen (); path.create_list ();- + add_active_path (null, path); }- + if (remaining_points.paths.size > 0) { delete_path (p); return true; }- + return false; }- + public override void motion_notify (double x, double y) { Tool t = MainWindow.get_toolbox ().get_current_tool ();- + if (view_is_moving) { move_view_offset (x, y); return; }- + help_line_event ((int) x, (int) y); t.move_action (t, (int) x, (int) y); motion_x = x * ivz () - xc () + view_offset_x; motion_y = yc () - y * ivz () - view_offset_y; }- + public override void button_release (int button, double ex, double ey) { bool line_moving = false; view_is_moving = false;- + foreach (Line line in get_all_help_lines ()) { if (!line.set_move (false)) { line_moving = true;@@ -912,13 +912,13 @@ public class Glyph : FontDisplay { Tool t = MainWindow.get_toolbox ().get_current_tool (); t.release_action (t, (int) button, (int) ex, (int) ey); }- + update_view (); } private Gee.ArrayList<Line> get_all_help_lines () { Gee.ArrayList<Line> all_lines = new Gee.ArrayList<Line> ();- + foreach (Line l in vertical_help_lines) { all_lines.add (l); }@@ -926,35 +926,35 @@ public class Glyph : FontDisplay { foreach (Line l in horizontal_help_lines) { all_lines.add (l); }- + if (GridTool.is_visible ()) { foreach (Line l in GridTool.get_vertical_lines ()) { all_lines.add (l); }- + foreach (Line l in GridTool.get_horizontal_lines ()) { all_lines.add (l); } }- + return all_lines; }- + public void update_view () { GlyphCanvas.redraw (); }- - public override void double_click (uint button, double ex, double ey) { ++ public override void double_click (uint button, double ex, double ey) { Tool t = MainWindow.get_toolbox ().get_current_tool (); t.double_click_action (t, (int) button, (int) ex, (int) ey); }- - public override void button_press (uint button, double ex, double ey) { ++ public override void button_press (uint button, double ex, double ey) { bool moving_lines = false;- + pointer_begin_x = ex; pointer_begin_y = ey;- + foreach (Line line in horizontal_help_lines) { if (!moving_lines && line.is_visible () && line.button_press (button)) { moving_lines = true;@@ -966,11 +966,11 @@ public class Glyph : FontDisplay { moving_lines = true; } }- + if (moving_lines) { return; }- + if (move_canvas || DrawingTools.move_canvas.is_selected ()) { view_is_moving = true; move_offset_x = view_offset_x;@@ -992,9 +992,9 @@ public class Glyph : FontDisplay { public void set_center (double x, double y) { x -= allocation.width / 2.0; y -= allocation.height / 2.0;- + view_offset_x += x / view_zoom;- view_offset_y += y / view_zoom; + view_offset_y += y / view_zoom; } public void set_zoom_from_area () {@@ -1003,7 +1003,7 @@ public class Glyph : FontDisplay { double w = Math.fabs (zoom_x1 - zoom_x2); double h = Math.fabs (zoom_y1 - zoom_y2);- + double view_zoom_x, view_zoom_y; double ivz, off; @@ -1016,57 +1016,57 @@ public class Glyph : FontDisplay { } else { view_offset_x += x / view_zoom; view_offset_y += y / view_zoom;- + if (unlikely (allocation.width == 0 || allocation.height == 0)) { return; }- + view_zoom_x = allocation.width * view_zoom / w; view_zoom_y = allocation.height * view_zoom / h;- + // TODO: there is a max zoom level- + if (view_zoom_x * allocation.width < view_zoom_y * allocation.height) { view_zoom = view_zoom_x; ivz = 1 / view_zoom; - off = (view_zoom / view_zoom_y) * allocation.height / view_zoom; + off = (view_zoom / view_zoom_y) * allocation.height / view_zoom; off = allocation.height/view_zoom - off; off /= 2;- + view_offset_y -= off; } else { view_zoom = view_zoom_y; ivz = 1 / view_zoom; - off = (view_zoom / view_zoom_x) * allocation.width / view_zoom; + off = (view_zoom / view_zoom_x) * allocation.width / view_zoom; off = allocation.width / view_zoom - off;- off /= 2; + off /= 2; view_offset_x -= off; }- + zoom_area_is_visible = false; store_current_view (); }- + update_zoom_bar (); }- + public void show_zoom_area (int sx, int sy, int nx, int ny) { double x, y, w, h;- + set_zoom_area (sx, sy, nx, ny);- + zoom_area_is_visible = true;- + x = Math.fmin (zoom_x1, zoom_x2) - 50; y = Math.fmin (zoom_y1, zoom_y2) - 50; w = Math.fabs (zoom_x1 - zoom_x2) + 100; h = Math.fabs (zoom_y1 - zoom_y2) + 100;- + redraw_area ((int)x, (int)y, (int)w, (int)h); } @@ -1082,13 +1082,13 @@ public class Glyph : FontDisplay { if (unlikely (g.view_zoom == 0)) { warning ("Zoom is zero."); g.reset_zoom ();- + if (g.view_zoom == 0) { g.view_zoom = 1; g.view_offset_x = 0; g.view_offset_y = 0; }- } + } } public static double path_coordinate_x (double x) {@@ -1108,7 +1108,7 @@ public class Glyph : FontDisplay { validate_zoom (); return (x - g.view_offset_x + xc ()) * g.view_zoom; }- + public static double path_coordinate_y (double y) { Glyph g = MainWindow.get_current_glyph (); validate_zoom ();@@ -1118,14 +1118,14 @@ public class Glyph : FontDisplay { public static int reverse_path_coordinate_y (double y) { Glyph g = MainWindow.get_current_glyph (); validate_zoom ();- y = Math.rint ((y + g.view_offset_y - yc ()) * g.view_zoom); + y = Math.rint ((y + g.view_offset_y - yc ()) * g.view_zoom); return (int) (-y); } public static double precise_reverse_path_coordinate_y (double y) { Glyph g = MainWindow.get_current_glyph (); validate_zoom ();- y = (y + g.view_offset_y - yc ()) * g.view_zoom; + y = (y + g.view_offset_y - yc ()) * g.view_zoom; return -y; } @@ -1141,7 +1141,7 @@ public class Glyph : FontDisplay { } } }- + if (!found) { foreach (Path pt in get_paths_in_current_layer ()) { if (pt.is_over (x, y)) {@@ -1153,43 +1153,43 @@ public class Glyph : FontDisplay { } } }- + return group; }- + public bool select_path (double x, double y) { Path? p = null; bool found = false;- + foreach (Path pt in get_paths_in_current_layer ()) { if (pt.is_over (x, y)) { p = pt; found = true; } }- + if (!KeyBindings.has_shift ()) { clear_active_paths (); }- + add_active_path (null, p);- + return found; }- + public bool is_over_selected_path (double x, double y) { foreach (Path pt in active_paths) { if (pt.is_over (x, y)) { return true; } }- return false; + return false; }- + public void queue_redraw_path (Path path) { redraw_path (path.xmin, path.ymin, path.xmax, path.ymax); }- + private void redraw_path (double xmin, double ymin, double xmax, double ymax) { int yc = (int)(allocation.height / 2.0); @@ -1205,7 +1205,7 @@ public class Glyph : FontDisplay { public Path get_closeset_path (double x, double y) { double d; EditPoint ep = new EditPoint ();- + Path min_point = new Path (); double min_distance = double.MAX; @@ -1221,17 +1221,17 @@ public class Glyph : FontDisplay { foreach (Path p in paths) { if (p.points.size == 0) continue;- + p.get_closest_point_on_path (ep, xt, yt); d = Math.pow (ep.x - xt, 2) + Math.pow (ep.y - yt, 2);- + if (d < min_distance) { min_distance = d; min_point = p; } }- + // a path without any editpoints if (paths.size > 0) { return paths.get (0);@@ -1240,47 +1240,47 @@ public class Glyph : FontDisplay { if (unlikely (min_distance == double.MAX)) { warning (@"No path found in path_list."); }- + return min_point; }- - public void move_selected_edit_point_coordinates (EditPoint selected_point, double xt, double yt) { ++ public void move_selected_edit_point_coordinates (EditPoint selected_point, double xt, double yt) { double x, y;- + BirdFont.get_current_font ().touch (); x = reverse_path_coordinate_x (xt); y = reverse_path_coordinate_y (yt);- + // redraw control point redraw_area ((int)(x - 4*view_zoom), (int)(y - 4*view_zoom), (int)(x + 3*view_zoom), (int)(y + 3*view_zoom));- + // update position of selected point selected_point.set_position (xt, yt);- + if (view_zoom >= 2) { redraw_area (0, 0, allocation.width, allocation.height); } else { redraw_last_stroke (x, y);- } + } } - public void move_selected_edit_point (EditPoint selected_point, double x, double y) { + public void move_selected_edit_point (EditPoint selected_point, double x, double y) { double xt = path_coordinate_x (x); double yt = path_coordinate_y (y); move_selected_edit_point_coordinates (selected_point, xt, yt); }- + public void redraw_segment (EditPoint a, EditPoint b) { double margin = 10; double x = Math.fmin (reverse_path_coordinate_x (a.x), reverse_path_coordinate_x (b.x)) - margin; double y = Math.fmin (reverse_path_coordinate_y (a.y), reverse_path_coordinate_y(b.y)) - margin; double w = Math.fabs (reverse_path_coordinate_x (a.x) - reverse_path_coordinate_x(b.x)) + 2 * margin; double h = Math.fabs (reverse_path_coordinate_y (a.y) - reverse_path_coordinate_y (b.y)) + 2 * margin;- + redraw_area ((int)x, (int)y, (int)w, (int)h); }- + private void redraw_last_stroke (double x, double y) { // redraw line, if we have more than one new point on path double px = 0;@@ -1293,23 +1293,23 @@ public class Glyph : FontDisplay { if (active_paths.size == 0) { return; }- + foreach (Path path in active_paths) { EditPoint p; EditPoint pl = path.get_last_point ();- + if (pl.prev != null) { p = pl.get_prev ();- + px = p.x + xc; py = p.y - xc;- + tw = (px > x) ? (int) (px - x) : (int) (x - px); th = (py > y) ? (int) (py - y) : (int) (y - py);- + if (px > x) px -= tw + 60; if (py > y) py -= th + 60;- + } else { px = x - 60; py = y - 60;@@ -1317,18 +1317,18 @@ public class Glyph : FontDisplay { th = 0; } }- - redraw_area ((int)px - 20, (int)py - 20, tw + 120, th + 120); ++ redraw_area ((int)px - 20, (int)py - 20, tw + 120, th + 120); }- + public bool has_active_path () { return active_paths.size > 0; }- + public bool is_open () { return open; }- + /** Close all editable paths and return false if no path have been closed. */ public bool close_path () { bool r = false;@@ -1337,15 +1337,15 @@ public class Glyph : FontDisplay { if (p.is_editable ()) { r = true; p.set_editable (false);- } + } }- + open = false; clear_active_paths (); GlyphCanvas.redraw ();- + MainWindow.set_cursor (NativeWindow.VISIBLE);- + return r; } @@ -1353,7 +1353,7 @@ public class Glyph : FontDisplay { foreach (Path p in get_visible_paths ()) { p.set_editable (true); p.recalculate_linear_handles ();- + if (p.is_open () && p.points.size > 0) { p.get_first_point ().set_reflective_handles (false); p.get_first_point ().set_tie_handle (false);@@ -1361,52 +1361,52 @@ public class Glyph : FontDisplay { p.get_last_point ().set_tie_handle (false); } }- + open = true; redraw_area (0, 0, allocation.width, allocation.height); }- + public void redraw_path_region (Path p) { int x, y, w, h;- + p.update_region_boundaries ();- + x = reverse_path_coordinate_x (p.xmin); y = reverse_path_coordinate_x (p.xmin); w = reverse_path_coordinate_x (p.xmax) - x; h = reverse_path_coordinate_x (p.ymax) - y; // FIXME: redraw path- - redraw_area (x, y, w, h); ++ redraw_area (x, y, w, h); } - public Line get_line (string name) { + public Line get_line (string name) { foreach (Line line in vertical_help_lines) { if (likely (line.get_label () == name)) { return line; } }- + foreach (Line line in horizontal_help_lines) { if (likely (line.get_label () == name)) { return line; } }- + warning (@"No line with label $name found"); return new Line ("Err"); }- + public override void zoom_in () { if (move_canvas) { return; }- + set_zoom_area (10, 10, allocation.width - 10, allocation.height - 10); set_zoom_from_area (); update_view (); update_zoom_bar (); }- + public override void zoom_out () { double w = allocation.width; int n = (int) (10 * ((w - 10) / allocation.width));@@ -1415,35 +1415,35 @@ public class Glyph : FontDisplay { update_view (); update_zoom_bar (); }- + public override void zoom_max () { default_zoom (); update_zoom_bar (); }- + public override void zoom_min () { double ax = 1000; double ay = 1000; double bx = -1000; double by = -1000;- + int iax, iay, ibx, iby;- + reset_zoom (); foreach (var p in get_visible_paths ()) { p.update_region_boundaries ();- + if (p.points.size > 2) { if (p.xmin < ax) ax = p.xmin;- if (p.ymin < ay) ay = p.ymin; + if (p.ymin < ay) ay = p.ymin; if (p.xmax > bx) bx = p.xmax; if (p.ymax > by) by = p.ymax; } }- + if (ax == 1000) return; // empty page- + iax = (int) ((ax + view_offset_x + allocation.width / 2.0) * view_zoom); iay = (int) ((-ay + view_offset_y + allocation.height / 2.0) * view_zoom); ibx = (int) ((bx + view_offset_x + allocation.width / 2.0) * view_zoom);@@ -1452,81 +1452,81 @@ public class Glyph : FontDisplay { show_zoom_area (iax, iay, ibx, iby); // set this later on button release set_zoom_from_area (); zoom_out (); // add some margin- + redraw_area (0, 0, allocation.width, allocation.height); update_zoom_bar (); } public override void store_current_view () { ZoomView n;- + if (zoom_list_index + 1 < zoom_list.size) { n = zoom_list.get (zoom_list_index); while (n != zoom_list.get (zoom_list.size - 1)) { zoom_list.remove_at (zoom_list.size - 1); } }- + zoom_list.add (new ZoomView (view_offset_x, view_offset_y, view_zoom, allocation)); zoom_list_index = (int) zoom_list.size - 1;- + if (zoom_list.size > 50) { zoom_list.remove_at (0); } }- + public override void restore_last_view () { if (zoom_list.size == 0 || zoom_list_index - 1 < 0) { return; }- + zoom_list_index--;- + ZoomView z = zoom_list.get (zoom_list_index);- + view_offset_x = z.x; view_offset_y = z.y; view_zoom = z.zoom; allocation = z.allocation;- + update_zoom_bar (); } public override void next_view () { ZoomView z;- + if (zoom_list.size == 0 || zoom_list_index + 1 >= zoom_list.size) { return; }- + zoom_list_index++;- + z = zoom_list.get (zoom_list_index);- + view_offset_x = z.x; view_offset_y = z.y; view_zoom = z.zoom; allocation = z.allocation;- - update_zoom_bar (); ++ update_zoom_bar (); }- + public override void reset_zoom () { view_offset_x = 0; view_offset_y = 0;- + set_zoom (1);- + store_current_view (); update_zoom_bar (); }- + /** Get x-height or top line. */ public Line get_upper_line () { if (has_top_line () || xheight_lines_visible) { return get_line ("top"); }- + return get_line ("x-height"); } @@ -1534,72 +1534,72 @@ public class Glyph : FontDisplay { public Line get_lower_line () { return get_line ("baseline"); }- + /** Set default zoom. See default_zoom. */ public void set_default_zoom () { int bottom = 0; int top = 0; int left = 0; int right = 0;- + return_if_fail (vertical_help_lines.size != 0); return_if_fail (horizontal_help_lines.size != 0); reset_zoom ();- + bottom = get_lower_line ().get_position_pixel (); top = get_upper_line ().get_position_pixel (); left = vertical_help_lines.get (vertical_help_lines.size - 1).get_position_pixel (); right = vertical_help_lines.get (0).get_position_pixel ();- + set_zoom_area (left + 10, top - 10, right - 10, bottom + 10); set_zoom_from_area (); }- + /** Set default zoom and redraw canvas. */ public void default_zoom () { set_default_zoom (); update_view (); }- + public bool is_empty () { foreach (Path p in get_visible_paths ()) { if (p.points.size > 0) { return false; } }- + return true; }- + public void set_zoom (double z) requires (z > 0)- { + { view_zoom = z; } public void set_background_visible (bool visibility) { background_image_visible = visibility; }- + public bool get_background_visible () { return background_image_visible; }- + public void draw_coordinate (Context cr) { Theme.color (cr, "Table Border"); cr.set_font_size (12); cr.move_to (0, 10); cr.show_text (@"($motion_x, $motion_y)");- cr.stroke (); + cr.stroke (); }- + /** Draw filled paths. */ public void draw_paths (Context cr, Color? c = null) { PathList stroke; Color color;- + cr.save (); cr.new_path (); foreach (Path p in get_visible_paths ()) {@@ -1610,7 +1610,7 @@ public class Glyph : FontDisplay { } else { color = Color.black (); }- + if (p.stroke > 0) { stroke = p.get_stroke_fast (); draw_path_list (stroke, cr, color);@@ -1621,24 +1621,24 @@ public class Glyph : FontDisplay { cr.fill (); cr.restore (); }- + public void draw_path (Context cr) { PathList stroke; Color color;- + cr.save (); cr.new_path (); foreach (Path p in get_visible_paths ()) { if (p.stroke > 0) { stroke = p.get_stroke_fast ();- + if (p.is_editable ()) {- color = Theme.get_color ("Filled Stroke"); + color = Theme.get_color ("Filled Stroke"); color.a = 0.8; } else { color = Color.black (); }- + draw_path_list (stroke, cr, color); } }@@ -1661,7 +1661,7 @@ public class Glyph : FontDisplay { cr.fill (); cr.restore (); }- + if (is_open () && Path.fill_open_path) { cr.save (); cr.new_path ();@@ -1674,7 +1674,7 @@ public class Glyph : FontDisplay { cr.fill (); cr.restore (); }- + if (is_open ()) { cr.save (); cr.new_path ();@@ -1684,11 +1684,11 @@ public class Glyph : FontDisplay { } cr.restore (); }- + if (!is_open ()) { // This was good for testing but it is way too slow: // Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline);- + cr.save (); cr.new_path (); foreach (Path p in get_visible_paths ()) {@@ -1700,7 +1700,7 @@ public class Glyph : FontDisplay { cr.close_path (); cr.fill (); cr.restore ();- + foreach (Path p in active_paths) { cr.save (); cr.new_path ();@@ -1712,25 +1712,25 @@ public class Glyph : FontDisplay { cr.restore (); } }- + if (show_orientation_arrow) { foreach (Path p in get_visible_paths ()) { if (p.stroke > 0) { stroke = p.get_stroke_fast (); foreach (Path ps in stroke.paths) { ps.draw_orientation_arrow (cr, orientation_arrow_opacity);- } + } } else { p.draw_orientation_arrow (cr, orientation_arrow_opacity); } } } }- + private Color get_path_fill_color () { return Theme.get_color ("Fill Color"); }- + public void draw_path_list (PathList pl, Context cr, Color? c = null) { foreach (Path p in pl.paths) { p.draw_path (cr, this, c);@@ -1746,7 +1746,7 @@ public class Glyph : FontDisplay { cr.restore (); } }- + public void draw_help_lines (Context cr) { foreach (Line line in get_all_help_lines ()) { cr.save ();@@ -1754,20 +1754,20 @@ public class Glyph : FontDisplay { cr.restore (); } }- + public void set_allocation (WidgetAllocation a) { allocation = a; }- + public override void draw (WidgetAllocation allocation, Context cmp) { Tool tool;- + this.allocation = allocation;- + cmp.save (); draw_background_color (cmp, 1); cmp.restore ();- + if (background_image != null && background_image_visible) { ((!)background_image).draw (cmp, allocation, view_offset_x, view_offset_y, view_zoom); }@@ -1777,7 +1777,7 @@ public class Glyph : FontDisplay { p.draw_boundaries (cmp); } }- + draw_background_glyph (allocation, cmp); juxtapose (allocation, cmp); @@ -1799,23 +1799,23 @@ public class Glyph : FontDisplay { cmp.restore (); } - cmp.save (); + cmp.save (); tool = MainWindow.get_toolbox ().get_current_tool (); tool.draw_action (tool, cmp, this); cmp.restore ();- } + } private void zoom_in_at_point (double x, double y, double amount = 15) { int n = (int) (-amount); zoom_at_point (x, y, n); }- + private void zoom_out_at_point (double x, double y, double amount = 15) { double a = -amount; int n = (int) (a * ((allocation.width - a) / allocation.width)); zoom_at_point (x, y, n); }- + public void zoom_tap (double distance) { int w = (int) (distance); if (distance != 0) {@@ -1823,22 +1823,22 @@ public class Glyph : FontDisplay { set_zoom_from_area (); } }- + /** Zoom in @param n pixels. */ private void zoom_at_point (double x, double y, int n) { double w = allocation.width; double h = allocation.height;- + double rx = Math.fabs (w / 2 - x) / (w / 2); double ry = Math.fabs (h / 2 - y) / (h / 2);- + int xd = (x < w / 2) ? (int) (n * rx) : (int) (-n * rx); int yd = (y < h / 2) ? (int) (n * ry) : (int) (-n * ry);- + show_zoom_area (-n + xd, -n + yd, allocation.width + n + xd, allocation.height + n + yd); set_zoom_from_area (); }- + private void move_view_offset (double x, double y) { view_offset_x = move_offset_x + (pointer_begin_x - x) * (1/view_zoom); view_offset_y = move_offset_y + (pointer_begin_y - y) * (1/view_zoom);@@ -1848,7 +1848,7 @@ public class Glyph : FontDisplay { public void store_undo_state (bool clear_redo = false) { Glyph g = copy (); undo_list.add (g);- + if (clear_redo) { redo_list.clear (); }@@ -1856,29 +1856,29 @@ public class Glyph : FontDisplay { public void store_redo_state () { Glyph g = copy ();- redo_list.add (g); + redo_list.add (g); } public Glyph copy () { Glyph g = new Glyph.no_lines (name, unichar_code);- + g.current_layer = current_layer;- + g.left_limit = left_limit; g.right_limit = right_limit;- + g.remove_lines ();- + foreach (Line line in get_all_help_lines ()) { g.add_line (line.copy ()); }- + g.layers = layers.copy ();- + foreach (Path p in active_paths) { g.active_paths.add (p); }- + if (background_image != null) { g.background_image = ((!) background_image).copy (); }@@ -1886,13 +1886,13 @@ public class Glyph : FontDisplay { g.empty = empty; g.open = open; g.version_id = version_id;- + return g; } public void reload () { Font f = BirdFont.get_current_font ();- + if (f.has_glyph (name)) { set_glyph_data ((!) f.get_glyph (name)); }@@ -1901,49 +1901,49 @@ public class Glyph : FontDisplay { public override void undo () { Glyph g; Tool tool;- + if (undo_list.size == 0) { return; }- + tool = MainWindow.get_toolbox ().get_current_tool (); tool.before_undo ();- - g = undo_list.get (undo_list.size - 1); - ++ g = undo_list.get (undo_list.size - 1);+ store_redo_state (); set_glyph_data (g);- + undo_list.remove_at (undo_list.size - 1);- + DrawingTools.update_layers (); PenTool.update_selected_points ();- + clear_active_paths ();- + tool.after_undo (); } public override void redo () { Glyph g;- + if (redo_list.size == 0) { return; }- - g = redo_list.get (redo_list.size - 1); - ++ g = redo_list.get (redo_list.size - 1);+ store_undo_state (false); set_glyph_data (g);- + redo_list.remove_at (redo_list.size - 1); DrawingTools.update_layers (); PenTool.update_selected_points ();- + clear_active_paths (); }- + void set_glyph_data (Glyph g) { current_layer = g.current_layer; layers = g.layers.copy ();@@ -1954,17 +1954,17 @@ public class Glyph : FontDisplay { } add_help_lines ();- + if (g.background_image != null) { background_image = ((!) g.background_image).copy (); }- + clear_active_paths (); foreach (Path p in g.active_paths) { add_active_path (null, p); } - redraw_area (0, 0, allocation.width, allocation.height); + redraw_area (0, 0, allocation.width, allocation.height); } /** Split curve in two parts and add a new point in between.@@ -1976,20 +1976,20 @@ public class Glyph : FontDisplay { Path path; EditPoint? np = null; EditPoint lep;- + double xt; double yt; xt = x * ivz () - xc () + view_offset_x; yt = yc () - y * ivz () - view_offset_y;- + min = double.MAX;- + foreach (Path pp in get_visible_paths ()) { lep = new EditPoint (); pp.get_closest_point_on_path (lep, xt, yt); distance = Math.sqrt (Math.pow (Math.fabs (xt - lep.x), 2) + Math.pow (Math.fabs (yt - lep.y), 2));- + if (distance < min) { min = distance; p = pp;@@ -2000,18 +2000,18 @@ public class Glyph : FontDisplay { if (p == null) { return; }- + path = (!) p; lep = new EditPoint (); path.get_closest_point_on_path (lep, xt, yt); path.insert_new_point_on_path (lep); }- + static bool in_range (double offset_x, double coordinate_x1, double coordinate_x2) { return coordinate_x1 <= offset_x <= coordinate_x2; }- + public void juxtapose (WidgetAllocation allocation, Context cr) { string glyph_sequence = Preferences.get ("glyph_sequence"); unichar c;@@ -2024,22 +2024,22 @@ public class Glyph : FontDisplay { double x, kern; double left, baseline; string last_name;- + double box_x1, box_x2, box_y1, box_y2; double marker_x, marker_y;- + KerningClasses classes = font.get_kerning_classes ();- + x = 0;- + box_x1 = path_coordinate_x (0); box_y1 = path_coordinate_y (0); box_x2 = path_coordinate_x (allocation.width); box_y2 = path_coordinate_y (allocation.height);- + current.append_unichar (glyph.unichar_code); pos = glyph_sequence.index_of (current.str);- + baseline = font.base_line;; left = glyph.get_line ("left").pos; @@ -2047,22 +2047,22 @@ public class Glyph : FontDisplay { last_name = glyph.name; for (int i = pos + 1; i < glyph_sequence.char_count (); i++) { c = glyph_sequence.get_char (i);- name = (!) c.to_string (); + name = (!) c.to_string (); juxtaposed = (font.has_glyph (name)) ? (!) font.get_glyph (name) : font.get_space ().get_current ();- + if (font.has_glyph (last_name) && font.has_glyph (name)) { kern = classes.get_kerning (last_name, name); } else { kern = 0; }- + if (!juxtaposed.is_empty () && (in_range (left + x + kern, box_x1, box_x2) // the letter is visible || in_range (left + x + kern + juxtaposed.get_width (), box_x1, box_x2))) { marker_x = Glyph.xc () + left + x + kern - glyph.view_offset_x; marker_y = Glyph.yc () - baseline - glyph.view_offset_y;- + cr.save (); cr.scale (glyph.view_zoom, glyph.view_zoom); Theme.color (cr, "Foreground 1");@@ -2070,7 +2070,7 @@ public class Glyph : FontDisplay { Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), marker_x, marker_y); cr.restore (); }- + x += juxtaposed.get_width () + kern; last_name = name;@@ -2082,19 +2082,19 @@ public class Glyph : FontDisplay { c = glyph_sequence.get_char (i); name = (!) c.to_string (); juxtaposed = (font.has_glyph (name)) ? (!) font.get_glyph (name) : font.get_space ().get_current ();- + if (font.has_glyph (last_name) && font.has_glyph (name)) { kern = classes.get_kerning (name, last_name); } else { kern = 0; }- + x -= juxtaposed.get_width (); x -= kern;- + marker_x = Glyph.xc () + left + x; marker_y = Glyph.yc () - baseline;- if (!juxtaposed.is_empty () + if (!juxtaposed.is_empty () &&(in_range (left + x, box_x1, box_x2) || in_range (left + x + juxtaposed.get_width (), box_x1, box_x2))) { cr.save ();@@ -2104,11 +2104,11 @@ public class Glyph : FontDisplay { Svg.draw_svg_path (cr, juxtaposed.get_svg_data (), marker_x, marker_y); cr.restore (); }- + last_name = name; } }- + /** @return left side bearing */ public double get_lsb () { return get_line ("left").pos;@@ -2119,14 +2119,14 @@ public class Glyph : FontDisplay { Font font = BirdFont.get_current_font (); return font.base_line; }- + void draw_background_glyph (WidgetAllocation allocation, Context cr) { double left, baseline, current_left; Glyph g; Font font = BirdFont.get_current_font ();- + current_left = get_line ("left").pos;- + if (background_glyph != null) { g = (!) background_glyph; baseline = font.base_line;@@ -2135,21 +2135,21 @@ public class Glyph : FontDisplay { cr.scale (view_zoom, view_zoom); cr.translate (-view_offset_x, -view_offset_y); Theme.color (cr, "Background Glyph");- - Svg.draw_svg_path (cr, g.get_svg_data (), - Glyph.xc () + left - (left - current_left) , ++ Svg.draw_svg_path (cr, g.get_svg_data (),+ Glyph.xc () + left - (left - current_left) , Glyph.yc () - baseline); cr.restore (); }- + }- + public string get_hex () { return Font.to_hex_code (unichar_code); }- + public override void move_view (double x, double y) {- view_offset_x += x / view_zoom; + view_offset_x += x / view_zoom; view_offset_y += y / view_zoom; GlyphCanvas.redraw (); }@@ -2163,40 +2163,40 @@ public class Glyph : FontDisplay { dy = 0; new_distance = 0;- + if (last_tap0_y == -1 || last_tap0_x == -1 || last_tap1_y == -1 || last_tap1_x == -1) { return; }- + if (finger == 0) { dx = last_tap0_x - x; dy = last_tap0_y - y; new_distance = Path.distance (last_tap1_x, x, last_tap1_y, y); }- + if (finger == 1) { dx = last_tap1_x - x; dy = last_tap1_y - y; new_distance = Path.distance (last_tap0_x, x, last_tap0_y, y); }- + last_distance = Path.distance (last_tap0_x, last_tap1_x, last_tap0_y, last_tap1_y); if (zoom_distance != 0) {- zoom_tap (zoom_distance - new_distance); - } - + zoom_tap (zoom_distance - new_distance);+ }+ if (finger == 1) { warning (@"dx $dx dy $dy last_tap1_x $last_tap1_x last_tap1_y $last_tap1_y x $x y $y");- move_view (dx, dy); - } + move_view (dx, dy);+ } zoom_distance = new_distance; } public override void tap_down (int finger, int x, int y) { TimeoutSource delay;- + if (finger == 0) { delay = new TimeoutSource (400); // wait for second finger delay.set_callback(() => {@@ -2206,53 +2206,53 @@ public class Glyph : FontDisplay { return false; }); delay.attach (null);- + last_tap0_x = x; last_tap0_y = y; }- + if (finger == 1) { change_view = true; last_tap1_x = x; last_tap1_y = y; } }- + public override void tap_up (int finger, int x, int y) { if (finger == 0) { button_release (1, x, y);- + last_tap0_x = -1; last_tap0_y = -1; }- + if (finger == 1) { last_tap1_x = -1; last_tap1_y = -1;- + change_view = false; zoom_distance = 0; } }- + public override void tap_move (int finger, int x, int y) { if (!change_view) { motion_notify (x, y); } else { change_view_event (finger, x, y); }- + if (finger == 0) { last_tap0_x = x; last_tap0_y = y; }- + if (finger == 1) { last_tap1_x = x; last_tap1_y = y; } }- + public void update_spacing_class () { Font font = BirdFont.get_current_font (); GlyphCollection? g;@@ -2260,7 +2260,7 @@ public class Glyph : FontDisplay { Glyph glyph; Gee.ArrayList<string> s; SpacingData sd;- + sd = font.get_spacing (); s = sd.get_all_connections ((!) unichar_code.to_string ()); foreach (string l in s) {@@ -2273,7 +2273,7 @@ public class Glyph : FontDisplay { if (glyph.left_limit == glyph.right_limit) { warning ("Zero width glyph in kerning class."); }- + left_limit = glyph.left_limit; right_limit = glyph.right_limit; @@ -2281,7 +2281,7 @@ public class Glyph : FontDisplay { } } }- + add_help_lines (); } @@ -2292,10 +2292,10 @@ public class Glyph : FontDisplay { Glyph glyph; Gee.ArrayList<string> s; SpacingData sd;- + sd = font.get_spacing (); s = sd.get_all_connections ((!) unichar_code.to_string ());- + foreach (string l in s) { if (l != (!) unichar_code.to_string ()) { g = font.get_glyph_collection (l);@@ -2306,7 +2306,7 @@ public class Glyph : FontDisplay { glyph.right_limit = right_limit; } }- } + } } public void set_cache (string key, Surface cache) {@@ -2322,33 +2322,33 @@ public class Glyph : FontDisplay { warning ("No cache for glyph."); return new ImageSurface (Cairo.Format.ARGB32, 1, 1); }- + return glyph_cache.get (key); }- + public void add_custom_guide () { TextListener listener;- + listener = new TextListener (t_("Guide"), "", t_("Add"));- + listener.signal_text_input.connect ((text) => { new_guide_name = text; });- + listener.signal_submit.connect (() => { Line guide; double position;- + position = path_coordinate_y (allocation.height / 2.0); guide = new Line (new_guide_name, position); horizontal_help_lines.add (guide);- + BirdFont.get_current_font ().custom_guides.add (guide);- + TabContent.hide_text_input (); GlyphCanvas.redraw (); });- + TabContent.show_text_input (listener); } @@ -2360,53 +2360,53 @@ public class Glyph : FontDisplay { public void move_layer_up () { Layer layer = get_current_layer ();- + if (current_layer + 2 <= layers.subgroups.size) { return_if_fail (0 <= current_layer + 2 <= layers.subgroups.size); layers.subgroups.insert (current_layer + 2, layer); return_if_fail (0 <= current_layer + 1 < layers.subgroups.size); layers.subgroups.remove_at (current_layer);- + set_current_layer (layer);- } + } }- + public void move_layer_down () { Layer layer = get_current_layer ();- + if (current_layer >= 1) { return_if_fail (0 <= current_layer - 1 < layers.subgroups.size); layers.subgroups.insert (current_layer - 1, layer); return_if_fail (0 <= current_layer + 1 < layers.subgroups.size); layers.subgroups.remove_at (current_layer + 1);- + set_current_layer (layer);- } + } }- + public void fix_curve_orientation () { int inside_count; bool inside; Path outline;- + foreach (Path p1 in get_visible_paths ()) { inside_count = 0;- + foreach (Path p2 in get_visible_paths ()) { if (p1 != p2) { inside = true; outline = p2.flatten ();- + foreach (EditPoint ep in p1.points) { if (!SvgParser.is_inside (ep, outline)) { inside = false; } }- + if (inside) {- inside_count++; + inside_count++; } } }@@ -2418,6 +2418,18 @@ public class Glyph : FontDisplay { } } }++ public override void magnify (double magnification) {+ double x_center = path_coordinate_x (xc ());+ double y_center = path_coordinate_y (yc ());++ view_zoom *= 1 + magnification;++ view_offset_x -= path_coordinate_x (xc ()) - x_center;+ view_offset_y += path_coordinate_y (yc ()) - y_center;++ GlyphCanvas.redraw ();+ } } }@@ -1,24 +1,24 @@ /* Copyright (C) 2012 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 + 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 + 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 Preview : FontDisplay { - +public class Preview : FontDisplay {+ public Preview () { }- + public override string get_name () { return "Preview"; }@@ -26,8 +26,9 @@ public class Preview : FontDisplay { public override string get_label () { return t_("Preview"); }- + public override void selected_canvas () {+ MainWindow.set_scrollbar_size (0); } public static string get_html_path () {@@ -39,14 +40,14 @@ public class Preview : FontDisplay { string fn = get_html_file_name (); File dir = font.get_folder (); File file = get_child (dir, fn);- + if (!file.query_exists ()) {- ExportTool.generate_html_document ((!)file.get_path (), font); + ExportTool.generate_html_document ((!)file.get_path (), font); }- + return file; }- + public static bool has_html_document () { Font font = BirdFont.get_current_font (); string path = get_html_file_name ();@@ -54,7 +55,7 @@ public class Preview : FontDisplay { File file = get_child (dir, path); return file.query_exists (); }- + public static void generate_html_document () { Font font = BirdFont.get_current_font (); string path = get_html_file_name ();@@ -74,20 +75,20 @@ public class Preview : FontDisplay { warning (e.message); } }- + static string get_html_file_name () { Font font = BirdFont.get_current_font (); return @"$(ExportSettings.get_file_name (font)).html"; } public static File get_html_file () {- return get_file (); + return get_file (); } public static string get_uri () { return TabContent.path_to_uri ((!) get_html_file ().get_path ()); }- + public static string get_windows_uri () { Font font = BirdFont.get_current_font (); string html = get_html_file_name ();@@ -95,16 +96,16 @@ public class Preview : FontDisplay { File file = get_child (dir, html); return "file:///" + (!) file.get_path (); }- - public static string get_html_with_absolute_paths () { - // hack: force webkit to ignore cache in preview ++ public static string get_html_with_absolute_paths () {+ // hack: force webkit to ignore cache in preview StringBuilder sb = new StringBuilder (); DataInputStream dis; string? line;- + uint rid = Random.next_int (); Font font = BirdFont.get_current_font ();- + File preview_directory; File f_ttf; File f_eot;@@ -112,9 +113,9 @@ public class Preview : FontDisplay { try { dis = new DataInputStream (get_file ().read ());- + preview_directory = BirdFont.get_preview_directory ();- + f_ttf = get_child (font.get_folder (), @"$(ExportSettings.get_file_name (font)).ttf"); f_eot = get_child (font.get_folder (), @"$(ExportSettings.get_file_name (font)).eot"); f_svg = get_child (font.get_folder (), @"$(ExportSettings.get_file_name (font)).svg");@@ -122,11 +123,11 @@ public class Preview : FontDisplay { if (!f_ttf.query_exists ()) { warning ("TTF file does not exist."); }- + if (!f_svg.query_exists ()) { warning ("SVG file does not exist."); }- + while ((line = dis.read_line (null)) != null) { line = ((!) line).replace (@"$(ExportSettings.get_file_name (font)).ttf", @"$(TabContent.path_to_uri ((!) f_ttf.get_path ()))?$rid"); line = ((!) line).replace (@"$(ExportSettings.get_file_name (font)).eot", @"$(TabContent.path_to_uri ((!) f_eot.get_path ()))?$rid");@@ -140,7 +141,7 @@ public class Preview : FontDisplay { } return sb.str; }- + public override bool needs_modifier () { return true; }@@ -1,14 +1,14 @@ /* Copyright (C) 2014 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 + 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 + 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. */ @@ -27,123 +27,123 @@ public class TabContent : GLib.Object { static ImageSurface? pause_surface = null; static const int TEXT_INPUT_HEIGHT = 51;- + static double last_press_time = 0;- + public static void zoom_in () { if (MenuTab.has_suppress_event ()) { }- + GlyphCanvas.current_display.zoom_in (); }- + public static void zoom_out () { if (MenuTab.has_suppress_event ()) { return; }- + GlyphCanvas.current_display.zoom_out (); }- + public static void move_view (double x, double y) { if (MenuTab.has_suppress_event ()) { return; }- + GlyphCanvas.current_display.move_view (x, y); }- + public static bool has_scrollbar () { if (MenuTab.has_suppress_event ()) { return false; }- + return GlyphCanvas.current_display.has_scrollbar (); }- + public static void scroll_to (double percent) { if (MenuTab.has_suppress_event ()) { return; }- + GlyphCanvas.current_display.scroll_to (percent); }- + public static void draw (WidgetAllocation allocation, Context cr) { AbstractMenu menu; Dialog dialog;- + if (unlikely (MenuTab.has_suppress_event ())) { cr.save (); Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height); cr.fill ();- + if (pause_surface != null) { cr.scale (1.0 / Screen.get_scale (), 1.0 / Screen.get_scale ()); cr.set_source_surface ((!) pause_surface, 0, 0); cr.paint (); }- + cr.restore (); } else { menu = MainWindow.get_menu (); dialog = MainWindow.get_dialog ();- + GlyphCanvas.set_allocation (allocation); MainWindow.get_current_glyph ().resized (allocation); GlyphCanvas.current_display.draw (allocation, cr);- + if (dialog.visible) { dialog.allocation = allocation; dialog.draw (cr); }- + if (menu.show_menu) { menu.draw (allocation, cr); }- + if (FontDisplay.dirty_scrollbar) { GlyphCanvas.current_display.update_scrollbar (); FontDisplay.dirty_scrollbar = false; }- + if (text_input_visible) { draw_text_input (allocation, cr); } } }- + public static void create_pause_surface () { Context cr; WidgetAllocation alloc;- + if (MenuTab.has_suppress_event ()) { warning ("Background surface already created."); return; }- + alloc = GlyphCanvas.get_allocation (); pause_surface = Screen.create_background_surface (alloc.width, alloc.height); cr = new Context ((!) pause_surface); cr.scale (Screen.get_scale (), Screen.get_scale ()); draw (alloc, cr); }- + public static void key_press (uint keyval) { if (MenuTab.has_suppress_event ()) { return; }- + unichar c = (unichar) keyval;- + if (unlikely (!c.validate ())) { warning ("Invalid unichar: $(keyval)"); return; }- + KeyBindings.add_modifier_from_keyval (keyval);- + if (!text_input_visible) { MainWindow.get_menu ().process_key_binding_events (keyval); GlyphCanvas.current_display.key_press (keyval);@@ -151,14 +151,14 @@ public class TabContent : GLib.Object { text_input.key_press (keyval); } }- + public static void key_release (uint keyval) { if (MenuTab.has_suppress_event ()) { return; } unichar c = (unichar) keyval;- + if (unlikely (!c.validate ())) { warning ("Invalid unichar: $(keyval)"); return;@@ -170,57 +170,57 @@ public class TabContent : GLib.Object { GlyphCanvas.current_display.key_release (keyval); } }- + public static void motion_notify (double x, double y) { Toolbox toolbox;- + if (MenuTab.has_suppress_event ()) { return; }- + if (!text_input_visible) { GlyphCanvas.current_display.motion_notify (x, y); } else { text_input.motion (x, y); GlyphCanvas.redraw (); }- + toolbox = MainWindow.get_toolbox (); toolbox.hide_tooltip (); }- + public static void button_release (int button, double x, double y) { if (MenuTab.has_suppress_event ()) { return; }- + if (MainWindow.get_dialog ().visible) { MainWindow.get_dialog ().button_release (button, x, y); } else if (MainWindow.get_menu ().show_menu) { MainWindow.get_menu ().button_release (button, x, y); } else if (text_input_visible) { text_input_button.button_release (button, x, y);- text_input.button_release (button, x, y); + text_input.button_release (button, x, y); GlyphCanvas.redraw (); } else { GlyphCanvas.current_display.button_release (button, x, y); } }- + public static void button_press (uint button, double x, double y) { if (MenuTab.has_suppress_event ()) { return; } last_press_time = GLib.get_real_time ();- + if (MainWindow.get_dialog ().visible) { MainWindow.get_dialog ().button_press (button, x, y); } else if (!MainWindow.get_menu ().show_menu) { if (text_input_visible) { text_input.button_press (button, x, y); text_input_button.button_press (button, x, y);- + if (y > TEXT_INPUT_HEIGHT) { hide_text_input (); }@@ -234,79 +234,89 @@ public class TabContent : GLib.Object { if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.double_click (button, ex, ey); } }- - public static void scroll_wheel_pixel_delta (double x, double y, ++ public static void scroll_wheel_pixel_delta (double x, double y, double pixeldelta_x, double pixeldelta_y) {- + if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.scroll_wheel (x, y, pixeldelta_x, pixeldelta_y);- } + } }- + public static void scroll_wheel_up (double x, double y) { if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.scroll_wheel (x, y, 0, 15); } }- + public static void scroll_wheel_down (double x, double y) { if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.scroll_wheel (x, y, 0, -15); } } + public static void magnify (double magnification) {+ if (MenuTab.has_suppress_event ()) {+ return;+ }++ if (!MainWindow.get_menu ().show_menu) {+ GlyphCanvas.current_display.magnify (magnification);+ }+ }+ public static void tap_down (int finger, int x, int y) { if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.tap_down (finger, x, y); } }- + public static void tap_up (int finger, int x, int y) { if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.tap_up (finger, x, y); } }- + public static void tap_move (int finger, int x, int y) { if (MenuTab.has_suppress_event ()) { return; }- + if (!MainWindow.get_menu ().show_menu) { GlyphCanvas.current_display.tap_move (finger, x, y); } }- + public static void undo () { if (MenuTab.has_suppress_event ()) { return; }- + GlyphCanvas.current_display.undo (); } @@ -314,18 +324,18 @@ public class TabContent : GLib.Object { if (MenuTab.has_suppress_event ()) { return; }- + GlyphCanvas.current_display.redo (); }- + public static string path_to_uri (string path) { string uri = path; string wp;- + // wine uri hack if (BirdFont.win32) { wp = wine_to_unix_path (uri);- + if (SearchPaths.find_file (wp, "").query_exists ()) { uri = wp; }@@ -340,20 +350,20 @@ public class TabContent : GLib.Object { } else { uri = @"file:///$uri"; }- + return uri; }- + public static void draw_text_input (WidgetAllocation allocation, Context cr) { cr.save ();- + Theme.color (cr, "Default Background"); cr.rectangle (0, 0, allocation.width, TEXT_INPUT_HEIGHT); cr.fill (); cr.restore ();- + Theme.text_color (text_input_label, "Button Foreground");- + text_input_label.widget_x = 10; text_input_label.widget_y = 17; @@ -361,11 +371,11 @@ public class TabContent : GLib.Object { text_input.layout (); text_input.widget_x = text_input_label.get_extent () + 20; text_input.widget_y = 10;- text_input.width = allocation.width - - text_input_button.get_width () + text_input.width = allocation.width+ - text_input_button.get_width () - text_input_label.get_extent () - 40;- + text_input_button.allocation = allocation; text_input_button.widget_x = text_input.widget_x + text_input.width + 10; text_input_button.widget_y = 10;@@ -374,40 +384,40 @@ public class TabContent : GLib.Object { text_input.draw (cr); text_input_button.draw (cr); }- + public static void show_text_input (TextListener tl) { text_callback = tl;- + text_input_label = new Text (tl.label); text_input = new LineTextArea (20 * MainWindow.units); text_input_button = new Button (tl.button_label);- + text_input.carret_is_visible = true;- + text_input.set_text (tl.default_text); text_input.text_changed.connect ((text) => { tl.signal_text_input (text); });- + text_input.enter.connect ((text) => { tl.signal_submit (text); text_input_visible = false; GlyphCanvas.redraw (); });- + text_input_button.action.connect (() => { tl.signal_submit (text_input.get_text ()); });- + text_input_visible = true; GlyphCanvas.redraw (); }- + public static void hide_text_input () { text_input_visible = false; text_callback = new TextListener ("", "", ""); }- + public static void reset_modifier () { TabContent.key_release (Key.CTRL_RIGHT); TabContent.key_release (Key.CTRL_LEFT);@@ -417,7 +427,7 @@ public class TabContent : GLib.Object { TabContent.key_release (Key.ALT_RIGHT); TabContent.key_release (Key.LOGO_LEFT); TabContent.key_release (Key.LOGO_RIGHT);- + if (MainWindow.get_current_display () is Glyph) { TabContent.key_release ((uint) ' '); }