/* Copyright (C) 2001-2006 Artifex Software, Inc.
   All Rights Reserved.
  
   This software is provided AS-IS with no warranty, either express or
   implied.

   This software is distributed under license and may not be copied, modified
   or distributed except as expressly authorized under the terms of that
   license.  Refer to licensing information at http://www.artifex.com/
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
*/

/* $Id: gdevmac.c 8766 2008-05-21 19:46:43Z giles $ */
/* MacOS bitmap output device. This code is superceeded by
   the newer gsapi_* interface and the DISPLAY device. Please
   use that instead. See doc/API.htm for more information */
   
#include "gdevmac.h"
#include "gsparam.h"
#include "gsdll.h"



/* The device descriptor */

gx_device_procs gs_mac_procs = {
	mac_open,							/* open_device */
	mac_get_initial_matrix,				/* get_initial_matrix */
	mac_sync_output,					/* sync_output */
	mac_output_page,					/* output_page */
	mac_close,							/* close_device */
	gx_default_rgb_map_rgb_color,		/* map_rgb_color */
	gx_default_rgb_map_color_rgb,		/* map_color_rgb */
	mac_fill_rectangle,					/* fill_rectangle */
	NULL,								/* tile_rectangle */
	mac_copy_mono,				/* copy_mono */
	NULL,//	mac_copy_color,				/* copy_color */
	mac_draw_line,				/* draw_line */
	NULL,								/* get_bits */
	mac_get_params,						/* get_params */
	mac_put_params,						/* put_params */
	NULL,								/* map_cmyk_color */
	mac_get_xfont_procs,				/* get_xfont_procs */
	NULL, 								/* get_xfont_device */
	NULL, 								/* map_rgb_alpha_color */
	gx_page_device_get_page_device,		/* get_page_device */
	gx_default_get_alpha_bits, 			/* get_alpha_bits */
	mac_copy_alpha,						/* copy_alpha */
	NULL,								/* get_band */
	NULL,								/* copy_rop */
	NULL,								/* fill_path */
	NULL,								/* stroke_path */
	NULL,								/* fill_mask */
	NULL,								/* fill_trapezoid */
	NULL,								/* fill_parallelogram */
	NULL,								/* fill_triangle */
	NULL,								/* draw_thin_line */
	NULL,								/* begin_image */
	NULL,								/* image_data */
	NULL,								/* end_image */
	NULL //mac_strip_tile_rectangle			/* strip_tile_rectangle */
};



/* The instance is public. */

gx_device_macos gs_macos_device = {
	std_device_color_body(gx_device_macos,
						  &gs_mac_procs,
						  DEV_MAC_NAME,
						  DEFAULT_DEV_WIDTH, /* x and y extent (nominal) */
						  DEFAULT_DEV_HEIGHT,
	  					  DEFAULT_DEV_DPI,	/* x and y density (nominal) */
	  					  DEFAULT_DEV_DPI,
	  					  /*dci_color(*/8, 255, 256/*)*/),
	{ 0 },			/* std_procs */
	"",				/* Output Filename */
	NULL,			/* Output File */
	NULL,			/* PicHandle to "draw" into */
	NULL,			/* PicPtr */
	false,			/* outputPage */
	false,			/* use XFont interface (render with local TrueType fonts) */
	-1,				/* lastFontFace */
	-1,				/* lastFontSize */
	-1,				/* lastFontID */
	0				/* numUsedFonts */
};





