summaryrefslogtreecommitdiff
path: root/fonttools
diff options
context:
space:
mode:
authorpfaedit <pfaedit>2009-08-18 00:56:08 +0000
committerpfaedit <pfaedit>2009-08-18 00:56:08 +0000
commitd04b0f8169798e9ab6e2c64d9391d7c6cc1aa48f (patch)
tree05cb126080d396a0fec0deef7778d3681bb2b86d /fonttools
parent2e32f628ff202faf90f18f67697da70e98d13d9b (diff)
A little program which will unwrap each font in a ttc file and put it in its own ttf file.
Diffstat (limited to 'fonttools')
-rw-r--r--fonttools/stripttc.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/fonttools/stripttc.c b/fonttools/stripttc.c
new file mode 100644
index 00000000..0dd8e34e
--- /dev/null
+++ b/fonttools/stripttc.c
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* This program takes a ttc file and turns it into its component ttf files */
+/* The makes two changes to the data: */
+/* * The tables are placed a different offsets */
+/* (so the offset fields in the table header are different) */
+/* * the checksumAdjustment field of the 'head' table is set correctly*/
+
+#define CHR(ch1,ch2,ch3,ch4) (((ch1)<<24)|((ch2)<<16)|((ch3)<<8)|(ch4))
+
+static void putshort(FILE *file,int sval) {
+ putc((sval>>8)&0xff,file);
+ putc(sval&0xff,file);
+}
+
+static void putlong(FILE *file,int val) {
+ putc((val>>24)&0xff,file);
+ putc((val>>16)&0xff,file);
+ putc((val>>8)&0xff,file);
+ putc(val&0xff,file);
+}
+
+static int getushort(FILE *ttf) {
+ int ch1 = getc(ttf);
+ int ch2 = getc(ttf);
+ if ( ch2==EOF )
+return( EOF );
+return( (ch1<<8)|ch2 );
+}
+
+static int getlong(FILE *ttf) {
+ int ch1 = getc(ttf);
+ int ch2 = getc(ttf);
+ int ch3 = getc(ttf);
+ int ch4 = getc(ttf);
+ if ( ch4==EOF )
+return( EOF );
+return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
+}
+
+static unsigned int filecheck(FILE *file) {
+ unsigned int sum = 0, chunk;
+
+ rewind(file);
+ while ( 1 ) {
+ chunk = getlong(file);
+ if ( feof(file) || ferror(file))
+ break;
+ sum += chunk;
+ }
+return( sum );
+}
+
+static void copytable(FILE *ttf,FILE *ttc,int offset,int length) {
+ int i, ch;
+
+ fseek(ttc,offset,SEEK_SET);
+ for ( i=0; i<length && (ch=getc(ttc))!=EOF ; ++i )
+ putc(ch,ttf);
+ if ( ch==EOF )
+ fprintf( stderr, "File ended before table\n" );
+ if ( length&1 ) {
+ putc('\0',ttf);
+ ++length;
+ }
+ if ( length & 2 ) {
+ putshort(ttf,0);
+ }
+}
+
+static void handlefont(char *filename,int which,FILE *ttc,int offset) {
+ char outfile[2000], *pt;
+ FILE *ttf;
+ int i, cnt, *offsets, *lengths, head, tag, pos, headpos;
+
+ strcpy(outfile,filename);
+ pt = strrchr(outfile,'.');
+ if ( pt==NULL )
+ pt = outfile + strlen(outfile);
+ sprintf( pt, "_%02d.ttf", which );
+
+ ttf = fopen( outfile,"wb");
+ if ( ttf==NULL ) {
+ fprintf( stderr, "Failed to open %s for output.\n", outfile );
+return;
+ }
+ printf ( "%s ", outfile );
+
+ fseek(ttc,offset,SEEK_SET);
+ putlong(ttf,getlong(ttc)); /* sfnt version */
+ putshort(ttf,cnt = getushort(ttc)); /* table cnt */
+ putshort(ttf,getushort(ttc)); /* binary search header */
+ putshort(ttf,getushort(ttc));
+ putshort(ttf,getushort(ttc));
+
+ offsets = malloc(cnt*sizeof(int));
+ lengths = malloc(cnt*sizeof(int));
+ head = -1;
+ for ( i=0; i<cnt; ++i ) {
+ tag = getlong(ttc);
+ if ( tag==CHR('h','e','a','d'))
+ head = i;
+ putlong(ttf,tag);
+ putlong(ttf,getlong(ttc)); /* checksum */
+ putlong(ttf,offsets[i] = getlong(ttc)); /* Reserve space for offset, will fix later */
+ putlong(ttf,lengths[i] = getlong(ttc));
+ }
+ headpos = -1;
+ for ( i=0; i<cnt; ++i ) {
+ pos = ftell(ttf);
+ copytable(ttf,ttc,offsets[i],lengths[i]);
+ if ( i==head ) {
+ fseek(ttf,pos+8,SEEK_SET);
+ putlong(ttf,0);
+ headpos = pos;
+ }
+ fseek(ttf,12+i*16+8,SEEK_SET);
+ putlong(ttf,pos); /* Fix offset here */
+ fseek(ttf,0,SEEK_END);
+ }
+ if ( headpos!=-1 ) {
+ unsigned int checksum;
+ checksum = filecheck(ttf);
+ checksum = 0xb1b0afba-checksum;
+ fseek(ttf,headpos+2*sizeof(int),SEEK_SET);
+ putlong(ttf,checksum);
+ }
+ fclose(ttf);
+ free(offsets); free(lengths);
+}
+
+static void handlefile(char *filename) {
+ FILE *ttc = fopen(filename,"r");
+ int version, cnt, i;
+ int *offsets;
+
+ if ( ttc==NULL ) {
+ fprintf( stderr, "Could not open %s\n", filename );
+return;
+ }
+
+ version = getlong(ttc);
+ if ( version!=CHR('t','t','c','f')) {
+ fprintf( stderr, "%s does not look like a ttc file, bad version.\n", filename );
+ fclose(ttc);
+return;
+ }
+
+ version = getlong(ttc);
+ if ( version!=0x10000 && version != 0x20000 )
+ fprintf( stderr, "Unexpected ttc version number: %08x\n", version );
+ cnt = getlong(ttc);
+ offsets = malloc(cnt*sizeof(int));
+ for ( i=0; i<cnt; ++i )
+ offsets[i] = getlong(ttc);
+ printf( "%s => ", filename );
+ for ( i=0; i<cnt; ++i )
+ handlefont(filename,i,ttc,offsets[i]);
+ printf( "\n" );
+ fclose(ttc);
+ free(offsets);
+}
+
+int main(int argc, char *argv[]) {
+ int i;
+
+ for ( i=1; i<argc; ++i )
+ handlefile(argv[i]);
+return( 0 );
+}