Always redraw the screen using a blit from the backbuffer.
[geda-gaf/peter-b.git] / gschem / src / o_arc.c
blob3fc6ee4d282d0a2aa87ec2f934e0dab08e00860c
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
21 #include <stdio.h>
22 #include <math.h>
24 #include <libgeda/libgeda.h>
26 #include "../include/gschem_struct.h"
27 #include "../include/globals.h"
28 #include "../include/prototype.h"
30 #ifdef HAVE_LIBDMALLOC
31 #include <dmalloc.h>
32 #endif
34 /* Kazu on July 8, 1999 - added these macros to simplify the code */
35 /*! \brief */
36 #define GET_BOX_WIDTH(w) \
37 abs((w)->last_x - (w)->start_x)
38 /*! \brief */
39 #define GET_BOX_HEIGHT(w) \
40 abs((w)->last_y - (w)->start_y)
42 typedef void (*DRAW_FUNC)( GdkDrawable *w, GdkGC *gc, GdkColor *color,
43 GdkCapStyle cap, gint x, gint y, gint radius,
44 gint angle1, gint angle2,
45 gint arc_width, gint length, gint space );
47 /*! \brief
48 * \note pb20011011 - added this macro to compute distance
50 #define GET_DISTANCE(w) \
51 sqrt(pow((w)->last_x-(w)->start_x,2)+pow((w)->last_y-(w)->start_y,2))
53 /*! \brief Draw an arc on the screen.
54 * \par Function Description
55 * This function is used to draw an arc on screen. The arc is described
56 * in the object which is referred by <B>o_current</B>. The arc is displayed
57 * according to the current state, described in the GSCHEM_TOPLEVEL object
58 * pointed by <B>w_current</B>.
60 * It first checkes if the object is valid or not. If not it returns
61 * and do not output anything. That should never happen though.
63 * \param [in] w_current The GSCHEM_TOPLEVEL object.
64 * \param [in] o_current The arc OBJECT to draw.
66 void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
68 TOPLEVEL *toplevel = w_current->toplevel;
69 int wleft, wright, wtop, wbottom;
70 int x, y, radius, start_angle, end_angle;
71 int arc_width;
72 GdkCapStyle arc_end;
73 GdkColor *color;
74 DRAW_FUNC draw_func = NULL;
75 int length, space;
77 if (o_current->arc == NULL) {
78 return;
81 world_get_arc_bounds(toplevel, o_current,
82 &wleft, &wtop, &wright, &wbottom);
84 if ( (toplevel->DONT_REDRAW == 1) ||
85 (!visible(toplevel, wleft, wtop, wright, wbottom)) ) {
86 return;
90 * As an arc is definetely not a closed shape there is no need to
91 * define and call any filling function. Another way to say that is
92 * that an arc can not be filled. It simply draws the arc according
93 * to the type line.
95 * The values describing the line type are extracted from the
96 * <B>o_current</B> pointed structure. These are the width of the line,
97 * the field called length and the field called space and the desired
98 * end type for the arc.
100 * Depending on the type of line desired the appropriate function is
101 * called. Values of space and length are adapted to the type of line.
102 * The possible functions are the following : #o_arc_draw_solid(),
103 * #o_arc_draw_dotted(), #o_arc_draw_dashed() and #o_arc_draw_phantom().
105 * The combination <B>length</B> == 0 and <B>space</B> == 0 is avoided as it
106 * leads to an endless loop in function called after. If such a case is
107 * encountered the arc is drawn as a solid arc independently of its
108 * initial type.
110 WORLDtoSCREEN( toplevel, o_current->arc->x, o_current->arc->y, &x, &y );
111 radius = SCREENabs( toplevel, o_current->arc->width / 2 );
112 start_angle = o_current->arc->start_angle;
113 end_angle = o_current->arc->end_angle;
115 #if DEBUG
116 printf("drawing arc x: %d y: %d sa: %d ea: %d width: %d height: %d\n",
119 o_current->arc->start_angle,
120 o_current->arc->end_angle,
121 radius,
122 radius);
123 #endif
125 if (toplevel->override_color != -1 )
126 color = x_get_color(toplevel->override_color);
127 else
128 color = x_get_color(o_current->color);
130 arc_width = SCREENabs( toplevel, o_current->line_width );
131 if(arc_width <= 0) {
132 arc_width = 1;
135 switch(o_current->line_end) {
136 case END_NONE: arc_end = GDK_CAP_BUTT; break;
137 case END_SQUARE: arc_end = GDK_CAP_PROJECTING; break;
138 case END_ROUND: arc_end = GDK_CAP_ROUND; break;
139 default: fprintf(stderr, _("Unknown end for arc (%d)\n"), o_current->line_end);
140 arc_end = GDK_CAP_BUTT;
141 break;
144 length = SCREENabs( toplevel, o_current->line_length );
145 space = SCREENabs( toplevel, o_current->line_space );
147 switch(o_current->line_type) {
148 case TYPE_SOLID:
149 length = -1;
150 space = -1;
151 draw_func = o_arc_draw_solid;
152 break;
154 case TYPE_DOTTED:
155 length = -1; /* AVH changed o_arc_draw_dotted to use */
156 /* space parameter only */
157 draw_func = o_arc_draw_dotted;
158 break;
160 case TYPE_DASHED:
161 draw_func = o_arc_draw_dashed;
162 break;
164 case TYPE_CENTER:
165 draw_func = o_arc_draw_center;
166 break;
168 case TYPE_PHANTOM:
169 draw_func = o_arc_draw_phantom;
170 break;
172 case TYPE_ERASE:
173 break;
175 default:
176 length = -1;
177 space = -1;
178 arc_width = 0; /* just to be careful */
179 draw_func = o_arc_draw_solid;
180 fprintf(stderr, _("Unknown type for arc !\n"));
181 break;
184 if((length == 0) || (space == 0))
185 draw_func = o_arc_draw_solid;
187 (*draw_func)(w_current->backingstore, w_current->gc, color,
188 arc_end,
189 x, y, radius, start_angle, end_angle,
190 arc_width, length, space);
193 if (o_current->draw_grips && w_current->draw_grips == TRUE) {
195 /* pb29911903 - modified to use the new o_arc_[draw|erase]_grips() */
196 if(!o_current->selected) {
197 /* object is no more selected, erase the grips */
198 o_current->draw_grips = FALSE;
199 o_arc_erase_grips(w_current, o_current);
200 } else {
201 /* object is selected, draw the grips on the arc */
202 o_arc_draw_grips(w_current, o_current);
208 #if DEBUG
209 printf("drawing arc\n");
210 #endif
213 /*! \brief Draw an arc with a solid line type.
214 * \par Function Description
215 * This function draw an arc with a solid line type. The arc is defined
216 * by two angle (start and end of arc) and the definition of a box by
217 * which the arc is restricted by. The parameters <B>length</B> and
218 * <B>space</B> are unused here.
220 * The unit of <B>x</B>, <B>y</B> and <B>width</B>, <B>height</B> and <B>arc_width</B>,
221 * <B>space</B>, <B>length</B> is pixel.
223 * <B>angle1</B> and <B>angle2</B> are in degrees.
225 * The lines attributes are settled. Then it simply make a call to
226 * the gdk original function.
228 * \param [in] w GdkWindow to draw in.
229 * \param [in] gc GdkGC graphics context to draw on.
230 * \param [in] color Arc line color.
231 * \param [in] cap Arc line end cap type (unused).
232 * \param [in] x Arc center x.
233 * \param [in] y Arc center y.
234 * \param [in] radius Arc radius.
235 * \param [in] angle1 Start angle in degrees.
236 * \param [in] angle2 End angle in degrees.
237 * \param [in] arc_width Width of arc line.
238 * \param [in] length (unused)
239 * \param [in] space (unused)
241 void o_arc_draw_solid(GdkWindow *w, GdkGC *gc,
242 GdkColor *color, GdkCapStyle cap,
243 gint x, gint y, gint radius,
244 gint angle1, gint angle2,
245 gint arc_width, gint length, gint space)
247 gdk_gc_set_foreground(gc, color);
248 /* Set the width, end type and join style of the line */
249 gdk_gc_set_line_attributes(gc, arc_width,
250 GDK_LINE_SOLID, cap, GDK_JOIN_MITER);
252 /* Draw the arc */
253 gdk_draw_arc(w, gc, FALSE,
254 x - radius, y - radius, 2 * radius, 2 * radius,
255 angle1 * 64, angle2 * 64);
259 /*! \brief Draw an arch with a dotted line type.
260 * \par Function Description
261 * This functions draws an arc with a dotted line type. The parameter
262 * <B>space</B> represents the distance between two of the dots. The
263 * parameter <B>length</B> is unused. The diameter of the dots is given
264 * by the width of the line given by <B>arc_width</B>.
266 * The unit of <B>x</B>, <B>y</B> and <B>width</B>, <B>height</B> and
267 * <B>arc_width</B>, <B>space</B>, <B>length</B> is pixel.
269 * <B>angle1</B> and <B>angle2</B> are in degrees.
270 * A negative or null value for length leads to an endless loop.
271 * length parameter is not used here.
273 * \param [in] w GdkWindow to draw in.
274 * \param [in] gc GdkGC graphics context to draw on.
275 * \param [in] color Arc line color.
276 * \param [in] cap Arc line end cap type (unused).
277 * \param [in] x Arc center x.
278 * \param [in] y Arc center y.
279 * \param [in] radius Arc radius.
280 * \param [in] angle1 Start angle in degrees.
281 * \param [in] angle2 End angle in degrees.
282 * \param [in] arc_width Width of arc line.
283 * \param [in] length (unused).
284 * \param [in] space Spacing between dots in pixels.
286 void o_arc_draw_dotted(GdkWindow *w, GdkGC *gc,
287 GdkColor *color, GdkCapStyle cap,
288 gint x, gint y, gint radius,
289 gint angle1, gint angle2,
290 gint arc_width, gint length, gint space)
292 double xa, ya;
293 int da, d;
295 gdk_gc_set_foreground(gc, color);
298 * It calculates the angle that match the length <B>space</B> as <B>da</B>.
299 * If <B>da</B> is negative or null, the way the function uses it after
300 * leads to an andless loop. In fact such a case occur when it is not
301 * possible to distinguish a solid line from a dotted line because of
302 * zoom factor. The arc is therefore drawn solid.
304 /* PB inverting angle2 if < 0 and changing angle1 accordingly */
305 /* the loop test assume that da > 0 */
306 if(angle2 < 0) {
307 angle1 = angle1 + angle2;
308 angle2 = -angle2;
311 da = space * 180 / (M_PI * radius);
313 /* If da is too small for arc to be displayed as dotted,
314 draw a solid arc */
315 if(da <= 0) {
316 gdk_draw_arc(w, gc, FALSE,
317 x - radius, y - radius, 2 * radius, 2 * radius,
318 angle1 * 64, angle2 * 64);
319 return;
322 * It starts from <B>angle1</B> and increments <B>angle1</B> by <B>da</B> as
323 * a loop until all the arc has been browsed. For each angle value a
324 * dot is drawing after calculating back its coordinates from the angle.
326 d = angle1;
327 while(d < (angle2 + angle1)) {
328 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
329 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
332 * Depending on the width of the line, dots has to be drawn in a
333 * different manner : if the real worl width is equal to 0, then the
334 * width is translated to 1 in screen coordinates to be visible.
335 * Drawing a circle with a 1-diameter and the GDK function
336 * #gdk_draw_arc() is not possible. So we needs to test
337 * whether the width is 1 or not.
339 if(arc_width == 1) {
340 gdk_draw_point(w, gc, (int) xa, (int) ya);
341 } else {
342 gdk_draw_arc(w, gc, TRUE,
343 ((int) xa) - arc_width/2,
344 ((int) ya) - arc_width/2,
345 arc_width, arc_width, 0, FULL_CIRCLE);
348 d = d + da;
353 /*! \brief Draw an arc with a dashed line type.
354 * This functions draws an arc with a dashed line type. The parameter
355 * <B>space</B> represents the distance between two of the dash. The
356 * parameter <B>length</B> represents the length of the dash.
358 * The unit of <B>x</B>, <B>y</B> and <B>width</B>, <B>height</B> and
359 * <B>arc_width</B>, <B>space</B>, <B>length</B> is pixel.
361 * <B>angle1</B> and <B>angle2</B> are in degrees.
363 * A negative or null value for <B>length</B> and <B>space</B> leads to an
364 * endless loop.
366 * \param [in] w GdkWindow to draw in.
367 * \param [in] gc GdkGC graphics context to draw on.
368 * \param [in] color Arc line color.
369 * \param [in] cap Arc line end cap type (unused).
370 * \param [in] x Arc center x.
371 * \param [in] y Arc center y.
372 * \param [in] radius Arc radius.
373 * \param [in] angle1 Start angle in degrees.
374 * \param [in] angle2 End angle in degrees.
375 * \param [in] arc_width Width of arc line.
376 * \param [in] length Length of dash in pixels..
377 * \param [in] space Spacing between dashes in pixels.
379 void o_arc_draw_dashed(GdkWindow *w, GdkGC *gc,
380 GdkColor *color, GdkCapStyle cap,
381 gint x, gint y,
382 gint radius,
383 gint angle1, gint angle2,
384 gint arc_width, gint length, gint space)
386 int da, db, a1, a2, d;
388 gdk_gc_set_foreground(gc, color);
389 gdk_gc_set_line_attributes(gc, arc_width, GDK_LINE_SOLID, cap,
390 GDK_JOIN_MITER);
393 * The function first determines the radius and the center of the arc.
395 * The function determines the angular increments that match the
396 * <B>length</B> and <B>space</B> parameter. These are <B>db</B> and <B>da</B>.
397 * Whenever one or both of these variables are null or negative, the
398 * line is drawn solid. It means that it is not possible to distinguish
399 * a dashed line from a solid line because of current value of zoom.
402 /* PB inverting angle2 if < 0 and changing angle1 accordingly */
403 /* the loop test assume that da > 0 */
404 if(angle2 < 0) {
405 angle1 = angle1 + angle2;
406 angle2 = -angle2;
408 da = length * 180 / (M_PI * radius);
409 db = space * 180 / (M_PI * radius);
411 /* If da or db too small for arc to be displayed as dotted,
412 draw a solid arc */
413 if((da <= 0) || (db <= 0)) {
414 gdk_draw_arc(w, gc, FALSE,
415 x - radius, y - radius, 2 * radius, 2 * radius,
416 angle1 * 64, angle2 * 64);
417 return;
421 * It starts from <B>angle1</B> and increments <B>angle1</B> by <B>da</B> as a
422 * loop until the whole arc has been browsed. At each position a dash
423 * of length <B>length</B> - represented by the <B>da</B> increment - is drawn.
425 * It draws as many dashes of length <B>length</B> as possible.
428 d = angle1;
429 while((d + da + db) < (angle1 + angle2)) {
430 a1 = d;
431 d = d + da;
432 gdk_draw_arc(w, gc, FALSE,
433 x - radius, y - radius, 2 * radius, 2 * radius,
434 a1 * 64, da * 64);
436 d = d + db;
441 * When the above condition is no more satisfied, the it is possible
442 * to draw a dash of length <B>length</B>. However it may be possible to
443 * draw a shorter dash.
446 if((d + da) < (angle1 + angle2)) {
447 a1 = d;
448 a2 = da;
449 } else {
450 a1 = d;
451 a2 = (angle1 + angle2) - d;
453 gdk_draw_arc(w, gc, FALSE,
454 x - radius, y - radius, 2 * radius, 2 * radius,
455 a1 * 64, a2 * 64);
460 /*! \brief Draw arc with a centered line type.
461 * \par Function Description
462 * This functions draws an arc with a centered line type. The parameter
463 * <B>space</B> represents the distance between a dot and the dash. The
464 * parameter <B>length</B> represents the length of a dash.
466 * The unit of <B>x</B>, <B>y</B> and <B>width</B>, <B>height</B> and
467 * <B>arc_width</B>, <B>space</B>, <B>length</B> is pixel.
469 * <B>angle1</B> and <B>angle2</B> are in units of degrees.
471 * A negative or null value for <B>length</B> and <B>space</B> leads to an
472 * endless loop.
474 * \param [in] w GdkWindow to draw in.
475 * \param [in] gc GdkGC graphics context to draw on.
476 * \param [in] color Arc line color.
477 * \param [in] cap Arc line end cap type (unused).
478 * \param [in] x Arc center x.
479 * \param [in] y Arc center y.
480 * \param [in] radius Arc radius.
481 * \param [in] angle1 Start angle in degrees.
482 * \param [in] angle2 End angle in degrees.
483 * \param [in] arc_width Width of arc line.
484 * \param [in] length Length of dash in pixels..
485 * \param [in] space Spacing between dashes in pixels.
487 void o_arc_draw_center(GdkWindow *w, GdkGC *gc,
488 GdkColor *color, GdkCapStyle cap,
489 gint x, gint y,
490 gint radius,
491 gint angle1, gint angle2,
492 gint arc_width, gint length, gint space)
494 double xa, ya; /* coordinate of center */
495 int da, db, a1, a2, d;
497 gdk_gc_set_foreground(gc, color);
498 gdk_gc_set_line_attributes(gc, arc_width,
499 GDK_LINE_SOLID, cap, GDK_JOIN_MITER);
502 * The function determines the angular increments that match the
503 * <B>length</B> and <B>space</B> parameter. These are <B>db</B> and <B>da</B>.
504 * Whenever one or both of these variables are null or negative, the
505 * line is drawn solid. It means that it is not possible to distinguish
506 * a dashed line from a solid line because of current value of zoom.
509 /* PB inverting angle2 if < 0 and changing angle1 accordingly */
510 /* the loop test assume that da > 0 */
511 if(angle2 < 0) {
512 angle1 = angle1 + angle2;
513 angle2 = -angle2;
515 da = length * 180 / (M_PI * radius);
516 db = space * 180 / (M_PI * radius);
518 /* If da or db too small to be displayed, draw an arc */
519 if((da <= 0) || (db <= 0)) {
520 gdk_draw_arc(w, gc, FALSE,
521 x - radius, y - radius, 2* radius, 2 * radius,
522 angle1 * 64, angle2 * 64);
523 return;
527 * Starting from <B>angle1</B> and incrementing the position gives the
528 * coordinates of every dots and dashes on the arc providing that the
529 * second extremity is not exceeded.
531 * It draws as many sets of 'dash of length <B>length</B> and dot' as possible.
534 d = angle1;
535 while((d + da + 2 * db) < (angle1 + angle2)) {
536 a1 = d;
537 d = d + da;
538 gdk_draw_arc(w, gc, FALSE,
539 x - radius, y - radius, 2 * radius, 2 * radius,
540 a1 * 64, da * 64);
542 d = d + db;
543 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
544 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
547 if(arc_width == 1) {
548 gdk_draw_point(w, gc, (int) xa, (int) ya);
549 } else {
550 gdk_draw_arc(w, gc, TRUE,
551 ((int) xa) - arc_width/2,
552 ((int) ya) - arc_width/2,
553 arc_width, arc_width, 0, FULL_CIRCLE);
557 * If the above condition is no more satisfied, it may still be possible
558 * to continue drawing a part of the initial pattern. Here two cases are
559 * possible :
560 * <DL>
561 * <DT>*</DT><DD>it is possible to draw a dash and a dot.
562 * <DT>*</DT><DD>it is possible to draw a dash or at least
563 * a part of the original dash.
564 * </DL>
567 d = d + db;
571 if((d + da) < (angle1 + angle2)) {
572 a1 = d;
573 a2 = da;
575 d = d + da;
576 } else {
577 a1 = d;
578 a2 = (angle1 + angle2) - d;
580 d = d + da;
582 gdk_draw_arc(w, gc, FALSE,
583 x - radius, y - radius, 2 * radius, 2 * radius,
584 a1 * 64, da * 64);
586 if((d + db) < (angle1 + angle2)) {
587 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
588 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
591 * Depending on the width of the line, dots has to be drawn in a
592 * different manner : if the real worl width is equal to 0, then the
593 * width is translated to 1 in screen coordinates to be visible.
594 * Drawing a circle with a 1-diameter and the GDK function
595 * #gdk_draw_arc() is not possible. So we needs to test whether the
596 * width is 1 or not.
599 if(arc_width == 1) {
600 gdk_draw_point(w, gc, (int) xa, (int) ya);
601 } else {
602 gdk_draw_arc(w, gc, TRUE,
603 ((int) xa) - arc_width/2,
604 ((int) ya) - arc_width/2,
605 arc_width, arc_width, 0, FULL_CIRCLE);
614 /*! \brief Draw an arc with a phantom line type.
615 * \par Function Description
616 * This function draws an arc with a phantom line type. The parameter
617 * <B>space</B> represents the distance between a dot and a dash. The
618 * parameter <B>length</B> represents the length of a dash.
620 * The unit of <B>x</B>, <B>y</B> and <B>width</B>, <B>height</B> and
621 * <B>arc_width</B>, <B>space</B>, <B>length</B> is pixel.
623 * <B>angle1</B> and <B>angle2</B> are in units of degrees.
625 * A negative or null value for <B>length</B> and <B>space</B> leads to an
626 * endless loop.
628 * \param [in] w GdkWindow to draw in.
629 * \param [in] gc GdkGC graphics context to draw on.
630 * \param [in] color Arc line color.
631 * \param [in] cap Arc line end cap type (unused).
632 * \param [in] x Arc center x.
633 * \param [in] y Arc center y.
634 * \param [in] radius Arc radius.
635 * \param [in] angle1 Start angle in degrees.
636 * \param [in] angle2 End angle in degrees.
637 * \param [in] arc_width Width of arc line.
638 * \param [in] length Length of dash in pixels.
639 * \param [in] space Spacing between dashes in pixels.
641 void o_arc_draw_phantom(GdkWindow *w, GdkGC *gc,
642 GdkColor *color, GdkCapStyle cap,
643 gint x, gint y,
644 gint radius,
645 gint angle1, gint angle2,
646 gint arc_width, gint length, gint space)
648 double xa, ya;
649 int da, db, a1, a2, d;
651 gdk_gc_set_foreground(gc, color);
652 gdk_gc_set_line_attributes(gc, arc_width,
653 GDK_LINE_SOLID, cap, GDK_JOIN_MITER);
655 /* The function determines the angular increments that match the
656 * <B>length</B> and <B>space</B> parameters. These are <B>db</B> and <B>da</B>.
657 * Whenever one or both of these variables are null or negative, the
658 * line is drawn solid. It means that it is not possible to distinguish
659 * a dashed line from a solid line because of current value of zoom.
662 /* PB inverting angle2 if < 0 and changing angle1 accordingly */
663 /* the loop test assume that da > 0 */
664 if(angle2 < 0) {
665 angle1 = angle1 + angle2;
666 angle2 = -angle2;
668 da = length * 180 / (M_PI * radius);
669 db = space * 180 / (M_PI * radius);
671 /* If da or db too small for arc to be displayed as dotted,
672 draw a solid arc */
673 if((da <= 0) || (db <= 0)) {
674 gdk_draw_arc(w, gc, FALSE,
675 x - radius, y - radius, 2 * radius, 2 * radius,
676 angle1 * 64, angle2 * 64);
677 return;
681 * Starting from <B>angle1</B> and incrementing the position gives the
682 * coordinates of every dots and dashes on the arc providing that the
683 * second extremity is not exceeded.
685 * It draws as many sets of 'dash of length <B>length</B> and two dots'
686 * as possible.
689 d = angle1;
690 while((d + da + 3 * db) < (angle1 + angle2)) {
691 a1 = d;
692 d = d + da;
693 gdk_draw_arc(w, gc, FALSE,
694 x - radius, y - radius, 2 * radius, 2 * radius,
695 a1 * 64, da * 64);
697 d = d + db;
698 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
699 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
702 * Depending on the width of the line, dots has to be drawn in a
703 * different manner : if the real worl width is equal to 0, then the
704 * width is translated to 1 in screen coordinates to be visible.
705 * Drawing a circle with a 1-diameter and the GDK function
706 * #gdk_draw_arc() is not possible. So we needs to test whether the
707 * width is 1 or not.
710 if(arc_width == 1) {
711 gdk_draw_point(w, gc, (int) xa, (int) ya);
712 } else {
713 gdk_draw_arc(w, gc, TRUE,
714 ((int) xa) - arc_width/2,
715 ((int) ya) - arc_width/2,
716 arc_width, arc_width, 0, FULL_CIRCLE);
720 d = d + db;
721 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
722 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
726 * Depending on the width of the line, dots has to be drawn in a
727 * different manner : if the real world width is equal to 0, then the
728 * width is translated to 1 in screen coordinates to be visible. Drawing
729 * a circle with a 1-diameter and the GDK function #gdk_draw_arc() is
730 * not possible. So we needs to test whether the width is 1 or not.
733 if(arc_width == 1) {
734 gdk_draw_point(w, gc, (int) xa, (int) ya);
735 } else {
736 gdk_draw_arc(w, gc, TRUE,
737 ((int) xa) - arc_width/2,
738 ((int) ya) - arc_width/2,
739 arc_width, arc_width, 0, FULL_CIRCLE);
744 d = d + db;
748 * If the above condition is no more satisfied, it may still be possible
749 * to continue drawing a part of the original pattern. Here three cases
750 * are possible :
751 * <DL>
752 * <DT>*</DT><DD>it is possible to draw a dash and the two dots.
753 * <DT>*</DT><DD>it is possible to draw a dash and one of the two dots.
754 * <DT>*</DT><DD>it is possible to draw at least a part of the initial
755 * dash.
758 if((d + da) < (angle1 + angle2)) {
759 a1 = d;
760 a2 = da;
761 d = d + da;
762 } else {
763 a1 = d;
764 a2 = (angle1 + angle2) - d;
765 d = d + da;
767 gdk_draw_arc(w, gc, FALSE,
768 x - radius, y - radius, 2 * radius, 2 * radius,
769 a1 * 64, a2 * 64);
771 if((d + db) < (angle1 + angle2)) {
772 d = d + db;
774 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
775 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
777 if(arc_width == 1) {
778 gdk_draw_point(w, gc, (int) xa, (int) ya);
779 } else {
780 gdk_draw_arc(w, gc, TRUE,
781 ((int) xa) - arc_width/2,
782 ((int) ya) - arc_width/2,
783 arc_width, arc_width, 0, FULL_CIRCLE);
787 if((d + db) < (angle1 + angle2)) {
788 d = d + db;
790 xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
791 ya = ((double) y) - ((double) radius) * sin(d * M_PI / 180);
793 if(arc_width == 1) {
794 gdk_draw_point(w, gc, (int) xa, (int) ya);
795 } else {
796 gdk_draw_arc(w, gc, TRUE,
797 ((int) xa) - arc_width/2,
798 ((int) ya) - arc_width/2,
799 arc_width, arc_width, 0, FULL_CIRCLE);
806 /*! \brief Erase arc described by OBJECT.
807 * \par Function Description
808 * This function erases the arc described in the <B>OBJECT</B> structure
809 * pointed by <B>o_current</B>.
811 * It makes a call to the #o_box_draw() function after setting the
812 * special color. Therefo re an arc is drawn with the background color
813 * over the previous one.
815 void o_arc_erase(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
817 TOPLEVEL *toplevel = w_current->toplevel;
818 toplevel->override_color = toplevel->background_color;
819 o_arc_draw(w_current, o_current);
820 toplevel->override_color = -1;
823 /*! \todo Finish function documentation!!!
824 * \brief
825 * \par Function Description
828 void o_arc_eraserubber(GSCHEM_TOPLEVEL *w_current)
830 o_arc_rubberarc_xor(w_current);
833 /*! \brief Draw an arc described by OBJECT with translation
834 * \par Function Description
835 * This function draws the arc object described by <B>*o_current</B>
836 * translated by the vector (<B>dx</B>,<B>dy</B>) with an xor-function over
837 * the current sheet.
838 * The translation vector is in screen unit.
840 * The arc is displayed with the color of the object.
842 * \param [in] w_current The GSCHEM_TOPLEVEL object.
843 * \param [in] dx Delta x coordinate for arc.
844 * \param [in] dy Delta y coordinate for arc.
845 * \param [in] o_current Arc OBJECT to draw.
847 void o_arc_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
849 TOPLEVEL *toplevel = w_current->toplevel;
850 int x, y, width, height, start_angle, end_angle;
851 int color;
853 if (o_current->arc == NULL) {
854 return;
857 /* diameter */
858 width = SCREENabs( toplevel, o_current->arc->width );
859 /* height MUST be equal to width, just another name for diameter */
860 height = SCREENabs( toplevel, o_current->arc->height );
861 /* center */
862 WORLDtoSCREEN( toplevel, o_current->arc->x, o_current->arc->y, &x, &y );
863 x -= (width / 2);
864 y -= (height / 2);
865 /* start and end angles */
866 start_angle = o_current->arc->start_angle;
867 end_angle = o_current->arc->end_angle;
869 /* check the size of the displayed arc */
870 /* do not allow null diameter = arc always displayed */
871 if (height < 1) {
872 height = 1;
874 if (width < 1) {
875 width = 1;
878 if (o_current->saved_color != -1) {
879 color = o_current->saved_color;
880 } else {
881 color = o_current->color;
884 gdk_gc_set_foreground(w_current->outline_xor_gc,
885 x_get_darkcolor(color));
886 /* better to set the line attributes here ? */
887 gdk_draw_arc(w_current->backingstore, w_current->outline_xor_gc, FALSE,
888 x + dx, y + dy, width, height,
889 start_angle * 64, end_angle * 64);
891 /* backing store? not appropriate here */
895 /*! \brief Start process to input a new arc.
896 * \par Function Description
897 * This function starts the process to input a new arc. Parameters for
898 * this arc are put into/extracted from the <B>w_current</B> toplevel structure.
899 * <B>x</B> and <B>y</B> are current coordinates of the pointer in screen unit.
901 * First step of the arc input is to set the radius of the arc. The center
902 * of the arc is kept in (<B>w_current->start_x</B>,<B>w_current->start_y</B>).
903 * The other point of the radius, i.e. on the arc, in
904 * (<B>w_current->last_x</B>,<B>w_current->last_y</B>). The radius of the arc is
905 * in <B>w_current->distance</B>.
907 * \param [in] w_current The GSCHEM_TOPLEVEL object.
908 * \param [in] x Current x coordinate of pointer in screen units.
909 * \param [in] y Current y coordinate of pointer in screen units.
911 void o_arc_start(GSCHEM_TOPLEVEL *w_current, int x, int y)
913 TOPLEVEL *toplevel = w_current->toplevel;
914 /* set the center of the arc */
915 w_current->last_x = w_current->start_x = fix_x(toplevel, x);
916 w_current->last_y = w_current->start_y = fix_y(toplevel, y);
918 /* set the radius */
919 w_current->distance = 0;
921 /* set the start and end angles */
922 w_current->loc_x = w_current->loc_y = 0;
924 /* start the rubberbanding process of the radius */
925 o_arc_rubberarc_xor(w_current);
929 /*! \brief End the input of an arc.
930 * \par Function Description
931 * This function ends the input of the radius of the arc.
932 * The (<B>x</B>,<B>y</B>) point is taken as the other end of the radius segment.
933 * The distance between this point and the center is the radius of the arc.
934 * <B>x</B> and <B>y</B> are in screen coords.
936 * At the end of this function, the center of the arc is at
937 * (<B>w_current->start_x</B>,<B>w_current->start_y</B>) and its radius is
938 * <B>w_current->distance</B>.
940 * The two angles needs to be input to fully define the arc.
942 * \param [in] w_current The GSCHEM_TOPLEVEL object.
943 * \param [in] x Current x coordinate of pointer in screen units.
944 * \param [in] y Current y coordinate of pointer in screen units.
946 void o_arc_end1(GSCHEM_TOPLEVEL *w_current, int x, int y)
948 TOPLEVEL *toplevel = w_current->toplevel;
949 int diff_x, diff_y;
951 g_assert( w_current->inside_action != 0 );
953 /* erases the previous temporary radius segment */
954 o_arc_rubberarc_xor(w_current);
956 w_current->last_x = fix_x(toplevel, x);
957 w_current->last_y = fix_y(toplevel, y);
958 /* compute the radius */
959 diff_x = GET_BOX_WIDTH (w_current);
960 diff_y = GET_BOX_HEIGHT(w_current);
961 if (diff_x >= diff_y) {
962 w_current->distance = diff_x;
963 } else {
964 w_current->distance = diff_y;
967 /* ack! zero length radius */
968 if (w_current->distance == 0) {
969 return;
972 #if DEBUG
973 printf("DIST: %d\n", w_current->distance);
974 #endif
976 /* open a dialog to input the start and end angle */
977 arc_angle_dialog(w_current);
981 /*! \brief Set the start angle of a temporary arc.
982 * \par Function Description
983 * This function sets the start angle of the temporary representation of
984 * an arc. This angle is determined from the current mouse position
985 * described by <B>x</B> and <B>y</B> in screen coords, and the arc center
986 * previously set as (<B>w_current->start_x</B>,<B>w_current->start_y</B>).
988 * The previous temporary arc is erased, the start angle is then updated
989 * and finally, the temporary arc is drawn again.
991 * This function is used when the input of an arc is fully interactive,
992 * not through a dialog box.
994 * \param [in] w_current The GSCHEM_TOPLEVEL object.
995 * \param [in] x Current x coordinate of pointer in screen units.
996 * \param [in] y Current y coordinate of pointer in screen units.
998 void o_arc_end2(GSCHEM_TOPLEVEL *w_current, int x, int y)
1000 double dx, dy, d, cos_a_, sin_a_, a;
1002 /* erase the previous temporary arc */
1003 o_arc_rubberarc_xor(w_current);
1005 /* compute the start angle */
1006 dx = ((double) x) - ((double) w_current->start_x);
1007 dy = - ((double) y) + ((double) w_current->start_y);
1008 d = sqrt((dx * dx) + (dy * dy));
1010 sin_a_ = dy / ((double) d);
1011 cos_a_ = dx / ((double) d);
1012 a = asin(sin_a_) * 180 / M_PI;
1013 if(a < 0) a *= -1;
1015 /* find the right quadrant */
1016 if(sin_a_ >= 0) {
1017 if(cos_a_ >= 0) a = a;
1018 else a = 180 - a;
1019 } else {
1020 if(cos_a_ >= 0) a = 360 - a;
1021 else a = 180 + a;
1024 /* start angle in degree is in a */
1025 w_current->loc_x = (int) a;
1027 /* draw the new temporary arc */
1028 o_arc_rubberarc_xor(w_current);
1032 /*! \brief Set the end angle during the input of a new arc object.
1033 * \par Function Description
1034 * This function sets the end angle during the input of a new arc object.
1035 * The angle is computed from the current mouse position in <B>x</B> and
1036 * <B>y</B> and the center of the arc. The arc is internally represented
1037 * with its center in (<B>w_current->start_x</B>,<B>w_current->start_y</B>),
1038 * its radius in <B>w_current->distance</B> and its start angle in
1039 * <B>w_current->loc_x</B>.
1041 * The temporary arc is erased, a new object is initialized and drawn.
1043 * This function is used when the input of an arc is fully interactive,
1044 * i.e. not through a dialog box.
1046 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1047 * \param [in] x Current x coordinate of pointer in screen units.
1048 * \param [in] y Current x coordinate of pointer in screen units.
1050 void o_arc_end3(GSCHEM_TOPLEVEL *w_current, int x, int y)
1052 TOPLEVEL *toplevel = w_current->toplevel;
1053 double d, dx, dy, cos_a_, sin_a_, a;
1055 /* erase the previous temporary arc */
1056 o_arc_rubberarc_xor(w_current);
1058 /* compute the end angle */
1059 dx = ((double) x) - ((double) w_current->start_x);
1060 dy = - ((double) y) + ((double) w_current->start_y);
1061 d = sqrt((dx * dx) + (dy * dy));
1063 sin_a_ = dy / ((double) d);
1064 cos_a_ = dx / ((double) d);
1065 a = asin(sin_a_) * 180 / M_PI;
1066 if(a < 0) a *= -1;
1068 /* find the right quadrant */
1069 if(sin_a_ >= 0) {
1070 if(cos_a_ >= 0) a = a;
1071 else a = 180 - a;
1072 } else {
1073 if(cos_a_ >= 0) a = 360 - a;
1074 else a = 180 + a;
1077 /* end angle in degree is in a */
1078 w_current->loc_y = (int) a;
1080 /* create, initialize and link the new arc object */
1081 toplevel->page_current->object_tail =
1082 o_arc_add(toplevel, toplevel->page_current->object_tail,
1083 OBJ_ARC, w_current->graphic_color,
1084 w_current->start_x, w_current->start_y,
1085 w_current->distance,
1086 w_current->loc_x, w_current->loc_y);
1088 /* draw the new object */
1089 o_redraw_single(w_current, toplevel->page_current->object_tail);
1091 w_current->start_x = (-1);
1092 w_current->start_y = (-1);
1093 w_current->last_x = (-1);
1094 w_current->last_y = (-1);
1095 w_current->loc_x = -1;
1096 w_current->loc_y = -1;
1097 w_current->distance = -1;
1099 toplevel->page_current->CHANGED = 1;
1101 o_undo_savestate(w_current, UNDO_ALL);
1105 /*! \brief Ends the process of arc input.
1106 * \par Function Description
1107 * The #o_arc_end4() function ends the process of the input of an arc.
1108 * <B>start_angle</B> and <B>end_angle</B> are the start and end angle of the
1109 * arc in degrees. The partial internal representation of the arc, i.e.
1110 * the center and the radius of the arc, are converted in world units.
1111 * A new object is created and linked to the object list.
1113 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1114 * \param [in] start_angle Start of angle in degrees.
1115 * \param [in] end_angle End of angle in degrees.
1117 void o_arc_end4(GSCHEM_TOPLEVEL *w_current, int start_angle, int end_angle)
1119 TOPLEVEL *toplevel = w_current->toplevel;
1120 int x1, y1;
1121 int radius;
1123 /* get the center in world coords */
1124 SCREENtoWORLD(toplevel,
1125 w_current->start_x, w_current->start_y,
1126 &x1, &y1);
1128 /* get the radius in world coords */
1129 radius = snap_grid(toplevel, WORLDabs(toplevel, w_current->distance));
1131 /* create, initialize and link the new arc object */
1132 toplevel->page_current->object_tail =
1133 o_arc_add(toplevel, toplevel->page_current->object_tail,
1134 OBJ_ARC, w_current->graphic_color,
1135 x1, y1, radius, start_angle, end_angle);
1137 /* draw the new object */
1138 o_redraw_single(w_current, toplevel->page_current->object_tail);
1140 w_current->start_x = (-1);
1141 w_current->start_y = (-1);
1142 w_current->last_x = (-1);
1143 w_current->last_y = (-1);
1144 w_current->loc_x = -1;
1145 w_current->loc_y = -1;
1146 w_current->distance = -1;
1148 toplevel->page_current->CHANGED = 1;
1150 o_undo_savestate(w_current, UNDO_ALL);
1154 /*! \brief Draw an arc using one angle modification.
1155 * \par Function Description
1156 * This function draws an arc according to its internal representation
1157 * and allows the modification of one of its angle. The start or end
1158 * angle of the arc is updated according to <B>whichone</B> with the angle
1159 * that the current pointer and the arc center are making with the horizontal.
1161 * The previous temporary arc is erased, the angle is then computed
1162 * and updated and finally a new temporary arc with the new angle is drawn.
1164 * The arc is internally described by :
1165 * <DL>
1166 * <DT>*</DT><DD>(<B>w_current->start_x</B>,<B>w_current->start_y</B>) as
1167 * its center.
1168 * <DT>*</DT><DD><B>w_current->distance</B> as its radius.
1169 * <DT>*</DT><DD><B>w_current->loc_x</B> and <B>w_current->loc_y</B> as its
1170 * start and end angle respectively.
1171 * </DL>
1173 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1174 * \param [in] x Current x coordinate of pointer in screen units.
1175 * \param [in] y Current y coordinate of pointer in screen units.
1176 * \param [in] whichone Which angle to change.
1178 * <B>whichone</B> can have one of the following values:
1179 * <DL>
1180 * <DT>*</DT><DD>ARC_START_ANGLE
1181 * <DT>*</DT><DD>ARC_END_ANGLE
1182 * </DL>
1184 void o_arc_rubberarc(GSCHEM_TOPLEVEL *w_current, int x, int y, int whichone)
1186 TOPLEVEL *toplevel = w_current->toplevel;
1187 double dx, dy, a;
1188 int diff_x, diff_y;
1190 /* erase the previous temporary arc */
1191 o_arc_rubberarc_xor(w_current);
1193 if(whichone == ARC_RADIUS) {
1196 * The radius is taken as the biggest distance on the x and y
1197 * axis between the center of the arc and the mouse position.
1199 /* update the radius */
1200 w_current->last_x = fix_x(toplevel, x);
1201 w_current->last_y = fix_y(toplevel, y);
1203 diff_x = GET_BOX_WIDTH (w_current);
1204 diff_y = GET_BOX_HEIGHT(w_current);
1205 if (diff_x >= diff_y) {
1206 w_current->distance = diff_x;
1207 } else {
1208 w_current->distance = diff_y;
1212 else if((whichone == ARC_START_ANGLE) || (whichone == ARC_END_ANGLE)) {
1214 /* compute the angle */
1215 dx = ((double) x) - ((double) w_current->start_x);
1216 dy = - ((double) y) + ((double) w_current->start_y);
1217 a = atan2(dy,dx) * 180 / M_PI;
1219 /* set the start or end angle with this angle */
1220 switch(whichone) {
1221 case ARC_START_ANGLE:
1222 w_current->loc_x = ((int) a + 360) % 360;
1223 break;
1225 case ARC_END_ANGLE:
1226 w_current->loc_y = ((int) a - w_current->loc_x + 720) % 360;
1227 break;
1229 default:
1230 return;
1235 /* draw the new temporary arc */
1236 o_arc_rubberarc_xor(w_current);
1240 /*! \brief Draw arc from GSCHEM_TOPLEVEL object.
1241 * \par Function Description
1242 * This function draws the arc from the variables in the GSCHEM_TOPLEVEL
1243 * structure <B>*w_current</B>.
1244 * The center of the arc is at (<B>w_current->start_x</B>,
1245 * <B>w_current->start_y</B>), its radius equal to <B>w_current->radius</B>,
1246 * and the start and end angle are given by <B>w_current->loc_x</B> and
1247 * <B>w_current->loc_y</B>.
1249 * The arc is drawn with a xor function over the current sheet with the
1250 * selection color.
1252 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1254 void o_arc_rubberarc_xor(GSCHEM_TOPLEVEL *w_current)
1256 double tmp;
1257 int x1, y1;
1259 gdk_gc_set_foreground(w_current->xor_gc,
1260 x_get_darkcolor(w_current->select_color));
1261 gdk_gc_set_line_attributes(w_current->xor_gc, 0,
1262 GDK_LINE_SOLID, GDK_CAP_NOT_LAST,
1263 GDK_JOIN_MITER);
1264 /* draw the arc from the w_current variables */
1265 gdk_draw_arc(w_current->backingstore, w_current->xor_gc, FALSE,
1266 w_current->start_x - w_current->distance,
1267 w_current->start_y - w_current->distance,
1268 w_current->distance * 2,
1269 w_current->distance * 2,
1270 w_current->loc_x * 64,
1271 w_current->loc_y * 64);
1272 /* draw the radius segment from the w_current variables */
1273 tmp = ((double) w_current->loc_x) * M_PI / 180;
1274 x1 = w_current->start_x + w_current->distance*cos(tmp);
1275 y1 = w_current->start_y - w_current->distance*sin(tmp);
1276 gdk_draw_line(w_current->backingstore, w_current->xor_gc,
1277 w_current->start_x, w_current->start_y,
1278 x1, y1);
1279 /* FIXME: This isn't a tight bounding box for now, but the code
1280 * to compute a better bounds it complex, and might wait
1281 * until we're considered having real OBJECT data during
1282 * rubberbanding and using world_get_arc_bounds().
1284 o_invalidate_rect(w_current, w_current->start_x - w_current->distance,
1285 w_current->start_y - w_current->distance,
1286 w_current->start_x + w_current->distance,
1287 w_current->start_y + w_current->distance);
1290 /*! \brief Draw grip marks on arc.
1291 * \par Function Description
1292 * This function draws three grips on the center and on the ends of
1293 * the arc object described by <B>*o_current</B>.
1295 * \param [in] w_current The GSCHE_TOPLEVEL object.
1296 * \param [in] o_current Arc OBJECT to draw grip points on.
1298 void o_arc_draw_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
1300 TOPLEVEL *toplevel = w_current->toplevel;
1301 int radius, x, y, start_angle, end_angle;
1302 int x1, y1, x2, y2;
1304 if (w_current->draw_grips == FALSE)
1305 return;
1308 * An arc has three grips:
1309 * <DL>
1310 * <DT>*</DT><DD>one at the center that allows changes on the
1311 * radius - at (<B>x</B>,<B>y</B>).
1312 * <DT>*</DT><DD>one at the start of the arc - at (<B>x1</B>,<B>y1</B>).
1313 * <DT>*</DT><DD>one at the end of the arc - at (<B>x2</B>,<B>y2</B>).
1316 WORLDtoSCREEN( toplevel, o_current->arc->x, o_current->arc->y, &x, &y );
1317 radius = SCREENabs( toplevel, o_current->arc->width / 2 );
1318 start_angle = o_current->arc->start_angle;
1319 end_angle = o_current->arc->end_angle;
1321 x1 = x + radius * cos(((double) start_angle) * M_PI / 180);
1322 y1 = y - radius * sin(((double) start_angle) * M_PI / 180);
1323 x2 = x + radius * cos(((double) (start_angle + end_angle)) * M_PI / 180);
1324 y2 = y - radius * sin(((double) (start_angle + end_angle)) * M_PI / 180);
1326 /* draw the grip at the center */
1327 o_grips_draw(w_current, x, y);
1329 /* draw the grip at the start_angle end of the arc */
1330 o_grips_draw(w_current, x1, y1);
1332 /* draw the grip at the end_angle end of the arc */
1333 o_grips_draw(w_current, x2, y2);
1337 /*! \brief Erase grip marks from arc.
1338 * \par Function Description
1339 * This function erases the three grips displayed on the <B>o_current</B>
1340 * arc object. These grips are on the center of the arc and on each end
1341 * of the arc.
1343 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1344 * \param [in] o_current Arc OBJECT to remove grip marks from.
1346 void o_arc_erase_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
1348 TOPLEVEL *toplevel = w_current->toplevel;
1349 int radius, x, y, start_angle, end_angle;
1350 int x1, y1, x2, y2;
1352 if (w_current->draw_grips == FALSE)
1353 return;
1356 * The coordinates of the three grips are determined by the parameters
1357 * of the arc. The grips are centered at (<B>x</B>,<B>y</B>), (<B>x1</B>,<B>y1</B>)
1358 * and (<B>x2</B>,<B>y2</B>).
1361 WORLDtoSCREEN( toplevel, o_current->arc->x, o_current->arc->y, &x, &y );
1362 radius = SCREENabs( toplevel, o_current->arc->width / 2 );
1363 start_angle = o_current->arc->start_angle;
1364 end_angle = o_current->arc->end_angle;
1366 x1 = x + radius * cos(((double) start_angle) * M_PI / 180);
1367 y1 = y - radius * sin(((double) start_angle) * M_PI / 180);
1368 x2 = x + radius * cos(((double) start_angle + end_angle) * M_PI / 180);
1369 y2 = y - radius * sin(((double) start_angle + end_angle) * M_PI / 180);
1371 /* erase the grip at the center */
1372 o_grips_erase(w_current, x, y);
1374 /* erase the grip at the start_angle end of the arc */
1375 o_grips_erase(w_current, x1, y1);
1377 /* erase the grip at the end_angle end of the arc */
1378 o_grips_erase(w_current, x2, y2);