848 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			848 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $Xorg: PclColor.c,v 1.3 2000/08/17 19:48:07 cpqbld Exp $ */
 | |
| /*******************************************************************
 | |
| **
 | |
| **    *********************************************************
 | |
| **    *
 | |
| **    *  File:		PclColorInit.c
 | |
| **    *
 | |
| **    *  Contents:
 | |
| **    *                 Colormap handing code of Pcl driver for the 
 | |
| **    *                 print server.
 | |
| **    *
 | |
| **    *  Created:	4/8/96
 | |
| **    *
 | |
| **    *********************************************************
 | |
| ** 
 | |
| ********************************************************************/
 | |
| /*
 | |
| (c) Copyright 1996 Hewlett-Packard Company
 | |
| (c) Copyright 1996 International Business Machines Corp.
 | |
| (c) Copyright 1996 Sun Microsystems, Inc.
 | |
| (c) Copyright 1996 Novell, Inc.
 | |
| (c) Copyright 1996 Digital Equipment Corp.
 | |
| (c) Copyright 1996 Fujitsu Limited
 | |
| (c) Copyright 1996 Hitachi, Ltd.
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| of this software and associated documentation files (the "Software"), to deal
 | |
| in the Software without restriction, including without limitation the rights
 | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in
 | |
| all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | |
| IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| Except as contained in this notice, the names of the copyright holders shall
 | |
| not be used in advertising or otherwise to promote the sale, use or other
 | |
| dealings in this Software without prior written authorization from said
 | |
| copyright holders.
 | |
| */
 | |
| /* $XFree86: xc/programs/Xserver/Xprint/pcl/PclColor.c,v 1.9tsi Exp $ */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <stdlib.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/wait.h>
 | |
| #include <unistd.h>
 | |
| #include <math.h>
 | |
| 
 | |
| #include "colormapst.h"
 | |
| #include "windowstr.h"
 | |
| #include "resource.h"
 | |
| 
 | |
| #include "Pcl.h"
 | |
| #include "cfb.h"
 | |
| 
 | |
| static void lookup(unsigned char *src,
 | |
| 		unsigned char *dst,
 | |
| 		int num,
 | |
| 		unsigned char *map,
 | |
| 		int dim);
 | |
| static void trilinear(unsigned char *p,
 | |
| 		unsigned char *out,
 | |
| 		unsigned char *d,
 | |
| 		int dim,
 | |
| 		unsigned char def);
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * This seems to be (and is) a duplication of effort; one would think
 | |
|  * that cfbCreateDefColormap would be sufficient.  It almost is.  The
 | |
|  * only change made in this function is that the black and white pixels
 | |
|  * are allocated with three separate variables for red, green and blue
 | |
|  * values, instead of the single variable in cfbCreateDefColormap.  The
 | |
|  * single variable leads to the one value being corrected by
 | |
|  * ResolveColor three times, which leads to incorrect colors.
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| PclCreateDefColormap(ScreenPtr pScreen)
 | |
| {
 | |
|     unsigned short wp_red = ~0, wp_green = ~0, wp_blue = ~0;
 | |
|     unsigned short bp_red = 0, bp_green = 0, bp_blue = 0;
 | |
|     VisualPtr	pVisual;
 | |
|     ColormapPtr	cmap;
 | |
|     Pixel wp, bp;
 | |
|     
 | |
|     for (pVisual = pScreen->visuals;
 | |
| 	 pVisual->vid != pScreen->rootVisual;
 | |
| 	 pVisual++)
 | |
| 	;
 | |
| 
 | |
|     if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
 | |
| 		       (pVisual->class & DynamicClass) ? AllocNone : AllocAll,
 | |
| 		       0)
 | |
| 	!= Success)
 | |
| 	return FALSE;
 | |
|     wp = pScreen->whitePixel;
 | |
|     bp = pScreen->blackPixel;
 | |
|     if ((AllocColor(cmap, &wp_red, &wp_green, &wp_blue, &wp, 0) !=
 | |
|        	   Success) ||
 | |
|     	(AllocColor(cmap, &bp_red, &bp_green, &bp_blue, &bp, 0) !=
 | |
|        	   Success))
 | |
|     	return FALSE;
 | |
| 
 | |
| 	pScreen->whitePixel = wp;
 | |
| 	pScreen->blackPixel = bp;
 | |
|     
 | |
|     (*pScreen->InstallColormap)(cmap);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Add colormap to list of colormaps on screen
 | |
|  */
 | |
| Bool
 | |
| PclCreateColormap(ColormapPtr pColor)
 | |
