summaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorRay Johnston <ray.johnston@artifex.com>2021-03-16 18:00:13 -0700
committerRay Johnston <ray.johnston@artifex.com>2021-05-03 08:43:18 -0700
commit032cb22e6d63e2e81b86ae6ba1cbd04d7798bae7 (patch)
tree384383fb28c5e38380019437c026087ac99d2196 /base
parent2b5118c3fcb8e5cc58c9a3d87ad9fe327eece117 (diff)
downloadghostpdl-032cb22e6d63e2e81b86ae6ba1cbd04d7798bae7.tar.gz
Add object type specific device halftones to the graphics state.
PostScript 'sethalftone' has an optional parameter "ObjectType" that allows one of the three object specific types to be set: Vector, Image or Text. Also add a new PostScript operator to set the current halftone (dev_ht, set by sethalftone) as the device halftone to be used for an object type: path, image and text. For non-PostScript clients, the gs_halftone structure adds a 'objtype' element (enum) that can be set prior to calling gs_sethalftone. The gs_gstate_s dev_ht is now an array of HT_OBJTYPE_COUNT elements, indexed by the gs_HT_objtype_t enum, with HT_OBJTYPE_DEFAULT (value 0) used for prior sethalftone/setscreen/setcolorscreen operations. NOTE: adding object types beyond the default+3 entries will require modification of gx_select_dev_ht since it only uses 3 bits of the 'tag' to get the index for the dev_ht[] array. For code style, change to use != NULL instead of != 0 in most places that this commit touched (but we may want a general cleanup of this everywhere). TBD: Command line options for all PDL's will need a method to take a halftone specification -- most likely a file that may be "PS-lite" syntax and may be limited to a threshold array. Discussions are in progress.
Diffstat (limited to 'base')
-rw-r--r--base/gsgstate.c26
-rw-r--r--base/gsht.c72
-rw-r--r--base/gsht.h9
-rw-r--r--base/gsht1.c2
-rw-r--r--base/gshtscr.c1
-rw-r--r--base/gshtx.c1
-rw-r--r--base/gsptype2.c5
-rw-r--r--base/gsstate.c2
-rw-r--r--base/gxcht.c6
-rw-r--r--base/gxclimag.c2
-rw-r--r--base/gxclrast.c10
-rw-r--r--base/gxcmap.c62
-rw-r--r--base/gxcmap.h4
-rw-r--r--base/gxdhtserial.c2
-rw-r--r--base/gxgstate.h38
-rw-r--r--base/gxht.c8
-rw-r--r--base/gxht.h1
-rw-r--r--base/gxht_thresh.c23
-rw-r--r--base/gxicolor.c14
-rw-r--r--base/gximono.c16
-rw-r--r--base/gxshade.c2
-rw-r--r--base/gzht.h9
22 files changed, 206 insertions, 109 deletions
diff --git a/base/gsgstate.c b/base/gsgstate.c
index 6eb9b8178..0f7d182a5 100644
--- a/base/gsgstate.c
+++ b/base/gsgstate.c
@@ -112,7 +112,8 @@ gs_gstate_initialize(gs_gstate * pgs, gs_memory_t * mem)
for (i = 0; i < gs_color_select_count; ++i)
pgs->screen_phase[i].x = pgs->screen_phase[i].y = 0;
}
- pgs->dev_ht = 0;
+ for (i=0; i < HT_OBJTYPE_COUNT; i++)
+ pgs->dev_ht[i] = NULL;
pgs->cie_render = 0;
pgs->cie_to_xyz = false;
pgs->black_generation = 0;
@@ -159,8 +160,11 @@ gs_gstate_initialize(gs_gstate * pgs, gs_memory_t * mem)
void
gs_gstate_copied(gs_gstate * pgs)
{
+ int i;
+
rc_increment(pgs->halftone);
- rc_increment(pgs->dev_ht);
+ for (i=0; i < HT_OBJTYPE_COUNT; i++)
+ rc_increment(pgs->dev_ht[i]);
rc_increment(pgs->cie_render);
rc_increment(pgs->black_generation);
rc_increment(pgs->undercolor_removal);
@@ -183,6 +187,7 @@ void
gs_gstate_pre_assign(gs_gstate *pto, const gs_gstate *pfrom)
{
const char *const cname = "gs_gstate_pre_assign";
+ int i;
#define RCCOPY(element)\
rc_pre_assign(pto->element, pfrom->element, cname)
@@ -196,7 +201,8 @@ gs_gstate_pre_assign(gs_gstate *pto, const gs_gstate *pfrom)
RCCOPY(undercolor_removal);
RCCOPY(black_generation);
RCCOPY(cie_render);
- RCCOPY(dev_ht);
+ for (i=0; i < HT_OBJTYPE_COUNT; i++)
+ RCCOPY(dev_ht[i]);
RCCOPY(halftone);
RCCOPY(devicergb_cs);
RCCOPY(devicecmyk_cs);
@@ -212,7 +218,8 @@ void
gs_gstate_release(gs_gstate * pgs)
{
const char *const cname = "gs_gstate_release";
- gx_device_halftone *pdht = pgs->dev_ht;
+ gx_device_halftone *pdht;
+ int i;
#define RCDECR(element)\
rc_decrement(pgs->element, cname);\
@@ -227,13 +234,16 @@ gs_gstate_release(gs_gstate * pgs)
RCDECR(black_generation);
RCDECR(cie_render);
/*
- * If we're going to free the device halftone, make sure we free the
+ * If we're going to free a device halftone, make sure we free the
* dependent structures as well.
*/
- if (pdht != 0 && pdht->rc.ref_count == 1) {
- gx_device_halftone_release(pdht, pdht->rc.memory);
+ for (i=0; i < HT_OBJTYPE_COUNT; i++) {
+ pdht = pgs->dev_ht[i];
+ if (pdht != NULL && pdht->rc.ref_count == 1) {
+ gx_device_halftone_release(pdht, pdht->rc.memory);
+ }
+ RCDECR(dev_ht[i]);
}
- RCDECR(dev_ht);
RCDECR(halftone);
RCDECR(devicergb_cs);
RCDECR(devicecmyk_cs);
diff --git a/base/gsht.c b/base/gsht.c
index bc72f0e17..20c92e125 100644
--- a/base/gsht.c
+++ b/base/gsht.c
@@ -17,6 +17,7 @@
/* setscreen operator for Ghostscript library */
#include "memory_.h"
#include "string_.h"
+#include "assert_.h"
#include <stdlib.h> /* for qsort */
#include "gx.h"
#include "gserrors.h"
@@ -168,12 +169,12 @@ gs_currentscreenlevels(const gs_gstate * pgs)
{
int gi = 0;
- if (pgs->device != 0)
+ if (pgs->device != NULL)
gi = pgs->device->color_info.gray_index;
if (gi != GX_CINFO_COMP_NO_INDEX)
- return pgs->dev_ht->components[gi].corder.num_levels;
+ return pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[gi].corder.num_levels;
else
- return pgs->dev_ht->components[0].corder.num_levels;
+ return pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[0].corder.num_levels;
}
/* .setscreenphase */
@@ -321,9 +322,9 @@ gx_ht_copy_ht_order(gx_ht_order * pdest, gx_ht_order * psrc, gs_memory_t * mem)
psrc->procs, mem);
if (code < 0)
return code;
- if (pdest->levels != 0)
+ if (pdest->levels != NULL)
memcpy(pdest->levels, psrc->levels, psrc->num_levels * sizeof(uint));
- if (pdest->bit_data != 0)
+ if (pdest->bit_data != NULL)
memcpy(pdest->bit_data, psrc->bit_data,
(size_t)psrc->num_bits * psrc->procs->bit_data_elt_size);
pdest->transfer = psrc->transfer;
@@ -576,13 +577,13 @@ gx_ht_order_release(gx_ht_order * porder, gs_memory_t * mem, bool free_cache)
{
/* "free cache" is a proxy for "differs from default" */
if (free_cache) {
- if (porder->cache != 0)
+ if (porder->cache != NULL)
gx_ht_free_cache(mem, porder->cache);
}
porder->cache = 0;
rc_decrement(porder->transfer, "gx_ht_order_release(transfer)");
porder->transfer = 0;
- if (porder->data_memory != 0) {
+ if (porder->data_memory != NULL) {
gs_free_object(porder->data_memory, porder->bit_data,
"gx_ht_order_release(bit_data)");
gs_free_object(porder->data_memory, porder->levels,
@@ -949,7 +950,8 @@ gx_gstate_dev_ht_install(
gs_gstate * pgs,
gx_device_halftone * pdht,
gs_halftone_type type,
- const gx_device * dev )
+ const gx_device * dev,
+ gs_HT_objtype_t objtype )
{
gx_device_halftone dht;
int num_comps = pdht->num_dev_comp;
@@ -960,6 +962,8 @@ gx_gstate_dev_ht_install(
uint w, h;
int dw, dh;
+ assert(objtype < HT_OBJTYPE_COUNT);
+
/* construct the new device halftone structure */
memset(&dht.order, 0, sizeof(dht.order));
/* the rc field is filled in later */
@@ -988,7 +992,7 @@ gx_gstate_dev_ht_install(
* by clearing the corresponding pointers in the operand halftone's
* orders.
*/
- if (pdht->components != 0) {
+ if (pdht->components != NULL) {
int input_ncomps = pdht->num_comp;
for (i = 0; i < input_ncomps && code >= 0; i++) {
@@ -1101,27 +1105,28 @@ gx_gstate_dev_ht_install(
* we still need.
*/
if (code >= 0) {
- gx_device_halftone * pgsdht = pgs->dev_ht;
- rc_header tmp_rc;
-
- if (pgsdht != 0 && pgsdht->rc.ref_count == 1) {
- if (pdht != pgsdht)
- gx_device_halftone_release(pgsdht, pgsdht->rc.memory);
+ gx_device_halftone **ppgsdht;
+ rc_header tmp_rc;
+
+ /* The pgsdht corresponds to the one we will be installing according to 'objtype' */
+ ppgsdht = &(pgs->dev_ht[objtype]);
+ if (*ppgsdht != NULL && (*ppgsdht)->rc.ref_count == 1) {
+ if (pdht != *ppgsdht)
+ gx_device_halftone_release(*ppgsdht, (*ppgsdht)->rc.memory);
} else {
- rc_unshare_struct( pgs->dev_ht,
+ rc_unshare_struct( *ppgsdht,
gx_device_halftone,
&st_device_halftone,
pgs->memory,
BEGIN code = gs_error_VMerror; goto err; END,
"gx_gstate_dev_ht_install" );
- pgsdht = pgs->dev_ht;
}
/*
* Everything worked. "Assume ownership" of the appropriate
* portions of the source device halftone by clearing the
* associated references. Since we might have
- * pdht == pgs->dev_ht, this must done before updating pgs->dev_ht.
+ * pdht == pgs->dev_ht[], this must done before updating pgs->dev_ht[].
*
* If the default order has been used for a device component, and
* any of the source component orders share their levels or bit_data
@@ -1130,7 +1135,7 @@ gx_gstate_dev_ht_install(
* be cleared immediately below, so subsequently it will not be
* possible to tell if that this information is being shared.
*/
- if (pdht->components != 0) {
+ if (pdht->components != NULL) {
int input_ncomps = pdht->num_comp;
for (i = 0; i < input_ncomps; i++) {
@@ -1150,9 +1155,9 @@ gx_gstate_dev_ht_install(
memset(&pdht->order, 0, sizeof(pdht->order));
}
- tmp_rc = pgsdht->rc;
- *pgsdht = dht;
- pgsdht->rc = tmp_rc;
+ tmp_rc = (*ppgsdht)->rc;
+ **ppgsdht = dht;
+ (*ppgsdht)->rc = tmp_rc;
/* update the effective transfer function array */
gx_gstate_set_effective_xfer(pgs);
@@ -1180,6 +1185,22 @@ gx_gstate_dev_ht_install(
}
/*
+ * Copy the dev_ht[HT_OBJTYPE_DEFAULT] to the dev_ht[] for the specified object type.
+ */
+int
+gx_gstate_dev_ht_copy_to_objtype(gs_gstate *pgs, gs_HT_objtype_t objtype)
+{
+ gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT]; /* the current dev_ht */
+
+ if (objtype >= HT_OBJTYPE_COUNT) {
+ return_error(gs_error_undefined);
+ }
+ rc_increment(pdht);
+ pgs->dev_ht[objtype] = pdht;
+ return 0;
+}
+
+/*
* Install a new halftone in the graphics state. Note that we copy the top
* level of the gs_halftone and the gx_device_halftone, and take ownership
* of any substructures.
@@ -1194,7 +1215,7 @@ gx_ht_install(gs_gstate * pgs, const gs_halftone * pht,
int code;
pdht->num_dev_comp = pgs->device->color_info.num_components;
- if (old_ht != 0 && old_ht->rc.memory == mem &&
+ if (old_ht != NULL && old_ht->rc.memory == mem &&
old_ht->rc.ref_count == 1
)
new_ht = old_ht;
@@ -1203,7 +1224,8 @@ gx_ht_install(gs_gstate * pgs, const gs_halftone * pht,
mem, return_error(gs_error_VMerror),
"gx_ht_install(new halftone)");
code = gx_gstate_dev_ht_install(pgs,
- pdht, pht->type, gs_currentdevice_inline(pgs));
+ pdht, pht->type, gs_currentdevice_inline(pgs),
+ pht->objtype);
if (code < 0) {
if (new_ht != old_ht)
gs_free_object(mem, new_ht, "gx_ht_install(new halftone)");
@@ -1242,7 +1264,7 @@ gx_ht_install(gs_gstate * pgs, const gs_halftone * pht,
void
gx_gstate_set_effective_xfer(gs_gstate * pgs)
{
- gx_device_halftone *pdht = pgs->dev_ht;
+ gx_device_halftone *pdht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
gx_transfer_map *pmap;
gx_ht_order *porder;
int i, component_num, non_id_count;
diff --git a/base/gsht.h b/base/gsht.h
index 05857f9fc..f52808524 100644
--- a/base/gsht.h
+++ b/base/gsht.h
@@ -23,6 +23,15 @@
#include "gsgstate.h"
#include "gstypes.h"
+/* Define the ObjectType enum for Halftones */
+typedef enum {
+ HT_OBJTYPE_DEFAULT = 0,
+ HT_OBJTYPE_VECTOR,
+ HT_OBJTYPE_IMAGE,
+ HT_OBJTYPE_TEXT,
+ HT_OBJTYPE_COUNT /* Must be last */
+} gs_HT_objtype_t;
+
/* Client definition of (Type 1) halftones */
typedef struct gs_screen_halftone_s {
float frequency;
diff --git a/base/gsht1.c b/base/gsht1.c
index 05fceb54b..90f7e51b4 100644
--- a/base/gsht1.c
+++ b/base/gsht1.c
@@ -169,6 +169,8 @@ gs_sethalftone_prepare(gs_gstate * pgs, gs_halftone * pht,
gx_ht_order_component *pocs = 0;
int code = 0;
+ if (pht->objtype >= HT_OBJTYPE_COUNT)
+ return_error(gs_error_limitcheck);
switch (pht->type) {
case ht_type_colorscreen:
{
diff --git a/base/gshtscr.c b/base/gshtscr.c
index 34ca12405..6807a9f37 100644
--- a/base/gshtscr.c
+++ b/base/gshtscr.c
@@ -627,6 +627,7 @@ gs_screen_install(gs_screen_enum * penum)
dev_ht.rc.memory = penum->halftone.rc.memory;
dev_ht.order = penum->order;
dev_ht.components = 0;
+ penum->halftone.objtype = HT_OBJTYPE_DEFAULT;
if ((code = gx_ht_install(penum->pgs, &penum->halftone, &dev_ht)) < 0)
gx_device_halftone_release(&dev_ht, dev_ht.rc.memory);
return code;
diff --git a/base/gshtx.c b/base/gshtx.c
index c42f19ba1..bf01fb247 100644
--- a/base/gshtx.c
+++ b/base/gshtx.c
@@ -95,6 +95,7 @@ gs_ht_build(
/* initialize the halftone */
pht->type = ht_type_multiple;
pht->rc.free = free_comps;
+ pht->objtype = HT_OBJTYPE_DEFAULT;
pht->params.ht_multiple.components = phtc;
pht->params.ht_multiple.num_comp = num_comps;
diff --git a/base/gsptype2.c b/base/gsptype2.c
index 878fbe644..b9ef6a05c 100644
--- a/base/gsptype2.c
+++ b/base/gsptype2.c
@@ -158,13 +158,14 @@ gx_dc_is_pattern2_color(const gx_device_color *pdevc)
}
/*
- * The device halftone used by a PatternType 2 patter is that current in
+ * The device halftone used by a PatternType 2 pattern is that current in
* the graphic state at the time of the makepattern call.
*/
static const gx_device_halftone *
gx_dc_pattern2_get_dev_halftone(const gx_device_color * pdevc)
{
- return ((gs_pattern2_instance_t *)pdevc->ccolor.pattern)->saved->dev_ht;
+ /* FIXME: Do we need to be objtype specific w.r.t. to the dev_ht ??? */
+ return ((gs_pattern2_instance_t *)pdevc->ccolor.pattern)->saved->dev_ht[HT_OBJTYPE_DEFAULT];
}
/* Load a PatternType 2 color into the cache. (No effect.) */
diff --git a/base/gsstate.c b/base/gsstate.c
index 7a279201a..f9c06e605 100644
--- a/base/gsstate.c
+++ b/base/gsstate.c
@@ -76,7 +76,7 @@ static void clip_stack_rc_adjust(gx_clip_stack_t *cs, int delta, client_name_t c
*
* (3a) Objects that are logically connected to individual gstates.
* We use reference counting to manage these. Currently these are:
- * halftone, dev_ht, cie_render, black_generation,
+ * halftone, dev_ht(4), cie_render, black_generation,
* undercolor_removal, set_transfer.*, cie_joint_caches,
* clip_stack, {opacity,shape}.mask
* effective_transfer.* may point to some of the same objects as
diff --git a/base/gxcht.c b/base/gxcht.c
index 6625601aa..fa40565a3 100644
--- a/base/gxcht.c
+++ b/base/gxcht.c
@@ -379,7 +379,7 @@ gx_dc_ht_colored_read(
/* the number of components is determined by the color model */
devc.colors.colored.num_components = num_comps;
- devc.colors.colored.c_ht = pgs->dev_ht;
+ devc.colors.colored.c_ht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
/*
* Verify that we have at least the flag bits. For performance
@@ -462,8 +462,8 @@ gx_dc_ht_colored_read(
color_set_phase_mod( &devc,
pgs->screen_phase[0].x,
pgs->screen_phase[0].y,
- pgs->dev_ht->lcm_width,
- pgs->dev_ht->lcm_height );
+ pgs->dev_ht[HT_OBJTYPE_DEFAULT]->lcm_width,
+ pgs->dev_ht[HT_OBJTYPE_DEFAULT]->lcm_height );
/* everything looks OK */
*pdevc = devc;
diff --git a/base/gxclimag.c b/base/gxclimag.c
index 68ab81f54..3958e3728 100644
--- a/base/gxclimag.c
+++ b/base/gxclimag.c
@@ -1585,7 +1585,7 @@ cmd_put_color_mapping(gx_device_clist_writer * cldev,
const gs_gstate * pgs)
{
int code;
- const gx_device_halftone *pdht = pgs->dev_ht;
+ const gx_device_halftone *pdht = gx_select_dev_ht(pgs);
/* Put out the halftone, if present. */
if (pdht && pdht->id != cldev->device_halftone_id) {
diff --git a/base/gxclrast.c b/base/gxclrast.c
index ce683a94f..bfed7ddbb 100644
--- a/base/gxclrast.c
+++ b/base/gxclrast.c
@@ -809,7 +809,7 @@ in: /* Initialize for a new page. */
halftone_type, num_comp);
#endif
code = cmd_resize_halftone(
- &gs_gstate.dev_ht,
+ &gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT],
num_comp, mem);
if (code < 0)
goto out;
@@ -1209,10 +1209,10 @@ set_phase: /*
if (state_tile.size.x)
tile_phase.x =
(state.tile_phase.x + x0) % state_tile.size.x;
- if (gs_gstate.dev_ht && gs_gstate.dev_ht->lcm_width)
+ if (gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT] && gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT]->lcm_width)
color_phase.x =
(state.tile_phase.x + x0) %
- gs_gstate.dev_ht->lcm_width;
+ gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT]->lcm_width;
/*
* The true tile height for shifted tiles is not
* size.y: see gxbitmap.h for the computation.
@@ -1230,10 +1230,10 @@ set_phase: /*
tile_phase.y =
(state.tile_phase.y + y0) % full_height;
}
- if (gs_gstate.dev_ht && gs_gstate.dev_ht->lcm_height)
+ if (gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT] && gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT]->lcm_height)
color_phase.y =
(state.tile_phase.y + y0) %
- gs_gstate.dev_ht->lcm_height;
+ gs_gstate.dev_ht[HT_OBJTYPE_DEFAULT]->lcm_height;
gx_gstate_setscreenphase(&gs_gstate,
-(state.tile_phase.x + x0),
-(state.tile_phase.y + y0),
diff --git a/base/gxcmap.c b/base/gxcmap.c
index cba4908e9..d8344773a 100644
--- a/base/gxcmap.c
+++ b/base/gxcmap.c
@@ -15,6 +15,7 @@
/* Color mapping for Ghostscript */
+#include "assert_.h"
#include "gx.h"
#include "gserrors.h"
#include "gsccolor.h"
@@ -27,6 +28,7 @@
#include "gxcmap.h"
#include "gxlum.h"
#include "gzstate.h"
+#include "gzht.h"
#include "gxdither.h"
#include "gxcdevn.h"
#include "string_.h"
@@ -888,6 +890,32 @@ gx_remap_DeviceCMYK(const gs_client_color * pc, const gs_color_space * pcs,
return 0;
}
+/* ------ Utility for selecting the dev_ht from the pgs using the dev->graphics_type_tag ----- */
+
+static gs_HT_objtype_t
+tag_to_HT_objtype[8] = { HT_OBJTYPE_DEFAULT,
+ HT_OBJTYPE_TEXT, /* GS_TEXT_TAG = 0x1 */
+ HT_OBJTYPE_IMAGE, /* GS_IMAGE_TAG = 0x2 */
+ HT_OBJTYPE_DEFAULT,
+ HT_OBJTYPE_VECTOR, /* GS_VECTOR_TAG = 0x4 */
+ HT_OBJTYPE_DEFAULT, HT_OBJTYPE_DEFAULT, HT_OBJTYPE_DEFAULT
+ };
+
+/* Return the selected dev_ht[] or the pgs->dev_ht[HT_OBJTYPE_DEFAULT] */
+gx_device_halftone *
+gx_select_dev_ht(const gs_gstate *pgs)
+{
+ gs_HT_objtype_t objtype;
+
+ /* This function only works with 3 bits currently. Flag here in case we add object types */
+ assert(HT_OBJTYPE_COUNT == 4);
+
+ objtype = tag_to_HT_objtype[pgs->device->graphics_type_tag & 7];
+ if (pgs->dev_ht[objtype] == NULL)
+ objtype = HT_OBJTYPE_DEFAULT;
+ return pgs->dev_ht[objtype];
+}
+
/* ------ Render Gray color. ------ */
static void
@@ -924,7 +952,7 @@ cmap_gray_halftoned(frac gray, gx_device_color * pdc,
(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
}
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -981,7 +1009,7 @@ cmap_gray_direct(frac gray, gx_device_color * pdc, const gs_gstate * pgs,
color_set_pure(pdc, color);
return;
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1012,7 +1040,7 @@ cmap_rgb_halftoned(frac r, frac g, frac b, gx_device_color * pdc,
(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1056,7 +1084,7 @@ cmap_rgb_direct(frac r, frac g, frac b, gx_device_color * pdc,
color_set_pure(pdc, color);
return;
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1115,7 +1143,7 @@ cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
/* duplicating most of the code of this procedure. */
if (gx_device_must_halftone(dev)) {
if (gx_render_device_DeviceN(cm_comps, pdc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
return;
}
@@ -1133,7 +1161,7 @@ cmap_cmyk_direct(frac c, frac m, frac y, frac k, gx_device_color * pdc,
color_set_pure(pdc, color);
else {
if (gx_render_device_DeviceN(cm_comps, pdc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
}
@@ -1177,7 +1205,7 @@ cmap_rgb_alpha_halftoned(frac r, frac g, frac b, frac alpha,
(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1233,7 +1261,7 @@ cmap_rgb_alpha_direct(frac r, frac g, frac b, frac alpha, gx_device_color * pdc,
color_set_pure(pdc, color);
return;
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1447,7 +1475,7 @@ cmap_separation_halftoned(frac all, gx_device_color * pdc,
(frac)(frac_1 - cm_comps[i]), effective_transfer[i]);
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1572,7 +1600,7 @@ cmap_separation_direct(frac all, gx_device_color * pdc, const gs_gstate * pgs,
return;
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1618,7 +1646,7 @@ cmap_devicen_halftoned(const frac * pcc,
}
/* We need to finish halftoning */
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -1713,7 +1741,7 @@ cmap_devicen_direct(const frac * pcc,
color_set_pure(pdc, color);
return;
}
- if (gx_render_device_DeviceN(cm_comps, pdc, dev, pgs->dev_ht,
+ if (gx_render_device_DeviceN(cm_comps, pdc, dev, gx_select_dev_ht(pgs),
&pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
}
@@ -2093,7 +2121,7 @@ cmapper_transfer_halftone_add(gx_cmapper_t *data)
}
/* Halftoning */
if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(&data->devc, pgs, dev, select);
}
@@ -2122,7 +2150,7 @@ cmapper_transfer_halftone_op(gx_cmapper_t *data)
}
/* Halftoning */
if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(&data->devc, pgs, dev, select);
}
@@ -2146,7 +2174,7 @@ cmapper_transfer_halftone_sub(gx_cmapper_t *data)
}
/* Halftoning */
if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(&data->devc, pgs, dev, select);
}
@@ -2242,7 +2270,7 @@ cmapper_halftone(gx_cmapper_t *data)
cv_frac[i] = cv2frac(pconc[i]);
}
if (gx_render_device_DeviceN(&(cv_frac[0]), &data->devc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(&data->devc, pgs, dev, select);
}
@@ -2371,7 +2399,7 @@ cmap_transfer_halftone(gx_color_value *pconc, gx_device_color * pdc,
/* Halftoning */
if (has_halftone) {
if (gx_render_device_DeviceN(&(cv_frac[0]), pdc, dev,
- pgs->dev_ht, &pgs->screen_phase[select]) == 1)
+ gx_select_dev_ht(pgs), &pgs->screen_phase[select]) == 1)
gx_color_load_select(pdc, pgs, dev, select);
} else {
/* We have a frac value from the transfer function. Do the encode.
diff --git a/base/gxcmap.h b/base/gxcmap.h
index b626e632b..3c7cdb47f 100644
--- a/base/gxcmap.h
+++ b/base/gxcmap.h
@@ -290,4 +290,8 @@ void gx_get_cmapper(gx_cmapper_t *cmapper, const gs_gstate *pgs,
gx_device *dev, bool has_transfer, bool has_halftone,
gs_color_select_t select);
+/* Return the dev_ht[] selected by the pgs->device->graphics_tag */
+/* or the pgs->dev_ht[HT_OBJTYPE_DEFAULT] */
+gx_device_halftone *gx_select_dev_ht(const gs_gstate *pgs);
+
#endif /* gxcmap_INCLUDED */
diff --git a/base/gxdhtserial.c b/base/gxdhtserial.c
index 6f8bb18f3..cd851951a 100644
--- a/base/gxdhtserial.c
+++ b/base/gxdhtserial.c
@@ -584,7 +584,7 @@ gx_ht_read_and_install(
/* save since the 'install' copies the order, but then clears the source order */
for (i = 0; i < num_dev_comps; i++)
components_save[i] = components[i];
- code = gx_gstate_dev_ht_install(pgs, &dht, dht.type, dev);
+ code = gx_gstate_dev_ht_install(pgs, &dht, dht.type, dev, HT_OBJTYPE_DEFAULT);
if (code >= 0) {
for (i = 0; i < num_dev_comps; i++)
gx_ht_order_release(&components_save[i].corder, mem, false);
diff --git a/base/gxgstate.h b/base/gxgstate.h
index a6309d899..c81dfc49e 100644
--- a/base/gxgstate.h
+++ b/base/gxgstate.h
@@ -81,7 +81,7 @@ typedef struct gx_transfer_s {
gs_halftone *halftone; /* (RC) */\
gs_int_point screen_phase[gs_color_select_count];\
/* dev_ht depends on halftone and device resolution. */\
- gx_device_halftone *dev_ht; /* (RC) */\
+ gx_device_halftone *dev_ht[HT_OBJTYPE_COUNT]; /* (RC) */\
\
/* Color (device-dependent): */\
\
@@ -139,7 +139,10 @@ typedef struct gs_gstate_color_s {
*/
#define gs_cr_state_do_rc_ptrs(m)\
m(halftone) \
- m(dev_ht) \
+ m(dev_ht[HT_OBJTYPE_DEFAULT]) \
+ m(dev_ht[HT_OBJTYPE_VECTOR]) \
+ m(dev_ht[HT_OBJTYPE_IMAGE]) \
+ m(dev_ht[HT_OBJTYPE_TEXT]) \
m(cie_render) \
m(black_generation) \
m(undercolor_removal) \
@@ -155,19 +158,22 @@ typedef struct gs_gstate_color_s {
/* Enumerate the pointers in a c.r. state. */
#define gs_cr_state_do_ptrs(m)\
m(0,halftone) \
- m(1,dev_ht) \
- m(2,cie_render) \
- m(3,black_generation) \
- m(4,undercolor_removal) \
- m(5,set_transfer.red) \
- m(6,set_transfer.green) \
- m(7,set_transfer.blue) \
- m(8,set_transfer.gray)\
- m(9,cie_joint_caches) \
- m(10,pattern_cache) \
- m(11,devicergb_cs) \
- m(12,devicecmyk_cs)\
- m(13,cie_joint_caches_alt)
+ m(1,dev_ht[HT_OBJTYPE_DEFAULT]) \
+ m(2, dev_ht[HT_OBJTYPE_VECTOR]) \
+ m(3, dev_ht[HT_OBJTYPE_IMAGE]) \
+ m(4, dev_ht[HT_OBJTYPE_TEXT]) \
+ m(5,cie_render) \
+ m(6,black_generation) \
+ m(7,undercolor_removal) \
+ m(8,set_transfer.red) \
+ m(9,set_transfer.green) \
+ m(10,set_transfer.blue) \
+ m(11,set_transfer.gray)\
+ m(12,cie_joint_caches) \
+ m(13,pattern_cache) \
+ m(14,devicergb_cs) \
+ m(15,devicecmyk_cs)\
+ m(16,cie_joint_caches_alt)
/*
* We handle effective_transfer specially in gsistate.c since its pointers
* are not enumerated for garbage collection but they are are relocated.
@@ -176,7 +182,7 @@ typedef struct gs_gstate_color_s {
* This count does not include the effective_transfer pointers since they
* are not enumerated for GC.
*/
-#define st_cr_state_num_ptrs 14
+#define st_cr_state_num_ptrs 17
struct gs_devicen_color_map_s {
bool use_alt_cspace;
diff --git a/base/gxht.c b/base/gxht.c
index b2322a237..a57662cee 100644
--- a/base/gxht.c
+++ b/base/gxht.c
@@ -545,7 +545,7 @@ gx_dc_ht_binary_read(
devc.type = gx_dc_type_ht_binary;
/* the halftone is always taken from the gs_gstate */
- devc.colors.binary.b_ht = pgs->dev_ht;
+ devc.colors.binary.b_ht = pgs->dev_ht[HT_OBJTYPE_DEFAULT];
/* cache is not porvided until the device color is used */
devc.colors.binary.b_tile = 0;
@@ -592,14 +592,14 @@ gx_dc_ht_binary_read(
devc.colors.binary.b_index = *pdata++;
}
- if (pgs->dev_ht == NULL)
+ if (pgs->dev_ht[HT_OBJTYPE_DEFAULT] == NULL)
return_error(gs_error_unregistered); /* Must not happen. */
/* set the phase as required (select value is arbitrary) */
color_set_phase_mod( &devc,
pgs->screen_phase[0].x,
pgs->screen_phase[0].y,
- pgs->dev_ht->lcm_width,
- pgs->dev_ht->lcm_height );
+ pgs->dev_ht[HT_OBJTYPE_DEFAULT]->lcm_width,
+ pgs->dev_ht[HT_OBJTYPE_DEFAULT]->lcm_height );
/* everything looks good */
*pdevc = devc;
diff --git a/base/gxht.h b/base/gxht.h
index b2743a5a8..e22f4f9ab 100644
--- a/base/gxht.h
+++ b/base/gxht.h
@@ -182,6 +182,7 @@ typedef struct gs_multiple_halftone_s {
struct gs_halftone_s {
gs_halftone_type type;
rc_header rc;
+ gs_HT_objtype_t objtype;
union {
gs_screen_halftone screen; /* setscreen */
gs_colorscreen_halftone colorscreen; /* setcolorscreen */
diff --git a/base/gxht_thresh.c b/base/gxht_thresh.c
index 348307ec4..c981f81b9 100644
--- a/base/gxht_thresh.c
+++ b/base/gxht_thresh.c
@@ -585,9 +585,11 @@ gxht_thresh_image_init(gx_image_enum *penum)
gx_dda_fixed dda_ht;
if (gx_device_must_halftone(penum->dev)) {
- if (penum->pgs != NULL && penum->pgs->dev_ht != NULL) {
- for (k = 0; k < penum->pgs->dev_ht->num_comp; k++) {
- d_order = &(penum->pgs->dev_ht->components[k].corder);
+ if (penum->pgs != NULL && penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT] != NULL) {
+ gx_device_halftone *pdht = gx_select_dev_ht(penum->pgs);
+
+ for (k = 0; k < pdht->num_comp; k++) {
+ d_order = &(pdht->components[k].corder);
code = gx_ht_construct_threshold(d_order, penum->dev,
penum->pgs, k);
if (code < 0 ) {
@@ -871,6 +873,7 @@ gxht_thresh_planes(gx_image_enum *penum, fixed xrun,
gx_color_index dev_black = gx_device_black(dev);
int spp_out = dev->color_info.num_components;
byte *contone_align = NULL; /* Init to silence compiler warnings */
+ gx_device_halftone *pdht = gx_select_dev_ht(penum->pgs);
/* Go ahead and fill the threshold line buffer with tiled threshold values.
First just grab the row or column that we are going to tile with and
@@ -883,10 +886,10 @@ gxht_thresh_planes(gx_image_enum *penum, fixed xrun,
/* Iterate over the vdi and fill up our threshold buffer. We
also need to loop across the planes of data */
for (j = 0; j < spp_out; j++) {
- bool threshold_inverted = penum->pgs->dev_ht->components[j].corder.threshold_inverted;
+ bool threshold_inverted = pdht->components[j].corder.threshold_inverted;
- thresh_width = penum->pgs->dev_ht->components[j].corder.width;
- thresh_height = penum->pgs->dev_ht->components[j].corder.full_height;
+ thresh_width = pdht->components[j].corder.width;
+ thresh_height = pdht->components[j].corder.full_height;
halftone = penum->ht_buffer + j * vdi * dithered_stride;
/* Compute the tiling positions with dest_width */
dx = (fixed2int_var_rounded(xrun) + penum->pgs->screen_phase[0].x) % thresh_width;
@@ -901,7 +904,7 @@ gxht_thresh_planes(gx_image_enum *penum, fixed xrun,
right_tile_width = dest_width - num_full_tiles * thresh_width -
left_width;
/* Get the proper threshold for the colorant count */
- threshold = penum->pgs->dev_ht->components[j].corder.threshold;
+ threshold = pdht->components[j].corder.threshold;
/* Point to the proper contone data */
contone_align = penum->line + contone_stride * j +
offset_contone[j];
@@ -995,11 +998,11 @@ gxht_thresh_planes(gx_image_enum *penum, fixed xrun,
for (j = 0; j < spp_out; j++) {
halftone = penum->ht_buffer +
j * penum->ht_plane_height * (LAND_BITS>>3);
- thresh_width = penum->pgs->dev_ht->components[j].corder.width;
+ thresh_width = pdht->components[j].corder.width;
thresh_height =
- penum->pgs->dev_ht->components[j].corder.full_height;
+ pdht->components[j].corder.full_height;
/* Get the proper threshold for the colorant count */
- threshold = penum->pgs->dev_ht->components[j].corder.threshold;
+ threshold = pdht->components[j].corder.threshold;
/* Point to the proper contone data */
contone_align = penum->line + offset_contone[j] +
LAND_BITS * j * contone_stride;
diff --git a/base/gxicolor.c b/base/gxicolor.c
index 05820695b..4785ab4f0 100644
--- a/base/gxicolor.c
+++ b/base/gxicolor.c
@@ -108,7 +108,7 @@ color_halftone_init(gx_image_enum *penum)
if (!gx_device_must_halftone(penum->dev))
return NULL;
- if (penum->pgs == NULL || penum->pgs->dev_ht == NULL)
+ if (penum->pgs == NULL || penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT] == NULL)
return NULL;
dda_ht = penum->dda.pixel0.x;
if (penum->dxx > 0)
@@ -136,20 +136,20 @@ color_halftone_init(gx_image_enum *penum)
if (cal_ht == NULL)
goto fail;
- for (k = 0; k < penum->pgs->dev_ht->num_comp; k++) {
- d_order = &(penum->pgs->dev_ht->components[k].corder);
+ for (k = 0; k < penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT]->num_comp; k++) {
+ d_order = &(penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[k].corder);
code = gx_ht_construct_threshold(d_order, penum->dev, penum->pgs, k);
if (code < 0)
goto fail;
if (cal_halftone_add_screen(ctx,
penum->memory->non_gc_memory,
cal_ht,
- penum->pgs->dev_ht->components[k].corder.threshold_inverted,
- penum->pgs->dev_ht->components[k].corder.width,
- penum->pgs->dev_ht->components[k].corder.full_height,
+ penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[k].corder.threshold_inverted,
+ penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[k].corder.width,
+ penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[k].corder.full_height,
-penum->pgs->screen_phase[k].x,
-penum->pgs->screen_phase[k].y,
- penum->pgs->dev_ht->components[k].corder.threshold) < 0)
+ penum->pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[k].corder.threshold) < 0)
goto fail;
}
diff --git a/base/gximono.c b/base/gximono.c
index 659a6ccb9..7b40f3de7 100644
--- a/base/gximono.c
+++ b/base/gximono.c
@@ -96,12 +96,14 @@ halftone_init(gx_image_enum *penum)
byte *cache = (penum->color_cache != NULL ? penum->color_cache->device_contone : NULL);
cal_matrix matrix;
int clip_x, clip_y;
+ gx_device_halftone *pdht = gx_select_dev_ht(penum->pgs);
if (!gx_device_must_halftone(penum->dev))
return NULL;
- if (penum->pgs == NULL || penum->pgs->dev_ht == NULL)
+ if (penum->pgs == NULL || pdht == NULL)
return NULL;
+
dda_ht = penum->dda.pixel0.x;
if (penum->dxx > 0)
dda_translate(dda_ht, -fixed_epsilon);
@@ -129,20 +131,20 @@ halftone_init(gx_image_enum *penum)
if (cal_ht == NULL)
goto fail;
- for (k = 0; k < penum->pgs->dev_ht->num_comp; k++) {
- d_order = &(penum->pgs->dev_ht->components[k].corder);
+ for (k = 0; k < pdht->num_comp; k++) {
+ d_order = &(pdht->components[k].corder);
code = gx_ht_construct_threshold(d_order, penum->dev, penum->pgs, k);
if (code < 0)
goto fail;
if (cal_halftone_add_screen(penum->memory->gs_lib_ctx->core->cal_ctx,
penum->memory->non_gc_memory,
cal_ht,
- penum->pgs->dev_ht->components[k].corder.threshold_inverted,
- penum->pgs->dev_ht->components[k].corder.width,
- penum->pgs->dev_ht->components[k].corder.full_height,
+ pdht->components[k].corder.threshold_inverted,
+ pdht->components[k].corder.width,
+ pdht->components[k].corder.full_height,
penum->pgs->screen_phase[k].x,
-penum->pgs->screen_phase[k].y,
- penum->pgs->dev_ht->components[k].corder.threshold) < 0)
+ pdht->components[k].corder.threshold) < 0)
goto fail;
}
diff --git a/base/gxshade.c b/base/gxshade.c
index a0ddf2900..08b9edcc2 100644
--- a/base/gxshade.c
+++ b/base/gxshade.c
@@ -365,7 +365,7 @@ top:
}
if (num_colors <= 32) {
/****** WRONG FOR MULTI-PLANE HALFTONES ******/
- num_colors *= pgs->dev_ht->components[0].corder.num_levels;
+ num_colors *= pgs->dev_ht[HT_OBJTYPE_DEFAULT]->components[0].corder.num_levels;
}
if (psh->head.type == 2 || psh->head.type == 3) {
max_error *= 0.25;
diff --git a/base/gzht.h b/base/gzht.h
index 9c1e0fe8a..358bd350f 100644
--- a/base/gzht.h
+++ b/base/gzht.h
@@ -196,7 +196,14 @@ void gx_ht_order_release(gx_ht_order * porder, gs_memory_t * mem, bool free_cach
int gx_gstate_dev_ht_install(gs_gstate * pgs,
gx_device_halftone * pdht,
gs_halftone_type type,
- const gx_device * dev);
+ const gx_device * dev,
+ gs_HT_objtype_t objtype);
+
+/*
+ * Copy the current dev_ht[HT_OBJTYPE_DEFAULT] to the dev_ht[] for the specified object type.
+ */
+int
+gx_gstate_dev_ht_copy_to_objtype(gs_gstate *pgs, gs_HT_objtype_t objtype);
/*
* Install a new halftone in the graphics state. Note that we copy the top