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 #include <config.h> 00021 00022 #include <stdio.h> 00023 #include <math.h> 00024 00025 #include "libgeda_priv.h" 00026 00027 #ifdef HAVE_LIBDMALLOC 00028 #include <dmalloc.h> 00029 #endif 00030 00046 void world_get_pin_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, 00047 int *right, int *bottom) 00048 { 00049 world_get_line_bounds( toplevel, object, left, top, right, bottom ); 00050 } 00051 00062 gboolean o_pin_get_position (TOPLEVEL *toplevel, gint *x, gint *y, 00063 OBJECT *object) 00064 { 00065 *x = object->line->x[object->whichend]; 00066 *y = object->line->y[object->whichend]; 00067 return TRUE; 00068 } 00069 00085 OBJECT *o_pin_new(TOPLEVEL *toplevel, 00086 char type, int color, 00087 int x1, int y1, int x2, int y2, int pin_type, int whichend) 00088 { 00089 OBJECT *new_node; 00090 00091 new_node = s_basic_new_object(type, "pin"); 00092 new_node->color = color; 00093 00094 new_node->line = (LINE *) g_malloc(sizeof(LINE)); 00095 00096 new_node->line->x[0] = x1; 00097 new_node->line->y[0] = y1; 00098 new_node->line->x[1] = x2; 00099 new_node->line->y[1] = y2; 00100 00101 o_pin_set_type (toplevel, new_node, pin_type); 00102 00103 o_pin_recalc (toplevel, new_node); 00104 00105 new_node->whichend = whichend; 00106 00107 return new_node; 00108 } 00109 00118 void o_pin_recalc(TOPLEVEL *toplevel, OBJECT *o_current) 00119 { 00120 int left, right, top, bottom; 00121 00122 if (o_current->line == NULL) { 00123 return; 00124 } 00125 00126 world_get_pin_bounds(toplevel, o_current, &left, &top, &right, &bottom); 00127 00128 o_current->w_left = left; 00129 o_current->w_top = top; 00130 o_current->w_right = right; 00131 o_current->w_bottom = bottom; 00132 o_current->w_bounds_valid = TRUE; 00133 } 00134 00147 OBJECT *o_pin_read (TOPLEVEL *toplevel, const char buf[], 00148 unsigned int release_ver, unsigned int fileformat_ver, GError **err) 00149 { 00150 OBJECT *new_obj; 00151 char type; 00152 int x1, y1; 00153 int x2, y2; 00154 int color; 00155 int pin_type; 00156 int whichend; 00157 00158 if (release_ver <= VERSION_20020825) { 00159 if (sscanf (buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color) != 6) { 00160 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse pin object")); 00161 return NULL; 00162 } 00163 pin_type = PIN_TYPE_NET; 00164 whichend = -1; 00165 } else { 00166 if (sscanf (buf, "%c %d %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, 00167 &color, &pin_type, &whichend) != 8) { 00168 g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse pin object")); 00169 return NULL; 00170 } 00171 } 00172 00173 if (whichend == -1) { 00174 s_log_message (_("Found a pin which did not have the whichone field set.\n" 00175 "Verify and correct manually.\n")); 00176 } else if (whichend < -1 || whichend > 1) { 00177 s_log_message (_("Found an invalid whichend on a pin (reseting to zero): %d\n"), 00178 whichend); 00179 whichend = 0; 00180 } 00181 00182 if (color < 0 || color > MAX_COLORS) { 00183 s_log_message (_("Found an invalid color [ %s ]\n"), buf); 00184 s_log_message (_("Setting color to default color\n")); 00185 color = DEFAULT_COLOR; 00186 } 00187 00188 if (toplevel->override_pin_color != -1) { 00189 color = toplevel->override_pin_color; 00190 } 00191 00192 new_obj = o_pin_new (toplevel, type, color, x1, y1, x2, y2, 00193 pin_type, whichend); 00194 00195 return new_obj; 00196 } 00197 00207 char *o_pin_save(TOPLEVEL *toplevel, OBJECT *object) 00208 { 00209 int x1, x2, y1, y2; 00210 int pin_type, whichend; 00211 char *buf; 00212 00213 x1 = object->line->x[0]; 00214 y1 = object->line->y[0]; 00215 x2 = object->line->x[1]; 00216 y2 = object->line->y[1]; 00217 00218 pin_type = object->pin_type; 00219 whichend = object->whichend; 00220 00221 buf = g_strdup_printf("%c %d %d %d %d %d %d %d", object->type, 00222 x1, y1, x2, y2, object->color, pin_type, whichend); 00223 return(buf); 00224 } 00225 00235 void o_pin_translate_world(TOPLEVEL *toplevel, int dx, int dy, OBJECT *object) 00236 { 00237 /* Update world coords */ 00238 object->line->x[0] = object->line->x[0] + dx; 00239 object->line->y[0] = object->line->y[0] + dy; 00240 object->line->x[1] = object->line->x[1] + dx; 00241 object->line->y[1] = object->line->y[1] + dy; 00242 00243 /* Update bounding box */ 00244 o_pin_recalc (toplevel, object); 00245 00246 s_tile_update_object(toplevel, object); 00247 } 00248 00257 OBJECT *o_pin_copy(TOPLEVEL *toplevel, OBJECT *o_current) 00258 { 00259 OBJECT *new_obj; 00260 00261 new_obj = o_pin_new (toplevel, OBJ_PIN, o_current->color, 00262 o_current->line->x[0], o_current->line->y[0], 00263 o_current->line->x[1], o_current->line->y[1], 00264 o_current->pin_type, o_current->whichend); 00265 00266 return new_obj; 00267 } 00268 00280 void o_pin_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, 00281 int origin_x, int origin_y) 00282 { 00283 int pin_width; 00284 int x1, y1; 00285 int x2, y2; 00286 00287 if (o_current == NULL) { 00288 printf("got null in o_pin_print\n"); 00289 return; 00290 } 00291 00292 f_print_set_color(toplevel, fp, o_current->color); 00293 00294 x1 = o_current->line->x[0] - origin_x; 00295 y1 = o_current->line->y[0] - origin_y; 00296 x2 = o_current->line->x[1] - origin_x; 00297 y2 = o_current->line->y[1] - origin_y; 00298 pin_width = 2; 00299 if(toplevel->pin_style == THICK) { 00300 pin_width = o_current->line_width; 00301 } 00302 00303 fprintf(fp, "%d %d %d %d %d line\n",x1,y1,x2,y2,pin_width); 00304 00305 } 00306 00319 void o_pin_rotate_world(TOPLEVEL *toplevel, int world_centerx, 00320 int world_centery, int angle, 00321 OBJECT *object) 00322 { 00323 int newx, newy; 00324 00325 if (angle == 0) 00326 return; 00327 00328 /* translate object to origin */ 00329 o_pin_translate_world(toplevel, -world_centerx, -world_centery, object); 00330 00331 rotate_point_90(object->line->x[0], object->line->y[0], angle, 00332 &newx, &newy); 00333 00334 object->line->x[0] = newx; 00335 object->line->y[0] = newy; 00336 00337 rotate_point_90(object->line->x[1], object->line->y[1], angle, 00338 &newx, &newy); 00339 00340 object->line->x[1] = newx; 00341 object->line->y[1] = newy; 00342 00343 o_pin_translate_world(toplevel, world_centerx, world_centery, object); 00344 } 00345 00356 void o_pin_mirror_world(TOPLEVEL *toplevel, 00357 int world_centerx, int world_centery, OBJECT *object) 00358 { 00359 /* translate object to origin */ 00360 o_pin_translate_world(toplevel, -world_centerx, -world_centery, object); 00361 00362 object->line->x[0] = -object->line->x[0]; 00363 00364 object->line->x[1] = -object->line->x[1]; 00365 00366 o_pin_translate_world(toplevel, world_centerx, world_centery, object); 00367 } 00368 00382 void o_pin_modify(TOPLEVEL *toplevel, OBJECT *object, 00383 int x, int y, int whichone) 00384 { 00385 object->line->x[whichone] = x; 00386 object->line->y[whichone] = y; 00387 00388 o_pin_recalc (toplevel, object); 00389 00390 s_tile_update_object(toplevel, object); 00391 } 00392 00407 void o_pin_update_whichend(TOPLEVEL *toplevel, 00408 GList *object_list, int num_pins) 00409 { 00410 OBJECT *o_current; 00411 GList *iter; 00412 int top = 0, left = 0; 00413 int right = 0, bottom = 0; 00414 int d1, d2, d3, d4; 00415 int min0, min1; 00416 int min0_whichend, min1_whichend; 00417 int rleft, rtop, rright, rbottom; 00418 int found; 00419 00420 if (object_list && num_pins) { 00421 if (num_pins == 1 || toplevel->force_boundingbox) { 00422 world_get_object_glist_bounds (toplevel, object_list, 00423 &left, &top, &right, &bottom); 00424 } else { 00425 found = 0; 00426 00427 /* only look at the pins to calculate bounds of the symbol */ 00428 iter = object_list; 00429 while (iter != NULL) { 00430 o_current = (OBJECT *)iter->data; 00431 if (o_current->type == OBJ_PIN) { 00432 rleft = o_current->w_left; 00433 rtop = o_current->w_top; 00434 rright = o_current->w_right; 00435 rbottom = o_current->w_bottom; 00436 00437 if ( found ) { 00438 left = min( left, rleft ); 00439 top = min( top, rtop ); 00440 right = max( right, rright ); 00441 bottom = max( bottom, rbottom ); 00442 } else { 00443 left = rleft; 00444 top = rtop; 00445 right = rright; 00446 bottom = rbottom; 00447 found = 1; 00448 } 00449 } 00450 iter = g_list_next (iter); 00451 } 00452 00453 } 00454 } else { 00455 return; 00456 } 00457 00458 iter = object_list; 00459 while (iter != NULL) { 00460 o_current = (OBJECT *)iter->data; 00461 /* Determine which end of the pin is on or nearest the boundary */ 00462 if (o_current->type == OBJ_PIN && o_current->whichend == -1) { 00463 if (o_current->line->y[0] == o_current->line->y[1]) { 00464 /* horizontal */ 00465 00466 if (o_current->line->x[0] == left) { 00467 o_current->whichend = 0; 00468 } else if (o_current->line->x[1] == left) { 00469 o_current->whichend = 1; 00470 } else if (o_current->line->x[0] == right) { 00471 o_current->whichend = 0; 00472 } else if (o_current->line->x[1] == right) { 00473 o_current->whichend = 1; 00474 } else { 00475 00476 d1 = abs(o_current->line->x[0] - left); 00477 d2 = abs(o_current->line->x[1] - left); 00478 d3 = abs(o_current->line->x[0] - right); 00479 d4 = abs(o_current->line->x[1] - right); 00480 00481 if (d1 <= d2) { 00482 min0 = d1; 00483 min0_whichend = 0; 00484 } else { 00485 min0 = d2; 00486 min0_whichend = 1; 00487 } 00488 00489 if (d3 <= d4) { 00490 min1 = d3; 00491 min1_whichend = 0; 00492 } else { 00493 min1 = d4; 00494 min1_whichend = 1; 00495 } 00496 00497 if (min0 <= min1) { 00498 o_current->whichend = min0_whichend; 00499 } else { 00500 o_current->whichend = min1_whichend; 00501 } 00502 } 00503 00504 } else if (o_current->line->x[0] == o_current->line->x[1]) { 00505 /* vertical */ 00506 00507 if (o_current->line->y[0] == top) { 00508 o_current->whichend = 0; 00509 } else if (o_current->line->y[1] == top) { 00510 o_current->whichend = 1; 00511 } else if (o_current->line->x[0] == bottom) { 00512 o_current->whichend = 0; 00513 } else if (o_current->line->x[1] == bottom) { 00514 o_current->whichend = 1; 00515 } else { 00516 00517 d1 = abs(o_current->line->y[0] - top); 00518 d2 = abs(o_current->line->y[1] - top); 00519 d3 = abs(o_current->line->y[0] - bottom); 00520 d4 = abs(o_current->line->y[1] - bottom); 00521 00522 if (d1 <= d2) { 00523 min0 = d1; 00524 min0_whichend = 0; 00525 } else { 00526 min0 = d2; 00527 min0_whichend = 1; 00528 } 00529 00530 if (d3 <= d4) { 00531 min1 = d3; 00532 min1_whichend = 0; 00533 } else { 00534 min1 = d4; 00535 min1_whichend = 1; 00536 } 00537 00538 if (min0 <= min1) { 00539 o_current->whichend = min0_whichend; 00540 } else { 00541 o_current->whichend = min1_whichend; 00542 } 00543 } 00544 } 00545 } 00546 iter = g_list_next (iter); 00547 } 00548 } 00549 00550 00560 void o_pin_set_type (TOPLEVEL *toplevel, OBJECT *o_current, int pin_type) 00561 { 00562 o_emit_pre_change_notify (toplevel, o_current); 00563 switch (pin_type) { 00564 default: 00565 g_critical ("o_pin_set_type: Got invalid pin type %i\n", pin_type); 00566 /* Fall through */ 00567 case PIN_TYPE_NET: 00568 o_current->line_width = PIN_WIDTH_NET; 00569 o_current->pin_type = PIN_TYPE_NET; 00570 break; 00571 case PIN_TYPE_BUS: 00572 o_current->line_width = PIN_WIDTH_BUS; 00573 o_current->pin_type = PIN_TYPE_BUS; 00574 break; 00575 } 00576 o_emit_change_notify (toplevel, o_current); 00577 }