Commit 93110ab
Adjust font size and fix crash bug Add tools for setting the font size in the kerning tab. This commit also adds a fix for a critical crash bug in the kerning code.
Changed files (10)
modifiedbirdfont/GtkWindow.valamodifiedgraphics/tools_and_buttons.svgmodifiedlibbirdfont/FileTab.valamodifiedlibbirdfont/KerningClasses.valamodifiedlibbirdfont/KerningDisplay.valamodifiedlibbirdfont/KerningTools.valamodifiedlibbirdfont/MenuTab.valamodifiedlibbirdfont/PreviewTools.valamodifiedlibbirdfont/TestCases.valamodifiedlibbirdfont/TooltipArea.vala
Diff
@@ -636,7 +636,7 @@ public class GtkWindow : Gtk.Window, NativeWindow { Gtk.MenuItem avalilable_characters_item = new Gtk.MenuItem.with_mnemonic (t_("Show Characters in Font")); tool_menu.append (avalilable_characters_item);- avalilable_characters_item.activate.connect (() => { + avalilable_characters_item.activate.connect (() => { Toolbox.select_tool_by_name ("available_characters"); }); avalilable_characters_item.add_accelerator ("activate", accel_group, 'D', Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE);@@ -516,9 +516,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2"- inkscape:zoom="17.798202"- inkscape:cx="198.57286"- inkscape:cy="713.71441"+ inkscape:zoom="10.139082"+ inkscape:cx="202.54523"+ inkscape:cy="708.83752" inkscape:current-layer="layer1" inkscape:document-units="px" showgrid="false"@@ -538,7 +538,7 @@ <dc:format>image/svg+xml</dc:format> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />- <dc:title />+ <dc:title></dc:title> </cc:Work> </rdf:RDF> </metadata>@@ -1939,31 +1939,6 @@ style="" id="path3763" /> </g>- <path- style="fill:#e6e6e6;stroke:#858585;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"- d="m 197.66197,52.57551 c 0.85553,2.191047 4.9245,9.369166 4.9245,9.369166 1.13323,-0.111314 2.02494,-0.38761 2.77792,-1.111168 0,0 -2.27634,-7.933034 -3.42269,-9.995514 -1.14635,-2.06248 -2.27205,-2.782916 -2.27205,-2.782916 0,0 -0.8337,-0.292969 -1.68551,0.06911 -0.72362,0.30759 -1.2313,1.042059 -1.2313,1.042059 0,0 0.0536,1.218217 0.90913,3.409263 z"- id="path3617"- inkscape:connector-curvature="0"- inkscape:export-filename="/home/johan/birdfont/icons/track.png"- inkscape:export-xdpi="319.89001"- inkscape:export-ydpi="319.89001"- sodipodi:nodetypes="zcczcscz" />- <path- style="fill:none;stroke:#000000;stroke-width:0.59260023px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"- d="m 194.88239,63.475848 c 2.26624,-4.567729 6.53453,3.336107 9.74418,1.026228 0.72121,-0.519032 0.65487,-0.262366 0.47533,-0.94071"- id="path3623"- inkscape:connector-curvature="0"- inkscape:export-filename="/home/johan/birdfont/icons/track.png"- inkscape:export-xdpi="319.89001"- inkscape:export-ydpi="319.89001" />- <path- style="fill:none;stroke:#858585;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"- d="m 203.99938,61.379513 1.22611,2.787498"- id="path3621"- inkscape:connector-curvature="0"- inkscape:export-filename="/home/johan/birdfont/icons/track.png"- inkscape:export-xdpi="319.89001"- inkscape:export-ydpi="319.89001" /> <g id="g4075" inkscape:export-filename="/home/johan/birdfont/icons/update_webview.png"@@ -2056,11 +2031,42 @@ d="m 92.92596,416.18009 0.01336,-3.554" style="fill:none;stroke:#e6e6e6;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> </g>- <path- style="fill:none;stroke:#858585;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"- d="m 200.78554,58.501116 c 1.85663,0.04157 2.59285,-0.471854 3.47686,-1.323342"- id="path3795"- inkscape:connector-curvature="0"- sodipodi:nodetypes="cc" />+ <g+ id="g3799"+ inkscape:export-filename="/home/johan/birdfont/icons/track.png"+ inkscape:export-xdpi="319"+ inkscape:export-ydpi="319">+ <path+ sodipodi:nodetypes="zcczcscz"+ inkscape:export-ydpi="319.89001"+ inkscape:export-xdpi="319.89001"+ inkscape:export-filename="/home/johan/birdfont/icons/track.png"+ inkscape:connector-curvature="0"+ id="path3617"+ d="m 197.66197,52.57551 c 0.85553,2.191047 4.9245,9.369166 4.9245,9.369166 1.13323,-0.111314 2.02494,-0.38761 2.77792,-1.111168 0,0 -2.27634,-7.933034 -3.42269,-9.995514 -1.14635,-2.06248 -2.27205,-2.782916 -2.27205,-2.782916 0,0 -0.8337,-0.292969 -1.68551,0.06911 -0.72362,0.30759 -1.2313,1.042059 -1.2313,1.042059 0,0 0.0536,1.218217 0.90913,3.409263 z"+ style="fill:#e6e6e6;stroke:#858585;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ inkscape:export-ydpi="319.89001"+ inkscape:export-xdpi="319.89001"+ inkscape:export-filename="/home/johan/birdfont/icons/track.png"+ inkscape:connector-curvature="0"+ id="path3623"+ d="m 194.88239,63.475848 c 2.26624,-4.567729 6.53453,3.336107 9.74418,1.026228 0.72121,-0.519032 0.65487,-0.262366 0.47533,-0.94071"+ style="fill:none;stroke:#000000;stroke-width:0.59260023px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ inkscape:export-ydpi="319.89001"+ inkscape:export-xdpi="319.89001"+ inkscape:export-filename="/home/johan/birdfont/icons/track.png"+ inkscape:connector-curvature="0"+ id="path3621"+ d="m 203.99938,61.379513 1.22611,2.787498"+ style="fill:none;stroke:#858585;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ <path+ sodipodi:nodetypes="cc"+ inkscape:connector-curvature="0"+ id="path3795"+ d="m 200.78554,58.501116 c 1.85663,0.04157 2.59285,-0.471854 3.47686,-1.323342"+ style="fill:none;stroke:#858585;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />+ </g> </g> </svg>@@ -54,7 +54,7 @@ public class FileTab : FontDisplay { loaded = f.load (fn); if (!unlikely (loaded)) {- warning (@"Failed to load fond $fn");+ warning (@"Failed to load font $fn"); return; } @@ -34,6 +34,9 @@ public class KerningClasses : GLib.Object { public delegate void KerningIterator (KerningPair list); public delegate void KerningClassIterator (string left, string right, double kerning); + /** Ensure that map iterator is not invalidated because of inserts. */+ bool protect_map = false;+ public KerningClasses () { classes_first = new GLib.List<GlyphRange> (); classes_last = new GLib.List<GlyphRange> ();@@ -58,6 +61,11 @@ public class KerningClasses : GLib.Object { string cleft = (!)GlyphRange.unserialize (left).get_char ().to_string (); string cright = (!)GlyphRange.unserialize (right).get_char ().to_string (); + if (protect_map) {+ warning ("Map is protected.");+ return;+ }+ if (single_kerning_letters_left.index (cleft) < 0) { single_kerning_letters_left.append (cleft); }@@ -77,6 +85,11 @@ public class KerningClasses : GLib.Object { return; } + if (protect_map) {+ warning ("Map is protected.");+ return;+ }+ if (!left_range.is_class () && !right_range.is_class ()) { set_kerning_for_single_glyphs (left_range.get_all_ranges (), right_range.get_all_ranges (), k); return;@@ -254,11 +267,16 @@ public class KerningClasses : GLib.Object { print ("\n"); print ("Kernings for pairs:\n");+ if (!set_protect_map (true)) {+ warning ("Map is protected.");+ return;+ } foreach (string key in single_kerning.keys) { print (key); print ("\t\t"); print (@"$((!) single_kerning.get (key))\n"); }+ set_protect_map (false); } public void get_classes (KerningClassIterator kerningIterator) {@@ -272,6 +290,11 @@ public class KerningClasses : GLib.Object { public void get_single_position_pairs (KerningClassIterator kerningIterator) { double k = 0; + if (!set_protect_map (true)) {+ warning ("Map is protected.");+ return;+ }+ foreach (string key in single_kerning.keys) { var chars = key.split (" - "); @@ -282,6 +305,7 @@ public class KerningClasses : GLib.Object { kerningIterator (chars[0], chars[1], k); } }+ set_protect_map (false); } public void each_pair (KerningClassIterator iter) {@@ -373,7 +397,22 @@ public class KerningClasses : GLib.Object { } } + private bool set_protect_map (bool p) {+ if (unlikely (p && protect_map)) {+ warning ("Map is already protected, this is a criticl error.");+ return false;+ }+ + protect_map = p;+ return true;+ }+ public void remove_all_pairs () {+ if (protect_map) {+ warning ("Map is protected.");+ return;+ }+ print ("Remove all kerning pairs\n"); while (classes_first.length () > 0) {@@ -102,6 +102,7 @@ public class KerningDisplay : FontDisplay { bool first_row = true; double row_height; Font font;+ double item_size = 1.0 / KerningTools.font_size; font = BirdFont.get_current_font (); i = 0;@@ -113,6 +114,9 @@ public class KerningDisplay : FontDisplay { cr.fill (); cr.restore (); + cr.save ();+ cr.scale (KerningTools.font_size, KerningTools.font_size);+ glyph = MainWindow.get_current_glyph (); row_height = get_row_height ();@@ -153,9 +157,7 @@ public class KerningDisplay : FontDisplay { } else { alpha = 0; glyph = (!) g;- - // TODO: set font size- // cr.scale (KerningTools.font_size, KerningTools.font_size);+ cr.save (); glyph.add_help_lines (); cr.translate (kern + x - glyph.get_lsb () - Glyph.xc (), glyph.get_baseline () + y - Glyph.yc ());@@ -177,9 +179,9 @@ public class KerningDisplay : FontDisplay { cr.set_source_rgba (123/255.0, 123/255.0, 123/255.0, 1); } - cr.move_to (x2 - 5, y + 20);- cr.line_to (x2 + 0, y + 20 - 5);- cr.line_to (x2 + 5, y + 20);+ cr.move_to (x2 - 5 * item_size, y + 20 * item_size);+ cr.line_to (x2 + 0, y + 20 * item_size - 5 * item_size);+ cr.line_to (x2 + 5 * item_size, y + 20* item_size); cr.fill (); if (gr_left != null || gr_right != null) {@@ -202,7 +204,7 @@ public class KerningDisplay : FontDisplay { cr.save (); cr.set_source_rgba (153/255.0, 153/255.0, 153/255.0, alpha); cr.move_to (x - w / 2.0 - 5, y + 20);- cr.set_font_size (10);+ cr.set_font_size (10 * item_size); cr.show_text ("?"); cr.restore (); }@@ -218,6 +220,7 @@ public class KerningDisplay : FontDisplay { x2 = x; caret_y = get_row_height () + font.base_line + 20; cr.save ();+ cr.set_line_width (1.0 / KerningTools.font_size); cr.set_source_rgba (0, 0, 0, 0.5); cr.move_to (x2, caret_y + 20); cr.line_to (x2, 20);@@ -225,7 +228,7 @@ public class KerningDisplay : FontDisplay { cr.restore (); } - if (y > allocation.height && i > 10) {+ if (y * KerningTools.font_size > allocation.height && i > 10) { row.remove (word); } @@ -233,6 +236,8 @@ public class KerningDisplay : FontDisplay { x = 20; first_row = false; }+ + cr.restore (); } private void display_kerning_value (double k) {@@ -339,7 +344,13 @@ public class KerningDisplay : FontDisplay { } public void set_absolute_kerning (int handle, double val) {- double kern = get_kerning_for_handle (handle);+ double kern;+ + if (MenuTab.suppress_event) {+ return;+ }+ + kern = get_kerning_for_handle (handle); set_kerning (handle, val - kern); } @@ -502,8 +513,13 @@ public class KerningDisplay : FontDisplay { } public override void key_press (uint keyval) {- unichar c = (unichar) keyval;+ unichar c;+ + if (MenuTab.suppress_event) { // don't update kerning while saving font+ return;+ } + c = (unichar) keyval; parse_error = false; if (suppress_input) {@@ -554,6 +570,10 @@ public class KerningDisplay : FontDisplay { Glyph? g; string name; Font f = BirdFont.get_current_font ();++ if (MenuTab.suppress_event) {+ return;+ } if (!is_modifier_key (c) && c.validate ()) { name = f.get_name_for_character (c);@@ -570,10 +590,14 @@ public class KerningDisplay : FontDisplay { public override void motion_notify (double ex, double ey) { double k, y;- ++ if (MenuTab.suppress_event) {+ return;+ }+ if (!moving) { set_active_handle (ex, ey);- } else {+ } else { y = 1; if (Math.fabs (ey - begin_handle_y) > 20) {@@ -581,6 +605,7 @@ public class KerningDisplay : FontDisplay { } k = (ex - last_handle_x) / y; // y-axis is for variable precision+ k /= KerningTools.font_size; set_kerning (selected_handle, k); GlyphCanvas.redraw (); }@@ -597,6 +622,7 @@ public class KerningDisplay : FontDisplay { int i = 0; int row_index = 0; int col_index = 0;+ double fs = KerningTools.font_size; Glyph glyph = new Glyph.no_lines (""); GlyphRange? gr_left, gr_right;@@ -636,7 +662,7 @@ public class KerningDisplay : FontDisplay { kern = get_kerning_for_pair (((!)prev).get_name (), ((!)g).get_name (), gr_left, gr_right); } - d = Math.pow (x + kern - ex, 2) + Math.pow (y - ey, 2);+ d = Math.pow (fs * (x + kern) - ex, 2) + Math.pow (y - ey, 2); if (d < min) { min = d;@@ -678,7 +704,11 @@ public class KerningDisplay : FontDisplay { public void set_kerning_by_text () { TextListener listener; string kerning = @"$(get_kerning_for_handle (selected_handle))";- ++ if (MenuTab.suppress_event) {+ return;+ }+ if (selected_handle == -1) { selected_handle = 0; }@@ -686,8 +716,15 @@ public class KerningDisplay : FontDisplay { listener = new TextListener (t_("Kerning"), kerning, t_("Close")); listener.signal_text_input.connect ((text) => {- string submitted_value = text.replace (",", ".");- double parsed_value = double.parse (submitted_value);+ string submitted_value;+ double parsed_value;+ + if (MenuTab.suppress_event) {+ return;+ }+ + submitted_value = text.replace (",", ".");+ parsed_value = double.parse (submitted_value); set_absolute_kerning (selected_handle, parsed_value); GlyphCanvas.redraw (); });@@ -706,6 +743,10 @@ public class KerningDisplay : FontDisplay { } public override void button_press (uint button, double ex, double ey) {+ if (MenuTab.suppress_event) {+ return;+ }+ set_active_handle (ex, ey); selected_handle = active_handle; begin_handle_x = ex;@@ -716,7 +757,13 @@ public class KerningDisplay : FontDisplay { /** Insert text form clipboard. */ public void add_text (string t) {- int c = t.char_count ();+ int c;+ + if (MenuTab.suppress_event) {+ return;+ }+ + c = t.char_count (); for (int i = 0; i < c; i++) { add_character (t.get_char (i)); }@@ -46,25 +46,55 @@ public class KerningTools : ToolCollection { }); kerning_tools.add_tool (text_kerning); - SpinButton font_size = new SpinButton ("kerning_font_size", t_("Font size "));+ SpinButton font_size1 = new SpinButton ("kerning_font_size_one", t_("Font size ")); - font_size.set_max (9);- font_size.set_min (0.002);- font_size.set_value_round (1);+ font_size1.set_max (9);+ font_size1.set_min (0.1);+ font_size1.set_value_round (0.5); - if (Preferences.get ("kerning_font_size_settings") != "") {- font_size.set_value (Preferences.get ("kerning_font_size_settings"));+ if (Preferences.get ("kerning_font_size_one_settings") != "") {+ font_size1.set_value (Preferences.get ("kerning_font_size_one_settings")); } - font_size.new_value_action.connect ((self) => {+ font_size1.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph ();- KerningTools.font_size = font_size.get_value ();+ KerningTools.font_size = font_size1.get_value ();+ g.update_view ();+ });++ font_size1.new_value_action.connect ((self) => {+ Glyph g = MainWindow.get_current_glyph ();+ KerningTools.font_size = font_size1.get_value ();+ g.update_view ();+ Preferences.set ("kerning_font_size_one_settings", font_size1.get_display_value ());+ });+ + kerning_tools.add_tool (font_size1);++ SpinButton font_size2 = new SpinButton ("kerning_font_size_two", t_("Font size "));++ font_size2.set_max (9);+ font_size2.set_min (0.1);+ font_size2.set_value_round (1);++ if (Preferences.get ("kerning_font_size_two_settings") != "") {+ font_size2.set_value (Preferences.get ("kerning_font_size_two_settings"));+ }++ font_size2.new_value_action.connect ((self) => {+ Glyph g = MainWindow.get_current_glyph ();+ KerningTools.font_size = font_size2.get_value ();+ g.update_view ();+ Preferences.set ("kerning_font_size_two_settings", font_size2.get_display_value ());+ });++ font_size2.select_action.connect ((self) => {+ Glyph g = MainWindow.get_current_glyph ();+ KerningTools.font_size = font_size2.get_value (); g.update_view ();- Preferences.set ("kerning_font_size_settings", font_size.get_display_value ()); }); - // TODO: add font size- // kerning_tools.add_tool (font_size);+ kerning_tools.add_tool (font_size2); kerning_tools.set_persistent (false); kerning_tools.set_unique (false);@@ -16,7 +16,16 @@ namespace BirdFont { public class MenuTab : FontDisplay { - /** Ignore actions when export is in progress. */+ /** Ignore new actions when export is in progress.+ * + * BirdFont runs in a single thread but the glib main loop will still+ * execute events with the idle priority in order to update the + * progress bar while export, save and possibly other actions are + * in progress. + * + * Do always check the return value of set_suppress_event when this+ * variable is updated.+ */ public static bool suppress_event = false; public MenuTab () {@@ -26,15 +35,28 @@ public class MenuTab : FontDisplay { Font font = BirdFont.get_current_font (); if (font.font_file == null) { if (MenuTab.save ()) {- ExportTool.export_all ();+ export_all (); } } else {- ExportTool.export_all ();+ export_all (); } } - public static void set_suppress_event (bool e) {+ public static void export_all () {+ if (set_suppress_event (true)) { + ExportTool.export_all ();+ } else {+ warning ("suppressed event");+ } + }+ + public static bool set_suppress_event (bool e) {+ if (suppress_event && e) {+ warning ("suppress_event is already set");+ return false;+ } suppress_event = e;+ return true; } public override string get_label () {@@ -62,7 +84,7 @@ public class MenuTab : FontDisplay { string f; bool saved = false; Font font = BirdFont.get_current_font ();-+ if (suppress_event) { return false; }@@ -80,19 +102,23 @@ public class MenuTab : FontDisplay { save (); saved = true; }- return saved; } public static bool save () {- Font f = BirdFont.get_current_font ();+ Font f; string fn; bool saved = false; if (suppress_event) { return false;+ } + + if (!set_suppress_event (true)) {+ return false; } + f = BirdFont.get_current_font (); f.delete_backup (); fn = f.get_path ();@@ -110,7 +136,9 @@ public class MenuTab : FontDisplay { f.save (fn); saved = true;+ set_suppress_event (false); } else {+ set_suppress_event (false); saved = save_as (); } @@ -235,12 +263,21 @@ public class MenuTab : FontDisplay { } public static void show_kerning_context () {+ if (suppress_event) {+ return;+ }+ KerningDisplay kd = MainWindow.get_kerning_display (); MainWindow.get_tab_bar ().add_unique_tab (kd); } public static void preview () {- Font font = BirdFont.get_current_font (); + Font font = BirdFont.get_current_font ();+ + if (suppress_event) {+ return;+ }+ if (font.font_file == null) { if (MenuTab.save ()) { show_preview_tab ();@@ -273,10 +310,18 @@ public class MenuTab : FontDisplay { /** Display the language selection tab. */ public static void select_language () {+ if (suppress_event) {+ return;+ }+ MainWindow.get_tab_bar ().add_unique_tab (new LanguageSelectionTab ()); } public static void use_current_glyph_as_background () {+ if (suppress_event) {+ return;+ }+ Glyph.background_glyph = MainWindow.get_current_glyph (); if (MainWindow.get_current_display () is OverView) {@@ -289,11 +334,19 @@ public class MenuTab : FontDisplay { } public static void remove_all_kerning_pairs () {+ if (suppress_event) {+ return;+ }+ KerningClasses.get_instance ().remove_all_pairs (); KerningTools.update_kerning_classes (); } public static void list_all_kerning_pairs () {+ if (suppress_event) {+ return;+ }+ MainWindow.get_tab_bar ().add_unique_tab (new KerningList ()); } }@@ -64,7 +64,7 @@ public class PreviewTools : ToolCollection { suppress_event = true; ExportTool.export_ttf_font_sync (); ExportTool.export_svg_font ();- TooltipArea.show_text (t_("Three font files has been created.")); + TooltipArea.show_text (t_("Three font files have been created.")); suppress_event = false; } }@@ -44,7 +44,7 @@ class TestCases { add (test_preview, "Preview"); add (test_kerning, "Kerning"); add (test_boundaries, "Boundaries");- + add_bechmark (benchmark_stroke, "Stroke"); } @@ -33,9 +33,7 @@ public class TooltipArea : GLib.Object { void progress () { redraw ();- MenuTab.set_suppress_event (true); Tool.yield ();- MenuTab.set_suppress_event (false); } public void update_text () {