~ubuntu-branches/ubuntu/breezy/gimp/breezy

« back to all changes in this revision

Viewing changes to plug-ins/gfig/gfig-arc.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2005-10-04 19:04:46 UTC
  • Revision ID: james.westby@ubuntu.com-20051004190446-ukh32kwk56s4sjhu
Tags: upstream-2.2.8
ImportĀ upstreamĀ versionĀ 2.2.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 
3
 *
 
4
 * This is a plug-in for the GIMP.
 
5
 *
 
6
 * Generates images containing vector type drawings.
 
7
 *
 
8
 * Copyright (C) 1997 Andy Thomas  alt@picnic.demon.co.uk
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
23
 *
 
24
 */
 
25
 
 
26
#include "config.h"
 
27
 
 
28
#include <math.h>
 
29
#include <stdio.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
 
 
33
#include <gtk/gtk.h>
 
34
 
 
35
#include <libgimp/gimp.h>
 
36
 
 
37
#include "gfig.h"
 
38
#include "gfig-dobject.h"
 
39
 
 
40
#include "libgimp/stdplugins-intl.h"
 
41
 
 
42
static gdouble     dist                (gdouble   x1,
 
43
                                        gdouble   y1,
 
44
                                        gdouble   x2,
 
45
                                        gdouble   y2);
 
46
 
 
47
static void        mid_point           (gdouble   x1,
 
48
                                        gdouble   y1,
 
49
                                        gdouble   x2,
 
50
                                        gdouble   y2,
 
51
                                        gdouble  *mx,
 
52
                                        gdouble  *my);
 
53
 
 
54
static gdouble     line_grad           (gdouble   x1,
 
55
                                        gdouble   y1,
 
56
                                        gdouble   x2,
 
57
                                        gdouble   y2);
 
58
 
 
59
static gdouble     line_cons           (gdouble   x,
 
60
                                        gdouble   y,
 
61
                                        gdouble   lgrad);
 
62
 
 
63
static void        line_definition     (gdouble   x1,
 
64
                                        gdouble   y1,
 
65
                                        gdouble   x2,
 
66
                                        gdouble   y2,
 
67
                                        gdouble  *lgrad,
 
68
                                        gdouble  *lconst);
 
69
 
 
70
static void        arc_details         (GdkPoint *vert_a,
 
71
                                        GdkPoint *vert_b,
 
72
                                        GdkPoint *vert_c,
 
73
                                        GdkPoint *center_pnt,
 
74
                                        gdouble  *radius);
 
75
 
 
76
static gdouble     arc_angle           (GdkPoint *pnt,
 
77
                                        GdkPoint *center);
 
78
 
 
79
static void        arc_drawing_details (GfigObject *obj,
 
80
                                        gdouble    *minang,
 
81
                                        GdkPoint   *center_pnt,
 
82
                                        gdouble    *arcang,
 
83
                                        gdouble    *radius,
 
84
                                        gboolean    draw_cnts,
 
85
                                        gboolean    do_scale);
 
86
 
 
87
static void        d_draw_arc          (GfigObject *obj);
 
88
 
 
89
static void        d_paint_arc         (GfigObject *obj);
 
90
 
 
91
static GfigObject *d_copy_arc          (GfigObject *obj);
 
92
 
 
93
static void        d_update_arc_line   (GdkPoint   *pnt);
 
94
static void        d_update_arc        (GdkPoint   *pnt);
 
95
static void        d_arc_line_start    (GdkPoint   *pnt,
 
96
                                        gboolean    shift_down);
 
97
static void        d_arc_line_end      (GdkPoint *pnt,
 
98
                                        gboolean  shift_down);
 
99
 
 
100
/* Distance between two points. */
 
101
static gdouble
 
102
dist (gdouble x1,
 
103
      gdouble y1,
 
104
      gdouble x2,
 
105
      gdouble y2)
 
106
{
 
107
 
 
108
  double s1 = x1 - x2;
 
109
  double s2 = y1 - y2;
 
110
 
 
111
  return sqrt (s1 * s1 + s2 * s2);
 
112
}
 
