1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1985-1988 by Supoj Sutanthavibul
4 * Parts Copyright (c) 1989-2007 by Brian V. Smith
5 * Parts Copyright (c) 1991 by Paul King
6 *
7 * Any party obtaining a copy of these files is granted, free of charge, a
8 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
9 * nonexclusive right and license to deal in this software and documentation
10 * files (the "Software"), including without limitation the rights to use,
11 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
12 * the Software, and to permit persons who receive copies from any such
13 * party to do so, with the only requirement being that the above copyright
14 * and this permission notice remain intact.
15 *
16 */
17
18 #include "fig.h"
19 #include "resources.h"
20 #include "mode.h"
21 #include "object.h"
22 #include "paintop.h"
23 #include "u_elastic.h"
24 #include "u_geom.h"
25 #include "w_canvas.h"
26 #include "w_drawprim.h"
27 #include "w_setup.h"
28 #include "w_zoom.h"
29 #include "d_arc.h"
30
31 #include "u_draw.h"
32 #include "w_cursor.h"
33 #include "w_msgpanel.h"
34
35 /********************** EXPORTS **************/
36
37 int constrained;
38 int work_numsides;
39 float cur_angle;
40 int x1off, x2off, y1off, y2off;
41 Cursor cur_latexcursor;
42 int from_x, from_y;
43 double cosa, sina;
44 intptr_t movedpoint_num;
45 F_point *left_point, *right_point;
46
47 /**************** LOCAL ***********/
48
49 static void elastic_links(int dx, int dy, float sx, float sy);
50 static void angle0_line(int x, int y);
51 static void angle45_line(int x, int y);
52 static void angle90_line(int x, int y);
53 static void angle135_line(int x, int y);
54
55 /*************************** BOXES *************************/
56
57
58
59 void
elastic_box(int x1,int y1,int x2,int y2)60 elastic_box(int x1, int y1, int x2, int y2)
61 {
62 int wid, ht;
63
64 set_line_stuff(1, RUBBER_LINE, 0.0, JOIN_MITER, CAP_BUTT,
65 INV_PAINT, DEFAULT);
66 wid = abs(x2-x1)+1;
67 ht = abs(y2-y1)+1;
68 zXDrawRectangle(tool_d, canvas_win, gccache[INV_PAINT],min2(x1,x2),min2(y1,y2),wid,ht);
69 }
70
71 void
elastic_fixedbox(void)72 elastic_fixedbox(void)
73 {
74 elastic_box(fix_x, fix_y, cur_x, cur_y);
75 }
76
77 void
elastic_movebox(void)78 elastic_movebox(void)
79 {
80 register int x1, y1, x2, y2;
81
82 x1 = cur_x + x1off;
83 x2 = cur_x + x2off;
84 y1 = cur_y + y1off;
85 y2 = cur_y + y2off;
86 elastic_box(x1, y1, x2, y2);
87 elastic_links(cur_x - fix_x, cur_y - fix_y, 1.0, 1.0);
88 }
89
90 void
moving_box(int x,int y)91 moving_box(int x, int y)
92 {
93 elastic_movebox();
94 adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
95 length_msg(MSG_DIST);
96 elastic_movebox();
97 }
98
99 void
resizing_box(int x,int y)100 resizing_box(int x, int y)
101 {
102 elastic_fixedbox();
103 cur_x = x;
104 cur_y = y;
105 boxsize_msg(1);
106 elastic_fixedbox();
107 }
108
109 void
constrained_resizing_box(int x,int y)110 constrained_resizing_box(int x, int y)
111 {
112 elastic_fixedbox();
113 adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
114 boxsize_msg(1);
115 elastic_fixedbox();
116 }
117
118 void
constrained_resizing_scale_box(int x,int y)119 constrained_resizing_scale_box(int x, int y)
120 {
121 elastic_fixedbox();
122 adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
123 elastic_fixedbox();
124 boxsize_scale_msg(1);
125 }
126
127 void
scaling_compound(int x,int y)128 scaling_compound(int x, int y)
129 {
130 elastic_scalecompound(cur_c);
131 adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
132 elastic_scalecompound(cur_c);
133 }
134
135 void
elastic_scale_curcompound(void)136 elastic_scale_curcompound(void)
137 {
138 elastic_scalecompound(cur_c);
139 }
140
141 void
elastic_scalecompound(F_compound * c)142 elastic_scalecompound(F_compound *c)
143 {
144 double newx, newy, oldx, oldy;
145 double newd, oldd, scalefact;
146 int x1, y1, x2, y2;
147
148 newx = cur_x - fix_x;
149 newy = cur_y - fix_y;
150 newd = sqrt(newx * newx + newy * newy);
151 oldx = from_x - fix_x;
152 oldy = from_y - fix_y;
153 oldd = sqrt(oldx * oldx + oldy * oldy);
154 scalefact = newd / oldd;
155 x1 = fix_x + round((c->secorner.x - fix_x) * scalefact);
156 y1 = fix_y + round((c->secorner.y - fix_y) * scalefact);
157 x2 = fix_x + round((c->nwcorner.x - fix_x) * scalefact);
158 y2 = fix_y + round((c->nwcorner.y - fix_y) * scalefact);
159 boxsize_scale_msg(2);
160 elastic_box(x1, y1, x2, y2);
161 }
162
163 /*************************** LINES *************************/
164
165 /* refresh a line segment */
166
167 void
elastic_line(void)168 elastic_line(void)
169 {
170 pw_vector(canvas_win, fix_x, fix_y, cur_x, cur_y,
171 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
172 /* erase endpoint because next seg will redraw it */
173 pw_vector(canvas_win, cur_x, cur_y, cur_x, cur_y,
174 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
175 }
176
177 /* this is only called by get_intermediatepoint() for drawing lines and by
178 the canvas_locmove_proc for drawing arcs */
179
180 void
unconstrained_line(int x,int y)181 unconstrained_line(int x, int y)
182 {
183 elastic_line();
184 cur_x = x;
185 cur_y = y;
186 length_msg(MSG_PNTS_LENGTH);
187 elastic_line();
188 }
189
190 void
latex_line(int x,int y)191 latex_line(int x, int y)
192 {
193 Cursor c;
194
195 elastic_line();
196 latex_endpoint(fix_x, fix_y, x, y, &cur_x, &cur_y, latexarrow_mode,
197 (cur_pointposn == P_ANY) ? 1 : max2(1, point_spacing()));
198 length_msg(MSG_LENGTH);
199 elastic_line();
200 c = (x == cur_x && y == cur_y) ? null_cursor : crosshair_cursor;
201 if (c != cur_cursor) {
202 set_temp_cursor(c);
203 cur_cursor = c;
204 }
205 }
206
207 void
constrainedangle_line(int x,int y)208 constrainedangle_line(int x, int y)
209 {
210 double angle, dx, dy;
211
212 if (x == cur_x && y == cur_y)
213 return;
214
215 dx = x - fix_x;
216 dy = fix_y - y;
217 /* only move if the pointer has moved at least 2 pixels */
218 if (sqrt(dx * dx + dy * dy) < 2.0)
219 return;
220 if (dx == 0)
221 angle = -90.0;
222 else
223 angle = 180.0 * atan(dy / dx) / M_PI;
224
225 elastic_line();
226 if (manhattan_mode) {
227 if (mountain_mode) {
228 if (angle < -67.5)
229 angle90_line(x, y);
230 else if (angle < -22.5)
231 angle135_line(x, y);
232 else if (angle < 22.5)
233 angle0_line(x, y);
234 else if (angle < 67.5)
235 angle45_line(x, y);
236 else
237 angle90_line(x, y);
238 } else {
239 if (angle < -45.0)
240 angle90_line(x, y);
241 else if (angle < 45.0)
242 angle0_line(x, y);
243 else
244 angle90_line(x, y);
245 }
246 } else {
247 if (angle < 0.0)
248 angle135_line(x, y);
249 else
250 angle45_line(x, y);
251 }
252 length_msg(MSG_LENGTH);
253 elastic_line();
254 }
255
256 static void
angle0_line(int x,int y)257 angle0_line(int x, int y)
258 {
259 cur_x = x;
260 cur_y = fix_y;
261 }
262
263 static void
angle90_line(int x,int y)264 angle90_line(int x, int y)
265 {
266 cur_y = y;
267 cur_x = fix_x;
268 }
269
270 static void
angle45_line(int x,int y)271 angle45_line(int x, int y)
272 {
273 if (abs(x - fix_x) < abs(y - fix_y)) {
274 cur_x = fix_x - y + fix_y;
275 cur_y = y;
276 } else {
277 cur_y = fix_y + fix_x - x;
278 cur_x = x;
279 }
280 }
281
282 static void
angle135_line(int x,int y)283 angle135_line(int x, int y)
284 {
285 if (abs(x - fix_x) < abs(y - fix_y)) {
286 cur_x = fix_x + y - fix_y;
287 cur_y = y;
288 } else {
289 cur_y = fix_y + x - fix_x;
290 cur_x = x;
291 }
292 }
293
294 void
reshaping_line(int x,int y)295 reshaping_line(int x, int y)
296 {
297 elastic_linelink();
298 adjust_pos(x, y, from_x, from_y, &cur_x, &cur_y);
299 /* one or two lines moving with the move point? */
300 if (left_point != NULL && right_point != NULL) {
301 length_msg2(left_point->x,left_point->y,
302 right_point->x,right_point->y,cur_x,cur_y);
303 } else if (left_point != NULL) {
304 altlength_msg(MSG_LENGTH,left_point->x,left_point->y);
305 } else if (right_point != NULL) {
306 altlength_msg(MSG_LENGTH,right_point->x,right_point->y);
307 }
308 elastic_linelink();
309 }
310
311 void
elastic_linelink(void)312 elastic_linelink(void)
313 {
314 if (left_point != NULL) {
315 pw_vector(canvas_win, left_point->x, left_point->y,
316 cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
317 }
318 if (right_point != NULL) {
319 pw_vector(canvas_win, right_point->x, right_point->y,
320 cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
321 }
322 }
323
324 void
moving_line(int x,int y)325 moving_line(int x, int y)
326 {
327 elastic_moveline(new_l->points);
328 adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
329 length_msg(MSG_DIST);
330 elastic_moveline(new_l->points);
331 }
332
333 void
elastic_movenewline(void)334 elastic_movenewline(void)
335 {
336 elastic_moveline(new_l->points);
337 }
338
339 void
elastic_moveline(F_point * pts)340 elastic_moveline(F_point *pts)
341 {
342 F_point *p;
343 int dx, dy, x, y, xx, yy;
344
345 p = pts;
346 if (p->next == NULL) { /* dot */
347 pw_vector(canvas_win, cur_x, cur_y, cur_x, cur_y,
348 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
349 } else {
350 dx = cur_x - fix_x;
351 dy = cur_y - fix_y;
352 x = p->x + dx;
353 y = p->y + dy;
354 for (p = p->next; p != NULL; x = xx, y = yy, p = p->next) {
355 xx = p->x + dx;
356 yy = p->y + dy;
357 pw_vector(canvas_win, x, y, xx, yy, INV_PAINT, 1,
358 RUBBER_LINE, 0.0, DEFAULT);
359 /* erase endpoint of last segment because next will redraw it */
360 if (p->next)
361 pw_vector(canvas_win, xx, yy, xx, yy, INV_PAINT, 1,
362 RUBBER_LINE, 0.0, DEFAULT);
363 }
364 elastic_links(dx, dy, 1.0, 1.0);
365 }
366 }
367
368 static void
elastic_links(int dx,int dy,float sx,float sy)369 elastic_links(int dx, int dy, float sx, float sy)
370 {
371 F_linkinfo *k;
372
373 if (cur_linkmode == SMART_OFF)
374 return;
375
376 for (k = cur_links; k != NULL; k = k->next)
377 if (k->prevpt == NULL) {/* dot */
378 pw_vector(canvas_win, k->endpt->x, k->endpt->y,
379 k->endpt->x, k->endpt->y,
380 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
381 } else {
382 if (cur_linkmode == SMART_MOVE)
383 pw_vector(canvas_win, k->endpt->x + dx, k->endpt->y + dy,
384 k->prevpt->x, k->prevpt->y,
385 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
386 else if (cur_linkmode == SMART_SLIDE) {
387 if (k->endpt->x == k->prevpt->x) {
388 if (!k->two_pts)
389 pw_vector(canvas_win, k->prevpt->x,
390 k->prevpt->y, k->prevpt->x + dx, k->prevpt->y,
391 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
392 pw_vector(canvas_win, k->endpt->x + dx,
393 k->endpt->y + dy, k->prevpt->x + dx, k->prevpt->y,
394 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
395 } else {
396 if (!k->two_pts)
397 pw_vector(canvas_win, k->prevpt->x,
398 k->prevpt->y, k->prevpt->x, k->prevpt->y + dy,
399 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
400 pw_vector(canvas_win, k->endpt->x + dx,
401 k->endpt->y + dy, k->prevpt->x, k->prevpt->y + dy,
402 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
403 }
404 }
405 }
406 }
407
408 void
scaling_line(int x,int y)409 scaling_line(int x, int y)
410 {
411 elastic_scalepts(cur_l->points);
412 adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
413 if (cur_l->type == T_BOX || cur_l->type == T_ARCBOX || cur_l->type == T_PICTURE)
414 boxsize_msg(2);
415 elastic_scalepts(cur_l->points);
416 }
417
418 void
elastic_scale_curline(int x,int y)419 elastic_scale_curline(int x, int y)
420 {
421 elastic_scalepts(cur_l->points);
422 }
423
424 void
scaling_spline(int x,int y)425 scaling_spline(int x, int y)
426 {
427 elastic_scalepts(cur_s->points);
428 adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
429 elastic_scalepts(cur_s->points);
430 }
431
432 void
elastic_scale_curspline(void)433 elastic_scale_curspline(void)
434 {
435 elastic_scalepts(cur_s->points);
436 }
437
438 void
elastic_scalepts(F_point * pts)439 elastic_scalepts(F_point *pts)
440 {
441 F_point *p;
442 double newx, newy, oldx, oldy;
443 double newd, oldd, scalefact;
444 int ox, oy, xx, yy;
445
446 p = pts;
447 newx = cur_x - fix_x;
448 newy = cur_y - fix_y;
449 newd = sqrt(newx * newx + newy * newy);
450
451 oldx = from_x - fix_x;
452 oldy = from_y - fix_y;
453 oldd = sqrt(oldx * oldx + oldy * oldy);
454
455 scalefact = newd / oldd;
456 ox = fix_x + round((p->x - fix_x) * scalefact);
457 oy = fix_y + round((p->y - fix_y) * scalefact);
458 for (p = p->next; p != NULL; ox = xx, oy = yy, p = p->next) {
459 xx = fix_x + round((p->x - fix_x) * scalefact);
460 yy = fix_y + round((p->y - fix_y) * scalefact);
461 pw_vector(canvas_win, ox, oy, xx, yy, INV_PAINT, 1,
462 RUBBER_LINE, 0.0, DEFAULT);
463 }
464 }
465
466 void
elastic_poly(int x1,int y1,int x2,int y2,int numsides)467 elastic_poly(int x1, int y1, int x2, int y2, int numsides)
468 {
469 register float angle;
470 register int nx, ny, i;
471 double dx, dy;
472 double init_angle, mag;
473 int ox, oy;
474
475 dx = x2 - x1;
476 dy = y2 - y1;
477 mag = sqrt(dx * dx + dy * dy);
478 init_angle = compute_angle(dx, dy);
479 ox = x2;
480 oy = y2;
481
482 /* now append numsides points */
483 for (i = 1; i < numsides; i++) {
484 angle = (float)(init_angle - M_2PI * (double) i / (double) numsides);
485 if (angle < 0)
486 angle += M_2PI;
487 nx = x1 + round(mag * cos((double) angle));
488 ny = y1 + round(mag * sin((double) angle));
489 pw_vector(canvas_win, nx, ny, ox, oy, INV_PAINT, 1,
490 RUBBER_LINE, 0.0, DEFAULT);
491 ox = nx;
492 oy = ny;
493 }
494 pw_vector(canvas_win, ox, oy, x2, y2, INV_PAINT, 1,
495 RUBBER_LINE, 0.0, DEFAULT);
496 }
497
498 void
resizing_poly(int x,int y)499 resizing_poly(int x, int y)
500 {
501 elastic_poly(fix_x, fix_y, cur_x, cur_y, work_numsides);
502 cur_x = x;
503 cur_y = y;
504 work_numsides = cur_numsides;
505 length_msg(MSG_LENGTH);
506 elastic_poly(fix_x, fix_y, cur_x, cur_y, work_numsides);
507 }
508
509 /*********************** ELLIPSES *************************/
510
511 void
elastic_ebr(void)512 elastic_ebr(void)
513 {
514 register int x1, y1, x2, y2;
515 int rx, ry;
516
517 rx = cur_x - fix_x;
518 ry = cur_y - fix_y;
519 if (cur_angle != 0.0) {
520 angle_ellipse(fix_x, fix_y, rx, ry, cur_angle, INV_PAINT, MAX_DEPTH+1, 1,
521 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT);
522 } else {
523 x1 = fix_x + rx;
524 x2 = fix_x - rx;
525 y1 = fix_y + ry;
526 y2 = fix_y - ry;
527 pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, MAX_DEPTH+1, 1,
528 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT, CAP_BUTT);
529 }
530 }
531
532 void
resizing_ebr(int x,int y)533 resizing_ebr(int x, int y)
534 {
535 elastic_ebr();
536 cur_x = x;
537 cur_y = y;
538 length_msg(MSG_RADIUS2);
539 elastic_ebr();
540 }
541
542 void
constrained_resizing_ebr(int x,int y)543 constrained_resizing_ebr(int x, int y)
544 {
545 elastic_ebr();
546 adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
547 length_msg(MSG_RADIUS2);
548 elastic_ebr();
549 }
550
551 void
elastic_ebd(void)552 elastic_ebd(void)
553 {
554 int centx,centy;
555
556 centx = (fix_x+cur_x)/2;
557 centy = (fix_y+cur_y)/2;
558 length_msg(MSG_DIAM);
559 if (cur_angle != 0.0) {
560 angle_ellipse(centx, centy, abs(cur_x-fix_x)/2,
561 abs(cur_y-fix_y)/2, cur_angle,
562 INV_PAINT, MAX_DEPTH+1, 1, RUBBER_LINE, 0.0, UNFILLED,
563 DEFAULT, DEFAULT);
564 } else {
565 pw_curve(canvas_win, fix_x, fix_y, cur_x, cur_y, INV_PAINT, MAX_DEPTH+1, 1,
566 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT, CAP_BUTT);
567 }
568 }
569
570 void
resizing_ebd(int x,int y)571 resizing_ebd(int x, int y)
572 {
573 elastic_ebd();
574 cur_x = x;
575 cur_y = y;
576 length_msg(MSG_DIAM);
577 elastic_ebd();
578 }
579
580 void
constrained_resizing_ebd(int x,int y)581 constrained_resizing_ebd(int x, int y)
582 {
583 elastic_ebd();
584 adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
585 length_msg(MSG_DIAM);
586 elastic_ebd();
587 }
588
589 void
elastic_cbr(void)590 elastic_cbr(void)
591 {
592 register int radius, x1, y1, x2, y2;
593 double rx, ry;
594
595 rx = cur_x - fix_x;
596 ry = cur_y - fix_y;
597 radius = round(sqrt(rx * rx + ry * ry));
598 x1 = fix_x + radius;
599 x2 = fix_x - radius;
600 y1 = fix_y + radius;
601 y2 = fix_y - radius;
602 pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, MAX_DEPTH+1, 1,
603 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT, CAP_BUTT);
604 }
605
606 void
resizing_cbr(int x,int y)607 resizing_cbr(int x, int y)
608 {
609 elastic_cbr();
610 cur_x = x;
611 cur_y = y;
612 length_msg(MSG_RADIUS);
613 elastic_cbr();
614 }
615
616 void
elastic_cbd(void)617 elastic_cbd(void)
618 {
619 register int x1, y1, x2, y2;
620 int radius;
621 double rx, ry;
622
623 rx = (cur_x - fix_x) / 2;
624 ry = (cur_y - fix_y) / 2;
625 radius = round(sqrt(rx * rx + ry * ry));
626 x1 = fix_x + rx + radius;
627 x2 = fix_x + rx - radius;
628 y1 = fix_y + ry + radius;
629 y2 = fix_y + ry - radius;
630 pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, MAX_DEPTH+1, 1,
631 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT, CAP_BUTT);
632 }
633
634 void
resizing_cbd(int x,int y)635 resizing_cbd(int x, int y)
636 {
637 elastic_cbd();
638 cur_x = x;
639 cur_y = y;
640 length_msg(MSG_DIAM);
641 elastic_cbd();
642 }
643
644 void
constrained_resizing_cbd(int x,int y)645 constrained_resizing_cbd(int x, int y)
646 {
647 elastic_cbd();
648 adjust_box_pos(x, y, from_x, from_y, &cur_x, &cur_y);
649 length_msg(MSG_DIAM);
650 elastic_cbd();
651 }
652
653 void
elastic_moveellipse(void)654 elastic_moveellipse(void)
655 {
656 register int x1, y1, x2, y2;
657
658 x1 = cur_x + x1off;
659 x2 = cur_x + x2off;
660 y1 = cur_y + y1off;
661 y2 = cur_y + y2off;
662 if (cur_angle != 0.0) {
663 angle_ellipse((x1+x2)/2, (y1+y2)/2, abs(x1-x2)/2, abs(y1-y2)/2, cur_angle,
664 INV_PAINT, MAX_DEPTH+1, 1, RUBBER_LINE, 0.0, UNFILLED,
665 DEFAULT, DEFAULT);
666 } else {
667 pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, MAX_DEPTH+1, 1,
668 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT, CAP_BUTT);
669 }
670 }
671
672 void
moving_ellipse(int x,int y)673 moving_ellipse(int x, int y)
674 {
675 elastic_moveellipse();
676 adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
677 length_msg(MSG_DIST);
678 elastic_moveellipse();
679 }
680
681 void
elastic_scaleellipse(F_ellipse * e)682 elastic_scaleellipse(F_ellipse *e)
683 {
684 register int x1, y1, x2, y2;
685 int rx, ry;
686 double newx, newy, oldx, oldy;
687 float newd, oldd, scalefact;
688
689 newx = cur_x - fix_x;
690 newy = cur_y - fix_y;
691 newd = sqrt(newx * newx + newy * newy);
692
693 oldx = from_x - fix_x;
694 oldy = from_y - fix_y;
695 oldd = sqrt(oldx * oldx + oldy * oldy);
696
697 scalefact = newd / oldd;
698
699 rx = round(e->radiuses.x * scalefact);
700 ry = round(e->radiuses.y * scalefact);
701 if (cur_angle != 0.0) {
702 angle_ellipse(e->center.x, e->center.y, rx, ry, cur_angle,
703 INV_PAINT, MAX_DEPTH+1, 1, RUBBER_LINE, 0.0, UNFILLED,
704 DEFAULT, DEFAULT);
705 } else {
706 x1 = fix_x + rx;
707 x2 = fix_x - rx;
708 y1 = fix_y + ry;
709 y2 = fix_y - ry;
710 pw_curve(canvas_win, x1, y1, x2, y2, INV_PAINT, MAX_DEPTH+1, 1,
711 RUBBER_LINE, 0.0, UNFILLED, DEFAULT, DEFAULT, CAP_BUTT);
712 }
713 }
714
715 void
scaling_ellipse(int x,int y)716 scaling_ellipse(int x, int y)
717 {
718 elastic_scaleellipse(cur_e);
719 adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
720 if (cur_e->type == T_ELLIPSE_BY_RAD)
721 length_msg(MSG_RADIUS2);
722 else if (cur_e->type == T_CIRCLE_BY_RAD)
723 length_msg(MSG_RADIUS);
724 else
725 length_msg(MSG_DIAM);
726 elastic_scaleellipse(cur_e);
727 }
728
729 void
elastic_scale_curellipse(void)730 elastic_scale_curellipse(void)
731 {
732 elastic_scaleellipse(cur_e);
733 }
734
735 /*************************** ARCS *************************/
736
737 void
arc_point(int x,int y,int numpoint)738 arc_point(int x, int y, int numpoint)
739 {
740 elastic_line();
741 cur_x = x;
742 cur_y = y;
743 altlength_msg(MSG_RADIUS_ANGLE, center_point.x, center_point.y);
744 elastic_line();
745 }
746
747 void
reshaping_arc(int x,int y)748 reshaping_arc(int x, int y)
749 {
750 elastic_arclink();
751 adjust_pos(x, y, cur_a->point[movedpoint_num].x,
752 cur_a->point[movedpoint_num].y, &cur_x, &cur_y);
753 if (movedpoint_num == 1) {
754 /* middle point */
755 arc_msg(cur_a->point[0].x, cur_a->point[0].y,
756 cur_a->point[2].x, cur_a->point[2].y,
757 cur_x, cur_y);
758 } else {
759 /* end point */
760 altlength_msg(MSG_LENGTH,cur_a->point[1].x,cur_a->point[1].y);
761 }
762 elastic_arclink();
763 }
764
765 void
elastic_arclink(void)766 elastic_arclink(void)
767 {
768 switch (movedpoint_num) {
769 case 0:
770 pw_vector(canvas_win, cur_x, cur_y,
771 cur_a->point[1].x, cur_a->point[1].y,
772 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
773 break;
774 case 1:
775 pw_vector(canvas_win, cur_a->point[0].x, cur_a->point[0].y,
776 cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
777 pw_vector(canvas_win, cur_a->point[2].x, cur_a->point[2].y,
778 cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
779 break;
780 default:
781 pw_vector(canvas_win, cur_a->point[1].x, cur_a->point[1].y,
782 cur_x, cur_y, INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
783 }
784 }
785
786 void
moving_arc(int x,int y)787 moving_arc(int x, int y)
788 {
789 elastic_movearc(new_a);
790 adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
791 length_msg(MSG_DIST);
792 elastic_movearc(new_a);
793 }
794
795 void
elastic_movenewarc(void)796 elastic_movenewarc(void)
797 {
798 elastic_movearc(new_a);
799 }
800
801 void
elastic_movearc(F_arc * a)802 elastic_movearc(F_arc *a)
803 {
804 int dx, dy;
805
806 dx = cur_x - fix_x;
807 dy = cur_y - fix_y;
808 pw_vector(canvas_win, a->point[0].x + dx, a->point[0].y + dy,
809 a->point[1].x + dx, a->point[1].y + dy,
810 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
811 pw_vector(canvas_win, a->point[1].x + dx, a->point[1].y + dy,
812 a->point[2].x + dx, a->point[2].y + dy,
813 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
814 }
815
816 void
scaling_arc(int x,int y)817 scaling_arc(int x, int y)
818 {
819 elastic_scalearc(cur_a);
820 adjust_box_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
821 elastic_scalearc(cur_a);
822 }
823
824 void
elastic_scale_curarc(void)825 elastic_scale_curarc(void)
826 {
827 elastic_scalearc(cur_a);
828 }
829
830 void
elastic_scalearc(F_arc * a)831 elastic_scalearc(F_arc *a)
832 {
833 double newx, newy, oldx, oldy;
834 double newd, oldd, scalefact;
835 F_pos p0, p1, p2;
836
837 newx = cur_x - fix_x;
838 newy = cur_y - fix_y;
839 newd = sqrt(newx * newx + newy * newy);
840
841 oldx = from_x - fix_x;
842 oldy = from_y - fix_y;
843 oldd = sqrt(oldx * oldx + oldy * oldy);
844
845 scalefact = newd / oldd;
846
847 p0 = a->point[0];
848 p1 = a->point[1];
849 p2 = a->point[2];
850 p0.x = fix_x + round((p0.x - fix_x) * scalefact);
851 p0.y = fix_y + round((p0.y - fix_y) * scalefact);
852 p1.x = fix_x + round((p1.x - fix_x) * scalefact);
853 p1.y = fix_y + round((p1.y - fix_y) * scalefact);
854 p2.x = fix_x + round((p2.x - fix_x) * scalefact);
855 p2.y = fix_y + round((p2.y - fix_y) * scalefact);
856
857 length_msg2(p0.x, p0.y, p2.x, p2.y, p1.x, p1.y);
858 pw_vector(canvas_win, p0.x, p0.y, p1.x, p1.y,
859 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
860 pw_vector(canvas_win, p1.x, p1.y, p2.x, p2.y,
861 INV_PAINT, 1, RUBBER_LINE, 0.0, DEFAULT);
862 }
863
864 /*************************** TEXT *************************/
865
866 void
moving_text(int x,int y)867 moving_text(int x, int y)
868 {
869 elastic_movetext();
870 adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
871 length_msg(MSG_DIST);
872 elastic_movetext();
873 }
874
875 /* use x1off, y1off so that the beginning of the text isn't
876 shifted under the cursor */
877
878 void
elastic_movetext(void)879 elastic_movetext(void)
880 {
881 pw_text(canvas_win, cur_x + x1off, cur_y + y1off, INV_PAINT, MAX_DEPTH+1,
882 new_t->fontstruct, new_t->angle,
883 new_t->cstring, new_t->color, COLOR_NONE);
884 }
885
886
887 /*************************** SPLINES *************************/
888
889 void
moving_spline(int x,int y)890 moving_spline(int x, int y)
891 {
892 elastic_moveline(new_s->points);
893 adjust_pos(x, y, fix_x, fix_y, &cur_x, &cur_y);
894 length_msg(MSG_DIST);
895 elastic_moveline(new_s->points);
896 }
897
898 void
elastic_movenewspline(void)899 elastic_movenewspline(void)
900 {
901 elastic_moveline(new_s->points);
902 }
903
904 /*********** AUXILIARY FUNCTIONS FOR CONSTRAINED MOVES ******************/
905
906 void
adjust_box_pos(int curs_x,int curs_y,int orig_x,int orig_y,int * ret_x,int * ret_y)907 adjust_box_pos(int curs_x, int curs_y, int orig_x, int orig_y, int *ret_x, int *ret_y)
908 {
909 int xx, sgn_csr2fix_x, yy, sgn_csr2fix_y;
910 double mag_csr2fix_x, mag_csr2fix_y;
911
912 switch (constrained) {
913 case MOVE_ARB:
914 *ret_x = curs_x;
915 *ret_y = curs_y;
916 break;
917 case BOX_HSTRETCH:
918 *ret_x = curs_x;
919 *ret_y = orig_y;
920 break;
921 case BOX_VSTRETCH:
922 *ret_x = orig_x;
923 *ret_y = curs_y;
924 break;
925 default:
926 /* calculate where scaled and stretched box corners would be */
927 xx = curs_x - fix_x;
928 sgn_csr2fix_x = signof(xx);
929 mag_csr2fix_x = (double) abs(xx);
930
931 yy = curs_y - fix_y;
932 sgn_csr2fix_y = signof(yy);
933 mag_csr2fix_y = (double) abs(yy);
934
935 if (mag_csr2fix_x * sina > mag_csr2fix_y * cosa) { /* above diagonal */
936 *ret_x = curs_x;
937 if (constrained == BOX_SCALE) {
938 if (cosa == 0.0) {
939 *ret_y = fix_y + sgn_csr2fix_y * (int) (mag_csr2fix_x);
940 } else {
941 *ret_y = fix_y + sgn_csr2fix_y * (int) (mag_csr2fix_x * sina / cosa);
942 }
943 } else {
944 *ret_y = fix_y + sgn_csr2fix_y * abs(fix_y - orig_y);
945 }
946 } else {
947 *ret_y = curs_y;
948 if (constrained == BOX_SCALE) {
949 if (sina == 0.0) {
950 *ret_x = fix_x + sgn_csr2fix_x * (int) (mag_csr2fix_y);
951 } else {
952 *ret_x = fix_x + sgn_csr2fix_x * (int) (mag_csr2fix_y * cosa / sina);
953 }
954 } else {
955 *ret_x = fix_x + sgn_csr2fix_x * abs(fix_x - orig_x);
956 }
957 }
958 } /* switch */
959 }
960
961 void
adjust_pos(int curs_x,int curs_y,int orig_x,int orig_y,int * ret_x,int * ret_y)962 adjust_pos(int curs_x, int curs_y, int orig_x, int orig_y, int *ret_x, int *ret_y)
963 {
964 if (constrained) {
965 if (abs(orig_x - curs_x) > abs(orig_y - curs_y)) {
966 *ret_x = curs_x;
967 *ret_y = orig_y;
968 } else {
969 *ret_x = orig_x;
970 *ret_y = curs_y;
971 }
972 } else {
973 *ret_x = curs_x;
974 *ret_y = curs_y;
975 }
976 }
977