static int
mac_open(register gx_device *dev)
{
	gx_device_macos				* mdev = (gx_device_macos *)dev;
	
	static short picHeader[42] = {	0x0000,									// picture size
									0x0000, 0x0000, 0x0318, 0x0264,			// bounding rect at 72dpi
									0x0011, 0x02ff, 0x0c00, 0xfffe, 0x0000,	// version/header opcodes
									0x0048, 0x0000,							// best x resolution
									0x0048, 0x0000,							// best y resolution
									0x0000, 0x0000, 0x0318, 0x0264,			// optimal src rect at 72dpi
									0x0000,									// reserved
									
									0x0000, 0x001e,							// DefHilite
									0x0008, 0x0048,							// PenMode
									0x001a, 0x0000, 0x0000, 0x0000,			// RGBFgCol = Black
									0x001b, 0xFFFF, 0xFFFF, 0xFFFF,			// RGBBkCol = White
									
									0x0001, 0x000A,							// set clipping
									0x0000, 0x0000, 0x0318, 0x0264,			// clipping rect
									0x0032, 0x0000, 0x0000, 0x0318, 0x0264	// erase rect
								};

	
	mac_set_colordepth(dev, mdev->color_info.depth);
	
	mdev->numUsedFonts = 0;
	mdev->lastFontFace = -1;
	mdev->lastFontSize = -1;
	mdev->lastFontID = -1;
	
	mdev->pic		= (PicHandle) NewHandle(500000);
	if (mdev->pic == 0)	// error, not enough memory
		return gs_error_VMerror;
	
	HLockHi((Handle) mdev->pic);	// move handle high and lock it
	
	mdev->currPicPos	= (short*) *mdev->pic;
	memcpy(mdev->currPicPos, picHeader, 42*2);
	mdev->currPicPos += 42;
	
	// enter correct dimensions and resolutions
	((short*)(*mdev->pic))[ 3]	= mdev->MediaSize[1];
	((short*)(*mdev->pic))[ 4]	= mdev->MediaSize[0];
	
	((short*)(*mdev->pic))[16] = ((short*)(*mdev->pic))[35]	= ((short*)(*mdev->pic))[40] = mdev->height;
	((short*)(*mdev->pic))[17] = ((short*)(*mdev->pic))[36] = ((short*)(*mdev->pic))[41] = mdev->width;
	
	((short*)(*mdev->pic))[10]	= (((long) X2Fix( mdev->x_pixels_per_inch )) & 0xFFFF0000) >> 16;
	((short*)(*mdev->pic))[11]	=  ((long) X2Fix( mdev->x_pixels_per_inch )) & 0x0000FFFF;
	((short*)(*mdev->pic))[12]	= (((long) X2Fix( mdev->y_pixels_per_inch )) & 0xFFFF0000) >> 16;
	((short*)(*mdev->pic))[13]	=  ((long) X2Fix( mdev->y_pixels_per_inch )) & 0x0000FFFF;
	
	// finish picture, but dont increment pointer, we want to go on drawing
	*mdev->currPicPos = 0x00ff;
	
	// notify the caller that a new device was opened
	if (pgsdll_callback)
		(*pgsdll_callback) (GSDLL_DEVICE, (char *)mdev, 1);
	
	return 0;
}



static void
mac_get_initial_matrix(register gx_device *dev, register gs_matrix *pmat)
{
	pmat->xx = dev->x_pixels_per_inch /  72.0;
	pmat->xy = 0;
	pmat->yx = 0;
	pmat->yy = dev->y_pixels_per_inch / -72.0;
	pmat->tx = 0;
	pmat->ty = dev->height;
}



/* Make the output appear on the screen. */
int
mac_sync_output(gx_device * dev)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	
	// finish picture, but dont increment pointer, we want to go on drawing
	*mdev->currPicPos = 0x00ff;
	
	// tell the caller to sync
	if (pgsdll_callback)
		(*pgsdll_callback) (GSDLL_SYNC, (char *)mdev, 0);
	
	return (0);
}



int
mac_output_page(gx_device * dev, int copies, int flush)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	int					code = 0;
	
	mdev->outputPage = true;
	
	if (strcmp(mdev->outputFileName, "")) {
		// save file
		code = mac_save_pict(dev);
	}
	
	// tell the caller that the page is done
	if (pgsdll_callback)
		(*pgsdll_callback) (GSDLL_PAGE, (char *)mdev, 0);
	
	gx_finish_output_page(dev, copies, flush);
	
	return code;
}


static int
mac_save_pict(gx_device * dev)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	int					code = 0;
	int					i;
	
	if (mdev->outputFile == NULL) {
		code = gx_device_open_output_file(dev, mdev->outputFileName, true, true, &(mdev->outputFile));
		if (code < 0) return code;
	}
	
	for (i=0; i<512; i++) fputc(0, mdev->outputFile);
	fwrite(*(mdev->pic), sizeof(char), ((long) mdev->currPicPos - (long) *mdev->pic + 2), mdev->outputFile);
	
	gx_device_close_output_file(dev, mdev->outputFileName, mdev->outputFile);
	mdev->outputFile = NULL;
	
	return code;
}


