CrGC.c revision 1ab64890
1/* $Xorg: CrGC.c,v 1.5 2001/02/09 02:03:32 xorgcvs Exp $ */ 2/* 3 4Copyright 1986, 1998 The Open Group 5 6Permission to use, copy, modify, distribute, and sell this software and its 7documentation for any purpose is hereby granted without fee, provided that 8the above copyright notice appear in all copies and that both that 9copyright notice and this permission notice appear in supporting 10documentation. 11 12The above copyright notice and this permission notice shall be included in 13all copies or substantial portions of the Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall not be 23used in advertising or otherwise to promote the sale, use or other dealings 24in this Software without prior written authorization from The Open Group. 25 26*/ 27/* $XFree86: xc/lib/X11/CrGC.c,v 3.6 2001/12/14 19:53:59 dawes Exp $ */ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include "Xlibint.h" 33#include "Cr.h" 34 35static XGCValues const initial_GC = { 36 GXcopy, /* function */ 37 AllPlanes, /* plane_mask */ 38 0L, /* foreground */ 39 1L, /* background */ 40 0, /* line_width */ 41 LineSolid, /* line_style */ 42 CapButt, /* cap_style */ 43 JoinMiter, /* join_style */ 44 FillSolid, /* fill_style */ 45 EvenOddRule,/* fill_rule */ 46 ArcPieSlice,/* arc_mode */ 47 (Pixmap)~0L,/* tile, impossible (unknown) resource */ 48 (Pixmap)~0L,/* stipple, impossible (unknown) resource */ 49 0, /* ts_x_origin */ 50 0, /* ts_y_origin */ 51 (Font)~0L, /* font, impossible (unknown) resource */ 52 ClipByChildren, /* subwindow_mode */ 53 True, /* graphics_exposures */ 54 0, /* clip_x_origin */ 55 0, /* clip_y_origin */ 56 None, /* clip_mask */ 57 0, /* dash_offset */ 58 4 /* dashes (list [4,4]) */ 59}; 60 61static void _XGenerateGCList( 62 register Display *dpy, 63 GC gc, 64 xReq *req); 65 66GC XCreateGC ( 67 register Display *dpy, 68 Drawable d, /* Window or Pixmap for which depth matches */ 69 unsigned long valuemask, /* which ones to set initially */ 70 XGCValues *values) /* the values themselves */ 71{ 72 register GC gc; 73 register xCreateGCReq *req; 74 register _XExtension *ext; 75 76 LockDisplay(dpy); 77 if ((gc = (GC)Xmalloc (sizeof(struct _XGC))) == NULL) { 78 UnlockDisplay(dpy); 79 SyncHandle(); 80 return (NULL); 81 } 82 gc->rects = 0; 83 gc->dashes = 0; 84 gc->ext_data = NULL; 85 gc->values = initial_GC; 86 gc->dirty = 0L; 87 88 valuemask &= (1L << (GCLastBit + 1)) - 1; 89 if (valuemask) _XUpdateGCCache (gc, valuemask, values); 90 91 GetReq(CreateGC, req); 92 req->drawable = d; 93 req->gc = gc->gid = XAllocID(dpy); 94 95 if ((req->mask = gc->dirty)) 96 _XGenerateGCList (dpy, gc, (xReq *) req); 97 /* call out to any extensions interested */ 98 for (ext = dpy->ext_procs; ext; ext = ext->next) 99 if (ext->create_GC) (*ext->create_GC)(dpy, gc, &ext->codes); 100 gc->dirty = 0L; /* allow extensions to see dirty bits */ 101 UnlockDisplay(dpy); 102 SyncHandle(); 103 return (gc); 104 } 105 106/* 107 * GenerateGCList looks at the GC dirty bits, and appends all the required 108 * long words to the request being generated. 109 */ 110 111static void 112_XGenerateGCList ( 113 register Display *dpy, 114 GC gc, 115 xReq *req) 116 { 117 unsigned long values[32]; 118 register unsigned long *value = values; 119 long nvalues; 120 register XGCValues *gv = &gc->values; 121 register unsigned long dirty = gc->dirty; 122 123 /* 124 * Note: The order of these tests are critical; the order must be the 125 * same as the GC mask bits in the word. 126 */ 127 if (dirty & GCFunction) *value++ = gv->function; 128 if (dirty & GCPlaneMask) *value++ = gv->plane_mask; 129 if (dirty & GCForeground) *value++ = gv->foreground; 130 if (dirty & GCBackground) *value++ = gv->background; 131 if (dirty & GCLineWidth) *value++ = gv->line_width; 132 if (dirty & GCLineStyle) *value++ = gv->line_style; 133 if (dirty & GCCapStyle) *value++ = gv->cap_style; 134 if (dirty & GCJoinStyle) *value++ = gv->join_style; 135 if (dirty & GCFillStyle) *value++ = gv->fill_style; 136 if (dirty & GCFillRule) *value++ = gv->fill_rule; 137 if (dirty & GCTile) *value++ = gv->tile; 138 if (dirty & GCStipple) *value++ = gv->stipple; 139 if (dirty & GCTileStipXOrigin) *value++ = gv->ts_x_origin; 140 if (dirty & GCTileStipYOrigin) *value++ = gv->ts_y_origin; 141 if (dirty & GCFont) *value++ = gv->font; 142 if (dirty & GCSubwindowMode) *value++ = gv->subwindow_mode; 143 if (dirty & GCGraphicsExposures) *value++ = gv->graphics_exposures; 144 if (dirty & GCClipXOrigin) *value++ = gv->clip_x_origin; 145 if (dirty & GCClipYOrigin) *value++ = gv->clip_y_origin; 146 if (dirty & GCClipMask) *value++ = gv->clip_mask; 147 if (dirty & GCDashOffset) *value++ = gv->dash_offset; 148 if (dirty & GCDashList) *value++ = gv->dashes; 149 if (dirty & GCArcMode) *value++ = gv->arc_mode; 150 151 req->length += (nvalues = value - values); 152 153 /* 154 * note: Data is a macro that uses its arguments multiple 155 * times, so "nvalues" is changed in a separate assignment 156 * statement 157 */ 158 159 nvalues <<= 2; 160 Data32 (dpy, (long *) values, nvalues); 161 162 } 163 164 165int 166_XUpdateGCCache ( 167 register GC gc, 168 register unsigned long mask, 169 register XGCValues *attr) 170{ 171 register XGCValues *gv = &gc->values; 172 173 if (mask & GCFunction) 174 if (gv->function != attr->function) { 175 gv->function = attr->function; 176 gc->dirty |= GCFunction; 177 } 178 179 if (mask & GCPlaneMask) 180 if (gv->plane_mask != attr->plane_mask) { 181 gv->plane_mask = attr->plane_mask; 182 gc->dirty |= GCPlaneMask; 183 } 184 185 if (mask & GCForeground) 186 if (gv->foreground != attr->foreground) { 187 gv->foreground = attr->foreground; 188 gc->dirty |= GCForeground; 189 } 190 191 if (mask & GCBackground) 192 if (gv->background != attr->background) { 193 gv->background = attr->background; 194 gc->dirty |= GCBackground; 195 } 196 197 if (mask & GCLineWidth) 198 if (gv->line_width != attr->line_width) { 199 gv->line_width = attr->line_width; 200 gc->dirty |= GCLineWidth; 201 } 202 203 if (mask & GCLineStyle) 204 if (gv->line_style != attr->line_style) { 205 gv->line_style = attr->line_style; 206 gc->dirty |= GCLineStyle; 207 } 208 209 if (mask & GCCapStyle) 210 if (gv->cap_style != attr->cap_style) { 211 gv->cap_style = attr->cap_style; 212 gc->dirty |= GCCapStyle; 213 } 214 215 if (mask & GCJoinStyle) 216 if (gv->join_style != attr->join_style) { 217 gv->join_style = attr->join_style; 218 gc->dirty |= GCJoinStyle; 219 } 220 221 if (mask & GCFillStyle) 222 if (gv->fill_style != attr->fill_style) { 223 gv->fill_style = attr->fill_style; 224 gc->dirty |= GCFillStyle; 225 } 226 227 if (mask & GCFillRule) 228 if (gv->fill_rule != attr->fill_rule) { 229 gv->fill_rule = attr->fill_rule; 230 gc->dirty |= GCFillRule; 231 } 232 233 if (mask & GCArcMode) 234 if (gv->arc_mode != attr->arc_mode) { 235 gv->arc_mode = attr->arc_mode; 236 gc->dirty |= GCArcMode; 237 } 238 239 /* always write through tile change, since client may have changed pixmap contents */ 240 if (mask & GCTile) { 241 gv->tile = attr->tile; 242 gc->dirty |= GCTile; 243 } 244 245 /* always write through stipple change, since client may have changed pixmap contents */ 246 if (mask & GCStipple) { 247 gv->stipple = attr->stipple; 248 gc->dirty |= GCStipple; 249 } 250 251 if (mask & GCTileStipXOrigin) 252 if (gv->ts_x_origin != attr->ts_x_origin) { 253 gv->ts_x_origin = attr->ts_x_origin; 254 gc->dirty |= GCTileStipXOrigin; 255 } 256 257 if (mask & GCTileStipYOrigin) 258 if (gv->ts_y_origin != attr->ts_y_origin) { 259 gv->ts_y_origin = attr->ts_y_origin; 260 gc->dirty |= GCTileStipYOrigin; 261 } 262 263 if (mask & GCFont) 264 if (gv->font != attr->font) { 265 gv->font = attr->font; 266 gc->dirty |= GCFont; 267 } 268 269 if (mask & GCSubwindowMode) 270 if (gv->subwindow_mode != attr->subwindow_mode) { 271 gv->subwindow_mode = attr->subwindow_mode; 272 gc->dirty |= GCSubwindowMode; 273 } 274 275 if (mask & GCGraphicsExposures) 276 if (gv->graphics_exposures != attr->graphics_exposures) { 277 gv->graphics_exposures = attr->graphics_exposures; 278 gc->dirty |= GCGraphicsExposures; 279 } 280 281 if (mask & GCClipXOrigin) 282 if (gv->clip_x_origin != attr->clip_x_origin) { 283 gv->clip_x_origin = attr->clip_x_origin; 284 gc->dirty |= GCClipXOrigin; 285 } 286 287 if (mask & GCClipYOrigin) 288 if (gv->clip_y_origin != attr->clip_y_origin) { 289 gv->clip_y_origin = attr->clip_y_origin; 290 gc->dirty |= GCClipYOrigin; 291 } 292 293 /* always write through mask change, since client may have changed pixmap contents */ 294 if (mask & GCClipMask) { 295 gv->clip_mask = attr->clip_mask; 296 gc->dirty |= GCClipMask; 297 gc->rects = 0; 298 } 299 300 if (mask & GCDashOffset) 301 if (gv->dash_offset != attr->dash_offset) { 302 gv->dash_offset = attr->dash_offset; 303 gc->dirty |= GCDashOffset; 304 } 305 306 if (mask & GCDashList) 307 if ((gv->dashes != attr->dashes) || (gc->dashes == True)) { 308 gv->dashes = attr->dashes; 309 gc->dirty |= GCDashList; 310 gc->dashes = 0; 311 } 312 return 0; 313} 314 315/* can only call when display is already locked. */ 316 317void _XFlushGCCache( 318 Display *dpy, 319 GC gc) 320{ 321 register xChangeGCReq *req; 322 register _XExtension *ext; 323 324 if (gc->dirty) { 325 GetReq(ChangeGC, req); 326 req->gc = gc->gid; 327 req->mask = gc->dirty; 328 _XGenerateGCList (dpy, gc, (xReq *) req); 329 /* call out to any extensions interested */ 330 for (ext = dpy->ext_procs; ext; ext = ext->next) 331 if (ext->flush_GC) (*ext->flush_GC)(dpy, gc, &ext->codes); 332 gc->dirty = 0L; /* allow extensions to see dirty bits */ 333 } 334} 335 336void 337XFlushGC( 338 Display *dpy, 339 GC gc) 340{ 341 FlushGC(dpy, gc); 342} 343 344GContext XGContextFromGC(GC gc) 345{ 346 return (gc->gid); 347} 348