gc.c revision 4642e01f
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" 6305b261ecSmrg 644642e01fSmrg#include "privates.h" 6505b261ecSmrg#include "dix.h" 664642e01fSmrg#include "xace.h" 6705b261ecSmrg#include <assert.h> 6805b261ecSmrg 6905b261ecSmrgextern XID clientErrorValue; 7005b261ecSmrgextern FontPtr defaultFont; 7105b261ecSmrg 7205b261ecSmrgstatic Bool CreateDefaultTile(GCPtr pGC); 7305b261ecSmrg 7405b261ecSmrgstatic unsigned char DefaultDash[2] = {4, 4}; 7505b261ecSmrg 7605b261ecSmrg_X_EXPORT void 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 8505b261ecSmrg/* dixChangeGC(client, pGC, mask, pC32, pUnion) 8605b261ecSmrg * 8705b261ecSmrg * This function was created as part of the Security extension 8805b261ecSmrg * implementation. The client performing the gc change must be passed so 8905b261ecSmrg * that access checks can be performed on any tiles, stipples, or fonts 9005b261ecSmrg * that are specified. ddxen can call this too; they should normally 9105b261ecSmrg * pass NullClient for the client since any access checking should have 9205b261ecSmrg * already been done at a higher level. 9305b261ecSmrg * 9405b261ecSmrg * Since we had to create a new function anyway, we decided to change the 9505b261ecSmrg * way the list of gc values is passed to eliminate the compiler warnings 9605b261ecSmrg * caused by the DoChangeGC interface. You can pass the values via pC32 9705b261ecSmrg * or pUnion, but not both; one of them must be NULL. If you don't need 9805b261ecSmrg * to pass any pointers, you can use either one: 9905b261ecSmrg * 10005b261ecSmrg * example calling dixChangeGC using pC32 parameter 10105b261ecSmrg * 10205b261ecSmrg * CARD32 v[2]; 10305b261ecSmrg * v[0] = foreground; 10405b261ecSmrg * v[1] = background; 10505b261ecSmrg * dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL); 10605b261ecSmrg * 10705b261ecSmrg * example calling dixChangeGC using pUnion parameter; 10805b261ecSmrg * same effect as above 10905b261ecSmrg * 11005b261ecSmrg * ChangeGCVal v[2]; 11105b261ecSmrg * v[0].val = foreground; 11205b261ecSmrg * v[1].val = background; 11305b261ecSmrg * dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v); 11405b261ecSmrg * 11505b261ecSmrg * However, if you need to pass a pointer to a pixmap or font, you MUST 11605b261ecSmrg * use the pUnion parameter. 11705b261ecSmrg * 11805b261ecSmrg * example calling dixChangeGC passing pointers in the value list 11905b261ecSmrg * v[1].ptr is a pointer to a pixmap 12005b261ecSmrg * 12105b261ecSmrg * ChangeGCVal v[2]; 12205b261ecSmrg * v[0].val = FillTiled; 12305b261ecSmrg * v[1].ptr = pPixmap; 12405b261ecSmrg * dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v); 12505b261ecSmrg * 12605b261ecSmrg * Note: we could have gotten by with just the pUnion parameter, but on 12705b261ecSmrg * 64 bit machines that would have forced us to copy the value list that 12805b261ecSmrg * comes in the ChangeGC request. 12905b261ecSmrg * 13005b261ecSmrg * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this 13105b261ecSmrg * is far too many changes to consider at this time, so we've only 13205b261ecSmrg * changed the ones that caused compiler warnings. New code should use 13305b261ecSmrg * dixChangeGC. 13405b261ecSmrg * 13505b261ecSmrg * dpw 13605b261ecSmrg */ 13705b261ecSmrg 13805b261ecSmrg#define NEXTVAL(_type, _var) { \ 13905b261ecSmrg if (pC32) _var = (_type)*pC32++; \ 14005b261ecSmrg else { \ 14105b261ecSmrg _var = (_type)(pUnion->val); pUnion++; \ 14205b261ecSmrg } \ 14305b261ecSmrg } 14405b261ecSmrg 14505b261ecSmrg#define NEXT_PTR(_type, _var) { \ 14605b261ecSmrg assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; } 14705b261ecSmrg 14805b261ecSmrg_X_EXPORT int 14905b261ecSmrgdixChangeGC(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion) 15005b261ecSmrg{ 15105b261ecSmrg BITS32 index2; 1524642e01fSmrg int rc, error = 0; 15305b261ecSmrg PixmapPtr pPixmap; 15405b261ecSmrg BITS32 maskQ; 15505b261ecSmrg 15605b261ecSmrg assert( (pC32 && !pUnion) || (!pC32 && pUnion) ); 15705b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 15805b261ecSmrg 15905b261ecSmrg maskQ = mask; /* save these for when we walk the GCque */ 16005b261ecSmrg while (mask && !error) 16105b261ecSmrg { 16205b261ecSmrg index2 = (BITS32) lowbit (mask); 16305b261ecSmrg mask &= ~index2; 16405b261ecSmrg pGC->stateChanges |= index2; 16505b261ecSmrg switch (index2) 16605b261ecSmrg { 16705b261ecSmrg case GCFunction: 16805b261ecSmrg { 16905b261ecSmrg CARD8 newalu; 17005b261ecSmrg NEXTVAL(CARD8, newalu); 17105b261ecSmrg if (newalu <= GXset) 17205b261ecSmrg pGC->alu = newalu; 17305b261ecSmrg else 17405b261ecSmrg { 17505b261ecSmrg clientErrorValue = newalu; 17605b261ecSmrg error = BadValue; 17705b261ecSmrg } 17805b261ecSmrg break; 17905b261ecSmrg } 18005b261ecSmrg case GCPlaneMask: 18105b261ecSmrg NEXTVAL(unsigned long, pGC->planemask); 18205b261ecSmrg break; 18305b261ecSmrg case GCForeground: 18405b261ecSmrg NEXTVAL(unsigned long, pGC->fgPixel); 18505b261ecSmrg /* 18605b261ecSmrg * this is for CreateGC 18705b261ecSmrg */ 18805b261ecSmrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 18905b261ecSmrg { 19005b261ecSmrg pGC->tileIsPixel = TRUE; 19105b261ecSmrg pGC->tile.pixel = pGC->fgPixel; 19205b261ecSmrg } 19305b261ecSmrg break; 19405b261ecSmrg case GCBackground: 19505b261ecSmrg NEXTVAL(unsigned long, pGC->bgPixel); 19605b261ecSmrg break; 19705b261ecSmrg case GCLineWidth: /* ??? line width is a CARD16 */ 19805b261ecSmrg NEXTVAL(CARD16, pGC->lineWidth); 19905b261ecSmrg break; 20005b261ecSmrg case GCLineStyle: 20105b261ecSmrg { 20205b261ecSmrg unsigned int newlinestyle; 20305b261ecSmrg NEXTVAL(unsigned int, newlinestyle); 20405b261ecSmrg if (newlinestyle <= LineDoubleDash) 20505b261ecSmrg pGC->lineStyle = newlinestyle; 20605b261ecSmrg else 20705b261ecSmrg { 20805b261ecSmrg clientErrorValue = newlinestyle; 20905b261ecSmrg error = BadValue; 21005b261ecSmrg } 21105b261ecSmrg break; 21205b261ecSmrg } 21305b261ecSmrg case GCCapStyle: 21405b261ecSmrg { 21505b261ecSmrg unsigned int newcapstyle; 21605b261ecSmrg NEXTVAL(unsigned int, newcapstyle); 21705b261ecSmrg if (newcapstyle <= CapProjecting) 21805b261ecSmrg pGC->capStyle = newcapstyle; 21905b261ecSmrg else 22005b261ecSmrg { 22105b261ecSmrg clientErrorValue = newcapstyle; 22205b261ecSmrg error = BadValue; 22305b261ecSmrg } 22405b261ecSmrg break; 22505b261ecSmrg } 22605b261ecSmrg case GCJoinStyle: 22705b261ecSmrg { 22805b261ecSmrg unsigned int newjoinstyle; 22905b261ecSmrg NEXTVAL(unsigned int, newjoinstyle); 23005b261ecSmrg if (newjoinstyle <= JoinBevel) 23105b261ecSmrg pGC->joinStyle = newjoinstyle; 23205b261ecSmrg else 23305b261ecSmrg { 23405b261ecSmrg clientErrorValue = newjoinstyle; 23505b261ecSmrg error = BadValue; 23605b261ecSmrg } 23705b261ecSmrg break; 23805b261ecSmrg } 23905b261ecSmrg case GCFillStyle: 24005b261ecSmrg { 24105b261ecSmrg unsigned int newfillstyle; 24205b261ecSmrg NEXTVAL(unsigned int, newfillstyle); 24305b261ecSmrg if (newfillstyle <= FillOpaqueStippled) 24405b261ecSmrg pGC->fillStyle = newfillstyle; 24505b261ecSmrg else 24605b261ecSmrg { 24705b261ecSmrg clientErrorValue = newfillstyle; 24805b261ecSmrg error = BadValue; 24905b261ecSmrg } 25005b261ecSmrg break; 25105b261ecSmrg } 25205b261ecSmrg case GCFillRule: 25305b261ecSmrg { 25405b261ecSmrg unsigned int newfillrule; 25505b261ecSmrg NEXTVAL(unsigned int, newfillrule); 25605b261ecSmrg if (newfillrule <= WindingRule) 25705b261ecSmrg pGC->fillRule = newfillrule; 25805b261ecSmrg else 25905b261ecSmrg { 26005b261ecSmrg clientErrorValue = newfillrule; 26105b261ecSmrg error = BadValue; 26205b261ecSmrg } 26305b261ecSmrg break; 26405b261ecSmrg } 26505b261ecSmrg case GCTile: 26605b261ecSmrg { 26705b261ecSmrg XID newpix = 0; 26805b261ecSmrg if (pUnion) 26905b261ecSmrg { 27005b261ecSmrg NEXT_PTR(PixmapPtr, pPixmap); 2714642e01fSmrg rc = Success; 27205b261ecSmrg } 27305b261ecSmrg else 27405b261ecSmrg { 27505b261ecSmrg NEXTVAL(XID, newpix); 2764642e01fSmrg rc = dixLookupResource((pointer *)&pPixmap, newpix, 2774642e01fSmrg RT_PIXMAP, client, DixReadAccess); 27805b261ecSmrg } 2794642e01fSmrg if (rc == Success) 28005b261ecSmrg { 28105b261ecSmrg if ((pPixmap->drawable.depth != pGC->depth) || 28205b261ecSmrg (pPixmap->drawable.pScreen != pGC->pScreen)) 28305b261ecSmrg { 28405b261ecSmrg error = BadMatch; 28505b261ecSmrg } 28605b261ecSmrg else 28705b261ecSmrg { 28805b261ecSmrg pPixmap->refcnt++; 28905b261ecSmrg if (!pGC->tileIsPixel) 29005b261ecSmrg (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); 29105b261ecSmrg pGC->tileIsPixel = FALSE; 29205b261ecSmrg pGC->tile.pixmap = pPixmap; 29305b261ecSmrg } 29405b261ecSmrg } 29505b261ecSmrg else 29605b261ecSmrg { 29705b261ecSmrg clientErrorValue = newpix; 2984642e01fSmrg error = (rc == BadValue) ? BadPixmap : rc; 29905b261ecSmrg } 30005b261ecSmrg break; 30105b261ecSmrg } 30205b261ecSmrg case GCStipple: 30305b261ecSmrg { 30405b261ecSmrg XID newstipple = 0; 30505b261ecSmrg if (pUnion) 30605b261ecSmrg { 30705b261ecSmrg NEXT_PTR(PixmapPtr, pPixmap); 3084642e01fSmrg rc = Success; 30905b261ecSmrg } 31005b261ecSmrg else 31105b261ecSmrg { 31205b261ecSmrg NEXTVAL(XID, newstipple) 3134642e01fSmrg rc = dixLookupResource((pointer *)&pPixmap, newstipple, 3144642e01fSmrg RT_PIXMAP, client, DixReadAccess); 31505b261ecSmrg } 3164642e01fSmrg if (rc == Success) 31705b261ecSmrg { 31805b261ecSmrg if ((pPixmap->drawable.depth != 1) || 31905b261ecSmrg (pPixmap->drawable.pScreen != pGC->pScreen)) 32005b261ecSmrg { 32105b261ecSmrg error = BadMatch; 32205b261ecSmrg } 32305b261ecSmrg else 32405b261ecSmrg { 32505b261ecSmrg pPixmap->refcnt++; 32605b261ecSmrg if (pGC->stipple) 32705b261ecSmrg (* pGC->pScreen->DestroyPixmap)(pGC->stipple); 32805b261ecSmrg pGC->stipple = pPixmap; 32905b261ecSmrg } 33005b261ecSmrg } 33105b261ecSmrg else 33205b261ecSmrg { 33305b261ecSmrg clientErrorValue = newstipple; 3344642e01fSmrg error = (rc == BadValue) ? BadPixmap : rc; 33505b261ecSmrg } 33605b261ecSmrg break; 33705b261ecSmrg } 33805b261ecSmrg case GCTileStipXOrigin: 33905b261ecSmrg NEXTVAL(INT16, pGC->patOrg.x); 34005b261ecSmrg break; 34105b261ecSmrg case GCTileStipYOrigin: 34205b261ecSmrg NEXTVAL(INT16, pGC->patOrg.y); 34305b261ecSmrg break; 34405b261ecSmrg case GCFont: 34505b261ecSmrg { 34605b261ecSmrg FontPtr pFont; 34705b261ecSmrg XID newfont = 0; 34805b261ecSmrg if (pUnion) 34905b261ecSmrg { 35005b261ecSmrg NEXT_PTR(FontPtr, pFont); 3514642e01fSmrg rc = Success; 35205b261ecSmrg } 35305b261ecSmrg else 35405b261ecSmrg { 35505b261ecSmrg NEXTVAL(XID, newfont) 3564642e01fSmrg rc = dixLookupResource((pointer *)&pFont, newfont, 3574642e01fSmrg RT_FONT, client, DixUseAccess); 35805b261ecSmrg } 3594642e01fSmrg if (rc == Success) 36005b261ecSmrg { 36105b261ecSmrg pFont->refcnt++; 36205b261ecSmrg if (pGC->font) 36305b261ecSmrg CloseFont(pGC->font, (Font)0); 36405b261ecSmrg pGC->font = pFont; 36505b261ecSmrg } 36605b261ecSmrg else 36705b261ecSmrg { 36805b261ecSmrg clientErrorValue = newfont; 3694642e01fSmrg error = (rc == BadValue) ? BadFont : rc; 37005b261ecSmrg } 37105b261ecSmrg break; 37205b261ecSmrg } 37305b261ecSmrg case GCSubwindowMode: 37405b261ecSmrg { 37505b261ecSmrg unsigned int newclipmode; 37605b261ecSmrg NEXTVAL(unsigned int, newclipmode); 37705b261ecSmrg if (newclipmode <= IncludeInferiors) 37805b261ecSmrg pGC->subWindowMode = newclipmode; 37905b261ecSmrg else 38005b261ecSmrg { 38105b261ecSmrg clientErrorValue = newclipmode; 38205b261ecSmrg error = BadValue; 38305b261ecSmrg } 38405b261ecSmrg break; 38505b261ecSmrg } 38605b261ecSmrg case GCGraphicsExposures: 38705b261ecSmrg { 38805b261ecSmrg unsigned int newge; 38905b261ecSmrg NEXTVAL(unsigned int, newge); 39005b261ecSmrg if (newge <= xTrue) 39105b261ecSmrg pGC->graphicsExposures = newge; 39205b261ecSmrg else 39305b261ecSmrg { 39405b261ecSmrg clientErrorValue = newge; 39505b261ecSmrg error = BadValue; 39605b261ecSmrg } 39705b261ecSmrg break; 39805b261ecSmrg } 39905b261ecSmrg case GCClipXOrigin: 40005b261ecSmrg NEXTVAL(INT16, pGC->clipOrg.x); 40105b261ecSmrg break; 40205b261ecSmrg case GCClipYOrigin: 40305b261ecSmrg NEXTVAL(INT16, pGC->clipOrg.y); 40405b261ecSmrg break; 40505b261ecSmrg case GCClipMask: 40605b261ecSmrg { 40705b261ecSmrg Pixmap pid = 0; 40805b261ecSmrg int clipType = 0; 40905b261ecSmrg 41005b261ecSmrg if (pUnion) 41105b261ecSmrg { 41205b261ecSmrg NEXT_PTR(PixmapPtr, pPixmap); 41305b261ecSmrg } 41405b261ecSmrg else 41505b261ecSmrg { 41605b261ecSmrg NEXTVAL(Pixmap, pid) 41705b261ecSmrg if (pid == None) 41805b261ecSmrg { 41905b261ecSmrg clipType = CT_NONE; 42005b261ecSmrg pPixmap = NullPixmap; 42105b261ecSmrg } 4224642e01fSmrg else { 4234642e01fSmrg rc = dixLookupResource((pointer *)&pPixmap, pid, 4244642e01fSmrg RT_PIXMAP, client, 4254642e01fSmrg DixReadAccess); 4264642e01fSmrg if (rc != Success) { 4274642e01fSmrg clientErrorValue = pid; 4284642e01fSmrg error = (rc == BadValue) ? BadPixmap : rc; 4294642e01fSmrg } 4304642e01fSmrg } 43105b261ecSmrg } 43205b261ecSmrg 43305b261ecSmrg if (pPixmap) 43405b261ecSmrg { 43505b261ecSmrg if ((pPixmap->drawable.depth != 1) || 43605b261ecSmrg (pPixmap->drawable.pScreen != pGC->pScreen)) 43705b261ecSmrg { 43805b261ecSmrg error = BadMatch; 43905b261ecSmrg } 44005b261ecSmrg else 44105b261ecSmrg { 44205b261ecSmrg clipType = CT_PIXMAP; 44305b261ecSmrg pPixmap->refcnt++; 44405b261ecSmrg } 44505b261ecSmrg } 44605b261ecSmrg if(error == Success) 44705b261ecSmrg { 44805b261ecSmrg (*pGC->funcs->ChangeClip)(pGC, clipType, 44905b261ecSmrg (pointer)pPixmap, 0); 45005b261ecSmrg } 45105b261ecSmrg break; 45205b261ecSmrg } 45305b261ecSmrg case GCDashOffset: 45405b261ecSmrg NEXTVAL(INT16, pGC->dashOffset); 45505b261ecSmrg break; 45605b261ecSmrg case GCDashList: 45705b261ecSmrg { 45805b261ecSmrg CARD8 newdash; 45905b261ecSmrg NEXTVAL(CARD8, newdash); 46005b261ecSmrg if (newdash == 4) 46105b261ecSmrg { 46205b261ecSmrg if (pGC->dash != DefaultDash) 46305b261ecSmrg { 46405b261ecSmrg xfree(pGC->dash); 46505b261ecSmrg pGC->numInDashList = 2; 46605b261ecSmrg pGC->dash = DefaultDash; 46705b261ecSmrg } 46805b261ecSmrg } 46905b261ecSmrg else if (newdash != 0) 47005b261ecSmrg { 47105b261ecSmrg unsigned char *dash; 47205b261ecSmrg 47305b261ecSmrg dash = (unsigned char *)xalloc(2 * sizeof(unsigned char)); 47405b261ecSmrg if (dash) 47505b261ecSmrg { 47605b261ecSmrg if (pGC->dash != DefaultDash) 47705b261ecSmrg xfree(pGC->dash); 47805b261ecSmrg pGC->numInDashList = 2; 47905b261ecSmrg pGC->dash = dash; 48005b261ecSmrg dash[0] = newdash; 48105b261ecSmrg dash[1] = newdash; 48205b261ecSmrg } 48305b261ecSmrg else 48405b261ecSmrg error = BadAlloc; 48505b261ecSmrg } 48605b261ecSmrg else 48705b261ecSmrg { 48805b261ecSmrg clientErrorValue = newdash; 48905b261ecSmrg error = BadValue; 49005b261ecSmrg } 49105b261ecSmrg break; 49205b261ecSmrg } 49305b261ecSmrg case GCArcMode: 49405b261ecSmrg { 49505b261ecSmrg unsigned int newarcmode; 49605b261ecSmrg NEXTVAL(unsigned int, newarcmode); 49705b261ecSmrg if (newarcmode <= ArcPieSlice) 49805b261ecSmrg pGC->arcMode = newarcmode; 49905b261ecSmrg else 50005b261ecSmrg { 50105b261ecSmrg clientErrorValue = newarcmode; 50205b261ecSmrg error = BadValue; 50305b261ecSmrg } 50405b261ecSmrg break; 50505b261ecSmrg } 50605b261ecSmrg default: 50705b261ecSmrg clientErrorValue = maskQ; 50805b261ecSmrg error = BadValue; 50905b261ecSmrg break; 51005b261ecSmrg } 51105b261ecSmrg } /* end while mask && !error */ 51205b261ecSmrg 51305b261ecSmrg if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) 51405b261ecSmrg { 51505b261ecSmrg if (!CreateDefaultTile (pGC)) 51605b261ecSmrg { 51705b261ecSmrg pGC->fillStyle = FillSolid; 51805b261ecSmrg error = BadAlloc; 51905b261ecSmrg } 52005b261ecSmrg } 52105b261ecSmrg (*pGC->funcs->ChangeGC)(pGC, maskQ); 52205b261ecSmrg return error; 52305b261ecSmrg} 52405b261ecSmrg 52505b261ecSmrg#undef NEXTVAL 52605b261ecSmrg#undef NEXT_PTR 52705b261ecSmrg 52805b261ecSmrg/* Publically defined entry to ChangeGC. Just calls dixChangeGC and tells 52905b261ecSmrg * it that all of the entries are constants or IDs */ 53005b261ecSmrg_X_EXPORT int 53105b261ecSmrgChangeGC(GC *pGC, BITS32 mask, XID *pval) 53205b261ecSmrg{ 53305b261ecSmrg return (dixChangeGC(NullClient, pGC, mask, pval, NULL)); 53405b261ecSmrg} 53505b261ecSmrg 53605b261ecSmrg/* DoChangeGC(pGC, mask, pval, fPointer) 53705b261ecSmrg mask is a set of bits indicating which values to change. 53805b261ecSmrg pval contains an appropriate value for each mask. 53905b261ecSmrg fPointer is true if the values for tiles, stipples, fonts or clipmasks 54005b261ecSmrg are pointers instead of IDs. Note: if you are passing pointers you 54105b261ecSmrg MUST declare the array of values as type pointer! Other data types 54205b261ecSmrg may not be large enough to hold pointers on some machines. Yes, 54305b261ecSmrg this means you have to cast to (XID *) when you pass the array to 54405b261ecSmrg DoChangeGC. Similarly, if you are not passing pointers (fPointer = 0) you 54505b261ecSmrg MUST declare the array as type XID (not unsigned long!), or again the wrong 54605b261ecSmrg size data type may be used. To avoid this cruftiness, use dixChangeGC 54705b261ecSmrg above. 54805b261ecSmrg 54905b261ecSmrg if there is an error, the value is marked as changed 55005b261ecSmrg anyway, which is probably wrong, but infrequent. 55105b261ecSmrg 55205b261ecSmrgNOTE: 55305b261ecSmrg all values sent over the protocol for ChangeGC requests are 55405b261ecSmrg32 bits long 55505b261ecSmrg*/ 55605b261ecSmrg_X_EXPORT int 55705b261ecSmrgDoChangeGC(GC *pGC, BITS32 mask, XID *pval, int fPointer) 55805b261ecSmrg{ 55905b261ecSmrg if (fPointer) 56005b261ecSmrg /* XXX might be a problem on 64 bit big-endian servers */ 56105b261ecSmrg return dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval); 56205b261ecSmrg else 56305b261ecSmrg return dixChangeGC(NullClient, pGC, mask, pval, NULL); 56405b261ecSmrg} 56505b261ecSmrg 56605b261ecSmrg 56705b261ecSmrg/* CreateGC(pDrawable, mask, pval, pStatus) 56805b261ecSmrg creates a default GC for the given drawable, using mask to fill 56905b261ecSmrg in any non-default values. 57005b261ecSmrg Returns a pointer to the new GC on success, NULL otherwise. 57105b261ecSmrg returns status of non-default fields in pStatus 57205b261ecSmrgBUG: 57305b261ecSmrg should check for failure to create default tile 57405b261ecSmrg 57505b261ecSmrg*/ 57605b261ecSmrg_X_EXPORT GCPtr 5774642e01fSmrgCreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, 5784642e01fSmrg XID gcid, ClientPtr client) 57905b261ecSmrg{ 58005b261ecSmrg GCPtr pGC; 58105b261ecSmrg 5824642e01fSmrg pGC = (GCPtr)xalloc(sizeof(GC)); 58305b261ecSmrg if (!pGC) 58405b261ecSmrg { 58505b261ecSmrg *pStatus = BadAlloc; 58605b261ecSmrg return (GCPtr)NULL; 58705b261ecSmrg } 58805b261ecSmrg 58905b261ecSmrg pGC->pScreen = pDrawable->pScreen; 59005b261ecSmrg pGC->depth = pDrawable->depth; 59105b261ecSmrg pGC->alu = GXcopy; /* dst <- src */ 59205b261ecSmrg pGC->planemask = ~0; 59305b261ecSmrg pGC->serialNumber = GC_CHANGE_SERIAL_BIT; 59405b261ecSmrg pGC->funcs = 0; 5954642e01fSmrg pGC->devPrivates = NULL; 59605b261ecSmrg pGC->fgPixel = 0; 59705b261ecSmrg pGC->bgPixel = 1; 59805b261ecSmrg pGC->lineWidth = 0; 59905b261ecSmrg pGC->lineStyle = LineSolid; 60005b261ecSmrg pGC->capStyle = CapButt; 60105b261ecSmrg pGC->joinStyle = JoinMiter; 60205b261ecSmrg pGC->fillStyle = FillSolid; 60305b261ecSmrg pGC->fillRule = EvenOddRule; 60405b261ecSmrg pGC->arcMode = ArcPieSlice; 60505b261ecSmrg if (mask & GCForeground) 60605b261ecSmrg { 60705b261ecSmrg /* 60805b261ecSmrg * magic special case -- ChangeGC checks for this condition 60905b261ecSmrg * and snags the Foreground value to create a pseudo default-tile 61005b261ecSmrg */ 61105b261ecSmrg pGC->tileIsPixel = FALSE; 61205b261ecSmrg pGC->tile.pixmap = NullPixmap; 61305b261ecSmrg } 61405b261ecSmrg else 61505b261ecSmrg { 61605b261ecSmrg pGC->tileIsPixel = TRUE; 61705b261ecSmrg pGC->tile.pixel = 0; 61805b261ecSmrg } 61905b261ecSmrg 62005b261ecSmrg pGC->patOrg.x = 0; 62105b261ecSmrg pGC->patOrg.y = 0; 62205b261ecSmrg pGC->subWindowMode = ClipByChildren; 62305b261ecSmrg pGC->graphicsExposures = TRUE; 62405b261ecSmrg pGC->clipOrg.x = 0; 62505b261ecSmrg pGC->clipOrg.y = 0; 62605b261ecSmrg pGC->clientClipType = CT_NONE; 62705b261ecSmrg pGC->clientClip = (pointer)NULL; 62805b261ecSmrg pGC->numInDashList = 2; 62905b261ecSmrg pGC->dash = DefaultDash; 63005b261ecSmrg pGC->dashOffset = 0; 63105b261ecSmrg pGC->lastWinOrg.x = 0; 63205b261ecSmrg pGC->lastWinOrg.y = 0; 63305b261ecSmrg 63405b261ecSmrg /* use the default font and stipple */ 63505b261ecSmrg pGC->font = defaultFont; 63605b261ecSmrg defaultFont->refcnt++; 63705b261ecSmrg pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; 63805b261ecSmrg pGC->stipple->refcnt++; 63905b261ecSmrg 6404642e01fSmrg /* security creation/labeling check */ 6414642e01fSmrg *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, 6424642e01fSmrg RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); 6434642e01fSmrg if (*pStatus != Success) 6444642e01fSmrg goto out; 6454642e01fSmrg 64605b261ecSmrg pGC->stateChanges = (1 << (GCLastBit+1)) - 1; 64705b261ecSmrg if (!(*pGC->pScreen->CreateGC)(pGC)) 64805b261ecSmrg *pStatus = BadAlloc; 64905b261ecSmrg else if (mask) 65005b261ecSmrg *pStatus = ChangeGC(pGC, mask, pval); 65105b261ecSmrg else 65205b261ecSmrg *pStatus = Success; 6534642e01fSmrg 6544642e01fSmrgout: 65505b261ecSmrg if (*pStatus != Success) 65605b261ecSmrg { 65705b261ecSmrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 65805b261ecSmrg pGC->tileIsPixel = TRUE; /* undo special case */ 65905b261ecSmrg FreeGC(pGC, (XID)0); 66005b261ecSmrg pGC = (GCPtr)NULL; 66105b261ecSmrg } 66205b261ecSmrg 66305b261ecSmrg return (pGC); 66405b261ecSmrg} 66505b261ecSmrg 66605b261ecSmrgstatic Bool 66705b261ecSmrgCreateDefaultTile (GCPtr pGC) 66805b261ecSmrg{ 66905b261ecSmrg XID tmpval[3]; 67005b261ecSmrg PixmapPtr pTile; 67105b261ecSmrg GCPtr pgcScratch; 67205b261ecSmrg xRectangle rect; 67305b261ecSmrg CARD16 w, h; 67405b261ecSmrg 67505b261ecSmrg w = 1; 67605b261ecSmrg h = 1; 67705b261ecSmrg (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); 67805b261ecSmrg pTile = (PixmapPtr) 67905b261ecSmrg (*pGC->pScreen->CreatePixmap)(pGC->pScreen, 6804642e01fSmrg w, h, pGC->depth, 0); 68105b261ecSmrg pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); 68205b261ecSmrg if (!pTile || !pgcScratch) 68305b261ecSmrg { 68405b261ecSmrg if (pTile) 68505b261ecSmrg (*pTile->drawable.pScreen->DestroyPixmap)(pTile); 68605b261ecSmrg if (pgcScratch) 68705b261ecSmrg FreeScratchGC(pgcScratch); 68805b261ecSmrg return FALSE; 68905b261ecSmrg } 69005b261ecSmrg tmpval[0] = GXcopy; 69105b261ecSmrg tmpval[1] = pGC->tile.pixel; 69205b261ecSmrg tmpval[2] = FillSolid; 69305b261ecSmrg (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, 69405b261ecSmrg tmpval); 69505b261ecSmrg ValidateGC((DrawablePtr)pTile, pgcScratch); 69605b261ecSmrg rect.x = 0; 69705b261ecSmrg rect.y = 0; 69805b261ecSmrg rect.width = w; 69905b261ecSmrg rect.height = h; 70005b261ecSmrg (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); 70105b261ecSmrg /* Always remember to free the scratch graphics context after use. */ 70205b261ecSmrg FreeScratchGC(pgcScratch); 70305b261ecSmrg 70405b261ecSmrg pGC->tileIsPixel = FALSE; 70505b261ecSmrg pGC->tile.pixmap = pTile; 70605b261ecSmrg return TRUE; 70705b261ecSmrg} 70805b261ecSmrg 70905b261ecSmrg_X_EXPORT int 71005b261ecSmrgCopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) 71105b261ecSmrg{ 71205b261ecSmrg BITS32 index2; 71305b261ecSmrg BITS32 maskQ; 71405b261ecSmrg int error = 0; 71505b261ecSmrg 71605b261ecSmrg if (pgcSrc == pgcDst) 71705b261ecSmrg return Success; 71805b261ecSmrg pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; 71905b261ecSmrg pgcDst->stateChanges |= mask; 72005b261ecSmrg maskQ = mask; 72105b261ecSmrg while (mask) 72205b261ecSmrg { 72305b261ecSmrg index2 = (BITS32) lowbit (mask); 72405b261ecSmrg mask &= ~index2; 72505b261ecSmrg switch (index2) 72605b261ecSmrg { 72705b261ecSmrg case GCFunction: 72805b261ecSmrg pgcDst->alu = pgcSrc->alu; 72905b261ecSmrg break; 73005b261ecSmrg case GCPlaneMask: 73105b261ecSmrg pgcDst->planemask = pgcSrc->planemask; 73205b261ecSmrg break; 73305b261ecSmrg case GCForeground: 73405b261ecSmrg pgcDst->fgPixel = pgcSrc->fgPixel; 73505b261ecSmrg break; 73605b261ecSmrg case GCBackground: 73705b261ecSmrg pgcDst->bgPixel = pgcSrc->bgPixel; 73805b261ecSmrg break; 73905b261ecSmrg case GCLineWidth: 74005b261ecSmrg pgcDst->lineWidth = pgcSrc->lineWidth; 74105b261ecSmrg break; 74205b261ecSmrg case GCLineStyle: 74305b261ecSmrg pgcDst->lineStyle = pgcSrc->lineStyle; 74405b261ecSmrg break; 74505b261ecSmrg case GCCapStyle: 74605b261ecSmrg pgcDst->capStyle = pgcSrc->capStyle; 74705b261ecSmrg break; 74805b261ecSmrg case GCJoinStyle: 74905b261ecSmrg pgcDst->joinStyle = pgcSrc->joinStyle; 75005b261ecSmrg break; 75105b261ecSmrg case GCFillStyle: 75205b261ecSmrg pgcDst->fillStyle = pgcSrc->fillStyle; 75305b261ecSmrg break; 75405b261ecSmrg case GCFillRule: 75505b261ecSmrg pgcDst->fillRule = pgcSrc->fillRule; 75605b261ecSmrg break; 75705b261ecSmrg case GCTile: 75805b261ecSmrg { 75905b261ecSmrg if (EqualPixUnion(pgcDst->tileIsPixel, 76005b261ecSmrg pgcDst->tile, 76105b261ecSmrg pgcSrc->tileIsPixel, 76205b261ecSmrg pgcSrc->tile)) 76305b261ecSmrg { 76405b261ecSmrg break; 76505b261ecSmrg } 76605b261ecSmrg if (!pgcDst->tileIsPixel) 76705b261ecSmrg (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); 76805b261ecSmrg pgcDst->tileIsPixel = pgcSrc->tileIsPixel; 76905b261ecSmrg pgcDst->tile = pgcSrc->tile; 77005b261ecSmrg if (!pgcDst->tileIsPixel) 77105b261ecSmrg pgcDst->tile.pixmap->refcnt++; 77205b261ecSmrg break; 77305b261ecSmrg } 77405b261ecSmrg case GCStipple: 77505b261ecSmrg { 77605b261ecSmrg if (pgcDst->stipple == pgcSrc->stipple) 77705b261ecSmrg break; 77805b261ecSmrg if (pgcDst->stipple) 77905b261ecSmrg (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); 78005b261ecSmrg pgcDst->stipple = pgcSrc->stipple; 78105b261ecSmrg if (pgcDst->stipple) 78205b261ecSmrg pgcDst->stipple->refcnt ++; 78305b261ecSmrg break; 78405b261ecSmrg } 78505b261ecSmrg case GCTileStipXOrigin: 78605b261ecSmrg pgcDst->patOrg.x = pgcSrc->patOrg.x; 78705b261ecSmrg break; 78805b261ecSmrg case GCTileStipYOrigin: 78905b261ecSmrg pgcDst->patOrg.y = pgcSrc->patOrg.y; 79005b261ecSmrg break; 79105b261ecSmrg case GCFont: 79205b261ecSmrg if (pgcDst->font == pgcSrc->font) 79305b261ecSmrg break; 79405b261ecSmrg if (pgcDst->font) 79505b261ecSmrg CloseFont(pgcDst->font, (Font)0); 79605b261ecSmrg if ((pgcDst->font = pgcSrc->font) != NullFont) 79705b261ecSmrg (pgcDst->font)->refcnt++; 79805b261ecSmrg break; 79905b261ecSmrg case GCSubwindowMode: 80005b261ecSmrg pgcDst->subWindowMode = pgcSrc->subWindowMode; 80105b261ecSmrg break; 80205b261ecSmrg case GCGraphicsExposures: 80305b261ecSmrg pgcDst->graphicsExposures = pgcSrc->graphicsExposures; 80405b261ecSmrg break; 80505b261ecSmrg case GCClipXOrigin: 80605b261ecSmrg pgcDst->clipOrg.x = pgcSrc->clipOrg.x; 80705b261ecSmrg break; 80805b261ecSmrg case GCClipYOrigin: 80905b261ecSmrg pgcDst->clipOrg.y = pgcSrc->clipOrg.y; 81005b261ecSmrg break; 81105b261ecSmrg case GCClipMask: 81205b261ecSmrg (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); 81305b261ecSmrg break; 81405b261ecSmrg case GCDashOffset: 81505b261ecSmrg pgcDst->dashOffset = pgcSrc->dashOffset; 81605b261ecSmrg break; 81705b261ecSmrg case GCDashList: 81805b261ecSmrg if (pgcSrc->dash == DefaultDash) 81905b261ecSmrg { 82005b261ecSmrg if (pgcDst->dash != DefaultDash) 82105b261ecSmrg { 82205b261ecSmrg xfree(pgcDst->dash); 82305b261ecSmrg pgcDst->numInDashList = pgcSrc->numInDashList; 82405b261ecSmrg pgcDst->dash = pgcSrc->dash; 82505b261ecSmrg } 82605b261ecSmrg } 82705b261ecSmrg else 82805b261ecSmrg { 82905b261ecSmrg unsigned char *dash; 83005b261ecSmrg unsigned int i; 83105b261ecSmrg 83205b261ecSmrg dash = (unsigned char *)xalloc(pgcSrc->numInDashList * 83305b261ecSmrg sizeof(unsigned char)); 83405b261ecSmrg if (dash) 83505b261ecSmrg { 83605b261ecSmrg if (pgcDst->dash != DefaultDash) 83705b261ecSmrg xfree(pgcDst->dash); 83805b261ecSmrg pgcDst->numInDashList = pgcSrc->numInDashList; 83905b261ecSmrg pgcDst->dash = dash; 84005b261ecSmrg for (i=0; i<pgcSrc->numInDashList; i++) 84105b261ecSmrg dash[i] = pgcSrc->dash[i]; 84205b261ecSmrg } 84305b261ecSmrg else 84405b261ecSmrg error = BadAlloc; 84505b261ecSmrg } 84605b261ecSmrg break; 84705b261ecSmrg case GCArcMode: 84805b261ecSmrg pgcDst->arcMode = pgcSrc->arcMode; 84905b261ecSmrg break; 85005b261ecSmrg default: 85105b261ecSmrg clientErrorValue = maskQ; 85205b261ecSmrg error = BadValue; 85305b261ecSmrg break; 85405b261ecSmrg } 85505b261ecSmrg } 85605b261ecSmrg if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) 85705b261ecSmrg { 85805b261ecSmrg if (!CreateDefaultTile (pgcDst)) 85905b261ecSmrg { 86005b261ecSmrg pgcDst->fillStyle = FillSolid; 86105b261ecSmrg error = BadAlloc; 86205b261ecSmrg } 86305b261ecSmrg } 86405b261ecSmrg (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); 86505b261ecSmrg return error; 86605b261ecSmrg} 86705b261ecSmrg 86805b261ecSmrg/** 86905b261ecSmrg * does the diX part of freeing the characteristics in the GC. 87005b261ecSmrg * 87105b261ecSmrg * \param value must conform to DeleteType 87205b261ecSmrg */ 87305b261ecSmrg_X_EXPORT int 87405b261ecSmrgFreeGC(pointer value, XID gid) 87505b261ecSmrg{ 87605b261ecSmrg GCPtr pGC = (GCPtr)value; 87705b261ecSmrg 87805b261ecSmrg CloseFont(pGC->font, (Font)0); 87905b261ecSmrg (* pGC->funcs->DestroyClip)(pGC); 88005b261ecSmrg 88105b261ecSmrg if (!pGC->tileIsPixel) 88205b261ecSmrg (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); 88305b261ecSmrg if (pGC->stipple) 88405b261ecSmrg (* pGC->pScreen->DestroyPixmap)(pGC->stipple); 88505b261ecSmrg 88605b261ecSmrg (*pGC->funcs->DestroyGC) (pGC); 88705b261ecSmrg if (pGC->dash != DefaultDash) 88805b261ecSmrg xfree(pGC->dash); 8894642e01fSmrg dixFreePrivates(pGC->devPrivates); 89005b261ecSmrg xfree(pGC); 89105b261ecSmrg return(Success); 89205b261ecSmrg} 89305b261ecSmrg 89405b261ecSmrg/* CreateScratchGC(pScreen, depth) 89505b261ecSmrg like CreateGC, but doesn't do the default tile or stipple, 89605b261ecSmrgsince we can't create them without already having a GC. any code 89705b261ecSmrgusing the tile or stipple has to set them explicitly anyway, 89805b261ecSmrgsince the state of the scratch gc is unknown. This is OK 89905b261ecSmrgbecause ChangeGC() has to be able to deal with NULL tiles and 90005b261ecSmrgstipples anyway (in case the CreateGC() call has provided a 90105b261ecSmrgvalue for them -- we can't set the default tile until the 90205b261ecSmrgclient-supplied attributes are installed, since the fgPixel 90305b261ecSmrgis what fills the default tile. (maybe this comment should 90405b261ecSmrggo with CreateGC() or ChangeGC().) 90505b261ecSmrg*/ 90605b261ecSmrg 90705b261ecSmrg_X_EXPORT GCPtr 90805b261ecSmrgCreateScratchGC(ScreenPtr pScreen, unsigned depth) 90905b261ecSmrg{ 91005b261ecSmrg GCPtr pGC; 91105b261ecSmrg 9124642e01fSmrg pGC = (GCPtr)xalloc(sizeof(GC)); 91305b261ecSmrg if (!pGC) 91405b261ecSmrg return (GCPtr)NULL; 91505b261ecSmrg 91605b261ecSmrg pGC->pScreen = pScreen; 91705b261ecSmrg pGC->depth = depth; 91805b261ecSmrg pGC->alu = GXcopy; /* dst <- src */ 91905b261ecSmrg pGC->planemask = ~0; 92005b261ecSmrg pGC->serialNumber = 0; 9214642e01fSmrg pGC->devPrivates = NULL; 92205b261ecSmrg pGC->fgPixel = 0; 92305b261ecSmrg pGC->bgPixel = 1; 92405b261ecSmrg pGC->lineWidth = 0; 92505b261ecSmrg pGC->lineStyle = LineSolid; 92605b261ecSmrg pGC->capStyle = CapButt; 92705b261ecSmrg pGC->joinStyle = JoinMiter; 92805b261ecSmrg pGC->fillStyle = FillSolid; 92905b261ecSmrg pGC->fillRule = EvenOddRule; 93005b261ecSmrg pGC->arcMode = ArcPieSlice; 93105b261ecSmrg pGC->font = defaultFont; 93205b261ecSmrg if ( pGC->font) /* necessary, because open of default font could fail */ 93305b261ecSmrg pGC->font->refcnt++; 93405b261ecSmrg pGC->tileIsPixel = TRUE; 93505b261ecSmrg pGC->tile.pixel = 0; 93605b261ecSmrg pGC->stipple = NullPixmap; 93705b261ecSmrg pGC->patOrg.x = 0; 93805b261ecSmrg pGC->patOrg.y = 0; 93905b261ecSmrg pGC->subWindowMode = ClipByChildren; 94005b261ecSmrg pGC->graphicsExposures = TRUE; 94105b261ecSmrg pGC->clipOrg.x = 0; 94205b261ecSmrg pGC->clipOrg.y = 0; 94305b261ecSmrg pGC->clientClipType = CT_NONE; 94405b261ecSmrg pGC->dashOffset = 0; 94505b261ecSmrg pGC->numInDashList = 2; 94605b261ecSmrg pGC->dash = DefaultDash; 94705b261ecSmrg pGC->lastWinOrg.x = 0; 94805b261ecSmrg pGC->lastWinOrg.y = 0; 94905b261ecSmrg 95005b261ecSmrg pGC->stateChanges = (1 << (GCLastBit+1)) - 1; 95105b261ecSmrg if (!(*pScreen->CreateGC)(pGC)) 95205b261ecSmrg { 95305b261ecSmrg FreeGC(pGC, (XID)0); 95405b261ecSmrg pGC = (GCPtr)NULL; 95505b261ecSmrg } 95605b261ecSmrg return pGC; 95705b261ecSmrg} 95805b261ecSmrg 95905b261ecSmrgvoid 96005b261ecSmrgFreeGCperDepth(int screenNum) 96105b261ecSmrg{ 96205b261ecSmrg int i; 96305b261ecSmrg ScreenPtr pScreen; 96405b261ecSmrg GCPtr *ppGC; 96505b261ecSmrg 96605b261ecSmrg pScreen = screenInfo.screens[screenNum]; 96705b261ecSmrg ppGC = pScreen->GCperDepth; 96805b261ecSmrg 96905b261ecSmrg for (i = 0; i <= pScreen->numDepths; i++) 97005b261ecSmrg (void)FreeGC(ppGC[i], (XID)0); 97105b261ecSmrg pScreen->rgf = ~0L; 97205b261ecSmrg} 97305b261ecSmrg 97405b261ecSmrg 97505b261ecSmrgBool 97605b261ecSmrgCreateGCperDepth(int screenNum) 97705b261ecSmrg{ 97805b261ecSmrg int i; 97905b261ecSmrg ScreenPtr pScreen; 98005b261ecSmrg DepthPtr pDepth; 98105b261ecSmrg GCPtr *ppGC; 98205b261ecSmrg 98305b261ecSmrg pScreen = screenInfo.screens[screenNum]; 98405b261ecSmrg pScreen->rgf = 0; 98505b261ecSmrg ppGC = pScreen->GCperDepth; 98605b261ecSmrg /* do depth 1 separately because it's not included in list */ 98705b261ecSmrg if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) 98805b261ecSmrg return FALSE; 98905b261ecSmrg ppGC[0]->graphicsExposures = FALSE; 99005b261ecSmrg /* Make sure we don't overflow GCperDepth[] */ 99105b261ecSmrg if( pScreen->numDepths > MAXFORMATS ) 99205b261ecSmrg return FALSE; 99305b261ecSmrg 99405b261ecSmrg pDepth = pScreen->allowedDepths; 99505b261ecSmrg for (i=0; i<pScreen->numDepths; i++, pDepth++) 99605b261ecSmrg { 99705b261ecSmrg if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) 99805b261ecSmrg { 99905b261ecSmrg for (; i >= 0; i--) 100005b261ecSmrg (void)FreeGC(ppGC[i], (XID)0); 100105b261ecSmrg return FALSE; 100205b261ecSmrg } 100305b261ecSmrg ppGC[i+1]->graphicsExposures = FALSE; 100405b261ecSmrg } 100505b261ecSmrg return TRUE; 100605b261ecSmrg} 100705b261ecSmrg 100805b261ecSmrgBool 100905b261ecSmrgCreateDefaultStipple(int screenNum) 101005b261ecSmrg{ 101105b261ecSmrg ScreenPtr pScreen; 101205b261ecSmrg XID tmpval[3]; 101305b261ecSmrg xRectangle rect; 101405b261ecSmrg CARD16 w, h; 101505b261ecSmrg GCPtr pgcScratch; 101605b261ecSmrg 101705b261ecSmrg pScreen = screenInfo.screens[screenNum]; 101805b261ecSmrg 101905b261ecSmrg w = 16; 102005b261ecSmrg h = 16; 102105b261ecSmrg (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); 102205b261ecSmrg if (!(pScreen->PixmapPerDepth[0] = 10234642e01fSmrg (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) 102405b261ecSmrg return FALSE; 102505b261ecSmrg /* fill stipple with 1 */ 102605b261ecSmrg tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid; 102705b261ecSmrg pgcScratch = GetScratchGC(1, pScreen); 102805b261ecSmrg if (!pgcScratch) 102905b261ecSmrg { 103005b261ecSmrg (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); 103105b261ecSmrg return FALSE; 103205b261ecSmrg } 103305b261ecSmrg (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); 103405b261ecSmrg ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); 103505b261ecSmrg rect.x = 0; 103605b261ecSmrg rect.y = 0; 103705b261ecSmrg rect.width = w; 103805b261ecSmrg rect.height = h; 103905b261ecSmrg (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], 104005b261ecSmrg pgcScratch, 1, &rect); 104105b261ecSmrg FreeScratchGC(pgcScratch); 104205b261ecSmrg return TRUE; 104305b261ecSmrg} 104405b261ecSmrg 104505b261ecSmrgvoid 104605b261ecSmrgFreeDefaultStipple(int screenNum) 104705b261ecSmrg{ 104805b261ecSmrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 104905b261ecSmrg (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); 105005b261ecSmrg} 105105b261ecSmrg 10524642e01fSmrgint 105305b261ecSmrgSetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) 105405b261ecSmrg{ 105505b261ecSmrg long i; 105605b261ecSmrg unsigned char *p, *indash; 105705b261ecSmrg BITS32 maskQ = 0; 105805b261ecSmrg 105905b261ecSmrg i = ndash; 106005b261ecSmrg p = pdash; 106105b261ecSmrg while (i--) 106205b261ecSmrg { 106305b261ecSmrg if (!*p++) 106405b261ecSmrg { 106505b261ecSmrg /* dash segment must be > 0 */ 106605b261ecSmrg clientErrorValue = 0; 106705b261ecSmrg return BadValue; 106805b261ecSmrg } 106905b261ecSmrg } 107005b261ecSmrg 107105b261ecSmrg if (ndash & 1) 107205b261ecSmrg p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char)); 107305b261ecSmrg else 107405b261ecSmrg p = (unsigned char *)xalloc(ndash * sizeof(unsigned char)); 107505b261ecSmrg if (!p) 107605b261ecSmrg return BadAlloc; 107705b261ecSmrg 107805b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 107905b261ecSmrg if (offset != pGC->dashOffset) 108005b261ecSmrg { 108105b261ecSmrg pGC->dashOffset = offset; 108205b261ecSmrg pGC->stateChanges |= GCDashOffset; 108305b261ecSmrg maskQ |= GCDashOffset; 108405b261ecSmrg } 108505b261ecSmrg 108605b261ecSmrg if (pGC->dash != DefaultDash) 108705b261ecSmrg xfree(pGC->dash); 108805b261ecSmrg pGC->numInDashList = ndash; 108905b261ecSmrg pGC->dash = p; 109005b261ecSmrg if (ndash & 1) 109105b261ecSmrg { 109205b261ecSmrg pGC->numInDashList += ndash; 109305b261ecSmrg indash = pdash; 109405b261ecSmrg i = ndash; 109505b261ecSmrg while (i--) 109605b261ecSmrg *p++ = *indash++; 109705b261ecSmrg } 109805b261ecSmrg while(ndash--) 109905b261ecSmrg *p++ = *pdash++; 110005b261ecSmrg pGC->stateChanges |= GCDashList; 110105b261ecSmrg maskQ |= GCDashList; 110205b261ecSmrg 110305b261ecSmrg if (pGC->funcs->ChangeGC) 110405b261ecSmrg (*pGC->funcs->ChangeGC) (pGC, maskQ); 110505b261ecSmrg return Success; 110605b261ecSmrg} 110705b261ecSmrg 110805b261ecSmrg_X_EXPORT int 110905b261ecSmrgVerifyRectOrder(int nrects, xRectangle *prects, int ordering) 111005b261ecSmrg{ 111105b261ecSmrg xRectangle *prectP, *prectN; 111205b261ecSmrg int i; 111305b261ecSmrg 111405b261ecSmrg switch(ordering) 111505b261ecSmrg { 111605b261ecSmrg case Unsorted: 111705b261ecSmrg return CT_UNSORTED; 111805b261ecSmrg case YSorted: 111905b261ecSmrg if(nrects > 1) 112005b261ecSmrg { 112105b261ecSmrg for(i = 1, prectP = prects, prectN = prects + 1; 112205b261ecSmrg i < nrects; 112305b261ecSmrg i++, prectP++, prectN++) 112405b261ecSmrg if(prectN->y < prectP->y) 112505b261ecSmrg return -1; 112605b261ecSmrg } 112705b261ecSmrg return CT_YSORTED; 112805b261ecSmrg case YXSorted: 112905b261ecSmrg if(nrects > 1) 113005b261ecSmrg { 113105b261ecSmrg for(i = 1, prectP = prects, prectN = prects + 1; 113205b261ecSmrg i < nrects; 113305b261ecSmrg i++, prectP++, prectN++) 113405b261ecSmrg if((prectN->y < prectP->y) || 113505b261ecSmrg ( (prectN->y == prectP->y) && 113605b261ecSmrg (prectN->x < prectP->x) ) ) 113705b261ecSmrg return -1; 113805b261ecSmrg } 113905b261ecSmrg return CT_YXSORTED; 114005b261ecSmrg case YXBanded: 114105b261ecSmrg if(nrects > 1) 114205b261ecSmrg { 114305b261ecSmrg for(i = 1, prectP = prects, prectN = prects + 1; 114405b261ecSmrg i < nrects; 114505b261ecSmrg i++, prectP++, prectN++) 114605b261ecSmrg if((prectN->y != prectP->y && 114705b261ecSmrg prectN->y < prectP->y + (int) prectP->height) || 114805b261ecSmrg ((prectN->y == prectP->y) && 114905b261ecSmrg (prectN->height != prectP->height || 115005b261ecSmrg prectN->x < prectP->x + (int) prectP->width))) 115105b261ecSmrg return -1; 115205b261ecSmrg } 115305b261ecSmrg return CT_YXBANDED; 115405b261ecSmrg } 115505b261ecSmrg return -1; 115605b261ecSmrg} 115705b261ecSmrg 11584642e01fSmrgint 115905b261ecSmrgSetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, 116005b261ecSmrg xRectangle *prects, int ordering) 116105b261ecSmrg{ 116205b261ecSmrg int newct, size; 116305b261ecSmrg xRectangle *prectsNew; 116405b261ecSmrg 116505b261ecSmrg newct = VerifyRectOrder(nrects, prects, ordering); 116605b261ecSmrg if (newct < 0) 116705b261ecSmrg return(BadMatch); 116805b261ecSmrg size = nrects * sizeof(xRectangle); 116905b261ecSmrg prectsNew = (xRectangle *) xalloc(size); 117005b261ecSmrg if (!prectsNew && size) 117105b261ecSmrg return BadAlloc; 117205b261ecSmrg 117305b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 117405b261ecSmrg pGC->clipOrg.x = xOrigin; 117505b261ecSmrg pGC->stateChanges |= GCClipXOrigin; 117605b261ecSmrg 117705b261ecSmrg pGC->clipOrg.y = yOrigin; 117805b261ecSmrg pGC->stateChanges |= GCClipYOrigin; 117905b261ecSmrg 118005b261ecSmrg if (size) 118105b261ecSmrg memmove((char *)prectsNew, (char *)prects, size); 118205b261ecSmrg (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); 118305b261ecSmrg if (pGC->funcs->ChangeGC) 118405b261ecSmrg (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); 118505b261ecSmrg return Success; 118605b261ecSmrg} 118705b261ecSmrg 118805b261ecSmrg 118905b261ecSmrg/* 119005b261ecSmrg sets reasonable defaults 119105b261ecSmrg if we can get a pre-allocated one, use it and mark it as used. 119205b261ecSmrg if we can't, create one out of whole cloth (The Velveteen GC -- if 119305b261ecSmrg you use it often enough it will become real.) 119405b261ecSmrg*/ 119505b261ecSmrg_X_EXPORT GCPtr 119605b261ecSmrgGetScratchGC(unsigned depth, ScreenPtr pScreen) 119705b261ecSmrg{ 119805b261ecSmrg int i; 119905b261ecSmrg GCPtr pGC; 120005b261ecSmrg 120105b261ecSmrg for (i=0; i<=pScreen->numDepths; i++) 120205b261ecSmrg if ( pScreen->GCperDepth[i]->depth == depth && 120305b261ecSmrg !(pScreen->rgf & (1L << (i+1))) 120405b261ecSmrg ) 120505b261ecSmrg { 120605b261ecSmrg pScreen->rgf |= (1L << (i+1)); 120705b261ecSmrg pGC = (pScreen->GCperDepth[i]); 120805b261ecSmrg 120905b261ecSmrg pGC->alu = GXcopy; 121005b261ecSmrg pGC->planemask = ~0; 121105b261ecSmrg pGC->serialNumber = 0; 121205b261ecSmrg pGC->fgPixel = 0; 121305b261ecSmrg pGC->bgPixel = 1; 121405b261ecSmrg pGC->lineWidth = 0; 121505b261ecSmrg pGC->lineStyle = LineSolid; 121605b261ecSmrg pGC->capStyle = CapButt; 121705b261ecSmrg pGC->joinStyle = JoinMiter; 121805b261ecSmrg pGC->fillStyle = FillSolid; 121905b261ecSmrg pGC->fillRule = EvenOddRule; 122005b261ecSmrg pGC->arcMode = ArcChord; 122105b261ecSmrg pGC->patOrg.x = 0; 122205b261ecSmrg pGC->patOrg.y = 0; 122305b261ecSmrg pGC->subWindowMode = ClipByChildren; 122405b261ecSmrg pGC->graphicsExposures = FALSE; 122505b261ecSmrg pGC->clipOrg.x = 0; 122605b261ecSmrg pGC->clipOrg.y = 0; 122705b261ecSmrg if (pGC->clientClipType != CT_NONE) 122805b261ecSmrg (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); 122905b261ecSmrg pGC->stateChanges = (1 << (GCLastBit+1)) - 1; 123005b261ecSmrg return pGC; 123105b261ecSmrg } 123205b261ecSmrg /* if we make it this far, need to roll our own */ 123305b261ecSmrg pGC = CreateScratchGC(pScreen, depth); 123405b261ecSmrg if (pGC) 123505b261ecSmrg pGC->graphicsExposures = FALSE; 123605b261ecSmrg return pGC; 123705b261ecSmrg} 123805b261ecSmrg 123905b261ecSmrg/* 124005b261ecSmrg if the gc to free is in the table of pre-existing ones, 124105b261ecSmrgmark it as available. 124205b261ecSmrg if not, free it for real 124305b261ecSmrg*/ 124405b261ecSmrg_X_EXPORT void 124505b261ecSmrgFreeScratchGC(GCPtr pGC) 124605b261ecSmrg{ 124705b261ecSmrg ScreenPtr pScreen = pGC->pScreen; 124805b261ecSmrg int i; 124905b261ecSmrg 125005b261ecSmrg for (i=0; i<=pScreen->numDepths; i++) 125105b261ecSmrg { 125205b261ecSmrg if ( pScreen->GCperDepth[i] == pGC) 125305b261ecSmrg { 125405b261ecSmrg pScreen->rgf &= ~(1L << (i+1)); 125505b261ecSmrg return; 125605b261ecSmrg } 125705b261ecSmrg } 125805b261ecSmrg (void)FreeGC(pGC, (GContext)0); 125905b261ecSmrg} 1260