~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to dix/gc.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/programs/Xserver/dix/gc.c,v 3.9 2001/12/14 19:59:32 dawes Exp $ */
 
2
/***********************************************************
 
3
 
 
4
Copyright 1987, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
Except as contained in this notice, the name of The Open Group shall not be
 
23
used in advertising or otherwise to promote the sale, use or other dealings
 
24
in this Software without prior written authorization from The Open Group.
 
25
 
 
26
 
 
27
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
28
 
 
29
                        All Rights Reserved
 
30
 
 
31
Permission to use, copy, modify, and distribute this software and its 
 
32
documentation for any purpose and without fee is hereby granted, 
 
33
provided that the above copyright notice appear in all copies and that
 
34
both that copyright notice and this permission notice appear in 
 
35
supporting documentation, and that the name of Digital not be
 
36
used in advertising or publicity pertaining to distribution of the
 
37
software without specific, written prior permission.  
 
38
 
 
39
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
40
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
41
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
42
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
43
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
44
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
45
SOFTWARE.
 
46
 
 
47
******************************************************************/
 
48
 
 
49
/* $Xorg: gc.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */
 
50
 
 
51
#ifdef HAVE_DIX_CONFIG_H
 
52
#include <dix-config.h>
 
53
#endif
 
54
 
 
55
#include <X11/X.h>
 
56
#include <X11/Xmd.h>
 
57
#include <X11/Xproto.h>
 
58
#include "misc.h"
 
59
#include "resource.h"
 
60
#include "gcstruct.h"
 
61
#include "pixmapstr.h"
 
62
#include "dixfontstr.h"
 
63
#include "scrnintstr.h"
 
64
#include "region.h"
 
65
 
 
66
#include "dix.h"
 
67
#include <assert.h>
 
68
 
 
69
extern XID clientErrorValue;
 
70
extern FontPtr defaultFont;
 
71
 
 
72
static Bool CreateDefaultTile(GCPtr pGC);
 
73
 
 
74
unsigned char DefaultDash[2] = {4, 4};
 
75
 
 
76
void
 
77
ValidateGC(DrawablePtr pDraw, GC *pGC)
 
78
{
 
79
    (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw);
 
80
    pGC->stateChanges = 0;
 
81
    pGC->serialNumber = pDraw->serialNumber;
 
82
}
 
83
 
 
84
 
 
85
/* dixChangeGC(client, pGC, mask, pC32, pUnion)
 
86
 * 
 
87
 * This function was created as part of the Security extension
 
88
 * implementation.  The client performing the gc change must be passed so
 
89
 * that access checks can be performed on any tiles, stipples, or fonts
 
90
 * that are specified.  ddxen can call this too; they should normally
 
91
 * pass NullClient for the client since any access checking should have
 
92
 * already been done at a higher level.
 
93
 * 
 
94
 * Since we had to create a new function anyway, we decided to change the
 
95
 * way the list of gc values is passed to eliminate the compiler warnings
 
96
 * caused by the DoChangeGC interface.  You can pass the values via pC32
 
97
 * or pUnion, but not both; one of them must be NULL.  If you don't need
 
98
 * to pass any pointers, you can use either one:
 
99
 * 
 
100
 *     example calling dixChangeGC using pC32 parameter
 
101
 *
 
102
 *     CARD32 v[2];
 
103
 *     v[0] = foreground;
 
104
 *     v[1] = background;
 
105
 *     dixChangeGC(client, pGC, GCForeground|GCBackground, v, NULL);
 
106
 * 
 
107
 *     example calling dixChangeGC using pUnion parameter;
 
108
 *     same effect as above
 
109
 *
 
110
 *     ChangeGCVal v[2];
 
111
 *     v[0].val = foreground;
 
112
 *     v[1].val = background;
 
113
 *     dixChangeGC(client, pGC, GCForeground|GCBackground, NULL, v);
 
114
 * 
 
115
 * However, if you need to pass a pointer to a pixmap or font, you MUST
 
116
 * use the pUnion parameter.
 
117
 * 
 
118
 *     example calling dixChangeGC passing pointers in the value list
 
119
 *     v[1].ptr is a pointer to a pixmap
 
120
 *
 
121
 *     ChangeGCVal v[2];
 
122
 *     v[0].val = FillTiled;
 
123
 *     v[1].ptr = pPixmap;
 
124
 *     dixChangeGC(client, pGC, GCFillStyle|GCTile, NULL, v);
 
125
 * 
 
126
 * Note: we could have gotten by with just the pUnion parameter, but on
 
127
 * 64 bit machines that would have forced us to copy the value list that
 
128
 * comes in the ChangeGC request.
 
129
 * 
 
130
 * Ideally, we'd change all the DoChangeGC calls to dixChangeGC, but this
 
131
 * is far too many changes to consider at this time, so we've only
 
132
 * changed the ones that caused compiler warnings.  New code should use
 
133
 * dixChangeGC.
 
134
 * 
 
135
 * dpw
 
136
 */
 
137
 
 
138
#define NEXTVAL(_type, _var) { \
 
139
      if (pC32) _var = (_type)*pC32++; \
 
140
      else { \
 
141
        _var = (_type)(pUnion->val); pUnion++; \
 
142
      } \
 
143
    }
 
144
 
 
145
#define NEXT_PTR(_type, _var) { \
 
146
    assert(pUnion); _var = (_type)pUnion->ptr; pUnion++; }
 
147
 
 
148
int
 
149
dixChangeGC(ClientPtr client, register GC *pGC, register BITS32 mask, CARD32 *pC32, ChangeGCValPtr pUnion)
 
