summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_check.c')
-rw-r--r--pdf/pdf_check.c92
1 files changed, 85 insertions, 7 deletions
diff --git a/pdf/pdf_check.c b/pdf/pdf_check.c
index 13d974cb..00933bdf 100644
--- a/pdf/pdf_check.c
+++ b/pdf/pdf_check.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2019-2021 Artifex Software, Inc.
+/* Copyright (C) 2019-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -24,10 +24,12 @@
#include "pdf_loop_detect.h"
#include "pdf_colour.h"
#include "pdf_trans.h"
+#include "pdf_font_types.h"
#include "pdf_gstate.h"
#include "pdf_misc.h"
#include "pdf_check.h"
#include "pdf_device.h"
+#include "gsdevice.h" /* For gs_setdevice_no_erase */
#include "gspaint.h" /* For gs_erasepage() */
/* For performance and resource reasons we do not want to install the transparency blending
@@ -133,7 +135,8 @@ pdfi_check_init_tracker(pdf_context *ctx, pdfi_check_tracker_t *tracker)
memset(tracker->CheckedResources, 0x00, tracker->size);
- if (ctx->device_state.spot_capable || ctx->args.overprint_control == PDF_OVERPRINT_SIMULATE) {
+ if (ctx->device_state.spot_capable ||
+ (ctx->pgs->device->icc_struct->overprint_control) == gs_overprint_control_simulate) {
code = pdfi_dict_alloc(ctx, 32, &tracker->spot_dict);
if (code < 0)
goto cleanup;
@@ -1143,6 +1146,8 @@ int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup)
*/
pdfi_device_set_flags(ctx);
code = pdfi_check_init_tracker(ctx, &tracker);
+ if (code < 0)
+ goto exit;
/* Check for spots and transparency in this page */
code = pdfi_check_page_inner(ctx, page_dict, &tracker);
@@ -1156,20 +1161,88 @@ int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup)
/* If setup requested, tell the device about spots and transparency */
if (do_setup) {
gs_c_param_list list;
+ int a = 0;
+ pdf_name *Key = NULL;
+ pdf_obj *Value = NULL;
+ uint64_t index = 0;
gs_c_param_list_write(&list, ctx->memory);
/* If there are spot colours (and by inference, the device renders spot plates) then
* send the number of Spots to the device, so it can setup correctly.
*/
- if (tracker.spot_dict)
- param_write_int((gs_param_list *)&list, "PageSpotColors", &spots);
+ if (tracker.spot_dict) {
+ /* There is some awkwardness here. If the SeparationColorNames setting
+ * fails, we want to ignore it (this can mean that we exceeded the maximum
+ * number of colourants and some will be converted to CMYK). But if that happens,
+ * any other parameters in the same list which haven't already been prcoessed
+ * will be lost. So we need to send two lists, the SeparationColorNames and
+ * 'everything else'.
+ */
+ if (spots > 0) {
+ gs_param_string_array sa;
+ gs_param_string *table = NULL;
+
+ table = (gs_param_string *)gs_alloc_byte_array(ctx->memory, spots, sizeof(gs_param_string), "SeparationNames");
+ if (table != NULL)
+ {
+ memset(table, 0x00, spots * sizeof(gs_param_string));
+
+ code = pdfi_dict_first(ctx, tracker.spot_dict, (pdf_obj **)&Key, &Value, &index);
+ while (code >= 0)
+ {
+ if (Key->type == PDF_NAME) {
+ table[a].data = ((pdf_string *)Key)->data;
+ table[a].size = ((pdf_string *)Key)->length;
+ table[a++].persistent = false;
+ }
+ /* Although we count down the returned PDF objects here, the pointers
+ * to the name data remain valid and won't move. Provided we don't
+ * retain the pointers after we free the tracker dictionary this is
+ * safe to do.
+ */
+ pdfi_countdown(Key);
+ Key = NULL;
+ pdfi_countdown(Value);
+ Value = NULL;
+ code = pdfi_dict_next(ctx, tracker.spot_dict, (pdf_obj **)&Key, &Value, &index);
+ }
+ sa.data = table;
+ sa.size = spots;
+ sa.persistent = false;
+
+ (void)param_write_string_array((gs_param_list *)&list, "SeparationColorNames", &sa);
+ gs_c_param_list_read(&list);
+ code = gs_putdeviceparams(ctx->pgs->device, (gs_param_list *)&list);
+ gs_c_param_list_release(&list);
- code = param_write_bool((gs_param_list *)&list, "PageUsesTransparency",
- &tracker.transparent);
+ gs_free_object(ctx->memory, table, "SeparationNames");
+ if (code > 0) {
+ /* The device was closed, we need to reopen it */
+ code = gs_setdevice_no_erase(ctx->pgs, ctx->pgs->device);
+ if (code < 0)
+ goto exit;
+ gs_erasepage(ctx->pgs);
+ }
+
+ /* Reset the list back to being writeable */
+ gs_c_param_list_write(&list, ctx->memory);
+ }
+ else {
+ code = gs_note_error(gs_error_VMerror);
+ goto exit;
+ }
+ }
+ /* Update the number of spots */
+ param_write_int((gs_param_list *)&list, "PageSpotColors", &spots);
+ }
+ /* Update the page transparency */
+ (void)param_write_bool((gs_param_list *)&list, "PageUsesTransparency",
+ &tracker.transparent);
gs_c_param_list_read(&list);
code = gs_putdeviceparams(ctx->pgs->device, (gs_param_list *)&list);
gs_c_param_list_release(&list);
+
if (code > 0) {
/* The device was closed, we need to reopen it */
code = gs_setdevice_no_erase(ctx->pgs, ctx->pgs->device);
@@ -1180,10 +1253,15 @@ int pdfi_check_page(pdf_context *ctx, pdf_dict *page_dict, bool do_setup)
}
/* Set our values in the context, for caller */
- ctx->page.has_transparency = tracker.transparent;
+ if (!ctx->args.notransparency)
+ ctx->page.has_transparency = tracker.transparent;
ctx->page.num_spots = spots;
ctx->page.has_OP = tracker.has_overprint;
+ /* High level devices do not render overprint */
+ if (ctx->device_state.HighLevelDevice)
+ ctx->page.has_OP = false;
+
exit:
(void)pdfi_check_free_tracker(ctx, &tracker);
return code;