Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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 */