150
{
 
151
    register BITS32     index2;
 
152
    register int        error = 0;
 
153
    PixmapPtr           pPixmap;
 
154
    BITS32              maskQ;
 
155
 
 
156
    assert( (pC32 && !pUnion) || (!pC32 && pUnion) );
 
157
    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
 
158
 
 
159
    maskQ = mask;       /* save these for when we walk the GCque */
 
160
    while (mask && !error) 
 
161
    {
 
162
        index2 = (BITS32) lowbit (mask);
 
163
        mask &= ~index2;
 
164
        pGC->stateChanges |= index2;
 
165
        switch (index2)
 
166
        {
 
167
            case GCFunction:
 
168
            {
 
169
                CARD8 newalu;
 
170
                NEXTVAL(CARD8, newalu);
 
171
                if (newalu <= GXset)
 
172
                    pGC->alu = newalu;
 
173
                else
 
174
                {
 
175
                    clientErrorValue = newalu;
 
176
                    error = BadValue;
 
177
                }
 
178
                break;
 
179
            }
 
180
            case GCPlaneMask:
 
181
                NEXTVAL(unsigned long, pGC->planemask);
 
182
                break;
 
183
            case GCForeground:
 
184
                NEXTVAL(unsigned long, pGC->fgPixel);
 
185
                /*
 
186
                 * this is for CreateGC
 
187
                 */
 
188
                if (!pGC->tileIsPixel && !pGC->tile.pixmap)
 
189
                {
 
190
                    pGC->tileIsPixel = TRUE;
 
191
                    pGC->tile.pixel = pGC->fgPixel;
 
192
                }
 
193
                break;
 
194
            case GCBackground:
 
195
                NEXTVAL(unsigned long, pGC->bgPixel);
 
196
                break;
 
197
            case GCLineWidth:           /* ??? line width is a CARD16 */
 
198
                 NEXTVAL(CARD16, pGC->lineWidth);
 
199
                break;
 
200
            case GCLineStyle:
 
201
            {
 
202
                unsigned int newlinestyle;
 
203
                NEXTVAL(unsigned int, newlinestyle);
 
204
                if (newlinestyle <= LineDoubleDash)
 
205
                    pGC->lineStyle = newlinestyle;
 
206
                else
 
207
                {
 
208
                    clientErrorValue = newlinestyle;
 
209
                    error = BadValue;
 
210
                }
 
211
                break;
 
212
            }
 
213
            case GCCapStyle:
 
214
            {
 
215
                unsigned int newcapstyle;
 
216
                NEXTVAL(unsigned int, newcapstyle);
 
217
                if (newcapstyle <= CapProjecting)
 
218
                    pGC->capStyle = newcapstyle;
 
219
                else
 
220
                {
 
221
                    clientErrorValue = newcapstyle;
 
222
                    error = BadValue;
 
223
                }
 
224
                break;
 
225
            }
 
226
            case GCJoinStyle:
 
227
            {
 
228
                unsigned int newjoinstyle;
 
229
                NEXTVAL(unsigned int, newjoinstyle);
 
230
                if (newjoinstyle <= JoinBevel)
 
231
                    pGC->joinStyle = newjoinstyle;
 
232
                else
 
233
                {
 
234
                    clientErrorValue = newjoinstyle;
 
235
                    error = BadValue;
 
236
                }
 
237
                break;
 
238
            }
 
239
            case GCFillStyle:
 
240
            {
 
241
                unsigned int newfillstyle;
 
242
                NEXTVAL(unsigned int, newfillstyle);
 
243
                if (newfillstyle <= FillOpaqueStippled)
 
244
                    pGC->fillStyle = newfillstyle;
 
245
                else
 
246
                {
 
247
                    clientErrorValue = newfillstyle;
 
248
                    error = BadValue;
 
249
                }
 
250
                break;
 
251
            }
 
252
            case GCFillRule:
 
253
            {
 
254
                unsigned int newfillrule;
 
255
                NEXTVAL(unsigned int, newfillrule);
 
256
                if (newfillrule <= WindingRule)
 
257
                    pGC->fillRule = newfillrule;
 
258
                else
 
259
                {
 
260
                    clientErrorValue = newfillrule;
 
261
                    error = BadValue;
 
262
                }
 
263
                break;
 
264
            }
 
265
            case GCTile:
 
266
            {
 
267
                XID newpix = 0;
 
268
                if (pUnion)
 
269
                {
 
270
                    NEXT_PTR(PixmapPtr, pPixmap);
 
271
                }
 
272
                else
 
273
                {
 
274
                    NEXTVAL(XID, newpix);
 
275
                    pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
 
276
                                        newpix, RT_PIXMAP, SecurityReadAccess);
 
277
                }
 
278
                if (pPixmap)
 
279
                {
 
280
                    if ((pPixmap->drawable.depth != pGC->depth) ||
 
281
                        (pPixmap->drawable.pScreen != pGC->pScreen))
 
282
                    {
 
283
                        error = BadMatch;
 
284
                    }
 
285
                    else
 
286
                    {
 
287
                        pPixmap->refcnt++;
 
288
                        if (!pGC->tileIsPixel)
 
289
                            (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
 
290
                        pGC->tileIsPixel = FALSE;
 
291
                        pGC->tile.pixmap = pPixmap;
 
292
                    }
 
293
                }
 
294
                else
 
295
                {
 
296
                    clientErrorValue = newpix;
 
297
                    error = BadPixmap;
 
298
                }
 
299
                break;
 
300
            }
 
301
            case GCStipple:
 
302
            {
 
303
                XID newstipple = 0;
 
304
                if (pUnion)
 
305
                {
 
306
                    NEXT_PTR(PixmapPtr, pPixmap);
 
307
                }
 
308
                else
 
309
                {
 
310
                    NEXTVAL(XID, newstipple)
 
311
                    pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
 
312
                                newstipple, RT_PIXMAP, SecurityReadAccess);
 
313
                }
 
314
                if (pPixmap)
 
315
                {
 
316
                    if ((pPixmap->drawable.depth != 1) ||
 
317
                        (pPixmap->drawable.pScreen != pGC->pScreen))
 
318
                    {
 
319
                        error = BadMatch;
 
320
                    }
 
321
                    else
 
322
                    {
 
323
                        pPixmap->refcnt++;
 
324
                        if (pGC->stipple)
 
325
                            (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
 
326
                        pGC->stipple = pPixmap;
 
327
                    }
 
328
                }
 
329
                else
 
330
                {
 
331
                    clientErrorValue = newstipple;
 
332
                    error = BadPixmap;
 
333
                }
 
334
                break;
 
335
            }
 
336
            case GCTileStipXOrigin:
 
337
                NEXTVAL(INT16, pGC->patOrg.x);
 
338
                break;
 
339
            case GCTileStipYOrigin:
 
340
                NEXTVAL(INT16, pGC->patOrg.y);
 
341
                break;
 
342
            case GCFont:
 
343
            {
 
344
                FontPtr pFont;
 
345
                XID newfont = 0;
 
346
                if (pUnion)
 
347
                {
 
348
                    NEXT_PTR(FontPtr, pFont);
 
349
                }
 
350
                else
 
351
                {
 
352
                    NEXTVAL(XID, newfont)
 
353
                    pFont = (FontPtr)SecurityLookupIDByType(client, newfont,
 
354
                                                RT_FONT, SecurityReadAccess);
 
355
                }
 
356
                if (pFont)
 
357
                {
 
358
                    pFont->refcnt++;
 
359
                    if (pGC->font)
 
360
                        CloseFont(pGC->font, (Font)0);
 
361
                    pGC->font = pFont;
 
362
                 }
 
363
                else
 
364
                {
 
365
                    clientErrorValue = newfont;
 
366
                    error = BadFont;
 
367
                }
 
368
                break;
 
369
            }
 
370
            case GCSubwindowMode:
 
371
            {
 
372
                unsigned int newclipmode;
 
373
                NEXTVAL(unsigned int, newclipmode);
 
374
                if (newclipmode <= IncludeInferiors)
 
375
                    pGC->subWindowMode = newclipmode;
 
376
                else
 
377
                {
 
378
                    clientErrorValue = newclipmode;
 
379
                    error = BadValue;
 
380
                }
 
381
                break;
 
382
            }
 
383
            case GCGraphicsExposures:
 
384
            {
 
385
                unsigned int newge;
 
386
                NEXTVAL(unsigned int, newge);
 
387
                if (newge <= xTrue)
 
388
                    pGC->graphicsExposures = newge;
 
389
                else
 
390
                {
 
391
                    clientErrorValue = newge;
 
392
                    error = BadValue;
 
393
                }
 
394
                break;
 
395
            }
 
396
            case GCClipXOrigin:
 
397
                NEXTVAL(INT16, pGC->clipOrg.x);
 
398
                break;
 
399
            case GCClipYOrigin:
 
400
                NEXTVAL(INT16, pGC->clipOrg.y);
 
401
                break;
 
402
            case GCClipMask:
 
403
            {
 
404
                Pixmap pid = 0;
 
405
                int    clipType = 0;
 
406
 
 
407
                if (pUnion)
 
408
                {
 
409
                    NEXT_PTR(PixmapPtr, pPixmap);
 
410
                }
 
411
                else
 
412
                {
 
413
                    NEXTVAL(Pixmap, pid)
 
414
                    if (pid == None)
 
415
                    {
 
416
                        clipType = CT_NONE;
 
417
                        pPixmap = NullPixmap;
 
418
                    }
 
419
                    else
 
420
                        pPixmap = (PixmapPtr)SecurityLookupIDByType(client,
 
421
                                        pid, RT_PIXMAP, SecurityReadAccess);
 
422
                }
 
423
 
 
424
                if (pPixmap)
 
425
                {
 
426
                    if ((pPixmap->drawable.depth != 1) ||
 
427
                        (pPixmap->drawable.pScreen != pGC->pScreen))
 
428
                    {
 
429
                        error = BadMatch;
 
430
                    }
 
431
                    else
 
432
                    {
 
433
                        clipType = CT_PIXMAP;
 
434
                        pPixmap->refcnt++;
 
435
                    }
 
436
                }
 
437
                else if (!pUnion && (pid != None))
 
438
                {
 
439
                    clientErrorValue = pid;
 
440
                    error = BadPixmap;
 
441
                }
 
442
                if(error == Success)
 
443
                {
 
444
                    (*pGC->funcs->ChangeClip)(pGC, clipType,
 
445
                                              (pointer)pPixmap, 0);
 
446
                }
 
447
                break;
 
448
            }
 
449
            case GCDashOffset:
 
450
                NEXTVAL(INT16, pGC->dashOffset);
 
451
                break;
 
452
            case GCDashList:
 
453
            {
 
454
                CARD8 newdash;
 
455
                NEXTVAL(CARD8, newdash);
 
456
                if (newdash == 4)
 
457
                {
 
458
                    if (pGC->dash != DefaultDash)
 
459
                    {
 
460
                        xfree(pGC->dash);
 
461
                        pGC->numInDashList = 2;
 
462
                        pGC->dash = DefaultDash;
 
463
                    }
 
464
                }
 
465
                else if (newdash != 0)
 
466
                {
 
467
                    unsigned char *dash;
 
468
 
 
469
                    dash = (unsigned char *)xalloc(2 * sizeof(unsigned char));
 
470
                    if (dash)
 
471
                    {
 
472
                        if (pGC->dash != DefaultDash)
 
473
                            xfree(pGC->dash);
 
474
                        pGC->numInDashList = 2;
 
475
                        pGC->dash = dash;
 
476
                        dash[0] = newdash;
 
477
                        dash[1] = newdash;
 
478
                    }
 
479
                    else
 
480
                        error = BadAlloc;
 
481
                }
 
482
                else
 
483
                {
 
484
                   clientErrorValue = newdash;
 
485
                   error = BadValue;
 
486
                }
 
487
                break;
 
488
            }
 
489
            case GCArcMode:
 
490
            {
 
491
                unsigned int newarcmode;
 
492
                NEXTVAL(unsigned int, newarcmode);
 
493
                if (newarcmode <= ArcPieSlice)
 
494
                    pGC->arcMode = newarcmode;
 
495
                else
 
496
                {
 
497
                    clientErrorValue = newarcmode;
 
498
                    error = BadValue;
 
499
                }
 
500
                break;
 
501
            }
 
502
            default:
 
503
                clientErrorValue = maskQ;
 
504
                error = BadValue;
 
505
                break;
 
506
        }
 
507
    } /* end while mask && !error */
 
508
 
 
509
    if (pGC->fillStyle == FillTiled && pGC->tileIsPixel)
 
510
    {
 
511
        if (!CreateDefaultTile (pGC))
 
512
        {
 
513
            pGC->fillStyle = FillSolid;
 
514
            error = BadAlloc;
 
515
        }
 
516
    }
 
517
    (*pGC->funcs->ChangeGC)(pGC, maskQ);
 
518
    return error;
 
519
}
 
