Index: trunk/src_plugins/io_kicad_legacy/write.c =================================================================== --- trunk/src_plugins/io_kicad_legacy/write.c (revision 14397) +++ trunk/src_plugins/io_kicad_legacy/write.c (revision 14398) @@ -46,408 +46,12 @@ */ /* generates a line by line listing of the elements being saved */ -static int io_kicad_legacy_write_element_index(FILE *FP, pcb_data_t *Data); + /* generates a default via drill size for the layout */ static int write_kicad_legacy_layout_via_drill_size(FILE *FP); -/* writes the buffer to file */ -int io_kicad_legacy_write_buffer(pcb_plug_io_t *ctx, FILE *FP, pcb_buffer_t *buff, pcb_bool elem_only) -{ - /*fputs("io_kicad_legacy_write_buffer()", FP); */ - - if (elementlist_length(&buff->Data->Element) == 0) { - pcb_message(PCB_MSG_ERROR, "Buffer has no elements!\n"); - return -1; - } - - fputs("PCBNEW-LibModule-V1 jan 01 jan 2016 00:00:01 CET\n", FP); - fputs("Units mm\n", FP); - fputs("$INDEX\n", FP); - io_kicad_legacy_write_element_index(FP, buff->Data); - fputs("$EndINDEX\n", FP); - - /* WriteViaData(FP, buff->Data); */ - - pcb_write_element_data(FP, buff->Data, "kicadl"); - - /* - for (i = 0; i < pcb_max_layer; i++) - WriteLayerData(FP, i, &(buff->Data->Layer[i])); - */ - return 0; -} - /* --------------------------------------------------------------------------- - * writes PCB to file - */ -int io_kicad_legacy_write_pcb(pcb_plug_io_t *ctx, FILE *FP, const char *old_filename, const char *new_filename, pcb_bool emergency) -{ - /* this is the first step in exporting a layout; - * creating a kicd module containing the elements used in the layout - */ - - /*fputs("io_kicad_legacy_write_pcb()", FP); */ - - pcb_cardinal_t i; - int kicadLayerCount = 0; - int physicalLayerCount = 0; - int layer = 0; - int currentKicadLayer = 0; - int currentGroup = 0; - pcb_coord_t outlineThickness = PCB_MIL_TO_COORD(10); - - int bottomCount; - pcb_layer_id_t *bottomLayers; - int innerCount; - pcb_layer_id_t *innerLayers; - int topCount; - pcb_layer_id_t *topLayers; - int bottomSilkCount; - pcb_layer_id_t *bottomSilk; - int topSilkCount; - pcb_layer_id_t *topSilk; - int outlineCount; - pcb_layer_id_t *outlineLayers; - - pcb_coord_t LayoutXOffset; - pcb_coord_t LayoutYOffset; - - /* Kicad expects a layout "sheet" size to be specified in mils, and A4, A3 etc... */ - int A4HeightMil = 8267; - int A4WidthMil = 11700; - int sheetHeight = A4HeightMil; - int sheetWidth = A4WidthMil; - int paperSize = 4; /* default paper size is A4 */ - - fputs("PCBNEW-BOARD Version 1 jan 01 jan 2016 00:00:01 CET\n", FP); - - fputs("$GENERAL\n", FP); - fputs("Ly 1FFF8001\n", FP); /* obsolete, needed for old pcbnew */ - /*puts("Units mm\n",FP); *//*decimils most universal legacy format */ - fputs("$EndGENERAL\n", FP); - - fputs("$SHEETDESCR\n", FP); - - - /* we sort out the needed kicad sheet size here, using A4, A3, A2, A1 or A0 size as needed */ - if (PCB_COORD_TO_MIL(PCB->MaxWidth) > A4WidthMil || PCB_COORD_TO_MIL(PCB->MaxHeight) > A4HeightMil) { - sheetHeight = A4WidthMil; /* 11.7" */ - sheetWidth = 2 * A4HeightMil; /* 16.5" */ - paperSize = 3; /* this is A3 size */ - } - if (PCB_COORD_TO_MIL(PCB->MaxWidth) > sheetWidth || PCB_COORD_TO_MIL(PCB->MaxHeight) > sheetHeight) { - sheetHeight = 2 * A4HeightMil; /* 16.5" */ - sheetWidth = 2 * A4WidthMil; /* 23.4" */ - paperSize = 2; /* this is A2 size */ - } - if (PCB_COORD_TO_MIL(PCB->MaxWidth) > sheetWidth || PCB_COORD_TO_MIL(PCB->MaxHeight) > sheetHeight) { - sheetHeight = 2 * A4WidthMil; /* 23.4" */ - sheetWidth = 4 * A4HeightMil; /* 33.1" */ - paperSize = 1; /* this is A1 size */ - } - if (PCB_COORD_TO_MIL(PCB->MaxWidth) > sheetWidth || PCB_COORD_TO_MIL(PCB->MaxHeight) > sheetHeight) { - sheetHeight = 4 * A4HeightMil; /* 33.1" */ - sheetWidth = 4 * A4WidthMil; /* 46.8" */ - paperSize = 0; /* this is A0 size; where would you get it made ?!?! */ - } - fprintf(FP, "Sheet A%d ", paperSize); - /* we now sort out the offsets for centring the layout in the chosen sheet size here */ - if (sheetWidth > PCB_COORD_TO_MIL(PCB->MaxWidth)) { /* usually A4, bigger if needed */ - fprintf(FP, "%d ", sheetWidth); /* legacy kicad: elements decimils, sheet size mils */ - LayoutXOffset = PCB_MIL_TO_COORD(sheetWidth) / 2 - PCB->MaxWidth / 2; - } - else { /* the layout is bigger than A0; most unlikely, but... */ - pcb_fprintf(FP, "%.0ml ", PCB->MaxWidth); - LayoutXOffset = 0; - } - if (sheetHeight > PCB_COORD_TO_MIL(PCB->MaxHeight)) { - fprintf(FP, "%d", sheetHeight); - LayoutYOffset = PCB_MIL_TO_COORD(sheetHeight) / 2 - PCB->MaxHeight / 2; - } - else { /* the layout is bigger than A0; most unlikely, but... */ - pcb_fprintf(FP, "%.0ml", PCB->MaxHeight); - LayoutYOffset = 0; - } - fputs("\n", FP); - fputs("$EndSHEETDESCR\n", FP); - - fputs("$SETUP\n", FP); - fputs("InternalUnit 0.000100 INCH\n", FP); /* decimil is the default v1 kicad legacy unit */ - - /* here we define the copper layers in the exported kicad file */ - physicalLayerCount = pcb_layergrp_list(PCB, PCB_LYT_COPPER, NULL, 0); - - fputs("Layers ", FP); - kicadLayerCount = physicalLayerCount; - if (kicadLayerCount % 2 == 1) { - kicadLayerCount++; /* kicad doesn't like odd numbers of layers, has been deprecated for some time apparently */ - } - - fprintf(FP, "%d\n", kicadLayerCount); - layer = 0; - if (physicalLayerCount >= 1) { - fprintf(FP, "Layer[%d] COPPER_LAYER_0 signal\n", layer); - } - if (physicalLayerCount > 1) { /* seems we need to ignore layers > 16 due to kicad limitation */ - for(layer = 1; (layer < (kicadLayerCount - 1)) && (layer < 15); layer++) { - fprintf(FP, "Layer[%d] Inner%d.Cu signal\n", layer, layer); - } - fputs("Layer[15] COPPER_LAYER_15 signal\n", FP); - } - - write_kicad_legacy_layout_via_drill_size(FP); - - fputs("$EndSETUP\n", FP); - - /* now come the netlist "equipotential" descriptors */ - - write_kicad_legacy_equipotential_netlists(FP, PCB); - - /* module descriptions come next */ - - write_kicad_legacy_layout_elements(FP, PCB, PCB->Data, LayoutXOffset, LayoutYOffset); - - /* we now need to map pcb's layer groups onto the kicad layer numbers */ - currentKicadLayer = 0; - currentGroup = 0; - - /* figure out which pcb layers are bottom copper and make a list */ - bottomCount = pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, NULL, 0); - if (bottomCount > 0) { - bottomLayers = malloc(sizeof(pcb_layer_id_t) * bottomCount); - pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, bottomLayers, bottomCount); - } - else { - bottomLayers = NULL; - } - - /* figure out which pcb layers are internal copper layers and make a list */ - innerCount = pcb_layer_list(PCB, PCB_LYT_INTERN | PCB_LYT_COPPER, NULL, 0); - if (innerCount > 0) { - innerLayers = malloc(sizeof(pcb_layer_id_t) * innerCount); - pcb_layer_list(PCB, PCB_LYT_INTERN | PCB_LYT_COPPER, innerLayers, innerCount); - } - else { - innerLayers = NULL; - } - - /* figure out which pcb layers are top copper and make a list */ - topCount = pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, NULL, 0); - if (topCount > 0) { - topLayers = malloc(sizeof(pcb_layer_id_t) * topCount); - pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, topLayers, topCount); - } - else { - topLayers = NULL; - } - - /* figure out which pcb layers are bottom silk and make a list */ - bottomSilkCount = pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_SILK, NULL, 0); - if (bottomSilkCount > 0) { - bottomSilk = malloc(sizeof(pcb_layer_id_t) * bottomSilkCount); - pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_SILK, bottomSilk, bottomSilkCount); - } - else { - bottomSilk = NULL; - } - - /* figure out which pcb layers are top silk and make a list */ - topSilkCount = pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_SILK, NULL, 0); - if (topSilkCount > 0) { - topSilk = malloc(sizeof(pcb_layer_id_t) * topSilkCount); - pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_SILK, topSilk, topSilkCount); - } - else { - topSilk = NULL; - } - - /* figure out which pcb layers are outlines and make a list */ - outlineCount = pcb_layer_list(PCB, PCB_LYT_OUTLINE, NULL, 0); - if (outlineCount > 0) { - outlineLayers = malloc(sizeof(pcb_layer_id_t) * outlineCount); - pcb_layer_list(PCB, PCB_LYT_OUTLINE, outlineLayers, outlineCount); - } - else { - outlineLayers = NULL; - } - - /* we now proceed to write the outline tracks to the kicad file, layer by layer */ - currentKicadLayer = 28; /* 28 is the edge cuts layer in kicad */ - if (outlineCount > 0) { - for(i = 0; i < outlineCount; i++) { /* write top copper tracks, if any */ - write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[outlineLayers[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[outlineLayers[i]]), LayoutXOffset, LayoutYOffset); - } - } - else { /* no outline layer per se, export the board margins instead - obviously some scope to reduce redundant code... */ - fputs("$DRAWSEGMENT\n", FP); - pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, outlineThickness); - pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); - fputs("$EndDRAWSEGMENT\n", FP); - fputs("$DRAWSEGMENT\n", FP); - pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, outlineThickness); - pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); - fputs("$EndDRAWSEGMENT\n", FP); - fputs("$DRAWSEGMENT\n", FP); - pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, outlineThickness); - pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); - fputs("$EndDRAWSEGMENT\n", FP); - fputs("$DRAWSEGMENT\n", FP); - pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, outlineThickness); - pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); - fputs("$EndDRAWSEGMENT\n", FP); - } - - - /* we now proceed to write the bottom silk lines, arcs, text to the kicad legacy file, using layer 20 */ - currentKicadLayer = 20; /* 20 is the bottom silk layer in kicad */ - for(i = 0; i < bottomSilkCount; i++) { /* write bottom silk lines, if any */ - write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the bottom copper text to the kicad legacy file, layer by layer */ - currentKicadLayer = 0; /* 0 is the bottom copper layer in kicad */ - for(i = 0; i < bottomCount; i++) { /* write bottom copper tracks, if any */ - write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); - } /* 0 is the bottom most track in kicad */ - - /* we now proceed to write the internal copper text to the kicad file, layer by layer */ - if (innerCount > 0) { - currentGroup = pcb_layer_get_group(PCB, innerLayers[0]); - } - for(i = 0, currentKicadLayer = 1; i < innerCount; i++) { /* write inner copper text, group by group */ - if (currentGroup != pcb_layer_get_group(PCB, innerLayers[i])) { - currentGroup = pcb_layer_get_group(PCB, innerLayers[i]); - currentKicadLayer++; - if (currentKicadLayer > 14) { - currentKicadLayer = 14; /* kicad 16 layers in total, 0...15 */ - } - } - write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the top copper text to the kicad legacy file, layer by layer */ - currentKicadLayer = 15; /* 15 is the top most copper layer in kicad */ - for(i = 0; i < topCount; i++) { /* write top copper tracks, if any */ - write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the top silk lines, arcs, text to the kicad legacy file, using layer 21 */ - currentKicadLayer = 21; /* 21 is the top silk layer in kicad */ - for(i = 0; i < topSilkCount; i++) { /* write top silk lines, if any */ - write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); - } - - /* having done the graphical elements, we move onto tracks and vias */ - - fputs("$TRACK\n", FP); - write_kicad_legacy_layout_vias(FP, PCB->Data, LayoutXOffset, LayoutYOffset); - - /* we now proceed to write the bottom copper tracks to the kicad legacy file, layer by layer */ - currentKicadLayer = 0; /* 0 is the bottom copper layer in kicad */ - for(i = 0; i < bottomCount; i++) { /* write bottom copper tracks, if any */ - write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); - } /* 0 is the bottom most track in kicad */ - - /* we now proceed to write the internal copper tracks to the kicad file, layer by layer */ - if (innerCount > 0) { - currentGroup = pcb_layer_get_group(PCB, innerLayers[0]); - } - for(i = 0, currentKicadLayer = 1; i < innerCount; i++) { /* write inner copper tracks, group by group */ - if (currentGroup != pcb_layer_get_group(PCB, innerLayers[i])) { - currentGroup = pcb_layer_get_group(PCB, innerLayers[i]); - currentKicadLayer++; - if (currentKicadLayer > 14) { - currentKicadLayer = 14; /* kicad 16 layers in total, 0...15 */ - } - } - write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the top copper tracks to the kicad legacy file, layer by layer */ - currentKicadLayer = 15; /* 15 is the top most copper layer in kicad */ - for(i = 0; i < topCount; i++) { /* write top copper tracks, if any */ - write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); - write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); - } - fputs("$EndTRACK\n", FP); - - /* - * now we proceed to write polygons for each layer, and iterate much like we did for tracks - */ - - /* we now proceed to write the bottom silk polygons to the kicad legacy file, using layer 20 */ - currentKicadLayer = 20; /* 20 is the bottom silk layer in kicad */ - for(i = 0; i < bottomSilkCount; i++) { /* write bottom silk polygons, if any */ - write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the bottom copper polygons to the kicad legacy file, layer by layer */ - currentKicadLayer = 0; /* 0 is the bottom copper layer in kicad */ - for(i = 0; i < bottomCount; i++) { /* write bottom copper polygons, if any */ - write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); - } /* 0 is the bottom most track in kicad */ - - /* we now proceed to write the internal copper polygons to the kicad file, layer by layer */ - if (innerCount > 0) { - currentGroup = pcb_layer_get_group(PCB, innerLayers[0]); - } - for(i = 0, currentKicadLayer = 1; i < innerCount; i++) { /* write inner copper polygons, group by group */ - if (currentGroup != pcb_layer_get_group(PCB, innerLayers[i])) { - currentGroup = pcb_layer_get_group(PCB, innerLayers[i]); - currentKicadLayer++; - if (currentKicadLayer > 14) { - currentKicadLayer = 14; /* kicad 16 layers in total, 0...15 */ - } - } - write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the top copper polygons to the kicad legacy file, layer by layer */ - currentKicadLayer = 15; /* 15 is the top most copper layer in kicad */ - for(i = 0; i < topCount; i++) { /* write top copper polygons, if any */ - write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); - } - - /* we now proceed to write the top silk polygons to the kicad legacy file, using layer 21 */ - currentKicadLayer = 21; /* 21 is the top silk layer in kicad */ - for(i = 0; i < topSilkCount; i++) { /* write top silk polygons, if any */ - write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); - } - - - fputs("$EndBOARD\n", FP); - - /* now free memory from arrays that were used */ - if (bottomCount > 0) { - free(bottomLayers); - } - if (innerCount > 0) { - free(innerLayers); - } - if (topCount > 0) { - free(topLayers); - } - if (topSilkCount > 0) { - free(topSilk); - } - if (bottomSilkCount > 0) { - free(bottomSilk); - } - if (outlineCount > 0) { - free(outlineLayers); - } - return 0; -} - -/* --------------------------------------------------------------------------- * writes (eventually) de-duplicated list of element names in kicad legacy format module $INDEX */ static int io_kicad_legacy_write_element_index(FILE *FP, pcb_data_t *Data) @@ -483,6 +87,8 @@ } + + /* --------------------------------------------------------------------------- * writes kicad format via data For a track segment: @@ -1190,3 +796,399 @@ return 0; } } + +/* writes the buffer to file */ +int io_kicad_legacy_write_buffer(pcb_plug_io_t *ctx, FILE *FP, pcb_buffer_t *buff, pcb_bool elem_only) +{ + /*fputs("io_kicad_legacy_write_buffer()", FP); */ + + if (elementlist_length(&buff->Data->Element) == 0) { + pcb_message(PCB_MSG_ERROR, "Buffer has no elements!\n"); + return -1; + } + + fputs("PCBNEW-LibModule-V1 jan 01 jan 2016 00:00:01 CET\n", FP); + fputs("Units mm\n", FP); + fputs("$INDEX\n", FP); + io_kicad_legacy_write_element_index(FP, buff->Data); + fputs("$EndINDEX\n", FP); + + /* WriteViaData(FP, buff->Data); */ + + pcb_write_element_data(FP, buff->Data, "kicadl"); + + /* + for (i = 0; i < pcb_max_layer; i++) + WriteLayerData(FP, i, &(buff->Data->Layer[i])); + */ + return 0; +} + +/* --------------------------------------------------------------------------- + * writes PCB to file + */ +int io_kicad_legacy_write_pcb(pcb_plug_io_t *ctx, FILE *FP, const char *old_filename, const char *new_filename, pcb_bool emergency) +{ + /* this is the first step in exporting a layout; + * creating a kicd module containing the elements used in the layout + */ + + /*fputs("io_kicad_legacy_write_pcb()", FP); */ + + pcb_cardinal_t i; + int kicadLayerCount = 0; + int physicalLayerCount = 0; + int layer = 0; + int currentKicadLayer = 0; + int currentGroup = 0; + pcb_coord_t outlineThickness = PCB_MIL_TO_COORD(10); + + int bottomCount; + pcb_layer_id_t *bottomLayers; + int innerCount; + pcb_layer_id_t *innerLayers; + int topCount; + pcb_layer_id_t *topLayers; + int bottomSilkCount; + pcb_layer_id_t *bottomSilk; + int topSilkCount; + pcb_layer_id_t *topSilk; + int outlineCount; + pcb_layer_id_t *outlineLayers; + + pcb_coord_t LayoutXOffset; + pcb_coord_t LayoutYOffset; + + /* Kicad expects a layout "sheet" size to be specified in mils, and A4, A3 etc... */ + int A4HeightMil = 8267; + int A4WidthMil = 11700; + int sheetHeight = A4HeightMil; + int sheetWidth = A4WidthMil; + int paperSize = 4; /* default paper size is A4 */ + + fputs("PCBNEW-BOARD Version 1 jan 01 jan 2016 00:00:01 CET\n", FP); + + fputs("$GENERAL\n", FP); + fputs("Ly 1FFF8001\n", FP); /* obsolete, needed for old pcbnew */ + /*puts("Units mm\n",FP); *//*decimils most universal legacy format */ + fputs("$EndGENERAL\n", FP); + + fputs("$SHEETDESCR\n", FP); + + + /* we sort out the needed kicad sheet size here, using A4, A3, A2, A1 or A0 size as needed */ + if (PCB_COORD_TO_MIL(PCB->MaxWidth) > A4WidthMil || PCB_COORD_TO_MIL(PCB->MaxHeight) > A4HeightMil) { + sheetHeight = A4WidthMil; /* 11.7" */ + sheetWidth = 2 * A4HeightMil; /* 16.5" */ + paperSize = 3; /* this is A3 size */ + } + if (PCB_COORD_TO_MIL(PCB->MaxWidth) > sheetWidth || PCB_COORD_TO_MIL(PCB->MaxHeight) > sheetHeight) { + sheetHeight = 2 * A4HeightMil; /* 16.5" */ + sheetWidth = 2 * A4WidthMil; /* 23.4" */ + paperSize = 2; /* this is A2 size */ + } + if (PCB_COORD_TO_MIL(PCB->MaxWidth) > sheetWidth || PCB_COORD_TO_MIL(PCB->MaxHeight) > sheetHeight) { + sheetHeight = 2 * A4WidthMil; /* 23.4" */ + sheetWidth = 4 * A4HeightMil; /* 33.1" */ + paperSize = 1; /* this is A1 size */ + } + if (PCB_COORD_TO_MIL(PCB->MaxWidth) > sheetWidth || PCB_COORD_TO_MIL(PCB->MaxHeight) > sheetHeight) { + sheetHeight = 4 * A4HeightMil; /* 33.1" */ + sheetWidth = 4 * A4WidthMil; /* 46.8" */ + paperSize = 0; /* this is A0 size; where would you get it made ?!?! */ + } + fprintf(FP, "Sheet A%d ", paperSize); + /* we now sort out the offsets for centring the layout in the chosen sheet size here */ + if (sheetWidth > PCB_COORD_TO_MIL(PCB->MaxWidth)) { /* usually A4, bigger if needed */ + fprintf(FP, "%d ", sheetWidth); /* legacy kicad: elements decimils, sheet size mils */ + LayoutXOffset = PCB_MIL_TO_COORD(sheetWidth) / 2 - PCB->MaxWidth / 2; + } + else { /* the layout is bigger than A0; most unlikely, but... */ + pcb_fprintf(FP, "%.0ml ", PCB->MaxWidth); + LayoutXOffset = 0; + } + if (sheetHeight > PCB_COORD_TO_MIL(PCB->MaxHeight)) { + fprintf(FP, "%d", sheetHeight); + LayoutYOffset = PCB_MIL_TO_COORD(sheetHeight) / 2 - PCB->MaxHeight / 2; + } + else { /* the layout is bigger than A0; most unlikely, but... */ + pcb_fprintf(FP, "%.0ml", PCB->MaxHeight); + LayoutYOffset = 0; + } + fputs("\n", FP); + fputs("$EndSHEETDESCR\n", FP); + + fputs("$SETUP\n", FP); + fputs("InternalUnit 0.000100 INCH\n", FP); /* decimil is the default v1 kicad legacy unit */ + + /* here we define the copper layers in the exported kicad file */ + physicalLayerCount = pcb_layergrp_list(PCB, PCB_LYT_COPPER, NULL, 0); + + fputs("Layers ", FP); + kicadLayerCount = physicalLayerCount; + if (kicadLayerCount % 2 == 1) { + kicadLayerCount++; /* kicad doesn't like odd numbers of layers, has been deprecated for some time apparently */ + } + + fprintf(FP, "%d\n", kicadLayerCount); + layer = 0; + if (physicalLayerCount >= 1) { + fprintf(FP, "Layer[%d] COPPER_LAYER_0 signal\n", layer); + } + if (physicalLayerCount > 1) { /* seems we need to ignore layers > 16 due to kicad limitation */ + for(layer = 1; (layer < (kicadLayerCount - 1)) && (layer < 15); layer++) { + fprintf(FP, "Layer[%d] Inner%d.Cu signal\n", layer, layer); + } + fputs("Layer[15] COPPER_LAYER_15 signal\n", FP); + } + + write_kicad_legacy_layout_via_drill_size(FP); + + fputs("$EndSETUP\n", FP); + + /* now come the netlist "equipotential" descriptors */ + + write_kicad_legacy_equipotential_netlists(FP, PCB); + + /* module descriptions come next */ + + write_kicad_legacy_layout_elements(FP, PCB, PCB->Data, LayoutXOffset, LayoutYOffset); + + /* we now need to map pcb's layer groups onto the kicad layer numbers */ + currentKicadLayer = 0; + currentGroup = 0; + + /* figure out which pcb layers are bottom copper and make a list */ + bottomCount = pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, NULL, 0); + if (bottomCount > 0) { + bottomLayers = malloc(sizeof(pcb_layer_id_t) * bottomCount); + pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, bottomLayers, bottomCount); + } + else { + bottomLayers = NULL; + } + + /* figure out which pcb layers are internal copper layers and make a list */ + innerCount = pcb_layer_list(PCB, PCB_LYT_INTERN | PCB_LYT_COPPER, NULL, 0); + if (innerCount > 0) { + innerLayers = malloc(sizeof(pcb_layer_id_t) * innerCount); + pcb_layer_list(PCB, PCB_LYT_INTERN | PCB_LYT_COPPER, innerLayers, innerCount); + } + else { + innerLayers = NULL; + } + + /* figure out which pcb layers are top copper and make a list */ + topCount = pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, NULL, 0); + if (topCount > 0) { + topLayers = malloc(sizeof(pcb_layer_id_t) * topCount); + pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, topLayers, topCount); + } + else { + topLayers = NULL; + } + + /* figure out which pcb layers are bottom silk and make a list */ + bottomSilkCount = pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_SILK, NULL, 0); + if (bottomSilkCount > 0) { + bottomSilk = malloc(sizeof(pcb_layer_id_t) * bottomSilkCount); + pcb_layer_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_SILK, bottomSilk, bottomSilkCount); + } + else { + bottomSilk = NULL; + } + + /* figure out which pcb layers are top silk and make a list */ + topSilkCount = pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_SILK, NULL, 0); + if (topSilkCount > 0) { + topSilk = malloc(sizeof(pcb_layer_id_t) * topSilkCount); + pcb_layer_list(PCB, PCB_LYT_TOP | PCB_LYT_SILK, topSilk, topSilkCount); + } + else { + topSilk = NULL; + } + + /* figure out which pcb layers are outlines and make a list */ + outlineCount = pcb_layer_list(PCB, PCB_LYT_OUTLINE, NULL, 0); + if (outlineCount > 0) { + outlineLayers = malloc(sizeof(pcb_layer_id_t) * outlineCount); + pcb_layer_list(PCB, PCB_LYT_OUTLINE, outlineLayers, outlineCount); + } + else { + outlineLayers = NULL; + } + + /* we now proceed to write the outline tracks to the kicad file, layer by layer */ + currentKicadLayer = 28; /* 28 is the edge cuts layer in kicad */ + if (outlineCount > 0) { + for(i = 0; i < outlineCount; i++) { /* write top copper tracks, if any */ + write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[outlineLayers[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[outlineLayers[i]]), LayoutXOffset, LayoutYOffset); + } + } + else { /* no outline layer per se, export the board margins instead - obviously some scope to reduce redundant code... */ + fputs("$DRAWSEGMENT\n", FP); + pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, outlineThickness); + pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); + fputs("$EndDRAWSEGMENT\n", FP); + fputs("$DRAWSEGMENT\n", FP); + pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, outlineThickness); + pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); + fputs("$EndDRAWSEGMENT\n", FP); + fputs("$DRAWSEGMENT\n", FP); + pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 + LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, outlineThickness); + pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); + fputs("$EndDRAWSEGMENT\n", FP); + fputs("$DRAWSEGMENT\n", FP); + pcb_fprintf(FP, "Po 0 %.0mk %.0mk %.0mk %.0mk %.0mk\n", PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 + LayoutYOffset, PCB->MaxWidth / 2 - LayoutXOffset, PCB->MaxHeight / 2 - LayoutYOffset, outlineThickness); + pcb_fprintf(FP, "De %d 0 0 0 0\n", currentKicadLayer); + fputs("$EndDRAWSEGMENT\n", FP); + } + + + /* we now proceed to write the bottom silk lines, arcs, text to the kicad legacy file, using layer 20 */ + currentKicadLayer = 20; /* 20 is the bottom silk layer in kicad */ + for(i = 0; i < bottomSilkCount; i++) { /* write bottom silk lines, if any */ + write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the bottom copper text to the kicad legacy file, layer by layer */ + currentKicadLayer = 0; /* 0 is the bottom copper layer in kicad */ + for(i = 0; i < bottomCount; i++) { /* write bottom copper tracks, if any */ + write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); + } /* 0 is the bottom most track in kicad */ + + /* we now proceed to write the internal copper text to the kicad file, layer by layer */ + if (innerCount > 0) { + currentGroup = pcb_layer_get_group(PCB, innerLayers[0]); + } + for(i = 0, currentKicadLayer = 1; i < innerCount; i++) { /* write inner copper text, group by group */ + if (currentGroup != pcb_layer_get_group(PCB, innerLayers[i])) { + currentGroup = pcb_layer_get_group(PCB, innerLayers[i]); + currentKicadLayer++; + if (currentKicadLayer > 14) { + currentKicadLayer = 14; /* kicad 16 layers in total, 0...15 */ + } + } + write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the top copper text to the kicad legacy file, layer by layer */ + currentKicadLayer = 15; /* 15 is the top most copper layer in kicad */ + for(i = 0; i < topCount; i++) { /* write top copper tracks, if any */ + write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the top silk lines, arcs, text to the kicad legacy file, using layer 21 */ + currentKicadLayer = 21; /* 21 is the top silk layer in kicad */ + for(i = 0; i < topSilkCount; i++) { /* write top silk lines, if any */ + write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_text(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); + } + + /* having done the graphical elements, we move onto tracks and vias */ + + fputs("$TRACK\n", FP); + write_kicad_legacy_layout_vias(FP, PCB->Data, LayoutXOffset, LayoutYOffset); + + /* we now proceed to write the bottom copper tracks to the kicad legacy file, layer by layer */ + currentKicadLayer = 0; /* 0 is the bottom copper layer in kicad */ + for(i = 0; i < bottomCount; i++) { /* write bottom copper tracks, if any */ + write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); + } /* 0 is the bottom most track in kicad */ + + /* we now proceed to write the internal copper tracks to the kicad file, layer by layer */ + if (innerCount > 0) { + currentGroup = pcb_layer_get_group(PCB, innerLayers[0]); + } + for(i = 0, currentKicadLayer = 1; i < innerCount; i++) { /* write inner copper tracks, group by group */ + if (currentGroup != pcb_layer_get_group(PCB, innerLayers[i])) { + currentGroup = pcb_layer_get_group(PCB, innerLayers[i]); + currentKicadLayer++; + if (currentKicadLayer > 14) { + currentKicadLayer = 14; /* kicad 16 layers in total, 0...15 */ + } + } + write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the top copper tracks to the kicad legacy file, layer by layer */ + currentKicadLayer = 15; /* 15 is the top most copper layer in kicad */ + for(i = 0; i < topCount; i++) { /* write top copper tracks, if any */ + write_kicad_legacy_layout_tracks(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); + write_kicad_legacy_layout_arcs(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); + } + fputs("$EndTRACK\n", FP); + + /* + * now we proceed to write polygons for each layer, and iterate much like we did for tracks + */ + + /* we now proceed to write the bottom silk polygons to the kicad legacy file, using layer 20 */ + currentKicadLayer = 20; /* 20 is the bottom silk layer in kicad */ + for(i = 0; i < bottomSilkCount; i++) { /* write bottom silk polygons, if any */ + write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[bottomSilk[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the bottom copper polygons to the kicad legacy file, layer by layer */ + currentKicadLayer = 0; /* 0 is the bottom copper layer in kicad */ + for(i = 0; i < bottomCount; i++) { /* write bottom copper polygons, if any */ + write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[bottomLayers[i]]), LayoutXOffset, LayoutYOffset); + } /* 0 is the bottom most track in kicad */ + + /* we now proceed to write the internal copper polygons to the kicad file, layer by layer */ + if (innerCount > 0) { + currentGroup = pcb_layer_get_group(PCB, innerLayers[0]); + } + for(i = 0, currentKicadLayer = 1; i < innerCount; i++) { /* write inner copper polygons, group by group */ + if (currentGroup != pcb_layer_get_group(PCB, innerLayers[i])) { + currentGroup = pcb_layer_get_group(PCB, innerLayers[i]); + currentKicadLayer++; + if (currentKicadLayer > 14) { + currentKicadLayer = 14; /* kicad 16 layers in total, 0...15 */ + } + } + write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[innerLayers[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the top copper polygons to the kicad legacy file, layer by layer */ + currentKicadLayer = 15; /* 15 is the top most copper layer in kicad */ + for(i = 0; i < topCount; i++) { /* write top copper polygons, if any */ + write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[topLayers[i]]), LayoutXOffset, LayoutYOffset); + } + + /* we now proceed to write the top silk polygons to the kicad legacy file, using layer 21 */ + currentKicadLayer = 21; /* 21 is the top silk layer in kicad */ + for(i = 0; i < topSilkCount; i++) { /* write top silk polygons, if any */ + write_kicad_legacy_layout_polygons(FP, currentKicadLayer, &(PCB->Data->Layer[topSilk[i]]), LayoutXOffset, LayoutYOffset); + } + + + fputs("$EndBOARD\n", FP); + + /* now free memory from arrays that were used */ + if (bottomCount > 0) { + free(bottomLayers); + } + if (innerCount > 0) { + free(innerLayers); + } + if (topCount > 0) { + free(topLayers); + } + if (topSilkCount > 0) { + free(topSilk); + } + if (bottomSilkCount > 0) { + free(bottomSilk); + } + if (outlineCount > 0) { + free(outlineLayers); + } + return 0; +} Index: trunk/src_plugins/io_kicad_legacy/write.h =================================================================== --- trunk/src_plugins/io_kicad_legacy/write.h (revision 14397) +++ trunk/src_plugins/io_kicad_legacy/write.h (revision 14398) @@ -33,12 +33,3 @@ int io_kicad_legacy_write_element(pcb_plug_io_t *ctx, FILE *FP, pcb_data_t *Data); int io_kicad_legacy_write_buffer(pcb_plug_io_t *ctx, FILE *FP, pcb_buffer_t *buff, pcb_bool elem_only); int io_kicad_legacy_write_pcb(pcb_plug_io_t *ctx, FILE *FP, const char *old_filename, const char *new_filename, pcb_bool emergency); -int write_kicad_legacy_module_header(FILE *FP); -int write_kicad_legacy_layout_header(FILE *FP); -int write_kicad_legacy_layout_vias(FILE *FP, pcb_data_t *Data, pcb_coord_t MaxWidth, pcb_coord_t MaxHeight); -int write_kicad_legacy_layout_tracks(FILE *FP, pcb_cardinal_t number, pcb_layer_t *layer, pcb_coord_t MaxWidth, pcb_coord_t MaxHeight); -int write_kicad_legacy_layout_arcs(FILE *FP, pcb_cardinal_t number, pcb_layer_t *layer, pcb_coord_t xOffset, pcb_coord_t yOffset); -int write_kicad_legacy_layout_text(FILE *FP, pcb_cardinal_t number, pcb_layer_t *layer, pcb_coord_t xOffset, pcb_coord_t yOffset); -int write_kicad_legacy_equipotential_netlists(FILE *FP, pcb_board_t *Layout); -int write_kicad_legacy_layout_elements(FILE *FP, pcb_board_t *Layout, pcb_data_t *Data, pcb_coord_t xOffset, pcb_coord_t yOffset); -int write_kicad_legacy_layout_polygons(FILE *FP, pcb_cardinal_t number, pcb_layer_t *layer, pcb_coord_t xOffset, pcb_coord_t yOffset);