113
 
 
114
/* Mid point of line returned */
 
115
static void
 
116
mid_point (gdouble  x1,
 
117
           gdouble  y1,
 
118
           gdouble  x2,
 
119
           gdouble  y2,
 
120
           gdouble *mx,
 
121
           gdouble *my)
 
122
{
 
123
  *mx = (x1 + x2) / 2.0;
 
124
  *my = (y1 + y2) / 2.0;
 
125
}
 
126
 
 
127
/* Careful about infinite grads */
 
128
static gdouble
 
129
line_grad (gdouble x1,
 
130
           gdouble y1,
 
131
           gdouble x2,
 
132
           gdouble y2)
 
133
{
 
134
  double dx, dy;
 
135
 
 
136
  dx = x1 - x2;
 
137
  dy = y1 - y2;
 
138
 
 
139
  return (dx == 0.0) ? 0.0 : dy / dx;
 
140
}
 
141
 
 
142
/* Constant of line that goes through x, y with grad lgrad */
 
143
static gdouble
 
144
line_cons (gdouble x,
 
145
           gdouble y,
 
146
           gdouble lgrad)
 
147
{
 
148
  return y - lgrad * x;
 
149
}
 
150
 
 
151
/* Get grad & const for perpend. line to given points */
 
152
static void
 
153
line_definition (gdouble  x1,
 
154
                 gdouble  y1,
 
155
                 gdouble  x2,
 
156
                 gdouble  y2,
 
157
                 gdouble *lgrad,
 
158
                 gdouble *lconst)
 
159
{
 
160
  double grad1;
 
161
  double midx, midy;
 
162
 
 
163
  grad1 = line_grad (x1, y1, x2, y2);
 
164
 
 
165
  if (grad1 == 0.0)
 
166
    {
 
167
#ifdef DEBUG
 
168
      printf ("Infinite grad....\n");
 
169
#endif /* DEBUG */
 
170
      return;
 
171
    }
 
172
 
 
173
  mid_point (x1, y1, x2, y2, &midx, &midy);
 
174
 
 
175
  /* Invert grad for perpen gradient */
 
176
 
 
177
  *lgrad = -1.0 / grad1;
 
178
 
 
179
  *lconst = line_cons (midx, midy,*lgrad);
 
180
}
 
181
 
 
182
/* Arch details
 
183
 * Given three points get arc radius and the co-ords
 
184
 * of center point.
 
185
 */
 
186
 
 
187
static void
 
188
arc_details (GdkPoint *vert_a,
 
189
             GdkPoint *vert_b,
 
190
             GdkPoint *vert_c,
 
191
             GdkPoint *center_pnt,
 
192
             gdouble  *radius)
 
