xref: /plan9/sys/src/cmd/gs/src/gdevdgbr.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gdevdgbr.c,v 1.14 2005/09/04 05:44:43 dan Exp $ */
18 /* Default implementation of device get_bits[_rectangle] */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gserrors.h"
22 #include "gxdevice.h"
23 #include "gxdevmem.h"
24 #include "gxgetbit.h"
25 #include "gxlum.h"
26 #include "gdevmem.h"
27 
28 int
gx_no_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)29 gx_no_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
30 {
31     return_error(gs_error_unknownerror);
32 }
33 int
gx_default_get_bits(gx_device * dev,int y,byte * data,byte ** actual_data)34 gx_default_get_bits(gx_device * dev, int y, byte * data, byte ** actual_data)
35 {	/*
36 	 * Hand off to get_bits_rectangle, being careful to avoid a
37 	 * possible recursion loop.
38 	 */
39     dev_proc_get_bits((*save_get_bits)) = dev_proc(dev, get_bits);
40     gs_int_rect rect;
41     gs_get_bits_params_t params;
42     int code;
43 
44     rect.p.x = 0, rect.p.y = y;
45     rect.q.x = dev->width, rect.q.y = y + 1;
46     params.options =
47 	(actual_data ? GB_RETURN_POINTER : 0) | GB_RETURN_COPY |
48 	(GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_RASTER_STANDARD |
49     /* No depth specified, we always use native colors. */
50 	 GB_PACKING_CHUNKY | GB_COLORS_NATIVE | GB_ALPHA_NONE);
51     params.x_offset = 0;
52     params.raster = bitmap_raster(dev->width * dev->color_info.depth);
53     params.data[0] = data;
54     set_dev_proc(dev, get_bits, gx_no_get_bits);
55     code = (*dev_proc(dev, get_bits_rectangle))
56 	(dev, &rect, &params, NULL);
57     if (actual_data)
58 	*actual_data = params.data[0];
59     set_dev_proc(dev, get_bits, save_get_bits);
60     return code;
61 }
62 
63 /*
64  * Determine whether we can satisfy a request by simply using the stored
65  * representation.  dev is used only for color_info.{num_components, depth}.
66  */
67 private bool
requested_includes_stored(const gx_device * dev,const gs_get_bits_params_t * requested,const gs_get_bits_params_t * stored)68 requested_includes_stored(const gx_device *dev,
69 			  const gs_get_bits_params_t *requested,
70 			  const gs_get_bits_params_t *stored)
71 {
72     gs_get_bits_options_t both = requested->options & stored->options;
73 
74     if (!(both & GB_PACKING_ALL))
75 	return false;
76     if (stored->options & GB_SELECT_PLANES) {
77 	/*
78 	 * The device only provides a subset of the planes.
79 	 * Make sure it provides all the requested ones.
80 	 */
81 	int i;
82 	int n = (stored->options & GB_PACKING_BIT_PLANAR ?
83 		 dev->color_info.depth : dev->color_info.num_components);
84 
85 	if (!(requested->options & GB_SELECT_PLANES) ||
86 	    !(both & (GB_PACKING_PLANAR || GB_PACKING_BIT_PLANAR))
87 	    )
88 	    return false;
89 	for (i = 0; i < n; ++i)
90 	    if (requested->data[i] && !stored->data[i])
91 		return false;
92     }
93     if (both & GB_COLORS_NATIVE)
94 	return true;
95     if (both & GB_COLORS_STANDARD_ALL) {
96 	if ((both & GB_ALPHA_ALL) && (both & GB_DEPTH_ALL))
97 	    return true;
98     }
99     return false;
100 }
101 
102 /*
103  * Try to implement get_bits_rectangle by returning a pointer.
104  * Note that dev is used only for computing the default raster
105  * and for color_info.depth.
106  * This routine does not check x or h for validity.
107  */
108 int
gx_get_bits_return_pointer(gx_device * dev,int x,int h,gs_get_bits_params_t * params,const gs_get_bits_params_t * stored,byte * stored_base)109 gx_get_bits_return_pointer(gx_device * dev, int x, int h,
110 			   gs_get_bits_params_t *params,
111 			   const gs_get_bits_params_t *stored,
112 			   byte * stored_base)
113 {
114     gs_get_bits_options_t options = params->options;
115     gs_get_bits_options_t both = options & stored->options;
116 
117     if (!(options & GB_RETURN_POINTER) ||
118 	!requested_includes_stored(dev, params, stored)
119 	)
120 	return -1;
121     /*
122      * See whether we can return the bits in place.  Note that even if
123      * OFFSET_ANY isn't set, x_offset and x don't have to be equal: their
124      * bit offsets only have to match modulo align_bitmap_mod * 8 (to
125      * preserve alignment) if ALIGN_ANY isn't set, or mod 8 (since
126      * byte alignment is always required) if ALIGN_ANY is set.
127      */
128     {
129 	int depth = dev->color_info.depth;
130 	/*
131 	 * For PLANAR devices, we assume that each plane consists of
132 	 * depth/num_components bits.  This is wrong in general, but if
133 	 * the device wants something else, it should implement
134 	 * get_bits_rectangle itself.
135 	 */
136 	uint dev_raster =
137 	    (both & GB_PACKING_CHUNKY ?
138 	       gx_device_raster(dev, true) :
139 	     both & GB_PACKING_PLANAR ?
140 	       bitmap_raster(dev->color_info.depth /
141 			     dev->color_info.num_components * dev->width) :
142 	     both & GB_PACKING_BIT_PLANAR ?
143 	       bitmap_raster(dev->width) :
144 	     0 /* not possible */);
145 	uint raster =
146 	    (options & (GB_RASTER_STANDARD | GB_RASTER_ANY) ? dev_raster :
147 	     params->raster);
148 	byte *base;
149 
150 	if (h <= 1 || raster == dev_raster) {
151 	    int x_offset =
152 		(options & GB_OFFSET_ANY ? x :
153 		 options & GB_OFFSET_0 ? 0 : params->x_offset);
154 
155 	    if (x_offset == x) {
156 		base = stored_base;
157 		params->x_offset = x;
158 	    } else {
159 		uint align_mod =
160 		    (options & GB_ALIGN_ANY ? 8 : align_bitmap_mod * 8);
161 		int bit_offset = x - x_offset;
162 		int bytes;
163 
164 		if (bit_offset & (align_mod - 1))
165 		    return -1;	/* can't align */
166 		if (depth & (depth - 1)) {
167 		    /* step = lcm(depth, align_mod) */
168 		    int step = depth / igcd(depth, align_mod) * align_mod;
169 
170 		    bytes = bit_offset / step * step;
171 		} else {
172 		    /* Use a faster algorithm if depth is a power of 2. */
173 		    bytes = bit_offset & (-depth & -(int)align_mod);
174 		}
175 		base = stored_base + arith_rshift(bytes, 3);
176 		params->x_offset = (bit_offset - bytes) / depth;
177 	    }
178 	    params->options =
179 		GB_ALIGN_STANDARD | GB_RETURN_POINTER | GB_RASTER_STANDARD |
180 		(stored->options & ~GB_PACKING_ALL) /*see below for PACKING*/ |
181 		(params->x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED);
182 	    if (both & GB_PACKING_CHUNKY) {
183 		params->options |= GB_PACKING_CHUNKY;
184 		params->data[0] = base;
185 	    } else {
186 		int n =
187 		    (stored->options & GB_PACKING_BIT_PLANAR ?
188 		       (params->options |= GB_PACKING_BIT_PLANAR,
189 			dev->color_info.depth) :
190 		       (params->options |= GB_PACKING_PLANAR,
191 			dev->color_info.num_components));
192 		int i;
193 
194 		for (i = 0; i < n; ++i)
195 		    if (!(both & GB_SELECT_PLANES) || stored->data[i] != 0) {
196 			params->data[i] = base;
197 			base += dev_raster * dev->height;
198 		    }
199 	    }
200 	    return 0;
201 	}
202     }
203     return -1;
204 }
205 
206 /*
207  * Implement gx_get_bits_copy (see below) for the case of converting
208  * 4-bit CMYK to 24-bit RGB with standard mapping, used heavily by PCL.
209  */
210 private void
gx_get_bits_copy_cmyk_1bit(byte * dest_line,uint dest_raster,const byte * src_line,uint src_raster,int src_bit,int w,int h)211 gx_get_bits_copy_cmyk_1bit(byte *dest_line, uint dest_raster,
212 			   const byte *src_line, uint src_raster,
213 			   int src_bit, int w, int h)
214 {
215     for (; h > 0; dest_line += dest_raster, src_line += src_raster, --h) {
216 	const byte *src = src_line;
217 	byte *dest = dest_line;
218 	bool hi = (src_bit & 4) != 0;  /* last nibble processed was hi */
219 	int i;
220 
221 	for (i = w; i > 0; dest += 3, --i) {
222 	    uint pixel =
223 		((hi = !hi)? *src >> 4 : *src++ & 0xf);
224 
225 	    if (pixel & 1)
226 		dest[0] = dest[1] = dest[2] = 0;
227 	    else {
228 		dest[0] = (byte)((pixel >> 3) - 1);
229 		dest[1] = (byte)(((pixel >> 2) & 1) - 1);
230 		dest[2] = (byte)(((pixel >> 1) & 1) - 1);
231 	    }
232 	}
233     }
234 }
235 
236 /*
237  * Convert pixels between representations, primarily for get_bits_rectangle.
238  * stored indicates how the data are actually stored, and includes:
239  *      - one option from the GB_PACKING group;
240  *      - if h > 1, one option from the GB_RASTER group;
241  *      - optionally (and normally), GB_COLORS_NATIVE;
242  *      - optionally, one option each from the GB_COLORS_STANDARD, GB_DEPTH,
243  *      and GB_ALPHA groups.
244  * Note that dev is used only for color mapping.  This routine assumes that
245  * the stored data are aligned.
246  *
247  * Note: this routine does not check x, w, h for validity.
248  *
249  * The code for converting between standard and native colors has been
250  * factored out into single-use procedures strictly for readability.
251  * A good optimizing compiler would compile them in-line.
252  */
253 private int
254     gx_get_bits_std_to_native(gx_device * dev, int x, int w, int h,
255 				  gs_get_bits_params_t * params,
256 			      const gs_get_bits_params_t *stored,
257 			      const byte * src_base, uint dev_raster,
258 			      int x_offset, uint raster),
259     gx_get_bits_native_to_std(gx_device * dev, int x, int w, int h,
260 			      gs_get_bits_params_t * params,
261 			      const gs_get_bits_params_t *stored,
262 			      const byte * src_base, uint dev_raster,
263 			      int x_offset, uint raster, uint std_raster);
264 int
gx_get_bits_copy(gx_device * dev,int x,int w,int h,gs_get_bits_params_t * params,const gs_get_bits_params_t * stored,const byte * src_base,uint dev_raster)265 gx_get_bits_copy(gx_device * dev, int x, int w, int h,
266 		 gs_get_bits_params_t * params,
267 		 const gs_get_bits_params_t *stored,
268 		 const byte * src_base, uint dev_raster)
269 {
270     gs_get_bits_options_t options = params->options;
271     gs_get_bits_options_t stored_options = stored->options;
272     int x_offset = (options & GB_OFFSET_0 ? 0 : params->x_offset);
273     int depth = dev->color_info.depth;
274     int bit_x = x * depth;
275     const byte *src = src_base;
276     /*
277      * If the stored representation matches a requested representation,
278      * we can copy the data without any transformations.
279      */
280     bool direct_copy = requested_includes_stored(dev, params, stored);
281     int code = 0;
282 
283     /*
284      * The request must include either GB_PACKING_CHUNKY or
285      * GB_PACKING_PLANAR + GB_SELECT_PLANES, GB_RETURN_COPY,
286      * and an offset and raster specification.  In the planar case,
287      * the request must include GB_ALIGN_STANDARD, the stored
288      * representation must include GB_PACKING_CHUNKY, and both must
289      * include GB_COLORS_NATIVE.
290      */
291     if ((~options & GB_RETURN_COPY) ||
292 	!(options & (GB_OFFSET_0 | GB_OFFSET_SPECIFIED)) ||
293 	!(options & (GB_RASTER_STANDARD | GB_RASTER_SPECIFIED))
294 	)
295 	return_error(gs_error_rangecheck);
296     if (options & GB_PACKING_CHUNKY) {
297 	byte *data = params->data[0];
298 	int end_bit = (x_offset + w) * depth;
299 	uint std_raster =
300 	    (options & GB_ALIGN_STANDARD ? bitmap_raster(end_bit) :
301 	     (end_bit + 7) >> 3);
302 	uint raster =
303 	    (options & GB_RASTER_STANDARD ? std_raster : params->raster);
304 	int dest_bit_x = x_offset * depth;
305 	int skew = bit_x - dest_bit_x;
306 
307 	/*
308 	 * If the bit positions line up, use bytes_copy_rectangle.
309 	 * Since bytes_copy_rectangle doesn't require alignment,
310 	 * the bit positions only have to match within a byte,
311 	 * not within align_bitmap_mod bytes.
312 	 */
313 	if (!(skew & 7) && direct_copy) {
314 	    int bit_w = w * depth;
315 
316 	    bytes_copy_rectangle(data + (dest_bit_x >> 3), raster,
317 				 src + (bit_x >> 3), dev_raster,
318 			      ((bit_x + bit_w + 7) >> 3) - (bit_x >> 3), h);
319 	} else if (direct_copy) {
320 	    /*
321 	     * Use the logic already in mem_mono_copy_mono to copy the
322 	     * bits to the destination.  We do this one line at a time,
323 	     * to avoid having to allocate a line pointer table.
324 	     */
325 	    gx_device_memory tdev;
326 	    byte *line_ptr = data;
327 	    int bit_w = w * depth;
328 
329 	    tdev.line_ptrs = &tdev.base;
330 	    for (; h > 0; line_ptr += raster, src += dev_raster, --h) {
331 		/* Make sure the destination is aligned. */
332 		int align = ALIGNMENT_MOD(line_ptr, align_bitmap_mod);
333 
334 		tdev.base = line_ptr - align;
335 		/* set up parameters required by copy_mono's fit_copy */
336 		tdev.width = dest_bit_x + (align << 3) + bit_w;
337 		tdev.height = 1;
338 		(*dev_proc(&mem_mono_device, copy_mono))
339 		    ((gx_device *) & tdev, src, bit_x, dev_raster, gx_no_bitmap_id,
340 		     dest_bit_x + (align << 3), 0, bit_w, 1,
341 		     (gx_color_index) 0, (gx_color_index) 1);
342 	    }
343 	} else if (options & ~stored_options & GB_COLORS_NATIVE) {
344 	    /* Convert standard colors to native. */
345 	    code = gx_get_bits_std_to_native(dev, x, w, h, params, stored,
346 					     src_base, dev_raster,
347 					     x_offset, raster);
348 	    options = params->options;
349 	} else {
350 	    /* Convert native colors to standard. */
351 	    code = gx_get_bits_native_to_std(dev, x, w, h, params, stored,
352 					     src_base, dev_raster,
353 					     x_offset, raster, std_raster);
354 	    options = params->options;
355 	}
356 	params->options =
357 	    (options & (GB_COLORS_ALL | GB_ALPHA_ALL)) | GB_PACKING_CHUNKY |
358 	    (options & GB_COLORS_NATIVE ? 0 : options & GB_DEPTH_ALL) |
359 	    (options & GB_ALIGN_STANDARD ? GB_ALIGN_STANDARD : GB_ALIGN_ANY) |
360 	    GB_RETURN_COPY |
361 	    (x_offset == 0 ? GB_OFFSET_0 : GB_OFFSET_SPECIFIED) |
362 	    (raster == std_raster ? GB_RASTER_STANDARD : GB_RASTER_SPECIFIED);
363     } else if (!(~options &
364 		 (GB_PACKING_PLANAR | GB_SELECT_PLANES | GB_ALIGN_STANDARD)) &&
365 	       (stored_options & GB_PACKING_CHUNKY) &&
366 	       ((options & stored_options) & GB_COLORS_NATIVE)
367 	       ) {
368 	int num_planes = dev->color_info.num_components;
369 	int dest_depth = depth / num_planes;
370 	bits_plane_t source, dest;
371 	int plane = -1;
372 	int i;
373 
374 	/* Make sure only one plane is being requested. */
375 	for (i = 0; i < num_planes; ++i)
376 	    if (params->data[i] != 0) {
377 		if (plane >= 0)
378 		    return_error(gs_error_rangecheck); /* > 1 plane */
379 		plane = i;
380 	    }
381 	source.data.read = src_base;
382 	source.raster = dev_raster;
383 	source.depth = depth;
384 	source.x = x;
385 	dest.data.write = params->data[plane];
386 	dest.raster =
387 	    (options & GB_RASTER_STANDARD ?
388 	     bitmap_raster((x_offset + w) * dest_depth) : params->raster);
389 	dest.depth = dest_depth;
390 	dest.x = x_offset;
391 	return bits_extract_plane(&dest, &source,
392 				  (num_planes - 1 - plane) * dest_depth,
393 				  w, h);
394     } else
395 	return_error(gs_error_rangecheck);
396     return code;
397 }
398 
399 /*
400  * Convert standard colors to native.  Note that the source
401  * may have depths other than 8 bits per component.
402  */
403 private int
gx_get_bits_std_to_native(gx_device * dev,int x,int w,int h,gs_get_bits_params_t * params,const gs_get_bits_params_t * stored,const byte * src_base,uint dev_raster,int x_offset,uint raster)404 gx_get_bits_std_to_native(gx_device * dev, int x, int w, int h,
405 			  gs_get_bits_params_t * params,
406 			  const gs_get_bits_params_t *stored,
407 			  const byte * src_base, uint dev_raster,
408 			  int x_offset, uint raster)
409 {
410     int depth = dev->color_info.depth;
411     int dest_bit_offset = x_offset * depth;
412     byte *dest_line = params->data[0] + (dest_bit_offset >> 3);
413     int ncolors =
414 	(stored->options & GB_COLORS_RGB ? 3 :
415 	 stored->options & GB_COLORS_CMYK ? 4 :
416 	 stored->options & GB_COLORS_GRAY ? 1 : -1);
417     int ncomp = ncolors +
418 	((stored->options & (GB_ALPHA_FIRST | GB_ALPHA_LAST)) != 0);
419     int src_depth = GB_OPTIONS_DEPTH(stored->options);
420     int src_bit_offset = x * src_depth * ncomp;
421     const byte *src_line = src_base + (src_bit_offset >> 3);
422     gx_color_value src_max = (1 << src_depth) - 1;
423 #define v2cv(value) ((ulong)(value) * gx_max_color_value / src_max)
424     gx_color_value alpha_default = src_max;
425 
426     params->options &= ~GB_COLORS_ALL | GB_COLORS_NATIVE;
427     for (; h > 0; dest_line += raster, src_line += dev_raster, --h) {
428 	int i;
429 
430 	sample_load_declare_setup(src, sbit, src_line,
431 				  src_bit_offset & 7, src_depth);
432 	sample_store_declare_setup(dest, dbit, dbyte, dest_line,
433 				   dest_bit_offset & 7, depth);
434 
435 #define v2frac(value) ((long)(value) * frac_1 / src_max)
436 
437         for (i = 0; i < w; ++i) {
438             int j;
439             frac sc[4], dc[GX_DEVICE_COLOR_MAX_COMPONENTS];
440             gx_color_value v[GX_DEVICE_COLOR_MAX_COMPONENTS], va = alpha_default;
441             gx_color_index pixel;
442             bool do_alpha = false;
443             const gx_cm_color_map_procs * map_procs;
444 
445             map_procs = dev_proc(dev, get_color_mapping_procs)(dev);
446 
447             /* Fetch the source data. */
448             if (stored->options & GB_ALPHA_FIRST) {
449                 sample_load_next16(va, src, sbit, src_depth);
450                 va = v2cv(va);
451                 do_alpha = true;
452             }
453             for (j = 0; j < ncolors; ++j) {
454                 gx_color_value vj;
455 
456                 sample_load_next16(vj, src, sbit, src_depth);
457                 sc[j] = v2frac(vj);
458             }
459             if (stored->options & GB_ALPHA_LAST) {
460                 sample_load_next16(va, src, sbit, src_depth);
461                 va = v2cv(va);
462                 do_alpha = true;
463             }
464 
465             /* Convert and store the pixel value. */
466             if (do_alpha) {
467                 for (j = 0; j < ncolors; j++)
468                     v[j] = frac2cv(sc[j]);
469                 if (ncolors == 1)
470                     v[2] = v[1] = v[0];
471                 pixel = dev_proc(dev, map_rgb_alpha_color)
472                     (dev, v[0], v[1], v[2], va);
473             } else {
474 
475                 switch (ncolors) {
476                 case 1:
477                     map_procs->map_gray(dev, sc[0], dc);
478                     break;
479                 case 3:
480                     map_procs->map_rgb(dev, 0, sc[0], sc[1], sc[2], dc);
481                     break;
482                 case 4:
483                     map_procs->map_cmyk(dev, sc[0], sc[1], sc[2], sc[3], dc);
484                     break;
485                 default:
486                     return_error(gs_error_rangecheck);
487                 }
488 
489                 for (j = 0; j < dev->color_info.num_components; j++)
490                     v[j] = frac2cv(dc[j]);
491 
492                 pixel = dev_proc(dev, encode_color)(dev, v);
493             }
494             sample_store_next_any(pixel, dest, dbit, depth, dbyte);
495         }
496 	sample_store_flush(dest, dbit, depth, dbyte);
497     }
498     return 0;
499 }
500 
501 /*
502  * Convert native colors to standard.  Only GB_DEPTH_8 is supported.
503  */
504 private int
gx_get_bits_native_to_std(gx_device * dev,int x,int w,int h,gs_get_bits_params_t * params,const gs_get_bits_params_t * stored,const byte * src_base,uint dev_raster,int x_offset,uint raster,uint std_raster)505 gx_get_bits_native_to_std(gx_device * dev, int x, int w, int h,
506 			  gs_get_bits_params_t * params,
507 			  const gs_get_bits_params_t *stored,
508 			  const byte * src_base, uint dev_raster,
509 			  int x_offset, uint raster, uint std_raster)
510 {
511     int depth = dev->color_info.depth;
512     int src_bit_offset = x * depth;
513     const byte *src_line = src_base + (src_bit_offset >> 3);
514     gs_get_bits_options_t options = params->options;
515     int ncomp =
516 	(options & (GB_ALPHA_FIRST | GB_ALPHA_LAST) ? 4 : 3);
517     byte *dest_line = params->data[0] + x_offset * ncomp;
518     byte *mapped[16];
519     int dest_bytes;
520     int i;
521 
522     if (!(options & GB_DEPTH_8)) {
523 	/*
524 	 * We don't support general depths yet, or conversion between
525 	 * different formats.  Punt.
526 	 */
527 	return_error(gs_error_rangecheck);
528     }
529 
530     /* Pick the representation that's most likely to be useful. */
531     if (options & GB_COLORS_RGB)
532 	params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_RGB,
533 	    dest_bytes = 3;
534     else if (options & GB_COLORS_CMYK)
535 	params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_CMYK,
536 	    dest_bytes = 4;
537     else if (options & GB_COLORS_GRAY)
538 	params->options = options &= ~GB_COLORS_STANDARD_ALL | GB_COLORS_GRAY,
539 	    dest_bytes = 1;
540     else
541 	return_error(gs_error_rangecheck);
542     /* Recompute the destination raster based on the color space. */
543     if (options & GB_RASTER_STANDARD) {
544 	uint end_byte = (x_offset + w) * dest_bytes;
545 
546 	raster = std_raster =
547 	    (options & GB_ALIGN_STANDARD ?
548 	     bitmap_raster(end_byte << 3) : end_byte);
549     }
550     /* Check for the one special case we care about. */
551     if (((options & (GB_COLORS_RGB | GB_ALPHA_FIRST | GB_ALPHA_LAST))
552 	   == GB_COLORS_RGB) &&
553 	dev_proc(dev, map_color_rgb) == cmyk_1bit_map_color_rgb) {
554 	gx_get_bits_copy_cmyk_1bit(dest_line, raster,
555 				   src_line, dev_raster,
556 				   src_bit_offset & 7, w, h);
557 	return 0;
558     }
559     if (options & (GB_ALPHA_FIRST | GB_ALPHA_LAST))
560 	++dest_bytes;
561     /* Clear the color translation cache. */
562     for (i = (depth > 4 ? 16 : 1 << depth); --i >= 0; )
563 	mapped[i] = 0;
564     for (; h > 0; dest_line += raster, src_line += dev_raster, --h) {
565 	sample_load_declare_setup(src, bit, src_line,
566 				  src_bit_offset & 7, depth);
567 	byte *dest = dest_line;
568 
569 	for (i = 0; i < w; ++i) {
570 	    gx_color_index pixel = 0;
571 	    gx_color_value rgba[4];
572 
573 	    sample_load_next_any(pixel, src, bit, depth);
574 	    if (pixel < 16) {
575 		if (mapped[pixel]) {
576 		    /* Use the value from the cache. */
577 		    memcpy(dest, mapped[pixel], dest_bytes);
578 		    dest += dest_bytes;
579 		    continue;
580 		}
581 		mapped[pixel] = dest;
582 	    }
583 	    (*dev_proc(dev, map_color_rgb_alpha)) (dev, pixel, rgba);
584 	    if (options & GB_ALPHA_FIRST)
585 		*dest++ = gx_color_value_to_byte(rgba[3]);
586 	    /* Convert to the requested color space. */
587 	    if (options & GB_COLORS_RGB) {
588 		dest[0] = gx_color_value_to_byte(rgba[0]);
589 		dest[1] = gx_color_value_to_byte(rgba[1]);
590 		dest[2] = gx_color_value_to_byte(rgba[2]);
591 		dest += 3;
592 	    } else if (options & GB_COLORS_CMYK) {
593 		/* Use the standard RGB to CMYK algorithm, */
594 		/* with maximum black generation and undercolor removal. */
595 		gx_color_value white = max(rgba[0], max(rgba[1], rgba[2]));
596 
597 		dest[0] = gx_color_value_to_byte(white - rgba[0]);
598 		dest[1] = gx_color_value_to_byte(white - rgba[1]);
599 		dest[2] = gx_color_value_to_byte(white - rgba[2]);
600 		dest[3] = gx_color_value_to_byte(gx_max_color_value - white);
601 		dest += 4;
602 	    } else {	/* GB_COLORS_GRAY */
603 		/* Use the standard RGB to Gray algorithm. */
604 		*dest++ = gx_color_value_to_byte(
605 				((rgba[0] * (ulong) lum_red_weight) +
606 				 (rgba[1] * (ulong) lum_green_weight) +
607 				 (rgba[2] * (ulong) lum_blue_weight) +
608 				   (lum_all_weights / 2))
609 				/ lum_all_weights);
610 	    }
611 	    if (options & GB_ALPHA_LAST)
612 		*dest++ = gx_color_value_to_byte(rgba[3]);
613 	}
614     }
615     return 0;
616 }
617 
618 /* ------ Default implementations of get_bits_rectangle ------ */
619 
620 int
gx_no_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)621 gx_no_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
622 		       gs_get_bits_params_t * params, gs_int_rect ** unread)
623 {
624     return_error(gs_error_unknownerror);
625 }
626 
627 int
gx_default_get_bits_rectangle(gx_device * dev,const gs_int_rect * prect,gs_get_bits_params_t * params,gs_int_rect ** unread)628 gx_default_get_bits_rectangle(gx_device * dev, const gs_int_rect * prect,
629 		       gs_get_bits_params_t * params, gs_int_rect ** unread)
630 {
631     dev_proc_get_bits_rectangle((*save_get_bits_rectangle)) =
632 	dev_proc(dev, get_bits_rectangle);
633     int depth = dev->color_info.depth;
634     uint min_raster = (dev->width * depth + 7) >> 3;
635     gs_get_bits_options_t options = params->options;
636     int code;
637 
638     /* Avoid a recursion loop. */
639     set_dev_proc(dev, get_bits_rectangle, gx_no_get_bits_rectangle);
640     /*
641      * If the parameters are right, try to call get_bits directly.  Note
642      * that this may fail if a device only implements get_bits_rectangle
643      * (not get_bits) for a limited set of options.  Note also that this
644      * must handle the case of the recursive call from within
645      * get_bits_rectangle (see below): because of this, and only because
646      * of this, it must handle partial scan lines.
647      */
648     if (prect->q.y == prect->p.y + 1 &&
649 	!(~options &
650 	  (GB_RETURN_COPY | GB_PACKING_CHUNKY | GB_COLORS_NATIVE)) &&
651 	(options & (GB_ALIGN_STANDARD | GB_ALIGN_ANY)) &&
652 	((options & (GB_OFFSET_0 | GB_OFFSET_ANY)) ||
653 	 ((options & GB_OFFSET_SPECIFIED) && params->x_offset == 0)) &&
654 	((options & (GB_RASTER_STANDARD | GB_RASTER_ANY)) ||
655 	 ((options & GB_RASTER_SPECIFIED) &&
656 	  params->raster >= min_raster)) &&
657 	unread == NULL
658 	) {
659 	byte *data = params->data[0];
660 	byte *row = data;
661 
662 	if (!(prect->p.x == 0 && prect->q.x == dev->width)) {
663 	    /* Allocate an intermediate row buffer. */
664 	    row = gs_alloc_bytes(dev->memory, min_raster,
665 				 "gx_default_get_bits_rectangle");
666 
667 	    if (row == 0) {
668 		code = gs_note_error(gs_error_VMerror);
669 		goto ret;
670 	    }
671 	}
672 	code = (*dev_proc(dev, get_bits)) (dev, prect->p.y, row,
673 		(params->options & GB_RETURN_POINTER) ? &params->data[0]
674 						      : NULL );
675 	if (code >= 0) {
676 	    if (row != data) {
677 		if (prect->p.x == 0 && params->data[0] != row
678 		    && params->options & GB_RETURN_POINTER) {
679 		    /*
680 		     * get_bits returned an appropriate pointer: we can
681 		     * avoid doing any copying.
682 		     */
683 		    DO_NOTHING;
684 		} else {
685 		    /* Copy the partial row into the supplied buffer. */
686 		    int width_bits = (prect->q.x - prect->p.x) * depth;
687 		    gx_device_memory tdev;
688 
689 		    tdev.width = width_bits;
690 		    tdev.height = 1;
691 		    tdev.line_ptrs = &tdev.base;
692 		    tdev.base = data;
693 		    code = (*dev_proc(&mem_mono_device, copy_mono))
694 			((gx_device *) & tdev, row, prect->p.x * depth,
695 			 min_raster, gx_no_bitmap_id, 0, 0, width_bits, 1,
696 			 (gx_color_index) 0, (gx_color_index) 1);
697 		    params->data[0] = data;
698 		}
699 		gs_free_object(dev->memory, row,
700 			       "gx_default_get_bits_rectangle");
701 	    }
702 	    params->options =
703 		GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_PACKING_CHUNKY |
704 		GB_ALPHA_NONE | GB_COLORS_NATIVE | GB_RASTER_STANDARD |
705 		(params->data[0] == data ? GB_RETURN_COPY : GB_RETURN_POINTER);
706 	    goto ret;
707 	}
708     } {
709 	/* Do the transfer row-by-row using a buffer. */
710 	int x = prect->p.x, w = prect->q.x - x;
711 	int bits_per_pixel = depth;
712 	byte *row;
713 
714 	if (options & GB_COLORS_STANDARD_ALL) {
715 	    /*
716 	     * Make sure the row buffer can hold the standard color
717 	     * representation, in case the device decides to use it.
718 	     */
719 	    int bpc = GB_OPTIONS_MAX_DEPTH(options);
720 	    int nc =
721 	    (options & GB_COLORS_CMYK ? 4 :
722 	     options & GB_COLORS_RGB ? 3 : 1) +
723 	    (options & (GB_ALPHA_ALL - GB_ALPHA_NONE) ? 1 : 0);
724 	    int bpp = bpc * nc;
725 
726 	    if (bpp > bits_per_pixel)
727 		bits_per_pixel = bpp;
728 	}
729 	row = gs_alloc_bytes(dev->memory, (bits_per_pixel * w + 7) >> 3,
730 			     "gx_default_get_bits_rectangle");
731 	if (row == 0) {
732 	    code = gs_note_error(gs_error_VMerror);
733 	} else {
734 	    uint dev_raster = gx_device_raster(dev, true);
735 	    uint raster =
736 	    (options & GB_RASTER_SPECIFIED ? params->raster :
737 	     options & GB_ALIGN_STANDARD ? bitmap_raster(depth * w) :
738 	     (depth * w + 7) >> 3);
739 	    gs_int_rect rect;
740 	    gs_get_bits_params_t copy_params;
741 	    gs_get_bits_options_t copy_options =
742 		(GB_ALIGN_STANDARD | GB_ALIGN_ANY) |
743 		(GB_RETURN_COPY | GB_RETURN_POINTER) |
744 		(GB_OFFSET_0 | GB_OFFSET_ANY) |
745 		(GB_RASTER_STANDARD | GB_RASTER_ANY) | GB_PACKING_CHUNKY |
746 		GB_COLORS_NATIVE | (options & (GB_DEPTH_ALL | GB_COLORS_ALL)) |
747 		GB_ALPHA_ALL;
748 	    byte *dest = params->data[0];
749 	    int y;
750 
751 	    rect.p.x = x, rect.q.x = x + w;
752 	    code = 0;
753 	    for (y = prect->p.y; y < prect->q.y; ++y) {
754 		rect.p.y = y, rect.q.y = y + 1;
755 		copy_params.options = copy_options;
756 		copy_params.data[0] = row;
757 		code = (*save_get_bits_rectangle)
758 		    (dev, &rect, &copy_params, NULL);
759 		if (code < 0)
760 		    break;
761 		if (copy_params.options & GB_OFFSET_0)
762 		    copy_params.x_offset = 0;
763 		params->data[0] = dest + (y - prect->p.y) * raster;
764 		code = gx_get_bits_copy(dev, copy_params.x_offset, w, 1,
765 					params, &copy_params,
766 					copy_params.data[0], dev_raster);
767 		if (code < 0)
768 		    break;
769 	    }
770 	    gs_free_object(dev->memory, row, "gx_default_get_bits_rectangle");
771 	    params->data[0] = dest;
772 	}
773     }
774   ret:set_dev_proc(dev, get_bits_rectangle, save_get_bits_rectangle);
775     return (code < 0 ? code : 0);
776 }
777 
778 
779