| {
 | |
|     PclCmapToContexts *new;
 | |
|     PclScreenPrivPtr sPriv;
 | |
| 
 | |
|     sPriv = (PclScreenPrivPtr)pColor->pScreen
 | |
|       ->devPrivates[PclScreenPrivateIndex].ptr;
 | |
| 
 | |
| 	/*
 | |
| 	 * Use existing code to initialize the values in the colormap
 | |
| 	 */
 | |
| 	cfbInitializeColormap( pColor );
 | |
| 
 | |
| 	/*
 | |
| 	 * Set up the mapping between the color map and the context
 | |
| 	 */
 | |
|     new = (PclCmapToContexts *)xalloc( sizeof( PclCmapToContexts ) );
 | |
| 
 | |
|     if( new )
 | |
|       {
 | |
| 	  new->colormapId = pColor->mid;
 | |
| 	  new->contexts = NULL;
 | |
| 	  new->next = sPriv->colormaps;
 | |
| 	  sPriv->colormaps = new;
 | |
| 	  
 | |
| 	  return TRUE;
 | |
|       }
 | |
|     else
 | |
|       return FALSE;
 | |
| }
 | |
| 
 | |
| void
 | |
| PclDestroyColormap(ColormapPtr pColor)
 | |
| {
 | |
|     PclScreenPrivPtr sPriv;
 | |
|     PclCmapToContexts *pCmap, *tCmap = 0;
 | |
|     PclContextListPtr con, tCon;
 | |
|     PclContextPrivPtr cPriv;
 | |
|     PclPaletteMapPtr pPal;
 | |
|     char t[80];
 | |
| 
 | |
|     /*
 | |
|      * At DestroyContext time, colormaps may be destroyed twice, so if the
 | |
|      * pointer is NULL, just crash out.
 | |
|      */
 | |
|     if( !pColor )
 | |
|       return;
 | |
|     
 | |
|     /*
 | |
|      * Find the colormap <-> contexts mapping 
 | |
|      */
 | |
|     sPriv = (PclScreenPrivPtr)pColor->pScreen
 | |
|       ->devPrivates[PclScreenPrivateIndex].ptr;
 | |
|     pCmap = sPriv->colormaps;
 | |
|     while( pCmap )
 | |
|       {
 | |
| 	  if( pCmap->colormapId == pColor->mid )
 | |
| 	    break;
 | |
| 	  tCmap = pCmap;
 | |
| 	  pCmap = pCmap->next;
 | |
|       }
 | |
| 
 | |
|     /*
 | |
|      * For each context, delete the palette in the printer and
 | |
|      * free the mapping.
 | |
|      */
 | |
|     if( pCmap )
 | |
|       {
 | |
| 	  con = pCmap->contexts;
 | |
| 	  while( con )
 | |
| 	    {
 | |
| 		cPriv = con->context->devPrivates[PclContextPrivateIndex].ptr;
 | |
| 
 | |
| 		pPal = cPriv->palettes;
 | |
| 		while( pPal )
 | |
| 		  {
 | |
| 		      if( pPal->colormapId == pColor->mid )
 | |
| 			break;
 | |
| 		      pPal = pPal->next;
 | |
| 		  }
 | |
| 		
 | |
| 		if( cPriv->pPageFile )
 | |
| 		  {
 | |
| 		      sprintf( t, "\033&p%dI\033*p2C", pPal->paletteId );
 | |
| 		      SEND_PCL( cPriv->pPageFile, t );
 | |
| 		  }
 | |
| 		
 | |
| 		tCon = con;
 | |
| 		con = con->next;
 | |
| 		xfree( tCon );
 | |
| 	    }
 | |
| 	  
 | |
| 	  /*
 | |
| 	   * Delete the colormap<->contexts mapping
 | |
| 	   */
 | |
| 	  if( sPriv->colormaps == pCmap )
 | |
| 	    /* Delete from the front */
 | |
| 	    sPriv->colormaps = pCmap->next;
 | |
| 	  else
 | |
| 	    /* Delete from the middle */
 | |
| 	    tCmap->next = pCmap->next;
 | |
| 	  free( pCmap );
 | |
|       }
 | |
| }
 | |
| 
 | |
| void
 | |
| PclInstallColormap(ColormapPtr pColor)
 | |
| {
 | |
| }
 | |
| 
 | |
| void
 | |
| PclUninstallColormap(ColormapPtr pColor)
 | |
| {
 | |
| }
 | |
| 
 | |
| int
 | |
| PclListInstalledColormaps(ScreenPtr pScreen,
 | |
| 			  XID *pCmapList)
 | |
