Commit 9b3c1ae
Ligatures and a fix for the kerning bug
Changed files (12)
modifiedbirdfont/GtkWindow.valamodifiedlibbirdfont/KerningDisplay.valadeletedlibbirdfont/KerningPair.valaaddedlibbirdfont/LigatureList.valaaddedlibbirdfont/Ligatures.valamodifiedlibbirdfont/MainWindow.valamodifiedlibbirdfont/MenuTab.valamodifiedlibbirdfont/OpenFontFormat/DirectoryTable.valamodifiedlibbirdfont/OpenFontFormat/GposTable.valamodifiedlibbirdfont/OpenFontFormat/Gsub.valamodifiedlibbirdfont/OpenFontFormat/KernList.valaaddedlibbirdfont/OpenFontFormat/KerningPair.vala
Diff
@@ -415,6 +415,7 @@ public class GtkWindow : Gtk.Window, NativeWindow { Gtk.Menu tool_menu = new Gtk.Menu (); Gtk.Menu kerning_menu = new Gtk.Menu (); Gtk.Menu git_menu = new Gtk.Menu ();+ Gtk.Menu ligature_menu = new Gtk.Menu (); AccelGroup accel_group = new Gtk.AccelGroup(); add_accel_group (accel_group);@@ -709,6 +710,13 @@ public class GtkWindow : Gtk.Window, NativeWindow { save_as_bfp.activate.connect (() => { MenuTab.save_as_bfp (); });++ // Ligatures+ Gtk.MenuItem show_ligatures = new Gtk.MenuItem.with_mnemonic (t_("_Show Ligatures"));+ ligature_menu.append (show_ligatures);+ show_ligatures.activate.connect (() => { + MenuTab.show_ligature_tab ();+ }); // Add menus Gtk.MenuItem file_launcher = new Gtk.MenuItem.with_mnemonic (t_("_File"));@@ -728,7 +736,10 @@ public class GtkWindow : Gtk.Window, NativeWindow { Gtk.MenuItem git_launcher = new Gtk.MenuItem.with_mnemonic ("_Git"); git_launcher.set_submenu (git_menu);- ++ Gtk.MenuItem ligature_launcher = new Gtk.MenuItem.with_mnemonic ("_Ligatures");+ ligature_launcher.set_submenu (ligature_menu);+ menubar.append (file_launcher); menubar.append (edit_launcher); menubar.append (tab_launcher);@@ -737,6 +748,7 @@ public class GtkWindow : Gtk.Window, NativeWindow { if (BirdFont.has_argument ("--test")) { menubar.append (git_launcher);+ menubar.append (ligature_launcher); } return menubar; @@ -443,7 +443,6 @@ public class KerningDisplay : FontDisplay { public override void selected_canvas () { Glyph g; GlyphSequence w;- unowned List<GlyphSequence>? r; StringBuilder s = new StringBuilder (); bool append_char = false; Font font = BirdFont.get_current_font ();deleted file mode 100644@@ -1,50 +0,0 @@-/*- Copyright (C) 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 - License, or (at your option) any later version.-- This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details.-*/--using Cairo;-using Xml;--namespace BirdFont {--/** A list of all kerning pairs for one glyph. */-public class KerningPair : GLib.Object {- public Glyph character;- public Gee.ArrayList<Kerning> kerning;-- Gee.ArrayList<Glyph> right; // FIXME: should be fast and sorted- - public KerningPair (Glyph left) {- character = left;- right = new Gee.ArrayList<Glyph> ();- kerning = new Gee.ArrayList<Kerning> ();- }- - public void add_unique (Glyph g, double k) {- if (right.contains ((!) g)) {- right.add ((!) g);- kerning.add (new Kerning.for_glyph (g, k));- }- }- - public void sort () {- kerning.sort ((a, b) => {- Kerning first, next;- first = (Kerning) a;- next = (Kerning) b;- return strcmp (((!)first.glyph).get_unichar_string (), ((!)next.glyph).get_unichar_string ());- }); - }-}- -}new file mode 100644@@ -0,0 +1,149 @@+/*+ Copyright (C) 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 + License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details.+*/++using Cairo;+using Math;++namespace BirdFont {++public class LigatureList : FontDisplay {+ + Ligatures ligatures;+ + int scroll = 0;+ int visible_rows = 0;+ WidgetAllocation allocation;+ + public LigatureList () {+ allocation = new WidgetAllocation ();+ ligatures = new Ligatures ();+ }++ public override void draw (WidgetAllocation allocation, Context cr) {+ int y = 20;+ int s = 0;+ bool color = (scroll % 2) == 0;+ + this.allocation = allocation;+ + visible_rows = (int) (allocation.height / 18.0);+ + cr.save ();+ cr.set_source_rgba (1, 1, 1, 1);+ cr.rectangle (0, 0, allocation.width, allocation.height);+ cr.fill ();+ cr.restore ();+ + cr.save ();+ cr.set_source_rgba (0.3, 0.3, 0.3, 1);+ cr.set_font_size (12);++ ligatures.get_ligatures ((substitution, ligature) => {+ if (s++ >= scroll) {+ draw_row (allocation, cr, substitution, ligature, y, color);+ y += 18;+ color = !color;+ }+ });+ + cr.restore ();+ } ++ private static void draw_row (WidgetAllocation allocation, Context cr,+ string substitution, string ligature, int y, bool color) {++ if (color) {+ cr.save ();+ cr.set_source_rgba (224/255.0, 224/255.0, 224/255.0, 1);+ cr.rectangle (0, y - 14, allocation.width, 18);+ cr.fill ();+ cr.restore ();+ }+ + cr.move_to (30, y);+ cr.show_text (substitution);+ cr.move_to (230, y);+ cr.show_text (ligature);+ }++ public override string get_label () {+ return t_("Ligatures");+ }++ public override string get_name () {+ return "Ligatures";+ }++ public override bool has_scrollbar () {+ return true;+ }+ + public override void scroll_wheel_down (double x, double y) {+ uint liga = ligatures.count ();+ scroll += 3;++ if (scroll > liga - visible_rows) {+ scroll = (int) (liga - visible_rows);+ }+ + if (visible_rows > liga) {+ scroll = 0;+ } + + update_scrollbar ();+ redraw_area (0, 0, allocation.width, allocation.height);+ }+ + public override void scroll_wheel_up (double x, double y) {+ scroll -= 3;+ + if (scroll < 0) {+ scroll = 0;+ }+ + update_scrollbar ();+ redraw_area (0, 0, allocation.width, allocation.height);+ }++ public override void selected_canvas () {+ update_scrollbar ();+ redraw_area (0, 0, allocation.width, allocation.height);+ }+ + public void update_scrollbar () {+ uint rows = ligatures.count ();++ if (rows == 0 || visible_rows == 0) {+ MainWindow.set_scrollbar_size (0);+ MainWindow.set_scrollbar_position (0);+ } else {+ MainWindow.set_scrollbar_size ((double) visible_rows / rows);+ MainWindow.set_scrollbar_position ((double) scroll / rows);+ }+ }++ public override void scroll_to (double percent) {+ uint liga = ligatures.count ();+ scroll = (int) (percent * liga);+ + if (scroll > liga - visible_rows) {+ scroll = (int) (liga - visible_rows);+ }+ + redraw_area (0, 0, allocation.width, allocation.height);+ }+}++}+new file mode 100644@@ -0,0 +1,36 @@+/*+ Copyright (C) 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 + License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details.+*/++using Cairo;+using Math;++namespace BirdFont {++public class Ligatures : GLib.Object {+ + public delegate void LigatureIterator (string substitution, string ligature);++ public Ligatures () {+ }++ public void get_ligatures (LigatureIterator iter) {+ iter ("f i", "fi");+ }+ + public int count () {+ return 1;+ }+}++}@@ -27,6 +27,7 @@ public class MainWindow { public static NativeWindow native_window; public static KerningDisplay kerning_display; public static CharDatabase character_database; + public static LigatureList ligature_display; public MainWindow () { singleton = this; @@ -40,6 +41,7 @@ public class MainWindow { over_view = new OverView(); kerning_display = new KerningDisplay (); character_database = new CharDatabase (); + ligature_display = new LigatureList (); } public static FileTab get_recent_files_tab () {@@ -198,6 +200,10 @@ public class MainWindow { public static KerningDisplay get_kerning_display () { return kerning_display; } + + public static LigatureList get_ligature_display () { + return ligature_display; + } } } @@ -333,6 +333,16 @@ public class MenuTab : FontDisplay { KerningDisplay kd = MainWindow.get_kerning_display (); MainWindow.get_tab_bar ().add_unique_tab (kd); }++ public static void show_ligature_tab () {+ if (suppress_event) {+ warn_if_test ("Event suppressed");+ return;+ }+ + LigatureList d = MainWindow.get_ligature_display ();+ MainWindow.get_tab_bar ().add_unique_tab (d);+ } public static void preview () { Font font = BirdFont.get_current_font ();@@ -23,6 +23,7 @@ public class DirectoryTable : Table { public GdefTable gdef_table; public GlyfTable glyf_table; public GposTable gpos_table;+ public GsubTable gsub_table; public HeadTable head_table; public HheaTable hhea_table; public HmtxTable hmtx_table;@@ -44,6 +45,7 @@ public class DirectoryTable : Table { gasp_table = new GaspTable (); gdef_table = new GdefTable (); glyf_table = new GlyfTable (loca_table);+ gsub_table = new GsubTable (glyf_table); cmap_table = new CmapTable (glyf_table); cvt_table = new CvtTable (); head_table = new HeadTable (glyf_table);@@ -64,6 +66,7 @@ public class DirectoryTable : Table { glyf_table.process (); gasp_table.process (); gdef_table.process ();+ gsub_table.process (); cmap_table.process (glyf_table); cvt_table.process (); hmtx_table.process ();@@ -87,6 +90,10 @@ public class DirectoryTable : Table { tables.append (this); tables.append (gpos_table);+ + // FIXME: implement it+ // tables.append (gsub_table);+ tables.append (os_2_table); // tables.append (gdef_table); // invalid table@@ -258,7 +258,7 @@ public class GposTable : Table { } public uint pairs_offset_length () {- return 2 * pairs.pairs.length ();+ return 2 * pairs.pairs.size; } } @@ -1,5 +1,5 @@ /*- Copyright (C) 2012, 2013 Johan Mattsson+ Copyright (C) 2012, 2013, 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 @@ -17,8 +17,10 @@ namespace BirdFont { public class GsubTable : Table { - public GsubTable () {- id = "GPOS";+ GlyfTable glyf_table;+ + public GsubTable (GlyfTable glyf_table) {+ this.glyf_table = glyf_table; } public override void parse (FontData dis) throws Error {@@ -35,7 +37,7 @@ public class GsubTable : Table { // script list fd.add_ushort (1); // number of items in script list fd.add_tag ("DFLT"); // default script- fd.add_ushort (8); // offset to script table from script list+ fd.add_ushort (8); // offset to script table from script list // script table fd.add_ushort (4); // offset to default language system@@ -61,14 +63,27 @@ public class GsubTable : Table { fd.add_ushort (1); // number of lookups fd.add_ushort (4); // offset to lookup 1 - fd.add_ushort (2); // lookup type // FIXME - fd.add_ushort (0); // lookup flags- fd.add_ushort (1); // number of subtables- fd.add_ushort (8); // array of offsets to subtables+ // ligature substitution+ fd.add_ushort (1); // lookup type, format identifier+ fd.add_ushort (20); // offset to coverage+ fd.add_ushort (1); // number of ligature set tables+ fd.add_ushort (10); // array of offsets to ligature sets+ + // ligature sets+ fd.add_ushort (1); // number of offsets+ fd.add_ushort (4); // offset to ligature table+ + // ligatures+ fd.add_ushort ((uint16) glyf_table.get_gid ("fi")); // gid of ligature+ fd.add_ushort (2); // number of components+ fd.add_ushort ((uint16) glyf_table.get_gid ("f")); // gid to component + fd.add_ushort ((uint16) glyf_table.get_gid ("i")); // gid to component + + // coverage+ fd.add_ushort (1); // format+ fd.add_ushort (1); // num glyphs+ fd.add_ushort ((uint16) glyf_table.get_gid ("f")); // gid - // MarkFilteringSet -- //fd.append (get_clig_data ()); fd.pad (); this.font_data = fd;@@ -15,7 +15,7 @@ namespace BirdFont { public class KernList : GLib.Object {- public List<PairFormat1> pairs;+ public Gee.ArrayList<PairFormat1> pairs; public delegate void KernIterator (Kern k); public delegate void PairFormat1Iterator (PairFormat1 k);@@ -26,20 +26,19 @@ public class KernList : GLib.Object { public KernList (GlyfTable glyf_table) { this.glyf_table = glyf_table; num_pairs = 0;+ pairs = new Gee.ArrayList<PairFormat1> (); } /** @return number of pairs. */ public uint fetch_all_pairs () { PairFormat1 current_pairs = new PairFormat1 (); - if (pairs.length () > 0 || num_pairs > 0) {+ if (pairs.size > 0 || num_pairs > 0) { warning ("Pairs already loaded."); } num_pairs = 0;- while (pairs.length () > 0) {- pairs.remove_link (pairs.first ());- }+ pairs.clear (); KerningClasses.get_instance ().all_pairs ((kp) => { uint16 gid_left, gid_right;@@ -54,7 +53,7 @@ public class KernList : GLib.Object { current_pairs = new PairFormat1 (); gid_left = (uint16) glyf_table.get_gid (kerning_pair.character.get_name ()); current_pairs.left = gid_left;- pairs.append (current_pairs);+ pairs.add (current_pairs); if (unlikely (kerning_pair.kerning.size == 0)) { warning ("No pairs.");@@ -76,7 +75,7 @@ public class KernList : GLib.Object { * pair pos format 1. */ public uint get_length_left () {- return pairs.length ();+ return pairs.size; } /** @return the total number of pairs. */new file mode 100644@@ -0,0 +1,50 @@+/*+ Copyright (C) 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 + License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details.+*/++using Cairo;+using Xml;++namespace BirdFont {++/** A list of all kerning pairs for one glyph. */+public class KerningPair : GLib.Object {+ public Glyph character;+ public Gee.ArrayList<Kerning> kerning;++ Gee.ArrayList<Glyph> right;+ + public KerningPair (Glyph left) {+ character = left;+ right = new Gee.ArrayList<Glyph> ();+ kerning = new Gee.ArrayList<Kerning> ();+ }+ + public void add_unique (Glyph g, double k) {+ if (!right.contains ((!) g)) {+ right.add ((!) g);+ kerning.add (new Kerning.for_glyph (g, k));+ }+ }+ + public void sort () {+ kerning.sort ((a, b) => {+ Kerning first, next;+ first = (Kerning) a;+ next = (Kerning) b;+ return strcmp (((!)first.glyph).get_unichar_string (), ((!)next.glyph).get_unichar_string ());+ }); + }+}+ +}