summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2022-03-31 11:58:22 -0700
committerMichael Vrhel <michael.vrhel@artifex.com>2022-04-07 17:51:40 -0700
commit276dc19f45bf09c8f1273d01ed5ce7c0161d7369 (patch)
treedc81119e9a4474fe30f7c65e3bb95ecc23362875 /base
parentb7b40987730375a571f817ffb75db663734753f3 (diff)
downloadghostpdl-276dc19f45bf09c8f1273d01ed5ce7c0161d7369.tar.gz
-dBlackVector=true/false option added
If set to true, stroke and fill operations that are fills of DeviceGray, DeviceRGB, DeviceCMYK, ICC, or LAB colors will be black. The exception is that white fills will remain white. DeviceN, Separation, shading and pattern fills will remain as is. We use the same structure as the -dBlackText option used to store the color space into the graphic state. This structure has been renamed black_textvec_state from black_text_state to denote this usage, as have other variables.
Diffstat (limited to 'base')
-rw-r--r--base/gdevp14.c1
-rw-r--r--base/gscms.h3
-rw-r--r--base/gsdparam.c45
-rw-r--r--base/gsequivc.c9
-rw-r--r--base/gsequivc.h2
-rw-r--r--base/gsgstate.c10
-rw-r--r--base/gsicc_blacktext.c198
-rw-r--r--base/gsicc_blacktext.h21
-rw-r--r--base/gsicc_manage.c1
-rw-r--r--base/gspaint.c104
-rw-r--r--base/gstext.c36
-rw-r--r--base/gxgstate.h8
-rw-r--r--base/gxpaint.c10
-rw-r--r--base/gxtext.h4
14 files changed, 315 insertions, 137 deletions
diff --git a/base/gdevp14.c b/base/gdevp14.c
index b3018f855..af594ff1f 100644
--- a/base/gdevp14.c
+++ b/base/gdevp14.c
@@ -3859,6 +3859,7 @@ gs_pdf14_device_copy_params(gx_device *dev, const gx_device *target)
dev->icc_struct->supports_devn = profile_targ->supports_devn;
dev->icc_struct->usefastcolor = profile_targ->usefastcolor;
dev->icc_struct->blacktext = profile_targ->blacktext;
+ dev->icc_struct->blackvector = profile_targ->blackvector;
switch (pdev->blend_cs_state) {
case PDF14_BLEND_CS_UNSPECIFIED:
diff --git a/base/gscms.h b/base/gscms.h
index 7fb362fe7..fb9085277 100644
--- a/base/gscms.h
+++ b/base/gscms.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -291,6 +291,7 @@ struct cmm_dev_profile_s {
bool pageneutralcolor; /* Only valid if graydetection true */
bool usefastcolor; /* Used when we want to use no cm */
bool blacktext; /* Force text to be pure black */
+ bool blackvector; /* Force vectors to be pure black */
bool supports_devn; /* If the target handles devn colors */
gs_overprint_control_t overprint_control; /* enable is the default */
gsicc_namelist_t *spotnames; /* If our device profiles are devn */
diff --git a/base/gsdparam.c b/base/gsdparam.c
index 069b21384..0a8b949f1 100644
--- a/base/gsdparam.c
+++ b/base/gsdparam.c
@@ -96,6 +96,7 @@ int gx_default_get_param(gx_device *dev, char *Param, void *list)
bool graydetection = false;
bool usefastcolor = false; /* set for unmanaged color */
bool blacktext = false;
+ bool blackvector = false;
/* By default overprinting only valid with cmyk devices */
gs_overprint_control_t overprint_control = gs_overprint_control_enable;
bool prebandthreshold = true, temp_bool = false;
@@ -354,6 +355,7 @@ int gx_default_get_param(gx_device *dev, char *Param, void *list)
graydetection = dev_profile->graydetection;
usefastcolor = dev_profile->usefastcolor;
blacktext = dev_profile->blacktext;
+ blackvector = dev_profile->blackvector;
overprint_control = dev_profile->overprint_control;
prebandthreshold = dev_profile->prebandthreshold;
/* With respect to Output profiles that have non-standard colorants,
@@ -397,6 +399,9 @@ int gx_default_get_param(gx_device *dev, char *Param, void *list)
if (strcmp(Param, "BlackText") == 0) {
return param_write_bool(plist, "BlackText", &blacktext);
}
+ if (strcmp(Param, "BlackVector") == 0) {
+ return param_write_bool(plist, "BlackVector", &blackvector);
+ }
if (strcmp(Param, "Overprint") == 0) {
gs_param_string opc_name;
const char *s = overprint_control_names[(int)overprint_control];
@@ -539,6 +544,7 @@ gx_default_get_params(gx_device * dev, gs_param_list * plist)
bool graydetection = false;
bool usefastcolor = false; /* set for unmanaged color */
bool blacktext = false;
+ bool blackvector = false;
/* By default, only overprint if the device supports it */
gs_overprint_control_t overprint_control = gs_overprint_control_enable;
bool prebandthreshold = true, temp_bool;
@@ -654,6 +660,7 @@ gx_default_get_params(gx_device * dev, gs_param_list * plist)
graydetection = dev_profile->graydetection;
usefastcolor = dev_profile->usefastcolor;
blacktext = dev_profile->blacktext;
+ blackvector = dev_profile->blackvector;
overprint_control = dev_profile->overprint_control;
prebandthreshold = dev_profile->prebandthreshold;
/* With respect to Output profiles that have non-standard colorants,
@@ -715,6 +722,7 @@ gx_default_get_params(gx_device * dev, gs_param_list * plist)
(code = param_write_bool(plist, "GrayDetection", &graydetection)) < 0 ||
(code = param_write_bool(plist, "UseFastColor", &usefastcolor)) < 0 ||
(code = param_write_bool(plist, "BlackText", &blacktext)) < 0 ||
+ (code = param_write_bool(plist, "BlackVector", &blackvector)) < 0 ||
(code = param_write_bool(plist, "PreBandThreshold", &prebandthreshold)) < 0 ||
(code = param_write_string(plist,"OutputICCProfile", &(profile_array[0]))) < 0 ||
(code = param_write_string(plist,"VectorICCProfile", &(profile_array[1]))) < 0 ||
@@ -1239,6 +1247,33 @@ gx_default_put_blacktext(bool blacktext, gx_device* dev)
}
static int
+gx_default_put_blackvector(bool blackvector, gx_device* dev)
+{
+ int code = 0;
+ cmm_dev_profile_t* profile_struct;
+
+ if (dev_proc(dev, get_profile) == NULL) {
+ if (dev->icc_struct == NULL) {
+ dev->icc_struct = gsicc_new_device_profile_array(dev);
+ if (dev->icc_struct == NULL)
+ return_error(gs_error_VMerror);
+ }
+ dev->icc_struct->blackvector = blackvector;
+ } else {
+ code = dev_proc(dev, get_profile)(dev, &profile_struct);
+ if (profile_struct == NULL) {
+ /* Create now */
+ dev->icc_struct = gsicc_new_device_profile_array(dev);
+ profile_struct = dev->icc_struct;
+ if (profile_struct == NULL)
+ return_error(gs_error_VMerror);
+ }
+ profile_struct->blackvector = blackvector;
+ }
+ return code;
+}
+
+static int
gx_default_put_overprint_control(gs_overprint_control_t overprint_control, gx_device * dev)
{
int code = 0;
@@ -1515,6 +1550,7 @@ gx_default_put_params(gx_device * dev, gs_param_list * plist)
bool graydetection = false;
bool usefastcolor = false;
bool blacktext = false;
+ bool blackvector = false;
gs_overprint_control_t overprint_control = gs_overprint_control_enable;
bool prebandthreshold = false;
bool use_antidropout = dev->color_info.use_antidropout_downscaler;
@@ -1535,6 +1571,7 @@ gx_default_put_params(gx_device * dev, gs_param_list * plist)
devicegraytok = dev->icc_struct->devicegraytok;
usefastcolor = dev->icc_struct->usefastcolor;
blacktext = dev->icc_struct->blacktext;
+ blackvector = dev->icc_struct->blackvector;
prebandthreshold = dev->icc_struct->prebandthreshold;
overprint_control = dev->icc_struct->overprint_control;
} else {
@@ -1850,6 +1887,11 @@ nce:
ecode = code;
param_signal_error(plist, param_name, ecode);
}
+ if ((code = param_read_bool(plist, (param_name = "BlackVector"),
+ &blackvector)) < 0) {
+ ecode = code;
+ param_signal_error(plist, param_name, ecode);
+ }
if ((code = param_put_enum(plist, "Overprint",
(int*)&overprint_control, overprint_control_names, ecode)) < 0) {
ecode = code;
@@ -2296,6 +2338,9 @@ label:\
code = gx_default_put_blacktext(blacktext, dev);
if (code < 0)
return code;
+ code = gx_default_put_blackvector(blackvector, dev);
+ if (code < 0)
+ return code;
code = gx_default_put_overprint_control(overprint_control, dev);
if (code < 0)
return code;
diff --git a/base/gsequivc.c b/base/gsequivc.c
index 441183ed6..5aea0c73c 100644
--- a/base/gsequivc.c
+++ b/base/gsequivc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -472,9 +472,9 @@ capture_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_gstate * pgs,
0 /* blend_profile */, 0 /* postren_profile */,
{ {0} } /* rendercond[] */, 0 /* devicegraytok */,
0 /* graydection */, 0 /* pageneutralcolor */,
- 0 /* usefastcolor */, 0 /* blacktext */, 0 /* supports_devn */,
- 0 /* overprint_control */, 0 /* spotnames */,
- 0 /* prebandthreshold */, 0 /* memory */,
+ 0 /* usefastcolor */, 0 /* blacktext */, 0 /* blackvectir */,
+ 0 /* supports_devn */, 0 /* overprint_control */,
+ 0 /* spotnames */, 0 /* prebandthreshold */, 0 /* memory */,
{ 0 } /* rc_header */
};
@@ -502,6 +502,7 @@ capture_spot_equivalent_cmyk_colors(gx_device * pdev, const gs_gstate * pgs,
temp_profile.usefastcolor = false; /* This avoids a few headaches */
temp_profile.blacktext = false;
+ temp_profile.blackvector = false;
temp_profile.prebandthreshold = true;
temp_profile.supports_devn = false;
temp_profile.rendercond[0] = render_cond;
diff --git a/base/gsequivc.h b/base/gsequivc.h
index d5501b2df..4317be2d6 100644
--- a/base/gsequivc.h
+++ b/base/gsequivc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
diff --git a/base/gsgstate.c b/base/gsgstate.c
index 0f7d182a5..76b511c5e 100644
--- a/base/gsgstate.c
+++ b/base/gsgstate.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -149,7 +149,7 @@ gs_gstate_initialize(gs_gstate * pgs, gs_memory_t * mem)
pgs->icc_profile_cache = gsicc_profilecache_new(pgs->memory);
if (pgs->icc_profile_cache == NULL)
return_error(gs_error_VMerror);
- pgs->black_text_state = NULL;
+ pgs->black_textvec_state = NULL;
#if ENABLE_CUSTOM_COLOR_CALLBACK
pgs->custom_color_callback = INIT_CUSTOM_COLOR_PTR;
#endif
@@ -179,7 +179,7 @@ gs_gstate_copied(gs_gstate * pgs)
rc_increment(pgs->icc_link_cache);
rc_increment(pgs->icc_profile_cache);
rc_increment(pgs->icc_manager);
- rc_increment(pgs->black_text_state);
+ rc_increment(pgs->black_textvec_state);
}
/* Adjust reference counts before assigning one gs_gstate to another. */
@@ -209,7 +209,7 @@ gs_gstate_pre_assign(gs_gstate *pto, const gs_gstate *pfrom)
RCCOPY(icc_link_cache);
RCCOPY(icc_profile_cache);
RCCOPY(icc_manager);
- RCCOPY(black_text_state);
+ RCCOPY(black_textvec_state);
#undef RCCOPY
}
@@ -250,6 +250,6 @@ gs_gstate_release(gs_gstate * pgs)
RCDECR(icc_link_cache);
RCDECR(icc_profile_cache);
RCDECR(icc_manager);
- RCDECR(black_text_state);
+ RCDECR(black_textvec_state);
#undef RCDECR
}
diff --git a/base/gsicc_blacktext.c b/base/gsicc_blacktext.c
index 826992330..14e0dc995 100644
--- a/base/gsicc_blacktext.c
+++ b/base/gsicc_blacktext.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -22,87 +22,185 @@
#include "gzstate.h"
#include "gsicc_blacktext.h"
-/* gsicc_blacktext_state_t is going to be storing GCed items
+/* gsicc_blacktextvec_state_t is going to be storing GCed items
(color spaces and client colors) and so will need to be GCed */
-gs_private_st_ptrs4(st_blacktext_state, gsicc_blacktext_state_t,
- "gsicc_blacktext_state", blacktext_state_enum_ptrs,
- blacktext_state_reloc_ptrs, pcs[0], pcs[1], pcc[0], pcc[1]);
+gs_private_st_ptrs4(st_blacktextvec_state, gsicc_blacktextvec_state_t,
+ "gsicc_blacktextvec_state", blacktextvec_state_enum_ptrs,
+ blacktextvec_state_reloc_ptrs, pcs, pcs_alt, pcc, pcc_alt);
static void
-rc_gsicc_blacktext_state_free(gs_memory_t *mem, void *ptr_in,
+rc_gsicc_blacktextvec_state_free(gs_memory_t *mem, void *ptr_in,
client_name_t cname)
{
- gsicc_blacktext_state_t *state = (gsicc_blacktext_state_t*)ptr_in;
+ gsicc_blacktextvec_state_t *state = (gsicc_blacktextvec_state_t*)ptr_in;
- rc_decrement_cs(state->pcs[0], "rc_gsicc_blacktext_state_free");
- rc_decrement_cs(state->pcs[1], "rc_gsicc_blacktext_state_free");
+ rc_decrement_cs(state->pcs, "rc_gsicc_blacktextvec_state_free");
+ rc_decrement_cs(state->pcs_alt, "rc_gsicc_blacktextvec_state_free");
- gs_free_object(mem->stable_memory, state,
- "rc_gsicc_blacktext_state_free");
+ gs_free_object(state->memory, state,
+ "rc_gsicc_blacktextvec_state_free");
}
-gsicc_blacktext_state_t*
-gsicc_blacktext_state_new(gs_memory_t *memory)
+gsicc_blacktextvec_state_t*
+gsicc_blacktextvec_state_new(gs_memory_t *memory, bool is_text)
{
- gsicc_blacktext_state_t *result;
+ gsicc_blacktextvec_state_t *result;
- result = gs_alloc_struct(memory->stable_memory, gsicc_blacktext_state_t,
- &st_blacktext_state, "gsicc_blacktext_state_new");
+ result = gs_alloc_struct(memory->stable_memory, gsicc_blacktextvec_state_t,
+ &st_blacktextvec_state, "gsicc_blacktextvec_state_new");
if (result == NULL)
return NULL;
- rc_init_free(result, memory->stable_memory, 1, rc_gsicc_blacktext_state_free);
- result->memory = memory;
- result->pcs[0] = NULL;
- result->pcs[1] = NULL;
- result->pcc[0] = NULL;
- result->pcc[1] = NULL;
+ rc_init_free(result, memory->stable_memory, 1, rc_gsicc_blacktextvec_state_free);
+ result->memory = memory->stable_memory;
+ result->pcs = NULL;
+ result->pcs_alt = NULL;
+ result->pcc = NULL;
+ result->pcc_alt = NULL;
+ result->is_text = is_text;
return result;
}
+/* Crude white color check. Only valid for ICC based RGB, CMYK, Gray, and LAB CS.
+ Makes some assumptions about profile. Also may want some tolerance check. */
+static inline bool is_white(gs_color_space* pcs, gs_client_color* pcc)
+{
+ if (gs_color_space_get_index(pcs) == gs_color_space_index_ICC) {
+ switch (pcs->cmm_icc_profile_data->data_cs) {
+ case gsGRAY:
+ if (pcc->paint.values[0] == 1.0)
+ return true;
+ else
+ return false;
+ break;
+ case gsRGB:
+ if (pcc->paint.values[0] == 1.0 && pcc->paint.values[1] == 1.0 &&
+ pcc->paint.values[2] == 1.0)
+ return true;
+ else
+ return false;
+ break;
+ case gsCMYK:
+ if (pcc->paint.values[0] == 0.0 && pcc->paint.values[1] == 0.0 &&
+ pcc->paint.values[2] == 0.0 && pcc->paint.values[3] == 0.0)
+ return true;
+ else
+ return false;
+ break;
+ case gsCIELAB:
+ if (pcc->paint.values[0] == 100.0 && pcc->paint.values[1] == 0.0 &&
+ pcc->paint.values[2] == 0.0)
+ return true;
+ else
+ return false;
+ break;
+ default:
+ return false;
+ }
+ } else
+ return false;
+}
+
+bool gsicc_setup_black_textvec(gs_gstate *pgs, gx_device *dev, bool is_text)
+{
+ gs_color_space *pcs_curr = gs_currentcolorspace_inline(pgs);
+ gs_color_space *pcs_alt = gs_swappedcolorspace_inline(pgs);
+
+ /* If neither space is ICC then we are not doing anything */
+ if (!gs_color_space_is_ICC(pcs_curr) && !gs_color_space_is_ICC(pcs_alt))
+ return false;
+
+ /* Create a new object to hold the cs details */
+ pgs->black_textvec_state = gsicc_blacktextvec_state_new(pgs->memory, is_text);
+ if (pgs->black_textvec_state == NULL)
+ return false; /* No error just move on */
+
+ /* If curr space is ICC then store it */
+ if (gs_color_space_is_ICC(pcs_curr)) {
+ rc_increment_cs(pcs_curr); /* We are storing the cs. Will decrement when structure is released */
+ pgs->black_textvec_state->pcs = pcs_curr;
+ pgs->black_textvec_state->pcc = pgs->color[0].ccolor;
+ cs_adjust_color_count(pgs, 1); /* The set_gray will do a decrement, only need if pattern */
+ pgs->black_textvec_state->value[0] = pgs->color[0].ccolor->paint.values[0];
+
+ if (is_white(pcs_curr, pgs->color[0].ccolor))
+ gs_setgray(pgs, 1.0);
+ else
+ gs_setgray(pgs, 0.0);
+ }
+
+ /* If alt space is ICC then store it */
+ if (gs_color_space_is_ICC(pcs_alt)) {
+ rc_increment_cs(pcs_alt); /* We are storing the cs. Will decrement when structure is released */
+ pgs->black_textvec_state->pcs_alt = pcs_alt;
+
+ gs_swapcolors_quick(pgs); /* Have to swap for set_gray and adjust color count */
+ pgs->black_textvec_state->pcc_alt = pgs->color[0].ccolor;
+ cs_adjust_color_count(pgs, 1); /* The set_gray will do a decrement, only need if pattern */
+ pgs->black_textvec_state->value[1] = pgs->color[0].ccolor->paint.values[0];
+
+ if (is_white(pcs_alt, pgs->color[0].ccolor))
+ gs_setgray(pgs, 1.0);
+ else
+ gs_setgray(pgs, 0.0);
+ gs_swapcolors_quick(pgs);
+ }
+
+ pgs->black_textvec_state->is_fill = pgs->is_fill_color;
+ return true; /* Need to clean up */
+}
+
void
-gsicc_restore_black_text(gs_gstate *pgs)
+gsicc_restore_blacktextvec(gs_gstate *pgs, bool is_text)
{
- gsicc_blacktext_state_t *state = pgs->black_text_state;
+ gsicc_blacktextvec_state_t *state = pgs->black_textvec_state;
int code;
if (state == NULL)
return;
+ if (is_text != state->is_text)
+ return;
+
/* Make sure state and original are same fill_color condition */
if (state->rc.ref_count == 1) {
- if ((state->is_fill && pgs->is_fill_color) ||
- (!state->is_fill && !pgs->is_fill_color)) {
-
- if ((code = gs_setcolorspace_only(pgs, pgs->black_text_state->pcs[0])) >= 0) {
- /* current client color is gray. no need to decrement */
- pgs->color[0].ccolor = pgs->black_text_state->pcc[0];
- pgs->color[0].ccolor->paint.values[0] = pgs->black_text_state->value[0];
+ if ((state->is_fill && pgs->is_fill_color) || (!state->is_fill && !pgs->is_fill_color)) {
+ if (pgs->black_textvec_state->pcs != NULL) {
+ if ((code = gs_setcolorspace_only(pgs, pgs->black_textvec_state->pcs)) >= 0) {
+ /* current client color is gray. no need to decrement */
+ pgs->color[0].ccolor = pgs->black_textvec_state->pcc;
+ pgs->color[0].ccolor->paint.values[0] = pgs->black_textvec_state->value[0];
+ }
+ gx_unset_dev_color(pgs);
}
- gs_swapcolors_quick(pgs);
- if ((code = gs_setcolorspace_only(pgs, pgs->black_text_state->pcs[1])) >= 0) {
- pgs->color[0].ccolor = pgs->black_text_state->pcc[1];
- pgs->color[0].ccolor->paint.values[0] = pgs->black_text_state->value[1];
-
+ if (pgs->black_textvec_state->pcs_alt != NULL) {
+ gs_swapcolors_quick(pgs);
+ if ((code = gs_setcolorspace_only(pgs, pgs->black_textvec_state->pcs_alt)) >= 0) {
+ pgs->color[0].ccolor = pgs->black_textvec_state->pcc_alt;
+ pgs->color[0].ccolor->paint.values[0] = pgs->black_textvec_state->value[1];
+ }
+ gs_swapcolors_quick(pgs);
+ gx_unset_alt_dev_color(pgs);
}
- gs_swapcolors_quick(pgs);
-
} else {
-
- if ((code = gs_setcolorspace_only(pgs, pgs->black_text_state->pcs[1])) >= 0) {
- pgs->color[0].ccolor = pgs->black_text_state->pcc[1];
- pgs->color[0].ccolor->paint.values[0] = pgs->black_text_state->value[1];
+ if (pgs->black_textvec_state->pcs_alt != NULL) {
+ if ((code = gs_setcolorspace_only(pgs, pgs->black_textvec_state->pcs_alt)) >= 0) {
+ pgs->color[0].ccolor = pgs->black_textvec_state->pcc_alt;
+ pgs->color[0].ccolor->paint.values[0] = pgs->black_textvec_state->value[1];
+ }
+ gx_unset_dev_color(pgs);
}
- gs_swapcolors_quick(pgs);
- if ((code = gs_setcolorspace_only(pgs, pgs->black_text_state->pcs[0])) >= 0) {
- pgs->color[0].ccolor = pgs->black_text_state->pcc[0];
- pgs->color[0].ccolor->paint.values[0] = pgs->black_text_state->value[0];
+ if (pgs->black_textvec_state->pcs != NULL) {
+ gs_swapcolors_quick(pgs);
+ if ((code = gs_setcolorspace_only(pgs, pgs->black_textvec_state->pcs)) >= 0) {
+ pgs->color[0].ccolor = pgs->black_textvec_state->pcc;
+ pgs->color[0].ccolor->paint.values[0] = pgs->black_textvec_state->value[0];
+ }
+ gs_swapcolors_quick(pgs);
+ gx_unset_alt_dev_color(pgs);
}
- gs_swapcolors_quick(pgs);
}
- gx_unset_dev_color(pgs);
- gx_unset_alt_dev_color(pgs);
}
rc_decrement(state, "gsicc_restore_black_text");
- pgs->black_text_state = NULL;
+ pgs->black_textvec_state = NULL;
} \ No newline at end of file
diff --git a/base/gsicc_blacktext.h b/base/gsicc_blacktext.h
index 09d541a55..8776fb9fd 100644
--- a/base/gsicc_blacktext.h
+++ b/base/gsicc_blacktext.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -16,19 +16,22 @@
#ifndef gsicc_blacktext_INCLUDED
# define gsicc_blacktext_INCLUDED
-typedef struct gsicc_blacktext_state_s gsicc_blacktext_state_t;
+typedef struct gsicc_blacktextvec_state_s gsicc_blacktextvec_state_t;
-struct gsicc_blacktext_state_s {
+struct gsicc_blacktextvec_state_s {
gs_memory_t *memory;
rc_header rc;
bool is_fill; /* Needed for proper color restore */
- gs_color_space *pcs[2]; /* If doing black text, color spaces to restore */
- gs_client_color *pcc[2]; /* If doing black text, client colors to restore */
- float value[2]; /* DeviceGray setting blows away the client color
- zero value */
+ gs_color_space *pcs; /* color spaces to restore */
+ gs_color_space *pcs_alt;
+ gs_client_color *pcc; /* client colors to restore */
+ gs_client_color *pcc_alt; /* client colors to restore */
+ float value[2]; /* DeviceGray setting blows away the client color zero value */
+ bool is_text;
};
-gsicc_blacktext_state_t* gsicc_blacktext_state_new(gs_memory_t *memory);
-void gsicc_restore_black_text(gs_gstate *pgs);
+gsicc_blacktextvec_state_t* gsicc_blacktextvec_state_new(gs_memory_t *memory, bool is_text);
+void gsicc_restore_blacktextvec(gs_gstate *pgs, bool is_text);
+bool gsicc_setup_black_textvec(gs_gstate *pgs, gx_device *dev, bool is_text);
#endif
diff --git a/base/gsicc_manage.c b/base/gsicc_manage.c
index 2c57b650a..fa775b5ca 100644
--- a/base/gsicc_manage.c
+++ b/base/gsicc_manage.c
@@ -1464,6 +1464,7 @@ gsicc_new_device_profile_array(gx_device *dev)
result->pageneutralcolor = false;
result->usefastcolor = false; /* Default is to not use fast color */
result->blacktext = false;
+ result->blackvector = false;
result->prebandthreshold = true;
result->supports_devn = false;
result->overprint_control = gs_overprint_control_enable; /* Default overprint if the device can */
diff --git a/base/gspaint.c b/base/gspaint.c
index 8e4c75cf1..728d2b2f9 100644
--- a/base/gspaint.c
+++ b/base/gspaint.c
@@ -273,10 +273,23 @@ alpha_buffer_release(gs_gstate * pgs, bool newpath)
return code;
}
+/* Setup for black vector handling */
+static inline bool black_vectors(gs_gstate *pgs, gx_device *dev)
+{
+ if (dev->icc_struct != NULL && dev->icc_struct->blackvector &&
+ pgs->black_textvec_state == NULL) {
+ return gsicc_setup_black_textvec(pgs, dev, false);
+ }
+ return false;
+}
+
static int do_fill(gs_gstate *pgs, int rule)
{
int code, abits, acode, rcode = 0;
bool devn;
+ bool black_vector = false;
+ bool in_smask =
+ (dev_proc(pgs->device, dev_spec_op)(pgs->device, gxdso_in_smask_construction, NULL, 0)) > 0;
/* We need to distinguish text from vectors to set the object tag.
@@ -294,17 +307,18 @@ static int do_fill(gs_gstate *pgs, int rule)
handle that, we'll have to add a flag to the path structure, or to the path
segment structure (depending on how fine grained we require it to be).
*/
- if (pgs->show_gstate == NULL)
+ if (pgs->show_gstate == NULL && !in_smask) {
ensure_tag_is_set(pgs, pgs->device, GS_VECTOR_TAG); /* NB: may unset_dev_color */
- else
+ black_vector = black_vectors(pgs, pgs->device); /* Set vector fill to black */
+ } else
ensure_tag_is_set(pgs, pgs->device, GS_TEXT_TAG); /* NB: may unset_dev_color */
code = gx_set_dev_color(pgs);
if (code != 0)
- return code;
+ goto out;
code = gs_gstate_color_load(pgs);
if (code < 0)
- return code;
+ goto out;
if (pgs->overprint || (!pgs->overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
gxdso_overprint_active, NULL, 0))) {
@@ -314,7 +328,7 @@ static int do_fill(gs_gstate *pgs, int rule)
"[overprint] Fill Overprint\n");
code = gs_do_set_overprint(pgs);
if (code < 0)
- return code;
+ goto out;
op_params.op_state = OP_STATE_FILL;
gs_gstate_update_overprint(pgs, &op_params);
@@ -330,10 +344,14 @@ static int do_fill(gs_gstate *pgs, int rule)
if (abits > 1) {
acode = alpha_buffer_init(pgs, pgs->fill_adjust.x,
pgs->fill_adjust.y, abits, devn);
- if (acode == 2) /* Special case for no fill required */
- return 0;
- if (acode < 0)
- return acode;
+ if (acode == 2) { /* Special case for no fill required */
+ code = 0;
+ goto out;
+ }
+ if (acode < 0) {
+ code = acode;
+ goto out;
+ }
} else
acode = 0;
code = gx_fill_path(pgs->path, gs_currentdevicecolor_inline(pgs), pgs, rule,
@@ -343,6 +361,12 @@ static int do_fill(gs_gstate *pgs, int rule)
if (code >= 0 && rcode < 0)
code = rcode;
+out:
+ if (black_vector) {
+ /* Restore color */
+ gsicc_restore_blacktextvec(pgs, false);
+ }
+
return code;
}
@@ -397,6 +421,10 @@ do_stroke(gs_gstate * pgs)
int code, abits, acode, rcode = 0;
bool devn;
bool is_fill_correct = true;
+ bool black_vector = false;
+ bool in_smask =
+ (dev_proc(pgs->device, dev_spec_op)(pgs->device, gxdso_in_smask_construction, NULL, 0)) > 0;
+
/* We need to distinguish text from vectors to set the object tag.
@@ -414,17 +442,18 @@ do_stroke(gs_gstate * pgs)
handle that, we'll have to add a flag to the path structure, or to the path
segment structure (depending on how fine grained we require it to be).
*/
- if (pgs->show_gstate == NULL)
+ if (pgs->show_gstate == NULL && !in_smask) {
ensure_tag_is_set(pgs, pgs->device, GS_VECTOR_TAG); /* NB: may unset_dev_color */
- else
+ black_vector = black_vectors(pgs, pgs->device);
+ } else
ensure_tag_is_set(pgs, pgs->device, GS_TEXT_TAG); /* NB: may unset_dev_color */
code = gx_set_dev_color(pgs);
if (code != 0)
- return code;
+ goto out;
code = gs_gstate_color_load(pgs);
if (code < 0)
- return code;
+ goto out;
if (pgs->stroke_overprint || (!pgs->stroke_overprint && dev_proc(pgs->device, dev_spec_op)(pgs->device,
@@ -446,7 +475,7 @@ do_stroke(gs_gstate * pgs)
if (!is_fill_correct) {
pgs->is_fill_color = true;
}
- return code;
+ goto out;
}
op_params.op_state = OP_STATE_STROKE;
@@ -487,13 +516,15 @@ do_stroke(gs_gstate * pgs)
if (!is_fill_correct) {
pgs->is_fill_color = true;
}
- return 0;
+ code = 0;
+ goto out;
}
if (acode < 0) {
if (!is_fill_correct) {
pgs->is_fill_color = true;
}
- return acode;
+ code = acode;
+ goto out;
}
gs_setlinewidth(pgs, new_width);
scale_dash_pattern(pgs, scale);
@@ -523,6 +554,12 @@ do_stroke(gs_gstate * pgs)
if (!is_fill_correct) {
pgs->is_fill_color = true;
}
+
+out:
+ if (black_vector) {
+ /* Restore color */
+ gsicc_restore_blacktextvec(pgs, false);
+ }
return code;
}
@@ -603,6 +640,10 @@ static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
int code, abits, acode = 0, rcode = 0;
bool devn;
float orig_width, scale, orig_flatness;
+ bool black_vector = false;
+ bool in_smask =
+ (dev_proc(pgs->device, dev_spec_op)(pgs->device, gxdso_in_smask_construction, NULL, 0)) > 0;
+
/* It is either our first time, or the stroke was a pattern and
we are coming back from the error if restart < 1 (0 is first
@@ -643,18 +684,19 @@ static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
handle that, we'll have to add a flag to the path structure, or to the path
segment structure (depending on how fine grained we require it to be).
*/
- if (pgs->show_gstate == NULL)
+ if (pgs->show_gstate == NULL && !in_smask) {
ensure_tag_is_set(pgs, pgs->device, GS_VECTOR_TAG); /* NB: may unset_dev_color */
- else
+ black_vector = black_vectors(pgs, pgs->device);
+ } else
ensure_tag_is_set(pgs, pgs->device, GS_TEXT_TAG); /* NB: may unset_dev_color */
/* if we are at restart == 0, we set the stroke color. */
code = gx_set_dev_color(pgs);
if (code != 0)
- return code; /* may be gs_error_Remap_color or real error */
+ goto out2; /* may be gs_error_Remap_color or real error */
code = gs_gstate_color_load(pgs);
if (code < 0)
- return code;
+ goto out2;
/* If this was a pattern color, make sure and lock it in the pattern_cache */
if (gx_dc_is_pattern1_color(gs_currentdevicecolor_inline(pgs))) {
gs_id id;
@@ -665,8 +707,8 @@ static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
} else {
code = 0;
}
- if (code < 0)
- return code; /* lock failed -- tile not in cache? */
+ if (code < 0)
+ goto out2; /* lock failed -- tile not in cache? */
}
}
@@ -676,7 +718,7 @@ static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
"[overprint] StrokeFill Stroke Set Overprint\n");
code = gs_do_set_overprint(pgs);
if (code < 0)
- return code;
+ goto out2;
}
*restart = 1; /* finished, successfully with stroke_color */
@@ -690,7 +732,7 @@ static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
code = gx_set_dev_color(pgs);
if (code != 0) {
- return code;
+ goto out2;
}
code = gs_gstate_color_load(pgs);
if (code < 0) {
@@ -774,10 +816,15 @@ static int do_fill_stroke(gs_gstate *pgs, int rule, int *restart)
code = 0;
}
if (code < 0)
- return code; /* lock failed -- tile not in cache? */
+ goto out2; /* lock failed -- tile not in cache? */
}
}
out:
+ if (black_vector) {
+ /* Restore color */
+ gsicc_restore_blacktextvec(pgs, false);
+ }
+
if (gx_dc_is_pattern1_color(gs_swappeddevicecolor_inline(pgs))) {
gs_id id;
@@ -793,6 +840,13 @@ out:
if (code >= 0 && acode < 0)
code = acode;
return code;
+
+out2:
+ if (black_vector) {
+ /* Restore color */
+ gsicc_restore_blacktextvec(pgs, false);
+ }
+ return code;
}
/* Fill the current path using a specified rule. */
diff --git a/base/gstext.c b/base/gstext.c
index 306c476df..9fb9a34b8 100644
--- a/base/gstext.c
+++ b/base/gstext.c
@@ -324,34 +324,8 @@ gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text,
/* Processing a text object operation */
ensure_tag_is_set(pgs, pgs->device, GS_TEXT_TAG); /* NB: may unset_dev_color */
- if (black_text && pgs->black_text_state == NULL) {
- gs_color_space *pcs_curr = gs_currentcolorspace_inline(pgs);
- gs_color_space *pcs_alt = gs_swappedcolorspace_inline(pgs);
-
- pgs->black_text_state = gsicc_blacktext_state_new(pgs->memory);
- if (pgs->black_text_state == NULL)
- return gs_error_VMerror;
-
- rc_increment_cs(pcs_curr);
- rc_increment_cs(pcs_alt);
- pgs->black_text_state->pcs[0] = pcs_curr;
- pgs->black_text_state->pcs[1] = pcs_alt;
-
- pgs->black_text_state->pcc[0] = pgs->color[0].ccolor;
- cs_adjust_color_count(pgs, 1); /* The set_gray will do a decrement */
- pgs->black_text_state->value[0] = pgs->color[0].ccolor->paint.values[0];
- gs_setgray(pgs, 0.0);
-
- gs_swapcolors_quick(pgs);
-
- pgs->black_text_state->pcc[1] = pgs->color[0].ccolor;
- cs_adjust_color_count(pgs, 1);
- pgs->black_text_state->value[1] = pgs->color[0].ccolor->paint.values[0];
- gs_setgray(pgs, 0.0);
-
- gs_swapcolors_quick(pgs);
-
- pgs->black_text_state->is_fill = pgs->is_fill_color;
+ if (black_text && pgs->black_textvec_state == NULL) {
+ gsicc_setup_black_textvec(pgs, (gx_device *)pgs->device, true);
}
code = gx_set_dev_color(pgs);
@@ -405,7 +379,7 @@ gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text,
/* we need to know if we are doing a highlevel device.
Also we need to know if we are doing any stroke
or stroke fill operations. This determines when
- we need to release the black_text_state structure. */
+ we need to release the black_textvec_state structure. */
if (code >= 0 && *ppte != NULL) {
if (black_text) {
if (!((*ppte)->k_text_release)) {
@@ -821,8 +795,8 @@ rc_free_text_enum(gs_memory_t * mem, void *obj, client_name_t cname)
void
gs_text_release(gs_gstate *pgs, gs_text_enum_t * pte, client_name_t cname)
{
- if (pgs != NULL && pgs->black_text_state != NULL)
- gsicc_restore_black_text(pgs);
+ if (pgs != NULL && pgs->black_textvec_state != NULL)
+ gsicc_restore_blacktextvec(pgs, true);
rc_decrement_only(pte, cname);
}
diff --git a/base/gxgstate.h b/base/gxgstate.h
index b1ce6a088..c199a9588 100644
--- a/base/gxgstate.h
+++ b/base/gxgstate.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -270,7 +270,7 @@ struct gs_gstate_s {
gsicc_manager_t *icc_manager; /* ICC color manager, profile */
gsicc_link_cache_t *icc_link_cache; /* ICC linked transforms */
gsicc_profile_cache_t *icc_profile_cache; /* ICC profiles from PS. */
- gsicc_blacktext_state_t *black_text_state; /* Used to store and restore cs for black text */
+ gsicc_blacktextvec_state_t *black_textvec_state; /* Used to store and restore cs for black text */
CUSTOM_COLOR_PTR /* Pointer to custom color callback struct */
const gx_color_map_procs *
@@ -378,7 +378,7 @@ struct gs_gstate_s {
s->icc_link_cache = __state_init.icc_link_cache; \
s->icc_profile_cache = __state_init.icc_profile_cache; \
s->get_cmap_procs = __state_init.get_cmap_procs; \
- s->black_text_state = NULL; \
+ s->black_textvec_state = NULL; \
s->show_gstate = NULL; \
s->is_fill_color = 1; \
s->strokeconstantalpha = 1.0; \
@@ -422,7 +422,7 @@ struct_proc_finalize(gs_gstate_finalize);
m(17, font) \
m(18, root_font) \
m(19, show_gstate) \
- m(20, black_text_state)
+ m(20, black_textvec_state)
#define gs_gstate_num_ptrs 21
diff --git a/base/gxpaint.c b/base/gxpaint.c
index 2e4955c11..cd0f573e7 100644
--- a/base/gxpaint.c
+++ b/base/gxpaint.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -72,8 +72,8 @@ gx_stroke_fill(gx_path * ppath, gs_gstate * pgs)
(dev, (const gs_gstate *)pgs, ppath, &params,
gs_currentdevicecolor_inline(pgs), pcpath);
- if (pgs->black_text_state) {
- gsicc_restore_black_text(pgs);
+ if (pgs->black_textvec_state) {
+ gsicc_restore_blacktextvec(pgs, true);
}
return code;
@@ -103,8 +103,8 @@ gx_fill_stroke_path(gs_gstate * pgs, int rule)
&stroke_params, gs_swappeddevicecolor_inline(pgs),
pcpath);
- if (pgs->black_text_state) {
- gsicc_restore_black_text(pgs);
+ if (pgs->black_textvec_state) {
+ gsicc_restore_blacktextvec(pgs, true);
}
return code;
diff --git a/base/gxtext.h b/base/gxtext.h
index babaaf1e3..100c70e53 100644
--- a/base/gxtext.h
+++ b/base/gxtext.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -124,7 +124,7 @@ rc_free_proc(rc_free_text_enum);
int bytes_decoded; \
gs_point FontBBox_as_Metrics2; /* used with FontType 9,11 && WMode 1 */\
ulong text_enum_id; /* debug purpose only - not used by algorythm. */\
- bool k_text_release; /* Set at time of gs_text_begin to know to do release of black_text_state */\
+ bool k_text_release; /* Set at time of gs_text_begin to know to do release of black_textvec_state */\
/* The following is controlled by a device. */\
bool device_disabled_grid_fitting;\
/* Following two members moved from the show enumerator */\