520
 
 
521
#undef NEXTVAL
 
522
#undef NEXT_PTR
 
523
 
 
524
/* Publically defined entry to ChangeGC.  Just calls dixChangeGC and tells
 
525
 * it that all of the entries are constants or IDs */
 
526
int
 
527
ChangeGC(register GC *pGC, register BITS32 mask, XID *pval)
 
528
{
 
529
    return (dixChangeGC(NullClient, pGC, mask, pval, NULL));
 
530
}
 
531
 
 
532
/* DoChangeGC(pGC, mask, pval, fPointer)
 
533
   mask is a set of bits indicating which values to change.
 
534
   pval contains an appropriate value for each mask.
 
535
   fPointer is true if the values for tiles, stipples, fonts or clipmasks
 
536
   are pointers instead of IDs.  Note: if you are passing pointers you
 
537
   MUST declare the array of values as type pointer!  Other data types
 
538
   may not be large enough to hold pointers on some machines.  Yes,
 
539
   this means you have to cast to (XID *) when you pass the array to
 
540
   DoChangeGC.  Similarly, if you are not passing pointers (fPointer = 0) you
 
541
   MUST declare the array as type XID (not unsigned long!), or again the wrong
 
542
   size data type may be used.  To avoid this cruftiness, use dixChangeGC
 
543
   above.
 
544
 
 
545
   if there is an error, the value is marked as changed 
 
546
   anyway, which is probably wrong, but infrequent.
 
547
 
 
548
NOTE:
 
549
        all values sent over the protocol for ChangeGC requests are
 
550
32 bits long
 
551
*/
 