/* Close the device. */
static int
mac_close(register gx_device *dev)
{
	gx_device_macos	* mdev = (gx_device_macos *)dev;
	
	long	len;
	
	HUnlock((Handle) mdev->pic);	// no more changes in the pict -> unlock handle
	if (strcmp(mdev->outputFileName, "")) {
		DisposeHandle((Handle) mdev->pic);
		gx_device_close_output_file(dev, mdev->outputFileName, mdev->outputFile);
		mdev->outputFile = 0;
	} else {
		len = (long)mdev->currPicPos - (long)*mdev->pic;
		SetHandleSize((Handle) mdev->pic, len + 10);  // +10 just for the case
	}
	
	// notify the caller that the device was closed
	// it has to dispose the PICT handle when it is ready!
	if (pgsdll_callback)
		(*pgsdll_callback) (GSDLL_DEVICE, (char *)mdev, 0);
	
	return 0;
}



/* Fill a rectangle with a color. */
static int
mac_fill_rectangle(register gx_device *dev,
					  int x, int y, int w, int h,
					  gx_color_index color)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	
	/* ignore a fullpage rect directly after an output_page, this would clear the pict */
	if (mdev->outputPage &&
			(x == 0) && (y == 0) && (w == mdev->width) && (h == mdev->height)) {
		return 0;
	}
	
	CheckMem(1024, 100*1024);
	ResetPage();
	
	GSSetFgCol(dev, mdev->currPicPos, color);
	PICT_fillRect(mdev->currPicPos, x, y, w, h);
	
	PICT_OpEndPicGoOn(mdev->currPicPos);
	
	return 0;
}



/* Draw a line */
static int
mac_draw_line (register gx_device *dev,
				  int x0, int y0,
				  int x1, int y1,
				  gx_color_index color)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	
	CheckMem(1024, 100*1024);
	ResetPage();
	
	GSSetFgCol(dev, mdev->currPicPos, color);
	PICT_Line(mdev->currPicPos, x0, y0, x1, y1);
	
	PICT_OpEndPicGoOn(mdev->currPicPos);
	
	return 0;
}



/* Copy a monochrome bitmap. */
static 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)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	
	int				byteCount = raster * h;
	short			copyMode;
	
	// this case doesn't change the picture -> return without wasting time
	if (color_0 == gx_no_color_index && color_1 == gx_no_color_index)
		return 0;
	
	fit_copy(dev, base, data_x, raster, id, x, y, w, h);
	
	CheckMem(10*1024 + byteCount*10,  100*1024 + byteCount*10);
	ResetPage();
	
	if (color_0 == gx_no_color_index)
		copyMode = srcOr;
	else if (color_1 == gx_no_color_index)
		copyMode = notSrcBic;	// this mode is untested ! (no file found which is using it)
	else
		copyMode = srcCopy;
	
	copyMode += ditherCopy;
	
	GSSetBkCol(dev, mdev->currPicPos, color_0);
	GSSetFgCol(dev, mdev->currPicPos, color_1);
	
	PICTWriteOpcode(mdev->currPicPos, 0x0098);
	PICTWriteInt(mdev->currPicPos, raster);
	PICTWriteRect(mdev->currPicPos, 0, 0, raster*8, h);
	PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
	PICTWriteRect(mdev->currPicPos, x, y, w, h);
	PICTWriteInt(mdev->currPicPos, copyMode);
	PICTWriteDataPackBits(mdev->currPicPos, base, raster, h);
	
	PICT_OpEndPicGoOn(mdev->currPicPos);
	
	return 0;
}



