libgeda

o_pin_basic.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * libgeda - gEDA's library
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <math.h>
00024 
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines