1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 /*$Id: gdevm64.c 8250 2007-09-25 13:31:24Z giles $ */
14 /* 64-bit-per-pixel "memory" (stored bitmap) device */
15 #include "memory_.h"
16 #include "gx.h"
17 #include "gxdevice.h"
18 #include "gxdevmem.h" /* semi-public definitions */
19 #include "gdevmem.h" /* private definitions */
20
21 /* Define debugging statistics. */
22 #ifdef DEBUG
23 struct stats_mem64_s {
24 long
25 fill, fwide, fgray[101], fsetc, fcolor[101], fnarrow[5],
26 fprevc[257];
27 double ftotal;
28 } stats_mem64;
29 static int prev_count = 0;
30 static gx_color_index prev_colors[256];
31 # define INCR(v) (++(stats_mem64.v))
32 #else
33 # define INCR(v) DO_NOTHING
34 #endif
35
36
37 /* ================ Standard (byte-oriented) device ================ */
38
39 #undef chunk
40 #define chunk byte
41 #define PIXEL_SIZE 2
42
43 /* Procedures */
44 declare_mem_procs(mem_true64_copy_mono, mem_true64_copy_color, mem_true64_fill_rectangle);
45
46 /* The device descriptor. */
47 const gx_device_memory mem_true64_device =
48 mem_full_alpha_device("image64", 64, 0, mem_open,
49 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
50 mem_true64_copy_mono, mem_true64_copy_color, mem_true64_fill_rectangle,
51 gx_default_map_cmyk_color, gx_default_copy_alpha,
52 gx_default_strip_tile_rectangle, mem_default_strip_copy_rop,
53 mem_get_bits_rectangle);
54
55 /* Convert x coordinate to byte offset in scan line. */
56 #undef x_to_byte
57 #define x_to_byte(x) ((x) << 3)
58
59 /* Put a 64-bit color into the bitmap. */
60 #define put8(ptr, abcd, efgh)\
61 (ptr)[0] = abcd, (ptr)[1] = efgh
62 /* Free variables: [m]dev, abcd, degh. */
63 #if arch_is_big_endian
64 /* Unpack a color into 32 bit chunks. */
65 # define declare_unpack_color(abcd, efgh, color)\
66 bits32 abcd = (bits32)((color) >> 32);\
67 bits32 efgh = (bits32)(color)
68 #else
69 /* Unpack a color into 32 bit chunks. */
70 # define declare_unpack_color(abcd, efgh, color)\
71 bits32 abcd = (bits32)((0x000000ff & ((color) >> 56)) |\
72 (0x0000ff00 & ((color) >> 40)) |\
73 (0x00ff0000 & ((color) >> 24)) |\
74 (0xff000000 & ((color) >> 8)));\
75 bits32 efgh = (bits32)((0x000000ff & ((color) >> 24)) |\
76 (0x0000ff00 & ((color) >> 8)) |\
77 (0x00ff0000 & ((color) << 8)) |\
78 (0xff000000 & ((color) << 24)))
79 #endif
80 #define dest32 ((bits32 *)dest)
81
82 /* Fill a rectangle with a color. */
83 static int
mem_true64_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)84 mem_true64_fill_rectangle(gx_device * dev,
85 int x, int y, int w, int h, gx_color_index color)
86 {
87 gx_device_memory * const mdev = (gx_device_memory *)dev;
88 declare_scan_ptr(dest);
89 declare_unpack_color(abcd, efgh, color);
90
91 /*
92 * In order to avoid testing w > 0 and h > 0 twice, we defer
93 * executing setup_rect, and use fit_fill_xywh instead of
94 * fit_fill.
95 */
96 fit_fill_xywh(dev, x, y, w, h);
97 INCR(fill);
98 #ifdef DEBUG
99 stats_mem64.ftotal += w;
100 #endif
101 if (h <= 0)
102 return 0;
103 if (w >= 5) {
104 INCR(fwide);
105 setup_rect(dest);
106 #ifdef DEBUG
107 {
108 int ci;
109 for (ci = 0; ci < prev_count; ++ci)
110 if (prev_colors[ci] == color)
111 break;
112 INCR(fprevc[ci]);
113 if (ci == prev_count) {
114 if (ci < countof(prev_colors))
115 ++prev_count;
116 else
117 --ci;
118 }
119 if (ci) {
120 memmove(&prev_colors[1], &prev_colors[0],
121 ci * sizeof(prev_colors[0]));
122 prev_colors[0] = color;
123 }
124 }
125 #endif
126 INCR(fcolor[min(w, 100)]);
127 while (h-- > 0) {
128 register bits32 *pptr = dest32;
129 int w1 = w;
130
131 while (w1 >= 4) {
132 put8(pptr, abcd, efgh);
133 put8(pptr + 2, abcd, efgh);
134 put8(pptr + 4, abcd, efgh);
135 put8(pptr + 6, abcd, efgh);
136 pptr += 4 * PIXEL_SIZE;
137 w1 -= 4;
138 }
139 switch (w1) {
140 case 1:
141 put8(pptr, abcd, efgh);
142 break;
143 case 2:
144 put8(pptr, abcd, efgh);
145 put8(pptr + 2, abcd, efgh);
146 break;
147 case 3:
148 put8(pptr, abcd, efgh);
149 put8(pptr + 2, abcd, efgh);
150 put8(pptr + 4, abcd, efgh);
151 break;
152 case 0:
153 ;
154 }
155 inc_ptr(dest, draster);
156 }
157 } else { /* w < 5 */
158 INCR(fnarrow[max(w, 0)]);
159 setup_rect(dest);
160 switch (w) {
161 case 4:
162 do {
163 put8(dest32, abcd, efgh);
164 put8(dest32 + 2, abcd, efgh);
165 put8(dest32 + 4, abcd, efgh);
166 put8(dest32 + 6, abcd, efgh);
167 inc_ptr(dest, draster);
168 }
169 while (--h);
170 break;
171 case 3:
172 do {
173 put8(dest32, abcd, efgh);
174 put8(dest32 + 2, abcd, efgh);
175 put8(dest32 + 4, abcd, efgh);
176 inc_ptr(dest, draster);
177 }
178 while (--h);
179 break;
180 case 2:
181 do {
182 put8(dest32, abcd, efgh);
183 put8(dest32 + 2, abcd, efgh);
184 inc_ptr(dest, draster);
185 }
186 while (--h);
187 break;
188 case 1:
189 do {
190 put8(dest32, abcd, efgh);
191 inc_ptr(dest, draster);
192 }
193 while (--h);
194 break;
195 case 0:
196 default:
197 ;
198 }
199 }
200 return 0;
201 }
202
203 /* Copy a monochrome bitmap. */
204 static int
mem_true64_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)205 mem_true64_copy_mono(gx_device * dev,
206 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
207 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
208 {
209 gx_device_memory * const mdev = (gx_device_memory *)dev;
210 const byte *line;
211 int sbit;
212 int first_bit;
213
214 declare_scan_ptr(dest);
215
216 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
217 setup_rect(dest);
218 line = base + (sourcex >> 3);
219 sbit = sourcex & 7;
220 first_bit = 0x80 >> sbit;
221 if (zero != gx_no_color_index) { /* Loop for halftones or inverted masks */
222 /* (never used). */
223 declare_unpack_color(abcd0, efgh0, zero);
224 declare_unpack_color(abcd1, efgh1, one);
225 while (h-- > 0) {
226 register bits32 *pptr = dest32;
227 const byte *sptr = line;
228 register int sbyte = *sptr++;
229 register int bit = first_bit;
230 int count = w;
231
232 do {
233 if (sbyte & bit) {
234 if (one != gx_no_color_index)
235 put8(pptr, abcd1, efgh1);
236 } else
237 put8(pptr, abcd0, efgh0);
238 pptr += PIXEL_SIZE;
239 if ((bit >>= 1) == 0)
240 bit = 0x80, sbyte = *sptr++;
241 }
242 while (--count > 0);
243 line += sraster;
244 inc_ptr(dest, draster);
245 }
246 } else if (one != gx_no_color_index) { /* Loop for character and pattern masks. */
247 /* This is used heavily. */
248 declare_unpack_color(abcd1, efgh1, one);
249 int first_mask = first_bit << 1;
250 int first_count, first_skip;
251
252 if (sbit + w > 8)
253 first_mask -= 1,
254 first_count = 8 - sbit;
255 else
256 first_mask -= first_mask >> w,
257 first_count = w;
258 first_skip = first_count * PIXEL_SIZE;
259 while (h-- > 0) {
260 register bits32 *pptr = dest32;
261 const byte *sptr = line;
262 register int sbyte = *sptr++ & first_mask;
263 int count = w - first_count;
264
265 if (sbyte) {
266 register int bit = first_bit;
267
268 do {
269 if (sbyte & bit)
270 put8(pptr, abcd1, efgh1);
271 pptr += PIXEL_SIZE;
272 }
273 while ((bit >>= 1) & first_mask);
274 } else
275 pptr += first_skip;
276 while (count >= 8) {
277 sbyte = *sptr++;
278 if (sbyte & 0xf0) {
279 if (sbyte & 0x80)
280 put8(pptr, abcd1, efgh1);
281 if (sbyte & 0x40)
282 put8(pptr + 2, abcd1, efgh1);
283 if (sbyte & 0x20)
284 put8(pptr + 4, abcd1, efgh1);
285 if (sbyte & 0x10)
286 put8(pptr + 6, abcd1, efgh1);
287 }
288 if (sbyte & 0xf) {
289 if (sbyte & 8)
290 put8(pptr + 8, abcd1, efgh1);
291 if (sbyte & 4)
292 put8(pptr + 10, abcd1, efgh1);
293 if (sbyte & 2)
294 put8(pptr + 12, abcd1, efgh1);
295 if (sbyte & 1)
296 put8(pptr + 14, abcd1, efgh1);
297 }
298 pptr += 8 * PIXEL_SIZE;
299 count -= 8;
300 }
301 if (count > 0) {
302 register int bit = 0x80;
303
304 sbyte = *sptr++;
305 do {
306 if (sbyte & bit)
307 put8(pptr, abcd1, efgh1);
308 pptr += PIXEL_SIZE;
309 bit >>= 1;
310 }
311 while (--count > 0);
312 }
313 line += sraster;
314 inc_ptr(dest, draster);
315 }
316 }
317 return 0;
318 }
319
320 /* Copy a color bitmap. */
321 static int
mem_true64_copy_color(gx_device * dev,const byte * base,int sourcex,int sraster,gx_bitmap_id id,int x,int y,int w,int h)322 mem_true64_copy_color(gx_device * dev,
323 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
324 int x, int y, int w, int h)
325 {
326 gx_device_memory * const mdev = (gx_device_memory *)dev;
327
328 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
329 mem_copy_byte_rect(mdev, base, sourcex, sraster, x, y, w, h);
330 return 0;
331 }
332
333 /* ================ "Word"-oriented device ================ */
334
335 /* Note that on a big-endian machine, this is the same as the */
336 /* standard byte-oriented-device. */
337
338 #if !arch_is_big_endian
339
340 /* Procedures */
341 declare_mem_procs(mem64_word_copy_mono, mem64_word_copy_color, mem64_word_fill_rectangle);
342
343 /* Here is the device descriptor. */
344 const gx_device_memory mem_true64_word_device =
345 mem_full_device("image64w", 64, 0, mem_open,
346 gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb,
347 mem64_word_copy_mono, mem64_word_copy_color, mem64_word_fill_rectangle,
348 gx_default_map_cmyk_color, gx_default_strip_tile_rectangle,
349 gx_no_strip_copy_rop, mem_word_get_bits_rectangle);
350
351 /* Fill a rectangle with a color. */
352 static int
mem64_word_fill_rectangle(gx_device * dev,int x,int y,int w,int h,gx_color_index color)353 mem64_word_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
354 gx_color_index color)
355 {
356 gx_device_memory * const mdev = (gx_device_memory *)dev;
357 byte *base;
358 uint raster;
359
360 fit_fill(dev, x, y, w, h);
361 base = scan_line_base(mdev, y);
362 raster = mdev->raster;
363 mem_swap_byte_rect(base, raster, x * 64, w * 64, h, true);
364 mem_true64_fill_rectangle(dev, x, y, w, h, color);
365 mem_swap_byte_rect(base, raster, x * 64, w * 64, h, false);
366 return 0;
367 }
368
369 /* Copy a bitmap. */
370 static int
mem64_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)371 mem64_word_copy_mono(gx_device * dev,
372 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
373 int x, int y, int w, int h, gx_color_index zero, gx_color_index one)
374 {
375 gx_device_memory * const mdev = (gx_device_memory *)dev;
376 byte *row;
377 uint raster;
378 bool store;
379
380 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
381 row = scan_line_base(mdev, y);
382 raster = mdev->raster;
383 store = (zero != gx_no_color_index && one != gx_no_color_index);
384 mem_swap_byte_rect(row, raster, x * 64, w * 64, h, store);
385 mem_true64_copy_mono(dev, base, sourcex, sraster, id,
386 x, y, w, h, zero, one);
387 mem_swap_byte_rect(row, raster, x * 64, w * 64, h, false);
388 return 0;
389 }
390
391 /* Copy a color bitmap. */
392 static int
mem64_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)393 mem64_word_copy_color(gx_device * dev,
394 const byte * base, int sourcex, int sraster, gx_bitmap_id id,
395 int x, int y, int w, int h)
396 {
397 gx_device_memory * const mdev = (gx_device_memory *)dev;
398 byte *row;
399 uint raster;
400
401 fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
402 row = scan_line_base(mdev, y);
403 raster = mdev->raster;
404 mem_swap_byte_rect(row, raster, x * 64, w * 64, h, true);
405 bytes_copy_rectangle(row + x * PIXEL_SIZE, raster, base + sourcex * PIXEL_SIZE,
406 sraster, w * PIXEL_SIZE, h);
407 mem_swap_byte_rect(row, raster, x * 64, w * 64, h, false);
408 return 0;
409 }
410
411 #endif /* !arch_is_big_endian */
412