| {
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void
 | |
| PclStoreColors(ColormapPtr pColor,
 | |
| 	       int ndef,
 | |
| 	       xColorItem *pdefs)
 | |
| {
 | |
|     PclCmapToContexts *p;
 | |
|     PclScreenPrivPtr sPriv;
 | |
|     PclContextListPtr con;
 | |
|     PclContextPrivPtr cPriv;
 | |
|     PclPaletteMapPtr pMap;
 | |
|     char t[80];
 | |
|     int i;
 | |
| 
 | |
|     sPriv = (PclScreenPrivPtr)pColor->pScreen
 | |
|       ->devPrivates[PclScreenPrivateIndex].ptr;
 | |
|     p = sPriv->colormaps;
 | |
|     while( p )
 | |
|       {
 | |
| 	  if( p->colormapId == pColor->mid )
 | |
| 	    break;
 | |
| 	  p = p->next;
 | |
|       }
 | |
| 
 | |
|     if( p )
 | |
|       {
 | |
| 	  con = p->contexts;
 | |
| 	  while( con )
 | |
| 	    {
 | |
| 		/*
 | |
| 		 * For each context, get the palette ID and update the
 | |
| 		 * appropriate palette.
 | |
| 		 */
 | |
| 		cPriv = con->context
 | |
| 		  ->devPrivates[PclContextPrivateIndex].ptr;
 | |
| 		pMap = PclFindPaletteMap( cPriv, pColor, NULL );
 | |
| 
 | |
| 		/*
 | |
| 		 * Update the palette
 | |
| 		 */
 | |
| 		sprintf( t, "\033&p%dS", pMap->paletteId );
 | |
| 		SEND_PCL( cPriv->pPageFile, t );
 | |
| 		
 | |
| 		if( pColor->class == PseudoColor )
 | |
| 		  {
 | |
| 		      unsigned short r, g, b;
 | |
| 		      unsigned int pID;
 | |
| 		      for( i = 0; i < ndef; i++ )
 | |
| 			{
 | |
| 			    pID = pdefs[i].pixel;
 | |
| 			    if ( pColor->red[i].fShared )
 | |
| 			      {
 | |
| 				  r = pColor->red[pID].co.shco.red->color;
 | |
| 				  g = pColor->red[pID].co.shco.green->color;
 | |
| 				  b = pColor->red[pID].co.shco.blue->color;
 | |
| 			      }
 | |
| 			    else
 | |
| 			      {
 | |
| 				  r = pColor->red[pID].co.local.red;
 | |
| 				  g = pColor->red[pID].co.local.green;
 | |
| 				  b = pColor->red[pID].co.local.blue;
 | |
| 			      }
 | |
| 
 | |
| 			    if( pdefs[i].flags & DoRed )
 | |
| 				  r = pdefs[i].red;
 | |
| 			    if( pdefs[i].flags & DoGreen )
 | |
| 				  g = pdefs[i].green;
 | |
| 			    if( pdefs[i].flags & DoBlue )
 | |
| 				  b = pdefs[i].blue;
 | |
| 			    PclLookUp(pColor, cPriv, &r, &g, &b);
 | |
| 			    sprintf( t, "\033*v%ua%ub%uc%dI", r, g, b, pID);
 | |
| 			    SEND_PCL( cPriv->pPageFile, t );
 | |
| 			}
 | |
| 		  }    
 | |
| 
 | |
| 		sprintf( t, "\033&p%dS", cPriv->currentPalette );
 | |
| 		SEND_PCL( cPriv->pPageFile, t );
 | |
| 
 | |
| 		con = con->next;
 | |
| 	    }
 | |
|       }
 | |
| }
 | |
| 
 | |
| void
 | |
| PclResolveColor(unsigned short *pRed,
 | |
| 		unsigned short *pGreen,
 | |
| 		unsigned short *pBlue,
 | |
| 		VisualPtr pVisual)
 | |
| {
 | |
|     /*
 | |
|      * We need to map the X color range of [0,65535] to the PCL color
 | |
|      * range of [0,32767].
 | |
|      */
 | |
|     *pRed >>= 1;
 | |
|     *pGreen >>= 1;
 | |
|     *pBlue >>= 1;
 | |
| }
 | |
| 
 | |
| PclPaletteMapPtr
 | |
| PclFindPaletteMap(PclContextPrivPtr cPriv,
 | |
| 		  ColormapPtr cmap,
 | |
| 		  GCPtr gc)
 | |
| {
 | |
|     PclPaletteMapPtr p = cPriv->palettes, new;
 | |
| 
 | |
|     /*
 | |
|      * If the colormap is static, grab one of the special palettes.  If we come
 | |
|      * into this from StoreColors, there will be no GC, but by definition we're
 | |
|      * looking at a dynamic color map, so the special colors will not be
 | |
|      * needed.
 | |
|      */
 | |
|     if( gc )
 | |
|       {
 | |
| 	  if( cmap->pVisual->class == StaticGray )
 | |
| 	    return &( cPriv->staticGrayPalette );
 | |
| 	  else if( cmap->pVisual->class == TrueColor )
 | |
| 	    {
 | |
| 		if( gc->fillStyle == FillTiled && !( gc->tileIsPixel ) )
 | |
| 		  return &( cPriv->specialTrueColorPalette );
 | |
| 		else
 | |
| 		  return &( cPriv->trueColorPalette );
 | |
| 	    }
 | |
|       }
 | |
|     
 | |
|     
 | |
|     /* Look for the colormap ID <-> palette ID mapping */
 | |
|     while( p )
 | |
|       {
 | |
| 	  if( p->colormapId == cmap->mid )
 | |
| 	    return p;
 | |
| 	  p = p->next;
 | |
|       }
 | |
| 
 | |
|     /* If the colormap isn't already there, make an entry for it */
 | |
|     new = (PclPaletteMapPtr)xalloc( sizeof( PclPaletteMap ) );
 | |
|     new->colormapId = cmap->mid;
 | |
|     new->paletteId = cPriv->nextPaletteId++;
 | |
|     new->downloaded = 0;
 | |
|     new->next = cPriv->palettes;
 | |
|     cPriv->palettes = new;
 | |
|     return new;
 | |
| }
 | |
| 
 | |
| int
 | |
| PclUpdateColormap(DrawablePtr pDrawable,
 | |
| 		  XpContextPtr pCon,
 | |
| 		  GCPtr gc,
 | |
| 		  FILE *outFile)
 | |
| {
 | |
|     PclScreenPrivPtr sPriv;
 | |
|     
 | |
|     PclContextPrivPtr cPriv;
 | |
|     PclPaletteMapPtr pMap;
 | |
|     PclCmapToContexts *pCmap;
 | |
|     PclContextListPtr new;
 | |
|     char t[80];
 | |
|     Colormap c;
 | |
|     ColormapPtr cmap;
 | |
|     WindowPtr win = (WindowPtr)pDrawable;
 | |
|     unsigned short r, g, b, rr, gg, bb;
 | |
|     int i;
 | |
| 
 | |
|     cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr;
 | |
|     
 | |
|     c = wColormap( win );
 | |
|     cmap = (ColormapPtr)LookupIDByType( c, RT_COLORMAP );
 | |
|     pMap = PclFindPaletteMap( cPriv, cmap, gc );
 | |
|     
 | |
|     if( cPriv->currentPalette == pMap->paletteId )
 | |
|       /*
 | |
|        * If the requested colormap is already active, nothing needs to
 | |
|        * be done.
 | |
|        */
 | |
|       return FALSE;
 | |
| 
 | |
|     /*
 | |
|      * Now we activate the palette in the printer
 | |
|      */
 | |
|     sprintf( t, "\033&p%dS", pMap->paletteId );
 | |
|     SEND_PCL( outFile, t );
 | |
|     cPriv->currentPalette = pMap->paletteId;
 | |
| 
 | |
|     if( pMap->downloaded == 0 )
 | |
|       /*
 | |
|        * If the requested colormap has not been downloaded to the
 | |
|        * printer, we need to do that before activating it.
 | |
|        */
 | |
|       {
 | |
| 	  /*
 | |
| 	   * Add the colormap to the screen-level colormap<->context mapping.
 | |
| 	   */
 | |
| 	  sPriv = (PclScreenPrivPtr)cmap->pScreen
 | |
| 	    ->devPrivates[PclScreenPrivateIndex].ptr;
 | |
| 	  pCmap = sPriv->colormaps;
 | |
| 	  while( pCmap && ( pCmap->colormapId != cmap->mid ) )
 | |
| 		pCmap = pCmap->next;
 | |
| 	  new = (PclContextListPtr)xalloc( sizeof( PclContextList ) );
 | |
| 	  new->context = pCon;
 | |
| 	  new->next = pCmap->contexts;
 | |
| 	  pCmap->contexts = new;
 | |
| 
 | |
| 	  /*
 | |
| 	   * XXX Download the colormap
 | |
| 	   */
 | |
| 	  if( cmap->class == StaticGray )
 | |
| 	    {
 | |
| #ifdef XP_PCL_COLOR
 | |
| 		sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, 1, 1, 1, 1 );
 | |
| 		SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
 | |
| 		
 | |
| 		/* Send the white reference point... */
 | |
| 		sprintf( t, "%c%c%c%c%c%c", 0x7f, 0xff, 0x7f, 0xff,
 | |
| 			0x7f, 0xff );
 | |
| 		SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 		/* ... and the black reference point */
 | |
| 		sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00,
 | |
| 			0x00, 0x00 );
 | |
| 		SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 		
 | |
| 		/* Now program the two colors */
 | |
| 		sprintf( t, "\033*v0a0b0c%ldI", (long) cmap->pScreen->blackPixel );
 | |
| 		SEND_PCL( cPriv->pPageFile, t );
 | |
| 		sprintf( t, "\033*v32767a32767b32767c%ldI",
 | |
| 			(long) cmap->pScreen->whitePixel );
 | |
| 		SEND_PCL( cPriv->pPageFile, t );
 | |
| #endif /* XP_PCL_COLOR */
 | |
| 	    }
 | |
| 	  else if( cmap->class == PseudoColor )
 | |
| 	    {
 | |
| 		sprintf( t,
 | |
| 			"\033*v18W%c%c%c%c%c%c",
 | |
| 			0, 1, cmap->pVisual->nplanes, 16, 16, 16 );
 | |
| 		SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
 | |
| 		
 | |
| 		/* Send the white reference point... */
 | |
| 		if ( cPriv->ctbl != NULL )
 | |
| 		    sprintf( t, "%c%c%c%c%c%c", 0x00, 0xff, 0x00, 0xff,
 | |
| 			0x00, 0xff );
 | |
| 		else
 | |
| 		    sprintf( t, "%c%c%c%c%c%c", 0x7f, 0xff, 0x7f, 0xff,
 | |
| 			0x7f, 0xff );
 | |
| 		SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 		/* ... and the black reference point */
 | |
| 		sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00,
 | |
| 			0x00, 0x00 );
 | |
| 		SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 		
 | |
| 		for(i = 0; i < cmap->pVisual->ColormapEntries; i++ )
 | |
| 		  {
 | |
| 		      if( cmap->red[i].fShared )
 | |
| 			{
 | |
| 			    r = cmap->red[i].co.shco.red->color;
 | |
| 			    g = cmap->red[i].co.shco.green->color;
 | |
| 			    b = cmap->red[i].co.shco.blue->color;
 | |
| 			}
 | |
| 		      else
 | |
| 			{
 | |
| 			    r = cmap->red[i].co.local.red;
 | |
| 			    g = cmap->red[i].co.local.green;
 | |
| 			    b = cmap->red[i].co.local.blue;
 | |
| 			}
 | |
| 		      PclLookUp(cmap, cPriv, &r, &g, &b);
 | |
| 		      sprintf( t, "\033*v%ua%ub%uc%dI", r, g, b, i );
 | |
| 		      SEND_PCL( outFile, t );
 | |
| 		  }
 | |
| 	    }
 | |
