summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pdf/pdf_trans.c')
-rw-r--r--pdf/pdf_trans.c103
1 files changed, 87 insertions, 16 deletions
diff --git a/pdf/pdf_trans.c b/pdf/pdf_trans.c
index 93ab8a6c..df0194d7 100644
--- a/pdf/pdf_trans.c
+++ b/pdf/pdf_trans.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
@@ -20,6 +20,7 @@
#include "pdf_trans.h"
#include "pdf_dict.h"
#include "pdf_colour.h"
+#include "pdf_font_types.h"
#include "pdf_gstate.h"
#include "pdf_array.h"
#include "pdf_image.h"
@@ -32,6 +33,7 @@
#include "gscoord.h" /* For gs_setmatrix()*/
#include "gsstate.h" /* For gs_currentstrokeoverprint() and others */
#include "gspath.h" /* For gs_clippath() */
+#include "gsicc_cache.h" /* For gsicc_profiles_equal() */
/* Implement the TransferFunction using a Function. */
static int
@@ -156,13 +158,15 @@ static int pdfi_trans_set_mask(pdf_context *ctx, pdfi_int_gstate *igs, int color
code = pdfi_dict_knownget_type(ctx, SMask, "S", PDF_NAME, (pdf_obj **)&S);
if (code <= 0) {
dmprintf(ctx->memory, "WARNING: Missing 'S' in SMask (defaulting to Luminosity)\n");
+ subtype = TRANSPARENCY_MASK_Luminosity;
}
- if (pdfi_name_is(S, "Luminosity")) {
+ else if (pdfi_name_is(S, "Luminosity")) {
subtype = TRANSPARENCY_MASK_Luminosity;
} else if (pdfi_name_is(S, "Alpha")) {
subtype = TRANSPARENCY_MASK_Alpha;
} else {
dmprintf(ctx->memory, "WARNING: Unknown subtype 'S' in SMask (defaulting to Luminosity)\n");
+ subtype = TRANSPARENCY_MASK_Luminosity;
}
/* TR is transfer function (Optional) */
@@ -172,6 +176,11 @@ static int pdfi_trans_set_mask(pdf_context *ctx, pdfi_int_gstate *igs, int color
code = pdfi_build_function(ctx, &gsfunc, NULL, 1, TR, NULL);
if (code < 0)
goto exit;
+ if (gsfunc->params.m != 1 || gsfunc->params.n != 1) {
+ pdfi_free_function(ctx, gsfunc);
+ gsfunc = NULL;
+ dmprintf(ctx->memory, "WARNING: Ignoring invalid TR (number of inpuits or outputs not 1) in SMask\n");
+ }
} else if (TR->type == PDF_NAME) {
if (!pdfi_name_is((pdf_name *)TR, "Identity")) {
dmprintf(ctx->memory, "WARNING: Unknown TR in SMask\n");
@@ -401,6 +410,32 @@ static int pdfi_transparency_group_common(pdf_context *ctx, pdf_dict *page_dict,
return pdfi_gs_begin_transparency_group(ctx->pgs, &params, (const gs_rect *)bbox, group_type);
}
+static bool pdfi_outputprofile_matches_oiprofile(pdf_context *ctx)
+{
+ cmm_dev_profile_t *profile_struct;
+ int code;
+ int k;
+
+ code = dev_proc(ctx->pgs->device, get_profile)(ctx->pgs->device, &profile_struct);
+ if (code < 0)
+ return true; /* Assume they match by default and in error condition */
+
+ if (profile_struct->oi_profile == NULL)
+ return true; /* no OI profile so no special case to worry about */
+ else {
+ /* Check the device profile(s). If any of them do not match, then
+ we assume there is not a match and it may be necessary to
+ use the pdf14 device to prerender to the OI profile */
+ for (k = 0; k < NUM_DEVICE_PROFILES; k++) {
+ if (profile_struct->device_profile[k] != NULL) {
+ if (!gsicc_profiles_equal(profile_struct->oi_profile, profile_struct->device_profile[k]))
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
/* Begin a simple group
* pathbbox -- bbox to use, but can be NULL
*/
@@ -591,14 +626,19 @@ void pdfi_trans_set_needs_OP(pdf_context *ctx)
ctx->page.needs_OP = false;
ctx->page.simulate_op = false;
- switch(ctx->args.overprint_control) {
- case PDF_OVERPRINT_DISABLE:
+ switch(ctx->pgs->device->icc_struct->overprint_control) {
+ case gs_overprint_control_disable:
/* Use defaults */
break;
- case PDF_OVERPRINT_SIMULATE:
+ case gs_overprint_control_simulate:
if (!device_transparency && ctx->page.has_OP) {
if (is_cmyk) {
- if (ctx->page.num_spots > 0) {
+ /* If the page has spots and the device is not spot capable OR
+ if the output intent profile is to be used, but we have
+ a device output profile that is different, then we will be
+ doing simulation with the pdf14 device buffer */
+ if ((ctx->page.num_spots > 0 && !ctx->device_state.spot_capable) ||
+ !pdfi_outputprofile_matches_oiprofile(ctx)) {
ctx->page.needs_OP = true;
ctx->page.simulate_op = true;
}
@@ -608,7 +648,7 @@ void pdfi_trans_set_needs_OP(pdf_context *ctx)
}
}
break;
- case PDF_OVERPRINT_ENABLE:
+ case gs_overprint_control_enable:
default:
if (!is_cmyk || device_transparency)
ctx->page.needs_OP = false;
@@ -624,7 +664,7 @@ void pdfi_trans_set_needs_OP(pdf_context *ctx)
}
/* Figures out if current colorspace is okay for Overprint (see pdf_ops.ps/okOPcs and setupOPtrans) */
-static bool pdfi_trans_okOPcs(pdf_context *ctx)
+bool pdfi_trans_okOPcs(pdf_context *ctx)
{
gs_color_space_index csi;
@@ -707,11 +747,22 @@ int pdfi_trans_setup(pdf_context *ctx, pdfi_trans_state_t *state, gs_rect *bbox,
/* TODO: error handling... */
if (need_group) {
+ bool isolated = false;
+ mode = gs_currentblendmode(ctx->pgs);
+
stroked_bbox = (caller == TRANSPARENCY_Caller_Stroke || caller == TRANSPARENCY_Caller_FillStroke);
+
/* When changing to compatible overprint bm, the group pushed must be non-isolated. The exception
- is if we have a softmask. See /setupOPtrans in pdf_ops.ps */
- code = pdfi_trans_begin_simple_group(ctx, bbox, stroked_bbox, igs->SMask != NULL, false);
- state->GroupPushed = true;
+ is if we have a softmask AND the blend mode is not normal and not compatible.
+ See /setupOPtrans in pdf_ops.ps */
+ if (igs->SMask != NULL && mode != BLEND_MODE_Normal && mode != BLEND_MODE_Compatible)
+ isolated = true;
+ code = pdfi_trans_begin_simple_group(ctx, bbox, stroked_bbox, isolated, false);
+
+ /* Group was not pushed if error */
+ if (code >= 0)
+ state->GroupPushed = true;
+
state->saveStrokeAlpha = gs_getstrokeconstantalpha(ctx->pgs);
state->saveFillAlpha = gs_getfillconstantalpha(ctx->pgs);
code = gs_setfillconstantalpha(ctx->pgs, 1.0);
@@ -725,12 +776,33 @@ int pdfi_trans_setup(pdf_context *ctx, pdfi_trans_state_t *state, gs_rect *bbox,
return code;
}
+int pdfi_trans_required(pdf_context *ctx)
+{
+ gs_blend_mode_t mode;
+
+ if (!ctx->page.has_transparency)
+ return 0;
+
+ mode = gs_currentblendmode(ctx->pgs);
+ if ((mode == BLEND_MODE_Normal || mode == BLEND_MODE_Compatible) &&
+ ctx->pgs->fillconstantalpha == 1 &&
+ ctx->pgs->strokeconstantalpha == 1 &&
+ ((pdfi_int_gstate *)ctx->pgs->client_data)->SMask == NULL)
+ return 0;
+
+ return 1;
+}
+
int pdfi_trans_setup_text(pdf_context *ctx, pdfi_trans_state_t *state, bool is_show)
{
- int Trmode = gs_currenttextrenderingmode(ctx->pgs);
+ int Trmode;
int code, code1;
gs_rect bbox;
+ if (!pdfi_trans_required(ctx))
+ return 0;
+
+ Trmode = gs_currenttextrenderingmode(ctx->pgs);
code = gs_gsave(ctx->pgs);
if (code < 0) goto exit;
@@ -766,11 +838,10 @@ int pdfi_trans_setup_text(pdf_context *ctx, pdfi_trans_state_t *state, bool is_s
int pdfi_trans_teardown_text(pdf_context *ctx, pdfi_trans_state_t *state)
{
- int code = 0;
+ if (!pdfi_trans_required(ctx))
+ return 0;
- code = pdfi_trans_teardown(ctx, state);
-
- return code;
+ return pdfi_trans_teardown(ctx, state);
}
int pdfi_trans_teardown(pdf_context *ctx, pdfi_trans_state_t *state)