#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "gcstruct.h"
#include "Pcl.h"
#include "pixmapstr.h"
#include "colormapst.h"
#include "windowstr.h"
#include "fb.h"
#include "scrnintstr.h"
#include "resource.h"
static GCOps PclGCOps =
{
PclFillSpans,
PclSetSpans,
PclPutImage,
PclCopyArea,
PclCopyPlane,
PclPolyPoint,
PclPolyLine,
PclPolySegment,
PclPolyRectangle,
PclPolyArc,
PclFillPolygon,
PclPolyFillRect,
PclPolyFillArc,
PclPolyText8,
PclPolyText16,
PclImageText8,
PclImageText16,
PclImageGlyphBlt,
PclPolyGlyphBlt,
PclPushPixels
}
;
static GCFuncs PclGCFuncs =
{
PclValidateGC,
miChangeGC,
miCopyGC,
PclDestroyGC,
miChangeClip,
miDestroyClip,
miCopyClip,
}
;
Bool
PclCreateGC(GCPtr pGC)
{
if (fbCreateGC(pGC) == FALSE)
return FALSE;
pGC->clientClip = NULL;
pGC->clientClipType = CT_NONE;
pGC->ops = &PclGCOps;
pGC->funcs = &PclGCFuncs;
return TRUE;
}
void
PclDestroyGC(GCPtr pGC)
{
miDestroyGC( pGC );
}
int
PclGetDrawablePrivateStuff(
DrawablePtr pDrawable,
GC *gc,
unsigned long *valid,
FILE **file)
{
XpContextPtr pCon;
PclContextPrivPtr cPriv;
switch( pDrawable->type )
{
case DRAWABLE_PIXMAP:
return FALSE;
case DRAWABLE_WINDOW:
pCon = PclGetContextFromWindow( (WindowPtr)pDrawable );
if( pCon == NULL )
return FALSE;
else
{
cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr;
*gc = cPriv->lastGC;
*valid = cPriv->validGC;
*file = cPriv->pPageFile;
return TRUE;
}
default:
return FALSE;
}
}
void
PclSetDrawablePrivateGC(
DrawablePtr pDrawable,
GC gc)
{
PixmapPtr pix;
XpContextPtr pCon;
PclPixmapPrivPtr pixPriv;
PclContextPrivPtr pPriv;
int i;
switch( pDrawable->type )
{
case DRAWABLE_PIXMAP:
pix = (PixmapPtr)pDrawable;
pixPriv = pix->devPrivates[PclPixmapPrivateIndex].ptr;
pixPriv->lastGC = gc;
pixPriv->validGC = 1;
break;
case DRAWABLE_WINDOW:
pCon = PclGetContextFromWindow( (WindowPtr)pDrawable );
pPriv = ((PclContextPrivPtr)
(pCon->devPrivates[PclContextPrivateIndex].ptr));
pPriv->validGC = 1;
pPriv->lastGC = gc;
if( pPriv->dash != NULL )
xfree( pPriv->dash );
if( gc.numInDashList != 0 )
{
pPriv->dash = (unsigned char *)xalloc( sizeof( unsigned char )
* gc.numInDashList );
for( i = 0; i < gc.numInDashList; i++ )
pPriv->dash[i] = gc.dash[i];
}
else
pPriv->dash = NULL;
if( pPriv->dash != NULL )
xfree( pPriv->dash );
if( gc.numInDashList != 0 )
{
pPriv->dash = (unsigned char *)xalloc( sizeof( unsigned char )
* gc.numInDashList );
for( i = 0; i < gc.numInDashList; i++ )
pPriv->dash[i] = gc.dash[i];
}
else
pPriv->dash = NULL;
break;
}
}
static void
PclSendPattern(char *bits,
int sz,
int depth,
int h,
int w,
int patNum,
FILE *outFile)
{
char t[80], *row, *mod;
int w2;
int i, j;
SEND_PCL( outFile, "\033%0A" );
if( depth == 1 )
{
w2 = ( w / 8 ) + ( ( w%8 ) ? 1 : 0 );
sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 );
SEND_PCL( outFile, t );
sprintf( t, "%c%c%c%c%c%c%c%c", 0, 0, 1, 0, h>>8, h&0xff, w>>8,
w&0xff );
SEND_PCL_COUNT( outFile, t, 8 );
for( row = bits, i = 0; i < h; i++, row += BitmapBytePad( w ) )
SEND_PCL_COUNT( outFile, row, w2 );
}
else if( depth == 8 )
{
w2 = ( w % 2 ) ? w + 1 : w;
sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 );
SEND_PCL( outFile, t );
sprintf( t, "%c%c%c%c%c%c%c%c", 1, 0, 8, 0, h>>8, h&0xff,
w>>8, w&0xff );
SEND_PCL_COUNT( outFile, t, 8 );
for( row = bits, i = 0; i < h; i++,
row += PixmapBytePad( w, 8 ) )
SEND_PCL_COUNT( outFile, row, w2 );
}
else
{
w2 = ( w % 2 ) ? w + 1 : w;
sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 );
SEND_PCL( outFile, t );
sprintf( t, "%c%c%c%c%c%c%c%c", 1, 0, 8, 0, h>>8, h&0xff,
w>>8, w&0xff );
SEND_PCL_COUNT( outFile, t, 8 );
mod = (char *)xalloc( w2 );
for( row = bits, i = 0; i < h; i++,
row += PixmapBytePad( w, 24 ) )
{
char r, g, b;
for( j = 0; j < w2; j++ ) {
r = ((row[j*4+1] >> 5) & 0x7) << 5;
g = ((row[j*4+2] >> 5) & 0x7) << 2;
b = ((row[j*4+3] >> 6) & 0x3);
mod[j] = r | g | b;
}
SEND_PCL_COUNT( outFile, mod, w2 );
}
xfree( mod );
}
SEND_PCL( outFile, "\033%0B" );
}
int
PclUpdateDrawableGC(
GCPtr pGC,
DrawablePtr pDrawable,
FILE **outFile)
{
Mask changeMask = 0;
GC dGC;
unsigned long valid;
int i;
XpContextPtr pCon;
PclContextPrivPtr cPriv;
PclGCPrivPtr gcPriv = (PclGCPrivPtr)
(pGC->devPrivates[PclGCPrivateIndex].ptr);
if( !PclGetDrawablePrivateStuff( pDrawable, &dGC, &valid, outFile ) )
return FALSE;
pCon = PclGetContextFromWindow( (WindowPtr)pDrawable );
cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr;
if( !PclUpdateColormap( pDrawable, pCon, pGC, *outFile ) )
return FALSE;
if( valid == 0 )
changeMask = ~0;
else
{
if( dGC.alu != pGC->alu )
changeMask |= GCFunction;
if( dGC.fgPixel != pGC->fgPixel )
changeMask |= GCForeground;
if( dGC.bgPixel != pGC->bgPixel )
changeMask |= GCBackground;
if( dGC.lineWidth != pGC->lineWidth )
changeMask |= GCLineWidth;
if( dGC.lineStyle != pGC->lineStyle )
changeMask |= GCLineStyle;
if( dGC.capStyle != pGC->capStyle )
changeMask |= GCCapStyle;
if( dGC.joinStyle != pGC->joinStyle )
changeMask |= GCJoinStyle;
if( dGC.fillStyle != pGC->fillStyle )
changeMask |= GCFillStyle;
if( dGC.tile.pixmap != pGC->tile.pixmap )
changeMask |= GCTile;
if( dGC.stipple != pGC->stipple )
changeMask |= GCStipple;
if( dGC.patOrg.x != pGC->patOrg.x )
changeMask |= GCTileStipXOrigin;
if( dGC.patOrg.y != pGC->patOrg.y )
changeMask |= GCTileStipYOrigin;
if( dGC.numInDashList == pGC->numInDashList )
{
for( i = 0; i < dGC.numInDashList; i++ )
if( cPriv->dash[i] != pGC->dash[i] )
{
changeMask |= GCDashList;
break;
}
}
else
changeMask |= GCDashList;
}
SEND_PCL( *outFile, "\033%0B" );
if( changeMask & GCFunction )
{
#ifdef XP_PCL_COLOR
if( pGC->alu == GXclear )
SEND_PCL( *outFile, "SP0;" );
else
SEND_PCL( *outFile, "SP1;" );
#else
if( pGC->alu == GXclear )
SEND_PCL( *outFile, "SP0;" );
else
SEND_PCL( *outFile, "SP1;" );
#endif
}
#if 0
if( changeMask & GCFunction )
{
int rop = -1;
char t[10];
switch( pGC->alu )
{
case GXclear:
rop = 1;
break;
case GXand:
rop = 136;
break;
case GXandReverse:
rop = 68;
break;
case GXcopy:
rop = 204;
break;
case GXandInverted:
rop = 34;
break;
case GXnoop:
rop = 170;
break;
case GXxor:
rop = 238;
break;
case GXor:
rop = 238;
break;
case GXnor:
rop = 17;
break;
case GXequiv:
rop = 153;
break;
case GXinvert:
rop = 85;
break;
case GXorReverse:
rop = 221;
break;
case GXcopyInverted:
rop = 51;
break;
case GXorInverted:
rop = 187;
break;
case GXnand:
rop = 119;
break;
case GXset:
rop = 0;
break;
}
if( rop != -1 )
{
sprintf( t, "MC1,%d;", rop );
SEND_PCL( *outFile, t );
#endif
if( changeMask & GCForeground )
switch( pGC->fgPixel )
{
case 1:
SEND_PCL( *outFile, "SP1;" );
break;
default:
SEND_PCL( *outFile, "SP0;" );
break;
}
if( changeMask & GCForeground )
{
#ifdef XP_PCL_COLOR
ColormapPtr cmap;
Colormap c;
char t[40];
c = wColormap( ((WindowPtr)pDrawable) );
cmap = (ColormapPtr)LookupIDByType( c, RT_COLORMAP );
if( cmap->class == TrueColor )
{
if( pGC->fillStyle != FillTiled || pGC->tileIsPixel ) {
unsigned short r, g, b;
r = (pGC->fgPixel & cmap->pVisual->redMask)
>> (cmap->pVisual->offsetRed );
g = (pGC->fgPixel & cmap->pVisual->greenMask)
>> (cmap->pVisual->offsetGreen);
b = (pGC->fgPixel & cmap->pVisual->blueMask)
>> (cmap->pVisual->offsetBlue);
PclLookUp(cmap, cPriv, &r, &g, &b);
sprintf( t, "\033%%0A\033*v%ua%ub%uc0I\033%%0B", r, g, b);
SEND_PCL( *outFile, t );
}
}
else
{
sprintf( t, "SP%ld;", (long) pGC->fgPixel );
SEND_PCL( *outFile, t );
}
#else
ScreenPtr screen;
screen = pDrawable->pScreen;
if ( pGC->fgPixel == screen->whitePixel )
SEND_PCL( *outFile, "SP0;");
else
SEND_PCL( *outFile, "SP1;");
#endif
}
if( changeMask & GCJoinStyle )
switch( pGC->joinStyle )
{
case JoinMiter:
SEND_PCL( *outFile, "LA2,1;" );
break;
case JoinRound:
SEND_PCL( *outFile, "LA2,4;" );
break;
case JoinBevel:
SEND_PCL( *outFile, "LA2,5;" );
break;
}
if( changeMask & GCCapStyle )
switch( pGC->capStyle )
{
case CapNotLast:
case CapButt:
SEND_PCL( *outFile, "LA1,1;" );
break;
case CapRound:
SEND_PCL( *outFile, "LA1,4;" );
break;
case CapProjecting:
SEND_PCL( *outFile, "LA1,2;" );
break;
}
if( changeMask & GCLineWidth )
{
float penWidth, pixelsPerMM;
ScreenPtr screen;
char temp[30];
if( pGC->lineWidth == 0 || pGC->lineWidth == 1 )
penWidth = 0.0;
else
{
screen = pDrawable->pScreen;
pixelsPerMM = (float)screen->width / (float)screen->mmWidth;
penWidth = pGC->lineWidth / pixelsPerMM;
}
sprintf( temp, "PW%g;", penWidth );
SEND_PCL( *outFile, temp );
}
if( changeMask & GCLineStyle )
{
int i, num = pGC->numInDashList;
double total;
char t[30];
switch( pGC->lineStyle )
{
case LineSolid:
SEND_PCL( *outFile, "LT;" );
break;
case LineOnOffDash:
for( i = 0, total = 0.0; i < 20 && i < num; i++ )
total += pGC->dash[i];
if( num % 2 )
for( i = num; i < 20 && i < num + num; i++ )
total += pGC->dash[i-num];
total *= ( (double)pDrawable->pScreen->mmWidth /
(double)pDrawable->pScreen->width );
sprintf( t, "LT8,%f,1;", total );
SEND_PCL( *outFile, t );
break;
}
}
if( changeMask & GCFillStyle )
switch( pGC->fillStyle )
{
case FillSolid:
SEND_PCL( *outFile, "FT1;TR0;CF;" );
break;
case FillTiled:
SEND_PCL( *outFile, "FT22,100;TR0;CF2,0;" );
break;
case FillOpaqueStippled:
SEND_PCL( *outFile, "FT22,101;TR0;CF2,0;" );
if( pGC->fgPixel != gcPriv->stippleFg ||
pGC->bgPixel != gcPriv->stippleBg )
changeMask |= GCStipple;
break;
case FillStippled:
SEND_PCL( *outFile, "FT22,102;TR1;CF2,0;" );
break;
}
if( changeMask & GCTile && !pGC->tileIsPixel )
{
char *bits;
int h, w, sz;
h = pGC->tile.pixmap->drawable.height;
w = pGC->tile.pixmap->drawable.width;
sz = h * PixmapBytePad(w, pGC->tile.pixmap->drawable.depth);
bits = (char *)xalloc(sz);
fbGetImage(&(pGC->tile.pixmap->drawable), 0, 0, w, h, XYPixmap, ~0,
bits);
PclSendPattern( bits, sz, 1, h, w, 100, *outFile );
xfree( bits );
}
if( changeMask & ( GCTileStipXOrigin | GCTileStipYOrigin ) )
{
char t[30];
sprintf( t, "AC%d,%d;", pGC->patOrg.x, pGC->patOrg.y );
SEND_PCL( *outFile, t );
}
if( changeMask & GCStipple ||
( pGC->fillStyle == FillOpaqueStippled &&
( pGC->fgPixel != gcPriv->stippleFg ||
pGC->bgPixel != gcPriv->stippleBg ) ) )
{
int h, w, i, sz, w2;
char *bits, *row, t[30];
PixmapPtr scratchPix;
GCPtr scratchGC;
if( pGC->stipple != NULL )
{
SEND_PCL( *outFile, "\033%0A" );
h = pGC->stipple->drawable.height;
w = pGC->stipple->drawable.width;
sz = h * BitmapBytePad( w );
bits = (char *)xalloc( sz );
fbGetImage( &(pGC->stipple->drawable), 0, 0, w, h, XYPixmap, ~0, bits );
w2 = ( w / 8 ) + ( ( w%8 ) ? 1 : 0 );
sprintf( t, "\033*c102g%dW", h * w2 + 8 );
SEND_PCL( *outFile, t );
sprintf( t, "%c%c%c%c%c%c%c%c", 0, 0, 1, 0, h>>8, h&0xff, w>>8,
w&0xff );
SEND_PCL_COUNT( *outFile, t, 8 );
for( row = bits, i = 0; i < h; i++, row += BitmapBytePad( w ) )
SEND_PCL_COUNT( *outFile, row, w2 );
SEND_PCL( *outFile, "\033%0B" );
xfree( bits );
if( pGC->depth != 1 )
sz = h * PixmapBytePad( w, pGC->depth );
bits = (char *)xalloc( sz );
scratchPix =
(*pGC->pScreen->CreatePixmap)( pGC->pScreen,
w, h, pGC->depth );
scratchGC = GetScratchGC( pGC->depth, pGC->pScreen );
CopyGC( pGC, scratchGC, ~0L );
fbValidateGC(scratchGC, ~0L, (DrawablePtr)scratchPix);
fbCopyPlane(&(pGC->stipple->drawable), (DrawablePtr)scratchPix,
scratchGC, 0, 0, w, h, 0, 0, 1);
fbGetImage(&(scratchPix->drawable), 0, 0, w, h, XYPixmap, ~0,
bits);
PclSendPattern( bits, sz, pGC->depth, h, w, 101, *outFile );
FreeScratchGC( scratchGC );
(*pGC->pScreen->DestroyPixmap)( scratchPix );
xfree( bits );
}
}
if( changeMask & ( GCTileStipXOrigin | GCTileStipYOrigin ) )
{
char t[30];
sprintf( t, "AC%d,%d;", pGC->patOrg.x, pGC->patOrg.y );
SEND_PCL( *outFile, t );
}
if( changeMask & GCDashList )
{
int num = pGC->numInDashList;
double total;
char dashes[20];
char t[100], t2[20];
for( i = 0; i < 20 && i < num; i++ )
dashes[i] = pGC->dash[i];
if( num % 2 )
{
for( i = num; i < 20 && i < num + num; i++ )
dashes[i] = dashes[i-num];
if( ( num *= 2 ) > 20 )
num = 20;
}
for( i = 0, total = 0; i < num; i++ )
total += dashes[i];
strcpy( t, "UL8" );
for( i = 0; i < num; i++ )
{
sprintf( t2, ",%d",
(int)( ( (double)dashes[i] / total * 100.0 ) + 0.5 ) );
strcat( t, t2 );
}
strcat( t, ";" );
SEND_PCL( *outFile, t );
}
SEND_PCL( *outFile, "\033%0A" );
if( changeMask )
PclSetDrawablePrivateGC( pDrawable, *pGC );
return TRUE;
}
void
PclComputeCompositeClip(
GCPtr pGC,
DrawablePtr pDrawable)
{
if (pDrawable->type == DRAWABLE_WINDOW)
{
WindowPtr pWin = (WindowPtr) pDrawable;
RegionPtr pregWin;
Bool freeTmpClip, freeCompClip;
if (pGC->subWindowMode == IncludeInferiors)
{
pregWin = NotClippedByChildren(pWin);
freeTmpClip = TRUE;
}
else
{
pregWin = &pWin->clipList;
freeTmpClip = FALSE;
}
freeCompClip = pGC->freeCompClip;
if (pGC->clientClipType == CT_NONE)
{
if (freeCompClip)
REGION_DESTROY(pGC->pScreen, pGC->pCompositeClip);
pGC->pCompositeClip = pregWin;
pGC->freeCompClip = freeTmpClip;
}
else
{
REGION_TRANSLATE(pGC->pScreen, pGC->clientClip,
pDrawable->x + pGC->clipOrg.x,
pDrawable->y + pGC->clipOrg.y);
if (freeCompClip)
{
REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
pregWin, pGC->clientClip);
if (freeTmpClip)
REGION_DESTROY(pGC->pScreen, pregWin);
}
else if (freeTmpClip)
{
REGION_INTERSECT(pGC->pScreen, pregWin, pregWin,
pGC->clientClip);
pGC->pCompositeClip = pregWin;
}
else
{
pGC->pCompositeClip = REGION_CREATE(pGC->pScreen, NullBox, 0);
REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
pregWin, pGC->clientClip);
}
pGC->freeCompClip = TRUE;
REGION_TRANSLATE(pGC->pScreen, pGC->clientClip,
-(pDrawable->x + pGC->clipOrg.x),
-(pDrawable->y + pGC->clipOrg.y));
}
}
else
{
BoxRec pixbounds;
pixbounds.x1 = 0;
pixbounds.y1 = 0;
pixbounds.x2 = pDrawable->width;
pixbounds.y2 = pDrawable->height;
if (pGC->freeCompClip)
{
REGION_RESET(pGC->pScreen, pGC->pCompositeClip, &pixbounds);
}
else
{
pGC->freeCompClip = TRUE;
pGC->pCompositeClip = REGION_CREATE(pGC->pScreen, &pixbounds, 1);
}
if (pGC->clientClipType == CT_REGION)
{
REGION_TRANSLATE(pGC->pScreen, pGC->pCompositeClip,
-pGC->clipOrg.x, -pGC->clipOrg.y);
REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
pGC->pCompositeClip, pGC->clientClip);
REGION_TRANSLATE(pGC->pScreen, pGC->pCompositeClip,
pGC->clipOrg.x, pGC->clipOrg.y);
}
}
}
void
PclValidateGC(
GCPtr pGC,
unsigned long changes,
DrawablePtr pDrawable)
{
if( pDrawable->type == DRAWABLE_PIXMAP )
{
fbValidateGC(pGC, ~0, pDrawable);
return;
}
pGC->ops = &PclGCOps;
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
)
{
PclComputeCompositeClip(pGC, pDrawable);
}
if( ( changes & GCLineStyle ) && ( pGC->lineStyle == LineDoubleDash ) )
pGC->lineStyle = LineOnOffDash;
}