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 XPoint *points; 27static GC pgc; 28 29static void 30GenerateLines(XParms xp, Parms p, Bool ddashed) 31{ 32 int size; 33 int half; /* Half of width if wide line */ 34 int rows; /* Number of rows filled in current column */ 35 int x, y; /* Next point */ 36 int xdir, ydir; /* Which direction x, y are going */ 37 int bigxdir; 38 int x1 = 0, y1 = 0; /* offsets to compute next point from current */ 39 int phase; /* how far into 0..4*(size_1) we are */ 40 float phasef; /* how far we are in real numbers */ 41 float phaseinc; /* how much to increment phasef at each segment */ 42 int size4; /* 4 * size */ 43 44 if(ddashed) 45 pgc = xp->ddfggc; 46 else 47 pgc = xp->fggc; 48 49 size = p->special; 50 size4 = 4 * (size+1); 51 half = (size + 19) / 20; 52 53 points = malloc((p->objects+1) * sizeof(XPoint)); 54 55 /* All this x, x1, x1inc, etc. stuff is to create a pattern that 56 (1) scans down the screen vertically 57 58 (2) rotates the endpoints through all possible orientations 59 60 (3) bounces off bottom and top of window as needed 61 62 (4) moves left or right at each bounce to make things less boring 63 */ 64 65 x = half; 66 y = half; 67 xdir = 1; 68 ydir = 1; 69 bigxdir = 1; 70 phasef = 0.0; 71 phaseinc = ((float)size4) / ((float)p->objects); 72 if (phaseinc < 1.0) phaseinc = 1.0; 73 rows = 0; 74 75 points[0].x = x; 76 points[0].y = y; 77 78 for (int i = 1; i != (p->objects+1); i++) { 79 phase = phasef; 80 switch (phase / (size+1)) { 81 case 0: 82 x1 = size; 83 y1 = phase; 84 break; 85 86 case 1: 87 x1 = size - phase % (size+1); 88 y1 = size; 89 break; 90 91 case 2: 92 x1 = phase % (size+1); 93 y1 = size; 94 break; 95 96 case 3: 97 x1 = size; 98 y1 = size - phase % (size+1); 99 break; 100 } /* end switch */ 101 102 /* Move down or up the screen */ 103 y += (ydir * y1); 104 105 /* If off either top or bottom, backtrack to previous position and go 106 the other way instead. Also move in bigxdir if not already. */ 107 rows++; 108 if (y < half || y >= (HEIGHT-half) || rows > MAXROWS) { 109 rows = 0; 110 if (bigxdir > 0) { 111 if (x + size < WIDTH - half) { 112 xdir = 1; 113 } else { 114 bigxdir = -1; 115 } 116 } else { 117 if (x - size > half) { 118 xdir = -1; 119 } else { 120 bigxdir = 1; 121 } 122 } 123 ydir = -ydir; 124 y += (2 * ydir * y1); 125 /* If still off top or bottom, we can't do the line we want. 126 This will happen infrequently if the window is not twice the 127 length of the line. So instead, let's draw a line that puts 128 the line after this approximately through the center of the 129 window. Since it is very unlikely that both x and y will 130 need such adjustment, line length (in pixels) should not 131 change...we just can't get the slope we want for this line. */ 132 if (y < half) { 133 y = (HEIGHT - y1)/2; 134 ydir = 1; 135 } else if (y > (HEIGHT - half)) { 136 y = (HEIGHT + y1)/2; 137 ydir = -1; 138 } 139 } 140 141 /* Move x left or right by x1 */ 142 x += (xdir * x1); 143 xdir = -xdir; 144 /* Again, if we are off the bottom then we can't really draw the line 145 we want. */ 146 if (x < half) { 147 x = (WIDTH - x1)/2; 148 xdir = 1; 149 } else if (x > (WIDTH - half)) { 150 x = (WIDTH + x1)/2; 151 xdir = -1; 152 } 153 points[i].x = x; 154 points[i].y = y; 155 156 /* Increment phasef */ 157 phasef += phaseinc; 158 if (phasef >= size4) phasef -= size4; 159 160 } 161} 162 163int 164InitLines(XParms xp, Parms p, int64_t reps) 165{ 166 GenerateLines(xp, p, False); 167 return reps; 168} 169 170static int 171GenerateWideLines(XParms xp, Parms p, int64_t reps, Bool ddashed) 172{ 173 int size; 174 175 GenerateLines(xp, p, ddashed); 176 177 size = p->special; 178 if(ddashed) { 179 XSetLineAttributes(xp->d, xp->ddbggc, (int) ((size + 9) / 10), 180 LineSolid, CapRound, JoinRound); 181 XSetLineAttributes(xp->d, xp->ddfggc, (int) ((size + 9) / 10), 182 LineSolid, CapRound, JoinRound); 183 } 184 else { 185 XSetLineAttributes(xp->d, xp->bggc, (int) ((size + 9) / 10), 186 LineSolid, CapRound, JoinRound); 187 XSetLineAttributes(xp->d, xp->fggc, (int) ((size + 9) / 10), 188 LineSolid, CapRound, JoinRound); 189 } 190 191 return reps; 192} 193 194int 195InitWideLines(XParms xp, Parms p, int64_t reps) 196{ 197 return GenerateWideLines(xp, p, reps, False); 198} 199 200int 201InitDashedLines(XParms xp, Parms p, int64_t reps) 202{ 203 char dashes[2]; 204 205 GenerateLines(xp, p, False); 206 207 /* Modify GCs to draw dashed */ 208 XSetLineAttributes(xp->d, xp->bggc, 0, LineOnOffDash, CapButt, JoinMiter); 209 XSetLineAttributes(xp->d, xp->fggc, 0, LineOnOffDash, CapButt, JoinMiter); 210 dashes[0] = 3; dashes[1] = 2; 211 XSetDashes(xp->d, xp->fggc, 0, dashes, 2); 212 XSetDashes(xp->d, xp->bggc, 0, dashes, 2); 213 return reps; 214} 215 216int 217InitWideDashedLines(XParms xp, Parms p, int64_t reps) 218{ 219 int size; 220 XGCValues gcv; 221 char dashes[2]; 222 223 (void)GenerateWideLines(xp, p, reps, False); 224 size = p->special; 225 size = (size + 9) / 10; 226 227 /* Modify GCs to draw dashed */ 228 dashes[0] = 2*size; dashes[1] = 2*size; 229 gcv.line_style = LineOnOffDash; 230 XChangeGC(xp->d, xp->fggc, GCLineStyle, &gcv); 231 XChangeGC(xp->d, xp->bggc, GCLineStyle, &gcv); 232 XSetDashes(xp->d, xp->fggc, 0, dashes, 2); 233 XSetDashes(xp->d, xp->bggc, 0, dashes, 2); 234 return reps; 235} 236 237int 238InitDoubleDashedLines(XParms xp, Parms p, int64_t reps) 239{ 240 char dashes[2]; 241 242 GenerateLines(xp, p, True); 243 244 /* Modify GCs to draw dashed */ 245 XSetLineAttributes(xp->d, xp->ddbggc, 0, LineDoubleDash, CapButt, JoinMiter); 246 XSetLineAttributes(xp->d, xp->ddfggc, 0, LineDoubleDash, CapButt, JoinMiter); 247 dashes[0] = 3; dashes[1] = 2; 248 XSetDashes(xp->d, xp->ddfggc, 0, dashes, 2); 249 XSetDashes(xp->d, xp->ddbggc, 0, dashes, 2); 250 return reps; 251} 252 253int 254InitWideDoubleDashedLines(XParms xp, Parms p, int64_t reps) 255{ 256 int size; 257 XGCValues gcv; 258 char dashes[2]; 259 260 (void)GenerateWideLines(xp, p, reps, True); 261 size = p->special; 262 size = (size + 9) / 10; 263 264 /* Modify GCs to draw dashed */ 265 dashes[0] = 2*size; dashes[1] = 2*size; 266 gcv.line_style = LineDoubleDash; 267 XChangeGC(xp->d, xp->ddfggc, GCLineStyle, &gcv); 268 XChangeGC(xp->d, xp->ddbggc, GCLineStyle, &gcv); 269 XSetDashes(xp->d, xp->ddfggc, 0, dashes, 2); 270 XSetDashes(xp->d, xp->ddbggc, 0, dashes, 2); 271 return reps; 272} 273 274void 275DoLines(XParms xp, Parms p, int64_t reps) 276{ 277 for (int i = 0; i != reps; i++) 278 { 279 XDrawLines(xp->d, xp->w, pgc, points, p->objects+1, CoordModeOrigin); 280 if (pgc == xp->ddbggc) 281 pgc = xp->ddfggc; 282 else if(pgc == xp->ddfggc) 283 pgc = xp->ddbggc; 284 else if (pgc == xp->bggc) 285 pgc = xp->fggc; 286 else 287 pgc = xp->bggc; 288 CheckAbort (); 289 } 290} 291 292void 293EndLines(XParms xp, Parms p) 294{ 295 free(points); 296} 297 298