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) 1992, 1993, 1994, 1997, 1999 Aladdin Enterprises.  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: gdevmgr.c,v 1.8 2005/01/19 00:24:07 dan Exp $*/
18
/* MGR device driver */
19
#include "gdevprn.h"
20
#include "gdevpccm.h"
21
#include "gdevmgr.h"
22
 
23
/* Structure for MGR devices, which extend the generic printer device. */
24
struct gx_device_mgr_s {
25
	gx_device_common;
26
	gx_prn_device_common;
27
	/* Add MGR specific variables */
28
	int mgr_depth;
29
};
30
typedef struct gx_device_mgr_s gx_device_mgr;
31
 
32
static struct nclut clut[256];
33
 
34
private unsigned int clut2mgr(int, int);
35
private void swap_bwords(unsigned char *, int);
36
 
37
/* ------ The device descriptors ------ */
38
 
39
/*
40
 * Default X and Y resolution.
41
 */
42
#define X_DPI 72
43
#define Y_DPI 72
44
 
45
/* Macro for generating MGR device descriptors. */
46
#define mgr_prn_device(procs, dev_name, num_comp, depth, mgr_depth,\
47
	max_gray, max_rgb, dither_gray, dither_rgb, print_page)\
48
{	prn_device_body(gx_device_mgr, procs, dev_name,\
49
	  DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, X_DPI, Y_DPI,\
50
	  0, 0, 0, 0,\
51
	  num_comp, depth, max_gray, max_rgb, dither_gray, dither_rgb,\
52
	  print_page),\
53
	  mgr_depth\
54
}
55
 
56
/* For all mgr variants we do some extra things at opening time. */
57
/* private dev_proc_open_device(gdev_mgr_open); */
58
#define gdev_mgr_open gdev_prn_open		/* no we don't! */
59
 
60
/* And of course we need our own print-page routines. */
61
private dev_proc_print_page(mgr_print_page);
62
private dev_proc_print_page(mgrN_print_page);
63
private dev_proc_print_page(cmgrN_print_page);
64
 
65
/* The device procedures */
66
private gx_device_procs mgr_procs =
67
    prn_procs(gdev_mgr_open, gdev_prn_output_page, gdev_prn_close);
68
private gx_device_procs mgrN_procs =
69
    prn_color_procs(gdev_mgr_open, gdev_prn_output_page, gdev_prn_close,
70
	gx_default_gray_map_rgb_color, gx_default_gray_map_color_rgb);
71
private gx_device_procs cmgr4_procs =
72
    prn_color_procs(gdev_mgr_open, gdev_prn_output_page, gdev_prn_close,
73
	pc_4bit_map_rgb_color, pc_4bit_map_color_rgb);
74
private gx_device_procs cmgr8_procs =
75
    prn_color_procs(gdev_mgr_open, gdev_prn_output_page, gdev_prn_close,
76
	mgr_8bit_map_rgb_color, mgr_8bit_map_color_rgb);
77
 
78
/* The device descriptors themselves */
79
gx_device_mgr far_data gs_mgrmono_device =
80
  mgr_prn_device( mgr_procs,  "mgrmono", 1,  1, 1,   1,   0, 2, 0, mgr_print_page);
81
gx_device_mgr far_data gs_mgrgray2_device =
82
  mgr_prn_device(mgrN_procs,  "mgrgray2",1,  8, 2, 255,   0, 4, 0, mgrN_print_page);
83
gx_device_mgr far_data gs_mgrgray4_device =
84
  mgr_prn_device(mgrN_procs,  "mgrgray4",1,  8, 4, 255,   0,16, 0, mgrN_print_page);
85
gx_device_mgr far_data gs_mgrgray8_device =
86
  mgr_prn_device(mgrN_procs,  "mgrgray8",1,  8, 8, 255,   0, 0, 0, mgrN_print_page);