193
{
 
194
  /* Only vertices are in whole numbers - everything else is in doubles */
 
195
  double ax, ay;
 
196
  double bx, by;
 
197
  double cx, cy;
 
198
 
 
199
  double len_a, len_b, len_c;
 
200
  double sum_sides2;
 
201
  double area;
 
202
  double circumcircle_R;
 
203
  double line1_grad, line1_const;
 
204
  double line2_grad, line2_const;
 
205
  double inter_x = 0.0, inter_y = 0.0;
 
206
  int    got_x = 0, got_y = 0;
 
207
 
 
208
  ax = (double) (vert_a->x);
 
209
  ay = (double) (vert_a->y);
 
210
  bx = (double) (vert_b->x);
 
211
  by = (double) (vert_b->y);
 
212
  cx = (double) (vert_c->x);
 
213
  cy = (double) (vert_c->y);
 
214
 
 
215
  len_a = dist (ax, ay, bx, by);
 
216
  len_b = dist (bx, by, cx, cy);
 
217
  len_c = dist (cx, cy, ax, ay);
 
218
 
 
219
  sum_sides2 = (fabs (len_a) + fabs (len_b) + fabs (len_c))/2;
 
220
 
 
221
  /* Area */
 
222
  area = sqrt (sum_sides2 * (sum_sides2 - len_a) *
 
223
                            (sum_sides2 - len_b) *
 
224
                            (sum_sides2 - len_c));
 
225
 
 
226
  /* Circumcircle */
 
227
  circumcircle_R = len_a * len_b * len_c / (4 * area);
 
228
  *radius = circumcircle_R;
 
229
 
 
230
  /* Deal with exceptions - I hate exceptions */
 
231
 
 
232
  if (ax == bx || ax == cx || cx == bx)
 
233
    {
 
234
      /* vert line -> mid point gives inter_x */
 
235
      if (ax == bx && bx == cx)
 
236
        {
 
237
          /* Straight line */
 
238
          double miny = ay;
 
239
          double maxy = ay;
 
240
 
 
241
          if (by > maxy)
 
242
            maxy = by;
 
243
 
 
244
          if (by < miny)
 
245
            miny = by;
 
246
 
 
247
          if (cy > maxy)
 
248
            maxy = cy;
 
249
 
 
250
          if (cy < miny)
 
251
            miny = cy;
 
252
 
 
253
          inter_y = (maxy - miny) / 2 + miny;
 
254
        }
 
255
      else if (ax == bx)
 
256
        {
 
257
          inter_y = (ay - by) / 2 + by;
 
258
        }
 
259
      else if (bx == cx)
 
260
        {
 
261
          inter_y = (by - cy) / 2 + cy;
 
262
        }
 
263
      else
 
264
        {
 
265
          inter_y = (cy - ay) / 2 + ay;
 
266
        }
 
267
      got_y = 1;
 
268
    }
 
269
 
 
270
  if (ay == by || by == cy || ay == cy)
 
271
    {
 
272
      /* Horz line -> midpoint gives inter_y */
 
273
      if (ax == bx && bx == cx)
 
274
        {
 
275
          /* Straight line */
 
276
          double minx = ax;
 
277
          double maxx = ax;
 
278
 
 
279
          if (bx > maxx)
 
280
            maxx = bx;
 
281
 
 
282
          if (bx < minx)
 
283
            minx = bx;
 
284
 
 
285
          if (cx > maxx)
 
286
            maxx = cx;
 
287
 
 
288
          if (cx < minx)
 
289
            minx = cx;
 
290
 
 
291
          inter_x = (maxx - minx) / 2 + minx;
 
292
        }
 
293
      else if (ay == by)
 
294
        {
 
295
          inter_x = (ax - bx) / 2 + bx;
 
296
        }
 
297
      else if (by == cy)
 
298
        {
 
299
          inter_x = (bx - cx) / 2 + cx;
 
300
        }
 
301
      else
 
302
        {
 
303
          inter_x = (cx - ax) / 2 + ax;
 
304
        }
 
305
      got_x = 1;
 
306
    }
 
307
 
 
308
  if (!got_x || !got_y)
 
309
    {
 
310
      /* At least two of the lines are not parallel to the axis */
 
311
      /*first line */
 
312
      if (ax != bx && ay != by)
 
313
        line_definition (ax, ay, bx, by, &line1_grad, &line1_const);
 
314
      else
 
315
        line_definition (ax, ay, cx, cy, &line1_grad, &line1_const);
 
316
      /* second line */
 
317
      if (bx != cx && by != cy)
 
318
        line_definition (bx, by, cx, cy, &line2_grad, &line2_const);
 
319
      else
 
320
        line_definition (ax, ay, cx, cy, &line2_grad, &line2_const);
 
321
    }
 
322
 
 
323
  /* Intersection point */
 
324
 
 
325
  if (!got_x)
 
326
    inter_x = (line2_const - line1_const) / (line1_grad - line2_grad);
 
327
  if (!got_y)
 
328
    inter_y = line1_grad * inter_x + line1_const;
 
329
 
 
330
  center_pnt->x = (gint) inter_x;
 
331
  center_pnt->y = (gint) inter_y;
 
332
}
 
333
 
 
334
static gdouble
 
335
arc_angle (GdkPoint *pnt,
 
336
           GdkPoint *center)
 
