Clone in a terminal:
Commit 13b9d75
Johan Mattsson - 2015-10-02T18:34:09+00:00
13b9d75ae930e4bac1f33dadde65e3978b433911johan.mattsson.m@gmail.com

Apply OTF substitution in kerning tab

Changed files (9)

Diff

diff --git a/libbirdfont/BirdFontFile.vala b/libbirdfont/BirdFontFile.valaindex 279ec4a..30f8e54 100644--- a/libbirdfont/BirdFontFile.vala+++ b/libbirdfont/BirdFontFile.vala@@ -850,6 +850,21 @@ class BirdFontFile : GLib.Object { 			} 		} 		+		if (glyph_name == "") {+			warning ("No name for source glyph in alternate.");+			return;+		}++		if (alt == "") {+			warning ("No name for alternate.");+			return;+		}++		if (alt_tag == "") {+			warning ("No tag for alternate.");+			return;+		}+		 		font.add_alternate (glyph_name, alt, alt_tag); 	} 	diff --git a/libbirdfont/GlyphSequence.vala b/libbirdfont/GlyphSequence.valaindex 5411939..3546435 100644--- a/libbirdfont/GlyphSequence.vala+++ b/libbirdfont/GlyphSequence.vala@@ -21,9 +21,16 @@ public class GlyphSequence : GLib.Object { 	/** A list of corresponding glyph ranges if applicable. */  	public Gee.ArrayList<GlyphRange?> ranges; +	OtfTags otf_tags;+ 	public GlyphSequence () { 		glyph = new Gee.ArrayList<Glyph?> (); 		ranges = new Gee.ArrayList<GlyphRange?> ();+		otf_tags = new OtfTags ();+	}+	+	public void set_otf_tags (OtfTags tags) {+		this.otf_tags = tags; 	} 	 	public int length () {@@ -45,7 +52,8 @@ public class GlyphSequence : GLib.Object { 		} 	} 	-	/** Do ligature substitution.+	/** Perform glyph substitution.+	 * @param tags enable otf features 	 * @return a new sequence with ligatures 	 */ 	public GlyphSequence process_ligatures (Font font) {@@ -81,6 +89,37 @@ public class GlyphSequence : GLib.Object { 			ligature_sequence.replace (substitute, ligature); 		}); 		+		// salt and similar tags+		foreach (string tag in otf_tags.elements) {+			Gee.ArrayList<Alternate> alternates;+			alternates = font.alternates.get_alt (tag);++			foreach (Alternate a in alternates) {+				GlyphSequence old = new GlyphSequence ();+				Glyph? g = font.get_glyph_by_name (a.glyph_name);++				if (g != null) {+					old.add (g);+						+					if (a.alternates.size > 0) {+						// FIXME: pick one of several alternates+						string alt_name = a.alternates.get (0);+						Glyph? alt = font.get_glyph_by_name (alt_name);+						+						if (alt != null) {+							GlyphSequence replacement = new GlyphSequence ();+							replacement.add (alt);+							ligature_sequence.replace (old, replacement);+						} else {+							warning (@"Alternate does not exist: $(alt_name)");+						}+					}+				} else {+					warning (@"Alternative for a missing glyph: $(a.glyph_name)");+				}+			}+		}+		 		ligature_sequence.ranges.clear (); 		for (int i = 0; i < ligature_sequence.glyph.size; i++) { 			ligature_sequence.ranges.add (null);diff --git a/libbirdfont/KerningDisplay.vala b/libbirdfont/KerningDisplay.valaindex c6a3b78..d4c5c0c 100644--- a/libbirdfont/KerningDisplay.vala+++ b/libbirdfont/KerningDisplay.vala@@ -1,5 +1,5 @@ /*-    Copyright (C) 2012, 2014 Johan Mattsson+    Copyright (C) 2012 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 @@ -21,7 +21,9 @@ public class KerningDisplay : FontDisplay {  	public bool suppress_input = false; 	-	Gee.ArrayList <GlyphSequence> row;+	Gee.ArrayList <GlyphSequence> first_row;+	Gee.ArrayList <GlyphSequence> rows;+	 	int active_handle = -1; 	int selected_handle = -1; 	bool moving = false;@@ -39,7 +41,6 @@ public class KerningDisplay : FontDisplay { 	Gee.ArrayList<UndoItem> redo_items; 	bool first_update = true; -	Font current_font = new Font (); 	Text kerning_label = new Text (); 	 	public bool adjust_side_bearings = false;@@ -47,14 +48,49 @@ public class KerningDisplay : FontDisplay { 	 	public KerningDisplay () { 		GlyphSequence w = new GlyphSequence ();-		row = new Gee.ArrayList <GlyphSequence> ();+		rows = new Gee.ArrayList <GlyphSequence> ();+		first_row = new Gee.ArrayList <GlyphSequence> (); 		undo_items = new Gee.ArrayList <UndoItem> (); 		redo_items = new Gee.ArrayList <UndoItem> ();-		row.add (w);+		w.set_otf_tags (KerningTools.get_otf_tags ());+		first_row.add (w); 	}  	public GlyphSequence get_first_row () {-		return row.size > 0 ? row.get (0) : new GlyphSequence ();+		GlyphSequence first = new GlyphSequence ();+		Font font = BirdFont.get_current_font ();+		+		foreach (GlyphSequence s in first_row) {+			first.append (s.process_ligatures (font));+		}+		+		return first;+	}++	public void new_segment () {+		GlyphSequence s = new GlyphSequence ();+		s.set_otf_tags (KerningTools.get_otf_tags ());+		first_row.add (s);+	}++	public GlyphSequence get_last_segment () {+		if (first_row.size == 0) {+			new_segment ();+		}+		+		return first_row.get (first_row.size - 1);+	}+	+	Gee.ArrayList <GlyphSequence> get_all_rows () {+		Gee.ArrayList <GlyphSequence> r;+		+		r = new Gee.ArrayList <GlyphSequence> ();+		r.add (get_first_row ());+		foreach (GlyphSequence s in rows) {+			r.add (s);+		}+		+		return r; 	}  	public override string get_label () {@@ -78,6 +114,7 @@ public class KerningDisplay : FontDisplay { 	} 	 	public double get_row_height () {+		Font current_font = BirdFont.get_current_font (); 		return current_font.top_limit - current_font.bottom_limit; 	} @@ -92,11 +129,10 @@ public class KerningDisplay : FontDisplay { 		GlyphRange? gr_left, gr_right; 		bool first_row = true; 		double row_height;-		Font font;+		Font font = BirdFont.get_current_font (); 		double item_size = 1.0 / KerningTools.font_size; 		double item_size2 = 2.0 / KerningTools.font_size;-		-		font = current_font;+ 		i = 0; 		 		// bg color@@ -120,7 +156,7 @@ public class KerningDisplay : FontDisplay { 		prev = null; 		kern = 0; 		-		foreach (GlyphSequence word in row) {+		foreach (GlyphSequence word in get_all_rows ()) { 			wi = 0; 			word_with_ligatures = word.process_ligatures (font); 			gr_left = null;@@ -253,8 +289,8 @@ public class KerningDisplay : FontDisplay { 			} 		} 		-		for (int j = row.size - 1; j > 30; j--) {-			row.remove_at (j);+		for (int j = rows.size - 1; j > 30; j--) {+			rows.remove_at (j); 		} 		 		cr.fill ();@@ -270,7 +306,7 @@ public class KerningDisplay : FontDisplay { 		double kern = get_kerning_for_handle (h); 		active_handle = h; 		-		if (1 <= active_handle < row.get (0).glyph.size) {+		if (1 <= active_handle < get_first_row ().glyph.size) { 			display_kerning_value (kern); 		} 	}@@ -298,9 +334,8 @@ public class KerningDisplay : FontDisplay { 		int ranges_index = 0; 		GlyphRange? gr_left, gr_right; 		int row_index = 0;-		-		font = current_font; +		font = BirdFont.get_current_font (); 		font.touch ();  		a = "";@@ -315,46 +350,42 @@ public class KerningDisplay : FontDisplay { 			return false; 		} 		-		foreach (GlyphSequence word in row) {-			word_with_ligatures = word.process_ligatures (font);-			ranges_index = 0;-			foreach (Glyph? g in word_with_ligatures.glyph) {-				-				if (g == null) {-					continue;+		word_with_ligatures = get_first_row ();+		ranges_index = 0;+		foreach (Glyph? g in word_with_ligatures.glyph) {+			+			if (g == null) {+				continue;+			}+			+			b = ((!) g).get_name ();+			+			if (handle == wi && row_index == 0) {+				if (wi >= word_with_ligatures.ranges.size) {+					return false; 				}+				return_val_if_fail (wi - 1 >= 0, false); 				-				b = ((!) g).get_name ();-				-				if (handle == wi && row_index == 0) {-					if (wi >= word_with_ligatures.ranges.size) {-						return false;-					}-					return_val_if_fail (wi - 1 >= 0, false);-					-					if (word_with_ligatures.ranges.size != word_with_ligatures.glyph.size) {-						return false;-					}-					-					gr_left = word_with_ligatures.ranges.get (wi - 1);-					gr_right = word_with_ligatures.ranges.get (wi);-					-					left = a;-					right = b;-					range_left = gr_left;-					range_right = gr_right;-					-					return true;+				if (word_with_ligatures.ranges.size != word_with_ligatures.glyph.size) {+					return false; 				} 				-				wi++;+				gr_left = word_with_ligatures.ranges.get (wi - 1);+				gr_right = word_with_ligatures.ranges.get (wi);+				+				left = a;+				right = b;+				range_left = gr_left;+				range_right = gr_right; 				-				a = b;+				return true; 			} 			-			row_index++;+			wi++;+			+			a = b; 		}-		+ 		return false;	 	} @@ -378,7 +409,7 @@ public class KerningDisplay : FontDisplay { 		Font font; 		GlyphRange? gr_left, gr_right; -		font = current_font;+		font = BirdFont.get_current_font (); 		font.touch ();  		if (!adjust_side_bearings) {@@ -410,7 +441,7 @@ public class KerningDisplay : FontDisplay { 		bool has_kerning; 		Font font; 		-		font = current_font;+		font = BirdFont.get_current_font (); 		font.touch (); 		classes = font.get_kerning_classes (); 			@@ -455,32 +486,8 @@ public class KerningDisplay : FontDisplay { 		return k.get_kerning_for_pair (a, b, gr_left, gr_right); 	} 	-	public void set_current_font (Font f) {-		current_font = f;-	}-	 	public override void selected_canvas () {-		Glyph g;-		GlyphSequence w;-		StringBuilder s = new StringBuilder ();-		bool append_char = false;-		-		current_font = BirdFont.get_current_font ();-		-		KeyBindings.set_require_modifier (true);-		-		g = MainWindow.get_current_glyph ();-		s.append_unichar (g.get_unichar ());--		if (row.size == 0) {-			append_char = true;-		}-		-		if (append_char) {-			w = new GlyphSequence ();-			row.add (w);-			w.glyph.insert (0, current_font.get_glyph (s.str));-		}		+		KeyBindings.set_require_modifier (true);		 	} 	 	public void add_kerning_class (int index) {@@ -488,8 +495,9 @@ public class KerningDisplay : FontDisplay { 	} 	 	public void add_range (GlyphRange range) {-		Font font = current_font;+		Font font = BirdFont.get_current_font (); 		Glyph? glyph;+		GlyphSequence s; 		 		glyph = font.get_glyph_by_name (range.get_char (0)); 		@@ -498,8 +506,15 @@ public class KerningDisplay : FontDisplay { 			return; 		} 		-		row.get (0).glyph.add ((!) glyph);-		row.get (0).ranges.add (range);+		if (first_row.size == 0) {+			s = new GlyphSequence ();+			first_row.add (s);+		} else {+			s = first_row.get (first_row.size - 1);+		}+		+		s.glyph.add ((!) glyph);+		s.ranges.add (range); 		 		GlyphCanvas.redraw (); 	}@@ -508,9 +523,8 @@ public class KerningDisplay : FontDisplay { 		Glyph? g; 		selected_handle = handle; 		GlyphSequence sequence_with_ligatures;-		Font font = BirdFont.get_current_font (); -		sequence_with_ligatures = row.get (0).process_ligatures (font);+		sequence_with_ligatures = get_first_row (); 		 		if (selected_handle <= 0) { 			selected_handle = 1;@@ -625,12 +639,11 @@ public class KerningDisplay : FontDisplay { 				|| KeyBindings.modifier == SHIFT  				|| KeyBindings.modifier == ALT) {		 				-				if (keyval == Key.BACK_SPACE && row.size > 0 && row.get (0).glyph.size > 0) {-					row.get (0).glyph.remove_at (row.get (0).glyph.size - 1);-					row.get (0).ranges.remove_at (row.get (0).ranges.size - 1);+				if (keyval == Key.BACK_SPACE) {+					remove_last_character (); 				} 				-				if (row.size == 0 || c == Key.ENTER) {+				if (c == Key.ENTER) { 					new_line (); 				} 				@@ -641,13 +654,27 @@ public class KerningDisplay : FontDisplay { 		GlyphCanvas.redraw (); 	} 	+	void remove_last_character () {+		if (first_row.size > 0) {+			GlyphSequence gs = first_row.get (first_row.size - 1);+			+			if (gs.glyph.size > 0) {+				gs.glyph.remove_at (gs.glyph.size - 1);+				return_if_fail (gs.ranges.size > 0);+				gs.ranges.remove_at (gs.ranges.size - 1);+			} else {+				first_row.remove_at (first_row.size - 1);+				remove_last_character ();+			}+		}		+	}+	 	public void insert_unichar () { 		TextListener listener; 		string submitted_value = ""; 		string unicodestart; 		 		unicodestart = (KeyBindings.has_shift ()) ? "" : "U+";- 		listener = new TextListener (t_("Unicode"), unicodestart, t_("Insert")); 		 		listener.signal_text_input.connect ((text) => {@@ -681,34 +708,44 @@ public class KerningDisplay : FontDisplay { 	} 	 	public void new_line () {-		row.insert (0, new GlyphSequence ());+		rows.insert (0, get_first_row ());+		first_row = new Gee.ArrayList<GlyphSequence> ();+		GlyphSequence gs = new GlyphSequence ();+		gs.set_otf_tags (KerningTools.get_otf_tags ());+		first_row.add (gs); 	} 	 	void add_character (unichar c) { 		Glyph? g; 		string name;-		Font f;  		if (MenuTab.suppress_event) { 			return; 		} 		-		f = current_font;-		 		if (!is_modifier_key (c) && c.validate ()) { 			name = (!) c.to_string ();-			g = f.get_glyph_by_name (name);+			g = BirdFont.get_current_font ().get_glyph_by_name (name); 			inser_glyph (g); 		} 	} 	 	public void inser_glyph (Glyph? g) {+		int handle;+		+		if (first_row.size == 0) {+			GlyphSequence gs = new GlyphSequence ();+			gs.set_otf_tags (KerningTools.get_otf_tags ());+			first_row.add (gs);+		}+		 		if (g != null) {-			row.get (0).glyph.add (g);-			row.get (0).ranges.add (null);+			first_row.get (first_row.size - 1).glyph.add (g);+			first_row.get (first_row.size - 1).ranges.add (null); 			-			set_selected_handle ((int) row.get (0).glyph.size - 1);-			set_active_handle_index (selected_handle);+			handle = get_first_row ().glyph.size - 1;+			set_selected_handle (handle);+			set_active_handle_index (handle); 		} 	} 	@@ -745,7 +782,6 @@ public class KerningDisplay : FontDisplay { 		int row_index = 0; 		int col_index = 0; 		Glyph glyph = new Glyph.no_lines ("");-		Font font = BirdFont.get_current_font (); 		double fs = KerningTools.font_size; 		double x = 20; 				@@ -755,68 +791,65 @@ public class KerningDisplay : FontDisplay { 		string gl_name = ""; 		GlyphSequence word_with_ligatures; 		-		foreach (GlyphSequence word in row) {-			col_index = 0;+		col_index = 0;+		+		word_with_ligatures = get_first_row ();+		foreach (Glyph? g in word_with_ligatures.glyph) {+			if (g == null) {+				w = 50;+				warning ("glyph does not exist");	+			} else {+				glyph = (!) g;+				w = glyph.get_width ();+			} 			-			word_with_ligatures = word.process_ligatures (font);-			foreach (Glyph? g in word_with_ligatures.glyph) {-				if (g == null) {-					w = 50;-					warning ("glyph does not exist");	-				} else {-					glyph = (!) g;-					w = glyph.get_width ();-				}+			gl_name = glyph.get_name ();+			+			if (prev == null && col_index != 0) {+				warning (@"previous glyph does not exist row: $row_index column: $col_index");+			}+			+			if (prev == null || col_index == 0) {+				kern = 0;+			} else {+				return_if_fail (col_index < word_with_ligatures.ranges.size);+				return_if_fail (col_index - 1 >= 0); 				-				gl_name = glyph.get_name ();+				gr_left = word_with_ligatures.ranges.get (col_index - 1);+				gr_right = word_with_ligatures.ranges.get (col_index);++				kern = get_kerning_for_pair (((!)prev).get_name (), ((!)g).get_name (), gr_left, gr_right);+			}+							+			d = Math.pow (fs * (x + kern) - ex, 2);+			+			if (d < min) {+				min = d; 				-				if (prev == null && col_index != 0) {-					warning (@"previous glyph does not exist row: $row_index column: $col_index");+				if (ex != fs * (x + kern)) {	// don't swap direction after button release+					right_side_bearing = ex < fs * (x + kern); // right or left side bearing handle 				} 				-				if (prev == null || col_index == 0) {-					kern = 0;-				} else {-					return_if_fail (col_index < word_with_ligatures.ranges.size);-					return_if_fail (col_index - 1 >= 0);-					-					gr_left = word_with_ligatures.ranges.get (col_index - 1);-					gr_right = word_with_ligatures.ranges.get (col_index);--					kern = get_kerning_for_pair (((!)prev).get_name (), ((!)g).get_name (), gr_left, gr_right);+				if (active_handle != i - row_index) {+					set_active_handle_index (i - row_index);+					GlyphCanvas.redraw (); 				}-								-				d = Math.pow (fs * (x + kern) - ex, 2); 				-				if (d < min) {-					min = d;-					-					if (ex != fs * (x + kern)) {	// don't swap direction after button release-						right_side_bearing = ex < fs * (x + kern); // right or left side bearing handle-					}-					-					if (active_handle != i - row_index) {-						set_active_handle_index (i - row_index);-						GlyphCanvas.redraw ();-					}-					-					if (col_index == word.glyph.size || col_index == 0) {-						set_active_handle_index (-1);-					} else {-						set_active_handle_index (active_handle + row_index);-					}+				if (col_index == word_with_ligatures.glyph.size || col_index == 0) {+					set_active_handle_index (-1);+				} else {+					set_active_handle_index (active_handle + row_index); 				}-				-				prev = g;-				x += w + kern;-				i++;-				col_index++; 			} 			-			row_index++;-			x = 20;-			return;+			prev = g;+			x += w + kern;+			i++;+			col_index++; 		}+		+		row_index++;+		x = 20; 	} 	 	public override void button_release (int button, double ex, double ey) {@@ -935,7 +968,7 @@ public class KerningDisplay : FontDisplay { 	public UndoItem apply_undo (UndoItem ui) { 		KerningClasses classes = BirdFont.get_current_font ().get_kerning_classes (); 		GlyphRange glyph_range_first, glyph_range_next;-		Font font = current_font;+		Font font = BirdFont.get_current_font (); 		string l, r; 		UndoItem redo_state = new UndoItem ("", "", 0, false); 		double? k;diff --git a/libbirdfont/KerningTools.vala b/libbirdfont/KerningTools.valaindex a843e23..968a9a8 100644--- a/libbirdfont/KerningTools.vala+++ b/libbirdfont/KerningTools.vala@@ -28,11 +28,30 @@ public class KerningTools : ToolCollection  { 	public static Tool previous_kerning_string; 	public static Tool next_kerning_string; 	+	public static Expander otf_features;+	+	static OtfTags active_otf_features;+	 	public KerningTools () {+		active_otf_features = new OtfTags ();+		selected ();+	}+	+	public override void selected () { 		init (); 	} 	+	public static OtfTags get_otf_tags () {+		if (is_null (active_otf_features)) {+			return new OtfTags ();+		}+		+		return active_otf_features;+	}+ 	public static void init () {+		Font font = BirdFont.get_current_font ();+		 		Expander kerning_tools = new Expander (t_("Kerning Tools")); 		classes = new Expander (); 		expanders = new Gee.ArrayList<Expander> ();@@ -61,9 +80,9 @@ public class KerningTools : ToolCollection  { 		 		Tool new_kerning_class = new Tool ("kerning_class", t_("Create new kerning class.")); 		new_kerning_class.select_action.connect ((self) => {-			Font font = BirdFont.get_current_font ();+			Font f = BirdFont.get_current_font (); 			string label = t_("Kerning class");-			KerningRange kr = new KerningRange (font, @"$label $(++next_class)");+			KerningRange kr = new KerningRange (f, @"$label $(++next_class)"); 			classes.add_tool (kr); 			self.set_selected (false); 			classes.redraw ();@@ -141,9 +160,15 @@ public class KerningTools : ToolCollection  { 		}); 		kerning_tools.add_tool (next_kerning_string); 				+		otf_features = new Expander (t_("Substitutions"));+		+		foreach (string tag in font.alternates.get_all_tags ()) {+			add_otf_label (tag);+		}+ 		kerning_tools.set_persistent (false); 		kerning_tools.set_unique (false);-+		 		classes.set_persistent (true); 		classes.set_unique (true); 		@@ -151,6 +176,33 @@ public class KerningTools : ToolCollection  { 		expanders.add (zoom_expander); 		expanders.add (kerning_tools); 		expanders.add (classes);+		expanders.add (otf_features);+	}+	+	public static void add_otf_label (string tag) {+		OtfLabel otf_label = new OtfLabel (tag);+		otf_features.add_tool (otf_label);+		otf_label.otf_feature_activity.connect ((enable, tag) => {+			OtfTags tags = active_otf_features.copy ();+			KerningDisplay kd = MainWindow.get_kerning_display ();+			kd.new_segment ();+			+			// create a new feature set in order to keep the features+			// for other parts of the text in kerning tab+			active_otf_features = tags;++			if (enable) {+				print ("enable " + tag + "\n");+				tags.add (tag);+			} else {+				print ("disable " + tag + "\n");+				tags.remove (tag);+			}+			+			kd.get_last_segment ().set_otf_tags (tags);+			+			GlyphCanvas.redraw ();+		}); 	} 	 	public static void add_unique_class (KerningRange kerning_class) {@@ -271,6 +323,7 @@ public class KerningTools : ToolCollection  { 		d.add ("Spacing"); 		return d; 	}+		 }  }diff --git a/libbirdfont/OtfFeatureTable.vala b/libbirdfont/OtfFeatureTable.valaindex 6ae5e6f..c947c56 100644--- a/libbirdfont/OtfFeatureTable.vala+++ b/libbirdfont/OtfFeatureTable.vala@@ -91,19 +91,19 @@ public class OtfFeatureTable : Table { 		row = new Row.headline (t_("Tag")); 		rows.add (row); 		-		row = new Row.columns_1 (t_("Stylistic Alternate") + " (salt)", OTF_FEATURE, false);+		row = new Row.columns_1 (OtfLabel.get_string ("salt"), OTF_FEATURE, false); 		row.set_row_data (new String ("salt")); 		rows.add (row); -		row = new Row.columns_1 (t_("Small Caps") + " (smcp)", OTF_FEATURE, false);+		row = new Row.columns_1 (OtfLabel.get_string ("smcp"), OTF_FEATURE, false); 		row.set_row_data (new String ("smcp")); 		rows.add (row); -		row = new Row.columns_1 (t_("Capitals to Small Caps") + " (c2sc)", OTF_FEATURE, false);+		row = new Row.columns_1 (OtfLabel.get_string ("c2sc"), OTF_FEATURE, false); 		row.set_row_data (new String ("c2sc")); 		rows.add (row); -		row = new Row.columns_1 (t_("Swashes") + " (swsh)", OTF_FEATURE, false);+		row = new Row.columns_1 (OtfLabel.get_string ("swsh"), OTF_FEATURE, false); 		row.set_row_data (new String ("swsh")); 		rows.add (row); 				diff --git a/libbirdfont/OtfLabel.vala b/libbirdfont/OtfLabel.valanew file mode 100644index 0000000..b51a672--- /dev/null+++ b/libbirdfont/OtfLabel.vala@@ -0,0 +1,57 @@+/*+    Copyright (C) 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 +    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.+*/++namespace BirdFont {++/** Gsub substitutions will be performed kening and spacing tab when + * this tool is selected.+ */+public class OtfLabel : LabelTool {++	public bool active_substitution = false;+	public string tag;+	+	public signal void otf_feature_activity (bool enable, string tag);+	+	public OtfLabel (string tag) {+		string label = get_string(tag);+		base (label);+		+		this.tag = tag;+		+		select_action.connect ((self) => {+			active_substitution = !active_substitution;+			self.set_selected (active_substitution);+			otf_feature_activity (active_substitution, tag);+		});+	}+	+	/** @return translated string representation of a OTF feature tag. */+	public static string get_string (string tag) {+		if (tag == "salt") {+			return t_("Stylistic Alternate") + " (salt)";+		} else if (tag == "smcp") {+			return t_("Small Caps") + " (smcp)";+		} else if (tag == "c2sc") {+			return t_("Capitals to Small Caps") + " (c2sc)";+		} else if (tag == "swsh") {+			return t_("Swashes") + " (swsh)";+		}+		+		warning (@"Unknown tag: $tag");+		return tag;+	}+}++}diff --git a/libbirdfont/SpacingTab.vala b/libbirdfont/SpacingTab.valaindex ef7ea62..0fc1b98 100644--- a/libbirdfont/SpacingTab.vala+++ b/libbirdfont/SpacingTab.vala@@ -70,7 +70,6 @@ public class SpacingTab : KerningDisplay { 		cr.stroke (); 		cr.restore (); 		-		// TODO: add button for processing ligatures 		row = get_first_row ().process_ligatures (font); 		index = 0; 		foreach (Glyph? g in row.glyph) {diff --git a/libbirdfont/ToolCollection.vala b/libbirdfont/ToolCollection.valaindex 626874e..c5bc6f5 100644--- a/libbirdfont/ToolCollection.vala+++ b/libbirdfont/ToolCollection.vala@@ -32,6 +32,9 @@ public abstract class ToolCollection : GLib.Object  { 			e.redraw (); 		} 	}+	+	public virtual void selected () {	+	} }  }diff --git a/libbirdfont/Toolbox.vala b/libbirdfont/Toolbox.valaindex 2c1a6ef..ebc8d5f 100644--- a/libbirdfont/Toolbox.vala+++ b/libbirdfont/Toolbox.vala@@ -81,6 +81,7 @@ public class Toolbox : GLib.Object  { 		tool_sets.add (hidden_tools); // tools without a button 		 		current_set = file_tools;+		current_set.selected (); 		 		tab_bar.signal_tab_selected.connect ((tab) => { 			string tab_name = tab.get_display ().get_name ();@@ -120,6 +121,7 @@ public class Toolbox : GLib.Object  { 			current_set = (ToolCollection) file_tools; 		} 		+		current_set.selected (); 		MainWindow.get_toolbox ().update_expanders (); 		redraw_tool_box (); 	}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112