gc.c revision 9ace9065
105b261ecSmrg/*********************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrg 2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2705b261ecSmrg 2805b261ecSmrg All Rights Reserved 2905b261ecSmrg 3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3205b261ecSmrgprovided that the above copyright notice appear in all copies and that 3305b261ecSmrgboth that copyright notice and this permission notice appear in 3405b261ecSmrgsupporting documentation, and that the name of Digital not be 3505b261ecSmrgused in advertising or publicity pertaining to distribution of the 3605b261ecSmrgsoftware without specific, written prior permission. 3705b261ecSmrg 3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4405b261ecSmrgSOFTWARE. 4505b261ecSmrg 4605b261ecSmrg******************************************************************/ 4705b261ecSmrg 4805b261ecSmrg 4905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5005b261ecSmrg#include <dix-config.h> 5105b261ecSmrg#endif 5205b261ecSmrg 5305b261ecSmrg#include <X11/X.h> 5405b261ecSmrg#include <X11/Xmd.h> 5505b261ecSmrg#include <X11/Xproto.h> 5605b261ecSmrg#include "misc.h" 5705b261ecSmrg#include "resource.h" 5805b261ecSmrg#include "gcstruct.h" 5905b261ecSmrg#include "pixmapstr.h" 6005b261ecSmrg#include "dixfontstr.h" 6105b261ecSmrg#include "scrnintstr.h" 6205b261ecSmrg#include "region.h" 636747b715Smrg#include "dixstruct.h" 6405b261ecSmrg 654642e01fSmrg#include "privates.h" 6605b261ecSmrg#include "dix.h" 674642e01fSmrg#include "xace.h" 6805b261ecSmrg#include <assert.h> 6905b261ecSmrg 7005b261ecSmrgextern FontPtr defaultFont; 7105b261ecSmrg 7205b261ecSmrgstatic Bool CreateDefaultTile(GCPtr pGC); 7305b261ecSmrg 7405b261ecSmrgstatic unsigned char DefaultDash[2] = {4, 4}; 7505b261ecSmrg 766747b715Smrgvoid 7705b261ecSmrgValidateGC(DrawablePtr pDraw, GC *pGC) 7805b261ecSmrg{ 7905b261ecSmrg (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); 8005b261ecSmrg pGC->stateChanges = 0; 8105b261ecSmrg pGC->serialNumber = pDraw->serialNumber; 8205b261ecSmrg} 8305b261ecSmrg 8405b261ecSmrg 856747b715Smrg/* 866747b715Smrg * ChangeGC/ChangeGCXIDs: 876747b715Smrg * 886747b715Smrg * The client performing the gc change must be passed so that access 896747b715Smrg * checks can be performed on any tiles, stipples, or fonts that are 906747b715Smrg * specified. ddxen can call this too; they should normally pass 916747b715Smrg * NullClient for the client since any access checking should have 9205b261ecSmrg * already been done at a higher level. 9305b261ecSmrg * 946747b715Smrg * If you have any XIDs, you must use ChangeGCXIDs: 9505b261ecSmrg * 9605b261ecSmrg * CARD32 v[2]; 976747b715Smrg * v[0] = FillTiled; 986747b715Smrg * v[1] = pid; 996747b715Smrg * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); 10005b261ecSmrg * 1016747b715Smrg * However, if you need to pass a pointer to a pixmap or font, you must 1026747b715Smrg * use ChangeGC: 10305b261ecSmrg * 10405b261ecSmrg * ChangeGCVal v[2]; 10505b261ecSmrg * v[0].val = FillTiled; 10605b261ecSmrg * v[1].ptr = pPixmap; 1076747b715Smrg * ChangeGC(client, pGC, GCFillStyle|GCTile, v); 10805b261ecSmrg * 1096747b715Smrg * If you have neither XIDs nor pointers, you can use either function, 1106747b715Smrg * but ChangeGC will do less work. 1116747b715Smrg * 1126747b715Smrg * ChangeGCVal v[2]; 1136747b715Smrg * v[0].val = foreground; 1146747b715Smrg * v[1].val = background; 1156747b715Smrg * ChangeGC(client, pGC, GCForeground|GCBackground, v); 11605b261ecSmrg */ 11705b261ecSmrg 11805b261ecSmrg#define NEXTVAL(_type, _var) { \ 11905b261ecSmrg _var = (_type)(pUnion->val); pUnion++; \ 12005b261ecSmrg } 12105b261ecSmrg 12205b261ecSmrg#define NEXT_PTR(_type, _var) { \ 1236747b715Smrg _var = (_type)pUnion->ptr; pUnion++; } 12405b261ecSmrg 1256747b715Smrgint 1266747b715SmrgChangeGC(ClientPtr client, GC *pGC, BITS32 mask, ChangeGCValPtr pUnion) 12705b261ecSmrg{ 12805b261ecSmrg BITS32 index2; 1296747b715Smrg int error = 0; 13005b261ecSmrg PixmapPtr pPixmap; 13105b261ecSmrg BITS32 maskQ; 13205b261ecSmrg 1336747b715Smrg assert(pUnion); 13405b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 13505b261ecSmrg 13605b261ecSmrg maskQ = mask; /* save these for when we walk the GCque */ 13705b261ecSmrg while (mask && !error) 13805b261ecSmrg { 13905b261ecSmrg index2 = (BITS32) lowbit (mask); 14005b261ecSmrg mask &= ~index2; 14105b261ecSmrg pGC->stateChanges |= index2; 14205b261ecSmrg switch (index2) 14305b261ecSmrg { 14405b261ecSmrg case GCFunction: 14505b261ecSmrg { 14605b261ecSmrg CARD8 newalu; 14705b261ecSmrg NEXTVAL(CARD8, newalu); 14805b261ecSmrg if (newalu <= GXset) 14905b261ecSmrg pGC->alu = newalu; 15005b261ecSmrg else 15105b261ecSmrg { 1526747b715Smrg if (client) 1536747b715Smrg client->errorValue = newalu; 15405b261ecSmrg error = BadValue; 15505b261ecSmrg } 15605b261ecSmrg break; 15705b261ecSmrg } 15805b261ecSmrg case GCPlaneMask: 15905b261ecSmrg NEXTVAL(unsigned long, pGC->planemask); 16005b261ecSmrg break; 16105b261ecSmrg case GCForeground: 16205b261ecSmrg NEXTVAL(unsigned long, pGC->fgPixel); 16305b261ecSmrg /* 16405b261ecSmrg * this is for CreateGC 16505b261ecSmrg */ 16605b261ecSmrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 16705b261ecSmrg { 16805b261ecSmrg pGC->tileIsPixel = TRUE; 16905b261ecSmrg pGC->tile.pixel = pGC->fgPixel; 17005b261ecSmrg } 17105b261ecSmrg break; 17205b261ecSmrg case GCBackground: 17305b261ecSmrg NEXTVAL(unsigned long, pGC->bgPixel); 17405b261ecSmrg break; 17505b261ecSmrg case GCLineWidth: /* ??? line width is a CARD16 */ 17605b261ecSmrg NEXTVAL(CARD16, pGC->lineWidth); 17705b261ecSmrg break; 17805b261ecSmrg case GCLineStyle: 17905b261ecSmrg { 18005b261ecSmrg unsigned int newlinestyle; 18105b261ecSmrg NEXTVAL(unsigned int, newlinestyle); 18205b261ecSmrg if (newlinestyle <= LineDoubleDash) 18305b261ecSmrg pGC->lineStyle = newlinestyle; 18405b261ecSmrg else 18505b261ecSmrg { 1866747b715Smrg if (client) 1876747b715Smrg client->errorValue = newlinestyle; 18805b261ecSmrg error = BadValue; 18905b261ecSmrg } 19005b261ecSmrg break; 19105b261ecSmrg } 19205b261ecSmrg case GCCapStyle: 19305b261ecSmrg { 19405b261ecSmrg unsigned int newcapstyle; 19505b261ecSmrg NEXTVAL(unsigned int, newcapstyle); 19605b261ecSmrg if (newcapstyle <= CapProjecting) 19705b261ecSmrg pGC->capStyle = newcapstyle; 19805b261ecSmrg else 19905b261ecSmrg { 2006747b715Smrg if (client) 2016747b715Smrg client->errorValue = newcapstyle; 20205b261ecSmrg error = BadValue; 20305b261ecSmrg } 20405b261ecSmrg break; 20505b261ecSmrg } 20605b261ecSmrg case GCJoinStyle: 20705b261ecSmrg { 20805b261ecSmrg unsigned int newjoinstyle; 20905b261ecSmrg NEXTVAL(unsigned int, newjoinstyle); 21005b261ecSmrg if (newjoinstyle <= JoinBevel) 21105b261ecSmrg pGC->joinStyle = newjoinstyle; 21205b261ecSmrg else 21305b261ecSmrg { 2146747b715Smrg if (client) 2156747b715Smrg client->errorValue = newjoinstyle; 21605b261ecSmrg error = BadValue; 21705b261ecSmrg } 21805b261ecSmrg break; 21905b261ecSmrg } 22005b261ecSmrg case GCFillStyle: 22105b261ecSmrg { 22205b261ecSmrg unsigned int newfillstyle; 22305b261ecSmrg NEXTVAL(unsigned int, newfillstyle); 22405b261ecSmrg if (newfillstyle <= FillOpaqueStippled) 22505b261ecSmrg pGC->fillStyle = newfillstyle; 22605b261ecSmrg else 22705b261ecSmrg { 2286747b715Smrg if (client) 2296747b715Smrg client->errorValue = newfillstyle; 23005b261ecSmrg error = BadValue; 23105b261ecSmrg } 23205b261ecSmrg break; 23305b261ecSmrg } 23405b261ecSmrg case GCFillRule: 23505b261ecSmrg { 23605b261ecSmrg unsigned int newfillrule; 23705b261ecSmrg NEXTVAL(unsigned int, newfillrule); 23805b261ecSmrg if (newfillrule <= WindingRule) 23905b261ecSmrg pGC->fillRule = newfillrule; 24005b261ecSmrg else 24105b261ecSmrg { 2426747b715Smrg if (client) 2436747b715Smrg client->errorValue = newfillrule; 24405b261ecSmrg error = BadValue; 24505b261ecSmrg } 24605b261ecSmrg break; 24705b261ecSmrg } 24805b261ecSmrg case GCTile: 2496747b715Smrg NEXT_PTR(PixmapPtr, pPixmap); 2506747b715Smrg if ((pPixmap->drawable.depth != pGC->depth) || 2516747b715Smrg (pPixmap->drawable.pScreen != pGC->pScreen)) 25205b261ecSmrg { 2536747b715Smrg error = BadMatch; 25405b261ecSmrg } 25505b261ecSmrg else 25605b261ecSmrg { 2576747b715Smrg pPixmap->refcnt++; 2586747b715Smrg if (!pGC->tileIsPixel) 2596747b715Smrg (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); 2606747b715Smrg pGC->tileIsPixel = FALSE; 2616747b715Smrg pGC->tile.pixmap = pPixmap; 26205b261ecSmrg } 26305b261ecSmrg break; 26405b261ecSmrg case GCStipple: 2656747b715Smrg NEXT_PTR(PixmapPtr, pPixmap); 2666747b715Smrg if ((pPixmap->drawable.depth != 1) || 2676747b715Smrg (pPixmap->drawable.pScreen != pGC->pScreen)) 26805b261ecSmrg { 2696747b715Smrg error = BadMatch; 27005b261ecSmrg } 27105b261ecSmrg else 27205b261ecSmrg { 2736747b715Smrg pPixmap->refcnt++; 2746747b715Smrg if (pGC->stipple) 2756747b715Smrg (* pGC->pScreen->DestroyPixmap)(pGC->stipple); 2766747b715Smrg pGC->stipple = pPixmap; 27705b261ecSmrg } 27805b261ecSmrg break; 27905b261ecSmrg case GCTileStipXOrigin: 28005b261ecSmrg NEXTVAL(INT16, pGC->patOrg.x); 28105b261ecSmrg break; 28205b261ecSmrg case GCTileStipYOrigin: 28305b261ecSmrg NEXTVAL(INT16, pGC->patOrg.y); 28405b261ecSmrg break; 28505b261ecSmrg case GCFont: 28605b261ecSmrg { 28705b261ecSmrg FontPtr pFont; 2886747b715Smrg NEXT_PTR(FontPtr, pFont); 2896747b715Smrg pFont->refcnt++; 2906747b715Smrg if (pGC->font) 2916747b715Smrg CloseFont(pGC->font, (Font)0); 2926747b715Smrg pGC->font = pFont; 29305b261ecSmrg break; 29405b261ecSmrg } 29505b261ecSmrg case GCSubwindowMode: 29605b261ecSmrg { 29705b261ecSmrg unsigned int newclipmode; 29805b261ecSmrg NEXTVAL(unsigned int, newclipmode); 29905b261ecSmrg if (newclipmode <= IncludeInferiors) 30005b261ecSmrg pGC->subWindowMode = newclipmode; 30105b261ecSmrg else 30205b261ecSmrg { 3036747b715Smrg if (client) 3046747b715Smrg client->errorValue = newclipmode; 30505b261ecSmrg error = BadValue; 30605b261ecSmrg } 30705b261ecSmrg break; 30805b261ecSmrg } 30905b261ecSmrg case GCGraphicsExposures: 31005b261ecSmrg { 31105b261ecSmrg unsigned int newge; 31205b261ecSmrg NEXTVAL(unsigned int, newge); 31305b261ecSmrg if (newge <= xTrue) 31405b261ecSmrg pGC->graphicsExposures = newge; 31505b261ecSmrg else 31605b261ecSmrg { 3176747b715Smrg if (client) 3186747b715Smrg client->errorValue = newge; 31905b261ecSmrg error = BadValue; 32005b261ecSmrg } 32105b261ecSmrg break; 32205b261ecSmrg } 32305b261ecSmrg case GCClipXOrigin: 32405b261ecSmrg NEXTVAL(INT16, pGC->clipOrg.x); 32505b261ecSmrg break; 32605b261ecSmrg case GCClipYOrigin: 32705b261ecSmrg NEXTVAL(INT16, pGC->clipOrg.y); 32805b261ecSmrg break; 32905b261ecSmrg case GCClipMask: 3306747b715Smrg NEXT_PTR(PixmapPtr, pPixmap); 33105b261ecSmrg if (pPixmap) 33205b261ecSmrg { 33305b261ecSmrg if ((pPixmap->drawable.depth != 1) || 33405b261ecSmrg (pPixmap->drawable.pScreen != pGC->pScreen)) 33505b261ecSmrg { 33605b261ecSmrg error = BadMatch; 3376747b715Smrg break; 33805b261ecSmrg } 3396747b715Smrg pPixmap->refcnt++; 34005b261ecSmrg } 3416747b715Smrg (*pGC->funcs->ChangeClip)(pGC, pPixmap ? CT_PIXMAP : CT_NONE, 3426747b715Smrg (pointer)pPixmap, 0); 34305b261ecSmrg break; 34405b261ecSmrg case GCDashOffset: 34505b261ecSmrg NEXTVAL(INT16, pGC->dashOffset); 34605b261ecSmrg break; 34705b261ecSmrg case GCDashList: 34805b261ecSmrg { 34905b261ecSmrg CARD8 newdash; 35005b261ecSmrg NEXTVAL(CARD8, newdash); 35105b261ecSmrg if (newdash == 4) 35205b261ecSmrg { 35305b261ecSmrg if (pGC->dash != DefaultDash) 35405b261ecSmrg { 3556747b715Smrg free(pGC->dash); 35605b261ecSmrg pGC->numInDashList = 2; 35705b261ecSmrg pGC->dash = DefaultDash; 35805b261ecSmrg } 35905b261ecSmrg } 36005b261ecSmrg else if (newdash != 0) 36105b261ecSmrg { 36205b261ecSmrg unsigned char *dash; 36305b261ecSmrg 3646747b715Smrg dash = malloc(2 * sizeof(unsigned char)); 36505b261ecSmrg if (dash) 36605b261ecSmrg { 36705b261ecSmrg if (pGC->dash != DefaultDash) 3686747b715Smrg free(pGC->dash); 36905b261ecSmrg pGC->numInDashList = 2; 37005b261ecSmrg pGC->dash = dash; 37105b261ecSmrg dash[0] = newdash; 37205b261ecSmrg dash[1] = newdash; 37305b261ecSmrg } 37405b261ecSmrg else 37505b261ecSmrg error = BadAlloc; 37605b261ecSmrg } 37705b261ecSmrg else 37805b261ecSmrg { 3796747b715Smrg if (client) 3806747b715Smrg client->errorValue = newdash; 38105b261ecSmrg error = BadValue; 38205b261ecSmrg } 38305b261ecSmrg break; 38405b261ecSmrg } 38505b261ecSmrg case GCArcMode: 38605b261ecSmrg { 38705b261ecSmrg unsigned int newarcmode; 38805b261ecSmrg NEXTVAL(unsigned int, newarcmode); 38905b261ecSmrg if (newarcmode <= ArcPieSlice) 39005b261ecSmrg pGC->arcMode = newarcmode; 39105b261ecSmrg else 39205b261ecSmrg { 3936747b715Smrg if (client) 3946747b715Smrg client->errorValue = newarcmode; 39505b261ecSmrg error = BadValue; 39605b261ecSmrg } 39705b261ecSmrg break; 39805b261ecSmrg } 39905b261ecSmrg default: 4006747b715Smrg if (client) 4016747b715Smrg client->errorValue = maskQ; 40205b261ecSmrg error = BadValue; 40305b261ecSmrg break; 40405b261ecSmrg } 40505b261ecSmrg } /* end while mask && !error */ 40605b261ecSmrg 40705b261ecSmrg if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) 40805b261ecSmrg { 40905b261ecSmrg if (!CreateDefaultTile (pGC)) 41005b261ecSmrg { 41105b261ecSmrg pGC->fillStyle = FillSolid; 41205b261ecSmrg error = BadAlloc; 41305b261ecSmrg } 41405b261ecSmrg } 41505b261ecSmrg (*pGC->funcs->ChangeGC)(pGC, maskQ); 41605b261ecSmrg return error; 41705b261ecSmrg} 41805b261ecSmrg 41905b261ecSmrg#undef NEXTVAL 42005b261ecSmrg#undef NEXT_PTR 42105b261ecSmrg 4226747b715Smrgstatic const struct { 4236747b715Smrg BITS32 mask; 4246747b715Smrg RESTYPE type; 4256747b715Smrg Mask access_mode; 4266747b715Smrg} xidfields[] = { 4276747b715Smrg { GCTile, RT_PIXMAP, DixReadAccess }, 4286747b715Smrg { GCStipple, RT_PIXMAP, DixReadAccess }, 4296747b715Smrg { GCFont, RT_FONT, DixUseAccess }, 4306747b715Smrg { GCClipMask, RT_PIXMAP, DixReadAccess }, 4316747b715Smrg}; 43205b261ecSmrg 4336747b715Smrgint 4346747b715SmrgChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32) 43505b261ecSmrg{ 4366747b715Smrg ChangeGCVal vals[GCLastBit + 1]; 4376747b715Smrg int i; 4386747b715Smrg if (mask & ~GCAllBits) 4396747b715Smrg { 4406747b715Smrg client->errorValue = mask; 4416747b715Smrg return BadValue; 4426747b715Smrg } 4436747b715Smrg for (i = Ones(mask); i--; ) 4446747b715Smrg vals[i].val = pC32[i]; 4456747b715Smrg for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) 4466747b715Smrg { 4476747b715Smrg int offset, rc; 4486747b715Smrg if (!(mask & xidfields[i].mask)) 4496747b715Smrg continue; 4506747b715Smrg offset = Ones(mask & (xidfields[i].mask - 1)); 4516747b715Smrg if (xidfields[i].mask == GCClipMask && vals[offset].val == None) 4526747b715Smrg { 4536747b715Smrg vals[offset].ptr = NullPixmap; 4546747b715Smrg continue; 4556747b715Smrg } 4566747b715Smrg rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, 4576747b715Smrg xidfields[i].type, client, xidfields[i].access_mode); 4586747b715Smrg if (rc != Success) 4596747b715Smrg { 4606747b715Smrg client->errorValue = vals[offset].val; 4616747b715Smrg return rc; 4626747b715Smrg } 4636747b715Smrg } 4646747b715Smrg return ChangeGC(client, pGC, mask, vals); 46505b261ecSmrg} 46605b261ecSmrg 46705b261ecSmrg/* CreateGC(pDrawable, mask, pval, pStatus) 46805b261ecSmrg creates a default GC for the given drawable, using mask to fill 46905b261ecSmrg in any non-default values. 47005b261ecSmrg Returns a pointer to the new GC on success, NULL otherwise. 47105b261ecSmrg returns status of non-default fields in pStatus 47205b261ecSmrgBUG: 47305b261ecSmrg should check for failure to create default tile 47405b261ecSmrg 47505b261ecSmrg*/ 4766747b715SmrgGCPtr 4774642e01fSmrgCreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, 4784642e01fSmrg XID gcid, ClientPtr client) 47905b261ecSmrg{ 48005b261ecSmrg GCPtr pGC; 48105b261ecSmrg 4826747b715Smrg pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC); 48305b261ecSmrg if (!pGC) 48405b261ecSmrg { 48505b261ecSmrg *pStatus = BadAlloc; 48605b261ecSmrg return (GCPtr)NULL; 48705b261ecSmrg } 48805b261ecSmrg 48905b261ecSmrg pGC->pScreen = pDrawable->pScreen; 49005b261ecSmrg pGC->depth = pDrawable->depth; 49105b261ecSmrg pGC->alu = GXcopy; /* dst <- src */ 49205b261ecSmrg pGC->planemask = ~0; 49305b261ecSmrg pGC->serialNumber = GC_CHANGE_SERIAL_BIT; 49405b261ecSmrg pGC->funcs = 0; 49505b261ecSmrg pGC->fgPixel = 0; 49605b261ecSmrg pGC->bgPixel = 1; 49705b261ecSmrg pGC->lineWidth = 0; 49805b261ecSmrg pGC->lineStyle = LineSolid; 49905b261ecSmrg pGC->capStyle = CapButt; 50005b261ecSmrg pGC->joinStyle = JoinMiter; 50105b261ecSmrg pGC->fillStyle = FillSolid; 50205b261ecSmrg pGC->fillRule = EvenOddRule; 50305b261ecSmrg pGC->arcMode = ArcPieSlice; 5046747b715Smrg pGC->tile.pixel = 0; 5056747b715Smrg pGC->tile.pixmap = NullPixmap; 50605b261ecSmrg if (mask & GCForeground) 50705b261ecSmrg { 50805b261ecSmrg /* 50905b261ecSmrg * magic special case -- ChangeGC checks for this condition 51005b261ecSmrg * and snags the Foreground value to create a pseudo default-tile 51105b261ecSmrg */ 51205b261ecSmrg pGC->tileIsPixel = FALSE; 51305b261ecSmrg } 51405b261ecSmrg else 51505b261ecSmrg { 51605b261ecSmrg pGC->tileIsPixel = TRUE; 51705b261ecSmrg } 51805b261ecSmrg 51905b261ecSmrg pGC->patOrg.x = 0; 52005b261ecSmrg pGC->patOrg.y = 0; 52105b261ecSmrg pGC->subWindowMode = ClipByChildren; 52205b261ecSmrg pGC->graphicsExposures = TRUE; 52305b261ecSmrg pGC->clipOrg.x = 0; 52405b261ecSmrg pGC->clipOrg.y = 0; 52505b261ecSmrg pGC->clientClipType = CT_NONE; 52605b261ecSmrg pGC->clientClip = (pointer)NULL; 52705b261ecSmrg pGC->numInDashList = 2; 52805b261ecSmrg pGC->dash = DefaultDash; 52905b261ecSmrg pGC->dashOffset = 0; 53005b261ecSmrg 53105b261ecSmrg /* use the default font and stipple */ 53205b261ecSmrg pGC->font = defaultFont; 53305b261ecSmrg defaultFont->refcnt++; 53405b261ecSmrg pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; 53505b261ecSmrg pGC->stipple->refcnt++; 53605b261ecSmrg 5376747b715Smrg /* this is not a scratch GC */ 5386747b715Smrg pGC->scratch_inuse = FALSE; 5396747b715Smrg 5404642e01fSmrg /* security creation/labeling check */ 5414642e01fSmrg *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, 5424642e01fSmrg RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); 5434642e01fSmrg if (*pStatus != Success) 5444642e01fSmrg goto out; 5454642e01fSmrg 5466747b715Smrg pGC->stateChanges = GCAllBits; 54705b261ecSmrg if (!(*pGC->pScreen->CreateGC)(pGC)) 54805b261ecSmrg *pStatus = BadAlloc; 54905b261ecSmrg else if (mask) 5506747b715Smrg *pStatus = ChangeGCXIDs(client, pGC, mask, pval); 55105b261ecSmrg else 55205b261ecSmrg *pStatus = Success; 5534642e01fSmrg 5544642e01fSmrgout: 55505b261ecSmrg if (*pStatus != Success) 55605b261ecSmrg { 55705b261ecSmrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 55805b261ecSmrg pGC->tileIsPixel = TRUE; /* undo special case */ 55905b261ecSmrg FreeGC(pGC, (XID)0); 56005b261ecSmrg pGC = (GCPtr)NULL; 56105b261ecSmrg } 56205b261ecSmrg 5636747b715Smrg return pGC; 56405b261ecSmrg} 56505b261ecSmrg 56605b261ecSmrgstatic Bool 56705b261ecSmrgCreateDefaultTile (GCPtr pGC) 56805b261ecSmrg{ 5696747b715Smrg ChangeGCVal tmpval[3]; 57005b261ecSmrg PixmapPtr pTile; 57105b261ecSmrg GCPtr pgcScratch; 57205b261ecSmrg xRectangle rect; 57305b261ecSmrg CARD16 w, h; 57405b261ecSmrg 57505b261ecSmrg w = 1; 57605b261ecSmrg h = 1; 57705b261ecSmrg (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); 57805b261ecSmrg pTile = (PixmapPtr) 57905b261ecSmrg (*pGC->pScreen->CreatePixmap)(pGC->pScreen, 5804642e01fSmrg w, h, pGC->depth, 0); 58105b261ecSmrg pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); 58205b261ecSmrg if (!pTile || !pgcScratch) 58305b261ecSmrg { 58405b261ecSmrg if (pTile) 58505b261ecSmrg (*pTile->drawable.pScreen->DestroyPixmap)(pTile); 58605b261ecSmrg if (pgcScratch) 58705b261ecSmrg FreeScratchGC(pgcScratch); 58805b261ecSmrg return FALSE; 58905b261ecSmrg } 5906747b715Smrg tmpval[0].val = GXcopy; 5916747b715Smrg tmpval[1].val = pGC->tile.pixel; 5926747b715Smrg tmpval[2].val = FillSolid; 5936747b715Smrg (void)ChangeGC(NullClient, pgcScratch, GCFunction | GCForeground | GCFillStyle, tmpval); 59405b261ecSmrg ValidateGC((DrawablePtr)pTile, pgcScratch); 59505b261ecSmrg rect.x = 0; 59605b261ecSmrg rect.y = 0; 59705b261ecSmrg rect.width = w; 59805b261ecSmrg rect.height = h; 59905b261ecSmrg (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); 60005b261ecSmrg /* Always remember to free the scratch graphics context after use. */ 60105b261ecSmrg FreeScratchGC(pgcScratch); 60205b261ecSmrg 60305b261ecSmrg pGC->tileIsPixel = FALSE; 60405b261ecSmrg pGC->tile.pixmap = pTile; 60505b261ecSmrg return TRUE; 60605b261ecSmrg} 60705b261ecSmrg 6086747b715Smrgint 60905b261ecSmrgCopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) 61005b261ecSmrg{ 61105b261ecSmrg BITS32 index2; 61205b261ecSmrg BITS32 maskQ; 61305b261ecSmrg int error = 0; 61405b261ecSmrg 61505b261ecSmrg if (pgcSrc == pgcDst) 61605b261ecSmrg return Success; 61705b261ecSmrg pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; 61805b261ecSmrg pgcDst->stateChanges |= mask; 61905b261ecSmrg maskQ = mask; 62005b261ecSmrg while (mask) 62105b261ecSmrg { 62205b261ecSmrg index2 = (BITS32) lowbit (mask); 62305b261ecSmrg mask &= ~index2; 62405b261ecSmrg switch (index2) 62505b261ecSmrg { 62605b261ecSmrg case GCFunction: 62705b261ecSmrg pgcDst->alu = pgcSrc->alu; 62805b261ecSmrg break; 62905b261ecSmrg case GCPlaneMask: 63005b261ecSmrg pgcDst->planemask = pgcSrc->planemask; 63105b261ecSmrg break; 63205b261ecSmrg case GCForeground: 63305b261ecSmrg pgcDst->fgPixel = pgcSrc->fgPixel; 63405b261ecSmrg break; 63505b261ecSmrg case GCBackground: 63605b261ecSmrg pgcDst->bgPixel = pgcSrc->bgPixel; 63705b261ecSmrg break; 63805b261ecSmrg case GCLineWidth: 63905b261ecSmrg pgcDst->lineWidth = pgcSrc->lineWidth; 64005b261ecSmrg break; 64105b261ecSmrg case GCLineStyle: 64205b261ecSmrg pgcDst->lineStyle = pgcSrc->lineStyle; 64305b261ecSmrg break; 64405b261ecSmrg case GCCapStyle: 64505b261ecSmrg pgcDst->capStyle = pgcSrc->capStyle; 64605b261ecSmrg break; 64705b261ecSmrg case GCJoinStyle: 64805b261ecSmrg pgcDst->joinStyle = pgcSrc->joinStyle; 64905b261ecSmrg break; 65005b261ecSmrg case GCFillStyle: 65105b261ecSmrg pgcDst->fillStyle = pgcSrc->fillStyle; 65205b261ecSmrg break; 65305b261ecSmrg case GCFillRule: 65405b261ecSmrg pgcDst->fillRule = pgcSrc->fillRule; 65505b261ecSmrg break; 65605b261ecSmrg case GCTile: 65705b261ecSmrg { 65805b261ecSmrg if (EqualPixUnion(pgcDst->tileIsPixel, 65905b261ecSmrg pgcDst->tile, 66005b261ecSmrg pgcSrc->tileIsPixel, 66105b261ecSmrg pgcSrc->tile)) 66205b261ecSmrg { 66305b261ecSmrg break; 66405b261ecSmrg } 66505b261ecSmrg if (!pgcDst->tileIsPixel) 66605b261ecSmrg (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); 66705b261ecSmrg pgcDst->tileIsPixel = pgcSrc->tileIsPixel; 66805b261ecSmrg pgcDst->tile = pgcSrc->tile; 66905b261ecSmrg if (!pgcDst->tileIsPixel) 67005b261ecSmrg pgcDst->tile.pixmap->refcnt++; 67105b261ecSmrg break; 67205b261ecSmrg } 67305b261ecSmrg case GCStipple: 67405b261ecSmrg { 67505b261ecSmrg if (pgcDst->stipple == pgcSrc->stipple) 67605b261ecSmrg break; 67705b261ecSmrg if (pgcDst->stipple) 67805b261ecSmrg (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); 67905b261ecSmrg pgcDst->stipple = pgcSrc->stipple; 68005b261ecSmrg if (pgcDst->stipple) 68105b261ecSmrg pgcDst->stipple->refcnt ++; 68205b261ecSmrg break; 68305b261ecSmrg } 68405b261ecSmrg case GCTileStipXOrigin: 68505b261ecSmrg pgcDst->patOrg.x = pgcSrc->patOrg.x; 68605b261ecSmrg break; 68705b261ecSmrg case GCTileStipYOrigin: 68805b261ecSmrg pgcDst->patOrg.y = pgcSrc->patOrg.y; 68905b261ecSmrg break; 69005b261ecSmrg case GCFont: 69105b261ecSmrg if (pgcDst->font == pgcSrc->font) 69205b261ecSmrg break; 69305b261ecSmrg if (pgcDst->font) 69405b261ecSmrg CloseFont(pgcDst->font, (Font)0); 69505b261ecSmrg if ((pgcDst->font = pgcSrc->font) != NullFont) 69605b261ecSmrg (pgcDst->font)->refcnt++; 69705b261ecSmrg break; 69805b261ecSmrg case GCSubwindowMode: 69905b261ecSmrg pgcDst->subWindowMode = pgcSrc->subWindowMode; 70005b261ecSmrg break; 70105b261ecSmrg case GCGraphicsExposures: 70205b261ecSmrg pgcDst->graphicsExposures = pgcSrc->graphicsExposures; 70305b261ecSmrg break; 70405b261ecSmrg case GCClipXOrigin: 70505b261ecSmrg pgcDst->clipOrg.x = pgcSrc->clipOrg.x; 70605b261ecSmrg break; 70705b261ecSmrg case GCClipYOrigin: 70805b261ecSmrg pgcDst->clipOrg.y = pgcSrc->clipOrg.y; 70905b261ecSmrg break; 71005b261ecSmrg case GCClipMask: 71105b261ecSmrg (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); 71205b261ecSmrg break; 71305b261ecSmrg case GCDashOffset: 71405b261ecSmrg pgcDst->dashOffset = pgcSrc->dashOffset; 71505b261ecSmrg break; 71605b261ecSmrg case GCDashList: 71705b261ecSmrg if (pgcSrc->dash == DefaultDash) 71805b261ecSmrg { 71905b261ecSmrg if (pgcDst->dash != DefaultDash) 72005b261ecSmrg { 7216747b715Smrg free(pgcDst->dash); 72205b261ecSmrg pgcDst->numInDashList = pgcSrc->numInDashList; 72305b261ecSmrg pgcDst->dash = pgcSrc->dash; 72405b261ecSmrg } 72505b261ecSmrg } 72605b261ecSmrg else 72705b261ecSmrg { 72805b261ecSmrg unsigned char *dash; 72905b261ecSmrg unsigned int i; 73005b261ecSmrg 7316747b715Smrg dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); 73205b261ecSmrg if (dash) 73305b261ecSmrg { 73405b261ecSmrg if (pgcDst->dash != DefaultDash) 7356747b715Smrg free(pgcDst->dash); 73605b261ecSmrg pgcDst->numInDashList = pgcSrc->numInDashList; 73705b261ecSmrg pgcDst->dash = dash; 73805b261ecSmrg for (i=0; i<pgcSrc->numInDashList; i++) 73905b261ecSmrg dash[i] = pgcSrc->dash[i]; 74005b261ecSmrg } 74105b261ecSmrg else 74205b261ecSmrg error = BadAlloc; 74305b261ecSmrg } 74405b261ecSmrg break; 74505b261ecSmrg case GCArcMode: 74605b261ecSmrg pgcDst->arcMode = pgcSrc->arcMode; 74705b261ecSmrg break; 74805b261ecSmrg default: 7496747b715Smrg FatalError ("CopyGC: Unhandled mask!\n"); 75005b261ecSmrg } 75105b261ecSmrg } 75205b261ecSmrg if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) 75305b261ecSmrg { 75405b261ecSmrg if (!CreateDefaultTile (pgcDst)) 75505b261ecSmrg { 75605b261ecSmrg pgcDst->fillStyle = FillSolid; 75705b261ecSmrg error = BadAlloc; 75805b261ecSmrg } 75905b261ecSmrg } 76005b261ecSmrg (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); 76105b261ecSmrg return error; 76205b261ecSmrg} 76305b261ecSmrg 76405b261ecSmrg/** 76505b261ecSmrg * does the diX part of freeing the characteristics in the GC. 76605b261ecSmrg * 76705b261ecSmrg * \param value must conform to DeleteType 76805b261ecSmrg */ 7696747b715Smrgint 77005b261ecSmrgFreeGC(pointer value, XID gid) 77105b261ecSmrg{ 77205b261ecSmrg GCPtr pGC = (GCPtr)value; 77305b261ecSmrg 77405b261ecSmrg CloseFont(pGC->font, (Font)0); 77505b261ecSmrg (* pGC->funcs->DestroyClip)(pGC); 77605b261ecSmrg 77705b261ecSmrg if (!pGC->tileIsPixel) 77805b261ecSmrg (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); 77905b261ecSmrg if (pGC->stipple) 78005b261ecSmrg (* pGC->pScreen->DestroyPixmap)(pGC->stipple); 78105b261ecSmrg 78205b261ecSmrg (*pGC->funcs->DestroyGC) (pGC); 78305b261ecSmrg if (pGC->dash != DefaultDash) 7846747b715Smrg free(pGC->dash); 7856747b715Smrg dixFreeObjectWithPrivates(pGC, PRIVATE_GC); 7866747b715Smrg return Success; 78705b261ecSmrg} 78805b261ecSmrg 78905b261ecSmrg/* CreateScratchGC(pScreen, depth) 79005b261ecSmrg like CreateGC, but doesn't do the default tile or stipple, 79105b261ecSmrgsince we can't create them without already having a GC. any code 79205b261ecSmrgusing the tile or stipple has to set them explicitly anyway, 79305b261ecSmrgsince the state of the scratch gc is unknown. This is OK 79405b261ecSmrgbecause ChangeGC() has to be able to deal with NULL tiles and 79505b261ecSmrgstipples anyway (in case the CreateGC() call has provided a 79605b261ecSmrgvalue for them -- we can't set the default tile until the 79705b261ecSmrgclient-supplied attributes are installed, since the fgPixel 79805b261ecSmrgis what fills the default tile. (maybe this comment should 79905b261ecSmrggo with CreateGC() or ChangeGC().) 80005b261ecSmrg*/ 80105b261ecSmrg 8029ace9065Smrgstatic GCPtr 80305b261ecSmrgCreateScratchGC(ScreenPtr pScreen, unsigned depth) 80405b261ecSmrg{ 80505b261ecSmrg GCPtr pGC; 80605b261ecSmrg 8076747b715Smrg pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC); 80805b261ecSmrg if (!pGC) 80905b261ecSmrg return (GCPtr)NULL; 81005b261ecSmrg 81105b261ecSmrg pGC->pScreen = pScreen; 81205b261ecSmrg pGC->depth = depth; 81305b261ecSmrg pGC->alu = GXcopy; /* dst <- src */ 81405b261ecSmrg pGC->planemask = ~0; 81505b261ecSmrg pGC->serialNumber = 0; 81605b261ecSmrg pGC->fgPixel = 0; 81705b261ecSmrg pGC->bgPixel = 1; 81805b261ecSmrg pGC->lineWidth = 0; 81905b261ecSmrg pGC->lineStyle = LineSolid; 82005b261ecSmrg pGC->capStyle = CapButt; 82105b261ecSmrg pGC->joinStyle = JoinMiter; 82205b261ecSmrg pGC->fillStyle = FillSolid; 82305b261ecSmrg pGC->fillRule = EvenOddRule; 82405b261ecSmrg pGC->arcMode = ArcPieSlice; 82505b261ecSmrg pGC->font = defaultFont; 82605b261ecSmrg if ( pGC->font) /* necessary, because open of default font could fail */ 82705b261ecSmrg pGC->font->refcnt++; 82805b261ecSmrg pGC->tileIsPixel = TRUE; 82905b261ecSmrg pGC->tile.pixel = 0; 8306747b715Smrg pGC->tile.pixmap = NullPixmap; 83105b261ecSmrg pGC->stipple = NullPixmap; 83205b261ecSmrg pGC->patOrg.x = 0; 83305b261ecSmrg pGC->patOrg.y = 0; 83405b261ecSmrg pGC->subWindowMode = ClipByChildren; 83505b261ecSmrg pGC->graphicsExposures = TRUE; 83605b261ecSmrg pGC->clipOrg.x = 0; 83705b261ecSmrg pGC->clipOrg.y = 0; 83805b261ecSmrg pGC->clientClipType = CT_NONE; 83905b261ecSmrg pGC->dashOffset = 0; 84005b261ecSmrg pGC->numInDashList = 2; 84105b261ecSmrg pGC->dash = DefaultDash; 84205b261ecSmrg 8436747b715Smrg /* scratch GCs in the GCperDepth pool start off unused */ 8446747b715Smrg pGC->scratch_inuse = FALSE; 8456747b715Smrg 8466747b715Smrg pGC->stateChanges = GCAllBits; 84705b261ecSmrg if (!(*pScreen->CreateGC)(pGC)) 84805b261ecSmrg { 84905b261ecSmrg FreeGC(pGC, (XID)0); 85005b261ecSmrg pGC = (GCPtr)NULL; 85105b261ecSmrg } 85205b261ecSmrg return pGC; 85305b261ecSmrg} 85405b261ecSmrg 85505b261ecSmrgvoid 85605b261ecSmrgFreeGCperDepth(int screenNum) 85705b261ecSmrg{ 85805b261ecSmrg int i; 85905b261ecSmrg ScreenPtr pScreen; 86005b261ecSmrg GCPtr *ppGC; 86105b261ecSmrg 86205b261ecSmrg pScreen = screenInfo.screens[screenNum]; 86305b261ecSmrg ppGC = pScreen->GCperDepth; 86405b261ecSmrg 86505b261ecSmrg for (i = 0; i <= pScreen->numDepths; i++) 8666747b715Smrg { 86705b261ecSmrg (void)FreeGC(ppGC[i], (XID)0); 8686747b715Smrg ppGC[i] = NULL; 8696747b715Smrg } 87005b261ecSmrg} 87105b261ecSmrg 87205b261ecSmrg 87305b261ecSmrgBool 87405b261ecSmrgCreateGCperDepth(int screenNum) 87505b261ecSmrg{ 87605b261ecSmrg int i; 87705b261ecSmrg ScreenPtr pScreen; 87805b261ecSmrg DepthPtr pDepth; 87905b261ecSmrg GCPtr *ppGC; 88005b261ecSmrg 88105b261ecSmrg pScreen = screenInfo.screens[screenNum]; 88205b261ecSmrg ppGC = pScreen->GCperDepth; 88305b261ecSmrg /* do depth 1 separately because it's not included in list */ 88405b261ecSmrg if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) 88505b261ecSmrg return FALSE; 88605b261ecSmrg ppGC[0]->graphicsExposures = FALSE; 88705b261ecSmrg /* Make sure we don't overflow GCperDepth[] */ 88805b261ecSmrg if( pScreen->numDepths > MAXFORMATS ) 88905b261ecSmrg return FALSE; 89005b261ecSmrg 89105b261ecSmrg pDepth = pScreen->allowedDepths; 89205b261ecSmrg for (i=0; i<pScreen->numDepths; i++, pDepth++) 89305b261ecSmrg { 89405b261ecSmrg if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) 89505b261ecSmrg { 89605b261ecSmrg for (; i >= 0; i--) 89705b261ecSmrg (void)FreeGC(ppGC[i], (XID)0); 89805b261ecSmrg return FALSE; 89905b261ecSmrg } 90005b261ecSmrg ppGC[i+1]->graphicsExposures = FALSE; 90105b261ecSmrg } 90205b261ecSmrg return TRUE; 90305b261ecSmrg} 90405b261ecSmrg 90505b261ecSmrgBool 90605b261ecSmrgCreateDefaultStipple(int screenNum) 90705b261ecSmrg{ 90805b261ecSmrg ScreenPtr pScreen; 9096747b715Smrg ChangeGCVal tmpval[3]; 91005b261ecSmrg xRectangle rect; 91105b261ecSmrg CARD16 w, h; 91205b261ecSmrg GCPtr pgcScratch; 91305b261ecSmrg 91405b261ecSmrg pScreen = screenInfo.screens[screenNum]; 91505b261ecSmrg 91605b261ecSmrg w = 16; 91705b261ecSmrg h = 16; 91805b261ecSmrg (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); 91905b261ecSmrg if (!(pScreen->PixmapPerDepth[0] = 9204642e01fSmrg (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) 92105b261ecSmrg return FALSE; 92205b261ecSmrg /* fill stipple with 1 */ 9236747b715Smrg tmpval[0].val = GXcopy; 9246747b715Smrg tmpval[1].val = 1; 9256747b715Smrg tmpval[2].val = FillSolid; 92605b261ecSmrg pgcScratch = GetScratchGC(1, pScreen); 92705b261ecSmrg if (!pgcScratch) 92805b261ecSmrg { 92905b261ecSmrg (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); 93005b261ecSmrg return FALSE; 93105b261ecSmrg } 9326747b715Smrg (void)ChangeGC(NullClient, pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); 93305b261ecSmrg ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); 93405b261ecSmrg rect.x = 0; 93505b261ecSmrg rect.y = 0; 93605b261ecSmrg rect.width = w; 93705b261ecSmrg rect.height = h; 93805b261ecSmrg (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], 93905b261ecSmrg pgcScratch, 1, &rect); 94005b261ecSmrg FreeScratchGC(pgcScratch); 94105b261ecSmrg return TRUE; 94205b261ecSmrg} 94305b261ecSmrg 94405b261ecSmrgvoid 94505b261ecSmrgFreeDefaultStipple(int screenNum) 94605b261ecSmrg{ 94705b261ecSmrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 94805b261ecSmrg (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); 94905b261ecSmrg} 95005b261ecSmrg 9514642e01fSmrgint 95205b261ecSmrgSetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) 95305b261ecSmrg{ 95405b261ecSmrg long i; 95505b261ecSmrg unsigned char *p, *indash; 95605b261ecSmrg BITS32 maskQ = 0; 95705b261ecSmrg 95805b261ecSmrg i = ndash; 95905b261ecSmrg p = pdash; 96005b261ecSmrg while (i--) 96105b261ecSmrg { 96205b261ecSmrg if (!*p++) 96305b261ecSmrg { 96405b261ecSmrg /* dash segment must be > 0 */ 96505b261ecSmrg return BadValue; 96605b261ecSmrg } 96705b261ecSmrg } 96805b261ecSmrg 96905b261ecSmrg if (ndash & 1) 9706747b715Smrg p = malloc(2 * ndash * sizeof(unsigned char)); 97105b261ecSmrg else 9726747b715Smrg p = malloc(ndash * sizeof(unsigned char)); 97305b261ecSmrg if (!p) 97405b261ecSmrg return BadAlloc; 97505b261ecSmrg 97605b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 97705b261ecSmrg if (offset != pGC->dashOffset) 97805b261ecSmrg { 97905b261ecSmrg pGC->dashOffset = offset; 98005b261ecSmrg pGC->stateChanges |= GCDashOffset; 98105b261ecSmrg maskQ |= GCDashOffset; 98205b261ecSmrg } 98305b261ecSmrg 98405b261ecSmrg if (pGC->dash != DefaultDash) 9856747b715Smrg free(pGC->dash); 98605b261ecSmrg pGC->numInDashList = ndash; 98705b261ecSmrg pGC->dash = p; 98805b261ecSmrg if (ndash & 1) 98905b261ecSmrg { 99005b261ecSmrg pGC->numInDashList += ndash; 99105b261ecSmrg indash = pdash; 99205b261ecSmrg i = ndash; 99305b261ecSmrg while (i--) 99405b261ecSmrg *p++ = *indash++; 99505b261ecSmrg } 99605b261ecSmrg while(ndash--) 99705b261ecSmrg *p++ = *pdash++; 99805b261ecSmrg pGC->stateChanges |= GCDashList; 99905b261ecSmrg maskQ |= GCDashList; 100005b261ecSmrg 100105b261ecSmrg if (pGC->funcs->ChangeGC) 100205b261ecSmrg (*pGC->funcs->ChangeGC) (pGC, maskQ); 100305b261ecSmrg return Success; 100405b261ecSmrg} 100505b261ecSmrg 10066747b715Smrgint 100705b261ecSmrgVerifyRectOrder(int nrects, xRectangle *prects, int ordering) 100805b261ecSmrg{ 100905b261ecSmrg xRectangle *prectP, *prectN; 101005b261ecSmrg int i; 101105b261ecSmrg 101205b261ecSmrg switch(ordering) 101305b261ecSmrg { 101405b261ecSmrg case Unsorted: 101505b261ecSmrg return CT_UNSORTED; 101605b261ecSmrg case YSorted: 101705b261ecSmrg if(nrects > 1) 101805b261ecSmrg { 101905b261ecSmrg for(i = 1, prectP = prects, prectN = prects + 1; 102005b261ecSmrg i < nrects; 102105b261ecSmrg i++, prectP++, prectN++) 102205b261ecSmrg if(prectN->y < prectP->y) 102305b261ecSmrg return -1; 102405b261ecSmrg } 102505b261ecSmrg return CT_YSORTED; 102605b261ecSmrg case YXSorted: 102705b261ecSmrg if(nrects > 1) 102805b261ecSmrg { 102905b261ecSmrg for(i = 1, prectP = prects, prectN = prects + 1; 103005b261ecSmrg i < nrects; 103105b261ecSmrg i++, prectP++, prectN++) 103205b261ecSmrg if((prectN->y < prectP->y) || 103305b261ecSmrg ( (prectN->y == prectP->y) && 103405b261ecSmrg (prectN->x < prectP->x) ) ) 103505b261ecSmrg return -1; 103605b261ecSmrg } 103705b261ecSmrg return CT_YXSORTED; 103805b261ecSmrg case YXBanded: 103905b261ecSmrg if(nrects > 1) 104005b261ecSmrg { 104105b261ecSmrg for(i = 1, prectP = prects, prectN = prects + 1; 104205b261ecSmrg i < nrects; 104305b261ecSmrg i++, prectP++, prectN++) 104405b261ecSmrg if((prectN->y != prectP->y && 104505b261ecSmrg prectN->y < prectP->y + (int) prectP->height) || 104605b261ecSmrg ((prectN->y == prectP->y) && 104705b261ecSmrg (prectN->height != prectP->height || 104805b261ecSmrg prectN->x < prectP->x + (int) prectP->width))) 104905b261ecSmrg return -1; 105005b261ecSmrg } 105105b261ecSmrg return CT_YXBANDED; 105205b261ecSmrg } 105305b261ecSmrg return -1; 105405b261ecSmrg} 105505b261ecSmrg 10564642e01fSmrgint 105705b261ecSmrgSetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, 105805b261ecSmrg xRectangle *prects, int ordering) 105905b261ecSmrg{ 106005b261ecSmrg int newct, size; 106105b261ecSmrg xRectangle *prectsNew; 106205b261ecSmrg 106305b261ecSmrg newct = VerifyRectOrder(nrects, prects, ordering); 106405b261ecSmrg if (newct < 0) 10656747b715Smrg return BadMatch; 106605b261ecSmrg size = nrects * sizeof(xRectangle); 10676747b715Smrg prectsNew = malloc(size); 106805b261ecSmrg if (!prectsNew && size) 106905b261ecSmrg return BadAlloc; 107005b261ecSmrg 107105b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 107205b261ecSmrg pGC->clipOrg.x = xOrigin; 107305b261ecSmrg pGC->stateChanges |= GCClipXOrigin; 107405b261ecSmrg 107505b261ecSmrg pGC->clipOrg.y = yOrigin; 107605b261ecSmrg pGC->stateChanges |= GCClipYOrigin; 107705b261ecSmrg 107805b261ecSmrg if (size) 107905b261ecSmrg memmove((char *)prectsNew, (char *)prects, size); 108005b261ecSmrg (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); 108105b261ecSmrg if (pGC->funcs->ChangeGC) 108205b261ecSmrg (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); 108305b261ecSmrg return Success; 108405b261ecSmrg} 108505b261ecSmrg 108605b261ecSmrg 108705b261ecSmrg/* 108805b261ecSmrg sets reasonable defaults 108905b261ecSmrg if we can get a pre-allocated one, use it and mark it as used. 109005b261ecSmrg if we can't, create one out of whole cloth (The Velveteen GC -- if 109105b261ecSmrg you use it often enough it will become real.) 109205b261ecSmrg*/ 10936747b715SmrgGCPtr 109405b261ecSmrgGetScratchGC(unsigned depth, ScreenPtr pScreen) 109505b261ecSmrg{ 109605b261ecSmrg int i; 109705b261ecSmrg GCPtr pGC; 109805b261ecSmrg 109905b261ecSmrg for (i=0; i<=pScreen->numDepths; i++) 11006747b715Smrg { 11016747b715Smrg pGC = pScreen->GCperDepth[i]; 11026747b715Smrg if (pGC && pGC->depth == depth && !pGC->scratch_inuse) 110305b261ecSmrg { 11046747b715Smrg pGC->scratch_inuse = TRUE; 110505b261ecSmrg 110605b261ecSmrg pGC->alu = GXcopy; 110705b261ecSmrg pGC->planemask = ~0; 110805b261ecSmrg pGC->serialNumber = 0; 110905b261ecSmrg pGC->fgPixel = 0; 111005b261ecSmrg pGC->bgPixel = 1; 111105b261ecSmrg pGC->lineWidth = 0; 111205b261ecSmrg pGC->lineStyle = LineSolid; 111305b261ecSmrg pGC->capStyle = CapButt; 111405b261ecSmrg pGC->joinStyle = JoinMiter; 111505b261ecSmrg pGC->fillStyle = FillSolid; 111605b261ecSmrg pGC->fillRule = EvenOddRule; 111705b261ecSmrg pGC->arcMode = ArcChord; 111805b261ecSmrg pGC->patOrg.x = 0; 111905b261ecSmrg pGC->patOrg.y = 0; 112005b261ecSmrg pGC->subWindowMode = ClipByChildren; 112105b261ecSmrg pGC->graphicsExposures = FALSE; 112205b261ecSmrg pGC->clipOrg.x = 0; 112305b261ecSmrg pGC->clipOrg.y = 0; 112405b261ecSmrg if (pGC->clientClipType != CT_NONE) 112505b261ecSmrg (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); 11266747b715Smrg pGC->stateChanges = GCAllBits; 112705b261ecSmrg return pGC; 112805b261ecSmrg } 11296747b715Smrg } 113005b261ecSmrg /* if we make it this far, need to roll our own */ 113105b261ecSmrg pGC = CreateScratchGC(pScreen, depth); 113205b261ecSmrg if (pGC) 113305b261ecSmrg pGC->graphicsExposures = FALSE; 113405b261ecSmrg return pGC; 113505b261ecSmrg} 113605b261ecSmrg 113705b261ecSmrg/* 113805b261ecSmrg if the gc to free is in the table of pre-existing ones, 113905b261ecSmrgmark it as available. 114005b261ecSmrg if not, free it for real 114105b261ecSmrg*/ 11426747b715Smrgvoid 114305b261ecSmrgFreeScratchGC(GCPtr pGC) 114405b261ecSmrg{ 11456747b715Smrg if (pGC->scratch_inuse) 11466747b715Smrg pGC->scratch_inuse = FALSE; 11476747b715Smrg else 11486747b715Smrg FreeGC(pGC, (GContext)0); 114905b261ecSmrg} 1150