This question is related to a few questions that have been asked long time ago. I saw comments that Opentype fonts were not supported in Java, but this was 11 years ago. Nowadays they are. The only problem is that kerning pairs are only given in the GPOS table. I have seen that they are there but it is hard to make sure the code is correct.
I am currently dumping the GPOS table trying to follow the pointers until the kerning pairs.
The code so far is below, where GPOS table has been previously copied to the array gpos
. The function to dump the table is dumpGPOS()
. I need help to determine if what I am doing is correct and how to code the TODO parts:
byte[] gpos;
char[] hexasc( char[] hex, byte num ) {
int up = num >> 4;
int down = num & 15;
hex[0] = (char) ((up < 10)? '0' + up : 'A' + up - 10);
hex[1] = (char) ((down < 10)? '0' + down : 'A' + down - 10);
return hex;
}
char[] hex = { '0', '0' };
void printHex(byte b) {
hexasc(hex, b);
System.out.print(hex[0]);
System.out.print(hex[1]);
}
void dumpGPOS() {
int i, j;
System.out.println("GPOS header");
System.out.print("Version: ");
for ( i = 0; i < 4; i++ ) printHex(gpos[i]);
System.out.println(" (" + (gpos[0] << 8 | gpos[1]) + "." + (gpos[2] << 8 | gpos[3]) + ")" );
j = i;
System.out.print("TheScriptList: ");
for ( i = 4; i < 6; i++ ) printHex(gpos[i]);
System.out.println(" (" + (gpos[j] << 8 | gpos[j+1]) + ")" );
j = i;
System.out.print("TheFeatureList: ");
for ( i = 6; i < 8; i++ ) printHex(gpos[i]);
System.out.println(" (" + (gpos[j] << 8 | gpos[j+1]) + ")" );
j = i;
System.out.print("TheLookupList: ");
for ( i = 8; i < 10; i++ ) printHex(gpos[i]);
int lookup = (gpos[j] << 8 | gpos[j+1]);
System.out.println(" (" + lookup + ")" );
j = i;
System.out.println("Lookup List Table");
System.out.print("lookupCount: ");
for ( i = lookup; i <= lookup+1; i++ ) printHex(gpos[i]);
System.out.print('\n');
int count = (gpos[lookup] << 8 | gpos[lookup+1]);
int tab = lookup + 2;
int[] LookupList = new int[count];
for ( j = 0; j < count; j++ ) {
System.out.print("lookup[" + j + "] = ");
printHex(gpos[tab]);
printHex(gpos[tab + 1]);
System.out.println(" (" + ( LookupList[j] = (gpos[tab] << 8 | gpos[tab+1]) ) + ")" );
tab += 2;
}
int item, sub, size;
for ( j = 0; j < count; j++ ) {
item = lookup + LookupList[j];
System.out.println("Lookup [" + j + "]");
System.out.println("Lookup Type: " + (gpos[item] << 8 | gpos[item + 1]) );
System.out.print("Lookup flag: ");
printHex(gpos[item + 2]);
printHex(gpos[item + 3]);
size = (gpos[item + 4] << 8 | gpos[item + 5]);
System.out.println("\nNumber of subtables: " + size);
sub = item + 6;
int[] subTable = new int[size];
System.out.println("Subtable offsets");
for ( i = 0; i < size; i++ ) {
subTable[i] = (gpos[sub] << 8 | gpos[sub +1 ]);
sub += 2;
System.out.println( " " + subTable[i] );
}
for ( i = 0; i < size; i++ ) {
System.out.println("Subtable [" + i + "]");
sub = item + subTable[i];
printSubtable(sub);
}
}
}
void printSubtable(int sub) {
int format = gpos[sub] << 8 | gpos[sub + 1];
System.out.println("Format: " + format );
if (format == 1) {
/* TODO format 1*/
return;
}
/* TODO format 2*/
}
This problem is also related to the question How to use kerning pairs extracted from a TTF file to correctly show glyphs as Path2D in Java?.
The context is the same, but since Apache FOP doesn't read Opentype fonts and that Opentype fonts use only the kerning information from GPOS table, it is being much harder.
I am using the Microsoft Opentype reference, but it is way over the top (too vague, no drawings, no example code, and not enough examples). What could be more hints, some drawings, code snippets, more examples (especially for extracting kerning tables from GPOS table)?
How can I make 100% sure this code is really doing what it is supposed to do?
kern
table process) is incredibly hard because langauges are incredibly hard: GPOS is script, langsys, and feature dependent, and may require multiple passes of various GPOS lookups in specific orders to perform correct shaping. Your best bet is to just look at parser code that others have already written (Harfbuzz, Opentype.js, etc). However, it's also wise to post in the right place: typedrawers.com is by far the better forum to ask about font engineering =) – Mike 'Pomax' Kamermans