1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises, 2001 Artifex Software. All rights reserved.
3 This software is provided AS-IS with no warranty, either express or
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.
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.
17 /*$Id: gdevm40.c,v 1.3 2005/06/20 08:59:23 igor Exp $ */
18 /* 40-bit-per-pixel "memory" (stored bitmap) device */
22 #include "gxdevmem.h" /* semi-public definitions */
23 #include "gdevmem.h" /* private definitions */
25 /* Define debugging statistics. */
27 struct stats_mem40_s {
29 fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
33 static int prev_count = 0;
34 static gx_color_index prev_colors[256];
35 # define INCR(v) (++(stats_mem40.v))
37 # define INCR(v) DO_NOTHING
41 /* ================ Standard (byte-oriented) device ================ */
48 declare_mem_procs(mem_true40_copy_mono, mem_true40_copy_color, mem_true40_fill_rectangle);
50 /* The device descriptor. */
51 const gx_device_memory mem_true40_device =
52 mem_full_alpha_device("image40", 40, 0, mem_open,
53 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
54 mem_true40_copy_mono, mem_true40_copy_color, mem_true40_fill_rectangle,
55 gx_default_map_cmyk_color, gx_default_copy_alpha,
56 gx_default_strip_tile_rectangle, mem_default_strip_copy_rop,
57 mem_get_bits_rectangle);
59 /* Convert x coordinate to byte offset in scan line. */
61 #define x_to_byte(x) ((x) * PIXEL_SIZE)
63 /* Unpack a color into its bytes. */
64 #define declare_unpack_color(a, b, c, d, e, color)\
65 byte a = (byte)((uint64_t)color >> 32);\
66 byte b = (byte)((uint)color >> 24);\
67 byte c = (byte)((uint)color >> 16);\
68 byte d = (byte)((uint)color >> 8);\
70 /* Put a 40-bit color into the bitmap. */
71 #define put5(ptr, a, b, c, d, e)\
72 (ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e
73 /* Put 4 bytes of color into the bitmap. */
74 #define putw(ptr, wxyz)\
75 *(bits32 *)(ptr) = (wxyz)
76 /* Load the 5-word 40-bit-color cache. */
77 /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */
78 #if arch_is_big_endian
79 # define set_color40_cache(color, a, b, c, d, e)\
80 mdev->color40.abcd = abcd = (color) >> 8, \
81 mdev->color40.bcde = bcde = (abcd << 8) | (e),\
82 mdev->color40.cdea = cdea = (bcde << 8) | (a),\
83 mdev->color40.deab = deab = (cdea << 8) | (b),\
84 mdev->color40.eabc = eabc = (deab << 8) | (c),\
85 mdev->color40.abcde = (color)
87 # define set_color40_cache(color, a, b, c, d, e)\
88 mdev->color40.abcd = abcd =\
89 ((bits32)(d) << 24) | ((bits32)(c) << 16) |\
90 ((bits16)(b) << 8) | (a),\
91 mdev->color40.eabc = eabc = (abcd << 8) | (e),\
92 mdev->color40.deab = deab = (eabc << 8) | (d),\
93 mdev->color40.cdea = cdea = (deab << 8) | (c),\
94 mdev->color40.bcde = bcde = (cdea << 8) | (b),\
95 mdev->color40.abcde = (color)
98 /* Fill a rectangle with a color. */
100 mem_true40_fill_rectangle(gx_device * dev,
101 int x, int y, int w, int h, gx_color_index color)
103 gx_device_memory * const mdev = (gx_device_memory *)dev;
104 declare_unpack_color(a, b, c, d, e, color);
105 declare_scan_ptr(dest);
108 * In order to avoid testing w > 0 and h > 0 twice, we defer
109 * executing setup_rect, and use fit_fill_xywh instead of
112 fit_fill_xywh(dev, x, y, w, h);
115 stats_mem40.ftotal += w;
122 if (a == b && b == c && c == d && d == e) {
123 int bcnt = w * PIXEL_SIZE;
125 INCR(fgray[min(w, 100)]);
127 memset(dest, a, bcnt);
128 inc_ptr(dest, draster);
131 int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */
132 bits32 abcd, bcde, cdea, deab, eabc;
134 if (mdev->color40.abcde == color) {
135 abcd = mdev->color40.abcd;
136 bcde = mdev->color40.bcde;
137 cdea = mdev->color40.cdea;
138 deab = mdev->color40.deab;
139 eabc = mdev->color40.eabc;
142 set_color40_cache(color, a, b, c, d, e);
147 for (ci = 0; ci < prev_count; ++ci)
148 if (prev_colors[ci] == color)
151 if (ci == prev_count) {
152 if (ci < countof(prev_colors))
158 memmove(&prev_colors[1], &prev_colors[0],
159 ci * sizeof(prev_colors[0]));
160 prev_colors[0] = color;
164 INCR(fcolor[min(w, 100)]);
166 register byte *pptr = dest;
172 putw(pptr + 1, bcde);
178 putw(pptr + 2, cdea);
179 putw(pptr + 6, bcde);
180 pptr += 2 * PIXEL_SIZE;
186 putw(pptr + 3, deab);
187 putw(pptr + 7, cdea);
188 putw(pptr + 11, bcde);
189 pptr += 3 * PIXEL_SIZE;
196 putw(pptr + 4, eabc);
197 putw(pptr + 8, deab);
198 putw(pptr + 12, cdea);
199 putw(pptr + 16, bcde);
200 pptr += 4 * PIXEL_SIZE;
210 putw(pptr + 4, eabc);
216 putw(pptr + 4, eabc);
217 putw(pptr + 8, deab);
225 inc_ptr(dest, draster);
228 } else if (h > 0) { /* w < 5 */
229 INCR(fnarrow[max(w, 0)]);
234 dest[15] = dest[10] = dest[5] = dest[0] = a;
235 dest[16] = dest[11] = dest[6] = dest[1] = b;
236 dest[17] = dest[12] = dest[7] = dest[2] = c;
237 dest[18] = dest[13] = dest[8] = dest[3] = d;
238 dest[19] = dest[14] = dest[9] = dest[4] = e;
239 inc_ptr(dest, draster);
245 dest[10] = dest[5] = dest[0] = a;
246 dest[11] = dest[6] = dest[1] = b;
247 dest[12] = dest[7] = dest[2] = c;
248 dest[13] = dest[8] = dest[3] = d;
249 dest[14] = dest[9] = dest[4] = e;
250 inc_ptr(dest, draster);
256 dest[5] = dest[0] = a;
257 dest[6] = dest[1] = b;
258 dest[7] = dest[2] = c;
259 dest[8] = dest[3] = d;
260 dest[9] = dest[4] = e;
261 inc_ptr(dest, draster);
267 dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d; dest[4] = e;
268 inc_ptr(dest, draster);
280 /* Copy a monochrome bitmap. */
282 mem_true40_copy_mono(gx_device * dev,
283 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
284 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
286 gx_device_memory * const mdev = (gx_device_memory *)dev;
291 declare_scan_ptr(dest);
293 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
295 line = base + (sourcex >> 3);
297 first_bit = 0x80 >> sbit;
298 if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
300 declare_unpack_color(a0, b0, c0, d0, e0, zero);
301 declare_unpack_color(a1, b1, c1, d1, e1, one);
303 register byte *pptr = dest;
304 const byte *sptr = line;
305 register int sbyte = *sptr++;
306 register int bit = first_bit;
311 if (one != gx_no_color_index)
312 put5(pptr, a1, b1, c1, d1, e1);
314 put5(pptr, a0, b0, c0, d0, e0);
316 if ((bit >>= 1) == 0)
317 bit = 0x80, sbyte = *sptr++;
321 inc_ptr(dest, draster);
323 } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
324 /* This is used heavily. */
325 declare_unpack_color(a1, b1, c1, d1, e1, one);
326 int first_mask = first_bit << 1;
327 int first_count, first_skip;
331 first_count = 8 - sbit;
333 first_mask -= first_mask >> w,
335 first_skip = first_count * PIXEL_SIZE;
337 register byte *pptr = dest;
338 const byte *sptr = line;
339 register int sbyte = *sptr++ & first_mask;
340 int count = w - first_count;
343 register int bit = first_bit;
347 put5(pptr, a1, b1, c1, d1, e1);
350 while ((bit >>= 1) & first_mask);
357 put5(pptr, a1, b1, c1, d1, e1);
359 put5(pptr + 5, a1, b1, c1, d1, e1);
361 put5(pptr + 10, a1, b1, c1, d1, e1);
363 put5(pptr + 15, a1, b1, c1, d1, e1);
367 put5(pptr + 20, a1, b1, c1, d1, e1);
369 put5(pptr + 25, a1, b1, c1, d1, e1);
371 put5(pptr + 30, a1, b1, c1, d1, e1);
373 put5(pptr + 35, a1, b1, c1, d1, e1);
375 pptr += 8 * PIXEL_SIZE;
379 register int bit = 0x80;
384 put5(pptr, a1, b1, c1, d1, e1);
391 inc_ptr(dest, draster);
397 /* Copy a color bitmap. */
399 mem_true40_copy_color(gx_device * dev,
400 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
401 int x, int y, int w, int h)
403 gx_device_memory * const mdev = (gx_device_memory *)dev;
405 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
406 mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
410 /* ================ "Word"-oriented device ================ */
412 /* Note that on a big-endian machine, this is the same as the */
413 /* standard byte-oriented-device. */
415 #if !arch_is_big_endian
418 declare_mem_procs(mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle);
420 /* Here is the device descriptor. */
421 const gx_device_memory mem_true40_word_device =
422 mem_full_device("image40w", 40, 0, mem_open,
423 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
424 mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle,
425 gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
426 gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
428 /* Fill a rectangle with a color. */
430 mem40_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
431 gx_color_index color)
433 gx_device_memory * const mdev = (gx_device_memory *)dev;
437 fit_fill(dev, x, y, w, h);
438 base = scan_line_base(mdev, y);
439 raster = mdev->raster;
440 mem_swap_byte_rect(base, raster, x * 40, w * 40, h, true);
441 mem_true40_fill_rectangle(dev, x, y, w, h, color);
442 mem_swap_byte_rect(base, raster, x * 40, w * 40, h, false);
448 mem40_word_copy_mono(gx_device * dev,
449 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
450 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
452 gx_device_memory * const mdev = (gx_device_memory *)dev;
457 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
458 row = scan_line_base(mdev, y);
459 raster = mdev->raster;
460 store = (zero != gx_no_color_index && one != gx_no_color_index);
461 mem_swap_byte_rect(row, raster, x * 40, w * 40, h, store);
462 mem_true40_copy_mono(dev, base, sourcex, sraster, id,
463 x, y, w, h, zero, one);
464 mem_swap_byte_rect(row, raster, x * 40, w * 40, h, false);
468 /* Copy a color bitmap. */
470 mem40_word_copy_color(gx_device * dev,
471 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
472 int x, int y, int w, int h)
474 gx_device_memory * const mdev = (gx_device_memory *)dev;
478 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
479 row = scan_line_base(mdev, y);
480 raster = mdev->raster;
481 mem_swap_byte_rect(row, raster, x * 40, w * 40, h, true);
482 bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
483 sraster, w * PIXEL_SIZE, h);
484 mem_swap_byte_rect(row, raster, x * 40, w * 40, h, false);
488 #endif /* !arch_is_big_endian */