1 /*
2 * FIG : Facility for Interactive Generation of figures
3 * Copyright (c) 1991 by Paul King
4 * Parts Copyright (c) 1989-2007 by Brian V. Smith
5 *
6 * Any party obtaining a copy of these files is granted, free of charge, a
7 * full and unrestricted irrevocable, world-wide, paid up, royalty-free,
8 * nonexclusive right and license to deal in this software and documentation
9 * files (the "Software"), including without limitation the rights to use,
10 * copy, modify, merge, publish, distribute, sublicense and/or sell copies of
11 * the Software, and to permit persons who receive copies from any such
12 * party to do so, with the only requirement being that the above copyright
13 * and this permission notice remain intact.
14 *
15 */
16
17 #include "e_align.h"
18
19 #include <stdlib.h>
20 #include <limits.h> /* INT_MAX, INT_MIN */
21 #include <X11/Intrinsic.h> /* includes X11/Xlib.h */
22
23 #include "resources.h"
24 #include "object.h"
25 #include "paintop.h"
26 #include "mode.h"
27 #include "u_bound.h"
28 #include "u_create.h"
29 #include "u_draw.h"
30 #include "u_markers.h"
31 #include "u_search.h"
32 #include "u_translate.h"
33 #include "u_undo.h"
34 #include "w_canvas.h"
35 #include "w_cursor.h"
36 #include "w_layers.h"
37 #include "w_mousefun.h"
38 #include "w_msgpanel.h"
39 #include "w_setup.h"
40 #include "xfig_math.h"
41
42
43 static int llx, lly, urx, ury;
44 static int xcmin, ycmin, xcmax, ycmax;
45 static int dx, dy;
46
47 static Boolean pos_arc(F_arc *a, int *min, int *size, int dir);
48 static Boolean pos_ellipse(F_ellipse *e, int *min, int *size, int dir);
49 static Boolean pos_line(F_line *l, int *min, int *size, int dir);
50 static Boolean pos_spline(F_spline *s, int *min, int *size, int dir);
51 static Boolean pos_text(F_text *t, int *min, int *size, int dir);
52 static Boolean pos_compound(F_compound *c, int *min, int *size, int dir);
53
54 static void init_align(F_line *p, int type, int x, int y, int px, int py);
55 static void init_align_canvas(int x, int y, unsigned int shift);
56 static void align_arc(void);
57 static void align_ellipse(void);
58 static void align_line(void);
59 static void align_spline(void);
60 static void align_text(void);
61 static void align_compound(void);
62 static void get_dx_dy(void);
63 static void distribute_horizontally(void);
64 static void distribute_vertically(void);
65
66
67
68 void
align_selected(void)69 align_selected(void)
70 {
71 set_mousefun("align compound", "align canvas", "", LOC_OBJ, "", LOC_OBJ);
72 canvas_kbd_proc = null_proc;
73 canvas_locmove_proc = null_proc;
74 canvas_ref_proc = null_proc;
75 init_searchproc_left(init_align);
76 canvas_leftbut_proc = object_search_left;
77 canvas_middlebut_proc = init_align_canvas;
78 canvas_rightbut_proc = null_proc;
79 set_cursor(pick15_cursor);
80 reset_action_on();
81 }
82
83 /* align objects to the whole canvas */
84
85 static void
init_align_canvas(int x,int y,unsigned int shift)86 init_align_canvas(int x, int y, unsigned int shift)
87 /* Shift Key Status from XEvent */
88 {
89 (void)x;
90 (void)y;
91 (void)shift;
92 int ux;
93
94 cur_c = &objects;
95 toggle_all_compoundmarkers();
96 draw_compoundelements(cur_c, ERASE);
97 old_c = copy_compound(&objects);
98 xcmin=ycmin=0;
99
100 /* get the current page size */
101 xcmax = paper_sizes[appres.papersize].width;
102 ycmax = paper_sizes[appres.papersize].height;
103 if (!appres.INCHES) {
104 xcmax = (int)(xcmax*2.54*PIX_PER_CM/PIX_PER_INCH);
105 ycmax = (int)(ycmax*2.54*PIX_PER_CM/PIX_PER_INCH);
106 }
107 /* swap height and width if landscape */
108 if (appres.landscape) {
109 ux = xcmax;
110 xcmax = ycmax;
111 ycmax = ux;
112 }
113 align_ellipse();
114 align_arc();
115 align_line();
116 align_spline();
117 align_compound();
118 align_text();
119
120 /*
121 * Display messages indicating that distribution or alignment can't be
122 * performed with respect to the canvas.
123 */
124 if ((cur_halign == ALIGN_DISTRIB_C) || (cur_halign == ALIGN_DISTRIB_E))
125 put_msg("Can't DISTRIBUTE horizontally with respect to the canvas");
126 else if (cur_halign == ALIGN_ABUT)
127 put_msg("Can't ABUT horizontally with respect to the canvas");
128 if ((cur_valign == ALIGN_DISTRIB_C) || (cur_valign == ALIGN_DISTRIB_E))
129 put_msg("Can't DISTRIBUTE vertically with respect to the canvas");
130 else if (cur_valign == ALIGN_ABUT)
131 put_msg("Can't ABUT vertically with respect to the canvas");
132
133 draw_compoundelements(cur_c, PAINT);
134 toggle_all_compoundmarkers();
135 clean_up();
136 set_latestobjects(old_c);
137 set_action_object(F_EDIT, O_ALL_OBJECT);
138 set_modifiedflag();
139 }
140
141 static void
init_align(F_line * p,int type,int x,int y,int px,int py)142 init_align(F_line *p, int type, int x, int y, int px, int py)
143 {
144 (void)x;
145 (void)y;
146 (void)px;
147 (void)py;
148
149 if (type != O_COMPOUND)
150 return;
151 cur_c = (F_compound *) p;
152 toggle_compoundmarker(cur_c);
153 draw_compoundelements(cur_c, ERASE);
154 old_c = copy_compound(cur_c);
155 compound_bound(cur_c, &xcmin, &ycmin, &xcmax, &ycmax);
156 align_ellipse();
157 align_arc();
158 align_line();
159 align_spline();
160 align_compound();
161 align_text();
162
163 /*
164 * Perform the distribution of the objects in the compound
165 */
166 if ( (cur_halign == ALIGN_DISTRIB_C) || (cur_halign == ALIGN_DISTRIB_E)
167 || (cur_halign == ALIGN_ABUT) )
168 distribute_horizontally();
169 if ( (cur_valign == ALIGN_DISTRIB_C) || (cur_valign == ALIGN_DISTRIB_E)
170 || (cur_valign == ALIGN_ABUT) )
171 distribute_vertically();
172
173 /*
174 * recompute the compound's bounding box
175 */
176 compound_bound(cur_c, &cur_c->nwcorner.x, &cur_c->nwcorner.y,
177 &cur_c->secorner.x, &cur_c->secorner.y);
178 draw_compoundelements(cur_c, PAINT);
179 toggle_compoundmarker(cur_c);
180 clean_up();
181 old_c->next = cur_c;
182 set_latestcompound(old_c);
183 set_action_object(F_EDIT, O_COMPOUND);
184 set_modifiedflag();
185 }
186
187 static void
align_ellipse(void)188 align_ellipse(void)
189 {
190 F_ellipse *e;
191
192 for (e = cur_c->ellipses; e != NULL; e = e->next) {
193 if (!active_layer(e->depth))
194 continue;
195 ellipse_bound(e, &llx, &lly, &urx, &ury);
196 get_dx_dy();
197 translate_ellipse(e, dx, dy);
198 }
199 }
200
201 static void
align_arc(void)202 align_arc(void)
203 {
204 F_arc *a;
205
206 for (a = cur_c->arcs; a != NULL; a = a->next) {
207 if (!active_layer(a->depth))
208 continue;
209 arc_bound(a, &llx, &lly, &urx, &ury);
210 get_dx_dy();
211 translate_arc(a, dx, dy);
212 }
213 }
214
215 static void
align_line(void)216 align_line(void)
217 {
218 F_line *l;
219
220 for (l = cur_c->lines; l != NULL; l = l->next) {
221 if (!active_layer(l->depth))
222 continue;
223 line_bound(l, &llx, &lly, &urx, &ury);
224 get_dx_dy();
225 translate_line(l, dx, dy);
226 }
227 }
228
229 static void
align_spline(void)230 align_spline(void)
231 {
232 F_spline *s;
233
234 for (s = cur_c->splines; s != NULL; s = s->next) {
235 if (!active_layer(s->depth))
236 continue;
237 spline_bound(s, &llx, &lly, &urx, &ury);
238 get_dx_dy();
239 translate_spline(s, dx, dy);
240 }
241 }
242
243 static void
align_compound(void)244 align_compound(void)
245 {
246 F_compound *c;
247
248 for (c = cur_c->compounds; c != NULL; c = c->next) {
249 if (!any_active_in_compound(c))
250 continue;
251 compound_bound(c, &llx, &lly, &urx, &ury);
252 get_dx_dy();
253 translate_compound(c, dx, dy);
254 }
255 }
256
257 static void
align_text(void)258 align_text(void)
259 {
260 F_text *t;
261 int dum;
262
263 for (t = cur_c->texts; t != NULL; t = t->next) {
264 if (!active_layer(t->depth))
265 continue;
266 text_bound(t, &llx, &lly, &urx, &ury,
267 &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
268 get_dx_dy();
269 translate_text(t, dx, dy);
270 }
271 }
272
273 static void
get_dx_dy(void)274 get_dx_dy(void)
275 {
276 switch (cur_valign) {
277 case ALIGN_NONE:
278 dy = 0;
279 break;
280 case ALIGN_TOP:
281 dy = ycmin - lly;
282 break;
283 case ALIGN_BOTTOM:
284 dy = ycmax - ury;
285 break;
286 case ALIGN_CENTER:
287 dy = (ycmin - lly) + (abs(ycmin - lly) + abs(ycmax - ury)) / 2;
288 break;
289 case ALIGN_DISTRIB_C:
290 case ALIGN_DISTRIB_E:
291 case ALIGN_ABUT:
292 break;
293 }
294 switch (cur_halign) {
295 case ALIGN_NONE:
296 dx = 0;
297 break;
298 case ALIGN_LEFT:
299 dx = xcmin - llx;
300 break;
301 case ALIGN_RIGHT:
302 dx = xcmax - urx;
303 break;
304 case ALIGN_CENTER:
305 dx = (xcmin - llx) + (abs(xcmin - llx) + abs(xcmax - urx)) / 2;
306 break;
307 case ALIGN_DISTRIB_C:
308 case ALIGN_DISTRIB_E:
309 case ALIGN_ABUT:
310 break;
311 }
312 }
313
314
315
316
317 /* ====================== Object distribution routines =================== */
318
319
320
321 /*
322 * pos_arc: If the position of the given arc is less than
323 * passed in and the arc hasn't already been distributed, adjust the value
324 * of the passed in parameter. Also set the width/height if smaller.
325 * If dir == 0, handle horizontal, otherwise vertical.
326 */
327 static Boolean
pos_arc(F_arc * a,int * min,int * size,int dir)328 pos_arc (F_arc *a, int *min, int *size, int dir)
329 {
330 int center;
331
332 arc_bound (a, &llx, &lly, &urx, &ury);
333 if (dir == 0) {
334 if (cur_halign == ALIGN_DISTRIB_C)
335 center = (urx + llx)/2;
336 else
337 center = min2(urx, llx);
338 } else {
339 if (cur_valign == ALIGN_DISTRIB_C)
340 center = (ury + lly)/2;
341 else
342 center = min2(ury, lly);
343 }
344
345 if ( (center < *min) && (a->distrib == 0) ) {
346 *min = center;
347 if (dir == 0)
348 *size = abs(urx - llx);
349 else
350 *size = abs(ury - lly);
351 return True;
352 } else
353 return False;
354 } /* pos_arc */
355
356
357
358 /*
359 * pos_ellipse: If the position of the given ellipse is less
360 * than passed in and the ellipse hasn't already been distributed, adjust the
361 * value of the passed in parameter. Also set the width/height if smaller.
362 * If dir == 0, handle horizontal, otherwise vertical.
363 */
364 static Boolean
pos_ellipse(F_ellipse * e,int * min,int * size,int dir)365 pos_ellipse (F_ellipse *e, int *min, int *size, int dir)
366 {
367 int center;
368
369 ellipse_bound (e, &llx, &lly, &urx, &ury);
370 if (dir == 0) {
371 if (cur_halign == ALIGN_DISTRIB_C)
372 center = (urx + llx)/2;
373 else
374 center = min2(urx, llx);
375 } else {
376 if (cur_valign == ALIGN_DISTRIB_C)
377 center = (ury + lly)/2;
378 else
379 center = min2(ury, lly);
380 }
381
382 if ( (center < *min) && (e->distrib == 0) ) {
383 *min = center;
384 if (dir == 0)
385 *size = abs(urx - llx);
386 else
387 *size = abs(ury - lly);
388 return True;
389 } else
390 return False;
391 } /* pos_ellipse */
392
393
394
395 /*
396 * pos_line: If the position of the given line is less than
397 * passed in and the line hasn't already been distributed, adjust the value
398 * of the passed in parameter. Also set the width/height if smaller.
399 * If dir == 0, handle horizontal, otherwise vertical.
400 */
401 static Boolean
pos_line(F_line * l,int * min,int * size,int dir)402 pos_line (F_line *l, int *min, int *size, int dir)
403 {
404 int center;
405
406 line_bound (l, &llx, &lly, &urx, &ury);
407 if (dir == 0) {
408 if (cur_halign == ALIGN_DISTRIB_C)
409 center = (urx + llx)/2;
410 else
411 center = min2(urx, llx);
412 } else {
413 if (cur_valign == ALIGN_DISTRIB_C)
414 center = (ury + lly)/2;
415 else
416 center = min2(ury, lly);
417 }
418
419 if ( (center < *min) && (l->distrib == 0) ) {
420 *min = center;
421 if (dir == 0)
422 *size = abs(urx - llx);
423 else
424 *size = abs(ury - lly);
425 return True;
426 } else
427 return False;
428 } /* pos_line */
429
430
431
432 /*
433 * pos_spline: If the position of the given spline is less than
434 * passed in and the spline hasn't already been distributed, adjust the value
435 * of the passed in parameter. Also set the width/height if smaller.
436 * If dir == 0, handle horizontal, otherwise vertical.
437 */
438 static Boolean
pos_spline(F_spline * s,int * min,int * size,int dir)439 pos_spline (F_spline *s, int *min, int *size, int dir)
440 {
441 int center;
442
443 spline_bound (s, &llx, &lly, &urx, &ury);
444 if (dir == 0) {
445 if (cur_halign == ALIGN_DISTRIB_C)
446 center = (urx + llx)/2;
447 else
448 center = min2(urx, llx);
449 } else {
450 if (cur_valign == ALIGN_DISTRIB_C)
451 center = (ury + lly)/2;
452 else
453 center = min2(ury, lly);
454 }
455
456 if ( (center < *min) && (s->distrib == 0) ) {
457 *min = center;
458 if (dir == 0)
459 *size = abs(urx - llx);
460 else
461 *size = abs(ury - lly);
462 return True;
463 } else
464 return False;
465 } /* pos_spline */
466
467
468
469 /*
470 * pos_text: If the position of the given text is less than
471 * passed in and the text hasn't already been distributed, adjust the value
472 * of the passed in parameter. Also set the width/height if smaller.
473 * If dir == 0, handle horizontal, otherwise vertical.
474 */
475 static Boolean
pos_text(F_text * t,int * min,int * size,int dir)476 pos_text (F_text *t, int *min, int *size, int dir)
477 {
478 int center, dum;
479
480 text_bound (t, &llx, &lly, &urx, &ury,
481 &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
482 if (dir == 0) {
483 if (cur_halign == ALIGN_DISTRIB_C)
484 center = (urx + llx)/2;
485 else
486 center = min2(urx, llx);
487 } else {
488 if (cur_valign == ALIGN_DISTRIB_C)
489 center = (ury + lly)/2;
490 else
491 center = min2(ury, lly);
492 }
493
494 if ( (center < *min) && (t->distrib == 0) ) {
495 *min = center;
496 if (dir == 0)
497 *size = abs(urx - llx);
498 else
499 *size = abs(ury - lly);
500 return True;
501 } else
502 return False;
503 } /* pos_text */
504
505
506 /*
507 * pos_compound: If the position of the given compound is less
508 * than passed in and the compound hasn't already been distributed, adjust the
509 * value of the passed in parameter. Also set the width/height if smaller.
510 * If dir == 0, handle horizontal, otherwise vertical.
511 */
512 static Boolean
pos_compound(F_compound * c,int * min,int * size,int dir)513 pos_compound (F_compound *c, int *min, int *size, int dir)
514 {
515 int center;
516
517 compound_bound (c, &llx, &lly, &urx, &ury);
518 if (dir == 0) {
519 if (cur_halign == ALIGN_DISTRIB_C)
520 center = (urx + llx)/2;
521 else
522 center = min2(urx, llx);
523 } else {
524 if (cur_valign == ALIGN_DISTRIB_C)
525 center = (ury + lly)/2;
526 else
527 center = min2(ury, lly);
528 }
529
530 if ( (center < *min) && (c->distrib == 0) ) {
531 *min = center;
532 if (dir == 0)
533 *size = abs(urx - llx);
534 else
535 *size = abs(ury - lly);
536 return True;
537 } else
538 return False;
539 } /* pos_compound */
540
541
542
543 #define MIN_MAX_CENTRE(lower,upper,min,max) \
544 { \
545 int centre = (lower + upper)/2; \
546 if (centre < min) \
547 min = centre; \
548 if (centre > max) \
549 max = centre; \
550 }
551
552
553
554
555 /*
556 * Determine:
557 * - the number of objects,
558 * - the left/top most centre and the right/bottom most centre,
559 * - mark all objects as not distributed.
560 *
561 * dir = 0 for horizontal, 1 for vertical.
562 */
563 static int
init_distrib_centres(int * min,int * max,int dir)564 init_distrib_centres (int *min, int *max, int dir)
565 {
566 F_ellipse *e;
567 F_arc *a;
568 F_line *l;
569 F_spline *s;
570 F_compound *c;
571 F_text *t;
572 int num_objects = 0;
573
574 *min = INT_MAX;
575 *max = INT_MIN;
576
577 for (e = cur_c->ellipses; e != NULL; e = e->next) {
578 num_objects++;
579 e->distrib = 0;
580 ellipse_bound (e, &llx, &lly, &urx, &ury);
581 if (dir == 0)
582 MIN_MAX_CENTRE(llx, urx, *min, *max)
583 else
584 MIN_MAX_CENTRE(lly, ury, *min, *max)
585 }
586
587 for (a = cur_c->arcs; a != NULL; a = a->next) {
588 num_objects++;
589 a->distrib = 0;
590 arc_bound (a, &llx, &lly, &urx, &ury);
591 if (dir == 0)
592 MIN_MAX_CENTRE(llx, urx, *min, *max)
593 else
594 MIN_MAX_CENTRE(lly, ury, *min, *max)
595 }
596
597 for (l = cur_c->lines; l != NULL; l = l->next) {
598 num_objects++;
599 l->distrib = 0;
600 line_bound (l, &llx, &lly, &urx, &ury);
601 if (dir == 0)
602 MIN_MAX_CENTRE(llx, urx, *min, *max)
603 else
604 MIN_MAX_CENTRE(lly, ury, *min, *max)
605 }
606
607 for (s = cur_c->splines; s != NULL; s = s->next) {
608 num_objects++;
609 s->distrib = 0;
610 spline_bound (s, &llx, &lly, &urx, &ury);
611 if (dir == 0)
612 MIN_MAX_CENTRE(llx, urx, *min, *max)
613 else
614 MIN_MAX_CENTRE(lly, ury, *min, *max)
615 }
616
617 for (c = cur_c->compounds; c != NULL; c = c->next) {
618 num_objects++;
619 c->distrib = 0;
620 compound_bound (c, &llx, &lly, &urx, &ury);
621 if (dir == 0)
622 MIN_MAX_CENTRE(llx, urx, *min, *max)
623 else
624 MIN_MAX_CENTRE(lly, ury, *min, *max)
625 }
626
627 for (t = cur_c->texts; t != NULL; t = t->next) {
628 int dum;
629 num_objects++;
630 t->distrib = 0;
631 text_bound (t, &llx, &lly, &urx, &ury,
632 &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
633 if (dir == 0)
634 MIN_MAX_CENTRE(llx, urx, *min, *max)
635 else
636 MIN_MAX_CENTRE(lly, ury, *min, *max)
637 }
638
639 return (num_objects);
640 } /* init_distrib_centres */
641
642
643
644 /*
645 * Determine:
646 * - the number of objects,
647 * - the sum of the widths/heights of all objects,
648 * - the left/top most left/top object edge,
649 * - the right/bottom most right/bottom object edge,
650 * - mark all objects as not distributed.
651 *
652 * dir = 0 for horizontal, 1 for vertical.
653 */
654 static int
init_distrib_edges(int * min,int * max,int * sum,int dir)655 init_distrib_edges (int *min, int *max, int *sum, int dir)
656 {
657 F_ellipse *e;
658 F_arc *a;
659 F_line *l;
660 F_spline *s;
661 F_compound *c;
662 F_text *t;
663 int num_objects = 0;
664
665 *min = INT_MAX;
666 *max = INT_MIN;
667 *sum = 0;
668
669 for (e = cur_c->ellipses; e != NULL; e = e->next) {
670 num_objects++;
671 e->distrib = 0;
672 ellipse_bound (e, &llx, &lly, &urx, &ury);
673 if (dir == 0) {
674 *sum += abs(urx - llx);
675 if (llx < *min) *min = llx;
676 if (urx > *max) *max = urx;
677 } else {
678 *sum += abs(ury - lly);
679 if (lly < *min) *min = lly;
680 if (ury > *max) *max = ury;
681 }
682 }
683
684 for (a = cur_c->arcs; a != NULL; a = a->next) {
685 num_objects++;
686 a->distrib = 0;
687 arc_bound (a, &llx, &lly, &urx, &ury);
688 if (dir == 0) {
689 *sum += abs(urx - llx);
690 if (llx < *min) *min = llx;
691 if (urx > *max) *max = urx;
692 } else {
693 *sum += abs(ury - lly);
694 if (lly < *min) *min = lly;
695 if (ury > *max) *max = ury;
696 }
697 }
698
699 for (l = cur_c->lines; l != NULL; l = l->next) {
700 num_objects++;
701 l->distrib = 0;
702 line_bound (l, &llx, &lly, &urx, &ury);
703 if (dir == 0) {
704 *sum += abs(urx - llx);
705 if (llx < *min) *min = llx;
706 if (urx > *max) *max = urx;
707 } else {
708 *sum += abs(ury - lly);
709 if (lly < *min) *min = lly;
710 if (ury > *max) *max = ury;
711 }
712 }
713
714 for (s = cur_c->splines; s != NULL; s = s->next) {
715 num_objects++;
716 s->distrib = 0;
717 spline_bound (s, &llx, &lly, &urx, &ury);
718 if (dir == 0) {
719 *sum += abs(urx - llx);
720 if (llx < *min) *min = llx;
721 if (urx > *max) *max = urx;
722 } else {
723 *sum += abs(ury - lly);
724 if (lly < *min) *min = lly;
725 if (ury > *max) *max = ury;
726 }
727 }
728
729 for (c = cur_c->compounds; c != NULL; c = c->next) {
730 num_objects++;
731 c->distrib = 0;
732 compound_bound (c, &llx, &lly, &urx, &ury);
733 if (dir == 0) {
734 *sum += abs(urx - llx);
735 if (llx < *min) *min = llx;
736 if (urx > *max) *max = urx;
737 } else {
738 *sum += abs(ury - lly);
739 if (lly < *min) *min = lly;
740 if (ury > *max) *max = ury;
741 }
742 }
743
744 for (t = cur_c->texts; t != NULL; t = t->next) {
745 int dum;
746 num_objects++;
747 t->distrib = 0;
748 text_bound (t, &llx, &lly, &urx, &ury,
749 &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
750 if (dir == 0) {
751 *sum += abs(urx - llx);
752 if (llx < *min) *min = llx;
753 if (urx > *max) *max = urx;
754 } else {
755 *sum += abs(ury - lly);
756 if (lly < *min) *min = lly;
757 if (ury > *max) *max = ury;
758 }
759 }
760
761 return (num_objects);
762 } /* init_distrib_edges */
763
764
765 static void
adjust_object_pos(F_line * obj_ptr,int obj_type,int delta_x,int delta_y)766 adjust_object_pos (F_line *obj_ptr, int obj_type, int delta_x, int delta_y)
767 {
768 F_ellipse *e;
769 F_arc *a;
770 F_line *l;
771 F_spline *s;
772 F_compound *c;
773 F_text *t;
774
775
776 switch (obj_type) {
777 case O_ELLIPSE:
778 e = (F_ellipse *) obj_ptr;
779 translate_ellipse(e, delta_x, delta_y);
780 e->distrib = 1;
781 break;
782 case O_POLYLINE:
783 l = (F_line *) obj_ptr;
784 translate_line(l, delta_x, delta_y);
785 l->distrib = 1;
786 break;
787 case O_SPLINE:
788 s = (F_spline *) obj_ptr;
789 translate_spline(s, delta_x, delta_y);
790 s->distrib = 1;
791 break;
792 case O_TXT:
793 t = (F_text *) obj_ptr;
794 translate_text(t, delta_x, delta_y);
795 t->distrib = 1;
796 break;
797 case O_ARC:
798 a = (F_arc *) obj_ptr;
799 translate_arc(a, delta_x, delta_y);
800 a->distrib = 1;
801 break;
802 case O_COMPOUND:
803 c = (F_compound *) obj_ptr;
804 translate_compound(c, delta_x, delta_y);
805 c->distrib = 1;
806 break;
807 default:
808 break;
809 }
810
811 } /* adjust_object_pos */
812
813 static void
distribute_horizontally(void)814 distribute_horizontally(void)
815 {
816 int num_objects = 0;
817 F_ellipse *e;
818 F_arc *a;
819 F_line *l;
820 F_spline *s;
821 F_compound *c;
822 F_text *t;
823 float inter_obj_space;
824 int min_x, max_x;
825 int obj1, obj2;
826 int obj_type;
827 F_line *obj_ptr;
828 int min_left, min_width;
829 int req_pos;
830 int sum_obj_width;
831
832
833 if (cur_halign == ALIGN_DISTRIB_C)
834 num_objects = init_distrib_centres (&min_x, &max_x, 0);
835 else {
836 num_objects = init_distrib_edges (&min_x, &max_x, &sum_obj_width, 0);
837 req_pos = min_x;
838 }
839 if (num_objects <= 1)
840 return;
841
842 /* Determine the amount of space between objects (centres or edges) */
843 if (cur_halign == ALIGN_DISTRIB_C)
844 inter_obj_space = (float) (max_x - min_x) / (float)(num_objects - 1);
845 else if (cur_halign == ALIGN_DISTRIB_E)
846 inter_obj_space = (float) (max_x - min_x - sum_obj_width) / (float)(num_objects - 1);
847 else
848 inter_obj_space = 0.0;
849
850 /*
851 * Go through all of the objects, finding the left most, then the second
852 * left-most, ...
853 */
854 for (obj1=0; obj1<num_objects; obj1++) {
855 min_left = INT_MAX;
856 for (obj2=0; obj2<num_objects; obj2++) {
857 for (e = cur_c->ellipses; e != NULL; e = e->next)
858 if (pos_ellipse(e, &min_left, &min_width, 0))
859 { obj_ptr = (F_line *) e; obj_type = O_ELLIPSE; }
860 for (a = cur_c->arcs; a != NULL; a = a->next)
861 if (pos_arc(a, &min_left, &min_width, 0))
862 { obj_ptr = (F_line *) a; obj_type = O_ARC; }
863 for (l = cur_c->lines; l != NULL; l = l->next)
864 if (pos_line(l, &min_left, &min_width, 0))
865 { obj_ptr = l; obj_type = O_POLYLINE; }
866 for (s = cur_c->splines; s != NULL; s = s->next)
867 if (pos_spline(s, &min_left, &min_width, 0))
868 { obj_ptr = (F_line *) s; obj_type = O_SPLINE; }
869 for (c = cur_c->compounds; c != NULL; c = c->next)
870 if (pos_compound(c, &min_left, &min_width, 0))
871 { obj_ptr = (F_line *) c; obj_type = O_COMPOUND; }
872 for (t = cur_c->texts; t != NULL; t = t->next)
873 if (pos_text(t, &min_left, &min_width, 0))
874 { obj_ptr = (F_line *) t; obj_type = O_TXT; }
875 }
876
877 /* Determine the new horizontal position of the object */
878 if (cur_halign == ALIGN_DISTRIB_C)
879 req_pos = min_x + (int)((float)obj1 * inter_obj_space);
880
881 /* Adjust position of left-most undistributed object */
882 adjust_object_pos (obj_ptr, obj_type, req_pos - min_left, 0);
883
884 /* Determine the horizontal position of the next object */
885 if ( (cur_halign == ALIGN_DISTRIB_E) || (cur_halign == ALIGN_ABUT) )
886 req_pos += min_width + (int)inter_obj_space;
887 } /* next object */
888 } /* distribute_horizontally */
889
890 static void
distribute_vertically(void)891 distribute_vertically(void)
892 {
893 int num_objects = 0;
894 F_ellipse *e;
895 F_arc *a;
896 F_line *l;
897 F_spline *s;
898 F_compound *c;
899 F_text *t;
900 float inter_obj_space;
901 int min_y, max_y;
902 int obj1, obj2;
903 int obj_type;
904 F_line *obj_ptr;
905 int min_top, min_height;
906 int req_pos;
907 int sum_obj_height;
908
909
910 if (cur_valign == ALIGN_DISTRIB_C)
911 num_objects = init_distrib_centres (&min_y, &max_y, 1);
912 else {
913 num_objects = init_distrib_edges (&min_y, &max_y, &sum_obj_height, 1);
914 req_pos = min_y;
915 }
916 if (num_objects <= 1)
917 return;
918
919 /* Determine the amount of space between objects (centres or edges) */
920 if (cur_valign == ALIGN_DISTRIB_C)
921 inter_obj_space = (float) (max_y - min_y) / (float)(num_objects - 1);
922 else if (cur_valign == ALIGN_DISTRIB_E)
923 inter_obj_space = (float) (max_y - min_y - sum_obj_height) / (float)(num_objects - 1);
924 else
925 inter_obj_space = 0.0;
926
927 /*
928 * Go through all of the objects, finding the top-most, then the second
929 * top-most, ...
930 */
931 for (obj1=0; obj1<num_objects; obj1++) {
932 min_top = INT_MAX;
933 for (obj2=0; obj2<num_objects; obj2++) {
934 for (e = cur_c->ellipses; e != NULL; e = e->next)
935 if (pos_ellipse(e, &min_top, &min_height, 1))
936 { obj_ptr = (F_line *) e; obj_type = O_ELLIPSE; }
937 for (a = cur_c->arcs; a != NULL; a = a->next)
938 if (pos_arc(a, &min_top, &min_height, 1))
939 { obj_ptr = (F_line *) a; obj_type = O_ARC; }
940 for (l = cur_c->lines; l != NULL; l = l->next)
941 if (pos_line(l, &min_top, &min_height, 1))
942 { obj_ptr = (F_line *) l; obj_type = O_POLYLINE; }
943 for (s = cur_c->splines; s != NULL; s = s->next)
944 if (pos_spline(s, &min_top, &min_height, 1))
945 { obj_ptr = (F_line *) s; obj_type = O_SPLINE; }
946 for (c = cur_c->compounds; c != NULL; c = c->next)
947 if (pos_compound(c, &min_top, &min_height, 1))
948 { obj_ptr = (F_line *) c; obj_type = O_COMPOUND; }
949 for (t = cur_c->texts; t != NULL; t = t->next)
950 if (pos_text(t, &min_top, &min_height, 1))
951 { obj_ptr = (F_line *) t; obj_type = O_TXT; }
952 }
953
954 /* Determine the new vertical position of the object */
955 if (cur_valign == ALIGN_DISTRIB_C)
956 req_pos = min_y + (int)((float)obj1 * inter_obj_space);
957
958 /* Adjust position of left-most undistributed object */
959 adjust_object_pos (obj_ptr, obj_type, 0, req_pos - min_top);
960
961 /* Determine the virtical position of the next object */
962 if ((cur_valign == ALIGN_DISTRIB_E) || (cur_valign == ALIGN_ABUT) )
963 req_pos += min_height + (int)inter_obj_space;
964 }
965
966 } /* distribute_vertically */
967
968