1 /* Lepton EDA library
2 * Copyright (C) 1998-2010 Ales Hvezda
3 * Copyright (C) 1998-2016 gEDA Contributors
4 * Copyright (C) 2017-2021 Lepton EDA Contributors
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 box_object.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 "liblepton_priv.h"
30
31 /*! \brief Get the upper x coordinate of a box object.
32 *
33 * \param [in] object The box object.
34 * \return The x coordinate of the upper corner of the box.
35 */
36 int
lepton_box_object_get_upper_x(const LeptonObject * object)37 lepton_box_object_get_upper_x (const LeptonObject *object)
38 {
39 g_return_val_if_fail (lepton_object_is_box (object), 0);
40 g_return_val_if_fail (object->box != NULL, 0);
41
42 return object->box->upper_x;
43 }
44
45 /*! \brief Get the upper y coordinate of a box object.
46 *
47 * \param [in] object The box object.
48 * \return The y coordinate of the upper corner of the box.
49 */
50 int
lepton_box_object_get_upper_y(const LeptonObject * object)51 lepton_box_object_get_upper_y (const LeptonObject *object)
52 {
53 g_return_val_if_fail (lepton_object_is_box (object), 0);
54 g_return_val_if_fail (object->box != NULL, 0);
55
56 return object->box->upper_y;
57 }
58
59 /*! \brief Get the lower x coordinate of a box object.
60 *
61 * \param [in] object The box object.
62 * \return The x coordinate of the lower corner of the box.
63 */
64 int
lepton_box_object_get_lower_x(const LeptonObject * object)65 lepton_box_object_get_lower_x (const LeptonObject *object)
66 {
67 g_return_val_if_fail (lepton_object_is_box (object), 0);
68 g_return_val_if_fail (object->box != NULL, 0);
69
70 return object->box->lower_x;
71 }
72
73 /*! \brief Get the lower y coordinate of a box object.
74 *
75 * \param [in] object The box object.
76 * \return The y coordinate of the lower corner of the box.
77 */
78 int
lepton_box_object_get_lower_y(const LeptonObject * object)79 lepton_box_object_get_lower_y (const LeptonObject *object)
80 {
81 g_return_val_if_fail (lepton_object_is_box (object), 0);
82 g_return_val_if_fail (object->box != NULL, 0);
83
84 return object->box->lower_y;
85 }
86
87
88 /*! \brief Set the value of the upper x coordinate of a box object.
89 *
90 * \param [in,out] object The box object.
91 * \param [in] x The new upper x coordinate of the box.
92 */
93 void
lepton_box_object_set_upper_x(LeptonObject * object,int val)94 lepton_box_object_set_upper_x (LeptonObject *object, int val)
95 {
96 g_return_if_fail (lepton_object_is_box (object));
97 g_return_if_fail (object->box != NULL);
98
99 object->box->upper_x = val;
100 }
101
102 /*! \brief Set the value of the upper y coordinate of a box object.
103 *
104 * \param [in,out] object The box object.
105 * \param [in] y The new upper y coordinate of the box.
106 */
107 void
lepton_box_object_set_upper_y(LeptonObject * object,int val)108 lepton_box_object_set_upper_y (LeptonObject *object, int val)
109 {
110 g_return_if_fail (lepton_object_is_box (object));
111 g_return_if_fail (object->box != NULL);
112
113 object->box->upper_y = val;
114 }
115
116 /*! \brief Set the value of the lower x coordinate of a box object.
117 *
118 * \param [in,out] object The box object.
119 * \param [in] x The new lower x coordinate of the box.
120 */
121 void
lepton_box_object_set_lower_x(LeptonObject * object,int val)122 lepton_box_object_set_lower_x (LeptonObject *object, int val)
123 {
124 g_return_if_fail (lepton_object_is_box (object));
125 g_return_if_fail (object->box != NULL);
126
127 object->box->lower_x = val;
128 }
129
130 /*! \brief Set the value of the lower y coordinate of a box object.
131 *
132 * \param [in,out] object The box object.
133 * \param [in] y The new lower y coordinate of the box.
134 */
135 void
lepton_box_object_set_lower_y(LeptonObject * object,int val)136 lepton_box_object_set_lower_y (LeptonObject *object, int val)
137 {
138 g_return_if_fail (lepton_object_is_box (object));
139 g_return_if_fail (object->box != NULL);
140
141 object->box->lower_y = val;
142 }
143
144 /*! \brief Create a box LeptonObject
145 * \par Function Description
146 * This function creates a new object representing a box.
147 *
148 * The box is described by its upper left corner - <B>x1</B>, <B>y1</B> - and
149 * its lower right corner - <B>x2</B>, <B>y2</B>.
150 * The <B>type</B> parameter must be equal to <B>OBJ_BOX</B>. The <B>color</B>
151 * corresponds to the color the box will be drawn with.
152 * The <B>LeptonObject</B> structure is allocated with the #lepton_object_new()
153 * function. The structure describing the box is allocated and initialized
154 * with the parameters given to the function.
155 *
156 * Both the line type and the filling type are set to default
157 * values : solid line type with a width of 0, and no filling. It
158 * can be changed after with the
159 * #lepton_object_set_line_options() and
160 * #lepton_object_set_fill_options().
161 *
162 * \param [in] color Box border color.
163 * \param [in] x1 Upper x coordinate.
164 * \param [in] y1 Upper y coordinate.
165 * \param [in] x2 Lower x coordinate.
166 * \param [in] y2 Lower y coordinate.
167 * \return The new LeptonObject
168 */
169 LeptonObject*
lepton_box_object_new(int color,int x1,int y1,int x2,int y2)170 lepton_box_object_new (int color,
171 int x1,
172 int y1,
173 int x2,
174 int y2)
175 {
176 LeptonObject *new_node;
177 LeptonBox *box;
178
179 /* create the object */
180 new_node = lepton_object_new (OBJ_BOX, "box");
181 lepton_object_set_color (new_node, color);
182
183 box = lepton_box_new ();
184 new_node->box = box;
185
186 /* describe the box with its upper left and lower right corner */
187 box->upper_x = x1;
188 box->upper_y = y1;
189 box->lower_x = x2;
190 box->lower_y = y2;
191
192 /* line type and filling initialized to default */
193 lepton_object_set_line_options (new_node,
194 DEFAULT_OBJECT_END,
195 TYPE_SOLID,
196 LINE_WIDTH,
197 -1,
198 -1);
199
200 lepton_object_set_fill_options (new_node,
201 FILLING_HOLLOW,
202 -1,
203 -1,
204 -1,
205 -1,
206 -1);
207
208 return new_node;
209 }
210
211 /*! \brief Copy a box to a list.
212 * \par Function Description
213 * The function #lepton_box_object_copy() creates a verbatim copy
214 * of the object pointed by <B>o_current</B> describing a box.
215 *
216 * \param [in] o_current Box LeptonObject to copy.
217 * \return The new LeptonObject
218 */
219 LeptonObject*
lepton_box_object_copy(LeptonObject * o_current)220 lepton_box_object_copy (LeptonObject *o_current)
221 {
222 LeptonObject *new_obj;
223 int upper_x, upper_y, lower_x, lower_y;
224
225 /* A new box object is created with #lepton_box_object_new().
226 * Values for its fields are default and need to be modified. */
227 new_obj = lepton_box_object_new (lepton_object_get_color (o_current),
228 0, 0, 0, 0);
229
230 /*
231 * The dimensions of the new box are set with the ones of the original box.
232 * The two boxes have the same line type and the same filling options.
233 */
234 upper_x = lepton_box_object_get_upper_x (o_current);
235 upper_y = lepton_box_object_get_upper_y (o_current);
236 lower_x = lepton_box_object_get_lower_x (o_current);
237 lower_y = lepton_box_object_get_lower_y (o_current);
238
239 lepton_box_object_set_upper_x (new_obj, upper_x);
240 lepton_box_object_set_upper_y (new_obj, upper_y);
241 lepton_box_object_set_lower_x (new_obj, lower_x);
242 lepton_box_object_set_lower_y (new_obj, lower_y);
243
244 lepton_object_set_line_options (new_obj,
245 lepton_object_get_stroke_cap_type (o_current),
246 lepton_object_get_stroke_type (o_current),
247 lepton_object_get_stroke_width (o_current),
248 lepton_object_get_stroke_dash_length (o_current),
249 lepton_object_get_stroke_space_length (o_current));
250 lepton_object_set_fill_options (new_obj,
251 lepton_object_get_fill_type (o_current),
252 lepton_object_get_fill_width (o_current),
253 lepton_object_get_fill_pitch1 (o_current),
254 lepton_object_get_fill_angle1 (o_current),
255 lepton_object_get_fill_pitch2 (o_current),
256 lepton_object_get_fill_angle2 (o_current));
257
258 return new_obj;
259 }
260
261 /*! \brief Modify a box LeptonObject's coordinates.
262 * \par Function Description
263 * This function modifies the coordinates of one of the four corner of
264 * the box. The new coordinates of the corner identified by <B>whichone</B>
265 * are given by <B>x</B> and <B>y</B> in world unit.
266 *
267 * The coordinates of the corner is modified in the world coordinate system.
268 * Screen coordinates and boundings are then updated.
269 *
270 * \param [in,out] object Box LeptonObject to be modified.
271 * \param [in] x x coordinate.
272 * \param [in] y y coordinate.
273 * \param [in] whichone coordinate to change.
274 *
275 * \note
276 * <B>whichone</B> can take the following values:
277 * <DL>
278 * <DT>*</DT><DD>BOX_UPPER_LEFT
279 * <DT>*</DT><DD>BOX_LOWER_LEFT
280 * <DT>*</DT><DD>BOX_UPPER_RIGHT
281 * <DT>*</DT><DD>BOX_LOWER_RIGHT
282 * </DL>
283 */
284 void
lepton_box_object_modify(LeptonObject * object,int x,int y,int whichone)285 lepton_box_object_modify (LeptonObject *object,
286 int x,
287 int y,
288 int whichone)
289 {
290 int tmp;
291
292 lepton_object_emit_pre_change_notify (object);
293
294 /* change the position of the selected corner */
295 switch(whichone) {
296 case BOX_UPPER_LEFT:
297 lepton_box_object_set_upper_x (object, x);
298 lepton_box_object_set_upper_y (object, y);
299 break;
300
301 case BOX_LOWER_LEFT:
302 lepton_box_object_set_upper_x (object, x);
303 lepton_box_object_set_lower_y (object, y);
304 break;
305
306 case BOX_UPPER_RIGHT:
307 lepton_box_object_set_lower_x (object, x);
308 lepton_box_object_set_upper_y (object, y);
309 break;
310
311 case BOX_LOWER_RIGHT:
312 lepton_box_object_set_lower_x (object, x);
313 lepton_box_object_set_lower_y (object, y);
314 break;
315
316 default:
317 return;
318 }
319
320 int upper_x, upper_y, lower_x, lower_y;
321 upper_x = lepton_box_object_get_upper_x (object);
322 upper_y = lepton_box_object_get_upper_y (object);
323 lower_x = lepton_box_object_get_lower_x (object);
324 lower_y = lepton_box_object_get_lower_y (object);
325
326 /* need to update the upper left and lower right corners */
327 if (upper_x > lower_x)
328 {
329 tmp = upper_x;
330 lepton_box_object_set_upper_x (object, lower_x);
331 lepton_box_object_set_lower_x (object, tmp);
332 }
333
334 if (upper_y < lower_y)
335 {
336 tmp = upper_y;
337 lepton_box_object_set_upper_y (object, lower_y);
338 lepton_box_object_set_lower_y (object, tmp);
339 }
340
341 lepton_object_emit_change_notify (object);
342
343 }
344
345 /*! \brief Create a box from a character string.
346 * \par Function Description
347 * This function gets the description of a box from the <B>*buf</B> character
348 * string.
349 *
350 * Depending on <B>*version</B>, the correct file format is considered.
351 * Currently two file format revisions are supported :
352 * <DL>
353 * <DT>*</DT><DD>the file format used until 20000704 release
354 * <DT>*</DT><DD>the file format used for the releases after 2000704.
355 * </DL>
356 *
357 * \param [in] buf Character string with box description.
358 * \param [in] release_ver libgeda release version number.
359 * \param [in] fileformat_ver libgeda file format version number.
360 * \return The box LeptonObject that was created, or NULL on error.
361 */
362 LeptonObject*
lepton_box_object_read(const char buf[],unsigned int release_ver,unsigned int fileformat_ver,GError ** err)363 lepton_box_object_read (const char buf[],
364 unsigned int release_ver,
365 unsigned int fileformat_ver,
366 GError **err)
367 {
368 LeptonObject *new_obj;
369 char type;
370 int x1, y1;
371 int width, height;
372 int d_x1, d_y1;
373 int d_x2, d_y2;
374 int color;
375 int box_width, box_space, box_length;
376 int fill_width, angle1, pitch1, angle2, pitch2;
377 int box_end;
378 int box_type;
379 int box_filling;
380
381 if (release_ver <= VERSION_20000704) {
382
383 /*! \note
384 * The old geda file format, i.e. releases 20000704 and older, does not
385 * handle the line type and the filling of the box object. They are set
386 * to default.
387 */
388
389 if (sscanf (buf, "%c %d %d %d %d %d\n",
390 &type, &x1, &y1, &width, &height, &color) != 6) {
391 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse box object"));
392 return NULL;
393 }
394
395 box_width = 0;
396 box_end = END_NONE;
397 box_type = TYPE_SOLID;
398 box_length = -1;
399 box_space = -1;
400
401 box_filling = FILLING_HOLLOW;
402 fill_width = 0;
403 angle1 = -1;
404 pitch1 = -1;
405 angle2 = -1;
406 pitch2 = -1;
407
408 } else {
409
410 /*! \note
411 * The current line format to describe a box is a space separated list of
412 * characters and numbers in plain ASCII on a single line. The meaning of
413 * each item is described in the file format documentation.
414 */
415 if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
416 &type, &x1, &y1, &width, &height, &color,
417 &box_width, &box_end, &box_type, &box_length,
418 &box_space, &box_filling,
419 &fill_width, &angle1, &pitch1, &angle2, &pitch2) != 17) {
420 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse box object"));
421 return NULL;
422 }
423 }
424
425 if (width == 0 || height == 0) {
426 g_message (_("Found a zero width/height box "
427 "[ %1$c %2$d %3$d %4$d %5$d %6$d ]"),
428 type, x1, y1, width, height, color);
429 }
430
431 if (!color_id_valid (color)) {
432 g_message (_("Found an invalid color [ %1$s ]"), buf);
433 g_message (_("Setting color to default color."));
434 color = default_color_id();
435 }
436
437 /*! \note
438 * A box is internally described by its lower right and upper left corner
439 * whereas the line describe it with the lower left corner and the width
440 * and height.
441 *
442 * A new object is allocated, initialized and added to the object list.
443 * Its filling and line type are set according to the values of the field
444 * on the line.
445 */
446
447 /* upper left corner of the box */
448 d_x1 = x1;
449 d_y1 = y1 + height; /* move box origin to top left */
450
451 /* lower right corner of the box */
452 d_x2 = x1 + width; /* end points of the box */
453 d_y2 = y1;
454
455 /* create a new box */
456 new_obj = lepton_box_object_new (color, d_x1, d_y1, d_x2, d_y2);
457 /* set its line options */
458 lepton_object_set_line_options (new_obj,
459 (LeptonStrokeCapType) box_end,
460 (LeptonStrokeType) box_type,
461 box_width,
462 box_length,
463 box_space);
464 /* set its fill options */
465 lepton_object_set_fill_options (new_obj,
466 (LeptonFillType) box_filling,
467 fill_width,
468 pitch1,
469 angle1,
470 pitch2,
471 angle2);
472
473 return new_obj;
474 }
475
476 /*! \brief Create a character string representation of a box object.
477 * \par Function Description
478 * This function formats a string in the buffer <B>*buff</B> to describe the
479 * box object <B>*object</B>.
480 * It follows the post-20000704 release file format that handle the line type
481 * and fill options.
482 *
483 * \param [in] object The box LeptonObject to create string from.
484 * \return A pointer to the box character string.
485 *
486 * \warning
487 * Caller must g_free returned character string.
488 */
489 gchar*
lepton_box_object_to_buffer(const LeptonObject * object)490 lepton_box_object_to_buffer (const LeptonObject *object)
491 {
492 int x1, y1;
493 int width, height;
494 int box_width, box_space, box_length;
495 int fill_width, angle1, pitch1, angle2, pitch2;
496 LeptonStrokeCapType box_end;
497 LeptonStrokeType box_type;
498 LeptonFillType box_fill;
499 char *buf;
500 int upper_x, upper_y, lower_x, lower_y;
501
502 /*! \note
503 * A box is internally represented by its lower right and upper left corner
504 * whereas it is described in the file format as its lower left corner and
505 * its width and height.
506 */
507
508 upper_x = lepton_box_object_get_upper_x (object);
509 upper_y = lepton_box_object_get_upper_y (object);
510 lower_x = lepton_box_object_get_lower_x (object);
511 lower_y = lepton_box_object_get_lower_y (object);
512
513 /* calculate the width and height of the box */
514 width = abs (lower_x - upper_x);
515 height = abs (upper_y - lower_y);
516
517 /* calculate the lower left corner of the box */
518 x1 = upper_x;
519 y1 = upper_y - height; /* move the origin to 0, 0*/
520
521 #if DEBUG
522 printf("box: %d %d %d %d\n", x1, y1, width, height);
523 #endif
524
525 /* description of the line type for the outline */
526 box_end = lepton_object_get_stroke_cap_type (object);
527 box_width = lepton_object_get_stroke_width (object);
528 box_type = lepton_object_get_stroke_type (object);
529 box_length = lepton_object_get_stroke_dash_length (object);
530 box_space = lepton_object_get_stroke_space_length (object);
531
532 /* description of the filling of the box */
533 box_fill = lepton_object_get_fill_type (object);
534 fill_width = lepton_object_get_fill_width (object);
535 angle1 = lepton_object_get_fill_angle1 (object);
536 pitch1 = lepton_object_get_fill_pitch1 (object);
537 angle2 = lepton_object_get_fill_angle2 (object);
538 pitch2 = lepton_object_get_fill_pitch2 (object);
539
540 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
541 lepton_object_get_type (object),
542 x1, y1, width, height, lepton_object_get_color (object),
543 box_width, box_end, box_type, box_length, box_space,
544 box_fill,
545 fill_width, angle1, pitch1, angle2, pitch2);
546
547 return(buf);
548 }
549
550 /*! \brief Translate a box position in WORLD coordinates by a delta.
551 * \par Function Description
552 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the box
553 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
554 *
555 * \param [in,out] object Box LeptonObject to translate.
556 * \param [in] dx x distance to move.
557 * \param [in] dy y distance to move.
558 */
559 void
lepton_box_object_translate(LeptonObject * object,int dx,int dy)560 lepton_box_object_translate (LeptonObject *object,
561 int dx,
562 int dy)
563 {
564 g_return_if_fail (lepton_object_is_box (object));
565 g_return_if_fail (object->box != NULL);
566 int upper_x, upper_y, lower_x, lower_y;
567
568 /* Do world coords */
569 upper_x = lepton_box_object_get_upper_x (object);
570 upper_y = lepton_box_object_get_upper_y (object);
571 lower_x = lepton_box_object_get_lower_x (object);
572 lower_y = lepton_box_object_get_lower_y (object);
573
574 lepton_box_object_set_upper_x (object, upper_x + dx);
575 lepton_box_object_set_upper_y (object, upper_y + dy);
576 lepton_box_object_set_lower_x (object, lower_x + dx);
577 lepton_box_object_set_lower_y (object, lower_y + dy);
578 }
579
580 /*! \brief Rotate box LeptonObject using WORLD coordinates.
581 * \par Function Description
582 * The function #o_box_rotate_world() rotate the box described by
583 * <B>*object</B> around the (<B>world_centerx</B>, <B>world_centery</B>) point by
584 * <B>angle</B> degrees.
585 * The center of rotation is in world unit.
586 *
587 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
588 * \param [in] world_centery Rotation center y coordinate in WORLD units.
589 * \param [in] angle Rotation angle in degrees (See note below).
590 * \param [in,out] object Box LeptonObject to rotate.
591 *
592 */
593 void
lepton_box_object_rotate(int world_centerx,int world_centery,int angle,LeptonObject * object)594 lepton_box_object_rotate (int world_centerx,
595 int world_centery,
596 int angle,
597 LeptonObject *object)
598 {
599 int newx1, newy1;
600 int newx2, newy2;
601
602 g_return_if_fail (lepton_object_is_box (object));
603 g_return_if_fail (object->box != NULL);
604
605 /*! \note
606 * Only 90 degree multiple and positive angles are allowed.
607 */
608
609 /* angle must be positive */
610 if(angle < 0) angle = -angle;
611 /* angle must be a 90 multiple or no rotation performed */
612 if((angle % 90) != 0) return;
613
614 /*! \note
615 * The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is
616 * translated to the origin. The rotation of the upper left and lower right
617 * corner are then performed. Finally, the rotated box is translated back
618 * to its previous location.
619 */
620 /* translate object to origin */
621 lepton_box_object_translate (object, -world_centerx, -world_centery);
622
623 /* rotate the upper left corner of the box */
624 lepton_point_rotate_90 (lepton_box_object_get_upper_x (object),
625 lepton_box_object_get_upper_y (object),
626 angle,
627 &newx1,
628 &newy1);
629
630 /* rotate the lower left corner of the box */
631 lepton_point_rotate_90 (lepton_box_object_get_lower_x (object),
632 lepton_box_object_get_lower_y (object),
633 angle,
634 &newx2,
635 &newy2);
636
637 /* reorder the corners after rotation */
638 lepton_box_object_set_upper_x (object, MIN (newx1, newx2));
639 lepton_box_object_set_upper_y (object, MAX (newy1, newy2));
640 lepton_box_object_set_lower_x (object, MAX (newx1, newx2));
641 lepton_box_object_set_lower_y (object, MIN (newy1, newy2));
642
643 /* translate object back to normal position */
644 lepton_box_object_translate (object, world_centerx, world_centery);
645 }
646
647 /*! \brief Mirror box using WORLD coordinates.
648 * \par Function Description
649 * This function mirrors the box from the point
650 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
651 *
652 * The box is first translated to the origin, then mirrored and finally
653 * translated back at its previous position.
654 *
655 * \param [in] world_centerx Origin x coordinate in WORLD units.
656 * \param [in] world_centery Origin y coordinate in WORLD units.
657 * \param [in,out] object Box LeptonObject to mirror.
658 */
659 void
lepton_box_object_mirror(int world_centerx,int world_centery,LeptonObject * object)660 lepton_box_object_mirror (int world_centerx,
661 int world_centery,
662 LeptonObject *object)
663 {
664 int upper_x, upper_y, lower_x, lower_y;
665 int newx1, newy1;
666 int newx2, newy2;
667
668 g_return_if_fail (lepton_object_is_box (object));
669 g_return_if_fail (object->box != NULL);
670
671 /* translate object to origin */
672 lepton_box_object_translate (object, -world_centerx, -world_centery);
673
674 upper_x = lepton_box_object_get_upper_x (object);
675 upper_y = lepton_box_object_get_upper_y (object);
676 lower_x = lepton_box_object_get_lower_x (object);
677 lower_y = lepton_box_object_get_lower_y (object);
678
679 /* mirror the corners */
680 newx1 = -upper_x;
681 newy1 = upper_y;
682 newx2 = -lower_x;
683 newy2 = lower_y;
684
685 /* reorder the corners */
686 lepton_box_object_set_upper_x (object, MIN (newx1, newx2));
687 lepton_box_object_set_upper_y (object, MAX (newy1, newy2));
688 lepton_box_object_set_lower_x (object, MAX (newx1, newx2));
689 lepton_box_object_set_lower_y (object, MIN (newy1, newy2));
690
691 /* translate back in position */
692 lepton_box_object_translate (object, world_centerx, world_centery);
693 }
694
695 /*! \brief Get box bounding rectangle in WORLD coordinates.
696 * \par Function Description
697 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
698 * parameters to the boundings of the box object described in <B>*box</B>
699 * in world units.
700 *
701 * \param [in] object Box LeptonObject to read coordinates from.
702 * \param [out] left Left box coordinate in WORLD units.
703 * \param [out] top Top box coordinate in WORLD units.
704 * \param [out] right Right box coordinate in WORLD units.
705 * \param [out] bottom Bottom box coordinate in WORLD units.
706 */
707 void
lepton_box_object_calculate_bounds(const LeptonObject * object,LeptonBounds * bounds)708 lepton_box_object_calculate_bounds (const LeptonObject *object,
709 LeptonBounds *bounds)
710 {
711 gint expand;
712
713 lepton_bounds_init (bounds);
714
715 g_return_if_fail (lepton_object_is_box (object));
716 g_return_if_fail (object->box != NULL);
717
718 lepton_box_calculate_bounds (object->box, bounds);
719
720 expand = (lepton_object_get_stroke_width (object) + 1) / 2;
721
722 /* This isn't strictly correct, but a 1st order approximation */
723 lepton_bounds_expand (bounds, bounds, expand, expand);
724 }
725
726 /*! \brief get the position of the left bottom point
727 * \par Function Description
728 * This function gets the position of the bottom left point of a box object.
729 *
730 * \param [in] object The object to get the position.
731 * \param [out] x pointer to the x-position
732 * \param [out] y pointer to the y-position
733 * \return TRUE if successfully determined the position, FALSE otherwise
734 */
735 gboolean
lepton_box_object_get_position(const LeptonObject * object,gint * x,gint * y)736 lepton_box_object_get_position (const LeptonObject *object,
737 gint *x,
738 gint *y)
739 {
740 g_return_val_if_fail (lepton_object_is_box (object), FALSE);
741 g_return_val_if_fail (object->box != NULL, FALSE);
742
743 if (x != NULL) {
744 *x = MIN (lepton_box_object_get_lower_x (object),
745 lepton_box_object_get_upper_x (object));
746 }
747
748 if (y != NULL) {
749 *y = MIN (lepton_box_object_get_lower_y (object),
750 lepton_box_object_get_upper_y (object));
751 }
752
753 return TRUE;
754 }
755
756 /*! \brief Calculates the distance between the given point and the closest
757 * point on the perimeter of the box.
758 *
759 * \param [in] object The box LeptonObject.
760 * \param [in] x The x coordinate of the given point.
761 * \param [in] y The y coordinate of the given point.
762 * \param [in] force_solid If true, force treating the object as solid.
763 * \param [in] include_hidden Take hidden text into account.
764 * \return The shortest distance from the object to the point. With an
765 * invalid parameter, this function returns G_MAXDOUBLE.
766 */
767 double
lepton_box_object_shortest_distance(LeptonObject * object,int x,int y,int force_solid,gboolean include_hidden)768 lepton_box_object_shortest_distance (LeptonObject *object,
769 int x,
770 int y,
771 int force_solid,
772 gboolean include_hidden)
773 {
774 int solid;
775
776 g_return_val_if_fail (object->box != NULL, G_MAXDOUBLE);
777
778 solid = force_solid ||
779 lepton_object_get_fill_type (object) != FILLING_HOLLOW;
780
781 return lepton_box_shortest_distance (object->box, x, y, solid);
782 }
783