summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_gstate.c')
-rw-r--r--pdf/pdf_gstate.c114
1 files changed, 51 insertions, 63 deletions
diff --git a/pdf/pdf_gstate.c b/pdf/pdf_gstate.c
index 7544aa48..c1444b4b 100644
--- a/pdf/pdf_gstate.c
+++ b/pdf/pdf_gstate.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2021 Artifex Software, Inc.
+/* Copyright (C) 2018-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -17,6 +17,7 @@
#include "pdf_int.h"
#include "pdf_doc.h"
+#include "pdf_font_types.h"
#include "pdf_gstate.h"
#include "pdf_stack.h"
#include "pdf_dict.h"
@@ -113,7 +114,9 @@ pdfi_gstate_copy_cb(void *to, const void *from)
*/
if (igs_to != NULL) {
pdfi_gstate_smask_free(igs_to);
+ pdfi_countdown(igs_to->current_font);
*(pdfi_int_gstate *) igs_to = *igs_from;
+ pdfi_countup(igs_to->current_font);
pdfi_gstate_smask_install(igs_to, igs_from->memory, igs_from->SMask, igs_from->GroupGState);
}
return 0;
@@ -127,6 +130,7 @@ pdfi_gstate_free_cb(void *old, gs_memory_t * mem, gs_gstate *pgs)
if (old == NULL)
return;
pdfi_gstate_smask_free(igs);
+ pdfi_countdown(igs->current_font);
/* We need to use the graphics state memory, in case we are running under Ghostscript. */
gs_free_object(pgs->memory, igs, "pdfi_gstate_free");
}
@@ -145,6 +149,8 @@ pdfi_gstate_set_client(pdf_context *ctx, gs_gstate *pgs)
/* We need to use the graphics state memory, in case we are running under Ghostscript. */
igs = pdfi_gstate_alloc_cb(pgs->memory);
+ if (igs == NULL)
+ return_error(gs_error_VMerror);
igs->ctx = ctx;
gs_gstate_set_client(pgs, igs, &pdfi_gstate_procs, true /* TODO: client_has_pattern_streams ? */);
return 0;
@@ -252,93 +258,38 @@ int pdfi_op_Q(pdf_context *ctx)
return code;
}
+/* We want pdfi_grestore() so we can track and warn of "too many Qs"
+ * in the interests of symmetry, we also have pdfi_gsave()
+ */
int pdfi_gsave(pdf_context *ctx)
{
- int code;
-
- code = gs_gsave(ctx->pgs);
-
- if(code < 0)
- return code;
- else {
- pdfi_countup_current_font(ctx);
- return 0;
- }
+ return gs_gsave(ctx->pgs);
}
int pdfi_grestore(pdf_context *ctx)
{
- int code;
- pdf_font *font = NULL, *font1 = NULL;
+ int code = 0;
/* Make sure we have encountered as many gsave operations in this
* stream as grestores. If not, log an error
*/
if (ctx->pgs->level > ctx->current_stream_save.gsave_level) {
- font = pdfi_get_current_pdf_font(ctx);
-
code = gs_grestore(ctx->pgs);
-
- font1 = pdfi_get_current_pdf_font(ctx);
- if (font != NULL && (font != font1 || ((pdf_obj *)font)->refcnt > 1)) {
- /* TODO: This countdown might have been causing memory corruption (dangling pointer)
- * but seems to be okay now. Maybe was fixed by other memory issue. 8-28-19
- * If you come upon this comment in the future and it all seems fine, feel free to
- * clean this up... (delete comment, remove the commented out warning message, etc)
- */
-#if REFCNT_DEBUG
- dbgmprintf2(ctx->memory, "pdfi_grestore() counting down font UID %ld, refcnt %d\n",
- font->UID, font->refcnt);
-#endif
- // dbgmprintf(ctx->memory, "WARNING pdfi_grestore() DISABLED pdfi_countdown (FIXME!)\n");
- pdfi_countdown(font);
- }
-
- return code;
} else {
/* We don't throw an error here, we just ignore it and continue */
pdfi_set_warning(ctx, 0, NULL, W_PDF_TOOMANYQ, "pdfi_grestore", (char *)"ignoring q");
}
- return 0;
+ return code;
}
-/* gs_setgstate is somewhat unpleasant from our point of view, because it replaces
- * the content of the graphics state, without going through our pdfi_gsave/pdfi_grestore
- * functionaltiy. In particular we replace the current font in the graphics state when
- * we call it, and this means we *don't* count down the PDF_font object reference count
- * which leads to an incorrect count and either memory leaks or early freeing.
- * This function *requires* that the calling function will do a pdfi_gsave *before*
- * calling pdfi_setgstate, and a pdfi_grestore *after* calling pdfi_gs_setgstate.
- * it correctly increments/decrements the font reference counts for that condition
- * and no other.
- */
int pdfi_gs_setgstate(gs_gstate * pgs, const gs_gstate * pfrom)
{
- pdf_font *font = NULL;
int code = 0;
- /* We are going to release a reference to the font from the graphics state
- * (if there is one) so count it down to keep things straight.
- */
- if (pgs->font) {
- font = (pdf_font *)pgs->font->client_data;
- if (font)
- pdfi_countdown(font);
- }
-
code = gs_setgstate(pgs, pfrom);
if (code < 0)
return code;
- /* The copied gstate may have contained a font, and we expect to do a
- * pdfi_grestore on exit from here, which will count down the font
- * so count it up now in preparation.
- */
- if (pgs->font) {
- font = (pdf_font *)pgs->font->client_data;
- if (font)
- pdfi_countup(font);
- }
return code;
}
@@ -924,6 +875,11 @@ static int pdfi_set_all_transfers(pdf_context *ctx, pdf_array *a, pdf_dict *page
pdfi_countdown(o);
goto exit;
}
+ if (pfn[i]->params.m != 1 || pfn[i]->params.n != 1) {
+ pdfi_countdown(o);
+ code = gs_note_error(gs_error_rangecheck);
+ goto exit;
+ }
} else {
pdfi_countdown(o);
code = gs_note_error(gs_error_typecheck);
@@ -987,7 +943,6 @@ static int pdfi_set_all_transfers(pdf_context *ctx, pdf_array *a, pdf_dict *page
}
}
exit:
-// (void)pdfi_seek(ctx, ctx->main_stream, saved_stream_offset, SEEK_SET);
for (i = 0; i < 4; i++) {
pdfi_free_function(ctx, pfn[i]);
}
@@ -1006,6 +961,11 @@ static int pdfi_set_gray_transfer(pdf_context *ctx, pdf_obj *tr_obj, pdf_dict *p
if (code < 0)
return code;
+ if (pfn->params.m != 1 || pfn->params.n != 1) {
+ (void)pdfi_free_function(ctx, pfn);
+ return_error(gs_error_rangecheck);
+ }
+
gs_settransfer_remap(ctx->pgs, gs_mapped_transfer, false);
for (i = 0; i < transfer_map_size; i++) {
float v, f;
@@ -1206,6 +1166,7 @@ static int build_type1_halftone(pdf_context *ctx, pdf_dict *halftone_dict, pdf_d
gs_screen_enum *penum = NULL;
gs_point pt;
gx_transfer_map *pmap = NULL;
+ bool as;
code = pdfi_dict_get_number(ctx, halftone_dict, "Frequency", &f);
if (code < 0)
@@ -1219,6 +1180,12 @@ static int build_type1_halftone(pdf_context *ctx, pdf_dict *halftone_dict, pdf_d
if (code < 0)
return code;
+ code = pdfi_dict_get_bool(ctx, halftone_dict, "AccurateScreens", &as);
+ if (code == gs_error_undefined)
+ as = 0;
+ else if (code < 0)
+ return code;
+
order = (gx_ht_order *)gs_alloc_bytes(ctx->memory, sizeof(gx_ht_order), "build_type1_halftone");
if (order == NULL) {
code = gs_note_error(gs_error_VMerror);
@@ -1275,6 +1242,7 @@ static int build_type1_halftone(pdf_context *ctx, pdf_dict *halftone_dict, pdf_d
phtc->params.spot.transfer = (code > 0 ? (gs_mapping_proc) 0 : gs_mapped_transfer);
phtc->params.spot.transfer_closure.proc = 0;
phtc->params.spot.transfer_closure.data = 0;
+ phtc->params.spot.accurate_screens = as;
phtc->type = ht_type_spot;
code = pdfi_get_name_index(ctx, name, len, (unsigned int *)&phtc->cname);
if (code < 0)
@@ -2199,6 +2167,16 @@ static int GS_CA(pdf_context *ctx, pdf_dict *GS, pdf_dict *stream_dict, pdf_dict
if (code < 0)
return code;
+ if (d1 > 1.0) {
+ pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_CA", NULL);
+ d1 = 1.0;
+ }
+
+ if (d1 < 0.0) {
+ pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_CA", NULL);
+ d1 = 0.0;
+ }
+
code = gs_setstrokeconstantalpha(ctx->pgs, d1);
return code;
}
@@ -2212,6 +2190,16 @@ static int GS_ca(pdf_context *ctx, pdf_dict *GS, pdf_dict *stream_dict, pdf_dict
if (code < 0)
return code;
+ if (d1 > 1.0) {
+ pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_ca", NULL);
+ d1 = 1.0;
+ }
+
+ if (d1 < 0.0) {
+ pdfi_set_warning(ctx, 0, NULL, W_PDF_CA_OUTOFRANGE, "GS_ca", NULL);
+ d1 = 0.0;
+ }
+
code = gs_setfillconstantalpha(ctx->pgs, d1);
return code;
}