pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00041 #ifdef HAVE_CONFIG_H 00042 #include "config.h" 00043 #endif 00044 00045 #include "global.h" 00046 #include "hid_draw.h" 00047 00048 #include <time.h> 00049 #ifdef HAVE_UNISTD_H 00050 #include <unistd.h> 00051 #endif 00052 00053 #if defined(ENABLE_NLS) && defined(HAVE_LOCALE_H) 00054 #include <locale.h> 00055 #endif 00056 00057 #include "data.h" 00058 #include "draw.h" 00059 #include "drill.h" 00060 #include "file.h" 00061 #include "find.h" 00062 #include "error.h" 00063 #include "misc.h" 00064 #include "print.h" 00065 #include "polygon.h" 00066 #include "rtree.h" 00067 #include "search.h" 00068 00069 #include "hid.h" 00070 00071 #ifdef HAVE_LIBDMALLOC 00072 #include <dmalloc.h> 00073 #endif 00074 00075 /* --------------------------------------------------------------------------- 00076 * prints a FAB drawing. 00077 */ 00078 00079 #define TEXT_SIZE MIL_TO_COORD(150) 00080 #define TEXT_LINE MIL_TO_COORD(150) 00081 #define DRILL_MARK_SIZE MIL_TO_COORD(16) 00082 #define FAB_LINE_W MIL_TO_COORD(8) 00083 00084 static void 00085 fab_line (hidGC gc, int x1, int y1, int x2, int y2) 00086 { 00087 gui->graphics->draw_line (gc, x1, y1, x2, y2); 00088 } 00089 00090 static void 00091 fab_circle (hidGC gc, int x, int y, int r) 00092 { 00093 gui->graphics->draw_arc (gc, x, y, r, r, 0, 180); 00094 gui->graphics->draw_arc (gc, x, y, r, r, 180, 180); 00095 } 00096 00102 static void 00103 text_at (hidGC gc, int x, int y, int align, char *fmt, ...) 00104 { 00105 char tmp[512]; 00106 int w = 0, i; 00107 TextType t; 00108 va_list a; 00109 FontType *font = &PCB->Font; 00110 va_start (a, fmt); 00111 vsprintf (tmp, fmt, a); 00112 va_end (a); 00113 t.Direction = 0; 00114 t.TextString = tmp; 00115 t.Scale = COORD_TO_MIL(TEXT_SIZE); /* pcnt of 100mil base height */ 00116 t.Flags = NoFlags (); 00117 t.X = x; 00118 t.Y = y; 00119 for (i = 0; tmp[i]; i++) 00120 w += 00121 (font->Symbol[(int) tmp[i]].Width + font->Symbol[(int) tmp[i]].Delta); 00122 w = SCALE_TEXT (w, t.Scale); 00123 t.X -= w * (align & 3) / 2; 00124 if (t.X < 0) 00125 t.X = 0; 00126 gui->graphics->draw_pcb_text (gc, &t, 0); 00127 if (align & 8) 00128 fab_line (gc, t.X, 00129 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10), 00130 t.X + w, 00131 t.Y + SCALE_TEXT (font->MaxHeight, t.Scale) + MIL_TO_COORD(10)); 00132 } 00133 00139 static void 00140 drill_sym (hidGC gc, int idx, int x, int y) 00141 { 00142 int type = idx % 5; 00143 int size = idx / 5; 00144 int s2 = (size + 1) * DRILL_MARK_SIZE; 00145 int i; 00146 switch (type) 00147 { 00148 case 0: /* Y */ ; 00149 fab_line (gc, x, y, x, y + s2); 00150 fab_line (gc, x, y, x + s2 * 13 / 15, y - s2 / 2); 00151 fab_line (gc, x, y, x - s2 * 13 / 15, y - s2 / 2); 00152 for (i = 1; i <= size; i++) 00153 fab_circle (gc, x, y, i * DRILL_MARK_SIZE); 00154 break; 00155 case 1: /* + */ 00156 ; 00157 fab_line (gc, x, y - s2, x, y + s2); 00158 fab_line (gc, x - s2, y, x + s2, y); 00159 for (i = 1; i <= size; i++) 00160 { 00161 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00162 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE); 00163 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00164 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00165 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE, 00166 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00167 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00168 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00169 } 00170 break; 00171 case 2: /* X */ ; 00172 fab_line (gc, x - s2 * 3 / 4, y - s2 * 3 / 4, x + s2 * 3 / 4, 00173 y + s2 * 3 / 4); 00174 fab_line (gc, x - s2 * 3 / 4, y + s2 * 3 / 4, x + s2 * 3 / 4, 00175 y - s2 * 3 / 4); 00176 for (i = 1; i <= size; i++) 00177 { 00178 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00179 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE); 00180 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00181 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00182 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE, 00183 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00184 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00185 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00186 } 00187 break; 00188 case 3: /* circle */ ; 00189 for (i = 0; i <= size; i++) 00190 fab_circle (gc, x, y, (i + 1) * DRILL_MARK_SIZE - DRILL_MARK_SIZE / 2); 00191 break; 00192 case 4: /* square */ 00193 for (i = 1; i <= size + 1; i++) 00194 { 00195 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00196 x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE); 00197 fab_line (gc, x - i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00198 x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00199 fab_line (gc, x - i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE, 00200 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00201 fab_line (gc, x + i * DRILL_MARK_SIZE, y - i * DRILL_MARK_SIZE, 00202 x + i * DRILL_MARK_SIZE, y + i * DRILL_MARK_SIZE); 00203 } 00204 break; 00205 } 00206 } 00207 00208 static int 00209 count_drill_lines (DrillInfoType *AllDrills) 00210 { 00211 int n, ds = 0; 00212 for (n = AllDrills->DrillN - 1; n >= 0; n--) 00213 { 00214 DrillType *drill = &(AllDrills->Drill[n]); 00215 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount) 00216 ds++; 00217 if (drill->UnplatedCount) 00218 ds++; 00219 } 00220 return ds; 00221 } 00222 00223 00224 int 00225 PrintFab_overhang (void) 00226 { 00227 DrillInfoType *AllDrills = GetDrillInfo (PCB->Data); 00228 int ds = count_drill_lines (AllDrills); 00229 if (ds < 4) 00230 ds = 4; 00231 return (ds + 2) * TEXT_LINE; 00232 } 00233 00234 void 00235 PrintFab (hidGC gc) 00236 { 00237 DrillInfoType *AllDrills; 00238 int i, n, yoff, total_drills = 0, ds = 0; 00239 time_t currenttime; 00240 const char *utcFmt = "%c UTC"; 00241 char utcTime[64]; 00242 #ifdef ENABLE_NLS 00243 char *oldlocale; 00244 #endif 00245 AllDrills = GetDrillInfo (PCB->Data); 00246 yoff = -TEXT_LINE; 00247 00248 /* count how many drill description lines will be needed */ 00249 ds = count_drill_lines (AllDrills); 00250 00251 /* 00252 * When we only have a few drill sizes we need to make sure the 00253 * drill table header doesn't fall on top of the board info 00254 * section. 00255 */ 00256 if (ds < 4) 00257 { 00258 yoff -= (4 - ds) * TEXT_LINE; 00259 } 00260 00261 gui->graphics->set_line_width (gc, FAB_LINE_W); 00262 00263 for (n = AllDrills->DrillN - 1; n >= 0; n--) 00264 { 00265 int plated_sym = -1, unplated_sym = -1; 00266 DrillType *drill = &(AllDrills->Drill[n]); 00267 if (drill->PinCount + drill->ViaCount > drill->UnplatedCount) 00268 plated_sym = --ds; 00269 if (drill->UnplatedCount) 00270 unplated_sym = --ds; 00271 gui->graphics->set_color (gc, PCB->PinColor); 00272 for (i = 0; i < drill->PinN; i++) 00273 drill_sym (gc, TEST_FLAG (HOLEFLAG, drill->Pin[i]) ? 00274 unplated_sym : plated_sym, drill->Pin[i]->X, 00275 drill->Pin[i]->Y); 00276 if (plated_sym != -1) 00277 { 00278 drill_sym (gc, plated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4); 00279 text_at (gc, MIL_TO_COORD(1350), yoff, MIL_TO_COORD(2), "YES"); 00280 text_at (gc, MIL_TO_COORD(980), yoff, MIL_TO_COORD(2), "%d", 00281 drill->PinCount + drill->ViaCount - drill->UnplatedCount); 00282 00283 if (unplated_sym != -1) 00284 yoff -= TEXT_LINE; 00285 } 00286 if (unplated_sym != -1) 00287 { 00288 drill_sym (gc, unplated_sym, TEXT_SIZE, yoff + TEXT_SIZE / 4); 00289 text_at (gc, MIL_TO_COORD(1400), yoff, MIL_TO_COORD(2), "NO"); 00290 text_at (gc, MIL_TO_COORD(980), yoff, MIL_TO_COORD(2), "%d", drill->UnplatedCount); 00291 } 00292 gui->graphics->set_color (gc, PCB->ElementColor); 00293 text_at (gc, MIL_TO_COORD(450), yoff, MIL_TO_COORD(2), "%0.3f", 00294 COORD_TO_INCH(drill->DrillSize)); 00295 if (plated_sym != -1 && unplated_sym != -1) 00296 text_at (gc, MIL_TO_COORD(450), yoff + TEXT_LINE, MIL_TO_COORD(2), "%0.3f", 00297 COORD_TO_INCH(drill->DrillSize)); 00298 yoff -= TEXT_LINE; 00299 total_drills += drill->PinCount; 00300 total_drills += drill->ViaCount; 00301 } 00302 00303 gui->graphics->set_color (gc, PCB->ElementColor); 00304 text_at (gc, 0, yoff, MIL_TO_COORD(9), "Symbol"); 00305 text_at (gc, MIL_TO_COORD(410), yoff, MIL_TO_COORD(9), "Diam. (Inch)"); 00306 text_at (gc, MIL_TO_COORD(950), yoff, MIL_TO_COORD(9), "Count"); 00307 text_at (gc, MIL_TO_COORD(1300), yoff, MIL_TO_COORD(9), "Plated?"); 00308 yoff -= TEXT_LINE; 00309 text_at (gc, 0, yoff, 0, 00310 "There are %d different drill sizes used in this layout, %d holes total", 00311 AllDrills->DrillN, total_drills); 00312 /* Create a portable timestamp. */ 00313 #ifdef ENABLE_NLS 00314 oldlocale = setlocale (LC_TIME, "C"); 00315 #endif 00316 currenttime = time (NULL); 00317 strftime (utcTime, sizeof utcTime, utcFmt, gmtime (¤ttime)); 00318 #ifdef ENABLE_NLS 00319 setlocale (LC_TIME, oldlocale); 00320 #endif 00321 00322 yoff = -TEXT_LINE; 00323 for (i = 0; i < max_copper_layer; i++) 00324 { 00325 LayerType *l = LAYER_PTR (i); 00326 if (l->Name && (l->LineN || l->ArcN)) 00327 { 00328 if (strcmp ("route", l->Name) == 0) 00329 break; 00330 if (strcmp ("outline", l->Name) == 0) 00331 break; 00332 } 00333 } 00334 if (i == max_copper_layer) 00335 { 00336 gui->graphics->set_line_width (gc, MIL_TO_COORD(10)); 00337 gui->graphics->draw_line (gc, 0, 0, PCB->MaxWidth, 0); 00338 gui->graphics->draw_line (gc, 0, 0, 0, PCB->MaxHeight); 00339 gui->graphics->draw_line (gc, PCB->MaxWidth, 0, PCB->MaxWidth, 00340 PCB->MaxHeight); 00341 gui->graphics->draw_line (gc, 0, PCB->MaxHeight, PCB->MaxWidth, 00342 PCB->MaxHeight); 00343 /*FPrintOutline (); */ 00344 gui->graphics->set_line_width (gc, FAB_LINE_W); 00345 text_at (gc, MIL_TO_COORD(2000), yoff, 0, 00346 "Maximum Dimensions: %f mils wide, %f mils high", 00347 COORD_TO_MIL(PCB->MaxWidth), COORD_TO_MIL(PCB->MaxHeight)); 00348 text_at (gc, PCB->MaxWidth / 2, PCB->MaxHeight + MIL_TO_COORD(20), 1, 00349 "Board outline is the centerline of this %f mil" 00350 " rectangle - 0,0 to %f,%f mils", 00351 COORD_TO_MIL(FAB_LINE_W), COORD_TO_MIL(PCB->MaxWidth), COORD_TO_MIL(PCB->MaxHeight)); 00352 } 00353 else 00354 { 00355 LayerType *layer = LAYER_PTR (i); 00356 gui->graphics->set_line_width (gc, MIL_TO_COORD(10)); 00357 LINE_LOOP (layer); 00358 { 00359 gui->graphics->draw_line (gc, line->Point1.X, line->Point1.Y, 00360 line->Point2.X, line->Point2.Y); 00361 } 00362 END_LOOP; 00363 ARC_LOOP (layer); 00364 { 00365 gui->graphics->draw_arc (gc, arc->X, arc->Y, arc->Width, 00366 arc->Height, arc->StartAngle, arc->Delta); 00367 } 00368 END_LOOP; 00369 TEXT_LOOP (layer); 00370 { 00371 gui->graphics->draw_pcb_text (gc, text, 0); 00372 } 00373 END_LOOP; 00374 gui->graphics->set_line_width (gc, FAB_LINE_W); 00375 text_at (gc, PCB->MaxWidth / 2, PCB->MaxHeight + MIL_TO_COORD(20), 1, 00376 "Board outline is the centerline of this path"); 00377 } 00378 yoff -= TEXT_LINE; 00379 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime); 00380 yoff -= TEXT_LINE; 00381 text_at (gc, MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author ()); 00382 yoff -= TEXT_LINE; 00383 text_at (gc, MIL_TO_COORD(2000), yoff, 0, 00384 "Title: %s - Fabrication Drawing", UNKNOWN (PCB->Name)); 00385 }