87
gx_device_mgr far_data gs_mgr4_device =
88
  mgr_prn_device(cmgr4_procs, "mgr4",    3,  8, 4,   1,   1, 2, 2, cmgrN_print_page);
89
gx_device_mgr far_data gs_mgr8_device =
90
  mgr_prn_device(cmgr8_procs, "mgr8",    3,  8, 8, 255, 255, 6, 5, cmgrN_print_page);
91
 
92
/* ------ Internal routines ------ */
93
 
94
/* Define a "cursor" that keeps track of where we are in the page. */
95
typedef struct mgr_cursor_s {
96
	gx_device_mgr *dev;
97
	int bpp;			/* bits per pixel */
98
	uint line_size;			/* bytes per scan line */
99
	byte *data;			/* output row buffer */
100
	int lnum;			/* row within page */
101
} mgr_cursor;
102
 
103
/* Begin an MGR output page. */
104
/* Write the header information and initialize the cursor. */
105
private int
106
mgr_begin_page(gx_device_mgr *bdev, FILE *pstream, mgr_cursor *pcur)
107
{	struct b_header head;
108
	uint line_size =
109
		gdev_prn_raster((gx_device_printer *)bdev) + 3;
110
	byte *data = (byte *)gs_malloc(bdev->memory, line_size, 1, "mgr_begin_page");
111
	if ( data == 0 )
112
		return_error(gs_error_VMerror);
113
 
114
	/* Write the header */
115
	B_PUTHDR8(&head, bdev->width, bdev->height, bdev->mgr_depth);
116
	fprintf(pstream, "");
117
	if ( fwrite(&head, 1, sizeof(head), pstream) < sizeof(head) )
118
		return_error(gs_error_ioerror);
119
	fflush(pstream);
120
 
121
	/* Initialize the cursor. */
122
	pcur->dev = bdev;
123
	pcur->bpp = bdev->color_info.depth;
124
	pcur->line_size = line_size;
125
	pcur->data = data;
126
	pcur->lnum = 0;
127
	return 0;
128
}
129
 
130
/* Advance to the next row.  Return 0 if more, 1 if done. */
131
private int
132
mgr_next_row(mgr_cursor *pcur)
133
{	if ( pcur->lnum >= pcur->dev->height )
134
	{	gs_free(((gx_device_printer *)pcur->dev)->memory,
135
			(char *)pcur->data, pcur->line_size, 1,
136
			"mgr_next_row(done)");
137
		return 1;
138
	   }
139
	gdev_prn_copy_scan_lines((gx_device_printer *)pcur->dev,
140
				 pcur->lnum++, pcur->data, pcur->line_size);
141
	return 0;
142
}
143
 
144
/* ------ Individual page printing routines ------ */
145
 
146
#define bdev ((gx_device_mgr *)pdev)
147
 
148
/* Print a monochrome page. */
149
private int
150
mgr_print_page(gx_device_printer *pdev, FILE *pstream)
151
{	mgr_cursor cur;
152
	int mgr_wide;
153
	int code = mgr_begin_page(bdev, pstream, &cur);
154
	if ( code < 0 ) return code;
155
 
156
	mgr_wide = bdev->width;
157
	if (mgr_wide & 7)
158
	   mgr_wide += 8 - (mgr_wide & 7);
159
 
160
	while ( !(code = mgr_next_row(&cur)) )
161
	   {	if ( fwrite(cur.data, sizeof(char), mgr_wide / 8, pstream) <
162
                    mgr_wide / 8)
163
		return_error(gs_error_ioerror);
164
	   }
165
	return (code < 0 ? code : 0);
166
}
167
 
168
 