552
int
 
553
DoChangeGC(register GC *pGC, register BITS32 mask, XID *pval, int fPointer)
 
554
{
 
555
    if (fPointer)
 
556
    /* XXX might be a problem on 64 bit big-endian servers */
 
557
        return dixChangeGC(NullClient, pGC, mask, NULL, (ChangeGCValPtr)pval);
 
558
    else
 
559
        return dixChangeGC(NullClient, pGC, mask, pval, NULL);
 
560
}
 
561
 
 
562
 
 
563
/* CreateGC(pDrawable, mask, pval, pStatus)
 
564
   creates a default GC for the given drawable, using mask to fill
 
565
   in any non-default values.
 
566
   Returns a pointer to the new GC on success, NULL otherwise.
 
567
   returns status of non-default fields in pStatus
 
568
BUG:
 
569
   should check for failure to create default tile
 
570
 
 
571
*/
 
572
 
 
573
static GCPtr
 
574
AllocateGC(ScreenPtr pScreen)
 
575
{
 
576
    GCPtr pGC;
 
577
    register char *ptr;
 
578
    register DevUnion *ppriv;
 
579
    register unsigned *sizes;
 
580
    register unsigned size;
 
581
    register int i;
 
582
 
 
583
    pGC = (GCPtr)xalloc(pScreen->totalGCSize);
 
584
    if (pGC)
 
585
    {
 
586
        ppriv = (DevUnion *)(pGC + 1);
 
587
        pGC->devPrivates = ppriv;
 
588
        sizes = pScreen->GCPrivateSizes;
 
589
        ptr = (char *)(ppriv + pScreen->GCPrivateLen);
 
590
        for (i = pScreen->GCPrivateLen; --i >= 0; ppriv++, sizes++)
 
591
        {
 
592
            if ( (size = *sizes) )
 
593
            {
 
594
                ppriv->ptr = (pointer)ptr;
 
595
                ptr += size;
 
596
            }
 
597
            else
 
598
                ppriv->ptr = (pointer)NULL;
 
599
        }
 
600
    }
 
601
    return pGC;
 
602
}
 
603
 
 
604
GCPtr
 
605
CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus)
 
606
{
 
607
    register GCPtr pGC;
 
608
 
 
609
    pGC = AllocateGC(pDrawable->pScreen);
 
610
    if (!pGC)
 
611
    {
 
612
        *pStatus = BadAlloc;
 
613
        return (GCPtr)NULL;
 
614
    }
 
615
 
 
616
    pGC->pScreen = pDrawable->pScreen;
 
617
    pGC->depth = pDrawable->depth;
 
618
    pGC->alu = GXcopy; /* dst <- src */
 
619
    pGC->planemask = ~0;
 
620
    pGC->serialNumber = GC_CHANGE_SERIAL_BIT;
 
621
    pGC->funcs = 0;
 
622
 
 
623
    pGC->fgPixel = 0;
 
624
    pGC->bgPixel = 1;
 
625
    pGC->lineWidth = 0;
 
626
    pGC->lineStyle = LineSolid;
 
627
    pGC->capStyle = CapButt;
 
628
    pGC->joinStyle = JoinMiter;
 
629
    pGC->fillStyle = FillSolid;
 
630
    pGC->fillRule = EvenOddRule;
 
631
    pGC->arcMode = ArcPieSlice;
 
632
    if (mask & GCForeground)
 
633
    {
 
634
        /*
 
635
         * magic special case -- ChangeGC checks for this condition
 
636
         * and snags the Foreground value to create a pseudo default-tile
 
637
         */
 
638
        pGC->tileIsPixel = FALSE;
 
639
        pGC->tile.pixmap = NullPixmap;
 
640
    }
 
641
    else
 
642
    {
 
643
        pGC->tileIsPixel = TRUE;
 
644
        pGC->tile.pixel = 0;
 
645
    }
 
646
 
 
647
    pGC->patOrg.x = 0;
 
648
    pGC->patOrg.y = 0;
 
649
    pGC->subWindowMode = ClipByChildren;
 
650
    pGC->graphicsExposures = TRUE;
 
651
    pGC->clipOrg.x = 0;
 
652
    pGC->clipOrg.y = 0;
 
653
    pGC->clientClipType = CT_NONE;
 
654
    pGC->clientClip = (pointer)NULL;
 
655
    pGC->numInDashList = 2;
 
656
    pGC->dash = DefaultDash;
 
657
    pGC->dashOffset = 0;
 
658
    pGC->lastWinOrg.x = 0;
 
659
    pGC->lastWinOrg.y = 0;
 
660
 
 
661
    /* use the default font and stipple */
 
662
    pGC->font = defaultFont;
 
663
    defaultFont->refcnt++;
 
664
    pGC->stipple = pGC->pScreen->PixmapPerDepth[0];
 
665
    pGC->stipple->refcnt++;
 
666
 
 
667
    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
 
668
    if (!(*pGC->pScreen->CreateGC)(pGC))
 
669
        *pStatus = BadAlloc;
 
670
    else if (mask)
 
671
        *pStatus = ChangeGC(pGC, mask, pval);
 
672
    else
 
673
        *pStatus = Success;
 
674
    if (*pStatus != Success)
 
675
    {
 
676
        if (!pGC->tileIsPixel && !pGC->tile.pixmap)
 
677
            pGC->tileIsPixel = TRUE; /* undo special case */
 
678
        FreeGC(pGC, (XID)0);
 
679
        pGC = (GCPtr)NULL;
 
680
    }
 
681
 
 
682
    return (pGC);
 
683
}
 