| 	  else if( cmap->class == TrueColor )
 | |
| 	    {
 | |
| 		unsigned short lim;
 | |
| 
 | |
| 		if( gc->fillStyle == FillTiled && !( gc->tileIsPixel ) )
 | |
| 		  {
 | |
| 		      if( cPriv->ctbl != NULL )
 | |
| 			{
 | |
| 			   /* Send the "special" colormap for 24-bit fills */
 | |
| 			   sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, 
 | |
| 					8,
 | |
| 					cmap->pVisual->bitsPerRGBValue,
 | |
| 					cmap->pVisual->bitsPerRGBValue,
 | |
| 					cmap->pVisual->bitsPerRGBValue );
 | |
| 			   SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
 | |
| 
 | |
| 			   /* Send the white reference point... */
 | |
| 			   sprintf( t, "%c%c%c%c%c%c",
 | |
| 					0x00, 0xff,
 | |
| 					0x00, 0xff,
 | |
| 					0x00, 0xff );
 | |
| 			   SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 			   /* ... and the black reference point */
 | |
| 			   sprintf( t, "%c%c%c%c%c%c",
 | |
| 					0x00, 0x00,
 | |
| 					0x00, 0x00,
 | |
| 					0x00, 0x00 );
 | |
| 			   SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 			   /* Now send the color entries, RRRGGGBB */
 | |
| 			   i=0;
 | |
| 			   for( r = 0; r < 8; r++ )
 | |
| 			     for( g = 0; g < 8; g ++ )
 | |
| 			       for( b = 0; b < 4; b++ )
 | |
| 				  {
 | |
| 				      rr = (r * 0xff)/7;
 | |
| 				      gg = (g * 0xff)/7;
 | |
| 				      bb = (b * 0xff)/3;
 | |
| 				      PclLookUp(cmap, cPriv, &rr, &gg, &bb);
 | |
| 				      sprintf( t, "\033*v%ua%ub%uc%dI",
 | |
| 								rr, gg, bb, i );
 | |
| 				      SEND_PCL( outFile, t );
 | |
| 				      i++;
 | |
| 				   }
 | |
| 			}
 | |
| 		      else
 | |
| 			{
 | |
| 			   /* Send the "special" colormap for 24-bit fills */
 | |
| 			   sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 1, 
 | |
| 				8,
 | |
| 				cmap->pVisual->bitsPerRGBValue,
 | |
| 				cmap->pVisual->bitsPerRGBValue,
 | |
| 				cmap->pVisual->bitsPerRGBValue );
 | |
| 			   SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
 | |
| 
 | |
| 			   /* Send the white reference point... */
 | |
| 			   sprintf( t, "%c%c%c%c%c%c",
 | |
| 					0x00, 0x07,
 | |
| 					0x00, 0x07,
 | |
| 					0x00, 0x03 );
 | |
| 			   SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 			   /* ... and the black reference point */
 | |
| 			   sprintf( t, "%c%c%c%c%c%c",
 | |
| 					0x00, 0x00,
 | |
| 					0x00, 0x00,
 | |
| 					0x00, 0x00 );
 | |
| 			   SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 			   /* Now send the color entries, RRRGGGBB */
 | |
| 			   i=0;
 | |
| 			   for( r = 0; r < 8; r++ )
 | |
| 			     for( g = 0; g < 8; g ++ )
 | |
| 			       for( b = 0; b < 4; b++ )
 | |
| 				  {
 | |
| 				      sprintf( t, "\033*v%ua%ub%uc%dI",
 | |
| 								r, g, b, i );
 | |
| 				      SEND_PCL( outFile, t );
 | |
| 				      i++;
 | |
| 				   }
 | |
| 			}
 | |
