diff options
Diffstat (limited to 'pdf/pdf_trans.c')
-rw-r--r-- | pdf/pdf_trans.c | 103 |
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, ¶ms, (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) |