684
 
 
685
static Bool
 
686
CreateDefaultTile (GCPtr pGC)
 
687
{
 
688
    XID         tmpval[3];
 
689
    PixmapPtr   pTile;
 
690
    GCPtr       pgcScratch;
 
691
    xRectangle  rect;
 
692
    CARD16      w, h;
 
693
 
 
694
    w = 1;
 
695
    h = 1;
 
696
    (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen);
 
697
    pTile = (PixmapPtr)
 
698
            (*pGC->pScreen->CreatePixmap)(pGC->pScreen,
 
699
                                          w, h, pGC->depth);
 
700
    pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen);
 
701
    if (!pTile || !pgcScratch)
 
702
    {
 
703
        if (pTile)
 
704
            (*pTile->drawable.pScreen->DestroyPixmap)(pTile);
 
705
        if (pgcScratch)
 
706
            FreeScratchGC(pgcScratch);
 
707
        return FALSE;
 
708
    }
 
709
    tmpval[0] = GXcopy;
 
710
    tmpval[1] = pGC->tile.pixel;
 
711
    tmpval[2] = FillSolid;
 
712
    (void)ChangeGC(pgcScratch, GCFunction | GCForeground | GCFillStyle, 
 
713
                   tmpval);
 
714
    ValidateGC((DrawablePtr)pTile, pgcScratch);
 
715
    rect.x = 0;
 
716
    rect.y = 0;
 
717
    rect.width = w;
 
718
    rect.height = h;
 
719
    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect);
 
720
    /* Always remember to free the scratch graphics context after use. */
 
721
    FreeScratchGC(pgcScratch);
 
722
 
 
723
    pGC->tileIsPixel = FALSE;
 
724
    pGC->tile.pixmap = pTile;
 
725
    return TRUE;
 
726
}
 
727
 
 
728
int
 
729
CopyGC(register GC *pgcSrc, register GC *pgcDst, register BITS32 mask)
 
730
{
 
731
    register BITS32     index2;
 
732
    BITS32              maskQ;
 
733
    int                 error = 0;
 
734
 
 
735
    if (pgcSrc == pgcDst)
 
736
        return Success;
 
737
    pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
 
738
    pgcDst->stateChanges |= mask;
 
739
    maskQ = mask;
 
740
    while (mask)
 
741
    {
 
742
        index2 = (BITS32) lowbit (mask);
 
743
        mask &= ~index2;
 
744
        switch (index2)
 
745
        {
 
746
            case GCFunction:
 
747
                pgcDst->alu = pgcSrc->alu;
 
748
                break;
 
749
            case GCPlaneMask:
 
750
                pgcDst->planemask = pgcSrc->planemask;
 
751
                break;
 
752
            case GCForeground:
 
753
                pgcDst->fgPixel = pgcSrc->fgPixel;
 
754
                break;
 
755
            case GCBackground:
 
756
                pgcDst->bgPixel = pgcSrc->bgPixel;
 
757
                break;
 
758
            case GCLineWidth:
 
759
                pgcDst->lineWidth = pgcSrc->lineWidth;
 
760
                break;
 
761
            case GCLineStyle:
 
762
                pgcDst->lineStyle = pgcSrc->lineStyle;
 
763
                break;
 
764
            case GCCapStyle:
 
765
                pgcDst->capStyle = pgcSrc->capStyle;
 
766
                break;
 
767
            case GCJoinStyle:
 
768
                pgcDst->joinStyle = pgcSrc->joinStyle;
 
769
                break;
 
770
            case GCFillStyle:
 
771
                pgcDst->fillStyle = pgcSrc->fillStyle;
 
772
                break;
 
773
            case GCFillRule:
 
774
                pgcDst->fillRule = pgcSrc->fillRule;
 
775
                break;
 
776
            case GCTile:
 
777
                {
 
778
                    if (EqualPixUnion(pgcDst->tileIsPixel,
 
779
                                      pgcDst->tile,
 
780
                                      pgcSrc->tileIsPixel,
 
781
                                      pgcSrc->tile))
 
782
                    {
 
783
                        break;
 
784
                    }
 
785
                    if (!pgcDst->tileIsPixel)
 
786
                        (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap);
 
787
                    pgcDst->tileIsPixel = pgcSrc->tileIsPixel;
 
788
                    pgcDst->tile = pgcSrc->tile;
 
789
                    if (!pgcDst->tileIsPixel)
 
790
                       pgcDst->tile.pixmap->refcnt++;
 
791
                    break;
 
792
                }
 
793
            case GCStipple:
 
794
                {
 
795
                    if (pgcDst->stipple == pgcSrc->stipple)
 
796
                        break;
 
797
                    if (pgcDst->stipple)
 
798
                        (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple);
 
799
                    pgcDst->stipple = pgcSrc->stipple;
 
800
                    if (pgcDst->stipple)
 
801
                        pgcDst->stipple->refcnt ++;
 
802
                    break;
 
803
                }
 
804
            case GCTileStipXOrigin:
 
805
                pgcDst->patOrg.x = pgcSrc->patOrg.x;
 
806
                break;
 
807
            case GCTileStipYOrigin:
 
808
                pgcDst->patOrg.y = pgcSrc->patOrg.y;
 
809
                break;
 
810
            case GCFont:
 
811
                if (pgcDst->font == pgcSrc->font)
 
812
                    break;
 
813
                if (pgcDst->font)
 
814
                    CloseFont(pgcDst->font, (Font)0);
 
815
                if ((pgcDst->font = pgcSrc->font) != NullFont)
 
816
                    (pgcDst->font)->refcnt++;
 
817
                break;
 
818
            case GCSubwindowMode:
 
819
                pgcDst->subWindowMode = pgcSrc->subWindowMode;
 
820
                break;
 
821
            case GCGraphicsExposures:
 
822
                pgcDst->graphicsExposures = pgcSrc->graphicsExposures;
 
823
                break;
 
824
            case GCClipXOrigin:
 
825
                pgcDst->clipOrg.x = pgcSrc->clipOrg.x;
 
826
                break;
 
827
            case GCClipYOrigin:
 
828
                pgcDst->clipOrg.y = pgcSrc->clipOrg.y;
 
829
                break;
 
830
            case GCClipMask:
 
831
                (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
 
832
                break;
 
833
            case GCDashOffset:
 
834
                pgcDst->dashOffset = pgcSrc->dashOffset;
 
835
                break;
 
836
            case GCDashList:
 
837
                if (pgcSrc->dash == DefaultDash)
 
838
                {
 
839
                    if (pgcDst->dash != DefaultDash)
 
840
                    {
 
841
                        xfree(pgcDst->dash);
 
842
                        pgcDst->numInDashList = pgcSrc->numInDashList;
 
843
                        pgcDst->dash = pgcSrc->dash;
 
844
                    }
 
845
                }
 
846
                else
 
847
                {
 
848
                    unsigned char *dash;
 
849
                    unsigned int i;
 
850
 
 
851
                    dash = (unsigned char *)xalloc(pgcSrc->numInDashList *
 
852
                                                   sizeof(unsigned char));
 
853
                    if (dash)
 
854
                    {
 
855
                        if (pgcDst->dash != DefaultDash)
 
856
                            xfree(pgcDst->dash);
 
857
                        pgcDst->numInDashList = pgcSrc->numInDashList;
 
858
                        pgcDst->dash = dash;
 
859
                        for (i=0; i<pgcSrc->numInDashList; i++)
 
860
                            dash[i] = pgcSrc->dash[i];
 
861
                    }
 
862
                    else
 
863
                        error = BadAlloc;
 
864
                }
 
865
                break;
 
866
            case GCArcMode:
 
867
                pgcDst->arcMode = pgcSrc->arcMode;
 
868
                break;
 
869
            default:
 
870
                clientErrorValue = maskQ;
 
871
                error = BadValue;
 
872
                break;
 
873
        }
 
874
    }
 
875
    if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel)
 
876
    {
 
877
        if (!CreateDefaultTile (pgcDst))
 
878
        {
 
879
            pgcDst->fillStyle = FillSolid;
 
880
            error = BadAlloc;
 
881
        }
 
882
    }
 
883
    (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst);
 
884
    return error;
 
885
}
 
