libgeda
|
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 00025 #include <config.h> 00026 00027 #include <stdio.h> 00028 #include <math.h> 00029 00030 #include "libgeda_priv.h" 00031 00032 #ifdef HAVE_LIBDMALLOC 00033 #include <dmalloc.h> 00034 #endif 00035 00064 OBJECT *o_line_new(TOPLEVEL *toplevel, 00065 char type, int color, 00066 int x1, int y1, int x2, int y2) 00067 { 00068 OBJECT *new_node; 00069 00070 /* create the object */ 00071 new_node = s_basic_new_object(type, "line"); 00072 new_node->color = color; 00073 00074 new_node->line = (LINE *) g_malloc(sizeof(LINE)); 00075 00076 /* describe the line with its two ends */ 00077 new_node->line->x[0] = x1; 00078 new_node->line->y[0] = y1; 00079 new_node->line->x[1] = x2; 00080 new_node->line->y[1] = y2; 00081 00082 /* line type and filling initialized to default */ 00083 o_set_line_options(toplevel, new_node, 00084 END_NONE, TYPE_SOLID, 0, -1, -1); 00085 o_set_fill_options(toplevel, new_node, 00086 FILLING_HOLLOW, -1, -1, -1, -1, -1); 00087 00088 /* compute bounding box */ 00089 o_line_recalc(toplevel, new_node); 00090 00091 return new_node; 00092 } 00093 00103 OBJECT *o_line_copy(TOPLEVEL *toplevel, OBJECT *o_current) 00104 { 00105 OBJECT *new_obj; 00106 00107 /* A new line object is created with #o_line_new(). 00108 * Values for its fields are default and need to be modified. */ 00109 new_obj = o_line_new (toplevel, OBJ_LINE, o_current->color, 00110 o_current->line->x[0], o_current->line->y[0], 00111 o_current->line->x[1], o_current->line->y[1]); 00112 00113 /* 00114 * The coordinates of the ends of the new line are set with the ones 00115 * of the original line. The two lines have the sale line type and 00116 * filling options. 00117 * 00118 * The bounding box are computed with 00119 * #o_line_recalc(). 00120 */ 00121 00122 /* copy the line type and filling options */ 00123 o_set_line_options(toplevel, new_obj, o_current->line_end, 00124 o_current->line_type, o_current->line_width, 00125 o_current->line_length, o_current->line_space); 00126 o_set_fill_options(toplevel, new_obj, 00127 o_current->fill_type, o_current->fill_width, 00128 o_current->fill_pitch1, o_current->fill_angle1, 00129 o_current->fill_pitch2, o_current->fill_angle2); 00130 00131 /* calc the bounding box */ 00132 o_line_recalc(toplevel, o_current); 00133 00134 /* new_obj->attribute = 0;*/ 00135 00136 /* return the new tail of the object list */ 00137 return new_obj; 00138 } 00139 00162 void o_line_modify(TOPLEVEL *toplevel, OBJECT *object, 00163 int x, int y, int whichone) 00164 { 00165 o_emit_pre_change_notify (toplevel, object); 00166 00167 /* change one of the end of the line */ 00168 switch (whichone) { 00169 case LINE_END1: 00170 object->line->x[0] = x; 00171 object->line->y[0] = y; 00172 break; 00173 00174 case LINE_END2: 00175 object->line->x[1] = x; 00176 object->line->y[1] = y; 00177 break; 00178 00179 default: 00180 return; 00181 } 00182 00183 /* recalculate the bounding box */ 00184 o_line_recalc(toplevel, object); 00185 o_emit_change_notify (toplevel, object); 00186 } 00187 00209 OBJECT *o_line_read (TOPLEVEL *toplevel, const char buf[], 00210 unsigned int release_ver, unsigned int fileformat_ver, GError ** err) 00211 { 00212 OBJECT *new_obj; 00213 char type; 00214 int x1, y1; 00215 int x2, y2; 00216 int line_width, line_space, line_length; 00217 int line_end; 00218 int line_type; 00219 int color; 00220 00221 if (release_ver <= VERSION_20000704) { 00222 /* 00223 * The old geda file format, i.e. releases 20000704 and older, does 00224 * not handle the line type and the filling - here filling is irrelevant. 00225 * They are set to default. 00226 */ 00227 if (sscanf (buf, "%c %d %d %d %d %d\n", &type, 00228 &x1, &y1, &x2, &y2, &color) != 6) { 00229 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse line object")); 00230 return NULL; 00231 } 00232 00233 line_width = 0; 00234 line_end = END_NONE; 00235 line_type = TYPE_SOLID; 00236 line_length= -1; 00237 line_space = -1; 00238 } else { 00239 /* 00240 * The current line format to describe a line is a space separated 00241 * list of characters and numbers in plain ASCII on a single line. 00242 * The meaning of each item is described in the file format documentation. 00243 */ 00244 if (sscanf (buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type, 00245 &x1, &y1, &x2, &y2, &color, 00246 &line_width, &line_end, &line_type, &line_length, &line_space) != 11) { 00247 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse line object")); 00248 return NULL; 00249 } 00250 } 00251 00252 /* 00253 * Null length line are not allowed. If such a line is detected a 00254 * message is issued. 00255 * 00256 * It also checks is the required color is valid. 00257 */ 00258 if (x1 == x2 && y1 == y2) { 00259 s_log_message (_("Found a zero length line [ %c %d %d %d %d %d ]\n"), 00260 type, x1, y1, x2, y2, color); 00261 } 00262 00263 if (color < 0 || color > MAX_COLORS) { 00264 s_log_message (_("Found an invalid color [ %s ]\n"), buf); 00265 s_log_message (_("Setting color to default color\n")); 00266 color = DEFAULT_COLOR; 00267 } 00268 00269 /* 00270 * A line is internally described by its two ends. A new object is 00271 * allocated, initialized and added to the list of objects. Its line 00272 * type is set according to the values of the fields on the line. 00273 */ 00274 /* create and add the line to the list */ 00275 new_obj = o_line_new (toplevel, type, color, x1, y1, x2, y2); 00276 /* set its line options */ 00277 o_set_line_options (toplevel, new_obj, 00278 line_end, line_type, line_width, line_length, 00279 line_space); 00280 /* filling is irrelevant for line, just set to default */ 00281 o_set_fill_options (toplevel, new_obj, 00282 FILLING_HOLLOW, -1, -1, -1, -1, -1); 00283 00284 return new_obj; 00285 } 00286 00302 char *o_line_save(TOPLEVEL *toplevel, OBJECT *object) 00303 { 00304 int x1, x2, y1, y2; 00305 int line_width, line_space, line_length; 00306 char *buf; 00307 OBJECT_END line_end; 00308 OBJECT_TYPE line_type; 00309 00310 /* get the two ends */ 00311 x1 = object->line->x[0]; 00312 y1 = object->line->y[0]; 00313 x2 = object->line->x[1]; 00314 y2 = object->line->y[1]; 00315 00316 /* description of the line type */ 00317 line_width = object->line_width; 00318 line_end = object->line_end; 00319 line_type = object->line_type; 00320 line_length= object->line_length; 00321 line_space = object->line_space; 00322 00323 buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d", object->type, 00324 x1, y1, x2, y2, object->color, 00325 line_width, line_end, line_type, 00326 line_length, line_space); 00327 00328 return(buf); 00329 } 00330 00341 void o_line_translate_world(TOPLEVEL *toplevel, 00342 int dx, int dy, OBJECT *object) 00343 { 00344 /* Update world coords */ 00345 object->line->x[0] = object->line->x[0] + dx; 00346 object->line->y[0] = object->line->y[0] + dy; 00347 object->line->x[1] = object->line->x[1] + dx; 00348 object->line->y[1] = object->line->y[1] + dy; 00349 00350 /* Update bounding box */ 00351 o_line_recalc (toplevel, object); 00352 } 00353 00367 void o_line_rotate_world(TOPLEVEL *toplevel, 00368 int world_centerx, int world_centery, int angle, 00369 OBJECT *object) 00370 { 00371 int newx, newy; 00372 00373 if (angle == 0) 00374 return; 00375 00376 /* angle must be positive */ 00377 if(angle < 0) angle = -angle; 00378 /* angle must be 90 multiple or no rotation performed */ 00379 if((angle % 90) != 0) return; 00380 00381 /* 00382 * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>) 00383 * is translated to the origin. The rotation of the two ends of 00384 * the line is performed. FInally, the rotated line is translated 00385 * back to its previous location. 00386 */ 00387 /* translate object to origin */ 00388 o_line_translate_world(toplevel, -world_centerx, -world_centery, object); 00389 00390 /* rotate line end 1 */ 00391 rotate_point_90(object->line->x[0], object->line->y[0], angle, 00392 &newx, &newy); 00393 00394 object->line->x[0] = newx; 00395 object->line->y[0] = newy; 00396 00397 /* rotate line end 2 */ 00398 rotate_point_90(object->line->x[1], object->line->y[1], angle, 00399 &newx, &newy); 00400 00401 object->line->x[1] = newx; 00402 object->line->y[1] = newy; 00403 00404 /* translate object back to normal position */ 00405 o_line_translate_world(toplevel, world_centerx, world_centery, object); 00406 00407 } 00408 00422 void o_line_mirror_world(TOPLEVEL *toplevel, int world_centerx, 00423 int world_centery, OBJECT *object) 00424 { 00425 /* translate object to origin */ 00426 o_line_translate_world(toplevel, -world_centerx, -world_centery, object); 00427 00428 /* mirror the line ends */ 00429 object->line->x[0] = -object->line->x[0]; 00430 object->line->x[1] = -object->line->x[1]; 00431 00432 /* translate back in position */ 00433 o_line_translate_world(toplevel, world_centerx, world_centery, object); 00434 00435 } 00436 00444 void o_line_recalc(TOPLEVEL *toplevel, OBJECT *o_current) 00445 { 00446 int left, right, top, bottom; 00447 00448 if (o_current->line == NULL) { 00449 return; 00450 } 00451 00452 /* update the bounding box - screen unit */ 00453 world_get_line_bounds(toplevel, o_current, 00454 &left, &top, &right, &bottom); 00455 o_current->w_left = left; 00456 o_current->w_top = top; 00457 o_current->w_right = right; 00458 o_current->w_bottom = bottom; 00459 o_current->w_bounds_valid = TRUE; 00460 } 00461 00475 void world_get_line_bounds(TOPLEVEL *toplevel, OBJECT *object, 00476 int *left, int *top, int *right, int *bottom) 00477 { 00478 int halfwidth; 00479 00480 halfwidth = object->line_width / 2; 00481 00482 *left = min( object->line->x[0], object->line->x[1] ); 00483 *top = min( object->line->y[0], object->line->y[1] ); 00484 *right = max( object->line->x[0], object->line->x[1] ); 00485 *bottom = max( object->line->y[0], object->line->y[1] ); 00486 00487 /* This isn't strictly correct, but a 1st order approximation */ 00488 *left -= halfwidth; 00489 *top -= halfwidth; 00490 *right += halfwidth; 00491 *bottom += halfwidth; 00492 } 00493 00504 gboolean o_line_get_position (TOPLEVEL *toplevel, gint *x, gint *y, 00505 OBJECT *object) 00506 { 00507 *x = object->line->x[0]; 00508 *y = object->line->y[0]; 00509 return TRUE; 00510 } 00511 00512 00528 void o_line_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, 00529 int origin_x, int origin_y) 00530 { 00531 int x1, y1, x2, y2; 00532 int color; 00533 int line_width, length, space; 00534 void (*outl_func)() = NULL; 00535 00536 if (o_current == NULL) { 00537 printf("got null in o_line_print\n"); 00538 return; 00539 } 00540 00541 x1 = o_current->line->x[0]; 00542 y1 = o_current->line->y[0]; 00543 x2 = o_current->line->x[1]; 00544 y2 = o_current->line->y[1]; 00545 color = o_current->color; 00546 00547 /* 00548 * Depending on the type of the line for this particular line, the 00549 * appropriate function is chosen among 00550 * #o_line_print_solid(), #o_line_print_dotted()#, #o_line_print_dashed(), 00551 * #o_line_print_center() and #o_line_print_phantom(). 00552 * 00553 * The needed parameters for each of these types are extracted from the 00554 * <B>o_current</B> object. Depending on the type, unused parameters are 00555 * set to -1. 00556 * 00557 * In the eventuality of a length and/or space null, the line is printed 00558 * solid to avoid and endless loop produced by other functions. 00559 */ 00560 line_width = o_current->line_width; 00561 if(line_width <=2) { 00562 if(toplevel->line_style == THICK) { 00563 line_width=LINE_WIDTH; 00564 } else { 00565 line_width=2; 00566 } 00567 } 00568 00569 length = o_current->line_length; 00570 space = o_current->line_space; 00571 00572 switch(o_current->line_type) { 00573 case(TYPE_SOLID): 00574 length = -1; space = -1; 00575 outl_func = o_line_print_solid; 00576 break; 00577 00578 case(TYPE_DOTTED): 00579 length = -1; 00580 outl_func = o_line_print_dotted; 00581 break; 00582 00583 case(TYPE_DASHED): 00584 outl_func = o_line_print_dashed; 00585 break; 00586 00587 case(TYPE_CENTER): 00588 outl_func = o_line_print_center; 00589 break; 00590 00591 case(TYPE_PHANTOM): 00592 outl_func = o_line_print_phantom; 00593 break; 00594 00595 case(TYPE_ERASE): 00596 /* Unused for now, print it solid */ 00597 length = -1; space = -1; 00598 outl_func = o_line_print_solid; 00599 break; 00600 } 00601 00602 if((length == 0) || (space == 0)) { 00603 length = -1; space = -1; 00604 outl_func = o_line_print_solid; 00605 } 00606 00607 (*outl_func)(toplevel, fp, 00608 x1 - origin_x, y1 - origin_y, 00609 x2 - origin_x, y2 - origin_y, 00610 color, 00611 line_width, length, space, 00612 origin_x, origin_y); 00613 } 00614 00637 void o_line_print_solid(TOPLEVEL *toplevel, FILE *fp, 00638 int x1, int y1, int x2, int y2, 00639 int color, 00640 int line_width, int length, int space, 00641 int origin_x, int origin_y) 00642 { 00643 f_print_set_color(toplevel, fp, color); 00644 00645 fprintf(fp,"%d %d %d %d %d line\n", 00646 x1,y1,x2,y2, line_width); 00647 } 00648 00678 void o_line_print_dotted(TOPLEVEL *toplevel, FILE *fp, 00679 int x1, int y1, int x2, int y2, 00680 int color, 00681 int line_width, int length, int space, 00682 int origin_x, int origin_y) 00683 { 00684 double dx, dy, l, d; 00685 double dx1, dy1; 00686 double xa, ya; 00687 00688 f_print_set_color(toplevel, fp, color); 00689 00690 /* The dotted line command takes an array of dots so print out the 00691 * beginnings of the array 00692 */ 00693 fprintf(fp,"["); 00694 /* is the width relevant for a dot (circle) ? */ 00695 /* f_print_set_line_width(fp, line_width); */ 00696 00697 /* 00698 * Depending on the slope of the line the space parameter is 00699 * projected on each of the two directions x and y resulting 00700 * in <B>dx1</B> and <B>dy1</B>. Starting from one end by increments 00701 * of space the dots are printed. 00702 * 00703 * A dot is represented by a filled circle. Position of the 00704 * circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>line_width</B> 00705 * parameter. 00706 */ 00707 00708 dx = (double) (x2 - x1); 00709 dy = (double) (y2 - y1); 00710 l = sqrt((dx * dx) + (dy * dy)); 00711 00712 dx1 = (dx * space) / l; 00713 dy1 = (dy * space) / l; 00714 00715 d = 0; 00716 xa = x1; ya = y1; 00717 while(d < l) { 00718 00719 fprintf(fp,"[%d %d] ", 00720 (int)xa, (int)ya); 00721 d = d + space; 00722 xa = xa + dx1; 00723 ya = ya + dy1; 00724 } 00725 00726 fprintf(fp,"] %d dashed\n",line_width); 00727 00728 } 00729 00730 00759 void o_line_print_dashed(TOPLEVEL *toplevel, FILE *fp, 00760 int x1, int y1, int x2, int y2, 00761 int color, 00762 int line_width, int length, int space, 00763 int origin_x, int origin_y) 00764 { 00765 double dx, dy, l, d; 00766 double dx1, dy1, dx2, dy2; 00767 double xa, ya, xb, yb; 00768 00769 f_print_set_color(toplevel, fp, color); 00770 00771 /* the dashed line function takes an array of start-finish pairs 00772 * output the beginnings of the array now 00773 */ 00774 fprintf(fp,"["); 00775 00776 /* 00777 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>) 00778 * parameter is projected on each of the two directions x and y 00779 * resulting in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>). 00780 * Starting from one end and incrementing alternatively by <B>space</B> 00781 * and <B>length</B> the dashes are printed. 00782 * 00783 * It prints as many dashes of length <B>length</B> as possible. 00784 */ 00785 dx = (double) (x2 - x1); 00786 dy = (double) (y2 - y1); 00787 l = sqrt((dx * dx) + (dy * dy)); 00788 00789 dx1 = (dx * length) / l; 00790 dy1 = (dy * length) / l; 00791 00792 dx2 = (dx * space) / l; 00793 dy2 = (dy * space) / l; 00794 00795 d = 0; 00796 xa = x1; ya = y1; 00797 while((d + length + space) < l) { 00798 d = d + length; 00799 xb = xa + dx1; 00800 yb = ya + dy1; 00801 00802 fprintf(fp, "[%d %d %d %d] ", 00803 (int) xa, (int) ya, 00804 (int) xb, (int) yb); 00805 00806 d = d + space; 00807 xa = xb + dx2; 00808 ya = yb + dy2; 00809 } 00810 /* 00811 * When the above condition is no more satisfied, then it is not possible 00812 * to print a dash of length <B>length</B>. However it may be possible to 00813 * print the complete dash or a shorter one. 00814 */ 00815 00816 if((d + length) < l) { 00817 d = d + length; 00818 xb = xa + dx1; 00819 yb = ya + dy1; 00820 } else { 00821 xb = x2; 00822 yb = y2; 00823 } 00824 00825 fprintf(fp, "[%d %d %d %d] ", 00826 (int) xa, (int) ya, 00827 (int) xb, (int) yb); 00828 00829 fprintf(fp,"] %d dashed\n", line_width); 00830 } 00831 00832 00862 void o_line_print_center(TOPLEVEL *toplevel, FILE *fp, 00863 int x1, int y1, int x2, int y2, 00864 int color, 00865 int line_width, int length, int space, 00866 int origin_x, int origin_y) 00867 { 00868 double dx, dy, l, d; 00869 double dx1, dy1, dx2, dy2; 00870 double xa, ya, xb, yb; 00871 00872 f_print_set_color(toplevel, fp, color); 00873 00874 fprintf(fp, "["); 00875 00876 /* 00877 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>) 00878 * parameter is projected on each of the two directions x and y resulting 00879 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>). 00880 * Starting from one end and incrementing alternatively by <B>space</B> 00881 * and <B>length</B> the dashes and dots are printed. 00882 * 00883 * It prints as many sets of dash and dot as possible. 00884 */ 00885 dx = (double) (x2 - x1); 00886 dy = (double) (y2 - y1); 00887 l = sqrt((dx * dx) + (dy * dy)); 00888 00889 dx1 = (dx * length) / l; 00890 dy1 = (dy * length) / l; 00891 00892 dx2 = (dx * space) / l; 00893 dy2 = (dy * space) / l; 00894 00895 d = 0; 00896 xa = x1; ya = y1; 00897 while((d + length + 2 * space) < l) { 00898 d = d + length; 00899 xb = xa + dx1; 00900 yb = ya + dy1; 00901 00902 fprintf(fp, "[%d %d %d %d] ", 00903 (int) xa, (int) ya, 00904 (int) xb, (int) yb); 00905 00906 d = d + space; 00907 xa = xb + dx2; 00908 ya = yb + dy2; 00909 00910 fprintf(fp,"[%d %d] ",(int) xa, (int) ya); 00911 00912 d = d + space; 00913 xa = xa + dx2; 00914 ya = ya + dy2; 00915 } 00916 /* 00917 * When the above condition is no more satisfied, then it is not possible 00918 * to print a dash of length <B>length</B>. 00919 * However two cases are possible : 00920 * <DL> 00921 * <DT>*</DT><DD>it is possible to print the dash and the dot. 00922 * <DT>*</DT><DD>it is possible to print the dash or a part 00923 * of the original dash. 00924 * </DL> 00925 */ 00926 00927 if((d + length + space) < l) { 00928 d = d + length; 00929 xb = xa + dx1; 00930 yb = ya + dy1; 00931 00932 fprintf(fp, "[%d %d %d %d] ", 00933 (int) xa, (int) ya, 00934 (int) xb, (int) yb); 00935 00936 d = d + space; 00937 xa = xb + dx2; 00938 ya = yb + dy2; 00939 00940 fprintf(fp,"[%d %d] ",(int) xa, (int) ya); 00941 00942 } else { 00943 if(d + length < l) { 00944 xb = xa + dx1; 00945 yb = ya + dy1; 00946 } else { 00947 xb = x2; 00948 yb = y2; 00949 } 00950 00951 fprintf(fp, "[%d %d %d %d] ", 00952 (int) xa, (int) ya, 00953 (int) xb, (int) yb); 00954 00955 } 00956 00957 fprintf(fp,"] %d dashed\n", line_width); 00958 00959 /* 00960 * A dot is represented by a filled circle. Position of the circle is 00961 * (<B>xa</B>, <B>ya</B>) and its radius by the <B>line_width</B> parameter. 00962 */ 00963 } 00964 00994 void o_line_print_phantom(TOPLEVEL *toplevel, FILE *fp, 00995 int x1, int y1, int x2, int y2, 00996 int color, 00997 int line_width, int length, int space, 00998 int origin_x, int origin_y) 00999 { 01000 double dx, dy, l, d; 01001 double dx1, dy1, dx2, dy2; 01002 double xa, ya, xb, yb; 01003 01004 f_print_set_color(toplevel, fp, color); 01005 01006 fprintf(fp,"["); 01007 01008 /* 01009 * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>) 01010 * parameter is projected on each of the two directions x and y resulting 01011 * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>). 01012 * Starting from one end and incrementing alternatively by <B>space</B> 01013 * and <B>length</B> the dashes and dots are printed. 01014 * 01015 * It prints as many sets of dash-dot-dot as possible. 01016 */ 01017 dx = (double) (x2 - x1); 01018 dy = (double) (y2 - y1); 01019 l = sqrt((dx * dx) + (dy * dy)); 01020 01021 dx1 = (dx * length) / l; 01022 dy1 = (dy * length) / l; 01023 01024 dx2 = (dx * space) / l; 01025 dy2 = (dy * space) / l; 01026 01027 d = 0; 01028 xa = x1; ya = y1; 01029 while((d + length + 3 * space) < l) { 01030 d = d + length; 01031 xb = xa + dx1; 01032 yb = ya + dy1; 01033 01034 fprintf(fp,"[%d %d %d %d] ", 01035 (int) xa, (int)ya, 01036 (int) xb, (int)yb); 01037 01038 d = d + space; 01039 xa = xb + dx2; 01040 ya = yb + dy2; 01041 01042 fprintf(fp,"[%d %d] ",(int) xa, (int) ya); 01043 01044 d = d + space; 01045 xa = xa + dx2; 01046 ya = ya + dy2; 01047 01048 fprintf(fp,"[%d %d] ",(int) xa, (int) ya); 01049 01050 d = d + space; 01051 xa = xa + dx2; 01052 ya = ya + dy2; 01053 } 01054 /* 01055 * When the above condition is no more satisfied, then it is not possible 01056 * to print a complete set of dash-dot-dot. 01057 * However three cases are possible : 01058 * <DL> 01059 * <DT>*</DT><DD>it is possible to print a dash and a dot and a dot. 01060 * <DT>*</DT><DD>it is possible to print a dash and a dot. 01061 * <DT>*</DT><DD>it is possible to print the dash or a part 01062 * of the original dash. 01063 * </DL> 01064 */ 01065 01066 if((d + length + 2 * space) < l) { 01067 d = d + length; 01068 xb = xa + dx1; 01069 yb = ya + dy1; 01070 01071 fprintf(fp,"[%d %d %d %d] ", 01072 (int) xa, (int)ya, 01073 (int) xb, (int)yb); 01074 01075 d = d + space; 01076 xa = xb + dx2; 01077 ya = yb + dy2; 01078 01079 fprintf(fp,"[%d %d] ",(int) xa, (int)ya); 01080 01081 d = d + space; 01082 xa = xb + dx2; 01083 ya = yb + dy2; 01084 01085 fprintf(fp,"[%d %d] ",(int) xa, (int)ya); 01086 01087 } else { 01088 if(d + length + space < l) { 01089 d = d + length; 01090 xb = xa + dx1; 01091 yb = ya + dy1; 01092 01093 fprintf(fp,"[%d %d %d %d] ", 01094 (int) xa, (int)ya, 01095 (int) xb, (int)yb); 01096 01097 d = d + space; 01098 xa = xb + dx2; 01099 ya = yb + dy2; 01100 01101 fprintf(fp,"[%d %d] ",(int) xa, (int)ya); 01102 01103 } else { 01104 if(d + length < l) { 01105 xb = xa + dx1; 01106 yb = ya + dy1; 01107 } else { 01108 xb = x2; 01109 yb = y2; 01110 } 01111 01112 fprintf(fp,"[%d %d %d %d] ", 01113 (int) xa, (int)ya, 01114 (int) xb, (int)yb); 01115 01116 } 01117 } 01118 01119 fprintf(fp,"] %d dashed\n", line_width); 01120 } 01121 01122 01131 void o_line_scale_world(TOPLEVEL *toplevel, int x_scale, int y_scale, 01132 OBJECT *object) 01133 { 01134 /* scale the line world coords */ 01135 object->line->x[0] = object->line->x[0] * x_scale; 01136 object->line->y[0] = object->line->y[0] * y_scale; 01137 object->line->x[1] = object->line->x[1] * x_scale; 01138 object->line->y[1] = object->line->y[1] * y_scale; 01139 01140 /* update boundingbox */ 01141 o_line_recalc(toplevel, object); 01142 01143 } 01144 01145 01153 double o_line_length(OBJECT *object) 01154 { 01155 double length; 01156 double dx, dy; 01157 01158 if (!object->line) { 01159 return 0.0; 01160 } 01161 01162 dx = object->line->x[0]-object->line->x[1]; 01163 dy = object->line->y[0]-object->line->y[1]; 01164 01165 length = sqrt((dx*dx) + (dy*dy)); 01166 01167 return(length); 01168 } 01169 01187 double o_line_shortest_distance (OBJECT *object, int x, int y, int force_solid) 01188 { 01189 return m_line_shortest_distance (object->line, x, y); 01190 } 01191