diff options
-rw-r--r-- | pdf/ghostpdf.c | 2 | ||||
-rw-r--r-- | pdf/ghostpdf.h | 1 | ||||
-rw-r--r-- | pdf/pdf_fapi.c | 66 | ||||
-rw-r--r-- | pdf/pdf_font.c | 397 | ||||
-rw-r--r-- | pdf/pdf_font.h | 2 | ||||
-rw-r--r-- | pdf/pdf_font0.c | 3 | ||||
-rw-r--r-- | pdf/pdf_font1.c | 305 | ||||
-rw-r--r-- | pdf/pdf_font1.h | 4 | ||||
-rw-r--r-- | pdf/pdf_font11.c | 62 | ||||
-rw-r--r-- | pdf/pdf_font1C.c | 351 | ||||
-rw-r--r-- | pdf/pdf_font1C.h | 5 | ||||
-rw-r--r-- | pdf/pdf_font3.c | 63 | ||||
-rw-r--r-- | pdf/pdf_fontTT.c | 301 | ||||
-rw-r--r-- | pdf/pdf_fontTT.h | 3 | ||||
-rw-r--r-- | pdf/pdf_font_types.h | 31 | ||||
-rw-r--r-- | pdf/pdf_fontps.c | 36 | ||||
-rw-r--r-- | pdf/pdf_obj.c | 57 | ||||
-rw-r--r-- | pdf/pdf_obj.h | 18 | ||||
-rw-r--r-- | pdf/pdf_types.h | 11 |
19 files changed, 1126 insertions, 592 deletions
diff --git a/pdf/ghostpdf.c b/pdf/ghostpdf.c index 24bf7394b..2dd4c63cc 100644 --- a/pdf/ghostpdf.c +++ b/pdf/ghostpdf.c @@ -2095,6 +2095,8 @@ int pdfi_clear_context(pdf_context *ctx) ctx->pdffontmap = NULL; pdfi_countdown(ctx->pdfnativefontmap); ctx->pdfnativefontmap = NULL; + pdfi_countdown(ctx->pdf_substitute_fonts); + ctx->pdf_substitute_fonts = NULL; return 0; } diff --git a/pdf/ghostpdf.h b/pdf/ghostpdf.h index 6e8906726..a2ca382f0 100644 --- a/pdf/ghostpdf.h +++ b/pdf/ghostpdf.h @@ -452,6 +452,7 @@ typedef struct pdf_context_s search_paths_t search_paths; pdf_dict *pdffontmap; pdf_dict *pdfnativefontmap; /* Explicit mappings take precedence, hence we need separate dictionaries */ + pdf_dict *pdf_substitute_fonts; pdf_dict *pdfcidfmap; /* These function pointers can be replaced by ones intended to replicate diff --git a/pdf/pdf_fapi.c b/pdf/pdf_fapi.c index 503064e13..7fb7c954c 100644 --- a/pdf/pdf_fapi.c +++ b/pdf/pdf_fapi.c @@ -254,7 +254,7 @@ pdfi_fapi_get_word(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, uns { if (pfont->FontType == ft_encrypted2) { pdf_font_cff *pdffont2 = (pdf_font_cff *)pfont->client_data; - *ret = pdffont2->NumGlobalSubrs; + *ret = pdffont2->GlobalSubrs == NULL ? 0 : pdfi_array_size(pdffont2->GlobalSubrs); } else { *ret = 0; @@ -266,11 +266,11 @@ pdfi_fapi_get_word(gs_fapi_font *ff, gs_fapi_font_feature var_id, int index, uns { if (pfont->FontType == ft_encrypted) { pdf_font_type1 *pdffont1 = (pdf_font_type1 *)pfont->client_data; - *ret = pdffont1->NumSubrs; + *ret = pdffont1->Subrs == NULL ? 0 : pdfi_array_size(pdffont1->Subrs); } else if (pfont->FontType == ft_encrypted2) { pdf_font_cff *pdffont2 = (pdf_font_cff *)pfont->client_data; - *ret = pdffont2->NumSubrs; + *ret = pdffont2->Subrs == NULL ? 0 : pdfi_array_size(pdffont2->Subrs); } else { *ret = 0; @@ -449,8 +449,13 @@ pdfi_fapi_get_long(gs_fapi_font * ff, gs_fapi_font_feature var_id, int index, un pdf_font_type1 *pdffont1 = (pdf_font_type1 *)pfont->client_data; int i; *ret = 0; - for (i = 0; i < pdffont1->NumSubrs; i++) { - *ret += pdffont1->Subrs[i].size; + for (i = 0; i < (pdffont1->Subrs == NULL ? 0 : pdfi_array_size(pdffont1->Subrs)); i++) { + pdf_string *subr_str = NULL; + code = pdfi_array_get_type(pdffont1->ctx, pdffont1->Subrs, i, PDF_STRING, (pdf_obj **)&subr_str); + if (code >= 0) { + *ret += subr_str->length; + } + pdfi_countdown(subr_str); } } } @@ -675,7 +680,7 @@ pdfi_fapi_get_gsubr(gs_fapi_font *ff, int index, byte *buf, int buf_length) int code = 0; if (pfont->FontType == ft_encrypted2) { pdf_font_cff *pdffont2 = (pdf_font_cff *)pfont->client_data; - if (index > pdffont2->NumGlobalSubrs) { + if (index > (pdffont2->GlobalSubrs == NULL ? 0 : pdfi_array_size(pdffont2->GlobalSubrs))) { code = gs_error_rangecheck; } else { @@ -716,27 +721,35 @@ pdfi_fapi_get_subr(gs_fapi_font *ff, int index, byte *buf, int buf_length) if (pfont->FontType == ft_encrypted) { pdf_font_type1 *pdffont1 = (pdf_font_type1 *)pfont->client_data; - if (index > pdffont1->NumSubrs) { + if (index > (pdffont1->Subrs == NULL ? 0 : pdfi_array_size(pdffont1->Subrs))) { code = gs_note_error(gs_error_rangecheck); } else { int leniv = (pfont->data.lenIV > 0 ? pfont->data.lenIV : 0); - if (pdffont1->Subrs[index].size > 0) { - code = pdffont1->Subrs[index].size - leniv; + pdf_string *subr_str = NULL; + + code = pdfi_array_get_type(pdffont1->ctx, pdffont1->Subrs, index, PDF_STRING, (pdf_obj **)&subr_str); + if (code >= 0) { + code = subr_str->length - leniv; if (buf && buf_length >= code) { if (ff->need_decrypt && pfont->data.lenIV >= 0) { - decode_bytes(buf, pdffont1->Subrs[index].data, code + leniv, pfont->data.lenIV); + decode_bytes(buf, subr_str->data, code + leniv, pfont->data.lenIV); } else { - memcpy(buf, pdffont1->Subrs[index].data, code); + memcpy(buf, subr_str->data, code); } } } + else { + /* Ignore invalid or missing subrs */ + code = 0; + } + pdfi_countdown(subr_str); } } else if (pfont->FontType == ft_encrypted2) { pdf_font_cff *pdffont2 = (pdf_font_cff *)pfont->client_data; - if (index > pdffont2->NumSubrs) { + if (index > (pdffont2->Subrs == NULL ? 0 : pdfi_array_size(pdffont2->Subrs))) { code = gs_error_rangecheck; } else { @@ -782,14 +795,23 @@ pdfi_fapi_get_raw_subr(gs_fapi_font *ff, int index, byte *buf, int buf_length) if (pfont->FontType == ft_encrypted) { pdf_font_type1 *pdffont1 = (pdf_font_type1 *)pfont->client_data; - if (index > pdffont1->NumSubrs) { + if (index > (pdffont1->Subrs == NULL ? 0 : pdfi_array_size(pdffont1->Subrs))) { code = gs_error_rangecheck; } else { - code = pdffont1->Subrs[index].size; - if (buf && buf_length >= code) { - memcpy(buf, pdffont1->Subrs[index].data, code); + pdf_string *subr_str = NULL; + code = pdfi_array_get_type(pdffont1->ctx, pdffont1->Subrs, index, PDF_STRING, (pdf_obj **)&subr_str); + if (code >= 0) { + code = subr_str->length; + if (buf && buf_length >= code) { + memcpy(buf, subr_str->data, code); + } + } + else { + /* Ignore missing or invalid subrs */ + code = 0; } + pdfi_countdown(subr_str); } } return code; @@ -825,8 +847,8 @@ pdfi_fapi_get_glyphname_or_cid(gs_text_enum_t *penum, gs_font_base * pbfont, gs_ if (pttfont->substitute == false) { gid = ccode; - if (pttfont->cidtogidmap.size > (ccode << 1) + 1) { - gid = pttfont->cidtogidmap.data[ccode << 1] << 8 | pttfont->cidtogidmap.data[(ccode << 1) + 1]; + if (pttfont->cidtogidmap != NULL && pttfont->cidtogidmap->length > (ccode << 1) + 1) { + gid = pttfont->cidtogidmap->data[ccode << 1] << 8 | pttfont->cidtogidmap->data[(ccode << 1) + 1]; } cr->client_char_code = ccode; cr->char_codes[0] = gid; @@ -1287,8 +1309,8 @@ pdfi_fapi_retrieve_tt_font(gs_fapi_font * ff, void **buf, int *buf_size) gs_font_type42 *pfonttt = (gs_font_type42 *) ff->client_font_data; pdf_font_truetype *pdfttf = (pdf_font_truetype *)pfonttt->client_data; - *buf = pdfttf->sfnt.data; - *buf_size = pdfttf->sfnt.size; + *buf = pdfttf->sfnt->data; + *buf_size = pdfttf->sfnt->length; return 0; } @@ -1472,8 +1494,8 @@ pdfi_fapi_passfont(pdf_font *font, int subfont, char *fapi_request, fdatap = NULL; } else if (font->pdfi_font_type == e_pdf_cidfont_type2) { - fdatap->data = ((pdf_cidfont_type2 *)font)->sfnt.data; - fdatap->size = ((pdf_cidfont_type2 *)font)->sfnt.size; + fdatap->data = ((pdf_cidfont_type2 *)font)->sfnt->data; + fdatap->size = ((pdf_cidfont_type2 *)font)->sfnt->length; } else { fdatap->data = font_data; diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c index 6479cf791..634feb890 100644 --- a/pdf/pdf_font.c +++ b/pdf/pdf_font.c @@ -159,8 +159,14 @@ static void pdfi_print_font_name(pdf_context *ctx, pdf_name *n) (void)outwrite(ctx->memory, (const char *)n->data, n->length); } +static void pdfi_print_font_string(pdf_context *ctx, pdf_string *s) +{ + if (ctx->args.QUIET != true) + (void)outwrite(ctx->memory, (const char *)s->data, s->length); +} + /* Print a null terminated string to stdout */ -static void pdfi_print_string(pdf_context *ctx, const char *str) +static void pdfi_print_cstring(pdf_context *ctx, const char *str) { if (ctx->args.QUIET != true) (void)outwrite(ctx->memory, str, strlen(str)); @@ -256,12 +262,12 @@ pdfi_open_CIDFont_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dic } else { if (cidname) { - pdfi_print_string(ctx, "Loading CIDFont "); + pdfi_print_cstring(ctx, "Loading CIDFont "); pdfi_print_font_name(ctx, (pdf_name *)cidname); - pdfi_print_string(ctx, " substitute from "); + pdfi_print_cstring(ctx, " substitute from "); } else { - pdfi_print_string(ctx, "Loading nameless CIDFont from "); + pdfi_print_cstring(ctx, "Loading nameless CIDFont from "); } sfilename(s, &fname); if (fname.size < gp_file_name_sizeof) { @@ -271,8 +277,8 @@ pdfi_open_CIDFont_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dic else { strcpy(fontfname, "unnamed file"); } - pdfi_print_string(ctx, fontfname); - pdfi_print_string(ctx, "\n"); + pdfi_print_cstring(ctx, fontfname); + pdfi_print_cstring(ctx, "\n"); sfseek(s, 0, SEEK_END); @@ -303,12 +309,12 @@ pdfi_open_CIDFont_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dic } else { if (cidname) { - pdfi_print_string(ctx, "Loading CIDFont "); + pdfi_print_cstring(ctx, "Loading CIDFont "); pdfi_print_font_name(ctx, (pdf_name *)cidname); - pdfi_print_string(ctx, " (or substitute) from "); + pdfi_print_cstring(ctx, " (or substitute) from "); } else { - pdfi_print_string(ctx, "Loading nameless CIDFont from "); + pdfi_print_cstring(ctx, "Loading nameless CIDFont from "); } sfilename(s, &fname); if (fname.size < gp_file_name_sizeof) { @@ -318,8 +324,8 @@ pdfi_open_CIDFont_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dic else { strcpy(fontfname, "unnamed file"); } - pdfi_print_string(ctx, fontfname); - pdfi_print_string(ctx, "\n"); + pdfi_print_cstring(ctx, fontfname); + pdfi_print_cstring(ctx, "\n"); sfseek(s, 0, SEEK_END); *buflen = sftell(s); sfseek(s, 0, SEEK_SET); @@ -559,22 +565,100 @@ static int pdfi_fonttype_picker(byte *buf, int64_t buflen) #undef MAKEMAGIC } -static int -pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *fontdesc, bool fallback, byte **buf, int64_t *buflen, int *findex) +static int pdfi_copy_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont) +{ + int code; + if (pdfi_type_of(spdffont) != PDF_FONT) + return_error(gs_error_typecheck); + + switch(spdffont->pdfi_font_type) { + case e_pdf_font_type1: + code = pdfi_copy_type1_font(ctx, spdffont, font_dict, tpdffont); + break; + case e_pdf_font_cff: + code = pdfi_copy_cff_font(ctx, spdffont, font_dict, tpdffont); + break; + case e_pdf_font_truetype: + code = pdfi_copy_truetype_font(ctx, spdffont, font_dict, tpdffont); + break; + default: + return_error(gs_error_invalidfont); + } + return code; +} + +enum { + font_embedded = 0, + font_from_file = 1, + font_substitute = 2 +}; + +static int pdfi_load_font_buffer(pdf_context *ctx, byte *fbuf, int fbuflen, int fftype, pdf_name *Subtype, int findex, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, pdf_font **ppdffont, bool cidfont) +{ + int code = gs_error_invalidfont; + if (fbuf != NULL) { + /* First, see if we can glean the type from the magic number */ + int sftype = pdfi_fonttype_picker(fbuf, fbuflen); + if (sftype == no_type_font) { + if (fftype != no_type_font) + sftype = fftype; + else { + /* If we don't have a Subtype, can't work it out, try Type 1 */ + if (Subtype == NULL || pdfi_name_is(Subtype, "Type1") || pdfi_name_is(Subtype, "MMType1")) + sftype = type1_font; + else if (pdfi_name_is(Subtype, "Type1C")) + sftype = cff_font; + else if (pdfi_name_is(Subtype, "TrueType")) + sftype = tt_font; + } + } + /* fbuf ownership passes to the font loader */ + switch (sftype) { + case type1_font: + code = pdfi_read_type1_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, fbuf, fbuflen, ppdffont); + fbuf = NULL; + break; + case cff_font: + code = pdfi_read_cff_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, fbuf, fbuflen, cidfont, ppdffont); + fbuf = NULL; + break; + case tt_font: + { + if (cidfont) + code = pdfi_read_cidtype2_font(ctx, font_dict, stream_dict, page_dict, fbuf, fbuflen, findex, ppdffont); + else + code = pdfi_read_truetype_font(ctx, font_dict, stream_dict, page_dict, fbuf, fbuflen, findex, ppdffont); + fbuf = NULL; + } + break; + default: + gs_free_object(ctx->memory, fbuf, "pdfi_load_font_buffer(fbuf)"); + code = gs_note_error(gs_error_invalidfont); + } + } + return code; +} + +static int pdfi_load_font_file(pdf_context *ctx, int fftype, pdf_name *Subtype, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, pdf_dict *fontdesc, bool substitute, pdf_font **ppdffont) { int code; char fontfname[gp_file_name_sizeof]; - pdf_obj *basefont = NULL, *mapname; + pdf_obj *basefont = NULL, *mapname = NULL; pdf_obj *fontname = NULL; stream *s; const char *fn; + int findex = 0; + byte *buf; + int buflen; + pdf_font *pdffont = NULL; + pdf_font *substpdffont = NULL; bool f_retry = true; code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &basefont); if (code < 0 || basefont == NULL || ((pdf_name *)basefont)->length == 0) - fallback = true; + return_error(gs_error_invalidfont); - if (fallback == true) { + if (substitute == true) { char *fbname; int fbnamelen; int64_t flags = 0; @@ -607,7 +691,7 @@ pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict * } do { - code = pdf_fontmap_lookup_font(ctx, (pdf_name *) fontname, &mapname, findex); + code = pdf_fontmap_lookup_font(ctx, (pdf_name *) fontname, &mapname, &findex); if (code < 0) { if (((pdf_name *)fontname)->length < gp_file_name_sizeof) { memcpy(fontfname, ((pdf_name *)fontname)->data, ((pdf_name *)fontname)->length); @@ -622,7 +706,7 @@ pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict * pdfi_countup(fontname); } } - code = pdf_fontmap_lookup_font(ctx, (pdf_name *) fontname, &mapname, findex); + code = pdf_fontmap_lookup_font(ctx, (pdf_name *) fontname, &mapname, &findex); if (code < 0) { mapname = fontname; pdfi_countup(mapname); @@ -647,62 +731,100 @@ pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict * return_error(gs_error_invalidfileaccess); } - code = pdfi_open_font_file(ctx, fontfname, strlen(fontfname), &s); - if (code < 0 && f_retry && pdfi_type_of(mapname) == PDF_NAME) { - pdfi_countdown(fontname); - fontname = mapname; - mapname = NULL; - f_retry = false; - continue; - } - if (code >= 0) { - gs_const_string fname; - if (basefont) { - pdfi_print_string(ctx, "Loading font "); - pdfi_print_font_name(ctx, (pdf_name *)basefont); - pdfi_print_string(ctx, " (or substitute) from "); - } - else { - pdfi_print_string(ctx, "Loading nameless font from "); - } - sfilename(s, &fname); - if (fname.size < gp_file_name_sizeof) { - memcpy(fontfname, fname.data, fname.size); - fontfname[fname.size] = '\0'; - } - else { - strcpy(fontfname, "unnamed file"); + if (ctx->pdf_substitute_fonts != NULL) { + code = pdfi_dict_knownget_type(ctx, ctx->pdf_substitute_fonts, fontfname, PDF_FONT, (pdf_obj **)&pdffont); + if (code == 1 && pdffont->filename == NULL) { + pdfi_countdown(pdffont); + pdffont = NULL; + code = 0; } - pdfi_print_string(ctx, fontfname); - pdfi_print_string(ctx, "\n"); + } + else + code = 0; - sfseek(s, 0, SEEK_END); - *buflen = sftell(s); - sfseek(s, 0, SEEK_SET); - *buf = gs_alloc_bytes(ctx->memory, *buflen, "pdfi_open_t1_font_file(buf)"); - if (*buf != NULL) { - sfread(*buf, 1, *buflen, s); + if (code != 1) { + code = pdfi_open_font_file(ctx, fontfname, strlen(fontfname), &s); + if (code < 0 && f_retry && pdfi_type_of(mapname) == PDF_NAME) { + pdfi_countdown(fontname); + fontname = mapname; + mapname = NULL; + f_retry = false; + continue; } - else { - code = gs_note_error(gs_error_VMerror); + if (code >= 0) { + gs_const_string fname; + + sfilename(s, &fname); + if (fname.size < gp_file_name_sizeof) { + memcpy(fontfname, fname.data, fname.size); + fontfname[fname.size] = '\0'; + } + else { + strcpy(fontfname, "unnamed file"); + } + sfseek(s, 0, SEEK_END); + buflen = sftell(s); + sfseek(s, 0, SEEK_SET); + buf = gs_alloc_bytes(ctx->memory, buflen, "pdfi_open_t1_font_file(buf)"); + if (buf != NULL) { + sfread(buf, 1, buflen, s); + } + else { + code = gs_note_error(gs_error_VMerror); + } + sfclose(s); + /* On success, the buffer owership moves to the font object */ + code = pdfi_load_font_buffer(ctx, buf, buflen, no_type_font, NULL, findex, stream_dict, page_dict, NULL, &pdffont, false); + if (code < 0) { + gs_free_object(ctx->memory, buf, "pdfi_load_font_file"); + } + else { + pdffont->filename = NULL; + code = pdfi_object_alloc(ctx, PDF_STRING,strlen(fontfname) , (pdf_obj **)&pdffont->filename); + if (code >= 0) { + pdfi_countup(pdffont->filename); + memcpy(pdffont->filename->data, fontfname, strlen(fontfname)); + pdffont->filename->length = strlen(fontfname); + } + + if (ctx->pdf_substitute_fonts == NULL) { + code = pdfi_dict_alloc(ctx, 16, &ctx->pdf_substitute_fonts); + if (code >= 0) + pdfi_countup(ctx->pdf_substitute_fonts); + } + if (ctx->pdf_substitute_fonts != NULL) { + code = pdfi_dict_put_obj(ctx, ctx->pdf_substitute_fonts, mapname, (pdf_obj *)pdffont, true); + } + } } - sfclose(s); } break; } while (1); + if (code >= 0) { + if (basefont) { + pdfi_print_cstring(ctx, "Loading font "); + pdfi_print_font_name(ctx, (pdf_name *)basefont); + pdfi_print_cstring(ctx, " (or substitute) from "); + } + else { + pdfi_print_cstring(ctx, "Loading nameless font from "); + } + pdfi_print_font_string(ctx, pdffont->filename); + pdfi_print_cstring(ctx, "\n"); + + code = pdfi_copy_font(ctx, pdffont, font_dict, &substpdffont); + pdfi_countdown(pdffont); + } + + *ppdffont = substpdffont; + pdfi_countdown(basefont); pdfi_countdown(mapname); pdfi_countdown(fontname); return code; } -enum { - font_embedded = 0, - font_from_file = 1, - font_substitute = 2 -}; - int pdfi_load_font(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, gs_font **ppfont, bool cidfont) { int code; @@ -788,59 +910,27 @@ int pdfi_load_font(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, while (1) { if (fbuf != NULL) { - /* First, see if we can glean the type from the magic number */ - int sftype = pdfi_fonttype_picker(fbuf, fbuflen); - if (sftype == no_type_font) { - if (fftype != no_type_font) - sftype = fftype; - else { - /* If we don't have a Subtype, can't work it out, try Type 1 */ - if (Subtype == NULL || pdfi_name_is(Subtype, "Type1") || pdfi_name_is(Subtype, "MMType1")) - sftype = type1_font; - else if (pdfi_name_is(Subtype, "Type1C")) - sftype = cff_font; - else if (pdfi_name_is(Subtype, "TrueType")) - sftype = tt_font; - } - } - /* fbuf ownership passes to the font loader */ - switch (sftype) { - case type1_font: - code = pdfi_read_type1_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, fbuf, fbuflen, &ppdffont); - fbuf = NULL; - break; - case cff_font: - code = pdfi_read_cff_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, fbuf, fbuflen, cidfont, &ppdffont); - fbuf = NULL; - break; - case tt_font: - { - if (cidfont) - code = pdfi_read_cidtype2_font(ctx, font_dict, stream_dict, page_dict, fbuf, fbuflen, findex, &ppdffont); - else - code = pdfi_read_truetype_font(ctx, font_dict, stream_dict, page_dict, fbuf, fbuflen, findex, &ppdffont); - fbuf = NULL; - } - break; - default: - code = gs_note_error(gs_error_invalidfont); - } + /* fbuf overship passes to pdfi_load_font_buffer() */ + code = pdfi_load_font_buffer(ctx, fbuf, fbuflen, fftype, Subtype, findex, stream_dict, page_dict, font_dict, &ppdffont, cidfont); if (code < 0 && substitute == font_embedded) { - char obj[129]; - pdfi_print_string(ctx, "**** Warning: cannot process embedded stream for font object "); - gs_snprintf(obj, 128, "%d %d\n", (int)font_dict->object_num, (int)font_dict->generation_num); - pdfi_print_string(ctx, obj); - pdfi_print_string(ctx, "**** Attempting to load a substitute font.\n"); + if (ctx->args.pdfstoponerror == true) { + goto exit; + } + else { + char obj[129]; + pdfi_print_cstring(ctx, "**** Warning: cannot process embedded stream for font object "); + gs_snprintf(obj, 128, "%d %d\n", (int)font_dict->object_num, (int)font_dict->generation_num); + pdfi_print_cstring(ctx, obj); + pdfi_print_cstring(ctx, "**** Attempting to load a substitute font.\n"); + } } } + else { + code = gs_error_invalidfont; + } if (code < 0 && code != gs_error_VMerror && substitute == font_embedded) { - /* Font not embedded, or embedded font not usable - use a substitute */ - if (fbuf != NULL) { - gs_free_object(ctx->memory, fbuf, "pdfi_load_font(fbuf)"); - } - substitute = font_from_file; if (cidfont == true) { @@ -854,14 +944,12 @@ int pdfi_load_font(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, goto exit; } else { - code = pdfi_open_font_substitute_file(ctx, font_dict, fontdesc, false, &fbuf, &fbuflen, &findex); + code = pdfi_load_font_file(ctx, no_type_font, Subtype, stream_dict, page_dict, font_dict, fontdesc, false, &ppdffont); if (code < 0) { - code = pdfi_open_font_substitute_file(ctx, font_dict, fontdesc, true, &fbuf, &fbuflen, &findex); + code = pdfi_load_font_file(ctx, no_type_font, Subtype, stream_dict, page_dict, font_dict, fontdesc, true, &ppdffont); substitute |= font_substitute; } - - if (code < 0) - goto exit; + break; } continue; } @@ -1802,6 +1890,91 @@ int pdfi_load_font_by_name_string(pdf_context *ctx, const byte *fontname, size_t return code; } + +int pdfi_font_create_widths(pdf_context *ctx, pdf_dict *fontdict, pdf_font *font, double scale) +{ + int code = 0; + pdf_obj *obj = NULL; + int i; + + font->Widths = NULL; + + if (font->FontDescriptor != NULL) { + code = pdfi_dict_knownget(ctx, font->FontDescriptor, "MissingWidth", &obj); + if (code > 0) { + if (pdfi_type_of(obj) == PDF_INT) { + font->MissingWidth = ((pdf_num *) obj)->value.i * scale; + } + else if (pdfi_type_of(obj) == PDF_REAL) { + font->MissingWidth = ((pdf_num *) obj)->value.d * scale; + } + else { + font->MissingWidth = 0; + } + pdfi_countdown(obj); + obj = NULL; + } + else { + font->MissingWidth = 0; + } + } + else { + font->MissingWidth = 1000.0 * scale; + } + + code = pdfi_dict_knownget_type(ctx, fontdict, "Widths", PDF_ARRAY, (pdf_obj **)&obj); + if (code > 0) { + if (pdfi_array_size((pdf_array *)obj) < font->LastChar - font->FirstChar + 1) { + code = gs_note_error(gs_error_rangecheck); + goto error; + } + + font->Widths = (double *)gs_alloc_bytes(OBJ_MEMORY(font), sizeof(double) * (font->LastChar - font->FirstChar + 1), "pdfi_font_create_widths(Widths)"); + if (font->Widths == NULL) { + code = gs_note_error(gs_error_VMerror); + goto error; + } + memset(font->Widths, 0x00, sizeof(double) * (font->LastChar - font->FirstChar + 1)); + for (i = 0; i < (font->LastChar - font->FirstChar + 1); i++) { + code = pdfi_array_get_number(ctx, (pdf_array *)obj, (uint64_t)i, &font->Widths[i]); + if (code < 0) + goto error; + font->Widths[i] *= scale; + } + } +error: + pdfi_countdown(obj); + if (code < 0) { + gs_free_object(OBJ_MEMORY(font), font->Widths, "pdfi_font_create_widths(Widths)"); + font->Widths = NULL; + } + return code; +} + +void pdfi_font_set_first_last_char(pdf_context *ctx, pdf_dict *fontdict, pdf_font *font) +{ + double f; + int code; + + if (fontdict == NULL) { + font->FirstChar = 0; + font->LastChar = 255; + } + else { + code = pdfi_dict_get_number(ctx, fontdict, "FirstChar", &f); + if (code < 0) + font->FirstChar = 0; + else + font->FirstChar = (int)(f < 0 ? 0 : f); + + code = pdfi_dict_get_number(ctx, fontdict, "LastChar", &f); + if (code < 0) + font->LastChar = 255; + else + font->LastChar = (int)(f > 255 ? 255 : f); + } +} + /* Patch or create a new XUID based on the existing UID/XUID, a simple hash of the input file name and the font dictionary object number. This allows improved glyph cache efficiency, also ensures pdfwrite understands diff --git a/pdf/pdf_font.h b/pdf/pdf_font.h index 9da05eb5a..a18541c6f 100644 --- a/pdf/pdf_font.h +++ b/pdf/pdf_font.h @@ -106,5 +106,7 @@ enum { }; int pdfi_get_cidfont_glyph_metrics(gs_font *pfont, gs_glyph cid, double *widths, bool vertical); +int pdfi_font_create_widths(pdf_context *ctx, pdf_dict *fontdict, pdf_font *font, double wscale); +void pdfi_font_set_first_last_char(pdf_context *ctx, pdf_dict *fontdict, pdf_font *font); int pdfi_font_generate_pseudo_XUID(pdf_context *ctx, pdf_dict *fontdict, gs_font_base *pfont); #endif diff --git a/pdf/pdf_font0.c b/pdf/pdf_font0.c index a88e7a93e..76a94c8a4 100644 --- a/pdf/pdf_font0.c +++ b/pdf/pdf_font0.c @@ -365,6 +365,7 @@ int pdfi_read_type0_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream dmprintf2(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", pdft0->type, pdft0->UID); #endif pdft0->refcnt = 1; + pdft0->filename = NULL; pdft0->object_num = font_dict->object_num; pdft0->generation_num = font_dict->generation_num; pdft0->indirect_num = font_dict->indirect_num; @@ -537,6 +538,8 @@ pdfi_free_font_type0(pdf_obj *font) pdfi_countdown(pdft0->Encoding); pdfi_countdown(pdft0->DescendantFonts); pdfi_countdown(pdft0->ToUnicode); + pdfi_countdown(pdft0->filename); + gs_free_object(OBJ_MEMORY(pdft0), pfont0->data.Encoding, "pdfi_free_font_type0(data.Encoding)"); /* We shouldn't need to free the fonts in the FDepVector, that should happen with DescendantFonts above. diff --git a/pdf/pdf_font1.c b/pdf/pdf_font1.c index 2c54ad312..aa0c9ac07 100644 --- a/pdf/pdf_font1.c +++ b/pdf/pdf_font1.c @@ -135,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; + 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; } @@ -515,7 +521,8 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic pdf_obj *tounicode = NULL; ps_font_interp_private fpriv = { 0 }; - (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; @@ -541,7 +548,7 @@ pdfi_read_type1_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dic 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; @@ -561,22 +568,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) { @@ -594,7 +605,7 @@ 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 && pdfi_type_of(tounicode) == PDF_STREAM) { pdf_cmap *tu = NULL; @@ -614,88 +625,22 @@ 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; - } - - 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)); + pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)t1f); /* 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); - if (t1f->FontDescriptor != NULL) { - code = pdfi_dict_knownget(ctx, t1f->FontDescriptor, "MissingWidth", &tmp); - if (code > 0) { - if (pdfi_type_of(tmp) == PDF_INT) { - t1f->MissingWidth = ((pdf_num *) tmp)->value.i * x_scale; - } - else if (pdfi_type_of(tmp) == PDF_REAL) { - t1f->MissingWidth = ((pdf_num *) tmp)->value.d * x_scale; - } - else { - t1f->MissingWidth = 0; - } - pdfi_countdown(tmp); - tmp = NULL; - } - else { - t1f->MissingWidth = 0; - } - } - else { - t1f->MissingWidth = 1000 * x_scale; - } - code = pdfi_dict_knownget_type(ctx, font_dict, "Widths", PDF_ARRAY, &tmp); - if (code > 0) { - int i; - 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; - } - - 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; + /* 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 ((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); @@ -740,7 +685,6 @@ 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; t1f->blenddesignpositions = fpriv.u.t1.blenddesignpositions; pdfi_countup(t1f->blenddesignpositions); @@ -780,20 +724,179 @@ 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; + (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->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) { + memcpy(dpfont1->key_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont1->key_name.size = ((pdf_name *)font->BaseFont)->length; + memcpy(dpfont1->font_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont1->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 / 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); + } + } + + 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; + 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(&font->pfont->UID)) + uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); + uid_set_invalid(&font->pfont->UID); + } + } + else { + pdfi_countdown(tmp); + tmp = NULL; + code = 0; + } + + 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; } - gs_free_object(ctx->memory, fpriv.u.t1.Subrs, "Subrs"); } + else { + tmp = NULL; + } + font->ToUnicode = tmp; + + code = gs_definefont(ctx->font_dir, (gs_font *) font->pfont); if (code < 0) { - pdfi_countdown(t1f); + 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; } @@ -801,7 +904,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"); @@ -816,20 +918,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; diff --git a/pdf/pdf_font1.h b/pdf/pdf_font1.h index 0385aafd5..5fd41afa0 100644 --- a/pdf/pdf_font1.h +++ b/pdf/pdf_font1.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019-2021 Artifex Software, Inc. +/* Copyright (C) 2019-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -21,6 +21,8 @@ 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 pdfi_free_font_type1(pdf_obj *font); +int pdfi_copy_type1_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont); + int pdfi_t1_global_glyph_code(const gs_font *pfont, gs_const_string *gstr, gs_glyph *pglyph); #endif diff --git a/pdf/pdf_font11.c b/pdf/pdf_font11.c index f4c002589..685ebe768 100644 --- a/pdf/pdf_font11.c +++ b/pdf/pdf_font11.c @@ -36,12 +36,12 @@ static int pdfi_cidtype2_string_proc(gs_font_type42 * pfont, ulong offset, uint pdf_cidfont_type2 *ttfont = (pdf_cidfont_type2 *)pfont->client_data; int code = 0; - if (offset + length > ttfont->sfnt.size) { + if (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; } @@ -51,8 +51,8 @@ static int pdfi_cidtype2_CIDMap_proc(gs_font_cid2 *pfont, gs_glyph glyph) pdf_cidfont_type2 *pdffont11 = (pdf_cidfont_type2 *)pfont->client_data; uint gid = glyph - GS_MIN_CID_GLYPH; - if (pdffont11->cidtogidmap.size > (gid << 1) + 1) { - gid = pdffont11->cidtogidmap.data[gid << 1] << 8 | pdffont11->cidtogidmap.data[(gid << 1) + 1]; + if (pdffont11->cidtogidmap != NULL && pdffont11->cidtogidmap->length > (gid << 1) + 1) { + gid = pdffont11->cidtogidmap->data[gid << 1] << 8 | pdffont11->cidtogidmap->data[(gid << 1) + 1]; } return (int)gid; @@ -69,8 +69,8 @@ static uint pdfi_cidtype2_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph) else { if (glyph < GS_MIN_GLYPH_INDEX) { gid = glyph - GS_MIN_CID_GLYPH; - if (pdffont11->cidtogidmap.size > 0) { - gid = pdffont11->cidtogidmap.data[gid << 1] << 8 | pdffont11->cidtogidmap.data[(gid << 1) + 1]; + if (pdffont11->cidtogidmap != NULL && pdffont11->cidtogidmap->length > 0) { + gid = pdffont11->cidtogidmap->data[gid << 1] << 8 | pdffont11->cidtogidmap->data[(gid << 1) + 1]; } } else { @@ -151,15 +151,15 @@ pdfi_cidtype2_enumerate_glyph(gs_font *font, int *pindex, if (*pindex <= 0) *pindex = 0; - if (pdffont11->cidtogidmap.size > 0) { + if (pdffont11->cidtogidmap != NULL && pdffont11->cidtogidmap->length > 0) { do { - *pglyph = pdffont11->cidtogidmap.data[(*pindex) << 1] << 8 | pdffont11->cidtogidmap.data[((*pindex) << 1) + 1]; + *pglyph = pdffont11->cidtogidmap->data[(*pindex) << 1] << 8 | pdffont11->cidtogidmap->data[((*pindex) << 1) + 1]; (*pindex)++; if (*pglyph == 0 && *pindex == 1) /* notdef - special case */ break; - } while (*pglyph == 0 && ((*pindex) << 1) < pdffont11->cidtogidmap.size); + } while (*pglyph == 0 && ((*pindex) << 1) < pdffont11->cidtogidmap->length); - if (((*pindex) << 1) >= pdffont11->cidtogidmap.size) { + if (((*pindex) << 1) >= pdffont11->cidtogidmap->length) { *pindex = 0; } else { @@ -312,9 +312,16 @@ int pdfi_read_cidtype2_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str font->FontDescriptor = (pdf_dict *)fontdesc; fontdesc = NULL; - /* Ownership of buf is now part of the font and managed via its lifetime */ - font->sfnt.data = buf; - font->sfnt.size = buflen; + code = pdfi_object_alloc(ctx, PDF_BUFFER, 0, (pdf_obj **)&font->sfnt); + if (code < 0) { + goto error; + } + pdfi_countup(font->sfnt); + code = pdfi_buffer_set_data((pdf_obj *)font->sfnt, buf, buflen); + if (code < 0) { + goto error; + } + 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 **)&obj); @@ -368,18 +375,26 @@ int pdfi_read_cidtype2_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str code = pdfi_dict_knownget(ctx, font_dict, "CIDToGIDMap", (pdf_obj **)&obj); if (code > 0) { - font->cidtogidmap.data = NULL; - font->cidtogidmap.size = 0; /* CIDToGIDMap can only be a stream or a name, and if it's a name it's only permitted to be "/Identity", so ignore it */ if (pdfi_type_of(obj) == PDF_STREAM) { + byte *d; int64_t sz; - code = pdfi_stream_to_buffer(ctx, (pdf_stream *)obj, &(font->cidtogidmap.data), &sz); + + code = pdfi_object_alloc(ctx, PDF_BUFFER, 0, (pdf_obj **)&font->cidtogidmap); + if (code < 0) { + goto error; + } + pdfi_countup(font->cidtogidmap); + code = pdfi_stream_to_buffer(ctx, (pdf_stream *)obj, &d, &sz); + if (code < 0) { + goto error; + } + code = pdfi_buffer_set_data((pdf_obj *)font->cidtogidmap, d, (int32_t)sz); if (code < 0) { goto error; } - font->cidtogidmap.size = (uint)sz; } pdfi_countdown(obj); obj = NULL; @@ -435,12 +450,12 @@ int pdfi_read_cidtype2_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str font->pfont->procs.glyph_info = pdfi_cidtype2_glyph_info; font->pfont->procs.enumerate_glyph = pdfi_cidtype2_enumerate_glyph; - if (font->cidtogidmap.size > 0) { + if (font->cidtogidmap != NULL) { gs_font_cid2 *cid2 = (gs_font_cid2 *)font->pfont; - if (cid2->data.numGlyphs > font->cidtogidmap.size >> 1) + if (cid2->data.numGlyphs > font->cidtogidmap->length >> 1) cid2->cidata.common.CIDCount = cid2->data.numGlyphs; else { - cid2->cidata.common.CIDCount = font->cidtogidmap.size >> 1; + cid2->cidata.common.CIDCount = font->cidtogidmap->length >> 1; } cid2->cidata.common.MaxCID = cid2->cidata.common.CIDCount; } @@ -462,7 +477,7 @@ int pdfi_read_cidtype2_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str 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; } @@ -487,9 +502,9 @@ int pdfi_free_font_cidtype2(pdf_obj *font) gs_font_cid2 *pfont = (gs_font_cid2 *)pdfcidf->pfont; gs_free_object(OBJ_MEMORY(pdfcidf), pfont, "pdfi_free_font_cidtype2(pfont)"); - gs_free_object(OBJ_MEMORY(pdfcidf), pdfcidf->cidtogidmap.data, "pdfi_free_font_cidtype2(cidtogidmap.data)"); - gs_free_object(OBJ_MEMORY(pdfcidf), pdfcidf->sfnt.data, "pdfi_free_font_cidtype2(sfnt.data)"); + pdfi_countdown(pdfcidf->cidtogidmap); + pdfi_countdown(pdfcidf->sfnt); pdfi_countdown(pdfcidf->PDF_font); pdfi_countdown(pdfcidf->BaseFont); pdfi_countdown(pdfcidf->FontDescriptor); @@ -498,6 +513,7 @@ int pdfi_free_font_cidtype2(pdf_obj *font) pdfi_countdown(pdfcidf->W2); pdfi_countdown(pdfcidf->registry); pdfi_countdown(pdfcidf->ordering); + pdfi_countdown(pdfcidf->filename); gs_free_object(OBJ_MEMORY(pdfcidf), pdfcidf, "pdfi_free_font_cidtype2(pdfcidf)"); return 0; diff --git a/pdf/pdf_font1C.c b/pdf/pdf_font1C.c index 7753bf2f7..6bebc5a2d 100644 --- a/pdf/pdf_font1C.c +++ b/pdf/pdf_font1C.c @@ -60,7 +60,7 @@ typedef struct pdfi_cff_font_priv_s { pdf_array *W; pdf_array *DW2; pdf_array *W2; - gs_string cidtogidmap; + pdf_buffer *cidtogidmap; pdf_array *FDArray; /* The registry and ordering strings in gs_font_cid0_data are just references to strings assumed to be managed be managed by the interpreter - so we have to stash @@ -301,9 +301,9 @@ pdfi_cff_enumerate_glyph(gs_font *pfont, int *pindex, } if (l > 0) { pdf_cidfont_type0 *cffcidfont = (pdf_cidfont_type0 *) pdffont; - if (cffcidfont->cidtogidmap.size > 0) { - for (j = (cffcidfont->cidtogidmap.size >> 1) - 1; j >= 0; j--) { - if (val == (cffcidfont->cidtogidmap.data[j << 1] << 8 | cffcidfont->cidtogidmap.data[(j << 1) + 1])) { + if (cffcidfont->cidtogidmap != NULL && cffcidfont->cidtogidmap->length > 0) { + for (j = (cffcidfont->cidtogidmap->length >> 1) - 1; j >= 0; j--) { + if (val == (cffcidfont->cidtogidmap->data[j << 1] << 8 | cffcidfont->cidtogidmap->data[(j << 1) + 1])) { val = j; break; } @@ -432,8 +432,8 @@ pdfi_cff_cid_glyph_data(gs_font_base *pbfont, gs_glyph glyph, gs_glyph_data_t *p else gid = glyph - GS_MIN_CID_GLYPH; - if (pdffont9->cidtogidmap.size > (gid << 1) + 1) { - gid = pdffont9->cidtogidmap.data[gid << 1] << 8 | pdffont9->cidtogidmap.data[(gid << 1) + 1]; + if (pdffont9->cidtogidmap != NULL && pdffont9->cidtogidmap->length > (gid << 1) + 1) { + gid = pdffont9->cidtogidmap->data[gid << 1] << 8 | pdffont9->cidtogidmap->data[(gid << 1) + 1]; } l = gs_snprintf(nbuf, sizeof(nbuf), "%" PRId64, gid); @@ -1874,9 +1874,8 @@ pdfi_read_cff(pdf_context *ctx, pdfi_gs_cff_font_priv *ptpriv) /* Check the subrs index */ pdffont->Subrs = NULL; - pdffont->subrs = fdptpriv.pdfcffpriv.subrs; - if (pdffont->subrs) { - p = pdfi_count_cff_index(pdffont->subrs, e, &pdffont->NumSubrs); + if (fdptpriv.pdfcffpriv.subrs) { + p = pdfi_count_cff_index(fdptpriv.pdfcffpriv.subrs, e, &pdffont->NumSubrs); if (!p) { pdffont->Subrs = NULL; pdffont->NumSubrs = 0; @@ -1892,7 +1891,7 @@ pdfi_read_cff(pdf_context *ctx, pdfi_gs_cff_font_priv *ptpriv) for (j = 0; j < pdffont->NumSubrs; j++) { pdf_string *subrstr; - p = pdfi_find_cff_index(pdffont->subrs, e, j, &strp, &stre); + p = pdfi_find_cff_index(fdptpriv.pdfcffpriv.subrs, e, j, &strp, &stre); if (p) { code = pdfi_object_alloc(ctx, PDF_STRING, stre - strp, (pdf_obj **) &subrstr); if (code >= 0) { @@ -2265,8 +2264,13 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, fbuflen = tlen; } - code = pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); - if (code < 0) { + if (font_dict != NULL) { + code = pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); + if (code < 0) { + fontdesc = NULL; + } + } + else { fontdesc = NULL; } @@ -2353,9 +2357,6 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, cffcid->PDF_font = font_dict; pdfi_countup(font_dict); - cffcid->cidtogidmap.data = NULL; - cffcid->cidtogidmap.size = 0; - pfont->client_data = cffcid; cffcid->object_num = font_dict->object_num; @@ -2379,23 +2380,35 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pfont->cidata.common.CIDCount = cffpriv.pdfcffpriv.cidcount; - cffcid->cidtogidmap.data = NULL; - cffcid->cidtogidmap.size = 0; + cffcid->cidtogidmap = NULL; code = pdfi_dict_knownget(ctx, font_dict, "CIDToGIDMap", (pdf_obj **) &obj); if (code > 0) { /* CIDToGIDMap can only be a stream or a name, and if it's a name it's only permitted to be "/Identity", so ignore it */ - int64_t size = 0; if (pdfi_type_of(obj) == PDF_STREAM) { - code = pdfi_stream_to_buffer(ctx, (pdf_stream *) obj, &(cffcid->cidtogidmap.data), &size); + byte *d; + int64_t sz; + + code = pdfi_object_alloc(ctx, PDF_BUFFER, 0, (pdf_obj **)&cffcid->cidtogidmap); + if (code < 0) { + goto error; + } + pdfi_countup(cffcid->cidtogidmap); + code = pdfi_stream_to_buffer(ctx, (pdf_stream *)obj, &d, &sz); + if (code < 0) { + goto error; + } + code = pdfi_buffer_set_data((pdf_obj *)cffcid->cidtogidmap, d, (int32_t)sz); + if (code < 0) { + goto error; + } } pdfi_countdown(obj); obj = NULL; - cffcid->cidtogidmap.size = size; - if (size > 0) { - pfont->cidata.common.CIDCount = size >> 1; + if (cffcid->cidtogidmap != NULL && cffcid->cidtogidmap->length > 0) { + pfont->cidata.common.CIDCount = cffcid->cidtogidmap->length >> 1; } } pfont->cidata.common.MaxCID = pfont->cidata.common.CIDCount - 1; @@ -2576,22 +2589,34 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, cffcid->PDF_font = font_dict; pdfi_countup(font_dict); - cffcid->cidtogidmap.data = NULL; - cffcid->cidtogidmap.size = 0; + cffcid->cidtogidmap = NULL; code = pdfi_dict_knownget(ctx, font_dict, "CIDToGIDMap", (pdf_obj **) &obj); if (code > 0) { + byte *d; + int64_t sz; /* CIDToGIDMap can only be a stream or a name, and if it's a name it's only permitted to be "/Identity", so ignore it */ - int64_t size = 0; if (pdfi_type_of(obj) == PDF_STREAM) { - code = pdfi_stream_to_buffer(ctx, (pdf_stream *) obj, &(cffcid->cidtogidmap.data), (int64_t *) &size); + code = pdfi_object_alloc(ctx, PDF_BUFFER, 0, (pdf_obj **)&cffcid->cidtogidmap); + if (code < 0) { + goto error; + } + pdfi_countup(cffcid->cidtogidmap); + code = pdfi_stream_to_buffer(ctx, (pdf_stream *)obj, &d, &sz); + if (code < 0) { + goto error; + } + code = pdfi_buffer_set_data((pdf_obj *)cffcid->cidtogidmap, d, (int32_t)sz); + if (code < 0) { + goto error; + } } pdfi_countdown(obj); obj = NULL; - cffcid->cidtogidmap.size = size; - if (size > 0) { - pfont->cidata.common.CIDCount = size >> 1; + + if (cffcid->cidtogidmap != NULL && cffcid->cidtogidmap->length > 0) { + pfont->cidata.common.CIDCount = cffcid->cidtogidmap->length >> 1; } } pfont->cidata.common.MaxCID = pfont->cidata.common.CIDCount - 1; @@ -2639,9 +2664,8 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_font_cff *cfffont; gs_font_type1 *pfont = NULL; pdf_obj *tounicode = NULL; - double x_scale; - code = pdfi_alloc_cff_font(ctx, &cfffont, font_dict->object_num, false); + code = pdfi_alloc_cff_font(ctx, &cfffont, font_dict != NULL ? font_dict->object_num : 0, false); pfont = (gs_font_type1 *) cfffont->pfont; ppdfont = (pdf_font *) cfffont; @@ -2653,12 +2677,15 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pfont->procs.glyph_info = pdfi_cff_glyph_info; - cfffont->object_num = font_dict->object_num; - cfffont->generation_num = font_dict->generation_num; - cfffont->indirect_num = font_dict->indirect_num; - cfffont->indirect_gen = font_dict->indirect_gen; + if (font_dict) { + cfffont->object_num = font_dict->object_num; + cfffont->generation_num = font_dict->generation_num; + cfffont->indirect_num = font_dict->indirect_num; + cfffont->indirect_gen = font_dict->indirect_gen; + + (void)pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &basefont); + } - (void)pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &basefont); cfffont->BaseFont = basefont; cfffont->Name = basefont; pdfi_countup(basefont); @@ -2696,89 +2723,21 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, cfffont->descflags |= 4; } - code = pdfi_dict_knownget_type(ctx, font_dict, "FirstChar", PDF_INT, &tmp); - if (code == 1) { - cfffont->FirstChar = ((pdf_num *) tmp)->value.i; - pdfi_countdown(tmp); - tmp = NULL; - } - else { - cfffont->FirstChar = 0; - } - code = pdfi_dict_knownget_type(ctx, font_dict, "LastChar", PDF_INT, &tmp); - if (code == 1) { - cfffont->LastChar = ((pdf_num *) tmp)->value.i; - pdfi_countdown(tmp); - tmp = NULL; - } - else { - cfffont->LastChar = 255; - } - - cfffont->fake_glyph_names = (gs_string *) gs_alloc_bytes(ctx->memory, cfffont->LastChar * sizeof(gs_string), "pdfi_read_cff_font: fake_glyph_names"); - if (!cfffont->fake_glyph_names) { - code = gs_note_error(gs_error_VMerror); - goto error; - } - memset(cfffont->fake_glyph_names, 0x00, cfffont->LastChar * sizeof(gs_string)); + pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)cfffont); /* 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(pfont->FontMatrix.xx, pfont->FontMatrix.xy); - if (cfffont->FontDescriptor != NULL) { - code = pdfi_dict_knownget(ctx, cfffont->FontDescriptor, "MissingWidth", &tmp); - if (code > 0) { - if (pdfi_type_of(tmp) == PDF_INT) { - cfffont->MissingWidth = ((pdf_num *) tmp)->value.i * x_scale; - } - else if (pdfi_type_of(tmp) == PDF_REAL) { - cfffont->MissingWidth = ((pdf_num *) tmp)->value.d * x_scale; - } - else { - cfffont->MissingWidth = 0; - } - pdfi_countdown(tmp); - tmp = NULL; - } - else { - cfffont->MissingWidth = 0; - } - } - else { - cfffont->MissingWidth = 1000 * x_scale; - } - - code = pdfi_dict_knownget_type(ctx, font_dict, "Widths", PDF_ARRAY, &tmp); - if (code > 0) { - int i; - int num_chars = cfffont->LastChar - cfffont->FirstChar + 1; - - if (num_chars != pdfi_array_size((pdf_array *) tmp)) { - pdfi_countdown(tmp); - code = gs_note_error(gs_error_rangecheck); - goto error; - } - - cfffont->Widths = (double *)gs_alloc_bytes(ctx->memory, sizeof(double) * num_chars, "Type 1C font Widths array"); - if (cfffont->Widths == NULL) { - code = gs_note_error(gs_error_VMerror); - goto error; - } - memset(cfffont->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, &cfffont->Widths[i]); - if (code < 0) - goto error; - cfffont->Widths[i] *= x_scale; - } + if (font_dict != NULL) { + /* ignore errors with widths... for now */ + (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)cfffont, (double)(0.001 / hypot(pfont->FontMatrix.xx, pfont->FontMatrix.xy))); } - pdfi_countdown(tmp); - tmp = NULL; - 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 ((cfffont->descflags & 4) != 0 && pdfi_type_of(tmp) == PDF_DICT) { code = pdfi_create_Encoding(ctx, tmp, (pdf_obj *)cffpriv.pdfcffpriv.Encoding, (pdf_obj **) &cfffont->Encoding); @@ -2810,7 +2769,7 @@ pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, cfffont->Encoding = cffpriv.pdfcffpriv.Encoding; cffpriv.pdfcffpriv.Encoding = NULL; } - 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 && pdfi_type_of(tounicode) == PDF_STREAM) { pdf_cmap *tu = NULL; @@ -2916,6 +2875,167 @@ pdfi_read_type1C_font(pdf_context *ctx, pdf_dict *font_dict, } int +pdfi_copy_cff_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont) +{ + int code = 0; + pdf_font_cff *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_cff_font(ctx, &font, font_dict->object_num, false); + 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; + dpfont1->notify_list.memory = NULL; + dpfont1->notify_list.first = NULL; + gs_notify_init(&dpfont1->notify_list, dpfont1->memory); + + memcpy(font, spdffont, sizeof(pdf_font_type1)); + font->refcnt = 1; + font->pfont = (gs_font_base *)dpfont1; + dpfont1->client_data = (void *)font; + font->filename = NULL; + + 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->Name); + pdfi_countup(font->CharStrings); + pdfi_countup(font->Subrs); + pdfi_countup(font->GlobalSubrs); + + if (font->BaseFont != NULL && ((pdf_name *)font->BaseFont)->length <= gs_font_name_max) { + memcpy(dpfont1->key_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont1->key_name.size = ((pdf_name *)font->BaseFont)->length; + memcpy(dpfont1->font_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); + dpfont1->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 / 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); + } + } + + 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; + 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(&font->pfont->UID)) + uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); + uid_set_invalid(&font->pfont->UID); + } + } + else { + pdfi_countdown(tmp); + tmp = NULL; + code = 0; + } + + 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_cff(pdf_obj *font) { pdf_font_cff *pdfontcff = (pdf_font_cff *) font; @@ -2931,8 +3051,8 @@ pdfi_free_font_cff(pdf_obj *font) pdfi_countdown(pdfontcff->GlobalSubrs); pdfi_countdown(pdfontcff->Encoding); pdfi_countdown(pdfontcff->ToUnicode); + pdfi_countdown(pdfontcff->filename); - gs_free_object(OBJ_MEMORY(font), pdfontcff->fake_glyph_names, "Type 2 fake_glyph_names"); gs_free_object(OBJ_MEMORY(font), pdfontcff->Widths, "Type 2 fontWidths"); gs_free_object(OBJ_MEMORY(font), pdfontcff, "pdfi_free_font_cff(pbfont)"); @@ -2966,8 +3086,9 @@ pdfi_free_font_cidtype0(pdf_obj *font) pdfi_countdown(pdfont0->FDArray); pdfi_countdown(pdfont0->registry); pdfi_countdown(pdfont0->ordering); + pdfi_countdown(pdfont0->cidtogidmap); + pdfi_countdown(pdfont0->filename); - gs_free_object(OBJ_MEMORY(font), pdfont0->cidtogidmap.data, "pdfi_free_font_cff(cidtogidmap.data)"); gs_free_object(OBJ_MEMORY(font), pdfont0, "pdfi_free_font_cff(pbfont)"); return 0; diff --git a/pdf/pdf_font1C.h b/pdf/pdf_font1C.h index e02b63424..ea8c7084f 100644 --- a/pdf/pdf_font1C.h +++ b/pdf/pdf_font1C.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019-2021 Artifex Software, Inc. +/* Copyright (C) 2019-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -19,10 +19,11 @@ #define PDF_TYPE1C_FONT int pdfi_read_type1C_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_font **ppdffont); int pdfi_cff_global_glyph_code(const gs_font *pfont, gs_const_string *gstr, gs_glyph *pglyph); -int pdfi_free_font_cff(pdf_obj *font); int pdfi_read_cff_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, byte *pfbuf, int64_t fbuflen, bool forcecid, pdf_font **ppdffont); +int pdfi_copy_cff_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont); +int pdfi_free_font_cff(pdf_obj *font); int pdfi_free_font_cidtype0(pdf_obj *font); #endif diff --git a/pdf/pdf_font3.c b/pdf/pdf_font3.c index 0ca1431c0..708e7658e 100644 --- a/pdf/pdf_font3.c +++ b/pdf/pdf_font3.c @@ -223,6 +223,8 @@ int pdfi_free_font_type3(pdf_obj *font) pdfi_countdown(t3font->CharProcs); pdfi_countdown(t3font->Encoding); pdfi_countdown(t3font->ToUnicode); + pdfi_countdown(t3font->filename); /* Should never exist, but just in case */ + gs_free_object(OBJ_MEMORY(font), font, "Free type 3 font"); return 0; } @@ -230,10 +232,9 @@ int pdfi_free_font_type3(pdf_obj *font) int pdfi_read_type3_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_font **ppdffont) { - int code = 0, i, num_chars = 0; + int code = 0; pdf_font_type3 *font = NULL; pdf_obj *obj = NULL; - double f; pdf_obj *tounicode = NULL; *ppdffont = NULL; @@ -271,67 +272,15 @@ int pdfi_read_type3_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream if (code < 0) goto font3_error; - code = pdfi_dict_get_number(ctx, font_dict, "FirstChar", &f); - if (code < 0) - goto font3_error; - font->FirstChar = (int)f; - code = pdfi_dict_get_number(ctx, font_dict, "LastChar", &f); - if (code < 0) - goto font3_error; - font->LastChar = (int)f; - - num_chars = (font->LastChar - font->FirstChar) + 1; code = pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, (pdf_obj **)&font->FontDescriptor); if (code < 0) goto font3_error; - if (font->FontDescriptor != NULL) { - code = pdfi_dict_knownget(ctx, font->FontDescriptor, "MissingWidth", &obj); - if (code > 0) { - if (pdfi_type_of(obj) == PDF_INT) { - font->MissingWidth = (double)((pdf_num *) obj)->value.i; - } - else if (pdfi_type_of(obj) == PDF_REAL) { - font->MissingWidth = ((pdf_num *) obj)->value.d; - } - else { - font->MissingWidth = 0; - } - pdfi_countdown(obj); - obj = NULL; - } - else { - font->MissingWidth = 0; - } - } - else { - font->MissingWidth = 1000; - } - - code = pdfi_dict_knownget_type(ctx, font_dict, "Widths", PDF_ARRAY, (pdf_obj **)&obj); - if (code < 0) - goto font3_error; - if (code > 0) { - if (num_chars != pdfi_array_size((pdf_array *)obj)) { - code = gs_note_error(gs_error_rangecheck); - goto font3_error; - } + pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)font); + /* ignore errors with widths... for now */ + (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)font, 1.0); - font->Widths = (double *)gs_alloc_bytes(ctx->memory, sizeof(double) * num_chars, "type 3 font Widths array"); - if (font->Widths == NULL) { - code = gs_note_error(gs_error_VMerror); - goto font3_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 font3_error; - } - } - pdfi_countdown(obj); - obj = NULL; code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj); if (code < 0) diff --git a/pdf/pdf_fontTT.c b/pdf/pdf_fontTT.c index 628c01033..661c182a2 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,107 +370,63 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str *ppdffont = NULL; - (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 ((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) { - f = 0; - 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) { - f = 255; - 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; - } - font->BaseFont = basefont; - basefont = NULL; - font->PDF_font = font_dict; - pdfi_countup(font_dict); - - if (font->FontDescriptor != NULL) { - code = pdfi_dict_knownget(ctx, font->FontDescriptor, "MissingWidth", &obj); + if (font_dict != NULL) { + code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, (pdf_obj **)&basefont); if (code > 0) { - if (pdfi_type_of(obj) == PDF_INT) { - font->MissingWidth = ((pdf_num *) obj)->value.i / 1000.0; - } - else if (pdfi_type_of(obj) == PDF_REAL) { - font->MissingWidth = ((pdf_num *) obj)->value.d / 1000.0; - } - else { - font->MissingWidth = 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; } - else { - font->MissingWidth = 0; - } - } - else { - font->MissingWidth = 1.0; } + 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) { - 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.0; - } - } - 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 && pdfi_type_of(tounicode) == PDF_STREAM) { pdf_cmap *tu = NULL; @@ -500,7 +455,11 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str descflags = 0; } - code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj); + if (font_dict != NULL) + code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj); + else + code = gs_error_undefined; + if (code < 0) { static const char encstr[] = "WinAnsiEncoding"; code = pdfi_name_alloc(ctx, (byte *)encstr, strlen(encstr), (pdf_obj **)&obj); @@ -532,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; @@ -626,7 +578,7 @@ int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *str 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; } @@ -648,30 +600,177 @@ 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); + 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; + 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(&font->pfont->UID)) + uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); + uid_set_invalid(&font->pfont->UID); + } + } + else { + pdfi_countdown(tmp); + tmp = NULL; + code = 0; + } + + 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; diff --git a/pdf/pdf_fontTT.h b/pdf/pdf_fontTT.h index 90e4086ea..14932f665 100644 --- a/pdf/pdf_fontTT.h +++ b/pdf/pdf_fontTT.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019-2021 Artifex Software, Inc. +/* Copyright (C) 2019-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -19,6 +19,7 @@ #define PDF_TRUETYPE_FONT 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); +int pdfi_copy_truetype_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont); int pdfi_free_font_truetype(pdf_obj *font); #endif diff --git a/pdf/pdf_font_types.h b/pdf/pdf_font_types.h index 7eb28d15b..f29088f59 100644 --- a/pdf/pdf_font_types.h +++ b/pdf/pdf_font_types.h @@ -84,8 +84,9 @@ typedef enum pdf_font_type_e { pdf_dict *PDF_font; /* The original font dictionary from the PDF file */\ pdf_obj *BaseFont; /* Should be a name object, but best allow for strings as well */\ pdf_dict *FontDescriptor; /* For PDF up to 1.4 this may be absent for the base 14 */ \ - int64_t descflags - + int64_t descflags; \ + pdf_obj *ToUnicode; /* Name or stream (technically should be a stream, but we've seen Identity names */ \ + pdf_string *filename /* If we read this from disk, this is the file it came from */ #define pdf_font_common \ pdf_font_base;\ @@ -93,10 +94,8 @@ typedef enum pdf_font_type_e { unsigned int FirstChar; /* For PDF up to 1.4 this may be absent for the base 14 */\ unsigned int LastChar; /* For PDF up to 1.4 this may be absent for the base 14 */\ double MissingWidth; \ - double *Widths; /* For PDF up to 1.4 this may be absent for the base 14 */\ - pdf_array *Encoding; /* Array built from name or dictionary */\ - pdf_obj *ToUnicode; /* Name or stream (technically should be a stream, but we've seen Identity names */ \ - gs_string *fake_glyph_names /* For when we encounter a glyph not in the Encoding */ + double *Widths; /* For PDF up to 1.4 this may be absent for the base 14 */\ + pdf_array *Encoding /* Array built from name or dictionary */\ /* The registry and ordering strings in gs_font_cid0_data are just references to @@ -113,7 +112,7 @@ typedef enum pdf_font_type_e { pdf_string *registry; \ pdf_string *ordering; \ int supplement; \ - gs_string cidtogidmap; \ + pdf_buffer *cidtogidmap; \ bool substitute; /* We need to know what a CIDFont is a substitute */ \ font_proc_glyph_info((*orig_glyph_info)) @@ -148,16 +147,14 @@ typedef struct pdf_font_type0_s { pdf_obj *Encoding; /* CMap */ pdf_array *DescendantFonts; /* A single element array specifying the CIDFont dictionary */ - pdf_obj *ToUnicode; /* Name or stream (technically shoudl be a stream, but we've seen Identity names */ pdfi_cid_decoding_t *decoding; /* Used when substituting a non-Identity CIDFont */ pdfi_cid_subst_nwp_table_t *substnwp; /* Also used for CIDFont substitions */ } pdf_font_type0; typedef struct pdf_font_type1_s { pdf_font_common; - gs_string *Subrs; + pdf_array *Subrs; pdf_dict *CharStrings; - int NumSubrs; /* Multiple Master Support - weightvector is stored in gs_font_type1 */ pdf_array *blenddesignpositions; pdf_array *blenddesignmap; @@ -172,11 +169,6 @@ typedef struct pdf_font_cff_s { pdf_array *GlobalSubrs; int NumGlobalSubrs; pdf_dict *CharStrings; - byte *cffdata; - byte *cffend; - byte *gsubrs; - byte *subrs; - byte *charstrings; int ncharstrings; } pdf_font_cff; @@ -198,7 +190,7 @@ typedef enum { typedef struct pdf_font_truetype_s { pdf_font_common; - gs_string sfnt; + pdf_buffer *sfnt; pdfi_truetype_cmap cmap; } pdf_font_truetype; @@ -213,11 +205,6 @@ typedef struct pdf_cidfont_type0_s { pdf_array *GlobalSubrs; int NumGlobalSubrs; pdf_dict *CharStrings; - byte *cffdata; - byte *cffend; - byte *gsubrs; - byte *subrs; - byte *charstrings; int ncharstrings; pdf_array *FDArray; int cidcount; @@ -226,7 +213,7 @@ typedef struct pdf_cidfont_type0_s { typedef struct pdf_cidfont_type2_s { pdf_cid_font_common; - gs_string sfnt; + pdf_buffer *sfnt; } pdf_cidfont_type2; #endif diff --git a/pdf/pdf_fontps.c b/pdf/pdf_fontps.c index 45ae23bd6..c7488c2e4 100644 --- a/pdf/pdf_fontps.c +++ b/pdf/pdf_fontps.c @@ -1045,21 +1045,14 @@ ps_font_array_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) !memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("Subrs"))) { if (s->cur[0].val.i > 0) { - if (priv->u.t1.Subrs != NULL) { - int i; - for (i = 0; i < priv->u.t1.NumSubrs; i++) { - gs_free_object(mem, priv->u.t1.Subrs[i].data, "ps_font_array_func(Subrs[i])"); - } - gs_free_object(mem, priv->u.t1.Subrs, "ps_font_array_func(Subrs)"); - } + pdfi_countdown(priv->u.t1.Subrs); - priv->u.t1.Subrs = (gs_string *) gs_alloc_bytes(mem, s->cur[0].val.i *sizeof(gs_string), "ps_font_array_func(Subrs)"); - if (priv->u.t1.Subrs == NULL) { - return_error(gs_error_VMerror); + pdfi_object_alloc(s->pdfi_ctx, PDF_ARRAY, (unsigned int)s->cur[0].val.i, (pdf_obj **)&priv->u.t1.Subrs); + if (code < 0) { + return code; } - memset(priv->u.t1.Subrs, 0x00, s->cur[0].val.i * sizeof(gs_string)); + pdfi_countup(priv->u.t1.Subrs); } - priv->u.t1.NumSubrs = s->cur[0].val.i; code = pdf_ps_stack_pop(s, 1); } else if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME) && @@ -1162,14 +1155,19 @@ pdf_ps_RD_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) size = s->cur[0].val.i; buf++; if (buf + size < bufend) { - priv->u.t1.Subrs[inx].data = - gs_alloc_bytes(mem, size, "pdf_ps_RD_oper_func(subr string)"); - if (priv->u.t1.Subrs[inx].data == NULL) { - (void)pdf_ps_stack_pop(s, 2); - return_error(gs_error_VMerror); + pdf_string *subr_str; + + code = pdfi_object_alloc(s->pdfi_ctx, PDF_STRING, (unsigned int)size, (pdf_obj **)&subr_str); + if (code < 0) { + return code; + } + memcpy(subr_str->data, buf, size); + pdfi_countup(subr_str); + code = pdfi_array_put(s->pdfi_ctx, priv->u.t1.Subrs, inx, (pdf_obj *)subr_str); + if (code < 0) { + pdfi_countdown(subr_str); + return code; } - memcpy(priv->u.t1.Subrs[inx].data, buf, size); - priv->u.t1.Subrs[inx].size = size; } } } diff --git a/pdf/pdf_obj.c b/pdf/pdf_obj.c index a0607ebb1..aae9401bf 100644 --- a/pdf/pdf_obj.c +++ b/pdf/pdf_obj.c @@ -36,6 +36,7 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pdf_obj **obj) { int bytes = 0; + int code = 0; switch(type) { case PDF_ARRAY_MARK: @@ -51,6 +52,9 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd case PDF_NAME: bytes = sizeof(pdf_string) + size - PDF_NAME_DECLARED_LENGTH; break; + case PDF_BUFFER: + bytes = sizeof(pdf_buffer); + break; case PDF_ARRAY: bytes = sizeof(pdf_array); break; @@ -75,11 +79,14 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd case PDF_NULL: case PDF_BOOL: default: - return_error(gs_error_typecheck); + code = gs_note_error(gs_error_typecheck); + goto error_out; } *obj = (pdf_obj *)gs_alloc_bytes(ctx->memory, bytes, "pdfi_object_alloc"); - if (*obj == NULL) - return_error(gs_error_VMerror); + if (*obj == NULL) { + code = gs_note_error(gs_error_VMerror); + goto error_out; + } memset(*obj, 0x00, bytes); (*obj)->ctx = ctx; @@ -106,6 +113,24 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd case PDF_NAME: ((pdf_string *)*obj)->length = size; break; + case PDF_BUFFER: + { + pdf_buffer *b = (pdf_buffer *)*obj; + /* NOTE: size can be 0 if the caller wants to allocate the data area itself + */ + if (size > 0) { + b->data = gs_alloc_bytes(ctx->memory, size, "pdfi_object_alloc"); + if (b->data == NULL) { + code = gs_note_error(gs_error_VMerror); + goto error_out; + } + } + else { + b->data = NULL; + } + b->length = size; + } + break; case PDF_ARRAY: { pdf_obj **values = NULL; @@ -114,10 +139,8 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd if (size > 0) { values = (pdf_obj **)gs_alloc_bytes(ctx->memory, size * sizeof(pdf_obj *), "pdfi_object_alloc"); if (values == NULL) { - gs_free_object(ctx->memory, *obj, "pdfi_object_alloc"); - gs_free_object(ctx->memory, values, "pdfi_object_alloc"); - *obj = NULL; - return_error(gs_error_VMerror); + code = gs_note_error(gs_error_VMerror); + goto error_out; } ((pdf_array *)*obj)->values = values; memset(((pdf_array *)*obj)->values, 0x00, size * sizeof(pdf_obj *)); @@ -132,9 +155,8 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd if (size > 0) { entries = (pdf_dict_entry *)gs_alloc_bytes(ctx->memory, size * sizeof(pdf_dict_entry), "pdfi_object_alloc"); if (entries == NULL) { - gs_free_object(ctx->memory, *obj, "pdfi_object_alloc"); - *obj = NULL; - return_error(gs_error_VMerror); + code = gs_note_error(gs_error_VMerror); + goto error_out; } ((pdf_dict *)*obj)->list = entries; memset(((pdf_dict *)*obj)->list, 0x00, size * sizeof(pdf_dict_entry)); @@ -154,6 +176,10 @@ int pdfi_object_alloc(pdf_context *ctx, pdf_obj_type type, unsigned int size, pd dmprintf2(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", (*obj)->type, (*obj)->UID); #endif return 0; +error_out: + gs_free_object(ctx->memory, *obj, "pdfi_object_alloc"); + *obj = NULL; + return code; } /* Create a PDF number object from a numeric value. Attempts to create @@ -221,6 +247,14 @@ static void pdfi_free_stream(pdf_obj *o) gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_stream"); } +static void pdfi_free_buffer(pdf_obj *o) +{ + pdf_buffer *b = (pdf_buffer *)o; + + gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_free_buffer(data)"); + gs_free_object(OBJ_MEMORY(o), o, "pdfi_free_buffer"); +} + void pdfi_free_object(pdf_obj *o) { if (o == NULL) @@ -240,6 +274,9 @@ void pdfi_free_object(pdf_obj *o) case PDF_NAME: pdfi_free_namestring(o); break; + case PDF_BUFFER: + pdfi_free_buffer(o); + break; case PDF_ARRAY: pdfi_free_array(o); break; diff --git a/pdf/pdf_obj.h b/pdf/pdf_obj.h index f058a872b..eb512db96 100644 --- a/pdf/pdf_obj.h +++ b/pdf/pdf_obj.h @@ -93,4 +93,22 @@ pdfi_obj_to_int(pdf_context *ctx, pdf_obj *obj, int64_t *i) return 0; } +/* NOTE: the buffer object takes ownership of "data" */ +static inline int +pdfi_buffer_set_data(pdf_obj *o, byte *data, int32_t length) +{ + pdf_buffer *b = (pdf_buffer *)o; + if (pdfi_type_of(b) != PDF_BUFFER) { + return_error(gs_error_typecheck); + } + + if (b->data) { + gs_free_object(OBJ_MEMORY(b), b->data, "pdfi_buffer_set_data(data)"); + } + b->data = data; + b->length = length; + return 0; +} + + #endif diff --git a/pdf/pdf_types.h b/pdf/pdf_types.h index 6528be7ff..6f78dde7f 100644 --- a/pdf/pdf_types.h +++ b/pdf/pdf_types.h @@ -58,6 +58,7 @@ typedef enum pdf_obj_type_e { PDF_DICT_MARK = '<', PDF_PROC_MARK = '{', PDF_CMAP = 'C', + PDF_BUFFER = 'B', /* Lastly, for the benefit of duplicate colour space identification, we store either * a name for a colour space, or if there is no name, the context (we can get the * context from the name object if there is one). We need to be able to tell if a @@ -137,6 +138,16 @@ typedef struct pdf_name_s { unsigned char data[PDF_NAME_DECLARED_LENGTH]; } pdf_name; +/* For storing arbitrary byte arrays where the length may be + greater than PDF_NAME_DECLARED_LENGTH - prevents static + alalysis tools complaining if we just used pdf_string + */ +typedef struct pdf_buffer_s { + pdf_obj_common; + uint32_t length; + unsigned char *data; +} pdf_buffer; + typedef enum pdf_key_e { #include "pdf_tokens.h" TOKEN__LAST_KEY, |