libgeda

o_path_basic.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * libgeda - gEDA's library
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <math.h>
00024 #include <string.h>
00025 
00026 #include "libgeda_priv.h"
00027 
00028 #ifdef HAVE_LIBDMALLOC
00029 #include <dmalloc.h>
00030 #endif
00031 
00032 
00033 typedef void (*DRAW_FUNC) (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00034                            int line_width, int length, int space,
00035                            int origin_x, int origin_y);
00036 
00037 
00038 typedef void (*FILL_FUNC) (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00039                            int fill_width,
00040                            int angle1, int pitch1, int angle2, int pitch2,
00041                            int origin_x, int origin_y);
00042 
00043 
00074 OBJECT *o_path_new (TOPLEVEL *toplevel,
00075                     char type, int color, const char *path_string)
00076 {
00077   OBJECT *new_node;
00078 
00079   /* create the object */
00080   new_node        = s_basic_new_object (type, "path");
00081   new_node->color = color;
00082 
00083   new_node->path  = s_path_parse (path_string);
00084 
00085   /* path type and filling initialized to default */
00086   o_set_line_options (toplevel, new_node,
00087                       END_NONE, TYPE_SOLID, 0, -1, -1);
00088   o_set_fill_options (toplevel, new_node,
00089                       FILLING_HOLLOW, -1, -1, -1, -1, -1);
00090 
00091   /* compute bounding box */
00092   o_path_recalc (toplevel, new_node);
00093 
00094   return new_node;
00095 }
00096 
00097 
00109 OBJECT *o_path_copy (TOPLEVEL *toplevel, OBJECT *o_current)
00110 {
00111   OBJECT *new_obj;
00112   char *path_string;
00113 
00114   path_string = s_path_string_from_path (o_current->path);
00115   new_obj = o_path_new (toplevel, OBJ_PATH, o_current->color, path_string);
00116   g_free (path_string);
00117 
00118   /* copy the path type and filling options */
00119   o_set_line_options (toplevel, new_obj, o_current->line_end,
00120                       o_current->line_type, o_current->line_width,
00121                       o_current->line_length, o_current->line_space);
00122   o_set_fill_options (toplevel, new_obj,
00123                       o_current->fill_type, o_current->fill_width,
00124                       o_current->fill_pitch1, o_current->fill_angle1,
00125                       o_current->fill_pitch2, o_current->fill_angle2);
00126 
00127   /* calc the bounding box */
00128   o_path_recalc (toplevel, o_current);
00129 
00130   /* return the new tail of the object list */
00131   return new_obj;
00132 }
00133 
00134 
00155 OBJECT *o_path_read (TOPLEVEL *toplevel,
00156                      const char *first_line, TextBuffer *tb,
00157                      unsigned int release_ver, unsigned int fileformat_ver, GError **err)
00158 {
00159   OBJECT *new_obj;
00160   char type;
00161   int color;
00162   int line_width, line_space, line_length;
00163   int line_end;
00164   int line_type;
00165   int fill_type, fill_width, angle1, pitch1, angle2, pitch2;
00166   int num_lines = 0;
00167   int i;
00168   char *string;
00169   GString *pathstr;
00170 
00171   /*
00172    * The current path format to describe a line is a space separated
00173    * list of characters and numbers in plain ASCII on a single path.
00174    * The meaning of each item is described in the file format documentation.
00175    */
00176   /* Allocate enough space */
00177   if (sscanf (first_line, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
00178           &type, &color, &line_width, &line_end, &line_type,
00179           &line_length, &line_space, &fill_type, &fill_width, &angle1,
00180           &pitch1, &angle2, &pitch2, &num_lines) != 14) {
00181     g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse path object"));
00182     return NULL;
00183   }
00184 
00185   /*
00186    * Checks if the required color is valid.
00187    */
00188   if (color < 0 || color > MAX_COLORS) {
00189     s_log_message (_("Found an invalid color [ %s ]\n"), first_line);
00190     s_log_message (_("Setting color to default color\n"));
00191     color = DEFAULT_COLOR;
00192   }
00193 
00194   /*
00195    * A path is internally described by its two ends. A new object is
00196    * allocated, initialized and added to the list of objects. Its path
00197    * type is set according to the values of the fields on the path.
00198    */
00199 
00200   pathstr = g_string_new ("");
00201   for (i = 0; i < num_lines; i++) {
00202     const gchar *line;
00203 
00204     line = s_textbuffer_next_line (tb);
00205 
00206     if (line == NULL) {
00207       g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Unexpected end-of-file when reading path"));
00208       return NULL;
00209     }
00210 
00211     pathstr = g_string_append (pathstr, line);
00212   }
00213 
00214   /* retrieve the character string from the GString */
00215   string = g_string_free (pathstr, FALSE);
00216   string = remove_last_nl (string);
00217 
00218   /* create a new path */
00219   new_obj = o_path_new (toplevel, type, color, string);
00220   g_free (string);
00221 
00222   /* set its line options */
00223   o_set_line_options (toplevel, new_obj,
00224                       line_end, line_type, line_width, line_length, line_space);
00225   /* set its fill options */
00226   o_set_fill_options (toplevel, new_obj,
00227                       fill_type, fill_width, pitch1, angle1, pitch2, angle2);
00228 
00229   return new_obj;
00230 }
00231 
00232 
00246 char *o_path_save (TOPLEVEL *toplevel, OBJECT *object)
00247 {
00248   int line_width, line_space, line_length;
00249   char *buf;
00250   int num_lines;
00251   OBJECT_END line_end;
00252   OBJECT_TYPE line_type;
00253   OBJECT_FILLING fill_type;
00254   int fill_width, angle1, pitch1, angle2, pitch2;
00255   char *path_string;
00256 
00257   /* description of the line type */
00258   line_width  = object->line_width;
00259   line_end    = object->line_end;
00260   line_type   = object->line_type;
00261   line_length = object->line_length;
00262   line_space  = object->line_space;
00263 
00264   /* filling parameters */
00265   fill_type    = object->fill_type;
00266   fill_width   = object->fill_width;
00267   angle1       = object->fill_angle1;
00268   pitch1       = object->fill_pitch1;
00269   angle2       = object->fill_angle2;
00270   pitch2       = object->fill_pitch2;
00271 
00272   path_string = s_path_string_from_path (object->path);
00273   num_lines = o_text_num_lines (path_string);
00274   buf = g_strdup_printf ("%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n%s",
00275                          object->type, object->color, line_width, line_end,
00276                          line_type, line_length, line_space, fill_type,
00277                          fill_width, angle1, pitch1, angle2, pitch2,
00278                          num_lines, path_string);
00279   g_free (path_string);
00280 
00281   return buf;
00282 }
00283 
00284 
00300 void o_path_modify (TOPLEVEL *toplevel, OBJECT *object,
00301                     int x, int y, int whichone)
00302 {
00303   int i;
00304   int grip_no = 0;
00305   PATH_SECTION *section;
00306 
00307   o_emit_pre_change_notify (toplevel, object);
00308 
00309   for (i = 0; i <  object->path->num_sections; i++) {
00310     section = &object->path->sections[i];
00311 
00312     switch (section->code) {
00313     case PATH_CURVETO:
00314       /* Two control point grips */
00315       if (whichone == grip_no++) {
00316         section->x1 = x;
00317         section->y1 = y;
00318       }
00319       if (whichone == grip_no++) {
00320         section->x2 = x;
00321         section->y2 = y;
00322       }
00323       /* Fall through */
00324     case PATH_MOVETO:
00325     case PATH_MOVETO_OPEN:
00326     case PATH_LINETO:
00327       /* Destination point grip */
00328       if (whichone == grip_no++) {
00329         section->x3 = x;
00330         section->y3 = y;
00331       }
00332       break;
00333     case PATH_END:
00334       break;
00335     }
00336   }
00337 
00338   /* Update bounding box */
00339   o_path_recalc (toplevel, object);
00340   o_emit_change_notify (toplevel, object);
00341 }
00342 
00343 
00354 void o_path_translate_world (TOPLEVEL *toplevel,
00355                              int dx, int dy, OBJECT *object)
00356 {
00357   PATH_SECTION *section;
00358   int i;
00359 
00360   for (i = 0; i < object->path->num_sections; i++) {
00361     section = &object->path->sections[i];
00362 
00363     switch (section->code) {
00364     case PATH_CURVETO:
00365       section->x1 += dx;
00366       section->y1 += dy;
00367       section->x2 += dx;
00368       section->y2 += dy;
00369       /* Fall through */
00370     case PATH_MOVETO:
00371     case PATH_MOVETO_OPEN:
00372     case PATH_LINETO:
00373       section->x3 += dx;
00374       section->y3 += dy;
00375       break;
00376     case PATH_END:
00377       break;
00378     }
00379   }
00380 
00381   /* Update bounding box */
00382   o_path_recalc (toplevel, object);
00383 }
00384 
00385 
00399 void o_path_rotate_world (TOPLEVEL *toplevel,
00400                           int world_centerx, int world_centery, int angle,
00401                           OBJECT *object)
00402 {
00403   PATH_SECTION *section;
00404   int i;
00405 
00406   for (i = 0; i < object->path->num_sections; i++) {
00407     section = &object->path->sections[i];
00408 
00409     switch (section->code) {
00410     case PATH_CURVETO:
00411       /* Two control point grips */
00412       section->x1 -= world_centerx; section->y1 -= world_centery;
00413       section->x2 -= world_centerx; section->y2 -= world_centery;
00414       rotate_point_90 (section->x1, section->y1, angle, &section->x1, &section->y1);
00415       rotate_point_90 (section->x2, section->y2, angle, &section->x2, &section->y2);
00416       section->x1 += world_centerx; section->y1 += world_centery;
00417       section->x2 += world_centerx; section->y2 += world_centery;
00418       /* Fall through */
00419     case PATH_MOVETO:
00420     case PATH_MOVETO_OPEN:
00421     case PATH_LINETO:
00422       /* Destination point grip */
00423       section->x3 -= world_centerx; section->y3 -= world_centery;
00424       rotate_point_90 (section->x3, section->y3, angle, &section->x3, &section->y3);
00425       section->x3 += world_centerx; section->y3 += world_centery;
00426       break;
00427     case PATH_END:
00428       break;
00429     }
00430   }
00431   o_path_recalc (toplevel, object);
00432 }
00433 
00434 
00445 void o_path_mirror_world (TOPLEVEL *toplevel, int world_centerx,
00446                           int world_centery, OBJECT *object)
00447 {
00448   PATH_SECTION *section;
00449   int i;
00450 
00451   for (i = 0; i < object->path->num_sections; i++) {
00452     section = &object->path->sections[i];
00453 
00454     switch (section->code) {
00455     case PATH_CURVETO:
00456       /* Two control point grips */
00457       section->x1 = 2 * world_centerx - section->x1;
00458       section->x2 = 2 * world_centerx - section->x2;
00459       /* Fall through */
00460     case PATH_MOVETO:
00461     case PATH_MOVETO_OPEN:
00462     case PATH_LINETO:
00463       /* Destination point grip */
00464       section->x3 = 2 * world_centerx - section->x3;
00465       break;
00466     case PATH_END:
00467       break;
00468     }
00469   }
00470 
00471   o_path_recalc (toplevel, object);
00472 }
00473 
00474 
00482 void o_path_recalc (TOPLEVEL *toplevel, OBJECT *o_current)
00483 {
00484   int left = 0, right = 0, top = 0, bottom = 0;
00485 
00486   g_return_if_fail (o_current->path != NULL);
00487 
00488   /* Update the bounding box */
00489   if (o_current->path->num_sections > 0) {
00490     world_get_path_bounds (toplevel, o_current, &left, &top, &right, &bottom);
00491     o_current->w_left   = left;
00492     o_current->w_top    = top;
00493     o_current->w_right  = right;
00494     o_current->w_bottom = bottom;
00495     o_current->w_bounds_valid = TRUE;
00496   } else {
00497     o_current->w_bounds_valid = FALSE;
00498   }
00499 }
00500 
00501 
00518 void world_get_path_bounds (TOPLEVEL *toplevel, OBJECT *object,
00519                             int *left, int *top, int *right, int *bottom)
00520 {
00521   PATH_SECTION *section;
00522   int halfwidth;
00523   int i;
00524   int found_bound = FALSE;
00525 
00526   /* Find the bounds of the path region */
00527   for (i = 0; i < object->path->num_sections; i++) {
00528     section = &object->path->sections[i];
00529     switch (section->code) {
00530       case PATH_CURVETO:
00531         /* Bezier curves with this construction of control points will lie
00532          * within the convex hull of the control and curve end points */
00533         *left   = (found_bound) ? MIN (*left,   section->x1) : section->x1;
00534         *top    = (found_bound) ? MIN (*top,    section->y1) : section->y1;
00535         *right  = (found_bound) ? MAX (*right,  section->x1) : section->x1;
00536         *bottom = (found_bound) ? MAX (*bottom, section->y1) : section->y1;
00537         found_bound = TRUE;
00538         *left   = MIN (*left,   section->x2);
00539         *top    = MIN (*top,    section->y2);
00540         *right  = MAX (*right,  section->x2);
00541         *bottom = MAX (*bottom, section->y2);
00542         /* Fall through */
00543       case PATH_MOVETO:
00544       case PATH_MOVETO_OPEN:
00545       case PATH_LINETO:
00546         *left   = (found_bound) ? MIN (*left,   section->x3) : section->x3;
00547         *top    = (found_bound) ? MIN (*top,    section->y3) : section->y3;
00548         *right  = (found_bound) ? MAX (*right,  section->x3) : section->x3;
00549         *bottom = (found_bound) ? MAX (*bottom, section->y3) : section->y3;
00550         found_bound = TRUE;
00551         break;
00552       case PATH_END:
00553         break;
00554     }
00555   }
00556 
00557   if (found_bound) {
00558     /* This isn't strictly correct, but a 1st order approximation */
00559     halfwidth = object->line_width / 2;
00560     *left   -= halfwidth;
00561     *top    -= halfwidth;
00562     *right  += halfwidth;
00563     *bottom += halfwidth;
00564   }
00565 }
00566 
00577 gboolean o_path_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
00578                               OBJECT *object)
00579 {
00580   if (object->path->num_sections == 0)
00581     return FALSE;
00582 
00583   *x = object->path->sections[0].x3;
00584   *y = object->path->sections[0].y3;
00585   return TRUE;
00586 }
00587 
00605 static void o_path_print_solid (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00606                                 int line_width, int length, int space,
00607                                 int origin_x, int origin_y)
00608 {
00609   int i;
00610 
00611   for (i = 0; i < path->num_sections; i++) {
00612     PATH_SECTION *section = &path->sections[i];
00613 
00614     if (i > 0)
00615       fprintf (fp, " ");
00616 
00617     switch (section->code) {
00618       case PATH_MOVETO:
00619         fprintf (fp, "closepath");
00620         /* Fall through */
00621       case PATH_MOVETO_OPEN:
00622         fprintf (fp, "%i %i moveto",
00623                      section->x3 - origin_x, section->y3 - origin_y);
00624         break;
00625       case PATH_CURVETO:
00626         fprintf (fp, "%i %i %i %i %i %i curveto",
00627                      section->x1 - origin_x, section->y1 - origin_y,
00628                      section->x2 - origin_x, section->y2 - origin_y,
00629                      section->x3 - origin_x, section->y3 - origin_y);
00630         break;
00631       case PATH_LINETO:
00632         fprintf (fp, "%i %i lineto",
00633                      section->x3 - origin_x, section->y3 - origin_y);
00634         break;
00635       case PATH_END:
00636         fprintf (fp, "closepath");
00637         break;
00638     }
00639   }
00640 
00641   fprintf (fp, " stroke\n");
00642 }
00643 
00644 
00662 static void o_path_print_dotted (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00663                                  int line_width, int length, int space,
00664                                  int origin_x, int origin_y)
00665 {
00666   o_path_print_solid (toplevel, fp, path, line_width,
00667                       length, space, origin_x, origin_y);
00668 }
00669 
00670 
00687 static void o_path_print_dashed (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00688                                  int line_width, int length, int space,
00689                                  int origin_x, int origin_y)
00690 {
00691   o_path_print_solid (toplevel, fp, path, line_width,
00692                       length, space, origin_x, origin_y);
00693 }
00694 
00695 
00712 static void o_path_print_center (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00713                                  int line_width, int length,
00714                                  int space, int origin_x, int origin_y)
00715 {
00716   o_path_print_solid (toplevel, fp, path, line_width,
00717                       length, space, origin_x, origin_y);
00718 }
00719 
00720 
00737 static void o_path_print_phantom (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00738                                   int line_width, int length,
00739                                   int space, int origin_x, int origin_y)
00740 {
00741   o_path_print_solid (toplevel, fp, path, line_width,
00742                       length, space, origin_x, origin_y);
00743 }
00744 
00745 
00767 static void o_path_print_filled (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00768                                  int fill_width,
00769                                  int angle1, int pitch1, int angle2, int pitch2,
00770                                  int origin_x, int origin_y)
00771 {
00772   int i;
00773 
00774   for (i = 0; i < path->num_sections; i++) {
00775     PATH_SECTION *section = &path->sections[i];
00776 
00777     if (i > 0)
00778       fprintf (fp, " ");
00779 
00780     switch (section->code) {
00781       case PATH_MOVETO:
00782         fprintf (fp, "closepath");
00783         /* Fall through */
00784       case PATH_MOVETO_OPEN:
00785         fprintf (fp, "%i %i moveto",
00786                      section->x3 - origin_x, section->y3 - origin_y);
00787         break;
00788       case PATH_CURVETO:
00789         fprintf (fp, "%i %i %i %i %i %i curveto",
00790                      section->x1 - origin_x, section->y1 - origin_y,
00791                      section->x2 - origin_x, section->y2 - origin_y,
00792                      section->x3 - origin_x, section->y3 - origin_y);
00793         break;
00794       case PATH_LINETO:
00795         fprintf (fp, "%i %i lineto",
00796                      section->x3 - origin_x, section->y3 - origin_y);
00797         break;
00798       case PATH_END:
00799         fprintf (fp, "closepath");
00800         break;
00801     }
00802   }
00803 
00804   fprintf (fp, " fill\n");
00805 }
00806 
00807 
00832 static void o_path_print_hatch (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00833                                 int fill_width,
00834                                 int angle1, int pitch1, int angle2, int pitch2,
00835                                 int origin_x, int origin_y)
00836 {
00837   int i;
00838   GArray *lines;
00839 
00840   g_return_if_fail (toplevel != NULL);
00841   g_return_if_fail (fp != NULL);
00842 
00843   /* Avoid printing line widths too small */
00844   if (fill_width <= 1) fill_width = 2;
00845 
00846   lines = g_array_new (FALSE, FALSE, sizeof(LINE));
00847 
00848   m_hatch_path (path, angle1, pitch1, lines);
00849 
00850   for (i=0; i < lines->len; i++) {
00851     LINE *line = &g_array_index (lines, LINE, i);
00852 
00853     fprintf (fp,"%d %d %d %d %d line\n", line->x[0], line->y[0],
00854                                          line->x[1], line->y[1], fill_width);
00855   }
00856 
00857   g_array_free (lines, TRUE);
00858 }
00859 
00860 
00882 static void o_path_print_mesh (TOPLEVEL *toplevel, FILE *fp, PATH *path,
00883                                int fill_width,
00884                                int angle1, int pitch1, int angle2, int pitch2,
00885                                int origin_x, int origin_y)
00886 {
00887   o_path_print_hatch (toplevel, fp, path, fill_width,
00888                       angle1, pitch1, -1, -1, origin_x, origin_y);
00889 
00890   o_path_print_hatch (toplevel, fp, path, fill_width,
00891                       angle2, pitch2, -1, -1, origin_x, origin_y);
00892 }
00893 
00894 
00907 void o_path_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
00908                   int origin_x, int origin_y)
00909 {
00910   int line_width, length, space;
00911   int fill_width, angle1, pitch1, angle2, pitch2;
00912   DRAW_FUNC outl_func = NULL;
00913   FILL_FUNC fill_func = NULL;
00914 
00929   line_width = o_current->line_width;
00930 
00931   if (line_width <= 2) {
00932     if (toplevel->line_style == THICK) {
00933       line_width = LINE_WIDTH;
00934     } else {
00935       line_width=2;
00936     }
00937   }
00938   length = o_current->line_length;
00939   space  = o_current->line_space;
00940 
00941   switch(o_current->line_type) {
00942     case TYPE_SOLID:
00943       length = -1; space  = -1;
00944       outl_func = o_path_print_solid;
00945       break;
00946 
00947     case TYPE_DOTTED:
00948       length = -1;
00949       outl_func = o_path_print_dotted;
00950       break;
00951 
00952     case TYPE_DASHED:
00953       outl_func = o_path_print_dashed;
00954       break;
00955 
00956     case TYPE_CENTER:
00957       outl_func = o_path_print_center;
00958       break;
00959 
00960     case TYPE_PHANTOM:
00961       outl_func = o_path_print_phantom;
00962       break;
00963 
00964     case TYPE_ERASE:
00965       /* Unused for now, print it solid */
00966       length = -1; space  = -1;
00967       outl_func = o_path_print_solid;
00968       break;
00969   }
00970 
00971   if((length == 0) || (space == 0)) {
00972     length = -1; space  = -1;
00973     outl_func = o_path_print_solid;
00974   }
00975 
00976   f_print_set_color (toplevel, fp, o_current->color);
00977 
00978   f_print_set_line_width (fp, line_width);
00979 
00980   (*outl_func) (toplevel, fp, o_current->path, line_width,
00981                 length, space, origin_x, origin_y);
00982 
00994   if(o_current->fill_type != FILLING_HOLLOW) {
00995     fill_width = o_current->fill_width;
00996     angle1     = o_current->fill_angle1;
00997     pitch1     = o_current->fill_pitch1;
00998     angle2     = o_current->fill_angle2;
00999     pitch2     = o_current->fill_pitch2;
01000 
01001     switch(o_current->fill_type) {
01002       case FILLING_FILL:
01003         angle1 = -1; pitch1 = 1;
01004         angle2 = -1; pitch2 = 1;
01005         fill_width = -1;
01006         fill_func = o_path_print_filled;
01007         break;
01008 
01009       case FILLING_MESH:
01010         fill_func = o_path_print_mesh;
01011         break;
01012 
01013       case FILLING_HATCH:
01014         angle2 = -1; pitch2 = 1;
01015         fill_func = o_path_print_hatch;
01016         break;
01017 
01018       case FILLING_VOID:
01019         /* Unused for now, print it filled */
01020         angle1 = -1; pitch1 = 1;
01021         angle2 = -1; pitch2 = 1;
01022         fill_width = -1;
01023         fill_func = o_path_print_filled;
01024         break;
01025 
01026       case FILLING_HOLLOW:
01027         /* nop */
01028         break;
01029 
01030     }
01031 
01032     if((pitch1 <= 0) || (pitch2 <= 0)) {
01033       angle1 = -1; pitch1 = 1;
01034       angle2 = -1; pitch2 = 1;
01035       fill_func = o_path_print_filled;
01036     }
01037 
01038     (*fill_func) (toplevel, fp,
01039                   o_current->path, fill_width,
01040                   angle1, pitch1, angle2, pitch2, origin_x, origin_y);
01041   }
01042 }
01043 
01044 
01055 double o_path_shortest_distance (OBJECT *object, int x, int y, int force_solid)
01056 {
01057   int solid;
01058 
01059   solid = force_solid || object->fill_type != FILLING_HOLLOW;
01060 
01061   return s_path_shortest_distance (object->path, x, y, solid);
01062 }
01063 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines