diff options
author | Chris Liddell <chris.liddell@artifex.com> | 2021-09-03 11:26:43 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2021-09-09 12:02:08 +0100 |
commit | 245ae9816d7a970347df194d1ea9ebaedb18ee12 (patch) | |
tree | c71ad5d25ec267c737d91db43d0f955104843ad1 | |
parent | 3ccbae8583ddc2e1c53b0fdfae05e1a57e36ba01 (diff) | |
download | ghostpdl-245ae9816d7a970347df194d1ea9ebaedb18ee12.tar.gz |
gpdf: Build and use resource search path list
Also use the genericrsourcedir to find fonts.
gpdf: allow setting of FONTPATH param
gpdf/gs: Populate the pdfi search paths from the PS environment
-rw-r--r-- | pdf/ghostpdf.c | 166 | ||||
-rw-r--r-- | pdf/ghostpdf.h | 23 | ||||
-rw-r--r-- | pdf/pdf.mak | 4 | ||||
-rw-r--r-- | pdf/pdf_cmap.c | 10 | ||||
-rw-r--r-- | pdf/pdf_file.c | 137 | ||||
-rw-r--r-- | pdf/pdf_file.h | 3 | ||||
-rw-r--r-- | pdf/pdf_fmap.c | 16 | ||||
-rw-r--r-- | pdf/pdf_font.c | 41 | ||||
-rw-r--r-- | pdf/pdftop.c | 54 | ||||
-rw-r--r-- | psi/int.mak | 2 | ||||
-rw-r--r-- | psi/zpdfops.c | 51 |
11 files changed, 465 insertions, 42 deletions
diff --git a/pdf/ghostpdf.c b/pdf/ghostpdf.c index 0e4b3d3db..770da4d05 100644 --- a/pdf/ghostpdf.c +++ b/pdf/ghostpdf.c @@ -47,6 +47,7 @@ #include "gsmchunk.h" #endif +extern const char gp_file_name_list_separator; /* * Convenience routine to check if a given string exists in a dictionary * verify its contents and print it in a particular fashion to stdout. This @@ -1339,6 +1340,169 @@ int pdfi_open_pdf_file(pdf_context *ctx, char *filename) return code; } +static size_t pdfi_grdir_path_string_match(const byte *str, size_t sl0, byte *pat, size_t pl) +{ + bool found = false; + size_t sl = sl0; + + while (found == false) { + if (pl > sl) + break; + if (*str == *pat && memcmp(str, pat, pl) == 0) + found = true; + else { + str++; + sl--; + } + } + if (found) + return (sl0 - sl) + pl; + else + return 0; +} + +int pdfi_add_paths_to_search_paths(pdf_context *ctx, const char *ppath, int l, bool fontpath) +{ + int i, slen, npaths = (l > 0); + const char *p = ppath; + char *ps; + const char *pe = p + l + 1; + int code = 0; + static const char *resstr = "Resource"; + const int restrlen = strlen(resstr); + const char *dirsepstr = gp_file_name_directory_separator(); + const int dirsepstrlen = strlen(dirsepstr); + char genresstr[64]; + + for (ps = (char *)p; ps < pe; ps++) { + if (*ps == gp_file_name_list_separator) + npaths++; + } + + if (npaths > 0) { + gs_param_string *pathstrings; + int new_npaths = ctx->search_paths.num_resource_paths + npaths; + + if (fontpath != true) { + pathstrings = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * new_npaths, "array of paths"); + if (pathstrings == NULL) + return_error(gs_error_VMerror); + + memset(pathstrings, 0x00, sizeof(gs_param_string) * new_npaths); + + for (i = 1; i <= ctx->search_paths.num_init_resource_paths; i++) { + pathstrings[new_npaths - i] = ctx->search_paths.resource_paths[ctx->search_paths.num_resource_paths - i]; + } + + for (i = 0; i < ctx->search_paths.num_resource_paths - ctx->search_paths.num_init_resource_paths; i++) { + pathstrings[i] = ctx->search_paths.resource_paths[i]; + } + /* NO NOT CHANGE "i" BETWEEN HERE....... */ + gs_free_object(ctx->memory, ctx->search_paths.resource_paths, "old array of paths"); + ctx->search_paths.resource_paths = pathstrings; + ctx->search_paths.num_resource_paths += npaths; + + /* .....AND HERE */ + for (ps = (char *)p; ps < pe; ps++) { + if (*ps == gp_file_name_list_separator || ps == pe - 1) { + if (*p == gp_file_name_list_separator) p++; /* move past the separator */ + slen = ps - p; + pathstrings[i].data = (byte *)gs_alloc_bytes(ctx->memory, slen, "path string body"); + + if (pathstrings[i].data == NULL) { + code = gs_note_error(gs_error_VMerror); + break; + } + + memcpy((char *)pathstrings[i].data, p, slen); + pathstrings[i].size = slen; + pathstrings[i].persistent = false; + i++; + p = ps++; + } + } + if ((restrlen + 2 * dirsepstrlen) < 64) { + size_t grdlen; + + memcpy(genresstr, resstr, restrlen +1); /* +1 So we get the null terminator */ + strncat(genresstr, dirsepstr, dirsepstrlen); + + for (i = 0; i < ctx->search_paths.num_resource_paths; i++) { + if ((grdlen = pdfi_grdir_path_string_match(ctx->search_paths.resource_paths[i].data, ctx->search_paths.resource_paths[i].size, (byte *)genresstr, restrlen + dirsepstrlen)) > 0) { + ctx->search_paths.genericresourcedir.data = ctx->search_paths.resource_paths[i].data; + ctx->search_paths.genericresourcedir.size = grdlen; + ctx->search_paths.genericresourcedir.persistent = true; + break; + } + } + } + } + else { + p = ppath; + pathstrings = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * (npaths + ctx->search_paths.num_font_paths), "array of font paths"); + if (pathstrings == NULL) + return_error(gs_error_VMerror); + + memset(pathstrings, 0x00, sizeof(gs_param_string) * (npaths + ctx->search_paths.num_font_paths)); + + for (i = 0; i < ctx->search_paths.num_font_paths; i++) { + pathstrings[ctx->search_paths.num_font_paths + i] = ctx->search_paths.font_paths[i]; + } + gs_free_object(ctx->memory, ctx->search_paths.font_paths, "old array of paths"); + ctx->search_paths.font_paths = pathstrings; + ctx->search_paths.num_font_paths += npaths; + + i = 0; + for (ps = (char *)p; ps < pe; ps++) { + if (*ps == gp_file_name_list_separator || ps == pe - 1) { + slen = ps - p; + pathstrings[i].data = (byte *)gs_alloc_bytes(ctx->memory, slen, "path string body"); + + if (pathstrings[i].data == NULL) { + code = gs_note_error(gs_error_VMerror); + break; + } + + memcpy((char *)pathstrings[i].data, p, slen); + pathstrings[i].size = slen; + pathstrings[i].persistent = false; + i++; + p = ps++; + } + } + } + } + + return code; +} + +int pdfi_add_initial_paths_to_search_paths(pdf_context *ctx, const char *ppath, int l) +{ + int code; + if (ctx->search_paths.num_resource_paths != 0) + return_error(gs_error_invalidaccess); + + code = pdfi_add_paths_to_search_paths(ctx, ppath, l, false); + ctx->search_paths.num_init_resource_paths = ctx->search_paths.num_resource_paths; + + return code; +} + +static void pdfi_free_search_paths(pdf_context *ctx) +{ + int i; + for (i = 0; i < ctx->search_paths.num_resource_paths; i++) { + if (ctx->search_paths.resource_paths[i].persistent == false) + gs_free_object(ctx->memory, (byte *)ctx->search_paths.resource_paths[i].data, "path string body"); + } + for (i = 0; i < ctx->search_paths.num_font_paths; i++) { + if (ctx->search_paths.font_paths[i].persistent == false) + gs_free_object(ctx->memory, (byte *)ctx->search_paths.font_paths[i].data, "path string body"); + } + gs_free_object(ctx->memory, (byte *)ctx->search_paths.resource_paths, "array of paths"); + gs_free_object(ctx->memory, (byte *)ctx->search_paths.font_paths, "array of font paths"); +} + /***********************************************************************************/ /* 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 */ @@ -1731,6 +1895,8 @@ int pdfi_free_context(pdf_context *ctx) gs_free_object(ctx->memory, ctx->loop_detection, "pdfi_free_context"); } + pdfi_free_search_paths(ctx); + gs_free_object(ctx->memory, ctx, "pdfi_free_context"); #if PDFI_LEAK_CHECK gs_memory_status(mem, &mstat); diff --git a/pdf/ghostpdf.h b/pdf/ghostpdf.h index 5af8dde03..3cc1b8cd4 100644 --- a/pdf/ghostpdf.h +++ b/pdf/ghostpdf.h @@ -321,6 +321,25 @@ typedef struct device_state_s { bool annotations_preserved; } device_state_t; +/* + * resource_paths: for CMaps, iccprofiles, fonts... mainly build time settings and from + * "-I" command line options. + * font_paths: Specific to fonts: from the -sFONTPATH=<> option + * We keep a running count (num_resource_paths) of all, and a one off count of paths that + * came from the build (num_init_resource_paths) so we can keep the (weird) search order + * that gs uses. + */ +typedef struct search_paths_s +{ + gs_param_string *resource_paths; + int num_resource_paths; /* total */ + int num_init_resource_paths; /* number of paths that came from the build */ + gs_param_string *font_paths; + int num_font_paths; + gs_param_string genericresourcedir; + bool search_here_first; +} search_paths_t; + typedef struct pdf_context_s { void *instance; @@ -444,6 +463,7 @@ typedef struct pdf_context_s /* A name table :-( */ pdfi_name_entry_t *name_table; + search_paths_t search_paths; pdf_dict *pdffontmap; /* These function pointers can be replaced by ones intended to replicate @@ -471,6 +491,9 @@ typedef struct pdf_context_s #define OBJ_CTX(o) ((pdf_context *)(o->ctx)) #define OBJ_MEMORY(o) OBJ_CTX(o)->memory +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); + pdf_context *pdfi_create_context(gs_memory_t *pmem); int pdfi_clear_context(pdf_context *ctx); int pdfi_free_context(pdf_context *ctx); diff --git a/pdf/pdf.mak b/pdf/pdf.mak index 2ec827855..ccb709161 100644 --- a/pdf/pdf.mak +++ b/pdf/pdf.mak @@ -209,7 +209,7 @@ $(PDFOBJ)pdf_int.$(OBJ): $(PDFSRC)pdf_int.c $(PDFINCLUDES) $(plmain_h) \ $(PDFCCC) $(PDFSRC)pdf_int.c $(PDFO_)pdf_int.$(OBJ) $(PDFOBJ)pdf_file_luratech.$(OBJ): $(PDFSRC)pdf_file.c $(sjpeg_h) $(stream_h) $(strimpl_h) \ - $(strmio_h) $(simscale_h) $(szlibx_h) $(spngx_h) $(spdiffx_h) $(slzw_h) $(sstring_h) \ + $(strmio_h) $(gpmisc_h) $(simscale_h) $(szlibx_h) $(spngx_h) $(spdiffx_h) $(slzw_h) $(sstring_h) \ $(sa85d_h) $(scfx_h) $(srlx_h) $(jpeglib__h) $(sdct_h) $(sjpeg_h) $(sfilter_h) $(sarc4_h) \ $(saes_h) $(ssha2_h) $(sjbig2_luratech_h) $(sjpx_luratech_h) \ $(PDFINCLUDES) $(PDF_MAK) $(MAKEDIRS) @@ -273,7 +273,7 @@ $(PDF_TOP_OBJ): $(PDFSRC)pdftop.c $(plmain_h) $(pltop_h) $(PDFINCLUDES) \ $(GLGEN)gconfig.$(OBJ) $(pltop_h) $(plmain_h) $(plparse_h) $(gxdevice_h) \ $(gxht_h) $(gsht1_h) $(pconfig_h) \ $(PDF_MAK) $(MAKEDIRS) - $(PDFCCC) $(PDFSRC)pdftop.c $(PDFO_)pdftop.$(OBJ) + $(PDFCCC) $(D_)GS_LIB_DEFAULT=$(GS_LIB_DEFAULT)$(_D) $(D_)COMPILE_INITS=$(COMPILE_INITS)$(_D) $(PDFSRC)pdftop.c $(PDFO_)pdftop.$(OBJ) PDF_OBJS=\ $(PDFOBJ)pdf_loop_detect.$(OBJ)\ diff --git a/pdf/pdf_cmap.c b/pdf/pdf_cmap.c index 7bdbd0966..fcf363ff5 100644 --- a/pdf/pdf_cmap.c +++ b/pdf/pdf_cmap.c @@ -633,19 +633,15 @@ static int pdf_cmap_open_file(pdf_context *ctx, gs_string *cmap_name, byte **buf, int64_t *buflen) { int code = 0; - /* FIXME: romfs hardcoded coded for now */ stream *s; char fname[gp_file_name_sizeof]; - const char *path_pfx = "%rom%Resource/CMap/"; + const char *path_pfx = "CMap/"; fname[0] = '\0'; strncat(fname, path_pfx, strlen(path_pfx)); strncat(fname, (char *)cmap_name->data, cmap_name->size); - s = sfopen(fname, "r", ctx->memory); - if (s == NULL) { - code = gs_note_error(gs_error_undefinedfilename); - } - else { + code = pdfi_open_resource_file(ctx, (const char *)fname, (const int)strlen(fname), &s); + if (code >= 0) { sfseek(s, 0, SEEK_END); *buflen = sftell(s); sfseek(s, 0, SEEK_SET); diff --git a/pdf/pdf_file.c b/pdf/pdf_file.c index 2666a55ea..214d448de 100644 --- a/pdf/pdf_file.c +++ b/pdf/pdf_file.c @@ -25,6 +25,7 @@ #include "stream.h" #include "strimpl.h" #include "strmio.h" +#include "gpmisc.h" #include "simscale.h" /* SIMScaleDecode */ #include "szlibx.h" /* Flate */ #include "spngpx.h" /* PNG Predictor */ @@ -1561,3 +1562,139 @@ pdfi_stream_to_buffer(pdf_context *ctx, pdf_stream *stream_obj, byte **buf, int6 *bufferlen = buflen; return code; } + +int pdfi_open_resource_file(pdf_context *ctx, const char *fname, const int fnamelen, stream **s) +{ + int code = 0; + if (fname == NULL || fnamelen == 0) + *s = NULL; + else if (gp_file_name_is_absolute(fname, fnamelen) || fname[0] == '%') { + /* If it's an absolute path or an explicit PS style device, just try to open it */ + *s = sfopen(fname, "r", ctx->memory); + } + else { + char fnametotry[gp_file_name_sizeof]; + uint fnlen; + gs_parsed_file_name_t pname; + gp_file_name_combine_result r; + int i, total; + + *s = NULL; + i = 0; + total = ctx->search_paths.num_resource_paths - ctx->search_paths.num_init_resource_paths - 1; +retry: + for (; i < total; i++) { + gs_param_string *ss = &ctx->search_paths.resource_paths[i]; + + if (ss->data[0] == '%') { + code = gs_parse_file_name(&pname, (char *)ss->data, ss->size, ctx->memory); + if (code < 0 || (pname.len + fnamelen >= gp_file_name_sizeof)) { + continue; + } + memcpy(fnametotry, pname.fname, pname.len); + memcpy(fnametotry + pname.len, fname, fnamelen); + code = pname.iodev->procs.open_file(pname.iodev, fnametotry, pname.len + fnamelen, "r", s, ctx->memory); + if (code < 0) { + continue; + } + break; + } + else { + fnlen = gp_file_name_sizeof; + r = gp_file_name_combine((char *)ss->data, ss->size, fname, fnamelen, false, fnametotry, &fnlen); + if (r != gp_combine_success || fnlen > gp_file_name_sizeof - 1) + continue; + fnametotry[fnlen] = '\0'; + *s = sfopen(fnametotry, "r", ctx->memory); + if (*s != NULL) + break; + } + } + if (*s == NULL && i < ctx->search_paths.num_resource_paths) { + gs_param_string *ss = &ctx->search_paths.genericresourcedir; + fnlen = gp_file_name_sizeof; + r = gp_file_name_combine((char *)ss->data, ss->size, fname, fnamelen, false, fnametotry, &fnlen); + if (r == gp_combine_success || fnlen < gp_file_name_sizeof) { + fnametotry[fnlen] = '\0'; + *s = sfopen(fnametotry, "r", ctx->memory); + } + } + if (*s == NULL && i < ctx->search_paths.num_resource_paths) { + total = ctx->search_paths.num_resource_paths; + goto retry; + } + } + if (*s == NULL) + return_error(gs_error_invalidfileaccess); + + return 0; +} + +int pdfi_open_font_file(pdf_context *ctx, const char *fname, const int fnamelen, stream **s) +{ + int code = 0; + const char *fontdirstr = "Font/"; + const int fontdirstrlen = strlen(fontdirstr); + + if (fname == NULL || fnamelen == 0) + *s = NULL; + else if (gp_file_name_is_absolute(fname, fnamelen) || fname[0] == '%') { + /* If it's an absolute path or an explicit PS style device, just try to open it */ + *s = sfopen(fname, "r", ctx->memory); + } + else { + char fnametotry[gp_file_name_sizeof]; + uint fnlen; + gs_parsed_file_name_t pname; + gp_file_name_combine_result r; + int i; + + *s = NULL; + for (i = 0; i < ctx->search_paths.num_font_paths; i++) { + gs_param_string *ss = &ctx->search_paths.font_paths[i]; + + if (ss->data[0] == '%') { + code = gs_parse_file_name(&pname, (char *)ss->data, ss->size, ctx->memory); + if (code < 0 || (pname.len + fnamelen >= gp_file_name_sizeof)) { + continue; + } + memcpy(fnametotry, pname.fname, pname.len); + memcpy(fnametotry + pname.len, fname, fnamelen); + code = pname.iodev->procs.open_file(pname.iodev, fnametotry, pname.len + fnamelen, "r", s, ctx->memory); + if (code < 0) { + continue; + } + break; + } + else { + fnlen = gp_file_name_sizeof; + r = gp_file_name_combine((char *)ss->data, ss->size, fname, fnamelen, false, fnametotry, &fnlen); + if (r != gp_combine_success || fnlen > gp_file_name_sizeof - 1) + continue; + fnametotry[fnlen] = '\0'; + *s = sfopen(fnametotry, "r", ctx->memory); + if (*s != NULL) + break; + } + } + if (*s == NULL && i < ctx->search_paths.num_resource_paths) { + gs_param_string *ss = &ctx->search_paths.genericresourcedir; + char fstr[gp_file_name_sizeof]; + + fnlen = gp_file_name_sizeof; + + memcpy(fstr, fontdirstr, fontdirstrlen); + memcpy(fstr + fontdirstrlen, fname, fnamelen); + + r = gp_file_name_combine((char *)ss->data, ss->size, fstr, fontdirstrlen + fnamelen, false, fnametotry, &fnlen); + if (r == gp_combine_success || fnlen < gp_file_name_sizeof) { + fnametotry[fnlen] = '\0'; + *s = sfopen(fnametotry, "r", ctx->memory); + } + } + } + if (*s == NULL) + return pdfi_open_resource_file(ctx, fname, fnamelen, s); + + return 0; +} diff --git a/pdf/pdf_file.h b/pdf/pdf_file.h index 2002f2acd..a02d7f75d 100644 --- a/pdf/pdf_file.h +++ b/pdf/pdf_file.h @@ -106,4 +106,7 @@ int pdfi_apply_imscale_filter(pdf_context *ctx, pdf_string *Key, int width, int int pdfi_apply_SHA256_filter(pdf_context *ctx, pdf_c_stream *source, pdf_c_stream **new_stream); #endif +int pdfi_open_resource_file(pdf_context *ctx, const char *fname, const int fnamelen, stream **s); +int pdfi_open_font_file(pdf_context *ctx, const char *fname, const int fnamelen, stream **s); + #endif /* PDF_FILES */ diff --git a/pdf/pdf_fmap.c b/pdf/pdf_fmap.c index 66501a089..8fabb7571 100644 --- a/pdf/pdf_fmap.c +++ b/pdf/pdf_fmap.c @@ -41,10 +41,9 @@ static int pdf_fontmap_open_file(pdf_context *ctx, byte **buf, int *buflen) { int code = 0; - /* FIXME: romfs/filename hardcoded coded for now */ stream *s; char fname[gp_file_name_sizeof]; - const char *path_pfx = "%rom%Resource/Init/"; + const char *path_pfx = "Init/"; const char *fmap_default = "Fontmap.GS"; const char *prestring = "<<\n"; const char *poststring = ">>\nendstream\n"; @@ -55,13 +54,14 @@ pdf_fontmap_open_file(pdf_context *ctx, byte **buf, int *buflen) if (strlen(path_pfx) + strlen(fmap_default) + 1 > gp_file_name_sizeof) return_error(gs_error_invalidfileaccess); - strncat(fname, path_pfx, strlen(path_pfx)); - strncat(fname, (char *)fmap_default, strlen(fmap_default)); - s = sfopen(fname, "r", ctx->memory); - if (s == NULL) { - code = gs_note_error(gs_error_undefinedfilename); + code = pdfi_open_resource_file(ctx, fmap_default, strlen(fmap_default), &s); + if (code < 0) { + strncat(fname, path_pfx, strlen(path_pfx)); + strncat(fname, (char *)fmap_default, strlen(fmap_default)); + code = pdfi_open_resource_file(ctx, fname, strlen(fname), &s); } - else { + + if (code >= 0) { int i; sfseek(s, 0, SEEK_END); *buflen = sftell(s); diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c index 790126363..7fa8a4272 100644 --- a/pdf/pdf_font.c +++ b/pdf/pdf_font.c @@ -158,22 +158,19 @@ pdfi_open_CIDFont_substitute_file(pdf_context * ctx, pdf_dict *font_dict, pdf_di if (fallback == true) { char fontfname[gp_file_name_sizeof]; - const char *romfsprefix = "%rom%Resource/CIDFSubst/"; - const int romfsprefixlen = strlen(romfsprefix); + const char *fsprefix = "CIDFSubst/"; + const int fsprefixlen = strlen(fsprefix); const char *defcidfallack = "DroidSansFallback.ttf"; const int defcidfallacklen = strlen(defcidfallack); stream *s; code = 0; - memcpy(fontfname, romfsprefix, romfsprefixlen); - memcpy(fontfname + romfsprefixlen, defcidfallack, defcidfallacklen); - fontfname[romfsprefixlen + defcidfallacklen] = '\0'; + memcpy(fontfname, fsprefix, fsprefixlen); + memcpy(fontfname + fsprefixlen, defcidfallack, defcidfallacklen); + fontfname[fsprefixlen + defcidfallacklen] = '\0'; - s = sfopen(fontfname, "r", ctx->memory); - if (s == NULL) { - code = gs_note_error(gs_error_invalidfont); - } - else { + code = pdfi_open_resource_file(ctx, fontfname, strlen(fontfname), &s); + if (code >= 0) { sfseek(s, 0, SEEK_END); *buflen = sftell(s); sfseek(s, 0, SEEK_SET); @@ -332,8 +329,6 @@ pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict * { int code; char fontfname[gp_file_name_sizeof]; - const char *romfsprefix = "%rom%Resource/Font/"; - const int romfsprefixlen = strlen(romfsprefix); pdf_obj *basefont = NULL, *mapname; pdf_obj *fontname = NULL; stream *s; @@ -381,21 +376,18 @@ pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict * } if (mapname->type == PDF_NAME) { pdf_name *mname = (pdf_name *) mapname; - if (romfsprefixlen + mname->length + 1 < gp_file_name_sizeof) { - memcpy(fontfname, romfsprefix, romfsprefixlen); - memcpy(fontfname + romfsprefixlen, mname->data, mname->length); - fontfname[romfsprefixlen + mname->length] = '\0'; + if (mname->length + 1 < gp_file_name_sizeof) { + memcpy(fontfname, mname->data, mname->length); + fontfname[mname->length] = '\0'; } else { return_error(gs_error_invalidfileaccess); } } - s = sfopen(fontfname, "r", ctx->memory); - if (s == NULL) { - code = gs_note_error(gs_error_undefinedfilename); - } - else { + code = pdfi_open_font_file(ctx, fontfname, strlen(fontfname), &s); + if (code >= 0) { + gs_const_string fname; if (basefont) { dmprintf(ctx->memory, "Loading font "); pdfi_emprint_font_name(ctx, (pdf_name *)basefont); @@ -404,6 +396,11 @@ pdfi_open_font_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict * else { dmprintf(ctx->memory, "Loading nameless font from "); } + sfilename(s, &fname); + if (fname.size < gp_file_name_sizeof) { + memcpy(fontfname, fname.data, fname.size); + fontfname[fname.size] = '\0'; + } dmprintf1(ctx->memory, "%s.\n", fontfname); sfseek(s, 0, SEEK_END); @@ -1437,7 +1434,7 @@ int pdfi_init_font_directory(pdf_context *ctx) } /* Loads a (should be!) non-embedded font by name - Only currently works for the Type 1 font set from romfs. + Only currently works for Type 1 fonts set. */ int pdfi_load_font_by_name_string(pdf_context *ctx, const byte *fontname, size_t length, pdf_obj **ppdffont) diff --git a/pdf/pdftop.c b/pdf/pdftop.c index feb8e8b3e..6dbe1817d 100644 --- a/pdf/pdftop.c +++ b/pdf/pdftop.c @@ -33,7 +33,10 @@ #include "gspaint.h" /* For gs_erasepage() */ #include "gscolor3.h" /* For gs_setsmoothness() */ +extern const char gp_file_name_list_separator; + static int pdfi_install_halftone(pdf_context *ctx, gx_device *pdevice); +static int pdf_impl_add_path(pl_interp_implementation_t *impl, const char *path); /* * The PDF interpreter instance is derived from pl_interp_implementation_t. @@ -48,6 +51,12 @@ typedef struct pdf_interp_instance_s char scratch_name[gp_file_name_sizeof]; }pdf_interp_instance_t; +extern const char gp_file_name_list_separator; + +#define _PDFI_STRING_IT(s) #s +#define PDFI_STRING_IT(s) _PDFI_STRING_IT(s) +#define GS_LIB_DEFAULT_STRING PDFI_STRING_IT(GS_LIB_DEFAULT) + static int pdf_detect_language(const char *s, int len) { @@ -102,6 +111,10 @@ pdf_impl_allocate_interp_instance(pl_interp_implementation_t *impl, { pdf_interp_instance_t *instance; pdf_context *ctx; + int code; + const char *rompathstr = "%rom%Resource/Init"; + const char *deflibstr = GS_LIB_DEFAULT_STRING; + char *newpathsstr = (char *)deflibstr; instance = (pdf_interp_instance_t *) gs_alloc_bytes(pmem, sizeof(pdf_interp_instance_t), "pdf_impl_allocate_interp_instance"); @@ -125,8 +138,28 @@ pdf_impl_allocate_interp_instance(pl_interp_implementation_t *impl, instance->memory = pmem; impl->interp_client_data = instance; + if (COMPILE_INITS == 1) { + newpathsstr = (char *)gs_alloc_bytes(ctx->memory, strlen(rompathstr) + strlen(GS_LIB_DEFAULT_STRING) + 2, "temp paths string"); + if (newpathsstr == NULL) { + newpathsstr = (char *)rompathstr; + } + else { + char sepstr[2]; - return 0; + sepstr[0] = gp_file_name_list_separator; + sepstr[1] = '\0'; + + memcpy(newpathsstr, rompathstr, strlen(rompathstr) + 1); + strncat(newpathsstr, sepstr, strlen(sepstr)); + strncat(newpathsstr, GS_LIB_DEFAULT_STRING, strlen(GS_LIB_DEFAULT_STRING)); + } + } + + code = pdfi_add_initial_paths_to_search_paths(ctx, newpathsstr, strlen(newpathsstr)); + if (newpathsstr != deflibstr && newpathsstr != rompathstr) { + gs_free_object(ctx->memory, newpathsstr, "temp paths string"); + } + return code; } static int @@ -665,6 +698,14 @@ pdf_impl_set_param(pl_interp_implementation_t *impl, if (code < 0) return code; } + if (!strncmp(param, "FONTPATH", 11)) { + char *s = NULL; + int slen; + code = plist_value_get_string_or_name(ctx, &pvalue, &s , &slen); + if (code < 0) + return code; + code = pdfi_add_paths_to_search_paths(ctx, (const char *)s, slen, true); + } } exit: @@ -672,6 +713,15 @@ pdf_impl_set_param(pl_interp_implementation_t *impl, } static int +pdf_impl_add_path(pl_interp_implementation_t *impl, const char *path) +{ + pdf_interp_instance_t *instance = impl->interp_client_data; + pdf_context *ctx = instance->ctx; + + return pdfi_add_paths_to_search_paths(ctx, path, strlen(path), false); +} + +static int pdf_impl_post_args_init(pl_interp_implementation_t *impl) { return 0; @@ -728,7 +778,7 @@ pl_interp_implementation_t pdf_implementation = pdf_impl_allocate_interp_instance, pdf_impl_get_device_memory, pdf_impl_set_param, - NULL, /* add_path */ + pdf_impl_add_path, pdf_impl_post_args_init, pdf_impl_init_job, NULL, /* run_prefix_commands */ diff --git a/psi/int.mak b/psi/int.mak index 6499f5d9a..db0e5c2df 100644 --- a/psi/int.mak +++ b/psi/int.mak @@ -1812,7 +1812,7 @@ $(PSD)pdfops.dev : $(ECHOGS_XE) $(zpdfops_) $(INT_MAK) $(MAKEDIRS) $(PSOBJ)zpdfops.$(OBJ) : $(PSSRC)zpdfops.c $(OP) $(MAKEFILE)\ $(ghost_h) $(gsmchunk_h) $(oper_h) \ $(igstate_h) $(istack_h) $(iutil_h) $(gspath_h) $(math__h) $(ialloc_h)\ - $(string__h) $(store_h) $(INT_MAK) $(MAKEDIRS) + $(string__h) $(store_h) $(iminst_h) $(idstack_h) $(INT_MAK) $(MAKEDIRS) $(PSCC) $(PSO_)zpdfops.$(OBJ) $(C_) $(PSSRC)zpdfops.c zutf8_=$(PSOBJ)zutf8.$(OBJ) diff --git a/psi/zpdfops.c b/psi/zpdfops.c index c52973e02..4c01de030 100644 --- a/psi/zpdfops.c +++ b/psi/zpdfops.c @@ -22,6 +22,9 @@ #include "gzht.h" #include "gsrefct.h" #include "pdf_misc.h" + +#include "iminst.h" +#include "dstack.h" #endif #include "ghost.h" @@ -270,6 +273,53 @@ zsaslprep(i_ctx_t *i_ctx_p) #if defined(BUILD_PDF) && BUILD_PDF == 1 /* + This cannot fail. If gs doesn't have these settings it will never reach here. + Because the lives of the string values here are all tied to the Postscript + context, and the Postscript context *must* outlast the pdfi context, we can + safely just take references, marking the strings as "persistent" so destroying + the pdfi context doesn't try to free the string bodies. + */ +static void zpdfi_populate_search_paths(i_ctx_t *i_ctx_p, pdf_context *ctx) +{ + /* This should only be called once per pdfi context + if the paths are already populated, just skip it. + */ + if (ctx->search_paths.resource_paths == NULL) { + ref *l2dictref, *grdref, *fpathref; + int code, i; + const gs_file_path *pfpath = i_ctx_p->lib_path; + gs_main_instance *minst = get_minst_from_memory(imemory); + code = dict_find_string(systemdict, "pssystemparams", &l2dictref); + if (code >= 0 && r_has_type(l2dictref, t_dictionary)) { + code = dict_find_string(l2dictref, "GenericResourceDir", &grdref); + if (code >= 0 && r_has_type(grdref, t_string)) { + ctx->search_paths.genericresourcedir.data = grdref->value.const_bytes; + ctx->search_paths.genericresourcedir.size = r_size(grdref); + ctx->search_paths.genericresourcedir.persistent = true; + } + } + ctx->search_paths.resource_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * r_size(&pfpath->list), "array of paths"); + ctx->search_paths.num_resource_paths = r_size(&pfpath->list); + for (i = 0; i < r_size(&pfpath->list); i++) { + const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */ + ctx->search_paths.resource_paths[i].data = prdir->value.const_bytes; + ctx->search_paths.resource_paths[i].size = r_size(prdir); + ctx->search_paths.resource_paths[i].persistent = true; + } + code = dict_find_string(systemdict, "FONTPATH", &fpathref); + ctx->search_paths.font_paths = (gs_param_string *)gs_alloc_bytes(ctx->memory, sizeof(gs_param_string) * r_size(fpathref), "array of font paths"); + ctx->search_paths.num_font_paths = r_size(fpathref); + for (i = 0; i < r_size(fpathref); i++) { + const ref *prdir = pfpath->list.value.refs + i; /* By nature, this cannot be a short/mixed array, only a "normal" array */ + ctx->search_paths.resource_paths[i].data = prdir->value.const_bytes; + ctx->search_paths.resource_paths[i].size = r_size(prdir); + ctx->search_paths.resource_paths[i].persistent = true; + } + ctx->search_paths.search_here_first = minst->search_here_first; + } +} + +/* * Declare the structure we use to represent an instance of the PDF parser * as a t_struct. */ @@ -1044,6 +1094,7 @@ static int zPDFInit(i_ctx_t *i_ctx_p) code = 0; pop(1); } + zpdfi_populate_search_paths(i_ctx_p, ctx); op = osp; push(1); make_tav(op, t_pdfctx, icurrent_space | a_all, pstruct, (obj_header_t *)(pdfctx)); |