diff options
author | Sam James <sam@gentoo.org> | 2022-03-29 10:27:10 +0100 |
---|---|---|
committer | Sam James <sam@gentoo.org> | 2022-04-17 12:53:05 +0100 |
commit | 085bde903b9e684c3c1160e4df912bea9a660997 (patch) | |
tree | c4f5e6e9f2422e869ca5bc0b944520d451001282 /pdf/pdf_colour.c | |
parent | Import Ghostscript 9.55 (diff) | |
download | ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.tar.gz ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.tar.bz2 ghostscript-gpl-patches-085bde903b9e684c3c1160e4df912bea9a660997.zip |
Import Ghostscript 9.56.0ghostscript-9.56
Signed-off-by: Sam James <sam@gentoo.org>
Diffstat (limited to 'pdf/pdf_colour.c')
-rw-r--r-- | pdf/pdf_colour.c | 397 |
1 files changed, 337 insertions, 60 deletions
diff --git a/pdf/pdf_colour.c b/pdf/pdf_colour.c index e6061db1..dcc3ebf0 100644 --- a/pdf/pdf_colour.c +++ b/pdf/pdf_colour.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 @@ -24,9 +24,12 @@ #include "pdf_misc.h" #include "gsicc_manage.h" #include "gsicc_profilecache.h" +#include "gsicc_cache.h" + #include "gsicc_create.h" #include "gsptype2.h" + #include "pdf_file.h" #include "pdf_dict.h" #include "pdf_loop_detect.h" @@ -189,7 +192,7 @@ static int pdfi_check_for_spots_by_array(pdf_context *ctx, pdf_array *color_arra if (code < 0) goto exit; - code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy); + code = pdfi_dict_put_obj(ctx, spot_dict, name, dummy, true); pdfi_countdown(name); if (code < 0) break; @@ -216,7 +219,7 @@ static int pdfi_check_for_spots_by_array(pdf_context *ctx, pdf_array *color_arra if (code < 0) goto exit; - code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy); + code = pdfi_dict_put_obj(ctx, spot_dict, (pdf_obj *)space, dummy, true); goto exit; } else { code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", @@ -305,9 +308,15 @@ int pdfi_ri(pdf_context *ctx) static void pdfi_cspace_free_callback(gs_memory_t * mem, void *cs) { gs_color_space *pcs = (gs_color_space *)cs; - pdf_context *ctx = (pdf_context *)pcs->interpreter_data; + pdf_obj *o = (pdf_obj *)pcs->interpreter_data; + pdf_context *ctx = NULL; gs_function_t *pfn; + if (o == NULL) + return; + + ctx = o->ctx; + if (gs_color_space_get_index(pcs) == gs_color_space_index_Separation) { /* Handle cleanup of Separation functions if applicable */ pfn = gs_cspace_get_sepr_function(pcs); @@ -321,6 +330,10 @@ static void pdfi_cspace_free_callback(gs_memory_t * mem, void *cs) if (pfn) pdfi_free_function(ctx, pfn); } + if (o->type != PDF_CTX) { + pdfi_countdown(o); + pcs->interpreter_data = NULL; + } } int pdfi_gs_setgray(pdf_context *ctx, double d) @@ -328,7 +341,7 @@ int pdfi_gs_setgray(pdf_context *ctx, double d) int code = 0; /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */ - if (ctx->text.inside_CharProc && ctx->text.CharProc_is_d1) + if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) return 0; if (ctx->page.DefaultGray_cs != NULL) { @@ -337,15 +350,15 @@ int pdfi_gs_setgray(pdf_context *ctx, double d) code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultGray_cs); if (code < 0) return code; - pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, NULL); cc.paint.values[0] = d; + cc.pattern = 0; return gs_setcolor(ctx->pgs, &cc); } else { code = gs_setgray(ctx->pgs, d); if (code < 0) return code; - pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback); } + pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback); return 0; } @@ -354,7 +367,7 @@ int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b) int code = 0; /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */ - if (ctx->text.inside_CharProc && ctx->text.CharProc_is_d1) + if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) return 0; if (ctx->page.DefaultRGB_cs != NULL) { @@ -367,6 +380,7 @@ int pdfi_gs_setrgbcolor(pdf_context *ctx, double r, double g, double b) cc.paint.values[0] = r; cc.paint.values[1] = g; cc.paint.values[2] = b; + cc.pattern = 0; return gs_setcolor(ctx->pgs, &cc); } else { code = gs_setrgbcolor(ctx->pgs, r, g, b); @@ -382,7 +396,7 @@ static int pdfi_gs_setcmykcolor(pdf_context *ctx, double c, double m, double y, int code = 0; /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */ - if (ctx->text.inside_CharProc && ctx->text.CharProc_is_d1) + if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) return 0; if (ctx->page.DefaultCMYK_cs != NULL) { @@ -391,18 +405,18 @@ static int pdfi_gs_setcmykcolor(pdf_context *ctx, double c, double m, double y, code = gs_setcolorspace(ctx->pgs, ctx->page.DefaultCMYK_cs); if (code < 0) return code; - pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, NULL); cc.paint.values[0] = c; cc.paint.values[1] = m; cc.paint.values[2] = y; cc.paint.values[3] = k; + cc.pattern = 0; return gs_setcolor(ctx->pgs, &cc); } else { code = gs_setcmykcolor(ctx->pgs, c, m, y, k); if (code < 0) return code; - pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback); } + pdfi_set_colour_callback(ctx->pgs->color[0].color_space, ctx, pdfi_cspace_free_callback); return 0; } @@ -413,7 +427,7 @@ int pdfi_gs_setcolorspace(pdf_context *ctx, gs_color_space *pcs) */ if (ctx->pgs->color[0].color_space->id != pcs->id) { /* PDF Reference 1.7 p423, any colour operators in a CharProc, following a d1, should be ignored */ - if (ctx->text.inside_CharProc && ctx->text.CharProc_is_d1) + if (ctx->text.inside_CharProc && ctx->text.CharProc_d_type != pdf_type3_d0) return 0; pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback); @@ -699,9 +713,14 @@ int pdfi_setstrokecolor(pdf_context *ctx) int ncomps, code; gs_client_color cc; + cc.pattern = 0; gs_swapcolors_quick(ctx->pgs); pcs = gs_currentcolorspace(ctx->pgs); ncomps = cs_num_components(pcs); + if (ncomps < 1) { + gs_swapcolors_quick(ctx->pgs); + return_error(gs_error_syntaxerror); + } code = pdfi_get_color_from_stack(ctx, &cc, ncomps); if (code == 0) { code = gs_setcolor(ctx->pgs, &cc); @@ -716,7 +735,10 @@ int pdfi_setfillcolor(pdf_context *ctx) int ncomps, code; gs_client_color cc; + cc.pattern = 0; ncomps = cs_num_components(pcs); + if (ncomps < 1) + return_error(gs_error_syntaxerror); code = pdfi_get_color_from_stack(ctx, &cc, ncomps); if (code == 0) { code = gs_setcolor(ctx->pgs, &cc); @@ -750,16 +772,18 @@ pdfi_setcolorN(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, boo if (pdfi_count_stack(ctx) < 1) { code = gs_note_error(gs_error_stackunderflow); - goto cleanupExit; + goto cleanupExit1; } + memset(&cc, 0x00, sizeof(gs_client_color)); + if (pcs->type == &gs_color_space_type_Pattern) is_pattern = true; if (is_pattern) { if (ctx->stack_top[-1]->type != PDF_NAME) { pdfi_clearstack(ctx); code = gs_note_error(gs_error_syntaxerror); - goto cleanupExit; + goto cleanupExit0; } base_space = pcs->base_space; code = pdfi_pattern_set(ctx, stream_dict, page_dict, (pdf_name *)ctx->stack_top[-1], &cc); @@ -768,23 +792,27 @@ pdfi_setcolorN(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, boo /* Ignore the pattern if we failed to set it */ pdfi_set_warning(ctx, 0, NULL, W_PDF_BADPATTERN, "pdfi_setcolorN", (char *)"PATTERN: Error setting pattern"); code = 0; - goto cleanupExit; + goto cleanupExit1; } if (base_space && pattern_instance_uses_base_space(cc.pattern)) ncomps = cs_num_components(base_space); else ncomps = 0; - } else { + } else ncomps = cs_num_components(pcs); - cc.pattern = NULL; - } - if (ncomps > 0) + if (ncomps > 0) { code = pdfi_get_color_from_stack(ctx, &cc, ncomps); - if (code < 0) - goto cleanupExit; + if (code < 0) + goto cleanupExit1; + } if (pcs->type == &gs_color_space_type_Indexed) { + if (ncomps <= 0) + { + code = gs_note_error(gs_error_rangecheck); + goto cleanupExit1; + } if (cc.paint.values[0] < 0) cc.paint.values[0] = 0.0; else @@ -806,6 +834,7 @@ pdfi_setcolorN(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, boo code = gs_setcolor(ctx->pgs, &cc); +cleanupExit1: if (is_pattern) /* cc is a local scope variable, holding a reference to a pattern. * We need to count the refrence down before the variable goes out of scope @@ -813,7 +842,7 @@ pdfi_setcolorN(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, boo */ rc_decrement(cc.pattern, "pdfi_setcolorN"); -cleanupExit: +cleanupExit0: if (!is_fill) gs_swapcolors_quick(ctx->pgs); return code; @@ -824,7 +853,7 @@ cleanupExit: /* Starting with the ICCBased colour space */ /* This routine is mostly a copy of seticc() in zicc.c */ -static int pdfi_create_icc(pdf_context *ctx, char *Name, stream *s, int ncomps, int *icc_N, float *range_buff, gs_color_space **ppcs) +static int pdfi_create_icc(pdf_context *ctx, char *Name, stream *s, int ncomps, int *icc_N, float *range_buff, ulong dictkey, gs_color_space **ppcs) { int code, k; gs_color_space * pcs; @@ -981,13 +1010,16 @@ static int pdfi_create_icc(pdf_context *ctx, char *Name, stream *s, int ncomps, rc_adjust(picc_profile, -2, "pdfi_create_icc"); rc_increment(pcs->cmm_icc_profile_data); } + /* Add the color space to the profile cache */ + if (dictkey != 0) + gsicc_add_cs(ctx->pgs, pcs, dictkey); if (ppcs!= NULL){ *ppcs = pcs; pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback); } else { code = pdfi_gs_setcolorspace(ctx, pcs); - rc_decrement_only_cs(pcs, "pdfi_seticc_cal"); + rc_decrement_only_cs(pcs, "pdfi_create_icc"); } /* The context has taken a reference to the colorspace. We no longer need @@ -1003,6 +1035,34 @@ static int pdfi_create_iccprofile(pdf_context *ctx, pdf_stream *ICC_obj, char *c byte *profile_buffer; gs_offset_t savedoffset; int code, code1; + ulong dictkey = 0; + + /* See if the color space is in the profile cache */ + /* NOTE! 0 indicates a named colour space for JPX images, do not attempt to + * find a cached space for this. Conveniently should we somehow manage to get + * here from an array or other object which is not an indirect reference then we will + * again not attempt to cache the space or lookup the cache. + */ + if (!gs_currentoverrideicc(ctx->pgs)) { + if (ICC_obj->object_num != 0) { + gs_color_space *pcs = NULL; + + pcs = gsicc_find_cs(ICC_obj->object_num, ctx->pgs); + if (pcs != NULL) { + if (ppcs!= NULL){ + *ppcs = pcs; + } else { + code = pdfi_gs_setcolorspace(ctx, pcs); + rc_decrement_only_cs(pcs, "pdfi_create_iccprofile"); + } + *icc_N = gs_color_space_num_components(pcs); + /* We're passing back a new reference, increment the count */ + rc_adjust_only(pcs, 1, "pdfi_create_iccprofile, return cached ICC profile"); + return 0; + } + dictkey = ICC_obj->object_num; + } + } /* Save the current stream position, and move to the start of the profile stream */ savedoffset = pdfi_tell(ctx->main_stream); @@ -1022,7 +1082,7 @@ static int pdfi_create_iccprofile(pdf_context *ctx, pdf_stream *ICC_obj, char *c } /* Now, finally, we can call the code to create and set the profile */ - code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, ppcs); + code = pdfi_create_icc(ctx, cname, profile_stream->s, (int)N, icc_N, range, dictkey, ppcs); code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream); @@ -1059,6 +1119,10 @@ static int pdfi_create_iccbased(pdf_context *ctx, pdf_array *color_array, int in code = pdfi_dict_get_int(ctx, dict, "N", &N); if (code < 0) goto done; + if (N != 1 && N != 3 && N != 4) { + code = gs_note_error(gs_error_rangecheck); + goto done; + } code = pdfi_dict_knownget(ctx, dict, "Name", &Name); if (code > 0) { if(Name->type == PDF_STRING || Name->type == PDF_NAME) { @@ -1186,8 +1250,11 @@ static int pdfi_create_iccbased(pdf_context *ctx, pdf_array *color_array, int in break; } } - if (ppcs!= NULL) + if (ppcs!= NULL) { *ppcs = pcs; + if (pcs != NULL) + pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback); + } else { if (pcs != NULL) { code = pdfi_gs_setcolorspace(ctx, pcs); @@ -1351,6 +1418,7 @@ pdfi_seticc_cal(pdf_context *ctx, float *white, float *black, float *gamma, if (ppcs!= NULL){ *ppcs = pcs; + pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback); } else { code = pdfi_gs_setcolorspace(ctx, pcs); rc_decrement_only_cs(pcs, "pdfi_seticc_cal"); @@ -1404,7 +1472,7 @@ static int pdfi_create_CalGray(pdf_context *ctx, pdf_array *color_array, int ind goto exit; } - if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray)) { + if (pdfi_dict_knownget_type(ctx, CalGray_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) { if (pdfi_array_size(PDFArray) != 3){ code = gs_note_error(gs_error_rangecheck); goto exit; @@ -1426,7 +1494,7 @@ static int pdfi_create_CalGray(pdf_context *ctx, pdf_array *color_array, int ind PDFArray = NULL; } - if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f)) + if (pdfi_dict_knownget_number(ctx, CalGray_dict, "Gamma", &f) > 0) Gamma = (float)f; /* The PDF 1.7 reference states that Gamma * (if present) must be positive. @@ -1487,7 +1555,7 @@ static int pdfi_create_CalRGB(pdf_context *ctx, pdf_array *color_array, int inde goto exit; } - if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray)) { + if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "BlackPoint", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) { if (pdfi_array_size(PDFArray) != 3){ code = gs_note_error(gs_error_rangecheck); goto exit; @@ -1509,7 +1577,7 @@ static int pdfi_create_CalRGB(pdf_context *ctx, pdf_array *color_array, int inde PDFArray = NULL; } - if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray)) { + if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Gamma", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) { if (pdfi_array_size(PDFArray) != 3){ code = gs_note_error(gs_error_rangecheck); goto exit; @@ -1524,7 +1592,7 @@ static int pdfi_create_CalRGB(pdf_context *ctx, pdf_array *color_array, int inde PDFArray = NULL; } - if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray)) { + if (pdfi_dict_knownget_type(ctx, CalRGB_dict, "Matrix", PDF_ARRAY, (pdf_obj **)&PDFArray) > 0) { if (pdfi_array_size(PDFArray) != 9){ code = gs_note_error(gs_error_rangecheck); goto exit; @@ -1603,6 +1671,7 @@ static int pdfi_create_Separation(pdf_context *ctx, pdf_array *color_array, int goto pdfi_separation_error; rc_decrement(pcs_alt, "pdfi_create_Separation"); + pcs_alt = NULL; pcs->params.separation.mem = ctx->memory; pcs->params.separation.sep_type = sep_type; pcs->params.separation.sep_name = (char *)gs_alloc_bytes(ctx->memory->non_gc_memory, name->length + 1, "pdfi_setseparationspace(ink)"); @@ -1621,6 +1690,7 @@ static int pdfi_create_Separation(pdf_context *ctx, pdf_array *color_array, int */ code = pdfi_gs_setcolorspace(ctx, pcs); *ppcs = pcs; + pdfi_set_colour_callback(pcs, ctx, pdfi_cspace_free_callback); } else { code = pdfi_gs_setcolorspace(ctx, pcs); /* release reference from construction */ @@ -1754,10 +1824,12 @@ all_error: if (o->type == PDF_ARRAY) { ArrayAlternate = (pdf_array *)o; code = pdfi_create_colorspace_by_array(ctx, ArrayAlternate, 0, stream_dict, page_dict, &pcs_alt, inline_image); - if (code < 0) { - pdfi_countdown(o); + if (code < 0) + /* OSS-fuzz error 42973; we don't need to count down 'o' here because + * we have assigned it to ArrayAlternate and both the success and error + * paths count down ArrayAlternate. + */ goto pdfi_devicen_error; - } } else { code = gs_error_typecheck; @@ -2066,7 +2138,7 @@ pdfi_create_indexed(pdf_context *ctx, pdf_array *color_array, int index, num_values = (hival+1) * cs_num_components(pcs_base); if (num_values > lookup_length) { - dmprintf2(ctx->memory, "WARNING: pdfi_create_indexed() got %ld values, expected at least %d values\n", + dmprintf2(ctx->memory, "WARNING: pdfi_create_indexed() got %"PRIi64" values, expected at least %d values\n", lookup_length, num_values); code = gs_note_error(gs_error_rangecheck); goto exit; @@ -2201,7 +2273,7 @@ static int pdfi_create_JPX_space(pdf_context *ctx, const char *name, int num_com int code, icc_N; float range_buff[6] = {0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f}; - code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, ppcs); + code = pdfi_create_icc(ctx, (char *)name, NULL, num_components, &icc_N, range_buff, 0, ppcs); return code; } @@ -2272,7 +2344,10 @@ pdfi_create_colorspace_by_array(pdf_context *ctx, pdf_array *color_array, int in } else if (pdfi_name_is(space, "Separation")) { code = pdfi_create_Separation(ctx, color_array, index, stream_dict, page_dict, ppcs, inline_image); } else { - code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", + if (stream_dict == NULL) + code = gs_note_error(gs_error_syntaxerror); + else + code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", space, (pdf_dict *)stream_dict, page_dict, (pdf_obj **)&a); if (code < 0) goto exit; @@ -2332,13 +2407,32 @@ pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name, code = pdfi_create_JPX_space(ctx, "sgray", 1, ppcs); } else { pdf_obj *ref_space = NULL; + + if (ppcs == NULL && check_same_current_space(ctx, name) == 1) + return 0; + code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", name, (pdf_dict *)stream_dict, page_dict, &ref_space); if (code < 0) return code; + if (ref_space->type == PDF_NAME) { + if (ref_space->object_num != 0 && ref_space->object_num == name->object_num) { + pdfi_countdown(ref_space); + return_error(gs_error_circular_reference); + } + } + /* recursion */ code = pdfi_create_colorspace(ctx, ref_space, stream_dict, page_dict, ppcs, inline_image); + + if (code >= 0) { + if (ppcs != NULL) + pdfi_set_colourspace_name(ctx, *ppcs, name); + else + pdfi_set_colourspace_name(ctx, ctx->pgs->color[0].color_space, name); + } + pdfi_countdown(ref_space); return code; } @@ -2357,7 +2451,7 @@ pdfi_create_colorspace_by_name(pdf_context *ctx, pdf_name *name, */ int pdfi_create_icc_colorspace_from_stream(pdf_context *ctx, pdf_c_stream *stream, gs_offset_t offset, - unsigned int length, int comps, int *icc_N, gs_color_space **ppcs) + unsigned int length, int comps, int *icc_N, ulong dictkey, gs_color_space **ppcs) { pdf_c_stream *profile_stream = NULL; byte *profile_buffer; @@ -2380,7 +2474,7 @@ pdfi_create_icc_colorspace_from_stream(pdf_context *ctx, pdf_c_stream *stream, g } /* Now, finally, we can call the code to create and set the profile */ - code = pdfi_create_icc(ctx, NULL, profile_stream->s, comps, icc_N, range, ppcs); + code = pdfi_create_icc(ctx, NULL, profile_stream->s, comps, icc_N, range, dictkey, ppcs); code1 = pdfi_close_memory_stream(ctx, profile_buffer, profile_stream); @@ -2408,7 +2502,7 @@ int pdfi_create_colorspace(pdf_context *ctx, pdf_obj *space, pdf_dict *stream_di return_error(gs_error_typecheck); } } - if (ppcs && *ppcs && code >= 0) + if (code >= 0 && ppcs && *ppcs) (void)(*ppcs)->type->install_cspace(*ppcs, ctx->pgs); (void)pdfi_loop_detector_cleartomark(ctx); @@ -2569,32 +2663,47 @@ static int pdfi_device_setoutputintent(pdf_context *ctx, pdf_dict *profile_dict, Finally, we will use the output intent profile for the default profile of the proper Device profile in the icc manager, again, unless someone has explicitly set this default profile. + + All of this is skipped if we are forcing oveprint simulation with + the output intent set, in which case we will push the pdf14 device + to render directly to the the output intent color space and then + do a final transform to the target color space. */ dev_comps = dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]->num_comps; index = gsicc_get_default_type(dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]); - if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) { - /* The OI profile is the same type as the profile for the device and a - "default" profile for the device was not externally set. So we go - ahead and use the OI profile as the device profile. Care needs to be - taken here to keep from screwing up any device parameters. We will - use a keyword of OIProfile for the user/device parameter to indicate - its usage. Also, note conflicts if one is setting object dependent - color management */ - dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile; - rc_increment(picc_profile); - if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n"); - } else { - if (dev_profile->proof_profile == NULL) { - /* This means that we should use the OI profile as the proofing - profile. Note that if someone already has specified a - proofing profile it is unclear what they are trying to do - with the output intent. In this case, we will use it - just for the source data below */ - dev_profile->proof_profile = picc_profile; + + /* If we are doing simulate overprint and the output intent is different than + what the device profile is the we will end up pushing the pdf14 device + and doing a rendering to the output intent color space. Keep the device + profile as is, and do not do a proofing profile */ + + if (!(ctx->pgs->device->icc_struct->overprint_control == gs_overprint_control_simulate && + !gsicc_profiles_equal(dev_profile->oi_profile, dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE]))) { + if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) { + /* The OI profile is the same type as the profile for the device and a + "default" profile for the device was not externally set. So we go + ahead and use the OI profile as the device profile. Care needs to be + taken here to keep from screwing up any device parameters. We will + use a keyword of OIProfile for the user/device parameter to indicate + its usage. Also, note conflicts if one is setting object dependent + color management */ + dev_profile->device_profile[GS_DEFAULT_DEVICE_PROFILE] = picc_profile; rc_increment(picc_profile); - if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n"); + if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for device profile\n"); + } else { + if (dev_profile->proof_profile == NULL) { + /* This means that we should use the OI profile as the proofing + profile. Note that if someone already has specified a + proofing profile it is unclear what they are trying to do + with the output intent. In this case, we will use it + just for the source data below */ + dev_profile->proof_profile = picc_profile; + rc_increment(picc_profile); + if_debug0m(gs_debug_flag_icc, ctx->memory, "[icc] OutputIntent used for proof profile\n"); + } } } + /* Now the source colors. See which source color space needs to use the output intent ICC profile */ index = gsicc_get_default_type(source_profile); @@ -2674,3 +2783,171 @@ int pdfi_color_setoutputintent(pdf_context *ctx, pdf_dict *intent_dict, pdf_stre pdfi_seek(ctx, ctx->main_stream, savedoffset, SEEK_SET); return code; } + +static int Check_Default_Space(pdf_context *ctx, pdf_obj *space, pdf_dict *source_dict, int num_components) +{ + pdf_obj *primary = NULL; + pdf_obj *ref_space = NULL; + int code = 0; + + if (space->type == PDF_NAME) + { + if (pdfi_name_is((const pdf_name *)space, "DeviceGray")) + return (num_components == 1 ? 0 : gs_error_rangecheck); + if (pdfi_name_is((const pdf_name *)space, "DeviceCMYK")) + return (num_components == 4 ? 0 : gs_error_rangecheck); + if (pdfi_name_is((const pdf_name *)space, "DeviceRGB")) + return (num_components == 3 ? 0 : gs_error_rangecheck); + + code = pdfi_find_resource(ctx, (unsigned char *)"ColorSpace", (pdf_name *)space, (pdf_dict *)source_dict, + NULL, &ref_space); + if (code < 0) + return code; + + if (ref_space->type == PDF_NAME) { + if (ref_space->object_num != 0 && ref_space->object_num == space->object_num) { + pdfi_countdown(ref_space); + return_error(gs_error_circular_reference); + } + if (pdfi_name_is((const pdf_name *)ref_space, "DeviceGray")) { + pdfi_countdown(ref_space); + return (num_components == 1 ? 0 : gs_error_rangecheck); + } + if (pdfi_name_is((const pdf_name *)ref_space, "DeviceCMYK")) { + pdfi_countdown(ref_space); + return (num_components == 4 ? 0 : gs_error_rangecheck); + } + if (pdfi_name_is((const pdf_name *)ref_space, "DeviceRGB")) { + pdfi_countdown(ref_space); + return (num_components == 3 ? 0 : gs_error_rangecheck); + } + pdfi_countdown(ref_space); + return_error(gs_error_typecheck); + } + space = ref_space; + } + + if (space->type == PDF_ARRAY) { + code = pdfi_array_get(ctx, (pdf_array *)space, 0, &primary); + if (code < 0) + goto exit; + + if (primary->type == PDF_NAME) { + if (pdfi_name_is((pdf_name *)primary, "Lab")) { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + if (pdfi_name_is((pdf_name *)primary, "Pattern")) { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + if (pdfi_name_is((pdf_name *)primary, "Indexed")) { + code = gs_note_error(gs_error_typecheck); + goto exit; + } + } + } else + code = gs_note_error(gs_error_typecheck); + +exit: + pdfi_countdown(primary); + pdfi_countdown(ref_space); + return code; +} + +int pdfi_setup_DefaultSpaces(pdf_context *ctx, pdf_dict *source_dict) +{ + int code = 0; + pdf_dict *resources_dict = NULL, *colorspaces_dict = NULL; + pdf_obj *DefaultSpace = NULL; + + if (ctx->args.NOSUBSTDEVICECOLORS) + return 0; + + /* Create any required DefaultGray, DefaultRGB or DefaultCMYK + * spaces. + */ + code = pdfi_dict_knownget(ctx, source_dict, "Resources", (pdf_obj **)&resources_dict); + if (code > 0) { + code = pdfi_dict_knownget(ctx, resources_dict, "ColorSpace", (pdf_obj **)&colorspaces_dict); + if (code > 0) { + code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultGray", &DefaultSpace); + if (code > 0) { + gs_color_space *pcs; + + code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1); + if (code >= 0) { + code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false); + /* If any given Default* space fails simply ignore it, we wil then use the Device + * space instead, this is as per the spec. + */ + if (code >= 0) { + if (gs_color_space_num_components(pcs) == 1) { + ctx->page.DefaultGray_cs = pcs; + pdfi_set_colour_callback(pcs, ctx, NULL); + } else { + pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL); + rc_decrement(pcs, "setup_DefautSpaces"); + } + } + } else + pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL); + } + pdfi_countdown(DefaultSpace); + DefaultSpace = NULL; + code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultRGB", &DefaultSpace); + if (code > 0) { + gs_color_space *pcs; + + code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1); + if (code >= 0) { + code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false); + /* If any given Default* space fails simply ignore it, we wil then use the Device + * space instead, this is as per the spec. + */ + if (code >= 0) { + if (gs_color_space_num_components(pcs) == 3) { + ctx->page.DefaultRGB_cs = pcs; + pdfi_set_colour_callback(pcs, ctx, NULL); + } else { + rc_decrement(pcs, "setup_DefautSpaces"); + pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL); + } + } + } else + pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL); + } + pdfi_countdown(DefaultSpace); + DefaultSpace = NULL; + code = pdfi_dict_knownget(ctx, colorspaces_dict, "DefaultCMYK", &DefaultSpace); + if (code > 0) { + gs_color_space *pcs; + + code = Check_Default_Space(ctx, DefaultSpace, source_dict, 1); + if (code >= 0) { + code = pdfi_create_colorspace(ctx, DefaultSpace, NULL, source_dict, &pcs, false); + /* If any given Default* space fails simply ignore it, we wil then use the Device + * space instead, this is as per the spec. + */ + if (code >= 0) { + if (gs_color_space_num_components(pcs) == 4) { + ctx->page.DefaultCMYK_cs = pcs; + pdfi_set_colour_callback(pcs, ctx, NULL); + } else { + pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL); + rc_decrement(pcs, "setup_DefautSpaces"); + } + } + } else + pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_DEFAULTSPACE, "pdfi_setup_DefaultSpaces", NULL); + } + pdfi_countdown(DefaultSpace); + DefaultSpace = NULL; + } + } + + pdfi_countdown(DefaultSpace); + pdfi_countdown(resources_dict); + pdfi_countdown(colorspaces_dict); + return 0; +} |