Home | History | Annotate | Line # | Download | only in src
      1 /*
      2 
      3 Copyright 1986, 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 */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 #include <config.h>
     29 #endif
     30 #include "Xlibint.h"
     31 #include "Cr.h"
     32 
     33 static XGCValues const initial_GC = {
     34     GXcopy, 	/* function */
     35     AllPlanes,	/* plane_mask */
     36     0L,		/* foreground */
     37     1L,		/* background */
     38     0,		/* line_width */
     39     LineSolid,	/* line_style */
     40     CapButt,	/* cap_style */
     41     JoinMiter,	/* join_style */
     42     FillSolid,	/* fill_style */
     43     EvenOddRule,/* fill_rule */
     44     ArcPieSlice,/* arc_mode */
     45     (Pixmap)~0L,/* tile, impossible (unknown) resource */
     46     (Pixmap)~0L,/* stipple, impossible (unknown) resource */
     47     0,		/* ts_x_origin */
     48     0,		/* ts_y_origin */
     49     (Font)~0L,	/* font, impossible (unknown) resource */
     50     ClipByChildren, /* subwindow_mode */
     51     True,	/* graphics_exposures */
     52     0,		/* clip_x_origin */
     53     0,		/* clip_y_origin */
     54     None,	/* clip_mask */
     55     0,		/* dash_offset */
     56     4		/* dashes (list [4,4]) */
     57 };
     58 
     59 static void _XGenerateGCList(
     60     register Display *dpy,
     61     GC gc,
     62     xReq *req);
     63 
     64 GC XCreateGC (
     65      register Display *dpy,
     66      Drawable d,		/* Window or Pixmap for which depth matches */
     67      unsigned long valuemask,	/* which ones to set initially */
     68      XGCValues *values)		/* the values themselves */
     69 {
     70     register GC gc;
     71     register xCreateGCReq *req;
     72     register _XExtension *ext;
     73 
     74     LockDisplay(dpy);
     75     if ((gc = Xmalloc (sizeof(struct _XGC))) == NULL) {
     76 	UnlockDisplay(dpy);
     77 	SyncHandle();
     78 	return (NULL);
     79     }
     80     gc->rects = 0;
     81     gc->dashes = 0;
     82     gc->ext_data = NULL;
     83     gc->values = initial_GC;
     84     gc->dirty = 0L;
     85 
     86     valuemask &= (1L << (GCLastBit + 1)) - 1;
     87     if (valuemask) _XUpdateGCCache (gc, valuemask, values);
     88 
     89     GetReq(CreateGC, req);
     90     req->drawable = d;
     91     req->gc = gc->gid = XAllocID(dpy);
     92 
     93     if ((req->mask = gc->dirty))
     94         _XGenerateGCList (dpy, gc, (xReq *) req);
     95     /* call out to any extensions interested */
     96     for (ext = dpy->ext_procs; ext; ext = ext->next)
     97 	if (ext->create_GC) (*ext->create_GC)(dpy, gc, &ext->codes);
     98     gc->dirty = 0L; /* allow extensions to see dirty bits */
     99     UnlockDisplay(dpy);
    100     SyncHandle();
    101     return (gc);
    102     }
    103 
    104 /*
    105  * GenerateGCList looks at the GC dirty bits, and appends all the required
    106  * long words to the request being generated.
    107  */
    108 
    109 static void
    110 _XGenerateGCList (
    111     register Display *dpy,
    112     GC gc,
    113     xReq *req)
    114     {
    115     unsigned long values[32];
    116     register unsigned long *value = values;
    117     long nvalues;
    118     register XGCValues *gv = &gc->values;
    119     register unsigned long dirty = gc->dirty;
    120 
    121     /*
    122      * Note: The order of these tests are critical; the order must be the
    123      * same as the GC mask bits in the word.
    124      */
    125     if (dirty & GCFunction)          *value++ = gv->function;
    126     if (dirty & GCPlaneMask)         *value++ = gv->plane_mask;
    127     if (dirty & GCForeground)        *value++ = gv->foreground;
    128     if (dirty & GCBackground)        *value++ = gv->background;
    129     if (dirty & GCLineWidth)         *value++ = gv->line_width;
    130     if (dirty & GCLineStyle)         *value++ = gv->line_style;
    131     if (dirty & GCCapStyle)          *value++ = gv->cap_style;
    132     if (dirty & GCJoinStyle)         *value++ = gv->join_style;
    133     if (dirty & GCFillStyle)         *value++ = gv->fill_style;
    134     if (dirty & GCFillRule)          *value++ = gv->fill_rule;
    135     if (dirty & GCTile)              *value++ = gv->tile;
    136     if (dirty & GCStipple)           *value++ = gv->stipple;
    137     if (dirty & GCTileStipXOrigin)   *value++ = gv->ts_x_origin;
    138     if (dirty & GCTileStipYOrigin)   *value++ = gv->ts_y_origin;
    139     if (dirty & GCFont)              *value++ = gv->font;
    140     if (dirty & GCSubwindowMode)     *value++ = gv->subwindow_mode;
    141     if (dirty & GCGraphicsExposures) *value++ = gv->graphics_exposures;
    142     if (dirty & GCClipXOrigin)       *value++ = gv->clip_x_origin;
    143     if (dirty & GCClipYOrigin)       *value++ = gv->clip_y_origin;
    144     if (dirty & GCClipMask)          *value++ = gv->clip_mask;
    145     if (dirty & GCDashOffset)        *value++ = gv->dash_offset;
    146     if (dirty & GCDashList)          *value++ = gv->dashes;
    147     if (dirty & GCArcMode)           *value++ = gv->arc_mode;
    148 
    149     req->length += (nvalues = value - values);
    150 
    151     /*
    152      * note: Data is a macro that uses its arguments multiple
    153      * times, so "nvalues" is changed in a separate assignment
    154      * statement
    155      */
    156 
    157     nvalues <<= 2;
    158     Data32 (dpy, (long *) values, nvalues);
    159 
    160     }
    161 
    162 
    163 int
    164 _XUpdateGCCache (
    165     register GC gc,
    166     register unsigned long mask,
    167     register XGCValues *attr)
    168 {
    169     register XGCValues *gv = &gc->values;
    170 
    171     if (mask & GCFunction)
    172         if (gv->function != attr->function) {
    173 	  gv->function = attr->function;
    174 	  gc->dirty |= GCFunction;
    175 	}
    176 
    177     if (mask & GCPlaneMask)
    178         if (gv->plane_mask != attr->plane_mask) {
    179             gv->plane_mask = attr->plane_mask;
    180 	    gc->dirty |= GCPlaneMask;
    181 	  }
    182 
    183     if (mask & GCForeground)
    184         if (gv->foreground != attr->foreground) {
    185             gv->foreground = attr->foreground;
    186 	    gc->dirty |= GCForeground;
    187 	  }
    188 
    189     if (mask & GCBackground)
    190         if (gv->background != attr->background) {
    191             gv->background = attr->background;
    192 	    gc->dirty |= GCBackground;
    193 	  }
    194 
    195     if (mask & GCLineWidth)
    196         if (gv->line_width != attr->line_width) {
    197             gv->line_width = attr->line_width;
    198 	    gc->dirty |= GCLineWidth;
    199 	  }
    200 
    201     if (mask & GCLineStyle)
    202         if (gv->line_style != attr->line_style) {
    203             gv->line_style = attr->line_style;
    204 	    gc->dirty |= GCLineStyle;
    205 	  }
    206 
    207     if (mask & GCCapStyle)
    208         if (gv->cap_style != attr->cap_style) {
    209             gv->cap_style = attr->cap_style;
    210 	    gc->dirty |= GCCapStyle;
    211 	  }
    212 
    213     if (mask & GCJoinStyle)
    214         if (gv->join_style != attr->join_style) {
    215             gv->join_style = attr->join_style;
    216 	    gc->dirty |= GCJoinStyle;
    217 	  }
    218 
    219     if (mask & GCFillStyle)
    220         if (gv->fill_style != attr->fill_style) {
    221             gv->fill_style = attr->fill_style;
    222 	    gc->dirty |= GCFillStyle;
    223 	  }
    224 
    225     if (mask & GCFillRule)
    226         if (gv->fill_rule != attr->fill_rule) {
    227     	    gv->fill_rule = attr->fill_rule;
    228 	    gc->dirty |= GCFillRule;
    229 	  }
    230 
    231     if (mask & GCArcMode)
    232         if (gv->arc_mode != attr->arc_mode) {
    233 	    gv->arc_mode = attr->arc_mode;
    234 	    gc->dirty |= GCArcMode;
    235 	  }
    236 
    237     /* always write through tile change, since client may have changed pixmap contents */
    238     if (mask & GCTile) {
    239 	    gv->tile = attr->tile;
    240 	    gc->dirty |= GCTile;
    241 	  }
    242 
    243     /* always write through stipple change, since client may have changed pixmap contents */
    244     if (mask & GCStipple) {
    245 	    gv->stipple = attr->stipple;
    246 	    gc->dirty |= GCStipple;
    247 	  }
    248 
    249     if (mask & GCTileStipXOrigin)
    250         if (gv->ts_x_origin != attr->ts_x_origin) {
    251     	    gv->ts_x_origin = attr->ts_x_origin;
    252 	    gc->dirty |= GCTileStipXOrigin;
    253 	  }
    254 
    255     if (mask & GCTileStipYOrigin)
    256         if (gv->ts_y_origin != attr->ts_y_origin) {
    257 	    gv->ts_y_origin = attr->ts_y_origin;
    258 	    gc->dirty |= GCTileStipYOrigin;
    259 	  }
    260 
    261     if (mask & GCFont)
    262         if (gv->font != attr->font) {
    263 	    gv->font = attr->font;
    264 	    gc->dirty |= GCFont;
    265 	  }
    266 
    267     if (mask & GCSubwindowMode)
    268         if (gv->subwindow_mode != attr->subwindow_mode) {
    269 	    gv->subwindow_mode = attr->subwindow_mode;
    270 	    gc->dirty |= GCSubwindowMode;
    271 	  }
    272 
    273     if (mask & GCGraphicsExposures)
    274         if (gv->graphics_exposures != attr->graphics_exposures) {
    275 	    gv->graphics_exposures = attr->graphics_exposures;
    276 	    gc->dirty |= GCGraphicsExposures;
    277 	  }
    278 
    279     if (mask & GCClipXOrigin)
    280         if (gv->clip_x_origin != attr->clip_x_origin) {
    281 	    gv->clip_x_origin = attr->clip_x_origin;
    282 	    gc->dirty |= GCClipXOrigin;
    283 	  }
    284 
    285     if (mask & GCClipYOrigin)
    286         if (gv->clip_y_origin != attr->clip_y_origin) {
    287 	    gv->clip_y_origin = attr->clip_y_origin;
    288 	    gc->dirty |= GCClipYOrigin;
    289 	  }
    290 
    291     /* always write through mask change, since client may have changed pixmap contents */
    292     if (mask & GCClipMask) {
    293 	    gv->clip_mask = attr->clip_mask;
    294 	    gc->dirty |= GCClipMask;
    295 	    gc->rects = 0;
    296 	  }
    297 
    298     if (mask & GCDashOffset)
    299         if (gv->dash_offset != attr->dash_offset) {
    300 	    gv->dash_offset = attr->dash_offset;
    301 	    gc->dirty |= GCDashOffset;
    302 	  }
    303 
    304     if (mask & GCDashList)
    305         if ((gv->dashes != attr->dashes) || (gc->dashes == True)) {
    306             gv->dashes = attr->dashes;
    307 	    gc->dirty |= GCDashList;
    308 	    gc->dashes = 0;
    309 	    }
    310     return 0;
    311 }
    312 
    313 /* can only call when display is already locked. */
    314 
    315 void _XFlushGCCache(
    316      Display *dpy,
    317      GC gc)
    318 {
    319     register xChangeGCReq *req;
    320     register _XExtension *ext;
    321 
    322     if (gc->dirty) {
    323         GetReq(ChangeGC, req);
    324         req->gc = gc->gid;
    325 	req->mask = gc->dirty;
    326         _XGenerateGCList (dpy, gc, (xReq *) req);
    327 	/* call out to any extensions interested */
    328 	for (ext = dpy->ext_procs; ext; ext = ext->next)
    329 	    if (ext->flush_GC) (*ext->flush_GC)(dpy, gc, &ext->codes);
    330 	gc->dirty = 0L; /* allow extensions to see dirty bits */
    331     }
    332 }
    333 
    334 void
    335 XFlushGC(
    336     Display *dpy,
    337     GC gc)
    338 {
    339     FlushGC(dpy, gc);
    340 }
    341 
    342 GContext XGContextFromGC(GC gc)
    343 {
    344     return (gc->gid);
    345 }
    346