| File: | dix/gc.c |
| Location: | line 739, column 35 |
| Description: | Use of memory after it is freed |
| 1 | /*********************************************************** | |||
| 2 | ||||
| 3 | Copyright 1987, 1998 The Open Group | |||
| 4 | ||||
| 5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | the above copyright notice appear in all copies and that both that | |||
| 8 | copyright notice and this permission notice appear in supporting | |||
| 9 | documentation. | |||
| 10 | ||||
| 11 | The above copyright notice and this permission notice shall be included in | |||
| 12 | all copies or substantial portions of the Software. | |||
| 13 | ||||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| 17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
| 18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| 20 | ||||
| 21 | Except as contained in this notice, the name of The Open Group shall not be | |||
| 22 | used in advertising or otherwise to promote the sale, use or other dealings | |||
| 23 | in this Software without prior written authorization from The Open Group. | |||
| 24 | ||||
| 25 | Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. | |||
| 26 | ||||
| 27 | All Rights Reserved | |||
| 28 | ||||
| 29 | Permission to use, copy, modify, and distribute this software and its | |||
| 30 | documentation for any purpose and without fee is hereby granted, | |||
| 31 | provided that the above copyright notice appear in all copies and that | |||
| 32 | both that copyright notice and this permission notice appear in | |||
| 33 | supporting documentation, and that the name of Digital not be | |||
| 34 | used in advertising or publicity pertaining to distribution of the | |||
| 35 | software without specific, written prior permission. | |||
| 36 | ||||
| 37 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |||
| 38 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |||
| 39 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |||
| 40 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |||
| 41 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |||
| 42 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |||
| 43 | SOFTWARE. | |||
| 44 | ||||
| 45 | ******************************************************************/ | |||
| 46 | ||||
| 47 | #ifdef HAVE_DIX_CONFIG_H1 | |||
| 48 | #include <dix-config.h> | |||
| 49 | #endif | |||
| 50 | ||||
| 51 | #include <X11/X.h> | |||
| 52 | #include <X11/Xmd.h> | |||
| 53 | #include <X11/Xproto.h> | |||
| 54 | #include "misc.h" | |||
| 55 | #include "resource.h" | |||
| 56 | #include "gcstruct.h" | |||
| 57 | #include "pixmapstr.h" | |||
| 58 | #include "dixfontstr.h" | |||
| 59 | #include "scrnintstr.h" | |||
| 60 | #include "region.h" | |||
| 61 | #include "dixstruct.h" | |||
| 62 | ||||
| 63 | #include "privates.h" | |||
| 64 | #include "dix.h" | |||
| 65 | #include "xace.h" | |||
| 66 | #include <assert.h> | |||
| 67 | ||||
| 68 | extern FontPtr defaultFont; | |||
| 69 | ||||
| 70 | static Bool CreateDefaultTile(GCPtr pGC); | |||
| 71 | ||||
| 72 | static unsigned char DefaultDash[2] = { 4, 4 }; | |||
| 73 | ||||
| 74 | void | |||
| 75 | ValidateGC(DrawablePtr pDraw, GC * pGC) | |||
| 76 | { | |||
| 77 | (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); | |||
| 78 | pGC->stateChanges = 0; | |||
| 79 | pGC->serialNumber = pDraw->serialNumber; | |||
| 80 | } | |||
| 81 | ||||
| 82 | /* | |||
| 83 | * ChangeGC/ChangeGCXIDs: | |||
| 84 | * | |||
| 85 | * The client performing the gc change must be passed so that access | |||
| 86 | * checks can be performed on any tiles, stipples, or fonts that are | |||
| 87 | * specified. ddxen can call this too; they should normally pass | |||
| 88 | * NullClient for the client since any access checking should have | |||
| 89 | * already been done at a higher level. | |||
| 90 | * | |||
| 91 | * If you have any XIDs, you must use ChangeGCXIDs: | |||
| 92 | * | |||
| 93 | * CARD32 v[2]; | |||
| 94 | * v[0] = FillTiled; | |||
| 95 | * v[1] = pid; | |||
| 96 | * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); | |||
| 97 | * | |||
| 98 | * However, if you need to pass a pointer to a pixmap or font, you must | |||
| 99 | * use ChangeGC: | |||
| 100 | * | |||
| 101 | * ChangeGCVal v[2]; | |||
| 102 | * v[0].val = FillTiled; | |||
| 103 | * v[1].ptr = pPixmap; | |||
| 104 | * ChangeGC(client, pGC, GCFillStyle|GCTile, v); | |||
| 105 | * | |||
| 106 | * If you have neither XIDs nor pointers, you can use either function, | |||
| 107 | * but ChangeGC will do less work. | |||
| 108 | * | |||
| 109 | * ChangeGCVal v[2]; | |||
| 110 | * v[0].val = foreground; | |||
| 111 | * v[1].val = background; | |||
| 112 | * ChangeGC(client, pGC, GCForeground|GCBackground, v); | |||
| 113 | */ | |||
| 114 | ||||
| 115 | #define NEXTVAL(_type, _var) { \ | |||
| 116 | _var = (_type)(pUnion->val); pUnion++; \ | |||
| 117 | } | |||
| 118 | ||||
| 119 | #define NEXT_PTR(_type, _var) { \ | |||
| 120 | _var = (_type)pUnion->ptr; pUnion++; } | |||
| 121 | ||||
| 122 | int | |||
| 123 | ChangeGC(ClientPtr client, GC * pGC, BITS32 mask, ChangeGCValPtr pUnion) | |||
| 124 | { | |||
| 125 | BITS32 index2; | |||
| 126 | int error = 0; | |||
| 127 | PixmapPtr pPixmap; | |||
| 128 | BITS32 maskQ; | |||
| 129 | ||||
| 130 | assert(pUnion)(__builtin_expect(!(pUnion), 0) ? __assert_rtn(__func__, "gc.c" , 130, "pUnion") : (void)0); | |||
| 131 | pGC->serialNumber |= GC_CHANGE_SERIAL_BIT(((unsigned long)1)<<31); | |||
| 132 | ||||
| 133 | maskQ = mask; /* save these for when we walk the GCque */ | |||
| 134 | while (mask && !error) { | |||
| 135 | index2 = (BITS32) lowbit(mask)((mask) & (~(mask) + 1)); | |||
| 136 | mask &= ~index2; | |||
| 137 | pGC->stateChanges |= index2; | |||
| 138 | switch (index2) { | |||
| 139 | case GCFunction(1L<<0): | |||
| 140 | { | |||
| 141 | CARD8 newalu; | |||
| 142 | NEXTVAL(CARD8, newalu); | |||
| 143 | ||||
| 144 | if (newalu <= GXset0xf) | |||
| 145 | pGC->alu = newalu; | |||
| 146 | else { | |||
| 147 | if (client) | |||
| 148 | client->errorValue = newalu; | |||
| 149 | error = BadValue2; | |||
| 150 | } | |||
| 151 | break; | |||
| 152 | } | |||
| 153 | case GCPlaneMask(1L<<1): | |||
| 154 | NEXTVAL(unsigned long, pGC->planemask); | |||
| 155 | ||||
| 156 | break; | |||
| 157 | case GCForeground(1L<<2): | |||
| 158 | NEXTVAL(unsigned long, pGC->fgPixel); | |||
| 159 | ||||
| 160 | /* | |||
| 161 | * this is for CreateGC | |||
| 162 | */ | |||
| 163 | if (!pGC->tileIsPixel && !pGC->tile.pixmap) { | |||
| 164 | pGC->tileIsPixel = TRUE1; | |||
| 165 | pGC->tile.pixel = pGC->fgPixel; | |||
| 166 | } | |||
| 167 | break; | |||
| 168 | case GCBackground(1L<<3): | |||
| 169 | NEXTVAL(unsigned long, pGC->bgPixel); | |||
| 170 | ||||
| 171 | break; | |||
| 172 | case GCLineWidth(1L<<4): /* ??? line width is a CARD16 */ | |||
| 173 | NEXTVAL(CARD16, pGC->lineWidth); | |||
| 174 | ||||
| 175 | break; | |||
| 176 | case GCLineStyle(1L<<5): | |||
| 177 | { | |||
| 178 | unsigned int newlinestyle; | |||
| 179 | NEXTVAL(unsigned int, newlinestyle); | |||
| 180 | ||||
| 181 | if (newlinestyle <= LineDoubleDash2) | |||
| 182 | pGC->lineStyle = newlinestyle; | |||
| 183 | else { | |||
| 184 | if (client) | |||
| 185 | client->errorValue = newlinestyle; | |||
| 186 | error = BadValue2; | |||
| 187 | } | |||
| 188 | break; | |||
| 189 | } | |||
| 190 | case GCCapStyle(1L<<6): | |||
| 191 | { | |||
| 192 | unsigned int newcapstyle; | |||
| 193 | NEXTVAL(unsigned int, newcapstyle); | |||
| 194 | ||||
| 195 | if (newcapstyle <= CapProjecting3) | |||
| 196 | pGC->capStyle = newcapstyle; | |||
| 197 | else { | |||
| 198 | if (client) | |||
| 199 | client->errorValue = newcapstyle; | |||
| 200 | error = BadValue2; | |||
| 201 | } | |||
| 202 | break; | |||
| 203 | } | |||
| 204 | case GCJoinStyle(1L<<7): | |||
| 205 | { | |||
| 206 | unsigned int newjoinstyle; | |||
| 207 | NEXTVAL(unsigned int, newjoinstyle); | |||
| 208 | ||||
| 209 | if (newjoinstyle <= JoinBevel2) | |||
| 210 | pGC->joinStyle = newjoinstyle; | |||
| 211 | else { | |||
| 212 | if (client) | |||
| 213 | client->errorValue = newjoinstyle; | |||
| 214 | error = BadValue2; | |||
| 215 | } | |||
| 216 | break; | |||
| 217 | } | |||
| 218 | case GCFillStyle(1L<<8): | |||
| 219 | { | |||
| 220 | unsigned int newfillstyle; | |||
| 221 | NEXTVAL(unsigned int, newfillstyle); | |||
| 222 | ||||
| 223 | if (newfillstyle <= FillOpaqueStippled3) | |||
| 224 | pGC->fillStyle = newfillstyle; | |||
| 225 | else { | |||
| 226 | if (client) | |||
| 227 | client->errorValue = newfillstyle; | |||
| 228 | error = BadValue2; | |||
| 229 | } | |||
| 230 | break; | |||
| 231 | } | |||
| 232 | case GCFillRule(1L<<9): | |||
| 233 | { | |||
| 234 | unsigned int newfillrule; | |||
| 235 | NEXTVAL(unsigned int, newfillrule); | |||
| 236 | ||||
| 237 | if (newfillrule <= WindingRule1) | |||
| 238 | pGC->fillRule = newfillrule; | |||
| 239 | else { | |||
| 240 | if (client) | |||
| 241 | client->errorValue = newfillrule; | |||
| 242 | error = BadValue2; | |||
| 243 | } | |||
| 244 | break; | |||
| 245 | } | |||
| 246 | case GCTile(1L<<10): | |||
| 247 | NEXT_PTR(PixmapPtr, pPixmap); | |||
| 248 | ||||
| 249 | if ((pPixmap->drawable.depth != pGC->depth) || | |||
| 250 | (pPixmap->drawable.pScreen != pGC->pScreen)) { | |||
| 251 | error = BadMatch8; | |||
| 252 | } | |||
| 253 | else { | |||
| 254 | pPixmap->refcnt++; | |||
| 255 | if (!pGC->tileIsPixel) | |||
| 256 | (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap); | |||
| 257 | pGC->tileIsPixel = FALSE0; | |||
| 258 | pGC->tile.pixmap = pPixmap; | |||
| 259 | } | |||
| 260 | break; | |||
| 261 | case GCStipple(1L<<11): | |||
| 262 | NEXT_PTR(PixmapPtr, pPixmap); | |||
| 263 | ||||
| 264 | if (pPixmap && ((pPixmap->drawable.depth != 1) || | |||
| 265 | (pPixmap->drawable.pScreen != pGC->pScreen))) | |||
| 266 | { | |||
| 267 | error = BadMatch8; | |||
| 268 | } | |||
| 269 | else { | |||
| 270 | if (pPixmap) | |||
| 271 | pPixmap->refcnt++; | |||
| 272 | if (pGC->stipple) | |||
| 273 | (*pGC->pScreen->DestroyPixmap) (pGC->stipple); | |||
| 274 | pGC->stipple = pPixmap; | |||
| 275 | } | |||
| 276 | break; | |||
| 277 | case GCTileStipXOrigin(1L<<12): | |||
| 278 | NEXTVAL(INT16, pGC->patOrg.x); | |||
| 279 | ||||
| 280 | break; | |||
| 281 | case GCTileStipYOrigin(1L<<13): | |||
| 282 | NEXTVAL(INT16, pGC->patOrg.y); | |||
| 283 | ||||
| 284 | break; | |||
| 285 | case GCFont(1L<<14): | |||
| 286 | { | |||
| 287 | FontPtr pFont; | |||
| 288 | NEXT_PTR(FontPtr, pFont); | |||
| 289 | ||||
| 290 | pFont->refcnt++; | |||
| 291 | if (pGC->font) | |||
| 292 | CloseFont(pGC->font, (Font) 0); | |||
| 293 | pGC->font = pFont; | |||
| 294 | break; | |||
| 295 | } | |||
| 296 | case GCSubwindowMode(1L<<15): | |||
| 297 | { | |||
| 298 | unsigned int newclipmode; | |||
| 299 | NEXTVAL(unsigned int, newclipmode); | |||
| 300 | ||||
| 301 | if (newclipmode <= IncludeInferiors1) | |||
| 302 | pGC->subWindowMode = newclipmode; | |||
| 303 | else { | |||
| 304 | if (client) | |||
| 305 | client->errorValue = newclipmode; | |||
| 306 | error = BadValue2; | |||
| 307 | } | |||
| 308 | break; | |||
| 309 | } | |||
| 310 | case GCGraphicsExposures(1L<<16): | |||
| 311 | { | |||
| 312 | unsigned int newge; | |||
| 313 | NEXTVAL(unsigned int, newge); | |||
| 314 | ||||
| 315 | if (newge <= xTrue1) | |||
| 316 | pGC->graphicsExposures = newge; | |||
| 317 | else { | |||
| 318 | if (client) | |||
| 319 | client->errorValue = newge; | |||
| 320 | error = BadValue2; | |||
| 321 | } | |||
| 322 | break; | |||
| 323 | } | |||
| 324 | case GCClipXOrigin(1L<<17): | |||
| 325 | NEXTVAL(INT16, pGC->clipOrg.x); | |||
| 326 | ||||
| 327 | break; | |||
| 328 | case GCClipYOrigin(1L<<18): | |||
| 329 | NEXTVAL(INT16, pGC->clipOrg.y); | |||
| 330 | ||||
| 331 | break; | |||
| 332 | case GCClipMask(1L<<19): | |||
| 333 | NEXT_PTR(PixmapPtr, pPixmap); | |||
| 334 | ||||
| 335 | if (pPixmap) { | |||
| 336 | if ((pPixmap->drawable.depth != 1) || | |||
| 337 | (pPixmap->drawable.pScreen != pGC->pScreen)) { | |||
| 338 | error = BadMatch8; | |||
| 339 | break; | |||
| 340 | } | |||
| 341 | pPixmap->refcnt++; | |||
| 342 | } | |||
| 343 | (*pGC->funcs->ChangeClip) (pGC, pPixmap ? CT_PIXMAP1 : CT_NONE0, | |||
| 344 | (void *) pPixmap, 0); | |||
| 345 | break; | |||
| 346 | case GCDashOffset(1L<<20): | |||
| 347 | NEXTVAL(INT16, pGC->dashOffset); | |||
| 348 | ||||
| 349 | break; | |||
| 350 | case GCDashList(1L<<21): | |||
| 351 | { | |||
| 352 | CARD8 newdash; | |||
| 353 | NEXTVAL(CARD8, newdash); | |||
| 354 | ||||
| 355 | if (newdash == 4) { | |||
| 356 | if (pGC->dash != DefaultDash) { | |||
| 357 | free(pGC->dash); | |||
| 358 | pGC->numInDashList = 2; | |||
| 359 | pGC->dash = DefaultDash; | |||
| 360 | } | |||
| 361 | } | |||
| 362 | else if (newdash != 0) { | |||
| 363 | unsigned char *dash; | |||
| 364 | ||||
| 365 | dash = malloc(2 * sizeof(unsigned char)); | |||
| 366 | if (dash) { | |||
| 367 | if (pGC->dash != DefaultDash) | |||
| 368 | free(pGC->dash); | |||
| 369 | pGC->numInDashList = 2; | |||
| 370 | pGC->dash = dash; | |||
| 371 | dash[0] = newdash; | |||
| 372 | dash[1] = newdash; | |||
| 373 | } | |||
| 374 | else | |||
| 375 | error = BadAlloc11; | |||
| 376 | } | |||
| 377 | else { | |||
| 378 | if (client) | |||
| 379 | client->errorValue = newdash; | |||
| 380 | error = BadValue2; | |||
| 381 | } | |||
| 382 | break; | |||
| 383 | } | |||
| 384 | case GCArcMode(1L<<22): | |||
| 385 | { | |||
| 386 | unsigned int newarcmode; | |||
| 387 | NEXTVAL(unsigned int, newarcmode); | |||
| 388 | ||||
| 389 | if (newarcmode <= ArcPieSlice1) | |||
| 390 | pGC->arcMode = newarcmode; | |||
| 391 | else { | |||
| 392 | if (client) | |||
| 393 | client->errorValue = newarcmode; | |||
| 394 | error = BadValue2; | |||
| 395 | } | |||
| 396 | break; | |||
| 397 | } | |||
| 398 | default: | |||
| 399 | if (client) | |||
| 400 | client->errorValue = maskQ; | |||
| 401 | error = BadValue2; | |||
| 402 | break; | |||
| 403 | } | |||
| 404 | } /* end while mask && !error */ | |||
| 405 | ||||
| 406 | if (pGC->fillStyle == FillTiled1 && pGC->tileIsPixel) { | |||
| 407 | if (!CreateDefaultTile(pGC)) { | |||
| 408 | pGC->fillStyle = FillSolid0; | |||
| 409 | error = BadAlloc11; | |||
| 410 | } | |||
| 411 | } | |||
| 412 | (*pGC->funcs->ChangeGC) (pGC, maskQ); | |||
| 413 | return error; | |||
| 414 | } | |||
| 415 | ||||
| 416 | #undef NEXTVAL | |||
| 417 | #undef NEXT_PTR | |||
| 418 | ||||
| 419 | static const struct { | |||
| 420 | BITS32 mask; | |||
| 421 | RESTYPE type; | |||
| 422 | Mask access_mode; | |||
| 423 | } xidfields[] = { | |||
| 424 | {GCTile(1L<<10), RT_PIXMAP((RESTYPE)2|((RESTYPE)1<<30)), DixReadAccess(1<<0)}, | |||
| 425 | {GCStipple(1L<<11), RT_PIXMAP((RESTYPE)2|((RESTYPE)1<<30)), DixReadAccess(1<<0)}, | |||
| 426 | {GCFont(1L<<14), RT_FONT((RESTYPE)4), DixUseAccess(1<<24)}, | |||
| 427 | {GCClipMask(1L<<19), RT_PIXMAP((RESTYPE)2|((RESTYPE)1<<30)), DixReadAccess(1<<0)}, | |||
| 428 | }; | |||
| 429 | ||||
| 430 | int | |||
| 431 | ChangeGCXIDs(ClientPtr client, GC * pGC, BITS32 mask, CARD32 *pC32) | |||
| 432 | { | |||
| 433 | ChangeGCVal vals[GCLastBit22 + 1]; | |||
| 434 | int i; | |||
| 435 | ||||
| 436 | if (mask & ~GCAllBits((1 << (22 + 1)) - 1)) { | |||
| 437 | client->errorValue = mask; | |||
| 438 | return BadValue2; | |||
| 439 | } | |||
| 440 | for (i = Ones(mask); i--;) | |||
| 441 | vals[i].val = pC32[i]; | |||
| 442 | for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) { | |||
| 443 | int offset, rc; | |||
| 444 | ||||
| 445 | if (!(mask & xidfields[i].mask)) | |||
| 446 | continue; | |||
| 447 | offset = Ones(mask & (xidfields[i].mask - 1)); | |||
| 448 | if (xidfields[i].mask == GCClipMask(1L<<19) && vals[offset].val == None0L) { | |||
| 449 | vals[offset].ptr = NullPixmap((PixmapPtr)0); | |||
| 450 | continue; | |||
| 451 | } | |||
| 452 | rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, | |||
| 453 | xidfields[i].type, client, | |||
| 454 | xidfields[i].access_mode); | |||
| 455 | if (rc != Success0) { | |||
| 456 | client->errorValue = vals[offset].val; | |||
| 457 | return rc; | |||
| 458 | } | |||
| 459 | } | |||
| 460 | return ChangeGC(client, pGC, mask, vals); | |||
| 461 | } | |||
| 462 | ||||
| 463 | static GCPtr | |||
| 464 | NewGCObject(ScreenPtr pScreen, int depth) | |||
| 465 | { | |||
| 466 | GCPtr pGC; | |||
| 467 | ||||
| 468 | pGC = dixAllocateScreenObjectWithPrivates(pScreen, GC, PRIVATE_GC)_dixAllocateScreenObjectWithPrivates(pScreen, sizeof(GC), sizeof (GC), __builtin_offsetof(GC, devPrivates), PRIVATE_GC); | |||
| 469 | if (!pGC) { | |||
| 470 | return (GCPtr) NULL((void*)0); | |||
| 471 | } | |||
| 472 | ||||
| 473 | pGC->pScreen = pScreen; | |||
| 474 | pGC->depth = depth; | |||
| 475 | pGC->alu = GXcopy0x3; /* dst <- src */ | |||
| 476 | pGC->planemask = ~0; | |||
| 477 | pGC->serialNumber = 0; | |||
| 478 | pGC->funcs = 0; | |||
| 479 | pGC->fgPixel = 0; | |||
| 480 | pGC->bgPixel = 1; | |||
| 481 | pGC->lineWidth = 0; | |||
| 482 | pGC->lineStyle = LineSolid0; | |||
| 483 | pGC->capStyle = CapButt1; | |||
| 484 | pGC->joinStyle = JoinMiter0; | |||
| 485 | pGC->fillStyle = FillSolid0; | |||
| 486 | pGC->fillRule = EvenOddRule0; | |||
| 487 | pGC->arcMode = ArcPieSlice1; | |||
| 488 | pGC->tile.pixel = 0; | |||
| 489 | pGC->tile.pixmap = NullPixmap((PixmapPtr)0); | |||
| 490 | ||||
| 491 | pGC->tileIsPixel = TRUE1; | |||
| 492 | pGC->patOrg.x = 0; | |||
| 493 | pGC->patOrg.y = 0; | |||
| 494 | pGC->subWindowMode = ClipByChildren0; | |||
| 495 | pGC->graphicsExposures = TRUE1; | |||
| 496 | pGC->clipOrg.x = 0; | |||
| 497 | pGC->clipOrg.y = 0; | |||
| 498 | pGC->clientClip = (void *) NULL((void*)0); | |||
| 499 | pGC->numInDashList = 2; | |||
| 500 | pGC->dash = DefaultDash; | |||
| 501 | pGC->dashOffset = 0; | |||
| 502 | ||||
| 503 | /* use the default font and stipple */ | |||
| 504 | pGC->font = defaultFont; | |||
| 505 | if (pGC->font) /* necessary, because open of default font could fail */ | |||
| 506 | pGC->font->refcnt++; | |||
| 507 | pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; | |||
| 508 | if (pGC->stipple) | |||
| 509 | pGC->stipple->refcnt++; | |||
| 510 | ||||
| 511 | /* this is not a scratch GC */ | |||
| 512 | pGC->scratch_inuse = FALSE0; | |||
| 513 | return pGC; | |||
| 514 | } | |||
| 515 | ||||
| 516 | /* CreateGC(pDrawable, mask, pval, pStatus) | |||
| 517 | creates a default GC for the given drawable, using mask to fill | |||
| 518 | in any non-default values. | |||
| 519 | Returns a pointer to the new GC on success, NULL otherwise. | |||
| 520 | returns status of non-default fields in pStatus | |||
| 521 | BUG: | |||
| 522 | should check for failure to create default tile | |||
| 523 | ||||
| 524 | */ | |||
| 525 | GCPtr | |||
| 526 | CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, | |||
| 527 | XID gcid, ClientPtr client) | |||
| 528 | { | |||
| 529 | GCPtr pGC; | |||
| 530 | ||||
| 531 | pGC = NewGCObject(pDrawable->pScreen, pDrawable->depth); | |||
| 532 | if (!pGC) { | |||
| 533 | *pStatus = BadAlloc11; | |||
| 534 | return (GCPtr) NULL((void*)0); | |||
| 535 | } | |||
| 536 | ||||
| 537 | pGC->serialNumber = GC_CHANGE_SERIAL_BIT(((unsigned long)1)<<31); | |||
| 538 | if (mask & GCForeground(1L<<2)) { | |||
| 539 | /* | |||
| 540 | * magic special case -- ChangeGC checks for this condition | |||
| 541 | * and snags the Foreground value to create a pseudo default-tile | |||
| 542 | */ | |||
| 543 | pGC->tileIsPixel = FALSE0; | |||
| 544 | } | |||
| 545 | else { | |||
| 546 | pGC->tileIsPixel = TRUE1; | |||
| 547 | } | |||
| 548 | ||||
| 549 | /* security creation/labeling check */ | |||
| 550 | *pStatus = XaceHook(XACE_RESOURCE_ACCESS2, client, gcid, RT_GC((RESTYPE)3), pGC, | |||
| 551 | RT_NONE((RESTYPE)0), NULL((void*)0), DixCreateAccess(1<<3) | DixSetAttrAccess(1<<5)); | |||
| 552 | if (*pStatus != Success0) | |||
| 553 | goto out; | |||
| 554 | ||||
| 555 | pGC->stateChanges = GCAllBits((1 << (22 + 1)) - 1); | |||
| 556 | if (!(*pGC->pScreen->CreateGC) (pGC)) | |||
| 557 | *pStatus = BadAlloc11; | |||
| 558 | else if (mask) | |||
| 559 | *pStatus = ChangeGCXIDs(client, pGC, mask, pval); | |||
| 560 | else | |||
| 561 | *pStatus = Success0; | |||
| 562 | ||||
| 563 | out: | |||
| 564 | if (*pStatus != Success0) { | |||
| 565 | if (!pGC->tileIsPixel && !pGC->tile.pixmap) | |||
| 566 | pGC->tileIsPixel = TRUE1; /* undo special case */ | |||
| 567 | FreeGC(pGC, (XID) 0); | |||
| 568 | pGC = (GCPtr) NULL((void*)0); | |||
| 569 | } | |||
| 570 | ||||
| 571 | return pGC; | |||
| 572 | } | |||
| 573 | ||||
| 574 | static Bool | |||
| 575 | CreateDefaultTile(GCPtr pGC) | |||
| 576 | { | |||
| 577 | ChangeGCVal tmpval[3]; | |||
| 578 | PixmapPtr pTile; | |||
| 579 | GCPtr pgcScratch; | |||
| 580 | xRectangle rect; | |||
| 581 | CARD16 w, h; | |||
| 582 | ||||
| 583 | w = 1; | |||
| 584 | h = 1; | |||
| 585 | (*pGC->pScreen->QueryBestSize) (TileShape1, &w, &h, pGC->pScreen); | |||
| 586 | pTile = (PixmapPtr) | |||
| 587 | (*pGC->pScreen->CreatePixmap) (pGC->pScreen, w, h, pGC->depth, 0); | |||
| 588 | pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); | |||
| 589 | if (!pTile || !pgcScratch) { | |||
| 590 | if (pTile) | |||
| 591 | (*pTile->drawable.pScreen->DestroyPixmap) (pTile); | |||
| 592 | if (pgcScratch) | |||
| 593 | FreeScratchGC(pgcScratch); | |||
| 594 | return FALSE0; | |||
| 595 | } | |||
| 596 | tmpval[0].val = GXcopy0x3; | |||
| 597 | tmpval[1].val = pGC->tile.pixel; | |||
| 598 | tmpval[2].val = FillSolid0; | |||
| 599 | (void) ChangeGC(NullClient((ClientPtr) 0), pgcScratch, | |||
| 600 | GCFunction(1L<<0) | GCForeground(1L<<2) | GCFillStyle(1L<<8), tmpval); | |||
| 601 | ValidateGC((DrawablePtr) pTile, pgcScratch); | |||
| 602 | rect.x = 0; | |||
| 603 | rect.y = 0; | |||
| 604 | rect.width = w; | |||
| 605 | rect.height = h; | |||
| 606 | (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pTile, pgcScratch, 1, | |||
| 607 | &rect); | |||
| 608 | /* Always remember to free the scratch graphics context after use. */ | |||
| 609 | FreeScratchGC(pgcScratch); | |||
| 610 | ||||
| 611 | pGC->tileIsPixel = FALSE0; | |||
| 612 | pGC->tile.pixmap = pTile; | |||
| 613 | return TRUE1; | |||
| 614 | } | |||
| 615 | ||||
| 616 | int | |||
| 617 | CopyGC(GC * pgcSrc, GC * pgcDst, BITS32 mask) | |||
| 618 | { | |||
| 619 | BITS32 index2; | |||
| 620 | BITS32 maskQ; | |||
| 621 | int error = 0; | |||
| 622 | ||||
| 623 | if (pgcSrc == pgcDst) | |||
| ||||
| 624 | return Success0; | |||
| 625 | pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT(((unsigned long)1)<<31); | |||
| 626 | pgcDst->stateChanges |= mask; | |||
| 627 | maskQ = mask; | |||
| 628 | while (mask) { | |||
| 629 | index2 = (BITS32) lowbit(mask)((mask) & (~(mask) + 1)); | |||
| 630 | mask &= ~index2; | |||
| 631 | switch (index2) { | |||
| 632 | case GCFunction(1L<<0): | |||
| 633 | pgcDst->alu = pgcSrc->alu; | |||
| 634 | break; | |||
| 635 | case GCPlaneMask(1L<<1): | |||
| 636 | pgcDst->planemask = pgcSrc->planemask; | |||
| 637 | break; | |||
| 638 | case GCForeground(1L<<2): | |||
| 639 | pgcDst->fgPixel = pgcSrc->fgPixel; | |||
| 640 | break; | |||
| 641 | case GCBackground(1L<<3): | |||
| 642 | pgcDst->bgPixel = pgcSrc->bgPixel; | |||
| 643 | break; | |||
| 644 | case GCLineWidth(1L<<4): | |||
| 645 | pgcDst->lineWidth = pgcSrc->lineWidth; | |||
| 646 | break; | |||
| 647 | case GCLineStyle(1L<<5): | |||
| 648 | pgcDst->lineStyle = pgcSrc->lineStyle; | |||
| 649 | break; | |||
| 650 | case GCCapStyle(1L<<6): | |||
| 651 | pgcDst->capStyle = pgcSrc->capStyle; | |||
| 652 | break; | |||
| 653 | case GCJoinStyle(1L<<7): | |||
| 654 | pgcDst->joinStyle = pgcSrc->joinStyle; | |||
| 655 | break; | |||
| 656 | case GCFillStyle(1L<<8): | |||
| 657 | pgcDst->fillStyle = pgcSrc->fillStyle; | |||
| 658 | break; | |||
| 659 | case GCFillRule(1L<<9): | |||
| 660 | pgcDst->fillRule = pgcSrc->fillRule; | |||
| 661 | break; | |||
| 662 | case GCTile(1L<<10): | |||
| 663 | { | |||
| 664 | if (EqualPixUnion(pgcDst->tileIsPixel,((pgcDst->tileIsPixel) == (pgcSrc->tileIsPixel) && (((pgcDst->tileIsPixel) ? (pgcDst->tile).pixel == (pgcSrc ->tile).pixel : (pgcDst->tile).pixmap == (pgcSrc->tile ).pixmap))) | |||
| 665 | pgcDst->tile,((pgcDst->tileIsPixel) == (pgcSrc->tileIsPixel) && (((pgcDst->tileIsPixel) ? (pgcDst->tile).pixel == (pgcSrc ->tile).pixel : (pgcDst->tile).pixmap == (pgcSrc->tile ).pixmap))) | |||
| 666 | pgcSrc->tileIsPixel, pgcSrc->tile)((pgcDst->tileIsPixel) == (pgcSrc->tileIsPixel) && (((pgcDst->tileIsPixel) ? (pgcDst->tile).pixel == (pgcSrc ->tile).pixel : (pgcDst->tile).pixmap == (pgcSrc->tile ).pixmap)))) { | |||
| 667 | break; | |||
| 668 | } | |||
| 669 | if (!pgcDst->tileIsPixel) | |||
| 670 | (*pgcDst->pScreen->DestroyPixmap) (pgcDst->tile.pixmap); | |||
| 671 | pgcDst->tileIsPixel = pgcSrc->tileIsPixel; | |||
| 672 | pgcDst->tile = pgcSrc->tile; | |||
| 673 | if (!pgcDst->tileIsPixel) | |||
| 674 | pgcDst->tile.pixmap->refcnt++; | |||
| 675 | break; | |||
| 676 | } | |||
| 677 | case GCStipple(1L<<11): | |||
| 678 | { | |||
| 679 | if (pgcDst->stipple == pgcSrc->stipple) | |||
| 680 | break; | |||
| 681 | if (pgcDst->stipple) | |||
| 682 | (*pgcDst->pScreen->DestroyPixmap) (pgcDst->stipple); | |||
| 683 | pgcDst->stipple = pgcSrc->stipple; | |||
| 684 | if (pgcDst->stipple) | |||
| 685 | pgcDst->stipple->refcnt++; | |||
| 686 | break; | |||
| 687 | } | |||
| 688 | case GCTileStipXOrigin(1L<<12): | |||
| 689 | pgcDst->patOrg.x = pgcSrc->patOrg.x; | |||
| 690 | break; | |||
| 691 | case GCTileStipYOrigin(1L<<13): | |||
| 692 | pgcDst->patOrg.y = pgcSrc->patOrg.y; | |||
| 693 | break; | |||
| 694 | case GCFont(1L<<14): | |||
| 695 | if (pgcDst->font == pgcSrc->font) | |||
| 696 | break; | |||
| 697 | if (pgcDst->font) | |||
| 698 | CloseFont(pgcDst->font, (Font) 0); | |||
| 699 | if ((pgcDst->font = pgcSrc->font) != NullFont((FontPtr) 0)) | |||
| 700 | (pgcDst->font)->refcnt++; | |||
| 701 | break; | |||
| 702 | case GCSubwindowMode(1L<<15): | |||
| 703 | pgcDst->subWindowMode = pgcSrc->subWindowMode; | |||
| 704 | break; | |||
| 705 | case GCGraphicsExposures(1L<<16): | |||
| 706 | pgcDst->graphicsExposures = pgcSrc->graphicsExposures; | |||
| 707 | break; | |||
| 708 | case GCClipXOrigin(1L<<17): | |||
| 709 | pgcDst->clipOrg.x = pgcSrc->clipOrg.x; | |||
| 710 | break; | |||
| 711 | case GCClipYOrigin(1L<<18): | |||
| 712 | pgcDst->clipOrg.y = pgcSrc->clipOrg.y; | |||
| 713 | break; | |||
| 714 | case GCClipMask(1L<<19): | |||
| 715 | (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc); | |||
| 716 | break; | |||
| 717 | case GCDashOffset(1L<<20): | |||
| 718 | pgcDst->dashOffset = pgcSrc->dashOffset; | |||
| 719 | break; | |||
| 720 | case GCDashList(1L<<21): | |||
| 721 | if (pgcSrc->dash == DefaultDash) { | |||
| 722 | if (pgcDst->dash != DefaultDash) { | |||
| 723 | free(pgcDst->dash); | |||
| 724 | pgcDst->numInDashList = pgcSrc->numInDashList; | |||
| 725 | pgcDst->dash = pgcSrc->dash; | |||
| 726 | } | |||
| 727 | } | |||
| 728 | else { | |||
| 729 | unsigned char *dash; | |||
| 730 | unsigned int i; | |||
| 731 | ||||
| 732 | dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); | |||
| 733 | if (dash) { | |||
| 734 | if (pgcDst->dash != DefaultDash) | |||
| 735 | free(pgcDst->dash); | |||
| 736 | pgcDst->numInDashList = pgcSrc->numInDashList; | |||
| 737 | pgcDst->dash = dash; | |||
| 738 | for (i = 0; i < pgcSrc->numInDashList; i++) | |||
| 739 | dash[i] = pgcSrc->dash[i]; | |||
| ||||
| 740 | } | |||
| 741 | else | |||
| 742 | error = BadAlloc11; | |||
| 743 | } | |||
| 744 | break; | |||
| 745 | case GCArcMode(1L<<22): | |||
| 746 | pgcDst->arcMode = pgcSrc->arcMode; | |||
| 747 | break; | |||
| 748 | default: | |||
| 749 | FatalError("CopyGC: Unhandled mask!\n"); | |||
| 750 | } | |||
| 751 | } | |||
| 752 | if (pgcDst->fillStyle == FillTiled1 && pgcDst->tileIsPixel) { | |||
| 753 | if (!CreateDefaultTile(pgcDst)) { | |||
| 754 | pgcDst->fillStyle = FillSolid0; | |||
| 755 | error = BadAlloc11; | |||
| 756 | } | |||
| 757 | } | |||
| 758 | (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); | |||
| 759 | return error; | |||
| 760 | } | |||
| 761 | ||||
| 762 | /** | |||
| 763 | * does the diX part of freeing the characteristics in the GC. | |||
| 764 | * | |||
| 765 | * \param value must conform to DeleteType | |||
| 766 | */ | |||
| 767 | int | |||
| 768 | FreeGC(void *value, XID gid) | |||
| 769 | { | |||
| 770 | GCPtr pGC = (GCPtr) value; | |||
| 771 | ||||
| 772 | CloseFont(pGC->font, (Font) 0); | |||
| 773 | (*pGC->funcs->DestroyClip) (pGC); | |||
| 774 | ||||
| 775 | if (!pGC->tileIsPixel) | |||
| 776 | (*pGC->pScreen->DestroyPixmap) (pGC->tile.pixmap); | |||
| 777 | if (pGC->stipple) | |||
| 778 | (*pGC->pScreen->DestroyPixmap) (pGC->stipple); | |||
| 779 | ||||
| 780 | (*pGC->funcs->DestroyGC) (pGC); | |||
| 781 | if (pGC->dash != DefaultDash) | |||
| 782 | free(pGC->dash); | |||
| 783 | dixFreeObjectWithPrivates(pGC, PRIVATE_GC)_dixFreeObjectWithPrivates(pGC, (pGC)->devPrivates, PRIVATE_GC ); | |||
| 784 | return Success0; | |||
| 785 | } | |||
| 786 | ||||
| 787 | /* CreateScratchGC(pScreen, depth) | |||
| 788 | like CreateGC, but doesn't do the default tile or stipple, | |||
| 789 | since we can't create them without already having a GC. any code | |||
| 790 | using the tile or stipple has to set them explicitly anyway, | |||
| 791 | since the state of the scratch gc is unknown. This is OK | |||
| 792 | because ChangeGC() has to be able to deal with NULL tiles and | |||
| 793 | stipples anyway (in case the CreateGC() call has provided a | |||
| 794 | value for them -- we can't set the default tile until the | |||
| 795 | client-supplied attributes are installed, since the fgPixel | |||
| 796 | is what fills the default tile. (maybe this comment should | |||
| 797 | go with CreateGC() or ChangeGC().) | |||
| 798 | */ | |||
| 799 | ||||
| 800 | static GCPtr | |||
| 801 | CreateScratchGC(ScreenPtr pScreen, unsigned depth) | |||
| 802 | { | |||
| 803 | GCPtr pGC; | |||
| 804 | ||||
| 805 | pGC = NewGCObject(pScreen, depth); | |||
| 806 | if (!pGC) | |||
| 807 | return (GCPtr) NULL((void*)0); | |||
| 808 | ||||
| 809 | pGC->stateChanges = GCAllBits((1 << (22 + 1)) - 1); | |||
| 810 | if (!(*pScreen->CreateGC) (pGC)) { | |||
| 811 | FreeGC(pGC, (XID) 0); | |||
| 812 | pGC = (GCPtr) NULL((void*)0); | |||
| 813 | } | |||
| 814 | return pGC; | |||
| 815 | } | |||
| 816 | ||||
| 817 | void | |||
| 818 | FreeGCperDepth(int screenNum) | |||
| 819 | { | |||
| 820 | int i; | |||
| 821 | ScreenPtr pScreen; | |||
| 822 | GCPtr *ppGC; | |||
| 823 | ||||
| 824 | pScreen = screenInfo.screens[screenNum]; | |||
| 825 | ppGC = pScreen->GCperDepth; | |||
| 826 | ||||
| 827 | for (i = 0; i <= pScreen->numDepths; i++) { | |||
| 828 | (void) FreeGC(ppGC[i], (XID) 0); | |||
| 829 | ppGC[i] = NULL((void*)0); | |||
| 830 | } | |||
| 831 | } | |||
| 832 | ||||
| 833 | Bool | |||
| 834 | CreateGCperDepth(int screenNum) | |||
| 835 | { | |||
| 836 | int i; | |||
| 837 | ScreenPtr pScreen; | |||
| 838 | DepthPtr pDepth; | |||
| 839 | GCPtr *ppGC; | |||
| 840 | ||||
| 841 | pScreen = screenInfo.screens[screenNum]; | |||
| 842 | ppGC = pScreen->GCperDepth; | |||
| 843 | /* do depth 1 separately because it's not included in list */ | |||
| 844 | if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) | |||
| 845 | return FALSE0; | |||
| 846 | ppGC[0]->graphicsExposures = FALSE0; | |||
| 847 | /* Make sure we don't overflow GCperDepth[] */ | |||
| 848 | if (pScreen->numDepths > MAXFORMATS8) | |||
| 849 | return FALSE0; | |||
| 850 | ||||
| 851 | pDepth = pScreen->allowedDepths; | |||
| 852 | for (i = 0; i < pScreen->numDepths; i++, pDepth++) { | |||
| 853 | if (!(ppGC[i + 1] = CreateScratchGC(pScreen, pDepth->depth))) { | |||
| 854 | for (; i >= 0; i--) | |||
| 855 | (void) FreeGC(ppGC[i], (XID) 0); | |||
| 856 | return FALSE0; | |||
| 857 | } | |||
| 858 | ppGC[i + 1]->graphicsExposures = FALSE0; | |||
| 859 | } | |||
| 860 | return TRUE1; | |||
| 861 | } | |||
| 862 | ||||
| 863 | Bool | |||
| 864 | CreateDefaultStipple(int screenNum) | |||
| 865 | { | |||
| 866 | ScreenPtr pScreen; | |||
| 867 | ChangeGCVal tmpval[3]; | |||
| 868 | xRectangle rect; | |||
| 869 | CARD16 w, h; | |||
| 870 | GCPtr pgcScratch; | |||
| 871 | ||||
| 872 | pScreen = screenInfo.screens[screenNum]; | |||
| 873 | ||||
| 874 | w = 16; | |||
| 875 | h = 16; | |||
| 876 | (*pScreen->QueryBestSize) (StippleShape2, &w, &h, pScreen); | |||
| 877 | if (!(pScreen->PixmapPerDepth[0] = | |||
| 878 | (*pScreen->CreatePixmap) (pScreen, w, h, 1, 0))) | |||
| 879 | return FALSE0; | |||
| 880 | /* fill stipple with 1 */ | |||
| 881 | tmpval[0].val = GXcopy0x3; | |||
| 882 | tmpval[1].val = 1; | |||
| 883 | tmpval[2].val = FillSolid0; | |||
| 884 | pgcScratch = GetScratchGC(1, pScreen); | |||
| 885 | if (!pgcScratch) { | |||
| 886 | (*pScreen->DestroyPixmap) (pScreen->PixmapPerDepth[0]); | |||
| 887 | return FALSE0; | |||
| 888 | } | |||
| 889 | (void) ChangeGC(NullClient((ClientPtr) 0), pgcScratch, | |||
| 890 | GCFunction(1L<<0) | GCForeground(1L<<2) | GCFillStyle(1L<<8), tmpval); | |||
| 891 | ValidateGC((DrawablePtr) pScreen->PixmapPerDepth[0], pgcScratch); | |||
| 892 | rect.x = 0; | |||
| 893 | rect.y = 0; | |||
| 894 | rect.width = w; | |||
| 895 | rect.height = h; | |||
| 896 | (*pgcScratch->ops->PolyFillRect) ((DrawablePtr) pScreen->PixmapPerDepth[0], | |||
| 897 | pgcScratch, 1, &rect); | |||
| 898 | FreeScratchGC(pgcScratch); | |||
| 899 | return TRUE1; | |||
| 900 | } | |||
| 901 | ||||
| 902 | void | |||
| 903 | FreeDefaultStipple(int screenNum) | |||
| 904 | { | |||
| 905 | ScreenPtr pScreen = screenInfo.screens[screenNum]; | |||
| 906 | ||||
| 907 | (*pScreen->DestroyPixmap) (pScreen->PixmapPerDepth[0]); | |||
| 908 | } | |||
| 909 | ||||
| 910 | int | |||
| 911 | SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) | |||
| 912 | { | |||
| 913 | long i; | |||
| 914 | unsigned char *p, *indash; | |||
| 915 | BITS32 maskQ = 0; | |||
| 916 | ||||
| 917 | i = ndash; | |||
| 918 | p = pdash; | |||
| 919 | while (i--) { | |||
| 920 | if (!*p++) { | |||
| 921 | /* dash segment must be > 0 */ | |||
| 922 | return BadValue2; | |||
| 923 | } | |||
| 924 | } | |||
| 925 | ||||
| 926 | if (ndash & 1) | |||
| 927 | p = malloc(2 * ndash * sizeof(unsigned char)); | |||
| 928 | else | |||
| 929 | p = malloc(ndash * sizeof(unsigned char)); | |||
| 930 | if (!p) | |||
| 931 | return BadAlloc11; | |||
| 932 | ||||
| 933 | pGC->serialNumber |= GC_CHANGE_SERIAL_BIT(((unsigned long)1)<<31); | |||
| 934 | if (offset != pGC->dashOffset) { | |||
| 935 | pGC->dashOffset = offset; | |||
| 936 | pGC->stateChanges |= GCDashOffset(1L<<20); | |||
| 937 | maskQ |= GCDashOffset(1L<<20); | |||
| 938 | } | |||
| 939 | ||||
| 940 | if (pGC->dash != DefaultDash) | |||
| 941 | free(pGC->dash); | |||
| 942 | pGC->numInDashList = ndash; | |||
| 943 | pGC->dash = p; | |||
| 944 | if (ndash & 1) { | |||
| 945 | pGC->numInDashList += ndash; | |||
| 946 | indash = pdash; | |||
| 947 | i = ndash; | |||
| 948 | while (i--) | |||
| 949 | *p++ = *indash++; | |||
| 950 | } | |||
| 951 | while (ndash--) | |||
| 952 | *p++ = *pdash++; | |||
| 953 | pGC->stateChanges |= GCDashList(1L<<21); | |||
| 954 | maskQ |= GCDashList(1L<<21); | |||
| 955 | ||||
| 956 | if (pGC->funcs->ChangeGC) | |||
| 957 | (*pGC->funcs->ChangeGC) (pGC, maskQ); | |||
| 958 | return Success0; | |||
| 959 | } | |||
| 960 | ||||
| 961 | int | |||
| 962 | VerifyRectOrder(int nrects, xRectangle *prects, int ordering) | |||
| 963 | { | |||
| 964 | xRectangle *prectP, *prectN; | |||
| 965 | int i; | |||
| 966 | ||||
| 967 | switch (ordering) { | |||
| 968 | case Unsorted0: | |||
| 969 | return CT_UNSORTED6; | |||
| 970 | case YSorted1: | |||
| 971 | if (nrects > 1) { | |||
| 972 | for (i = 1, prectP = prects, prectN = prects + 1; | |||
| 973 | i < nrects; i++, prectP++, prectN++) | |||
| 974 | if (prectN->y < prectP->y) | |||
| 975 | return -1; | |||
| 976 | } | |||
| 977 | return CT_YSORTED10; | |||
| 978 | case YXSorted2: | |||
| 979 | if (nrects > 1) { | |||
| 980 | for (i = 1, prectP = prects, prectN = prects + 1; | |||
| 981 | i < nrects; i++, prectP++, prectN++) | |||
| 982 | if ((prectN->y < prectP->y) || | |||
| 983 | ((prectN->y == prectP->y) && (prectN->x < prectP->x))) | |||
| 984 | return -1; | |||
| 985 | } | |||
| 986 | return CT_YXSORTED14; | |||
| 987 | case YXBanded3: | |||
| 988 | if (nrects > 1) { | |||
| 989 | for (i = 1, prectP = prects, prectN = prects + 1; | |||
| 990 | i < nrects; i++, prectP++, prectN++) | |||
| 991 | if ((prectN->y != prectP->y && | |||
| 992 | prectN->y < prectP->y + (int) prectP->height) || | |||
| 993 | ((prectN->y == prectP->y) && | |||
| 994 | (prectN->height != prectP->height || | |||
| 995 | prectN->x < prectP->x + (int) prectP->width))) | |||
| 996 | return -1; | |||
| 997 | } | |||
| 998 | return CT_YXBANDED18; | |||
| 999 | } | |||
| 1000 | return -1; | |||
| 1001 | } | |||
| 1002 | ||||
| 1003 | int | |||
| 1004 | SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, | |||
| 1005 | xRectangle *prects, int ordering) | |||
| 1006 | { | |||
| 1007 | int newct, size; | |||
| 1008 | xRectangle *prectsNew; | |||
| 1009 | ||||
| 1010 | newct = VerifyRectOrder(nrects, prects, ordering); | |||
| 1011 | if (newct < 0) | |||
| 1012 | return BadMatch8; | |||
| 1013 | size = nrects * sizeof(xRectangle); | |||
| 1014 | prectsNew = malloc(size); | |||
| 1015 | if (!prectsNew && size) | |||
| 1016 | return BadAlloc11; | |||
| 1017 | ||||
| 1018 | pGC->serialNumber |= GC_CHANGE_SERIAL_BIT(((unsigned long)1)<<31); | |||
| 1019 | pGC->clipOrg.x = xOrigin; | |||
| 1020 | pGC->stateChanges |= GCClipXOrigin(1L<<17); | |||
| 1021 | ||||
| 1022 | pGC->clipOrg.y = yOrigin; | |||
| 1023 | pGC->stateChanges |= GCClipYOrigin(1L<<18); | |||
| 1024 | ||||
| 1025 | if (size) | |||
| 1026 | memmove((char *) prectsNew, (char *) prects, size)__builtin___memmove_chk ((char *) prectsNew, (char *) prects, size, __builtin_object_size ((char *) prectsNew, 0)); | |||
| 1027 | (*pGC->funcs->ChangeClip) (pGC, newct, (void *) prectsNew, nrects); | |||
| 1028 | if (pGC->funcs->ChangeGC) | |||
| 1029 | (*pGC->funcs->ChangeGC) (pGC, | |||
| 1030 | GCClipXOrigin(1L<<17) | GCClipYOrigin(1L<<18) | GCClipMask(1L<<19)); | |||
| 1031 | return Success0; | |||
| 1032 | } | |||
| 1033 | ||||
| 1034 | /* | |||
| 1035 | sets reasonable defaults | |||
| 1036 | if we can get a pre-allocated one, use it and mark it as used. | |||
| 1037 | if we can't, create one out of whole cloth (The Velveteen GC -- if | |||
| 1038 | you use it often enough it will become real.) | |||
| 1039 | */ | |||
| 1040 | GCPtr | |||
| 1041 | GetScratchGC(unsigned depth, ScreenPtr pScreen) | |||
| 1042 | { | |||
| 1043 | int i; | |||
| 1044 | GCPtr pGC; | |||
| 1045 | ||||
| 1046 | for (i = 0; i <= pScreen->numDepths; i++) { | |||
| 1047 | pGC = pScreen->GCperDepth[i]; | |||
| 1048 | if (pGC && pGC->depth == depth && !pGC->scratch_inuse) { | |||
| 1049 | pGC->scratch_inuse = TRUE1; | |||
| 1050 | ||||
| 1051 | pGC->alu = GXcopy0x3; | |||
| 1052 | pGC->planemask = ~0; | |||
| 1053 | pGC->serialNumber = 0; | |||
| 1054 | pGC->fgPixel = 0; | |||
| 1055 | pGC->bgPixel = 1; | |||
| 1056 | pGC->lineWidth = 0; | |||
| 1057 | pGC->lineStyle = LineSolid0; | |||
| 1058 | pGC->capStyle = CapButt1; | |||
| 1059 | pGC->joinStyle = JoinMiter0; | |||
| 1060 | pGC->fillStyle = FillSolid0; | |||
| 1061 | pGC->fillRule = EvenOddRule0; | |||
| 1062 | pGC->arcMode = ArcChord0; | |||
| 1063 | pGC->patOrg.x = 0; | |||
| 1064 | pGC->patOrg.y = 0; | |||
| 1065 | pGC->subWindowMode = ClipByChildren0; | |||
| 1066 | pGC->graphicsExposures = FALSE0; | |||
| 1067 | pGC->clipOrg.x = 0; | |||
| 1068 | pGC->clipOrg.y = 0; | |||
| 1069 | if (pGC->clientClip) | |||
| 1070 | (*pGC->funcs->ChangeClip) (pGC, CT_NONE0, NULL((void*)0), 0); | |||
| 1071 | pGC->stateChanges = GCAllBits((1 << (22 + 1)) - 1); | |||
| 1072 | return pGC; | |||
| 1073 | } | |||
| 1074 | } | |||
| 1075 | /* if we make it this far, need to roll our own */ | |||
| 1076 | pGC = CreateScratchGC(pScreen, depth); | |||
| 1077 | if (pGC) | |||
| 1078 | pGC->graphicsExposures = FALSE0; | |||
| 1079 | return pGC; | |||
| 1080 | } | |||
| 1081 | ||||
| 1082 | /* | |||
| 1083 | if the gc to free is in the table of pre-existing ones, | |||
| 1084 | mark it as available. | |||
| 1085 | if not, free it for real | |||
| 1086 | */ | |||
| 1087 | void | |||
| 1088 | FreeScratchGC(GCPtr pGC) | |||
| 1089 | { | |||
| 1090 | if (pGC->scratch_inuse) | |||
| 1091 | pGC->scratch_inuse = FALSE0; | |||
| 1092 | else | |||
| 1093 | FreeGC(pGC, (GContext) 0); | |||
| 1094 | } |