pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00051 #ifdef HAVE_CONFIG_H 00052 #include "config.h" 00053 #endif 00054 00055 #include <stdio.h> 00056 #include <stdarg.h> 00057 #include <stdlib.h> 00058 #include <string.h> 00059 #include <assert.h> 00060 00061 #include <time.h> 00062 00063 #include "global.h" 00064 #include "error.h" /* Message() */ 00065 #include "data.h" 00066 #include "misc.h" 00067 #include "rats.h" 00068 #include "find.h" 00069 00070 #include "hid.h" 00071 #include "hid_draw.h" 00072 #include "../hidint.h" 00073 #include "hid/common/hidnogui.h" 00074 #include "hid/common/draw_helpers.h" 00075 00076 #include <gd.h> 00077 #include "xmlout.h" 00078 00079 #include "hid/common/hidinit.h" 00080 #include "pcb-printf.h" 00081 00082 #ifdef HAVE_LIBDMALLOC 00083 #include <dmalloc.h> 00084 #endif 00085 00086 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented PNG function %s.\n", __FUNCTION__); abort() 00087 #define MAXREFPINS 32 /* max length of following list */ 00088 static char *reference_pin_names[] = {"1", "2", "A1", "A2", "B1", "B2", 0}; 00089 00090 /* Needed for PNG export */ 00091 00092 struct color_struct { 00093 /* the descriptor used by the gd library */ 00094 int c; 00095 /* so I can figure out what rgb value c refers to */ 00096 unsigned int r, g, b; 00097 }; 00098 00099 struct hid_gc_struct { 00100 HID *me_pointer; 00101 EndCapStyle cap; 00102 Coord width; 00103 unsigned char r, g, b; 00104 int erase; 00105 struct color_struct *color; 00106 gdImagePtr brush; 00107 }; 00108 00109 struct gsvit_net_layer { 00110 GList *Line; 00111 GList *Arc; 00112 GList *Polygon; 00113 }; 00114 00115 struct gsvit_netlist { 00116 char* name; 00117 GList *Pin; 00118 GList *Via; 00119 GList *Pad; 00120 struct gsvit_net_layer layer[MAX_LAYER]; 00121 struct color_struct color; 00122 int colorIndex; 00123 }; 00124 00125 00129 struct drill_hole 00130 { 00131 int cx; 00132 int cy; 00133 int is_plated; 00134 }; 00135 00139 struct single_size_drills 00140 { 00141 double diameter_inches; 00142 Coord radius; 00143 int n_holes; 00144 int n_holes_allocated; 00145 struct drill_hole* holes; 00146 }; 00147 static struct single_size_drills* drills = NULL; 00148 00149 typedef struct _StringList 00150 { 00151 char *str; 00152 struct _StringList *next; 00153 } StringList; 00154 00155 typedef struct _BomList 00156 { 00157 char *descr; 00158 char *value; 00159 int num; 00160 StringList *refdes; 00161 struct _BomList *next; 00162 } BomList; 00163 00164 static int n_drills = 0; 00166 static int n_drills_allocated = 0; 00167 00168 static int save_drill = 0; 00169 00170 static int is_plated = 0; 00171 00172 struct gsvit_netlist* gsvit_netlist = NULL; 00173 00174 int hashColor = gdBrushed; 00175 00176 static struct color_struct* color_array[0x100]; 00177 00178 static HID gsvit_hid; 00179 00180 static HID_DRAW gsvit_graphics; 00181 00182 static struct color_struct *black = NULL, *white = NULL; 00183 00184 static Coord linewidth = -1; 00185 00186 static gdImagePtr lastbrush = (gdImagePtr)((void *) -1); 00187 00191 static gdImagePtr gsvit_im = NULL; 00192 00196 static FILE *gsvit_f = NULL; 00197 00198 static int is_mask; 00199 00200 static int is_drill; 00201 00207 static int gsvit_export_group[MAX_GROUP]; 00208 00212 static int gsvit_cur_group; 00213 00217 static const char *gsvit_basename = NULL; 00218 00222 static int gsvit_dpi = -1; 00223 00224 HID_Attribute gsvit_attribute_list[] = { 00225 /* other HIDs expect this to be first. */ 00226 00227 /* %start-doc options "96 gsvit Options" 00228 @ftable @code 00229 @item -- basename <string> 00230 File name prefix. 00231 @end ftable 00232 %end-doc 00233 */ 00234 {"basename", "File name prefix", 00235 HID_String, 0, 0, {0, 0, 0}, 0, 0}, 00236 #define HA_basename 0 00237 00238 /* %start-doc options "96 gsvit Options" 00239 @ftable @code 00240 @item --dpi <num> 00241 Horizontal scale factor (grid points/inch). 00242 @end ftable 00243 %end-doc 00244 */ 00245 {"dpi", "Horizontal scale factor (grid points/inch)", 00246 HID_Integer, 0, 1000, {1000, 0, 0}, 0, 0}, /* 1000 --> 1 mil (25.4 um) resolution */ 00247 #define HA_dpi 1 00248 00249 }; 00250 00251 #define NUM_OPTIONS (sizeof (gsvit_attribute_list) / sizeof (gsvit_attribute_list[0])) 00252 00253 REGISTER_ATTRIBUTES(gsvit_attribute_list) 00254 static HID_Attr_Val gsvit_values[NUM_OPTIONS]; 00255 00256 void gsvit_create_netlist (void); 00257 void gsvit_destroy_netlist (void); 00258 static void gsvit_xml_out (char* gsvit_basename); 00259 static void gsvit_build_net_from_selected (struct gsvit_netlist* currNet); 00260 static void gsvit_fill_rect (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2); 00261 static void gsvit_write_xnets (void); 00262 00263 00282 char * 00283 hslToRgb (int h, uint8_t s, uint8_t l) 00284 { 00285 static char rgb[3]; 00286 float H = fmod ((float)(h), 360.0); 00287 float S = s; 00288 float L = l; 00289 00290 int sect; 00291 float C, X; 00292 float m; 00293 float Rp, Gp, Bp; 00294 00295 L /= 255.0; 00296 S /= 255.0; 00297 sect = h / 60; 00298 00299 C = (1.0 - fabs (2 * L - 1.0)) * S; 00300 X = C * (1.0 - fabs (fmod ((H / 60.0), 2.0) - 1.0)); 00301 m = L - C / 2.0; 00302 00303 switch (sect) 00304 { 00305 case 0: 00306 Rp = C; 00307 Gp = X; 00308 Bp = 0.0; 00309 break; 00310 case 1: 00311 Rp = X; 00312 Gp = C; 00313 Bp = 0.0; 00314 break; 00315 case 2: 00316 Rp = 0.0; 00317 Gp = C; 00318 Bp = X; 00319 break; 00320 case 3: 00321 Rp = 0.0; 00322 Gp = X; 00323 Bp = C; 00324 break; 00325 case 4: 00326 Rp = X; 00327 Gp = 0.0; 00328 Bp = C; 00329 break; 00330 case 5: 00331 Rp = C; 00332 Gp = 0.0; 00333 Bp = X; 00334 break; 00335 default: 00336 Rp = 0.0; 00337 Gp = 0.0; 00338 Bp = 0.0; 00339 break; 00340 } 00341 00342 rgb[0] = (Rp + m) * 0xFF; 00343 rgb[1] = (Gp + m) * 0xFF; 00344 rgb[2] = (Bp + m) * 0xFF; 00345 00346 return (rgb); 00347 } 00348 00349 00350 void 00351 gsvit_build_net_from_selected (struct gsvit_netlist* currNet) 00352 { 00353 COPPERLINE_LOOP (PCB->Data); 00354 { 00355 if (TEST_FLAG (SELECTEDFLAG, line)) 00356 { 00357 currNet->layer[l].Line = g_list_prepend(currNet->layer[l].Line, line); 00358 } 00359 } 00360 ENDALL_LOOP; 00361 00362 COPPERARC_LOOP (PCB->Data); 00363 { 00364 if (TEST_FLAG (SELECTEDFLAG, arc)) 00365 { 00366 currNet->layer[l].Arc = g_list_prepend (currNet->layer[l].Arc, arc); 00367 } 00368 } 00369 ENDALL_LOOP; 00370 00371 COPPERPOLYGON_LOOP (PCB->Data); 00372 { 00373 if (TEST_FLAG (SELECTEDFLAG, polygon)) 00374 { 00375 currNet->layer[l].Polygon = g_list_prepend (currNet->layer[l].Polygon, polygon); 00376 } 00377 } 00378 ENDALL_LOOP; 00379 00380 ALLPAD_LOOP (PCB->Data); 00381 { 00382 if (TEST_FLAG (SELECTEDFLAG, pad)) 00383 { 00384 currNet->Pad = g_list_prepend (currNet->Pad, pad); 00385 } 00386 } 00387 ENDALL_LOOP; 00388 00389 ALLPIN_LOOP (PCB->Data); 00390 { 00391 if (TEST_FLAG (SELECTEDFLAG, pin)) 00392 { 00393 currNet->Pin = g_list_prepend (currNet->Pin, pin); 00394 } 00395 } 00396 ENDALL_LOOP; 00397 00398 VIA_LOOP (PCB->Data); 00399 { 00400 if (TEST_FLAG (SELECTEDFLAG, via)) 00401 { 00402 currNet->Via = g_list_prepend(currNet->Via, via); 00403 } 00404 } 00405 END_LOOP; 00406 } 00407 00408 00409 void 00410 gsvit_create_netlist (void) 00411 { 00412 int i; 00413 int numNets = PCB->NetlistLib.MenuN; 00414 gsvit_netlist = (struct gsvit_netlist*) malloc (sizeof (struct gsvit_netlist) * numNets); 00415 memset (gsvit_netlist, 0, sizeof (struct gsvit_netlist) * numNets); 00416 00417 for (i = 0; i < numNets; i++) 00418 { /* For each net in the netlist. */ 00419 int j; 00420 LibraryEntryType* entry; 00421 ConnectionType conn; 00422 00423 struct gsvit_netlist* currNet = &gsvit_netlist[i]; 00424 currNet->name = PCB->NetlistLib.Menu[i].Name + 2; 00427 InitConnectionLookup (); 00428 ClearFlagOnAllObjects (false, FOUNDFLAG | SELECTEDFLAG); 00429 for (j = PCB->NetlistLib.Menu[i].EntryN, entry = PCB->NetlistLib.Menu[i].Entry; j; j--, entry++) 00430 { /* For each component (pin/pad) in the net. */ 00431 if (SeekPad(entry, &conn, false)) 00432 { 00433 RatFindHook(conn.type, conn.ptr1, conn.ptr2, conn.ptr2, false, SELECTEDFLAG, false); 00434 } 00435 } 00436 /* The conn should now contain a list of all elements that are part 00437 * of the net. 00438 * Now build a database of all things selected as part of this net. 00439 */ 00440 gsvit_build_net_from_selected (currNet); 00441 00442 ClearFlagOnAllObjects (false, FOUNDFLAG | SELECTEDFLAG); 00443 FreeConnectionLookupMemory (); 00444 } 00445 00446 /* Assign colors to nets. */ 00447 for (i = 0; i < numNets; i++) 00448 { 00449 char *rgb = NULL; 00450 char name[0x100]; 00451 int j; 00452 int phase = (360 * i) / numNets; 00453 00454 for (j = 0; gsvit_netlist[i].name[j]; j++) 00455 { 00456 name[j] = tolower (gsvit_netlist[i].name[j]); 00457 } 00458 00459 name[j] = 0; 00461 if (strstr (name, "gnd") || strstr (name, "ground")) 00462 { /* Make gnd nets darker. */ 00463 rgb = hslToRgb (phase, (70 * 256) / 100, (20 * 256) / 100); 00464 } 00465 else if (strstr (name, "unnamed")) 00466 {/* Make unnamed nets grayer. */ 00467 rgb = hslToRgb (phase, (15 * 256) / 100, (40 * 256) / 100); 00468 } 00469 else 00470 rgb = hslToRgb (phase, (70 * 256) / 100, (50 * 256) / 100); 00471 00472 gsvit_netlist[i].color.r = rgb[0]; 00473 gsvit_netlist[i].color.g = rgb[1]; 00474 gsvit_netlist[i].color.b = rgb[2]; 00475 } 00476 } 00477 00478 00479 void 00480 gsvit_destroy_netlist (void) 00481 { 00482 int i; 00483 for (i = 0; i < PCB->NetlistLib.MenuN; i++) 00484 { /* For each net in the netlist. */ 00485 struct gsvit_netlist* currNet = &gsvit_netlist[i]; 00486 int j; 00487 for (j = 0; j < MAX_LAYER; j++) 00488 { 00489 g_list_free (currNet->layer[j].Line); 00490 g_list_free (currNet->layer[j].Arc); 00491 g_list_free (currNet->layer[j].Polygon); 00492 } 00493 g_list_free (currNet->Pad); 00494 g_list_free (currNet->Pin); 00495 g_list_free (currNet->Via); 00496 } 00497 free (gsvit_netlist); 00498 } 00499 00500 00504 static int 00505 pcb_to_gsvit (Coord pcb) 00506 { 00507 return COORD_TO_INCH (pcb) * gsvit_dpi; 00508 } 00509 00510 00511 static char * 00512 gsvit_get_png_name (const char *basename, const char *suffix) 00513 { 00514 char *buf; 00515 int len; 00516 00517 len = strlen (basename) + strlen(suffix) + 6; 00518 buf = (char *) malloc (sizeof (*buf) * len); 00519 00520 sprintf (buf, "%s.%s.png", basename, suffix); 00521 00522 return buf; 00523 } 00524 00525 00526 static void 00527 gsvit_write_xspace (void) 00528 { 00529 double xh; 00530 uint32_t h; 00531 uint32_t w; 00532 char buff[0x100]; 00533 int i, idx; 00534 const char *ext; 00535 char *src; 00536 00537 xh = (1000.0* 2.54e-2) / ((double) gsvit_dpi); /* Units are in mm. */ 00538 h = (uint32_t) pcb_to_gsvit (PCB->MaxHeight); /* Units are in counts. */ 00539 w = (uint32_t) pcb_to_gsvit (PCB->MaxWidth); 00540 00541 sprintf (buff, "%f", xh); 00542 XOUT_ELEMENT_START ("space"); 00543 XOUT_INDENT (); 00544 XOUT_NEWLINE (); 00545 XOUT_ELEMENT ("comment", "***** Space *****"); 00546 XOUT_NEWLINE (); 00547 00548 XOUT_ELEMENT_ATTR ("resolution", "units", "mm", buff); 00549 XOUT_NEWLINE (); 00550 00551 sprintf (buff, "%d", w); 00552 XOUT_ELEMENT ("width", buff); 00553 XOUT_NEWLINE (); 00554 sprintf (buff, "%d", h); 00555 XOUT_ELEMENT ("height", buff); 00556 XOUT_NEWLINE (); 00557 XOUT_ELEMENT_START ("layers"); 00558 XOUT_INDENT (); 00559 for (i = 0; i < MAX_GROUP; i++) 00560 if (gsvit_export_group[i]) { 00561 idx = (i >= 0 && i < max_group) ? PCB->LayerGroups.Entries[i][0] : i; 00562 ext = layer_type_to_file_name (idx, FNS_fixed); 00563 src = gsvit_get_png_name (gsvit_basename, ext); 00564 XOUT_NEWLINE (); 00565 XOUT_ELEMENT_ATTR ("layer", "name", ext, src); 00566 } 00567 XOUT_DETENT (); 00568 XOUT_NEWLINE (); 00569 XOUT_ELEMENT_END ("layers"); 00570 XOUT_DETENT (); 00571 XOUT_NEWLINE (); 00572 XOUT_ELEMENT_END ("space"); 00573 XOUT_DETENT (); 00574 } 00575 00576 00577 static void 00578 gsvit_write_xnets (void) 00579 { 00580 LibraryType netlist; 00581 LibraryMenuType *net; 00582 LibraryEntryType *pin; 00583 int n, m, i, idx; 00584 00585 netlist = PCB->NetlistLib; 00586 00587 XOUT_INDENT (); 00588 XOUT_NEWLINE (); 00589 XOUT_ELEMENT_START ("nets"); 00590 XOUT_INDENT (); 00591 XOUT_NEWLINE (); 00592 XOUT_ELEMENT ("comment", "***** Nets *****"); 00593 XOUT_NEWLINE (); 00594 00595 for (n = 0; n < netlist.MenuN; n++) { 00596 char buff[0x100]; 00597 net = &netlist.Menu[n]; 00598 00599 /* Weird, but correct */ 00600 XOUT_ELEMENT_ATTR_START ("net", "name", &net->Name[2]); 00601 // snprintf(buff, 0x100, "%d,%d,%d", net->color.r, net->color.g, net->color.b); 00602 // XOUT_ELEMENT_2ATTR_START("net", "name", &net->Name[2], "color", buff ); 00603 00604 for (m = 0; m < net->EntryN; m++) { 00605 pin = &net->Entry[m]; 00606 00607 /* pin_name_to_xy(pin, &x, &y); */ 00608 00609 for (i = 0; i < MAX_GROUP; i++) 00610 if (gsvit_export_group[i]) { 00611 idx = (i >= 0 && i < max_group) ? PCB->LayerGroups.Entries[i][0] : i; 00612 layer_type_to_file_name (idx, FNS_fixed); 00613 00614 if (m != 0 || i != 0) 00615 XOUT_ELEMENT_DATA (", "); 00616 snprintf (buff, 0x100, "%s", pin->ListEntry); 00617 { 00618 char* src = buff; 00619 while (*src) 00620 { 00621 if (*src == '-') 00622 *src = '.'; 00623 src++; 00624 } 00625 } 00626 00627 XOUT_ELEMENT_DATA (buff); 00628 break; 00629 } 00630 } 00631 00632 XOUT_ELEMENT_END ("net"); 00633 if (n+1 >= netlist.MenuN) 00634 XOUT_DETENT (); 00635 XOUT_NEWLINE (); 00636 } 00637 XOUT_ELEMENT_END ("nets"); 00638 XOUT_DETENT (); 00639 } 00640 00641 00642 static StringList * 00643 string_insert (char *str, StringList *list) 00644 { 00645 StringList *newlist, *cur; 00646 00647 if ((newlist = (StringList *) malloc (sizeof (StringList))) == NULL) 00648 { 00649 fprintf (stderr, "malloc() failed in string_insert()\n"); 00650 exit (1); 00651 } 00652 00653 newlist->next = NULL; 00654 newlist->str = strdup (str); 00655 00656 if (list == NULL) 00657 return (newlist); 00658 00659 cur = list; 00660 while (cur->next != NULL) 00661 cur = cur->next; 00662 00663 cur->next = newlist; 00664 00665 return (list); 00666 } 00667 00668 00669 static BomList * 00670 bom_insert (char *refdes, char *descr, char *value, BomList * bom) 00671 { 00672 BomList *newlist, *cur, *prev = NULL; 00673 00674 if (bom == NULL) 00675 { 00676 /* this is the first element so automatically create an entry */ 00677 if ((newlist = (BomList *) malloc (sizeof (BomList))) == NULL) 00678 { 00679 fprintf (stderr, "malloc() failed in bom_insert()\n"); 00680 exit (1); 00681 } 00682 00683 newlist->next = NULL; 00684 newlist->descr = strdup (descr); 00685 newlist->value = strdup (value); 00686 newlist->num = 1; 00687 newlist->refdes = string_insert (refdes, NULL); 00688 return (newlist); 00689 } 00690 00691 /* search and see if we already have used one of these 00692 components */ 00693 cur = bom; 00694 while (cur != NULL) 00695 { 00696 if ((NSTRCMP (descr, cur->descr) == 0) && (NSTRCMP (value, cur->value) == 0)) 00697 { 00698 cur->num++; 00699 cur->refdes = string_insert (refdes, cur->refdes); 00700 break; 00701 } 00702 prev = cur; 00703 cur = cur->next; 00704 } 00705 00706 if (cur == NULL) 00707 { 00708 if ((newlist = (BomList *) malloc (sizeof (BomList))) == NULL) 00709 { 00710 fprintf (stderr, "malloc() failed in bom_insert()\n"); 00711 exit (1); 00712 } 00713 00714 prev->next = newlist; 00715 00716 newlist->next = NULL; 00717 newlist->descr = strdup (descr); 00718 newlist->value = strdup (value); 00719 newlist->num = 1; 00720 newlist->refdes = string_insert (refdes, NULL); 00721 } 00722 return (bom); 00723 } 00724 00725 00726 static double 00727 xyToAngle (double x, double y, bool morethan2pins) 00728 { 00729 double d = atan2 (-y, x) * 180.0 / M_PI; 00730 00731 /* IPC 7351 defines different rules for 2 pin elements */ 00732 if (morethan2pins) 00733 { 00734 /* Multi pin case: 00735 * Output 0 degrees if pin1 in is top left or top, i.e. between angles of 00736 * 80 to 170 degrees. 00737 * Pin #1 can be at dead top (e.g. certain PLCCs) or anywhere in the top 00738 * left. 00739 */ 00740 if (d < -100) 00741 return 90; /* -180 to -100 */ 00742 else if (d < -10) 00743 return 180; /* -100 to -10 */ 00744 else if (d < 80) 00745 return 270; /* -10 to 80 */ 00746 else if (d < 170) 00747 return 0; /* 80 to 170 */ 00748 else 00749 return 90; /* 170 to 180 */ 00750 } 00751 else 00752 { 00753 /* 2 pin element: 00754 * Output 0 degrees if pin #1 is in top left or left, i.e. in sector 00755 * between angles of 95 and 185 degrees. 00756 */ 00757 if (d < -175) 00758 return 0; /* -180 to -175 */ 00759 else if (d < -85) 00760 return 90; /* -175 to -85 */ 00761 else if (d < 5) 00762 return 180; /* -85 to 5 */ 00763 else if (d < 95) 00764 return 270; /* 5 to 95 */ 00765 else 00766 return 0; /* 95 to 180 */ 00767 } 00768 } 00769 00770 00774 static void 00775 gsvit_parse_arguments (int *argc, char ***argv) 00776 { 00777 hid_register_attributes (gsvit_attribute_list, sizeof (gsvit_attribute_list) / 00778 sizeof (gsvit_attribute_list[0])); 00779 00780 hid_parse_command_line(argc, argv); 00781 } 00782 00783 00784 static HID_Attribute * 00785 gsvit_get_export_options (int *n) 00786 { 00787 static char *last_made_filename = 0; 00788 00789 if (PCB) { 00790 derive_default_filename (PCB->Filename, &gsvit_attribute_list[HA_basename], 00791 ".gsvit", &last_made_filename); 00792 } 00793 00794 if (n) { 00795 *n = NUM_OPTIONS; 00796 } 00797 00798 return gsvit_attribute_list; 00799 } 00800 00801 00802 static char* CleanXBOMString (char *in) 00803 { 00804 char *out; 00805 // int i; 00806 char* src; 00807 char* dest; 00808 00809 if ((out = (char *)malloc ((strlen (in) + 1+0x40) * sizeof (char))) == NULL) 00810 { 00811 fprintf (stderr, "Error: CleanBOMString() malloc() failed\n"); 00812 exit (1); 00813 } 00814 dest = out; 00815 src = in; 00816 while(*src != '\0') 00817 { 00818 switch (*src) 00819 { 00820 case '<': 00821 *dest++ = '&'; 00822 *dest++ = 'l'; 00823 *dest++ = 't'; 00824 *dest = ';'; 00825 break; 00826 case '&': 00827 *dest++ = '&'; 00828 *dest++ = 'a'; 00829 *dest++ = 'm'; 00830 *dest++ = 'p'; 00831 *dest = ';'; 00832 break; 00833 default: 00834 *dest = *src; 00835 } 00836 src++; 00837 dest++; 00838 } 00839 return out; 00840 } 00841 00842 00843 static void gsvit_write_xdrills (void) 00844 { 00845 int i = 0; 00846 int j; 00847 char buff[0x100]; 00848 00849 XOUT_NEWLINE (); 00850 XOUT_ELEMENT_START ("drills"); 00851 XOUT_INDENT (); 00852 XOUT_NEWLINE (); 00853 XOUT_ELEMENT ("comment", "***** Drills *****"); 00854 for (i = 0; i < n_drills; i++) 00855 { 00856 snprintf (buff, 0x100, "D%d", i); 00857 XOUT_NEWLINE (); 00858 XOUT_ELEMENT_ATTR_START ("drill", "id", buff); 00859 XOUT_INDENT (); 00860 snprintf (buff, 0x100, "%g", drills[i].diameter_inches); 00861 XOUT_NEWLINE (); 00862 XOUT_ELEMENT ("dia_inches", buff); 00863 snprintf (buff, 0x100, "%d", pcb_to_gsvit(drills[i].radius)); 00864 XOUT_NEWLINE (); 00865 XOUT_ELEMENT ("radius", buff); 00866 for (j = 0; j < drills[i].n_holes; j++) 00867 { 00868 snprintf (buff, 0x100, "%d,%d", drills[i].holes[j].cx, drills[i].holes[j].cy); 00869 XOUT_NEWLINE (); 00870 if (drills[i].holes[j].is_plated) 00871 { 00872 XOUT_ELEMENT_ATTR_START ("pos", "type", "plated"); 00873 } 00874 else 00875 { 00876 XOUT_ELEMENT_ATTR_START ("pos", "type", "unplated"); 00877 } 00878 XOUT_ELEMENT_DATA (buff); 00879 XOUT_ELEMENT_END ("pos"); 00880 } 00881 XOUT_DETENT (); 00882 XOUT_NEWLINE (); 00883 XOUT_ELEMENT_END ("drill"); 00884 } 00885 // if (drills[i].diameter_inches >= diameter_inches) 00886 // break; 00887 XOUT_DETENT (); 00888 XOUT_NEWLINE (); 00889 XOUT_ELEMENT_END ("drills"); 00890 XOUT_DETENT (); 00891 XOUT_NEWLINE (); 00892 } 00893 00894 00895 static void gsvit_write_xcentroids (void) 00896 { 00897 char buff[0x100]; 00898 00899 Coord x, y; 00900 double theta = 0.0; 00901 double sumx, sumy; 00902 int pinfound[MAXREFPINS]; 00903 double pinx[MAXREFPINS]; 00904 double piny[MAXREFPINS]; 00905 double pinangle[MAXREFPINS]; 00906 double padcentrex, padcentrey; 00907 double centroidx, centroidy; 00908 double pin1x, pin1y; 00909 int pin_cnt; 00910 int found_any_not_at_centroid; 00911 int found_any; 00912 BomList *bom = NULL; 00913 char *name, *descr, *value,*fixed_rotation; 00914 int rpindex; 00915 00916 XOUT_INDENT (); 00917 XOUT_NEWLINE (); 00918 00919 XOUT_ELEMENT_START ("centroids"); 00920 XOUT_INDENT (); 00921 XOUT_NEWLINE (); 00922 XOUT_ELEMENT ("comment", "***** Centroids *****"); 00923 00924 /* 00925 * For each element we calculate the centroid of the footprint. 00926 * In addition, we need to extract some notion of rotation. 00927 * While here generate the BOM list 00928 */ 00929 ELEMENT_LOOP (PCB->Data); 00930 { 00931 00932 /* Initialize our pin count and our totals for finding the centroid. */ 00933 pin_cnt = 0; 00934 sumx = 0.0; 00935 sumy = 0.0; 00936 for (rpindex = 0; rpindex < MAXREFPINS; rpindex++) 00937 pinfound[rpindex] = 0; 00938 00939 /* Insert this component into the bill of materials list. */ 00940 bom = bom_insert ((char *)UNKNOWN (NAMEONPCB_NAME (element)), 00941 (char *)UNKNOWN (DESCRIPTION_NAME (element)), 00942 (char *)UNKNOWN (VALUE_NAME (element)), bom); 00943 00944 00945 /* 00946 * Iterate over the pins and pads keeping a running count of how 00947 * many pins/pads total and the sum of x and y coordinates 00948 * 00949 * While we're at it, store the location of pin/pad #1 and #2 if 00950 * we can find them. 00951 */ 00952 00953 PIN_LOOP (element); 00954 { 00955 sumx += (double) pin->X; 00956 sumy += (double) pin->Y; 00957 pin_cnt++; 00958 00959 for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { 00960 if (NSTRCMP (pin->Number, reference_pin_names[rpindex]) == 0){ 00961 pinx[rpindex] = (double) pin->X; 00962 piny[rpindex] = (double) pin->Y; 00963 pinangle[rpindex] = 0.0; /* pins have no notion of angle */ 00964 pinfound[rpindex] = 1; 00965 } 00966 } 00967 } 00968 END_LOOP; 00969 00970 PAD_LOOP (element); 00971 { 00972 sumx += (pad->Point1.X + pad->Point2.X) / 2.0; 00973 sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; 00974 pin_cnt++; 00975 00976 for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { 00977 if (NSTRCMP (pad->Number, reference_pin_names[rpindex]) == 0) { 00978 padcentrex = (double) (pad->Point1.X + pad->Point2.X) / 2.0; 00979 padcentrey = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; 00980 pinx[rpindex] = padcentrex; 00981 piny[rpindex] = padcentrey; 00982 /* 00983 * NOTE: We swap the Y points because in PCB, the Y-axis 00984 * is inverted. Increasing Y moves down. We want to deal 00985 * in the usual increasing Y moves up coordinates though. 00986 */ 00987 pinangle[rpindex] = (180.0 / M_PI) * atan2 (pad->Point1.Y - pad->Point2.Y, 00988 pad->Point2.X - pad->Point1.X); 00989 pinfound[rpindex]=1; 00990 } 00991 } 00992 } 00993 END_LOOP; 00994 00995 if (pin_cnt > 0) { 00996 centroidx = sumx / (double) pin_cnt; 00997 centroidy = sumy / (double) pin_cnt; 00998 00999 if (NSTRCMP (AttributeGetFromList (&element->Attributes,"xy-centre"), "origin") == 0 ) { 01000 x = element->MarkX; 01001 y = element->MarkY; 01002 } 01003 else { 01004 x = centroidx; 01005 y = centroidy; 01006 } 01007 01008 fixed_rotation = AttributeGetFromList (&element->Attributes, "xy-fixed-rotation"); 01009 if (fixed_rotation) { 01010 /* The user specified a fixed rotation */ 01011 theta = atof (fixed_rotation); 01012 found_any_not_at_centroid = 1; 01013 found_any = 1; 01014 } 01015 else { 01016 /* Find first reference pin not at the centroid */ 01017 found_any_not_at_centroid = 0; 01018 found_any = 0; 01019 theta = 0.0; 01020 for (rpindex = 0; 01021 reference_pin_names[rpindex] && !found_any_not_at_centroid; 01022 rpindex++) { 01023 if (pinfound[rpindex]) { 01024 found_any = 1; 01025 01026 /* Recenter pin "#1" onto the axis which cross at the part 01027 * centroid. */ 01028 pin1x = pinx[rpindex] - x; 01029 pin1y = piny[rpindex] - y; 01030 01031 /* flip x, to reverse rotation for elements on back. */ 01032 if (FRONT (element) != 1) 01033 pin1x = -pin1x; 01034 01035 /* if only 1 pin, use pin 1's angle */ 01036 if (pin_cnt == 1) { 01037 theta = pinangle[rpindex]; 01038 found_any_not_at_centroid = 1; 01039 } 01040 else if ((pin1x != 0.0) || (pin1y != 0.0)) { 01041 theta = xyToAngle (pin1x, pin1y, pin_cnt > 2); 01042 found_any_not_at_centroid = 1; 01043 } 01044 } 01045 } 01046 01047 if (!found_any) { 01048 Message 01049 ("PrintBOM(): unable to figure out angle because I could\n" 01050 " not find a suitable reference pin of element %s\n" 01051 " Setting to %g degrees\n", 01052 UNKNOWN (NAMEONPCB_NAME (element)), theta); 01053 } 01054 else if (!found_any_not_at_centroid) { 01055 Message 01056 ("PrintBOM(): unable to figure out angle of element\n" 01057 " %s because the reference pin(s) are at the centroid of the part.\n" 01058 " Setting to %g degrees\n", 01059 UNKNOWN (NAMEONPCB_NAME (element)), theta); 01060 } 01061 } 01062 name = CleanXBOMString ((char *)UNKNOWN (NAMEONPCB_NAME (element))); 01063 descr = CleanXBOMString ((char *)UNKNOWN (DESCRIPTION_NAME (element))); 01064 value = CleanXBOMString ((char *)UNKNOWN (VALUE_NAME (element))); 01065 01066 y = PCB->MaxHeight - y; 01067 XOUT_NEWLINE (); 01068 XOUT_ELEMENT_ATTR_START ("xy", "name", name); 01069 XOUT_INDENT (); 01070 XOUT_NEWLINE (); 01071 XOUT_ELEMENT ("description", descr); 01072 XOUT_NEWLINE (); 01073 XOUT_ELEMENT ("value", value); 01074 XOUT_NEWLINE (); 01075 snprintf (buff, 0x100, "%d,%d", pcb_to_gsvit(x), pcb_to_gsvit(y)); 01076 XOUT_ELEMENT ("pos", buff); 01077 XOUT_NEWLINE (); 01078 pcb_snprintf (buff, 0x100, "%g", theta); 01079 XOUT_ELEMENT ("rotation", buff); 01080 XOUT_NEWLINE (); 01081 XOUT_ELEMENT ("side", FRONT (element) == 1 ? "top" : "bottom"); 01082 XOUT_DETENT (); 01083 XOUT_NEWLINE (); 01084 XOUT_ELEMENT_END ("xy"); 01085 01086 free (name); 01087 free (descr); 01088 free (value); 01089 } 01090 } 01091 END_LOOP; 01092 01093 XOUT_DETENT (); 01094 XOUT_NEWLINE (); 01095 XOUT_ELEMENT_END ("centroids"); 01096 } 01097 01098 01102 void 01103 gsvit_choose_groups () 01104 { 01105 int n, m; 01106 LayerType *layer; 01107 01108 /* Set entire array to 0 (don't export any layer groups by default */ 01109 memset (gsvit_export_group, 0, sizeof (gsvit_export_group)); 01110 01111 for (n = 0; n < max_copper_layer; n++) { 01112 layer = &PCB->Data->Layer[n]; 01113 01114 if (layer->LineN || layer->TextN || layer->ArcN || layer->PolygonN) { 01115 /* Layer isn't empty. */ 01120 if (SL_TYPE(n) == 0) { 01121 /* Layer is a copper layer. */ 01122 m = GetLayerGroupNumberByNumber (n); 01123 01124 /* The export layer. */ 01125 gsvit_export_group[m] = 1; 01126 } 01127 } 01128 } 01129 } 01130 01131 01138 static void 01139 gsvit_alloc_colors () 01140 { 01141 int i; 01142 int numNets = PCB->NetlistLib.MenuN; 01143 char *rgb; 01144 01145 white = (struct color_struct *) malloc (sizeof (*white)); 01146 white->r = white->g = white->b = 255; 01147 white->c = gdImageColorAllocate (gsvit_im, white->r, white->g, white->b); 01148 01149 black = (struct color_struct *) malloc (sizeof (*black)); 01150 black->r = black->g = black->b = 0; 01151 black->c = gdImageColorAllocate (gsvit_im, black->r, black->g, black->b); 01152 01153 for (i = 0; i < numNets; i++) { 01154 gsvit_netlist[i].colorIndex = i; 01155 color_array[i] = malloc (sizeof (*white)); 01156 color_array[i]->r = gsvit_netlist[i].color.r; 01157 color_array[i]->g = gsvit_netlist[i].color.g; 01158 color_array[i]->b = gsvit_netlist[i].color.b; 01159 01160 color_array[i]->c = gdImageColorAllocate (gsvit_im, color_array[i]->r, color_array[i]->g, color_array[i]->b); 01161 } 01162 01163 color_array[i] = malloc (sizeof (*white)); 01164 rgb = hslToRgb (128, (20 * 256) / 100, (20 * 256) / 100); 01165 01166 color_array[i]->r = rgb[0]; 01167 color_array[i]->g = rgb[1]; 01168 color_array[i]->b = rgb[2]; 01169 color_array[i]->c = gdImageColorAllocate (gsvit_im, color_array[i]->r, color_array[i]->g, color_array[i]->b); 01170 01171 printf ("%d colors allocated\n", numNets); 01172 } 01173 01174 01175 static void 01176 gsvit_start_png (const char *basename, const char *suffix) 01177 { 01178 int h, w; 01179 char *buf; 01180 01181 buf = gsvit_get_png_name (basename, suffix); 01182 01183 h = pcb_to_gsvit (PCB->MaxHeight); 01184 w = pcb_to_gsvit (PCB->MaxWidth); 01185 01186 /* gsvit only works with true color images. */ 01187 gsvit_im = gdImageCreate (w, h); 01188 gsvit_f = fopen (buf, "wb"); 01189 01190 gsvit_alloc_colors (); 01191 01192 free (buf); 01193 } 01194 01195 01196 static void 01197 gsvit_finish_png () 01198 { 01199 int i; 01200 #ifdef HAVE_GDIMAGEPNG 01201 gdImagePng (gsvit_im, gsvit_f); 01202 #else 01203 Message ("gsvit: PNG not supported by gd. Can't write layer mask.\n"); 01204 #endif 01205 gdImageDestroy (gsvit_im); 01206 fclose (gsvit_f); 01207 01208 for (i = 0; i < 0x100; i++) { 01209 free (color_array[i]); 01210 } 01211 01212 gsvit_im = NULL; 01213 gsvit_f = NULL; 01214 } 01215 01216 01217 void 01218 gsvit_start_png_export () 01219 { 01220 BoxType region; 01221 01222 region.X1 = 0; 01223 region.Y1 = 0; 01224 region.X2 = PCB->MaxWidth; 01225 region.Y2 = PCB->MaxHeight; 01226 01227 linewidth = -1; 01228 lastbrush = (gdImagePtr)((void *) -1); 01229 01230 hid_expose_callback (&gsvit_hid, ®ion, 0); 01231 } 01232 01233 01234 static void 01235 gsvit_do_export (HID_Attr_Val *options) 01236 { 01237 int save_ons[MAX_ALL_LAYER]; 01238 int i, idx; 01239 char *buf; 01240 int len; 01241 01242 01243 if (!options) { 01244 gsvit_get_export_options(0); 01245 01246 for (i = 0; i < NUM_OPTIONS; i++) { 01247 gsvit_values[i] = gsvit_attribute_list[i].default_val; 01248 } 01249 01250 options = gsvit_values; 01251 } 01252 01253 gsvit_basename = options[HA_basename].str_value; 01254 01255 if (!gsvit_basename) { 01256 gsvit_basename = "pcb-out"; 01257 } 01258 01259 gsvit_dpi = options[HA_dpi].int_value; 01260 01261 if (gsvit_dpi < 0) { 01262 fprintf (stderr, "ERROR: dpi may not be < 0\n"); 01263 return; 01264 } 01265 01266 gsvit_create_netlist (); 01267 gsvit_choose_groups (); 01268 01269 for (i = 0; i < MAX_GROUP; i++) { 01270 if (gsvit_export_group[i]) { 01271 gsvit_cur_group = i; 01272 /* Magic. */ 01273 idx = (i >= 0 && i < max_group) ? PCB->LayerGroups.Entries[i][0] : i; 01274 save_drill = (GetLayerGroupNumberByNumber (idx) == GetLayerGroupNumberBySide (BOTTOM_SIDE)) ? 1 : 0; 01275 /* save drills for one layer only */ 01276 gsvit_start_png (gsvit_basename, layer_type_to_file_name (idx, FNS_fixed)); 01277 hid_save_and_show_layer_ons (save_ons); 01278 gsvit_start_png_export (); 01279 hid_restore_layer_ons (save_ons); 01280 gsvit_finish_png (); 01281 } 01282 } 01283 01284 len = strlen (gsvit_basename) + 4; 01285 buf = (char *) malloc (sizeof (*buf) * len); 01286 01287 gsvit_xml_out ((char*) gsvit_basename); 01288 gsvit_destroy_netlist (); 01289 } 01290 01291 01292 void 01293 gsvit_xml_out (char *gsvit_basename) 01294 { 01295 char *buf; 01296 int len; 01297 time_t t; 01298 01299 len = strlen (gsvit_basename) + 4; 01300 buf = (char *) malloc (sizeof (*buf) * len); 01301 01302 sprintf (buf, "%s.xem", gsvit_basename); 01303 XOUT_INIT (buf); 01304 free (buf); 01305 01306 XOUT_HEADER (); 01307 XOUT_NEWLINE (); 01308 XOUT_ELEMENT_START ("gsvit"); 01309 XOUT_INDENT (); 01310 XOUT_NEWLINE (); 01311 XOUT_ELEMENT ("comment", "Made with PCB gsvit export HID"); 01312 XOUT_NEWLINE (); 01313 { 01314 char buff[0x100]; 01315 char* src = buff; 01316 t = time (NULL); 01317 strncpy (buff, ctime(&t), 0x100); 01318 while (*src) 01319 { 01320 if ((*src =='\r') || (*src =='\n')) { 01321 *src = 0; 01322 break; 01323 } 01324 src++; 01325 } 01326 XOUT_ELEMENT ("genTime", buff); 01327 XOUT_NEWLINE (); 01328 } 01329 gsvit_write_xspace (); 01330 gsvit_write_xnets (); 01331 gsvit_write_xcentroids(); 01332 gsvit_write_xdrills(); 01333 01334 XOUT_ELEMENT_END ("gsvit"); 01335 XOUT_NEWLINE (); 01336 XOUT_CLOSE (); 01337 } 01338 01339 /* *** PNG export (slightly modified code from PNG export HID) ************* */ 01340 01341 static int 01342 gsvit_set_layer (const char *name, int group, int empty) 01343 { 01344 int idx = (group >= 0 && group < max_group) ? PCB->LayerGroups.Entries[group][0] : group; 01345 01346 if (name == 0) { 01347 name = PCB->Data->Layer[idx].Name; 01348 } 01349 01350 if (strcmp(name, "invisible") == 0) { 01351 return 0; 01352 } 01353 01354 is_drill = (SL_TYPE (idx) == SL_PDRILL || SL_TYPE (idx) == SL_UDRILL); 01355 is_mask = (SL_TYPE (idx) == SL_MASK); 01356 01357 if (is_mask) { 01358 /* Don't print masks. */ 01359 return 0; 01360 } 01361 01362 if (is_drill) { 01363 if (SL_TYPE(idx) == SL_PDRILL) 01364 is_plated =1; 01365 else if (SL_TYPE(idx) == SL_UDRILL) 01366 is_plated =0; 01367 01368 /* Print 'holes', so that we can fill gaps in the copper layer. */ 01369 return 1; 01370 } 01371 01372 if (group == gsvit_cur_group) { 01373 return 1; 01374 } 01375 01376 return 0; 01377 } 01378 01379 01380 static hidGC 01381 gsvit_make_gc (void) 01382 { 01383 hidGC rv = (hidGC) malloc (sizeof (struct hid_gc_struct)); 01384 rv->me_pointer = &gsvit_hid; 01385 rv->cap = Trace_Cap; 01386 rv->width = 1; 01387 rv->color = (struct color_struct *) malloc (sizeof (*rv->color)); 01388 rv->color->r = rv->color->g = rv->color->b = 0; 01389 rv->color->c = 0; 01390 return rv; 01391 } 01392 01393 01394 static void 01395 gsvit_destroy_gc (hidGC gc) 01396 { 01397 free (gc); 01398 } 01399 01400 01401 static void 01402 gsvit_use_mask (enum mask_mode mode) 01403 { 01404 /* Do nothing. */ 01405 } 01406 01407 01408 static void 01409 gsvit_set_color (hidGC gc, const char *name) 01410 { 01411 if (gsvit_im == NULL) { 01412 return; 01413 } 01414 01415 if (name == NULL) { 01416 name = "#ff0000"; 01417 } 01418 01419 if (!strcmp(name, "drill")) { 01420 gc->color = black; 01421 gc->erase = 0; 01422 return; 01423 } 01424 01425 if (!strcmp(name, "erase")) { 01427 gc->color = white; 01428 gc->erase = 1; 01429 return; 01430 } 01431 01432 gc->color = black; 01433 gc->erase = 0; 01434 return; 01435 } 01436 01437 01438 static void 01439 gsvit_set_line_cap (hidGC gc, EndCapStyle style) 01440 { 01441 gc->cap = style; 01442 } 01443 01444 01445 static void 01446 gsvit_set_line_width (hidGC gc, Coord width) 01447 { 01448 gc->width = width; 01449 } 01450 01451 01452 static void 01453 gsvit_set_draw_xor (hidGC gc, int xor_) 01454 { 01455 /* Do nothing. */ 01456 } 01457 01458 01459 static void 01460 gsvit_set_draw_faded (hidGC gc, int faded) 01461 { 01462 /* Do nothing. */ 01463 } 01464 01465 01466 static void 01467 use_gc (hidGC gc) 01468 { 01469 int need_brush = 0; 01470 01471 if (gc->me_pointer != &gsvit_hid) { 01472 fprintf (stderr, "Fatal: GC from another HID passed to gsvit HID\n"); 01473 abort (); 01474 } 01475 01476 if (hashColor != gdBrushed) { 01477 need_brush = 1; 01478 } 01479 01480 if (linewidth != gc->width) { 01481 /* Make sure the scaling doesn't erase lines completely */ 01482 /* 01483 if (SCALE (gc->width) == 0 && gc->width > 0) 01484 gdImageSetThickness (im, 1); 01485 else 01486 */ 01487 gdImageSetThickness (gsvit_im, pcb_to_gsvit (gc->width)); 01488 linewidth = gc->width; 01489 need_brush = 1; 01490 } 01491 01492 if (lastbrush != gc->brush || need_brush) { 01493 static void *bcache = 0; 01494 hidval bval; 01495 char name[256]; 01496 char type; 01497 int r; 01498 01499 switch (gc->cap) { 01500 case Round_Cap: 01501 case Trace_Cap: 01502 type = 'C'; 01503 r = pcb_to_gsvit (gc->width / 2); 01504 break; 01505 default: 01506 case Square_Cap: 01507 r = pcb_to_gsvit(gc->width); 01508 type = 'S'; 01509 break; 01510 } 01511 sprintf (name, "#%.2x%.2x%.2x_%c_%d", gc->color->r, gc->color->g, gc->color->b, type, r); 01512 /* 01513 if (hid_cache_color(0, name, &bval, &bcache)) { 01514 gc->brush = (gdImagePtr) bval.ptr; 01515 } 01516 else { 01517 */ 01518 { 01519 int bg, fg; 01520 01521 if (type == 'C') 01522 gc->brush = gdImageCreate (2 * r + 1, 2 * r + 1); 01523 else 01524 gc->brush = gdImageCreate (r + 1, r + 1); 01525 01526 bg = gdImageColorAllocate (gc->brush, 255, 255, 255); 01527 if (hashColor != gdBrushed) { 01528 /* 01529 printf ("hash:%d\n",hashColor); 01530 */ 01531 fg = gdImageColorAllocate (gc->brush, color_array[hashColor]->r,color_array[hashColor]->g,color_array[hashColor]->b); 01532 } 01533 else { 01534 fg = gdImageColorAllocate (gc->brush, gc->color->r, gc->color->g, gc->color->b); 01535 } 01536 gdImageColorTransparent (gc->brush, bg); 01537 01538 /* If we shrunk to a radius/box width of zero, then just use a 01539 * single pixel to draw with. 01540 */ 01541 if (r == 0) { 01542 gdImageFilledRectangle (gc->brush, 0, 0, 0, 0, fg); 01543 } 01544 else { 01545 if (type == 'C') 01546 gdImageFilledEllipse (gc->brush, r, r, 2 * r, 2 * r, fg); 01547 else 01548 gdImageFilledRectangle (gc->brush, 0, 0, r, r, fg); 01549 } 01550 bval.ptr = gc->brush; 01551 hid_cache_color (1, name, &bval, &bcache); 01552 } 01553 01554 gdImageSetBrush (gsvit_im, gc->brush); 01555 lastbrush = gc->brush; 01556 } 01557 } 01558 01559 01560 static void 01561 gsvit_draw_rect (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2) 01562 { 01563 use_gc (gc); 01564 01565 gdImageRectangle (gsvit_im, pcb_to_gsvit (x1), pcb_to_gsvit (y1), 01566 pcb_to_gsvit (x2), pcb_to_gsvit (y2), gc->color->c); 01567 } 01568 01569 01570 static void 01571 gsvit_fill_rect (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2) 01572 { 01573 use_gc (gc); 01574 gdImageSetThickness (gsvit_im, 0); 01575 linewidth = 0; 01576 01577 gdImageFilledRectangle (gsvit_im, pcb_to_gsvit (x1), pcb_to_gsvit (y1), 01578 pcb_to_gsvit (x2), pcb_to_gsvit (y2), gc->color->c); 01579 } 01580 01581 01582 struct gsvit_netlist * 01583 gsvit_lookup_net_from_arc (ArcType *targetArc) 01584 { 01585 int i; 01586 01587 for (i = 0; i < PCB->NetlistLib.MenuN; i++) { 01588 /* For each net in the netlist. */ 01589 struct gsvit_netlist *currNet = &gsvit_netlist[i]; 01590 int j; 01591 01592 for (j = 0; j < PCB->LayerGroups.Number[gsvit_cur_group]; j++) { 01593 /* For each layer of the current group. */ 01594 int layer = PCB->LayerGroups.Entries[gsvit_cur_group][j]; 01595 01596 ARC_LOOP (&(currNet->layer[layer])); 01597 { 01598 if (targetArc == arc) 01599 return (currNet); 01600 } 01601 END_LOOP; 01602 } 01603 } 01604 01605 return (NULL); 01606 } 01607 01608 01609 struct gsvit_netlist * 01610 gsvit_lookup_net_from_line (LineType *targetLine) 01611 { 01612 int i; 01613 01614 for (i = 0; i < PCB->NetlistLib.MenuN; i++) { 01615 /* For each net in the netlist. */ 01616 struct gsvit_netlist* currNet = &gsvit_netlist[i]; 01617 int j; 01618 01619 for (j = 0; j < PCB->LayerGroups.Number[gsvit_cur_group]; j++) { 01620 /* For each layer of the current group. */ 01621 int layer = PCB->LayerGroups.Entries[gsvit_cur_group][j]; 01622 01623 LINE_LOOP (&(currNet->layer[layer])); 01624 { 01625 if (targetLine == line) 01626 return (currNet); 01627 } 01628 END_LOOP; 01629 01630 } 01631 } 01632 01633 return (NULL); 01634 } 01635 01636 01637 struct gsvit_netlist * 01638 gsvit_lookup_net_from_polygon (PolygonType *targetPolygon) 01639 { 01640 int i; 01641 01642 for (i = 0; i < PCB->NetlistLib.MenuN; i++) { 01643 /* For each net in the netlist. */ 01644 struct gsvit_netlist* currNet = &gsvit_netlist[i]; 01645 int j; 01646 01647 for (j = 0; j < PCB->LayerGroups.Number[gsvit_cur_group]; j++) { 01648 /* For each layer of the current group. */ 01649 int layer = PCB->LayerGroups.Entries[gsvit_cur_group][j]; 01650 01651 POLYGON_LOOP (&(currNet->layer[layer])); 01652 { 01653 if (targetPolygon == polygon) 01654 return (currNet); 01655 } 01656 END_LOOP; 01657 01658 } 01659 } 01660 01661 return (NULL); 01662 } 01663 01664 01665 struct gsvit_netlist * 01666 gsvit_lookup_net_from_pad (PadType *targetPad) 01667 { 01668 int i; 01669 01670 for (i = 0; i < PCB->NetlistLib.MenuN; i++) { 01671 /* For each net in the netlist. */ 01672 struct gsvit_netlist* currNet = &gsvit_netlist[i]; 01673 01674 PAD_LOOP (currNet); 01675 { 01676 if (targetPad == pad) 01677 return (currNet); 01678 } 01679 END_LOOP; 01680 01681 } 01682 01683 return (NULL); 01684 } 01685 01686 01687 struct gsvit_netlist * 01688 gsvit_lookup_net_from_pv (PinType *targetPv) 01689 { 01690 int i; 01691 01692 for (i = 0; i < PCB->NetlistLib.MenuN; i++) { 01693 /* For each net in the netlist. */ 01694 struct gsvit_netlist* currNet = &gsvit_netlist[i]; 01695 01696 PIN_LOOP (currNet); 01697 { 01698 if (targetPv == pin) 01699 return (currNet); 01700 } 01701 END_LOOP; 01702 01703 VIA_LOOP (currNet); 01704 { 01705 if (targetPv == via) 01706 return (currNet); 01707 } 01708 END_LOOP; 01709 } 01710 01711 return (NULL); 01712 } 01713 01714 01715 static void 01716 add_hole (struct single_size_drills* drill, int cx, int cy) 01717 { 01718 if (drill->n_holes == drill->n_holes_allocated) { 01719 drill->n_holes_allocated += 100; 01720 drill->holes = (struct drill_hole *) realloc (drill->holes,drill->n_holes_allocated *sizeof (struct drill_hole)); 01721 } 01722 drill->holes[drill->n_holes].cx = cx; 01723 drill->holes[drill->n_holes].cy = cy; 01724 drill->holes[drill->n_holes].is_plated = is_plated; 01725 drill->n_holes++; 01726 printf ("holes %d\n", drill->n_holes); 01727 } 01728 01729 01736 static int 01737 _drill_size_comparator (const void* _size0, const void* _size1) 01738 { 01739 double size0 = ((const struct single_size_drills*)_size0)->diameter_inches; 01740 double size1 = ((const struct single_size_drills*)_size1)->diameter_inches; 01741 if (size0 == size1) 01742 return 0; 01743 if (size0 < size1) 01744 return -1; 01745 return 1; 01746 } 01747 01748 01749 static struct single_size_drills * 01750 get_drill (double diameter_inches, Coord radius) 01751 { 01752 /* See if we already have this size. If so, return that structure. */ 01753 struct single_size_drills* drill = bsearch (&diameter_inches, 01754 drills, n_drills, sizeof (drills[0]), 01755 _drill_size_comparator); 01756 01757 if (drill != NULL) 01758 return( drill); 01759 01760 /* Haven't seen this hole size before, so make a new structure for it. */ 01761 if (n_drills == n_drills_allocated) { 01762 n_drills_allocated += 100; 01763 drills = (struct single_size_drills *) realloc (drills, 01764 n_drills_allocated * sizeof (struct single_size_drills)); 01765 } 01766 01767 /* I now add the structure to the list, making sure to keep the list 01768 * sorted. Ideally the bsearch() call above would have given me the location 01769 * to insert this element while keeping things sorted, but it doesn't. For 01770 * simplicity I manually lsearch() to find this location myself */ 01771 { 01772 int i = 0; 01773 for (i = 0; i<n_drills; i++) 01774 if (drills[i].diameter_inches >= diameter_inches) 01775 break; 01776 01777 if (n_drills != i) 01778 memmove (&drills[i+1], &drills[i], 01779 (n_drills-i) * sizeof (struct single_size_drills)); 01780 01781 drills[i].diameter_inches = diameter_inches; 01782 drills[i].radius = radius; 01783 drills[i].n_holes = 0; 01784 drills[i].n_holes_allocated = 0; 01785 drills[i].holes = NULL; 01786 n_drills++; 01787 return &drills[i]; 01788 } 01789 } 01790 01791 01792 static void 01793 gsvit_draw_line (hidGC gc, Coord x1, Coord y1, Coord x2, Coord y2) 01794 { 01795 if (x1 == x2 && y1 == y2) { 01796 Coord w = gc->width / 2; 01797 gsvit_fill_rect (gc, x1 - w, y1 - w, x1 + w, y1 + w); 01798 return; 01799 } 01800 01801 linewidth = -1; 01802 use_gc (gc); 01803 linewidth = -1; 01804 01805 gdImageSetThickness (gsvit_im, 0); 01806 linewidth = 0; 01807 gdImageLine (gsvit_im, pcb_to_gsvit (x1), pcb_to_gsvit (y1), 01808 pcb_to_gsvit (x2), pcb_to_gsvit (y2), gdBrushed); 01809 } 01810 01811 01812 static void 01813 gsvit_draw_arc (hidGC gc, Coord cx, Coord cy, Coord width, Coord height, Angle start_angle, Angle delta_angle) 01814 { 01815 Angle sa, ea; 01816 01817 /* In gdImageArc, 0 degrees is to the right and +90 degrees is down. 01818 * in pcb, 0 degrees is to the left and +90 degrees is down. 01819 */ 01820 start_angle = 180 - start_angle; 01821 delta_angle = -delta_angle; 01822 if (delta_angle > 0) { 01823 sa = start_angle; 01824 ea = start_angle + delta_angle; 01825 } 01826 else { 01827 sa = start_angle + delta_angle; 01828 ea = start_angle; 01829 } 01830 01831 /* Make sure we start between 0 and 360 otherwise gd does strange 01832 * things. 01833 */ 01834 sa = NormalizeAngle (sa); 01835 ea = NormalizeAngle (ea); 01836 01837 #if 0 01838 printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n", 01839 cx, cy, width, height, start_angle, delta_angle, sa, ea); 01840 printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n", 01841 im, SCALE_X (cx), SCALE_Y (cy), SCALE (width), SCALE (height), sa, ea, 01842 gc->color->c); 01843 #endif 01844 use_gc (gc); 01845 gdImageSetThickness (gsvit_im, 0); 01846 linewidth = 0; 01847 gdImageArc (gsvit_im, pcb_to_gsvit (cx), pcb_to_gsvit (cy), 01848 pcb_to_gsvit (2 * width), pcb_to_gsvit (2 * height), sa, ea, gdBrushed); 01849 } 01850 01851 01852 static void 01853 gsvit_fill_circle (hidGC gc, Coord cx, Coord cy, Coord radius) 01854 { 01855 use_gc (gc); 01856 01857 gdImageSetThickness (gsvit_im, 0); 01858 linewidth = 0; 01859 gdImageFilledEllipse (gsvit_im, pcb_to_gsvit (cx), pcb_to_gsvit (cy), 01860 pcb_to_gsvit (2 * radius), pcb_to_gsvit (2 * radius), color_array[hashColor]->c); 01861 01862 if (save_drill && is_drill) 01863 { 01864 double diameter_inches = COORD_TO_INCH(radius*2); 01865 struct single_size_drills* drill = get_drill (diameter_inches, radius); 01866 add_hole(drill, pcb_to_gsvit(cx), pcb_to_gsvit(cy)); 01867 /* convert to inch, flip: will drill from bottom side */ 01868 // COORD_TO_INCH(PCB->MaxWidth - cx), 01869 /* PCB reverses y axis */ 01870 // COORD_TO_INCH(PCB->MaxHeight - cy)); 01871 } 01872 } 01873 01874 01875 static void 01876 gsvit_fill_polygon (hidGC gc, int n_coords, Coord *x, Coord *y) 01877 { 01878 int i; 01879 gdPoint *points; 01880 01881 points = (gdPoint *) malloc (n_coords * sizeof (gdPoint)); 01882 01883 if (points == NULL) { 01884 fprintf (stderr, "ERROR: gsvit_fill_polygon(): malloc failed\n"); 01885 exit (1); 01886 } 01887 01888 use_gc (gc); 01889 01890 for (i = 0; i < n_coords; i++) { 01891 points[i].x = pcb_to_gsvit (x[i]); 01892 points[i].y = pcb_to_gsvit (y[i]); 01893 } 01894 01895 gdImageSetThickness (gsvit_im, 0); 01896 linewidth = 0; 01897 gdImageFilledPolygon (gsvit_im, points, n_coords, color_array[hashColor]->c); 01898 01899 free (points); 01900 } 01901 01902 01903 static void 01904 gsvit_calibrate (double xval, double yval) 01905 { 01906 CRASH; 01907 } 01908 01909 01910 static void 01911 gsvit_set_crosshair (int x, int y, int a) 01912 { 01913 /* Do nothing. */ 01914 } 01915 01916 01917 static void 01918 gsvit_draw_pcb_arc (hidGC gc, ArcType *arc) 01919 { 01920 struct gsvit_netlist *net; 01921 01922 net = gsvit_lookup_net_from_arc (arc); 01923 01924 if (net) { 01925 hashColor = net->colorIndex; 01926 } 01927 else { 01928 hashColor = PCB->NetlistLib.MenuN; 01929 } 01930 01931 common_draw_pcb_arc (gc, arc); 01932 hashColor = PCB->NetlistLib.MenuN; 01933 } 01934 01935 01936 static void 01937 gsvit_draw_pcb_line (hidGC gc, LineType *line) 01938 { 01939 struct gsvit_netlist *net; 01940 01941 net = gsvit_lookup_net_from_line (line); 01942 01943 if (net) { 01944 hashColor = net->colorIndex; 01945 } 01946 else { 01947 hashColor = PCB->NetlistLib.MenuN; 01948 } 01949 01950 common_draw_pcb_line (gc, line); 01951 hashColor = PCB->NetlistLib.MenuN; 01952 01953 } 01954 01955 01956 void 01957 gsvit_fill_pcb_polygon (hidGC gc, PolygonType *poly, const BoxType *clip_box) 01958 { 01959 /* Hijack the fill_pcb_polygon function to get *poly, then proceed 01960 * with the default handler. 01961 */ 01962 struct gsvit_netlist *net; 01963 01964 net = gsvit_lookup_net_from_polygon (poly); 01965 01966 if (net) { 01967 hashColor = net->colorIndex; 01968 } 01969 else { 01970 hashColor = PCB->NetlistLib.MenuN; 01971 } 01972 01973 common_fill_pcb_polygon (gc, poly, clip_box); 01974 hashColor = PCB->NetlistLib.MenuN; 01975 } 01976 01977 01978 void 01979 gsvit_fill_pcb_pad (hidGC gc, PadType *pad, bool clear, bool mask) 01980 { 01981 struct gsvit_netlist *net = NULL; 01982 01983 net = gsvit_lookup_net_from_pad(pad); 01984 01985 if (net) { 01986 hashColor = net->colorIndex; 01987 } 01988 else { 01989 hashColor = PCB->NetlistLib.MenuN; 01990 } 01991 01992 common_fill_pcb_pad (gc, pad, clear, mask); 01993 hashColor = PCB->NetlistLib.MenuN; 01994 } 01995 01996 01997 void 01998 gsvit_fill_pcb_pv (hidGC fg_gc, hidGC bg_gc, PinType *pv, bool drawHole, bool mask) 01999 { 02000 struct gsvit_netlist *net = NULL; 02001 02002 net = gsvit_lookup_net_from_pv (pv); 02003 02004 if (net) { 02005 hashColor = net->colorIndex; 02006 } 02007 else { 02008 hashColor = PCB->NetlistLib.MenuN; 02009 } 02010 02011 common_fill_pcb_pv (fg_gc, bg_gc, pv, drawHole, mask); 02012 hashColor = PCB->NetlistLib.MenuN; 02013 } 02014 02015 02016 #include "dolists.h" 02017 02018 02019 void 02020 hid_gsvit_init () 02021 { 02022 memset (&gsvit_hid, 0, sizeof (HID)); 02023 memset (&gsvit_graphics, 0, sizeof (HID_DRAW)); 02024 02025 common_nogui_init (&gsvit_hid); 02026 common_draw_helpers_init (&gsvit_graphics); 02027 02028 //hid_gtk_init(); 02029 gsvit_hid.struct_size = sizeof (HID); 02030 gsvit_hid.name = "gsvit"; 02031 gsvit_hid.description = "Numerical analysis package export"; 02032 gsvit_hid.exporter = 1; 02033 gsvit_hid.poly_before = 1; 02034 02035 gsvit_hid.get_export_options = gsvit_get_export_options; 02036 gsvit_hid.do_export = gsvit_do_export; 02037 gsvit_hid.parse_arguments = gsvit_parse_arguments; 02038 gsvit_hid.set_layer = gsvit_set_layer; 02039 gsvit_hid.calibrate = gsvit_calibrate; 02040 gsvit_hid.set_crosshair = gsvit_set_crosshair; 02041 02042 gsvit_hid.graphics = &gsvit_graphics; 02043 02044 gsvit_graphics.make_gc = gsvit_make_gc; 02045 gsvit_graphics.destroy_gc = gsvit_destroy_gc; 02046 gsvit_graphics.use_mask = gsvit_use_mask; 02047 gsvit_graphics.set_color = gsvit_set_color; 02048 gsvit_graphics.set_line_cap = gsvit_set_line_cap; 02049 gsvit_graphics.set_line_width = gsvit_set_line_width; 02050 gsvit_graphics.set_draw_xor = gsvit_set_draw_xor; 02051 gsvit_graphics.set_draw_faded = gsvit_set_draw_faded; 02052 gsvit_graphics.draw_line = gsvit_draw_line; 02053 gsvit_graphics.draw_arc = gsvit_draw_arc; 02054 gsvit_graphics.draw_rect = gsvit_draw_rect; 02055 gsvit_graphics.fill_circle = gsvit_fill_circle; 02056 gsvit_graphics.fill_polygon = gsvit_fill_polygon; 02057 gsvit_graphics.fill_rect = gsvit_fill_rect; 02058 02059 /* Hijack these functions because what is passed to fill_polygon is a 02060 * series of polygons (for holes,...). 02061 */ 02062 gsvit_graphics.draw_pcb_line = gsvit_draw_pcb_line; 02063 gsvit_graphics.draw_pcb_arc = gsvit_draw_pcb_arc; 02064 gsvit_graphics.draw_pcb_polygon = gsvit_fill_pcb_polygon; 02065 02066 gsvit_graphics.fill_pcb_polygon = gsvit_fill_pcb_polygon; 02067 gsvit_graphics.fill_pcb_pad = gsvit_fill_pcb_pad; 02068 gsvit_graphics.fill_pcb_pv = gsvit_fill_pcb_pv; 02069 02070 hid_register_hid (&gsvit_hid); 02071 02072 #include "gsvit_lists.h" 02073 }