summaryrefslogtreecommitdiff
path: root/fonttools
diff options
context:
space:
mode:
authorpfaedit <pfaedit>2006-08-04 21:24:31 +0000
committerpfaedit <pfaedit>2006-08-04 21:24:31 +0000
commit4f95451f8939eae15878e1497ab530e3b842a22e (patch)
treea364533e1d2c330bebb5b73404048ea27bc75e4d /fonttools
parentd276ce861bfc2d017c777e82e753fed1ed513d84 (diff)
Try to keep track of font creation and modification times. NOTE: This is different from file times (which is what appears to be stored in the 'head' table of an sfnt file). Add a new table 'FFTM' to our sfnt output with these timestamps (and the timestamp of fontforge itself, just in case we ever care).
Diffstat (limited to 'fonttools')
-rw-r--r--fonttools/showttf.c159
1 files changed, 156 insertions, 3 deletions
diff --git a/fonttools/showttf.c b/fonttools/showttf.c
index ddad06a8..3f8d3310 100644
--- a/fonttools/showttf.c
+++ b/fonttools/showttf.c
@@ -3,6 +3,7 @@
#else
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
typedef unsigned int uint32;
typedef int int32;
typedef short int16;
@@ -129,6 +130,9 @@ struct ttfinfo {
int prep_length;
int prop_start;
+ /* head */
+ int fftm_start;
+
unsigned int *glyph_unicode;
char **glyph_names;
struct dup *dups;
@@ -310,6 +314,9 @@ exit ( 1 );
info->cvt_start = offset;
info->cvt_length = length;
break;
+ case CHR('F','F','T','M'):
+ info->fftm_start = offset;
+ break;
case CHR('f','p','g','m'):
info->fpgm_start = offset;
info->fpgm_length = length;
@@ -441,8 +448,68 @@ exit ( 1 );
return( true );
}
+static time_t readdate(FILE *ttf) {
+ int date[4], date1970[4], year[2];
+ int i;
+ /* Dates in sfnt files are seconds since 1904. I adjust to unix time */
+ /* seconds since 1970 by figuring out how many seconds were in between */
+
+ date[3] = getushort(ttf);
+ date[2] = getushort(ttf);
+ date[1] = getushort(ttf);
+ date[0] = getushort(ttf);
+ memset(date1970,0,sizeof(date1970));
+ year[0] = (60*60*24*365L)&0xffff;
+ year[1] = (60*60*24*365L)>>16;
+ for ( i=1904; i<1970; ++i ) {
+ date1970[0] += year[0];
+ date1970[1] += year[1];
+ if ( (i&3)==0 && (i%100!=0 || i%400==0))
+ date1970[0] += 24*60*60L; /* Leap year */
+ date1970[1] += (date1970[0]>>16);
+ date1970[0] &= 0xffff;
+ date1970[2] += date1970[1]>>16;
+ date1970[1] &= 0xffff;
+ date1970[3] += date1970[2]>>16;
+ date1970[2] &= 0xffff;
+ }
+
+ for ( i=0; i<3; ++i ) {
+ date[i] -= date1970[i];
+ date[i+1] += date[i]>>16;
+ date[i] &= 0xffff;
+ }
+ date[3] -= date1970[3];
+return( (date[1]<<16) | date[0] );
+}
+
+static void readttfFFTM(FILE *ttf, FILE *util, struct ttfinfo *info) {
+ time_t unix_date;
+ struct tm *tm;
+ static const char *months[] = { "Jan", "Feb", "March", "April", "May",
+ "June", "July", "August", "Sept", "Oct", "Nov", "Dec", NULL };
+
+ fseek(ttf,info->fftm_start,SEEK_SET);
+ printf( "\n\nCreated by FontForge " );
+ if ( getlong(ttf)!=0x00000001 ) {
+ fprintf( stderr, "Unknown version for 'FFTM' table\n" );
+ } else {
+ unix_date = readdate(ttf);
+ tm = localtime(&unix_date);
+ printf( "%d:%02d %02d-%s-%d\n",
+ tm->tm_hour, tm->tm_min, tm->tm_mday, months[tm->tm_mon],
+ tm->tm_year+1900 );
+ unix_date = readdate(ttf);
+ printf( "\tFont created: %s", ctime(&unix_date));
+ unix_date = readdate(ttf);
+ printf( "\tFont modified: %s", ctime(&unix_date));
+ }
+ printf( "\n" );
+}
+
static void readttfhead(FILE *ttf, FILE *util, struct ttfinfo *info) {
int mn, flags, fd;
+ time_t unix_date;
fseek(ttf,info->head_start,SEEK_SET);
printf( "\nHEAD table (at %d)\n", info->head_start );
@@ -461,8 +528,14 @@ static void readttfhead(FILE *ttf, FILE *util, struct ttfinfo *info) {
printf( "\tunitsPerEm=%d\n", getushort(ttf));
printf( "\tcreate[0]=%x\n", getlong(ttf));
printf( "\t create[1]=%x\n", getlong(ttf));
+ fseek(ttf,-8,SEEK_CUR);
+ unix_date = readdate(ttf);
+ printf( "\tFile created: %s", ctime(&unix_date));
printf( "\tmodtime[0]=%x\n", getlong(ttf));
printf( "\t modtime[1]=%x\n", getlong(ttf));
+ fseek(ttf,-8,SEEK_CUR);
+ unix_date = readdate(ttf);
+ printf( "\tFile modified: %s", ctime(&unix_date));
printf( "\txmin=%d\n", (short) getushort(ttf));
printf( "\tymin=%d\n", (short) getushort(ttf));
printf( "\txmax=%d\n", (short) getushort(ttf));
@@ -2256,6 +2329,19 @@ static void readvaluerecord(int vf,FILE *ttf,char *label) {
printf( "\n" );
}
+static void PrintGlyphs(uint16 *glyphs, struct ttfinfo *info) {
+ if ( glyphs==NULL )
+ printf( "<Empty>\n" );
+ else if ( info->glyph_names!=NULL ) {
+ int i;
+ printf( " " );
+ for ( i=0; glyphs[i]!=0xffff; ++i ) {
+ printf( "%s ", info->glyph_names[glyphs[i]]);
+ }
+ printf("\n" );
+ }
+}
+
static void gposPairSubTable(FILE *ttf, int which, int stoffset, struct ttfinfo *info) {
int coverage, cnt, i, subformat, vf1, vf2, j, pair_cnt;
uint16 *glyphs;
@@ -2304,8 +2390,11 @@ static void gposPairSubTable(FILE *ttf, int which, int stoffset, struct ttfinfo
}
}
free(ps_offsets);
- } else {
+ } else if ( subformat==2 ) {
printf( "\t Class based kerning (not displayed)\n" );
+ PrintGlyphs( showCoverageTable(ttf,stoffset+coverage),info);
+ } else {
+ printf( "\t !!! unknown sub-table format !!!!\n" );
}
}
@@ -2515,7 +2604,7 @@ static void gsubChainingContextSubTable(FILE *ttf, int which, int stoffset, stru
}
static void showgpossublookups(FILE *ttf,int lookup_start, struct ttfinfo *info, int gpos ) {
- int i, lu_cnt, lu_type, flags, cnt, j, st;
+ int i, lu_cnt, lu_type, flags, cnt, j, st, is_exten_lu;
uint16 *lu_offsets, *st_offsets;
fseek(ttf,lookup_start,SEEK_SET);
@@ -2543,7 +2632,8 @@ static void showgpossublookups(FILE *ttf,int lookup_start, struct ttfinfo *info,
lu_type==8?"Chained Context positioning":
lu_type==9?"Extension positioning":
"Reserved");
- } else
+ is_exten_lu = lu_type==9;
+ } else {
printf( "\t Type=%d %s\n", lu_type,
lu_type==1?"Single":
lu_type==2?"Multiple":
@@ -2551,7 +2641,11 @@ static void showgpossublookups(FILE *ttf,int lookup_start, struct ttfinfo *info,
lu_type==4?"Ligature":
lu_type==5?"Context":
lu_type==6?"Chaining Context":
+ lu_type==7?"Extension":
+ lu_type==8?"Reverse chaining":
"Reserved");
+ is_exten_lu = lu_type==7;
+ }
printf( "\t Flags=0x%x %s|%s|%s|%s\n", flags,
(flags&0x1)?"RightToLeft":"LeftToRight",
(flags&0x2)?"IgnoreBaseGlyphs":"",
@@ -2564,12 +2658,52 @@ static void showgpossublookups(FILE *ttf,int lookup_start, struct ttfinfo *info,
for ( j=0; j<cnt; ++j ) {
fseek(ttf,st = lookup_start+lu_offsets[i]+st_offsets[j],SEEK_SET);
if ( gpos ) {
+ if ( is_exten_lu ) { /* Extension lookup */
+ int format = getushort(ttf);
+ int subtype = getushort(ttf);
+ int offset = getlong(ttf);
+ printf( "\t (extension format)=%d\n", format );
+ lu_type = subtype;
+ printf( "\t (extension type)=%d %s\n", lu_type,
+ lu_type==1?"Single adjustment":
+ lu_type==2?"Pair adjustment":
+ lu_type==3?"Cursive attachment":
+ lu_type==4?"MarkToBase attachment":
+ lu_type==5?"MarkToLigature attachment":
+ lu_type==6?"MarkToMark attachment":
+ lu_type==7?"Context positioning":
+ lu_type==8?"Chained Context positioning":
+ lu_type==9?"Extension !!! Illegal here !!!":
+ "Reserved");
+ printf( "\t (extension offset)=%d\n", offset );
+ st += offset;
+ fseek(ttf,st,SEEK_SET);
+ }
switch ( lu_type ) {
case 2: gposPairSubTable(ttf,j,st,info); break;
case 4: gposMarkToBaseSubTable(ttf,j,st,info,true); break;
case 6: gposMarkToBaseSubTable(ttf,j,st,info,false); break;
}
} else {
+ if ( is_exten_lu ) { /* Extension lookup */
+ int format = getushort(ttf);
+ int subtype = getushort(ttf);
+ int offset = getlong(ttf);
+ printf( "\t (extension format)=%d\n", format );
+ lu_type = subtype;
+ printf( "\t (extension type)=%d %s\n", lu_type,
+ lu_type==1?"Single":
+ lu_type==2?"Multiple":
+ lu_type==3?"Alternate":
+ lu_type==4?"Ligature":
+ lu_type==5?"Context":
+ lu_type==6?"Chaining Context":
+ lu_type==7?"Extension !!! Illegal here !!!":
+ lu_type==8?"Reverse chaining":
+ "Reserved");
+ st += offset;
+ fseek(ttf,st,SEEK_SET);
+ }
switch ( lu_type ) {
case 1: gsubSingleSubTable(ttf,j,st,info); break;
case 2: gsubMultipleSubTable(ttf,j,st,info); break;
@@ -5795,6 +5929,8 @@ static void readit(FILE *ttf, FILE *util) {
return;
}
+ if ( info.fftm_start!=0 )
+ readttfFFTM(ttf,util,&info);
if ( info.head_start!=0 )
readttfhead(ttf,util,&info);
if ( info.hhea_start!=0 )
@@ -5847,6 +5983,23 @@ return;
readttfapplefvar(ttf,util,&info);
if ( info.gvar_start!=0 )
readttfapplegvar(ttf,util,&info);
+ if ( info.glyphlocations_start!=0 ) {
+ int i, pos;
+ fseek(ttf,info.glyphlocations_start,SEEK_SET);
+ if ( info.index_to_loc_is_long ) {
+ for ( i=0; 4*i<info.loca_length; ++i ) {
+ pos = getlong(ttf);
+ if ( pos&3 )
+ fprintf( stderr, "Not aligned GID=%d, pos=0x%x\n", i, pos);
+ }
+ } else {
+ for ( i=0; 2*i<info.loca_length; ++i ) {
+ pos = getushort(ttf);
+ if ( pos&1 )
+ fprintf( stderr, "Not aligned GID=%d, pos=0x%x\n", i, pos<<1 );
+ }
+ }
+ }
}
int main(int argc, char **argv) {