Clone in a terminal:
Commit dbb19d5
Johan Mattsson - 2012-07-23T22:20:24+00:00
dbb19d508cce1eafae966b88295a590e806f07a2johan.mattsson.m@gmail.com

the awkward indexing trick

Changed files (6)

Diff

diff --git a/src/ContentDisplay.vala b/src/ContentDisplay.valaindex a13f1fe..6123016 100644--- a/src/ContentDisplay.vala+++ b/src/ContentDisplay.vala@@ -498,8 +498,6 @@ class ContentDisplay : FontDisplay { 		}  		if (0 <= recent_active <= columns) {-			-			return_if_fail (cf.font_file != null); 			return_if_fail (recent_fonts.nth (recent_active).data.font_file != null); 			 			f = (!) cf.font_file;diff --git a/src/Font.vala b/src/Font.valaindex d55887e..2b89507 100644--- a/src/Font.vala+++ b/src/Font.vala@@ -554,9 +554,12 @@ class Font : GLib.Object { 	public bool parse_otf_file (string path) { 		OpenFontFormatReader otf = new OpenFontFormatReader (path); 		GlyphCollection? gc;+		int unindexed = 0; 		 		glyph_cache.remove_all (); 		+		print (@"Adding $(otf.get_glyphs ().length ()) to font.");+		 		foreach (Glyph g in otf.get_glyphs ()) { 			gc = get_glyph_collection (g.get_name ()); 		@@ -564,7 +567,9 @@ class Font : GLib.Object { 				gc = new GlyphCollection (); 				glyph_cache.insert (g.get_name (), (!) gc); 			} else {-				stderr.printf (@"Glyph collection does already exit for $(g.get_name ()).\n");+				stderr.printf (@"Glyph collection does already have an entry for $(g.get_name ()) char $((uint64) g.unichar_code).\n");+				gc = new GlyphCollection ();+				glyph_cache.insert (@"$(++unindexed) $(g.get_name ())", (!) gc); 			} 			 			((!)gc).insert_glyph (g, true);diff --git a/src/Glyph.vala b/src/Glyph.valaindex 429c58f..6fb6399 100644--- a/src/Glyph.vala+++ b/src/Glyph.vala@@ -1260,6 +1260,7 @@ class Glyph : FontDisplay { 	public bool is_empty () { 		bool p = path_list.length () == 0 || path_list.first ().data.points.length () == 0; 		return p && background_image == null;+		return false; 	} 	 	private void set_zoom (double z)diff --git a/src/OpenFontFormatWriter.vala b/src/OpenFontFormatWriter.valaindex 49c50cd..2722df4 100644--- a/src/OpenFontFormatWriter.vala+++ b/src/OpenFontFormatWriter.vala@@ -448,7 +448,6 @@ class Table : Object { 		uint8 v;
 		uint8 b = 3;
 		
-		print (@"Seek $offset\n");
 		dis.seek (offset);
 
 		if (length % 4 > 0) {
@@ -609,21 +608,19 @@ class GlyfTable : Table { 	}
 	
 	public void parse (OtfInputStream dis, CmapTable cmap, LocaTable loca, HmtxTable hmtx_table, HeadTable head_table) {
-		print (@"Parsing $(cmap.get_length ()) glyfs\n");
-		print (@"Parsing loca size: $(loca.size)\n");
-
 		uint32 glyph_offset;
 		Glyph glyph = new Glyph ("");
 		double xmin, xmax;
 		
 		for (uint32 i = 0; i < loca.size; i++) {
+			unichar character = 0;
+			StringBuilder name = new StringBuilder ();
+				
 			try {
-				unichar character = cmap.get_char (i);
-				StringBuilder name = new StringBuilder ();
+				character = cmap.get_char (i);
+				name = new StringBuilder ();
 				name.append_unichar (character);
 				
-				print (@"\nnew glyph: gid $i. name: $(name.str)\n");
-				
 				if (!loca.is_empty (i)) {	
 					glyph_offset = loca.get_offset(i);
 					
@@ -642,12 +639,20 @@ class GlyfTable : Table { 					// add empty glyph
 					glyph = new Glyph (name.str, character);
 					glyph.left_limit = -hmtx_table.get_lsb (i);
-					glyph.right_limit = hmtx_table.get_advance (i) - hmtx_table.get_lsb (i);;
+					glyph.right_limit = hmtx_table.get_advance (i) - hmtx_table.get_lsb (i);				
 				}
 				
 				glyphs.append (glyph);
+				
 			} catch (Error e) {
-				stderr.printf (@"Falied to parse glyf:\n$(e.message)\n");
+				stderr.printf (@"Cmap length $(cmap.get_length ()) glyfs\n");
+				stderr.printf (@"Loca size: $(loca.size)\n");
+				stderr.printf (@"Loca offset at $i: $glyph_offset\n");
+				stderr.printf (@"Glyph name: $(name.str)\n");
+				stderr.printf (@"Unicode character: $((uint64)character)\n");
+				stderr.printf (@"\n");
+				stderr.printf (@"Falied to parse glyf: $(e.message)\n");
+				
 				break;
 			}
 		}
@@ -669,14 +674,14 @@ class GlyfTable : Table { 		
 		uint16 num_instructions;
 		
-		print ("Parsing composite glyph\n");
-		
+		Glyph glyph;
+		StringBuilder name = new StringBuilder ();
+		name.append_unichar (character);
+
 		do {
 			component_flags = dis.read_ushort ();
 			glyph_index = dis.read_ushort ();
-			
-			print (@"glyph_index: $glyph_index\n");
-			
+
 			if ((component_flags & BOTH_ARE_WORDS) > 0) {
 				arg1 = dis.read_short ();
 				arg1 = dis.read_short ();			
@@ -707,14 +712,14 @@ class GlyfTable : Table { 		if ((component_flags & INSTRUCTIONS) > 0) {
 			num_instructions = dis.read_ushort ();
 			
-			print (@"num_instructions: $num_instructions\n");
-			
 			for (int i = 0; i < num_instructions; i++) {
 				dis.read_byte ();
 			}
 		}
+
+		glyph = new Glyph (name.str, character);
 		
-		return new Glyph ("");
+		return glyph;
 	}
 	
 	Glyph parse_next_glyf (OtfInputStream dis, unichar character, uint32 glyph_offset,
@@ -741,14 +746,11 @@ class GlyfTable : Table { 		
 		StringBuilder name = new StringBuilder ();
 		name.append_unichar (character);
-		print (@"glyph_offset: $glyph_offset\n");
-		
+
 		dis.seek (offset + glyph_offset);
 		
 		ncontours = dis.read_short ();
 		
-		print (@"$ncontours contours in glyf table.\n");
-		
 		if (ncontours == 0) {
 			warning (@"Got zero contours in glyph $(name.str).");
 
@@ -756,7 +758,6 @@ class GlyfTable : Table { 		}
 				
 		if (ncontours == -1) {
-			print ("Skipping composite glyph.\n");
 			return parse_next_composite_glyf (dis, character);
 		}
 				
@@ -770,11 +771,7 @@ class GlyfTable : Table { 		iymin = dis.read_short ();
 		ixmax = dis.read_short ();
 		iymax = dis.read_short ();
-		
-		print (@"($ixmin,$iymin) to ($ixmax, $iymax)\n");
-		
-		print ("Simple\n");
-	
+
 		end_points = new uint16[ncontours + 1];
 		for (int i = 0; i < ncontours; i++) {
 			end_points[i] = dis.read_ushort (); // FIXA: mind shot vector is negative
@@ -792,9 +789,8 @@ class GlyfTable : Table { 			npoints = 0;
 		}
 
-		ninstructions = dis.read_ushort ();
-		print (@"$ninstructions instructions in glyf table.\n");
-		
+		// FIXA: Implement this
+		ninstructions = dis.read_ushort ();		
 		instructions = new uint8[ninstructions + 1];
 		uint8 repeat;
 		for (int i = 0; i < ninstructions; i++) {
@@ -832,8 +828,6 @@ class GlyfTable : Table { 			error = new BadFormat.PARSE (@"Wrong number of flags in glyph $(name.str). (nflags != npoints) ($nflags != $npoints)");
 		}
 		
-		print (@"npoints: $npoints\n");
-		
 		int16 last = 0;
 		xcoordinates = new int16[npoints + 1];
 		for (int i = 0; i < npoints; i++) {
@@ -893,12 +887,9 @@ class GlyfTable : Table { 		xmax = ixmax * 1000.0 / units_per_em;
 		
 		for (int i = 0; i < ncontours; i++) {
-			
 			x = 0;
 			y = 0;
 			
-			print ("Next path\n");
-			
 			Path path = new Path ();
 			EditPoint edit_point = new EditPoint ();
 			bool prev_is_curve = false;
@@ -962,8 +953,6 @@ class GlyfTable : Table { 			glyph.add_path (path);
 		}
 		
-		print (@" ($ixmax == $ixmin)\n");
-		
 		// glyphs with no bounding boxes
 		if (ixmax <= ixmin) {
 			warning (@"Bounding box is bad. (xmax == xmin) ($xmax == $xmin)");
@@ -1174,6 +1163,12 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		}
 		
 		if (c == 0) {
+			while (table.lookup (--indice) == 0) {
+				if (indice == 0) {
+					return 0;
+				}
+			} 
+			
 			// FIXA: yes there is for null character
 			warning (@"There is no char for glyph number $indice in cmap table. table.size: $(table.size ()))");
 			return 0;
@@ -1195,6 +1190,8 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		int16* id_delta = null;
 		uint16* id_range_offset = null;
 		uint16* glyph_id_array = null;
+	
+		uint32 gid_len;
 		
 		length = dis.read_ushort ();
 		lang = dis.read_ushort ();
@@ -1238,32 +1235,49 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 			id_range_offset[i] = dis.read_ushort ();
 		}
 
-		glyph_id_array = new uint16[seg_count];
-		for (int i = 0; i < seg_count; i++) {
+		gid_len = (length - 16 - 8 * seg_count) / 2;
+		glyph_id_array = new uint16[gid_len];
+		for (int i = 0; i < gid_len; i++) {
 			glyph_id_array[i] = dis.read_ushort ();
 		}
 		
 		// map all values in a hashtable
 		int indice = 0;
 		unichar character = 0;
+		uint32 id;
 		for (uint16 i = 0; i < seg_count && start_char[i] != 0xFFFF; i++) {
 			
 			print (@"Insert range $((int)start_char[i]) to $((int)end_char[i]). id_delta[i] $(id_delta[i])  id_range_offset[i] $(id_range_offset[i])\n");
-
-			if (id_range_offset[i] == 0) {
-				uint16 j = 0;
-				do {
-					character = start_char[i] + j;
-					indice = start_char[i] + id_delta[i] + j;
-					
+			
+			uint16 j = 0;
+			do {
+				character = start_char[i] + j;
+				indice = start_char[i] + id_delta[i] + j;
+				
+				if (id_range_offset[i] == 0) {
 					table.insert (indice, character);
+				} else {
+					// the awkward indexing trick:
+					id = id_range_offset[i] / 2 + j + i - seg_count;
 					
-					indice++;
-					j++;
-				} while (character != end_char[i]);
-			} else {
-				warning ("Glyph indice with id_range_offset > 0 is not implemented yet.");
-			}		
+					if (!(0 <= id < gid_len)) {
+						warning (@"(0 <= id < gid_len) (0 <= $id < $gid_len)");
+						break;
+					}
+					
+					indice = glyph_id_array [id] + id_delta[i];
+										
+					StringBuilder s = new StringBuilder ();
+					s.append_unichar (character);					
+					
+					print (@"$(s.str) -> $indice      j $j  id_delta[i] $(id_delta[i])  id $id gidi  $(glyph_id_array [id])   char: $((uint32)character)\n");
+					
+					table.insert (indice, character);
+				}
+				
+				indice++;
+				j++;
+			} while (character != end_char[i]);
 	
 		}
 		
@@ -1272,6 +1286,42 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		if (id_delta != null) delete id_delta;
 		if (id_range_offset != null) delete id_range_offset;
 		if (glyph_id_array != null) delete glyph_id_array;
+		
+		// it is has a character for every glyph indice
+		// assert (validate_subtable ());
+	}
+	
+	public bool validate_subtable () {
+		uint32 length = get_length ();
+		unichar c;
+		unichar prev;
+		uint32 i = 0;
+		uint32 err = 0;
+		StringBuilder s;
+		
+		c = get_char (i);
+		i++;
+		
+		while (i < length) {
+			if (c == 0) {
+				s = new StringBuilder ();
+				s.append_unichar (c);
+				warning (@"No characte in cmap for index $i. Last avalable char is $(s.str) Got $(s.str), ($((uint32)c))");
+				err++;
+				return false;
+			} else {
+				prev = c;
+			}
+			
+			c = get_char (i);
+			i++;
+		}
+		
+		if (err > 0) {
+			stderr.printf (@"$err glyphs without mapping to a charactercode were found in this font.\n");
+		}
+		
+		return true;
 	}
 }
 
@@ -1498,8 +1548,7 @@ class HeadTable : Table { 		uint64 modified;
 		
 		List<CmapSubtable> maps = new List<CmapSubtable> ();
-		
-		print (@"Seek $offset\n");
+
 		dis.seek (offset);
 	
 		version = dis.read_fixed ();
diff --git a/src/OverView.vala b/src/OverView.valaindex b1687f4..c754ad8 100644--- a/src/OverView.vala+++ b/src/OverView.vala@@ -663,7 +663,6 @@ class OverView : FontDisplay { 		set_glyph_range (full); 		selected = c + 1; 		set_glyph_range (gr);-		 	} 		 	public override void motion_notify (EventMotion e) {diff --git a/src/Preferences.vala b/src/Preferences.valaindex f093d4e..e38ea8b 100644--- a/src/Preferences.vala+++ b/src/Preferences.vala@@ -56,10 +56,16 @@ class Preferences { 		return files; 	} -	public static bool is_ffi_file (string file) {-		// Fixa: Valabug: char_count deal with non-ascii letters+	public static bool is_font_file (string file) {+		// Valabug: char_count deal with non-ascii letters 		// return (file.last_index_of (".ffi") != file.char_count () - 4); 		int i = file.last_index_of (".ffi");+		+		if (i > -1) {+			return true;+		}+		+		i = file.last_index_of (".ttf"); 		return (i > -1); 	} @@ -67,7 +73,7 @@ class Preferences { 		string escaped_string = file.replace ("\t", "\\t"); 		StringBuilder recent = new StringBuilder (); -		if (!is_ffi_file (file)) {+		if (!is_font_file (file)) { 			warning (@"\"$file\" is not a .ffi file."); 			return; 		}

Contact

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