~ubuntu-branches/ubuntu/lucid/graphviz/lucid-security

« back to all changes in this revision

Viewing changes to gd/gd_arc_f_buggy.c

  • Committer: Bazaar Package Importer
  • Author(s): Stephen M Moraco
  • Date: 2002-02-05 18:52:12 UTC
  • Revision ID: james.westby@ubuntu.com-20020205185212-8i04c70te00rc40y
Tags: upstream-1.7.16
ImportĀ upstreamĀ versionĀ 1.7.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This is potentially great stuff, but fails against the test
 
2
   program at the end. This would probably be much more 
 
3
   efficent than the implementation currently in gd.c if the 
 
4
   errors in the output were corrected. TBB */
 
5
 
 
6
#if 0
 
7
 
 
8
#include "gd.h"
 
9
#include <math.h>
 
10
 
 
11
/* Courtesy of F J Franklin. */
 
12
 
 
13
static gdPoint gdArcClosest (int width, int height, int angle);
 
14
 
 
15
void
 
16
gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int width, int height, int color)
 
17
{
 
18
  gdImageFilledArc (im, cx, cy, width, height, 0, 360, color, gdChord);
 
19
}
 
20
 
 
21
void
 
22
gdImageFilledArc (gdImagePtr im, int cx, int cy, int width, int height, int s, int e, int color, int style)
 
