The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Merge branch 'master' of https://github.com/johanmattssonm/birdfont into HEAD

These changes was commited to the Birdfont repository Fri, 20 Mar 2015 12:51:56 +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>
Fri, 20 Mar 2015 12:51:56 +0000 (13:51 +0100)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Fri, 20 Mar 2015 12:51:56 +0000 (13:51 +0100)
commit ec89776d0bb79e20ad4d3bb6f4a8beafd9fbd115
tree 7a9814296fbd1b579da907245a56731ec9059c84
parent 5767b833660124a4461ca0ede288877df3d1ad9f
parent d67f84d334c3c696cab7eadcdd4c90aca014f176
Merge branch 'master' of https://github.com/johanmattssonm/birdfont into HEAD

20 files changed:
libbirdfont/BirdFontFile.vala
libbirdfont/ClickMap.vala
libbirdfont/Font.vala
libbirdfont/ForesightTool.vala
libbirdfont/Glyph.vala
libbirdfont/KerningClasses.vala
libbirdfont/KerningRange.vala
libbirdfont/KerningTools.vala
libbirdfont/Line.vala
libbirdfont/Menu.vala
libbirdfont/MenuTab.vala
libbirdfont/OpenFontFormat/GsubTable.vala
libbirdfont/OpenFontFormat/KernList.vala
libbirdfont/Path.vala
libbirdfont/PenTool.vala
libbirdfont/Renderer/TextArea.vala
libbirdfont/Row.vala
libbirdfont/SpacingData.vala
libbirdfont/TabContent.vala
--- a/libbirdfont/BirdFontFile.vala +++ b/libbirdfont/BirdFontFile.vala @@ -923,13 +923,13 @@ } if (range_left.get_length () > 1) { - kerning_range = new KerningRange (); + kerning_range = new KerningRange (font); kerning_range.set_ranges (range_left.get_all_ranges ()); KerningTools.add_unique_class (kerning_range); } if (range_right.get_length () > 1) { - kerning_range = new KerningRange (); + kerning_range = new KerningRange (font); kerning_range.set_ranges (range_right.get_all_ranges ()); KerningTools.add_unique_class (kerning_range); }
--- a/libbirdfont/ClickMap.vala +++ b/libbirdfont/ClickMap.vala @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Johan Mattsson + 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 @@ -11,180 +11,60 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ + + using Cairo; namespace BirdFont { - // This is a refcounted container in order to avoid double free - // corruption in lambda functions. public class ClickMap : GLib.Object { - char* map; + ImageSurface map; int width; - int margin; - int map_size; - + public ClickMap (int width) { this.width = width; - margin = 10; - map_size = width + margin; - map = malloc (map_size * map_size); + map = new Cairo.ImageSurface (Cairo.Format.ARGB32, width, width); } - - ~ClickMap () { - delete map; - } - - public char get_value (int x, int y) { - if (unlikely (!(0 <= x < map_size && 0 <= y < map_size))) { + public bool get_value (int x, int y) { + unowned uchar[] d = map.get_data (); + bool transparent; + + if (unlikely (!(0 <= x < width && 0 <= y < width))) { warning ("Array index out of bounds."); - return '\0'; + return true; } - return map[y * width + x]; + transparent = d[y * map.get_stride () + 4 * x + 3] == 0; + + return !transparent; } - - public void set_value (int x, int y, char val) { - if (unlikely (!(0 <= x < map_size && 0 <= y < map_size))) { - warning ("Array index out of bounds."); - return; - } - map[y * width + x] = val; - } + public void create_click_map (Path path) { + double w, h; + Context c; + + c = new Context (map); + + c.save (); + + c.set_source_rgba (0, 0, 0, 1); + c.new_path (); - private void map_outline (Path path) { path.all_of_path ((cx, cy, ct) => { int px = (int) (width * ((cx - path.xmin) / (path.xmax - path.xmin))); int py = (int) (width * ((cy - path.ymin) / (path.ymax - path.ymin))); - set_value (px, py, '#'); + c.line_to (px, py); return true; }, 2 * width); - } - - private void close_outline (Path path) { - // first to last point in case the path is open - Path.all_of (path.get_last_point (), path.get_first_point (), (cx, cy, ct) => { - int px = (int) (width * ((cx - path.xmin) / (path.xmax - path.xmin))); - int py = (int) (width * ((cy - path.ymin) / (path.ymax - path.ymin))); - - set_value (px, py, '#'); - - return true; - }, 2 * width); - } - - public void create_click_map (Path path) { - // Clear the map - for (int i = 0; i < map_size; i++) { - for (int j = 0; j < map_size; j++) { - set_value (i, j, '\0'); - } - } - // Create outline - map_outline (path); - close_outline (path); + c.close_path (); + c.fill (); - // Fill the map - for (int j = 0; j < width; j++) { - for (int k = 0; k < width; k++) { - if (get_value (k, j) == '#') { - - k++; - while (k < width && get_value (k, j) == '#') { - k++; - } - - while (k < width && get_value (k, j) == '\0') { - set_value (k, j, 'o'); - k++; - } - - k++; - while (k < width && get_value (k, j) == '#') { - k++; - } - } - } - } - - // Remove fill from the out side - for (int k = 0; k < width; k++) { - - if (get_value (k, 0) == 'o') { - set_value (k, 0, '\0'); - } - - for (int l = width - 1; l >= 0; l--) { - if (get_value (k, l) != '#') { - if (get_value (k, l + 1) == '\0') { - set_value (k, l, '\0'); - } - - if (get_value (k, l + 1) == 'o') { - set_value (k, l, 'o'); - } - } - } - } - - for (int k = 0; k < width; k++) { - if (get_value (0, k) == 'o') { - set_value (0, k,'\0'); - } - - for (int l = width - 1; l >= 0; l--) { - if (get_value (l, k) != '#') { - if (get_value (l + 1, k) == '\0') { - set_value (l, k, '\0'); - } - - if (get_value (l + 1, k) == 'o') { - set_value (l, k, 'o'); - } - } - } - } - - for (int k = width - 1; k > 0; k--) { - if (get_value (k, 0) == 'o') { - set_value (k, 0,'\0'); - } - - for (int l = width - 1; l >= 0; l--) { - if (get_value (k, l) != '#') { - if (get_value (k, l + 1) == 'o') { - set_value (k, l, 'o'); - } - } - } - } - } - - public void print () { - char c; - for (int i = width - 1; i >= 0; i--) { - for (int j = 0; j < width; j++) { - c = get_value (j, i); - if (c == '\0') { - stdout.printf (" "); - } else if (c == '#') { - stdout.printf ("#"); - } else if (c == 'o') { - stdout.printf ("o"); - } else if (c == 'X') { - stdout.printf ("X"); - } else { - stdout.printf ("?"); - } - } - - stdout.printf ("\n"); - } + c.restore (); } } }
--- a/libbirdfont/Font.vala +++ b/libbirdfont/Font.vala @@ -87,7 +87,7 @@ /** File format. */ public FontFormat format = FontFormat.BIRDFONT; - SpacingData spacing; + public SpacingData spacing; bool read_only = false;
--- a/libbirdfont/ForesightTool.vala +++ b/libbirdfont/ForesightTool.vala @@ -94,11 +94,9 @@ ps = new PointSelection (PenTool.active_path.points.get (PenTool.active_path.points.size - 1), PenTool.active_path); ps.point.set_tie_handle (false); - ps.point.convert_to_curve (); ps = new PointSelection (PenTool.active_path.points.get (0), PenTool.active_path); ps.point.set_tie_handle (false); - ps.point.convert_to_curve (); first_point = PenTool.active_path.points.get (0); clockwise = PenTool.active_path.is_clockwise (); @@ -197,6 +195,7 @@ return; } last = PenTool.selected_points.get (PenTool.selected_points.size - 1); + last.point.convert_to_curve (); } PenTool.move_selected_handle = true;
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -186,13 +186,13 @@ return active_paths.get (active_paths.size - 1); } - public void boundaries (out double x1, out double y1, out double x2, out double y2) { + public bool boundaries (out double x1, out double y1, out double x2, out double y2) { if (path_list.size == 0) { x1 = 0; y1 = 0; x2 = 0; y2 = 0; - return; + return false; } x1 = double.MAX; @@ -221,6 +221,8 @@ } } } + + return x1 != double.MAX; } public void selection_boundaries (out double x, out double y, out double w, out double h) { @@ -484,8 +486,7 @@ public double get_left_side_bearing () { double x1, y1, x2, y2; - if (path_list.size > 0 && path_list.get (0).points.size > 0) { - boundaries (out x1, out y1, out x2, out y2); + if (boundaries (out x1, out y1, out x2, out y2)) { return x1 - left_limit; } else { return right_limit - left_limit; @@ -495,8 +496,7 @@ public double get_right_side_bearing () { double x1, y1, x2, y2; - if (path_list.size > 0 && path_list.get (0).points.size > 0) { - boundaries (out x1, out y1, out x2, out y2); + if (boundaries (out x1, out y1, out x2, out y2)) { return right_limit - x2; } else { return right_limit - left_limit;
--- a/libbirdfont/KerningClasses.vala +++ b/libbirdfont/KerningClasses.vala @@ -50,6 +50,30 @@ single_kerning_letters_right = new Gee.ArrayList<string> (); single_kerning = new HashMap<string, double?> (); + } + + public void update_range (GlyphRange old, GlyphRange new_range) { + string o = old.get_all_ranges (); + + foreach (GlyphRange gr in classes_first) { + try { + if (gr.get_all_ranges () == o) { + gr.parse_ranges (new_range.get_all_ranges ()); + } + } catch (GLib.MarkupError e) { + warning (e.message); + } + } + + foreach (GlyphRange gr in classes_last) { + try { + if (gr.get_all_ranges () == o) { + gr.parse_ranges (new_range.get_all_ranges ()); + } + } catch (GLib.MarkupError e) { + warning (e.message); + } + } } /** Class based gpos kerning. */ @@ -492,7 +516,6 @@ // add the right hand glyph and the kerning value foreach (Glyph character in left_glyphs) { KerningPair kl = new KerningPair (character); - pairs.add (kl); foreach (GlyphRange r in classes_last) { foreach (UniRange u in r.ranges) { @@ -523,6 +546,15 @@ } } + if (kl.kerning.size > 0) { + pairs.add (kl); + } + + if (kl.kerning.size == 0) { + warning (@"No kerning pairs for character: $((kl.character.get_name ()))"); + } + + kl.sort (); }
--- a/libbirdfont/KerningRange.vala +++ b/libbirdfont/KerningRange.vala @@ -22,9 +22,13 @@ public string ranges = ""; public GlyphRange glyph_range; bool malformed = false; + Font font; - public KerningRange (string? name = null, string tip = "") { + public KerningRange (Font f, string? name = null, string tip = "") { base (null , tip); + + font = f; + glyph_range = new GlyphRange (); if (name != null) { @@ -57,7 +61,6 @@ public void set_ranges (string r) { GlyphRange glyph_range = new GlyphRange (); - Font font = BirdFont.get_current_font (); SpacingData spacing = font.get_spacing (); string new_range; string ch; @@ -90,12 +93,19 @@ } private void set_one_range (string r) throws MarkupError { + GlyphRange old = new GlyphRange (); + + old.parse_ranges (ranges); + old.set_class (true); + ranges = r; name = r; glyph_range.empty (); glyph_range.parse_ranges (r); glyph_range.set_class (true); + + font.spacing.kerning_classes.update_range (old, glyph_range); } public void update_kerning_classes () { @@ -124,22 +134,24 @@ public override void draw (Context cr) { double xt, yt; + Text label_text; xt = x + 5; yt = y + 10; cr.save (); - // FIXME: use color to indicate error - Theme.color (cr, "Foreground 1"); + label_text = new Text (); + label_text.set_text (name); + Theme.text_color (label_text, "Foreground 2"); + label_text.set_font_size (18); + label_text.widget_x = x; + label_text.widget_y = y; + label_text.draw (cr); - cr.set_font_size (10); - cr.select_font_face ("Cantarell", FontSlant.NORMAL, FontWeight.NORMAL); - cr.move_to (xt, yt); - cr.show_text (name); cr.restore (); } } }
--- a/libbirdfont/KerningTools.vala +++ b/libbirdfont/KerningTools.vala @@ -54,7 +54,10 @@ Tool new_kerning_class = new Tool ("kerning_class", t_("Create new kerning class.")); new_kerning_class.select_action.connect ((self) => { - classes.add_tool (new KerningRange (@"Kerning class $(++next_class)")); + Font font = BirdFont.get_current_font (); + string label = t_("Kerning class"); + KerningRange kr = new KerningRange (font, @"$label $(++next_class)"); + classes.add_tool (kr); Toolbox.redraw_tool_box (); }); kerning_tools.add_tool (new_kerning_class); @@ -131,7 +134,8 @@ } public static void update_kerning_classes () { - KerningClasses k = BirdFont.get_current_font ().get_kerning_classes (); + Font font = BirdFont.get_current_font (); + KerningClasses k = font.get_kerning_classes (); KerningRange kr; GlyphRange r; int i; @@ -141,14 +145,14 @@ for (i = 0; i < k.classes_first.size; i++) { r = k.classes_first.get (i); if (r.is_class ()) { - kr = new KerningRange (); + kr = new KerningRange (font); kr.set_ranges (r.get_all_ranges ()); add_unique_class (kr); } r = k.classes_last.get (i); if (r.is_class ()) { - kr = new KerningRange (); + kr = new KerningRange (font); kr.set_ranges (r.get_all_ranges ()); add_unique_class (kr); }
--- a/libbirdfont/Line.vala +++ b/libbirdfont/Line.vala @@ -172,16 +172,7 @@ } void redraw_line () { - double p; - Glyph g = MainWindow.get_current_glyph (); - - if (vertical) { - p = Glyph.reverse_path_coordinate_x (pos); - queue_draw_area ((int)p - 100, 0, 200, g.allocation.height); - } else { - p = Glyph.reverse_path_coordinate_y (pos); - queue_draw_area (0, (int)p - 100, g.allocation.width, 300); - } + GlyphCanvas.redraw (); } public void move_line_to (int x, int y, WidgetAllocation allocation) {
--- a/libbirdfont/Menu.vala +++ b/libbirdfont/Menu.vala @@ -441,7 +441,7 @@ show_menu = false; }); menu.items.add (description); - + current_menu = menu; top_menu = menu; allocation = new WidgetAllocation (); @@ -465,7 +465,7 @@ display = current_display.get_name (); - if (!(display == "Kerning" && item.modifiers == NONE)) { + if (!(display == "Kerning" && display == "Spacing" && display != "Preview" && item.modifiers == NONE)) { if (!SettingsDisplay.update_key_bindings && (item.display == "" || item.display == display)) { item.action (); @@ -476,8 +476,10 @@ if (!tm.tool.is_tool_modifier) { MainWindow.get_toolbox ().set_current_tool (tm.tool); + return; } else { tm.tool.select_action (tm.tool); + return; } } }
--- a/libbirdfont/MenuTab.vala +++ b/libbirdfont/MenuTab.vala @@ -360,6 +360,7 @@ } dialog.overwrite_signal.connect (() => { + KeyBindings.set_modifier (NONE); tab_bar.add_unique_tab (new Preview (), true); PreviewTools.update_preview (); }); @@ -465,6 +466,11 @@ } public static void simplify_path () { + if (suppress_event) { + warn_if_test ("Event suppressed"); + return; + } + Task t = new Task (); t.task.connect (simplify); MainWindow.native_window.run_background_thread (t);
--- a/libbirdfont/OpenFontFormat/GsubTable.vala +++ b/libbirdfont/OpenFontFormat/GsubTable.vala @@ -79,7 +79,7 @@ // lookup table fd.add_ushort (1); // number of lookups FIXME: should be 3 - fd.add_ushort (8); // offset to lookup 1 + fd.add_ushort (4); // offset to lookup 1 FIXME: should be 8 //fd.add_ushort (16); // offset to lookup 2 //fd.add_ushort (24); // offset to lookup 3 @@ -87,7 +87,7 @@ fd.add_ushort (4); // lookup type fd.add_ushort (0); // lookup flags fd.add_ushort (1); // number of subtables - fd.add_ushort (24 + length); // array of offsets to subtable + fd.add_ushort (8 + length); // array of offsets to subtable FIXME: should be 24 length += (uint16) clig_subtable.length_with_padding (); /*
--- a/libbirdfont/OpenFontFormat/KernList.vala +++ b/libbirdfont/OpenFontFormat/KernList.vala @@ -57,7 +57,7 @@ pairs.add (current_pairs); if (unlikely (kerning_pair.kerning.size == 0)) { - warning ("No pairs."); + warning (@"No kerning pairs for character: $((kerning_pair.character.get_name ()))"); } i = 0;
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -736,7 +736,6 @@ /** Variable precision */ public bool is_over_coordinate_var (double x, double y) { PathList pathlist; - bool in_path = false; int width; ClickMap click_map; int px, py; @@ -774,11 +773,7 @@ click_x = (int) (width * ((x - xmin) / (xmax - xmin))); click_y = (int) (width * ((y - ymin) / (ymax - ymin))); - in_path = click_map.get_value (click_x, click_y) != '\0'; - - click_map.set_value (click_x, click_y, 'X'); - - return in_path; + return click_map.get_value (click_x, click_y); } public bool is_over_boundry (double x, double y) {
--- a/libbirdfont/PenTool.vala +++ b/libbirdfont/PenTool.vala @@ -125,7 +125,9 @@ move_action (this, x, y); - press (b, x, y, false); + if (!has_join_icon ()) { + press (b, x, y, false); + } if (BirdFont.android) { point_selection_image = true; @@ -157,7 +159,7 @@ x = Glyph.path_coordinate_x (ix); y = Glyph.path_coordinate_y (iy); - + if (has_join_icon ()) { join_paths (x, y); } @@ -195,7 +197,7 @@ move_action.connect ((self, x, y) => { selection_box_last_x = x; selection_box_last_y = y; - + if (Path.distance (begin_action_x, x, begin_action_y, y) > 10 * MainWindow.units) { point_selection_image = false; } @@ -1013,7 +1015,9 @@ Path union, second_path; EditPoint first_point; int px, py; - + bool last_segment_is_line; + bool first_segment_is_line; + if (glyph.path_list.size == 0) { return; } @@ -1024,11 +1028,13 @@ return; } path = (!) p; - + if (!path.is_open ()) { warning ("Path is closed."); return; } + + return_if_fail (path.points.size > 1); if (active_edit_point == path.points.get (0)) { path.reverse (); @@ -1049,6 +1055,10 @@ py = Glyph.reverse_path_coordinate_y (((!) active_edit_point).y); if (is_endpoint ((!) active_edit_point) && is_close_to_point (path.points.get (0), px, py)) { + + last_segment_is_line = path.get_last_point ().get_left_handle ().is_line (); + first_segment_is_line = path.get_first_point ().get_right_handle ().is_line (); + // TODO: set point type path.points.get (0).left_handle.move_to_coordinate ( path.points.get (path.points.size - 1).left_handle.x, @@ -1068,6 +1078,16 @@ path.close (); glyph.close_path (); + + if (last_segment_is_line) { + path.get_first_point ().get_left_handle ().convert_to_line (); + path.get_first_point ().recalculate_linear_handles (); + } + + if (first_segment_is_line) { + path.get_first_point ().get_right_handle ().convert_to_line (); + path.get_first_point ().recalculate_linear_handles (); + } force_direction (); @@ -1077,6 +1097,7 @@ } remove_all_selected_points (); + return; }
--- a/libbirdfont/Renderer/TextArea.vala +++ b/libbirdfont/Renderer/TextArea.vala @@ -130,21 +130,21 @@ add_character (keyval); break; case 'a': - if (KeyBindings.has_ctrl ()) { + if (KeyBindings.has_ctrl () || KeyBindings.has_logo ()) { select_all (); } else { add_character (keyval); } break; case 'c': - if (KeyBindings.has_ctrl ()) { + if (KeyBindings.has_ctrl () || KeyBindings.has_logo ()) { ClipTool.copy_text (this); } else { add_character (keyval); } break; case 'v': - if (KeyBindings.has_ctrl ()) { + if (KeyBindings.has_ctrl () || KeyBindings.has_logo ()) { ClipTool.paste_text (this); store_undo_state_at_next_event = true; } else { @@ -152,14 +152,14 @@ } break; case 'y': - if (KeyBindings.has_ctrl ()) { + if (KeyBindings.has_ctrl () || KeyBindings.has_logo ()) { redo (); } else { add_character (keyval); } break; case 'z': - if (KeyBindings.has_ctrl ()) { + if (KeyBindings.has_ctrl () || KeyBindings.has_logo ()) { undo (); } else { add_character (keyval); @@ -811,8 +811,8 @@ } if (unlikely (c.paragraph < 0)) { - c.paragraph = 0; - c.character_index = 0; + c.paragraph = paragraphs.size > 0 ? paragraphs.size - 1 : 0; + c.character_index = paragraphs.size > 0 ? paragraphs.get (c.paragraph).text.length : 0; } store_undo_state_at_next_event = true;
--- a/libbirdfont/Row.vala +++ b/libbirdfont/Row.vala @@ -20,7 +20,7 @@ int index = 0; bool delete_button = true; - Gee.ArrayList<string> columns_labels = new Gee.ArrayList<string> (); + public Gee.ArrayList<string> columns_labels = new Gee.ArrayList<string> (); GLib.Object? row_data = null; public int columns {
--- a/libbirdfont/SpacingData.vala +++ b/libbirdfont/SpacingData.vala @@ -21,7 +21,7 @@ public KerningClasses kerning_classes; public Gee.ArrayList<SpacingClass> classes = new Gee.ArrayList<SpacingClass> (); - Gee.ArrayList<String> connections = new Gee.ArrayList<String> (); + Gee.ArrayList<string> connections = new Gee.ArrayList<string> (); public SpacingData (KerningClasses kerning) { kerning_classes = kerning; @@ -32,15 +32,14 @@ } public Gee.ArrayList<string> get_all_connections (string glyph) { - String s; Gee.ArrayList<string> c = new Gee.ArrayList<string> (); connections.clear (); add_connections (glyph); - foreach (String t in connections) { - c.add (t.data.dup ()); + foreach (string t in connections) { + c.add (t.dup ()); } connections.clear (); @@ -49,8 +48,8 @@ } bool has_connection (string s) { - foreach (String t in connections) { - if (t.data == s) { + foreach (string t in connections) { + if (t == s) { return true; } } @@ -59,7 +58,7 @@ } public void add_connections (string glyph) { - String sb = new String (glyph); + string sb = glyph; connections.add (sb); @@ -118,17 +117,8 @@ } KerningTools.update_spacing_classes (); - } - - class String : GLib.Object { - - public string data; - - public String (string s) { - data = s.dup (); - } } } }
--- a/libbirdfont/TabContent.vala +++ b/libbirdfont/TabContent.vala @@ -23,6 +23,7 @@ static LineTextArea text_input; static Button text_input_button; static bool text_input_visible = false; + static TextListener text_callback; static const int TEXT_INPUT_HEIGHT = 51; @@ -319,6 +320,8 @@ } 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);