do_segs.c revision 736a7e2c
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 = (XSegment *)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, int reps)
170{
171    GenerateSegments(xp, p, False);
172    return reps;
173}
174
175int
176InitDashedSegments(XParms xp, Parms p, int 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, int 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
211int
212InitHorizSegments(XParms xp, Parms p, int reps)
213{
214    int     size;
215    int     half;
216    int     i;
217    int     rows;       /* Number of rows filled in current column      */
218    int     x, y;	/* base of square to draw in			*/
219    int     y1;		/* y position inside square			*/
220    int     inc;
221    XGCValues   gcv;
222
223    pgc = xp->fggc;
224
225    size = p->special;
226    half = (size + 19) / 20;
227
228    segments = (XSegment *)malloc((p->objects) * sizeof(XSegment));
229
230    x = half;
231    y = half;
232    y1 = 0;
233    rows = 0;
234    inc = size / p->objects;
235    if (inc == 0) inc = 1;
236
237    for (i = 0; i != p->objects; i++) {
238	if (i % 2) {
239	    segments[i].x1 = x + size;
240	    segments[i].x2 = x;
241	    segments[i].y1 = y + size - y1;
242	    segments[i].y2 = y + size - y1;
243	    y1 += inc;
244	    if (y1 >= size) y1 -= size;
245	} else {
246	    segments[i].x1 = x;
247	    segments[i].x2 = x + size;
248	    segments[i].y1 = y + y1;
249	    segments[i].y2 = y + y1;
250	}
251	rows++;
252	y += size;
253	if (y >= HEIGHT - size - half || rows == MAXROWS) {
254	    rows = 0;
255	    y = half;
256	    x += size;
257	    if (x >= WIDTH - size - half)
258		x = half;
259	}
260    }
261    gcv.cap_style = CapNotLast;
262    XChangeGC(xp->d, xp->fggc, GCCapStyle, &gcv);
263    XChangeGC(xp->d, xp->bggc, GCCapStyle, &gcv);
264    return reps;
265}
266
267int
268InitWideHorizSegments(XParms xp, Parms p, int reps)
269{
270    int size;
271
272    (void)InitHorizSegments(xp, p, reps);
273
274    size = p->special;
275    XSetLineAttributes(xp->d, xp->bggc, (int) ((size + 9) / 10),
276	LineSolid, CapRound, JoinRound);
277    XSetLineAttributes(xp->d, xp->fggc, (int) ((size + 9) / 10),
278	LineSolid, CapRound, JoinRound);
279
280    return reps;
281}
282
283
284int
285InitVertSegments(XParms xp, Parms p, int reps)
286{
287    int     size;
288    int     half;
289    int     i;
290    int     rows;       /* Number of rows filled in current column      */
291    int     x, y;	/* base of square to draw in			*/
292    int     x1;		/* x position inside square			*/
293    int     inc;
294    XGCValues   gcv;
295
296    pgc = xp->fggc;
297
298    size = p->special;
299    half = (size + 19) / 20;
300
301    segments = (XSegment *)malloc((p->objects) * sizeof(XSegment));
302
303    x = half;
304    y = half;
305    x1 = 0;
306    rows = 0;
307    inc = size / p->objects;
308    if (inc == 0) inc = 1;
309
310    for (i = 0; i != p->objects; i++) {
311	if (i % 2) {
312	    segments[i].x1 = x + size - x1;
313	    segments[i].x2 = x + size - x1;
314	    segments[i].y1 = y + size;
315	    segments[i].y2 = y;
316	    x1 += inc;
317	    if (x1 >= size) x1 -= size;
318	} else {
319	    segments[i].x1 = x + x1;
320	    segments[i].x2 = x + x1;
321	    segments[i].y1 = y;
322	    segments[i].y2 = y + size;
323	}
324	rows++;
325	y += size;
326	if (y >= HEIGHT - size - half || rows == MAXROWS) {
327	    /* Go to next column */
328	    rows = 0;
329	    y = half;
330	    x += size;
331	    if (x >= WIDTH - size - half) {
332		x = half;
333	    }
334	}
335    }
336    gcv.cap_style = CapNotLast;
337    XChangeGC(xp->d, xp->fggc, GCCapStyle, &gcv);
338    XChangeGC(xp->d, xp->bggc, GCCapStyle, &gcv);
339    return reps;
340}
341
342int
343InitWideVertSegments(XParms xp, Parms p, int reps)
344{
345    int size;
346
347    (void)InitVertSegments(xp, p, reps);
348
349    size = p->special;
350    XSetLineAttributes(xp->d, xp->bggc, (int) ((size + 9) / 10),
351	LineSolid, CapRound, JoinRound);
352    XSetLineAttributes(xp->d, xp->fggc, (int) ((size + 9) / 10),
353	LineSolid, CapRound, JoinRound);
354
355    return reps;
356}
357
358
359void
360DoSegments(XParms xp, Parms p, int reps)
361{
362    int i;
363
364    for (i = 0; i != reps; i++) {
365        XDrawSegments(xp->d, xp->w, pgc, segments, p->objects);
366        if (pgc == xp->ddbggc)
367            pgc = xp->ddfggc;
368        else if(pgc == xp->ddfggc)
369            pgc = xp->ddbggc;
370        else if (pgc == xp->bggc)
371            pgc = xp->fggc;
372        else
373            pgc = xp->bggc;
374	CheckAbort ();
375    }
376}
377
378void
379EndSegments(XParms xp, Parms p)
380{
381    free(segments);
382}
383
384