337
{
 
338
  /* Get angle (in degress) of point given origin of center */
 
339
  gint16  shift_x;
 
340
  gint16  shift_y;
 
341
  gdouble offset_angle;
 
342
 
 
343
  shift_x =  pnt->x - center->x;
 
344
  shift_y = -pnt->y + center->y;
 
345
  offset_angle = atan2 (shift_y, shift_x);
 
346
 
 
347
  if (offset_angle < 0)
 
348
    offset_angle += 2.0 * G_PI;
 
349
 
 
350
  return offset_angle * 360 / (2.0 * G_PI);
 
351
}
 
352
 
 
353
static void
 
354
arc_drawing_details (GfigObject *obj,
 
355
                     gdouble    *minang,
 
356
                     GdkPoint   *center_pnt,
 
357
                     gdouble    *arcang,
 
358
                     gdouble    *radius,
 
359
                     gboolean    draw_cnts,
 
360
                     gboolean    do_scale)
 
361
{
 
362
  DobjPoints *pnt1 = NULL;
 
363
  DobjPoints *pnt2 = NULL;
 
364
  DobjPoints *pnt3 = NULL;
 
365
  DobjPoints  dpnts[3];
 
366
  gdouble     ang1, ang2, ang3;
 
367
  gdouble     maxang;
 
368
 
 
369
  pnt1 = obj->points;
 
370
 
 
371
  if (!pnt1)
 
372
    return; /* Not fully drawn */
 
373
 
 
374
  pnt2 = pnt1->next;
 
375
 
 
376
  if (!pnt2)
 
377
    return; /* Not fully drawn */
 
378
 
 
379
  pnt3 = pnt2->next;
 
380
 
 
381
  if (!pnt3)
 
382
    return; /* Still not fully drawn */
 
383
 
 
384
  if (draw_cnts)
 
385
    {
 
386
      draw_sqr (&pnt1->pnt, obj == gfig_context->selected_obj);
 
387
      draw_sqr (&pnt2->pnt, obj == gfig_context->selected_obj);
 
388
      draw_sqr (&pnt3->pnt, obj == gfig_context->selected_obj);
 
389
    }
 
390
 
 
391
  if (do_scale)
 
392
    {
 
393
      /* Adjust pnts for scaling */
 
394
      /* Warning struct copies here! and casting to double <-> int */
 
395
      /* Too complex fix me - to much hacking */
 
396
      gdouble xy[2];
 
397
      int     j;
 
398
 
 
399
      dpnts[0] = *pnt1;
 
400
      dpnts[1] = *pnt2;
 
401
      dpnts[2] = *pnt3;
 
402
 
 
403
      pnt1 = &dpnts[0];
 
404
      pnt2 = &dpnts[1];
 
405
      pnt3 = &dpnts[2];
 
406
 
 
407
      for (j = 0 ; j < 3; j++)
 
408
        {
 
409
          xy[0] = dpnts[j].pnt.x;
 
410
          xy[1] = dpnts[j].pnt.y;
 
411
          if (selvals.scaletoimage)
 
412
            scale_to_original_xy (&xy[0], 1);
 
413
          else
 
414
            scale_to_xy (&xy[0], 1);
 
415
          dpnts[j].pnt.x = xy[0];
 
416
          dpnts[j].pnt.y = xy[1];
 
417
        }
 
418
    }
 
419
 
 
420
  arc_details (&pnt1->pnt, &pnt2->pnt, &pnt3->pnt, center_pnt, radius);
 
421
 
 
422
  ang1 = arc_angle (&pnt1->pnt, center_pnt);
 
423
  ang2 = arc_angle (&pnt2->pnt, center_pnt);
 
424
  ang3 = arc_angle (&pnt3->pnt, center_pnt);
 
425
 
 
426
  /* Find min/max angle */
 
427
 
 
428
  maxang = ang1;
 
429
 
 
430
  if (ang3 > maxang)
 
431
    maxang = ang3;
 
432
 
 
433
  *minang = ang1;
 
434
 
 
435
  if (ang3 < *minang)
 
436
    *minang = ang3;
 
437
 
 
438
  if (ang2 > *minang && ang2 < maxang)
 
439
    *arcang = maxang - *minang;
 
440
  else
 
441
    *arcang = maxang - *minang - 360;
 
442
}
 