23
{
 
24
  gdPoint pt[7];
 
25
  gdPoint axis_pt[4];
 
26
 
 
27
  int angle;
 
28
 
 
29
  int have_s = 0;
 
30
  int have_e = 0;
 
31
 
 
32
  int flip_x = 0;
 
33
  int flip_y = 0;
 
34
 
 
35
  int conquer = 0;
 
36
 
 
37
  int i;
 
38
 
 
39
  int a;
 
40
  int b;
 
41
 
 
42
  int x;
 
43
  int y;
 
44
 
 
45
  long s_sin = 0;
 
46
  long s_cos = 0;
 
47
  long e_sin = 0;
 
48
  long e_cos = 0;
 
49
 
 
50
  long w;                       /* a * 2 */
 
51
  long h;                       /* b * 2 */
 
52
 
 
53
  long x2;                      /* x * 2 */
 
54
  long y2;                      /* y * 2 */
 
55
  long lx2;                     /* x * 2 (line) */
 
56
  long ly2;                     /* y * 2 (line) */
 
57
 
 
58
  long ws;                      /* (a * 2)^2 */
 
59
  long hs;                      /* (b * 2)^2 */
 
60
 
 
61
  long whs;                     /* (a * 2)^2 * (b * 2)^2 */
 
62
 
 
63
  long g;                       /* decision variable */
 
64
  long lg;                      /* decision variable (line) */
 
65
 
 
66
  width = (width & 1) ? (width + 1) : (width);
 
67
  height = (height & 1) ? (height + 1) : (height);
 
68
 
 
69
  a = width / 2;
 
70
  b = height / 2;
 
71
 
 
72
  axis_pt[0].x = a;
 
73
  axis_pt[0].y = 0;
 
74
  axis_pt[1].x = 0;
 
75
  axis_pt[1].y = b;
 
76
  axis_pt[2].x = -a;
 
77
  axis_pt[2].y = 0;
 
78
  axis_pt[3].x = 0;
 
79
  axis_pt[3].y = -b;
 
80
 
 
81
  if (s == e)
 
82
    return;
 
83
 
 
84
  if ((e - s) >= 360)
 
85
    {
 
86
      s = 0;
 
87
      e = 0;
 
88
    }
 
89
 
 
90
  while (s < 0)
 
91
    s += 360;
 
92
  while (s >= 360)
 
93
    s -= 360;
 
94
  while (e < 0)
 
95
    e += 360;
 
96
  while (e >= 360)
 
97
    e -= 360;
 
98
 
 
99
  if (e <= s)
 
100
    e += 360;
 
101
 
 
102
  /* I'm assuming a chord-rule at the moment. Need to add origin to get a
 
103
   * pie-rule, but will need to set chord-rule before recursion...
 
104
   */
 
105
 
 
106
  for (i = 0; i < 4; i++)
 
107
    {
 
108
      if ((s < (i + 1) * 90) && (e > (i + 1) * 90))
 
109
        {
 
110
          gdImageFilledArc (im, cx, cy, width, height, s, (i + 1) * 90, color, gdChord);
 
111
          pt[0] = gdArcClosest (width, height, s);
 
112
          pt[0].x += cx;
 
113
          pt[0].y += cy;
 
114
          pt[1].x = cx + axis_pt[(i + 1) & 3].x;
 
115
          pt[1].y = cy + axis_pt[(i + 1) & 3].y;
 
116
          if (e <= (i + 2) * 90)
 
117
            {
 
118
              gdImageFilledArc (im, cx, cy, width, height, (i + 1) * 90, e, color, gdChord);
 
119
              pt[2] = gdArcClosest (width, height, e);
 
120
              pt[2].x += cx;
 
121
              pt[2].y += cy;
 
122
              if (style == gdChord)
 
123
                {
 
124
                  gdImageFilledPolygon (im, pt, 3, color);
 
125
                  gdImagePolygon (im, pt, 3, color);
 
126
                }
 
127
              else if (style == gdPie)
 
128
                {
 
129
                  pt[3].x = cx;
 
130
                  pt[3].y = cy;
 
131
                  gdImageFilledPolygon (im, pt, 4, color);
 
132
                  gdImagePolygon (im, pt, 4, color);
 
133
                }
 
134
            }
 
135
          else
 
136
            {
 
137
              gdImageFilledArc (im, cx, cy, width, height, (i + 1) * 90, (i + 2) * 90, color, gdChord);
 
138
              pt[2].x = cx + axis_pt[(i + 2) & 3].x;
 
139
              pt[2].y = cy + axis_pt[(i + 2) & 3].y;
 
140
              if (e <= (i + 3) * 90)
 
141
                {
 
142
                  gdImageFilledArc (im, cx, cy, width, height, (i + 2) * 90, e, color, gdChord);
 
143
                  pt[3] = gdArcClosest (width, height, e);
 
144
                  pt[3].x += cx;
 
145
                  pt[3].y += cy;
 
146
                  if (style == gdChord)
 
147
                    {
 
148
                      gdImageFilledPolygon (im, pt, 4, color);
 
149
                      gdImagePolygon (im, pt, 4, color);
 
150
                    }
 
151
                  else if (style == gdPie)
 
152
                    {
 
153
                      pt[4].x = cx;
 
154
                      pt[4].y = cy;
 
155
                      gdImageFilledPolygon (im, pt, 5, color);
 
156
                      gdImagePolygon (im, pt, 5, color);
 
157
                    }
 
158
                }
 
159
              else
 
160
                {
 
161
                  gdImageFilledArc (im, cx, cy, width, height, (i + 2) * 90, (i + 3) * 90, color, gdChord);
 
162
                  pt[3].x = cx + axis_pt[(i + 3) & 3].x;
 
163
                  pt[3].y = cy + axis_pt[(i + 3) & 3].y;
 
164
                  if (e <= (i + 4) * 90)
 
165
                    {
 
166
                      gdImageFilledArc (im, cx, cy, width, height, (i + 3) * 90, e, color, gdChord);
 
167
                      pt[4] = gdArcClosest (width, height, e);
 
168
                      pt[4].x += cx;
 
169
                      pt[4].y += cy;
 
170
                      if (style == gdChord)
 
171
                        {
 
172
                          gdImageFilledPolygon (im, pt, 5, color);
 
173
                          gdImagePolygon (im, pt, 5, color);
 
174
                        }
 
175
                      else if (style == gdPie)
 
176
                        {
 
177
                          pt[5].x = cx;
 
178
                          pt[5].y = cy;
 
179
                          gdImageFilledPolygon (im, pt, 6, color);
 
180
                          gdImagePolygon (im, pt, 6, color);
 
181
                        }
 
182
                    }
 
183
                  else
 
184
                    {
 
185
                      gdImageFilledArc (im, cx, cy, width, height, (i + 3) * 90, (i + 4) * 90, color, gdChord);
 
186
                      pt[4].x = cx + axis_pt[(i + 4) & 3].x;
 
187
                      pt[4].y = cy + axis_pt[(i + 4) & 3].y;
 
188
 
 
189
                      gdImageFilledArc (im, cx, cy, width, height, (i + 4) * 90, e, color, gdChord);
 
190
                      pt[5] = gdArcClosest (width, height, e);
 
191
                      pt[5].x += cx;
 
192
                      pt[5].y += cy;
 
193
                      if (style == gdChord)
 
194
                        {
 
195
                          gdImageFilledPolygon (im, pt, 6, color);
 
196
                          gdImagePolygon (im, pt, 6, color);
 
197
                        }
 
198
                      else if (style == gdPie)
 
199
                        {
 
200
                          pt[6].x = cx;
 
201
                          pt[6].y = cy;
 
202
                          gdImageFilledPolygon (im, pt, 7, color);
 
203
                          gdImagePolygon (im, pt, 7, color);
 
204
                        }
 
205
                    }
 
206
                }
 
207
            }
 
208
          return;
 
209
        }
 
210
    }
 
211
 
 
212
  /* At this point we have only arcs that lies within a quadrant -
 
213
   * map this to first quadrant...
 
214
   */
 
215
 
 
216
  if ((s >= 90) && (e <= 180))
 
217
    {
 
218
      angle = s;
 
219
      s = 180 - e;
 
220
      e = 180 - angle;
 
221
      flip_x = 1;
 
222
    }
 
223
  if ((s >= 180) && (e <= 270))
 
224
    {
 
225
      s = s - 180;
 
226
      e = e - 180;
 
227
      flip_x = 1;
 
228
      flip_y = 1;
 
229
    }
 
230
  if ((s >= 270) && (e <= 360))
 
231
    {
 
232
      angle = s;
 
233
      s = 360 - e;
 
234
      e = 360 - angle;
 
235
      flip_y = 1;
 
236
    }
 
237
 
 
238
  if (s == 0)
 
239
    {
 
240
      s_sin = 0;
 
241
      s_cos = (long) ((double) 32768);
 
242
    }
 
243
  else
 
244
    {
 
245
      s_sin = (long) ((double) 32768 * sin ((double) s * M_PI / (double) 180));
 
246
      s_cos = (long) ((double) 32768 * cos ((double) s * M_PI / (double) 180));
 
247
    }
 
248
  if (e == 0)
 
249
    {
 
250
      e_sin = (long) ((double) 32768);
 
251
      e_cos = 0;
 
252
    }
 
253
  else
 
254
    {
 
255
      e_sin = (long) ((double) 32768 * sin ((double) e * M_PI / (double) 180));
 
256
      e_cos = (long) ((double) 32768 * cos ((double) e * M_PI / (double) 180));
 
257
    }
 
258
 
 
259
  w = (long) width;
 
260
  h = (long) height;
 
261
 
 
262
  ws = w * w;
 
263
  hs = h * h;
 
264
 
 
265
  whs = 1;
 
266
  while ((ws > 32768) || (hs > 32768))
 
267
    {
 
268
      ws = (ws + 1) / 2;        /* Unfortunate limitations on integers makes */
 
269
      hs = (hs + 1) / 2;        /* drawing large  ellipses problematic...    */
 
270
      whs *= 2;
 
271
    }
 
272
  while ((ws * hs) > (0x04000000L / whs))
 
273
    {
 
274
      ws = (ws + 1) / 2;
 
275
      hs = (hs + 1) / 2;
 
276
      whs *= 2;
 
277
    }
 
278
  whs *= ws * hs;
 
279
 
 
280
  pt[0].x = w / 2;
 
281
  pt[0].y = 0;
 
282
 
 
283
  pt[2].x = 0;
 
284
  pt[2].y = h / 2;
 
285
 
 
286
  have_s = 0;
 
287
  have_e = 0;
 
288
 
 
289
  if (s == 0)
 
290
    have_s = 1;
 
291
  if (e == 90)
 
292
    have_e = 1;
 
293
 
 
294
  x2 = w;
 
295
  y2 = 0;                       /* Starting point is exactly on ellipse */
 
296
 
 
297
  g = x2 - 1;
 
298
  g = g * g * hs + 4 * ws - whs;
 
299
 
 
300
  while ((x2 * hs) > (y2 * ws)) /* Keep |tangent| > 1 */
 
301
    {
 
302
      y2 += 2;
 
303
      g += ws * 4 * (y2 + 1);
 
304
 
 
305
      if (g > 0)                /* Need to drop */
 
306
        {
 
307
          x2 -= 2;
 
308
          g -= hs * 4 * x2;
 
309
        }
 
310
 
 
311
      if ((have_s == 0) && ((s_sin * x2) <= (y2 * s_cos)))
 
312
        {
 
313
          pt[0].x = (int) (x2 / 2);
 
314
          pt[0].y = (int) (y2 / 2);
 
315
          have_s = 1;
 
316
        }
 
317
 
 
318
      if ((have_e == 0) && ((e_sin * x2) <= (y2 * e_cos)))
 
319
        {
 
320
          pt[2].x = (int) (x2 / 2);
 
321
          pt[2].y = (int) (y2 / 2);
 
322
          have_e = 1;
 
323
        }
 
324
    }
 
325
  pt[1].x = (int) (x2 / 2);
 
326
  pt[1].y = (int) (y2 / 2);
 
327
 
 
328
  x2 = 0;
 
329
  y2 = h;                       /* Starting point is exactly on ellipse */
 
330
 
 
331
  g = y2 - 1;
 
332
  g = g * g * ws + 4 * hs - whs;
 
333
 
 
334
  while ((x2 * hs) < (y2 * ws))
 
335
    {
 
336
      x2 += 2;
 
337
      g += hs * 4 * (x2 + 1);
 
338
 
 
339
      if (g > 0)                /* Need to drop */
 
340
        {
 
341
          y2 -= 2;
 
342
          g -= ws * 4 * y2;
 
343
        }
 
344
 
 
345
      if ((have_s == 0) && ((s_sin * x2) >= (y2 * s_cos)))
 
346
        {
 
347
          pt[0].x = (int) (x2 / 2);
 
348
          pt[0].y = (int) (y2 / 2);
 
349
          have_s = 1;
 
350
        }
 
351
 
 
352
      if ((have_e == 0) && ((e_sin * x2) >= (y2 * e_cos)))
 
353
        {
 
354
          pt[2].x = (int) (x2 / 2);
 
355
          pt[2].y = (int) (y2 / 2);
 
356
          have_e = 1;
 
357
        }
 
358
    }
 
359
 
 
360
  if ((have_s == 0) || (have_e == 0))
 
361
    return;                     /* Bizarre case */
 
362
 
 
363
  if (style == gdPie)
 
364
    {
 
365
      pt[3] = pt[0];
 
366
      pt[4] = pt[1];
 
367
      pt[5] = pt[2];
 
368
 
 
369
      pt[0].x = cx + (flip_x ? (-pt[0].x) : pt[0].x);
 
370
      pt[0].y = cy + (flip_y ? (-pt[0].y) : pt[0].y);
 
371
      pt[1].x = cx;
 
372
      pt[1].y = cy;
 
373
      pt[2].x = cx + (flip_x ? (-pt[2].x) : pt[2].x);
 
374
      pt[2].y = cy + (flip_y ? (-pt[2].y) : pt[2].y);
 
375
      gdImageFilledPolygon (im, pt, 3, color);
 
376
      gdImagePolygon (im, pt, 3, color);
 
377
 
 
378
      pt[0] = pt[3];
 
379
      pt[1] = pt[4];
 
380
      pt[2] = pt[5];
 
381
    }
 
382
 
 
383
  if (((s_cos * hs) > (s_sin * ws)) && ((e_cos * hs) < (e_sin * ws)))
 
384
    {                           /* the points are on different parts of the curve...
 
385
                                 * this is too tricky to try to handle, so divide and conquer:
 
386
                                 */
 
387
      pt[3] = pt[0];
 
388
      pt[4] = pt[1];
 
389
      pt[5] = pt[2];
 
390
 
 
391
      pt[0].x = cx + (flip_x ? (-pt[0].x) : pt[0].x);
 
392
      pt[0].y = cy + (flip_y ? (-pt[0].y) : pt[0].y);
 
393
      pt[1].x = cx + (flip_x ? (-pt[1].x) : pt[1].x);
 
394
      pt[1].y = cy + (flip_y ? (-pt[1].y) : pt[1].y);
 
395
      pt[2].x = cx + (flip_x ? (-pt[2].x) : pt[2].x);
 
396
      pt[2].y = cy + (flip_y ? (-pt[2].y) : pt[2].y);
 
397
      gdImageFilledPolygon (im, pt, 3, color);
 
398
      gdImagePolygon (im, pt, 3, color);
 
399
 
 
400
      pt[0] = pt[3];
 
401
      pt[2] = pt[4];
 
402
 
 
403
      conquer = 1;
 
404
    }
 
405
 
 
406
  if (conquer || (((s_cos * hs) > (s_sin * ws)) && ((e_cos * hs) > (e_sin * ws))))
 
407
    {                           /* This is the best bit... */
 
408
      /* steep line + ellipse */
 
409
      /* go up & left from pt[0] to pt[2] */
 
410
 
 
411
      x2 = w;
 
412
      y2 = 0;                   /* Starting point is exactly on ellipse */
 
413
 
 
414
      g = x2 - 1;
 
415
      g = g * g * hs + 4 * ws - whs;
 
416
 
 
417
      while ((x2 * hs) > (y2 * ws))     /* Keep |tangent| > 1 */
 
418
        {
 
419
          if ((s_sin * x2) <= (y2 * s_cos))
 
420
            break;
 
421
 
 
422
          y2 += 2;
 
423
          g += ws * 4 * (y2 + 1);
 
424
 
 
425
          if (g > 0)            /* Need to drop */
 
426
            {
 
427
              x2 -= 2;
 
428
              g -= hs * 4 * x2;
 
429
            }
 
430
        }
 
431
 
 
432
      lx2 = x2;
 
433
      ly2 = y2;
 
434
 
 
435
      lg = lx2 * (pt[0].y - pt[2].y) - ly2 * (pt[0].x - pt[2].x);
 
436
      lg = (lx2 - 1) * (pt[0].y - pt[2].y) - (ly2 + 2) * (pt[0].x - pt[2].x) - lg;
 
437
 
 
438
      while (y2 < (2 * pt[2].y))
 
439
        {
 
440
          y2 += 2;
 
441
          g += ws * 4 * (y2 + 1);
 
442
 
 
443
          if (g > 0)            /* Need to drop */
 
444
            {
 
445
              x2 -= 2;
 
446
              g -= hs * 4 * x2;
 
447
            }
 
448
 
 
449
          ly2 += 2;
 
450
          lg -= 2 * (pt[0].x - pt[2].x);
 
451
 
 
452
          if (lg < 0)           /* Need to drop */
 
453
            {
 
454
              lx2 -= 2;
 
455
              lg -= 2 * (pt[0].y - pt[2].y);
 
456
            }
 
457
 
 
458
          y = (int) (y2 / 2);
 
459
          for (x = (int) (lx2 / 2); x <= (int) (x2 / 2); x++)
 
460
            {
 
461
              gdImageSetPixel (im, ((flip_x) ? (cx - x) : (cx + x)),
 
462
                               ((flip_y) ? (cy - y) : (cy + y)), color);
 
463
            }
 
464
        }
 
465
    }
 
466
  if (conquer)
 
467
    {
 
468
      pt[0] = pt[4];
 
469
      pt[2] = pt[5];
 
470
    }
 
471
  if (conquer || (((s_cos * hs) < (s_sin * ws)) && ((e_cos * hs) < (e_sin * ws))))
 
472
    {                           /* This is the best bit... */
 
473
      /* gradual line + ellipse */
 
474
      /* go down & right from pt[2] to pt[0] */
 
475
 
 
476
      x2 = 0;
 
477
      y2 = h;                   /* Starting point is exactly on ellipse */
 
478
 
 
479
      g = y2 - 1;
 
480
      g = g * g * ws + 4 * hs - whs;
 
481
 
 
482
      while ((x2 * hs) < (y2 * ws))
 
483
        {
 
484
          x2 += 2;
 
485
          g += hs * 4 * (x2 + 1);
 
486
 
 
487
          if (g > 0)            /* Need to drop */
 
488
            {
 
489
              y2 -= 2;
 
490
              g -= ws * 4 * y2;
 
491
            }
 
492
 
 
493
          if ((e_sin * x2) >= (y2 * e_cos))
 
494
            break;
 
495
        }
 
496
 
 
497
      lx2 = x2;
 
498
      ly2 = y2;
 
499
 
 
500
      lg = lx2 * (pt[0].y - pt[2].y) - ly2 * (pt[0].x - pt[2].x);
 
501
      lg = (lx2 + 2) * (pt[0].y - pt[2].y) - (ly2 - 1) * (pt[0].x - pt[2].x) - lg;
 
502
 
 
503
      while (x2 < (2 * pt[0].x))
 
504
        {
 
505
          x2 += 2;
 
506
          g += hs * 4 * (x2 + 1);
 
507
 
 
508
          if (g > 0)            /* Need to drop */
 
509
            {
 
510
              y2 -= 2;
 
511
              g -= ws * 4 * y2;
 
512
            }
 
513
 
 
514
          lx2 += 2;
 
515
          lg += 2 * (pt[0].y - pt[2].y);
 
516
 
 
517
          if (lg < 0)           /* Need to drop */
 
518
            {
 
519
              ly2 -= 2;
 
520
              lg += 2 * (pt[0].x - pt[2].x);
 
521
            }
 
522
 
 
523
          x = (int) (x2 / 2);
 
524
          for (y = (int) (ly2 / 2); y <= (int) (y2 / 2); y++)
 
525
            {
 
526
              gdImageSetPixel (im, ((flip_x) ? (cx - x) : (cx + x)),
 
527
                               ((flip_y) ? (cy - y) : (cy + y)), color);
 
528
            }
 
529
        }
 
530
    }
 
531
}
 