| 
 | |
| 		  }
 | |
| 		else
 | |
| 		  {
 | |
| 		      lim = (1 << cmap->pVisual->bitsPerRGBValue) - 1;
 | |
| 
 | |
| 		      /* Send the "special" colormap for 24-bit fills */
 | |
| 		      sprintf( t, "\033*v18W%c%c%c%c%c%c", 0, 3, 
 | |
| 				cmap->pVisual->nplanes,
 | |
| 				cmap->pVisual->bitsPerRGBValue,
 | |
| 				cmap->pVisual->bitsPerRGBValue,
 | |
| 				cmap->pVisual->bitsPerRGBValue );
 | |
| 		      SEND_PCL_COUNT( cPriv->pPageFile, t, 12 );
 | |
| 		     
 | |
| 		      /* Send the white reference point... */
 | |
| 		      sprintf( t, "%c%c%c%c%c%c",
 | |
| 				(lim >> 8) & 0xff, lim & 0xff,
 | |
| 				(lim >> 8) & 0xff, lim & 0xff,
 | |
| 				(lim >> 8) & 0xff, lim & 0xff);
 | |
| 		      SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 
 | |
| 		      /* ... and the black reference point */
 | |
| 		      sprintf( t, "%c%c%c%c%c%c", 0x00, 0x00, 0x00, 0x00,
 | |
| 			      0x00, 0x00 );
 | |
| 		      SEND_PCL_COUNT( cPriv->pPageFile, t, 6 );
 | |
| 		  }
 | |
