]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mfb/mfbgc.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / mfb / mfbgc.c
1 /***********************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ******************************************************************/
48 /* $XConsortium: mfbgc.c,v 5.35 94/04/17 20:28:23 dpw Exp $ */
49 #include "X.h"
50 #include "Xmd.h"
51 #include "Xproto.h"
52 #include "mfb.h"
53 #include "dixfontstr.h"
54 #include "fontstruct.h"
55 #include "gcstruct.h"
56 #include "windowstr.h"
57 #include "pixmapstr.h"
58 #include "scrnintstr.h"
59 #include "region.h"
60
61 #include "mistruct.h"
62 #include "migc.h"
63
64 #include "maskbits.h"
65
66 static GCFuncs  mfbFuncs = {
67         mfbValidateGC,
68         miChangeGC,
69         miCopyGC,
70         miDestroyGC,
71         miChangeClip,
72         miDestroyClip,
73         miCopyClip
74 };
75
76 static GCOps    whiteTECopyOps = {
77         mfbWhiteSolidFS,
78         mfbSetSpans,
79         mfbPutImage,
80         mfbCopyArea,
81         mfbCopyPlane,
82         mfbPolyPoint,
83         mfbLineSS,
84         mfbSegmentSS,
85         miPolyRectangle,
86         mfbZeroPolyArcSS,
87         mfbFillPolyWhite,
88         mfbPolyFillRect,
89         mfbPolyFillArcSolid,
90         miPolyText8,
91         miPolyText16,
92         miImageText8,
93         miImageText16,
94         mfbTEGlyphBltWhite,
95         mfbPolyGlyphBltWhite,
96         mfbSolidPP
97 #ifdef NEED_LINEHELPER
98         ,NULL
99 #endif
100 };
101
102 static GCOps    blackTECopyOps = {
103         mfbBlackSolidFS,
104         mfbSetSpans,
105         mfbPutImage,
106         mfbCopyArea,
107         mfbCopyPlane,
108         mfbPolyPoint,
109         mfbLineSS,
110         mfbSegmentSS,
111         miPolyRectangle,
112         mfbZeroPolyArcSS,
113         mfbFillPolyBlack,
114         mfbPolyFillRect,
115         mfbPolyFillArcSolid,
116         miPolyText8,
117         miPolyText16,
118         miImageText8,
119         miImageText16,
120         mfbTEGlyphBltBlack,
121         mfbPolyGlyphBltBlack,
122         mfbSolidPP
123 #ifdef NEED_LINEHELPER
124         ,NULL
125 #endif
126 };
127
128 static GCOps    whiteTEInvertOps = {
129         mfbInvertSolidFS,
130         mfbSetSpans,
131         mfbPutImage,
132         mfbCopyArea,
133         mfbCopyPlane,
134         mfbPolyPoint,
135         mfbLineSS,
136         mfbSegmentSS,
137         miPolyRectangle,
138         miZeroPolyArc,
139         mfbFillPolyInvert,
140         mfbPolyFillRect,
141         mfbPolyFillArcSolid,
142         miPolyText8,
143         miPolyText16,
144         miImageText8,
145         miImageText16,
146         mfbTEGlyphBltWhite,
147         mfbPolyGlyphBltInvert,
148         mfbSolidPP
149 #ifdef NEED_LINEHELPER
150         ,NULL
151 #endif
152 };
153
154 static GCOps    blackTEInvertOps = {
155         mfbInvertSolidFS,
156         mfbSetSpans,
157         mfbPutImage,
158         mfbCopyArea,
159         mfbCopyPlane,
160         mfbPolyPoint,
161         mfbLineSS,
162         mfbSegmentSS,
163         miPolyRectangle,
164         miZeroPolyArc,
165         mfbFillPolyInvert,
166         mfbPolyFillRect,
167         mfbPolyFillArcSolid,
168         miPolyText8,
169         miPolyText16,
170         miImageText8,
171         miImageText16,
172         mfbTEGlyphBltBlack,
173         mfbPolyGlyphBltInvert,
174         mfbSolidPP
175 #ifdef NEED_LINEHELPER
176         ,NULL
177 #endif
178 };
179
180 static GCOps    whiteCopyOps = {
181         mfbWhiteSolidFS,
182         mfbSetSpans,
183         mfbPutImage,
184         mfbCopyArea,
185         mfbCopyPlane,
186         mfbPolyPoint,
187         mfbLineSS,
188         mfbSegmentSS,
189         miPolyRectangle,
190         mfbZeroPolyArcSS,
191         mfbFillPolyWhite,
192         mfbPolyFillRect,
193         mfbPolyFillArcSolid,
194         miPolyText8,
195         miPolyText16,
196         miImageText8,
197         miImageText16,
198         mfbImageGlyphBltWhite,
199         mfbPolyGlyphBltWhite,
200         mfbSolidPP
201 #ifdef NEED_LINEHELPER
202         ,NULL
203 #endif
204 };
205
206 static GCOps    blackCopyOps = {
207         mfbBlackSolidFS,
208         mfbSetSpans,
209         mfbPutImage,
210         mfbCopyArea,
211         mfbCopyPlane,
212         mfbPolyPoint,
213         mfbLineSS,
214         mfbSegmentSS,
215         miPolyRectangle,
216         mfbZeroPolyArcSS,
217         mfbFillPolyBlack,
218         mfbPolyFillRect,
219         mfbPolyFillArcSolid,
220         miPolyText8,
221         miPolyText16,
222         miImageText8,
223         miImageText16,
224         mfbImageGlyphBltBlack,
225         mfbPolyGlyphBltBlack,
226         mfbSolidPP
227 #ifdef NEED_LINEHELPER
228         ,NULL
229 #endif
230 };
231
232 static GCOps    whiteInvertOps = {
233         mfbInvertSolidFS,
234         mfbSetSpans,
235         mfbPutImage,
236         mfbCopyArea,
237         mfbCopyPlane,
238         mfbPolyPoint,
239         mfbLineSS,
240         mfbSegmentSS,
241         miPolyRectangle,
242         miZeroPolyArc,
243         mfbFillPolyInvert,
244         mfbPolyFillRect,
245         mfbPolyFillArcSolid,
246         miPolyText8,
247         miPolyText16,
248         miImageText8,
249         miImageText16,
250         mfbImageGlyphBltWhite,
251         mfbPolyGlyphBltInvert,
252         mfbSolidPP
253 #ifdef NEED_LINEHELPER
254         ,NULL
255 #endif
256 };
257
258 static GCOps    blackInvertOps = {
259         mfbInvertSolidFS,
260         mfbSetSpans,
261         mfbPutImage,
262         mfbCopyArea,
263         mfbCopyPlane,
264         mfbPolyPoint,
265         mfbLineSS,
266         mfbSegmentSS,
267         miPolyRectangle,
268         miZeroPolyArc,
269         mfbFillPolyInvert,
270         mfbPolyFillRect,
271         mfbPolyFillArcSolid,
272         miPolyText8,
273         miPolyText16,
274         miImageText8,
275         miImageText16,
276         mfbImageGlyphBltBlack,
277         mfbPolyGlyphBltInvert,
278         mfbSolidPP
279 #ifdef NEED_LINEHELPER
280         ,NULL
281 #endif
282 };
283
284 static GCOps    whiteWhiteCopyOps = {
285         mfbWhiteSolidFS,
286         mfbSetSpans,
287         mfbPutImage,
288         mfbCopyArea,
289         mfbCopyPlane,
290         mfbPolyPoint,
291         mfbLineSS,
292         mfbSegmentSS,
293         miPolyRectangle,
294         mfbZeroPolyArcSS,
295         mfbFillPolyWhite,
296         mfbPolyFillRect,
297         mfbPolyFillArcSolid,
298         miPolyText8,
299         miPolyText16,
300         miImageText8,
301         miImageText16,
302         miImageGlyphBlt,
303         mfbPolyGlyphBltWhite,
304         mfbSolidPP
305 #ifdef NEED_LINEHELPER
306         ,NULL
307 #endif
308 };
309
310 static GCOps    blackBlackCopyOps = {
311         mfbBlackSolidFS,
312         mfbSetSpans,
313         mfbPutImage,
314         mfbCopyArea,
315         mfbCopyPlane,
316         mfbPolyPoint,
317         mfbLineSS,
318         mfbSegmentSS,
319         miPolyRectangle,
320         mfbZeroPolyArcSS,
321         mfbFillPolyBlack,
322         mfbPolyFillRect,
323         mfbPolyFillArcSolid,
324         miPolyText8,
325         miPolyText16,
326         miImageText8,
327         miImageText16,
328         miImageGlyphBlt,
329         mfbPolyGlyphBltBlack,
330         mfbSolidPP
331 #ifdef NEED_LINEHELPER
332         ,NULL
333 #endif
334 };
335
336 static GCOps    fgEqBgInvertOps = {
337         mfbInvertSolidFS,
338         mfbSetSpans,
339         mfbPutImage,
340         mfbCopyArea,
341         mfbCopyPlane,
342         mfbPolyPoint,
343         mfbLineSS,
344         mfbSegmentSS,
345         miPolyRectangle,
346         miZeroPolyArc,
347         mfbFillPolyInvert,
348         mfbPolyFillRect,
349         mfbPolyFillArcSolid,
350         miPolyText8,
351         miPolyText16,
352         miImageText8,
353         miImageText16,
354         miImageGlyphBlt,
355         mfbPolyGlyphBltInvert,
356         mfbSolidPP
357 #ifdef NEED_LINEHELPER
358         ,NULL
359 #endif
360 };
361
362 struct commonOps {
363     int             fg, bg;
364     int             rrop;
365     int             terminalFont;
366     GCOps           *ops;
367     void            (*fillArea)();
368 };
369
370 static struct commonOps mfbCommonOps[] = {
371     { 1, 0, RROP_WHITE, 1, &whiteTECopyOps, mfbSolidWhiteArea },
372     { 0, 1, RROP_BLACK, 1, &blackTECopyOps, mfbSolidBlackArea },
373     { 1, 0, RROP_INVERT, 1, &whiteTEInvertOps, mfbSolidInvertArea },
374     { 0, 1, RROP_INVERT, 1, &blackTEInvertOps, mfbSolidInvertArea },
375     { 1, 0, RROP_WHITE, 0, &whiteCopyOps, mfbSolidWhiteArea },
376     { 0, 1, RROP_BLACK, 0, &blackCopyOps, mfbSolidBlackArea },
377     { 1, 0, RROP_INVERT, 0, &whiteInvertOps, mfbSolidInvertArea },
378     { 0, 1, RROP_INVERT, 0, &blackInvertOps, mfbSolidInvertArea },
379     { 1, 1, RROP_WHITE, 0, &whiteWhiteCopyOps, mfbSolidWhiteArea },
380     { 0, 0, RROP_BLACK, 0, &blackBlackCopyOps, mfbSolidBlackArea },
381     { 1, 1, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
382     { 0, 0, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
383 };
384
385 #define numberCommonOps (sizeof (mfbCommonOps) / sizeof (mfbCommonOps[0]))
386
387 static GCOps *
388 matchCommon (pGC)
389     GCPtr   pGC;
390 {
391     int i;
392     struct commonOps    *cop;
393     mfbPrivGC           *priv;
394
395     if (pGC->lineWidth != 0)
396         return 0;
397     if (pGC->lineStyle != LineSolid)
398         return 0;
399     if (pGC->fillStyle != FillSolid)
400         return 0;
401     if (!pGC->font ||
402         FONTMAXBOUNDS(pGC->font,rightSideBearing) -
403         FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
404         FONTMINBOUNDS(pGC->font,characterWidth) < 0)
405         return 0;
406     priv = (mfbPrivGC *) pGC->devPrivates[mfbGCPrivateIndex].ptr;
407     for (i = 0; i < numberCommonOps; i++) {
408         cop = &mfbCommonOps[i];
409         if ((pGC->fgPixel & 1) != cop->fg)
410             continue;
411         if ((pGC->bgPixel & 1) != cop->bg)
412             continue;
413         if (priv->rop != cop->rrop)
414             continue;
415         if (cop->terminalFont && !TERMINALFONT(pGC->font))
416             continue;
417         priv->FillArea = cop->fillArea;
418         return cop->ops;
419     }
420     return 0;
421 }
422
423 Bool
424 mfbCreateGC(pGC)
425     register GCPtr pGC;
426 {
427     mfbPrivGC   *pPriv;
428
429     pGC->clientClip = NULL;
430     pGC->clientClipType = CT_NONE;
431     
432     /* some of the output primitives aren't really necessary, since
433        they will be filled in ValidateGC because of dix/CreateGC()
434        setting all the change bits.  Others are necessary because although
435        they depend on being a monochrome frame buffer, they don't change 
436     */
437
438     pGC->ops = &whiteCopyOps;
439     pGC->funcs = &mfbFuncs;
440
441     /* mfb wants to translate before scan convesion */
442     pGC->miTranslate = 1;
443
444     pPriv = (mfbPrivGC *)(pGC->devPrivates[mfbGCPrivateIndex].ptr);
445     pPriv->rop = mfbReduceRop(pGC->alu, pGC->fgPixel);
446     pPriv->fExpose = TRUE;
447     pPriv->pRotatedPixmap = NullPixmap;
448     pPriv->freeCompClip = FALSE;
449     pPriv->FillArea = mfbSolidInvertArea;
450     return TRUE;
451 }
452
453 /* Clipping conventions
454         if the drawable is a window
455             CT_REGION ==> pCompositeClip really is the composite
456             CT_other ==> pCompositeClip is the window clip region
457         if the drawable is a pixmap
458             CT_REGION ==> pCompositeClip is the translated client region
459                 clipped to the pixmap boundary
460             CT_other ==> pCompositeClip is the pixmap bounding box
461 */
462
463 /*ARGSUSED*/
464 void
465 mfbValidateGC(pGC, changes, pDrawable)
466     register GCPtr      pGC;
467     unsigned long       changes;
468     DrawablePtr         pDrawable;
469 {
470     register mfbPrivGCPtr       devPriv;
471     int mask;                   /* stateChanges */
472     int index;                  /* used for stepping through bitfields */
473     int xrot, yrot;             /* rotations for tile and stipple pattern */
474     int rrop;                   /* reduced rasterop */
475                                 /* flags for changing the proc vector 
476                                    and updating things in devPriv
477                                 */
478     int new_rotate, new_rrop,  new_line, new_text, new_fill;
479     DDXPointRec oldOrg;         /* origin of thing GC was last used with */
480
481     oldOrg = pGC->lastWinOrg;
482
483     pGC->lastWinOrg.x = pDrawable->x;
484     pGC->lastWinOrg.y = pDrawable->y;
485
486     /* we need to re-rotate the tile if the previous window/pixmap
487        origin (oldOrg) differs from the new window/pixmap origin
488        (pGC->lastWinOrg)
489     */
490     new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
491                  (oldOrg.y != pGC->lastWinOrg.y);
492
493     devPriv = ((mfbPrivGCPtr) (pGC->devPrivates[mfbGCPrivateIndex].ptr));
494
495     /*
496         if the client clip is different or moved OR
497         the subwindowMode has changed OR
498         the window's clip has changed since the last validation
499         we need to recompute the composite clip
500     */
501     if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
502         (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
503        )
504     {
505         miComputeCompositeClip(pGC, pDrawable);
506     }
507
508     new_rrop = FALSE;
509     new_line = FALSE;
510     new_text = FALSE;
511     new_fill = FALSE;
512
513     mask = changes;
514     while (mask)
515     {
516         index = lowbit (mask);
517         mask &= ~index;
518
519         /* this switch acculmulates a list of which procedures
520            might have to change due to changes in the GC.  in
521            some cases (e.g. changing one 16 bit tile for another)
522            we might not really need a change, but the code is
523            being paranoid.
524            this sort of batching wins if, for example, the alu
525            and the font have been changed, or any other pair
526            of items that both change the same thing.
527         */
528         switch (index)
529         {
530           case GCFunction:
531           case GCForeground:
532             new_rrop = TRUE;
533             break;
534           case GCPlaneMask:
535             break;
536           case GCBackground:
537             new_rrop = TRUE;    /* for opaque stipples */
538             break;
539           case GCLineStyle:
540           case GCLineWidth:
541           case GCJoinStyle:
542             new_line = TRUE;
543             break;
544           case GCCapStyle:
545             break;
546           case GCFillStyle:
547             new_fill = TRUE;
548             break;
549           case GCFillRule:
550             break;
551           case GCTile:
552             if(pGC->tileIsPixel)
553                 break;
554             new_rotate = TRUE;
555             new_fill = TRUE;
556             break;
557
558           case GCStipple:
559             if(pGC->stipple == (PixmapPtr)NULL)
560                 break;
561             new_rotate = TRUE;
562             new_fill = TRUE;
563             break;
564
565           case GCTileStipXOrigin:
566             new_rotate = TRUE;
567             break;
568
569           case GCTileStipYOrigin:
570             new_rotate = TRUE;
571             break;
572
573           case GCFont:
574             new_text = TRUE;
575             break;
576           case GCSubwindowMode:
577             break;
578           case GCGraphicsExposures:
579             break;
580           case GCClipXOrigin:
581             break;
582           case GCClipYOrigin:
583             break;
584           case GCClipMask:
585             break;
586           case GCDashOffset:
587             break;
588           case GCDashList:
589             break;
590           case GCArcMode:
591             break;
592           default:
593             break;
594         }
595     }
596
597     /* deal with the changes we've collected .
598        new_rrop must be done first because subsequent things
599        depend on it.
600     */
601
602     if(new_rotate || new_fill)
603     {
604         Bool new_pix = FALSE;
605
606         /* figure out how much to rotate */
607         xrot = pGC->patOrg.x;
608         yrot = pGC->patOrg.y;
609         xrot += pDrawable->x;
610         yrot += pDrawable->y;
611
612         switch (pGC->fillStyle)
613         {
614         case FillTiled:
615             /* copy current tile and stipple */
616             if (!pGC->tileIsPixel && (pGC->tile.pixmap->drawable.width <= PPW) &&
617                 !(pGC->tile.pixmap->drawable.width & (pGC->tile.pixmap->drawable.width - 1)))
618             {
619                 mfbCopyRotatePixmap(pGC->tile.pixmap,
620                                     &devPriv->pRotatedPixmap, xrot, yrot);
621                 new_pix = TRUE;
622             }
623             break;
624         case FillStippled:
625         case FillOpaqueStippled:
626             if (pGC->stipple && (pGC->stipple->drawable.width <= PPW) &&
627                 !(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1)))
628             {
629                 mfbCopyRotatePixmap(pGC->stipple,
630                                     &devPriv->pRotatedPixmap, xrot, yrot);
631                 new_pix = TRUE;
632             }
633         }
634         /* destroy any previously rotated tile or stipple */
635         if (!new_pix && devPriv->pRotatedPixmap)
636         {
637             (*pDrawable->pScreen->DestroyPixmap)(devPriv->pRotatedPixmap);
638             devPriv->pRotatedPixmap = (PixmapPtr)NULL;
639         }
640     }
641
642     /*
643      * duck out here when the GC is unchanged
644      */
645
646     if (!changes)
647         return;
648
649     if (new_rrop || new_fill)
650     {
651         rrop = mfbReduceRop(pGC->alu, pGC->fgPixel);
652         devPriv->rop = rrop;
653         new_fill = TRUE;
654         /* FillArea raster op is GC's for tile filling,
655            and the reduced rop for solid and stipple
656         */
657         if (pGC->fillStyle == FillTiled)
658             devPriv->ropFillArea = pGC->alu;
659         else
660             devPriv->ropFillArea = rrop;
661
662         /* opaque stipples:
663            fg   bg      ropOpStip       fill style
664            1    0       alu             tile
665            0    1       inverseAlu      tile
666            1    1       rrop(fg, alu)   solid
667            0    0       rrop(fg, alu)   solid
668         Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to
669         compute it.
670         */
671         if (pGC->fillStyle == FillOpaqueStippled)
672         {
673             if ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))
674             {
675                 if (pGC->fgPixel & 1)
676                     devPriv->ropOpStip = pGC->alu;
677                 else
678                     devPriv->ropOpStip = InverseAlu[pGC->alu];
679             }
680             else
681                 devPriv->ropOpStip = rrop;
682             devPriv->ropFillArea = devPriv->ropOpStip;
683         }
684     }
685     else
686         rrop = devPriv->rop;
687
688     if (new_line || new_fill || new_text)
689     {
690         GCOps   *newops;
691
692         if (newops = matchCommon (pGC))
693         {
694             if (pGC->ops->devPrivate.val)
695                 miDestroyGCOps (pGC->ops);
696             pGC->ops = newops;
697             new_line = new_fill = new_text = 0;
698         }
699         else
700         {
701             if (!pGC->ops->devPrivate.val)
702             {
703                 pGC->ops = miCreateGCOps (pGC->ops);
704                 pGC->ops->devPrivate.val = 1;
705             }
706         }
707     }
708
709     if (new_line || new_fill)
710     {
711         if (pGC->lineWidth == 0)
712         {
713             if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)
714                 && ((rrop == RROP_WHITE) || (rrop == RROP_BLACK)))
715                 pGC->ops->PolyArc = mfbZeroPolyArcSS;
716             else
717                 pGC->ops->PolyArc = miZeroPolyArc;
718         }
719         else
720             pGC->ops->PolyArc = miPolyArc;
721         if (pGC->lineStyle == LineSolid)
722         {
723             if(pGC->lineWidth == 0)
724             {
725                 if (pGC->fillStyle == FillSolid)
726                 {
727                     pGC->ops->PolySegment = mfbSegmentSS;
728                     pGC->ops->Polylines = mfbLineSS;
729                 }
730                 else
731                 {
732                     pGC->ops->PolySegment = miPolySegment;
733                     pGC->ops->Polylines = miZeroLine;
734                 }
735             }
736             else
737             {
738                 pGC->ops->PolySegment = miPolySegment;
739                 pGC->ops->Polylines = miWideLine;
740             }
741         }
742         else
743         {
744             if(pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
745             {
746                 pGC->ops->Polylines = mfbLineSD;
747                 pGC->ops->PolySegment = mfbSegmentSD;
748             }
749             else
750             {
751                 pGC->ops->Polylines = miWideDash;
752                 pGC->ops->PolySegment = miPolySegment;
753             }
754         }
755     }
756
757     if (new_text || new_fill)
758     {
759         if ((pGC->font) &&
760             (FONTMAXBOUNDS(pGC->font,rightSideBearing) -
761              FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
762              FONTMINBOUNDS(pGC->font,characterWidth) < 0))
763         {
764             pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
765             pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
766         }
767         else
768         {
769             /* special case ImageGlyphBlt for terminal emulator fonts */
770             if ((pGC->font) &&
771                 TERMINALFONT(pGC->font) &&
772                 ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)))
773             {
774                 /* pcc bug makes this not compile...
775                 pGC->ops->ImageGlyphBlt = (pGC->fgPixel & 1) ? mfbTEGlyphBltWhite :
776                                                       mfbTEGlyphBltBlack;
777                 */
778                 if (pGC->fgPixel & 1)
779                     pGC->ops->ImageGlyphBlt = mfbTEGlyphBltWhite;
780                 else
781                     pGC->ops->ImageGlyphBlt = mfbTEGlyphBltBlack;
782             }
783             else
784             {
785                 if (pGC->fgPixel & 1)
786                     pGC->ops->ImageGlyphBlt = mfbImageGlyphBltWhite;
787                 else
788                     pGC->ops->ImageGlyphBlt = mfbImageGlyphBltBlack;
789             }
790
791             /* now do PolyGlyphBlt */
792             if (pGC->fillStyle == FillSolid ||
793                 (pGC->fillStyle == FillOpaqueStippled &&
794                  (pGC->fgPixel & 1) == (pGC->bgPixel & 1)
795                 )
796                )
797             {
798                 if (rrop == RROP_WHITE)
799                     pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltWhite;
800                 else if (rrop == RROP_BLACK)
801                     pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltBlack;
802                 else if (rrop == RROP_INVERT)
803                     pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltInvert;
804                 else
805                     pGC->ops->PolyGlyphBlt = (void (*)())NoopDDA;
806             }
807             else
808             {
809                 pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
810             }
811         }
812     }
813
814     if (new_fill)
815     {
816         /* install a suitable fillspans and pushpixels */
817         pGC->ops->PushPixels = mfbPushPixels;
818         pGC->ops->FillPolygon = miFillPolygon;
819         if ((pGC->fillStyle == FillSolid) ||
820             ((pGC->fillStyle == FillOpaqueStippled) &&
821              ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))))
822         {
823             pGC->ops->PushPixels = mfbSolidPP;
824             switch(devPriv->rop)
825             {
826               case RROP_WHITE:
827                 pGC->ops->FillSpans = mfbWhiteSolidFS;
828                 pGC->ops->FillPolygon = mfbFillPolyWhite;
829                 break;
830               case RROP_BLACK:
831                 pGC->ops->FillSpans = mfbBlackSolidFS;
832                 pGC->ops->FillPolygon = mfbFillPolyBlack;
833                 break;
834               case RROP_INVERT:
835                 pGC->ops->FillSpans = mfbInvertSolidFS;
836                 pGC->ops->FillPolygon = mfbFillPolyInvert;
837                 break;
838               case RROP_NOP:
839                 pGC->ops->FillSpans = (void (*)())NoopDDA;
840                 pGC->ops->FillPolygon = (void (*)())NoopDDA;
841                 break;
842             }
843         }
844         /* beyond this point, opaqueStippled ==> fg != bg */
845         else if (((pGC->fillStyle == FillTiled) ||
846                   (pGC->fillStyle == FillOpaqueStippled)) &&
847                  !devPriv->pRotatedPixmap)
848         {
849             pGC->ops->FillSpans = mfbUnnaturalTileFS;
850         }
851         else if ((pGC->fillStyle == FillStippled) && !devPriv->pRotatedPixmap)
852         {
853             pGC->ops->FillSpans = mfbUnnaturalStippleFS;
854         }
855         else if (pGC->fillStyle == FillStippled)
856         {
857             switch(devPriv->rop)
858             {
859               case RROP_WHITE:
860                 pGC->ops->FillSpans = mfbWhiteStippleFS;
861                 break;
862               case RROP_BLACK:
863                 pGC->ops->FillSpans = mfbBlackStippleFS;
864                 break;
865               case RROP_INVERT:
866                 pGC->ops->FillSpans = mfbInvertStippleFS;
867                 break;
868               case RROP_NOP:
869                 pGC->ops->FillSpans = (void (*)())NoopDDA;
870                 break;
871             }
872         }
873         else /* overload tiles to do parti-colored opaque stipples */
874         {
875             pGC->ops->FillSpans = mfbTileFS;
876         }
877         if (pGC->fillStyle == FillSolid)
878             pGC->ops->PolyFillArc = mfbPolyFillArcSolid;
879         else
880             pGC->ops->PolyFillArc = miPolyFillArc;
881         /* the rectangle code doesn't deal with opaque stipples that
882            are two colors -- we can fool it for fg==bg, though
883          */
884         if ((((pGC->fillStyle == FillTiled) ||
885               (pGC->fillStyle == FillStippled)) &&
886              !devPriv->pRotatedPixmap) ||
887             ((pGC->fillStyle == FillOpaqueStippled) &&
888              ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)))
889            )
890         {
891             pGC->ops->PolyFillRect = miPolyFillRect;
892         }
893         else /* deal with solids and natural stipples and tiles */
894         {
895             pGC->ops->PolyFillRect = mfbPolyFillRect;
896
897             if ((pGC->fillStyle == FillSolid) ||
898                 ((pGC->fillStyle == FillOpaqueStippled) &&
899                  ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))))
900             {
901                 switch(devPriv->rop)
902                 {
903                   case RROP_WHITE:
904                     devPriv->FillArea = mfbSolidWhiteArea;
905                     break;
906                   case RROP_BLACK:
907                     devPriv->FillArea = mfbSolidBlackArea;
908                     break;
909                   case RROP_INVERT:
910                     devPriv->FillArea = mfbSolidInvertArea;
911                     break;
912                   case RROP_NOP:
913                     devPriv->FillArea = (void (*)())NoopDDA;
914                     break;
915                 }
916             }
917             else if (pGC->fillStyle == FillStippled)
918             {
919                 switch(devPriv->rop)
920                 {
921                   case RROP_WHITE:
922                     devPriv->FillArea = mfbStippleWhiteArea;
923                     break;
924                   case RROP_BLACK:
925                     devPriv->FillArea = mfbStippleBlackArea;
926                     break;
927                   case RROP_INVERT:
928                     devPriv->FillArea = mfbStippleInvertArea;
929                     break;
930                   case RROP_NOP:
931                     devPriv->FillArea = (void (*)())NoopDDA;
932                     break;
933                 }
934             }
935             else /* deal with tiles */
936             {
937                 switch (pGC->alu)
938                 {
939                   case GXcopy:
940                     devPriv->FillArea = mfbTileAreaPPWCopy;
941                     break;
942                   default:
943                     devPriv->FillArea = mfbTileAreaPPWGeneral;
944                     break;
945                 }
946             }
947         } /* end of natural rectangles */
948     } /* end of new_fill */
949 }
950
951 /* table to map alu(src, dst) to alu(~src, dst) */
952 int InverseAlu[16] = {
953         GXclear,
954         GXandInverted,
955         GXnor,
956         GXcopyInverted,
957         GXand,
958         GXnoop,
959         GXequiv,
960         GXorInverted,
961         GXandReverse,
962         GXxor,
963         GXinvert,
964         GXnand,
965         GXcopy,
966         GXor,
967         GXorReverse,
968         GXset
969 };
970
971 int
972 mfbReduceRop(alu, src)
973     register int alu;
974     register Pixel src;
975 {
976     int rop;
977     if ((src & 1) == 0) /* src is black */
978     {
979         switch(alu)
980         {
981           case GXclear:
982             rop = RROP_BLACK;
983             break;
984           case GXand:
985             rop = RROP_BLACK;
986             break;
987           case GXandReverse:
988             rop = RROP_BLACK;
989             break;
990           case GXcopy:
991             rop = RROP_BLACK;
992             break;
993           case GXandInverted:
994             rop = RROP_NOP;
995             break;
996           case GXnoop:
997             rop = RROP_NOP;
998             break;
999           case GXxor:
1000             rop = RROP_NOP;
1001             break;
1002           case GXor:
1003             rop = RROP_NOP;
1004             break;
1005           case GXnor:
1006             rop = RROP_INVERT;
1007             break;
1008           case GXequiv:
1009             rop = RROP_INVERT;
1010             break;
1011           case GXinvert:
1012             rop = RROP_INVERT;
1013             break;
1014           case GXorReverse:
1015             rop = RROP_INVERT;
1016             break;
1017           case GXcopyInverted:
1018             rop = RROP_WHITE;
1019             break;
1020           case GXorInverted:
1021             rop = RROP_WHITE;
1022             break;
1023           case GXnand:
1024             rop = RROP_WHITE;
1025             break;
1026           case GXset:
1027             rop = RROP_WHITE;
1028             break;
1029         }
1030     }
1031     else /* src is white */
1032     {
1033         switch(alu)
1034         {
1035           case GXclear:
1036             rop = RROP_BLACK;
1037             break;
1038           case GXand:
1039             rop = RROP_NOP;
1040             break;
1041           case GXandReverse:
1042             rop = RROP_INVERT;
1043             break;
1044           case GXcopy:
1045             rop = RROP_WHITE;
1046             break;
1047           case GXandInverted:
1048             rop = RROP_BLACK;
1049             break;
1050           case GXnoop:
1051             rop = RROP_NOP;
1052             break;
1053           case GXxor:
1054             rop = RROP_INVERT;
1055             break;
1056           case GXor:
1057             rop = RROP_WHITE;
1058             break;
1059           case GXnor:
1060             rop = RROP_BLACK;
1061             break;
1062           case GXequiv:
1063             rop = RROP_NOP;
1064             break;
1065           case GXinvert:
1066             rop = RROP_INVERT;
1067             break;
1068           case GXorReverse:
1069             rop = RROP_WHITE;
1070             break;
1071           case GXcopyInverted:
1072             rop = RROP_BLACK;
1073             break;
1074           case GXorInverted:
1075             rop = RROP_NOP;
1076             break;
1077           case GXnand:
1078             rop = RROP_INVERT;
1079             break;
1080           case GXset:
1081             rop = RROP_WHITE;
1082             break;
1083         }
1084     }
1085     return rop;
1086 }