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