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 | } |