443
 
 
444
static void
 
445
d_draw_arc (GfigObject *obj)
 
446
{
 
447
  GdkPoint center_pnt;
 
448
  gdouble  radius, minang, arcang;
 
449
 
 
450
  g_assert (obj != NULL);
 
451
 
 
452
  if (!obj)
 
453
    return;
 
454
 
 
455
  arc_drawing_details (obj, &minang, &center_pnt, &arcang, &radius,
 
456
                       TRUE, FALSE);
 
457
  gfig_draw_arc (center_pnt.x, center_pnt.y, radius, radius, minang, arcang);
 
458
}
 
459
 
 
460
static void
 
461
d_paint_arc (GfigObject *obj)
 
462
{
 
463
  /* first point center */
 
464
  /* Next point is radius */
 
465
  gdouble *line_pnts;
 
466
  gint     seg_count = 0;
 
467
  gint     i = 0;
 
468
  gdouble  ang_grid;
 
469
  gdouble  ang_loop;
 
470
  gdouble  radius;
 
471
  gint     loop;
 
472
  GdkPoint first_pnt, last_pnt;
 
473
  gboolean first = TRUE;
 
474
  GdkPoint center_pnt;
 
475
  gdouble  minang, arcang;
 
476
 
 
477
  g_assert (obj != NULL);
 
478
 
 
479
  if (!obj)
 
480
    return;
 
481
 
 
482
  /* No cnt pnts & must scale */
 
483
  arc_drawing_details (obj, &minang, &center_pnt, &arcang, &radius,
 
484
                       FALSE, TRUE);
 
485
 
 
486
  seg_count = 360; /* Should make a smoth-ish curve */
 
487
 
 
488
  /* +3 because we MIGHT do pie selection */
 
489
  line_pnts = g_new0 (gdouble, 2 * seg_count + 3);
 
490
 
 
491
  /* Lines */
 
492
  ang_grid = 2.0 * G_PI / 360.0;
 
493
 
 
494
  if (arcang < 0.0)
 
495
    {
 
496
      /* Swap - since we always draw anti-clock wise */
 
497
      minang += arcang;
 
498
      arcang  = -arcang;
 
499
    }
 
500
 
 
501
  minang = minang * (2.0 * G_PI / 360.0); /* min ang is in degrees - need in rads */
 
502
 
 
503
  for (loop = 0 ; loop < abs ((gint)arcang) ; loop++)
 
504
    {
 
505
      gdouble  lx, ly;
 
506
      GdkPoint calc_pnt;
 
507
 
 
508
      ang_loop = (gdouble)loop * ang_grid + minang;
 
509
 
 
510
      lx =  radius * cos (ang_loop);
 
511
      ly = -radius * sin (ang_loop); /* y grows down screen and angs measured from x clockwise */
 
512
 
 
513
      calc_pnt.x = RINT (lx + center_pnt.x);
 
514
      calc_pnt.y = RINT (ly + center_pnt.y);
 
515
 
 
516
      /* Miss out duped pnts */
 
517
      if (!first)
 
518
        {
 
519
          if (calc_pnt.x == last_pnt.x && calc_pnt.y == last_pnt.y)
 
520
            {
 
521
              continue;
 
522
            }
 
523
        }
 
524
 
 
525
      line_pnts[i++] = calc_pnt.x;
 
526
      line_pnts[i++] = calc_pnt.y;
 
527
      last_pnt = calc_pnt;
 
528
 
 
529
      if (first)
 
530
        {
 
531
          first_pnt = calc_pnt;
 
532
          first = FALSE;
 
533
        }
 
534
    }
 
535
 
 
536
  /* One go */
 
537
  if (obj->style.paint_type == PAINT_BRUSH_TYPE)
 
538
    {
 
539
      gfig_paint (selvals.brshtype,
 
540
                  gfig_context->drawable_id,
 
541
                  i, line_pnts);
 
542
    }
 
543
 
 
544
  g_free (line_pnts);
 
545
}
 