886
 
 
887
/**
 
888
 * does the diX part of freeing the characteristics in the GC.
 
889
 *
 
890
 *  \param value  must conform to DeleteType
 
891
 */
 
892
int
 
893
FreeGC(pointer value, XID gid)
 
894
{
 
895
    GCPtr pGC = (GCPtr)value;
 
896
 
 
897
    CloseFont(pGC->font, (Font)0);
 
898
    (* pGC->funcs->DestroyClip)(pGC);
 
899
 
 
900
    if (!pGC->tileIsPixel)
 
901
        (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap);
 
902
    if (pGC->stipple)
 
903
        (* pGC->pScreen->DestroyPixmap)(pGC->stipple);
 
904
 
 
905
    (*pGC->funcs->DestroyGC) (pGC);
 
906
    if (pGC->dash != DefaultDash)
 
907
        xfree(pGC->dash);
 
908
    xfree(pGC);
 
909
    return(Success);
 
910
}
 
911
 
 
912
void
 
913
SetGCMask(GCPtr pGC, Mask selectMask, Mask newDataMask)
 
914
{
 
915
    pGC->stateChanges = (~selectMask & pGC->stateChanges) |
 
916
                        (selectMask & newDataMask);
 
917
    if (selectMask & newDataMask)
 
918
        pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;        
 
919
}
 
920
 
 
921
 
 
922
 
 
923
/* CreateScratchGC(pScreen, depth)
 
924
    like CreateGC, but doesn't do the default tile or stipple,
 
925
since we can't create them without already having a GC.  any code
 
926
using the tile or stipple has to set them explicitly anyway,
 
927
since the state of the scratch gc is unknown.  This is OK
 
928
because ChangeGC() has to be able to deal with NULL tiles and
 
929
stipples anyway (in case the CreateGC() call has provided a 
 
930
value for them -- we can't set the default tile until the
 
931
client-supplied attributes are installed, since the fgPixel
 
932
is what fills the default tile.  (maybe this comment should
 
933
go with CreateGC() or ChangeGC().)
 
934
*/
 
935
 
 
936
GCPtr
 
937
CreateScratchGC(ScreenPtr pScreen, unsigned depth)
 
938
{
 
939
    register GCPtr pGC;
 
940
 
 
941
    pGC = AllocateGC(pScreen);
 
942
    if (!pGC)
 
943
        return (GCPtr)NULL;
 
944
 
 
945
    pGC->pScreen = pScreen;
 
946
    pGC->depth = depth;
 
947
    pGC->alu = GXcopy; /* dst <- src */
 
948
    pGC->planemask = ~0;
 
949
    pGC->serialNumber = 0;
 
950
 
 
951
    pGC->fgPixel = 0;
 
952
    pGC->bgPixel = 1;
 
953
    pGC->lineWidth = 0;
 
954
    pGC->lineStyle = LineSolid;
 
955
    pGC->capStyle = CapButt;
 
956
    pGC->joinStyle = JoinMiter;
 
957
    pGC->fillStyle = FillSolid;
 
958
    pGC->fillRule = EvenOddRule;
 
959
    pGC->arcMode = ArcPieSlice;
 
960
    pGC->font = defaultFont;
 
961
    if ( pGC->font)  /* necessary, because open of default font could fail */
 
962
        pGC->font->refcnt++;
 
963
    pGC->tileIsPixel = TRUE;
 
964
    pGC->tile.pixel = 0;
 
965
    pGC->stipple = NullPixmap;
 
966
    pGC->patOrg.x = 0;
 
967
    pGC->patOrg.y = 0;
 
968
    pGC->subWindowMode = ClipByChildren;
 
969
    pGC->graphicsExposures = TRUE;
 
970
    pGC->clipOrg.x = 0;
 
971
    pGC->clipOrg.y = 0;
 
972
    pGC->clientClipType = CT_NONE;
 
973
    pGC->dashOffset = 0;
 
974
    pGC->numInDashList = 2;
 
975
    pGC->dash = DefaultDash;
 
976
    pGC->lastWinOrg.x = 0;
 
977
    pGC->lastWinOrg.y = 0;
 
978
 
 
979
    pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
 
980
    if (!(*pScreen->CreateGC)(pGC))
 
981
    {
 
982
        FreeGC(pGC, (XID)0);
 
983
        pGC = (GCPtr)NULL;
 
984
    }
 
985
    return pGC;
 
986
}
 
