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 line_object.c
22  *  \brief functions for the line object
23  */
24 
25 #include <config.h>
26 
27 #include <stdio.h>
28 #include <math.h>
29 
30 #include "liblepton_priv.h"
31 
32 /*! \brief Create and add line LeptonObject to list.
33  *  \par Function Description
34  *  This function creates a new object representing a line.
35  *
36  *  The line is described by its two ends - <B>x1</B>,<B>y1</B> and
37  *  <B>x2</B>,<B>y2</B>.
38  *  The <B>type</B> parameter must be equal to #OBJ_LINE.
39  *  The <B>color</B> parameter corresponds to the color the box
40  *  will be drawn with.
41  *
42  *  The #LeptonObject structure is allocated with the #lepton_object_new()
43  *  function. The structure describing the line is allocated and
44  *  initialized with the parameters given to the function.
45  *
46  *  Both the line type and the filling type are set to default
47  *  values : solid line type with a width of 0, and no filling.
48  *  It can be changed after with the #lepton_object_set_line_options() and
49  *  #lepton_object_set_fill_options().
50  *
51  *  \param [in]     type         Must be OBJ_LINE.
52  *  \param [in]     color        Circle line color.
53  *  \param [in]     x1           Upper x coordinate.
54  *  \param [in]     y1           Upper y coordinate.
55  *  \param [in]     x2           Lower x coordinate.
56  *  \param [in]     y2           Lower y coordinate.
57  *  \return A pointer to the new end of the object list.
58  */
59 LeptonObject*
lepton_line_object_new(gint color,gint x1,gint y1,gint x2,gint y2)60 lepton_line_object_new (gint color,
61                         gint x1,
62                         gint y1,
63                         gint x2,
64                         gint y2)
65 {
66   LeptonObject *new_node;
67 
68   /* create the object */
69   new_node = lepton_object_new (OBJ_LINE, "line");
70   lepton_object_set_color (new_node, color);
71 
72   new_node->line  = lepton_line_new ();
73 
74   /* describe the line with its two ends */
75   new_node->line->x[0] = x1;
76   new_node->line->y[0] = y1;
77   new_node->line->x[1] = x2;
78   new_node->line->y[1] = y2;
79 
80   /* line type and filling initialized to default */
81   lepton_object_set_line_options (new_node,
82                                   DEFAULT_OBJECT_END,
83                                   TYPE_SOLID,
84                                   LINE_WIDTH,
85                                   -1,
86                                   -1);
87 
88   lepton_object_set_fill_options (new_node,
89                                   FILLING_HOLLOW,
90                                   -1,
91                                   -1,
92                                   -1,
93                                   -1,
94                                   -1);
95 
96   return new_node;
97 }
98 
99 /*! \brief Create a copy of a line.
100  *  \par Function Description
101  *  This function creates a verbatim copy of the
102  *  object pointed by <B>o_current</B> describing a line.
103  *
104  *  \param [in]  o_current  Line LeptonObject to copy.
105  *  \return The new LeptonObject
106  */
107 LeptonObject*
lepton_line_object_copy(LeptonObject * o_current)108 lepton_line_object_copy (LeptonObject *o_current)
109 {
110   LeptonObject *new_obj;
111 
112   new_obj = lepton_line_object_new (lepton_object_get_color (o_current),
113                                     o_current->line->x[0],
114                                     o_current->line->y[0],
115                                     o_current->line->x[1],
116                                     o_current->line->y[1]);
117 
118   /* copy the line type and filling options */
119   lepton_object_set_line_options (new_obj,
120                                   lepton_object_get_stroke_cap_type (o_current),
121                                   lepton_object_get_stroke_type (o_current),
122                                   lepton_object_get_stroke_width (o_current),
123                                   lepton_object_get_stroke_dash_length (o_current),
124                                   lepton_object_get_stroke_space_length (o_current));
125 
126   lepton_object_set_fill_options (new_obj,
127                                   lepton_object_get_fill_type (o_current),
128                                   lepton_object_get_fill_width (o_current),
129                                   lepton_object_get_fill_pitch1 (o_current),
130                                   lepton_object_get_fill_angle1 (o_current),
131                                   lepton_object_get_fill_pitch2 (o_current),
132                                   lepton_object_get_fill_angle2 (o_current));
133 
134   return new_obj;
135 }
136 
137 /*! \brief Get the x coordinate of first endpoint
138  *
139  *  The coordinate properties are broken out individually to make it easier for
140  *  the GUI. This way, the GUI does not need as many adapters to interface to
141  *  a line boxed type.
142  *
143  *  \param [in] object The line
144  *  \return The x coordinate for the first endpoint
145  */
146 gint
lepton_line_object_get_x0(const LeptonObject * object)147 lepton_line_object_get_x0 (const LeptonObject *object)
148 {
149   g_return_val_if_fail (object != NULL, 0);
150   g_return_val_if_fail (object->line != NULL, 0);
151 
152   return object->line->x[0];
153 }
154 
155 /*! \brief Get the x coordinate of second endpoint
156  *
157  *  The coordinate properties are broken out individually to make it easier for
158  *  the GUI. This way, the GUI does not need as many adapters to interface to
159  *  a line boxed type.
160  *
161  *  \param [in] object The line
162  *  \return The x coordinate for the second endpoint
163  */
164 gint
lepton_line_object_get_x1(const LeptonObject * object)165 lepton_line_object_get_x1 (const LeptonObject *object)
166 {
167   g_return_val_if_fail (object != NULL, 0);
168   g_return_val_if_fail (object->line != NULL, 0);
169 
170   return object->line->x[1];
171 }
172 
173 /*! \brief Get the y coordinate of first endpoint
174  *
175  *  The coordinate properties are broken out individually to make it easier for
176  *  the GUI. This way, the GUI does not need as many adapters to interface to
177  *  a line boxed type.
178  *
179  *  \param [in] object The line
180  *  \return The y coordinate for the first endpoint
181  */
182 gint
lepton_line_object_get_y0(const LeptonObject * object)183 lepton_line_object_get_y0 (const LeptonObject *object)
184 {
185   g_return_val_if_fail (object != NULL, 0);
186   g_return_val_if_fail (object->line != NULL, 0);
187 
188   return object->line->y[0];
189 }
190 
191 /*! \brief Get the y coordinate of second endpoint
192  *
193  *  The coordinate properties are broken out individually to make it easier for
194  *  the GUI. This way, the GUI does not need as many adapters to interface to
195  *  a line boxed type.
196  *
197  *  \param [in] object The line
198  *  \return The y coordinate for the second endpoint
199  */
200 gint
lepton_line_object_get_y1(const LeptonObject * object)201 lepton_line_object_get_y1 (const LeptonObject *object)
202 {
203   g_return_val_if_fail (object != NULL, 0);
204   g_return_val_if_fail (object->line != NULL, 0);
205 
206   return object->line->y[1];
207 }
208 
209 /*! \brief Set the x coordinate of first endpoint
210  *
211  *  The coordinate properties are broken out individually to make it easier for
212  *  the GUI. This way, the GUI does not need as many adapters to interface to
213  *  a line boxed type.
214  *
215  *  \param [in,out] object The line
216  *  \param [in] x The new x coordinate for the first endpoint
217  */
218 void
lepton_line_object_set_x0(LeptonObject * object,gint x)219 lepton_line_object_set_x0 (LeptonObject *object,
220                            gint x)
221 {
222   g_return_if_fail (object != NULL);
223   g_return_if_fail (object->line != NULL);
224 
225   object->line->x[0] = x;
226 }
227 
228 /*! \brief Set the x coordinate of second endpoint
229  *
230  *  The coordinate properties are broken out individually to make it easier for
231  *  the GUI. This way, the GUI does not need as many adapters to interface to
232  *  a line boxed type.
233  *
234  *  \param [in,out] object The line
235  *  \param [in] x The new x coordinate for the second endpoint
236  */
237 void
lepton_line_object_set_x1(LeptonObject * object,gint x)238 lepton_line_object_set_x1 (LeptonObject *object,
239                            gint x)
240 {
241   g_return_if_fail (object != NULL);
242   g_return_if_fail (object->line != NULL);
243 
244   object->line->x[1] = x;
245 }
246 
247 /*! \brief Set the y coordinate of first endpoint
248  *
249  *  The coordinate properties are broken out individually to make it easier for
250  *  the GUI. This way, the GUI does not need as many adapters to interface to
251  *  a line boxed type.
252  *
253  *  \param [in,out] object The line
254  *  \param [in] y The new y coordinate for the first endpoint
255  */
256 void
lepton_line_object_set_y0(LeptonObject * object,gint y)257 lepton_line_object_set_y0 (LeptonObject *object,
258                            gint y)
259 {
260   g_return_if_fail (object != NULL);
261   g_return_if_fail (object->line != NULL);
262 
263   object->line->y[0] = y;
264 }
265 
266 /*! \brief Set the y coordinate of second endpoint
267  *
268  *  The coordinate properties are broken out individually to make it easier for
269  *  the GUI. This way, the GUI does not need as many adapters to interface to
270  *  a line boxed type.
271  *
272  *  \param [in,out] object The line
273  *  \param [in] y The new y coordinate for the second endpoint
274  */
275 void
lepton_line_object_set_y1(LeptonObject * object,gint y)276 lepton_line_object_set_y1 (LeptonObject *object,
277                            gint y)
278 {
279   g_return_if_fail (object != NULL);
280   g_return_if_fail (object->line != NULL);
281 
282   object->line->y[1] = y;
283 }
284 
285 /*! \brief Modify the description of a line LeptonObject.
286  *  \par Function Description
287  *  This function modifies the coordinates of one of the two ends of
288  *  the line described by <B>*object</B>. The new coordinates of this end,
289  *  identified by <B>whichone</B>, are given by <B>x</B> and <B>y</B>
290  *  in world unit.
291  *
292  *  The coordinates of the end of line is modified in the world
293  *  coordinate system. Screen coordinates and boundings are then updated.
294  *
295  *  \param [in,out] object     Line LeptonObject to modify.
296  *  \param [in]     x          New x coordinate.
297  *  \param [in]     y          New y coordinate.
298  *  \param [in]     whichone   Which line parameter to modify.
299  *
300  *  <B>whichone</B> can have the following values:
301  *  <DL>
302  *    <DT>*</DT><DD>LINE_END1
303  *    <DT>*</DT><DD>LINE_END2
304  *  </DL>
305  */
306 void
lepton_line_object_modify(LeptonObject * object,int x,int y,int whichone)307 lepton_line_object_modify (LeptonObject *object,
308                            int x,
309                            int y,
310                            int whichone)
311 {
312   lepton_object_emit_pre_change_notify (object);
313 
314   switch (whichone) {
315     case LINE_END1:
316       lepton_line_object_set_x0 (object, x);
317       lepton_line_object_set_y0 (object, y);
318       break;
319 
320     case LINE_END2:
321       lepton_line_object_set_x1 (object, x);
322       lepton_line_object_set_y1 (object, y);
323       break;
324 
325     default:
326       return;
327   }
328 
329   lepton_object_emit_change_notify (object);
330 }
331 
332 /*! \brief Create line LeptonObject from character string.
333  *  \par Function Description
334  *  This function creates a line LeptonObject from the character
335  *  string <B>*buf</B> the description of a box.
336  *
337  *  The function returns a pointer on the new last element, that is
338  *  the added line object.
339  *
340  *  Depending on <B>*version</B>, the correct file format is considered.
341  *  Currently two file format revisions are supported :
342  *  <DL>
343  *    <DT>*</DT><DD>the file format used until 20010704 release.
344  *    <DT>*</DT><DD>the file format used for the releases after 20010704.
345  *  </DL>
346  *
347  *  \param [in]  buf             Character string with line description.
348  *  \param [in]  release_ver     libgeda release version number.
349  *  \param [in]  fileformat_ver  libgeda file format version number.
350  *  \return A pointer to the new line object, or NULL on error.
351  */
352 LeptonObject*
o_line_read(const char buf[],unsigned int release_ver,unsigned int fileformat_ver,GError ** err)353 o_line_read (const char buf[],
354              unsigned int release_ver,
355              unsigned int fileformat_ver,
356              GError ** err)
357 {
358   LeptonObject *new_obj;
359   char type;
360   int x1, y1;
361   int x2, y2;
362   int line_width, line_space, line_length;
363   int line_end;
364   int line_type;
365   int color;
366 
367   if (release_ver <= VERSION_20000704) {
368     /*
369      * The old geda file format, i.e. releases 20000704 and older, does
370      * not handle the line type and the filling - here filling is irrelevant.
371      * They are set to default.
372      */
373     if (sscanf (buf, "%c %d %d %d %d %d\n", &type,
374                 &x1, &y1, &x2, &y2, &color) != 6) {
375       g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse line object"));
376       return NULL;
377     }
378 
379     line_width = 0;
380     line_end   = END_NONE;
381     line_type  = TYPE_SOLID;
382     line_length= -1;
383     line_space = -1;
384   } else {
385     /*
386      * The current line format to describe a line is a space separated
387      * list of characters and numbers in plain ASCII on a single line.
388      * The meaning of each item is described in the file format documentation.
389      */
390       if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type,
391                   &x1, &y1, &x2, &y2, &color,
392                   &line_width, &line_end, &line_type, &line_length, &line_space) != 11) {
393         g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse line object"));
394         return NULL;
395       }
396   }
397 
398   /*
399    * Null length line are not allowed. If such a line is detected a
400    * message is issued.
401    *
402    * It also checks is the required color is valid.
403    */
404   if (x1 == x2 && y1 == y2) {
405     g_message (_("Found a zero length line "
406                  "[ %1$c %2$d %3$d %4$d %5$d %6$d ]"),
407                type, x1, y1, x2, y2, color);
408   }
409 
410   if (!color_id_valid (color)) {
411     g_message (_("Found an invalid color [ %1$s ]"), buf);
412     g_message (_("Setting color to default color."));
413     color = default_color_id();
414   }
415 
416   /*
417    * A line is internally described by its two ends. A new object is
418    * allocated, initialized and added to the list of objects. Its line
419    * type is set according to the values of the fields on the line.
420    */
421   /* create and add the line to the list */
422   new_obj = lepton_line_object_new (color,
423                                     x1,
424                                     y1,
425                                     x2,
426                                     y2);
427 
428   /* set its line options */
429   lepton_object_set_line_options (new_obj,
430                                   (LeptonStrokeCapType) line_end,
431                                   (LeptonStrokeType) line_type,
432                                   line_width,
433                                   line_length,
434                                   line_space);
435   /* filling is irrelevant for line, just set to default */
436   lepton_object_set_fill_options (new_obj,
437                                   FILLING_HOLLOW,
438                                   -1,
439                                   -1,
440                                   -1,
441                                   -1,
442                                   -1);
443 
444   return new_obj;
445 }
446 
447 /*! \brief Create a character string representation of a line LeptonObject.
448  *  \par Function Description
449  *  The function formats a string in the buffer <B>*buff</B> to describe
450  *  the box object <B>*object</B>.
451  *  It follows the post-20000704 release file format that handle the
452  *  line type and fill options - filling is irrelevant here.
453  *
454  *  \param [in] object  Line LeptonObject to create string from.
455  *  \return A pointer to the line LeptonObject character string.
456  *
457  *  \note
458  *  Caller must g_free returned character string.
459  *
460  */
461 gchar*
lepton_line_object_to_buffer(const LeptonObject * object)462 lepton_line_object_to_buffer (const LeptonObject *object)
463 {
464   g_return_val_if_fail (lepton_object_is_line (object), NULL);
465   g_return_val_if_fail (object->line != NULL, NULL);
466 
467   return g_strdup_printf ("%c %d %d %d %d %d %d %d %d %d %d",
468                           lepton_object_get_type (object),
469                           lepton_line_object_get_x0 (object),
470                           lepton_line_object_get_y0 (object),
471                           lepton_line_object_get_x1 (object),
472                           lepton_line_object_get_y1 (object),
473                           lepton_object_get_color (object),
474                           lepton_object_get_stroke_width (object),
475                           lepton_object_get_stroke_cap_type (object),
476                           lepton_object_get_stroke_type (object),
477                           lepton_object_get_stroke_dash_length (object),
478                           lepton_object_get_stroke_space_length (object));
479 }
480 
481 /*! \brief Translate a line position in WORLD coordinates by a delta.
482  *  \par Function Description
483  *  This function applies a translation of (<B>x1</B>,<B>y1</B>) to the line
484  *  described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
485  *
486  *  \param [in,out] object     Line LeptonObject to translate.
487  *  \param [in]     dx         x distance to move.
488  *  \param [in]     dy         y distance to move.
489  */
490 void
lepton_line_object_translate(LeptonObject * object,int dx,int dy)491 lepton_line_object_translate (LeptonObject *object,
492                               int dx,
493                               int dy)
494 {
495   g_return_if_fail (lepton_object_is_line (object));
496   g_return_if_fail (object->line != NULL);
497 
498   /* Update world coords */
499   object->line->x[0] = object->line->x[0] + dx;
500   object->line->y[0] = object->line->y[0] + dy;
501   object->line->x[1] = object->line->x[1] + dx;
502   object->line->y[1] = object->line->y[1] + dy;
503 }
504 
505 /*! \brief Rotate Line LeptonObject using WORLD coordinates.
506  *  \par Function Description
507  *  This function rotates the line described by
508  *  <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>)
509  *  point by <B>angle</B> degrees.
510  *  The center of rotation is in world units.
511  *
512  *  \param [in]      world_centerx  Rotation center x coordinate in WORLD units.
513  *  \param [in]      world_centery  Rotation center y coordinate in WORLD units.
514  *  \param [in]      angle          Rotation angle in degrees (See note below).
515  *  \param [in,out]  object         Line LeptonObject to rotate.
516  */
517 void
lepton_line_object_rotate(int world_centerx,int world_centery,int angle,LeptonObject * object)518 lepton_line_object_rotate (int world_centerx,
519                            int world_centery,
520                            int angle,
521                            LeptonObject *object)
522 {
523   int newx, newy;
524 
525   g_return_if_fail (lepton_object_is_line (object));
526   g_return_if_fail (object->line != NULL);
527 
528   if (angle == 0)
529     return;
530 
531   /* angle must be positive */
532   if(angle < 0) angle = -angle;
533   /* angle must be 90 multiple or no rotation performed */
534   if((angle % 90) != 0) return;
535 
536   /*
537    * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>)
538    * is translated to the origin. The rotation of the two ends of
539    * the line is performed. FInally, the rotated line is translated
540    * back to its previous location.
541    */
542   /* translate object to origin */
543   lepton_line_object_translate (object, -world_centerx, -world_centery);
544 
545   /* rotate line end 1 */
546   lepton_point_rotate_90 (object->line->x[0],
547                           object->line->y[0],
548                           angle,
549                           &newx,
550                           &newy);
551 
552   object->line->x[0] = newx;
553   object->line->y[0] = newy;
554 
555   /* rotate line end 2 */
556   lepton_point_rotate_90 (object->line->x[1],
557                           object->line->y[1],
558                           angle,
559                           &newx,
560                           &newy);
561 
562   object->line->x[1] = newx;
563   object->line->y[1] = newy;
564 
565   /* translate object back to normal position */
566   lepton_line_object_translate (object, world_centerx, world_centery);
567 
568 }
569 
570 /*! \brief Mirror a line using WORLD coordinates.
571  *  \par Function Description
572  *  This function mirrors the line from the point
573  *  (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
574  *
575  *  The line if first translated to the origin, then mirrored
576  *  and finally translated back at its previous position.
577  *
578  *  \param [in]     world_centerx  Origin x coordinate in WORLD units.
579  *  \param [in]     world_centery  Origin y coordinate in WORLD units.
580  *  \param [in,out] object         Line LeptonObject to mirror.
581  */
582 void
lepton_line_object_mirror(int world_centerx,int world_centery,LeptonObject * object)583 lepton_line_object_mirror (int world_centerx,
584                            int world_centery,
585                            LeptonObject *object)
586 {
587   g_return_if_fail (lepton_object_is_line (object));
588   g_return_if_fail (object->line != NULL);
589 
590   /* translate object to origin */
591   lepton_line_object_translate (object, -world_centerx, -world_centery);
592 
593   /* mirror the line ends */
594   object->line->x[0] = -object->line->x[0];
595   object->line->x[1] = -object->line->x[1];
596 
597   /* translate back in position */
598   lepton_line_object_translate (object, world_centerx, world_centery);
599 
600 }
601 
602 /*! \brief Calculate the bounds of the line
603  *
604  *  On failure, this function sets the bounds to empty.
605  *
606  *  \param [in]  object   The line object
607  *  \param [out] bounds   The bounds of the line
608  */
609 void
lepton_line_object_calculate_bounds(const LeptonObject * object,LeptonBounds * bounds)610 lepton_line_object_calculate_bounds (const LeptonObject *object,
611                                      LeptonBounds *bounds)
612 {
613   gint expand;
614 
615   lepton_bounds_init (bounds);
616 
617   g_return_if_fail (lepton_object_is_line (object));
618   g_return_if_fail (object->line != NULL);
619 
620   lepton_line_calculate_bounds (object->line, bounds);
621 
622   expand = ceil (0.5 * G_SQRT2 * lepton_object_get_stroke_width (object));
623 
624   /* This isn't strictly correct, but a 1st order approximation */
625   lepton_bounds_expand (bounds, bounds, expand, expand);
626 }
627 
628 /*! \brief get the position of the first line point
629  *  \par Function Description
630  *  This function gets the position of the first point of a line object.
631  *
632  *  \param [in] object   The object to get the position.
633  *  \param [out] x       pointer to the x-position
634  *  \param [out] y       pointer to the y-position
635  *  \return TRUE if successfully determined the position, FALSE otherwise
636  */
637 gboolean
lepton_line_object_get_position(const LeptonObject * object,gint * x,gint * y)638 lepton_line_object_get_position (const LeptonObject *object,
639                                  gint *x,
640                                  gint *y)
641 {
642   g_return_val_if_fail (lepton_object_is_line (object), FALSE);
643   g_return_val_if_fail (object->line != NULL, FALSE);
644 
645   if (x != NULL) {
646     *x = object->line->x[0];
647   }
648 
649   if (y != NULL) {
650     *y = object->line->y[0];
651   }
652 
653   return TRUE;
654 }
655 
656 /*! \brief calculate the length of a line object
657  *  \par Function Description
658  *  This function calculates the length of a line object
659  *
660  *  \param [in] object  a line LeptonObject
661  *  \return The length of the line
662  */
663 double
lepton_line_object_length(LeptonObject * object)664 lepton_line_object_length (LeptonObject *object)
665 {
666   double length;
667   double dx, dy;
668 
669   if (!object->line) {
670     return 0.0;
671   }
672 
673   dx = object->line->x[0]-object->line->x[1];
674   dy = object->line->y[0]-object->line->y[1];
675 
676   length = hypot(dx, dy);
677 
678   return(length);
679 }
680 
681 /*! \brief Calculates the distance between the given point and the closest
682  *  point on the given line segment.
683  *
684  *  If the closest point on the line resides beyond the line segment's
685  *  end point, this function returns the distance from the given point to the
686  *  closest end point.
687  *
688  *  If the line represents a single point (the endpoints are the same), this
689  *  function calcualtes the distance to that point.
690  *
691  *  \param [in] object         The line LeptonObject.
692  *  \param [in] x              The x coordinate of the given point.
693  *  \param [in] y              The y coordinate of the given point.
694  *  \param [in] force_solid    If true, force treating the object as solid.
695  *  \param [in] include_hidden Take hidden text into account.
696  *  \return The shortest distance from the object to the point. With an
697  *  invalid parameter, this function returns G_MAXDOUBLE.
698  */
699 double
lepton_line_object_shortest_distance(LeptonObject * object,int x,int y,int force_solid,gboolean include_hidden)700 lepton_line_object_shortest_distance (LeptonObject *object,
701                                       int x,
702                                       int y,
703                                       int force_solid,
704                                       gboolean include_hidden)
705 {
706   return lepton_line_shortest_distance (object->line, x, y);
707 }
708