1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
49 #ifdef HAVE_DIX_CONFIG_H
50 #include <dix-config.h>
55 #include <X11/Xproto.h>
59 #include "pixmapstr.h"
60 #include "dixfontstr.h"
61 #include "scrnintstr.h"
67 extern XID clientErrorValue
;
68 extern FontPtr defaultFont
;
70 static Bool
CreateDefaultTile(GCPtr pGC
);
72 static unsigned char DefaultDash
[2] = {4, 4};
75 ValidateGC(DrawablePtr pDraw
, GC
*pGC
)
77 (*pGC
->funcs
->ValidateGC
) (pGC
, pGC
->stateChanges
, pDraw
);
78 pGC
->stateChanges
= 0;
79 pGC
->serialNumber
= pDraw
->serialNumber
;
83 /* dixChangeGC(client, pGC, mask, pC32, pUnion)
85 * This function was created as part of the Security extension
86 * implementation. The client performing the gc change must be passed so
87 * that access checks can be performed on any tiles, stipples, or fonts
88 * that are specified. ddxen can call this too; they should normally
89 * pass NullClient for the client since any access checking should have
90 * already been done at a higher level.
92 * Since we had to create a new function anyway, we decided to change the
93 * way the list of gc values is passed to eliminate the compiler warnings
94 * caused by the DoChangeGC interface. You can pass the values via pC32
95 * or pUnion, but not both; one of them must be NULL. If you don't need
96 * to pass any pointers, you can use either one:
98 * example calling dixChangeGC using pC32 parameter
103 * dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL);
105 * example calling dixChangeGC using pUnion parameter;
106 * same effect as above
109 * v[0].val = foreground;
110 * v[1].val = background;
111 * dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v);
113 * However, if you need to pass a pointer to a pixmap or font, you MUST
114 * use the pUnion parameter.
116 * example calling dixChangeGC passing pointers in the value list
117 * v[1].ptr is a pointer to a pixmap
120 * v[0].val = FillTiled;
121 * v[1].ptr = pPixmap;
122 * dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v);
124 * Note: we could have gotten by with just the pUnion parameter, but on
125 * 64 bit machines that would have forced us to copy the value list that
126 * comes in the ChangeGC request.
128 * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this
129 * is far too many changes to consider at this time, so we've only
130 * changed the ones that caused compiler warnings. New code should use
136 #define NEXTVAL(_type, _var) { \
137 if (pC32) _var = (_type)*pC32++; \
139 _var = (_type)(pUnion->val); pUnion++; \
143 #define NEXT_PTR(_type, _var) { \
144 assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; }
147 dixChangeGC(ClientPtr client
, GC
*pGC
, BITS32 mask
, CARD32
*pC32
, ChangeGCValPtr pUnion
)
154 assert( (pC32
&& !pUnion
) || (!pC32
&& pUnion
) );
155 pGC
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
157 maskQ
= mask
; /* save these for when we walk the GCque */
158 while (mask
&& !error
)
160 index2
= (BITS32
) lowbit (mask
);
162 pGC
->stateChanges
|= index2
;
168 NEXTVAL(CARD8
, newalu
);
173 clientErrorValue
= newalu
;
179 NEXTVAL(unsigned long, pGC
->planemask
);
182 NEXTVAL(unsigned long, pGC
->fgPixel
);
184 * this is for CreateGC
186 if (!pGC
->tileIsPixel
&& !pGC
->tile
.pixmap
)
188 pGC
->tileIsPixel
= TRUE
;
189 pGC
->tile
.pixel
= pGC
->fgPixel
;
193 NEXTVAL(unsigned long, pGC
->bgPixel
);
195 case GCLineWidth
: /* ??? line width is a CARD16 */
196 NEXTVAL(CARD16
, pGC
->lineWidth
);
200 unsigned int newlinestyle
;
201 NEXTVAL(unsigned int, newlinestyle
);
202 if (newlinestyle
<= LineDoubleDash
)
203 pGC
->lineStyle
= newlinestyle
;
206 clientErrorValue
= newlinestyle
;
213 unsigned int newcapstyle
;
214 NEXTVAL(unsigned int, newcapstyle
);
215 if (newcapstyle
<= CapProjecting
)
216 pGC
->capStyle
= newcapstyle
;
219 clientErrorValue
= newcapstyle
;
226 unsigned int newjoinstyle
;
227 NEXTVAL(unsigned int, newjoinstyle
);
228 if (newjoinstyle
<= JoinBevel
)
229 pGC
->joinStyle
= newjoinstyle
;
232 clientErrorValue
= newjoinstyle
;
239 unsigned int newfillstyle
;
240 NEXTVAL(unsigned int, newfillstyle
);
241 if (newfillstyle
<= FillOpaqueStippled
)
242 pGC
->fillStyle
= newfillstyle
;
245 clientErrorValue
= newfillstyle
;
252 unsigned int newfillrule
;
253 NEXTVAL(unsigned int, newfillrule
);
254 if (newfillrule
<= WindingRule
)
255 pGC
->fillRule
= newfillrule
;
258 clientErrorValue
= newfillrule
;
268 NEXT_PTR(PixmapPtr
, pPixmap
);
272 NEXTVAL(XID
, newpix
);
273 pPixmap
= (PixmapPtr
)SecurityLookupIDByType(client
,
274 newpix
, RT_PIXMAP
, DixReadAccess
);
278 if ((pPixmap
->drawable
.depth
!= pGC
->depth
) ||
279 (pPixmap
->drawable
.pScreen
!= pGC
->pScreen
))
286 if (!pGC
->tileIsPixel
)
287 (* pGC
->pScreen
->DestroyPixmap
)(pGC
->tile
.pixmap
);
288 pGC
->tileIsPixel
= FALSE
;
289 pGC
->tile
.pixmap
= pPixmap
;
294 clientErrorValue
= newpix
;
304 NEXT_PTR(PixmapPtr
, pPixmap
);
308 NEXTVAL(XID
, newstipple
)
309 pPixmap
= (PixmapPtr
)SecurityLookupIDByType(client
,
310 newstipple
, RT_PIXMAP
, DixReadAccess
);
314 if ((pPixmap
->drawable
.depth
!= 1) ||
315 (pPixmap
->drawable
.pScreen
!= pGC
->pScreen
))
323 (* pGC
->pScreen
->DestroyPixmap
)(pGC
->stipple
);
324 pGC
->stipple
= pPixmap
;
329 clientErrorValue
= newstipple
;
334 case GCTileStipXOrigin
:
335 NEXTVAL(INT16
, pGC
->patOrg
.x
);
337 case GCTileStipYOrigin
:
338 NEXTVAL(INT16
, pGC
->patOrg
.y
);
346 NEXT_PTR(FontPtr
, pFont
);
350 NEXTVAL(XID
, newfont
)
351 pFont
= (FontPtr
)SecurityLookupIDByType(client
, newfont
,
352 RT_FONT
, DixReadAccess
);
358 CloseFont(pGC
->font
, (Font
)0);
363 clientErrorValue
= newfont
;
368 case GCSubwindowMode
:
370 unsigned int newclipmode
;
371 NEXTVAL(unsigned int, newclipmode
);
372 if (newclipmode
<= IncludeInferiors
)
373 pGC
->subWindowMode
= newclipmode
;
376 clientErrorValue
= newclipmode
;
381 case GCGraphicsExposures
:
384 NEXTVAL(unsigned int, newge
);
386 pGC
->graphicsExposures
= newge
;
389 clientErrorValue
= newge
;
395 NEXTVAL(INT16
, pGC
->clipOrg
.x
);
398 NEXTVAL(INT16
, pGC
->clipOrg
.y
);
407 NEXT_PTR(PixmapPtr
, pPixmap
);
415 pPixmap
= NullPixmap
;
418 pPixmap
= (PixmapPtr
)SecurityLookupIDByType(client
,
419 pid
, RT_PIXMAP
, DixReadAccess
);
424 if ((pPixmap
->drawable
.depth
!= 1) ||
425 (pPixmap
->drawable
.pScreen
!= pGC
->pScreen
))
431 clipType
= CT_PIXMAP
;
435 else if (!pUnion
&& (pid
!= None
))
437 clientErrorValue
= pid
;
442 (*pGC
->funcs
->ChangeClip
)(pGC
, clipType
,
443 (pointer
)pPixmap
, 0);
448 NEXTVAL(INT16
, pGC
->dashOffset
);
453 NEXTVAL(CARD8
, newdash
);
456 if (pGC
->dash
!= DefaultDash
)
459 pGC
->numInDashList
= 2;
460 pGC
->dash
= DefaultDash
;
463 else if (newdash
!= 0)
467 dash
= (unsigned char *)xalloc(2 * sizeof(unsigned char));
470 if (pGC
->dash
!= DefaultDash
)
472 pGC
->numInDashList
= 2;
482 clientErrorValue
= newdash
;
489 unsigned int newarcmode
;
490 NEXTVAL(unsigned int, newarcmode
);
491 if (newarcmode
<= ArcPieSlice
)
492 pGC
->arcMode
= newarcmode
;
495 clientErrorValue
= newarcmode
;
501 clientErrorValue
= maskQ
;
505 } /* end while mask && !error */
507 if (pGC
->fillStyle
== FillTiled
&& pGC
->tileIsPixel
)
509 if (!CreateDefaultTile (pGC
))
511 pGC
->fillStyle
= FillSolid
;
515 (*pGC
->funcs
->ChangeGC
)(pGC
, maskQ
);
522 /* Publically defined entry to ChangeGC. Just calls dixChangeGC and tells
523 * it that all of the entries are constants or IDs */
525 ChangeGC(GC
*pGC
, BITS32 mask
, XID
*pval
)
527 return (dixChangeGC(NullClient
, pGC
, mask
, pval
, NULL
));
530 /* DoChangeGC(pGC, mask, pval, fPointer)
531 mask is a set of bits indicating which values to change.
532 pval contains an appropriate value for each mask.
533 fPointer is true if the values for tiles, stipples, fonts or clipmasks
534 are pointers instead of IDs. Note: if you are passing pointers you
535 MUST declare the array of values as type pointer! Other data types
536 may not be large enough to hold pointers on some machines. Yes,
537 this means you have to cast to (XID *) when you pass the array to
538 DoChangeGC. Similarly, if you are not passing pointers (fPointer = 0) you
539 MUST declare the array as type XID (not unsigned long!), or again the wrong
540 size data type may be used. To avoid this cruftiness, use dixChangeGC
543 if there is an error, the value is marked as changed
544 anyway, which is probably wrong, but infrequent.
547 all values sent over the protocol for ChangeGC requests are
551 DoChangeGC(GC
*pGC
, BITS32 mask
, XID
*pval
, int fPointer
)
554 /* XXX might be a problem on 64 bit big-endian servers */
555 return dixChangeGC(NullClient
, pGC
, mask
, NULL
, (ChangeGCValPtr
)pval
);
557 return dixChangeGC(NullClient
, pGC
, mask
, pval
, NULL
);
561 /* CreateGC(pDrawable, mask, pval, pStatus)
562 creates a default GC for the given drawable, using mask to fill
563 in any non-default values.
564 Returns a pointer to the new GC on success, NULL otherwise.
565 returns status of non-default fields in pStatus
567 should check for failure to create default tile
572 AllocateGC(ScreenPtr pScreen
)
581 pGC
= (GCPtr
)xalloc(pScreen
->totalGCSize
);
584 ppriv
= (DevUnion
*)(pGC
+ 1);
585 pGC
->devPrivates
= ppriv
;
586 sizes
= pScreen
->GCPrivateSizes
;
587 ptr
= (char *)(ppriv
+ pScreen
->GCPrivateLen
);
588 for (i
= pScreen
->GCPrivateLen
; --i
>= 0; ppriv
++, sizes
++)
590 if ( (size
= *sizes
) )
592 ppriv
->ptr
= (pointer
)ptr
;
596 ppriv
->ptr
= (pointer
)NULL
;
603 CreateGC(DrawablePtr pDrawable
, BITS32 mask
, XID
*pval
, int *pStatus
)
607 pGC
= AllocateGC(pDrawable
->pScreen
);
614 pGC
->pScreen
= pDrawable
->pScreen
;
615 pGC
->depth
= pDrawable
->depth
;
616 pGC
->alu
= GXcopy
; /* dst <- src */
618 pGC
->serialNumber
= GC_CHANGE_SERIAL_BIT
;
624 pGC
->lineStyle
= LineSolid
;
625 pGC
->capStyle
= CapButt
;
626 pGC
->joinStyle
= JoinMiter
;
627 pGC
->fillStyle
= FillSolid
;
628 pGC
->fillRule
= EvenOddRule
;
629 pGC
->arcMode
= ArcPieSlice
;
630 if (mask
& GCForeground
)
633 * magic special case -- ChangeGC checks for this condition
634 * and snags the Foreground value to create a pseudo default-tile
636 pGC
->tileIsPixel
= FALSE
;
637 pGC
->tile
.pixmap
= NullPixmap
;
641 pGC
->tileIsPixel
= TRUE
;
647 pGC
->subWindowMode
= ClipByChildren
;
648 pGC
->graphicsExposures
= TRUE
;
651 pGC
->clientClipType
= CT_NONE
;
652 pGC
->clientClip
= (pointer
)NULL
;
653 pGC
->numInDashList
= 2;
654 pGC
->dash
= DefaultDash
;
656 pGC
->lastWinOrg
.x
= 0;
657 pGC
->lastWinOrg
.y
= 0;
659 /* use the default font and stipple */
660 pGC
->font
= defaultFont
;
661 defaultFont
->refcnt
++;
662 pGC
->stipple
= pGC
->pScreen
->PixmapPerDepth
[0];
663 pGC
->stipple
->refcnt
++;
665 pGC
->stateChanges
= (1 << (GCLastBit
+1)) - 1;
666 if (!(*pGC
->pScreen
->CreateGC
)(pGC
))
669 *pStatus
= ChangeGC(pGC
, mask
, pval
);
672 if (*pStatus
!= Success
)
674 if (!pGC
->tileIsPixel
&& !pGC
->tile
.pixmap
)
675 pGC
->tileIsPixel
= TRUE
; /* undo special case */
684 CreateDefaultTile (GCPtr pGC
)
694 (*pGC
->pScreen
->QueryBestSize
)(TileShape
, &w
, &h
, pGC
->pScreen
);
696 (*pGC
->pScreen
->CreatePixmap
)(pGC
->pScreen
,
698 pgcScratch
= GetScratchGC(pGC
->depth
, pGC
->pScreen
);
699 if (!pTile
|| !pgcScratch
)
702 (*pTile
->drawable
.pScreen
->DestroyPixmap
)(pTile
);
704 FreeScratchGC(pgcScratch
);
708 tmpval
[1] = pGC
->tile
.pixel
;
709 tmpval
[2] = FillSolid
;
710 (void)ChangeGC(pgcScratch
, GCFunction
| GCForeground
| GCFillStyle
,
712 ValidateGC((DrawablePtr
)pTile
, pgcScratch
);
717 (*pgcScratch
->ops
->PolyFillRect
)((DrawablePtr
)pTile
, pgcScratch
, 1, &rect
);
718 /* Always remember to free the scratch graphics context after use. */
719 FreeScratchGC(pgcScratch
);
721 pGC
->tileIsPixel
= FALSE
;
722 pGC
->tile
.pixmap
= pTile
;
727 CopyGC(GC
*pgcSrc
, GC
*pgcDst
, BITS32 mask
)
733 if (pgcSrc
== pgcDst
)
735 pgcDst
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
736 pgcDst
->stateChanges
|= mask
;
740 index2
= (BITS32
) lowbit (mask
);
745 pgcDst
->alu
= pgcSrc
->alu
;
748 pgcDst
->planemask
= pgcSrc
->planemask
;
751 pgcDst
->fgPixel
= pgcSrc
->fgPixel
;
754 pgcDst
->bgPixel
= pgcSrc
->bgPixel
;
757 pgcDst
->lineWidth
= pgcSrc
->lineWidth
;
760 pgcDst
->lineStyle
= pgcSrc
->lineStyle
;
763 pgcDst
->capStyle
= pgcSrc
->capStyle
;
766 pgcDst
->joinStyle
= pgcSrc
->joinStyle
;
769 pgcDst
->fillStyle
= pgcSrc
->fillStyle
;
772 pgcDst
->fillRule
= pgcSrc
->fillRule
;
776 if (EqualPixUnion(pgcDst
->tileIsPixel
,
783 if (!pgcDst
->tileIsPixel
)
784 (* pgcDst
->pScreen
->DestroyPixmap
)(pgcDst
->tile
.pixmap
);
785 pgcDst
->tileIsPixel
= pgcSrc
->tileIsPixel
;
786 pgcDst
->tile
= pgcSrc
->tile
;
787 if (!pgcDst
->tileIsPixel
)
788 pgcDst
->tile
.pixmap
->refcnt
++;
793 if (pgcDst
->stipple
== pgcSrc
->stipple
)
796 (* pgcDst
->pScreen
->DestroyPixmap
)(pgcDst
->stipple
);
797 pgcDst
->stipple
= pgcSrc
->stipple
;
799 pgcDst
->stipple
->refcnt
++;
802 case GCTileStipXOrigin
:
803 pgcDst
->patOrg
.x
= pgcSrc
->patOrg
.x
;
805 case GCTileStipYOrigin
:
806 pgcDst
->patOrg
.y
= pgcSrc
->patOrg
.y
;
809 if (pgcDst
->font
== pgcSrc
->font
)
812 CloseFont(pgcDst
->font
, (Font
)0);
813 if ((pgcDst
->font
= pgcSrc
->font
) != NullFont
)
814 (pgcDst
->font
)->refcnt
++;
816 case GCSubwindowMode
:
817 pgcDst
->subWindowMode
= pgcSrc
->subWindowMode
;
819 case GCGraphicsExposures
:
820 pgcDst
->graphicsExposures
= pgcSrc
->graphicsExposures
;
823 pgcDst
->clipOrg
.x
= pgcSrc
->clipOrg
.x
;
826 pgcDst
->clipOrg
.y
= pgcSrc
->clipOrg
.y
;
829 (* pgcDst
->funcs
->CopyClip
)(pgcDst
, pgcSrc
);
832 pgcDst
->dashOffset
= pgcSrc
->dashOffset
;
835 if (pgcSrc
->dash
== DefaultDash
)
837 if (pgcDst
->dash
!= DefaultDash
)
840 pgcDst
->numInDashList
= pgcSrc
->numInDashList
;
841 pgcDst
->dash
= pgcSrc
->dash
;
849 dash
= (unsigned char *)xalloc(pgcSrc
->numInDashList
*
850 sizeof(unsigned char));
853 if (pgcDst
->dash
!= DefaultDash
)
855 pgcDst
->numInDashList
= pgcSrc
->numInDashList
;
857 for (i
=0; i
<pgcSrc
->numInDashList
; i
++)
858 dash
[i
] = pgcSrc
->dash
[i
];
865 pgcDst
->arcMode
= pgcSrc
->arcMode
;
868 clientErrorValue
= maskQ
;
873 if (pgcDst
->fillStyle
== FillTiled
&& pgcDst
->tileIsPixel
)
875 if (!CreateDefaultTile (pgcDst
))
877 pgcDst
->fillStyle
= FillSolid
;
881 (*pgcDst
->funcs
->CopyGC
) (pgcSrc
, maskQ
, pgcDst
);
886 * does the diX part of freeing the characteristics in the GC.
888 * \param value must conform to DeleteType
891 FreeGC(pointer value
, XID gid
)
893 GCPtr pGC
= (GCPtr
)value
;
895 CloseFont(pGC
->font
, (Font
)0);
896 (* pGC
->funcs
->DestroyClip
)(pGC
);
898 if (!pGC
->tileIsPixel
)
899 (* pGC
->pScreen
->DestroyPixmap
)(pGC
->tile
.pixmap
);
901 (* pGC
->pScreen
->DestroyPixmap
)(pGC
->stipple
);
903 (*pGC
->funcs
->DestroyGC
) (pGC
);
904 if (pGC
->dash
!= DefaultDash
)
910 /* CreateScratchGC(pScreen, depth)
911 like CreateGC, but doesn't do the default tile or stipple,
912 since we can't create them without already having a GC. any code
913 using the tile or stipple has to set them explicitly anyway,
914 since the state of the scratch gc is unknown. This is OK
915 because ChangeGC() has to be able to deal with NULL tiles and
916 stipples anyway (in case the CreateGC() call has provided a
917 value for them -- we can't set the default tile until the
918 client-supplied attributes are installed, since the fgPixel
919 is what fills the default tile. (maybe this comment should
920 go with CreateGC() or ChangeGC().)
924 CreateScratchGC(ScreenPtr pScreen
, unsigned depth
)
928 pGC
= AllocateGC(pScreen
);
932 pGC
->pScreen
= pScreen
;
934 pGC
->alu
= GXcopy
; /* dst <- src */
936 pGC
->serialNumber
= 0;
941 pGC
->lineStyle
= LineSolid
;
942 pGC
->capStyle
= CapButt
;
943 pGC
->joinStyle
= JoinMiter
;
944 pGC
->fillStyle
= FillSolid
;
945 pGC
->fillRule
= EvenOddRule
;
946 pGC
->arcMode
= ArcPieSlice
;
947 pGC
->font
= defaultFont
;
948 if ( pGC
->font
) /* necessary, because open of default font could fail */
950 pGC
->tileIsPixel
= TRUE
;
952 pGC
->stipple
= NullPixmap
;
955 pGC
->subWindowMode
= ClipByChildren
;
956 pGC
->graphicsExposures
= TRUE
;
959 pGC
->clientClipType
= CT_NONE
;
961 pGC
->numInDashList
= 2;
962 pGC
->dash
= DefaultDash
;
963 pGC
->lastWinOrg
.x
= 0;
964 pGC
->lastWinOrg
.y
= 0;
966 pGC
->stateChanges
= (1 << (GCLastBit
+1)) - 1;
967 if (!(*pScreen
->CreateGC
)(pGC
))
976 FreeGCperDepth(int screenNum
)
982 pScreen
= screenInfo
.screens
[screenNum
];
983 ppGC
= pScreen
->GCperDepth
;
985 for (i
= 0; i
<= pScreen
->numDepths
; i
++)
986 (void)FreeGC(ppGC
[i
], (XID
)0);
992 CreateGCperDepth(int screenNum
)
999 pScreen
= screenInfo
.screens
[screenNum
];
1001 ppGC
= pScreen
->GCperDepth
;
1002 /* do depth 1 separately because it's not included in list */
1003 if (!(ppGC
[0] = CreateScratchGC(pScreen
, 1)))
1005 ppGC
[0]->graphicsExposures
= FALSE
;
1006 /* Make sure we don't overflow GCperDepth[] */
1007 if( pScreen
->numDepths
> MAXFORMATS
)
1010 pDepth
= pScreen
->allowedDepths
;
1011 for (i
=0; i
<pScreen
->numDepths
; i
++, pDepth
++)
1013 if (!(ppGC
[i
+1] = CreateScratchGC(pScreen
, pDepth
->depth
)))
1016 (void)FreeGC(ppGC
[i
], (XID
)0);
1019 ppGC
[i
+1]->graphicsExposures
= FALSE
;
1025 CreateDefaultStipple(int screenNum
)
1033 pScreen
= screenInfo
.screens
[screenNum
];
1037 (* pScreen
->QueryBestSize
)(StippleShape
, &w
, &h
, pScreen
);
1038 if (!(pScreen
->PixmapPerDepth
[0] =
1039 (*pScreen
->CreatePixmap
)(pScreen
, w
, h
, 1)))
1041 /* fill stipple with 1 */
1042 tmpval
[0] = GXcopy
; tmpval
[1] = 1; tmpval
[2] = FillSolid
;
1043 pgcScratch
= GetScratchGC(1, pScreen
);
1046 (*pScreen
->DestroyPixmap
)(pScreen
->PixmapPerDepth
[0]);
1049 (void)ChangeGC(pgcScratch
, GCFunction
|GCForeground
|GCFillStyle
, tmpval
);
1050 ValidateGC((DrawablePtr
)pScreen
->PixmapPerDepth
[0], pgcScratch
);
1055 (*pgcScratch
->ops
->PolyFillRect
)((DrawablePtr
)pScreen
->PixmapPerDepth
[0],
1056 pgcScratch
, 1, &rect
);
1057 FreeScratchGC(pgcScratch
);
1062 FreeDefaultStipple(int screenNum
)
1064 ScreenPtr pScreen
= screenInfo
.screens
[screenNum
];
1065 (*pScreen
->DestroyPixmap
)(pScreen
->PixmapPerDepth
[0]);
1069 SetDashes(GCPtr pGC
, unsigned offset
, unsigned ndash
, unsigned char *pdash
)
1072 unsigned char *p
, *indash
;
1081 /* dash segment must be > 0 */
1082 clientErrorValue
= 0;
1088 p
= (unsigned char *)xalloc(2 * ndash
* sizeof(unsigned char));
1090 p
= (unsigned char *)xalloc(ndash
* sizeof(unsigned char));
1094 pGC
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1095 if (offset
!= pGC
->dashOffset
)
1097 pGC
->dashOffset
= offset
;
1098 pGC
->stateChanges
|= GCDashOffset
;
1099 maskQ
|= GCDashOffset
;
1102 if (pGC
->dash
!= DefaultDash
)
1104 pGC
->numInDashList
= ndash
;
1108 pGC
->numInDashList
+= ndash
;
1116 pGC
->stateChanges
|= GCDashList
;
1117 maskQ
|= GCDashList
;
1119 if (pGC
->funcs
->ChangeGC
)
1120 (*pGC
->funcs
->ChangeGC
) (pGC
, maskQ
);
1125 VerifyRectOrder(int nrects
, xRectangle
*prects
, int ordering
)
1127 xRectangle
*prectP
, *prectN
;
1137 for(i
= 1, prectP
= prects
, prectN
= prects
+ 1;
1139 i
++, prectP
++, prectN
++)
1140 if(prectN
->y
< prectP
->y
)
1147 for(i
= 1, prectP
= prects
, prectN
= prects
+ 1;
1149 i
++, prectP
++, prectN
++)
1150 if((prectN
->y
< prectP
->y
) ||
1151 ( (prectN
->y
== prectP
->y
) &&
1152 (prectN
->x
< prectP
->x
) ) )
1159 for(i
= 1, prectP
= prects
, prectN
= prects
+ 1;
1161 i
++, prectP
++, prectN
++)
1162 if((prectN
->y
!= prectP
->y
&&
1163 prectN
->y
< prectP
->y
+ (int) prectP
->height
) ||
1164 ((prectN
->y
== prectP
->y
) &&
1165 (prectN
->height
!= prectP
->height
||
1166 prectN
->x
< prectP
->x
+ (int) prectP
->width
)))
1175 SetClipRects(GCPtr pGC
, int xOrigin
, int yOrigin
, int nrects
,
1176 xRectangle
*prects
, int ordering
)
1179 xRectangle
*prectsNew
;
1181 newct
= VerifyRectOrder(nrects
, prects
, ordering
);
1184 size
= nrects
* sizeof(xRectangle
);
1185 prectsNew
= (xRectangle
*) xalloc(size
);
1186 if (!prectsNew
&& size
)
1189 pGC
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1190 pGC
->clipOrg
.x
= xOrigin
;
1191 pGC
->stateChanges
|= GCClipXOrigin
;
1193 pGC
->clipOrg
.y
= yOrigin
;
1194 pGC
->stateChanges
|= GCClipYOrigin
;
1197 memmove((char *)prectsNew
, (char *)prects
, size
);
1198 (*pGC
->funcs
->ChangeClip
)(pGC
, newct
, (pointer
)prectsNew
, nrects
);
1199 if (pGC
->funcs
->ChangeGC
)
1200 (*pGC
->funcs
->ChangeGC
) (pGC
, GCClipXOrigin
|GCClipYOrigin
|GCClipMask
);
1206 sets reasonable defaults
1207 if we can get a pre-allocated one, use it and mark it as used.
1208 if we can't, create one out of whole cloth (The Velveteen GC -- if
1209 you use it often enough it will become real.)
1212 GetScratchGC(unsigned depth
, ScreenPtr pScreen
)
1217 for (i
=0; i
<=pScreen
->numDepths
; i
++)
1218 if ( pScreen
->GCperDepth
[i
]->depth
== depth
&&
1219 !(pScreen
->rgf
& (1L << (i
+1)))
1222 pScreen
->rgf
|= (1L << (i
+1));
1223 pGC
= (pScreen
->GCperDepth
[i
]);
1226 pGC
->planemask
= ~0;
1227 pGC
->serialNumber
= 0;
1231 pGC
->lineStyle
= LineSolid
;
1232 pGC
->capStyle
= CapButt
;
1233 pGC
->joinStyle
= JoinMiter
;
1234 pGC
->fillStyle
= FillSolid
;
1235 pGC
->fillRule
= EvenOddRule
;
1236 pGC
->arcMode
= ArcChord
;
1239 pGC
->subWindowMode
= ClipByChildren
;
1240 pGC
->graphicsExposures
= FALSE
;
1243 if (pGC
->clientClipType
!= CT_NONE
)
1244 (*pGC
->funcs
->ChangeClip
) (pGC
, CT_NONE
, NULL
, 0);
1245 pGC
->stateChanges
= (1 << (GCLastBit
+1)) - 1;
1248 /* if we make it this far, need to roll our own */
1249 pGC
= CreateScratchGC(pScreen
, depth
);
1251 pGC
->graphicsExposures
= FALSE
;
1256 if the gc to free is in the table of pre-existing ones,
1257 mark it as available.
1258 if not, free it for real
1261 FreeScratchGC(GCPtr pGC
)
1263 ScreenPtr pScreen
= pGC
->pScreen
;
1266 for (i
=0; i
<=pScreen
->numDepths
; i
++)
1268 if ( pScreen
->GCperDepth
[i
] == pGC
)
1270 pScreen
->rgf
&= ~(1L << (i
+1));
1274 (void)FreeGC(pGC
, (GContext
)0);