Updated copyright text/header in most source files.
[geda-gaf/peter-b.git] / libgeda / src / o_path_basic.c
blobed502c1b1708634aa81c38e5c52be6e95ce3506a
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <string.h>
26 #include "libgeda_priv.h"
28 #ifdef HAVE_LIBDMALLOC
29 #include <dmalloc.h>
30 #endif
32 /*! Default setting for path draw function. */
33 void (*path_draw_func)() = NULL;
36 typedef void (*DRAW_FUNC) (TOPLEVEL *toplevel, FILE *fp, PATH *path,
37 int line_width, int length, int space,
38 int origin_x, int origin_y);
41 typedef void (*FILL_FUNC) (TOPLEVEL *toplevel, FILE *fp, PATH *path,
42 int fill_width,
43 int angle1, int pitch1, int angle2, int pitch2,
44 int origin_x, int origin_y);
47 /*! \brief Create and add path OBJECT to list.
48 * \par Function Description
49 * This function creates a new object representing a path.
50 * This object is added to the end of the list <B>object_list</B>
51 * pointed object belongs to.
52 * The path is described by its two ends - <B>x1</B>,<B>y1</B> and
53 * <B>x2</B>,<B>y2</B>.
54 * The <B>type</B> parameter must be equal to #OBJ_PATH.
55 * The <B>color</B> parameter corresponds to the color the path
56 * will be drawn with.
58 * The #OBJECT structure is allocated with the
59 * #s_basic_init_object() function. The structure describing
60 * the path is allocated and initialized with the parameters given
61 * to the function.
63 * Both the path type and the filling type are set to default
64 * values : solid path type with a width of 0, and no filling.
65 * It can be changed after with the #o_set_line_options() and
66 * #o_set_fill_options().
68 * The object is added to the end of the list described by the
69 * <B>object_list</B> parameter by the #s_basic_link_object().
71 * \param [in] toplevel The TOPLEVEL object.
72 * \param [in] type Must be OBJ_PATH.
73 * \param [in] color The path color.
74 * \param [in] path_string The string representation of the path
75 * \return A pointer to the new end of the object list.
77 OBJECT *o_path_new (TOPLEVEL *toplevel,
78 char type, int color, const char *path_string)
80 OBJECT *new_node;
82 /* create the object */
83 new_node = s_basic_new_object (type, "path");
84 new_node->color = color;
86 new_node->path = s_path_parse (path_string);
88 /* path type and filling initialized to default */
89 o_set_line_options (toplevel, new_node,
90 END_NONE, TYPE_SOLID, 0, -1, -1);
91 o_set_fill_options (toplevel, new_node,
92 FILLING_HOLLOW, -1, -1, -1, -1, -1);
94 new_node->draw_func = path_draw_func;
95 new_node->sel_func = select_func;
97 /* compute bounding box */
98 o_path_recalc (toplevel, new_node);
100 return new_node;
104 /*! \brief Create a copy of a path.
105 * \par Function Description
106 * This function creates a verbatim copy of the
107 * object pointed by <B>o_current</B> describing a path. The new object
108 * is added at the end of the list following the <B>list_tail</B>
109 * parameter.
111 * \param [in] toplevel The TOPLEVEL object.
112 * \param [in] o_current Line OBJECT to copy.
113 * \return A new pointer to the end of the object list.
115 OBJECT *o_path_copy (TOPLEVEL *toplevel, OBJECT *o_current)
117 OBJECT *new_obj;
118 char *path_string;
120 path_string = s_path_string_from_path (o_current->path);
121 new_obj = o_path_new (toplevel, OBJ_PATH, o_current->color, path_string);
122 g_free (path_string);
124 /* copy the path type and filling options */
125 o_set_line_options (toplevel, new_obj, o_current->line_end,
126 o_current->line_type, o_current->line_width,
127 o_current->line_length, o_current->line_space);
128 o_set_fill_options (toplevel, new_obj,
129 o_current->fill_type, o_current->fill_width,
130 o_current->fill_pitch1, o_current->fill_angle1,
131 o_current->fill_pitch2, o_current->fill_angle2);
133 /* calc the bounding box */
134 o_path_recalc (toplevel, o_current);
136 /* return the new tail of the object list */
137 return new_obj;
141 /*! \brief Create path OBJECT from character string.
142 * \par Function Description
143 * This function creates a path OBJECT from the character string
144 * <B>*buf</B> and a number of lines following that describing the
145 * path, read from <B>*tb</B>.
147 * Depending on <B>*version</B>, the correct file format is considered.
148 * Currently two file format revisions are supported :
149 * <DL>
150 * <DT>*</DT><DD>the file format used until 20010704 release.
151 * <DT>*</DT><DD>the file format used for the releases after 20010704.
152 * </DL>
154 * \param [in] toplevel The TOPLEVEL object.
155 * \param [in] first_line Character string with path description.
156 * \param [in] tb Text buffer containing the path string.
157 * \param [in] release_ver libgeda release version number.
158 * \param [in] fileformat_ver libgeda file format version number.
159 * \return A pointer to the new path object.
161 OBJECT *o_path_read (TOPLEVEL *toplevel,
162 const char *first_line, TextBuffer *tb,
163 unsigned int release_ver, unsigned int fileformat_ver)
165 OBJECT *new_obj;
166 char type;
167 int color;
168 int line_width, line_space, line_length;
169 int line_end;
170 int line_type;
171 int fill_type, fill_width, angle1, pitch1, angle2, pitch2;
172 int num_lines = 0;
173 int i;
174 char *string;
175 GString *pathstr;
178 * The current path format to describe a line is a space separated
179 * list of characters and numbers in plain ASCII on a single path.
180 * The meaning of each item is described in the file format documentation.
182 /* Allocate enough space */
183 sscanf (first_line, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
184 &type, &color, &line_width, &line_end, &line_type,
185 &line_length, &line_space, &fill_type, &fill_width, &angle1,
186 &pitch1, &angle2, &pitch2, &num_lines);
189 * Checks if the required color is valid.
191 if (color < 0 || color > MAX_COLORS) {
192 s_log_message (_("Found an invalid color [ %s ]\n"), first_line);
193 s_log_message (_("Setting color to default color\n"));
194 color = DEFAULT_COLOR;
198 * A path is internally described by its two ends. A new object is
199 * allocated, initialized and added to the list of objects. Its path
200 * type is set according to the values of the fields on the path.
203 pathstr = g_string_new ("");
204 for (i = 0; i < num_lines; i++) {
205 gchar *line;
207 line = s_textbuffer_next_line (tb);
209 if (line != NULL) {
210 pathstr = g_string_append (pathstr, line);
214 /* retrieve the character string from the GString */
215 string = g_string_free (pathstr, FALSE);
216 string = remove_last_nl (string);
218 /* create a new path */
219 new_obj = o_path_new (toplevel, type, color, string);
220 g_free (string);
222 /* set its line options */
223 o_set_line_options (toplevel, new_obj,
224 line_end, line_type, line_width, line_length, line_space);
225 /* set its fill options */
226 o_set_fill_options (toplevel, new_obj,
227 fill_type, fill_width, pitch1, angle1, pitch2, angle2);
229 return new_obj;
233 /*! \brief Create a character string representation of a path OBJECT.
234 * \par Function Description
235 * The function formats a string in the buffer <B>*buff</B> to describe
236 * the path object <B>*object</B>.
238 * \param [in] object path OBJECT to create string from.
239 * \return A pointer to the path OBJECT character string.
241 * \note
242 * Caller must g_free returned character string.
245 char *o_path_save (OBJECT *object)
247 int line_width, line_space, line_length;
248 char *buf;
249 int num_lines;
250 OBJECT_END line_end;
251 OBJECT_TYPE line_type;
252 OBJECT_FILLING fill_type;
253 int fill_width, angle1, pitch1, angle2, pitch2;
254 char *path_string;
256 /* description of the line type */
257 line_width = object->line_width;
258 line_end = object->line_end;
259 line_type = object->line_type;
260 line_length = object->line_length;
261 line_space = object->line_space;
263 /* filling parameters */
264 fill_type = object->fill_type;
265 fill_width = object->fill_width;
266 angle1 = object->fill_angle1;
267 pitch1 = object->fill_pitch1;
268 angle2 = object->fill_angle2;
269 pitch2 = object->fill_pitch2;
271 path_string = s_path_string_from_path (object->path);
272 num_lines = o_text_num_lines (path_string);
273 buf = g_strdup_printf ("%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n%s",
274 object->type, object->color, line_width, line_end,
275 line_type, line_length, line_space, fill_type,
276 fill_width, angle1, pitch1, angle2, pitch2,
277 num_lines, path_string);
278 g_free (path_string);
280 return buf;
284 /*! \brief Modify controol point location
286 * \par Function Description
287 * This function modifies a control point location of the path object
288 * *object. The control point being modified is selected according to
289 * the whichone parameter.
291 * The new position is given by <B>x</B> and <B>y</B>.
293 * \param [in] toplevel The TOPLEVEL object.
294 * \param [in,out] object The path OBJECT
295 * \param [in] x New x coordinate for the control point
296 * \param [in] y New y coordinate for the control point
297 * \param [in] whichone Which control point is being modified
299 void o_path_modify (TOPLEVEL *toplevel, OBJECT *object,
300 int x, int y, int whichone)
302 int i;
303 int grip_no = 0;
304 PATH_SECTION *section;
306 for (i = 0; i < object->path->num_sections; i++) {
307 section = &object->path->sections[i];
309 switch (section->code) {
310 case PATH_CURVETO:
311 /* Two control point grips */
312 if (whichone == grip_no++) {
313 section->x1 = x;
314 section->y1 = y;
316 if (whichone == grip_no++) {
317 section->x2 = x;
318 section->y2 = y;
320 /* Fall through */
321 case PATH_MOVETO:
322 case PATH_MOVETO_OPEN:
323 case PATH_LINETO:
324 /* Destination point grip */
325 if (whichone == grip_no++) {
326 section->x3 = x;
327 section->y3 = y;
329 break;
330 case PATH_END:
331 break;
335 /* Update bounding box */
336 o_path_recalc (toplevel, object);
340 /*! \brief Translate a path position in WORLD coordinates by a delta.
341 * \par Function Description
342 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the path
343 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
345 * \param [in] toplevel The TOPLEVEL object.
346 * \param [in] dx x distance to move.
347 * \param [in] dy y distance to move.
348 * \param [in,out] object Line OBJECT to translate.
350 void o_path_translate_world (TOPLEVEL *toplevel,
351 int dx, int dy, OBJECT *object)
353 PATH_SECTION *section;
354 int i;
356 for (i = 0; i < object->path->num_sections; i++) {
357 section = &object->path->sections[i];
359 switch (section->code) {
360 case PATH_CURVETO:
361 section->x1 += dx;
362 section->y1 += dy;
363 section->x2 += dx;
364 section->y2 += dy;
365 /* Fall through */
366 case PATH_MOVETO:
367 case PATH_MOVETO_OPEN:
368 case PATH_LINETO:
369 section->x3 += dx;
370 section->y3 += dy;
371 break;
372 case PATH_END:
373 break;
377 /* Update bounding box */
378 o_path_recalc (toplevel, object);
382 /*! \brief Rotate Line OBJECT using WORLD coordinates.
383 * \par Function Description
384 * This function rotates the path described by
385 * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>)
386 * point by <B>angle</B> degrees.
387 * The center of rotation is in world units.
389 * \param [in] toplevel The TOPLEVEL object.
390 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
391 * \param [in] world_centery Rotation center y coordinate in WORLD units.
392 * \param [in] angle Rotation angle in degrees (See note below).
393 * \param [in,out] object Line OBJECT to rotate.
395 void o_path_rotate_world (TOPLEVEL *toplevel,
396 int world_centerx, int world_centery, int angle,
397 OBJECT *object)
399 PATH_SECTION *section;
400 int i;
402 for (i = 0; i < object->path->num_sections; i++) {
403 section = &object->path->sections[i];
405 switch (section->code) {
406 case PATH_CURVETO:
407 /* Two control point grips */
408 section->x1 -= world_centerx; section->y1 -= world_centery;
409 section->x2 -= world_centerx; section->y2 -= world_centery;
410 rotate_point_90 (section->x1, section->y1, angle, &section->x1, &section->y1);
411 rotate_point_90 (section->x2, section->y2, angle, &section->x2, &section->y2);
412 section->x1 += world_centerx; section->y1 += world_centery;
413 section->x2 += world_centerx; section->y2 += world_centery;
414 /* Fall through */
415 case PATH_MOVETO:
416 case PATH_MOVETO_OPEN:
417 case PATH_LINETO:
418 /* Destination point grip */
419 section->x3 -= world_centerx; section->y3 -= world_centery;
420 rotate_point_90 (section->x3, section->y3, angle, &section->x3, &section->y3);
421 section->x3 += world_centerx; section->y3 += world_centery;
422 break;
423 case PATH_END:
424 break;
427 o_path_recalc (toplevel, object);
431 /*! \brief Mirror a path using WORLD coordinates.
432 * \par Function Description
433 * This function mirrors the path from the point
434 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
436 * \param [in] toplevel The TOPLEVEL object.
437 * \param [in] world_centerx Origin x coordinate in WORLD units.
438 * \param [in] world_centery Origin y coordinate in WORLD units.
439 * \param [in,out] object Line OBJECT to mirror.
441 void o_path_mirror_world (TOPLEVEL *toplevel, int world_centerx,
442 int world_centery, OBJECT *object)
444 PATH_SECTION *section;
445 int i;
447 for (i = 0; i < object->path->num_sections; i++) {
448 section = &object->path->sections[i];
450 switch (section->code) {
451 case PATH_CURVETO:
452 /* Two control point grips */
453 section->x1 = 2 * world_centerx - section->x1;
454 section->x2 = 2 * world_centerx - section->x2;
455 /* Fall through */
456 case PATH_MOVETO:
457 case PATH_MOVETO_OPEN:
458 case PATH_LINETO:
459 /* Destination point grip */
460 section->x3 = 2 * world_centerx - section->x3;
461 break;
462 case PATH_END:
463 break;
467 o_path_recalc (toplevel, object);
471 /*! \brief Recalculate path coordinates in SCREEN units.
472 * \par Function Description
473 * This function recalculate the bounding box of the <B>o_current</B>
475 * \param [in] toplevel The TOPLEVEL object.
476 * \param [in,out] o_current Line OBJECT to be recalculated.
478 void o_path_recalc (TOPLEVEL *toplevel, OBJECT *o_current)
480 int left, right, top, bottom;
482 if (o_current->path == NULL) {
483 return;
486 /* Update the bounding box */
487 world_get_path_bounds (toplevel, o_current, &left, &top, &right, &bottom);
488 o_current->w_left = left;
489 o_current->w_top = top;
490 o_current->w_right = right;
491 o_current->w_bottom = bottom;
492 o_current->w_bounds_valid = TRUE;
496 /*! \brief Get path bounding rectangle in WORLD coordinates.
497 * \par Function Description
498 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
499 * <B>bottom</B> parameters to the boundings of the path object described
500 * in <B>*path</B> in world units.
502 * \note Bounding box for bezier curves is loose because we just consider
503 * the convex hull of the curve control and end-points.
505 * \param [in] toplevel The TOPLEVEL object.
506 * \param [in] object Line OBJECT to read coordinates from.
507 * \param [out] left Left path coordinate in WORLD units.
508 * \param [out] top Top path coordinate in WORLD units.
509 * \param [out] right Right path coordinate in WORLD units.
510 * \param [out] bottom Bottom path coordinate in WORLD units.
512 void world_get_path_bounds (TOPLEVEL *toplevel, OBJECT *object,
513 int *left, int *top, int *right, int *bottom)
515 PATH_SECTION *section;
516 int halfwidth;
517 int i;
518 int found_bound = FALSE;
520 /* Find the bounds of the path region */
521 for (i = 0; i < object->path->num_sections; i++) {
522 section = &object->path->sections[i];
523 switch (section->code) {
524 case PATH_CURVETO:
525 /* Bezier curves with this construction of control points will lie
526 * within the convex hull of the control and curve end points */
527 *left = (found_bound) ? MIN (*left, section->x1) : section->x1;
528 *top = (found_bound) ? MIN (*top, section->y1) : section->y1;
529 *right = (found_bound) ? MAX (*right, section->x1) : section->x1;
530 *bottom = (found_bound) ? MAX (*bottom, section->y1) : section->y1;
531 found_bound = TRUE;
532 *left = MIN (*left, section->x2);
533 *top = MIN (*top, section->y2);
534 *right = MAX (*right, section->x2);
535 *bottom = MAX (*bottom, section->y2);
536 /* Fall through */
537 case PATH_MOVETO:
538 case PATH_MOVETO_OPEN:
539 case PATH_LINETO:
540 *left = (found_bound) ? MIN (*left, section->x3) : section->x3;
541 *top = (found_bound) ? MIN (*top, section->y3) : section->y3;
542 *right = (found_bound) ? MAX (*right, section->x3) : section->x3;
543 *bottom = (found_bound) ? MAX (*bottom, section->y3) : section->y3;
544 found_bound = TRUE;
545 break;
546 case PATH_END:
547 break;
551 if (found_bound) {
552 /* This isn't strictly correct, but a 1st order approximation */
553 halfwidth = object->line_width / 2;
554 *left -= halfwidth;
555 *top -= halfwidth;
556 *right += halfwidth;
557 *bottom += halfwidth;
561 /*! \brief get the position of the first path point
562 * \par Function Description
563 * This function gets the position of the first point of an path object.
565 * \param [in] toplevel The toplevel environment.
566 * \param [out] x pointer to the x-position
567 * \param [out] y pointer to the y-position
568 * \param [in] object The object to get the position.
569 * \return TRUE if successfully determined the position, FALSE otherwise
571 gboolean o_path_get_position (TOPLEVEL *toplevel, gint *x, gint *y,
572 OBJECT *object)
574 if (object->path->num_sections == 0)
575 return FALSE;
577 *x = object->path->sections[0].x3;
578 *y = object->path->sections[0].y3;
579 return TRUE;
582 /*! \brief Print a solid PATH to Postscript document.
583 * \par Function Description
584 * This function prints the outline of a path when a solid line type is
585 * required. The postscript file is defined by the file pointer <B>fp</B>.
586 * The parameters <B>length</B> and <B>space</B> are ignored.
588 * All dimensions are in mils.
590 * \param [in] toplevel The TOPLEVEL object.
591 * \param [in] fp FILE pointer to Postscript document.
592 * \param [in] path The PATH object ot print
593 * \param [in] line_width PATH Line width.
594 * \param [in] length Dashed line length.
595 * \param [in] space Amount of space between dashes.
596 * \param [in] origin_x Page x coordinate to place PATH OBJECT.
597 * \param [in] origin_y Page y coordinate to place PATH OBJECT.
599 static void o_path_print_solid (TOPLEVEL *toplevel, FILE *fp, PATH *path,
600 int line_width, int length, int space,
601 int origin_x, int origin_y)
603 int i;
605 for (i = 0; i < path->num_sections; i++) {
606 PATH_SECTION *section = &path->sections[i];
608 if (i > 0)
609 fprintf (fp, " ");
611 switch (section->code) {
612 case PATH_MOVETO:
613 fprintf (fp, "closepath");
614 /* Fall through */
615 case PATH_MOVETO_OPEN:
616 fprintf (fp, "%i %i moveto",
617 section->x3 - origin_x, section->y3 - origin_y);
618 break;
619 case PATH_CURVETO:
620 fprintf (fp, "%i %i %i %i %i %i curveto",
621 section->x1 - origin_x, section->y1 - origin_y,
622 section->x2 - origin_x, section->y2 - origin_y,
623 section->x3 - origin_x, section->y3 - origin_y);
624 break;
625 case PATH_LINETO:
626 fprintf (fp, "%i %i lineto",
627 section->x3 - origin_x, section->y3 - origin_y);
628 break;
629 case PATH_END:
630 fprintf (fp, "closepath");
631 break;
635 fprintf (fp, " stroke\n");
639 /*! \brief Print a dotted PATH to Postscript document.
640 * \par Function Description
641 * This function prints the outline of a path when a dotted line type is
642 * required. The postscript file is defined by the file pointer <B>fp</B>.
643 * The parameter <B>length</B> is ignored.
645 * All dimensions are in mils.
647 * \param [in] toplevel The TOPLEVEL object
648 * \param [in] fp FILE pointer to Postscript document
649 * \param [in] path The PATH object to print
650 * \param [in] line_width PATH Line width
651 * \param [in] length Dashed line length
652 * \param [in] space Amount of space between dashes
653 * \param [in] origin_x Page x coordinate to place PATH OBJECT
654 * \param [in] origin_y Page y coordinate to place PATH OBJECT
656 static void o_path_print_dotted (TOPLEVEL *toplevel, FILE *fp, PATH *path,
657 int line_width, int length, int space,
658 int origin_x, int origin_y)
660 o_path_print_solid (toplevel, fp, path, line_width,
661 length, space, origin_x, origin_y);
665 /*! \brief Print a dashed PATH to Postscript document.
666 * \par Function Description
667 * This function prints the outline of a path when a dashed line type is
668 * required. The postscript file is defined by the file pointer <B>fp</B>.
670 * All dimensions are in mils.
672 * \param [in] toplevel The TOPLEVEL object.
673 * \param [in] fp FILE pointer to Postscript document.
674 * \param [in] path The PATH object to print.
675 * \param [in] line_width PATH Line width.
676 * \param [in] length Dashed line length.
677 * \param [in] space Amount of space between dashes.
678 * \param [in] origin_x Page x coordinate to place PATH OBJECT.
679 * \param [in] origin_y Page y coordinate to place PATH OBJECT.
681 static void o_path_print_dashed (TOPLEVEL *toplevel, FILE *fp, PATH *path,
682 int line_width, int length, int space,
683 int origin_x, int origin_y)
685 o_path_print_solid (toplevel, fp, path, line_width,
686 length, space, origin_x, origin_y);
690 /*! \brief Print centered line type PATH to Postscript document.
691 * \par Function Description
692 * This function prints the outline of a path when a centered line type is
693 * required. The postscript file is defined by the file pointer <B>fp</B>.
695 * All dimensions are in mils.
697 * \param [in] toplevel The TOPLEVEL object
698 * \param [in] fp FILE pointer to Postscript document
699 * \param [in] path The PATH object to print
700 * \param [in] line_width PATH Line width
701 * \param [in] length Dashed line length
702 * \param [in] space Amount of space between dashes
703 * \param [in] origin_x Page x coordinate to place PATH OBJECT
704 * \param [in] origin_y Page y coordinate to place PATH OBJECT
706 static void o_path_print_center (TOPLEVEL *toplevel, FILE *fp, PATH *path,
707 int line_width, int length,
708 int space, int origin_x, int origin_y)
710 o_path_print_solid (toplevel, fp, path, line_width,
711 length, space, origin_x, origin_y);
715 /*! \brief Print phantom line type PATH to Postscript document.
716 * \par Function Description
717 * This function prints the outline of a path when a phantom line type is
718 * required. The postscript file is defined by the file pointer <B>fp</B>.
720 * All dimensions are in mils.
722 * \param [in] toplevel The TOPLEVEL object
723 * \param [in] fp FILE pointer to Postscript document
724 * \param [in] path The PATH object to print
725 * \param [in] line_width PATH Line width
726 * \param [in] length Dashed line length
727 * \param [in] space Amount of space between dashes
728 * \param [in] origin_x Page x coordinate to place PATH OBJECT
729 * \param [in] origin_y Page y coordinate to place PATH OBJECT
731 static void o_path_print_phantom (TOPLEVEL *toplevel, FILE *fp, PATH *path,
732 int line_width, int length,
733 int space, int origin_x, int origin_y)
735 o_path_print_solid (toplevel, fp, path, line_width,
736 length, space, origin_x, origin_y);
740 /*! \brief Print a solid pattern PATH to Postscript document.
741 * \par Function Description
742 * The function prints a filled path with a solid pattern. No outline is
743 * printed. The postscript file is defined by the file pointer <B>fp</B>.
744 * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B> and <B>pitch2</B>
745 * parameters are ignored in this functions but kept for compatibility
746 * with other fill functions.
748 * All dimensions are in mils.
750 * \param [in] toplevel The TOPLEVEL object
751 * \param [in] fp FILE pointer to Postscript document
752 * \param [in] path The PATH object to print
753 * \param [in] fill_width PATH fill width (unused)
754 * \param [in] angle1 (unused)
755 * \param [in] pitch1 (unused)
756 * \param [in] angle2 (unused)
757 * \param [in] pitch2 (unused)
758 * \param [in] origin_x Page x coordinate to place PATH OBJECT
759 * \param [in] origin_y Page y coordinate to place PATH OBJECT
761 static void o_path_print_filled (TOPLEVEL *toplevel, FILE *fp, PATH *path,
762 int fill_width,
763 int angle1, int pitch1, int angle2, int pitch2,
764 int origin_x, int origin_y)
766 int i;
768 for (i = 0; i < path->num_sections; i++) {
769 PATH_SECTION *section = &path->sections[i];
771 if (i > 0)
772 fprintf (fp, " ");
774 switch (section->code) {
775 case PATH_MOVETO:
776 fprintf (fp, "closepath");
777 /* Fall through */
778 case PATH_MOVETO_OPEN:
779 fprintf (fp, "%i %i moveto",
780 section->x3 - origin_x, section->y3 - origin_y);
781 break;
782 case PATH_CURVETO:
783 fprintf (fp, "%i %i %i %i %i %i curveto",
784 section->x1 - origin_x, section->y1 - origin_y,
785 section->x2 - origin_x, section->y2 - origin_y,
786 section->x3 - origin_x, section->y3 - origin_y);
787 break;
788 case PATH_LINETO:
789 fprintf (fp, "%i %i lineto",
790 section->x3 - origin_x, section->y3 - origin_y);
791 break;
792 case PATH_END:
793 fprintf (fp, "closepath");
794 break;
798 fprintf (fp, " fill\n");
802 /*! \brief Print a hatch pattern PATH to Postscript document.
803 * \par Function Description
804 * The function prints a hatched path. No outline is printed.
805 * The postscript file is defined by the file pointer <B>fp</B>.
806 * <B>fill_width</B>, <B>angle1</B>, <B>pitch1</B> parameters define the way the path
807 * has to be hatched.
808 * <B>angle2</B> and <B>pitch2</B> parameters are unused but kept for compatibility
809 * with other fill functions.
811 * Negative or zero values for <B>pitch1</B> are not allowed.
813 * All dimensions are in mils.
815 * \param [in] toplevel The TOPLEVEL object
816 * \param [in] fp FILE pointer to Postscript document
817 * \param [in] path The PATH object to print
818 * \param [in] fill_width PATH fill width
819 * \param [in] angle1 Angle of hatch pattern
820 * \param [in] pitch1 Pitch of hatch pattern
821 * \param [in] angle2 (unused)
822 * \param [in] pitch2 (unused)
823 * \param [in] origin_x Page x coordinate to place PATH OBJECT
824 * \param [in] origin_y Page y coordinate to place PATH OBJECT
826 static void o_path_print_hatch (TOPLEVEL *toplevel, FILE *fp, PATH *path,
827 int fill_width,
828 int angle1, int pitch1, int angle2, int pitch2,
829 int origin_x, int origin_y)
831 int i;
832 GArray *lines;
834 g_return_if_fail (toplevel != NULL);
835 g_return_if_fail (fp != NULL);
837 /* Avoid printing line widths too small */
838 if (fill_width <= 1) fill_width = 2;
840 lines = g_array_new (FALSE, FALSE, sizeof(LINE));
842 m_hatch_path (path, angle1, pitch1, lines);
844 for (i=0; i < lines->len; i++) {
845 LINE *line = &g_array_index (lines, LINE, i);
847 fprintf (fp,"%d %d %d %d %d line\n", line->x[0], line->y[0],
848 line->x[1], line->y[1], fill_width);
851 g_array_free (lines, TRUE);
855 /*! \brief Print a mesh pattern PATH to Postscript document.
856 * \par Function Description
857 * This function prints a meshed path. No outline is printed.
858 * The postscript file is defined by the file pointer <B>fp</B>.
860 * Negative or zero values for <B>pitch1</B> and/or <B>pitch2</B> are
861 * not allowed.
863 * All dimensions are in mils.
865 * \param [in] toplevel The TOPLEVEL object
866 * \param [in] fp FILE pointer to Postscript document
867 * \param [in] path The PATH object to print
868 * \param [in] fill_width PATH fill width
869 * \param [in] angle1 1st angle for mesh pattern
870 * \param [in] pitch1 1st pitch for mesh pattern
871 * \param [in] angle2 2nd angle for mesh pattern
872 * \param [in] pitch2 2nd pitch for mesh pattern
873 * \param [in] origin_x Page x coordinate to place PATH OBJECT
874 * \param [in] origin_y Page y coordinate to place PATH OBJECT
876 static void o_path_print_mesh (TOPLEVEL *toplevel, FILE *fp, PATH *path,
877 int fill_width,
878 int angle1, int pitch1, int angle2, int pitch2,
879 int origin_x, int origin_y)
881 o_path_print_hatch (toplevel, fp, path, fill_width,
882 angle1, pitch1, -1, -1, origin_x, origin_y);
884 o_path_print_hatch (toplevel, fp, path, fill_width,
885 angle2, pitch2, -1, -1, origin_x, origin_y);
889 /*! \brief Print PATH to Postscript document.
890 * \par Function Description
891 * This function prints the path described by the <B>o_current</B>
892 * parameter to a Postscript document.
893 * The Postscript document is descibed by the file pointer <B>fp</B>.
895 * \param [in] toplevel The TOPLEVEL object.
896 * \param [in] fp FILE pointer to Postscript document.
897 * \param [in] o_current PATH OBJECT to write to document.
898 * \param [in] origin_x Page x coordinate to place PATH OBJECT.
899 * \param [in] origin_y Page y coordinate to place PATH OBJECT.
901 void o_path_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
902 int origin_x, int origin_y)
904 int color;
905 int line_width, length, space;
906 int fill_width, angle1, pitch1, angle2, pitch2;
907 DRAW_FUNC outl_func = NULL;
908 FILL_FUNC fill_func = NULL;
910 color = o_current->color;
912 /*! \note
913 * Depending on the type of the line for this particular path, the
914 * appropriate function is chosen among #o_path_print_solid(),
915 * #o_path_print_dotted(), #o_path_print_dashed(),
916 * #o_path_print_center() and #o_path_print_phantom().
918 * The needed parameters for each of these type is extracted from the
919 * <B>o_current</B> object. Depending on the type, unused parameters are
920 * set to -1.
922 * In the eventuality of a length and/or space null, the line is printed
923 * solid to avoid and endless loop produced by other functions in such a
924 * case.
926 line_width = o_current->line_width;
928 if (line_width <= 2) {
929 if (toplevel->line_style == THICK) {
930 line_width = LINE_WIDTH;
931 } else {
932 line_width=2;
935 length = o_current->line_length;
936 space = o_current->line_space;
938 switch(o_current->line_type) {
939 case TYPE_SOLID:
940 length = -1; space = -1;
941 outl_func = o_path_print_solid;
942 break;
944 case TYPE_DOTTED:
945 length = -1;
946 outl_func = o_path_print_dotted;
947 break;
949 case TYPE_DASHED:
950 outl_func = o_path_print_dashed;
951 break;
953 case TYPE_CENTER:
954 outl_func = o_path_print_center;
955 break;
957 case TYPE_PHANTOM:
958 outl_func = o_path_print_phantom;
959 break;
961 case TYPE_ERASE:
962 /* Unused for now, print it solid */
963 length = -1; space = -1;
964 outl_func = o_path_print_solid;
965 break;
968 if((length == 0) || (space == 0)) {
969 length = -1; space = -1;
970 outl_func = o_path_print_solid;
973 f_print_set_color (toplevel, fp, o_current->color);
975 f_print_set_line_width (fp, line_width);
977 (*outl_func) (toplevel, fp, o_current->path, line_width,
978 length, space, origin_x, origin_y);
980 /*! \note
981 * If the filling type of the path is not <B>HOLLOW</B>, the appropriate
982 * function is chosen among #o_path_print_filled(), #o_path_print_mesh()
983 * and #o_path_print_hatch(). The corresponding parameters are extracted
984 * from the <B>o_current</B> object and corrected afterward.
986 * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
987 * avoided as it leads to an endless loop in most of the called functions.
988 * In such a case, the path is printed filled. Unused parameters for each of
989 * these functions are set to -1 or any passive value.
991 if(o_current->fill_type != FILLING_HOLLOW) {
992 fill_width = o_current->fill_width;
993 angle1 = o_current->fill_angle1;
994 pitch1 = o_current->fill_pitch1;
995 angle2 = o_current->fill_angle2;
996 pitch2 = o_current->fill_pitch2;
998 switch(o_current->fill_type) {
999 case FILLING_FILL:
1000 angle1 = -1; pitch1 = 1;
1001 angle2 = -1; pitch2 = 1;
1002 fill_width = -1;
1003 fill_func = o_path_print_filled;
1004 break;
1006 case FILLING_MESH:
1007 fill_func = o_path_print_mesh;
1008 break;
1010 case FILLING_HATCH:
1011 angle2 = -1; pitch2 = 1;
1012 fill_func = o_path_print_hatch;
1013 break;
1015 case FILLING_VOID:
1016 /* Unused for now, print it filled */
1017 angle1 = -1; pitch1 = 1;
1018 angle2 = -1; pitch2 = 1;
1019 fill_width = -1;
1020 fill_func = o_path_print_filled;
1021 break;
1023 case FILLING_HOLLOW:
1024 /* nop */
1025 break;
1029 if((pitch1 <= 0) || (pitch2 <= 0)) {
1030 angle1 = -1; pitch1 = 1;
1031 angle2 = -1; pitch2 = 1;
1032 fill_func = o_path_print_filled;
1035 (*fill_func) (toplevel, fp,
1036 o_current->path, fill_width,
1037 angle1, pitch1, angle2, pitch2, origin_x, origin_y);
1042 /*! \brief Calculates the distance between the given point and the closest
1043 * point on the given path segment.
1045 * \param [in] object The path OBJECT.
1046 * \param [in] x The x coordinate of the given point.
1047 * \param [in] y The y coordinate of the given point.
1048 * \param [in] force_solid If true, force treating the object as solid.
1049 * \return The shortest distance from the object to the point. With an
1050 * invalid parameter, this function returns G_MAXDOUBLE.
1052 double o_path_shortest_distance (OBJECT *object, int x, int y, int force_solid)
1054 int solid;
1056 solid = force_solid || object->fill_type != FILLING_HOLLOW;
1058 return s_path_shortest_distance (object->path, x, y, solid);