532
 
 
533
static gdPoint
 
534
gdArcClosest (int width, int height, int angle)
 
535
{
 
536
  gdPoint pt;
 
537
 
 
538
  int flip_x = 0;
 
539
  int flip_y = 0;
 
540
 
 
541
  long a_sin = 0;
 
542
  long a_cos = 0;
 
543
 
 
544
  long w;                       /* a * 2 */
 
545
  long h;                       /* b * 2 */
 
546
 
 
547
  long x2;                      /* x * 2 */
 
548
  long y2;                      /* y * 2 */
 
549
 
 
550
  long ws;                      /* (a * 2)^2 */
 
551
  long hs;                      /* (b * 2)^2 */
 
552
 
 
553
  long whs;                     /* (a * 2)^2 * (b * 2)^2 */
 
554
 
 
555
  long g;                       /* decision variable */
 
556
 
 
557
  w = (long) ((width & 1) ? (width + 1) : (width));
 
558
  h = (long) ((height & 1) ? (height + 1) : (height));
 
559
 
 
560
  while (angle < 0)
 
561
    angle += 360;
 
562
  while (angle >= 360)
 
563
    angle -= 360;
 
564
 
 
565
  if (angle == 0)
 
566
    {
 
567
      pt.x = w / 2;
 
568
      pt.y = 0;
 
569
      return (pt);
 
570
    }
 
571
  if (angle == 90)
 
572
    {
 
573
      pt.x = 0;
 
574
      pt.y = h / 2;
 
575
      return (pt);
 
576
    }
 
577
  if (angle == 180)
 
578
    {
 
579
      pt.x = -w / 2;
 
580
      pt.y = 0;
 
581
      return (pt);
 
582
    }
 
583
  if (angle == 270)
 
584
    {
 
585
      pt.x = 0;
 
586
      pt.y = -h / 2;
 
587
      return (pt);
 
588
    }
 
589
 
 
590
  pt.x = 0;
 
591
  pt.y = 0;
 
592
 
 
593
  if ((angle > 90) && (angle < 180))
 
594
    {
 
595
      angle = 180 - angle;
 
596
      flip_x = 1;
 
597
    }
 
598
  if ((angle > 180) && (angle < 270))
 
599
    {
 
600
      angle = angle - 180;
 
601
      flip_x = 1;
 
602
      flip_y = 1;
 
603
    }
 
604
  if ((angle > 270) && (angle < 360))
 
605
    {
 
606
      angle = 360 - angle;
 
607
      flip_y = 1;
 
608
    }
 
609
 
 
610
  a_sin = (long) ((double) 32768 * sin ((double) angle * M_PI / (double) 180));
 
611
  a_cos = (long) ((double) 32768 * cos ((double) angle * M_PI / (double) 180));
 
612
 
 
613
  ws = w * w;
 
614
  hs = h * h;
 
615
 
 
616
  whs = 1;
 
617
  while ((ws > 32768) || (hs > 32768))
 
618
    {
 
619
      ws = (ws + 1) / 2;        /* Unfortunate limitations on integers makes */
 
620
      hs = (hs + 1) / 2;        /* drawing large  ellipses problematic...    */
 
621
      whs *= 2;
 
622
    }
 
623
  while ((ws * hs) > (0x04000000L / whs))
 
624
    {
 
625
      ws = (ws + 1) / 2;
 
626
      hs = (hs + 1) / 2;
 
627
      whs *= 2;
 
628
    }
 
629
  whs *= ws * hs;
 
630
 
 
631
  if ((a_cos * hs) > (a_sin * ws))
 
632
    {
 
633
      x2 = w;
 
634
      y2 = 0;                   /* Starting point is exactly on ellipse */
 
635
 
 
636
      g = x2 - 1;
 
637
      g = g * g * hs + 4 * ws - whs;
 
638
 
 
639
      while ((x2 * hs) > (y2 * ws))     /* Keep |tangent| > 1 */
 
640
        {
 
641
          y2 += 2;
 
642
          g += ws * 4 * (y2 + 1);
 
643
 
 
644
          if (g > 0)            /* Need to drop */
 
645
            {
 
646
              x2 -= 2;
 
647
              g -= hs * 4 * x2;
 
648
            }
 
649
 
 
650
          if ((a_sin * x2) <= (y2 * a_cos))
 
651
            {
 
652
              pt.x = (int) (x2 / 2);
 
653
              pt.y = (int) (y2 / 2);
 
654
              break;
 
655
            }
 
656
        }
 
657
    }
 
658
  else
 
659
    {
 
660
      x2 = 0;
 
661
      y2 = h;                   /* Starting point is exactly on ellipse */
 
662
 
 
663
      g = y2 - 1;
 
664
      g = g * g * ws + 4 * hs - whs;
 
665
 
 
666
      while ((x2 * hs) < (y2 * ws))
 
667
        {
 
668
          x2 += 2;
 
669
          g += hs * 4 * (x2 + 1);
 
670
 
 
671
          if (g > 0)            /* Need to drop */
 
672
            {
 
673
              y2 -= 2;
 
674
              g -= ws * 4 * y2;
 
675
            }
 
676
 
 
677
          if ((a_sin * x2) >= (y2 * a_cos))
 
678
            {
 
679
              pt.x = (int) (x2 / 2);
 
680
              pt.y = (int) (y2 / 2);
 
681
              break;
 
682
            }
 
683
        }
 
684
    }
 
685
 
 
686
  if (flip_x)
 
687
    pt.x = -pt.x;
 
688
  if (flip_y)
 
689
    pt.y = -pt.y;
 
690
 
 
691
  return (pt);
 
692
}
 
