diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2021-05-28 11:07:22 +0100 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2021-06-01 07:51:21 +0100 |
commit | a2ce7744473da06118de0c038045af35a25c041f (patch) | |
tree | 9030f825fc5d436801670f0c1c9d2e37c8041c50 | |
parent | 0be6b1335935c2c1faef0347a8b03c24fa6fed53 (diff) | |
download | ghostpdl-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.c | 71 | ||||
-rw-r--r-- | pdf/ghostpdf.h | 6 | ||||
-rw-r--r-- | pdf/pdftop.c | 4 | ||||
-rw-r--r-- | psi/zpdfops.c | 12 |
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) |