From 260243a6d9a1fc77b02d308216f4522c8180d6f5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 8 Jul 2018 23:44:36 +0200 Subject: [PATCH] WIP: Fixed PCB import for non-Qt builds, added missing file. --- src/db/db/db.pro | 4 +- src/db/db/dbConverters.cc | 32 ++ src/db/db/dbConverters.h | 101 ++++ src/laybasic/laybasic/layConverters.h | 66 --- .../pcb/db_plugin/dbGerberImportData.cc | 517 ++++++++++++++++++ .../pcb/db_plugin/dbGerberImportData.h | 102 ++++ .../pcb/db_plugin/dbGerberImporter.cc | 110 ++++ .../streamers/pcb/db_plugin/db_plugin.pro | 6 +- .../pcb/lay_plugin/layGerberImport.cc | 108 ---- .../pcb/lay_plugin/layGerberImportDialog.cc | 485 ---------------- .../pcb/lay_plugin/layGerberImportDialog.h | 60 +- src/tl/tl/atomic/atomic.h | 203 +++++++ src/tl/tl/atomic/atomic_msvc.h | 238 ++++++++ src/tl/tl/atomic/spinlock.h | 78 +++ 14 files changed, 1389 insertions(+), 721 deletions(-) create mode 100644 src/db/db/dbConverters.cc create mode 100644 src/db/db/dbConverters.h create mode 100644 src/plugins/streamers/pcb/db_plugin/dbGerberImportData.cc create mode 100644 src/plugins/streamers/pcb/db_plugin/dbGerberImportData.h create mode 100644 src/tl/tl/atomic/atomic.h create mode 100644 src/tl/tl/atomic/atomic_msvc.h create mode 100644 src/tl/tl/atomic/spinlock.h diff --git a/src/db/db/db.pro b/src/db/db/db.pro index 4cdf18611..8c0a4e558 100644 --- a/src/db/db/db.pro +++ b/src/db/db/db.pro @@ -119,6 +119,7 @@ SOURCES = \ gsiDeclDbVector.cc \ gsiDeclDbLayoutDiff.cc \ gsiDeclDbGlyphs.cc \ + dbConverters.cc HEADERS = \ dbArray.h \ @@ -206,7 +207,8 @@ HEADERS = \ dbNamedLayerReader.h \ dbForceLink.h \ dbPlugin.h \ - dbInit.h + dbInit.h \ + dbConverters.h !equals(HAVE_QT, "0") { diff --git a/src/db/db/dbConverters.cc b/src/db/db/dbConverters.cc new file mode 100644 index 000000000..77abf43c0 --- /dev/null +++ b/src/db/db/dbConverters.cc @@ -0,0 +1,32 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbConverters.h" +#include "tlInternational.h" + +namespace db +{ + + // .. nothing yet .. + +} + diff --git a/src/db/db/dbConverters.h b/src/db/db/dbConverters.h new file mode 100644 index 000000000..63e374759 --- /dev/null +++ b/src/db/db/dbConverters.h @@ -0,0 +1,101 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#ifndef HDR_dbConverters +#define HDR_dbConverters + +#include "dbCommon.h" + +#include "dbLayerProperties.h" +#include "dbTrans.h" +#include "dbPoint.h" + +namespace db +{ + +/** + * @brief A converter for transformations + * + * T is supposed a transformation type such as "db::DCplxTrans". + */ +template +struct DB_PUBLIC TransformationConverter +{ + std::string to_string (const T &t) const + { + return t.to_string (); + } + + void from_string (const std::string &s, T &t) const + { + tl::Extractor ex (s.c_str ()); + ex.read (t); + ex.expect_end (); + } +}; + +/** + * @brief A converter for layout layers + */ +struct DB_PUBLIC LayoutLayerConverter +{ + std::string to_string (const db::LayerProperties &p) const + { + return p.to_string (); + } + + void from_string (const std::string &s, db::LayerProperties &p) const + { + tl::Extractor ex (s.c_str ()); + p.read (ex); + ex.expect_end (); + } +}; + +/** + * @brief A converter for points + * + * P is supposed to be a point type (i.e. db::DPoint). + */ +template +struct DB_PUBLIC PointConverter +{ + std::string to_string (const P &p) const + { + return tl::to_string (p.x ()) + "," + tl::to_string (p.y ()); + } + + void from_string (const std::string &s, P &p) const + { + typename P::coord_type x, y; + tl::Extractor ex (s.c_str ()); + ex.read (x); + ex.expect (","); + ex.read (y); + p = P (x, y); + ex.expect_end (); + } +}; + +} + +#endif diff --git a/src/laybasic/laybasic/layConverters.h b/src/laybasic/laybasic/layConverters.h index 1ab7924fe..f164b899e 100644 --- a/src/laybasic/laybasic/layConverters.h +++ b/src/laybasic/laybasic/layConverters.h @@ -28,8 +28,6 @@ #include -#include "dbLayerProperties.h" - namespace lay { @@ -42,70 +40,6 @@ struct LAYBASIC_PUBLIC ColorConverter void from_string (const std::string &s, QColor &c) const; }; -/** - * @brief A converter for transformations - * - * T is supposed a transformation type such as "db::DCplxTrans". - */ -template -struct LAYBASIC_PUBLIC TransformationConverter -{ - std::string to_string (const T &t) const - { - return t.to_string (); - } - - void from_string (const std::string &s, T &t) const - { - tl::Extractor ex (s.c_str ()); - ex.read (t); - ex.expect_end (); - } -}; - -/** - * @brief A converter for layout layers - */ -struct LAYBASIC_PUBLIC LayoutLayerConverter -{ - std::string to_string (const db::LayerProperties &p) const - { - return p.to_string (); - } - - void from_string (const std::string &s, db::LayerProperties &p) const - { - tl::Extractor ex (s.c_str ()); - p.read (ex); - ex.expect_end (); - } -}; - -/** - * @brief A converter for points - * - * P is supposed to be a point type (i.e. db::DPoint). - */ -template -struct LAYBASIC_PUBLIC PointConverter -{ - std::string to_string (const P &p) const - { - return tl::to_string (p.x ()) + "," + tl::to_string (p.y ()); - } - - void from_string (const std::string &s, P &p) const - { - typename P::coord_type x, y; - tl::Extractor ex (s.c_str ()); - ex.read (x); - ex.expect (","); - ex.read (y); - p = P (x, y); - ex.expect_end (); - } -}; - } #endif diff --git a/src/plugins/streamers/pcb/db_plugin/dbGerberImportData.cc b/src/plugins/streamers/pcb/db_plugin/dbGerberImportData.cc new file mode 100644 index 000000000..e0db81c35 --- /dev/null +++ b/src/plugins/streamers/pcb/db_plugin/dbGerberImportData.cc @@ -0,0 +1,517 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "dbGerberImportData.h" +#include "dbGerberImporter.h" +#include "dbPoint.h" +#include "dbConverters.h" + +#include "tlFileUtils.h" +#include "tlXMLParser.h" + +namespace db +{ + +// ----------------------------------------------------------------------------------------- +// GerberImportData implementation + +GerberImportData::GerberImportData () + : invert_negative_layers (false), border (5000), + free_layer_mapping (false), mode (ModeSamePanel), mounting (MountingTop), + num_metal_layers (0), num_via_types (0), num_circle_points (-1), + merge_flag (false), dbu (0.001), topcell_name ("PCB") +{ + // .. nothing yet .. +} + +void +GerberImportData::reset () +{ + double dbu_saved = dbu; + std::string base_dir_saved = base_dir; + bool free_layer_mapping_saved = free_layer_mapping; + mode_type mode_saved = mode; + + *this = GerberImportData (); + + dbu = dbu_saved; + base_dir = base_dir_saved; + free_layer_mapping = free_layer_mapping_saved; + mode = mode_saved; +} + +std::string +GerberImportData::get_layer_properties_file () const +{ + std::string lyp_file = layer_properties_file; + if (! lyp_file.empty ()) { + if (! base_dir.empty () && ! tl::is_absolute (lyp_file)) { + lyp_file = tl::absolute_file_path (tl::combine_path (base_dir, lyp_file)); + } + } + + return lyp_file; +} + +void +GerberImportData::setup_importer (db::GerberImporter *importer) +{ + if (num_circle_points >= 4) { + importer->set_circle_points (num_circle_points); + } + + importer->set_dbu (dbu); + importer->set_cell_name (topcell_name); + importer->set_dir (base_dir); + importer->set_global_trans (explicit_trans); + importer->set_reference_points (reference_points); + importer->set_merge (merge_flag); + importer->set_invert_negative_layers (invert_negative_layers); + importer->set_border (border); + + if (free_layer_mapping) { + + for (std::vector::iterator file = free_files.begin (); file != free_files.end (); ++file) { + + if (! file->filename.empty ()) { + + db::GerberFile file_spec; + file_spec.set_filename (file->filename); + + for (std::vector ::const_iterator i = file->layout_layers.begin (); i != file->layout_layers.end (); ++i) { + if (*i >= 0 && *i < int (layout_layers.size ())) { + file_spec.add_layer_spec (layout_layers [*i]); + } + } + + importer->add_file (file_spec); + + } + + } + + } else { + + for (std::vector::iterator file = artwork_files.begin (); file != artwork_files.end (); ++file) { + + if (! file->filename.empty ()) { + + size_t n; + if (mounting == MountingTop) { + n = std::distance (artwork_files.begin (), file); + } else { + n = std::distance (file, artwork_files.end ()) - 1; + } + + if (n * 2 < layout_layers.size ()) { + db::GerberFile file_spec; + file_spec.set_filename (file->filename); + file_spec.add_layer_spec (layout_layers [n * 2]); + importer->add_file (file_spec); + } + + } + + } + + for (std::vector::iterator file = drill_files.begin (); file != drill_files.end (); ++file) { + + if (! file->filename.empty ()) { + + size_t nstart, nstop; + if (mounting == MountingTop) { + nstart = std::distance (artwork_files.begin (), artwork_files.begin () + file->start); + nstop = std::distance (artwork_files.begin (), artwork_files.begin () + file->stop); + } else { + nstop = std::distance (artwork_files.begin () + file->start, artwork_files.end ()) - 1; + nstart = std::distance (artwork_files.begin () + file->stop, artwork_files.end ()) - 1; + } + + db::GerberFile file_spec; + file_spec.set_filename (file->filename); + + for (size_t n = nstart; n < nstop; ++n) { + if (n * 2 + 1 < layout_layers.size ()) { + file_spec.add_layer_spec (layout_layers [n * 2 + 1]); + } + } + + importer->add_file (file_spec); + + } + + } + + } +} + +struct MountingConverter +{ + std::string to_string (GerberImportData::mounting_type m) const + { + return m == GerberImportData::MountingTop ? "top" : "bottom"; + } + + void from_string (const std::string &s, GerberImportData::mounting_type &m) const + { + if (s == "top") { + m = GerberImportData::MountingTop; + } else if (s == "bottom") { + m = GerberImportData::MountingBottom; + } else { + throw tl::Exception (tl::to_string (tr ("Invalid mounting specification: %s")), s); + } + } +}; + +// declaration of the layer properties file XML structure +static const tl::XMLStruct +pcb_project_structure ("pcb-project", + tl::make_member (&GerberImportData::invert_negative_layers, "invert-negative-layers") + + tl::make_member (&GerberImportData::border, "border") + + tl::make_member (&GerberImportData::free_layer_mapping, "free-layer-mapping") + + tl::make_element (&GerberImportData::layout_layers, "layout-layers", + tl::make_member::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "layout-layer", db::LayoutLayerConverter ()) + ) + + tl::make_member (&GerberImportData::mounting, "mounting", MountingConverter ()) + + tl::make_member (&GerberImportData::num_metal_layers, "num-metal-layers") + + tl::make_member (&GerberImportData::num_via_types, "num-via-types") + + tl::make_element (&GerberImportData::artwork_files, "artwork-files", + tl::make_element::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "artwork-file", + tl::make_member (&GerberArtworkFileDescriptor::filename, "filename") + ) + ) + + tl::make_element (&GerberImportData::drill_files, "drill-files", + tl::make_element::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "drill-file", + tl::make_member (&GerberDrillFileDescriptor::start, "start") + + tl::make_member (&GerberDrillFileDescriptor::stop, "stop") + + tl::make_member (&GerberDrillFileDescriptor::filename, "filename") + ) + ) + + tl::make_element (&GerberImportData::free_files, "free-files", + tl::make_element::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "free-file", + tl::make_member (&GerberFreeFileDescriptor::filename, "filename") + + tl::make_element (&GerberFreeFileDescriptor::layout_layers, "layout-layers", + tl::make_member::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "index") + ) + ) + ) + + tl::make_element (&GerberImportData::reference_points, "reference-points", + tl::make_element, std::vector >::const_iterator, std::vector > > (&std::vector >::begin, &std::vector >::end, &std::vector >::push_back, "reference-point", + tl::make_member (&std::pair ::first, "pcb", db::PointConverter ()) + + tl::make_member (&std::pair ::second, "layout", db::PointConverter ()) + ) + ) + + tl::make_member (&GerberImportData::explicit_trans, "explicit-trans", db::TransformationConverter ()) + + tl::make_member (&GerberImportData::layer_properties_file, "layer-properties-file") + + tl::make_member (&GerberImportData::num_circle_points, "num-circle-points") + + tl::make_member (&GerberImportData::merge_flag, "merge-flag") + + tl::make_member (&GerberImportData::dbu, "dbu") + + tl::make_member (&GerberImportData::topcell_name, "cell-name") +); + +void +GerberImportData::load (const std::string &file) +{ + reset (); + current_file = file; + tl::XMLFileSource in (file); + pcb_project_structure.parse (in, *this); +} + +void +GerberImportData::load (tl::InputStream &stream) +{ + reset (); + current_file = std::string (); + tl::XMLStreamSource in (stream); + pcb_project_structure.parse (in, *this); +} + +void +GerberImportData::save (const std::string &file) +{ + tl::OutputStream os (file, tl::OutputStream::OM_Plain); + pcb_project_structure.write (os, *this); + current_file = file; +} + +void +GerberImportData::from_string (const std::string &s) +{ + tl::Extractor ex (s.c_str ()); + while (! ex.at_end ()) { + + if (ex.test ("free-layer-mapping")) { + + ex.test ("="); + ex.read (free_layer_mapping); + ex.test (";"); + + } else if (ex.test ("invert-negative-layers")) { + + ex.test ("="); + ex.read (invert_negative_layers); + ex.test (";"); + + } else if (ex.test ("border")) { + + ex.test ("="); + ex.read (border); + ex.test (";"); + + } else if (ex.test ("import-mode")) { + + ex.test ("="); + int m = 0; + ex.read (m); + mode = (mode_type) m; + ex.test (";"); + + } else if (ex.test ("base-dir")) { + + ex.test ("="); + ex.read_word_or_quoted (base_dir); + ex.test (";"); + + } else if (ex.test ("layout-layers")) { + + ex.test ("="); + layout_layers.clear (); + while (! ex.test (";") && ! ex.at_end ()) { + layout_layers.push_back (db::LayerProperties ()); + layout_layers.back ().read (ex); + ex.test (","); + } + ex.test (";"); + + } else if (ex.test ("mounting")) { + + ex.test ("="); + std::string m; + ex.read_word (m); + mounting = (m == "top") ? MountingTop : MountingBottom; + ex.test (";"); + + } else if (ex.test ("num-metal-layers")) { + + ex.test ("="); + ex.read (num_metal_layers); + ex.test (";"); + + } else if (ex.test ("num-via-types")) { + + ex.test ("="); + ex.read (num_via_types); + ex.test (";"); + + } else if (ex.test ("artwork-files")) { + + ex.test ("="); + artwork_files.clear (); + while (! ex.test (";") && ! ex.at_end ()) { + ex.test ("("); + artwork_files.push_back (db::GerberArtworkFileDescriptor ()); + ex.read_word_or_quoted (artwork_files.back ().filename); + ex.test (")"); + ex.test (","); + } + ex.test (";"); + + } else if (ex.test ("drill-files")) { + + ex.test ("="); + drill_files.clear (); + while (! ex.test (";") && ! ex.at_end ()) { + ex.test ("("); + drill_files.push_back (db::GerberDrillFileDescriptor ()); + ex.read (drill_files.back ().start); + ex.test (","); + ex.read (drill_files.back ().stop); + ex.test (","); + ex.read_word_or_quoted (drill_files.back ().filename); + ex.test (")"); + ex.test (","); + } + ex.test (";"); + + } else if (ex.test ("free-files")) { + + ex.test ("="); + free_files.clear (); + while (! ex.test (";") && ! ex.at_end ()) { + ex.test ("("); + free_files.push_back (db::GerberFreeFileDescriptor ()); + ex.read_word_or_quoted (free_files.back ().filename); + ex.test (","); + while (! ex.test (")") && ! ex.at_end ()) { + int i = -1; + ex.read (i); + free_files.back ().layout_layers.push_back (i); + ex.test (","); + } + ex.test (","); + } + ex.test (";"); + + } else if (ex.test ("reference-points")) { + + ex.test ("="); + reference_points.clear (); + while (! ex.test (";") && ! ex.at_end ()) { + double x1, y1, x2, y2; + ex.test ("("); + ex.test ("("); + ex.read (x1); + ex.test (","); + ex.read (y1); + ex.test (")"); + ex.test (","); + ex.test ("("); + ex.read (x2); + ex.test (","); + ex.read (y2); + ex.test (")"); + ex.test (")"); + ex.test (","); + reference_points.push_back (std::make_pair (db::DPoint (x1, y1), db::DPoint (x2, y2))); + } + ex.test (";"); + + } else if (ex.test ("explicit-trans")) { + + ex.test ("="); + ex.read (explicit_trans); + ex.test (";"); + + } else if (ex.test ("layer-properties-file")) { + + ex.test ("="); + ex.read_word_or_quoted (layer_properties_file); + ex.test (";"); + + } else if (ex.test ("num-circle-points")) { + + ex.test ("="); + ex.read (num_circle_points); + ex.test (";"); + + } else if (ex.test ("merge-flag")) { + + ex.test ("="); + ex.read (merge_flag); + ex.test (";"); + + } else if (ex.test ("dbu")) { + + ex.test ("="); + ex.read (dbu); + ex.test (";"); + + } else if (ex.test ("cell-name")) { + + ex.test ("="); + ex.read_word_or_quoted (topcell_name); + ex.test (";"); + + } else { + ex.expect_end (); + } + + } +} + +std::string +GerberImportData::to_string () const +{ + std::string s; + s += "free-layer-mapping=" + tl::to_string(free_layer_mapping) + ";"; + s += "import-mode=" + tl::to_string(int (mode)) + ";"; + s += "base-dir=" + tl::to_quoted_string (base_dir) + ";"; + s += "invert-negative-layers=" + tl::to_string (invert_negative_layers) + ";"; + s += "border=" + tl::to_string (border) + ";"; + + s += "layout-layers="; + for (std::vector ::const_iterator ll = layout_layers.begin (); ll != layout_layers.end (); ++ll) { + if (ll != layout_layers.begin ()) { + s += ","; + } + s += ll->to_string (); + } + s += ";"; + + s += "mounting=" + std::string (mounting == MountingTop ? "top" : "bottom") + ";"; + s += "num-metal-layers=" + tl::to_string (num_metal_layers) + ";"; + s += "num-via-types=" + tl::to_string (num_via_types) + ";"; + + s += "artwork-files="; + for (std::vector ::const_iterator f = artwork_files.begin (); f != artwork_files.end (); ++f) { + if (f != artwork_files.begin ()) { + s += ","; + } + s += "(" + tl::to_quoted_string (f->filename) + ")"; + } + s += ";"; + + s += "drill-files="; + for (std::vector ::const_iterator f = drill_files.begin (); f != drill_files.end (); ++f) { + if (f != drill_files.begin ()) { + s += ","; + } + s += "(" + tl::to_string (f->start) + "," + tl::to_string (f->stop) + "," + tl::to_quoted_string (f->filename) + ")"; + } + s += ";"; + + s += "free-files="; + for (std::vector ::const_iterator f = free_files.begin (); f != free_files.end (); ++f) { + if (f != free_files.begin ()) { + s += ","; + } + s += "(" + tl::to_quoted_string (f->filename); + for (std::vector ::const_iterator i = f->layout_layers.begin (); i != f->layout_layers.end (); ++i) { + s += "," + tl::to_string (*i); + } + s += ")"; + } + s += ";"; + + s += "reference-points="; + for (std::vector >::const_iterator rp = reference_points.begin (); rp != reference_points.end (); ++rp) { + if (rp != reference_points.begin ()) { + s += ","; + } + s += "((" + tl::to_string (rp->first.x ()) + "," + tl::to_string (rp->first.y ()) + "),(" + + tl::to_string (rp->second.x ()) + "," + tl::to_string (rp->second.y ()) + "))"; + } + s += ";"; + + s += "explicit-trans=" + explicit_trans.to_string () + ";"; + s += "layer-properties-file=" + tl::to_quoted_string (layer_properties_file) + ";"; + s += "num-circle-points=" + tl::to_string (num_circle_points) + ";"; + s += "merge-flag=" + tl::to_string (merge_flag) + ";"; + s += "dbu=" + tl::to_string (dbu) + ";"; + s += "cell-name=" + tl::to_quoted_string (topcell_name) + ";"; + + return s; +} + +} diff --git a/src/plugins/streamers/pcb/db_plugin/dbGerberImportData.h b/src/plugins/streamers/pcb/db_plugin/dbGerberImportData.h new file mode 100644 index 000000000..78ae2c71f --- /dev/null +++ b/src/plugins/streamers/pcb/db_plugin/dbGerberImportData.h @@ -0,0 +1,102 @@ + +/* + + KLayout Layout Viewer + Copyright (C) 2006-2018 Matthias Koefferlein + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + + +#ifndef HDR_dbGerberImportData +#define HDR_dbGerberImportData + +#include "dbTrans.h" +#include "dbLayerProperties.h" + +#include "tlStream.h" + +#include +#include + + +namespace db +{ + +class GerberImporter; + +struct GerberArtworkFileDescriptor +{ + std::string filename; +}; + +struct GerberDrillFileDescriptor +{ + GerberDrillFileDescriptor () : start (-1), stop (-1) { } + + int start; + int stop; + std::string filename; +}; + +struct GerberFreeFileDescriptor +{ + std::string filename; + std::vector layout_layers; +}; + +struct GerberImportData +{ +public: + GerberImportData (); + + enum mode_type { ModeIntoLayout = 0, ModeSamePanel, ModeNewPanel }; + enum mounting_type { MountingTop = 0, MountingBottom }; + + bool invert_negative_layers; + double border; + bool free_layer_mapping; + mode_type mode; + std::string base_dir; + std::string current_file; + std::vector layout_layers; + mounting_type mounting; + int num_metal_layers; + int num_via_types; + std::vector artwork_files; + std::vector drill_files; + std::vector free_files; + std::vector > reference_points; + db::DCplxTrans explicit_trans; + std::string layer_properties_file; + int num_circle_points; + bool merge_flag; + double dbu; + std::string topcell_name; + + std::string get_layer_properties_file () const; + void setup_importer (db::GerberImporter *importer); + void reset (); + void load (tl::InputStream &stream); + void load (const std::string &file); + void save (const std::string &file); + void from_string (const std::string &s); + std::string to_string () const; +}; + +} + +#endif diff --git a/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc b/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc index 14df727f0..18a20dd17 100644 --- a/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc +++ b/src/plugins/streamers/pcb/db_plugin/dbGerberImporter.cc @@ -22,8 +22,12 @@ #include "dbGerberImporter.h" +#include "dbGerberImportData.h" #include "dbGerberDrillFileReader.h" #include "dbRS274XReader.h" +#include "dbReader.h" +#include "dbStream.h" + #include "tlStream.h" #include "tlString.h" #include "tlString.h" @@ -1070,5 +1074,111 @@ GerberImporter::do_read (db::Layout &layout, db::cell_index_type cell_index) } +// --------------------------------------------------------------- +// Plugin for the stream reader + + +class GerberReader + : public db::ReaderBase +{ +public: + + GerberReader (tl::InputStream &s) + : m_stream (s) + { + // .. nothing yet .. + } + + ~GerberReader () + { + // .. nothing yet .. + } + + virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions & /*options*/) throw (tl::Exception) + { + // TODO: too simple, should provide at least a layer filtering. + return read (layout); + } + + virtual const db::LayerMap &read (db::Layout &layout) throw (tl::Exception) + { + db::GerberImportData data; + + std::string fn (m_stream.source ()); + if (! fn.empty ()) { + data.base_dir = tl::absolute_path (fn); + } + + data.load (m_stream); + + db::GerberImporter importer; + data.setup_importer (&importer); + + importer.read (layout); + + std::string lyr_file = data.get_layer_properties_file (); + if (! lyr_file.empty ()) { + layout.add_meta_info (db::MetaInfo ("layer-properties-file", "Layer Properties File", lyr_file)); + } + + return m_layers; + } + + virtual const char *format () const + { + return "GerberPCB"; + } + +private: + tl::InputStream &m_stream; + db::LayerMap m_layers; +}; + +class GerberFormatDeclaration + : public db::StreamFormatDeclaration +{ + virtual std::string format_name () const { return "GerberPCB"; } + virtual std::string format_desc () const { return "Gerber PCB"; } + virtual std::string format_title () const { return "Gerber PCB (project files)"; } + virtual std::string file_format () const { return "Gerber PCB project files (*.pcb)"; } + + virtual bool detect (tl::InputStream &stream) const + { + // The test is that somewhere within the first 1000 bytes, a XML tag appears. + // 1000 bytes are within the initial block that the stream reader reads and hence + // this does not trigger any reread which is not available on some sources. + // TODO: this is pretty simple test. A more elaborate test would be in place here. + std::string h = stream.read_all (1000); + // HINT: this assumes UTF8 or ISO encoding ... + if (h.find ("") != std::string::npos) { + return true; + } else { + return false; + } + } + + virtual db::ReaderBase *create_reader (tl::InputStream &s) const + { + return new GerberReader (s); + } + + virtual db::WriterBase *create_writer () const + { + return 0; + } + + virtual bool can_read () const + { + return true; + } + + virtual bool can_write () const + { + return false; + } +}; + +static tl::RegisteredClass format_decl (new GerberFormatDeclaration (), 1000, "GerberPCB"); + } diff --git a/src/plugins/streamers/pcb/db_plugin/db_plugin.pro b/src/plugins/streamers/pcb/db_plugin/db_plugin.pro index b80245675..132271498 100644 --- a/src/plugins/streamers/pcb/db_plugin/db_plugin.pro +++ b/src/plugins/streamers/pcb/db_plugin/db_plugin.pro @@ -8,10 +8,12 @@ HEADERS = \ dbGerberDrillFileReader.h \ dbGerberImporter.h \ dbRS274XApertures.h \ - dbRS274XReader.h + dbRS274XReader.h \ + dbGerberImportData.h SOURCES = \ dbGerberDrillFileReader.cc \ dbGerberImporter.cc \ dbRS274XApertures.cc \ - dbRS274XReader.cc + dbRS274XReader.cc \ + dbGerberImportData.cc diff --git a/src/plugins/streamers/pcb/lay_plugin/layGerberImport.cc b/src/plugins/streamers/pcb/lay_plugin/layGerberImport.cc index 57c54b3ae..e7abb0866 100644 --- a/src/plugins/streamers/pcb/lay_plugin/layGerberImport.cc +++ b/src/plugins/streamers/pcb/lay_plugin/layGerberImport.cc @@ -191,113 +191,5 @@ private: static tl::RegisteredClass config_decl (new lay::GerberImportPluginDeclaration (), 1200, "db::GerberImportPlugin"); -// --------------------------------------------------------------- -// Plugin for the stream reader - - -class GerberReader - : public db::ReaderBase -{ -public: - - GerberReader (tl::InputStream &s) - : m_stream (s) - { - // .. nothing yet .. - } - - ~GerberReader () - { - // .. nothing yet .. - } - - virtual const db::LayerMap &read (db::Layout &layout, const db::LoadLayoutOptions & /*options*/) throw (tl::Exception) - { - // TODO: too simple, should provide at least a layer filtering. - return read (layout); - } - - virtual const db::LayerMap &read (db::Layout &layout) throw (tl::Exception) - { - GerberImportData data; - - std::string fn (m_stream.source ()); - if (! fn.empty ()) { - QFileInfo fi (tl::to_qstring (fn)); - data.base_dir = tl::to_string (fi.absoluteDir ().path ()); - } - - data.load (m_stream); - - db::GerberImporter importer; - data.setup_importer (&importer); - - importer.read (layout); - - std::string lyr_file = data.get_layer_properties_file (); - if (! lyr_file.empty ()) { - layout.add_meta_info (db::MetaInfo ("layer-properties-file", "Layer Properties File", lyr_file)); - } - - return m_layers; - } - - virtual const char *format () const - { - return "GerberPCB"; - } - -private: - tl::InputStream &m_stream; - db::LayerMap m_layers; -}; - -class GerberFormatDeclaration - : public db::StreamFormatDeclaration -{ - virtual std::string format_name () const { return "GerberPCB"; } - virtual std::string format_desc () const { return "Gerber PCB"; } - virtual std::string format_title () const { return "Gerber PCB (project files)"; } - virtual std::string file_format () const { return "Gerber PCB project files (*.pcb)"; } - - virtual bool detect (tl::InputStream &stream) const - { - // The test is that somewhere within the first 1000 bytes, a XML tag appears. - // 1000 bytes are within the initial block that the stream reader reads and hence - // this does not trigger any reread which is not available on some sources. - // TODO: this is pretty simple test. A more elaborate test would be in place here. - std::string h = stream.read_all (1000); - // HINT: this assumes UTF8 or ISO encoding ... - if (h.find ("") != std::string::npos) { - return true; - } else { - return false; - } - } - - virtual db::ReaderBase *create_reader (tl::InputStream &s) const - { - return new GerberReader (s); - } - - virtual db::WriterBase *create_writer () const - { - return 0; - } - - virtual bool can_read () const - { - return true; - } - - virtual bool can_write () const - { - return false; - } -}; - -static tl::RegisteredClass format_decl (new GerberFormatDeclaration (), 1000, "GerberPCB"); - - } diff --git a/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.cc b/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.cc index 85ca76cb9..1d10a6ee6 100644 --- a/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.cc +++ b/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.cc @@ -42,491 +42,6 @@ namespace lay { -// ----------------------------------------------------------------------------------------- -// GerberImportData implementation - -GerberImportData::GerberImportData () - : invert_negative_layers (false), border (5000), - free_layer_mapping (false), mode (ModeSamePanel), mounting (MountingTop), - num_metal_layers (0), num_via_types (0), num_circle_points (-1), - merge_flag (false), dbu (0.001), topcell_name ("PCB") -{ - // .. nothing yet .. -} - -void -GerberImportData::reset () -{ - double dbu_saved = dbu; - std::string base_dir_saved = base_dir; - bool free_layer_mapping_saved = free_layer_mapping; - mode_type mode_saved = mode; - - *this = GerberImportData (); - - dbu = dbu_saved; - base_dir = base_dir_saved; - free_layer_mapping = free_layer_mapping_saved; - mode = mode_saved; -} - -std::string -GerberImportData::get_layer_properties_file () const -{ - std::string lyp_file = layer_properties_file; - if (! lyp_file.empty ()) { - QFileInfo lyp_file_info (tl::to_qstring (lyp_file)); - if (! base_dir.empty () && ! lyp_file_info.isAbsolute ()) { - lyp_file_info = QFileInfo (QDir (tl::to_qstring (base_dir)), tl::to_qstring (lyp_file)); - lyp_file = tl::to_string (lyp_file_info.absoluteFilePath ()); - } - } - - return lyp_file; -} - -void -GerberImportData::setup_importer (db::GerberImporter *importer) -{ - if (num_circle_points >= 4) { - importer->set_circle_points (num_circle_points); - } - - importer->set_dbu (dbu); - importer->set_cell_name (topcell_name); - importer->set_dir (base_dir); - importer->set_global_trans (explicit_trans); - importer->set_reference_points (reference_points); - importer->set_merge (merge_flag); - importer->set_invert_negative_layers (invert_negative_layers); - importer->set_border (border); - - if (free_layer_mapping) { - - for (std::vector::iterator file = free_files.begin (); file != free_files.end (); ++file) { - - if (! file->filename.empty ()) { - - db::GerberFile file_spec; - file_spec.set_filename (file->filename); - - for (std::vector ::const_iterator i = file->layout_layers.begin (); i != file->layout_layers.end (); ++i) { - if (*i >= 0 && *i < int (layout_layers.size ())) { - file_spec.add_layer_spec (layout_layers [*i]); - } - } - - importer->add_file (file_spec); - - } - - } - - } else { - - for (std::vector::iterator file = artwork_files.begin (); file != artwork_files.end (); ++file) { - - if (! file->filename.empty ()) { - - size_t n; - if (mounting == MountingTop) { - n = std::distance (artwork_files.begin (), file); - } else { - n = std::distance (file, artwork_files.end ()) - 1; - } - - if (n * 2 < layout_layers.size ()) { - db::GerberFile file_spec; - file_spec.set_filename (file->filename); - file_spec.add_layer_spec (layout_layers [n * 2]); - importer->add_file (file_spec); - } - - } - - } - - for (std::vector::iterator file = drill_files.begin (); file != drill_files.end (); ++file) { - - if (! file->filename.empty ()) { - - size_t nstart, nstop; - if (mounting == MountingTop) { - nstart = std::distance (artwork_files.begin (), artwork_files.begin () + file->start); - nstop = std::distance (artwork_files.begin (), artwork_files.begin () + file->stop); - } else { - nstop = std::distance (artwork_files.begin () + file->start, artwork_files.end ()) - 1; - nstart = std::distance (artwork_files.begin () + file->stop, artwork_files.end ()) - 1; - } - - db::GerberFile file_spec; - file_spec.set_filename (file->filename); - - for (size_t n = nstart; n < nstop; ++n) { - if (n * 2 + 1 < layout_layers.size ()) { - file_spec.add_layer_spec (layout_layers [n * 2 + 1]); - } - } - - importer->add_file (file_spec); - - } - - } - - } -} - -struct MountingConverter -{ - std::string to_string (GerberImportData::mounting_type m) const - { - return m == GerberImportData::MountingTop ? "top" : "bottom"; - } - - void from_string (const std::string &s, GerberImportData::mounting_type &m) const - { - if (s == "top") { - m = GerberImportData::MountingTop; - } else if (s == "bottom") { - m = GerberImportData::MountingBottom; - } else { - throw tl::Exception (tl::to_string (QObject::tr ("Invalid mounting specification: %s")), s); - } - } -}; - -// declaration of the layer properties file XML structure -static const tl::XMLStruct -pcb_project_structure ("pcb-project", - tl::make_member (&GerberImportData::invert_negative_layers, "invert-negative-layers") + - tl::make_member (&GerberImportData::border, "border") + - tl::make_member (&GerberImportData::free_layer_mapping, "free-layer-mapping") + - tl::make_element (&GerberImportData::layout_layers, "layout-layers", - tl::make_member::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "layout-layer", lay::LayoutLayerConverter ()) - ) + - tl::make_member (&GerberImportData::mounting, "mounting", MountingConverter ()) + - tl::make_member (&GerberImportData::num_metal_layers, "num-metal-layers") + - tl::make_member (&GerberImportData::num_via_types, "num-via-types") + - tl::make_element (&GerberImportData::artwork_files, "artwork-files", - tl::make_element::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "artwork-file", - tl::make_member (&GerberArtworkFileDescriptor::filename, "filename") - ) - ) + - tl::make_element (&GerberImportData::drill_files, "drill-files", - tl::make_element::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "drill-file", - tl::make_member (&GerberDrillFileDescriptor::start, "start") + - tl::make_member (&GerberDrillFileDescriptor::stop, "stop") + - tl::make_member (&GerberDrillFileDescriptor::filename, "filename") - ) - ) + - tl::make_element (&GerberImportData::free_files, "free-files", - tl::make_element::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "free-file", - tl::make_member (&GerberFreeFileDescriptor::filename, "filename") + - tl::make_element (&GerberFreeFileDescriptor::layout_layers, "layout-layers", - tl::make_member::const_iterator, std::vector > (&std::vector::begin, &std::vector::end, &std::vector::push_back, "index") - ) - ) - ) + - tl::make_element (&GerberImportData::reference_points, "reference-points", - tl::make_element, std::vector >::const_iterator, std::vector > > (&std::vector >::begin, &std::vector >::end, &std::vector >::push_back, "reference-point", - tl::make_member (&std::pair ::first, "pcb", lay::PointConverter ()) + - tl::make_member (&std::pair ::second, "layout", lay::PointConverter ()) - ) - ) + - tl::make_member (&GerberImportData::explicit_trans, "explicit-trans", lay::TransformationConverter ()) + - tl::make_member (&GerberImportData::layer_properties_file, "layer-properties-file") + - tl::make_member (&GerberImportData::num_circle_points, "num-circle-points") + - tl::make_member (&GerberImportData::merge_flag, "merge-flag") + - tl::make_member (&GerberImportData::dbu, "dbu") + - tl::make_member (&GerberImportData::topcell_name, "cell-name") -); - -void -GerberImportData::load (const std::string &file) -{ - reset (); - current_file = file; - tl::XMLFileSource in (file); - pcb_project_structure.parse (in, *this); -} - -void -GerberImportData::load (tl::InputStream &stream) -{ - reset (); - current_file = std::string (); - tl::XMLStreamSource in (stream); - pcb_project_structure.parse (in, *this); -} - -void -GerberImportData::save (const std::string &file) -{ - tl::OutputStream os (file, tl::OutputStream::OM_Plain); - pcb_project_structure.write (os, *this); - current_file = file; -} - -void -GerberImportData::from_string (const std::string &s) -{ - tl::Extractor ex (s.c_str ()); - while (! ex.at_end ()) { - - if (ex.test ("free-layer-mapping")) { - - ex.test ("="); - ex.read (free_layer_mapping); - ex.test (";"); - - } else if (ex.test ("invert-negative-layers")) { - - ex.test ("="); - ex.read (invert_negative_layers); - ex.test (";"); - - } else if (ex.test ("border")) { - - ex.test ("="); - ex.read (border); - ex.test (";"); - - } else if (ex.test ("import-mode")) { - - ex.test ("="); - int m = 0; - ex.read (m); - mode = (mode_type) m; - ex.test (";"); - - } else if (ex.test ("base-dir")) { - - ex.test ("="); - ex.read_word_or_quoted (base_dir); - ex.test (";"); - - } else if (ex.test ("layout-layers")) { - - ex.test ("="); - layout_layers.clear (); - while (! ex.test (";") && ! ex.at_end ()) { - layout_layers.push_back (db::LayerProperties ()); - layout_layers.back ().read (ex); - ex.test (","); - } - ex.test (";"); - - } else if (ex.test ("mounting")) { - - ex.test ("="); - std::string m; - ex.read_word (m); - mounting = (m == "top") ? MountingTop : MountingBottom; - ex.test (";"); - - } else if (ex.test ("num-metal-layers")) { - - ex.test ("="); - ex.read (num_metal_layers); - ex.test (";"); - - } else if (ex.test ("num-via-types")) { - - ex.test ("="); - ex.read (num_via_types); - ex.test (";"); - - } else if (ex.test ("artwork-files")) { - - ex.test ("="); - artwork_files.clear (); - while (! ex.test (";") && ! ex.at_end ()) { - ex.test ("("); - artwork_files.push_back (lay::GerberArtworkFileDescriptor ()); - ex.read_word_or_quoted (artwork_files.back ().filename); - ex.test (")"); - ex.test (","); - } - ex.test (";"); - - } else if (ex.test ("drill-files")) { - - ex.test ("="); - drill_files.clear (); - while (! ex.test (";") && ! ex.at_end ()) { - ex.test ("("); - drill_files.push_back (lay::GerberDrillFileDescriptor ()); - ex.read (drill_files.back ().start); - ex.test (","); - ex.read (drill_files.back ().stop); - ex.test (","); - ex.read_word_or_quoted (drill_files.back ().filename); - ex.test (")"); - ex.test (","); - } - ex.test (";"); - - } else if (ex.test ("free-files")) { - - ex.test ("="); - free_files.clear (); - while (! ex.test (";") && ! ex.at_end ()) { - ex.test ("("); - free_files.push_back (lay::GerberFreeFileDescriptor ()); - ex.read_word_or_quoted (free_files.back ().filename); - ex.test (","); - while (! ex.test (")") && ! ex.at_end ()) { - int i = -1; - ex.read (i); - free_files.back ().layout_layers.push_back (i); - ex.test (","); - } - ex.test (","); - } - ex.test (";"); - - } else if (ex.test ("reference-points")) { - - ex.test ("="); - reference_points.clear (); - while (! ex.test (";") && ! ex.at_end ()) { - double x1, y1, x2, y2; - ex.test ("("); - ex.test ("("); - ex.read (x1); - ex.test (","); - ex.read (y1); - ex.test (")"); - ex.test (","); - ex.test ("("); - ex.read (x2); - ex.test (","); - ex.read (y2); - ex.test (")"); - ex.test (")"); - ex.test (","); - reference_points.push_back (std::make_pair (db::DPoint (x1, y1), db::DPoint (x2, y2))); - } - ex.test (";"); - - } else if (ex.test ("explicit-trans")) { - - ex.test ("="); - ex.read (explicit_trans); - ex.test (";"); - - } else if (ex.test ("layer-properties-file")) { - - ex.test ("="); - ex.read_word_or_quoted (layer_properties_file); - ex.test (";"); - - } else if (ex.test ("num-circle-points")) { - - ex.test ("="); - ex.read (num_circle_points); - ex.test (";"); - - } else if (ex.test ("merge-flag")) { - - ex.test ("="); - ex.read (merge_flag); - ex.test (";"); - - } else if (ex.test ("dbu")) { - - ex.test ("="); - ex.read (dbu); - ex.test (";"); - - } else if (ex.test ("cell-name")) { - - ex.test ("="); - ex.read_word_or_quoted (topcell_name); - ex.test (";"); - - } else { - ex.expect_end (); - } - - } -} - -std::string -GerberImportData::to_string () const -{ - std::string s; - s += "free-layer-mapping=" + tl::to_string(free_layer_mapping) + ";"; - s += "import-mode=" + tl::to_string(int (mode)) + ";"; - s += "base-dir=" + tl::to_quoted_string (base_dir) + ";"; - s += "invert-negative-layers=" + tl::to_string (invert_negative_layers) + ";"; - s += "border=" + tl::to_string (border) + ";"; - - s += "layout-layers="; - for (std::vector ::const_iterator ll = layout_layers.begin (); ll != layout_layers.end (); ++ll) { - if (ll != layout_layers.begin ()) { - s += ","; - } - s += ll->to_string (); - } - s += ";"; - - s += "mounting=" + std::string (mounting == MountingTop ? "top" : "bottom") + ";"; - s += "num-metal-layers=" + tl::to_string (num_metal_layers) + ";"; - s += "num-via-types=" + tl::to_string (num_via_types) + ";"; - - s += "artwork-files="; - for (std::vector ::const_iterator f = artwork_files.begin (); f != artwork_files.end (); ++f) { - if (f != artwork_files.begin ()) { - s += ","; - } - s += "(" + tl::to_quoted_string (f->filename) + ")"; - } - s += ";"; - - s += "drill-files="; - for (std::vector ::const_iterator f = drill_files.begin (); f != drill_files.end (); ++f) { - if (f != drill_files.begin ()) { - s += ","; - } - s += "(" + tl::to_string (f->start) + "," + tl::to_string (f->stop) + "," + tl::to_quoted_string (f->filename) + ")"; - } - s += ";"; - - s += "free-files="; - for (std::vector ::const_iterator f = free_files.begin (); f != free_files.end (); ++f) { - if (f != free_files.begin ()) { - s += ","; - } - s += "(" + tl::to_quoted_string (f->filename); - for (std::vector ::const_iterator i = f->layout_layers.begin (); i != f->layout_layers.end (); ++i) { - s += "," + tl::to_string (*i); - } - s += ")"; - } - s += ";"; - - s += "reference-points="; - for (std::vector >::const_iterator rp = reference_points.begin (); rp != reference_points.end (); ++rp) { - if (rp != reference_points.begin ()) { - s += ","; - } - s += "((" + tl::to_string (rp->first.x ()) + "," + tl::to_string (rp->first.y ()) + "),(" - + tl::to_string (rp->second.x ()) + "," + tl::to_string (rp->second.y ()) + "))"; - } - s += ";"; - - s += "explicit-trans=" + explicit_trans.to_string () + ";"; - s += "layer-properties-file=" + tl::to_quoted_string (layer_properties_file) + ";"; - s += "num-circle-points=" + tl::to_string (num_circle_points) + ";"; - s += "merge-flag=" + tl::to_string (merge_flag) + ";"; - s += "dbu=" + tl::to_string (dbu) + ";"; - s += "cell-name=" + tl::to_quoted_string (topcell_name) + ";"; - - return s; -} - // ----------------------------------------------------------------------------------------- // GerberImportDialogFileColumnEditorWidget implementation diff --git a/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.h b/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.h index b2a3b1e7c..5971abe27 100644 --- a/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.h +++ b/src/plugins/streamers/pcb/lay_plugin/layGerberImportDialog.h @@ -32,6 +32,7 @@ #include "dbLayout.h" #include "dbPoint.h" #include "dbTrans.h" +#include "dbGerberImportData.h" #include #include @@ -60,65 +61,6 @@ namespace db namespace lay { -struct GerberArtworkFileDescriptor -{ - std::string filename; -}; - -struct GerberDrillFileDescriptor -{ - GerberDrillFileDescriptor () : start (-1), stop (-1) { } - - int start; - int stop; - std::string filename; -}; - -struct GerberFreeFileDescriptor -{ - std::string filename; - std::vector layout_layers; -}; - -struct GerberImportData -{ -public: - GerberImportData (); - - enum mode_type { ModeIntoLayout = 0, ModeSamePanel, ModeNewPanel }; - enum mounting_type { MountingTop = 0, MountingBottom }; - - bool invert_negative_layers; - double border; - bool free_layer_mapping; - mode_type mode; - std::string base_dir; - std::string current_file; - std::vector layout_layers; - mounting_type mounting; - int num_metal_layers; - int num_via_types; - std::vector artwork_files; - std::vector drill_files; - std::vector free_files; - std::vector > reference_points; - db::DCplxTrans explicit_trans; - std::string layer_properties_file; - int num_circle_points; - bool merge_flag; - double dbu; - std::string topcell_name; - - std::string get_layer_properties_file () const; - void setup_importer (db::GerberImporter *importer); - void reset (); - void load (tl::InputStream &stream); - void load (const std::string &file); - void save (const std::string &file); - void from_string (const std::string &s); - std::string to_string () const; -}; - // The item editor for the file column class GerberImportDialogFileColumnEditorWidget : public QFrame diff --git a/src/tl/tl/atomic/atomic.h b/src/tl/tl/atomic/atomic.h new file mode 100644 index 000000000..45f2af681 --- /dev/null +++ b/src/tl/tl/atomic/atomic.h @@ -0,0 +1,203 @@ +//---------------------------------------------------------------------------- +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or distribute +// this software, either in source code form or as a compiled binary, for any +// purpose, commercial or non-commercial, and by any means. +// +// In jurisdictions that recognize copyright laws, the author or authors of +// this software dedicate any and all copyright interest in the software to the +// public domain. We make this dedication for the benefit of the public at +// large and to the detriment of our heirs and successors. We intend this +// dedication to be an overt act of relinquishment in perpetuity of all present +// and future rights to this software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// For more information, please refer to +//----------------------------------------------------------------------------- + +#ifndef ATOMIC_ATOMIC_H_ +#define ATOMIC_ATOMIC_H_ + +// Macro for disallowing copying of an object. +#if __cplusplus >= 201103L +#define ATOMIC_DISALLOW_COPY(T) \ + T(const T&) = delete; \ + T& operator=(const T&) = delete; +#else +#define ATOMIC_DISALLOW_COPY(T) \ + T(const T&); \ + T& operator=(const T&); +#endif + +// A portable static assert. +#if __cplusplus >= 201103L +#define ATOMIC_STATIC_ASSERT(condition, message) \ + static_assert((condition), message) +#else +// Based on: http://stackoverflow.com/a/809465/5778708 +#define ATOMIC_STATIC_ASSERT(condition, message) \ + _impl_STATIC_ASSERT_LINE(condition, __LINE__) +#define _impl_PASTE(a, b) a##b +#ifdef __GNUC__ +#define _impl_UNUSED __attribute__((__unused__)) +#else +#define _impl_UNUSED +#endif +#define _impl_STATIC_ASSERT_LINE(condition, line) \ + typedef char _impl_PASTE( \ + STATIC_ASSERT_failed_, \ + line)[(2 * static_cast(!!(condition))) - 1] _impl_UNUSED +#endif + +#if defined(__GNUC__) || defined(__clang__) || defined(__xlc__) +#define ATOMIC_USE_GCC_INTRINSICS +#elif defined(_MSC_VER) +#define ATOMIC_USE_MSVC_INTRINSICS +#include "atomic_msvc.h" +#elif __cplusplus >= 201103L +#define ATOMIC_USE_CPP11_ATOMIC +#include +#else +#error Unsupported compiler / system. +#endif + +namespace atomic { +template +class atomic { +public: + ATOMIC_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || + sizeof(T) == 8, + "Only types of size 1, 2, 4 or 8 are supported"); + + atomic() : value_(static_cast(0)) {} + + explicit atomic(const T value) : value_(value) {} + + /// @brief Performs an atomic increment operation (value + 1). + /// @returns The new value of the atomic object. + T operator++() { +#if defined(ATOMIC_USE_GCC_INTRINSICS) + return __atomic_add_fetch(&value_, 1, __ATOMIC_SEQ_CST); +#elif defined(ATOMIC_USE_MSVC_INTRINSICS) + return msvc::interlocked::increment(&value_); +#else + return ++value_; +#endif + } + + /// @brief Performs an atomic decrement operation (value - 1). + /// @returns The new value of the atomic object. + T operator--() { +#if defined(ATOMIC_USE_GCC_INTRINSICS) + return __atomic_sub_fetch(&value_, 1, __ATOMIC_SEQ_CST); +#elif defined(ATOMIC_USE_MSVC_INTRINSICS) + return msvc::interlocked::decrement(&value_); +#else + return --value_; +#endif + } + + /// @brief Performs an atomic compare-and-swap (CAS) operation. + /// + /// The value of the atomic object is only updated to the new value if the + /// old value of the atomic object matches @c expected_val. + /// + /// @param expected_val The expected value of the atomic object. + /// @param new_val The new value to write to the atomic object. + /// @returns True if new_value was written to the atomic object. + bool compare_exchange(const T expected_val, const T new_val) { +#if defined(ATOMIC_USE_GCC_INTRINSICS) + T e = expected_val; + return __atomic_compare_exchange_n( + &value_, &e, new_val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +#elif defined(ATOMIC_USE_MSVC_INTRINSICS) + const T old_val = + msvc::interlocked::compare_exchange(&value_, new_val, expected_val); + return (old_val == expected_val); +#else + T e = expected_val; + return value_.compare_exchange_weak(e, new_val); +#endif + } + + /// @brief Performs an atomic set operation. + /// + /// The value of the atomic object is unconditionally updated to the new + /// value. + /// + /// @param new_val The new value to write to the atomic object. + void store(const T new_val) { +#if defined(ATOMIC_USE_GCC_INTRINSICS) + __atomic_store_n(&value_, new_val, __ATOMIC_SEQ_CST); +#elif defined(ATOMIC_USE_MSVC_INTRINSICS) + (void)msvc::interlocked::exchange(&value_, new_val); +#else + value_.store(new_val); +#endif + } + + /// @returns the current value of the atomic object. + /// @note Be careful about how this is used, since any operations on the + /// returned value are inherently non-atomic. + T load() const { +#if defined(ATOMIC_USE_GCC_INTRINSICS) + return __atomic_load_n(&value_, __ATOMIC_SEQ_CST); +#elif defined(ATOMIC_USE_MSVC_INTRINSICS) + // TODO(m): Is there a better solution for MSVC? + return value_; +#else + return value_; +#endif + } + + /// @brief Performs an atomic exchange operation. + /// + /// The value of the atomic object is unconditionally updated to the new + /// value, and the old value is returned. + /// + /// @param new_val The new value to write to the atomic object. + /// @returns the old value. + T exchange(const T new_val) { +#if defined(ATOMIC_USE_GCC_INTRINSICS) + return __atomic_exchange_n(&value_, new_val, __ATOMIC_SEQ_CST); +#elif defined(ATOMIC_USE_MSVC_INTRINSICS) + return msvc::interlocked::exchange(&value_, new_val); +#else + return value_.exchange(new_val); +#endif + } + + T operator=(const T new_value) { + store(new_value); + return new_value; + } + + operator T() const { + return load(); + } + +private: +#if defined(ATOMIC_USE_GCC_INTRINSICS) || defined(ATOMIC_USE_MSVC_INTRINSICS) + volatile T value_; +#else + std::atomic value_; +#endif + + ATOMIC_DISALLOW_COPY(atomic) +}; + +} // namespace atomic + +// Undef temporary defines. +#undef ATOMIC_USE_GCC_INTRINSICS +#undef ATOMIC_USE_MSVC_INTRINSICS +#undef ATOMIC_USE_CPP11_ATOMIC + +#endif // ATOMIC_ATOMIC_H_ diff --git a/src/tl/tl/atomic/atomic_msvc.h b/src/tl/tl/atomic/atomic_msvc.h new file mode 100644 index 000000000..d17254f48 --- /dev/null +++ b/src/tl/tl/atomic/atomic_msvc.h @@ -0,0 +1,238 @@ +//----------------------------------------------------------------------------- +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or distribute +// this software, either in source code form or as a compiled binary, for any +// purpose, commercial or non-commercial, and by any means. +// +// In jurisdictions that recognize copyright laws, the author or authors of +// this software dedicate any and all copyright interest in the software to the +// public domain. We make this dedication for the benefit of the public at +// large and to the detriment of our heirs and successors. We intend this +// dedication to be an overt act of relinquishment in perpetuity of all present +// and future rights to this software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// For more information, please refer to +//----------------------------------------------------------------------------- + +#ifndef ATOMIC_ATOMIC_MSVC_H_ +#define ATOMIC_ATOMIC_MSVC_H_ + +// Define which functions we need (don't include ). +extern "C" { +short _InterlockedIncrement16(short volatile*); +long _InterlockedIncrement(long volatile*); +__int64 _InterlockedIncrement64(__int64 volatile*); + +short _InterlockedDecrement16(short volatile*); +long _InterlockedDecrement(long volatile*); +__int64 _InterlockedDecrement64(__int64 volatile*); + +char _InterlockedExchange8(char volatile*, char); +short _InterlockedExchange16(short volatile*, short); +long __cdecl _InterlockedExchange(long volatile*, long); +__int64 _InterlockedExchange64(__int64 volatile*, __int64); + +char _InterlockedCompareExchange8(char volatile*, char, char); +short _InterlockedCompareExchange16(short volatile*, short, short); +long __cdecl _InterlockedCompareExchange(long volatile*, long, long); +__int64 _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64); +}; + +// Define which functions we want to use as inline intriniscs. +#pragma intrinsic(_InterlockedIncrement) +#pragma intrinsic(_InterlockedIncrement16) + +#pragma intrinsic(_InterlockedDecrement) +#pragma intrinsic(_InterlockedDecrement16) + +#pragma intrinsic(_InterlockedCompareExchange) +#pragma intrinsic(_InterlockedCompareExchange8) +#pragma intrinsic(_InterlockedCompareExchange16) + +#pragma intrinsic(_InterlockedExchange) +#pragma intrinsic(_InterlockedExchange8) +#pragma intrinsic(_InterlockedExchange16) + +#if defined(_M_X64) +#pragma intrinsic(_InterlockedIncrement64) +#pragma intrinsic(_InterlockedDecrement64) +#pragma intrinsic(_InterlockedCompareExchange64) +#pragma intrinsic(_InterlockedExchange64) +#endif // _M_X64 + +namespace atomic { +namespace msvc { +template +struct interlocked { +}; + +template +struct interlocked { + static inline T increment(T volatile* x) { + // There's no _InterlockedIncrement8(). + char old_val, new_val; + do { + old_val = static_cast(*x); + new_val = old_val + static_cast(1); + } while (_InterlockedCompareExchange8(reinterpret_cast(x), + new_val, + old_val) != old_val); + return static_cast(new_val); + } + + static inline T decrement(T volatile* x) { + // There's no _InterlockedDecrement8(). + char old_val, new_val; + do { + old_val = static_cast(*x); + new_val = old_val - static_cast(1); + } while (_InterlockedCompareExchange8(reinterpret_cast(x), + new_val, + old_val) != old_val); + return static_cast(new_val); + } + + static inline T compare_exchange(T volatile* x, + const T new_val, + const T expected_val) { + return static_cast( + _InterlockedCompareExchange8(reinterpret_cast(x), + static_cast(new_val), + static_cast(expected_val))); + } + + static inline T exchange(T volatile* x, const T new_val) { + return static_cast(_InterlockedExchange8( + reinterpret_cast(x), static_cast(new_val))); + } +}; + +template +struct interlocked { + static inline T increment(T volatile* x) { + return static_cast( + _InterlockedIncrement16(reinterpret_cast(x))); + } + + static inline T decrement(T volatile* x) { + return static_cast( + _InterlockedDecrement16(reinterpret_cast(x))); + } + + static inline T compare_exchange(T volatile* x, + const T new_val, + const T expected_val) { + return static_cast( + _InterlockedCompareExchange16(reinterpret_cast(x), + static_cast(new_val), + static_cast(expected_val))); + } + + static inline T exchange(T volatile* x, const T new_val) { + return static_cast( + _InterlockedExchange16(reinterpret_cast(x), + static_cast(new_val))); + } +}; + +template +struct interlocked { + static inline T increment(T volatile* x) { + return static_cast( + _InterlockedIncrement(reinterpret_cast(x))); + } + + static inline T decrement(T volatile* x) { + return static_cast( + _InterlockedDecrement(reinterpret_cast(x))); + } + + static inline T compare_exchange(T volatile* x, + const T new_val, + const T expected_val) { + return static_cast( + _InterlockedCompareExchange(reinterpret_cast(x), + static_cast(new_val), + static_cast(expected_val))); + } + + static inline T exchange(T volatile* x, const T new_val) { + return static_cast(_InterlockedExchange( + reinterpret_cast(x), static_cast(new_val))); + } +}; + +template +struct interlocked { + static inline T increment(T volatile* x) { +#if defined(_M_X64) + return static_cast( + _InterlockedIncrement64(reinterpret_cast(x))); +#else + // There's no _InterlockedIncrement64() for 32-bit x86. + __int64 old_val, new_val; + do { + old_val = static_cast<__int64>(*x); + new_val = old_val + static_cast<__int64>(1); + } while (_InterlockedCompareExchange64( + reinterpret_cast(x), new_val, old_val) != + old_val); + return static_cast(new_val); +#endif // _M_X64 + } + + static inline T decrement(T volatile* x) { +#if defined(_M_X64) + return static_cast( + _InterlockedDecrement64(reinterpret_cast(x))); +#else + // There's no _InterlockedDecrement64() for 32-bit x86. + __int64 old_val, new_val; + do { + old_val = static_cast<__int64>(*x); + new_val = old_val - static_cast<__int64>(1); + } while (_InterlockedCompareExchange64( + reinterpret_cast(x), new_val, old_val) != + old_val); + return static_cast(new_val); +#endif // _M_X64 + } + + static inline T compare_exchange(T volatile* x, + const T new_val, + const T expected_val) { + return static_cast(_InterlockedCompareExchange64( + reinterpret_cast(x), + static_cast(new_val), + static_cast(expected_val))); + } + + static inline T exchange(T volatile* x, const T new_val) { +#if defined(_M_X64) + return static_cast( + _InterlockedExchange64(reinterpret_cast(x), + static_cast(new_val))); +#else + // There's no _InterlockedExchange64 for 32-bit x86. + __int64 old_val; + do { + old_val = static_cast<__int64>(*x); + } while (_InterlockedCompareExchange64( + reinterpret_cast(x), new_val, old_val) != + old_val); + return static_cast(old_val); +#endif // _M_X64 + } +}; +} // namespace msvc +} // namespace atomic + +#endif // ATOMIC_ATOMIC_MSVC_H_ diff --git a/src/tl/tl/atomic/spinlock.h b/src/tl/tl/atomic/spinlock.h new file mode 100644 index 000000000..3e9959672 --- /dev/null +++ b/src/tl/tl/atomic/spinlock.h @@ -0,0 +1,78 @@ +//----------------------------------------------------------------------------- +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or distribute +// this software, either in source code form or as a compiled binary, for any +// purpose, commercial or non-commercial, and by any means. +// +// In jurisdictions that recognize copyright laws, the author or authors of +// this software dedicate any and all copyright interest in the software to the +// public domain. We make this dedication for the benefit of the public at +// large and to the detriment of our heirs and successors. We intend this +// dedication to be an overt act of relinquishment in perpetuity of all present +// and future rights to this software under copyright law. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// For more information, please refer to +//----------------------------------------------------------------------------- + +#ifndef ATOMIC_SPINLOCK_H_ +#define ATOMIC_SPINLOCK_H_ + +#include "atomic/atomic.h" + +namespace atomic { +class spinlock { +public: + spinlock() : value_(0) {} + + /// @brief Acquire the lock (blocking). + /// @note Trying to acquire a lock that is already held by the calling thread + /// will dead-lock (block indefinitely). + void lock() { + while (!value_.compare_exchange(UNLOCKED, LOCKED)) + ; + } + + /// @brief Release the lock. + /// @note It is an error to release a lock that has not been previously + /// acquired. + void unlock() { value_.store(UNLOCKED); } + +private: + static const int UNLOCKED = 0; + static const int LOCKED = 1; + + atomic value_; + + ATOMIC_DISALLOW_COPY(spinlock) +}; + +class lock_guard { +public: + /// @brief The constructor acquires the lock. + /// @param lock The spinlock that will be locked. + explicit lock_guard(spinlock& lock) : lock_(lock) { + lock_.lock(); + } + + /// @brief The destructor releases the lock. + ~lock_guard() { + lock_.unlock(); + } + +private: + spinlock& lock_; + + ATOMIC_DISALLOW_COPY(lock_guard) +}; + +} // namespace atomic + +#endif // ATOMIC_SPINLOCK_H_