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.
25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 ******************************************************************/
47 #ifdef HAVE_DIX_CONFIG_H
48 #include <dix-config.h>
53 #include <X11/Xproto.h>
57 #include "pixmapstr.h"
58 #include "dixfontstr.h"
59 #include "scrnintstr.h"
61 #include "dixstruct.h"
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 * ChangeGC/ChangeGCXIDs:
85 * The client performing the gc change must be passed so that access
86 * checks can be performed on any tiles, stipples, or fonts that are
87 * specified. ddxen can call this too; they should normally pass
88 * NullClient for the client since any access checking should have
89 * already been done at a higher level.
91 * If you have any XIDs, you must use ChangeGCXIDs:
96 * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v);
98 * However, if you need to pass a pointer to a pixmap or font, you must
102 * v[0].val = FillTiled;
103 * v[1].ptr = pPixmap;
104 * ChangeGC(client, pGC, GCFillStyle|GCTile, v);
106 * If you have neither XIDs nor pointers, you can use either function,
107 * but ChangeGC will do less work.
110 * v[0].val = foreground;
111 * v[1].val = background;
112 * ChangeGC(client, pGC, GCForeground|GCBackground, v);
115 #define NEXTVAL(_type, _var) { \
116 _var = (_type)(pUnion->val); pUnion++; \
119 #define NEXT_PTR(_type, _var) { \
120 _var = (_type)pUnion->ptr; pUnion++; }
123 ChangeGC(ClientPtr client
, GC
* pGC
, BITS32 mask
, ChangeGCValPtr pUnion
)
131 pGC
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
133 maskQ
= mask
; /* save these for when we walk the GCque */
134 while (mask
&& !error
) {
135 index2
= (BITS32
) lowbit(mask
);
137 pGC
->stateChanges
|= index2
;
142 NEXTVAL(CARD8
, newalu
);
148 client
->errorValue
= newalu
;
154 NEXTVAL(unsigned long, pGC
->planemask
);
158 NEXTVAL(unsigned long, pGC
->fgPixel
);
161 * this is for CreateGC
163 if (!pGC
->tileIsPixel
&& !pGC
->tile
.pixmap
) {
164 pGC
->tileIsPixel
= TRUE
;
165 pGC
->tile
.pixel
= pGC
->fgPixel
;
169 NEXTVAL(unsigned long, pGC
->bgPixel
);
172 case GCLineWidth
: /* ??? line width is a CARD16 */
173 NEXTVAL(CARD16
, pGC
->lineWidth
);
178 unsigned int newlinestyle
;
179 NEXTVAL(unsigned int, newlinestyle
);
181 if (newlinestyle
<= LineDoubleDash
)
182 pGC
->lineStyle
= newlinestyle
;
185 client
->errorValue
= newlinestyle
;
192 unsigned int newcapstyle
;
193 NEXTVAL(unsigned int, newcapstyle
);
195 if (newcapstyle
<= CapProjecting
)
196 pGC
->capStyle
= newcapstyle
;
199 client
->errorValue
= newcapstyle
;
206 unsigned int newjoinstyle
;
207 NEXTVAL(unsigned int, newjoinstyle
);
209 if (newjoinstyle
<= JoinBevel
)
210 pGC
->joinStyle
= newjoinstyle
;
213 client
->errorValue
= newjoinstyle
;
220 unsigned int newfillstyle
;
221 NEXTVAL(unsigned int, newfillstyle
);
223 if (newfillstyle
<= FillOpaqueStippled
)
224 pGC
->fillStyle
= newfillstyle
;
227 client
->errorValue
= newfillstyle
;
234 unsigned int newfillrule
;
235 NEXTVAL(unsigned int, newfillrule
);
237 if (newfillrule
<= WindingRule
)
238 pGC
->fillRule
= newfillrule
;
241 client
->errorValue
= newfillrule
;
247 NEXT_PTR(PixmapPtr
, pPixmap
);
249 if ((pPixmap
->drawable
.depth
!= pGC
->depth
) ||
250 (pPixmap
->drawable
.pScreen
!= pGC
->pScreen
)) {
255 if (!pGC
->tileIsPixel
)
256 (*pGC
->pScreen
->DestroyPixmap
) (pGC
->tile
.pixmap
);
257 pGC
->tileIsPixel
= FALSE
;
258 pGC
->tile
.pixmap
= pPixmap
;
262 NEXT_PTR(PixmapPtr
, pPixmap
);
264 if ((pPixmap
->drawable
.depth
!= 1) ||
265 (pPixmap
->drawable
.pScreen
!= pGC
->pScreen
)) {
271 (*pGC
->pScreen
->DestroyPixmap
) (pGC
->stipple
);
272 pGC
->stipple
= pPixmap
;
275 case GCTileStipXOrigin
:
276 NEXTVAL(INT16
, pGC
->patOrg
.x
);
279 case GCTileStipYOrigin
:
280 NEXTVAL(INT16
, pGC
->patOrg
.y
);
286 NEXT_PTR(FontPtr
, pFont
);
290 CloseFont(pGC
->font
, (Font
) 0);
294 case GCSubwindowMode
:
296 unsigned int newclipmode
;
297 NEXTVAL(unsigned int, newclipmode
);
299 if (newclipmode
<= IncludeInferiors
)
300 pGC
->subWindowMode
= newclipmode
;
303 client
->errorValue
= newclipmode
;
308 case GCGraphicsExposures
:
311 NEXTVAL(unsigned int, newge
);
314 pGC
->graphicsExposures
= newge
;
317 client
->errorValue
= newge
;
323 NEXTVAL(INT16
, pGC
->clipOrg
.x
);
327 NEXTVAL(INT16
, pGC
->clipOrg
.y
);
331 NEXT_PTR(PixmapPtr
, pPixmap
);
334 if ((pPixmap
->drawable
.depth
!= 1) ||
335 (pPixmap
->drawable
.pScreen
!= pGC
->pScreen
)) {
341 (*pGC
->funcs
->ChangeClip
) (pGC
, pPixmap
? CT_PIXMAP
: CT_NONE
,
342 (pointer
) pPixmap
, 0);
345 NEXTVAL(INT16
, pGC
->dashOffset
);
351 NEXTVAL(CARD8
, newdash
);
354 if (pGC
->dash
!= DefaultDash
) {
356 pGC
->numInDashList
= 2;
357 pGC
->dash
= DefaultDash
;
360 else if (newdash
!= 0) {
363 dash
= malloc(2 * sizeof(unsigned char));
365 if (pGC
->dash
!= DefaultDash
)
367 pGC
->numInDashList
= 2;
377 client
->errorValue
= newdash
;
384 unsigned int newarcmode
;
385 NEXTVAL(unsigned int, newarcmode
);
387 if (newarcmode
<= ArcPieSlice
)
388 pGC
->arcMode
= newarcmode
;
391 client
->errorValue
= newarcmode
;
398 client
->errorValue
= maskQ
;
402 } /* end while mask && !error */
404 if (pGC
->fillStyle
== FillTiled
&& pGC
->tileIsPixel
) {
405 if (!CreateDefaultTile(pGC
)) {
406 pGC
->fillStyle
= FillSolid
;
410 (*pGC
->funcs
->ChangeGC
) (pGC
, maskQ
);
417 static const struct {
422 {GCTile
, RT_PIXMAP
, DixReadAccess
},
423 {GCStipple
, RT_PIXMAP
, DixReadAccess
},
424 {GCFont
, RT_FONT
, DixUseAccess
},
425 {GCClipMask
, RT_PIXMAP
, DixReadAccess
},
429 ChangeGCXIDs(ClientPtr client
, GC
* pGC
, BITS32 mask
, CARD32
*pC32
)
431 ChangeGCVal vals
[GCLastBit
+ 1];
434 if (mask
& ~GCAllBits
) {
435 client
->errorValue
= mask
;
438 for (i
= Ones(mask
); i
--;)
439 vals
[i
].val
= pC32
[i
];
440 for (i
= 0; i
< sizeof(xidfields
) / sizeof(*xidfields
); ++i
) {
443 if (!(mask
& xidfields
[i
].mask
))
445 offset
= Ones(mask
& (xidfields
[i
].mask
- 1));
446 if (xidfields
[i
].mask
== GCClipMask
&& vals
[offset
].val
== None
) {
447 vals
[offset
].ptr
= NullPixmap
;
450 rc
= dixLookupResourceByType(&vals
[offset
].ptr
, vals
[offset
].val
,
451 xidfields
[i
].type
, client
,
452 xidfields
[i
].access_mode
);
454 client
->errorValue
= vals
[offset
].val
;
458 return ChangeGC(client
, pGC
, mask
, vals
);
462 NewGCObject(ScreenPtr pScreen
, int depth
)
466 pGC
= dixAllocateScreenObjectWithPrivates(pScreen
, GC
, PRIVATE_GC
);
471 pGC
->pScreen
= pScreen
;
473 pGC
->alu
= GXcopy
; /* dst <- src */
475 pGC
->serialNumber
= 0;
480 pGC
->lineStyle
= LineSolid
;
481 pGC
->capStyle
= CapButt
;
482 pGC
->joinStyle
= JoinMiter
;
483 pGC
->fillStyle
= FillSolid
;
484 pGC
->fillRule
= EvenOddRule
;
485 pGC
->arcMode
= ArcPieSlice
;
487 pGC
->tile
.pixmap
= NullPixmap
;
489 pGC
->tileIsPixel
= TRUE
;
492 pGC
->subWindowMode
= ClipByChildren
;
493 pGC
->graphicsExposures
= TRUE
;
496 pGC
->clientClipType
= CT_NONE
;
497 pGC
->clientClip
= (pointer
) NULL
;
498 pGC
->numInDashList
= 2;
499 pGC
->dash
= DefaultDash
;
502 /* use the default font and stipple */
503 pGC
->font
= defaultFont
;
504 if (pGC
->font
) /* necessary, because open of default font could fail */
506 pGC
->stipple
= pGC
->pScreen
->PixmapPerDepth
[0];
508 pGC
->stipple
->refcnt
++;
510 /* this is not a scratch GC */
511 pGC
->scratch_inuse
= FALSE
;
515 /* CreateGC(pDrawable, mask, pval, pStatus)
516 creates a default GC for the given drawable, using mask to fill
517 in any non-default values.
518 Returns a pointer to the new GC on success, NULL otherwise.
519 returns status of non-default fields in pStatus
521 should check for failure to create default tile
525 CreateGC(DrawablePtr pDrawable
, BITS32 mask
, XID
*pval
, int *pStatus
,
526 XID gcid
, ClientPtr client
)
530 pGC
= NewGCObject(pDrawable
->pScreen
, pDrawable
->depth
);
536 pGC
->serialNumber
= GC_CHANGE_SERIAL_BIT
;
537 if (mask
& GCForeground
) {
539 * magic special case -- ChangeGC checks for this condition
540 * and snags the Foreground value to create a pseudo default-tile
542 pGC
->tileIsPixel
= FALSE
;
545 pGC
->tileIsPixel
= TRUE
;
548 /* security creation/labeling check */
549 *pStatus
= XaceHook(XACE_RESOURCE_ACCESS
, client
, gcid
, RT_GC
, pGC
,
550 RT_NONE
, NULL
, DixCreateAccess
| DixSetAttrAccess
);
551 if (*pStatus
!= Success
)
554 pGC
->stateChanges
= GCAllBits
;
555 if (!(*pGC
->pScreen
->CreateGC
) (pGC
))
558 *pStatus
= ChangeGCXIDs(client
, pGC
, mask
, pval
);
563 if (*pStatus
!= Success
) {
564 if (!pGC
->tileIsPixel
&& !pGC
->tile
.pixmap
)
565 pGC
->tileIsPixel
= TRUE
; /* undo special case */
566 FreeGC(pGC
, (XID
) 0);
574 CreateDefaultTile(GCPtr pGC
)
576 ChangeGCVal tmpval
[3];
584 (*pGC
->pScreen
->QueryBestSize
) (TileShape
, &w
, &h
, pGC
->pScreen
);
586 (*pGC
->pScreen
->CreatePixmap
) (pGC
->pScreen
, w
, h
, pGC
->depth
, 0);
587 pgcScratch
= GetScratchGC(pGC
->depth
, pGC
->pScreen
);
588 if (!pTile
|| !pgcScratch
) {
590 (*pTile
->drawable
.pScreen
->DestroyPixmap
) (pTile
);
592 FreeScratchGC(pgcScratch
);
595 tmpval
[0].val
= GXcopy
;
596 tmpval
[1].val
= pGC
->tile
.pixel
;
597 tmpval
[2].val
= FillSolid
;
598 (void) ChangeGC(NullClient
, pgcScratch
,
599 GCFunction
| GCForeground
| GCFillStyle
, tmpval
);
600 ValidateGC((DrawablePtr
) pTile
, pgcScratch
);
605 (*pgcScratch
->ops
->PolyFillRect
) ((DrawablePtr
) pTile
, pgcScratch
, 1,
607 /* Always remember to free the scratch graphics context after use. */
608 FreeScratchGC(pgcScratch
);
610 pGC
->tileIsPixel
= FALSE
;
611 pGC
->tile
.pixmap
= pTile
;
616 CopyGC(GC
* pgcSrc
, GC
* pgcDst
, BITS32 mask
)
622 if (pgcSrc
== pgcDst
)
624 pgcDst
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
625 pgcDst
->stateChanges
|= mask
;
628 index2
= (BITS32
) lowbit(mask
);
632 pgcDst
->alu
= pgcSrc
->alu
;
635 pgcDst
->planemask
= pgcSrc
->planemask
;
638 pgcDst
->fgPixel
= pgcSrc
->fgPixel
;
641 pgcDst
->bgPixel
= pgcSrc
->bgPixel
;
644 pgcDst
->lineWidth
= pgcSrc
->lineWidth
;
647 pgcDst
->lineStyle
= pgcSrc
->lineStyle
;
650 pgcDst
->capStyle
= pgcSrc
->capStyle
;
653 pgcDst
->joinStyle
= pgcSrc
->joinStyle
;
656 pgcDst
->fillStyle
= pgcSrc
->fillStyle
;
659 pgcDst
->fillRule
= pgcSrc
->fillRule
;
663 if (EqualPixUnion(pgcDst
->tileIsPixel
,
665 pgcSrc
->tileIsPixel
, pgcSrc
->tile
)) {
668 if (!pgcDst
->tileIsPixel
)
669 (*pgcDst
->pScreen
->DestroyPixmap
) (pgcDst
->tile
.pixmap
);
670 pgcDst
->tileIsPixel
= pgcSrc
->tileIsPixel
;
671 pgcDst
->tile
= pgcSrc
->tile
;
672 if (!pgcDst
->tileIsPixel
)
673 pgcDst
->tile
.pixmap
->refcnt
++;
678 if (pgcDst
->stipple
== pgcSrc
->stipple
)
681 (*pgcDst
->pScreen
->DestroyPixmap
) (pgcDst
->stipple
);
682 pgcDst
->stipple
= pgcSrc
->stipple
;
684 pgcDst
->stipple
->refcnt
++;
687 case GCTileStipXOrigin
:
688 pgcDst
->patOrg
.x
= pgcSrc
->patOrg
.x
;
690 case GCTileStipYOrigin
:
691 pgcDst
->patOrg
.y
= pgcSrc
->patOrg
.y
;
694 if (pgcDst
->font
== pgcSrc
->font
)
697 CloseFont(pgcDst
->font
, (Font
) 0);
698 if ((pgcDst
->font
= pgcSrc
->font
) != NullFont
)
699 (pgcDst
->font
)->refcnt
++;
701 case GCSubwindowMode
:
702 pgcDst
->subWindowMode
= pgcSrc
->subWindowMode
;
704 case GCGraphicsExposures
:
705 pgcDst
->graphicsExposures
= pgcSrc
->graphicsExposures
;
708 pgcDst
->clipOrg
.x
= pgcSrc
->clipOrg
.x
;
711 pgcDst
->clipOrg
.y
= pgcSrc
->clipOrg
.y
;
714 (*pgcDst
->funcs
->CopyClip
) (pgcDst
, pgcSrc
);
717 pgcDst
->dashOffset
= pgcSrc
->dashOffset
;
720 if (pgcSrc
->dash
== DefaultDash
) {
721 if (pgcDst
->dash
!= DefaultDash
) {
723 pgcDst
->numInDashList
= pgcSrc
->numInDashList
;
724 pgcDst
->dash
= pgcSrc
->dash
;
731 dash
= malloc(pgcSrc
->numInDashList
* sizeof(unsigned char));
733 if (pgcDst
->dash
!= DefaultDash
)
735 pgcDst
->numInDashList
= pgcSrc
->numInDashList
;
737 for (i
= 0; i
< pgcSrc
->numInDashList
; i
++)
738 dash
[i
] = pgcSrc
->dash
[i
];
745 pgcDst
->arcMode
= pgcSrc
->arcMode
;
748 FatalError("CopyGC: Unhandled mask!\n");
751 if (pgcDst
->fillStyle
== FillTiled
&& pgcDst
->tileIsPixel
) {
752 if (!CreateDefaultTile(pgcDst
)) {
753 pgcDst
->fillStyle
= FillSolid
;
757 (*pgcDst
->funcs
->CopyGC
) (pgcSrc
, maskQ
, pgcDst
);
762 * does the diX part of freeing the characteristics in the GC.
764 * \param value must conform to DeleteType
767 FreeGC(pointer value
, XID gid
)
769 GCPtr pGC
= (GCPtr
) value
;
771 CloseFont(pGC
->font
, (Font
) 0);
772 (*pGC
->funcs
->DestroyClip
) (pGC
);
774 if (!pGC
->tileIsPixel
)
775 (*pGC
->pScreen
->DestroyPixmap
) (pGC
->tile
.pixmap
);
777 (*pGC
->pScreen
->DestroyPixmap
) (pGC
->stipple
);
779 (*pGC
->funcs
->DestroyGC
) (pGC
);
780 if (pGC
->dash
!= DefaultDash
)
782 dixFreeObjectWithPrivates(pGC
, PRIVATE_GC
);
786 /* CreateScratchGC(pScreen, depth)
787 like CreateGC, but doesn't do the default tile or stipple,
788 since we can't create them without already having a GC. any code
789 using the tile or stipple has to set them explicitly anyway,
790 since the state of the scratch gc is unknown. This is OK
791 because ChangeGC() has to be able to deal with NULL tiles and
792 stipples anyway (in case the CreateGC() call has provided a
793 value for them -- we can't set the default tile until the
794 client-supplied attributes are installed, since the fgPixel
795 is what fills the default tile. (maybe this comment should
796 go with CreateGC() or ChangeGC().)
800 CreateScratchGC(ScreenPtr pScreen
, unsigned depth
)
804 pGC
= NewGCObject(pScreen
, depth
);
808 pGC
->stateChanges
= GCAllBits
;
809 if (!(*pScreen
->CreateGC
) (pGC
)) {
810 FreeGC(pGC
, (XID
) 0);
817 FreeGCperDepth(int screenNum
)
823 pScreen
= screenInfo
.screens
[screenNum
];
824 ppGC
= pScreen
->GCperDepth
;
826 for (i
= 0; i
<= pScreen
->numDepths
; i
++) {
827 (void) FreeGC(ppGC
[i
], (XID
) 0);
833 CreateGCperDepth(int screenNum
)
840 pScreen
= screenInfo
.screens
[screenNum
];
841 ppGC
= pScreen
->GCperDepth
;
842 /* do depth 1 separately because it's not included in list */
843 if (!(ppGC
[0] = CreateScratchGC(pScreen
, 1)))
845 ppGC
[0]->graphicsExposures
= FALSE
;
846 /* Make sure we don't overflow GCperDepth[] */
847 if (pScreen
->numDepths
> MAXFORMATS
)
850 pDepth
= pScreen
->allowedDepths
;
851 for (i
= 0; i
< pScreen
->numDepths
; i
++, pDepth
++) {
852 if (!(ppGC
[i
+ 1] = CreateScratchGC(pScreen
, pDepth
->depth
))) {
854 (void) FreeGC(ppGC
[i
], (XID
) 0);
857 ppGC
[i
+ 1]->graphicsExposures
= FALSE
;
863 CreateDefaultStipple(int screenNum
)
866 ChangeGCVal tmpval
[3];
871 pScreen
= screenInfo
.screens
[screenNum
];
875 (*pScreen
->QueryBestSize
) (StippleShape
, &w
, &h
, pScreen
);
876 if (!(pScreen
->PixmapPerDepth
[0] =
877 (*pScreen
->CreatePixmap
) (pScreen
, w
, h
, 1, 0)))
879 /* fill stipple with 1 */
880 tmpval
[0].val
= GXcopy
;
882 tmpval
[2].val
= FillSolid
;
883 pgcScratch
= GetScratchGC(1, pScreen
);
885 (*pScreen
->DestroyPixmap
) (pScreen
->PixmapPerDepth
[0]);
888 (void) ChangeGC(NullClient
, pgcScratch
,
889 GCFunction
| GCForeground
| GCFillStyle
, tmpval
);
890 ValidateGC((DrawablePtr
) pScreen
->PixmapPerDepth
[0], pgcScratch
);
895 (*pgcScratch
->ops
->PolyFillRect
) ((DrawablePtr
) pScreen
->PixmapPerDepth
[0],
896 pgcScratch
, 1, &rect
);
897 FreeScratchGC(pgcScratch
);
902 FreeDefaultStipple(int screenNum
)
904 ScreenPtr pScreen
= screenInfo
.screens
[screenNum
];
906 (*pScreen
->DestroyPixmap
) (pScreen
->PixmapPerDepth
[0]);
910 SetDashes(GCPtr pGC
, unsigned offset
, unsigned ndash
, unsigned char *pdash
)
913 unsigned char *p
, *indash
;
920 /* dash segment must be > 0 */
926 p
= malloc(2 * ndash
* sizeof(unsigned char));
928 p
= malloc(ndash
* sizeof(unsigned char));
932 pGC
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
933 if (offset
!= pGC
->dashOffset
) {
934 pGC
->dashOffset
= offset
;
935 pGC
->stateChanges
|= GCDashOffset
;
936 maskQ
|= GCDashOffset
;
939 if (pGC
->dash
!= DefaultDash
)
941 pGC
->numInDashList
= ndash
;
944 pGC
->numInDashList
+= ndash
;
952 pGC
->stateChanges
|= GCDashList
;
955 if (pGC
->funcs
->ChangeGC
)
956 (*pGC
->funcs
->ChangeGC
) (pGC
, maskQ
);
961 VerifyRectOrder(int nrects
, xRectangle
*prects
, int ordering
)
963 xRectangle
*prectP
, *prectN
;
971 for (i
= 1, prectP
= prects
, prectN
= prects
+ 1;
972 i
< nrects
; i
++, prectP
++, prectN
++)
973 if (prectN
->y
< prectP
->y
)
979 for (i
= 1, prectP
= prects
, prectN
= prects
+ 1;
980 i
< nrects
; i
++, prectP
++, prectN
++)
981 if ((prectN
->y
< prectP
->y
) ||
982 ((prectN
->y
== prectP
->y
) && (prectN
->x
< prectP
->x
)))
988 for (i
= 1, prectP
= prects
, prectN
= prects
+ 1;
989 i
< nrects
; i
++, prectP
++, prectN
++)
990 if ((prectN
->y
!= prectP
->y
&&
991 prectN
->y
< prectP
->y
+ (int) prectP
->height
) ||
992 ((prectN
->y
== prectP
->y
) &&
993 (prectN
->height
!= prectP
->height
||
994 prectN
->x
< prectP
->x
+ (int) prectP
->width
)))
1003 SetClipRects(GCPtr pGC
, int xOrigin
, int yOrigin
, int nrects
,
1004 xRectangle
*prects
, int ordering
)
1007 xRectangle
*prectsNew
;
1009 newct
= VerifyRectOrder(nrects
, prects
, ordering
);
1012 size
= nrects
* sizeof(xRectangle
);
1013 prectsNew
= malloc(size
);
1014 if (!prectsNew
&& size
)
1017 pGC
->serialNumber
|= GC_CHANGE_SERIAL_BIT
;
1018 pGC
->clipOrg
.x
= xOrigin
;
1019 pGC
->stateChanges
|= GCClipXOrigin
;
1021 pGC
->clipOrg
.y
= yOrigin
;
1022 pGC
->stateChanges
|= GCClipYOrigin
;
1025 memmove((char *) prectsNew
, (char *) prects
, size
);
1026 (*pGC
->funcs
->ChangeClip
) (pGC
, newct
, (pointer
) prectsNew
, nrects
);
1027 if (pGC
->funcs
->ChangeGC
)
1028 (*pGC
->funcs
->ChangeGC
) (pGC
,
1029 GCClipXOrigin
| GCClipYOrigin
| GCClipMask
);
1034 sets reasonable defaults
1035 if we can get a pre-allocated one, use it and mark it as used.
1036 if we can't, create one out of whole cloth (The Velveteen GC -- if
1037 you use it often enough it will become real.)
1040 GetScratchGC(unsigned depth
, ScreenPtr pScreen
)
1045 for (i
= 0; i
<= pScreen
->numDepths
; i
++) {
1046 pGC
= pScreen
->GCperDepth
[i
];
1047 if (pGC
&& pGC
->depth
== depth
&& !pGC
->scratch_inuse
) {
1048 pGC
->scratch_inuse
= TRUE
;
1051 pGC
->planemask
= ~0;
1052 pGC
->serialNumber
= 0;
1056 pGC
->lineStyle
= LineSolid
;
1057 pGC
->capStyle
= CapButt
;
1058 pGC
->joinStyle
= JoinMiter
;
1059 pGC
->fillStyle
= FillSolid
;
1060 pGC
->fillRule
= EvenOddRule
;
1061 pGC
->arcMode
= ArcChord
;
1064 pGC
->subWindowMode
= ClipByChildren
;
1065 pGC
->graphicsExposures
= FALSE
;
1068 if (pGC
->clientClipType
!= CT_NONE
)
1069 (*pGC
->funcs
->ChangeClip
) (pGC
, CT_NONE
, NULL
, 0);
1070 pGC
->stateChanges
= GCAllBits
;
1074 /* if we make it this far, need to roll our own */
1075 pGC
= CreateScratchGC(pScreen
, depth
);
1077 pGC
->graphicsExposures
= FALSE
;
1082 if the gc to free is in the table of pre-existing ones,
1083 mark it as available.
1084 if not, free it for real
1087 FreeScratchGC(GCPtr pGC
)
1089 if (pGC
->scratch_inuse
)
1090 pGC
->scratch_inuse
= FALSE
;
1092 FreeGC(pGC
, (GContext
) 0);