#include #include #include #include enum KicadLayer { // visit: http://en.wikibooks.org/wiki/Kicad/file_formats#Layer_numbering TOP = 24, TOP_SILKSCREEN = 23, BOTTOM_SILKSCREEN = 22, TOP_PLACE_BOUND = 24, TOP_ASSEMBLY = 15 }; int print_pads(const pugi::xml_document& doc, const std::string& footprint_name, std::ostream& out) { using namespace pugi; using namespace std; xpath_node_set pins = doc.select_nodes((string("//footprint[@name='") + footprint_name + "']/pcbpin").c_str()); for (auto &pin : pins) { map ul_kicad_shape = { {"round", "C"}, {"rectangle", "R"} // ...others I don't know about }; const string pin_name = pin.node().attribute("name").value(); const string pin_style = pin.node().attribute("style").value(); xpath_node_set shape_node = doc.select_nodes( (string("//padstyle[@name='") + pin_style + "']" + "/padshape").c_str()); if (shape_node.empty()) throw runtime_error("We're screwed!"); const string pin_shape = shape_node.first().node().attribute("shape").value(); double pin_width = shape_node.first().node().attribute("width").as_double()*10; double pin_height = shape_node.first().node().attribute("height").as_double()*10; double pin_posx = pin.node().attribute("originx").as_double()*10; double pin_posy = pin.node().attribute("originy").as_double()*10; double pin_rotation = pin.node().attribute("rotation").as_double()*10; out << "$PAD" << endl; out << ".LocalClearance 0.001" << endl; out << "Po " << pin_posx << " " << pin_posy << endl; out << "Sh \"" << pin_name << "\" " << ul_kicad_shape[pin_shape] << " " << pin_width << " " << pin_height << " " << 0 << " " << 0 << " " << pin_rotation << endl; out << "At SMD N 00888000" << endl; out << "$EndPAD" << endl; } return pins.size(); } int print_lines(const pugi::xml_document& doc, const std::string& footprint_name, std::ostream& out) { using namespace pugi; using namespace std; xpath_node_set lines = doc.select_nodes((string("//footprint[@name='") + footprint_name + "']/line").c_str()); for (auto &line : lines) { double originx = line.node().attribute("originx").as_double()*10; double originy = line.node().attribute("originy").as_double()*10; double endx = line.node().attribute("endx").as_double()*10; double endy = line.node().attribute("endy").as_double()*10; double width = line.node().attribute("width").as_double()*10; out << "DS " << originx << " " << originy << " " << endx << " " << endy << " " << width << " " << TOP_SILKSCREEN << endl; } return lines.size(); } int print_polygons(const pugi::xml_document& doc, const std::string& footprint_name, std::ostream& out) { using namespace pugi; using namespace std; xpath_node_set polygons = doc.select_nodes((string("//footprint[@name='") + footprint_name + "']/polygon").c_str()); for (auto &polygon : polygons) { // no better way to do this :( int count = 0; for (auto &vertex : polygon.node()) ++count; double width = polygon.node().attribute("width").as_double()*10; out << "DP 0 0 0 0 " << count << " " << width << " " << TOP_PLACE_BOUND << endl; for (auto &vertex : polygon.node()) { double x = vertex.attribute("x").as_double()*10; double y = vertex.attribute("y").as_double()*10; out << "Dl " << x << " " << y << endl; } } } int print_footprints(const pugi::xml_document& doc, std::ostream& out) { using namespace pugi; using namespace std; xpath_node_set footprints = doc.select_nodes("//footprint"); for (auto &pin : footprints) { string footprint_name = pin.node().attribute("name").value(); out << "$MODULE " << footprint_name << endl << "Po 0 0 0 15 00000000 00000000 ~~" << endl << "Li " << footprint_name << endl; //print_lines(doc, footprint_name, out); //print_polygons(doc, footprint_name, out); print_pads(doc, footprint_name, out); out << ".LocalClearance 0" << endl; out << "$EndMODULE " << footprint_name << endl; } return footprints.size(); } void print_index(const pugi::xml_document& doc, std::ostream& out) { using namespace pugi; using namespace std; xpath_node_set footprints = doc.select_nodes("//footprint"); for (auto &footprint : footprints) out << footprint.node().attribute("name").value() << endl; } void print_library(const pugi::xml_document& doc, std::ostream& out) { using namespace pugi; using namespace std; out << "PCBNEW-LibModule-V1 Wed 17 Apr 2013 03:54:45 PM CEST" << endl; out << "$INDEX" << endl; print_index(doc,out); out << "$EndINDEX" << endl; print_footprints(doc, out); out << "$EndLIBRARY" << endl; } int main(int argc, char* argv[]) { using namespace std; using namespace pugi; if (argc != 2) return 1; xml_document doc; doc.load_file(argv[1]); print_library(doc,cout); return 0; }