|
|
1.1 root 1: /***********************************************************
2: Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3: and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4:
5: All Rights Reserved
6:
7: Permission to use, copy, modify, and distribute this software and its
8: documentation for any purpose and without fee is hereby granted,
9: provided that the above copyright notice appear in all copies and that
10: both that copyright notice and this permission notice appear in
11: supporting documentation, and that the names of Digital or MIT not be
12: used in advertising or publicity pertaining to distribution of the
13: software without specific, written prior permission.
14:
15: DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17: DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21: SOFTWARE.
22:
23: ******************************************************************/
24: /* $Header: mfbgc.c,v 1.115 87/09/03 09:04:25 toddb Exp $ */
25: #include "X.h"
26: #include "Xmd.h"
27: #include "Xproto.h"
28: #include "dixfontstr.h"
29: #include "fontstruct.h"
30: #include "gcstruct.h"
31: #include "windowstr.h"
32: #include "pixmapstr.h"
33: #include "scrnintstr.h"
34: #include "region.h"
35:
36: #include "mfb.h"
37: #include "mistruct.h"
38:
39: #include "maskbits.h"
40:
41: static PixmapPtr BogusPixmap = (PixmapPtr)1;
42:
43: Bool
44: mfbCreateGC(pGC)
45: register GCPtr pGC;
46: {
47: mfbPrivGC *pPriv;
48: GCInterestPtr pQ;
49:
50: pGC->clientClip = NULL;
51: pGC->clientClipType = CT_NONE;
52:
53: /* some of the output primitives aren't really necessary, since
54: they will be filled in ValidateGC because of dix/CreateGC()
55: setting all the change bits. Others are necessary because although
56: they depend on being a monochrome frame buffer, they don't change
57: */
58:
59: pGC->FillSpans = mfbWhiteSolidFS;
60: pGC->SetSpans = mfbSetSpans;
61: pGC->PutImage = mfbPutImage;
62: pGC->CopyArea = mfbCopyArea;
63: pGC->CopyPlane = mfbCopyPlane;
64: pGC->PolyPoint = mfbPolyPoint;
65:
66: pGC->Polylines = mfbLineSS;
67: pGC->PolySegment = miPolySegment;
68: pGC->PolyRectangle = miPolyRectangle;
69: pGC->PolyArc = miPolyArc;
70: pGC->FillPolygon = miFillPolygon;
71: pGC->PolyFillRect = mfbPolyFillRect;
72: pGC->PolyFillArc = miPolyFillArc;
73: pGC->PolyText8 = miPolyText8;
74: pGC->ImageText8 = miImageText8;
75: pGC->PolyText16 = miPolyText16;
76: pGC->ImageText16 = miImageText16;
77: pGC->ImageGlyphBlt = mfbImageGlyphBltWhite;
78: pGC->PolyGlyphBlt = mfbPolyGlyphBltInvert;
79: pGC->PushPixels = mfbPushPixels;
80: pGC->LineHelper = miMiter;
81: pGC->ChangeClip = mfbChangeClip;
82: pGC->DestroyClip = mfbDestroyClip;
83: pGC->CopyClip = mfbCopyClip;
84:
85: /* mfb wants to translate before scan convesion */
86: pGC->miTranslate = 1;
87:
88: pPriv = (mfbPrivGC *)Xalloc(sizeof(mfbPrivGC));
89: if (!pPriv)
90: return FALSE;
91: else
92: {
93: pPriv->rop = ReduceRop(pGC->alu, pGC->fgPixel);
94: pPriv->fExpose = TRUE;
95: pGC->devPriv = (pointer)pPriv;
96: pPriv->pRotatedTile = NullPixmap;
97: pPriv->pRotatedStipple = NullPixmap;
98: pPriv->pAbsClientRegion =(* pGC->pScreen->RegionCreate)(NULL, 1);
99:
100: /* since freeCompClip isn't FREE_CC, we don't need to create
101: a null region -- no one will try to free the field.
102: */
103: pPriv->freeCompClip = REPLACE_CC;
104: pPriv->ppPixmap = &BogusPixmap;
105: pPriv->FillArea = mfbSolidInvertArea;
106: }
107: pQ = (GCInterestPtr) Xalloc(sizeof(GCInterestRec));
108: if(!pQ)
109: {
110: Xfree(pPriv);
111: return FALSE;
112: }
113:
114: /* Now link this device into the GCque */
115: pGC->pNextGCInterest = pQ;
116: pGC->pLastGCInterest = pQ;
117: pQ->pNextGCInterest = (GCInterestPtr) &pGC->pNextGCInterest;
118: pQ->pLastGCInterest = (GCInterestPtr) &pGC->pNextGCInterest;
119: pQ->length = sizeof(GCInterestRec);
120: pQ->owner = 0; /* server owns this */
121: pQ->ValInterestMask = ~0; /* interested in everything at validate time */
122: pQ->ValidateGC = mfbValidateGC;
123: pQ->ChangeInterestMask = 0; /* interested in nothing at change time */
124: pQ->ChangeGC = (int (*) () ) NULL;
125: pQ->CopyGCSource = (void (*) () ) NULL;
126: pQ->CopyGCDest = (void (*) () ) NULL;
127: pQ->DestroyGC = mfbDestroyGC;
128: return TRUE;
129: }
130:
131: void
132: mfbDestroyGC(pGC, pQ)
133: GC *pGC;
134: GCInterestPtr pQ;
135:
136: {
137: mfbPrivGC *pPriv;
138:
139: /* Most GCInterest pointers would free pQ->devPriv. This one is privileged
140: * and allowed to allocate its private data directly in the GC (this
141: * saves an indirection). We must also unlink and free the pQ.
142: */
143: pQ->pLastGCInterest->pNextGCInterest = pQ->pNextGCInterest;
144: pQ->pNextGCInterest->pLastGCInterest = pQ->pLastGCInterest;
145:
146: pPriv = (mfbPrivGC *)(pGC->devPriv);
147: if (pPriv->pRotatedTile)
148: mfbDestroyPixmap(pPriv->pRotatedTile);
149: if (pPriv->pRotatedStipple)
150: mfbDestroyPixmap(pPriv->pRotatedStipple);
151: if (pPriv->freeCompClip == FREE_CC)
152: (*pGC->pScreen->RegionDestroy)(pPriv->pCompositeClip);
153: if(pPriv->pAbsClientRegion)
154: (*pGC->pScreen->RegionDestroy)(pPriv->pAbsClientRegion);
155: Xfree(pGC->devPriv);
156: Xfree(pQ);
157: }
158:
159: #define WINMOVED(pWin, pGC) \
160: ((pWin->absCorner.x != pGC->lastWinOrg.x) || \
161: (pWin->absCorner.y != pGC->lastWinOrg.y))
162:
163: /* Clipping conventions
164: if the drawable is a window
165: CT_REGION ==> pCompositeClip really is the composite
166: CT_other ==> pCompositeClip is the window clip region
167: if the drawable is a pixmap
168: CT_REGION ==> pCompositeClip is the translated client region
169: clipped to the pixmap boundary
170: CT_other ==> pCompositeClip is the pixmap bounding box
171: */
172:
173: void
174: mfbValidateGC(pGC, pQ, changes, pDrawable)
175: register GCPtr pGC;
176: GCInterestPtr pQ;
177: Mask changes;
178: DrawablePtr pDrawable;
179: {
180: register mfbPrivGCPtr devPriv;
181: WindowPtr pWin;
182: int mask; /* stateChanges */
183: int index; /* used for stepping through bitfields */
184: int xrot, yrot; /* rotations for tile and stipple pattern */
185: int rrop; /* reduced rasterop */
186: /* flags for changing the proc vector
187: and updating things in devPriv
188: */
189: int new_rotate, new_rrop, new_line, new_text, new_fill;
190: DDXPointRec oldOrg; /* origin of thing GC was last used with */
191:
192: if (pDrawable->type == DRAWABLE_WINDOW)
193: pWin = (WindowPtr)pDrawable;
194: else
195: pWin = (WindowPtr)NULL;
196:
197: devPriv = ((mfbPrivGCPtr) (pGC->devPriv));
198: oldOrg = pGC->lastWinOrg;
199: /*
200: if the client clip is different or moved OR
201: the subwindowMode has changed OR
202: the window's clip has changed since the last validation
203: we need to recompute the composite clip
204: */
205:
206: if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask)) ||
207: (changes & GCSubwindowMode) ||
208: (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
209: )
210: {
211:
212: /* if there is a client clip (always a region, for us) AND
213: it has moved or is different OR
214: the window has moved
215: we need to (re)translate it.
216: */
217: if ((pGC->clientClipType == CT_REGION) &&
218: ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask)) ||
219: (pWin && WINMOVED(pWin, pGC))
220: )
221: )
222: {
223: /* retranslate client clip */
224: (* pGC->pScreen->RegionCopy)( devPriv->pAbsClientRegion,
225: pGC->clientClip);
226:
227: if (pWin)
228: {
229: pGC->lastWinOrg.x = pWin->absCorner.x;
230: pGC->lastWinOrg.y = pWin->absCorner.y;
231: (* pGC->pScreen->TranslateRegion)(
232: devPriv->pAbsClientRegion,
233: pGC->lastWinOrg.x + pGC->clipOrg.x,
234: pGC->lastWinOrg.y + pGC->clipOrg.y);
235: }
236: else
237: {
238: pGC->lastWinOrg.x = 0;
239: pGC->lastWinOrg.y = 0;
240: (* pGC->pScreen->TranslateRegion)(
241: devPriv->pAbsClientRegion, pGC->clipOrg.x, pGC->clipOrg.y);
242: }
243: }
244:
245: if (pWin)
246: {
247: int freeTmpClip, freeCompClip;
248: RegionPtr pregWin; /* clip for this window, without
249: client clip */
250:
251: if (pGC->subWindowMode == IncludeInferiors)
252: {
253: pregWin = NotClippedByChildren(pWin);
254: freeTmpClip = FREE_CC;
255: }
256: else
257: {
258: pregWin = pWin->clipList;
259: freeTmpClip = REPLACE_CC;
260: }
261: freeCompClip = devPriv->freeCompClip;
262:
263: /* if there is no client clip, we can get by with
264: just keeping the pointer we got, and remembering
265: whether or not should destroy (or maybe re-use)
266: it later. this way, we avoid unnecessary copying
267: of regions. (this wins especially if many clients clip
268: by children and have no client clip.)
269: */
270: if (pGC->clientClipType == CT_NONE)
271: {
272: if(freeCompClip == FREE_CC)
273: {
274: (* pGC->pScreen->RegionDestroy) (devPriv->pCompositeClip);
275: }
276: devPriv->pCompositeClip = pregWin;
277: devPriv->freeCompClip = freeTmpClip;
278: }
279: else
280: {
281: /* we need one 'real' region to put into the composite
282: clip.
283: if pregWin and the current composite clip
284: are real, we can get rid of one.
285: if the current composite clip is real and
286: pregWin isn't, intersect the client clip and
287: pregWin into the existing composite clip.
288: if pregWin is real and the current composite
289: clip isn't, intersect pregWin with the client clip
290: and replace the composite clip with it.
291: if neither is real, create a new region and
292: do the intersection into it.
293: */
294:
295: if ((freeTmpClip == FREE_CC) && (freeCompClip == FREE_CC))
296: {
297: (* pGC->pScreen->Intersect)(
298: devPriv->pCompositeClip,
299: pregWin,
300: devPriv->pAbsClientRegion);
301: (* pGC->pScreen->RegionDestroy)(pregWin);
302: }
303: else if ((freeTmpClip == REPLACE_CC) &&
304: (freeCompClip == FREE_CC))
305: {
306: (* pGC->pScreen->Intersect)(
307: devPriv->pCompositeClip,
308: pregWin,
309: devPriv->pAbsClientRegion);
310: }
311: else if ((freeTmpClip == FREE_CC) &&
312: (freeCompClip == REPLACE_CC))
313: {
314: (* pGC->pScreen->Intersect)(
315: pregWin,
316: pregWin,
317: devPriv->pAbsClientRegion);
318: devPriv->pCompositeClip = pregWin;
319: }
320: else if ((freeTmpClip == REPLACE_CC) &&
321: (freeCompClip == REPLACE_CC))
322: {
323: devPriv->pCompositeClip =
324: (* pGC->pScreen->RegionCreate)(NULL, 1);
325: (* pGC->pScreen->Intersect)(
326: devPriv->pCompositeClip,
327: pregWin,
328: devPriv->pAbsClientRegion);
329: }
330: devPriv->freeCompClip = FREE_CC;
331: }
332: } /* end of composite clip for a window */
333: else
334: {
335: BoxRec pixbounds;
336:
337: pixbounds.x1 = 0;
338: pixbounds.y1 = 0;
339: pixbounds.x2 = ((PixmapPtr)pDrawable)->width;
340: pixbounds.y2 = ((PixmapPtr)pDrawable)->height;
341:
342: if (devPriv->freeCompClip == FREE_CC)
343: (* pGC->pScreen->RegionReset)(
344: devPriv->pCompositeClip, &pixbounds);
345: else
346: {
347: devPriv->freeCompClip = FREE_CC;
348: devPriv->pCompositeClip =
349: (* pGC->pScreen->RegionCreate)(&pixbounds, 1);
350: }
351:
352: if (pGC->clientClipType == CT_REGION)
353: (* pGC->pScreen->Intersect)(
354: devPriv->pCompositeClip,
355: devPriv->pCompositeClip,
356: devPriv->pAbsClientRegion);
357: } /* end of composite clip for pixmap */
358: }
359:
360: /* we need to re-rotate the tile if the previous window/pixmap
361: origin (oldOrg) differs from the new window/pixmap origin
362: (pGC->lastWinOrg)
363: */
364: if ((oldOrg.x != pGC->lastWinOrg.x) ||
365: (oldOrg.y != pGC->lastWinOrg.y))
366: {
367: new_rotate = TRUE;
368: }
369: else
370: {
371: new_rotate = FALSE;
372: }
373:
374: new_rrop = FALSE;
375: new_line = FALSE;
376: new_text = FALSE;
377: new_fill = FALSE;
378:
379: mask = changes;
380: while (mask)
381: {
382: index = ffs(mask) - 1;
383: mask &= ~(index = (1 << index));
384:
385: /* this switch acculmulates a list of which procedures
386: might have to change due to changes in the GC. in
387: some cases (e.g. changing one 16 bit tile for another)
388: we might not really need a change, but the code is
389: being paranoid.
390: this sort of batching wins if, for example, the alu
391: and the font have been changed, or any other pair
392: of items that both change the same thing.
393: */
394: switch (index)
395: {
396: case GCFunction:
397: case GCForeground:
398: new_rrop = TRUE;
399: break;
400: case GCPlaneMask:
401: break;
402: case GCBackground:
403: new_rrop = TRUE; /* for opaque stipples */
404: break;
405: case GCLineStyle:
406: new_line = TRUE;
407: break;
408: case GCLineWidth:
409: case GCCapStyle:
410: case GCJoinStyle:
411: new_line = TRUE;
412: break;
413: case GCFillStyle:
414: new_fill = TRUE;
415: break;
416: case GCFillRule:
417: break;
418: case GCTile:
419: if(pGC->tile == (PixmapPtr)NULL)
420: break;
421: mfbPadPixmap(pGC->tile);
422: new_rotate = TRUE;
423: new_fill = TRUE;
424: break;
425:
426: case GCStipple:
427: if(pGC->stipple == (PixmapPtr)NULL)
428: break;
429: mfbPadPixmap(pGC->stipple);
430: new_rotate = TRUE;
431: new_fill = TRUE;
432: break;
433:
434: case GCTileStipXOrigin:
435: new_rotate = TRUE;
436: break;
437:
438: case GCTileStipYOrigin:
439: new_rotate = TRUE;
440: break;
441:
442: case GCFont:
443: new_text = TRUE;
444: break;
445: case GCSubwindowMode:
446: break;
447: case GCGraphicsExposures:
448: break;
449: case GCClipXOrigin:
450: break;
451: case GCClipYOrigin:
452: break;
453: case GCClipMask:
454: break;
455: case GCDashOffset:
456: break;
457: case GCDashList:
458: break;
459: case GCArcMode:
460: break;
461: default:
462: break;
463: }
464: }
465:
466: /* deal with the changes we've collected .
467: new_rrop must be done first because subsequent things
468: depend on it.
469: */
470: if (new_rrop || new_fill)
471: {
472: rrop = ReduceRop(pGC->alu, pGC->fgPixel);
473: devPriv->rop = rrop;
474: new_fill = TRUE;
475: /* FillArea raster op is GC's for tile filling,
476: and the reduced rop for solid and stipple
477: */
478: if (pGC->fillStyle == FillTiled)
479: devPriv->ropFillArea = pGC->alu;
480: else
481: devPriv->ropFillArea = rrop;
482:
483: /* opaque stipples:
484: fg bg ropOpStip fill style
485: 1 0 alu tile
486: 0 1 inverseAlu tile
487: 1 1 rrop(fg, alu) solid
488: 0 0 rrop(fg, alu) solid
489: Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to
490: compute it.
491: */
492: if (pGC->fillStyle == FillOpaqueStippled)
493: {
494: if (pGC->fgPixel != pGC->bgPixel)
495: {
496: if (pGC->fgPixel)
497: devPriv->ropOpStip = pGC->alu;
498: else
499: devPriv->ropOpStip = InverseAlu[pGC->alu];
500: }
501: else
502: devPriv->ropOpStip = rrop;
503: devPriv->ropFillArea = devPriv->ropOpStip;
504: }
505: }
506: else
507: rrop = devPriv->rop;
508:
509: if (new_line || new_fill)
510: {
511: if (pGC->lineStyle == LineSolid)
512: {
513: if(pGC->lineWidth == 0)
514: {
515: if (pGC->fillStyle == FillSolid)
516: pGC->Polylines = mfbLineSS;
517: else
518: pGC->Polylines = miZeroLine;
519: }
520: else
521: {
522: pGC->Polylines = miWideLine;
523: }
524: }
525: else
526: if(pGC->lineWidth == 0)
527: pGC->Polylines = mfbDashLine;
528: else
529: pGC->Polylines = miWideDash;
530:
531: switch(pGC->joinStyle)
532: {
533: case JoinMiter:
534: pGC->LineHelper = miMiter;
535: break;
536: case JoinRound:
537: case JoinBevel:
538: pGC->LineHelper = miNotMiter;
539: break;
540: }
541: }
542:
543: if (new_text || new_fill)
544: {
545: if ((pGC->font) &&
546: (pGC->font->pFI->maxbounds.metrics.rightSideBearing -
547: pGC->font->pFI->maxbounds.metrics.leftSideBearing) > 32)
548: {
549: pGC->PolyGlyphBlt = miPolyGlyphBlt;
550: pGC->ImageGlyphBlt = miImageGlyphBlt;
551: }
552: else
553: {
554: /* special case ImageGlyphBlt for terminal emulator fonts */
555: if ((pGC->font) &&
556: (pGC->font->pFI->terminalFont) &&
557: (pGC->fgPixel != pGC->bgPixel))
558: {
559: /* pcc bug makes this not compile...
560: pGC->ImageGlyphBlt = (pGC->fgPixel) ? mfbTEGlyphBltWhite :
561: mfbTEGlyphBltBlack;
562: */
563: if (pGC->fgPixel)
564: pGC->ImageGlyphBlt = mfbTEGlyphBltWhite;
565: else
566: pGC->ImageGlyphBlt = mfbTEGlyphBltBlack;
567: }
568: else
569: {
570: if (pGC->fgPixel == 0)
571: pGC->ImageGlyphBlt = mfbImageGlyphBltBlack;
572: else
573: pGC->ImageGlyphBlt = mfbImageGlyphBltWhite;
574: }
575:
576: /* now do PolyGlyphBlt */
577: if (pGC->fillStyle == FillSolid ||
578: (pGC->fillStyle == FillOpaqueStippled &&
579: pGC->fgPixel == pGC->bgPixel
580: )
581: )
582: {
583: if (rrop == RROP_WHITE)
584: pGC->PolyGlyphBlt = mfbPolyGlyphBltWhite;
585: else if (rrop == RROP_BLACK)
586: pGC->PolyGlyphBlt = mfbPolyGlyphBltBlack;
587: else if (rrop == RROP_INVERT)
588: pGC->PolyGlyphBlt = mfbPolyGlyphBltInvert;
589: else
590: pGC->PolyGlyphBlt = NoopDDA;
591: }
592: else
593: {
594: pGC->PolyGlyphBlt = miPolyGlyphBlt;
595: }
596: }
597: }
598:
599: if (new_fill)
600: {
601: /* install a suitable fillspans */
602: if ((pGC->fillStyle == FillSolid) ||
603: (pGC->fillStyle == FillOpaqueStippled && pGC->fgPixel==pGC->bgPixel)
604: )
605: {
606: switch(devPriv->rop)
607: {
608: case RROP_WHITE:
609: pGC->FillSpans = mfbWhiteSolidFS;
610: break;
611: case RROP_BLACK:
612: pGC->FillSpans = mfbBlackSolidFS;
613: break;
614: case RROP_INVERT:
615: pGC->FillSpans = mfbInvertSolidFS;
616: break;
617: case RROP_NOP:
618: pGC->FillSpans = NoopDDA;
619: break;
620: }
621: }
622: /* beyond this point, opaqueStippled ==> fg != bg */
623: else if ((pGC->fillStyle==FillTiled && pGC->tile->width!=32) ||
624: (pGC->fillStyle==FillOpaqueStippled && pGC->stipple->width!=32)
625: )
626: {
627: pGC->FillSpans = mfbUnnaturalTileFS;
628: }
629: else if (pGC->fillStyle == FillStippled && pGC->stipple->width != 32)
630: {
631: pGC->FillSpans = mfbUnnaturalStippleFS;
632: }
633: else if (pGC->fillStyle == FillStippled)
634: {
635: switch(devPriv->rop)
636: {
637: case RROP_WHITE:
638: pGC->FillSpans = mfbWhiteStippleFS;
639: break;
640: case RROP_BLACK:
641: pGC->FillSpans = mfbBlackStippleFS;
642: break;
643: case RROP_INVERT:
644: pGC->FillSpans = mfbInvertStippleFS;
645: break;
646: case RROP_NOP:
647: pGC->FillSpans = NoopDDA;
648: break;
649: }
650: }
651: else /* overload tiles to do parti-colored opaque stipples */
652: {
653: pGC->FillSpans = mfbTileFS;
654: }
655:
656: /* the rectangle code doesn't deal with opaque stipples that
657: are two colors -- we can fool it for fg==bg, though
658: */
659: if (((pGC->fillStyle == FillTiled) && (pGC->tile->width!=32)) ||
660: ((pGC->fillStyle == FillStippled) && (pGC->stipple->width!=32)) ||
661: ((pGC->fillStyle == FillOpaqueStippled) &&
662: (pGC->fgPixel != pGC->bgPixel))
663: )
664: {
665: pGC->PolyFillRect = miPolyFillRect;
666: devPriv->ppPixmap = &BogusPixmap;
667: }
668: else /* deal with solids and natural stipples and tiles */
669: {
670: pGC->PolyFillRect = mfbPolyFillRect;
671:
672: if ((pGC->fillStyle == FillSolid) ||
673: (pGC->fillStyle == FillOpaqueStippled &&
674: pGC->fgPixel == pGC->bgPixel)
675: )
676: {
677: devPriv->ppPixmap = &BogusPixmap;
678: switch(devPriv->rop)
679: {
680: case RROP_WHITE:
681: devPriv->FillArea = mfbSolidWhiteArea;
682: break;
683: case RROP_BLACK:
684: devPriv->FillArea = mfbSolidBlackArea;
685: break;
686: case RROP_INVERT:
687: devPriv->FillArea = mfbSolidInvertArea;
688: break;
689: case RROP_NOP:
690: devPriv->FillArea = NoopDDA;
691: break;
692: }
693: }
694: else if (pGC->fillStyle == FillStippled)
695: {
696: devPriv->ppPixmap = &devPriv->pRotatedStipple;
697: switch(devPriv->rop)
698: {
699: case RROP_WHITE:
700: devPriv->FillArea = mfbStippleWhiteArea;
701: break;
702: case RROP_BLACK:
703: devPriv->FillArea = mfbStippleBlackArea;
704: break;
705: case RROP_INVERT:
706: devPriv->FillArea = mfbStippleInvertArea;
707: break;
708: case RROP_NOP:
709: devPriv->FillArea = NoopDDA;
710: break;
711: }
712: }
713: else /* deal with tiles */
714: {
715: if (pGC->fillStyle == FillTiled)
716: devPriv->ppPixmap = &devPriv->pRotatedTile;
717: else
718: devPriv->ppPixmap = &devPriv->pRotatedStipple;
719: devPriv->FillArea = mfbTileArea32;
720: }
721: } /* end of natural rectangles */
722: } /* end of new_fill */
723:
724:
725: if(new_rotate)
726: {
727: /* figure out how much to rotate */
728: xrot = pGC->patOrg.x;
729: yrot = pGC->patOrg.y;
730: if (pWin)
731: {
732: xrot += pWin->absCorner.x;
733: yrot += pWin->absCorner.y;
734: }
735:
736: /* destroy any previously rotated tile or stipple */
737: if(devPriv->pRotatedTile)
738: {
739: mfbDestroyPixmap(devPriv->pRotatedTile);
740: devPriv->pRotatedTile = (PixmapPtr)NULL;
741: }
742: if(devPriv->pRotatedStipple)
743: {
744: mfbDestroyPixmap(devPriv->pRotatedStipple);
745: devPriv->pRotatedStipple = (PixmapPtr)NULL;
746: }
747:
748: /* copy current tile and stipple */
749: if(pGC->tile &&
750: (pGC->tile->width == 32) &&
751: (devPriv->pRotatedTile = mfbCopyPixmap(pGC->tile)) ==
752: (PixmapPtr)NULL)
753: return ; /* shouldn't happen, internal error */
754: if(pGC->stipple &&
755: (pGC->stipple->width == 32) &&
756: (devPriv->pRotatedStipple = mfbCopyPixmap(pGC->stipple)) ==
757: (PixmapPtr)NULL)
758: return ; /* shouldn't happen, internal error */
759:
760: if(xrot)
761: {
762: if (pGC->tile && pGC->tile->width == 32 &&
763: devPriv->pRotatedTile)
764: mfbXRotatePixmap(devPriv->pRotatedTile, xrot);
765: if (pGC->stipple && pGC->stipple->width == 32 &&
766: devPriv->pRotatedStipple)
767: mfbXRotatePixmap(devPriv->pRotatedStipple, xrot);
768: }
769: if(yrot)
770: {
771: if (pGC->tile && pGC->tile->width == 32 &&
772: devPriv->pRotatedTile)
773: mfbYRotatePixmap(devPriv->pRotatedTile, yrot);
774: if (pGC->tile && pGC->tile->width == 32 &&
775: devPriv->pRotatedStipple)
776: mfbYRotatePixmap(devPriv->pRotatedStipple, yrot);
777: }
778: }
779:
780: return ;
781: }
782:
783: /* table to map alu(src, dst) to alu(~src, dst) */
784: int InverseAlu[16] = {
785: GXclear,
786: GXandInverted,
787: GXnor,
788: GXcopyInverted,
789: GXand,
790: GXnoop,
791: GXequiv,
792: GXorInverted,
793: GXandReverse,
794: GXxor,
795: GXinvert,
796: GXnand,
797: GXcopy,
798: GXor,
799: GXorReverse,
800: GXset
801: };
802:
803: ReduceRop(alu, src)
804: register int alu;
805: register int src;
806: {
807: int rop;
808: if (src == 0) /* src is black */
809: {
810: switch(alu)
811: {
812: case GXclear:
813: rop = RROP_BLACK;
814: break;
815: case GXand:
816: rop = RROP_BLACK;
817: break;
818: case GXandReverse:
819: rop = RROP_BLACK;
820: break;
821: case GXcopy:
822: rop = RROP_BLACK;
823: break;
824: case GXandInverted:
825: rop = RROP_NOP;
826: break;
827: case GXnoop:
828: rop = RROP_NOP;
829: break;
830: case GXxor:
831: rop = RROP_NOP;
832: break;
833: case GXor:
834: rop = RROP_NOP;
835: break;
836: case GXnor:
837: rop = RROP_INVERT;
838: break;
839: case GXequiv:
840: rop = RROP_INVERT;
841: break;
842: case GXinvert:
843: rop = RROP_INVERT;
844: break;
845: case GXorReverse:
846: rop = RROP_INVERT;
847: break;
848: case GXcopyInverted:
849: rop = RROP_WHITE;
850: break;
851: case GXorInverted:
852: rop = RROP_WHITE;
853: break;
854: case GXnand:
855: rop = RROP_WHITE;
856: break;
857: case GXset:
858: rop = RROP_WHITE;
859: break;
860: }
861: }
862: else /* src is white */
863: {
864: switch(alu)
865: {
866: case GXclear:
867: rop = RROP_BLACK;
868: break;
869: case GXand:
870: rop = RROP_NOP;
871: break;
872: case GXandReverse:
873: rop = RROP_INVERT;
874: break;
875: case GXcopy:
876: rop = RROP_WHITE;
877: break;
878: case GXandInverted:
879: rop = RROP_BLACK;
880: break;
881: case GXnoop:
882: rop = RROP_NOP;
883: break;
884: case GXxor:
885: rop = RROP_INVERT;
886: break;
887: case GXor:
888: rop = RROP_WHITE;
889: break;
890: case GXnor:
891: rop = RROP_BLACK;
892: break;
893: case GXequiv:
894: rop = RROP_NOP;
895: break;
896: case GXinvert:
897: rop = RROP_INVERT;
898: break;
899: case GXorReverse:
900: rop = RROP_WHITE;
901: break;
902: case GXcopyInverted:
903: rop = RROP_BLACK;
904: break;
905: case GXorInverted:
906: rop = RROP_NOP;
907: break;
908: case GXnand:
909: rop = RROP_INVERT;
910: break;
911: case GXset:
912: rop = RROP_WHITE;
913: break;
914: }
915: }
916: return rop;
917: }
918:
919: void
920: mfbDestroyClip(pGC)
921: GCPtr pGC;
922: {
923: if(pGC->clientClipType == CT_NONE)
924: return;
925: else if (pGC->clientClipType == CT_PIXMAP)
926: {
927: mfbDestroyPixmap((PixmapPtr)(pGC->clientClip));
928: }
929: else
930: {
931: /* we know we'll never have a list of rectangles, since
932: ChangeClip immediately turns them into a region
933: */
934: (*pGC->pScreen->RegionDestroy)(pGC->clientClip);
935: }
936: pGC->clientClip = NULL;
937: pGC->clientClipType = CT_NONE;
938: }
939:
940: void
941: mfbChangeClip(pGC, type, pvalue, nrects)
942: GCPtr pGC;
943: int type;
944: pointer pvalue;
945: int nrects;
946: {
947: /*
948: remember to bump the pixmap's refcnt before destroying the old
949: one, since the two may be the same.
950: regions that have been fed to the clip code are assumed to have
951: disappeared, so we'll never see the same one twice.
952: */
953:
954: if (type == CT_PIXMAP)
955: {
956: /* so we can call destroy later, and leave this as
957: an example
958: */
959: ((PixmapPtr)(pvalue))->refcnt++;
960: }
961:
962: mfbDestroyClip(pGC);
963: if(type == CT_PIXMAP)
964: {
965: /* convert the pixmap to a region */
966: pGC->clientClip = (pointer) mfbPixmapToRegion(pvalue);
967: /* you wouldn't do this if you were leaving the pixmap in
968: rather than converting it.
969: */
970: (*pGC->pScreen->DestroyPixmap)(pvalue);
971: }
972: else if (type == CT_REGION)
973: {
974: /* stuff the region in the GC */
975: pGC->clientClip = pvalue;
976: }
977: else if (type != CT_NONE)
978: {
979: pGC->clientClip = (pointer) miRectsToRegion(pGC, nrects, pvalue, type);
980: Xfree(pvalue);
981: }
982: pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION :
983: CT_NONE;
984: pGC->stateChanges |= GCClipMask;
985: }
986:
987: void
988: mfbCopyClip (pgcDst, pgcSrc)
989: GCPtr pgcDst, pgcSrc;
990: {
991: RegionPtr prgnNew;
992:
993: switch(pgcSrc->clientClipType)
994: {
995: case CT_NONE:
996: case CT_PIXMAP:
997: mfbChangeClip(pgcDst, pgcSrc->clientClipType, pgcSrc->clientClip, 0);
998: break;
999: case CT_REGION:
1000: prgnNew = (*pgcSrc->pScreen->RegionCreate)(NULL, 1);
1001: (*pgcSrc->pScreen->RegionCopy)(prgnNew,
1002: (RegionPtr)(pgcSrc->clientClip));
1003: mfbChangeClip(pgcDst, CT_REGION, prgnNew, 0);
1004: break;
1005: }
1006: }
1007:
1008: void
1009: mfbCopyGCDest (pGC, pQ, changes, pGCSrc)
1010: GCPtr pGC;
1011: GCInterestPtr pQ;
1012: Mask changes;
1013: GCPtr pGCSrc;
1014: {
1015: RegionPtr pClip;
1016:
1017: if(changes & GCClipMask)
1018: {
1019: if(pGC->clientClipType == CT_PIXMAP)
1020: {
1021: ((PixmapPtr)pGC->clientClip)->refcnt++;
1022: }
1023: else if(pGC->clientClipType == CT_REGION)
1024: {
1025: BoxRec pixbounds;
1026:
1027: pixbounds.x1 = 0;
1028: pixbounds.y1 = 0;
1029: pixbounds.x2 = 0;
1030: pixbounds.y2 = 0;
1031:
1032: pClip = (RegionPtr) pGC->clientClip;
1033: pGC->clientClip =
1034: (pointer)(* pGC->pScreen->RegionCreate)(&pixbounds, 1);
1035: (* pGC->pScreen->RegionCopy)(pGC->clientClip, pClip);
1036: }
1037: }
1038: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.