987
 
 
988
void
 
989
FreeGCperDepth(int screenNum)
 
990
{
 
991
    register int i;
 
992
    register ScreenPtr pScreen;
 
993
    GCPtr *ppGC;
 
994
 
 
995
    pScreen = screenInfo.screens[screenNum];
 
996
    ppGC = pScreen->GCperDepth;
 
997
 
 
998
    for (i = 0; i <= pScreen->numDepths; i++)
 
999
        (void)FreeGC(ppGC[i], (XID)0);
 
1000
    pScreen->rgf = ~0L;
 
1001
}
 
1002
 
 
1003
 
 
1004
Bool
 
1005
CreateGCperDepth(int screenNum)
 
1006
{
 
1007
    register int i;
 
1008
    register ScreenPtr pScreen;
 
1009
    DepthPtr pDepth;
 
1010
    GCPtr *ppGC;
 
1011
 
 
1012
    pScreen = screenInfo.screens[screenNum];
 
1013
    pScreen->rgf = 0;
 
1014
    ppGC = pScreen->GCperDepth;
 
1015
    /* do depth 1 separately because it's not included in list */
 
1016
    if (!(ppGC[0] = CreateScratchGC(pScreen, 1)))
 
1017
        return FALSE;
 
1018
    ppGC[0]->graphicsExposures = FALSE;
 
1019
    /* Make sure we don't overflow GCperDepth[] */
 
1020
    if( pScreen->numDepths > MAXFORMATS )
 
1021
            return FALSE;
 
1022
 
 
1023
    pDepth = pScreen->allowedDepths;
 
1024
    for (i=0; i<pScreen->numDepths; i++, pDepth++)
 
1025
    {
 
1026
        if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth)))
 
1027
        {
 
1028
            for (; i >= 0; i--)
 
1029
                (void)FreeGC(ppGC[i], (XID)0);
 
1030
            return FALSE;
 
1031
        }
 
1032
        ppGC[i+1]->graphicsExposures = FALSE;
 
1033
    }
 
1034
    return TRUE;
 
1035
}
 
1036
 
 
1037
Bool
 
1038
CreateDefaultStipple(int screenNum)
 
1039
{
 
1040
    register ScreenPtr pScreen;
 
1041
    XID tmpval[3];
 
1042
    xRectangle rect;
 
1043
    CARD16 w, h;
 
1044
    GCPtr pgcScratch;
 
1045
 
 
1046
    pScreen = screenInfo.screens[screenNum];
 
1047
 
 
1048
    w = 16;
 
1049
    h = 16;
 
1050
    (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen);
 
1051
    if (!(pScreen->PixmapPerDepth[0] =
 
1052
                        (*pScreen->CreatePixmap)(pScreen, w, h, 1)))
 
1053
        return FALSE;
 
1054
    /* fill stipple with 1 */
 
1055
    tmpval[0] = GXcopy; tmpval[1] = 1; tmpval[2] = FillSolid;
 
1056
    pgcScratch = GetScratchGC(1, pScreen);
 
1057
    if (!pgcScratch)
 
1058
    {
 
1059
        (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
 
1060
        return FALSE;
 
1061
    }
 
1062
    (void)ChangeGC(pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval);
 
1063
    ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch);
 
1064
    rect.x = 0;
 
1065
    rect.y = 0;
 
1066
    rect.width = w;
 
1067
    rect.height = h;
 
1068
    (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], 
 
1069
                                     pgcScratch, 1, &rect);
 
1070
    FreeScratchGC(pgcScratch);
 
1071
    return TRUE;
 
1072
}
 
1073
 
 
1074
void
 
1075
FreeDefaultStipple(int screenNum)
 
1076
{
 
1077
    ScreenPtr pScreen = screenInfo.screens[screenNum];
 
1078
    (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]);
 
1079
}
 
1080
 
 
1081
int
 
1082
SetDashes(register GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash)
 
1083
{
 
1084
    register long i;
 
1085
    register unsigned char *p, *indash;
 
1086
    BITS32 maskQ = 0;
 
1087
 
 
1088
    i = ndash;
 
1089
    p = pdash;
 
1090
    while (i--)
 
1091
    {
 
1092
        if (!*p++)
 
1093
        {
 
1094
            /* dash segment must be > 0 */
 
1095
            clientErrorValue = 0;
 
1096
            return BadValue;
 
1097
        }
 
1098
    }
 
1099
 
 
1100
    if (ndash & 1)
 
1101
        p = (unsigned char *)xalloc(2 * ndash * sizeof(unsigned char));
 
1102
    else
 
1103
        p = (unsigned char *)xalloc(ndash * sizeof(unsigned char));
 
1104
    if (!p)
 
1105
        return BadAlloc;
 
1106
 
 
1107
    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
 
1108
    if (offset != pGC->dashOffset)
 
1109
    {
 
1110
        pGC->dashOffset = offset;
 
1111
        pGC->stateChanges |= GCDashOffset;
 
1112
        maskQ |= GCDashOffset;
 
1113
    }
 
1114
 
 
1115
    if (pGC->dash != DefaultDash)
 
1116
        xfree(pGC->dash);
 
1117
    pGC->numInDashList = ndash;
 
1118
    pGC->dash = p;
 
1119
    if (ndash & 1)
 
1120
    {
 
1121
        pGC->numInDashList += ndash;
 
1122
        indash = pdash;
 
1123
        i = ndash;
 
1124
        while (i--)
 
1125
            *p++ = *indash++;
 
1126
    }
 
1127
    while(ndash--)
 
1128
        *p++ = *pdash++;
 
1129
    pGC->stateChanges |= GCDashList;
 
1130
    maskQ |= GCDashList;
 
1131
 
 
1132
    if (pGC->funcs->ChangeGC)
 
1133
        (*pGC->funcs->ChangeGC) (pGC, maskQ);
 
1134
    return Success;
 
1135
}
 
1136
 
 
1137
int
 
1138
VerifyRectOrder(int nrects, xRectangle *prects, int ordering)
 
