From a972dbb9bd731a439d009bd51e36981c41a06232 Mon Sep 17 00:00:00 2001 From: scuri Date: Tue, 20 Oct 2009 18:12:26 +0000 Subject: *** empty log message *** --- src/pdflib/font/ft_truetype.c | 287 +++++++++++++++++++++++++++--------------- 1 file changed, 185 insertions(+), 102 deletions(-) (limited to 'src/pdflib/font/ft_truetype.c') diff --git a/src/pdflib/font/ft_truetype.c b/src/pdflib/font/ft_truetype.c index b4e33a6..8aa437c 100644 --- a/src/pdflib/font/ft_truetype.c +++ b/src/pdflib/font/ft_truetype.c @@ -10,7 +10,7 @@ | | *---------------------------------------------------------------------------*/ -/* $Id: ft_truetype.c,v 1.1 2008/10/17 06:10:43 scuri Exp $ +/* $Id: ft_truetype.c,v 1.2 2009/10/20 18:12:26 scuri Exp $ * * FONT TrueType handling routines * @@ -198,14 +198,13 @@ tt_get_offset(tt_file *ttf, tt_byte offsize) static void tt_get_dirent(tt_dirent *dirent, tt_file *ttf) { - tt_read(ttf, dirent->tag, 4); - dirent->tag[4] = 0; + tt_read(ttf, dirent->tag, TT_TABTAG_SIZE); + dirent->tag[TT_TABTAG_SIZE] = 0; dirent->checksum = tt_get_ulong(ttf); dirent->offset = tt_get_ulong(ttf); dirent->length = tt_get_ulong(ttf); } /* tt_get_dirent */ - int tt_tag2idx(tt_file *ttf, char *tag) { @@ -233,6 +232,10 @@ tt_get_tab(tt_file *ttf, char *tag, size_t nbytes, pdc_bool tterror, return NULL; } + pdc_logg_cond(pdc, 3, trc_font, + "\t\treading table \"%s\" (offset=0x%05X, length=%d)\n", + tag, ttf->dir[idx].offset, ttf->dir[idx].length); + tt_seek(ttf, (long) ttf->dir[idx].offset); if (offset) @@ -298,6 +301,28 @@ tt_get_cmap6(tt_file *ttf, tt_cmap0_6 *cm0_6) } /* tt_get_cmap6 */ static void +tt_cleanup_cmap4(tt_file *ttf, tt_cmap4 *cm4) +{ + pdc_core *pdc = ttf->pdc; + + if (cm4 != (tt_cmap4 *) 0) + { + if (cm4->endCount != (tt_ushort *) 0) + pdc_free(pdc, cm4->endCount); + if (cm4->startCount != (tt_ushort *) 0) + pdc_free(pdc, cm4->startCount); + if (cm4->idDelta != (tt_short *) 0) + pdc_free(pdc, cm4->idDelta); + if (cm4->idRangeOffs != (tt_ushort *) 0) + pdc_free(pdc, cm4->idRangeOffs); + if (cm4->glyphIdArray != (tt_ushort *) 0) + pdc_free(pdc, cm4->glyphIdArray); + + pdc_free(pdc, cm4); + } +} + +static tt_cmap4 * tt_get_cmap4(tt_file *ttf, tt_cmap4 *cm4) { static const char *fn = "tt_get_cmap4"; @@ -321,63 +346,57 @@ tt_get_cmap4(tt_file *ttf, tt_cmap4 *cm4) segs = cm4->segCountX2 / 2; - cm4->numGlyphIds = (tt_ushort)( - ((cm4->length - ( 16L + 8L * segs )) & 0xFFFFU) / 2); + if (segs >= 1) + { + cm4->numGlyphIds = (tt_ushort)( + ((cm4->length - ( 16L + 8L * segs )) & 0xFFFFU) / 2); - TT_IOCHECK(ttf, 0 <= cm4->numGlyphIds); + TT_IOCHECK(ttf, 0 <= cm4->numGlyphIds); - cm4->endCount = - (tt_ushort *) - pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); - cm4->startCount = - (tt_ushort *) - pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); - cm4->idDelta = - (tt_short *) - pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); - cm4->idRangeOffs = - (tt_ushort *) - pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); + cm4->endCount = + (tt_ushort *) + pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); + cm4->startCount = + (tt_ushort *) + pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); + cm4->idDelta = + (tt_short *) + pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); + cm4->idRangeOffs = + (tt_ushort *) + pdc_malloc(pdc, (size_t) (sizeof (tt_ushort) * segs), fn); - if (cm4->numGlyphIds) - { - cm4->glyphIdArray = (tt_ushort *) - pdc_malloc(pdc, - (size_t) (sizeof (tt_ushort) * cm4->numGlyphIds), fn); - } + if (cm4->numGlyphIds) + { + cm4->glyphIdArray = (tt_ushort *) + pdc_malloc(pdc, + (size_t) (sizeof (tt_ushort) * cm4->numGlyphIds), fn); + } - for (i = 0; i < segs; ++i) - cm4->endCount[i] = tt_get_ushort(ttf); + for (i = 0; i < segs; ++i) + cm4->endCount[i] = tt_get_ushort(ttf); - TT_IOCHECK(ttf, cm4->endCount[segs - 1] == 0xFFFF); + TT_IOCHECK(ttf, cm4->endCount[segs - 1] == 0xFFFF); - (void) tt_get_ushort(ttf); /* padding */ - for (i = 0; i < segs; ++i) cm4->startCount[i] = tt_get_ushort(ttf); - for (i = 0; i < segs; ++i) cm4->idDelta[i] = tt_get_short(ttf); - for (i = 0; i < segs; ++i) cm4->idRangeOffs[i] = tt_get_ushort(ttf); + (void) tt_get_ushort(ttf); /* padding */ + for (i = 0; i < segs; ++i) cm4->startCount[i] = tt_get_ushort(ttf); + for (i = 0; i < segs; ++i) cm4->idDelta[i] = tt_get_short(ttf); + for (i = 0; i < segs; ++i) cm4->idRangeOffs[i] = tt_get_ushort(ttf); - for (i = 0; i < cm4->numGlyphIds; ++i) - cm4->glyphIdArray[i] = tt_get_ushort(ttf); + for (i = 0; i < cm4->numGlyphIds; ++i) + cm4->glyphIdArray[i] = tt_get_ushort(ttf); + } /* empty cmap */ - if (segs == 1 && cm4->endCount[0] == cm4->startCount[0]) - { - cm4->segCountX2 = 0; - pdc_free(pdc, cm4->endCount); - cm4->endCount = (tt_ushort *) 0; - pdc_free(pdc, cm4->startCount); - cm4->startCount = (tt_ushort *) 0; - pdc_free(pdc, cm4->idDelta); - cm4->idDelta = (tt_short *) 0; - pdc_free(pdc, cm4->idRangeOffs); - cm4->idRangeOffs = (tt_ushort *) 0; - if (cm4->numGlyphIds) - { - pdc_free(pdc, cm4->glyphIdArray); - cm4->glyphIdArray = (tt_ushort *) 0; - } + if (segs == 0 || (segs == 1 && cm4->endCount[0] == cm4->startCount[0])) + { + tt_cleanup_cmap4(ttf, cm4); + + cm4 = (tt_cmap4 *) 0; } + return cm4; + } /* tt_get_cmap4 */ @@ -452,6 +471,8 @@ tt_get_tab_cmap(tt_file *ttf) pdc_malloc(pdc, sizeof (tt_cmap0_6), fn); tp->mac->format = 0; tt_get_cmap0(ttf, tp->mac); + + offset_mac = offsetEncTab; } else if (tableFormat == 6 && tp->mac == (tt_cmap0_6 *) 0) { @@ -459,53 +480,67 @@ tt_get_tab_cmap(tt_file *ttf) pdc_malloc(pdc, sizeof (tt_cmap0_6), fn); tp->mac->format = 6; tt_get_cmap6(ttf, tp->mac); + + offset_mac = offsetEncTab; } - offset_mac = offsetEncTab; + else if (numEncTabs == 1 && tableFormat == 4) + { + /* simulating Windows */ + tp->win = (tt_cmap4 *) pdc_malloc(pdc, sizeof (tt_cmap4), fn); + tp->win->format = tableFormat; + tp->win->encodingID = encodingID; + tp->win = tt_get_cmap4(ttf, tp->win); + + /* cmap picking not necessary */ + } } /* - * platformID: 0 encodingID: 3 tableFormat: 4 (old mac) - * platformID: 3 encodingID: 0/1 tableFormat: 4 + * platformID: 0 encodingID: 3 tableFormat: 4 (old mac) + * platformID: 3 encodingID: 0/1/4 tableFormat: 4 preferred! */ - else if ((tp->win == (tt_cmap4 *) 0 && tableFormat == 4) && + else if (tableFormat == 4 && ((platformID == tt_pfid_win && (encodingID == tt_wenc_symbol || - encodingID == tt_wenc_text)) || + encodingID == tt_wenc_text || + encodingID == tt_wenc_big5)) || (platformID == tt_pfid_uni && encodingID == tt_wenc_mtext))) { - tp->win = (tt_cmap4 *) pdc_malloc(pdc, sizeof (tt_cmap4), fn); - tp->win->format = tableFormat; - - /* we suppose a windows platform (see old mac hostfont Times) */ - if (encodingID == tt_wenc_mtext) + if (tp->win == (tt_cmap4 *) 0 || + (tp->win != (tt_cmap4 *) 0 && + ((tp->win->encodingID == tt_wenc_mtext || + tp->win->encodingID == tt_wenc_big5) && + encodingID < tt_wenc_mtext))) { - encodingID = tt_wenc_text; - } - - tt_get_cmap4(ttf, tp->win); + if (tp->win != (tt_cmap4 *) 0) + tt_cleanup_cmap4(ttf, tp->win); + tp->win = (tt_cmap4 *) pdc_malloc(pdc, sizeof (tt_cmap4), fn); - if (tp->win->segCountX2) - { + tp->win->format = tableFormat; tp->win->encodingID = encodingID; + tp->win = tt_get_cmap4(ttf, tp->win); + + if (tp->win != (tt_cmap4 *) 0) + offset_win = offsetEncTab; } - else - { - pdc_free(pdc, tp->win); - tp->win = (tt_cmap4 *) 0; - } - offset_win = offsetEncTab; } tt_seek(ttf, pos); } /* for */ + /* we suppose a windows platform (see old mac hostfont Times) */ + if (tp->win && tp->win->encodingID == tt_wenc_mtext) + { + encodingID = tt_wenc_text; + } + /* is symbol font */ ttf->issymbol = (tp->win && tp->win->encodingID == tt_wenc_symbol) ? pdc_true : pdc_false; - /* has Unicode cmap */ + /* has Unicode/CMap cmap */ ttf->haswinuni = (!ttf->issymbol && (tp->win || tp->ucs4)) ? pdc_true : pdc_false; @@ -540,6 +575,7 @@ tt_get_tab_cmap(tt_file *ttf) } else { + ttf->hasbig5cmap = tp->win->encodingID == tt_wenc_big5; tp->encoding = tt_wenc_text; tp->format = tp->win->format; tp->offset = offset_win; @@ -553,12 +589,16 @@ tt_get_tab_cmap(tt_file *ttf) tp->platform, tp->encoding, tp->format, ttf->issymbol ? "symbol" : "text"); + if (ttf->hasbig5cmap) + pdc_logg_cond(ttf->pdc, 1, trc_font, "\t\tCID font with Big5 cmap\n"); + /* for subsetting and symbolic font: * tp->platform = tt_pfid_mac according PDF specification * otherwise GS will emit an error message */ if (ttf->issymbol && offset_mac > 0) { + ttf->forcesubset = !ttf->hasonlymac; tp->platform = tt_pfid_mac; tp->encoding = tt_wenc_symbol; tp->format = tp->mac->format; @@ -600,7 +640,7 @@ tt_get_tab_head(tt_file *ttf) tp->glyphDataFormat = tt_get_short(ttf); } /* tt_get_tab_head */ -static void +void tt_get_tab_hhea(tt_file *ttf) { tt_tab_hhea *tp = NULL; @@ -764,7 +804,6 @@ tt_get_tab_name(tt_file *ttf) tp->englishname4 = NULL; tp->englishname6 = NULL; tp->producer = NULL; - tp->format = tt_get_ushort(ttf); /* Format 0 is the only document one, but some Apple fonts use 65535. @@ -782,6 +821,13 @@ tt_get_tab_name(tt_file *ttf) "\tRecords in name table of format %d: %d:\n", tp->format, tp->numNameRecords); + if (ttf->utf16fontname != NULL) + { + pdc_logg_cond(pdc, 1, trc_font, + "\tSearching for a host font with Unicode name \"%T\"\n", + ttf->utf16fontname, ttf->fnamelen); + } + /* this was observed. we ignore it in TET */ if (ttf->fortet && tp->numNameRecords == 0) return pdc_true; @@ -865,7 +911,7 @@ tt_get_tab_name(tt_file *ttf) if (namerec->length && namerec->namid == namid) { /* TTC font search */ - if (ttf->utf16fontname) + if (ttf->utf16fontname != NULL) { /* read font name */ if (localname == NULL) @@ -925,7 +971,7 @@ tt_get_tab_name(tt_file *ttf) } /* TTC font not found */ - if (ttf->utf16fontname) + if (ttf->utf16fontname != NULL) return pdc_false; /* English font names */ @@ -1018,6 +1064,7 @@ void tt_get_tab_OS_2(tt_file *ttf) { pdc_bool logg3 = pdc_logg_is_enabled(ttf->pdc, 3, trc_font); + pdc_bool logg5 = pdc_logg_is_enabled(ttf->pdc, 5, trc_font); int i, j; tt_tab_OS_2 *tp = NULL; @@ -1077,7 +1124,8 @@ tt_get_tab_OS_2(tt_file *ttf) for (i = 0; i < PDC_NUMCHARCOLL; i++) { j = i + 17; - if (tp->ulCodePageRange1 & (1<ulCodePageRange1 & (1<hasbig5cmap && + tt_cpflag2charcoll[i] == cc_traditional_chinese)) tp->charcolls[i] = tt_cpflag2charcoll[i]; else tp->charcolls[i] = cc_none; @@ -1100,6 +1148,15 @@ tt_get_tab_OS_2(tt_file *ttf) tp->usMaxContext = 0; } + if (logg5) + { + pdc_logg(ttf->pdc, "\t\t\tusFirstCharIndex=0x%04X\n", + ttf->tab_OS_2->usFirstCharIndex); + if (ttf->tab_cmap && ttf->tab_cmap->win) + pdc_logg(ttf->pdc, "\t\t\tstartCount[0]=0x%04X\n", + ttf->tab_cmap->win->startCount[0]); + } + /* there are fonts with inconsistent usFirstCharIndex */ if (ttf->tab_cmap && ttf->tab_cmap->win && tp->usFirstCharIndex != ttf->tab_cmap->win->startCount[0]) @@ -1191,7 +1248,12 @@ tt_get_tab_post(tt_file *ttf) tp->maxMemType42 = tt_get_ulong(ttf); tp->minMemType1 = tt_get_ulong(ttf); tp->maxMemType1 = tt_get_ulong(ttf); + tp->numberOfGlyphs = ttf->numGlyphs; + /* there are subset fonts with different number of glyphs + * see bug #1418 + */ + ttf->numGlyphs = MAX(tp->numberOfGlyphs, ttf->numGlyphs); } /* tt_get_tab_post */ @@ -1279,6 +1341,7 @@ fnt_test_tt_font(pdc_core *pdc, tt_byte *img, tt_ulong *n_fonts, return pdc_true; } + pdc_bool fnt_is_opentype_font(tt_file *ttf) { @@ -1387,22 +1450,43 @@ tt_unicode2gidx(tt_file *ttf, int usv, pdc_bool logg) pdc_core *pdc = ttf->pdc; tt_cmap4 *cm4 = ttf->tab_cmap->win; pdc_ushort uv; - int segs; - int gidx = 0; - int i; + int lo, hi, segs; + int gidx = 0, i = 0; uv = (pdc_ushort) usv; - if (logg) pdc_logg(pdc, "\t\t\tU+%04X: ", uv); + if (logg) pdc_logg(pdc, "\t\t\tUCS2: %04X: ", uv); segs = cm4->segCountX2 / 2; - for (i = 0; i < segs; ++i) + lo = 0; + hi = segs; + while (lo < hi) + { + i = (lo + hi) / 2; + if (uv <= cm4->endCount[i]) - break; + { + if (uv >= cm4->startCount[i]) + { + break; + } + else if (!i || uv > cm4->endCount[i - 1]) + { + i = -1; + break; + } + } + + if (uv < cm4->startCount[i]) + hi = i; + else + lo = i + 1; + } - if (logg) pdc_logg(pdc, "i=%d start=U+%04X ", i, cm4->startCount[i]); + + if (logg) pdc_logg(pdc, "i=%d start=UCS2: %04X ", i, cm4->startCount[i]); TT_IOCHECK(ttf, i != segs); - if (uv < cm4->startCount[i] || uv == 0xFFFF) + if (i == -1 || uv == 0xFFFF) { if (logg) pdc_logg(pdc, "==> gidx=0\n"); return 0; @@ -1478,12 +1562,16 @@ tt_gidx2width(tt_file *ttf, int gidx) void fnt_set_tt_fontvalues(tt_file *ttf) { + pdc_bool logg3 = pdc_logg_is_enabled(ttf->pdc, 3, trc_font); fnt_font *font = ttf->font; fnt_font_metric *ftm = &font->m; if (ttf->onlyCFF) return; + if (logg3) + pdc_logg(ttf->pdc, "\tUnits per EM: %d\n", ttf->tab_head->unitsPerEm); + if (ttf->tab_head) { ftm->llx = FNT_TT2PDF(ttf->tab_head->xMin); @@ -1601,6 +1689,9 @@ fnt_set_tt_fontarrays(tt_file *ttf, int flags) ** like that; perhaps we have to apply similar tricks then... */ uvoffset = (ttf->tab_OS_2->usFirstCharIndex & 0xFF00); + + if (logg5) + pdc_logg(pdc, "\t\tuvoffset=0x%04X\n", uvoffset); } else { @@ -2140,6 +2231,8 @@ fnt_check_tt_font(pdc_core *pdc, const char *filename, const char *fontname, * ttf->verbose = pdc_false; * ttf->kerning = pdc_true; * ttf->vertical = pdc_true; + * ttf->ignorename = pdc_true; + * ttf->cmst = ~NULL; * ttf->fortet = pdc_true; * * ttf->check = pdc_true; @@ -2201,6 +2294,9 @@ fnt_new_tt(pdc_core *pdc, fnt_font *font) ttf->issymbol = pdc_false; ttf->haswinuni = pdc_false; ttf->hasonlymac = pdc_false; + ttf->hasbig5cmap = pdc_false; + ttf->forcesubset = pdc_false; + ttf->gidunequcid = pdc_false; ttf->utf16fontname = (char *) 0; @@ -2214,9 +2310,6 @@ void fnt_delete_tt(tt_file *ttf) { pdc_core *pdc = ttf->pdc; - int i; - - (void) i; if (ttf->check == pdc_false && ttf->fp != (pdc_file *) 0) pdc_fclose(ttf->fp); @@ -2243,24 +2336,14 @@ fnt_delete_tt(tt_file *ttf) if (ttf->tab_cmap != (tt_tab_cmap *) 0) { - if (ttf->tab_cmap->mac != (tt_cmap0_6 *) 0) { + if (ttf->tab_cmap->mac != (tt_cmap0_6 *) 0) + { if (ttf->tab_cmap->mac->glyphIdArray) pdc_free(pdc, ttf->tab_cmap->mac->glyphIdArray); pdc_free(pdc, ttf->tab_cmap->mac); } - if (ttf->tab_cmap->win != (tt_cmap4 *) 0) - { - tt_cmap4 *cm4 = (tt_cmap4 *) ttf->tab_cmap->win; - - if (cm4->endCount != 0) pdc_free(pdc, cm4->endCount); - if (cm4->startCount != 0) pdc_free(pdc, cm4->startCount); - if (cm4->idDelta != 0) pdc_free(pdc, cm4->idDelta); - if (cm4->idRangeOffs != 0) pdc_free(pdc, cm4->idRangeOffs); - if (cm4->glyphIdArray != 0) pdc_free(pdc, cm4->glyphIdArray); - - pdc_free(pdc, cm4); - } + tt_cleanup_cmap4(ttf, ttf->tab_cmap->win); if (ttf->tab_cmap->ucs4 != (tt_cmap12 *) 0) { -- cgit v1.2.3