1/***************************************************************************** 2Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, and distribute this software and its 7documentation for any purpose and without fee is hereby granted, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Digital not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. 13 14DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20SOFTWARE. 21 22******************************************************************************/ 23 24#include "x11perf.h" 25 26static XSegment *segments; 27static GC pgc; 28 29static void 30GenerateSegments(XParms xp, Parms p, Bool ddashed) 31{ 32 int size; 33 int half; 34 int i; 35 int rows; /* Number of rows filled in current column */ 36 int x, y; /* base of square to draw in */ 37 int x1=0, y1=0, x2=0, y2=0; /* offsets into square */ 38 int phase; /* how far into 0..8*size we are */ 39 int phaseinc; /* how much to increment phase at each segment */ 40 int size8; /* 8 * size */ 41 XGCValues gcv; 42 43 if(ddashed) 44 pgc = xp->ddfggc; 45 else 46 pgc = xp->fggc; 47 48 49 size = p->special; 50 size8 = 8 * size; 51 half = (size + 19) / 20; 52 53 segments = malloc((p->objects) * sizeof(XSegment)); 54 55 /* All this x, x1, etc. stuff is to create a pattern that 56 (1) scans down the screen vertically, with each new segment going 57 into a square of size^2. 58 59 (2) rotates the endpoints clockwise around the square 60 61 (3) rotates by ``large'' steps if we aren't going to paint enough 62 segments to get full coverage 63 64 (4) uses CapNotLast so we can create segments of length 1 that 65 nonetheless have a distinct direction 66 */ 67 68 x = half; y = half; 69 phase = 0; 70 phaseinc = size8 / p->objects; 71 if (phaseinc == 0) phaseinc = 1; 72 rows = 0; 73 74 for (i = 0; i != p->objects; i++) { 75 switch (phase / size) { 76 case 0: 77 x1 = 0; 78 y1 = 0; 79 x2 = size; 80 y2 = phase; 81 break; 82 83 case 1: 84 x1 = phase % size; 85 y1 = 0; 86 x2 = size; 87 y2 = size; 88 break; 89 90 case 2: 91 x1 = size; 92 y1 = 0; 93 x2 = size - phase % size; 94 y2 = size; 95 break; 96 97 case 3: 98 x1 = size; 99 y1 = phase % size; 100 x2 = 0; 101 y2 = size; 102 break; 103 104 case 4: 105 x1 = size; 106 y1 = size; 107 x2 = 0; 108 y2 = size - phase % size; 109 break; 110 111 case 5: 112 x1 = size - phase % size; 113 y1 = size; 114 x2 = 0; 115 y2 = 0; 116 break; 117 118 case 6: 119 x1 = 0; 120 y1 = size; 121 x2 = phase % size; 122 y2 = 0; 123 break; 124 125 case 7: 126 x1 = 0; 127 y1 = size - phase % size; 128 x2 = size; 129 y2 = 0; 130 break; 131 } /* end switch */ 132 133 segments[i].x1 = x + x1; 134 segments[i].y1 = y + y1; 135 segments[i].x2 = x + x2; 136 segments[i].y2 = y + y2; 137 138 /* Change square to draw segment in */ 139 rows++; 140 y += size; 141 if (y >= HEIGHT - size - half || rows == MAXROWS) { 142 /* Go to next column */ 143 rows = 0; 144 y = half; 145 x += size; 146 if (x >= WIDTH - size - half) { 147 x = half; 148 } 149 } 150 151 /* Increment phase */ 152 phase += phaseinc; 153 if (phase >= size8) phase -= size8; 154 155 } 156 157 gcv.cap_style = CapNotLast; 158 159 if(ddashed) { 160 XChangeGC(xp->d, xp->ddfggc, GCCapStyle, &gcv); 161 XChangeGC(xp->d, xp->ddbggc, GCCapStyle, &gcv); 162 } else { 163 XChangeGC(xp->d, xp->fggc, GCCapStyle, &gcv); 164 XChangeGC(xp->d, xp->bggc, GCCapStyle, &gcv); 165 } 166} 167 168int 169InitSegments(XParms xp, Parms p, int64_t reps) 170{ 171 GenerateSegments(xp, p, False); 172 return reps; 173} 174 175int 176InitDashedSegments(XParms xp, Parms p, int64_t reps) 177{ 178 char dashes[2]; 179 180 GenerateSegments(xp, p, False); 181 182 /* Modify GCs to draw dashed */ 183 XSetLineAttributes 184 (xp->d, xp->bggc, 0, LineOnOffDash, CapNotLast, JoinMiter); 185 XSetLineAttributes 186 (xp->d, xp->fggc, 0, LineOnOffDash, CapNotLast, JoinMiter); 187 dashes[0] = 3; dashes[1] = 2; 188 XSetDashes(xp->d, xp->fggc, 0, dashes, 2); 189 XSetDashes(xp->d, xp->bggc, 0, dashes, 2); 190 return reps; 191} 192 193int 194InitDoubleDashedSegments(XParms xp, Parms p, int64_t reps) 195{ 196 char dashes[2]; 197 198 GenerateSegments(xp, p, True); 199 200 /* Modify GCs to draw dashed */ 201 XSetLineAttributes 202 (xp->d, xp->ddbggc, 0, LineDoubleDash, CapNotLast, JoinMiter); 203 XSetLineAttributes 204 (xp->d, xp->ddfggc, 0, LineDoubleDash, CapNotLast, JoinMiter); 205 dashes[0] = 3; dashes[1] = 2; 206 XSetDashes(xp->d, xp->ddfggc, 0, dashes, 2); 207 XSetDashes(xp->d, xp->ddbggc, 0, dashes, 2); 208 return reps; 209} 210 211static int 212InitHorizSegmentsWidth(XParms xp, Parms p, int64_t reps, int width) 213{ 214 int size; 215 int i; 216 int x, y; /* base of square to draw in */ 217 int y1; /* y position inside square */ 218 int inc; 219 XGCValues gcv; 220 221 pgc = xp->fggc; 222 223 size = p->special; 224 225 segments = malloc((p->objects) * sizeof(XSegment)); 226 227 x = width / 2 + 1; 228 y = width / 2 + 1; 229 y1 = 0; 230 inc = width + 1; 231 232 for (i = 0; i != p->objects; i++) { 233 if (i % 2) { 234 segments[i].x1 = x + size; 235 segments[i].x2 = x; 236 segments[i].y1 = y + (HEIGHT - width - 2) - y1; 237 segments[i].y2 = y + (HEIGHT - width - 2) - y1; 238 y1 += inc; 239 } else { 240 segments[i].x1 = x; 241 segments[i].x2 = x + size; 242 segments[i].y1 = y + y1; 243 segments[i].y2 = y + y1; 244 } 245 /* Go to next row */ 246 if (y1 >= HEIGHT / 2 - (width + 2)) { 247 y1 =0; 248 x += size + inc; 249 if (x >= WIDTH - size - width) 250 x = width/2 + 1; 251 } 252 } 253 gcv.cap_style = CapNotLast; 254 XChangeGC(xp->d, xp->fggc, GCCapStyle, &gcv); 255 XChangeGC(xp->d, xp->bggc, GCCapStyle, &gcv); 256 return reps; 257} 258 259int 260InitHorizSegments(XParms xp, Parms p, int64_t reps) 261{ 262 return InitHorizSegmentsWidth(xp, p, reps, 1); 263} 264 265int 266InitWideHorizSegments(XParms xp, Parms p, int64_t reps) 267{ 268 int size = p->special; 269 270 (void)InitHorizSegmentsWidth(xp, p, reps, (int) ((size + 9) / 10)); 271 272 XSetLineAttributes(xp->d, xp->bggc, (int) ((size + 9) / 10), 273 LineSolid, CapRound, JoinRound); 274 XSetLineAttributes(xp->d, xp->fggc, (int) ((size + 9) / 10), 275 LineSolid, CapRound, JoinRound); 276 277 return reps; 278} 279 280static int 281InitVertSegmentsWidth(XParms xp, Parms p, int64_t reps, int width) 282{ 283 int size; 284 int i; 285 int x, y; /* base of square to draw in */ 286 int x1; /* x position inside square */ 287 int inc; 288 XGCValues gcv; 289 290 pgc = xp->fggc; 291 292 size = p->special; 293 294 segments = malloc((p->objects) * sizeof(XSegment)); 295 296 x = width / 2 + 1; 297 y = width / 2 + 1; 298 x1 = 0; 299 inc = width + 1; 300 301 for (i = 0; i != p->objects; i++) { 302 if (i % 2) { 303 segments[i].x1 = x + (WIDTH - width - 2) - x1; 304 segments[i].x2 = x + (WIDTH - width - 2) - x1; 305 segments[i].y1 = y + size; 306 segments[i].y2 = y; 307 x1 += inc; 308 } else { 309 segments[i].x1 = x + x1; 310 segments[i].x2 = x + x1; 311 segments[i].y1 = y; 312 segments[i].y2 = y + size; 313 } 314 /* Go to next column */ 315 if (x1 >= WIDTH / 2 - (width + 2)) { 316 x1 = 0; 317 y += size + inc; 318 if (y >= HEIGHT - size - width) 319 y = width/2 + 1; 320 } 321 } 322 gcv.cap_style = CapNotLast; 323 XChangeGC(xp->d, xp->fggc, GCCapStyle, &gcv); 324 XChangeGC(xp->d, xp->bggc, GCCapStyle, &gcv); 325 return reps; 326} 327 328int 329InitVertSegments(XParms xp, Parms p, int64_t reps) 330{ 331 return InitVertSegmentsWidth(xp, p, reps, 1); 332} 333 334int 335InitWideVertSegments(XParms xp, Parms p, int64_t reps) 336{ 337 int size = p->special; 338 339 (void)InitVertSegmentsWidth(xp, p, reps, (size + 9) / 10); 340 341 XSetLineAttributes(xp->d, xp->bggc, (int) ((size + 9) / 10), 342 LineSolid, CapRound, JoinRound); 343 XSetLineAttributes(xp->d, xp->fggc, (int) ((size + 9) / 10), 344 LineSolid, CapRound, JoinRound); 345 346 return reps; 347} 348 349void 350DoSegments(XParms xp, Parms p, int64_t reps) 351{ 352 int i; 353 354 for (i = 0; i != reps; i++) { 355 XDrawSegments(xp->d, xp->w, pgc, segments, p->objects); 356 if (pgc == xp->ddbggc) 357 pgc = xp->ddfggc; 358 else if(pgc == xp->ddfggc) 359 pgc = xp->ddbggc; 360 else if (pgc == xp->bggc) 361 pgc = xp->fggc; 362 else 363 pgc = xp->bggc; 364 CheckAbort (); 365 } 366} 367 368void 369EndSegments(XParms xp, Parms p) 370{ 371 free(segments); 372} 373