1 /* ellipse.c */
2 /* COPYRIGHT (C) 2000 THE VICTORIA UNIVERSITY OF MANCHESTER and John Levon
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the Free
5 * Software Foundation; either version 2 of the License, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307, USA.
16 */
17 /* contains functions assoc. with ellipse and circle composition */
18 /*
19 * $Log: ellipse.c,v $
20 * Revision 1.2 2000/12/06 20:56:01 moz
21 * GPL stuff.
22 *
23 * Revision 1.1.1.1 2000/08/21 01:05:30 moz
24 *
25 *
26 * Revision 1.1.1.1 2000/07/19 22:45:30 moz
27 * CVS Import
28 *
29 * Revision 1.5 2000/03/08 00:43:42 moz
30 * Compile fixes.
31 *
32 * Revision 1.4 1999/11/15 02:11:10 moz
33 * Name change.
34 *
35 * Revision 1.3 1999/05/19 17:10:54 moz
36 * 1.0 Checkin.
37 *
38 * Revision 1.2 1999/04/29 00:13:11 moz
39 * In draw_ellipse, make sure it is this object we are scaling (test gc==blackxorgc).
40 *
41 * Revision 1.1 1999/03/30 00:04:48 moz
42 * Initial revision
43 *
44 */
45
46 /* see mouse_button.c for general behaviour */
47
48 #include "include/figurine.h"
49 #include "include/extern.h"
50
51 static long x1=0; /* for boxellipse */
52 static long y1=0;
53 static long cx=0;
54 static long cy=0;
55 static long xr=0;
56 static long yr=0;
57
58 static Boolean held=FALSE;
59
60 void
commit_ellipse(View * view,long x,long y)61 commit_ellipse(View *view, long x, long y)
62 {
63 Object *ob;
64
65 if (state.current_icon==BOXELLIPSEICON)
66 {
67 if (view->gridon)
68 {
69 cx = (GXP2D(x,view) - x1)/2 + x1;
70 cy = (GYP2D(y,view) - y1)/2 + y1;
71 xr = abs(GXP2D(x,view) - x1)/2;
72 yr = abs(GYP2D(y,view) - y1)/2;
73 }
74 else
75 {
76 cx = (XP2D(x,view) - x1)/2 + x1;
77 cy = (YP2D(y,view) - y1)/2 + y1;
78 xr = abs(XP2D(x,view) - x1)/2;
79 yr = abs(YP2D(y,view) - y1)/2;
80 };
81 }
82 else
83 {
84 if (view->gridon)
85 {
86 xr = abs(GXP2D(x, view) - cx);
87 yr = abs(GYP2D(y, view) - cy);
88 }
89 else
90 {
91 xr = abs(XP2D(x, view) - cx);
92 yr = abs(YP2D(y, view) - cy);
93 };
94 };
95
96 /* constrain */
97 if (state.control_down)
98 constrain_ellipse(&xr,&yr);
99
100 ob = (Object *)malloc(sizeof(Object));
101 if (ob==NULL)
102 return;
103
104 ob->type = ELLIPSE;
105 ob->ticket = ob_ticket++;
106 ob->derries = NULL;
107 ob->depth = view->doc->ob_depth--;
108 ob->ls = view->linestyle;
109 ob->lw = view->linewidth;
110 ob->colour = view->colour;
111 ob->fillcolour = view->fillcolour;
112 if (view->fillon)
113 ob->fs = view->fillstyle;
114 else
115 ob->fs = NONE;
116
117 ob->dash = 5;
118 ob->gap = 4;
119 ob->bbox.x1 = cx - xr;
120 ob->bbox.y1 = cy - yr;
121 ob->bbox.x2 = cx + xr;
122 ob->bbox.y2 = cy + yr;
123 ob->ob.ellipse.centre.x = cx - ob->bbox.x1;
124 ob->ob.ellipse.centre.y = cy - ob->bbox.y1;
125 ob->ob.ellipse.xradius = xr;
126 ob->ob.ellipse.yradius = yr;
127 ob->farrow = NULL;
128 ob->barrow = NULL;
129
130 normalise_rectangle(&ob->bbox.x1, &ob->bbox.y1, &ob->bbox.x2, &ob->bbox.y2);
131 ob->bbox.x2 = cx + xr +1;
132 ob->bbox.y2 = cy + yr +1;
133
134 view->doc->o = add_object(view->doc->o, &view->doc->lo, ob);
135
136 register_undo(UNDO_PASTE,ob,view->doc);
137 send_redraw_object(view,ob);
138 }
139
140 void
ellipse_button(BEvent * bev,View * view)141 ellipse_button(BEvent *bev, View *view)
142 {
143
144 if (((held && bev->button==Button2) || bev->button==Button3) && state.busy_drawing )
145 {
146 /* cancel the current ellipse */
147 if (!held)
148 XUngrabPointer(display,CurrentTime);
149
150 toggle_ellipse(view, bev->x, bev->y);
151
152 state.busy_drawing = FALSE;
153 held = FALSE;
154 }
155 else if (bev->button==Button1)
156 {
157 if (!P_IN_DOC(bev->x, bev->y, view) && state.busy_drawing)
158 {
159 /* ok, cancel the ellipse we're drawing */
160 state.busy_drawing = FALSE;
161
162 if (!held)
163 XUngrabPointer(display,CurrentTime);
164 else
165 held = FALSE;
166
167 toggle_ellipse(view, bev->x, bev->y);
168 }
169 else
170 {
171 switch (bev->type)
172 {
173 case BUTTON_HELD:
174
175 if (!state.busy_drawing)
176 {
177 /* start drawing */
178 state.busy_drawing = TRUE;
179 held = TRUE;
180 if (state.current_icon==BOXELLIPSEICON)
181 {
182 if (view->gridon)
183 {
184 x1 = GXP2D(bev->x,view);
185 y1 = GYP2D(bev->y,view);
186 }
187 else
188 {
189 x1 = XP2D(bev->x,view);
190 y1 = YP2D(bev->y,view);
191 };
192 };
193
194 if (view->gridon)
195 {
196 cx = GXP2D(bev->x,view);
197 cy = GYP2D(bev->y,view);
198 }
199 else
200 {
201 cx = XP2D(bev->x,view);
202 cy = YP2D(bev->y,view);
203 };
204
205 xr = 1;
206 yr = 1;
207
208 toggle_ellipse(view, bev->x, bev->y);
209 };
210
211 break; /* BUTTON_HELD */
212
213 case BUTTON_CLICKED:
214
215 if (held)
216 {
217 XGrabPointer(display, view->draw_window->win, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ButtonMotionMask
218 | Button1MotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
219 }
220 else
221 {
222 XUngrabPointer(display,CurrentTime);
223 toggle_ellipse(view, bev->x, bev->y);
224
225 commit_ellipse(view, bev->x, bev->y);
226
227 state.busy_drawing=FALSE;
228 };
229
230 held = FALSE;
231 break;
232
233
234 case BUTTON_RELEASED:
235
236 toggle_ellipse(view, bev->x, bev->y);
237
238 commit_ellipse(view, bev->x, bev->y);
239 held = FALSE;
240 state.busy_drawing=FALSE;
241
242 break;
243 };
244 };
245 };
246 }
247
248 void
toggle_ellipse(View * view,int x,int y)249 toggle_ellipse(View *view, int x, int y)
250 {
251 if (state.current_icon==BOXELLIPSEICON)
252 {
253 if (view->gridon)
254 {
255 cx = (GXP2D(x,view) - x1)/2 + x1;
256 cy = (GYP2D(y,view) - y1)/2 + y1;
257 xr = abs(GXP2D(x,view) - x1)/2;
258 yr = abs(GYP2D(y,view) - y1)/2;
259 }
260 else
261 {
262 cx = (XP2D(x,view) - x1)/2 + x1;
263 cy = (YP2D(y,view) - y1)/2 + y1;
264 xr = abs(XP2D(x,view) - x1)/2;
265 yr = abs(YP2D(y,view) - y1)/2;
266 };
267 }
268 else
269 {
270 if (view->gridon)
271 {
272 xr = abs(GXP2D(x, view) - cx);
273 yr = abs(GYP2D(y, view) - cy);
274 }
275 else
276 {
277 xr = abs(XP2D(x, view) - cx);
278 yr = abs(YP2D(y, view) - cy);
279 };
280 };
281
282 /* constrain */
283 if (state.control_down)
284 constrain_ellipse(&xr,&yr);
285
286 XDrawArc(display, view->draw_window->win, blackxorgc, XD2P(cx-xr,view), YD2P(cy-yr,view),
287 (uint)D2P(2*xr,view), (uint)D2P(2*yr,view), 0, 360*64);
288 }
289
290 void
draw_ellipse(Object * ob,View * view,GC gc,long x,long y,double rx,double ry)291 draw_ellipse(Object *ob, View *view, GC gc, long x,long y, double rx, double ry)
292 {
293 GC tgc;
294 int r;
295
296 if (gc==NULL)
297 tgc = ugc;
298 else
299 tgc = gc;
300
301 if (gc==blackxorgc && state.tied_corner != NOTSCALING)
302 {
303 corner_magic(ob, &x, &y, rx, ry);
304 r = ellipse_box(XD2P(x+ob->ob.ellipse.centre.x,view),YD2P(y+ob->ob.ellipse.centre.y,view),
305 D2P(ob->ob.ellipse.xradius,view), D2P(ob->ob.ellipse.yradius,view),
306 0, 0, (long)view->window.w, (long)view->window.h);
307
308 if (r!=NO_INTERSECT && r!=CONTAINS)
309 {
310 XDrawArc(display, view->draw_window->win, tgc,
311 XD2P(x,view), YD2P(y,view),
312 (uint)D2P(abs(R(2*ob->ob.ellipse.xradius,rx)),view),
313 (uint)D2P(abs(R(2*ob->ob.ellipse.yradius,ry)),view),
314 0, 360*64);
315 };
316 }
317 else
318 {
319 r = ellipse_box(XD2P(x+ob->ob.ellipse.centre.x,view),YD2P(y+ob->ob.ellipse.centre.y,view),
320 D2P(ob->ob.ellipse.xradius,view), D2P(ob->ob.ellipse.yradius,view),
321 0, 0, (long)view->draw_window->w, (long)view->draw_window->h);
322
323 if (r==CONTAINED && ob->fs!=NONE && gc!=blackxorgc)
324 {
325 XFillArc(display, view->draw_window->win, fillgc,
326 XD2P(x,view), YD2P(y,view),
327 (uint)D2P(2*ob->ob.ellipse.xradius,view),
328 (uint)D2P(2*ob->ob.ellipse.yradius,view),
329 0, 360*64);
330 };
331
332 if (r==CONTAINS && ob->fs!=NONE && gc!=blackxorgc)
333 XFillRectangle(display,view->draw_window->win,fillgc,0,0,view->draw_window->w, view->draw_window->h);
334
335 if (r!=NO_INTERSECT && r!=CONTAINS && (gc==blackxorgc || ob->lw!=0))
336 {
337 XDrawArc(display, view->draw_window->win, tgc,
338 XD2P(x,view), YD2P(y,view),
339 (uint)D2P(2*ob->ob.ellipse.xradius,view),
340 (uint)D2P(2*ob->ob.ellipse.yradius,view),
341 0, 360*64);
342 };
343 };
344
345 }
346