From 4c8d80f91aef717877f36699fbf0bae6a568494c Mon Sep 17 00:00:00 2001 From: Michael Vrhel Date: Tue, 5 Nov 2019 15:12:35 -0800 Subject: Add a way to set the op device state (fill or stroke) through the compositor This command will only occur when we are doing an actual operation (e.g. fill stroke) --- base/gscdevn.c | 1 + base/gscsepr.c | 1 + base/gscspace.c | 3 +++ base/gsovrc.c | 62 ++++++++++++++++++++++++++++++++++----------------------- base/gsovrc.h | 9 ++++++++- base/gstext.c | 19 ++++++++++++++++++ 6 files changed, 69 insertions(+), 26 deletions(-) diff --git a/base/gscdevn.c b/base/gscdevn.c index f40bf2c93..6e0e0f269 100644 --- a/base/gscdevn.c +++ b/base/gscdevn.c @@ -752,6 +752,7 @@ gx_set_overprint_DeviceN(const gs_color_space * pcs, gs_gstate * pgs) /* Only DeviceCMYK can use overprint mode */ pgs->color[0].effective_opm = 0; + params.op_state = OP_STATE_NONE; return gs_gstate_update_overprint(pgs, ¶ms); } } diff --git a/base/gscsepr.c b/base/gscsepr.c index 83f10c811..09317e4c9 100644 --- a/base/gscsepr.c +++ b/base/gscsepr.c @@ -195,6 +195,7 @@ gx_set_overprint_Separation(const gs_color_space * pcs, gs_gstate * pgs) pcs->params.separation.sep_type != SEP_ALL; params.is_fill_color = pgs->is_fill_color; params.drawn_comps = 0; + params.op_state = OP_STATE_NONE; if (params.retain_any_comps) { if (pcs->params.separation.sep_type != SEP_NONE) { int mcomp = pcmap->color_map[0]; diff --git a/base/gscspace.c b/base/gscspace.c index 2d5583f17..8e4f51422 100644 --- a/base/gscspace.c +++ b/base/gscspace.c @@ -476,6 +476,7 @@ gx_set_no_overprint(gs_gstate* pgs) gs_overprint_params_t params = { 0 }; params.retain_any_comps = false; + params.op_state = OP_STATE_NONE; params.is_fill_color = pgs->is_fill_color; pgs->color[0].effective_opm = 0; @@ -501,6 +502,7 @@ gx_spot_colors_set_overprint(const gs_color_space * pcs, gs_gstate * pgs) params.retain_any_comps = true; params.is_fill_color = pgs->is_fill_color; + params.op_state = OP_STATE_NONE; /* Only DeviceCMYK case can have overprint mode set to true */ pgs->color[0].effective_opm = 0; @@ -746,6 +748,7 @@ int gx_set_overprint_cmyk(const gs_color_space * pcs, gs_gstate * pgs) params.is_fill_color = pgs->is_fill_color; params.retain_any_comps = true; params.drawn_comps = drawn_comps; + params.op_state = OP_STATE_NONE; if_debug2m(gs_debug_flag_overprint, pgs->memory, "[overprint] gx_set_overprint_cmyk. retain_any_comps = %d, drawn_comps = 0x%x\n", diff --git a/base/gsovrc.c b/base/gsovrc.c index d1e814476..58e1ee671 100644 --- a/base/gsovrc.c +++ b/base/gsovrc.c @@ -109,6 +109,7 @@ c_overprint_equal(const gs_composite_t * pct0, const gs_composite_t * pct1) pparams0 = &((const gs_overprint_t *)(pct0))->params; pparams1 = &((const gs_overprint_t *)(pct1))->params; + if (pparams0->is_fill_color != pparams1->is_fill_color) return true; /* this changed */ if (!pparams0->retain_any_comps) @@ -124,8 +125,8 @@ c_overprint_equal(const gs_composite_t * pct0, const gs_composite_t * pct1) * representation of an overprint compositor. */ #define OVERPRINT_ANY_COMPS 1 -#define OVERPRINT_SPOT_COMPS 2 -#define OVERPRINT_IS_FILL_COLOR 4 +#define OVERPRINT_IS_FILL_COLOR 2 +#define OVERPRINT_SET_FILL_COLOR 0xc /* * Convert an overprint compositor to string form for use by the command @@ -139,9 +140,11 @@ c_overprint_write(const gs_composite_t * pct, byte * data, uint * psize, gx_devi int used = 1, avail = *psize; /* encoded the booleans in a single byte */ - if (pparams->retain_any_comps || pparams->is_fill_color) { + if (pparams->retain_any_comps || pparams->is_fill_color || pparams->op_state) { flags |= (pparams->retain_any_comps) ? OVERPRINT_ANY_COMPS : 0; flags |= (pparams->is_fill_color) ? OVERPRINT_IS_FILL_COLOR : 0; + flags |= (pparams->op_state) ? OVERPRINT_SET_FILL_COLOR : 0; + /* write out the component bits */ if (pparams->retain_any_comps) { uint tmp_size = (avail > 0 ? avail - 1 : 0); @@ -186,6 +189,7 @@ c_overprint_read( if_debug1m('v', mem, "[v]c_overprint_read(%d)", flags); params.retain_any_comps = (flags & OVERPRINT_ANY_COMPS) != 0; params.is_fill_color = (flags & OVERPRINT_IS_FILL_COLOR) != 0; + params.op_state = (flags & OVERPRINT_SET_FILL_COLOR) != 0; params.idle = 0; params.drawn_comps = 0; @@ -197,6 +201,8 @@ c_overprint_read( nbytes += code; if_debug0m('v', mem, ", drawn_comps read"); } + if_debug1m('v', mem, ", retain_any_comps=%d", params.retain_any_comps); + if_debug1m('v', mem, ", is_fill_color=%d", params.is_fill_color); if_debug1m('v', mem, ", drawn_comps=0x%x", params.drawn_comps); if_debug0m('v', mem, "\n"); code = gs_create_overprint(ppct, ¶ms, mem); @@ -294,7 +300,7 @@ typedef struct overprint_device_s { * target color space is not separable and linear. It is also used * for the devn color values since we may need more than 8 components */ - bool is_fill_color; /* used to select drawn_comps, fill or stroke */ + OP_FS_STATE op_state; /* used to select drawn_comps, fill or stroke */ gx_color_index drawn_comps_fill; gx_color_index drawn_comps_stroke; /* pparams->is_fill_color determines which to set */ bool retain_none_stroke; /* These are used to know when we can set the procs to forward */ @@ -755,6 +761,12 @@ update_overprint_params( we will turn it off when setting one and turn on when setting the other (or vice versa) */ + /* Note if pparams is to set the opdev fill stroke state. Do that now and exit */ + if (pparams->op_state != OP_STATE_NONE) { + opdev->op_state = pparams->op_state; + return 0; + } + if_debug4m(gs_debug_flag_overprint, opdev->memory, "[overprint] update_overprint_params enter. retain_any_comps = %d, idle = %d, drawn_comps = 0x%x, is_fill_color = %d\n", pparams->retain_any_comps, pparams->idle, pparams->drawn_comps, pparams->is_fill_color); @@ -927,9 +939,9 @@ overprint_create_compositor( params.idle = pct->idle; /* device must already exist, so just update the parameters if settings change */ - if_debug7m(gs_debug_flag_overprint, opdev->memory, - "[overprint] overprint_create_compositor test for change. params.idle = %d vs. opdev->is_idle = %d \n params.is_fill_color = %d vs. opdev->is_fill_color = %d \n params.drawn_comps = 0x%x vs. opdev->drawn_comps_fill = 0x%x OR opdev->drawn_comps_stroke = 0x%x\n", - params.idle, opdev->is_idle, params.is_fill_color, opdev->is_fill_color, params.drawn_comps, opdev->drawn_comps_fill, opdev->drawn_comps_stroke); + if_debug6m(gs_debug_flag_overprint, opdev->memory, + "[overprint] overprint_create_compositor test for change. params.idle = %d vs. opdev->is_idle = %d \n params.is_fill_color = %d: params.drawn_comps = 0x%x vs. opdev->drawn_comps_fill = 0x%x OR opdev->drawn_comps_stroke = 0x%x\n", + params.idle, opdev->is_idle, params.is_fill_color, params.drawn_comps, opdev->drawn_comps_fill, opdev->drawn_comps_stroke); if (!params.retain_any_comps || params.idle != opdev->is_idle || params.drawn_comps != (params.is_fill_color ? @@ -967,12 +979,12 @@ overprint_generic_fill_rectangle( /* See if we even need to do any overprinting. We have to maintain the compositor active for fill/stroke cases even if we are only doing a fill or a stroke */ - if ((opdev->is_fill_color && opdev->retain_none_fill) || - (!opdev->is_fill_color && opdev->retain_none_stroke)) + if ((opdev->op_state == OP_STATE_FILL && opdev->retain_none_fill) || + (opdev->op_state == OP_STATE_STROKE && opdev->retain_none_stroke)) return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, width, height, color); return gx_overprint_generic_fill_rectangle(tdev, - opdev->is_fill_color ? + opdev->op_state == OP_STATE_FILL ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke, x, y, width, height, color, dev->memory); } @@ -1020,7 +1032,7 @@ overprint_copy_planes(gx_device * dev, const byte * data, int data_x, int raster uchar num_comps; uchar k,j; gs_memory_t * mem = dev->memory; - gx_color_index comps = opdev->is_fill_color ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke; + gx_color_index comps = opdev->op_state == OP_STATE_FILL ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke; byte *curr_data = (byte *) data + data_x; int row, offset; @@ -1144,8 +1156,8 @@ overprint_fill_rectangle_hl_color(gx_device *dev, /* See if we even need to do any overprinting. We have to maintain the compositor active for fill/stroke cases even if we are only doing a fill or a stroke */ - if ((opdev->is_fill_color && opdev->retain_none_fill) || - (!opdev->is_fill_color && opdev->retain_none_stroke)) + if ((opdev->op_state == OP_STATE_FILL && opdev->retain_none_fill) || + (opdev->op_state == OP_STATE_STROKE && opdev->retain_none_stroke)) return (*dev_proc(tdev, fill_rectangle_hl_color)) (tdev, rect, pgs, pdcolor, pcpath); depth = tdev->color_info.depth; @@ -1188,7 +1200,7 @@ overprint_fill_rectangle_hl_color(gx_device *dev, while (h-- > 0 && code >= 0) { gb_rect.p.y = y++; gb_rect.q.y = y; - comps = opdev->is_fill_color ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke; + comps = opdev->op_state == OP_STATE_FILL ? opdev->drawn_comps_fill : opdev->drawn_comps_stroke; /* And now through each plane */ for (k = 0; k < tdev->color_info.num_components; k++) { /* First set the params to zero for all planes except the one we want */ @@ -1245,8 +1257,8 @@ overprint_sep_fill_rectangle( /* See if we even need to do any overprinting. We have to maintain the compositor active for fill/stroke cases even if we are only doing a fill or a stroke */ - if ((opdev->is_fill_color && opdev->retain_none_fill) || - (!opdev->is_fill_color && opdev->retain_none_stroke)) + if ((opdev->op_state == OP_STATE_FILL && opdev->retain_none_fill) || + (opdev->op_state == OP_STATE_STROKE && opdev->retain_none_stroke)) return (*dev_proc(tdev, fill_rectangle)) (tdev, x, y, width, height, color); /* @@ -1274,12 +1286,12 @@ overprint_sep_fill_rectangle( * depth < 8 * sizeof(mono_fill_chunk). */ if ( depth <= 8 * sizeof(mono_fill_chunk) && (depth & (depth - 1)) == 0) - return gx_overprint_sep_fill_rectangle_1(tdev, opdev->is_fill_color ? + return gx_overprint_sep_fill_rectangle_1(tdev, opdev->op_state == OP_STATE_FILL ? opdev->retain_mask_fill : opdev->retain_mask_stroke, x, y, width, height, color, dev->memory); else - return gx_overprint_sep_fill_rectangle_2(tdev, opdev->is_fill_color ? + return gx_overprint_sep_fill_rectangle_2(tdev, opdev->op_state == OP_STATE_FILL ? opdev->retain_mask_fill : opdev->retain_mask_stroke, x, y, width, height, color, dev->memory); @@ -1294,7 +1306,7 @@ overprint_fill_path(gx_device* pdev, const gs_gstate* pgs, { overprint_device_t* opdev = (overprint_device_t*)pdev; - opdev->is_fill_color = true; + opdev->op_state = OP_STATE_FILL; return gx_default_fill_path(pdev, pgs, ppath, params_fill, pdcolor, pcpath); } @@ -1308,7 +1320,7 @@ overprint_stroke_path(gx_device* pdev, const gs_gstate* pgs, overprint_device_t* opdev = (overprint_device_t*)pdev; int code; - opdev->is_fill_color = false; + opdev->op_state = OP_STATE_STROKE; /* Stroke methods use fill path so set that to default to avoid mix up of is_fill_color */ @@ -1335,14 +1347,14 @@ overprint_fill_stroke_path(gx_device * pdev, const gs_gstate * pgs, int code; overprint_device_t *opdev = (overprint_device_t *)pdev; - opdev->is_fill_color = true; + opdev->op_state = OP_STATE_FILL; code = dev_proc(pdev, fill_path)(pdev, pgs, ppath, params_fill, pdevc_fill, pcpath); if (code < 0) return code; + /* Set up for stroke */ - opdev->is_fill_color = false; + opdev->op_state = OP_STATE_STROKE; code = dev_proc(pdev, stroke_path)(pdev, pgs, ppath, params_stroke, pdevc_stroke, pcpath); - opdev->is_fill_color = true; return code; } @@ -1357,9 +1369,9 @@ overprint_text_begin(gx_device* dev, gs_gstate* pgs, overprint_device_t* opdev = (overprint_device_t*)dev; if (pgs->text_rendering_mode == 0) - opdev->is_fill_color = true; + opdev->op_state = OP_STATE_FILL; else if (pgs->text_rendering_mode == 1) - opdev->is_fill_color = false; + opdev->op_state = OP_STATE_STROKE; return gx_default_text_begin(dev, pgs, text, font, path, pdcolor, pcpath, mem, ppte); diff --git a/base/gsovrc.h b/base/gsovrc.h index 22822b1b1..48ce148e9 100644 --- a/base/gsovrc.h +++ b/base/gsovrc.h @@ -216,6 +216,12 @@ * closing of a device is not itself used as an error indication. */ +typedef enum { + OP_STATE_NONE = 0, + OP_STATE_FILL, + OP_STATE_STROKE, +} OP_FS_STATE; + typedef struct gs_overprint_params_s gs_overprint_params_t; struct gs_overprint_params_s { @@ -248,7 +254,8 @@ struct gs_overprint_params_s { * it is to be left unaffected. */ gx_color_index drawn_comps; - bool is_fill_color; /* for fill_stroke_path we differentiate */ + bool is_fill_color; /* This tells us what the current color is for our set up */ + OP_FS_STATE op_state; /* This sets the state of the device for an upcoming command */ }; /* diff --git a/base/gstext.c b/base/gstext.c index 1296e64f4..bb8b08e9c 100644 --- a/base/gstext.c +++ b/base/gstext.c @@ -271,6 +271,7 @@ gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text, { gx_clip_path *pcpath = 0; int code; + gs_overprint_params_t op_params = { 0 }; /* * Detect nocurrentpoint now, even if the string is empty, for Adobe @@ -310,6 +311,24 @@ gs_text_begin(gs_gstate * pgs, const gs_text_params_t * text, code = gs_gstate_color_load(pgs); if (code < 0) return code; + + /* If overprint is true, push the compositor action to set the op device state */ + if (pgs->overprint || pgs->stroke_overprint) { + gx_device* dev = pgs->device; + cmm_dev_profile_t* dev_profile; + + dev_proc(dev, get_profile)(dev, &dev_profile); + if (dev_profile->sim_overprint && dev_profile->device_profile[0]->data_cs == gsCMYK) { + if (pgs->overprint && (pgs->text_rendering_mode == 0)) { + op_params.op_state = OP_STATE_FILL; + gs_gstate_update_overprint(pgs, &op_params); + } else if (pgs->stroke_overprint && (pgs->text_rendering_mode == 1)) { + op_params.op_state = OP_STATE_STROKE; + gs_gstate_update_overprint(pgs, &op_params); + } + } + } + pgs->device->sgr.stroke_stored = false; return gx_device_text_begin(pgs->device, pgs, text, pgs->font, pgs->path, -- cgit v1.2.1