/* Fill a region with a color and apply a per-pixel alpha-value */
/* alpha value is simulated by changed the value to white. Full transparency means white color */
/* that's why this will only work on a fully white background!!!! */
static 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)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	
	ColorSpec			*colorTable;
	short				copyMode, shade, maxShade = (1 << depth) - 1, byteCount = raster * h;
	gx_color_value		rgb[3];
	colorHSV			colHSV;
	colorRGB			colRGB;
	float				saturation, value;
	
	fit_copy(dev, base, data_x, raster, id, x, y, w, h);
	
	CheckMem( byteCount*4 + 200*1024, byteCount*4 + 500*1024 );
	ResetPage();
	
	colorTable = (ColorSpec*) malloc(sizeof(ColorSpec) * (maxShade+1));
	if (colorTable == NULL)
		return gs_error_VMerror;
	
	(*dev_proc(dev, map_color_rgb))(dev, color, rgb);
	colRGB.red = rgb[0];
	colRGB.green = rgb[1];
	colRGB.blue = rgb[2];
	mac_convert_rgb_hsv(&colRGB, &colHSV);
	saturation = colHSV.s;
	value = colHSV.v;
	
	for (shade=0; shade <= maxShade; shade++) {
		colorTable[shade].value = maxShade -  shade;
		
		colHSV.s = saturation * (1.0 - (float)shade/(float)maxShade);
		colHSV.v = value + ((1.0 - value) * (float)shade/(float)maxShade);
		
		mac_convert_hsv_rgb(&colHSV, &colRGB);
		colorTable[shade].rgb.red   = colRGB.red;
		colorTable[shade].rgb.green = colRGB.green;
		colorTable[shade].rgb.blue  = colRGB.blue;
	}
	copyMode = srcCopy + ditherCopy;
	
	GSSetStdCol(mdev->currPicPos);
	
	if (raster < 8) {
		PICTWriteOpcode(mdev->currPicPos, 0x0090);
	} else {
		PICTWriteOpcode(mdev->currPicPos, 0x0098);
	}
	PICTWritePixMap(mdev->currPicPos, 0, 0, raster*8/depth, h, raster, 0, 0,
					X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), depth);
	PICTWriteColorTable(mdev->currPicPos, 0, maxShade+1, colorTable);
	PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
	PICTWriteRect(mdev->currPicPos, x, y, w, h);
	PICTWriteInt(mdev->currPicPos, copyMode);
	PICTWriteDataPackBits(mdev->currPicPos, base, raster, h);
	
	PICT_OpEndPicGoOn(mdev->currPicPos);
	
	free(colorTable);
	
	return 0;
}



void
mac_convert_rgb_hsv(colorRGB *inRGB, colorHSV *HSV)
{
#define NORMALIZE_RGB(col)	((float)col/(float)0xFFFF)
	
	float	min = 1.0, temp;
	float	r = NORMALIZE_RGB(inRGB->red),
			g = NORMALIZE_RGB(inRGB->green),
			b = NORMALIZE_RGB(inRGB->blue);
	
	HSV->h = 0;
	
	HSV->v = r;
	if (g > HSV->v) HSV->v = g;
	if (b  > HSV->v) HSV->v = b;
	
	min = r;
	if (g < min) min = g;
	if (b  < min) min = b;
	
	temp = HSV->v - min;
	
	if (HSV->v > 0)
		HSV->s = temp / HSV->v;
	else
		HSV->s = 0;
	
	if (HSV->s > 0) {
		float	rd = (HSV->v - r) / temp,
				gd = (HSV->v - g) / temp,
				bd = (HSV->v - b) / temp;
		
		if (HSV->v == r) {
			if (min == g)	HSV->h = 5 + bd;
			else			HSV->h = 1 - gd;
		} else if (HSV->v == g) {
			if (min == b)	HSV->h = 1 + rd;
			else			HSV->h = 3 - bd;
		} else {
			if (min == r)	HSV->h = 3 + gd;
			else			HSV->h = 5 - rd;
		}
		
		if (HSV->h < 6)		HSV->h *= 60;
		else				HSV->h = 0;
	}
}


