First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xprint / pcl / PclGC.c
blobba82c566abce5b9ecba9671ad1aeb02c9768d593
1 /*******************************************************************
2 **
3 ** *********************************************************
4 ** *
5 ** * File: PclGC.c
6 ** *
7 ** * Contents:
8 ** * Graphics Context handling for the PCL driver
9 ** *
10 ** * Created: 10/11/95
11 ** *
12 ** *********************************************************
13 **
14 ********************************************************************/
16 (c) Copyright 1996 Hewlett-Packard Company
17 (c) Copyright 1996 International Business Machines Corp.
18 (c) Copyright 1996 Sun Microsystems, Inc.
19 (c) Copyright 1996 Novell, Inc.
20 (c) Copyright 1996 Digital Equipment Corp.
21 (c) Copyright 1996 Fujitsu Limited
22 (c) Copyright 1996 Hitachi, Ltd.
24 Permission is hereby granted, free of charge, to any person obtaining a copy
25 of this software and associated documentation files (the "Software"), to deal
26 in the Software without restriction, including without limitation the rights
27 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28 copies of the Software, and to permit persons to whom the Software is
29 furnished to do so, subject to the following conditions:
31 The above copyright notice and this permission notice shall be included in
32 all copies or substantial portions of the Software.
34 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
38 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 Except as contained in this notice, the names of the copyright holders shall
42 not be used in advertising or otherwise to promote the sale, use or other
43 dealings in this Software without prior written authorization from said
44 copyright holders.
47 #ifdef HAVE_DIX_CONFIG_H
48 #include <dix-config.h>
49 #endif
51 #include "gcstruct.h"
53 #include "Pcl.h"
54 #include "pixmapstr.h"
55 #include "colormapst.h"
56 #include "windowstr.h"
57 #include "fb.h"
58 #include "scrnintstr.h"
59 #include "resource.h"
61 static GCOps PclGCOps =
63 PclFillSpans,
64 PclSetSpans,
65 PclPutImage,
66 PclCopyArea,
67 PclCopyPlane,
68 PclPolyPoint,
69 PclPolyLine,
70 PclPolySegment,
71 PclPolyRectangle,
72 PclPolyArc,
73 PclFillPolygon,
74 PclPolyFillRect,
75 PclPolyFillArc,
76 PclPolyText8,
77 PclPolyText16,
78 PclImageText8,
79 PclImageText16,
80 PclImageGlyphBlt,
81 PclPolyGlyphBlt,
82 PclPushPixels
87 static GCFuncs PclGCFuncs =
89 PclValidateGC,
90 miChangeGC,
91 miCopyGC,
92 PclDestroyGC,
93 miChangeClip,
94 miDestroyClip,
95 miCopyClip,
99 Bool
100 PclCreateGC(GCPtr pGC)
102 if (fbCreateGC(pGC) == FALSE)
103 return FALSE;
105 pGC->clientClip = NULL;
106 pGC->clientClipType = CT_NONE;
108 pGC->ops = &PclGCOps;
109 pGC->funcs = &PclGCFuncs;
111 return TRUE;
114 void
115 PclDestroyGC(GCPtr pGC)
117 /* fb doesn't specialize DestroyGC */
118 miDestroyGC( pGC );
123 PclGetDrawablePrivateStuff(
124 DrawablePtr pDrawable,
125 GC *gc,
126 unsigned long *valid,
127 FILE **file)
129 XpContextPtr pCon;
130 PclContextPrivPtr cPriv;
132 switch( pDrawable->type )
134 case DRAWABLE_PIXMAP:
136 * If we ever get here, something is wrong.
138 return FALSE;
140 case DRAWABLE_WINDOW:
141 pCon = PclGetContextFromWindow( (WindowPtr)pDrawable );
143 if( pCon == NULL )
144 return FALSE;
145 else
147 cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr;
148 *gc = cPriv->lastGC;
149 *valid = cPriv->validGC;
150 *file = cPriv->pPageFile;
151 return TRUE;
154 default:
155 return FALSE;
159 void
160 PclSetDrawablePrivateGC(
161 DrawablePtr pDrawable,
162 GC gc)
164 PixmapPtr pix;
165 XpContextPtr pCon;
166 PclPixmapPrivPtr pixPriv;
167 PclContextPrivPtr pPriv;
168 int i;
170 switch( pDrawable->type )
172 case DRAWABLE_PIXMAP:
173 pix = (PixmapPtr)pDrawable;
174 pixPriv = pix->devPrivates[PclPixmapPrivateIndex].ptr;
176 pixPriv->lastGC = gc;
177 pixPriv->validGC = 1;
178 break;
180 case DRAWABLE_WINDOW:
181 pCon = PclGetContextFromWindow( (WindowPtr)pDrawable );
182 pPriv = ((PclContextPrivPtr)
183 (pCon->devPrivates[PclContextPrivateIndex].ptr));
185 pPriv->validGC = 1;
186 pPriv->lastGC = gc;
189 * Store the dash list separately, to avoid having it freed
190 * out from under us.
192 if( pPriv->dash != NULL )
193 xfree( pPriv->dash );
194 if( gc.numInDashList != 0 )
196 pPriv->dash = (unsigned char *)xalloc( sizeof( unsigned char )
197 * gc.numInDashList );
198 for( i = 0; i < gc.numInDashList; i++ )
199 pPriv->dash[i] = gc.dash[i];
201 else
202 pPriv->dash = NULL;
206 * Store the dash list separately, to avoid having it freed
207 * out from under us.
209 if( pPriv->dash != NULL )
210 xfree( pPriv->dash );
211 if( gc.numInDashList != 0 )
213 pPriv->dash = (unsigned char *)xalloc( sizeof( unsigned char )
214 * gc.numInDashList );
215 for( i = 0; i < gc.numInDashList; i++ )
216 pPriv->dash[i] = gc.dash[i];
218 else
219 pPriv->dash = NULL;
221 break;
225 static void
226 PclSendPattern(char *bits,
227 int sz,
228 int depth,
229 int h,
230 int w,
231 int patNum,
232 FILE *outFile)
234 char t[80], *row, *mod;
235 int w2;
236 int i, j;
238 SEND_PCL( outFile, "\033%0A" );
240 if( depth == 1 )
242 /* Each row must be word-aligned */
243 w2 = ( w / 8 ) + ( ( w%8 ) ? 1 : 0 );
245 if( w2 % 2 )
246 w2++;
249 sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 );
250 SEND_PCL( outFile, t );
252 sprintf( t, "%c%c%c%c%c%c%c%c", 0, 0, 1, 0, h>>8, h&0xff, w>>8,
253 w&0xff );
254 SEND_PCL_COUNT( outFile, t, 8 );
256 for( row = bits, i = 0; i < h; i++, row += BitmapBytePad( w ) )
257 SEND_PCL_COUNT( outFile, row, w2 );
259 else if( depth == 8 )
261 w2 = ( w % 2 ) ? w + 1 : w;
263 sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 );
264 SEND_PCL( outFile, t );
266 sprintf( t, "%c%c%c%c%c%c%c%c", 1, 0, 8, 0, h>>8, h&0xff,
267 w>>8, w&0xff );
268 SEND_PCL_COUNT( outFile, t, 8 );
270 for( row = bits, i = 0; i < h; i++,
271 row += PixmapBytePad( w, 8 ) )
272 SEND_PCL_COUNT( outFile, row, w2 );
274 else
276 w2 = ( w % 2 ) ? w + 1 : w;
278 sprintf( t, "\033*c%dg%dW", patNum, h * w2 + 8 );
279 SEND_PCL( outFile, t );
281 sprintf( t, "%c%c%c%c%c%c%c%c", 1, 0, 8, 0, h>>8, h&0xff,
282 w>>8, w&0xff );
283 SEND_PCL_COUNT( outFile, t, 8 );
285 mod = (char *)xalloc( w2 );
287 for( row = bits, i = 0; i < h; i++,
288 row += PixmapBytePad( w, 24 ) )
290 char r, g, b;
291 for( j = 0; j < w2; j++ ) {
292 r = ((row[j*4+1] >> 5) & 0x7) << 5;
293 g = ((row[j*4+2] >> 5) & 0x7) << 2;
294 b = ((row[j*4+3] >> 6) & 0x3);
295 mod[j] = r | g | b;
297 SEND_PCL_COUNT( outFile, mod, w2 );
300 xfree( mod );
303 SEND_PCL( outFile, "\033%0B" );
307 PclUpdateDrawableGC(
308 GCPtr pGC,
309 DrawablePtr pDrawable,
310 FILE **outFile)
312 Mask changeMask = 0;
313 GC dGC;
314 unsigned long valid;
315 int i;
316 XpContextPtr pCon;
317 PclContextPrivPtr cPriv;
318 PclGCPrivPtr gcPriv = (PclGCPrivPtr)
319 (pGC->devPrivates[PclGCPrivateIndex].ptr);
321 if( !PclGetDrawablePrivateStuff( pDrawable, &dGC, &valid, outFile ) )
322 return FALSE;
324 pCon = PclGetContextFromWindow( (WindowPtr)pDrawable );
325 cPriv = pCon->devPrivates[PclContextPrivateIndex].ptr;
328 * Here's where we update the colormap. Since there can be
329 * different colormaps installed on each window, we need to check
330 * before each drawing request that the correct palette is active in
331 * the printer. This is as good a place as any.
333 if( !PclUpdateColormap( pDrawable, pCon, pGC, *outFile ) )
334 return FALSE;
337 * If the drawable's last GC is NULL, this means that this is
338 * the first time the drawable is being used. Therefore, we need
339 * to emit PCL for all the GC fields.
341 if( valid == 0 )
342 changeMask = ~0;
345 * If we have two different GC structures, there is no alternative
346 * but to scan through them both to determine the changeMask.
348 else
350 if( dGC.alu != pGC->alu )
351 changeMask |= GCFunction;
352 if( dGC.fgPixel != pGC->fgPixel )
353 changeMask |= GCForeground;
354 if( dGC.bgPixel != pGC->bgPixel )
355 changeMask |= GCBackground;
356 if( dGC.lineWidth != pGC->lineWidth )
357 changeMask |= GCLineWidth;
358 if( dGC.lineStyle != pGC->lineStyle )
359 changeMask |= GCLineStyle;
360 if( dGC.capStyle != pGC->capStyle )
361 changeMask |= GCCapStyle;
362 if( dGC.joinStyle != pGC->joinStyle )
363 changeMask |= GCJoinStyle;
364 if( dGC.fillStyle != pGC->fillStyle )
365 changeMask |= GCFillStyle;
366 if( dGC.tile.pixmap != pGC->tile.pixmap )
367 changeMask |= GCTile;
368 if( dGC.stipple != pGC->stipple )
369 changeMask |= GCStipple;
370 if( dGC.patOrg.x != pGC->patOrg.x )
371 changeMask |= GCTileStipXOrigin;
372 if( dGC.patOrg.y != pGC->patOrg.y )
373 changeMask |= GCTileStipYOrigin;
375 if( dGC.numInDashList == pGC->numInDashList )
377 for( i = 0; i < dGC.numInDashList; i++ )
378 if( cPriv->dash[i] != pGC->dash[i] )
380 changeMask |= GCDashList;
381 break;
384 else
385 changeMask |= GCDashList;
389 * Once the changeMask has been determined, we scan it and emit
390 * the appropriate PCL code to set the drawing attributes.
393 /* Must be in HP-GL/2 mode to set attributes */
394 SEND_PCL( *outFile, "\033%0B" );
396 if( changeMask & GCFunction )
398 #ifdef XP_PCL_COLOR
400 if( pGC->alu == GXclear )
401 SEND_PCL( *outFile, "SP0;" );
402 else
403 SEND_PCL( *outFile, "SP1;" );
404 #else
405 if( pGC->alu == GXclear )
406 SEND_PCL( *outFile, "SP0;" );
407 else
408 SEND_PCL( *outFile, "SP1;" );
409 #endif /* XP_PCL_COLOR */
412 #if 0
413 if( changeMask & GCFunction )
415 int rop = -1;
416 char t[10];
418 switch( pGC->alu )
420 case GXclear:
421 rop = 1;
422 break;
423 case GXand:
424 rop = 136;
425 break;
426 case GXandReverse:
427 rop = 68;
428 break;
429 case GXcopy:
430 rop = 204;
431 break;
432 case GXandInverted:
433 rop = 34;
434 break;
435 case GXnoop:
436 rop = 170;
437 break;
438 case GXxor:
439 rop = 238;
440 break;
441 case GXor:
442 rop = 238;
443 break;
444 case GXnor:
445 rop = 17;
446 break;
447 case GXequiv:
448 rop = 153;
449 break;
450 case GXinvert:
451 rop = 85;
452 break;
453 case GXorReverse:
454 rop = 221;
455 break;
456 case GXcopyInverted:
457 rop = 51;
458 break;
459 case GXorInverted:
460 rop = 187;
461 break;
462 case GXnand:
463 rop = 119;
464 break;
465 case GXset:
466 rop = 0;
467 break;
469 if( rop != -1 )
471 sprintf( t, "MC1,%d;", rop );
472 SEND_PCL( *outFile, t );
473 #endif
475 if( changeMask & GCForeground )
476 switch( pGC->fgPixel )
478 case 1:
479 SEND_PCL( *outFile, "SP1;" );
480 break;
481 default:
482 SEND_PCL( *outFile, "SP0;" );
483 break;
486 if( changeMask & GCForeground )
488 #ifdef XP_PCL_COLOR
489 ColormapPtr cmap;
490 Colormap c;
491 char t[40];
493 c = wColormap( ((WindowPtr)pDrawable) );
494 cmap = (ColormapPtr)LookupIDByType( c, RT_COLORMAP );
496 if( cmap->class == TrueColor )
498 if( pGC->fillStyle != FillTiled || pGC->tileIsPixel ) {
499 unsigned short r, g, b;
501 r = (pGC->fgPixel & cmap->pVisual->redMask)
502 >> (cmap->pVisual->offsetRed );
503 g = (pGC->fgPixel & cmap->pVisual->greenMask)
504 >> (cmap->pVisual->offsetGreen);
505 b = (pGC->fgPixel & cmap->pVisual->blueMask)
506 >> (cmap->pVisual->offsetBlue);
508 PclLookUp(cmap, cPriv, &r, &g, &b);
509 sprintf( t, "\033%%0A\033*v%ua%ub%uc0I\033%%0B", r, g, b);
510 SEND_PCL( *outFile, t );
513 else /* PseudoColor or StaticGray */
515 sprintf( t, "SP%ld;", (long) pGC->fgPixel );
516 SEND_PCL( *outFile, t );
518 #else
519 ScreenPtr screen;
520 screen = pDrawable->pScreen;
521 if ( pGC->fgPixel == screen->whitePixel )
522 SEND_PCL( *outFile, "SP0;");
523 else
524 SEND_PCL( *outFile, "SP1;");
525 #endif /* XP_PCL_COLOR */
528 if( changeMask & GCJoinStyle )
529 switch( pGC->joinStyle )
531 case JoinMiter:
532 SEND_PCL( *outFile, "LA2,1;" );
533 break;
534 case JoinRound:
535 SEND_PCL( *outFile, "LA2,4;" );
536 break;
537 case JoinBevel:
538 SEND_PCL( *outFile, "LA2,5;" );
539 break;
542 if( changeMask & GCCapStyle )
543 switch( pGC->capStyle )
545 case CapNotLast:
546 case CapButt:
547 SEND_PCL( *outFile, "LA1,1;" );
548 break;
549 case CapRound:
550 SEND_PCL( *outFile, "LA1,4;" );
551 break;
552 case CapProjecting:
553 SEND_PCL( *outFile, "LA1,2;" );
554 break;
557 if( changeMask & GCLineWidth )
559 float penWidth, pixelsPerMM;
560 ScreenPtr screen;
561 char temp[30];
563 if( pGC->lineWidth == 0 || pGC->lineWidth == 1 )
564 /* A pen width of 0.0 mm gives a one-pixel-wide line */
565 penWidth = 0.0;
566 else
568 screen = pDrawable->pScreen;
569 pixelsPerMM = (float)screen->width / (float)screen->mmWidth;
571 penWidth = pGC->lineWidth / pixelsPerMM;
573 sprintf( temp, "PW%g;", penWidth );
574 SEND_PCL( *outFile, temp );
577 if( changeMask & GCLineStyle )
579 int i, num = pGC->numInDashList;
580 double total;
581 char t[30];
583 switch( pGC->lineStyle )
585 case LineSolid:
586 SEND_PCL( *outFile, "LT;" );
587 break;
588 case LineOnOffDash:
590 * Calculate the pattern length of the dashes, in pixels,
591 * then convert to mm
593 for( i = 0, total = 0.0; i < 20 && i < num; i++ )
594 total += pGC->dash[i];
595 if( num % 2 )
596 for( i = num; i < 20 && i < num + num; i++ )
597 total += pGC->dash[i-num];
599 total *= ( (double)pDrawable->pScreen->mmWidth /
600 (double)pDrawable->pScreen->width );
602 sprintf( t, "LT8,%f,1;", total );
603 SEND_PCL( *outFile, t );
604 break;
609 if( changeMask & GCFillStyle )
610 switch( pGC->fillStyle )
612 case FillSolid:
613 SEND_PCL( *outFile, "FT1;TR0;CF;" );
614 break;
615 case FillTiled:
616 SEND_PCL( *outFile, "FT22,100;TR0;CF2,0;" );
617 break;
618 case FillOpaqueStippled:
619 SEND_PCL( *outFile, "FT22,101;TR0;CF2,0;" );
620 if( pGC->fgPixel != gcPriv->stippleFg ||
621 pGC->bgPixel != gcPriv->stippleBg )
622 changeMask |= GCStipple;
623 break;
624 case FillStippled:
625 SEND_PCL( *outFile, "FT22,102;TR1;CF2,0;" );
626 break;
629 if( changeMask & GCTile && !pGC->tileIsPixel )
631 char *bits;
632 int h, w, sz;
634 h = pGC->tile.pixmap->drawable.height;
635 w = pGC->tile.pixmap->drawable.width;
637 sz = h * PixmapBytePad(w, pGC->tile.pixmap->drawable.depth);
638 bits = (char *)xalloc(sz);
639 fbGetImage(&(pGC->tile.pixmap->drawable), 0, 0, w, h, XYPixmap, ~0,
640 bits);
641 PclSendPattern( bits, sz, 1, h, w, 100, *outFile );
642 xfree( bits );
645 if( changeMask & ( GCTileStipXOrigin | GCTileStipYOrigin ) )
647 char t[30];
649 sprintf( t, "AC%d,%d;", pGC->patOrg.x, pGC->patOrg.y );
650 SEND_PCL( *outFile, t );
654 * We have to resend the stipple pattern either when the stipple itself
655 * changes, or if we're in FillOpaqueStippled mode and either the
656 * foreground or the background color changes.
658 if( changeMask & GCStipple ||
659 ( pGC->fillStyle == FillOpaqueStippled &&
660 ( pGC->fgPixel != gcPriv->stippleFg ||
661 pGC->bgPixel != gcPriv->stippleBg ) ) )
663 int h, w, i, sz, w2;
664 char *bits, *row, t[30];
665 PixmapPtr scratchPix;
666 GCPtr scratchGC;
668 if( pGC->stipple != NULL )
670 SEND_PCL( *outFile, "\033%0A" );
672 h = pGC->stipple->drawable.height;
673 w = pGC->stipple->drawable.width;
674 sz = h * BitmapBytePad( w );
676 bits = (char *)xalloc( sz );
677 fbGetImage( &(pGC->stipple->drawable), 0, 0, w, h, XYPixmap, ~0, bits );
679 w2 = ( w / 8 ) + ( ( w%8 ) ? 1 : 0 );
681 * XXX The PCL docs say that I need to word-align each
682 * XXX row, but I get garbage when I do...
685 if( w2 % 2 )
686 w2++;
689 sprintf( t, "\033*c102g%dW", h * w2 + 8 );
690 SEND_PCL( *outFile, t );
692 sprintf( t, "%c%c%c%c%c%c%c%c", 0, 0, 1, 0, h>>8, h&0xff, w>>8,
693 w&0xff );
694 SEND_PCL_COUNT( *outFile, t, 8 );
696 for( row = bits, i = 0; i < h; i++, row += BitmapBytePad( w ) )
697 SEND_PCL_COUNT( *outFile, row, w2 );
699 SEND_PCL( *outFile, "\033%0B" );
701 xfree( bits );
704 * Also do the opaque stipple, as a tile
706 if( pGC->depth != 1 )
707 sz = h * PixmapBytePad( w, pGC->depth );
708 bits = (char *)xalloc( sz );
710 scratchPix =
711 (*pGC->pScreen->CreatePixmap)( pGC->pScreen,
712 w, h, pGC->depth );
713 scratchGC = GetScratchGC( pGC->depth, pGC->pScreen );
714 CopyGC( pGC, scratchGC, ~0L );
716 fbValidateGC(scratchGC, ~0L, (DrawablePtr)scratchPix);
717 fbCopyPlane(&(pGC->stipple->drawable), (DrawablePtr)scratchPix,
718 scratchGC, 0, 0, w, h, 0, 0, 1);
719 fbGetImage(&(scratchPix->drawable), 0, 0, w, h, XYPixmap, ~0,
720 bits);
721 PclSendPattern( bits, sz, pGC->depth, h, w, 101, *outFile );
722 FreeScratchGC( scratchGC );
723 (*pGC->pScreen->DestroyPixmap)( scratchPix );
724 xfree( bits );
728 if( changeMask & ( GCTileStipXOrigin | GCTileStipYOrigin ) )
730 char t[30];
732 sprintf( t, "AC%d,%d;", pGC->patOrg.x, pGC->patOrg.y );
733 SEND_PCL( *outFile, t );
736 if( changeMask & GCDashList )
738 int num = pGC->numInDashList;
739 double total;
740 char dashes[20];
741 char t[100], t2[20];
743 /* Make up the doubled dash list, if necessary */
744 for( i = 0; i < 20 && i < num; i++ )
745 dashes[i] = pGC->dash[i];
747 if( num % 2 )
749 for( i = num; i < 20 && i < num + num; i++ )
750 dashes[i] = dashes[i-num];
751 if( ( num *= 2 ) > 20 )
752 num = 20;
755 /* Add up dash lengths to get percentage */
756 for( i = 0, total = 0; i < num; i++ )
757 total += dashes[i];
759 /* Build up the HP-GL/2 for the dash list */
760 strcpy( t, "UL8" );
761 for( i = 0; i < num; i++ )
763 sprintf( t2, ",%d",
764 (int)( ( (double)dashes[i] / total * 100.0 ) + 0.5 ) );
765 strcat( t, t2 );
767 strcat( t, ";" );
768 SEND_PCL( *outFile, t );
772 /* Go back to PCL mode */
773 SEND_PCL( *outFile, "\033%0A" );
776 * Update the drawable's private information, which includes
777 * erasing the drawable's private changeMask, since all the
778 * changes have been made.
780 if( changeMask )
781 PclSetDrawablePrivateGC( pDrawable, *pGC );
783 return TRUE;
787 * PclComputeCompositeClip()
789 * I'd like to use the miComputeCompositeClip function, but it sticks
790 * things into the mi GC privates, where the PCL driver can't get at
791 * it. So, rather than mess around with the mi code, I ripped it out
792 * and made the appropriate changes here.
796 void
797 PclComputeCompositeClip(
798 GCPtr pGC,
799 DrawablePtr pDrawable)
801 if (pDrawable->type == DRAWABLE_WINDOW)
803 WindowPtr pWin = (WindowPtr) pDrawable;
804 RegionPtr pregWin;
805 Bool freeTmpClip, freeCompClip;
807 if (pGC->subWindowMode == IncludeInferiors)
809 pregWin = NotClippedByChildren(pWin);
810 freeTmpClip = TRUE;
812 else
814 pregWin = &pWin->clipList;
815 freeTmpClip = FALSE;
817 freeCompClip = pGC->freeCompClip;
820 * if there is no client clip, we can get by with just keeping the
821 * pointer we got, and remembering whether or not should destroy (or
822 * maybe re-use) it later. this way, we avoid unnecessary copying of
823 * regions. (this wins especially if many clients clip by children
824 * and have no client clip.)
826 if (pGC->clientClipType == CT_NONE)
828 if (freeCompClip)
829 REGION_DESTROY(pGC->pScreen, pGC->pCompositeClip);
830 pGC->pCompositeClip = pregWin;
831 pGC->freeCompClip = freeTmpClip;
833 else
836 * we need one 'real' region to put into the composite clip. if
837 * pregWin the current composite clip are real, we can get rid of
838 * one. if pregWin is real and the current composite clip isn't,
839 * use pregWin for the composite clip. if the current composite
840 * clip is real and pregWin isn't, use the current composite
841 * clip. if neither is real, create a new region.
844 REGION_TRANSLATE(pGC->pScreen, pGC->clientClip,
845 pDrawable->x + pGC->clipOrg.x,
846 pDrawable->y + pGC->clipOrg.y);
848 if (freeCompClip)
850 REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
851 pregWin, pGC->clientClip);
852 if (freeTmpClip)
853 REGION_DESTROY(pGC->pScreen, pregWin);
855 else if (freeTmpClip)
857 REGION_INTERSECT(pGC->pScreen, pregWin, pregWin,
858 pGC->clientClip);
859 pGC->pCompositeClip = pregWin;
861 else
863 pGC->pCompositeClip = REGION_CREATE(pGC->pScreen, NullBox, 0);
864 REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
865 pregWin, pGC->clientClip);
867 pGC->freeCompClip = TRUE;
868 REGION_TRANSLATE(pGC->pScreen, pGC->clientClip,
869 -(pDrawable->x + pGC->clipOrg.x),
870 -(pDrawable->y + pGC->clipOrg.y));
872 } /* end of composite clip for a window */
873 else
875 BoxRec pixbounds;
877 /* XXX should we translate by drawable.x/y here ? */
878 pixbounds.x1 = 0;
879 pixbounds.y1 = 0;
880 pixbounds.x2 = pDrawable->width;
881 pixbounds.y2 = pDrawable->height;
883 if (pGC->freeCompClip)
885 REGION_RESET(pGC->pScreen, pGC->pCompositeClip, &pixbounds);
887 else
889 pGC->freeCompClip = TRUE;
890 pGC->pCompositeClip = REGION_CREATE(pGC->pScreen, &pixbounds, 1);
893 if (pGC->clientClipType == CT_REGION)
895 REGION_TRANSLATE(pGC->pScreen, pGC->pCompositeClip,
896 -pGC->clipOrg.x, -pGC->clipOrg.y);
897 REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
898 pGC->pCompositeClip, pGC->clientClip);
899 REGION_TRANSLATE(pGC->pScreen, pGC->pCompositeClip,
900 pGC->clipOrg.x, pGC->clipOrg.y);
902 } /* end of composite clip for pixmap */
906 * PclValidateGC()
908 * Unlike many screen GCValidate routines, this function should not need
909 * to mess with setting the drawing functions. Different drawing
910 * functions are usually needed to optimize such things as drawing
911 * wide or dashed lines; this functionality will be handled primarily
912 * by the printer itself, while the necessary PCL code to set the
913 * attributes will be done in PclUpdateDrawableGC().
916 /*ARGSUSED*/
917 void
918 PclValidateGC(
919 GCPtr pGC,
920 unsigned long changes,
921 DrawablePtr pDrawable)
924 * Pixmaps should be handled by their respective validation
925 * functions.
927 if( pDrawable->type == DRAWABLE_PIXMAP )
929 fbValidateGC(pGC, ~0, pDrawable);
930 return;
934 * Reset the drawing operations
936 pGC->ops = &PclGCOps;
939 * Validate the information, and correct it if necessary.
943 * If necessary, compute the composite clip region. (Code ripped
944 * from migc.c)
946 if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
947 (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
950 PclComputeCompositeClip(pGC, pDrawable);
954 * PCL does not directly support the DoubleDash line style, nor is
955 * there an easy way to simulate it, so we'll just change it to a
956 * LineOnOffDash, which is supported by PCL.
958 if( ( changes & GCLineStyle ) && ( pGC->lineStyle == LineDoubleDash ) )
959 pGC->lineStyle = LineOnOffDash;
962 * Update the drawable's changeMask to reflect the changes made to the GC.
965 PclSetDrawablePrivateGC( pDrawable, *pGC, changes );