diff options
-rw-r--r-- | Resource/Init/gs_fonts.ps | 7 | ||||
-rw-r--r-- | pdf/ghostpdf.c | 58 | ||||
-rw-r--r-- | pdf/ghostpdf.h | 4 | ||||
-rw-r--r-- | pdf/pdf_fmap.c | 90 | ||||
-rw-r--r-- | pdf/pdf_fmap.h | 2 | ||||
-rw-r--r-- | pdf/pdf_font.c | 53 | ||||
-rw-r--r-- | pdf/pdftop.c | 8 | ||||
-rw-r--r-- | psi/zpdfops.c | 55 |
8 files changed, 220 insertions, 57 deletions
diff --git a/Resource/Init/gs_fonts.ps b/Resource/Init/gs_fonts.ps index f1e26b093..aaee616f4 100644 --- a/Resource/Init/gs_fonts.ps +++ b/Resource/Init/gs_fonts.ps @@ -429,6 +429,11 @@ FONTPATH %END FONTPATH +/FONTMAP where +{ + dup /FONTMAP get /FONTMAP exch [ exch //.pathlist exec] put +} if + % Try to enumerate native fonts registered with the os % and add them to the fontmap. This relies on a custom % operator which calls platform-specific C code. It @@ -1315,7 +1320,7 @@ FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined /.loadinitialfonts { NOFONTMAP not { /FONTMAP where - { pop [ FONTMAP //.pathlist exec] + { pop FONTMAP { dup VMDEBUG findlibfile { exch pop //.loadFontmap exec } { /undefinedfilename signalerror } diff --git a/pdf/ghostpdf.c b/pdf/ghostpdf.c index e71d39649..0d703d261 100644 --- a/pdf/ghostpdf.c +++ b/pdf/ghostpdf.c @@ -1363,7 +1363,7 @@ static size_t pdfi_grdir_path_string_match(const byte *str, size_t sl0, byte *pa int pdfi_add_paths_to_search_paths(pdf_context *ctx, const char *ppath, int l, bool fontpath) { - int i, slen, npaths = (l > 0); + int i, slen, npaths = (l > 0) ? 1 : 0; const char *p = ppath; char *ps; const char *pe = p + l + 1; @@ -1503,6 +1503,61 @@ static void pdfi_free_search_paths(pdf_context *ctx) gs_free_object(ctx->memory, (byte *)ctx->search_paths.font_paths, "array of font paths"); } +static void pdfi_free_fontmapfiles(pdf_context *ctx) +{ + int i; + for (i = 0; i < ctx->num_fontmapfiles; i++) { + gs_free_object(ctx->memory, ctx->fontmapfiles[i].data, "fontmapfiles string body"); + } + gs_free_object(ctx->memory, ctx->fontmapfiles, "fontmapfiles array"); +} + +/* The fontmap file list doesn't extend, later settings in the command line override earlier ones + (Unlike the "-I" search paths above). + */ +int pdfi_add_fontmapfiles(pdf_context *ctx, const char *ppath, int l) +{ + int i, nfilenames = (l > 0) ? 1 : 0; + const char *p = ppath; + char *ps; + const char *pe = p + l + 1; + int code = 0; + + pdfi_free_fontmapfiles(ctx); + + for (ps = (char *)p; ps < pe; ps++) { + if (*ps == gp_file_name_list_separator) + nfilenames++; + } + if (nfilenames > 0) { + ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string) * nfilenames, "array of fontmap files"); + if (ctx->fontmapfiles == NULL) { + return_error(gs_error_VMerror); + } + else { + memset(ctx->fontmapfiles, 0x00, sizeof(gs_string) * nfilenames); + ctx->num_fontmapfiles = nfilenames; + + for (i = 0; i < nfilenames; i++) { + for (ps = (char *)p; ps < pe; ps++) { + if (*ps == gp_file_name_list_separator) + break; + } + ctx->fontmapfiles[i].data = gs_alloc_bytes(ctx->memory, ps - p, "fontmap file name body"); + if (ctx->fontmapfiles[i].data == NULL) { + code = gs_note_error(gs_error_VMerror); + goto done; + } + memcpy(ctx->fontmapfiles[i].data, p, ps - p); + ctx->fontmapfiles[i].size = ps - p; + p = ps + 1; + } + } + } +done: + return code; +} + /***********************************************************************************/ /* Highest level functions. The context we create here is returned to the 'PL' */ /* implementation, in future we plan to return it to PostScript by wrapping a */ @@ -1900,6 +1955,7 @@ int pdfi_free_context(pdf_context *ctx) } pdfi_free_search_paths(ctx); + pdfi_free_fontmapfiles(ctx); gs_free_object(ctx->memory, ctx, "pdfi_free_context"); #if PDFI_LEAK_CHECK diff --git a/pdf/ghostpdf.h b/pdf/ghostpdf.h index 5dd7c70bf..0ba1d8884 100644 --- a/pdf/ghostpdf.h +++ b/pdf/ghostpdf.h @@ -479,6 +479,9 @@ typedef struct pdf_context_s /* A name table :-( */ pdfi_name_entry_t *name_table; + gs_string *fontmapfiles; + int num_fontmapfiles; + search_paths_t search_paths; pdf_dict *pdffontmap; pdf_dict *pdfnativefontmap; /* Explicit mappings take precedence, hence we need separate dictionaries */ @@ -511,6 +514,7 @@ typedef struct pdf_context_s int pdfi_add_paths_to_search_paths(pdf_context *ctx, const char *ppath, int l, bool fontpath); int pdfi_add_initial_paths_to_search_paths(pdf_context *ctx, const char *ppath, int l); +int pdfi_add_fontmapfiles(pdf_context *ctx, const char *ppath, int l); pdf_context *pdfi_create_context(gs_memory_t *pmem); int pdfi_clear_context(pdf_context *ctx); diff --git a/pdf/pdf_fmap.c b/pdf/pdf_fmap.c index 6420910f9..71cd2480c 100644 --- a/pdf/pdf_fmap.c +++ b/pdf/pdf_fmap.c @@ -33,7 +33,7 @@ typedef struct const char *mappedname; } pdfi_custom_fmap_entry; -pdfi_custom_fmap_entry pdfi_custom_fmap_enties[] = +pdfi_custom_fmap_entry pdfi_custom_fmap_entries[] = { {"Helv", "Helvetica"}, {NULL, NULL} @@ -103,35 +103,62 @@ pdf_fontmap_open_file(pdf_context *ctx, const char *mapfilename, byte **buf, int } static int -pdf_make_fontmap(pdf_context *ctx, const char *fmapname, bool cidfmap) +pdf_make_fontmap(pdf_context *ctx, const char *default_fmapname, int cidfmap) { byte *fmapbuf = NULL; int code, fmapbuflen; pdf_c_stream *fmapstr = NULL; pdf_stream fakedict = {0}; - pdfi_custom_fmap_entry *pcfe = pdfi_custom_fmap_enties; - int i; - + pdfi_custom_fmap_entry *pcfe = pdfi_custom_fmap_entries; + int i, j = 0; + char fmapname[gp_file_name_sizeof]; pdf_c_stream fakemainstream = {0}; + int stacksize = pdfi_count_stack(ctx); - code = pdf_fontmap_open_file(ctx, (const char *)fmapname, &fmapbuf, &fmapbuflen); + strncpy(fmapname, default_fmapname, strlen(default_fmapname) + 1); + + code = pdfi_mark_stack(ctx, PDF_DICT_MARK); if (code < 0) - return code; + goto done; - code = pdfi_open_memory_stream_from_memory(ctx, fmapbuflen, fmapbuf, &fmapstr, true); - if (code >= 0) { - int stacksize = pdfi_count_stack(ctx); + do { + if (j < ctx->num_fontmapfiles) { + memcpy(fmapname, ctx->fontmapfiles[j].data, ctx->fontmapfiles[j].size); + fmapname[ctx->fontmapfiles[j].size] = '\0'; + } - if (ctx->main_stream == NULL) { - ctx->main_stream = &fakemainstream; + code = pdf_fontmap_open_file(ctx, (const char *)fmapname, &fmapbuf, &fmapbuflen); + if (code < 0) { + if (ctx->args.QUIET != true) { + (void)outwrite(ctx->memory, "Warning: ", 9); + if (cidfmap) + (void)outwrite(ctx->memory, "cidfmap file ", 13); + else + (void)outwrite(ctx->memory, "Fontmap file \"", 14); + (void)outwrite(ctx->memory, fmapname, strlen(fmapname)); + (void)outwrite(ctx->memory, "\" not found.\n", 13); + code = 0; + } } - code = pdfi_mark_stack(ctx, PDF_DICT_MARK); - if (code < 0) - goto done; - code = pdfi_interpret_content_stream(ctx, fmapstr, &fakedict, NULL); - if (ctx->main_stream == &fakemainstream) { - ctx->main_stream = NULL; + else { + code = pdfi_open_memory_stream_from_memory(ctx, fmapbuflen, fmapbuf, &fmapstr, true); + if (code >= 0) { + + if (ctx->main_stream == NULL) { + ctx->main_stream = &fakemainstream; + } + + code = pdfi_interpret_content_stream(ctx, fmapstr, &fakedict, NULL); + if (ctx->main_stream == &fakemainstream) { + ctx->main_stream = NULL; + } + gs_free_object(ctx->memory, fmapbuf, "pdf_make_fontmap(fmapbuf)"); + } } + j++; + } while(j < ctx->num_fontmapfiles && cidfmap == false && code >= 0); + + if (code >= 0) { if (code >= 0 && pdfi_count_stack(ctx) > stacksize) { code = pdfi_dict_from_stack(ctx, 0, 0, true); if (code < 0) @@ -173,7 +200,22 @@ pdf_make_fontmap(pdf_context *ctx, const char *fmapname, bool cidfmap) } } done: - gs_free_object(ctx->memory, fmapbuf, "pdf_make_fontmap(fmapbuf)"); + /* We always want to leave here with a valid map dictionary + even if it's empty + */ + if (cidfmap == true) { + if (ctx->pdfcidfmap == NULL) { + code = pdfi_dict_alloc(ctx, 0, &ctx->pdfcidfmap); + pdfi_countup(ctx->pdfcidfmap); + } + } + else { + if (ctx->pdffontmap == NULL) { + code = pdfi_dict_alloc(ctx, 0, &ctx->pdffontmap); + pdfi_countup(ctx->pdffontmap); + } + } + pdfi_clearstack(ctx); return code; } @@ -536,7 +578,7 @@ static bool font_scan_skip_file(char *fname) static int pdfi_generate_native_fontmap(pdf_context *ctx) { file_enum *fe; - int i, j; + int i; char *patrn= NULL; char *result = NULL; char *working = NULL; @@ -688,7 +730,7 @@ static int pdfi_generate_native_fontmap(pdf_context *ctx) int pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname, int *findex) { - int code, code2 = gs_error_undefined; + int code; pdf_obj *mname; *findex = -1; @@ -714,7 +756,6 @@ pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname, in subsitute name -> file name So we want to loop until we no more hits. */ - code2 = 0; while(1) { pdf_obj *mname2; code = pdfi_dict_get_by_key(ctx, ctx->pdffontmap, (pdf_name *)mname, &mname2); @@ -728,7 +769,6 @@ pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname, in code = pdfi_dict_get_by_key(ctx, ctx->pdfnativefontmap, fname, &record); if (code < 0) return code; - code2 = 0; if (record->type == PDF_STRING) { mname = record; } @@ -746,11 +786,11 @@ pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname, in } } - if (mname->type == PDF_STRING && pdfi_fmap_file_exists(ctx, (pdf_string *)mname)) { + if (mname != NULL && mname->type == PDF_STRING && pdfi_fmap_file_exists(ctx, (pdf_string *)mname)) { *mapname = mname; code = 0; } - else if (mname->type == PDF_NAME) { /* If we map to a name, we assume (for now) we have the font as a "built-in" */ + else if (mname != NULL && mname->type == PDF_NAME) { /* If we map to a name, we assume (for now) we have the font as a "built-in" */ *mapname = mname; code = 0; } diff --git a/pdf/pdf_fmap.h b/pdf/pdf_fmap.h index 73ae6aee6..c76502039 100644 --- a/pdf/pdf_fmap.h +++ b/pdf/pdf_fmap.h @@ -17,7 +17,7 @@ or might be a string. */ int -pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname); +pdf_fontmap_lookup_font(pdf_context *ctx, pdf_name *fname, pdf_obj **mapname, int *findex); /* The name parameter is to allow for internally derived font names to be looked up, like, for example, /Adobe-Japan1 diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c index 1d9c56dc7..08b78f5b6 100644 --- a/pdf/pdf_font.c +++ b/pdf/pdf_font.c @@ -145,12 +145,18 @@ pdfi_font_match_glyph_widths(pdf_font *pdfont) return code; } -static void pdfi_emprint_font_name(pdf_context *ctx, pdf_name *n) +/* Print a name object to stdout */ +static void pdfi_print_font_name(pdf_context *ctx, pdf_name *n) { - int i; - for (i = 0; i < n->length; i++) { - dmprintf1(ctx->memory, "%c", n->data[i]); - } + if (ctx->args.QUIET != true) + (void)outwrite(ctx->memory, (const char *)n->data, n->length); +} + +/* Print a null terminated string to stdout */ +static void pdfi_print_string(pdf_context *ctx, const char *str) +{ + if (ctx->args.QUIET != true) + (void)outwrite(ctx->memory, str, strlen(str)); } /* Call with a CIDFont name to try to find the CIDFont on disk @@ -195,12 +201,12 @@ pdfi_open_CIDFont_substitute_file(pdf_context * ctx, pdf_dict *font_dict, pdf_di } else { if (cidname) { - dmprintf(ctx->memory, "Loading CIDFont "); - pdfi_emprint_font_name(ctx, (pdf_name *)cidname); - dmprintf(ctx->memory, " substitute from "); + pdfi_print_string(ctx, "Loading CIDFont "); + pdfi_print_font_name(ctx, (pdf_name *)cidname); + pdfi_print_string(ctx, " substitute from "); } else { - dmprintf(ctx->memory, "Loading nameless CIDFont from "); + pdfi_print_string(ctx, "Loading nameless CIDFont from "); } sfilename(s, &fname); if (fname.size < gp_file_name_sizeof) { @@ -210,7 +216,9 @@ pdfi_open_CIDFont_substitute_file(pdf_context * ctx, pdf_dict *font_dict, pdf_di else { strcpy(fontfname, "unnamed file"); } - dmprintf1(ctx->memory, "%s.\n", fontfname); + pdfi_print_string(ctx, fontfname); + pdfi_print_string(ctx, "\n"); + sfseek(s, 0, SEEK_END); *buflen = sftell(s); @@ -234,12 +242,12 @@ pdfi_open_CIDFont_substitute_file(pdf_context * ctx, pdf_dict *font_dict, pdf_di } else { if (cidname) { - dmprintf(ctx->memory, "Loading CIDFont "); - pdfi_emprint_font_name(ctx, (pdf_name *)cidname); - dmprintf(ctx->memory, " (or substitute) from "); + pdfi_print_string(ctx, "Loading CIDFont "); + pdfi_print_font_name(ctx, (pdf_name *)cidname); + pdfi_print_string(ctx, " (or substitute) from "); } else { - dmprintf(ctx->memory, "Loading nameless CIDFont from "); + pdfi_print_string(ctx, "Loading nameless CIDFont from "); } sfilename(s, &fname); if (fname.size < gp_file_name_sizeof) { @@ -249,7 +257,8 @@ pdfi_open_CIDFont_substitute_file(pdf_context * ctx, pdf_dict *font_dict, pdf_di else { strcpy(fontfname, "unnamed file"); } - dmprintf1(ctx->memory, "%s.\n", fontfname); + pdfi_print_string(ctx, fontfname); + pdfi_print_string(ctx, "\n"); sfseek(s, 0, SEEK_END); *buflen = sftell(s); sfseek(s, 0, SEEK_SET); @@ -425,20 +434,6 @@ static const char *pdfi_font_substitute_by_flags(unsigned int flags) return "Helvetica"; /* Really shouldn't ever happen */ } -/* Print a name object to stdout */ -static void pdfi_print_font_name(pdf_context *ctx, pdf_name *n) -{ - if (ctx->args.QUIET != true) - (void)outwrite(ctx->memory, (const char *)n->data, n->length); -} - -/* Print a null terminated string to stdout */ -static void pdfi_print_string(pdf_context *ctx, const char *str) -{ - if (ctx->args.QUIET != true) - (void)outwrite(ctx->memory, str, strlen(str)); -} - enum { no_type_font = -1, type0_font = 0, diff --git a/pdf/pdftop.c b/pdf/pdftop.c index 3c56ca096..0e524336f 100644 --- a/pdf/pdftop.c +++ b/pdf/pdftop.c @@ -711,6 +711,14 @@ pdf_impl_set_param(pl_interp_implementation_t *impl, return code; code = pdfi_add_paths_to_search_paths(ctx, (const char *)s, slen, true); } + if (!strncmp(param, "FONTMAP", 7)) { + char *s = NULL; + int slen; + code = plist_value_get_string_or_name(ctx, &pvalue, &s , &slen); + if (code < 0) + return code; + code = pdfi_add_fontmapfiles(ctx, (const char *)s, slen); + } } exit: diff --git a/psi/zpdfops.c b/psi/zpdfops.c index 20ac81ea9..abd1a3da0 100644 --- a/psi/zpdfops.c +++ b/psi/zpdfops.c @@ -338,6 +338,56 @@ done: return code >= 0 ? 0 : code; } +static int zpdfi_populate_fontmap_files(i_ctx_t *i_ctx_p, pdf_context *ctx) +{ + int code, i; + ref *fontmaps; + + code = dict_find_string(systemdict, "FONTMAP", &fontmaps); + if (code >= 0 && r_has_type(fontmaps, t_array)) { + ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string) * r_size(fontmaps), "array of fontmap files"); + if (ctx->fontmapfiles != 0) { + memset(ctx->fontmapfiles, 0x00, sizeof(gs_string) * r_size(fontmaps)); + ctx->num_fontmapfiles = r_size(fontmaps); + for (i = 0; i < r_size(fontmaps); i++) { + const ref *fmapfile = fontmaps->value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */ + ctx->fontmapfiles[i].data = gs_alloc_bytes(ctx->memory, r_size(fmapfile), "zpdfi_populate_fontmap_files"); + if (ctx->fontmapfiles[i].data == NULL) { + code = gs_note_error(gs_error_VMerror); + goto done; + } + memcpy((char *)ctx->fontmapfiles[i].data, fmapfile->value.const_bytes, r_size(fmapfile)); + ctx->fontmapfiles[i].size = r_size(fmapfile); + } + } + else { + code = gs_note_error(gs_error_VMerror); + goto done; + } + } + else if (code >= 0 && r_has_type(fontmaps, t_string)) { + ctx->fontmapfiles = (gs_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_string), "array of fontmap files"); + if (ctx->fontmapfiles != 0) { + ctx->num_fontmapfiles = 1; + ctx->fontmapfiles[0].data = gs_alloc_bytes(ctx->memory, r_size(fontmaps), "zpdfi_populate_fontmap_files"); + if (ctx->fontmapfiles[0].data == NULL) { + code = gs_note_error(gs_error_VMerror); + goto done; + } + memcpy((char *)ctx->fontmapfiles[0].data, fontmaps->value.const_bytes, r_size(fontmaps)); + ctx->fontmapfiles[0].size = r_size(fontmaps); + } + else { + code = gs_note_error(gs_error_VMerror); + goto done; + } + } + else + code = 0; +done: + return code; +} + /* * Declare the structure we use to represent an instance of the PDF parser * as a t_struct. @@ -1129,6 +1179,11 @@ static int zPDFInit(i_ctx_t *i_ctx_p) code = zpdfi_populate_search_paths(i_ctx_p, ctx); if (code < 0) goto error; + + code = zpdfi_populate_fontmap_files(i_ctx_p, ctx); + if (code < 0) + goto error; + op = osp; push(1); make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx)); |