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 2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its 3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 3235c4bbdfSmrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 3535c4bbdfSmrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg******************************************************************/ 4605b261ecSmrg 4705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 4805b261ecSmrg#include <dix-config.h> 4905b261ecSmrg#endif 5005b261ecSmrg 5105b261ecSmrg#include <X11/X.h> 5205b261ecSmrg#include <X11/Xmd.h> 5305b261ecSmrg#include <X11/Xproto.h> 5405b261ecSmrg#include "misc.h" 5505b261ecSmrg#include "resource.h" 5605b261ecSmrg#include "gcstruct.h" 5705b261ecSmrg#include "pixmapstr.h" 5805b261ecSmrg#include "dixfontstr.h" 5905b261ecSmrg#include "scrnintstr.h" 6005b261ecSmrg#include "region.h" 616747b715Smrg#include "dixstruct.h" 6205b261ecSmrg 634642e01fSmrg#include "privates.h" 6405b261ecSmrg#include "dix.h" 654642e01fSmrg#include "xace.h" 6605b261ecSmrg#include <assert.h> 6705b261ecSmrg 6805b261ecSmrgextern FontPtr defaultFont; 6905b261ecSmrg 7005b261ecSmrgstatic Bool CreateDefaultTile(GCPtr pGC); 7105b261ecSmrg 7235c4bbdfSmrgstatic unsigned char DefaultDash[2] = { 4, 4 }; 7305b261ecSmrg 746747b715Smrgvoid 7535c4bbdfSmrgValidateGC(DrawablePtr pDraw, GC * pGC) 7605b261ecSmrg{ 7705b261ecSmrg (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); 7805b261ecSmrg pGC->stateChanges = 0; 7905b261ecSmrg pGC->serialNumber = pDraw->serialNumber; 8005b261ecSmrg} 8105b261ecSmrg 826747b715Smrg/* 836747b715Smrg * ChangeGC/ChangeGCXIDs: 846747b715Smrg * 856747b715Smrg * The client performing the gc change must be passed so that access 866747b715Smrg * checks can be performed on any tiles, stipples, or fonts that are 876747b715Smrg * specified. ddxen can call this too; they should normally pass 886747b715Smrg * NullClient for the client since any access checking should have 8905b261ecSmrg * already been done at a higher level. 9035c4bbdfSmrg * 916747b715Smrg * If you have any XIDs, you must use ChangeGCXIDs: 9235c4bbdfSmrg * 9305b261ecSmrg * CARD32 v[2]; 946747b715Smrg * v[0] = FillTiled; 956747b715Smrg * v[1] = pid; 966747b715Smrg * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); 9735c4bbdfSmrg * 986747b715Smrg * However, if you need to pass a pointer to a pixmap or font, you must 996747b715Smrg * use ChangeGC: 10035c4bbdfSmrg * 10105b261ecSmrg * ChangeGCVal v[2]; 10205b261ecSmrg * v[0].val = FillTiled; 10305b261ecSmrg * v[1].ptr = pPixmap; 1046747b715Smrg * ChangeGC(client, pGC, GCFillStyle|GCTile, v); 10535c4bbdfSmrg * 1066747b715Smrg * If you have neither XIDs nor pointers, you can use either function, 1076747b715Smrg * but ChangeGC will do less work. 1086747b715Smrg * 1096747b715Smrg * ChangeGCVal v[2]; 1106747b715Smrg * v[0].val = foreground; 1116747b715Smrg * v[1].val = background; 1126747b715Smrg * ChangeGC(client, pGC, GCForeground|GCBackground, v); 11305b261ecSmrg */ 11405b261ecSmrg 11505b261ecSmrg#define NEXTVAL(_type, _var) { \ 11605b261ecSmrg _var = (_type)(pUnion->val); pUnion++; \ 11705b261ecSmrg } 11805b261ecSmrg 11905b261ecSmrg#define NEXT_PTR(_type, _var) { \ 1206747b715Smrg _var = (_type)pUnion->ptr; pUnion++; } 12105b261ecSmrg 1226747b715Smrgint 12335c4bbdfSmrgChangeGC(ClientPtr client, GC * pGC, BITS32 mask, ChangeGCValPtr pUnion) 12405b261ecSmrg{ 12535c4bbdfSmrg BITS32 index2; 12635c4bbdfSmrg int error = 0; 12735c4bbdfSmrg PixmapPtr pPixmap; 12835c4bbdfSmrg BITS32 maskQ; 12905b261ecSmrg 1306747b715Smrg assert(pUnion); 13105b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 13205b261ecSmrg 13335c4bbdfSmrg maskQ = mask; /* save these for when we walk the GCque */ 13435c4bbdfSmrg while (mask && !error) { 13535c4bbdfSmrg index2 = (BITS32) lowbit(mask); 13635c4bbdfSmrg mask &= ~index2; 13735c4bbdfSmrg pGC->stateChanges |= index2; 13835c4bbdfSmrg switch (index2) { 13935c4bbdfSmrg case GCFunction: 14035c4bbdfSmrg { 14135c4bbdfSmrg CARD8 newalu; 14235c4bbdfSmrg NEXTVAL(CARD8, newalu); 14335c4bbdfSmrg 14435c4bbdfSmrg if (newalu <= GXset) 14535c4bbdfSmrg pGC->alu = newalu; 14635c4bbdfSmrg else { 14735c4bbdfSmrg if (client) 14835c4bbdfSmrg client->errorValue = newalu; 14935c4bbdfSmrg error = BadValue; 15035c4bbdfSmrg } 15135c4bbdfSmrg break; 15235c4bbdfSmrg } 15335c4bbdfSmrg case GCPlaneMask: 15435c4bbdfSmrg NEXTVAL(unsigned long, pGC->planemask); 15535c4bbdfSmrg 15635c4bbdfSmrg break; 15735c4bbdfSmrg case GCForeground: 15835c4bbdfSmrg NEXTVAL(unsigned long, pGC->fgPixel); 15935c4bbdfSmrg 16035c4bbdfSmrg /* 16135c4bbdfSmrg * this is for CreateGC 16235c4bbdfSmrg */ 16335c4bbdfSmrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) { 16435c4bbdfSmrg pGC->tileIsPixel = TRUE; 16535c4bbdfSmrg pGC->tile.pixel = pGC->fgPixel; 16635c4bbdfSmrg } 16735c4bbdfSmrg break; 16835c4bbdfSmrg case GCBackground: 16935c4bbdfSmrg NEXTVAL(unsigned long, pGC->bgPixel); 17035c4bbdfSmrg 17135c4bbdfSmrg break; 17235c4bbdfSmrg case GCLineWidth: /* ??? line width is a CARD16 */ 17335c4bbdfSmrg NEXTVAL(CARD16, pGC->lineWidth); 17435c4bbdfSmrg 17535c4bbdfSmrg break; 17635c4bbdfSmrg case GCLineStyle: 17735c4bbdfSmrg { 17835c4bbdfSmrg unsigned int newlinestyle; 17935c4bbdfSmrg NEXTVAL(unsigned int, newlinestyle); 18035c4bbdfSmrg 18135c4bbdfSmrg if (newlinestyle <= LineDoubleDash) 18235c4bbdfSmrg pGC->lineStyle = newlinestyle; 18335c4bbdfSmrg else { 18435c4bbdfSmrg if (client) 18535c4bbdfSmrg client->errorValue = newlinestyle; 18635c4bbdfSmrg error = BadValue; 18735c4bbdfSmrg } 18835c4bbdfSmrg break; 18935c4bbdfSmrg } 19035c4bbdfSmrg case GCCapStyle: 19135c4bbdfSmrg { 19235c4bbdfSmrg unsigned int newcapstyle; 19335c4bbdfSmrg NEXTVAL(unsigned int, newcapstyle); 19435c4bbdfSmrg 19535c4bbdfSmrg if (newcapstyle <= CapProjecting) 19635c4bbdfSmrg pGC->capStyle = newcapstyle; 19735c4bbdfSmrg else { 19835c4bbdfSmrg if (client) 19935c4bbdfSmrg client->errorValue = newcapstyle; 20035c4bbdfSmrg error = BadValue; 20135c4bbdfSmrg } 20235c4bbdfSmrg break; 20335c4bbdfSmrg } 20435c4bbdfSmrg case GCJoinStyle: 20535c4bbdfSmrg { 20635c4bbdfSmrg unsigned int newjoinstyle; 20735c4bbdfSmrg NEXTVAL(unsigned int, newjoinstyle); 20835c4bbdfSmrg 20935c4bbdfSmrg if (newjoinstyle <= JoinBevel) 21035c4bbdfSmrg pGC->joinStyle = newjoinstyle; 21135c4bbdfSmrg else { 21235c4bbdfSmrg if (client) 21335c4bbdfSmrg client->errorValue = newjoinstyle; 21435c4bbdfSmrg error = BadValue; 21535c4bbdfSmrg } 21635c4bbdfSmrg break; 21735c4bbdfSmrg } 21835c4bbdfSmrg case GCFillStyle: 21935c4bbdfSmrg { 22035c4bbdfSmrg unsigned int newfillstyle; 22135c4bbdfSmrg NEXTVAL(unsigned int, newfillstyle); 22235c4bbdfSmrg 22335c4bbdfSmrg if (newfillstyle <= FillOpaqueStippled) 22435c4bbdfSmrg pGC->fillStyle = newfillstyle; 22535c4bbdfSmrg else { 22635c4bbdfSmrg if (client) 22735c4bbdfSmrg client->errorValue = newfillstyle; 22835c4bbdfSmrg error = BadValue; 22935c4bbdfSmrg } 23035c4bbdfSmrg break; 23135c4bbdfSmrg } 23235c4bbdfSmrg case GCFillRule: 23335c4bbdfSmrg { 23435c4bbdfSmrg unsigned int newfillrule; 23535c4bbdfSmrg NEXTVAL(unsigned int, newfillrule); 23635c4bbdfSmrg 23735c4bbdfSmrg if (newfillrule <= WindingRule) 23835c4bbdfSmrg pGC->fillRule = newfillrule; 23935c4bbdfSmrg else { 24035c4bbdfSmrg if (client) 24135c4bbdfSmrg client->errorValue = newfillrule; 24235c4bbdfSmrg error = BadValue; 24335c4bbdfSmrg } 24435c4bbdfSmrg break; 24535c4bbdfSmrg } 24635c4bbdfSmrg case GCTile: 24735c4bbdfSmrg NEXT_PTR(PixmapPtr, pPixmap); 24835c4bbdfSmrg 24935c4bbdfSmrg if ((pPixmap->drawable.depth != pGC->depth) || 25035c4bbdfSmrg (pPixmap->drawable.pScreen != pGC->pScreen)) { 25135c4bbdfSmrg error = BadMatch; 25235c4bbdfSmrg } 25335c4bbdfSmrg else { 25435c4bbdfSmrg pPixmap->refcnt++; 25535c4bbdfSmrg if (!pGC->tileIsPixel) 25635c4bbdfSmrg (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap); 25735c4bbdfSmrg pGC->tileIsPixel = FALSE; 25835c4bbdfSmrg pGC->tile.pixmap = pPixmap; 25935c4bbdfSmrg } 26035c4bbdfSmrg break; 26135c4bbdfSmrg case GCStipple: 26235c4bbdfSmrg NEXT_PTR(PixmapPtr, pPixmap); 26335c4bbdfSmrg 26435c4bbdfSmrg if (pPixmap && ((pPixmap->drawable.depth != 1) || 26535c4bbdfSmrg (pPixmap->drawable.pScreen != pGC->pScreen))) 26635c4bbdfSmrg { 26735c4bbdfSmrg error = BadMatch; 26835c4bbdfSmrg } 26935c4bbdfSmrg else { 27035c4bbdfSmrg if (pPixmap) 27135c4bbdfSmrg pPixmap->refcnt++; 27235c4bbdfSmrg if (pGC->stipple) 27335c4bbdfSmrg (*pGC->pScreen->DestroyPixmap) (pGC->stipple); 27435c4bbdfSmrg pGC->stipple = pPixmap; 27535c4bbdfSmrg } 27635c4bbdfSmrg break; 27735c4bbdfSmrg case GCTileStipXOrigin: 27835c4bbdfSmrg NEXTVAL(INT16, pGC->patOrg.x); 27935c4bbdfSmrg 28035c4bbdfSmrg break; 28135c4bbdfSmrg case GCTileStipYOrigin: 28235c4bbdfSmrg NEXTVAL(INT16, pGC->patOrg.y); 28335c4bbdfSmrg 28435c4bbdfSmrg break; 28535c4bbdfSmrg case GCFont: 28635c4bbdfSmrg { 28735c4bbdfSmrg FontPtr pFont; 28835c4bbdfSmrg NEXT_PTR(FontPtr, pFont); 28935c4bbdfSmrg 29035c4bbdfSmrg pFont->refcnt++; 29135c4bbdfSmrg if (pGC->font) 29235c4bbdfSmrg CloseFont(pGC->font, (Font) 0); 29335c4bbdfSmrg pGC->font = pFont; 29435c4bbdfSmrg break; 29535c4bbdfSmrg } 29635c4bbdfSmrg case GCSubwindowMode: 29735c4bbdfSmrg { 29835c4bbdfSmrg unsigned int newclipmode; 29935c4bbdfSmrg NEXTVAL(unsigned int, newclipmode); 30035c4bbdfSmrg 30135c4bbdfSmrg if (newclipmode <= IncludeInferiors) 30235c4bbdfSmrg pGC->subWindowMode = newclipmode; 30335c4bbdfSmrg else { 30435c4bbdfSmrg if (client) 30535c4bbdfSmrg client->errorValue = newclipmode; 30635c4bbdfSmrg error = BadValue; 30735c4bbdfSmrg } 30835c4bbdfSmrg break; 30935c4bbdfSmrg } 31035c4bbdfSmrg case GCGraphicsExposures: 31135c4bbdfSmrg { 31235c4bbdfSmrg unsigned int newge; 31335c4bbdfSmrg NEXTVAL(unsigned int, newge); 31435c4bbdfSmrg 31535c4bbdfSmrg if (newge <= xTrue) 31635c4bbdfSmrg pGC->graphicsExposures = newge; 31735c4bbdfSmrg else { 31835c4bbdfSmrg if (client) 31935c4bbdfSmrg client->errorValue = newge; 32035c4bbdfSmrg error = BadValue; 32135c4bbdfSmrg } 32235c4bbdfSmrg break; 32335c4bbdfSmrg } 32435c4bbdfSmrg case GCClipXOrigin: 32535c4bbdfSmrg NEXTVAL(INT16, pGC->clipOrg.x); 32635c4bbdfSmrg 32735c4bbdfSmrg break; 32835c4bbdfSmrg case GCClipYOrigin: 32935c4bbdfSmrg NEXTVAL(INT16, pGC->clipOrg.y); 33035c4bbdfSmrg 33135c4bbdfSmrg break; 33235c4bbdfSmrg case GCClipMask: 33335c4bbdfSmrg NEXT_PTR(PixmapPtr, pPixmap); 33435c4bbdfSmrg 33535c4bbdfSmrg if (pPixmap) { 33635c4bbdfSmrg if ((pPixmap->drawable.depth != 1) || 33735c4bbdfSmrg (pPixmap->drawable.pScreen != pGC->pScreen)) { 33835c4bbdfSmrg error = BadMatch; 33935c4bbdfSmrg break; 34035c4bbdfSmrg } 34135c4bbdfSmrg pPixmap->refcnt++; 34235c4bbdfSmrg } 34335c4bbdfSmrg (*pGC->funcs->ChangeClip) (pGC, pPixmap ? CT_PIXMAP : CT_NONE, 34435c4bbdfSmrg (void *) pPixmap, 0); 34535c4bbdfSmrg break; 34635c4bbdfSmrg case GCDashOffset: 34735c4bbdfSmrg NEXTVAL(INT16, pGC->dashOffset); 34835c4bbdfSmrg 34935c4bbdfSmrg break; 35035c4bbdfSmrg case GCDashList: 35135c4bbdfSmrg { 35235c4bbdfSmrg CARD8 newdash; 35335c4bbdfSmrg NEXTVAL(CARD8, newdash); 35435c4bbdfSmrg 35535c4bbdfSmrg if (newdash == 4) { 35635c4bbdfSmrg if (pGC->dash != DefaultDash) { 35735c4bbdfSmrg free(pGC->dash); 35835c4bbdfSmrg pGC->numInDashList = 2; 35935c4bbdfSmrg pGC->dash = DefaultDash; 36035c4bbdfSmrg } 36135c4bbdfSmrg } 36235c4bbdfSmrg else if (newdash != 0) { 36335c4bbdfSmrg unsigned char *dash; 36435c4bbdfSmrg 36535c4bbdfSmrg dash = malloc(2 * sizeof(unsigned char)); 36635c4bbdfSmrg if (dash) { 36735c4bbdfSmrg if (pGC->dash != DefaultDash) 36835c4bbdfSmrg free(pGC->dash); 36935c4bbdfSmrg pGC->numInDashList = 2; 37035c4bbdfSmrg pGC->dash = dash; 37135c4bbdfSmrg dash[0] = newdash; 37235c4bbdfSmrg dash[1] = newdash; 37335c4bbdfSmrg } 37435c4bbdfSmrg else 37535c4bbdfSmrg error = BadAlloc; 37635c4bbdfSmrg } 37735c4bbdfSmrg else { 37835c4bbdfSmrg if (client) 37935c4bbdfSmrg client->errorValue = newdash; 38035c4bbdfSmrg error = BadValue; 38135c4bbdfSmrg } 38235c4bbdfSmrg break; 38335c4bbdfSmrg } 38435c4bbdfSmrg case GCArcMode: 38535c4bbdfSmrg { 38635c4bbdfSmrg unsigned int newarcmode; 38735c4bbdfSmrg NEXTVAL(unsigned int, newarcmode); 38835c4bbdfSmrg 38935c4bbdfSmrg if (newarcmode <= ArcPieSlice) 39035c4bbdfSmrg pGC->arcMode = newarcmode; 39135c4bbdfSmrg else { 39235c4bbdfSmrg if (client) 39335c4bbdfSmrg client->errorValue = newarcmode; 39435c4bbdfSmrg error = BadValue; 39535c4bbdfSmrg } 39635c4bbdfSmrg break; 39735c4bbdfSmrg } 39835c4bbdfSmrg default: 39935c4bbdfSmrg if (client) 40035c4bbdfSmrg client->errorValue = maskQ; 40135c4bbdfSmrg error = BadValue; 40235c4bbdfSmrg break; 40335c4bbdfSmrg } 40435c4bbdfSmrg } /* end while mask && !error */ 40535c4bbdfSmrg 40635c4bbdfSmrg if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) { 40735c4bbdfSmrg if (!CreateDefaultTile(pGC)) { 40835c4bbdfSmrg pGC->fillStyle = FillSolid; 40935c4bbdfSmrg error = BadAlloc; 41035c4bbdfSmrg } 41105b261ecSmrg } 41235c4bbdfSmrg (*pGC->funcs->ChangeGC) (pGC, maskQ); 41305b261ecSmrg return error; 41405b261ecSmrg} 41505b261ecSmrg 41605b261ecSmrg#undef NEXTVAL 41705b261ecSmrg#undef NEXT_PTR 41805b261ecSmrg 4196747b715Smrgstatic const struct { 4206747b715Smrg BITS32 mask; 4216747b715Smrg RESTYPE type; 4226747b715Smrg Mask access_mode; 4236747b715Smrg} xidfields[] = { 42435c4bbdfSmrg {GCTile, RT_PIXMAP, DixReadAccess}, 42535c4bbdfSmrg {GCStipple, RT_PIXMAP, DixReadAccess}, 42635c4bbdfSmrg {GCFont, RT_FONT, DixUseAccess}, 42735c4bbdfSmrg {GCClipMask, RT_PIXMAP, DixReadAccess}, 4286747b715Smrg}; 42905b261ecSmrg 4306747b715Smrgint 43135c4bbdfSmrgChangeGCXIDs(ClientPtr client, GC * pGC, BITS32 mask, CARD32 *pC32) 43205b261ecSmrg{ 4336747b715Smrg ChangeGCVal vals[GCLastBit + 1]; 4346747b715Smrg int i; 43535c4bbdfSmrg 43635c4bbdfSmrg if (mask & ~GCAllBits) { 43735c4bbdfSmrg client->errorValue = mask; 43835c4bbdfSmrg return BadValue; 4396747b715Smrg } 44035c4bbdfSmrg for (i = Ones(mask); i--;) 44135c4bbdfSmrg vals[i].val = pC32[i]; 4421b5d61b8Smrg for (i = 0; i < ARRAY_SIZE(xidfields); ++i) { 44335c4bbdfSmrg int offset, rc; 44435c4bbdfSmrg 44535c4bbdfSmrg if (!(mask & xidfields[i].mask)) 44635c4bbdfSmrg continue; 44735c4bbdfSmrg offset = Ones(mask & (xidfields[i].mask - 1)); 44835c4bbdfSmrg if (xidfields[i].mask == GCClipMask && vals[offset].val == None) { 44935c4bbdfSmrg vals[offset].ptr = NullPixmap; 45035c4bbdfSmrg continue; 45135c4bbdfSmrg } 45235c4bbdfSmrg rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, 45335c4bbdfSmrg xidfields[i].type, client, 45435c4bbdfSmrg xidfields[i].access_mode); 45535c4bbdfSmrg if (rc != Success) { 45635c4bbdfSmrg client->errorValue = vals[offset].val; 45735c4bbdfSmrg return rc; 45835c4bbdfSmrg } 4596747b715Smrg } 4606747b715Smrg return ChangeGC(client, pGC, mask, vals); 46105b261ecSmrg} 46205b261ecSmrg 46335c4bbdfSmrgstatic GCPtr 46435c4bbdfSmrgNewGCObject(ScreenPtr pScreen, int depth) 46505b261ecSmrg{ 46605b261ecSmrg GCPtr pGC; 46705b261ecSmrg 46835c4bbdfSmrg pGC = dixAllocateScreenObjectWithPrivates(pScreen, GC, PRIVATE_GC); 46935c4bbdfSmrg if (!pGC) { 47035c4bbdfSmrg return (GCPtr) NULL; 47105b261ecSmrg } 47205b261ecSmrg 47335c4bbdfSmrg pGC->pScreen = pScreen; 47435c4bbdfSmrg pGC->depth = depth; 47535c4bbdfSmrg pGC->alu = GXcopy; /* dst <- src */ 47605b261ecSmrg pGC->planemask = ~0; 47735c4bbdfSmrg pGC->serialNumber = 0; 47805b261ecSmrg pGC->funcs = 0; 47905b261ecSmrg pGC->fgPixel = 0; 48005b261ecSmrg pGC->bgPixel = 1; 48105b261ecSmrg pGC->lineWidth = 0; 48205b261ecSmrg pGC->lineStyle = LineSolid; 48305b261ecSmrg pGC->capStyle = CapButt; 48405b261ecSmrg pGC->joinStyle = JoinMiter; 48505b261ecSmrg pGC->fillStyle = FillSolid; 48605b261ecSmrg pGC->fillRule = EvenOddRule; 48705b261ecSmrg pGC->arcMode = ArcPieSlice; 4886747b715Smrg pGC->tile.pixel = 0; 4896747b715Smrg pGC->tile.pixmap = NullPixmap; 49005b261ecSmrg 49135c4bbdfSmrg pGC->tileIsPixel = TRUE; 49205b261ecSmrg pGC->patOrg.x = 0; 49305b261ecSmrg pGC->patOrg.y = 0; 49405b261ecSmrg pGC->subWindowMode = ClipByChildren; 49505b261ecSmrg pGC->graphicsExposures = TRUE; 49605b261ecSmrg pGC->clipOrg.x = 0; 49705b261ecSmrg pGC->clipOrg.y = 0; 49835c4bbdfSmrg pGC->clientClip = (void *) NULL; 49905b261ecSmrg pGC->numInDashList = 2; 50005b261ecSmrg pGC->dash = DefaultDash; 50105b261ecSmrg pGC->dashOffset = 0; 50205b261ecSmrg 50305b261ecSmrg /* use the default font and stipple */ 50405b261ecSmrg pGC->font = defaultFont; 50535c4bbdfSmrg if (pGC->font) /* necessary, because open of default font could fail */ 50635c4bbdfSmrg pGC->font->refcnt++; 5071b5d61b8Smrg pGC->stipple = pGC->pScreen->defaultStipple; 50835c4bbdfSmrg if (pGC->stipple) 50935c4bbdfSmrg pGC->stipple->refcnt++; 51005b261ecSmrg 5116747b715Smrg /* this is not a scratch GC */ 5126747b715Smrg pGC->scratch_inuse = FALSE; 51335c4bbdfSmrg return pGC; 51435c4bbdfSmrg} 51535c4bbdfSmrg 51635c4bbdfSmrg/* CreateGC(pDrawable, mask, pval, pStatus) 51735c4bbdfSmrg creates a default GC for the given drawable, using mask to fill 51835c4bbdfSmrg in any non-default values. 51935c4bbdfSmrg Returns a pointer to the new GC on success, NULL otherwise. 52035c4bbdfSmrg returns status of non-default fields in pStatus 52135c4bbdfSmrgBUG: 52235c4bbdfSmrg should check for failure to create default tile 52335c4bbdfSmrg 52435c4bbdfSmrg*/ 52535c4bbdfSmrgGCPtr 52635c4bbdfSmrgCreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, 52735c4bbdfSmrg XID gcid, ClientPtr client) 52835c4bbdfSmrg{ 52935c4bbdfSmrg GCPtr pGC; 53035c4bbdfSmrg 53135c4bbdfSmrg pGC = NewGCObject(pDrawable->pScreen, pDrawable->depth); 53235c4bbdfSmrg if (!pGC) { 53335c4bbdfSmrg *pStatus = BadAlloc; 53435c4bbdfSmrg return (GCPtr) NULL; 53535c4bbdfSmrg } 53635c4bbdfSmrg 53735c4bbdfSmrg pGC->serialNumber = GC_CHANGE_SERIAL_BIT; 53835c4bbdfSmrg if (mask & GCForeground) { 53935c4bbdfSmrg /* 54035c4bbdfSmrg * magic special case -- ChangeGC checks for this condition 54135c4bbdfSmrg * and snags the Foreground value to create a pseudo default-tile 54235c4bbdfSmrg */ 54335c4bbdfSmrg pGC->tileIsPixel = FALSE; 54435c4bbdfSmrg } 54535c4bbdfSmrg else { 54635c4bbdfSmrg pGC->tileIsPixel = TRUE; 54735c4bbdfSmrg } 5486747b715Smrg 5494642e01fSmrg /* security creation/labeling check */ 5504642e01fSmrg *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, 55135c4bbdfSmrg RT_NONE, NULL, DixCreateAccess | DixSetAttrAccess); 5524642e01fSmrg if (*pStatus != Success) 55335c4bbdfSmrg goto out; 5544642e01fSmrg 5556747b715Smrg pGC->stateChanges = GCAllBits; 55635c4bbdfSmrg if (!(*pGC->pScreen->CreateGC) (pGC)) 55735c4bbdfSmrg *pStatus = BadAlloc; 55805b261ecSmrg else if (mask) 5596747b715Smrg *pStatus = ChangeGCXIDs(client, pGC, mask, pval); 56005b261ecSmrg else 56135c4bbdfSmrg *pStatus = Success; 56235c4bbdfSmrg 56335c4bbdfSmrg out: 56435c4bbdfSmrg if (*pStatus != Success) { 56535c4bbdfSmrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 56635c4bbdfSmrg pGC->tileIsPixel = TRUE; /* undo special case */ 56735c4bbdfSmrg FreeGC(pGC, (XID) 0); 56835c4bbdfSmrg pGC = (GCPtr) NULL; 56905b261ecSmrg } 57005b261ecSmrg 5716747b715Smrg return pGC; 57205b261ecSmrg} 57305b261ecSmrg 57405b261ecSmrgstatic Bool 57535c4bbdfSmrgCreateDefaultTile(GCPtr pGC) 57605b261ecSmrg{ 57735c4bbdfSmrg ChangeGCVal tmpval[3]; 57835c4bbdfSmrg PixmapPtr pTile; 57935c4bbdfSmrg GCPtr pgcScratch; 58035c4bbdfSmrg xRectangle rect; 58135c4bbdfSmrg CARD16 w, h; 58205b261ecSmrg 58305b261ecSmrg w = 1; 58405b261ecSmrg h = 1; 58535c4bbdfSmrg (*pGC->pScreen->QueryBestSize) (TileShape, &w, &h, pGC->pScreen); 58605b261ecSmrg pTile = (PixmapPtr) 58735c4bbdfSmrg (*pGC->pScreen->CreatePixmap) (pGC->pScreen, w, h, pGC->depth, 0); 58805b261ecSmrg pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); 58935c4bbdfSmrg if (!pTile || !pgcScratch) { 59035c4bbdfSmrg if (pTile) 59135c4bbdfSmrg (*pTile->drawable.pScreen->DestroyPixmap) (pTile); 59235c4bbdfSmrg if (pgcScratch) 59335c4bbdfSmrg FreeScratchGC(pgcScratch); 59435c4bbdfSmrg return FALSE; 59505b261ecSmrg } 5966747b715Smrg tmpval[0].val = GXcopy; 5976747b715Smrg tmpval[1].val = pGC->tile.pixel; 5986747b715Smrg tmpval[2].val = FillSolid; 59935c4bbdfSmrg (void) ChangeGC(NullClient, pgcScratch, 60035c4bbdfSmrg GCFunction | GCForeground | GCFillStyle, tmpval); 60135c4bbdfSmrg ValidateGC((DrawablePtr) pTile, pgcScratch); 60205b261ecSmrg rect.x = 0; 60305b261ecSmrg rect.y = 0; 60405b261ecSmrg rect.width = w; 60505b261ecSmrg rect.height = h; 60635c4bbdfSmrg (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pTile, pgcScratch, 1, 60735c4bbdfSmrg &rect); 60805b261ecSmrg /* Always remember to free the scratch graphics context after use. */ 60905b261ecSmrg FreeScratchGC(pgcScratch); 61005b261ecSmrg 61105b261ecSmrg pGC->tileIsPixel = FALSE; 61205b261ecSmrg pGC->tile.pixmap = pTile; 61305b261ecSmrg return TRUE; 61405b261ecSmrg} 61505b261ecSmrg 6166747b715Smrgint 61735c4bbdfSmrgCopyGC(GC * pgcSrc, GC * pgcDst, BITS32 mask) 61805b261ecSmrg{ 61935c4bbdfSmrg BITS32 index2; 62035c4bbdfSmrg BITS32 maskQ; 62135c4bbdfSmrg int error = 0; 62205b261ecSmrg 62305b261ecSmrg if (pgcSrc == pgcDst) 62435c4bbdfSmrg return Success; 62505b261ecSmrg pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; 62605b261ecSmrg pgcDst->stateChanges |= mask; 62705b261ecSmrg maskQ = mask; 62835c4bbdfSmrg while (mask) { 62935c4bbdfSmrg index2 = (BITS32) lowbit(mask); 63035c4bbdfSmrg mask &= ~index2; 63135c4bbdfSmrg switch (index2) { 63235c4bbdfSmrg case GCFunction: 63335c4bbdfSmrg pgcDst->alu = pgcSrc->alu; 63435c4bbdfSmrg break; 63535c4bbdfSmrg case GCPlaneMask: 63635c4bbdfSmrg pgcDst->planemask = pgcSrc->planemask; 63735c4bbdfSmrg break; 63835c4bbdfSmrg case GCForeground: 63935c4bbdfSmrg pgcDst->fgPixel = pgcSrc->fgPixel; 64035c4bbdfSmrg break; 64135c4bbdfSmrg case GCBackground: 64235c4bbdfSmrg pgcDst->bgPixel = pgcSrc->bgPixel; 64335c4bbdfSmrg break; 64435c4bbdfSmrg case GCLineWidth: 64535c4bbdfSmrg pgcDst->lineWidth = pgcSrc->lineWidth; 64635c4bbdfSmrg break; 64735c4bbdfSmrg case GCLineStyle: 64835c4bbdfSmrg pgcDst->lineStyle = pgcSrc->lineStyle; 64935c4bbdfSmrg break; 65035c4bbdfSmrg case GCCapStyle: 65135c4bbdfSmrg pgcDst->capStyle = pgcSrc->capStyle; 65235c4bbdfSmrg break; 65335c4bbdfSmrg case GCJoinStyle: 65435c4bbdfSmrg pgcDst->joinStyle = pgcSrc->joinStyle; 65535c4bbdfSmrg break; 65635c4bbdfSmrg case GCFillStyle: 65735c4bbdfSmrg pgcDst->fillStyle = pgcSrc->fillStyle; 65835c4bbdfSmrg break; 65935c4bbdfSmrg case GCFillRule: 66035c4bbdfSmrg pgcDst->fillRule = pgcSrc->fillRule; 66135c4bbdfSmrg break; 66235c4bbdfSmrg case GCTile: 66335c4bbdfSmrg { 66435c4bbdfSmrg if (EqualPixUnion(pgcDst->tileIsPixel, 66535c4bbdfSmrg pgcDst->tile, 66635c4bbdfSmrg pgcSrc->tileIsPixel, pgcSrc->tile)) { 66735c4bbdfSmrg break; 66835c4bbdfSmrg } 66935c4bbdfSmrg if (!pgcDst->tileIsPixel) 67035c4bbdfSmrg (*pgcDst->pScreen->DestroyPixmap) (pgcDst->tile.pixmap); 67135c4bbdfSmrg pgcDst->tileIsPixel = pgcSrc->tileIsPixel; 67235c4bbdfSmrg pgcDst->tile = pgcSrc->tile; 67335c4bbdfSmrg if (!pgcDst->tileIsPixel) 67435c4bbdfSmrg pgcDst->tile.pixmap->refcnt++; 67535c4bbdfSmrg break; 67635c4bbdfSmrg } 67735c4bbdfSmrg case GCStipple: 67835c4bbdfSmrg { 67935c4bbdfSmrg if (pgcDst->stipple == pgcSrc->stipple) 68035c4bbdfSmrg break; 68135c4bbdfSmrg if (pgcDst->stipple) 68235c4bbdfSmrg (*pgcDst->pScreen->DestroyPixmap) (pgcDst->stipple); 68335c4bbdfSmrg pgcDst->stipple = pgcSrc->stipple; 68435c4bbdfSmrg if (pgcDst->stipple) 68535c4bbdfSmrg pgcDst->stipple->refcnt++; 68635c4bbdfSmrg break; 68735c4bbdfSmrg } 68835c4bbdfSmrg case GCTileStipXOrigin: 68935c4bbdfSmrg pgcDst->patOrg.x = pgcSrc->patOrg.x; 69035c4bbdfSmrg break; 69135c4bbdfSmrg case GCTileStipYOrigin: 69235c4bbdfSmrg pgcDst->patOrg.y = pgcSrc->patOrg.y; 69335c4bbdfSmrg break; 69435c4bbdfSmrg case GCFont: 69535c4bbdfSmrg if (pgcDst->font == pgcSrc->font) 69635c4bbdfSmrg break; 69735c4bbdfSmrg if (pgcDst->font) 69835c4bbdfSmrg CloseFont(pgcDst->font, (Font) 0); 69935c4bbdfSmrg if ((pgcDst->font = pgcSrc->font) != NullFont) 70035c4bbdfSmrg (pgcDst->font)->refcnt++; 70135c4bbdfSmrg break; 70235c4bbdfSmrg case GCSubwindowMode: 70335c4bbdfSmrg pgcDst->subWindowMode = pgcSrc->subWindowMode; 70435c4bbdfSmrg break; 70535c4bbdfSmrg case GCGraphicsExposures: 70635c4bbdfSmrg pgcDst->graphicsExposures = pgcSrc->graphicsExposures; 70735c4bbdfSmrg break; 70835c4bbdfSmrg case GCClipXOrigin: 70935c4bbdfSmrg pgcDst->clipOrg.x = pgcSrc->clipOrg.x; 71035c4bbdfSmrg break; 71135c4bbdfSmrg case GCClipYOrigin: 71235c4bbdfSmrg pgcDst->clipOrg.y = pgcSrc->clipOrg.y; 71335c4bbdfSmrg break; 71435c4bbdfSmrg case GCClipMask: 71535c4bbdfSmrg (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc); 71635c4bbdfSmrg break; 71735c4bbdfSmrg case GCDashOffset: 71835c4bbdfSmrg pgcDst->dashOffset = pgcSrc->dashOffset; 71935c4bbdfSmrg break; 72035c4bbdfSmrg case GCDashList: 72135c4bbdfSmrg if (pgcSrc->dash == DefaultDash) { 72235c4bbdfSmrg if (pgcDst->dash != DefaultDash) { 72335c4bbdfSmrg free(pgcDst->dash); 72435c4bbdfSmrg pgcDst->numInDashList = pgcSrc->numInDashList; 72535c4bbdfSmrg pgcDst->dash = pgcSrc->dash; 72635c4bbdfSmrg } 72735c4bbdfSmrg } 72835c4bbdfSmrg else { 72935c4bbdfSmrg unsigned char *dash; 73035c4bbdfSmrg unsigned int i; 73135c4bbdfSmrg 73235c4bbdfSmrg dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); 73335c4bbdfSmrg if (dash) { 73435c4bbdfSmrg if (pgcDst->dash != DefaultDash) 73535c4bbdfSmrg free(pgcDst->dash); 73635c4bbdfSmrg pgcDst->numInDashList = pgcSrc->numInDashList; 73735c4bbdfSmrg pgcDst->dash = dash; 73835c4bbdfSmrg for (i = 0; i < pgcSrc->numInDashList; i++) 73935c4bbdfSmrg dash[i] = pgcSrc->dash[i]; 74035c4bbdfSmrg } 74135c4bbdfSmrg else 74235c4bbdfSmrg error = BadAlloc; 74335c4bbdfSmrg } 74435c4bbdfSmrg break; 74535c4bbdfSmrg case GCArcMode: 74635c4bbdfSmrg pgcDst->arcMode = pgcSrc->arcMode; 74735c4bbdfSmrg break; 74835c4bbdfSmrg default: 74935c4bbdfSmrg FatalError("CopyGC: Unhandled mask!\n"); 75035c4bbdfSmrg } 75105b261ecSmrg } 75235c4bbdfSmrg if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) { 75335c4bbdfSmrg if (!CreateDefaultTile(pgcDst)) { 75435c4bbdfSmrg pgcDst->fillStyle = FillSolid; 75535c4bbdfSmrg error = BadAlloc; 75635c4bbdfSmrg } 75705b261ecSmrg } 75805b261ecSmrg (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); 75905b261ecSmrg return error; 76005b261ecSmrg} 76105b261ecSmrg 76205b261ecSmrg/** 76305b261ecSmrg * does the diX part of freeing the characteristics in the GC. 76405b261ecSmrg * 76505b261ecSmrg * \param value must conform to DeleteType 76605b261ecSmrg */ 7676747b715Smrgint 76835c4bbdfSmrgFreeGC(void *value, XID gid) 76905b261ecSmrg{ 77035c4bbdfSmrg GCPtr pGC = (GCPtr) value; 77105b261ecSmrg 77235c4bbdfSmrg CloseFont(pGC->font, (Font) 0); 77335c4bbdfSmrg (*pGC->funcs->DestroyClip) (pGC); 77405b261ecSmrg 77505b261ecSmrg if (!pGC->tileIsPixel) 77635c4bbdfSmrg (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap); 77705b261ecSmrg if (pGC->stipple) 77835c4bbdfSmrg (*pGC->pScreen->DestroyPixmap) (pGC->stipple); 77905b261ecSmrg 78005b261ecSmrg (*pGC->funcs->DestroyGC) (pGC); 78105b261ecSmrg if (pGC->dash != DefaultDash) 78235c4bbdfSmrg free(pGC->dash); 7836747b715Smrg dixFreeObjectWithPrivates(pGC, PRIVATE_GC); 7846747b715Smrg return Success; 78505b261ecSmrg} 78605b261ecSmrg 78705b261ecSmrg/* CreateScratchGC(pScreen, depth) 78805b261ecSmrg like CreateGC, but doesn't do the default tile or stipple, 78905b261ecSmrgsince we can't create them without already having a GC. any code 79005b261ecSmrgusing the tile or stipple has to set them explicitly anyway, 79105b261ecSmrgsince the state of the scratch gc is unknown. This is OK 79205b261ecSmrgbecause ChangeGC() has to be able to deal with NULL tiles and 79335c4bbdfSmrgstipples anyway (in case the CreateGC() call has provided a 79405b261ecSmrgvalue for them -- we can't set the default tile until the 79505b261ecSmrgclient-supplied attributes are installed, since the fgPixel 79605b261ecSmrgis what fills the default tile. (maybe this comment should 79705b261ecSmrggo with CreateGC() or ChangeGC().) 79805b261ecSmrg*/ 79905b261ecSmrg 8009ace9065Smrgstatic GCPtr 80105b261ecSmrgCreateScratchGC(ScreenPtr pScreen, unsigned depth) 80205b261ecSmrg{ 80305b261ecSmrg GCPtr pGC; 80405b261ecSmrg 80535c4bbdfSmrg pGC = NewGCObject(pScreen, depth); 80605b261ecSmrg if (!pGC) 80735c4bbdfSmrg return (GCPtr) NULL; 8086747b715Smrg 8096747b715Smrg pGC->stateChanges = GCAllBits; 81035c4bbdfSmrg if (!(*pScreen->CreateGC) (pGC)) { 81135c4bbdfSmrg FreeGC(pGC, (XID) 0); 81235c4bbdfSmrg pGC = (GCPtr) NULL; 81305b261ecSmrg } 81458cf2af7Smrg else 81558cf2af7Smrg pGC->graphicsExposures = FALSE; 81605b261ecSmrg return pGC; 81705b261ecSmrg} 81805b261ecSmrg 81905b261ecSmrgvoid 82005b261ecSmrgFreeGCperDepth(int screenNum) 82105b261ecSmrg{ 82205b261ecSmrg int i; 82305b261ecSmrg ScreenPtr pScreen; 82405b261ecSmrg GCPtr *ppGC; 82505b261ecSmrg 82605b261ecSmrg pScreen = screenInfo.screens[screenNum]; 82705b261ecSmrg ppGC = pScreen->GCperDepth; 82805b261ecSmrg 82935c4bbdfSmrg for (i = 0; i <= pScreen->numDepths; i++) { 83035c4bbdfSmrg (void) FreeGC(ppGC[i], (XID) 0); 83135c4bbdfSmrg ppGC[i] = NULL; 8326747b715Smrg } 83305b261ecSmrg} 83405b261ecSmrg 83505b261ecSmrgBool 83605b261ecSmrgCreateGCperDepth(int screenNum) 83705b261ecSmrg{ 83805b261ecSmrg int i; 83905b261ecSmrg ScreenPtr pScreen; 84005b261ecSmrg DepthPtr pDepth; 84105b261ecSmrg GCPtr *ppGC; 84205b261ecSmrg 84305b261ecSmrg pScreen = screenInfo.screens[screenNum]; 84405b261ecSmrg ppGC = pScreen->GCperDepth; 84505b261ecSmrg /* do depth 1 separately because it's not included in list */ 84605b261ecSmrg if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) 84735c4bbdfSmrg return FALSE; 84805b261ecSmrg /* Make sure we don't overflow GCperDepth[] */ 84935c4bbdfSmrg if (pScreen->numDepths > MAXFORMATS) 85035c4bbdfSmrg return FALSE; 85105b261ecSmrg 85205b261ecSmrg pDepth = pScreen->allowedDepths; 85335c4bbdfSmrg for (i = 0; i < pScreen->numDepths; i++, pDepth++) { 85435c4bbdfSmrg if (!(ppGC[i + 1] = CreateScratchGC(pScreen, pDepth->depth))) { 85535c4bbdfSmrg for (; i >= 0; i--) 85635c4bbdfSmrg (void) FreeGC(ppGC[i], (XID) 0); 85735c4bbdfSmrg return FALSE; 85835c4bbdfSmrg } 85905b261ecSmrg } 86005b261ecSmrg return TRUE; 86105b261ecSmrg} 86205b261ecSmrg 86305b261ecSmrgBool 86405b261ecSmrgCreateDefaultStipple(int screenNum) 86505b261ecSmrg{ 86605b261ecSmrg ScreenPtr pScreen; 8676747b715Smrg ChangeGCVal tmpval[3]; 86805b261ecSmrg xRectangle rect; 86905b261ecSmrg CARD16 w, h; 87005b261ecSmrg GCPtr pgcScratch; 87105b261ecSmrg 87205b261ecSmrg pScreen = screenInfo.screens[screenNum]; 87305b261ecSmrg 87405b261ecSmrg w = 16; 87505b261ecSmrg h = 16; 87635c4bbdfSmrg (*pScreen->QueryBestSize) (StippleShape, &w, &h, pScreen); 8771b5d61b8Smrg if (!(pScreen->defaultStipple = pScreen->CreatePixmap(pScreen, w, h, 1, 0))) 87835c4bbdfSmrg return FALSE; 87905b261ecSmrg /* fill stipple with 1 */ 8806747b715Smrg tmpval[0].val = GXcopy; 8816747b715Smrg tmpval[1].val = 1; 8826747b715Smrg tmpval[2].val = FillSolid; 88305b261ecSmrg pgcScratch = GetScratchGC(1, pScreen); 88435c4bbdfSmrg if (!pgcScratch) { 8851b5d61b8Smrg (*pScreen->DestroyPixmap) (pScreen->defaultStipple); 88635c4bbdfSmrg return FALSE; 88705b261ecSmrg } 88835c4bbdfSmrg (void) ChangeGC(NullClient, pgcScratch, 88935c4bbdfSmrg GCFunction | GCForeground | GCFillStyle, tmpval); 8901b5d61b8Smrg ValidateGC((DrawablePtr) pScreen->defaultStipple, pgcScratch); 89105b261ecSmrg rect.x = 0; 89205b261ecSmrg rect.y = 0; 89305b261ecSmrg rect.width = w; 89405b261ecSmrg rect.height = h; 8951b5d61b8Smrg (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pScreen->defaultStipple, 89635c4bbdfSmrg pgcScratch, 1, &rect); 89705b261ecSmrg FreeScratchGC(pgcScratch); 89805b261ecSmrg return TRUE; 89905b261ecSmrg} 90005b261ecSmrg 90105b261ecSmrgvoid 90205b261ecSmrgFreeDefaultStipple(int screenNum) 90305b261ecSmrg{ 90405b261ecSmrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 90535c4bbdfSmrg 9061b5d61b8Smrg (*pScreen->DestroyPixmap) (pScreen->defaultStipple); 90705b261ecSmrg} 90805b261ecSmrg 9094642e01fSmrgint 91005b261ecSmrgSetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) 91105b261ecSmrg{ 91205b261ecSmrg long i; 91305b261ecSmrg unsigned char *p, *indash; 91405b261ecSmrg BITS32 maskQ = 0; 91505b261ecSmrg 91605b261ecSmrg i = ndash; 91705b261ecSmrg p = pdash; 91835c4bbdfSmrg while (i--) { 91935c4bbdfSmrg if (!*p++) { 92035c4bbdfSmrg /* dash segment must be > 0 */ 92135c4bbdfSmrg return BadValue; 92235c4bbdfSmrg } 92305b261ecSmrg } 92405b261ecSmrg 92505b261ecSmrg if (ndash & 1) 92635c4bbdfSmrg p = malloc(2 * ndash * sizeof(unsigned char)); 92705b261ecSmrg else 92835c4bbdfSmrg p = malloc(ndash * sizeof(unsigned char)); 92905b261ecSmrg if (!p) 93035c4bbdfSmrg return BadAlloc; 93105b261ecSmrg 93205b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 93335c4bbdfSmrg if (offset != pGC->dashOffset) { 93435c4bbdfSmrg pGC->dashOffset = offset; 93535c4bbdfSmrg pGC->stateChanges |= GCDashOffset; 93635c4bbdfSmrg maskQ |= GCDashOffset; 93705b261ecSmrg } 93805b261ecSmrg 93905b261ecSmrg if (pGC->dash != DefaultDash) 94035c4bbdfSmrg free(pGC->dash); 94105b261ecSmrg pGC->numInDashList = ndash; 94205b261ecSmrg pGC->dash = p; 94335c4bbdfSmrg if (ndash & 1) { 94435c4bbdfSmrg pGC->numInDashList += ndash; 94535c4bbdfSmrg indash = pdash; 94635c4bbdfSmrg i = ndash; 94735c4bbdfSmrg while (i--) 94835c4bbdfSmrg *p++ = *indash++; 94905b261ecSmrg } 95035c4bbdfSmrg while (ndash--) 95135c4bbdfSmrg *p++ = *pdash++; 95205b261ecSmrg pGC->stateChanges |= GCDashList; 95305b261ecSmrg maskQ |= GCDashList; 95405b261ecSmrg 95505b261ecSmrg if (pGC->funcs->ChangeGC) 95635c4bbdfSmrg (*pGC->funcs->ChangeGC) (pGC, maskQ); 95705b261ecSmrg return Success; 95805b261ecSmrg} 95905b261ecSmrg 9606747b715Smrgint 96105b261ecSmrgVerifyRectOrder(int nrects, xRectangle *prects, int ordering) 96205b261ecSmrg{ 96335c4bbdfSmrg xRectangle *prectP, *prectN; 96435c4bbdfSmrg int i; 96535c4bbdfSmrg 96635c4bbdfSmrg switch (ordering) { 96735c4bbdfSmrg case Unsorted: 96835c4bbdfSmrg return CT_UNSORTED; 96935c4bbdfSmrg case YSorted: 97035c4bbdfSmrg if (nrects > 1) { 97135c4bbdfSmrg for (i = 1, prectP = prects, prectN = prects + 1; 97235c4bbdfSmrg i < nrects; i++, prectP++, prectN++) 97335c4bbdfSmrg if (prectN->y < prectP->y) 97435c4bbdfSmrg return -1; 97535c4bbdfSmrg } 97635c4bbdfSmrg return CT_YSORTED; 97735c4bbdfSmrg case YXSorted: 97835c4bbdfSmrg if (nrects > 1) { 97935c4bbdfSmrg for (i = 1, prectP = prects, prectN = prects + 1; 98035c4bbdfSmrg i < nrects; i++, prectP++, prectN++) 98135c4bbdfSmrg if ((prectN->y < prectP->y) || 98235c4bbdfSmrg ((prectN->y == prectP->y) && (prectN->x < prectP->x))) 98335c4bbdfSmrg return -1; 98435c4bbdfSmrg } 98535c4bbdfSmrg return CT_YXSORTED; 98635c4bbdfSmrg case YXBanded: 98735c4bbdfSmrg if (nrects > 1) { 98835c4bbdfSmrg for (i = 1, prectP = prects, prectN = prects + 1; 98935c4bbdfSmrg i < nrects; i++, prectP++, prectN++) 99035c4bbdfSmrg if ((prectN->y != prectP->y && 99135c4bbdfSmrg prectN->y < prectP->y + (int) prectP->height) || 99235c4bbdfSmrg ((prectN->y == prectP->y) && 99335c4bbdfSmrg (prectN->height != prectP->height || 99435c4bbdfSmrg prectN->x < prectP->x + (int) prectP->width))) 99535c4bbdfSmrg return -1; 99635c4bbdfSmrg } 99735c4bbdfSmrg return CT_YXBANDED; 99805b261ecSmrg } 99905b261ecSmrg return -1; 100005b261ecSmrg} 100105b261ecSmrg 10024642e01fSmrgint 100335c4bbdfSmrgSetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, 100405b261ecSmrg xRectangle *prects, int ordering) 100505b261ecSmrg{ 100635c4bbdfSmrg int newct, size; 100735c4bbdfSmrg xRectangle *prectsNew; 100805b261ecSmrg 100905b261ecSmrg newct = VerifyRectOrder(nrects, prects, ordering); 101005b261ecSmrg if (newct < 0) 101135c4bbdfSmrg return BadMatch; 101205b261ecSmrg size = nrects * sizeof(xRectangle); 10136747b715Smrg prectsNew = malloc(size); 101405b261ecSmrg if (!prectsNew && size) 101535c4bbdfSmrg return BadAlloc; 101605b261ecSmrg 101705b261ecSmrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 101805b261ecSmrg pGC->clipOrg.x = xOrigin; 101905b261ecSmrg pGC->stateChanges |= GCClipXOrigin; 102035c4bbdfSmrg 102105b261ecSmrg pGC->clipOrg.y = yOrigin; 102205b261ecSmrg pGC->stateChanges |= GCClipYOrigin; 102305b261ecSmrg 102405b261ecSmrg if (size) 102535c4bbdfSmrg memmove((char *) prectsNew, (char *) prects, size); 102635c4bbdfSmrg (*pGC->funcs->ChangeClip) (pGC, newct, (void *) prectsNew, nrects); 102705b261ecSmrg if (pGC->funcs->ChangeGC) 102835c4bbdfSmrg (*pGC->funcs->ChangeGC) (pGC, 102935c4bbdfSmrg GCClipXOrigin | GCClipYOrigin | GCClipMask); 103005b261ecSmrg return Success; 103105b261ecSmrg} 103205b261ecSmrg 103305b261ecSmrg/* 103435c4bbdfSmrg sets reasonable defaults 103505b261ecSmrg if we can get a pre-allocated one, use it and mark it as used. 103605b261ecSmrg if we can't, create one out of whole cloth (The Velveteen GC -- if 103705b261ecSmrg you use it often enough it will become real.) 103805b261ecSmrg*/ 10396747b715SmrgGCPtr 104005b261ecSmrgGetScratchGC(unsigned depth, ScreenPtr pScreen) 104105b261ecSmrg{ 104205b261ecSmrg int i; 104305b261ecSmrg GCPtr pGC; 104405b261ecSmrg 104535c4bbdfSmrg for (i = 0; i <= pScreen->numDepths; i++) { 104635c4bbdfSmrg pGC = pScreen->GCperDepth[i]; 104735c4bbdfSmrg if (pGC && pGC->depth == depth && !pGC->scratch_inuse) { 104835c4bbdfSmrg pGC->scratch_inuse = TRUE; 104935c4bbdfSmrg 105035c4bbdfSmrg pGC->alu = GXcopy; 105135c4bbdfSmrg pGC->planemask = ~0; 105235c4bbdfSmrg pGC->serialNumber = 0; 105335c4bbdfSmrg pGC->fgPixel = 0; 105435c4bbdfSmrg pGC->bgPixel = 1; 105535c4bbdfSmrg pGC->lineWidth = 0; 105635c4bbdfSmrg pGC->lineStyle = LineSolid; 105735c4bbdfSmrg pGC->capStyle = CapButt; 105835c4bbdfSmrg pGC->joinStyle = JoinMiter; 105935c4bbdfSmrg pGC->fillStyle = FillSolid; 106035c4bbdfSmrg pGC->fillRule = EvenOddRule; 106135c4bbdfSmrg pGC->arcMode = ArcChord; 106235c4bbdfSmrg pGC->patOrg.x = 0; 106335c4bbdfSmrg pGC->patOrg.y = 0; 106435c4bbdfSmrg pGC->subWindowMode = ClipByChildren; 106535c4bbdfSmrg pGC->graphicsExposures = FALSE; 106635c4bbdfSmrg pGC->clipOrg.x = 0; 106735c4bbdfSmrg pGC->clipOrg.y = 0; 106835c4bbdfSmrg if (pGC->clientClip) 106935c4bbdfSmrg (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); 107035c4bbdfSmrg pGC->stateChanges = GCAllBits; 107135c4bbdfSmrg return pGC; 107235c4bbdfSmrg } 10736747b715Smrg } 107405b261ecSmrg /* if we make it this far, need to roll our own */ 10751b5d61b8Smrg return CreateScratchGC(pScreen, depth); 107605b261ecSmrg} 107705b261ecSmrg 107805b261ecSmrg/* 107905b261ecSmrg if the gc to free is in the table of pre-existing ones, 108005b261ecSmrgmark it as available. 108105b261ecSmrg if not, free it for real 108205b261ecSmrg*/ 10836747b715Smrgvoid 108405b261ecSmrgFreeScratchGC(GCPtr pGC) 108505b261ecSmrg{ 10866747b715Smrg if (pGC->scratch_inuse) 108735c4bbdfSmrg pGC->scratch_inuse = FALSE; 10886747b715Smrg else 108935c4bbdfSmrg FreeGC(pGC, (GContext) 0); 109005b261ecSmrg} 1091