xref: /plan9/sys/src/cmd/gs/src/gdevmac.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1994-2003 artofcode LLC.  All rights reserved.
2 
3   This file is part of Aladdin Ghostscript.
4 
5   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
6   or distributor accepts any responsibility for the consequences of using it,
7   or for whether it serves any particular purpose or works at all, unless he
8   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
9   License (the "License") for full details.
10 
11   Every copy of Aladdin Ghostscript must include a copy of the License,
12   normally in a plain ASCII text file named PUBLIC.  The License grants you
13   the right to copy, modify and redistribute Aladdin Ghostscript, but only
14   under certain conditions described in the License.  Among other things, the
15   License requires that the copyright notice and this notice be preserved on
16   all copies.
17 */
18 
19 /* $Id: gdevmac.c,v 1.8 2003/04/08 12:17:17 giles Exp $ */
20 /* MacOS bitmap output device. This code is superceeded by
21    the newer gsapi_* interface and the DISPLAY device. Please
22    use that instead. See doc/API.htm for more information */
23 
24 #include "gdevmac.h"
25 #include "gsparam.h"
26 #include "gsdll.h"
27 
28 
29 
30 /* The device descriptor */
31 
32 gx_device_procs gs_mac_procs = {
33 	mac_open,							/* open_device */
34 	mac_get_initial_matrix,				/* get_initial_matrix */
35 	mac_sync_output,					/* sync_output */
36 	mac_output_page,					/* output_page */
37 	mac_close,							/* close_device */
38 	gx_default_rgb_map_rgb_color,		/* map_rgb_color */
39 	gx_default_rgb_map_color_rgb,		/* map_color_rgb */
40 	mac_fill_rectangle,					/* fill_rectangle */
41 	NULL,								/* tile_rectangle */
42 	mac_copy_mono,				/* copy_mono */
43 	NULL,//	mac_copy_color,				/* copy_color */
44 	mac_draw_line,				/* draw_line */
45 	NULL,								/* get_bits */
46 	mac_get_params,						/* get_params */
47 	mac_put_params,						/* put_params */
48 	NULL,								/* map_cmyk_color */
49 	mac_get_xfont_procs,				/* get_xfont_procs */
50 	NULL, 								/* get_xfont_device */
51 	NULL, 								/* map_rgb_alpha_color */
52 	gx_page_device_get_page_device,		/* get_page_device */
53 	gx_default_get_alpha_bits, 			/* get_alpha_bits */
54 	mac_copy_alpha,						/* copy_alpha */
55 	NULL,								/* get_band */
56 	NULL,								/* copy_rop */
57 	NULL,								/* fill_path */
58 	NULL,								/* stroke_path */
59 	NULL,								/* fill_mask */
60 	NULL,								/* fill_trapezoid */
61 	NULL,								/* fill_parallelogram */
62 	NULL,								/* fill_triangle */
63 	NULL,								/* draw_thin_line */
64 	NULL,								/* begin_image */
65 	NULL,								/* image_data */
66 	NULL,								/* end_image */
67 	NULL //mac_strip_tile_rectangle			/* strip_tile_rectangle */
68 };
69 
70 
71 
72 /* The instance is public. */
73 
74 gx_device_macos gs_macos_device = {
75 	std_device_color_body(gx_device_macos,
76 						  &gs_mac_procs,
77 						  DEV_MAC_NAME,
78 						  DEFAULT_DEV_WIDTH, /* x and y extent (nominal) */
79 						  DEFAULT_DEV_HEIGHT,
80 	  					  DEFAULT_DEV_DPI,	/* x and y density (nominal) */
81 	  					  DEFAULT_DEV_DPI,
82 	  					  /*dci_color(*/8, 255, 256/*)*/),
83 	{ 0 },			/* std_procs */
84 	"",				/* Output Filename */
85 	NULL,			/* Output File */
86 	NULL,			/* PicHandle to "draw" into */
87 	NULL,			/* PicPtr */
88 	false,			/* outputPage */
89 	false,			/* use XFont interface (render with local TrueType fonts) */
90 	-1,				/* lastFontFace */
91 	-1,				/* lastFontSize */
92 	-1,				/* lastFontID */
93 	0				/* numUsedFonts */
94 };
95 
96 
97 
98 
99 
100 private int
mac_open(register gx_device * dev)101 mac_open(register gx_device *dev)
102 {
103 	gx_device_macos				* mdev = (gx_device_macos *)dev;
104 
105 	static short picHeader[42] = {	0x0000,									// picture size
106 									0x0000, 0x0000, 0x0318, 0x0264,			// bounding rect at 72dpi
107 									0x0011, 0x02ff, 0x0c00, 0xfffe, 0x0000,	// version/header opcodes
108 									0x0048, 0x0000,							// best x resolution
109 									0x0048, 0x0000,							// best y resolution
110 									0x0000, 0x0000, 0x0318, 0x0264,			// optimal src rect at 72dpi
111 									0x0000,									// reserved
112 
113 									0x0000, 0x001e,							// DefHilite
114 									0x0008, 0x0048,							// PenMode
115 									0x001a, 0x0000, 0x0000, 0x0000,			// RGBFgCol = Black
116 									0x001b, 0xFFFF, 0xFFFF, 0xFFFF,			// RGBBkCol = White
117 
118 									0x0001, 0x000A,							// set clipping
119 									0x0000, 0x0000, 0x0318, 0x0264,			// clipping rect
120 									0x0032, 0x0000, 0x0000, 0x0318, 0x0264	// erase rect
121 								};
122 
123 
124 	mac_set_colordepth(dev, mdev->color_info.depth);
125 
126 	mdev->numUsedFonts = 0;
127 	mdev->lastFontFace = -1;
128 	mdev->lastFontSize = -1;
129 	mdev->lastFontID = -1;
130 
131 	mdev->pic		= (PicHandle) NewHandle(500000);
132 	if (mdev->pic == 0)	// error, not enough memory
133 		return gs_error_VMerror;
134 
135 	HLockHi((Handle) mdev->pic);	// move handle high and lock it
136 
137 	mdev->currPicPos	= (short*) *mdev->pic;
138 	memcpy(mdev->currPicPos, picHeader, 42*2);
139 	mdev->currPicPos += 42;
140 
141 	// enter correct dimensions and resolutions
142 	((short*)(*mdev->pic))[ 3]	= mdev->MediaSize[1];
143 	((short*)(*mdev->pic))[ 4]	= mdev->MediaSize[0];
144 
145 	((short*)(*mdev->pic))[16] = ((short*)(*mdev->pic))[35]	= ((short*)(*mdev->pic))[40] = mdev->height;
146 	((short*)(*mdev->pic))[17] = ((short*)(*mdev->pic))[36] = ((short*)(*mdev->pic))[41] = mdev->width;
147 
148 	((short*)(*mdev->pic))[10]	= (((long) X2Fix( mdev->x_pixels_per_inch )) & 0xFFFF0000) >> 16;
149 	((short*)(*mdev->pic))[11]	=  ((long) X2Fix( mdev->x_pixels_per_inch )) & 0x0000FFFF;
150 	((short*)(*mdev->pic))[12]	= (((long) X2Fix( mdev->y_pixels_per_inch )) & 0xFFFF0000) >> 16;
151 	((short*)(*mdev->pic))[13]	=  ((long) X2Fix( mdev->y_pixels_per_inch )) & 0x0000FFFF;
152 
153 	// finish picture, but dont increment pointer, we want to go on drawing
154 	*mdev->currPicPos = 0x00ff;
155 
156 	// notify the caller that a new device was opened
157 	if (pgsdll_callback)
158 		(*pgsdll_callback) (GSDLL_DEVICE, (char *)mdev, 1);
159 
160 	return 0;
161 }
162 
163 
164 
165 private void
mac_get_initial_matrix(register gx_device * dev,register gs_matrix * pmat)166 mac_get_initial_matrix(register gx_device *dev, register gs_matrix *pmat)
167 {
168 	pmat->xx = dev->x_pixels_per_inch /  72.0;
169 	pmat->xy = 0;
170 	pmat->yx = 0;
171 	pmat->yy = dev->y_pixels_per_inch / -72.0;
172 	pmat->tx = 0;
173 	pmat->ty = dev->height;
174 }
175 
176 
177 
178 /* Make the output appear on the screen. */
179 int
mac_sync_output(gx_device * dev)180 mac_sync_output(gx_device * dev)
181 {
182 	gx_device_macos		* mdev = (gx_device_macos *)dev;
183 
184 	// finish picture, but dont increment pointer, we want to go on drawing
185 	*mdev->currPicPos = 0x00ff;
186 
187 	// tell the caller to sync
188 	if (pgsdll_callback)
189 		(*pgsdll_callback) (GSDLL_SYNC, (char *)mdev, 0);
190 
191 	return (0);
192 }
193 
194 
195 
196 int
mac_output_page(gx_device * dev,int copies,int flush)197 mac_output_page(gx_device * dev, int copies, int flush)
198 {
199 	gx_device_macos		* mdev = (gx_device_macos *)dev;
200 	int					code = 0;
201 
202 	mdev->outputPage = true;
203 
204 	if (strcmp(mdev->outputFileName, "")) {
205 		// save file
206 		code = mac_save_pict(dev);
207 	}
208 
209 	// tell the caller that the page is done
210 	if (pgsdll_callback)
211 		(*pgsdll_callback) (GSDLL_PAGE, (char *)mdev, 0);
212 
213 	gx_finish_output_page(dev, copies, flush);
214 
215 	return code;
216 }
217 
218 
219 private int
mac_save_pict(gx_device * dev)220 mac_save_pict(gx_device * dev)
221 {
222 	gx_device_macos		* mdev = (gx_device_macos *)dev;
223 	int					code = 0;
224 	int					i;
225 
226 	if (mdev->outputFile == NULL) {
227 		code = gx_device_open_output_file(dev, mdev->outputFileName, true, true, &(mdev->outputFile));
228 		if (code < 0) return code;
229 	}
230 
231 	for (i=0; i<512; i++) fputc(0, mdev->outputFile);
232 	fwrite(*(mdev->pic), sizeof(char), ((long) mdev->currPicPos - (long) *mdev->pic + 2), mdev->outputFile);
233 
234 	gx_device_close_output_file(dev, mdev->outputFileName, mdev->outputFile);
235 	mdev->outputFile = NULL;
236 
237 	return code;
238 }
239 
240 
241 /* Close the device. */
242 private int
mac_close(register gx_device * dev)243 mac_close(register gx_device *dev)
244 {
245 	gx_device_macos	* mdev = (gx_device_macos *)dev;
246 
247 	long	len;
248 
249 	HUnlock((Handle) mdev->pic);	// no more changes in the pict -> unlock handle
250 	if (strcmp(mdev->outputFileName, "")) {
251 		DisposeHandle((Handle) mdev->pic);
252 		gx_device_close_output_file(dev, mdev->outputFileName, mdev->outputFile);
253 		mdev->outputFile = 0;
254 	} else {
255 		len = (long)mdev->currPicPos - (long)*mdev->pic;
256 		SetHandleSize((Handle) mdev->pic, len + 10);  // +10 just for the case
257 	}
258 
259 	// notify the caller that the device was closed
260 	// it has to dispose the PICT handle when it is ready!
261 	if (pgsdll_callback)
262 		(*pgsdll_callback) (GSDLL_DEVICE, (char *)mdev, 0);
263 
264 	return 0;
265 }
266 
267 
268 
269 /* Fill a rectangle with a color. */
270 private int
mac_fill_rectangle(register gx_device * dev,int x,int y,int w,int h,gx_color_index color)271 mac_fill_rectangle(register gx_device *dev,
272 					  int x, int y, int w, int h,
273 					  gx_color_index color)
274 {
275 	gx_device_macos		* mdev = (gx_device_macos *)dev;
276 
277 	/* ignore a fullpage rect directly after an output_page, this would clear the pict */
278 	if (mdev->outputPage &&
279 			(x == 0) && (y == 0) && (w == mdev->width) && (h == mdev->height)) {
280 		return 0;
281 	}
282 
283 	CheckMem(1024, 100*1024);
284 	ResetPage();
285 
286 	GSSetFgCol(dev, mdev->currPicPos, color);
287 	PICT_fillRect(mdev->currPicPos, x, y, w, h);
288 
289 	PICT_OpEndPicGoOn(mdev->currPicPos);
290 
291 	return 0;
292 }
293 
294 
295 
296 /* Draw a line */
297 private int
mac_draw_line(register gx_device * dev,int x0,int y0,int x1,int y1,gx_color_index color)298 mac_draw_line (register gx_device *dev,
299 				  int x0, int y0,
300 				  int x1, int y1,
301 				  gx_color_index color)
302 {
303 	gx_device_macos		* mdev = (gx_device_macos *)dev;
304 
305 	CheckMem(1024, 100*1024);
306 	ResetPage();
307 
308 	GSSetFgCol(dev, mdev->currPicPos, color);
309 	PICT_Line(mdev->currPicPos, x0, y0, x1, y1);
310 
311 	PICT_OpEndPicGoOn(mdev->currPicPos);
312 
313 	return 0;
314 }
315 
316 
317 
318 /* Copy a monochrome bitmap. */
319 private int
mac_copy_mono(register gx_device * dev,const unsigned char * base,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index color_0,gx_color_index color_1)320 mac_copy_mono (register gx_device *dev,
321 				  const unsigned char *base, int data_x, int raster, gx_bitmap_id id,
322 				  int x, int y, int w, int h,
323 				  gx_color_index color_0, gx_color_index color_1)
324 {
325 	gx_device_macos		* mdev = (gx_device_macos *)dev;
326 
327 	int				byteCount = raster * h;
328 	short			copyMode;
329 
330 	// this case doesn't change the picture -> return without wasting time
331 	if (color_0 == gx_no_color_index && color_1 == gx_no_color_index)
332 		return 0;
333 
334 	fit_copy(dev, base, data_x, raster, id, x, y, w, h);
335 
336 	CheckMem(10*1024 + byteCount*10,  100*1024 + byteCount*10);
337 	ResetPage();
338 
339 	if (color_0 == gx_no_color_index)
340 		copyMode = srcOr;
341 	else if (color_1 == gx_no_color_index)
342 		copyMode = notSrcBic;	// this mode is untested ! (no file found which is using it)
343 	else
344 		copyMode = srcCopy;
345 
346 	copyMode += ditherCopy;
347 
348 	GSSetBkCol(dev, mdev->currPicPos, color_0);
349 	GSSetFgCol(dev, mdev->currPicPos, color_1);
350 
351 	PICTWriteOpcode(mdev->currPicPos, 0x0098);
352 	PICTWriteInt(mdev->currPicPos, raster);
353 	PICTWriteRect(mdev->currPicPos, 0, 0, raster*8, h);
354 	PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
355 	PICTWriteRect(mdev->currPicPos, x, y, w, h);
356 	PICTWriteInt(mdev->currPicPos, copyMode);
357 	PICTWriteDataPackBits(mdev->currPicPos, base, raster, h);
358 
359 	PICT_OpEndPicGoOn(mdev->currPicPos);
360 
361 	return 0;
362 }
363 
364 
365 
366 /* Fill a region with a color and apply a per-pixel alpha-value */
367 /* alpha value is simulated by changed the value to white. Full transparency means white color */
368 /* that's why this will only work on a fully white background!!!! */
369 private int
mac_copy_alpha(gx_device * dev,const unsigned char * base,int data_x,int raster,gx_bitmap_id id,int x,int y,int w,int h,gx_color_index color,int depth)370 mac_copy_alpha(gx_device *dev, const unsigned char *base, int data_x,
371 		   int raster, gx_bitmap_id id, int x, int y, int w, int h,
372 		   gx_color_index color, int depth)
373 {
374 	gx_device_macos		* mdev = (gx_device_macos *)dev;
375 
376 	ColorSpec			*colorTable;
377 	short				copyMode, shade, maxShade = (1 << depth) - 1, byteCount = raster * h;
378 	gx_color_value		rgb[3];
379 	colorHSV			colHSV;
380 	colorRGB			colRGB;
381 	float				saturation, value;
382 
383 	fit_copy(dev, base, data_x, raster, id, x, y, w, h);
384 
385 	CheckMem( byteCount*4 + 200*1024, byteCount*4 + 500*1024 );
386 	ResetPage();
387 
388 	colorTable = (ColorSpec*) malloc(sizeof(ColorSpec) * (maxShade+1));
389 	if (colorTable == NULL)
390 		return gs_error_VMerror;
391 
392 	(*dev_proc(dev, map_color_rgb))(dev, color, rgb);
393 	colRGB.red = rgb[0];
394 	colRGB.green = rgb[1];
395 	colRGB.blue = rgb[2];
396 	mac_convert_rgb_hsv(&colRGB, &colHSV);
397 	saturation = colHSV.s;
398 	value = colHSV.v;
399 
400 	for (shade=0; shade <= maxShade; shade++) {
401 		colorTable[shade].value = maxShade -  shade;
402 
403 		colHSV.s = saturation * (1.0 - (float)shade/(float)maxShade);
404 		colHSV.v = value + ((1.0 - value) * (float)shade/(float)maxShade);
405 
406 		mac_convert_hsv_rgb(&colHSV, &colRGB);
407 		colorTable[shade].rgb.red   = colRGB.red;
408 		colorTable[shade].rgb.green = colRGB.green;
409 		colorTable[shade].rgb.blue  = colRGB.blue;
410 	}
411 	copyMode = srcCopy + ditherCopy;
412 
413 	GSSetStdCol(mdev->currPicPos);
414 
415 	if (raster < 8) {
416 		PICTWriteOpcode(mdev->currPicPos, 0x0090);
417 	} else {
418 		PICTWriteOpcode(mdev->currPicPos, 0x0098);
419 	}
420 	PICTWritePixMap(mdev->currPicPos, 0, 0, raster*8/depth, h, raster, 0, 0,
421 					X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), depth);
422 	PICTWriteColorTable(mdev->currPicPos, 0, maxShade+1, colorTable);
423 	PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
424 	PICTWriteRect(mdev->currPicPos, x, y, w, h);
425 	PICTWriteInt(mdev->currPicPos, copyMode);
426 	PICTWriteDataPackBits(mdev->currPicPos, base, raster, h);
427 
428 	PICT_OpEndPicGoOn(mdev->currPicPos);
429 
430 	free(colorTable);
431 
432 	return 0;
433 }
434 
435 
436 
437 void
mac_convert_rgb_hsv(colorRGB * inRGB,colorHSV * HSV)438 mac_convert_rgb_hsv(colorRGB *inRGB, colorHSV *HSV)
439 {
440 #define NORMALIZE_RGB(col)	((float)col/(float)0xFFFF)
441 
442 	float	min = 1.0, temp;
443 	float	r = NORMALIZE_RGB(inRGB->red),
444 			g = NORMALIZE_RGB(inRGB->green),
445 			b = NORMALIZE_RGB(inRGB->blue);
446 
447 	HSV->h = 0;
448 
449 	HSV->v = r;
450 	if (g > HSV->v) HSV->v = g;
451 	if (b  > HSV->v) HSV->v = b;
452 
453 	min = r;
454 	if (g < min) min = g;
455 	if (b  < min) min = b;
456 
457 	temp = HSV->v - min;
458 
459 	if (HSV->v > 0)
460 		HSV->s = temp / HSV->v;
461 	else
462 		HSV->s = 0;
463 
464 	if (HSV->s > 0) {
465 		float	rd = (HSV->v - r) / temp,
466 				gd = (HSV->v - g) / temp,
467 				bd = (HSV->v - b) / temp;
468 
469 		if (HSV->v == r) {
470 			if (min == g)	HSV->h = 5 + bd;
471 			else			HSV->h = 1 - gd;
472 		} else if (HSV->v == g) {
473 			if (min == b)	HSV->h = 1 + rd;
474 			else			HSV->h = 3 - bd;
475 		} else {
476 			if (min == r)	HSV->h = 3 + gd;
477 			else			HSV->h = 5 - rd;
478 		}
479 
480 		if (HSV->h < 6)		HSV->h *= 60;
481 		else				HSV->h = 0;
482 	}
483 }
484 
485 
486 void
mac_convert_hsv_rgb(colorHSV * inHSV,colorRGB * RGB)487 mac_convert_hsv_rgb(colorHSV *inHSV, colorRGB *RGB)
488 {
489 	if (inHSV->s == 0) {
490 		RGB->red = RGB->green = RGB->blue = inHSV->v * 0xFFFF;
491 	} else {
492 		float	h = inHSV->h / 60;
493 		int		i = trunc(h);
494 		float	fract = h - i;
495 		unsigned short	t1 = (inHSV->v * (1 - inHSV->s)) * 0xFFFF,
496 						t2 = (inHSV->v * (1 - inHSV->s * fract)) * 0xFFFF,
497 						t3 = (inHSV->v * (1 - inHSV->s * (1 - fract))) * 0xFFFF,
498 						v  = inHSV->v * 0xFFFF;
499 
500 		switch(i) {
501 			case 0:		RGB->red   = v;
502 						RGB->green = t3;
503 						RGB->blue  = t1;
504 						break;
505 
506 			case 1:		RGB->red   = t2;
507 						RGB->green = v;
508 						RGB->blue  = t1;
509 						break;
510 
511 			case 2:		RGB->red   = t1;
512 						RGB->green = v;
513 						RGB->blue  = t3;
514 						break;
515 
516 			case 3:		RGB->red   = t1;
517 						RGB->green = t2;
518 						RGB->blue  = v;
519 						break;
520 
521 			case 4:		RGB->red   = t3;
522 						RGB->green = t1;
523 						RGB->blue  = v;
524 						break;
525 
526 			case 5:		RGB->red   = v;
527 						RGB->green = t1;
528 						RGB->blue  = t2;
529 						break;
530 		}
531 	}
532 }
533 
534 
535 
536 // set color info and procedures according to pixeldepth
537 private int
mac_set_colordepth(gx_device * dev,int depth)538 mac_set_colordepth(gx_device *dev, int depth)
539 {
540 	gx_device_macos				* mdev = (gx_device_macos *)dev;
541 	gx_device_color_info		* ci = &mdev->color_info;
542 
543 	if (depth != 1 && depth != 4 && depth != 7 && depth != 8 && depth != 24)
544 		return gs_error_rangecheck;
545 
546 	mdev->color_info.depth = depth;
547 	switch (depth)
548 	{
549 		case 1:		// Black/White
550 			ci->num_components	= 1;
551 			ci->max_gray		= 1;		ci->max_color		= 0;
552 			ci->dither_grays	= 2;		ci->dither_colors	= 0;
553 			set_dev_proc(dev, map_rgb_color, gx_default_b_w_map_rgb_color);
554 			set_dev_proc(dev, map_color_rgb, gx_default_b_w_map_color_rgb);
555 			break;
556 
557 		case 4:		// 4Bit-Gray
558 			ci->num_components	= 1;
559 			ci->max_gray		= 15;		ci->max_color		= 0;
560 			ci->dither_grays	= 16;		ci->dither_colors	= 0;
561 			set_dev_proc(dev, map_rgb_color, gx_default_gray_map_rgb_color);
562 			set_dev_proc(dev, map_color_rgb, gx_default_gray_map_color_rgb);
563 			break;
564 
565 		case 7:		// 8Bit-Gray
566 			ci->depth			= 7;
567 			ci->num_components	= 1;
568 			ci->max_gray		= 255;		ci->max_color		= 0;
569 			ci->dither_grays	= 256;		ci->dither_colors	= 0;
570 			set_dev_proc(dev, map_rgb_color, gx_default_gray_map_rgb_color);
571 			set_dev_proc(dev, map_color_rgb, gx_default_gray_map_color_rgb);
572 			break;
573 
574 		case 8:		// 8Bit-Color
575 			ci->num_components	= 3;
576 			ci->max_gray		= 15;		ci->max_color		= 5;
577 			ci->dither_grays	= 16;		ci->dither_colors	= 6;
578 			set_dev_proc(dev, map_rgb_color, gx_default_rgb_map_rgb_color);
579 			set_dev_proc(dev, map_color_rgb, gx_default_rgb_map_color_rgb);
580 			break;
581 
582 /*		case 16:	// 16Bit-Color
583 			ci->num_components	= 3;
584 			ci->max_gray		= 255;		ci->max_color		= 65535;
585 			ci->dither_grays	= 256;		ci->dither_colors	= 65536;
586 			set_dev_proc(dev, map_rgb_color, gx_default_rgb_map_rgb_color);
587 			set_dev_proc(dev, map_color_rgb, gx_default_rgb_map_color_rgb);
588 			break;
589 */
590 		case 24:	// 24Bit-Color
591 			ci->num_components	= 3;
592 			ci->max_gray		= 255;		ci->max_color		= 16777215;
593 			ci->dither_grays	= 256;		ci->dither_colors	= 16777216;
594 			set_dev_proc(dev, map_rgb_color, gx_default_rgb_map_rgb_color);
595 			set_dev_proc(dev, map_color_rgb, gx_default_rgb_map_color_rgb);
596 			break;
597 	}
598 
599 	return 0;
600 }
601 
602 
603 private int
mac_put_params(gx_device * dev,gs_param_list * plist)604 mac_put_params(gx_device *dev, gs_param_list *plist)
605 {
606 	gx_device_macos		*mdev	= (gx_device_macos *)dev;
607 
608 	int						isOpen = mdev->is_open;
609 	int						code;
610     bool					useXFonts;
611 	int						depth;
612     gs_param_string			outputFile;
613 
614 	// Get the UseExternalFonts Parameter
615 	code = param_read_bool(plist, "UseExternalFonts", &useXFonts);
616 	if (!code)
617 		mdev->useXFonts = useXFonts;
618 
619 	// Get the BitsPerPixel Parameter
620 	code = param_read_int(plist, "BitsPerPixel", &depth);
621 	if (!code) {
622 		code = mac_set_colordepth(dev, depth);
623 		if (code)
624 			param_return_error(plist, "BitsPerPixel", gs_error_rangecheck);
625 	}
626 
627 	// Get OutputFile
628 	code = param_read_string(plist, "OutputFile", &outputFile);
629 	if (code < 0) {
630 		param_signal_error(plist, "OutputFile", code);
631 		return code;
632 	} else if (code == 0) {
633 
634 		if (dev->LockSafetyParams &&
635 			bytes_compare(outputFile.data, outputFile.size,
636 			    (const byte *)mdev->outputFileName, strlen(mdev->outputFileName))) {
637 			param_signal_error(plist, "OutputFile", gs_error_invalidaccess);
638 			return gs_error_invalidaccess;
639 		}
640 		if (outputFile.size > (gp_file_name_sizeof - 1)) {
641 			param_signal_error(plist, "OutputFile", gs_error_limitcheck);
642 			return gs_error_limitcheck;
643 		}
644 
645 		/* If filename changed, close file. */
646 		if (outputFile.data != 0 &&
647 				bytes_compare(outputFile.data, outputFile.size,
648 					(const byte *)mdev->outputFileName, strlen(mdev->outputFileName))) {
649 			/* Close the file if it's open. */
650 			if (mdev->outputFile != NULL) {
651 		    	gx_device_close_output_file(dev, mdev->outputFileName, mdev->outputFile);
652 				memcpy(mdev->outputFileName, outputFile.data, outputFile.size);
653 				mdev->outputFileName[outputFile.size] = 0;
654 				gx_device_open_output_file(dev, mdev->outputFileName, true, true, &(mdev->outputFile));
655 		    } else {
656 				memcpy(mdev->outputFileName, outputFile.data, outputFile.size);
657 				mdev->outputFileName[outputFile.size] = 0;
658 		    }
659 	    }
660 	}
661 
662 	// Get the Default Parameters
663 	mdev->is_open = 0;
664 	code = gx_default_put_params( dev, plist );
665 	mdev->is_open = isOpen;
666 
667 	return code;
668 }
669 
670 
671 private int
mac_get_params(gx_device * dev,gs_param_list * plist)672 mac_get_params(gx_device *dev, gs_param_list *plist)
673 {
674 	gx_device_macos		*mdev	= (gx_device_macos *)dev;
675 
676 	int						code;
677     gs_param_string			outputFile;
678 
679 	code = gx_default_get_params(dev, plist);
680 	if (code < 0)
681 		return code;
682 
683 	// UseExternalFonts
684 	code = param_write_bool(plist, "UseExternalFonts", &(mdev->useXFonts));
685 
686 	// color depth
687 	code = param_write_int(plist, "BitsPerPixel", &(mdev->color_info.depth));
688 
689 	// output file name
690 	outputFile.data = (const byte *) mdev->outputFileName;
691 	outputFile.size = strlen(mdev->outputFileName);
692 	outputFile.persistent = false;
693 	code = param_write_string(plist, "OutputFile", &outputFile);
694 
695 	return code;
696 }
697 
698 
699 
700 /* let the caller get the device PictHandle, he has to draw it to screen */
701 int GSDLLAPI
gsdll_get_pict(unsigned char * dev,PicHandle * thePict)702 gsdll_get_pict(unsigned char *dev, PicHandle *thePict)
703 {
704 	gx_device_macos			* mdev = (gx_device_macos *)dev;
705 
706 	*thePict = mdev->pic;
707 
708 	return 0;
709 }
710 
711 
712 
713 
714 
715 
716 /*************************************************************************************/
717 /*************************************************************************************/
718 /**		Experimental functions!														**/
719 /*************************************************************************************/
720 /*************************************************************************************/
721 
722 
723 
724 
725 #if 0
726 /* NOT FUNCTIONAL !!! */
727 /* Copy a color bitmap. */
728 private int
729 mac_copy_color (register gx_device *dev,
730 				const unsigned char *base, int data_x, int raster,  gx_bitmap_id id,
731 				int x, int y, int w, int h)
732 {
733 	gx_device_macos		* mdev = (gx_device_macos *)dev;
734 
735 	int				byteCount = raster * h, color;
736 	gx_color_value	rgb[3];
737 
738 	fit_copy(dev, base, data_x, raster, id, x, y, w, h);
739 
740 	CheckMem(10*1024 + byteCount*4, 100*1024 + byteCount*4);
741 	ResetPage();
742 
743 	GSSetStdCol(mdev->currPicPos);		// Sets FgCol to Black and BkCol to White
744 
745 	if (mdev->color_info.depth == 24) {
746 		PICTWriteOpcode(mdev->currPicPos, 0x009A);
747 		PICTWriteLong(mdev->currPicPos, 0x000000FF);
748 		PICTWritePixMap(mdev->currPicPos, 0, 0, raster/4, h, raster, 2, 0,
749 						X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), 32);
750 		PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
751 		PICTWriteRect(mdev->currPicPos, x, y, w, h);
752 		PICTWriteInt(mdev->currPicPos, srcCopy);
753 
754 /*		memcpy(mdev->currPicPos, base, byteCount);
755 		(char*)(mdev->currPicPos) += byteCount;*/
756 
757 		{
758 			short	i;
759 			byteCount = 0;
760 
761 			for (i=0; i<raster/4*h; i++) {
762 			//	PICTWriteByte(mdev->currPicPos, 0x00);
763 				PICTWriteByte(mdev->currPicPos, 0x00);
764 				PICTWriteByte(mdev->currPicPos, 0x00);
765 				PICTWriteByte(mdev->currPicPos, 0x00);
766 				byteCount += 3;
767 			}
768 		}
769 
770 		if (byteCount % 2)
771 			PICTWriteFillByte(mdev->currPicPos);
772 
773 	} else if (mdev->color_info.depth <= 8) {
774 		ColorSpec		*colorTable;
775 
776 		colorTable = (ColorSpec*) malloc(sizeof(ColorSpec) * (1 << mdev->color_info.depth));
777 		for (color=0; color < (1 << mdev->color_info.depth); color++) {
778 			(*dev_proc(dev, map_color_rgb))(dev, color, rgb);
779 			colorTable[color].value		= color;
780 			colorTable[color].rgb.red	= rgb[0];
781 			colorTable[color].rgb.green	= rgb[1];
782 			colorTable[color].rgb.blue	= rgb[2];
783 		}
784 
785 		PICTWriteOpcode(mdev->currPicPos, 0x0098);
786 		PICTWritePixMap(mdev->currPicPos, 0, 0, raster*8/mdev->color_info.depth, h, raster, 1, 0,
787 						X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch),
788 						mdev->color_info.depth);
789 		PICTWriteColorTable(mdev->currPicPos, 0, (1 << mdev->color_info.depth), colorTable);
790 		PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
791 		PICTWriteRect(mdev->currPicPos, x, y, w, h);
792 		PICTWriteInt(mdev->currPicPos, srcCopy);
793 
794 		PICTWriteDataPackBits(mdev->currPicPos, base, raster, h);
795 
796 		free(colorTable);
797 	} else {
798 		gx_default_copy_color( dev, base, data_x, raster, id, x, y, w, h );
799 	}
800 
801 	PICT_OpEndPicGoOn(mdev->currPicPos);
802 
803 	return 0;
804 }
805 #endif
806 
807 
808 
809 #if 0
810 /* tile a rectangle with a bitmap or pixmap */
811 private int
812 mac_strip_tile_rectangle(register gx_device *dev, const gx_strip_bitmap *tile,
813 						 int x, int y, int w, int h,
814 						 gx_color_index color_0, gx_color_index color_1,
815 						 int phase_x, int phase_y)
816 {
817 	gx_device_macos		* mdev = (gx_device_macos *)dev;
818 
819 	int					byteCount = tile->raster * tile->size.y;
820 /*
821 	// tile is a pixmap
822 	if (color_0 == gx_no_color_index && color_1 == gx_no_color_index)
823 		return 0;// gx_default_strip_tile_rectangle(dev, tile, x, y, w, h, color_0, color_1, phase_x, phase_y);
824 
825 	if (color_0 != gx_no_color_index && color_1 != gx_no_color_index) {
826 		// monochrome tiles
827 		if (phase_x != 0 ||�phase_y != 0 || tile->shift != 0 ||
828 				tile->strip_height != 0 ||�tile->strip_shift != 0) {
829 			return gx_default_strip_tile_rectangle(dev, tile, x, y, w, h, color_0, color_1, phase_x, phase_y);
830 		}
831 
832 	} else {
833 		return 0;//gx_default_strip_tile_rectangle(dev, tile, x, y, w, h, color_0, color_1, phase_x, phase_y);
834 	}
835 */
836 }
837 #endif
838 
839 
840 
841 
842 
843 
844 
845 
846 
847 
848