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