summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2021-05-28 11:07:22 +0100
committerChris Liddell <chris.liddell@artifex.com>2021-06-01 07:51:21 +0100
commita2ce7744473da06118de0c038045af35a25c041f (patch)
tree9030f825fc5d436801670f0c1c9d2e37c8041c50
parent0be6b1335935c2c1faef0347a8b03c24fa6fed53 (diff)
downloadghostpdl-a2ce7744473da06118de0c038045af35a25c041f.tar.gz
When running from PostScript, use the PS gstate
We are supposed to use the PostScript graphics state when run from the PostScript environment, but the act of creating a PDF interpreter context created a new graphics state, which we used. This commit has the create context function take a pointer to an initial gstate, which it uses if present. Otherwise we create a new graphics state, as before. Also update the clear and free context functions so that they don't attempt to throw away anything being used by the initial graphics state. Modify the PDF interpreter to call create_context with a NULL pointer and the PostScript interface code to call it with the PostScript graphics state.
-rw-r--r--pdf/ghostpdf.c71
-rw-r--r--pdf/ghostpdf.h6
-rw-r--r--pdf/pdftop.c4
-rw-r--r--psi/zpdfops.c12
4 files changed, 53 insertions, 40 deletions
diff --git a/pdf/ghostpdf.c b/pdf/ghostpdf.c
index 05d91e0bb..ef1f3c673 100644
--- a/pdf/ghostpdf.c
+++ b/pdf/ghostpdf.c
@@ -578,7 +578,7 @@ int pdfi_close_pdf_file(pdf_context *ctx)
ctx->filename = NULL;
}
- pdfi_clear_context(ctx);
+ pdfi_clear_context(ctx, true);
return 0;
}
@@ -1165,7 +1165,7 @@ int pdfi_open_pdf_file(pdf_context *ctx, char *filename)
/* the interpreter access to its context. */
/* We start with routines for creating and destroying the interpreter context */
-pdf_context *pdfi_create_context(gs_memory_t *pmem)
+pdf_context *pdfi_create_context(gs_memory_t *pmem, gs_gstate *initial_gstate)
{
pdf_context *ctx = NULL;
gs_gstate *pgs = NULL;
@@ -1174,13 +1174,16 @@ pdf_context *pdfi_create_context(gs_memory_t *pmem)
ctx = (pdf_context *) gs_alloc_bytes(pmem->non_gc_memory,
sizeof(pdf_context), "pdf_create_context");
- pgs = gs_gstate_alloc(pmem);
+ if (initial_gstate == NULL)
+ pgs = gs_gstate_alloc(pmem);
+ else
+ pgs = initial_gstate;
if (!ctx || !pgs)
{
if (ctx)
gs_free_object(pmem->non_gc_memory, ctx, "pdf_create_context");
- if (pgs)
+ if (pgs && initial_gstate == NULL)
gs_gstate_free(pgs);
return NULL;
}
@@ -1191,7 +1194,8 @@ pdf_context *pdfi_create_context(gs_memory_t *pmem)
ctx->stack_bot = (pdf_obj **)gs_alloc_bytes(ctx->memory, INITIAL_STACK_SIZE * sizeof (pdf_obj *), "pdf_imp_allocate_interp_stack");
if (ctx->stack_bot == NULL) {
gs_free_object(pmem->non_gc_memory, ctx, "pdf_create_context");
- gs_gstate_free(pgs);
+ if (initial_gstate == NULL)
+ gs_gstate_free(pgs);
return NULL;
}
ctx->stack_size = INITIAL_STACK_SIZE;
@@ -1204,7 +1208,8 @@ pdf_context *pdfi_create_context(gs_memory_t *pmem)
if (code < 0) {
gs_free_object(pmem->non_gc_memory, ctx->stack_bot, "pdf_create_context");
gs_free_object(pmem->non_gc_memory, ctx, "pdf_create_context");
- gs_gstate_free(pgs);
+ if (initial_gstate == NULL)
+ gs_gstate_free(pgs);
return NULL;
}
@@ -1213,19 +1218,23 @@ pdf_context *pdfi_create_context(gs_memory_t *pmem)
gs_free_object(ctx->memory, ctx->font_dir, "pdf_create_context");
gs_free_object(pmem->non_gc_memory, ctx->stack_bot, "pdf_create_context");
gs_free_object(pmem->non_gc_memory, ctx, "pdf_create_context");
- gs_gstate_free(pgs);
+ if (initial_gstate == NULL)
+ gs_gstate_free(pgs);
return NULL;
}
ctx->pgs = pgs;
- pdfi_gstate_set_client(ctx, pgs);
- /* Declare PDL client support for high level patterns, for the benefit
- * of pdfwrite and other high-level devices
- */
- ctx->pgs->have_pattern_streams = true;
- ctx->device_state.preserve_tr_mode = 0;
- ctx->args.notransparency = false;
+ if (initial_gstate == NULL) {
+ pdfi_gstate_set_client(ctx, pgs);
+ /* Declare PDL client support for high level patterns, for the benefit
+ * of pdfwrite and other high-level devices
+ */
+ ctx->pgs->have_pattern_streams = true;
+ ctx->device_state.preserve_tr_mode = 0;
+ }
+
+ ctx->args.notransparency = false;
ctx->main_stream = NULL;
/* Setup some flags that don't default to 'false' */
@@ -1242,6 +1251,7 @@ pdf_context *pdfi_create_context(gs_memory_t *pmem)
ctx->get_glyph_name = pdfi_glyph_name;
ctx->get_glyph_index = pdfi_glyph_index;
+ ctx->job_gstate_level = ctx->pgs->level;
/* Weirdly the graphics library wants us to always have two gstates, the
* initial state and at least one saved state. if we don't then when we
* grestore back to the initial state, it immediately saves another one.
@@ -1300,7 +1310,7 @@ pdfi_print_cache(pdf_context *ctx)
* called by pdf_free_context (in case of errors during the file leaving state around)
* and by pdfi_close_pdf_file.
*/
-int pdfi_clear_context(pdf_context *ctx)
+int pdfi_clear_context(pdf_context *ctx, bool free_gstate)
{
#if CACHE_STATISTICS
float compressed_hit_rate = 0.0, hit_rate = 0.0;
@@ -1371,20 +1381,20 @@ int pdfi_clear_context(pdf_context *ctx)
}
ctx->main_stream_length = 0;
- if(ctx->pgs != NULL) {
+ if(ctx->pgs != NULL && free_gstate) {
gx_pattern_cache_free(ctx->pgs->pattern_cache);
ctx->pgs->pattern_cache = NULL;
if (ctx->pgs->font)
pdfi_countdown_current_font(ctx);
-
- /* We use gs_grestore_only() instead of gs_grestore, because gs_grestore
- * will not restore below two gstates and we want to clear the entire
- * stack of saved states, back to the initial state.
- */
- while (ctx->pgs->level != ctx->job_gstate_level && ctx->pgs->saved)
- gs_grestore_only(ctx->pgs);
}
+ /* We use gs_grestore_only() instead of gs_grestore, because gs_grestore
+ * will not restore below two gstates and we want to clear the entire
+ * stack of saved states, back to the initial state.
+ */
+ while (ctx->pgs->level != ctx->job_gstate_level && ctx->pgs->saved)
+ gs_grestore_only(ctx->pgs);
+
pdfi_free_DefaultQState(ctx);
pdfi_oc_free(ctx);
@@ -1472,19 +1482,22 @@ int pdfi_clear_context(pdf_context *ctx)
return 0;
}
-int pdfi_free_context(pdf_context *ctx)
+int pdfi_free_context(pdf_context *ctx, bool free_gstate)
{
- pdfi_clear_context(ctx);
+ pdfi_clear_context(ctx, free_gstate);
gs_free_object(ctx->memory, ctx->stack_bot, "pdfi_free_context");
pdfi_free_name_table(ctx);
- while (ctx->pgs->saved)
- gs_grestore_only(ctx->pgs);
-
/* And here we free the initial graphics state */
- gs_gstate_free(ctx->pgs);
+ if (free_gstate) {
+ while (ctx->pgs->saved)
+ gs_grestore_only(ctx->pgs);
+
+ gs_gstate_free(ctx->pgs);
+ }
+
ctx->pgs = NULL;
if (ctx->font_dir)
diff --git a/pdf/ghostpdf.h b/pdf/ghostpdf.h
index 64ba5c583..d9e1e6b80 100644
--- a/pdf/ghostpdf.h
+++ b/pdf/ghostpdf.h
@@ -509,9 +509,9 @@ typedef struct pdf_context_s
#define OBJ_CTX(o) ((pdf_context *)(o->ctx))
#define OBJ_MEMORY(o) OBJ_CTX(o)->memory
-pdf_context *pdfi_create_context(gs_memory_t *pmem);
-int pdfi_clear_context(pdf_context *ctx);
-int pdfi_free_context(pdf_context *ctx);
+pdf_context *pdfi_create_context(gs_memory_t *pmem, gs_gstate *initial_gstate);
+int pdfi_clear_context(pdf_context *ctx, bool free_gstate);
+int pdfi_free_context(pdf_context *ctx, bool free_gstate);
int pdfi_get_name_index(pdf_context *ctx, char *name, int len, unsigned int *returned);
int pdfi_name_from_index(pdf_context *ctx, int index, unsigned char **name, unsigned int *len);
diff --git a/pdf/pdftop.c b/pdf/pdftop.c
index dd532949a..3a729d325 100644
--- a/pdf/pdftop.c
+++ b/pdf/pdftop.c
@@ -112,7 +112,7 @@ pdf_impl_allocate_interp_instance(pl_interp_implementation_t *impl,
if (!instance)
return gs_error_VMerror;
- ctx = pdfi_create_context(pmem);
+ ctx = pdfi_create_context(pmem, NULL);
if (ctx == NULL) {
gs_free_object(pmem, instance, "pdf_impl_allocate_interp_instance");
@@ -664,7 +664,7 @@ pdf_impl_deallocate_interp_instance(pl_interp_implementation_t *impl)
gs_memory_t *mem = ctx->memory;
int code = 0;
- code = pdfi_free_context(ctx);
+ code = pdfi_free_context(ctx, true);
gs_free_object(mem, instance, "pdf_impl_deallocate_interp_instance");
diff --git a/psi/zpdfops.c b/psi/zpdfops.c
index d2684a916..46fe1ae01 100644
--- a/psi/zpdfops.c
+++ b/psi/zpdfops.c
@@ -289,7 +289,7 @@ static int zdopdffile(i_ctx_t *i_ctx_p)
if (code < 0)
return_error(gs_error_VMerror);
- ctx = pdfi_create_context(cmem);
+ ctx = pdfi_create_context(cmem, igs);
if (ctx == NULL) {
code = gs_note_error(gs_error_VMerror);
goto done;
@@ -310,7 +310,7 @@ static int zdopdffile(i_ctx_t *i_ctx_p)
code = gs_grestore(ctx->pgs);
done:
if (ctx)
- code2 = pdfi_free_context(ctx);
+ code2 = pdfi_free_context(ctx, false);
/* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
(void)gs_memory_chunk_unwrap(cmem);
@@ -351,7 +351,7 @@ pdfctx_finalize(const gs_memory_t *cmem, void *vptr)
pdfctx_t *pdfctx = vptr;
if (cmem != NULL && pdfctx->ctx != NULL)
- (void)pdfi_free_context(pdfctx->ctx);
+ (void)pdfi_free_context(pdfctx->ctx, false);
}
static int zPDFstream(i_ctx_t *i_ctx_p)
@@ -425,7 +425,7 @@ static int zPDFclose(i_ctx_t *i_ctx_p)
if (pdfctx->ctx != NULL) {
gs_memory_t *cmem = pdfctx->ctx->memory;
- code = pdfi_free_context(pdfctx->ctx);
+ code = pdfi_free_context(pdfctx->ctx, false);
/* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
(void)gs_memory_chunk_unwrap(cmem);
pdfctx->ctx = NULL;
@@ -784,7 +784,7 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
if (code < 0)
return_error(gs_error_VMerror);
- ctx = pdfi_create_context(cmem);
+ ctx = pdfi_create_context(cmem, igs);
if (ctx == NULL) {
code = gs_note_error(gs_error_VMerror);
goto error;
@@ -956,7 +956,7 @@ static int zPDFInit(i_ctx_t *i_ctx_p)
error:
if (ctx)
- pdfi_free_context(ctx);
+ pdfi_free_context(ctx, false);
/* gs_memory_chunk_unwrap() returns the "wrapped" allocator, which we don't need */
(void)gs_memory_chunk_unwrap(cmem);
if (pdfctx)