diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/ttfdump/libttf | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff) |
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/ttfdump/libttf')
35 files changed, 7966 insertions, 0 deletions
diff --git a/Build/source/texk/ttfdump/libttf/cmap.c b/Build/source/texk/ttfdump/libttf/cmap.c new file mode 100644 index 00000000000..e75b0adfb60 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/cmap.c @@ -0,0 +1,972 @@ +/* cmap.c -- Load and Print the content of cmap table + * Copyright (C) 1996 Li-Da Lho, All right reserved + * + * The structure of a cmap is really complex, it depends on which format the + * cmap is and loading a cmap is a kind of confusing thing. + * The structure of CMAP: + * A cmap begins with a general description of the table + * USHORT version indicates the version of this cmap. + * USHORT numEncodings is the number of encodings in the cmap table. + * Then follow 'numEncodings' of encoding tables, each of which contains + * the following informations for each subtable. The subtable contains the + * true data to map character code to glyph index + * USHORT PlatformID shows which platform the subtable is to be used + * (e.g. Mac, PC) + * USHORT Platfrom specific EncodingID shows what kind of encoding scheme + * this table uses (e.g. Big5, iso8859, Unicode etc.) + * ULONG offset is the offset from the beginning of the whole cmap table + * to the beginning of the corresponding subtable + * ----------------------- --- --- + * | USHORT version | ^ ^ + * ----------------------- | | + * | USHORT numEncodings | | | + * ----------------------- | | + * | Encoding Table 1 | | | + * | USHORT PlatformID | | | + * | USHORT EncodingID | | | + * | ULONG offset 1 |------ | | + * ----------------------- | | offset 1 | offset 2 + * | Encoding Table 2 | | | | + * | USHORT PlatformID | | | | + * | USHORT EncodingID | | | | + * | ULONG offset 2 |--- | v | + * ----------------------- | | --- | + * | Subtable 1 |<----- | + * | with format 0 | | v + * ----------------------- | --- + * | Subtable 2 |<-- + * | with format 2 | + * ----------------------| + * + * Problem with Character Code vs. Byte Endianess. + * + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: cmap.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +typedef union _TwoBytes { + USHORT u; + unsigned char c[2]; +} TwoBytes; + +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) +{ + ULONG tag = FT_MAKE_TAG ('c', 'm', 'a', 'p'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->cmap = XCALLOC1 (CMAP); + ttfLoadCMAP(font->fp,font->cmap,ptd->offset); + } +} + +static void ttfLoadCMAP(FILE *fp,CMAPPtr cmap,ULONG offset) +{ + USHORT i,n; + int k = 0; + + xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP"); + + cmap->version = ttfGetUSHORT(fp); + cmap->numberOfEncodings = n = ttfGetUSHORT(fp); + 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) +{ + USHORT i; + + 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 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(MapPtr map, USHORT cc) +{ + USHORT idx,format = *map.format; + + switch (format) + { + 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; +} +void ttfFreeCMAP(CMAPPtr cmap) +{ + USHORT i; + + if (!cmap) + return; + + free(cmap->encoding); + + for (i = 0; i < cmap->numberOfMaps; i++) + ttfFreeSubTable(cmap->subTable+i); + free(cmap->subTable); + + free(cmap); +} + +static void ttfLoadSubTable(FILE *fp, SubTablePtr subTable, ULONG offset) +{ + ULONG pos; + USHORT format; + + /* seek to the actuall position for this subtable + * base: beginning of cmap + * offset: offset field of each encoding table */ + pos = offset + subTable->offset; + xfseek(fp, pos, SEEK_SET, "ttfLoadEncoding"); + + format = ttfGetUSHORT(fp); + + switch(format) + { + 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; + + switch(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(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; + + 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 following procedures */ + if (fread(array,sizeof(BYTE),256,fp) != 256) + ttfError("Error when getting glyphIndexArray\n"); +} +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(map, i); + fprintf(fp,"\t\t Char %3d -> Index %4d\n",i,index); + } +} +static USHORT ttfLookUpCMAP0(MapPtr map, USHORT cc) +{ + return map.cmap0->glyphIndexArray[cc & 0x00ff]; +} +static void ttfFreeCMAP0(MapPtr map) +{ + free(map.cmap0); +} + +static void ttfLoadCMAP2(FILE *fp, MapPtr *map) +{ + USHORT * array,i,n = 0; + USHORT numGlyphId; + SubHeaderPtr header; + + 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 */ + } + n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ + + 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)) ; + } + + /* caculate the length of glyphIndexArray, this is ugly, there should be + * a better way to get this information. */ + numGlyphId = + map->cmap2->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); + numGlyphId /= sizeof(USHORT); + map->cmap2->glyphIndexArray = XCALLOC (numGlyphId, USHORT); + for (i=0;i<numGlyphId;i++) + { + map->cmap2->glyphIndexArray[i] = ttfGetUSHORT(fp); + } +} +static void ttfPrintCMAP2(FILE *fp, MapPtr map) +{ + USHORT i,j,numGlyphId; + USHORT *array,n=0,index; + SubHeaderPtr header; + TwoBytes tb; + + 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]); + } + 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); + } + + /* caculate the length of glyphIndexArray, this is ugly, there should be + * a better way to get this information. */ + numGlyphId = + 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, + 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(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(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 = map.cmap2->subHeaderKeys; + SubHeaderPtr headers = map.cmap2->subHeaders; + SHORT idDelta; + USHORT firstCode, entryCount, idRangeOffset; + TwoBytes tb; + unsigned char first,second; + + + /* On little endian platforms "low byte" is the "first byte". + * It determines if it is necessary to use the second byte to + * fully interprete the character code; for example, if the first byte + * is obviously an ASCII character then it is not necessary to + * interpret the second byte, on the other hand, if the first byte is + * zero then the second byte is a ASCII char, when the first byte + * is not an ASCII char nor zero, those two bytes together determine + * the meanning of the character code + */ + tb.u = cc; + first = tb.c[1]; + second = tb.c[0]; + + /* select which subHeader to use */ + idx = array[first]; + + firstCode = (headers+idx)->firstCode; + entryCount = (headers+idx)->entryCount; + idDelta = (headers+idx)->idDelta; + 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 = 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; + + return index; +} +static void ttfFreeCMAP2(MapPtr map) +{ + free(map.cmap2->subHeaders); + free(map.cmap2->glyphIndexArray); + free(map.cmap2); +} + +static void ttfLoadCMAP4(FILE *fp, MapPtr *map) +{ + USHORT segCount; + USHORT len; + + map->cmap4 = XCALLOC1 (CMAP4); + map->cmap4->length = ttfGetUSHORT(fp); + map->cmap4->version = 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; + map->cmap4->endCount = ttfMakeUSHORT (segCount, fp); + + map->cmap4->reservedPad = ttfGetUSHORT(fp); + + map->cmap4->startCount = ttfMakeUSHORT (segCount, fp); + + map->cmap4->idDelta = 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 = map->cmap4->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); + len /= sizeof(USHORT); + map->cmap4->glyphIndexArray = ttfMakeUSHORT (len, fp); +} +static void ttfPrintCMAP4(FILE *fp, MapPtr map) +{ + USHORT i; + USHORT segCount,len; + + 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", 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,", 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 = 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, + map.cmap4->glyphIndexArray[i]); + } + + for (i=0;i<segCount;i++) + { + 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 = map.cmap4->segCountX2/2; + + for (i=0;i<segCount;i++) + { + 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(MapPtr map) +{ + 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, MapPtr *map) +{ + USHORT len; + + 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, MapPtr map) +{ + USHORT i; + + 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<map.cmap6->entryCount;i++) + { + fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, + map.cmap6->glyphIndexArray[i]); + } +} +static USHORT ttfLookUpCMAP6(MapPtr map, USHORT cc) +{ + USHORT 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; +} +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 ttfFreeCMAP14(MapPtr map) +{ + free(map.cmap14); +} + diff --git a/Build/source/texk/ttfdump/libttf/cvt.c b/Build/source/texk/ttfdump/libttf/cvt.c new file mode 100644 index 00000000000..6af49920bfc --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/cvt.c @@ -0,0 +1,57 @@ +/* cvt.c -- Control Value Table + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: cvt.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadCVT(FILE *fp,FWord *cvt,USHORT lenght,ULONG offset); + +void ttfInitCVT(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('c', 'v', 't', ' '); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->cvtLength = ptd->length / sizeof(FWord); + font->cvt = XCALLOC (font->cvtLength, FWord); + ttfLoadCVT(font->fp,font->cvt,font->cvtLength,ptd->offset); + } +} + +static void ttfLoadCVT(FILE *fp,FWord *cvt,USHORT length,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadCVT"); + + ttfReadFWord (cvt, length, fp); +} + +void ttfPrintCVT(FILE *fp, FWord *cvt, USHORT cvtLength) +{ + USHORT i; + + fprintf(fp,"'cvt ' Table - Control Value Table\n"); + fprintf(fp,"----------------------------------\n"); + fprintf(fp,"Size = %d bytes, %d entries\n", (int) (cvtLength*sizeof(FWord)), + cvtLength); + + for (i=0;i<cvtLength;i++) + { + fprintf(fp,"\t %4d. \t %d\n",i,cvt[i]); + } + fprintf(fp,"\n"); +} + +void ttfFreeCVT(FWord *cvt) +{ + if (cvt != NULL) + free(cvt); +} diff --git a/Build/source/texk/ttfdump/libttf/disasm.c b/Build/source/texk/ttfdump/libttf/disasm.c new file mode 100644 index 00000000000..8b26895ebb8 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/disasm.c @@ -0,0 +1,17 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: disasm.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +void ttfPrintInstructions(FILE *fp, BYTE * ins) +{ + /* not implemented yet */ +} + +/* Pushing data onto the interpreter stack */ diff --git a/Build/source/texk/ttfdump/libttf/fixed.c b/Build/source/texk/ttfdump/libttf/fixed.c new file mode 100644 index 00000000000..3ff834b300a --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/fixed.c @@ -0,0 +1,8 @@ +/* fixed.c -- dealing with fixed point arithmetic + * Copyright (C) 1996 Li-Da Lho, All right reserved. + */ +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: fixed.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ diff --git a/Build/source/texk/ttfdump/libttf/font.c b/Build/source/texk/ttfdump/libttf/font.c new file mode 100644 index 00000000000..4aa74e34e99 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/font.c @@ -0,0 +1,172 @@ +/* font.c -- general font init and clean up codes + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ttf.h" +#include "ttfutil.h" +#include "protos.h" + +/* $Id: font.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfInitInterpreter(TTFontPtr font); + +TTFontPtr ttfInitFont(char *filename) +{ + TTFontPtr font; + + font = XCALLOC1 (TTFont); + + font->ttfname = filename; + if ((font->fp = fopen_truetype (filename)) == NULL) + { + fprintf(stderr,"Can't open ttf file %s\n",filename); + free(font); + return NULL; + } + + ttfLoadFont(font, 0); + return font; +} +void ttfLoadFont(TTFontPtr font, ULONG offset) +{ + xfseek(font->fp, offset, SEEK_SET, "ttfLoadFont"); + + /* offset table */ + font->version = ttfGetFixed(font->fp); + font->numTables = ttfGetUSHORT(font->fp); + + ttfInitTableDir(font,offset); + + ttfLoadRequiredTables(font); + ttfLoadOptionalTables(font); + ttfLoadOpenTypeTables(font); + + ttfInitInterpreter(font); + + /* initialize the reference count to 1 */ + font->refcount = XCALLOC1 (int); + *(font->refcount) = 1; +} +void ttfFreeFont(TTFontPtr font) +{ + ttfFreeRequiredTables(font); + + ttfFreeOptionalTables(font); + + ttfFreeOpenTypeTables(font); + + ttfFreeTableDir(font->dir); + free(font->refcount); + free(font); +} + +void ttfLoadRequiredTables(TTFontPtr font) +{ + ttfInitCMAP(font); + ttfInitNAME(font); + + ttfInitMAXP(font); + ttfInitHEAD(font); + + ttfInitGlyphCache(font); + ttfInitGLYF(font); + + ttfInitHHEA(font); + ttfInitHMTX(font); + + ttfInitPOST(font); + ttfInitOS2(font); +} + +void ttfFreeRequiredTables(TTFontPtr font) +{ + ttfFreeCMAP(font->cmap); + ttfFreeNAME(font->name); + + ttfCleanUpGlyphCache(font); + ttfFreeHEAD(font->head); + ttfFreeMAXP(font->maxp); + + ttfFreeHMTX(font->hmtx); + ttfFreeHHEA(font->hhea); + + ttfFreePOST(font->post); + ttfFreeOS2(font->os2); +} + +void ttfLoadOptionalTables(TTFontPtr font) +{ + ttfInitCVT(font); + ttfInitFPGM(font); + ttfInitGASP(font); + ttfInitHDMX(font); + ttfInitKERN(font); + ttfInitLOCA(font); + ttfInitPREP(font); + ttfInitLTSH(font); + ttfInitPCLT(font); + ttfInitVDMX(font); + ttfInitVHEA(font); + ttfInitVMTX(font); +} +void ttfFreeOptionalTables(TTFontPtr font) +{ + ttfFreeCVT(font->cvt); + ttfFreeFPGM(font->fpgm); + ttfFreeGASP(font->gasp); + ttfFreeHDMX(font->hdmx); + ttfFreeKERN(font->kern); + ttfFreeLOCA(font->loca); + ttfFreePREP(font->prep); + ttfFreeLTSH(font->ltsh); + ttfFreePCLT(font->pclt); + ttfFreeVDMX(font->vdmx); + ttfFreeVHEA(font->vhea); + 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 + * This is use for fonts that support more than one encoding scheme + * + * Problems: + * 1. which of those members can be shared between two instances + * 2. How can we free a font safely + */ +TTFontPtr ttfCloneFont(TTFontPtr font) +{ + TTFontPtr newfont; + + newfont = XTALLOC1 (TTFont); + + memcpy(newfont, font, sizeof(TTFont)); + newfont->refcount += 1; + + return newfont; +} +#endif + +static void ttfInitInterpreter(TTFontPtr font) +{ + ttfInitStorageArea(font); + ttfInitStack(font); + ttfInitGraphicsState(font); +} diff --git a/Build/source/texk/ttfdump/libttf/fpgm.c b/Build/source/texk/ttfdump/libttf/fpgm.c new file mode 100644 index 00000000000..99c5c3ca7ba --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/fpgm.c @@ -0,0 +1,47 @@ +/* fpgm.c -- Font Program + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: fpgm.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadFPGM(FILE *fp,BYTE *fpgm,USHORT lenght,ULONG offset); + +void ttfInitFPGM(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('f', 'p', 'g', 'm'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->fpgmLength = ptd->length; + font->fpgm = XCALLOC (font->fpgmLength, BYTE); + ttfLoadFPGM(font->fp,font->fpgm,font->fpgmLength,ptd->offset); + } +} + +static void ttfLoadFPGM(FILE *fp,BYTE *fpgm,USHORT length,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadFPGM"); + + if (fread(fpgm, sizeof(BYTE), length, fp) != length) + ttfError("Error when getting CVT\n"); +} + +void ttfPrintFPGM(FILE *fp, BYTE *fpgm, USHORT length) +{ + ttfPrintInstructions(fp, fpgm); +} + +void ttfFreeFPGM(BYTE *fpgm) +{ + if (fpgm != NULL) + free(fpgm); +} diff --git a/Build/source/texk/ttfdump/libttf/gasp.c b/Build/source/texk/ttfdump/libttf/gasp.c new file mode 100644 index 00000000000..9f3aadc467b --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gasp.c @@ -0,0 +1,75 @@ +/* gasp.c -- Grid-fitting And Scan-conversion Procedure + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: gasp.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadGASP(FILE *fp,GASPPtr gasp,ULONG offset); + +void ttfInitGASP(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('g', 'a', 's', 'p'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->gasp = XCALLOC1 (GASP); + ttfLoadGASP(font->fp,font->gasp,ptd->offset); + } +} + +static void ttfLoadGASP (FILE *fp,GASPPtr gasp,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadGASP"); + + gasp->version = ttfGetUSHORT(fp); + gasp->numRanges = ttfGetUSHORT(fp); + + gasp->gaspRange = XCALLOC (gasp->numRanges, GASPRANGE); + + for (i=0;i<gasp->numRanges;i++) + { + gasp->gaspRange[i].rangeMaxPPEM = ttfGetUSHORT(fp); + gasp->gaspRange[i].rangeGaspBehavior = ttfGetUSHORT(fp); + } +} + +void ttfPrintGASP(FILE *fp,GASPPtr gasp) +{ + int i; + + fprintf(fp,"'gasp' Table - Grid-fitting And Scan-conversion Procedure\n"); + fprintf(fp,"---------------------------------------------------------\n"); + + fprintf(fp,"'gasp' version:\t %d\n",gasp->version); + fprintf(fp,"numRanges: \t %d\n\n",gasp->numRanges); + + for (i=0;i<gasp->numRanges;i++) + { + fprintf(fp,"\t gasp Range %d\n",i); + fprintf(fp,"\t rangeMaxPPEM:\t %d\n", + gasp->gaspRange[i].rangeMaxPPEM); + fprintf(fp,"\t rangeGaspBehavior:\t 0x%04x\n\n", + gasp->gaspRange[i].rangeGaspBehavior); + } + fprintf(fp,"\n"); +} + +void ttfFreeGASP(GASPPtr gasp) +{ + if (gasp != NULL) + { + free(gasp->gaspRange); + free(gasp); + } +} diff --git a/Build/source/texk/ttfdump/libttf/gcache.c b/Build/source/texk/ttfdump/libttf/gcache.c new file mode 100644 index 00000000000..b501530a1e1 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gcache.c @@ -0,0 +1,403 @@ +/* + * gcache.c -- Provide the cache mechanicsm for outlines + * Copyright (C) 1996 Li-Da Lho, All right reserved + * + * This file is a little bit more complicated, the structure of the cache is + * described as fellow: + * Basically the cache can be divided onto two parts, the first one is a + * linear part which is a least recently utilitied list (LRU), + * the second part is the nonlinear one which is a binary serach tree. + * Normally each cache element is on the LRU as well as on the BST. + * Those glyph elements are allocated at once as an array of glyph cache + * elements at the init phase of glyph cache. + * + * font->gcache-- + * | + * ________| + * | + * v + * ------------------------------------------------------------------ + * |element 0| 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... + * ------------------------------------------------------------------ + * The first element of the glyph cache array serves as a dummy header + * for two purposes, one is for the head and tail of the LRU, the other is + * to point to the root of the BST. As a pointer to the root of the + * BST, the right subtree points to the root of the BST while the left one is + * not used and arbitrarly points to itself. + * + * After initialization, all the glyph cache element are on the LRU but + * none of them is on the BST. + * + * |-----------------------------------------------------------| + * | ------------- ------ ------ | + * |-> |head & tail| <-----> | |<-----> ...<----->| | <--| + * ------------- ------ ------ + * / \ / \ / \ + * / \ / \ / \ + * left=self right=root left right left right + * + * The cached data are pointed by the entries of the glyph cache element + * in a strait forward fashion. + * + * |-----------------------------------------------------------| + * | ------------- ------ ------ | + * |-> |head & tail| <-----> | |<-----> ...<----->| | <--| + * ------------- ------ ------ + * | | -------------|--|-------------------------------- + * | |---->| | |-> array for flag, instruction| + * | -------------|----------------------------------- + * | -------------|----------------------------------- + * |------->| |----> xcoordinates, ycoordinates| + * ------------------------------------------------- + * Implementation in this way is effecient for the reason that when we + * need to free the cache, we only need to do the two things + * 1. free the data pointed by the entries in the dummy header + * 2. free the dummy header + * + * Every time a glyph outline is required and ttfLoadGlyphCached is called, + * the glyph is searched on the BST with its offset as a key. + * If the glyph is on the BST then the address of the glyph cache is returned + * and the glyph cache is moved to the tail of the LRU such that the order of + * LRU is mantained. + * When the glyph required is not on the BST, something more complicated should + * be done. + * 1. Remove the first element on the LRU from the BST. + * 2. Load the glyph data to the cache element. + * 3. Insert the element back to the BST. + * 4. Move the element to the tail of the LRU. + * + * The only problem remain is how to deal with composite components. + * The asnwer simply is not to support cache for composite components at the + * current stage for the two reasons: + * 1. It will makes the code an order of magnitude more complicate to support + * composite glyf cache. + * 2. The space occupied by composite glyf is not very much + * + * It is not clear right now if it is wise to add tree balancing code. + * The overhaed introduced by BST seems minimal for 256 elements cache. + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: gcache.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfInitCache(TTFontPtr font); +static void ttfFreeCache(TTFontPtr font); +static void ttfRotateCache(TTFontPtr font); +static void ttfAllocCacheData(TTFontPtr font); +static void ttfInitCacheData(TTFontPtr font); +static void ttfFreeCacheData(TTFontPtr font); +static void ttfInsertBST(TTFontPtr font,GlyphCachePtr gcache); +static GlyphCachePtr ttfSearchBST(TTFontPtr font,ULONG offset); +static void ttfDeleteBST(TTFontPtr font,ULONG offset); +#ifdef MERGEDELETE +static void merge(GlyphCachePtr *root); +#endif +static void copy(GlyphCachePtr *root); + +void ttfInitGlyphCache(TTFontPtr font) +{ + /* this should be made configurable */ + if (font->maxp->numGlyphs > 256) + font->numCacheElements = 128; + else + font->numCacheElements = 64; + + font->gcache = XCALLOC (font->numCacheElements+1, GlyphCache); + ttfInitCache(font); + + ttfAllocCacheData(font); + ttfInitCacheData(font); +} + +void ttfCleanUpGlyphCache(TTFontPtr font) +{ + ttfFreeCacheData(font); + ttfFreeCache(font); +} + +/* provide cache mechanism for glyph */ +GLYFPtr ttfLoadGlyphCached(TTFontPtr font,ULONG offset) +{ +#ifdef OLDCODE + GLYFPtr glyf; + + glyf = &(font->gcache->next->glyf); + font->gcache->next->offset = offset; + ttfRotateCache(font); + ttfLoadGLYF(font->fp,glyf,offset); + return glyf; + +#else + GlyphCachePtr gcache; + + if ((gcache = ttfSearchBST(font,offset)) == NULL) + { + /* if the glyph is not in the cache */ + ttfDeleteBST(font,font->gcache->next->offset); + gcache = font->gcache->next; + font->gcache->next->offset = offset; + ttfRotateCache(font); + ttfLoadGLYF(font->fp,&gcache->glyf,offset); + ttfInsertBST(font,gcache); + } + return &gcache->glyf; +#endif +} + +/* threading glyph cache headers */ +static void ttfInitCache(TTFontPtr font) +{ + USHORT i,numCache = font->numCacheElements; + GlyphCachePtr cur,tmp; + + cur = tmp = font->gcache; + tmp++; + /* there are numGlyph+1 of cache header, the first one is for + * mark as the head and tail of the queue */ + for (i=0;i<numCache;i++) + { + cur->right = cur->left = NULL; + cur->next = tmp; + tmp->prev = cur; + cur = tmp; + tmp++; + } + + /* make the LRU circular */ + cur->next = font->gcache; + font->gcache->prev = cur; + + /* make the dummy header point to it self on the BST */ + font->gcache->left = font->gcache; + font->gcache->offset = 0; +} +static void ttfFreeCache(TTFontPtr font) +{ + free(font->gcache); +} +/* move the first element on the LRU the the tail */ +static void ttfRotateCache(TTFontPtr font) +{ + GlyphCachePtr gcache = font->gcache, tmp = font->gcache->next; + + /* remove the first element */ + gcache->next = tmp->next; + tmp->next->prev = gcache; + /* add the element to the tail */ + tmp->next = gcache; + tmp->prev = gcache->prev; + gcache->prev->next = tmp; + gcache->prev = tmp; +} +static void ttfAllocCacheData(TTFontPtr font) +{ + USHORT numCache = font->numCacheElements+1; + USHORT maxPoints = font->maxp->maxPoints; + USHORT maxContours = font->maxp->maxContours; + USHORT insLength = font->maxp->maxSizeOfInstructions; + + font->gcache->glyf.endPtsOfContours = XCALLOC (numCache*maxContours, USHORT); + font->gcache->glyf.instructions = XCALLOC (numCache*insLength, BYTE); + font->gcache->glyf.flags = XCALLOC (numCache*maxPoints, BYTE); + font->gcache->glyf.xCoordinates = XCALLOC (numCache*maxPoints, SHORT); + font->gcache->glyf.yCoordinates = XCALLOC (numCache*maxPoints, SHORT); + font->gcache->glyf.comp = NULL; +} +static void ttfInitCacheData(TTFontPtr font) +{ + USHORT i; + USHORT numCache = font->numCacheElements; + USHORT maxPoints = font->maxp->maxPoints; + USHORT maxContours = font->maxp->maxContours; + USHORT insLength = font->maxp->maxSizeOfInstructions; + GlyphCachePtr cur,tmp; + + tmp = font->gcache; + cur = font->gcache->next; + + for (i=0;i<numCache;i++) + { + /* makes the pointer in the cache element point to correct + * addresses in the data area */ + cur->glyf.endPtsOfContours = tmp->glyf.endPtsOfContours + maxContours; + cur->glyf.instructions = tmp->glyf.instructions + insLength; + cur->glyf.flags = tmp->glyf.flags + maxPoints; + cur->glyf.xCoordinates = tmp->glyf.xCoordinates + maxPoints; + cur->glyf.yCoordinates = tmp->glyf.yCoordinates + maxPoints; + tmp = cur++; + } +} +static void ttfFreeCacheData(TTFontPtr font) +{ + USHORT i,numCache = font->numCacheElements; + GlyphCachePtr cur = font->gcache+1; + + /* free components of composite glyfs */ + for (i=0;i<numCache;i++) + { + ttfFreeGLYF(&cur->glyf); + cur++; + } + free(font->gcache->glyf.endPtsOfContours); + free(font->gcache->glyf.instructions); + free(font->gcache->glyf.flags); + free(font->gcache->glyf.xCoordinates); + free(font->gcache->glyf.yCoordinates); +} + +/* code to deal with nonlinear part of glyph cache */ +static void ttfInsertBST(TTFontPtr font,GlyphCachePtr gcache) +{ + GlyphCachePtr root,parent; + + parent = font->gcache; + root = parent->right; + + while (root) + { + parent = root; + if (root->offset > gcache->offset) + root = root->left; + else + root = root->right; + } + + if (parent->offset > gcache->offset) + parent->left = gcache; + else + parent->right = gcache; +} +static GlyphCachePtr ttfSearchBST(TTFontPtr font,ULONG offset) +{ + GlyphCachePtr root = font->gcache->right; + + while (root) + { + if (root->offset == offset) + return root; + if (root->offset > offset) + root = root->left; + else + root = root->right; + } + return NULL; +} +/* Deleting a node form a BST is a little bit tricky. + * Basically, there are three different situations for deleteing a node + * 1. The node to delete is a leaf, then just delete the node and make the + * node's parent point to null. + * 2. The node has one subtree, the let the node's parent adopt it. + * 3. The node has both subtrees, in this situation, there are two + * alternatives + * a. let the parent adopt one of the subtree and the subtree adopt the + * other. (delete by merge) + * b. replace the node with its precedeer, and leave the topology almost + * unchanged. + */ +static void ttfDeleteBST(TTFontPtr font,ULONG offset) +{ + GlyphCachePtr root,parent; + + parent = font->gcache; + root = parent->right; + + /* find the node to delete */ + while (root) + { + if (root->offset == offset) + break; + parent = root; + if (root->offset > offset) + root = root->left; + else + root = root->right; + } + if (root != NULL) + { + /* the node to be deleted is on the tree */ + if (root->glyf.numberOfContours < 0) + /* a composite glyf with components */ + ttfFreeGLYF(&root->glyf); + +#ifdef MERGEDELETE + if (parent == font->gcache) + /* delete root */ + merge(&parent->right); + else if (parent->left == root) + merge(&parent->left); + else + merge(&parent->right); +#else + if (parent == font->gcache) + /* delete root */ + copy(&parent->right); + else if (parent->left == root) + copy(&parent->left); + else + copy(&parent->right); +#endif + + root->left = root->right = NULL; + } + else + ; /* the tree is empty or the node is not on the tree */ + +} + +#ifdef MERGEDELETE +static void merge(GlyphCachePtr *root) +{ + GlyphCachePtr tmp; + + if ((*root)->right == NULL) + *root = (*root)->left; + else if ((*root)->left == NULL) + *root = (*root)->right; + else + { + /* the node to be attached has both left and right + * subtrees */ + tmp = (*root)->left; + while (tmp->right) + { + tmp = tmp->right; + } + tmp->right = (*root)->right; + *root = (*root)->left; + } +} +#endif +static void copy(GlyphCachePtr *root) +{ + GlyphCachePtr tmp, parent; + + if ((*root)->right == NULL) + *root = (*root)->left; + else if ((*root)->left == NULL) + *root = (*root)->right; + else + { + tmp = (*root)->left; + parent = *root; + while (tmp->right) + { + parent = tmp; + tmp = tmp->right; + } + tmp->right = (*root)->right; + if (parent != *root) + { + parent->right = tmp->left; + tmp->left = parent; + } + *root = tmp; + } +} diff --git a/Build/source/texk/ttfdump/libttf/glyf.c b/Build/source/texk/ttfdump/libttf/glyf.c new file mode 100644 index 00000000000..9ab63cab99e --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/glyf.c @@ -0,0 +1,423 @@ +/* glyf.c -- Load and print Glyf outline data + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: glyf.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadSimpleGlyph(FILE *fp,GLYFPtr glyf,ULONG offset); +static void ttfPrintSimpleGlyph(FILE *fp,GLYFPtr glyf); +static void ttfLoadCompositeGlyph(FILE *fp,GLYFPtr glyf,ULONG offset); +static void ttfPrintCompositeGlyph(FILE*fp,GLYFPtr glyf); +static void ttfFreeCompositeGlyph(GLYFPtr glyf); +double fix2dbl(F2Dot14 fixed); + +/* Naming convention about GLYF and Glyph: + * High level functions which are exported should have their name + * contain GLYF, on the other hand, low level function (or structures) + * which is not intended to be exported should have their name + * contain Glyph + */ +void ttfInitGLYF(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('g', 'l', 'y', 'f'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag, font)) != NULL) + { + font->glyphOffset = ptd->offset; + } +} +/* offset: where the specified glyph really starts + * callers should compute this themself form the loca tables */ +void ttfLoadGLYF(FILE *fp, GLYFPtr glyf, ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadGLYF"); + + glyf->numberOfContours = ttfGetSHORT(fp); + glyf->xMin = ttfGetFWord(fp); + glyf->yMin = ttfGetFWord(fp); + glyf->xMax = ttfGetFWord(fp); + glyf->yMax = ttfGetFWord(fp); + + offset += sizeof(USHORT) + 4*sizeof(FWord); + + if (glyf->numberOfContours >= 0) + ttfLoadSimpleGlyph(fp, glyf, offset); + else + ttfLoadCompositeGlyph(fp, glyf, offset); +} +void ttfPrintGLYF(FILE *fp, GLYFPtr glyf) +{ + 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); + fprintf(fp,"\t yMax:\t\t\t %d\n\n", glyf->yMax); + + if (glyf->numberOfContours >= 0) + ttfPrintSimpleGlyph(fp, glyf); + else + ttfPrintCompositeGlyph(fp, glyf); +} +void ttfFreeGLYF(GLYFPtr glyf) +{ + if (glyf->numberOfContours < 0) + ttfFreeCompositeGlyph(glyf); +} +static void ttfLoadSimpleGlyph(FILE *fp, GLYFPtr glyf, ULONG offset) +{ + SHORT nCnts = glyf->numberOfContours; + USHORT i,nIns,nPts; + + xfseek(fp, offset, SEEK_SET, "ttfLoadSimpleGlyph"); + + if (nCnts != 0) + { + ttfReadUSHORT (glyf->endPtsOfContours, nCnts, fp); + nPts = (glyf->endPtsOfContours)[nCnts-1]+1; + } + else + /* there seems to be something wrong with my interpretation of + * NOGLYPH chars, doing this way in case there is a char that has + * zero contour */ + nPts = 0; + + /* how to deal with zero instruction glyf properly ?? */ + glyf->instructionLength = nIns = ttfGetUSHORT(fp); + if (nIns != 0) + { + if (fread(glyf->instructions, sizeof(BYTE), nIns, fp) != nIns) + ttfError("Error when getting instructions\n"); + } + + for (i=0;i<nPts;i++) + { + BYTE j,c; + if (((glyf->flags)[i] = c = ttfGetBYTE(fp)) & FLAGS_REPEAT) + { /* if this flag should be repeated */ + j = ttfGetBYTE(fp); /* j times */ + while (j--) + { + i++; + (glyf->flags)[i] = c; + + } + } + } + + for (i=0;i<nPts;i++) + { + BYTE flag; + flag = (glyf->flags)[i]; + + if (flag & FLAGS_X_SHORT_VECTOR) + { /* if the coordinate is a BYTE */ + if (flag & FLAGS_X_SAME) + (glyf->xCoordinates)[i] = (SHORT) ttfGetBYTE(fp); + else + (glyf->xCoordinates)[i] = (SHORT) -ttfGetBYTE(fp); + } + else + { /* the coordiante is a SHORT */ + if (flag & FLAGS_X_SAME) + (glyf->xCoordinates)[i] = 0; + else + (glyf->xCoordinates)[i] = ttfGetSHORT(fp); + } + } + for (i=0;i<nPts;i++) + { + BYTE flag; + flag = (glyf->flags)[i]; + + if (flag & FLAGS_Y_SHORT_VECTOR) + { /* if the coordinate is a BYTE */ + if (flag & FLAGS_Y_SAME) + (glyf->yCoordinates)[i] = (SHORT) ttfGetBYTE(fp); + else + (glyf->yCoordinates)[i] = (SHORT) -ttfGetBYTE(fp); + } + else + { /* the coordiante is a SHORT */ + if (flag & FLAGS_Y_SAME) + (glyf->yCoordinates)[i] = 0; + else + (glyf->yCoordinates)[i] = ttfGetSHORT(fp); + } + } +} +static void ttfPrintSimpleGlyph(FILE *fp, GLYFPtr glyf) +{ + USHORT i, nPts, nCnts; + SHORT x=0, y=0; + + nPts = (glyf->endPtsOfContours)[glyf->numberOfContours-1]+1; + nCnts = glyf->numberOfContours; + + fprintf(fp,"\t EndPoints\n"); + fprintf(fp,"\t ---------\n"); + for (i=0;i<nCnts;i++) + fprintf(fp,"\t %d: %2d\n",i,(glyf->endPtsOfContours)[i]); + fprintf(fp,"\n"); + + fprintf(fp,"\t Length of Instructions: %2d\n\n",glyf->instructionLength); + ttfPrintInstructions(fp,glyf->instructions); + + fprintf(fp,"\t Flags\n"); + fprintf(fp,"\t -----\n"); + for (i=0;i<nPts;i++) + { + BYTE flag; + char buf[80]; + + flag = (glyf->flags)[i]; + + if (flag & FLAGS_Y_SAME) + sprintf(buf,"YDual "); + else + sprintf(buf," "); + if (flag & FLAGS_X_SAME) + strcat(buf,"XDual "); + else + strcat(buf," "); + if (flag & FLAGS_REPEAT) + strcat(buf,"Repeat "); + else + strcat(buf," "); + if (flag & FLAGS_Y_SHORT_VECTOR) + strcat(buf,"Y-Short "); + else + strcat(buf," "); + if (flag & FLAGS_X_SHORT_VECTOR) + strcat(buf,"X-Short "); + else + strcat(buf," "); + if (flag & FLAGS_ON_CURVE) + strcat(buf,"On\n"); + else + strcat(buf,"Off\n"); + + fprintf(fp,"\t %2d: %s",i,buf); + } + fprintf(fp,"\n"); + fprintf(fp,"\t Coordinates\n"); + fprintf(fp,"\t -----------\n"); + for (i=0;i<nPts;i++) + { + x += (glyf->xCoordinates)[i]; + y += (glyf->yCoordinates)[i]; + fprintf(fp,"\t %2d Rel ( %6d, %6d) -> Abs ( %6d, %6d)\n", i, + (glyf->xCoordinates)[i], (glyf->yCoordinates)[i], x, y); + } + fprintf(fp,"\n"); +} + +static void ttfLoadCompositeGlyph(FILE *fp, GLYFPtr glyf, ULONG offset) +{ + USHORT nIns,flags; + Component *cur; + + xfseek(fp, offset, SEEK_SET, "ttfLoadCompositeGlyph"); + + glyf->comp = cur = XCALLOC1 (Component); + cur->previous = NULL; /* beginning of a linked list */ + + do { + cur->flags = flags = ttfGetUSHORT(fp); + cur->glyphIndex = ttfGetUSHORT(fp); + if (flags & ARG_1_AND_2_ARE_WORDS) + { + (cur->data).args[0] = ttfGetSHORT(fp); + (cur->data).args[1] = ttfGetSHORT(fp); + } + else + (cur->data).args[0] = ttfGetUSHORT(fp); + + if (flags & WE_HAVE_A_SCALE) + { + (cur->data).transform.scale = ttfGetF2Dot14(fp); + } + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) + { + (cur->data).transform.vector.xscale = ttfGetF2Dot14(fp); + (cur->data).transform.vector.yscale = ttfGetF2Dot14(fp); + } + else if (flags & WE_HAVE_A_TWO_BY_TWO) + { + (cur->data).transform.tensor.xscale = ttfGetF2Dot14(fp); + (cur->data).transform.tensor.scale01 = ttfGetF2Dot14(fp); + (cur->data).transform.tensor.scale10 = ttfGetF2Dot14(fp); + (cur->data).transform.tensor.yscale = ttfGetF2Dot14(fp); + } + /* allocate next component */ + cur->next = XCALLOC1 (Component); + cur->next->previous = cur; + cur = cur->next; /* move to next component */ + } while (flags & MORE_COMPONENT); + cur->next = NULL; /* end of the linked list */ + + if (flags & WE_HAVE_INSTRUCTIONS) + { + glyf->instructionLength = nIns = ttfGetUSHORT(fp); + if (fread(glyf->instructions, sizeof(BYTE), nIns, fp) != nIns) + ttfError("Error when loading instructions\n"); + } + else + { + glyf->instructionLength = 0; + } +} +static void ttfPrintCompositeGlyph(FILE *fp, GLYFPtr glyf) +{ + int i = 0; + char buf[80]; + USHORT flags; + Component *cur; + + cur = glyf->comp; + + do { + flags = cur->flags; + fprintf(fp, "\t %d: Flags:\t 0x%x\n", i, flags); + fprintf(fp, "\t Glyf Index:\t %d\n", cur->glyphIndex); + if (flags & ARGS_ARE_XY_VALUES) + { + if (flags & ARG_1_AND_2_ARE_WORDS) + { + fprintf(fp, "\t X WOffset:\t %d\n", (cur->data).args[0]); + fprintf(fp, "\t Y WOffset:\t %d\n", (cur->data).args[1]); + } + else + { + fprintf(fp, "\t X BOffset:\t %d\n", + (signed char) ((cur->data).args[0] >> 8 & 0xff)); + fprintf(fp, "\t Y BOffset:\t %d\n", + (signed char) ((cur->data).args[0] & 0xff)); + } + } + else + { + /* what the hell are the "patch points" ?? */ + } + + if (flags & WE_HAVE_A_SCALE) + { + fprintf(fp, "\t X,Y Scale:\t %f\n", + fix2dbl((cur->data).transform.scale)); + } + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) + { + fprintf(fp, "\t X Scale:\t %f\n", + fix2dbl((cur->data).transform.vector.xscale)); + fprintf(fp, "\t Y Scale:\t %f\n", + fix2dbl((cur->data).transform.vector.yscale)); + } + else if (flags & WE_HAVE_A_TWO_BY_TWO) + { + fprintf(fp, "\t X Scale:\t %f\n", + fix2dbl((cur->data).transform.tensor.xscale)); + fprintf(fp, "\t X,Y Scale:\t %f\n", + fix2dbl((cur->data).transform.tensor.scale01)); + fprintf(fp, "\t Y,X Scale:\t %f\n", + fix2dbl((cur->data).transform.tensor.scale10)); + fprintf(fp, "\t Y Scale:\t %f\n", + fix2dbl((cur->data).transform.tensor.yscale)); + } + + if (flags & ROUND_XY_TO_GRID) + sprintf(buf, "Round X,Y to Grid "); + else + sprintf(buf, " "); + + if (flags & NO_OVERLAP) + strcat(buf, "NO Overlap "); + else + strcat(buf, " "); + + if (flags & USE_MY_METRICS) + strcat(buf, "Use My Metrics "); + else + strcat(buf, " "); + + fprintf(fp, "\t Others:\t %s\n\n", buf); + + i++; + cur = cur->next; + } while (cur->next != NULL); + + fprintf(fp, "\n"); + + if (flags & WE_HAVE_INSTRUCTIONS) + { + fprintf(fp,"\t Length of Instructions: %2d\n\n", + glyf->instructionLength); + ttfPrintInstructions(fp, glyf->instructions); + } +} +static void ttfFreeCompositeGlyph(GLYFPtr glyf) +{ + Component *cur,*next; + + cur = glyf->comp; + + do { + next = cur->next; + free(cur); + cur = next; + } while (cur != NULL); +} + +/* what I want: + * outter procedures should not have any ideas about where the glyph starts, + * + * it just provide the TTFont structure and the character code or the index + * of that glyph. Procedures below should do: + * 1. look up where the glyph data is. + * 2. provided some glyph cache mechanism for the reason that + * a. it is not necessary to load all glyph into memory, especially for + * eastern languages. + * b. if a glyph data has been loaded previously, it is not necessary to + * load it again. + * c. malloc and free are SLOW !! + */ +/* Load a glyph by glyph index */ +GLYFPtr ttfLoadGlyphIndex(TTFont *font, USHORT idx) +{ + ULONG pos; + GLYFPtr glyf; + + /* compute the actual place where the glyph stored */ + pos = font->glyphOffset + ttfLookUpGlyfLOCA(font->loca, idx); + glyf = ttfLoadGlyphCached(font, pos); + + return glyf; +} +/* Load a glyph by character code in the current encoding scheme */ +GLYFPtr ttfLoadGlyphCode(TTFont *font,USHORT cc) +{ + USHORT index; + + index = ttfLookUpCMAP(font->encoding->map,cc); + return ttfLoadGlyphIndex(font,index); +} + +double fix2dbl(F2Dot14 fixed) +{ + double mantissa, fraction; + + mantissa = (double) (fixed >> 14); + + fraction = (double) (double)(fixed & 0x3fff) / 16384.0; + + return mantissa+fraction; +} diff --git a/Build/source/texk/ttfdump/libttf/gpos.c b/Build/source/texk/ttfdump/libttf/gpos.c new file mode 100644 index 00000000000..bc01e29cf24 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gpos.c @@ -0,0 +1,1006 @@ +/* gpos.c -- Glyph Positioning Table + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.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) +{ + 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)) + value->valDevice[i].offset = ttfGetUSHORT (fp); + + return value; +} + +static void +gposLoadValueRecord (ValueRecordPtr value, FILE *fp, ULONG offset) +{ + int i; + + if (value == NULL) + return; + for (i = 0; i < 4; i++) + if (value->valDevice[i].offset) + value->valDevice[i].device = otfMakeDevice (fp, offset + value->valDevice[i].offset); +} + +static const char *txtDesign[4] = { + "XPlacement", + "YPlacement", + "XAdvance", + "YAdvance" +}; + +static const char *txtDevice[4] = { + "XPlaDevice", + "YPlaDevice", + "XAdvDevice", + "YAdvDevice" +}; + +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; + } + for (i = 0; i < 4; i++) + if (value->valDevice[i].device) { + fprintf (fp, "%s %s:", s, txtDevice[i]); + otfPrintDevice (fp, value->valDevice[i].device); + s = str; + } +} + +static void freeValueRecord (ValueRecordPtr value) +{ + if (value) { + int i; + + for (i = 0; i < 4; i++) + if (value->valDevice[i].device) + free (value->valDevice[i].device); + 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); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + gposLoadValueRecord (pos->value, fp, offset); + + 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); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + for (i = 0; i < pos->valueCount; i++) + gposLoadValueRecord (pos->value[i], fp, offset); + + 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) +{ + int j; + PairSetPtr pairSet = &pos->pairSet[i]; + + xfseek (fp, offset, 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); + pairSet->pairValue[j].value2 = gposMakeValueRecord (pos->valueFormat2, fp); + } +} + +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); + for (i = 0; i < pos->pairSetCount; i++) { + int j; + + for (j = 0; j < pos->pairSet[i].pairValueCount; j++) { + gposLoadValueRecord (pos->pairSet[i].pairValue[j].value1, fp, offset); + gposLoadValueRecord (pos->pairSet[i].pairValue[j].value2, fp, offset); + } + } + + 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 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 < 2 * pos->class1Count * pos->class2Count; i++) + pos->values[i] = gposMakeValueRecord (i & 1 ? pos->valueFormat2 : pos->valueFormat1, fp); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->classDef1 = otfMakeClassDef (fp, offset + cOffset1); + pos->classDef2 = otfMakeClassDef (fp, offset + cOffset2); + for (i = 0; i < 2 * pos->class1Count * pos->class2Count; i++) + gposLoadValueRecord (pos->values[i], fp, offset); + + return pos; +} + +static void printGPOS22 (FILE *fp, Pos22Ptr pos) +{ + int i, num = 0; + + 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/gstate.c b/Build/source/texk/ttfdump/libttf/gstate.c new file mode 100644 index 00000000000..d8b7adcca79 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gstate.c @@ -0,0 +1,38 @@ +/* gstate.c -- manage graphics state + * Copyright (C) 1996 Li-Da Lho, All right reserved. + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: gstate.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +GraphicsState gsdefault; + +void ttfInitGraphicsState(TTFontPtr font) +{ +#if 0 + font->gstate = GS_DEFAULT; + font->gstate_init = GS_DEFAULT; +#endif + +#if 0 + ttfExecuteInstruction(font, font->fpgm); + ttfExecuteInstruction(font, font->prep); +#endif +} + +void ttfInitStack(TTFontPtr font) +{ + font->vm.sp = 0; + font->vm.Stack = XCALLOC (font->maxp->maxStackElements, LONG); +} + +void ttfInitStorageArea(TTFontPtr font) +{ + font->vm.StorageArea = XCALLOC (font->maxp->maxStorage, LONG); +} diff --git a/Build/source/texk/ttfdump/libttf/gsub.c b/Build/source/texk/ttfdump/libttf/gsub.c new file mode 100644 index 00000000000..b0ca3ee5b54 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gsub.c @@ -0,0 +1,556 @@ +/* gsub.c -- Glyph Substitution Table + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.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/hdmx.c b/Build/source/texk/ttfdump/libttf/hdmx.c new file mode 100644 index 00000000000..d91b98eb1b3 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/hdmx.c @@ -0,0 +1,87 @@ +/* hdmx.c -- Horizontal Device Metrics + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: hdmx.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadHDMX(FILE *fp,HDMXPtr hdmx,ULONG offset); + +void ttfInitHDMX(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('h', 'd', 'm', 'x'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->hdmx = XCALLOC1 (HDMX); + font->hdmx->numGlyphs = font->maxp->numGlyphs; + ttfLoadHDMX(font->fp,font->hdmx,ptd->offset); + } +} + +static void ttfLoadHDMX (FILE *fp,HDMXPtr hdmx,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadHDMX"); + + hdmx->version = ttfGetUSHORT(fp); + hdmx->numDevices = ttfGetUSHORT(fp); + hdmx->size = ttfGetLONG(fp); + + hdmx->Records = XCALLOC (hdmx->numDevices, DeviceRecord); + + for (i=0;i<hdmx->numDevices;i++) + { + hdmx->Records[i].PixelSize = ttfGetBYTE(fp); + hdmx->Records[i].MaxWidth = ttfGetBYTE(fp); + hdmx->Records[i].Width = XCALLOC (hdmx->size, BYTE); + fread ((hdmx->Records+i)->Width, sizeof(BYTE), hdmx->numGlyphs+1,fp); + } +} + +void ttfPrintHDMX(FILE *fp,HDMXPtr hdmx) +{ + int i; + + fprintf(fp,"'hdmx' Table - Horizontal Device Metrics\n"); + fprintf(fp,"----------------------------------------\n"); + + fprintf(fp,"\t 'hdmx' version:\t %d\n",hdmx->version); + fprintf(fp,"\t # device records:\t %d\n",hdmx->numDevices); + fprintf(fp,"\t Record length:\t %d\n",hdmx->size); + + for (i=0;i<hdmx->numDevices;i++) + { + int j; + fprintf(fp,"\t DevRec %d: ppem = %d, maxWid = %d\n", + i,hdmx->Records[i].PixelSize,hdmx->Records[i].MaxWidth); + + for (j=0;j<hdmx->numGlyphs;j++) + fprintf(fp,"\t %d. \t %d\n",j,(hdmx->Records+i)->Width[j]); + fprintf(fp,"\n"); + } + fprintf(fp,"\n"); +} + +void ttfFreeHDMX(HDMXPtr hdmx) +{ + int i; + + if (hdmx != NULL) + { + for (i=0;i<hdmx->numDevices;i++) + free(hdmx->Records[i].Width); + + free(hdmx->Records); + free(hdmx); + } +} diff --git a/Build/source/texk/ttfdump/libttf/head.c b/Build/source/texk/ttfdump/libttf/head.c new file mode 100644 index 00000000000..bc07fc7baf1 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/head.c @@ -0,0 +1,91 @@ +/* head.c -- Header Table + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: head.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadHEAD(FILE *fp,HEADPtr head,ULONG offset); + +void ttfInitHEAD(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('h', 'e', 'a', 'd'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->head = XCALLOC1 (HEAD); + ttfLoadHEAD(font->fp,font->head,ptd->offset); + } +} + +static void ttfLoadHEAD(FILE *fp,HEADPtr head,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadHEAD"); + + head->version = ttfGetFixed(fp); + head->fontRevision = ttfGetFixed(fp); + head->checkSumAdj = ttfGetULONG(fp); + head->magicNumber = ttfGetULONG(fp); + head->flags = ttfGetUSHORT(fp); + head->unitsPerEm = ttfGetUSHORT(fp); + + ttfReadULONG (head->created, 2, fp); + ttfReadULONG (head->modified, 2, fp); + + head->xMin = ttfGetFWord(fp); + head->yMin = ttfGetFWord(fp); + head->xMax = ttfGetFWord(fp); + head->yMax = ttfGetFWord(fp); + + head->macStyle = ttfGetUSHORT(fp); + head->lowestRecPPEM = ttfGetUSHORT(fp); + + head->fontDirectionHint = ttfGetSHORT(fp); + head->indexToLocFormat = ttfGetSHORT(fp); + head->glyphDataFormat = ttfGetSHORT(fp); +} + +void ttfPrintHEAD(FILE *fp,HEADPtr head) +{ + int b1[2],b2[2]; + + FixedSplit(head->version,b1); + FixedSplit(head->fontRevision,b2); + + fprintf(fp,"'head' Table - Font Header\n"); + fprintf(fp,"--------------------------\n"); + 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:\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); + fprintf(fp,"\t xMax:\t\t\t %d\n",head->xMax); + fprintf(fp,"\t yMax:\t\t\t %d\n",head->yMax); + fprintf(fp,"\t macStyle bits:\t\t 0x%04x\n",head->macStyle); + fprintf(fp,"\t lowestRecPPEM:\t\t %d\n",head->lowestRecPPEM); + fprintf(fp,"\t fontDirectionHint:\t %d\n",head->fontDirectionHint); + fprintf(fp,"\t indexToLocFormat:\t %d\n",head->indexToLocFormat); + fprintf(fp,"\t glyphDataFormat:\t %d\n",head->glyphDataFormat); + fprintf(fp,"\n"); +} + +void ttfFreeHEAD(HEADPtr head) +{ + free(head); +} diff --git a/Build/source/texk/ttfdump/libttf/hhea.c b/Build/source/texk/ttfdump/libttf/hhea.c new file mode 100644 index 00000000000..6d8d9caecf1 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/hhea.c @@ -0,0 +1,78 @@ +/* hhea.c -- Horizontal header + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: hhea.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadHHEA(FILE *fp,HHEAPtr hhea,ULONG offset); + +void ttfInitHHEA(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('h', 'h', 'e', 'a'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->hhea = XCALLOC1 (HHEA); + ttfLoadHHEA(font->fp,font->hhea,ptd->offset); + } +} + +static void ttfLoadHHEA (FILE *fp,HHEAPtr hhea,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadHHEA"); + + hhea->version = ttfGetFixed(fp); + hhea->Ascender = ttfGetFWord(fp); + hhea->Descender = ttfGetFWord(fp); + hhea->LineGap = ttfGetFWord(fp); + hhea->advanceWidthMax = ttfGetuFWord(fp); + hhea->minLeftSideBearing = ttfGetFWord(fp); + hhea->minRightSideBearing = ttfGetFWord(fp); + hhea->xMaxExtent = ttfGetFWord(fp); + hhea->caretSlopeRise = ttfGetSHORT(fp); + hhea->caretSlopeRun = ttfGetSHORT(fp); + for(i=0;i<5;i++) + (hhea->reserved)[i] = ttfGetSHORT(fp); + hhea->metricDataFormat = ttfGetSHORT(fp); + hhea->numberOfHMetrics = ttfGetUSHORT(fp); +} + +void ttfPrintHHEA(FILE *fp,HHEAPtr hhea) +{ + int i,b[2]; + + FixedSplit(hhea->version,b); + + fprintf(fp,"'hhea' Table - Horizontal Header\n"); + fprintf(fp,"--------------------------\n"); + 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); + fprintf(fp,"\t advanceWidthMax:\t %d\n",hhea->advanceWidthMax); + fprintf(fp,"\t minLeftSideBearing:\t %d\n",hhea->minLeftSideBearing); + fprintf(fp,"\t minRightSideBearing:\t %d\n",hhea->minRightSideBearing); + fprintf(fp,"\t xMaxExtent:\t\t %d\n",hhea->xMaxExtent); + fprintf(fp,"\t caretSlopeRise:\t %d\n",hhea->caretSlopeRise); + fprintf(fp,"\t caretSlopeRun:\t\t %d\n",hhea->caretSlopeRun); + for (i=0;i<5;i++) + fprintf(fp,"\t reserved%d:\t\t %d\n",i,(hhea->reserved)[i]); + fprintf(fp,"\t metricDataFormat:\t %d\n",hhea->metricDataFormat); + fprintf(fp,"\t numberOfHMetrics:\t %d\n",hhea->numberOfHMetrics); +} + +void ttfFreeHHEA(HHEAPtr hhea) +{ + free(hhea); +} diff --git a/Build/source/texk/ttfdump/libttf/hmtx.c b/Build/source/texk/ttfdump/libttf/hmtx.c new file mode 100644 index 00000000000..dfcd60670d7 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/hmtx.c @@ -0,0 +1,89 @@ +/* hmtx.c -- Horizontal Metrics Table + * Copyright (C) 1997 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: hmtx.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadHMTX(FILE *fp,HMTXPtr hmtx,ULONG offset); + +/* Caution: Because of interdependency between tables, + * table hhea and maxp should be well initalized before + * ttfInitHMTX is been called + */ +void ttfInitHMTX(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('h', 'm', 't', 'x'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->hmtx = XCALLOC1 (HMTX); + font->hmtx->numberOfHMetrics = font->hhea->numberOfHMetrics; + font->hmtx->numberOfLSB = font->maxp->numGlyphs - + font->hhea->numberOfHMetrics; + ttfLoadHMTX(font->fp,font->hmtx,ptd->offset); + } +} + +static void ttfLoadHMTX(FILE *fp,HMTXPtr hmtx,ULONG offset) +{ + USHORT i,n = hmtx->numberOfHMetrics,m=hmtx->numberOfLSB; + + xfseek(fp, offset, SEEK_SET, "ttfLoadHMTX"); + + hmtx->hMetrics = XCALLOC (n, longHorMetric); + for (i=0;i<n;i++) + { + (hmtx->hMetrics+i)->advanceWidth = ttfGetuFWord(fp); + (hmtx->hMetrics+i)->lsb = ttfGetFWord(fp); + } + + /* codes dealing with leftSideBearing entry */ + if (m) + { + hmtx->leftSideBearing = XCALLOC (m, FWord); + for (i=0;i<m;i++) + { + (hmtx->leftSideBearing)[i] = ttfGetFWord(fp); + } + } +} + +void ttfPrintHMTX(FILE *fp,HMTXPtr hmtx) +{ + int i; + + fprintf(fp,"'hmtx' Table - Horizontal Metrics\n"); + fprintf(fp,"---------------------------------\n"); + + for (i=0;i<hmtx->numberOfHMetrics;i++) + { + fprintf(fp,"\t %4d. advWid: %4d, LSBear: %4d\n",i, + (hmtx->hMetrics+i)->advanceWidth, + (hmtx->hMetrics+i)->lsb); + } + + for (i=0;i<hmtx->numberOfLSB;i++) + { + fprintf(fp,"\t %4d. LSbear: %4d\n",i+hmtx->numberOfHMetrics, + (hmtx->leftSideBearing)[i]); + } +} + +void ttfFreeHMTX(HMTXPtr hmtx) +{ + free(hmtx->hMetrics); + + if (hmtx->numberOfLSB) + free(hmtx->leftSideBearing); + + free(hmtx); +} diff --git a/Build/source/texk/ttfdump/libttf/interp.c b/Build/source/texk/ttfdump/libttf/interp.c new file mode 100644 index 00000000000..030c4bbadde --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/interp.c @@ -0,0 +1,856 @@ +/* interp.c -- Instruction Interpreter + * Copyright (C) 1996 Li-Da Lho, All right reserved. + */ +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: interp.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +/* A bit about error checking: The execution of a TrueType instruction is + * "atomic" which means that we don't process the error until a single + * instruction is fully decoded and executed */ + +/* Pushing data onto the interpreter stack */ + +void Interp_NPUSHB (VirtualMachine *vm) +{ + BYTE i,n; + ULONG l; + + n = GetBYTE(vm); + + for (i=1;i<=n;i++) + { + /* unsigned extension to four bytes */ + l = (ULONG) GetBYTE(vm); + Push(vm, l); + } +} + +void Interp_NPUSHW(VirtualMachine *vm) +{ + BYTE i,n; + LONG l; + + n = GetBYTE(vm); + + for (i=1;i<=n;i++) + { + /* signed extension to four bytes */ + l = (LONG) GetSHORT(vm); + Push(vm, l); + } + +} + +void Interp_PUSHB(VirtualMachine *vm) +{ + BYTE opcode,n,i; + ULONG l; + + opcode = (vm->iStream)[vm->ip]; + n = opcode - 0xB0; + + for (i=0;i<=n;i++) + { + l = (ULONG) GetBYTE(vm); + Push(vm, l); + } +} +/* PUSHW[abc] Push Words + * Code Range 0xB8 - 0x0BF + * From IS w0,w1,...wn + * Pushes w0,w1,...wn */ +void Interp_PUSHW(VirtualMachine *vm) +{ + BYTE opcode,n,i; + LONG l; + + opcode = (vm->iStream)[vm->ip]; + n = opcode - 0xB8; + + for (i=0;i<=n;i++) + { + l = (LONG) GetSHORT(vm); + Push(vm,l); + } +} + +/* Managing the Storage Area */ + +/* RS[] Read Store + * Code Range 0x43 + * Pops location: Storage Area location (ULONG) + * Pushes value: Storage Area value (ULONG) + * Gets Storage Area value */ +void Interp_RS(VirtualMachine *vm) +{ + ULONG location,value; + + location = Pop(vm); + value = (vm->StorageArea)[location]; + Push(vm,value); +} +/* WS[] Write Store + * Code Range 0x42 + * Pops value: Storage Area value (ULONG) + * location: Storage Area location (ULONG) + * Pushes - + * Sets Storage Area */ +void Interp_WS(VirtualMachine *vm) +{ + ULONG location,value; + + value = Pop(vm); + location = Pop(vm); + (vm->StorageArea)[location] = value; +} + +/* Managing the Control Value Table */ + +/* WCVTP[] Write control Value Table in Pixel units + * Code Range 0x44 + * Pops value: number in pixels (F26Dot6) + * location: Control Value Table location (ULONG) + * Pushes - + * Sets Control Value Table entry */ +void Interp_WCVTP(VirtualMachine *vm) +{ + F26Dot6 value; + ULONG location; + + value = Pop(vm); + location = Pop(vm); + + (vm->cvt)[location] = value; +} +/* WCVTF[] Write Control Value Table in FUnits + * Code Range 0x70 + * Pops value: number in FUnits (ULONG) (LONG actually,i think) + * location: Control Value (ULONG) + * Pushes - + * Sets Control Value Table entry + */ +void Interp_WCVTF(VirtualMachine *vm) +{ + ULONG location; + LONG value; + + value = Pop(vm); + location = Pop(vm); + + value = ScaleToPoints(vm,value); + (vm->cvt)[location] = value; +} +/* RCVT[] Read Control Value Table + * Code Range 0x45 + * Pops location: CVT entry number (ULONG) + * Pushes value: CVT value (F26Dot6) + * Gets Control Value Table entry + */ +void Interp_RCVT(VirtualMachine *vm) +{ + ULONG location; + F26Dot6 value; + + location = Pop(vm); + value = (vm->cvt)[location]; + Push(vm,value); +} + +/* Managing Graphics State */ + +/* SVTCA[a] Set freedom and projection vector to Coordinate Axia + * Code Range 0x00 - 0x01 + * a 0: set to y axis + * 1: set to x axis + * Pops - + * Pushes - + * Sets projection_vector + * freedom_vector + */ +void Interp_SVTCA(VirtualMachine *vm) +{ + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + switch (opcode) + { + case 0x00: + vect.x = 0; + vect.y = F2Dot14_ONE; + break; + case 0x01: + vect.x = F2Dot14_ONE; + vect.y = 0; + break; + } + vm->gstate.projection_vector = vm->gstate.freedom_vector = vect; +} +/* SPVCA[a] Set projection vector to coordinate axis + * Code Range 0x02 - 0x03 + * a 0: set to y axis + * 1: set to x axis + * Pops - + * Pushes - + * Sets projection vector + */ +void Interp_SPVTCA(VirtualMachine *vm) +{ + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + switch (opcode) + { + case 0x02: + vect.x = 0; + vect.y = F2Dot14_ONE; + break; + case 0x03: + vect.x = F2Dot14_ONE; + vect.y = 0; + break; + } + vm->gstate.projection_vector = vect; +} +/* SFVTCA[a] Set freedom vector to coordinate axis + * Code Range 0x04 - 0x05 + * a 0: set to y axis + * 1: set to x axis + * Pops - + * Pushes - + * Sets freedom vector + */ +void Interp_SFVTCA(VirtualMachine *vm) +{ + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + switch (opcode) + { + case 0x04: + vect.x = 0; + vect.y = F2Dot14_ONE; + break; + case 0x05: + vect.x = F2Dot14_ONE; + vect.y = 0; + break; + } + vm->gstate.freedom_vector = vect; +} +/* SPVTL[a] Set projection vector to line + * Code Range 0x06 - 0x07 + * a 0: set projection_vector to be parallel to line segment from p1 + * to p2 + * 1: set projection_vector to be perpendicular to line segment from + * p1 to p2; the vector is retated counter clockwise 90 degrees + * Pops p1: point number (ULONG) + * p2: point number (ULONG) + * Pushes - + * Uses point p1 in the zone pointed at by zp2 + * point p2 in the zone pointed at by zp1 + * Sets projection vector + */ +void Interp_SPVTL(VirtualMachine *vm) +{ + ULONG p1,p2; + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + p1 = Pop(vm); + p2 = Pop(vm); + + switch (opcode) + { + /* not finished yet */ + case 0x06: + break; + case 0x07: + break; + } + vm->gstate.projection_vector = vect; +} +/* SFVTL[a] Set freedom vector to line + * Code Range 0x08 - 0x09 + * a 0: set freedom_vector to be parallel to line segment from p1 + * to p2 + * 1: set freedom_vector to be perpendicular to line segment from + * p1 to p2; the vector is retated counter clockwise 90 degrees + * Pops p1: point number (ULONG) + * p2: point number (ULONG) + * Pushes - + * Uses point p1 in the zone pointed at by zp2 + * point p2 in the zone pointed at by zp1 + * Sets freedom vector + */ +void Interp_SFVTL(VirtualMachine *vm) +{ + ULONG p1,p2; + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + p1 = Pop(vm); + p2 = Pop(vm); + switch (opcode) + { + /* not finished yet */ + case 0x08: + break; + case 0x09: + break; + } + vm->gstate.freedom_vector = vect; +} +/* SFVTPV[] Set freedom vector to projection vector + * Code Range 0x0E + * Pops - + * Pushes - + * Sets freedom vector + */ +void Interp_SFVTPV(VirtualMachine *vm) +{ + vm->gstate.freedom_vector = vm->gstate.projection_vector; +} +/* SDPVTL[a] Set dual projection vector to line + * Code Range 0x86 - 0x87 + * a 0: vectors are parallel to line + * 1: vectors are perpendicular to line + * Pops p1: first point number (ULONG) + * p2: second point number (ULONG) + * Pushes - + * Sets dual_projection_vector and projection_vector + * Uses point p1 in the zone pointed by zp2 + * point p2 in the zone pointed by zp1 + */ +void Interp_SDPVTL(VirtualMachine *vm) +{ + ULONG p1,p2; + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + p1 = Pop(vm); + p2 = Pop(vm); + switch (opcode) + { + /* not finished yet */ + case 0x86: + break; + case 0x87: + break; + } + vm->gstate.dual_projection_vector = vm->gstate.projection_vector = vect; +} +/* SPVFS[] Set projection vector from stack + * Code Range 0x0A + * Pops y: y component of projection vector (2.14 padded with zeros) + * x: x component of projection vector (2.14 padded with zeros) + * Pushes - + * Sets projection_vector + */ +void Inpterp_SPVFS(VirtualMachine *vm) +{ + F2Dot14 x,y; + + x = Pop(vm); + y = Pop(vm); + + vm->gstate.projection_vector.x = x; + vm->gstate.projection_vector.y = y; + /* vm->gstate.projection = Normalize(vm->gstate.projection); ?? */ +} +/* SFVFS[] Set freedom vector form stack + * Code Range 0x0B + * Pops y: y component of freedom vector (2.14 padded with zeros) + * x: x component of freedom vector (2.14 padded with zeros) + * Pushes - + * Sets freedom_vector + */ +void Inpterp_SFVFS(VirtualMachine *vm) +{ + F2Dot14 x,y; + + x = Pop(vm); + y = Pop(vm); + + vm->gstate.freedom_vector.x = x; + vm->gstate.freedom_vector.y = y; + /* vm->gstate.freedom = Normalize(vm->gstate.freedom); ?? */ +} +/* GPV[] Get projection vector + * Code Range 0x0C + * Pops - + * Pushes x: x component of projection vector (2.14 padded with zeros) + * y: y component of projection vector (2.14 padded with zeros) + * Gets projection vector + */ +void Interp_GPV(VirtualMachine *vm) +{ + ULONG l; + + l = (ULONG) vm->gstate.projection_vector.x; + Push(vm,l); + l = (ULONG) vm->gstate.projection_vector.y; + Push(vm,l); +} +/* GFV[] Get freedom vector + * Code Range 0x0D + * Pops - + * Pushes x: x component of freedom vector (2.14 padded with zeros) + * y: y component of freedom vector (2.14 padded with zeros) + * Gets freedom vector + */ +void Interp_GFV(VirtualMachine *vm) +{ + ULONG l; + + l = (ULONG) vm->gstate.freedom_vector.x; + Push(vm,l); + l = (ULONG) vm->gstate.freedom_vector.y; + Push(vm,l); +} +/* SRP0[] Set reference point 0 + * Code Range 0x10 + * Pops p: point number (ULONG) + * Pushes - + * Sets rp0 + * Affects IP,MDAP,MIAP,MIRP,MSIRP,SHC,SHE,SHP + */ +void Inpter_SRP0(VirtualMachine *vm) +{ + vm->gstate.rp0 = Pop(vm); +} +/* SRP1[] Set reference point 1 + * Code Range 0x11 + * Pops p: point number (ULONG) + * Pushes - + * Sets rp1 + * Affects IP,MDAP,MIAP,MIRP,MSIRP,SHC,SHE,SHP + */ +void Inpter_SRP1(VirtualMachine *vm) +{ + vm->gstate.rp1 = Pop(vm); +} +/* SRP2[] Set reference point 2 + * Code Range 0x12 + * Pops p: point number (ULONG) + * Pushes - + * Sets rp2 + * Affects IP,MDAP,MIAP,MIRP,MSIRP,SHC,SHE,SHP + */ +void Inpter_SRP2(VirtualMachine *vm) +{ + vm->gstate.rp2 = Pop(vm); +} +/* SZP0[] Set zone pointer 0 + * Code Range 0x13 + * Pops n: zone number (ULONG) + * Pushes - + * Sets zp0 + * Affects ALIGNPTS,ALIGNRP,DELTAP1,DELTAP2,DELTAP3,IP,ISECT,MD,MDAP,MIAP, + * MIRP,MSIRP,SHC,SHE,SHP,UTP + */ +void Inpterp_SZP0(VirtualMachine *vm) +{ + vm->gstate.zp0 = Pop(vm); +} +/* SZP1[] Set zone pointer 1 + * Code Range 0x14 + * Pops n: zone number (ULONG) + * Pushes - + * Sets zp1 + * Affects ALIGNPTS,ALIGNRP,DELTAP1,DELTAP2,DELTAP3,IP,ISECT,MD,MDAP,MIAP, + * MIRP,MSIRP,SHC,SHE,SHP,UTP + */ +void Inpterp_SZP1(VirtualMachine *vm) +{ + vm->gstate.zp1 = Pop(vm); +} +/* SZP2[] Set zone pointer 2 + * Code Range 0x15 + * Pops n: zone number (ULONG) + * Pushes - + * Sets zp2 + * Affects ALIGNPTS,ALIGNRP,DELTAP1,DELTAP2,DELTAP3,IP,ISECT,MD,MDAP,MIAP, + * MIRP,MSIRP,SHC,SHE,SHP,UTP + */ +void Inpterp_SZP2(VirtualMachine *vm) +{ + vm->gstate.zp2 = Pop(vm); +} +/* SZPS[] Set zone pointerS + * Code Range 0x16 + * Pops n: zone number (ULONG) + * Pushes - + * Sets zp0,zp1,zp2 + * Affects ALIGNPTS,ALIGNRP,DELTAP1,DELTAP2,DELTAP3,IP,ISECT,MD,MDAP,MIAP, + * MIRP,MSIRP,SHC,SHE,SHP,UTP + */ +void Inpterp_SZPS(VirtualMachine *vm) +{ + vm->gstate.zp0 = vm->gstate.zp1 = vm->gstate.zp2 = Pop(vm); +} +/* RTHG[] Round to half grid + * Code Range 0x19 + * Pops - + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MDIAP,MIRP,ROUND + * Uses freedom_vector, projection_vetor + */ +void Interp_RTHG(VirtualMachine *vm) +{ + vm->gstate.round_state = 0; +} +/* RTG[] Round to grid + * Code Range 0x18 + * Pops - + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MDIAP,MIRP,ROUND + * Uses freedom_vector, projection_vetor + */ +void Interp_RTG(VirtualMachine *vm) +{ + vm->gstate.round_state = 1; +} +/* RTDG[] Round to double grid + * Code Range 0x3D + * Pops - + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MDIAP,MIRP,ROUND + * Uses freedom_vector, projection_vetor + */ +void Interp_RTDG(VirtualMachine *vm) +{ + vm->gstate.round_state = 2; +} +/* RTHG[] Round down to grid + * Code Range 0x7D + * Pops - + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MDIAP,MIRP,ROUND + * Uses freedom_vector, projection_vetor + */ +void Interp_RDTG(VirtualMachine *vm) +{ + vm->gstate.round_state = 3; +} +/* RUTG[] Round up to grid + * Code Range 0x7C + * Pops - + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MDIAP,MIRP,ROUND + * Uses freedom_vector, projection_vetor + */ +void Interp_RUTG(VirtualMachine *vm) +{ + vm->gstate.round_state = 4; +} +/* ROFF[] Round off + * Code Range 0x7A + * Pops - + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MDIAP,MIRP,ROUND + * Uses freedom_vector, projection_vetor + */ +void Interp_ROFF(VirtualMachine *vm) +{ + vm->gstate.round_state = 5; +} +/* SROUND[] Super round + * Code Range 0x76 + * Pops n: number (ULONG) decomposed to obtain period, phase, threshold + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MIAP,MIRP,ROUND + */ +void Interp_SROUND(VirtualMachine *vm) +{ + ULONG n; + + n = Pop(vm); + /* not finished yet */ +} +/* S45ROUND[] Super round 45 degrees + * Code Range 0x77 + * Pops n: number (ULONG) decomposed to obtain period, phase, threshold + * Pushes - + * Sets round_state + * Affects MDAP,MDRP,MIAP,MIRP,ROUND + */ +void Interp_S45ROUND(VirtualMachine *vm) +{ + ULONG n; + + n = Pop(vm); + /* not finished yet */ +} +/* SLOOP[] Set LOOP variable + * Code Range 0x17 + * Pops n: value for loop graphics state variable + * Pushes - + * Set loop + * Affects ALIGNRP,FLIPPT,IP,SHP,SHIP + */ +void Interp_SLOOP(VirtualMachine *vm) +{ + vm->gstate.loop = Pop(vm); +} +/* SMD[] Set minimum_distance + * Code Range 0x1a + * Pops distance: value for minimum_distance (F26Dot6) + * Pushes - + * Sets minimum_distance + */ +void Interp_SMD(VirtualMachine *vm) +{ + vm->gstate.minimum_distance = Pop(vm); +} +/* INSTCTRL[] Instruction execution control + * Code Range 0x8E + * Pops s: selector flags + * value: USHORT padded to 32 bits used to set value of + * instruction control + * Pushes - + * Sets instruction_control + */ +void Interp_INSTCTRL(VirtualMachine *vm) +{ + ULONG flag; + + flag = Pop(vm); + vm->gstate.instruction_control = Pop(vm); + /* not finished yet */ +} +/* SCANCTRL[] Scan conversion cotrol + * Code Range 0x85 + * Pops n: flags indication when to turn on dropout mode (16 bits padded + * to 32 bits) + * Pushes - + * Sets scan_control + */ +void Interp_SCANCTRL(VirtualMachine *vm) +{ + USHORT flag; + + flag = Pop(vm); + /* not finished yet */ +} +/* SCANTYPE[] Scantype + * Code Range 0x8D + * Pops n: 16 bit interger + * Pushes - + * Sets scan_control + */ +void Interp_SCANTYPE(VirtualMachine *vm) +{ + /* not finished yet */ +} +/* SCVTCI[] Set control value table cut in + * Code Range 0x1D + * Pops n: value for cut_in (F26Dot6) + * Pushes - + * Sets control_value_cut_in + * Affects MIAP,MIRP + */ +void Interp_SCVTCI(VirtualMachine *vm) +{ + vm->gstate.control_value_cut_in = Pop(vm); +} +/* SSWCI[] Single width cut in + * Code Range 0x1E + * Pops n: value for single_width_cut_in + * Pushes - + * Sets signel_width_cut_in + * Affects MIAP,MIRP + */ +void Interp_SSWCI(VirtualMachine *vm) +{ + vm->gstate.single_width_cut_in = Pop(vm); +} +/* SSW[] Set single width + * Code Range 0x1F + * Pops n: value for single_width_value (FUnits) + * Pushes - + * Sets single_width_value + */ +void Interp_SSW(VirtualMachine *vm) +{ + vm->gstate.single_width_cut_in = Pop(vm); +} +/* FLIPON[] Set the auto_flip on + * Code Range 0x4D + * Pops - + * Pushes - + * Sets auto_flip + * Affects MIRP + */ +void Interp_FLIPON(VirtualMachine *vm) +{ + vm->gstate.auto_flip = 1; +} +/* FLIPOFF[] Set the auto_flip off + * Code Range 0x4E + * Pops - + * Pushes - + * Sets auto_flip + * Affects MIRP + */ +void Interp_FLIPOFF(VirtualMachine *vm) +{ + vm->gstate.auto_flip = 0; +} +/* SDB Set delta_base in the graphics state + * Code Range 0x5E + * Pops n: value for delta_base (ULONG) + * Pushes - + * Sets delta_base + * Affects DELTAP1,DELTAP2,DELTAP3,DELTAC1,DELTAC2,DELTAC3 + */ +void Interp_SDB(VirtualMachine *vm) +{ + vm->gstate.delta_base = Pop(vm); +} +/* SDS Set delta_shift in the graphics state + * Code Range 0x5F + * Pops n: value for delat_shift (ULONG) + * Sets delta_shift + * Affects DELTAP1,DELTAP2,DELTAP3,DELATC1,DELTAC2,DELTAC3 + */ +void Interp_SDS(VirtualMachine *vm) +{ + vm->gstate.delta_shift = Pop(vm); +} + +/* Reading and writing data */ + +/* GC[a] Get coordinate projected on to the projection_vector + * Code Range 0x46 - 0x47 + * a 0: use current position of point p + * 1: use the position of point p in the original outline + * Pops p: point number (ULONG) + * Pushes value: coordinate location (F26Dot6) + * Uses zp2,projection + */ +void Interp_GC(VirtualMachine *vm) +{ + ULONG point; + TTFVector pos; + + point = Pop(vm); + + /* not finished yet */ +} +/* SCFS[] Sets coordinate from the stack using projection_vector and + * freedom_vector + * Code Range 0x48 + * Pops value: distance from origin to move point (F26Dot6) + * p: point number (ULONG) + * Pushes - + * Uses zp2, freedom_vector, projection_vector + */ +void Interp_SCFS(VirtualMachine *vm) +{ +#ifdef WIN32 + __int64 tmp; +#else + long long tmp; +#endif + F26Dot6 value; + ULONG point; + + value = Pop(vm); + point = Pop(vm); + /* not finished yet */ +} +/* MD[a] Measure Distance + * + * Code Range 0x49-0x4A + * a 0: measure distance in grid-fitted outline + * 1: measure distance in original outline + * Pops p1: point number (ULONG) + * p2: point number (ULONG); + * Pushes distance (F26Dot6) + * uses zp1 with point p1, zp2 withe point p2, projection_vector + */ +void Interp_MD(VirtualMachine *vm) +{ + ULONG p1,p2; + BYTE opcode; + TTFUnitVector vect; + + opcode = (vm->iStream)[vm->ip]; + p1 = Pop(vm); + p2 = Pop(vm); + switch (opcode) + { + /* not finished yet */ + case 0x49: + break; + case 0x4A: + break; + } + /* not finished yet */ +} +/* MPPEM[] Measure Pixel Per EM + * + * Code Range 0x4B + * Pops - + * Pushes ppem:pixel per em (ULONG) + */ +void Interp_MPPEM(VirtualMachine *vm) +{ + /* not finished yet */ +} +/* MPS[] Measure Point Size + * + * Code Range 0x4C + * Pops - + * Pushes pointSize: the size in points of the current glyph (F26Dot6) + */ +void Interp_MPS(VirtualMachine *vm) +{ + F26Dot6 pointSize = vm->pointsize; + + Push(vm,pointSize); +} + +/* Mananging Outlines */ + +/* FLIPPT[] Flip point + * Code Range 0x80 + * Pops p: point number (ULONG) + * Pushes - + * Uses loop, p is referenced in zp0 + */ +void Interp_FLIPPT(VirtualMachine *vm) +{ + ULONG point; + + point = Pop(vm); + + /* not finished yet */ +} +/* FLIPRGON[] Filp range on + * Code Range 0x81 + * Pops hightpoint: highest point number in range of points to be flipped + * lowpoint: lowest point number in range of points to be flipped + * both are ULONG + * Pushes - + */ +void Interp_FLIPRGON(VirtualMachine *vm) +{ + +} diff --git a/Build/source/texk/ttfdump/libttf/kern.c b/Build/source/texk/ttfdump/libttf/kern.c new file mode 100644 index 00000000000..5ae636d9d44 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/kern.c @@ -0,0 +1,161 @@ +/* kern.c -- Kerning Table + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: kern.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadKERN(FILE *fp,KERNPtr kern,ULONG offset); + +void ttfInitKERN(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('k', 'e', 'r', 'n'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->kern = XCALLOC1 (KERN); + ttfLoadKERN(font->fp,font->kern,ptd->offset); + } +} + +static void ttfLoadKERN (FILE *fp,KERNPtr kern,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadKERN"); + + kern->version = ttfGetUSHORT(fp); + kern->nTables = ttfGetUSHORT(fp); + + kern->subtable = XCALLOC (kern->nTables, KernSubtable); + + for (i=0;i<kern->nTables;i++) + { + struct kernpair *pairs; + int j,n; + (kern->subtable+i)->version = ttfGetUSHORT(fp); + (kern->subtable+i)->length = ttfGetUSHORT(fp); + (kern->subtable+i)->coverage = ttfGetUSHORT(fp); + + switch ((kern->subtable+i)->coverage >> 8) + { + case 0: + (kern->subtable+i)->kern.kern0.nPairs = n = + ttfGetUSHORT(fp); + (kern->subtable+i)->kern.kern0.searchRange = + ttfGetUSHORT(fp); + (kern->subtable+i)->kern.kern0.entrySelector = + ttfGetUSHORT(fp); + (kern->subtable+i)->kern.kern0.rangeShift = + ttfGetUSHORT(fp); + (kern->subtable+i)->kern.kern0.pairs = pairs = + XCALLOC (n, struct kernpair); + + for (j=0;j<n;j++) + { + (pairs+j)->left = ttfGetUSHORT(fp); + (pairs+j)->right = ttfGetUSHORT(fp); + (pairs+j)->value = ttfGetFWord(fp); + } + break; + case 2: + /* not implemented yet */ + break; + default: + /* do nothing */ + break; + } + } +} + +void ttfPrintKERN(FILE *fp,KERNPtr kern) +{ + int i; + + fprintf(fp,"'kern' Table - Kerning Data\n"); + fprintf(fp,"---------------------------\n"); + fprintf(fp,"'kern' Version:\t %d\n", kern->version); + fprintf(fp,"Number of subtables:\t %d\n\n",kern->nTables); + + for (i=0;i<kern->nTables;i++) + { + struct kernpair *pairs; + int j,n; + + fprintf(fp,"\t Subtable format \t %d\n", + (kern->subtable+i)->coverage >> 8); + fprintf(fp,"\t Subtable version \t %d\n", + (kern->subtable+i)->version); + fprintf(fp,"\t Bytes in subtable \t %d\n", + (kern->subtable+i)->length); + fprintf(fp,"\t Coverage bits \t 0x%x\n", + (kern->subtable+i)->coverage); + switch ((kern->subtable+i)->coverage >> 8) + { + case 0: + n = (kern->subtable+i)->kern.kern0.nPairs; + pairs = (kern->subtable+i)->kern.kern0.pairs; + + fprintf(fp,"\t Number of pairs %d\n",n); + fprintf(fp,"\t Search Range %d\n", + (kern->subtable+i)->kern.kern0.searchRange); + fprintf(fp,"\t Entry Selector %d\n", + (kern->subtable+i)->kern.kern0.entrySelector); + fprintf(fp,"\t Range Shift %d\n", + (kern->subtable+i)->kern.kern0.rangeShift); + + fprintf(fp,"\t Left Glyph \t Right Glyph \t Kern Move\n"); + fprintf(fp,"\t ---------- \t ----------- \t ---------\n"); + + for (j=0;j<n;j++) + { + fprintf(fp,"\t\t %d \t\t %d \t\t %d\n", + (pairs+j)->left,(pairs+j)->right, + (pairs+j)->value); + } + break; + case 2: + /* not implemented yet */ + break; + default: + /* do nothing */ + break; + } + fprintf(fp,"\n"); + } + +} + +void ttfFreeKERN(KERNPtr kern) +{ + int i; + + if (kern != NULL) + { + for (i=0;i<kern->nTables;i++) + { + switch ((kern->subtable+i)->coverage >> 8) + { + case 0: + free((kern->subtable+i)->kern.kern0.pairs); + break; + case 2: + /* not implemented yet */ + break; + default: + /* do nothing */ + break; + } + } + free(kern->subtable); + free(kern); + } +} diff --git a/Build/source/texk/ttfdump/libttf/loca.c b/Build/source/texk/ttfdump/libttf/loca.c new file mode 100644 index 00000000000..0a170006389 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/loca.c @@ -0,0 +1,95 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: loca.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static LOCAPtr ttfAllocLOCA(TTFontPtr font); +static void ttfLoadLOCA(FILE *fp,LOCAPtr loca,ULONG offset); + +void ttfInitLOCA(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('l', 'o', 'c', 'a'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->loca = (LOCAPtr) ttfAllocLOCA(font); + ttfLoadLOCA(font->fp,font->loca,ptd->offset); + } +} +static LOCAPtr ttfAllocLOCA(TTFontPtr font) +{ + USHORT n=0; + LOCAPtr loca; + + loca = XCALLOC1 (LOCA); + loca->indexToLocFormat = font->head->indexToLocFormat; + loca->numGlyphs = n = font->maxp->numGlyphs; + + n += 1;/* the number of loca entry is numberOfGlyph+1 */ + loca->offset = XCALLOC (n, ULONG); + + return loca; +} +static void ttfLoadLOCA(FILE *fp,LOCAPtr loca,ULONG offset) +{ + /* warning: the number of loca entry is numberOfGlyph+1 !! */ + USHORT i,n = loca->numGlyphs+1; + + xfseek(fp, offset, SEEK_SET, "ttfLoadLOCA"); + + switch (loca->indexToLocFormat) + { + case LOCA_OFFSET_SHORT: + for (i=0;i<n;i++) + { + (loca->offset)[i] = (ULONG) ttfGetUSHORT(fp)*2; + } + break; + case LOCA_OFFSET_LONG: + ttfReadULONG (loca->offset, n, fp); + break; + } +} + +void ttfPrintLOCA(FILE *fp,LOCAPtr loca) +{ + USHORT i; + + 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) +{ + if (loca) + { + free (loca->offset); + free (loca); + } +} + +ULONG ttfLookUpGlyfLOCA(LOCAPtr loca,USHORT idx) +{ + /* out of bound or it is a non-glyph character */ + if (idx >= loca->numGlyphs || + loca->offset[idx] == loca->offset[idx+1]) + return (loca->offset)[0]; + + return (loca->offset)[idx]; +} diff --git a/Build/source/texk/ttfdump/libttf/ltsh.c b/Build/source/texk/ttfdump/libttf/ltsh.c new file mode 100644 index 00000000000..45c6f86e559 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/ltsh.c @@ -0,0 +1,62 @@ +/* ltsh.c -- Linear Threshold table + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: ltsh.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadLTSH(FILE *fp,LTSHPtr ltsh,ULONG offset); + +void ttfInitLTSH(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('L', 'T', 'S', 'H'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->ltsh = XCALLOC1 (LTSH); + ttfLoadLTSH(font->fp,font->ltsh,ptd->offset); + } +} + +static void ttfLoadLTSH (FILE *fp,LTSHPtr ltsh,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadLTSH"); + + ltsh->version = ttfGetUSHORT(fp); + ltsh->numGlyphs = ttfGetUSHORT(fp); + + ltsh->yPels = ttfMakeBYTE (ltsh->numGlyphs, fp); +} + +void ttfPrintLTSH(FILE *fp,LTSHPtr ltsh) +{ + int i; + + fprintf(fp,"'LTSH' Table - Linear Threshold Table\n"); + fprintf(fp,"-------------------------------------\n"); + fprintf(fp,"'LTSH' Version:\t %d\n",ltsh->version); + fprintf(fp,"Number of Glyphs:\t %d\n",ltsh->numGlyphs); + fprintf(fp,"\t Glyph # \t Threshold\n"); + + for (i=0;i<ltsh->numGlyphs;i++) + { + fprintf(fp,"\t %d. \t\t %d\n",i,ltsh->yPels[i]); + } +} + +void ttfFreeLTSH(LTSHPtr ltsh) +{ + if (ltsh != NULL) + { + free(ltsh->yPels); + free(ltsh); + } +} diff --git a/Build/source/texk/ttfdump/libttf/maxp.c b/Build/source/texk/ttfdump/libttf/maxp.c new file mode 100644 index 00000000000..1eadc12108a --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/maxp.c @@ -0,0 +1,75 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: maxp.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadMAXP(FILE *fp,MAXPPtr maxp,ULONG offset); + +void ttfInitMAXP(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('m', 'a', 'x', 'p'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->maxp = XCALLOC1 (MAXP); + ttfLoadMAXP(font->fp,font->maxp,ptd->offset); + } +} + +static void ttfLoadMAXP(FILE *fp,MAXPPtr maxp,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadMAXP"); + + maxp->version = ttfGetFixed(fp); + maxp->numGlyphs = ttfGetUSHORT(fp); + maxp->maxPoints = ttfGetUSHORT(fp); + maxp->maxContours = ttfGetUSHORT(fp); + maxp->maxCompositePoints = ttfGetUSHORT(fp); + maxp->maxCompositeContours = ttfGetUSHORT(fp); + maxp->maxZones = ttfGetUSHORT(fp); + maxp->maxTwilightPoints = ttfGetUSHORT(fp); + maxp->maxStorage = ttfGetUSHORT(fp); + maxp->maxFunctionDefs = ttfGetUSHORT(fp); + maxp->maxInstructionDefs = ttfGetUSHORT(fp); + maxp->maxStackElements = ttfGetUSHORT(fp); + maxp->maxSizeOfInstructions = ttfGetUSHORT(fp); + maxp->maxComponentElements = ttfGetUSHORT(fp); + maxp->maxComponentDepth = ttfGetUSHORT(fp); +} + +void ttfPrintMAXP(FILE *fp,MAXPPtr maxp) +{ + int b[2]; + + FixedSplit(maxp->version,b); + + fprintf(fp,"'maxp' Table - Maximum Profile\n"); + fprintf(fp,"------------------------------\n"); + 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); + fprintf(fp,"\t maxCompositePoints:\t %d\n",maxp->maxCompositePoints); + fprintf(fp,"\t maxCompositeContours:\t %d\n",maxp->maxCompositeContours); + fprintf(fp,"\t maxZones:\t\t %d\n",maxp->maxZones); + fprintf(fp,"\t maxTwilightPoints:\t %d\n",maxp->maxTwilightPoints); + fprintf(fp,"\t maxStorage:\t\t %d\n",maxp->maxStorage); + fprintf(fp,"\t maxFunctionDefs:\t %d\n",maxp->maxFunctionDefs); + fprintf(fp,"\t maxInstructionDefs:\t %d\n",maxp->maxInstructionDefs); + fprintf(fp,"\t maxStackElements:\t %d\n",maxp->maxStackElements); + fprintf(fp,"\t maxSizeOfInstructions:\t %d\n",maxp->maxSizeOfInstructions); + fprintf(fp,"\t maxComponentElements:\t %d\n",maxp->maxComponentElements); + fprintf(fp,"\t maxCompoenetDepth:\t %d\n",maxp->maxComponentDepth); +} + +void ttfFreeMAXP(MAXPPtr maxp) +{ + free(maxp); +} diff --git a/Build/source/texk/ttfdump/libttf/name.c b/Build/source/texk/ttfdump/libttf/name.c new file mode 100644 index 00000000000..6c8c6c64d1e --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/name.c @@ -0,0 +1,165 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: name.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadNAME(FILE *fp,NAMEPtr name,ULONG offset); +static void ttfLoadNameRecord(FILE *fp,NameRecordPtr rec,ULONG offset); +static void ttfPrintNameRecord(FILE *fp,NameRecordPtr rec); +static void ttfLoadNameRecordData(FILE *fp,NameRecordPtr rec,ULONG offset); +static void ttfPrintNameRecordData(FILE *fp,NameRecordPtr rec); +static void ttfFreeNameRecordData(NameRecordPtr rec); +static void HexDump(char *p,char *hex,char *asc,int len); + +void ttfInitNAME(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('n', 'a', 'm', 'e'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->name = XCALLOC1 (NAME); + ttfLoadNAME(font->fp,font->name,ptd->offset); + } +} + +static void ttfLoadNAME(FILE *fp,NAMEPtr name,ULONG offset) +{ + USHORT i,n; + ULONG pos; + + xfseek(fp, offset, SEEK_SET, "ttfLoadNAME"); + + name->format = ttfGetUSHORT(fp); + name->numberOfRecords = n = ttfGetUSHORT(fp); + name->offset = ttfGetUSHORT(fp); + + name->NameRecords = XCALLOC (n, NameRecord); + + pos = offset + sizeof(USHORT)*3; + + for(i=0;i<n;i++,pos+=12 /*sizeof(NameRecord)*/) + { + ttfLoadNameRecord(fp,name->NameRecords+i,pos); + ttfLoadNameRecordData(fp,name->NameRecords+i,offset+name->offset); + } +} +void ttfPrintNAME(FILE *fp,NAMEPtr name) +{ + USHORT i; + + fprintf(fp,"'name' Table - Naming Table\n"); + fprintf(fp,"---------------------------\n"); + fprintf(fp,"\t Format:\t\t %d\n",name->format); + fprintf(fp,"\t Number of Record:\t %d\n",name->numberOfRecords); + fprintf(fp,"\t Storage offset:\t %d\n",name->offset); + + for (i=0;i<name->numberOfRecords;i++) + { + fprintf(fp,"Name table %3d.\t",i); + ttfPrintNameRecord(fp,name->NameRecords+i); + } + +} +void ttfFreeNAME(NAMEPtr name) +{ + USHORT i; + + if (!name) + return; + + for (i=0;i<name->numberOfRecords;i++) + ttfFreeNameRecordData(name->NameRecords+i); + free(name->NameRecords); + free(name); +} +/* offset: address of the beginning of the name record */ +static void ttfLoadNameRecord(FILE *fp,NameRecordPtr rec,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadNameRecord"); + + rec->PlatformID = ttfGetUSHORT(fp); + rec->EncodingID = ttfGetUSHORT(fp); + rec->LanguageID = ttfGetUSHORT(fp); + rec->NameID = ttfGetUSHORT(fp); + rec->length = ttfGetUSHORT(fp); + rec->offset = ttfGetUSHORT(fp); +} +static void ttfPrintNameRecord(FILE *fp,NameRecordPtr rec) +{ + fprintf(fp," PlatformID:\t %d\n",rec->PlatformID); + fprintf(fp,"\t\t EncodingID:\t %d\n",rec->EncodingID); + fprintf(fp,"\t\t LanguageID:\t %d\n",rec->LanguageID); + fprintf(fp,"\t\t NameID:\t %d\n",rec->NameID); + fprintf(fp,"\t\t Length:\t %d\n",rec->length); + fprintf(fp,"\t\t Offset:\t %d\n",rec->offset); + ttfPrintNameRecordData(fp,rec); +} +/* ULONG offset: address of the beginning of the actual data (base actually) + * base: start of data storage, specified by NAME.offset + * offset: specified by NameRecord.offset */ +static void ttfLoadNameRecordData(FILE *fp,NameRecordPtr rec,ULONG offset) +{ + ULONG pos; + + pos = offset + rec->offset; + xfseek(fp, pos, SEEK_SET, "ttfLoadNameRecordData"); + + rec->data = XTALLOC (rec->length, char); + if (fread(rec->data,sizeof(char),rec->length,fp) != rec->length) + ttfError("Error when getting Name Record Data\n"); +} + +static void ttfPrintNameRecordData(FILE *fp,NameRecordPtr rec) +{ + USHORT i,j; + char hexbuf[100],ascbuf[100],*p; + + p = rec->data; + for (i=0;i<rec->length/10;i++,p+=10) + { + HexDump(p,hexbuf,ascbuf,10); + fprintf(fp,"\t\t %s > %s\n",hexbuf,ascbuf); + } + HexDump(p,hexbuf,ascbuf,rec->length % 10); + /* i know that this is ugly, but this makes output beautiful */ + i = strlen(hexbuf); + for (j=i;j<30;j++) + { + hexbuf[j] = ' '; + } + fprintf(fp,"\t\t %s > %s\n",hexbuf,ascbuf); + +} +static void HexDump(char *p,char *hex,char *asc,int len) +{ + int i; + unsigned char c; + char buf[100]; + + *hex = '\0'; + *asc = '\0'; + for (i=0;i<len;i++) + { + c = *(p+i); + sprintf(buf,"%02x ",c); + strcat(hex,buf); + if (isprint(c)) + *(asc+i) = c; + else + *(asc+i) = '.'; + } + *(asc+len) = *(hex+len*3) = '\0'; +} +static void ttfFreeNameRecordData(NameRecordPtr rec) +{ + free(rec->data); +} diff --git a/Build/source/texk/ttfdump/libttf/os2.c b/Build/source/texk/ttfdump/libttf/os2.c new file mode 100644 index 00000000000..66701e3dc61 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/os2.c @@ -0,0 +1,195 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ttf.h" +#include "ttfutil.h" + +#define __TTF_OS2 +#include "os2_P.h" + +/* $Id: os2.c,v 1.2 1998/07/06 06:07:01 werner Exp $ */ + +static void ttfLoadOS2(FILE *fp, OS_2Ptr os2, ULONG offset); + +void ttfInitOS2(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('O', 'S', '/', '2'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag, font)) != NULL) + { + font->os2 = XCALLOC1 (OS_2); + ttfLoadOS2(font->fp, font->os2, ptd->offset); + } +} + +static void ttfLoadOS2(FILE *fp, OS_2Ptr os2, ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadOS2"); + + os2->version = ttfGetUSHORT(fp); + os2->xAvgCharWidth = ttfGetSHORT(fp); + os2->usWeightClass = ttfGetUSHORT(fp); + os2->usWidthClass = ttfGetUSHORT(fp); + os2->fsType = ttfGetUSHORT(fp); + os2->ySubscriptXSize = ttfGetSHORT(fp); + os2->ySubscriptYSize = ttfGetSHORT(fp); + os2->ySubscriptXOffset = ttfGetSHORT(fp); + os2->ySubscriptYOffset = ttfGetSHORT(fp); + os2->ySuperscriptXSize = ttfGetSHORT(fp); + os2->ySuperscriptYSize = ttfGetSHORT(fp); + os2->ySuperscriptXOffset = ttfGetSHORT(fp); + os2->ySuperscriptYOffset = ttfGetSHORT(fp); + os2->yStrikeoutSize = ttfGetSHORT(fp); + os2->yStrikeoutPosition = ttfGetSHORT(fp); + os2->sFamilyClass = ttfGetSHORT(fp); + + if (fread(os2->panose, sizeof(CHAR), 10, fp) != 10) + ttfError("Error reading PANOSE\n"); + + os2->ulUnicodeRange1 = ttfGetULONG(fp); + os2->ulUnicodeRange2 = ttfGetULONG(fp); + os2->ulUnicodeRange3 = ttfGetULONG(fp); + os2->ulUnicodeRange4 = ttfGetULONG(fp); + + if (fread(os2->achVendID, sizeof(CHAR), 4, fp) != 4) + ttfError("Error reading achVendID\n"); + os2->achVendID[4] = 0x0; + + os2->fsSelection = ttfGetUSHORT(fp); + os2->usFirstCharIndex = ttfGetUSHORT(fp); + os2->usLastCharIndex = ttfGetUSHORT(fp); + os2->sTypoAscender = ttfGetSHORT(fp); + os2->sTypoDescender = ttfGetSHORT(fp); + os2->sTypoLineGap = ttfGetSHORT(fp); + os2->usWinAscent = ttfGetUSHORT(fp); + os2->usWinDescent = ttfGetUSHORT(fp); + + if (os2->version < 0x0001) + return; + + os2->ulCodePageRange1 = ttfGetULONG(fp); + os2->ulCodePageRange2 = ttfGetULONG(fp); + + if (os2->version < 0x0002) + return; + + os2->sxHeight = ttfGetSHORT(fp); + os2->sCapHeight = ttfGetSHORT(fp); + os2->usDefaultChar = ttfGetUSHORT(fp); + os2->usBreakChar = ttfGetUSHORT(fp); + os2->usMaxContext = ttfGetUSHORT(fp); +} + +/* Index checking for string array elements. */ +#define StrFromInd(str, ind) StringFromIndex(str, sizeof(str) / sizeof(str[0]), (int)ind) +static inline const char *StringFromIndex(const char **str, size_t sz, int ind) +{ + return ind >= 0 && ind < sz ? str[ind] : "invalid"; +} + +void ttfPrintOS2(FILE *fp,OS_2Ptr os2) +{ + char buf[80]; + + fprintf(fp,"'OS/2' Table - OS/2 and Windows Metrics\n"); + fprintf(fp,"---------------------------------------\n"); + + fprintf(fp,"\t 'OS/2' version:\t %d\n",os2->version); + fprintf(fp,"\t xAvgCharWidth:\t\t %d\n",os2->xAvgCharWidth); + fprintf(fp,"\t usWeightClass:\t\t %d \t '%s'\n",os2->usWeightClass, + StrFromInd(WeightClassName,os2->usWeightClass/100 - 1)); + fprintf(fp,"\t usWidthClass:\t\t %d \t '%s'\n",os2->usWidthClass, + StrFromInd(WidthClassName,os2->usWidthClass - 1)); + fprintf(fp,"\t fsType:\t\t %d\n",os2->fsType); + fprintf(fp,"\t ySubscriptXSize:\t %d\n",os2->ySubscriptXSize); + fprintf(fp,"\t ySubscriptYSize:\t %d\n",os2->ySubscriptYSize); + fprintf(fp,"\t ySubscriptXOffset:\t %d\n",os2->ySubscriptXOffset); + fprintf(fp,"\t ySubscriptYOffset:\t %d\n",os2->ySubscriptYOffset); + fprintf(fp,"\t ySuperscriptXSize:\t %d\n",os2-> ySuperscriptXSize); + fprintf(fp,"\t ySuperscriptYSize:\t %d\n",os2->ySuperscriptYSize); + fprintf(fp,"\t ySuperscriptXOffset:\t %d\n",os2->ySuperscriptXOffset); + fprintf(fp,"\t ySuperscriptYOffset:\t %d\n",os2->ySuperscriptYOffset); + fprintf(fp,"\t yStrikeoutSize:\t %d\n",os2->yStrikeoutSize); + fprintf(fp,"\t yStrikeoutPosition\t %d\n",os2->yStrikeoutPosition); + fprintf(fp,"\t sFamilyClass:\t %d \t subclass = %d\n", + (os2->sFamilyClass) >> 8,(os2->sFamilyClass) & 0x00ff); + fprintf(fp,"\t PANOSE:\n"); + fprintf(fp,"\t\t Family Kind:\t %d \t '%s'\n",os2->panose[0], + StrFromInd(PanoseFamily,os2->panose[0])); + fprintf(fp,"\t\t Serif Style:\t %d \t '%s'\n",os2->panose[1], + StrFromInd(PanoseSerif,os2->panose[1])); + fprintf(fp,"\t\t Weight:\t %d \t '%s'\n",os2->panose[2], + StrFromInd(PanoseWeight,os2->panose[2])); + fprintf(fp,"\t\t Proportion:\t %d \t '%s'\n",os2->panose[3], + StrFromInd(PanoseProportion,os2->panose[3])); + fprintf(fp,"\t\t Contrast:\t %d \t '%s'\n",os2->panose[4], + StrFromInd(PanoseContrast,os2->panose[4])); + fprintf(fp,"\t\t Stroke:\t %d \t '%s'\n",os2->panose[5], + StrFromInd(PanoseStroke,os2->panose[5])); + fprintf(fp,"\t\t Arm Style:\t %d \t '%s'\n",os2->panose[6], + StrFromInd(PanoseArm,os2->panose[6])); + fprintf(fp,"\t\t Lettreform:\t %d \t '%s'\n",os2->panose[7], + StrFromInd(PanoseLetterform,os2->panose[7])); + fprintf(fp,"\t\t Midline:\t %d \t '%s'\n",os2->panose[8], + StrFromInd(PanoseMidline,os2->panose[8])); + fprintf(fp,"\t\t X-height:\t %d \t '%s'\n",os2->panose[9], + StrFromInd(PanoseXHeight,os2->panose[9])); + fprintf(fp,"\t Unicode Range 1( Bits 0 - 31 ): \t 0x%08x\n", + os2->ulUnicodeRange1); + fprintf(fp,"\t Unicode Range 2( Bits 32 - 63 ): \t 0x%08x\n", + os2->ulUnicodeRange2); + fprintf(fp,"\t Unicode Range 3( Bits 64 - 95 ): \t 0x%08x\n", + os2->ulUnicodeRange3); + fprintf(fp,"\t Unicode Range 4( Bits 96 - 128 ): \t 0x%08x\n", + os2->ulUnicodeRange4); + + fprintf(fp,"\t achVendID:\t\t '%s'\n",os2->achVendID); + + buf[0] = 0x0; + if (os2->fsSelection & FS_FLAGS_REGULAR) + { + strcat(buf,"Regular "); + } + else + { + if (os2->fsSelection & FS_FLAGS_BOLD) + strcat(buf,"Bold "); + if (os2->fsSelection & FS_FLAGS_ITALIC) + strcat(buf,"Italic "); + } + fprintf(fp,"\t fsSelection:\t\t 0x%04x \t '%s'\n",os2->fsSelection,buf); + fprintf(fp,"\t usFirstCharIndex:\t 0x%04x\n ",os2->usFirstCharIndex); + fprintf(fp,"\t usLastCharIndex:\t 0x%04x\n",os2->usLastCharIndex); + fprintf(fp,"\t sTypoAscender:\t\t %d\n",os2->sTypoAscender); + fprintf(fp,"\t sTypoDescender:\t %d\n",os2->sTypoDescender); + fprintf(fp,"\t sTypoLineGap:\t\t %d\n",os2->sTypoLineGap); + fprintf(fp,"\t usWinAscent:\t\t %d\n",os2->usWinAscent); + fprintf(fp,"\t usWinDescent:\t\t %d\n",os2->usWinDescent); + + if (os2->version < 0x0001) + return; + + fprintf(fp,"\t CodePage Range 1( Bits 0 - 31 ):\t 0x%08x\n", + os2->ulCodePageRange1); + fprintf(fp,"\t CodePage Range 2( Bits 32- 63 ):\t 0x%08x\n", + os2->ulCodePageRange2); + + if (os2->version < 0x0002) + return; + + fprintf(fp,"\t sxHeight:\t\t %d\n",os2->sxHeight); + fprintf(fp,"\t sCapHeight:\t\t %d\n",os2->sCapHeight); + fprintf(fp,"\t usDefaultChar:\t\t 0x%04x\n",os2->usDefaultChar); + fprintf(fp,"\t usBreakChar:\t\t 0x%04x\n",os2->usBreakChar); + fprintf(fp,"\t usMaxContext:\t\t %d\n",os2->usMaxContext); +} + +void ttfFreeOS2(OS_2Ptr os2) +{ + free(os2); +} diff --git a/Build/source/texk/ttfdump/libttf/otfcommon.c b/Build/source/texk/ttfdump/libttf/otfcommon.c new file mode 100644 index 00000000000..55cb46c8ff7 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/otfcommon.c @@ -0,0 +1,1083 @@ +/* otfcommon.c -- OpenType Common Table Formats + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.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 *rOffset; + + xfseek (fp, offset, SEEK_SET, "loadOtfRuleSet"); + + otfRuleSet->otfRuleCount = ttfGetUSHORT (fp); + rOffset = ttfMakeUSHORT (otfRuleSet->otfRuleCount, fp); + otfRuleSet->otfRule = XCALLOC (otfRuleSet->otfRuleCount, OtfRule); + for (i = 0; i < otfRuleSet->otfRuleCount; i++) + loadOtfRule (&otfRuleSet->otfRule[i], fp, offset + rOffset[i]); + free (rOffset); +} + +OtfCtx1Ptr makeOTFCtx1 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *rOffset; + OtfCtx1Ptr otf = XCALLOC1 (OtfCtx1); + + cOffset = ttfGetUSHORT (fp); + otf->otfRuleSetCount = ttfGetUSHORT (fp); + rOffset = 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 + rOffset[i]); + free (rOffset); + + return otf; +} + +void printOTFCtx1 (FILE *fp, OtfCtx1Ptr otf) +{ + int i; + + fprintf (fp, " - Context %s Simple\n\t ", + otf->lookupType == 7 ? "Positioning" : "Substitution"); + 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. glyphCount: %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 *sOffset; + + xfseek (fp, offset, SEEK_SET, "loadOtfClassSet"); + + otfClassSet->otfClassRuleCnt = ttfGetUSHORT (fp); + sOffset = ttfMakeUSHORT (otfClassSet->otfClassRuleCnt, fp); + otfClassSet->otfClassRule = XCALLOC (otfClassSet->otfClassRuleCnt, OtfClassRule); + for (i = 0; i < otfClassSet->otfClassRuleCnt; i++) + loadOtfClassRule (&otfClassSet->otfClassRule[i], fp, offset + sOffset[i]); + free (sOffset); +} + +OtfCtx2Ptr makeOTFCtx2 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT clOffset; + USHORT *sOffset; + OtfCtx2Ptr otf = XCALLOC1 (OtfCtx2); + + cOffset = ttfGetUSHORT (fp); + clOffset = ttfGetUSHORT (fp); + otf->otfClassSetCnt = ttfGetUSHORT (fp); + sOffset = 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 (sOffset[i]) + loadOtfClassSet (&otf->otfClassSet[i], fp, offset + sOffset[i]); + free (sOffset); + + return otf; +} + +void printOTFCtx2 (FILE *fp, OtfCtx2Ptr otf) +{ + int i; + + fprintf (fp, " - Context %s Class-based\n\t ", + otf->lookupType == 7 ? "Positioning" : "Substitution"); + 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. glyphCount: %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 %s Coverage-based\n", + otf->lookupType == 7 ? "Positioning" : "Substitution"); + 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 *rOffset; + + xfseek (fp, offset, SEEK_SET, "loadChainOtfRuleSet"); + + chainOtfRuleSet->chainOtfRuleCount = ttfGetUSHORT (fp); + rOffset = ttfMakeUSHORT (chainOtfRuleSet->chainOtfRuleCount, fp); + chainOtfRuleSet->chainOtfRule = XCALLOC (chainOtfRuleSet->chainOtfRuleCount, ChainOtfRule); + for (i = 0; i < chainOtfRuleSet->chainOtfRuleCount; i++) + loadChainOtfRule (&chainOtfRuleSet->chainOtfRule[i], fp, offset + rOffset[i]); + free (rOffset); +} + +OtfChn1Ptr makeOTFChn1 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *rOffset; + OtfChn1Ptr otf = XCALLOC1 (OtfChn1); + + cOffset = ttfGetUSHORT (fp); + otf->chainOtfRuleSetCount = ttfGetUSHORT (fp); + rOffset = 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 + rOffset[i]); + free (rOffset); + + return otf; +} + +void printOTFChn1 (FILE *fp, OtfChn1Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context %s Simple\n\t ", + otf->lookupType == 8 ? "Positioning" : "Substitution"); + 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 *rOffset; + + xfseek (fp, offset, SEEK_SET, "loadChainOtfClassSet"); + + chainOtfClassSet->chainOtfClassRuleCnt = ttfGetUSHORT (fp); + rOffset = ttfMakeUSHORT (chainOtfClassSet->chainOtfClassRuleCnt, fp); + chainOtfClassSet->chainOtfClassRule = XCALLOC (chainOtfClassSet->chainOtfClassRuleCnt, ChainOtfClassRule); + for (i = 0; i < chainOtfClassSet->chainOtfClassRuleCnt; i++) + loadChainOtfClassRule (&chainOtfClassSet->chainOtfClassRule[i], fp, offset + rOffset[i]); + free (rOffset); +} + +OtfChn2Ptr makeOTFChn2 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT bOffset, iOffset, lOffset; + USHORT *sOffset; + OtfChn2Ptr otf = XCALLOC1 (OtfChn2); + + cOffset = ttfGetUSHORT (fp); + bOffset = ttfGetUSHORT (fp); + iOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + otf->chainOtfClassSetCnt = ttfGetUSHORT (fp); + sOffset = 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 (sOffset[i]) + loadChainOtfClassSet (&otf->chainOtfClassSet[i], fp, offset + sOffset[i]); + free (sOffset); + + return otf; +} + +void printOTFChn2 (FILE *fp, OtfChn2Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context %s Class-based\n\t ", + otf->lookupType == 8 ? "Positioning" : "Substitution"); + 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 %s Coverage-based\n", + otf->lookupType == 8 ? "Positioning" : "Substitution"); + 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/pclt.c b/Build/source/texk/ttfdump/libttf/pclt.c new file mode 100644 index 00000000000..73bbaf7ddd9 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/pclt.c @@ -0,0 +1,96 @@ +/* pclt.c -- PCL5 Table + * Copyright (C) 1997 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: pclt.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadPCLT(FILE *fp,PCLTPtr pclt,ULONG offset); + +void ttfInitPCLT(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('P', 'C', 'L', 'T'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->pclt = XCALLOC1 (PCLT); + ttfLoadPCLT(font->fp,font->pclt,ptd->offset); + } +} + +static void ttfLoadPCLT(FILE *fp,PCLTPtr pclt,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadPCLT"); + + pclt->version = ttfGetFixed(fp); + pclt->FontNumber = ttfGetULONG(fp); + pclt->Pitch = ttfGetUSHORT(fp); + pclt->xHeight = ttfGetUSHORT(fp); + pclt->Style = ttfGetUSHORT(fp); + pclt->TypeFamily = ttfGetUSHORT(fp); + pclt->CapHeight = ttfGetUSHORT(fp); + pclt->SymbolSet = ttfGetUSHORT(fp); + for (i=0;i<16;i++) + pclt->Typeface[i] = ttfGetCHAR(fp); + for (i=0;i<8;i++) + pclt->CharacterComplement[i] = ttfGetCHAR(fp); + for (i=0;i<6;i++) + pclt->FileName[i] = ttfGetCHAR(fp); + pclt->StrokeWeight = ttfGetCHAR(fp); + pclt->WidthType = ttfGetCHAR(fp); + pclt->SerifStyle = ttfGetBYTE(fp); +} + +void ttfPrintPCLT(FILE *fp,PCLTPtr pclt) +{ + int i; + int b[2]; + + FixedSplit(pclt->version,b); + + fprintf(fp,"`PCLT' Table - Printer Command Language Table\n"); + fprintf(fp,"---------------------------------------------\n"); + fprintf(fp,"\t version \t %d.%d\n",b[1],b[0]); + fprintf(fp,"\t fontNumber \t %d (0x%x)\n",pclt->FontNumber, + pclt->FontNumber ); + fprintf(fp,"\t pitch \t %d\n",pclt->Pitch); + fprintf(fp,"\t xHeight \t %d\n",pclt->xHeight); + fprintf(fp,"\t style \t %d\n",pclt->Style); + fprintf(fp,"\t typeFamily \t %x\n",pclt->TypeFamily); + fprintf(fp,"\t capHeight \t %d\n",pclt->CapHeight); + fprintf(fp,"\t symbolSet \t %d\n",pclt->SymbolSet); + fprintf(fp,"\t typeFace \t "); + for (i=0;i<6;i++) + fprintf(fp,"%c",pclt->Typeface[i]); + fprintf(fp,"\n"); + + fprintf(fp,"\t characterComplement 0x"); + for (i=0;i<8;i++) + fprintf(fp,"%02x",(unsigned char)pclt->CharacterComplement[i]); + fprintf(fp,"\n"); + + fprintf(fp,"\t fileName \t "); + for (i=0;i<6;i++) + fprintf(fp,"%c",pclt->FileName[i]); + fprintf(fp,"\n"); + + fprintf(fp,"\t strokeWeight \t %d\n",pclt->StrokeWeight); + fprintf(fp,"\t widthType \t %d\n",pclt->WidthType); + fprintf(fp,"\t serifStyle \t %d\n",pclt->SerifStyle); +} + +void ttfFreePCLT(PCLTPtr pclt) +{ + if (pclt != NULL) + free(pclt); +} diff --git a/Build/source/texk/ttfdump/libttf/post.c b/Build/source/texk/ttfdump/libttf/post.c new file mode 100644 index 00000000000..ab8f13c227c --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/post.c @@ -0,0 +1,156 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: post.c,v 1.3 1998/06/06 12:55:53 werner Exp $ */ + +static void ttfLoadPOST(FILE *fp, POSTPtr post, ULONG offset); + +void ttfInitPOST(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('p', 'o', 's', 't'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag, font)) != NULL) + { + font->post = XCALLOC1 (POST); + ttfLoadPOST(font->fp, font->post, ptd->offset); + } +} + +static void ttfLoadPOST(FILE *fp, POSTPtr post, ULONG offset) +{ + USHORT i,numGlyphs; + xfseek(fp, offset, SEEK_SET, "ttfLoadPOST"); + + post->format = ttfGetFixed(fp); + post->italicAngle = ttfGetFixed(fp); + post->underlinePosition = ttfGetFWord(fp); + post->underlineThickness = ttfGetFWord(fp); + post->isFixedPitch = ttfGetULONG(fp); + post->minMemType42 = ttfGetULONG(fp); + post->maxMemType42 = ttfGetULONG(fp); + post->minMemType1 = ttfGetULONG(fp); + post->maxMemType1 = ttfGetULONG(fp); + + switch (post->format) + { + case 0x00020000: + post->name.format20 = XCALLOC1 (Format20); + post->name.format20->numGlyphs = numGlyphs = ttfGetUSHORT(fp); + post->name.format20->glyphNameIndex = ttfMakeUSHORT (numGlyphs, fp); + + post->name.format20->GlyphName = XCALLOC (numGlyphs, CHAR *); + for (i=0;i<numGlyphs;i++) + { + unsigned char len; + if (post->name.format20->glyphNameIndex[i] <= 257) + { + /* do nothing for standard Mac glyf name */ + } + else if (post->name.format20->glyphNameIndex[i] <= 32767) + { + /* non-standard glyf name is stored as a Pascal + * string in the file i.e. + * the first byte is the length of the string + * but the string is not ended with a null + * character */ + len = (unsigned char) ttfGetCHAR(fp); + post->name.format20->GlyphName[i] = XTALLOC (len+1, CHAR); + if (len) + fread(post->name.format20->GlyphName[i], + sizeof(CHAR), len, fp); + post->name.format20->GlyphName[i][len] = 0x0; + } + } + break; + case 0x00028000: /* 2.5 in 16.16 format */ + /* not implemented yet */ + break; + default: + /* do nothing */ ; + } +} + +void ttfPrintPOST(FILE *fp,POSTPtr post) +{ + int b[2],b1[2]; + USHORT i,numGlyphs; + + FixedSplit(post->format, b); + FixedSplit(post->italicAngle, b1); + fprintf(fp,"'post' Table - PostScript\n"); + fprintf(fp,"-------------------------\n"); + fprintf(fp,"\t 'post' format:\t\t %d.%d\n", b[1], b[0]); + fprintf(fp,"\t italicAngle:\t\t %d.%d\n", b1[1], b1[0]); + fprintf(fp,"\t underlinePosition:\t %d\n", post->underlinePosition); + fprintf(fp,"\t underlineThichness:\t %d\n", post->underlineThickness); + fprintf(fp,"\t isFixedPitch:\t\t %ud\n", post->isFixedPitch); + fprintf(fp,"\t minMemType42:\t\t %ud\n", post->minMemType42); + fprintf(fp,"\t maxMemType42:\t\t %ud\n", post->maxMemType42); + fprintf(fp,"\t minMemType1:\t\t %ud\n", post->minMemType1); + fprintf(fp,"\t maxMemType1:\t\t %ud\n", post->maxMemType1); + + switch (post->format) + { + case 0x00020000: + numGlyphs = post->name.format20->numGlyphs; + fprintf(fp, "\t Format 2.0: Non-Standard (for PostScript) TrueType Glyph Set.\n"); + fprintf(fp,"\t\t numGlyphs:\t %d\n", + post->name.format20->numGlyphs); + for (i=0;i<numGlyphs;i++) + { + if (post->name.format20->glyphNameIndex[i] < 257) + { + fprintf(fp,"\t\t Glyf %3d -> Mac Glyph # %3d\n", i, + post->name.format20->glyphNameIndex[i]); + } + else if (post->name.format20->glyphNameIndex[i] < 32767) + { + fprintf(fp,"\t\t Glyf %3d -> PSGlyf Name # %3d, '%s'\n", + i, post->name.format20->glyphNameIndex[i] - 257, + post->name.format20->GlyphName[i]); + } + } + break; + case 0x00020005: + /* not implemented yet */ + break; + default: + /* do nothing */; + } +} + +void ttfFreePOST(POSTPtr post) +{ + USHORT i, numGlyphs; + + if (!post) + return; + + switch (post->format) + { + case 0x00020000: + numGlyphs = post->name.format20->numGlyphs; + for (i=0;i<numGlyphs;i++) + { + if (post->name.format20->glyphNameIndex[i] > 257) + free(post->name.format20->GlyphName[i]); + } + free(post->name.format20->glyphNameIndex); + free(post->name.format20->GlyphName); + free(post->name.format20); + break; + case 0x00020005: + /* not implemented yet */ + break; + default: + /* do nothing */; + } + free(post); +} diff --git a/Build/source/texk/ttfdump/libttf/prep.c b/Build/source/texk/ttfdump/libttf/prep.c new file mode 100644 index 00000000000..6408e9ef881 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/prep.c @@ -0,0 +1,47 @@ +/* prep.c -- Control Value Program + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: prep.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadPREP(FILE *fp,BYTE *prep,USHORT lenght,ULONG offset); + +void ttfInitPREP(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('p', 'r', 'e', 'p'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->prepLength = ptd->length; + font->prep = XCALLOC (font->prepLength, BYTE); + ttfLoadPREP(font->fp,font->prep,font->prepLength,ptd->offset); + } +} + +static void ttfLoadPREP(FILE *fp,BYTE *prep,USHORT length,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadPREP"); + + if (fread(prep, sizeof(BYTE), length, fp) != length) + ttfError("Error when getting PREP\n"); +} + +void ttfPrintPREP(FILE *fp, BYTE *prep, USHORT length) +{ + ttfPrintInstructions(fp, prep); +} + +void ttfFreePREP(BYTE *prep) +{ + if (prep != NULL) + free(prep); +} diff --git a/Build/source/texk/ttfdump/libttf/stack.c b/Build/source/texk/ttfdump/libttf/stack.c new file mode 100644 index 00000000000..e560fc854e7 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/stack.c @@ -0,0 +1,96 @@ +/* stack.c -- primitives for managing instruction stack and stream + * Copyright (C) 1996 Li-Da Lho, All right reserved. + */ +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: stack.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +#define stack (vm->Stack) +#define sp (vm->sp) +#define limit (vm->stklimit) +#define ins (vm->iStream) +#define ip (vm->ip) + +enum TTF_ERROR {StackOverflow ,InstructionOverflow}; + +/* Push LONG l onto the stack of vm */ +inline void Push(VirtualMachine *vm, LONG l) +{ + if (sp < limit) + { + stack[sp] = l; + sp += 1; + } + else + vm->Error_State = StackOverflow; +} +/* Pop LONG from the stack of vm and store in l */ +inline LONG Pop(VirtualMachine *vm) +{ + LONG l; + + if (sp > 0) + { + l = stack[sp]; + sp -= 1; + return l; + } + else + { + vm->Error_State = StackOverflow; + return 0; + } +} + +/* read one byte from the instruction stream */ +inline BYTE GetBYTE(VirtualMachine *vm) +{ + if (ip < vm->insLength+1) + return ins[ip++]; + else + { + vm->Error_State = InstructionOverflow; + return 0; + } +} +/* read two bytes from the instruction stream */ +inline SHORT GetSHORT(VirtualMachine *vm) +{ + SHORT n = 0; + + if (ip < vm->insLength + 2) + { + n = ins[ip++] << 8; + n |= ins[ip++]; + return n; + } + else + { + vm->Error_State = InstructionOverflow; + return 0; + } +} +#if 0 +/* Not used */ +/* read four bytes from the instruction steam */ +inline LONG GetLONG(VirtualMachine *vm) +{ + LONG n = 0; + + if (ip < vm->insLength + 4) + { + n = ins[ip++] << 24; + n |= ins[ip++] << 16; + n |= ins[ip++] << 8; + n |= ins[ip++] ; + return n; + } + else + { + vm->Error_State = InstructionOverflow; + return 0; + } +} +#endif diff --git a/Build/source/texk/ttfdump/libttf/tabledir.c b/Build/source/texk/ttfdump/libttf/tabledir.c new file mode 100644 index 00000000000..799736bce5e --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/tabledir.c @@ -0,0 +1,96 @@ +/* loadtable.c + * Load the tables of the Table Directory of a True Type font file + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: tabledir.c,v 1.2 1998/07/04 13:17:51 werner Exp $ */ + +static void ttfLoadTableDir(FILE *fp,TableDirPtr p,ULONG offset); + +#define Offset 12 /* start point of table dir */ + +void ttfInitTableDir(TTFontPtr font, ULONG offset) +{ + int i,pos; /* table directory starts form position 12 */ + + font->dir = XCALLOC (font->numTables, TableDir); + pos = Offset + offset; + for (i=0;i<font->numTables;i++) + { + ttfLoadTableDir(font->fp,font->dir+i,pos); + pos += sizeof(TableDir); + } +} + +static void ttfLoadTableDir(FILE *fp,TableDirPtr p,ULONG offset) +{ + xfseek(fp, offset, SEEK_SET, "ttfLoadTableDir"); + + p -> tag = ttfGetULONG(fp); + p -> checksum = ttfGetULONG(fp); + p -> offset = ttfGetULONG(fp); + p -> length = ttfGetULONG(fp); +} + +void ttfPrintTableDir(FILE *fp,TableDirPtr p) +{ + fprintf(fp,"'%s' - checksum = 0x%08x, offset = 0x%08x, len = %9u\n", + TagToStr(p->tag),p->checksum,p->offset,p->length); +} + +void ttfFreeTableDir(TableDirPtr p) +{ + free(p); +} + +/* ttfLookUpTableDir + * lookup the specified table in an array of TableDir + * Linear search at present, should change to binary search in the + * future to improve effcience + * The tag name are sorted in ascent order in ttf file. + */ +TableDirPtr ttfLookUpTableDir(ULONG tagname,TTFontPtr font) +{ + USHORT i,n = font->numTables; + TableDirPtr ptable = font->dir; + + for (i=0;i<n;i++,ptable++) + { + if (ptable->tag == tagname) + return ptable; + } + return NULL; +} + +#if 0 +/* Not used */ +/* calculate table check sum */ +/* can't be done until the data abstraction have been finished */ +/* not finished yet */ +ULONG ttfCalcTableCheckSum(ULONG tagname,TTFontPtr font) +{ + ULONG sum = 0L,Length; + TableDirPtr ptable; + + Length = ((ptable->length+3) & ~3) / sizeof(ULONG); + + ptable = ttfLookUpTableDir(tagname, font); + xfseek(font->fp, ptable->offset, SEEK_SET, "ttfCalcTableCheckSum"); + + while (Length--) + { + sum += ttfGetULONG(font->fp); + } + + return sum; +} +#endif diff --git a/Build/source/texk/ttfdump/libttf/ttc.c b/Build/source/texk/ttfdump/libttf/ttc.c new file mode 100644 index 00000000000..09295af270f --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/ttc.c @@ -0,0 +1,81 @@ +/* ttc.c -- True Type Collection Support + * Copyright (C) 1997 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ttf.h" +#include "ttfutil.h" +#include "ttc.h" + +/* $Id: ttc.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadTTCFont(TTCHeaderPtr ttc, FILE *fp, const char *filename); + +TTCHeaderPtr ttfLoadTTCHeader(char * filename) +{ + ULONG tag = FT_MAKE_TAG ('t', 't', 'c', 'f'); + TTCHeaderPtr ttc; + FILE *fp; + + if ((fp = fopen_truetype (filename)) == NULL) + { + fprintf(stderr,"Can't open ttc file %s\n",filename); + return NULL; + } + ttc = XCALLOC1 (TTCHeader); + + /* True Type Collection's TTCHeader */ + if ((ttc->TTCTag = ttfGetULONG(fp)) == tag) + { + ttc->version = ttfGetFixed(fp); + ttc->DirCount = (USHORT) ttfGetULONG(fp); + ttc->offset = ttfMakeULONG (ttc->DirCount, fp); + ttfLoadTTCFont(ttc,fp,filename); + return ttc; + } + else + /* a file with ttc in name but no ttc tag in it */ + return NULL; +} + +static void ttfLoadTTCFont(TTCHeaderPtr ttc,FILE *fp,const char *filename) +{ + unsigned int i; + + ttc->font = XCALLOC (ttc->DirCount, TTFont); + + /* currently, we are loading all fonts in a TTC file. + * I still can't find a good way to share the data. */ + for (i=0;i<ttc->DirCount;i++) + { + (ttc->font+i) -> fp = fp; + (ttc->font+i) -> ttfname = XTALLOC (strlen(filename)+16, char); + sprintf ((ttc->font+i)->ttfname, "%s:%u", filename, i); + ttfLoadFont((ttc->font+i),(ttc->offset)[i]); + } +} + +void ttfFreeTTCFont(TTCHeaderPtr ttc) +{ + int i; + + for (i=0;i<ttc->DirCount;i++) + { + ttfFreeRequiredTables(ttc->font+i); + + ttfFreeOptionalTables(ttc->font+i); + + ttfFreeTableDir((ttc->font+i)->dir); + free((ttc->font+i)->refcount); + } + + free(ttc->offset); + free(ttc->font); + free(ttc); +} diff --git a/Build/source/texk/ttfdump/libttf/ttfread.c b/Build/source/texk/ttfdump/libttf/ttfread.c new file mode 100644 index 00000000000..5947484e00b --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/ttfread.c @@ -0,0 +1,180 @@ +/* ttfread.c + * read data element form ttf file + * swap byte order carefully for MSBFirst + * presume that int is 32 bits + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> + +#if defined(__GNUC__) && defined(_IBMR2) +/* Workaround for missing typedef in gcc (egcs-2.90.27 980315 (egcs-1.0.2 release)) */ +typedef long blkcnt_t; /* number of blocks in the file */ +#endif + +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: ttfread.c,v 1.2 1998/07/04 13:17:51 werner Exp $ */ + +BYTE ttfGetBYTE(FILE *fp) +{ + int cc; + if ((cc = fgetc(fp)) == EOF) + { + if (feof(fp) != 0) + ttfError("Unexpected EOF\n"); + else + ttfError("Error Getting BYTE\n"); + } + return (BYTE) cc; +} + +CHAR ttfGetCHAR(FILE *fp) +{ + int cc; + if ((cc = fgetc(fp)) == EOF) + { + if (feof(fp) != 0) + ttfError("Unexpected EOF\n"); + else + ttfError("Error Getting CHAR\n"); + } + return (CHAR) cc; +} + +USHORT ttfGetUSHORT(FILE *fp) +{ + int cc; + cc = ttfGetBYTE(fp) << 8; + cc |= ttfGetBYTE(fp); + + return (USHORT) cc; +} + +SHORT ttfGetSHORT(FILE *fp) +{ + int cc; + cc = ttfGetBYTE(fp) << 8; + cc |= ttfGetBYTE(fp); + + return (SHORT) cc; +} + +ULONG ttfGetULONG(FILE *fp) +{ + int cc; + cc = ttfGetBYTE(fp) << 24; + cc |= ttfGetBYTE(fp) << 16; + cc |= ttfGetBYTE(fp) << 8; + cc |= ttfGetBYTE(fp); + + return (ULONG) cc; +} + +LONG ttfGetLONG(FILE *fp) +{ + int cc; + cc = ttfGetBYTE(fp) << 24; + cc |= ttfGetBYTE(fp) << 16; + cc |= ttfGetBYTE(fp) << 8; + cc |= ttfGetBYTE(fp); + + return (LONG) cc; +} + +Fixed ttfGetFixed(FILE *fp) +{ + return (Fixed) ttfGetULONG(fp); +} + +FUnit ttfGetFUnit(FILE *fp) +{ + return (FUnit) ttfGetUSHORT(fp); +} + +FWord ttfGetFWord(FILE *fp) +{ + return (FWord) ttfGetSHORT(fp); +} + +uFWord ttfGetuFWord(FILE *fp) +{ + return (uFWord) ttfGetUSHORT(fp); +} + +F2Dot14 ttfGetF2Dot14(FILE *fp) +{ + return (F2Dot14) ttfGetUSHORT(fp); +} + +/* Read arrays. */ +void ttfReadUSHORT(USHORT *array, size_t nelem, FILE *fp) +{ + int i; + for (i = 0; i < nelem; i++) + array[i] = ttfGetUSHORT (fp); +} + +void ttfReadULONG(ULONG *array, size_t nelem, FILE *fp) +{ + int i; + for (i = 0; i < nelem; i++) + array[i] = ttfGetULONG (fp); +} + +void ttfReadFWord(FWord *array, size_t nelem, FILE *fp) +{ + int i; + for (i = 0; i < nelem; i++) + array[i] = ttfGetFWord (fp); +} + +/* Allocate and read arrays. */ +BYTE *ttfMakeBYTE(size_t nelem, FILE *fp) +{ + int i; + BYTE *array = XTALLOC (nelem, BYTE); + for (i = 0; i < nelem; i++) + array[i] = ttfGetBYTE (fp); + return array; +} + +USHORT *ttfMakeUSHORT(size_t nelem, FILE *fp) +{ + int i; + USHORT *array = XTALLOC (nelem, USHORT); + for (i = 0; i < nelem; i++) + array[i] = ttfGetUSHORT (fp); + return array; +} + +SHORT *ttfMakeSHORT(size_t nelem, FILE *fp) +{ + int i; + SHORT *array = XTALLOC (nelem, SHORT); + for (i = 0; i < nelem; i++) + array[i] = ttfGetSHORT (fp); + return array; +} + +ULONG *ttfMakeULONG(size_t nelem, FILE *fp) +{ + int i; + ULONG *array = XTALLOC (nelem, ULONG); + for (i = 0; i < nelem; i++) + array[i] = ttfGetULONG (fp); + return array; +} + +LONG *ttfMakeLONG(size_t nelem, FILE *fp) +{ + int i; + LONG *array = XTALLOC (nelem, LONG); + for (i = 0; i < nelem; i++) + array[i] = ttfGetLONG (fp); + return array; +} + diff --git a/Build/source/texk/ttfdump/libttf/ttfutil.c b/Build/source/texk/ttfdump/libttf/ttfutil.c new file mode 100644 index 00000000000..4c436f993c9 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/ttfutil.c @@ -0,0 +1,93 @@ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: ttfutil.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +/* FixedSplit: split Fixed in to two interger (16.16) */ +void FixedSplit(Fixed f,int b[]) +{ + b[0] = f & 0xff00; + b[1] = f >> 16; +} + +char * +TagToStr(ULONG tag) +{ + static char str[5] = "XXXX"; + + str[0] = (tag >> 24) & 0xff; + str[1] = (tag >> 16) & 0xff; + str[2] = (tag >> 8) & 0xff; + str[3] = tag & 0xff; + return str; +} + +void ttfError(const char * msg) +{ + fprintf(stderr,"%s",msg); + exit(EXIT_FAILURE); +} + +#ifndef KPATHSEA +/* 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) + FATAL_PERROR(funcname); +} + +void * +xmalloc (size_t size) +{ + void *new_mem = (void *)malloc(size ? size : 1); + + if (new_mem == NULL) { + fprintf(stderr, "fatal: memory exhausted (xmalloc of %lu bytes).\n", + (unsigned long)size); + exit(EXIT_FAILURE); + } + + return new_mem; +} + +void * +xcalloc (size_t nelem, size_t elsize) +{ + void *new_mem = (void*)calloc(nelem ? nelem : 1, elsize ? elsize : 1); + + if (new_mem == NULL) { + fprintf(stderr, + "xcalloc: request for %lu elements of size %lu failed.\n", + (unsigned long)nelem, (unsigned long)elsize); + exit(EXIT_FAILURE); + } + + return new_mem; +} + +char * +xstrdup (const char *s) +{ + char *new_string = xmalloc(strlen (s) + 1); + return strcpy(new_string, s); +} +#endif /* !KPATHSEA */ diff --git a/Build/source/texk/ttfdump/libttf/vdmx.c b/Build/source/texk/ttfdump/libttf/vdmx.c new file mode 100644 index 00000000000..ed9139d7c11 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/vdmx.c @@ -0,0 +1,133 @@ +/* vdmx.c -- Vertical Device Metrics + * Copyright (C) 1996 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: vdmx.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadVDMX(FILE *fp,VDMXPtr vdmx,ULONG offset); + +void ttfInitVDMX(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('V', 'D', 'M', 'X'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->vdmx = XCALLOC1 (VDMX); + ttfLoadVDMX(font->fp,font->vdmx,ptd->offset); + } +} + +static void ttfLoadVDMX (FILE *fp,VDMXPtr vdmx,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadVDMX"); + + vdmx->version = ttfGetUSHORT(fp); + vdmx->numRecs = ttfGetUSHORT(fp); + vdmx->numRatios = ttfGetUSHORT(fp); + + vdmx->ratRange = XCALLOC (vdmx->numRatios, Ratios); + for (i=0;i<vdmx->numRatios;i++) + { + (vdmx->ratRange+i)->CharSet = ttfGetBYTE(fp); + (vdmx->ratRange+i)->xRatio = ttfGetBYTE(fp); + (vdmx->ratRange+i)->yStartRatio = ttfGetBYTE(fp); + (vdmx->ratRange+i)->yEndRatio = ttfGetBYTE(fp); + + } + + vdmx->offset = ttfMakeUSHORT (vdmx->numRatios, fp); + + vdmx->groups = XCALLOC (vdmx->numRecs, Vdmx); + for (i=0;i<vdmx->numRecs;i++) + { + int j; + (vdmx->groups+i)->recs = ttfGetUSHORT(fp); + (vdmx->groups+i)->startsz = ttfGetBYTE(fp); + (vdmx->groups+i)->endsz = ttfGetBYTE(fp); + + (vdmx->groups+i)->entry = XCALLOC ((vdmx->groups+i)->recs, vTable); + + for (j=0;j<(vdmx->groups+i)->recs;j++) + { + ((vdmx->groups+i)->entry+j)->yPelHeight = ttfGetUSHORT(fp); + ((vdmx->groups+i)->entry+j)->yMax = ttfGetSHORT(fp); + ((vdmx->groups+i)->entry+j)->yMin = ttfGetSHORT(fp); + } + } +} + +void ttfPrintVDMX(FILE *fp,VDMXPtr vdmx) +{ + int i; + + fprintf(fp,"'VDMX' Table - Precomputed Vertical Device Metrics\n"); + fprintf(fp,"--------------------------------------------------\n"); + + + fprintf(fp,"Version:\t %d\n", vdmx->version); + fprintf(fp,"Number of Hgt Records:\t %d\n",vdmx->numRecs); + fprintf(fp,"Number of Ratio Records:\t %d\n",vdmx->numRecs); + + for (i=0;i<vdmx->numRatios;i++) + { + fprintf(fp,"\t Ratio Record #%d\n",i+1); + fprintf(fp,"\t\t CharSetId \t %d\n",(vdmx->ratRange+i)->CharSet); + fprintf(fp,"\t\t xRatio \t %d\n",(vdmx->ratRange+i)->xRatio); + fprintf(fp,"\t\t yStartRatio \t %d\n",(vdmx->ratRange+i)->yStartRatio); + fprintf(fp,"\t\t yEndRatio \t %d\n",(vdmx->ratRange+i)->yEndRatio); + fprintf(fp,"\t\t Record Offset %d (group #%d)\n\n",vdmx->offset[i],i); + } + + fprintf(fp,"\t VDMX Height Record Groups\n"); + fprintf(fp,"\t -------------------------\n\n"); + + for (i=0;i<vdmx->numRecs;i++) + { + int j; + + fprintf(fp,"\t %d. Number of Hgt Records %d\n",i, + (vdmx->groups+i)->recs); + fprintf(fp,"\t Starting Y Pel Height %d\n", + (vdmx->groups+i)->startsz); + fprintf(fp,"\t Ending Y Pel Height %d\n", + (vdmx->groups+i)->endsz); + + for (j=0;j<(vdmx->groups+i)->recs;j++) + { + fprintf(fp,"\t\t %d. Pel Height= %d\n",j+1, + ((vdmx->groups+i)->entry+j)->yPelHeight); + fprintf(fp,"\t\t yMax= \t %d\n", + ((vdmx->groups+i)->entry+j)->yMax); + fprintf(fp,"\t\t yMin= \t %d\n\n", + ((vdmx->groups+i)->entry+j)->yMin); + } + } + +} + +void ttfFreeVDMX(VDMXPtr vdmx) +{ + int i; + if (vdmx != NULL) + { + for (i=0;i<vdmx->numRecs;i++) + { + free((vdmx->groups+i)->entry); + } + free(vdmx->ratRange); + free(vdmx->offset); + free(vdmx->groups); + free(vdmx); + } +} diff --git a/Build/source/texk/ttfdump/libttf/vhea.c b/Build/source/texk/ttfdump/libttf/vhea.c new file mode 100644 index 00000000000..3a74c36adb0 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/vhea.c @@ -0,0 +1,84 @@ +/* vhea.c -- Vertical Header Table + * Copyright (C) 1997 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: vhea.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadVHEA(FILE *fp,VHEAPtr vhea,ULONG offset); + +void ttfInitVHEA(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('v', 'h', 'e', 'a'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->vhea = XCALLOC1 (VHEA); + ttfLoadVHEA(font->fp,font->vhea,ptd->offset); + } +} + +static void ttfLoadVHEA (FILE *fp,VHEAPtr vhea,ULONG offset) +{ + int i; + + xfseek(fp, offset, SEEK_SET, "ttfLoadVHEA"); + + vhea->version = ttfGetFixed(fp); + vhea->ascent = ttfGetSHORT(fp); + vhea->descent = ttfGetSHORT(fp); + vhea->lineGap = ttfGetSHORT(fp); + vhea->advanceHeightMax = ttfGetSHORT(fp); + vhea->minTopSideBearing = ttfGetSHORT(fp); + vhea->minBottomSideBearing = ttfGetSHORT(fp); + vhea->yMaxExtent = ttfGetSHORT(fp); + vhea->caretSlopeRise = ttfGetSHORT(fp); + vhea->caretSlopeRun = ttfGetSHORT(fp); + vhea->caretOffset = ttfGetSHORT(fp); + for(i=0;i<4;i++) + (vhea->reserved)[i] = ttfGetSHORT(fp); + vhea->metricDataFormat = ttfGetSHORT(fp); + vhea->numOfLongVerMetrics = ttfGetUSHORT(fp); +} + +void ttfPrintVHEA(FILE *fp,VHEAPtr vhea) +{ + int i,b[2]; + + fprintf(fp,"'VHEA' - Vertical Header Table\n"); + fprintf(fp,"------------------------------\n"); + + FixedSplit(vhea->version,b); + + fprintf(fp,"\t version:\t %d.%d\n",b[1],b[0]); + fprintf(fp,"\t ascent:\t %d\n",vhea->ascent); + fprintf(fp,"\t descent:\t %d\n",vhea->descent); + fprintf(fp,"\t lineGap:\t %d\n",vhea->lineGap); + fprintf(fp,"\t advanceHeightMax: %d\n",vhea->advanceHeightMax); + fprintf(fp,"\t minTopSideBearing: %d\n",vhea->minTopSideBearing); + fprintf(fp,"\t minBottomBearing: %d\n",vhea->minBottomSideBearing); + fprintf(fp,"\t yMaxExtent:\t %d\n",vhea->yMaxExtent); + fprintf(fp,"\t caretSlopeRise: %d\n", vhea->caretSlopeRise); + fprintf(fp,"\t caretSlopeRun: %d\n", vhea->caretSlopeRun); + fprintf(fp,"\t caretOffset:\t %d\n", vhea->caretOffset); + for(i=0;i<4;i++) + fprintf(fp,"\t reserved %d:\t %d\n",i,(vhea->reserved)[i]); + fprintf(fp,"\t metricDataFormat:\t %d\n", vhea->metricDataFormat); + fprintf(fp,"\t numOfLongVerMetrics: %d\n",vhea->numOfLongVerMetrics); +} + +void ttfFreeVHEA(VHEAPtr vhea) +{ + if (vhea != NULL) + { + free(vhea); + } +} diff --git a/Build/source/texk/ttfdump/libttf/vmtx.c b/Build/source/texk/ttfdump/libttf/vmtx.c new file mode 100644 index 00000000000..0cdc9edd147 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/vmtx.c @@ -0,0 +1,93 @@ +/* vmtx.c -- Vertical Metrics Table + * Copyright (C) 1997 Li-Da Lho, All right reserved + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include "ttf.h" +#include "ttfutil.h" + +/* $Id: vmtx.c,v 1.1.1.1 1998/06/05 07:47:52 robert Exp $ */ + +static void ttfLoadVMTX(FILE *fp,VMTXPtr vmtx,ULONG offset); + +/* Caution: Because of interdependency between tables, + * table vhea and maxp should be well initalized before + * ttfInitVMTX has been called + */ +void ttfInitVMTX(TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('v', 'm', 't', 'x'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) + { + font->vmtx = XCALLOC1 (VMTX); + font->vmtx->numOfLongVerMetrics = + font->vhea->numOfLongVerMetrics; + font->vmtx->numOfTSB = font->maxp->numGlyphs - + font->vhea->numOfLongVerMetrics; + ttfLoadVMTX(font->fp,font->vmtx,ptd->offset); + } +} + +static void ttfLoadVMTX(FILE *fp,VMTXPtr vmtx,ULONG offset) +{ + USHORT i,n = vmtx->numOfLongVerMetrics,m=vmtx->numOfTSB; + + xfseek(fp, offset, SEEK_SET, "ttfLoadVMTX"); + + vmtx->vMetrics = XCALLOC (n, longVerMetric); + for (i=0;i<n;i++) + { + (vmtx->vMetrics+i)->advanceHeight = ttfGetuFWord(fp); + (vmtx->vMetrics+i)->topSideBearing = ttfGetFWord(fp); + } + + /* codes dealing with topSideBearing entry */ + if (m) + { + vmtx->topSideBearing = XCALLOC (m, FWord); + for (i=0;i<m;i++) + { + (vmtx->topSideBearing)[i] = ttfGetFWord(fp); + } + } +} + +void ttfPrintVMTX(FILE *fp,VMTXPtr vmtx) +{ + int i; + + fprintf(fp,"'vmtx' Table - Vertical Metrics\n"); + fprintf(fp,"---------------------------------\n"); + + for (i=0;i<vmtx->numOfLongVerMetrics;i++) + { + fprintf(fp,"\t %4d. advWid: %4d, TSBear: %4d\n",i, + (vmtx->vMetrics+i)->advanceHeight, + (vmtx->vMetrics+i)->topSideBearing); + } + + for (i=0;i<vmtx->numOfTSB;i++) + { + fprintf(fp,"\t %4d. TSBear: %4d\n",i+vmtx->numOfLongVerMetrics, + (vmtx->topSideBearing)[i]); + } +} + +void ttfFreeVMTX(VMTXPtr vmtx) +{ + if (vmtx != NULL) + { + free(vmtx->vMetrics); + + if (vmtx->numOfTSB) + free(vmtx->topSideBearing); + + free(vmtx); + } +} |