void
mac_convert_hsv_rgb(colorHSV *inHSV, colorRGB *RGB)
{
	if (inHSV->s == 0) {
		RGB->red = RGB->green = RGB->blue = inHSV->v * 0xFFFF;
	} else {
		float	h = inHSV->h / 60;
		int		i = trunc(h);
		float	fract = h - i;
		unsigned short	t1 = (inHSV->v * (1 - inHSV->s)) * 0xFFFF,
						t2 = (inHSV->v * (1 - inHSV->s * fract)) * 0xFFFF,
						t3 = (inHSV->v * (1 - inHSV->s * (1 - fract))) * 0xFFFF,
						v  = inHSV->v * 0xFFFF;
		
		switch(i) {
			case 0:		RGB->red   = v;
						RGB->green = t3;
						RGB->blue  = t1;
						break;
						
			case 1:		RGB->red   = t2;
						RGB->green = v;
						RGB->blue  = t1;
						break;
						
			case 2:		RGB->red   = t1;
						RGB->green = v;
						RGB->blue  = t3;
						break;
						
			case 3:		RGB->red   = t1;
						RGB->green = t2;
						RGB->blue  = v;
						break;
						
			case 4:		RGB->red   = t3;
						RGB->green = t1;
						RGB->blue  = v;
						break;
						
			case 5:		RGB->red   = v;
						RGB->green = t1;
						RGB->blue  = t2;
						break;
		}
	}
}



// set color info and procedures according to pixeldepth
static int
mac_set_colordepth(gx_device *dev, int depth)
{
	gx_device_macos				* mdev = (gx_device_macos *)dev;
	gx_device_color_info		* ci = &mdev->color_info;
	
	if (depth != 1 && depth != 4 && depth != 7 && depth != 8 && depth != 24)
		return gs_error_rangecheck;
	
	mdev->color_info.depth = depth;
	switch (depth)
	{
		case 1:		// Black/White
			ci->num_components	= 1;
			ci->max_gray		= 1;		ci->max_color		= 0;
			ci->dither_grays	= 2;		ci->dither_colors	= 0;
			set_dev_proc(dev, map_rgb_color, gx_default_b_w_map_rgb_color);
			set_dev_proc(dev, map_color_rgb, gx_default_b_w_map_color_rgb);
			break;
			
		case 4:		// 4Bit-Gray
			ci->num_components	= 1;
			ci->max_gray		= 15;		ci->max_color		= 0;
			ci->dither_grays	= 16;		ci->dither_colors	= 0;
			set_dev_proc(dev, map_rgb_color, gx_default_gray_map_rgb_color);
			set_dev_proc(dev, map_color_rgb, gx_default_gray_map_color_rgb);
			break;
		
		case 7:		// 8Bit-Gray
			ci->depth			= 7;
			ci->num_components	= 1;
			ci->max_gray		= 255;		ci->max_color		= 0;
			ci->dither_grays	= 256;		ci->dither_colors	= 0;
			set_dev_proc(dev, map_rgb_color, gx_default_gray_map_rgb_color);
			set_dev_proc(dev, map_color_rgb, gx_default_gray_map_color_rgb);
			break;
		
		case 8:		// 8Bit-Color
			ci->num_components	= 3;
			ci->max_gray		= 15;		ci->max_color		= 5;
			ci->dither_grays	= 16;		ci->dither_colors	= 6;
			set_dev_proc(dev, map_rgb_color, gx_default_rgb_map_rgb_color);
			set_dev_proc(dev, map_color_rgb, gx_default_rgb_map_color_rgb);
			break;
		
/*		case 16:	// 16Bit-Color
			ci->num_components	= 3;
			ci->max_gray		= 255;		ci->max_color		= 65535;
			ci->dither_grays	= 256;		ci->dither_colors	= 65536;
			set_dev_proc(dev, map_rgb_color, gx_default_rgb_map_rgb_color);
			set_dev_proc(dev, map_color_rgb, gx_default_rgb_map_color_rgb);
			break;
*/		
		case 24:	// 24Bit-Color
			ci->num_components	= 3;
			ci->max_gray		= 255;		ci->max_color		= 16777215;
			ci->dither_grays	= 256;		ci->dither_colors	= 16777216;
			set_dev_proc(dev, map_rgb_color, gx_default_rgb_map_rgb_color);
			set_dev_proc(dev, map_color_rgb, gx_default_rgb_map_color_rgb);
			break;
	}
	
	return 0;
}


static int
mac_put_params(gx_device *dev, gs_param_list *plist)
{	
	gx_device_macos		*mdev	= (gx_device_macos *)dev;
	
	int						isOpen = mdev->is_open;
	int						code;
    bool					useXFonts;
	int						depth;
    gs_param_string			outputFile;
	
	// Get the UseExternalFonts Parameter
	code = param_read_bool(plist, "UseExternalFonts", &useXFonts);
	if (!code)
		mdev->useXFonts = useXFonts;
	
	// Get the BitsPerPixel Parameter
	code = param_read_int(plist, "BitsPerPixel", &depth);
	if (!code) {
		code = mac_set_colordepth(dev, depth);
		if (code)
			param_return_error(plist, "BitsPerPixel", gs_error_rangecheck);
	}
	
	// Get OutputFile
	code = param_read_string(plist, "OutputFile", &outputFile);
	if (code < 0) {
		param_signal_error(plist, "OutputFile", code);
		return code;
	} else if (code == 0) {
		
		if (dev->LockSafetyParams &&
			bytes_compare(outputFile.data, outputFile.size,
			    (const byte *)mdev->outputFileName, strlen(mdev->outputFileName))) {
			param_signal_error(plist, "OutputFile", gs_error_invalidaccess);
			return gs_error_invalidaccess;
		}
		if (outputFile.size > (gp_file_name_sizeof - 1)) {
			param_signal_error(plist, "OutputFile", gs_error_limitcheck);
			return gs_error_limitcheck;
		}
		
		/* If filename changed, close file. */
		if (outputFile.data != 0 &&
				bytes_compare(outputFile.data, outputFile.size,
					(const byte *)mdev->outputFileName, strlen(mdev->outputFileName))) {
			/* Close the file if it's open. */
			if (mdev->outputFile != NULL) {
		    	gx_device_close_output_file(dev, mdev->outputFileName, mdev->outputFile);
				memcpy(mdev->outputFileName, outputFile.data, outputFile.size);
				mdev->outputFileName[outputFile.size] = 0;
				gx_device_open_output_file(dev, mdev->outputFileName, true, true, &(mdev->outputFile));
		    } else {
				memcpy(mdev->outputFileName, outputFile.data, outputFile.size);
				mdev->outputFileName[outputFile.size] = 0;
		    }
	    }
	}
	
	// Get the Default Parameters
	mdev->is_open = 0;
	code = gx_default_put_params( dev, plist );
	mdev->is_open = isOpen;
	
	return code;
}


static int
mac_get_params(gx_device *dev, gs_param_list *plist)
{
	gx_device_macos		*mdev	= (gx_device_macos *)dev;
	
	int						code;
    gs_param_string			outputFile;
	
	code = gx_default_get_params(dev, plist);
	if (code < 0)
		return code;
	
	// UseExternalFonts
	code = param_write_bool(plist, "UseExternalFonts", &(mdev->useXFonts));
	
	// color depth
	code = param_write_int(plist, "BitsPerPixel", &(mdev->color_info.depth));
	
	// output file name
	outputFile.data = (const byte *) mdev->outputFileName;
	outputFile.size = strlen(mdev->outputFileName);
	outputFile.persistent = false;
	code = param_write_string(plist, "OutputFile", &outputFile);
	
	return code;
}



/* let the caller get the device PictHandle, he has to draw it to screen */
int GSDLLAPI
gsdll_get_pict(unsigned char *dev, PicHandle *thePict)
{
	gx_device_macos			* mdev = (gx_device_macos *)dev;
	
	*thePict = mdev->pic;
	
	return 0;
}






/*************************************************************************************/
/*************************************************************************************/
/**		Experimental functions!														**/
/*************************************************************************************/
/*************************************************************************************/




