diff options
Diffstat (limited to 'pdf/pdf_font1.c')
-rw-r--r-- | pdf/pdf_font1.c | 369 |
1 files changed, 258 insertions, 111 deletions
diff --git a/pdf/pdf_font1.c b/pdf/pdf_font1.c index 87ba858b..b350f449 100644 --- a/pdf/pdf_font1.c +++ b/pdf/pdf_font1.c @@ -117,6 +117,9 @@ pdfi_t1_glyph_data(gs_font_type1 *pfont, gs_glyph glyph, gs_glyph_data_t *pgd) if (code >= 0) { code = pdfi_dict_get_by_key(ctx, pdffont1->CharStrings, glyphname, (pdf_obj **)&charstring); + if (code < 0) { + code = pdfi_map_glyph_name_via_agl(pdffont1->CharStrings, glyphname, &charstring); + } if (code >= 0) gs_glyph_data_from_bytes(pgd, charstring->data, 0, charstring->length, NULL); } @@ -132,11 +135,17 @@ pdfi_t1_subr_data(gs_font_type1 *pfont, int index, bool global, gs_glyph_data_t int code = 0; pdf_font_type1 *pdffont1 = (pdf_font_type1 *) pfont->client_data; - if (global == true || index < 0 || index >= pdffont1->NumSubrs) { + if (global == true || index < 0 || index >= (pdffont1->Subrs == NULL ? 0 : pdfi_array_size(pdffont1->Subrs))) { code = gs_note_error(gs_error_rangecheck); } else { - gs_glyph_data_from_bytes(pgd, pdffont1->Subrs[index].data, 0, pdffont1->Subrs[index].size, NULL); + pdf_string *subr_str = NULL; + code = pdfi_array_get_type(pdffont1->ctx, pdffont1->Subrs, index, PDF_STRING, (pdf_obj **)&subr_str); + if (code >= 0) { + gs_glyph_data_from_bytes(pgd, subr_str->data, 0, subr_str->length, NULL); + } + /* decrementing is safe here, because the reference in the pdffont1->Subrs will persist */ + pdfi_countdown(subr_str); } return code; } @@ -168,11 +177,13 @@ pdfi_t1_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph, gs_const_st pdfi_countup(glyphname); code = pdfi_dict_get_by_key(ctx, pdffont1->CharStrings, glyphname, (pdf_obj **)&charstring); pdfi_countdown(glyphname); - if (code >= 0) - if (pgd != NULL) + if (code >= 0) { + if (pgd != NULL) { gs_glyph_data_from_bytes(pgd, charstring->data, 0, charstring->length, NULL); + } pdfi_countdown(charstring); } + } } return code; @@ -368,7 +379,7 @@ pdfi_t1_decode_pfb(pdf_context *ctx, byte *inbuf, int inlen, byte **outbuf, int *outbuf = NULL; *outlen = 0; - strm = push_pfb_filter(ctx->memory, inbuf, inbuf + inlen + 1); + strm = push_pfb_filter(ctx->memory, inbuf, inbuf + inlen); if (strm == NULL) { code = gs_note_error(gs_error_VMerror); } @@ -386,7 +397,7 @@ pdfi_t1_decode_pfb(pdf_context *ctx, byte *inbuf, int inlen, byte **outbuf, int } else { d = decodebuf; - strm = push_pfb_filter(ctx->memory, inbuf, inbuf + inlen + 1); + strm = push_pfb_filter(ctx->memory, inbuf, inbuf + inlen); while (1) { c = sgetc(strm); if (c < 0) @@ -501,6 +512,7 @@ int pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, byte *fbuf, int64_t fbuflen, pdf_font **ppdffont) { int code = 0; + double x_scale; pdf_obj *fontdesc = NULL; pdf_obj *basefont = NULL; pdf_obj *mapname = NULL; @@ -508,8 +520,10 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic pdf_font_type1 *t1f = NULL; pdf_obj *tounicode = NULL; ps_font_interp_private fpriv = { 0 }; + bool key_known; - (void)pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); + if (font_dict != NULL) + (void)pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); if (fbuf[0] == 128 && fbuf[1] == 1) { byte *decodebuf = NULL; @@ -530,12 +544,12 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic gs_free_object(ctx->memory, fbuf, "pdfi_read_type1_font"); /* If we have a full CharStrings dictionary, we probably have enough to make a font */ - if (code < 0 || (fpriv.u.t1.CharStrings == NULL || fpriv.u.t1.CharStrings->type != PDF_DICT - || fpriv.u.t1.CharStrings->entries == 0)) { + if (code < 0 || fpriv.u.t1.CharStrings == NULL || pdfi_type_of(fpriv.u.t1.CharStrings) != PDF_DICT + || fpriv.u.t1.CharStrings->entries == 0) { code = gs_note_error(gs_error_invalidfont); goto error; } - code = pdfi_alloc_t1_font(ctx, &t1f, font_dict->object_num); + code = pdfi_alloc_t1_font(ctx, &t1f, font_dict != NULL ? font_dict->object_num : 0); if (code >= 0) { gs_font_type1 *pfont1 = (gs_font_type1 *) t1f->pfont; @@ -555,22 +569,26 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic pfont1->PaintType = fpriv.gsu.gst1.PaintType; pfont1->StrokeWidth = fpriv.gsu.gst1.StrokeWidth; - t1f->object_num = font_dict->object_num; - t1f->generation_num = font_dict->generation_num; - t1f->indirect_num = font_dict->indirect_num; - t1f->indirect_gen = font_dict->indirect_gen; + if (font_dict != NULL) { + t1f->object_num = font_dict->object_num; + t1f->generation_num = font_dict->generation_num; + t1f->indirect_num = font_dict->indirect_num; + t1f->indirect_gen = font_dict->indirect_gen; + } t1f->PDF_font = font_dict; pdfi_countup(font_dict); - t1f->BaseFont = basefont; - pdfi_countup(basefont); t1f->FontDescriptor = (pdf_dict *) fontdesc; pdfi_countup(fontdesc); t1f->Name = mapname; pdfi_countup(mapname); /* We want basefont, but we can live without it */ - (void)pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &basefont); + if (font_dict != NULL) { + (void)pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &basefont); + t1f->BaseFont = basefont; + pdfi_countup(basefont); + } t1f->descflags = 0; if (t1f->FontDescriptor != NULL) { @@ -588,15 +606,15 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic t1f->descflags |= 4; } - 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; @@ -608,74 +626,29 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic t1f->ToUnicode = tounicode; tounicode = NULL; - code = pdfi_dict_knownget_type(ctx, font_dict, "FirstChar", PDF_INT, &tmp); - if (code == 1) { - t1f->FirstChar = ((pdf_num *) tmp)->value.i; - pdfi_countdown(tmp); - tmp = NULL; - } - else { - t1f->FirstChar = 0; - } - code = pdfi_dict_knownget_type(ctx, font_dict, "LastChar", PDF_INT, &tmp); - if (code == 1) { - t1f->LastChar = ((pdf_num *) tmp)->value.i; - pdfi_countdown(tmp); - tmp = NULL; - } - else { - t1f->LastChar = 255; - } + pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)t1f); - t1f->fake_glyph_names = (gs_string *) gs_alloc_bytes(ctx->memory, t1f->LastChar * sizeof(gs_string), "pdfi_read_type1_font: fake_glyph_names"); - if (!t1f->fake_glyph_names) { - code = gs_note_error(gs_error_VMerror); - goto error; - } - memset(t1f->fake_glyph_names, 0x00, t1f->LastChar * sizeof(gs_string)); - - code = pdfi_dict_knownget_type(ctx, font_dict, "Widths", PDF_ARRAY, &tmp); - if (code > 0) { - int i; - double x_scale; - int num_chars = t1f->LastChar - t1f->FirstChar + 1; - - if (num_chars == pdfi_array_size((pdf_array *) tmp)) { - t1f->Widths = (double *)gs_alloc_bytes(ctx->memory, sizeof(double) * num_chars, "Type 1 font Widths array"); - if (t1f->Widths == NULL) { - code = gs_note_error(gs_error_VMerror); - goto error; - } - - /* Widths are defined assuming a 1000x1000 design grid, but we apply - * them in font space - so undo the 1000x1000 scaling, and apply - * the inverse of the font's x scaling - */ - x_scale = 0.001 / hypot(pfont1->FontMatrix.xx, pfont1->FontMatrix.xy); - - memset(t1f->Widths, 0x00, sizeof(double) * num_chars); - for (i = 0; i < num_chars; i++) { - code = pdfi_array_get_number(ctx, (pdf_array *) tmp, (uint64_t) i, &t1f->Widths[i]); - if (code < 0) - goto error; - t1f->Widths[i] *= x_scale; - } - } - else { - t1f->Widths = NULL; - } - } - pdfi_countdown(tmp); - tmp = NULL; + /* Widths are defined assuming a 1000x1000 design grid, but we apply + * them in font space - so undo the 1000x1000 scaling, and apply + * the inverse of the font's x scaling + */ + x_scale = 0.001 / hypot(pfont1->FontMatrix.xx, pfont1->FontMatrix.xy); + + /* ignore errors with widths... for now */ + if (font_dict != NULL) + (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)t1f, x_scale); - code = pdfi_dict_knownget(ctx, font_dict, "Encoding", &tmp); + if (font_dict != NULL) + code = pdfi_dict_knownget(ctx, font_dict, "Encoding", &tmp); + else + code = gs_error_undefined; if (code == 1) { - if ((tmp->type == PDF_NAME || tmp->type == PDF_DICT) && (t1f->descflags & 4) == 0) { + if ((pdfi_type_of(tmp) == PDF_NAME || pdfi_type_of(tmp) == PDF_DICT) && (t1f->descflags & 4) == 0) { code = pdfi_create_Encoding(ctx, tmp, NULL, (pdf_obj **) & t1f->Encoding); if (code >= 0) code = 1; } - else if (tmp->type == PDF_DICT && (t1f->descflags & 4) != 0) { + else if (pdfi_type_of(tmp) == PDF_DICT && (t1f->descflags & 4) != 0) { code = pdfi_create_Encoding(ctx, tmp, (pdf_obj *)fpriv.u.t1.Encoding, (pdf_obj **) & t1f->Encoding); if (code >= 0) code = 1; @@ -685,15 +658,6 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic pdfi_countdown(tmp); tmp = NULL; if (code == 1) { - /* Since the underlying font stream can be shared between font descriptors, - and the font descriptors can be shared between font objects, if we change - the encoding, we can't share cached glyphs with other instances of this - underlying font, so invalidate the UniqueID/XUID so the glyph cache won't - try. - */ - if (uid_is_XUID(&t1f->pfont->UID)) - uid_free(&t1f->pfont->UID, t1f->pfont->memory, "pdfi_read_type1_font"); - uid_set_invalid(&t1f->pfont->UID); } } else { @@ -706,6 +670,15 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic t1f->Encoding = fpriv.u.t1.Encoding; pdfi_countup(t1f->Encoding); } + /* Since the underlying font stream can be shared between font descriptors, + and the font descriptors can be shared between font objects, if we change + the encoding, we can't share cached glyphs with other instances of this + underlying font, so invalidate the UniqueID/XUID so the glyph cache won't + try. + */ + if (uid_is_XUID(&t1f->pfont->UID)) + uid_free(&t1f->pfont->UID, t1f->pfont->memory, "pdfi_read_type1_font"); + uid_set_invalid(&t1f->pfont->UID); t1f->CharStrings = fpriv.u.t1.CharStrings; pdfi_countup(t1f->CharStrings); @@ -713,7 +686,11 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic t1f->Subrs = fpriv.u.t1.Subrs; fpriv.u.t1.Subrs = NULL; - t1f->NumSubrs = fpriv.u.t1.NumSubrs; + + code = pdfi_font_generate_pseudo_XUID(ctx, font_dict, t1f->pfont); + if (code < 0) { + goto error; + } t1f->blenddesignpositions = fpriv.u.t1.blenddesignpositions; pdfi_countup(t1f->blenddesignpositions); @@ -724,6 +701,18 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic t1f->blendaxistypes = fpriv.u.t1.blendaxistypes; pdfi_countup(t1f->blendaxistypes); + key_known = false; + if (t1f->FontDescriptor != NULL) { + code = pdfi_dict_known(ctx, t1f->FontDescriptor, "FontFile", &key_known); + if (code < 0 || key_known == false) { + code = pdfi_dict_known(ctx, t1f->FontDescriptor, "FontFile2", &key_known); + if (code < 0 || key_known == false) { + code = pdfi_dict_known(ctx, t1f->FontDescriptor, "FontFile3", &key_known); + } + } + } + t1f->pfont->is_resource = (key_known == false); + code = gs_definefont(ctx->font_dir, (gs_font *) t1f->pfont); if (code < 0) { goto error; @@ -753,20 +742,190 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic pdfi_countdown(fpriv.u.t1.blenddesignmap); pdfi_countdown(fpriv.u.t1.blendfontbbox); pdfi_countdown(fpriv.u.t1.blendaxistypes); + pdfi_countdown(fpriv.u.t1.Subrs); if (fpriv.gsu.gst1.UID.xvalues != NULL) { gs_free_object(ctx->memory, fpriv.gsu.gst1.UID.xvalues, "pdfi_read_type1_font(xuid)"); } - if (fpriv.u.t1.Subrs) { - int i; - for (i = 0; i < fpriv.u.t1.NumSubrs; i++) { - gs_free_object(ctx->memory, fpriv.u.t1.Subrs[i].data, "Subrs[i]"); + if (code < 0) { + pdfi_countdown(t1f); + } + return code; +} + +int +pdfi_copy_type1_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont) +{ + int code = 0; + pdf_font_type1 *font = NULL; + gs_font_type1 *spfont1 = (gs_font_type1 *) spdffont->pfont; + gs_font_type1 *dpfont1; + gs_id t_id; + pdf_obj *tmp; + + if (font_dict == NULL) + return_error(gs_error_invalidfont); + + code = pdfi_alloc_t1_font(ctx, &font, font_dict->object_num); + if (code < 0) + return code; + dpfont1 = (gs_font_type1 *) font->pfont; + + t_id = dpfont1->id; + memcpy(dpfont1, spfont1, sizeof(gs_font_type1)); + dpfont1->id = t_id; + dpfont1->FAPI = NULL; + dpfont1->FAPI_font_data = NULL; + + memcpy(font, spdffont, sizeof(pdf_font_type1)); + font->pfont = (gs_font_base *)dpfont1; + font->refcnt = 1; + dpfont1->client_data = (void *)font; + font->filename = NULL; + + dpfont1->notify_list.memory = NULL; + dpfont1->notify_list.first = NULL; + gs_notify_init(&dpfont1->notify_list, dpfont1->memory); + + 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; + code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &font->BaseFont); + if (code < 0) { + pdfi_countdown(font->BaseFont); + font->BaseFont = NULL; + } + font->FontDescriptor = NULL; + code = pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, (pdf_obj **)&font->FontDescriptor); + if (code < 0) { + pdfi_countdown(font->FontDescriptor); + font->FontDescriptor = NULL; + } + + pdfi_countup(font->Name); + pdfi_countup(font->CharStrings); + pdfi_countup(font->blenddesignpositions); + pdfi_countup(font->blenddesignmap); + pdfi_countup(font->blendfontbbox); + pdfi_countup(font->blendaxistypes); + pdfi_countup(font->Subrs); + + if (font->BaseFont != NULL && ((pdf_name *)font->BaseFont)->length <= gs_font_name_max - 1) { + memcpy(dpfont1->key_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont1->key_name.size = ((pdf_name *)font->BaseFont)->length; + dpfont1->key_name.chars[dpfont1->key_name.size] = '\0'; + memcpy(dpfont1->font_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont1->font_name.size = ((pdf_name *)font->BaseFont)->length; + dpfont1->font_name.chars[dpfont1->font_name.size] = '\0'; + } + + 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 / hypot(dpfont1->FontMatrix.xx, dpfont1->FontMatrix.xy))); + + 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); } - gs_free_object(ctx->memory, fpriv.u.t1.Subrs, "Subrs"); } + + if (pdfi_font_known_symbolic(font->BaseFont)) { + 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); + if (code >= 0) + code = 1; + } + 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); + if (code >= 0) + code = 1; + } + else + code = gs_error_undefined; + pdfi_countdown(tmp); + tmp = NULL; + } + else { + pdfi_countdown(tmp); + tmp = NULL; + code = 0; + } + + if (code <= 0) { + font->Encoding = spdffont->Encoding; + pdfi_countup(font->Encoding); + } + + /* 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) { - pdfi_countdown(t1f); + goto error; } + + 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; } @@ -774,7 +933,6 @@ int pdfi_free_font_type1(pdf_obj *font) { pdf_font_type1 *t1f = (pdf_font_type1 *) font; - int i; gs_free_object(OBJ_MEMORY(font), t1f->pfont, "Free Type 1 gs_font"); @@ -789,20 +947,9 @@ pdfi_free_font_type1(pdf_obj *font) pdfi_countdown(t1f->blenddesignmap); pdfi_countdown(t1f->blendfontbbox); pdfi_countdown(t1f->blendaxistypes); + pdfi_countdown(t1f->Subrs); + pdfi_countdown(t1f->filename); - if (t1f->fake_glyph_names != NULL) { - for (i = 0; i < t1f->LastChar; i++) { - if (t1f->fake_glyph_names[i].data != NULL) - gs_free_object(OBJ_MEMORY(font), t1f->fake_glyph_names[i].data, "Type 1 fake_glyph_name"); - } - gs_free_object(OBJ_MEMORY(font), t1f->fake_glyph_names, "Type 1 fake_glyph_names"); - } - if (t1f->NumSubrs > 0 && t1f->Subrs != NULL) { - for (i = 0; i < t1f->NumSubrs; i++) { - gs_free_object(OBJ_MEMORY(font), t1f->Subrs[i].data, "Type 1 Subr"); - } - gs_free_object(OBJ_MEMORY(font), t1f->Subrs, "Type 1 Subrs"); - } gs_free_object(OBJ_MEMORY(font), t1f->Widths, "Free Type 1 fontWidths"); gs_free_object(OBJ_MEMORY(font), t1f, "Free Type 1 font"); return 0; |