1 /***********************************************************
3 Copyright (c) 1987 X Consortium
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
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.
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
47 ******************************************************************/
48 /* $XConsortium: mfbgc.c,v 5.35 94/04/17 20:28:23 dpw Exp $ */
53 #include "dixfontstr.h"
54 #include "fontstruct.h"
56 #include "windowstr.h"
57 #include "pixmapstr.h"
58 #include "scrnintstr.h"
66 static GCFuncs mfbFuncs = {
76 static GCOps whiteTECopyOps = {
97 #ifdef NEED_LINEHELPER
102 static GCOps blackTECopyOps = {
121 mfbPolyGlyphBltBlack,
123 #ifdef NEED_LINEHELPER
128 static GCOps whiteTEInvertOps = {
147 mfbPolyGlyphBltInvert,
149 #ifdef NEED_LINEHELPER
154 static GCOps blackTEInvertOps = {
173 mfbPolyGlyphBltInvert,
175 #ifdef NEED_LINEHELPER
180 static GCOps whiteCopyOps = {
198 mfbImageGlyphBltWhite,
199 mfbPolyGlyphBltWhite,
201 #ifdef NEED_LINEHELPER
206 static GCOps blackCopyOps = {
224 mfbImageGlyphBltBlack,
225 mfbPolyGlyphBltBlack,
227 #ifdef NEED_LINEHELPER
232 static GCOps whiteInvertOps = {
250 mfbImageGlyphBltWhite,
251 mfbPolyGlyphBltInvert,
253 #ifdef NEED_LINEHELPER
258 static GCOps blackInvertOps = {
276 mfbImageGlyphBltBlack,
277 mfbPolyGlyphBltInvert,
279 #ifdef NEED_LINEHELPER
284 static GCOps whiteWhiteCopyOps = {
303 mfbPolyGlyphBltWhite,
305 #ifdef NEED_LINEHELPER
310 static GCOps blackBlackCopyOps = {
329 mfbPolyGlyphBltBlack,
331 #ifdef NEED_LINEHELPER
336 static GCOps fgEqBgInvertOps = {
355 mfbPolyGlyphBltInvert,
357 #ifdef NEED_LINEHELPER
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 },
385 #define numberCommonOps (sizeof (mfbCommonOps) / sizeof (mfbCommonOps[0]))
392 struct commonOps *cop;
395 if (pGC->lineWidth != 0)
397 if (pGC->lineStyle != LineSolid)
399 if (pGC->fillStyle != FillSolid)
402 FONTMAXBOUNDS(pGC->font,rightSideBearing) -
403 FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
404 FONTMINBOUNDS(pGC->font,characterWidth) < 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)
411 if ((pGC->bgPixel & 1) != cop->bg)
413 if (priv->rop != cop->rrop)
415 if (cop->terminalFont && !TERMINALFONT(pGC->font))
417 priv->FillArea = cop->fillArea;
429 pGC->clientClip = NULL;
430 pGC->clientClipType = CT_NONE;
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
438 pGC->ops = &whiteCopyOps;
439 pGC->funcs = &mfbFuncs;
441 /* mfb wants to translate before scan convesion */
442 pGC->miTranslate = 1;
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;
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
465 mfbValidateGC(pGC, changes, pDrawable)
467 unsigned long changes;
468 DrawablePtr pDrawable;
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
478 int new_rotate, new_rrop, new_line, new_text, new_fill;
479 DDXPointRec oldOrg; /* origin of thing GC was last used with */
481 oldOrg = pGC->lastWinOrg;
483 pGC->lastWinOrg.x = pDrawable->x;
484 pGC->lastWinOrg.y = pDrawable->y;
486 /* we need to re-rotate the tile if the previous window/pixmap
487 origin (oldOrg) differs from the new window/pixmap origin
490 new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
491 (oldOrg.y != pGC->lastWinOrg.y);
493 devPriv = ((mfbPrivGCPtr) (pGC->devPrivates[mfbGCPrivateIndex].ptr));
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
501 if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
502 (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
505 miComputeCompositeClip(pGC, pDrawable);
516 index = lowbit (mask);
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
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.
537 new_rrop = TRUE; /* for opaque stipples */
559 if(pGC->stipple == (PixmapPtr)NULL)
565 case GCTileStipXOrigin:
569 case GCTileStipYOrigin:
576 case GCSubwindowMode:
578 case GCGraphicsExposures:
597 /* deal with the changes we've collected .
598 new_rrop must be done first because subsequent things
602 if(new_rotate || new_fill)
604 Bool new_pix = FALSE;
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;
612 switch (pGC->fillStyle)
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)))
619 mfbCopyRotatePixmap(pGC->tile.pixmap,
620 &devPriv->pRotatedPixmap, xrot, yrot);
625 case FillOpaqueStippled:
626 if (pGC->stipple && (pGC->stipple->drawable.width <= PPW) &&
627 !(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1)))
629 mfbCopyRotatePixmap(pGC->stipple,
630 &devPriv->pRotatedPixmap, xrot, yrot);
634 /* destroy any previously rotated tile or stipple */
635 if (!new_pix && devPriv->pRotatedPixmap)
637 (*pDrawable->pScreen->DestroyPixmap)(devPriv->pRotatedPixmap);
638 devPriv->pRotatedPixmap = (PixmapPtr)NULL;
643 * duck out here when the GC is unchanged
649 if (new_rrop || new_fill)
651 rrop = mfbReduceRop(pGC->alu, pGC->fgPixel);
654 /* FillArea raster op is GC's for tile filling,
655 and the reduced rop for solid and stipple
657 if (pGC->fillStyle == FillTiled)
658 devPriv->ropFillArea = pGC->alu;
660 devPriv->ropFillArea = rrop;
663 fg bg ropOpStip fill style
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
671 if (pGC->fillStyle == FillOpaqueStippled)
673 if ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))
675 if (pGC->fgPixel & 1)
676 devPriv->ropOpStip = pGC->alu;
678 devPriv->ropOpStip = InverseAlu[pGC->alu];
681 devPriv->ropOpStip = rrop;
682 devPriv->ropFillArea = devPriv->ropOpStip;
688 if (new_line || new_fill || new_text)
692 if (newops = matchCommon (pGC))
694 if (pGC->ops->devPrivate.val)
695 miDestroyGCOps (pGC->ops);
697 new_line = new_fill = new_text = 0;
701 if (!pGC->ops->devPrivate.val)
703 pGC->ops = miCreateGCOps (pGC->ops);
704 pGC->ops->devPrivate.val = 1;
709 if (new_line || new_fill)
711 if (pGC->lineWidth == 0)
713 if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)
714 && ((rrop == RROP_WHITE) || (rrop == RROP_BLACK)))
715 pGC->ops->PolyArc = mfbZeroPolyArcSS;
717 pGC->ops->PolyArc = miZeroPolyArc;
720 pGC->ops->PolyArc = miPolyArc;
721 if (pGC->lineStyle == LineSolid)
723 if(pGC->lineWidth == 0)
725 if (pGC->fillStyle == FillSolid)
727 pGC->ops->PolySegment = mfbSegmentSS;
728 pGC->ops->Polylines = mfbLineSS;
732 pGC->ops->PolySegment = miPolySegment;
733 pGC->ops->Polylines = miZeroLine;
738 pGC->ops->PolySegment = miPolySegment;
739 pGC->ops->Polylines = miWideLine;
744 if(pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
746 pGC->ops->Polylines = mfbLineSD;
747 pGC->ops->PolySegment = mfbSegmentSD;
751 pGC->ops->Polylines = miWideDash;
752 pGC->ops->PolySegment = miPolySegment;
757 if (new_text || new_fill)
760 (FONTMAXBOUNDS(pGC->font,rightSideBearing) -
761 FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
762 FONTMINBOUNDS(pGC->font,characterWidth) < 0))
764 pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
765 pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
769 /* special case ImageGlyphBlt for terminal emulator fonts */
771 TERMINALFONT(pGC->font) &&
772 ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)))
774 /* pcc bug makes this not compile...
775 pGC->ops->ImageGlyphBlt = (pGC->fgPixel & 1) ? mfbTEGlyphBltWhite :
778 if (pGC->fgPixel & 1)
779 pGC->ops->ImageGlyphBlt = mfbTEGlyphBltWhite;
781 pGC->ops->ImageGlyphBlt = mfbTEGlyphBltBlack;
785 if (pGC->fgPixel & 1)
786 pGC->ops->ImageGlyphBlt = mfbImageGlyphBltWhite;
788 pGC->ops->ImageGlyphBlt = mfbImageGlyphBltBlack;
791 /* now do PolyGlyphBlt */
792 if (pGC->fillStyle == FillSolid ||
793 (pGC->fillStyle == FillOpaqueStippled &&
794 (pGC->fgPixel & 1) == (pGC->bgPixel & 1)
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;
805 pGC->ops->PolyGlyphBlt = (void (*)())NoopDDA;
809 pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
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))))
823 pGC->ops->PushPixels = mfbSolidPP;
827 pGC->ops->FillSpans = mfbWhiteSolidFS;
828 pGC->ops->FillPolygon = mfbFillPolyWhite;
831 pGC->ops->FillSpans = mfbBlackSolidFS;
832 pGC->ops->FillPolygon = mfbFillPolyBlack;
835 pGC->ops->FillSpans = mfbInvertSolidFS;
836 pGC->ops->FillPolygon = mfbFillPolyInvert;
839 pGC->ops->FillSpans = (void (*)())NoopDDA;
840 pGC->ops->FillPolygon = (void (*)())NoopDDA;
844 /* beyond this point, opaqueStippled ==> fg != bg */
845 else if (((pGC->fillStyle == FillTiled) ||
846 (pGC->fillStyle == FillOpaqueStippled)) &&
847 !devPriv->pRotatedPixmap)
849 pGC->ops->FillSpans = mfbUnnaturalTileFS;
851 else if ((pGC->fillStyle == FillStippled) && !devPriv->pRotatedPixmap)
853 pGC->ops->FillSpans = mfbUnnaturalStippleFS;
855 else if (pGC->fillStyle == FillStippled)
860 pGC->ops->FillSpans = mfbWhiteStippleFS;
863 pGC->ops->FillSpans = mfbBlackStippleFS;
866 pGC->ops->FillSpans = mfbInvertStippleFS;
869 pGC->ops->FillSpans = (void (*)())NoopDDA;
873 else /* overload tiles to do parti-colored opaque stipples */
875 pGC->ops->FillSpans = mfbTileFS;
877 if (pGC->fillStyle == FillSolid)
878 pGC->ops->PolyFillArc = mfbPolyFillArcSolid;
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
884 if ((((pGC->fillStyle == FillTiled) ||
885 (pGC->fillStyle == FillStippled)) &&
886 !devPriv->pRotatedPixmap) ||
887 ((pGC->fillStyle == FillOpaqueStippled) &&
888 ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)))
891 pGC->ops->PolyFillRect = miPolyFillRect;
893 else /* deal with solids and natural stipples and tiles */
895 pGC->ops->PolyFillRect = mfbPolyFillRect;
897 if ((pGC->fillStyle == FillSolid) ||
898 ((pGC->fillStyle == FillOpaqueStippled) &&
899 ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))))
904 devPriv->FillArea = mfbSolidWhiteArea;
907 devPriv->FillArea = mfbSolidBlackArea;
910 devPriv->FillArea = mfbSolidInvertArea;
913 devPriv->FillArea = (void (*)())NoopDDA;
917 else if (pGC->fillStyle == FillStippled)
922 devPriv->FillArea = mfbStippleWhiteArea;
925 devPriv->FillArea = mfbStippleBlackArea;
928 devPriv->FillArea = mfbStippleInvertArea;
931 devPriv->FillArea = (void (*)())NoopDDA;
935 else /* deal with tiles */
940 devPriv->FillArea = mfbTileAreaPPWCopy;
943 devPriv->FillArea = mfbTileAreaPPWGeneral;
947 } /* end of natural rectangles */
948 } /* end of new_fill */
951 /* table to map alu(src, dst) to alu(~src, dst) */
952 int InverseAlu[16] = {
972 mfbReduceRop(alu, src)
977 if ((src & 1) == 0) /* src is black */
1017 case GXcopyInverted:
1031 else /* src is white */
1071 case GXcopyInverted: