summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2021-09-03 11:26:43 +0100
committerChris Liddell <chris.liddell@artifex.com>2021-09-09 12:02:08 +0100
commit245ae9816d7a970347df194d1ea9ebaedb18ee12 (patch)
treec71ad5d25ec267c737d91db43d0f955104843ad1
parent3ccbae8583ddc2e1c53b0fdfae05e1a57e36ba01 (diff)
downloadghostpdl-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.c166
-rw-r--r--pdf/ghostpdf.h23
-rw-r--r--pdf/pdf.mak4
-rw-r--r--pdf/pdf_cmap.c10
-rw-r--r--pdf/pdf_file.c137
-rw-r--r--pdf/pdf_file.h3
-rw-r--r--pdf/pdf_fmap.c16
-rw-r--r--pdf/pdf_font.c41
-rw-r--r--pdf/pdftop.c54
-rw-r--r--psi/int.mak2
-rw-r--r--psi/zpdfops.c51
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));