X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fttf.c;h=28bdee2ab13f2e3ab2aae05cd0c6c3a9b84324d7;hp=c17b6316b1342c22d4304281e93d9ec4af56b78f;hb=219ea5ad983fc389d894c967528b451ea321b8c6;hpb=4c389168a91bf083e434885fbfd8f51c6dab56fc diff --git a/lib/ttf.c b/lib/ttf.c index c17b631..28bdee2 100644 --- a/lib/ttf.c +++ b/lib/ttf.c @@ -24,6 +24,7 @@ #include #include "log.h" #include "os.h" +#include "q.h" #include "mem.h" #include "ttf.h" @@ -268,10 +269,10 @@ static table_head_t*head_new(ttf_t*ttf) head->xmax = ttf->glyphs[0].xmax; head->ymax = ttf->glyphs[0].ymax; for(t=1;tnum_glyphs;t++) { - if(ttf->glyphs[0].xmin < head->xmin) head->xmin = ttf->glyphs[0].xmin; - if(ttf->glyphs[0].ymin < head->ymin) head->ymin = ttf->glyphs[0].ymin; - if(ttf->glyphs[0].xmax > head->xmax) head->xmax = ttf->glyphs[0].xmax; - if(ttf->glyphs[0].ymax > head->ymax) head->ymax = ttf->glyphs[0].ymax; + if(ttf->glyphs[t].xmin < head->xmin) head->xmin = ttf->glyphs[t].xmin; + if(ttf->glyphs[t].ymin < head->ymin) head->ymin = ttf->glyphs[t].ymin; + if(ttf->glyphs[t].xmax > head->xmax) head->xmax = ttf->glyphs[t].xmax; + if(ttf->glyphs[t].ymax > head->ymax) head->ymax = ttf->glyphs[t].ymax; } } head->macStyle = 0; @@ -705,10 +706,10 @@ static table_hea_t*hea_new(ttf_t*ttf) for(t=0;tnum_glyphs;t++) { if(ttf->glyphs[t].advance > hea->advanceWidthMax) hea->advanceWidthMax = ttf->glyphs[t].advance; - if(ttf->glyphs[t].xmin < ttf->hea->minLeftSideBearing) - ttf->hea->minLeftSideBearing = ttf->glyphs[t].xmin; - if(ttf->glyphs[t].xmax < ttf->hea->minRightSideBearing) - ttf->hea->minRightSideBearing = ttf->glyphs[t].xmax; + if(ttf->glyphs[t].xmin < hea->minLeftSideBearing) + hea->minLeftSideBearing = ttf->glyphs[t].xmin; + if(ttf->glyphs[t].xmax < hea->minRightSideBearing) + hea->minRightSideBearing = ttf->glyphs[t].xmax; int width = ttf->glyphs[t].xmax - ttf->glyphs[t].xmin; if(width > hea->xMaxExtent) hea->xMaxExtent = width; @@ -1219,6 +1220,7 @@ void cmap_parse(memreader_t*r, ttf_t*ttf) readU16(r); // version (0) int num_subtables = readU16(r); int t; + char warn=1; if(r->pos+num_subtables*8 > r->size) { msg(" CMap overflow"); num_subtables = (r->size-r->pos)/8; @@ -1276,6 +1278,7 @@ void cmap_parse(memreader_t*r, ttf_t*ttf) INIT_READ(r_delta, t.mem, t.size, t.pos+2+segment_count*4); INIT_READ(r_range, t.mem, t.size, t.pos+2+segment_count*6); int glyphmap_start = t.pos+2+segment_count*8; + int glyphmap_size = t.size - glyphmap_start; int s; for(s=0;sunicode[u] = (u + delta) & 0xffff; } } else { - INIT_READ(g, t.mem, t.size, r_range.pos-2+range); + int pos = r_range.pos-2+range; + if(warn && pos+end-start+1 > t.size) { + msg(" glyphmap index out of bounds (%d-%d/%d)", pos, pos+end-start, t.size); + warn=0; + } + INIT_READ(g, t.mem, t.size, pos); for(u=start;u<=end;u++) { ttf->unicode[u] = readU16(&g); } @@ -1363,6 +1371,8 @@ void cmap_write(ttf_t* ttf, ttf_table_t*w) num_segments++; // account for 0xffff mapping + int glyphmap_start = w->len+2+num_segments*8; + int t; int end_pos = w->len; for(t=0;tlen; for(t=0;tdata[num_segments_pos]=(num_segments*2)>>8; w->data[num_segments_pos+1]=(num_segments*2); - + pos=0; num_segments = 0; while(pos < ttf->unicode_size) { @@ -1393,7 +1403,7 @@ void cmap_write(ttf_t* ttf, ttf_table_t*w) U16 delta = ttf->unicode[pos]-pos; char do_delta=1; for(s=pos+1;s<=end;s++) { - U16 delta2 = ttf->unicode[pos]-pos; + U16 delta2 = ttf->unicode[s]-s; if(delta2!=delta) { do_delta=0; break; @@ -1404,7 +1414,7 @@ void cmap_write(ttf_t* ttf, ttf_table_t*w) range = 0; } else { delta = 0; - range = w->len - range_pos+num_segments*2; + range = w->len - range_pos; for(s=pos;s<=end;s++) { writeU16(w, ttf->unicode[s]); } @@ -1439,6 +1449,92 @@ void cmap_delete(ttf_t*ttf) } ttf->unicode_size=0; } +void name_parse(memreader_t*r, ttf_t*ttf) +{ + U16 format = readU16(r); + U16 count = readU16(r); + U16 offset = readU16(r); + + int t; + for(t=0;tname) + free(ttf->name); + ttf->name = strdup_n(&r->mem[offset+offset_2], len); + } + } +} +void name_write(ttf_t*ttf, ttf_table_t*table) +{ + writeU16(table, 0); //format + writeU16(table, 1); //count + int offset = 18; + writeU16(table, offset); //offset + + writeU16(table, 1); //platform id + writeU16(table, 0); //encoding id + writeU16(table, 0); //language + writeU16(table, 4); //4: full name + int len = strlen(ttf->name); + writeU16(table, len); + writeU16(table, table->len+2 - offset); + int t; + for(t=0;tname[t]); + } +} +void name_delete(ttf_t*ttf) +{ + if(ttf->name) { + free(ttf->name); + ttf->name=0; + } +} + +static table_post_t*post_new(ttf_t*ttf) +{ + table_post_t*post = rfx_calloc(sizeof(table_post_t)); + return post; +} +void post_parse(memreader_t*r, ttf_t*ttf) +{ + table_post_t*post = ttf->post = rfx_calloc(sizeof(table_post_t)); + U16 format = readU16(r); + post->italic_angle = readU16(r); + post->underline_position = readU16(r); + post->underline_thickness = readU16(r); + U16 is_monospaced = readU16(r); + readU16(r); // min mem 42 + readU16(r); + readU16(r); // min mem 1 + readU16(r); +} +void post_write(ttf_t*ttf, ttf_table_t*table) +{ + table_post_t*post = ttf->post; + writeU32(table, 0x00030000); + writeU32(table, post->italic_angle); + writeU16(table, post->underline_position); + writeU16(table, post->underline_thickness); + writeU32(table, 0); //is monospaced TODO + writeU32(table, 0); //min mem 42 + writeU32(table, 0); + writeU32(table, 0); //min mem 1 + writeU32(table, 0); +} +void post_delete(ttf_t*ttf) +{ + if(ttf->post) { + free(ttf->post); + ttf->post = 0; + } +} static int ttf_parse_tables(ttf_t*ttf) { @@ -1525,6 +1621,20 @@ static int ttf_parse_tables(ttf_t*ttf) cmap_parse(&m, ttf); ttf_table_delete(ttf, table); } + + table = ttf_find_table(ttf, TAG_NAME); + if(table) { + INIT_READ(m, table->data, table->len, 0); + name_parse(&m, ttf); + ttf_table_delete(ttf, table); + } + + table = ttf_find_table(ttf, TAG_POST); + if(table) { + INIT_READ(m, table->data, table->len, 0); + post_parse(&m, ttf); + ttf_table_delete(ttf, table); + } return 1; } @@ -1566,6 +1676,17 @@ static void ttf_collapse_tables(ttf_t*ttf) loca_size = loca_write(ttf, table, locations); free(locations); } + + if(ttf->name) { + table = ttf_addtable(ttf, TAG_NAME); + name_write(ttf, table); + name_delete(ttf); + } + if(ttf->post) { + table = ttf_addtable(ttf, TAG_POST); + post_write(ttf, table); + post_delete(ttf); + } table = ttf_addtable(ttf, TAG_HEAD); head_write(ttf, table, loca_size); @@ -1672,6 +1793,8 @@ void ttf_create_truetype_tables(ttf_t*ttf) ttf->hea = hea_new(ttf); if(!ttf->os2) ttf->os2 = os2_new(ttf); + if(!ttf->post) + ttf->post = post_new(ttf); } ttf_table_t* ttf_write(ttf_t*ttf) { @@ -1772,7 +1895,7 @@ void ttf_dump(ttf_t*ttf) maxp_dump(ttf); glyf_dump(ttf); } -void ttf_destroy(ttf_t*ttf) +void ttf_destroy_tables(ttf_t*ttf) { ttf_table_t*table = ttf->tables; while(table) { @@ -1781,11 +1904,22 @@ void ttf_destroy(ttf_t*ttf) free(table); table = next; } + ttf->tables = 0; +} +void ttf_reduce(ttf_t*ttf) +{ + ttf_destroy_tables(ttf); +} +void ttf_destroy(ttf_t*ttf) +{ + ttf_destroy_tables(ttf); maxp_delete(ttf); os2_delete(ttf); head_delete(ttf); hea_delete(ttf); glyf_delete(ttf); + post_delete(ttf); + name_delete(ttf); free(ttf); } @@ -1799,12 +1933,18 @@ int main(int argn, const char*argv[]) //msg(" Loading %s", filename); memfile_t*m = memfile_open(filename); ttf_t*ttf = ttf_load(m->data, m->len); + if(!ttf) { + msg(" Couldn't load %s", filename); + return 1; + } + ttf_reduce(ttf); + ttf->name = strdup("testfont"); if(!ttf) return 1; memfile_close(m); //ttf_dump(ttf); //printf("os2 version: %04x (%d), maxp size: %d\n", // ttf->os2->version, ttf->os2->size, ttf->maxp->size); - ttf_save(ttf, "output.ttf"); + ttf_save(ttf, "testfont.ttf"); ttf_destroy(ttf); return 0;