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)
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 /*! \file o_box_basic.c
22  *  \brief functions for the box object
23  */
24 
25 #include <config.h>
26 #include <math.h>
27 #include <stdio.h>
28 
29 #include "libgeda_priv.h"
30 
31 #ifdef HAVE_LIBDMALLOC
32 #include <dmalloc.h>
33 #endif
34 
35 /*! \brief Create a BOX OBJECT
36  *  \par Function Description
37  *  This function creates a new object representing a box.
38  *
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.
46  *
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().
50  *
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
59  */
o_box_new(TOPLEVEL * toplevel,char type,int color,int x1,int y1,int x2,int y2)60 OBJECT *o_box_new(TOPLEVEL *toplevel,
61 		  char type, int color,
62 		  int x1, int y1, int x2, int y2)
63 {
64   OBJECT *new_node;
65   BOX *box;
66 
67   /* create the object */
68   new_node = s_basic_new_object(type, "box");
69   new_node->color = color;
70 
71   box = (BOX *) g_malloc(sizeof(BOX));
72   new_node->box   = box;
73 
74   /* describe the box with its upper left and lower right corner */
75   box->upper_x = x1;
76   box->upper_y = y1;
77   box->lower_x = x2;
78   box->lower_y = y2;
79 
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);
85 
86   /* compute the bounding box */
87   o_box_recalc(toplevel, new_node);
88 
89   return new_node;
90 }
91 
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.
96  *
97  *  \param [in]      toplevel  The TOPLEVEL object.
98  *  \param [in]      o_current  BOX OBJECT to copy.
99  *  \return The new OBJECT
100  */
o_box_copy(TOPLEVEL * toplevel,OBJECT * o_current)101 OBJECT *o_box_copy(TOPLEVEL *toplevel, OBJECT *o_current)
102 {
103   OBJECT *new_obj;
104 
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);
108 
109   /*
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.
112    *
113    * The coordinates and the values in world unit are computed with
114    *  #o_box_recalc().
115    */
116 
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;
121 
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);
129 
130   o_box_recalc(toplevel, new_obj);
131 
132   /* new_obj->attribute = 0;*/
133 
134   return new_obj;
135 }
136 
137 /*! \brief Modify a BOX OBJECT's coordinates.
138  * \par Function Description
139  * Modifies the coordinates of all four corners of \a box, by setting
140  * the box to the rectangle enclosed by the points (\a x1, \a y1) and
141  * (\a x2, \a y2).
142  *
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,
149  */
150 void
o_box_modify_all(TOPLEVEL * toplevel,OBJECT * object,int x1,int y1,int x2,int y2)151 o_box_modify_all (TOPLEVEL *toplevel, OBJECT *object,
152                   int x1, int y1, int x2, int y2)
153 {
154   o_emit_pre_change_notify (toplevel, object);
155 
156   object->box->lower_x = (x1 > x2) ? x1 : x2;
157   object->box->lower_y = (y1 > y2) ? y2 : y1;
158 
159   object->box->upper_x = (x1 > x2) ? x2 : x1;
160   object->box->upper_y = (y1 > y2) ? y1 : y2;
161 
162   /* recalculate the world coords and bounds */
163   o_box_recalc(toplevel, object);
164   o_emit_change_notify (toplevel, object);
165 }
166 
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.
172  *
173  *  The coordinates of the corner is modified in the world coordinate system.
174  *  Screen coordinates and boundings are then updated.
175  *
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.
181  *
182  *  \note
183  *  <B>whichone</B> can take the following values:
184  *  <DL>
185  *    <DT>*</DT><DD>BOX_UPPER_LEFT
186  *    <DT>*</DT><DD>BOX_LOWER_LEFT
187  *    <DT>*</DT><DD>BOX_UPPER_RIGHT
188  *    <DT>*</DT><DD>BOX_LOWER_RIGHT
189  *  </DL>
190  */
o_box_modify(TOPLEVEL * toplevel,OBJECT * object,int x,int y,int whichone)191 void o_box_modify(TOPLEVEL *toplevel, OBJECT *object,
192 		  int x, int y, int whichone)
193 {
194 	int tmp;
195 
196 	o_emit_pre_change_notify (toplevel, object);
197 
198 	/* change the position of the selected corner */
199 	switch(whichone) {
200 		case BOX_UPPER_LEFT:
201 			object->box->upper_x = x;
202 			object->box->upper_y = y;
203 			break;
204 
205 		case BOX_LOWER_LEFT:
206 			object->box->upper_x = x;
207 			object->box->lower_y = y;
208 			break;
209 
210 		case BOX_UPPER_RIGHT:
211 			object->box->lower_x = x;
212 			object->box->upper_y = y;
213 			break;
214 
215 		case BOX_LOWER_RIGHT:
216 			object->box->lower_x = x;
217 			object->box->lower_y = y;
218 			break;
219 
220 		default:
221 			return;
222 	}
223 
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;
229 	}
230 
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;
235 	}
236 
237 	/* recalculate the world coords and the boundings */
238 	o_box_recalc(toplevel, object);
239 	o_emit_change_notify (toplevel, object);
240 
241 }
242 
243 /*! \brief Create a box from a character string.
244  *  \par Function Description
245  *  This function gets the description of a box from the <B>*buf</B> character
246  *  string.
247  *
248  *  Depending on <B>*version</B>, the correct file format is considered.
249  *  Currently two file format revisions are supported :
250  *  <DL>
251  *    <DT>*</DT><DD>the file format used until 20000704 release
252  *    <DT>*</DT><DD>the file format used for the releases after 2000704.
253  *  </DL>
254  *
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, or NULL on error.
260  */
o_box_read(TOPLEVEL * toplevel,const char buf[],unsigned int release_ver,unsigned int fileformat_ver,GError ** err)261 OBJECT *o_box_read (TOPLEVEL *toplevel, const char buf[],
262                     unsigned int release_ver, unsigned int fileformat_ver, GError **err)
263 {
264   OBJECT *new_obj;
265   char type;
266   int x1, y1;
267   int width, height;
268   int d_x1, d_y1;
269   int d_x2, d_y2;
270   int color;
271   int box_width, box_space, box_length;
272   int fill_width, angle1, pitch1, angle2, pitch2;
273   int box_end;
274   int box_type;
275   int box_filling;
276 
277   if (release_ver <= VERSION_20000704) {
278 
279   /*! \note
280    *  The old geda file format, i.e. releases 20000704 and older, does not
281    *  handle the line type and the filling of the box object. They are set
282    *  to default.
283    */
284 
285     if (sscanf (buf, "%c %d %d %d %d %d\n",
286 		&type, &x1, &y1, &width, &height, &color) != 6) {
287       g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse box object"));
288       return NULL;
289     }
290 
291     box_width   = 0;
292     box_end     = END_NONE;
293     box_type    = TYPE_SOLID;
294     box_length  = -1;
295     box_space   = -1;
296 
297     box_filling = FILLING_HOLLOW;
298     fill_width  = 0;
299     angle1      = -1;
300     pitch1      = -1;
301     angle2      = -1;
302     pitch2      = -1;
303 
304   } else {
305 
306     /*! \note
307      *  The current line format to describe a box is a space separated list of
308      *  characters and numbers in plain ASCII on a single line. The meaning of
309      *  each item is described in the file format documentation.
310      */
311     if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
312 		&type, &x1, &y1, &width, &height, &color,
313 		&box_width, &box_end, &box_type, &box_length,
314 		&box_space, &box_filling,
315 		&fill_width, &angle1, &pitch1, &angle2, &pitch2) != 17) {
316       g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse box object"));
317       return NULL;
318     }
319   }
320 
321   if (width == 0 || height == 0) {
322     s_log_message (_("Found a zero width/height box [ %c %d %d %d %d %d ]\n"),
323                    type, x1, y1, width, height, color);
324   }
325 
326   if (color < 0 || color > MAX_COLORS) {
327     s_log_message (_("Found an invalid color [ %s ]\n"), buf);
328     s_log_message (_("Setting color to default color\n"));
329     color = DEFAULT_COLOR;
330   }
331 
332   /*! \note
333    *  A box is internally described by its lower right and upper left corner
334    *  whereas the line describe it with the lower left corner and the width
335    *  and height.
336    *
337    *  A new object is allocated, initialized and added to the object list.
338    *  Its filling and line type are set according to the values of the field
339    *  on the line.
340    */
341 
342   /* upper left corner of the box */
343   d_x1 = x1;
344   d_y1 = y1 + height; /* move box origin to top left */
345 
346   /* lower right corner of the box */
347   d_x2 = x1 + width;  /* end points of the box */
348   d_y2 = y1;
349 
350   /* create a new box */
351   new_obj = o_box_new (toplevel, type, color, d_x1, d_y1, d_x2, d_y2);
352   /* set its line options */
353   o_set_line_options (toplevel, new_obj,
354                       box_end, box_type, box_width,
355                       box_length, box_space);
356   /* set its fill options */
357   o_set_fill_options (toplevel, new_obj,
358                       box_filling, fill_width,
359                       pitch1, angle1, pitch2, angle2);
360 
361   return new_obj;
362 }
363 
364 /*! \brief Create a character string representation of a BOX.
365  *  \par Function Description
366  *  This function formats a string in the buffer <B>*buff</B> to describe the
367  *  box object <B>*object</B>.
368  *  It follows the post-20000704 release file format that handle the line type
369  *  and fill options.
370  *
371  *  \param [in] toplevel  The TOPLEVEL structure.
372  *  \param [in] object  The BOX OBJECT to create string from.
373  *  \return A pointer to the BOX character string.
374  *
375  *  \warning
376  *  Caller must g_free returned character string.
377  */
o_box_save(TOPLEVEL * toplevel,OBJECT * object)378 char *o_box_save(TOPLEVEL *toplevel, OBJECT *object)
379 {
380   int x1, y1;
381   int width, height;
382   int box_width, box_space, box_length;
383   int fill_width, angle1, pitch1, angle2, pitch2;
384   OBJECT_END box_end;
385   OBJECT_TYPE box_type;
386   OBJECT_FILLING box_fill;
387   char *buf;
388 
389   /*! \note
390    *  A box is internally represented by its lower right and upper left corner
391    *  whereas it is described in the file format as its lower left corner and
392    *  its width and height.
393    */
394 
395   /* calculate the width and height of the box */
396   width  = abs(object->box->lower_x - object->box->upper_x);
397   height = abs(object->box->upper_y - object->box->lower_y);
398 
399   /* calculate the lower left corner of the box */
400   x1 = object->box->upper_x;
401   y1 = object->box->upper_y - height; /* move the origin to 0, 0*/
402 
403 #if DEBUG
404   printf("box: %d %d %d %d\n", x1, y1, width, height);
405 #endif
406 
407   /* description of the line type for the outline */
408   box_end    = object->line_end;
409   box_width  = object->line_width;
410   box_type   = object->line_type;
411   box_length = object->line_length;
412   box_space  = object->line_space;
413 
414   /* description of the filling of the box */
415   box_fill   = object->fill_type;
416   fill_width = object->fill_width;
417   angle1     = object->fill_angle1;
418   pitch1     = object->fill_pitch1;
419   angle2     = object->fill_angle2;
420   pitch2     = object->fill_pitch2;
421 
422   buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
423 			object->type,
424 			x1, y1, width, height, object->color,
425 			box_width, box_end, box_type, box_length, box_space,
426 			box_fill,
427 			fill_width, angle1, pitch1, angle2, pitch2);
428 
429   return(buf);
430 }
431 
432 /*! \brief Translate a BOX position in WORLD coordinates by a delta.
433  *  \par Function Description
434  *  This function applies a translation of (<B>x1</B>,<B>y1</B>) to the box
435  *  described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
436  *
437  *  \param [in]     toplevel  The TOPLEVEL object.
438  *  \param [in]     dx         x distance to move.
439  *  \param [in]     dy         y distance to move.
440  *  \param [in,out] object     BOX OBJECT to translate.
441  */
o_box_translate_world(TOPLEVEL * toplevel,int dx,int dy,OBJECT * object)442 void o_box_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object)
443 {
444   /* Do world coords */
445   object->box->upper_x = object->box->upper_x + dx;
446   object->box->upper_y = object->box->upper_y + dy;
447   object->box->lower_x = object->box->lower_x + dx;
448   object->box->lower_y = object->box->lower_y + dy;
449 
450   /* recalc the screen coords and the bounding box */
451   o_box_recalc(toplevel, object);
452 }
453 
454 /*! \brief Rotate BOX OBJECT using WORLD coordinates.
455  *  \par Function Description
456  *  The function #o_box_rotate_world() rotate the box described by
457  *  <B>*object</B> around the (<B>world_centerx</B>, <B>world_centery</B>) point by
458  *  <B>angle</B> degrees.
459  *  The center of rotation is in world unit.
460  *
461  *  \param [in]      toplevel      The TOPLEVEL object.
462  *  \param [in]      world_centerx  Rotation center x coordinate in WORLD units.
463  *  \param [in]      world_centery  Rotation center y coordinate in WORLD units.
464  *  \param [in]      angle          Rotation angle in degrees (See note below).
465  *  \param [in,out]  object         BOX OBJECT to rotate.
466  *
467  */
o_box_rotate_world(TOPLEVEL * toplevel,int world_centerx,int world_centery,int angle,OBJECT * object)468 void o_box_rotate_world(TOPLEVEL *toplevel,
469 			int world_centerx, int world_centery, int angle,
470 			OBJECT *object)
471 {
472   int newx1, newy1;
473   int newx2, newy2;
474 
475   /*! \note
476    *  Only 90 degree multiple and positive angles are allowed.
477    */
478 
479   /* angle must be positive */
480   if(angle < 0) angle = -angle;
481   /* angle must be a 90 multiple or no rotation performed */
482   if((angle % 90) != 0) return;
483 
484   /*! \note
485    *  The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is
486    *  translated to the origin. The rotation of the upper left and lower right
487    *  corner are then performed. Finally, the rotated box is translated back
488    *  to its previous location.
489    */
490   /* translate object to origin */
491   object->box->upper_x -= world_centerx;
492   object->box->upper_y -= world_centery;
493   object->box->lower_x -= world_centerx;
494   object->box->lower_y -= world_centery;
495 
496   /* rotate the upper left corner of the box */
497   rotate_point_90(object->box->upper_x, object->box->upper_y, angle,
498 		  &newx1, &newy1);
499 
500   /* rotate the lower left corner of the box */
501   rotate_point_90(object->box->lower_x, object->box->lower_y, angle,
502 		  &newx2, &newy2);
503 
504   /* reorder the corners after rotation */
505   object->box->upper_x = min(newx1,newx2);
506   object->box->upper_y = max(newy1,newy2);
507   object->box->lower_x = max(newx1,newx2);
508   object->box->lower_y = min(newy1,newy2);
509 
510   /* translate object back to normal position */
511   object->box->upper_x += world_centerx;
512   object->box->upper_y += world_centery;
513   object->box->lower_x += world_centerx;
514   object->box->lower_y += world_centery;
515 
516   /* recalc boundings and world coords */
517   o_box_recalc(toplevel, object);
518 }
519 
520 /*! \brief Mirror BOX using WORLD coordinates.
521  *  \par Function Description
522  *  This function mirrors the box from the point
523  *  (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
524  *
525  *  The box is first translated to the origin, then mirrored and finally
526  *  translated back at its previous position.
527  *
528  *  \param [in]     toplevel      The TOPLEVEL object.
529  *  \param [in]     world_centerx  Origin x coordinate in WORLD units.
530  *  \param [in]     world_centery  Origin y coordinate in WORLD units.
531  *  \param [in,out] object         BOX OBJECT to mirror.
532  */
o_box_mirror_world(TOPLEVEL * toplevel,int world_centerx,int world_centery,OBJECT * object)533 void o_box_mirror_world(TOPLEVEL *toplevel,
534 			int world_centerx, int world_centery,
535 			OBJECT *object)
536 {
537   int newx1, newy1;
538   int newx2, newy2;
539 
540   /* translate object to origin */
541   object->box->upper_x -= world_centerx;
542   object->box->upper_y -= world_centery;
543   object->box->lower_x -= world_centerx;
544   object->box->lower_y -= world_centery;
545 
546   /* mirror the corners */
547   newx1 = -object->box->upper_x;
548   newy1 = object->box->upper_y;
549   newx2 = -object->box->lower_x;
550   newy2 = object->box->lower_y;
551 
552   /* reorder the corners */
553   object->box->upper_x = min(newx1,newx2);
554   object->box->upper_y = max(newy1,newy2);
555   object->box->lower_x = max(newx1,newx2);
556   object->box->lower_y = min(newy1,newy2);
557 
558   /* translate back in position */
559   object->box->upper_x += world_centerx;
560   object->box->upper_y += world_centery;
561   object->box->lower_x += world_centerx;
562   object->box->lower_y += world_centery;
563 
564   /* recalc boundings and world coords */
565   o_box_recalc(toplevel, object);
566 
567 }
568 
569 /*! \brief Recalculate BOX coordinates in WORLD units.
570  *  \par Function Description
571  *  This function recalculates the box coordinates and its
572  *  bounding are recalculated as well.
573  *
574  *  \param [in] toplevel      The TOPLEVEL object.
575  *  \param [in,out] o_current  BOX OBJECT to be recalculated.
576  */
o_box_recalc(TOPLEVEL * toplevel,OBJECT * o_current)577 void o_box_recalc(TOPLEVEL *toplevel, OBJECT *o_current)
578 {
579   int left, top, right, bottom;
580 
581   if (o_current->box == NULL) {
582     return;
583   }
584 
585   /* update the bounding box - world unit */
586   world_get_box_bounds(toplevel, o_current, &left, &top, &right, &bottom);
587   o_current->w_left   = left;
588   o_current->w_top    = top;
589   o_current->w_right  = right;
590   o_current->w_bottom = bottom;
591   o_current->w_bounds_valid = TRUE;
592 }
593 
594 /*! \brief Get BOX bounding rectangle in WORLD coordinates.
595  *  \par Function Description
596  *  This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
597  *  parameters to the boundings of the box object described in <B>*box</B>
598  *  in world units.
599  *
600  *  \param [in]  toplevel  The TOPLEVEL object.
601  *  \param [in]  object     BOX OBJECT to read coordinates from.
602  *  \param [out] left       Left box coordinate in WORLD units.
603  *  \param [out] top        Top box coordinate in WORLD units.
604  *  \param [out] right      Right box coordinate in WORLD units.
605  *  \param [out] bottom     Bottom box coordinate in WORLD units.
606  */
world_get_box_bounds(TOPLEVEL * toplevel,OBJECT * object,int * left,int * top,int * right,int * bottom)607 void world_get_box_bounds(TOPLEVEL *toplevel, OBJECT *object,
608                           int *left, int *top, int *right, int *bottom)
609 {
610   int halfwidth;
611 
612   halfwidth = object->line_width / 2;
613 
614   *left   = min(object->box->upper_x, object->box->lower_x);
615   *top    = min(object->box->upper_y, object->box->lower_y);
616   *right  = max(object->box->upper_x, object->box->lower_x);
617   *bottom = max(object->box->upper_y, object->box->lower_y);
618 
619   /* This isn't strictly correct, but a 1st order approximation */
620   *left   -= halfwidth;
621   *top    -= halfwidth;
622   *right  += halfwidth;
623   *bottom += halfwidth;
624 }
625 
626 /*! \brief get the position of the left bottom point
627  *  \par Function Description
628  *  This function gets the position of the bottom left point of a box object.
629  *
630  *  \param [in] toplevel The toplevel environment.
631  *  \param [out] x       pointer to the x-position
632  *  \param [out] y       pointer to the y-position
633  *  \param [in] object   The object to get the position.
634  *  \return TRUE if successfully determined the position, FALSE otherwise
635  */
o_box_get_position(TOPLEVEL * toplevel,gint * x,gint * y,OBJECT * object)636 gboolean o_box_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
637                               OBJECT *object)
638 {
639   *x = min(object->box->lower_x, object->box->upper_x);
640   *y = min(object->box->lower_y, object->box->upper_y);
641   return TRUE;
642 }
643 
644 /*! \brief Print BOX to Postscript document.
645  *  \par Function Description
646  *  This function prints the box described by the <B>o_current</B>
647  *  parameter to a Postscript document. It takes into account its line
648  *  type and fill type.
649  *  The Postscript document is descibed by the file pointer <B>fp</B>.
650  *
651  *  The validity of the <B>o_current</B> parameter is verified : a null pointer
652  *  causes an error message and a return.
653  *
654  *  The description of the box is extracted from
655  *  the <B>o_current</B> parameter :
656  *  the coordinates of the box - upper left corner and width and
657  *  height of the box -, its line type, its fill type.
658  *
659  *  The outline and the inside of the box are successively handled by two
660  *  differend sets of functions.
661  *
662  *  \param [in] toplevel  The TOPLEVEL object.
663  *  \param [in] fp         FILE pointer to Postscript document.
664  *  \param [in] o_current  BOX OBJECT to write to document.
665  *  \param [in] origin_x   Page x coordinate to place BOX OBJECT.
666  *  \param [in] origin_y   Page y coordinate to place BOX OBJECT.
667  */
o_box_print(TOPLEVEL * toplevel,FILE * fp,OBJECT * o_current,int origin_x,int origin_y)668 void o_box_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
669 		 int origin_x, int origin_y)
670 {
671   int x, y, width, height;
672   int color;
673   int line_width, length, space;
674   int fill_width, angle1, pitch1, angle2, pitch2;
675   void (*outl_func)() = NULL;
676   void (*fill_func)() = NULL;
677 
678   if (o_current == NULL) {
679     printf("got null in o_box_print\n");
680     return;
681   }
682 
683   x = o_current->box->upper_x;
684   y = o_current->box->upper_y;
685   width  = abs(o_current->box->lower_x - o_current->box->upper_x);
686   height = abs(o_current->box->lower_y - o_current->box->upper_y);
687   color  = o_current->color;
688 
689   /*! \note
690    *  Depending on the type of the line for this particular box, the
691    *  appropriate function is chosen among #o_box_print_solid(),
692    *  #o_box_print_dotted(), #o_box_print_dashed(),
693    *  #o_box_print_center() and #o_box_print_phantom().
694    *
695    *  The needed parameters for each of these type is extracted from the
696    *  <B>o_current</B> object. Depending on the type, unused parameters are
697    *  set to -1.
698    *
699    *  In the eventuality of a length and/or space null, the line is printed
700    *  solid to avoid and endless loop produced by other functions in such a
701    *  case.
702    */
703   line_width = o_current->line_width;
704 
705   if(line_width <=2) {
706     if(toplevel->line_style == THICK) {
707       line_width=LINE_WIDTH;
708     } else {
709       line_width=2;
710     }
711   }
712   length = o_current->line_length;
713   space  = o_current->line_space;
714 
715   switch(o_current->line_type) {
716     case(TYPE_SOLID):
717       length = -1; space  = -1;
718       outl_func = o_box_print_solid;
719       break;
720 
721     case(TYPE_DOTTED):
722       length = -1;
723       outl_func = o_box_print_dotted;
724       break;
725 
726     case(TYPE_DASHED):
727       outl_func = o_box_print_dashed;
728       break;
729 
730     case(TYPE_CENTER):
731       outl_func = o_box_print_center;
732       break;
733 
734     case(TYPE_PHANTOM):
735       outl_func = o_box_print_phantom;
736       break;
737 
738     case(TYPE_ERASE):
739       /* Unused for now, print it solid */
740       length = -1; space  = -1;
741       outl_func = o_box_print_solid;
742       break;
743   }
744 
745   if((length == 0) || (space == 0)) {
746     length = -1; space  = -1;
747     outl_func = o_box_print_solid;
748   }
749 
750   (*outl_func)(toplevel, fp,
751 	       x, y, width, height,
752 	       color,
753 	       line_width,
754 	       length, space,
755 	       origin_x, origin_y);
756 
757   /*! \note
758    *  If the filling type of the box is not <B>HOLLOW</B>, the appropriate
759    *  function is chosen among #o_box_print_filled(), #o_box_print_mesh()
760    *  and #o_box_print_hatch(). The corresponding parameters are extracted
761    *  from the <B>o_current</B> object and corrected afterward.
762    *
763    *  The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
764    *  avoided as it leads to an endless loop in most of the called functions.
765    *  In such a case, the box is printed filled. Unused parameters for each of
766    *  these functions are set to -1 or any passive value.
767    */
768   if(o_current->fill_type != FILLING_HOLLOW) {
769     fill_width = o_current->fill_width;
770     angle1     = o_current->fill_angle1;
771     pitch1     = o_current->fill_pitch1;
772     angle2     = o_current->fill_angle2;
773     pitch2     = o_current->fill_pitch2;
774 
775     switch(o_current->fill_type) {
776       case(FILLING_FILL):
777 	angle1 = -1; pitch1 = 1;
778 	angle2 = -1; pitch2 = 1;
779 	fill_width = -1;
780 	fill_func = o_box_print_filled;
781 	break;
782 
783       case(FILLING_MESH):
784 	fill_func = o_box_print_mesh;
785 	break;
786 
787       case(FILLING_HATCH):
788 	angle2 = -1; pitch2 = 1;
789 	fill_func = o_box_print_hatch;
790 	break;
791 
792       case(FILLING_VOID):
793 	/* Unused for now, print it filled */
794 	angle1 = -1; pitch1 = 1;
795 	angle2 = -1; pitch2 = 1;
796 	fill_width = -1;
797 	fill_func = o_box_print_filled;
798 	break;
799       case(FILLING_HOLLOW):
800 	/* nop */
801 	break;
802 
803     }
804 
805     if((pitch1 <= 0) || (pitch2 <= 0)) {
806       angle1 = -1; pitch1 = 1;
807       angle2 = -1; pitch2 = 1;
808       fill_func = o_box_print_filled;
809     }
810 
811     (*fill_func)(toplevel, fp,
812                  x, y, width, height,
813                  color,
814                  fill_width,
815                  angle1, pitch1, angle2, pitch2,
816                  origin_x, origin_y);
817   }
818 }
819 
820 /*! \brief Print a solid BOX to Postscript document.
821  *  \par Function Description
822  *  This function prints the outline of a box when a solid line type is
823  *  required. The box is defined by the coordinates of its upper left corner
824  *  in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
825  *  <B>height</B> parameters.
826  *  The postscript file is defined by the file pointer <B>fp</B>.
827  *  The parameters <B>length</B> and <B>space</B> are ignored.
828  *
829  *  It uses the function #o_line_print_solid() to print the outline.
830  *  It performs four calls to this function, one for each of its side.
831  *
832  *  All dimensions are in mils.
833  *
834  *  \param [in] toplevel   The TOPLEVEL object.
835  *  \param [in] fp          FILE pointer to Postscript document.
836  *  \param [in] x           Upper x coordinate of BOX.
837  *  \param [in] y           Upper y coordinate of BOX.
838  *  \param [in] width       Width of BOX.
839  *  \param [in] height      Height of BOX.
840  *  \param [in] color       BOX color.
841  *  \param [in] line_width  BOX Line width.
842  *  \param [in] length      Dashed line length.
843  *  \param [in] space       Amount of space between dashes.
844  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
845  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
846  */
847 void
o_box_print_solid(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int line_width,int length,int space,int origin_x,int origin_y)848 o_box_print_solid(TOPLEVEL *toplevel, FILE *fp,
849                   int x, int y,
850                   int width, int height,
851                   int color,
852                   int line_width, int length, int space,
853                   int origin_x, int origin_y)
854 {
855   int x1, y1;
856 
857   f_print_set_color(toplevel, fp, color);
858 
859   x1 = x;
860   y1 = y - height; /* move the origin to 0, 0*/
861 
862   o_line_print_solid(toplevel, fp,
863                      x1, y1, x1 + width, y1,
864                      color,
865                      line_width, length, space,
866                      origin_x, origin_y);
867   o_line_print_solid(toplevel, fp,
868                      x1 + width, y1, x1 + width, y1 + height,
869                      color,
870                      line_width, length, space,
871                      origin_x, origin_y);
872   o_line_print_solid(toplevel, fp,
873                      x1 + width, y1 + height, x1, y1 + height,
874                      color,
875                      line_width, length, space,
876                      origin_x, origin_y);
877   o_line_print_solid(toplevel, fp,
878                      x1, y1 + height, x1, y1,
879                      color,
880                      line_width, length, space,
881                      origin_x, origin_y);
882 }
883 
884 /*! \brief Print a dotted BOX to Postscript document.
885  *  \par Function Description
886  *  This function prints the outline of a box when a dotted line type is
887  *  required. The box is defined by the coordinates of its upper left corner
888  *  in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
889  *  <B>height</B> parameters.
890  *  The postscript file is defined by the file pointer <B>fp</B>.
891  *  The parameters <B>length</B> is ignored.
892  *
893  *  It uses the function #o_line_print_dotted() to print the outline.
894  *  It performs four calls to this function, one for each of its side.
895  *
896  *  All dimensions are in mils.
897  *
898  *  \param [in] toplevel   The TOPLEVEL object.
899  *  \param [in] fp          FILE pointer to Postscript document.
900  *  \param [in] x           Upper x coordinate of BOX.
901  *  \param [in] y           Upper y coordinate of BOX.
902  *  \param [in] width       Width of BOX.
903  *  \param [in] height      Height of BOX.
904  *  \param [in] color       BOX color.
905  *  \param [in] line_width  BOX Line width.
906  *  \param [in] length      Dashed line length.
907  *  \param [in] space       Amount of space between dashes.
908  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
909  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
910  */
o_box_print_dotted(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int line_width,int length,int space,int origin_x,int origin_y)911 void o_box_print_dotted(TOPLEVEL *toplevel, FILE *fp,
912 			int x, int y,
913 			int width, int height,
914 			int color,
915 			int line_width, int length, int space,
916 			int origin_x, int origin_y)
917 {
918   int x1, y1;
919 
920   f_print_set_color(toplevel, fp, color);
921 
922   x1 = x;
923   y1 = y - height; /* move the origin to 0, 0*/
924 
925   o_line_print_dotted(toplevel, fp,
926                       x1, y1, x1 + width, y1,
927                       color,
928                       line_width, length, space,
929                       origin_x, origin_y);
930   o_line_print_dotted(toplevel, fp,
931                       x1 + width, y1, x1 + width, y1 + height,
932                       color,
933                       line_width, length, space,
934                       origin_x, origin_y);
935   o_line_print_dotted(toplevel, fp,
936                       x1 + width, y1 + height, x1, y1 + height,
937                       color,
938                       line_width, length, space,
939                       origin_x, origin_y);
940   o_line_print_dotted(toplevel, fp,
941                       x1, y1 + height, x1, y1,
942                       color,
943                       line_width, length, space,
944                       origin_x, origin_y);
945 }
946 
947 /*! \brief Print a dashed BOX to Postscript document.
948  *  \par Function Description
949  *  This function prints the outline of a box when a dashed line type is
950  *  required. The box is defined by the coordinates of its upper left corner
951  *  in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
952  *  <B>height</B> parameters.
953  *  The postscript file is defined by the file pointer <B>fp</B>.
954  *
955  *  It uses the function #o_line_print_dashed() to print the outline.
956  *  It performs four calls to this function, one for each of its side.
957  *
958  *  All dimensions are in mils.
959  *
960  *  \param [in] toplevel   The TOPLEVEL object.
961  *  \param [in] fp          FILE pointer to Postscript document.
962  *  \param [in] x           Upper x coordinate of BOX.
963  *  \param [in] y           Upper y coordinate of BOX.
964  *  \param [in] width       Width of BOX.
965  *  \param [in] height      Height of BOX.
966  *  \param [in] color       BOX color.
967  *  \param [in] line_width  BOX Line width.
968  *  \param [in] length      Dashed line length.
969  *  \param [in] space       Amount of space between dashes.
970  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
971  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
972  */
o_box_print_dashed(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int line_width,int length,int space,int origin_x,int origin_y)973 void o_box_print_dashed(TOPLEVEL *toplevel, FILE *fp,
974 			int x, int y,
975 			int width, int height,
976 			int color,
977 			int line_width, int length, int space,
978 			int origin_x, int origin_y)
979 {
980   int x1, y1;
981 
982   f_print_set_color(toplevel, fp, color);
983 
984 
985   x1 = x;
986   y1 = y - height; /* move the origin to 0, 0*/
987 
988   o_line_print_dashed(toplevel, fp,
989                       x1, y1, x1 + width, y1,
990                       color,
991                       line_width, length, space,
992                       origin_x, origin_y);
993   o_line_print_dashed(toplevel, fp,
994                       x1 + width, y1, x1 + width, y1 + height,
995                       color,
996                       line_width, length, space,
997                       origin_x, origin_y);
998   o_line_print_dashed(toplevel, fp,
999                       x1 + width, y1 + height, x1, y1 + height,
1000                       color,
1001                       line_width, length, space,
1002                       origin_x, origin_y);
1003   o_line_print_dashed(toplevel, fp,
1004                       x1, y1 + height, x1, y1,
1005                       color,
1006                       line_width, length, space,
1007                       origin_x, origin_y);
1008 }
1009 
1010 /*! \brief Print centered line type BOX to Postscript document.
1011  *  \par Function Description
1012  *  This function prints the outline of a box when a centered line type is
1013  *  required. The box is defined by the coordinates of its upper left corner
1014  *  in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1015  *  <B>height</B> parameters.
1016  *  The postscript file is defined by the file pointer <B>fp</B>.
1017  *
1018  *  It uses the function #o_line_print_center() to print the outline.
1019  *  It performs four calls to this function, one for each of its side.
1020  *
1021  *  All dimensions are in mils.
1022  *
1023  *  \param [in] toplevel   The TOPLEVEL object.
1024  *  \param [in] fp          FILE pointer to Postscript document.
1025  *  \param [in] x           Upper x coordinate of BOX.
1026  *  \param [in] y           Upper y coordinate of BOX.
1027  *  \param [in] width       Width of BOX.
1028  *  \param [in] height      Height of BOX.
1029  *  \param [in] color       BOX color.
1030  *  \param [in] line_width  BOX Line width.
1031  *  \param [in] length      Dashed line length.
1032  *  \param [in] space       Amount of space between dashes.
1033  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
1034  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
1035  */
o_box_print_center(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int line_width,int length,int space,int origin_x,int origin_y)1036 void o_box_print_center(TOPLEVEL *toplevel, FILE *fp,
1037 			int x, int y,
1038 			int width, int height,
1039 			int color,
1040 			int line_width, int length, int space,
1041 			int origin_x, int origin_y)
1042 {
1043   int x1, y1;
1044 
1045   f_print_set_color(toplevel, fp, color);
1046 
1047   x1 = x;
1048   y1 = y - height; /* move the origin to 0, 0*/
1049 
1050   o_line_print_center(toplevel, fp,
1051                       x1, y1, x1 + width, y1,
1052                       color,
1053                       line_width, length, space,
1054                       origin_x, origin_y);
1055   o_line_print_center(toplevel, fp,
1056                       x1 + width, y1, x1 + width, y1 + height,
1057                       color,
1058                       line_width, length, space,
1059                       origin_x, origin_y);
1060   o_line_print_center(toplevel, fp,
1061                       x1 + width, y1 + height, x1, y1 + height,
1062                       color,
1063                       line_width, length, space,
1064                       origin_x, origin_y);
1065   o_line_print_center(toplevel, fp,
1066                       x1, y1 + height, x1, y1,
1067                       color,
1068                       line_width, length, space,
1069                       origin_x, origin_y);
1070 }
1071 
1072 /*! \brief Print phantom line type BOX to Postscript document.
1073  *  \par Function Description
1074  *  This function prints the outline of a box when a phantom line type is
1075  *  required. The box is defined by the coordinates of its upper left corner
1076  *  in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1077  *  <B>height</B> parameters.
1078  *  The postscript file is defined by the file pointer <B>fp</B>.
1079  *
1080  *  It uses the function #o_line_print_phantom() to print the outline.
1081  *  It performs four calls to this function, one for each of its side.
1082  *
1083  *  All dimensions are in mils.
1084  *
1085  *  \param [in] toplevel   The TOPLEVEL object.
1086  *  \param [in] fp          FILE pointer to Postscript document.
1087  *  \param [in] x           Upper x coordinate of BOX.
1088  *  \param [in] y           Upper y coordinate of BOX.
1089  *  \param [in] width       Width of BOX.
1090  *  \param [in] height      Height of BOX.
1091  *  \param [in] color       BOX color.
1092  *  \param [in] line_width  BOX Line width.
1093  *  \param [in] length      Dashed line length.
1094  *  \param [in] space       Amount of space between dashes.
1095  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
1096  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
1097  */
o_box_print_phantom(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int line_width,int length,int space,int origin_x,int origin_y)1098 void o_box_print_phantom(TOPLEVEL *toplevel, FILE *fp,
1099 			 int x, int y,
1100 			 int width, int height,
1101 			 int color,
1102 			 int line_width, int length, int space,
1103 			 int origin_x, int origin_y)
1104 {
1105   int x1, y1;
1106 
1107   f_print_set_color(toplevel, fp, color);
1108 
1109   x1 = x;
1110   y1 = y - height; /* move the origin to 0, 0*/
1111 
1112   o_line_print_phantom(toplevel, fp,
1113                        x1, y1, x1 + width, y1,
1114                        color,
1115                        line_width, length, space,
1116                        origin_x, origin_y);
1117   o_line_print_phantom(toplevel, fp,
1118                        x1 + width, y1, x1 + width, y1 + height,
1119                        color,
1120                        line_width, length, space,
1121                        origin_x, origin_y);
1122   o_line_print_phantom(toplevel, fp,
1123                        x1 + width, y1 + height, x1, y1 + height,
1124                        color,
1125                        line_width, length, space,
1126                        origin_x, origin_y);
1127   o_line_print_phantom(toplevel, fp,
1128                        x1, y1 + height, x1, y1,
1129                        color,
1130                        line_width, length, space,
1131                        origin_x, origin_y);
1132 }
1133 
1134 /*! \brief Print a solid pattern BOX to Postscript document.
1135  *  \par Function Description
1136  *  The function prints a filled box with a solid pattern. No outline is
1137  *  printed.
1138  *  The box is defined by the coordinates of its upper left corner in
1139  *  (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
1140  *  <B>height</B> parameters. The postscript file is defined by the file
1141  *  pointer <B>fp</B>.
1142  *  <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B> and <B>pitch2</B>
1143  *  parameters are ignored in this functions but kept for compatibility
1144  *  with other fill functions.
1145  *
1146  *  It uses the fbox postscript function defined in the prolog to
1147  *  specify a filled box.
1148  *
1149  *  All dimensions are in mils.
1150  *
1151  *  \param [in] toplevel   The TOPLEVEL object.
1152  *  \param [in] fp          FILE pointer to Postscript document.
1153  *  \param [in] x           Upper x coordinate of BOX.
1154  *  \param [in] y           Upper y coordinate of BOX.
1155  *  \param [in] width       Width of BOX.
1156  *  \param [in] height      Height of BOX.
1157  *  \param [in] color       BOX color.
1158  *  \param [in] fill_width  BOX fill width. (unused).
1159  *  \param [in] angle1      (unused).
1160  *  \param [in] pitch1      (unused).
1161  *  \param [in] angle2      (unused).
1162  *  \param [in] pitch2      (unused).
1163  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
1164  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
1165  */
o_box_print_filled(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int fill_width,int angle1,int pitch1,int angle2,int pitch2,int origin_x,int origin_y)1166 void o_box_print_filled(TOPLEVEL *toplevel, FILE *fp,
1167 			int x, int y,
1168 			int width, int height,
1169 			int color,
1170 			int fill_width,
1171 			int angle1, int pitch1,
1172 			int angle2, int pitch2,
1173 			int origin_x, int origin_y)
1174 {
1175   int x1, y1;
1176 
1177   f_print_set_color(toplevel, fp, color);
1178 
1179   x1 = x;
1180   y1 = y-height; /* move the origin to 0, 0*/
1181   fprintf(fp, "%d %d %d %d fbox\n",
1182 	  width, height,
1183 	  x1-origin_x, y1-origin_y);
1184 
1185 }
1186 
1187 /*! \brief Print a mesh pattern BOX to Postscript document.
1188  *  \par Function Description
1189  *  This function prints a meshed box. No outline is printed. The box is
1190  *  defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
1191  *  its width and height given by the <B>width</B> and <B>height</B> parameters.
1192  *  The postscript file is defined by the file pointer <B>fp</B>.
1193  *
1194  *  The inside mesh is achieved by two successive call to the
1195  *  #o_box_print_hatch() function, given <B>angle1</B> and <B>pitch1</B> the first
1196  *  time and <B>angle2</B> and <B>pitch2</B> the second time.
1197  *
1198  *  Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are not allowed
1199  *  as it leads to an endless loop in #o_box_print_hatch().
1200  *
1201  *  All dimensions are in mils.
1202  *
1203  *  \param [in] toplevel   The TOPLEVEL object.
1204  *  \param [in] fp          FILE pointer to Postscript document.
1205  *  \param [in] x           Upper x coordinate of BOX.
1206  *  \param [in] y           Upper y coordinate of BOX.
1207  *  \param [in] width       Width of BOX.
1208  *  \param [in] height      Height of BOX.
1209  *  \param [in] color       BOX color.
1210  *  \param [in] fill_width  BOX fill width.
1211  *  \param [in] angle1      1st angle for mesh pattern.
1212  *  \param [in] pitch1      1st pitch for mesh pattern.
1213  *  \param [in] angle2      2nd angle for mesh pattern.
1214  *  \param [in] pitch2      2nd pitch for mesh pattern.
1215  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
1216  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
1217  */
o_box_print_mesh(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int fill_width,int angle1,int pitch1,int angle2,int pitch2,int origin_x,int origin_y)1218 void o_box_print_mesh(TOPLEVEL *toplevel, FILE *fp,
1219 		      int x, int y,
1220 		      int width, int height,
1221 		      int color,
1222 		      int fill_width,
1223 		      int angle1, int pitch1,
1224 		      int angle2, int pitch2,
1225 		      int origin_x, int origin_y)
1226 {
1227   o_box_print_hatch(toplevel, fp,
1228                     x, y, width, height,
1229                     color,
1230                     fill_width,
1231                     angle1, pitch1, -1, -1,
1232                     origin_x, origin_y);
1233   o_box_print_hatch(toplevel, fp,
1234                     x, y, width, height,
1235                     color,
1236                     fill_width,
1237                     angle2, pitch2, -1, -1,
1238                     origin_x, origin_y);
1239 
1240 }
1241 
1242 /*! \brief Print a hatch pattern BOX to Postscript document.
1243  *  \par Function Description
1244  *  The function prints a hatched box. No outline is printed. The box is
1245  *  defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
1246  *  its width and height given by the <B>width</B> and <B>height</B> parameters.
1247  *  The postscript file is defined by the file pointer <B>fp</B>.
1248  *  <B>fill_width</B>, <B>angle1</B>, <B>pitch1</B> parameters define the way the box
1249  *  has to be hatched.
1250  *  <B>angle2</B> and <B>pitch2</B> parameters are unused but kept for compatibility
1251  *  with other fill functions.
1252  *
1253  *  Negative or null values for <B>pitch1</B> are not allowed as it leads to an
1254  *  endless loop.
1255  *
1256  *  All dimensions are in mils.
1257  *
1258  *  \param [in] toplevel   The TOPLEVEL object.
1259  *  \param [in] fp          FILE pointer to Postscript document.
1260  *  \param [in] x           Upper x coordinate of BOX.
1261  *  \param [in] y           Upper y coordinate of BOX.
1262  *  \param [in] width       Width of BOX.
1263  *  \param [in] height      Height of BOX.
1264  *  \param [in] color       BOX color.
1265  *  \param [in] fill_width  BOX fill width.
1266  *  \param [in] angle1      Angle of hatch pattern.
1267  *  \param [in] pitch1      Pitch of hatch pattern.
1268  *  \param [in] angle2      (unused).
1269  *  \param [in] pitch2      (unused).
1270  *  \param [in] origin_x    Page x coordinate to place BOX OBJECT.
1271  *  \param [in] origin_y    Page y coordinate to place BOX OBJECT.
1272  */
o_box_print_hatch(TOPLEVEL * toplevel,FILE * fp,int x,int y,int width,int height,int color,int fill_width,int angle1,int pitch1,int angle2,int pitch2,int origin_x,int origin_y)1273 void o_box_print_hatch(TOPLEVEL *toplevel, FILE *fp,
1274 		       int x, int y,
1275 		       int width, int height,
1276 		       int color,
1277 		       int fill_width,
1278 		       int angle1, int pitch1,
1279 		       int angle2, int pitch2,
1280 		       int origin_x, int origin_y)
1281 {
1282   BOX box;
1283   gint index;
1284   GArray *lines;
1285 
1286   g_return_if_fail(toplevel != NULL);
1287   g_return_if_fail(fp != NULL);
1288 
1289   f_print_set_color(toplevel, fp, color);
1290 
1291   /* Avoid printing line widths too small */
1292   if (fill_width <= 1) fill_width = 2;
1293 
1294   lines = g_array_new(FALSE, FALSE, sizeof(LINE));
1295 
1296   box.upper_x = x;
1297   box.upper_y = y;
1298   box.lower_x = x + width;
1299   box.lower_y = y - height;    /* Hmmm... */
1300 
1301   m_hatch_box(&box, angle1, pitch1, lines);
1302 
1303   for(index=0; index<lines->len; index++) {
1304     LINE *line = &g_array_index(lines, LINE, index);
1305 
1306     fprintf(fp,"%d %d %d %d %d line\n",
1307             line->x[0], line->y[0],
1308             line->x[1], line->y[1],
1309             fill_width);
1310   }
1311 
1312   g_array_free(lines, TRUE);
1313 }
1314 
1315 /*! \brief Calculates the distance between the given point and the closest
1316  * point on the perimeter of the box.
1317  *
1318  *  \param [in] object       The box OBJECT.
1319  *  \param [in] x            The x coordinate of the given point.
1320  *  \param [in] y            The y coordinate of the given point.
1321  *  \param [in] force_solid  If true, force treating the object as solid.
1322  *  \return The shortest distance from the object to the point. With an
1323  *  invalid parameter, this function returns G_MAXDOUBLE.
1324  */
o_box_shortest_distance(OBJECT * object,int x,int y,int force_solid)1325 double o_box_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1326 {
1327   int solid;
1328 
1329   g_return_val_if_fail (object->box != NULL, G_MAXDOUBLE);
1330 
1331   solid = force_solid || object->fill_type != FILLING_HOLLOW;
1332 
1333   return m_box_shortest_distance (object->box, x, y, solid);
1334 }
1335 
1336