#if 0
/* NOT FUNCTIONAL !!! */
/* Copy a color bitmap. */
static int
mac_copy_color (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_device_macos		* mdev = (gx_device_macos *)dev;
	
	int				byteCount = raster * h, color;
	gx_color_value	rgb[3];
	
	fit_copy(dev, base, data_x, raster, id, x, y, w, h);
	
	CheckMem(10*1024 + byteCount*4, 100*1024 + byteCount*4);
	ResetPage();
	
	GSSetStdCol(mdev->currPicPos);		// Sets FgCol to Black and BkCol to White
	
	if (mdev->color_info.depth == 24) {
		PICTWriteOpcode(mdev->currPicPos, 0x009A);
		PICTWriteLong(mdev->currPicPos, 0x000000FF);
		PICTWritePixMap(mdev->currPicPos, 0, 0, raster/4, h, raster, 2, 0,
						X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), 32);
		PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
		PICTWriteRect(mdev->currPicPos, x, y, w, h);
		PICTWriteInt(mdev->currPicPos, srcCopy);
		
/*		memcpy(mdev->currPicPos, base, byteCount);
		(char*)(mdev->currPicPos) += byteCount;*/
		
		{
			short	i;
			byteCount = 0;
			
			for (i=0; i<raster/4*h; i++) {
			//	PICTWriteByte(mdev->currPicPos, 0x00);
				PICTWriteByte(mdev->currPicPos, 0x00);
				PICTWriteByte(mdev->currPicPos, 0x00);
				PICTWriteByte(mdev->currPicPos, 0x00);
				byteCount += 3;
			}
		}
		
		if (byteCount % 2)
			PICTWriteFillByte(mdev->currPicPos);
		
	} else if (mdev->color_info.depth <= 8) {
		ColorSpec		*colorTable;
		
		colorTable = (ColorSpec*) malloc(sizeof(ColorSpec) * (1 << mdev->color_info.depth));
		for (color=0; color < (1 << mdev->color_info.depth); color++) {
			(*dev_proc(dev, map_color_rgb))(dev, color, rgb);
			colorTable[color].value		= color;
			colorTable[color].rgb.red	= rgb[0];
			colorTable[color].rgb.green	= rgb[1];
			colorTable[color].rgb.blue	= rgb[2];
		}
		
		PICTWriteOpcode(mdev->currPicPos, 0x0098);
		PICTWritePixMap(mdev->currPicPos, 0, 0, raster*8/mdev->color_info.depth, h, raster, 1, 0,
						X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch),
						mdev->color_info.depth);
		PICTWriteColorTable(mdev->currPicPos, 0, (1 << mdev->color_info.depth), colorTable);
		PICTWriteRect(mdev->currPicPos, data_x, 0, w, h);
		PICTWriteRect(mdev->currPicPos, x, y, w, h);
		PICTWriteInt(mdev->currPicPos, srcCopy);
		
		PICTWriteDataPackBits(mdev->currPicPos, base, raster, h);
		
		free(colorTable);
	} else {
		gx_default_copy_color( dev, base, data_x, raster, id, x, y, w, h );
	}
	
	PICT_OpEndPicGoOn(mdev->currPicPos);
	
	return 0;
}
#endif



#if 0
/* tile a rectangle with a bitmap or pixmap */
static int
mac_strip_tile_rectangle(register gx_device *dev, const gx_strip_bitmap *tile,
						 int x, int y, int w, int h,
						 gx_color_index color_0, gx_color_index color_1,
						 int phase_x, int phase_y)
{
	gx_device_macos		* mdev = (gx_device_macos *)dev;
	
	int					byteCount = tile->raster * tile->size.y;
/*	
	// tile is a pixmap
	if (color_0 == gx_no_color_index && color_1 == gx_no_color_index)
		return 0;// gx_default_strip_tile_rectangle(dev, tile, x, y, w, h, color_0, color_1, phase_x, phase_y);
	
	if (color_0 != gx_no_color_index && color_1 != gx_no_color_index) {
		// monochrome tiles
		if (phase_x != 0 ||Ęphase_y != 0 || tile->shift != 0 ||
				tile->strip_height != 0 ||Ętile->strip_shift != 0) {
			return gx_default_strip_tile_rectangle(dev, tile, x, y, w, h, color_0, color_1, phase_x, phase_y);
		}
		
	} else {
		return 0;//gx_default_strip_tile_rectangle(dev, tile, x, y, w, h, color_0, color_1, phase_x, phase_y);
	}
*/
}
#endif   










