1 /* Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises, 2001 Artifex Software. 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: gdevm56.c,v 1.3 2004/08/30 21:45:48 dan Exp $ */
18 /* 56-bit-per-pixel "memory" (stored bitmap) device */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gxdevice.h"
22 #include "gxdevmem.h" /* semi-public definitions */
23 #include "gdevmem.h" /* private definitions */
24
25 /* Define debugging statistics. */
26 #ifdef DEBUG
27 struct stats_mem56_s {
28 long
29 fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
30 fprevc[257];
31 double ftotal;
32 } stats_mem56;
33 static int prev_count;
34 static gx_color_index prev_colors[256];
35 # define INCR(v) (++(stats_mem56.v))
36 #else
37 # define INCR(v) DO_NOTHING
38 #endif
39
40
41 /* ================ Standard (byte-oriented) device ================ */
42
43 #undef chunk
44 #define chunk byte
45 #define PIXEL_SIZE 7
46
47 /* Procedures */
48 declare_mem_procs(mem_true56_copy_mono, mem_true56_copy_color, mem_true56_fill_rectangle);
49
50 /* The device descriptor. */
51 const gx_device_memory mem_true56_device =
52 mem_full_alpha_device("image56", 56, 0, mem_open,
53 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
54 mem_true56_copy_mono, mem_true56_copy_color, mem_true56_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);
58
59 /* Convert x coordinate to byte offset in scan line. */
60 #undef x_to_byte
61 #define x_to_byte(x) ((x) * PIXEL_SIZE)
62
63 /* Unpack a color into its bytes. */
64 #define declare_unpack_color(a, b, c, d, e, f, g, color)\
65 byte a = (byte)(color >> 48);\
66 byte b = (byte)(color >> 40);\
67 byte c = (byte)(color >> 32);\
68 byte d = (byte)((uint)color >> 24);\
69 byte e = (byte)((uint)color >> 16);\
70 byte f = (byte)((uint)color >> 8);\
71 byte g = (byte)color
72 /* Put a 56-bit color into the bitmap. */
73 #define put7(ptr, a, b, c, d, e, f, g)\
74 (ptr)[0] = a, (ptr)[1] = b, (ptr)[2] = c, (ptr)[3] = d, (ptr)[4] = e, \
75 (ptr)[5] = f, (ptr)[6] = g
76 /* Put 4 bytes of color into the bitmap. */
77 #define putw(ptr, wxyz)\
78 *(bits32 *)(ptr) = (wxyz)
79 /* Load the 7-word 56-bit-color cache. */
80 /* Free variables: [m]dev, abcd, bcde, cdea, deab, earc. */
81 #if arch_is_big_endian
82 # define set_color56_cache(color, a, b, c, d, e, f, g)\
83 mdev->color56.abcd = abcd = (color) >> 24, \
84 mdev->color56.bcde = bcde = (abcd << 8) | (e),\
85 mdev->color56.cdef = cdef = (bcde << 8) | (f),\
86 mdev->color56.defg = defg = (cdef << 8) | (g),\
87 mdev->color56.efga = efga = (defg << 8) | (a),\
88 mdev->color56.fgab = fgab = (efga << 8) | (b),\
89 mdev->color56.gabc = gabc = (fgab << 8) | (c),\
90 mdev->color56.abcdefg = (color)
91 #else
92 # define set_color56_cache(color, a, b, c, d, e, f, g)\
93 mdev->color56.abcd = abcd =\
94 ((bits32)(d) << 24) | ((bits32)(c) << 16) |\
95 ((bits16)(b) << 8) | (a),\
96 mdev->color56.gabc = gabc = (abcd << 8) | (g),\
97 mdev->color56.fgab = fgab = (gabc << 8) | (f),\
98 mdev->color56.efga = efga = (fgab << 8) | (e),\
99 mdev->color56.defg = defg = (efga << 8) | (d),\
100 mdev->color56.cdef = cdef = (defg << 8) | (c),\
101 mdev->color56.bcde = bcde = (cdef << 8) | (b),\
102 mdev->color56.abcdefg = (color)
103 #endif
104
105 /* Fill a rectangle with a color. */
106 private int
mem_true56_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)107 mem_true56_fill_rectangle(gx_device * dev,
108 int x, int y, int w, int h, gx_color_index color)
109 {
110 gx_device_memory * const mdev = (gx_device_memory *)dev;
111 declare_unpack_color(a, b, c, d, e, f, g, color);
112 declare_scan_ptr(dest);
113
114 /*
115 * In order to avoid testing w > 0 and h > 0 twice, we defer
116 * executing setup_rect, and use fit_fill_xywh instead of
117 * fit_fill.
118 */
119 fit_fill_xywh(dev, x, y, w, h);
120 INCR(fill);
121 #ifdef DEBUG
122 stats_mem56.ftotal += w;
123 #endif
124 if (w >= 5) {
125 if (h <= 0)
126 return 0;
127 INCR(fwide);
128 setup_rect(dest);
129 if (a == b && b == c && c == d && d == e && e == f && f == g) {
130 int bcnt = w * PIXEL_SIZE;
131
132 INCR(fgray[min(w, 100)]);
133 while (h-- > 0) {
134 memset(dest, a, bcnt);
135 inc_ptr(dest, draster);
136 }
137 } else {
138 int x3 = -x & 3, ww = w - x3; /* we know ww >= 2 */
139 bits32 abcd, bcde, cdef, defg, efga, fgab, gabc;
140
141 if (mdev->color56.abcdefg == color) {
142 abcd = mdev->color56.abcd;
143 bcde = mdev->color56.bcde;
144 cdef = mdev->color56.cdef;
145 defg = mdev->color56.defg;
146 efga = mdev->color56.efga;
147 fgab = mdev->color56.fgab;
148 gabc = mdev->color56.gabc;
149 } else {
150 INCR(fsetc);
151 set_color56_cache(color, a, b, c, d, e, f, g);
152 }
153 #ifdef DEBUG
154 {
155 int ci;
156 for (ci = 0; ci < prev_count; ++ci)
157 if (prev_colors[ci] == color)
158 break;
159 INCR(fprevc[ci]);
160 if (ci == prev_count) {
161 if (ci < countof(prev_colors))
162 ++prev_count;
163 else
164 --ci;
165 }
166 if (ci) {
167 memmove(&prev_colors[1], &prev_colors[0],
168 ci * sizeof(prev_colors[0]));
169 prev_colors[0] = color;
170 }
171 }
172 #endif
173 INCR(fcolor[min(w, 100)]);
174 while (h-- > 0) {
175 register byte *pptr = dest;
176 int w1 = ww;
177
178 switch (x3) {
179 case 1:
180 pptr[0] = a;
181 pptr[1] = b;
182 pptr[2] = c;
183 putw(pptr + 3, defg);
184 pptr += PIXEL_SIZE;
185 break;
186 case 2:
187 pptr[0] = a;
188 pptr[1] = b;
189 putw(pptr + 2, cdef);
190 putw(pptr + 6, gabc);
191 putw(pptr + 10, defg);
192 pptr += 2 * PIXEL_SIZE;
193 break;
194 case 3:
195 pptr[0] = a;
196 putw(pptr + 1, bcde);
197 putw(pptr + 5, fgab);
198 putw(pptr + 9, cdef);
199 putw(pptr + 13, gabc);
200 putw(pptr + 17, defg);
201 pptr += 3 * PIXEL_SIZE;
202 break;
203 case 0:
204 ;
205 }
206 while (w1 >= 4) {
207 putw(pptr, abcd);
208 putw(pptr + 4, efga);
209 putw(pptr + 8, bcde);
210 putw(pptr + 12, fgab);
211 putw(pptr + 16, cdef);
212 putw(pptr + 20, gabc);
213 putw(pptr + 24, defg);
214 pptr += 4 * PIXEL_SIZE;
215 w1 -= 4;
216 }
217 switch (w1) {
218 case 1:
219 putw(pptr, abcd);
220 pptr[4] = e;
221 pptr[5] = f;
222 pptr[6] = g;
223 break;
224 case 2:
225 putw(pptr, abcd);
226 putw(pptr + 4, efga);
227 putw(pptr + 8, bcde);
228 pptr[12] = f;
229 pptr[13] = g;
230 break;
231 case 3:
232 putw(pptr, abcd);
233 putw(pptr + 4, efga);
234 putw(pptr + 8, bcde);
235 putw(pptr + 12, fgab);
236 putw(pptr + 16, cdef);
237 pptr[20] = g;
238 break;
239 case 0:
240 ;
241 }
242 inc_ptr(dest, draster);
243 }
244 }
245 } else if (h > 0) { /* w < 5 */
246 INCR(fnarrow[max(w, 0)]);
247 setup_rect(dest);
248 switch (w) {
249 case 4:
250 do {
251 dest[21] = dest[14] = dest[7] = dest[0] = a;
252 dest[22] = dest[15] = dest[8] = dest[1] = b;
253 dest[23] = dest[16] = dest[9] = dest[2] = c;
254 dest[24] = dest[17] = dest[10] = dest[3] = d;
255 dest[25] = dest[18] = dest[11] = dest[4] = e;
256 dest[26] = dest[19] = dest[12] = dest[5] = f;
257 dest[27] = dest[20] = dest[13] = dest[6] = g;
258 inc_ptr(dest, draster);
259 }
260 while (--h);
261 break;
262 case 3:
263 do {
264 dest[14] = dest[7] = dest[0] = a;
265 dest[15] = dest[8] = dest[1] = b;
266 dest[16] = dest[9] = dest[2] = c;
267 dest[17] = dest[10] = dest[3] = d;
268 dest[18] = dest[11] = dest[4] = e;
269 dest[19] = dest[12] = dest[5] = f;
270 dest[20] = dest[13] = dest[6] = g;
271 inc_ptr(dest, draster);
272 }
273 while (--h);
274 break;
275 case 2:
276 do {
277 dest[7] = dest[0] = a;
278 dest[8] = dest[1] = b;
279 dest[9] = dest[2] = c;
280 dest[10] = dest[3] = d;
281 dest[11] = dest[4] = e;
282 dest[12] = dest[5] = f;
283 dest[13] = dest[6] = g;
284 inc_ptr(dest, draster);
285 }
286 while (--h);
287 break;
288 case 1:
289 do {
290 dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d;
291 dest[4] = e; dest[5] = f; dest[6] = g;
292 inc_ptr(dest, draster);
293 }
294 while (--h);
295 break;
296 case 0:
297 default:
298 ;
299 }
300 }
301 return 0;
302 }
303
304 /* Copy a monochrome bitmap. */
305 private int
mem_true56_copy_mono(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)306 mem_true56_copy_mono(gx_device * dev,
307 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
308 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
309 {
310 gx_device_memory * const mdev = (gx_device_memory *)dev;
311 const byte *line;
312 int sbit;
313 int first_bit;
314
315 declare_scan_ptr(dest);
316
317 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
318 setup_rect(dest);
319 line = base + (sourcex >> 3);
320 sbit = sourcex & 7;
321 first_bit = 0x80 >> sbit;
322 if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
323 /* (never used). */
324 declare_unpack_color(a0, b0, c0, d0, e0, f0, g0, zero);
325 declare_unpack_color(a1, b1, c1, d1, e1, f1, g1, one);
326 while (h-- > 0) {
327 register byte *pptr = dest;
328 const byte *sptr = line;
329 register int sbyte = *sptr++;
330 register int bit = first_bit;
331 int count = w;
332
333 do {
334 if (sbyte & bit) {
335 if (one != gx_no_color_index)
336 put7(pptr, a1, b1, c1, d1, e1, f1, g1);
337 } else
338 put7(pptr, a0, b0, c0, d0, e0, f0, g0);
339 pptr += PIXEL_SIZE;
340 if ((bit >>= 1) == 0)
341 bit = 0x80, sbyte = *sptr++;
342 }
343 while (--count > 0);
344 line += sraster;
345 inc_ptr(dest, draster);
346 }
347 } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
348 /* This is used heavily. */
349 declare_unpack_color(a1, b1, c1, d1, e1, f1, g1, one);
350 int first_mask = first_bit << 1;
351 int first_count, first_skip;
352
353 if (sbit + w > 8)
354 first_mask -= 1,
355 first_count = 8 - sbit;
356 else
357 first_mask -= first_mask >> w,
358 first_count = w;
359 first_skip = first_count * PIXEL_SIZE;
360 while (h-- > 0) {
361 register byte *pptr = dest;
362 const byte *sptr = line;
363 register int sbyte = *sptr++ & first_mask;
364 int count = w - first_count;
365
366 if (sbyte) {
367 register int bit = first_bit;
368
369 do {
370 if (sbyte & bit)
371 put7(pptr, a1, b1, c1, d1, e1, f1, g1);
372 pptr += PIXEL_SIZE;
373 }
374 while ((bit >>= 1) & first_mask);
375 } else
376 pptr += first_skip;
377 while (count >= 8) {
378 sbyte = *sptr++;
379 if (sbyte & 0xf0) {
380 if (sbyte & 0x80)
381 put7(pptr, a1, b1, c1, d1, e1, f1, g1);
382 if (sbyte & 0x40)
383 put7(pptr + 7, a1, b1, c1, d1, e1, f1, g1);
384 if (sbyte & 0x20)
385 put7(pptr + 14, a1, b1, c1, d1, e1, f1, g1);
386 if (sbyte & 0x10)
387 put7(pptr + 21, a1, b1, c1, d1, e1, f1, g1);
388 }
389 if (sbyte & 0xf) {
390 if (sbyte & 8)
391 put7(pptr + 28, a1, b1, c1, d1, e1, f1, g1);
392 if (sbyte & 4)
393 put7(pptr + 35, a1, b1, c1, d1, e1, f1, g1);
394 if (sbyte & 2)
395 put7(pptr + 42, a1, b1, c1, d1, e1, f1, g1);
396 if (sbyte & 1)
397 put7(pptr + 49, a1, b1, c1, d1, e1, f1, g1);
398 }
399 pptr += 8 * PIXEL_SIZE;
400 count -= 8;
401 }
402 if (count > 0) {
403 register int bit = 0x80;
404
405 sbyte = *sptr++;
406 do {
407 if (sbyte & bit)
408 put7(pptr, a1, b1, c1, d1, e1, f1, g1);
409 pptr += PIXEL_SIZE;
410 bit >>= 1;
411 }
412 while (--count > 0);
413 }
414 line += sraster;
415 inc_ptr(dest, draster);
416 }
417 }
418 return 0;
419 }
420
421 /* Copy a color bitmap. */
422 private int
mem_true56_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)423 mem_true56_copy_color(gx_device * dev,
424 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
425 int x, int y, int w, int h)
426 {
427 gx_device_memory * const mdev = (gx_device_memory *)dev;
428
429 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
430 mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
431 return 0;
432 }
433
434 /* ================ "Word"-oriented device ================ */
435
436 /* Note that on a big-endian machine, this is the same as the */
437 /* standard byte-oriented-device. */
438
439 #if !arch_is_big_endian
440
441 /* Procedures */
442 declare_mem_procs(mem56_word_copy_mono, mem56_word_copy_color, mem56_word_fill_rectangle);
443
444 /* Here is the device descriptor. */
445 const gx_device_memory mem_true56_word_device =
446 mem_full_device("image56w", 56, 0, mem_open,
447 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
448 mem56_word_copy_mono, mem56_word_copy_color, mem56_word_fill_rectangle,
449 gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
450 gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
451
452 /* Fill a rectangle with a color. */
453 private int
mem56_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)454 mem56_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
455 gx_color_index color)
456 {
457 gx_device_memory * const mdev = (gx_device_memory *)dev;
458 byte *base;
459 uint raster;
460
461 fit_fill(dev, x, y, w, h);
462 base = scan_line_base(mdev, y);
463 raster = mdev->raster;
464 mem_swap_byte_rect(base, raster, x * 56, w * 56, h, true);
465 mem_true56_fill_rectangle(dev, x, y, w, h, color);
466 mem_swap_byte_rect(base, raster, x * 56, w * 56, h, false);
467 return 0;
468 }
469
470 /* Copy a bitmap. */
471 private int
mem56_word_copy_mono(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index zero,gx_color_index one)472 mem56_word_copy_mono(gx_device * dev,
473 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
474 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
475 {
476 gx_device_memory * const mdev = (gx_device_memory *)dev;
477 byte *row;
478 uint raster;
479 bool store;
480
481 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
482 row = scan_line_base(mdev, y);
483 raster = mdev->raster;
484 store = (zero != gx_no_color_index && one != gx_no_color_index);
485 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, store);
486 mem_true56_copy_mono(dev, base, sourcex, sraster, id,
487 x, y, w, h, zero, one);
488 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, false);
489 return 0;
490 }
491
492 /* Copy a color bitmap. */
493 private int
mem56_word_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)494 mem56_word_copy_color(gx_device * dev,
495 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
496 int x, int y, int w, int h)
497 {
498 gx_device_memory * const mdev = (gx_device_memory *)dev;
499 byte *row;
500 uint raster;
501
502 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
503 row = scan_line_base(mdev, y);
504 raster = mdev->raster;
505 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, true);
506 bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
507 sraster, w * PIXEL_SIZE, h);
508 mem_swap_byte_rect(row, raster, x * 56, w * 56, h, false);
509 return 0;
510 }
511
512 #endif /* !arch_is_big_endian */
513