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 ******************************************************************/
49 /* $XConsortium: cfbgc.c,v 5.62 94/04/17 20:28:49 dpw Exp $ */
55 #include "fontstruct.h"
56 #include "dixfontstr.h"
58 #include "windowstr.h"
59 #include "pixmapstr.h"
60 #include "scrnintstr.h"
67 #include "cfbmskbits.h"
71 # define useTEGlyphBlt cfbTEGlyphBlt8
74 # define useTEGlyphBlt cfbImageGlyphBlt8
76 # define useTEGlyphBlt cfbTEGlyphBlt
81 # define useImageGlyphBlt cfbImageGlyphBlt8
82 # define usePolyGlyphBlt cfbPolyGlyphBlt8
84 # define useImageGlyphBlt miImageGlyphBlt
85 # define usePolyGlyphBlt miPolyGlyphBlt
89 # define usePushPixels cfbPushPixels8
91 # define usePushPixels mfbPushPixels
95 # define ZeroPolyArc cfbZeroPolyArcSS8Copy
97 # define ZeroPolyArc miZeroPolyArc
100 GCFuncs cfbGCFuncs = {
110 GCOps cfbTEOps1Rect = {
126 cfbFillPoly1RectCopy,
128 cfbPolyFillArcSolidCopy,
136 #ifdef NEED_LINEHELPER
141 GCOps cfbNonTEOps1Rect = {
157 cfbFillPoly1RectCopy,
159 cfbPolyFillArcSolidCopy,
167 #ifdef NEED_LINEHELPER
185 cfbPolyFillArcSolidCopy,
193 #ifdef NEED_LINEHELPER
198 GCOps cfbNonTEOps = {
209 cfbZeroPolyArcSS8Copy,
215 cfbPolyFillArcSolidCopy,
223 #ifdef NEED_LINEHELPER
229 cfbMatchCommon (pGC, devPriv)
231 cfbPrivGCPtr devPriv;
233 if (pGC->lineWidth != 0)
235 if (pGC->lineStyle != LineSolid)
237 if (pGC->fillStyle != FillSolid)
239 if (devPriv->rop != GXcopy)
242 FONTMAXBOUNDS(pGC->font,rightSideBearing) -
243 FONTMINBOUNDS(pGC->font,leftSideBearing) <= 32 &&
244 FONTMINBOUNDS(pGC->font,characterWidth) >= 0)
246 if (TERMINALFONT(pGC->font)
248 && FONTMAXBOUNDS(pGC->font,characterWidth) >= PGSZB
252 return &cfbTEOps1Rect;
254 if (devPriv->oneRect)
255 return &cfbTEOps1Rect;
261 return &cfbNonTEOps1Rect;
263 if (devPriv->oneRect)
264 return &cfbNonTEOps1Rect;
278 if (PixmapWidthPaddingInfo[pGC->depth].padPixelsLog2 == LOG2_BITMAP_PAD)
279 return (mfbCreateGC(pGC));
280 pGC->clientClip = NULL;
281 pGC->clientClipType = CT_NONE;
284 * some of the output primitives aren't really necessary, since they
285 * will be filled in ValidateGC because of dix/CreateGC() setting all
286 * the change bits. Others are necessary because although they depend
287 * on being a color frame buffer, they don't change
290 pGC->ops = &cfbNonTEOps;
291 pGC->funcs = &cfbGCFuncs;
293 /* cfb wants to translate before scan conversion */
294 pGC->miTranslate = 1;
296 pPriv = cfbGetGCPrivate(pGC);
297 pPriv->rop = pGC->alu;
298 pPriv->oneRect = FALSE;
299 pPriv->fExpose = TRUE;
300 pPriv->freeCompClip = FALSE;
301 pPriv->pRotatedPixmap = (PixmapPtr) NULL;
305 /* Clipping conventions
306 if the drawable is a window
307 CT_REGION ==> pCompositeClip really is the composite
308 CT_other ==> pCompositeClip is the window clip region
309 if the drawable is a pixmap
310 CT_REGION ==> pCompositeClip is the translated client region
311 clipped to the pixmap boundary
312 CT_other ==> pCompositeClip is the pixmap bounding box
316 cfbValidateGC(pGC, changes, pDrawable)
318 unsigned long changes;
319 DrawablePtr pDrawable;
321 int mask; /* stateChanges */
322 int index; /* used for stepping through bitfields */
324 int new_line, new_text, new_fillspans, new_fillarea;
327 /* flags for changing the proc vector */
328 cfbPrivGCPtr devPriv;
331 new_rotate = pGC->lastWinOrg.x != pDrawable->x ||
332 pGC->lastWinOrg.y != pDrawable->y;
334 pGC->lastWinOrg.x = pDrawable->x;
335 pGC->lastWinOrg.y = pDrawable->y;
336 devPriv = cfbGetGCPrivate(pGC);
341 new_fillspans = FALSE;
342 new_fillarea = FALSE;
345 * if the client clip is different or moved OR the subwindowMode has
346 * changed OR the window's clip has changed since the last validation
347 * we need to recompute the composite clip
350 if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
351 (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
354 miComputeCompositeClip (pGC, pDrawable);
356 devPriv->oneRect = FALSE;
358 oneRect = REGION_NUM_RECTS(devPriv->pCompositeClip) == 1;
359 if (oneRect != devPriv->oneRect)
361 devPriv->oneRect = oneRect;
367 index = lowbit (mask);
371 * this switch acculmulates a list of which procedures might have
372 * to change due to changes in the GC. in some cases (e.g.
373 * changing one 16 bit tile for another) we might not really need
374 * a change, but the code is being paranoid. this sort of batching
375 * wins if, for example, the alu and the font have been changed,
376 * or any other pair of items that both change the same thing.
398 new_fillspans = TRUE;
405 new_fillspans = TRUE;
412 int width = pGC->stipple->drawable.width;
415 if ((width <= PGSZ) && !(width & (width - 1)) &&
416 (nstipple = cfbCopyPixmap(pGC->stipple)))
418 cfbPadPixmap(nstipple);
419 (*pGC->pScreen->DestroyPixmap)(pGC->stipple);
420 pGC->stipple = nstipple;
423 new_fillspans = TRUE;
427 case GCTileStipXOrigin:
431 case GCTileStipYOrigin:
438 case GCSubwindowMode:
440 case GCGraphicsExposures:
460 * If the drawable has changed, ensure suitable
461 * entries are in the proc vector.
463 if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) {
464 new_fillspans = TRUE; /* deal with FillSpans later */
467 if (new_rotate || new_fillspans)
469 Bool new_pix = FALSE;
471 xrot = pGC->patOrg.x + pDrawable->x;
472 yrot = pGC->patOrg.y + pDrawable->y;
474 switch (pGC->fillStyle)
477 if (!pGC->tileIsPixel)
479 int width = pGC->tile.pixmap->drawable.width * PSZ;
481 if ((width <= PGSZ) && !(width & (width - 1)))
483 cfbCopyRotatePixmap(pGC->tile.pixmap,
484 &devPriv->pRotatedPixmap,
492 case FillOpaqueStippled:
494 int width = pGC->stipple->drawable.width;
496 if ((width <= PGSZ) && !(width & (width - 1)))
498 mfbCopyRotatePixmap(pGC->stipple,
499 &devPriv->pRotatedPixmap, xrot, yrot);
506 if (!new_pix && devPriv->pRotatedPixmap)
508 (*pGC->pScreen->DestroyPixmap)(devPriv->pRotatedPixmap);
509 devPriv->pRotatedPixmap = (PixmapPtr) NULL;
517 old_rrop = devPriv->rop;
518 devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel,
520 &devPriv->and, &devPriv->xor);
521 if (old_rrop == devPriv->rop)
531 new_fillspans = TRUE;
536 if (new_rrop || new_fillspans || new_text || new_fillarea || new_line)
540 if (newops = cfbMatchCommon (pGC, devPriv))
542 if (pGC->ops->devPrivate.val)
543 miDestroyGCOps (pGC->ops);
545 new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0;
549 if (!pGC->ops->devPrivate.val)
551 pGC->ops = miCreateGCOps (pGC->ops);
552 pGC->ops->devPrivate.val = 1;
557 /* deal with the changes we've collected */
560 pGC->ops->FillPolygon = miFillPolygon;
562 if (pGC->fillStyle == FillSolid)
564 switch (devPriv->rop) {
566 pGC->ops->FillPolygon = cfbFillPoly1RectCopy;
569 pGC->ops->FillPolygon = cfbFillPoly1RectGeneral;
574 if (devPriv->oneRect && pGC->fillStyle == FillSolid)
576 switch (devPriv->rop) {
578 pGC->ops->FillPolygon = cfbFillPoly1RectCopy;
581 pGC->ops->FillPolygon = cfbFillPoly1RectGeneral;
586 if (pGC->lineWidth == 0)
589 if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid))
591 switch (devPriv->rop)
594 pGC->ops->PolyArc = cfbZeroPolyArcSS8Xor;
597 pGC->ops->PolyArc = cfbZeroPolyArcSS8Copy;
600 pGC->ops->PolyArc = cfbZeroPolyArcSS8General;
606 pGC->ops->PolyArc = miZeroPolyArc;
609 pGC->ops->PolyArc = miPolyArc;
610 pGC->ops->PolySegment = miPolySegment;
611 switch (pGC->lineStyle)
614 if(pGC->lineWidth == 0)
616 if (pGC->fillStyle == FillSolid)
618 #if defined(PIXEL_ADDR) && !defined(NO_ONE_RECT)
619 if (devPriv->oneRect &&
620 ((pDrawable->x >= pGC->pScreen->width - 32768) &&
621 (pDrawable->y >= pGC->pScreen->height - 32768)))
623 pGC->ops->Polylines = cfb8LineSS1Rect;
624 pGC->ops->PolySegment = cfb8SegmentSS1Rect;
629 pGC->ops->Polylines = cfb8LineSS1Rect;
630 pGC->ops->PolySegment = cfb8SegmentSS1Rect;
634 pGC->ops->Polylines = cfbLineSS;
635 pGC->ops->PolySegment = cfbSegmentSS;
640 pGC->ops->Polylines = miZeroLine;
643 pGC->ops->Polylines = miWideLine;
647 if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
649 pGC->ops->Polylines = cfbLineSD;
650 pGC->ops->PolySegment = cfbSegmentSD;
652 pGC->ops->Polylines = miWideDash;
657 if (new_text && (pGC->font))
659 if (FONTMAXBOUNDS(pGC->font,rightSideBearing) -
660 FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
661 FONTMINBOUNDS(pGC->font,characterWidth) < 0)
663 pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
664 pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
669 if (pGC->fillStyle == FillSolid)
671 if (devPriv->rop == GXcopy)
672 pGC->ops->PolyGlyphBlt = cfbPolyGlyphBlt8;
675 pGC->ops->PolyGlyphBlt = cfbPolyGlyphRop8;
677 pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
682 pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
683 /* special case ImageGlyphBlt for terminal emulator fonts */
684 #if !defined(WriteBitGroup) || PSZ == 8
685 if (TERMINALFONT(pGC->font) &&
686 (pGC->planemask & PMSK) == PMSK
688 && FONTMAXBOUNDS(pGC->font,characterWidth) >= PGSZB
692 pGC->ops->ImageGlyphBlt = useTEGlyphBlt;
698 if (devPriv->rop == GXcopy &&
699 pGC->fillStyle == FillSolid &&
700 (pGC->planemask & PMSK) == PMSK)
701 pGC->ops->ImageGlyphBlt = cfbImageGlyphBlt8;
704 pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
711 switch (pGC->fillStyle) {
713 switch (devPriv->rop) {
715 pGC->ops->FillSpans = cfbSolidSpansCopy;
718 pGC->ops->FillSpans = cfbSolidSpansXor;
721 pGC->ops->FillSpans = cfbSolidSpansGeneral;
726 if (devPriv->pRotatedPixmap)
728 if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK)
729 pGC->ops->FillSpans = cfbTile32FSCopy;
731 pGC->ops->FillSpans = cfbTile32FSGeneral;
734 pGC->ops->FillSpans = cfbUnnaturalTileFS;
738 if (devPriv->pRotatedPixmap)
739 pGC->ops->FillSpans = cfb8Stipple32FS;
742 pGC->ops->FillSpans = cfbUnnaturalStippleFS;
744 case FillOpaqueStippled:
746 if (devPriv->pRotatedPixmap)
747 pGC->ops->FillSpans = cfb8OpaqueStipple32FS;
750 pGC->ops->FillSpans = cfbUnnaturalStippleFS;
753 FatalError("cfbValidateGC: illegal fillStyle\n");
755 } /* end of new_fillspans */
758 #ifndef FOUR_BIT_CODE
759 pGC->ops->PolyFillRect = miPolyFillRect;
760 if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled)
762 pGC->ops->PolyFillRect = cfbPolyFillRect;
766 pGC->ops->PushPixels = mfbPushPixels;
767 if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy)
768 pGC->ops->PushPixels = cfbPushPixels8;
770 pGC->ops->PolyFillArc = miPolyFillArc;
771 if (pGC->fillStyle == FillSolid)
773 switch (devPriv->rop)
776 pGC->ops->PolyFillArc = cfbPolyFillArcSolidCopy;
779 pGC->ops->PolyFillArc = cfbPolyFillArcSolidGeneral;