The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Zoom with trackpad and other fixes for Mac

These changes was commited to the Birdfont repository Thu, 22 Oct 2015 21:06:48 +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>
Thu, 22 Oct 2015 21:06:48 +0000 (23:06 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Thu, 22 Oct 2015 21:06:48 +0000 (23:06 +0200)
commit 9597194e8206e113c25612b89758da2b1a4fc2e2
tree d7f8599d1caba04620de95ad18bdfe3691bdeb27
parent 67c39f18d87318e5ca43b78e39758cbe223a22fd
Zoom with trackpad and other fixes for Mac

install.py
libbirdfont/BirdFont.vala
libbirdfont/FontDisplay.vala
libbirdfont/Glyph.vala
libbirdfont/Preview.vala
libbirdfont/TabContent.vala
--- a/install.py +++ b/install.py @@ -123,7 +123,9 @@ 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)
--- a/libbirdfont/BirdFont.vala +++ b/libbirdfont/BirdFont.vala @@ -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 @@ 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 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 @@ string theme_version; CharDatabaseParser parser; CodePageBits codepage_bits; - + set_settings_subdir (settings_subdir); args = new Argument.command_line (arg); @@ -128,17 +127,17 @@ #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 @@ if (BirdFont.logging) { init_logfile (); } - + if (!args.has_argument ("--no-translation")) { init_gettext (); } @@ -157,24 +156,25 @@ 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 @@ } 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 @@ #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 @@ } 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 @@ 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 @@ 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 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 @@ 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 @@ __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 @@ 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 @@ } 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 @@ 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 @@ } else { warning ("No logstream."); } - + stderr.printf (s); } catch (GLib.Error e) { warning (e.message); @@ -438,26 +438,26 @@ 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 @@ if (log_domain != null) { printd ((!) log_domain); } - + printd ("\n"); printd (message); printd ("\n"); @@ -487,7 +487,7 @@ public string t_ (string t) { #if ANDROID return t; - #else + #else return _(t); #endif } @@ -505,7 +505,7 @@ } } - /** 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 @@ 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 @@ if (!f.has_suffix (s)) { f += s; } - + printd (@"File in Directory: $f Name: $n\n"); - + return File.new_for_path (f + n); }
--- a/libbirdfont/FontDisplay.vala +++ b/libbirdfont/FontDisplay.vala @@ -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 @@ 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 @@ /** 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 @@ 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 @@ } 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 @@ 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. */
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -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 @@ 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 @@ 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 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 @@ 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 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 @@ this.unichar_code = unichar_code; add_help_lines (); - + left_limit = -28; right_limit = 28; } @@ -156,7 +156,7 @@ 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 @@ } 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 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 @@ undo_list.clear (); redo_list.clear (); } - + public void set_empty_ttf (bool e) { empty = e; } @@ -241,24 +241,24 @@ 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 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 @@ x2 = CANVAS_MIN; y1 = CANVAS_MAX; y2 = CANVAS_MIN; - + foreach (Path p in paths) { p.update_region_boundaries (); @@ -307,36 +307,36 @@ 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 @@ 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 @@ } 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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ // 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 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 @@ 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 @@ 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 @@ 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 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 @@ 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 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 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 @@ } 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 @@ 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 @@ return (int) (first.get_pos () - next.get_pos ()); }); } - + public override string get_name () { return name; } @@ -797,10 +797,10 @@ 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 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 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 @@ } /** 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ } 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 @@ 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 @@ 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 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 @@ } } } - + if (!found) { foreach (Path pt in get_paths_in_current_layer ()) { if (pt.is_over (x, y)) { @@ -1153,43 +1153,43 @@ } } } - + 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ } else { color = Color.black (); } - + if (p.stroke > 0) { stroke = p.get_stroke_fast (); draw_path_list (stroke, cr, color); @@ -1621,24 +1621,24 @@ 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 @@ cr.fill (); cr.restore (); } - + if (is_open () && Path.fill_open_path) { cr.save (); cr.new_path (); @@ -1674,7 +1674,7 @@ cr.fill (); cr.restore (); } - + if (is_open ()) { cr.save (); cr.new_path (); @@ -1684,11 +1684,11 @@ } 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 @@ cr.close_path (); cr.fill (); cr.restore (); - + foreach (Path p in active_paths) { cr.save (); cr.new_path (); @@ -1712,25 +1712,25 @@ 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 @@ cr.restore (); } } - + public void draw_help_lines (Context cr) { foreach (Line line in get_all_help_lines ()) { cr.save (); @@ -1754,20 +1754,20 @@ 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 @@ p.draw_boundaries (cmp); } } - + draw_background_glyph (allocation, cmp); juxtapose (allocation, cmp); @@ -1799,23 +1799,23 @@ 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 @@ 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 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 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 @@ 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 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } } - + add_help_lines (); } @@ -2292,10 +2292,10 @@ 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 @@ glyph.right_limit = right_limit; } } - } + } } public void set_cache (string key, Surface cache) { @@ -2322,33 +2322,33 @@ 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 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,7 +2418,19 @@ } } } + + 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 (); + } } }
--- a/libbirdfont/Preview.vala +++ b/libbirdfont/Preview.vala @@ -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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } return sb.str; } - + public override bool needs_modifier () { return true; }
--- a/libbirdfont/TabContent.vala +++ b/libbirdfont/TabContent.vala @@ -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 @@ 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 @@ 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 @@ 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,41 +234,51 @@ 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); } } @@ -276,37 +286,37 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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) ' '); }