Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / libgeda / src / o_box_basic.c
blob32608644981d16ff10221da64721959c2fa710d2
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., 59 Temple Place, Suite 330, Boston, MA 02111 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 /*! Default setting for draw function. */
36 void (*box_draw_func)() = NULL;
38 /*! \brief Create a BOX OBJECT
39 * \par Function Description
40 * This function creates a new object representing a box.
42 * The box is described by its upper left corner - <B>x1</B>, <B>y1</B> - and
43 * its lower right corner - <B>x2</B>, <B>y2</B>.
44 * The <B>type</B> parameter must be equal to <B>OBJ_BOX</B>. The <B>color</B>
45 * corresponds to the color the box will be drawn with.
46 * The <B>OBJECT</B> structure is allocated with the #s_basic_new_object()
47 * function. The structure describing the box is allocated and initialized
48 * with the parameters given to the function.
50 * Both the line type and the filling type are set to default values : solid
51 * line type with a width of 0, and no filling. It can be changed after
52 * with the #o_set_line_options() and #o_set_fill_options().
54 * \param [in] toplevel The TOPLEVEL object.
55 * \param [in] type Box type.
56 * \param [in] color Box border color.
57 * \param [in] x1 Upper x coordinate.
58 * \param [in] y1 Upper y coordinate.
59 * \param [in] x2 Lower x coordinate.
60 * \param [in] y2 Lower y coordinate.
61 * \return The new OBJECT
63 OBJECT *o_box_new(TOPLEVEL *toplevel,
64 char type, int color,
65 int x1, int y1, int x2, int y2)
67 OBJECT *new_node;
68 BOX *box;
70 /* create the object */
71 new_node = s_basic_new_object(type, "box");
72 new_node->color = color;
74 box = (BOX *) g_malloc(sizeof(BOX));
75 new_node->box = box;
77 /* describe the box with its upper left and lower right corner */
78 box->upper_x = x1;
79 box->upper_y = y1;
80 box->lower_x = x2;
81 box->lower_y = y2;
83 /* line type and filling initialized to default */
84 o_set_line_options(toplevel, new_node,
85 END_NONE, TYPE_SOLID, 0, -1, -1);
86 o_set_fill_options(toplevel, new_node,
87 FILLING_HOLLOW, -1, -1, -1, -1, -1);
89 new_node->draw_func = box_draw_func;
90 new_node->sel_func = select_func;
92 /* compute the bounding box */
93 o_box_recalc(toplevel, new_node);
95 return new_node;
98 /*! \brief Copy a box to a list.
99 * \par Function Description
100 * The function #o_box_copy() creates a verbatim copy of the object
101 * pointed by <B>o_current</B> describing a box.
103 * \param [in] toplevel The TOPLEVEL object.
104 * \param [in] o_current BOX OBJECT to copy.
105 * \return The new OBJECT
107 OBJECT *o_box_copy(TOPLEVEL *toplevel, OBJECT *o_current)
109 OBJECT *new_obj;
111 /* A new box object is created with #o_box_new().
112 * Values for its fields are default and need to be modified. */
113 new_obj = o_box_new (toplevel, OBJ_BOX, o_current->color, 0, 0, 0, 0);
116 * The dimensions of the new box are set with the ones of the original box.
117 * The two boxes have the same line type and the same filling options.
119 * The coordinates and the values in world unit are computed with
120 * #o_box_recalc().
123 new_obj->box->upper_x = o_current->box->upper_x;
124 new_obj->box->upper_y = o_current->box->upper_y;
125 new_obj->box->lower_x = o_current->box->lower_x;
126 new_obj->box->lower_y = o_current->box->lower_y;
128 o_set_line_options(toplevel, new_obj, o_current->line_end,
129 o_current->line_type, o_current->line_width,
130 o_current->line_length, o_current->line_space);
131 o_set_fill_options(toplevel, new_obj,
132 o_current->fill_type, o_current->fill_width,
133 o_current->fill_pitch1, o_current->fill_angle1,
134 o_current->fill_pitch2, o_current->fill_angle2);
136 o_box_recalc(toplevel, new_obj);
138 /* new_obj->attribute = 0;*/
140 return new_obj;
143 /*! \brief Modify a BOX OBJECT's coordinates.
144 * \par Function Description
145 * This function modifies the coordinates of one of the four corner of
146 * the box. The new coordinates of the corner identified by <B>whichone</B>
147 * are given by <B>x</B> and <B>y</B> in world unit.
149 * The coordinates of the corner is modified in the world coordinate system.
150 * Screen coordinates and boundings are then updated.
152 * \param [in] toplevel The TOPLEVEL object.
153 * \param [in,out] object BOX OBJECT to be modified.
154 * \param [in] x x coordinate.
155 * \param [in] y y coordinate.
156 * \param [in] whichone coordinate to change.
158 * \note
159 * <B>whichone</B> can take the following values:
160 * <DL>
161 * <DT>*</DT><DD>BOX_UPPER_LEFT
162 * <DT>*</DT><DD>BOX_LOWER_LEFT
163 * <DT>*</DT><DD>BOX_UPPER_RIGHT
164 * <DT>*</DT><DD>BOX_LOWER_RIGHT
165 * </DL>
167 void o_box_modify(TOPLEVEL *toplevel, OBJECT *object,
168 int x, int y, int whichone)
170 int tmp;
172 /* change the position of the selected corner */
173 switch(whichone) {
174 case BOX_UPPER_LEFT:
175 object->box->upper_x = x;
176 object->box->upper_y = y;
177 break;
179 case BOX_LOWER_LEFT:
180 object->box->upper_x = x;
181 object->box->lower_y = y;
182 break;
184 case BOX_UPPER_RIGHT:
185 object->box->lower_x = x;
186 object->box->upper_y = y;
187 break;
189 case BOX_LOWER_RIGHT:
190 object->box->lower_x = x;
191 object->box->lower_y = y;
192 break;
194 default:
195 return;
198 /* need to update the upper left and lower right corners */
199 if(object->box->upper_x > object->box->lower_x) {
200 tmp = object->box->upper_x;
201 object->box->upper_x = object->box->lower_x;
202 object->box->lower_x = tmp;
205 if(object->box->upper_y < object->box->lower_y) {
206 tmp = object->box->upper_y;
207 object->box->upper_y = object->box->lower_y;
208 object->box->lower_y = tmp;
211 /* recalculate the world coords and the boundings */
212 o_box_recalc(toplevel, object);
216 /*! \brief Create a box from a character string.
217 * \par Function Description
218 * This function gets the description of a box from the <B>*buf</B> character
219 * string.
221 * Depending on <B>*version</B>, the correct file format is considered.
222 * Currently two file format revisions are supported :
223 * <DL>
224 * <DT>*</DT><DD>the file format used until 20000704 release
225 * <DT>*</DT><DD>the file format used for the releases after 2000704.
226 * </DL>
228 * \param [in] toplevel The TOPLEVEL object.
229 * \param [in] buf Character string with box description.
230 * \param [in] release_ver libgeda release version number.
231 * \param [in] fileformat_ver libgeda file format version number.
232 * \return The BOX OBJECT that was created.
234 OBJECT *o_box_read (TOPLEVEL *toplevel, char buf[],
235 unsigned int release_ver, unsigned int fileformat_ver)
237 OBJECT *new_obj;
238 char type;
239 int x1, y1;
240 int width, height;
241 int d_x1, d_y1;
242 int d_x2, d_y2;
243 int color;
244 int box_width, box_space, box_length;
245 int fill_width, angle1, pitch1, angle2, pitch2;
246 int box_end;
247 int box_type;
248 int box_filling;
250 if (release_ver <= VERSION_20000704) {
252 /*! \note
253 * The old geda file format, i.e. releases 20000704 and older, does not
254 * handle the line type and the filling of the box object. They are set
255 * to default.
258 sscanf (buf, "%c %d %d %d %d %d\n",
259 &type, &x1, &y1, &width, &height, &color);
261 box_width = 0;
262 box_end = END_NONE;
263 box_type = TYPE_SOLID;
264 box_length = -1;
265 box_space = -1;
267 box_filling = FILLING_HOLLOW;
268 fill_width = 0;
269 angle1 = -1;
270 pitch1 = -1;
271 angle2 = -1;
272 pitch2 = -1;
274 } else {
276 /*! \note
277 * The current line format to describe a box is a space separated list of
278 * characters and numbers in plain ASCII on a single line. The meaning of
279 * each item is described in the file format documentation.
281 sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
282 &type, &x1, &y1, &width, &height, &color,
283 &box_width, &box_end, &box_type, &box_length,
284 &box_space, &box_filling,
285 &fill_width, &angle1, &pitch1, &angle2, &pitch2);
288 if (width == 0 || height == 0) {
289 s_log_message (_("Found a zero width/height box [ %c %d %d %d %d %d ]\n"),
290 type, x1, y1, width, height, color);
293 if (color < 0 || color > MAX_COLORS) {
294 s_log_message (_("Found an invalid color [ %s ]\n"), buf);
295 s_log_message (_("Setting color to default color\n"));
296 color = DEFAULT_COLOR;
299 /*! \note
300 * A box is internally described by its lower right and upper left corner
301 * whereas the line describe it with the lower left corner and the width
302 * and height.
304 * A new object is allocated, initialized and added to the object list.
305 * Its filling and line type are set according to the values of the field
306 * on the line.
309 /* upper left corner of the box */
310 d_x1 = x1;
311 d_y1 = y1 + height; /* move box origin to top left */
313 /* lower right corner of the box */
314 d_x2 = x1 + width; /* end points of the box */
315 d_y2 = y1;
317 /* create a new box */
318 new_obj = o_box_new (toplevel, type, color, d_x1, d_y1, d_x2, d_y2);
319 /* set its line options */
320 o_set_line_options (toplevel, new_obj,
321 box_end, box_type, box_width,
322 box_length, box_space);
323 /* set its fill options */
324 o_set_fill_options (toplevel, new_obj,
325 box_filling, fill_width,
326 pitch1, angle1, pitch2, angle2);
328 return new_obj;
331 /*! \brief Create a character string representation of a BOX.
332 * \par Function Description
333 * This function formats a string in the buffer <B>*buff</B> to describe the
334 * box object <B>*object</B>.
335 * It follows the post-20000704 release file format that handle the line type
336 * and fill options.
338 * \param [in] object The BOX OBJECT to create string from.
339 * \return A pointer to the BOX character string.
341 * \warning
342 * Caller must g_free returned character string.
344 char *o_box_save(OBJECT *object)
346 int x1, y1;
347 int width, height;
348 int box_width, box_space, box_length;
349 int fill_width, angle1, pitch1, angle2, pitch2;
350 OBJECT_END box_end;
351 OBJECT_TYPE box_type;
352 OBJECT_FILLING box_fill;
353 char *buf;
355 /*! \note
356 * A box is internally represented by its lower right and upper left corner
357 * whereas it is described in the file format as its lower left corner and
358 * its width and height.
361 /* calculate the width and height of the box */
362 width = abs(object->box->lower_x - object->box->upper_x);
363 height = abs(object->box->upper_y - object->box->lower_y);
365 /* calculate the lower left corner of the box */
366 x1 = object->box->upper_x;
367 y1 = object->box->upper_y - height; /* move the origin to 0, 0*/
369 #if DEBUG
370 printf("box: %d %d %d %d\n", x1, y1, width, height);
371 #endif
373 /* description of the line type for the outline */
374 box_end = object->line_end;
375 box_width = object->line_width;
376 box_type = object->line_type;
377 box_length = object->line_length;
378 box_space = object->line_space;
380 /* description of the filling of the box */
381 box_fill = object->fill_type;
382 fill_width = object->fill_width;
383 angle1 = object->fill_angle1;
384 pitch1 = object->fill_pitch1;
385 angle2 = object->fill_angle2;
386 pitch2 = object->fill_pitch2;
388 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
389 object->type,
390 x1, y1, width, height, object->color,
391 box_width, box_end, box_type, box_length, box_space,
392 box_fill,
393 fill_width, angle1, pitch1, angle2, pitch2);
395 return(buf);
398 /*! \brief Translate a BOX position in WORLD coordinates by a delta.
399 * \par Function Description
400 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the box
401 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
403 * \param [in] toplevel The TOPLEVEL object.
404 * \param [in] dx x distance to move.
405 * \param [in] dy y distance to move.
406 * \param [in,out] object BOX OBJECT to translate.
408 void o_box_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object)
410 if (object == NULL) printf("btw NO!\n");
412 /* Do world coords */
413 object->box->upper_x = object->box->upper_x + dx;
414 object->box->upper_y = object->box->upper_y + dy;
415 object->box->lower_x = object->box->lower_x + dx;
416 object->box->lower_y = object->box->lower_y + dy;
418 /* recalc the screen coords and the bounding box */
419 o_box_recalc(toplevel, object);
422 /*! \brief Rotate BOX OBJECT using WORLD coordinates.
423 * \par Function Description
424 * The function #o_box_rotate_world() rotate the box described by
425 * <B>*object</B> around the (<B>world_centerx</B>, <B>world_centery</B>) point by
426 * <B>angle</B> degrees.
427 * The center of rotation is in world unit.
429 * \param [in] toplevel The TOPLEVEL object.
430 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
431 * \param [in] world_centery Rotation center y coordinate in WORLD units.
432 * \param [in] angle Rotation angle in degrees (See note below).
433 * \param [in,out] object BOX OBJECT to rotate.
436 void o_box_rotate_world(TOPLEVEL *toplevel,
437 int world_centerx, int world_centery, int angle,
438 OBJECT *object)
440 int newx1, newy1;
441 int newx2, newy2;
443 /*! \note
444 * Only 90 degree multiple and positive angles are allowed.
447 /* angle must be positive */
448 if(angle < 0) angle = -angle;
449 /* angle must be a 90 multiple or no rotation performed */
450 if((angle % 90) != 0) return;
452 /*! \note
453 * The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is
454 * translated to the origin. The rotation of the upper left and lower right
455 * corner are then performed. Finally, the rotated box is translated back
456 * to its previous location.
458 /* translate object to origin */
459 object->box->upper_x -= world_centerx;
460 object->box->upper_y -= world_centery;
461 object->box->lower_x -= world_centerx;
462 object->box->lower_y -= world_centery;
464 /* rotate the upper left corner of the box */
465 rotate_point_90(object->box->upper_x, object->box->upper_y, angle,
466 &newx1, &newy1);
468 /* rotate the lower left corner of the box */
469 rotate_point_90(object->box->lower_x, object->box->lower_y, angle,
470 &newx2, &newy2);
472 /* reorder the corners after rotation */
473 object->box->upper_x = min(newx1,newx2);
474 object->box->upper_y = max(newy1,newy2);
475 object->box->lower_x = max(newx1,newx2);
476 object->box->lower_y = min(newy1,newy2);
478 /* translate object back to normal position */
479 object->box->upper_x += world_centerx;
480 object->box->upper_y += world_centery;
481 object->box->lower_x += world_centerx;
482 object->box->lower_y += world_centery;
484 /* recalc boundings and world coords */
485 o_box_recalc(toplevel, object);
488 /*! \brief Mirror BOX using WORLD coordinates.
489 * \par Function Description
490 * This function mirrors the box from the point
491 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
493 * The box is first translated to the origin, then mirrored and finally
494 * translated back at its previous position.
496 * \param [in] toplevel The TOPLEVEL object.
497 * \param [in] world_centerx Origin x coordinate in WORLD units.
498 * \param [in] world_centery Origin y coordinate in WORLD units.
499 * \param [in,out] object BOX OBJECT to mirror.
501 void o_box_mirror_world(TOPLEVEL *toplevel,
502 int world_centerx, int world_centery,
503 OBJECT *object)
505 int newx1, newy1;
506 int newx2, newy2;
508 /* translate object to origin */
509 object->box->upper_x -= world_centerx;
510 object->box->upper_y -= world_centery;
511 object->box->lower_x -= world_centerx;
512 object->box->lower_y -= world_centery;
514 /* mirror the corners */
515 newx1 = -object->box->upper_x;
516 newy1 = object->box->upper_y;
517 newx2 = -object->box->lower_x;
518 newy2 = object->box->lower_y;
520 /* reorder the corners */
521 object->box->upper_x = min(newx1,newx2);
522 object->box->upper_y = max(newy1,newy2);
523 object->box->lower_x = max(newx1,newx2);
524 object->box->lower_y = min(newy1,newy2);
526 /* translate back in position */
527 object->box->upper_x += world_centerx;
528 object->box->upper_y += world_centery;
529 object->box->lower_x += world_centerx;
530 object->box->lower_y += world_centery;
532 /* recalc boundings and world coords */
533 o_box_recalc(toplevel, object);
537 /*! \brief Recalculate BOX coordinates in WORLD units.
538 * \par Function Description
539 * This function recalculates the box coordinates and its
540 * bounding are recalculated as well.
542 * \param [in] toplevel The TOPLEVEL object.
543 * \param [in,out] o_current BOX OBJECT to be recalculated.
545 void o_box_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
547 int left, top, right, bottom;
549 if (o_current->box == NULL) {
550 return;
553 /* update the bounding box - world unit */
554 world_get_box_bounds(toplevel, o_current, &left, &top, &right, &bottom);
555 o_current->w_left = left;
556 o_current->w_top = top;
557 o_current->w_right = right;
558 o_current->w_bottom = bottom;
559 o_current->w_bounds_valid = TRUE;
562 /*! \brief Get BOX bounding rectangle in WORLD coordinates.
563 * \par Function Description
564 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
565 * parameters to the boundings of the box object described in <B>*box</B>
566 * in world units.
568 * \param [in] toplevel The TOPLEVEL object.
569 * \param [in] object BOX OBJECT to read coordinates from.
570 * \param [out] left Left box coordinate in WORLD units.
571 * \param [out] top Top box coordinate in WORLD units.
572 * \param [out] right Right box coordinate in WORLD units.
573 * \param [out] bottom Bottom box coordinate in WORLD units.
575 void world_get_box_bounds(TOPLEVEL *toplevel, OBJECT *object,
576 int *left, int *top, int *right, int *bottom)
578 int halfwidth;
580 halfwidth = object->line_width / 2;
582 *left = min(object->box->upper_x, object->box->lower_x);
583 *top = min(object->box->upper_y, object->box->lower_y);
584 *right = max(object->box->upper_x, object->box->lower_x);
585 *bottom = max(object->box->upper_y, object->box->lower_y);
587 /* This isn't strictly correct, but a 1st order approximation */
588 *left -= halfwidth;
589 *top -= halfwidth;
590 *right += halfwidth;
591 *bottom += halfwidth;
594 /*! \brief get the position of the left bottom point
595 * \par Function Description
596 * This function gets the position of the bottom left point of a box object.
598 * \param [in] toplevel The toplevel environment.
599 * \param [out] x pointer to the x-position
600 * \param [out] y pointer to the y-position
601 * \param [in] object The object to get the position.
602 * \return TRUE if successfully determined the position, FALSE otherwise
604 gboolean o_box_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
605 OBJECT *object)
607 *x = min(object->box->lower_x, object->box->upper_x);
608 *y = min(object->box->lower_y, object->box->upper_y);
609 return TRUE;
612 /*! \brief Print BOX to Postscript document.
613 * \par Function Description
614 * This function prints the box described by the <B>o_current</B>
615 * parameter to a Postscript document. It takes into account its line
616 * type and fill type.
617 * The Postscript document is descibed by the file pointer <B>fp</B>.
619 * The validity of the <B>o_current</B> parameter is verified : a null pointer
620 * causes an error message and a return.
622 * The description of the box is extracted from
623 * the <B>o_current</B> parameter :
624 * the coordinates of the box - upper left corner and width and
625 * height of the box -, its line type, its fill type.
627 * The outline and the inside of the box are successively handled by two
628 * differend sets of functions.
630 * \param [in] toplevel The TOPLEVEL object.
631 * \param [in] fp FILE pointer to Postscript document.
632 * \param [in] o_current BOX OBJECT to write to document.
633 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
634 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
636 void o_box_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
637 int origin_x, int origin_y)
639 int x, y, width, height;
640 int color;
641 int line_width, length, space;
642 int fill_width, angle1, pitch1, angle2, pitch2;
643 void (*outl_func)() = NULL;
644 void (*fill_func)() = NULL;
646 if (o_current == NULL) {
647 printf("got null in o_box_print\n");
648 return;
651 x = o_current->box->upper_x;
652 y = o_current->box->upper_y;
653 width = abs(o_current->box->lower_x - o_current->box->upper_x);
654 height = abs(o_current->box->lower_y - o_current->box->upper_y);
655 color = o_current->color;
657 /*! \note
658 * Depending on the type of the line for this particular box, the
659 * appropriate function is chosen among #o_box_print_solid(),
660 * #o_box_print_dotted(), #o_box_print_dashed(),
661 * #o_box_print_center() and #o_box_print_phantom().
663 * The needed parameters for each of these type is extracted from the
664 * <B>o_current</B> object. Depending on the type, unused parameters are
665 * set to -1.
667 * In the eventuality of a length and/or space null, the line is printed
668 * solid to avoid and endless loop produced by other functions in such a
669 * case.
671 line_width = o_current->line_width;
673 if(line_width <=2) {
674 if(toplevel->line_style == THICK) {
675 line_width=LINE_WIDTH;
676 } else {
677 line_width=2;
680 length = o_current->line_length;
681 space = o_current->line_space;
683 switch(o_current->line_type) {
684 case(TYPE_SOLID):
685 length = -1; space = -1;
686 outl_func = o_box_print_solid;
687 break;
689 case(TYPE_DOTTED):
690 length = -1;
691 outl_func = o_box_print_dotted;
692 break;
694 case(TYPE_DASHED):
695 outl_func = o_box_print_dashed;
696 break;
698 case(TYPE_CENTER):
699 outl_func = o_box_print_center;
700 break;
702 case(TYPE_PHANTOM):
703 outl_func = o_box_print_phantom;
704 break;
706 case(TYPE_ERASE):
707 /* Unused for now, print it solid */
708 length = -1; space = -1;
709 outl_func = o_box_print_solid;
710 break;
713 if((length == 0) || (space == 0)) {
714 length = -1; space = -1;
715 outl_func = o_box_print_solid;
718 (*outl_func)(toplevel, fp,
719 x, y, width, height,
720 color,
721 line_width,
722 length, space,
723 origin_x, origin_y);
725 /*! \note
726 * If the filling type of the box is not <B>HOLLOW</B>, the appropriate
727 * function is chosen among #o_box_print_filled(), #o_box_print_mesh()
728 * and #o_box_print_hatch(). The corresponding parameters are extracted
729 * from the <B>o_current</B> object and corrected afterward.
731 * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
732 * avoided as it leads to an endless loop in most of the called functions.
733 * In such a case, the box is printed filled. Unused parameters for each of
734 * these functions are set to -1 or any passive value.
736 if(o_current->fill_type != FILLING_HOLLOW) {
737 fill_width = o_current->fill_width;
738 angle1 = o_current->fill_angle1;
739 pitch1 = o_current->fill_pitch1;
740 angle2 = o_current->fill_angle2;
741 pitch2 = o_current->fill_pitch2;
743 switch(o_current->fill_type) {
744 case(FILLING_FILL):
745 angle1 = -1; pitch1 = 1;
746 angle2 = -1; pitch2 = 1;
747 fill_width = -1;
748 fill_func = o_box_print_filled;
749 break;
751 case(FILLING_MESH):
752 fill_func = o_box_print_mesh;
753 break;
755 case(FILLING_HATCH):
756 angle2 = -1; pitch2 = 1;
757 fill_func = o_box_print_hatch;
758 break;
760 case(FILLING_VOID):
761 /* Unused for now, print it filled */
762 angle1 = -1; pitch1 = 1;
763 angle2 = -1; pitch2 = 1;
764 fill_width = -1;
765 fill_func = o_box_print_filled;
766 break;
767 case(FILLING_HOLLOW):
768 /* nop */
769 break;
773 if((pitch1 <= 0) || (pitch2 <= 0)) {
774 angle1 = -1; pitch1 = 1;
775 angle2 = -1; pitch2 = 1;
776 fill_func = o_box_print_filled;
779 (*fill_func)(toplevel, fp,
780 x, y, width, height,
781 color,
782 fill_width,
783 angle1, pitch1, angle2, pitch2,
784 origin_x, origin_y);
788 /*! \brief Print a solid BOX to Postscript document.
789 * \par Function Description
790 * This function prints the outline of a box when a solid line type is
791 * required. The box is defined by the coordinates of its upper left corner
792 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
793 * <B>height</B> parameters.
794 * The postscript file is defined by the file pointer <B>fp</B>.
795 * The parameters <B>length</B> and <B>space</B> are ignored.
797 * It uses the function #o_line_print_solid() to print the outline.
798 * It performs four calls to this function, one for each of its side.
800 * All dimensions are in mils.
802 * \param [in] toplevel The TOPLEVEL object.
803 * \param [in] fp FILE pointer to Postscript document.
804 * \param [in] x Upper x coordinate of BOX.
805 * \param [in] y Upper y coordinate of BOX.
806 * \param [in] width Width of BOX.
807 * \param [in] height Height of BOX.
808 * \param [in] color BOX color.
809 * \param [in] line_width BOX Line width.
810 * \param [in] length Dashed line length.
811 * \param [in] space Amount of space between dashes.
812 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
813 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
815 void
816 o_box_print_solid(TOPLEVEL *toplevel, FILE *fp,
817 int x, int y,
818 int width, int height,
819 int color,
820 int line_width, int length, int space,
821 int origin_x, int origin_y)
823 int x1, y1;
825 f_print_set_color(toplevel, fp, color);
827 x1 = x;
828 y1 = y - height; /* move the origin to 0, 0*/
830 o_line_print_solid(toplevel, fp,
831 x1, y1, x1 + width, y1,
832 color,
833 line_width, length, space,
834 origin_x, origin_y);
835 o_line_print_solid(toplevel, fp,
836 x1 + width, y1, x1 + width, y1 + height,
837 color,
838 line_width, length, space,
839 origin_x, origin_y);
840 o_line_print_solid(toplevel, fp,
841 x1 + width, y1 + height, x1, y1 + height,
842 color,
843 line_width, length, space,
844 origin_x, origin_y);
845 o_line_print_solid(toplevel, fp,
846 x1, y1 + height, x1, y1,
847 color,
848 line_width, length, space,
849 origin_x, origin_y);
852 /*! \brief Print a dotted BOX to Postscript document.
853 * \par Function Description
854 * This function prints the outline of a box when a dotted line type is
855 * required. The box is defined by the coordinates of its upper left corner
856 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
857 * <B>height</B> parameters.
858 * The postscript file is defined by the file pointer <B>fp</B>.
859 * The parameters <B>length</B> is ignored.
861 * It uses the function #o_line_print_dotted() to print the outline.
862 * It performs four calls to this function, one for each of its side.
864 * All dimensions are in mils.
866 * \param [in] toplevel The TOPLEVEL object.
867 * \param [in] fp FILE pointer to Postscript document.
868 * \param [in] x Upper x coordinate of BOX.
869 * \param [in] y Upper y coordinate of BOX.
870 * \param [in] width Width of BOX.
871 * \param [in] height Height of BOX.
872 * \param [in] color BOX color.
873 * \param [in] line_width BOX Line width.
874 * \param [in] length Dashed line length.
875 * \param [in] space Amount of space between dashes.
876 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
877 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
879 void o_box_print_dotted(TOPLEVEL *toplevel, FILE *fp,
880 int x, int y,
881 int width, int height,
882 int color,
883 int line_width, int length, int space,
884 int origin_x, int origin_y)
886 int x1, y1;
888 f_print_set_color(toplevel, fp, color);
890 x1 = x;
891 y1 = y - height; /* move the origin to 0, 0*/
893 o_line_print_dotted(toplevel, fp,
894 x1, y1, x1 + width, y1,
895 color,
896 line_width, length, space,
897 origin_x, origin_y);
898 o_line_print_dotted(toplevel, fp,
899 x1 + width, y1, x1 + width, y1 + height,
900 color,
901 line_width, length, space,
902 origin_x, origin_y);
903 o_line_print_dotted(toplevel, fp,
904 x1 + width, y1 + height, x1, y1 + height,
905 color,
906 line_width, length, space,
907 origin_x, origin_y);
908 o_line_print_dotted(toplevel, fp,
909 x1, y1 + height, x1, y1,
910 color,
911 line_width, length, space,
912 origin_x, origin_y);
915 /*! \brief Print a dashed BOX to Postscript document.
916 * \par Function Description
917 * This function prints the outline of a box when a dashed line type is
918 * required. The box is defined by the coordinates of its upper left corner
919 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
920 * <B>height</B> parameters.
921 * The postscript file is defined by the file pointer <B>fp</B>.
923 * It uses the function #o_line_print_dashed() to print the outline.
924 * It performs four calls to this function, one for each of its side.
926 * All dimensions are in mils.
928 * \param [in] toplevel The TOPLEVEL object.
929 * \param [in] fp FILE pointer to Postscript document.
930 * \param [in] x Upper x coordinate of BOX.
931 * \param [in] y Upper y coordinate of BOX.
932 * \param [in] width Width of BOX.
933 * \param [in] height Height of BOX.
934 * \param [in] color BOX color.
935 * \param [in] line_width BOX Line width.
936 * \param [in] length Dashed line length.
937 * \param [in] space Amount of space between dashes.
938 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
939 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
941 void o_box_print_dashed(TOPLEVEL *toplevel, FILE *fp,
942 int x, int y,
943 int width, int height,
944 int color,
945 int line_width, int length, int space,
946 int origin_x, int origin_y)
948 int x1, y1;
950 f_print_set_color(toplevel, fp, color);
953 x1 = x;
954 y1 = y - height; /* move the origin to 0, 0*/
956 o_line_print_dashed(toplevel, fp,
957 x1, y1, x1 + width, y1,
958 color,
959 line_width, length, space,
960 origin_x, origin_y);
961 o_line_print_dashed(toplevel, fp,
962 x1 + width, y1, x1 + width, y1 + height,
963 color,
964 line_width, length, space,
965 origin_x, origin_y);
966 o_line_print_dashed(toplevel, fp,
967 x1 + width, y1 + height, x1, y1 + height,
968 color,
969 line_width, length, space,
970 origin_x, origin_y);
971 o_line_print_dashed(toplevel, fp,
972 x1, y1 + height, x1, y1,
973 color,
974 line_width, length, space,
975 origin_x, origin_y);
978 /*! \brief Print centered line type BOX to Postscript document.
979 * \par Function Description
980 * This function prints the outline of a box when a centered line type is
981 * required. The box is defined by the coordinates of its upper left corner
982 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
983 * <B>height</B> parameters.
984 * The postscript file is defined by the file pointer <B>fp</B>.
986 * It uses the function #o_line_print_center() to print the outline.
987 * It performs four calls to this function, one for each of its side.
989 * All dimensions are in mils.
991 * \param [in] toplevel The TOPLEVEL object.
992 * \param [in] fp FILE pointer to Postscript document.
993 * \param [in] x Upper x coordinate of BOX.
994 * \param [in] y Upper y coordinate of BOX.
995 * \param [in] width Width of BOX.
996 * \param [in] height Height of BOX.
997 * \param [in] color BOX color.
998 * \param [in] line_width BOX Line width.
999 * \param [in] length Dashed line length.
1000 * \param [in] space Amount of space between dashes.
1001 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1002 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1004 void o_box_print_center(TOPLEVEL *toplevel, FILE *fp,
1005 int x, int y,
1006 int width, int height,
1007 int color,
1008 int line_width, int length, int space,
1009 int origin_x, int origin_y)
1011 int x1, y1;
1013 f_print_set_color(toplevel, fp, color);
1015 x1 = x;
1016 y1 = y - height; /* move the origin to 0, 0*/
1018 o_line_print_center(toplevel, fp,
1019 x1, y1, x1 + width, y1,
1020 color,
1021 line_width, length, space,
1022 origin_x, origin_y);
1023 o_line_print_center(toplevel, fp,
1024 x1 + width, y1, x1 + width, y1 + height,
1025 color,
1026 line_width, length, space,
1027 origin_x, origin_y);
1028 o_line_print_center(toplevel, fp,
1029 x1 + width, y1 + height, x1, y1 + height,
1030 color,
1031 line_width, length, space,
1032 origin_x, origin_y);
1033 o_line_print_center(toplevel, fp,
1034 x1, y1 + height, x1, y1,
1035 color,
1036 line_width, length, space,
1037 origin_x, origin_y);
1040 /*! \brief Print phantom line type BOX to Postscript document.
1041 * \par Function Description
1042 * This function prints the outline of a box when a phantom line type is
1043 * required. The box is defined by the coordinates of its upper left corner
1044 * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1045 * <B>height</B> parameters.
1046 * The postscript file is defined by the file pointer <B>fp</B>.
1048 * It uses the function #o_line_print_phantom() to print the outline.
1049 * It performs four calls to this function, one for each of its side.
1051 * All dimensions are in mils.
1053 * \param [in] toplevel The TOPLEVEL object.
1054 * \param [in] fp FILE pointer to Postscript document.
1055 * \param [in] x Upper x coordinate of BOX.
1056 * \param [in] y Upper y coordinate of BOX.
1057 * \param [in] width Width of BOX.
1058 * \param [in] height Height of BOX.
1059 * \param [in] color BOX color.
1060 * \param [in] line_width BOX Line width.
1061 * \param [in] length Dashed line length.
1062 * \param [in] space Amount of space between dashes.
1063 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1064 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1066 void o_box_print_phantom(TOPLEVEL *toplevel, FILE *fp,
1067 int x, int y,
1068 int width, int height,
1069 int color,
1070 int line_width, int length, int space,
1071 int origin_x, int origin_y)
1073 int x1, y1;
1075 f_print_set_color(toplevel, fp, color);
1077 x1 = x;
1078 y1 = y - height; /* move the origin to 0, 0*/
1080 o_line_print_phantom(toplevel, fp,
1081 x1, y1, x1 + width, y1,
1082 color,
1083 line_width, length, space,
1084 origin_x, origin_y);
1085 o_line_print_phantom(toplevel, fp,
1086 x1 + width, y1, x1 + width, y1 + height,
1087 color,
1088 line_width, length, space,
1089 origin_x, origin_y);
1090 o_line_print_phantom(toplevel, fp,
1091 x1 + width, y1 + height, x1, y1 + height,
1092 color,
1093 line_width, length, space,
1094 origin_x, origin_y);
1095 o_line_print_phantom(toplevel, fp,
1096 x1, y1 + height, x1, y1,
1097 color,
1098 line_width, length, space,
1099 origin_x, origin_y);
1102 /*! \brief Print a solid pattern BOX to Postscript document.
1103 * \par Function Description
1104 * The function prints a filled box with a solid pattern. No outline is
1105 * printed.
1106 * The box is defined by the coordinates of its upper left corner in
1107 * (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1108 * <B>height</B> parameters. The postscript file is defined by the file
1109 * pointer <B>fp</B>.
1110 * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B> and <B>pitch2</B>
1111 * parameters are ignored in this functions but kept for compatibility
1112 * with other fill functions.
1114 * It uses the fbox postscript function defined in the prolog to
1115 * specify a filled box.
1117 * All dimensions are in mils.
1119 * \param [in] toplevel The TOPLEVEL object.
1120 * \param [in] fp FILE pointer to Postscript document.
1121 * \param [in] x Upper x coordinate of BOX.
1122 * \param [in] y Upper y coordinate of BOX.
1123 * \param [in] width Width of BOX.
1124 * \param [in] height Height of BOX.
1125 * \param [in] color BOX color.
1126 * \param [in] fill_width BOX fill width. (unused).
1127 * \param [in] angle1 (unused).
1128 * \param [in] pitch1 (unused).
1129 * \param [in] angle2 (unused).
1130 * \param [in] pitch2 (unused).
1131 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1132 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1134 void o_box_print_filled(TOPLEVEL *toplevel, FILE *fp,
1135 int x, int y,
1136 int width, int height,
1137 int color,
1138 int fill_width,
1139 int angle1, int pitch1,
1140 int angle2, int pitch2,
1141 int origin_x, int origin_y)
1143 int x1, y1;
1145 f_print_set_color(toplevel, fp, color);
1147 x1 = x;
1148 y1 = y-height; /* move the origin to 0, 0*/
1149 fprintf(fp, "%d %d %d %d fbox\n",
1150 width, height,
1151 x1-origin_x, y1-origin_y);
1155 /*! \brief Print a mesh pattern BOX to Postscript document.
1156 * \par Function Description
1157 * This function prints a meshed box. No outline is printed. The box is
1158 * defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
1159 * its width and height given by the <B>width</B> and <B>height</B> parameters.
1160 * The postscript file is defined by the file pointer <B>fp</B>.
1162 * The inside mesh is achieved by two successive call to the
1163 * #o_box_print_hatch() function, given <B>angle1</B> and <B>pitch1</B> the first
1164 * time and <B>angle2</B> and <B>pitch2</B> the second time.
1166 * Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are not allowed
1167 * as it leads to an endless loop in #o_box_print_hatch().
1169 * All dimensions are in mils.
1171 * \param [in] toplevel The TOPLEVEL object.
1172 * \param [in] fp FILE pointer to Postscript document.
1173 * \param [in] x Upper x coordinate of BOX.
1174 * \param [in] y Upper y coordinate of BOX.
1175 * \param [in] width Width of BOX.
1176 * \param [in] height Height of BOX.
1177 * \param [in] color BOX color.
1178 * \param [in] fill_width BOX fill width.
1179 * \param [in] angle1 1st angle for mesh pattern.
1180 * \param [in] pitch1 1st pitch for mesh pattern.
1181 * \param [in] angle2 2nd angle for mesh pattern.
1182 * \param [in] pitch2 2nd pitch for mesh pattern.
1183 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1184 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1186 void o_box_print_mesh(TOPLEVEL *toplevel, FILE *fp,
1187 int x, int y,
1188 int width, int height,
1189 int color,
1190 int fill_width,
1191 int angle1, int pitch1,
1192 int angle2, int pitch2,
1193 int origin_x, int origin_y)
1195 o_box_print_hatch(toplevel, fp,
1196 x, y, width, height,
1197 color,
1198 fill_width,
1199 angle1, pitch1, -1, -1,
1200 origin_x, origin_y);
1201 o_box_print_hatch(toplevel, fp,
1202 x, y, width, height,
1203 color,
1204 fill_width,
1205 angle2, pitch2, -1, -1,
1206 origin_x, origin_y);
1210 /*! \brief Print a hatch pattern BOX to Postscript document.
1211 * \par Function Description
1212 * The function prints a hatched box. No outline is printed. The box is
1213 * defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
1214 * its width and height given by the <B>width</B> and <B>height</B> parameters.
1215 * The postscript file is defined by the file pointer <B>fp</B>.
1216 * <B>fill_width</B>, <B>angle1</B>, <B>pitch1</B> parameters define the way the box
1217 * has to be hatched.
1218 * <B>angle2</B> and <B>pitch2</B> parameters are unused but kept for compatibility
1219 * with other fill functions.
1221 * Negative or null values for <B>pitch1</B> are not allowed as it leads to an
1222 * endless loop.
1224 * All dimensions are in mils.
1226 * \param [in] toplevel The TOPLEVEL object.
1227 * \param [in] fp FILE pointer to Postscript document.
1228 * \param [in] x Upper x coordinate of BOX.
1229 * \param [in] y Upper y coordinate of BOX.
1230 * \param [in] width Width of BOX.
1231 * \param [in] height Height of BOX.
1232 * \param [in] color BOX color.
1233 * \param [in] fill_width BOX fill width.
1234 * \param [in] angle1 Angle of hatch pattern.
1235 * \param [in] pitch1 Pitch of hatch pattern.
1236 * \param [in] angle2 (unused).
1237 * \param [in] pitch2 (unused).
1238 * \param [in] origin_x Page x coordinate to place BOX OBJECT.
1239 * \param [in] origin_y Page y coordinate to place BOX OBJECT.
1241 void o_box_print_hatch(TOPLEVEL *toplevel, FILE *fp,
1242 int x, int y,
1243 int width, int height,
1244 int color,
1245 int fill_width,
1246 int angle1, int pitch1,
1247 int angle2, int pitch2,
1248 int origin_x, int origin_y)
1250 BOX box;
1251 gint index;
1252 GArray *lines;
1254 g_return_if_fail(toplevel != NULL);
1255 g_return_if_fail(fp != NULL);
1257 f_print_set_color(toplevel, fp, color);
1259 /* Avoid printing line widths too small */
1260 if (fill_width <= 1) fill_width = 2;
1262 lines = g_array_new(FALSE, FALSE, sizeof(LINE));
1264 box.upper_x = x;
1265 box.upper_y = y;
1266 box.lower_x = x + width;
1267 box.lower_y = y - height; /* Hmmm... */
1269 m_hatch_box(&box, angle1, pitch1, lines);
1271 for(index=0; index<lines->len; index++) {
1272 LINE *line = &g_array_index(lines, LINE, index);
1274 fprintf(fp,"%d %d %d %d %d line\n",
1275 line->x[0], line->y[0],
1276 line->x[1], line->y[1],
1277 fill_width);
1280 g_array_free(lines, TRUE);
1283 /*! \brief Calculates the distance between the given point and the closest
1284 * point on the perimeter of the box.
1286 * \param [in] object The box OBJECT.
1287 * \param [in] x The x coordinate of the given point.
1288 * \param [in] y The y coordinate of the given point.
1289 * \param [in] force_solid If true, force treating the object as solid.
1290 * \return The shortest distance from the object to the point. With an
1291 * invalid parameter, this function returns G_MAXDOUBLE.
1293 double o_box_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1295 int solid;
1297 g_return_val_if_fail (object->box != NULL, G_MAXDOUBLE);
1299 solid = force_solid || object->fill_type != FILLING_HOLLOW;
1301 return m_box_shortest_distance (object->box, x, y, solid);