546
 
 
547
static GfigObject *
 
548
d_copy_arc (GfigObject *obj)
 
549
{
 
550
  GfigObject *nc;
 
551
 
 
552
  g_assert (obj->type == ARC);
 
553
 
 
554
  nc = d_new_object (ARC, obj->points->pnt.x, obj->points->pnt.y);
 
555
  nc->points->next = d_copy_dobjpoints (obj->points->next);
 
556
 
 
557
  return nc;
 
558
}
 
559
 
 
560
void
 
561
d_arc_object_class_init (void)
 
562
{
 
563
  GfigObjectClass *class = &dobj_class[ARC];
 
564
 
 
565
  class->type      = ARC;
 
566
  class->name      = "ARC";
 
567
  class->drawfunc  = d_draw_arc;
 
568
  class->paintfunc = d_paint_arc;
 
569
  class->copyfunc  = d_copy_arc;
 
570
  class->update    = d_update_arc;
 
571
}
 
572
 
 
573
/* Update end point of line */
 
574
static void
 
575
d_update_arc_line (GdkPoint *pnt)
 
576
{
 
577
  DobjPoints *spnt, *epnt;
 
578
  /* Get last but one segment and undraw it -
 
579
   * Then draw new segment in.
 
580
   * always dealing with the static object.
 
581
   */
 
582
 
 
583
  /* Get start of segments */
 
584
  spnt = obj_creating->points;
 
585
 
 
586
  if (!spnt)
 
587
    return; /* No points */
 
588
 
 
589
  if ((epnt = spnt->next))
 
590
    {
 
591
      /* undraw  current */
 
592
      /* Draw square on point */
 
593
      draw_circle (&epnt->pnt, TRUE);
 
594
 
 
595
      gdk_draw_line (gfig_context->preview->window,
 
596
                     /*gfig_context->preview->style->bg_gc[GTK_STATE_NORMAL],*/
 
597
                     gfig_gc,
 
598
                     spnt->pnt.x,
 
599
                     spnt->pnt.y,
 
600
                     epnt->pnt.x,
 
601
                     epnt->pnt.y);
 
602
      g_free (epnt);
 
603
    }
 
604
 
 
605
  /* draw new */
 
606
  /* Draw circle on point */
 
607
  draw_circle (pnt, TRUE);
 
608
 
 
609
  epnt = new_dobjpoint (pnt->x, pnt->y);
 
610
 
 
611
  gdk_draw_line (gfig_context->preview->window,
 
612
                 /*gfig_context->preview->style->bg_gc[GTK_STATE_NORMAL],*/
 
613
                 gfig_gc,
 
614
                 spnt->pnt.x,
 
615
                 spnt->pnt.y,
 
616
                 epnt->pnt.x,
 
617
                 epnt->pnt.y);
 
618
  spnt->next = epnt;
 
619
}
 
620
 
 
621
static void
 
622
d_update_arc (GdkPoint *pnt)
 
623
{
 
624
  DobjPoints *pnt1 = NULL;
 
625
  DobjPoints *pnt2 = NULL;
 
626
  DobjPoints *pnt3 = NULL;
 
627
 
 
628
  /* First two points as line only become arch when third
 
629
   * point is placed on canvas.
 
630
   */
 
631
 
 
632
  pnt1 = obj_creating->points;
 
633
 
 
634
  if (!pnt1                ||
 
635
      !(pnt2 = pnt1->next) ||
 
636
      !(pnt3 = pnt2->next))
 
637
    {
 
638
      d_update_arc_line (pnt);
 
639
      return; /* Not fully drawn */
 
640
    }
 
641
 
 
642
  /* Update a real curve */
 
643
  /* Nothing to be done ... */
 
644
}
 
645
 
 
646
static void
 
647
d_arc_line_start (GdkPoint *pnt,
 
648
                  gboolean  shift_down)
 