| 
 | |
| 	    }
 | |
| 	  pMap->downloaded = 1;
 | |
|       }
 | |
|       return TRUE;
 | |
|     
 | |
| }    
 | |
| 
 | |
| void PclLookUp(
 | |
|     ColormapPtr cmap,
 | |
|     PclContextPrivPtr cPriv,
 | |
|     unsigned short *r, 
 | |
|     unsigned short *g, 
 | |
|     unsigned short *b
 | |
| )
 | |
| {
 | |
|     unsigned char cdata[3];
 | |
| 
 | |
|     if( cmap->class == PseudoColor )
 | |
|       {
 | |
| 	if( cPriv->ctbl != NULL )
 | |
| 	  {
 | |
| 	    cdata[0] = *r >> 8;
 | |
| 	    cdata[1] = *g >> 8;
 | |
| 	    cdata[2] = *b >> 8;
 | |
| 	    lookup(cdata, cdata, 1, cPriv->ctbl, cPriv->ctbldim);
 | |
| 	    *r = cdata[0];
 | |
| 	    *g = cdata[1];
 | |
| 	    *b = cdata[2];
 | |
| 	  }
 | |
| 	else
 | |
| 	  {
 | |
| 	    *r >>= 1;
 | |
| 	    *g >>= 1;
 | |
| 	    *b >>= 1;
 | |
| 	  }
 | |
|       }
 | |
|     else if( cmap->class == TrueColor )
 | |
|       {
 | |
| 	if( cPriv->ctbl != NULL )
 | |
| 	  {
 | |
| 	    cdata[0] = *r;
 | |
| 	    cdata[1] = *g;
 | |
| 	    cdata[2] = *b;
 | |
| 	    lookup(cdata, cdata, 1, cPriv->ctbl, cPriv->ctbldim);
 | |
| 	    *r = cdata[0];
 | |
| 	    *g = cdata[1];
 | |
| 	    *b = cdata[2];
 | |
| 	  }
 | |
|       }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| unsigned char *PclReadMap(char *name, int *dim)
 | |
| {
 | |
|     FILE *fp;
 | |
|     unsigned char *data;
 | |
|     long size;
 | |
| 
 | |
|     if ((fp=fopen(name, "r")) == NULL) {
 | |
| 	return(NULL);
 | |
|     }
 | |
| 
 | |
|     fseek(fp, 0, SEEK_END);
 | |
|     size = ftell(fp);
 | |
|     
 | |
|     /* Could do this with a lookup table, if the constraint is that the
 | |
|        3 map dimensions must be equal. */
 | |
|     switch (size) {
 | |
|     case 8*8*8*3:
 | |
| 	*dim = 8;
 | |
| 	break;
 | |
|     case 16*16*16*3:
 | |
| 	*dim = 16;
 | |
| 	break;
 | |
|     case 17*17*17*3:
 | |
| 	*dim = 17;
 | |
| 	break;
 | |
|     case 65*65*65*3:
 | |
| 	*dim = 65;
 | |
| 	break;
 | |
|     default:
 | |
| 	fclose(fp);
 | |
| 	return(NULL);
 | |
|     }
 | |
|     
 | |
|     if ((data = (unsigned char *) xalloc(sizeof(char) * size)) == NULL) {
 | |
| 	fclose(fp);
 | |
| 	return(NULL);
 | |
|     }
 | |
| 
 | |
|     fseek(fp, 0, SEEK_SET);
 | |
| 
 | |
|     if (fread(data, sizeof(char), size, fp) != (unsigned) size) {
 | |
| 	fclose(fp);
 | |
| 	free(data);
 | |
| 	return(NULL);
 | |
|     }
 | |
| 
 | |
|     fclose(fp);
 | |
|     return(data);
 | |
| }
 | |
| 
 | |
| /************************************************************************
 | |
|  *
 | |
|  * Here is the mapper.
 | |
|  *
 | |
|  ************************************************************************/
 | |
| 
 | |
| #define SCL(x) ((x)*(dim-1)/255)
 | |
| /* Interleaved-map lookup */
 | |
| static void lookup(unsigned char *src, unsigned char *dst, int num, unsigned char *map, int dim)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
| #define _INTERPOLATE
 | |
| #ifndef _INTERPOLATE
 | |
|     unsigned char *p1, *p2, *p3;
 | |
| 
 | |
|     for (i=0; i<num; i++) {
 | |
| 	p1 = map + (SCL(src[0])*dim*dim + SCL(src[1])*dim + SCL(src[2])) * 3;
 | |
| 	*dst++ = *p1++;
 | |
| 	*dst++ = *p1++;
 | |
| 	*dst++ = *p1++;
 | |
| 	src += 3;
 | |
|     }
 | |
| #else
 | |
|     for (i=0; i<num; i++) {
 | |
| 	trilinear(src, dst, map, dim, 128);
 | |
| 	src += 3;
 | |
| 	dst += 3;
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * C code from the article
 | |
|  * "Tri-linear Interpolation"
 | |
|  * by Steve Hill, sah@ukc.ac.uk
 | |
|  * in "Graphics Gems IV", Academic Press, 1994
 | |
|  *
 | |
|  * Fri Feb 16 14:12:43 PST 1996
 | |
|  *	Modified to use for 8-bit color mapping -- A. Fitzhugh, 
 | |
|  * 	HP Labs, Printing Technology Department
 | |
|  */
 | |
| 
 | |
| /* linear interpolation from l (when a=0) to h (when a=1)*/
 | |
| /* (equal to (a*h)+((1-a)*l) */
 | |
| #define LERP(a,l,h)	((l)+((((h)-(l))*(a))>>8))
 | |
| 
 | |
| static void trilinear(unsigned char *p, unsigned char *out, unsigned char *d, int dim, unsigned char def)
 | |
| {
 | |
| #define DENS(X, Y, Z, ch) d[((X*dim+Y)*dim+Z)*3+ch]
 | |
|     
 | |
|     int	x0, y0, z0, 
 | |
| 	x1, y1, z1,
 | |
| 	i;
 | |
|     unsigned char *dp,
 | |
| 	fx, fy, fz,
 | |
| 	d000, d001, d010, d011,
 | |
| 	d100, d101, d110, d111,
 | |
| 	dx00, dx01, dx10, dx11,
 | |
| 	dxy0, dxy1;
 | |
|     float scale;
 | |
|     
 | |
|     scale = 255.0 / (dim-1);
 | |
| 
 | |
|     x0 = p[0] / scale;
 | |
|     y0 = p[1] / scale;
 | |
|     z0 = p[2] / scale;
 | |
| 
 | |
|     /* Fractions should range from 0-1.0 (fixed point 8-256) */
 | |
|     fx = (((int) (p[0] - x0 * scale)) << 8) / 255;
 | |
|     fy = (((int) (p[1] - y0 * scale)) << 8) / 255;
 | |
|     fz = (((int) (p[2] - z0 * scale)) << 8) / 255;
 | |
|     
 | |
|     x1 = x0 + 1;
 | |
|     y1 = y0 + 1;
 | |
|     z1 = z0 + 1;
 | |
|     
 | |
|     for (i=0; i<3; i++) {
 | |
| 	
 | |
| 	if (x0 >= 0 && x1 < dim &&
 | |
| 	    y0 >= 0 && y1 < dim &&
 | |
| 	    z0 >= 0 && z1 < dim) {
 | |
| 	    dp = &DENS(x0, y0, z0, i);
 | |
| 	    d000 = dp[0];
 | |
| 	    d100 = dp[3];
 | |
| 	    dp += dim*3;
 | |
| 	    d010 = dp[0];
 | |
| 	    d110 = dp[3];
 | |
| 	    dp += dim*dim*3;
 | |
| 	    d011 = dp[0];
 | |
| 	    d111 = dp[3];
 | |
| 	    dp -= dim*3;
 | |
| 	    d001 = dp[0];
 | |
| 	    d101 = dp[3];
 | |
| 	} else {
 | |
| #	define INRANGE(X, Y, Z) \
 | |
| 	    ((X) >= 0 && (X) < dim && \
 | |
| 	     (Y) >= 0 && (Y) < dim && \
 | |
| 	     (Z) >= 0 && (Z) < dim)
 | |
| 	    
 | |
| 	    d000 = INRANGE(x0, y0, z0) ? DENS(x0, y0, z0, i) : def;
 | |
| 	    d001 = INRANGE(x0, y0, z1) ? DENS(x0, y0, z1, i) : def;
 | |
| 	    d010 = INRANGE(x0, y1, z0) ? DENS(x0, y1, z0, i) : def;
 | |
| 	    d011 = INRANGE(x0, y1, z1) ? DENS(x0, y1, z1, i) : def;
 | |
| 	    
 | |
| 	    d100 = INRANGE(x1, y0, z0) ? DENS(x1, y0, z0, i) : def;
 | |
| 	    d101 = INRANGE(x1, y0, z1) ? DENS(x1, y0, z1, i) : def;
 | |
| 	    d110 = INRANGE(x1, y1, z0) ? DENS(x1, y1, z0, i) : def;
 | |
| 	    d111 = INRANGE(x1, y1, z1) ? DENS(x1, y1, z1, i) : def;
 | |
| 	}
 | |
| 	
 | |
| 	dx00 = LERP(fx, d000, d100);
 | |
| 	dx01 = LERP(fx, d001, d101);
 | |
| 	dx10 = LERP(fx, d010, d110);
 | |
| 	dx11 = LERP(fx, d011, d111);
 | |
| 	
 | |
| 	dxy0 = LERP(fy, dx00, dx10);
 | |
| 	dxy1 = LERP(fy, dx01, dx11);
 | |
| 	
 | |
| 	out[i] = LERP(fz, dxy0, dxy1);
 | |
|     }
 | |
| }
 | |
|     
 |