static int info (int argc, char **argv, Coord x, Coord y) { int i, j; int cg, sg; if (!PCB || !PCB->Data || !PCB->Filename) { printf("No PCB loaded.\n"); return 0; } printf("Filename: %s\n", PCB->Filename); pcb_printf("Size: %ml x %ml mils, %mm x %mm mm\n", PCB->MaxWidth, PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight); cg = GetLayerGroupNumberByNumber (component_silk_layer); sg = GetLayerGroupNumberByNumber (solder_silk_layer); for (i=0; i<MAX_LAYER; i++) { int lg = GetLayerGroupNumberByNumber (i); for (j=0; j<MAX_LAYER; j++) putchar(j==lg ? '#' : '-'); printf(" %c %s\n", lg==cg ? 'c' : lg==sg ? 's' : '-', PCB->Data->Layer[i].Name); } return 0; }
/* --------------------------------------------------------------------------- * Draws pins pads and vias - Always draws for non-gui HIDs, * otherwise drawing depends on PCB->PinOn and PCB->ViaOn */ static void DrawPPV (int group, const BoxType *drawn_area) { int component_group = GetLayerGroupNumberByNumber (component_silk_layer); int solder_group = GetLayerGroupNumberByNumber (solder_silk_layer); int side; if (PCB->PinOn || !gui->gui) { /* draw element pins */ r_search (PCB->Data->pin_tree, drawn_area, NULL, pin_callback, NULL); /* draw element pads */ if (group == component_group) { side = COMPONENT_LAYER; r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side); } if (group == solder_group) { side = SOLDER_LAYER; r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side); } } /* draw vias */ if (PCB->ViaOn || !gui->gui) { r_search (PCB->Data->via_tree, drawn_area, NULL, via_callback, NULL); r_search (PCB->Data->via_tree, drawn_area, NULL, hole_callback, NULL); } if (PCB->PinOn || doing_assy) r_search (PCB->Data->pin_tree, drawn_area, NULL, hole_callback, NULL); }
/* --------------------------------------------------------------------------- * Update the X, Y and group position information stored in the NetList after * elements have possibly been moved, rotated, flipped, etc. */ static void UpdateXY (NetListTypePtr Nets) { Cardinal SLayer, CLayer; Cardinal i, j; /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); /* update all nets */ for (i = 0; i < Nets->NetN; i++) { for (j = 0; j < Nets->Net[i].ConnectionN; j++) { ConnectionTypePtr c = &(Nets->Net[i].Connection[j]); switch (c->type) { case PAD_TYPE: c->group = TEST_FLAG (ONSOLDERFLAG, (ElementTypePtr) c->ptr1) ? SLayer : CLayer; c->X = ((PadTypePtr) c->ptr2)->Point1.X; c->Y = ((PadTypePtr) c->ptr2)->Point1.Y; break; case PIN_TYPE: c->group = SLayer; /* any layer will do */ c->X = ((PinTypePtr) c->ptr2)->X; c->Y = ((PinTypePtr) c->ptr2)->Y; break; default: Message ("Odd connection type encountered in " "UpdateXY"); break; } } } }
static int LastLayerInComponentGroup (int layer) { int cgroup = GetLayerGroupNumberByNumber(max_group + COMPONENT_LAYER); int lgroup = GetLayerGroupNumberByNumber(layer); if (cgroup == lgroup && PCB->LayerGroups.Number[lgroup] == 2) return 1; return 0; }
static int LastLayerInSolderGroup (int layer) { int sgroup = GetLayerGroupNumberByNumber(max_group + SOLDER_LAYER); int lgroup = GetLayerGroupNumberByNumber(layer); if (sgroup == lgroup && PCB->LayerGroups.Number[lgroup] == 2) return 1; return 0; }
/* Very similar to layer_type_to_file_name() but appends only a three-character suffix compatible with Eagle's defaults. */ static void assign_eagle_file_suffix (char *dest, int idx) { int group; int nlayers; char *suff = "out"; switch (idx) { case SL (SILK, TOP): suff = "plc"; break; case SL (SILK, BOTTOM): suff = "pls"; break; case SL (MASK, TOP): suff = "stc"; break; case SL (MASK, BOTTOM): suff = "sts"; break; case SL (PDRILL, 0): suff = "drd"; break; case SL (UDRILL, 0): suff = "dru"; break; case SL (PASTE, TOP): suff = "crc"; break; case SL (PASTE, BOTTOM): suff = "crs"; break; case SL (INVISIBLE, 0): suff = "inv"; break; case SL (FAB, 0): suff = "fab"; break; case SL (ASSY, TOP): suff = "ast"; break; case SL (ASSY, BOTTOM): suff = "asb"; break; default: group = GetLayerGroupNumberByNumber(idx); nlayers = PCB->LayerGroups.Number[group]; if (group == GetLayerGroupNumberByNumber(component_silk_layer)) { suff = "cmp"; } else if (group == GetLayerGroupNumberByNumber(solder_silk_layer)) { suff = "sol"; } else if (nlayers == 1 && (strcmp (PCB->Data->Layer[idx].Name, "route") == 0 || strcmp (PCB->Data->Layer[idx].Name, "outline") == 0)) { suff = "oln"; } else { static char buf[20]; sprintf (buf, "ly%d", group); suff = buf; } break; } strcpy (dest, suff); }
const char * layer_type_to_file_name (int idx) { int group; switch (idx) { case SL (SILK, TOP): return "frontsilk"; case SL (SILK, BOTTOM): return "backsilk"; case SL (MASK, TOP): return "frontmask"; case SL (MASK, BOTTOM): return "backmask"; case SL (PDRILL, 0): return "plated-drill"; case SL (UDRILL, 0): return "unplated-drill"; case SL (PASTE, TOP): return "frontpaste"; case SL (PASTE, BOTTOM): return "backpaste"; case SL (INVISIBLE, 0): return "invisible"; case SL (FAB, 0): return "fab"; case SL (ASSY, TOP): return "frontassembly"; case SL (ASSY, BOTTOM): return "backassembly"; default: group = GetLayerGroupNumberByNumber(idx); if (group == GetLayerGroupNumberByNumber(component_silk_layer)) return "front"; else if (group == GetLayerGroupNumberByNumber(solder_silk_layer)) return "back"; else if (PCB->LayerGroups.Number[group] == 1 && (strcmp (PCB->Data->Layer[idx].Name, "route") == 0 || strcmp (PCB->Data->Layer[idx].Name, "outline") == 0)) return "outline"; else { static char buf[20]; sprintf (buf, "group%d", group); return buf; } break; } }
/* --------------------------------------------------------------------------- * checks all visible lines which belong to the same layergroup as the * passed pad. If one of the endpoints of the line lays inside the pad, * the line is added to the 'rubberband' list */ static void CheckPadForRubberbandConnection (PadTypePtr Pad) { BDimension half = Pad->Thickness / 2; Cardinal i, group; struct rubber_info info; info.box.X1 = MIN (Pad->Point1.X, Pad->Point2.X) - half; info.box.Y1 = MIN (Pad->Point1.Y, Pad->Point2.Y) - half; info.box.X2 = MAX (Pad->Point1.X, Pad->Point2.X) + half; info.box.Y2 = MAX (Pad->Point1.Y, Pad->Point2.Y) + half; info.radius = 0; info.line = NULL; i = TEST_FLAG (ONSOLDERFLAG, Pad) ? solder_silk_layer : component_silk_layer; group = GetLayerGroupNumberByNumber (i); /* check all visible layers in the same group */ GROUP_LOOP (PCB->Data, group); { /* check all visible lines of the group member */ info.layer = layer; if (info.layer->On) { r_search (info.layer->line_tree, &info.box, NULL, rubber_callback, &info); } } END_LOOP; }
/* --------------------------------------------------------------------------- * moves a text object between layers; lowlevel routines */ static void * MoveTextToLayerLowLevel (LayerType *Source, TextType *text, LayerType *Destination) { RestoreToPolygon (PCB->Data, TEXT_TYPE, Source, text); r_delete_entry (Source->text_tree, (BoxType *)text); Source->Text = g_list_remove (Source->Text, text); Source->TextN --; Destination->Text = g_list_append (Destination->Text, text); Destination->TextN ++; if (GetLayerGroupNumberByNumber (solder_silk_layer) == GetLayerGroupNumberByPointer (Destination)) SET_FLAG (ONSOLDERFLAG, text); else CLEAR_FLAG (ONSOLDERFLAG, text); /* re-calculate the bounding box (it could be mirrored now) */ SetTextBoundingBox (&PCB->Font, text); if (!Destination->text_tree) Destination->text_tree = r_create_tree (NULL, 0, 0); r_insert_entry (Destination->text_tree, (BoxType *)text, 0); ClearFromPolygon (PCB->Data, TEXT_TYPE, Destination, text); return text; }
static int info (int argc, char **argv, Coord x, Coord y) { int i, j; int top_group, bottom_group; if (!PCB || !PCB->Data || !PCB->Filename) { printf("No PCB loaded.\n"); return 0; } printf("Filename: %s\n", PCB->Filename); pcb_printf("Size: %ml x %ml mils, %mm x %mm mm\n", PCB->MaxWidth, PCB->MaxHeight, PCB->MaxWidth, PCB->MaxHeight); top_group = GetLayerGroupNumberBySide (TOP_SIDE); bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); for (i=0; i<MAX_LAYER; i++) { int lg = GetLayerGroupNumberByNumber (i); for (j = 0; j < MAX_GROUP; j++) putchar(j==lg ? '#' : '-'); printf(" %c %s\n", lg == top_group ? 'c' : lg == bottom_group ? 's' : '-', PCB->Data->Layer[i].Name); } return 0; }
static int group_for_layer (int l) { if (l < max_copper_layer + 2 && l >= 0) return GetLayerGroupNumberByNumber (l); /* else something unique */ return max_group + 3 + l; }
void PrintAssembly (int side, const BoxType * drawn_area) { int side_group = GetLayerGroupNumberByNumber (max_copper_layer + side); doing_assy = true; gui->graphics->set_draw_faded (Output.fgGC, 1); DrawLayerGroup (side_group, drawn_area); gui->graphics->set_draw_faded (Output.fgGC, 0); /* draw package */ DrawSilk (side, drawn_area); doing_assy = false; }
static void CheckPadForRat (PadTypePtr Pad) { struct rinfo info; Cardinal i; i = TEST_FLAG (ONSOLDERFLAG, Pad) ? solder_silk_layer : component_silk_layer; info.group = GetLayerGroupNumberByNumber (i); info.pad = Pad; info.type = PAD_TYPE; r_search (PCB->Data->rat_tree, &Pad->BoundingBox, NULL, rat_callback, &info); }
static void layer_button_callback (Widget w, int layer, XmPushButtonCallbackStruct * pbcs) { int l, set; switch (layer) { case LB_SILK: set = PCB->ElementOn = !PCB->ElementOn; PCB->Data->SILKLAYER.On = set; PCB->Data->BACKSILKLAYER.On = set; break; case LB_RATS: set = PCB->RatOn = !PCB->RatOn; break; case LB_PINS: set = PCB->PinOn = !PCB->PinOn; break; case LB_VIAS: set = PCB->ViaOn = !PCB->ViaOn; break; case LB_BACK: set = PCB->InvisibleObjectsOn = !PCB->InvisibleObjectsOn; break; case LB_MASK: TOGGLE_FLAG (SHOWMASKFLAG, PCB); set = TEST_FLAG (SHOWMASKFLAG, PCB); break; default: /* layers */ set = PCB->Data->Layer[layer].On = !PCB->Data->Layer[layer].On; break; } show_one_layer_button (layer, set); if (layer < max_copper_layer) { int i; int group = GetLayerGroupNumberByNumber (layer); for (i = 0; i < PCB->LayerGroups.Number[group]; i++) { l = PCB->LayerGroups.Entries[group][i]; if (l != layer && l < max_copper_layer) { show_one_layer_button (l, set); PCB->Data->Layer[l].On = set; } } } lesstif_invalidate_all (); }
NetListTypePtr ProcNetlist (LibraryTypePtr net_menu) { ConnectionTypePtr connection; ConnectionType LastPoint; NetTypePtr net; static NetListTypePtr Wantlist = NULL; if (!net_menu->MenuN) return (NULL); FreeNetListMemory (Wantlist); SaveFree (Wantlist); /* MYFREE (Wantlist); *//* awkward */ badnet = false; /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); Wantlist = MyCalloc (1, sizeof (NetListType), "ProcNetlist()"); if (Wantlist) { ALLPIN_LOOP (PCB->Data); { pin->Spare = NULL; CLEAR_FLAG (DRCFLAG, pin); } ENDALL_LOOP; ALLPAD_LOOP (PCB->Data); { pad->Spare = NULL; CLEAR_FLAG (DRCFLAG, pad); } ENDALL_LOOP; MENU_LOOP (net_menu); { if (menu->Name[0] == '*' || menu->flag == 0) { badnet = true; continue; } net = GetNetMemory (Wantlist); if (menu->Style) { STYLE_LOOP (PCB); { if (style->Name && !NSTRCMP (style->Name, menu->Style)) { net->Style = style; break; } } END_LOOP; } else /* default to NULL if none found */ net->Style = NULL; ENTRY_LOOP (menu); { if (SeekPad (entry, &LastPoint, false)) { if (TEST_FLAG (DRCFLAG, (PinTypePtr) LastPoint.ptr2)) Message (_ ("Error! Element %s pin %s appears multiple times in the netlist file.\n"), NAMEONPCB_NAME ((ElementTypePtr) LastPoint.ptr1), (LastPoint.type == PIN_TYPE) ? ((PinTypePtr) LastPoint.ptr2)-> Number : ((PadTypePtr) LastPoint.ptr2)->Number); else { connection = GetConnectionMemory (net); *connection = LastPoint; /* indicate expect net */ connection->menu = menu; /* mark as visited */ SET_FLAG (DRCFLAG, (PinTypePtr) LastPoint.ptr2); if (LastPoint.type == PIN_TYPE) ((PinTypePtr) LastPoint.ptr2)->Spare = (void *) menu; else ((PadTypePtr) LastPoint.ptr2)->Spare = (void *) menu; } } else badnet = true; /* check for more pins with the same number */ for (; SeekPad (entry, &LastPoint, true);) { connection = GetConnectionMemory (net); *connection = LastPoint; /* indicate expect net */ connection->menu = menu; /* mark as visited */ SET_FLAG (DRCFLAG, (PinTypePtr) LastPoint.ptr2); if (LastPoint.type == PIN_TYPE) ((PinTypePtr) LastPoint.ptr2)->Spare = (void *) menu; else ((PadTypePtr) LastPoint.ptr2)->Spare = (void *) menu; } } END_LOOP; } END_LOOP; } /* clear all visit marks */ ALLPIN_LOOP (PCB->Data); { CLEAR_FLAG (DRCFLAG, pin); } ENDALL_LOOP; ALLPAD_LOOP (PCB->Data); { CLEAR_FLAG (DRCFLAG, pad); } ENDALL_LOOP; return (Wantlist); }
/* --------------------------------------------------------------------------- * recalculates the passed coordinates to fit the current grid setting */ void FitCrosshairIntoGrid (LocationType X, LocationType Y) { LocationType x2, y2, x0, y0; void *ptr1, *ptr2, *ptr3; float nearest, sq_dist; int ans; x0 = 0; y0 = 0; x2 = PCB->MaxWidth; y2 = PCB->MaxHeight; Crosshair.X = MIN (Crosshair.MaxX, MAX (Crosshair.MinX, X)); Crosshair.Y = MIN (Crosshair.MaxY, MAX (Crosshair.MinY, Y)); if (PCB->RatDraw) { x0 = -600; y0 = -600; } else { /* check if new position is inside the output window * This might not be true after the window has been resized. * In this case we just set it to the center of the window or * with respect to the grid (if possible) */ if (Crosshair.X < x0 || Crosshair.X > x2) { if (x2 + 1 >= PCB->Grid) /* there must be a point that matches the grid * so we just have to look for it with some integer * calculations */ x0 = GRIDFIT_X (PCB->Grid, PCB->Grid); else x0 = (x2) / 2; } else /* check if the new position matches the grid */ x0 = GRIDFIT_X (Crosshair.X, PCB->Grid); /* do the same for the second coordinate */ if (Crosshair.Y < y0 || Crosshair.Y > y2) { if (y2 + 1 >= PCB->Grid) y0 = GRIDFIT_Y (PCB->Grid, PCB->Grid); else y0 = (y2) / 2; } else y0 = GRIDFIT_Y (Crosshair.Y, PCB->Grid); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { int dx = Crosshair.X - Marked.X; int dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) y0 = Marked.Y; else x0 = Marked.X; } } nearest = -1; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PAD_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; /* Avoid self-snapping when moving */ if (ans && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans && (Settings.Mode == LINE_MODE || (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE))) { PadTypePtr pad = (PadTypePtr) ptr2; LayerType *desired_layer; Cardinal desired_group; Cardinal SLayer, CLayer; int found_our_layer = false; desired_layer = CURRENT; if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE) { desired_layer = (LayerType *)Crosshair.AttachedObject.Ptr1; } /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); desired_group = TEST_FLAG (ONSOLDERFLAG, pad) ? SLayer : CLayer; GROUP_LOOP (PCB->Data, desired_group); { if (layer == desired_layer) { found_our_layer = true; break; } } END_LOOP; if (found_our_layer == false) ans = NO_TYPE; } if (ans) { PadTypePtr pad = (PadTypePtr) ptr2; LocationType px, py; px = (pad->Point1.X + pad->Point2.X) / 2; py = (pad->Point1.Y + pad->Point2.Y) / 2; sq_dist = SQUARE (px - Crosshair.X) + SQUARE (py - Crosshair.Y); if (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist) { x0 = px; y0 = py; nearest = sq_dist; } } if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PIN_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; /* Avoid self-snapping when moving */ if (ans && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans) { PinTypePtr pin = (PinTypePtr) ptr2; sq_dist = SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pin->X; y0 = pin->Y; nearest = sq_dist; } } if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, VIA_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; /* Avoid snapping vias to any other vias */ if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == VIA_TYPE) { if (ans & PIN_TYPES) ans = NO_TYPE; } if (ans) { PinTypePtr pin = (PinTypePtr) ptr2; sq_dist = SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pin->X; y0 = pin->Y; nearest = sq_dist; } } if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; if (ans) { PointTypePtr pnt = (PointTypePtr) ptr3; sq_dist = SQUARE (pnt->X - Crosshair.X) + SQUARE (pnt->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pnt->X; y0 = pnt->Y; nearest = sq_dist; } } if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, POLYGONPOINT_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; if (ans) { PointTypePtr pnt = (PointTypePtr) ptr3; sq_dist = SQUARE (pnt->X - Crosshair.X) + SQUARE (pnt->Y - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && (!gui->shift_is_pressed() || SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)) { x0 = pnt->X; y0 = pnt->Y; nearest = sq_dist; } } if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2, &ptr3); else ans = NO_TYPE; if (ans & ELEMENT_TYPE) { ElementTypePtr el = (ElementTypePtr) ptr1; sq_dist = SQUARE (el->MarkX - Crosshair.X) + SQUARE (el->MarkY - Crosshair.Y); if ((nearest == -1 || sq_dist < nearest) && SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist) { x0 = el->MarkX; y0 = el->MarkY; nearest = sq_dist; } } if (x0 >= 0 && y0 >= 0) { Crosshair.X = x0; Crosshair.Y = y0; } if (Settings.Mode == ARROW_MODE) { ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }
static void gerber_do_export (HID_Attr_Val * options) { const char *fnbase; int i; static int saved_layer_stack[MAX_LAYER]; int save_ons[MAX_LAYER + 2]; FlagType save_thindraw; save_thindraw = PCB->Flags; CLEAR_FLAG(THINDRAWFLAG, PCB); CLEAR_FLAG(THINDRAWPOLYFLAG, PCB); CLEAR_FLAG(CHECKPLANESFLAG, PCB); if (!options) { gerber_get_export_options (NULL); for (i = 0; i < NUM_OPTIONS; i++) gerber_values[i] = gerber_options[i].default_val; options = gerber_values; } fnbase = options[HA_gerberfile].str_value; if (!fnbase) fnbase = "pcb-out"; verbose = options[HA_verbose].int_value; metric = options[HA_metric].int_value; if (metric) { x_convspec = "X%.0mu"; y_convspec = "Y%.0mu"; } else { x_convspec = "X%.0mc"; y_convspec = "Y%.0mc"; } all_layers = options[HA_all_layers].int_value; copy_outline_mode = options[HA_copy_outline].int_value; name_style = options[HA_name_style].int_value; outline_layer = NULL; for (i = 0; i < max_copper_layer; i++) { LayerType *layer = PCB->Data->Layer + i; if (strcmp (layer->Name, "outline") == 0 || strcmp (layer->Name, "route") == 0) { outline_layer = layer; } } i = strlen (fnbase); filename = (char *)realloc (filename, i + 40); strcpy (filename, fnbase); strcat (filename, "."); filesuff = filename + strlen (filename); if (all_layers) { memset (print_group, 1, sizeof (print_group)); memset (print_layer, 1, sizeof (print_layer)); } else { memset (print_group, 0, sizeof (print_group)); memset (print_layer, 0, sizeof (print_layer)); } hid_save_and_show_layer_ons (save_ons); for (i = 0; i < max_copper_layer; i++) { LayerType *layer = PCB->Data->Layer + i; if (layer->LineN || layer->TextN || layer->ArcN || layer->PolygonN) print_group[GetLayerGroupNumberByNumber (i)] = 1; } print_group[GetLayerGroupNumberByNumber (solder_silk_layer)] = 1; print_group[GetLayerGroupNumberByNumber (component_silk_layer)] = 1; for (i = 0; i < max_copper_layer; i++) if (print_group[GetLayerGroupNumberByNumber (i)]) print_layer[i] = 1; memcpy (saved_layer_stack, LayerStack, sizeof (LayerStack)); qsort (LayerStack, max_copper_layer, sizeof (LayerStack[0]), layer_sort); linewidth = -1; lastcap = -1; lastgroup = -1; region.X1 = 0; region.Y1 = 0; region.X2 = PCB->MaxWidth; region.Y2 = PCB->MaxHeight; pagecount = 1; resetApertures (); lastgroup = -1; layer_list_idx = 0; finding_apertures = 1; hid_expose_callback (&gerber_hid, ®ion, 0); layer_list_idx = 0; finding_apertures = 0; hid_expose_callback (&gerber_hid, ®ion, 0); memcpy (LayerStack, saved_layer_stack, sizeof (LayerStack)); maybe_close_f (f); f = NULL; hid_restore_layer_ons (save_ons); PCB->Flags = save_thindraw; }
/* These next two functions moved from the original netlist.c as part of the | gui code separation for the Gtk port. */ RatTypePtr AddNet (void) { static int ratDrawn = 0; char name1[256], *name2; Cardinal group1, group2; char ratname[20]; int found; void *ptr1, *ptr2, *ptr3; LibraryMenuTypePtr menu; LibraryEntryTypePtr entry; if (Crosshair.AttachedLine.Point1.X == Crosshair.AttachedLine.Point2.X && Crosshair.AttachedLine.Point1.Y == Crosshair.AttachedLine.Point2.Y) return (NULL); found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.AttachedLine.Point1.X, Crosshair.AttachedLine.Point1.Y, 5); if (found == NO_TYPE) { Message (_("No pad/pin under rat line\n")); return (NULL); } if (NAMEONPCB_NAME ((ElementTypePtr) ptr1) == NULL || *NAMEONPCB_NAME ((ElementTypePtr) ptr1) == 0) { Message (_("You must name the starting element first\n")); return (NULL); } /* will work for pins to since the FLAG is common */ group1 = (TEST_FLAG (ONSOLDERFLAG, (PadTypePtr) ptr2) ? GetLayerGroupNumberByNumber (solder_silk_layer) : GetLayerGroupNumberByNumber (component_silk_layer)); strcpy (name1, ConnectionName (found, ptr1, ptr2)); found = SearchObjectByLocation (PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3, Crosshair.AttachedLine.Point2.X, Crosshair.AttachedLine.Point2.Y, 5); if (found == NO_TYPE) { Message (_("No pad/pin under rat line\n")); return (NULL); } if (NAMEONPCB_NAME ((ElementTypePtr) ptr1) == NULL || *NAMEONPCB_NAME ((ElementTypePtr) ptr1) == 0) { Message (_("You must name the ending element first\n")); return (NULL); } group2 = (TEST_FLAG (ONSOLDERFLAG, (PadTypePtr) ptr2) ? GetLayerGroupNumberByNumber (solder_silk_layer) : GetLayerGroupNumberByNumber (component_silk_layer)); name2 = ConnectionName (found, ptr1, ptr2); menu = netnode_to_netname (name1); if (menu) { if (netnode_to_netname (name2)) { Message (_ ("Both connections already in netlist - cannot merge nets\n")); return (NULL); } entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name2); netnode_to_netname (name2); goto ratIt; } /* ok, the first name did not belong to a net */ menu = netnode_to_netname (name2); if (menu) { entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name1); netnode_to_netname (name1); goto ratIt; } /* * neither belong to a net, so create a new one. * * before creating a new rats here, we need to search * for a unique name. */ sprintf (ratname, " ratDrawn%i", ++ratDrawn); while (rat_used (ratname)) { sprintf (ratname, " ratDrawn%i", ++ratDrawn); } menu = GetLibraryMenuMemory (&PCB->NetlistLib); menu->Name = strdup (ratname); entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name1); entry = GetLibraryEntryMemory (menu); entry->ListEntry = strdup (name2); menu->flag = 1; ratIt: NetlistChanged (0); return (CreateNewRat (PCB->Data, Crosshair.AttachedLine.Point1.X, Crosshair.AttachedLine.Point1.Y, Crosshair.AttachedLine.Point2.X, Crosshair.AttachedLine.Point2.Y, group1, group2, Settings.RatThickness, NoFlags ())); }
static float drc_lines (PointTypePtr end, bool way) { float f, s, f2, s2, len, best; LocationType dx, dy, temp, last, length; LocationType temp2, last2, length2; LineType line1, line2; Cardinal group, comp; struct drc_info info; bool two_lines, x_is_long, blocker; PointType ans; f = 1.0; s = 0.5; last = -1; line1.Flags = line2.Flags = NoFlags (); line1.Thickness = Settings.LineThickness + 2 * (PCB->Bloat + 1); line2.Thickness = line1.Thickness; line1.Clearance = line2.Clearance = 0; line1.Point1.X = Crosshair.AttachedLine.Point1.X; line1.Point1.Y = Crosshair.AttachedLine.Point1.Y; dy = end->Y - line1.Point1.Y; dx = end->X - line1.Point1.X; if (abs (dx) > abs (dy)) { x_is_long = true; length = abs (dx); } else { x_is_long = false; length = abs (dy); } group = GetGroupOfLayer (INDEXOFCURRENT); comp = max_group + 10; /* this out-of-range group might save a call */ if (GetLayerGroupNumberByNumber (solder_silk_layer) == group) info.solder = true; else { info.solder = false; comp = GetLayerGroupNumberByNumber (component_silk_layer); } temp = length; /* assume the worst */ best = 0.0; ans.X = line1.Point1.X; ans.Y = line1.Point1.Y; while (length != last) { last = length; if (x_is_long) { dx = SGN (dx) * length; dy = end->Y - line1.Point1.Y; length2 = abs (dy); } else { dy = SGN (dy) * length; dx = end->X - line1.Point1.X; length2 = abs (dx); } temp2 = length2; f2 = 1.0; s2 = 0.5; last2 = -1; blocker = true; while (length2 != last2) { if (x_is_long) dy = SGN (dy) * length2; else dx = SGN (dx) * length2; two_lines = true; if (abs (dx) > abs (dy) && x_is_long) { line1.Point2.X = line1.Point1.X + (way ? SGN (dx) * abs (dy) : dx - SGN (dx) * abs (dy)); line1.Point2.Y = line1.Point1.Y + (way ? dy : 0); } else if (abs (dy) >= abs (dx) && !x_is_long) { line1.Point2.X = line1.Point1.X + (way ? dx : 0); line1.Point2.Y = line1.Point1.Y + (way ? SGN (dy) * abs (dx) : dy - SGN (dy) * abs (dx)); } else if (x_is_long) { /* we've changed which axis is long, so only do one line */ line1.Point2.X = line1.Point1.X + dx; line1.Point2.Y = line1.Point1.Y + (way ? SGN (dy) * abs (dx) : 0); two_lines = false; } else { /* we've changed which axis is long, so only do one line */ line1.Point2.Y = line1.Point1.Y + dy; line1.Point2.X = line1.Point1.X + (way ? SGN (dx) * abs (dy) : 0); two_lines = false; } line2.Point1.X = line1.Point2.X; line2.Point1.Y = line1.Point2.Y; if (!two_lines) { line2.Point2.Y = line1.Point2.Y; line2.Point2.X = line1.Point2.X; } else { line2.Point2.X = line1.Point1.X + dx; line2.Point2.Y = line1.Point1.Y + dy; } SetLineBoundingBox (&line1); SetLineBoundingBox (&line2); last2 = length2; if (setjmp (info.env) == 0) { info.line = &line1; r_search (PCB->Data->via_tree, &line1.BoundingBox, NULL, drcVia_callback, &info); r_search (PCB->Data->pin_tree, &line1.BoundingBox, NULL, drcVia_callback, &info); if (info.solder || comp == group) r_search (PCB->Data->pad_tree, &line1.BoundingBox, NULL, drcPad_callback, &info); if (two_lines) { info.line = &line2; r_search (PCB->Data->via_tree, &line2.BoundingBox, NULL, drcVia_callback, &info); r_search (PCB->Data->pin_tree, &line2.BoundingBox, NULL, drcVia_callback, &info); if (info.solder || comp == group) r_search (PCB->Data->pad_tree, &line2.BoundingBox, NULL, drcPad_callback, &info); } GROUP_LOOP (PCB->Data, group); { info.line = &line1; r_search (layer->line_tree, &line1.BoundingBox, NULL, drcLine_callback, &info); r_search (layer->arc_tree, &line1.BoundingBox, NULL, drcArc_callback, &info); if (two_lines) { info.line = &line2; r_search (layer->line_tree, &line2.BoundingBox, NULL, drcLine_callback, &info); r_search (layer->arc_tree, &line2.BoundingBox, NULL, drcArc_callback, &info); } } END_LOOP; /* no intersector! */ blocker = false; f2 += s2; len = (line2.Point2.X - line1.Point1.X); len *= len; len += (float) (line2.Point2.Y - line1.Point1.Y) * (line2.Point2.Y - line1.Point1.Y); if (len > best) { best = len; ans.X = line2.Point2.X; ans.Y = line2.Point2.Y; } #if 0 if (f2 > 1.0) f2 = 0.5; #endif } else { /* bumped into something, back off */ f2 -= s2; } s2 *= 0.5; length2 = MIN (f2 * temp2, temp2); } if (!blocker && ((x_is_long && line2.Point2.X - line1.Point1.X == dx) || (!x_is_long && line2.Point2.Y - line1.Point1.Y == dy))) f += s; else f -= s; s *= 0.5; length = MIN (f * temp, temp); } end->X = ans.X; end->Y = ans.Y; return best; }
/* --------------------------------------------------------------------------- * recalculates the passed coordinates to fit the current grid setting */ void FitCrosshairIntoGrid (Coord X, Coord Y) { Coord nearest_grid_x, nearest_grid_y; void *ptr1, *ptr2, *ptr3; struct snap_data snap_data; int ans; Crosshair.X = CLAMP (X, Crosshair.MinX, Crosshair.MaxX); Crosshair.Y = CLAMP (Y, Crosshair.MinY, Crosshair.MaxY); if (PCB->RatDraw) { nearest_grid_x = -MIL_TO_COORD (6); nearest_grid_y = -MIL_TO_COORD (6); } else { nearest_grid_x = GridFit (Crosshair.X, PCB->Grid, PCB->GridOffsetX); nearest_grid_y = GridFit (Crosshair.Y, PCB->Grid, PCB->GridOffsetY); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { Coord dx = Crosshair.X - Marked.X; Coord dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) nearest_grid_y = Marked.Y; else nearest_grid_x = Marked.X; } } snap_data.crosshair = &Crosshair; snap_data.nearest_sq_dist = crosshair_sq_dist (&Crosshair, nearest_grid_x, nearest_grid_y); snap_data.nearest_is_grid = true; snap_data.x = nearest_grid_x; snap_data.y = nearest_grid_y; ans = NO_TYPE; if (!PCB->RatDraw) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2, &ptr3); if (ans & ELEMENT_TYPE) { ElementType *el = (ElementType *) ptr1; check_snap_object (&snap_data, el->MarkX, el->MarkY, false); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PAD_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE && ( Settings.Mode == LINE_MODE || (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE))) { PadTypePtr pad = (PadTypePtr) ptr2; LayerType *desired_layer; Cardinal desired_group; Cardinal SLayer, CLayer; int found_our_layer = false; desired_layer = CURRENT; if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE) { desired_layer = (LayerType *)Crosshair.AttachedObject.Ptr1; } /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); desired_group = TEST_FLAG (ONSOLDERFLAG, pad) ? SLayer : CLayer; GROUP_LOOP (PCB->Data, desired_group); { if (layer == desired_layer) { found_our_layer = true; break; } } END_LOOP; if (found_our_layer == false) ans = NO_TYPE; } if (ans != NO_TYPE) { PadType *pad = (PadType *)ptr2; check_snap_object (&snap_data, (pad->Point1.X + pad->Point2.X) / 2, (pad->Point1.Y + pad->Point2.Y) / 2, true); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PIN_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, VIA_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid snapping vias to any other vias */ if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == VIA_TYPE && (ans & PIN_TYPES)) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } check_snap_offgrid_line (&snap_data, nearest_grid_x, nearest_grid_y); ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, POLYGONPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } if (snap_data.x >= 0 && snap_data.y >= 0) { Crosshair.X = snap_data.x; Crosshair.Y = snap_data.y; } if (Settings.Mode == ARROW_MODE) { ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }
/* --------------------------------------------------------------------------- * initializes some identifiers for a new zoom factor and redraws whole screen */ static void DrawEverything (const BoxType *drawn_area) { int i, ngroups, side; int component, solder; /* This is the list of layer groups we will draw. */ int do_group[MAX_LAYER]; /* This is the reverse of the order in which we draw them. */ int drawn_groups[MAX_LAYER]; int plated, unplated; bool paste_empty; PCB->Data->SILKLAYER.Color = PCB->ElementColor; PCB->Data->BACKSILKLAYER.Color = PCB->InvisibleObjectsColor; memset (do_group, 0, sizeof (do_group)); for (ngroups = 0, i = 0; i < max_copper_layer; i++) { LayerType *l = LAYER_ON_STACK (i); int group = GetLayerGroupNumberByNumber (LayerStack[i]); if (l->On && !do_group[group]) { do_group[group] = 1; drawn_groups[ngroups++] = group; } } component = GetLayerGroupNumberByNumber (component_silk_layer); solder = GetLayerGroupNumberByNumber (solder_silk_layer); /* * first draw all 'invisible' stuff */ if (!TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->set_layer ("invisible", SL (INVISIBLE, 0), 0)) { side = SWAP_IDENT ? COMPONENT_LAYER : SOLDER_LAYER; if (PCB->ElementOn) { r_search (PCB->Data->element_tree, drawn_area, NULL, element_callback, &side); r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL, name_callback, &side); DrawLayer (&(PCB->Data->Layer[max_copper_layer + side]), drawn_area); } r_search (PCB->Data->pad_tree, drawn_area, NULL, pad_callback, &side); gui->end_layer (); } /* draw all layers in layerstack order */ for (i = ngroups - 1; i >= 0; i--) { int group = drawn_groups[i]; if (gui->set_layer (0, group, 0)) { DrawLayerGroup (group, drawn_area); gui->end_layer (); } } if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui) return; /* Draw pins, pads, vias below silk */ if (gui->gui) DrawPPV (SWAP_IDENT ? solder : component, drawn_area); else { CountHoles (&plated, &unplated, drawn_area); if (plated && gui->set_layer ("plated-drill", SL (PDRILL, 0), 0)) { DrawHoles (true, false, drawn_area); gui->end_layer (); } if (unplated && gui->set_layer ("unplated-drill", SL (UDRILL, 0), 0)) { DrawHoles (false, true, drawn_area); gui->end_layer (); } } /* Draw the solder mask if turned on */ if (gui->set_layer ("componentmask", SL (MASK, TOP), 0)) { DrawMask (COMPONENT_LAYER, drawn_area); gui->end_layer (); } if (gui->set_layer ("soldermask", SL (MASK, BOTTOM), 0)) { DrawMask (SOLDER_LAYER, drawn_area); gui->end_layer (); } if (gui->set_layer ("topsilk", SL (SILK, TOP), 0)) { DrawSilk (COMPONENT_LAYER, drawn_area); gui->end_layer (); } if (gui->set_layer ("bottomsilk", SL (SILK, BOTTOM), 0)) { DrawSilk (SOLDER_LAYER, drawn_area); gui->end_layer (); } if (gui->gui) { /* Draw element Marks */ if (PCB->PinOn) r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback, NULL); /* Draw rat lines on top */ if (gui->set_layer ("rats", SL (RATS, 0), 0)) { DrawRats(drawn_area); gui->end_layer (); } } paste_empty = IsPasteEmpty (COMPONENT_LAYER); if (gui->set_layer ("toppaste", SL (PASTE, TOP), paste_empty)) { DrawPaste (COMPONENT_LAYER, drawn_area); gui->end_layer (); } paste_empty = IsPasteEmpty (SOLDER_LAYER); if (gui->set_layer ("bottompaste", SL (PASTE, BOTTOM), paste_empty)) { DrawPaste (SOLDER_LAYER, drawn_area); gui->end_layer (); } if (gui->set_layer ("topassembly", SL (ASSY, TOP), 0)) { PrintAssembly (COMPONENT_LAYER, drawn_area); gui->end_layer (); } if (gui->set_layer ("bottomassembly", SL (ASSY, BOTTOM), 0)) { PrintAssembly (SOLDER_LAYER, drawn_area); gui->end_layer (); } if (gui->set_layer ("fab", SL (FAB, 0), 0)) { PrintFab (Output.fgGC); gui->end_layer (); } }
/* --------------------------------------------------------------------------- * flip components/tracks from one side to the other */ static void SwapBuffer (BufferType *Buffer) { int j, k; Cardinal sgroup, cgroup; LayerType swap; ELEMENT_LOOP (Buffer->Data); { r_delete_element (Buffer->Data, element); MirrorElementCoordinates (Buffer->Data, element, 0); } END_LOOP; /* set buffer offset to 'mark' position */ Buffer->X = SWAP_X (Buffer->X); Buffer->Y = SWAP_Y (Buffer->Y); VIA_LOOP (Buffer->Data); { r_delete_entry (Buffer->Data->via_tree, (BoxType *)via); via->X = SWAP_X (via->X); via->Y = SWAP_Y (via->Y); SetPinBoundingBox (via); r_insert_entry (Buffer->Data->via_tree, (BoxType *)via, 0); } END_LOOP; ALLLINE_LOOP (Buffer->Data); { r_delete_entry (layer->line_tree, (BoxType *)line); line->Point1.X = SWAP_X (line->Point1.X); line->Point1.Y = SWAP_Y (line->Point1.Y); line->Point2.X = SWAP_X (line->Point2.X); line->Point2.Y = SWAP_Y (line->Point2.Y); SetLineBoundingBox (line); r_insert_entry (layer->line_tree, (BoxType *)line, 0); } ENDALL_LOOP; ALLARC_LOOP (Buffer->Data); { r_delete_entry (layer->arc_tree, (BoxType *)arc); arc->X = SWAP_X (arc->X); arc->Y = SWAP_Y (arc->Y); arc->StartAngle = SWAP_ANGLE (arc->StartAngle); arc->Delta = SWAP_DELTA (arc->Delta); SetArcBoundingBox (arc); r_insert_entry (layer->arc_tree, (BoxType *)arc, 0); } ENDALL_LOOP; ALLPOLYGON_LOOP (Buffer->Data); { r_delete_entry (layer->polygon_tree, (BoxType *)polygon); POLYGONPOINT_LOOP (polygon); { point->X = SWAP_X (point->X); point->Y = SWAP_Y (point->Y); } END_LOOP; SetPolygonBoundingBox (polygon); r_insert_entry (layer->polygon_tree, (BoxType *)polygon, 0); /* hmmm, how to handle clip */ } ENDALL_LOOP; ALLTEXT_LOOP (Buffer->Data); { r_delete_entry (layer->text_tree, (BoxType *)text); text->X = SWAP_X (text->X); text->Y = SWAP_Y (text->Y); TOGGLE_FLAG (ONSOLDERFLAG, text); SetTextBoundingBox (&PCB->Font, text); r_insert_entry (layer->text_tree, (BoxType *)text, 0); } ENDALL_LOOP; /* swap silkscreen layers */ swap = Buffer->Data->Layer[solder_silk_layer]; Buffer->Data->Layer[solder_silk_layer] = Buffer->Data->Layer[component_silk_layer]; Buffer->Data->Layer[component_silk_layer] = swap; /* swap layer groups when balanced */ sgroup = GetLayerGroupNumberByNumber (solder_silk_layer); cgroup = GetLayerGroupNumberByNumber (component_silk_layer); if (PCB->LayerGroups.Number[cgroup] == PCB->LayerGroups.Number[sgroup]) { for (j = k = 0; j < PCB->LayerGroups.Number[sgroup]; j++) { int t1, t2; Cardinal cnumber = PCB->LayerGroups.Entries[cgroup][k]; Cardinal snumber = PCB->LayerGroups.Entries[sgroup][j]; if (snumber >= max_copper_layer) continue; swap = Buffer->Data->Layer[snumber]; while (cnumber >= max_copper_layer) { k++; cnumber = PCB->LayerGroups.Entries[cgroup][k]; } Buffer->Data->Layer[snumber] = Buffer->Data->Layer[cnumber]; Buffer->Data->Layer[cnumber] = swap; k++; /* move the thermal flags with the layers */ ALLPIN_LOOP (Buffer->Data); { t1 = TEST_THERM (snumber, pin); t2 = TEST_THERM (cnumber, pin); ASSIGN_THERM (snumber, t2, pin); ASSIGN_THERM (cnumber, t1, pin); } ENDALL_LOOP; VIA_LOOP (Buffer->Data); { t1 = TEST_THERM (snumber, via); t2 = TEST_THERM (cnumber, via); ASSIGN_THERM (snumber, t2, via); ASSIGN_THERM (cnumber, t1, via); } END_LOOP; } } SetBufferBoundingBox (Buffer); SetCrosshairRangeToBuffer (); }
/*--------------------------------------------------------------------------- * * convert buffer contents into an element */ bool ConvertBufferToElement (BufferType *Buffer) { ElementType *Element; Cardinal group; Cardinal pin_n = 1; bool hasParts = false, crooked = false; int onsolder; bool warned = false; if (Buffer->Data->pcb == 0) Buffer->Data->pcb = PCB; Element = CreateNewElement (PCB->Data, &PCB->Font, NoFlags (), NULL, NULL, NULL, PASTEBUFFER->X, PASTEBUFFER->Y, 0, 100, MakeFlags (SWAP_IDENT ? ONSOLDERFLAG : NOFLAG), false); if (!Element) return (false); VIA_LOOP (Buffer->Data); { char num[8]; if (via->Mask < via->Thickness) via->Mask = via->Thickness + 2 * MASKFRAME; if (via->Name) CreateNewPin (Element, via->X, via->Y, via->Thickness, via->Clearance, via->Mask, via->DrillingHole, NULL, via->Name, MaskFlags (via->Flags, VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG | WARNFLAG)); else { sprintf (num, "%d", pin_n++); CreateNewPin (Element, via->X, via->Y, via->Thickness, via->Clearance, via->Mask, via->DrillingHole, NULL, num, MaskFlags (via->Flags, VIAFLAG | NOCOPY_FLAGS | SELECTEDFLAG | WARNFLAG)); } hasParts = true; } END_LOOP; for (onsolder = 0; onsolder < 2; onsolder ++) { int silk_layer; int onsolderflag; if ((!onsolder) == (!SWAP_IDENT)) { silk_layer = component_silk_layer; onsolderflag = NOFLAG; } else { silk_layer = solder_silk_layer; onsolderflag = ONSOLDERFLAG; } #define MAYBE_WARN() \ if (onsolder && !hasParts && !warned) \ { \ warned = true; \ Message \ (_("Warning: All of the pads are on the opposite\n" \ "side from the component - that's probably not what\n" \ "you wanted\n")); \ } \ /* get the component-side SM pads */ group = GetLayerGroupNumberByNumber (silk_layer); GROUP_LOOP (Buffer->Data, group); { char num[8]; LINE_LOOP (layer); { sprintf (num, "%d", pin_n++); CreateNewPad (Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, line->Clearance, line->Thickness + line->Clearance, NULL, line->Number ? line->Number : num, MakeFlags (onsolderflag)); MAYBE_WARN(); hasParts = true; } END_LOOP; POLYGON_LOOP (layer); { Coord x1, y1, x2, y2, w, h, t; if (! polygon_is_rectangle (polygon)) { crooked = true; continue; } w = polygon->Points[2].X - polygon->Points[0].X; h = polygon->Points[1].Y - polygon->Points[0].Y; t = (w < h) ? w : h; x1 = polygon->Points[0].X + t/2; y1 = polygon->Points[0].Y + t/2; x2 = x1 + (w-t); y2 = y1 + (h-t); sprintf (num, "%d", pin_n++); CreateNewPad (Element, x1, y1, x2, y2, t, 2 * Settings.Keepaway, t + Settings.Keepaway, NULL, num, MakeFlags (SQUAREFLAG | onsolderflag)); MAYBE_WARN(); hasParts = true; } END_LOOP; } END_LOOP; } /* now add the silkscreen. NOTE: elements must have pads or pins too */ LINE_LOOP (&Buffer->Data->SILKLAYER); { if (line->Number && !NAMEONPCB_NAME (Element)) NAMEONPCB_NAME (Element) = strdup (line->Number); CreateNewLineInElement (Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness); hasParts = true; } END_LOOP; ARC_LOOP (&Buffer->Data->SILKLAYER); { CreateNewArcInElement (Element, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); hasParts = true; } END_LOOP; if (!hasParts) { DestroyObject (PCB->Data, ELEMENT_TYPE, Element, Element, Element); Message (_("There was nothing to convert!\n" "Elements must have some silk, pads or pins.\n")); return (false); } if (crooked) Message (_("There were polygons that can't be made into pins!\n" "So they were not included in the element\n")); Element->MarkX = Buffer->X; Element->MarkY = Buffer->Y; if (SWAP_IDENT) SET_FLAG (ONSOLDERFLAG, Element); SetElementBoundingBox (PCB->Data, Element, &PCB->Font); ClearBuffer (Buffer); MoveObjectToBuffer (Buffer->Data, PCB->Data, ELEMENT_TYPE, Element, Element, Element); SetBufferBoundingBox (Buffer); return (true); }
/*--------------------------------------------------------------------------- * * break buffer element into pieces */ bool SmashBufferElement (BufferType *Buffer) { ElementType *element; Cardinal group; LayerType *clayer, *slayer; if (Buffer->Data->ElementN != 1) { Message (_("Error! Buffer doesn't contain a single element\n")); return (false); } /* * At this point the buffer should contain just a single element. * Now we detach the single element from the buffer and then clear the * buffer, ready to receive the smashed elements. As a result of detaching * it the single element is orphaned from the buffer and thus will not be * free()'d by FreeDataMemory (called via ClearBuffer). This leaves it * around for us to smash bits off it. It then becomes our responsibility, * however, to free the single element when we're finished with it. */ element = Buffer->Data->Element->data; Buffer->Data->Element = NULL; Buffer->Data->ElementN = 0; ClearBuffer (Buffer); ELEMENTLINE_LOOP (element); { CreateNewLineOnLayer (&Buffer->Data->SILKLAYER, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, 0, NoFlags ()); if (line) line->Number = STRDUP (NAMEONPCB_NAME (element)); } END_LOOP; ARC_LOOP (element); { CreateNewArcOnLayer (&Buffer->Data->SILKLAYER, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness, 0, NoFlags ()); } END_LOOP; PIN_LOOP (element); { FlagType f = NoFlags (); AddFlags (f, VIAFLAG); if (TEST_FLAG (HOLEFLAG, pin)) AddFlags (f, HOLEFLAG); CreateNewVia (Buffer->Data, pin->X, pin->Y, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Number, f); } END_LOOP; group = GetLayerGroupNumberByNumber (SWAP_IDENT ? solder_silk_layer : component_silk_layer); clayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]]; group = GetLayerGroupNumberByNumber (SWAP_IDENT ? component_silk_layer : solder_silk_layer); slayer = &Buffer->Data->Layer[PCB->LayerGroups.Entries[group][0]]; PAD_LOOP (element); { LineType *line; line = CreateNewLineOnLayer (TEST_FLAG (ONSOLDERFLAG, pad) ? slayer : clayer, pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y, pad->Thickness, pad->Clearance, NoFlags ()); if (line) line->Number = STRDUP (pad->Number); } END_LOOP; FreeElementMemory (element); g_slice_free (ElementType, element); return (true); }