summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam James <sam@gentoo.org>2022-03-29 10:27:10 +0100
committerSam James <sam@gentoo.org>2022-04-17 12:53:05 +0100
commit085bde903b9e684c3c1160e4df912bea9a660997 (patch)
treec4f5e6e9f2422e869ca5bc0b944520d451001282 /pdf/pdf_colour.c
parentImport Ghostscript 9.55 (diff)
downloadghostscript-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.c397
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;
+}