Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gdevmplt.c
Line
Count
Source
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
/* Device to set monochrome mode in PCL */
17
/* This device is one of the 'subclassing' devices, part of a chain or pipeline
18
 * of devices, each of which can process some aspect of the graphics methods
19
 * before passing them on to the next device in the chain.
20
 * In this case, the device simply returns monochrome color_mapping procs
21
 * instead of color ones. When we want to go back to color, we just
22
 * remove this device.
23
 */
24
#include "math_.h"
25
#include "memory_.h"
26
#include "gx.h"
27
#include "gserrors.h"
28
#include "gsparam.h"
29
#include "gxdevice.h"
30
#include "gsdevice.h"   /* requires gsmatrix.h */
31
#include "gxdcolor.h"   /* for gx_device_black/white */
32
#include "gxiparam.h"   /* for image source size */
33
#include "gxgstate.h"
34
#include "gxpaint.h"
35
#include "gxpath.h"
36
#include "gxcpath.h"
37
#include "gxcmap.h"         /* color mapping procs */
38
#include "gsstype.h"
39
#include "gdevprn.h"
40
#include "gdevp14.h"        /* Needed to patch up the procs after compositor creation */
41
#include "gdevsclass.h"
42
#include "gdevmplt.h"
43
#include "gxdcconv.h"       /* for color_rgb_to_gray and color_cmyk_to_gray */
44
#include "gxdevsop.h"
45
46
/* Device procedures, we only need one */
47
static dev_proc_get_color_mapping_procs(pcl_mono_palette_get_color_mapping_procs);
48
49
/* The device prototype */
50
#define MAX_COORD (max_int_in_fixed - 1000)
51
#define MAX_RESOLUTION 4000
52
53
/* GC descriptor */
54
#define public_st_pcl_mono_palette_device() /* in gsdevice.c */\
55
  gs_public_st_complex_only(st_pcl_mono_palette_device, gx_device, "PCL_Mono_Palette",\
56
    0, pcl_mono_palette_enum_ptrs, pcl_mono_palette_reloc_ptrs, default_subclass_finalize)
57
58
static
59
0
ENUM_PTRS_WITH(pcl_mono_palette_enum_ptrs, gx_device *dev);
60
0
return 0; /* default case */
61
0
case 0:ENUM_RETURN(gx_device_enum_ptr(dev->parent));
62
0
case 1:ENUM_RETURN(gx_device_enum_ptr(dev->child));
63
0
ENUM_PTRS_END
64
0
static RELOC_PTRS_WITH(pcl_mono_palette_reloc_ptrs, gx_device *dev)
65
0
{
66
0
    dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
67
0
    dev->child = gx_device_reloc_ptr(dev->child, gcst);
68
0
}
69
0
RELOC_PTRS_END
70
71
public_st_pcl_mono_palette_device();
72
73
static int
74
pcl_mono_dev_spec_op(gx_device *dev, int dev_spec_op, void *data, int size)
75
0
{
76
0
    if (dev_spec_op == gxdso_supports_hlcolor)
77
0
        return 0;
78
0
    if (dev->child)
79
0
        return dev_proc(dev->child, dev_spec_op)(dev->child, dev_spec_op, data, size);
80
0
    return_error(gs_error_rangecheck);
81
0
}
82
83
static int
84
pcl_mono_text_begin(gx_device *dev, gs_gstate *pgs, const gs_text_params_t *text,
85
    gs_font *font, const gx_clip_path *pcpath, gs_text_enum_t **ppte)
