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
29 #include "libgeda_priv.h"
31 #ifdef HAVE_LIBDMALLOC
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
,
65 int x1
, int y1
, int x2
, int y2
)
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
));
77 /* describe the box with its upper left and lower right corner */
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
);
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
)
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
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;*/
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.
159 * <B>whichone</B> can take the following values:
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
167 void o_box_modify(TOPLEVEL
*toplevel
, OBJECT
*object
,
168 int x
, int y
, int whichone
)
172 /* change the position of the selected corner */
175 object
->box
->upper_x
= x
;
176 object
->box
->upper_y
= y
;
180 object
->box
->upper_x
= x
;
181 object
->box
->lower_y
= y
;
184 case BOX_UPPER_RIGHT
:
185 object
->box
->lower_x
= x
;
186 object
->box
->upper_y
= y
;
189 case BOX_LOWER_RIGHT
:
190 object
->box
->lower_x
= x
;
191 object
->box
->lower_y
= y
;
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
221 * Depending on <B>*version</B>, the correct file format is considered.
222 * Currently two file format revisions are supported :
224 * <DT>*</DT><DD>the file format used until 20000704 release
225 * <DT>*</DT><DD>the file format used for the releases after 2000704.
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
)
244 int box_width
, box_space
, box_length
;
245 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
250 if (release_ver
<= VERSION_20000704
) {
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
258 sscanf (buf
, "%c %d %d %d %d %d\n",
259 &type
, &x1
, &y1
, &width
, &height
, &color
);
263 box_type
= TYPE_SOLID
;
267 box_filling
= FILLING_HOLLOW
;
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
;
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
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
309 /* upper left corner of the box */
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 */
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
);
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
338 * \param [in] object The BOX OBJECT to create string from.
339 * \return A pointer to the BOX character string.
342 * Caller must g_free returned character string.
344 char *o_box_save(OBJECT
*object
)
348 int box_width
, box_space
, box_length
;
349 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
351 OBJECT_TYPE box_type
;
352 OBJECT_FILLING box_fill
;
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*/
370 printf("box: %d %d %d %d\n", x1
, y1
, width
, height
);
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",
390 x1
, y1
, width
, height
, object
->color
,
391 box_width
, box_end
, box_type
, box_length
, box_space
,
393 fill_width
, angle1
, pitch1
, angle2
, pitch2
);
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
,
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;
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
,
468 /* rotate the lower left corner of the box */
469 rotate_point_90(object
->box
->lower_x
, object
->box
->lower_y
, angle
,
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
,
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
) {
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>
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
)
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 */
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
,
607 *x
= min(object
->box
->lower_x
, object
->box
->upper_x
);
608 *y
= min(object
->box
->lower_y
, object
->box
->upper_y
);
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
;
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");
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
;
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
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
671 line_width
= o_current
->line_width
;
674 if(toplevel
->line_style
== THICK
) {
675 line_width
=LINE_WIDTH
;
680 length
= o_current
->line_length
;
681 space
= o_current
->line_space
;
683 switch(o_current
->line_type
) {
685 length
= -1; space
= -1;
686 outl_func
= o_box_print_solid
;
691 outl_func
= o_box_print_dotted
;
695 outl_func
= o_box_print_dashed
;
699 outl_func
= o_box_print_center
;
703 outl_func
= o_box_print_phantom
;
707 /* Unused for now, print it solid */
708 length
= -1; space
= -1;
709 outl_func
= o_box_print_solid
;
713 if((length
== 0) || (space
== 0)) {
714 length
= -1; space
= -1;
715 outl_func
= o_box_print_solid
;
718 (*outl_func
)(toplevel
, fp
,
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
) {
745 angle1
= -1; pitch1
= 1;
746 angle2
= -1; pitch2
= 1;
748 fill_func
= o_box_print_filled
;
752 fill_func
= o_box_print_mesh
;
756 angle2
= -1; pitch2
= 1;
757 fill_func
= o_box_print_hatch
;
761 /* Unused for now, print it filled */
762 angle1
= -1; pitch1
= 1;
763 angle2
= -1; pitch2
= 1;
765 fill_func
= o_box_print_filled
;
767 case(FILLING_HOLLOW
):
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
,
783 angle1
, pitch1
, angle2
, pitch2
,
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.
816 o_box_print_solid(TOPLEVEL
*toplevel
, FILE *fp
,
818 int width
, int height
,
820 int line_width
, int length
, int space
,
821 int origin_x
, int origin_y
)
825 f_print_set_color(toplevel
, fp
, color
);
828 y1
= y
- height
; /* move the origin to 0, 0*/
830 o_line_print_solid(toplevel
, fp
,
831 x1
, y1
, x1
+ width
, y1
,
833 line_width
, length
, space
,
835 o_line_print_solid(toplevel
, fp
,
836 x1
+ width
, y1
, x1
+ width
, y1
+ height
,
838 line_width
, length
, space
,
840 o_line_print_solid(toplevel
, fp
,
841 x1
+ width
, y1
+ height
, x1
, y1
+ height
,
843 line_width
, length
, space
,
845 o_line_print_solid(toplevel
, fp
,
846 x1
, y1
+ height
, x1
, y1
,
848 line_width
, length
, space
,
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
,
881 int width
, int height
,
883 int line_width
, int length
, int space
,
884 int origin_x
, int origin_y
)
888 f_print_set_color(toplevel
, fp
, color
);
891 y1
= y
- height
; /* move the origin to 0, 0*/
893 o_line_print_dotted(toplevel
, fp
,
894 x1
, y1
, x1
+ width
, y1
,
896 line_width
, length
, space
,
898 o_line_print_dotted(toplevel
, fp
,
899 x1
+ width
, y1
, x1
+ width
, y1
+ height
,
901 line_width
, length
, space
,
903 o_line_print_dotted(toplevel
, fp
,
904 x1
+ width
, y1
+ height
, x1
, y1
+ height
,
906 line_width
, length
, space
,
908 o_line_print_dotted(toplevel
, fp
,
909 x1
, y1
+ height
, x1
, y1
,
911 line_width
, length
, space
,
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
,
943 int width
, int height
,
945 int line_width
, int length
, int space
,
946 int origin_x
, int origin_y
)
950 f_print_set_color(toplevel
, fp
, color
);
954 y1
= y
- height
; /* move the origin to 0, 0*/
956 o_line_print_dashed(toplevel
, fp
,
957 x1
, y1
, x1
+ width
, y1
,
959 line_width
, length
, space
,
961 o_line_print_dashed(toplevel
, fp
,
962 x1
+ width
, y1
, x1
+ width
, y1
+ height
,
964 line_width
, length
, space
,
966 o_line_print_dashed(toplevel
, fp
,
967 x1
+ width
, y1
+ height
, x1
, y1
+ height
,
969 line_width
, length
, space
,
971 o_line_print_dashed(toplevel
, fp
,
972 x1
, y1
+ height
, x1
, y1
,
974 line_width
, length
, space
,
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
,
1006 int width
, int height
,
1008 int line_width
, int length
, int space
,
1009 int origin_x
, int origin_y
)
1013 f_print_set_color(toplevel
, fp
, color
);
1016 y1
= y
- height
; /* move the origin to 0, 0*/
1018 o_line_print_center(toplevel
, fp
,
1019 x1
, y1
, x1
+ width
, y1
,
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
,
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
,
1031 line_width
, length
, space
,
1032 origin_x
, origin_y
);
1033 o_line_print_center(toplevel
, fp
,
1034 x1
, y1
+ height
, x1
, y1
,
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
,
1068 int width
, int height
,
1070 int line_width
, int length
, int space
,
1071 int origin_x
, int origin_y
)
1075 f_print_set_color(toplevel
, fp
, color
);
1078 y1
= y
- height
; /* move the origin to 0, 0*/
1080 o_line_print_phantom(toplevel
, fp
,
1081 x1
, y1
, x1
+ width
, y1
,
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
,
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
,
1093 line_width
, length
, space
,
1094 origin_x
, origin_y
);
1095 o_line_print_phantom(toplevel
, fp
,
1096 x1
, y1
+ height
, x1
, y1
,
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
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
,
1136 int width
, int height
,
1139 int angle1
, int pitch1
,
1140 int angle2
, int pitch2
,
1141 int origin_x
, int origin_y
)
1145 f_print_set_color(toplevel
, fp
, color
);
1148 y1
= y
-height
; /* move the origin to 0, 0*/
1149 fprintf(fp
, "%d %d %d %d fbox\n",
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
,
1188 int width
, int height
,
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
,
1199 angle1
, pitch1
, -1, -1,
1200 origin_x
, origin_y
);
1201 o_box_print_hatch(toplevel
, fp
,
1202 x
, y
, width
, height
,
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
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
,
1243 int width
, int height
,
1246 int angle1
, int pitch1
,
1247 int angle2
, int pitch2
,
1248 int origin_x
, int origin_y
)
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
));
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],
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
)
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
);