169
/* Print a gray-mapped page. */
170
static unsigned char bgreytable[16], bgreybacktable[16];
171
static unsigned char bgrey256table[256], bgrey256backtable[256];        
172
private int
173
mgrN_print_page(gx_device_printer *pdev, FILE *pstream)
174
{	mgr_cursor cur;
175
	int i = 0, j, k, mgr_wide;
176
	uint mgr_line_size;
177
	byte *bp, *data = NULL, *dp;
178
 
179
	int code = mgr_begin_page(bdev, pstream, &cur);
180
	if ( code < 0 ) return code;
181
 
182
	mgr_wide = bdev->width;
183
	if ( bdev->mgr_depth == 2 && mgr_wide & 3 )
184
            mgr_wide += 4 - (mgr_wide & 3);
185
	if ( bdev->mgr_depth == 4 && mgr_wide & 1 )
186
            mgr_wide++;
187
	mgr_line_size = mgr_wide / ( 8 / bdev->mgr_depth );
188
 
189
	if ( bdev->mgr_depth == 4 )
190
            for ( i = 0; i < 16; i++ ) {
191
		bgreytable[i] = mgrlut[LUT_BGREY][RGB_RED][i];
192
		bgreybacktable[bgreytable[i]] = i;
193
            }
194
 
195
	if ( bdev->mgr_depth == 8 ) {
196
            for ( i = 0; i < 16; i++ ) {
197
		bgrey256table[i] = mgrlut[LUT_BGREY][RGB_RED][i] << 4;
198
		bgrey256backtable[bgrey256table[i]] = i;
199
            }
200
            for ( i = 16,j = 0; i < 256; i++ ) {
201
		for ( k = 0; k < 16; k++ )
202
                  if ( j == mgrlut[LUT_BGREY][RGB_RED][k] << 4 ) {
203
                    j++;
204
                    break;
205
                  }
206
		bgrey256table[i] = j;
207
		bgrey256backtable[j++] = i;
208
            }
209
	}
210
 
211
	if ( bdev->mgr_depth != 8 )
212
	    data = (byte *)gs_malloc(pdev->memory, mgr_line_size, 1, "mgrN_print_page");
213
 
214
	while ( !(code = mgr_next_row(&cur)) )
215
	   {
216
		switch (bdev->mgr_depth) {
217
			case 2:
218
				for (i = 0,dp = data,bp = cur.data; i < mgr_line_size; i++) {
219
					*dp =	*(bp++) & 0xc0;
220
					*dp |= (*(bp++) & 0xc0) >> 2;
221
					*dp |= (*(bp++) & 0xc0) >> 4;
222
                                    *(dp++) |= (*(bp++) & 0xc0) >> 6;
223
				}
224
                		if ( fwrite(data, sizeof(byte), mgr_line_size, pstream) < mgr_line_size )
225
                                	return_error(gs_error_ioerror);
226
				break;
227
 
228
			case 4:
229
				for (i = 0,dp = data, bp = cur.data; i < mgr_line_size; i++) {
230
					*dp =  bgreybacktable[*(bp++) >> 4] << 4;
231
                                    *(dp++) |= bgreybacktable[*(bp++) >> 4];
232
				}
233
                		if ( fwrite(data, sizeof(byte), mgr_line_size, pstream) < mgr_line_size )
234
                                	return_error(gs_error_ioerror);
235
				break;
236
 
237
			case 8:
238
				for (i = 0,bp = cur.data; i < mgr_line_size; i++, bp++)
239
	                              *bp = bgrey256backtable[*bp];
240
                		if ( fwrite(cur.data, sizeof(cur.data[0]), mgr_line_size, pstream)
241
					< mgr_line_size )
242
                                	return_error(gs_error_ioerror);
243
				break;
244
		}  
245
	   }
246
	if (bdev->mgr_depth != 8)
247
	    gs_free(bdev->memory, (char *)data, mgr_line_size, 1, "mgrN_print_page(done)");
248
 
249
	if (bdev->mgr_depth == 2) {
250
            for (i = 0; i < 4; i++) {
251
               clut[i].colnum = i;
252
               clut[i].red    = clut[i].green = clut[i].blue = clut2mgr(i, 2);
253
	    }
254
   	}
255
	if (bdev->mgr_depth == 4) {
256
            for (i = 0; i < 16; i++) {
257
               clut[i].colnum = i;
258
               clut[i].red    = clut[i].green = clut[i].blue = clut2mgr(bgreytable[i], 4);
259
	    }
260
   	}
261
	if (bdev->mgr_depth == 8) {
262
            for (i = 0; i < 256; i++) {
263
               clut[i].colnum = i;
264
               clut[i].red    = clut[i].green = clut[i].blue = clut2mgr(bgrey256table[i], 8);
265
	    }
266
   	}
267
#if !arch_is_big_endian
268
	swap_bwords( (unsigned char *) clut, sizeof( struct nclut ) * i );
269
#endif
270
	if ( fwrite(&clut, sizeof(struct nclut), i, pstream) < i )
271
            return_error(gs_error_ioerror);
272
	return (code < 0 ? code : 0);
273
}
274
 