693
 
 
694
#include "gd.h"
 
695
#include <string.h>
 
696
#include <math.h>
 
697
 
 
698
#define WIDTH   500
 
699
#define HEIGHT  300
 
700
 
 
701
int 
 
702
main (int argc, char *argv[])
 
703
{
 
704
  gdImagePtr im = gdImageCreate (WIDTH, HEIGHT);
 
705
  int white = gdImageColorResolve (im, 0xFF, 0xFF, 0xFF), black = gdImageColorResolve (im, 0, 0, 0),
 
706
    red = gdImageColorResolve (im, 0xFF, 0xA0, 0xA0);
 
707
  FILE *out;
 
708
 
 
709
  /* filled arc - circle */
 
710
  gdImageFilledArc (im, WIDTH / 5, HEIGHT / 4, 200, 200, 45, 90, red, gdPie);
 
711
  gdImageArc (im, WIDTH / 5, HEIGHT / 4, 200, 200, 45, 90, black);
 
712
 
 
713
  /* filled arc - ellipse */
 
714
  gdImageFilledArc (im, WIDTH / 2, HEIGHT / 4, 200, 150, 45, 90, red, gdPie);
 
715
  gdImageArc (im, WIDTH / 2, HEIGHT / 4, 200, 150, 45, 90, black);
 
716
 
 
717
 
 
718
  /* reference lines */
 
719
  gdImageLine (im, 0, HEIGHT / 4, WIDTH, HEIGHT / 4, black);
 
720
  gdImageLine (im, WIDTH / 5, 0, WIDTH / 5, HEIGHT, black);
 
721
  gdImageLine (im, WIDTH / 2, 0, WIDTH / 2, HEIGHT, black);
 
722
  gdImageLine (im, WIDTH / 2, HEIGHT / 4, WIDTH / 2 + 300, HEIGHT / 4 + 300, black);
 
723
  gdImageLine (im, WIDTH / 5, HEIGHT / 4, WIDTH / 5 + 300, HEIGHT / 4 + 300, black);
 
724
 
 
725
  /* TBB: Write img to test/arctest.png */
 
726
  out = fopen ("test/arctest.png", "wb");
 
727
  if (!out)
 
728
    {
 
729
      fprintf (stderr, "Can't create test/arctest.png\n");
 
730
      exit (1);
 
731
    }
 
732
  gdImagePng (im, out);
 
733
  fclose (out);
 
734
  fprintf (stderr, "Test image written to test/arctest.png\n");
 
735
  /* Destroy it */
 
736
  gdImageDestroy (im);
 
737
 
 
738
  return 0;
 
739
}
 
740
 
 
741
#endif