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);
 | 
						|
    }
 | 
						|
}
 | 
						|
    
 |