275
/* Print a color page. */
276
private int
277
cmgrN_print_page(gx_device_printer *pdev, FILE *pstream)
278
{	mgr_cursor cur;
279
	int i = 0, j, mgr_wide, r, g, b, colors8 = 0;
280
	uint mgr_line_size;
281
	byte *bp, *data, *dp;
282
	ushort prgb[3];
283
	unsigned char table[256], backtable[256];
284
 
285
	int code = mgr_begin_page(bdev, pstream, &cur);
286
	if ( code < 0 ) return code;
287
 
288
	mgr_wide = bdev->width;
289
	if (bdev->mgr_depth == 4 && mgr_wide & 1)
290
            mgr_wide++;
291
	mgr_line_size = mgr_wide / (8 / bdev->mgr_depth);
292
       	data = (byte *)gs_malloc(pdev->memory, mgr_line_size, 1, "cmgrN_print_page");
293
 
294
       	if ( bdev->mgr_depth == 8 ) {
295
            memset( table, 0, sizeof(table) );
296
            for ( r = 0; r <= 6; r++ )
297
		for ( g = 0; g <= 6; g++ )
298
       	            for ( b = 0; b <= 6; b++ )
299
       			if ( r == g && g == b )
300
                            table[ r + (256-7) ] = 1;
301
			else
302
                            table[ (r << 5) + (g << 2) + (b >> 1) ] = 1;
303
            for ( i = j = 0; i < sizeof(table); i++ )
304
		if ( table[i] == 1 ) {
305
                    backtable[i] = j;
306
                    table[j++] = i;
307
		}
308
            colors8 = j;
309
	}
310
	while ( !(code = mgr_next_row(&cur)) )
311
	   {
312
		switch (bdev->mgr_depth) {
313
			case 4:
314
				for (i = 0,dp = data, bp = cur.data; i < mgr_line_size; i++) {
315
					*dp =  *(bp++) << 4;
316
                                    *(dp++) |= *(bp++) & 0x0f;
317
				}
318
                		if ( fwrite(data, sizeof(byte), mgr_line_size, pstream) < mgr_line_size )
319
                                	return_error(gs_error_ioerror);
320
				break;
321
 
322
			case 8:
323
				for (i = 0,bp = cur.data; i < mgr_line_size; i++, bp++)
324
	                              *bp = backtable[*bp] + MGR_RESERVEDCOLORS;
325
                		if ( fwrite(cur.data, sizeof(cur.data[0]), mgr_line_size, pstream) < mgr_line_size )
326
                                	return_error(gs_error_ioerror);
327
				break;
328
		}  
329
	   }
330
       	gs_free(bdev->memory, (char *)data, mgr_line_size, 1, "cmgrN_print_page(done)");
331
 
332
	if (bdev->mgr_depth == 4) {
333
            for (i = 0; i < 16; i++) {
334
               pc_4bit_map_color_rgb((gx_device *)0, (gx_color_index) i, prgb);
335
               clut[i].colnum = i;
336
               clut[i].red    = clut2mgr(prgb[0], 16);
337
               clut[i].green  = clut2mgr(prgb[1], 16);
338
               clut[i].blue   = clut2mgr(prgb[2], 16);
339
	    }
340
   	}
341
	if (bdev->mgr_depth == 8) {
342
            for (i = 0; i < colors8; i++) {
343
               mgr_8bit_map_color_rgb((gx_device *)0, (gx_color_index)
344
                   table[i], prgb);
345
               clut[i].colnum = MGR_RESERVEDCOLORS + i;
346
               clut[i].red    = clut2mgr(prgb[0], 16);
347
               clut[i].green  = clut2mgr(prgb[1], 16);
348
               clut[i].blue   = clut2mgr(prgb[2], 16);
349
	    }
350
   	}
351
#if !arch_is_big_endian
352
	swap_bwords( (unsigned char *) clut, sizeof( struct nclut ) * i );
353
#endif    
354
	if ( fwrite(&clut, sizeof(struct nclut), i, pstream) < i )
355
            return_error(gs_error_ioerror);
356
	return (code < 0 ? code : 0);
357
}
358
 
