diff options
Diffstat (limited to 'pdf/pdf_fontTT.c')
-rw-r--r-- | pdf/pdf_fontTT.c | 311 |
1 files changed, 226 insertions, 85 deletions
diff --git a/pdf/pdf_fontTT.c b/pdf/pdf_fontTT.c index aec3ee7b..d7d43e62 100644 --- a/pdf/pdf_fontTT.c +++ b/pdf/pdf_fontTT.c @@ -44,12 +44,12 @@ pdfi_ttf_string_proc(gs_font_type42 * pfont, ulong offset, uint length, const by pdf_font_truetype *ttfont = (pdf_font_truetype *)pfont->client_data; int code = 0; - if ((uint64_t)offset + length > ttfont->sfnt.size) { + if ((uint64_t)offset + length > ttfont->sfnt->length) { *pdata = NULL; code = gs_note_error(gs_error_invalidfont); } else { - *pdata = ttfont->sfnt.data + offset; + *pdata = ttfont->sfnt->data + offset; } return code; } @@ -356,11 +356,10 @@ static int pdfi_set_type42_data_procs(gs_font_type42 *pfont) int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, byte *buf, int64_t buflen, int findex, pdf_font **ppdffont) { pdf_font_truetype *font = NULL; - int code = 0, num_chars = 0, i; + int code = 0, i; pdf_obj *fontdesc = NULL; pdf_obj *obj = NULL; pdf_obj *basefont = NULL; - double f; int64_t descflags; bool encoding_known = false; bool forced_symbolic = false; @@ -371,96 +370,71 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str *ppdffont = NULL; - code = pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); - if (code <= 0) { - code = gs_note_error(gs_error_invalidfont); - goto error; - } + if (font_dict != NULL) + (void)pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); if ((code = pdfi_alloc_tt_font(ctx, &font, false)) < 0) { code = gs_note_error(gs_error_invalidfont); goto error; } - font->object_num = font_dict->object_num; - font->generation_num = font_dict->generation_num; - font->indirect_num = font_dict->indirect_num; - font->indirect_gen = font_dict->indirect_gen; + if (font_dict != NULL) { + font->object_num = font_dict->object_num; + font->generation_num = font_dict->generation_num; + font->indirect_num = font_dict->indirect_num; + font->indirect_gen = font_dict->indirect_gen; + } font->FontDescriptor = (pdf_dict *)fontdesc; fontdesc = NULL; - code = pdfi_dict_get_number(ctx, font_dict, "FirstChar", &f); + pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)font); + + code = pdfi_object_alloc(ctx, PDF_BUFFER, 0, (pdf_obj **)&font->sfnt); if (code < 0) { goto error; } - font->FirstChar = (int)f; - - code = pdfi_dict_get_number(ctx, font_dict, "LastChar", &f); + pdfi_countup(font->sfnt); + code = pdfi_buffer_set_data((pdf_obj *)font->sfnt, buf, buflen); if (code < 0) { goto error; } - font->LastChar = (int)f; - - num_chars = font->LastChar - font->FirstChar + 1; - - font->sfnt.data = buf; - font->sfnt.size = buflen; buf = NULL; /* Strictly speaking BaseFont is required, but we can continue without one */ - code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, (pdf_obj **)&basefont); - if (code > 0) { - pdf_name *nobj = (pdf_name *)basefont; - int nlen = nobj->length > gs_font_name_max ? gs_font_name_max : nobj->length; - - memcpy(font->pfont->key_name.chars, nobj->data, nlen); - font->pfont->key_name.chars[nlen] = 0; - font->pfont->key_name.size = nlen; - memcpy(font->pfont->font_name.chars, nobj->data, nlen); - font->pfont->font_name.chars[nlen] = 0; - font->pfont->font_name.size = nlen; - pdfi_countdown(obj); - obj = NULL; + if (font_dict != NULL) { + code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, (pdf_obj **)&basefont); + if (code > 0) { + pdf_name *nobj = (pdf_name *)basefont; + int nlen = nobj->length > gs_font_name_max ? gs_font_name_max : nobj->length; + + memcpy(font->pfont->key_name.chars, nobj->data, nlen); + font->pfont->key_name.chars[nlen] = 0; + font->pfont->key_name.size = nlen; + memcpy(font->pfont->font_name.chars, nobj->data, nlen); + font->pfont->font_name.chars[nlen] = 0; + font->pfont->font_name.size = nlen; + pdfi_countdown(obj); + obj = NULL; + } } font->BaseFont = basefont; basefont = NULL; font->PDF_font = font_dict; pdfi_countup(font_dict); - code = pdfi_dict_knownget_type(ctx, font_dict, "Widths", PDF_ARRAY, (pdf_obj **)&obj); - if (code < 0) - goto error; - if (code > 0) { - if (num_chars != pdfi_array_size((pdf_array *)obj)) { - code = gs_note_error(gs_error_rangecheck); - goto error; - } - - font->Widths = (double *)gs_alloc_bytes(ctx->memory, sizeof(double) * num_chars, "truetype font Widths array"); - if (font->Widths == NULL) { - code = gs_note_error(gs_error_VMerror); - goto error; - } - memset(font->Widths, 0x00, sizeof(double) * num_chars); - for (i = 0; i < num_chars; i++) { - code = pdfi_array_get_number(ctx, (pdf_array *)obj, (uint64_t)i, &font->Widths[i]); - if (code < 0) - goto error; - font->Widths[i] /= 1000; - } - } - pdfi_countdown(obj); - obj = NULL; + /* ignore errors with widths... for now */ + if (font_dict != NULL) + (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)font, 0.001); - if (ctx->args.ignoretounicode != true) { + if (ctx->args.ignoretounicode != true && font_dict != NULL) { code = pdfi_dict_get(ctx, font_dict, "ToUnicode", (pdf_obj **)&tounicode); - if (code >= 0 && tounicode->type == PDF_STREAM) { + if (code >= 0 && pdfi_type_of(tounicode) == PDF_STREAM) { pdf_cmap *tu = NULL; code = pdfi_read_cmap(ctx, tounicode, &tu); pdfi_countdown(tounicode); tounicode = (pdf_obj *)tu; } - if (code < 0 || (tounicode != NULL && tounicode->type != PDF_CMAP)) { + if (code < 0 || (tounicode != NULL && pdfi_type_of(tounicode) != PDF_CMAP)) { pdfi_countdown(tounicode); tounicode = NULL; code = 0; @@ -472,11 +446,20 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str font->ToUnicode = tounicode; tounicode = NULL; - code = pdfi_dict_get_int(ctx, font->FontDescriptor, "Flags", &descflags); - if (code < 0) + if (font->FontDescriptor != NULL) { + code = pdfi_dict_get_int(ctx, font->FontDescriptor, "Flags", &descflags); + if (code < 0) + descflags = 0; + } + else { descflags = 0; + } + + if (font_dict != NULL) + code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj); + else + code = gs_error_undefined; - code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj); if (code < 0) { static const char encstr[] = "WinAnsiEncoding"; code = pdfi_name_alloc(ctx, (byte *)encstr, strlen(encstr), (pdf_obj **)&obj); @@ -508,13 +491,6 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str pdfi_countdown(obj); obj = NULL; - font->fake_glyph_names = (gs_string *)gs_alloc_bytes(OBJ_MEMORY(font), font->LastChar * sizeof(gs_string), "pdfi_read_truetype_font: fake_glyph_names"); - if (!font->fake_glyph_names) { - code = gs_note_error(gs_error_VMerror); - goto error; - } - memset(font->fake_glyph_names, 0x00, font->LastChar * sizeof(gs_string)); - code = gs_type42_font_init((gs_font_type42 *)font->pfont, 0); if (code < 0) { goto error; @@ -565,7 +541,9 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str font->descflags = descflags; } else if (encoding_known == true) { - static const char encstr[] = "WinAnsiEncoding"; + static const char mrencstr[] = "MacRomanEncoding"; + static const char waencstr[] = "WinAnsiEncoding"; + const char *encstr = ((cmaps_available & CMAP_TABLE_31_PRESENT) == CMAP_TABLE_31_PRESENT) ? waencstr : mrencstr; font->descflags = descflags & ~4; code = pdfi_name_alloc(ctx, (byte *)encstr, strlen(encstr), (pdf_obj **)&obj); if (code >= 0) @@ -586,12 +564,30 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str font->descflags = descflags; } + if (uid_is_XUID(&font->pfont->UID)) + uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); + uid_set_invalid(&font->pfont->UID); + + code = pdfi_font_generate_pseudo_XUID(ctx, font_dict, font->pfont); + if (code < 0) { + goto error; + } + + if ((font->descflags & 4) == 0) { + /* Horrid hacky solution */ + /* We don't want to draw the TTF notdef */ + gs_font_type42 *gst42 = ((gs_font_type42 *)font->pfont); + if (gst42->data.len_glyphs != NULL && gst42->data.len_glyphs[0] > 10) { + gst42->data.len_glyphs[0] = 0; + } + } + code = gs_definefont(ctx->font_dir, (gs_font *)font->pfont); if (code < 0) { goto error; } - code = pdfi_fapi_passfont((pdf_font *)font, 0, NULL, NULL, font->sfnt.data, font->sfnt.size); + code = pdfi_fapi_passfont((pdf_font *)font, 0, NULL, NULL, font->sfnt->data, font->sfnt->length); if (code < 0) { goto error; } @@ -613,30 +609,175 @@ error: return code; } +int +pdfi_copy_truetype_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont) +{ + int code = 0; + pdf_font_truetype *font = NULL; + gs_font_type42 *spfont1 = (gs_font_type42 *) spdffont->pfont; + gs_font_type42 *dpfont42; + gs_id t_id; + pdf_obj *tmp; + + if (font_dict == NULL) + return_error(gs_error_invalidfont); + + code = pdfi_alloc_tt_font(ctx, &font, font_dict->object_num); + if (code < 0) + return code; + dpfont42 = (gs_font_type42 *) font->pfont; + + t_id = dpfont42->id; + memcpy(dpfont42, spfont1, sizeof(gs_font_type42)); + dpfont42->id = t_id; + dpfont42->FAPI = NULL; + dpfont42->FAPI_font_data = NULL; + dpfont42->notify_list.memory = NULL; + dpfont42->notify_list.first = NULL; + gs_notify_init(&dpfont42->notify_list, dpfont42->memory); + + memcpy(font, spdffont, sizeof(pdf_font_truetype)); + font->refcnt = 1; + font->filename = NULL; + + font->pfont = (gs_font_base *)dpfont42; + dpfont42->client_data = (void *)font; + + font->PDF_font = font_dict; + font->object_num = font_dict->object_num; + font->generation_num = font_dict->generation_num; + pdfi_countup(font->PDF_font); + + /* We want basefont and descriptor, but we can live without them */ + font->BaseFont = NULL; + (void)pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &font->BaseFont); + font->FontDescriptor = NULL; + (void)pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, (pdf_obj **)&font->FontDescriptor); + + pdfi_countup(font->sfnt); + + if (font->BaseFont != NULL && ((pdf_name *)font->BaseFont)->length <= gs_font_name_max) { + memcpy(dpfont42->key_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont42->key_name.size = ((pdf_name *)font->BaseFont)->length; + memcpy(dpfont42->font_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont42->font_name.size = ((pdf_name *)font->BaseFont)->length; + } + + font->Encoding = NULL; + font->ToUnicode = NULL; + font->Widths = NULL; + + pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)font); + (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)font, (double)0.001); + + font->descflags = 0; + if (font->FontDescriptor != NULL) { + code = pdfi_dict_get_int(ctx, font->FontDescriptor, "Flags", &font->descflags); + if (code >= 0) { + /* If both the symbolic and non-symbolic flag are set, + believe that latter. + */ + if ((font->descflags & 32) != 0) + font->descflags = (font->descflags & ~4); + } + } + + tmp = NULL; + code = pdfi_dict_knownget(ctx, font_dict, "Encoding", &tmp); + if (code == 1) { + if ((pdfi_type_of(tmp) == PDF_NAME || pdfi_type_of(tmp) == PDF_DICT) && (font->descflags & 4) == 0) { + code = pdfi_create_Encoding(ctx, tmp, NULL, (pdf_obj **) & font->Encoding); + } + else if (pdfi_type_of(tmp) == PDF_DICT && (font->descflags & 4) != 0) { + code = pdfi_create_Encoding(ctx, tmp, (pdf_obj *)spdffont->Encoding, (pdf_obj **) &font->Encoding); + } + pdfi_countdown(tmp); + tmp = NULL; + } + else { + pdfi_countdown(tmp); + tmp = NULL; + code = 0; + } + if (code < 0) { + goto error; + } + + /* Since various aspects of the font may differ (widths, encoding, etc) + we cannot reliably use the UniqueID/XUID for copied fonts. + */ + if (uid_is_XUID(&font->pfont->UID)) + uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); + uid_set_invalid(&font->pfont->UID); + + code = pdfi_font_generate_pseudo_XUID(ctx, font_dict, font->pfont); + if (code < 0) { + goto error; + } + + if (code <= 0) { + font->Encoding = spdffont->Encoding; + pdfi_countup(font->Encoding); + } + + if (ctx->args.ignoretounicode != true) { + code = pdfi_dict_get(ctx, font_dict, "ToUnicode", (pdf_obj **)&tmp); + if (code >= 0 && pdfi_type_of(tmp) == PDF_STREAM) { + pdf_cmap *tu = NULL; + code = pdfi_read_cmap(ctx, tmp, &tu); + pdfi_countdown(tmp); + tmp = (pdf_obj *)tu; + } + if (code < 0 || (tmp != NULL && pdfi_type_of(tmp) != PDF_CMAP)) { + pdfi_countdown(tmp); + tmp = NULL; + code = 0; + } + } + else { + tmp = NULL; + } + font->ToUnicode = tmp; + code = gs_definefont(ctx->font_dir, (gs_font *) font->pfont); + if (code < 0) { + goto error; + } + + code = pdfi_fapi_passfont((pdf_font *) font, 0, NULL, NULL, NULL, 0); + if (code < 0) { + goto error; + } + /* object_num can be zero if the dictionary was defined inline */ + if (font->object_num != 0) { + (void)replace_cache_entry(ctx, (pdf_obj *) font); + } + + *tpdffont = (pdf_font *)font; + +error: + if (code < 0) + pdfi_countdown(font); + return code; +} + int pdfi_free_font_truetype(pdf_obj *font) { pdf_font_truetype *ttfont = (pdf_font_truetype *)font; - int i; + if (ttfont->pfont) gs_free_object(OBJ_MEMORY(ttfont), ttfont->pfont, "Free TrueType gs_font"); if (ttfont->Widths) gs_free_object(OBJ_MEMORY(ttfont), ttfont->Widths, "Free TrueType font Widths array"); - if (ttfont->fake_glyph_names != NULL) { - for (i = 0; i < ttfont->LastChar; i++) { - if (ttfont->fake_glyph_names[i].data != NULL) - gs_free_object(OBJ_MEMORY(ttfont), ttfont->fake_glyph_names[i].data, "Free TrueType fake_glyph_name"); - } - } - gs_free_object(OBJ_MEMORY(ttfont), ttfont->fake_glyph_names, "Free TrueType fake_glyph_names"); - gs_free_object(OBJ_MEMORY(ttfont), ttfont->sfnt.data, "Free TrueType font sfnt buffer"); - + pdfi_countdown(ttfont->sfnt); pdfi_countdown(ttfont->FontDescriptor); pdfi_countdown(ttfont->Encoding); pdfi_countdown(ttfont->BaseFont); pdfi_countdown(ttfont->PDF_font); pdfi_countdown(ttfont->ToUnicode); + pdfi_countdown(ttfont->filename); + gs_free_object(OBJ_MEMORY(ttfont), ttfont, "Free TrueType font"); return 0; |