1 /* Copyright (C) 2001-2019 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.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, 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 
45 /* Device procedures, we only need one */
46 static dev_proc_get_color_mapping_procs(pcl_mono_palette_get_color_mapping_procs);
47 
48 /* The device prototype */
49 #define MAX_COORD (max_int_in_fixed - 1000)
50 #define MAX_RESOLUTION 4000
51 
52 /* GC descriptor */
53 #define public_st_pcl_mono_palette_device()	/* in gsdevice.c */\
54   gs_public_st_complex_only(st_pcl_mono_palette_device, gx_device, "PCL_Mono_Palette",\
55     0, pcl_mono_palette_enum_ptrs, pcl_mono_palette_reloc_ptrs, default_subclass_finalize)
56 
57 static
58 ENUM_PTRS_WITH(pcl_mono_palette_enum_ptrs, gx_device *dev);
59 return 0; /* default case */
60 case 0:ENUM_RETURN(gx_device_enum_ptr(dev->parent));
61 case 1:ENUM_RETURN(gx_device_enum_ptr(dev->child));
62 ENUM_PTRS_END
RELOC_PTRS_WITH(pcl_mono_palette_reloc_ptrs,gx_device * dev)63 static RELOC_PTRS_WITH(pcl_mono_palette_reloc_ptrs, gx_device *dev)
64 {
65     dev->parent = gx_device_reloc_ptr(dev->parent, gcst);
66     dev->child = gx_device_reloc_ptr(dev->child, gcst);
67 }
68 RELOC_PTRS_END
69 
70 public_st_pcl_mono_palette_device();
71 
72 const
73 gx_device_mplt gs_pcl_mono_palette_device =
74 {
75     /*
76      * Define the device as 8-bit gray scale to avoid computing halftones.
77      */
78     std_device_dci_type_body(gx_device_mplt, 0, "PCL_Mono_Palette", &st_pcl_mono_palette_device,
79                         MAX_COORD, MAX_COORD,
80                         MAX_RESOLUTION, MAX_RESOLUTION,
81                         1, 8, 255, 0, 256, 1),
82     {default_subclass_open_device,
83      default_subclass_get_initial_matrix,
84      default_subclass_sync_output,			/* sync_output */
85      default_subclass_output_page,
86      default_subclass_close_device,
87      default_subclass_map_rgb_color,
88      default_subclass_map_color_rgb,
89      default_subclass_fill_rectangle,
90      default_subclass_tile_rectangle,			/* tile_rectangle */
91      default_subclass_copy_mono,
92      default_subclass_copy_color,
93      default_subclass_draw_line,			/* draw_line */
94      default_subclass_get_bits,			/* get_bits */
95      default_subclass_get_params,
96      default_subclass_put_params,
97      default_subclass_map_cmyk_color,
98      default_subclass_get_xfont_procs,			/* get_xfont_procs */
99      default_subclass_get_xfont_device,			/* get_xfont_device */
100      default_subclass_map_rgb_alpha_color,
101      default_subclass_get_page_device,
102      default_subclass_get_alpha_bits,			/* get_alpha_bits */
103      default_subclass_copy_alpha,
104      default_subclass_get_band,			/* get_band */
105      default_subclass_copy_rop,			/* copy_rop */
106      default_subclass_fill_path,
107      default_subclass_stroke_path,
108      default_subclass_fill_mask,
109      default_subclass_fill_trapezoid,
110      default_subclass_fill_parallelogram,
111      default_subclass_fill_triangle,
112      default_subclass_draw_thin_line,
113      default_subclass_begin_image,
114      default_subclass_image_data,			/* image_data */
115      default_subclass_end_image,			/* end_image */
116      default_subclass_strip_tile_rectangle,
117      default_subclass_strip_copy_rop,
118      default_subclass_get_clipping_box,			/* get_clipping_box */
119      default_subclass_begin_typed_image,
120      default_subclass_get_bits_rectangle,			/* get_bits_rectangle */
121      default_subclass_map_color_rgb_alpha,
122      default_subclass_create_compositor,
123      default_subclass_get_hardware_params,			/* get_hardware_params */
124      default_subclass_text_begin,
125      default_subclass_finish_copydevice,			/* finish_copydevice */
126      default_subclass_begin_transparency_group,			/* begin_transparency_group */
127      default_subclass_end_transparency_group,			/* end_transparency_group */
128      default_subclass_begin_transparency_mask,			/* begin_transparency_mask */
129      default_subclass_end_transparency_mask,			/* end_transparency_mask */
130      default_subclass_discard_transparency_layer,			/* discard_transparency_layer */
131      pcl_mono_palette_get_color_mapping_procs,			/* get_color_mapping_procs */
132      default_subclass_get_color_comp_index,			/* get_color_comp_index */
133      default_subclass_encode_color,			/* encode_color */
134      default_subclass_decode_color,			/* decode_color */
135      default_subclass_pattern_manage,			/* pattern_manage */
136      default_subclass_fill_rectangle_hl_color,			/* fill_rectangle_hl_color */
137      default_subclass_include_color_space,			/* include_color_space */
138      default_subclass_fill_linear_color_scanline,			/* fill_linear_color_scanline */
139      default_subclass_fill_linear_color_trapezoid,			/* fill_linear_color_trapezoid */
140      default_subclass_fill_linear_color_triangle,			/* fill_linear_color_triangle */
141      default_subclass_update_spot_equivalent_colors,			/* update_spot_equivalent_colors */
142      default_subclass_ret_devn_params,			/* ret_devn_params */
143      default_subclass_fillpage,		/* fillpage */
144      default_subclass_push_transparency_state,                      /* push_transparency_state */
145      default_subclass_pop_transparency_state,                      /* pop_transparency_state */
146      default_subclass_put_image,                      /* put_image */
147      default_subclass_dev_spec_op,                      /* dev_spec_op */
148      default_subclass_copy_planes,                      /* copy_planes */
149      default_subclass_get_profile,                      /* get_profile */
150      default_subclass_set_graphics_type_tag,                      /* set_graphics_type_tag */
151      default_subclass_strip_copy_rop2,
152      default_subclass_strip_tile_rect_devn,
153      default_subclass_copy_alpha_hl_color,
154      default_subclass_process_page,
155      default_subclass_transform_pixel_region,
156      default_subclass_fill_stroke_path,
157     }
158 };
159 
160 #undef MAX_COORD
161 #undef MAX_RESOLUTION
162 
163 /* The justification for this device, these 3 procedures map colour values
164  * to gray values
165  */
166 static void
pcl_gray_cs_to_cm(gx_device * dev,frac gray,frac out[])167 pcl_gray_cs_to_cm(gx_device * dev, frac gray, frac out[])
168 {
169     pcl_mono_palette_subclass_data *psubclass_data;
170 
171     while(dev && dev->child) {
172         if (strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0)
173             break;
174         dev = dev->child;
175     };
176 
177     if (dev && dev->child) {
178         psubclass_data = dev->subclass_data;
179         /* just pass it along */
180         psubclass_data->device_cm_procs->map_gray(dev, gray, out);
181     } else
182         return;
183 }
184 
185 static void
pcl_rgb_cs_to_cm(gx_device * dev,const gs_gstate * pgs,frac r,frac g,frac b,frac out[])186 pcl_rgb_cs_to_cm(gx_device * dev, const gs_gstate * pgs, frac r, frac g,
187                  frac b, frac out[])
188 {
189     pcl_mono_palette_subclass_data *psubclass_data;
190     frac gray;
191 
192     while(dev && dev->child) {
193         if (strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0)
194             break;
195         dev = dev->child;
196     };
197 
198     if (dev && dev->child) {
199         psubclass_data = dev->subclass_data;
200         gray = color_rgb_to_gray(r, g, b, NULL);
201 
202         psubclass_data->device_cm_procs->map_rgb(dev, pgs, gray, gray, gray, out);
203     } else
204         return;
205 }
206 
207 static void
pcl_cmyk_cs_to_cm(gx_device * dev,frac c,frac m,frac y,frac k,frac out[])208 pcl_cmyk_cs_to_cm(gx_device * dev, frac c, frac m, frac y, frac k, frac out[])
209 {
210     pcl_mono_palette_subclass_data *psubclass_data;
211     frac gray;
212 
213     while(dev && dev->child) {
214         if (strncmp(dev->dname, "PCL_Mono_Palette", 16) == 0)
215             break;
216         dev = dev->child;
217     };
218 
219     if (dev && dev->child) {
220         psubclass_data = dev->subclass_data;
221         gray = color_cmyk_to_gray(c, m, y, k, NULL);
222 
223         psubclass_data->device_cm_procs->map_cmyk(dev, gray, gray, gray, gray, out);
224     } else
225         return;
226 }
227 
pcl_mono_palette_get_color_mapping_procs(const gx_device * dev)228 const gx_cm_color_map_procs *pcl_mono_palette_get_color_mapping_procs(const gx_device *dev)
229 {
230     pcl_mono_palette_subclass_data *psubclass_data = dev->subclass_data;
231 
232     if (psubclass_data->device_cm_procs == 0L) {
233         psubclass_data->pcl_mono_procs.map_gray = pcl_gray_cs_to_cm;
234         psubclass_data->pcl_mono_procs.map_rgb = pcl_rgb_cs_to_cm;
235         psubclass_data->pcl_mono_procs.map_cmyk = pcl_cmyk_cs_to_cm;
236         psubclass_data->device_cm_procs = (gx_cm_color_map_procs *)dev_proc(dev->child, get_color_mapping_procs) (dev->child);
237     }
238     return &psubclass_data->pcl_mono_procs;
239 }
240