359
 
360
/* Color mapping routines for 8-bit color with a fixed palette */
361
/* (3 bits of R, 3 bits of G, 2 bits of B). */
362
/* We have to trade off even spacing of colors along each axis */
363
/* against the desire to have real gray shades; */
364
/* MGR compromises by using a 7x7x4 "cube" with extra gray shades */
365
/* (1/6, 1/2, and 5/6), instead of the obvious 8x8x4. */
366
 
367
gx_color_index
368
mgr_8bit_map_rgb_color(gx_device *dev, const gx_color_value cv[])
369
{
370
	uint rv = cv[0] / (gx_max_color_value / 7 + 1);
371
	uint gv = cv[1] / (gx_max_color_value / 7 + 1);
372
	uint bv = cv[2] / (gx_max_color_value / 7 + 1);
373
	return (gx_color_index)
374
		(rv == gv && gv == bv ? rv + (256-7) :
375
		 (rv << 5) + (gv << 2) + (bv >> 1));
376
}
377
int
378
mgr_8bit_map_color_rgb(gx_device *dev, gx_color_index color,
379
  gx_color_value prgb[3])
380
{	static const gx_color_value ramp[8] =
381
	{	0, gx_max_color_value / 6, gx_max_color_value / 3,
382
		gx_max_color_value / 2, 2 * (gx_max_color_value / 3),
383
		5 * (gx_max_color_value / 6), gx_max_color_value,
384
		/* The 8th entry is not actually ever used, */
385
		/* except to fill out the palette. */
386
		gx_max_color_value
387
	};
388
#define icolor (uint)color
389
	if ( icolor >= 256-7 )
390
	{	prgb[0] = prgb[1] = prgb[2] = ramp[icolor - (256-7)];
391
	}
392
	else
393
	{	prgb[0] = ramp[(icolor >> 5) & 7];
394
		prgb[1] = ramp[(icolor >> 2) & 7];
395
		prgb[2] = ramp[(icolor & 3) << 1];
396
	}
397
#undef icolor
398
	return 0;
399
}
400
 
401
 
402
/* convert the 8-bit look-up table into the standard MGR look-up table */
403
private unsigned int
404
clut2mgr(
405
  register int v,		/* value in clut */
406
  register int bits		/* number of bits in clut */
407
)
408
{
409
  register unsigned int i;
410
 
411
  i = (unsigned int) 0xffffffff / ((1<<bits)-1);
412
  return((v*i)/0x10000);
413
}
414
 
415
 
416
/*
417
 * s w a p _ b w o r d s
418
 */
419
private void
420
swap_bwords(register unsigned char *p, int n)
421
{
422
  register unsigned char c;
423
 
424
  n /= 2;
425
 
426
  for (; n > 0; n--, p += 2) {
427
    c    = p[0];
428
    p[0] = p[1];
429
    p[1] = c;
430
  }
431
}