Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
 
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
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
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
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
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
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
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