diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2011-12-01 13:24:38 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2011-12-01 13:24:38 +0000 |
commit | 3131715fb5bce44da6c7584315237731aa752eba (patch) | |
tree | b4e748ed3b19d603c4ac1b29f33340c196003e0e /Build/source/texk/ttfdump/libttf | |
parent | 9417d53067c450b541cecd8c3ae224e5d17b8e54 (diff) |
ttfdump: Added functionality
- do not segfault for fonts without loca table
- allow cmap subtables with format 8, 10, 12, and 13
- handle GPOS and GSUB tables
- additional tests
git-svn-id: svn://tug.org/texlive/trunk@24713 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/ttfdump/libttf')
-rw-r--r-- | Build/source/texk/ttfdump/libttf/cmap.c | 1091 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/font.c | 18 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/glyf.c | 6 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/gpos.c | 971 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/gsub.c | 553 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/head.c | 14 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/hhea.c | 2 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/loca.c | 26 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/maxp.c | 2 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/otfcommon.c | 1074 | ||||
-rw-r--r-- | Build/source/texk/ttfdump/libttf/ttfutil.c | 16 |
11 files changed, 3356 insertions, 417 deletions
diff --git a/Build/source/texk/ttfdump/libttf/cmap.c b/Build/source/texk/ttfdump/libttf/cmap.c index d876cfb8a96..c3ae65f3b61 100644 --- a/Build/source/texk/ttfdump/libttf/cmap.c +++ b/Build/source/texk/ttfdump/libttf/cmap.c @@ -54,32 +54,56 @@ typedef union _TwoBytes { unsigned char c[2]; } TwoBytes; -static void ttfLoadCMAP(FILE *fp,CMAPPtr cmap,ULONG offset); - -static void ttfLoadEncodingTable(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfLoadSubTable(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintSubTable(FILE* fp,SubTablePtr ptable); -static void ttfFreeSubTable(SubTablePtr ptable); - -static void ttfLoadCMAP0(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP0(FILE *fp,SubTablePtr subTable); -static USHORT ttfLookUpCMAP0(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP0(SubTablePtr subTable); - -static void ttfLoadCMAP2(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP2(FILE *fp,SubTablePtr subTable); -static USHORT ttfLookUpCMAP2(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP2(SubTablePtr subTable); - -static void ttfLoadCMAP4(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP4(FILE *fp,SubTablePtr subTable); -static USHORT ttfLookUpCMAP4(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP4(SubTablePtr subTable); - -static void ttfLoadCMAP6(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP6(FILE *fp, SubTablePtr sbuTable); -static USHORT ttfLookUpCMAP6(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP6(SubTablePtr subTable); +static void ttfLoadCMAP(FILE *fp, CMAPPtr cmap, ULONG offset); + +static void ttfLoadSubTable(FILE *fp, SubTablePtr subTable, ULONG offset); +static void ttfPrintSubTable(FILE* fp, SubTablePtr subTable); +static void ttfFreeSubTable(SubTablePtr subTable); + +static void ttfLoadCMAP0(FILE *fp, MapPtr *map); +static void ttfPrintCMAP0(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP0(MapPtr map, USHORT cc); +static void ttfFreeCMAP0(MapPtr map); + +static void ttfLoadCMAP2(FILE *fp, MapPtr *map); +static void ttfPrintCMAP2(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP2(MapPtr map, USHORT cc); +static void ttfFreeCMAP2(MapPtr map); + +static void ttfLoadCMAP4(FILE *fp, MapPtr *map); +static void ttfPrintCMAP4(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP4(MapPtr map, USHORT cc); +static void ttfFreeCMAP4(MapPtr map); + +static void ttfLoadCMAP6(FILE *fp, MapPtr *map); +static void ttfPrintCMAP6(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP6(MapPtr map, USHORT cc); +static void ttfFreeCMAP6(MapPtr map); + +static void ttfLoadCMAP8(FILE *fp, MapPtr *map); +static void ttfPrintCMAP8(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP8(MapPtr map, ULONG cc); +static void ttfFreeCMAP8(MapPtr map); + +static void ttfLoadCMAP10(FILE *fp, MapPtr *map); +static void ttfPrintCMAP10(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP10(MapPtr map, ULONG cc); +static void ttfFreeCMAP10(MapPtr map); + +static void ttfLoadCMAP12(FILE *fp, MapPtr *map); +static void ttfPrintCMAP12(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP12(MapPtr map, ULONG cc); +static void ttfFreeCMAP12(MapPtr map); + +static void ttfLoadCMAP13(FILE *fp, MapPtr *map); +static void ttfPrintCMAP13(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP13(MapPtr map, ULONG cc); +static void ttfFreeCMAP13(MapPtr map); + +static void ttfLoadCMAP14(FILE *fp, MapPtr *map); +static void ttfPrintCMAP14(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP14(MapPtr map, ULONG cc); +static void ttfFreeCMAP14(MapPtr map); void ttfInitCMAP(TTFontPtr font) { @@ -87,34 +111,47 @@ void ttfInitCMAP(TTFontPtr font) TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) - { - font->cmap = XCALLOC1 (CMAP); - ttfLoadCMAP(font->fp,font->cmap,ptd->offset); - } + { + font->cmap = XCALLOC1 (CMAP); + ttfLoadCMAP(font->fp,font->cmap,ptd->offset); + } } static void ttfLoadCMAP(FILE *fp,CMAPPtr cmap,ULONG offset) { USHORT i,n; - ULONG posEnc; /* beginning of the Encoding Table */ - ULONG baseSub = offset; /* base of SubTable offset */ + int k = 0; xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP"); cmap->version = ttfGetUSHORT(fp); cmap->numberOfEncodings = n = ttfGetUSHORT(fp); - cmap->subTables = XCALLOC (cmap->numberOfEncodings, SubTable); - - posEnc = baseSub + sizeof(USHORT)*2; /* step over the beginning of encoding - * table */ - - /* for each encoding scheme, load the encoding table (EncodingTable) and - * the real cmap data (SubTable) */ - for (i=0;i<n;i++,posEnc += 8) - { /* 8 == ushort*2 + ulong*1 */ - ttfLoadEncodingTable(fp,cmap->subTables+i,posEnc); - ttfLoadSubTable(fp,cmap->subTables+i,baseSub); - } + cmap->encoding = XCALLOC (cmap->numberOfEncodings, Encoding); + + for (i = 0; i < n; i++) + { + int j; + + cmap->encoding[i].PlatformID = ttfGetUSHORT(fp); + cmap->encoding[i].EncodingID = ttfGetUSHORT(fp); + cmap->encoding[i].offset = ttfGetULONG(fp); + cmap->encoding[i].mapindex = k++; + for (j = 0; j < i; j++) { + if (cmap->encoding[i].offset == cmap->encoding[j].offset) + { + cmap->encoding[i].mapindex = cmap->encoding[j].mapindex; + k--; + break; + + } + } + } + cmap->numberOfMaps = k; + cmap->subTable = XCALLOC (cmap->numberOfMaps, SubTable); + for (i = 0; i < n; i++) + cmap->subTable[cmap->encoding[i].mapindex].offset = cmap->encoding[i].offset; + for (i = 0; i < k; i++) + ttfLoadSubTable(fp, cmap->subTable+i, offset); } void ttfPrintCMAP(FILE *fp,CMAPPtr cmap) { @@ -122,75 +159,79 @@ void ttfPrintCMAP(FILE *fp,CMAPPtr cmap) fprintf(fp,"'cmap' Table - Character to Glyph Index Mapping Table\n"); fprintf(fp,"-----------------------------------------------------\n"); - fprintf(fp,"\t 'cmap' version: %d\n",cmap->version); - fprintf(fp,"\t number of encoding: %d\n\n",cmap->numberOfEncodings); - - for (i=0;i<cmap->numberOfEncodings;i++) - { - fprintf(fp,"Subtable %3d.\t",i); - ttfPrintSubTable(fp,cmap->subTables+i); - fprintf(fp,"\n"); - } + fprintf(fp,"\t 'cmap' version: %d\n", cmap->version); + fprintf(fp,"\t number of encodings: %d\n", cmap->numberOfEncodings); + fprintf(fp,"\t number of subtables: %d\n\n", cmap->numberOfMaps); + + for (i = 0; i < cmap->numberOfEncodings; i++) + { + fprintf(fp, "Encoding %3d.\t PlatformID: %2d\n", i, + cmap->encoding[i].PlatformID); + fprintf(fp, "\t\t EcodingID: %2d\n", + cmap->encoding[i].EncodingID); + fprintf(fp, "\t\t SubTable: %d, Offset: 0x%08x\n\n", + cmap->encoding[i].mapindex, cmap->encoding[i].offset); + } + for (i = 0; i < cmap->numberOfMaps; i++) + { + fprintf(fp,"SubTable %3d.\t",i); + ttfPrintSubTable(fp, cmap->subTable+i); + fprintf(fp,"\n"); + } } -USHORT ttfLookUpCMAP(SubTablePtr subTable,USHORT cc) +USHORT ttfLookUpCMAP(MapPtr map, USHORT cc) { - USHORT idx,format = subTable->format; + USHORT idx,format = *map.format; switch (format) - { - case 0: - idx = ttfLookUpCMAP0(subTable,cc); - break; - case 2: - idx = ttfLookUpCMAP2(subTable,cc); - break; - case 4: - idx = ttfLookUpCMAP4(subTable,cc); - break; - case 6: - idx = ttfLookUpCMAP6(subTable,cc); - break; - default: - ttfError("Unrecognized CMAP format\n"); - return 0; - } + { + case 0: + idx = ttfLookUpCMAP0(map, cc); + break; + case 2: + idx = ttfLookUpCMAP2(map, cc); + break; + case 4: + idx = ttfLookUpCMAP4(map, cc); + break; + case 6: + idx = ttfLookUpCMAP6(map, cc); + break; + case 8: + idx = ttfLookUpCMAP8(map, cc); + break; + case 10: + idx = ttfLookUpCMAP10(map, cc); + break; + case 12: + idx = ttfLookUpCMAP12(map, cc); + break; + case 13: + idx = ttfLookUpCMAP13(map, cc); + break; + case 14: + idx = ttfLookUpCMAP14(map, cc); + break; + default: + ttfError("Unrecognized CMAP format\n"); + return 0; + } return idx; } -SubTablePtr ttfSelectCMAP(CMAPPtr cmap, USHORT PlatformID, USHORT EncodingID) -{ - USHORT i; - - for (i=0;i<cmap->numberOfEncodings;i++) - { - if ((cmap->subTables+i)->PlatformID == PlatformID && - (cmap->subTables+i)->EncodingID == EncodingID) - return cmap->subTables+i; - } - return NULL; -} void ttfFreeCMAP(CMAPPtr cmap) { USHORT i; - for (i=0;i<cmap->numberOfEncodings;i++) - ttfFreeSubTable(cmap->subTables+i); + free(cmap->encoding); - free(cmap->subTables); - free(cmap); -} + for (i = 0; i < cmap->numberOfMaps; i++) + ttfFreeSubTable(cmap->subTable+i); + free(cmap->subTable); -/* actually, EncodingTable is a part of SubTable */ -static void ttfLoadEncodingTable(FILE *fp,SubTablePtr subTable,ULONG offset) -{ - xfseek(fp, offset, SEEK_SET, "ttfLoadEncodingTable"); - - subTable->PlatformID = ttfGetUSHORT(fp); - subTable->EncodingID = ttfGetUSHORT(fp); - subTable->offset = ttfGetULONG(fp); + free(cmap); } -/* should this one be static ? */ -static void ttfLoadSubTable(FILE *fp,SubTablePtr subTable,ULONG base) +static void ttfLoadSubTable(FILE *fp, SubTablePtr subTable, ULONG offset) { ULONG pos; USHORT format; @@ -198,239 +239,275 @@ static void ttfLoadSubTable(FILE *fp,SubTablePtr subTable,ULONG base) /* seek to the actuall position for this subtable * base: beginning of cmap * offset: offset field of each encoding table */ - pos = base + subTable->offset; - xfseek(fp, pos, SEEK_SET, "ttfLoadSubTable"); + pos = offset + subTable->offset; + xfseek(fp, pos, SEEK_SET, "ttfLoadEncoding"); - subTable->format = format = ttfGetUSHORT(fp); - subTable->length = ttfGetUSHORT(fp); - subTable->version = ttfGetUSHORT(fp); + format = ttfGetUSHORT(fp); - pos += 6;/* step over format independent data,USHORT*3 */ - switch(format) - { - case 0: - ttfLoadCMAP0(fp,subTable,pos); - break; - case 2: - ttfLoadCMAP2(fp,subTable,pos); - break; - case 4: - ttfLoadCMAP4(fp,subTable,pos); - break; - case 6: - ttfLoadCMAP6(fp,subTable,pos); - break; - default: - ttfError("Unrecognized CMAP format\n"); - } -} -static void ttfPrintSubTable(FILE* fp,SubTablePtr ptable) -{ - USHORT format = ptable->format; - - /* print encoding table */ - fprintf(fp, " PlatformID: %2d\n",ptable->PlatformID); - fprintf(fp,"\t\t EcodingID: %2d\n",ptable->EncodingID); - fprintf(fp,"\t\t 'cmap' Offset: 0x%08x\n",ptable->offset); + { + case 0: + ttfLoadCMAP0(fp, &subTable->map); + break; + case 2: + ttfLoadCMAP2(fp, &subTable->map); + break; + case 4: + ttfLoadCMAP4(fp, &subTable->map); + break; + case 6: + ttfLoadCMAP6(fp, &subTable->map); + break; + case 8: + ttfLoadCMAP8(fp, &subTable->map); + break; + case 10: + ttfLoadCMAP10(fp, &subTable->map); + break; + case 12: + ttfLoadCMAP12(fp, &subTable->map); + break; + case 13: + ttfLoadCMAP13(fp, &subTable->map); + break; + case 14: + ttfLoadCMAP14(fp, &subTable->map); + break; + default: + ttfError("Unrecognized CMAP format\n"); + } + + *subTable->map.format = format; +} +static void ttfPrintSubTable(FILE* fp, SubTablePtr subTable) +{ + USHORT format = *subTable->map.format; - /* print SubTable part */ - fprintf(fp,"\t\t Length: %6d\n",ptable->length); - fprintf(fp,"\t\t Version: %6d\n",ptable->version); - switch(format) - { - case 0: - fprintf(fp,"\t\t Format 0 - Byte encoding table\n"); - ttfPrintCMAP0(fp,ptable); - break; - case 2: - fprintf(fp,"\t\t Format 2 - High-byte mapping through table\n"); - ttfPrintCMAP2(fp,ptable); - break; - case 4: - fprintf(fp,"\t\t Format 4 - Segment mapping to delta values\n"); - ttfPrintCMAP4(fp,ptable); - break; - case 6: - fprintf(fp,"\t\t Format 6 - Trimmed table mapping\n"); - ttfPrintCMAP6(fp,ptable); - break; - default: - ttfError("Unrecognized CMAP format\n"); - } -} -static void ttfFreeSubTable(SubTablePtr ptable) -{ - USHORT format = ptable->format; + { + case 0: + ttfPrintCMAP0(fp, subTable->map); + break; + case 2: + ttfPrintCMAP2(fp, subTable->map); + break; + case 4: + ttfPrintCMAP4(fp, subTable->map); + break; + case 6: + ttfPrintCMAP6(fp, subTable->map); + break; + case 8: + ttfPrintCMAP8(fp, subTable->map); + break; + case 10: + ttfPrintCMAP10(fp, subTable->map); + break; + case 12: + ttfPrintCMAP12(fp, subTable->map); + break; + case 13: + ttfPrintCMAP13(fp, subTable->map); + break; + case 14: + ttfPrintCMAP14(fp, subTable->map); + break; + default: + ttfError("Unrecognized CMAP format\n"); + } +} +static void ttfFreeSubTable(SubTablePtr subTable) +{ + USHORT format = *subTable->map.format; switch(format) - { - case 0: - ttfFreeCMAP0(ptable); - break; - case 2: - ttfFreeCMAP2(ptable); - break; - case 4: - ttfFreeCMAP4(ptable); - break; - case 6: - ttfFreeCMAP6(ptable); - break; - } -} - -static void ttfLoadCMAP0(FILE *fp,SubTablePtr subTable,ULONG offset) + { + case 0: + ttfFreeCMAP0(subTable->map); + break; + case 2: + ttfFreeCMAP2(subTable->map); + break; + case 4: + ttfFreeCMAP4(subTable->map); + break; + case 6: + ttfFreeCMAP6(subTable->map); + break; + case 8: + ttfFreeCMAP8(subTable->map); + break; + case 10: + ttfFreeCMAP10(subTable->map); + break; + case 12: + ttfFreeCMAP12(subTable->map); + break; + case 13: + ttfFreeCMAP13(subTable->map); + break; + case 14: + ttfFreeCMAP14(subTable->map); + break; + } +} + +static void ttfLoadCMAP0(FILE *fp, MapPtr *map) { BYTE * array; - subTable->map.cmap0 = XCALLOC1 (CMAP0); - array = subTable->map.cmap0->glyphIndexArray; - - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP0"); + map->cmap0 = XCALLOC1 (CMAP0); + map->cmap0->length = ttfGetUSHORT(fp); + map->cmap0->version = ttfGetUSHORT(fp); + array = map->cmap0->glyphIndexArray; /* Attention: we get lots of bytes at once as a work around of the * usual ttfGet*, this cause byte sex trouble as will be seen - * in the fellowing procedures */ + * in the following procedures */ if (fread(array,sizeof(BYTE),256,fp) != 256) - ttfError("Error when getting glyphIndexArray\n"); + ttfError("Error when getting glyphIndexArray\n"); } -static void ttfPrintCMAP0(FILE *fp,SubTablePtr subTable) +static void ttfPrintCMAP0(FILE *fp, MapPtr map) { USHORT index; int i; + fprintf(fp, " Format 0 - Byte encoding table\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap0->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap0->version); for (i=0;i<256;i++) - { - index = ttfLookUpCMAP(subTable,i); - fprintf(fp,"\t\t Char %3d -> Index %4d\n",i,index); - } + { + index = ttfLookUpCMAP(map, i); + fprintf(fp,"\t\t Char %3d -> Index %4d\n",i,index); + } } -static USHORT ttfLookUpCMAP0(SubTablePtr subTable,USHORT cc) +static USHORT ttfLookUpCMAP0(MapPtr map, USHORT cc) { - return subTable->map.cmap0->glyphIndexArray[cc & 0x00ff]; + return map.cmap0->glyphIndexArray[cc & 0x00ff]; } -static void ttfFreeCMAP0(SubTablePtr subTable) +static void ttfFreeCMAP0(MapPtr map) { - free(subTable->map.cmap0); + free(map.cmap0); } -static void ttfLoadCMAP2(FILE *fp,SubTablePtr subTable,ULONG offset) +static void ttfLoadCMAP2(FILE *fp, MapPtr *map) { USHORT * array,i,n = 0; USHORT numGlyphId; SubHeaderPtr header; - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP2"); - - subTable->map.cmap2 = XCALLOC1 (CMAP2); - array = subTable->map.cmap2->subHeaderKeys; + map->cmap2 = XCALLOC1 (CMAP2); + map->cmap2->length = ttfGetUSHORT(fp); + map->cmap2->version = ttfGetUSHORT(fp); + array = map->cmap2->subHeaderKeys; ttfReadUSHORT (array, 256, fp); for (i=0;i<256;i++) - { - array[i] /= 8; - if (n< array[i]) - n = array[i]; /* find the max of subHeaderKeys */ - } + { + array[i] /= 8; + if (n< array[i]) + n = array[i]; /* find the max of subHeaderKeys */ + } n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ - subTable->map.cmap2->subHeaders = header = XCALLOC (n, SubHeader); + map->cmap2->subHeaders = header = XCALLOC (n, SubHeader); for (i=0;i<n;i++) - { - (header+i)->firstCode = ttfGetUSHORT(fp); - (header+i)->entryCount = ttfGetUSHORT(fp); - (header+i)->idDelta = ttfGetSHORT(fp); - (header+i)->idRangeOffset = ttfGetUSHORT(fp); - - /* it makes things easier to let the offset starts from - * the beginning of glyphIndexArray */ - if ((header+i)->idRangeOffset != 0) - (header+i)->idRangeOffset -= (sizeof(USHORT) + - (n-i-1) * sizeof(SubHeader)) ; - } + { + (header+i)->firstCode = ttfGetUSHORT(fp); + (header+i)->entryCount = ttfGetUSHORT(fp); + (header+i)->idDelta = ttfGetSHORT(fp); + (header+i)->idRangeOffset = ttfGetUSHORT(fp); + + /* it makes things easier to let the offset starts from + * the beginning of glyphIndexArray */ + if ((header+i)->idRangeOffset != 0) + (header+i)->idRangeOffset -= (sizeof(USHORT) + + (n-i-1) * sizeof(SubHeader)) ; + } /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ numGlyphId = - subTable->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); + map->cmap2->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); numGlyphId /= sizeof(USHORT); - subTable->map.cmap2->glyphIndexArray = XCALLOC (numGlyphId, USHORT); + map->cmap2->glyphIndexArray = XCALLOC (numGlyphId, USHORT); for (i=0;i<numGlyphId;i++) - { - subTable->map.cmap2->glyphIndexArray[i] = ttfGetUSHORT(fp); - } + { + map->cmap2->glyphIndexArray[i] = ttfGetUSHORT(fp); + } } -static void ttfPrintCMAP2(FILE *fp,SubTablePtr subTable) +static void ttfPrintCMAP2(FILE *fp, MapPtr map) { USHORT i,j,numGlyphId; USHORT *array,n=0,index; SubHeaderPtr header; TwoBytes tb; - array = subTable->map.cmap2->subHeaderKeys; - header = subTable->map.cmap2->subHeaders; + fprintf(fp, " Format 2 - High-byte mapping through table\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap2->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap2->version); + array = map.cmap2->subHeaderKeys; + header = map.cmap2->subHeaders; for (i=0;i<256;i++) - { - /* find the number of subHeader */ - if (n< array[i]) - n = array[i]; - fprintf(fp,"\t\t subHeaderKeys[%d] = %d\n",i,array[i]); - } + { + /* find the number of subHeader */ + if (n< array[i]) + n = array[i]; + fprintf(fp,"\t\t subHeaderKeys[%d] = %d\n",i,array[i]); + } n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ fprintf(fp,"\t\t Number of SubHeaders is %d\n",n); for (i=0;i<=n;i++) - { - fprintf(fp,"\t\t SubHeader[%d]\n",i); - fprintf(fp,"\t\t firstCode \t 0x%04x\n",(header+i)->firstCode); - fprintf(fp,"\t\t entryCount \t %d\n",(header+i)->entryCount); - fprintf(fp,"\t\t idDelta \t %d\n",(header+i)->idDelta); - fprintf(fp,"\t\t idRangeOffset \t 0x%04x\n\n", - (header+i)->idRangeOffset); - } + { + fprintf(fp,"\t\t SubHeader[%d]\n",i); + fprintf(fp,"\t\t firstCode \t 0x%04x\n",(header+i)->firstCode); + fprintf(fp,"\t\t entryCount \t %d\n",(header+i)->entryCount); + fprintf(fp,"\t\t idDelta \t %d\n",(header+i)->idDelta); + fprintf(fp,"\t\t idRangeOffset \t 0x%04x\n\n", + (header+i)->idRangeOffset); + } /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ numGlyphId = - subTable->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); + map.cmap2->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); numGlyphId /= sizeof(USHORT); fprintf(fp,"Number of glyphIndex: %d\n", numGlyphId); for (i=0;i<numGlyphId;i++) - { - fprintf(fp,"\t\t glyphIdArray[%d] = %4d\n",i, - subTable->map.cmap2->glyphIndexArray[i]); - } + { + fprintf(fp,"\t\t glyphIdArray[%d] = %4d\n",i, + map.cmap2->glyphIndexArray[i]); + } i = 0; fprintf(fp,"\t\t First Byte:\t %2x\n",i); tb.c[1] = i; for(j=0;j<=255;j++) - { - tb.c[0] = j; - index = ttfLookUpCMAP2(subTable,tb.u); - fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); - } + { + tb.c[0] = j; + index = ttfLookUpCMAP2(map, tb.u); + fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); + } for (i=128;i<=255;i++) - { - fprintf(fp,"\t\t First Byte:\t %2x\n",i); - tb.c[1] = i; - for(j=0;j<=255;j++) - { - tb.c[0] = j; - index = ttfLookUpCMAP2(subTable,tb.u); - fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); - } - } -} -static USHORT ttfLookUpCMAP2(SubTablePtr subTable,USHORT cc) + { + fprintf(fp,"\t\t First Byte:\t %2x\n",i); + tb.c[1] = i; + for(j=0;j<=255;j++) + { + tb.c[0] = j; + index = ttfLookUpCMAP2(map, tb.u); + fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); + } + } +} +static USHORT ttfLookUpCMAP2(MapPtr map, USHORT cc) { USHORT index,idx = 0; - USHORT *array = subTable->map.cmap2->subHeaderKeys; - SubHeaderPtr headers = subTable->map.cmap2->subHeaders; + USHORT *array = map.cmap2->subHeaderKeys; + SubHeaderPtr headers = map.cmap2->subHeaders; SHORT idDelta; USHORT firstCode, entryCount, idRangeOffset; TwoBytes tb; @@ -459,195 +536,431 @@ static USHORT ttfLookUpCMAP2(SubTablePtr subTable,USHORT cc) idRangeOffset = (headers+idx)->idRangeOffset / sizeof (USHORT); if (second >= firstCode && second < firstCode+entryCount) - { - /* use idRangeOffset to find where in the glyphIndexArray - * the correspinding index is */ - idRangeOffset += (second - firstCode); - index = subTable->map.cmap2->glyphIndexArray[idRangeOffset]; - if (index != 0) - /* if the character is not a missing character then - * add idDelta to it */ - index += idDelta; - } + { + /* use idRangeOffset to find where in the glyphIndexArray + * the correspinding index is */ + idRangeOffset += (second - firstCode); + index = map.cmap2->glyphIndexArray[idRangeOffset]; + if (index != 0) + /* if the character is not a missing character then + * add idDelta to it */ + index += idDelta; + } else - /* The second code is out ranged then return the - * missing glyph character */ - index = 0; - + /* The second code is out ranged then return the + * missing glyph character */ + index = 0; + return index; } -static void ttfFreeCMAP2(SubTablePtr subTable) +static void ttfFreeCMAP2(MapPtr map) { - free(subTable->map.cmap2->subHeaders); - free(subTable->map.cmap2->glyphIndexArray); - free(subTable->map.cmap2); + free(map.cmap2->subHeaders); + free(map.cmap2->glyphIndexArray); + free(map.cmap2); } -static void ttfLoadCMAP4(FILE *fp,SubTablePtr subTable,ULONG offset) +static void ttfLoadCMAP4(FILE *fp, MapPtr *map) { USHORT segCount; USHORT len; - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP4"); - - subTable->map.cmap4 = XCALLOC1 (CMAP4); + map->cmap4 = XCALLOC1 (CMAP4); + map->cmap4->length = ttfGetUSHORT(fp); + map->cmap4->version = ttfGetUSHORT(fp); - subTable->map.cmap4->segCountX2 = segCount = ttfGetUSHORT(fp); - subTable->map.cmap4->searchRange = ttfGetUSHORT(fp); - subTable->map.cmap4->entrySelector = ttfGetUSHORT(fp); - subTable->map.cmap4->rangeShift = ttfGetUSHORT(fp); + map->cmap4->segCountX2 = segCount = ttfGetUSHORT(fp); + map->cmap4->searchRange = ttfGetUSHORT(fp); + map->cmap4->entrySelector = ttfGetUSHORT(fp); + map->cmap4->rangeShift = ttfGetUSHORT(fp); segCount /= 2; - subTable->map.cmap4->endCount = ttfMakeUSHORT (segCount, fp); + map->cmap4->endCount = ttfMakeUSHORT (segCount, fp); - subTable->map.cmap4->reservedPad = ttfGetUSHORT(fp); + map->cmap4->reservedPad = ttfGetUSHORT(fp); - subTable->map.cmap4->startCount = ttfMakeUSHORT (segCount, fp); + map->cmap4->startCount = ttfMakeUSHORT (segCount, fp); - subTable->map.cmap4->idDelta = ttfMakeUSHORT (segCount, fp); + map->cmap4->idDelta = ttfMakeUSHORT (segCount, fp); - subTable->map.cmap4->idRangeOffset = ttfMakeUSHORT (segCount, fp); + map->cmap4->idRangeOffset = ttfMakeUSHORT (segCount, fp); /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ - len = subTable->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); + len = map->cmap4->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); len /= sizeof(USHORT); - subTable->map.cmap4->glyphIndexArray = ttfMakeUSHORT (len, fp); + map->cmap4->glyphIndexArray = ttfMakeUSHORT (len, fp); } -static void ttfPrintCMAP4(FILE *fp,SubTablePtr subTable) +static void ttfPrintCMAP4(FILE *fp, MapPtr map) { USHORT i; USHORT segCount,len; - segCount = subTable->map.cmap4->segCountX2/2; + fprintf(fp, " Format 4 - Segment mapping to delta values\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap4->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap4->version); + segCount = map.cmap4->segCountX2/2; fprintf(fp, "\t\t segCount:\t %d\n", segCount); - fprintf(fp, "\t\t searchRange:\t %d\n", subTable->map.cmap4->searchRange); - fprintf(fp, "\t\t entrySelector:\t %d\n", subTable->map.cmap4->entrySelector); - fprintf(fp, "\t\t rangeShift:\t %d\n", subTable->map.cmap4->rangeShift); + fprintf(fp, "\t\t searchRange:\t %d\n", map.cmap4->searchRange); + fprintf(fp, "\t\t entrySelector:\t %d\n", map.cmap4->entrySelector); + fprintf(fp, "\t\t rangeShift:\t %d\n", map.cmap4->rangeShift); for (i=0;i<segCount;i++) - { - fprintf(fp, "\t\t Seg %3d :", i); - fprintf(fp, " St = %04x,", subTable->map.cmap4->startCount[i]); - fprintf(fp, " En = %04x,", subTable->map.cmap4->endCount[i]); - /* should this filed be SHORT or USHORT ?? */ - fprintf(fp, " D = %6d," , - (subTable->map.cmap4->idDelta[i])); - fprintf(fp, " RO = %6d," , subTable->map.cmap4->idRangeOffset[i]); - - /* find the glyphIndex correpsonding to this segment */ - if (subTable->map.cmap4->idRangeOffset[i] != 0) - { - USHORT j; - j = subTable->map.cmap4->segCountX2/2 - i; - j = subTable->map.cmap4->idRangeOffset[i] - - j*sizeof(USHORT); - fprintf(fp, " gId# = %d\n", (int) (j/sizeof(USHORT))); - } - else - fprintf(fp, " gId# = N/A\n"); - } + { + fprintf(fp, "\t\t Seg %3d :", i); + fprintf(fp, " St = %04x,", map.cmap4->startCount[i]); + fprintf(fp, " En = %04x,", map.cmap4->endCount[i]); + /* should this filed be SHORT or USHORT ?? */ + fprintf(fp, " D = %6d," , + (map.cmap4->idDelta[i])); + fprintf(fp, " RO = %6d," , map.cmap4->idRangeOffset[i]); + + /* find the glyphIndex correpsonding to this segment */ + if (map.cmap4->idRangeOffset[i] != 0) + { + USHORT j; + j = map.cmap4->segCountX2/2 - i; + j = map.cmap4->idRangeOffset[i] - + j*sizeof(USHORT); + fprintf(fp, " gId# = %d\n", (int) (j/sizeof(USHORT))); + } + else + fprintf(fp, " gId# = N/A\n"); + } /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ - len = subTable->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); + len = map.cmap4->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); len /= sizeof(USHORT); fprintf(fp,"\t\t Number of glyphIndex %d\n",len); for (i=0;i<len;i++) - { - fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, - subTable->map.cmap4->glyphIndexArray[i]); - } + { + fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, + map.cmap4->glyphIndexArray[i]); + } for (i=0;i<segCount;i++) - { - int j,index; - fprintf(fp,"Segment %d:\n",i); - for (j=subTable->map.cmap4->startCount[i]; - j<=subTable->map.cmap4->endCount[i];j++) - { - index = ttfLookUpCMAP4(subTable,j); - fprintf(fp,"\t\tChar 0x%04x -> Index %d\n",j,index); - } - } -} -static USHORT ttfLookUpCMAP4(SubTablePtr subTable,USHORT cc) + { + int j,index; + fprintf(fp,"Segment %d:\n",i); + for (j=map.cmap4->startCount[i]; + j<=map.cmap4->endCount[i];j++) + { + index = ttfLookUpCMAP4(map, j); + fprintf(fp,"\t\tChar 0x%04x -> Index %d\n",j,index); + } + } +} +static USHORT ttfLookUpCMAP4(MapPtr map, USHORT cc) { USHORT i; - USHORT index=0, segCount = subTable->map.cmap4->segCountX2/2; + USHORT index=0, segCount = map.cmap4->segCountX2/2; for (i=0;i<segCount;i++) - { - if (cc <= subTable->map.cmap4->endCount[i] && - cc >= subTable->map.cmap4->startCount[i]) - { - USHORT j; - if (subTable->map.cmap4->idRangeOffset[i] != 0) - { - j = subTable->map.cmap4->idRangeOffset[i] - - (segCount - i)*sizeof(USHORT); - j = cc - subTable->map.cmap4->startCount[i] + j/2; - index = subTable->map.cmap4->glyphIndexArray[j]; - if (index != 0) - index += subTable->map.cmap4->idDelta[i]; - } - else - { - index = cc + subTable->map.cmap4->idDelta[i]; - } - break; - } - } + { + if (cc <= map.cmap4->endCount[i] && + cc >= map.cmap4->startCount[i]) + { + USHORT j; + if (map.cmap4->idRangeOffset[i] != 0) + { + j = map.cmap4->idRangeOffset[i] - + (segCount - i)*sizeof(USHORT); + j = cc - map.cmap4->startCount[i] + j/2; + index = map.cmap4->glyphIndexArray[j]; + if (index != 0) + index += map.cmap4->idDelta[i]; + } + else + { + index = cc + map.cmap4->idDelta[i]; + } + break; + } + } return index; } -static void ttfFreeCMAP4(SubTablePtr subTable) +static void ttfFreeCMAP4(MapPtr map) { - free(subTable->map.cmap4->endCount); - free(subTable->map.cmap4->startCount); - free(subTable->map.cmap4->idDelta); - free(subTable->map.cmap4->idRangeOffset); - free(subTable->map.cmap4->glyphIndexArray); - free(subTable->map.cmap4); + free(map.cmap4->endCount); + free(map.cmap4->startCount); + free(map.cmap4->idDelta); + free(map.cmap4->idRangeOffset); + free(map.cmap4->glyphIndexArray); + free(map.cmap4); } -static void ttfLoadCMAP6(FILE *fp,SubTablePtr subTable,ULONG offset) +static void ttfLoadCMAP6(FILE *fp, MapPtr *map) { USHORT len; - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP6"); - - subTable->map.cmap6 = XCALLOC1 (CMAP6); - subTable->map.cmap6->firstCode = ttfGetUSHORT(fp); - subTable->map.cmap6->entryCount = len = ttfGetUSHORT(fp); - subTable->map.cmap6->glyphIndexArray = ttfMakeUSHORT (len, fp); + map->cmap6 = XCALLOC1 (CMAP6); + map->cmap6->length = ttfGetUSHORT(fp); + map->cmap6->version = ttfGetUSHORT(fp); + map->cmap6->firstCode = ttfGetUSHORT(fp); + map->cmap6->entryCount = len = ttfGetUSHORT(fp); + map->cmap6->glyphIndexArray = ttfMakeUSHORT (len, fp); } -static void ttfPrintCMAP6(FILE *fp, SubTablePtr subTable) +static void ttfPrintCMAP6(FILE *fp, MapPtr map) { USHORT i; - fprintf(fp,"\t\t First Code: 0x%04x\n",subTable->map.cmap6->firstCode); - fprintf(fp,"\t\t Entry Count: %d\n",subTable->map.cmap6->entryCount); + + fprintf(fp, " Format 6 - Trimmed table mapping\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap6->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap6->version); + fprintf(fp,"\t\t First Code: 0x%04x\n", map.cmap6->firstCode); + fprintf(fp,"\t\t Entry Count: %d\n", map.cmap6->entryCount); - for (i=0;i<subTable->map.cmap6->entryCount;i++) - { - fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, - subTable->map.cmap6->glyphIndexArray[i]); - } + for (i=0;i<map.cmap6->entryCount;i++) + { + fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, + map.cmap6->glyphIndexArray[i]); + } } -static USHORT ttfLookUpCMAP6(SubTablePtr subTable,USHORT cc) +static USHORT ttfLookUpCMAP6(MapPtr map, USHORT cc) { USHORT index; - index = cc - subTable->map.cmap6->firstCode; - if (index < subTable->map.cmap6->entryCount) - return subTable->map.cmap6->glyphIndexArray[index]; + index = cc - map.cmap6->firstCode; + if (index < map.cmap6->entryCount) + return map.cmap6->glyphIndexArray[index]; + else + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP6(MapPtr map) +{ + free(map.cmap6->glyphIndexArray); + free(map.cmap6); +} + +static void ttfLoadCMAP8(FILE *fp, MapPtr *map) +{ + int i; + + map->cmap8 = XCALLOC1 (CMAP8); + ttfGetUSHORT(fp); + map->cmap8->length = ttfGetULONG(fp); + map->cmap8->version = ttfGetULONG(fp); + if (fread(map->cmap8->is32, sizeof(BYTE), 8192, fp) != 8192) + ttfError("Error when getting is32\n"); + map->cmap8->nGroups = ttfGetULONG(fp); + map->cmap8->charGroup = XCALLOC (map->cmap8->nGroups, CharGroup); + for (i = 0; i < map->cmap8->nGroups; i++) { + map->cmap8->charGroup[i].startCharCode = ttfGetULONG(fp); + map->cmap8->charGroup[i].endCharCode = ttfGetULONG(fp); + map->cmap8->charGroup[i].startGlyphID = ttfGetULONG(fp); + } +} +static void ttfPrintCMAP8(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 8 - Mixed 16-bit and 32-bit coverage\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap8->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap8->version); + fprintf(fp,"\t\t nGroups: %6d\n", map.cmap8->nGroups); + for (i = 0; i < 256; i++) { + int j; + + fprintf(fp, "\t is32 %2x", i); + for (j = 0; j < 32; j++) + fprintf(fp, j % 4 ? "%2x" : " %2x", map.cmap8->is32[i << 5 | j]); + fprintf(fp, "\n"); + } + for (i = 0; i < map.cmap8->nGroups; i++) + fprintf(fp, "\t\t Group %4d : startCharCode = %d, endCharCode = %d, startGlyphID = %d\n", i, + map.cmap8->charGroup[i].startCharCode, + map.cmap8->charGroup[i].endCharCode, + map.cmap8->charGroup[i].startGlyphID); +} +static USHORT ttfLookUpCMAP8(MapPtr map, ULONG cc) +{ + int i; + + for (i = 0; i < map.cmap8->nGroups; i++) + if (cc > map.cmap8->charGroup[i].endCharCode) + continue; + else if (cc < map.cmap8->charGroup[i].startCharCode) + break; + else + return map.cmap8->charGroup[i].startGlyphID + + (cc - map.cmap8->charGroup[i].startCharCode); + + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP8(MapPtr map) +{ + free(map.cmap8->charGroup); + free(map.cmap8); +} + +static void ttfLoadCMAP10(FILE *fp, MapPtr *map) +{ + ULONG len; + + map->cmap10 = XCALLOC1 (CMAP10); + ttfGetUSHORT(fp); + map->cmap10->length = ttfGetULONG(fp); + map->cmap10->version = ttfGetULONG(fp); + map->cmap10->startCharCode = ttfGetULONG(fp); + map->cmap10->numChars = len = ttfGetULONG(fp); + map->cmap10->glyphs = ttfMakeUSHORT (len, fp); +} +static void ttfPrintCMAP10(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 10 - Trimmed array\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap10->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap10->version); + fprintf(fp,"\t\t Start Char Code: 0x%04x\n", map.cmap10->startCharCode); + fprintf(fp,"\t\t Num Chars: %d\n", map.cmap10->numChars); + + for (i = 0; i < map.cmap10->numChars; i++) + { + fprintf(fp, "\t\t glyphs[%d] = %d\n", i, map.cmap10->glyphs[i]); + } +} +static USHORT ttfLookUpCMAP10(MapPtr map, ULONG cc) +{ + ULONG index; + + index = cc - map.cmap10->startCharCode; + if (index < map.cmap10->numChars) + return map.cmap10->glyphs[index]; else - /* index out of range, return missing glyph */ - return 0; + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP10(MapPtr map) +{ + free(map.cmap10->glyphs); + free(map.cmap10); +} + +static void ttfLoadCMAP12(FILE *fp, MapPtr *map) +{ + int i; + + map->cmap12 = XCALLOC1 (CMAP12); + ttfGetUSHORT(fp); + map->cmap12->length = ttfGetULONG(fp); + map->cmap12->version = ttfGetULONG(fp); + map->cmap12->nGroups = ttfGetULONG(fp); + map->cmap12->charGroup = XCALLOC (map->cmap12->nGroups, CharGroup); + for (i = 0; i < map->cmap12->nGroups; i++) { + map->cmap12->charGroup[i].startCharCode = ttfGetULONG(fp); + map->cmap12->charGroup[i].endCharCode = ttfGetULONG(fp); + map->cmap12->charGroup[i].startGlyphID = ttfGetULONG(fp); + } +} +static void ttfPrintCMAP12(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 12 - Segmented coverage\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap12->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap12->version); + fprintf(fp,"\t\t nGroups: %6d\n", map.cmap12->nGroups); + for (i = 0; i < map.cmap12->nGroups; i++) + fprintf(fp, "\t\t Group %4d : startCharCode = %d, endCharCode = %d, startGlyphID = %d\n", i, + map.cmap12->charGroup[i].startCharCode, + map.cmap12->charGroup[i].endCharCode, + map.cmap12->charGroup[i].startGlyphID); +} +static USHORT ttfLookUpCMAP12(MapPtr map, ULONG cc) +{ + int i; + + for (i = 0; i < map.cmap12->nGroups; i++) + if (cc > map.cmap12->charGroup[i].endCharCode) + continue; + else if (cc < map.cmap12->charGroup[i].startCharCode) + break; + else + return map.cmap12->charGroup[i].startGlyphID + + (cc - map.cmap12->charGroup[i].startCharCode); + + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP12(MapPtr map) +{ + free(map.cmap12->charGroup); + free(map.cmap12); +} + +static void ttfLoadCMAP13(FILE *fp, MapPtr *map) +{ + int i; + + map->cmap13 = XCALLOC1 (CMAP13); + ttfGetUSHORT(fp); + map->cmap13->length = ttfGetULONG(fp); + map->cmap13->version = ttfGetULONG(fp); + map->cmap13->nGroups = ttfGetULONG(fp); + map->cmap13->charGroup = XCALLOC (map->cmap13->nGroups, CharGroup); + for (i = 0; i < map->cmap13->nGroups; i++) { + map->cmap13->charGroup[i].startCharCode = ttfGetULONG(fp); + map->cmap13->charGroup[i].endCharCode = ttfGetULONG(fp); + map->cmap13->charGroup[i].startGlyphID = ttfGetULONG(fp); + } +} +static void ttfPrintCMAP13(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 13 - Many-to-one range mappings\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap13->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap13->version); + fprintf(fp,"\t\t nGroups: %6d\n", map.cmap13->nGroups); + for (i = 0; i < map.cmap13->nGroups; i++) + fprintf(fp, "\t\t Group %4d : startCharCode = %d, endCharCode = %d, glyphID = %d\n", i, + map.cmap13->charGroup[i].startCharCode, + map.cmap13->charGroup[i].endCharCode, + map.cmap13->charGroup[i].startGlyphID); +} +static USHORT ttfLookUpCMAP13(MapPtr map, ULONG cc) +{ + int i; + + for (i = 0; i < map.cmap13->nGroups; i++) + if (cc > map.cmap13->charGroup[i].endCharCode) + continue; + else if (cc < map.cmap13->charGroup[i].startCharCode) + break; + else + return map.cmap12->charGroup[i].startGlyphID; + + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP13(MapPtr map) +{ + free(map.cmap13->charGroup); + free(map.cmap13); +} + +static void ttfLoadCMAP14(FILE *fp, MapPtr *map) +{ + map->cmap14 = XCALLOC1 (CMAP14); + map->cmap14->length = ttfGetULONG(fp); +} +static void ttfPrintCMAP14(FILE *fp, MapPtr map) +{ + fprintf(fp, " Format 14 - Unicode variation sequences\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap14->length); + fprintf(fp,"\t\t *** NOT YET IMPLEMENTED ***\n"); +} +static USHORT ttfLookUpCMAP14(MapPtr map, ULONG cc) +{ + return 0; } -static void ttfFreeCMAP6(SubTablePtr subTable) +static void ttfFreeCMAP14(MapPtr map) { - free(subTable->map.cmap6->glyphIndexArray); - free(subTable->map.cmap6); + free(map.cmap14); } diff --git a/Build/source/texk/ttfdump/libttf/font.c b/Build/source/texk/ttfdump/libttf/font.c index 0ee6c25ec02..8b5e0d0a247 100644 --- a/Build/source/texk/ttfdump/libttf/font.c +++ b/Build/source/texk/ttfdump/libttf/font.c @@ -42,6 +42,7 @@ void ttfLoadFont(TTFontPtr font, ULONG offset) ttfLoadRequiredTables(font); ttfLoadOptionalTables(font); + ttfLoadOpenTypeTables(font); ttfInitInterpreter(font); @@ -55,6 +56,8 @@ void ttfFreeFont(TTFontPtr font) ttfFreeOptionalTables(font); + ttfFreeOpenTypeTables(font); + ttfFreeTableDir(font->dir); free(font->refcount); free(font); @@ -67,7 +70,6 @@ void ttfLoadRequiredTables(TTFontPtr font) ttfInitMAXP(font); ttfInitHEAD(font); - ttfInitLOCA(font); ttfInitGlyphCache(font); ttfInitGLYF(font); @@ -85,7 +87,6 @@ void ttfFreeRequiredTables(TTFontPtr font) ttfFreeNAME(font->name); ttfCleanUpGlyphCache(font); - ttfFreeLOCA(font->loca); ttfFreeHEAD(font->head); ttfFreeMAXP(font->maxp); @@ -103,6 +104,7 @@ void ttfLoadOptionalTables(TTFontPtr font) ttfInitGASP(font); ttfInitHDMX(font); ttfInitKERN(font); + ttfInitLOCA(font); ttfInitPREP(font); ttfInitLTSH(font); ttfInitPCLT(font); @@ -117,6 +119,7 @@ void ttfFreeOptionalTables(TTFontPtr font) ttfFreeGASP(font->gasp); ttfFreeHDMX(font->hdmx); ttfFreeKERN(font->kern); + ttfFreeLOCA(font->loca); ttfFreePREP(font->prep); ttfFreeLTSH(font->ltsh); ttfFreePCLT(font->pclt); @@ -125,6 +128,17 @@ void ttfFreeOptionalTables(TTFontPtr font) ttfFreeVMTX(font->vmtx); } +void ttfLoadOpenTypeTables(TTFontPtr font) +{ + ttfInitGPOS(font); + ttfInitGSUB(font); +} +void ttfFreeOpenTypeTables(TTFontPtr font) +{ + ttfFreeGPOS(font->gpos); + ttfFreeGSUB(font->gsub); +} + #if 0 /* Not used */ /* make a clone of the origional font diff --git a/Build/source/texk/ttfdump/libttf/glyf.c b/Build/source/texk/ttfdump/libttf/glyf.c index 9804d1bb126..ca922d0e07f 100644 --- a/Build/source/texk/ttfdump/libttf/glyf.c +++ b/Build/source/texk/ttfdump/libttf/glyf.c @@ -54,8 +54,8 @@ void ttfLoadGLYF(FILE *fp, GLYFPtr glyf, ULONG offset) } void ttfPrintGLYF(FILE *fp, GLYFPtr glyf) { - fprintf(fp,"\t numberOfContours:\t %d %s\n", glyf->numberOfContours, - glyf->numberOfContours == -1 ? "(Composite)": ""); + fprintf(fp,"\t numberOfContours:\t %d%s\n", glyf->numberOfContours, + glyf->numberOfContours == -1 ? " (Composite)": ""); fprintf(fp,"\t xMin:\t\t\t %d\n", glyf->xMin); fprintf(fp,"\t yMin:\t\t\t %d\n", glyf->yMin); fprintf(fp,"\t xMax:\t\t\t %d\n", glyf->xMax); @@ -404,7 +404,7 @@ GLYFPtr ttfLoadGlyphCode(TTFont *font,USHORT cc) { USHORT index; - index = ttfLookUpCMAP(font->encoding,cc); + index = ttfLookUpCMAP(font->encoding->map,cc); return ttfLoadGlyphIndex(font,index); } diff --git a/Build/source/texk/ttfdump/libttf/gpos.c b/Build/source/texk/ttfdump/libttf/gpos.c new file mode 100644 index 00000000000..9d040298099 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gpos.c @@ -0,0 +1,971 @@ +/* gpos.c -- Glyph Positioning Table + */ +#include <stdio.h> +#include <stdlib.h> +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +static USHORT getValueFormat (FILE *fp) +{ + USHORT valueFormat = ttfGetUSHORT (fp); + + if (valueFormat & ValueFormat_Reserved) + ttfError ("Unrecognized GPOS valueFormat\n"); + + return valueFormat; +} + +static ValueRecordPtr +gposMakeValueRecord (USHORT valueFormat, FILE *fp, ULONG offset) +{ + int i; + ValueRecordPtr value; + + if (valueFormat == 0) + return NULL; + + value = XCALLOC1 (ValueRecord); + for (i = 0; i < 4; i++) + if (valueFormat & (ValueFormat_XPlacement << i)) + value->valDesign[i] = ttfGetSHORT (fp); + for (i = 0; i < 4; i++) + if (valueFormat & (ValueFormat_XPlaDevice << i)) + ttfGetUSHORT (fp); + + return value; +} + +static const char *txtDesign[4] = { + "XPlacement", + "YPlacement", + "XAdvance", + "YAdvance" +}; + +static void +gposPrintValueRecord (FILE *fp, const char *str, USHORT valueFormat, ValueRecordPtr value) +{ + const char *s = ":"; + int i; + + for (i = 0; i < 4; i++) + if (valueFormat & (ValueFormat_XPlacement << i)) { + fprintf (fp, "%s %s = %d\n", s, txtDesign[i], value->valDesign[i]); + s = str; + } + if (valueFormat & ValueFormat_AllDevice) + fprintf (fp, "\t\t *** Device Table NOT YET IMPLEMENTED ***\n"); +} + +static void freeValueRecord (ValueRecordPtr value) +{ + if (value) { + int i; + + for (i = 0; i < 4; i++) + if (value->valDevice[i]) + free (value->valDevice[i]); + free (value); + } +} + +static AnchorPtr gposMakeAnchor (FILE *fp, ULONG offset) +{ + AnchorPtr anchor; + USHORT anchorFormat; + USHORT xOffset, yOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeAnchor"); + + anchorFormat = ttfGetUSHORT (fp); + switch (anchorFormat) + { + case 1: + anchor.anchor1 = XCALLOC1 (Anchor1); + break; + case 2: + anchor.anchor2 = XCALLOC1 (Anchor2); + break; + case 3: + anchor.anchor3 = XCALLOC1 (Anchor3); + break; + default: + ttfError ("Unrecognized GPOS anchorFormat\n"); + } + anchor.anchor1->anchorFormat = anchorFormat; + anchor.anchor1->xCoordinate = ttfGetSHORT (fp); + anchor.anchor1->yCoordinate = ttfGetSHORT (fp); + + switch (anchorFormat) + { + case 2: + anchor.anchor2->anchorPoint = ttfGetUSHORT (fp); + break; + case 3: + xOffset = ttfGetUSHORT (fp); + yOffset = ttfGetUSHORT (fp); + if (xOffset) + anchor.anchor3->xDevice = otfMakeDevice (fp, offset + xOffset); + if (yOffset) + anchor.anchor3->yDevice = otfMakeDevice (fp, offset + yOffset); + break; + } + + return anchor; +} + +static void +gposPrintAnchor (FILE *fp, const char *str, AnchorPtr anchor) +{ + fprintf (fp, "anchorFormat = %d, xCoordinate = %d, yCoordinate = %d\n", + anchor.anchor1->anchorFormat, anchor.anchor1->xCoordinate, anchor.anchor1->yCoordinate); + + switch (anchor.anchor1->anchorFormat) + { + case 2: + fprintf (fp, "%sanchorPoint = %d\n", str, anchor.anchor2->anchorPoint); + break; + case 3: + if (anchor.anchor3->xDevice) { + fprintf (fp, "%sxDevice: ", str); + otfPrintDevice (fp, anchor.anchor3->xDevice); + } + if (anchor.anchor3->yDevice) { + fprintf (fp, "%syDevice: ", str); + otfPrintDevice (fp, anchor.anchor3->yDevice); + } + break; + } +} + +static void freeAnchor (AnchorPtr anchor) +{ + if (anchor.anchor3) { + if (anchor.anchor3->anchorFormat == 3) { + if (anchor.anchor3->xDevice) + free (anchor.anchor3->xDevice); + if (anchor.anchor3->yDevice) + free (anchor.anchor3->yDevice); + } + free (anchor.anchor3); + } +} + +static MarkRecordPtr +gposMakeMarkArray (FILE *fp, USHORT *markCount, ULONG offset) +{ + int i; + MarkRecordPtr markArray; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeMarkArray"); + + *markCount = ttfGetUSHORT (fp); + markArray = XCALLOC (*markCount, MarkRecord); + aOffset = XCALLOC (*markCount, USHORT); + for (i = 0; i < *markCount; i++) { + markArray[i].class = ttfGetUSHORT (fp); + aOffset[i] = ttfGetUSHORT (fp); + } + for (i = 0; i < *markCount; i++) + markArray[i].markAnchor = gposMakeAnchor (fp, offset + aOffset[i]); + free (aOffset); + + return markArray; +} + +static void +gposPrintMarkArray (FILE *fp, USHORT markCount, MarkRecordPtr markArray) +{ + int i; + + for (i = 0; i < markCount; i++) { + fprintf (fp, "\t %2d. class: %d - ", i, markArray[i].class); + gposPrintAnchor (fp, "\t\t ", markArray[i].markAnchor); + } +} + +/* Used for both pos41->baseArray and pos61->mark2Array. */ +static AnchorPtr * +gposMakeBaseArray (FILE *fp, USHORT *baseCount, USHORT classCount, ULONG offset) +{ + int i; + AnchorPtr *baseArray; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeBaseArray"); + + *baseCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (*baseCount * classCount, fp); + baseArray = XCALLOC (*baseCount * classCount, AnchorPtr); + for (i = 0; i < *baseCount * classCount; i++) + if (aOffset[i]) + baseArray[i] = gposMakeAnchor (fp, offset + aOffset[i]); + free (aOffset); + + return baseArray; +} + +static Pos11Ptr makeGPOS11 (FILE *fp, ULONG offset) +{ + USHORT cOffset; + Pos11Ptr pos = XCALLOC1 (Pos11); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat = getValueFormat (fp); + pos->value = gposMakeValueRecord (pos->valueFormat, fp, offset); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + + return pos; +} + +static void printGPOS11 (FILE *fp, Pos11Ptr pos) +{ + fprintf (fp, " - Single Adjustment Value\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat: 0x%04x\n", pos->valueFormat); + if (pos->valueFormat) { + fprintf (fp, "\t value"); + gposPrintValueRecord (fp, "\t\t", pos->valueFormat, pos->value); + } +} + +static void freeGPOS11 (Pos11Ptr pos) +{ + freeValueRecord (pos->value); + otfFreeCoverage (pos->coverage); +} + +static Pos12Ptr makeGPOS12 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + Pos12Ptr pos = XCALLOC1 (Pos12); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat = getValueFormat (fp); + pos->valueCount = ttfGetUSHORT (fp); + pos->value = XCALLOC (pos->valueCount, ValueRecordPtr); + for (i = 0; i < pos->valueCount; i++) + pos->value[i] = gposMakeValueRecord (pos->valueFormat, fp, offset); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + + return pos; +} + +static void printGPOS12 (FILE *fp, Pos12Ptr pos) +{ + int i; + + fprintf (fp, " - Single Adjustment List\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat: 0x%04x, valueCount: %d\n", pos->valueFormat, pos->valueCount); + for (i = 0; i < pos->valueCount; i++) { + fprintf (fp, "\t %2d. value", i); + gposPrintValueRecord (fp, "\t\t ", pos->valueFormat, pos->value[i]); + } +} + +static void freeGPOS12 (Pos12Ptr pos) +{ + int i; + + for (i = 0; i < pos->valueCount; i++) + freeValueRecord (pos->value[i]); + free (pos->value); + otfFreeCoverage (pos->coverage); +} + +static void gposLoadPairSet (Pos21Ptr pos, int i, FILE *fp, ULONG offset, USHORT poff) +{ + int j; + PairSetPtr pairSet = &pos->pairSet[i]; + + xfseek (fp, offset + poff, SEEK_SET, "gposLoadPairSet"); + + pairSet->pairValueCount = ttfGetUSHORT (fp); + pairSet->pairValue = XCALLOC (pairSet->pairValueCount, PairValueRecord); + for (j = 0; j < pairSet->pairValueCount; j++) { + pairSet->pairValue[j].secondGlyph = ttfGetUSHORT (fp); + pairSet->pairValue[j].value1 = gposMakeValueRecord (pos->valueFormat1, fp, offset); + pairSet->pairValue[j].value2 = gposMakeValueRecord (pos->valueFormat2, fp, offset); + } +} + +static Pos21Ptr makeGPOS21 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *pOffset; + Pos21Ptr pos = XCALLOC1 (Pos21); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat1 = getValueFormat (fp); + pos->valueFormat2 = getValueFormat (fp); + pos->pairSetCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (pos->pairSetCount, fp); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->pairSet = XCALLOC (pos->pairSetCount, PairSet); + for (i = 0; i < pos->pairSetCount; i++) + gposLoadPairSet (pos, i, fp, offset, pOffset[i]); + free (pOffset); + + return pos; +} + +static void printGPOS21 (FILE *fp, Pos21Ptr pos) +{ + int i; + + fprintf (fp, " - Pair Adjustment List\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat1: 0x%04x, valueFormat2: 0x%04x, pairSetCount: %d\n", + pos->valueFormat1, pos->valueFormat2, pos->pairSetCount); + for (i = 0; i < pos->pairSetCount; i++) { + int j; + fprintf (fp, "\t %2d. pairValueCount: %d\n", i, pos->pairSet[i].pairValueCount); + for (j = 0; j < pos->pairSet[i].pairValueCount; j++) { + fprintf (fp, "\t %2d. secondGlyph: %d\n", j, + pos->pairSet[i].pairValue[j].secondGlyph); + if (pos->valueFormat1) { + fprintf (fp, "\t\t value1"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat1, + pos->pairSet[i].pairValue[j].value1); + } + if (pos->valueFormat2) { + fprintf (fp, "\t\t value2"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat2, + pos->pairSet[i].pairValue[j].value2); + } + } + } +} + +static void freeGPOS21 (Pos21Ptr pos) +{ + int i; + + for (i = 0; i < pos->pairSetCount; i++) { + int j; + for (j = 0; j < pos->pairSet[i].pairValueCount; j++) { + freeValueRecord (pos->pairSet[i].pairValue[j].value1); + freeValueRecord (pos->pairSet[i].pairValue[j].value2); + } + free (pos->pairSet[i].pairValue); + } + free (pos->pairSet); + otfFreeCoverage (pos->coverage); +} + +static Pos22Ptr makeGPOS22 (FILE *fp, ULONG offset) +{ + int num = 0, i; + USHORT cOffset, cOffset1, cOffset2; + Pos22Ptr pos = XCALLOC1 (Pos22); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat1 = getValueFormat (fp); + pos->valueFormat2 = getValueFormat (fp); + cOffset1 = ttfGetUSHORT (fp); + cOffset2 = ttfGetUSHORT (fp); + pos->class1Count = ttfGetUSHORT (fp); + pos->class2Count = ttfGetUSHORT (fp); + pos->values = XCALLOC (2 * pos->class1Count * pos->class2Count, ValueRecordPtr); + for (i = 0; i < pos->class1Count; i++) { + int j; + + for (j = 0; j < pos->class2Count; j++) { + pos->values[num++] = gposMakeValueRecord (pos->valueFormat1, fp, offset); + pos->values[num++] = gposMakeValueRecord (pos->valueFormat2, fp, offset); + } + } + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->classDef1 = otfMakeClassDef (fp, offset + cOffset1); + pos->classDef2 = otfMakeClassDef (fp, offset + cOffset2); + + return pos; +} + +static void printGPOS22 (FILE *fp, Pos22Ptr pos) +{ + int num = 0, i; + + fprintf (fp, " - Pair Adjustment Class\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat1: 0x%04x, valueFormat2: 0x%04x\n", + pos->valueFormat1, pos->valueFormat2); + fprintf (fp, "\t ClassDef1 - "); + otfPrintClassDef (fp, pos->classDef1); + fprintf (fp, "\t ClassDef2 - "); + otfPrintClassDef (fp, pos->classDef2); + fprintf (fp, "\t class1Count: %d, class2Count: %d\n", + pos->class1Count, pos->class2Count); + for (i = 0; i < pos->class1Count; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d.", i); + for (j = 0; j < pos->class2Count; j++) { + fprintf (fp, "%s %2d.", s, j); + s = "\t "; + + if (pos->valueFormat1) { + fprintf (fp, " value1"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat1, + pos->values[num]); + } + num++; + if (pos->valueFormat2) { + fprintf (fp, " value2"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat2, + pos->values[num]); + } + num++; + } + } +} + +static void freeGPOS22 (Pos22Ptr pos) +{ + int i; + + for (i = 0; i < 2 * pos->class1Count * pos->class2Count; i++) + freeValueRecord (pos->values[i]); + free (pos->values); + otfFreeCoverage (pos->coverage); + otfFreeClassDef (pos->classDef1); + otfFreeClassDef (pos->classDef2); +} + +static Pos31Ptr makeGPOS31 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *eOffset; + Pos31Ptr pos = XCALLOC1 (Pos31); + + cOffset = ttfGetUSHORT (fp); + pos->entryExitCount = ttfGetUSHORT (fp); + eOffset = ttfMakeUSHORT (2 * pos->entryExitCount, fp); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->entryExit = XCALLOC (2 * pos->entryExitCount, AnchorPtr); + for (i = 0; i < 2 * pos->entryExitCount; i++) + if (eOffset[i]) + pos->entryExit[i] = gposMakeAnchor (fp, offset + eOffset[i]); + free (eOffset); + + return pos; +} + +static void printGPOS31 (FILE *fp, Pos31Ptr pos) +{ + int i, num = 0; + fprintf (fp, " - Cursive Attachment\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t entryExitCount: %d\n", pos->entryExitCount); + for (i = 0; i < pos->entryExitCount; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d. ", i); + for (j = 0; j < 2; j++) { + if (pos->entryExit[num].anchor1) { + fprintf (fp, "%s%sAnchor - ", s, j ? "exit" : "entry"); + gposPrintAnchor (fp, "\t\t ", pos->entryExit[num]); + s = "\t "; + } + num++; + } + } +} + +static void freeGPOS31 (Pos31Ptr pos) +{ + int i; + + for (i = 0; i < 2 * pos->entryExitCount; i++) + freeAnchor (pos->entryExit[i]); + free (pos->entryExit); + otfFreeCoverage (pos->coverage); +} + +static Pos41Ptr makeGPOS41 (FILE *fp, ULONG offset) +{ + USHORT mcOffset, bcOffset, maOffset, baOffset; + Pos41Ptr pos = XCALLOC1 (Pos41); + + mcOffset = ttfGetUSHORT (fp); + bcOffset = ttfGetUSHORT (fp); + pos->classCount = ttfGetUSHORT (fp); + maOffset = ttfGetUSHORT (fp); + baOffset = ttfGetUSHORT (fp); + pos->markCoverage = otfMakeCoverage (fp, offset + mcOffset); + pos->baseCoverage = otfMakeCoverage (fp, offset + bcOffset); + pos->markArray = gposMakeMarkArray (fp, &pos->markCount, offset + maOffset); + pos->baseArray = gposMakeBaseArray (fp, &pos->baseCount, pos->classCount, offset + baOffset); + + return pos; +} + +static void printGPOS41 (FILE *fp, Pos41Ptr pos) +{ + int i, num = 0; + + fprintf (fp, " - Mark To Base Attachment\n\t mark"); + otfPrintCoverage (fp, pos->markCoverage); + fprintf (fp, "\t markArray - markCount: %d\n", pos->markCount); + gposPrintMarkArray (fp, pos->markCount, pos->markArray); + fprintf (fp, "\t base"); + otfPrintCoverage (fp, pos->baseCoverage); + fprintf (fp, "\t baseArray - baseCount: %d, classCount: %d\n", + pos->baseCount, pos->classCount); + for (i = 0; i < pos->baseCount; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d. ", i); + for (j = 0; j < pos->classCount; j++) { + if (pos->baseArray[num].anchor1) { + fprintf (fp, "%s%2d. ", s, j); + gposPrintAnchor (fp, "\t\t ", pos->baseArray[num]); + s = "\t "; + } + num++; + } + } +} + +static void freeGPOS41 (Pos41Ptr pos) +{ + int i; + + for (i = 0; i < pos->markCount; i++) + freeAnchor (pos->markArray[i].markAnchor); + free (pos->markArray); + for (i = 0; i < pos->baseCount * pos->classCount; i++) + freeAnchor (pos->baseArray[i]); + free (pos->baseArray); + otfFreeCoverage (pos->markCoverage); + otfFreeCoverage (pos->baseCoverage); +} + +static void +gposLoadLigatureArray (LigatureAttachPtr ligatureArray, USHORT classCount, FILE *fp, ULONG offset) +{ + int i; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposLoadLigatureArray"); + + ligatureArray->componentCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (ligatureArray->componentCount * classCount, fp); + ligatureArray->componentRecord = XCALLOC (ligatureArray->componentCount * classCount, AnchorPtr); + for (i = 0; i < ligatureArray->componentCount * classCount; i++) + if (aOffset[i]) + ligatureArray->componentRecord[i] = gposMakeAnchor (fp, offset + aOffset[i]); + free (aOffset); +} + +static LigatureAttachPtr +gposMakeLigatureArray (FILE *fp, USHORT *ligatureCount, USHORT classCount, ULONG offset) +{ + int i; + LigatureAttachPtr ligatureArray; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeLigatureArray"); + + *ligatureCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (*ligatureCount, fp); + ligatureArray = XCALLOC (*ligatureCount, LigatureAttach); + for (i = 0; i < *ligatureCount; i++) + gposLoadLigatureArray (&ligatureArray[i], classCount, fp, offset + aOffset[i]); + free (aOffset); + + return ligatureArray; +} + +static Pos51Ptr makeGPOS51 (FILE *fp, ULONG offset) +{ + USHORT mcOffset, lcOffset, maOffset, laOffset; + Pos51Ptr pos = XCALLOC1 (Pos51); + + mcOffset = ttfGetUSHORT (fp); + lcOffset = ttfGetUSHORT (fp); + pos->classCount = ttfGetUSHORT (fp); + maOffset = ttfGetUSHORT (fp); + laOffset = ttfGetUSHORT (fp); + pos->markCoverage = otfMakeCoverage (fp, offset + mcOffset); + pos->ligatureCoverage = otfMakeCoverage (fp, offset + lcOffset); + pos->markArray = gposMakeMarkArray (fp, &pos->markCount, offset + maOffset); + pos->ligatureArray = gposMakeLigatureArray (fp, &pos->ligatureCount, pos->classCount, offset + laOffset); + + return pos; +} + +static void printGPOS51 (FILE *fp, Pos51Ptr pos) +{ + int i; + + fprintf (fp, " - Mark To Ligature Attachment\n\t mark"); + otfPrintCoverage (fp, pos->markCoverage); + fprintf (fp, "\t markArray - markCount: %d\n", pos->markCount); + gposPrintMarkArray (fp, pos->markCount, pos->markArray); + fprintf (fp, "\t ligature"); + otfPrintCoverage (fp, pos->ligatureCoverage); + fprintf (fp, "\t ligatureArray - ligatureCount: %d\n", pos->ligatureCount); + for (i = 0; i < pos->ligatureCount; i++) { + int j, num = 0; + + fprintf (fp, "\t %2d. componentCount: %d, classCount: %d\n", i, + pos->ligatureArray[i].componentCount, pos->classCount); + for (j = 0; j < pos->ligatureArray[i].componentCount; j++) { + int k; + const char *s = ""; + + fprintf (fp, "\t %2d. ", j); + for (k = 0; k < pos->classCount; k++) { + if (pos->ligatureArray[i].componentRecord[num].anchor1) { + fprintf (fp, "%s%2d. ", s, k); + gposPrintAnchor (fp, "\t\t ", pos->ligatureArray[i].componentRecord[num]); + s = "\t\t "; + } + num++; + } + } + } +} + +static void freeGPOS51 (Pos51Ptr pos) +{ + int i; + + for (i = 0; i < pos->markCount; i++) + freeAnchor (pos->markArray[i].markAnchor); + free (pos->markArray); + for (i = 0; i < pos->ligatureCount; i++) { + int j; + + for (j = 0; j < pos->ligatureArray[i].componentCount * pos->classCount; j++) + freeAnchor (pos->ligatureArray[i].componentRecord[j]); + } + free (pos->ligatureArray); + otfFreeCoverage (pos->markCoverage); + otfFreeCoverage (pos->ligatureCoverage); +} + +static Pos61Ptr makeGPOS61 (FILE *fp, ULONG offset) +{ + USHORT c1Offset, c2Offset, a1Offset, a2Offset; + Pos61Ptr pos = XCALLOC1 (Pos61); + + c1Offset = ttfGetUSHORT (fp); + c2Offset = ttfGetUSHORT (fp); + pos->classCount = ttfGetUSHORT (fp); + a1Offset = ttfGetUSHORT (fp); + a2Offset = ttfGetUSHORT (fp); + pos->mark1Coverage = otfMakeCoverage (fp, offset + c1Offset); + pos->mark2Coverage = otfMakeCoverage (fp, offset + c2Offset); + pos->mark1Array = gposMakeMarkArray (fp, &pos->mark1Count, offset + a1Offset); + pos->mark2Array = gposMakeBaseArray (fp, &pos->mark2Count, pos->classCount, offset + a2Offset); + + return pos; +} + +static void printGPOS61 (FILE *fp, Pos61Ptr pos) +{ + int i, num = 0; + + fprintf (fp, " - Mark To Mark Attachment\n\t mark1"); + otfPrintCoverage (fp, pos->mark1Coverage); + fprintf (fp, "\t mark1Array - mark1Count: %d\n", pos->mark1Count); + gposPrintMarkArray (fp, pos->mark1Count, pos->mark1Array); + fprintf (fp, "\t mark2"); + otfPrintCoverage (fp, pos->mark2Coverage); + fprintf (fp, "\t mark2Array - mark2Count: %d, classCount: %d\n", + pos->mark2Count, pos->classCount); + for (i = 0; i < pos->mark2Count; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d. ", i); + for (j = 0; j < pos->classCount; j++) { + if (pos->mark2Array[num].anchor1) { + fprintf (fp, "%s%2d. ", s, j); + gposPrintAnchor (fp, "\t\t ", pos->mark2Array[num]); + s = "\t "; + } + num++; + } + } +} + +static void freeGPOS61 (Pos61Ptr pos) +{ + int i; + + for (i = 0; i < pos->mark1Count; i++) + freeAnchor (pos->mark1Array[i].markAnchor); + free (pos->mark1Array); + for (i = 0; i < pos->mark2Count * pos->classCount; i++) + freeAnchor (pos->mark2Array[i]); + free (pos->mark2Array); + otfFreeCoverage (pos->mark1Coverage); + otfFreeCoverage (pos->mark2Coverage); +} + +#define makeGPOS71 makeOTFCtx1 +#define printGPOS71 printOTFCtx1 +#define freeGPOS71 freeOTFCtx1 + +#define makeGPOS72 makeOTFCtx2 +#define printGPOS72 printOTFCtx2 +#define freeGPOS72 freeOTFCtx2 + +#define makeGPOS73 makeOTFCtx3 +#define printGPOS73 printOTFCtx3 +#define freeGPOS73 freeOTFCtx3 + +#define makeGPOS81 makeOTFChn1 +#define printGPOS81 printOTFChn1 +#define freeGPOS81 freeOTFChn1 + +#define makeGPOS82 makeOTFChn2 +#define printGPOS82 printOTFChn2 +#define freeGPOS82 freeOTFChn2 + +#define makeGPOS83 makeOTFChn3 +#define printGPOS83 printOTFChn3 +#define freeGPOS83 freeOTFChn3 + +static LookupPtr makeGPOSLookup (FILE *fp, USHORT lookupType, ULONG offset) +{ + LookupPtr lookup; + USHORT lookupFormat; + +again: + if (lookupType == 0 || lookupType > PosLookup_Max) + ttfError ("Unrecognized GPOS lookupType\n"); + + xfseek (fp, offset, SEEK_SET, "makeGPOSLookup"); + + lookupFormat = ttfGetUSHORT (fp); + if (lookupFormat & 0xfff0) + lookupFormat = 0x000f; + + switch (lookupType << 4 | lookupFormat) + { + case 0x011: + lookup.pos.pos11 = makeGPOS11 (fp, offset); + break; + case 0x012: + lookup.pos.pos12 = makeGPOS12 (fp, offset); + break; + case 0x021: + lookup.pos.pos21 = makeGPOS21 (fp, offset); + break; + case 0x022: + lookup.pos.pos22 = makeGPOS22 (fp, offset); + break; + case 0x031: + lookup.pos.pos31 = makeGPOS31 (fp, offset); + break; + case 0x041: + lookup.pos.pos41 = makeGPOS41 (fp, offset); + break; + case 0x051: + lookup.pos.pos51 = makeGPOS51 (fp, offset); + break; + case 0x061: + lookup.pos.pos61 = makeGPOS61 (fp, offset); + break; + case 0x071: + lookup.pos.pos71 = makeGPOS71 (fp, offset); + break; + case 0x072: + lookup.pos.pos72 = makeGPOS72 (fp, offset); + break; + case 0x073: + lookup.pos.pos73 = makeGPOS73 (fp, offset); + break; + case 0x081: + lookup.pos.pos81 = makeGPOS81 (fp, offset); + break; + case 0x082: + lookup.pos.pos82 = makeGPOS82 (fp, offset); + break; + case 0x083: + lookup.pos.pos83 = makeGPOS83 (fp, offset); + break; + case 0x091: + lookupType = ttfGetUSHORT (fp); + if (lookupType == 9) + ttfError ("Invalid GPOS extensionLookupType\n"); + offset += ttfGetULONG (fp); + goto again; + default: + ttfError ("Unrecognized GPOS lookupFormat\n"); + } + + lookup.otf->lookupType = lookupType; + lookup.otf->lookupFormat = lookupFormat; + + return lookup; +} + +static void printGPOSLookup (FILE *fp, LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + printGPOS11 (fp, lookup.pos.pos11); + break; + case 0x012: + printGPOS12 (fp, lookup.pos.pos12); + break; + case 0x021: + printGPOS21 (fp, lookup.pos.pos21); + break; + case 0x022: + printGPOS22 (fp, lookup.pos.pos22); + break; + case 0x031: + printGPOS31 (fp, lookup.pos.pos31); + break; + case 0x041: + printGPOS41 (fp, lookup.pos.pos41); + break; + case 0x051: + printGPOS51 (fp, lookup.pos.pos51); + break; + case 0x061: + printGPOS61 (fp, lookup.pos.pos61); + break; + case 0x071: + printGPOS71 (fp, lookup.pos.pos71); + break; + case 0x072: + printGPOS72 (fp, lookup.pos.pos72); + break; + case 0x073: + printGPOS73 (fp, lookup.pos.pos73); + break; + case 0x081: + printGPOS81 (fp, lookup.pos.pos81); + break; + case 0x082: + printGPOS82 (fp, lookup.pos.pos82); + break; + case 0x083: + printGPOS83 (fp, lookup.pos.pos83); + break; + default: + ttfError ("Internal error: printGPOSLookup\n"); + } +} + +static void freeGPOSLookup (LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + freeGPOS11 (lookup.pos.pos11); + break; + case 0x012: + freeGPOS12 (lookup.pos.pos12); + break; + case 0x021: + freeGPOS21 (lookup.pos.pos21); + break; + case 0x022: + freeGPOS22 (lookup.pos.pos22); + break; + case 0x031: + freeGPOS31 (lookup.pos.pos31); + break; + case 0x041: + freeGPOS41 (lookup.pos.pos41); + break; + case 0x051: + freeGPOS51 (lookup.pos.pos51); + break; + case 0x061: + freeGPOS61 (lookup.pos.pos61); + break; + case 0x071: + freeGPOS71 (lookup.pos.pos71); + break; + case 0x072: + freeGPOS72 (lookup.pos.pos72); + break; + case 0x073: + freeGPOS73 (lookup.pos.pos73); + break; + case 0x081: + freeGPOS81 (lookup.pos.pos81); + break; + case 0x082: + freeGPOS82 (lookup.pos.pos82); + break; + case 0x083: + freeGPOS83 (lookup.pos.pos83); + break; + default: + ttfError ("Internal error: freeGPOSLookup\n"); + } +} + +static void ttfLoadGPOS (FILE *fp, GPOSPtr gpos, ULONG offset) +{ + USHORT sOffset, fOffset, lOffset; + + xfseek (fp, offset, SEEK_SET, "ttfLoadGPOS"); + + gpos->version = ttfGetFixed (fp); + sOffset = ttfGetUSHORT (fp); + fOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + + gpos->scriptList = otfMakeScriptList (fp, offset + sOffset); + gpos->featureList = otfMakeFeatureList (fp, offset + fOffset); + gpos->lookupList = otfMakeLookupList (fp, offset + lOffset, &makeGPOSLookup); +} + +void ttfInitGPOS (TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('G', 'P', 'O', 'S'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir (tag, font)) != NULL) + { + font->gpos = XCALLOC1 (GPOS); + ttfLoadGPOS (font->fp, font->gpos, ptd->offset); + } +} + +void ttfPrintGPOS (FILE *fp, GPOSPtr gpos) +{ + int b[2]; + + FixedSplit (gpos->version, b); + + fprintf (fp, "'GPOS' Table - Glyph Positioning Data\n"); + fprintf (fp, "-------------------------------------\n"); + fprintf (fp, "\t 'GPOS' Version:\t %d.%d\n",b[1],b[0]); + + otfPrintScriptList (fp, gpos->scriptList); + otfPrintFeatureList (fp, gpos->featureList); + otfPrintLookupList (fp, gpos->lookupList, &printGPOSLookup); +} + +void ttfFreeGPOS (GPOSPtr gpos) +{ + if (gpos != NULL) + { + otfFreeScriptList (gpos->scriptList); + otfFreeFeatureList (gpos->featureList); + otfFreeLookupList (gpos->lookupList, &freeGPOSLookup); + free (gpos); + } +} diff --git a/Build/source/texk/ttfdump/libttf/gsub.c b/Build/source/texk/ttfdump/libttf/gsub.c new file mode 100644 index 00000000000..a0c8549bfc2 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gsub.c @@ -0,0 +1,553 @@ +/* gsub.c -- Glyph Substitution Table + */ +#include <stdio.h> +#include <stdlib.h> +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +static Sub11Ptr makeGSUB11 (FILE *fp, ULONG offset) +{ + USHORT cOffset; + Sub11Ptr sub = XCALLOC1 (Sub11); + + cOffset = ttfGetUSHORT (fp); + sub->deltaGlyphID = ttfGetUSHORT (fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + + return sub; +} + +static void printGSUB11 (FILE *fp, Sub11Ptr sub) +{ + fprintf (fp, " - Single Substitution Delta\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t deltaGlyphID: %d\n", sub->deltaGlyphID); +} + +static void freeGSUB11 (Sub11Ptr sub) +{ + otfFreeCoverage (sub->coverage); +} + +static Sub12Ptr makeGSUB12 (FILE *fp, ULONG offset) +{ + USHORT cOffset; + Sub12Ptr sub = XCALLOC1 (Sub12); + + cOffset = ttfGetUSHORT (fp); + sub->glyphCount = ttfGetUSHORT (fp); + sub->substitute = ttfMakeUSHORT (sub->glyphCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + + return sub; +} + +static void printGSUB12 (FILE *fp, Sub12Ptr sub) +{ + int i; + + fprintf (fp, " - Single Substitution List\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t glyphCount: %d\n\t\t substitute: %d", + sub->glyphCount, sub->substitute[0]); + for (i = 1; i < sub->glyphCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t %d", sub->substitute[i]); + fprintf (fp, "\n"); +} + +static void freeGSUB12 (Sub12Ptr sub) +{ + otfFreeCoverage (sub->coverage); + free (sub->substitute); +} + +static void gsubLoadSequence (SequencePtr sequence, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "gsubLoadSequence"); + + sequence->glyphCount = ttfGetUSHORT (fp); + sequence->substitute = ttfMakeUSHORT (sequence->glyphCount, fp); +} + +static Sub21Ptr makeGSUB21 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *sOffset; + Sub21Ptr sub = XCALLOC1 (Sub21); + + cOffset = ttfGetUSHORT (fp); + sub->sequenceCount = ttfGetUSHORT (fp); + sOffset = ttfMakeUSHORT (sub->sequenceCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->sequence = XCALLOC (sub->sequenceCount, Sequence); + for (i = 0; i < sub->sequenceCount; i++) + gsubLoadSequence (&sub->sequence[i], fp, offset + sOffset[i]); + free (sOffset); + + return sub; +} + +static void printGSUB21 (FILE *fp, Sub21Ptr sub) +{ + int i; + + fprintf (fp, " - Multiple Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t sequenceCount: %d\n", sub->sequenceCount); + for (i = 0; i < sub->sequenceCount; i++) { + int j; + + fprintf (fp, "\t %2d. glyphCount: %d - ", i, sub->sequence[i].glyphCount); + for (j = 0; j < sub->sequence[i].glyphCount; j++) + fprintf (fp, j == 0 ? "- %d" : ", %d", sub->sequence[i].substitute[j]); + fprintf (fp, "\n"); + } +} + +static void freeGSUB21 (Sub21Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->sequenceCount; i++) + free (sub->sequence[i].substitute); + free (sub->sequence); +} + +static void gsubLoadAlternateSet (AlternateSetPtr alternateSet, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "gsubLoadAlternateSet"); + + alternateSet->glyphCount = ttfGetUSHORT (fp); + alternateSet->alternate = ttfMakeUSHORT (alternateSet->glyphCount, fp); +} + +static Sub31Ptr makeGSUB31 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *aOffset; + Sub31Ptr sub = XCALLOC1 (Sub31); + + cOffset = ttfGetUSHORT (fp); + sub->alternateSetCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (sub->alternateSetCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->alternateSet = XCALLOC (sub->alternateSetCount, AlternateSet); + for (i = 0; i < sub->alternateSetCount; i++) + gsubLoadAlternateSet (&sub->alternateSet[i], fp, offset + aOffset[i]); + free (aOffset); + + return sub; +} + +static void printGSUB31 (FILE *fp, Sub31Ptr sub) +{ + int i; + + fprintf (fp, " - Alternate Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t alternateSetCount: %d\n", sub->alternateSetCount); + for (i = 0; i < sub->alternateSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. glyphCount: %d ", i, sub->alternateSet[i].glyphCount); + for (j = 0; j < sub->alternateSet[i].glyphCount; j++) + fprintf (fp, j == 0 ? "- %d" : ", %d", sub->alternateSet[i].alternate[j]); + fprintf (fp, "\n"); + } +} + +static void freeGSUB31 (Sub31Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->alternateSetCount; i++) + free (sub->alternateSet[i].alternate); + free (sub->alternateSet); +} + +static void gsubLoadLigature (LigaturePtr ligature, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "gsubLoadLigature"); + + ligature->ligGlyph = ttfGetUSHORT (fp); + ligature->compCount = ttfGetUSHORT (fp); + ligature->component = ttfMakeUSHORT (ligature->compCount - 1, fp); +} + +static void gsubLoadLigatureSet (LigatureSetPtr ligatureSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *lOffset; + + xfseek (fp, offset, SEEK_SET, "gsubLoadLigatureSet"); + + ligatureSet->ligatureCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (ligatureSet->ligatureCount, fp); + ligatureSet->ligature = XCALLOC (ligatureSet->ligatureCount, Ligature); + for (i = 0; i < ligatureSet->ligatureCount; i++) + gsubLoadLigature (&ligatureSet->ligature[i], fp, offset + lOffset[i]); + free (lOffset); +} + +static Sub41Ptr makeGSUB41 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *lOffset; + Sub41Ptr sub = XCALLOC1 (Sub41); + + cOffset = ttfGetUSHORT (fp); + sub->ligSetCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (sub->ligSetCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->ligatureSet = XCALLOC (sub->ligSetCount, LigatureSet); + for (i = 0; i < sub->ligSetCount; i++) + gsubLoadLigatureSet (&sub->ligatureSet[i], fp, offset + lOffset[i]); + free (lOffset); + + return sub; +} + +static void printGSUB41 (FILE *fp, Sub41Ptr sub) +{ + int i; + + fprintf (fp, " - Ligature Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t ligSetCount: %d\n", sub->ligSetCount); + for (i = 0; i < sub->ligSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. ligatureCount: %d\n", i, sub->ligatureSet[i].ligatureCount); + for (j = 0; j < sub->ligatureSet[i].ligatureCount; j++) { + int k; + + fprintf (fp, "\t %2d. ligGlyph: %d, compCount: %d ", j, + sub->ligatureSet[i].ligature[j].ligGlyph, + sub->ligatureSet[i].ligature[j].compCount); + for (k = 0; k < sub->ligatureSet[i].ligature[j].compCount - 1; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", sub->ligatureSet[i].ligature[j].component[k]); + fprintf (fp, "\n"); + } + } +} + +static void freeGSUB41 (Sub41Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->ligSetCount; i++) { + int j; + + for (j = 0; j < sub->ligatureSet[i].ligatureCount; j++) + free (sub->ligatureSet[i].ligature[j].component); + free (sub->ligatureSet[i].ligature); + } + free (sub->ligatureSet); +} + +#define makeGSUB51 makeOTFCtx1 +#define printGSUB51 printOTFCtx1 +#define freeGSUB51 freeOTFCtx1 + +#define makeGSUB52 makeOTFCtx2 +#define printGSUB52 printOTFCtx2 +#define freeGSUB52 freeOTFCtx2 + +#define makeGSUB53 makeOTFCtx3 +#define printGSUB53 printOTFCtx3 +#define freeGSUB53 freeOTFCtx3 + +#define makeGSUB61 makeOTFChn1 +#define printGSUB61 printOTFChn1 +#define freeGSUB61 freeOTFChn1 + +#define makeGSUB62 makeOTFChn2 +#define printGSUB62 printOTFChn2 +#define freeGSUB62 freeOTFChn2 + +#define makeGSUB63 makeOTFChn3 +#define printGSUB63 printOTFChn3 +#define freeGSUB63 freeOTFChn3 + +static Sub81Ptr makeGSUB81 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *bOffset, *lOffset; + Sub81Ptr sub = XCALLOC1 (Sub81); + + cOffset = ttfGetUSHORT (fp); + sub->backtrackGlyphCount = ttfGetUSHORT (fp); + bOffset = ttfMakeUSHORT (sub->backtrackGlyphCount, fp); + sub->lookaheadGlyphCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (sub->lookaheadGlyphCount, fp); + sub->glyphCount = ttfGetUSHORT (fp); + sub->substitute = ttfMakeUSHORT (sub->glyphCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->backtrack = XCALLOC (sub->backtrackGlyphCount, CoveragePtr); + for (i = 0; i < sub->backtrackGlyphCount; i++) + sub->backtrack[i] = otfMakeCoverage (fp, offset + bOffset[i]); + free (bOffset); + sub->lookahead = XCALLOC (sub->lookaheadGlyphCount, CoveragePtr); + for (i = 0; i < sub->lookaheadGlyphCount; i++) + sub->lookahead[i] = otfMakeCoverage (fp, offset + lOffset[i]); + free (lOffset); + + return sub; +} + +static void printGSUB81 (FILE *fp, Sub81Ptr sub) +{ + int i; + + fprintf (fp, " - Reverse Chaining Context Single Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t backtrackGlyphCount: %d\n", sub->backtrackGlyphCount); + for (i = 0; i < sub->backtrackGlyphCount; i++) { + fprintf (fp, "\t %2d. backtrack", i); + otfPrintCoverage (fp, sub->backtrack[i]); + } + fprintf (fp, "\t lookaheadGlyphCount: %d\n", sub->lookaheadGlyphCount); + for (i = 0; i < sub->lookaheadGlyphCount; i++) { + fprintf (fp, "\t %2d. lookahead", i); + otfPrintCoverage (fp, sub->lookahead[i]); + } + fprintf (fp, "\t glyphCount: %d\n\t substitute - %d", + sub->glyphCount, sub->substitute[0]); + for (i = 1; i < sub->glyphCount; i++) + fprintf (fp, i % 8 ? ",\n\t\t %d" : ", %d", sub->substitute[i]); +} + +static void freeGSUB81 (Sub81Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->backtrackGlyphCount; i++) + otfFreeCoverage (sub->backtrack[i]); + free (sub->backtrack); + for (i = 0; i < sub->lookaheadGlyphCount; i++) + otfFreeCoverage (sub->lookahead[i]); + free (sub->lookahead); + free (sub->substitute); +} + +static LookupPtr makeGSUBLookup (FILE *fp, USHORT lookupType, ULONG offset) +{ + LookupPtr lookup; + USHORT lookupFormat; + +again: + if (lookupType == 0 || lookupType > SubLookup_Max) + ttfError ("Unrecognized GSUB lookupType\n"); + + xfseek (fp, offset, SEEK_SET, "makeGSUBLookup"); + + lookupFormat = ttfGetUSHORT (fp); + if (lookupFormat & 0xfff0) + lookupFormat = 0x000f; + + switch (lookupType << 4 | lookupFormat) + { + case 0x011: + lookup.sub.sub11 = makeGSUB11 (fp, offset); + break; + case 0x012: + lookup.sub.sub12 = makeGSUB12 (fp, offset); + break; + case 0x021: + lookup.sub.sub21 = makeGSUB21 (fp, offset); + break; + case 0x031: + lookup.sub.sub31 = makeGSUB31 (fp, offset); + break; + case 0x041: + lookup.sub.sub41 = makeGSUB41 (fp, offset); + break; + case 0x051: + lookup.sub.sub51 = makeGSUB51 (fp, offset); + break; + case 0x052: + lookup.sub.sub52 = makeGSUB52 (fp, offset); + break; + case 0x053: + lookup.sub.sub53 = makeGSUB53 (fp, offset); + break; + case 0x061: + lookup.sub.sub61 = makeGSUB61 (fp, offset); + break; + case 0x062: + lookup.sub.sub62 = makeGSUB62 (fp, offset); + break; + case 0x063: + lookup.sub.sub63 = makeGSUB63 (fp, offset); + break; + case 0x081: + lookup.sub.sub81 = makeGSUB81 (fp, offset); + break; + case 0x071: + lookupType = ttfGetUSHORT (fp); + if (lookupType == 7) + ttfError ("Invalid GSUB extensionLookupType\n"); + offset += ttfGetULONG (fp); + goto again; + default: + ttfError ("Unrecognized GSUB lookupFormat\n"); + } + + lookup.otf->lookupType = lookupType; + lookup.otf->lookupFormat = lookupFormat; + + return lookup; +} + +static void printGSUBLookup (FILE *fp, LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + printGSUB11 (fp, lookup.sub.sub11); + break; + case 0x012: + printGSUB12 (fp, lookup.sub.sub12); + break; + case 0x021: + printGSUB21 (fp, lookup.sub.sub21); + break; + case 0x031: + printGSUB31 (fp, lookup.sub.sub31); + break; + case 0x041: + printGSUB41 (fp, lookup.sub.sub41); + break; + case 0x051: + printGSUB51 (fp, lookup.sub.sub51); + break; + case 0x052: + printGSUB52 (fp, lookup.sub.sub52); + break; + case 0x053: + printGSUB53 (fp, lookup.sub.sub53); + break; + case 0x061: + printGSUB61 (fp, lookup.sub.sub61); + break; + case 0x062: + printGSUB62 (fp, lookup.sub.sub62); + break; + case 0x063: + printGSUB63 (fp, lookup.sub.sub63); + break; + case 0x081: + printGSUB81 (fp, lookup.sub.sub81); + break; + default: + ttfError ("Internal error: printGSUBLookup\n"); + } +} + +static void freeGSUBLookup (LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + freeGSUB11 (lookup.sub.sub11); + break; + case 0x012: + freeGSUB12 (lookup.sub.sub12); + break; + case 0x021: + freeGSUB21 (lookup.sub.sub21); + break; + case 0x031: + freeGSUB31 (lookup.sub.sub31); + break; + case 0x041: + freeGSUB41 (lookup.sub.sub41); + break; + case 0x051: + freeGSUB51 (lookup.sub.sub51); + break; + case 0x052: + freeGSUB52 (lookup.sub.sub52); + break; + case 0x053: + freeGSUB53 (lookup.sub.sub53); + break; + case 0x061: + freeGSUB61 (lookup.sub.sub61); + break; + case 0x062: + freeGSUB62 (lookup.sub.sub62); + break; + case 0x063: + freeGSUB63 (lookup.sub.sub63); + break; + case 0x081: + freeGSUB81 (lookup.sub.sub81); + break; + default: + ttfError ("Internal error: freeGSUBLookup\n"); + } +} + +static void ttfLoadGSUB (FILE *fp, GSUBPtr gsub, ULONG offset) +{ + USHORT sOffset, fOffset, lOffset; + + xfseek (fp, offset, SEEK_SET, "ttfLoadGSUB"); + + gsub->version = ttfGetFixed (fp); + sOffset = ttfGetUSHORT (fp); + fOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + + gsub->scriptList = otfMakeScriptList (fp, offset + sOffset); + gsub->featureList = otfMakeFeatureList (fp, offset + fOffset); + gsub->lookupList = otfMakeLookupList (fp, offset + lOffset, &makeGSUBLookup); +} + +void ttfInitGSUB (TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('G', 'S', 'U', 'B'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir (tag, font)) != NULL) + { + font->gsub = XCALLOC1 (GSUB); + ttfLoadGSUB (font->fp, font->gsub, ptd->offset); + } +} + +void ttfPrintGSUB (FILE *fp, GSUBPtr gsub) +{ + int b[2]; + + FixedSplit (gsub->version, b); + + fprintf (fp, "'GSUB' Table - Glyph Substitution Data\n"); + fprintf (fp, "--------------------------------------\n"); + fprintf (fp, "\t 'GSUB' Version:\t %d.%d\n",b[1],b[0]); + + otfPrintScriptList (fp, gsub->scriptList); + otfPrintFeatureList (fp, gsub->featureList); + otfPrintLookupList (fp, gsub->lookupList, &printGSUBLookup); +} + +void ttfFreeGSUB (GSUBPtr gsub) +{ + if (gsub != NULL) + { + otfFreeScriptList (gsub->scriptList); + otfFreeFeatureList (gsub->featureList); + otfFreeLookupList (gsub->lookupList, &freeGSUBLookup); + free (gsub); + } +} diff --git a/Build/source/texk/ttfdump/libttf/head.c b/Build/source/texk/ttfdump/libttf/head.c index ec4b33bcbaa..eec89cc9b2c 100644 --- a/Build/source/texk/ttfdump/libttf/head.c +++ b/Build/source/texk/ttfdump/libttf/head.c @@ -34,10 +34,8 @@ static void ttfLoadHEAD(FILE *fp,HEADPtr head,ULONG offset) head->flags = ttfGetUSHORT(fp); head->unitsPerEm = ttfGetUSHORT(fp); - if (fread(head->created,sizeof(char),8,fp) != 8) - ttfError("Error when getting HEAD created\n"); - if (fread(head->modified,sizeof(char),8,fp) != 8) - ttfError("Error when getting HEAD modified\n"); + ttfReadULONG (head->created, 2, fp); + ttfReadULONG (head->modified, 2, fp); head->xMin = ttfGetFWord(fp); head->yMin = ttfGetFWord(fp); @@ -61,16 +59,16 @@ void ttfPrintHEAD(FILE *fp,HEADPtr head) fprintf(fp,"'head' Table - Font Header\n"); fprintf(fp,"--------------------------\n"); - fprintf(fp,"\t 'head' version:\t %2d.%2d\n",b1[1],b1[0]); - fprintf(fp,"\t fontReversion:\t\t %2d.%2d\n",b2[1],b2[0]); + fprintf(fp,"\t 'head' version:\t %d.%d\n",b1[1],b1[0]); + fprintf(fp,"\t fontReversion:\t\t %d.%d\n",b2[1],b2[0]); fprintf(fp,"\t checkSumAdjustment:\t 0x%08x\n",head->checkSumAdj); fprintf(fp,"\t magicNumber:\t\t 0x%08x\n",head->magicNumber); fprintf(fp,"\t flags:\t\t\t 0x%04x\n",head->flags); fprintf(fp,"\t unitsPerEm:\t\t %d\n",head->unitsPerEm); /* don't know how to compute */ - fprintf(fp,"\t created:\n"); - fprintf(fp,"\t modified:\n"); + fprintf(fp,"\t created:\t\t 0x%08x%08x\n", head->created[0], head->created[1]); + fprintf(fp,"\t modified:\t\t 0x%08x%08x\n", head->modified[0], head->modified[1]); fprintf(fp,"\t xMin:\t\t\t %d\n",head->xMin); fprintf(fp,"\t yMin:\t\t\t %d\n",head->yMin); diff --git a/Build/source/texk/ttfdump/libttf/hhea.c b/Build/source/texk/ttfdump/libttf/hhea.c index 9b056dde6ab..3ec85c827d4 100644 --- a/Build/source/texk/ttfdump/libttf/hhea.c +++ b/Build/source/texk/ttfdump/libttf/hhea.c @@ -53,7 +53,7 @@ void ttfPrintHHEA(FILE *fp,HHEAPtr hhea) fprintf(fp,"'hhea' Table - Horizontal Header\n"); fprintf(fp,"--------------------------\n"); - fprintf(fp,"\t 'hhea' version:\t %2d.%2d\n",b[1],b[0]); + fprintf(fp,"\t 'hhea' version:\t %d.%d\n",b[1],b[0]); fprintf(fp,"\t yAscender:\t\t %d\n",hhea->Ascender); fprintf(fp,"\t yDescender:\t\t %d\n",hhea->Descender); fprintf(fp,"\t yLineGap:\t\t %d\n",hhea->LineGap); diff --git a/Build/source/texk/ttfdump/libttf/loca.c b/Build/source/texk/ttfdump/libttf/loca.c index 44ec5e05fcc..5342fbf20c3 100644 --- a/Build/source/texk/ttfdump/libttf/loca.c +++ b/Build/source/texk/ttfdump/libttf/loca.c @@ -59,20 +59,26 @@ void ttfPrintLOCA(FILE *fp,LOCAPtr loca) { USHORT i; - fprintf(fp,"'loca' Table - Index to Location\n"); - fprintf(fp,"--------------------------------\n"); - for (i=0;i<loca->numGlyphs;i++) - { - fprintf(fp,"\t Idx %6d -> GlyphOffset 0x%08x\n",i, - (loca->offset)[i]); - } - fprintf (fp,"\t Ended at 0x%08x\n",(loca->offset)[loca->numGlyphs]); + if (loca) + { + fprintf(fp,"'loca' Table - Index to Location\n"); + fprintf(fp,"--------------------------------\n"); + for (i=0;i<loca->numGlyphs;i++) + { + fprintf(fp,"\t Idx %6d -> GlyphOffset 0x%08x\n",i, + (loca->offset)[i]); + } + fprintf (fp,"\t Ended at 0x%08x\n",(loca->offset)[loca->numGlyphs]); + } } void ttfFreeLOCA(LOCAPtr loca) { - free (loca->offset); - free (loca); + if (loca) + { + free (loca->offset); + free (loca); + } } ULONG ttfLookUpGlyfLOCA(LOCAPtr loca,USHORT idx) diff --git a/Build/source/texk/ttfdump/libttf/maxp.c b/Build/source/texk/ttfdump/libttf/maxp.c index cefa38a4c0d..1b36fb2690b 100644 --- a/Build/source/texk/ttfdump/libttf/maxp.c +++ b/Build/source/texk/ttfdump/libttf/maxp.c @@ -49,7 +49,7 @@ void ttfPrintMAXP(FILE *fp,MAXPPtr maxp) fprintf(fp,"'maxp' Table - Maximum Profile\n"); fprintf(fp,"------------------------------\n"); - fprintf(fp,"\t 'maxp' version:\t %2d.%2d\n",b[1],b[0]); + fprintf(fp,"\t 'maxp' version:\t %d.%d\n",b[1],b[0]); fprintf(fp,"\t numGlyphs:\t\t %d\n",maxp->numGlyphs); fprintf(fp,"\t maxPoints:\t\t %d\n",maxp->maxPoints); fprintf(fp,"\t maxContours:\t\t %d\n",maxp->maxContours); diff --git a/Build/source/texk/ttfdump/libttf/otfcommon.c b/Build/source/texk/ttfdump/libttf/otfcommon.c new file mode 100644 index 00000000000..8102aae6ab5 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/otfcommon.c @@ -0,0 +1,1074 @@ +/* otfcommon.c -- OpenType Common Table Formats + */ +#include <stdio.h> +#include <stdlib.h> +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +static LangSysPtr +otfMakeLangSys (FILE *fp, ULONG offset) +{ + LangSysPtr langSys = XCALLOC1 (LangSys); + USHORT lookupOrder; + + xfseek (fp, offset, SEEK_SET, "otfMakeLangSys"); + + if ((lookupOrder = ttfGetUSHORT (fp)) != 0) + ttfError ("Non-zero lookupOrder\n"); + langSys->reqFeatureIndex = ttfGetUSHORT (fp); + langSys->featureCount = ttfGetUSHORT (fp); + langSys->featureIndex = ttfMakeUSHORT (langSys->featureCount, fp); + + return langSys; +} + +static void +otfLoadScriptRecord (FILE *fp, ScriptRecordPtr scriptRecord, ULONG offset) +{ + int i; + USHORT dOffset; + USHORT *lOffset; + + xfseek (fp, offset, SEEK_SET, "otfLoadScriptRecord"); + + dOffset = ttfGetUSHORT (fp); + + scriptRecord->langSysCount = ttfGetUSHORT (fp); + if (scriptRecord->langSysCount) { + scriptRecord->langSysRecord = XCALLOC (scriptRecord->langSysCount, LangSysRecord); + lOffset = XTALLOC (scriptRecord->langSysCount, USHORT); + + for (i = 0; i < scriptRecord->langSysCount; i++) { + scriptRecord->langSysRecord[i].tag = ttfGetULONG (fp); + lOffset[i] = ttfGetUSHORT (fp); + } + + for (i = 0; i < scriptRecord->langSysCount; i++) + scriptRecord->langSysRecord[i].langSys = otfMakeLangSys (fp, offset + lOffset[i]); + + free (lOffset); + } + + if (dOffset) + scriptRecord->defaultLangSys = otfMakeLangSys (fp, offset + dOffset); +} + +ScriptListPtr +otfMakeScriptList (FILE *fp, ULONG offset) +{ + int i; + USHORT *sOffset; + ScriptListPtr scriptList = XCALLOC1 (ScriptList); + + xfseek (fp, offset, SEEK_SET, "otfMakeScriptList"); + + scriptList->scriptCount = ttfGetUSHORT (fp); + scriptList->scriptRecord = XCALLOC (scriptList->scriptCount, ScriptRecord); + sOffset = XTALLOC (scriptList->scriptCount, USHORT); + + for (i = 0; i < scriptList->scriptCount; i++) { + scriptList->scriptRecord[i].tag = ttfGetULONG (fp); + sOffset[i] = ttfGetUSHORT (fp); + } + + for (i = 0; i < scriptList->scriptCount; i++) + otfLoadScriptRecord (fp, &scriptList->scriptRecord[i], offset + sOffset[i]); + + free (sOffset); + + return scriptList; +} + +static void +otfPrintLangSys (FILE *fp, LangSysPtr langSys) +{ + int i; + + fprintf (fp, " lang - featureCount: %d\n", langSys->featureCount); + if (langSys->reqFeatureIndex != 0xffff) + fprintf (fp, "\t\t reqFeatureIndex: %d\n", langSys->reqFeatureIndex); + if (langSys->featureCount) { + fprintf (fp, "\t\t featureIndex: %d", langSys->featureIndex[0]); + for (i = 1; i < langSys->featureCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t\t%d", + langSys->featureIndex[i]); + fprintf (fp, "\n"); + } +} + +static void +otfPrintScriptRecord (FILE *fp, ScriptRecordPtr scriptRecord) +{ + int i; + + fprintf (fp, "'%s' script - langSysCount: %d\n", + TagToStr (scriptRecord->tag), scriptRecord->langSysCount); + if (scriptRecord->defaultLangSys) { + fprintf (fp, "\t default"); + otfPrintLangSys (fp, scriptRecord->defaultLangSys); + } + for (i = 0; i < scriptRecord->langSysCount; i++) { + fprintf (fp, " %2d. '%s'", i, + TagToStr (scriptRecord->langSysRecord[i].tag)); + otfPrintLangSys (fp, scriptRecord->langSysRecord[i].langSys); + } +} + +void +otfPrintScriptList (FILE *fp, ScriptListPtr scriptList) +{ + int i; + + fprintf (fp, " scriptCount: %d\n", scriptList->scriptCount); + + for (i = 0; i < scriptList->scriptCount; i++) { + fprintf (fp, " %2d. ", i); + otfPrintScriptRecord (fp, &scriptList->scriptRecord[i]); + } + fprintf (fp, "\n"); +} + +static void +otfFreeLangSys (LangSysPtr langSys) +{ + free (langSys->featureIndex); + free (langSys); +} + +static void +otfFreeScriptRecord (ScriptRecordPtr scriptRecord) +{ + int i; + + if (scriptRecord->defaultLangSys) + otfFreeLangSys (scriptRecord->defaultLangSys); + for (i = 0; i < scriptRecord->langSysCount; i++) + otfFreeLangSys (scriptRecord->langSysRecord[i].langSys); + free (scriptRecord->langSysRecord); +} + +void +otfFreeScriptList (ScriptListPtr scriptList) +{ + int i; + + for (i = 0; i < scriptList->scriptCount; i++) + otfFreeScriptRecord (&scriptList->scriptRecord[i]); + free (scriptList->scriptRecord); + free (scriptList); +} + +static void +otfLoadFeatureRecord (FILE *fp, FeatureRecordPtr featureRecord, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "otfLoadFeatureRecord"); + + featureRecord->featureParams = ttfGetUSHORT (fp); + featureRecord->lookupCount = ttfGetUSHORT (fp); + featureRecord->lookupListIndex = ttfMakeUSHORT (featureRecord->lookupCount, fp); +} + +FeatureListPtr +otfMakeFeatureList (FILE *fp, ULONG offset) +{ + int i; + USHORT *fOffset; + FeatureListPtr featureList = XCALLOC1 (FeatureList); + + xfseek (fp, offset, SEEK_SET, "otfMakeFeatureList"); + + featureList->featureCount = ttfGetUSHORT (fp); + if (featureList->featureCount) { + featureList->featureRecord = XCALLOC (featureList->featureCount, FeatureRecord); + fOffset = XTALLOC (featureList->featureCount, USHORT); + + for (i = 0; i < featureList->featureCount; i++) { + featureList->featureRecord[i].tag = ttfGetULONG (fp); + fOffset[i] = ttfGetUSHORT (fp); + } + + for (i = 0; i < featureList->featureCount; i++) + otfLoadFeatureRecord (fp, &featureList->featureRecord[i], offset + fOffset[i]); + + free (fOffset); + } + + return featureList; +} + +static void +otfPrintFeatureRecord (FILE *fp, FeatureRecordPtr featureRecord) +{ + int i; + + fprintf (fp, "'%s' feature - lookupCount: %d\n", + TagToStr (featureRecord->tag), featureRecord->lookupCount); + fprintf (fp, "\t\tlookupListIndex: %d", featureRecord->lookupListIndex[0]); + for (i = 1; i < featureRecord->lookupCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t\t %d", + featureRecord->lookupListIndex[i]); + fprintf (fp, "\n"); + if (featureRecord->featureParams) + fprintf (fp, "\t\tfeatureParams Offset: 0x%04x\n", featureRecord->featureParams); +} + +void +otfPrintFeatureList (FILE *fp, FeatureListPtr featureList) +{ + int i; + + fprintf (fp, " featureCount: %d\n", featureList->featureCount); + + for (i = 0; i < featureList->featureCount; i++) { + fprintf (fp, " %2d. ", i); + otfPrintFeatureRecord (fp, &featureList->featureRecord[i]); + } + fprintf (fp, "\n"); +} + +void +otfFreeFeatureList (FeatureListPtr featureList) +{ + int i; + + if (featureList->featureCount) { + for (i = 0; i < featureList->featureCount; i++) + free (featureList->featureRecord[i].lookupListIndex); + free (featureList->featureRecord); + } + free (featureList); +} + +static void +otfLoadLookupRecord (FILE *fp, LookupRecordPtr lookupRecord, ULONG offset, MakeLookupFunc makeLookup) +{ + int i; + USHORT lookupType; + USHORT *lOffset; + + xfseek (fp, offset, SEEK_SET, "otfLoadLookupRecord"); + + lookupType = ttfGetUSHORT (fp); + lookupRecord->lookupFlag = ttfGetUSHORT (fp); + lookupRecord->subTableCount = ttfGetUSHORT (fp); + lookupRecord->lookup = XCALLOC (lookupRecord->subTableCount, LookupPtr); + lOffset = ttfMakeUSHORT (lookupRecord->subTableCount, fp); + if (lookupRecord->lookupFlag & lookupFlag_UseMarkFilteringSet) + lookupRecord->markFilteringSet = ttfGetUSHORT (fp); + for (i = 0; i < lookupRecord->subTableCount; i++) + lookupRecord->lookup[i] = (*makeLookup) (fp, lookupType, offset + lOffset[i]); + free (lOffset); +} + +LookupListPtr +otfMakeLookupList (FILE *fp, ULONG offset, MakeLookupFunc makeLookup) +{ + int i; + USHORT *lOffset; + LookupListPtr lookupList = XCALLOC1 (LookupList); + + xfseek (fp, offset, SEEK_SET, "otfMakeLookupList"); + + lookupList->lookupCount = ttfGetUSHORT (fp); + if (lookupList->lookupCount) { + lookupList->lookupRecord = XCALLOC (lookupList->lookupCount, LookupRecord); + lOffset = ttfMakeUSHORT (lookupList->lookupCount, fp); + + for (i = 0; i < lookupList->lookupCount; i++) + otfLoadLookupRecord (fp, &lookupList->lookupRecord[i], offset + lOffset[i], makeLookup); + + free (lOffset); + } + + return lookupList; +} + +void +otfPrintLookupList (FILE *fp, LookupListPtr lookupList, PrintLookupFunc printLookup) +{ + int i; + + fprintf (fp, " lookupCount: %d\n", lookupList->lookupCount); + + for (i = 0; i < lookupList->lookupCount; i++) { + int j; + + fprintf (fp, " %2d. lookupType: %d, lookupFlag: 0x%04x", i, + lookupList->lookupRecord[i].lookup[0].otf->lookupType, + lookupList->lookupRecord[i].lookupFlag); + if (lookupList->lookupRecord[i].lookupFlag & lookupFlag_UseMarkFilteringSet) + fprintf (fp, ", markFilteringSet: %d", lookupList->lookupRecord[i].markFilteringSet); + fprintf (fp, "\n\tsubTableCount:\t%d\n", lookupList->lookupRecord[i].subTableCount); + for (j = 0; j < lookupList->lookupRecord[i].subTableCount; j++) { + fprintf (fp, " %2d. lookupFormat: %d", j, + lookupList->lookupRecord[i].lookup[j].otf->lookupFormat); + (*printLookup) (fp, lookupList->lookupRecord[i].lookup[j]); + } + } + fprintf (fp, "\n"); +} + +void +otfFreeLookupList (LookupListPtr lookupList, FreeLookupFunc freeLookup) +{ + int i; + + if (lookupList->lookupCount) { + for (i = 0; i < lookupList->lookupCount; i++) { + int j; + + for (j = 0; j < lookupList->lookupRecord[i].subTableCount; j++) { + (*freeLookup) (lookupList->lookupRecord[i].lookup[j]); + free (lookupList->lookupRecord[i].lookup[j].otf); + } + free (lookupList->lookupRecord[i].lookup); + } + free (lookupList->lookupRecord); + } + free (lookupList); +} + +CoveragePtr +otfMakeCoverage (FILE *fp, ULONG offset) +{ + CoveragePtr coverage; + int i; + USHORT format; + + xfseek (fp, offset, SEEK_SET, "otfMakeCoverage"); + + format = ttfGetUSHORT (fp); + switch (format) + { + case 1: + coverage.coverage1 = XCALLOC1 (Coverage1); + coverage.coverage1->glyphCount = ttfGetUSHORT (fp); + coverage.coverage1->glyphArray = ttfMakeUSHORT (coverage.coverage1->glyphCount, fp); + break; + case 2: + coverage.coverage2 = XCALLOC1 (Coverage2); + coverage.coverage2->rangeCount = ttfGetUSHORT (fp); + coverage.coverage2->rangeRecord = XTALLOC (coverage.coverage2->rangeCount, RangeRecord); + for (i = 0; i < coverage.coverage2->rangeCount; i++) { + coverage.coverage2->rangeRecord[i].start = ttfGetUSHORT (fp); + coverage.coverage2->rangeRecord[i].end = ttfGetUSHORT (fp); + coverage.coverage2->rangeRecord[i].startCoverageIndex = ttfGetUSHORT (fp); + } + break; + default: + ttfError ("Unrecognized coverageFormat\n"); + } + + *coverage.format = format; + return coverage; +} + +void +otfPrintCoverage (FILE *fp, CoveragePtr coverage) +{ + int i; + + fprintf (fp, "Coverage - "); + switch (*coverage.format) + { + case 1: + fprintf (fp, "glyphCount: %d\n\t\t glyphArray: %d", + coverage.coverage1->glyphCount, coverage.coverage1->glyphArray[0]); + for (i = 1; i < coverage.coverage1->glyphCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t %d", + coverage.coverage1->glyphArray[i]); + fprintf (fp, "\n"); + break; + case 2: + fprintf (fp, "rangeCount: %d\n", coverage.coverage2->rangeCount); + for (i = 0; i < coverage.coverage2->rangeCount; i++) { + fprintf (fp, "\t %2d. start: %d, end: %d, startCoverageIndex: %d\n", i, + coverage.coverage2->rangeRecord[i].start, + coverage.coverage2->rangeRecord[i].end, + coverage.coverage2->rangeRecord[i].startCoverageIndex); + } + break; + default: + ttfError ("Internal error: otfPrintCoverage\n"); + } +} + +void +otfFreeCoverage (CoveragePtr coverage) +{ + switch (*coverage.format) + { + case 1: + free (coverage.coverage1->glyphArray); + break; + case 2: + free (coverage.coverage2->rangeRecord); + break; + default: + ttfError ("Internal error: otfFreeCoverage\n"); + } + free (coverage.format); +} + +ClassDefPtr +otfMakeClassDef (FILE *fp, ULONG offset) +{ + ClassDefPtr classDef; + int i; + USHORT format; + + xfseek (fp, offset, SEEK_SET, "otfMakeClassDef"); + + format = ttfGetUSHORT (fp); + switch (format) + { + case 1: + classDef.classDef1 = XCALLOC1 (ClassDef1); + classDef.classDef1->startGlyph = ttfGetUSHORT (fp); + classDef.classDef1->glyphCount = ttfGetUSHORT (fp); + classDef.classDef1->classValueArray = ttfMakeUSHORT (classDef.classDef1->glyphCount, fp); + break; + case 2: + classDef.classDef2 = XCALLOC1 (ClassDef2); + classDef.classDef2->classRangeCount = ttfGetUSHORT (fp); + classDef.classDef2->classRangeRecord = XTALLOC (classDef.classDef2->classRangeCount, ClassRangeRecord); + for (i = 0; i < classDef.classDef2->classRangeCount; i++) { + classDef.classDef2->classRangeRecord[i].start = ttfGetUSHORT (fp); + classDef.classDef2->classRangeRecord[i].end = ttfGetUSHORT (fp); + classDef.classDef2->classRangeRecord[i].classValue = ttfGetUSHORT (fp); + } + break; + default: + ttfError ("Unrecognized classDefFormat\n"); + } + + *classDef.format = format; + return classDef; +} + +void +otfPrintClassDef (FILE *fp, ClassDefPtr classDef) +{ + int i; + + switch (*classDef.format) + { + case 1: + fprintf (fp, "startGlyph: %d, glyphCount: %d\n\t\tclassValueArray ", + classDef.classDef1->startGlyph, classDef.classDef1->glyphCount); + for (i = 0; i < classDef.classDef1->glyphCount; i++) + fprintf (fp, i == 0 ? "- %d" : i % 8 ? ", %d" : ",\n\t\t\t\t %d", + classDef.classDef1->classValueArray[i]); + fprintf (fp, "\n"); + break; + case 2: + fprintf (fp, "classRangeCount: %d\n", classDef.classDef2->classRangeCount); + for (i = 0; i < classDef.classDef2->classRangeCount; i++) + fprintf (fp, "\t\t%2d. start: %d, end: %d, classValue: %d\n", i, + classDef.classDef2->classRangeRecord[i].start, + classDef.classDef2->classRangeRecord[i].end, + classDef.classDef2->classRangeRecord[i].classValue); + break; + default: + ttfError ("Internal error: otfPrintClassDef\n"); + } +} + +void +otfFreeClassDef (ClassDefPtr classDef) +{ + switch (*classDef.format) + { + case 1: + free (classDef.classDef1->classValueArray); + break; + case 2: + free (classDef.classDef2->classRangeRecord); + break; + default: + ttfError ("Internal error: otfFreeClassDef\n"); + } + free (classDef.format); +} + +DevicePtr +otfMakeDevice (FILE *fp, ULONG offset) +{ + size_t num; + DevicePtr device; + USHORT startSize, endSize, deltaFormat; + + xfseek (fp, offset, SEEK_SET, "otfMakeDevice"); + + startSize = ttfGetUSHORT (fp); + endSize = ttfGetUSHORT (fp); + deltaFormat = ttfGetUSHORT (fp); + if (deltaFormat < 1 || deltaFormat > 3) + ttfError ("Unrecognized deltaFormat\n"); + num = (endSize - startSize) >> (4 - deltaFormat); + device = (DevicePtr) xcalloc (1, sizeof (Device) + num * sizeof (USHORT)); + device->startSize = startSize; + device->endSize = endSize; + device->deltaFormat = deltaFormat; + ttfReadUSHORT (device->deltaValue, num + 1, fp); + + return device; +} + +void +otfPrintDevice (FILE *fp, DevicePtr device) +{ + int i; + size_t num = (device->endSize - device->startSize) >> (4 - device->deltaFormat); + + fprintf (fp, "startSize = %d, endSize = %d, deltaFormat = %d, deltaValue = 0x", + device->startSize, device->endSize, device->deltaFormat); + for (i = 0; i < num; i++) + fprintf (fp, "%04x", device->deltaValue[i]); + fprintf (fp, "%04x\n", device->deltaValue[num]); +} + +static OtfLookupRecordPtr +makeOtfLookupRecord (USHORT otfCount, FILE *fp) +{ + int i; + OtfLookupRecordPtr otf = XCALLOC (otfCount, OtfLookupRecord); + + for (i = 0; i < otfCount; i++) { + otf[i].sequenceIndex = ttfGetUSHORT (fp); + otf[i].lookupListIndex = ttfGetUSHORT (fp); + } + return otf; +} + +static void +printOtfLookupRecord (FILE * fp, const char *str, USHORT otfCount, OtfLookupRecordPtr otf) +{ + int i; + + fprintf (fp, "\t%sotfCount: %d\n", str, otfCount); + for (i = 0; i < otfCount; i++) + fprintf (fp, "\t%s%2d. sequenceIndex: %d, lookupListIndex: %d\n", + str, i, otf[i].sequenceIndex, otf[i].lookupListIndex); +} + +static void loadOtfRule (OtfRulePtr otfRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadOtfRule"); + + otfRule->glyphCount = ttfGetUSHORT (fp); + otfRule->otfCount = ttfGetUSHORT (fp); + otfRule->input = ttfMakeUSHORT (otfRule->glyphCount - 1, fp); + otfRule->otf = makeOtfLookupRecord (otfRule->otfCount, fp); +} + +static void loadOtfRuleSet (OtfRuleSetPtr otfRuleSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadOtfRuleSet"); + + otfRuleSet->otfRuleCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otfRuleSet->otfRuleCount, fp); + otfRuleSet->otfRule = XCALLOC (otfRuleSet->otfRuleCount, OtfRule); + for (i = 0; i < otfRuleSet->otfRuleCount; i++) + loadOtfRule (&otfRuleSet->otfRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfCtx1Ptr makeOTFCtx1 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *pOffset; + OtfCtx1Ptr otf = XCALLOC1 (OtfCtx1); + + cOffset = ttfGetUSHORT (fp); + otf->otfRuleSetCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->otfRuleSetCount, fp); + otf->otfRuleSet = XCALLOC (otf->otfRuleSetCount, OtfRuleSet); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + for (i = 0; i < otf->otfRuleSetCount; i++) + loadOtfRuleSet (&otf->otfRuleSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFCtx1 (FILE *fp, OtfCtx1Ptr otf) +{ + int i; + + fprintf (fp, " - Context Simple\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t otfRuleSetCount: %d\n", otf->otfRuleSetCount); + for (i = 0; i < otf->otfRuleSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. otfRuleCount: %d\n", i, otf->otfRuleSet[i].otfRuleCount); + for (j = 0; j < otf->otfRuleSet[i].otfRuleCount; j++) { + int k; + + fprintf (fp, "\t %2d. glyphtCount: %d ", j, + otf->otfRuleSet[i].otfRule[j].glyphCount); + for (k = 0; k < otf->otfRuleSet[i].otfRule[j].glyphCount - 1; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->otfRuleSet[i].otfRule[j].input[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->otfRuleSet[i].otfRule[j].otfCount, + otf->otfRuleSet[i].otfRule[j].otf); + } + } +} + +void freeOTFCtx1 (OtfCtx1Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + for (i = 0; i < otf->otfRuleSetCount; i++) { + int j; + + for (j = 0; j < otf->otfRuleSet[i].otfRuleCount; j++) { + free (otf->otfRuleSet[i].otfRule[j].input); + free (otf->otfRuleSet[i].otfRule[j].otf); + } + free (otf->otfRuleSet[i].otfRule); + } + free (otf->otfRuleSet); +} + +static void loadOtfClassRule (OtfClassRulePtr otfClassRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadOtfClassRule"); + + otfClassRule->glyphCount = ttfGetUSHORT (fp); + otfClassRule->otfCount = ttfGetUSHORT (fp); + otfClassRule->class = ttfMakeUSHORT (otfClassRule->glyphCount - 1, fp); + otfClassRule->otf = makeOtfLookupRecord (otfClassRule->otfCount, fp); +} + +static void loadOtfClassSet (OtfClassSetPtr otfClassSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadOtfClassSet"); + + otfClassSet->otfClassRuleCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otfClassSet->otfClassRuleCnt, fp); + otfClassSet->otfClassRule = XCALLOC (otfClassSet->otfClassRuleCnt, OtfClassRule); + for (i = 0; i < otfClassSet->otfClassRuleCnt; i++) + loadOtfClassRule (&otfClassSet->otfClassRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfCtx2Ptr makeOTFCtx2 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT clOffset; + USHORT *pOffset; + OtfCtx2Ptr otf = XCALLOC1 (OtfCtx2); + + cOffset = ttfGetUSHORT (fp); + clOffset = ttfGetUSHORT (fp); + otf->otfClassSetCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->otfClassSetCnt, fp); + otf->otfClassSet = XCALLOC (otf->otfClassSetCnt, OtfClassSet); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + otf->classDef = otfMakeClassDef (fp, offset + clOffset); + for (i = 0; i < otf->otfClassSetCnt; i++) + if (pOffset[i]) + loadOtfClassSet (&otf->otfClassSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFCtx2 (FILE *fp, OtfCtx2Ptr otf) +{ + int i; + + fprintf (fp, " - Context Class-based\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t ClassDef - "); + otfPrintClassDef (fp, otf->classDef); + fprintf (fp, "\t otfClassSetCnt: %d\n", otf->otfClassSetCnt); + for (i = 0; i < otf->otfClassSetCnt; i++) { + int j; + + fprintf (fp, "\t %2d. otfClassRuleCnt: %d\n", i, otf->otfClassSet[i].otfClassRuleCnt); + for (j = 0; j < otf->otfClassSet[i].otfClassRuleCnt; j++) { + int k; + + fprintf (fp, "\t %2d. glyphtCount: %d ", j, + otf->otfClassSet[i].otfClassRule[j].glyphCount); + for (k = 0; k < otf->otfClassSet[i].otfClassRule[j].glyphCount - 1; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->otfClassSet[i].otfClassRule[j].class[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->otfClassSet[i].otfClassRule[j].otfCount, + otf->otfClassSet[i].otfClassRule[j].otf); + } + } +} + +void freeOTFCtx2 (OtfCtx2Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + otfFreeClassDef (otf->classDef); + for (i = 0; i < otf->otfClassSetCnt; i++) { + int j; + + for (j = 0; j < otf->otfClassSet[i].otfClassRuleCnt; j++) { + free (otf->otfClassSet[i].otfClassRule[j].class); + free (otf->otfClassSet[i].otfClassRule[j].otf); + } + free (otf->otfClassSet[i].otfClassRule); + } + free (otf->otfClassSet); +} + +OtfCtx3Ptr makeOTFCtx3 (FILE *fp, ULONG offset) +{ + int i; + USHORT *gOffset; + OtfCtx3Ptr otf = XCALLOC1 (OtfCtx3); + + otf->glyphCount = ttfGetUSHORT (fp); + otf->otfCount = ttfGetUSHORT (fp); + gOffset = ttfMakeUSHORT (otf->glyphCount, fp); + otf->otf = makeOtfLookupRecord (otf->otfCount, fp); + otf->glyphs = XCALLOC (otf->glyphCount, CoveragePtr); + for (i = 0; i < otf->glyphCount; i++) + otf->glyphs[i] = otfMakeCoverage (fp, offset + gOffset[i]); + free (gOffset); + + return otf; +} + +void printOTFCtx3 (FILE *fp, OtfCtx3Ptr otf) +{ + int i; + + fprintf (fp, " - Context Coverage-based\n"); + fprintf (fp, "\t glyphCount: %d\n", otf->glyphCount); + for (i = 0; i < otf->glyphCount; i++) { + fprintf (fp, "\t %2d. ", i); + otfPrintCoverage (fp, otf->glyphs[i]); + } + printOtfLookupRecord (fp, " ", otf->otfCount, otf->otf); +} + +void freeOTFCtx3 (OtfCtx3Ptr otf) +{ + int i; + + for (i = 0; i < otf->glyphCount; i++) + otfFreeCoverage (otf->glyphs[i]); + free (otf->glyphs); + free (otf->otf); +} + +static void +loadChainOtfRule (ChainOtfRulePtr chainOtfRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadChainOtfRule"); + + chainOtfRule->backtrackGlyphCount = ttfGetUSHORT (fp); + chainOtfRule->backtrack = ttfMakeUSHORT (chainOtfRule->backtrackGlyphCount, fp); + chainOtfRule->inputGlyphCount = ttfGetUSHORT (fp); + chainOtfRule->input = ttfMakeUSHORT (chainOtfRule->inputGlyphCount - 1, fp); + chainOtfRule->lookaheadGlyphCount = ttfGetUSHORT (fp); + chainOtfRule->lookahead = ttfMakeUSHORT (chainOtfRule->lookaheadGlyphCount, fp); + chainOtfRule->otfCount = ttfGetUSHORT (fp); + chainOtfRule->otf = makeOtfLookupRecord (chainOtfRule->otfCount, fp); +} + +static void +loadChainOtfRuleSet (ChainOtfRuleSetPtr chainOtfRuleSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadChainOtfRuleSet"); + + chainOtfRuleSet->chainOtfRuleCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (chainOtfRuleSet->chainOtfRuleCount, fp); + chainOtfRuleSet->chainOtfRule = XCALLOC (chainOtfRuleSet->chainOtfRuleCount, ChainOtfRule); + for (i = 0; i < chainOtfRuleSet->chainOtfRuleCount; i++) + loadChainOtfRule (&chainOtfRuleSet->chainOtfRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfChn1Ptr makeOTFChn1 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *pOffset; + OtfChn1Ptr otf = XCALLOC1 (OtfChn1); + + cOffset = ttfGetUSHORT (fp); + otf->chainOtfRuleSetCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->chainOtfRuleSetCount, fp); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + otf->chainOtfRuleSet = XCALLOC (otf->chainOtfRuleSetCount, ChainOtfRuleSet); + for (i = 0; i < otf->chainOtfRuleSetCount; i++) + loadChainOtfRuleSet (&otf->chainOtfRuleSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFChn1 (FILE *fp, OtfChn1Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context Simple\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t chainOtfRuleSetCount: %d\n", otf->chainOtfRuleSetCount); + for (i = 0; i < otf->chainOtfRuleSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. chainOtfRuleCount: %d\n", i, + otf->chainOtfRuleSet[i].chainOtfRuleCount); + for (j = 0; j < otf->chainOtfRuleSet[i].chainOtfRuleCount; j++) { + int k; + + fprintf (fp, "\t %2d. backtrackGlyphCount: %d ", j, + otf->chainOtfRuleSet[i].chainOtfRule[j].backtrackGlyphCount); + for (k = 0; k < otf->chainOtfRuleSet[i].chainOtfRule[j].backtrackGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->chainOtfRuleSet[i].chainOtfRule[j].backtrack[k]); + fprintf (fp, "\n\t\tinputGlyphCount: %d ", + otf->chainOtfRuleSet[i].chainOtfRule[j].inputGlyphCount); + for (k = 0; k < otf->chainOtfRuleSet[i].chainOtfRule[j].inputGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->chainOtfRuleSet[i].chainOtfRule[j].input[k]); + fprintf (fp, "\n\t\tlookaheadGlyphCount: %d ", + otf->chainOtfRuleSet[i].chainOtfRule[j].lookaheadGlyphCount); + for (k = 0; k < otf->chainOtfRuleSet[i].chainOtfRule[j].lookaheadGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->chainOtfRuleSet[i].chainOtfRule[j].lookahead[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->chainOtfRuleSet[i].chainOtfRule[j].otfCount, + otf->chainOtfRuleSet[i].chainOtfRule[j].otf); + } + } +} + +void freeOTFChn1 (OtfChn1Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + for (i = 0; i < otf->chainOtfRuleSetCount; i++) { + int j; + + for (j = 0; j < otf->chainOtfRuleSet[i].chainOtfRuleCount; j++) { + free (otf->chainOtfRuleSet[i].chainOtfRule[j].backtrack); + free (otf->chainOtfRuleSet[i].chainOtfRule[j].input); + free (otf->chainOtfRuleSet[i].chainOtfRule[j].lookahead); + free (otf->chainOtfRuleSet[i].chainOtfRule[j].otf); + } + free (otf->chainOtfRuleSet[i].chainOtfRule); + } + free (otf->chainOtfRuleSet); +} + +static void +loadChainOtfClassRule (ChainOtfClassRulePtr chainOtfClassRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadChainOtfClassRule"); + + chainOtfClassRule->backtrackGlyphCount = ttfGetUSHORT (fp); + chainOtfClassRule->backtrack = ttfMakeUSHORT (chainOtfClassRule->backtrackGlyphCount, fp); + chainOtfClassRule->inputGlyphCount = ttfGetUSHORT (fp); + chainOtfClassRule->input = ttfMakeUSHORT (chainOtfClassRule->inputGlyphCount - 1, fp); + chainOtfClassRule->lookaheadGlyphCount = ttfGetUSHORT (fp); + chainOtfClassRule->lookahead = ttfMakeUSHORT (chainOtfClassRule->lookaheadGlyphCount, fp); + chainOtfClassRule->otfCount = ttfGetUSHORT (fp); + chainOtfClassRule->otf = makeOtfLookupRecord (chainOtfClassRule->otfCount, fp); +} + +static void +loadChainOtfClassSet (ChainOtfClassSetPtr chainOtfClassSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadChainOtfClassSet"); + + chainOtfClassSet->chainOtfClassRuleCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (chainOtfClassSet->chainOtfClassRuleCnt, fp); + chainOtfClassSet->chainOtfClassRule = XCALLOC (chainOtfClassSet->chainOtfClassRuleCnt, ChainOtfClassRule); + for (i = 0; i < chainOtfClassSet->chainOtfClassRuleCnt; i++) + loadChainOtfClassRule (&chainOtfClassSet->chainOtfClassRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfChn2Ptr makeOTFChn2 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT bOffset, iOffset, lOffset; + USHORT *pOffset; + OtfChn2Ptr otf = XCALLOC1 (OtfChn2); + + cOffset = ttfGetUSHORT (fp); + bOffset = ttfGetUSHORT (fp); + iOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + otf->chainOtfClassSetCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->chainOtfClassSetCnt, fp); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + otf->backtrackClassDef = otfMakeClassDef (fp, offset + bOffset); + otf->inputClassDef = otfMakeClassDef (fp, offset + iOffset); + otf->lookaheadClassDef = otfMakeClassDef (fp, offset + lOffset); + otf->chainOtfClassSet = XCALLOC (otf->chainOtfClassSetCnt, ChainOtfClassSet); + for (i = 0; i < otf->chainOtfClassSetCnt; i++) + if (pOffset[i]) + loadChainOtfClassSet (&otf->chainOtfClassSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFChn2 (FILE *fp, OtfChn2Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context Class-based\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t backtrackClassDef - "); + otfPrintClassDef (fp, otf->backtrackClassDef); + fprintf (fp, "\t inputClassDef - "); + otfPrintClassDef (fp, otf->inputClassDef); + fprintf (fp, "\t lookaheadClassDef - "); + otfPrintClassDef (fp, otf->lookaheadClassDef); + fprintf (fp, "\t chainOtfClassSetCnt: %d\n", otf->chainOtfClassSetCnt); + for (i = 0; i < otf->chainOtfClassSetCnt; i++) { + int j; + + fprintf (fp, "\t %2d. chainOtfClassRuleCnt: %d\n", i, + otf->chainOtfClassSet[i].chainOtfClassRuleCnt); + for (j = 0; j < otf->chainOtfClassSet[i].chainOtfClassRuleCnt; j++) { + int k; + + fprintf (fp, "\t %2d. backtrackGlyphCount: %2d ", j, + otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrackGlyphCount); + for (k = 0; k < otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrackGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : k % 8 ? ", %d" : ",\n\t\t\t\t\t %d", + otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrack[k]); + fprintf (fp, "\n\t\tinputGlyphCount: %2d ", + otf->chainOtfClassSet[i].chainOtfClassRule[j].inputGlyphCount); + for (k = 0; k < otf->chainOtfClassSet[i].chainOtfClassRule[j].inputGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : k % 8 ? ", %d" : ",\n\t\t\t\t %d", + otf->chainOtfClassSet[i].chainOtfClassRule[j].input[k]); + fprintf (fp, "\n\t\tlookaheadGlyphCount: %2d ", + otf->chainOtfClassSet[i].chainOtfClassRule[j].lookaheadGlyphCount); + for (k = 0; k < otf->chainOtfClassSet[i].chainOtfClassRule[j].lookaheadGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : k % 8 ? ", %d" : ",\n\t\t\t\t\t %d", + otf->chainOtfClassSet[i].chainOtfClassRule[j].lookahead[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->chainOtfClassSet[i].chainOtfClassRule[j].otfCount, + otf->chainOtfClassSet[i].chainOtfClassRule[j].otf); + } + } +} + +void freeOTFChn2 (OtfChn2Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + otfFreeClassDef (otf->backtrackClassDef); + otfFreeClassDef (otf->inputClassDef); + otfFreeClassDef (otf->lookaheadClassDef); + for (i = 0; i < otf->chainOtfClassSetCnt; i++) { + int j; + + for (j = 0; j < otf->chainOtfClassSet[i].chainOtfClassRuleCnt; j++) { + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrack); + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].input); + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].lookahead); + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].otf); + } + free (otf->chainOtfClassSet[i].chainOtfClassRule); + } + free (otf->chainOtfClassSet); +} + +OtfChn3Ptr makeOTFChn3 (FILE *fp, ULONG offset) +{ + int i; + USHORT *bOffset, *iOffset, *lOffset; + OtfChn3Ptr otf = XCALLOC1 (OtfChn3); + + otf->backtrackGlyphCount = ttfGetUSHORT (fp); + bOffset = ttfMakeUSHORT (otf->backtrackGlyphCount, fp); + otf->inputGlyphCount = ttfGetUSHORT (fp); + iOffset = ttfMakeUSHORT (otf->inputGlyphCount, fp); + otf->lookaheadGlyphCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (otf->lookaheadGlyphCount, fp); + otf->otfCount = ttfGetUSHORT (fp); + otf->otf = makeOtfLookupRecord (otf->otfCount, fp); + otf->backtrack = XCALLOC (otf->backtrackGlyphCount, CoveragePtr); + for (i = 0; i < otf->backtrackGlyphCount; i++) + otf->backtrack[i] = otfMakeCoverage (fp, offset + bOffset[i]); + free (bOffset); + otf->input = XCALLOC (otf->inputGlyphCount, CoveragePtr); + for (i = 0; i < otf->inputGlyphCount; i++) + otf->input[i] = otfMakeCoverage (fp, offset + iOffset[i]); + free (iOffset); + otf->lookahead = XCALLOC (otf->lookaheadGlyphCount, CoveragePtr); + for (i = 0; i < otf->lookaheadGlyphCount; i++) + otf->lookahead[i] = otfMakeCoverage (fp, offset + lOffset[i]); + free (lOffset); + + return otf; +} + +void printOTFChn3 (FILE *fp, OtfChn3Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context Coverage-based\n"); + fprintf (fp, "\t backtrackGlyphCount: %d\n", otf->backtrackGlyphCount); + for (i = 0; i < otf->backtrackGlyphCount; i++) { + fprintf (fp, "\t %2d. backtrack", i); + otfPrintCoverage (fp, otf->backtrack[i]); + } + fprintf (fp, "\t inputGlyphCount: %d\n", otf->inputGlyphCount); + for (i = 0; i < otf->inputGlyphCount; i++) { + fprintf (fp, "\t %2d. input", i); + otfPrintCoverage (fp, otf->input[i]); + } + fprintf (fp, "\t lookaheadGlyphCount: %d\n", otf->lookaheadGlyphCount); + for (i = 0; i < otf->lookaheadGlyphCount; i++) { + fprintf (fp, "\t %2d. lookahead", i); + otfPrintCoverage (fp, otf->lookahead[i]); + } + printOtfLookupRecord (fp, " ", otf->otfCount, otf->otf); +} + +void freeOTFChn3 (OtfChn3Ptr otf) +{ + int i; + + for (i = 0; i < otf->backtrackGlyphCount; i++) + otfFreeCoverage (otf->backtrack[i]); + free (otf->backtrack); + for (i = 0; i < otf->inputGlyphCount; i++) + otfFreeCoverage (otf->input[i]); + free (otf->input); + for (i = 0; i < otf->lookaheadGlyphCount; i++) + otfFreeCoverage (otf->lookahead[i]); + free (otf->lookahead); + free (otf->otf); +} + diff --git a/Build/source/texk/ttfdump/libttf/ttfutil.c b/Build/source/texk/ttfdump/libttf/ttfutil.c index 96a1bd3eb53..a31478002a5 100644 --- a/Build/source/texk/ttfdump/libttf/ttfutil.c +++ b/Build/source/texk/ttfdump/libttf/ttfutil.c @@ -32,12 +32,22 @@ void ttfError(const char * msg) } /* Functions copied or adapted from kpathsea. */ +long +xftell (FILE *fp, const char *funcname) +{ + long where = ftell (fp); + + if (where < 0) + FATAL_PERROR(funcname); + + return where; +} + void xfseek (FILE *f, long offset, int wherefrom, const char *funcname) { - if (fseek (f, offset, wherefrom) < 0) { + if (fseek (f, offset, wherefrom) < 0) FATAL_PERROR(funcname); - } } void * @@ -55,7 +65,7 @@ xmalloc (size_t size) } void * -xcalloc (size_t nelem, size_t elsize) +xcalloc (size_t nelem, size_t elsize) { void *new_mem = (void*)calloc(nelem ? nelem : 1, elsize ? elsize : 1); |