]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/gs/src/gdevm40.c
gs: avoid stupid shifts by casting to uint64_t
[plan9front.git] / sys / src / cmd / gs / src / gdevm40.c
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: gdevm40.c,v 1.3 2005/06/20 08:59:23 igor Exp $ */
18 /* 40-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_mem40_s {
28     long
29         fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
30         fprevc[257];
31     double ftotal;
32 } stats_mem40;
33 static int prev_count = 0;
34 static gx_color_index prev_colors[256];
35 # define INCR(v) (++(stats_mem40.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 5
46
47 /* Procedures */
48 declare_mem_procs(mem_true40_copy_mono, mem_true40_copy_color, mem_true40_fill_rectangle);
49
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);
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, 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);\
69         byte e = (byte)color
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)
86 #else
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)
96 #endif
97
98 /* Fill a rectangle with a color. */
99 private int
100 mem_true40_fill_rectangle(gx_device * dev,
101                           int x, int y, int w, int h, gx_color_index color)
102 {
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);
106
107     /*
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
110      * fit_fill.
111      */
112     fit_fill_xywh(dev, x, y, w, h);
113     INCR(fill);
114 #ifdef DEBUG
115     stats_mem40.ftotal += w;
116 #endif
117     if (w >= 5) {
118         if (h <= 0)
119             return 0;
120         INCR(fwide);
121         setup_rect(dest);
122         if (a == b && b == c && c == d && d == e) {
123             int bcnt = w * PIXEL_SIZE;
124
125             INCR(fgray[min(w, 100)]);
126             while (h-- > 0) {
127                 memset(dest, a, bcnt);
128                 inc_ptr(dest, draster);
129             }
130         } else {
131             int x3 = -x & 3, ww = w - x3;       /* we know ww >= 2 */
132             bits32 abcd, bcde, cdea, deab, eabc;
133
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;
140             } else {
141                 INCR(fsetc);
142                 set_color40_cache(color, a, b, c, d, e);
143             }
144 #ifdef DEBUG
145             {
146                 int ci;
147                 for (ci = 0; ci < prev_count; ++ci)
148                     if (prev_colors[ci] == color)
149                         break;
150                 INCR(fprevc[ci]);
151                 if (ci == prev_count) {
152                     if (ci < countof(prev_colors))
153                         ++prev_count;
154                     else
155                         --ci;
156                 }
157                 if (ci) {
158                     memmove(&prev_colors[1], &prev_colors[0],
159                             ci * sizeof(prev_colors[0]));
160                     prev_colors[0] = color;
161                 }
162             }
163 #endif
164             INCR(fcolor[min(w, 100)]);
165             while (h-- > 0) {
166                 register byte *pptr = dest;
167                 int w1 = ww;
168
169                 switch (x3) {
170                     case 1:
171                         pptr[0] = a;
172                         putw(pptr + 1, bcde);
173                         pptr += PIXEL_SIZE;
174                         break;
175                     case 2:
176                         pptr[0] = a;
177                         pptr[1] = b;
178                         putw(pptr + 2, cdea);
179                         putw(pptr + 6, bcde);
180                         pptr += 2 * PIXEL_SIZE;
181                         break;
182                     case 3:
183                         pptr[0] = a;
184                         pptr[1] = b;
185                         pptr[2] = c;
186                         putw(pptr + 3, deab);
187                         putw(pptr + 7, cdea);
188                         putw(pptr + 11, bcde);
189                         pptr += 3 * PIXEL_SIZE;
190                         break;
191                     case 0:
192                         ;
193                 }
194                 while (w1 >= 4) {
195                     putw(pptr, abcd);
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;
201                     w1 -= 4;
202                 }
203                 switch (w1) {
204                     case 1:
205                         putw(pptr, abcd);
206                         pptr[4] = e;
207                         break;
208                     case 2:
209                         putw(pptr, abcd);
210                         putw(pptr + 4, eabc);
211                         pptr[8] = d;
212                         pptr[9] = e;
213                         break;
214                     case 3:
215                         putw(pptr, abcd);
216                         putw(pptr + 4, eabc);
217                         putw(pptr + 8, deab);
218                         pptr[12] = c;
219                         pptr[13] = d;
220                         pptr[14] = e;
221                         break;
222                     case 0:
223                         ;
224                 }
225                 inc_ptr(dest, draster);
226             }
227         }
228     } else if (h > 0) {         /* w < 5 */
229         INCR(fnarrow[max(w, 0)]);
230         setup_rect(dest);
231         switch (w) {
232             case 4:
233                 do {
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);
240                 }
241                 while (--h);
242                 break;
243             case 3:
244                 do {
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);
251                 }
252                 while (--h);
253                 break;
254             case 2:
255                 do {
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);
262                 }
263                 while (--h);
264                 break;
265             case 1:
266                 do {
267                     dest[0] = a; dest[1] = b; dest[2] = c; dest[3] = d; dest[4] = e;
268                     inc_ptr(dest, draster);
269                 }
270                 while (--h);
271                 break;
272             case 0:
273             default:
274                 ;
275         }
276     }
277     return 0;
278 }
279
280 /* Copy a monochrome bitmap. */
281 private int
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)
285 {
286     gx_device_memory * const mdev = (gx_device_memory *)dev;
287     const byte *line;
288     int sbit;
289     int first_bit;
290
291     declare_scan_ptr(dest);
292
293     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
294     setup_rect(dest);
295     line = base + (sourcex >> 3);
296     sbit = sourcex & 7;
297     first_bit = 0x80 >> sbit;
298     if (zero != gx_no_color_index) {    /* Loop for halftones or inverted masks */
299         /* (never used). */
300         declare_unpack_color(a0, b0, c0, d0, e0, zero);
301         declare_unpack_color(a1, b1, c1, d1, e1, one);
302         while (h-- > 0) {
303             register byte *pptr = dest;
304             const byte *sptr = line;
305             register int sbyte = *sptr++;
306             register int bit = first_bit;
307             int count = w;
308
309             do {
310                 if (sbyte & bit) {
311                     if (one != gx_no_color_index)
312                         put5(pptr, a1, b1, c1, d1, e1);
313                 } else
314                     put5(pptr, a0, b0, c0, d0, e0);
315                 pptr += PIXEL_SIZE;
316                 if ((bit >>= 1) == 0)
317                     bit = 0x80, sbyte = *sptr++;
318             }
319             while (--count > 0);
320             line += sraster;
321             inc_ptr(dest, draster);
322         }
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;
328
329         if (sbit + w > 8)
330             first_mask -= 1,
331                 first_count = 8 - sbit;
332         else
333             first_mask -= first_mask >> w,
334                 first_count = w;
335         first_skip = first_count * PIXEL_SIZE;
336         while (h-- > 0) {
337             register byte *pptr = dest;
338             const byte *sptr = line;
339             register int sbyte = *sptr++ & first_mask;
340             int count = w - first_count;
341
342             if (sbyte) {
343                 register int bit = first_bit;
344
345                 do {
346                     if (sbyte & bit)
347                         put5(pptr, a1, b1, c1, d1, e1);
348                     pptr += PIXEL_SIZE;
349                 }
350                 while ((bit >>= 1) & first_mask);
351             } else
352                 pptr += first_skip;
353             while (count >= 8) {
354                 sbyte = *sptr++;
355                 if (sbyte & 0xf0) {
356                     if (sbyte & 0x80)
357                         put5(pptr, a1, b1, c1, d1, e1);
358                     if (sbyte & 0x40)
359                         put5(pptr + 5, a1, b1, c1, d1, e1);
360                     if (sbyte & 0x20)
361                         put5(pptr + 10, a1, b1, c1, d1, e1);
362                     if (sbyte & 0x10)
363                         put5(pptr + 15, a1, b1, c1, d1, e1);
364                 }
365                 if (sbyte & 0xf) {
366                     if (sbyte & 8)
367                         put5(pptr + 20, a1, b1, c1, d1, e1);
368                     if (sbyte & 4)
369                         put5(pptr + 25, a1, b1, c1, d1, e1);
370                     if (sbyte & 2)
371                         put5(pptr + 30, a1, b1, c1, d1, e1);
372                     if (sbyte & 1)
373                         put5(pptr + 35, a1, b1, c1, d1, e1);
374                 }
375                 pptr += 8 * PIXEL_SIZE;
376                 count -= 8;
377             }
378             if (count > 0) {
379                 register int bit = 0x80;
380
381                 sbyte = *sptr++;
382                 do {
383                     if (sbyte & bit)
384                         put5(pptr, a1, b1, c1, d1, e1);
385                     pptr += PIXEL_SIZE;
386                     bit >>= 1;
387                 }
388                 while (--count > 0);
389             }
390             line += sraster;
391             inc_ptr(dest, draster);
392         }
393     }
394     return 0;
395 }
396
397 /* Copy a color bitmap. */
398 private int
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)
402 {
403     gx_device_memory * const mdev = (gx_device_memory *)dev;
404
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);
407     return 0;
408 }
409
410 /* ================ "Word"-oriented device ================ */
411
412 /* Note that on a big-endian machine, this is the same as the */
413 /* standard byte-oriented-device. */
414
415 #if !arch_is_big_endian
416
417 /* Procedures */
418 declare_mem_procs(mem40_word_copy_mono, mem40_word_copy_color, mem40_word_fill_rectangle);
419
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);
427
428 /* Fill a rectangle with a color. */
429 private int
430 mem40_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
431                           gx_color_index color)
432 {
433     gx_device_memory * const mdev = (gx_device_memory *)dev;
434     byte *base;
435     uint raster;
436
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);
443     return 0;
444 }
445
446 /* Copy a bitmap. */
447 private int
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)
451 {
452     gx_device_memory * const mdev = (gx_device_memory *)dev;
453     byte *row;
454     uint raster;
455     bool store;
456
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);
465     return 0;
466 }
467
468 /* Copy a color bitmap. */
469 private int
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)
473 {
474     gx_device_memory * const mdev = (gx_device_memory *)dev;
475     byte *row;
476     uint raster;
477
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);
485     return 0;
486 }
487
488 #endif /* !arch_is_big_endian */