1139
{
 
1140
    register xRectangle *prectP, *prectN;
 
1141
    register int        i;
 
1142
 
 
1143
    switch(ordering)
 
1144
    {
 
1145
      case Unsorted:
 
1146
          return CT_UNSORTED;
 
1147
      case YSorted:
 
1148
          if(nrects > 1)
 
1149
          {
 
1150
              for(i = 1, prectP = prects, prectN = prects + 1;
 
1151
                  i < nrects;
 
1152
                  i++, prectP++, prectN++)
 
1153
                  if(prectN->y < prectP->y)
 
1154
                      return -1;
 
1155
          }
 
1156
          return CT_YSORTED;
 
1157
      case YXSorted:
 
1158
          if(nrects > 1)
 
1159
          {
 
1160
              for(i = 1, prectP = prects, prectN = prects + 1;
 
1161
                  i < nrects;
 
1162
                  i++, prectP++, prectN++)
 
1163
                  if((prectN->y < prectP->y) ||
 
1164
                      ( (prectN->y == prectP->y) &&
 
1165
                        (prectN->x < prectP->x) ) )
 
1166
                      return -1;
 
1167
          }
 
1168
          return CT_YXSORTED;
 
1169
      case YXBanded:
 
1170
          if(nrects > 1)
 
1171
          {
 
1172
              for(i = 1, prectP = prects, prectN = prects + 1;
 
1173
                  i < nrects;
 
1174
                  i++, prectP++, prectN++)
 
1175
                  if((prectN->y != prectP->y &&
 
1176
                      prectN->y < prectP->y + (int) prectP->height) ||
 
1177
                     ((prectN->y == prectP->y) &&
 
1178
                      (prectN->height != prectP->height ||
 
1179
                       prectN->x < prectP->x + (int) prectP->width)))
 
1180
                      return -1;
 
1181
          }
 
1182
          return CT_YXBANDED;
 
1183
    }
 
1184
    return -1;
 
1185
}
 
1186
 
 
1187
int
 
1188
SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, 
 
1189
             xRectangle *prects, int ordering)
 
1190
{
 
1191
    int                 newct, size;
 
1192
    xRectangle          *prectsNew;
 
1193
 
 
1194
    newct = VerifyRectOrder(nrects, prects, ordering);
 
1195
    if (newct < 0)
 
1196
        return(BadMatch);
 
1197
    size = nrects * sizeof(xRectangle);
 
1198
    prectsNew = (xRectangle *) xalloc(size);
 
1199
    if (!prectsNew && size)
 
1200
        return BadAlloc;
 
1201
 
 
1202
    pGC->serialNumber |= GC_CHANGE_SERIAL_BIT;
 
1203
    pGC->clipOrg.x = xOrigin;
 
1204
    pGC->stateChanges |= GCClipXOrigin;
 
1205
                 
 
1206
    pGC->clipOrg.y = yOrigin;
 
1207
    pGC->stateChanges |= GCClipYOrigin;
 
1208
 
 
1209
    if (size)
 
1210
        memmove((char *)prectsNew, (char *)prects, size);
 
1211
    (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects);
 
1212
    if (pGC->funcs->ChangeGC)
 
1213
        (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask);
 
1214
    return Success;
 
1215
}
 
1216
 
 
1217
 
 
1218
/*
 
1219
   sets reasonable defaults 
 
1220
   if we can get a pre-allocated one, use it and mark it as used.
 
1221
   if we can't, create one out of whole cloth (The Velveteen GC -- if
 
1222
   you use it often enough it will become real.)
 
1223
*/
 
1224
GCPtr
 
1225
GetScratchGC(register unsigned depth, register ScreenPtr pScreen)
 
1226
{
 
1227
    register int i;
 
1228
    register GCPtr pGC;
 
1229
 
 
1230
    for (i=0; i<=pScreen->numDepths; i++)
 
1231
        if ( pScreen->GCperDepth[i]->depth == depth &&
 
1232
             !(pScreen->rgf & (1L << (i+1)))
 
1233
           )
 
1234
        {
 
1235
            pScreen->rgf |= (1L << (i+1));
 
1236
            pGC = (pScreen->GCperDepth[i]);
 
1237
 
 
1238
            pGC->alu = GXcopy;
 
1239
            pGC->planemask = ~0;
 
1240
            pGC->serialNumber = 0;
 
1241
            pGC->fgPixel = 0;
 
1242
            pGC->bgPixel = 1;
 
1243
            pGC->lineWidth = 0;
 
1244
            pGC->lineStyle = LineSolid;
 
1245
            pGC->capStyle = CapButt;
 
1246
            pGC->joinStyle = JoinMiter;
 
1247
            pGC->fillStyle = FillSolid;
 
1248
            pGC->fillRule = EvenOddRule;
 
1249
            pGC->arcMode = ArcChord;
 
1250
            pGC->patOrg.x = 0;
 
1251
            pGC->patOrg.y = 0;
 
1252
            pGC->subWindowMode = ClipByChildren;
 
1253
            pGC->graphicsExposures = FALSE;
 
1254
            pGC->clipOrg.x = 0;
 
1255
            pGC->clipOrg.y = 0;
 
1256
            if (pGC->clientClipType != CT_NONE)
 
1257
                (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0);
 
1258
            pGC->stateChanges = (1 << (GCLastBit+1)) - 1;
 
1259
            return pGC;
 
1260
        }
 
1261
    /* if we make it this far, need to roll our own */
 
1262
    pGC = CreateScratchGC(pScreen, depth);
 
1263
    if (pGC)
 
1264
        pGC->graphicsExposures = FALSE;
 
1265
    return pGC;
 
1266
}
 
1267
 
 
1268
/*
 
1269
   if the gc to free is in the table of pre-existing ones,
 
1270
mark it as available.
 
1271
   if not, free it for real
 
1272
*/
 
1273
void
 
1274
FreeScratchGC(register GCPtr pGC)
 
1275
{
 
1276
    register ScreenPtr pScreen = pGC->pScreen;
 
1277
    register int i;
 
1278
 
 
1279
    for (i=0; i<=pScreen->numDepths; i++)
 
1280
    {
 
1281
        if ( pScreen->GCperDepth[i] == pGC)
 
1282
        {
 
1283
            pScreen->rgf &= ~(1L << (i+1));
 
1284
            return;
 
1285
        }
 
1286
    }
 
1287
    (void)FreeGC(pGC, (GContext)0);
 
1288
}