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
29 #include "libgeda_priv.h"
31 #ifdef HAVE_LIBDMALLOC
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
,
62 int x1
, int y1
, int x2
, int y2
)
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
));
74 /* describe the box with its upper left and lower right corner */
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
);
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
)
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
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;*/
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
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,
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.
183 * <B>whichone</B> can take the following values:
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
191 void o_box_modify(TOPLEVEL
*toplevel
, OBJECT
*object
,
192 int x
, int y
, int whichone
)
196 o_emit_pre_change_notify (toplevel
, object
);
198 /* change the position of the selected corner */
201 object
->box
->upper_x
= x
;
202 object
->box
->upper_y
= y
;
206 object
->box
->upper_x
= x
;
207 object
->box
->lower_y
= y
;
210 case BOX_UPPER_RIGHT
:
211 object
->box
->lower_x
= x
;
212 object
->box
->upper_y
= y
;
215 case BOX_LOWER_RIGHT
:
216 object
->box
->lower_x
= x
;
217 object
->box
->lower_y
= y
;
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
248 * Depending on <B>*version</B>, the correct file format is considered.
249 * Currently two file format revisions are supported :
251 * <DT>*</DT><DD>the file format used until 20000704 release
252 * <DT>*</DT><DD>the file format used for the releases after 2000704.
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
)
271 int box_width
, box_space
, box_length
;
272 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
277 if (release_ver
<= VERSION_20000704
) {
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
285 sscanf (buf
, "%c %d %d %d %d %d\n",
286 &type
, &x1
, &y1
, &width
, &height
, &color
);
290 box_type
= TYPE_SOLID
;
294 box_filling
= FILLING_HOLLOW
;
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
;
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
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
336 /* upper left corner of the box */
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 */
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
);
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
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.
370 * Caller must g_free returned character string.
372 char *o_box_save(TOPLEVEL
*toplevel
, OBJECT
*object
)
376 int box_width
, box_space
, box_length
;
377 int fill_width
, angle1
, pitch1
, angle2
, pitch2
;
379 OBJECT_TYPE box_type
;
380 OBJECT_FILLING box_fill
;
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*/
398 printf("box: %d %d %d %d\n", x1
, y1
, width
, height
);
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",
418 x1
, y1
, width
, height
, object
->color
,
419 box_width
, box_end
, box_type
, box_length
, box_space
,
421 fill_width
, angle1
, pitch1
, angle2
, pitch2
);
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
,
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;
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
,
496 /* rotate the lower left corner of the box */
497 rotate_point_90(object
->box
->lower_x
, object
->box
->lower_y
, angle
,
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
,
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
) {
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>
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
)
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 */
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
,
635 *x
= min(object
->box
->lower_x
, object
->box
->upper_x
);
636 *y
= min(object
->box
->lower_y
, object
->box
->upper_y
);
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
;
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");
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
;
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
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
699 line_width
= o_current
->line_width
;
702 if(toplevel
->line_style
== THICK
) {
703 line_width
=LINE_WIDTH
;
708 length
= o_current
->line_length
;
709 space
= o_current
->line_space
;
711 switch(o_current
->line_type
) {
713 length
= -1; space
= -1;
714 outl_func
= o_box_print_solid
;
719 outl_func
= o_box_print_dotted
;
723 outl_func
= o_box_print_dashed
;
727 outl_func
= o_box_print_center
;
731 outl_func
= o_box_print_phantom
;
735 /* Unused for now, print it solid */
736 length
= -1; space
= -1;
737 outl_func
= o_box_print_solid
;
741 if((length
== 0) || (space
== 0)) {
742 length
= -1; space
= -1;
743 outl_func
= o_box_print_solid
;
746 (*outl_func
)(toplevel
, fp
,
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
) {
773 angle1
= -1; pitch1
= 1;
774 angle2
= -1; pitch2
= 1;
776 fill_func
= o_box_print_filled
;
780 fill_func
= o_box_print_mesh
;
784 angle2
= -1; pitch2
= 1;
785 fill_func
= o_box_print_hatch
;
789 /* Unused for now, print it filled */
790 angle1
= -1; pitch1
= 1;
791 angle2
= -1; pitch2
= 1;
793 fill_func
= o_box_print_filled
;
795 case(FILLING_HOLLOW
):
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
,
811 angle1
, pitch1
, angle2
, pitch2
,
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.
844 o_box_print_solid(TOPLEVEL
*toplevel
, FILE *fp
,
846 int width
, int height
,
848 int line_width
, int length
, int space
,
849 int origin_x
, int origin_y
)
853 f_print_set_color(toplevel
, fp
, color
);
856 y1
= y
- height
; /* move the origin to 0, 0*/
858 o_line_print_solid(toplevel
, fp
,
859 x1
, y1
, x1
+ width
, y1
,
861 line_width
, length
, space
,
863 o_line_print_solid(toplevel
, fp
,
864 x1
+ width
, y1
, x1
+ width
, y1
+ height
,
866 line_width
, length
, space
,
868 o_line_print_solid(toplevel
, fp
,
869 x1
+ width
, y1
+ height
, x1
, y1
+ height
,
871 line_width
, length
, space
,
873 o_line_print_solid(toplevel
, fp
,
874 x1
, y1
+ height
, x1
, y1
,
876 line_width
, length
, space
,
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
,
909 int width
, int height
,
911 int line_width
, int length
, int space
,
912 int origin_x
, int origin_y
)
916 f_print_set_color(toplevel
, fp
, color
);
919 y1
= y
- height
; /* move the origin to 0, 0*/
921 o_line_print_dotted(toplevel
, fp
,
922 x1
, y1
, x1
+ width
, y1
,
924 line_width
, length
, space
,
926 o_line_print_dotted(toplevel
, fp
,
927 x1
+ width
, y1
, x1
+ width
, y1
+ height
,
929 line_width
, length
, space
,
931 o_line_print_dotted(toplevel
, fp
,
932 x1
+ width
, y1
+ height
, x1
, y1
+ height
,
934 line_width
, length
, space
,
936 o_line_print_dotted(toplevel
, fp
,
937 x1
, y1
+ height
, x1
, y1
,
939 line_width
, length
, space
,
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
,
971 int width
, int height
,
973 int line_width
, int length
, int space
,
974 int origin_x
, int origin_y
)
978 f_print_set_color(toplevel
, fp
, color
);
982 y1
= y
- height
; /* move the origin to 0, 0*/
984 o_line_print_dashed(toplevel
, fp
,
985 x1
, y1
, x1
+ width
, y1
,
987 line_width
, length
, space
,
989 o_line_print_dashed(toplevel
, fp
,
990 x1
+ width
, y1
, x1
+ width
, y1
+ height
,
992 line_width
, length
, space
,
994 o_line_print_dashed(toplevel
, fp
,
995 x1
+ width
, y1
+ height
, x1
, y1
+ height
,
997 line_width
, length
, space
,
999 o_line_print_dashed(toplevel
, fp
,
1000 x1
, y1
+ height
, x1
, y1
,
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
,
1034 int width
, int height
,
1036 int line_width
, int length
, int space
,
1037 int origin_x
, int origin_y
)
1041 f_print_set_color(toplevel
, fp
, color
);
1044 y1
= y
- height
; /* move the origin to 0, 0*/
1046 o_line_print_center(toplevel
, fp
,
1047 x1
, y1
, x1
+ width
, y1
,
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
,
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
,
1059 line_width
, length
, space
,
1060 origin_x
, origin_y
);
1061 o_line_print_center(toplevel
, fp
,
1062 x1
, y1
+ height
, x1
, y1
,
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
,
1096 int width
, int height
,
1098 int line_width
, int length
, int space
,
1099 int origin_x
, int origin_y
)
1103 f_print_set_color(toplevel
, fp
, color
);
1106 y1
= y
- height
; /* move the origin to 0, 0*/
1108 o_line_print_phantom(toplevel
, fp
,
1109 x1
, y1
, x1
+ width
, y1
,
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
,
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
,
1121 line_width
, length
, space
,
1122 origin_x
, origin_y
);
1123 o_line_print_phantom(toplevel
, fp
,
1124 x1
, y1
+ height
, x1
, y1
,
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
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
,
1164 int width
, int height
,
1167 int angle1
, int pitch1
,
1168 int angle2
, int pitch2
,
1169 int origin_x
, int origin_y
)
1173 f_print_set_color(toplevel
, fp
, color
);
1176 y1
= y
-height
; /* move the origin to 0, 0*/
1177 fprintf(fp
, "%d %d %d %d fbox\n",
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
,
1216 int width
, int height
,
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
,
1227 angle1
, pitch1
, -1, -1,
1228 origin_x
, origin_y
);
1229 o_box_print_hatch(toplevel
, fp
,
1230 x
, y
, width
, height
,
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
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
,
1271 int width
, int height
,
1274 int angle1
, int pitch1
,
1275 int angle2
, int pitch2
,
1276 int origin_x
, int origin_y
)
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
));
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],
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
)
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
);