X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fttf.c;h=46190eef9da998ad6d22d4ef99c1472e96e961a1;hp=3774b5056e902076957afb6abdb59a2b75a02ba1;hb=27a1543b139be30ef7e9d2ba21cb067f8ae685c0;hpb=22d7c3136c6dbd0a68ce0c1db8ce22180d5127a3 diff --git a/lib/ttf.c b/lib/ttf.c index 3774b50..46190ee 100644 --- a/lib/ttf.c +++ b/lib/ttf.c @@ -49,13 +49,11 @@ #define TAG_NAME 0x6e616d65 #define TAG_POST 0x706f7374 #define TAG_CFF 0x43464620 //required for opentype +#define TAG_CVT 0x63767420 +#define TAG_FPGM 0x6670676d +#define TAG_GASP 0x67617370 +#define TAG_PREP 0x70726570 -/* TODO: - fpgm - assembly instructions - prep - assembly instructions - cvt - constant value table - gasp - gridfitting procedure -*/ static U32 checksum_block(U8*_data, int len) { @@ -405,8 +403,8 @@ static table_os2_t*os2_new(ttf_t*ttf) os2->ySuperscriptYOffset = (ttf->head->ymax - ttf->head->ymin)/2; os2->yStrikeoutSize = ttf->head->units_per_em / 10; os2->yStrikeoutPosition = ymid; - os2->usWinAscent = ttf->head->ymax; - os2->usWinDescent = ttf->head->ymin<0?0:ttf->head->ymin; + os2->usWinAscent = ttf->ascent; + os2->usWinDescent = -ttf->descent; os2->sxHeight = ymid; os2->sCapHeight = height*2/3; } @@ -736,7 +734,7 @@ static table_hea_t*hea_new(ttf_t*ttf) if(width > hea->xMaxExtent) hea->xMaxExtent = width; } - /* TODO: caret */ + hea->caretSlopeRise = 1; } return hea; } @@ -1512,34 +1510,34 @@ void name_parse(memreader_t*r, ttf_t*ttf) U16 len = readU16(r); U16 offset_2 = readU16(r); + char ** read_name = 0; + INIT_READ(ss, r->mem, r->size, offset+offset_2); if(!(platform==0 || (platform==1 && encoding==0))) continue; INIT_READ(s, r->mem, r->size, offset+offset_2); - if(name_id==1) { - if(ttf->family_name) free(ttf->family_name); - ttf->family_name = readString(&s, len); - } - if(name_id==2) { - if(ttf->subfamily_name) free(ttf->subfamily_name); - ttf->subfamily_name = readString(&s, len); - } - if(name_id==3) { - if(ttf->version_string) free(ttf->version_string); - ttf->version_string = readString(&s, len); + switch (name_id) { + case 1: read_name = &ttf->family_name; break; + case 2: read_name = &ttf->subfamily_name; break; + case 3: read_name = &ttf->font_uid; break; + case 4: read_name = &ttf->full_name; break; + case 5: read_name = &ttf->version_string; break; + case 6: read_name = &ttf->postscript_name; break; + default: read_name = 0; } - if(name_id==4) { - if(ttf->full_name) free(ttf->full_name); - ttf->full_name = readString(&s, len); + + if (read_name) { + if (*read_name) free(*read_name); + *read_name = readString(&s, len); } } } void name_write(ttf_t*ttf, ttf_table_t*table) { - char*strings[4] = {ttf->family_name, ttf->subfamily_name, ttf->version_string, ttf->full_name}; - int codes[4] = {1,2,3,4}; + char*strings[6] = {ttf->family_name, ttf->subfamily_name, ttf->font_uid, ttf->full_name, ttf->version_string, ttf->postscript_name}; + int codes[6] = {1,2,3,4,5,6}; writeU16(table, 0); //format int count = 0; @@ -1620,6 +1618,14 @@ void name_delete(ttf_t*ttf) free(ttf->version_string); ttf->version_string=0; } + if(ttf->font_uid) { + free(ttf->font_uid); + ttf->font_uid=0; + } + if(ttf->postscript_name) { + free(ttf->postscript_name); + ttf->postscript_name=0; + } } static table_post_t*post_new(ttf_t*ttf) @@ -1661,6 +1667,128 @@ void post_delete(ttf_t*ttf) } } +void cvt_parse(memreader_t*r, ttf_t*ttf) +{ + table_cvt_t*cvt = ttf->cvt = rfx_calloc(sizeof(table_cvt_t)); + cvt->num = r->size/2; + cvt->values = malloc(cvt->num*sizeof(S16)); + int t; + for(t=0;tnum;t++) { + cvt->values[t] = readS16(r); + } +} +void cvt_write(ttf_t*ttf, ttf_table_t*table) +{ + table_cvt_t*cvt = ttf->cvt; + int t; + for(t=0;tnum;t++) { + writeS16(table, cvt->values[t]); + } +} +void cvt_delete(ttf_t*ttf) +{ + if(ttf->cvt) { + if(ttf->cvt->values) + free(ttf->cvt->values); + free(ttf->cvt); + ttf->cvt = 0; + } +} + +static table_gasp_t*gasp_new(ttf_t*ttf) +{ + table_gasp_t*gasp = rfx_calloc(sizeof(table_gasp_t)); + gasp->num = 1; + gasp->records = rfx_calloc(sizeof(gasp->records[0])*gasp->num); + + gasp->records[0].size = 65535; + gasp->records[0].behaviour = 15; //gridfit+grayscale rendering + return gasp; +} +void gasp_parse(memreader_t*r, ttf_t*ttf) +{ + table_gasp_t*gasp = ttf->gasp = rfx_calloc(sizeof(table_gasp_t)); + readU16(r); //version + int num = readU16(r); + int t; + if(!num) return; + gasp->records = malloc(sizeof(gasp->records[0])*num); + for(t=0;trecords[t].size = readU16(r); + gasp->records[t].behaviour = readU16(r); + } +} +void gasp_write(ttf_t*ttf, ttf_table_t*table) +{ + table_gasp_t*gasp = ttf->gasp; + writeU16(table, 0); + writeU16(table, gasp->num); + int t; + for(t=0;tnum;t++) { + writeU16(table, gasp->records[t].size); + writeU16(table, gasp->records[t].behaviour); + } +} +void gasp_delete(ttf_t*ttf) +{ + if(ttf->gasp) { + if(ttf->gasp->records) + free(ttf->gasp->records); + free(ttf->gasp); + ttf->gasp = 0; + } +} + +void fpgm_new(ttf_t*ttf) +{ + table_code_t*fpgm = ttf->fpgm = rfx_calloc(sizeof(table_code_t)); +} +void fpgm_parse(memreader_t*r, ttf_t*ttf) +{ + table_code_t*fpgm = ttf->fpgm = rfx_calloc(sizeof(table_code_t)); + if(!r->size) return; + fpgm->size = r->size; + fpgm->code = malloc(r->size); + readBlock(r, fpgm->code, r->size); +} +void fpgm_write(ttf_t*ttf, ttf_table_t*table) +{ + table_code_t*code = ttf->fpgm; + writeBlock(table, code->code, code->size); +} +void fpgm_delete(ttf_t*ttf) +{ + if(ttf->fpgm) { + if(ttf->fpgm->code) + free(ttf->fpgm->code); + free(ttf->fpgm); + ttf->fpgm = 0; + } +} + +void prep_parse(memreader_t*r, ttf_t*ttf) +{ + table_code_t*prep = ttf->prep = rfx_calloc(sizeof(table_code_t)); + if(!r->size) return; + prep->size = r->size; + prep->code = malloc(r->size); + readBlock(r, prep->code, r->size); +} +void prep_write(ttf_t*ttf, ttf_table_t*table) +{ + table_code_t*code = ttf->prep; + writeBlock(table, code->code, code->size); +} +void prep_delete(ttf_t*ttf) +{ + if(ttf->prep) { + if(ttf->prep->code) + free(ttf->prep->code); + free(ttf->prep); + ttf->prep = 0; + } +} + static int ttf_parse_tables(ttf_t*ttf) { ttf_table_t*table; @@ -1762,6 +1890,34 @@ static int ttf_parse_tables(ttf_t*ttf) ttf_table_delete(ttf, table); } + table = ttf_find_table(ttf, TAG_CVT); + if(table) { + INIT_READ(m, table->data, table->len, 0); + cvt_parse(&m, ttf); + ttf_table_delete(ttf, table); + } + + table = ttf_find_table(ttf, TAG_GASP); + if(table) { + INIT_READ(m, table->data, table->len, 0); + gasp_parse(&m, ttf); + ttf_table_delete(ttf, table); + } + + table = ttf_find_table(ttf, TAG_PREP); + if(table) { + INIT_READ(m, table->data, table->len, 0); + prep_parse(&m, ttf); + ttf_table_delete(ttf, table); + } + + table = ttf_find_table(ttf, TAG_FPGM); + if(table) { + INIT_READ(m, table->data, table->len, 0); + fpgm_parse(&m, ttf); + ttf_table_delete(ttf, table); + } + return 1; } static void ttf_collapse_tables(ttf_t*ttf) @@ -1818,7 +1974,7 @@ static void ttf_collapse_tables(ttf_t*ttf) } } - if(ttf->full_name || ttf->family_name || ttf->subfamily_name) { + if(ttf->full_name || ttf->family_name || ttf->subfamily_name || ttf->font_uid || ttf->postscript_name) { table = ttf_addtable(ttf, TAG_NAME); name_write(ttf, table); name_delete(ttf); @@ -1828,6 +1984,16 @@ static void ttf_collapse_tables(ttf_t*ttf) post_write(ttf, table); post_delete(ttf); } + if(ttf->cvt) { + table = ttf_addtable(ttf, TAG_CVT); + cvt_write(ttf, table); + cvt_delete(ttf); + } + if(ttf->gasp) { + table = ttf_addtable(ttf, TAG_GASP); + gasp_write(ttf, table); + gasp_delete(ttf); + } table = ttf_addtable(ttf, TAG_HEAD); head_write(ttf, table, loca_size); @@ -1951,6 +2117,11 @@ ttf_t* ttf_load(void*data, int length) U32 checksum = table_data[t*4+1]; U32 pos = table_data[t*4+2]; U32 len = table_data[t*4+3]; + + printf("TTF Table %02x%02x%02x%02x %c%c%c%c\n", + (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, + (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff + ); if(pos+len > length) { msg(" TTF Table %02x%02x%02x%02x outside of stream (pos %d)", (tag>>24)&0xff, (tag>>16)&0xff, (tag>>8)&0xff, (tag)&0xff, pos); @@ -1992,6 +2163,10 @@ void ttf_create_truetype_tables(ttf_t*ttf) ttf->os2 = os2_new(ttf); if(!ttf->post) ttf->post = post_new(ttf); + if(!ttf->gasp) + ttf->gasp = gasp_new(ttf); + if(!ttf->fpgm) + ttf->fpgm = fpgm_new(ttf); } ttf_table_t* ttf_write(ttf_t*ttf, U32*checksum_adjust) @@ -2100,42 +2275,24 @@ ttf_table_t* ttf_eot_head(ttf_t*ttf) writeU32(file, 0); //reserved[3] writeU16(file, 0); //padding(1) - int t,len; + int i,t,len; - //family name - len = strlen(ttf->family_name); - writeU16_LE(file, len*2); - for(t=0;tfamily_name[t]); - } - writeU16(file, 0); //zero byte pad + char* strings[] = {ttf->family_name, ttf->subfamily_name, ttf->version_string, ttf->full_name}; + int nr = sizeof(strings)/sizeof(strings[0]); - //subfamily name - len = strlen(ttf->subfamily_name); - writeU16_LE(file, len*2); - for(t=0;tsubfamily_name[t]); - } - writeU16(file, 0); //zero byte pad + for(i=0;iversion_string); - writeU16_LE(file, len*2); //len - for(t=0;tversion_string[t]); + //family name + len = strlen(string); + writeU16_LE(file, len*2); + for(t=0;tfull_name); - writeU16_LE(file, len*2); //len - for(t=0;tfull_name[t]); - } writeU16(file, 0); //zero byte pad writeU16(file, 0); //padding(2) @@ -2236,6 +2393,7 @@ void ttf_destroy(ttf_t*ttf) hea_delete(ttf); glyf_delete(ttf); post_delete(ttf); + cvt_delete(ttf); name_delete(ttf); free(ttf); } @@ -2261,6 +2419,8 @@ int main(int argn, const char*argv[]) ttf->family_name = strdup("Test"); ttf->subfamily_name = strdup("Normal"); ttf->version_string = strdup("Version 1.0"); + ttf->font_uid = strdup("omguid"); + ttf->postscript_name = strdup("Test-psname"); if(!ttf) return 1; memfile_close(m);