86
0
{
87
    /* The 'high level' version of the color has not been 'monochromized' by this
88
     * device, so ensure that routines that we call (notably pdfwrite) don't
89
     * think it's valid and use it. */
90
0
    pgs->color[0].dev_color->ccolor_valid = 0;
91
92
0
    if (dev->child)
93
0
        return dev_proc(dev->child, text_begin)(dev->child, pgs, text, font, pcpath, ppte);
94
0
    else
95
0
        return gx_default_text_begin(dev, pgs, text, font, pcpath, ppte);
96
0
}
97
98
static void
99
pcl_mono_palette_initialize(gx_device *dev)
100
0
{
101
0
    default_subclass_initialize_device_procs(dev);
102
103
0
    set_dev_proc(dev, get_color_mapping_procs, pcl_mono_palette_get_color_mapping_procs);
104
    /* We must override begin_typed_image here with the default. If
105
     * we don't, then we forward down to the underlying devices own
106
     * begin_typed_image, and the color calls done during that bypass
107
     * the monochroming behaviour. See: page 32 of 75dpi png rendering of
108
     * tests_private/pcl/pcl5ccet/15-01.BIN for an example. */
109
0
    set_dev_proc(dev, begin_typed_image, gx_default_begin_typed_image);
110
0
    set_dev_proc(dev, dev_spec_op, pcl_mono_dev_spec_op);
111
0
    set_dev_proc(dev, text_begin, pcl_mono_text_begin);
112
0
}
113
114
const
115
gx_device_mplt gs_pcl_mono_palette_device =
116
{
117
    /*
118
     * Define the device as 8-bit gray scale to avoid computing halftones.
119
     */
120
    std_device_dci_type_body_sc(gx_device_mplt, pcl_mono_palette_initialize,
121
                        "PCL_Mono_Palette", &st_pcl_mono_palette_device,
122
                        MAX_COORD, MAX_COORD,
123
                        MAX_RESOLUTION, MAX_RESOLUTION,
124
                        1, 8, 255, 0, 256, 1, NULL, NULL, NULL)
125
};
126
127
#undef MAX_COORD
128
#undef MAX_RESOLUTION
129
130
/* The justification for this device, these 3 procedures map colour values
131
 * to gray values
132
 */
133
static void
134
pcl_gray_cs_to_cm(const gx_device * dev, frac gray, frac out[])
135
0
{
136
0
    pcl_mono_palette_subclass_data *psubclass_data = dev->subclass_data;
137
138
    /* assert(strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0) - otherwise we are being
139
     * called with the wrong dev! */
140
141
0
    if (psubclass_data->device_cm) {
142
        /* just pass it along */
143
0
        psubclass_data->device_cm_procs->map_gray(psubclass_data->device_cm, gray, out);
144
0
    }
145
0
}
146
147
static void
148
pcl_rgb_cs_to_cm(const gx_device * dev, const gs_gstate * pgs, frac r, frac g,
149
                 frac b, frac out[])
150
0
{
151
0
    pcl_mono_palette_subclass_data *psubclass_data = dev->subclass_data;
152
0
    frac gray;
153
154
    /* assert(strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0) - otherwise we are being
155
     * called with the wrong dev! */
156
157
0
    if (psubclass_data->device_cm) {
158
0
        gray = color_rgb_to_gray(r, g, b, NULL);
159
160
0
        psubclass_data->device_cm_procs->map_rgb(psubclass_data->device_cm, pgs, gray, gray, gray, out);
161
0
    }
162
0
}
163
164
static void
165
pcl_cmyk_cs_to_cm(const gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
166
0
{
167
0
    pcl_mono_palette_subclass_data *psubclass_data = dev->subclass_data;
168
0
    frac gray;
169
170
    /* assert(strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0) - otherwise we are being
171
     * called with the wrong dev! */
172
173
0
    if (psubclass_data->device_cm) {
174
0
        gray = color_cmyk_to_gray(c, m, y, k, NULL);
175
176
0
        psubclass_data->device_cm_procs->map_cmyk(psubclass_data->device_cm, gray, gray, gray, gray, out);
177
0
    }
178
0
}
179
180
static gx_cm_color_map_procs pcl_mono_procs =
181
{
182
    pcl_gray_cs_to_cm,
183
    pcl_rgb_cs_to_cm,
184
    pcl_cmyk_cs_to_cm
185
};
186
187
const gx_cm_color_map_procs *pcl_mono_palette_get_color_mapping_procs(const gx_device  *dev,
188
                                                                      const gx_device **tdev)
189
0
{
190
0
    pcl_mono_palette_subclass_data *psubclass_data = dev->subclass_data;
191
192
    /* assert(strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0) - otherwise we are being
193
     * called with the wrong dev! */
194
195
0
    *tdev = dev;
196
0
    if (psubclass_data->device_cm_procs == NULL) {
197
0
        psubclass_data->device_cm_procs = (gx_cm_color_map_procs *)dev_proc(dev->child, get_color_mapping_procs)(dev->child, &psubclass_data->device_cm);
198
0
    }
199
0
    return &pcl_mono_procs;
200
0
}