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
24 #include <libgeda/libgeda.h>
26 #include "../include/globals.h"
27 #include "../include/prototype.h"
29 #ifdef HAVE_LIBDMALLOC
33 /* Kazu on July 16, 1999 - Added these macros to simplify the code */
34 #define GET_BOX_WIDTH(w) \
35 abs((w)->last_x - (w)->start_x)
36 #define GET_BOX_HEIGHT(w) \
37 abs((w)->last_y - (w)->start_y)
39 typedef void (*DRAW_FUNC
)( GdkDrawable
*w
, GdkGC
*gc
, GdkColor
*color
,
40 GdkCapStyle cap
, gint x
, gint y
, gint radius
,
41 gint angle1
, gint angle2
,
42 gint arc_width
, gint length
, gint space
);
44 typedef void (*FILL_FUNC
)( GdkDrawable
*w
, GdkGC
*gc
, GdkColor
*color
,
45 gint x
, gint y
, gint radius
,
46 gint fill_width
, gint angle1
, gint pitch1
,
47 gint angle2
, gint pitch2
);
49 /*! \brief Draw a circle on the screen.
50 * \par Function Description
51 * This function is used to draw a circle on screen. The circle is described
52 * by the OBJECT which is referred by <B>o_current</B>. The display is done
53 * according to the current state, given by the TOPLEVEL object pointed by
56 * It first checks if the OBJECT pointed is valid or not. If not it
57 * returns and do not output anything. That should never happen though.
59 * \param [in] w_current The TOPLEVEL object.
60 * \param [in] o_current Circle OBJECT to draw.
62 void o_circle_draw(TOPLEVEL
*w_current
, OBJECT
*o_current
)
64 int wleft
, wright
, wtop
, wbottom
; /* world bounds */
67 int circle_width
, length
, space
;
68 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
69 GdkCapStyle circle_end
;
71 DRAW_FUNC draw_func
= NULL
;
74 if (o_current
->circle
== NULL
) {
79 * Get read to check for visibility of this line by using it's
82 world_get_circle_bounds(w_current
, o_current
,
83 &wleft
, &wtop
, &wright
, &wbottom
);
85 if ( (w_current
->DONT_REDRAW
== 1) ||
86 (!visible(w_current
, wleft
, wtop
, wright
, wbottom
)) ) {
91 printf("drawing circle\n\n");
95 * The draw of the circle is divided in two steps : first step is to draw
96 * the outline, the second is to draw the filling pattern inside (if any).
98 * Finally the function takes care of the grips.
100 if (w_current
->override_color
!= -1 ) {
101 color
= x_get_color(w_current
->override_color
);
103 color
= x_get_color(o_current
->color
);
106 radius
= SCREENabs( w_current
, o_current
->circle
->radius
);
109 * The values describing the line type are extracted from the
110 * <B>o_current</B> pointed structure. These are the width of the line, the
111 * field called length and the field called space and the desired end type
114 * Depending on the type of the line that has to be used to draw the circle
115 * the appropriate function is called. Values of space and length are
116 * adapted to the type of line. The possible functions are the following :
117 * #o_arc_draw_solid(), #o_arc_draw_dotted(), #o_arc_draw_dashed() and
118 * #o_arc_draw_phantom(). Therefore it reuses the code from arc primitive.
120 * The combination <B>length</B> == 0 and <B>space</B> == 0 is avoided as it lead
121 * to an endless loop in function called after. If such a case is encountered
122 * the circle is drawn as a solid circle independently of its initial type.
124 circle_width
= SCREENabs( w_current
, o_current
->line_width
);
125 if(circle_width
<= 0) {
129 length
= SCREENabs( w_current
, o_current
->line_length
);
130 space
= SCREENabs( w_current
, o_current
->line_space
);
132 switch(o_current
->line_end
) {
133 case END_NONE
: circle_end
= GDK_CAP_BUTT
; break;
134 case END_SQUARE
: circle_end
= GDK_CAP_PROJECTING
; break;
135 case END_ROUND
: circle_end
= GDK_CAP_ROUND
; break;
136 default: fprintf(stderr
, _("Unknown end for circle\n"));
137 circle_end
= GDK_CAP_BUTT
;
141 switch(o_current
->line_type
) {
145 draw_func
= o_arc_draw_solid
;
149 length
= -1; /* ..._draw_dotted only space used */
150 draw_func
= o_arc_draw_dotted
;
154 draw_func
= o_arc_draw_dashed
;
158 draw_func
= o_arc_draw_center
;
162 draw_func
= o_arc_draw_phantom
;
171 circle_width
= 0; /* just to be careful */
172 fprintf(stderr
, _("Unknown type for circle!\n"));
173 draw_func
= o_arc_draw_solid
;
177 if((length
== 0) || (space
== 0))
178 draw_func
= o_arc_draw_solid
;
180 WORLDtoSCREEN( w_current
, o_current
->circle
->center_x
, o_current
->circle
->center_y
,
183 (*draw_func
)(w_current
->window
, w_current
->gc
, color
,
188 circle_width
, length
, space
);
189 (*draw_func
)(w_current
->backingstore
, w_current
->gc
, color
,
194 circle_width
, length
, space
);
197 * The values needed for the fill operation are taken from the
198 * <B>o_current</B> pointed OBJECT. It include the type of fill required, the
199 * width of the lines (if the fill use line) and angles and pitchs for hatch
202 * Once again the width of the line is important as if it is equal to 0 it
203 * may not be displayed. That is definetely not what we are looking for.
205 * Depending on the type of fill that has to be used inside the circle the
206 * right function is called. Values of <B>angle1</B>, <B>angle2</B>,
207 * <B>pitch1</B> and <B>pitch2</B> are adapted to the type of filling. The
208 * possible functions are the following : #o_circle_fill_hollow(),
209 * #o_circle_fill_fill(), #o_circle_fill_mesh() and #o_circle_fill_hatch().
211 * The combination <B>pitch1</B> <= 0 and <B>pitch2</B> <= 0 is avoided as it
212 * lead to an endless loop in function called after. It happens when the
213 * zoom factor is too small for two lines separated by the pitch to be
214 * distinct. If such a case is encountered the circle is filled hollow
217 fill_width
= SCREENabs( w_current
, o_current
->fill_width
);
218 if( fill_width
<= 0) {
222 angle1
= o_current
->fill_angle1
;
223 pitch1
= SCREENabs( w_current
, o_current
->fill_pitch1
);
224 angle2
= o_current
->fill_angle2
;
225 pitch2
= SCREENabs( w_current
, o_current
->fill_pitch2
);
227 switch(o_current
->fill_type
) {
229 angle1
= -1; angle2
= -1;
230 pitch1
= 1; pitch2
= 1;
232 * this function is empty ! however if it do not use it we have to add
233 * a test before the call. Simply putting a return here instead is not
234 * possible as it would prevent any hollow circle from having its grips
236 fill_func
= o_circle_fill_hollow
;
240 angle1
= -1; angle2
= -1;
241 pitch1
= 1; pitch2
= 1;
242 fill_func
= o_circle_fill_fill
;
246 fill_func
= o_circle_fill_mesh
;
252 fill_func
= o_circle_fill_hatch
;
257 angle1
= -1; angle2
= -1;
258 pitch1
= 1; pitch2
= 1;
259 fill_func
= o_circle_fill_hollow
;
260 fprintf(stderr
, _("Unknown type for circle (fill)!\n"));
263 if((pitch1
<= 0) || (pitch2
<= 0)) {
264 fill_func
= o_circle_fill_fill
;
267 (*fill_func
)(w_current
->window
, w_current
->gc
, color
,
270 fill_width
, angle1
, pitch1
, angle2
, pitch2
);
271 (*fill_func
)(w_current
->backingstore
, w_current
->gc
, color
,
274 fill_width
, angle1
, pitch1
, angle2
, pitch2
);
277 printf("drawing circle\n");
280 if (o_current
->draw_grips
&& w_current
->draw_grips
== TRUE
) {
282 /* pb20011010 - modified to use the new o_circle_[draw|erase]_grips() */
283 if (!o_current
->selected
) {
284 /* object is no more selected, erase the grips */
285 o_current
->draw_grips
= FALSE
;
286 o_circle_erase_grips(w_current
, o_current
);
288 /* object is selected, draw the grips */
289 o_circle_draw_grips(w_current
, o_current
);
294 /*! \brief Placeholder filling function.
295 * \par Function Description
296 * This function does nothing. It has the same prototype as all the filling
297 * functions. It prevent from making a difference between filling in function
300 * The unit for <B>width</B>, <B>pitch1</B> and <B>pitch2</B> is pixel and unit
301 * for <B>angle1</B> and <B>angle2</B> is degree.
303 * \param [in] w GdkDrawable to draw in.
304 * \param [in] gc GdkGC graphics context to draw on.
305 * \param [in] color Circle fill color.
306 * \param [in] x Center x coordinate of Circle.
307 * \param [in] y Center y coordinate of Circle.
308 * \param [in] radius Radius of Circle.
309 * \param [in] width Circle pattern fill width.
310 * \param [in] angle1 1st angle for pattern.
311 * \param [in] pitch1 1st pitch for pattern.
312 * \param [in] angle2 2nd angle for pattern.
313 * \param [in] pitch2 2nd pitch for pattern.
315 void o_circle_fill_hollow(GdkDrawable
*w
, GdkGC
*gc
, GdkColor
*color
,
316 gint x
, gint y
, gint radius
,
318 gint angle1
, gint pitch1
, gint angle2
, gint pitch2
)
323 /*! \brief Fill inside of circle with a solid pattern.
324 * \par Function Description
325 * This function fills the inside of the circle with a solid pattern.
326 * Parameters <B>angle1</B>, <B>pitch1</B> and <B>angle2</B>, <B>pitch2</B>
327 * and <B>width</B> are unused here but kept for compatibility with other
328 * circle filling functions.
330 * The circle is described by the coordinates of its center and its radius.
331 * Please not that it is not the way GDK take it. Translation is made
334 * The unit for <B>width</B>, <B>pitch1</B> and <B>pitch2</B> is pixel and unit
335 * for <B>angle1</B> and <B>angle2</B> is degree.
337 * The solid fill is done with the #gdk_draw_arc() function and its
338 * parameters <B>filled</B> set. The circle is filled with the color
339 * <B>color</B> given as a parameter to the function.
341 * \param [in] w GdkDrawable to draw in.
342 * \param [in] gc GdkGC graphics context to draw on.
343 * \param [in] color Circle fill color.
344 * \param [in] x Center x coordinate of Circle.
345 * \param [in] y Center y coordinate of Circle.
346 * \param [in] radius Radius of Circle.
347 * \param [in] width (unused)
348 * \param [in] angle1 (unused)
349 * \param [in] pitch1 (unused)
350 * \param [in] angle2 (unused)
351 * \param [in] pitch2 (unused)
353 void o_circle_fill_fill(GdkDrawable
*w
, GdkGC
*gc
, GdkColor
*color
,
354 gint x
, gint y
, gint radius
,
356 gint angle1
, gint pitch1
, gint angle2
, gint pitch2
)
358 gdk_gc_set_foreground(gc
, color
);
359 gdk_gc_set_line_attributes(gc
, 1, GDK_LINE_SOLID
,
360 GDK_CAP_BUTT
, GDK_JOIN_MITER
);
363 TRUE
, x
-radius
, y
-radius
, 2*radius
, 2*radius
, 0, FULL_CIRCLE
);
367 /*! \brief Fill inside of circle with single line pattern.
368 * \par Function Description
369 * This function fills the inside of the circle with a pattern made of lines.
370 * The lines are drawn inside the circle with an angle <B>angle1</B> from the
371 * horizontal. The distance between two of these lines is given by
372 * <B>pitch1</B> and their width by <B>width</B>.
373 * Parameters <B>angle2</B>, <B>pitch2</B> are unused here but kept for
374 * compatibility with other circle filling functions.
376 * The circle is described by the coordinates of its center and its radius.
377 * Please not that it is not the way GDK take it. Translation is made
380 * The unit for <B>width</B>, <B>pitch1</B> and <B>pitch2</B> is pixel and unit
381 * for <B>angle1</B> and <B>angle2</B> is degree.
383 * The only attribute of line here is its width from the parameter <B>width</B>.
385 * Negative or null values for <B>pitch1</B> are not allowed as it leads to
388 * \param [in] w GdkDrawable to draw in.
389 * \param [in] gc GdkGC graphics context to draw on.
390 * \param [in] color Circle fill color.
391 * \param [in] x Center x coordinate of Circle.
392 * \param [in] y Center y coordinate of Circle.
393 * \param [in] radius Radius of Circle.
394 * \param [in] width Circle pattern fill width.
395 * \param [in] angle1 1st angle for pattern.
396 * \param [in] pitch1 1st pitch for pattern.
397 * \param [in] angle2 (unused)
398 * \param [in] pitch2 (unused)
400 void o_circle_fill_hatch(GdkDrawable
*w
, GdkGC
*gc
, GdkColor
*color
,
401 gint x
, gint y
, gint radius
,
403 gint angle1
, gint pitch1
, gint angle2
, gint pitch2
)
405 double x0
, y0
, x1
, y1
, x2
, y2
;
406 double cos_a_
, sin_a_
;
408 gdk_gc_set_line_attributes(gc
, width
, GDK_LINE_SOLID
,
409 GDK_CAP_BUTT
, GDK_JOIN_MITER
);
412 * The function use a matrix. Its elements are obtained from the sinus and
413 * cosinus of the angle <B>angle1</B>. It represent the rotation matrix that
414 * when applied to a point, rotate it of <B>angle1</B>.
416 cos_a_
= cos(((double) angle1
) * M_PI
/180);
417 sin_a_
= sin(((double) angle1
) * M_PI
/180);
420 * When drawing a line in a circle there is two intersections. It looks for
421 * the coordinates of one of these points when the line is horizontal.
422 * The second one can be easily obtained by symmetry in relation to the
423 * vertical axis going through the centre of the circle.
425 * These two points are then rotated of angle <B>angle1</B> using the
426 * elements of the rotation matrix previously computed.
428 * The corresponding line can be drawn providing that the coordinates
431 * These operations are repeated for every horizontal line that can fit
432 * in the upper half of the circle (using and incrementing the variable
436 while(y0
< (double) radius
) {
437 x0
= pow((double) radius
, 2) - pow(y0
, 2);
440 x1
= (x0
*cos_a_
- y0
*sin_a_
) + x
;
441 y1
= y
- (x0
*sin_a_
+ y0
*cos_a_
);
442 x2
= ((-x0
)*cos_a_
- y0
*sin_a_
) + x
;
443 y2
= y
- ((-x0
)*sin_a_
+ y0
*cos_a_
);
446 (int) x1
, (int) y1
, (int) x2
, (int) y2
);
449 * The function use the symetry in relation to the centre of the circle.
450 * It avoid repetitive computation for the second half of the surface
453 x1
= (x0
*cos_a_
- (-y0
)*sin_a_
) + x
;
454 y1
= y
- (x0
*sin_a_
+ (-y0
)*cos_a_
);
455 x2
= ((-x0
)*cos_a_
- (-y0
)*sin_a_
) + x
;
456 y2
= y
- ((-x0
)*sin_a_
+ (-y0
)*cos_a_
);
458 gdk_draw_line(w
, gc
, (int) x1
, (int) y1
, (int) x2
, (int) y2
);
464 /*! \brief Fill inside of circle with mesh pattern.
465 * \par Function Description
466 * This function fills the inside of the circle with a pattern made of set
467 * of parallel lines in two directions. The first set is drawn inside the
468 * circle with an angle <B>angle1</B> from the horizontal. The distance between
469 * two of these lines is given by <B>pitch1</B>.
470 * The second set is drawn inside the circle with an angle <B>angle2</B> from
471 * the horizontal. The distance between two of these lines is given by
473 * Every lines have the same width given by <B>width</B>.
475 * The unit for <B>width</B>, <B>pitch1</B> and <B>pitch2</B> is pixel and unit
476 * for <B>angle1</B> and <B>angle2</B> is degree.
478 * This function simply makes two successive calls to the function
479 * #o_circle_fill_hatch() respectively with <B>angle1</B>, <B>pitch1</B> and
480 * <B>angle2</B>, <B>pitch2</B> for parameters.
482 * \param [in] w GdkDrawable to draw in.
483 * \param [in] gc GdkGC graphics context to draw on.
484 * \param [in] color Circle fill color.
485 * \param [in] x Center x coordinate of Circle.
486 * \param [in] y Center y coordinate of Circle.
487 * \param [in] radius Radius of Circle.
488 * \param [in] width Circle pattern fill width.
489 * \param [in] angle1 1st angle for pattern.
490 * \param [in] pitch1 1st pitch for pattern.
491 * \param [in] angle2 2nd angle for pattern.
492 * \param [in] pitch2 2nd pitch for pattern.
494 void o_circle_fill_mesh(GdkDrawable
*w
, GdkGC
*gc
, GdkColor
*color
,
495 gint x
, gint y
, gint radius
,
497 gint angle1
, gint pitch1
, gint angle2
, gint pitch2
)
499 o_circle_fill_hatch(w
, gc
, color
,
501 width
, angle1
, pitch1
, -1, -1);
502 o_circle_fill_hatch(w
, gc
, color
,
504 width
, angle2
, pitch2
, -1, -1);
508 /*! \brief Erase a circle described by OBJECT
509 * \par Function Description
510 * This function erases a circle described in a #OBJECT structure
511 * pointed by <B>o_current</B>.
513 * It makes a call to the function #o_circle_draw() after setting the
514 * special color. Therefore a circle is drawn with background color over
517 * \param [in] w_current The TOPLEVEL object.
518 * \param [in] o_current Circle OBJECT to erase.
520 void o_circle_erase(TOPLEVEL
*w_current
, OBJECT
*o_current
)
522 w_current
->override_color
= w_current
->background_color
;
523 o_circle_draw(w_current
, o_current
);
524 w_current
->override_color
= -1;
527 /*! \todo Finish function documentation!!!
529 * \par Function Description
532 void o_circle_eraserubber(TOPLEVEL
*w_current
)
534 o_circle_rubbercircle_xor(w_current
);
537 /*! \brief Draw a circle described by OBJECT with translation
538 * \par Function Description
539 * This function draws the circle object described by <B>*o_current</B>
540 * translated by the vector (<B>dx</B>,<B>dy</B>) with an xor-function over
542 * The translation vector is in screen unit.
544 * The circle is displayed with the color of the object.
546 * \param [in] w_current The TOPLEVEL object.
547 * \param [in] dx Delta x coordinate for circle.
548 * \param [in] dy Delta y coordinate for circle.
549 * \param [in] o_current Circle OBJECT to draw.
552 * add in offsets, get rid of global diffs_x,y
554 void o_circle_draw_xor(TOPLEVEL
*w_current
, int dx
, int dy
, OBJECT
*o_current
)
559 if (o_current
->circle
== NULL
) {
563 if (o_current
->saved_color
!= -1) {
564 color
= o_current
->saved_color
;
566 color
= o_current
->color
;
569 /* radius of the circle */
570 radius
= SCREENabs( w_current
, o_current
->circle
->radius
);
571 /* upper left corner of the square the circle is inscribed in */
572 /* gdk coords system */
573 WORLDtoSCREEN( w_current
,
574 o_current
->circle
->center_x
- o_current
->circle
->radius
,
575 o_current
->circle
->center_y
+ o_current
->circle
->radius
,
578 /* translate the upper left corner */
582 /* To draw be sure to setup width height */
583 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
584 x_get_darkcolor(color
));
585 gdk_draw_arc(w_current
->window
, w_current
->outline_xor_gc
,
588 2 * radius
, 2 * radius
,
591 /* backing store ? not appropriate here */
594 /*! \brief Start process to input a new circle.
595 * \par Function Description
596 * This function starts the process to input a new circle. Parameters for
597 * this circle are pu into/extracted from the <B>w_current</B> toplevel
599 * <B>x</B> and <B>y</B> are current coordinates of the mouse pointer in
602 * The first step of the circle input is to set the center of the arc.
603 * This center is kept in (<B>w_current->start_x</B>,<B>w_current->start_y</B>).
605 * \param [in] w_current The TOPLEVEL object.
606 * \param [in] x Current x coordinate of pointer in screen units.
607 * \param [in] y Current y coordinate of pointer in screen units.
609 void o_circle_start(TOPLEVEL
*w_current
, int x
, int y
)
611 /* center of circle */
612 w_current
->last_x
= w_current
->start_x
= fix_x(w_current
, x
);
613 w_current
->last_y
= w_current
->start_y
= fix_y(w_current
, y
);
615 w_current
->distance
= 0;
617 /* first temporary circle */
618 o_circle_rubbercircle_xor(w_current
);
622 /*! \brief End the input of a circle.
623 * \par Function Description
624 * This function ends the input of the radius of the circle.
625 * The (<B>x</B>,<B>y</B>) point is taken as the other end of the radius
626 * segment, i.e. on the circle. The distance between this point and the
627 * center is the radius of the circle.
628 * <B>x</B> and <B>y</B> are in screen coords.
630 * The center has previously been input and saved as
631 * (<B>w_current->start_x</B>,<B>w_current->start_y</B>).
633 * The temporary circle drawn during the input of the radius is erased.
634 * A new object is allocated, initialized and linked in the object list.
635 * This new object is finally drawn.
637 * \param [in] w_current The TOPLEVEL object.
638 * \param [in] x Current x coordinate of pointer in screen units.
639 * \param [in] y Current y coordinate of pointer in screen units.
641 void o_circle_end(TOPLEVEL
*w_current
, int x
, int y
)
643 int center_x
, center_y
;
647 if (w_current
->inside_action
== 0) {
648 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
652 /* erase the temporary circle */
653 o_circle_rubbercircle_xor(w_current
);
655 /* get the last coords of the pointer */
656 fx
= fix_x(w_current
, x
);
657 fy
= fix_y(w_current
, y
);
658 /* compute the radius in screen unit */
659 w_current
->distance
= dist(w_current
->start_x
, w_current
->start_y
,
662 /* circle with null radius are not allowed */
663 if (w_current
->distance
== 0) {
664 /* cancel the object creation */
665 w_current
->start_x
= -1;
666 w_current
->start_y
= -1;
667 w_current
->last_x
= -1;
668 w_current
->last_y
= -1;
669 w_current
->distance
= -1;
673 /* get center coords in world unit */
674 SCREENtoWORLD(w_current
,
675 w_current
->start_x
, w_current
->start_y
,
676 ¢er_x
, ¢er_y
);
677 /* get radius in world unit */
678 radius
= snap_grid(w_current
,
679 WORLDabs(w_current
, w_current
->distance
));
681 /* create the object */
682 w_current
->page_current
->object_tail
=
683 o_circle_add(w_current
,
684 w_current
->page_current
->object_tail
,
685 OBJ_CIRCLE
, w_current
->graphic_color
,
686 center_x
, center_y
, radius
);
689 o_redraw_single(w_current
, w_current
->page_current
->object_tail
);
691 w_current
->start_x
= (-1);
692 w_current
->start_y
= (-1);
693 w_current
->last_x
= (-1);
694 w_current
->last_y
= (-1);
695 w_current
->loc_x
= (-1);
696 w_current
->loc_y
= (-1);
697 w_current
->distance
= (-1);
699 w_current
->page_current
->CHANGED
= 1;
701 o_undo_savestate(w_current
, UNDO_ALL
);
704 /*! \brief Draw temporary circle while dragging edge.
705 * \par Function Description
706 * This function draws a circle according to its internal representation and
707 * allows the modification of its radius. The radius is updated according to
708 * the current mouse position in <B>x</B> and <B>y</B>.
709 * It draws a full circle and the horizontal segment of the radius in the
710 * right half of the circle.
712 * The previous temporary circle is erased, the radius is then computed and
713 * updated and finally a new temporary circle is drawn.
715 * The arc is internally described by :
717 * <DT>*</DT><DD>(<B>w_current->start_x</B>,<B>w_current->start_y</B>) as its
719 * <DT>*</DT><DD><B>w_current->distance</B> as its radius.
722 * \param [in] w_current The TOPLEVEL object.
723 * \param [in] x Current x coordinate of pointer in screen units.
724 * \param [in] y Current y coordinate of pointer in screen units.
726 void o_circle_rubbercircle(TOPLEVEL
*w_current
, int x
, int y
)
730 if (w_current
->inside_action
== 0) {
731 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
735 /* erase the previous temporary circle */
736 o_circle_rubbercircle_xor(w_current
);
739 * The radius is taken as the biggest distance on the x and y axis between
740 * the center of the circle and the mouse position.
742 /* update the radius */
743 w_current
->last_x
= fix_x(w_current
, x
);
744 w_current
->last_y
= fix_y(w_current
, y
);
746 diff_x
= GET_BOX_WIDTH (w_current
);
747 diff_y
= GET_BOX_HEIGHT(w_current
);
748 if (diff_x
>= diff_y
) {
749 w_current
->last_y
= w_current
->start_y
;
750 w_current
->distance
= diff_x
;
752 w_current
->last_x
= w_current
->start_x
;
753 w_current
->distance
= diff_y
;
756 /* draw the new temporary circle */
757 o_circle_rubbercircle_xor(w_current
);
761 /*! \brief Draw circle from TOPLEVEL object.
762 * \par Function Description
763 * This function draws the circle from the variables in the toplevel
764 * structure <B>*w_current</B>.
765 * The center of the circle is at (<B>w_current->start_x</B>,
766 * <B>w_current->start_y</B>) and its radius is in <B>w_current->distance</B>.
768 * It draws a horizontal radius segment on the right half of the circle and
769 * the circle with the selection color and an xor-function over the current
772 * \param [in] w_current The TOPLEVEL object.
774 void o_circle_rubbercircle_xor(TOPLEVEL
*w_current
)
776 /* draw the circle from the w_current variables */
777 gdk_gc_set_foreground(w_current
->xor_gc
,
778 x_get_darkcolor(w_current
->select_color
));
779 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
780 w_current
->start_x
, w_current
->start_y
,
781 w_current
->start_x
+ w_current
->distance
,
783 gdk_draw_arc(w_current
->window
, w_current
->xor_gc
, FALSE
,
784 w_current
->start_x
- w_current
->distance
,
785 w_current
->start_y
- w_current
->distance
,
786 w_current
->distance
* 2,
787 w_current
->distance
* 2,
791 /*! \brief Draw grip marks on circle.
792 * \par Function Description
793 * This function draws the grip that match the circle object <B>*o_current</B>.
795 * \param [in] w_current The TOPLEVEL object.
796 * \param [in] o_current Circle OBJECT to draw grip points on.
798 void o_circle_draw_grips(TOPLEVEL
*w_current
, OBJECT
*o_current
)
802 if (w_current
->draw_grips
== FALSE
)
805 /* coords of the lower right corner of the square */
806 WORLDtoSCREEN( w_current
,
807 o_current
->circle
->center_x
+ o_current
->circle
->radius
,
808 o_current
->circle
->center_y
- o_current
->circle
->radius
,
811 /* grip on lower right corner of the square */
812 o_grips_draw(w_current
, x
, y
);
816 /*! \brief Erase grip marks from circle.
817 * \par Function Description
818 * The function erases the grips displayed on a circle object.
820 * A circle has a single grip on the lower right corner of the square it
823 * \param [in] w_current The TOPLEVEL object.
824 * \param [in] o_current Circle OBJECT to erase grip marks from.
826 void o_circle_erase_grips(TOPLEVEL
*w_current
, OBJECT
*o_current
)
830 if (w_current
->draw_grips
== FALSE
)
833 /* coords of the lower right corner of square */
834 WORLDtoSCREEN( w_current
,
835 o_current
->circle
->center_x
+ o_current
->circle
->radius
,
836 o_current
->circle
->center_y
- o_current
->circle
->radius
,
839 /* grip on lower right corner of the square */
840 o_grips_erase(w_current
, x
, y
);