437 lines
12 KiB
C
437 lines
12 KiB
C
/*******************************************************************
|
|
**
|
|
** *********************************************************
|
|
** *
|
|
** * File: PclArea.c
|
|
** *
|
|
** * Contents:
|
|
** * Image and Area functions for the PCL DDX driver
|
|
** *
|
|
** * Created: 10/23/95
|
|
** *
|
|
** *********************************************************
|
|
**
|
|
********************************************************************/
|
|
/*
|
|
(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.
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include "Pcl.h"
|
|
#include "pixmapstr.h"
|
|
#include "region.h"
|
|
|
|
#include "fb.h"
|
|
|
|
void
|
|
PclPutImage(DrawablePtr pDrawable,
|
|
GCPtr pGC,
|
|
int depth,
|
|
int x,
|
|
int y,
|
|
int w,
|
|
int h,
|
|
int leftPad,
|
|
int format,
|
|
char *pImage)
|
|
{
|
|
PixmapPtr pPixmap;
|
|
unsigned long oldFg, oldBg;
|
|
XID gcv[3];
|
|
unsigned long oldPlanemask;
|
|
unsigned long i;
|
|
long bytesPer;
|
|
|
|
if( ( w == 0 ) || ( h == 0 ) )
|
|
return;
|
|
|
|
if( format != XYPixmap )
|
|
{
|
|
pPixmap = GetScratchPixmapHeader( pDrawable->pScreen,
|
|
w+leftPad, h, depth,
|
|
BitsPerPixel( depth ),
|
|
PixmapBytePad( w + leftPad,
|
|
depth ), (pointer)pImage );
|
|
if( !pPixmap )
|
|
return;
|
|
|
|
if( format == ZPixmap )
|
|
(void)(*pGC->ops->CopyArea)( (DrawablePtr)pPixmap, pDrawable, pGC,
|
|
leftPad, 0, w, h, x, y );
|
|
else
|
|
(void)(*pGC->ops->CopyPlane)( (DrawablePtr)pPixmap, pDrawable, pGC,
|
|
leftPad, 0, w, h, x, y, 1 );
|
|
FreeScratchPixmapHeader( pPixmap );
|
|
}
|
|
else
|
|
{
|
|
pPixmap = GetScratchPixmapHeader( pDrawable->pScreen,
|
|
w+leftPad, h, depth,
|
|
BitsPerPixel( depth ),
|
|
PixmapBytePad( w + leftPad,
|
|
depth ), (pointer)pImage );
|
|
|
|
if( !pPixmap )
|
|
return;
|
|
|
|
depth = pGC->depth;
|
|
oldPlanemask = pGC->planemask;
|
|
oldFg = pGC->fgPixel;
|
|
oldBg = pGC->bgPixel;
|
|
gcv[0] = ~0L;
|
|
gcv[1] = 0;
|
|
DoChangeGC( pGC, GCForeground | GCBackground, gcv, 0 );
|
|
bytesPer = (long)h * BitmapBytePad( w + leftPad );
|
|
|
|
for( i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer )
|
|
{
|
|
if( i & oldPlanemask )
|
|
{
|
|
gcv[0] = i;
|
|
DoChangeGC( pGC, GCPlaneMask, gcv, 0 );
|
|
ValidateGC( pDrawable, pGC );
|
|
fbPutImage( (DrawablePtr)pPixmap, pGC, 1, x, y, w, h,
|
|
leftPad, XYBitmap, pImage );
|
|
}
|
|
}
|
|
gcv[0] = oldPlanemask;
|
|
gcv[1] = oldFg;
|
|
gcv[2] = oldBg;
|
|
DoChangeGC( pGC, GCPlaneMask | GCForeground | GCBackground,
|
|
gcv, 0 );
|
|
|
|
PclCopyArea( (DrawablePtr)pPixmap, pDrawable, pGC, leftPad,
|
|
0, w, h, x, y );
|
|
FreeScratchPixmapHeader( pPixmap );
|
|
}
|
|
}
|
|
|
|
/*
|
|
* PclMonoPixmapFragment()
|
|
*
|
|
* Given a 1-bit-deep pixmap, send the appropriate part of it to the
|
|
* output file as a PCL raster graphics command.
|
|
*/
|
|
static void
|
|
PclMonoPixmapFragment(FILE *outFile,
|
|
PixmapPtr pix,
|
|
short x1,
|
|
short y1,
|
|
short x2,
|
|
short y2,
|
|
short dstx,
|
|
short dsty)
|
|
{
|
|
char *bits, t[80], *row;
|
|
int h, w, i;
|
|
|
|
/*
|
|
* Create a storage area large enough to hold the entire pixmap,
|
|
* then use fbGetImage to get the appropriate bits.
|
|
*/
|
|
h = y2 - y1;
|
|
w = BitmapBytePad( x2 - x1 );
|
|
|
|
bits = (char *)xalloc( h * w );
|
|
fbGetImage( (DrawablePtr)pix, x1, y1, x2 - x1, h,
|
|
XYPixmap, ~0, bits );
|
|
|
|
/*
|
|
* Move the cursor to the appropriate place on the page. We have
|
|
* to jump into HP-GL/2 to do this correctly, then go back to PCL
|
|
* for the actual drawing.
|
|
*/
|
|
sprintf( t, "\033%%0BPU%d,%d;\033%%1A", dstx, dsty );
|
|
SEND_PCL( outFile, t );
|
|
|
|
/*
|
|
* Now, wrap the raster in the appropriate PCL code. Right now,
|
|
* it's going to go down the wire without any compression. That
|
|
* will have to be good enough for the sample implementation.
|
|
*/
|
|
sprintf( t, "\033*t300R\033*r%dT\033*r%dS\033*r1A\033*b0M",
|
|
h, x2 - x1 );
|
|
SEND_PCL( outFile, t );
|
|
|
|
sprintf( t, "\033*b%dW", w );
|
|
for( row = bits, i = 0; i <= h; i++, row += w )
|
|
{
|
|
SEND_PCL( outFile, t );
|
|
SEND_PCL_COUNT( outFile, row, w );
|
|
}
|
|
|
|
SEND_PCL( outFile, "\033*rC" );
|
|
|
|
/*
|
|
* Clean things up a bit
|
|
*/
|
|
xfree( bits );
|
|
}
|
|
|
|
static void
|
|
PclColorPixmapFragment(FILE *outFile,
|
|
PixmapPtr pix,
|
|
short x1,
|
|
short y1,
|
|
short x2,
|
|
short y2,
|
|
short dstx,
|
|
short dsty)
|
|
{
|
|
char *bits, t[80], *row;
|
|
int h, w, i;
|
|
|
|
/*
|
|
* Create a storage area large enough to hold the entire pixmap,
|
|
* then use fbGetImage to get the appropriate bits.
|
|
*/
|
|
h = y2 - y1;
|
|
w = PixmapBytePad( x2 - x1, pix->drawable.depth );
|
|
|
|
bits = (char *)xalloc( h * w );
|
|
fbGetImage( (DrawablePtr)pix, x1, y1, x2 - x1, h, ZPixmap, ~0, bits );
|
|
|
|
/*
|
|
* Move the cursor to the appropriate place on the page. We have
|
|
* to jump into HP-GL/2 to do this correctly, then go back to PCL
|
|
* for the actual drawing.
|
|
*/
|
|
sprintf( t, "\033%%0BPU%d,%d;\033%%1A", dstx, dsty );
|
|
SEND_PCL( outFile, t );
|
|
|
|
/*
|
|
* Now, wrap the raster in the appropriate PCL code. Right now,
|
|
* it's going to go down the wire without any compression. That
|
|
* will have to be good enough for the sample implementation.
|
|
*/
|
|
sprintf( t, "\033*t300R\033*r%dt%ds1A\033*b0M",
|
|
h, x2 - x1 );
|
|
SEND_PCL( outFile, t );
|
|
|
|
sprintf( t, "\033*b%dW", w );
|
|
for( row = bits, i = 0; i < h; i++, row += w )
|
|
{
|
|
SEND_PCL( outFile, t );
|
|
SEND_PCL_COUNT( outFile, row, w );
|
|
}
|
|
|
|
SEND_PCL( outFile, "\033*rC" );
|
|
|
|
/*
|
|
* Clean things up a bit
|
|
*/
|
|
xfree( bits );
|
|
}
|
|
|
|
RegionPtr
|
|
PclCopyArea(DrawablePtr pSrc,
|
|
DrawablePtr pDst,
|
|
GCPtr pGC,
|
|
int srcx,
|
|
int srcy,
|
|
int width,
|
|
int height,
|
|
int dstx,
|
|
int dsty)
|
|
{
|
|
PixmapPtr pixSrc = (PixmapPtr)pSrc;
|
|
/*
|
|
FILE *srcFile;
|
|
GC srcGC;
|
|
*/
|
|
FILE *dstFile;
|
|
GC dstGC;
|
|
unsigned long valid;
|
|
RegionPtr drawRegion, region, whole, ret;
|
|
BoxRec box;
|
|
BoxPtr prect;
|
|
int nrect;
|
|
void (*doFragment)(FILE *, PixmapPtr, short, short, short, short,
|
|
short, short );
|
|
|
|
/*
|
|
* Since we don't store any information on a per-window basis, we
|
|
* can't copy from a window.
|
|
*/
|
|
if( pSrc->type == DRAWABLE_WINDOW )
|
|
return NULL;
|
|
|
|
/*
|
|
* If we're copying from a pixmap to a pixmap, we just use the
|
|
* fb code to do the work.
|
|
*/
|
|
if( pDst->type == DRAWABLE_PIXMAP )
|
|
fbCopyArea( pSrc, pDst, pGC, srcx, srcy, width, height, dstx, dsty );
|
|
|
|
/*
|
|
PclGetDrawablePrivateStuff( pSrc, &srcGC, &valid, &srcFile );
|
|
*/
|
|
PclGetDrawablePrivateStuff( pDst, &dstGC, &valid, &dstFile );
|
|
|
|
/*
|
|
* If we're copying to a window, we have to do some actual
|
|
* drawing, instead of just handing it off to fb. Start
|
|
* by determining the region that will be drawn.
|
|
*/
|
|
box.x1 = srcx;
|
|
box.y1 = srcy;
|
|
box.x2 = srcx + width;
|
|
box.y2 = srcy + height;
|
|
drawRegion = REGION_CREATE( pGC->pScreen, &box, 0 );
|
|
REGION_TRANSLATE( pGC->pScreen, drawRegion, dstx, dsty );
|
|
|
|
region = REGION_CREATE( pGC->pScreen, NULL, 0 );
|
|
REGION_INTERSECT( pGC->pScreen, region, drawRegion, pGC->pCompositeClip );
|
|
|
|
/*
|
|
* Now select the operation to be performed on each box in the
|
|
* region.
|
|
*/
|
|
if( pSrc->depth == 1 )
|
|
doFragment = PclMonoPixmapFragment;
|
|
else
|
|
doFragment = PclColorPixmapFragment;
|
|
|
|
/*
|
|
* Actually draw each section of the bitmap.
|
|
*/
|
|
nrect = REGION_NUM_RECTS( region );
|
|
prect = REGION_RECTS( region );
|
|
|
|
while( nrect )
|
|
{
|
|
(*doFragment)( dstFile, (PixmapPtr)pSrc, prect->x1 - dstx,
|
|
prect->y1 - dsty, prect->x2 - dstx,
|
|
prect->y2 - dsty, prect->x1, prect->y1 );
|
|
|
|
nrect--;
|
|
prect++;
|
|
}
|
|
|
|
/*
|
|
* Update the destination's GC to the source's GC.
|
|
*/
|
|
/*
|
|
PclSetDrawablePrivateGC( pDst, srcGC );
|
|
*/
|
|
|
|
/*
|
|
* Determine the region that needs to be returned. This is the
|
|
* region of the source that falls outside the boundary of the
|
|
* pixmap.
|
|
*/
|
|
box.x1 = 0;
|
|
box.y1 = 0;
|
|
box.x2 = pixSrc->drawable.width;
|
|
box.y2 = pixSrc->drawable.height;
|
|
whole = REGION_CREATE( pGC->pScreen, &box, 0 );
|
|
ret = REGION_CREATE( pGC->pScreen, NULL, 0 );
|
|
|
|
REGION_TRANSLATE( pGC->pScreen, drawRegion, -dstx, -dsty );
|
|
REGION_SUBTRACT( pGC->pScreen, ret, drawRegion, whole );
|
|
|
|
/*
|
|
* Clean up the regions
|
|
*/
|
|
REGION_DESTROY( pGC->pScreen, drawRegion );
|
|
REGION_DESTROY( pGC->pScreen, region );
|
|
REGION_DESTROY( pGC->pScreen, whole );
|
|
|
|
if( REGION_NOTEMPTY( pGC->pScreen, ret ) )
|
|
return ret;
|
|
else
|
|
{
|
|
REGION_DESTROY( pGC->pScreen, ret );
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
RegionPtr
|
|
PclCopyPlane(DrawablePtr pSrc,
|
|
DrawablePtr pDst,
|
|
GCPtr pGC,
|
|
int srcx,
|
|
int srcy,
|
|
int width,
|
|
int height,
|
|
int dstx,
|
|
int dsty,
|
|
unsigned long plane)
|
|
{
|
|
RegionPtr reg;
|
|
GCPtr scratchGC;
|
|
PixmapPtr scratchPix;
|
|
|
|
/*
|
|
* Since we don't store PCL on a per-window basis, there's no good
|
|
* way to copy from a window.
|
|
*/
|
|
if( pSrc->type == DRAWABLE_WINDOW )
|
|
return NULL;
|
|
|
|
/* Copying from a pixmap to a pixmap is already implemented by fb. */
|
|
if( pSrc->type == DRAWABLE_PIXMAP &&
|
|
pDst->type == DRAWABLE_PIXMAP )
|
|
fbCopyPlane( pSrc, pDst, pGC, srcx, srcy, width, height,
|
|
dstx, dsty, plane );
|
|
|
|
/*
|
|
* We can use fbCopyPlane to do the work of grabbing the plane and
|
|
* converting it to the desired visual. Once that's done, we already
|
|
* know how to do a CopyArea.
|
|
*/
|
|
scratchPix = (*pDst->pScreen->CreatePixmap)( pDst->pScreen, width,
|
|
height, pDst->depth,
|
|
CREATE_PIXMAP_USAGE_SCRATCH );
|
|
|
|
scratchGC = GetScratchGC( pDst->depth, pDst->pScreen );
|
|
CopyGC( pGC, scratchGC, ~0L );
|
|
|
|
fbValidateGC( scratchGC, ~0L, (DrawablePtr)scratchPix );
|
|
fbCopyPlane( pSrc, (DrawablePtr)scratchPix, scratchGC,
|
|
srcx, srcy, width, height, 0, 0, plane );
|
|
|
|
reg = PclCopyArea( (DrawablePtr)scratchPix, pDst, pGC, 0, 0, width,
|
|
height, dstx, dsty );
|
|
|
|
FreeScratchGC( scratchGC );
|
|
|
|
(*pDst->pScreen->DestroyPixmap)( scratchPix );
|
|
|
|
return reg;
|
|
}
|