libgeda: Remove some exit() calls and assertions.
[geda-gaf/peter-b.git] / libgeda / src / o_box_basic.c
blob144d89c75e2297b8328b8415003a496bf1cb57be
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /*! \file o_box_basic.c
22 * \brief functions for the box object
25 #include <config.h>
26 #include <math.h>
27 #include <stdio.h>
29 #include "libgeda_priv.h"
31 #ifdef HAVE_LIBDMALLOC
32 #include <dmalloc.h>
33 #endif
35 /*! \brief Create a BOX OBJECT
36 * \par Function Description
37 * This function creates a new object representing a box.
39 * The box is described by its upper left corner - <B>x1</B>, <B>y1</B> - and
40 * its lower right corner - <B>x2</B>, <B>y2</B>.
41 * The <B>type</B> parameter must be equal to <B>OBJ_BOX</B>. The <B>color</B>
42 * corresponds to the color the box will be drawn with.
43 * The <B>OBJECT</B> structure is allocated with the #s_basic_new_object()
44 * function. The structure describing the box is allocated and initialized
45 * with the parameters given to the function.
47 * Both the line type and the filling type are set to default values : solid
48 * line type with a width of 0, and no filling. It can be changed after
49 * with the #o_set_line_options() and #o_set_fill_options().
51 * \param [in] toplevel The TOPLEVEL object.
52 * \param [in] type Box type.
53 * \param [in] color Box border color.
54 * \param [in] x1 Upper x coordinate.
55 * \param [in] y1 Upper y coordinate.
56 * \param [in] x2 Lower x coordinate.
57 * \param [in] y2 Lower y coordinate.
58 * \return The new OBJECT
60 OBJECT *o_box_new(TOPLEVEL *toplevel,
61 char type, int color,
62 int x1, int y1, int x2, int y2)
64 OBJECT *new_node;
65 BOX *box;
67 /* create the object */
68 new_node = s_basic_new_object(type, "box");
69 new_node->color = color;
71 box = (BOX *) g_malloc(sizeof(BOX));
72 new_node->box = box;
74 /* describe the box with its upper left and lower right corner */
75 box->upper_x = x1;
76 box->upper_y = y1;
77 box->lower_x = x2;
78 box->lower_y = y2;
80 /* line type and filling initialized to default */
81 o_set_line_options(toplevel, new_node,
82 END_NONE, TYPE_SOLID, 0, -1, -1);
83 o_set_fill_options(toplevel, new_node,
84 FILLING_HOLLOW, -1, -1, -1, -1, -1);
86 /* compute the bounding box */
87 o_box_recalc(toplevel, new_node);
89 return new_node;
92 /*! \brief Copy a box to a list.
93 * \par Function Description
94 * The function #o_box_copy() creates a verbatim copy of the object
95 * pointed by <B>o_current</B> describing a box.
97 * \param [in] toplevel The TOPLEVEL object.
98 * \param [in] o_current BOX OBJECT to copy.
99 * \return The new OBJECT
101 OBJECT *o_box_copy(TOPLEVEL *toplevel, OBJECT *o_current)
103 OBJECT *new_obj;
105 /* A new box object is created with #o_box_new().
106 * Values for its fields are default and need to be modified. */
107 new_obj = o_box_new (toplevel, OBJ_BOX, o_current->color, 0, 0, 0, 0);
110 * The dimensions of the new box are set with the ones of the original box.
111 * The two boxes have the same line type and the same filling options.
113 * The coordinates and the values in world unit are computed with
114 * #o_box_recalc().
117 new_obj->box->upper_x = o_current->box->upper_x;
118 new_obj->box->upper_y = o_current->box->upper_y;
119 new_obj->box->lower_x = o_current->box->lower_x;
120 new_obj->box->lower_y = o_current->box->lower_y;
122 o_set_line_options(toplevel, new_obj, o_current->line_end,
123 o_current->line_type, o_current->line_width,
124 o_current->line_length, o_current->line_space);
125 o_set_fill_options(toplevel, new_obj,
126 o_current->fill_type, o_current->fill_width,
127 o_current->fill_pitch1, o_current->fill_angle1,
128 o_current->fill_pitch2, o_current->fill_angle2);
130 o_box_recalc(toplevel, new_obj);
132 /* new_obj->attribute = 0;*/
134 return new_obj;
137 /*! \brief Modify a BOX OBJECT's coordinates.
138 * \par Function Description
139 * Modifies the coordinates of all four corners of \a box, by setting
140 * the box to the rectangle enclosed by the points (\a x1, \a y1) and
141 * (\a x2, \a y2).
143 * \param [in] toplevel current #TOPLEVEL.
144 * \param [in,out] object box #OBJECT to be modified.
145 * \param [in] x1 x coordinate of first corner of box.
146 * \param [in] y1 y coordinate of first corner of box.
147 * \param [in] x2 x coordinate of second corner of box.
148 * \param [in] y2 y coordinate of second corner of box,
150 void
151 o_box_modify_all (TOPLEVEL *toplevel, OBJECT *object,
152 int x1, int y1, int x2, int y2)
154 o_emit_pre_change_notify (toplevel, object);
156 object->box->lower_x = (x1 > x2) ? x1 : x2;
157 object->box->lower_y = (y1 > y2) ? y2 : y1;
159 object->box->upper_x = (x1 > x2) ? x2 : x1;
160 object->box->upper_y = (y1 > y2) ? y1 : y2;
162 /* recalculate the world coords and bounds */
163 o_box_recalc(toplevel, object);
164 o_emit_change_notify (toplevel, object);
167 /*! \brief Modify a BOX OBJECT's coordinates.
168 * \par Function Description
169 * This function modifies the coordinates of one of the four corner of
170 * the box. The new coordinates of the corner identified by <B>whichone</B>
171 * are given by <B>x</B> and <B>y</B> in world unit.
173 * The coordinates of the corner is modified in the world coordinate system.
174 * Screen coordinates and boundings are then updated.
176 * \param [in] toplevel The TOPLEVEL object.
177 * \param [in,out] object BOX OBJECT to be modified.
178 * \param [in] x x coordinate.
179 * \param [in] y y coordinate.
180 * \param [in] whichone coordinate to change.
182 * \note
183 * <B>whichone</B> can take the following values:
184 * <DL>
185 * <DT>*</DT><DD>BOX_UPPER_LEFT
186 * <DT>*</DT><DD>BOX_LOWER_LEFT
187 * <DT>*</DT><DD>BOX_UPPER_RIGHT
188 * <DT>*</DT><DD>BOX_LOWER_RIGHT
189 * </DL>
191 void o_box_modify(TOPLEVEL *toplevel, OBJECT *object,
192 int x, int y, int whichone)
194 int tmp;
196 o_emit_pre_change_notify (toplevel, object);
198 /* change the position of the selected corner */
199 switch(whichone) {
200 case BOX_UPPER_LEFT:
201 object->box->upper_x = x;
202 object->box->upper_y = y;
203 break;
205 case BOX_LOWER_LEFT:
206 object->box->upper_x = x;
207 object->box->lower_y = y;
208 break;
210 case BOX_UPPER_RIGHT:
211 object->box->lower_x = x;
212 object->box->upper_y = y;
213 break;
215 case BOX_LOWER_RIGHT:
216 object->box->lower_x = x;
217 object->box->lower_y = y;
218 break;
220 default:
221 return;
224 /* need to update the upper left and lower right corners */
225 if(object->box->upper_x > object->box->lower_x) {
226 tmp = object->box->upper_x;
227 object->box->upper_x = object->box->lower_x;
228 object->box->lower_x = tmp;
231 if(object->box->upper_y < object->box->lower_y) {
232 tmp = object->box->upper_y;
233 object->box->upper_y = object->box->lower_y;
234 object->box->lower_y = tmp;
237 /* recalculate the world coords and the boundings */
238 o_box_recalc(toplevel, object);
239 o_emit_change_notify (toplevel, object);
243 /*! \brief Create a box from a character string.
244 * \par Function Description
245 * This function gets the description of a box from the <B>*buf</B> character
246 * string.
248 * Depending on <B>*version</B>, the correct file format is considered.
249 * Currently two file format revisions are supported :
250 * <DL>
251 * <DT>*</DT><DD>the file format used until 20000704 release
252 * <DT>*</DT><DD>the file format used for the releases after 2000704.
253 * </DL>
255 * \param [in] toplevel The TOPLEVEL object.
256 * \param [in] buf Character string with box description.
257 * \param [in] release_ver libgeda release version number.
258 * \param [in] fileformat_ver libgeda file format version number.
259 * \return The BOX OBJECT that was created.
261 OBJECT *o_box_read (TOPLEVEL *toplevel, char buf[],
262 unsigned int release_ver, unsigned int fileformat_ver)
264 OBJECT *new_obj;
265 char type;
266 int x1, y1;
267 int width, height;
268 int d_x1, d_y1;
269 int d_x2, d_y2;
270 int color;
271 int box_width, box_space, box_length;
272 int fill_width, angle1, pitch1, angle2, pitch2;
273 int box_end;
274 int box_type;
275 int box_filling;
277 if (release_ver <= VERSION_20000704) {
279 /*! \note
280 * The old geda file format, i.e. releases 20000704 and older, does not
281 * handle the line type and the filling of the box object. They are set
282 * to default.
285 sscanf (buf, "%c %d %d %d %d %d\n",
286 &type, &x1, &y1, &width, &height, &color);
288 box_width = 0;
289 box_end = END_NONE;
290 box_type = TYPE_SOLID;
291 box_length = -1;
292 box_space = -1;
294 box_filling = FILLING_HOLLOW;
295 fill_width = 0;
296 angle1 = -1;
297 pitch1 = -1;
298 angle2 = -1;
299 pitch2 = -1;
301 } else {
303 /*! \note
304 * The current line format to describe a box is a space separated list of
305 * characters and numbers in plain ASCII on a single line. The meaning of
306 * each item is described in the file format documentation.
308 sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
309 &type, &x1, &y1, &width, &height, &color,
310 &box_width, &box_end, &box_type, &box_length,
311 &box_space, &box_filling,
312 &fill_width, &angle1, &pitch1, &angle2, &pitch2);
315 if (width == 0 || height == 0) {
316 s_log_message (_("Found a zero width/height box [ %c %d %d %d %d %d ]\n"),
317 type, x1, y1, width, height, color);
320 if (color < 0 || color > MAX_COLORS) {
321 s_log_message (_("Found an invalid color [ %s ]\n"), buf);
322 s_log_message (_("Setting color to default color\n"));
323 color = DEFAULT_COLOR;
326 /*! \note
327 * A box is internally described by its lower right and upper left corner
328 * whereas the line describe it with the lower left corner and the width
329 * and height.
331 * A new object is allocated, initialized and added to the object list.
332 * Its filling and line type are set according to the values of the field
333 * on the line.
336 /* upper left corner of the box */
337 d_x1 = x1;
338 d_y1 = y1 + height; /* move box origin to top left */
340 /* lower right corner of the box */
341 d_x2 = x1 + width; /* end points of the box */
342 d_y2 = y1;
344 /* create a new box */
345 new_obj = o_box_new (toplevel, type, color, d_x1, d_y1, d_x2, d_y2);
346 /* set its line options */
347 o_set_line_options (toplevel, new_obj,
348 box_end, box_type, box_width,
349 box_length, box_space);
350 /* set its fill options */
351 o_set_fill_options (toplevel, new_obj,
352 box_filling, fill_width,
353 pitch1, angle1, pitch2, angle2);
355 return new_obj;
358 /*! \brief Create a character string representation of a BOX.
359 * \par Function Description
360 * This function formats a string in the buffer <B>*buff</B> to describe the
361 * box object <B>*object</B>.
362 * It follows the post-20000704 release file format that handle the line type
363 * and fill options.
365 * \param [in] toplevel The TOPLEVEL structure.
366 * \param [in] object The BOX OBJECT to create string from.
367 * \return A pointer to the BOX character string.
369 * \warning
370 * Caller must g_free returned character string.
372 char *o_box_save(TOPLEVEL *toplevel, OBJECT *object)
374 int x1, y1;
375 int width, height;
376 int box_width, box_space, box_length;
377 int fill_width, angle1, pitch1, angle2, pitch2;
378 OBJECT_END box_end;
379 OBJECT_TYPE box_type;
380 OBJECT_FILLING box_fill;
381 char *buf;
383 /*! \note
384 * A box is internally represented by its lower right and upper left corner
385 * whereas it is described in the file format as its lower left corner and
386 * its width and height.
389 /* calculate the width and height of the box */
390 width = abs(object->box->lower_x - object->box->upper_x);
391 height = abs(object->box->upper_y - object->box->lower_y);
393 /* calculate the lower left corner of the box */
394 x1 = object->box->upper_x;
395 y1 = object->box->upper_y - height; /* move the origin to 0, 0*/
397 #if DEBUG
398 printf("box: %d %d %d %d\n", x1, y1, width, height);
399 #endif
401 /* description of the line type for the outline */
402 box_end = object->line_end;
403 box_width = object->line_width;
404 box_type = object->line_type;
405 box_length = object->line_length;
406 box_space = object->line_space;
408 /* description of the filling of the box */
409 box_fill = object->fill_type;
410 fill_width = object->fill_width;
411 angle1 = object->fill_angle1;
412 pitch1 = object->fill_pitch1;
413 angle2 = object->fill_angle2;
414 pitch2 = object->fill_pitch2;
416 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
417 object->type,
418 x1, y1, width, height, object->color,
419 box_width, box_end, box_type, box_length, box_space,
420 box_fill,
421 fill_width, angle1, pitch1, angle2, pitch2);
423 return(buf);
426 /*! \brief Translate a BOX position in WORLD coordinates by a delta.
427 * \par Function Description
428 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the box
429 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
431 * \param [in] toplevel The TOPLEVEL object.
432 * \param [in] dx x distance to move.
433 * \param [in] dy y distance to move.
434 * \param [in,out] object BOX OBJECT to translate.
436 void o_box_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object)
438 if (object == NULL) printf("btw NO!\n");
440 /* Do world coords */
441 object->box->upper_x = object->box->upper_x + dx;
442 object->box->upper_y = object->box->upper_y + dy;
443 object->box->lower_x = object->box->lower_x + dx;
444 object->box->lower_y = object->box->lower_y + dy;
446 /* recalc the screen coords and the bounding box */
447 o_box_recalc(toplevel, object);
450 /*! \brief Rotate BOX OBJECT using WORLD coordinates.
451 * \par Function Description
452 * The function #o_box_rotate_world() rotate the box described by
453 * <B>*object</B> around the (<B>world_centerx</B>, <B>world_centery</B>) point by
454 * <B>angle</B> degrees.
455 * The center of rotation is in world unit.
457 * \param [in] toplevel The TOPLEVEL object.
458 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
459 * \param [in] world_centery Rotation center y coordinate in WORLD units.
460 * \param [in] angle Rotation angle in degrees (See note below).
461 * \param [in,out] object BOX OBJECT to rotate.
464 void o_box_rotate_world(TOPLEVEL *toplevel,
465 int world_centerx, int world_centery, int angle,
466 OBJECT *object)
468 int newx1, newy1;
469 int newx2, newy2;
471 /*! \note
472 * Only 90 degree multiple and positive angles are allowed.
475 /* angle must be positive */
476 if(angle < 0) angle = -angle;
477 /* angle must be a 90 multiple or no rotation performed */
478 if((angle % 90) != 0) return;
480 /*! \note
481 * The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is
482 * translated to the origin. The rotation of the upper left and lower right
483 * corner are then performed. Finally, the rotated box is translated back
484 * to its previous location.
486 /* translate object to origin */
487 object->box->upper_x -= world_centerx;
488 object->box->upper_y -= world_centery;
489 object->box->lower_x -= world_centerx;
490 object->box->lower_y -= world_centery;
492 /* rotate the upper left corner of the box */
493 rotate_point_90(object->box->upper_x, object->box->upper_y, angle,
494 &newx1, &newy1);
496 /* rotate the lower left corner of the box */
497 rotate_point_90(object->box->lower_x, object->box->lower_y, angle,
498 &newx2, &newy2);
500 /* reorder the corners after rotation */
501 object->box->upper_x = min(newx1,newx2);
502 object->box->upper_y = max(newy1,newy2);
503 object->box->lower_x = max(newx1,newx2);
504 object->box->lower_y = min(newy1,newy2);
506 /* translate object back to normal position */
507 object->box->upper_x += world_centerx;
508 object->box->upper_y += world_centery;
509 object->box->lower_x += world_centerx;
510 object->box->lower_y += world_centery;
512 /* recalc boundings and world coords */
513 o_box_recalc(toplevel, object);
516 /*! \brief Mirror BOX using WORLD coordinates.
517 * \par Function Description
518 * This function mirrors the box from the point
519 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
521 * The box is first translated to the origin, then mirrored and finally
522 * translated back at its previous position.
524 * \param [in] toplevel The TOPLEVEL object.
525 * \param [in] world_centerx Origin x coordinate in WORLD units.
526 * \param [in] world_centery Origin y coordinate in WORLD units.
527 * \param [in,out] object BOX OBJECT to mirror.
529 void o_box_mirror_world(TOPLEVEL *toplevel,
530 int world_centerx, int world_centery,
531 OBJECT *object)
533 int newx1, newy1;
534 int newx2, newy2;
536 /* translate object to origin */
537 object->box->upper_x -= world_centerx;
538 object->box->upper_y -= world_centery;
539 object->box->lower_x -= world_centerx;
540 object->box->lower_y -= world_centery;
542 /* mirror the corners */
543 newx1 = -object->box->upper_x;
544 newy1 = object->box->upper_y;
545 newx2 = -object->box->lower_x;
546 newy2 = object->box->lower_y;
548 /* reorder the corners */
549 object->box->upper_x = min(newx1,newx2);
550 object->box->upper_y = max(newy1,newy2);
551 object->box->lower_x = max(newx1,newx2);
552 object->box->lower_y = min(newy1,newy2);
554 /* translate back in position */
555 object->box->upper_x += world_centerx;
556 object->box->upper_y += world_centery;
557 object->box->lower_x += world_centerx;
558 object->box->lower_y += world_centery;
560 /* recalc boundings and world coords */
561 o_box_recalc(toplevel, object);
565 /*! \brief Recalculate BOX coordinates in WORLD units.
566 * \par Function Description
567 * This function recalculates the box coordinates and its
568 * bounding are recalculated as well.
570 * \param [in] toplevel The TOPLEVEL object.
571 * \param [in,out] o_current BOX OBJECT to be recalculated.
573 void o_box_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
575 int left, top, right, bottom;
577 if (o_current->box == NULL) {
578 return;
581 /* update the bounding box - world unit */
582 world_get_box_bounds(toplevel, o_current, &left, &top, &right, &bottom);
583 o_current->w_left = left;
584 o_current->w_top = top;
585 o_current->w_right = right;
586 o_current->w_bottom = bottom;
587 o_current->w_bounds_valid = TRUE;
590 /*! \brief Get BOX bounding rectangle in WORLD coordinates.
591 * \par Function Description
592 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
593 * parameters to the boundings of the box object described in <B>*box</B>
594 * in world units.
596 * \param [in] toplevel The TOPLEVEL object.
597 * \param [in] object BOX OBJECT to read coordinates from.
598 * \param [out] left Left box coordinate in WORLD units.
599 * \param [out] top Top box coordinate in WORLD units.
600 * \param [out] right Right box coordinate in WORLD units.
601 * \param [out] bottom Bottom box coordinate in WORLD units.
603 void world_get_box_bounds(TOPLEVEL *toplevel, OBJECT *object,
604 int *left, int *top, int *right, int *bottom)
606 int halfwidth;
608 halfwidth = object->line_width / 2;
610 *left = min(object->box->upper_x, object->box->lower_x);
611 *top = min(object->box->upper_y, object->box->lower_y);
612 *right = max(object->box->upper_x, object->box->lower_x);
613 *bottom = max(object->box->upper_y, object->box->lower_y);
615 /* This isn't strictly correct, but a 1st order approximation */
616 *left -= halfwidth;
617 *top -= halfwidth;
618 *right += halfwidth;
619 *bottom += halfwidth;
622 /*! \brief get the position of the left bottom point
623 * \par Function Description
624 * This function gets the position of the bottom left point of a box object.
626 * \param [in] toplevel The toplevel environment.
627 * \param [out] x pointer to the x-position
628 * \param [out] y pointer to the y-position
629 * \param [in] object The object to get the position.
630 * \return TRUE if successfully determined the position, FALSE otherwise
632 gboolean o_box_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
633 OBJECT *object)
635 *x = min(object->box->lower_x, object->box->upper_x);
636 *y = min(object->box->lower_y, object->box->upper_y);
637 return TRUE;
640 /*! \brief Print BOX to Postscript document.
641 * \par Function Description
642 * This function prints the box described by the <B>o_current</B>
643 * parameter to a Postscript document. It takes into account its line
644 * type and fill type.
645 * The Postscript document is descibed by the file pointer <B>fp</B>.
647 * The validity of the <B>o_current</B> parameter is verified : a null pointer
648 * causes an error message and a return.
650 * The description of the box is extracted from
651 * the <B>o_current</B> parameter :
652 * the coordinates of the box - upper left corner and width and
653 * height of the box -, its line type, its fill type.
655 * The outline and the inside of the box are successively handled by two
656 * differend sets of functions.
658 * \param [in] toplevel The TOPLEVEL object.
659 * \param [in] fp FILE pointer to Postscript document.
660 * \param [in] o_current BOX OBJECT to write to document.
661 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
662 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
664 void o_box_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
665 int origin_x, int origin_y)
667 int x, y, width, height;
668 int color;
669 int line_width, length, space;
670 int fill_width, angle1, pitch1, angle2, pitch2;
671 void (*outl_func)() = NULL;
672 void (*fill_func)() = NULL;
674 if (o_current == NULL) {
675 printf("got null in o_box_print\n");
676 return;
679 x = o_current->box->upper_x;
680 y = o_current->box->upper_y;
681 width = abs(o_current->box->lower_x - o_current->box->upper_x);
682 height = abs(o_current->box->lower_y - o_current->box->upper_y);
683 color = o_current->color;
685 /*! \note
686 * Depending on the type of the line for this particular box, the
687 * appropriate function is chosen among #o_box_print_solid(),
688 * #o_box_print_dotted(), #o_box_print_dashed(),
689 * #o_box_print_center() and #o_box_print_phantom().
691 * The needed parameters for each of these type is extracted from the
692 * <B>o_current</B> object. Depending on the type, unused parameters are
693 * set to -1.
695 * In the eventuality of a length and/or space null, the line is printed
696 * solid to avoid and endless loop produced by other functions in such a
697 * case.
699 line_width = o_current->line_width;
701 if(line_width <=2) {
702 if(toplevel->line_style == THICK) {
703 line_width=LINE_WIDTH;
704 } else {
705 line_width=2;
708 length = o_current->line_length;
709 space = o_current->line_space;
711 switch(o_current->line_type) {
712 case(TYPE_SOLID):
713 length = -1; space = -1;
714 outl_func = o_box_print_solid;
715 break;
717 case(TYPE_DOTTED):
718 length = -1;
719 outl_func = o_box_print_dotted;
720 break;
722 case(TYPE_DASHED):
723 outl_func = o_box_print_dashed;
724 break;
726 case(TYPE_CENTER):
727 outl_func = o_box_print_center;
728 break;
730 case(TYPE_PHANTOM):
731 outl_func = o_box_print_phantom;
732 break;
734 case(TYPE_ERASE):
735 /* Unused for now, print it solid */
736 length = -1; space = -1;
737 outl_func = o_box_print_solid;
738 break;
741 if((length == 0) || (space == 0)) {
742 length = -1; space = -1;
743 outl_func = o_box_print_solid;
746 (*outl_func)(toplevel, fp,
747 x, y, width, height,
748 color,
749 line_width,
750 length, space,
751 origin_x, origin_y);
753 /*! \note
754 * If the filling type of the box is not <B>HOLLOW</B>, the appropriate
755 * function is chosen among #o_box_print_filled(), #o_box_print_mesh()
756 * and #o_box_print_hatch(). The corresponding parameters are extracted
757 * from the <B>o_current</B> object and corrected afterward.
759 * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
760 * avoided as it leads to an endless loop in most of the called functions.
761 * In such a case, the box is printed filled. Unused parameters for each of
762 * these functions are set to -1 or any passive value.
764 if(o_current->fill_type != FILLING_HOLLOW) {
765 fill_width = o_current->fill_width;
766 angle1 = o_current->fill_angle1;
767 pitch1 = o_current->fill_pitch1;
768 angle2 = o_current->fill_angle2;
769 pitch2 = o_current->fill_pitch2;
771 switch(o_current->fill_type) {
772 case(FILLING_FILL):
773 angle1 = -1; pitch1 = 1;
774 angle2 = -1; pitch2 = 1;
775 fill_width = -1;
776 fill_func = o_box_print_filled;
777 break;
779 case(FILLING_MESH):
780 fill_func = o_box_print_mesh;
781 break;
783 case(FILLING_HATCH):
784 angle2 = -1; pitch2 = 1;
785 fill_func = o_box_print_hatch;
786 break;
788 case(FILLING_VOID):
789 /* Unused for now, print it filled */
790 angle1 = -1; pitch1 = 1;
791 angle2 = -1; pitch2 = 1;
792 fill_width = -1;
793 fill_func = o_box_print_filled;
794 break;
795 case(FILLING_HOLLOW):
796 /* nop */
797 break;
801 if((pitch1 <= 0) || (pitch2 <= 0)) {
802 angle1 = -1; pitch1 = 1;
803 angle2 = -1; pitch2 = 1;
804 fill_func = o_box_print_filled;
807 (*fill_func)(toplevel, fp,
808 x, y, width, height,
809 color,
810 fill_width,
811 angle1, pitch1, angle2, pitch2,
812 origin_x, origin_y);
816 /*! \brief Print a solid BOX to Postscript document.
817 * \par Function Description
818 * This function prints the outline of a box when a solid line type is
819 * required. The box is defined by the coordinates of its upper left corner
820 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
821 * <B>height</B> parameters.
822 * The postscript file is defined by the file pointer <B>fp</B>.
823 * The parameters <B>length</B> and <B>space</B> are ignored.
825 * It uses the function #o_line_print_solid() to print the outline.
826 * It performs four calls to this function, one for each of its side.
828 * All dimensions are in mils.
830 * \param [in] toplevel The TOPLEVEL object.
831 * \param [in] fp FILE pointer to Postscript document.
832 * \param [in] x Upper x coordinate of BOX.
833 * \param [in] y Upper y coordinate of BOX.
834 * \param [in] width Width of BOX.
835 * \param [in] height Height of BOX.
836 * \param [in] color BOX color.
837 * \param [in] line_width BOX Line width.
838 * \param [in] length Dashed line length.
839 * \param [in] space Amount of space between dashes.
840 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
841 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
843 void
844 o_box_print_solid(TOPLEVEL *toplevel, FILE *fp,
845 int x, int y,
846 int width, int height,
847 int color,
848 int line_width, int length, int space,
849 int origin_x, int origin_y)
851 int x1, y1;
853 f_print_set_color(toplevel, fp, color);
855 x1 = x;
856 y1 = y - height; /* move the origin to 0, 0*/
858 o_line_print_solid(toplevel, fp,
859 x1, y1, x1 + width, y1,
860 color,
861 line_width, length, space,
862 origin_x, origin_y);
863 o_line_print_solid(toplevel, fp,
864 x1 + width, y1, x1 + width, y1 + height,
865 color,
866 line_width, length, space,
867 origin_x, origin_y);
868 o_line_print_solid(toplevel, fp,
869 x1 + width, y1 + height, x1, y1 + height,
870 color,
871 line_width, length, space,
872 origin_x, origin_y);
873 o_line_print_solid(toplevel, fp,
874 x1, y1 + height, x1, y1,
875 color,
876 line_width, length, space,
877 origin_x, origin_y);
880 /*! \brief Print a dotted BOX to Postscript document.
881 * \par Function Description
882 * This function prints the outline of a box when a dotted line type is
883 * required. The box is defined by the coordinates of its upper left corner
884 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
885 * <B>height</B> parameters.
886 * The postscript file is defined by the file pointer <B>fp</B>.
887 * The parameters <B>length</B> is ignored.
889 * It uses the function #o_line_print_dotted() to print the outline.
890 * It performs four calls to this function, one for each of its side.
892 * All dimensions are in mils.
894 * \param [in] toplevel The TOPLEVEL object.
895 * \param [in] fp FILE pointer to Postscript document.
896 * \param [in] x Upper x coordinate of BOX.
897 * \param [in] y Upper y coordinate of BOX.
898 * \param [in] width Width of BOX.
899 * \param [in] height Height of BOX.
900 * \param [in] color BOX color.
901 * \param [in] line_width BOX Line width.
902 * \param [in] length Dashed line length.
903 * \param [in] space Amount of space between dashes.
904 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
905 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
907 void o_box_print_dotted(TOPLEVEL *toplevel, FILE *fp,
908 int x, int y,
909 int width, int height,
910 int color,
911 int line_width, int length, int space,
912 int origin_x, int origin_y)
914 int x1, y1;
916 f_print_set_color(toplevel, fp, color);
918 x1 = x;
919 y1 = y - height; /* move the origin to 0, 0*/
921 o_line_print_dotted(toplevel, fp,
922 x1, y1, x1 + width, y1,
923 color,
924 line_width, length, space,
925 origin_x, origin_y);
926 o_line_print_dotted(toplevel, fp,
927 x1 + width, y1, x1 + width, y1 + height,
928 color,
929 line_width, length, space,
930 origin_x, origin_y);
931 o_line_print_dotted(toplevel, fp,
932 x1 + width, y1 + height, x1, y1 + height,
933 color,
934 line_width, length, space,
935 origin_x, origin_y);
936 o_line_print_dotted(toplevel, fp,
937 x1, y1 + height, x1, y1,
938 color,
939 line_width, length, space,
940 origin_x, origin_y);
943 /*! \brief Print a dashed BOX to Postscript document.
944 * \par Function Description
945 * This function prints the outline of a box when a dashed line type is
946 * required. The box is defined by the coordinates of its upper left corner
947 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
948 * <B>height</B> parameters.
949 * The postscript file is defined by the file pointer <B>fp</B>.
951 * It uses the function #o_line_print_dashed() to print the outline.
952 * It performs four calls to this function, one for each of its side.
954 * All dimensions are in mils.
956 * \param [in] toplevel The TOPLEVEL object.
957 * \param [in] fp FILE pointer to Postscript document.
958 * \param [in] x Upper x coordinate of BOX.
959 * \param [in] y Upper y coordinate of BOX.
960 * \param [in] width Width of BOX.
961 * \param [in] height Height of BOX.
962 * \param [in] color BOX color.
963 * \param [in] line_width BOX Line width.
964 * \param [in] length Dashed line length.
965 * \param [in] space Amount of space between dashes.
966 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
967 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
969 void o_box_print_dashed(TOPLEVEL *toplevel, FILE *fp,
970 int x, int y,
971 int width, int height,
972 int color,
973 int line_width, int length, int space,
974 int origin_x, int origin_y)
976 int x1, y1;
978 f_print_set_color(toplevel, fp, color);
981 x1 = x;
982 y1 = y - height; /* move the origin to 0, 0*/
984 o_line_print_dashed(toplevel, fp,
985 x1, y1, x1 + width, y1,
986 color,
987 line_width, length, space,
988 origin_x, origin_y);
989 o_line_print_dashed(toplevel, fp,
990 x1 + width, y1, x1 + width, y1 + height,
991 color,
992 line_width, length, space,
993 origin_x, origin_y);
994 o_line_print_dashed(toplevel, fp,
995 x1 + width, y1 + height, x1, y1 + height,
996 color,
997 line_width, length, space,
998 origin_x, origin_y);
999 o_line_print_dashed(toplevel, fp,
1000 x1, y1 + height, x1, y1,
1001 color,
1002 line_width, length, space,
1003 origin_x, origin_y);
1006 /*! \brief Print centered line type BOX to Postscript document.
1007 * \par Function Description
1008 * This function prints the outline of a box when a centered line type is
1009 * required. The box is defined by the coordinates of its upper left corner
1010 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1011 * <B>height</B> parameters.
1012 * The postscript file is defined by the file pointer <B>fp</B>.
1014 * It uses the function #o_line_print_center() to print the outline.
1015 * It performs four calls to this function, one for each of its side.
1017 * All dimensions are in mils.
1019 * \param [in] toplevel The TOPLEVEL object.
1020 * \param [in] fp FILE pointer to Postscript document.
1021 * \param [in] x Upper x coordinate of BOX.
1022 * \param [in] y Upper y coordinate of BOX.
1023 * \param [in] width Width of BOX.
1024 * \param [in] height Height of BOX.
1025 * \param [in] color BOX color.
1026 * \param [in] line_width BOX Line width.
1027 * \param [in] length Dashed line length.
1028 * \param [in] space Amount of space between dashes.
1029 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1030 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1032 void o_box_print_center(TOPLEVEL *toplevel, FILE *fp,
1033 int x, int y,
1034 int width, int height,
1035 int color,
1036 int line_width, int length, int space,
1037 int origin_x, int origin_y)
1039 int x1, y1;
1041 f_print_set_color(toplevel, fp, color);
1043 x1 = x;
1044 y1 = y - height; /* move the origin to 0, 0*/
1046 o_line_print_center(toplevel, fp,
1047 x1, y1, x1 + width, y1,
1048 color,
1049 line_width, length, space,
1050 origin_x, origin_y);
1051 o_line_print_center(toplevel, fp,
1052 x1 + width, y1, x1 + width, y1 + height,
1053 color,
1054 line_width, length, space,
1055 origin_x, origin_y);
1056 o_line_print_center(toplevel, fp,
1057 x1 + width, y1 + height, x1, y1 + height,
1058 color,
1059 line_width, length, space,
1060 origin_x, origin_y);
1061 o_line_print_center(toplevel, fp,
1062 x1, y1 + height, x1, y1,
1063 color,
1064 line_width, length, space,
1065 origin_x, origin_y);
1068 /*! \brief Print phantom line type BOX to Postscript document.
1069 * \par Function Description
1070 * This function prints the outline of a box when a phantom line type is
1071 * required. The box is defined by the coordinates of its upper left corner
1072 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1073 * <B>height</B> parameters.
1074 * The postscript file is defined by the file pointer <B>fp</B>.
1076 * It uses the function #o_line_print_phantom() to print the outline.
1077 * It performs four calls to this function, one for each of its side.
1079 * All dimensions are in mils.
1081 * \param [in] toplevel The TOPLEVEL object.
1082 * \param [in] fp FILE pointer to Postscript document.
1083 * \param [in] x Upper x coordinate of BOX.
1084 * \param [in] y Upper y coordinate of BOX.
1085 * \param [in] width Width of BOX.
1086 * \param [in] height Height of BOX.
1087 * \param [in] color BOX color.
1088 * \param [in] line_width BOX Line width.
1089 * \param [in] length Dashed line length.
1090 * \param [in] space Amount of space between dashes.
1091 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1092 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1094 void o_box_print_phantom(TOPLEVEL *toplevel, FILE *fp,
1095 int x, int y,
1096 int width, int height,
1097 int color,
1098 int line_width, int length, int space,
1099 int origin_x, int origin_y)
1101 int x1, y1;
1103 f_print_set_color(toplevel, fp, color);
1105 x1 = x;
1106 y1 = y - height; /* move the origin to 0, 0*/
1108 o_line_print_phantom(toplevel, fp,
1109 x1, y1, x1 + width, y1,
1110 color,
1111 line_width, length, space,
1112 origin_x, origin_y);
1113 o_line_print_phantom(toplevel, fp,
1114 x1 + width, y1, x1 + width, y1 + height,
1115 color,
1116 line_width, length, space,
1117 origin_x, origin_y);
1118 o_line_print_phantom(toplevel, fp,
1119 x1 + width, y1 + height, x1, y1 + height,
1120 color,
1121 line_width, length, space,
1122 origin_x, origin_y);
1123 o_line_print_phantom(toplevel, fp,
1124 x1, y1 + height, x1, y1,
1125 color,
1126 line_width, length, space,
1127 origin_x, origin_y);
1130 /*! \brief Print a solid pattern BOX to Postscript document.
1131 * \par Function Description
1132 * The function prints a filled box with a solid pattern. No outline is
1133 * printed.
1134 * The box is defined by the coordinates of its upper left corner in
1135 * (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1136 * <B>height</B> parameters. The postscript file is defined by the file
1137 * pointer <B>fp</B>.
1138 * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B> and <B>pitch2</B>
1139 * parameters are ignored in this functions but kept for compatibility
1140 * with other fill functions.
1142 * It uses the fbox postscript function defined in the prolog to
1143 * specify a filled box.
1145 * All dimensions are in mils.
1147 * \param [in] toplevel The TOPLEVEL object.
1148 * \param [in] fp FILE pointer to Postscript document.
1149 * \param [in] x Upper x coordinate of BOX.
1150 * \param [in] y Upper y coordinate of BOX.
1151 * \param [in] width Width of BOX.
1152 * \param [in] height Height of BOX.
1153 * \param [in] color BOX color.
1154 * \param [in] fill_width BOX fill width. (unused).
1155 * \param [in] angle1 (unused).
1156 * \param [in] pitch1 (unused).
1157 * \param [in] angle2 (unused).
1158 * \param [in] pitch2 (unused).
1159 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1160 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1162 void o_box_print_filled(TOPLEVEL *toplevel, FILE *fp,
1163 int x, int y,
1164 int width, int height,
1165 int color,
1166 int fill_width,
1167 int angle1, int pitch1,
1168 int angle2, int pitch2,
1169 int origin_x, int origin_y)
1171 int x1, y1;
1173 f_print_set_color(toplevel, fp, color);
1175 x1 = x;
1176 y1 = y-height; /* move the origin to 0, 0*/
1177 fprintf(fp, "%d %d %d %d fbox\n",
1178 width, height,
1179 x1-origin_x, y1-origin_y);
1183 /*! \brief Print a mesh pattern BOX to Postscript document.
1184 * \par Function Description
1185 * This function prints a meshed box. No outline is printed. The box is
1186 * defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
1187 * its width and height given by the <B>width</B> and <B>height</B> parameters.
1188 * The postscript file is defined by the file pointer <B>fp</B>.
1190 * The inside mesh is achieved by two successive call to the
1191 * #o_box_print_hatch() function, given <B>angle1</B> and <B>pitch1</B> the first
1192 * time and <B>angle2</B> and <B>pitch2</B> the second time.
1194 * Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are not allowed
1195 * as it leads to an endless loop in #o_box_print_hatch().
1197 * All dimensions are in mils.
1199 * \param [in] toplevel The TOPLEVEL object.
1200 * \param [in] fp FILE pointer to Postscript document.
1201 * \param [in] x Upper x coordinate of BOX.
1202 * \param [in] y Upper y coordinate of BOX.
1203 * \param [in] width Width of BOX.
1204 * \param [in] height Height of BOX.
1205 * \param [in] color BOX color.
1206 * \param [in] fill_width BOX fill width.
1207 * \param [in] angle1 1st angle for mesh pattern.
1208 * \param [in] pitch1 1st pitch for mesh pattern.
1209 * \param [in] angle2 2nd angle for mesh pattern.
1210 * \param [in] pitch2 2nd pitch for mesh pattern.
1211 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1212 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1214 void o_box_print_mesh(TOPLEVEL *toplevel, FILE *fp,
1215 int x, int y,
1216 int width, int height,
1217 int color,
1218 int fill_width,
1219 int angle1, int pitch1,
1220 int angle2, int pitch2,
1221 int origin_x, int origin_y)
1223 o_box_print_hatch(toplevel, fp,
1224 x, y, width, height,
1225 color,
1226 fill_width,
1227 angle1, pitch1, -1, -1,
1228 origin_x, origin_y);
1229 o_box_print_hatch(toplevel, fp,
1230 x, y, width, height,
1231 color,
1232 fill_width,
1233 angle2, pitch2, -1, -1,
1234 origin_x, origin_y);
1238 /*! \brief Print a hatch pattern BOX to Postscript document.
1239 * \par Function Description
1240 * The function prints a hatched box. No outline is printed. The box is
1241 * defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
1242 * its width and height given by the <B>width</B> and <B>height</B> parameters.
1243 * The postscript file is defined by the file pointer <B>fp</B>.
1244 * <B>fill_width</B>, <B>angle1</B>, <B>pitch1</B> parameters define the way the box
1245 * has to be hatched.
1246 * <B>angle2</B> and <B>pitch2</B> parameters are unused but kept for compatibility
1247 * with other fill functions.
1249 * Negative or null values for <B>pitch1</B> are not allowed as it leads to an
1250 * endless loop.
1252 * All dimensions are in mils.
1254 * \param [in] toplevel The TOPLEVEL object.
1255 * \param [in] fp FILE pointer to Postscript document.
1256 * \param [in] x Upper x coordinate of BOX.
1257 * \param [in] y Upper y coordinate of BOX.
1258 * \param [in] width Width of BOX.
1259 * \param [in] height Height of BOX.
1260 * \param [in] color BOX color.
1261 * \param [in] fill_width BOX fill width.
1262 * \param [in] angle1 Angle of hatch pattern.
1263 * \param [in] pitch1 Pitch of hatch pattern.
1264 * \param [in] angle2 (unused).
1265 * \param [in] pitch2 (unused).
1266 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1267 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1269 void o_box_print_hatch(TOPLEVEL *toplevel, FILE *fp,
1270 int x, int y,
1271 int width, int height,
1272 int color,
1273 int fill_width,
1274 int angle1, int pitch1,
1275 int angle2, int pitch2,
1276 int origin_x, int origin_y)
1278 BOX box;
1279 gint index;
1280 GArray *lines;
1282 g_return_if_fail(toplevel != NULL);
1283 g_return_if_fail(fp != NULL);
1285 f_print_set_color(toplevel, fp, color);
1287 /* Avoid printing line widths too small */
1288 if (fill_width <= 1) fill_width = 2;
1290 lines = g_array_new(FALSE, FALSE, sizeof(LINE));
1292 box.upper_x = x;
1293 box.upper_y = y;
1294 box.lower_x = x + width;
1295 box.lower_y = y - height; /* Hmmm... */
1297 m_hatch_box(&box, angle1, pitch1, lines);
1299 for(index=0; index<lines->len; index++) {
1300 LINE *line = &g_array_index(lines, LINE, index);
1302 fprintf(fp,"%d %d %d %d %d line\n",
1303 line->x[0], line->y[0],
1304 line->x[1], line->y[1],
1305 fill_width);
1308 g_array_free(lines, TRUE);
1311 /*! \brief Calculates the distance between the given point and the closest
1312 * point on the perimeter of the box.
1314 * \param [in] object The box OBJECT.
1315 * \param [in] x The x coordinate of the given point.
1316 * \param [in] y The y coordinate of the given point.
1317 * \param [in] force_solid If true, force treating the object as solid.
1318 * \return The shortest distance from the object to the point. With an
1319 * invalid parameter, this function returns G_MAXDOUBLE.
1321 double o_box_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1323 int solid;
1325 g_return_val_if_fail (object->box != NULL, G_MAXDOUBLE);
1327 solid = force_solid || object->fill_type != FILLING_HOLLOW;
1329 return m_box_shortest_distance (object->box, x, y, solid);