1706f2543Smrg/*********************************************************** 2706f2543Smrg 3706f2543SmrgCopyright 1987, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included in 12706f2543Smrgall copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20706f2543Smrg 21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 23706f2543Smrgin this Software without prior written authorization from The Open Group. 24706f2543Smrg 25706f2543Smrg 26706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 27706f2543Smrg 28706f2543Smrg All Rights Reserved 29706f2543Smrg 30706f2543SmrgPermission to use, copy, modify, and distribute this software and its 31706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 32706f2543Smrgprovided that the above copyright notice appear in all copies and that 33706f2543Smrgboth that copyright notice and this permission notice appear in 34706f2543Smrgsupporting documentation, and that the name of Digital not be 35706f2543Smrgused in advertising or publicity pertaining to distribution of the 36706f2543Smrgsoftware without specific, written prior permission. 37706f2543Smrg 38706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44706f2543SmrgSOFTWARE. 45706f2543Smrg 46706f2543Smrg******************************************************************/ 47706f2543Smrg 48706f2543Smrg 49706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 50706f2543Smrg#include <dix-config.h> 51706f2543Smrg#endif 52706f2543Smrg 53706f2543Smrg#include <X11/X.h> 54706f2543Smrg#include <X11/Xmd.h> 55706f2543Smrg#include <X11/Xproto.h> 56706f2543Smrg#include "misc.h" 57706f2543Smrg#include "resource.h" 58706f2543Smrg#include "gcstruct.h" 59706f2543Smrg#include "pixmapstr.h" 60706f2543Smrg#include "dixfontstr.h" 61706f2543Smrg#include "scrnintstr.h" 62706f2543Smrg#include "region.h" 63706f2543Smrg#include "dixstruct.h" 64706f2543Smrg 65706f2543Smrg#include "privates.h" 66706f2543Smrg#include "dix.h" 67706f2543Smrg#include "xace.h" 68706f2543Smrg#include <assert.h> 69706f2543Smrg 70706f2543Smrgextern FontPtr defaultFont; 71706f2543Smrg 72706f2543Smrgstatic Bool CreateDefaultTile(GCPtr pGC); 73706f2543Smrg 74706f2543Smrgstatic unsigned char DefaultDash[2] = {4, 4}; 75706f2543Smrg 76706f2543Smrgvoid 77706f2543SmrgValidateGC(DrawablePtr pDraw, GC *pGC) 78706f2543Smrg{ 79706f2543Smrg (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); 80706f2543Smrg pGC->stateChanges = 0; 81706f2543Smrg pGC->serialNumber = pDraw->serialNumber; 82706f2543Smrg} 83706f2543Smrg 84706f2543Smrg 85706f2543Smrg/* 86706f2543Smrg * ChangeGC/ChangeGCXIDs: 87706f2543Smrg * 88706f2543Smrg * The client performing the gc change must be passed so that access 89706f2543Smrg * checks can be performed on any tiles, stipples, or fonts that are 90706f2543Smrg * specified. ddxen can call this too; they should normally pass 91706f2543Smrg * NullClient for the client since any access checking should have 92706f2543Smrg * already been done at a higher level. 93706f2543Smrg * 94706f2543Smrg * If you have any XIDs, you must use ChangeGCXIDs: 95706f2543Smrg * 96706f2543Smrg * CARD32 v[2]; 97706f2543Smrg * v[0] = FillTiled; 98706f2543Smrg * v[1] = pid; 99706f2543Smrg * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); 100706f2543Smrg * 101706f2543Smrg * However, if you need to pass a pointer to a pixmap or font, you must 102706f2543Smrg * use ChangeGC: 103706f2543Smrg * 104706f2543Smrg * ChangeGCVal v[2]; 105706f2543Smrg * v[0].val = FillTiled; 106706f2543Smrg * v[1].ptr = pPixmap; 107706f2543Smrg * ChangeGC(client, pGC, GCFillStyle|GCTile, v); 108706f2543Smrg * 109706f2543Smrg * If you have neither XIDs nor pointers, you can use either function, 110706f2543Smrg * but ChangeGC will do less work. 111706f2543Smrg * 112706f2543Smrg * ChangeGCVal v[2]; 113706f2543Smrg * v[0].val = foreground; 114706f2543Smrg * v[1].val = background; 115706f2543Smrg * ChangeGC(client, pGC, GCForeground|GCBackground, v); 116706f2543Smrg */ 117706f2543Smrg 118706f2543Smrg#define NEXTVAL(_type, _var) { \ 119706f2543Smrg _var = (_type)(pUnion->val); pUnion++; \ 120706f2543Smrg } 121706f2543Smrg 122706f2543Smrg#define NEXT_PTR(_type, _var) { \ 123706f2543Smrg _var = (_type)pUnion->ptr; pUnion++; } 124706f2543Smrg 125706f2543Smrgint 126706f2543SmrgChangeGC(ClientPtr client, GC *pGC, BITS32 mask, ChangeGCValPtr pUnion) 127706f2543Smrg{ 128706f2543Smrg BITS32 index2; 129706f2543Smrg int error = 0; 130706f2543Smrg PixmapPtr pPixmap; 131706f2543Smrg BITS32 maskQ; 132706f2543Smrg 133706f2543Smrg assert(pUnion); 134706f2543Smrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 135706f2543Smrg 136706f2543Smrg maskQ = mask; /* save these for when we walk the GCque */ 137706f2543Smrg while (mask && !error) 138706f2543Smrg { 139706f2543Smrg index2 = (BITS32) lowbit (mask); 140706f2543Smrg mask &= ~index2; 141706f2543Smrg pGC->stateChanges |= index2; 142706f2543Smrg switch (index2) 143706f2543Smrg { 144706f2543Smrg case GCFunction: 145706f2543Smrg { 146706f2543Smrg CARD8 newalu; 147706f2543Smrg NEXTVAL(CARD8, newalu); 148706f2543Smrg if (newalu <= GXset) 149706f2543Smrg pGC->alu = newalu; 150706f2543Smrg else 151706f2543Smrg { 152706f2543Smrg if (client) 153706f2543Smrg client->errorValue = newalu; 154706f2543Smrg error = BadValue; 155706f2543Smrg } 156706f2543Smrg break; 157706f2543Smrg } 158706f2543Smrg case GCPlaneMask: 159706f2543Smrg NEXTVAL(unsigned long, pGC->planemask); 160706f2543Smrg break; 161706f2543Smrg case GCForeground: 162706f2543Smrg NEXTVAL(unsigned long, pGC->fgPixel); 163706f2543Smrg /* 164706f2543Smrg * this is for CreateGC 165706f2543Smrg */ 166706f2543Smrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 167706f2543Smrg { 168706f2543Smrg pGC->tileIsPixel = TRUE; 169706f2543Smrg pGC->tile.pixel = pGC->fgPixel; 170706f2543Smrg } 171706f2543Smrg break; 172706f2543Smrg case GCBackground: 173706f2543Smrg NEXTVAL(unsigned long, pGC->bgPixel); 174706f2543Smrg break; 175706f2543Smrg case GCLineWidth: /* ??? line width is a CARD16 */ 176706f2543Smrg NEXTVAL(CARD16, pGC->lineWidth); 177706f2543Smrg break; 178706f2543Smrg case GCLineStyle: 179706f2543Smrg { 180706f2543Smrg unsigned int newlinestyle; 181706f2543Smrg NEXTVAL(unsigned int, newlinestyle); 182706f2543Smrg if (newlinestyle <= LineDoubleDash) 183706f2543Smrg pGC->lineStyle = newlinestyle; 184706f2543Smrg else 185706f2543Smrg { 186706f2543Smrg if (client) 187706f2543Smrg client->errorValue = newlinestyle; 188706f2543Smrg error = BadValue; 189706f2543Smrg } 190706f2543Smrg break; 191706f2543Smrg } 192706f2543Smrg case GCCapStyle: 193706f2543Smrg { 194706f2543Smrg unsigned int newcapstyle; 195706f2543Smrg NEXTVAL(unsigned int, newcapstyle); 196706f2543Smrg if (newcapstyle <= CapProjecting) 197706f2543Smrg pGC->capStyle = newcapstyle; 198706f2543Smrg else 199706f2543Smrg { 200706f2543Smrg if (client) 201706f2543Smrg client->errorValue = newcapstyle; 202706f2543Smrg error = BadValue; 203706f2543Smrg } 204706f2543Smrg break; 205706f2543Smrg } 206706f2543Smrg case GCJoinStyle: 207706f2543Smrg { 208706f2543Smrg unsigned int newjoinstyle; 209706f2543Smrg NEXTVAL(unsigned int, newjoinstyle); 210706f2543Smrg if (newjoinstyle <= JoinBevel) 211706f2543Smrg pGC->joinStyle = newjoinstyle; 212706f2543Smrg else 213706f2543Smrg { 214706f2543Smrg if (client) 215706f2543Smrg client->errorValue = newjoinstyle; 216706f2543Smrg error = BadValue; 217706f2543Smrg } 218706f2543Smrg break; 219706f2543Smrg } 220706f2543Smrg case GCFillStyle: 221706f2543Smrg { 222706f2543Smrg unsigned int newfillstyle; 223706f2543Smrg NEXTVAL(unsigned int, newfillstyle); 224706f2543Smrg if (newfillstyle <= FillOpaqueStippled) 225706f2543Smrg pGC->fillStyle = newfillstyle; 226706f2543Smrg else 227706f2543Smrg { 228706f2543Smrg if (client) 229706f2543Smrg client->errorValue = newfillstyle; 230706f2543Smrg error = BadValue; 231706f2543Smrg } 232706f2543Smrg break; 233706f2543Smrg } 234706f2543Smrg case GCFillRule: 235706f2543Smrg { 236706f2543Smrg unsigned int newfillrule; 237706f2543Smrg NEXTVAL(unsigned int, newfillrule); 238706f2543Smrg if (newfillrule <= WindingRule) 239706f2543Smrg pGC->fillRule = newfillrule; 240706f2543Smrg else 241706f2543Smrg { 242706f2543Smrg if (client) 243706f2543Smrg client->errorValue = newfillrule; 244706f2543Smrg error = BadValue; 245706f2543Smrg } 246706f2543Smrg break; 247706f2543Smrg } 248706f2543Smrg case GCTile: 249706f2543Smrg NEXT_PTR(PixmapPtr, pPixmap); 250706f2543Smrg if ((pPixmap->drawable.depth != pGC->depth) || 251706f2543Smrg (pPixmap->drawable.pScreen != pGC->pScreen)) 252706f2543Smrg { 253706f2543Smrg error = BadMatch; 254706f2543Smrg } 255706f2543Smrg else 256706f2543Smrg { 257706f2543Smrg pPixmap->refcnt++; 258706f2543Smrg if (!pGC->tileIsPixel) 259706f2543Smrg (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); 260706f2543Smrg pGC->tileIsPixel = FALSE; 261706f2543Smrg pGC->tile.pixmap = pPixmap; 262706f2543Smrg } 263706f2543Smrg break; 264706f2543Smrg case GCStipple: 265706f2543Smrg NEXT_PTR(PixmapPtr, pPixmap); 266706f2543Smrg if ((pPixmap->drawable.depth != 1) || 267706f2543Smrg (pPixmap->drawable.pScreen != pGC->pScreen)) 268706f2543Smrg { 269706f2543Smrg error = BadMatch; 270706f2543Smrg } 271706f2543Smrg else 272706f2543Smrg { 273706f2543Smrg pPixmap->refcnt++; 274706f2543Smrg if (pGC->stipple) 275706f2543Smrg (* pGC->pScreen->DestroyPixmap)(pGC->stipple); 276706f2543Smrg pGC->stipple = pPixmap; 277706f2543Smrg } 278706f2543Smrg break; 279706f2543Smrg case GCTileStipXOrigin: 280706f2543Smrg NEXTVAL(INT16, pGC->patOrg.x); 281706f2543Smrg break; 282706f2543Smrg case GCTileStipYOrigin: 283706f2543Smrg NEXTVAL(INT16, pGC->patOrg.y); 284706f2543Smrg break; 285706f2543Smrg case GCFont: 286706f2543Smrg { 287706f2543Smrg FontPtr pFont; 288706f2543Smrg NEXT_PTR(FontPtr, pFont); 289706f2543Smrg pFont->refcnt++; 290706f2543Smrg if (pGC->font) 291706f2543Smrg CloseFont(pGC->font, (Font)0); 292706f2543Smrg pGC->font = pFont; 293706f2543Smrg break; 294706f2543Smrg } 295706f2543Smrg case GCSubwindowMode: 296706f2543Smrg { 297706f2543Smrg unsigned int newclipmode; 298706f2543Smrg NEXTVAL(unsigned int, newclipmode); 299706f2543Smrg if (newclipmode <= IncludeInferiors) 300706f2543Smrg pGC->subWindowMode = newclipmode; 301706f2543Smrg else 302706f2543Smrg { 303706f2543Smrg if (client) 304706f2543Smrg client->errorValue = newclipmode; 305706f2543Smrg error = BadValue; 306706f2543Smrg } 307706f2543Smrg break; 308706f2543Smrg } 309706f2543Smrg case GCGraphicsExposures: 310706f2543Smrg { 311706f2543Smrg unsigned int newge; 312706f2543Smrg NEXTVAL(unsigned int, newge); 313706f2543Smrg if (newge <= xTrue) 314706f2543Smrg pGC->graphicsExposures = newge; 315706f2543Smrg else 316706f2543Smrg { 317706f2543Smrg if (client) 318706f2543Smrg client->errorValue = newge; 319706f2543Smrg error = BadValue; 320706f2543Smrg } 321706f2543Smrg break; 322706f2543Smrg } 323706f2543Smrg case GCClipXOrigin: 324706f2543Smrg NEXTVAL(INT16, pGC->clipOrg.x); 325706f2543Smrg break; 326706f2543Smrg case GCClipYOrigin: 327706f2543Smrg NEXTVAL(INT16, pGC->clipOrg.y); 328706f2543Smrg break; 329706f2543Smrg case GCClipMask: 330706f2543Smrg NEXT_PTR(PixmapPtr, pPixmap); 331706f2543Smrg if (pPixmap) 332706f2543Smrg { 333706f2543Smrg if ((pPixmap->drawable.depth != 1) || 334706f2543Smrg (pPixmap->drawable.pScreen != pGC->pScreen)) 335706f2543Smrg { 336706f2543Smrg error = BadMatch; 337706f2543Smrg break; 338706f2543Smrg } 339706f2543Smrg pPixmap->refcnt++; 340706f2543Smrg } 341706f2543Smrg (*pGC->funcs->ChangeClip)(pGC, pPixmap ? CT_PIXMAP : CT_NONE, 342706f2543Smrg (pointer)pPixmap, 0); 343706f2543Smrg break; 344706f2543Smrg case GCDashOffset: 345706f2543Smrg NEXTVAL(INT16, pGC->dashOffset); 346706f2543Smrg break; 347706f2543Smrg case GCDashList: 348706f2543Smrg { 349706f2543Smrg CARD8 newdash; 350706f2543Smrg NEXTVAL(CARD8, newdash); 351706f2543Smrg if (newdash == 4) 352706f2543Smrg { 353706f2543Smrg if (pGC->dash != DefaultDash) 354706f2543Smrg { 355706f2543Smrg free(pGC->dash); 356706f2543Smrg pGC->numInDashList = 2; 357706f2543Smrg pGC->dash = DefaultDash; 358706f2543Smrg } 359706f2543Smrg } 360706f2543Smrg else if (newdash != 0) 361706f2543Smrg { 362706f2543Smrg unsigned char *dash; 363706f2543Smrg 364706f2543Smrg dash = malloc(2 * sizeof(unsigned char)); 365706f2543Smrg if (dash) 366706f2543Smrg { 367706f2543Smrg if (pGC->dash != DefaultDash) 368706f2543Smrg free(pGC->dash); 369706f2543Smrg pGC->numInDashList = 2; 370706f2543Smrg pGC->dash = dash; 371706f2543Smrg dash[0] = newdash; 372706f2543Smrg dash[1] = newdash; 373706f2543Smrg } 374706f2543Smrg else 375706f2543Smrg error = BadAlloc; 376706f2543Smrg } 377706f2543Smrg else 378706f2543Smrg { 379706f2543Smrg if (client) 380706f2543Smrg client->errorValue = newdash; 381706f2543Smrg error = BadValue; 382706f2543Smrg } 383706f2543Smrg break; 384706f2543Smrg } 385706f2543Smrg case GCArcMode: 386706f2543Smrg { 387706f2543Smrg unsigned int newarcmode; 388706f2543Smrg NEXTVAL(unsigned int, newarcmode); 389706f2543Smrg if (newarcmode <= ArcPieSlice) 390706f2543Smrg pGC->arcMode = newarcmode; 391706f2543Smrg else 392706f2543Smrg { 393706f2543Smrg if (client) 394706f2543Smrg client->errorValue = newarcmode; 395706f2543Smrg error = BadValue; 396706f2543Smrg } 397706f2543Smrg break; 398706f2543Smrg } 399706f2543Smrg default: 400706f2543Smrg if (client) 401706f2543Smrg client->errorValue = maskQ; 402706f2543Smrg error = BadValue; 403706f2543Smrg break; 404706f2543Smrg } 405706f2543Smrg } /* end while mask && !error */ 406706f2543Smrg 407706f2543Smrg if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) 408706f2543Smrg { 409706f2543Smrg if (!CreateDefaultTile (pGC)) 410706f2543Smrg { 411706f2543Smrg pGC->fillStyle = FillSolid; 412706f2543Smrg error = BadAlloc; 413706f2543Smrg } 414706f2543Smrg } 415706f2543Smrg (*pGC->funcs->ChangeGC)(pGC, maskQ); 416706f2543Smrg return error; 417706f2543Smrg} 418706f2543Smrg 419706f2543Smrg#undef NEXTVAL 420706f2543Smrg#undef NEXT_PTR 421706f2543Smrg 422706f2543Smrgstatic const struct { 423706f2543Smrg BITS32 mask; 424706f2543Smrg RESTYPE type; 425706f2543Smrg Mask access_mode; 426706f2543Smrg} xidfields[] = { 427706f2543Smrg { GCTile, RT_PIXMAP, DixReadAccess }, 428706f2543Smrg { GCStipple, RT_PIXMAP, DixReadAccess }, 429706f2543Smrg { GCFont, RT_FONT, DixUseAccess }, 430706f2543Smrg { GCClipMask, RT_PIXMAP, DixReadAccess }, 431706f2543Smrg}; 432706f2543Smrg 433706f2543Smrgint 434706f2543SmrgChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32) 435706f2543Smrg{ 436706f2543Smrg ChangeGCVal vals[GCLastBit + 1]; 437706f2543Smrg int i; 438706f2543Smrg if (mask & ~GCAllBits) 439706f2543Smrg { 440706f2543Smrg client->errorValue = mask; 441706f2543Smrg return BadValue; 442706f2543Smrg } 443706f2543Smrg for (i = Ones(mask); i--; ) 444706f2543Smrg vals[i].val = pC32[i]; 445706f2543Smrg for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) 446706f2543Smrg { 447706f2543Smrg int offset, rc; 448706f2543Smrg if (!(mask & xidfields[i].mask)) 449706f2543Smrg continue; 450706f2543Smrg offset = Ones(mask & (xidfields[i].mask - 1)); 451706f2543Smrg if (xidfields[i].mask == GCClipMask && vals[offset].val == None) 452706f2543Smrg { 453706f2543Smrg vals[offset].ptr = NullPixmap; 454706f2543Smrg continue; 455706f2543Smrg } 456706f2543Smrg rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, 457706f2543Smrg xidfields[i].type, client, xidfields[i].access_mode); 458706f2543Smrg if (rc != Success) 459706f2543Smrg { 460706f2543Smrg client->errorValue = vals[offset].val; 461706f2543Smrg return rc; 462706f2543Smrg } 463706f2543Smrg } 464706f2543Smrg return ChangeGC(client, pGC, mask, vals); 465706f2543Smrg} 466706f2543Smrg 467706f2543Smrg/* CreateGC(pDrawable, mask, pval, pStatus) 468706f2543Smrg creates a default GC for the given drawable, using mask to fill 469706f2543Smrg in any non-default values. 470706f2543Smrg Returns a pointer to the new GC on success, NULL otherwise. 471706f2543Smrg returns status of non-default fields in pStatus 472706f2543SmrgBUG: 473706f2543Smrg should check for failure to create default tile 474706f2543Smrg 475706f2543Smrg*/ 476706f2543SmrgGCPtr 477706f2543SmrgCreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, 478706f2543Smrg XID gcid, ClientPtr client) 479706f2543Smrg{ 480706f2543Smrg GCPtr pGC; 481706f2543Smrg 482706f2543Smrg pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC); 483706f2543Smrg if (!pGC) 484706f2543Smrg { 485706f2543Smrg *pStatus = BadAlloc; 486706f2543Smrg return (GCPtr)NULL; 487706f2543Smrg } 488706f2543Smrg 489706f2543Smrg pGC->pScreen = pDrawable->pScreen; 490706f2543Smrg pGC->depth = pDrawable->depth; 491706f2543Smrg pGC->alu = GXcopy; /* dst <- src */ 492706f2543Smrg pGC->planemask = ~0; 493706f2543Smrg pGC->serialNumber = GC_CHANGE_SERIAL_BIT; 494706f2543Smrg pGC->funcs = 0; 495706f2543Smrg pGC->fgPixel = 0; 496706f2543Smrg pGC->bgPixel = 1; 497706f2543Smrg pGC->lineWidth = 0; 498706f2543Smrg pGC->lineStyle = LineSolid; 499706f2543Smrg pGC->capStyle = CapButt; 500706f2543Smrg pGC->joinStyle = JoinMiter; 501706f2543Smrg pGC->fillStyle = FillSolid; 502706f2543Smrg pGC->fillRule = EvenOddRule; 503706f2543Smrg pGC->arcMode = ArcPieSlice; 504706f2543Smrg pGC->tile.pixel = 0; 505706f2543Smrg pGC->tile.pixmap = NullPixmap; 506706f2543Smrg if (mask & GCForeground) 507706f2543Smrg { 508706f2543Smrg /* 509706f2543Smrg * magic special case -- ChangeGC checks for this condition 510706f2543Smrg * and snags the Foreground value to create a pseudo default-tile 511706f2543Smrg */ 512706f2543Smrg pGC->tileIsPixel = FALSE; 513706f2543Smrg } 514706f2543Smrg else 515706f2543Smrg { 516706f2543Smrg pGC->tileIsPixel = TRUE; 517706f2543Smrg } 518706f2543Smrg 519706f2543Smrg pGC->patOrg.x = 0; 520706f2543Smrg pGC->patOrg.y = 0; 521706f2543Smrg pGC->subWindowMode = ClipByChildren; 522706f2543Smrg pGC->graphicsExposures = TRUE; 523706f2543Smrg pGC->clipOrg.x = 0; 524706f2543Smrg pGC->clipOrg.y = 0; 525706f2543Smrg pGC->clientClipType = CT_NONE; 526706f2543Smrg pGC->clientClip = (pointer)NULL; 527706f2543Smrg pGC->numInDashList = 2; 528706f2543Smrg pGC->dash = DefaultDash; 529706f2543Smrg pGC->dashOffset = 0; 530706f2543Smrg 531706f2543Smrg /* use the default font and stipple */ 532706f2543Smrg pGC->font = defaultFont; 533706f2543Smrg defaultFont->refcnt++; 534706f2543Smrg pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; 535706f2543Smrg pGC->stipple->refcnt++; 536706f2543Smrg 537706f2543Smrg /* this is not a scratch GC */ 538706f2543Smrg pGC->scratch_inuse = FALSE; 539706f2543Smrg 540706f2543Smrg /* security creation/labeling check */ 541706f2543Smrg *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, 542706f2543Smrg RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); 543706f2543Smrg if (*pStatus != Success) 544706f2543Smrg goto out; 545706f2543Smrg 546706f2543Smrg pGC->stateChanges = GCAllBits; 547706f2543Smrg if (!(*pGC->pScreen->CreateGC)(pGC)) 548706f2543Smrg *pStatus = BadAlloc; 549706f2543Smrg else if (mask) 550706f2543Smrg *pStatus = ChangeGCXIDs(client, pGC, mask, pval); 551706f2543Smrg else 552706f2543Smrg *pStatus = Success; 553706f2543Smrg 554706f2543Smrgout: 555706f2543Smrg if (*pStatus != Success) 556706f2543Smrg { 557706f2543Smrg if (!pGC->tileIsPixel && !pGC->tile.pixmap) 558706f2543Smrg pGC->tileIsPixel = TRUE; /* undo special case */ 559706f2543Smrg FreeGC(pGC, (XID)0); 560706f2543Smrg pGC = (GCPtr)NULL; 561706f2543Smrg } 562706f2543Smrg 563706f2543Smrg return pGC; 564706f2543Smrg} 565706f2543Smrg 566706f2543Smrgstatic Bool 567706f2543SmrgCreateDefaultTile (GCPtr pGC) 568706f2543Smrg{ 569706f2543Smrg ChangeGCVal tmpval[3]; 570706f2543Smrg PixmapPtr pTile; 571706f2543Smrg GCPtr pgcScratch; 572706f2543Smrg xRectangle rect; 573706f2543Smrg CARD16 w, h; 574706f2543Smrg 575706f2543Smrg w = 1; 576706f2543Smrg h = 1; 577706f2543Smrg (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); 578706f2543Smrg pTile = (PixmapPtr) 579706f2543Smrg (*pGC->pScreen->CreatePixmap)(pGC->pScreen, 580706f2543Smrg w, h, pGC->depth, 0); 581706f2543Smrg pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); 582706f2543Smrg if (!pTile || !pgcScratch) 583706f2543Smrg { 584706f2543Smrg if (pTile) 585706f2543Smrg (*pTile->drawable.pScreen->DestroyPixmap)(pTile); 586706f2543Smrg if (pgcScratch) 587706f2543Smrg FreeScratchGC(pgcScratch); 588706f2543Smrg return FALSE; 589706f2543Smrg } 590706f2543Smrg tmpval[0].val = GXcopy; 591706f2543Smrg tmpval[1].val = pGC->tile.pixel; 592706f2543Smrg tmpval[2].val = FillSolid; 593706f2543Smrg (void)ChangeGC(NullClient, pgcScratch, GCFunction | GCForeground | GCFillStyle, tmpval); 594706f2543Smrg ValidateGC((DrawablePtr)pTile, pgcScratch); 595706f2543Smrg rect.x = 0; 596706f2543Smrg rect.y = 0; 597706f2543Smrg rect.width = w; 598706f2543Smrg rect.height = h; 599706f2543Smrg (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); 600706f2543Smrg /* Always remember to free the scratch graphics context after use. */ 601706f2543Smrg FreeScratchGC(pgcScratch); 602706f2543Smrg 603706f2543Smrg pGC->tileIsPixel = FALSE; 604706f2543Smrg pGC->tile.pixmap = pTile; 605706f2543Smrg return TRUE; 606706f2543Smrg} 607706f2543Smrg 608706f2543Smrgint 609706f2543SmrgCopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) 610706f2543Smrg{ 611706f2543Smrg BITS32 index2; 612706f2543Smrg BITS32 maskQ; 613706f2543Smrg int error = 0; 614706f2543Smrg 615706f2543Smrg if (pgcSrc == pgcDst) 616706f2543Smrg return Success; 617706f2543Smrg pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; 618706f2543Smrg pgcDst->stateChanges |= mask; 619706f2543Smrg maskQ = mask; 620706f2543Smrg while (mask) 621706f2543Smrg { 622706f2543Smrg index2 = (BITS32) lowbit (mask); 623706f2543Smrg mask &= ~index2; 624706f2543Smrg switch (index2) 625706f2543Smrg { 626706f2543Smrg case GCFunction: 627706f2543Smrg pgcDst->alu = pgcSrc->alu; 628706f2543Smrg break; 629706f2543Smrg case GCPlaneMask: 630706f2543Smrg pgcDst->planemask = pgcSrc->planemask; 631706f2543Smrg break; 632706f2543Smrg case GCForeground: 633706f2543Smrg pgcDst->fgPixel = pgcSrc->fgPixel; 634706f2543Smrg break; 635706f2543Smrg case GCBackground: 636706f2543Smrg pgcDst->bgPixel = pgcSrc->bgPixel; 637706f2543Smrg break; 638706f2543Smrg case GCLineWidth: 639706f2543Smrg pgcDst->lineWidth = pgcSrc->lineWidth; 640706f2543Smrg break; 641706f2543Smrg case GCLineStyle: 642706f2543Smrg pgcDst->lineStyle = pgcSrc->lineStyle; 643706f2543Smrg break; 644706f2543Smrg case GCCapStyle: 645706f2543Smrg pgcDst->capStyle = pgcSrc->capStyle; 646706f2543Smrg break; 647706f2543Smrg case GCJoinStyle: 648706f2543Smrg pgcDst->joinStyle = pgcSrc->joinStyle; 649706f2543Smrg break; 650706f2543Smrg case GCFillStyle: 651706f2543Smrg pgcDst->fillStyle = pgcSrc->fillStyle; 652706f2543Smrg break; 653706f2543Smrg case GCFillRule: 654706f2543Smrg pgcDst->fillRule = pgcSrc->fillRule; 655706f2543Smrg break; 656706f2543Smrg case GCTile: 657706f2543Smrg { 658706f2543Smrg if (EqualPixUnion(pgcDst->tileIsPixel, 659706f2543Smrg pgcDst->tile, 660706f2543Smrg pgcSrc->tileIsPixel, 661706f2543Smrg pgcSrc->tile)) 662706f2543Smrg { 663706f2543Smrg break; 664706f2543Smrg } 665706f2543Smrg if (!pgcDst->tileIsPixel) 666706f2543Smrg (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); 667706f2543Smrg pgcDst->tileIsPixel = pgcSrc->tileIsPixel; 668706f2543Smrg pgcDst->tile = pgcSrc->tile; 669706f2543Smrg if (!pgcDst->tileIsPixel) 670706f2543Smrg pgcDst->tile.pixmap->refcnt++; 671706f2543Smrg break; 672706f2543Smrg } 673706f2543Smrg case GCStipple: 674706f2543Smrg { 675706f2543Smrg if (pgcDst->stipple == pgcSrc->stipple) 676706f2543Smrg break; 677706f2543Smrg if (pgcDst->stipple) 678706f2543Smrg (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); 679706f2543Smrg pgcDst->stipple = pgcSrc->stipple; 680706f2543Smrg if (pgcDst->stipple) 681706f2543Smrg pgcDst->stipple->refcnt ++; 682706f2543Smrg break; 683706f2543Smrg } 684706f2543Smrg case GCTileStipXOrigin: 685706f2543Smrg pgcDst->patOrg.x = pgcSrc->patOrg.x; 686706f2543Smrg break; 687706f2543Smrg case GCTileStipYOrigin: 688706f2543Smrg pgcDst->patOrg.y = pgcSrc->patOrg.y; 689706f2543Smrg break; 690706f2543Smrg case GCFont: 691706f2543Smrg if (pgcDst->font == pgcSrc->font) 692706f2543Smrg break; 693706f2543Smrg if (pgcDst->font) 694706f2543Smrg CloseFont(pgcDst->font, (Font)0); 695706f2543Smrg if ((pgcDst->font = pgcSrc->font) != NullFont) 696706f2543Smrg (pgcDst->font)->refcnt++; 697706f2543Smrg break; 698706f2543Smrg case GCSubwindowMode: 699706f2543Smrg pgcDst->subWindowMode = pgcSrc->subWindowMode; 700706f2543Smrg break; 701706f2543Smrg case GCGraphicsExposures: 702706f2543Smrg pgcDst->graphicsExposures = pgcSrc->graphicsExposures; 703706f2543Smrg break; 704706f2543Smrg case GCClipXOrigin: 705706f2543Smrg pgcDst->clipOrg.x = pgcSrc->clipOrg.x; 706706f2543Smrg break; 707706f2543Smrg case GCClipYOrigin: 708706f2543Smrg pgcDst->clipOrg.y = pgcSrc->clipOrg.y; 709706f2543Smrg break; 710706f2543Smrg case GCClipMask: 711706f2543Smrg (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); 712706f2543Smrg break; 713706f2543Smrg case GCDashOffset: 714706f2543Smrg pgcDst->dashOffset = pgcSrc->dashOffset; 715706f2543Smrg break; 716706f2543Smrg case GCDashList: 717706f2543Smrg if (pgcSrc->dash == DefaultDash) 718706f2543Smrg { 719706f2543Smrg if (pgcDst->dash != DefaultDash) 720706f2543Smrg { 721706f2543Smrg free(pgcDst->dash); 722706f2543Smrg pgcDst->numInDashList = pgcSrc->numInDashList; 723706f2543Smrg pgcDst->dash = pgcSrc->dash; 724706f2543Smrg } 725706f2543Smrg } 726706f2543Smrg else 727706f2543Smrg { 728706f2543Smrg unsigned char *dash; 729706f2543Smrg unsigned int i; 730706f2543Smrg 731706f2543Smrg dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); 732706f2543Smrg if (dash) 733706f2543Smrg { 734706f2543Smrg if (pgcDst->dash != DefaultDash) 735706f2543Smrg free(pgcDst->dash); 736706f2543Smrg pgcDst->numInDashList = pgcSrc->numInDashList; 737706f2543Smrg pgcDst->dash = dash; 738706f2543Smrg for (i=0; i<pgcSrc->numInDashList; i++) 739706f2543Smrg dash[i] = pgcSrc->dash[i]; 740706f2543Smrg } 741706f2543Smrg else 742706f2543Smrg error = BadAlloc; 743706f2543Smrg } 744706f2543Smrg break; 745706f2543Smrg case GCArcMode: 746706f2543Smrg pgcDst->arcMode = pgcSrc->arcMode; 747706f2543Smrg break; 748706f2543Smrg default: 749706f2543Smrg FatalError ("CopyGC: Unhandled mask!\n"); 750706f2543Smrg } 751706f2543Smrg } 752706f2543Smrg if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) 753706f2543Smrg { 754706f2543Smrg if (!CreateDefaultTile (pgcDst)) 755706f2543Smrg { 756706f2543Smrg pgcDst->fillStyle = FillSolid; 757706f2543Smrg error = BadAlloc; 758706f2543Smrg } 759706f2543Smrg } 760706f2543Smrg (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); 761706f2543Smrg return error; 762706f2543Smrg} 763706f2543Smrg 764706f2543Smrg/** 765706f2543Smrg * does the diX part of freeing the characteristics in the GC. 766706f2543Smrg * 767706f2543Smrg * \param value must conform to DeleteType 768706f2543Smrg */ 769706f2543Smrgint 770706f2543SmrgFreeGC(pointer value, XID gid) 771706f2543Smrg{ 772706f2543Smrg GCPtr pGC = (GCPtr)value; 773706f2543Smrg 774706f2543Smrg CloseFont(pGC->font, (Font)0); 775706f2543Smrg (* pGC->funcs->DestroyClip)(pGC); 776706f2543Smrg 777706f2543Smrg if (!pGC->tileIsPixel) 778706f2543Smrg (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); 779706f2543Smrg if (pGC->stipple) 780706f2543Smrg (* pGC->pScreen->DestroyPixmap)(pGC->stipple); 781706f2543Smrg 782706f2543Smrg (*pGC->funcs->DestroyGC) (pGC); 783706f2543Smrg if (pGC->dash != DefaultDash) 784706f2543Smrg free(pGC->dash); 785706f2543Smrg dixFreeObjectWithPrivates(pGC, PRIVATE_GC); 786706f2543Smrg return Success; 787706f2543Smrg} 788706f2543Smrg 789706f2543Smrg/* CreateScratchGC(pScreen, depth) 790706f2543Smrg like CreateGC, but doesn't do the default tile or stipple, 791706f2543Smrgsince we can't create them without already having a GC. any code 792706f2543Smrgusing the tile or stipple has to set them explicitly anyway, 793706f2543Smrgsince the state of the scratch gc is unknown. This is OK 794706f2543Smrgbecause ChangeGC() has to be able to deal with NULL tiles and 795706f2543Smrgstipples anyway (in case the CreateGC() call has provided a 796706f2543Smrgvalue for them -- we can't set the default tile until the 797706f2543Smrgclient-supplied attributes are installed, since the fgPixel 798706f2543Smrgis what fills the default tile. (maybe this comment should 799706f2543Smrggo with CreateGC() or ChangeGC().) 800706f2543Smrg*/ 801706f2543Smrg 802706f2543Smrgstatic GCPtr 803706f2543SmrgCreateScratchGC(ScreenPtr pScreen, unsigned depth) 804706f2543Smrg{ 805706f2543Smrg GCPtr pGC; 806706f2543Smrg 807706f2543Smrg pGC = dixAllocateObjectWithPrivates(GC, PRIVATE_GC); 808706f2543Smrg if (!pGC) 809706f2543Smrg return (GCPtr)NULL; 810706f2543Smrg 811706f2543Smrg pGC->pScreen = pScreen; 812706f2543Smrg pGC->depth = depth; 813706f2543Smrg pGC->alu = GXcopy; /* dst <- src */ 814706f2543Smrg pGC->planemask = ~0; 815706f2543Smrg pGC->serialNumber = 0; 816706f2543Smrg pGC->fgPixel = 0; 817706f2543Smrg pGC->bgPixel = 1; 818706f2543Smrg pGC->lineWidth = 0; 819706f2543Smrg pGC->lineStyle = LineSolid; 820706f2543Smrg pGC->capStyle = CapButt; 821706f2543Smrg pGC->joinStyle = JoinMiter; 822706f2543Smrg pGC->fillStyle = FillSolid; 823706f2543Smrg pGC->fillRule = EvenOddRule; 824706f2543Smrg pGC->arcMode = ArcPieSlice; 825706f2543Smrg pGC->font = defaultFont; 826706f2543Smrg if ( pGC->font) /* necessary, because open of default font could fail */ 827706f2543Smrg pGC->font->refcnt++; 828706f2543Smrg pGC->tileIsPixel = TRUE; 829706f2543Smrg pGC->tile.pixel = 0; 830706f2543Smrg pGC->tile.pixmap = NullPixmap; 831706f2543Smrg pGC->stipple = NullPixmap; 832706f2543Smrg pGC->patOrg.x = 0; 833706f2543Smrg pGC->patOrg.y = 0; 834706f2543Smrg pGC->subWindowMode = ClipByChildren; 835706f2543Smrg pGC->graphicsExposures = TRUE; 836706f2543Smrg pGC->clipOrg.x = 0; 837706f2543Smrg pGC->clipOrg.y = 0; 838706f2543Smrg pGC->clientClipType = CT_NONE; 839706f2543Smrg pGC->dashOffset = 0; 840706f2543Smrg pGC->numInDashList = 2; 841706f2543Smrg pGC->dash = DefaultDash; 842706f2543Smrg 843706f2543Smrg /* scratch GCs in the GCperDepth pool start off unused */ 844706f2543Smrg pGC->scratch_inuse = FALSE; 845706f2543Smrg 846706f2543Smrg pGC->stateChanges = GCAllBits; 847706f2543Smrg if (!(*pScreen->CreateGC)(pGC)) 848706f2543Smrg { 849706f2543Smrg FreeGC(pGC, (XID)0); 850706f2543Smrg pGC = (GCPtr)NULL; 851706f2543Smrg } 852706f2543Smrg return pGC; 853706f2543Smrg} 854706f2543Smrg 855706f2543Smrgvoid 856706f2543SmrgFreeGCperDepth(int screenNum) 857706f2543Smrg{ 858706f2543Smrg int i; 859706f2543Smrg ScreenPtr pScreen; 860706f2543Smrg GCPtr *ppGC; 861706f2543Smrg 862706f2543Smrg pScreen = screenInfo.screens[screenNum]; 863706f2543Smrg ppGC = pScreen->GCperDepth; 864706f2543Smrg 865706f2543Smrg for (i = 0; i <= pScreen->numDepths; i++) 866706f2543Smrg { 867706f2543Smrg (void)FreeGC(ppGC[i], (XID)0); 868706f2543Smrg ppGC[i] = NULL; 869706f2543Smrg } 870706f2543Smrg} 871706f2543Smrg 872706f2543Smrg 873706f2543SmrgBool 874706f2543SmrgCreateGCperDepth(int screenNum) 875706f2543Smrg{ 876706f2543Smrg int i; 877706f2543Smrg ScreenPtr pScreen; 878706f2543Smrg DepthPtr pDepth; 879706f2543Smrg GCPtr *ppGC; 880706f2543Smrg 881706f2543Smrg pScreen = screenInfo.screens[screenNum]; 882706f2543Smrg ppGC = pScreen->GCperDepth; 883706f2543Smrg /* do depth 1 separately because it's not included in list */ 884706f2543Smrg if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) 885706f2543Smrg return FALSE; 886706f2543Smrg ppGC[0]->graphicsExposures = FALSE; 887706f2543Smrg /* Make sure we don't overflow GCperDepth[] */ 888706f2543Smrg if( pScreen->numDepths > MAXFORMATS ) 889706f2543Smrg return FALSE; 890706f2543Smrg 891706f2543Smrg pDepth = pScreen->allowedDepths; 892706f2543Smrg for (i=0; i<pScreen->numDepths; i++, pDepth++) 893706f2543Smrg { 894706f2543Smrg if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) 895706f2543Smrg { 896706f2543Smrg for (; i >= 0; i--) 897706f2543Smrg (void)FreeGC(ppGC[i], (XID)0); 898706f2543Smrg return FALSE; 899706f2543Smrg } 900706f2543Smrg ppGC[i+1]->graphicsExposures = FALSE; 901706f2543Smrg } 902706f2543Smrg return TRUE; 903706f2543Smrg} 904706f2543Smrg 905706f2543SmrgBool 906706f2543SmrgCreateDefaultStipple(int screenNum) 907706f2543Smrg{ 908706f2543Smrg ScreenPtr pScreen; 909706f2543Smrg ChangeGCVal tmpval[3]; 910706f2543Smrg xRectangle rect; 911706f2543Smrg CARD16 w, h; 912706f2543Smrg GCPtr pgcScratch; 913706f2543Smrg 914706f2543Smrg pScreen = screenInfo.screens[screenNum]; 915706f2543Smrg 916706f2543Smrg w = 16; 917706f2543Smrg h = 16; 918706f2543Smrg (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); 919706f2543Smrg if (!(pScreen->PixmapPerDepth[0] = 920706f2543Smrg (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) 921706f2543Smrg return FALSE; 922706f2543Smrg /* fill stipple with 1 */ 923706f2543Smrg tmpval[0].val = GXcopy; 924706f2543Smrg tmpval[1].val = 1; 925706f2543Smrg tmpval[2].val = FillSolid; 926706f2543Smrg pgcScratch = GetScratchGC(1, pScreen); 927706f2543Smrg if (!pgcScratch) 928706f2543Smrg { 929706f2543Smrg (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); 930706f2543Smrg return FALSE; 931706f2543Smrg } 932706f2543Smrg (void)ChangeGC(NullClient, pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); 933706f2543Smrg ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); 934706f2543Smrg rect.x = 0; 935706f2543Smrg rect.y = 0; 936706f2543Smrg rect.width = w; 937706f2543Smrg rect.height = h; 938706f2543Smrg (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], 939706f2543Smrg pgcScratch, 1, &rect); 940706f2543Smrg FreeScratchGC(pgcScratch); 941706f2543Smrg return TRUE; 942706f2543Smrg} 943706f2543Smrg 944706f2543Smrgvoid 945706f2543SmrgFreeDefaultStipple(int screenNum) 946706f2543Smrg{ 947706f2543Smrg ScreenPtr pScreen = screenInfo.screens[screenNum]; 948706f2543Smrg (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); 949706f2543Smrg} 950706f2543Smrg 951706f2543Smrgint 952706f2543SmrgSetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) 953706f2543Smrg{ 954706f2543Smrg long i; 955706f2543Smrg unsigned char *p, *indash; 956706f2543Smrg BITS32 maskQ = 0; 957706f2543Smrg 958706f2543Smrg i = ndash; 959706f2543Smrg p = pdash; 960706f2543Smrg while (i--) 961706f2543Smrg { 962706f2543Smrg if (!*p++) 963706f2543Smrg { 964706f2543Smrg /* dash segment must be > 0 */ 965706f2543Smrg return BadValue; 966706f2543Smrg } 967706f2543Smrg } 968706f2543Smrg 969706f2543Smrg if (ndash & 1) 970706f2543Smrg p = malloc(2 * ndash * sizeof(unsigned char)); 971706f2543Smrg else 972706f2543Smrg p = malloc(ndash * sizeof(unsigned char)); 973706f2543Smrg if (!p) 974706f2543Smrg return BadAlloc; 975706f2543Smrg 976706f2543Smrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 977706f2543Smrg if (offset != pGC->dashOffset) 978706f2543Smrg { 979706f2543Smrg pGC->dashOffset = offset; 980706f2543Smrg pGC->stateChanges |= GCDashOffset; 981706f2543Smrg maskQ |= GCDashOffset; 982706f2543Smrg } 983706f2543Smrg 984706f2543Smrg if (pGC->dash != DefaultDash) 985706f2543Smrg free(pGC->dash); 986706f2543Smrg pGC->numInDashList = ndash; 987706f2543Smrg pGC->dash = p; 988706f2543Smrg if (ndash & 1) 989706f2543Smrg { 990706f2543Smrg pGC->numInDashList += ndash; 991706f2543Smrg indash = pdash; 992706f2543Smrg i = ndash; 993706f2543Smrg while (i--) 994706f2543Smrg *p++ = *indash++; 995706f2543Smrg } 996706f2543Smrg while(ndash--) 997706f2543Smrg *p++ = *pdash++; 998706f2543Smrg pGC->stateChanges |= GCDashList; 999706f2543Smrg maskQ |= GCDashList; 1000706f2543Smrg 1001706f2543Smrg if (pGC->funcs->ChangeGC) 1002706f2543Smrg (*pGC->funcs->ChangeGC) (pGC, maskQ); 1003706f2543Smrg return Success; 1004706f2543Smrg} 1005706f2543Smrg 1006706f2543Smrgint 1007706f2543SmrgVerifyRectOrder(int nrects, xRectangle *prects, int ordering) 1008706f2543Smrg{ 1009706f2543Smrg xRectangle *prectP, *prectN; 1010706f2543Smrg int i; 1011706f2543Smrg 1012706f2543Smrg switch(ordering) 1013706f2543Smrg { 1014706f2543Smrg case Unsorted: 1015706f2543Smrg return CT_UNSORTED; 1016706f2543Smrg case YSorted: 1017706f2543Smrg if(nrects > 1) 1018706f2543Smrg { 1019706f2543Smrg for(i = 1, prectP = prects, prectN = prects + 1; 1020706f2543Smrg i < nrects; 1021706f2543Smrg i++, prectP++, prectN++) 1022706f2543Smrg if(prectN->y < prectP->y) 1023706f2543Smrg return -1; 1024706f2543Smrg } 1025706f2543Smrg return CT_YSORTED; 1026706f2543Smrg case YXSorted: 1027706f2543Smrg if(nrects > 1) 1028706f2543Smrg { 1029706f2543Smrg for(i = 1, prectP = prects, prectN = prects + 1; 1030706f2543Smrg i < nrects; 1031706f2543Smrg i++, prectP++, prectN++) 1032706f2543Smrg if((prectN->y < prectP->y) || 1033706f2543Smrg ( (prectN->y == prectP->y) && 1034706f2543Smrg (prectN->x < prectP->x) ) ) 1035706f2543Smrg return -1; 1036706f2543Smrg } 1037706f2543Smrg return CT_YXSORTED; 1038706f2543Smrg case YXBanded: 1039706f2543Smrg if(nrects > 1) 1040706f2543Smrg { 1041706f2543Smrg for(i = 1, prectP = prects, prectN = prects + 1; 1042706f2543Smrg i < nrects; 1043706f2543Smrg i++, prectP++, prectN++) 1044706f2543Smrg if((prectN->y != prectP->y && 1045706f2543Smrg prectN->y < prectP->y + (int) prectP->height) || 1046706f2543Smrg ((prectN->y == prectP->y) && 1047706f2543Smrg (prectN->height != prectP->height || 1048706f2543Smrg prectN->x < prectP->x + (int) prectP->width))) 1049706f2543Smrg return -1; 1050706f2543Smrg } 1051706f2543Smrg return CT_YXBANDED; 1052706f2543Smrg } 1053706f2543Smrg return -1; 1054706f2543Smrg} 1055706f2543Smrg 1056706f2543Smrgint 1057706f2543SmrgSetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, 1058706f2543Smrg xRectangle *prects, int ordering) 1059706f2543Smrg{ 1060706f2543Smrg int newct, size; 1061706f2543Smrg xRectangle *prectsNew; 1062706f2543Smrg 1063706f2543Smrg newct = VerifyRectOrder(nrects, prects, ordering); 1064706f2543Smrg if (newct < 0) 1065706f2543Smrg return BadMatch; 1066706f2543Smrg size = nrects * sizeof(xRectangle); 1067706f2543Smrg prectsNew = malloc(size); 1068706f2543Smrg if (!prectsNew && size) 1069706f2543Smrg return BadAlloc; 1070706f2543Smrg 1071706f2543Smrg pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; 1072706f2543Smrg pGC->clipOrg.x = xOrigin; 1073706f2543Smrg pGC->stateChanges |= GCClipXOrigin; 1074706f2543Smrg 1075706f2543Smrg pGC->clipOrg.y = yOrigin; 1076706f2543Smrg pGC->stateChanges |= GCClipYOrigin; 1077706f2543Smrg 1078706f2543Smrg if (size) 1079706f2543Smrg memmove((char *)prectsNew, (char *)prects, size); 1080706f2543Smrg (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); 1081706f2543Smrg if (pGC->funcs->ChangeGC) 1082706f2543Smrg (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); 1083706f2543Smrg return Success; 1084706f2543Smrg} 1085706f2543Smrg 1086706f2543Smrg 1087706f2543Smrg/* 1088706f2543Smrg sets reasonable defaults 1089706f2543Smrg if we can get a pre-allocated one, use it and mark it as used. 1090706f2543Smrg if we can't, create one out of whole cloth (The Velveteen GC -- if 1091706f2543Smrg you use it often enough it will become real.) 1092706f2543Smrg*/ 1093706f2543SmrgGCPtr 1094706f2543SmrgGetScratchGC(unsigned depth, ScreenPtr pScreen) 1095706f2543Smrg{ 1096706f2543Smrg int i; 1097706f2543Smrg GCPtr pGC; 1098706f2543Smrg 1099706f2543Smrg for (i=0; i<=pScreen->numDepths; i++) 1100706f2543Smrg { 1101706f2543Smrg pGC = pScreen->GCperDepth[i]; 1102706f2543Smrg if (pGC && pGC->depth == depth && !pGC->scratch_inuse) 1103706f2543Smrg { 1104706f2543Smrg pGC->scratch_inuse = TRUE; 1105706f2543Smrg 1106706f2543Smrg pGC->alu = GXcopy; 1107706f2543Smrg pGC->planemask = ~0; 1108706f2543Smrg pGC->serialNumber = 0; 1109706f2543Smrg pGC->fgPixel = 0; 1110706f2543Smrg pGC->bgPixel = 1; 1111706f2543Smrg pGC->lineWidth = 0; 1112706f2543Smrg pGC->lineStyle = LineSolid; 1113706f2543Smrg pGC->capStyle = CapButt; 1114706f2543Smrg pGC->joinStyle = JoinMiter; 1115706f2543Smrg pGC->fillStyle = FillSolid; 1116706f2543Smrg pGC->fillRule = EvenOddRule; 1117706f2543Smrg pGC->arcMode = ArcChord; 1118706f2543Smrg pGC->patOrg.x = 0; 1119706f2543Smrg pGC->patOrg.y = 0; 1120706f2543Smrg pGC->subWindowMode = ClipByChildren; 1121706f2543Smrg pGC->graphicsExposures = FALSE; 1122706f2543Smrg pGC->clipOrg.x = 0; 1123706f2543Smrg pGC->clipOrg.y = 0; 1124706f2543Smrg if (pGC->clientClipType != CT_NONE) 1125706f2543Smrg (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); 1126706f2543Smrg pGC->stateChanges = GCAllBits; 1127706f2543Smrg return pGC; 1128706f2543Smrg } 1129706f2543Smrg } 1130706f2543Smrg /* if we make it this far, need to roll our own */ 1131706f2543Smrg pGC = CreateScratchGC(pScreen, depth); 1132706f2543Smrg if (pGC) 1133706f2543Smrg pGC->graphicsExposures = FALSE; 1134706f2543Smrg return pGC; 1135706f2543Smrg} 1136706f2543Smrg 1137706f2543Smrg/* 1138706f2543Smrg if the gc to free is in the table of pre-existing ones, 1139706f2543Smrgmark it as available. 1140706f2543Smrg if not, free it for real 1141706f2543Smrg*/ 1142706f2543Smrgvoid 1143706f2543SmrgFreeScratchGC(GCPtr pGC) 1144706f2543Smrg{ 1145706f2543Smrg if (pGC->scratch_inuse) 1146706f2543Smrg pGC->scratch_inuse = FALSE; 1147706f2543Smrg else 1148706f2543Smrg FreeGC(pGC, (GContext)0); 1149706f2543Smrg} 1150