Clone in a terminal:
AlternateFeature.vala
/*
	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 {

public class AlternateFeature : GLib.Object {
	GlyfTable glyf_table;
	Gee.ArrayList<Alternate> alternates;
	string tag;
	
	public AlternateFeature (GlyfTable glyf_table, string tag) {
		Font font = OpenFontFormatWriter.get_current_font ();
		
		this.tag = tag;
		this.glyf_table = glyf_table;
		alternates = font.alternates.get_alt_with_glyph (tag, font);

		alternates.sort ((a, b) => {
			Alternate alt1 = (Alternate) a;
			Alternate alt2 = (Alternate) b;
			return strcmp (alt1.glyph_name, alt2.glyph_name);
		});
	}
	
	public bool has_alternates () {
		return alternates.size > 0;
	}
	
	public Lookups get_lookups () throws GLib.Error {
		Lookups lookups = new Lookups ();
		Lookup lookup = new Lookup (3, 0, tag);
		FontData fd = new FontData ();

		fd.add_ushort (1); // format identifier
		
		// offset to coverage
		int coverage_offset = 6;
		coverage_offset += 2 * alternates.size;
		
		foreach (Alternate a in alternates) {
			coverage_offset += 2;
			coverage_offset += 2 * a.alternates.size;
		}
		
		fd.add_ushort ((uint16) coverage_offset);
		
		// number of alternate sets
		fd.add_ushort ((uint16) alternates.size); 
		
		int offset = 6 + 2 * alternates.size;
		for (int i = 0; i < alternates.size; i++) {
			// offset to each alternate set
			fd.add_ushort ((uint16) offset);
			offset += 2;
			offset += 2 * alternates.get (i).alternates.size;
		}
		
		// alternates
		foreach (Alternate alternate in alternates) {
			fd.add_ushort ((uint16) alternate.alternates.size);
			
			alternate.alternates.sort ((a, b) => {
				string alt1 = (string) a;
				string alt2 = (string) b;
				return strcmp (alt1, alt2);
			});
			
			foreach (string alt in alternate.alternates) {
				fd.add_ushort ((uint16) glyf_table.get_gid (alt));
			}
		}		

		if (fd.length_with_padding () != coverage_offset) {
			warning (@"Bad coverage offset. $(fd.length_with_padding ()) != $coverage_offset");
		}

		// coverage  
		fd.add_ushort (1); // format
		fd.add_ushort ((uint16) alternates.size); // coverage array length
		foreach (Alternate alternate in alternates) {
			string glyph_name = alternate.glyph_name;
			fd.add_ushort ((uint16) glyf_table.get_gid (glyph_name));
		}
		
		lookup.add_subtable (fd);
		lookups.add_lookup (lookup);
		
		return lookups;
	}
}

}

Contact

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