Removed all trace of libgd usage and removed some old ps printing routines.
[geda-gaf.git] / libgeda / src / o_line_basic.c
blob610d21933f6e573402f767c1886247dc497cae7d
1 /* gEDA - GPL Electronic Design Automation
2 * libgeda - gEDA's library
3 * Copyright (C) 1998-2000 Ales V. Hvezda
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
19 #include <config.h>
21 #include <stdio.h>
22 #include <math.h>
24 #include <gtk/gtk.h>
25 #include <libguile.h>
28 #include "defines.h"
29 #include "struct.h"
30 #include "globals.h"
31 #include "o_types.h"
32 #include "colors.h"
33 #include "funcs.h"
35 #include "../include/prototype.h"
37 #ifdef HAVE_LIBDMALLOC
38 #include <dmalloc.h>
39 #endif
41 /*! \brief Create and add line OBJECT to list.
42 * \par Function Description
43 * This function creates a new object representing a line.
44 * This object is added to the end of the list <B>object_list</B>
45 * pointed object belongs to.
46 * The line is described by its two ends - <B>x1</B>,<B>y1</B> and
47 * <B>x2</B>,<B>y2</B>.
48 * The <B>type</B> parameter must be equal to #OBJ_LINE.
49 * The <B>color</B> parameter corresponds to the color the box
50 * will be drawn with.
52 * The #OBJECT structure is allocated with the
53 * #s_basic_init_object() function. The structure describing
54 * the line is allocated and initialized with the parameters given
55 * to the function.
57 * Both the line type and the filling type are set to default
58 * values : solid line type with a width of 0, and no filling.
59 * It can be changed after with the #o_set_line_options() and
60 * #o_set_fill_options().
62 * The object is added to the end of the list described by the
63 * <B>object_list</B> parameter by the #s_basic_link_object().
65 * \param [in] w_current The TOPLEVEL object.
66 * \param [in,out] object_list OBJECT list to add line to.
67 * \param [in] type Must be OBJ_LINE.
68 * \param [in] color Circle line color.
69 * \param [in] x1 Upper x coordinate.
70 * \param [in] y1 Upper y coordinate.
71 * \param [in] x2 Lower x coordinate.
72 * \param [in] y2 Lower y coordinate.
73 * \return A pointer to the new end of the object list.
75 OBJECT *o_line_add(TOPLEVEL *w_current, OBJECT *object_list,
76 char type, int color,
77 int x1, int y1, int x2, int y2)
79 OBJECT *new_node;
81 /* create the object */
82 new_node = s_basic_init_object("line");
83 new_node->type = type;
84 new_node->color = color;
86 new_node->line = (LINE *) g_malloc(sizeof(LINE));
88 /* describe the line with its two ends */
89 new_node->line->x[0] = x1;
90 new_node->line->y[0] = y1;
91 new_node->line->x[1] = x2;
92 new_node->line->y[1] = y2;
94 /* line type and filling initialized to default */
95 o_set_line_options(w_current, new_node,
96 END_NONE, TYPE_SOLID, 0, -1, -1);
97 o_set_fill_options(w_current, new_node,
98 FILLING_HOLLOW, -1, -1, -1, -1, -1);
100 new_node->draw_func = line_draw_func;
101 new_node->sel_func = select_func;
103 /* compute bounding box */
104 o_line_recalc(w_current, new_node);
106 object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
108 return(object_list);
111 /*! \brief Create a copy of a line.
112 * \par Function Description
113 * This function creates a verbatim copy of the
114 * object pointed by <B>o_current</B> describing a line. The new object
115 * is added at the end of the list following the <B>list_tail</B>
116 * parameter.
118 * \param [in] w_current The TOPLEVEL object.
119 * \param [out] list_tail OBJECT list to copy to.
120 * \param [in] o_current Line OBJECT to copy.
121 * \return A new pointer to the end of the object list.
123 OBJECT *o_line_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
125 OBJECT *new_obj;
126 ATTRIB *a_current;
127 int color;
129 if (o_current->saved_color == -1) {
130 color = o_current->color;
131 } else {
132 color = o_current->saved_color;
136 * A new line object is added a the end of the object list with
137 * #o_line_add(). Values for its fields are default and need to
138 * be modified.
140 new_obj = o_line_add(w_current, list_tail,
141 OBJ_LINE, color,
142 0, 0, 0, 0);
145 * The coordinates of the ends of the new line are set with the ones
146 * of the original line. The two lines have the sale line type and
147 * filling options.
149 * The bounding box are computed with
150 * #o_line_recalc().
153 /* modify the line ends of the new line */
154 new_obj->line->x[0] = o_current->line->x[0];
155 new_obj->line->y[0] = o_current->line->y[0];
156 new_obj->line->x[1] = o_current->line->x[1];
157 new_obj->line->y[1] = o_current->line->y[1];
159 /* copy the line type and filling options */
160 o_set_line_options(w_current, new_obj, o_current->line_end,
161 o_current->line_type, o_current->line_width,
162 o_current->line_length, o_current->line_space);
163 o_set_fill_options(w_current, new_obj,
164 o_current->fill_type, o_current->fill_width,
165 o_current->fill_pitch1, o_current->fill_angle1,
166 o_current->fill_pitch2, o_current->fill_angle2);
168 /* calc the bounding box */
169 o_line_recalc(w_current, o_current);
171 /* new_obj->attribute = 0;*/
172 a_current = o_current->attribs;
173 if (a_current) {
174 while ( a_current ) {
175 /* head attrib node has prev = NULL */
176 if (a_current->prev != NULL) {
177 a_current->copied_to = new_obj;
179 a_current = a_current->next;
183 /* return the new tail of the object list */
184 return(new_obj);
187 /*! \brief Modify the description of a line OBJECT.
188 * \par Function Description
189 * This function modifies the coordinates of one of the two ends of
190 * the line described by <B>*object</B>. The new coordinates of this end,
191 * identified by <B>whichone</B>, are given by <B>x</B> and <B>y</B>
192 * in world unit.
194 * The coordinates of the end of line is modified in the world
195 * coordinate system. Screen coordinates and boundings are then updated.
197 * \param [in] w_current The TOPLEVEL object.
198 * \param [in,out] object Line OBJECT to modify.
199 * \param [in] x New x coordinate.
200 * \param [in] y New y coordinate.
201 * \param [in] whichone Which line parameter to modify.
203 * <B>whichone</B> can have the following values:
204 * <DL>
205 * <DT>*</DT><DD>LINE_END1
206 * <DT>*</DT><DD>LINE_END2
207 * </DL>
209 * \par Author's note
210 * pb20011009 - modified
212 void o_line_modify(TOPLEVEL *w_current, OBJECT *object,
213 int x, int y, int whichone)
215 /* change one of the end of the line */
216 switch(whichone) {
217 case LINE_END1:
218 object->line->x[0] = x;
219 object->line->y[0] = y;
220 break;
222 case LINE_END2:
223 object->line->x[1] = x;
224 object->line->y[1] = y;
225 break;
227 default:
228 return;
231 /* recalculate the bounding box */
232 o_line_recalc(w_current, object);
236 /*! \brief Create line OBJECT from character string.
237 * \par Function Description
238 * This function creates a line OBJECT from the character string
239 * <B>*buf</B> the description of a box. The new box is added to the
240 * list of objects of which <B>*object_list</B> is the last element
241 * before the call.
242 * The function returns a pointer on the new last element, that is
243 * the added line object.
245 * Depending on <B>*version</B>, the correct file format is considered.
246 * Currently two file format revisions are supported :
247 * <DL>
248 * <DT>*</DT><DD>the file format used until 20010704 release.
249 * <DT>*</DT><DD>the file format used for the releases after 20010704.
250 * </DL>
252 * \param [in] w_current The TOPLEVEL object.
253 * \param [out] object_list OBJECT list to create line in.
254 * \param [in] buf Character string with line description.
255 * \param [in] release_ver libgeda release version number.
256 * \param [in] fileformat_ver libgeda file format version number.
257 * \return A pointer to the new line object.
259 OBJECT *o_line_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
260 unsigned int release_ver, unsigned int fileformat_ver)
262 char type;
263 int x1, y1;
264 int x2, y2;
265 int d_x1, d_y1;
266 int d_x2, d_y2;
267 int line_width, line_space, line_length;
268 int line_end;
269 int line_type;
270 int color;
272 if(release_ver <= VERSION_20000704) {
274 * The old geda file format, i.e. releases 20000704 and older, does
275 * not handle the line type and the filling - here filling is irrelevant.
276 * They are set to default.
278 sscanf(buf, "%c %d %d %d %d %d\n", &type,
279 &x1, &y1, &x2, &y2, &color);
281 line_width = 0;
282 line_end = END_NONE;
283 line_type = TYPE_SOLID;
284 line_length= -1;
285 line_space = -1;
286 } else {
288 * The current line format to describe a line is a space separated
289 * list of characters and numbers in plain ASCII on a single line.
290 * The meaning of each item is described in the file format documentation.
292 sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type,
293 &x1, &y1, &x2, &y2, &color,
294 &line_width, &line_end, &line_type, &line_length, &line_space);
297 d_x1 = x1; /* \todo PB : Needed ? */
298 d_y1 = y1;
299 d_x2 = x2;
300 d_y2 = y2;
303 * Null length line are not allowed. If such a line is detected a
304 * message is issued.
306 * It also checks is the required color is valid.
308 if (x1 == x2 && y1 == y2) {
309 fprintf(stderr, "Found a zero length line [ %c %d %d %d %d %d ]\n",
310 type, x1, y1, x2, y2, color);
311 s_log_message("Found a zero length line [ %c %d %d %d %d %d ]\n",
312 type, x1, y1, x2, y2, color);
315 if (color < 0 || color > MAX_COLORS) {
316 fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
317 s_log_message("Found an invalid color [ %s ]\n", buf);
318 s_log_message("Setting color to WHITE\n");
319 color = WHITE;
323 * A line is internally described by its two ends. A new object is
324 * allocated, initialized and added to the list of objects. Its line
325 * type is set according to the values of the fields on the line.
327 /* create and add the line to the list */
328 object_list = o_line_add(w_current, object_list,
329 type, color, d_x1, d_y1, d_x2, d_y2);
330 /* set its line options */
331 o_set_line_options(w_current, object_list,
332 line_end, line_type, line_width, line_length,
333 line_space);
334 /* filling is irrelevant for line, just set to default */
335 o_set_fill_options(w_current, object_list,
336 FILLING_HOLLOW, -1, -1, -1, -1, -1);
338 return(object_list);
341 /*! \brief Create a character string representation of a line OBJECT.
342 * \par Function Description
343 * The function formats a string in the buffer <B>*buff</B> to describe
344 * the box object <B>*object</B>.
345 * It follows the post-20000704 release file format that handle the
346 * line type and fill options - filling is irrelevant here.
348 * \param [in] object Line OBJECT to create string from.
349 * \return A pointer to the line OBJECT character string.
351 * \note
352 * Caller must free returned character string.
355 char *o_line_save(OBJECT *object)
357 int x1, x2, y1, y2;
358 int color;
359 int line_width, line_space, line_length;
360 char *buf;
361 OBJECT_END line_end;
362 OBJECT_TYPE line_type;
364 /* get the two ends */
365 x1 = object->line->x[0];
366 y1 = object->line->y[0];
367 x2 = object->line->x[1];
368 y2 = object->line->y[1];
370 /* description of the line type */
371 line_width = object->line_width;
372 line_end = object->line_end;
373 line_type = object->line_type;
374 line_length= object->line_length;
375 line_space = object->line_space;
377 /* Use the right color */
378 if (object->saved_color == -1) {
379 color = object->color;
380 } else {
381 color = object->saved_color;
384 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d", object->type,
385 x1, y1, x2, y2, color,
386 line_width, line_end, line_type,
387 line_length, line_space);
389 return(buf);
392 /*! \brief Translate a line position in WORLD coordinates by a delta.
393 * \par Function Description
394 * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the line
395 * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
397 * \param [in] w_current The TOPLEVEL object.
398 * \param [in] x1 x distance to move.
399 * \param [in] y1 y distance to move.
400 * \param [in,out] object Line OBJECT to translate.
402 void o_line_translate_world(TOPLEVEL *w_current,
403 int x1, int y1, OBJECT *object)
405 int left, right, top, bottom;
407 if (object == NULL) printf("ltw NO!\n");
409 /* Update world coords */
410 object->line->x[0] = object->line->x[0] + x1;
411 object->line->y[0] = object->line->y[0] + y1;
412 object->line->x[1] = object->line->x[1] + x1;
413 object->line->y[1] = object->line->y[1] + y1;
415 /* Update bounding box */
416 world_get_line_bounds(w_current, object, &left, &top, &right, &bottom);
418 object->w_left = left;
419 object->w_top = top;
420 object->w_right = right;
421 object->w_bottom = bottom;
425 /*! \brief Rotate Line OBJECT using WORLD coordinates.
426 * \par Function Description
427 * This function rotates the line described by
428 * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>)
429 * point by <B>angle</B> degrees.
430 * The center of rotation is in world units.
432 * \param [in] w_current The TOPLEVEL object.
433 * \param [in] world_centerx Rotation center x coordinate in WORLD units.
434 * \param [in] world_centery Rotation center y coordinate in WORLD units.
435 * \param [in] angle Rotation angle in degrees (See note below).
436 * \param [in,out] object Line OBJECT to rotate.
438 void o_line_rotate_world(TOPLEVEL *w_current,
439 int world_centerx, int world_centery, int angle,
440 OBJECT *object)
442 int newx, newy;
444 if (angle == 0)
445 return;
447 /* angle must be positive */
448 if(angle < 0) angle = -angle;
449 /* angle must be 90 multiple or no rotation performed */
450 if((angle % 90) != 0) return;
453 * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>)
454 * is translated to the origin. The rotation of the two ends of
455 * the line is performed. FInally, the rotated line is translated
456 * back to its previous location.
458 /* translate object to origin */
459 o_line_translate_world(w_current, -world_centerx, -world_centery, object);
461 /* rotate line end 1 */
462 rotate_point_90(object->line->x[0], object->line->y[0], angle,
463 &newx, &newy);
465 object->line->x[0] = newx;
466 object->line->y[0] = newy;
468 /* rotate line end 2 */
469 rotate_point_90(object->line->x[1], object->line->y[1], angle,
470 &newx, &newy);
472 object->line->x[1] = newx;
473 object->line->y[1] = newy;
475 /* translate object back to normal position */
476 o_line_translate_world(w_current, world_centerx, world_centery, object);
480 /*! \brief Mirror a line using WORLD coordinates.
481 * \par Function Description
482 * This function mirrors the line from the point
483 * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
485 * The line if first translated to the origin, then mirrored
486 * and finally translated back at its previous position.
488 * \param [in] w_current The TOPLEVEL object.
489 * \param [in] world_centerx Origin x coordinate in WORLD units.
490 * \param [in] world_centery Origin y coordinate in WORLD units.
491 * \param [in,out] object Line OBJECT to mirror.
493 void o_line_mirror_world(TOPLEVEL *w_current, int world_centerx,
494 int world_centery, OBJECT *object)
496 /* translate object to origin */
497 o_line_translate_world(w_current, -world_centerx, -world_centery, object);
499 /* mirror the line ends */
500 object->line->x[0] = -object->line->x[0];
501 object->line->x[1] = -object->line->x[1];
503 /* translate back in position */
504 o_line_translate_world(w_current, world_centerx, world_centery, object);
508 /*! \brief Recalculate line coordinates in SCREEN units.
509 * \par Function Description
510 * This function recalculate the bounding box of the <B>o_current</B>
512 * \param [in] w_current The TOPLEVEL object.
513 * \param [in,out] o_current Line OBJECT to be recalculated.
515 void o_line_recalc(TOPLEVEL *w_current, OBJECT *o_current)
517 int left, right, top, bottom;
519 if (o_current->line == NULL) {
520 return;
523 /* update the bounding box - screen unit */
524 world_get_line_bounds(w_current, o_current,
525 &left, &top, &right, &bottom);
526 o_current->w_left = left;
527 o_current->w_top = top;
528 o_current->w_right = right;
529 o_current->w_bottom = bottom;
533 /*! \brief Get line bounding rectangle in WORLD coordinates.
534 * \par Function Description
535 * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
536 * <B>bottom</B> parameters to the boundings of the line object described
537 * in <B>*line</B> in world units.
539 * \param [in] w_current The TOPLEVEL object.
540 * \param [in] OBJECT Line OBJECT to read coordinates from.
541 * \param [out] left Left line coordinate in WORLD units.
542 * \param [out] top Top line coordinate in WORLD units.
543 * \param [out] right Right line coordinate in WORLD units.
544 * \param [out] bottom Bottom line coordinate in WORLD units.
546 void world_get_line_bounds(TOPLEVEL *w_current, OBJECT *object,
547 int *left, int *top, int *right, int *bottom)
549 int halfwidth;
551 halfwidth = object->line_width / 2;
553 *left = min( object->line->x[0], object->line->x[1] );
554 *top = min( object->line->y[0], object->line->y[1] );
555 *right = max( object->line->x[0], object->line->x[1] );
556 *bottom = max( object->line->y[0], object->line->y[1] );
558 /* This isn't strictly correct, but a 1st order approximation */
559 *left -= halfwidth;
560 *top -= halfwidth;
561 *right += halfwidth;
562 *bottom += halfwidth;
565 /*! \brief Print line to Postscript document.
566 * \par Function Description
567 * This function prints the line described by the <B>o_current</B>
568 * parameter to a Postscript document.
569 * The Postscript document is described by the <B>fp</B> file pointer.
571 * Parameters of the line are extracted from object pointed by
572 * <B>o_current</B>.
574 * \param [in] w_current The TOPLEVEL object.
575 * \param [in] fp FILE pointer to Postscript document.
576 * \param [in] o_current Line OBJECT to write to document.
577 * \param [in] origin_x Page x coordinate to place line OBJECT.
578 * \param [in] origin_y Page y coordinate to place line OBJECT.
580 void o_line_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
581 int origin_x, int origin_y)
583 int x1, y1, x2, y2;
584 int color;
585 int line_width, length, space;
586 void (*outl_func)() = NULL;
588 if (o_current == NULL) {
589 printf("got null in o_line_print\n");
590 return;
593 x1 = o_current->line->x[0];
594 y1 = o_current->line->y[0];
595 x2 = o_current->line->x[1];
596 y2 = o_current->line->y[1];
597 color = o_current->color;
600 * Depending on the type of the line for this particular line, the
601 * appropriate function is chosen among
602 * #o_line_print_solid(), #o_line_print_dotted()#, #o_line_print_dashed(),
603 * #o_line_print_center() and #o_line_print_phantom().
605 * The needed parameters for each of these types are extracted from the
606 * <B>o_current</B> object. Depending on the type, unused parameters are
607 * set to -1.
609 * In the eventuality of a length and/or space null, the line is printed
610 * solid to avoid and endless loop produced by other functions.
612 line_width = o_current->line_width;
613 if(line_width <=2) {
614 if(w_current->line_style == THICK) {
615 line_width=LINE_WIDTH;
616 } else {
617 line_width=2;
621 length = o_current->line_length;
622 space = o_current->line_space;
624 switch(o_current->line_type) {
625 case(TYPE_SOLID):
626 length = -1; space = -1;
627 outl_func = o_line_print_solid;
628 break;
630 case(TYPE_DOTTED):
631 length = -1;
632 outl_func = o_line_print_dotted;
633 break;
635 case(TYPE_DASHED):
636 outl_func = o_line_print_dashed;
637 break;
639 case(TYPE_CENTER):
640 outl_func = o_line_print_center;
641 break;
643 case(TYPE_PHANTOM):
644 outl_func = o_line_print_phantom;
645 break;
647 case(TYPE_ERASE):
648 /* Unused for now, print it solid */
649 length = -1; space = -1;
650 outl_func = o_line_print_solid;
651 break;
654 if((length == 0) || (space == 0)) {
655 length = -1; space = -1;
656 outl_func = o_line_print_solid;
659 (*outl_func)(w_current, fp,
660 x1 - origin_x, y1 - origin_y,
661 x2 - origin_x, y2 - origin_y,
662 color,
663 line_width, length, space,
664 origin_x, origin_y);
667 /*! \brief Print a solid line to Postscript document.
668 * \par Function Description
669 * This function prints a line when a solid line type is required.
670 * The line is defined by the coordinates of its two ends in
671 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
672 * The Postscript document is defined by the file pointer <B>fp</B>.
673 * The parameters <B>length</B> and <B>space</B> are ignored whereas
674 * <B>line_width</B> specifies the width of the printed line.
676 * \param [in] w_current The TOPLEVEL object.
677 * \param [in] fp FILE pointer to Postscript document.
678 * \param [in] x1 Upper x coordinate.
679 * \param [in] y1 Upper y coordinate.
680 * \param [in] x2 Lower x coordinate.
681 * \param [in] y2 Lower y coordinate.
682 * \param [in] color Line color.
683 * \param [in] line_width Width of line.
684 * \param [in] length (unused).
685 * \param [in] space (unused).
686 * \param [in] origin_x Page x coordinate to place line OBJECT.
687 * \param [in] origin_y Page y coordinate to place line OBJECT.
689 void o_line_print_solid(TOPLEVEL *w_current, FILE *fp,
690 int x1, int y1, int x2, int y2,
691 int color,
692 int line_width, int length, int space,
693 int origin_x, int origin_y)
695 if (w_current->print_color) {
696 f_print_set_color(fp, color);
699 fprintf(fp,"%d %d %d %d %d line\n",
700 x1,y1,x2,y2, line_width);
703 /*! \brief Print a dotted line to Postscript document.
704 * \par Function Description
705 * This function prints a line when a dotted line type is required.
706 * The line is defined by the coordinates of its two ends in
707 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
708 * The Postscript document is defined by the file pointer <B>fp</B>.
709 * The parameter <B>length</B> is ignored whereas <B>line_width</B>
710 * specifies the diameter of the dots and <B>space</B> the distance
711 * between two dots.
713 * A negative value for <B>space</B> leads to an endless loop.
715 * All dimensions are in mils.
717 * The function sets the color in which the line will be printed with.
719 * \param [in] w_current The TOPLEVEL object.
720 * \param [in] fp FILE pointer to Postscript document.
721 * \param [in] x1 Upper x coordinate.
722 * \param [in] y1 Upper y coordinate.
723 * \param [in] x2 Lower x coordinate.
724 * \param [in] y2 Lower y coordinate.
725 * \param [in] color Line color.
726 * \param [in] line_width Width of line.
727 * \param [in] length (unused).
728 * \param [in] space Space between dots.
729 * \param [in] origin_x Page x coordinate to place line OBJECT.
730 * \param [in] origin_y Page y coordinate to place line OBJECT.
732 void o_line_print_dotted(TOPLEVEL *w_current, FILE *fp,
733 int x1, int y1, int x2, int y2,
734 int color,
735 int line_width, int length, int space,
736 int origin_x, int origin_y)
738 double dx, dy, l, d;
739 double dx1, dy1;
740 double xa, ya;
742 if (w_current->print_color) {
743 f_print_set_color(fp, color);
746 /* The dotted line command takes an array of dots so print out the
747 * beginnings of the array
749 fprintf(fp,"[");
750 /* PB : is the width relevant for a dot (circle) ? */
751 /* f_print_set_line_width(fp, line_width); */
754 * Depending on the slope of the line the space parameter is
755 * projected on each of the two directions x and y resulting
756 * in <B>dx1</B> and <B>dy1</B>. Starting from one end by increments
757 * of space the dots are printed.
759 * A dot is represented by a filled circle. Position of the
760 * circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>line_width</B>
761 * parameter.
764 dx = (double) (x2 - x1);
765 dy = (double) (y2 - y1);
766 l = sqrt((dx * dx) + (dy * dy));
768 dx1 = (dx * space) / l;
769 dy1 = (dy * space) / l;
771 d = 0;
772 xa = x1; ya = y1;
773 while(d < l) {
775 fprintf(fp,"[%d %d] ",
776 (int)xa, (int)ya);
777 d = d + space;
778 xa = xa + dx1;
779 ya = ya + dy1;
782 fprintf(fp,"] %d dashed\n",line_width);
787 /*! \brief Print a dashed line to Postscript document.
788 * \par Function Description
789 * This function prints a line when a dashed line type is required.
790 * The line is defined by the coordinates of its two ends in
791 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
792 * The postscript file is defined by the file pointer <B>fp</B>.
794 * A negative value for <B>space</B> or <B>length</B> leads to an
795 * endless loop.
797 * All dimensions are in mils.
799 * The function sets the color in which the line will be printed and
800 * the width of the line - that is the width of the dashes.
802 * \param [in] w_current The TOPLEVEL object.
803 * \param [in] fp FILE pointer to Postscript document.
804 * \param [in] x1 Upper x coordinate.
805 * \param [in] y1 Upper y coordinate.
806 * \param [in] x2 Lower x coordinate.
807 * \param [in] y2 Lower y coordinate.
808 * \param [in] color Line color.
809 * \param [in] line_width Width of line.
810 * \param [in] length Length of a dash.
811 * \param [in] space Space between dashes.
812 * \param [in] origin_x Page x coordinate to place line OBJECT.
813 * \param [in] origin_y Page y coordinate to place line OBJECT.
815 void o_line_print_dashed(TOPLEVEL *w_current, FILE *fp,
816 int x1, int y1, int x2, int y2,
817 int color,
818 int line_width, int length, int space,
819 int origin_x, int origin_y)
821 double dx, dy, l, d;
822 double dx1, dy1, dx2, dy2;
823 double xa, ya, xb, yb;
825 if (w_current->print_color) {
826 f_print_set_color(fp, color);
829 /* the dashed line function takes an array of start-finish pairs
830 * output the beginnings of the array now
832 fprintf(fp,"[");
835 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
836 * parameter is projected on each of the two directions x and y
837 * resulting in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
838 * Starting from one end and incrementing alternatively by <B>space</B>
839 * and <B>length</B> the dashes are printed.
841 * It prints as many dashes of length <B>length</B> as possible.
843 dx = (double) (x2 - x1);
844 dy = (double) (y2 - y1);
845 l = sqrt((dx * dx) + (dy * dy));
847 dx1 = (dx * length) / l;
848 dy1 = (dy * length) / l;
850 dx2 = (dx * space) / l;
851 dy2 = (dy * space) / l;
853 d = 0;
854 xa = x1; ya = y1;
855 while((d + length + space) < l) {
856 d = d + length;
857 xb = xa + dx1;
858 yb = ya + dy1;
860 fprintf(fp, "[%d %d %d %d] ",
861 (int) xa, (int) ya,
862 (int) xb, (int) yb);
864 d = d + space;
865 xa = xb + dx2;
866 ya = yb + dy2;
869 * When the above condition is no more satisfied, then it is not possible
870 * to print a dash of length <B>length</B>. However it may be possible to
871 * print the complete dash or a shorter one.
874 if((d + length) < l) {
875 d = d + length;
876 xb = xa + dx1;
877 yb = ya + dy1;
878 } else {
879 xb = x2;
880 yb = y2;
883 fprintf(fp, "[%d %d %d %d] ",
884 (int) xa, (int) ya,
885 (int) xb, (int) yb);
887 fprintf(fp,"] %d dashed\n", line_width);
891 /*! \brief Print a centered line type line to Postscript document.
892 * \par Function Description
893 * This function prints a line when a centered line type is required.
894 * The line is defined by the coordinates of its two ends in
895 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
896 * The Postscript document is defined by the file pointer <B>fp</B>.
898 * A negative value for <B>space</B> or <B>length</B> leads to an
899 * endless loop.
901 * All dimensions are in mils.
903 * The function sets the color in which the line will be printed and the
904 * width of the line - that is the width of the dashes and the diameter
905 * of the dots.
907 * \param [in] w_current The TOPLEVEL object.
908 * \param [in] fp FILE pointer to Postscript document.
909 * \param [in] x1 Upper x coordinate.
910 * \param [in] y1 Upper y coordinate.
911 * \param [in] x2 Lower x coordinate.
912 * \param [in] y2 Lower y coordinate.
913 * \param [in] color Line color.
914 * \param [in] line_width Width of line.
915 * \param [in] length Length of a dash.
916 * \param [in] space Space between dashes.
917 * \param [in] origin_x Page x coordinate to place line OBJECT.
918 * \param [in] origin_y Page y coordinate to place line OBJECT.
920 void o_line_print_center(TOPLEVEL *w_current, FILE *fp,
921 int x1, int y1, int x2, int y2,
922 int color,
923 int line_width, int length, int space,
924 int origin_x, int origin_y)
926 double dx, dy, l, d;
927 double dx1, dy1, dx2, dy2;
928 double xa, ya, xb, yb;
930 if (w_current->print_color) {
931 f_print_set_color(fp, color);
934 fprintf(fp, "[");
937 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
938 * parameter is projected on each of the two directions x and y resulting
939 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
940 * Starting from one end and incrementing alternatively by <B>space</B>
941 * and <B>length</B> the dashes and dots are printed.
943 * It prints as many sets of dash and dot as possible.
945 dx = (double) (x2 - x1);
946 dy = (double) (y2 - y1);
947 l = sqrt((dx * dx) + (dy * dy));
949 dx1 = (dx * length) / l;
950 dy1 = (dy * length) / l;
952 dx2 = (dx * space) / l;
953 dy2 = (dy * space) / l;
955 d = 0;
956 xa = x1; ya = y1;
957 while((d + length + 2 * space) < l) {
958 d = d + length;
959 xb = xa + dx1;
960 yb = ya + dy1;
962 fprintf(fp, "[%d %d %d %d] ",
963 (int) xa, (int) ya,
964 (int) xb, (int) yb);
966 d = d + space;
967 xa = xb + dx2;
968 ya = yb + dy2;
970 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
972 d = d + space;
973 xa = xa + dx2;
974 ya = ya + dy2;
977 * When the above condition is no more satisfied, then it is not possible
978 * to print a dash of length <B>length</B>.
979 * However two cases are possible :
980 * <DL>
981 * <DT>*</DT><DD>it is possible to print the dash and the dot.
982 * <DT>*</DT><DD>it is possible to print the dash or a part
983 * of the original dash.
984 * </DL>
987 if((d + length + space) < l) {
988 d = d + length;
989 xb = xa + dx1;
990 yb = ya + dy1;
992 fprintf(fp, "[%d %d %d %d] ",
993 (int) xa, (int) ya,
994 (int) xb, (int) yb);
996 d = d + space;
997 xa = xb + dx2;
998 ya = yb + dy2;
1000 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1002 } else {
1003 if(d + length < l) {
1004 xb = xa + dx1;
1005 yb = ya + dy1;
1006 } else {
1007 xb = x2;
1008 yb = y2;
1011 fprintf(fp, "[%d %d %d %d] ",
1012 (int) xa, (int) ya,
1013 (int) xb, (int) yb);
1017 fprintf(fp,"] %d dashed\n", line_width);
1020 * A dot is represented by a filled circle. Position of the circle is
1021 * (<B>xa</B>, <B>ya</B>) and its radius by the <B>line_width</B> parameter.
1025 /*! \brief Print a phantom line type line to Postscript document.
1026 * \par Function Description
1027 * This function prints a line when a phantom line type is required.
1028 * The line is defined by the coordinates of its two ends in
1029 * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
1030 * The Postscript document is defined by the file pointer <B>fp</B>.
1032 * A negative value for <B>space</B> or <B>length</B> leads to an
1033 * endless loop.
1035 * All dimensions are in mils.
1037 * The function sets the color in which the line will be printed and the
1038 * width of the line - that is the width of the dashes and the diameter
1039 * of the dots.
1041 * \param [in] w_current The TOPLEVEL object.
1042 * \param [in] fp FILE pointer to Postscript document.
1043 * \param [in] x1 Upper x coordinate.
1044 * \param [in] y1 Upper y coordinate.
1045 * \param [in] x2 Lower x coordinate.
1046 * \param [in] y2 Lower y coordinate.
1047 * \param [in] color Line color.
1048 * \param [in] line_width Width of line.
1049 * \param [in] length Length of a dash.
1050 * \param [in] space Space between dashes.
1051 * \param [in] origin_x Page x coordinate to place line OBJECT.
1052 * \param [in] origin_y Page y coordinate to place line OBJECT.
1054 void o_line_print_phantom(TOPLEVEL *w_current, FILE *fp,
1055 int x1, int y1, int x2, int y2,
1056 int color,
1057 int line_width, int length, int space,
1058 int origin_x, int origin_y)
1060 double dx, dy, l, d;
1061 double dx1, dy1, dx2, dy2;
1062 double xa, ya, xb, yb;
1064 if (w_current->print_color) {
1065 f_print_set_color(fp, color);
1068 fprintf(fp,"[");
1071 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
1072 * parameter is projected on each of the two directions x and y resulting
1073 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
1074 * Starting from one end and incrementing alternatively by <B>space</B>
1075 * and <B>length</B> the dashes and dots are printed.
1077 * It prints as many sets of dash-dot-dot as possible.
1079 dx = (double) (x2 - x1);
1080 dy = (double) (y2 - y1);
1081 l = sqrt((dx * dx) + (dy * dy));
1083 dx1 = (dx * length) / l;
1084 dy1 = (dy * length) / l;
1086 dx2 = (dx * space) / l;
1087 dy2 = (dy * space) / l;
1089 d = 0;
1090 xa = x1; ya = y1;
1091 while((d + length + 3 * space) < l) {
1092 d = d + length;
1093 xb = xa + dx1;
1094 yb = ya + dy1;
1096 fprintf(fp,"[%d %d %d %d] ",
1097 (int) xa, (int)ya,
1098 (int) xb, (int)yb);
1100 d = d + space;
1101 xa = xb + dx2;
1102 ya = yb + dy2;
1104 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1106 d = d + space;
1107 xa = xa + dx2;
1108 ya = ya + dy2;
1110 fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
1112 d = d + space;
1113 xa = xa + dx2;
1114 ya = ya + dy2;
1117 * When the above condition is no more satisfied, then it is not possible
1118 * to print a complete set of dash-dot-dot.
1119 * However three cases are possible :
1120 * <DL>
1121 * <DT>*</DT><DD>it is possible to print a dash and a dot and a dot.
1122 * <DT>*</DT><DD>it is possible to print a dash and a dot.
1123 * <DT>*</DT><DD>it is possible to print the dash or a part
1124 * of the original dash.
1125 * </DL>
1128 if((d + length + 2 * space) < l) {
1129 d = d + length;
1130 xb = xa + dx1;
1131 yb = ya + dy1;
1133 fprintf(fp,"[%d %d %d %d] ",
1134 (int) xa, (int)ya,
1135 (int) xb, (int)yb);
1137 d = d + space;
1138 xa = xb + dx2;
1139 ya = yb + dy2;
1141 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1143 d = d + space;
1144 xa = xb + dx2;
1145 ya = yb + dy2;
1147 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1149 } else {
1150 if(d + length + space < l) {
1151 d = d + length;
1152 xb = xa + dx1;
1153 yb = ya + dy1;
1155 fprintf(fp,"[%d %d %d %d] ",
1156 (int) xa, (int)ya,
1157 (int) xb, (int)yb);
1159 d = d + space;
1160 xa = xb + dx2;
1161 ya = yb + dy2;
1163 fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
1165 } else {
1166 if(d + length < l) {
1167 xb = xa + dx1;
1168 yb = ya + dy1;
1169 } else {
1170 xb = x2;
1171 yb = y2;
1174 fprintf(fp,"[%d %d %d %d] ",
1175 (int) xa, (int)ya,
1176 (int) xb, (int)yb);
1181 fprintf(fp,"] %d dashed\n", line_width);
1185 /*! \brief
1186 * \par Function Description
1188 * \param [in] w_current The TOPLEVEL object.
1189 * \param [in] x_scale
1190 * \param [in] y_scale
1191 * \param [in] object
1193 void o_line_scale_world(TOPLEVEL *w_current, int x_scale, int y_scale,
1194 OBJECT *object)
1196 if (object == NULL) printf("lsw NO!\n");
1198 /* scale the line world coords */
1199 object->line->x[0] = object->line->x[0] * x_scale;
1200 object->line->y[0] = object->line->y[0] * y_scale;
1201 object->line->x[1] = object->line->x[1] * x_scale;
1202 object->line->y[1] = object->line->y[1] * y_scale;
1204 /* update boundingbox */
1205 o_line_recalc(w_current, object);
1209 /*! \brief
1210 * \par Function Description
1212 * \param [in] w_current The TOPLEVEL object.
1213 * \param [in] line
1214 * \param [in] x1
1215 * \param [in] y1
1216 * \param [in] x2
1217 * \param [in] y2
1218 * \return int
1220 int o_line_visible(TOPLEVEL *w_current, LINE *line,
1221 int *x1, int *y1, int *x2, int *y2)
1223 int visible=0;
1226 /* don't do clipping if this is false */
1227 if (!w_current->object_clipping) {
1228 return(TRUE);
1231 WORLDtoSCREEN( w_current, line->x[0], line->y[0], x1, y1 );
1232 WORLDtoSCREEN( w_current, line->x[1], line->y[1], x2, y2 );
1234 visible = SCREENclip_change(w_current, x1, y1, x2, y2);
1236 return(visible);
1239 /*! \brief
1240 * \par Function Description
1242 * \param [in] object
1243 * \return double
1245 double o_line_length(OBJECT *object)
1247 double length;
1248 double dx, dy;
1250 if (!object->line) {
1251 return 0.0;
1254 dx = object->line->x[0]-object->line->x[1];
1255 dy = object->line->y[0]-object->line->y[1];
1257 length = sqrt((dx*dx) + (dy*dy));
1259 return(length);