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
26#define NUM_POINTS 4    /* 4 points to an arrowhead */
27#define NUM_ANGLES 3    /* But mostly it looks like a triangle */
28static XPoint   *points;
29static GC       pgc;
30
31#include <math.h>
32#if defined(QNX4) || defined(__CYGWIN__) || defined(__UNIXOS2__)
33#define PI 3.14159265358979323846
34#else
35#define PI M_PI
36#endif /* QNX4 */
37
38int
39InitComplexPoly(XParms xp, Parms p, int64_t reps)
40{
41    int     numPoints;
42    int     x, y;
43    int     size, iradius;
44    double  phi, phiinc, radius, delta, phi2;
45    XPoint  *curPoint;
46
47    pgc = xp->fggc;
48
49    size = p->special;
50    phi = 0.0;
51    delta = 2.0 * PI / ((double) NUM_ANGLES);
52    if (xp->version == VERSION1_2) {
53	radius = ((double) size) * sqrt(3.0)/2.0;
54	phiinc = delta/10.0;
55    } else {
56	/* Version 1.2's radius computation was completely bogus, and resulted
57	   in triangles with sides about 50% longer than advertised.  Since
58	   in version 1.3 triangles are scaled to cover size^2 pixels, we do
59	   the same computation here.  The arrowheads are a little larger than
60	   simple triangles, because they lose 1/3 of their area due to the
61	   notch cut out from them, so radius has to be sqrt(3/2) larger than
62	   for simple triangles.
63	 */
64	radius = ((double) size) * sqrt(sqrt(4.0/3.0));
65	phiinc = 1.75*PI / ((double) p->objects);
66    }
67    iradius = (int) radius + 1;
68
69    numPoints = (p->objects) * NUM_POINTS;
70    points = malloc(numPoints * sizeof(XPoint));
71    curPoint = points;
72    x = iradius;
73    y = iradius;
74    for (int i = 0; i != p->objects; i++) {
75	for (int j = 0; j != NUM_ANGLES; j++) {
76	    phi2 = phi + ((double) j) * delta;
77	    curPoint->x = (int) ((double)x + (radius * cos(phi2)) + 0.5);
78	    curPoint->y = (int) ((double)y + (radius * sin(phi2)) + 0.5);
79	    curPoint++;
80	}
81	curPoint->x = x;
82	curPoint->y = y;
83	curPoint++;
84
85	phi += phiinc;
86	y += 2 * iradius;
87	if (y + iradius >= HEIGHT) {
88	    y = iradius;
89	    x += 2 * iradius;
90	    if (x + iradius >= WIDTH) {
91		x = iradius;
92	    }
93	}
94    }
95    return reps;
96}
97
98void
99DoComplexPoly(XParms xp, Parms p, int64_t reps)
100{
101    for (int i = 0; i != reps; i++) {
102        XPoint  *curPoint = points;
103        for (int j = 0; j != p->objects; j++) {
104            XFillPolygon(xp->d, xp->w, pgc, curPoint, NUM_POINTS, Complex,
105			 CoordModeOrigin);
106            curPoint += NUM_POINTS;
107	  }
108        if (pgc == xp->bggc)
109            pgc = xp->fggc;
110        else
111            pgc = xp->bggc;
112	CheckAbort ();
113    }
114}
115
116void
117EndComplexPoly(XParms xp, Parms p)
118{
119    free(points);
120}
121
122int
123InitGeneralPoly(XParms xp, Parms p, int64_t reps)
124{
125    int     numPoints;
126    int	    nsides;
127    int	    x, y;
128    int     size, iradius;
129    double  phi, phiinc, inner_radius, outer_radius, delta, phi2;
130    XPoint  *curPoint;
131
132    pgc = xp->fggc;
133    size = p->special;
134    nsides = (long) p->font;
135    phi = 0.0;
136    delta = 2.0 * PI / ((double) nsides);
137    phiinc = delta / 10.0;
138
139    inner_radius = size / sqrt (nsides * tan (PI / nsides));
140    outer_radius = inner_radius / cos (PI / (2 * nsides));
141    numPoints = p->objects * nsides;
142    points = malloc (numPoints * sizeof (XPoint));
143    curPoint = points;
144    iradius = outer_radius + 1;
145    x = iradius;
146    y = iradius;
147    for (int i = 0; i < p->objects; i++) {
148	phi2 = phi;
149	for (int j = 0; j < nsides; j++) {
150	    curPoint->x = x + (outer_radius * cos(phi2) + 0.5);
151	    curPoint->y = y + (outer_radius * sin(phi2) + 0.5);
152	    curPoint++;
153	    phi2 += delta;
154	}
155	phi += phiinc;
156	y += 2 * iradius;
157	if (y + iradius >= HEIGHT) {
158	    y = iradius;
159	    x += 2 * iradius;
160	    if (x + iradius >= WIDTH) {
161		x = iradius;
162	    }
163	}
164    }
165    return reps;
166}
167
168void
169DoGeneralPoly(XParms xp, Parms p, int64_t reps)
170{
171    int	    nsides;
172    int	    mode;
173
174    nsides = (long) p->font;
175    mode = (long) p->bfont;
176    for (int i = 0; i != reps; i++) {
177        XPoint  *curPoint = points;
178        for (int j = 0; j != p->objects; j++) {
179            XFillPolygon(xp->d, xp->w, pgc, curPoint, nsides, mode,
180			 CoordModeOrigin);
181            curPoint += nsides;
182	  }
183        if (pgc == xp->bggc)
184            pgc = xp->fggc;
185        else
186            pgc = xp->bggc;
187	CheckAbort ();
188    }
189}
190