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