649
{
 
650
  if (!obj_creating || !shift_down)
 
651
    {
 
652
      /* Draw square on point */
 
653
      /* Must delete obj_creating if we have one */
 
654
      obj_creating = d_new_object (LINE, pnt->x, pnt->y);
 
655
    }
 
656
  else
 
657
    {
 
658
      /* Contniuation */
 
659
      d_update_arc_line (pnt);
 
660
    }
 
661
}
 
662
 
 
663
void
 
664
d_arc_start (GdkPoint *pnt,
 
665
             gboolean  shift_down)
 
666
{
 
667
  /* Draw lines to start with -- then convert to an arc */
 
668
  if (!tmp_line)
 
669
    draw_sqr (pnt, TRUE);
 
670
  d_arc_line_start (pnt, TRUE); /* TRUE means multiple pointed line */
 
671
}
 
672
 
 
673
static void
 
674
d_arc_line_end (GdkPoint *pnt,
 
675
                gboolean  shift_down)
 
676
{
 
677
  /* Undraw the last circle */
 
678
  draw_circle (pnt, TRUE);
 
679
 
 
680
  if (shift_down)
 
681
    {
 
682
      if (tmp_line)
 
683
        {
 
684
          GdkPoint tmp_pnt = *pnt;
 
685
 
 
686
          if (need_to_scale)
 
687
            {
 
688
              tmp_pnt.x = pnt->x * scale_x_factor;
 
689
              tmp_pnt.y = pnt->y * scale_y_factor;
 
690
            }
 
691
 
 
692
          d_pnt_add_line (tmp_line, tmp_pnt.x, tmp_pnt.y, -1);
 
693
          free_one_obj (obj_creating);
 
694
          /* Must free obj_creating */
 
695
        }
 
696
      else
 
697
        {
 
698
          tmp_line = obj_creating;
 
699
          add_to_all_obj (gfig_context->current_obj, obj_creating);
 
700
        }
 
701
 
 
702
      obj_creating = d_new_object (LINE, pnt->x, pnt->y);
 
703
    }
 
704
  else
 
705
    {
 
706
      if (tmp_line)
 
707
        {
 
708
          GdkPoint tmp_pnt = *pnt;
 
709
 
 
710
          if (need_to_scale)
 
711
            {
 
712
              tmp_pnt.x = pnt->x * scale_x_factor;
 
713
              tmp_pnt.y = pnt->y * scale_y_factor;
 
714
            }
 
715
 
 
716
          d_pnt_add_line (tmp_line, tmp_pnt.x, tmp_pnt.y, -1);
 
717
          free_one_obj (obj_creating);
 
718
          /* Must free obj_creating */
 
719
        }
 
720
      else
 
721
        {
 
722
          add_to_all_obj (gfig_context->current_obj, obj_creating);
 
723
        }
 
724
      obj_creating = NULL;
 
725
      tmp_line = NULL;
 
726
    }
 
727
  /*gtk_widget_queue_draw (gfig_context->preview);*/
 
728
}
 
729
 
 
730
void
 
731
d_arc_end (GdkPoint *pnt,
 
732
           gboolean  shift_down)
 
733
{
 
734
  /* Under control point */
 
735
  if (!tmp_line               ||
 
736
      !tmp_line->points       ||
 
737
      !tmp_line->points->next)
 
738
    {
 
739
      /* No arc created  - yet. Must have three points */
 
740
      d_arc_line_end (pnt, TRUE);
 
741
    }
 
742
  else
 
743
    {
 
744
      /* Complete arc */
 
745
      /* Convert to an arc ... */
 
746
      tmp_line->type = ARC;
 
747
      tmp_line->class = &dobj_class[ARC];
 
748
      d_arc_line_end (pnt, FALSE);
 
749
      if (need_to_scale)
 
750
        {
 
751
          selvals.scaletoimage = 0;
 
752
        }
 
753
      /*d_draw_arc (newarc);*/
 
754
      gtk_widget_queue_draw (gfig_context->preview);
 
755
      if (need_to_scale)
 
756
        {
 
757
          selvals.scaletoimage = 1;
 
758
        }
 
759
    }
 
760
}
 
761